Skip to content

Commit 15cbd62

Browse files
committed
Fix mesh roof height to correctly classify nuclei at all
Z-slices - Changed roof height calculation to use max(mesh_max_z, max_scaled_z) * 1.05 - Roof now placed above maximum possible scaled Z coordinate of imaging volume - Removed Z<27 filters from visualization and analysis scripts - Fixes incorrect 'outside' classification for nuclei at Z >= 26
1 parent 403839b commit 15cbd62

File tree

3 files changed

+13
-7
lines changed

3 files changed

+13
-7
lines changed

EMT_data_analysis/analysis_scripts/Analysis_tools.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ def load_io_data(df):
8888
]]
8989

9090
df_io = io.load_inside_outside_classification()
91-
df_io = df_io[df_io['Z']<27]
9291

9392
dfio_merged=pd.merge(df_io, df_info, on='Data ID', suffixes=['','_remove'])
9493
remove = [col for col in dfio_merged.columns if 'remove' in col]

EMT_data_analysis/analysis_scripts/Nuclei_localization.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,22 @@ def localize_for_timepoint(
154154
v_idx = mesh.find_closest_point(vert)
155155
mesh.points[v_idx] = new_vert
156156

157+
# transpose segmentation to XYZ coordinates and set z-scale for isotropic resolution
158+
seg = seg.transpose(2, 1, 0)
159+
scale = 2.88 / 0.271
160+
161+
# Calculate roof height to enclose all nuclei in the imaging volume
162+
# The roof must be above the maximum possible scaled Z coordinate
163+
max_z_slices = seg.shape[2] # Number of Z slices in imaging volume
164+
max_scaled_z = max_z_slices * scale # Maximum Z after scaling to isotropic
165+
157166
vert, faces = mesh.points, mesh.faces.reshape(mesh.n_faces, 4)[:,1:]
158167
vert_up = np.zeros_like(vert)
159168
np.copyto(vert_up, vert)
160-
vert_up[:, 2] = max(vert[:,2])*.9
169+
# Place roof above the maximum scaled Z coordinate of the imaging volume
170+
# This ensures all nuclei (including those at high Z) are enclosed
171+
roof_height = max(max(vert[:,2]), max_scaled_z) * 1.05 # 5% margin above max
172+
vert_up[:, 2] = roof_height
161173
face_up = np.zeros_like(faces)
162174
np.copyto(face_up, faces)
163175

@@ -171,10 +183,6 @@ def localize_for_timepoint(
171183

172184
mesh = trimesh.Trimesh(vertices=vw, faces=fw)
173185

174-
# transpose segmentation to XYZ coordinates and set z-scale for isotropic resolution
175-
seg = seg.transpose(2, 1, 0)
176-
scale = 2.88 / 0.271
177-
178186
# initialize ray caster (for checking if a point is inside the mesh)
179187
rayCaster = trimesh.ray.ray_triangle.RayMeshIntersector(mesh)
180188

EMT_data_analysis/figure_generation/inside-outside_classification.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ def main(
4747
df_meta = df_meta[df_meta['Data ID'] == data_id]
4848
df = io.load_inside_outside_classification()
4949
df = df[df['Data ID'] == data_id]
50-
df = df[df['Z']<27]
5150

5251
tmp_dir = Path("./emt_tmp/nuclei_localization/")
5352
tmp_dir.mkdir(exist_ok=True, parents=True)

0 commit comments

Comments
 (0)