Skip to content

Commit 3b4c6c4

Browse files
Update analyses
1 parent 9728951 commit 3b4c6c4

File tree

5 files changed

+165
-8
lines changed

5 files changed

+165
-8
lines changed

scripts/cooper/analysis/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
screenshots/
2+
20241108_3D_Imig_DATA_2014/
3+
*az*/
4+
mrc_files/
5+
imig_data/
6+
results/
7+
*.xlsx
8+
*.tsv
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import os
2+
import tempfile
3+
from glob import glob
4+
from subprocess import run
5+
from shutil import copyfile
6+
7+
import h5py
8+
import pandas as pd
9+
10+
from synaptic_reconstruction.imod.to_imod import write_segmentation_to_imod
11+
from scipy.ndimage import binary_dilation, binary_closing
12+
13+
14+
def check_imod(tomo_path, mod_path):
15+
run(["imod", tomo_path, mod_path])
16+
17+
18+
def export_all_to_imod(check_input=True, check_export=True):
19+
files = sorted(glob("./az_segmentation/**/*.h5", recursive=True))
20+
mrc_root = "./mrc_files"
21+
output_folder = "./az_export/initial_model"
22+
23+
for ff in files:
24+
ds, fname = os.path.split(ff)
25+
ds = os.path.basename(ds)
26+
out_folder = os.path.join(output_folder, ds)
27+
out_path = os.path.join(out_folder, fname.replace(".h5", ".mod"))
28+
if os.path.exists(out_path):
29+
continue
30+
31+
os.makedirs(out_folder, exist_ok=True)
32+
mrc_path = os.path.join(mrc_root, ds, fname.replace(".h5", ".rec"))
33+
assert os.path.exists(mrc_path), mrc_path
34+
35+
with h5py.File(ff, "r") as f:
36+
seg = f["thin_az"][:]
37+
38+
seg = binary_dilation(seg, iterations=2)
39+
seg = binary_closing(seg, iterations=2)
40+
41+
write_segmentation_to_imod(mrc_path, seg, out_path)
42+
43+
if check_input:
44+
import napari
45+
from elf.io import open_file
46+
with open_file(mrc_path, "r") as f:
47+
raw = f["data"][:]
48+
v = napari.Viewer()
49+
v.add_image(raw)
50+
v.add_labels(seg)
51+
napari.run()
52+
53+
if check_export:
54+
check_imod(mrc_path, out_path)
55+
56+
57+
# https://bio3d.colorado.edu/imod/doc/man/reducecont.html
58+
def reduce_all_contours():
59+
pass
60+
61+
62+
# https://bio3d.colorado.edu/imod/doc/man/smoothsurf.html#TOP
63+
def smooth_all_surfaces(check_output=True):
64+
input_files = sorted(glob("./az_export/initial_model/**/*.mod", recursive=True))
65+
66+
mrc_root = "./mrc_files"
67+
output_folder = "./az_export/smoothed_model"
68+
for ff in input_files:
69+
ds, fname = os.path.split(ff)
70+
ds = os.path.basename(ds)
71+
out_folder = os.path.join(output_folder, ds)
72+
out_file = os.path.join(out_folder, fname)
73+
if os.path.exists(out_file):
74+
continue
75+
76+
os.makedirs(out_folder, exist_ok=True)
77+
run(["smoothsurf", ff, out_file])
78+
if check_output:
79+
mrc_path = os.path.join(mrc_root, ds, fname.replace(".mod", ".rec"))
80+
assert os.path.exists(mrc_path), mrc_path
81+
check_imod(mrc_path, out_file)
82+
83+
84+
def measure_surfaces():
85+
input_files = sorted(glob("./az_export/smoothed_model/**/*.mod", recursive=True))
86+
87+
result = {
88+
"Dataset": [],
89+
"Tomogram": [],
90+
"AZ Surface": [],
91+
}
92+
for ff in input_files:
93+
ds, fname = os.path.split(ff)
94+
ds = os.path.basename(ds)
95+
fname = os.path.splitext(fname)[0]
96+
97+
with tempfile.NamedTemporaryFile() as f_mesh, tempfile.NamedTemporaryFile() as f_mod:
98+
tmp_path_mesh = f_mesh.name
99+
tmp_path_mod = f_mod.name
100+
copyfile(ff, tmp_path_mesh)
101+
run(["imodmesh", tmp_path_mesh])
102+
run(["imodinfo", "-f", tmp_path_mod, tmp_path_mesh])
103+
area = None
104+
with open(tmp_path_mod, "r") as f:
105+
for line in f.readlines():
106+
line = line.strip()
107+
if line.startswith("Total mesh surface area"):
108+
area = float(line.split(" ")[-1])
109+
assert area is not None
110+
area /= 2
111+
112+
result["Dataset"].append(ds)
113+
result["Tomogram"].append(fname)
114+
result["AZ Surface"].append(area)
115+
116+
result = pd.DataFrame(result)
117+
result.to_excel("./az_measurements_all.xlsx", index=False)
118+
119+
120+
def filter_surfaces():
121+
all_results = pd.read_excel("./az_measurements_all.xlsx")
122+
man_tomos = pd.read_csv("./man_tomos.tsv")
123+
124+
man_results = all_results.merge(man_tomos[["Dataset", "Tomogram"]], on=["Dataset", "Tomogram"], how="inner")
125+
man_results.to_excel("./az_measuerements_manual.xlsx", index=False)
126+
127+
128+
def main():
129+
export_all_to_imod(False, False)
130+
smooth_all_surfaces(False)
131+
# measure_surfaces()
132+
filter_surfaces()
133+
134+
135+
if __name__ == "__main__":
136+
main()

