calculator / app.py
mbuuck's picture
Cast metric data to float to fix plot.
5f4fd41
raw
history blame
No virus
3.69 kB
import os
import gradio as gr
import plotly.express as px
import pandas as pd
from utils import duckdb_queries as dq
from utils.gradio import get_window_url_params
from utils.indicators import IndexGenerator
# Instantiate outside gradio app to avoid re-initializing GEE, which is slow
indexgenerator = IndexGenerator()
metric_names = os.listdir('metrics')
for i in range(len(metric_names)):
metric_names[i] = metric_names[i].split('.yaml')[0].replace('_', ' ')
def toggle_metric_definition_box(text_input):
if text_input is None or text_input == '':
return indexgenerator.get_metric_file()
else:
return None
def make_timeseries_plot(df):
for col in df.columns:
df[col] = pd.to_numeric(df[col], errors='ignore')
return px.line(df, x='Year', y='Score (Area * Value)', markers=True)
with gr.Blocks() as demo:
with gr.Column():
with gr.Row():
m1 = gr.Plot(label='Project Map')
ts_plot = gr.Plot(label='Metric scores over time')
with gr.Row():
project_name = gr.Dropdown([], label="Project", value="Select project")
metric = gr.Dropdown(metric_names, label='Metric', value='Select metric')
start_year = gr.Number(value=2017, label="Start Year", precision=0)
end_year = gr.Number(value=2022, label="End Year", precision=0)
with gr.Row():
view_btn = gr.Button(value="Show project map")
calc_btn = gr.Button(value="Calculate metric")
metric_btn = gr.Button(value='Show/hide metric definition')
metric_docs = gr.Textbox(
label="The chosen metric is a linear combination of these components normalized to a range of 0 to 1 and with the given coefficients",
interactive=False)
results_df = gr.Dataframe(
headers=["Year", "Project Name", "Score"],
datatype=["number", "str", "number"],
label="Scores by year",
)
calc_btn.click(
indexgenerator.calculate_score,
inputs=[start_year, end_year],
outputs=results_df,
).then(
make_timeseries_plot,
inputs=results_df,
outputs=ts_plot
)
view_btn.click(
fn=indexgenerator.show_project_map,
outputs=[m1],
)
def update_project_dropdown_list(url_params):
username = url_params.get("username", "default")
projects = dq.list_projects_by_author(author_id=username)
# Initialize the first project in the list
project_names = projects['name'].tolist()
return gr.Dropdown.update(choices=project_names)
# Change the project name in the index generator object when the
# user selects a new project
project_name.change(
indexgenerator.set_project,
inputs=project_name
)
# Set the metric to be calculated
metric.change(
indexgenerator.set_metric,
inputs=metric
)
# Toggle display of metric information
metric_btn.click(
toggle_metric_definition_box,
inputs=metric_docs,
outputs=metric_docs
)
# Get url params
url_params = gr.JSON({"username": "default"}, visible=False, label="URL Params")
# Gradio has a bug
# For dropdown to update by demo.load, dropdown value must be called downstream
b1 = gr.Button("Hidden button that fixes bug.", visible=False)
b1.click(lambda x: x, inputs=project_name, outputs=[])
# Update project dropdown list on page load
demo.load(
fn=update_project_dropdown_list,
inputs=[url_params],
outputs=[project_name],
_js=get_window_url_params,
queue=False,
)
demo.launch()