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