@hestia-earth/engine-models 0.81.5 → 0.82.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +19 -0
  2. package/cjs/formulas.d.ts +86 -0
  3. package/cjs/formulas.js +180 -0
  4. package/cjs/index.d.ts +1 -0
  5. package/cjs/index.js +1 -0
  6. package/cjs/version.d.ts +1 -1
  7. package/cjs/version.js +1 -1
  8. package/config/Cycle.json +2 -2
  9. package/config/ImpactAssessment.json +12 -0
  10. package/esm/formulas.d.ts +86 -0
  11. package/esm/formulas.js +130 -0
  12. package/esm/index.d.ts +1 -0
  13. package/esm/index.js +1 -0
  14. package/esm/version.d.ts +1 -1
  15. package/esm/version.js +1 -1
  16. package/formulas/README.md +190 -0
  17. package/formulas/deRuijterEtAl2010/nh3ToAirCropResidueDecomposition.json +30 -0
  18. package/formulas/emepEea2019/co2ToAirFuelCombustion.json +23 -0
  19. package/formulas/emepEea2019/nh3ToAirExcreta.json +27 -0
  20. package/formulas/emepEea2019/pm10ToAirAnimalHousing.json +28 -0
  21. package/formulas/emepEea2019/pm25ToAirAnimalHousing.json +28 -0
  22. package/formulas/emepEea2019/tspToAirAnimalHousing.json +28 -0
  23. package/formulas/hestia/feedConversionRatio/feedConversionRatioCarbon.json +23 -0
  24. package/formulas/index.json +2464 -0
  25. package/formulas/ipcc2019/belowGroundCropResidue.json +31 -0
  26. package/formulas/ipcc2019/ch4ToAirAquacultureSystems.json +29 -0
  27. package/formulas/ipcc2019/ch4ToAirEntericFermentation.json +29 -0
  28. package/formulas/ipcc2019/ch4ToAirExcreta.json +36 -0
  29. package/formulas/ipcc2019/ch4ToAirFloodedRice.json +31 -0
  30. package/formulas/ipcc2019/ch4ToAirOrganicSoilCultivation.json +40 -0
  31. package/formulas/ipcc2019/co2ToAirUreaHydrolysis.json +27 -0
  32. package/formulas/ipcc2019/emissionsToAirOrganicSoilBurning.json +49 -0
  33. package/formulas/ipcc2019/n2OToAirAquacultureSystemsIndirect.json +31 -0
  34. package/formulas/ipcc2019/n2OToAirCropResidueBurningDirect.json +25 -0
  35. package/formulas/ipcc2019/n2OToAirCropResidueDecompositionDirect.json +28 -0
  36. package/formulas/ipcc2019/n2OToAirCropResidueDecompositionIndirect.json +35 -0
  37. package/formulas/ipcc2019/n2OToAirExcretaDirect.json +25 -0
  38. package/formulas/ipcc2019/n2OToAirExcretaIndirect.json +39 -0
  39. package/formulas/ipcc2019/n2OToAirFuelCombustionIndirect.json +31 -0
  40. package/formulas/ipcc2019/n2OToAirInorganicFertiliserDirect.json +28 -0
  41. package/formulas/ipcc2019/n2OToAirInorganicFertiliserIndirect.json +39 -0
  42. package/formulas/ipcc2019/n2OToAirNaturalVegetationBurningIndirect.json +31 -0
  43. package/formulas/ipcc2019/n2OToAirOrganicFertiliserDirect.json +28 -0
  44. package/formulas/ipcc2019/n2OToAirOrganicFertiliserIndirect.json +39 -0
  45. package/formulas/ipcc2019/n2OToAirOrganicSoilBurningIndirect.json +31 -0
  46. package/formulas/ipcc2019/n2OToAirOrganicSoilCultivationIndirect.json +31 -0
  47. package/formulas/ipcc2019/nh3ToAirInorganicFertiliser.json +31 -0
  48. package/formulas/ipcc2019/nh3ToAirOrganicFertiliser.json +31 -0
  49. package/formulas/ipcc2019/no3ToGroundwaterCropResidueDecomposition.json +28 -0
  50. package/formulas/ipcc2019/no3ToGroundwaterExcreta.json +28 -0
  51. package/formulas/ipcc2019/no3ToGroundwaterInorganicFertiliser.json +28 -0
  52. package/formulas/ipcc2019/no3ToGroundwaterOrganicFertiliser.json +28 -0
  53. package/formulas/ipcc2019/nonCo2EmissionsToAirNaturalVegetationBurning.json +13 -0
  54. package/formulas/ipcc2019/noxToAirInorganicFertiliser.json +31 -0
  55. package/formulas/ipcc2019/noxToAirOrganicFertiliser.json +31 -0
  56. package/formulas/ipcc2019/pastureGrass.json +556 -0
  57. package/formulas/pooreNemecek2018/ch4ToAirAquacultureSystems.json +88 -0
  58. package/formulas/pooreNemecek2018/n2OToAirAquacultureSystemsDirect.json +32 -0
  59. package/formulas/pooreNemecek2018/n2ToAirAquacultureSystems.json +32 -0
  60. package/formulas/pooreNemecek2018/nh3ToAirAquacultureSystems.json +40 -0
  61. package/formulas/pooreNemecek2018/no3ToGroundwaterCropResidueDecomposition.json +68 -0
  62. package/formulas/pooreNemecek2018/no3ToGroundwaterExcreta.json +68 -0
  63. package/formulas/pooreNemecek2018/no3ToGroundwaterInorganicFertiliser.json +68 -0
  64. package/formulas/pooreNemecek2018/no3ToGroundwaterOrganicFertiliser.json +68 -0
  65. package/formulas/pooreNemecek2018/noxToAirAquacultureSystems.json +32 -0
  66. package/formulas/schererPfister2015/nErosionSoilFlux.json +34 -0
  67. package/formulas/schererPfister2015/pErosionSoilFlux.json +109 -0
  68. package/formulas/stehfestBouwman2006/n2OToAirCropResidueDecompositionDirect.json +37 -0
  69. package/formulas/stehfestBouwman2006/n2OToAirExcretaDirect.json +37 -0
  70. package/formulas/stehfestBouwman2006/n2OToAirInorganicFertiliserDirect.json +37 -0
  71. package/formulas/stehfestBouwman2006/n2OToAirOrganicFertiliserDirect.json +37 -0
  72. package/formulas/stehfestBouwman2006/noxToAirCropResidueDecomposition.json +36 -0
  73. package/formulas/stehfestBouwman2006/noxToAirExcreta.json +36 -0
  74. package/formulas/stehfestBouwman2006/noxToAirInorganicFertiliser.json +36 -0
  75. package/formulas/stehfestBouwman2006/noxToAirOrganicFertiliser.json +36 -0
  76. package/model-links.json +700 -9
  77. package/package.json +9 -8
