malcolmSQ commited on
Commit ·
1a9cae5
1
Parent(s): 03038b8
Fix LaTeX math delimiters in model explanation and ER calculation accordions for proper rendering in Gradio
Browse files- dashboard/app.py +99 -73
dashboard/app.py
CHANGED
|
@@ -209,19 +209,96 @@ with gr.Blocks() as demo:
|
|
| 209 |
</div>
|
| 210 |
""", elem_id="sequestr-header")
|
| 211 |
gr.Markdown(r"""
|
| 212 |
-
#
|
| 213 |
|
| 214 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
|
| 216 |
-
|
| 217 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 218 |
$$
|
| 219 |
-
|
| 220 |
$$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
|
| 222 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
|
| 224 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 225 |
""")
|
| 226 |
# --- Key Input Params Card ---
|
| 227 |
config = yaml.safe_load(open(MODEL_CONFIGS["Declining Increment"]))
|
|
@@ -254,10 +331,7 @@ This version is smoother and may yield slightly different results than the discr
|
|
| 254 |
)
|
| 255 |
gr.Markdown("""
|
| 256 |
### Key Model Inputs
|
| 257 |
-
""" + species_md
|
| 258 |
-
gr.Markdown("""
|
| 259 |
-
### Annual Mortality Rate
|
| 260 |
-
""" + mortality_md)
|
| 261 |
gr.Markdown("""
|
| 262 |
### Carbon Details
|
| 263 |
""" + carbon_md)
|
|
@@ -284,33 +358,14 @@ This version is smoother and may yield slightly different results than the discr
|
|
| 284 |
year_3 = gr.Number(value=year_3_default, label="Area to be planted in year 3 (ha)", interactive=True)
|
| 285 |
year_4 = gr.Number(value=year_4_default, label="Area to be planted in year 4 (ha)", interactive=True)
|
| 286 |
year_5 = gr.Number(value=year_5_default, label="Area to be planted in year 5 (ha)", interactive=True)
|
| 287 |
-
# Column 2:
|
| 288 |
with gr.Column(scale=1, min_width=220):
|
| 289 |
-
with gr.Accordion("
|
| 290 |
pdA = config['species'][0]['planting_density']
|
| 291 |
-
r0dA = config['species'][0]['declining_increment']['dbh']['r0']
|
| 292 |
-
tmdA = config['species'][0]['declining_increment']['dbh']['T_m']
|
| 293 |
-
r0hA = config['species'][0]['declining_increment']['height']['r0']
|
| 294 |
-
tmhA = config['species'][0]['declining_increment']['height']['T_m']
|
| 295 |
-
planting_density_A = gr.Slider(minimum=pdA*0.75, maximum=pdA*1.25, value=pdA, step=1, label="Initial planting density for Species A")
|
| 296 |
-
r0_dbh_A = gr.Slider(minimum=r0dA*0.75, maximum=r0dA*1.25, value=r0dA, step=0.01, label="Initial DBH growth rate for Species A")
|
| 297 |
-
tm_dbh_A = gr.Slider(minimum=tmdA*0.75, maximum=tmdA*1.25, value=tmdA, step=1, label="DBH growth duration for Species A")
|
| 298 |
-
r0_height_A = gr.Slider(minimum=r0hA*0.75, maximum=r0hA*1.25, value=r0hA, step=0.01, label="Initial height growth rate for Species A")
|
| 299 |
-
tm_height_A = gr.Slider(minimum=tmhA*0.75, maximum=tmhA*1.25, value=tmhA, step=1, label="Height growth duration for Species A")
|
| 300 |
-
# Column 3: Species B Parameters (as gr.Slider)
|
| 301 |
-
with gr.Column(scale=1, min_width=220):
|
| 302 |
-
with gr.Accordion("Species B Parameters", open=True):
|
| 303 |
pdB = config['species'][1]['planting_density']
|
| 304 |
-
|
| 305 |
-
tmdB = config['species'][1]['declining_increment']['dbh']['T_m']
|
| 306 |
-
r0hB = config['species'][1]['declining_increment']['height']['r0']
|
| 307 |
-
tmhB = config['species'][1]['declining_increment']['height']['T_m']
|
| 308 |
planting_density_B = gr.Slider(minimum=pdB*0.75, maximum=pdB*1.25, value=pdB, step=1, label="Initial planting density for Species B")
|
| 309 |
-
|
| 310 |
-
tm_dbh_B = gr.Slider(minimum=tmdB*0.75, maximum=tmdB*1.25, value=tmdB, step=1, label="DBH growth duration for Species B")
|
| 311 |
-
r0_height_B = gr.Slider(minimum=r0hB*0.75, maximum=r0hB*1.25, value=r0hB, step=0.01, label="Initial height growth rate for Species B")
|
| 312 |
-
tm_height_B = gr.Slider(minimum=tmhB*0.75, maximum=tmhB*1.25, value=tmhB, step=1, label="Height growth duration for Species B")
|
| 313 |
-
# Columns 4-5: Mortality Rates (as gr.Slider, split across two half-width columns in a single row)
|
| 314 |
with gr.Column(scale=2, min_width=300):
|
| 315 |
with gr.Accordion("Mortality Rates (%)", open=True):
|
| 316 |
mort_defaults = [config['species'][0]['mortality_rates'][f'year_{yr}'] for yr in range(1, 11)]
|
|
@@ -323,12 +378,8 @@ This version is smoother and may yield slightly different results than the discr
|
|
| 323 |
mort_sub = gr.Slider(minimum=mort_sub_default*0.75, maximum=mort_sub_default*1.25, value=mort_sub_default, step=0.1, label="Annual mortality rate for years 11+")
|
| 324 |
mort_vars = mort_vars_1 + mort_vars_2
|
| 325 |
# After the mortality columns, add:
|
| 326 |
-
project_duration_default = config['project']['duration_years']
|
| 327 |
-
buffer_pct_default = config['carbon']['buffer_percentage']
|
| 328 |
soil_carbon_default = config['carbon']['soil_carbon_per_ha_per_year']
|
| 329 |
|
| 330 |
-
project_duration = gr.Number(value=project_duration_default, label="Project Duration (years)", interactive=True, info="Total project duration in years")
|
| 331 |
-
buffer_pct = gr.Number(value=buffer_pct_default, label="Buffer %", interactive=True, info="Buffer pool percentage for risk mitigation")
|
| 332 |
soil_carbon = gr.Number(value=soil_carbon_default, label="Soil Carbon per ha per year (tCO2)", interactive=True, info="Annual soil carbon addition per hectare")
|
| 333 |
|
| 334 |
# Add a Reset to Defaults button
|
|
@@ -338,15 +389,7 @@ This version is smoother and may yield slightly different results than the discr
|
|
| 338 |
# Reload config and return all default values in widget order
|
| 339 |
config = yaml.safe_load(open(MODEL_CONFIGS["Declining Increment"]))
|
| 340 |
pdA = config['species'][0]['planting_density']
|
| 341 |
-
r0dA = config['species'][0]['declining_increment']['dbh']['r0']
|
| 342 |
-
tmdA = config['species'][0]['declining_increment']['dbh']['T_m']
|
| 343 |
-
r0hA = config['species'][0]['declining_increment']['height']['r0']
|
| 344 |
-
tmhA = config['species'][0]['declining_increment']['height']['T_m']
|
| 345 |
pdB = config['species'][1]['planting_density']
|
| 346 |
-
r0dB = config['species'][1]['declining_increment']['dbh']['r0']
|
| 347 |
-
tmdB = config['species'][1]['declining_increment']['dbh']['T_m']
|
| 348 |
-
r0hB = config['species'][1]['declining_increment']['height']['r0']
|
| 349 |
-
tmhB = config['species'][1]['declining_increment']['height']['T_m']
|
| 350 |
mort_defaults = [config['species'][0]['mortality_rates'][f'year_{yr}'] for yr in range(1, 11)]
|
| 351 |
mort_sub_default = config['species'][0]['mortality_rates']['subsequent']
|
| 352 |
return [
|
|
@@ -355,20 +398,16 @@ This version is smoother and may yield slightly different results than the discr
|
|
| 355 |
config['project']['planting_schedule']['year_3'],
|
| 356 |
config['project']['planting_schedule']['year_4'],
|
| 357 |
config['project']['planting_schedule']['year_5'],
|
| 358 |
-
pdA,
|
| 359 |
-
pdB, r0dB, tmdB, r0hB, tmhB,
|
| 360 |
*mort_defaults, mort_sub_default,
|
| 361 |
-
config['project']['duration_years'],
|
| 362 |
-
config['carbon']['buffer_percentage'],
|
| 363 |
config['carbon']['soil_carbon_per_ha_per_year']
|
| 364 |
]
|
| 365 |
reset_btn.click(
|
| 366 |
reset_to_defaults,
|
| 367 |
inputs=[],
|
| 368 |
outputs=[year_1, year_2, year_3, year_4, year_5,
|
| 369 |
-
planting_density_A,
|
| 370 |
-
|
| 371 |
-
*mort_vars, mort_sub, project_duration, buffer_pct, soil_carbon]
|
| 372 |
)
|
| 373 |
|
| 374 |
update_btn = gr.Button("Update Results", variant="primary")
|
|
@@ -391,32 +430,21 @@ This version is smoother and may yield slightly different results than the discr
|
|
| 391 |
# --- End tabbed tables ---
|
| 392 |
# Update the update_declining_increment callback to use these new inputs
|
| 393 |
def update_declining_increment(y1, y2, y3, y4, y5,
|
| 394 |
-
planting_density_A,
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
*mortality_inputs, project_duration, buffer_pct, soil_carbon = mortality_inputs_and_project_params
|
| 399 |
config = update_planting_schedule(MODEL_CONFIGS["Declining Increment"], [y1, y2, y3, y4, y5])
|
| 400 |
# Update species_A params
|
| 401 |
config['species'][0]['planting_density'] = planting_density_A
|
| 402 |
-
config['species'][0]['declining_increment']['dbh']['r0'] = r0_dbh_A
|
| 403 |
-
config['species'][0]['declining_increment']['dbh']['T_m'] = tm_dbh_A
|
| 404 |
-
config['species'][0]['declining_increment']['height']['r0'] = r0_height_A
|
| 405 |
-
config['species'][0]['declining_increment']['height']['T_m'] = tm_height_A
|
| 406 |
# Update species_B params
|
| 407 |
config['species'][1]['planting_density'] = planting_density_B
|
| 408 |
-
config['species'][1]['declining_increment']['dbh']['r0'] = r0_dbh_B
|
| 409 |
-
config['species'][1]['declining_increment']['dbh']['T_m'] = tm_dbh_B
|
| 410 |
-
config['species'][1]['declining_increment']['height']['r0'] = r0_height_B
|
| 411 |
-
config['species'][1]['declining_increment']['height']['T_m'] = tm_height_B
|
| 412 |
# Update mortality for BOTH species from the same UI values (years 1-10 + subsequent)
|
| 413 |
for i in [0, 1]:
|
| 414 |
for yr_idx, yr in enumerate(range(1, 11)):
|
| 415 |
config['species'][i]['mortality_rates'][f'year_{yr}'] = mortality_inputs[yr_idx]
|
| 416 |
config['species'][i]['mortality_rates']['subsequent'] = mortality_inputs[10]
|
| 417 |
# Update project/carbon params
|
| 418 |
-
config['project']['duration_years'] = int(project_duration)
|
| 419 |
-
config['carbon']['buffer_percentage'] = buffer_pct
|
| 420 |
config['carbon']['soil_carbon_per_ha_per_year'] = soil_carbon
|
| 421 |
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as tmp:
|
| 422 |
yaml.dump(config, tmp)
|
|
@@ -445,18 +473,16 @@ This version is smoother and may yield slightly different results than the discr
|
|
| 445 |
update_btn.click(
|
| 446 |
update_declining_increment,
|
| 447 |
inputs=[year_1, year_2, year_3, year_4, year_5,
|
| 448 |
-
planting_density_A,
|
| 449 |
-
|
| 450 |
-
*mort_vars, mort_sub, project_duration, buffer_pct, soil_carbon],
|
| 451 |
outputs=[carbon_plot, biomass_plot, annual_plot, growth_plot, summary_box, results_box, species_box, survival_box, biomass_debug_table]
|
| 452 |
)
|
| 453 |
# Show initial results
|
| 454 |
c, b, a, g, summary, r, s, surv, biomass_debug_df = update_declining_increment(
|
| 455 |
year_1_default, year_2_default, year_3_default, year_4_default, year_5_default,
|
| 456 |
-
pdA,
|
| 457 |
-
pdB, r0dB, tmdB, r0hB, tmhB,
|
| 458 |
*mort_defaults, mort_sub_default,
|
| 459 |
-
|
| 460 |
)
|
| 461 |
carbon_plot.value = c
|
| 462 |
biomass_plot.value = b
|
|
|
|
| 209 |
</div>
|
| 210 |
""", elem_id="sequestr-header")
|
| 211 |
gr.Markdown(r"""
|
| 212 |
+
# Mangrove Emissions Reduction (ER) Model & Dashboard
|
| 213 |
|
| 214 |
+
Welcome to the Mangrove ER Model Dashboard, a tool designed by [Sequestr](https://www.sequestr.io/) for simulating and analyzing carbon sequestration in mangrove restoration projects. This dashboard allows users to explore the "Declining Increment" growth model, adjust key project parameters, and visualize the resulting carbon and emission reduction outcomes over time.
|
| 215 |
+
""")
|
| 216 |
+
with gr.Accordion("How the Model Works", open=False):
|
| 217 |
+
gr.Markdown(r"""
|
| 218 |
+
## How the Model Works
|
| 219 |
+
|
| 220 |
+
The core of this dashboard is an emissions reduction (ER) model that projects mangrove growth, biomass accumulation, and carbon sequestration based on user-defined parameters and a chosen growth model. Currently, the active model is the **Declining Increment** model.
|
| 221 |
|
| 222 |
+
### Declining Increment Growth Model
|
| 223 |
|
| 224 |
+
This model assumes that the annual growth increment (for both Diameter at Breast Height - DBH, and Height) declines linearly over time, eventually reaching zero. The total size at any given age is the sum of all non-negative annual increments up to that age. This ensures that tree size never decreases.
|
| 225 |
+
|
| 226 |
+
**1. Discrete Declining Increment:**
|
| 227 |
+
The size at a given age $t$ (in years) is calculated by summing annual increments:
|
| 228 |
+
$$
|
| 229 |
+
\text{size}(t) = \text{initial\_size} + \sum_{i=1}^{t} \text{increment}(i)
|
| 230 |
$$
|
| 231 |
+
Where the increment for year $i$ is:
|
| 232 |
$$
|
| 233 |
+
\text{increment}(i) = \max\left(0, r_0 \cdot \left(1 - \frac{i - 0.5}{T_m}\right)\right)
|
| 234 |
+
$$
|
| 235 |
+
- $\text{initial\_size}$: The initial DBH (cm) or Height (m) at planting (age 0).
|
| 236 |
+
- $r_0$: The initial annual growth increment (cm/year for DBH, m/year for Height).
|
| 237 |
+
- $T_m$: The time (in years) at which the annual growth increment becomes zero.
|
| 238 |
|
| 239 |
+
**2. Continuous Declining Increment (Analytical Formula):**
|
| 240 |
+
For a smoother representation, the continuous version uses an analytical formula:
|
| 241 |
+
$$
|
| 242 |
+
\text{size}(t) = \text{initial\_size} + r_0 \cdot \left(t - \frac{t^2}{2T_m}\right), \quad \text{for } 0 \le t \le T_m
|
| 243 |
+
$$
|
| 244 |
+
If $t > T_m$, then $\text{size}(t) = \text{size}(T_m)$.
|
| 245 |
+
This version may yield slightly different results from the discrete sum, especially for short time periods or small $T_m$ values. The dashboard configuration specifies which version is active.
|
| 246 |
|
| 247 |
+
### Survival and Mortality
|
| 248 |
+
The number of surviving trees in a cohort is calculated annually. Mortality can be specified using either:
|
| 249 |
+
1. **Annual Mortality Rates**: A percentage mortality rate applied each year, potentially varying for the first few years and then stabilizing.
|
| 250 |
+
2. **DBH-Dependent Mortality (Optional, if configured)**: Mortality rate $m$ is a function of tree DBH:
|
| 251 |
+
$$
|
| 252 |
+
m = m_{\text{ref}} \cdot \left(\frac{\text{DBH}_{\text{ref}}}{\text{DBH}}\right)^p
|
| 253 |
+
$$
|
| 254 |
+
- $m_{\text{ref}}$: Reference mortality rate at $\text{DBH}_{\text{ref}}$.
|
| 255 |
+
- $\text{DBH}_{\text{ref}}$: Reference DBH.
|
| 256 |
+
- $p$: Exponent controlling the sensitivity of mortality to DBH.
|
| 257 |
+
The calculated $m$ is capped (e.g., between 0 and 0.99).
|
| 258 |
+
""")
|
| 259 |
+
with gr.Accordion("How Emission Reductions (ERs) are Calculated", open=False):
|
| 260 |
+
gr.Markdown(r"""
|
| 261 |
+
## How Emission Reductions (ERs) are Calculated
|
| 262 |
+
|
| 263 |
+
The model follows these steps to estimate net CO2 emission reductions:
|
| 264 |
+
|
| 265 |
+
**1. Biomass Calculation:**
|
| 266 |
+
Total above-ground and below-ground biomass per tree is calculated using allometric equations, which typically relate DBH and Height to biomass. For example, using equations from Zanvo et al. (2023):
|
| 267 |
+
- For *Rhizophora spp.* (Species A): $\text{Biomass}_{\text{total}} = 1.938 \times (\text{DBH}^2 \cdot H)^{0.67628}$ (kg)
|
| 268 |
+
- For *Avicennia germinans* (Species B): $\text{Biomass}_{\text{total}} = 1.486 \times (\text{DBH}^2 \cdot H)^{0.55864}$ (kg)
|
| 269 |
+
*(Note: The specific equations are defined in the model configuration.)*
|
| 270 |
+
|
| 271 |
+
**2. Carbon Stock Calculation:**
|
| 272 |
+
The total carbon stock in living biomass per hectare is calculated:
|
| 273 |
+
$$
|
| 274 |
+
\text{Carbon Stock (tC/ha)} = \frac{\text{Biomass per tree (kg)} \times \text{Surviving Trees per ha} \times \text{Biomass to Carbon ratio}}{1000}
|
| 275 |
+
$$
|
| 276 |
+
- The Biomass to Carbon ratio (e.g., 0.47) converts biomass to carbon mass.
|
| 277 |
+
|
| 278 |
+
**3. Gross CO2 Sequestration:**
|
| 279 |
+
The carbon stock is then converted to tons of CO2 equivalent:
|
| 280 |
+
$$
|
| 281 |
+
\text{Gross CO2eq (tCO2/ha)} = \text{Carbon Stock (tC/ha)} \times \text{Carbon to CO2 ratio}
|
| 282 |
+
$$
|
| 283 |
+
- The Carbon to CO2 ratio (typically 3.67) is based on molecular weights.
|
| 284 |
+
|
| 285 |
+
**4. Soil Carbon (Optional):**
|
| 286 |
+
If configured, annual soil carbon sequestration is added:
|
| 287 |
+
$$
|
| 288 |
+
\text{Soil Carbon CO2eq (tCO2/ha/yr)} = \text{User Defined Value (e.g. 1.0 tCO2/ha/yr)}
|
| 289 |
+
$$
|
| 290 |
+
This is added to the gross CO2 sequestration from biomass.
|
| 291 |
+
|
| 292 |
+
**5. Net Emission Reductions (ERs):**
|
| 293 |
+
Adjustments are made to the gross CO2 sequestration (including soil carbon, if applicable) to determine net ERs eligible for crediting:
|
| 294 |
+
$$
|
| 295 |
+
\text{Net ERs} = (\text{Gross CO2eq}_{\text{biomass + soil}}) \times (1 - \text{Buffer \%}) - (\text{Gross CO2eq}_{\text{biomass + soil}} \times \text{Leakage \%}) - (\text{Baseline Emissions per ha} \times \text{Area})
|
| 296 |
+
$$
|
| 297 |
+
- **Buffer Pool**: A percentage deduction to account for risks like project failure or natural disturbances.
|
| 298 |
+
- **Leakage**: Emissions occurring outside the project boundary due to project activities (often assumed to be 0% for mangrove projects if activities are self-contained).
|
| 299 |
+
- **Baseline Emissions**: Emissions that would have occurred in the absence of the project (e.g., from degrading land).
|
| 300 |
+
|
| 301 |
+
This dashboard visualizes these values annually over the project duration, providing insights into the project's carbon sequestration potential.
|
| 302 |
""")
|
| 303 |
# --- Key Input Params Card ---
|
| 304 |
config = yaml.safe_load(open(MODEL_CONFIGS["Declining Increment"]))
|
|
|
|
| 331 |
)
|
| 332 |
gr.Markdown("""
|
| 333 |
### Key Model Inputs
|
| 334 |
+
""" + species_md)
|
|
|
|
|
|
|
|
|
|
| 335 |
gr.Markdown("""
|
| 336 |
### Carbon Details
|
| 337 |
""" + carbon_md)
|
|
|
|
| 358 |
year_3 = gr.Number(value=year_3_default, label="Area to be planted in year 3 (ha)", interactive=True)
|
| 359 |
year_4 = gr.Number(value=year_4_default, label="Area to be planted in year 4 (ha)", interactive=True)
|
| 360 |
year_5 = gr.Number(value=year_5_default, label="Area to be planted in year 5 (ha)", interactive=True)
|
| 361 |
+
# Column 2: Planting Density (as gr.Slider)
|
| 362 |
with gr.Column(scale=1, min_width=220):
|
| 363 |
+
with gr.Accordion("Planting Density", open=True):
|
| 364 |
pdA = config['species'][0]['planting_density']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 365 |
pdB = config['species'][1]['planting_density']
|
| 366 |
+
planting_density_A = gr.Slider(minimum=pdA*0.75, maximum=pdA*1.25, value=pdA, step=1, label="Initial planting density for Species A")
|
|
|
|
|
|
|
|
|
|
| 367 |
planting_density_B = gr.Slider(minimum=pdB*0.75, maximum=pdB*1.25, value=pdB, step=1, label="Initial planting density for Species B")
|
| 368 |
+
# Columns 3-4: Mortality Rates (as gr.Slider, split across two half-width columns)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 369 |
with gr.Column(scale=2, min_width=300):
|
| 370 |
with gr.Accordion("Mortality Rates (%)", open=True):
|
| 371 |
mort_defaults = [config['species'][0]['mortality_rates'][f'year_{yr}'] for yr in range(1, 11)]
|
|
|
|
| 378 |
mort_sub = gr.Slider(minimum=mort_sub_default*0.75, maximum=mort_sub_default*1.25, value=mort_sub_default, step=0.1, label="Annual mortality rate for years 11+")
|
| 379 |
mort_vars = mort_vars_1 + mort_vars_2
|
| 380 |
# After the mortality columns, add:
|
|
|
|
|
|
|
| 381 |
soil_carbon_default = config['carbon']['soil_carbon_per_ha_per_year']
|
| 382 |
|
|
|
|
|
|
|
| 383 |
soil_carbon = gr.Number(value=soil_carbon_default, label="Soil Carbon per ha per year (tCO2)", interactive=True, info="Annual soil carbon addition per hectare")
|
| 384 |
|
| 385 |
# Add a Reset to Defaults button
|
|
|
|
| 389 |
# Reload config and return all default values in widget order
|
| 390 |
config = yaml.safe_load(open(MODEL_CONFIGS["Declining Increment"]))
|
| 391 |
pdA = config['species'][0]['planting_density']
|
|
|
|
|
|
|
|
|
|
|
|
|
| 392 |
pdB = config['species'][1]['planting_density']
|
|
|
|
|
|
|
|
|
|
|
|
|
| 393 |
mort_defaults = [config['species'][0]['mortality_rates'][f'year_{yr}'] for yr in range(1, 11)]
|
| 394 |
mort_sub_default = config['species'][0]['mortality_rates']['subsequent']
|
| 395 |
return [
|
|
|
|
| 398 |
config['project']['planting_schedule']['year_3'],
|
| 399 |
config['project']['planting_schedule']['year_4'],
|
| 400 |
config['project']['planting_schedule']['year_5'],
|
| 401 |
+
pdA, pdB,
|
|
|
|
| 402 |
*mort_defaults, mort_sub_default,
|
|
|
|
|
|
|
| 403 |
config['carbon']['soil_carbon_per_ha_per_year']
|
| 404 |
]
|
| 405 |
reset_btn.click(
|
| 406 |
reset_to_defaults,
|
| 407 |
inputs=[],
|
| 408 |
outputs=[year_1, year_2, year_3, year_4, year_5,
|
| 409 |
+
planting_density_A, planting_density_B,
|
| 410 |
+
*mort_vars, mort_sub, soil_carbon]
|
|
|
|
| 411 |
)
|
| 412 |
|
| 413 |
update_btn = gr.Button("Update Results", variant="primary")
|
|
|
|
| 430 |
# --- End tabbed tables ---
|
| 431 |
# Update the update_declining_increment callback to use these new inputs
|
| 432 |
def update_declining_increment(y1, y2, y3, y4, y5,
|
| 433 |
+
planting_density_A, planting_density_B,
|
| 434 |
+
*mortality_inputs_and_soil_carbon):
|
| 435 |
+
# Unpack the last one from the end
|
| 436 |
+
*mortality_inputs, soil_carbon = mortality_inputs_and_soil_carbon
|
|
|
|
| 437 |
config = update_planting_schedule(MODEL_CONFIGS["Declining Increment"], [y1, y2, y3, y4, y5])
|
| 438 |
# Update species_A params
|
| 439 |
config['species'][0]['planting_density'] = planting_density_A
|
|
|
|
|
|
|
|
|
|
|
|
|
| 440 |
# Update species_B params
|
| 441 |
config['species'][1]['planting_density'] = planting_density_B
|
|
|
|
|
|
|
|
|
|
|
|
|
| 442 |
# Update mortality for BOTH species from the same UI values (years 1-10 + subsequent)
|
| 443 |
for i in [0, 1]:
|
| 444 |
for yr_idx, yr in enumerate(range(1, 11)):
|
| 445 |
config['species'][i]['mortality_rates'][f'year_{yr}'] = mortality_inputs[yr_idx]
|
| 446 |
config['species'][i]['mortality_rates']['subsequent'] = mortality_inputs[10]
|
| 447 |
# Update project/carbon params
|
|
|
|
|
|
|
| 448 |
config['carbon']['soil_carbon_per_ha_per_year'] = soil_carbon
|
| 449 |
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as tmp:
|
| 450 |
yaml.dump(config, tmp)
|
|
|
|
| 473 |
update_btn.click(
|
| 474 |
update_declining_increment,
|
| 475 |
inputs=[year_1, year_2, year_3, year_4, year_5,
|
| 476 |
+
planting_density_A, planting_density_B,
|
| 477 |
+
*mort_vars, mort_sub, soil_carbon],
|
|
|
|
| 478 |
outputs=[carbon_plot, biomass_plot, annual_plot, growth_plot, summary_box, results_box, species_box, survival_box, biomass_debug_table]
|
| 479 |
)
|
| 480 |
# Show initial results
|
| 481 |
c, b, a, g, summary, r, s, surv, biomass_debug_df = update_declining_increment(
|
| 482 |
year_1_default, year_2_default, year_3_default, year_4_default, year_5_default,
|
| 483 |
+
pdA, pdB,
|
|
|
|
| 484 |
*mort_defaults, mort_sub_default,
|
| 485 |
+
soil_carbon_default
|
| 486 |
)
|
| 487 |
carbon_plot.value = c
|
| 488 |
biomass_plot.value = b
|