malcolmSQ commited on
Commit
bc8f256
·
1 Parent(s): 7b8bb25

Fix download functionality and import issues - Replace broken File components with working DownloadButton - Fix import paths to work without PYTHONPATH - Store raw data for proper CSV downloads - Update README with correct instructions - Improve UI layout by removing weird row layouts

Browse files
Files changed (2) hide show
  1. README.md +1 -3
  2. dashboard/app.py +97 -58
README.md CHANGED
@@ -30,12 +30,10 @@ This project implements a flexible, modular dashboard for mangrove carbon seques
30
  ```
31
  2. **Run the dashboard:**
32
  ```bash
33
- PYTHONPATH=. python dashboard/app.py
34
  ```
35
  The terminal will display a public share link.
36
 
37
- **Note:** The `PYTHONPATH=.` is required to ensure the `er_model_core` module can be found.
38
-
39
  ## Growth Models
40
  - **Declining Increment (ACTIVE):**
41
  - Annual increment declines linearly to zero; total size is the sum of non-negative increments (never decreases or goes negative).
 
30
  ```
31
  2. **Run the dashboard:**
32
  ```bash
33
+ python dashboard/app.py
34
  ```
35
  The terminal will display a public share link.
36
 
 
 
37
  ## Growth Models
38
  - **Declining Increment (ACTIVE):**
39
  - Annual increment declines linearly to zero; total size is the sum of non-negative increments (never decreases or goes negative).
dashboard/app.py CHANGED
@@ -8,6 +8,12 @@ Mangrove ER Model Dashboard
8
 
9
  import gradio as gr
10
  from pathlib import Path
 
 
 
 
 
 
11
  from er_model_core.er_model import ERModel
12
  import pandas as pd
13
  import numpy as np
@@ -434,21 +440,17 @@ This dashboard visualizes these values annually over the project duration, provi
434
  # --- Tabbed tables section ---
435
  with gr.Tabs():
436
  with gr.Tab("Project Results (Annual)"):
437
- with gr.Row():
438
- results_box = gr.Dataframe(label="Project Results (Annual)")
439
- download_results_btn = gr.Button("📥 Download CSV", variant="secondary", scale=1)
440
  with gr.Tab("Species Results (Annual)"):
441
- with gr.Row():
442
- species_box = gr.Dataframe(label="Species Results (Annual)")
443
- download_species_btn = gr.Button("📥 Download CSV", variant="secondary", scale=1)
444
  with gr.Tab("Surviving Trees Table"):
445
- with gr.Row():
446
- survival_box = gr.Dataframe(label="Surviving Trees Table")
447
- download_survival_btn = gr.Button("📥 Download CSV", variant="secondary", scale=1)
448
  with gr.Tab("Biomass Table"):
449
- with gr.Row():
450
- biomass_debug_table = gr.Dataframe(label="Biomass Table (inputs & outputs per year)")
451
- download_biomass_btn = gr.Button("📥 Download CSV", variant="secondary", scale=1)
452
  # --- End tabbed tables ---
453
  # Update the update_declining_increment callback to use these new inputs
454
  def update_declining_increment(y1, y2, y3, y4, y5,
@@ -488,6 +490,13 @@ This dashboard visualizes these values annually over the project duration, provi
488
  species_results_fmt = to_native(species_results_fmt)
489
  survival_table = to_native(survival_table)
490
  biomass_debug_df = to_native(biomass_debug_df)
 
 
 
 
 
 
 
491
  # --- Ensure all other values are native types ---
492
  if hasattr(summary, 'item'):
493
  summary = summary.item()
@@ -501,70 +510,100 @@ This dashboard visualizes these values annually over the project duration, provi
501
  )
502
 
503
  # Download functionality for tables
