Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,32 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import math
|
| 2 |
from pathlib import Path
|
| 3 |
import gradio as gr
|
| 4 |
import matplotlib.pyplot as plt
|
| 5 |
|
| 6 |
# ------------------------------
|
| 7 |
-
# Config:
|
| 8 |
# ------------------------------
|
| 9 |
ASSETS = Path("assets")
|
| 10 |
MSK_CFG = {
|
| 11 |
"description": (
|
| 12 |
-
"
|
| 13 |
-
"
|
| 14 |
),
|
| 15 |
-
"sample_images": ["msk/
|
| 16 |
"roi_inputs": {
|
| 17 |
-
"baseline_volume": 15000,
|
| 18 |
-
"avg_rev_per_study": 6000,
|
| 19 |
-
"mins_saved_per_study": 5,
|
| 20 |
-
"cost_per_rad_hour": 5200,
|
| 21 |
-
"baseline_repeats": 750,
|
| 22 |
-
"cost_per_repeat": 6000,
|
| 23 |
-
"repeat_reduction_pct": 10,
|
| 24 |
-
"program_cost_annual": 1200000
|
| 25 |
},
|
| 26 |
"evidence": [
|
| 27 |
-
"Time savings
|
| 28 |
-
"
|
| 29 |
-
"High agreement with subspecialty
|
| 30 |
],
|
| 31 |
"methodology": (
|
| 32 |
"Gross benefit = Efficiency savings + Savings from reduced repeats.\n"
|
|
@@ -40,19 +45,10 @@ MSK_CFG = {
|
|
| 40 |
# ------------------------------
|
| 41 |
# ROI math
|
| 42 |
# ------------------------------
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
mins_saved_per_study: float,
|
| 48 |
-
cost_per_rad_hour: float,
|
| 49 |
-
baseline_repeats: float,
|
| 50 |
-
cost_per_repeat: float,
|
| 51 |
-
repeat_reduction_pct: float,
|
| 52 |
-
program_cost_annual: float,
|
| 53 |
-
):
|
| 54 |
-
"""Compute ROI metrics; normalize internally to annual, then present for selected period."""
|
| 55 |
-
# annualized inputs
|
| 56 |
eff_savings_annual = (mins_saved_per_study / 60.0) * baseline_volume * cost_per_rad_hour
|
| 57 |
repeats_avoided_annual = baseline_repeats * (repeat_reduction_pct / 100.0)
|
| 58 |
repeat_savings_annual = repeats_avoided_annual * cost_per_repeat
|
|
@@ -64,11 +60,9 @@ def compute_roi(
|
|
| 64 |
roi_pct = (net_benefit_annual / program_cost * 100.0) if program_cost else 0.0
|
| 65 |
payback_months = (program_cost / (gross_benefit_annual / 12.0)) if gross_benefit_annual > 0 else math.inf
|
| 66 |
|
| 67 |
-
# simple operational metrics
|
| 68 |
hours_saved_annual = (mins_saved_per_study / 60.0) * baseline_volume
|
| 69 |
-
fte_saved_eq = hours_saved_annual / 1920.0
|
| 70 |
|
| 71 |
-
# scale for period view
|
| 72 |
factor = 1 if period == "Annual" else 1/12
|
| 73 |
|
| 74 |
metrics = {
|
|
@@ -81,29 +75,24 @@ def compute_roi(
|
|
| 81 |
"Payback (months)": (round(payback_months, 1) if payback_months != math.inf else float("inf")),
|
| 82 |
"Hours saved / year": round(hours_saved_annual, 1),
|
| 83 |
"FTE saved (β1920h/yr)": round(fte_saved_eq, 2),
|
| 84 |
-
# Keeping avg_rev_per_study visible for future throughput revenue logic
|
| 85 |
"Avg revenue per study (input)": avg_rev_per_study,
|
| 86 |
}
|
| 87 |
return metrics
|
| 88 |
|
| 89 |
|
| 90 |
def waterfall_plot(metrics: dict):
|
| 91 |
-
"""Return a simple matplotlib waterfall figure using current metrics."""
|
| 92 |
fig = plt.figure()
|
| 93 |
components = ["Efficiency savings", "Repeat savings", "Program cost"]
|
| 94 |
deltas = [metrics[c] for c in components]
|
| 95 |
-
# Program cost is a negative contributor
|
| 96 |
deltas[2] = -abs(deltas[2])
|
| 97 |
|
| 98 |
running = 0
|
| 99 |
-
x_positions = range(len(components) + 1)
|
| 100 |
cumulative = [0]
|
| 101 |
for d in deltas:
|
| 102 |
running += d
|
| 103 |
cumulative.append(running)
|
| 104 |
|
| 105 |
-
|
| 106 |
-
for i, d in enumerate(deltas):
|
| 107 |
y0, y1 = cumulative[i], cumulative[i+1]
|
| 108 |
plt.plot([i, i], [y0, y1], linewidth=14)
|
| 109 |
|
|
@@ -115,82 +104,48 @@ def waterfall_plot(metrics: dict):
|
|
| 115 |
return fig
|
| 116 |
|
| 117 |
|
| 118 |
-
# ------------------------------
|
| 119 |
-
# UI callbacks
|
| 120 |
-
# ------------------------------
|
| 121 |
-
|
| 122 |
def init(period):
|
| 123 |
cfg = MSK_CFG
|
| 124 |
desc = cfg["description"]
|
| 125 |
-
# only include existing asset files
|
| 126 |
gallery = [str(ASSETS / p) for p in cfg["sample_images"] if (ASSETS / p).exists()]
|
| 127 |
|
| 128 |
inputs = cfg["roi_inputs"]
|
| 129 |
-
metrics = compute_roi(
|
| 130 |
-
period,
|
| 131 |
-
inputs["baseline_volume"],
|
| 132 |
-
inputs["avg_rev_per_study"],
|
| 133 |
-
inputs["mins_saved_per_study"],
|
| 134 |
-
inputs["cost_per_rad_hour"],
|
| 135 |
-
inputs["baseline_repeats"],
|
| 136 |
-
inputs["cost_per_repeat"],
|
| 137 |
-
inputs["repeat_reduction_pct"],
|
| 138 |
-
inputs["program_cost_annual"],
|
| 139 |
-
)
|
| 140 |
fig = waterfall_plot(metrics)
|
| 141 |
|
| 142 |
-
# Executive readout
|
| 143 |
readout = (
|
| 144 |
-
f"**
|
| 145 |
f"ROI (annualized): {metrics['ROI % (annualized)']}%; "
|
| 146 |
f"Payback: {metrics['Payback (months)']} months.\n\n"
|
| 147 |
f"Operational: {metrics['Hours saved / year']:.0f} hours saved (~{metrics['FTE saved (β1920h/yr)']:.2f} FTE)."
|
| 148 |
)
|
| 149 |
|
| 150 |
-
ev_md = "\n".join([f"- {e}" for e in cfg.get(
|
| 151 |
meth_md = cfg.get("methodology", "")
|
| 152 |
|
| 153 |
-
defaults =
|
| 154 |
-
inputs["baseline_volume"],
|
| 155 |
-
inputs["avg_rev_per_study"],
|
| 156 |
-
inputs["mins_saved_per_study"],
|
| 157 |
-
inputs["cost_per_rad_hour"],
|
| 158 |
-
inputs["baseline_repeats"],
|
| 159 |
-
inputs["cost_per_repeat"],
|
| 160 |
-
inputs["repeat_reduction_pct"],
|
| 161 |
-
inputs["program_cost_annual"],
|
| 162 |
-
]
|
| 163 |
-
|
| 164 |
return desc, gallery, *defaults, metrics, fig, readout, ev_md, meth_md
|
| 165 |
|
| 166 |
|
| 167 |
-
def recalc(period,
|
| 168 |
-
baseline_volume, avg_rev_per_study, mins_saved_per_study,
|
| 169 |
cost_per_rad_hour, baseline_repeats, cost_per_repeat,
|
| 170 |
repeat_reduction_pct, program_cost_annual):
|
| 171 |
-
metrics = compute_roi(
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
cost_per_rad_hour, baseline_repeats, cost_per_repeat,
|
| 175 |
-
repeat_reduction_pct, program_cost_annual,
|
| 176 |
-
)
|
| 177 |
fig = waterfall_plot(metrics)
|
| 178 |
readout = (
|
| 179 |
-
f"**
|
| 180 |
f"ROI (annualized): {metrics['ROI % (annualized)']}%; "
|
| 181 |
f"Payback: {metrics['Payback (months)']} months.\n\n"
|
| 182 |
f"Operational: {metrics['Hours saved / year']:.0f} hours saved (~{metrics['FTE saved (β1920h/yr)']:.2f} FTE)."
|
| 183 |
)
|
| 184 |
return metrics, fig, readout
|
| 185 |
|
| 186 |
-
|
| 187 |
-
# ------------------------------
|
| 188 |
-
# Gradio UI
|
| 189 |
-
# ------------------------------
|
| 190 |
-
with gr.Blocks(title="MSK AI ROI β Interactive", fill_height=True) as demo:
|
| 191 |
gr.Markdown("""
|
| 192 |
-
#
|
| 193 |
-
**Clinician-first sandbox**: explore a sample
|
| 194 |
""")
|
| 195 |
|
| 196 |
period = gr.Radio(["Annual", "Monthly"], value="Annual", label="Time basis")
|
|
@@ -198,17 +153,17 @@ with gr.Blocks(title="MSK AI ROI β Interactive", fill_height=True) as demo:
|
|
| 198 |
with gr.Tabs():
|
| 199 |
with gr.Tab("Explore"):
|
| 200 |
desc = gr.Markdown()
|
| 201 |
-
gallery = gr.Gallery(label="Sample
|
| 202 |
|
| 203 |
with gr.Tab("ROI Simulator"):
|
| 204 |
with gr.Row():
|
| 205 |
with gr.Column(scale=1, min_width=360):
|
| 206 |
-
baseline_volume = gr.Slider(0, 100000, value=15000, step=50, label="Annual
|
| 207 |
avg_rev_per_study = gr.Slider(0, 50000, value=6000, step=50, label="Avg revenue per study (info)")
|
| 208 |
mins_saved_per_study = gr.Slider(0, 60, value=5, step=1, label="Minutes saved per study")
|
| 209 |
cost_per_rad_hour = gr.Slider(0, 20000, value=5200, step=50, label="Radiologist cost/hour")
|
| 210 |
-
baseline_repeats = gr.Slider(0, 100000, value=750, step=10, label="Baseline
|
| 211 |
-
cost_per_repeat = gr.Slider(0, 50000, value=6000, step=50, label="Cost per repeat
|
| 212 |
repeat_reduction_pct = gr.Slider(0, 100, value=10, step=1, label="Repeat reduction with AI (%)")
|
| 213 |
program_cost_annual = gr.Slider(0, 10000000, value=1200000, step=10000, label="Program cost (annual)")
|
| 214 |
with gr.Column(scale=1):
|
|
@@ -222,32 +177,26 @@ with gr.Blocks(title="MSK AI ROI β Interactive", fill_height=True) as demo:
|
|
| 222 |
with gr.Tab("Methodology"):
|
| 223 |
methodology_md = gr.Markdown()
|
| 224 |
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
[period],
|
| 229 |
-
[desc, gallery, baseline_volume, avg_rev_per_study, mins_saved_per_study,
|
| 230 |
-
cost_per_rad_hour, baseline_repeats, cost_per_repeat, repeat_reduction_pct, program_cost_annual,
|
| 231 |
-
metrics, chart, readout, evidence_md, methodology_md]
|
| 232 |
-
)
|
| 233 |
|
| 234 |
for comp in [baseline_volume, avg_rev_per_study, mins_saved_per_study, cost_per_rad_hour,
|
| 235 |
baseline_repeats, cost_per_repeat, repeat_reduction_pct, program_cost_annual]:
|
| 236 |
-
comp.change(
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
load=True,
|
| 245 |
-
fn=init,
|
| 246 |
-
inputs=[period],
|
| 247 |
-
outputs=[desc, gallery, baseline_volume, avg_rev_per_study, mins_saved_per_study,
|
| 248 |
-
cost_per_rad_hour, baseline_repeats, cost_per_repeat, repeat_reduction_pct, program_cost_annual,
|
| 249 |
-
metrics, chart, readout, evidence_md, methodology_md]
|
| 250 |
-
)
|
| 251 |
|
| 252 |
if __name__ == "__main__":
|
| 253 |
-
demo.launch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Repo layout (create these files in your Space)
|
| 2 |
+
# ββ app.py β paste this whole file
|
| 3 |
+
# ββ requirements.txt β at end of this file
|
| 4 |
+
# ββ assets/msk/Gleamer bone view.png, assets/msk/overlay.png β optional demo images
|
| 5 |
+
|
| 6 |
import math
|
| 7 |
from pathlib import Path
|
| 8 |
import gradio as gr
|
| 9 |
import matplotlib.pyplot as plt
|
| 10 |
|
| 11 |
# ------------------------------
|
| 12 |
+
# Config: Gleamer Bone View scenario
|
| 13 |
# ------------------------------
|
| 14 |
ASSETS = Path("assets")
|
| 15 |
MSK_CFG = {
|
| 16 |
"description": (
|
| 17 |
+
"Gleamer Bone View AI assists in detecting fractures on X-rays, speeding reporting, "
|
| 18 |
+
"reducing missed diagnoses, and improving workflow efficiency."
|
| 19 |
),
|
| 20 |
+
"sample_images": ["msk/Gleamer Bone View.png", "msk/overlay.png"],
|
| 21 |
"roi_inputs": {
|
| 22 |
+
"baseline_volume": 15000,
|
| 23 |
+
"avg_rev_per_study": 6000,
|
| 24 |
+
"mins_saved_per_study": 5,
|
| 25 |
+
"cost_per_rad_hour": 5200,
|
| 26 |
+
"baseline_repeats": 750,
|
| 27 |
+
"cost_per_repeat": 6000,
|
| 28 |
+
"repeat_reduction_pct": 10,
|
| 29 |
+
"program_cost_annual": 1200000
|
| 30 |
},
|
| 31 |
"evidence": [
|
| 32 |
+
"Time savings in fracture detection reported in multi-center settings.",
|
| 33 |
+
"Reduced missed fractures through AI-assisted reads.",
|
| 34 |
+
"High agreement with subspecialty musculoskeletal radiologists in fracture detection."
|
| 35 |
],
|
| 36 |
"methodology": (
|
| 37 |
"Gross benefit = Efficiency savings + Savings from reduced repeats.\n"
|
|
|
|
| 45 |
# ------------------------------
|
| 46 |
# ROI math
|
| 47 |
# ------------------------------
|
| 48 |
+
|
| 49 |
+
def compute_roi(period, baseline_volume, avg_rev_per_study, mins_saved_per_study,
|
| 50 |
+
cost_per_rad_hour, baseline_repeats, cost_per_repeat,
|
| 51 |
+
repeat_reduction_pct, program_cost_annual):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
eff_savings_annual = (mins_saved_per_study / 60.0) * baseline_volume * cost_per_rad_hour
|
| 53 |
repeats_avoided_annual = baseline_repeats * (repeat_reduction_pct / 100.0)
|
| 54 |
repeat_savings_annual = repeats_avoided_annual * cost_per_repeat
|
|
|
|
| 60 |
roi_pct = (net_benefit_annual / program_cost * 100.0) if program_cost else 0.0
|
| 61 |
payback_months = (program_cost / (gross_benefit_annual / 12.0)) if gross_benefit_annual > 0 else math.inf
|
| 62 |
|
|
|
|
| 63 |
hours_saved_annual = (mins_saved_per_study / 60.0) * baseline_volume
|
| 64 |
+
fte_saved_eq = hours_saved_annual / 1920.0
|
| 65 |
|
|
|
|
| 66 |
factor = 1 if period == "Annual" else 1/12
|
| 67 |
|
| 68 |
metrics = {
|
|
|
|
| 75 |
"Payback (months)": (round(payback_months, 1) if payback_months != math.inf else float("inf")),
|
| 76 |
"Hours saved / year": round(hours_saved_annual, 1),
|
| 77 |
"FTE saved (β1920h/yr)": round(fte_saved_eq, 2),
|
|
|
|
| 78 |
"Avg revenue per study (input)": avg_rev_per_study,
|
| 79 |
}
|
| 80 |
return metrics
|
| 81 |
|
| 82 |
|
| 83 |
def waterfall_plot(metrics: dict):
|
|
|
|
| 84 |
fig = plt.figure()
|
| 85 |
components = ["Efficiency savings", "Repeat savings", "Program cost"]
|
| 86 |
deltas = [metrics[c] for c in components]
|
|
|
|
| 87 |
deltas[2] = -abs(deltas[2])
|
| 88 |
|
| 89 |
running = 0
|
|
|
|
| 90 |
cumulative = [0]
|
| 91 |
for d in deltas:
|
| 92 |
running += d
|
| 93 |
cumulative.append(running)
|
| 94 |
|
| 95 |
+
for i in range(len(deltas)):
|
|
|
|
| 96 |
y0, y1 = cumulative[i], cumulative[i+1]
|
| 97 |
plt.plot([i, i], [y0, y1], linewidth=14)
|
| 98 |
|
|
|
|
| 104 |
return fig
|
| 105 |
|
| 106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
def init(period):
|
| 108 |
cfg = MSK_CFG
|
| 109 |
desc = cfg["description"]
|
|
|
|
| 110 |
gallery = [str(ASSETS / p) for p in cfg["sample_images"] if (ASSETS / p).exists()]
|
| 111 |
|
| 112 |
inputs = cfg["roi_inputs"]
|
| 113 |
+
metrics = compute_roi(period, **inputs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
fig = waterfall_plot(metrics)
|
| 115 |
|
|
|
|
| 116 |
readout = (
|
| 117 |
+
f"**Gleamer Bone View snapshot** β Net benefit: {metrics['Net benefit']:.0f}; "
|
| 118 |
f"ROI (annualized): {metrics['ROI % (annualized)']}%; "
|
| 119 |
f"Payback: {metrics['Payback (months)']} months.\n\n"
|
| 120 |
f"Operational: {metrics['Hours saved / year']:.0f} hours saved (~{metrics['FTE saved (β1920h/yr)']:.2f} FTE)."
|
| 121 |
)
|
| 122 |
|
| 123 |
+
ev_md = "\n".join([f"- {e}" for e in cfg.get('evidence', [])]) or "_Add citations_"
|
| 124 |
meth_md = cfg.get("methodology", "")
|
| 125 |
|
| 126 |
+
defaults = list(inputs.values())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
return desc, gallery, *defaults, metrics, fig, readout, ev_md, meth_md
|
| 128 |
|
| 129 |
|
| 130 |
+
def recalc(period, baseline_volume, avg_rev_per_study, mins_saved_per_study,
|
|
|
|
| 131 |
cost_per_rad_hour, baseline_repeats, cost_per_repeat,
|
| 132 |
repeat_reduction_pct, program_cost_annual):
|
| 133 |
+
metrics = compute_roi(period, baseline_volume, avg_rev_per_study, mins_saved_per_study,
|
| 134 |
+
cost_per_rad_hour, baseline_repeats, cost_per_repeat,
|
| 135 |
+
repeat_reduction_pct, program_cost_annual)
|
|
|
|
|
|
|
|
|
|
| 136 |
fig = waterfall_plot(metrics)
|
| 137 |
readout = (
|
| 138 |
+
f"**Gleamer Bone View snapshot** β Net benefit: {metrics['Net benefit']:.0f}; "
|
| 139 |
f"ROI (annualized): {metrics['ROI % (annualized)']}%; "
|
| 140 |
f"Payback: {metrics['Payback (months)']} months.\n\n"
|
| 141 |
f"Operational: {metrics['Hours saved / year']:.0f} hours saved (~{metrics['FTE saved (β1920h/yr)']:.2f} FTE)."
|
| 142 |
)
|
| 143 |
return metrics, fig, readout
|
| 144 |
|
| 145 |
+
with gr.Blocks(title="Gleamer Bone View ROI β Interactive", fill_height=True) as demo:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
gr.Markdown("""
|
| 147 |
+
# Gleamer Bone View ROI β Interactive
|
| 148 |
+
**Clinician-first sandbox**: explore a sample fracture detection case, tweak workflow assumptions, and see financial, operational, and clinical impact instantly.
|
| 149 |
""")
|
| 150 |
|
| 151 |
period = gr.Radio(["Annual", "Monthly"], value="Annual", label="Time basis")
|
|
|
|
| 153 |
with gr.Tabs():
|
| 154 |
with gr.Tab("Explore"):
|
| 155 |
desc = gr.Markdown()
|
| 156 |
+
gallery = gr.Gallery(label="Sample case", columns=3, height=320, show_label=True)
|
| 157 |
|
| 158 |
with gr.Tab("ROI Simulator"):
|
| 159 |
with gr.Row():
|
| 160 |
with gr.Column(scale=1, min_width=360):
|
| 161 |
+
baseline_volume = gr.Slider(0, 100000, value=15000, step=50, label="Annual volume")
|
| 162 |
avg_rev_per_study = gr.Slider(0, 50000, value=6000, step=50, label="Avg revenue per study (info)")
|
| 163 |
mins_saved_per_study = gr.Slider(0, 60, value=5, step=1, label="Minutes saved per study")
|
| 164 |
cost_per_rad_hour = gr.Slider(0, 20000, value=5200, step=50, label="Radiologist cost/hour")
|
| 165 |
+
baseline_repeats = gr.Slider(0, 100000, value=750, step=10, label="Baseline repeats/year")
|
| 166 |
+
cost_per_repeat = gr.Slider(0, 50000, value=6000, step=50, label="Cost per repeat")
|
| 167 |
repeat_reduction_pct = gr.Slider(0, 100, value=10, step=1, label="Repeat reduction with AI (%)")
|
| 168 |
program_cost_annual = gr.Slider(0, 10000000, value=1200000, step=10000, label="Program cost (annual)")
|
| 169 |
with gr.Column(scale=1):
|
|
|
|
| 177 |
with gr.Tab("Methodology"):
|
| 178 |
methodology_md = gr.Markdown()
|
| 179 |
|
| 180 |
+
period.change(init, [period], [desc, gallery, baseline_volume, avg_rev_per_study, mins_saved_per_study,
|
| 181 |
+
cost_per_rad_hour, baseline_repeats, cost_per_repeat, repeat_reduction_pct, program_cost_annual,
|
| 182 |
+
metrics, chart, readout, evidence_md, methodology_md])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 183 |
|
| 184 |
for comp in [baseline_volume, avg_rev_per_study, mins_saved_per_study, cost_per_rad_hour,
|
| 185 |
baseline_repeats, cost_per_repeat, repeat_reduction_pct, program_cost_annual]:
|
| 186 |
+
comp.change(recalc, [period, baseline_volume, avg_rev_per_study, mins_saved_per_study,
|
| 187 |
+
cost_per_rad_hour, baseline_repeats, cost_per_repeat, repeat_reduction_pct, program_cost_annual],
|
| 188 |
+
[metrics, chart, readout])
|
| 189 |
+
|
| 190 |
+
gr.on(load=True, fn=init, inputs=[period],
|
| 191 |
+
outputs=[desc, gallery, baseline_volume, avg_rev_per_study, mins_saved_per_study,
|
| 192 |
+
cost_per_rad_hour, baseline_repeats, cost_per_repeat, repeat_reduction_pct, program_cost_annual,
|
| 193 |
+
metrics, chart, readout, evidence_md, methodology_md])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
|
| 195 |
if __name__ == "__main__":
|
| 196 |
+
demo.launch()
|
| 197 |
+
|
| 198 |
+
# ------------------------------
|
| 199 |
+
# requirements.txt
|
| 200 |
+
# ------------------------------
|
| 201 |
+
# gradio>=4.44.0
|
| 202 |
+
# matplotlib
|