Skip to content

Commit 3db9e24

Browse files
Implement exclusion of zero-mapped synapses from IHC segmentation
1 parent 251f309 commit 3db9e24

File tree

2 files changed

+29
-9
lines changed

2 files changed

+29
-9
lines changed

flamingo_tools/validation.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ def _parse_annotation_path(annotation_path):
3737
return cochlea, slice_id
3838

3939

40+
def _get_table(fs, cochlea, seg_name):
41+
internal_path = os.path.join(BUCKET_NAME, cochlea, "tables", seg_name, "default.tsv")
42+
with fs.open(internal_path, "r") as f:
43+
table = pd.read_csv(f, sep="\t")
44+
return table
45+
46+
4047
def fetch_data_for_evaluation(
4148
annotation_path: str,
4249
cache_path: Optional[str] = None,
@@ -45,6 +52,7 @@ def fetch_data_for_evaluation(
4552
components_for_postprocessing: Optional[List[int]] = None,
4653
cochlea: Optional[str] = None,
4754
extra_data: Optional[str] = None,
55+
exclude_zero_synapse_count: bool = False,
4856
) -> Tuple[np.ndarray, pd.DataFrame]:
4957
"""Fetch segmentation from S3 matching the annotation path for evaluation.
5058
@@ -57,6 +65,8 @@ def fetch_data_for_evaluation(
5765
Choose [1] for the default componentn containing the helix.
5866
cochlea: Optional name of the cochlea.
5967
extra_data: Extra data to fetch.
68+
exclude_zero_synapse_count: Exclude cells that have zero synapses mapped.
69+
This is relevant for the IHC evaluation.
6070
6171
Returns:
6272
The segmentation downloaded from the S3 bucket.
@@ -96,20 +106,28 @@ def fetch_data_for_evaluation(
96106
with zarr.open(s3_store, mode="r") as f:
97107
segmentation = f[input_key][roi]
98108

109+
table = None
99110
if components_for_postprocessing is not None:
100111
# Filter the IDs so that only the ones part of 'components_for_postprocessing_remain'.
101-
102-
# First, we download the MoBIE table for this segmentation.
103-
internal_path = os.path.join(BUCKET_NAME, cochlea, "tables", seg_name, "default.tsv")
104-
with fs.open(internal_path, "r") as f:
105-
table = pd.read_csv(f, sep="\t")
112+
table = _get_table(fs, cochlea, seg_name)
106113

107114
# Then we get the ids for the components and us them to filter the segmentation.
108115
component_mask = np.isin(table.component_labels.values, components_for_postprocessing)
109116
keep_label_ids = table.label_id.values[component_mask].astype("int64")
110117
filter_mask = ~np.isin(segmentation, keep_label_ids)
111118
segmentation[filter_mask] = 0
112119

120+
# We also filter the table accordingly.
121+
table = table[table.label_id.isin(keep_label_ids)]
122+
123+
if exclude_zero_synapse_count:
124+
if table is None:
125+
table = _get_table(fs, cochlea, seg_name)
126+
127+
keep_label_ids = table.label_id[table.syn_per_IHC > 0].astype("int64")
128+
filter_mask = ~np.isin(segmentation, keep_label_ids)
129+
segmentation[filter_mask] = 0
130+
113131
segmentation, _, _ = relabel_sequential(segmentation)
114132

115133
# Cache it if required.

scripts/validation/IHCs/run_evaluation.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
ANNOTATION_FOLDERS = ["consensus_annotation"]
1313

1414

15-
def run_evaluation(root, annotation_folders, result_file, cache_folder, segmentation_name):
15+
def run_evaluation(root, annotation_folders, result_file, cache_folder, segmentation_name, exclude):
1616
results = {
1717
"annotator": [],
1818
"cochlea": [],
@@ -38,7 +38,8 @@ def run_evaluation(root, annotation_folders, result_file, cache_folder, segmenta
3838
segmentation, annotations = fetch_data_for_evaluation(
3939
annotation_path, components_for_postprocessing=[component],
4040
seg_name=segmentation_name,
41-
cache_path=None if cache_folder is None else os.path.join(cache_folder, f"{cochlea}_{slice_id}.tif")
41+
cache_path=None if cache_folder is None else os.path.join(cache_folder, f"{cochlea}_{slice_id}.tif"),
42+
exclude_zero_synapse_count=exclude,
4243
)
4344
scores = compute_scores_for_annotated_slice(segmentation, annotations, matching_tolerance=5)
4445
results["annotator"].append(annotator)
@@ -59,10 +60,11 @@ def main():
5960
parser.add_argument("-i", "--input", default=ROOT)
6061
parser.add_argument("--folders", default=ANNOTATION_FOLDERS)
6162
parser.add_argument("--result_file", default="results.csv")
62-
parser.add_argument("--segmentation_name", default="IHC_v4")
63+
parser.add_argument("--segmentation_name", default="IHC_v4c")
6364
parser.add_argument("--cache_folder")
65+
parser.add_argument("--exclude", action="store_true")
6466
args = parser.parse_args()
65-
run_evaluation(args.input, args.folders, args.result_file, args.cache_folder, args.segmentation_name)
67+
run_evaluation(args.input, args.folders, args.result_file, args.cache_folder, args.segmentation_name, args.exclude)
6668

6769

6870
if __name__ == "__main__":

0 commit comments

Comments
 (0)