updated forseparating singlecell and spheroid
Browse files- S2FApp/app.py +47 -17
S2FApp/app.py
CHANGED
|
@@ -29,17 +29,37 @@ st.markdown("""
|
|
| 29 |
st.title("🔬 Shape2Force (S2F)")
|
| 30 |
st.caption("Predict force maps from bright field microscopy images")
|
| 31 |
|
| 32 |
-
# Folders
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
SAMPLE_EXTENSIONS = (".tif", ".tiff", ".png", ".jpg", ".jpeg")
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
# Sidebar: model configuration
|
| 45 |
with st.sidebar:
|
|
@@ -49,16 +69,22 @@ with st.sidebar:
|
|
| 49 |
["single_cell", "spheroid"],
|
| 50 |
format_func=lambda x: "Single cell" if x == "single_cell" else "Spheroid",
|
| 51 |
horizontal=False,
|
|
|
|
| 52 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
|
| 54 |
if ckp_files:
|
| 55 |
checkpoint = st.selectbox(
|
| 56 |
"Checkpoint",
|
| 57 |
ckp_files,
|
| 58 |
-
help="Select a .pth file from
|
| 59 |
)
|
| 60 |
else:
|
| 61 |
-
st.warning("No .pth files in ckp/
|
| 62 |
checkpoint = None
|
| 63 |
|
| 64 |
substrate_config = None
|
|
@@ -110,17 +136,21 @@ if img_source == "Upload":
|
|
| 110 |
img = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)
|
| 111 |
uploaded.seek(0) # reset for potential re-read
|
| 112 |
else:
|
|
|
|
|
|
|
|
|
|
| 113 |
if sample_files:
|
| 114 |
selected_sample = st.selectbox(
|
| 115 |
"Select sample image",
|
| 116 |
sample_files,
|
| 117 |
format_func=lambda x: x,
|
|
|
|
| 118 |
)
|
| 119 |
if selected_sample:
|
| 120 |
sample_path = os.path.join(sample_folder, selected_sample)
|
| 121 |
img = cv2.imread(sample_path, cv2.IMREAD_GRAYSCALE)
|
| 122 |
-
# Show sample thumbnails
|
| 123 |
-
st.caption("Sample images
|
| 124 |
n_cols = min(4, len(sample_files))
|
| 125 |
cols = st.columns(n_cols)
|
| 126 |
for i, fname in enumerate(sample_files[:8]): # show up to 8
|
|
@@ -130,13 +160,13 @@ else:
|
|
| 130 |
if sample_img is not None:
|
| 131 |
st.image(sample_img, caption=fname, width='content')
|
| 132 |
else:
|
| 133 |
-
st.info("No sample images
|
| 134 |
|
| 135 |
run = st.button("Run prediction", type="primary")
|
| 136 |
has_image = img is not None
|
| 137 |
|
| 138 |
if run and checkpoint and has_image:
|
| 139 |
-
st.markdown(f"**Using checkpoint:** `{checkpoint}`")
|
| 140 |
with st.spinner("Loading model and predicting..."):
|
| 141 |
try:
|
| 142 |
from predictor import S2FPredictor
|
|
@@ -203,4 +233,4 @@ elif run and not has_image:
|
|
| 203 |
|
| 204 |
# Footer
|
| 205 |
st.sidebar.divider()
|
| 206 |
-
st.sidebar.caption("
|
|
|
|
| 29 |
st.title("🔬 Shape2Force (S2F)")
|
| 30 |
st.caption("Predict force maps from bright field microscopy images")
|
| 31 |
|
| 32 |
+
# Folders: checkpoints in subfolders by model type (single_cell / spheroid)
|
| 33 |
+
ckp_base = os.path.join(S2F_ROOT, "ckp")
|
| 34 |
+
# Fallback: use project root ckp when running from S2F repo (ckp at S2F/ckp/)
|
| 35 |
+
if not os.path.isdir(ckp_base):
|
| 36 |
+
project_root = os.path.dirname(S2F_ROOT)
|
| 37 |
+
if os.path.isdir(os.path.join(project_root, "ckp")):
|
| 38 |
+
ckp_base = os.path.join(project_root, "ckp")
|
| 39 |
+
ckp_single_cell = os.path.join(ckp_base, "single_cell")
|
| 40 |
+
ckp_spheroid = os.path.join(ckp_base, "spheroid")
|
| 41 |
+
sample_base = os.path.join(S2F_ROOT, "samples")
|
| 42 |
+
sample_single_cell = os.path.join(sample_base, "single_cell")
|
| 43 |
+
sample_spheroid = os.path.join(sample_base, "spheroid")
|
| 44 |
+
|
| 45 |
SAMPLE_EXTENSIONS = (".tif", ".tiff", ".png", ".jpg", ".jpeg")
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def get_ckp_files_for_model(model_type):
|
| 49 |
+
"""Return list of .pth files in the checkpoint folder for the given model type."""
|
| 50 |
+
folder = ckp_single_cell if model_type == "single_cell" else ckp_spheroid
|
| 51 |
+
if os.path.isdir(folder):
|
| 52 |
+
return sorted([f for f in os.listdir(folder) if f.endswith(".pth")])
|
| 53 |
+
return []
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def get_sample_files_for_model(model_type):
|
| 57 |
+
"""Return list of sample images in the sample folder for the given model type."""
|
| 58 |
+
folder = sample_single_cell if model_type == "single_cell" else sample_spheroid
|
| 59 |
+
if os.path.isdir(folder):
|
| 60 |
+
return sorted([f for f in os.listdir(folder)
|
| 61 |
+
if f.lower().endswith(SAMPLE_EXTENSIONS)])
|
| 62 |
+
return []
|
| 63 |
|
| 64 |
# Sidebar: model configuration
|
| 65 |
with st.sidebar:
|
|
|
|
| 69 |
["single_cell", "spheroid"],
|
| 70 |
format_func=lambda x: "Single cell" if x == "single_cell" else "Spheroid",
|
| 71 |
horizontal=False,
|
| 72 |
+
help="Single cell: substrate-aware force prediction. Spheroid: spheroid force maps.",
|
| 73 |
)
|
| 74 |
+
st.caption(f"Inference mode: **{'Single cell' if model_type == 'single_cell' else 'Spheroid'}**")
|
| 75 |
+
|
| 76 |
+
ckp_files = get_ckp_files_for_model(model_type)
|
| 77 |
+
ckp_folder = ckp_single_cell if model_type == "single_cell" else ckp_spheroid
|
| 78 |
+
ckp_subfolder_name = "single_cell" if model_type == "single_cell" else "spheroid"
|
| 79 |
|
| 80 |
if ckp_files:
|
| 81 |
checkpoint = st.selectbox(
|
| 82 |
"Checkpoint",
|
| 83 |
ckp_files,
|
| 84 |
+
help=f"Select a .pth file from ckp/{ckp_subfolder_name}/",
|
| 85 |
)
|
| 86 |
else:
|
| 87 |
+
st.warning(f"No .pth files in ckp/{ckp_subfolder_name}/. Add checkpoints to load.")
|
| 88 |
checkpoint = None
|
| 89 |
|
| 90 |
substrate_config = None
|
|
|
|
| 136 |
img = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)
|
| 137 |
uploaded.seek(0) # reset for potential re-read
|
| 138 |
else:
|
| 139 |
+
sample_files = get_sample_files_for_model(model_type)
|
| 140 |
+
sample_folder = sample_single_cell if model_type == "single_cell" else sample_spheroid
|
| 141 |
+
sample_subfolder_name = "single_cell" if model_type == "single_cell" else "spheroid"
|
| 142 |
if sample_files:
|
| 143 |
selected_sample = st.selectbox(
|
| 144 |
"Select sample image",
|
| 145 |
sample_files,
|
| 146 |
format_func=lambda x: x,
|
| 147 |
+
key=f"sample_{model_type}",
|
| 148 |
)
|
| 149 |
if selected_sample:
|
| 150 |
sample_path = os.path.join(sample_folder, selected_sample)
|
| 151 |
img = cv2.imread(sample_path, cv2.IMREAD_GRAYSCALE)
|
| 152 |
+
# Show sample thumbnails (filtered by model type)
|
| 153 |
+
st.caption(f"Sample images from `samples/{sample_subfolder_name}/`")
|
| 154 |
n_cols = min(4, len(sample_files))
|
| 155 |
cols = st.columns(n_cols)
|
| 156 |
for i, fname in enumerate(sample_files[:8]): # show up to 8
|
|
|
|
| 160 |
if sample_img is not None:
|
| 161 |
st.image(sample_img, caption=fname, width='content')
|
| 162 |
else:
|
| 163 |
+
st.info(f"No sample images in samples/{sample_subfolder_name}/. Add images or use Upload.")
|
| 164 |
|
| 165 |
run = st.button("Run prediction", type="primary")
|
| 166 |
has_image = img is not None
|
| 167 |
|
| 168 |
if run and checkpoint and has_image:
|
| 169 |
+
st.markdown(f"**Using checkpoint:** `ckp/{ckp_subfolder_name}/{checkpoint}`")
|
| 170 |
with st.spinner("Loading model and predicting..."):
|
| 171 |
try:
|
| 172 |
from predictor import S2FPredictor
|
|
|
|
| 233 |
|
| 234 |
# Footer
|
| 235 |
st.sidebar.divider()
|
| 236 |
+
st.sidebar.caption("Checkpoints: ckp/single_cell/ and ckp/spheroid/. Samples: samples/single_cell/ and samples/spheroid/")
|