Skip to content

Commit ab4e33c

Browse files
Implement synapse export for imaris
1 parent db7b524 commit ab4e33c

File tree

2 files changed

+96
-1
lines changed

2 files changed

+96
-1
lines changed

scripts/export_lower_resolution.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def export_lower_resolution(args):
4545
if args.filter_by_components is not None:
4646
data = filter_component(fs, data, args.cochlea, channel, args.filter_by_components)
4747
if args.binarize:
48-
data = (data > 0).astype("uint8")
48+
data = (data > 0).astype("uint16")
4949
tifffile.imwrite(out_path, data, bigtiff=True, compression="zlib")
5050

5151

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import argparse
2+
import json
3+
import os
4+
5+
import numpy as np
6+
import pandas as pd
7+
import tifffile
8+
import zarr
9+
10+
from flamingo_tools.s3_utils import BUCKET_NAME, SERVICE_ENDPOINT, create_s3_target, get_s3_path
11+
from skimage.morphology import ball
12+
from tqdm import tqdm
13+
14+
15+
def export_synapse_detections(cochlea, scale, output_folder, synapse_name, reference_ihcs, max_dist, radius):
16+
s3 = create_s3_target()
17+
18+
content = s3.open(f"{BUCKET_NAME}/{cochlea}/dataset.json", mode="r", encoding="utf-8")
19+
info = json.loads(content.read())
20+
sources = info["sources"]
21+
22+
# Load the synapse table.
23+
syn = sources[synapse_name]["spots"]
24+
rel_path = syn["tableData"]["tsv"]["relativePath"]
25+
table_content = s3.open(os.path.join(BUCKET_NAME, cochlea, rel_path, "default.tsv"), mode="rb")
26+
27+
syn_table = pd.read_csv(table_content, sep="\t")
28+
syn_table = syn_table[syn_table.distance_to_ihc <= max_dist]
29+
30+
# Get the reference segmentation info.
31+
reference_seg_info = sources[reference_ihcs]["segmentation"]
32+
33+
# Get the segmentation table.
34+
rel_path = reference_seg_info["tableData"]["tsv"]["relativePath"]
35+
seg_table_content = s3.open(os.path.join(BUCKET_NAME, cochlea, rel_path, "default.tsv"), mode="rb")
36+
seg_table = pd.read_csv(seg_table_content, sep="\t")
37+
38+
# Only keep synapses that match to segmented IHCs of the main component.
39+
valid_ihcs = seg_table[seg_table.component_labels == 1].label_id
40+
syn_table = syn_table[syn_table.matched_ihc.isin(valid_ihcs)]
41+
42+
# Get the reference shape at the given scale level.
43+
seg_path = os.path.join(cochlea, reference_seg_info["imageData"]["ome.zarr"]["relativePath"])
44+
s3_store, _ = get_s3_path(seg_path, bucket_name=BUCKET_NAME, service_endpoint=SERVICE_ENDPOINT)
45+
input_key = f"s{scale}"
46+
with zarr.open(s3_store, mode="r") as f:
47+
shape = f[input_key].shape
48+
49+
# Scale the coordinates according to the scale level.
50+
resolution = 0.38
51+
coordinates = syn_table[["z", "y", "x"]].values
52+
coordinates /= resolution
53+
coordinates /= (2 ** scale)
54+
coordinates = np.round(coordinates, 0).astype("int")
55+
56+
# Create the output.
57+
output = np.zeros(shape, dtype="uint16")
58+
mask = ball(radius).astype(bool)
59+
60+
for coord in tqdm(coordinates, desc="Writing synapses to volume"):
61+
bb = tuple(slice(c - radius, c + radius + 1) for c in coord)
62+
try:
63+
output[bb][mask] = 1
64+
except IndexError:
65+
print("Index error for", coord)
66+
continue
67+
68+
# Write the output.
69+
out_folder = os.path.join(output_folder, cochlea, f"scale{scale}")
70+
os.makedirs(out_folder, exist_ok=True)
71+
out_path = os.path.join(out_folder, f"{synapse_name}.tif")
72+
print("Writing synapses to", out_path)
73+
tifffile.imwrite(out_path, output, bigtiff=True, compression="zlib")
74+
75+
76+
def main():
77+
parser = argparse.ArgumentParser()
78+
parser.add_argument("--cochlea", "-c", required=True)
79+
parser.add_argument("--scale", "-s", type=int, required=True)
80+
parser.add_argument("--output_folder", "-o", required=True)
81+
parser.add_argument("--synapse_name", default="synapse_v3_ihc_v4")
82+
parser.add_argument("--reference_ihcs", default="IHC_v4")
83+
parser.add_argument("--max_dist", type=float, default=3.0)
84+
parser.add_argument("--radius", type=int, default=3)
85+
args = parser.parse_args()
86+
87+
export_synapse_detections(
88+
args.cochlea, args.scale, args.output_folder,
89+
args.synapse_name, args.reference_ihcs,
90+
args.max_dist, args.radius
91+
)
92+
93+
94+
if __name__ == "__main__":
95+
main()

0 commit comments

Comments
 (0)