BrewDay - Tools for Homebrewers¶
BrewDay is a set of tools for homebrewers written in python.
Tutorial¶
Features¶
- Build a Recipe to know what to expect from your brew
- Develop Recipes to help you pick ingredients to match a style
- Explore concepts like Bitterness, Color, and Alcohol Content
Building a Recipe¶
This tutorial is going to show you how to build a recipe using the objects provided by the BrewDay library. This will walk you through putting together each object, describe them and some methods, and then finally build a complete recipe.
The Grain Bill¶
To build a beer recipe you will want to first describe the grains to be used.
This is done by describing each grain with a brew.grains.Grain
object.
from brew.grains import Grain
pale = Grain('Pale Malt (2 Row) US',
color=1.8,
ppg=37)
This object is really only descriptive. It tells you the characteristics of
the Grain that you will later add to your beer. What you want to construct
is a brew.grains.GrainAddition
object, which describes how
much of the grain is added to the recipe:
from brew.grains import GrainAddition
pale_add = GrainAddition(pale, weight=13.96)
This object now decribes what will be added to the beer. You can further customize the grain by describing the type of grain being added:
from brew.constants import GRAIN_TYPE_LME
from brew.grains import GrainAddition
pale_add = GrainAddition(pale, weight=13.96, grain_type=GRAIN_TYPE_LME)
By describing the type of grain you change how it is utilized in the recipe equations.
The Hops Bill¶
The next piece to describe is the brew.hops.Hop
object.
from brew.hops import Hop
centennial = Hop('Centennial',
percent_alpha_acids=0.14)
Again, this object is really only descriptive. It tells you the characteristics
of the Hop that you will later add to your beer. What you want to construct
is a brew.hops.HopAddition
object, which describes how many hops
are added to the recipe and how long they are boiled for.
from brew.hops import HopAddition
centennial_add = HopAddition(centennial,
weight=0.57,
boil_time=60.0)
This object now decribes what will be added to the beer. You can further customize the hop by describing the type of hop being added:
from brew.constants import HOP_TYPE_WHOLE
from brew.hops import HopAddition
centennial_add = HopAddition(centennial,
weight=0.57,
boil_time=60.0,
hop_type=HOP_TYPE_WHOLE)
By describing the type of hop you change how it is utilized in the recipe equations.
Yeast¶
Yeast describes how much alcohol is expected to be produced by the recipe. This
is done with a brew.yeasts.Yeast
object.
from brew.yeasts import Yeast
yeast = Yeast('Wyeast 1056',
percent_attenuation=0.70)
By changing the percentage of attenuation you can estimate different final ABV amounts for the recipe. By default the yeast expects 75% attenuation.
Building the Recipe¶
Let’s take what we’ve learned so far and prepare a Pale Ale recipe:
from brew.grains import Grain
from brew.grains import GrainAddition
from brew.hops import Hop
from brew.hops import HopAddition
from brew.yeasts import Yeast
# Define Grains
pale = Grain('Pale Malt (2 Row) US',
color=1.8,
ppg=37)
pale_add = GrainAddition(pale,
weight=13.96)
crystal = Grain('Caramel/Crystal Malt - 20L',
color=20.0,
ppg=35)
crystal_add = GrainAddition(crystal,
weight=0.78)
grain_additions = [pale_add, crystal_add]
# Define Hops
centennial = Hop('Centennial',
percent_alpha_acids=0.14)
centennial_add = HopAddition(centennial,
weight=0.57,
boil_time=60.0)
cascade = Hop('Cascade (US)',
percent_alpha_acids=0.07)
cascade_add = HopAddition(cascade,
weight=0.76,
boil_time=5.0)
hop_additions = [centennial_add, cascade_add]
# Define Yeast
yeast = Yeast('Wyeast 1056')
Now we want to put them together into a brew.recipes.Recipe
.
from brew.recipes import Recipe
beer = Recipe('Pale Ale',
grain_additions=grain_additions,
hop_additions=hop_additions,
yeast=yeast,
brew_house_yield=0.70,
start_volume=7.0,
final_volume=5.0)
In any recipe you will want to define a few more pieces about the brew that will be done. The first is the Brew House Yield, or how efficient your system is. Typically this is set at 70% efficiency but can be anywhere from 60%-80% for a typical homebrewer.
You also need to describe the start and ending volume of your system. Here the recipe expects to start at 7 Gallons and end at 5 Gallons. The units are expected to be in Imperial Units unless otherwise specified.
Now you’ll want to see what this recipe produces. Just format the recipe to see what you’ve constructed!
print(beer.format())
Produces the output:
Pale Ale
===================================
Brew House Yield: 70.0%
Start Volume: 7.0
Final Volume: 5.0
Boil Gravity: 1.054
Original Gravity: 1.076
Final Gravity: 1.019
ABV / ABW Standard: 7.49% / 5.95%
ABV / ABW Alt: 7.98% / 6.33%
IBU: 33.0 ibu
BU/GU: 0.6
Morey (SRM/EBC): 6.3 degL / 12.4
Daniels (SRM/EBC): N/A degL / N/A
Mosher (SRM/EBC): 7.1 degL / 14.1
Grains
===================================
Pale Malt (2 Row) US Addition
-----------------------------------
Grain Type: cereal
Weight: 13.96 lbs
Percent Malt Bill: 95.0%
Working Yield: 56.0%
SRM/EBC: 4.5 degL / 8.9
Caramel/Crystal Malt - 20L Addition
-----------------------------------
Grain Type: cereal
Weight: 0.78 lbs
Percent Malt Bill: 5.0%
Working Yield: 53.0%
SRM/EBC: 3.3 degL / 6.4
Hops
===================================
Centennial Addition
-----------------------------------
Hop Type: pellet
AA %: 14.0%
Weight: 0.57 oz
Boil Time: 60.0 min
IBUs: 29.2
Utilization: 24.0%
Cascade (US) Addition
-----------------------------------
Hop Type: pellet
AA %: 7.0%
Weight: 0.76 oz
Boil Time: 5.0 min
IBUs: 3.9
Utilization: 5.0%
Yeast
===================================
Wyeast 1056 Yeast
-----------------------------------
Attenuation: 75.0%
Congratulations, you’ve now constructed your first recipe.
Designing a Recipe¶
This tutorial is going to show you how to design a beer recipe from raw ingredients. This will walk you through building the objects provided by the BrewDay library, describe some methods, and end by building a complete recipe.
The Style¶
The first thing you’ll want to do is determine the style of the beer. In this example we’re going to design a Pale Ale. The pale ale uses two types of grain and two types of hops. Let’s build those first:
from brew.grains import Grain
from brew.hops import Hop
pale = Grain('pale 2-row',
color=2.0,
ppg=37.0)
crystal = Grain('crystal C20',
color=20.0,
ppg=35.0)
grain_list = [pale, crystal]
centennial = Hop(name='centennial',
percent_alpha_acids=0.14)
cascade = Hop(name='cascade',
percent_alpha_acids=0.07)
hop_list = [centennial, cascade]
The style dictates the ingredients, the expected original gravity and the target IBU. Here is a list of what we expect for the latter two:
- Original Gravity: 1.076
- Target IBU: 33.0
We must also describe the system we intend to brew on:
- Percent brew house yield: 70%
- Start volume: 7.0
- Final volume: 5.0
This helps us construct the brew.recipes.RecipeBuilder
for building our recipe:
from brew.recipes import RecipeBuilder
builder = RecipeBuilder(name='Pale Ale',
grain_list=grain_list,
hop_list=hop_list,
target_ibu=33.0,
target_og=1.0761348,
brew_house_yield=0.70,
start_volume=7.0,
final_volume=5.0,
)
With the builder class we can now determine the amount of grains and hops that we will use in our recipe.
The Grain Bill¶
Now that we have a brew.recipes.RecipeBuilder
to help us build a
recipe we want to determine the grain additions that we’ll be using. This is
done by providing an estimate of the percentages each grain will contribute to
the final beer. In this case the pale 2-row will contribute 95% and the
crystal 20L will contribute 5%.
percent_list = [0.95, 0.05]
grain_additions = builder.get_grain_additions(percent_list)
for grain_add in grain_additions:
print(grain_add.format())
print('')
Produces the output:
Pale Malt (2 Row) US Addition
-----------------------------------
Grain Type: cereal
Weight: 13.96 lbs
Caramel/Crystal Malt - 20L Addition
-----------------------------------
Grain Type: cereal
Weight: 0.78 lbs
Now you have designed the grain bill for your recipe.
The Hops Bill¶
Next we will use the brew.recipes.RecipeBuilder
to determine the
hop additions that we’ll be using. This is done by providing an estimate of
the percentages each hop will contribute to the final beer. In this case the
centennial will contribute 88.27% and the cascade will contribute 11.73%.
Additionally we need to know how long each hop will be in the boil. For the centennial we will boil 60 minutes and for the cascade we will boil 5 minutes. Time is measured from the end of the boil.
percent_list = [0.8827, 0.1173]
boil_time_list = [60.0, 5.0]
hop_additions = builder.get_hop_additions(percent_list, boil_time_list)
for hop_add in hop_additions:
print(hop_add.format())
print('')
Produces the output:
Centennial Addition
-----------------------------------
Hop Type: pellet
AA %: 14.0%
Weight: 0.57 oz
Boil Time: 60.0 min
Cascade (US) Addition
-----------------------------------
Hop Type: pellet
AA %: 7.0%
Weight: 0.76 oz
Boil Time: 5.0 min
Now you have designed the hop bill for your recipe.
The Yeast¶
There is very little control over the yeast that you’ll use. The style typically dictates two or three choices of yeast to get the correct flavor. The remaining question is how much the yeast will attenuate the wort to create alcohol. Since attenuation is a property of the yeast the best you can do is set a target ABV and use that to determine what range of attenuation you will need from your yeast.
Let’s assume that your target ABV is 7.49%. Then you can find the needed attenuation with the following code:
abv = 0.0749
attenuation = builder.get_yeast_attenuation(abv)
print("Attenuation = {:0.1%}".format(attenuation))
Yields:
Attenuation = 75.0%
Using this number you can pick a yeast in your style that has the 75% expected attenuation number. Since there are so many factors surrounding yeast this should only be used as an estimate.
Matching Beer Styles¶
This tutorial is going to show you how to match your beer against a beer style.
The Style¶
To begin we’ll want to create an object that represents the style of the beer
we wish to brew. To do this we’ll need to make a brew.recipes.Style
object.
from brew.styles import Style
style = Style('American Pale Ale',
category='18',
subcategory='B',
og=[1.045, 1.060],
fg=[1.010, 1.015],
abv=[0.045, 0.062],
ibu=[30, 50],
color=[5, 10])
This represents an American Pale Ale from the BJCP 2015 Style Guidelines. The beer recipe will match the style if it falls within the range of values given here. For example, the original gravity must fall between 1.045 and 1.060 to be considered “in the style” of an American Pale Ale. Similarly the final gravity, alcohol by volume, IBUs, and color must all fall within the range.
Matching a Recipe¶
In previous tutorials we have created an American Pale Ale recipe. It looked something like this:
from brew.recipes import Recipe
beer = Recipe('Pale Ale',
grain_additions=grain_additions,
hop_additions=hop_additions,
yeast=yeast,
brew_house_yield=0.70,
start_volume=7.0,
final_volume=5.0)
In order to match the recipe we use a method on the class:
>>> style.recipe_matches(recipe)
False
>>> style.og_matches(recipe.og)
False
>>> style.fg_matches(recipe.fg)
False
>>> style.abv_matches(recipe.abv)
False
>>> style.ibu_matches(recipe.ibu)
True
>>> style.color_matches(recipe.color)
True
Interestingly the recipe used in the examples does not match the BJCP style! The only feature that matches the style is the IBUs and coor, but the remaining values for og, fg, and abv are all too high. That means its time to correct our recipe.
As a short hand you can also get this information in a more friendly way:
>>> style.recipe_errors(recipe)
['OG is above style', 'FG is above style', 'ABV is above style']
This will help you quickly discover the problems with your recipe.
Correcting a Recipe¶
The recipe we started with has the right ingredients but it appears the grain bill may contain too much grain. Let’s repeat the builder example but this time change the original gravity to 1.050 and keep everything else the same.
# Define Builder
builder = RecipeBuilder(name='Pale Ale',
grain_list=grain_list,
hop_list=hop_list,
target_ibu=33.0,
target_og=1.050,
brew_house_yield=0.70,
start_volume=7.0,
final_volume=5.0,
)
# Get Grain Bill
percent_list = [0.95, 0.05]
grain_additions = builder.get_grain_additions(percent_list)
for grain_add in grain_additions:
print(grain_add.format())
print('')
When we print out the grain bill with the new parameters we get:
pale 2-row Addition
-----------------------------------
Grain Type: cereal
Weight: 9.17 lbs
crystal C20 Addition
-----------------------------------
Grain Type: cereal
Weight: 0.51 lbs
Notice that the pale 2-row addition came down from 13.86 lbs to 9.17 lbs. The crystal 20L has come down from 0.78 lbs to 0.51 lbs. Let’s try this again.
>>> style.recipe_matches(recipe)
False
>>> style.og_matches(recipe.og)
True
>>> style.fg_matches(recipe.fg)
True
>>> style.abv_matches(recipe.abv)
True
>>> style.ibu_matches(recipe.ibu)
True
>>> style.color_matches(recipe.color)
False
It turns out the recipe still doesn’t match. Why? It appears that our color is now off after our adjustments.
Correcting for Color¶
Correcting color is difficult because it requires an understanding of the grains being used. In this case the pale ale should remain primarily pale 2-row grains. However, we can reduce the pale 2-row and increase the crystal 20L and get a different color.
# Get Grain Bill
percent_list = [0.90, 0.10]
grain_additions = builder.get_grain_additions(percent_list)
for grain_add in grain_additions:
print(grain_add.format())
print('')
Gives us:
pale 2-row Addition
-----------------------------------
Grain Type: cereal
Weight: 8.69 lbs
crystal C20 Addition
-----------------------------------
Grain Type: cereal
Weight: 1.02 lbs
Notice that the weight of the pale 2-row went down from 9.17 lbs to 8.69 lbs and the crystal 20L went up from 0.51 lbs to 1.02 lbs. Now we can recreate the recipe and check the style:
>>> style.recipe_matches(recipe)
True
>>> style.og_matches(recipe.og)
True
>>> style.fg_matches(recipe.fg)
True
>>> style.abv_matches(recipe.abv)
True
>>> style.ibu_matches(recipe.ibu)
True
>>> style.color_matches(recipe.color)
True
Nice job, now you have a beer recipe that matches the style of an American Pale Ale. Be sure that you have an accurate value for your percent brew house yield and your changes of brewing this beer will be pretty good.
Appendix¶
API Docs¶
Model API¶
brew.constants¶
brew.exceptions¶
brew.grains¶
-
class
brew.grains.
Grain
(name, color=None, ppg=None, hwe=None)¶ A representation of a type of grain.
Parameters: - name (str) – The name of the grain
- color (float) – The color of the grain in SRM
- ppg (float) – The potential points per gallon
- hwe (float) – The hot water extract value
Raises: - GrainException – If color is not provided
- GrainException – If ppg or hwe is not provided
- GrainException – If both ppg and hwe are provided
-
convert_to_cereal
(ppg=None)¶
-
convert_to_dme
(ppg=44.0)¶
-
convert_to_lme
(ppg=36.0)¶
-
format
()¶
-
get_working_yield
(brew_house_yield)¶ Get Working Yield
Parameters: brew_house_yield (float) – The Percent Brew House Yield Returns: The working yield Return type: float
-
to_dict
()¶
-
to_json
()¶
-
class
brew.grains.
GrainAddition
(grain, weight=None, grain_type=u'cereal', units=u'imperial')¶ A representation of the grain as added to a Recipe.
Parameters: - grain (Grain) – The Grain object
- weight (float) – The weight of the grain addition
- grain_type (str) – The type of the grain being used
- units (str) – The units
-
change_units
()¶ Change units of the class from one type to the other
Returns: Grain Addition in new unit type Return type: GrainAddition
-
convert_to_cereal
(ppg=None, brew_house_yield=1.0)¶ Convert Grain Addition to GRAIN_TYPE_CEREAL
Parameters: - ppg (float) – The potential points per gallon
- brew_house_yield (float) – The brew house yield as a percentage
Returns: GrainAddition of type GRAIN_TYPE_CEREAL
Return type:
-
convert_to_dme
(ppg=44.0, brew_house_yield=1.0)¶ Convert Grain Addition to GRAIN_TYPE_DME
Parameters: - ppg (float) – The potential points per gallon
- brew_house_yield (float) – The brew house yield as a percentage
Returns: GrainAddition of type GRAIN_TYPE_DME
Return type:
-
convert_to_lme
(ppg=36.0, brew_house_yield=1.0)¶ Convert Grain Addition to GRAIN_TYPE_LME
Parameters: - ppg (float) – The potential points per gallon
- brew_house_yield (float) – The brew house yield as a percentage
Returns: GrainAddition of type GRAIN_TYPE_LME
Return type:
-
format
()¶
-
get_cereal_weight
(ppg=30.0)¶ Get the weight of the addition in cereal weight
Parameters: ppg (float) – The potential points per gallon Returns: Cereal weight Return type: float
-
get_dme_weight
()¶ Get the weight of the addition in Dry Malt Extract weight
Returns: Dry weight Return type: float
-
get_gravity_units
()¶ Get the gravity units for the Grain Addition :return: Gravity Units as PPG or HWE depending on units :rtype: float
-
get_lme_weight
()¶ Get the weight of the addition in Liquid Malt Extract weight
Returns: LME weight Return type: float
-
get_weight_map
()¶ Get map of grain weights by type
Returns: Grain weights Return type: dict
-
gu
¶
-
set_units
(units)¶ Set the units and unit types
Parameters: units (str) – The units
-
to_dict
()¶
-
to_json
()¶
-
classmethod
validate
(grain_data)¶
brew.hops¶
-
class
brew.hops.
Hop
(name, percent_alpha_acids=None)¶ A representation of a type of Hop.
Parameters: - name (str) – The name of the hop
- percent_alpha_acids (float) – The percent alpha acids in the hop
Raises: HopException – If percent_alpha_acids is not provided
-
format
()¶
-
to_dict
()¶
-
to_json
()¶
-
class
brew.hops.
HopAddition
(hop, weight=None, boil_time=None, hop_type=u'pellet', utilization_cls=<class 'brew.utilities.hops.HopsUtilizationGlennTinseth'>, utilization_cls_kwargs=None, units=u'imperial')¶ A representation of the Hop as added to a Recipe.
Parameters: - hop (Hop) – The Hop object
- weight (float) – The weight of the hop addition
- boil_time (float) – The amount of time the hop is boiled
- hop_type (float) – The type of the hop being used
- utilization_cls (HopsUtilization) – The utilization class used for calculation
- utilization_cls_kwargs (dict) – The kwargs to initialize the utilization_cls object
- units (str) – The units
-
change_units
()¶ Change units of the class from one type to the other
Returns: Hop Addition in new unit type Return type: HopAddition
-
format
()¶
-
get_alpha_acid_units
()¶ Get Alpha Acid Units
Returns: alpha acid units Return type: float
-
get_ibus
(sg, final_volume)¶ Get the IBUs
Parameters: - sg (float) – The specific gravity of the wort
- final_volume (float) – The final volume of the wort
Returns: The IBUs of the wort
Return type: float
-
set_units
(units)¶ Set the units and unit types
Parameters: units (str) – The units
-
to_dict
()¶
-
to_json
()¶
-
classmethod
validate
(hop_data)¶
brew.parsers¶
-
class
brew.parsers.
DataLoader
(data_dir)¶ Base class for loading data from data files inside the data_dir.
Parameters: data_dir (str) – The directory where the data resides -
DATA
= {}¶
-
EXT
= ''¶
-
classmethod
format_name
(name)¶ Reformat a given name to match the filename of a data file.
-
get_item
(dir_suffix, item_name)¶ Parameters: - dir_suffix (str) – The directory name suffix
- item_name (str) – The name of the item to load
Returns: The item as a python dict
Raises: - DataLoaderException – If item directory does not exist
- Warning – If item not found in the directory
-
classmethod
read_data
(filename)¶ Parameters: filename (str) – The filename of the file to read Raises: NotImplementedError – Must be supplied in inherited class
-
-
class
brew.parsers.
JSONDataLoader
(data_dir)¶ Load data from JSON files inside the data_dir.
Parameters: data_dir (str) – The directory where the data resides -
DATA
= {}¶
-
EXT
= 'json'¶
-
format_name
(name)¶ Reformat a given name to match the filename of a data file.
-
get_item
(dir_suffix, item_name)¶ Parameters: - dir_suffix (str) – The directory name suffix
- item_name (str) – The name of the item to load
Returns: The item as a python dict
Raises: - DataLoaderException – If item directory does not exist
- Warning – If item not found in the directory
-
classmethod
read_data
(filename)¶ Parameters: filename (str) – The filename of the file to read Returns: The data loaded from a JSON file
-
-
parsers.
parse_cereals
(cereal, loader, dir_suffix='cereals/')¶ Parse grains data from a recipe
Parameters: - cereal (dict) – A representation of a cereal
- loader (DataLoader) – A class to load additional information
Grain must have the following top level attributes:
- name (str)
- weight (float)
- data (dict) (optional)
Additionally grains may contain override data in the ‘data’ attribute with the following keys:
- color (float)
- ppg (int)
-
parsers.
parse_hops
(hop, loader, dir_suffix='hops/')¶ Parse hops data from a recipe
Parameters: - hops (dict) – A representation of a hop
- loader (DataLoader) – A class to load additional information
Hops must have the following top level attributes:
- name (str)
- weight (float)
- boil_time (float)
- data (dict) (optional)
Additionally hops may contain override data in the ‘data’ attribute with the following keys:
- percent_alpha_acids (float)
-
parsers.
parse_yeast
(yeast, loader, dir_suffix='yeast/')¶ Parse yeast data from a recipe
Parameters: - hops (dict) – A representation of a yeast
- loader (DataLoader) – A class to load additional information
Yeast must have the following top level attributes:
- name (str)
- data (dict) (optional)
Additionally yeast may contain override data in the ‘data’ attribute with the following keys:
- percent_attenuation (float)
-
parsers.
parse_recipe
(recipe, loader, cereals_loader=None, hops_loader=None, yeast_loader=None, cereals_dir_suffix='cereals/', hops_dir_suffix='hops/', yeast_dir_suffix='yeast/')¶ Parse a recipe from a python Dict
Parameters: - recipe (dict) – A representation of a recipe
- loader (DataLoader) – A class to load additional information
- cereal_loader (DataLoader) – A class to load additional information specific to cereals
- hops_loader (DataLoader) – A class to load additional information specific to hops
- yeast_loader (DataLoader) – A class to load additional information specific to yeast
A recipe must have the following top level attributes:
- name (str)
- start_volume (float)
- final_volume (float)
- grains (list(dict))
- hops (list(dict))
- yeast (dict)
Additionally the recipe may contain override data in the ‘data’ attribute with the following keys:
- brew_house_yield (float)
- units (str)
All other fields will be ignored and may be used for other metadata.
The dict objects in the grains, hops, and yeast values are required to have the key ‘name’ and the remaining attributes will be looked up in the data directory if they are not provided.
brew.recipes¶
-
class
brew.recipes.
Recipe
(name, grain_additions=None, hop_additions=None, yeast=None, brew_house_yield=0.7, start_volume=7.0, final_volume=5.0, units=u'imperial')¶ A representation of a Recipe that can be brewed to make beer.
Parameters: - name (str) – The name of the recipe
- grain_additions (list of GrainAddition objects) – A list of Grain Additions
- hop_additions (list of HopAddition objects) – A list of Hop Additions
- brew_house_yield (float) – The brew house yield
- start_volume (float) – The starting volume of the wort
- final_volume (float) – The final volume of the wort
- units (str) – The units
Raises: - RecipeException – If the units of any GrainAddition is not the same as the units of the Recipe
- RecipeException – If the units of any HopAddition is not the same as the units of the Recipe
-
abv
¶
-
bg
¶
-
change_units
()¶ Change units of the class from one type to the other
Returns: Recipe in new unit type Return type: Recipe
-
color
¶
-
fg
¶
-
format
(short=False)¶ Format the recipe for printing
Parameters: short (bool) – Produce short output
-
get_boil_gravity
(evaporation=0.0)¶ Get the boil specific gravity
Parameters: evaporation (float) – Percent water evaporation during boil Returns: The boil specific gravity Return type: float
-
get_boil_gravity_units
(evaporation=0.0)¶ Get the boil gravity units
Parameters: evaporation (float) – Percent water evaporation during boil Returns: The boil gravity units Return type: float
-
get_brew_house_yield
(plato_actual, vol_actual)¶ Get the Brew House Yield
Parameters: - plato_actual (float) – The actual degrees Plato
- vol_actual (float) – The actual volume collected from the kettle
Returns: Brew House Yield
Rtyle: float
-
get_bu_to_gu
()¶ Get BU to GU Ratio
Returns: Ratio of Bitterness Units to Original Gravity Units Return type: float
-
get_degrees_plato
()¶ Get the degrees plato
Returns: The degrees plato of the wort Return type: float
-
get_extract_weight
()¶ Get the weight of the extract
Returns: The weight of extract Return type: float
-
get_final_gravity
()¶ Get the final specific gravity
Returns: The final specific gravity Return type: float
-
get_final_gravity_units
()¶ Get the final gravity units
Returns: The final gravity units Return type: float
-
get_grain_add_cereal_weight
(grain_add, ppg=30.0)¶ Get Grain Addition as Cereal
Parameters: grain_add (GrainAddition) – The Grain Addition Returns: The weight of the grain as Cereal Return type: float When converting DME or LME to grain its important to remember that you can’t get 100% efficiency from grains. Dividing by the brew house yield will increase the size of the grain accordingly.
-
get_grain_add_dry_weight
(grain_add)¶ Get Grain Addition as DME
Parameters: grain_add (GrainAddition) – The Grain Addition Returns: The weight of the grain as DME Return type: float When converting Grain to DME its important to remember that you can’t get 100% efficiency from grains. Multiplying by the brew house yield will decrease the size of the DME accordingly.
-
get_grain_additions_by_type
(grain_type)¶ Return grain additions by given grain_type
Parameters: grain_type (str) – The type of grains to return Returns: list of GrainAddition objects
-
get_hop_additions_by_type
(hop_type)¶ Return hop additions by given hop_type
Parameters: hop_type (str) – The type of hops to return Returns: list of HopAddition objects
-
get_original_gravity
()¶ Get the original specific gravity
Returns: The original specific gravity Return type: float
-
get_original_gravity_units
()¶ Get the original gravity units
Returns: The original gravity units Return type: float
-
get_percent_ibus
(hop_add)¶ Get the percentage the hops contributes to total ibus
Parameters: hop_add (HopAddition) – The Hop Addition Returns: The percent the hops contributes to total ibus Return type: float
-
get_percent_malt_bill
(grain_add)¶ Get Percent Malt Bill
Parameters: grain_add (GrainAddition) – The Grain Addition Returns: The percent extract the addition adds to the bill Return type: float To ensure different additions are measured equally each is converted to dry weight.
-
get_total_dry_weight
()¶ Get total DME weight
Returns: The total weight of the DME Return type: float
-
get_total_grain_weight
()¶ Get total Cereal weight
Returns: The total weight of the Cereal Return type: float
-
get_total_ibu
()¶ Convenience method to get total IBU for the recipe
Returns: The total IBU for the Recipe Return type: float
-
get_total_points
()¶ Get the total points of the recipe
Returns: PPG or HWE depending on the units of the Recipe Return type: float
-
get_total_wort_color
()¶ Get the Total Color of the Wort in SRM using Morey Power Equation
Returns: The total color of the wort in SRM Return type: float
-
get_total_wort_color_map
()¶ Get a map of wort color by method
Returns: A map of wort color in SRM and EBC by method (Morey, Daniels, and Mosher) Return type: dict
-
get_wort_color
(grain_add)¶ Get the Wort Color in SRM
Parameters: grain_add (GrainAddition) – The Grain Addition to calculate Returns: The SRM of the Grain Addition Return type: float
-
get_wort_color_mcu
(grain_add)¶ Get the Wort Color in Malt Color Units
Parameters: grain_add (GrainAddition) – The Grain Addition to calculate Returns: The MCU of the Grain Addition Return type: float
-
get_wort_correction
(current_gu, current_volume, efficiency=44.0)¶ Get the amount of sugar to add to correct the wort
-
grain_lookup
= {}¶
-
hop_lookup
= {}¶
-
ibu
¶
-
og
¶
-
plato
¶
-
set_units
(units)¶ Set the units and unit types
Parameters: units (str) – The units
-
to_dict
()¶
-
to_json
()¶
-
classmethod
validate
(recipe)¶
-
class
brew.recipes.
RecipeBuilder
(name, grain_list=None, hop_list=None, target_ibu=33.0, target_og=1.05, brew_house_yield=0.7, start_volume=7.0, final_volume=5.0, units=u'imperial')¶ A class for building recipes
Parameters: - name (str) – The name of the recipe
- grain_list (list of Grain objects) – A list of Grains
- hop_list (list of Hop objects) – A list of Hops
- target_ibu (float) – The IBU Target
- target_og (float) – The Original Gravity Target
- brew_house_yield (float) – The brew house yield
- start_volume (float) – The starting volume of the wort
- final_volume (float) – The final volume of the wort
- units (str) – The units
-
change_units
()¶ Change units of the class from one type to the other
Returns: RecipeBuilder in new unit type Return type: RecipeBuilder
-
get_grain_additions
(percent_list)¶ Calculate GrainAdditions from list of percentages
Parameters: percent_list (list) – A list of percentages mapped to each Grain
Returns: A list of Grain Additions
Return type: list(GrainAddition)
Raises: - RecipeException – If sum of percentages does not equal 1.0
- RecipeException – If length of percent_list does not match length of self.grain_list
-
get_hop_additions
(percent_list, boil_time_list, hop_type=u'pellet', utilization_cls=<class 'brew.utilities.hops.HopsUtilizationGlennTinseth'>)¶ Calculate HopAdditions from list of boil times
Parameters: - boil_time_list (list) – A list of boil times mapped to each Hop
- utilization_cls (HopsUtilization) – The utilization class used for calculation
Returns: A list of Hop Additions
Return type: list(HopAddition)
Raises: - RecipeException – If sum of percentages does not equal 1.0
- RecipeException – If length of percent_list does not match length of self.grain_list
- RecipeException – If length of boil_time_list does not match length of self.hop_list
-
get_yeast_attenuation
(abv)¶ Estimate yeast attenuation given a target abv
Parameters: abv (float) – Alcohol by Volume Returns: Yeast Attenuation Percentage Return type: float This uses the ABV Standard Equation
-
grain_lookup
= {}¶
-
hop_lookup
= {}¶
-
set_units
(units)¶ Set the units and unit types
Parameters: units (str) – The units
brew.styles¶
-
class
brew.styles.
Style
(style, category=u'', subcategory=u'', og=None, fg=None, abv=None, ibu=None, color=None)¶ A beer style
Parameters: - category (str) – The style category
- subcategory (str) – The style subcategory
- style (str) – The style name
- og (list(float)) – The lower and upper original gravity
- fg (list(float)) – The lower and upper final gravity
- abv (list(float)) – The lower and upper alcohol by volume
- ibu (list(float)) – The lower and upper IBU
- color (list(float)) – The lower and upper color (in SRM)
-
abv_errors
(abv)¶ Return list of errors if abv doesn’t match the style
Parameters: abv (float) – Alcohol by Volume Returns: List Return type: list
-
abv_matches
(abv)¶ Determine if abv matches the style
Parameters: abv (float) – Alcohol by Volume Returns: True if matches style, otherwise False Return type: bool
-
color_errors
(color)¶ Return list of errors if color doesn’t match the style
Parameters: color (float) – Color in SRM Returns: List Return type: list
-
color_matches
(color)¶ Determine if color matches the style
Parameters: color (float) – Color in SRM Returns: True if matches style, otherwise False Return type: bool
-
fg_errors
(fg)¶ Return list of errors if fg doesn’t match the style
Parameters: fg (float) – Final Gravity Returns: List Return type: list
-
fg_matches
(fg)¶ Determine if fg matches the style
Parameters: fg (float) – Final Gravity Returns: True if matches style, otherwise False Return type: bool
-
format
()¶
-
ibu_errors
(ibu)¶ Return list of errors if ibu doesn’t match the style
Parameters: ibu (float) – IBU Returns: List Return type: list
-
ibu_matches
(ibu)¶ Determine if ibu matches the style
Parameters: ibu (float) – IBU Returns: True if matches style, otherwise False Return type: bool
-
og_errors
(og)¶ Return list of errors if og doesn’t match the style
Parameters: og (float) – Original Gravity Returns: List Return type: list
-
og_matches
(og)¶ Determine if og matches the style
Parameters: og (float) – Original Gravity Returns: True if matches style, otherwise False Return type: bool
-
recipe_errors
(recipe)¶ Return list errors if the recipe doesn’t match the style
Parameters: recipe (Recipe) – A Recipe object Returns: Errors Return type: list
-
recipe_matches
(recipe)¶ Determine if a recipe matches the style
Parameters: recipe (Recipe) – A Recipe object Returns: True if recipe matches style, otherwise False Return type: bool
-
to_dict
()¶
-
to_json
()¶
-
classmethod
validate
(recipe)¶
brew.validators¶
-
validators.
validate_grain_type
(grain_type)¶ Validate a grain type
Parameters: grain_type (str) – Type of Grain Returns: grain type Return type: str Raises: ValidatorException – If grain type is unknown
-
validators.
validate_hop_type
(hop_type)¶ Validate a hop type
Parameters: hop_type (str) – Type of Grain Returns: hop type Return type: str Raises: ValidatorException – If hop type is unknown
-
validators.
validate_percentage
(percent)¶ Validate decimal percentage
Parameters: percent (float) – Percentage between 0.0 and 1.0 Returns: percentage Return type: float Raises: ValidatorException – If decimal percentage not between 0.0 and 1.0
-
validators.
validate_units
(units)¶ Validate units
Parameters: units (str) – Unit type Returns: units Return type: str Raises: ValidatorException – If units is unknown
-
validators.
validate_required_fields
(data, required_fields)¶ Validate fields which are required as part of the data.
Parameters: - data (dict) – A python dictionary to check for required fields
- required_fields (list(tuple)) – Values and types to check for in data
Raises: - ValidatorException – Required field is missing from data
- ValidatorException – Required field is of the wrong type
The format is a list of tuples where the first element is a string with a value that should be a key found in the data dict and where the second element is a python type or list/tuple of python types to check the field against.
-
validators.
validate_optional_fields
(data, optional_fields, data_field=u'data')¶ Validate fields which are optional as part of the data.
Parameters: - data (dict) – A python dictionary to check for required fields
- optional_fields (list(tuple)) – Values and types to check for in data
- data_field (str) – The key in the data dictionary containing the optional fields
Raises: ValidatorException – Optional field is of the wrong type
The format is a list of tuples where the first element is a string with a value that should be a key found in the data dict and where the second element is a python type or list/tuple of python types to check the field against.
brew.yeasts¶
-
class
brew.yeasts.
Yeast
(name, percent_attenuation=0.75)¶ A representation of a type of Yeast as added to a Recipe.
Parameters: percent_attenuation (float) – The percentage the yeast is expected to attenuate the sugar in the yeast to create alcohol Raises: YeastException – If percent_attenuation is not provided -
format
()¶
-
to_dict
()¶
-
to_json
()¶
-
classmethod
validate
(yeast_data)¶
-
Utilities API Docs¶
brew.utilities.abv¶
-
abv.
apparent_attenuation
(original_extract, apparent_extract)¶ Apparent Attenuation
Parameters: - original_extract (float) – Original degrees Plato
- apparent_extract (float) – Apparent degrees Plato of finished beer
Returns: The percent of apparent attenuation
Return type: float
Source:
- Formula from Balling: De Clerck, Jean, A Textbook Of Brewing, Chapman & Hall Ltd., 1958
- http://beersmith.com/blog/2010/09/07/apparent-and-real-attenuation-for-beer-brewers-part-1/
- http://beersmith.com/blog/2010/09/14/apparent-and-real-attenuation-for-beer-brewers-part-2/
-
abv.
real_attenuation
(original_extract, real_extract)¶ Real Attenuation
Parameters: - original_extract (float) – Original degrees Plato
- real_extract (float) – Real degrees Plato of finished beer
Returns: The percent of real attenuation
Return type: float
-
abv.
real_attenuation_from_apparent_extract
(original_extract, apparent_extract)¶ Real Attenuation from Apparent Extract
Parameters: - original_extract (float) – Original degrees Plato
- apparent_extract (float) – Apparent degrees Plato of finished beer
Returns: The percent of real attenuation
Return type: float
-
abv.
alcohol_by_volume_standard
(og, fg)¶ Alcohol by Volume Standard Calculation
Parameters: - og (float) – Original Gravity
- fg (float) – Final Gravity
Returns: Alcohol by Volume decimal percentage
Return type: float
Most brewing sites use this basic formula:
\(\text{ABV} = \big(\text{og} - \text{fg}\big) \times 131.25\)
This equation was created before the computer age. It is easy to do by hand, and over time became the accepted formula for home brewers!
Variations on this equation which report within tenths of each other come from The Joy of Homebrewing Method by Charlie Papazian, Bee Lee’s Method, Beer Advocate Method. Some variations use 131 instead of 131.25. The resulting difference is pretty minor.
Source:
- http://www.brewersfriend.com/2011/06/16/alcohol-by-volume-calculator-updated/
- http://www.brewmorebeer.com/calculate-percent-alcohol-in-beer/
\(\text{ABV} = \frac{46.07 \text{g/mol C2H6O}}{44.0095 \text{g/mol CO2}} \times \frac{1.0}{0.7936} \times 100 \times (og - fg)\)
-
abv.
alcohol_by_volume_alternative
(og, fg)¶ Alcohol by Volume Alternative Calculation
Parameters: - og (float) – Original Gravity
- fg (float) – Final Gravity
Returns: Alcohol by Volume decimal percentage
Return type: float
Alternate Formula:
A more complex equation which attempts to provide greater accuracy at higher gravities is:
\(\text{ABV} = \frac{76.08 \times \big( \text{og} - \text{fg} \big)}{1.775 - \text{og}} \times \frac{\text{fg}}{0.794}\)
This comes from Balling’s famous formula, where the Original Extract and Real Extract values have been converted using the simple Plato to SG equation, giving Alcohol by Weight. This is then converted to Alcohol by Volume multiplying by the ratio of Final Gravity to Density of Ethanol.
The alternate equation reports a higher ABV for higher gravity beers. This equation is just a different take on it. Scientists rarely agree when it comes to equations. There will probably be another equation for ABV down the road.
The complex formula, and variations on it come from:
- Ritchie Products Ltd, (Zymurgy, Summer 1995, vol. 18, no. 2)
- Michael L. Hall’s article Brew by the Numbers: Add Up What’s in Your Beer, and Designing Great Beers by Daniels.
Source:
-
abv.
alcohol_by_weight
(abv)¶ Alcohol by Weight from ABV
Parameters: abv (float) – Alcohol by Volume Returns: Alcohol by Weight Return type: float
brew.utilities.color¶
-
color.
srm_to_ebc
(srm)¶ Convert SRM to EBC Color
Parameters: srm (float) – SRM Color Returns: EBC Color Return type: float
-
color.
ebc_to_srm
(ebc)¶ Convert EBC to SRM Color
Parameters: ebc (float) – EBC Color Returns: SRM Color Return type: float
-
color.
calculate_mcu
(grain_weight, beer_color, final_volume, units=u'imperial')¶ Calculate MCU from Grain
Parameters: - grain_weight (float) – Grain weight in lbs or kg
- beer_color (float) – Beer color in deg Lovibond
- final_volume (float) – Final Volume in gal or liters
- units (str) – The units
Source:
-
color.
calculate_srm_mosher
(mcu)¶ Mosher Equation for SRM
Parameters: mcu (float) – The Malt Color Units Returns: SRM Color Return type: float Raises: ColorException – If the MCU is < 7.0
-
color.
calculate_srm_daniels
(mcu)¶ Daniels Equation for SRM
Parameters: mcu (float) – The Malt Color Units Returns: SRM Color Return type: float Raises: ColorException – If the MCU is < 11.0
-
color.
calculate_srm_daniels_power
(mcu)¶ Daniels Power Equation for SRM based on work by Druey
Parameters: mcu (float) – The Malt Color Units Returns: SRM Color Return type: float Raises: ColorException – If the SRM is > 50.0
-
color.
calculate_srm_noonan_power
(mcu)¶ Noonan Power Equation for SRM based on work by Druey
Parameters: mcu (float) – The Malt Color Units Returns: SRM Color Return type: float Raises: ColorException – If the SRM is > 50.0
-
color.
calculate_srm_morey_hybrid
(mcu)¶ A hybrid approach used by Morey for SRM.
Parameters: mcu (float) – The Malt Color Units Returns: SRM Color Return type: float Raises: ColorException – If the MCU is > 50.0 Assumptions:
- SRM is approximately equal to MCU for values from 0 to 10.
- Homebrew is generally darker than commercial beer.
- Base on the previous qualitative postulate, I assumed that Ray Daniels’ predicted relationship exists for beers with color greater than 10.
- Since Mosher’s equation predicts darker color than Daniels’ model for values of MCU greater than 37, I assumed that Mosher’s approximation governed beer color for all values more than 37 MCUs.
- Difference in color for beers greater than 40 SRM are essentially impossible to detect visually; therefore, I limited the analysis to SRM of 50 and less.
Source:
-
color.
calculate_srm_morey
(mcu)¶ Morey Equation for SRM
Parameters: mcu (float) – The Malt Color Units Returns: SRM Color Return type: float Raises: ColorException – If the SRM is > 50.0 Source:
-
color.
calculate_srm
(mcu)¶ General SRM calculation uses the Morey Power Equation
Parameters: mcu (float) – The Malt Color Units Returns: SRM Color Return type: float Raises: ColorException – If the SRM is > 50.0
-
color.
lovibond_to_srm
(lovibond)¶ Convert deg Lovibond to SRM
Parameters: lovibond (float) – The degrees Lovibond Returns: SRM Color Return type: float Source:
-
color.
srm_to_lovibond
(srm)¶ Convert SRM to deg Lovibond
Parameters: srm (float) – SRM Color Returns: The degrees Lovibond Return type: float Source:
-
color.
srm_to_a430
(srm, dilution=1.0)¶ Get attenuation at A430 from SRM and dilution
Parameters: - srm (float) – SRM Color
- dilution (float) – The dilution factor (D=1 for undiluted, D=2 for 1:1 dilution, etc)
Returns: The attenuiation at 430nm
Return type: float
Source:
-
color.
ebc_to_a430
(ebc, dilution=1.0)¶ Get attenuation at A430 from EBC and dilution
Parameters: - ebc (float) – EBC Color
- dilution (float) – The dilution factor (D=1 for undiluted, D=2 for 1:1 dilution, etc)
Returns: The attenuiation at 430nm
Return type: float
Source:
brew.utilities.hops¶
-
class
brew.utilities.hops.
HopsUtilization
(hop_addition, units=u'imperial')¶ http://www.boondocks-brewing.com/hops
Parameters: - hop_addition (HopAddition) – A hop addition
- units (str) – The units
-
change_units
()¶ Change units of the class from one type to the other
Returns: Hop Addition in new unit type Return type: HopAddition
-
classmethod
format_utilization_table
()¶ Percent Alpha Acid Utilization - Boil Time vs Wort Original Gravity
Returns: The formatted utilization table Return type: str Source:
-
get_ibus
(sg, final_volume)¶ Get the IBUs
Parameters: - sg (float) – Specific Gravity
- final_volume (float) – The Final Volume of the wort
Returns: The IBUs of the wort
Return type: float
-
classmethod
get_percent_utilization
(sg, boil_time)¶ Get the percent utilization
Parameters: - sg (float) – Specific Gravity
- boil_time (float) – The Boil Time in minutes
Raises: NotImplementedError – This must be overridden
-
classmethod
get_utilization_table
(gravity_list, boil_time_list, sig=3)¶ Get the utilization table for the class
Parameters: - gravity_list (list) – A list of specific gravities
- boil_time_list (list) – A list of boil times in minutes
- sig (int) – Significant figures to round
Returns: A table of utilization for specific gravity vs boil time
Return type: list
-
set_units
(units)¶ Set the units and unit types
Parameters: units (str) – The units
-
class
brew.utilities.hops.
HopsUtilizationJackieRager
(hop_addition, units=u'imperial')¶ Jackie Rager Hops Utilization Method
Best for extract and partial mash brewing.
Parameters: - hop_addition (HopAddition) – A hop addition
- units (str) – The units
-
change_units
()¶ Change units of the class from one type to the other
Returns: Hop Addition in new unit type Return type: HopAddition
-
format_utilization_table
()¶ Percent Alpha Acid Utilization - Boil Time vs Wort Original Gravity
Returns: The formatted utilization table Return type: str Source:
-
classmethod
get_c_gravity
(sg)¶ Get Cgravity
Parameters: sg (float) – Specific Gravity Returns: Cgravity Return type: float Cgravity is a constant to adjust the boil size when dealing with specific gravity greater than 1.050 in the calculation of IBUs.
-
get_ibus
(sg, final_volume)¶ Get the IBUs
Parameters: - sg (float) – Specific Gravity
- final_volume (float) – The Final Volume of the wort
Returns: The IBUs of the wort
Return type: float
-
classmethod
get_percent_utilization
(sg, boil_time)¶ Get the percent utilization
Parameters: - sg (float) – Specific Gravity
- boil_time (float) – The Boil Time in minutes
Returns: The percent utilization
Return type: float
Source:
-
get_utilization_table
(gravity_list, boil_time_list, sig=3)¶ Get the utilization table for the class
Parameters: - gravity_list (list) – A list of specific gravities
- boil_time_list (list) – A list of boil times in minutes
- sig (int) – Significant figures to round
Returns: A table of utilization for specific gravity vs boil time
Return type: list
-
set_units
(units)¶ Set the units and unit types
Parameters: units (str) – The units
-
class
brew.utilities.hops.
HopsUtilizationGlennTinseth
(hop_addition, units=u'imperial')¶ Glenn Tinseth Hops Utilization Method
Best for all grain brewing.
Parameters: - hop_addition (HopAddition) – A hop addition
- units (str) – The units
-
change_units
()¶ Change units of the class from one type to the other
Returns: Hop Addition in new unit type Return type: HopAddition
-
format_utilization_table
()¶ Percent Alpha Acid Utilization - Boil Time vs Wort Original Gravity
Returns: The formatted utilization table Return type: str Source:
-
classmethod
get_bigness_factor
(sg)¶ Get Bigness Factor
Parameters: sg (float) – Specific Gravity Returns: Bigness Factor Return type: float The Bigness factor accounts for reduced utilization due to higher wort gravities. Use an average gravity value for the entire boil to account for changes in the wort volume.
\(\text{Bigness factor} = 1.65 \times 0.000125^{\text{wort gravity} - 1}\)
-
classmethod
get_boil_time_factor
(boil_time)¶ Get Boil Time Factor
Parameters: boil_time (float) – Boil Time in minutes Returns: Boil Time Factor Return type: float The Boil Time factor accounts for the change in utilization due to boil time:
\(\text{Boil Time factor} = \frac{1 - e^{-0.04 \times \text{time in mins}}}{4.15}\)
-
get_ibus
(sg, final_volume)¶ Get the IBUs
Parameters: - sg (float) – Specific Gravity
- final_volume (float) – The Final Volume of the wort
Returns: The IBUs of the wort
Return type: float
-
classmethod
get_percent_utilization
(sg, boil_time)¶ Get the percent utilization
Parameters: - sg (float) – Specific Gravity
- boil_time (float) – The Boil Time in minutes
Returns: The percent utilization
Return type: float
Source:
-
get_utilization_table
(gravity_list, boil_time_list, sig=3)¶ Get the utilization table for the class
Parameters: - gravity_list (list) – A list of specific gravities
- boil_time_list (list) – A list of boil times in minutes
- sig (int) – Significant figures to round
Returns: A table of utilization for specific gravity vs boil time
Return type: list
-
set_units
(units)¶ Set the units and unit types
Parameters: units (str) – The units
brew.utilities.malt¶
-
malt.
dry_to_liquid_malt_weight
(malt)¶ DME to LME Weight
Parameters: malt (float) – Weight of DME Returns: LME Weight Return type: float Source:
-
malt.
liquid_to_dry_malt_weight
(malt)¶ LME to DME Weight
Parameters: malt (float) – Weight of LME Returns: DME Weight Return type: float
-
malt.
grain_to_liquid_malt_weight
(grain)¶ Grain to LME Weight
Parameters: grain (float) – Weight of Grain Returns: LME Weight Return type: float
-
malt.
liquid_malt_to_grain_weight
(malt)¶ LME to Grain Weight
Parameters: malt (float) – Weight of LME Returns: Grain Weight Return type: float
-
malt.
dry_malt_to_grain_weight
(malt)¶ DME to Grain Weight
Parameters: malt (float) – Weight of DME Returns: Grain Weight Return type: float
-
malt.
grain_to_dry_malt_weight
(malt)¶ Grain to DME Weight
Parameters: grain (float) – Weight of Grain Returns: DME Weight Return type: float
-
malt.
specialty_grain_to_liquid_malt_weight
(grain)¶ Specialty Grain to LME Weight
Parameters: grain (float) – Weight of Specialty Grain Returns: LME Weight Return type: float
-
malt.
liquid_malt_to_specialty_grain_weight
(malt)¶ LME to Specialty Grain Weight
Parameters: grain (float) – Weight of LME Returns: Specialty Grain Weight Return type: float
-
malt.
fine_grind_to_coarse_grind
(fine_grind, fc_diff=0.017)¶ Fine Grind to Coarse Grind Percentage
Parameters: - fine_grind (float) – A percentage from the malt bill
- fc_diff (float) – The F/C difference percentage from the malt bill
Returns: Coarse Grind Percentage
Return type: float
-
malt.
coarse_grind_to_fine_grind
(coarse_grind, fc_diff=0.017)¶ Coarse Grind to Fine Grind Percentage
Parameters: - coarse_grind (float) – A percentage from the malt bill
- fc_diff (float) – The F/C difference percentage from the malt bill
Returns: Fine Grind Percentage
Return type: float
-
malt.
dry_basis_to_as_is_basis
(dry_basis, moisture_content=0.04)¶ Dry Basis to As-Is Basis Percentage
Parameters: - dry_basis (float) – A percentage from the malt bill in decimal form
- moisture_content (float) – A percentage of moisture content in finished malt in decimal form
Returns: As-Is Basis
Return type: float
-
malt.
as_is_basis_to_dry_basis
(as_is, moisture_content=0.04)¶ As-Is Basis to Dry Basis Percentage
Parameters: - as_is (float) – A percentage from the malt bill in decimal form
- moisture_content (float) – A percentage of moisture content in finished malt in decimal form
Returns: Dry Basis
Return type: float
-
malt.
sg_from_dry_basis
(dbcg, moisture_content=0.04, moisture_correction=0.0, brew_house_efficiency=0.9)¶ Specific Gravity from Dry Basis Percentage
Parameters: - dbcg (float) – Dry Basis Coarse Grain in decimal form
- moisture_content (float) – A percentage of moisture content in finished malt in decimal form
- moisture_correction (float) – A percentage correction in decimal form
- brew_house_efficiency (float) – The efficiency in decimal form
Returns: Specific Gravity available from Malt
Return type: float
-
malt.
plato_from_dry_basis
(dbcg, moisture_content=0.04, moisture_correction=0.0, brew_house_efficiency=0.9)¶ Degrees Plato from Dry Basis Percentage
Parameters: - dbcg (float) – Dry Basis Coarse Grain in decimal form
- moisture_content (float) – A percentage of moisture content in finished malt in decimal form
- moisture_correction (float) – A percentage correction in decimal form
- brew_house_efficiency (float) – The efficiency in decimal form
Returns: Specific Gravity available from Malt
Return type: float
-
malt.
basis_to_hwe
(basis_percentage)¶ Basis Percentage to Hot Water Extract
Parameters: basis_percentage (float) – Basis as percentage Returns: Hot Water Extract as Ldeg/kg, dry basis Return type: float Ldeg/kg means how many litres of wort with a specific gravity of 1.001 you could produce from a kilogram of the fermentable
For example, if you had a kilogram of sucrose, you could make up 386 litres of wort with a specific gravity of 1.001.
-
malt.
hwe_to_basis
(hwe)¶ Hot Water Extract to Basis Percentage
Parameters: hwe (float) – Hot Water Extract as Ldeg/kg, dry basis Returns: Basis as percentage Return type: float
-
malt.
ppg_to_hwe
(ppg)¶ Points Per Gallon to Hot Water Extract
Parameters: ppg (float) – Points Per Gallon Returns: Hot Water Extract Return type: float
-
malt.
hwe_to_ppg
(hwe)¶ Hot Water Extract to Points Per Gallon
Parameters: hwe (float) – Hot Water Extract Returns: Points Per Gallon Return type: float
brew.utilities.sugar¶
-
sugar.
sg_to_gu
(sg)¶ Specific Gravity to Gravity Units
Parameters: sg (float) – Specific Gravity Returns: Gravity Units Return type: float
-
sugar.
gu_to_sg
(gu)¶ Gravity Units to Specific Gravity
Parameters: gu (float) – Gravity Units Returns: Specific Gravity Return type: float
-
sugar.
plato_to_sg
(deg_plato)¶ Degrees Plato to Specific Gravity
Parameters: deg_plato (float) – Degrees Plato Returns: Specific Gravity Return type: float The simple formula for S.G. is:
\(\text{SG} = 1 + 0.004 \times \text{Plato}\)
The more precise calculation of SG is:
\(\text{SG} = \frac{Plato}{258.6 - \big(\frac{Plato}{258.2} \times 227.1\big)} + 1\)
Source:
-
sugar.
sg_to_plato
(sg)¶ Specific Gravity to Degrees Plato
Parameters: sg (float) – Specific Gravity Returns: Degrees Plato Return type: float \(\text{Plato} = \frac{\big(\text{SG} - 1\big) \times 1000}{4}\)
The more precise calculation of Plato is:
\(\text{Plato} = -616.868 + 1111.14 \times sg - 630.272 \times sg^2 + 135.997 \times sg^3\)
Source:
-
sugar.
brix_to_sg
(brix)¶ Degrees Brix to Specific Gravity
Parameters: brix (float) – Degrees Brix Returns: Specific Gravity Return type: float Source:
-
sugar.
sg_to_brix
(sg)¶ Specific Gravity to Degrees Brix
Parameters: sg (float) – Specific Gravity Returns: Degrees Brix Return type: float Source:
-
sugar.
brix_to_plato
(brix)¶ Degrees Brix to Degrees Plato
Parameters: brix (float) – Degrees Brix Returns: Degrees Plato Return type: float The difference between the degBx and degP as calculated from the respective polynomials is:
\(\text{degP} - \text{degBx} = \big(\big(\big(-2.81615*sg + 8.79724\big) \times sg - 9.1626\big) \times sg + 3.18213\big)\)
The difference is generally less than +/-0.0005 degBx or degP with the exception being for weak solutions.
Source:
-
sugar.
plato_to_brix
(plato)¶ Degrees Plato to Degrees Brix
Parameters: brix (float) – Degrees Plato Returns: Degrees Brix Return type: float
-
sugar.
apparent_extract_to_real_extract
(original_extract, apparent_extract)¶ Apparent Extract to Real Extract in degrees Plato
Parameters: - original_extract (float) – Original degrees Plato
- apparent_extract (float) – Apparent degrees Plato of finished beer
Returns: Real degrees Plato of finished beer
Return type: float
Source:
- Formula from Balling: De Clerck, Jean, A Textbook Of Brewing, Chapman & Hall Ltd., 1958
-
sugar.
hydrometer_adjustment
(sg, temp, units=u'imperial')¶ Adjust the Hydrometer if the temperature deviates from 59degF.
Parameters: - sg (float) – Specific Gravity
- temp (float) – Temperature
- units (str) – The units
Returns: Specific Gravity corrected for temperature
Return type: float
Raises: SugarException – If temperature outside freezing to boiling range of water
The correction formula is from Lyons (1992), who used the following formula to fit data from the Handbook of Chemistry and Physics (CRC):
\(\text{Correction(@59F)} = 1.313454 - 0.132674 \times T + 2.057793e^{-3} \times T^2 - 2.627634e^{-6} \times T^3\)
where T is in degrees F.
Sources:
-
sugar.
refractometer_adjustment
(og, fg, wort_correction_factor=1.04)¶ Adjust the Refractometer for the presence of alcohol.
Parameters: - og (float) – Original Gravity
- fg (float) – Final Gravity
- wort_correction_factor (float) – A correction to the reading given by the refractometer
Returns: Final Gravity adjusted
Return type: float
NOTE: This calculation assumes using Brix or Plato, so the input will be converted from SG to Plato and then converted back.
Sources:
- New Cubic from http://seanterrill.com/2011/04/07/refractometer-fg-results/
brew.utilities.temperature¶
-
temperature.
fahrenheit_to_celsius
(temp)¶ Convert degrees Fahrenheit to degrees Celsius
Parameters: temp (float) – The temperature in Fahrenheit Returns: The temperature in Celsius Return type: float
-
temperature.
celsius_to_fahrenheit
(temp)¶ Convert degrees Celsius to degrees Fahrenheit
Parameters: temp (float) – The temperature in Celsius Returns: The temperature in Fahrenheit Return type: float
brew.utilities.yeast¶
-
class
brew.utilities.yeast.
YeastModel
(method, units=u'imperial')¶ -
METHOD_TO_GROWTH_ADJ
= {u'shaking': 0.0, u'stir plate': 0.0, u'no agitation': 0.0}¶
-
get_growth_rate
(inoculation_rate)¶
-
get_inoculation_rate
(growth_rate)¶
-
get_resulting_pitch_rate
(starter_cell_count, original_gravity=1.036, final_volume=5.0)¶
-
get_starter_volume
(available_cells, starter_volume=0.5283443537159779, original_gravity=1.036)¶ Calculate the number of cells given a stater volume and gravity
-
get_viability
(days_since_manufacture)¶ Yeast viability drops 21% each month or 0.7% per day from the date of manufacture. Assume linear change.
-
get_yeast_pitch_rate
(original_gravity=1.05, final_volume=5.0, target_pitch_rate=1.42, yeast_type=u'liquid', cells_per_pack=100, num_packs=1, days_since_manufacture=30)¶ Determine yeast pitch rate
original_gravity - specific gravity of original beer final_volume - volume of the batch post fermentation target_pitch_rate - million cells / (ml * degP) yeast_type - liquid, dry cells_per_pack - Billions of cells num_packs - how many in units days_since_manufacture - the older the yeast the less viable units - imperial, metric
Yeast Viability: lose 20% viability / month or 0.66% / day
Imperial: B / Gal / GU Metric: M / ml / Plato
Sources: - http://beersmith.com/blog/2011/01/10/yeast-starters-for-home-brewing-beer-part-2/
-
set_units
(units)¶
-
-
class
brew.utilities.yeast.
KaiserYeastModel
(method=u'stir plate', units=u'imperial')¶ Kaiser Yeast Model
Only works for Stir Plage Growth
Sources:
-
METHOD_TO_GROWTH_ADJ
= {u'stir plate': 0.0}¶
-
get_growth_rate
(initial_cells)¶ initial_cells - Billion / gram extract (B/g)
-
get_inoculation_rate
(growth_rate)¶
-
get_resulting_pitch_rate
(starter_cell_count, original_gravity=1.036, final_volume=5.0)¶
-
get_starter_volume
(available_cells, starter_volume=0.5283443537159779, original_gravity=1.036)¶ Calculate the number of cells given a stater volume and gravity
-
get_viability
(days_since_manufacture)¶ Yeast viability drops 21% each month or 0.7% per day from the date of manufacture. Assume linear change.
-
get_yeast_pitch_rate
(original_gravity=1.05, final_volume=5.0, target_pitch_rate=1.42, yeast_type=u'liquid', cells_per_pack=100, num_packs=1, days_since_manufacture=30)¶ Determine yeast pitch rate
original_gravity - specific gravity of original beer final_volume - volume of the batch post fermentation target_pitch_rate - million cells / (ml * degP) yeast_type - liquid, dry cells_per_pack - Billions of cells num_packs - how many in units days_since_manufacture - the older the yeast the less viable units - imperial, metric
Yeast Viability: lose 20% viability / month or 0.66% / day
Imperial: B / Gal / GU Metric: M / ml / Plato
Sources: - http://beersmith.com/blog/2011/01/10/yeast-starters-for-home-brewing-beer-part-2/
-
set_units
(units)¶
-
-
class
brew.utilities.yeast.
WhiteYeastModel
(method=u'no agitation', units=u'imperial')¶ Sources:
- http://www.brewersfriend.com/yeast-pitch-rate-and-starter-calculator/
- White, Chris, and Jamil Zainasheff. Yeast: The Practical Guide to Beer Fermentation. Boulder, CO: Brewers Publications, 2010. 139-44. Print.
-
INOCULATION_CONST
= [-0.999499, 12.547938, -0.459486]¶
-
METHOD_TO_GROWTH_ADJ
= {u'shaking': 0.5, u'stir plate': 1.0, u'no agitation': 0.0}¶
-
get_growth_rate
(inoculation_rate)¶ initial_cells - Billion / gram extract (B/g)
G = (12.54793776 * x^-0.4594858324) - 0.9994994906
-
get_inoculation_rate
(growth_rate)¶
-
get_resulting_pitch_rate
(starter_cell_count, original_gravity=1.036, final_volume=5.0)¶
-
get_starter_volume
(available_cells, starter_volume=0.5283443537159779, original_gravity=1.036)¶ Calculate the number of cells given a stater volume and gravity
-
get_viability
(days_since_manufacture)¶ Yeast viability drops 21% each month or 0.7% per day from the date of manufacture. Assume linear change.
-
get_yeast_pitch_rate
(original_gravity=1.05, final_volume=5.0, target_pitch_rate=1.42, yeast_type=u'liquid', cells_per_pack=100, num_packs=1, days_since_manufacture=30)¶ Determine yeast pitch rate
original_gravity - specific gravity of original beer final_volume - volume of the batch post fermentation target_pitch_rate - million cells / (ml * degP) yeast_type - liquid, dry cells_per_pack - Billions of cells num_packs - how many in units days_since_manufacture - the older the yeast the less viable units - imperial, metric
Yeast Viability: lose 20% viability / month or 0.66% / day
Imperial: B / Gal / GU Metric: M / ml / Plato
Sources: - http://beersmith.com/blog/2011/01/10/yeast-starters-for-home-brewing-beer-part-2/
-
set_units
(units)¶
-
yeast.
pitch_rate_conversion
(pitch_rate, units=u'imperial')¶ Pitch Rate Conversion
Input should be given in: Imperial: B / (Gal * GU) SI: B / (L * P)
Note: 1 M / (ml * P) == 1B / (L * P)
Glossary¶
- Alpha Acid Units (AAU)
- Defined as \(\text{AAU} = \text{weight of hops} \times \text{alpha acids}\).
- Apparent Extract (AE)
- The measured hydrometer reading for the finished beer.
- BJCP
- Beer Judge Certification Program. Publishes style guidelines for beer.
- Boil Gravity
- The specific gravity of the wort before it has been boiled and cooled. For a recipe where the boil volume is greater than the fermenting volume this can mean a gravity that is much lower than the Original Gravity. If the boil volume is less than the fermenting volume (ie water is ‘topped up’) then the gravity can be much higher than the OG.
- Boil Volume
- The volume of the wort during the boil.
- Brew House Yield (BHY)
Brew house yield is a measurement that tells the efficiency of the brewing. The actual degrees Plato from the brew and the actual gallons collected out of the kettle are needed to calculate the BHY.
\(\text{BHY} = \frac{P_{actual} \times \text{vol}_{actual} \times \text{BHY}_{target}}{P_{target} \times \text{vol}_{target}}\)
- Cereal
- A type of whole grain used for brewing.
- DME
- Dry Malt Extract
- Final Gravity
- The specific gravity of the beer after it has been fermented. The final gravity measures the density of a sugar, alcohol, and water mixture which is different than the original gravity which only measures sugar and water. This is why refractometers must be adjusted when used to measure FG.
- Final Volume
- The volume of the wort at the finish of the boil.
- Gravity Units (GU)
The gravity units of a recipe is defined as the total points of the recipe (as measured in PPG or HWE depending on units) divided by the volume of the wort.
\(\text{GU} = \text{PPG} \div \text{Wort Volume}\)
- Hot Water Extract
The international unit for the total soluble extract of a malt, based on specific gravity. HWE is measured as liter*degrees per kilogram, and is equivalent to points/pound/gallon (PPG) when you apply metric conversion factors for volume and weight. The combined conversion factor is:
\(\text{HWE} = 8.3454 \times \text{PPG}\)
- International Bitterness Units (IBUs)
IBUs or International Bittering Units measures a bitterness unit for hops. IBUs are the measurement in parts per million (ppm) of iso-alpha acids in the beer. For example, an IPA with 75 IBUs has 75 milligrams of isomerized alpha acids per liter. The equation used to calculate the weight of hops for the boil is as follows.
\(\text{Ounces hops} = \frac{\text{IBU Target} \times \text{galbeer} \times \text{IBU%}}{\text{%a-acid} \times \text{%Utilization} \times 7489}\)
The IBU target equals the total bitterness for the beer. (e.g. an IPA may have an IBU target of 75 IBUs) The percent IBU is equal to the percent of IBUs from each hop addition. You may wish for your first hop addition to contribute 95% of the total IBUs. This would make your IBU% 95%. The %a-acid is the amount of alpha acid in the hops and can be found on the hop packaging. The % Utilization is a measurement of the percentage of alpha acid units that will isomerize in the boil. The following chart outlines the typical utilizations and hop boil times.
Boil Time Utilization 60 min 30% 30 min 15% 5 min 2.5% The 7489 is a conversion factor and used to cancel the units in the equation, converting oz/gallon to mg/l. For the hops equation, the units for the % must be expressed in decimal form. (e.g. 10%= .10)
Source:
- LME
- Liquid Malt Extract
- Malt Color Units (MCU)
The color of malt as a function of weight, beer color, and wort volume.
\(\text{MCU} = \frac{\text{grain weight} \times \text{beer color in SRM}}{\text{wort volume}}\)
- Mash Water Volume
To calculate the mash water volume you will need to know your liquor to grist ratio. The term liquor refers to the mash water and grist refers to the milled malt. We need to calculate the appropriate amount of water to allow for enzyme action and starch conversion take place.
\(\text{gallons H2O} = \frac{\text{Lbs malt} \times \text{L:G} \times \text{1 gallon H2O}}{\text{8.32 pounds water}}\)
- Original Gravity
- The specific gravity of the wort after it has been cooled and put into the fermenter.
- Original Volume
- Start Volume
- The volume of the wort at the beginning of the process.
- Plato
- Degrees Plato
- Degrees Plato is the weight of the extract in a 100gram solution at 64 degrees Fahrenheit.
- Real Extract
- The real extract content of the finished beer.
- Specific Gravity
- The ratio of the density of the wort against the density of water.
- Standard Reference Method (SRM)
- SRM is the standard unit of measure of the color of beer
- Strike Water
As you know when you are mashing, your strike water has to be warmer than the target mash temperature because the cool malt will cool the temperature of the water. To correctly calculate the temperature of the strike water, use the following formula.
\(\text{Strike Temp} = \frac{0.4 \times \big(\text{T}_{mash} - \text{T}_{malt}\big)}{L:G} + \text{T}_{mash}\)
- Weight of Extract
The weight of extract is the amount of malt extract present in the wort.
\(\text{Lbs extract} = \text{density of water} \times \text{gal of wort} \times \text{SG} \times \frac{P}{100}\)
The weight of one gallon of water in the above formula is 8.32 lbs/gal
To find the weight of a gallon of wort, multiply the specific gravity of the wort by the density of water.
Plato is a percentage of sugars by weight. So 10 Plato means solution is 10% sugars. In this equation we convert the degrees plato to a decimal number between 0.0 and 1.0 by dividing it by 100. This is multiplied by the weight of a gallon of wort.
- Working Yield
The product of the Hot Water Extract multiplied by the Brew House Yield. This product will provide the percent of extract collected from the malt.
\(WY = \text{HWE as-is} \times \text{BHY}\)
- Wort Color
The color of the wort
\(\text{Color of Wort} = \text{S} \times \text{% extract} \times \text{L of malt} \times \frac{\text{P wort}}{\text{8P reference}}\)
Source: