Claar, Rembado et al. (2023) on dandiset 000458: spiking claims¶
Paper. Claar et al. (2023), eLife 12:RP84630, doi:10.7554/eLife.84630;
claims file written from the version of record. Dandiset.
DANDI:000458, version 0.230317.0039, the version the
paper cites and the only published one. See claar_eeg.ipynb for the EEG claims and the data check of the trial
tables; this notebook checks the unit tables and tests the spiking claims (Figures 2, 4, 5, 6B, 6C, 7E to 7H).
| Claim | Here |
|---|---|
| fig2c-superficial-quiescence | tested |
| fig2c-deep-triphasic-cortex | tested |
| fig2f-thalamus-triphasic | tested |
| fig3abc-decay-with-distance, fig3d-magnitudes | decided in claar_lfp.ipynb; the spiking part is computed here |
| fig4-unit-counts | tested |
| fig4ad-initial-excitation | tested |
| fig4be-off-period | tested |
| fig4cf-rebound | tested |
| fig4-supp1-fs-like-rs | tested |
| fig5a-thalamus-modulated | tested |
| fig5c-burst-probability-depth | tested |
| fig5e-early-latency | tested |
| fig5f-rebound-latency | tested |
| fig6a-csd-sink, fig6-supp1-erp-deep-csd | blocked (see the record): CSD by layer |
| fig6b-bursts-cortical-rate | tested |
| fig6c-cortical-rate-late-erp | tested |
| fig6-supp2-late-erp-bursts | tested |
| fig7e-baseline-rates | tested |
| fig7f-early-latency-state | tested |
| fig7g-rebound-latency-state | tested |
| fig7h-burst-probability-state | tested |
Readings run throughout: stimulus intensity ("high" and "medium" current), awake trials (all, or quiet only), the pre-stimulus window of the modulation test ("adjacent", ending at onset, or "mirror", -b to -a), and the Benjamini-Hochberg family ("site": per site and window, over cortical RS and SM-TH units; "pooled": all sites per window). Units are those in the files (the dandiset's quality threshold) unless a cell says otherwise.
import time
import warnings
from concurrent.futures import ThreadPoolExecutor
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from scipy import stats
from statsmodels.stats.anova import AnovaRM
import claar
pd.set_option("display.width", 220)
pd.set_option("display.max_columns", 40)
pd.set_option("display.max_rows", None)
warnings.filterwarnings("ignore", category=RuntimeWarning)
started = time.time()
urls = claar.asset_urls()
metas = [claar.read_meta(p, u) for p, u in urls]
metas = [m for m in metas if m["units"] is not None]
print(f"{len(metas)} sessions with units, dandiset {claar.DANDISET_ID} version {claar.DANDISET_VERSION}")
18 sessions with units, dandiset 000458 version 0.230317.0039
Data check¶
rows = []
for m in metas:
u = m["units"]
rows.append({"subject": m["subject"], "session": m["session"], "sites": ", ".join(sorted(m["estim"].site.unique())),
"units": len(u), "MO": int((u.group == "MO").sum()), "ACA": int((u.group == "ACA").sum()),
"SS": int((u.group == "SS").sum()), "VIS": int((u.group == "VIS").sum()), "SM-TH": int((u.group == "SM-TH").sum()),
"other": int(u.group.isna().sum()), "RS share": round(u.rs.mean(), 2),
"presence>0.9": int((u.presence_ratio > 0.9).sum()),
"isi max": round(u.isi_violations.max(), 3), "amp cutoff max": round(u.amplitude_cutoff.max(), 3),
"unit z range": f"{u.z.min():.0f}-{u.z.max():.0f}"})
ut = pd.DataFrame(rows)
print(ut.to_string(index=False))
allu = pd.concat([m["units"] for m in metas])
print("\nwaveform_duration (described as s): range", round(allu.waveform_duration.min(), 3), "to", round(allu.waveform_duration.max(), 3),
"; median", round(allu.waveform_duration.median(), 3), "-> values are in ms")
print("SM-TH acronyms present:", sorted(allu[allu.group == "SM-TH"].location.unique()))
print("cortical acronyms present:", sorted(allu[allu.group.isin(claar.CORTEX)].location.unique()))
print("acronyms with a layer suffix (e.g. MOs5):", sorted({a for a in allu.location.unique() if any(ch.isdigit() for ch in a) and not a.startswith(("CA", "DG"))}))
print("ISI violations max", allu.isi_violations.max().round(3), "; amplitude cutoff max", allu.amplitude_cutoff.max().round(3),
"; presence ratio min", allu.presence_ratio.min().round(3))
subject session sites units MO ACA SS VIS SM-TH other RS share presence>0.9 isi max amp cutoff max unit z range 546655 20201023 MOs-deep 265 18 0 0 9 30 208 0.72 126 0.486 0.094 93-184 551397 20210211 MOs-deep 607 89 136 76 0 120 186 0.86 382 0.497 0.099 165-227 551399 20210128 MOs-deep 593 99 19 120 0 82 273 0.84 416 0.494 0.100 162-227 569062 20210218 MOs-deep 902 132 154 213 0 155 248 0.87 663 0.498 0.098 113-216 569064 20210408 MOs-deep 481 29 59 4 56 0 333 0.74 322 0.492 0.099 123-209 569068 20210304 MOs-deep 338 62 2 80 0 47 147 0.78 258 0.500 0.099 90-197 569069 20210312 MOs-deep 520 32 44 0 73 56 315 0.90 403 0.494 0.099 144-221 569072 20210422 SSp-deep 995 223 85 99 90 141 357 0.83 620 0.493 0.099 96-215 569073 20210415 MOs-deep 631 29 70 24 47 100 361 0.79 358 0.500 0.099 110-229 569073 20210416 SSp-deep 705 50 116 13 23 129 374 0.84 423 0.498 0.099 111-225 571619 20210319 MOs-deep, MOs-superficial 859 103 154 14 60 62 466 0.82 501 0.496 0.100 118-223 571620 20210513 SSp-deep, SSp-superficial 771 181 33 14 11 97 435 0.81 302 0.492 0.099 131-190 575102 20210603 MOs-superficial 528 15 33 0 71 0 409 0.81 366 0.492 0.099 111-208 586466 20210729 SSp-deep, SSp-superficial 470 111 84 27 0 0 248 0.81 265 0.499 0.099 182-225 586468 20210819 SSp-deep, SSp-superficial 977 189 145 57 104 89 393 0.85 823 0.498 0.098 124-253 590479 20210921 SSp-deep, SSp-superficial 616 133 147 105 0 0 231 0.85 498 0.498 0.099 178-251 590480 20211111 SSp-deep, SSp-superficial 948 107 60 94 78 32 577 0.87 708 0.489 0.100 123-251 599017 20220210 SSp-deep, SSp-superficial 943 220 0 0 76 5 642 0.79 682 0.497 0.100 108-217 waveform_duration (described as s): range 0.096 to 2.074 ; median 0.577 -> values are in ms SM-TH acronyms present: ['AV', 'CL', 'MD', 'PO', 'RT', 'VAL', 'VPL', 'VPM'] cortical acronyms present: ['ACAd', 'ACAv', 'MOs', 'SSp-bfd', 'SSp-ll', 'SSp-tr', 'VISa', 'VISam', 'VISp', 'VISpm', 'VISrl'] acronyms with a layer suffix (e.g. MOs5): [] ISI violations max 0.5 ; amplitude cutoff max 0.1 ; presence ratio min 0.02
Waveform durations range from about 0.1 to 2 (median 0.577), which are milliseconds, not the seconds the unit table's description gives; the RS/FS split at 0.4 ms is applied to these values. Every unit meets ISI violations < 0.5 and amplitude cutoff < 0.1, but presence ratios go down to 0.02, so the file's "quality threshold" is not the three thresholds of Siegle et al. (2021); the counts are given both ways in fig4-unit-counts. Areas carry CCF acronyms without layers (MOs, SSp-ll, ...), so the layer-resolved analyses cannot be run from the files. Unit z coordinates (CCF, 25 um voxels; the midline is about 228) range from 90 to 253: most units lie on one side, but three sessions (586468, 590479, 590480) have units up to 25 voxels (0.6 mm) past 228, so the files do not show that every unit is ipsilateral.
t0 = time.time()
def load(m):
tab, sp = claar.read_units(m)
return [claar.spike_site_summary(m, s, tab, sp) for s in sorted(m["estim"].site.unique())]
with ThreadPoolExecutor(max_workers=3) as ex:
res = [r for rr in ex.map(load, metas) for r in rr]
for r in res:
r["depth"] = r["site"].split("-")[1]
print(f"{len(res)} sites with units summarised in {time.time() - t0:.0f} s")
empty = [(r["subject"], r["site"]) for r in res if r["n"][("high", "awake")] == 0 and r["n"][("medium", "awake")] == 0]
print("sites without a valid awake trial, left out:", empty)
res = [r for r in res if (r["subject"], r["site"]) not in empty]
print(pd.DataFrame([{"subject": r["subject"], "site": r["site"], **{f"{k[0]} {k[1]}": v for k, v in r["n"].items()}} for r in res]).to_string(index=False))
25 sites with units summarised in 893 s
sites without a valid awake trial, left out: [('586468', 'SSp-superficial')]
subject site high quiet high running high isoflurane high awake medium quiet medium running medium isoflurane medium awake low awake low quiet
546655 MOs-deep 38 81 75 119 40 80 109 120 120 40
551397 MOs-deep 96 24 120 120 96 24 120 120 120 85
551399 MOs-deep 106 14 120 120 108 12 120 120 118 109
569062 MOs-deep 90 30 120 120 102 18 120 120 120 94
569064 MOs-deep 117 3 119 120 116 4 118 120 120 117
569068 MOs-deep 100 20 118 120 99 21 119 120 119 96
569069 MOs-deep 80 38 119 118 82 37 120 119 120 78
569072 SSp-deep 104 16 120 120 109 11 120 120 119 108
569073 MOs-deep 100 13 120 113 86 25 120 111 112 91
569073 SSp-deep 81 37 120 118 93 24 120 117 120 95
571619 MOs-deep 103 17 120 120 97 21 120 118 119 104
571619 MOs-superficial 94 21 120 115 88 22 119 110 112 90
571620 SSp-deep 104 16 120 120 104 16 120 120 120 104
571620 SSp-superficial 88 32 120 120 93 27 120 120 120 93
575102 MOs-superficial 90 30 120 120 83 37 120 120 120 84
586466 SSp-deep 104 16 119 120 105 15 118 120 120 111
586466 SSp-superficial 114 6 117 120 113 4 119 117 120 117
586468 SSp-deep 99 21 120 120 93 27 120 120 120 98
590479 SSp-deep 99 21 120 120 101 19 120 120 120 102
590479 SSp-superficial 100 20 119 120 95 24 120 119 120 95
590480 SSp-deep 67 52 120 119 71 49 120 120 118 73
590480 SSp-superficial 30 90 120 120 35 85 120 120 120 32
599017 SSp-deep 19 100 120 119 22 98 120 120 120 18
599017 SSp-superficial 16 103 120 119 18 102 120 120 120 14
Clock check for the spikes: units of the stimulated cortex fire within 25 ms of the pulse in most deep sites (the fraction of significantly increased units at 2 to 25 ms against the same test with onsets shifted by 1 s):
rows = []
for m in metas[:6]:
tab, sp = claar.read_units(m, groups=("MO", "SS"))
for s in sorted(m["estim"].site.unique()):
tr = claar.site_trials(m, s, "high")
on = tr[tr.state.isin(["quiet", "running"])].start_time.values
stim = (tab.group == claar.STIM_AREA[s.split("-")[0]]).values
sps_ = [x for x, k in zip(sp, stim) if k]
fr = []
for shift in (0.0, 1.0):
p, sg = claar.modulation(sps_, on + shift, (0.002, 0.025))
fr.append(float(np.mean((claar.bh(p) < 0.05) & (sg > 0))))
rows.append({"subject": m["subject"], "site": s, "units": len(sps_), "increased, true onsets": round(fr[0], 3), "onsets + 1 s": round(fr[1], 3)})
print(pd.DataFrame(rows).to_string(index=False))
subject site units increased, true onsets onsets + 1 s 546655 MOs-deep 18 0.389 0.0 551397 MOs-deep 89 0.472 0.0 551399 MOs-deep 99 0.576 0.0 569062 MOs-deep 132 0.273 0.0 569064 MOs-deep 29 0.621 0.0 569068 MOs-deep 62 0.516 0.0
The contrast holds in the sessions checked: the spikes share the trial table's clock.
LEVELS, AWAKE = claar.LEVELS, ("awake", "quiet")
def unit_flags(r, level, trials, pre, family_q=None):
# per unit and window: q (BH within site and window over cortical RS + SM-TH units, or pooled q given), sign
p = r["p"]
p = p[(p.level == level) & (p.trials == trials) & (p.pre == pre)]
return p.merge(r["units"][["unit", "group", "rs", "stim", "presence_ratio"]], on="unit")
def flags_all(level, trials, pre, family, cell="RS"):
# q-values for every site: family 'site' (per site and window) or 'pooled' (all sites per window)
frames = []
for k, r in enumerate(res):
d = unit_flags(r, level, trials, pre)
d["site_idx"] = k
d["subject"], d["site"], d["depth"] = r["subject"], r["site"], r["depth"]
cort = d.group.isin(claar.CORTEX)
keep = ((cort & (d.rs if cell == "RS" else ~d.rs)) | (d.group == "SM-TH")) if cell == "RS" else (cort & ~d.rs)
frames.append(d[keep])
d = pd.concat(frames).reset_index(drop=True)
d["q"] = np.nan
if family == "site":
for key, g in d.groupby(["site_idx", "window"]):
d.loc[g.index, "q"] = claar.bh(g.p.values)
else:
d = d.reset_index(drop=True)
for w, g in d.groupby("window"):
d.loc[g.index, "q"] = claar.bh(g.p.values)
d["inc"] = (d.q < 0.05) & (d.sign > 0)
d["dec"] = (d.q < 0.05) & (d.sign < 0)
d["mod"] = d.q < 0.05
return d
combos = [(lvl, tr, pre, fam) for lvl in LEVELS for tr in AWAKE for pre in claar.PRE_READINGS for fam in ("site", "pooled")]
FL = {}
for c in combos:
FL[c] = flags_all(*c)
FL[c + ("FS",)] = flags_all(*c, cell="FS")
print("flag tables:", len(FL))
flag tables: 32
fig3abc-decay-with-distance and fig3d-magnitudes: the spiking part¶
Both claims are decided in claar_lfp.ipynb, which computes the LFP and CSD part. The spiking magnitudes need only the RS units of each area, and are computed here as the criterion of fig3d-magnitudes describes (claar.spiking_magnitude): all awake trials, kernels of 5 and 10 ms, baselines -2 to 0 and -0.5 to 0 s, onsets shuffled within -2 to +2 s or over the recording, 1000 shuffles. Units of layer 1 cannot be left out. Two signals are integrated: the signed z of the Methods ("signed"), in which a fall below baseline cancels a rise, and |z| (a variant after the verifier's round 2, supported by the Results' "our magnitude metric accounts for both reductions as well as increases"). These numbers do not decide the outcomes. The shuffle "none" rows give the AUC of the z-scored density itself (SD.s), before the comparison with the shuffles.
MAG = pd.concat([r["magnitude"].assign(subject=r["subject"], site=r["site"], depth=r["depth"], site_idx=k)
for k, r in enumerate(res) if len(r["magnitude"])], ignore_index=True)
ex = MAG[(MAG.subject == "571619") & (MAG.site == "MOs-deep")]
print("example 571619 MOs-deep (expected MO 30.9, VIS 1.8 SD.s):")
print(ex.pivot_table(index=["level", "shuffle", "kernel ms", "baseline"], columns=["signal", "group"], values="magnitude").round(2).to_string())
rows = []
for (sig, lvl, sh, kern, base), g in MAG.groupby(["signal", "level", "shuffle", "kernel ms", "baseline"]):
for unit in ("mouse", "region"):
out = {"signal": sig, "level": lvl, "shuffle": sh, "kernel ms": kern, "baseline": base, "unit": unit}
ps = {}
for dep in ("superficial", "deep"):
for st, lab in ((True, "stim"), (False, "non-stim")):
x = g[(g.depth == dep) & (g.stim == st)]
if unit == "mouse":
x = x.groupby("subject").magnitude.mean()
else:
x = x.magnitude
ps[(dep, lab)] = stats.wilcoxon(x).pvalue if len(x) > 1 else np.nan
out[f"{dep} {lab} median (n)"] = f"{np.median(x):.2f} ({len(x)})"
q = claar.bh(list(ps.values()))
for (k, v), qq in zip(ps.items(), q):
out[f"q {k[0][:3]} {k[1]}"] = round(qq, 4)
rows.append(out)
f3 = pd.DataFrame(rows)
print("\nmedians per group and signed-rank tests against 0 (BH over the four spiking tests); "
"expected medians superficial stimulated 1.8, deep stimulated 29.3, deep non-stimulated 4.4; superficial non-stimulated not significant")
print(f3.to_string(index=False))
exp3 = {("superficial", "stim"): (1.8, 0.18), ("deep", "stim"): (29.3, 2.93), ("deep", "non-stim"): (4.4, 0.44)}
def holds(row):
med = {k: float(row[f"{k[0]} {k[1]} median (n)"].split()[0]) for k in exp3}
inside = [k for k in exp3 if abs(med[k] - exp3[k][0]) <= exp3[k][1]]
sig = (row["q sup stim"] < 0.05 and med[("superficial", "stim")] > 0 and row["q dee stim"] < 0.05 and med[("deep", "stim")] > 0
and row["q dee non-stim"] < 0.05 and med[("deep", "non-stim")] > 0 and row["q sup non-stim"] >= 0.05)
return pd.Series({"spiking significance pattern": sig, "spiking medians within tolerance": len(inside)})
f3 = pd.concat([f3, f3.apply(holds, axis=1)], axis=1)
print("\nspiking significance pattern of the paper (stimulated groups and deep non-stimulated q < 0.05 with positive medians, superficial non-stimulated not significant):")
print(f3.groupby(["signal", "shuffle"])[["spiking significance pattern"]].sum().to_string(), "of", int(f3.groupby(["signal", "shuffle"]).size().iloc[0]), "rows each")
print(f3[f3["spiking significance pattern"] | (f3["spiking medians within tolerance"] >= 2)].to_string(index=False))
example 571619 MOs-deep (expected MO 30.9, VIS 1.8 SD.s):
signal signed |z|
group ACA MO SS VIS ACA MO SS VIS
level shuffle kernel ms baseline
high epoch 5 -0.5-0 0.59 1.46 -1.66 -1.29 4.82 11.22 0.73 1.30
-2-0 0.64 3.96 -2.39 -1.21 5.63 28.31 1.06 2.11
10 -0.5-0 0.60 0.59 -1.61 -1.18 3.76 3.57 0.60 0.52
-2-0 0.66 2.30 -2.25 -1.20 4.94 13.02 0.93 1.37
none 5 -0.5-0 0.13 0.34 -0.32 -0.35 1.12 1.75 0.51 0.60
-2-0 0.04 0.70 -0.37 -0.33 0.97 2.96 0.48 0.60
10 -0.5-0 0.17 0.14 -0.42 -0.43 1.26 1.08 0.56 0.59
-2-0 0.06 0.42 -0.44 -0.41 1.09 2.02 0.50 0.61
recording 5 -0.5-0 0.38 1.29 -1.84 -1.34 4.05 11.19 0.87 1.27
-2-0 0.11 3.09 -2.50 -1.35 3.59 29.19 1.07 2.08
10 -0.5-0 0.38 0.44 -1.77 -1.18 3.06 3.45 0.75 0.43
-2-0 0.12 1.58 -2.31 -1.30 3.13 13.70 0.93 1.26
medium epoch 5 -0.5-0 -0.66 1.18 -0.36 -1.24 2.43 13.14 -0.08 0.97
-2-0 -1.62 2.95 -0.84 -2.14 5.26 28.75 1.08 2.76
10 -0.5-0 -0.62 0.31 -0.38 -1.62 1.97 5.04 0.05 2.09
-2-0 -1.63 1.74 -0.87 -2.31 4.78 16.50 1.28 3.17
none 5 -0.5-0 -0.20 0.40 -0.08 -0.36 0.77 2.11 0.43 0.56
-2-0 -0.42 0.71 -0.12 -0.52 0.93 3.04 0.47 0.64
10 -0.5-0 -0.24 0.21 -0.11 -0.61 0.87 1.41 0.48 0.84
-2-0 -0.51 0.53 -0.16 -0.70 1.06 2.41 0.53 0.80
recording 5 -0.5-0 -0.56 1.45 -0.44 -1.33 1.71 15.21 -0.03 0.95
-2-0 -1.26 3.13 -0.86 -2.16 3.72 31.37 1.05 2.65
10 -0.5-0 -0.51 0.58 -0.45 -1.64 1.28 5.91 0.09 1.92
-2-0 -1.27 1.95 -0.86 -2.25 3.37 17.76 1.28 2.91
medians per group and signed-rank tests against 0 (BH over the four spiking tests); expected medians superficial stimulated 1.8, deep stimulated 29.3, deep non-stimulated 4.4; superficial non-stimulated not significant
signal level shuffle kernel ms baseline unit superficial stim median (n) superficial non-stim median (n) deep stim median (n) deep non-stim median (n) q sup stim q sup non-stim q dee stim q dee non-stim
signed high epoch 5 -0.5-0 mouse 0.79 (6) -0.17 (7) 0.48 (15) -0.39 (16) 1.0000 1.0000 1.0000 0.8457
signed high epoch 5 -0.5-0 region 0.79 (6) -0.29 (17) -0.00 (16) 0.15 (41) 1.0000 1.0000 1.0000 1.0000
signed high epoch 5 -2-0 mouse 0.95 (6) 0.22 (7) 1.69 (15) -0.55 (16) 0.8125 0.8125 0.8125 0.8125
signed high epoch 5 -2-0 region 0.95 (6) 0.34 (17) 0.70 (16) 0.02 (41) 0.7100 0.7100 0.7100 0.7100
signed high epoch 10 -0.5-0 mouse 0.41 (6) -0.17 (7) -0.04 (15) -0.41 (16) 0.7500 0.9375 0.7500 0.7500
signed high epoch 10 -0.5-0 region 0.41 (6) -0.27 (17) -0.30 (16) -0.00 (41) 0.7500 0.8536 0.7500 0.7500
signed high epoch 10 -2-0 mouse 0.67 (6) 0.24 (7) 0.71 (15) -0.52 (16) 0.9167 0.9167 0.9780 0.9167
signed high epoch 10 -2-0 region 0.67 (6) 0.39 (17) 0.04 (16) 0.01 (41) 0.9339 0.9339 0.9399 0.9339
signed high none 5 -0.5-0 mouse 0.15 (6) -0.04 (7) 0.13 (15) -0.11 (16) 0.9375 0.9375 0.9375 0.7712
signed high none 5 -0.5-0 region 0.15 (6) -0.05 (17) -0.00 (16) 0.03 (41) 1.0000 1.0000 1.0000 1.0000
signed high none 5 -2-0 mouse 0.14 (6) -0.01 (7) 0.31 (15) -0.09 (16) 0.9375 0.9375 0.9375 0.9375
signed high none 5 -2-0 region 0.14 (6) 0.05 (17) 0.16 (16) -0.04 (41) 0.8438 0.8438 0.8438 0.8438
signed high none 10 -0.5-0 mouse 0.10 (6) -0.06 (7) 0.03 (15) -0.14 (16) 1.0000 1.0000 0.7788 0.6362
signed high none 10 -0.5-0 region 0.10 (6) -0.06 (17) -0.08 (16) -0.00 (41) 0.9265 0.9265 0.8075 0.8075
signed high none 10 -2-0 mouse 0.14 (6) -0.01 (7) 0.17 (15) -0.13 (16) 0.9341 0.9341 0.9341 0.9341
signed high none 10 -2-0 region 0.14 (6) 0.08 (17) 0.05 (16) -0.05 (41) 0.9799 0.9799 0.9799 0.9799
signed high recording 5 -0.5-0 mouse 0.74 (6) -0.14 (7) 0.56 (15) -0.31 (16) 0.8750 0.9375 0.9375 0.6362
signed high recording 5 -0.5-0 region 0.74 (6) -0.18 (17) 0.06 (16) 0.06 (41) 0.8750 1.0000 1.0000 0.8750
signed high recording 5 -2-0 mouse 0.96 (6) -0.02 (7) 1.55 (15) -0.32 (16) 0.9596 1.0000 0.9596 0.9596
signed high recording 5 -2-0 region 0.96 (6) 0.13 (17) 0.77 (16) -0.15 (41) 0.7467 0.7467 0.7467 0.7467
signed high recording 10 -0.5-0 mouse 0.37 (6) -0.14 (7) 0.06 (15) -0.31 (16) 0.7500 0.9375 0.7500 0.5754
signed high recording 10 -0.5-0 region 0.37 (6) -0.16 (17) -0.22 (16) -0.00 (41) 0.7955 1.0000 0.7955 0.7955
signed high recording 10 -2-0 mouse 0.70 (6) -0.00 (7) 0.68 (15) -0.37 (16) 1.0000 1.0000 1.0000 1.0000
signed high recording 10 -2-0 region 0.70 (6) 0.17 (17) 0.18 (16) -0.17 (41) 0.9167 0.9167 0.9399 0.9167
signed medium epoch 5 -0.5-0 mouse -0.02 (6) 0.30 (7) 0.14 (15) -0.54 (16) 1.0000 1.0000 1.0000 0.1772
signed medium epoch 5 -0.5-0 region -0.02 (6) 0.16 (17) 0.13 (16) -0.83 (41) 1.0000 0.6121 1.0000 0.0921
signed medium epoch 5 -2-0 mouse -0.18 (6) 0.44 (7) 1.53 (15) -1.16 (16) 1.0000 0.3125 1.0000 0.0367
signed medium epoch 5 -2-0 region -0.18 (6) 0.33 (17) 1.55 (16) -0.89 (41) 1.0000 0.1428 0.7955 0.0224
signed medium epoch 10 -0.5-0 mouse -0.04 (6) 0.28 (7) -0.20 (15) -0.52 (16) 0.8438 0.8438 0.8438 0.1160
signed medium epoch 10 -0.5-0 region -0.04 (6) 0.22 (17) -0.19 (16) -0.77 (41) 0.8438 0.5683 0.8438 0.0921
signed medium epoch 10 -2-0 mouse -0.19 (6) 0.43 (7) 0.71 (15) -1.10 (16) 1.0000 0.2188 1.0000 0.0367
signed medium epoch 10 -2-0 region -0.19 (6) 0.34 (17) 0.96 (16) -0.93 (41) 1.0000 0.1428 1.0000 0.0189
signed medium none 5 -0.5-0 mouse 0.01 (6) 0.07 (7) 0.02 (15) -0.14 (16) 1.0000 0.9375 1.0000 0.1772
signed medium none 5 -0.5-0 region 0.01 (6) 0.07 (17) 0.03 (16) -0.20 (41) 1.0000 0.3802 1.0000 0.0798
signed medium none 5 -2-0 mouse 0.02 (6) 0.11 (7) 0.29 (15) -0.28 (16) 0.8040 0.3125 0.8040 0.0439
signed medium none 5 -2-0 region 0.02 (6) 0.06 (17) 0.32 (16) -0.16 (41) 0.6875 0.0696 0.6875 0.0289
signed medium none 10 -0.5-0 mouse -0.03 (6) 0.09 (7) -0.06 (15) -0.18 (16) 0.8438 0.6250 0.6250 0.1342
signed medium none 10 -0.5-0 region -0.03 (6) 0.10 (17) -0.06 (16) -0.24 (41) 0.8438 0.3802 0.7042 0.1024
signed medium none 10 -2-0 mouse 0.03 (6) 0.14 (7) 0.17 (15) -0.36 (16) 0.9167 0.2188 0.9780 0.0524
signed medium none 10 -2-0 region 0.03 (6) 0.10 (17) 0.19 (16) -0.22 (41) 0.8999 0.0403 0.8999 0.0289
signed medium recording 5 -0.5-0 mouse 0.10 (6) 0.19 (7) 0.10 (15) -0.43 (16) 1.0000 1.0000 1.0000 0.2307
signed medium recording 5 -0.5-0 region 0.10 (6) 0.16 (17) 0.09 (16) -0.56 (41) 1.0000 0.4870 0.9914 0.0593
signed medium recording 5 -2-0 mouse 0.22 (6) 0.35 (7) 1.41 (15) -1.03 (16) 0.6875 0.4375 0.6516 0.0620
signed medium recording 5 -2-0 region 0.22 (6) 0.26 (17) 1.45 (16) -0.86 (41) 0.6875 0.0696 0.5383 0.0245
signed medium recording 10 -0.5-0 mouse -0.07 (6) 0.19 (7) -0.21 (15) -0.43 (16) 1.0000 0.9050 0.9050 0.1772
signed medium recording 10 -0.5-0 region -0.07 (6) 0.20 (17) -0.19 (16) -0.59 (41) 1.0000 0.4870 1.0000 0.0615
signed medium recording 10 -2-0 mouse 0.21 (6) 0.39 (7) 0.70 (15) -1.05 (16) 0.7615 0.2188 0.7615 0.0620
signed medium recording 10 -2-0 region 0.21 (6) 0.29 (17) 0.73 (16) -0.86 (41) 0.6875 0.0300 0.6875 0.0245
|z| high epoch 5 -0.5-0 mouse 5.35 (6) 0.63 (7) 11.22 (15) 9.84 (16) 0.0417 0.2969 0.0001 0.0001
|z| high epoch 5 -0.5-0 region 5.35 (6) 0.13 (17) 11.99 (16) 8.57 (41) 0.0417 0.0569 0.0001 0.0000
|z| high epoch 5 -2-0 mouse 9.85 (6) 0.91 (7) 28.44 (15) 12.62 (16) 0.0417 0.0469 0.0001 0.0001
|z| high epoch 5 -2-0 region 9.85 (6) 0.79 (17) 28.60 (16) 11.14 (41) 0.0312 0.0014 0.0001 0.0000
|z| high epoch 10 -0.5-0 mouse 4.11 (6) 0.11 (7) 4.91 (15) 9.38 (16) 0.0417 0.5781 0.0001 0.0001
|z| high epoch 10 -0.5-0 region 4.11 (6) 0.09 (17) 6.22 (16) 6.51 (41) 0.0417 0.2247 0.0001 0.0000
|z| high epoch 10 -2-0 mouse 7.13 (6) 0.76 (7) 16.92 (15) 11.11 (16) 0.0417 0.0781 0.0001 0.0001
|z| high epoch 10 -2-0 region 7.13 (6) 0.43 (17) 19.31 (16) 9.58 (41) 0.0312 0.0089 0.0001 0.0000
|z| high none 5 -0.5-0 mouse 1.07 (6) 0.51 (7) 1.43 (15) 1.38 (16) 0.0312 0.0208 0.0001 0.0001
|z| high none 5 -0.5-0 region 1.07 (6) 0.47 (17) 1.59 (16) 1.23 (41) 0.0312 0.0000 0.0000 0.0000
|z| high none 5 -2-0 mouse 1.09 (6) 0.49 (7) 2.60 (15) 1.33 (16) 0.0312 0.0208 0.0001 0.0001
|z| high none 5 -2-0 region 1.09 (6) 0.48 (17) 2.74 (16) 1.23 (41) 0.0312 0.0000 0.0000 0.0000
|z| high none 10 -0.5-0 mouse 1.04 (6) 0.53 (7) 1.20 (15) 1.70 (16) 0.0312 0.0208 0.0001 0.0001
|z| high none 10 -0.5-0 region 1.04 (6) 0.52 (17) 1.25 (16) 1.46 (41) 0.0312 0.0000 0.0000 0.0000
|z| high none 10 -2-0 mouse 1.13 (6) 0.51 (7) 2.15 (15) 1.56 (16) 0.0312 0.0208 0.0001 0.0001
|z| high none 10 -2-0 region 1.13 (6) 0.50 (17) 2.17 (16) 1.53 (41) 0.0312 0.0000 0.0000 0.0000
|z| high recording 5 -0.5-0 mouse 4.36 (6) 0.02 (7) 11.19 (15) 8.40 (16) 0.0417 0.5781 0.0001 0.0001
|z| high recording 5 -0.5-0 region 4.36 (6) -0.14 (17) 11.80 (16) 6.01 (41) 0.0417 0.6112 0.0001 0.0000
|z| high recording 5 -2-0 mouse 9.40 (6) 0.48 (7) 28.52 (15) 10.46 (16) 0.0417 0.1094 0.0001 0.0001
|z| high recording 5 -2-0 region 9.40 (6) 0.48 (17) 28.54 (16) 7.26 (41) 0.0312 0.0146 0.0001 0.0000
|z| high recording 10 -0.5-0 mouse 3.49 (6) -0.05 (7) 4.42 (15) 8.53 (16) 0.0417 0.8125 0.0001 0.0001
|z| high recording 10 -0.5-0 region 3.49 (6) -0.07 (17) 5.36 (16) 5.17 (41) 0.0417 0.5171 0.0001 0.0000
|z| high recording 10 -2-0 mouse 6.76 (6) 0.30 (7) 15.52 (15) 9.88 (16) 0.0417 0.1562 0.0001 0.0001
|z| high recording 10 -2-0 region 6.76 (6) 0.34 (17) 18.08 (16) 7.21 (41) 0.0312 0.0312 0.0001 0.0000
|z| medium epoch 5 -0.5-0 mouse 3.28 (6) 0.52 (7) 13.14 (15) 4.41 (16) 0.0417 0.8125 0.0001 0.0001
|z| medium epoch 5 -0.5-0 region 3.28 (6) -0.10 (17) 14.18 (16) 4.84 (41) 0.0417 0.6112 0.0001 0.0000
|z| medium epoch 5 -2-0 mouse 4.81 (6) 0.02 (7) 29.18 (15) 6.25 (16) 0.0417 0.3750 0.0001 0.0001
|z| medium epoch 5 -2-0 region 4.81 (6) 0.18 (17) 28.97 (16) 5.85 (41) 0.0417 0.3289 0.0001 0.0000
|z| medium epoch 10 -0.5-0 mouse 2.17 (6) 0.36 (7) 6.94 (15) 3.68 (16) 0.0417 0.8125 0.0001 0.0001
|z| medium epoch 10 -0.5-0 region 2.17 (6) -0.30 (17) 7.79 (16) 3.94 (41) 0.0417 0.6777 0.0001 0.0000
|z| medium epoch 10 -2-0 mouse 3.68 (6) -0.10 (7) 21.43 (15) 5.62 (16) 0.0417 0.6875 0.0001 0.0001
|z| medium epoch 10 -2-0 region 3.68 (6) 0.16 (17) 21.14 (16) 5.37 (41) 0.0417 0.4307 0.0001 0.0000
|z| medium none 5 -0.5-0 mouse 0.67 (6) 0.49 (7) 1.69 (15) 0.83 (16) 0.0312 0.0208 0.0001 0.0001
|z| medium none 5 -0.5-0 region 0.67 (6) 0.44 (17) 1.77 (16) 0.90 (41) 0.0312 0.0000 0.0000 0.0000
|z| medium none 5 -2-0 mouse 0.69 (6) 0.43 (7) 2.88 (15) 0.87 (16) 0.0312 0.0208 0.0001 0.0001
|z| medium none 5 -2-0 region 0.69 (6) 0.44 (17) 2.79 (16) 0.83 (41) 0.0312 0.0000 0.0000 0.0000
|z| medium none 10 -0.5-0 mouse 0.79 (6) 0.54 (7) 1.53 (15) 1.01 (16) 0.0312 0.0208 0.0001 0.0001
|z| medium none 10 -0.5-0 region 0.79 (6) 0.46 (17) 1.54 (16) 1.13 (41) 0.0312 0.0000 0.0000 0.0000
|z| medium none 10 -2-0 mouse 0.76 (6) 0.43 (7) 2.49 (15) 1.01 (16) 0.0312 0.0208 0.0001 0.0001
|z| medium none 10 -2-0 region 0.76 (6) 0.47 (17) 2.45 (16) 1.03 (41) 0.0312 0.0000 0.0000 0.0000
|z| medium recording 5 -0.5-0 mouse 3.31 (6) -0.06 (7) 12.47 (15) 3.00 (16) 0.0417 0.9375 0.0001 0.0001
|z| medium recording 5 -0.5-0 region 3.31 (6) -0.46 (17) 13.08 (16) 3.36 (41) 0.0417 1.0000 0.0001 0.0000
|z| medium recording 5 -2-0 mouse 4.86 (6) -0.08 (7) 28.15 (15) 4.54 (16) 0.0417 1.0000 0.0001 0.0001
|z| medium recording 5 -2-0 region 4.86 (6) 0.10 (17) 27.96 (16) 4.18 (41) 0.0417 0.6112 0.0001 0.0000
|z| medium recording 10 -0.5-0 mouse 1.95 (6) -0.10 (7) 7.27 (15) 2.33 (16) 0.0417 0.9375 0.0001 0.0001
|z| medium recording 10 -0.5-0 region 1.95 (6) -0.46 (17) 7.26 (16) 2.28 (41) 0.0417 0.9632 0.0001 0.0000
|z| medium recording 10 -2-0 mouse 4.02 (6) -0.14 (7) 20.12 (15) 4.33 (16) 0.0417 1.0000 0.0001 0.0001
|z| medium recording 10 -2-0 region 4.02 (6) 0.15 (17) 19.97 (16) 3.49 (41) 0.0417 0.6112 0.0001 0.0000
spiking significance pattern of the paper (stimulated groups and deep non-stimulated q < 0.05 with positive medians, superficial non-stimulated not significant):
spiking significance pattern
signal shuffle
signed epoch 0
none 0
recording 0
|z| epoch 13
none 0
recording 14 of 16 rows each
signal level shuffle kernel ms baseline unit superficial stim median (n) superficial non-stim median (n) deep stim median (n) deep non-stim median (n) q sup stim q sup non-stim q dee stim q dee non-stim spiking significance pattern spiking medians within tolerance
|z| high epoch 5 -0.5-0 mouse 5.35 (6) 0.63 (7) 11.22 (15) 9.84 (16) 0.0417 0.2969 0.0001 0.0001 True 0
|z| high epoch 5 -0.5-0 region 5.35 (6) 0.13 (17) 11.99 (16) 8.57 (41) 0.0417 0.0569 0.0001 0.0000 True 0
|z| high epoch 10 -0.5-0 mouse 4.11 (6) 0.11 (7) 4.91 (15) 9.38 (16) 0.0417 0.5781 0.0001 0.0001 True 0
|z| high epoch 10 -0.5-0 region 4.11 (6) 0.09 (17) 6.22 (16) 6.51 (41) 0.0417 0.2247 0.0001 0.0000 True 0
|z| high epoch 10 -2-0 mouse 7.13 (6) 0.76 (7) 16.92 (15) 11.11 (16) 0.0417 0.0781 0.0001 0.0001 True 0
|z| high recording 5 -0.5-0 mouse 4.36 (6) 0.02 (7) 11.19 (15) 8.40 (16) 0.0417 0.5781 0.0001 0.0001 True 0
|z| high recording 5 -0.5-0 region 4.36 (6) -0.14 (17) 11.80 (16) 6.01 (41) 0.0417 0.6112 0.0001 0.0000 True 0
|z| high recording 5 -2-0 mouse 9.40 (6) 0.48 (7) 28.52 (15) 10.46 (16) 0.0417 0.1094 0.0001 0.0001 True 1
|z| high recording 10 -0.5-0 mouse 3.49 (6) -0.05 (7) 4.42 (15) 8.53 (16) 0.0417 0.8125 0.0001 0.0001 True 0
|z| high recording 10 -0.5-0 region 3.49 (6) -0.07 (17) 5.36 (16) 5.17 (41) 0.0417 0.5171 0.0001 0.0000 True 0
|z| high recording 10 -2-0 mouse 6.76 (6) 0.30 (7) 15.52 (15) 9.88 (16) 0.0417 0.1562 0.0001 0.0001 True 0
|z| medium epoch 5 -0.5-0 mouse 3.28 (6) 0.52 (7) 13.14 (15) 4.41 (16) 0.0417 0.8125 0.0001 0.0001 True 1
|z| medium epoch 5 -0.5-0 region 3.28 (6) -0.10 (17) 14.18 (16) 4.84 (41) 0.0417 0.6112 0.0001 0.0000 True 1
|z| medium epoch 5 -2-0 mouse 4.81 (6) 0.02 (7) 29.18 (15) 6.25 (16) 0.0417 0.3750 0.0001 0.0001 True 1
|z| medium epoch 5 -2-0 region 4.81 (6) 0.18 (17) 28.97 (16) 5.85 (41) 0.0417 0.3289 0.0001 0.0000 True 1
|z| medium epoch 10 -0.5-0 mouse 2.17 (6) 0.36 (7) 6.94 (15) 3.68 (16) 0.0417 0.8125 0.0001 0.0001 True 0
|z| medium epoch 10 -0.5-0 region 2.17 (6) -0.30 (17) 7.79 (16) 3.94 (41) 0.0417 0.6777 0.0001 0.0000 True 0
|z| medium epoch 10 -2-0 mouse 3.68 (6) -0.10 (7) 21.43 (15) 5.62 (16) 0.0417 0.6875 0.0001 0.0001 True 0
|z| medium epoch 10 -2-0 region 3.68 (6) 0.16 (17) 21.14 (16) 5.37 (41) 0.0417 0.4307 0.0001 0.0000 True 0
|z| medium recording 5 -0.5-0 mouse 3.31 (6) -0.06 (7) 12.47 (15) 3.00 (16) 0.0417 0.9375 0.0001 0.0001 True 0
|z| medium recording 5 -0.5-0 region 3.31 (6) -0.46 (17) 13.08 (16) 3.36 (41) 0.0417 1.0000 0.0001 0.0000 True 0
|z| medium recording 5 -2-0 mouse 4.86 (6) -0.08 (7) 28.15 (15) 4.54 (16) 0.0417 1.0000 0.0001 0.0001 True 2
|z| medium recording 5 -2-0 region 4.86 (6) 0.10 (17) 27.96 (16) 4.18 (41) 0.0417 0.6112 0.0001 0.0000 True 2
|z| medium recording 10 -0.5-0 mouse 1.95 (6) -0.10 (7) 7.27 (15) 2.33 (16) 0.0417 0.9375 0.0001 0.0001 True 1
|z| medium recording 10 -0.5-0 region 1.95 (6) -0.46 (17) 7.26 (16) 2.28 (41) 0.0417 0.9632 0.0001 0.0000 True 1
|z| medium recording 10 -2-0 mouse 4.02 (6) -0.14 (7) 20.12 (15) 4.33 (16) 0.0417 1.0000 0.0001 0.0001 True 1
|z| medium recording 10 -2-0 region 4.02 (6) 0.15 (17) 19.97 (16) 3.49 (41) 0.0417 0.6112 0.0001 0.0000 True 0
Result: spiking part only (the outcomes are in claar_lfp.ipynb). In the example session (571619, deep MOs) the MO spiking magnitude exceeds the VIS one in every reading. With the signed z of the Methods the values are far below the paper's (for example 3.96 against -1.21, high current, epoch shuffle, 5 ms kernel, -2 to 0 s), no stimulated group is significantly above zero after correction in any reading, and the deep non-stimulated medians are -1.16 to 0.15, against 4.4. With |z| the example gives 28.31 to 31.37 in MO with the 5 ms kernel and the -2 to 0 s baseline (30.9 in the paper) and 2.08 to 2.76 in VIS (1.8), and the paper's spiking significance pattern (both stimulated groups and the deep non-stimulated group above zero, the superficial non-stimulated group not significant) holds in 27 of the 32 shuffled rows (13 epoch, 14 recording). With |z|, the 5 ms kernel and the -2 to 0 s baseline at the medium current, the deep stimulated median is 27.96 to 29.18 (29.3 +/- 2.93) and the deep non-stimulated median 4.18 to 6.25 (4.4 +/- 0.44), but the superficial stimulated median is 4.81 to 4.86, against 1.8. The integral of |z| thus comes close to the paper's spiking magnitudes where the signed integral does not, which suggests that the paper's magnitude counts falls below baseline. These numbers do not decide the outcomes; the LFP and CSD part of fig3d-magnitudes is not run (claar_lfp.ipynb).
fig4-unit-counts¶
Figure 4 rests on 870 RS units from stimulated and 4110 from non-stimulated cortex in 7 mice with superficial stimulation, and 2559 and 9363 in 17 mice with deep stimulation.
rows = []
for qc in ("dataset", "siegle"):
for cell in ("RS", "FS"):
d = []
for r in res:
u = r["units"]
u = u[u.group.isin(claar.CORTEX) & (u.rs if cell == "RS" else ~u.rs)]
if qc == "siegle":
u = u[u.presence_ratio > 0.9]
d.append({"subject": r["subject"], "depth": r["depth"], "stim": int(u.stim.sum()), "nonstim": int((~u.stim).sum())})
d = pd.DataFrame(d)
for dep in ("superficial", "deep"):
x = d[d.depth == dep]
rows.append({"units": qc, "cell": cell, "depth": dep, "sites": len(x), "mice": x.subject.nunique(),
"stimulated": int(x.stim.sum()), "non-stimulated": int(x.nonstim.sum())})
cnt = pd.DataFrame(rows)
print(cnt.to_string(index=False))
print("\nexpected RS: superficial 870 / 4110 (7 mice), deep 2559 / 9363 (17 mice); FS: 180 / 585 (7), 387 / 1422 (16)")
# reading not in the claims file (verifier, round 1): each unit counted once per current with valid awake trials
rows = []
for r in res:
u = r["units"]
m = [mm for mm in metas if mm["subject"] == r["subject"] and mm["session"] == r["session"]][0]
el = m["estim"].query("site == @r['site'] and is_valid and state in ['quiet', 'running']")
nc = el.current.nunique()
for cell in ("RS", "FS"):
x = u[u.group.isin(claar.CORTEX) & (u.rs if cell == "RS" else ~u.rs)]
rows.append({"depth": r["depth"], "cell": cell, "currents": nc, "stim": nc * int(x.stim.sum()), "nonstim": nc * int((~x.stim).sum())})
pooled_cnt = pd.DataFrame(rows).groupby(["cell", "depth"])[["stim", "nonstim"]].sum()
print("\nunits x currents (each unit counted once per current with valid awake trials):")
print(pooled_cnt.to_string())
print("currents per site:", pd.DataFrame(rows).query("cell == 'RS'").currents.value_counts().to_dict())
units cell depth sites mice stimulated non-stimulated dataset RS superficial 7 7 290 1370 dataset RS deep 17 16 853 3162 dataset FS superficial 7 7 68 203 dataset FS deep 17 16 149 518 siegle RS superficial 7 7 221 1020 siegle RS deep 17 16 665 2421 siegle FS superficial 7 7 46 161 siegle FS deep 17 16 108 417 expected RS: superficial 870 / 4110 (7 mice), deep 2559 / 9363 (17 mice); FS: 180 / 585 (7), 387 / 1422 (16)
units x currents (each unit counted once per current with valid awake trials):
stim nonstim
cell depth
FS deep 447 1554
superficial 204 609
RS deep 2559 9486
superficial 870 4110
currents per site: {3: 24}
Result: not reproduced. The files hold 290 and 1370 RS units in stimulated and other cortex for the 7 superficial sites and 853 and 3162 for the 17 deep sites (16 mice): exactly one third of the legend's 870, 4110 and 2559, and 1.3% more than a third of its 9363. The site counts, 7 and 17, match the legend's N. With presence ratio > 0.9 the counts fall further (221, 1020, 665, 2421). Counting each unit once per current with valid awake trials (all 24 sites have three currents) gives 870, 4110, 2559 and 9486 RS units, the legend's first three counts exactly and 1.3% above its 9363, and 204, 609, 447 and 1554 FS units against 180, 585, 387 and 1422. This reading is not in the claims file and is asked of a reader; the outcome stays on the claims file's count of units.
fig4ad-initial-excitation¶
In the initial excitation window (2 to 25 ms), the fraction of activated RS neurons is always higher in stimulated cortex than elsewhere; across 24 animals an average of 0.5% (0 to 2.6%) of neurons in non-stimulated regions were modulated against 17.8% (0 to 83.3%) in stimulated cortex, and about three times more cortical neurons respond to deep than to superficial stimulation.
def area_fractions(d, window, cell_mask=None):
# per site and cortical area: fractions of RS units increased, decreased, modulated
x = d[(d.window == window) & d.group.isin(claar.CORTEX)]
g = x.groupby(["site_idx", "subject", "depth", "group", "stim"]).agg(n=("unit", "size"), inc=("inc", "mean"), dec=("dec", "mean"), mod=("mod", "mean")).reset_index()
return g
rows = []
for c in combos:
d = FL[c]
g = area_fractions(d, "early")
st, ns = g[g.stim], g[~g.stim]
# non-stimulated pooled per site
x = d[(d.window == "early") & d.group.isin(claar.CORTEX) & ~d.stim]
nsp = x.groupby("site_idx").agg(inc=("inc", "mean"), mod=("mod", "mean")) # non-stimulated areas pooled per session
stim_inc = st.set_index("site_idx").inc
order_pooled = all(stim_inc.get(k, 0) > nsp.inc.get(k, 0) for k in stim_inc.index)
order_region = all(stim_inc.get(k, 0) > v for k, v in zip(ns.site_idx, ns.inc))
ratio_a = st[st.depth == "deep"]["mod"].mean() / st[st.depth == "superficial"]["mod"].mean()
anyw = d[d.group.isin(claar.CORTEX) & d.stim & d.window.isin(["early", "off", "rebound"])].groupby(["site_idx", "depth", "unit"])["mod"].any().reset_index()
anyw = anyw.groupby(["site_idx", "depth"])["mod"].mean().reset_index()
ratio_b = anyw[anyw.depth == "deep"]["mod"].mean() / anyw[anyw.depth == "superficial"]["mod"].mean()
rows.append({"level": c[0], "trials": c[1], "pre": c[2], "FDR": c[3], "stim sites": len(st),
"non-stim mean %": round(100 * ns["mod"].mean(), 2), "non-stim max %": round(100 * ns["mod"].max(), 2),
"non-stim pooled per session mean %": round(100 * nsp["mod"].mean(), 2), "max %": round(100 * nsp["mod"].max(), 2),
"stim mean %": round(100 * st["mod"].mean(), 2), "stim max %": round(100 * st["mod"].max(), 2), "stim min %": round(100 * st["mod"].min(), 2),
"inc stim > non-stim (pooled)": order_pooled, "(every region)": order_region,
"ratio deep/sup (a)": round(ratio_a, 2), "ratio (b)": round(ratio_b, 2)})
f4a = pd.DataFrame(rows)
f4a["values within tol"] = (abs(f4a["non-stim mean %"] - 0.5) <= 0.05) & (abs(f4a["non-stim max %"] - 2.6) <= 0.26) & (abs(f4a["stim mean %"] - 17.8) <= 1.78) & (abs(f4a["stim max %"] - 83.3) <= 8.33)
f4a["ratio 2-4"] = f4a["ratio deep/sup (a)"].between(2, 4) | f4a["ratio (b)"].between(2, 4)
print(f4a.to_string(index=False))
g = area_fractions(FL[("high", "awake", "adjacent", "site")], "early")
print("\nper site and area, high current, all awake, adjacent, per-site FDR (fractions):")
print(g.round(3).to_string(index=False))
level trials pre FDR stim sites non-stim mean % non-stim max % non-stim pooled per session mean % max % stim mean % stim max % stim min % inc stim > non-stim (pooled) (every region) ratio deep/sup (a) ratio (b) values within tol ratio 2-4
high awake adjacent site 22 4.77 50.00 4.06 20.0 38.75 83.33 0.00 False False 2.48 2.44 False True
high awake adjacent pooled 22 4.64 50.00 3.92 20.0 38.35 83.33 7.14 False False 1.97 2.03 False True
high awake mirror site 22 5.08 50.00 4.26 20.0 39.20 83.33 0.00 False False 2.41 2.61 False True
high awake mirror pooled 22 4.73 50.00 4.00 20.0 39.34 83.33 7.14 False False 1.87 1.97 False False
high quiet adjacent site 22 4.14 50.00 3.66 20.0 35.57 100.00 0.00 False False 2.77 2.63 False True
high quiet adjacent pooled 22 3.94 50.00 3.37 20.0 34.84 100.00 3.45 False False 2.23 2.22 False True
high quiet mirror site 22 4.16 50.00 3.61 20.0 35.57 100.00 0.00 False False 2.85 3.01 False True
high quiet mirror pooled 22 4.19 50.00 3.59 20.0 35.16 100.00 5.06 False False 2.29 2.29 False True
medium awake adjacent site 22 3.60 50.00 2.91 20.0 27.99 83.33 0.00 False False 2.05 3.49 False True
medium awake adjacent pooled 22 3.30 50.00 2.64 20.0 28.10 100.00 0.00 False False 1.58 2.66 False True
medium awake mirror site 22 3.44 50.00 2.74 20.0 27.92 83.33 0.00 False False 2.05 3.52 False True
medium awake mirror pooled 22 2.35 29.27 2.51 20.0 27.82 100.00 0.00 False False 1.69 2.71 False True
medium quiet adjacent site 22 3.01 50.00 2.33 20.0 24.85 100.00 0.00 False False 2.47 4.69 False True
medium quiet adjacent pooled 22 2.83 50.00 2.13 20.0 24.07 100.00 0.00 False False 2.24 3.27 False True
medium quiet mirror site 22 3.09 50.00 2.34 20.0 25.06 100.00 0.00 False False 2.49 4.32 False True
medium quiet mirror pooled 22 2.78 50.00 2.11 20.0 24.31 100.00 0.00 False False 2.23 3.11 False True
per site and area, high current, all awake, adjacent, per-site FDR (fractions):
site_idx subject depth group stim n inc dec mod
0 546655 deep MO True 18 0.278 0.000 0.278
0 546655 deep VIS False 5 0.200 0.000 0.200
1 551397 deep ACA False 113 0.009 0.071 0.080
1 551397 deep MO True 84 0.488 0.071 0.560
1 551397 deep SS False 59 0.000 0.034 0.034
2 551399 deep ACA False 15 0.067 0.133 0.200
2 551399 deep MO True 89 0.528 0.011 0.539
2 551399 deep SS False 95 0.000 0.000 0.000
3 569062 deep ACA False 132 0.008 0.045 0.053
3 569062 deep MO True 120 0.242 0.100 0.342
3 569062 deep SS False 174 0.011 0.023 0.034
4 569064 deep ACA False 50 0.040 0.000 0.040
4 569064 deep MO True 24 0.542 0.000 0.542
4 569064 deep SS False 3 0.000 0.000 0.000
4 569064 deep VIS False 45 0.000 0.000 0.000
5 569068 deep ACA False 2 0.500 0.000 0.500
5 569068 deep MO True 49 0.592 0.102 0.694
5 569068 deep SS False 66 0.030 0.000 0.030
6 569069 deep ACA False 41 0.073 0.073 0.146
6 569069 deep MO True 29 0.103 0.172 0.276
6 569069 deep VIS False 59 0.068 0.017 0.085
7 569072 deep ACA False 72 0.028 0.028 0.056
7 569072 deep MO False 206 0.010 0.015 0.024
7 569072 deep SS True 83 0.193 0.253 0.446
7 569072 deep VIS False 76 0.013 0.039 0.053
8 569073 deep ACA False 63 0.016 0.032 0.048
8 569073 deep MO True 28 0.321 0.000 0.321
8 569073 deep SS False 22 0.045 0.000 0.045
8 569073 deep VIS False 36 0.000 0.000 0.000
9 569073 deep ACA False 100 0.010 0.000 0.010
9 569073 deep MO False 45 0.000 0.000 0.000
9 569073 deep SS True 12 0.833 0.000 0.833
9 569073 deep VIS False 18 0.000 0.000 0.000
10 571619 deep ACA False 138 0.014 0.014 0.029
10 571619 deep MO True 95 0.495 0.000 0.495
10 571619 deep SS False 12 0.000 0.000 0.000
10 571619 deep VIS False 47 0.021 0.000 0.021
11 571619 superficial ACA False 138 0.000 0.000 0.000
11 571619 superficial MO True 95 0.053 0.021 0.074
11 571619 superficial SS False 12 0.000 0.000 0.000
11 571619 superficial VIS False 47 0.000 0.000 0.000
12 571620 deep ACA False 28 0.036 0.000 0.036
12 571620 deep MO False 155 0.006 0.006 0.013
12 571620 deep SS True 9 0.333 0.111 0.444
12 571620 deep VIS False 11 0.000 0.000 0.000
13 571620 superficial ACA False 28 0.000 0.000 0.000
13 571620 superficial MO False 155 0.000 0.000 0.000
13 571620 superficial SS True 9 0.222 0.000 0.222
13 571620 superficial VIS False 11 0.000 0.000 0.000
14 575102 superficial ACA False 27 0.074 0.000 0.074
14 575102 superficial MO True 12 0.500 0.000 0.500
14 575102 superficial VIS False 59 0.000 0.000 0.000
15 586466 deep ACA False 77 0.078 0.039 0.117
15 586466 deep MO False 99 0.051 0.030 0.081
15 586466 deep SS True 14 0.286 0.071 0.357
16 586466 superficial ACA False 77 0.000 0.000 0.000
16 586466 superficial MO False 99 0.010 0.000 0.010
16 586466 superficial SS True 14 0.000 0.000 0.000
17 586468 deep ACA False 123 0.008 0.000 0.008
17 586468 deep MO False 173 0.006 0.000 0.006
17 586468 deep SS True 39 0.385 0.103 0.487
17 586468 deep VIS False 85 0.094 0.071 0.165
18 590479 deep ACA False 129 0.062 0.000 0.062
18 590479 deep MO False 122 0.008 0.008 0.016
18 590479 deep SS True 81 0.235 0.086 0.321
19 590479 superficial ACA False 129 0.008 0.000 0.008
19 590479 superficial MO False 122 0.000 0.000 0.000
19 590479 superficial SS True 81 0.086 0.062 0.148
20 590480 deep ACA False 53 0.208 0.075 0.283
20 590480 deep MO False 101 0.030 0.030 0.059
20 590480 deep SS True 79 0.241 0.228 0.468
20 590480 deep VIS False 63 0.079 0.063 0.143
21 590480 superficial ACA False 53 0.000 0.000 0.000
21 590480 superficial MO False 101 0.000 0.000 0.000
21 590480 superficial SS True 79 0.076 0.101 0.177
21 590480 superficial VIS False 63 0.000 0.000 0.000
22 599017 deep MO False 187 0.000 0.000 0.000
22 599017 deep VIS False 62 0.000 0.000 0.000
23 599017 superficial MO False 187 0.000 0.000 0.000
23 599017 superficial VIS False 62 0.000 0.000 0.000
Result: not reproduced. Modulated units at 2 to 25 ms are far more frequent than the paper reports in other cortex (mean 2.4 to 5.1% per region against 0.5%, maximum 29 to 50% against 2.6%) and in stimulated cortex (mean 24 to 39% against 17.8%), under every reading; the stimulated cortex does not exceed the other areas at every site. The deep over superficial ratio is between 2 and 4 in 15 of 16 readings. Pooling the non-stimulated areas of each session gives a mean of 2.1 to 4.3% and a maximum of 20%, also far above 0.5% and 2.6%.
fig4be-off-period¶
In the off period (25 to 150 ms) very few neurons increased their spiking (mean 0.4%, maximum 2.8%), spiking was significantly reduced in 18 of 22 subjects, and non-stimulated areas showed decreases only with deep stimulation (mean 10.1%, maximum 55.7%).
Readings of "spiking significantly reduced" in a site: (a) at least one stimulated-cortex RS unit decreased; (b) at least one cortical RS unit decreased; (c) the summed spike count of the stimulated-cortex RS units lower after than before by the signed-rank test.
POP = {}
for lvl in LEVELS:
for tr in AWAKE:
for w in ("off", "rebound"):
for pre in claar.PRE_READINGS:
rows = []
for r in res:
x = r["pop"]
if len(x):
x = x[(x.level == lvl) & (x.trials == tr) & (x.window == w) & (x.pre == pre)]
rows.append(x.assign(subject=r["subject"], site=r["site"], depth=r["depth"]))
POP[(lvl, tr, w, pre)] = pd.concat(rows).reset_index(drop=True)
print("population tests:", {k: len(v) for k, v in list(POP.items())[:2]})
population tests: {('high', 'awake', 'off', 'adjacent'): 46, ('high', 'awake', 'off', 'mirror'): 46}
rows = []
for c in combos:
d = FL[c]
g = area_fractions(d, "off")
st = d[(d.window == "off") & d.group.isin(claar.CORTEX)]
red_a = st[st.stim].groupby("site_idx").dec.any()
red_b = st.groupby("site_idx").dec.any()
pop = POP[(c[0], c[1], "off", c[2])]
red_c = pop[pop.area == "stim"].pipe(lambda x: (x.p < 0.05) & (x.sign < 0))
nsd = g[(~g.stim) & (g.depth == "deep")]
nss = g[(~g.stim) & (g.depth == "superficial")]
rows.append({"level": c[0], "trials": c[1], "pre": c[2], "FDR": c[3],
"inc mean %": round(100 * g.inc.mean(), 2), "inc max %": round(100 * g.inc.max(), 2),
"reduced (a)": f"{int(red_a.sum())}/{len(red_a)}", "(b)": f"{int(red_b.sum())}/{len(red_b)}", "(c)": f"{int(red_c.sum())}/{len(red_c)}",
"non-stim dec deep mean %": round(100 * nsd.dec.mean(), 2), "max %": round(100 * nsd.dec.max(), 2),
"sup sites with non-stim dec": int((nss.groupby("site_idx").dec.max() > 0).sum()), "of": nss.site_idx.nunique()})
f4b = pd.DataFrame(rows)
f4b["values within tol"] = (abs(f4b["inc mean %"] - 0.4) <= 0.04) & (abs(f4b["inc max %"] - 2.8) <= 0.28) & (abs(f4b["non-stim dec deep mean %"] - 10.1) <= 1.01) & (abs(f4b["max %"] - 55.7) <= 5.57)
print(f4b.to_string(index=False))
print("\nexpected: increased mean 0.4%, max 2.8%; reduced in 18 of 22 subjects; non-stim decreased with deep mean 10.1%, max 55.7%, none with superficial")
level trials pre FDR inc mean % inc max % reduced (a) (b) (c) non-stim dec deep mean % max % sup sites with non-stim dec of values within tol high awake adjacent site 1.15 17.70 21/22 22/24 21/22 27.49 80.81 3 7 False high awake adjacent pooled 1.35 16.81 21/22 24/24 21/22 27.26 76.77 5 7 False high awake mirror site 1.12 15.93 21/22 23/24 21/22 27.68 81.82 3 7 False high awake mirror pooled 1.25 14.29 21/22 24/24 21/22 27.03 78.05 6 7 False high quiet adjacent site 1.16 18.58 21/22 21/24 21/22 27.21 79.80 2 7 False high quiet adjacent pooled 1.09 15.93 22/22 23/24 21/22 26.13 76.77 3 7 False high quiet mirror site 1.10 19.47 19/22 20/24 21/22 27.29 80.81 2 7 False high quiet mirror pooled 1.21 16.81 22/22 23/24 21/22 25.64 77.78 2 7 False medium awake adjacent site 0.70 11.11 19/22 20/24 20/22 17.51 78.05 2 7 False medium awake adjacent pooled 0.82 11.11 19/22 22/24 20/22 16.85 78.05 4 7 False medium awake mirror site 0.66 11.11 18/22 19/24 20/22 17.65 82.93 2 7 False medium awake mirror pooled 0.76 11.11 21/22 22/24 20/22 16.75 78.05 4 7 False medium quiet adjacent site 0.74 11.11 17/22 18/24 20/22 18.04 80.49 2 7 False medium quiet adjacent pooled 0.76 11.11 21/22 21/24 20/22 16.87 72.73 4 7 False medium quiet mirror site 0.66 11.11 18/22 18/24 20/22 17.42 78.05 2 7 False medium quiet mirror pooled 0.70 11.11 21/22 23/24 20/22 15.90 75.61 5 7 False expected: increased mean 0.4%, max 2.8%; reduced in 18 of 22 subjects; non-stim decreased with deep mean 10.1%, max 55.7%, none with superficial
Result: not reproduced. Increases at 25 to 150 ms are few (mean 0.7 to 1.4%) but above the paper's 0.4% (maximum 11 to 19% against 2.8%); spiking is reduced in 17 to 22 of 22 stimulated areas (reading a) against 18 of 22; decreases in other cortex with deep stimulation average 16 to 28% against 10.1%; and 2 to 6 of 7 superficial sites also show decreases outside the stimulated area, where the paper reports none.
fig4cf-rebound¶
In the rebound window (150 to 300 ms), all 16 deep-stimulation subjects showed significant rebound excitation in stimulated cortex against 1 of 6 superficial subjects; 6 of 16 deep subjects showed it in non-stimulated areas, and none of 7 superficial subjects did.
rows = []
for c in combos:
d = FL[c]
x = d[(d.window == "rebound") & d.group.isin(claar.CORTEX)]
a_st = x[x.stim].groupby(["site_idx", "depth"]).inc.any().reset_index()
a_ns = x[~x.stim].groupby(["site_idx", "depth"]).inc.any().reset_index()
pop = POP[(c[0], c[1], "rebound", c[2])]
pop["inc"] = (pop.p < 0.05) & (pop.sign > 0)
out = {"level": c[0], "trials": c[1], "pre": c[2], "FDR": c[3]}
for rd, st, ns in (("a", a_st, a_ns), ("b", pop[pop.area == "stim"], pop[pop.area == "nonstim"])):
for dep in ("deep", "superficial"):
out[f"{rd} stim {dep}"] = f"{int(st[st.depth == dep].inc.sum())}/{(st.depth == dep).sum()}"
out[f"{rd} non-stim {dep}"] = f"{int(ns[ns.depth == dep].inc.sum())}/{(ns.depth == dep).sum()}"
ds, ss = st[st.depth == "deep"].inc, st[st.depth == "superficial"].inc
dn, sn = ns[ns.depth == "deep"].inc, ns[ns.depth == "superficial"].inc
out[f"{rd} holds"] = bool(ds.mean() >= 0.9 and ss.mean() <= 1 / 6 and abs(dn.mean() - 6 / 16) <= 0.1 * 6 / 16 and sn.sum() == 0)
rows.append(out)
f4c = pd.DataFrame(rows)
print(f4c.to_string(index=False))
level trials pre FDR a stim deep a non-stim deep a stim superficial a non-stim superficial a holds b stim deep b non-stim deep b stim superficial b non-stim superficial b holds high awake adjacent site 15/16 14/17 4/6 2/7 False 15/16 9/17 4/6 1/7 False high awake adjacent pooled 15/16 16/17 5/6 5/7 False 15/16 9/17 4/6 1/7 False high awake mirror site 15/16 15/17 3/6 2/7 False 14/16 9/17 3/6 1/7 False high awake mirror pooled 15/16 16/17 5/6 4/7 False 14/16 9/17 3/6 1/7 False high quiet adjacent site 15/16 16/17 4/6 2/7 False 15/16 10/17 4/6 2/7 False high quiet adjacent pooled 16/16 16/17 6/6 4/7 False 15/16 10/17 4/6 2/7 False high quiet mirror site 15/16 16/17 4/6 2/7 False 14/16 10/17 3/6 1/7 False high quiet mirror pooled 16/16 16/17 5/6 4/7 False 14/16 10/17 3/6 1/7 False medium awake adjacent site 16/16 14/17 1/6 2/7 False 15/16 5/17 1/6 1/7 False medium awake adjacent pooled 16/16 14/17 2/6 4/7 False 15/16 5/17 1/6 1/7 False medium awake mirror site 15/16 15/17 1/6 2/7 False 15/16 5/17 1/6 1/7 False medium awake mirror pooled 16/16 14/17 3/6 3/7 False 15/16 5/17 1/6 1/7 False medium quiet adjacent site 16/16 16/17 1/6 2/7 False 16/16 5/17 1/6 1/7 False medium quiet adjacent pooled 16/16 17/17 2/6 3/7 False 16/16 5/17 1/6 1/7 False medium quiet mirror site 16/16 15/17 1/6 2/7 False 15/16 6/17 1/6 1/7 False medium quiet mirror pooled 16/16 15/17 3/6 4/7 False 15/16 6/17 1/6 1/7 False
Result: partially reproduced. In stimulated cortex the counts match at the medium current: 16 of 16 deep and 1 of 6 superficial sites with a significantly increased RS unit (the paper's 16/16 and 1/6, and its denominators). Outside the stimulated area, deep sites show rebound in 14 to 17 of 17 (reading a) or 5 to 10 of 17 (reading b) against 6 of 16, and 1 to 5 of 7 superficial sites show it against none. No reading meets every part of the criterion.
fig4-supp1-fs-like-rs¶
FS neurons behave like RS neurons in their modulation by stimulation depth and time window.
The analyses of fig4ad, fig4be and fig4cf on FS units, FDR over FS units; unit counts in fig4-unit-counts.
rows = []
for c in combos:
for cell in ("RS", "FS"):
d = FL[c] if cell == "RS" else FL[c + ("FS",)]
e = area_fractions(d, "early")
o = area_fractions(d, "off")
rb = d[(d.window == "rebound") & d.group.isin(claar.CORTEX) & d.stim].groupby(["site_idx", "depth"]).inc.any().reset_index()
rows.append({"level": c[0], "trials": c[1], "pre": c[2], "FDR": c[3], "cell": cell,
"early inc stim %": round(100 * e[e.stim].inc.mean(), 1), "early inc non-stim %": round(100 * e[~e.stim].inc.mean(), 1),
"off dec %": round(100 * o.dec.mean(), 1), "off inc %": round(100 * o.inc.mean(), 1),
"rebound stim deep": f"{int(rb[rb.depth == 'deep'].inc.sum())}/{(rb.depth == 'deep').sum()}",
"rebound stim sup": f"{int(rb[rb.depth == 'superficial'].inc.sum())}/{(rb.depth == 'superficial').sum()}"})
fs = pd.DataFrame(rows)
fs["qualitative"] = (fs["early inc stim %"] > fs["early inc non-stim %"]) & (fs["off dec %"] > fs["off inc %"])
print(fs.to_string(index=False))
level trials pre FDR cell early inc stim % early inc non-stim % off dec % off inc % rebound stim deep rebound stim sup qualitative high awake adjacent site RS 32.0 3.3 30.1 1.2 15/16 4/6 True high awake adjacent site FS 49.4 14.2 41.0 1.4 14/15 4/6 True high awake adjacent pooled RS 31.6 3.5 30.1 1.4 15/16 5/6 True high awake adjacent pooled FS 50.0 14.5 41.4 1.8 14/15 5/6 True high awake mirror site RS 31.9 3.2 30.2 1.1 15/16 3/6 True high awake mirror site FS 47.6 13.9 41.3 1.2 14/15 4/6 True high awake mirror pooled RS 32.2 3.3 30.4 1.3 15/16 5/6 True high awake mirror pooled FS 49.1 13.6 41.4 1.5 14/15 4/6 True high quiet adjacent site RS 30.9 3.1 29.1 1.2 15/16 4/6 True high quiet adjacent site FS 49.8 13.2 39.5 1.5 14/15 4/6 True high quiet adjacent pooled RS 30.6 3.0 28.5 1.1 16/16 6/6 True high quiet adjacent pooled FS 49.7 12.5 39.5 1.7 14/15 4/6 True high quiet mirror site RS 30.9 3.0 28.8 1.1 15/16 4/6 True high quiet mirror site FS 49.1 13.0 39.2 1.4 14/15 4/6 True high quiet mirror pooled RS 30.8 3.1 28.3 1.2 16/16 5/6 True high quiet mirror pooled FS 49.4 12.5 39.1 1.8 14/15 4/6 True medium awake adjacent site RS 23.0 2.1 22.5 0.7 16/16 1/6 True medium awake adjacent site FS 47.8 10.3 31.1 0.1 14/15 3/6 True medium awake adjacent pooled RS 23.3 2.1 22.3 0.8 16/16 2/6 True medium awake adjacent pooled FS 51.6 9.9 29.9 0.7 14/15 4/6 True medium awake mirror site RS 22.5 2.1 22.6 0.7 15/16 1/6 True medium awake mirror site FS 51.4 10.1 29.3 0.1 14/15 3/6 True medium awake mirror pooled RS 23.1 1.2 22.5 0.8 16/16 3/6 True medium awake mirror pooled FS 51.4 9.8 29.6 0.1 14/15 4/6 True medium quiet adjacent site RS 21.7 2.1 22.1 0.7 16/16 1/6 True medium quiet adjacent site FS 48.9 9.2 30.4 0.6 14/15 2/6 True medium quiet adjacent pooled RS 21.2 2.0 21.8 0.8 16/16 2/6 True medium quiet adjacent pooled FS 47.9 8.7 29.0 0.7 14/15 4/6 True medium quiet mirror site RS 21.6 2.0 21.6 0.7 16/16 1/6 True medium quiet mirror site FS 49.1 8.5 29.8 0.5 14/15 3/6 True medium quiet mirror pooled RS 21.0 2.0 21.2 0.7 16/16 3/6 True medium quiet mirror pooled FS 47.4 8.5 30.2 0.6 14/15 4/6 True
Result: partially reproduced. FS units follow the RS pattern under every reading (more increases in stimulated than other cortex at 2 to 25 ms, decreases dominating at 25 to 150 ms, rebound in 14 of 15 deep stimulated areas), but rebound also appears in 2 to 5 of 6 superficial sites, and the FS counts (68, 203, 149, 518) are far below the legend's (180, 585, 387, 1422).
Figure 4 with the three currents pooled (a reading outside the claims file)¶
The Figure 4 legend's RS counts are three times the units in the files (fig4-unit-counts), which suggests that each unit was counted once per current. This reading is not in the claims file and is asked of a reader (questions/000458.yaml); it is shown here as a variant and does not decide an outcome. Each unit is tested at each current (all awake trials or quiet trials, both pre-stimulus windows, BH per site, window and current), and the fractions count unit x current.
rows = []
for tr in AWAKE:
for pre in claar.PRE_READINGS:
for cell in ("RS", "FS"):
parts = []
for lvl in ("high", "medium", "low"):
x = flags_all(lvl, tr, pre, "site", cell=cell)
parts.append(x.assign(unit=x.unit.astype(str) + "-" + lvl))
d = pd.concat(parts, ignore_index=True)
e, o = area_fractions(d, "early"), area_fractions(d, "off")
x = d[(d.window == "rebound") & d.group.isin(claar.CORTEX)]
rb_st = x[x.stim].groupby(["site_idx", "depth"]).inc.any().reset_index()
rb_ns = x[~x.stim].groupby(["site_idx", "depth"]).inc.any().reset_index()
nsd, nss = o[(~o.stim) & (o.depth == "deep")], o[(~o.stim) & (o.depth == "superficial")]
red = d[(d.window == "off") & d.group.isin(claar.CORTEX) & d.stim].groupby("site_idx").dec.any()
ns_e = e[~e.stim]
rows.append({"trials": tr, "pre": pre, "cell": cell,
"units x currents stim/non-stim": f"{int(e[e.stim].n.sum())}/{int(ns_e.n.sum())}",
"early: non-stim mean %": round(100 * ns_e["mod"].mean(), 2), "max %": round(100 * ns_e["mod"].max(), 2),
"stim mean %": round(100 * e[e.stim]["mod"].mean(), 2), "stim max %": round(100 * e[e.stim]["mod"].max(), 2),
"off: inc mean %": round(100 * o.inc.mean(), 2), "inc max %": round(100 * o.inc.max(), 2),
"reduced (a)": f"{int(red.sum())}/{len(red)}",
"non-stim dec deep mean %": round(100 * nsd.dec.mean(), 2), "dec max %": round(100 * nsd.dec.max(), 2),
"sup sites with non-stim dec": f"{int((nss.groupby('site_idx').dec.max() > 0).sum())}/{nss.site_idx.nunique()}",
"rebound stim deep": f"{int(rb_st[rb_st.depth == 'deep'].inc.sum())}/{(rb_st.depth == 'deep').sum()}",
"stim sup": f"{int(rb_st[rb_st.depth == 'superficial'].inc.sum())}/{(rb_st.depth == 'superficial').sum()}",
"non-stim deep": f"{int(rb_ns[rb_ns.depth == 'deep'].inc.sum())}/{(rb_ns.depth == 'deep').sum()}",
"non-stim sup": f"{int(rb_ns[rb_ns.depth == 'superficial'].inc.sum())}/{(rb_ns.depth == 'superficial').sum()}"})
f4p = pd.DataFrame(rows)
print(f4p.to_string(index=False))
print("\nexpected: early non-stim 0.5% (max 2.6%), stim 17.8% (max 83.3%); off inc 0.4% (max 2.8%), reduced 18 of 22, "
"non-stim dec deep 10.1% (max 55.7%), none superficial; rebound stim 16/16 deep, 1/6 superficial, non-stim 6/16 deep, 0/7 superficial")
trials pre cell units x currents stim/non-stim early: non-stim mean % max % stim mean % stim max % off: inc mean % inc max % reduced (a) non-stim dec deep mean % dec max % sup sites with non-stim dec rebound stim deep stim sup non-stim deep non-stim sup awake adjacent RS 3429/13596 3.18 33.33 29.08 86.11 0.74 7.41 21/22 17.21 71.38 3/7 16/16 4/6 15/17 2/7 awake adjacent FS 651/2163 11.54 77.78 53.41 100.00 0.56 9.80 20/21 26.40 94.44 3/7 14/15 4/6 15/17 3/7 awake mirror RS 3429/13596 3.11 33.33 29.34 86.11 0.74 7.41 21/22 17.33 70.37 3/7 16/16 3/6 15/17 2/7 awake mirror FS 651/2163 11.48 77.78 55.49 100.00 0.46 9.80 20/21 26.24 94.44 3/7 14/15 4/6 14/17 3/7 quiet adjacent RS 3429/13596 2.62 33.33 25.70 94.44 0.77 7.41 21/22 17.25 71.72 2/7 16/16 4/6 16/17 2/7 quiet adjacent FS 651/2163 10.33 77.78 52.72 100.00 0.79 13.04 19/21 26.69 94.44 3/7 14/15 4/6 15/17 2/7 quiet mirror RS 3429/13596 2.65 33.33 26.06 94.44 0.73 7.41 21/22 17.25 70.03 2/7 16/16 4/6 16/17 2/7 quiet mirror FS 651/2163 10.05 77.78 53.85 100.00 0.67 11.76 19/21 26.47 97.22 3/7 14/15 4/6 14/17 2/7 expected: early non-stim 0.5% (max 2.6%), stim 17.8% (max 83.3%); off inc 0.4% (max 2.8%), reduced 18 of 22, non-stim dec deep 10.1% (max 55.7%), none superficial; rebound stim 16/16 deep, 1/6 superficial, non-stim 6/16 deep, 0/7 superficial
Result: variant only. With the three currents pooled, RS fractions stay far from the paper's: at 2 to 25 ms 2.6 to 3.2% of non-stimulated units (maximum 33%) and 26 to 29% of stimulated units are modulated, against 0.5% and 17.8%; at 25 to 150 ms increases average 0.7 to 0.8% (maximum 7.4%) and decreases outside the stimulated area with deep stimulation 17.2 to 17.3% (maximum 70 to 72%), against 0.4%, 2.8%, 10.1% and 55.7%, with 2 or 3 of 7 superficial sites showing such decreases; rebound outside the stimulated area appears in 15 or 16 of 17 deep and 2 of 7 superficial sites, against 6 of 16 and none. This reading does not change any Figure 4 outcome.
fig2c-superficial-quiescence, fig2c-deep-triphasic-cortex, fig2f-thalamus-triphasic¶
Population rate: mean over units of the trial-averaged rate, 1 ms or 5 ms bins; baseline is the mean rate from -2 to 0 s. Quiescence readings (a) below the baseline mean, (b) at zero, from 25 ms on.
def pop_rate(r, level, trials, pop, bin_ms):
t, rate = r["rate"][(level, trials)]
u = r["units"]
mask = (u.stim & u.rs).values if pop == "stimRS" else (u.group == "SM-TH").values
if mask.sum() == 0:
return None, None
x = rate[mask].mean(0)
if bin_ms > 1:
x = x.reshape(-1, bin_ms).mean(1)
t = t.reshape(-1, bin_ms).mean(1)
return t, x
def triphasic(level, trials, pop, bin_ms, early, late, sites_filter):
rows = []
for k, r in enumerate(res):
if not sites_filter(r):
continue
t, x = pop_rate(r, level, trials, pop, bin_ms)
if x is None:
continue
base = x[t < 0].mean()
sd = x[t < 0].std()
e = x[(t >= early[0]) & (t <= early[1])].max()
l = x[(t >= late[0]) & (t <= late[1])].max()
rows.append({"subject": r["subject"], "site": r["site"], "base": base, "early peak": e, "late peak": l,
"quiescence a ms": 1000 * claar.quiescence(t, x, base), "quiescence b ms": 1000 * claar.quiescence(t, x, base, zero=True),
"quiescence a, gaps < 5 ms ignored": 1000 * claar.quiescence(t, x, base, max_gap=0.005),
"late z": (l - base) / sd if sd > 0 else np.inf,
"triphasic": bool(e > base and claar.quiescence(t, x, base) > 0 and l > base),
"triphasic, >= 10 ms below": bool(e > base and claar.quiescence(t, x, base, max_gap=0.005) >= 0.010 and l > base)})
return pd.DataFrame(rows)
rows = []
for lvl in LEVELS:
for tr in AWAKE:
for b in (1, 5):
d = triphasic(lvl, tr, "stimRS", b, (0.002, 0.025), (0.15, 0.3), lambda r: r["site"] == "MOs-superficial")
rows.append({"level": lvl, "trials": tr, "bin ms": b, "sites": len(d), "quiescence a": f"{d['quiescence a ms'].mean():.1f} +/- {stats.sem(d['quiescence a ms']):.1f}",
"a, gaps < 5 ms ignored": f"{d['quiescence a, gaps < 5 ms ignored'].mean():.1f}",
"quiescence b": f"{d['quiescence b ms'].mean():.1f} +/- {stats.sem(d['quiescence b ms']):.1f}",
"a within 94.2+/-16.1 or 44.3+/-16.4": bool(abs(d['quiescence a ms'].mean() - 94.2) <= 16.1 or abs(d['quiescence a ms'].mean() - 44.3) <= 16.4),
"b within": bool(abs(d['quiescence b ms'].mean() - 94.2) <= 16.1 or abs(d['quiescence b ms'].mean() - 44.3) <= 16.4)})
sq = pd.DataFrame(rows)
print(sq.to_string(index=False))
print("\nper site, high current, all awake, 1 ms bins:")
print(triphasic("high", "awake", "stimRS", 1, (0.002, 0.025), (0.15, 0.3), lambda r: r["site"] == "MOs-superficial").round(2).to_string(index=False))
level trials bin ms sites quiescence a a, gaps < 5 ms ignored quiescence b a within 94.2+/-16.1 or 44.3+/-16.4 b within high awake 1 2 84.0 +/- 25.0 117.5 32.0 +/- 32.0 True True high awake 5 2 112.5 +/- 2.5 112.5 30.0 +/- 30.0 False True high quiet 1 2 104.0 +/- 5.0 119.0 32.0 +/- 32.0 True True high quiet 5 2 110.0 +/- 10.0 110.0 30.0 +/- 30.0 True True medium awake 1 2 81.5 +/- 34.5 121.0 35.0 +/- 35.0 True True medium awake 5 2 115.0 +/- 0.0 115.0 35.0 +/- 35.0 False True medium quiet 1 2 90.5 +/- 25.5 119.0 35.0 +/- 35.0 True True medium quiet 5 2 115.0 +/- 0.0 115.0 35.0 +/- 35.0 False True per site, high current, all awake, 1 ms bins: subject site base early peak late peak quiescence a ms quiescence b ms quiescence a, gaps < 5 ms ignored late z triphasic triphasic, >= 10 ms below 571619 MOs-superficial 2.29 15.01 5.03 59.0 0.0 120.0 5.75 True True 575102 MOs-superficial 2.38 121.53 20.83 109.0 64.0 115.0 14.23 True True
Result: reproduced. In the two superficial MOs sites with units, MO RS population rates stay below baseline after 25 ms for 84.0 +/- 25.0 ms (high current, all awake, 1 ms bins), within 94.2 +/- 16.1; other readings give 81.5 to 115 ms below baseline, and 30 to 35 ms at zero rate, the latter within the Discussion's 44.3 +/- 16.4. Two sites are few. The measure is sensitive to single bins: when runs above baseline shorter than 5 ms do not end the period, the below-baseline quiescence lasts 110 to 121 ms, within 94.2 +/- 16.1 only with 5 ms bins and quiet trials at the high current (110.0 ms). The zero-rate reading (b) is within the Discussion's 44.3 +/- 16.4 in all eight readings, so the outcome does not rest on the single-bin reading alone.
rows = []
for lvl in LEVELS:
for tr in AWAKE:
for b in (1, 5):
for setname, flt in (("deep MOs", lambda r: r["site"] == "MOs-deep"), ("all deep", lambda r: r["depth"] == "deep")):
d = triphasic(lvl, tr, "stimRS", b, (0.002, 0.025), (0.15, 0.3), flt)
q = d["quiescence a ms"].mean(), d["quiescence b ms"].mean()
rows.append({"level": lvl, "trials": tr, "bin": b, "set": setname, "sites": len(d),
"early peak Hz": f"{d['early peak'].mean():.1f} +/- {stats.sem(d['early peak']):.1f}",
"quiescence a ms": f"{q[0]:.1f} +/- {stats.sem(d['quiescence a ms']):.1f}", "quiescence b ms": f"{q[1]:.1f}",
"rebound peak Hz": f"{d['late peak'].mean():.1f} +/- {stats.sem(d['late peak']):.1f}",
"triphasic": f"{int(d.triphasic.sum())}/{len(d)}", ">= 10 ms below": f"{int(d['triphasic, >= 10 ms below'].sum())}/{len(d)}",
"quiescence a, gaps < 5 ms ignored": f"{d['quiescence a, gaps < 5 ms ignored'].mean():.1f}",
"all within": bool(abs(d['early peak'].mean() - 38.1) <= 4.2 and abs(d['late peak'].mean() - 7.9) <= 0.7 and
any(abs(v - 125.0) <= 5.5 or abs(v - 127.8) <= 4.1 for v in q))})
dt = pd.DataFrame(rows)
print(dt.to_string(index=False))
print("\nper site, high current, all awake, 1 ms bins, all deep sites:")
print(triphasic("high", "awake", "stimRS", 1, (0.002, 0.025), (0.15, 0.3), lambda r: r["depth"] == "deep").round(2).to_string(index=False))
level trials bin set sites early peak Hz quiescence a ms quiescence b ms rebound peak Hz triphasic >= 10 ms below quiescence a, gaps < 5 ms ignored all within high awake 1 deep MOs 9 63.4 +/- 10.2 123.2 +/- 3.1 17.9 12.5 +/- 1.6 9/9 9/9 126.6 False high awake 1 all deep 16 64.5 +/- 8.7 118.3 +/- 8.2 12.4 12.2 +/- 0.9 16/16 16/16 143.7 False high awake 5 deep MOs 9 29.8 +/- 3.0 124.4 +/- 3.1 18.9 10.4 +/- 1.4 9/9 9/9 124.4 False high awake 5 all deep 16 30.4 +/- 4.1 129.1 +/- 3.1 13.1 9.8 +/- 0.9 16/16 16/16 129.1 False high quiet 1 deep MOs 9 63.8 +/- 10.4 125.6 +/- 3.3 24.9 14.6 +/- 2.0 9/9 9/9 128.7 False high quiet 1 all deep 16 65.2 +/- 8.9 119.7 +/- 8.4 17.0 13.6 +/- 1.2 16/16 16/16 153.8 False high quiet 5 deep MOs 9 30.7 +/- 2.9 127.2 +/- 3.0 26.7 11.3 +/- 1.5 9/9 9/9 127.2 False high quiet 5 all deep 16 30.9 +/- 4.0 131.9 +/- 2.9 18.1 10.6 +/- 1.0 16/16 16/16 131.9 False medium awake 1 deep MOs 9 43.5 +/- 5.0 114.0 +/- 4.8 3.9 10.6 +/- 0.9 9/9 9/9 121.6 False medium awake 1 all deep 16 53.3 +/- 8.8 116.1 +/- 3.7 3.0 11.0 +/- 0.6 16/16 16/16 127.7 False medium awake 5 deep MOs 9 20.1 +/- 2.5 120.6 +/- 3.5 5.6 8.5 +/- 0.7 9/9 9/9 120.6 False medium awake 5 all deep 16 24.2 +/- 4.0 124.7 +/- 2.8 3.7 8.9 +/- 0.5 16/16 16/16 124.7 False medium quiet 1 deep MOs 9 44.4 +/- 5.2 108.7 +/- 13.8 16.4 12.4 +/- 1.2 9/9 9/9 124.2 False medium quiet 1 all deep 16 53.8 +/- 8.7 115.7 +/- 8.1 10.1 12.5 +/- 0.7 16/16 16/16 128.7 False medium quiet 5 deep MOs 9 21.2 +/- 2.6 123.3 +/- 4.0 20.6 9.6 +/- 0.9 9/9 9/9 123.3 False medium quiet 5 all deep 16 24.7 +/- 3.8 126.9 +/- 2.8 12.8 9.8 +/- 0.6 16/16 16/16 126.9 False per site, high current, all awake, 1 ms bins, all deep sites: subject site base early peak late peak quiescence a ms quiescence b ms quiescence a, gaps < 5 ms ignored late z triphasic triphasic, >= 10 ms below 546655 MOs-deep 2.38 59.29 9.80 112.0 41.0 122.0 7.20 True True 551397 MOs-deep 4.44 90.77 12.80 122.0 1.0 122.0 12.49 True True 551399 MOs-deep 2.62 43.26 9.46 127.0 3.0 131.0 13.50 True True 569062 MOs-deep 3.70 39.72 10.69 114.0 0.0 117.0 13.59 True True 569064 MOs-deep 2.31 93.40 9.72 127.0 1.0 131.0 8.06 True True 569068 MOs-deep 3.81 119.05 10.20 127.0 1.0 127.0 7.82 True True 569069 MOs-deep 4.81 31.85 19.58 143.0 55.0 146.0 12.00 True True 569072 SSp-deep 4.64 36.14 8.33 146.0 1.0 151.0 5.10 True True 569073 MOs-deep 2.69 57.21 21.49 117.0 21.0 117.0 20.28 True True 569073 SSp-deep 5.38 157.49 12.71 2.0 1.0 344.0 3.59 True True 571619 MOs-deep 2.38 36.14 8.86 120.0 38.0 126.0 13.62 True True 571620 SSp-deep 2.78 71.30 11.11 115.0 30.0 140.0 5.12 True True 586466 SSp-deep 3.21 49.40 15.48 138.0 3.0 140.0 8.86 True True 586468 SSp-deep 5.58 57.91 11.11 123.0 0.0 123.0 4.84 True True 590479 SSp-deep 5.29 46.40 12.04 136.0 3.0 136.0 8.77 True True 590480 SSp-deep 5.63 42.66 11.91 124.0 0.0 126.0 7.69 True True
Result: partially reproduced. All 16 deep sites with stimulated-cortex RS units show the triphasic sequence. Quiescence below baseline lasts 108.7 to 131.9 ms (within 125.0 +/- 5.5 or 127.8 +/- 4.1 in several readings), but no reading puts the three values within tolerance: the early peak is 20 to 31 Hz in 5 ms bins and 44 to 65 Hz in 1 ms bins against 38.1 +/- 4.2, and the rebound peak 8.5 to 14.6 Hz against 7.9 +/- 0.7. Requiring at least 10 ms below baseline, with gaps under 5 ms ignored, keeps 16 of 16 sites triphasic.
rows = []
for lvl in LEVELS:
for tr in AWAKE:
for b in (1, 5):
d = triphasic(lvl, tr, "smth", b, (0.002, 0.025), (0.075, 0.3), lambda r: r["depth"] == "deep")
s = triphasic(lvl, tr, "smth", b, (0.002, 0.025), (0.075, 0.3), lambda r: r["depth"] == "superficial")
fl = FL[(lvl, tr, "adjacent", "site")]
sup_inc = fl[(fl.window == "rebound") & (fl.group == "SM-TH") & (fl.depth == "superficial")].groupby("site_idx").inc.any()
q = d["quiescence a ms"].mean(), d["quiescence b ms"].mean()
rows.append({"level": lvl, "trials": tr, "bin": b, "deep sites": len(d),
"early peak": f"{d['early peak'].mean():.1f} +/- {stats.sem(d['early peak']):.1f}",
"suppression a ms": f"{q[0]:.1f} +/- {stats.sem(d['quiescence a ms']):.1f}", "b ms": f"{q[1]:.1f}",
"triphasic": f"{int(d.triphasic.sum())}/{len(d)}", ">= 10 ms below": f"{int(d['triphasic, >= 10 ms below'].sum())}/{len(d)}",
"rebound peak": f"{d['late peak'].mean():.1f} +/- {stats.sem(d['late peak']):.1f}",
"sup sites": len(s), "sup no rebound (a: z<=3)": f"{int((s['late z'] <= 3).sum())}/{len(s)}",
"sup no rebound (b: no unit inc)": f"{int((~sup_inc).sum())}/{len(sup_inc)}",
"values within": bool(abs(d['early peak'].mean() - 22.3) <= 3.2 and abs(d['late peak'].mean() - 14.7) <= 1.0 and any(abs(v - 74.6) <= 15.5 for v in q))})
th = pd.DataFrame(rows)
print(th.to_string(index=False))
print("\nper site, high current, all awake, 1 ms bins, SM-TH:")
print(triphasic("high", "awake", "smth", 1, (0.002, 0.025), (0.075, 0.3), lambda r: True).round(2).to_string(index=False))
level trials bin deep sites early peak suppression a ms b ms triphasic >= 10 ms below rebound peak sup sites sup no rebound (a: z<=3) sup no rebound (b: no unit inc) values within high awake 1 14 31.4 +/- 6.8 70.7 +/- 9.5 0.1 12/14 12/14 19.7 +/- 1.8 4 1/4 3/4 False high awake 5 14 24.7 +/- 5.3 94.3 +/- 10.3 0.0 9/14 9/14 17.1 +/- 1.7 4 3/4 3/4 False high quiet 1 14 31.7 +/- 6.7 67.7 +/- 9.9 0.2 12/14 12/14 21.7 +/- 2.6 4 2/4 3/4 False high quiet 5 14 24.2 +/- 5.6 100.7 +/- 10.1 0.4 9/14 9/14 17.7 +/- 2.1 4 2/4 3/4 False medium awake 1 14 19.3 +/- 2.7 59.5 +/- 10.6 0.1 10/14 10/14 17.0 +/- 1.6 4 3/4 3/4 False medium awake 5 14 13.9 +/- 1.7 82.5 +/- 8.0 0.0 10/14 10/14 14.7 +/- 1.4 4 3/4 3/4 False medium quiet 1 14 19.0 +/- 2.7 66.9 +/- 11.8 0.1 11/14 11/14 18.5 +/- 2.3 4 1/4 4/4 False medium quiet 5 14 13.2 +/- 1.9 88.6 +/- 7.3 0.4 10/14 10/14 14.7 +/- 1.5 4 3/4 4/4 False per site, high current, all awake, 1 ms bins, SM-TH: subject site base early peak late peak quiescence a ms quiescence b ms quiescence a, gaps < 5 ms ignored late z triphasic triphasic, >= 10 ms below 546655 MOs-deep 10.66 21.85 15.41 64.0 0.0 181.0 2.68 True True 551397 MOs-deep 9.40 84.03 23.82 103.0 0.0 105.0 17.66 True True 551399 MOs-deep 17.09 19.21 21.95 75.0 0.0 135.0 3.68 True True 569062 MOs-deep 5.88 79.84 21.34 90.0 0.0 95.0 25.84 True True 569068 MOs-deep 6.78 31.21 19.68 78.0 0.0 78.0 11.34 True True 569069 MOs-deep 7.85 36.62 29.81 114.0 0.0 117.0 19.96 True True 569072 SSp-deep 8.84 23.52 15.07 91.0 0.0 121.0 7.61 True True 569073 MOs-deep 7.44 61.06 16.81 108.0 0.0 113.0 11.32 True True 569073 SSp-deep 10.15 11.30 13.66 35.0 0.0 83.0 4.10 True True 571619 MOs-deep 6.09 21.24 16.40 113.0 0.0 118.0 10.53 True True 571619 MOs-superficial 7.55 7.99 13.04 73.0 0.0 105.0 5.04 True True 571620 SSp-deep 14.63 13.92 18.64 40.0 0.0 117.0 3.26 False False 571620 SSp-superficial 16.84 16.75 20.10 2.0 0.0 65.0 2.65 False False 586468 SSp-deep 5.81 6.46 9.08 20.0 0.0 41.0 4.26 True True 590480 SSp-deep 24.85 19.96 34.93 56.0 0.0 74.0 3.71 False False 590480 SSp-superficial 27.15 29.95 35.68 4.0 0.0 7.0 3.19 True False 599017 SSp-deep 7.70 10.08 18.49 3.0 1.0 31.0 3.09 True True 599017 SSp-superficial 3.53 6.72 13.45 1.0 1.0 317.0 4.00 True True
Result: partially reproduced. SM-TH rates in the 14 deep sites with SM-TH units show early excitation, suppression and rebound, triphasic in 12 of 14 sites (per-site table, high current). The suppression (59.5 to 100.7 ms) is within 74.6 +/- 15.5 in most readings, but no reading puts the two peaks within tolerance together (early 13 to 32 Hz against 22.3 +/- 3.2; rebound 14.7 to 21.7 Hz against 14.7 +/- 1.0). With superficial stimulation 3 or 4 of 4 sites have no significantly increased SM-TH unit at 150 to 300 ms. Requiring at least 10 ms below baseline gives the same counts of triphasic sites in every reading.
fig5a-thalamus-modulated¶
SM-TH neurons were almost eight times more likely to be modulated by deep than by superficial stimulation (37.9 +/- 20.6% against 5.0 +/- 4.1%).
Readings: (a) one window 2 to 300 ms; (b) modulated in any of 2-25, 25-150, 150-300 ms.
rows = []
for c in combos:
d = FL[c]
x = d[d.group == "SM-TH"]
a = x[x.window == "2-300"].groupby(["site_idx", "depth"])["mod"].mean().reset_index()
b = x[x.window.isin(["early", "off", "rebound"])].groupby(["site_idx", "depth", "unit"])["mod"].any().groupby(["site_idx", "depth"]).mean().reset_index()
for rd, g in (("a", a), ("b", b)):
s, dp = 100 * g[g.depth == "superficial"]["mod"], 100 * g[g.depth == "deep"]["mod"]
tt = stats.ttest_ind(s, dp)
rows.append({"level": c[0], "trials": c[1], "pre": c[2], "FDR": c[3], "reading": rd,
"superficial %": f"{s.mean():.1f} +/- {stats.sem(s):.1f} (n={len(s)})", "deep %": f"{dp.mean():.1f} +/- {stats.sem(dp):.1f} (n={len(dp)})",
"p": f"{tt.pvalue:.3g}", "holds": bool(abs(s.mean() - 5.0) <= 4.1 and abs(dp.mean() - 37.9) <= 20.6 and tt.pvalue < 0.05 and dp.mean() > s.mean())})
f5a = pd.DataFrame(rows)
print(f5a.to_string(index=False))
level trials pre FDR reading superficial % deep % p holds high awake adjacent site a 0.7 +/- 0.4 (n=4) 42.3 +/- 7.1 (n=14) 0.00766 False high awake adjacent site b 7.9 +/- 4.8 (n=4) 59.2 +/- 9.3 (n=14) 0.0116 False high awake adjacent pooled a 1.9 +/- 1.5 (n=4) 42.7 +/- 5.8 (n=14) 0.002 True high awake adjacent pooled b 17.9 +/- 4.1 (n=4) 59.9 +/- 7.9 (n=14) 0.0141 False high awake mirror site a 0.7 +/- 0.4 (n=4) 42.6 +/- 7.2 (n=14) 0.00765 False high awake mirror site b 10.3 +/- 6.3 (n=4) 60.5 +/- 9.2 (n=14) 0.0123 False high awake mirror pooled a 2.1 +/- 1.5 (n=4) 42.9 +/- 5.8 (n=14) 0.00199 True high awake mirror pooled b 20.1 +/- 6.0 (n=4) 62.9 +/- 7.4 (n=14) 0.00953 False high quiet adjacent site a 0.8 +/- 0.8 (n=4) 45.3 +/- 7.8 (n=14) 0.00895 False high quiet adjacent site b 7.4 +/- 4.7 (n=4) 60.5 +/- 8.8 (n=14) 0.00668 False high quiet adjacent pooled a 3.3 +/- 2.0 (n=4) 43.8 +/- 7.3 (n=14) 0.0103 True high quiet adjacent pooled b 12.9 +/- 7.7 (n=4) 60.0 +/- 8.1 (n=14) 0.00959 False high quiet mirror site a 0.8 +/- 0.8 (n=4) 45.2 +/- 7.9 (n=14) 0.00938 False high quiet mirror site b 9.0 +/- 6.1 (n=4) 59.9 +/- 9.1 (n=14) 0.0107 False high quiet mirror pooled a 3.3 +/- 2.0 (n=4) 43.6 +/- 7.2 (n=14) 0.00971 True high quiet mirror pooled b 13.8 +/- 8.1 (n=4) 60.3 +/- 8.5 (n=14) 0.0135 False medium awake adjacent site a 0.0 +/- 0.0 (n=4) 29.6 +/- 5.8 (n=14) 0.0175 False medium awake adjacent site b 3.4 +/- 2.4 (n=4) 45.4 +/- 8.1 (n=14) 0.0161 True medium awake adjacent pooled a 0.8 +/- 0.8 (n=4) 28.4 +/- 5.4 (n=14) 0.0172 False medium awake adjacent pooled b 6.3 +/- 2.9 (n=4) 43.4 +/- 7.7 (n=14) 0.0234 True medium awake mirror site a 0.0 +/- 0.0 (n=4) 30.2 +/- 5.9 (n=14) 0.0166 False medium awake mirror site b 4.4 +/- 2.4 (n=4) 46.6 +/- 8.4 (n=14) 0.0189 True medium awake mirror pooled a 1.2 +/- 1.2 (n=4) 28.1 +/- 5.5 (n=14) 0.0202 True medium awake mirror pooled b 6.7 +/- 3.0 (n=4) 44.5 +/- 7.9 (n=14) 0.0238 True medium quiet adjacent site a 0.0 +/- 0.0 (n=4) 34.3 +/- 6.4 (n=14) 0.0124 False medium quiet adjacent site b 1.3 +/- 1.3 (n=4) 48.2 +/- 8.5 (n=14) 0.0107 True medium quiet adjacent pooled a 1.8 +/- 0.8 (n=4) 31.7 +/- 5.6 (n=14) 0.0131 True medium quiet adjacent pooled b 5.5 +/- 3.3 (n=4) 47.2 +/- 7.9 (n=14) 0.015 True medium quiet mirror site a 0.0 +/- 0.0 (n=4) 34.2 +/- 6.3 (n=14) 0.0122 False medium quiet mirror site b 2.5 +/- 2.0 (n=4) 47.2 +/- 8.3 (n=14) 0.0127 True medium quiet mirror pooled a 1.4 +/- 0.7 (n=4) 31.4 +/- 5.7 (n=14) 0.0142 True medium quiet mirror pooled b 5.5 +/- 3.3 (n=4) 45.2 +/- 7.9 (n=14) 0.0189 True
Result: reproduced. With one 2 to 300 ms window and pooled FDR, 1.9 +/- 1.5% of SM-TH units are modulated by superficial stimulation (n = 4 sites) and 42.7 +/- 5.8% by deep stimulation (n = 14), within 5.0 +/- 4.1 and 37.9 +/- 20.6, t-test p = 0.002. 15 of 32 readings meet the criterion; deep exceeds superficial with p < 0.05 in all 32.
fig5c-burst-probability-depth¶
Deep stimulation was significantly more likely than superficial stimulation to evoke SM-TH bursts 75 to 300 ms after the stimulus (median 0.12 [0.02 to 0.2] against 0 [0 to 0.02]).
Readings: (a) per site, the fraction of trials in which any SM-TH unit bursts; (b) the mean over SM-TH units of each unit's fraction of trials with a burst.
def burst_prob(r, level, trials):
b = r["burst"][(level, trials)]
m = (r["units"].group == "SM-TH").values
if m.sum() == 0 or b.shape[1] == 0:
return None
b = b[m]
return {"a": float(b.any(axis=0).mean()), "b": float(b.mean(axis=1).mean())}
def iqr(x):
q = np.percentile(x, [25, 50, 75])
return f"{q[1]:.3f} [{q[0]:.3f}-{q[2]:.3f}] (n={len(x)})"
rows = []
for lvl in LEVELS:
for tr in AWAKE:
d = pd.DataFrame([{"depth": r["depth"], **bp} for r in res if (bp := burst_prob(r, lvl, tr)) is not None])
for rd in ("a", "b"):
s, dp = d[d.depth == "superficial"][rd], d[d.depth == "deep"][rd]
mw = stats.mannwhitneyu(dp, s, alternative="two-sided")
rows.append({"level": lvl, "trials": tr, "reading": rd, "superficial": iqr(s), "deep": iqr(dp), "U p": f"{mw.pvalue:.3g}",
"holds": bool(abs(np.median(dp) - 0.12) <= 0.012 and np.median(s) == 0 and mw.pvalue < 0.05 and np.median(dp) > np.median(s))})
f5c = pd.DataFrame(rows)
print(f5c.to_string(index=False))
level trials reading superficial deep U p holds high awake a 0.117 [0.040-0.331] (n=4) 0.871 [0.551-1.000] (n=14) 0.0364 False high awake b 0.003 [0.002-0.029] (n=4) 0.131 [0.035-0.293] (n=14) 0.0248 False high quiet a 0.108 [0.025-0.352] (n=4) 0.927 [0.715-1.000] (n=14) 0.0266 False high quiet b 0.003 [0.001-0.033] (n=4) 0.155 [0.045-0.300] (n=14) 0.0176 False medium awake a 0.121 [0.044-0.317] (n=4) 0.838 [0.471-0.957] (n=14) 0.0383 False medium awake b 0.002 [0.001-0.017] (n=4) 0.117 [0.018-0.202] (n=14) 0.0176 False medium quiet a 0.145 [0.064-0.352] (n=4) 0.895 [0.519-0.997] (n=14) 0.0424 False medium quiet b 0.003 [0.002-0.020] (n=4) 0.130 [0.020-0.219] (n=14) 0.0435 False
Result: partially reproduced. With reading (b), the mean over SM-TH units of the fraction of trials with a burst, deep sites have a median of 0.131 [0.035 to 0.293] at the high current (within 0.12 +/- 0.012) and the Mann-Whitney test gives p = 0.025, deep higher; the superficial median is 0.003 [0.002 to 0.029], which is 0 at the paper's printed precision but not exactly 0 as the criterion requires. Reading (a) gives far higher probabilities (0.87 deep).
fig5e-early-latency and fig5f-rebound-latency¶
Responsive units: significantly increased in the window (stimulated-cortex RS; all SM-TH). Per unit, the median or mean over trials of the first-spike latency; per population, the median over its units; per site.
def latencies(c, lat_window, resp_window, summary, trials_state=None, depth=None, flags=None):
d = FL[c] if flags is None else flags
level, trials = c[0], c[1]
rows = []
for k, r in enumerate(res):
if depth and r["depth"] != depth:
continue
st = trials_state or trials
if (level, st, lat_window) not in r["latency"]:
continue
lat = r["latency"][(level, st, lat_window)]
x = d[(d.site_idx == k) & (d.window == resp_window) & d.inc]
u = r["units"].reset_index(drop=True)
out = {"subject": r["subject"], "site": r["site"], "depth": r["depth"]}
for pop, mask in (("cortex", (u.stim & u.rs)), ("SM-TH", (u.group == "SM-TH"))):
ids = set(x.unit) & set(u[mask].unit)
rowsel = u.index[u.unit.isin(ids)].values
if len(rowsel) == 0:
out[pop] = np.nan
continue
f = np.nanmedian if summary == "median" else np.nanmean
per_unit = f(lat[rowsel], axis=1)
out[pop] = 1000 * np.nanmedian(per_unit)
out[pop + " units"] = len(rowsel)
rows.append(out)
return pd.DataFrame(rows)
rows = []
for c in combos:
for summ in ("median", "mean"):
for dep in ("deep", None):
d = latencies(c, "early", "early", summ, depth=dep).dropna(subset=["cortex", "SM-TH"])
if len(d) < 2:
continue
tt = stats.ttest_rel(d["SM-TH"], d["cortex"])
diff = (d["SM-TH"] - d["cortex"]).mean()
rows.append({"level": c[0], "trials": c[1], "pre": c[2], "FDR": c[3], "unit summary": summ, "sites": dep or "all", "n": len(d),
"cortex ms": f"{d.cortex.mean():.1f} +/- {stats.sem(d.cortex):.1f}", "SM-TH ms": f"{d['SM-TH'].mean():.1f} +/- {stats.sem(d['SM-TH']):.1f}",
"diff ms": round(diff, 2), "p": f"{tt.pvalue:.3g}",
"holds": bool(abs(d.cortex.mean() - 4.4) <= 0.9 and abs(d['SM-TH'].mean() - 11.4) <= 2.8 and (abs(diff - 6.9) <= 0.69 or abs(diff - 6.7) <= 0.67) and tt.pvalue < 0.05 and diff > 0)})
f5e = pd.DataFrame(rows)
print(f5e.to_string(index=False))
level trials pre FDR unit summary sites n cortex ms SM-TH ms diff ms p holds high awake adjacent site median deep 10 4.3 +/- 0.3 8.2 +/- 0.8 3.90 0.00118 False high awake adjacent site median all 10 4.3 +/- 0.3 8.2 +/- 0.8 3.90 0.00118 False high awake adjacent site mean deep 10 4.6 +/- 0.3 8.8 +/- 0.6 4.15 0.000371 False high awake adjacent site mean all 10 4.6 +/- 0.3 8.8 +/- 0.6 4.15 0.000371 False high awake adjacent pooled median deep 11 4.3 +/- 0.3 9.0 +/- 0.4 4.69 3.57e-06 False high awake adjacent pooled median all 12 4.5 +/- 0.4 9.3 +/- 0.5 4.73 6.88e-07 False high awake adjacent pooled mean deep 11 4.6 +/- 0.3 9.3 +/- 0.5 4.70 3.1e-06 False high awake adjacent pooled mean all 12 4.9 +/- 0.4 9.6 +/- 0.5 4.75 5.92e-07 False high awake mirror site median deep 10 4.3 +/- 0.3 8.3 +/- 0.8 3.99 0.00122 False high awake mirror site median all 10 4.3 +/- 0.3 8.3 +/- 0.8 3.99 0.00122 False high awake mirror site mean deep 10 4.6 +/- 0.4 8.8 +/- 0.6 4.15 0.00033 False high awake mirror site mean all 10 4.6 +/- 0.4 8.8 +/- 0.6 4.15 0.00033 False high awake mirror pooled median deep 10 4.4 +/- 0.3 8.2 +/- 0.8 3.78 0.00128 False high awake mirror pooled median all 12 4.8 +/- 0.4 9.2 +/- 0.9 4.40 0.000317 False high awake mirror pooled mean deep 10 4.7 +/- 0.3 8.7 +/- 0.6 3.96 0.00036 False high awake mirror pooled mean all 12 5.2 +/- 0.4 9.5 +/- 0.7 4.29 3.65e-05 False high quiet adjacent site median deep 10 4.4 +/- 0.3 9.3 +/- 1.0 4.91 0.00142 False high quiet adjacent site median all 10 4.4 +/- 0.3 9.3 +/- 1.0 4.91 0.00142 False high quiet adjacent site mean deep 10 4.8 +/- 0.4 9.6 +/- 0.8 4.81 0.000833 False high quiet adjacent site mean all 10 4.8 +/- 0.4 9.6 +/- 0.8 4.81 0.000833 False high quiet adjacent pooled median deep 10 4.4 +/- 0.3 9.3 +/- 1.0 4.84 0.0016 False high quiet adjacent pooled median all 11 4.7 +/- 0.4 9.6 +/- 1.0 4.90 0.00056 False high quiet adjacent pooled mean deep 10 4.8 +/- 0.4 9.5 +/- 0.8 4.72 0.000911 False high quiet adjacent pooled mean all 11 5.1 +/- 0.5 9.8 +/- 0.8 4.72 0.000321 False high quiet mirror site median deep 11 4.3 +/- 0.3 8.9 +/- 0.9 4.60 0.000655 False high quiet mirror site median all 11 4.3 +/- 0.3 8.9 +/- 0.9 4.60 0.000655 False high quiet mirror site mean deep 11 4.6 +/- 0.4 9.2 +/- 0.7 4.56 0.000356 False high quiet mirror site mean all 11 4.6 +/- 0.4 9.2 +/- 0.7 4.56 0.000356 False high quiet mirror pooled median deep 11 4.3 +/- 0.3 8.9 +/- 0.9 4.57 0.000663 False high quiet mirror pooled median all 12 4.6 +/- 0.4 9.2 +/- 0.9 4.65 0.00022 False high quiet mirror pooled mean deep 11 4.6 +/- 0.4 9.1 +/- 0.7 4.53 0.000366 False high quiet mirror pooled mean all 12 4.9 +/- 0.4 9.4 +/- 0.7 4.54 0.000122 False medium awake adjacent site median deep 7 4.2 +/- 0.4 8.5 +/- 1.4 4.29 0.0166 False medium awake adjacent site median all 7 4.2 +/- 0.4 8.5 +/- 1.4 4.29 0.0166 False medium awake adjacent site mean deep 7 4.5 +/- 0.5 8.7 +/- 1.3 4.17 0.0111 False medium awake adjacent site mean all 7 4.5 +/- 0.5 8.7 +/- 1.3 4.17 0.0111 False medium awake adjacent pooled median deep 7 4.1 +/- 0.5 8.5 +/- 1.4 4.40 0.0176 False medium awake adjacent pooled median all 7 4.1 +/- 0.5 8.5 +/- 1.4 4.40 0.0176 False medium awake adjacent pooled mean deep 7 4.4 +/- 0.6 8.7 +/- 1.3 4.24 0.0117 False medium awake adjacent pooled mean all 7 4.4 +/- 0.6 8.7 +/- 1.3 4.24 0.0117 False medium awake mirror site median deep 7 4.2 +/- 0.4 8.4 +/- 1.4 4.27 0.017 False medium awake mirror site median all 7 4.2 +/- 0.4 8.4 +/- 1.4 4.27 0.017 False medium awake mirror site mean deep 7 4.5 +/- 0.5 8.7 +/- 1.3 4.17 0.0111 False medium awake mirror site mean all 7 4.5 +/- 0.5 8.7 +/- 1.3 4.17 0.0111 False medium awake mirror pooled median deep 7 4.2 +/- 0.4 8.4 +/- 1.4 4.28 0.0166 False medium awake mirror pooled median all 7 4.2 +/- 0.4 8.4 +/- 1.4 4.28 0.0166 False medium awake mirror pooled mean deep 7 4.5 +/- 0.6 8.6 +/- 1.3 4.11 0.0109 False medium awake mirror pooled mean all 7 4.5 +/- 0.6 8.6 +/- 1.3 4.11 0.0109 False medium quiet adjacent site median deep 6 4.0 +/- 0.5 7.4 +/- 1.3 3.33 0.0827 False medium quiet adjacent site median all 6 4.0 +/- 0.5 7.4 +/- 1.3 3.33 0.0827 False medium quiet adjacent site mean deep 6 4.2 +/- 0.5 7.7 +/- 1.2 3.52 0.0575 False medium quiet adjacent site mean all 6 4.2 +/- 0.5 7.7 +/- 1.2 3.52 0.0575 False medium quiet adjacent pooled median deep 6 4.0 +/- 0.5 7.2 +/- 1.3 3.24 0.0932 False medium quiet adjacent pooled median all 6 4.0 +/- 0.5 7.2 +/- 1.3 3.24 0.0932 False medium quiet adjacent pooled mean deep 6 4.2 +/- 0.5 7.7 +/- 1.3 3.46 0.0623 False medium quiet adjacent pooled mean all 6 4.2 +/- 0.5 7.7 +/- 1.3 3.46 0.0623 False medium quiet mirror site median deep 6 4.0 +/- 0.5 7.5 +/- 1.2 3.46 0.0667 False medium quiet mirror site median all 6 4.0 +/- 0.5 7.5 +/- 1.2 3.46 0.0667 False medium quiet mirror site mean deep 6 4.2 +/- 0.5 7.9 +/- 1.2 3.71 0.0413 False medium quiet mirror site mean all 6 4.2 +/- 0.5 7.9 +/- 1.2 3.71 0.0413 False medium quiet mirror pooled median deep 6 4.0 +/- 0.5 7.4 +/- 1.3 3.40 0.0754 False medium quiet mirror pooled median all 6 4.0 +/- 0.5 7.4 +/- 1.3 3.40 0.0754 False medium quiet mirror pooled mean deep 6 4.2 +/- 0.5 7.9 +/- 1.2 3.67 0.0445 False medium quiet mirror pooled mean all 6 4.2 +/- 0.5 7.9 +/- 1.2 3.67 0.0445 False
Result: partially reproduced. Stimulated-cortex RS units fire first, 4.0 to 5.2 ms (within 4.4 +/- 0.9), and SM-TH units later, 7.2 to 9.8 ms (within 11.4 +/- 2.8 in some readings), p < 0.05 in all high-current readings; but the mean difference is 3.2 to 4.9 ms against 6.9 (or 6.7), out of tolerance in every reading. 6 to 12 sites have responsive units in both populations, the paper 13.
rows = []
for c in combos:
for summ in ("median", "mean"):
for lw in ("late75", "late100"):
for resp in ("rebound", lw):
d = latencies(c, lw, resp, summ, depth="deep").dropna(subset=["cortex", "SM-TH"])
if len(d) < 2:
continue
tt = stats.ttest_rel(d["cortex"], d["SM-TH"])
diff = (d["cortex"] - d["SM-TH"]).mean()
rows.append({"level": c[0], "trials": c[1], "pre": c[2], "FDR": c[3], "summary": summ, "window": lw, "responsive in": resp, "n": len(d),
"SM-TH ms": f"{d['SM-TH'].mean():.1f} +/- {stats.sem(d['SM-TH']):.1f}", "cortex ms": f"{d.cortex.mean():.1f} +/- {stats.sem(d.cortex):.1f}",
"diff ms": round(diff, 1), "p": f"{tt.pvalue:.3g}",
"holds": bool(abs(d['SM-TH'].mean() - 148.2) <= 21.2 and abs(d.cortex.mean() - 184.2) <= 17.3 and (abs(diff - 36.0) <= 3.6 or abs(diff - 37.0) <= 3.7) and tt.pvalue < 0.05 and diff > 0)})
f5f = pd.DataFrame(rows)
print(f5f.to_string(index=False))
print("\ncombinations where the SM-TH fires first with p < 0.05:", int(((f5f["diff ms"] > 0) & (f5f.p.astype(float) < 0.05)).sum()), "of", len(f5f))
level trials pre FDR summary window responsive in n SM-TH ms cortex ms diff ms p holds high awake adjacent site median late75 rebound 12 173.4 +/- 7.2 180.6 +/- 3.7 7.2 0.352 False high awake adjacent site median late75 late75 12 164.9 +/- 8.0 179.4 +/- 5.2 14.5 0.106 False high awake adjacent site median late100 rebound 12 176.8 +/- 6.3 180.7 +/- 3.7 3.9 0.575 False high awake adjacent site median late100 late100 12 167.7 +/- 7.3 179.7 +/- 5.2 12.0 0.167 False high awake adjacent site mean late75 rebound 12 178.6 +/- 6.5 186.7 +/- 3.9 8.1 0.237 False high awake adjacent site mean late75 late75 12 168.6 +/- 7.8 184.3 +/- 5.2 15.8 0.0649 False high awake adjacent site mean late100 rebound 12 183.4 +/- 5.7 187.1 +/- 3.8 3.7 0.551 False high awake adjacent site mean late100 late100 12 174.3 +/- 6.6 185.0 +/- 5.1 10.7 0.149 False high awake adjacent pooled median late75 rebound 12 172.8 +/- 7.2 180.6 +/- 3.6 7.8 0.31 False high awake adjacent pooled median late75 late75 12 162.6 +/- 8.0 178.8 +/- 5.3 16.1 0.0778 False high awake adjacent pooled median late100 rebound 12 176.7 +/- 6.3 180.7 +/- 3.6 3.9 0.565 False high awake adjacent pooled median late100 late100 12 170.3 +/- 6.2 180.9 +/- 5.0 10.6 0.194 False high awake adjacent pooled mean late75 rebound 12 178.3 +/- 6.6 186.7 +/- 3.8 8.4 0.219 False high awake adjacent pooled mean late75 late75 12 168.9 +/- 7.4 183.7 +/- 5.2 14.8 0.0752 False high awake adjacent pooled mean late100 rebound 12 182.7 +/- 5.6 187.1 +/- 3.6 4.4 0.454 False high awake adjacent pooled mean late100 late100 12 178.2 +/- 5.4 186.1 +/- 4.7 7.9 0.259 False high awake mirror site median late75 rebound 12 170.2 +/- 7.4 179.7 +/- 3.5 9.5 0.239 False high awake mirror site median late75 late75 12 163.3 +/- 8.2 179.0 +/- 5.2 15.7 0.0782 False high awake mirror site median late100 rebound 12 173.9 +/- 6.3 179.8 +/- 3.4 5.8 0.401 False high awake mirror site median late100 late100 12 167.6 +/- 6.5 181.0 +/- 4.8 13.5 0.105 False high awake mirror site mean late75 rebound 12 176.1 +/- 6.5 185.8 +/- 3.8 9.8 0.149 False high awake mirror site mean late75 late75 12 167.5 +/- 8.2 183.6 +/- 5.5 16.1 0.0694 False high awake mirror site mean late100 rebound 12 181.1 +/- 5.5 186.4 +/- 3.6 5.3 0.366 False high awake mirror site mean late100 late100 12 175.4 +/- 5.8 186.7 +/- 4.8 11.3 0.114 False high awake mirror pooled median late75 rebound 12 168.5 +/- 8.1 179.2 +/- 3.5 10.6 0.208 False high awake mirror pooled median late75 late75 12 163.9 +/- 7.7 178.5 +/- 5.1 14.6 0.0857 False high awake mirror pooled median late100 rebound 12 173.6 +/- 6.4 179.2 +/- 3.5 5.6 0.416 False high awake mirror pooled median late100 late100 12 167.6 +/- 6.4 180.0 +/- 5.0 12.4 0.132 False high awake mirror pooled mean late75 rebound 12 174.0 +/- 7.4 185.5 +/- 3.8 11.5 0.119 False high awake mirror pooled mean late75 late75 12 169.4 +/- 7.3 182.9 +/- 5.4 13.5 0.0862 False high awake mirror pooled mean late100 rebound 12 180.3 +/- 6.2 185.9 +/- 3.7 5.6 0.37 False high awake mirror pooled mean late100 late100 12 175.9 +/- 5.4 185.9 +/- 5.0 9.9 0.158 False high quiet adjacent site median late75 rebound 12 175.6 +/- 7.7 182.9 +/- 4.1 7.3 0.355 False high quiet adjacent site median late75 late75 12 166.1 +/- 9.0 182.3 +/- 5.7 16.2 0.106 False high quiet adjacent site median late100 rebound 12 178.3 +/- 6.6 183.2 +/- 4.1 4.9 0.48 False high quiet adjacent site median late100 late100 12 170.5 +/- 7.4 182.5 +/- 5.6 12.0 0.156 False high quiet adjacent site mean late75 rebound 12 180.0 +/- 6.6 188.4 +/- 3.6 8.4 0.195 False high quiet adjacent site mean late75 late75 12 171.7 +/- 7.8 186.6 +/- 4.9 14.9 0.0646 False high quiet adjacent site mean late100 rebound 12 184.4 +/- 5.6 189.2 +/- 3.7 4.8 0.39 False high quiet adjacent site mean late100 late100 12 177.1 +/- 6.6 187.3 +/- 4.7 10.1 0.127 False high quiet adjacent pooled median late75 rebound 13 175.7 +/- 6.9 184.6 +/- 4.2 8.9 0.244 False high quiet adjacent pooled median late75 late75 12 165.3 +/- 9.0 184.8 +/- 5.8 19.5 0.0483 False high quiet adjacent pooled median late100 rebound 13 179.0 +/- 6.0 184.9 +/- 4.2 5.9 0.387 False high quiet adjacent pooled median late100 late100 12 169.6 +/- 7.7 184.0 +/- 5.4 14.4 0.121 False high quiet adjacent pooled mean late75 rebound 13 181.7 +/- 5.9 189.8 +/- 3.8 8.1 0.196 False high quiet adjacent pooled mean late75 late75 12 171.6 +/- 8.0 187.9 +/- 5.1 16.3 0.05 False high quiet adjacent pooled mean late100 rebound 13 185.7 +/- 5.1 190.4 +/- 3.8 4.7 0.407 False high quiet adjacent pooled mean late100 late100 12 177.5 +/- 6.7 188.3 +/- 4.4 10.8 0.123 False high quiet mirror site median late75 rebound 12 175.6 +/- 7.7 181.2 +/- 3.5 5.7 0.489 False high quiet mirror site median late75 late75 12 166.4 +/- 9.4 180.2 +/- 4.4 13.9 0.155 False high quiet mirror site median late100 rebound 12 179.4 +/- 6.6 181.2 +/- 3.5 1.9 0.795 False high quiet mirror site median late100 late100 12 172.7 +/- 7.6 182.3 +/- 4.2 9.5 0.267 False high quiet mirror site mean late75 rebound 12 181.5 +/- 6.4 187.2 +/- 3.4 5.7 0.367 False high quiet mirror site mean late75 late75 12 172.2 +/- 9.0 183.9 +/- 4.0 11.7 0.174 False high quiet mirror site mean late100 rebound 12 185.7 +/- 5.6 187.7 +/- 3.4 2.0 0.721 False high quiet mirror site mean late100 late100 12 179.5 +/- 6.9 187.4 +/- 3.9 7.8 0.245 False high quiet mirror pooled median late75 rebound 13 176.0 +/- 7.0 182.1 +/- 3.3 6.1 0.419 False high quiet mirror pooled median late75 late75 12 169.3 +/- 8.0 182.7 +/- 4.5 13.3 0.119 False high quiet mirror pooled median late100 rebound 13 179.8 +/- 6.0 182.2 +/- 3.3 2.4 0.716 False high quiet mirror pooled median late100 late100 12 172.6 +/- 7.6 181.6 +/- 4.3 9.0 0.297 False high quiet mirror pooled mean late75 rebound 13 182.0 +/- 5.8 188.5 +/- 3.2 6.5 0.298 False high quiet mirror pooled mean late75 late75 12 175.9 +/- 7.1 185.3 +/- 3.9 9.3 0.194 False high quiet mirror pooled mean late100 rebound 13 186.2 +/- 5.1 188.9 +/- 3.1 2.6 0.637 False high quiet mirror pooled mean late100 late100 12 179.7 +/- 6.9 186.4 +/- 4.0 6.7 0.339 False medium awake adjacent site median late75 rebound 11 163.1 +/- 10.1 177.8 +/- 4.3 14.7 0.165 False medium awake adjacent site median late75 late75 11 155.5 +/- 9.5 174.8 +/- 5.4 19.3 0.069 False medium awake adjacent site median late100 rebound 11 170.1 +/- 7.8 178.2 +/- 4.2 8.1 0.314 False medium awake adjacent site median late100 late100 10 165.7 +/- 7.6 177.4 +/- 5.0 11.7 0.179 False medium awake adjacent site mean late75 rebound 11 167.4 +/- 8.7 184.3 +/- 3.7 17.0 0.0541 False medium awake adjacent site mean late75 late75 11 161.7 +/- 8.6 180.8 +/- 4.7 19.1 0.0266 False medium awake adjacent site mean late100 rebound 11 175.9 +/- 7.0 185.5 +/- 3.5 9.6 0.167 False medium awake adjacent site mean late100 late100 10 172.6 +/- 6.9 184.3 +/- 4.3 11.6 0.101 False medium awake adjacent pooled median late75 rebound 13 161.0 +/- 9.0 174.2 +/- 4.3 13.2 0.185 False medium awake adjacent pooled median late75 late75 11 156.3 +/- 9.5 174.3 +/- 5.4 18.0 0.0951 False medium awake adjacent pooled median late100 rebound 13 170.8 +/- 7.0 175.2 +/- 4.0 4.4 0.574 False medium awake adjacent pooled median late100 late100 12 161.9 +/- 7.1 174.4 +/- 4.5 12.5 0.0935 False medium awake adjacent pooled mean late75 rebound 13 166.5 +/- 7.7 180.1 +/- 4.1 13.5 0.108 False medium awake adjacent pooled mean late75 late75 11 162.6 +/- 8.3 180.5 +/- 4.7 17.9 0.043 False medium awake adjacent pooled mean late100 rebound 13 176.9 +/- 6.3 182.0 +/- 3.7 5.1 0.46 False medium awake adjacent pooled mean late100 late100 12 170.7 +/- 6.2 181.0 +/- 4.1 10.3 0.0988 False medium awake mirror site median late75 rebound 10 169.0 +/- 9.9 174.7 +/- 5.5 5.8 0.585 False medium awake mirror site median late75 late75 11 159.8 +/- 9.4 174.7 +/- 5.7 15.0 0.187 False medium awake mirror site median late100 rebound 10 174.9 +/- 8.4 175.8 +/- 5.1 0.9 0.925 False medium awake mirror site median late100 late100 11 163.1 +/- 6.8 176.1 +/- 5.3 13.0 0.113 False medium awake mirror site mean late75 rebound 10 172.8 +/- 9.4 182.1 +/- 4.8 9.3 0.295 False medium awake mirror site mean late75 late75 11 166.0 +/- 7.7 181.2 +/- 5.1 15.2 0.0856 False medium awake mirror site mean late100 rebound 10 179.9 +/- 7.8 184.2 +/- 4.3 4.3 0.585 False medium awake mirror site mean late100 late100 11 171.6 +/- 6.3 182.8 +/- 4.5 11.2 0.09 False medium awake mirror pooled median late75 rebound 11 169.0 +/- 9.0 175.1 +/- 4.9 6.1 0.515 False medium awake mirror pooled median late75 late75 10 164.0 +/- 9.2 174.7 +/- 6.1 10.7 0.315 False medium awake mirror pooled median late100 rebound 11 173.6 +/- 7.4 176.0 +/- 4.6 2.4 0.759 False medium awake mirror pooled median late100 late100 11 166.1 +/- 7.4 175.8 +/- 5.4 9.7 0.287 False medium awake mirror pooled mean late75 rebound 11 172.2 +/- 8.7 182.7 +/- 4.4 10.5 0.185 False medium awake mirror pooled mean late75 late75 10 168.2 +/- 8.6 181.2 +/- 5.3 13.0 0.144 False medium awake mirror pooled mean late100 rebound 11 179.6 +/- 7.2 184.5 +/- 3.9 4.9 0.474 False medium awake mirror pooled mean late100 late100 11 172.9 +/- 6.6 182.0 +/- 4.6 9.1 0.204 False medium quiet adjacent site median late75 rebound 12 169.6 +/- 10.9 178.3 +/- 4.6 8.7 0.497 False medium quiet adjacent site median late75 late75 11 164.0 +/- 10.4 177.0 +/- 5.6 13.0 0.305 False medium quiet adjacent site median late100 rebound 12 176.5 +/- 9.0 179.1 +/- 4.2 2.6 0.801 False medium quiet adjacent site median late100 late100 12 173.9 +/- 8.3 178.6 +/- 4.7 4.8 0.631 False medium quiet adjacent site mean late75 rebound 12 174.1 +/- 9.2 186.5 +/- 4.1 12.5 0.247 False medium quiet adjacent site mean late75 late75 11 170.8 +/- 9.4 184.3 +/- 4.8 13.4 0.223 False medium quiet adjacent site mean late100 rebound 12 180.7 +/- 7.7 187.4 +/- 3.7 6.8 0.448 False medium quiet adjacent site mean late100 late100 12 179.5 +/- 7.4 187.1 +/- 4.2 7.6 0.396 False medium quiet adjacent pooled median late75 rebound 12 168.5 +/- 10.4 177.8 +/- 4.5 9.2 0.434 False medium quiet adjacent pooled median late75 late75 11 164.3 +/- 10.5 176.1 +/- 5.7 11.9 0.348 False medium quiet adjacent pooled median late100 rebound 12 175.1 +/- 8.4 178.6 +/- 4.2 3.5 0.709 False medium quiet adjacent pooled median late100 late100 13 171.3 +/- 7.3 177.9 +/- 4.4 6.6 0.453 False medium quiet adjacent pooled mean late75 rebound 12 173.9 +/- 9.3 186.0 +/- 4.0 12.1 0.26 False medium quiet adjacent pooled mean late75 late75 11 171.4 +/- 9.6 183.4 +/- 4.8 12.1 0.281 False medium quiet adjacent pooled mean late100 rebound 12 180.2 +/- 7.5 186.8 +/- 3.7 6.5 0.456 False medium quiet adjacent pooled mean late100 late100 13 178.6 +/- 6.7 185.4 +/- 4.1 6.8 0.4 False medium quiet mirror site median late75 rebound 11 171.0 +/- 11.6 177.5 +/- 4.9 6.4 0.62 False medium quiet mirror site median late75 late75 11 165.4 +/- 10.7 177.4 +/- 5.7 12.0 0.352 False medium quiet mirror site median late100 rebound 11 176.4 +/- 9.2 178.6 +/- 4.5 2.2 0.836 False medium quiet mirror site median late100 late100 11 172.7 +/- 8.3 177.8 +/- 5.2 5.0 0.609 False medium quiet mirror site mean late75 rebound 11 175.7 +/- 10.2 185.6 +/- 4.6 9.9 0.374 False medium quiet mirror site mean late75 late75 11 172.7 +/- 9.8 185.3 +/- 4.8 12.6 0.27 False medium quiet mirror site mean late100 rebound 11 181.5 +/- 8.1 186.6 +/- 4.2 5.1 0.573 False medium quiet mirror site mean late100 late100 11 179.3 +/- 7.7 185.6 +/- 4.6 6.3 0.481 False medium quiet mirror pooled median late75 rebound 12 171.3 +/- 10.8 178.2 +/- 4.6 6.9 0.564 False medium quiet mirror pooled median late75 late75 11 164.8 +/- 10.9 176.9 +/- 5.7 12.1 0.352 False medium quiet mirror pooled median late100 rebound 12 177.1 +/- 8.6 179.0 +/- 4.2 1.9 0.842 False medium quiet mirror pooled median late100 late100 13 171.5 +/- 7.2 177.0 +/- 4.4 5.5 0.517 False medium quiet mirror pooled mean late75 rebound 12 175.8 +/- 9.7 186.4 +/- 4.3 10.6 0.317 False medium quiet mirror pooled mean late75 late75 11 172.3 +/- 10.1 183.2 +/- 5.3 10.9 0.336 False medium quiet mirror pooled mean late100 rebound 12 181.7 +/- 7.6 187.4 +/- 3.9 5.6 0.508 False medium quiet mirror pooled mean late100 late100 13 179.0 +/- 6.6 184.5 +/- 4.1 5.4 0.476 False combinations where the SM-TH fires first with p < 0.05: 3 of 128
Result: not reproduced. In the late window the mean SM-TH latency (155.5 to 186.2 ms) is earlier than the cortical one (174.2 to 190.4 ms) in all 128 combinations of readings, but by 0.9 to 19.5 ms against 36.0, and significantly (p < 0.05) in 3 of 128.
fig6b, fig6c, fig6-supp2: trial-by-trial correlations in deep sites¶
Per deep site with SM-TH and stimulated-cortex RS units, awake trials: the fraction of SM-TH units with a burst in 75-300 ms, the peak stimulated-cortex population rate in 75-300 ms (5 or 10 ms bins), the peak SM-TH population rate, and the single-trial late ERP amplitude ((a) peak GFP, (b) peak |V| at the electrode with the largest trial-averaged late component). Pearson r and p per site.
t0 = time.time()
deep_sites = [(k, r) for k, r in enumerate(res) if r["depth"] == "deep" and (r["units"].group == "SM-TH").any() and (r["units"].stim & r["units"].rs).any()]
LATE = {}
for k, r in deep_sites:
m = [mm for mm in metas if mm["subject"] == r["subject"] and mm["session"] == r["session"]][0]
LATE[k] = claar.late_amplitudes(m, r["site"])
print(f"single-trial EEG for {len(deep_sites)} deep sites in {time.time() - t0:.0f} s")
def trial_table(k, r, level):
ids = r["trial_ids"][(level, "awake")]
b = r["burst"][(level, "awake")][(r["units"].group == "SM-TH").values]
d = pd.DataFrame({"trial": ids, "burst_frac": b.mean(axis=0)})
for bs in (0.005, 0.010):
d[f"ctx_{int(bs * 1000)}"] = r["rate"][(level, "single", bs, "stimRS")]
d[f"th_{int(bs * 1000)}"] = r["rate"][(level, "single", bs, "smth")]
return d.merge(LATE[k][level], on="trial")
def corr_rows(xcol, ycol, level):
out = []
for k, r in deep_sites:
d = trial_table(k, r, level)
if d[xcol].std() == 0 or d[ycol].std() == 0:
out.append({"subject": r["subject"], "site": r["site"], "r": np.nan, "p": np.nan, "n": len(d)})
continue
pr = stats.pearsonr(d[xcol], d[ycol])
out.append({"subject": r["subject"], "site": r["site"], "r": pr.statistic, "p": pr.pvalue, "n": len(d)})
return pd.DataFrame(out)
def summarize(pairs, exp_n, exp_r, tol_r):
rows = []
for lvl in LEVELS:
for name, (x, y) in pairs.items():
d = corr_rows(x, y, lvl)
n_sig = int((d.p < 0.05).sum())
rows.append({"level": lvl, "pair": name, "sites": len(d), "significant": f"{n_sig}/{len(d)}",
"mean r": f"{d.r.mean():.3f} +/- {stats.sem(d.r, nan_policy='omit'):.3f}",
"holds": bool(abs(d.r.mean() - exp_r) <= tol_r and abs(n_sig / len(d) - exp_n[0] / exp_n[1]) <= 0.1 * exp_n[0] / exp_n[1])})
return pd.DataFrame(rows)
single-trial EEG for 13 deep sites in 146 s
f6b = summarize({"bursts vs cortex 5 ms": ("burst_frac", "ctx_5"), "bursts vs cortex 10 ms": ("burst_frac", "ctx_10")}, (8, 13), 0.4, 0.04)
print(f6b.to_string(index=False))
print("\nper site, high current, 5 ms bins:")
print(corr_rows("burst_frac", "ctx_5", "high").round(3).to_string(index=False))
level pair sites significant mean r holds high bursts vs cortex 5 ms 13 6/13 0.139 +/- 0.055 False high bursts vs cortex 10 ms 13 6/13 0.132 +/- 0.057 False medium bursts vs cortex 5 ms 13 7/13 0.232 +/- 0.069 False medium bursts vs cortex 10 ms 13 10/13 0.238 +/- 0.069 False per site, high current, 5 ms bins: subject site r p n 546655 MOs-deep 0.057 0.536 119 551397 MOs-deep 0.337 0.000 120 551399 MOs-deep 0.161 0.079 120 569062 MOs-deep 0.221 0.015 120 569068 MOs-deep 0.380 0.000 120 569069 MOs-deep 0.266 0.004 118 569072 SSp-deep -0.261 0.004 120 569073 MOs-deep -0.058 0.540 113 569073 SSp-deep -0.056 0.549 118 571619 MOs-deep 0.464 0.000 120 571620 SSp-deep 0.110 0.231 120 586468 SSp-deep 0.079 0.390 120 590480 SSp-deep 0.106 0.252 119
Result: not reproduced. In the 13 deep sites with SM-TH and stimulated-cortex units (the paper's N), the trial-by-trial Pearson r between the SM-TH burst fraction and the peak cortical rate averages 0.13 to 0.24 against 0.4 +/- 0.04, with 6 to 10 sites significant against 8.
f6c = summarize({"cortex 5 ms vs late GFP (a)": ("ctx_5", "late_gfp"), "cortex 10 ms vs late GFP (a)": ("ctx_10", "late_gfp"),
"cortex 5 ms vs electrode (b)": ("ctx_5", "late_electrode"), "cortex 10 ms vs electrode (b)": ("ctx_10", "late_electrode")}, (9, 13), 0.5, 0.04)
print(f6c.to_string(index=False))
level pair sites significant mean r holds high cortex 5 ms vs late GFP (a) 13 7/13 0.218 +/- 0.065 False high cortex 10 ms vs late GFP (a) 13 8/13 0.243 +/- 0.067 False high cortex 5 ms vs electrode (b) 13 7/13 0.207 +/- 0.064 False high cortex 10 ms vs electrode (b) 13 8/13 0.241 +/- 0.061 False medium cortex 5 ms vs late GFP (a) 13 8/13 0.244 +/- 0.067 False medium cortex 10 ms vs late GFP (a) 13 10/13 0.259 +/- 0.071 False medium cortex 5 ms vs electrode (b) 13 9/13 0.305 +/- 0.067 False medium cortex 10 ms vs electrode (b) 13 11/13 0.320 +/- 0.070 False
Result: not reproduced. The peak cortical rate correlates with the single-trial late ERP amplitude with mean r 0.21 to 0.32 against 0.5 +/- 0.04; 7 to 11 of 13 sites are significant against 9.
rows = []
for lvl in LEVELS:
for amp in ("late_gfp", "late_electrode"):
b = corr_rows("burst_frac", amp, lvl)
for bs in ("th_5", "th_10"):
t = corr_rows(bs, amp, lvl)
nb, nt = int((b.p < 0.05).sum()), int((t.p < 0.05).sum())
rows.append({"level": lvl, "late ERP": amp, "SM-TH rate bins": bs, "sites": len(b),
"bursts: significant": f"{nb}/{len(b)}", "bursts: mean r": f"{b.r.mean():.3f} +/- {stats.sem(b.r, nan_policy='omit'):.3f}",
"rate: significant": f"{nt}/{len(t)}", "rate: mean r": f"{t.r.mean():.3f}",
"holds": bool(abs(b.r.mean() - 0.5) <= 0.07 and nb >= len(b) - 1 and t.r.mean() < b.r.mean() and nt < nb)})
f6s = pd.DataFrame(rows)
print(f6s.to_string(index=False))
level late ERP SM-TH rate bins sites bursts: significant bursts: mean r rate: significant rate: mean r holds high late_gfp th_5 13 13/13 0.462 +/- 0.039 4/13 0.059 True high late_gfp th_10 13 13/13 0.462 +/- 0.039 4/13 0.057 True high late_electrode th_5 13 12/13 0.424 +/- 0.045 5/13 0.067 False high late_electrode th_10 13 12/13 0.424 +/- 0.045 5/13 0.073 False medium late_gfp th_5 13 13/13 0.455 +/- 0.077 4/13 0.081 True medium late_gfp th_10 13 13/13 0.455 +/- 0.077 4/13 0.099 True medium late_electrode th_5 13 11/13 0.502 +/- 0.053 5/13 0.055 False medium late_electrode th_10 13 11/13 0.502 +/- 0.053 3/13 0.073 False
Result: reproduced. The late ERP amplitude (peak GFP, 75 to 300 ms) correlates with the SM-TH burst fraction in 13 of 13 sites at both currents, mean r 0.462 +/- 0.039 (high) and 0.455 (medium), within 0.5 +/- 0.07; its correlation with the peak SM-TH rate is lower (mean r 0.06 to 0.10, 4 of 13 significant). The electrode reading of the late ERP (b) does not meet the criterion: 12 of 13 sites significant at the high current (mean r 0.424) and 11 of 13 at the medium current (0.502).
Figure 7: states¶
Per site, quiet, running and isoflurane trials of the intensity used; per animal (sites of one animal averaged); session sets (a) deep sites, (b) all sites with units.
def baseline_frame(level, window):
rows = []
for r in res:
u = r["units"].reset_index(drop=True)
for st in ("quiet", "running", "isoflurane"):
if r["n"][(level, st)] == 0:
continue
b = r["baseline"][(level, st)][window]
for pop, mask in (("cortex", (u.stim & u.rs).values), ("SM-TH", (u.group == "SM-TH").values)):
if mask.sum():
rows.append({"subject": r["subject"], "depth": r["depth"], "state": st, "pop": pop, "rate": b[mask].mean()})
return pd.DataFrame(rows)
exp7e = {("cortex", "quiet"): [(3.5, 0.2), (3.3, 0.2)], ("cortex", "running"): [(5.2, 0.5), (5.0, 0.5)], ("cortex", "isoflurane"): [(1.1, 0.2), (1.1, 0.2)],
("SM-TH", "quiet"): [(9.0, 1.4), (9.4, 1.5)], ("SM-TH", "running"): [(16.4, 1.5), (16.8, 1.6)], ("SM-TH", "isoflurane"): [(0.8, 0.4), (0.8, 0.4)]}
rows = []
for lvl in LEVELS:
for win in ("-2-0", "-0.5-0"):
d = baseline_frame(lvl, win)
for setname, sub in (("a: deep", d[d.depth == "deep"]), ("b: all", d)):
out = {"level": lvl, "window": win, "set": setname}
within = [True, True]
order = True
for pop in ("cortex", "SM-TH"):
w = sub[sub["pop"] == pop].pivot_table(index="subject", columns="state", values="rate", aggfunc="mean").dropna()
for st in ("quiet", "running", "isoflurane"):
out[f"{pop} {st}"] = f"{w[st].mean():.2f} +/- {stats.sem(w[st]):.2f}"
for j in range(2):
within[j] &= abs(w[st].mean() - exp7e[(pop, st)][j][0]) <= exp7e[(pop, st)][j][1]
order &= bool(w.running.mean() > w.quiet.mean() > w.isoflurane.mean())
if pop == "cortex":
long = w.reset_index().melt(id_vars="subject", var_name="state", value_name="rate")
an = AnovaRM(long, "rate", "subject", within=["state"]).fit().anova_table
out["cortex RM ANOVA"] = f"F[{int(an['Num DF'].iloc[0])},{int(an['Den DF'].iloc[0])}]={an['F Value'].iloc[0]:.1f}, p={an['Pr > F'].iloc[0]:.2g}"
p1 = an["Pr > F"].iloc[0]
else:
fr = stats.friedmanchisquare(w.quiet, w.running, w.isoflurane)
out["SM-TH Friedman"] = f"Q={fr.statistic:.1f}, p={fr.pvalue:.2g}, n={len(w)}"
p2 = fr.pvalue
out["within (Results / Discussion)"] = f"{within[0]} / {within[1]}"
out["order"] = order
out["holds"] = bool(any(within) and order and p1 < 0.05 and p2 < 0.05)
rows.append(out)
f7e = pd.DataFrame(rows)
print(f7e.to_string(index=False))
level window set cortex quiet cortex running cortex isoflurane cortex RM ANOVA SM-TH quiet SM-TH running SM-TH isoflurane SM-TH Friedman within (Results / Discussion) order holds high -2-0 a: deep 3.56 +/- 0.26 4.97 +/- 0.49 1.02 +/- 0.16 F[2,28]=86.7, p=1e-12 9.11 +/- 1.48 15.52 +/- 1.70 0.81 +/- 0.35 Q=24.2, p=5.7e-06, n=13 True / False True True high -2-0 b: all 3.41 +/- 0.24 4.80 +/- 0.48 0.98 +/- 0.14 F[2,30]=80.7, p=8.5e-13 9.02 +/- 1.50 15.47 +/- 1.81 0.82 +/- 0.35 Q=24.2, p=5.7e-06, n=13 True / True True True high -0.5-0 a: deep 3.57 +/- 0.25 5.05 +/- 0.50 1.01 +/- 0.16 F[2,28]=85.7, p=1.2e-12 9.09 +/- 1.51 15.76 +/- 1.67 0.81 +/- 0.35 Q=24.2, p=5.7e-06, n=13 True / False True True high -0.5-0 b: all 3.41 +/- 0.24 4.85 +/- 0.48 0.98 +/- 0.14 F[2,30]=81.0, p=8.1e-13 8.98 +/- 1.53 15.65 +/- 1.76 0.82 +/- 0.36 Q=24.2, p=5.7e-06, n=13 True / True True True medium -2-0 a: deep 3.48 +/- 0.26 5.04 +/- 0.47 1.03 +/- 0.16 F[2,28]=94.3, p=3.7e-13 8.92 +/- 1.45 15.76 +/- 1.73 0.85 +/- 0.39 Q=24.2, p=5.7e-06, n=13 True / True True True medium -2-0 b: all 3.37 +/- 0.24 4.84 +/- 0.46 0.99 +/- 0.15 F[2,30]=86.1, p=3.7e-13 8.94 +/- 1.49 15.56 +/- 1.78 0.86 +/- 0.39 Q=24.2, p=5.7e-06, n=13 True / True True True medium -0.5-0 a: deep 3.50 +/- 0.25 5.15 +/- 0.50 1.06 +/- 0.17 F[2,28]=86.1, p=1.1e-12 8.85 +/- 1.46 16.06 +/- 1.73 0.85 +/- 0.38 Q=24.2, p=5.7e-06, n=13 True / False True True medium -0.5-0 b: all 3.38 +/- 0.23 4.94 +/- 0.49 1.00 +/- 0.15 F[2,30]=77.9, p=1.3e-12 8.87 +/- 1.50 15.79 +/- 1.79 0.86 +/- 0.39 Q=24.2, p=5.7e-06, n=13 True / True True True
Result: reproduced. In the deep sites, high current, -2 to 0 s: stimulated-cortex RS 3.56, 4.97 and 1.02 Hz and SM-TH 9.11, 15.52 and 0.81 Hz (quiet, running, isoflurane), all within tolerance of the Results' values; RM ANOVA F[2,28] = 86.7, p = 1e-12 (15 animals); Friedman Q = 24.2, p = 5.7e-06 (13 animals), the paper's Q and p. Over all sites the cortex has the paper's 16 animals (F[2,30] = 80.7) and the means are within tolerance of the Results' or the Discussion's values.
def lat_state(c, lat_window, resp_window, summ, depth, resp_from="state"):
# responsive units from the trials of each state, or from all awake trials (resp_from="awake")
rows = []
for st in ("quiet", "running", "isoflurane"):
cc = (c[0], st, c[2], c[3]) if st != "running" else (c[0], "running", "adjacent", c[3])
if cc not in FL:
FL[cc] = flags_all(*cc)
flags = FL[(c[0], "awake", c[2], c[3])] if resp_from == "awake" else None
d = latencies(cc, lat_window, resp_window, summ, depth=depth, flags=flags)
d["state"] = st
rows.append(d)
d = pd.concat(rows)
d = d.groupby(["subject", "state"])[["cortex", "SM-TH"]].mean().reset_index()
full = d.dropna().groupby("subject").filter(lambda g: len(g) == 3)
return full
def two_way(full):
long = full.melt(id_vars=["subject", "state"], value_vars=["cortex", "SM-TH"], var_name="region", value_name="lat")
return AnovaRM(long, "lat", "subject", within=["state", "region"]).fit().anova_table
rows = []
for lvl in LEVELS:
for pre in claar.PRE_READINGS:
for fam in ("site", "pooled"):
for summ, rf in (("median", "state"), ("mean", "state"), ("median", "awake"), ("mean", "awake")):
full = lat_state((lvl, None, pre, fam), "early", "early", summ, "deep", rf)
if full.subject.nunique() < 3:
continue
an = two_way(full)
g = full.groupby("state")[["cortex", "SM-TH"]].mean()
rows.append({"level": lvl, "pre": pre, "FDR": fam, "summary": summ, "responsive from": rf, "animals": full.subject.nunique(),
**{f"{p} {s}": round(g.loc[s, p], 2) for p in ("cortex", "SM-TH") for s in ("quiet", "running", "isoflurane")},
"state F, p": f"{an.loc['state', 'F Value']:.2f}, {an.loc['state', 'Pr > F']:.3g}",
"region F, p": f"{an.loc['region', 'F Value']:.1f}, {an.loc['region', 'Pr > F']:.3g}",
"holds": bool(an.loc["state", "Pr > F"] >= 0.05 and an.loc["region", "Pr > F"] < 0.05)})
f7f = pd.DataFrame(rows)
print(f7f.to_string(index=False))
if len(f7f):
print("\nrows where the state effect is absent (p >= 0.05) and the region effect present:", int(f7f.holds.sum()), "of", len(f7f))
full = lat_state(("high", None, "adjacent", "site"), "early", "early", "median", "deep", "awake")
print("\nbounds on the state effect, high current, adjacent, per-site FDR, median, responsive from all awake trials "
f"({full.subject.nunique()} animals): paired difference of state means, ms, mean [95% CI]")
w = full.pivot_table(index="subject", columns="state", values=["cortex", "SM-TH"])
for pop in ("cortex", "SM-TH"):
for a, b in (("quiet", "running"), ("quiet", "isoflurane"), ("running", "isoflurane")):
dd = (w[(pop, a)] - w[(pop, b)]).values
ci = stats.t.interval(0.95, len(dd) - 1, loc=dd.mean(), scale=stats.sem(dd))
print(f" {pop} {a} - {b}: {dd.mean():.2f} [{ci[0]:.2f}, {ci[1]:.2f}]")
level pre FDR summary responsive from animals cortex quiet cortex running cortex isoflurane SM-TH quiet SM-TH running SM-TH isoflurane state F, p region F, p holds high adjacent site median state 3 4.40 4.05 4.28 6.74 6.52 8.44 0.26, 0.782 1.9, 0.3 False high adjacent site mean state 3 4.88 4.41 4.44 7.61 6.41 7.97 0.31, 0.752 1.8, 0.314 False high adjacent site median awake 8 4.22 3.96 4.42 8.88 7.96 10.74 2.43, 0.124 28.1, 0.00112 True high adjacent site mean awake 8 4.53 4.18 4.67 9.09 8.30 11.09 2.92, 0.0871 34.1, 0.000637 True high adjacent pooled median state 3 4.45 4.31 4.32 6.72 6.25 8.44 0.29, 0.762 1.7, 0.321 False high adjacent pooled mean state 3 4.96 4.57 4.44 7.61 6.26 7.97 0.34, 0.734 1.7, 0.318 False high adjacent pooled median awake 8 4.34 4.10 4.49 9.12 8.38 11.28 2.32, 0.135 44.9, 0.000278 True high adjacent pooled mean awake 8 4.61 4.30 4.69 9.24 8.60 11.63 3.07, 0.0786 53.9, 0.000157 True high mirror site median state 3 4.46 4.05 4.49 6.72 6.52 8.48 0.30, 0.754 2.0, 0.296 False high mirror site mean state 3 4.92 4.41 4.62 7.59 6.41 8.01 0.31, 0.749 1.8, 0.314 False high mirror site median awake 8 4.21 3.98 4.43 8.88 7.95 10.60 2.37, 0.13 28.3, 0.0011 True high mirror site mean awake 8 4.48 4.22 4.64 9.07 8.35 10.95 2.74, 0.099 35.9, 0.000547 True high mirror pooled median state 3 4.45 4.31 4.52 6.71 6.25 8.42 0.31, 0.747 1.7, 0.319 False high mirror pooled mean state 3 4.96 4.57 4.62 7.59 6.26 8.01 0.32, 0.74 1.7, 0.318 False high mirror pooled median awake 8 4.30 4.08 4.47 8.72 7.94 10.17 1.79, 0.203 27.4, 0.00121 True high mirror pooled mean awake 8 4.57 4.29 4.65 8.95 8.34 10.53 2.07, 0.163 35.7, 0.000554 True medium adjacent site median awake 6 3.96 3.90 4.22 8.19 7.92 7.10 0.16, 0.852 14.3, 0.0129 True medium adjacent site mean awake 6 4.26 3.95 4.52 8.45 8.12 7.72 0.11, 0.894 14.2, 0.013 True medium adjacent pooled median awake 6 3.94 3.72 3.96 8.20 7.95 7.06 0.29, 0.751 12.4, 0.0168 True medium adjacent pooled mean awake 6 4.26 3.79 4.30 8.48 8.14 7.65 0.22, 0.803 12.4, 0.0168 True medium mirror site median awake 6 3.97 3.91 4.24 8.19 7.98 7.10 0.17, 0.848 14.1, 0.0132 True medium mirror site mean awake 6 4.27 3.99 4.53 8.48 8.20 7.69 0.10, 0.903 14.0, 0.0133 True medium mirror pooled median awake 6 4.00 3.85 4.21 8.19 7.96 7.06 0.20, 0.821 14.2, 0.0131 True medium mirror pooled mean awake 6 4.29 3.90 4.52 8.45 8.13 7.66 0.14, 0.871 14.0, 0.0134 True rows where the state effect is absent (p >= 0.05) and the region effect present: 16 of 24
bounds on the state effect, high current, adjacent, per-site FDR, median, responsive from all awake trials (8 animals): paired difference of state means, ms, mean [95% CI] cortex quiet - running: 0.25 [-0.06, 0.57] cortex quiet - isoflurane: -0.21 [-0.86, 0.45] cortex running - isoflurane: -0.46 [-1.22, 0.30] SM-TH quiet - running: 0.92 [0.04, 1.80] SM-TH quiet - isoflurane: -1.86 [-6.07, 2.36] SM-TH running - isoflurane: -2.78 [-7.48, 1.93]
Result: reproduced, resting on an assumption. With responsive units taken from all awake trials, the two-way RM ANOVA finds no state effect (p = 0.08 to 0.90) and a region effect (p = 0.00016 to 0.017) in all 16 such readings (8 animals at the high current, 6 at the medium). With responsive units taken from each state's own trials only 3 animals have units in every state and cell, and no region effect is found (p about 0.3). The SM-TH latencies (7.1 to 11.6 ms) are mostly below 11.5, 11.3 and 10.9 +/- 0.8. The absence of a state effect rests on 6 to 8 animals against the paper's 13; at the high current (8 animals) the 95% confidence intervals of the paired state differences are within -1.3 to +0.6 ms in cortex and -7.5 to +2.4 ms in SM-TH, and the SM-TH quiet against running difference (0.92 ms [0.04, 1.80]) excludes zero without a correction for the six pairs.
exp7g = {("cortex", "quiet"): (186.7, 4.6), ("cortex", "running"): (163.8, 5.0), ("cortex", "isoflurane"): (200.2, 7.5),
("SM-TH", "quiet"): (156.0, 7.1), ("SM-TH", "running"): (123.1, 3.9), ("SM-TH", "isoflurane"): (195.1, 9.5)}
rows = []
for lvl in LEVELS:
for pre in claar.PRE_READINGS:
for fam in ("site", "pooled"):
for summ in ("median", "mean"):
for lw in ("late100", "late75"):
for resp, rf in (("rebound", "state"), (lw, "state"), ("rebound", "awake"), (lw, "awake")):
full = lat_state((lvl, None, pre, fam), lw, resp, summ, "deep", rf)
if full.subject.nunique() < 3:
continue
an = two_way(full)
g = full.groupby("state")[["cortex", "SM-TH"]].mean()
pairs = [(p, a, b) for p in ("cortex", "SM-TH") for a, b in (("quiet", "running"), ("quiet", "isoflurane"), ("running", "isoflurane"))]
pv = []
for p, a, b in pairs:
w = full.pivot(index="subject", columns="state", values=p)
pv.append(stats.ttest_rel(w[a], w[b]).pvalue)
q = claar.bh(pv)
run_earlier = all(g.loc["running", p] < g.loc["quiet", p] for p in ("cortex", "SM-TH"))
within = all(abs(g.loc[s, p] - v[0]) <= v[1] for (p, s), v in exp7g.items())
rows.append({"level": lvl, "pre": pre, "FDR": fam, "summary": summ, "window": lw, "responsive in": resp, "from": rf, "animals": full.subject.nunique(),
**{f"{p[:3]} {s[:4]}": round(g.loc[s, p], 1) for p in ("cortex", "SM-TH") for s in ("quiet", "running", "isoflurane")},
"state p": f"{an.loc['state', 'Pr > F']:.3g}", "q ctx q-r": round(q[0], 3), "q th q-r": round(q[3], 3),
"within": within,
"state & run<quiet sig": bool(an.loc["state", "Pr > F"] < 0.05 and run_earlier and q[0] < 0.05 and q[3] < 0.05)})
f7g = pd.DataFrame(rows)
print(f7g.to_string(index=False))
if len(f7g):
print("\nrows where state p < 0.05 and running is earlier than quiet in both regions by the corrected test:", int(f7g["state & run<quiet sig"].sum()), "of", len(f7g))
print("rows with all six means within tolerance:", int(f7g.within.sum()))
level pre FDR summary window responsive in from animals cor quie cor runn cor isof SM- quie SM- runn SM- isof state p q ctx q-r q th q-r within state & run<quiet sig high adjacent site median late100 rebound awake 11 183.1 169.2 218.3 180.3 150.1 215.8 2.12e-06 0.000 0.000 False True high adjacent site median late100 late100 awake 12 182.3 163.8 207.7 171.4 146.7 207.4 8.07e-06 0.000 0.000 False True high adjacent site median late75 rebound awake 11 183.1 167.9 215.7 177.9 141.1 203.3 2.95e-05 0.001 0.001 False True high adjacent site median late75 late75 awake 12 181.9 162.4 206.4 168.6 137.6 203.0 2.34e-06 0.000 0.000 False True high adjacent site mean late100 rebound awake 11 190.1 176.3 216.7 186.3 162.7 216.4 8.63e-07 0.000 0.000 False True high adjacent site mean late100 late100 awake 12 187.3 170.8 207.5 178.4 158.1 207.6 5.13e-06 0.000 0.000 False True high adjacent site mean late75 rebound awake 11 189.9 174.8 214.4 182.3 153.4 203.1 2.51e-05 0.001 0.000 False True high adjacent site mean late75 late75 awake 12 186.6 167.9 205.9 173.9 146.2 201.4 1.09e-06 0.001 0.000 False True high adjacent pooled median late100 rebound awake 11 182.7 169.9 217.4 180.2 148.8 220.1 1.06e-06 0.000 0.000 False True high adjacent pooled median late100 late100 awake 12 183.3 163.5 216.4 174.3 146.1 208.3 1.02e-06 0.001 0.000 False True high adjacent pooled median late75 rebound awake 11 182.7 167.9 214.1 177.5 141.3 206.0 6.36e-06 0.001 0.001 False True high adjacent pooled median late75 late75 awake 12 181.4 161.7 206.3 166.9 134.1 204.3 2.08e-06 0.000 0.000 False True high adjacent pooled mean late100 rebound awake 11 190.0 176.4 216.2 186.7 161.6 219.1 4.25e-07 0.000 0.000 False True high adjacent pooled mean late100 late100 awake 12 188.3 170.4 215.4 182.6 159.9 208.8 2.95e-07 0.000 0.000 False True high adjacent pooled mean late75 rebound awake 11 189.7 174.8 213.0 182.1 153.7 203.8 8.63e-06 0.001 0.000 False True high adjacent pooled mean late75 late75 awake 12 186.1 168.2 206.4 173.9 145.3 205.0 1.15e-06 0.000 0.000 False True high mirror site median late100 rebound awake 11 182.0 166.5 216.4 179.5 151.4 218.5 1.93e-06 0.000 0.000 False True high mirror site median late100 late100 awake 11 183.8 162.6 219.8 173.6 145.2 209.7 1.88e-06 0.001 0.000 False True high mirror site median late75 rebound awake 11 181.9 166.1 214.4 177.2 141.1 213.6 1.1e-06 0.001 0.001 False True high mirror site median late75 late75 awake 11 181.8 160.7 211.4 169.6 136.7 204.5 2.68e-06 0.000 0.000 False True high mirror site mean late100 rebound awake 11 188.6 173.8 217.0 186.3 162.0 217.1 6.74e-07 0.000 0.000 False True high mirror site mean late100 late100 awake 11 189.0 168.7 218.8 181.8 159.2 209.7 6.04e-07 0.001 0.000 False True high mirror site mean late75 rebound awake 11 188.2 172.6 215.3 182.7 152.1 211.5 4e-07 0.000 0.000 False True high mirror site mean late75 late75 awake 11 186.1 165.5 209.9 175.4 146.8 204.6 1.59e-06 0.000 0.000 False True high mirror pooled median late100 rebound awake 11 181.0 165.5 216.3 178.9 153.5 221.0 2.71e-07 0.000 0.000 False True high mirror pooled median late100 late100 awake 11 182.8 162.2 219.4 173.1 145.0 213.8 4.21e-07 0.001 0.000 False True high mirror pooled median late75 rebound awake 11 180.9 165.0 214.5 175.7 141.0 216.1 3.1e-07 0.000 0.001 False True high mirror pooled median late75 late75 awake 11 181.4 159.8 211.3 170.3 136.9 205.2 1.93e-06 0.000 0.000 False True high mirror pooled mean late100 rebound awake 11 188.4 172.5 216.7 185.2 161.8 220.3 4.01e-08 0.000 0.000 False True high mirror pooled mean late100 late100 awake 11 187.9 169.4 218.6 182.4 159.0 212.1 1.05e-07 0.000 0.000 False True high mirror pooled mean late75 rebound awake 11 188.0 171.4 214.3 180.6 151.0 214.3 1.47e-07 0.000 0.001 False True high mirror pooled mean late75 late75 awake 11 185.9 164.9 209.8 177.4 147.3 204.7 9.14e-07 0.000 0.000 False True medium adjacent site median late100 rebound awake 9 180.4 163.0 216.2 176.0 146.0 212.8 1.08e-06 0.000 0.002 False True medium adjacent site median late100 late100 awake 9 179.1 161.3 217.6 172.9 144.9 215.3 1.27e-06 0.000 0.002 False True medium adjacent site median late75 rebound awake 9 180.2 160.5 209.0 173.0 134.6 204.0 8.18e-07 0.000 0.001 False True medium adjacent site median late75 late75 awake 9 179.6 156.8 210.8 169.4 132.7 207.6 1.16e-06 0.000 0.000 False True medium adjacent site mean late100 rebound awake 9 188.5 170.5 213.3 182.5 156.4 214.3 1.14e-06 0.000 0.001 False True medium adjacent site mean late100 late100 awake 9 185.9 169.1 213.6 179.6 155.7 212.5 4.77e-06 0.003 0.002 False True medium adjacent site mean late75 rebound awake 9 188.2 166.7 206.1 177.2 143.8 201.6 6.42e-07 0.000 0.001 False True medium adjacent site mean late75 late75 awake 9 185.9 164.5 206.4 174.9 142.9 200.1 3.72e-06 0.001 0.001 False True medium adjacent pooled median late100 rebound awake 10 178.5 159.0 213.6 174.0 145.7 208.5 2.66e-07 0.000 0.002 False True medium adjacent pooled median late100 late100 awake 11 176.0 158.4 216.9 167.4 142.9 208.0 3.43e-08 0.001 0.002 False True medium adjacent pooled median late75 rebound awake 10 178.3 156.3 204.6 170.2 133.1 198.8 1.47e-07 0.000 0.000 False True medium adjacent pooled median late75 late75 awake 10 176.6 153.6 209.8 166.9 127.7 205.6 4.87e-08 0.000 0.000 False True medium adjacent pooled mean late100 rebound awake 10 186.0 166.5 210.4 181.2 157.2 211.7 3.74e-07 0.000 0.001 False True medium adjacent pooled mean late100 late100 awake 11 182.8 168.0 212.5 176.2 155.7 208.4 1.21e-07 0.001 0.001 False True medium adjacent pooled mean late75 rebound awake 10 185.6 162.9 203.1 175.5 143.8 198.2 1.65e-07 0.000 0.000 False True medium adjacent pooled mean late75 late75 awake 10 183.0 162.3 207.5 172.8 140.4 199.5 2.93e-07 0.001 0.000 False True medium mirror site median late100 rebound awake 9 180.7 163.0 216.1 176.6 146.9 215.6 2.49e-06 0.000 0.002 False True medium mirror site median late100 late100 awake 10 177.4 162.5 217.6 171.3 143.7 212.5 2.84e-07 0.001 0.001 False True medium mirror site median late75 rebound awake 9 180.4 161.0 209.6 173.0 134.4 209.8 1.65e-06 0.000 0.000 False True medium mirror site median late75 late75 awake 9 179.0 160.1 209.6 170.3 133.5 210.5 1.89e-06 0.000 0.001 False True medium mirror site mean late100 rebound awake 9 188.0 171.2 212.0 182.5 156.9 216.3 3.48e-06 0.002 0.002 False True medium mirror site mean late100 late100 awake 10 184.5 169.8 214.4 179.0 155.4 210.9 7.32e-07 0.001 0.001 False True medium mirror site mean late75 rebound awake 9 187.7 167.9 205.9 178.2 144.0 203.8 2.03e-06 0.001 0.001 False True medium mirror site mean late75 late75 awake 9 186.2 167.9 206.3 176.8 144.1 204.5 7.25e-06 0.001 0.001 False True medium mirror pooled median late100 rebound awake 9 180.7 163.0 215.8 176.5 147.4 213.6 7.49e-07 0.000 0.002 False True medium mirror pooled median late100 late100 awake 10 177.0 162.0 217.9 173.9 143.3 210.1 8.51e-08 0.001 0.001 False True medium mirror pooled median late75 rebound awake 9 180.7 160.4 209.3 172.8 135.2 205.0 3.44e-07 0.000 0.000 False True medium mirror pooled median late75 late75 awake 9 179.7 160.6 209.9 168.1 131.4 207.2 9.41e-07 0.000 0.000 False True medium mirror pooled mean late100 rebound awake 9 189.2 170.5 211.4 183.2 156.8 214.8 5.78e-07 0.000 0.000 False True medium mirror pooled mean late100 late100 awake 10 183.7 169.3 214.4 181.1 155.9 208.8 2.29e-07 0.002 0.001 False True medium mirror pooled mean late75 rebound awake 9 189.0 166.3 206.6 178.2 143.4 201.9 3.97e-07 0.000 0.000 False True medium mirror pooled mean late75 late75 awake 9 187.1 166.9 206.7 174.1 142.5 201.6 3.03e-06 0.000 0.000 False True rows where state p < 0.05 and running is earlier than quiet in both regions by the corrected test: 64 of 64 rows with all six means within tolerance: 0
Result: partially reproduced, resting on the same assumption. In all 64 readings the state effect is significant (p from 3e-08 to 3e-05) and running is earlier than quiet wakefulness in both regions by the corrected paired test (q <= 0.003), but no reading puts all six means within tolerance: the SM-TH latencies in quiet wakefulness (167 to 187 ms) are later than 156.0 +/- 7.1, and the isoflurane latencies (cortex 203 to 220 ms, SM-TH 198 to 221 ms) mostly later than 200.2 +/- 7.5 and 195.1 +/- 9.5.
rows = []
for lvl in LEVELS:
for rd in ("a", "b"):
d = []
for r in res:
for st in ("quiet", "running", "isoflurane"):
if r["n"][(lvl, st)] == 0:
continue
bp = burst_prob(r, lvl, st)
if bp is not None:
d.append({"subject": r["subject"], "depth": r["depth"], "state": st, "p": bp[rd]})
d = pd.DataFrame(d)
for setname, sub in (("a: deep", d[d.depth == "deep"]), ("b: all", d)):
w = sub.pivot_table(index="subject", columns="state", values="p", aggfunc="mean").dropna()
fr = stats.friedmanchisquare(w.quiet, w.running, w.isoflurane)
med = w.median()
rows.append({"level": lvl, "reading": rd, "set": setname, "animals": len(w),
**{s: iqr(w[s]) for s in ("quiet", "running", "isoflurane")}, "Friedman": f"Q={fr.statistic:.1f}, p={fr.pvalue:.3g}",
"holds": bool((abs(med.quiet - 0.1) <= 0.01 or abs(med.quiet - 0.095) <= 0.0095) and med.running == 0 and med.isoflurane == 0 and fr.pvalue < 0.05 and med.quiet >= med.max())})
f7h = pd.DataFrame(rows)
print(f7h.to_string(index=False))
level reading set animals quiet running isoflurane Friedman holds high a a: deep 13 0.932 [0.707-1.000] (n=13) 0.716 [0.286-1.000] (n=13) 0.100 [0.058-0.275] (n=13) Q=15.2, p=0.000509 False high a b: all 13 0.926 [0.707-1.000] (n=13) 0.661 [0.286-1.000] (n=13) 0.108 [0.075-0.275] (n=13) Q=15.2, p=0.000509 False high b a: deep 13 0.177 [0.038-0.305] (n=13) 0.121 [0.010-0.273] (n=13) 0.005 [0.002-0.018] (n=13) Q=15.8, p=0.000362 False high b b: all 13 0.177 [0.038-0.305] (n=13) 0.121 [0.007-0.251] (n=13) 0.005 [0.002-0.015] (n=13) Q=17.1, p=0.000196 False medium a a: deep 13 0.919 [0.510-0.990] (n=13) 0.486 [0.167-0.892] (n=13) 0.150 [0.058-0.258] (n=13) Q=14.6, p=0.000689 False medium a b: all 13 0.887 [0.475-0.990] (n=13) 0.486 [0.167-0.892] (n=13) 0.150 [0.033-0.258] (n=13) Q=14.6, p=0.000689 False medium b a: deep 13 0.150 [0.020-0.219] (n=13) 0.028 [0.010-0.113] (n=13) 0.006 [0.003-0.013] (n=13) Q=15.8, p=0.000362 False medium b b: all 13 0.144 [0.018-0.219] (n=13) 0.028 [0.005-0.091] (n=13) 0.005 [0.003-0.015] (n=13) Q=15.8, p=0.000362 False
Result: partially reproduced. Burst probability falls from quiet wakefulness to running to isoflurane (13 animals, Friedman p from 0.0002 to 0.0007, quiet highest in every reading), but the medians do not match: reading (b) gives 0.177, 0.121 and 0.005 at the high current and 0.150, 0.028 and 0.006 at the medium current against 0.1, 0 and 0.
Summary¶
| Claim | Outcome |
|---|---|
| fig2c-superficial-quiescence | reproduced |
| fig2c-deep-triphasic-cortex | partially reproduced |
| fig2f-thalamus-triphasic | partially reproduced |
| fig3abc-decay-with-distance, fig3d-magnitudes | fig3abc partially reproduced, fig3d blocked: too large (claar_lfp.ipynb); the spiking part integrated as |z| comes near the paper's values |
| fig4-unit-counts | not reproduced (one third of the legend's counts; units x currents match) |
| fig4ad-initial-excitation | not reproduced |
| fig4be-off-period | not reproduced |
| fig4cf-rebound | partially reproduced |
| fig4-supp1-fs-like-rs | partially reproduced |
| fig5a-thalamus-modulated | reproduced |
| fig5c-burst-probability-depth | partially reproduced |
| fig5e-early-latency | partially reproduced |
| fig5f-rebound-latency | not reproduced |
| fig6a-csd-sink, fig6-supp1-erp-deep-csd | blocked: metadata insufficient (no cortical layers) |
| fig6b-bursts-cortical-rate | not reproduced |
| fig6c-cortical-rate-late-erp | not reproduced |
| fig6-supp2-late-erp-bursts | reproduced |
| fig7e-baseline-rates | reproduced |
| fig7f-early-latency-state | reproduced (assumption) |
| fig7g-rebound-latency-state | partially reproduced (assumption) |
| fig7h-burst-probability-state | partially reproduced |
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: the current analysed is not given and the highest and middle currents are both run; units are those in the files (their quality threshold is not stated, and presence ratios go down to 0.02); stimulated cortex is the area group of the target (MO or SS) on any probe, as the files give no distance to the stimulating electrode; the pre-stimulus window and the family of the Benjamini-Hochberg correction are not given and both readings of each are run; for the state latencies of Figure 7F and 7G, responsive units are taken from all awake trials, an assumption, because per-state selection leaves 3 animals. Variants outside the claims file are shown and decide no outcome: Figure 4 with the three currents pooled (counting units x currents gives the legend's first three counts exactly and 9486 against 9363), and the spiking part of Figure 3, with the signed z of the Methods and with |z|.
What was found about the dataset: units carry CCF areas without cortical layers, so layer 1 can only be approximated
(claar_lfp.ipynb) and the layer-resolved CSD analyses of Figure 6 cannot be run from the files; waveform_duration is in ms while its description says s; the RS unit
counts are one third of the Figure 4 legend's, and counting each unit once per current gives the legend's first three counts exactly and 9486
against 9363; one superficial site has no valid trial, which brings the dandiset's
8 superficial sites with units to the paper's 7.
Runtime of this notebook:
print(f"{(time.time() - started) / 60:.1f} min")
19.4 min