Sit & Goard (2023) on dandiset 000483: ADN and visual axons, light and dark (Figure 4)¶
Paper. Sit KK, Goard MJ (2023), Nature Communications 14:1992, doi:10.1038/s41467-023-37704-5; claims file written from the version of record without its supplement.
Dataset. DANDI:000483, version
0.230421.2321, the only published version (the paper cites none). See single_cue.ipynb for the
data check of all files.
| Claim | Here |
|---|---|
| fig4-axons-light-on-shape | tested |
| fig4-axons-light-off | tested |
The claims of Figure 5 are in somata.ipynb (fig5i-axons-in-clusters uses these axons too); Figures S5 and S6
and Figure 5K are in directions.ipynb, and the decoding of Figure 6 in decoding.ipynb. Activity is inferred spikes computed from the raw fluorescence (no
neuropil correction; see rsc.py). Light and dark segments are the code's hard-coded ones,
as the files do not mark them.
import os
for _v in ["OMP_NUM_THREADS", "OPENBLAS_NUM_THREADS", "MKL_NUM_THREADS"]:
os.environ[_v] = "1" # one BLAS thread, so that results do not depend on the number of cores
import time
import warnings
from multiprocessing import Pool
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import statsmodels.formula.api as smf
from scipy import stats
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.metrics import silhouette_score
from sklearn.mixture import GaussianMixture
import rsc
warnings.filterwarnings("ignore")
pd.set_option("display.width", 200)
pd.set_option("display.max_columns", 30)
started = time.time()
cat = rsc.catalog(full=False)
sub = cat[cat.experiment.isin(["adn_axons", "vis_axons"])].reset_index(drop=True)
recs = rsc.load_many(sub.url.tolist())
with Pool(4) as pool:
for r in recs:
r["dff"] = rsc.dff(r["F"])
r["sp"] = rsc.spikes(r["dff"], pool)
del r["F"]
print(f"dandiset {rsc.DANDISET_ID} version {rsc.DANDISET_VERSION}: {len(sub)} files loaded and deconvolved "
f"in {time.time() - started:.0f} s")
dandiset 000483 version 0.230421.2321: 24 files loaded and deconvolved in 134 s
rows = []
for m, r in zip(sub.itertuples(), recs):
L, D = rsc.light_dark_frames(m.n_frames)
r["seg_l"], r["seg_d"] = rsc.segments_within(r["heading"], L), rsc.segments_within(r["heading"], D)
r["seg_all"] = rsc.trial_segments(r["heading"])
step = rsc.wrap180(np.diff(rsc.clean_heading(r["heading"])))
# activity per segment, to see whether the hard-coded light and dark segments differ
act = r["sp"].sum(1)
rows.append(dict(experiment=m.experiment, subject=m.subject, identifier=m.identifier[:6] + " " + m.identifier.split("_")[-1],
frames=m.n_frames, rois=m.n_rois, median_step=round(float(np.median(step)), 2),
trials_all=len(r["seg_all"]), trials_light=len(r["seg_l"]), trials_dark=len(r["seg_d"]),
spikes_light=round(float(np.mean([act[s].mean() for s in L])), 2),
spikes_dark=round(float(np.mean([act[s].mean() for s in D])), 2)))
info = pd.DataFrame(rows)
print(info.to_string(index=False))
print(info.groupby("experiment").agg(files=("rois", "size"), mice=("subject", "nunique"), rois=("rois", "sum")).to_string())
experiment subject identifier frames rois median_step trials_all trials_light trials_dark spikes_light spikes_dark
adn_axons SKKS092 210217 SKKS092-axons-001 7550 27 1.93 38 17 19 0.15 0.09
adn_axons SKKS092 210217 SKKS092-axons-002 7550 60 1.93 38 19 18 0.45 0.24
adn_axons SKKS092 210304 SKKS092-ADNAxons-3rpm-001 7550 25 1.90 38 18 15 0.61 0.74
adn_axons SKKS092 210304 SKKS092-ADNAxons-3rpm-002 7550 26 1.89 39 18 19 0.47 0.65
adn_axons SKKS092 210304 SKKS092-ADNAxons-3rpm-003 7550 20 1.87 37 17 18 0.39 0.56
adn_axons SKKS093 210217 SKKS093-axons-001 7550 76 1.95 38 19 17 0.64 0.48
adn_axons SKKS093 210217 SKKS093-axons-002 7550 60 1.94 39 18 19 0.50 0.20
adn_axons SKKS093 210304 SKKS093-ADNAxons-3rpm-001 7550 67 1.89 39 18 20 0.90 0.64
adn_axons SKKS093 210304 SKKS093-ADNAxons-3rpm-002 7550 58 1.90 37 18 19 0.78 0.41
adn_axons SKKS093 210304 SKKS093-ADNAxons-3rpm-003 7550 79 1.89 39 18 18 0.82 0.72
adn_axons SKKS094 210217 SKKS094-axons-001 7550 66 1.88 37 17 20 0.81 0.56
adn_axons SKKS094 210217 SKKS094-axons-002 7550 75 1.88 38 17 18 0.82 0.47
adn_axons SKKS094 210304 SKKS094-ADNAxons-3rpm-001 7550 112 1.88 37 18 17 1.53 1.70
adn_axons SKKS094 210304 SKKS094-ADNAxons-3rpm-002 7550 110 1.84 35 18 17 1.55 1.53
adn_axons SKKS094 210304 SKKS094-ADNAxons-3rpm-003 7550 120 1.62 23 13 9 1.64 1.13
adn_axons SKKS095 210217 SKKS095-axons-001 7550 44 1.90 39 20 18 0.47 0.28
adn_axons SKKS095 210217 SKKS095-axons-002 7550 59 1.89 37 15 18 0.41 0.35
vis_axons SKKS097 210217 SKKS097-axons-001 7550 68 1.73 34 15 16 1.66 0.25
vis_axons SKKS097 210217 SKKS097-axons-002 7550 47 1.87 37 17 17 0.96 0.12
vis_axons SKKS098 210217 SKKS098-axons-001 7550 36 1.92 39 21 18 0.62 0.25
vis_axons SKKS098 210217 SKKS098-axons-002 7550 26 1.93 39 17 18 0.43 0.13
vis_axons SKKS103 210304 SKKS103-VISAxons-3rpm-001 7550 37 0.11 11 8 3 0.76 0.45
vis_axons SKKS103 210304 SKKS103-VISAxons-3rpm-002 7550 28 1.87 37 17 15 0.57 0.49
vis_axons SKKS103 210304 SKKS103-VISAxons-3rpm-003 7550 5 1.89 38 18 17 0.03 0.01
files mice rois
experiment
adn_axons 17 4 1084
vis_axons 7 3 247
The files do not say when the lights were on. The code hard-codes the segments (Separator.m):
950-frame light and dark halves for 1950-frame recordings, three light/dark repeats of 1250
frames for 7550-frame ones. The summed activity per segment is shown above as a check that is
consistent with, but does not prove, the segmentation. Several 1950-frame recordings of
2021-01-18 stop rotating early and have few trials.
Clock check. As in rotation_remapping.ipynb, files that rotate one way at constant speed
cannot show a time offset between heading and activity; the clock is checked only on the files
that rotate both ways (single_cue.ipynb), and is not established for these files.
Heading-selection test (two-term Gaussian)¶
On all trials, light and dark together (the code's default, claims file), with the centred fit
adopted in single_cue.ipynb. The code's uncentred fit is also run, and the test on light-off trials
alone (the code's 'dark' option) for fig4-axons-light-off.
t0 = time.time()
trials_all = [rsc.trial_tuning(r["sp"], r["heading"], r["seg_all"]) for r in recs]
ax_idx = [i for i in range(len(recs)) if "axons" in sub.experiment[i]]
with Pool(4) as pool:
sel = rsc.selection_many(trials_all, "double", 301, pool, centre=True) # all files here are axons
sel_ax_code = rsc.selection_many([trials_all[i] for i in ax_idx], "double", 302, pool, centre=False)
sel_ax_dark = rsc.selection_many([rsc.trial_tuning(recs[i]["sp"], recs[i]["heading"], recs[i]["seg_d"]) for i in ax_idx],
"double", 303, pool, centre=True)
info["selective"] = [s.is_hd.sum() for s in sel]
print(f"selection tests in {time.time() - t0:.0f} s")
print(info.groupby("experiment")[["rois", "selective"]].sum().to_string())
selection tests in 159 s
rois selective
experiment
adn_axons 1084 135
vis_axons 247 106
# Light and dark tuning, aligned with the light-on cross-validated shifts (Methods).
def light_dark_aligned(i):
r = recs[i]
lt = rsc.trial_tuning(r["sp"], r["heading"], r["seg_l"])
dt = rsc.trial_tuning(r["sp"], r["heading"], r["seg_d"])
if lt.shape[2] == 0:
return None, None
sh = rsc.cv_shifts(lt) if lt.shape[2] > 1 else (rsc.SHIFT_POINT - lt[:, :, 0].argmax(1))[:, None]
la = rsc.apply_shifts(lt, sh).mean(2)
# light-off trials take the shift of the mean light-on curve (all light trials)
sh_all = (rsc.SHIFT_POINT - lt.mean(2).argmax(1))[:, None]
da = rsc.apply_shifts(dt, np.repeat(sh_all, max(dt.shape[2], 1), 1)).mean(2) if dt.shape[2] else np.full_like(la, np.nan)
return la, da
aligned = [light_dark_aligned(i) for i in range(len(recs))]
print("Recordings without light-on trials (left out of the light/dark analyses):",
[info.identifier[i] for i in range(len(recs)) if aligned[i][0] is None])
print("Recordings without light-off trials:", [info.identifier[i] for i in range(len(recs)) if aligned[i][0] is not None and np.isnan(aligned[i][1]).all()])
Recordings without light-on trials (left out of the light/dark analyses): [] Recordings without light-off trials: []
fig4-axons-light-on-shape¶
In the light-on condition with two symmetric cues, ADN axons in RSC show unimodal heading tuning curves, while visual cortical (AM/PM) axons show bimodal tuning curves with peaks about 180 degrees apart.
Readings of the claims file: (a) axons passing the two-term test, (b) all axons. Flip score of the mean aligned light-on curve (ADN below 0, visual above 0), and the flip scores of single axons, visual above ADN by a two-sample KS test. The fit readings of the selection (centred, code) are both shown for (a).
def axon_sets(selection_by_rec):
out = {}
for kind in ["adn_axons", "vis_axons"]:
la, da, mice, recid = [], [], [], []
for k, i in enumerate(ax_idx):
if sub.experiment[i] != kind or aligned[i][0] is None:
continue
m = selection_by_rec(k, i)
la.append(aligned[i][0][m]); da.append(aligned[i][1][m])
mice += [sub.subject[i]] * int(m.sum()); recid += [i] * int(m.sum())
out[kind] = (np.vstack(la), np.vstack(da), np.array(mice), np.array(recid))
return out
readings = {"(a) selective, centred": axon_sets(lambda k, i: sel[i].is_hd.values),
"(a) selective, code fit": axon_sets(lambda k, i: sel_ax_code[k].is_hd.values),
"(b) all axons": axon_sets(lambda k, i: np.ones(len(sel[i]), bool))}
light_shape = {}
for name, s in readings.items():
(la_a, da_a, mice_a, _), (la_v, da_v, mice_v, _) = s["adn_axons"], s["vis_axons"]
fa, fv = rsc.flip_score(la_a), rsc.flip_score(la_v)
fa, fv = fa[np.isfinite(fa)], fv[np.isfinite(fv)]
mean_a, mean_v = rsc.flip_score(np.nanmean(la_a, 0)[None])[0], rsc.flip_score(np.nanmean(la_v, 0)[None])[0]
ks = stats.ks_2samp(fv, fa)
light_shape[name] = (mean_a, mean_v, fa.mean(), fv.mean(), ks.pvalue)
print(f"== {name}: ADN n={len(la_a)} ({len(set(mice_a))} mice), visual n={len(la_v)} ({len(set(mice_v))} mice)")
print(f" flip score of the mean light-on curve: ADN {mean_a:.3f}, visual {mean_v:.3f}")
print(f" single axons: ADN mean {fa.mean():.3f} (median {np.median(fa):.3f}), visual mean {fv.mean():.3f} (median {np.median(fv):.3f}); KS p = {ks.pvalue:.2g}")
for kind, mice, f in [("ADN", mice_a, rsc.flip_score(la_a)), ("visual", mice_v, rsc.flip_score(la_v))]:
print(f" {kind} by mouse:", {m: round(float(np.nanmean(f[mice == m])), 3) for m in np.unique(mice)})
fig, ax = plt.subplots(1, 2, figsize=(8, 3))
s = readings["(a) selective, centred"]
xdeg = np.arange(60) * 6 - 84
for a, kind, title in zip(ax, ["adn_axons", "vis_axons"], ["ADN axons", "visual axons"]):
la, da = rsc.rescale(s[kind][0]), rsc.rescale(s[kind][1])
a.plot(xdeg, np.nanmean(la, 0), label="light on"); a.plot(xdeg, np.nanmean(da, 0), label="light off")
a.set_title(title); a.set_xlabel("heading from aligned peak (deg)")
ax[0].set_ylabel("mean rescaled response"); ax[0].legend(); plt.tight_layout(); plt.show()
print("Curves are min-max rescaled per axon before averaging, so all values lie in 0 to 1.")
== (a) selective, centred: ADN n=135 (4 mice), visual n=106 (3 mice)
flip score of the mean light-on curve: ADN 0.277, visual 1.814
single axons: ADN mean -0.072 (median -0.279), visual mean 1.073 (median 1.146); KS p = 1.7e-21
ADN by mouse: {np.str_('SKKS092'): 0.48, np.str_('SKKS093'): -0.034, np.str_('SKKS094'): -0.196, np.str_('SKKS095'): -0.461}
visual by mouse: {np.str_('SKKS097'): 1.185, np.str_('SKKS098'): 1.026, np.str_('SKKS103'): 0.408}
== (a) selective, code fit: ADN n=73 (4 mice), visual n=50 (3 mice)
flip score of the mean light-on curve: ADN 1.132, visual 1.903
single axons: ADN mean 0.080 (median -0.100), visual mean 0.882 (median 1.021); KS p = 1.1e-06
ADN by mouse: {np.str_('SKKS092'): 0.423, np.str_('SKKS093'): -0.158, np.str_('SKKS094'): 0.125, np.str_('SKKS095'): -0.387}
visual by mouse: {np.str_('SKKS097'): 1.127, np.str_('SKKS098'): 0.578, np.str_('SKKS103'): 0.441}
== (b) all axons: ADN n=1084 (4 mice), visual n=247 (3 mice) flip score of the mean light-on curve: ADN -0.207, visual 1.875 single axons: ADN mean -0.109 (median -0.258), visual mean 0.506 (median 0.589); KS p = 1.6e-24
ADN by mouse: {np.str_('SKKS092'): -0.001, np.str_('SKKS093'): -0.12, np.str_('SKKS094'): -0.133, np.str_('SKKS095'): -0.127}
visual by mouse: {np.str_('SKKS097'): 0.867, np.str_('SKKS098'): 0.544, np.str_('SKKS103'): -0.121}
Curves are min-max rescaled per axon before averaging, so all values lie in 0 to 1.
Result: reproduced under reading (b), all axons. The mean aligned light-on curve has a flip score of -0.207 for ADN axons (unimodal) and 1.875 for visual axons (bimodal). Single visual axons have higher flip scores than ADN axons (means 0.506 and -0.109, KS p = 1.6e-24). Under reading (a), selective axons, the visual part holds (1.814; single axons 1.073 against -0.072, KS p = 1.7e-21). The ADN mean curve, however, has a flip score of 0.277 (centred fit) or 1.132 (code fit), above 0. One ADN mouse, SKKS092, has a mean flip score above 0 under reading (a) (0.48 and 0.42) and about 0 under (b) (-0.001).
fig4-axons-light-off¶
In the light-off condition ADN axons keep their heading tuning for several trials, while visual cortical axons lose their tuning.
Criterion: the fraction of axons selective by the test on light-off trials alone is higher for ADN than for visual axons (per-recording fractions, Mann-Whitney; Fisher's exact test on pooled counts as a variant), and the mean aligned light-off curve of ADN axons peaks within 18 degrees (3 bins) of the light-on peak (bin 15 after alignment) while that of visual axons has a peak-to-trough range under half its light-on range.
The fraction selective in light-off is computed under reading (b), over all axons, and under reading (a), over the axons selective on all trials.
fr = pd.DataFrame({"kind": [sub.experiment[i] for i in ax_idx], "subject": [sub.subject[i] for i in ax_idx],
"file": [info.identifier[i] for i in ax_idx], "dark_trials": [len(recs[i]["seg_d"]) for i in ax_idx],
"axons": [len(sel[i]) for i in ax_idx], "dark_selective": [s.is_hd.sum() for s in sel_ax_dark]})
fr["fraction"] = fr.dark_selective / fr.axons
print(fr.to_string(index=False))
fa_, fv_ = fr[fr.kind == "adn_axons"].fraction, fr[fr.kind == "vis_axons"].fraction
mw = stats.mannwhitneyu(fa_, fv_, alternative="two-sided")
pooled = fr.groupby("kind")[["dark_selective", "axons"]].sum()
odds, pf = stats.fisher_exact([[pooled.loc["adn_axons", "dark_selective"], pooled.loc["adn_axons", "axons"] - pooled.loc["adn_axons", "dark_selective"]],
[pooled.loc["vis_axons", "dark_selective"], pooled.loc["vis_axons", "axons"] - pooled.loc["vis_axons", "dark_selective"]]])
print(f"\nper-recording fraction selective in light-off: ADN median {fa_.median():.3f} (mean {fa_.mean():.3f}), "
f"visual median {fv_.median():.3f} (mean {fv_.mean():.3f}); Mann-Whitney p = {mw.pvalue:.2g}")
print(f"pooled: ADN {pooled.loc['adn_axons', 'dark_selective']}/{pooled.loc['adn_axons', 'axons']}, visual "
f"{pooled.loc['vis_axons', 'dark_selective']}/{pooled.loc['vis_axons', 'axons']}; Fisher p = {pf:.2g}, odds ratio {odds:.2f}")
# reading (a): among the axons selective on all trials (light-on selection), the share also selective in light-off
fr["a_selective"] = [sel[i].is_hd.sum() for i in ax_idx]
fr["a_dark_selective"] = [int((sel[i].is_hd.values & s.is_hd.values).sum()) for i, s in zip(ax_idx, sel_ax_dark)]
fr["a_fraction"] = fr.a_dark_selective / fr.a_selective.where(fr.a_selective > 0)
fa_a, fv_a = fr[fr.kind == "adn_axons"].a_fraction.dropna(), fr[fr.kind == "vis_axons"].a_fraction.dropna()
mw_a = stats.mannwhitneyu(fa_a, fv_a, alternative="two-sided")
pa = fr.groupby("kind")[["a_dark_selective", "a_selective"]].sum()
odds_a, pf_a = stats.fisher_exact([[pa.loc["adn_axons", "a_dark_selective"], pa.loc["adn_axons", "a_selective"] - pa.loc["adn_axons", "a_dark_selective"]],
[pa.loc["vis_axons", "a_dark_selective"], pa.loc["vis_axons", "a_selective"] - pa.loc["vis_axons", "a_dark_selective"]]])
print(f"\nreading (a), selective axons: per-recording share also selective in light-off, ADN median {fa_a.median():.3f} "
f"(n = {len(fa_a)} recordings), visual median {fv_a.median():.3f} (n = {len(fv_a)}); Mann-Whitney p = {mw_a.pvalue:.2g}; pooled ADN "
f"{pa.loc['adn_axons', 'a_dark_selective']}/{pa.loc['adn_axons', 'a_selective']}, visual {pa.loc['vis_axons', 'a_dark_selective']}/"
f"{pa.loc['vis_axons', 'a_selective']}, Fisher p = {pf_a:.2g}, odds ratio {odds_a:.2f}")
print("recordings without selective axons are left out of the per-recording comparison:", int(fr.a_fraction.isna().sum()))
for name, s in readings.items():
(la_a, da_a, _, _), (la_v, da_v, _, _) = s["adn_axons"], s["vis_axons"]
ma, mda = np.nanmean(la_a, 0), np.nanmean(da_a, 0)
mv, mdv = np.nanmean(la_v, 0), np.nanmean(da_v, 0)
pk_off = int(np.argmax(mda)); off_bins = int(abs(rsc.wrap180((pk_off - rsc.SHIFT_POINT) * 6)) // 6)
ratio_v = np.ptp(mdv) / np.ptp(mv)
print(f"== {name}: ADN mean light-off peak at bin {pk_off + 1} ({off_bins * 6} deg from the light-on peak bin 15); "
f"ADN light-off/light-on range {np.ptp(mda) / np.ptp(ma):.2f}; visual light-off/light-on range {ratio_v:.2f}")
kind subject file dark_trials axons dark_selective fraction adn_axons SKKS092 210217 SKKS092-axons-001 19 27 0 0.000000 adn_axons SKKS092 210217 SKKS092-axons-002 18 60 4 0.066667 adn_axons SKKS092 210304 SKKS092-ADNAxons-3rpm-001 15 25 2 0.080000 adn_axons SKKS092 210304 SKKS092-ADNAxons-3rpm-002 19 26 0 0.000000 adn_axons SKKS092 210304 SKKS092-ADNAxons-3rpm-003 18 20 0 0.000000 adn_axons SKKS093 210217 SKKS093-axons-001 17 76 13 0.171053 adn_axons SKKS093 210217 SKKS093-axons-002 19 60 3 0.050000 adn_axons SKKS093 210304 SKKS093-ADNAxons-3rpm-001 20 67 14 0.208955 adn_axons SKKS093 210304 SKKS093-ADNAxons-3rpm-002 19 58 3 0.051724 adn_axons SKKS093 210304 SKKS093-ADNAxons-3rpm-003 18 79 3 0.037975 adn_axons SKKS094 210217 SKKS094-axons-001 20 66 6 0.090909 adn_axons SKKS094 210217 SKKS094-axons-002 18 75 0 0.000000 adn_axons SKKS094 210304 SKKS094-ADNAxons-3rpm-001 17 112 2 0.017857 adn_axons SKKS094 210304 SKKS094-ADNAxons-3rpm-002 17 110 16 0.145455 adn_axons SKKS094 210304 SKKS094-ADNAxons-3rpm-003 9 120 26 0.216667 adn_axons SKKS095 210217 SKKS095-axons-001 18 44 0 0.000000 adn_axons SKKS095 210217 SKKS095-axons-002 18 59 1 0.016949 vis_axons SKKS097 210217 SKKS097-axons-001 16 68 1 0.014706 vis_axons SKKS097 210217 SKKS097-axons-002 17 47 7 0.148936 vis_axons SKKS098 210217 SKKS098-axons-001 18 36 2 0.055556 vis_axons SKKS098 210217 SKKS098-axons-002 18 26 1 0.038462 vis_axons SKKS103 210304 SKKS103-VISAxons-3rpm-001 3 37 0 0.000000 vis_axons SKKS103 210304 SKKS103-VISAxons-3rpm-002 15 28 0 0.000000 vis_axons SKKS103 210304 SKKS103-VISAxons-3rpm-003 17 5 0 0.000000 per-recording fraction selective in light-off: ADN median 0.050 (mean 0.068), visual median 0.015 (mean 0.037); Mann-Whitney p = 0.35 pooled: ADN 93/1084, visual 11/247; Fisher p = 0.035, odds ratio 2.01 reading (a), selective axons: per-recording share also selective in light-off, ADN median 0.134 (n = 14 recordings), visual median 0.000 (n = 7); Mann-Whitney p = 0.15; pooled ADN 39/135, visual 5/106, Fisher p = 5.4e-07, odds ratio 8.21 recordings without selective axons are left out of the per-recording comparison: 3 == (a) selective, centred: ADN mean light-off peak at bin 19 (24 deg from the light-on peak bin 15); ADN light-off/light-on range 0.86; visual light-off/light-on range 0.05 == (a) selective, code fit: ADN mean light-off peak at bin 18 (18 deg from the light-on peak bin 15); ADN light-off/light-on range 0.80; visual light-off/light-on range 0.11 == (b) all axons: ADN mean light-off peak at bin 20 (30 deg from the light-on peak bin 15); ADN light-off/light-on range 0.72; visual light-off/light-on range 0.10
Result: partially reproduced. Visual axons lose their tuning in light-off: their mean light-off curve keeps 5 to 11% of the light-on range, under 50%. The ADN part of the criterion fails. Over all axons (reading b) the per-recording fraction selective in light-off is not significantly higher for ADN than for visual axons (medians 0.050 and 0.015, Mann-Whitney p = 0.35); pooled counts differ (93 of 1084 against 11 of 247, Fisher p = 0.035, the variant). Among selective axons (reading a) the share also selective in light-off is higher for ADN, but not significantly per recording (medians 0.134 and 0.000, Mann-Whitney p = 0.15, 14 and 7 recordings); pooled, 39 of 135 against 5 of 106 (Fisher p = 5.4e-07). The ADN mean light-off curve keeps 72 to 86% of its light-on range, but its peak lies 24 degrees (reading a, centred fit) or 30 degrees (reading b) from the light-on peak, beyond the 18 degrees of the criterion; under the code fit it lies at 18 degrees.
Summary¶
| Claim | Outcome |
|---|---|
| fig4-axons-light-on-shape | reproduced (reading b, all axons) |
| fig4-axons-light-off | partially reproduced: visual axons lose tuning; the ADN tests of the criterion fail |
A failure to reproduce here may be a failure of this attempt, not of the paper: see the reasoning and the differences from the paper's method.
How the analysis differs from the paper's: inferred spikes from raw fluorescence (the paper used Suite2P traces for axons, not in the files); light and dark segments are the code's hard-coded ones; light-off curves take the shift of the mean light-on curve, as the code's aligner (leaveOneOutAligner) is not public.
What was found about the dataset: the files do not mark light-on and light-off periods; axon recordings are described as soma recordings.