504
- def create_csv_from_df(df):
505
- if isinstance(df, str):
506
- # Convert string representation of dataframe back to dataframe
507
- import ast
508
- try:
509
- data = ast.literal_eval(df)
510
- df = pd.DataFrame(data)
511
- except:
512
- return None
513
- elif hasattr(df, '_list_display') and hasattr(df, 'columns'):
514
- # Convert gradio dataframe to pandas dataframe
515
- df = pd.DataFrame(df._list_display, columns=df.columns)
516
- return df
517
-
518
- def download_results_csv(df):
519
- df = create_csv_from_df(df)
520
- if df is None:
521
- return None
522
- csv_data = df.to_csv(index=False)
523
- return (csv_data, "project_results.csv")
524
 
525
- def download_species_csv(df):
526
- df = create_csv_from_df(df)
527
- if df is None:
528
- return None
529
- csv_data = df.to_csv(index=False)
530
- return (csv_data, "species_results.csv")
 
 
 
 
 
 
 
 
 
 
 
531
 
532
- def download_survival_csv(df):
533
- df = create_csv_from_df(df)
534
- if df is None:
535
- return None
536
- csv_data = df.to_csv(index=False)
537
- return (csv_data, "surviving_trees.csv")
 
 
 
 
 
 
 
 
 
 
 
538
 
539
- def download_biomass_csv(df):
540
- df = create_csv_from_df(df)
541
- if df is None:
542
- return None
543
- csv_data = df.to_csv(index=False)
544
- return (csv_data, "biomass_table.csv")
 
 
 
 
 
 
 
 
 
 
 
545
 
546
  download_results_btn.click(
547
  download_results_csv,
548
- inputs=[results_box],
549
- outputs=[gr.File(label="Download Project Results", file_count="single", interactive=False)]
550
  )
551
 
552
  download_species_btn.click(
553
  download_species_csv,
554
- inputs=[species_box],
555
- outputs=[gr.File(label="Download Species Results", file_count="single", interactive=False)]
556
  )
557
 
558
  download_survival_btn.click(
559
  download_survival_csv,
560
- inputs=[survival_box],
561
- outputs=[gr.File(label="Download Surviving Trees", file_count="single", interactive=False)]
562
  )
563
 
564
  download_biomass_btn.click(
565
  download_biomass_csv,
566
- inputs=[biomass_debug_table],
567
- outputs=[gr.File(label="Download Biomass Table", file_count="single", interactive=False)]
568
  )
569
 
570
  # Show initial results
 
8
 
9
  import gradio as gr
10
  from pathlib import Path
11
+ import sys
12
+ import os
13
+
14
+ # Add the parent directory to Python path so we can import er_model_core
15
+ sys.path.insert(0, str(Path(__file__).parent.parent))
16
+
17
  from er_model_core.er_model import ERModel
18
  import pandas as pd
19
  import numpy as np
 
440
  # --- Tabbed tables section ---
441
  with gr.Tabs():
442
  with gr.Tab("Project Results (Annual)"):
443
+ results_box = gr.Dataframe(label="Project Results (Annual)")
444
+ download_results_btn = gr.DownloadButton("📥 Download CSV", variant="secondary")
 
445
  with gr.Tab("Species Results (Annual)"):
446
+ species_box = gr.Dataframe(label="Species Results (Annual)")
447
+ download_species_btn = gr.DownloadButton("📥 Download CSV", variant="secondary")
 
448
  with gr.Tab("Surviving Trees Table"):
449
+ survival_box = gr.Dataframe(label="Surviving Trees Table")
450
+ download_survival_btn = gr.DownloadButton("📥 Download CSV", variant="secondary")
 
451
  with gr.Tab("Biomass Table"):
452
+ biomass_debug_table = gr.Dataframe(label="Biomass Table (inputs & outputs per year)")
453
+ download_biomass_btn = gr.DownloadButton("📥 Download CSV", variant="secondary")
 
454
  # --- End tabbed tables ---
455
  # Update the update_declining_increment callback to use these new inputs
