LiangLabUMB commited on
Commit
2f0e119
·
verified ·
1 Parent(s): de7263b

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -0
app.py CHANGED
@@ -926,6 +926,69 @@ def compute_summary(r1, r2, r3, r4):
926
  _block(CONC_PRESETS[0][1]), _block(CONC_PRESETS[1][1]))
927
 
928
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
929
  # ---------------------------------------------------------------------------
930
  # Training data export — feature extraction per cell
931
  # ---------------------------------------------------------------------------
@@ -1859,6 +1922,26 @@ with gr.Blocks(
1859
  summary_conc_2x, summary_conc_10x]
1860
  )
1861
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1862
 
1863
 
1864
  if __name__ == "__main__":
 
926
  _block(CONC_PRESETS[0][1]), _block(CONC_PRESETS[1][1]))
927
 
928
 
929
+ def export_summary_csv(r1, r2, r3, r4):
930
+ """One rectangular table: a row per tab plus a Mean row, concentrations
931
+ included on every row. Rectangular rather than sectioned so it loads
932
+ straight into pandas/Excel without hand-editing.
933
+
934
+ Returns (path_or_None, status_message).
935
+ """
936
+ results = [r1, r2, r3, r4]
937
+ valid = [(i + 1, r) for i, r in enumerate(results)
938
+ if r is not None and r.get("cell_count") is not None]
939
+ if not valid:
940
+ return None, "No data to export — run segmentation in at least one tab first."
941
+
942
+ def _avg(key):
943
+ vals = [r.get(key) for _, r in valid if r.get(key) is not None]
944
+ return (sum(vals) / len(vals)) if vals else 0.0
945
+
946
+ means = {k: _avg(k) for k in
947
+ ("cell_count", "live", "dead", "viab_percent", "confluency")}
948
+
949
+ header = ["Tab", "Total cells", "Live cells", "Dead cells",
950
+ "Viability (%)", "Confluency (%)"]
951
+ for name, mult in CONC_PRESETS:
952
+ header += [f"Live conc {name} [x{mult}] (cells/mL)",
953
+ f"Dead conc {name} [x{mult}] (cells/mL)",
954
+ f"Total conc {name} [x{mult}] (cells/mL)"]
955
+ header += ["Tabs averaged", "Note"]
956
+
957
+ def _row(label, total, live, dead, viab, conf, n_avg="", note=""):
958
+ row = [label,
959
+ f"{total:.0f}" if label != "Mean" else f"{total:.2f}",
960
+ f"{live:.0f}" if label != "Mean" else f"{live:.2f}",
961
+ f"{dead:.0f}" if label != "Mean" else f"{dead:.2f}",
962
+ f"{viab:.1f}", f"{conf:.1f}"]
963
+ for _, mult in CONC_PRESETS:
964
+ row += [f"{live * mult:.0f}", f"{dead * mult:.0f}", f"{total * mult:.0f}"]
965
+ row += [n_avg, note]
966
+ return row
967
+
968
+ rows = [_row(str(tab),
969
+ r.get("cell_count") or 0.0, r.get("live") or 0.0,
970
+ r.get("dead") or 0.0, r.get("viab_percent") or 0.0,
971
+ r.get("confluency") or 0.0)
972
+ for tab, r in valid]
973
+
974
+ n = len(valid)
975
+ note = ("" if n == 4 else
976
+ "Fewer than 4 squares averaged - not the standard hemocytometer convention")
977
+ rows.append(_row("Mean", means["cell_count"], means["live"], means["dead"],
978
+ means["viab_percent"], means["confluency"], str(n), note))
979
+
980
+ tmp = tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False, newline="")
981
+ w = csv.writer(tmp)
982
+ w.writerow(header)
983
+ w.writerows(rows)
984
+ tmp.close()
985
+
986
+ msg = f"Exported {n} tab{'s' if n > 1 else ''} + mean row."
987
+ if note:
988
+ msg += " ⚠ " + note
989
+ return tmp.name, msg
990
+
991
+
992
  # ---------------------------------------------------------------------------
993
  # Training data export — feature extraction per cell
994
  # ---------------------------------------------------------------------------
 
1922
  summary_conc_2x, summary_conc_10x]
1923
  )
1924
 
1925
+ gr.Markdown("### Export")
1926
+ with gr.Row():
1927
+ summary_export_btn = gr.Button("⬇️ Export summary CSV",
1928
+ variant="secondary")
1929
+ summary_export_info = gr.Textbox(label="Export status", lines=2,
1930
+ interactive=False)
1931
+ summary_export_file = gr.File(label="Download summary CSV", visible=False)
1932
+
1933
+ def on_export_summary(*tab_results):
1934
+ path, msg = export_summary_csv(*tab_results)
1935
+ if path is None:
1936
+ return gr.update(visible=False), msg
1937
+ return gr.update(value=path, visible=True), msg
1938
+
1939
+ summary_export_btn.click(
1940
+ fn=on_export_summary,
1941
+ inputs=result_states,
1942
+ outputs=[summary_export_file, summary_export_info]
1943
+ )
1944
+
1945
 
1946
 
1947
  if __name__ == "__main__":