scripts/inner_ear/analysis/analyze_distances.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
from common import get_all_measurements, get_measurements_with_annotation
99

10+
POOL_DICT = {"Docked-V": "MP-V", "MP-V": "MP-V", "RA-V": "RA-V"}
11+
1012

1113
def _plot_all(distances):
1214
pools = pd.unique(distances["pool"])
@@ -45,7 +47,7 @@ def _plot_selected(distances, save_path=None):
4547

4648
def _plot(pool_name, distance_col, structure_name, ax):
4749

48-
this_distances = distances[distances["pool"] == pool_name][["tomogram", "approach", distance_col]]
50+
this_distances = distances[distances["combined_pool"] == pool_name][["tomogram", "approach", distance_col]]
4951

5052
ax.set_title(f"{pool_name} to {structure_name}")
5153
sns.histplot(
@@ -88,8 +90,8 @@ def _plot(pool_name, distance_col, structure_name, ax):
8890
# NOTE: we over-ride a plot here, should not do this in the actual version
8991
_plot("MP-V", "pd_distance [nm]", "PD", axes[0, 0])
9092
_plot("MP-V", "boundary_distance [nm]", "AZ Membrane", axes[0, 1])
91-
_plot("Docked-V", "pd_distance [nm]", "PD", axes[1, 0])
92-
_plot("Docked-V", "boundary_distance [nm]", "AZ Membrane", axes[1, 0])
93+
# _plot("Docked-V", "pd_distance [nm]", "PD", axes[1, 0])
94+
# _plot("Docked-V", "boundary_distance [nm]", "AZ Membrane", axes[1, 0])
9395
_plot("RA-V", "ribbon_distance [nm]", "Ribbon", axes[1, 1])
9496

9597
fig.tight_layout()
@@ -103,16 +105,19 @@ def for_tomos_with_annotation(plot_all=True):
103105
["tomogram", "pool", "ribbon_distance [nm]", "pd_distance [nm]", "boundary_distance [nm]"]
104106
]
105107
manual_distances["approach"] = ["manual"] * len(manual_distances)
108+
manual_distances.insert(1, "combined_pool", manual_distances["pool"].replace(POOL_DICT))
106109

107110
semi_automatic_distances = semi_automatic_assignments[
108111
["tomogram", "pool", "ribbon_distance [nm]", "pd_distance [nm]", "boundary_distance [nm]"]
109112
]
110113
semi_automatic_distances["approach"] = ["semi_automatic"] * len(semi_automatic_distances)
114+
semi_automatic_distances.insert(1, "combined_pool", semi_automatic_distances["pool"].replace(POOL_DICT))
111115