456
  def update_declining_increment(y1, y2, y3, y4, y5,
 
490
  species_results_fmt = to_native(species_results_fmt)
491
  survival_table = to_native(survival_table)
492
  biomass_debug_df = to_native(biomass_debug_df)
493
+
494
+ # Store raw data for downloads (before formatting)
495
+ update_declining_increment._last_results = results
496
+ update_declining_increment._last_species_results = species_results
497
+ update_declining_increment._last_survival_table = model.species_metrics.pivot(index="Year", columns="Species", values="Surviving Trees").reset_index()
498
+ update_declining_increment._last_biomass_table = model.species_metrics
499
+
500
  # --- Ensure all other values are native types ---
501
  if hasattr(summary, 'item'):
502
  summary = summary.item()
 
510
  )
511
 
512
  # Download functionality for tables
513
+ def download_results_csv():
514
+ if hasattr(update_declining_increment, '_last_results'):
515
+ df = update_declining_increment._last_results.copy()
516
+ # Remove formatting for CSV export
517
+ for col in df.columns:
518
+ if df[col].dtype == 'object':
519
+ try:
520
+ # Try to convert formatted strings back to numbers
521
+ df[col] = df[col].str.replace(',', '').astype(float)
522
+ except:
523
+ pass # Keep as string if conversion fails
524
+
525
+ temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False)
526
+ df.to_csv(temp_file.name, index=False)
527
+ temp_file.close()
528
+ return temp_file.name
529
+ return None
 
 
 
530
 
531
+ def download_species_csv():
532
+ if hasattr(update_declining_increment, '_last_species_results'):
533
+ df = update_declining_increment._last_species_results.copy()
534
+ # Remove formatting for CSV export
535
+ for col in df.columns:
536
+ if df[col].dtype == 'object':
537
+ try:
538
+ # Try to convert formatted strings back to numbers
539
+ df[col] = df[col].str.replace(',', '').astype(float)
540
+ except:
541
+ pass # Keep as string if conversion fails
542
+
543
+ temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False)
544
+ df.to_csv(temp_file.name, index=False)
545
+ temp_file.close()
546
+ return temp_file.name
547
+ return None
548
 
549
+ def download_survival_csv():
550
+ if hasattr(update_declining_increment, '_last_survival_table'):
551
+ df = update_declining_increment._last_survival_table.copy()
552
+ # Remove formatting for CSV export
553
+ for col in df.columns:
554
+ if df[col].dtype == 'object' and col != 'Year':
555
+ try:
556
+ # Try to convert formatted strings back to numbers
557
+ df[col] = df[col].str.replace(',', '').astype(float)
558
+ except:
559
+ pass # Keep as string if conversion fails
560
+
561
+ temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False)
562
+ df.to_csv(temp_file.name, index=False)
563
+ temp_file.close()
564
+ return temp_file.name
565
+ return None
566
 
567
+ def download_biomass_csv():
568
+ if hasattr(update_declining_increment, '_last_biomass_table'):
569
+ df = update_declining_increment._last_biomass_table.copy()
570
+ # Remove formatting for CSV export - this table has complex column names
571
+ for col in df.columns:
572
+ if df[col].dtype == 'object':
573
+ try:
574
+ # Try to convert formatted strings back to numbers
575
+ df[col] = df[col].str.replace(',', '').astype(float)
576
+ except:
577
+ pass # Keep as string if conversion fails
578
+
579
+ temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False)
580
+ df.to_csv(temp_file.name, index=False)
581
+ temp_file.close()
582
+ return temp_file.name
583
+ return None
584
 
585
  download_results_btn.click(
586
  download_results_csv,
587
+ inputs=[],
588
+ outputs=[]
589
  )
590
 
591
  download_species_btn.click(
592
  download_species_csv,
593
+ inputs=[],
594
+ outputs=[]
595
  )
596
 
597
  download_survival_btn.click(
598
  download_survival_csv,
599
+ inputs=[],
600
+ outputs=[]
601
  )
602
 
603
  download_biomass_btn.click(
604
  download_biomass_csv,
605
+ inputs=[],
606
+ outputs=[]
607
  )
608
 
609
  # Show initial results