# Input variables and calculated variables

**Input variables** and **calculated variables** are what turn your brew sheet from a checklist into data you can calculate with and report on.

* An **input variable** labels a reading or check on a recipe so the same measurement can be tracked across every batch, recipe and recipe version that uses it - your mash temperature, your post-boil gravity, and so on.

* A **calculated variable** is a formula that works out a new value from your input variables (and from other calculated variables) - your brewhouse efficiency, your apparent attenuation, the length of your mash.

Both live under **Production** → **View** → **Recipes** → **Settings & options**, where you'll find an **Input variables** page and a **Calculated variables** page.

> **Note:**
> **Renamed:** what used to be called **Reporting tags** are now **Input variables**, and **Calculated fields** are now **Calculated variables**. They work in exactly the same way - only the names have changed.

Breww also ships a set of **system** input and calculated variables that every account can see. You can't rename or delete these, but you can set your own [deviation thresholds](https://breww.com/docs/deviation-thresholds-and-targets/) on them. If you create your own variable with the same variable name as a system one, yours takes precedence in formulas.

## Finding a variable

Both pages show your variables a page at a time, so a long list stays quick to open. Move between pages with the links at the bottom, and use the picker at the top left to show 25, 50, 75 or 100 rows at a time.

* On the **Input variables** page, the search box at the top right matches both the name you gave the variable and the variable name used in formulas, so searching for `gravity` finds **Post boil gravity** and `post_boil_gravity` alike.

* Click a column heading to sort by it: **Name**, **Type** or **Sub-type** on the Input variables page, and **Name** on the Calculated variables page.

Each row shows the variable's name with its formula name underneath, its **Measurement type**, and the deviation thresholds that currently apply, along with buttons to edit it, set its deviation alerts, and delete it. Breww's own system variables can't be edited or deleted, so those two buttons are greyed out on their rows.

## Input variables

### Creating an input variable

Go to **Settings & options** → **Input variables** → **Add new** and fill in:

* **Name** - what you'll call it, e.g. **Post boil gravity**.

* **Type** - whether this variable is recorded by a **Reading** action or a **Check** action on your recipe.

* **Reading type** - for readings only, which of the reading types below it is. This determines the units offered, how the value is displayed, and which threshold units apply.