@@ -0,0 +1,190 @@
1
+ # Model formulas
2
+
3
+ This folder contains the KaTeX formulas extracted from each model's
4
+ documentation, together with the **bindings** that tie every symbol in a formula
5
+ to a value logged at runtime (the "jlog"). With these you can render a model's
6
+ formula and *substitute* its symbols with the actual values from a given
7
+ execution — so a user can see exactly where a result came from.
8
+
9
+ The files here are generated by `scripts/generate-formulas.js` (run as part of
10
+ `npm run build:models`). Do not edit them by hand — edit the model's `.md`
11
+ documentation instead (see [Authoring bindings](#authoring-bindings)).
12
+
13
+ ## Contents
14
+
15
+ | File | Description |
16
+ | --- | --- |
17
+ | `<model>/<term>.json` | One file per documentation page that contains at least one formula. |
18
+ | `index.json` | Aggregate of every formula, keyed by `docPath`. This is what the package imports. |
19
+
20
+ ## Data shape
21
+
22
+ ```ts
23
+ interface IFormulaBinding {
24
+ symbol: string; // the KaTeX symbol as written, e.g. "E_{CH4}", "GE"
25
+ description?: string; // the "Where:" list description text
26
+ key?: string; // the jlog field this symbol resolves to (absent for constants)
27
+ column?: string; // for a \sum: the column to read per row of a packed table
28
+ }
29
+
30
+ interface IFormula {
31
+ formula: string; // KaTeX source, without the `$$` delimiters
32
+ bindings: IFormulaBinding[];
33
+ }
34
+ ```
35
+
36
+ `key` is special-cased: `"value"` is the **result** (the left-hand side of the
37
+ equation), and any other key is a field to read from the model's jlog entry. A
38
+ binding with no `key` is a display-only constant (e.g. `55.65`).
39
+
40
+ When a symbol sits under a `\sum` and its value comes from a per-input **table**
41
+ (a packed `log_as_table` string), the binding also carries a `column`: `key` is
42
+ the table's log key and `column` is the field to read from each row.
43
+
44
+ ## Getting the formulas for a model
45
+
46
+ The package exposes two helpers (re-exported from the package root):
47
+
48
+ ```ts
49
+ import { getFormulas, getFormulasForLink } from '@hestia-earth/engine-models';
50
+
51
+ // By the same parameters used to look up a model in model-links.json:
52
+ getFormulas({ model: 'ipcc2019', term: 'ch4ToAirEntericFermentation' });
53
+ // => [ { formula: 'E_{CH4} = (GE \\times Y_m) / 55.65', bindings: [...] } ]
54
+
55
+ getFormulas({ model: 'ipcc2019', modelKey: 'pastureGrass' });
56
+ // => [ ...20 formulas... ]
57
+
58
+ // Or, if you already have a model-links entry (an IModel):
59
+ import { findMatchingModel } from '@hestia-earth/engine-models';
60
+ const link = findMatchingModel({ model: 'ipcc2019', term: 'ch4ToAirEntericFermentation' });
61
+ getFormulasForLink(link);
62
+ ```
63
+
64
+ Both always return an **array** (a documentation page may define several
65
+ formulas), and an **empty array** when the model is unknown or has no formulas.
66
+
67
+ ## Rendering & substituting
68
+
69
+ `renderFormula(formula, values)` turns one `IFormula` plus a map of values into
70
+ three KaTeX strings (without the `$$` delimiters):
71
+
72
+ - **symbolic** — the formula as authored (`E_{CH4} = (GE \times Y_m) / 55.65`)
73
+ - **substituted** — symbols replaced by their values (`59.24 = (52340 \times 0.063) / 55.65`)
74
+ - **annotated** — symbols kept, each wrapped in `\htmlData{key=..., value=...}{symbol}`
75
+ so the DOM node carries `data-key` / `data-value` for a tooltip or toggle
76
+
77
+ It only substitutes *declared* symbols (longest-first), so `\times`, subscripts
78
+ and constants are never touched, and a symbol with no value is left symbolic.
79
+
80
+ ```ts
81
+ import { getFormulas, renderFormula } from '@hestia-earth/engine-models';
82
+
83
+ const [formula] = getFormulas({ model: 'ipcc2019', term: 'ch4ToAirEntericFermentation' });
84
+
85
+ // `values` maps each binding key to its value for ONE execution. You supply it,
86
+ // so you decide where each value comes from (see "Where the values come from").
87
+ const values = { value: 59.24, total_feed_in_MJ: 52340, enteric_factor: 0.063 };
88
+
89
+ const { symbolic, substituted, annotated } = renderFormula(formula, values);
90
+ ```
91
+
92
+ ### Where the values come from
93
+
94
+ `renderFormula` is agnostic — it just reads `values[key]` for each binding. The
95
+ values for one execution come from that model's **jlog** entry (the fields logged
96
+ via `debugValues` / `logRequirements`, keyed exactly as in the bindings). The
97
+ result symbol (`key: "value"`) is a special case: an emission's numeric value may
98
+ be logged, or read from the recalculated node it belongs to — supply whichever
99
+ your platform has. A minimal join over a jlog node's `logs[]`:
100
+
101
+ ```ts
102
+ const values = Object.assign({}, ...(jlogNode.logs || []));
103
+ // then set values.value from the node's result if it isn't logged:
104
+ values.value ??= recalculatedEmission?.value;
105
+ ```
106
+
107
+ ### Expanding a `\sum`
108
+
109
+ When a formula sums over inputs (`CO_2 = \sum_i M_{urea,i} \times EF_i`) and its
110
+ summand symbols are bound to table columns, `renderFormula` expands the sum once
111
+ per row — provided `values[<table key>]` holds the packed `log_as_table` string
112
+ (or an array of row objects). Each row's columns fill the summand:
113
+
114
+ ```ts
115
+ const [formula] = getFormulas({ model: 'ipcc2019', term: 'co2ToAirUreaHydrolysis' });
116
+ const { substituted } = renderFormula(formula, {
117
+ value: 24.4,
118
+ urea_values: 'id:urea_value:100_factor:0.2;id:ureaKgN_value:50_factor:0.088'
119
+ });
120
+ // 24.4 = (100 \times 0.2) + (50 \times 0.088)
121
+ ```
122
+
123
+ Without the table string the `\sum` is left symbolic.
124
+
125
+ ### Rendering with KaTeX
126
+
127
+ `\htmlData` is **disabled by default** — opt in with a narrowly-scoped `trust`
128
+ callback:
129
+
130
+ ```ts
131
+ import katex from 'katex';
132
+ import 'katex/dist/katex.min.css';
133
+
134
+ katex.render(substituted, element, {
135
+ displayMode: true,
136
+ trust: (ctx) => ctx.command === '\\htmlData',
137
+ strict: false,
138
+ });
139
+ ```
140
+
141
+ Because every substituted symbol is a real DOM node carrying `data-key` /
142
+ `data-value`, the symbol ↔ value toggle and hover tooltips are pure DOM — no
143
+ re-render required:
144
+
145
+ ```ts
146
+ element.querySelectorAll('[data-key]').forEach((span) => {
147
+ const el = span as HTMLElement;
148
+ el.title = `${el.dataset.key} = ${el.dataset.value}`;
149
+ });
150
+ ```
151
+
152
+ ## Authoring bindings
153
+
154
+ Bindings live in the model's `.md` documentation. Add a backticked `` `[logkey]` ``
155
+ token to each symbol in the "Where:" list that follows a formula:
156
+
157
+ ```markdown
158
+ $$E_{CH4} = (GE \times Y_m) / 55.65$$
159
+
160
+ Where:
161
+
162
+ - $E_{CH4}$ = Methane emissions (in kg $CH_4$) `[value]`
163
+ - $GE$ = Gross Energy intake (in MJ). `[total_feed_in_MJ]`
164
+ - $Y_m$ = Methane conversion factor. `[enteric_factor]`
165
+ - $55.65$ = The energy content of methane. <!-- constant, no binding -->
166
+ ```
167
+
168
+ - Bind the result (left-hand side) to `` `[value]` ``.
169
+ - Bind every other symbol to the jlog field it corresponds to — the `key` passed
170
+ to `debugValues` / `logRequirements` in the model's `.py` (e.g. `enteric_factor`).
171
+ - Leave constants unbound; they render as-is.
172
+
173
+ For a `\sum` over inputs, bind each summand symbol to a **table column** with
174
+ `` `[<table key>:<column>]` `` — the log key of the packed `log_as_table` value
175
+ and the per-row field:
176
+
177
+ ```markdown
178
+ $$CO_2 = \sum_i M_{urea,i} \times EF_i$$
179
+
180
+ Where:
181
+
182
+ - $CO_2$ = carbon dioxide emission from urea hydrolysis (kg) `[value]`
183
+ - $M_{urea,i}$ = mass of each urea fertiliser applied (kg) `[urea_values:value]`
184
+ - $EF_i$ = product-specific CO<sub>2</sub> emission factor `[urea_values:factor]`
185
+ ```
186
+
187
+ `scripts/validate-documentation.js` validates these on every build: it errors if a
188
+ bound symbol is not in the formula or a symbol is bound twice. It warns (without
189
+ failing) when there is no `` `[value]` `` result, several results, or a key is not
190
+ found in the sibling `.py` — a hint that the value is logged via a shared util.
@@ -0,0 +1,30 @@
1
+ {
2
+ "docPath": "hestia_earth/models/deRuijterEtAl2010/nh3ToAirCropResidueDecomposition.md",
3
+ "formulas": [
4
+ {
5
+ "formula": "NH_3 = a \\times N_{AG} \\times \\frac{17}{14}",
6
+ "bindings": [
7
+ {
8
+ "symbol": "N_{AG}",
9
+ "description": "is the total nitrogen in crop residue in kg."
10
+ }
11
+ ]
12
+ },
13
+ {
14
+ "formula": "a = (0.38 \\times N_{AG} \\times \\frac{1000}{AG_{DM}} - 5.44) / 100",
15
+ "bindings": [
16
+ {
17
+ "symbol": "0 \\le a < 17\\%"
18
+ },
19
+ {
20
+ "symbol": "N_{AG}",
21
+ "description": "is the total nitrogen in crop residue in kg."
22
+ },
23
+ {
24
+ "symbol": "AG_{DM}",
25
+ "description": "is the above ground crop residue dry matter in kg, considering the quantity left on field or incorporated only."
26
+ }
27
+ ]
28
+ }
29
+ ]
30
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "docPath": "hestia_earth/models/emepEea2019/co2ToAirFuelCombustion.md",
3
+ "formulas": [
4
+ {
5
+ "formula": "CO_2 = \\sum_i M_{fuel,i} \\times EF_i",
6
+ "bindings": [
7
+ {
8
+ "symbol": "CO_2",
9
+ "description": "total carbon dioxide emission from fuel combustion (kg)",
10
+ "key": "value"
11
+ },
12
+ {
13
+ "symbol": "M_{fuel,i}",
14
+ "description": "mass of each fuel input $i$ (kg)"
15
+ },
16
+ {
17
+ "symbol": "EF_i",
18
+ "description": "CO<sub>2</sub> emission factor for fuel input $i$"
19
+ }
20
+ ]
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "docPath": "hestia_earth/models/emepEea2019/nh3ToAirExcreta.md",
3
+ "formulas": [
4
+ {
5
+ "formula": "NH_3 = TAN \\times EF_{NH_3} \\times \\frac{17}{14}",
6
+ "bindings": [
7
+ {
8
+ "symbol": "NH_3",
9
+ "description": "ammonia emission from excreta (kg NH<sub>3</sub>)",
10
+ "key": "value"
11
+ },
12
+ {
13
+ "symbol": "TAN",
14
+ "description": "total ammoniacal nitrogen in excreta (kg N)"
15
+ },
16
+ {
17
+ "symbol": "EF_{NH_3}",
18
+ "description": "management-specific NH<sub>3</sub> emission factor"
19
+ },
20
+ {
21
+ "symbol": "\\frac{17}{14}",
22
+ "description": "conversion of NH<sub>3</sub>-N to NH<sub>3</sub>"
23
+ }
24
+ ]
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "docPath": "hestia_earth/models/emepEea2019/pm10ToAirAnimalHousing.md",
3
+ "formulas": [
4
+ {
5
+ "formula": "PM = N_{animals} \\times EF_{PM} \\times t_{housing}",
6
+ "bindings": [
7
+ {
8
+ "symbol": "PM",
9
+ "description": "particulate matter (PM<sub>10</sub>) emission from animal housing (kg)",
10
+ "key": "value"
11
+ },
12
+ {
13
+ "symbol": "N_{animals}",
14
+ "description": "average animal population"
15
+ },
16
+ {
17
+ "symbol": "EF_{PM}",
18
+ "description": "animal-type-specific emission factor (from `pm10ToAirEea2019`)"
19
+ },
20
+ {
21
+ "symbol": "t_{housing}",
22
+ "description": "total housing duration (days)",
23
+ "key": "number_of_days_in_animal_housing"
24
+ }
25
+ ]
26
+ }
27
+ ]
28
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "docPath": "hestia_earth/models/emepEea2019/pm25ToAirAnimalHousing.md",
3
+ "formulas": [
4
+ {
5
+ "formula": "PM = N_{animals} \\times EF_{PM} \\times t_{housing}",
6
+ "bindings": [
7
+ {
8
+ "symbol": "PM",
9
+ "description": "particulate matter (PM<sub>2.5</sub>) emission from animal housing (kg)",
10
+ "key": "value"
11
+ },
12
+ {
13
+ "symbol": "N_{animals}",
14
+ "description": "average animal population"
15
+ },
16
+ {
17
+ "symbol": "EF_{PM}",
18
+ "description": "animal-type-specific emission factor (from `pm25ToAirEea2019`)"
19
+ },
20
+ {
21
+ "symbol": "t_{housing}",
22
+ "description": "total housing duration (days)",
23
+ "key": "number_of_days_in_animal_housing"
24
+ }
25
+ ]
26
+ }
27
+ ]
28
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "docPath": "hestia_earth/models/emepEea2019/tspToAirAnimalHousing.md",
3
+ "formulas": [
4
+ {
5
+ "formula": "PM = N_{animals} \\times EF_{PM} \\times t_{housing}",
6
+ "bindings": [
7
+ {
8
+ "symbol": "PM",
9
+ "description": "total suspended particulate (TSP) emission from animal housing (kg)",
10
+ "key": "value"
11
+ },
12
+ {
13
+ "symbol": "N_{animals}",
14
+ "description": "average animal population"
15
+ },
16
+ {
17
+ "symbol": "EF_{PM}",
18
+ "description": "animal-type-specific emission factor (from `tspToAirEea2019`)"
19
+ },
20
+ {
21
+ "symbol": "t_{housing}",
22
+ "description": "total housing duration (days)",
23
+ "key": "number_of_days_in_animal_housing"
24
+ }
25
+ ]
26
+ }
27
+ ]
28
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "docPath": "hestia_earth/models/hestia/feedConversionRatio/feedConversionRatioCarbon.md",
3
+ "formulas": [
4
+ {
5
+ "formula": "FCR_C = \\frac{\\sum C_{feed}}{C_{product}}",
6
+ "bindings": [
7
+ {
8
+ "symbol": "FCR_C",
9
+ "description": "carbon-based feed conversion ratio",
10
+ "key": "value"
11
+ },
12
+ {
13
+ "symbol": "\\sum C_{feed}",
14
+ "description": "total carbon in feed intake"
15
+ },
16
+ {
17
+ "symbol": "C_{product}",
18
+ "description": "carbon in animal product output"
19
+ }
20
+ ]
21
+ }
22
+ ]
23
+ }