Spaces:
Sleeping
Sleeping
[DOC] Readme updated with instructions on adding data and updating libraries
Browse files- .streamlit/config.toml +1 -4
- README.md +399 -218
- app.py +5 -7
- assets/styles.css +1 -20
.streamlit/config.toml
CHANGED
|
@@ -4,7 +4,4 @@ primaryColor = "#298231"
|
|
| 4 |
backgroundColor = "#ffffff"
|
| 5 |
secondaryBackgroundColor = "#eae9d8"
|
| 6 |
textColor = "#000000"
|
| 7 |
-
font = "sans-serif"
|
| 8 |
-
|
| 9 |
-
[server]
|
| 10 |
-
enableStaticServing = true
|
|
|
|
| 4 |
backgroundColor = "#ffffff"
|
| 5 |
secondaryBackgroundColor = "#eae9d8"
|
| 6 |
textColor = "#000000"
|
| 7 |
+
font = "sans-serif"
|
|
|
|
|
|
|
|
|
README.md
CHANGED
|
@@ -15,9 +15,45 @@ A Streamlit app for optimizing carbon removal portfolios across different method
|
|
| 15 |
|
| 16 |
---
|
| 17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
## Data Maintenance Guide
|
| 19 |
|
| 20 |
-
This guide is for Carbon Gap staff who need to update the tool's data
|
| 21 |
|
| 22 |
---
|
| 23 |
|
|
@@ -29,51 +65,82 @@ All the data the tool uses (CDR methods, resources, coefficients) comes from a s
|
|
| 29 |
data/inputs_aggregated.csv
|
| 30 |
```
|
| 31 |
|
| 32 |
-
Every time the app starts, it computes a fingerprint (hash) of the CSV and compares it to the last known value. If they differ
|
| 33 |
|
| 34 |
-
There are two ways to update the data, depending on whether you are working directly on Hugging Face or on a local copy of the project
|
| 35 |
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
### Option 1 — Edit directly on Hugging Face (no local setup needed)
|
| 39 |
|
| 40 |
This is the simplest option for non-coders with admin access to the Hugging Face Space.
|
| 41 |
|
| 42 |
**Steps:**
|
| 43 |
|
| 44 |
-
1. Go to the Hugging Face Space → click the **Files** tab
|
| 45 |
-
2. Open `data/inputs_aggregated.csv` and click **Edit** (pencil icon)
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
|
|
|
|
|
|
| 49 |
- You should see:
|
| 50 |
```
|
| 51 |
-
inputs_aggregated.csv has changed
|
| 52 |
[... update details ...]
|
| 53 |
Data files updated successfully.
|
| 54 |
```
|
| 55 |
-
|
| 56 |
|
| 57 |
> **Note:** with this option, only `inputs_aggregated.csv` needs to be uploaded. The app handles the rest automatically on restart.
|
| 58 |
|
| 59 |
-
|
| 60 |
|
| 61 |
-
|
| 62 |
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
-
**Step
|
| 66 |
|
| 67 |
-
If you
|
| 68 |
-
- Install [GitHub Desktop](https://desktop.github.com) (free, no command line needed)
|
| 69 |
-
- Open GitHub Desktop → **File** → **Clone repository** → enter the repository URL → choose a local folder → click **Clone**
|
| 70 |
|
| 71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
|
| 73 |
Open `data/inputs_aggregated.csv` in Excel or any spreadsheet editor. Make your changes and save.
|
| 74 |
|
| 75 |
-
**Step 3
|
| 76 |
|
|
|
|
|
|
|
|
|
|
| 77 |
- Mac: right-click the project folder → **New Terminal at Folder**
|
| 78 |
- Windows: open the folder, click in the address bar, type `cmd`, press Enter
|
| 79 |
|
|
@@ -83,78 +150,67 @@ source venv/bin/activate # Mac / Linux
|
|
| 83 |
venv\Scripts\activate # Windows
|
| 84 |
```
|
| 85 |
|
| 86 |
-
**Step 4
|
| 87 |
|
| 88 |
```
|
| 89 |
-
|
| 90 |
```
|
| 91 |
|
| 92 |
-
|
| 93 |
|
| 94 |
-
|
| 95 |
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
| 101 |
|
| 102 |
Hugging Face will detect the push and rebuild the Space automatically.
|
| 103 |
|
| 104 |
---
|
| 105 |
|
| 106 |
-
### Quick reference
|
| 107 |
|
| 108 |
| I want to change… | File | Where exactly |
|
| 109 |
|---|---|---|
|
| 110 |
-
| A coefficient value (min / median / max) | `data/inputs_aggregated.csv` | Columns `min`, `median`, `max`
|
| 111 |
-
| The name of a CDR method | `data/inputs_aggregated.csv` | Column `Implementation
|
| 112 |
| Which group a CDR method belongs to | `data/inputs_aggregated.csv` | Column `Method group` |
|
| 113 |
-
| The name of a resource | `data/inputs_aggregated.csv` | Column `Resource`
|
| 114 |
| Which group a resource belongs to | `data/inputs_aggregated.csv` | Column `Resource group` |
|
| 115 |
-
| The unit of a resource group | `data/inputs_aggregated.csv` | Column `Unit`
|
| 116 |
-
| Whether a resource is optional for a method | `data/inputs_aggregated.csv` | Column `Is secondary`
|
| 117 |
-
| The display order of methods or resources | `data/inputs_aggregated.csv` | Row order
|
| 118 |
-
| The app's colours | `
|
| 119 |
-
| The
|
| 120 |
-
| The
|
| 121 |
-
| The
|
| 122 |
-
| UI
|
| 123 |
-
|
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
### Before you start
|
| 130 |
-
|
| 131 |
-
**Open a terminal** in the project folder. On Mac: right-click the folder → "New Terminal at Folder". On Windows: open the folder, then type `cmd` in the address bar.
|
| 132 |
-
|
| 133 |
-
**Activate the Python environment** (only needed once per session):
|
| 134 |
-
|
| 135 |
-
- Mac / Linux: `source venv/bin/activate`
|
| 136 |
-
- Windows: `venv\Scripts\activate`
|
| 137 |
-
|
| 138 |
-
You should now see `(venv)` at the start of your terminal line.
|
| 139 |
-
|
| 140 |
-
---
|
| 141 |
|
| 142 |
### File structure (what each file does)
|
| 143 |
|
| 144 |
| File | What it is | Do you edit it? |
|
| 145 |
|------|-----------|-----------------|
|
| 146 |
-
| `data/inputs_aggregated.csv` | **Main data file**
|
| 147 |
| `data/update.py` | Script that regenerates everything from the CSV | ❌ No |
|
| 148 |
-
| `data/cost_sliders.json` | Auto-generated
|
| 149 |
-
| `data/method_groups.json` | Auto-generated
|
| 150 |
-
| `data/secondary_resources.json` | Auto-generated
|
| 151 |
-
| `data/inputs_template.xlsx` | Auto-generated
|
| 152 |
-
| `data/resource_template.xlsx` | Auto-generated
|
| 153 |
-
| `data/tooltips.xlsx` | Tooltip texts shown on hover in the app | ✅ Yes
|
| 154 |
|
| 155 |
-
> ⚠️ **Never edit the auto-generated files directly**
|
| 156 |
-
|
| 157 |
-
---
|
| 158 |
|
| 159 |
### Understanding `inputs_aggregated.csv`
|
| 160 |
|
|
@@ -174,98 +230,143 @@ Each row represents **one resource used by one CDR method**, with the following
|
|
| 174 |
| `Is secondary` | Whether this resource is optional for this method | `FALSE` |
|
| 175 |
|
| 176 |
> **Primary resources** (`Is secondary = FALSE`) are always active in the model.
|
| 177 |
-
> **Secondary resources** (`Is secondary = TRUE`) are optional
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
|
| 179 |
---
|
| 180 |
|
| 181 |
-
## Case 1
|
| 182 |
|
| 183 |
**When to use:** The literature has been updated and you want to change the min/median/max values for an existing method-resource pair.
|
| 184 |
|
| 185 |
-
**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
|
| 187 |
1. Open `data/inputs_aggregated.csv` in Excel or a text editor.
|
| 188 |
2. Find the row with the correct `Implementation` and `Resource`.
|
| 189 |
3. Edit the `min`, `median`, and/or `max` columns.
|
| 190 |
-
4. Save the file
|
| 191 |
-
5. In the terminal, run:
|
| 192 |
```
|
| 193 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
```
|
| 195 |
|
| 196 |
-
-
|
| 197 |
|
| 198 |
-
|
| 199 |
|
| 200 |
-
**
|
| 201 |
|
| 202 |
-
**
|
|
|
|
|
|
|
| 203 |
|
| 204 |
-
|
| 205 |
-
2. Add a **new row** at the end (or anywhere in the file — order of rows determines display order in the app):
|
| 206 |
-
|
| 207 |
-
| Column | What to enter |
|
| 208 |
-
|--------|--------------|
|
| 209 |
-
| `Implementation` | Exact name of the existing method (copy it from another row to avoid typos) |
|
| 210 |
-
| `Method group` | Same group as the other rows for that method |
|
| 211 |
-
| `Resource` | Name of the resource (must match an existing resource exactly, or see Case 4 to add a new one) |
|
| 212 |
-
| `Resource group` | Same group as the other rows for that resource |
|
| 213 |
-
| `Type` | `Physical` or `Energy` |
|
| 214 |
-
| `Unit` | Must match the unit already used for that resource (e.g., `Mha/MtCO2`) |
|
| 215 |
-
| `min` | Minimum coefficient |
|
| 216 |
-
| `median` | Median coefficient |
|
| 217 |
-
| `max` | Maximum coefficient |
|
| 218 |
-
| `Is secondary` | `TRUE` if optional, `FALSE` if always required |
|
| 219 |
-
|
| 220 |
-
3. Save the file.
|
| 221 |
-
4. Run `python data/update.py`.
|
| 222 |
|
| 223 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
|
| 225 |
-
## Case 3
|
| 226 |
|
| 227 |
**When to use:** A new carbon removal approach needs to be added to the tool.
|
| 228 |
|
| 229 |
-
**
|
| 230 |
|
| 231 |
-
1.
|
| 232 |
-
2. Add **one row per resource**
|
|
|
|
|
|
|
| 233 |
|
| 234 |
-
|
| 235 |
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 240 |
|
| 241 |
-
> ⚠️ **Special case
|
| 242 |
|
| 243 |
---
|
| 244 |
|
| 245 |
-
## Case 3b
|
| 246 |
|
| 247 |
**What is a derived method?**
|
| 248 |
-
Some methods in the tool are not standalone entries in the CSV
|
| 249 |
- `Bio-char` in the CSV → generates 3 variants in the app: `Bio-char - Forest biomass`, `Bio-char - Non-forest biomass`, `Bio-char - Unspecified biomass`
|
| 250 |
- `Enhanced weathering` in the CSV → generates 4 variants: one per mineral type
|
| 251 |
|
| 252 |
-
Each variant is identical to the base method **except** it only keeps the resource relevant to that variant
|
| 253 |
|
| 254 |
**When to use:** You want to add a new variant of an existing method (e.g. a new mineral type for Enhanced weathering, or a new biomass type for Bio-char).
|
| 255 |
|
| 256 |
-
|
| 257 |
|
| 258 |
-
1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
|
| 260 |
2. Open `data/generate_model_data.py`. Find the two structures at the top of the file:
|
| 261 |
|
| 262 |
-
**`REPLACED_BY_DERIVED`**
|
| 263 |
```
|
| 264 |
REPLACED_BY_DERIVED = {"Bio-char", "Enhanced weathering"}
|
| 265 |
```
|
| 266 |
-
If your new base method should disappear
|
| 267 |
|
| 268 |
-
**`DERIVED_FROM`**
|
| 269 |
```
|
| 270 |
DERIVED_FROM = {
|
| 271 |
"Bio-char": ["Bio-char - Forest biomass", ...],
|
|
@@ -273,136 +374,208 @@ Each variant is identical to the base method **except** it only keeps the resour
|
|
| 273 |
...
|
| 274 |
}
|
| 275 |
```
|
| 276 |
-
Add the new variant name to the relevant list
|
| 277 |
|
| 278 |
-
3. Further down in `create_sliders_inputs()`, add the derivation logic for
|
| 279 |
|
| 280 |
-
4. Save
|
| 281 |
```
|
| 282 |
python data/update.py
|
| 283 |
```
|
| 284 |
-
|
| 285 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 286 |
|
| 287 |
---
|
| 288 |
|
| 289 |
-
## Case 4
|
| 290 |
|
| 291 |
-
**When to use:** A resource that doesn't exist yet needs to be
|
| 292 |
|
| 293 |
-
**
|
| 294 |
-
|
| 295 |
-
1. Decide which **Resource group** the new resource belongs to (e.g., `Minerals`, `Energy`, `Land`). If it belongs to an existing group, use the exact same group name. If it needs its own group, invent a new name.
|
| 296 |
|
| 297 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 298 |
|
| 299 |
-
|
| 300 |
|
| 301 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 302 |
|
| 303 |
---
|
| 304 |
|
| 305 |
-
## Case 5
|
| 306 |
|
| 307 |
**When to use:** Your new resource doesn't fit any existing category.
|
| 308 |
|
| 309 |
-
**
|
|
|
|
|
|
|
| 310 |
|
| 311 |
-
|
| 312 |
|
| 313 |
-
|
| 314 |
|
| 315 |
---
|
| 316 |
|
| 317 |
-
## Case 6
|
| 318 |
|
| 319 |
**When to use:** You want to make a resource optional (user can enable/disable it) or make it always required.
|
| 320 |
|
| 321 |
-
**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 322 |
|
| 323 |
1. Open `data/inputs_aggregated.csv`.
|
| 324 |
2. Find the row with the correct `Implementation` and `Resource`.
|
| 325 |
-
3. Change
|
| 326 |
-
4. Save
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 327 |
|
| 328 |
---
|
| 329 |
|
| 330 |
-
## Case 7
|
| 331 |
|
| 332 |
**When to use:** Correcting a spelling mistake or updating nomenclature.
|
| 333 |
|
| 334 |
-
|
| 335 |
|
| 336 |
-
1
|
| 337 |
-
2. Use **Find & Replace** (Ctrl+H / Cmd+H) to replace the old name with the new name everywhere in the file. Make sure to replace it in both the `Implementation` column (for methods) or `Resource` column (for resources), and also in the `Method group` / `Resource group` columns if the group name changed.
|
| 338 |
-
3. Save and run `python data/update.py`.
|
| 339 |
|
| 340 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 341 |
|
| 342 |
---
|
| 343 |
|
| 344 |
-
## Case 8
|
| 345 |
|
| 346 |
**When to use:** You want to add, update, or remove the short description that appears when a user hovers over a resource or method name in the app.
|
| 347 |
|
| 348 |
-
**
|
| 349 |
|
| 350 |
-
1
|
| 351 |
-
2. Go to the relevant sheet:
|
| 352 |
-
- **Resources** — for the hover text on resource names (Tab 1 "Resource Inputs")
|
| 353 |
-
- **Methods** — for the hover text on method names (Tab 2 "Method Constraints")
|
| 354 |
-
3. Find the row with the name you want to edit. All resource and method names are already listed — you only need to fill in or change the `Tooltip` column.
|
| 355 |
-
4. To **add** a tooltip: type the text in the `Tooltip` cell for that row.
|
| 356 |
-
5. To **remove** a tooltip: leave the `Tooltip` cell empty.
|
| 357 |
-
6. Save the file.
|
| 358 |
-
7. Restart the app (no need to run `update.py`).
|
| 359 |
|
| 360 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 361 |
|
| 362 |
---
|
| 363 |
|
| 364 |
-
## Case 10
|
| 365 |
|
| 366 |
-
**When to use:** You want a method or resource group to appear earlier or later in the app.
|
| 367 |
|
| 368 |
-
**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 369 |
|
| 370 |
1. Open `data/inputs_aggregated.csv`.
|
| 371 |
-
2. Move the relevant rows up or down.
|
| 372 |
-
3. Save
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 373 |
|
| 374 |
---
|
| 375 |
|
| 376 |
-
## After any change
|
| 377 |
|
| 378 |
**Option 1 (Hugging Face direct):**
|
| 379 |
- [ ] Edited and committed `inputs_aggregated.csv` on Hugging Face
|
| 380 |
-
- [ ] Checked the Space logs
|
| 381 |
- [ ] Verified the change appears correctly in the app
|
| 382 |
|
| 383 |
**Option 2 (local):**
|
| 384 |
- [ ] Saved `inputs_aggregated.csv`
|
| 385 |
-
- [ ]
|
|
|
|
| 386 |
- [ ] Committed all modified files (CSV, JSON files, templates) and pushed
|
| 387 |
-
- [ ] Verified the change appears correctly in the app after the Space rebuilt
|
| 388 |
-
|
| 389 |
-
---
|
| 390 |
-
|
| 391 |
-
## Common mistakes
|
| 392 |
-
|
| 393 |
-
| Mistake | What happens | Fix |
|
| 394 |
-
|---------|-------------|-----|
|
| 395 |
-
| Typo in `Method group` or `Resource group` | A new accidental group is created in the app | Fix the typo and re-run `update.py` |
|
| 396 |
-
| Wrong unit (e.g., `MWh/MtCO2` instead of `Mha/MtCO2`) | The resource appears in the wrong group or breaks the unit display | Correct the `Unit` column |
|
| 397 |
-
| Edited a JSON file directly | Changes are overwritten next time `update.py` runs | Always edit the CSV, never the JSON |
|
| 398 |
-
| Forgot to run `update.py` | The app still shows the old data | Run `python data/update.py` |
|
| 399 |
-
| `min` value equals `max` value | The model automatically halves the `min` to create a range | Intentional for fixed-value resources like Geologic storage — leave as is |
|
| 400 |
|
| 401 |
---
|
| 402 |
|
| 403 |
## Library Maintenance Guide
|
| 404 |
|
| 405 |
-
This section explains how to keep the tool's software dependencies up to date
|
| 406 |
|
| 407 |
---
|
| 408 |
|
|
@@ -410,7 +583,7 @@ This section explains how to keep the tool's software dependencies up to date
|
|
| 410 |
|
| 411 |
The tool is built on top of external software packages ("libraries") that handle things like displaying the interface, reading Excel files, or running the optimization. These libraries are listed in `requirements.txt` with their exact version numbers (e.g., `streamlit==1.45.1`).
|
| 412 |
|
| 413 |
-
Libraries sometimes release updates
|
| 414 |
|
| 415 |
---
|
| 416 |
|
|
@@ -420,15 +593,15 @@ These are the libraries that matter most for this tool:
|
|
| 420 |
|
| 421 |
| Library | Role | Risk if updated |
|
| 422 |
|---------|------|----------------|
|
| 423 |
-
| **streamlit** | Powers the entire web interface (tabs, sliders, buttons, charts)
|
| 424 |
-
| **streamlit-option-menu** | The navigation sidebar menu | 🟡 Medium
|
| 425 |
-
| **pandas** | Reads and processes CSV and Excel files | 🟡 Medium
|
| 426 |
-
| **numpy** | Numerical operations (arrays, math) | 🟡 Medium
|
| 427 |
-
| **scipy** | Runs the LP optimization (`linprog`) | 🟡 Medium
|
| 428 |
-
| **plotly** | All charts and interactive graphs | 🟡 Medium
|
| 429 |
-
| **openpyxl** | Reads and writes Excel files (.xlsx) | 🟢 Low
|
| 430 |
| **pillow** | Image handling (indirect use) | 🟢 Low |
|
| 431 |
-
| **requests / urllib3 / certifi** | Network and security | 🟢 Low
|
| 432 |
|
| 433 |
---
|
| 434 |
|
|
@@ -462,13 +635,14 @@ openpyxl ──────────────► pillow
|
|
| 462 |
### When to update
|
| 463 |
|
| 464 |
#### ✅ Update immediately
|
| 465 |
-
- **
|
|
|
|
| 466 |
- Check https://pypi.org/project/[library-name] or subscribe to GitHub security alerts.
|
| 467 |
|
| 468 |
#### ✅ Update when needed
|
| 469 |
-
- **Streamlit**
|
| 470 |
-
- **pandas / numpy / scipy**
|
| 471 |
-
- **openpyxl**
|
| 472 |
|
| 473 |
#### ❌ Do NOT update just because a newer version exists
|
| 474 |
- "Latest is always better" is not true for production tools. An update that works fine in isolation can break interactions between libraries.
|
|
@@ -476,17 +650,29 @@ openpyxl ──────────────► pillow
|
|
| 476 |
|
| 477 |
---
|
| 478 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 479 |
### How to safely update a library
|
| 480 |
|
| 481 |
**Never update all libraries at once.** Update one at a time, test the tool after each one.
|
| 482 |
|
| 483 |
-
**Step 1
|
| 484 |
|
| 485 |
```
|
| 486 |
cp requirements.txt requirements.txt.backup
|
| 487 |
```
|
| 488 |
|
| 489 |
-
**Step 2
|
| 490 |
|
| 491 |
Before applying anything, check whether the update would cause conflicts:
|
| 492 |
```
|
|
@@ -494,7 +680,7 @@ pip install --upgrade streamlit --dry-run
|
|
| 494 |
```
|
| 495 |
If pip reports conflicts, investigate before proceeding.
|
| 496 |
|
| 497 |
-
**Step 3
|
| 498 |
|
| 499 |
```
|
| 500 |
pip install --upgrade streamlit
|
|
@@ -505,20 +691,21 @@ Or to a specific version:
|
|
| 505 |
pip install streamlit==1.58.0
|
| 506 |
```
|
| 507 |
|
| 508 |
-
**Step 4
|
| 509 |
|
| 510 |
```
|
| 511 |
pip check
|
| 512 |
```
|
| 513 |
-
This confirms that all installed packages are mutually compatible. If it reports any conflict, do not proceed to the next step
|
| 514 |
|
| 515 |
-
**Step 5
|
| 516 |
|
| 517 |
```
|
| 518 |
pip freeze > requirements.txt
|
| 519 |
```
|
|
|
|
| 520 |
|
| 521 |
-
**Step 6
|
| 522 |
|
| 523 |
- Start the app: `streamlit run app.py`
|
| 524 |
- Go through every tab
|
|
@@ -526,7 +713,7 @@ pip freeze > requirements.txt
|
|
| 526 |
- Run an optimization
|
| 527 |
- Check that charts display correctly
|
| 528 |
|
| 529 |
-
**Step 7
|
| 530 |
|
| 531 |
Restore the backup:
|
| 532 |
```
|
|
@@ -534,6 +721,14 @@ pip install -r requirements.txt.backup
|
|
| 534 |
cp requirements.txt.backup requirements.txt
|
| 535 |
```
|
| 536 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 537 |
---
|
| 538 |
|
| 539 |
### How to install all libraries on a new machine
|
|
@@ -547,18 +742,6 @@ pip install -r requirements.txt
|
|
| 547 |
|
| 548 |
---
|
| 549 |
|
| 550 |
-
### Checking for outdated libraries
|
| 551 |
-
|
| 552 |
-
To see which installed libraries have newer versions available:
|
| 553 |
-
|
| 554 |
-
```
|
| 555 |
-
pip list --outdated
|
| 556 |
-
```
|
| 557 |
-
|
| 558 |
-
This shows a list with current and latest versions. Use this to **identify** what could be updated — but don't update everything at once.
|
| 559 |
-
|
| 560 |
-
---
|
| 561 |
-
|
| 562 |
### Checking for known security vulnerabilities
|
| 563 |
|
| 564 |
Install the security scanner:
|
|
@@ -573,15 +756,15 @@ pip-audit
|
|
| 573 |
|
| 574 |
This will flag any library with a known security issue and suggest a fix. These should be addressed promptly.
|
| 575 |
|
| 576 |
-
> **Recommended frequency:** run `pip-audit` at least once a year, even if the tool appears stable. Security vulnerabilities are discovered independently of whether the library has changed
|
| 577 |
|
| 578 |
---
|
| 579 |
|
| 580 |
### Using an AI assistant to handle updates
|
| 581 |
|
| 582 |
-
Library updates sometimes require code changes alongside the pip update
|
| 583 |
|
| 584 |
-
An AI coding assistant such as **Claude Code**
|
| 585 |
|
| 586 |
- Run `pip-audit` or `pip list --outdated` and paste the output into Claude Code
|
| 587 |
- Describe the update you want to make (e.g., "update pandas and fix any deprecation warnings")
|
|
@@ -602,6 +785,4 @@ This is especially useful when:
|
|
| 602 |
Security fix needed? ──► Update immediately (requests, urllib3, certifi, pillow)
|
| 603 |
Something is broken? ──► Update only the relevant library, test thoroughly
|
| 604 |
Nothing is broken? ──► Do not update
|
| 605 |
-
```
|
| 606 |
-
|
| 607 |
-
---
|
|
|
|
| 15 |
|
| 16 |
---
|
| 17 |
|
| 18 |
+
## Table of contents
|
| 19 |
+
|
| 20 |
+
- [Data Maintenance Guide](#data-maintenance-guide)
|
| 21 |
+
- [How it works](#how-it-works-overview)
|
| 22 |
+
- [Option 1: Hugging Face](#option-1-edit-directly-on-hugging-face-no-local-setup-needed)
|
| 23 |
+
- [Option 2: Local](#option-2-work-locally)
|
| 24 |
+
- [Quick reference](#quick-reference-where-is-each-parameter)
|
| 25 |
+
- [File structure](#file-structure-what-each-file-does)
|
| 26 |
+
- [Understanding inputs_aggregated.csv](#understanding-inputs_aggregatedcsv)
|
| 27 |
+
- [Maintenance cases](#maintenance-cases)
|
| 28 |
+
- [Before you start](#before-you-start)
|
| 29 |
+
- [Case 1 - Modify existing coefficient values](#case-1--modify-existing-coefficient-values)
|
| 30 |
+
- [Case 2 - Add an existing resource to an existing method](#case-2--add-an-existing-resource-to-an-existing-method)
|
| 31 |
+
- [Case 3 - Add a new CDR method](#case-3--add-a-new-cdr-method)
|
| 32 |
+
- [(OPTIONAL) Case 3b - Add a derived CDR method](#optional-case-3b--add-a-derived-cdr-method-variant-of-an-existing-method)
|
| 33 |
+
- [Case 4 - Add a new resource](#case-4--add-a-new-resource)
|
| 34 |
+
- [Case 5 - Add a new resource group](#case-5--add-a-new-resource-group-new-category)
|
| 35 |
+
- [Case 6 - Change whether a resource is optional](#case-6--change-whether-a-resource-is-optional-secondary-for-a-method)
|
| 36 |
+
- [Case 7 - Rename a method or resource](#case-7--rename-a-method-or-resource)
|
| 37 |
+
- [Case 8 - Edit tooltip texts](#case-8--edit-tooltip-texts-hover-descriptions)
|
| 38 |
+
- [Case 10 - Change the display order](#case-10--change-the-display-order-of-methods-or-resources)
|
| 39 |
+
- [After any change - checklist](#after-any-change--checklist)
|
| 40 |
+
- [Library Maintenance Guide](#library-maintenance-guide)
|
| 41 |
+
- [What is a library?](#what-is-a-library-dependency)
|
| 42 |
+
- [The key libraries](#the-key-libraries-and-what-they-do)
|
| 43 |
+
- [Dependency chain](#dependency-chain-what-depends-on-what)
|
| 44 |
+
- [When to update](#when-to-update)
|
| 45 |
+
- [How to safely update](#how-to-safely-update-a-library)
|
| 46 |
+
- [Install on a new machine](#how-to-install-all-libraries-on-a-new-machine)
|
| 47 |
+
- [Check for outdated libraries](#checking-for-outdated-libraries)
|
| 48 |
+
- [Check for vulnerabilities](#checking-for-known-security-vulnerabilities)
|
| 49 |
+
- [Using AI to handle updates](#using-an-ai-assistant-to-handle-updates)
|
| 50 |
+
- [Summary: update strategy](#summary-update-strategy)
|
| 51 |
+
|
| 52 |
+
---
|
| 53 |
+
|
| 54 |
## Data Maintenance Guide
|
| 55 |
|
| 56 |
+
This guide is for Carbon Gap staff who need to update the tool's data: **no coding experience required** for most tasks.
|
| 57 |
|
| 58 |
---
|
| 59 |
|
|
|
|
| 65 |
data/inputs_aggregated.csv
|
| 66 |
```
|
| 67 |
|
| 68 |
+
Every time the app starts, it computes a fingerprint (hash) of the CSV and compares it to the last known value. If they differ, meaning the CSV has been modified, it automatically regenerates all the data files used by the application before loading. You do not need to run anything manually.
|
| 69 |
|
| 70 |
+
There are two ways to update the data, depending on whether you are working directly on Hugging Face or on a local copy of the project:
|
| 71 |
|
| 72 |
+
### Option 1: Edit directly on Hugging Face (no local setup needed)
|
|
|
|
|
|
|
| 73 |
|
| 74 |
This is the simplest option for non-coders with admin access to the Hugging Face Space.
|
| 75 |
|
| 76 |
**Steps:**
|
| 77 |
|
| 78 |
+
1. Go to the Hugging Face **Space** (Carbon Dioxide Removal Toolkit) → click the **Files** tab
|
| 79 |
+
2. Open `data/inputs_aggregated.csv` and click **Edit** (pencil icon)
|
| 80 |
+
*OR*
|
| 81 |
+
Upload a new version of the file: click **Delete** `data/inputs_aggregated.csv`, then go to **data** folder → click **+ Contribute** → Upload Files
|
| 82 |
+
4. Commit the change directly on Hugging Face (checkbox *Commit directly to the main branch*): the Space will restart automatically
|
| 83 |
+
5. **Check the logs** to confirm the update ran:
|
| 84 |
+
- In the Space, click **⋮ **Logs** (The button at the very top, next to *Running*)
|
| 85 |
- You should see:
|
| 86 |
```
|
| 87 |
+
inputs_aggregated.csv has changed - running data/update.py ...
|
| 88 |
[... update details ...]
|
| 89 |
Data files updated successfully.
|
| 90 |
```
|
| 91 |
+
6. If the logs show this message, the app is running with the new data. If not, something went wrong: try option 2 or contact a developer. You may also not have waited long enough or, conversely, you may have waited too long before checking the logs: check whether the app has successfully applied your changes.
|
| 92 |
|
| 93 |
> **Note:** with this option, only `inputs_aggregated.csv` needs to be uploaded. The app handles the rest automatically on restart.
|
| 94 |
|
| 95 |
+
### Option 2: Work locally
|
| 96 |
|
| 97 |
+
Use this option when making bigger changes where you want to preview the result before publishing.
|
| 98 |
|
| 99 |
+
**Step 1: Get the project on your machine**
|
| 100 |
+
|
| 101 |
+
If you do not already have git installed:
|
| 102 |
+
- Mac: install it via https://git-scm.com/download/mac
|
| 103 |
+
- Windows: install it via https://git-scm.com/download/win
|
| 104 |
+
-
|
| 105 |
+
Then in a terminal, navigate to the folder where you want to put the project and run:
|
| 106 |
+
```
|
| 107 |
+
git clone <repository URL>
|
| 108 |
+
```
|
| 109 |
+
Example:
|
| 110 |
+
```
|
| 111 |
+
git clone https://huggingface.co/spaces/CarbonGap/CRRA_Optimization_Tool
|
| 112 |
+
```
|
| 113 |
|
| 114 |
+
**Step 1b: Set up the Python environment (first time only)**
|
| 115 |
|
| 116 |
+
If you just cloned the repo, the venv/ folder doesn't exist yet. Create it by running in the terminal:
|
|
|
|
|
|
|
| 117 |
|
| 118 |
+
```
|
| 119 |
+
python -m venv venv
|
| 120 |
+
```
|
| 121 |
+
|
| 122 |
+
Then activate it and install the dependencies:
|
| 123 |
+
```
|
| 124 |
+
source venv/bin/activate # Mac / Linux
|
| 125 |
+
venv\Scripts\activate # Windows
|
| 126 |
+
```
|
| 127 |
+
|
| 128 |
+
You should now see `(venv)` at the start of your terminal line.
|
| 129 |
+
|
| 130 |
+
```
|
| 131 |
+
pip install -r requirements.txt
|
| 132 |
+
```
|
| 133 |
+
You only need to do this once per machine. After that, just activate the environment (Step 3) each time.
|
| 134 |
+
|
| 135 |
+
**Step 2: Edit the CSV**
|
| 136 |
|
| 137 |
Open `data/inputs_aggregated.csv` in Excel or any spreadsheet editor. Make your changes and save.
|
| 138 |
|
| 139 |
+
**Step 3: Open a terminal in the project folder**
|
| 140 |
|
| 141 |
+
You can use any of the following:
|
| 142 |
+
|
| 143 |
+
- In your code editor (VS Code, PyCharm, etc.): open the integrated terminal, it's usually already pointing to the project folder
|
| 144 |
- Mac: right-click the project folder → **New Terminal at Folder**
|
| 145 |
- Windows: open the folder, click in the address bar, type `cmd`, press Enter
|
| 146 |
|
|
|
|
| 150 |
venv\Scripts\activate # Windows
|
| 151 |
```
|
| 152 |
|
| 153 |
+
**Step 4: Start the app to verify**
|
| 154 |
|
| 155 |
```
|
| 156 |
+
streamlit run app.py
|
| 157 |
```
|
| 158 |
|
| 159 |
+
The app detects that the CSV has changed and automatically runs the update script before loading. Check the terminal output: it should say `Data files updated successfully.` Then browse the app to confirm the change looks correct.
|
| 160 |
|
| 161 |
+
> If the auto-update doesn't seem to work (no message in the terminal), you can trigger it manually as a fallback: `python data/update.py`
|
| 162 |
|
| 163 |
+
**Step 5: Commit and push**
|
| 164 |
+
|
| 165 |
+
In the terminal:
|
| 166 |
+
```
|
| 167 |
+
git add -A -- ':!venv/'
|
| 168 |
+
git commit -m "Your description here (e.g. Update coefficients for Afforestation)"
|
| 169 |
+
git push
|
| 170 |
+
```
|
| 171 |
|
| 172 |
Hugging Face will detect the push and rebuild the Space automatically.
|
| 173 |
|
| 174 |
---
|
| 175 |
|
| 176 |
+
### Quick reference: where is each parameter?
|
| 177 |
|
| 178 |
| I want to change… | File | Where exactly |
|
| 179 |
|---|---|---|
|
| 180 |
+
| A coefficient value (min / median / max) | `data/inputs_aggregated.csv` | Columns `min`, `median`, `max`: find the row by `Implementation` + `Resource` |
|
| 181 |
+
| The name of a CDR method | `data/inputs_aggregated.csv` | Column `Implementation |
|
| 182 |
| Which group a CDR method belongs to | `data/inputs_aggregated.csv` | Column `Method group` |
|
| 183 |
+
| The name of a resource | `data/inputs_aggregated.csv` | Column `Resource` |
|
| 184 |
| Which group a resource belongs to | `data/inputs_aggregated.csv` | Column `Resource group` |
|
| 185 |
+
| The unit of a resource group | `data/inputs_aggregated.csv` | Column `Unit`: must be consistent across all rows for that group |
|
| 186 |
+
| Whether a resource is optional for a method | `data/inputs_aggregated.csv` | Column `Is secondary`: `TRUE` = optional, `FALSE` = always active |
|
| 187 |
+
| The display order of methods or resources | `data/inputs_aggregated.csv` | Row order: in the app, groups are displayed in the order their first row is encountered in the CSV; within a group, methods or resources are displayed in the order their rows appear. Move rows up/down to reorder |
|
| 188 |
+
| The app's UI colours (background, buttons, links) | `.streamlit/config.toml` | `primaryColor`, `backgroundColor`, `secondaryBackgroundColor`, `textColor` |
|
| 189 |
+
| The chart colours (Plotly graphs) | `config/config.py` | `CRRA_COLORS` dictionary |
|
| 190 |
+
| The app's UI font | `.streamlit/config.toml` | `font` - accepted values: `"sans-serif"`, `"serif"`, `"monospace"` |
|
| 191 |
+
| The chart font (Plotly graphs) | `config/config.py` | `CRRA_FONT` variable |
|
| 192 |
+
| The app's UI colours and font (fine-tuned overrides) | `assets/styles.css` | `:root` block at the top of the file - change the hex values next to each variable name |
|
| 193 |
+
| The tooltip text on a method name | `data/tooltips.xlsx` | Sheet **Methods**: column `Tooltip` |
|
| 194 |
+
| The tooltip text on a resource name | `data/tooltips.xlsx` | Sheet **Resources**: column `Tooltip` |
|
| 195 |
+
| UI spacing, font sizes, button styles | `assets/styles.css` | Standard CSS: search for the element name |
|
| 196 |
+
| Python library versions | `requirements.txt` | One line per library: see Library Maintenance Guide below |
|
| 197 |
+
|
| 198 |
+
> After any change to `inputs_aggregated.csv`, start the app - it detects the change and updates automatically. After changes to `config/config.py`, `assets/styles.css`, or `data/tooltips.xlsx`, simply restart the app.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
|
| 200 |
### File structure (what each file does)
|
| 201 |
|
| 202 |
| File | What it is | Do you edit it? |
|
| 203 |
|------|-----------|-----------------|
|
| 204 |
+
| `data/inputs_aggregated.csv` | **Main data file**: all methods, resources and coefficients | ✅ Yes |
|
| 205 |
| `data/update.py` | Script that regenerates everything from the CSV | ❌ No |
|
| 206 |
+
| `data/cost_sliders.json` | Auto-generated. Coefficients used by the app | ❌ No (auto) |
|
| 207 |
+
| `data/method_groups.json` | Auto-generated. CDR method categories | ❌ No (auto) |
|
| 208 |
+
| `data/secondary_resources.json` | Auto-generated. optional resource assignments | ❌ No (auto) |
|
| 209 |
+
| `data/inputs_template.xlsx` | Auto-generated. Excel template for users | ❌ No (auto) |
|
| 210 |
+
| `data/resource_template.xlsx` | Auto-generated. Excel template for users | ❌ No (auto) |
|
| 211 |
+
| `data/tooltips.xlsx` | Tooltip texts shown on hover in the app | ✅ Yes |
|
| 212 |
|
| 213 |
+
> ⚠️ **Never edit the auto-generated files directly**: your changes will be overwritten the next time `update.py` is run.
|
|
|
|
|
|
|
| 214 |
|
| 215 |
### Understanding `inputs_aggregated.csv`
|
| 216 |
|
|
|
|
| 230 |
| `Is secondary` | Whether this resource is optional for this method | `FALSE` |
|
| 231 |
|
| 232 |
> **Primary resources** (`Is secondary = FALSE`) are always active in the model.
|
| 233 |
+
> **Secondary resources** (`Is secondary = TRUE`) are optional: users can toggle them on in the app.
|
| 234 |
+
|
| 235 |
+
---
|
| 236 |
+
|
| 237 |
+
## Maintenance cases
|
| 238 |
+
|
| 239 |
+
### Before you start
|
| 240 |
+
|
| 241 |
+
Each case below covers two workflows:
|
| 242 |
+
- **Option 1 - Hugging Face:** edit directly in the browser, no local setup needed.
|
| 243 |
+
- **Option 2 - Local:** make changes on your machine, then push to Hugging Face.
|
| 244 |
+
|
| 245 |
+
For Option 2, make sure the project is cloned and the Python environment is set up (see [Option 2](#option-2-work-locally) at the top of this guide). Before running any command in the terminal, activate the environment:
|
| 246 |
+
|
| 247 |
+
```
|
| 248 |
+
source venv/bin/activate # Mac / Linux
|
| 249 |
+
venv\Scripts\activate # Windows
|
| 250 |
+
```
|
| 251 |
+
|
| 252 |
+
You should see `(venv)` at the start of your terminal line.
|
| 253 |
+
|
| 254 |
+
> **For all Option 2 cases below:** after editing the CSV, start the app (`streamlit run app.py`) to verify - it detects the change and runs the update automatically. If the auto-update doesn't trigger (no message in the terminal), run `python data/update.py` manually as a fallback.
|
| 255 |
|
| 256 |
---
|
| 257 |
|
| 258 |
+
### Case 1 - Modify existing coefficient values
|
| 259 |
|
| 260 |
**When to use:** The literature has been updated and you want to change the min/median/max values for an existing method-resource pair.
|
| 261 |
|
| 262 |
+
**Option 1 - On Hugging Face**
|
| 263 |
+
|
| 264 |
+
1. In the Space, click the **Files** tab.
|
| 265 |
+
2. Open `data/inputs_aggregated.csv` → click the **pencil icon** to edit inline.
|
| 266 |
+
3. Find the row with the correct `Implementation` and `Resource`. Edit the `min`, `median`, and/or `max` columns.
|
| 267 |
+
4. Scroll down → **Commit directly to main branch** → **Commit changes to main**.
|
| 268 |
+
5. The Space restarts. Click **Logs** to confirm: `Data files updated successfully.`
|
| 269 |
+
|
| 270 |
+
**Option 2 - Locally**
|
| 271 |
|
| 272 |
1. Open `data/inputs_aggregated.csv` in Excel or a text editor.
|
| 273 |
2. Find the row with the correct `Implementation` and `Resource`.
|
| 274 |
3. Edit the `min`, `median`, and/or `max` columns.
|
| 275 |
+
4. Save the file, then start the app to verify:
|
|
|
|
| 276 |
```
|
| 277 |
+
streamlit run app.py
|
| 278 |
+
```
|
| 279 |
+
5. Commit and push:
|
| 280 |
+
```
|
| 281 |
+
git add -A -- ':!venv/'
|
| 282 |
+
git commit -m "Update coefficients for [method name] and [resource name]"
|
| 283 |
+
git push
|
| 284 |
```
|
| 285 |
|
| 286 |
+
### Case 2 - Add an existing resource to an existing method
|
| 287 |
|
| 288 |
+
**When to use:** A CDR method should now also use a resource that is already tracked for other methods (e.g., water is already listed for other methods, and you want to add it to Afforestation too). If the resource doesn't exist at all yet, use Case 4 first.
|
| 289 |
|
| 290 |
+
**Option 1 - On Hugging Face**
|
| 291 |
|
| 292 |
+
1. In the Space, click **Files** → open `data/inputs_aggregated.csv` → click the pencil icon.
|
| 293 |
+
2. Add a new row, making sure to include all the expected columns (see [Understanding inputs_aggregated.csv](#understanding-inputs_aggregatedcsv)).
|
| 294 |
+
3. Commit directly to main → Space restarts. Check Logs for `Data files updated successfully.`
|
| 295 |
|
| 296 |
+
**Option 2 - Locally**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 297 |
|
| 298 |
+
1. Open `data/inputs_aggregated.csv` and add a new row (see [Understanding inputs_aggregated.csv](#understanding-inputs_aggregatedcsv)).
|
| 299 |
+
2. Save the file, then start the app to verify:
|
| 300 |
+
```
|
| 301 |
+
streamlit run app.py
|
| 302 |
+
```
|
| 303 |
+
3. Commit and push:
|
| 304 |
+
```
|
| 305 |
+
git add -A -- ':!venv/'
|
| 306 |
+
git commit -m "Add [resource name] to [method name]"
|
| 307 |
+
git push
|
| 308 |
+
```
|
| 309 |
|
| 310 |
+
### Case 3 - Add a new CDR method
|
| 311 |
|
| 312 |
**When to use:** A new carbon removal approach needs to be added to the tool.
|
| 313 |
|
| 314 |
+
**Option 1 - On Hugging Face**
|
| 315 |
|
| 316 |
+
1. In the Space, click **Files** → open `data/inputs_aggregated.csv` → click the pencil icon.
|
| 317 |
+
2. Add **one row per resource** the new method uses (see [Understanding inputs_aggregated.csv](#understanding-inputs_aggregatedcsv)). Use an existing `Method group` or create a new one.
|
| 318 |
+
3. Place the rows where you want the method to appear: display order follows row order in the CSV.
|
| 319 |
+
4. Commit directly to main → Space restarts. Check Logs for `Data files updated successfully.`
|
| 320 |
|
| 321 |
+
**Option 2 - Locally**
|
| 322 |
|
| 323 |
+
1. Open `data/inputs_aggregated.csv`.
|
| 324 |
+
2. Add one row per resource used by the new method. Fill in all columns (see [Understanding inputs_aggregated.csv](#understanding-inputs_aggregatedcsv)).
|
| 325 |
+
3. Save the file, then start the app to verify:
|
| 326 |
+
```
|
| 327 |
+
streamlit run app.py
|
| 328 |
+
```
|
| 329 |
+
4. Commit and push:
|
| 330 |
+
```
|
| 331 |
+
git add -A -- ':!venv/'
|
| 332 |
+
git commit -m "Add new CDR method: [method name]"
|
| 333 |
+
git push
|
| 334 |
+
```
|
| 335 |
|
| 336 |
+
> ⚠️ **Special case - derived methods:** see Case 3b below.
|
| 337 |
|
| 338 |
---
|
| 339 |
|
| 340 |
+
### (OPTIONAL) Case 3b - Add a derived CDR method (variant of an existing method)
|
| 341 |
|
| 342 |
**What is a derived method?**
|
| 343 |
+
Some methods in the tool are not standalone entries in the CSV: they are automatically generated as **variants** of a base method. For example:
|
| 344 |
- `Bio-char` in the CSV → generates 3 variants in the app: `Bio-char - Forest biomass`, `Bio-char - Non-forest biomass`, `Bio-char - Unspecified biomass`
|
| 345 |
- `Enhanced weathering` in the CSV → generates 4 variants: one per mineral type
|
| 346 |
|
| 347 |
+
Each variant is identical to the base method **except** it only keeps the resource relevant to that variant.
|
| 348 |
|
| 349 |
**When to use:** You want to add a new variant of an existing method (e.g. a new mineral type for Enhanced weathering, or a new biomass type for Bio-char).
|
| 350 |
|
| 351 |
+
> ⚠️ This case requires editing Python code. If you are not comfortable with this, contact the developer - provide the name of the new variant and which resource it should keep, and they can add the 5–10 lines needed.
|
| 352 |
|
| 353 |
+
**Option 1 - On Hugging Face (developers only)**
|
| 354 |
+
|
| 355 |
+
Hugging Face allows editing Python files inline via the pencil icon. Follow the same steps as Option 2 but make all edits directly in the browser. Not recommended for non-coders.
|
| 356 |
+
|
| 357 |
+
**Option 2 - Locally**
|
| 358 |
+
|
| 359 |
+
1. Open `data/inputs_aggregated.csv` and make sure the base method has a row for the new resource.
|
| 360 |
|
| 361 |
2. Open `data/generate_model_data.py`. Find the two structures at the top of the file:
|
| 362 |
|
| 363 |
+
**`REPLACED_BY_DERIVED`**: lists base methods fully replaced by their variants (the base name disappears from the app):
|
| 364 |
```
|
| 365 |
REPLACED_BY_DERIVED = {"Bio-char", "Enhanced weathering"}
|
| 366 |
```
|
| 367 |
+
If your new base method should disappear once variants exist, add its name here.
|
| 368 |
|
| 369 |
+
**`DERIVED_FROM`**: maps each base method to its list of variant names (in display order):
|
| 370 |
```
|
| 371 |
DERIVED_FROM = {
|
| 372 |
"Bio-char": ["Bio-char - Forest biomass", ...],
|
|
|
|
| 374 |
...
|
| 375 |
}
|
| 376 |
```
|
| 377 |
+
Add the new variant name to the relevant list.
|
| 378 |
|
| 379 |
+
3. Further down in `create_sliders_inputs()`, add the derivation logic for the new variant: copy the pattern used for Bio-char or Enhanced weathering: copy the base method's coefficients, then remove the resources that don't apply to this variant.
|
| 380 |
|
| 381 |
+
4. Save both files and run:
|
| 382 |
```
|
| 383 |
python data/update.py
|
| 384 |
```
|
| 385 |
+
5. Commit and push:
|
| 386 |
+
```
|
| 387 |
+
git add -A -- ':!venv/'
|
| 388 |
+
git commit -m "Add derived method: [variant name]"
|
| 389 |
+
git push
|
| 390 |
+
```
|
| 391 |
|
| 392 |
---
|
| 393 |
|
| 394 |
+
### Case 4 - Add a new resource
|
| 395 |
|
| 396 |
+
**When to use:** A resource that doesn't exist yet needs to be used (e.g., a new type of mineral or energy).
|
| 397 |
|
| 398 |
+
**Option 1 - On Hugging Face**
|
|
|
|
|
|
|
| 399 |
|
| 400 |
+
1. Decide which **Resource group** the new resource belongs to. If it belongs to an existing group, use the exact same name. If it needs its own group, see Case 5.
|
| 401 |
+
2. In the Space, click **Files** → open `data/inputs_aggregated.csv` → pencil icon.
|
| 402 |
+
3. Add one row per method that uses this resource (see column descriptions in Case 2).
|
| 403 |
+
4. **Check the unit:** all resources in a group must share the same unit (e.g., all `Land` resources use `Mha/MtCO2`). If the unit differs, create a new group (Case 5).
|
| 404 |
+
5. Commit directly to main → Space restarts. Check Logs.
|
| 405 |
|
| 406 |
+
**Option 2 - Locally**
|
| 407 |
|
| 408 |
+
1. Decide which Resource group the new resource belongs to.
|
| 409 |
+
2. Open `data/inputs_aggregated.csv` and add one row per method that uses this resource.
|
| 410 |
+
3. Verify the unit is consistent with the rest of the group.
|
| 411 |
+
4. Save, then start the app to verify:
|
| 412 |
+
```
|
| 413 |
+
streamlit run app.py
|
| 414 |
+
```
|
| 415 |
+
5. Commit and push:
|
| 416 |
+
```
|
| 417 |
+
git add -A -- ':!venv/'
|
| 418 |
+
git commit -m "Add new resource: [resource name]"
|
| 419 |
+
git push
|
| 420 |
+
```
|
| 421 |
|
| 422 |
---
|
| 423 |
|
| 424 |
+
### Case 5 - Add a new resource group (new category)
|
| 425 |
|
| 426 |
**When to use:** Your new resource doesn't fit any existing category.
|
| 427 |
|
| 428 |
+
**Option 1 - On Hugging Face**
|
| 429 |
+
|
| 430 |
+
Same steps as Case 4, but write a **new group name** (never used before) in the `Resource group` column. The app will create a new section for it automatically. Place the rows where you want the group to appear: it appears at the position of its first row in the CSV.
|
| 431 |
|
| 432 |
+
**Option 2 - Locally**
|
| 433 |
|
| 434 |
+
Same steps as Case 4, but write a **new group name** in the `Resource group` column. The new group appears in the app at the position of its first row in the CSV.
|
| 435 |
|
| 436 |
---
|
| 437 |
|
| 438 |
+
### Case 6 - Change whether a resource is optional (secondary) for a method
|
| 439 |
|
| 440 |
**When to use:** You want to make a resource optional (user can enable/disable it) or make it always required.
|
| 441 |
|
| 442 |
+
**Option 1 - On Hugging Face**
|
| 443 |
+
|
| 444 |
+
1. In the Space, click **Files** → open `data/inputs_aggregated.csv` → pencil icon.
|
| 445 |
+
2. Find the row with the correct `Implementation` and `Resource`.
|
| 446 |
+
3. Change `Is secondary` to `TRUE` (optional) or `FALSE` (always active).
|
| 447 |
+
4. Commit directly to main → Space restarts. Check Logs.
|
| 448 |
+
|
| 449 |
+
**Option 2 - Locally**
|
| 450 |
|
| 451 |
1. Open `data/inputs_aggregated.csv`.
|
| 452 |
2. Find the row with the correct `Implementation` and `Resource`.
|
| 453 |
+
3. Change `Is secondary` to `TRUE` (optional) or `FALSE` (always active).
|
| 454 |
+
4. Save, then start the app to verify:
|
| 455 |
+
```
|
| 456 |
+
streamlit run app.py
|
| 457 |
+
```
|
| 458 |
+
5. Commit and push:
|
| 459 |
+
```
|
| 460 |
+
git add -A -- ':!venv/'
|
| 461 |
+
git commit -m "Update secondary status for [resource] in [method]"
|
| 462 |
+
git push
|
| 463 |
+
```
|
| 464 |
|
| 465 |
---
|
| 466 |
|
| 467 |
+
### Case 7 - Rename a method or resource
|
| 468 |
|
| 469 |
**When to use:** Correcting a spelling mistake or updating nomenclature.
|
| 470 |
|
| 471 |
+
> ⚠️ If users have saved scenario files (`.xlsx` or `.zip`) that reference the old name, those files will no longer load correctly after the rename.
|
| 472 |
|
| 473 |
+
**Option 1 - On Hugging Face**
|
|
|
|
|
|
|
| 474 |
|
| 475 |
+
Editing inline is not recommended for a rename because Find & Replace is not available in the browser editor. Instead:
|
| 476 |
+
1. Download `data/inputs_aggregated.csv` from the Files tab.
|
| 477 |
+
2. Open it in Excel. Use **Find & Replace** (Ctrl+H / Cmd+H) to replace the old name with the new name in the `Implementation` / `Resource` columns and, if the group name changed, in `Method group` / `Resource group`.
|
| 478 |
+
3. Also download `data/tooltips.xlsx`, update the name in the `Method` or `Resource` column of the relevant sheet, and save.
|
| 479 |
+
4. Upload both files via **Files** → `data/` folder → **+ Contribute** → **Upload Files** → Commit.
|
| 480 |
+
5. Space restarts → check Logs.
|
| 481 |
+
|
| 482 |
+
**Option 2 - Locally**
|
| 483 |
+
|
| 484 |
+
1. Open `data/inputs_aggregated.csv`. Use **Find & Replace** (Ctrl+H / Cmd+H) to replace the old name everywhere in the file.
|
| 485 |
+
2. Open `data/tooltips.xlsx` and update the name in the `Method` or `Resource` column of the relevant sheet. Save.
|
| 486 |
+
3. Start the app to verify:
|
| 487 |
+
```
|
| 488 |
+
streamlit run app.py
|
| 489 |
+
```
|
| 490 |
+
4. Commit and push:
|
| 491 |
+
```
|
| 492 |
+
git add -A -- ':!venv/'
|
| 493 |
+
git commit -m "Rename [old name] to [new name]"
|
| 494 |
+
git push
|
| 495 |
+
```
|
| 496 |
|
| 497 |
---
|
| 498 |
|
| 499 |
+
### Case 8 - Edit tooltip texts (hover descriptions)
|
| 500 |
|
| 501 |
**When to use:** You want to add, update, or remove the short description that appears when a user hovers over a resource or method name in the app.
|
| 502 |
|
| 503 |
+
> ⚠️ The name in column `Resource` or `Method` must match **exactly** the name used in `inputs_aggregated.csv` (same spelling, same capitalisation). If you rename a method or resource in the CSV, remember to update the name in `tooltips.xlsx` too.
|
| 504 |
|
| 505 |
+
**Option 1 - On Hugging Face**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
|
| 507 |
+
The `.xlsx` file cannot be edited inline on Hugging Face. Instead:
|
| 508 |
+
1. In the Files tab, open the `data/` folder → download `tooltips.xlsx`.
|
| 509 |
+
2. Open it in Excel. Go to the relevant sheet (**Resources** or **Methods**).
|
| 510 |
+
3. Find the row with the name you want to edit. Fill in or change the `Tooltip` column. Leave it empty to remove a tooltip.
|
| 511 |
+
4. Save the file.
|
| 512 |
+
5. Back in the Files tab, go to `data/` → **+ Contribute** → **Upload Files**.
|
| 513 |
+
6. Upload your edited `tooltips.xlsx` → Commit directly to main.
|
| 514 |
+
7. The Space restarts. **No update script runs for tooltips** - the file is read directly by the app on each restart.
|
| 515 |
+
|
| 516 |
+
**Option 2 - Locally**
|
| 517 |
+
|
| 518 |
+
1. Open `data/tooltips.xlsx` in Excel.
|
| 519 |
+
2. Go to the relevant sheet (**Resources** or **Methods**).
|
| 520 |
+
3. Find the row with the name you want to edit. Fill in or change the `Tooltip` column. Leave it empty to remove a tooltip.
|
| 521 |
+
4. Save the file.
|
| 522 |
+
5. Restart the app (`Ctrl+C` then `streamlit run app.py`). **No need to run `update.py`.**
|
| 523 |
+
6. Commit and push:
|
| 524 |
+
```
|
| 525 |
+
git add data/tooltips.xlsx
|
| 526 |
+
git commit -m "Update tooltip texts"
|
| 527 |
+
git push
|
| 528 |
+
```
|
| 529 |
|
| 530 |
---
|
| 531 |
|
| 532 |
+
### Case 10 - Change the display order of methods or resources
|
| 533 |
|
| 534 |
+
**When to use:** You want a method or resource group to appear earlier or later in the app (Resource inputs, Method constraints tabs...).
|
| 535 |
|
| 536 |
+
**Option 1 - On Hugging Face**
|
| 537 |
+
|
| 538 |
+
Moving rows is easier in Excel than in a browser editor:
|
| 539 |
+
1. Download `data/inputs_aggregated.csv` from the Files tab.
|
| 540 |
+
2. Open it in Excel. Move the relevant rows up or down - the app reads the CSV from top to bottom.
|
| 541 |
+
3. Upload the updated file via **Files** → `data/` → **+ Contribute** → **Upload Files** → Commit.
|
| 542 |
+
4. Space restarts → check Logs for `Data files updated successfully.`
|
| 543 |
+
|
| 544 |
+
**Option 2 - Locally**
|
| 545 |
|
| 546 |
1. Open `data/inputs_aggregated.csv`.
|
| 547 |
+
2. Move the relevant rows up or down.
|
| 548 |
+
3. Save, then start the app to verify:
|
| 549 |
+
```
|
| 550 |
+
streamlit run app.py
|
| 551 |
+
```
|
| 552 |
+
4. Commit and push:
|
| 553 |
+
```
|
| 554 |
+
git add -A -- ':!venv/'
|
| 555 |
+
git commit -m "Reorder [methods/resources]"
|
| 556 |
+
git push
|
| 557 |
+
```
|
| 558 |
|
| 559 |
---
|
| 560 |
|
| 561 |
+
### After any change - checklist
|
| 562 |
|
| 563 |
**Option 1 (Hugging Face direct):**
|
| 564 |
- [ ] Edited and committed `inputs_aggregated.csv` on Hugging Face
|
| 565 |
+
- [ ] Checked the Space logs: confirmed `Data files updated successfully.`
|
| 566 |
- [ ] Verified the change appears correctly in the app
|
| 567 |
|
| 568 |
**Option 2 (local):**
|
| 569 |
- [ ] Saved `inputs_aggregated.csv`
|
| 570 |
+
- [ ] Started the app locally (`streamlit run app.py`): confirmed `Data files updated successfully.` in the terminal
|
| 571 |
+
- [ ] Verified the change appears correctly in the app
|
| 572 |
- [ ] Committed all modified files (CSV, JSON files, templates) and pushed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 573 |
|
| 574 |
---
|
| 575 |
|
| 576 |
## Library Maintenance Guide
|
| 577 |
|
| 578 |
+
This section explains how to keep the tool's software dependencies up to date, safely and without breaking anything.
|
| 579 |
|
| 580 |
---
|
| 581 |
|
|
|
|
| 583 |
|
| 584 |
The tool is built on top of external software packages ("libraries") that handle things like displaying the interface, reading Excel files, or running the optimization. These libraries are listed in `requirements.txt` with their exact version numbers (e.g., `streamlit==1.45.1`).
|
| 585 |
|
| 586 |
+
Libraries sometimes release updates - fixing bugs, patching security holes, or adding new features. The risk is that an update can also change how a library behaves and break the tool.
|
| 587 |
|
| 588 |
---
|
| 589 |
|
|
|
|
| 593 |
|
| 594 |
| Library | Role | Risk if updated |
|
| 595 |
|---------|------|----------------|
|
| 596 |
+
| **streamlit** | Powers the entire web interface (tabs, sliders, buttons, charts) - currently 1.58.0 | 🔴 High - UI layout and widget behavior can change |
|
| 597 |
+
| **streamlit-option-menu** | The navigation sidebar menu | 🟡 Medium - must stay compatible with streamlit version |
|
| 598 |
+
| **pandas** | Reads and processes CSV and Excel files | 🟡 Medium - occasional API changes |
|
| 599 |
+
| **numpy** | Numerical operations (arrays, math) | 🟡 Medium - used by scipy and pandas |
|
| 600 |
+
| **scipy** | Runs the LP optimization (`linprog`) | 🟡 Medium - optimization results could change |
|
| 601 |
+
| **plotly** | All charts and interactive graphs | 🟡 Medium - chart API evolves |
|
| 602 |
+
| **openpyxl** | Reads and writes Excel files (.xlsx) | 🟢 Low - stable API |
|
| 603 |
| **pillow** | Image handling (indirect use) | 🟢 Low |
|
| 604 |
+
| **requests / urllib3 / certifi** | Network and security | 🟢 Low - update freely for security patches |
|
| 605 |
|
| 606 |
---
|
| 607 |
|
|
|
|
| 635 |
### When to update
|
| 636 |
|
| 637 |
#### ✅ Update immediately
|
| 638 |
+
- **`pip-audit` flags a vulnerability** - run `pip-audit` regularly (see [Check for vulnerabilities](#checking-for-known-security-vulnerabilities)); any flagged library should be patched without delay.
|
| 639 |
+
- **Security vulnerabilities** in `requests`, `urllib3`, `certifi`, or `pillow` - these are reported publicly and should be patched fast even before `pip-audit` catches them.
|
| 640 |
- Check https://pypi.org/project/[library-name] or subscribe to GitHub security alerts.
|
| 641 |
|
| 642 |
#### ✅ Update when needed
|
| 643 |
+
- **Streamlit** - when a new feature in the app requires it, or when a critical bug in the current version is causing problems.
|
| 644 |
+
- **pandas / numpy / scipy** - when a bug in the current version is causing incorrect data processing or optimization results.
|
| 645 |
+
- **openpyxl** - when Excel import/export breaks with newer `.xlsx` files.
|
| 646 |
|
| 647 |
#### ❌ Do NOT update just because a newer version exists
|
| 648 |
- "Latest is always better" is not true for production tools. An update that works fine in isolation can break interactions between libraries.
|
|
|
|
| 650 |
|
| 651 |
---
|
| 652 |
|
| 653 |
+
### Checking for outdated libraries
|
| 654 |
+
|
| 655 |
+
To see which installed libraries have newer versions available:
|
| 656 |
+
|
| 657 |
+
```
|
| 658 |
+
pip list --outdated
|
| 659 |
+
```
|
| 660 |
+
|
| 661 |
+
This shows a list with current and latest versions. Use this to **identify** what could be updated but don't update everything at once.
|
| 662 |
+
|
| 663 |
+
---
|
| 664 |
+
|
| 665 |
### How to safely update a library
|
| 666 |
|
| 667 |
**Never update all libraries at once.** Update one at a time, test the tool after each one.
|
| 668 |
|
| 669 |
+
**Step 1 - Back up the current working state**
|
| 670 |
|
| 671 |
```
|
| 672 |
cp requirements.txt requirements.txt.backup
|
| 673 |
```
|
| 674 |
|
| 675 |
+
**Step 2 - Simulate first (dry run)**
|
| 676 |
|
| 677 |
Before applying anything, check whether the update would cause conflicts:
|
| 678 |
```
|
|
|
|
| 680 |
```
|
| 681 |
If pip reports conflicts, investigate before proceeding.
|
| 682 |
|
| 683 |
+
**Step 3 - Update the library**
|
| 684 |
|
| 685 |
```
|
| 686 |
pip install --upgrade streamlit
|
|
|
|
| 691 |
pip install streamlit==1.58.0
|
| 692 |
```
|
| 693 |
|
| 694 |
+
**Step 4 - Verify no dependencies are broken**
|
| 695 |
|
| 696 |
```
|
| 697 |
pip check
|
| 698 |
```
|
| 699 |
+
This confirms that all installed packages are mutually compatible. If it reports any conflict, do not proceed to the next step - restore the backup instead (see Step 6).
|
| 700 |
|
| 701 |
+
**Step 5 - Freeze the new versions to requirements.txt**
|
| 702 |
|
| 703 |
```
|
| 704 |
pip freeze > requirements.txt
|
| 705 |
```
|
| 706 |
+
`pip freeze` lists every library currently installed in the environment with its exact version number, and `> requirements.txt` writes that list into the file. This ensures that anyone who installs from `requirements.txt` later, including Hugging Face when the Space rebuilds, gets exactly the same versions you just tested.
|
| 707 |
|
| 708 |
+
**Step 6 - Test the tool**
|
| 709 |
|
| 710 |
- Start the app: `streamlit run app.py`
|
| 711 |
- Go through every tab
|
|
|
|
| 713 |
- Run an optimization
|
| 714 |
- Check that charts display correctly
|
| 715 |
|
| 716 |
+
**Step 7 - If something breaks**
|
| 717 |
|
| 718 |
Restore the backup:
|
| 719 |
```
|
|
|
|
| 721 |
cp requirements.txt.backup requirements.txt
|
| 722 |
```
|
| 723 |
|
| 724 |
+
**Step 8 - If everything works**
|
| 725 |
+
|
| 726 |
+
Delete the backup file, it's no longer needed:
|
| 727 |
+
```
|
| 728 |
+
rm requirements.txt.backup
|
| 729 |
+
```
|
| 730 |
+
Then commit the updated `requirements.txt` and push.
|
| 731 |
+
|
| 732 |
---
|
| 733 |
|
| 734 |
### How to install all libraries on a new machine
|
|
|
|
| 742 |
|
| 743 |
---
|
| 744 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 745 |
### Checking for known security vulnerabilities
|
| 746 |
|
| 747 |
Install the security scanner:
|
|
|
|
| 756 |
|
| 757 |
This will flag any library with a known security issue and suggest a fix. These should be addressed promptly.
|
| 758 |
|
| 759 |
+
> **Recommended frequency:** run `pip-audit` at least once a year, even if the tool appears stable. Security vulnerabilities are discovered independently of whether the library has changed - a version that was safe last year may be flagged today.
|
| 760 |
|
| 761 |
---
|
| 762 |
|
| 763 |
### Using an AI assistant to handle updates
|
| 764 |
|
| 765 |
+
Library updates sometimes require code changes alongside the pip update - for example, a deprecated function that was renamed, or a new argument that became required. Doing this manually requires reading changelogs, finding every affected line, and testing the result.
|
| 766 |
|
| 767 |
+
An AI coding assistant such as **Claude Code** can handle this end-to-end:
|
| 768 |
|
| 769 |
- Run `pip-audit` or `pip list --outdated` and paste the output into Claude Code
|
| 770 |
- Describe the update you want to make (e.g., "update pandas and fix any deprecation warnings")
|
|
|
|
| 785 |
Security fix needed? ──► Update immediately (requests, urllib3, certifi, pillow)
|
| 786 |
Something is broken? ──► Update only the relevant library, test thoroughly
|
| 787 |
Nothing is broken? ──► Do not update
|
| 788 |
+
```
|
|
|
|
|
|
app.py
CHANGED
|
@@ -3,9 +3,13 @@ import os
|
|
| 3 |
import sys
|
| 4 |
import subprocess
|
| 5 |
import pathlib
|
| 6 |
-
|
| 7 |
import streamlit as st
|
| 8 |
from streamlit_option_menu import option_menu
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
# ── Auto-update: regenerate JSON files if inputs_aggregated.csv has changed ───
|
| 11 |
# Uses a hash file to detect changes — works both locally and on Hugging Face.
|
|
@@ -36,12 +40,6 @@ if os.path.exists(csv):
|
|
| 36 |
file.write(current_hash)
|
| 37 |
print("Data files updated successfully.")
|
| 38 |
|
| 39 |
-
from tabs import (tab0_welcome, tab1_inputs, tab2_constraints,
|
| 40 |
-
tab3_coefficients, tab4_optimization, tab5_sensitivity,
|
| 41 |
-
tab6_scenarios)
|
| 42 |
-
from utils.data_utils import load_slider_data, strip_unit_suffix
|
| 43 |
-
from config.config import method_order, secondary_resources
|
| 44 |
-
|
| 45 |
st.set_page_config("Carbon Portfolio Optimizer", layout="wide")
|
| 46 |
|
| 47 |
def load_css(file_path):
|
|
|
|
| 3 |
import sys
|
| 4 |
import subprocess
|
| 5 |
import pathlib
|
|
|
|
| 6 |
import streamlit as st
|
| 7 |
from streamlit_option_menu import option_menu
|
| 8 |
+
from tabs import (tab0_welcome, tab1_inputs, tab2_constraints,
|
| 9 |
+
tab3_coefficients, tab4_optimization, tab5_sensitivity,
|
| 10 |
+
tab6_scenarios)
|
| 11 |
+
from utils.data_utils import load_slider_data, strip_unit_suffix
|
| 12 |
+
from config.config import method_order, secondary_resources
|
| 13 |
|
| 14 |
# ── Auto-update: regenerate JSON files if inputs_aggregated.csv has changed ───
|
| 15 |
# Uses a hash file to detect changes — works both locally and on Hugging Face.
|
|
|
|
| 40 |
file.write(current_hash)
|
| 41 |
print("Data files updated successfully.")
|
| 42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
st.set_page_config("Carbon Portfolio Optimizer", layout="wide")
|
| 44 |
|
| 45 |
def load_css(file_path):
|
assets/styles.css
CHANGED
|
@@ -6,16 +6,6 @@
|
|
| 6 |
Font : Segoe UI, sans-serif
|
| 7 |
═══════════════════════════════════════════════════════════ */
|
| 8 |
|
| 9 |
-
/* ── 0. Font face ──────────────────────────────────────────── */
|
| 10 |
-
/* @font-face {
|
| 11 |
-
font-family: 'Segoe UI';
|
| 12 |
-
src: url(/app/static/fonts/segoe-ui-400.woff2) format('woff2'),
|
| 13 |
-
url(/app/static/fonts/segoe-ui-400.woff) format('woff');
|
| 14 |
-
font-weight: 400;
|
| 15 |
-
font-style: normal;
|
| 16 |
-
font-display: swap;
|
| 17 |
-
} */
|
| 18 |
-
|
| 19 |
/* ── 1. Variables ──────────────────────────────────────────── */
|
| 20 |
:root {
|
| 21 |
--off-white: #eae9d8;
|
|
@@ -53,20 +43,11 @@ input, textarea, select,
|
|
| 53 |
background: var(--off-white) !important;
|
| 54 |
}
|
| 55 |
|
|
|
|
| 56 |
section[data-testid="stSidebar"] {
|
| 57 |
width: 350px;
|
| 58 |
}
|
| 59 |
|
| 60 |
-
div[data-testid="stSidebarContent"] {
|
| 61 |
-
position: fixed;
|
| 62 |
-
top: 0;
|
| 63 |
-
left: 0;
|
| 64 |
-
width: inherit;
|
| 65 |
-
height: 100vh;
|
| 66 |
-
overflow-y: auto;
|
| 67 |
-
z-index: 100;
|
| 68 |
-
}
|
| 69 |
-
|
| 70 |
/* ── 4. Markdown headings (st.markdown "### …") ────────────── */
|
| 71 |
.stMarkdown h1 {
|
| 72 |
font-weight: 700;
|
|
|
|
| 6 |
Font : Segoe UI, sans-serif
|
| 7 |
═══════════════════════════════════════════════════════════ */
|
| 8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
/* ── 1. Variables ──────────────────────────────────────────── */
|
| 10 |
:root {
|
| 11 |
--off-white: #eae9d8;
|
|
|
|
| 43 |
background: var(--off-white) !important;
|
| 44 |
}
|
| 45 |
|
| 46 |
+
/* Default width — no !important so Streamlit's drag-to-resize JS can override it */
|
| 47 |
section[data-testid="stSidebar"] {
|
| 48 |
width: 350px;
|
| 49 |
}
|
| 50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
/* ── 4. Markdown headings (st.markdown "### …") ────────────── */
|
| 52 |
.stMarkdown h1 {
|
| 53 |
font-weight: 700;
|