Maths around brewing
Maths around brewing. Acan implements some known equations used by homebrewers. All of them are well documented, so anyone could check where they came from and why.
Acan only needs Python 3 to run. Having it, just install Acan and import it in your programs:
$ pip3 install acan $ python3 >>> import acan
Acan is a object-oriented calculator, so classes were implemented to do all the job.
Hydrometer class has all the methods needed to support hydrometer usage. The basic usage of this class is to instantiate it with the value read on hydrometer –in SG. Alternatively you can set up the temperatures to calibrate your results.
More info on its docstring.
In the first example, we only instantiate an Hydrometer object with the value read on hydrometer –e.g., 1.010.
In the second example, we calibrate the hydrometer using the temperatures. The first parameter is the value, the second is the current temperature of the sample, and the last value is the temperature in which the hydrometer was calibrated.
>>> from acan.tools import Hydrometer >>> # First example ... >>> h = Hydrometer(1.010) >>> print(h) SG...: 1.010 Plato: 2.56 Brix.: 2.34 >>> # Second example ... >>> h1 = Hydrometer(1.010, 37, 20) >>> print(h1) SG...: 1.015 Plato: 3.78 Brix.: 3.56
Refractometer class implements methods specific to refractometers. The most common way to use it is to inform the value –in Plato (ideally) or Brix– and it’ll correct this value automatically with the default correction factor. Read the class’ docstring for more information.
If you wish to set the calibration of your refractometer, you can use the calibration parameter, which accepts an iterable object with a tuple of refractometer value and the corresponding hydrometer value. Let’s go to examples to understand how it works.
>>> from acan.tools import Refractometer >>> # First example ... >>> r = Refractometer(23.75) r.calibration 1.04 >>> print(r) SG...: 1.097 Plato: 23.029 Brix.: 22.837 >>> # Second example ... >>> r1 = Refractometer(23.75, calibration=[(12.6, 1.050), (11.5, 1.045), (13.7, 1.055)]) >>> r1.calibration 1.0395278561663661 >>> print(r1) SG...: 1.097 Plato: 23.040 Brix.: 22.847
This class has methods relative to color calculations. The easiest way to use it is to instantiate an object with the corresponding color value in SRM, EBC or Lovibond.
>>> from acan.tools import Palette >>> # First example ... >>> p = Palette(15) >>> print(p) SRM: 15.00 EBC: 29.55 L..: 11.63 Hex: #964726 >>> # Second example ... >>> p1 = Palette(20, 'ebc') >>> print(p1) SRM: 10.16 EBC: 20.00 L..: 8.06 Hex: #a45a2d
Wort class aggregates all methods used to measure the wort quality. To use it, just take original and final gravities, and pass them as parameter to this class –for final gravity, you can assume the last sample taken from the wort.
>>> from acan.wort import Wort >>> w = Wort(1.051, 1.013) >>> print(w) Original gravity....[SG]: 1.051 Final gravity.......[SG]: 1.013 Volume...............[L]: 0.000 Efficiency...........[%]: 0.000 Original extract.[Plato]: 12.625 Actual extract...[Plato]: 3.321 Real extract.....[Plato]: 5.003 Apparent attenuation.[%]: 73.692 Real attenuation.....[%]: 60.368 Alcohol by weight....[%]: 3.951 Alcohol by volume....[%]: 5.067 Calories in 355 mL.[Cal]: 168.579
To calculate the efficiency, use the parameters grains and volume. Consider the example below:
The efficiency could be calculated like this:
>>> from acan.wort import Wort >>> print(Wort(1.038, 1.013, grains=[(2948.3, 36), (226.8, 34),(226.8, 34), (226.8, 35), (226.8, 30)], volume=22.71)) Original gravity.....[SG]: 1.038 Final gravity........[SG]: 1.013 Original extract..[Plato]: 9.510 Apparent extract..[Plato]: 3.321 Real extract......[Plato]: 4.440 Volume................[L]: 22.710 Points/Pound/Gallon.[PPG]: 26.821 Mash efficiency.......[%]: 75.866 Apparent attenuation..[%]: 65.789 Real attenuation......[%]: 59.573 Alcohol by weight.....[%]: 2.600 Alcohol by volume.....[%]: 3.333 Calories in 355 mL..[Cal]: 126.936
For more information, read the class’ docstring. It’s important to note that in this work, brewhose and mash efficiencies are the same.
This class have common equations to calculate hop bitterness. Methods like Tinseth, Rager, and Garetz are covered here as well as those used by John Palmer and Ray Daniels.
>>> from acan.wort import Hops >>> h = Hops(56.69904, 7, 18.92706, 1.020, 12) >>> print(h) Hops weight.......[g]: 56.70 Hops alpha acids..[%]: 7.00 Wort volume.......[L]: 18.93 Wort SG...........[L]: 1.020 Hops boil time....[m]: 12 Wort bitterness.[IBU]: 26.554 >>> h.daniels(28.34952, 12.5, 22.712471, 1.048, 60, 'whole') 37.44575392083054
Acan is now published at Python Package Index (PyPI). A Makefile was created to automate all the job of packaging, but some things must to be set first.
The steps below were based on:
The very first thing to be set up is the setup.py. This file must updated with the new version at least. The versioning adopted by Acan is: <major version>.<minor version>.<bug fixes>. By <major version>, we can understand very big changes in the code. <minor version> means new features in the current version, like new classes. Finally, <bug fixes> are, of course, bug fixes, or little changes in the code, like typo fixes.
In order to upload this new version to PyPI, a ~/.pypirc file must be created with a content like this –considering you already have a PyPI account:
[distutils] index-servers = pypi [pypi] repository=https://www.python.org/pypi username=USERNAME password=PASSWORD
Note that I had problems using some special characters in PASSWORD.
After all of this, just run $ make pypi to create the package and upload it to PyPI.
This way, the process I follow is:
According to Wikipedia, Acan is the Maya god of wine and intoxication, and his name means ‘belch’. He is identified with the local brew, balché, made from fermented honey to which the bark of the balché tree has been added.
Bierminen: Zug von verrükten!