fable-pyculator 0.1.0a1__tar.gz
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.
- fable_pyculator-0.1.0a1/LICENSE +22 -0
- fable_pyculator-0.1.0a1/PKG-INFO +267 -0
- fable_pyculator-0.1.0a1/README.md +218 -0
- fable_pyculator-0.1.0a1/pyproject.toml +87 -0
- fable_pyculator-0.1.0a1/setup.cfg +4 -0
- fable_pyculator-0.1.0a1/src/fable_pyculator/__init__.py +92 -0
- fable_pyculator-0.1.0a1/src/fable_pyculator/controls.py +87 -0
- fable_pyculator-0.1.0a1/src/fable_pyculator/discovery.py +618 -0
- fable_pyculator-0.1.0a1/src/fable_pyculator/notebook.py +180 -0
- fable_pyculator-0.1.0a1/src/fable_pyculator/spec.py +387 -0
- fable_pyculator-0.1.0a1/src/fable_pyculator/surface.py +491 -0
- fable_pyculator-0.1.0a1/src/fable_pyculator.egg-info/PKG-INFO +267 -0
- fable_pyculator-0.1.0a1/src/fable_pyculator.egg-info/SOURCES.txt +26 -0
- fable_pyculator-0.1.0a1/src/fable_pyculator.egg-info/dependency_links.txt +1 -0
- fable_pyculator-0.1.0a1/src/fable_pyculator.egg-info/requires.txt +30 -0
- fable_pyculator-0.1.0a1/src/fable_pyculator.egg-info/top_level.txt +1 -0
- fable_pyculator-0.1.0a1/tests/test_constants.py +19 -0
- fable_pyculator-0.1.0a1/tests/test_controls.py +72 -0
- fable_pyculator-0.1.0a1/tests/test_discovery.py +199 -0
- fable_pyculator-0.1.0a1/tests/test_examples.py +41 -0
- fable_pyculator-0.1.0a1/tests/test_fable_workbook_headline_series.py +40 -0
- fable_pyculator-0.1.0a1/tests/test_fable_workbook_output_flavour_tags.py +76 -0
- fable_pyculator-0.1.0a1/tests/test_fable_workbook_scenario_definition_tables.py +98 -0
- fable_pyculator-0.1.0a1/tests/test_fable_workbook_selection_controls.py +93 -0
- fable_pyculator-0.1.0a1/tests/test_notebook.py +221 -0
- fable_pyculator-0.1.0a1/tests/test_scripts.py +21 -0
- fable_pyculator-0.1.0a1/tests/test_spec.py +66 -0
- fable_pyculator-0.1.0a1/tests/test_surface.py +375 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 UBC FRESH Lab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fable-pyculator
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: FABLE Calculator-specific notebook controls for Modelwright-generated Python models.
|
|
5
|
+
Author: UBC FRESH Lab
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/UBC-FRESH/fable-pyculator
|
|
8
|
+
Project-URL: Documentation, https://ubc-fresh.github.io/fable-pyculator/
|
|
9
|
+
Project-URL: Repository, https://github.com/UBC-FRESH/fable-pyculator
|
|
10
|
+
Project-URL: Issues, https://github.com/UBC-FRESH/fable-pyculator/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/UBC-FRESH/fable-pyculator/blob/main/CHANGE_LOG.md
|
|
12
|
+
Keywords: fable,spreadsheet-models,jupyter,modelwright,scenario-analysis
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: modelwright[notebook]>=0.1.0a6
|
|
25
|
+
Requires-Dist: openpyxl>=3.1
|
|
26
|
+
Requires-Dist: pandas>=2
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
30
|
+
Requires-Dist: ruff>=0.8; extra == "dev"
|
|
31
|
+
Requires-Dist: sphinx>=7; extra == "dev"
|
|
32
|
+
Requires-Dist: sphinx-rtd-theme>=2; extra == "dev"
|
|
33
|
+
Requires-Dist: twine>=5; extra == "dev"
|
|
34
|
+
Provides-Extra: docs
|
|
35
|
+
Requires-Dist: sphinx>=7; extra == "docs"
|
|
36
|
+
Requires-Dist: sphinx-rtd-theme>=2; extra == "docs"
|
|
37
|
+
Provides-Extra: notebook
|
|
38
|
+
Requires-Dist: ipykernel>=6; extra == "notebook"
|
|
39
|
+
Requires-Dist: ipywidgets>=8; extra == "notebook"
|
|
40
|
+
Requires-Dist: matplotlib>=3.8; extra == "notebook"
|
|
41
|
+
Provides-Extra: quality
|
|
42
|
+
Requires-Dist: ruff>=0.8; extra == "quality"
|
|
43
|
+
Provides-Extra: release
|
|
44
|
+
Requires-Dist: build>=1.2; extra == "release"
|
|
45
|
+
Requires-Dist: twine>=5; extra == "release"
|
|
46
|
+
Provides-Extra: test
|
|
47
|
+
Requires-Dist: pytest>=8; extra == "test"
|
|
48
|
+
Dynamic: license-file
|
|
49
|
+
|
|
50
|
+
# FABLE Pyculator
|
|
51
|
+
|
|
52
|
+
FABLE Pyculator is a FABLE Calculator-specific notebook layer built on top of
|
|
53
|
+
Modelwright-generated Python models.
|
|
54
|
+
|
|
55
|
+
The goal is to keep Modelwright generic while collecting FABLE-C conventions in one public package:
|
|
56
|
+
|
|
57
|
+
- discover likely FABLE scenario input controls from workbook structure;
|
|
58
|
+
- declare those controls as named scenario parameters;
|
|
59
|
+
- expose a Jupyter-friendly control surface for scenario changes;
|
|
60
|
+
- run a generated Modelwright model with the selected scenario inputs;
|
|
61
|
+
- render standard FABLE outputs as pandas tables and matplotlib figures.
|
|
62
|
+
|
|
63
|
+
This repository does not store original FABLE Calculator workbooks, generated Python clones, or raw
|
|
64
|
+
validation outputs. Keep those under ignored `tmp/` paths.
|
|
65
|
+
|
|
66
|
+
## Development Workflow
|
|
67
|
+
|
|
68
|
+
This project uses the same agent-assisted workflow as Modelwright:
|
|
69
|
+
|
|
70
|
+
- read `AGENTS.md`, `ROADMAP.md`, and `CHANGE_LOG.md` before project-shaping work;
|
|
71
|
+
- keep the current plan in `ROADMAP.md`;
|
|
72
|
+
- record completed deliverables in `CHANGE_LOG.md`;
|
|
73
|
+
- use `planning/` for focused investigations and contracts;
|
|
74
|
+
- keep source workbooks, generated models, extracts, logs, and validation reports under ignored
|
|
75
|
+
`tmp/`;
|
|
76
|
+
- once the public GitHub repo and `gh` access exist, map roadmap phases to GitHub parent issues and
|
|
77
|
+
roadmap tasks to child issues;
|
|
78
|
+
- close every phase through a PR back to `main`, with Sphinx docs rebuilt in CI and deployed to
|
|
79
|
+
GitHub Pages after merge.
|
|
80
|
+
|
|
81
|
+
The local remote is expected to be:
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
https://github.com/UBC-FRESH/fable-pyculator.git
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Install For Development
|
|
88
|
+
|
|
89
|
+
Recommended VSCode/Jupyter setup from the `fable-pyculator` repo root:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
scripts/bootstrap_dev_env.sh
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Then select this interpreter as the VSCode notebook kernel:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
.venv/bin/python
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Manual equivalent:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
python -m venv .venv
|
|
105
|
+
.venv/bin/python -m pip install --upgrade pip
|
|
106
|
+
.venv/bin/python -m pip install -e '.[dev,notebook,docs]'
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Download FABLE Calculators
|
|
110
|
+
|
|
111
|
+
The current Modelwright benchmark metadata points to this public FABLE Calculator Dropbox folder:
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
https://www.dropbox.com/scl/fo/ndgldfnq81v794mm8yebe/ADusMz23xtmYKDXoEkiNtJM?rlkey=d87qhjf5zd0pcowd5pfl5qdu7&st=qijm4tta&e=2&dl=0
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
In this checkout, the three public FABLE-C workbooks are stored under `tmp/private-workbooks/`.
|
|
118
|
+
They are ignored local benchmark artifacts. Verify them with:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
sha256sum -c benchmarks/fable-calculator/checksums.sha256
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The public 2020 FABLE Calculator documentation PDF is tracked under `reference/fable-calculator/`.
|
|
125
|
+
|
|
126
|
+
The core FABLE-C output data surfaces are the consecutive workbook sheets `FOOD`, `PRODUCTION`,
|
|
127
|
+
`TRADE`, `BIODIVERSITY`, `LAND`, `GHG`, and `WATER`.
|
|
128
|
+
|
|
129
|
+
## Early Notebook Shape
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from fable_pyculator import (
|
|
133
|
+
FableCalculatorSpec,
|
|
134
|
+
OutputIndicator,
|
|
135
|
+
ScenarioControlSurface,
|
|
136
|
+
ScenarioParameter,
|
|
137
|
+
discover_output_tables,
|
|
138
|
+
discover_scenario_definition_tables,
|
|
139
|
+
discover_selection_controls,
|
|
140
|
+
output_table_frame,
|
|
141
|
+
run_scenario,
|
|
142
|
+
scenario_definition_table_frame,
|
|
143
|
+
scenario_definition_tables_for_location,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
spec = FableCalculatorSpec(
|
|
147
|
+
parameters=[
|
|
148
|
+
ScenarioParameter(name="ambition", label="Scenario ambition", cell_ref="SCENARIOS selection!D20"),
|
|
149
|
+
],
|
|
150
|
+
outputs=[
|
|
151
|
+
OutputIndicator(name="ghg", label="GHG emissions", cell_ref="SCENARIOS selection!D22", unit="MtCO2e"),
|
|
152
|
+
],
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
controls = ScenarioControlSurface(spec)
|
|
156
|
+
controls
|
|
157
|
+
|
|
158
|
+
result = run_scenario(generated_model, spec, controls.values())
|
|
159
|
+
result.outputs
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
For real FABLE-C workbooks, discover the high-level selection controls, scenario-definition tables,
|
|
163
|
+
and output tables:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
selection_controls = discover_selection_controls("tmp/private-workbooks/2020_Open_FABLECalculator.xlsx")
|
|
167
|
+
definition_tables = discover_scenario_definition_tables("tmp/private-workbooks/2020_Open_FABLECalculator.xlsx")
|
|
168
|
+
output_tables = discover_output_tables("tmp/private-workbooks/2020_Open_FABLECalculator.xlsx")
|
|
169
|
+
spec = FableCalculatorSpec(
|
|
170
|
+
selection_controls=selection_controls,
|
|
171
|
+
scenario_definition_tables=definition_tables,
|
|
172
|
+
output_tables=output_tables,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
scenario_definition_table_frame(spec, "DietTarget")
|
|
176
|
+
scenario_definition_tables_for_location(spec, "S.3")
|
|
177
|
+
|
|
178
|
+
run = run_scenario(generated_model, spec, {"gdp_scen": "SSP1"})
|
|
179
|
+
output_table_frame(run, "ghg_resultsghg")
|
|
180
|
+
output_table_frame(run, "ghg_resultsghg", column_flavour_tags="OUTPUT-8")
|
|
181
|
+
output_table_frame(run, "ghg_resultsghg", column_flavour_tags="DATA")
|
|
182
|
+
output_table_frame(run, "ghg_resultsghg", column_flavour_tags="OUTPUT-*")
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The first 2020 notebook loop helper uses ignored local artifacts by default:
|
|
186
|
+
|
|
187
|
+
```text
|
|
188
|
+
tmp/private-workbooks/2020_Open_FABLECalculator.xlsx
|
|
189
|
+
tmp/generated-models/fable-2020/generated_fable_2020_model.py
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
from fable_pyculator import run_2020_notebook_loop
|
|
194
|
+
|
|
195
|
+
result = run_2020_notebook_loop({"gdp_scen": "SSP1"})
|
|
196
|
+
result.output_tables.keys()
|
|
197
|
+
result.output_tables["ghg_resultsghg"]
|
|
198
|
+
result.headline_frames["ghg_total_co2e"]
|
|
199
|
+
result.headline_figures["ghg_total_co2e"]
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
By default the loop renders every discovered output table and every curated headline frame from the
|
|
203
|
+
single generated-model run. Pass `output_table_names` or `headline_series_names` only when you want a
|
|
204
|
+
smaller rendered subset.
|
|
205
|
+
|
|
206
|
+
Tracked notebook example:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
examples/notebooks/fable-pyculator-2020-loop.ipynb
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
This notebook is intentionally committed after a successful 2020 benchmark run so GitHub can render
|
|
213
|
+
the example tables and figure directly in the browser.
|
|
214
|
+
|
|
215
|
+
In VSCode, point the notebook kernel at the `.venv` created in the `fable-pyculator` repo root.
|
|
216
|
+
The notebook setup cell prints the active environment prefix and warns if the selected kernel does
|
|
217
|
+
not appear to be that repo-local `.venv`.
|
|
218
|
+
|
|
219
|
+
The Sphinx guide expands this into a full workflow under
|
|
220
|
+
`docs/guides/2020-notebook-workflow.rst`, with validation boundaries recorded in
|
|
221
|
+
`docs/guides/validation-scope.rst`.
|
|
222
|
+
|
|
223
|
+
`fable-pyculator` is pre-release. The current alpha line is `0.1.0a1`; alpha releases must not be
|
|
224
|
+
described as stable public API compatibility, full editable scenario-definition widgets, production
|
|
225
|
+
readiness, full generated-model equivalence, or arbitrary country-calculator support.
|
|
226
|
+
|
|
227
|
+
The public API is intentionally small while the FABLE-specific conventions are being discovered from
|
|
228
|
+
real country calculators.
|
|
229
|
+
|
|
230
|
+
## Build Docs
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
.venv/bin/python -m pip install -e '.[dev,notebook,docs]'
|
|
234
|
+
.venv/bin/sphinx-build -b html docs _build/html -W
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The `Docs Pages` GitHub Actions workflow builds Sphinx docs on pull requests to `main` and deploys
|
|
238
|
+
the built HTML to GitHub Pages after merges to `main`.
|
|
239
|
+
|
|
240
|
+
GitHub Pages URL:
|
|
241
|
+
|
|
242
|
+
```text
|
|
243
|
+
https://ubc-fresh.github.io/fable-pyculator/
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
See `docs/guides/release-deployment.rst` for the release and deployment runbook.
|
|
247
|
+
|
|
248
|
+
## Release Checks
|
|
249
|
+
|
|
250
|
+
Build and inspect release artifacts locally:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
scripts/check_release_artifacts.sh
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Release checks write build outputs under ignored `tmp/release-checks/`.
|
|
257
|
+
|
|
258
|
+
## Default Checks
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
.venv/bin/python -m ruff check .
|
|
262
|
+
.venv/bin/python -m pytest
|
|
263
|
+
.venv/bin/sphinx-build -b html docs _build/html -W
|
|
264
|
+
.venv/bin/python scripts/verify_docs_theme.py _build/html
|
|
265
|
+
scripts/check_release_artifacts.sh
|
|
266
|
+
sha256sum -c benchmarks/fable-calculator/checksums.sha256
|
|
267
|
+
```
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# FABLE Pyculator
|
|
2
|
+
|
|
3
|
+
FABLE Pyculator is a FABLE Calculator-specific notebook layer built on top of
|
|
4
|
+
Modelwright-generated Python models.
|
|
5
|
+
|
|
6
|
+
The goal is to keep Modelwright generic while collecting FABLE-C conventions in one public package:
|
|
7
|
+
|
|
8
|
+
- discover likely FABLE scenario input controls from workbook structure;
|
|
9
|
+
- declare those controls as named scenario parameters;
|
|
10
|
+
- expose a Jupyter-friendly control surface for scenario changes;
|
|
11
|
+
- run a generated Modelwright model with the selected scenario inputs;
|
|
12
|
+
- render standard FABLE outputs as pandas tables and matplotlib figures.
|
|
13
|
+
|
|
14
|
+
This repository does not store original FABLE Calculator workbooks, generated Python clones, or raw
|
|
15
|
+
validation outputs. Keep those under ignored `tmp/` paths.
|
|
16
|
+
|
|
17
|
+
## Development Workflow
|
|
18
|
+
|
|
19
|
+
This project uses the same agent-assisted workflow as Modelwright:
|
|
20
|
+
|
|
21
|
+
- read `AGENTS.md`, `ROADMAP.md`, and `CHANGE_LOG.md` before project-shaping work;
|
|
22
|
+
- keep the current plan in `ROADMAP.md`;
|
|
23
|
+
- record completed deliverables in `CHANGE_LOG.md`;
|
|
24
|
+
- use `planning/` for focused investigations and contracts;
|
|
25
|
+
- keep source workbooks, generated models, extracts, logs, and validation reports under ignored
|
|
26
|
+
`tmp/`;
|
|
27
|
+
- once the public GitHub repo and `gh` access exist, map roadmap phases to GitHub parent issues and
|
|
28
|
+
roadmap tasks to child issues;
|
|
29
|
+
- close every phase through a PR back to `main`, with Sphinx docs rebuilt in CI and deployed to
|
|
30
|
+
GitHub Pages after merge.
|
|
31
|
+
|
|
32
|
+
The local remote is expected to be:
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
https://github.com/UBC-FRESH/fable-pyculator.git
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Install For Development
|
|
39
|
+
|
|
40
|
+
Recommended VSCode/Jupyter setup from the `fable-pyculator` repo root:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
scripts/bootstrap_dev_env.sh
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Then select this interpreter as the VSCode notebook kernel:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
.venv/bin/python
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Manual equivalent:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
python -m venv .venv
|
|
56
|
+
.venv/bin/python -m pip install --upgrade pip
|
|
57
|
+
.venv/bin/python -m pip install -e '.[dev,notebook,docs]'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Download FABLE Calculators
|
|
61
|
+
|
|
62
|
+
The current Modelwright benchmark metadata points to this public FABLE Calculator Dropbox folder:
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
https://www.dropbox.com/scl/fo/ndgldfnq81v794mm8yebe/ADusMz23xtmYKDXoEkiNtJM?rlkey=d87qhjf5zd0pcowd5pfl5qdu7&st=qijm4tta&e=2&dl=0
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
In this checkout, the three public FABLE-C workbooks are stored under `tmp/private-workbooks/`.
|
|
69
|
+
They are ignored local benchmark artifacts. Verify them with:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
sha256sum -c benchmarks/fable-calculator/checksums.sha256
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The public 2020 FABLE Calculator documentation PDF is tracked under `reference/fable-calculator/`.
|
|
76
|
+
|
|
77
|
+
The core FABLE-C output data surfaces are the consecutive workbook sheets `FOOD`, `PRODUCTION`,
|
|
78
|
+
`TRADE`, `BIODIVERSITY`, `LAND`, `GHG`, and `WATER`.
|
|
79
|
+
|
|
80
|
+
## Early Notebook Shape
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from fable_pyculator import (
|
|
84
|
+
FableCalculatorSpec,
|
|
85
|
+
OutputIndicator,
|
|
86
|
+
ScenarioControlSurface,
|
|
87
|
+
ScenarioParameter,
|
|
88
|
+
discover_output_tables,
|
|
89
|
+
discover_scenario_definition_tables,
|
|
90
|
+
discover_selection_controls,
|
|
91
|
+
output_table_frame,
|
|
92
|
+
run_scenario,
|
|
93
|
+
scenario_definition_table_frame,
|
|
94
|
+
scenario_definition_tables_for_location,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
spec = FableCalculatorSpec(
|
|
98
|
+
parameters=[
|
|
99
|
+
ScenarioParameter(name="ambition", label="Scenario ambition", cell_ref="SCENARIOS selection!D20"),
|
|
100
|
+
],
|
|
101
|
+
outputs=[
|
|
102
|
+
OutputIndicator(name="ghg", label="GHG emissions", cell_ref="SCENARIOS selection!D22", unit="MtCO2e"),
|
|
103
|
+
],
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
controls = ScenarioControlSurface(spec)
|
|
107
|
+
controls
|
|
108
|
+
|
|
109
|
+
result = run_scenario(generated_model, spec, controls.values())
|
|
110
|
+
result.outputs
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
For real FABLE-C workbooks, discover the high-level selection controls, scenario-definition tables,
|
|
114
|
+
and output tables:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
selection_controls = discover_selection_controls("tmp/private-workbooks/2020_Open_FABLECalculator.xlsx")
|
|
118
|
+
definition_tables = discover_scenario_definition_tables("tmp/private-workbooks/2020_Open_FABLECalculator.xlsx")
|
|
119
|
+
output_tables = discover_output_tables("tmp/private-workbooks/2020_Open_FABLECalculator.xlsx")
|
|
120
|
+
spec = FableCalculatorSpec(
|
|
121
|
+
selection_controls=selection_controls,
|
|
122
|
+
scenario_definition_tables=definition_tables,
|
|
123
|
+
output_tables=output_tables,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
scenario_definition_table_frame(spec, "DietTarget")
|
|
127
|
+
scenario_definition_tables_for_location(spec, "S.3")
|
|
128
|
+
|
|
129
|
+
run = run_scenario(generated_model, spec, {"gdp_scen": "SSP1"})
|
|
130
|
+
output_table_frame(run, "ghg_resultsghg")
|
|
131
|
+
output_table_frame(run, "ghg_resultsghg", column_flavour_tags="OUTPUT-8")
|
|
132
|
+
output_table_frame(run, "ghg_resultsghg", column_flavour_tags="DATA")
|
|
133
|
+
output_table_frame(run, "ghg_resultsghg", column_flavour_tags="OUTPUT-*")
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The first 2020 notebook loop helper uses ignored local artifacts by default:
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
tmp/private-workbooks/2020_Open_FABLECalculator.xlsx
|
|
140
|
+
tmp/generated-models/fable-2020/generated_fable_2020_model.py
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from fable_pyculator import run_2020_notebook_loop
|
|
145
|
+
|
|
146
|
+
result = run_2020_notebook_loop({"gdp_scen": "SSP1"})
|
|
147
|
+
result.output_tables.keys()
|
|
148
|
+
result.output_tables["ghg_resultsghg"]
|
|
149
|
+
result.headline_frames["ghg_total_co2e"]
|
|
150
|
+
result.headline_figures["ghg_total_co2e"]
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
By default the loop renders every discovered output table and every curated headline frame from the
|
|
154
|
+
single generated-model run. Pass `output_table_names` or `headline_series_names` only when you want a
|
|
155
|
+
smaller rendered subset.
|
|
156
|
+
|
|
157
|
+
Tracked notebook example:
|
|
158
|
+
|
|
159
|
+
```text
|
|
160
|
+
examples/notebooks/fable-pyculator-2020-loop.ipynb
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
This notebook is intentionally committed after a successful 2020 benchmark run so GitHub can render
|
|
164
|
+
the example tables and figure directly in the browser.
|
|
165
|
+
|
|
166
|
+
In VSCode, point the notebook kernel at the `.venv` created in the `fable-pyculator` repo root.
|
|
167
|
+
The notebook setup cell prints the active environment prefix and warns if the selected kernel does
|
|
168
|
+
not appear to be that repo-local `.venv`.
|
|
169
|
+
|
|
170
|
+
The Sphinx guide expands this into a full workflow under
|
|
171
|
+
`docs/guides/2020-notebook-workflow.rst`, with validation boundaries recorded in
|
|
172
|
+
`docs/guides/validation-scope.rst`.
|
|
173
|
+
|
|
174
|
+
`fable-pyculator` is pre-release. The current alpha line is `0.1.0a1`; alpha releases must not be
|
|
175
|
+
described as stable public API compatibility, full editable scenario-definition widgets, production
|
|
176
|
+
readiness, full generated-model equivalence, or arbitrary country-calculator support.
|
|
177
|
+
|
|
178
|
+
The public API is intentionally small while the FABLE-specific conventions are being discovered from
|
|
179
|
+
real country calculators.
|
|
180
|
+
|
|
181
|
+
## Build Docs
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
.venv/bin/python -m pip install -e '.[dev,notebook,docs]'
|
|
185
|
+
.venv/bin/sphinx-build -b html docs _build/html -W
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
The `Docs Pages` GitHub Actions workflow builds Sphinx docs on pull requests to `main` and deploys
|
|
189
|
+
the built HTML to GitHub Pages after merges to `main`.
|
|
190
|
+
|
|
191
|
+
GitHub Pages URL:
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
https://ubc-fresh.github.io/fable-pyculator/
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
See `docs/guides/release-deployment.rst` for the release and deployment runbook.
|
|
198
|
+
|
|
199
|
+
## Release Checks
|
|
200
|
+
|
|
201
|
+
Build and inspect release artifacts locally:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
scripts/check_release_artifacts.sh
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Release checks write build outputs under ignored `tmp/release-checks/`.
|
|
208
|
+
|
|
209
|
+
## Default Checks
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
.venv/bin/python -m ruff check .
|
|
213
|
+
.venv/bin/python -m pytest
|
|
214
|
+
.venv/bin/sphinx-build -b html docs _build/html -W
|
|
215
|
+
.venv/bin/python scripts/verify_docs_theme.py _build/html
|
|
216
|
+
scripts/check_release_artifacts.sh
|
|
217
|
+
sha256sum -c benchmarks/fable-calculator/checksums.sha256
|
|
218
|
+
```
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "fable-pyculator"
|
|
7
|
+
version = "0.1.0a1"
|
|
8
|
+
description = "FABLE Calculator-specific notebook controls for Modelwright-generated Python models."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [
|
|
14
|
+
{ name = "UBC FRESH Lab" }
|
|
15
|
+
]
|
|
16
|
+
keywords = [
|
|
17
|
+
"fable",
|
|
18
|
+
"spreadsheet-models",
|
|
19
|
+
"jupyter",
|
|
20
|
+
"modelwright",
|
|
21
|
+
"scenario-analysis"
|
|
22
|
+
]
|
|
23
|
+
classifiers = [
|
|
24
|
+
"Development Status :: 3 - Alpha",
|
|
25
|
+
"Intended Audience :: Science/Research",
|
|
26
|
+
"Programming Language :: Python :: 3",
|
|
27
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
28
|
+
"Programming Language :: Python :: 3.10",
|
|
29
|
+
"Programming Language :: Python :: 3.11",
|
|
30
|
+
"Programming Language :: Python :: 3.12",
|
|
31
|
+
"Topic :: Scientific/Engineering"
|
|
32
|
+
]
|
|
33
|
+
dependencies = [
|
|
34
|
+
"modelwright[notebook]>=0.1.0a6",
|
|
35
|
+
"openpyxl>=3.1",
|
|
36
|
+
"pandas>=2"
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.optional-dependencies]
|
|
40
|
+
dev = [
|
|
41
|
+
"build>=1.2",
|
|
42
|
+
"pytest>=8",
|
|
43
|
+
"ruff>=0.8",
|
|
44
|
+
"sphinx>=7",
|
|
45
|
+
"sphinx-rtd-theme>=2",
|
|
46
|
+
"twine>=5"
|
|
47
|
+
]
|
|
48
|
+
docs = [
|
|
49
|
+
"sphinx>=7",
|
|
50
|
+
"sphinx-rtd-theme>=2"
|
|
51
|
+
]
|
|
52
|
+
notebook = [
|
|
53
|
+
"ipykernel>=6",
|
|
54
|
+
"ipywidgets>=8",
|
|
55
|
+
"matplotlib>=3.8"
|
|
56
|
+
]
|
|
57
|
+
quality = [
|
|
58
|
+
"ruff>=0.8"
|
|
59
|
+
]
|
|
60
|
+
release = [
|
|
61
|
+
"build>=1.2",
|
|
62
|
+
"twine>=5"
|
|
63
|
+
]
|
|
64
|
+
test = [
|
|
65
|
+
"pytest>=8"
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
[project.urls]
|
|
69
|
+
Homepage = "https://github.com/UBC-FRESH/fable-pyculator"
|
|
70
|
+
Documentation = "https://ubc-fresh.github.io/fable-pyculator/"
|
|
71
|
+
Repository = "https://github.com/UBC-FRESH/fable-pyculator"
|
|
72
|
+
Issues = "https://github.com/UBC-FRESH/fable-pyculator/issues"
|
|
73
|
+
Changelog = "https://github.com/UBC-FRESH/fable-pyculator/blob/main/CHANGE_LOG.md"
|
|
74
|
+
|
|
75
|
+
[tool.setuptools.packages.find]
|
|
76
|
+
where = ["src"]
|
|
77
|
+
|
|
78
|
+
[tool.pytest.ini_options]
|
|
79
|
+
testpaths = ["tests"]
|
|
80
|
+
markers = [
|
|
81
|
+
"workbook: tests that require local FABLE workbook artifacts and are skipped unless explicitly enabled"
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
[tool.ruff]
|
|
85
|
+
line-length = 120
|
|
86
|
+
target-version = "py310"
|
|
87
|
+
extend-exclude = ["tmp"]
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""FABLE Calculator-specific notebook helpers for Modelwright-generated models."""
|
|
2
|
+
|
|
3
|
+
from fable_pyculator.discovery import (
|
|
4
|
+
curate_default_headline_series,
|
|
5
|
+
discover_output_tables,
|
|
6
|
+
discover_scenario_parameters,
|
|
7
|
+
discover_scenario_definition_tables,
|
|
8
|
+
discover_selection_controls,
|
|
9
|
+
)
|
|
10
|
+
from fable_pyculator.spec import (
|
|
11
|
+
FABLE_OUTPUT_SURFACE_SHEETS,
|
|
12
|
+
FableCalculatorSpec,
|
|
13
|
+
HeadlinePoint,
|
|
14
|
+
HeadlineSeries,
|
|
15
|
+
OutputIndicator,
|
|
16
|
+
OutputTable,
|
|
17
|
+
ScenarioDefinitionTable,
|
|
18
|
+
ScenarioParameter,
|
|
19
|
+
SelectionControl,
|
|
20
|
+
SelectionOption,
|
|
21
|
+
)
|
|
22
|
+
from fable_pyculator.controls import ScenarioControlSurface
|
|
23
|
+
from fable_pyculator.notebook import (
|
|
24
|
+
DEFAULT_2020_GENERATED_MODEL_PATH,
|
|
25
|
+
DEFAULT_2020_WORKBOOK_PATH,
|
|
26
|
+
DEFAULT_HEADLINE_SERIES,
|
|
27
|
+
DEFAULT_OUTPUT_TABLES,
|
|
28
|
+
NotebookLoopResult,
|
|
29
|
+
build_2020_notebook_spec,
|
|
30
|
+
load_generated_model,
|
|
31
|
+
run_2020_notebook_loop,
|
|
32
|
+
run_notebook_loop,
|
|
33
|
+
)
|
|
34
|
+
from fable_pyculator.surface import (
|
|
35
|
+
ScenarioRun,
|
|
36
|
+
headline_frame,
|
|
37
|
+
headline_frames,
|
|
38
|
+
output_table_frame,
|
|
39
|
+
output_tables,
|
|
40
|
+
outputs_frame,
|
|
41
|
+
plot_headline,
|
|
42
|
+
plot_outputs,
|
|
43
|
+
run_scenario,
|
|
44
|
+
scenario_definition_table_frame,
|
|
45
|
+
scenario_definition_tables,
|
|
46
|
+
scenario_definition_tables_for_location,
|
|
47
|
+
scenario_frame,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
__version__ = "0.1.0a1"
|
|
51
|
+
|
|
52
|
+
__all__ = [
|
|
53
|
+
"FableCalculatorSpec",
|
|
54
|
+
"FABLE_OUTPUT_SURFACE_SHEETS",
|
|
55
|
+
"DEFAULT_2020_GENERATED_MODEL_PATH",
|
|
56
|
+
"DEFAULT_2020_WORKBOOK_PATH",
|
|
57
|
+
"DEFAULT_HEADLINE_SERIES",
|
|
58
|
+
"DEFAULT_OUTPUT_TABLES",
|
|
59
|
+
"HeadlinePoint",
|
|
60
|
+
"HeadlineSeries",
|
|
61
|
+
"NotebookLoopResult",
|
|
62
|
+
"OutputIndicator",
|
|
63
|
+
"OutputTable",
|
|
64
|
+
"ScenarioControlSurface",
|
|
65
|
+
"ScenarioDefinitionTable",
|
|
66
|
+
"ScenarioParameter",
|
|
67
|
+
"ScenarioRun",
|
|
68
|
+
"SelectionControl",
|
|
69
|
+
"SelectionOption",
|
|
70
|
+
"__version__",
|
|
71
|
+
"build_2020_notebook_spec",
|
|
72
|
+
"curate_default_headline_series",
|
|
73
|
+
"discover_output_tables",
|
|
74
|
+
"discover_scenario_definition_tables",
|
|
75
|
+
"discover_scenario_parameters",
|
|
76
|
+
"discover_selection_controls",
|
|
77
|
+
"headline_frame",
|
|
78
|
+
"headline_frames",
|
|
79
|
+
"output_table_frame",
|
|
80
|
+
"output_tables",
|
|
81
|
+
"outputs_frame",
|
|
82
|
+
"plot_headline",
|
|
83
|
+
"plot_outputs",
|
|
84
|
+
"load_generated_model",
|
|
85
|
+
"run_2020_notebook_loop",
|
|
86
|
+
"run_notebook_loop",
|
|
87
|
+
"run_scenario",
|
|
88
|
+
"scenario_definition_table_frame",
|
|
89
|
+
"scenario_definition_tables",
|
|
90
|
+
"scenario_definition_tables_for_location",
|
|
91
|
+
"scenario_frame",
|
|
92
|
+
]
|