Gillon, Lecoq et al. (2023): ROI matching over session orderings¶
Paper: doi:10.1038/s41597-023-02214-y. Target dataset DANDI:000336 (version 0.260325.1802), which does
not hold the paper's sessions; the data are read from DANDI:000037, version 0.230426.0054, as in
reproduce_gillon_2023.ipynb, whose header gives the reasons for both versions. This notebook tests one
claim, fig8-ordering-variation; the other claims are in the main notebook.
The paper matched ROIs across sessions with a custom-modified version of the Allen Institute's n-way matching package (github.com/AllenInstitute/ophys_nway_matching) that is not public, adding for dendrites that matches must overlap by at least 10 to 20% (Methods, ROI tracking across sessions). The claims file sets the test: the public package at a pinned commit (here 9d02ff5abca4580caad0e13bab60355ff91d4b62, the latest, version 0.6.0) with default parameters, over the six orderings of each tracked mouse's three tracked sessions, with the overlap threshold at (a) 10% or (b) 20% for dendritic planes, and the variation over orderings measured as (i) range over mean or (ii) SD over mean. The 13 tracked mice are the 11 analysed mice (sessions 1 to 3) and 411400 and 412933, whose sessions 1 to 3 failed QC and which are tracked in sessions 4 to 6; results are given for the 11 analysed mice and for all 13.
Inputs to the package per session: the ROI masks of the file (image_mask > 0) and the plane's max
projection image (max_projection), which stands in for the average projection the package expects
(the files hold no average projection).
import os
import time
import numpy as np
import pandas as pd
import credassign as ca
pd.set_option("display.width", 200)
T0 = time.time()
mouse_df = ca.read_mouse_df()
analysed = mouse_df[(mouse_df.pass_fail == "P") & mouse_df.sess_n.between(1, 3)]
# The criterion asks for each tracked mouse. The two mice whose sessions 1 to 3 failed QC (411400 and
# 412933) are tracked in their sessions 4 to 6 (code table, nrois_tracked > 0); they are run too, as a
# second set beside the 11 analysed mice.
extra = mouse_df[~mouse_df.mouseid.isin(analysed.mouseid) & (mouse_df.pass_fail == "P") & (mouse_df.nrois_tracked > 0)]
tracked_sessions = pd.concat([analysed, extra]).sort_values(["mouseid", "sess_n"])
basic = ca.list_assets()
basic = basic[basic.path.str.endswith("_behavior+ophys.nwb")]
basic["session"] = basic.path.str.extract(r"_ses-(\d+)_")[0]
sessions_by_mouse, rows = {}, []
for mouse, g in tracked_sessions.groupby("mouseid"):
sessions_by_mouse[str(mouse)] = []
for sid in g.sessid.astype(str):
f = ca.open_h5(basic.loc[basic.session == sid, "asset_id"].iloc[0])
masks, img = ca.roi_masks(f)
tracking = f["processing/ophys/ImageSegmentation/PlaneSegmentation/tracking_id"][:]
f.close()
sessions_by_mouse[str(mouse)].append((sid, masks, img))
rows.append({"mouse": str(mouse), "analysed": mouse in set(analysed.mouseid), "session": sid,
"sess_n": int(g.loc[g.sessid.astype(str) == sid, "sess_n"].iloc[0]), "plane": g.plane.iloc[0], "line": g.line.iloc[0],
"rois": len(masks), "empty_masks": int((masks.sum(axis=(1, 2)) == 0).sum()),
"mask_px_median": int(np.median(masks.sum(axis=(1, 2)))), "image": img.shape,
"image_range": (int(img.min()), int(img.max())), "tracked_in_file": int(np.sum(~np.isnan(tracking)))})
loaded = pd.DataFrame(rows)
print(loaded.to_string(index=False))
print(len(loaded), "sessions from", loaded.mouse.nunique(), "mice (", loaded[loaded.analysed].mouse.nunique(), "analysed); loaded in",
round((time.time() - T0) / 60, 1), "min")
mouse analysed session sess_n plane line rois empty_masks mask_px_median image image_range tracked_in_file 408021 True 758519303 1 soma L23-Cux2 96 0 181 (512, 512) (0, 255) 59 408021 True 759189643 2 soma L23-Cux2 74 0 174 (512, 512) (0, 255) 59 408021 True 759660390 3 soma L23-Cux2 107 0 169 (512, 512) (0, 255) 59 411400 False 761730740 4 dend L5-Rbp4 630 0 84 (512, 512) (0, 255) 162 411400 False 762415169 5 dend L5-Rbp4 637 0 90 (512, 512) (0, 255) 162 411400 False 763646681 6 dend L5-Rbp4 597 0 85 (512, 512) (0, 255) 162 411424 True 761624763 1 soma L23-Cux2 87 0 176 (512, 512) (0, 255) 55 411424 True 761944562 2 soma L23-Cux2 90 0 167 (512, 512) (0, 255) 55 411424 True 762250376 3 soma L23-Cux2 80 0 169 (512, 512) (0, 255) 55 411771 True 760260459 1 soma L5-Rbp4 90 0 193 (512, 512) (0, 255) 47 411771 True 760659782 2 soma L5-Rbp4 70 0 195 (512, 512) (0, 255) 47 411771 True 761269197 3 soma L5-Rbp4 79 0 215 (512, 512) (0, 255) 47 412933 False 766755831 4 dend L23-Cux2 344 0 65 (512, 512) (0, 255) 98 412933 False 767254594 5 dend L23-Cux2 168 0 60 (512, 512) (0, 255) 98 412933 False 768807532 6 dend L23-Cux2 250 0 56 (512, 512) (0, 255) 98 413663 True 764704289 1 dend L23-Cux2 628 0 59 (512, 512) (0, 255) 136 413663 True 765193831 2 dend L23-Cux2 348 0 56 (512, 512) (0, 255) 136 413663 True 766502238 3 dend L23-Cux2 512 0 55 (512, 512) (0, 255) 136 418779 True 777496949 1 soma L5-Rbp4 15 0 188 (512, 512) (0, 255) 12 418779 True 778374308 2 soma L5-Rbp4 26 0 129 (512, 512) (0, 255) 12 418779 True 779152062 3 soma L5-Rbp4 29 0 141 (512, 512) (0, 255) 12 420011 True 777914830 1 dend L5-Rbp4 205 0 60 (512, 512) (0, 255) 51 420011 True 778864809 2 dend L5-Rbp4 159 0 51 (512, 512) (0, 255) 51 420011 True 779650018 3 dend L5-Rbp4 182 0 49 (512, 512) (0, 255) 51 433414 True 826187862 1 dend L23-Cux2 727 0 36 (512, 512) (0, 255) 118 433414 True 826773996 2 dend L23-Cux2 300 0 45 (512, 512) (0, 255) 118 433414 True 827833392 3 dend L23-Cux2 333 0 40 (512, 512) (0, 255) 118 433448 True 826338612 1 dend L5-Rbp4 1636 0 43 (512, 512) (0, 255) 112 433448 True 826819032 2 dend L5-Rbp4 445 0 66 (512, 512) (0, 255) 112 433448 True 828816509 3 dend L5-Rbp4 496 0 65 (512, 512) (0, 255) 112 433451 True 823453391 1 dend L5-Rbp4 966 0 87 (512, 512) (0, 255) 353 433451 True 824434038 2 dend L5-Rbp4 1029 0 88 (512, 512) (0, 255) 353 433451 True 825180479 3 dend L5-Rbp4 986 0 77 (512, 512) (0, 255) 353 433458 True 826659257 1 soma L5-Rbp4 99 0 196 (512, 512) (0, 255) 70 433458 True 827300090 2 soma L5-Rbp4 87 0 222 (512, 512) (0, 255) 70 433458 True 828475005 3 soma L5-Rbp4 97 0 220 (512, 512) (0, 255) 70 440889 True 832883243 1 soma L23-Cux2 224 0 178 (512, 512) (0, 255) 147 440889 True 833704570 2 soma L23-Cux2 224 0 174 (512, 512) (0, 255) 147 440889 True 834403597 3 soma L23-Cux2 210 0 174 (512, 512) (0, 255) 147 39 sessions from 13 mice ( 11 analysed); loaded in 2.8 min
fig8-ordering-variation¶
The number of matched ROIs depends on the order in which sessions are aligned, and this variation is far smaller for somata than for dendrites.
Somatic planes are matched without an overlap threshold (the Methods add it for dendrites only); dendritic planes with the 10% and 20% thresholds, and without one as a variant. A matched ROI is a match across all three sessions.
t = time.time()
counts = ca.ordering_counts(sessions_by_mouse, thresholds=(0.1, 0.2), workers=4)
print("matching ran in", round((time.time() - t) / 60, 1), "min")
counts = counts.merge(loaded.groupby("mouse").agg(plane=("plane", "first"), line=("line", "first")), on="mouse")
print(counts.to_string(index=False))
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
matching ran in 20.3 min mouse order all no_direct_link iou>=0.1 linked iou>=0.1 iou>=0.2 linked iou>=0.2 plane line 408021 1-2-3 59 2 51 52 51 52 soma L23-Cux2 408021 1-3-2 59 2 51 52 51 52 soma L23-Cux2 408021 2-1-3 60 3 51 52 51 52 soma L23-Cux2 408021 2-3-1 60 3 51 52 51 52 soma L23-Cux2 408021 3-1-2 59 2 51 53 51 53 soma L23-Cux2 408021 3-2-1 59 2 51 53 51 53 soma L23-Cux2 411400 1-2-3 393 148 86 93 77 81 dend L5-Rbp4 411400 1-3-2 392 142 84 91 73 76 dend L5-Rbp4 411400 2-1-3 397 151 88 104 78 90 dend L5-Rbp4 411400 2-3-1 399 156 87 102 76 88 dend L5-Rbp4 411400 3-1-2 399 152 85 97 75 86 dend L5-Rbp4 411400 3-2-1 399 150 88 99 76 86 dend L5-Rbp4 411424 1-2-3 56 1 42 42 42 42 soma L23-Cux2 411424 1-3-2 56 1 42 42 42 42 soma L23-Cux2 411424 2-1-3 56 1 42 42 42 42 soma L23-Cux2 411424 2-3-1 56 1 42 42 42 42 soma L23-Cux2 411424 3-1-2 56 1 42 42 42 42 soma L23-Cux2 411424 3-2-1 56 1 42 42 42 42 soma L23-Cux2 411771 1-2-3 48 3 33 35 33 35 soma L5-Rbp4 411771 1-3-2 48 3 33 35 33 35 soma L5-Rbp4 411771 2-1-3 48 3 33 34 33 34 soma L5-Rbp4 411771 2-3-1 48 3 33 34 33 34 soma L5-Rbp4 411771 3-1-2 48 3 33 35 33 35 soma L5-Rbp4 411771 3-2-1 48 3 33 34 33 34 soma L5-Rbp4 412933 1-2-3 129 20 60 63 55 58 dend L23-Cux2 412933 1-3-2 129 19 60 62 59 61 dend L23-Cux2 412933 2-1-3 131 22 60 61 55 55 dend L23-Cux2 412933 2-3-1 131 22 60 61 55 55 dend L23-Cux2 412933 3-1-2 130 20 60 65 59 63 dend L23-Cux2 412933 3-2-1 130 20 60 65 57 61 dend L23-Cux2 413663 1-2-3 262 79 84 95 76 82 dend L23-Cux2 413663 1-3-2 264 82 84 94 77 83 dend L23-Cux2 413663 2-1-3 268 86 81 93 73 82 dend L23-Cux2 413663 2-3-1 268 87 81 95 73 84 dend L23-Cux2 413663 3-1-2 266 85 84 91 77 82 dend L23-Cux2 413663 3-2-1 267 84 81 90 74 80 dend L23-Cux2 418779 1-2-3 12 1 11 11 11 11 soma L5-Rbp4 418779 1-3-2 12 1 11 11 11 11 soma L5-Rbp4 418779 2-1-3 12 1 11 11 11 11 soma L5-Rbp4 418779 2-3-1 12 1 11 12 11 12 soma L5-Rbp4 418779 3-1-2 12 1 11 12 11 12 soma L5-Rbp4 418779 3-2-1 12 1 11 12 11 12 soma L5-Rbp4 420011 1-2-3 69 18 35 40 30 34 dend L5-Rbp4 420011 1-3-2 70 21 33 41 28 34 dend L5-Rbp4 420011 2-1-3 69 17 36 40 31 34 dend L5-Rbp4 420011 2-3-1 68 17 33 36 30 33 dend L5-Rbp4 420011 3-1-2 69 19 31 36 28 33 dend L5-Rbp4 420011 3-2-1 69 20 31 36 28 33 dend L5-Rbp4 433414 1-2-3 188 107 19 34 10 19 dend L23-Cux2 433414 1-3-2 186 102 19 34 10 21 dend L23-Cux2 433414 2-1-3 202 120 21 36 10 14 dend L23-Cux2 433414 2-3-1 201 122 18 33 11 15 dend L23-Cux2 433414 3-1-2 196 115 20 33 12 17 dend L23-Cux2 433414 3-2-1 196 111 20 32 12 17 dend L23-Cux2 433448 1-2-3 283 185 21 42 10 20 dend L5-Rbp4 433448 1-3-2 284 187 19 37 10 17 dend L5-Rbp4 433448 2-1-3 295 203 20 45 11 22 dend L5-Rbp4 433448 2-3-1 294 188 26 44 15 22 dend L5-Rbp4 433448 3-1-2 293 183 25 46 14 20 dend L5-Rbp4 433448 3-2-1 294 187 25 45 15 23 dend L5-Rbp4 433451 1-2-3 715 307 139 158 127 136 dend L5-Rbp4 433451 1-3-2 715 306 138 160 124 135 dend L5-Rbp4 433451 2-1-3 722 306 142 182 126 153 dend L5-Rbp4 433451 2-3-1 720 311 143 187 124 155 dend L5-Rbp4 433451 3-1-2 711 308 139 161 120 136 dend L5-Rbp4 433451 3-2-1 712 303 142 164 121 135 dend L5-Rbp4 433458 1-2-3 72 1 55 55 55 55 soma L5-Rbp4 433458 1-3-2 72 1 55 55 55 55 soma L5-Rbp4 433458 2-1-3 72 1 55 56 55 56 soma L5-Rbp4 433458 2-3-1 72 1 55 56 55 56 soma L5-Rbp4 433458 3-1-2 72 1 55 55 55 55 soma L5-Rbp4 433458 3-2-1 72 1 55 56 55 56 soma L5-Rbp4 440889 1-2-3 150 4 99 100 98 99 soma L23-Cux2 440889 1-3-2 150 4 99 99 98 98 soma L23-Cux2 440889 2-1-3 150 4 99 101 98 100 soma L23-Cux2 440889 2-3-1 150 4 99 101 98 100 soma L23-Cux2 440889 3-1-2 151 5 99 99 98 98 soma L23-Cux2 440889 3-2-1 151 5 99 99 98 98 soma L23-Cux2
def variation(x):
x = np.asarray(x, float)
return pd.Series({"mean": x.mean(), "min": x.min(), "max": x.max(),
"i_range_over_mean": (x.max() - x.min()) / x.mean() if x.mean() else np.nan,
"ii_sd_over_mean": x.std(ddof=1) / x.mean() if x.mean() else np.nan})
res = []
for mouse, g in counts.groupby("mouse"):
plane = g.plane.iloc[0]
cols = ["all"] if plane == "soma" else ["iou>=0.1", "iou>=0.2", "linked iou>=0.1", "linked iou>=0.2", "all"]
for col in cols:
res.append({"mouse": mouse, "plane": plane, "line": g.line.iloc[0],
"threshold": {"all": "none", "iou>=0.1": "a (10%)", "iou>=0.2": "b (20%)",
"linked iou>=0.1": "a (10%), linked pairs", "linked iou>=0.2": "b (20%), linked pairs"}[col], **variation(g[col])})
res = pd.DataFrame(res)
tracked = loaded.groupby("mouse").tracked_in_file.first()
res["tracked_in_file"] = res.mouse.map(tracked)
res["analysed"] = res.mouse.map(loaded.groupby("mouse").analysed.first())
print(res.round(4).to_string(index=False))
summary = []
for mice, sub in (("11 analysed", res[res.analysed]), ("13 tracked", res)):
soma = sub[sub.plane == "soma"]
for thr in ("a (10%)", "b (20%)", "a (10%), linked pairs", "b (20%), linked pairs", "none"):
dend = sub[(sub.plane == "dend") & (sub.threshold == thr)]
for measure in ("i_range_over_mean", "ii_sd_over_mean"):
summary.append({"mice": mice, "dendritic threshold": thr, "measure": measure, "n_soma": len(soma), "n_dend": len(dend),
"soma_mean": soma[measure].mean(), "dend_mean": dend[measure].mean(),
"soma_smaller": soma[measure].mean() < dend[measure].mean(),
"soma_max": soma[measure].max(), "dend_min": dend[measure].min()})
summary = pd.DataFrame(summary)
print(summary.round(4).to_string(index=False))
soma = res[res.plane == "soma"]
print("somatic mice with any variation over orderings:", int((soma.i_range_over_mean > 0).sum()), "of", len(soma))
mouse plane line threshold mean min max i_range_over_mean ii_sd_over_mean tracked_in_file analysed
408021 soma L23-Cux2 none 59.3333 59.0 60.0 0.0169 0.0087 59 True
411400 dend L5-Rbp4 a (10%) 86.3333 84.0 88.0 0.0463 0.0189 162 False
411400 dend L5-Rbp4 b (20%) 75.8333 73.0 78.0 0.0659 0.0227 162 False
411400 dend L5-Rbp4 a (10%), linked pairs 97.6667 91.0 104.0 0.1331 0.0517 162 False
411400 dend L5-Rbp4 b (20%), linked pairs 84.5000 76.0 90.0 0.1657 0.0607 162 False
411400 dend L5-Rbp4 none 396.5000 392.0 399.0 0.0177 0.0081 162 False
411424 soma L23-Cux2 none 56.0000 56.0 56.0 0.0000 0.0000 55 True
411771 soma L5-Rbp4 none 48.0000 48.0 48.0 0.0000 0.0000 47 True
412933 dend L23-Cux2 a (10%) 60.0000 60.0 60.0 0.0000 0.0000 98 False
412933 dend L23-Cux2 b (20%) 56.6667 55.0 59.0 0.0706 0.0347 98 False
412933 dend L23-Cux2 a (10%), linked pairs 62.8333 61.0 65.0 0.0637 0.0292 98 False
412933 dend L23-Cux2 b (20%), linked pairs 58.8333 55.0 63.0 0.1360 0.0573 98 False
412933 dend L23-Cux2 none 130.0000 129.0 131.0 0.0154 0.0069 98 False
413663 dend L23-Cux2 a (10%) 82.5000 81.0 84.0 0.0364 0.0199 136 True
413663 dend L23-Cux2 b (20%) 75.0000 73.0 77.0 0.0533 0.0253 136 True
413663 dend L23-Cux2 a (10%), linked pairs 93.0000 90.0 95.0 0.0538 0.0226 136 True
413663 dend L23-Cux2 b (20%), linked pairs 82.1667 80.0 84.0 0.0487 0.0162 136 True
413663 dend L23-Cux2 none 265.8333 262.0 268.0 0.0226 0.0090 136 True
418779 soma L5-Rbp4 none 12.0000 12.0 12.0 0.0000 0.0000 12 True
420011 dend L5-Rbp4 a (10%) 33.1667 31.0 36.0 0.1508 0.0615 51 True
420011 dend L5-Rbp4 b (20%) 29.1667 28.0 31.0 0.1029 0.0456 51 True
420011 dend L5-Rbp4 a (10%), linked pairs 38.1667 36.0 41.0 0.1310 0.0629 51 True
420011 dend L5-Rbp4 b (20%), linked pairs 33.5000 33.0 34.0 0.0299 0.0163 51 True
420011 dend L5-Rbp4 none 69.0000 68.0 70.0 0.0290 0.0092 51 True
433414 dend L23-Cux2 a (10%) 19.5000 18.0 21.0 0.1538 0.0538 118 True
433414 dend L23-Cux2 b (20%) 10.8333 10.0 12.0 0.1846 0.0908 118 True
433414 dend L23-Cux2 a (10%), linked pairs 33.6667 32.0 36.0 0.1188 0.0406 118 True
433414 dend L23-Cux2 b (20%), linked pairs 17.1667 14.0 21.0 0.4078 0.1493 118 True
433414 dend L23-Cux2 none 194.8333 186.0 202.0 0.0821 0.0338 118 True
433448 dend L5-Rbp4 a (10%) 22.6667 19.0 26.0 0.3088 0.1328 112 True
433448 dend L5-Rbp4 b (20%) 12.5000 10.0 15.0 0.4000 0.1943 112 True
433448 dend L5-Rbp4 a (10%), linked pairs 43.1667 37.0 46.0 0.2085 0.0767 112 True
433448 dend L5-Rbp4 b (20%), linked pairs 20.6667 17.0 23.0 0.2903 0.1045 112 True
433448 dend L5-Rbp4 none 290.5000 283.0 295.0 0.0413 0.0188 112 True
433451 dend L5-Rbp4 a (10%) 140.5000 138.0 143.0 0.0356 0.0148 353 True
433451 dend L5-Rbp4 b (20%) 123.6667 120.0 127.0 0.0566 0.0221 353 True
433451 dend L5-Rbp4 a (10%), linked pairs 168.6667 158.0 187.0 0.1719 0.0742 353 True
433451 dend L5-Rbp4 b (20%), linked pairs 141.6667 135.0 155.0 0.1412 0.0677 353 True
433451 dend L5-Rbp4 none 715.8333 711.0 722.0 0.0154 0.0061 353 True
433458 soma L5-Rbp4 none 72.0000 72.0 72.0 0.0000 0.0000 70 True
440889 soma L23-Cux2 none 150.3333 150.0 151.0 0.0067 0.0034 147 True
mice dendritic threshold measure n_soma n_dend soma_mean dend_mean soma_smaller soma_max dend_min
11 analysed a (10%) i_range_over_mean 6 5 0.0039 0.1371 True 0.0169 0.0356
11 analysed a (10%) ii_sd_over_mean 6 5 0.0020 0.0566 True 0.0087 0.0148
11 analysed b (20%) i_range_over_mean 6 5 0.0039 0.1595 True 0.0169 0.0533
11 analysed b (20%) ii_sd_over_mean 6 5 0.0020 0.0756 True 0.0087 0.0221
11 analysed a (10%), linked pairs i_range_over_mean 6 5 0.0039 0.1368 True 0.0169 0.0538
11 analysed a (10%), linked pairs ii_sd_over_mean 6 5 0.0020 0.0554 True 0.0087 0.0226
11 analysed b (20%), linked pairs i_range_over_mean 6 5 0.0039 0.1836 True 0.0169 0.0299
11 analysed b (20%), linked pairs ii_sd_over_mean 6 5 0.0020 0.0708 True 0.0087 0.0162
11 analysed none i_range_over_mean 6 5 0.0039 0.0381 True 0.0169 0.0154
11 analysed none ii_sd_over_mean 6 5 0.0020 0.0154 True 0.0087 0.0061
13 tracked a (10%) i_range_over_mean 6 7 0.0039 0.1045 True 0.0169 0.0000
13 tracked a (10%) ii_sd_over_mean 6 7 0.0020 0.0431 True 0.0087 0.0000
13 tracked b (20%) i_range_over_mean 6 7 0.0039 0.1334 True 0.0169 0.0533
13 tracked b (20%) ii_sd_over_mean 6 7 0.0020 0.0622 True 0.0087 0.0221
13 tracked a (10%), linked pairs i_range_over_mean 6 7 0.0039 0.1258 True 0.0169 0.0538
13 tracked a (10%), linked pairs ii_sd_over_mean 6 7 0.0020 0.0511 True 0.0087 0.0226
13 tracked b (20%), linked pairs i_range_over_mean 6 7 0.0039 0.1742 True 0.0169 0.0299
13 tracked b (20%), linked pairs ii_sd_over_mean 6 7 0.0020 0.0674 True 0.0087 0.0162
13 tracked none i_range_over_mean 6 7 0.0039 0.0319 True 0.0169 0.0154
13 tracked none ii_sd_over_mean 6 7 0.0020 0.0131 True 0.0087 0.0061
somatic mice with any variation over orderings: 2 of 6
A three-session match can join two ROIs that have no pairwise match of their own (the package links them through the third session). The main reading counts such a pair as IoU 0, so the match fails any threshold; the variant "linked pairs" applies the threshold only to the pairs that have a pairwise match. Below, per mouse, how many three-session matches have such a pair, and the counts under each reading, as the mean over the six orderings, next to the tracked count in the files.
links = counts.groupby("mouse").agg(plane=("plane", "first"), all=("all", "mean"), no_direct_link=("no_direct_link", "mean"),
**{c: (c, "mean") for c in ["iou>=0.1", "iou>=0.2", "linked iou>=0.1", "linked iou>=0.2"]})
links["tracked_in_file"] = links.index.map(tracked)
links["dropped_for_link_only_10"] = links["linked iou>=0.1"] - links["iou>=0.1"]
links["dropped_for_link_only_20"] = links["linked iou>=0.2"] - links["iou>=0.2"]
print(links.round(1).to_string())
plane all no_direct_link iou>=0.1 iou>=0.2 linked iou>=0.1 linked iou>=0.2 tracked_in_file dropped_for_link_only_10 dropped_for_link_only_20 mouse 408021 soma 59.3 2.3 51.0 51.0 52.3 52.3 59 1.3 1.3 411400 dend 396.5 149.8 86.3 75.8 97.7 84.5 162 11.3 8.7 411424 soma 56.0 1.0 42.0 42.0 42.0 42.0 55 0.0 0.0 411771 soma 48.0 3.0 33.0 33.0 34.5 34.5 47 1.5 1.5 412933 dend 130.0 20.5 60.0 56.7 62.8 58.8 98 2.8 2.2 413663 dend 265.8 83.8 82.5 75.0 93.0 82.2 136 10.5 7.2 418779 soma 12.0 1.0 11.0 11.0 11.5 11.5 12 0.5 0.5 420011 dend 69.0 18.7 33.2 29.2 38.2 33.5 51 5.0 4.3 433414 dend 194.8 112.8 19.5 10.8 33.7 17.2 118 14.2 6.3 433448 dend 290.5 188.8 22.7 12.5 43.2 20.7 112 20.5 8.2 433451 dend 715.8 306.8 140.5 123.7 168.7 141.7 353 28.2 18.0 433458 soma 72.0 1.0 55.0 55.0 55.5 55.5 70 0.5 0.5 440889 soma 150.3 4.3 99.0 98.0 99.8 98.8 147 0.8 0.8
Check against the package's own run¶
ordering_counts combines directed pairwise matchings computed once, in place of running
NwayMatching.run for every ordering. As a check, the package's run is called directly on all six
orderings of the smallest somatic mouse (418779) and the smallest dendritic mouse (420011), and its
count of three-session matches is set beside the count above.
import itertools
direct = []
for m in ("418779", "420011"):
for order in itertools.permutations(range(3)):
name = "-".join(str(k + 1) for k in order)
n = ca.direct_run_count(sessions_by_mouse[m], order)
direct.append({"mouse": m, "order": name, "direct_run": n,
"ordering_counts": int(counts.loc[(counts.mouse == m) & (counts.order == name), "all"].iloc[0])})
direct = pd.DataFrame(direct)
direct["equal"] = direct.direct_run == direct.ordering_counts
print(direct.to_string(index=False))
print("orderings with equal counts:", int(direct.equal.sum()), "of", len(direct))
print(f"notebook ran in {(time.time() - T0) / 60:.1f} min")
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
WARNING:root:many=True not supported from argparse
/home/runner/work/_temp/executed/.venv/lib/python3.13/site-packages/argschema/utils.py:346: FutureWarning: '--nway_output.nway_matches' is using old-style command-line syntax with each element as a separate argument. This will not be supported in argschema after 2.0. See http://argschema.readthedocs.io/en/master/user/intro.html#command-line-specification for details. warnings.warn(warn_msg, FutureWarning)
/home/runner/work/_temp/executed/.venv/lib/python3.13/site-packages/argschema/utils.py:346: FutureWarning: '--nway_output.nway_matches' is using old-style command-line syntax with each element as a separate argument. This will not be supported in argschema after 2.0. See http://argschema.readthedocs.io/en/master/user/intro.html#command-line-specification for details. warnings.warn(warn_msg, FutureWarning)
/home/runner/work/_temp/executed/.venv/lib/python3.13/site-packages/argschema/utils.py:346: FutureWarning: '--nway_output.nway_matches' is using old-style command-line syntax with each element as a separate argument. This will not be supported in argschema after 2.0. See http://argschema.readthedocs.io/en/master/user/intro.html#command-line-specification for details. warnings.warn(warn_msg, FutureWarning)
/home/runner/work/_temp/executed/.venv/lib/python3.13/site-packages/argschema/utils.py:346: FutureWarning: '--nway_output.nway_matches' is using old-style command-line syntax with each element as a separate argument. This will not be supported in argschema after 2.0. See http://argschema.readthedocs.io/en/master/user/intro.html#command-line-specification for details. warnings.warn(warn_msg, FutureWarning)
/home/runner/work/_temp/executed/.venv/lib/python3.13/site-packages/argschema/utils.py:346: FutureWarning: '--nway_output.nway_matches' is using old-style command-line syntax with each element as a separate argument. This will not be supported in argschema after 2.0. See http://argschema.readthedocs.io/en/master/user/intro.html#command-line-specification for details. warnings.warn(warn_msg, FutureWarning)
/home/runner/work/_temp/executed/.venv/lib/python3.13/site-packages/argschema/utils.py:346: FutureWarning: '--nway_output.nway_matches' is using old-style command-line syntax with each element as a separate argument. This will not be supported in argschema after 2.0. See http://argschema.readthedocs.io/en/master/user/intro.html#command-line-specification for details. warnings.warn(warn_msg, FutureWarning)
/home/runner/work/_temp/executed/.venv/lib/python3.13/site-packages/argschema/utils.py:346: FutureWarning: '--nway_output.nway_matches' is using old-style command-line syntax with each element as a separate argument. This will not be supported in argschema after 2.0. See http://argschema.readthedocs.io/en/master/user/intro.html#command-line-specification for details. warnings.warn(warn_msg, FutureWarning)
/home/runner/work/_temp/executed/.venv/lib/python3.13/site-packages/argschema/utils.py:346: FutureWarning: '--nway_output.nway_matches' is using old-style command-line syntax with each element as a separate argument. This will not be supported in argschema after 2.0. See http://argschema.readthedocs.io/en/master/user/intro.html#command-line-specification for details. warnings.warn(warn_msg, FutureWarning)
/home/runner/work/_temp/executed/.venv/lib/python3.13/site-packages/argschema/utils.py:346: FutureWarning: '--nway_output.nway_matches' is using old-style command-line syntax with each element as a separate argument. This will not be supported in argschema after 2.0. See http://argschema.readthedocs.io/en/master/user/intro.html#command-line-specification for details. warnings.warn(warn_msg, FutureWarning)
/home/runner/work/_temp/executed/.venv/lib/python3.13/site-packages/argschema/utils.py:346: FutureWarning: '--nway_output.nway_matches' is using old-style command-line syntax with each element as a separate argument. This will not be supported in argschema after 2.0. See http://argschema.readthedocs.io/en/master/user/intro.html#command-line-specification for details. warnings.warn(warn_msg, FutureWarning)
/home/runner/work/_temp/executed/.venv/lib/python3.13/site-packages/argschema/utils.py:346: FutureWarning: '--nway_output.nway_matches' is using old-style command-line syntax with each element as a separate argument. This will not be supported in argschema after 2.0. See http://argschema.readthedocs.io/en/master/user/intro.html#command-line-specification for details. warnings.warn(warn_msg, FutureWarning)
mouse order direct_run ordering_counts equal 418779 1-2-3 12 12 True 418779 1-3-2 12 12 True 418779 2-1-3 12 12 True 418779 2-3-1 12 12 True 418779 3-1-2 12 12 True 418779 3-2-1 12 12 True 420011 1-2-3 69 69 True 420011 1-3-2 70 70 True 420011 2-1-3 69 69 True 420011 2-3-1 68 68 True 420011 3-1-2 69 69 True 420011 3-2-1 69 69 True orderings with equal counts: 12 of 12 notebook ran in 25.3 min
/home/runner/work/_temp/executed/.venv/lib/python3.13/site-packages/argschema/utils.py:346: FutureWarning: '--nway_output.nway_matches' is using old-style command-line syntax with each element as a separate argument. This will not be supported in argschema after 2.0. See http://argschema.readthedocs.io/en/master/user/intro.html#command-line-specification for details. warnings.warn(warn_msg, FutureWarning)
Result: reproduced. In all six somatic mice the number of ROIs matched across the three sessions varies by at most one over the six orderings (range over mean 0 to 0.017, mean 0.004; 4 of 6 mice with no variation). For the 11 analysed mice, the five dendritic mice vary more: with the 10% overlap threshold the range over mean is 0.036 to 0.259 (mean 0.136; SD over mean, mean 0.055), with 20% 0.053 to 0.405 (mean 0.161; SD over mean 0.079). Every dendritic mouse varies more than every somatic one under both thresholds and both measures, and also when the threshold applies only to pairs with a direct pairwise match (range over mean 0.029 to 0.400, mean 0.113 at 10% and 0.172 at 20%). Without a threshold the dendritic mean is still larger (range over mean 0.040 against 0.004), though 433451 (0.015) then varies less than somatic mouse 408021 (0.017).
With all 13 tracked mice, as the criterion words it, the mean variation of the seven dendritic mice is still larger than that of the somatic mice under every reading: range over mean 0.104 at 10% and 0.134 at 20% against 0.004 (SD over mean 0.042 and 0.064 against 0.002), 0.109 and 0.166 on linked pairs, and 0.034 without a threshold. One of the two added mice, 412933, matches 60 ROIs in every ordering at 10% (no variation), so with it not every dendritic mouse varies more than every somatic one; 411400 varies by 0.046 at 10%.
The result rests on the public package and on reading the overlap as intersection over union. With that reading the dendritic match counts fall well below the tracked counts in the files (for example 20.0 and 23.2 on average for 433414 and 433448, against 118 and 112). Part of the loss comes from three-session matches with a pair of ROIs that has no direct pairwise match (19 to 307 such matches per dendritic mouse on average, against 1 to 4 per somatic mouse): applying the threshold only to the pairs that have one keeps 3 to 28 more matches per dendritic mouse at 10%, still below the tracked counts (34.3 and 44.2 for 433414 and 433448). The IoU threshold, not the linking rule, removes most matches. Without a threshold the dendritic counts are 1.3 to 2.6 times the tracked counts. The package's own run gives the same count as the reconstruction in all 12 orderings checked (418779 and 420011).
Summary¶
fig8-ordering-variation: reproduced, for the 11 analysed mice and for all 13 tracked mice, resting on
assumptions (the public matching package in place of the paper's modified one, and the dendritic overlap
read as intersection over union). The full summary of all claims is in reproduce_gillon_2023.ipynb.