* **Deviation thresholds** - optionally, how far a reading can drift from its target before Breww flags it. See [Deviation thresholds and targets](https://breww.com/docs/deviation-thresholds-and-targets/).

You don't enter the variable name used in formulas - Breww derives it from the name you give. **Original gravity** becomes `original_gravity`, **Post-boil gravity** becomes `post_boil_gravity`, and a name starting with a digit gets a `v_` prefix so it's still valid in a formula (**30 HL gravity reading** becomes `v_30_hl_gravity_reading`).

> **Note:**
> If you rename an input variable later, Breww automatically updates any formulas that reference it, so your calculated variables keep working. Only genuine references are updated. If the old name also happens to appear inside quotation marks somewhere in a formula, that text is left exactly as you wrote it.

### The reading types

| Reading type     | What it records                                                          | Units                       |
| ---------------- | ------------------------------------------------------------------------ | --------------------------- |
| Temperature      | A temperature                                                            | `°C`, `°F`                  |
| Gravity          | A gravity reading                                                        | `SG`, `Plato`, `Brix`       |
| pH               | A pH reading                                                             | `pH`                        |
| Weight           | A weight                                                                 | `kg`, `lb`                  |
| Volume           | A volume                                                                 | `l`, `hl`, `gal`, `bbl`     |
| Time of day      | A clock time, e.g. when you mashed in                                    | -                           |
| Duration         | An elapsed length of time, e.g. how long the mash took                   | -                           |
| Distance         | A length or depth                                                        | `mm`, `cm`, `m`, `in`, `ft` |
| Pressure         | A pressure                                                               | `bar`, `psi`                |
| CO₂              | Dissolved carbon dioxide                                                 | `g/l`, `mg/l`, `vol`        |
| Percentage       | Any percentage value                                                     | - (shown with `%`)          |
| Dissolved oxygen | Dissolved oxygen                                                         | `ppm`, `ppb`, `mg/l`        |
| Colour           | Beer colour                                                              | `EBC`, `SRM`                |
| Bitterness       | Bitterness                                                               | `IBU`                       |
| Haze             | Haze/turbidity                                                           | `EBC`, `NTU`, `ASBC`, `FTU` |
| Custom           | Anything that doesn't fit a standard measurement - recorded as free text | -                           |

> **Note:**
> **Time of day** and **Duration** are two separate types, and the difference matters. **Time of day** is a clock reading (`08:45`); **Duration** is how long something took (`1h 30m`). The type previously called simply **Time** is now called **Time of day** to make that distinction clear - nothing about your existing time readings has changed other than the name.

Because a **Custom** reading is free text, it can hold anything you like - but Breww can't do maths on it, so it can't be used in a formula or plotted on a comparison chart. If you want to calculate or chart a value, use one of the measured types instead.

### Using an input variable on a recipe action

Once created, apply the input variable to the relevant action in your recipe. When you choose **Add action** → **Reading**, Breww shows a two-pane picker:

* The **left rail** is a searchable list of all the reading types. Start typing to filter it, and each type shows how many of your input variables already use it.

* The **right pane** shows the input variables available for the reading type you've selected.

If the reading type you need doesn't yet have a suitable input variable, choose the **Other [type] reading** option. Breww will offer to **create an input variable first** (recommended, so the reading is reusable in calculations and reporting), or to **continue without one** for a genuine one-off.

### Recording readings on the brew sheet

On the brew sheet, each reading type gives the brewer the right kind of input - a number plus a unit for measured types, a time picker for **Time of day**, and a free-text length of time for **Duration**.

A **Duration** is typed with its unit, for example `45m` or `1h 30m`:

| You type | Breww records       |
| -------- | ------------------- |
| `45m`    | 45 minutes          |
| `1h 30m` | 1 hour 30 minutes   |
| `90s`    | 1 minute 30 seconds |
| `2d 6h`  | 2 days 6 hours      |
| `1w`     | 1 week              |

The units you can use are seconds (`s`, `sec`, `secs`, `second`, `seconds`), minutes (`m`, `min`, `mins`, `minute`, `minutes`), hours (`h`, `hour`, `hours`), days (`d`, `day`, `days`) and weeks (`w`, `week`, `weeks`).

> **Warning:**
> A duration always needs a unit. Typing `45` on its own won't be accepted - use `45m` so it's unambiguous whether you mean minutes, hours or something else.

### Check input variables

An input variable on a **Check** action records that a yes/no verification step was completed, which is useful for reporting across batches. Checks aren't numeric measurements, so they can't be used inside a calculated variable's formula - only reading input variables can.

## Calculated variables

### Creating a calculated variable

Go to **Settings & options** → **Calculated variables** → **Add new** and fill in:

* **Name** - e.g. **Litre degrees**. As with input variables, the formula name is derived automatically (`litre_degrees`).

* **Formula** - the calculation itself, written using your variable names.

* **Measurement type** - the kind of value the formula produces. This controls how the result is formatted and which units its thresholds use.

* **Deviation thresholds** - optionally, the acceptable and warning bands for the result.

Names have to be unique across both input variables and calculated variables (including the system ones), and can't be a reserved programming word. Breww will tell you if the name you've chosen clashes.

> **Warning:**
> If you edit a calculated variable that has already been used on a live brew sheet, you'll be asked to confirm. Changing the formula changes the calculated result on batches that have already been brewed, because the value is worked out from the readings rather than frozen at the time.

> **Note:**
> That confirmation only applies to editing the variable itself. If all you want to change is its deviation thresholds, use the **deviation alerts** (warning triangle) button on the **Calculated variables** page instead. It opens a thresholds-only form, and as the formula isn't changing there's nothing to confirm.

![The Calculated variables page, with the deviation alerts button beside Edit on each of your own variables](https://storage.googleapis.com/breww-user-uploads/markdown-embedded/3426e34a3cfe29a993b3b906a8cb66dd03d8d3001abf8579cc52e24efd3d9d6b.png)

### Writing a formula

Reference any input variable or calculated variable by its variable name, and combine them with the usual operators:

| Operator        | Meaning                                       |
| --------------- | --------------------------------------------- |
| `+` `-` `*` `/` | Add, subtract, multiply, divide               |
| `^` or `**`     | Raise to a power                              |
| `%`             | Remainder                                     |
| `( )`           | Grouping, to control the order of calculation |

For example, a simple "litre degrees" calculation:

```
post_boil_gravity * volume_in_fv
```

A few things worth knowing:

* **Calculated variables can reference other calculated variables,** so you can build a complicated figure up in readable steps rather than one enormous formula. Breww detects circular references (A depends on B which depends on A) and won't let you save them, since they can't be worked out.

* **A formula must produce a number, a time of day, or a duration.** A formula that produces a yes/no answer (e.g. `original_gravity > 1.05`) can't be saved as a calculated variable.

* **If a variable was recorded more than once on the batch, Breww averages the values** so the result is always well-defined.

* **On multi-turn batches,** a formula running on a stage that repeats per turn sees that turn's readings plus any readings from stages that don't repeat per turn. A formula running on a stage that doesn't repeat per turn averages any per-turn readings across all the turns.

The formula editor highlights your syntax, autocompletes your variable names as you type, and flags obvious mistakes before you save. The page also lists every input variable and calculated variable you can reference, and a **Functions** card showing the functions available to you.

### Functions

| Function   | Example              | What it does                                                                      |
| ---------- | -------------------- | --------------------------------------------------------------------------------- |
| `duration` | `duration("1h 30m")` | A fixed length of time you can add to or subtract from a time or another duration |

### Measurement types

The **measurement type** tells Breww what kind of value your formula produces:

**Temperature**, **Gravity**, **pH**, **Weight**, **Volume**, **Time of day**, **Duration**, **Distance**, **Pressure**, **CO₂**, **Percentage**, **Dissolved oxygen**, **Colour**, **Bitterness**, **Haze**, or **Unitless**.

Pick **Unitless** for a plain number that isn't a physical measurement (a ratio, an efficiency percentage point, a count). Otherwise pick the type that matches the result - it determines how the value is formatted on the brew sheet and which units are offered for its deviation thresholds.

For **Time of day** and **Duration** the measurement type isn't just cosmetic - it has to match what the formula actually works out:

* A formula that produces a clock time must use **Time of day**.

* A formula that produces an elapsed length of time must use **Duration**.

* A formula that produces a plain number must use **neither** of those.

If they don't match, Breww won't save the calculated variable, and will tell you which measurement type the formula needs.

### Working with times and durations

Clock times and lengths of time aren't interchangeable, so Breww keeps them apart in formulas. Subtracting one clock time from another gives you a length of time; adding a length of time to a clock time gives you another clock time.

| Formula                   | What you get                              |
| ------------------------- | ----------------------------------------- |
| time of day − time of day | a **duration** (how long between the two) |
| time of day + duration    | a **time of day** (later)                 |
| time of day − duration    | a **time of day** (earlier)               |
| duration + duration       | a **duration**                            |
| duration − duration       | a **duration**                            |
| duration × a number       | a **duration**                            |
| duration ÷ a number       | a **duration**                            |

Some combinations have no sensible meaning, and Breww will tell you so when you save:

* **Adding a plain number to a time of day or a duration.** A bare `45` doesn't say whether you mean minutes, hours or days - use `duration("45m")` instead.

* **Multiplying or dividing a time of day.** "Half past nine, doubled" isn't a meaningful value.

* **Subtracting a duration from a plain number**, or **comparing a time of day against a duration**.

Time-of-day readings are always converted to your brewery's own timezone before the calculation runs, using the date the reading was taken so daylight saving is handled for you.

### Worked examples

**Litre degrees**, from a gravity reading and a volume reading:

```
post_boil_gravity * volume_in_fv
```

Measurement type: **Unitless**.

**How long the mash took**, from two time-of-day input variables:

```
mash_out_time - mash_in_time
```

Measurement type: **Duration**. The brew sheet will show something like `1h 25m`.

**When to expect knockout**, from a single time-of-day input variable:

```
mash_in_time + duration("4h 30m")
```

Measurement type: **Time of day**. The brew sheet will show something like `13:15`.

**Total time across two stages**, from two duration readings or calculations:

```
mash_length + boil_length
```

Measurement type: **Duration**.

## Targets and deviation thresholds

Both input variables and calculated variables can have **deviation thresholds** - the acceptable and warning bands around a target - set centrally on the variable, with optional per-action overrides. Targets themselves are set on the individual recipe action. See [Deviation thresholds and targets](https://breww.com/docs/deviation-thresholds-and-targets/) for the full explanation.

How you enter a target depends on the type:

* **Measured types** (temperature, gravity, pH, weight, volume, and so on) - a number plus a unit.

* **Percentage** - a plain number; Breww adds the `%`.

* **Time of day** - a clock time, chosen with a time picker.

* **Duration** - a length of time, typed as e.g. `45m` or `1h 30m`.

For **Time of day** and **Duration**, the threshold bands are offsets in `second`, `minute`, `hour` or `day`. So a duration target of `1h 30m` with an acceptable band of `± 5 minutes` is in spec anywhere from `1h 25m` to `1h 35m`.

The live preview on the recipe action form renders in the same terms as the brew sheet, so you can check a target and its bands read sensibly before saving.

## How values are displayed and used

Once a reading is recorded or a calculation resolves, its value is formatted according to its type - a measured value with its unit, a percentage with `%`, a time of day as a clock time, and a duration as a span like `1h 30m`.

* A **time of day** that carries over midnight gets a day marker so it isn't misleading: `01:15 +1d` means quarter past one the following morning, and `23:45 -1d` means quarter to midnight the previous evening.

* A **negative duration** - usually a sign two readings were recorded the wrong way round - is shown with a leading minus, e.g. `-15m`.

You'll see the same formatting used consistently across:

* The **live brew sheet**, where calculations update as the brewer enters readings.

* The **PDF brew sheet**, including targets and threshold bands.

* The **Alerts** tab of the production dashboard, where out-of-spec readings and calculations are surfaced. See [Deviation thresholds and targets](https://breww.com/docs/deviation-thresholds-and-targets/) for how to choose whether a calculation raises alerts.

* **Batch comparison charts**, both from a batch's **Analysis** tab and on a saved [batch comparison dashboard](https://breww.com/docs/batch-comparison-dashboards/). Axis labels and tooltips are shown as clock times or durations where appropriate rather than raw numbers, and target lines and threshold bands line up with them. In the summary table, the **Range** column (highest minus lowest) is always shown as a duration for time-of-day variables, because the gap between two clock times is a length of time, not a time of day.

* **Approvals.** Approval templates (pre-packaging, post-packaging, pre-transfer and post-transfer) can include a **Calculated variable** line that pulls the result straight from the batch. When the linked variable is a time of day or a duration, the **Target**, **Acceptable range from** and **Acceptable range to** fields adapt to match - a time picker or a duration field - and the values display as clock times or durations on the approval itself.

* **Reporting**, where an input variable lets you compare the same measurement across batches, recipes and recipe versions.

## Deleting a variable

You can delete your own input and calculated variables from their list pages, but only while nothing depends on them. Breww will stop you and explain why if:

* the variable is **used on a recipe** - take it off the recipe action first;

* a calculated variable is **used on an approval template**, or on an approval that has already been raised; or

* a calculated variable is **used in another calculated variable's formula** - Breww names the variable that depends on it, so you know where to look.

Breww's own system variables can't be deleted. If you don't want to use one, simply don't add it to a recipe.

## Importing and exporting variables

Input variables and calculated variables are included when you export a recipe as a Breww recipe file, and can be created on import. The file format documents the exact `reading_type` and `measurement_type` values, and how targets and threshold blocks are written for each. See [Importing and exporting recipes using a Breww recipe file](https://breww.com/docs/breww-recipe-file-import-export/).

## What changed for existing accounts

If you were already using time readings in calculations, a few things were corrected automatically:

1. **Times are now read in your brewery's local time.** Previously, a time reading used in a formula was treated as UTC, so any brewery not on UTC saw results shifted by their offset - for example `mash_in_time + 45` returning `08:23` instead of `09:23`. Breww now converts each reading to your brewery's local time first, using the date the reading was taken so daylight saving is handled correctly.

2. **Formulas that added a bare number of minutes were updated for you.** A formula like `mash_in_time + 45` was rewritten to `mash_in_time + duration("45m")` so it keeps working and clearly says what the `45` means.

3. **Measurement types were corrected.** Calculated variables whose formula produces a clock time or an elapsed length of time had their measurement type set to **Time of day** or **Duration** as appropriate. Any variable marked as a time or duration but actually producing a plain number was reset to **Unitless**.

4. **Existing brew sheets were recalculated,** so historical batches show the corrected results rather than the old ones.

> **Note:**
> There's nothing you need to do for any of the above. If a time-based calculation still doesn't look right, open it under **Settings & options** → **Calculated variables** and check that its formula and measurement type describe what you're expecting.

## Related guides

* [Recipes & brew sheets](https://breww.com/docs/recipes-and-brew-sheets/)

* [Deviation thresholds and targets](https://breww.com/docs/deviation-thresholds-and-targets/)

* [Using your electronic brew sheet on a brew day](https://breww.com/docs/brew-sheets/)

* [Batch readings comparison](https://breww.com/docs/batch-comparison-reporting/)

* [Importing and exporting recipes using a Breww recipe file](https://breww.com/docs/breww-recipe-file-import-export/)