112116
proofread_distances = proofread_assignments[
113117
["tomogram", "pool", "ribbon_distance [nm]", "pd_distance [nm]", "boundary_distance [nm]"]
114118
]
115119
proofread_distances["approach"] = ["proofread"] * len(proofread_distances)
120+
proofread_distances.insert(1, "combined_pool", proofread_distances["pool"].replace(POOL_DICT))
116121

117122
distances = pd.concat([manual_distances, semi_automatic_distances, proofread_distances])
118123
if plot_all:
@@ -129,11 +134,13 @@ def for_all_tomos(plot_all=True):
129134
["tomogram", "pool", "ribbon_distance [nm]", "pd_distance [nm]", "boundary_distance [nm]"]
130135
]
131136
semi_automatic_distances["approach"] = ["semi_automatic"] * len(semi_automatic_distances)
137+
semi_automatic_distances.insert(1, "combined_pool", semi_automatic_distances["pool"].replace(POOL_DICT))
132138

133139
proofread_distances = proofread_assignments[
134140
["tomogram", "pool", "ribbon_distance [nm]", "pd_distance [nm]", "boundary_distance [nm]"]
135141
]
136142
proofread_distances["approach"] = ["proofread"] * len(proofread_distances)
143+
proofread_distances.insert(1, "combined_pool", proofread_distances["pool"].replace(POOL_DICT))
137144

138145
distances = pd.concat([semi_automatic_distances, proofread_distances])
139146
if plot_all:

scripts/inner_ear/analysis/analyze_vesicle_diameters.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
from common import get_finished_tomos
1414

15+
POOL_DICT = {"Docked-V": "MP-V", "MP-V": "MP-V", "RA-V": "RA-V"}
16+
1517
sys.path.append("../processing")
1618

1719

@@ -42,6 +44,7 @@ def aggregate_diameters(data_root, table, save_path, get_tab, include_names, she
4244
radius_table.append(this_tab)
4345

4446
radius_table = pd.concat(radius_table)
47+
radius_table.insert(1, "combined_pool", radius_table["pool"].replace(POOL_DICT))
4548

4649
print("Saving table for", len(radius_table), "vesicles to", save_path, sheet_name)
4750
if os.path.exists(save_path):
@@ -91,11 +94,13 @@ def aggregate_diameters_imod(data_root, table, save_path, include_names, sheet_n
9194
except AssertionError:
9295
continue
9396

97+
# Determined from matching the size of vesicles in IMOD.
98+
radius_factor = 0.85
9499
this_tab = pd.DataFrame({
95100
"tomogram": [tomo_name] * len(radii),
96101
"pool": [label_names[label_id] for label_id in labels],
97-
"radius [nm]": radii,
98-
"diameter [nm]": 2 * radii,
102+
"radius [nm]": radii * radius_factor,
103+
"diameter [nm]": 2 * radii * radius_factor,
99104
})
100105
radius_table.append(this_tab)
101106

synaptic_reconstruction/imod/to_imod.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def _pad(inp, n=3):
182182

183183
def write_segmentation_to_imod_as_points(
184184
mrc_path: str,
185-
segmentation_path: str,
185+
segmentation: Union[str, np.ndarray],
186186
output_path: str,
187187
min_radius: Union[int, float],
188188
radius_factor: float = 1.0,
@@ -194,7 +194,7 @@ def write_segmentation_to_imod_as_points(
194194
195195
Args:
196196
mrc_path: Filepath to the mrc volume that was segmented.
197-
segmentation_path: Filepath to the segmentation stored as .tif.
197+
segmentation: The segmentation (either as numpy array or filepath to a .tif file).
198198
output_path: Where to save the .mod file.
199199
min_radius: Minimum radius for export.
200200
radius_factor: Factor for increasing the radius to account for too small exported spheres.
@@ -211,7 +211,8 @@ def write_segmentation_to_imod_as_points(
211211
resolution = [res / 10 for res in resolution]
212212

213213
# Extract the center coordinates and radii from the segmentation.
214-
segmentation = imageio.imread(segmentation_path)
214+
if isinstance(segmentation, str):
215+
segmentation = imageio.imread(segmentation)
215216
coordinates, radii = convert_segmentation_to_spheres(
216217
segmentation, resolution=resolution, radius_factor=radius_factor, estimate_radius_2d=estimate_radius_2d
217218
)

0 commit comments

Comments
 (0)