Reproducing Guo et al. (2017) from dandiset 000009¶

Paper. Guo ZV, Inagaki HK, Daie K, Druckmann S, Gerfen CR, Svoboda K (2017). Maintenance of persistent activity in a frontal thalamocortical loop. Nature 545, 181-186. doi:10.1038/nature22324. The claims file (claims/000009/10.1038-nature22324.yaml) was written from the HHMI author manuscript in PubMed Central (PMC6431254): main text, Methods and the legends of Figures 1 to 6 and Extended Data Figures 1 to 10; the Supplementary Information and Supplementary Tables were not in the text read.

Dandiset. DANDI:000009, version 0.220126.1903. The paper cites no DANDI version (it names a CRCNS deposit, doi:10.6080/K03F4MH2). This is the only published version; the draft lists the same 173 assets and size, so the most recent published version is pinned.

What the dandiset holds. 137 silicon-probe sessions (ALM, thalamus, SNr) with trial tables, spike times, mean waveforms and unit positions, and 36 whole-cell recordings of ALM neurons during thalamus, M1 or contralateral ALM photoinhibition, from 31 mice. Behaviour-only sessions, the muscimol experiments, the weak photoinhibition of Fig. 5, non-behaving and M1 whole-cell recordings and the anatomy are not in it.

Questions asked and answered (questions/000009.yaml; the answers of 2026-10-20 are written into the claims file, and this notebook follows them):

  1. Unit classes. P1 (width computed on the deposited waveforms) is the Methods' rule; P2 (the files' cell_type label) stays a reading, as the paper does not say how the label was made. For the thalamic claims of Fig. 2 and 6, all units regardless of width is a further reading (P3, convention C), added here to fig2f-vmval-selectivity, fig6c-vmval-reduced, fig6b, fig6c-unmodulated, fig6d (its reading u2), vm1-photoinhibition-no-effect, fig6e and selectivity-time-course.
  2. The PV-Cre x Ai32 ALM sessions with thalamic photostimulation are not part of Fig. 3, which uses VGAT-ChR2-EYFP mice at 10 mW; they stay a variant.
  3. ALM photoinhibition is the 1.5 mW condition; trials at 0.75 or 0.79 mW are outside it, and all powers pooled is a variant.
  4. The whole-cell photostimulus onset has two readings, E (1.3 s after pole_in_time) and M (0.1 s after pole_out_time); placing it from the Vm change is not a reading. The answer assumed the files hold no laser time; they do (an OptogeneticSeries at 20 kHz, found after the first verification), so the onset of that trace is shown as a third reading, L, and a new question asks whether it should be used (question 7 below). The outcomes of the four whole-cell claims are the same under M and under L.
  5. The paper does not say which deposited condition is vM1; ALM is compared at 1.5 mW, matched power is a variant. The claim stays blocked on the site.
  6. Selectivity time course: correct control trials (t1) and all correct trials (t2) are both readings.
  7. Asked after the first verification, not yet answered: should the whole-cell photostimulus onset be taken from the deposited laser trace (reading L)? Under L the onset latency of wc-thalamus-hyperpolarization can be measured; no outcome depends on the answer.

Changes after the first verification: within a trial the extracellular files store spikes only to about 4.8 s after pole onset, so a window that ends later is now counted as missing for that trial (it had been counted with the spikes it held); SNr reading P2 is now the 'Narrow width spiking' label (146 units), as convention C says; the whole-cell laser trace is read; and checks were added for the onset rule, the VGAT delay lengths and the spike-threshold kink.

Changes after the second verification: no outcome changed in that round. The verifier found that nine claims were given partially reproduced under criteria with no partial clause; a section before the Summary counts the readings that meet each whole criterion (none does), and a change to not reproduced was proposed for each. Some sentences were corrected.

Changes after the third verification: the verifier agreed with all nine proposed changes, so alm-unit-classes, fig2e-alm-selectivity, thalamus-unit-classes, fig2f-vmval-selectivity, fig3f-thalamus-silenced, wc-thalamus-hyperpolarization, wc-m1-small-effect, fig6d-localized and snr-photoinhibition are now not reproduced.

Claim Tested here
task-performance tested
fig1c-alm-photoinhibition-bias tested (recording sessions)
fig1d-thalamus-photoinhibition-bias blocked: data missing
gad2-thalamus-reduction blocked: metadata insufficient
vgat-thalamus-reduction tested
muscimol-vmval-bias blocked: data missing
alm-unit-classes tested
fig2e-alm-selectivity tested
fig2e-alm-contra-ipsi-balance tested
thalamus-unit-classes tested
fig2f-vmval-selectivity tested
fig3-alm-collapse tested
fig3d-all-layers tested; blocked by its criterion (methods underspecified)
fig3b-selectivity-types-equally-inhibited tested; blocked by its criterion (methods underspecified)
fig3f-thalamus-silenced tested
fig3-onset-latencies tested
wc-near-threshold tested
wc-thalamus-hyperpolarization tested (onset readings E, M and L; the onset latency shown under L, not judged)
wc-loss-of-excitation blocked: data missing
wc-m1-small-effect tested (onset readings E, M and L)
wc-contra-alm-small-effect tested (onset readings E, M and L)
thalamus-stronger-than-cortex tested (onset readings E, M and L)
indirect-pathway-too-slow blocked: data missing
conduction-delay blocked: data missing
latency-model-t3 blocked: methods underspecified
fig5-weak-photoinhibition-rates blocked: data missing
fig5c-selectivity-reduced blocked: data missing
network-models blocked: methods underspecified
fig6c-vmval-reduced tested
fig6b-selectivity-types-equally-inhibited tested; blocked by its criterion (methods underspecified)
fig6c-unmodulated-less-selective tested
fig6d-localized tested
vm1-photoinhibition-no-effect run; blocked: metadata insufficient (site not named)
fig6e-onset-latencies tested
snr-photoinhibition tested
snr-unit-properties run in part; blocked: data missing (the selectivity part is tested)
anatomy-reciprocal-thalamus blocked: data missing
selectivity-time-course tested
alm-gabaergic-no-thalamic-projection blocked: data missing
In [1]:
# LOAD-CELL
import time
import warnings
from collections import Counter

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from scipy import stats

import loop

pd.set_option("display.width", 220)
pd.set_option("display.max_columns", 40)
pd.set_option("display.max_rows", 300)
warnings.filterwarnings("ignore", category=RuntimeWarning)

started = time.time()
assets = loop.list_assets()
sessions = loop.load_all_ecephys(assets)
cells = loop.load_all_wholecell(assets)
units = loop.unit_table(sessions)
units["vmval_d"] = loop.vmval_distance(units)
print(f"dandiset {loop.DANDISET_ID} version {loop.DANDISET_VERSION}: {len(assets)} assets; loaded "
      f"{len(sessions)} extracellular sessions ({len(units)} units) and {len(cells)} whole-cell recordings "
      f"in {time.time() - started:.0f} s")
dandiset 000009 version 0.220126.1903: 173 assets; loaded 137 extracellular sessions (1936 units) and 36 whole-cell recordings in 404 s

Data check¶

Each check of the metadata against the values is stated under its output.

In [2]:
info = loop.version_info()
meta = info["metadata"]
summ = meta["assetsSummary"]
print("Version", info["version"], "status", info["status"], "created", info["created"][:10])
print("Archive summary: subjects", summ["numberOfSubjects"], "| files", summ["numberOfFiles"],
      "| variables", summ.get("variableMeasured"))
print("Related resources:", [(r.get("identifier"), r.get("relation")) for r in meta.get("relatedResource", [])])
kind = np.where(assets.path.str.contains("icephys"), "whole-cell", "extracellular")
print("\nFiles by kind:", Counter(kind))
print("Distinct subject folders:", assets.path.str.split("/").str[0].nunique(),
      "| extracellular:", assets.path[kind == "extracellular"].str.split("/").str[0].nunique(),
      "| whole-cell:", assets.path[kind == "whole-cell"].str.split("/").str[0].nunique())
print("Size: extracellular", round(assets["size"][kind == "extracellular"].sum() / 1e9, 2), "GB; whole-cell",
      round(assets["size"][kind == "whole-cell"].sum() / 1e9, 2), "GB")
Version 0.220126.1903 status Valid created 2022-01-26
Archive summary: subjects 31 | files 173 | variables ['Units', 'ElectrodeGroup', 'ProcessingModule', 'BehavioralTimeSeries', 'CurrentClampStimulusSeries', 'OptogeneticSeries']
Related resources: [('doi:10.1038/nature22324', 'dcite:IsDescribedBy')]

Files by kind: Counter({np.str_('extracellular'): 137, np.str_('whole-cell'): 36})
Distinct subject folders: 31 | extracellular: 24 | whole-cell: 7
Size: extracellular 0.21 GB; whole-cell 12.71 GB
In [3]:
sess = pd.DataFrame([{**{k: s["meta"][k] for k in ("subject", "genotype", "region", "ogen_site")},
                      "units": len(s["units"]), "task_trials": len(s["trials"]), "rows": s["meta"]["n_rows"]}
                     for s in sessions])
sess["ogen_site"] = sess.ogen_site.fillna("none")
print("Extracellular sessions by genotype, recorded region and photostimulus site:")
print(sess.groupby(["genotype", "region", "ogen_site"]).agg(sessions=("subject", "size"), mice=("subject", "nunique"),
                                                            units=("units", "sum"), task_trials=("task_trials", "sum")).to_string())
print("\nBy region (paper, Methods: ALM 1214 units in 57 sessions, 10 mice; thalamus 790 units in 73 sessions, 11 mice;"
      " SNr 227 units in 23 sessions):")
print(sess.groupby("region").agg(sessions=("subject", "size"), mice=("subject", "nunique"), units=("units", "sum")).to_string())
lab = Counter()
for s in sessions:
    m = s["meta"]
    for k, v in s["trials"].stim.value_counts().items():
        lab[(m["genotype"], m["region"], m["ogen_site"] or "none", k)] += v
print("\nTask trials by photostimulus label (<site>:<period>:<power mW>):")
print(pd.Series(lab).rename_axis(["genotype", "region", "site", "label"]).to_frame("trials").to_string())
wc = pd.DataFrame([{"subject": c["meta"]["subject"], "genotype": c["meta"]["genotype"], "cell": c["meta"]["cell"],
                    "description": c["meta"]["description"], "site": c["meta"]["ogen_site"], "trials": len(c["trials"]),
                    "pi_trials": int(c["trials"].pi.sum())} for c in cells])
print("\nWhole-cell recordings:")
print(wc.groupby(["description", "genotype", "site"]).agg(cells=("cell", "size"), mice=("subject", "nunique"),
                                                         trials=("trials", "sum"), pi_trials=("pi_trials", "sum")).to_string())
Extracellular sessions by genotype, recorded region and photostimulus site:
                                     sessions  mice  units  task_trials
genotype         region   ogen_site                                    
Ai32 x PV-Cre    ALM      ALM               8     3    191         1716
                          Thalamus         21     4    434         4675
                 SNr      ALM              18     3    181         5080
                 Thalamus ALM              40     7    451        11141
Ai35D x GAD2_Cre Thalamus none              9     2     84         2993
C57BL6           Thalamus none             12     2    104         2192
VGAT-ChR2-EYFP   ALM      Thalamus         18     3    341         4112
                 Thalamus Thalamus         11     2    150         2361

By region (paper, Methods: ALM 1214 units in 57 sessions, 10 mice; thalamus 790 units in 73 sessions, 11 mice; SNr 227 units in 23 sessions):
          sessions  mice  units
region                         
ALM             47    10    966
SNr             18     3    181
Thalamus        72    13    789

Task trials by photostimulus label (<site>:<period>:<power mW>):
                                                         trials
genotype         region   site     label                       
Ai35D x GAD2_Cre Thalamus none     none                    2993
Ai32 x PV-Cre    Thalamus ALM      none                    8708
                                   ALM:delay:1.5           2045
                                   ALM:delay:0.79           261
C57BL6           Thalamus none     none                    2192
Ai32 x PV-Cre    SNr      ALM      none                    3942
                                   ALM:delay:1.5           1137
                                   ALM:sample:1.5             1
                 ALM      ALM      none                    1336
                                   ALM:delay:1.5            188
                                   ALM:delay:0.75           192
                          Thalamus none                    3649
                                   Thalamus:delay:10        531
                                   Thalamus:delay:22.5      380
                 Thalamus ALM      site0.5:delay:0.79       127
                 ALM      Thalamus Thalamus:delay:45        115
VGAT-ChR2-EYFP   Thalamus Thalamus none                    1841
                                   Thalamus:delay:2.23      465
                                   Thalamus:sample:2.23      55
                 ALM      Thalamus none                    3221
                                   Thalamus:delay:10        891

Whole-cell recordings:
                                                                                     cells  mice  trials  pi_trials
description                                                genotype       site                                     
ALM whole cell recording during M1 photoinhibition         Ai32 x PV-Cre  left-M1       11     4     913        387
ALM whole cell recording during contra ALM photoinhibition Ai32 x PV-Cre  right-ALM      9     3     618        271
ALM whole cell recording during thalamus photoinhibition   VGAT-ChR2-EYFP left-VM       16     3    1122        395

The dandiset holds 137 extracellular sessions and 36 whole-cell recordings from 31 mice, as the archive says. ALM: 47 sessions from 10 mice with 966 units, against 57 sessions and 1214 units in the paper (10 mice). Thalamus: 72 sessions with 789 units, against 73 and 790. SNr: 18 sessions with 181 units, against 23 sessions and 227 units, of which the paper keeps 181 as putative GABAergic. The whole-cell recordings are 16 ALM cells during thalamus photoinhibition (VGAT-ChR2-EYFP), 11 during M1 and 9 during contralateral ALM photoinhibition (PV-Cre x Ai32), the n of Fig. 3g and 4. Not in the dandiset: behaviour-only sessions, the muscimol experiments, the weak (0.5 mW) thalamus photoinhibition of Fig. 5, non-behaving whole-cell recordings (Extended Data Fig. 5c-h, 6c), M1 whole-cell recordings, and the anatomy.

What the files hold that the paper does not describe, or describes differently:

  • The 9 thalamic sessions of two Ai35D x GAD2_Cre mice carry no photostimulus in any trial (every period 'N/A', power 0), yet their 84 units equal the 26 + 41 + 17 Gad2-IRES-Cre optrode units of Extended Data Fig. 2c. The paper's Gad2 mice had ChR2 injected in TRN; Ai35D is an Arch line. 12 thalamic sessions of two C57BL6 mice (104 units) have no photostimulus either.
  • 21 ALM sessions of four Ai32 x PV-Cre mice have photostimulation of the thalamus at 10, 22.5 and 45 mW. The paper describes ALM recordings during thalamus photoinhibition in VGAT-ChR2-EYFP mice only (Fig. 3); the 18 VGAT ALM sessions here use 10 mW.
  • The VGAT thalamic sessions record 2.23 mW where the paper gives 10 mW (Extended Data Fig. 2d), and one of them was photostimulated in the sample epoch.
  • In thalamic sessions of mouse anm00264943, ALM photoinhibition at 0.79 and 1.5 mW is interleaved with photostimulation at galvo position (0.5, 0.5) mm, which is not named. The paper interleaves ALM and vM1 photoinhibition in 3 mice (Extended Data Fig. 8f, g).
  • Trials labelled 'delay' with power 0 (a few per session) are kept apart and used in no analysis.
In [4]:
# Recordings deposited twice: compare trial start times and unit spike counts between every pair.
sig = []
for i, s in enumerate(sessions):
    t = s["trials"]
    sig.append((i, s["meta"]["subject"], tuple(np.round(t.start_time.values[:20], 3)),
                set(zip(s["units"].n_spikes, np.round(s["units"].first_spike, 4)))))
pairs = []
for a in range(len(sig)):
    for b in range(a + 1, len(sig)):
        same_trials = sig[a][2] == sig[b][2]
        shared_units = len(sig[a][3] & sig[b][3])
        if same_trials or shared_units:
            pairs.append((sessions[a]["meta"]["path"], sessions[b]["meta"]["path"], same_trials, shared_units))
print("Extracellular session pairs sharing trial start times or units (spike count and first spike):", pairs if pairs else "none")
wsig = [(c["meta"]["path"], c["meta"]["n_samples"], c["meta"]["n_spikes"], round(c["meta"]["vm_range"][0], 3)) for c in cells]
dup = [(a[0], b[0]) for i, a in enumerate(wsig) for b in wsig[i + 1:] if a[1:] == b[1:]]
print("Whole-cell pairs with equal length, spike count and minimum Vm:", dup if dup else "none")
starts = pd.DataFrame([(c["meta"]["subject"], c["meta"]["cell"], c["trials"].start_time.min(), c["trials"].stop_time.max())
                       for c in cells], columns=["subject", "cell", "first", "last"])
print("Whole-cell cells per mouse:", starts.groupby("subject").cell.apply(list).to_dict())
Extracellular session pairs sharing trial start times or units (spike count and first spike): none
Whole-cell pairs with equal length, spike count and minimum Vm: none
Whole-cell cells per mouse: {'anm300476': ['cell_20_1', 'cell_21_1', 'cell_22_1', 'cell_23_1', 'cell_25_1', 'cell_29_1'], 'anm322808': ['cell_55_1', 'cell_56_1', 'cell_57_1', 'cell_58_1', 'cell_59_1', 'cell_60_1'], 'anm323951': ['cell_44_1', 'cell_45_1', 'cell_46_1', 'cell_45_2', 'cell_46_2'], 'anm323952': ['cell_40_2', 'cell_39_1', 'cell_40_1'], 'anm323953': ['cell_30_2', 'cell_30_1', 'cell_31_1', 'cell_32_1', 'cell_34_1', 'cell_35_1'], 'anm324791': ['cell_47_1', 'cell_49_1', 'cell_50_1', 'cell_51_1', 'cell_52_1', 'cell_53_1'], 'anm324792': ['cell_64_1', 'cell_65_1', 'cell_66_1', 'cell_73_2']}

No session or whole-cell recording is deposited twice: no two sessions share trial start times or any unit. Each whole-cell file holds one cell; cells of one mouse are counted as separate cells, as in the paper. A unit is never treated as the same across sessions here.

In [5]:
print("Mean waveform length (samples) and sampling rate by region:")
print(units.groupby("region").agg(wf_len=("wf_len", "unique"), rate=("sampling_rate", "unique")).to_string())
print("\nTrough-to-peak width (ms) of the deposited mean waveform, by region and the file's cell_type label:")
print(units.groupby(["region", "cell_type"]).width_ms.describe()[["count", "min", "25%", "50%", "75%", "max"]].round(2).to_string())
print("\nFraction of units whose waveform peak (after the trough) is its last sample, by region and label:")
print(units.groupby(["region", "cell_type"]).peak_last.mean().round(3).to_string())
print("\nUnit coordinates (mm) by region: unit_x (ML), unit_y (DV), unit_z (AP)")
print(units.groupby("region")[["ml", "dv", "ap"]].agg(["min", "max"]).round(2).to_string())
print("\nSNr unit AP (mm) by mouse:", units[units.region == "SNr"].groupby("subject").ap.agg(["min", "max"]).round(2).to_dict("index"))
eg = Counter((s["meta"]["region"], s["meta"]["eg_location"].get("coordinate_ap"), s["meta"]["eg_location"].get("coordinate_ml"),
              s["meta"]["eg_location"].get("coordinate_dv")) for s in sessions)
print("\nElectrode group locations (region, AP, ML, DV):", dict(eg))
og = Counter((k, v.get("coordinate_ap"), v.get("coordinate_ml"), v.get("coordinate_dv")) for s in sessions for k, v in s["meta"]["ogen"].items())
print("Photostimulus sites (name, AP, ML, DV):", dict(og))
print("Units with unsorted spike times:", sum(s["meta"]["unsorted_units"] for s in sessions))
print("\nFraction of its session's task trials a unit spans (first to last trial holding its spikes), by region:")
print(units.groupby("region").trial_coverage.describe()[["min", "25%", "50%", "75%", "max"]].round(3).to_string())
print("Units spanning less than 90% of their session's trials:", int((units.trial_coverage < 0.9).sum()), "of", len(units))
mid = np.array([np.nansum(s["counts"]["mid"]) for s in sessions]) / 2.5
late = np.array([np.nansum(s["counts"]["late"]) for s in sessions]) / 2.5
print("Spikes per s summed over units and trials, 2.0 to 4.5 s after pole onset:", int(mid.sum()), "| 5.5 to 8.0 s:", int(late.sum()),
      "| sessions with any spike 5.5 to 8.0 s:", int((late > 0).sum()), "of", len(sessions))
Mean waveform length (samples) and sampling rate by region:
                wf_len     rate
region                         
ALM       [29, 38, 37]  [25000]
SNr               [29]  [25000]
Thalamus      [29, 37]  [25000]

Trough-to-peak width (ms) of the deposited mean waveform, by region and the file's cell_type label:
                               count   min   25%   50%   75%   max
region   cell_type                                                
ALM      Cannot be determined   35.0  0.32  0.40  0.44  0.48  0.56
         Narrow width spiking  121.0  0.12  0.24  0.28  0.28  0.32
         Wide width spiking    810.0  0.44  0.60  0.68  0.72  0.72
SNr      Cannot be determined   22.0  0.32  0.32  0.32  0.35  0.36
         Narrow width spiking  146.0  0.08  0.16  0.20  0.24  0.28
         Wide width spiking     13.0  0.44  0.48  0.48  0.48  0.48
Thalamus Cannot be determined   62.0  0.28  0.32  0.32  0.40  0.44
         Narrow width spiking   45.0  0.08  0.16  0.24  0.24  0.32
         Wide width spiking    682.0  0.36  0.44  0.44  0.48  0.68

Fraction of units whose waveform peak (after the trough) is its last sample, by region and label:
region    cell_type           
ALM       Cannot be determined    0.000
          Narrow width spiking    0.000
          Wide width spiking      0.777
SNr       Cannot be determined    0.000
          Narrow width spiking    0.000
          Wide width spiking      0.000
Thalamus  Cannot be determined    0.000
          Narrow width spiking    0.000
          Wide width spiking      0.085

Unit coordinates (mm) by region: unit_x (ML), unit_y (DV), unit_z (AP)
            ml          dv         ap      
           min   max   min   max  min   max
region                                     
ALM       0.90  1.90 -1.21 -0.07  2.5  3.00
SNr       0.52  1.38 -4.84 -3.28 -4.2 -1.56
Thalamus  0.35  2.06 -4.79 -2.71 -2.1 -1.23

SNr unit AP (mm) by mouse: {'anm00261334': {'min': -4.02, 'max': -3.86}, 'anm00261335': {'min': -4.2, 'max': -3.6}, 'anm00261336': {'min': -1.56, 'max': -1.56}}

Electrode group locations (region, AP, ML, DV): {('Thalamus', '2.50', '-1.50', '0.00'): 72, ('SNr', '2.50', '-1.50', '0.00'): 18, ('ALM', '2.50', '-1.50', '0.00'): 47}
Photostimulus sites (name, AP, ML, DV): {('left-ALM', '2.50', '-1.50', '0.00'): 66, ('left-Thalamus', '-1.50', '-0.90', '-4.10'): 50}
Units with unsorted spike times: 0

Fraction of its session's task trials a unit spans (first to last trial holding its spikes), by region:
            min    25%    50%    75%  max
region                                   
ALM       0.119  0.474  0.698  0.924  1.0
SNr       0.176  0.641  0.888  0.992  1.0
Thalamus  0.000  0.477  0.715  0.926  1.0
Units spanning less than 90% of their session's trials: 1358 of 1936
Spikes per s summed over units and trials, 2.0 to 4.5 s after pole onset: 4094260 | 5.5 to 8.0 s: 57086 | sessions with any spike 5.5 to 8.0 s: 75 of 137

The deposited mean waveforms are short: 29 samples at 25 kHz (1.16 ms) in thalamus and SNr, and the trough sits at sample 15 to 19, so a trough-to-peak interval longer than 0.36 to 0.52 ms cannot be measured in many units. The peak after the trough is the last sample in 78% of ALM units labelled 'Wide width spiking'. Widths computed from these waveforms are therefore lower bounds for wide units, and the classes the Methods define by width (> 0.6 ms in ALM, > 0.5 ms in thalamus) cannot be recovered from them. The files' own cell_type labels ('Wide width spiking', 'Narrow width spiking', 'Cannot be determined') separate the units cleanly by computed width (narrow up to 0.32 ms in ALM, wide from 0.44 ms) and are shown below as the second reading (P2) of every unit class; reading P1 applies the Methods' thresholds to the computed widths.

Coordinates: unit_x is medio-lateral (positive), unit_y dorso-ventral (negative, mm), unit_z antero-posterior; thalamic units lie between AP -1.2 and -2.1 mm, inside the "bregma -1 to -2 mm" of the Methods, and ALM units at AP 2.5 to 3.0. Two inconsistencies: every electrode group, also in thalamus and SNr, carries the ALM coordinates (AP 2.5, ML -1.5, DV 0); and the SNr units of mouse anm00261336 are at AP -1.56 mm, where SNr is not (the other two SNr mice are at AP -3.6 to -4.2). Photostimulus sites give ML negative for the left hemisphere, units give it positive. The thalamic fibre site is the same nominal coordinate (AP -1.5, ML 0.9, DV -4.1) in all 29 sessions.

Spikes are stored only in part of each trial and for part of each session. Within a trial, spikes run from the trial start (0.57 s before pole onset) to about 4.8 s after pole onset: the summed rate 5.5 to 8 s after pole onset is 1.4% of that 2 to 4.5 s after it, although trials last about 9 s. The end is fixed to pole onset, not to the go cue (next table), so in trials with a long delay the response epoch, and in a few the delay epoch, runs past the stored spikes. Each trial's stored span is taken to end at the last spike of any unit of the session in it, and a window that ends later is counted as missing for that trial. Across a session, most units hold spikes over only some of its trials (median 70%), and the files give no observation interval per unit. A unit's trials are therefore taken to run from the trial holding its first spike to the trial holding its last; trials outside count as missing, not as zero spikes. This is a standard choice recorded as a deviation.

In [6]:
tr = pd.concat([s["trials"].assign(subject=s["meta"]["subject"], region=s["meta"]["region"]) for s in sessions], ignore_index=True)
rows_all = Counter()
for s in sessions:
    rows_all.update(s["meta"]["outcomes_all"])
print("Extracellular trial rows by outcome:", dict(rows_all), "| rows without pole times (dropped):",
      sum(s["meta"]["n_rows"] for s in sessions) - len(tr))
print("Task trials by type and outcome:")
print(pd.crosstab(tr["type"], tr.response).to_string())
print("\npole_out - pole_in (s), quantiles 1/50/99%:", np.round(np.nanpercentile(tr.pole_out_time - tr.pole_in_time, [1, 50, 99]), 3))
print("cue - pole_in (s), quantiles 1/50/99%:", np.round(np.nanpercentile(tr.cue - tr.pole_in_time, [1, 50, 99]), 3))
print("Delay (cue - pole_in - 1.3 s) within 0.05 s of 1.3 s:", round(float(np.mean(np.abs(tr.delay_s - 1.3) < 0.05)), 3),
      "| of 1.2 s:", round(float(np.mean(np.abs(tr.delay_s - 1.2) < 0.05)), 3))
print("Trial duration (stop - start, s), quantiles 1/50/99%:", np.round(np.percentile(tr.stop_time - tr.start_time, [1, 50, 99]), 2))
print("Go cue duration (s):", np.round(np.nanpercentile(tr.cue_end_time - tr.cue_start_time, [1, 50, 99]), 3))
tr["stored_from_cue"] = tr.stored_end - tr.cue
tr["delay_bin"] = pd.cut(tr.delay_s, [0, 1.35, 2.0, 3.0, 10.0])
print("\nEnd of the stored spikes in each trial (last spike of any unit of the session), by delay length (s):")
print(tr.groupby("delay_bin", observed=True).agg(trials=("stored_end", "size"),
                                                 after_pole_q10=("stored_from_pole", lambda x: x.quantile(0.1)),
                                                 after_pole_median=("stored_from_pole", "median"),
                                                 after_pole_q90=("stored_from_pole", lambda x: x.quantile(0.9)),
                                                 after_cue_median=("stored_from_cue", "median")).round(2).to_string())
lg = tr[tr.delay_s > 2.0]
print("Trials with delay > 2 s:", len(lg), "| histogram of the stored end after the go cue (s), 0.5 s bins:",
      pd.cut(lg.stored_from_cue, np.arange(-3.5, 4.01, 0.5)).value_counts().sort_index().to_dict())
for nm, end in (("delay epoch", tr.cue), ("R1", tr.cue + loop.RESP_S["R1"]), ("R2", tr.cue + loop.RESP_S["R2"]),
                ("20 to 120 ms window", tr.on + loop.PW[1])):
    cut = ~(end <= tr.stored_end)
    print(f"Task trials whose {nm} ends after the stored spikes (counted as missing):", int(cut.sum()), f"({100 * cut.mean():.1f}%)",
          "| of trials with a 1.3 s delay:", int(cut[np.abs(tr.delay_s - 1.3) < 0.05].sum()))
kp = tr.response.isin(loop.KEEP)
print("Correct and incorrect trials whose R1 ends after the stored spikes, by region:",
      {g: f"{int((~(d.cue + loop.RESP_S['R1'] <= d.stored_end)).sum())} of {len(d)}" for g, d in tr[kp].groupby("region")},
      "| by region, trials with a delay above 1.35 s:", {g: int((d.delay_s > 1.35).sum()) for g, d in tr[kp].groupby("region")})
wtr = pd.concat([c["trials"].assign(cell=c["meta"]["cell"]) for c in cells], ignore_index=True)
print("\nWhole-cell trials by type and outcome:")
print(pd.crosstab(wtr["type"], wtr.response).to_string())
print("Whole-cell pole_out - pole_in (s):", np.round(np.nanpercentile(wtr.pole_out_time - wtr.pole_in_time, [1, 50, 99]), 3),
      "| cue - pole_in:", np.round(np.nanpercentile(wtr.cue - wtr.pole_in_time, [1, 50, 99]), 3))
bad = wtr[~wtr.order_ok]
print("Whole-cell rows whose pole onset is outside [start_time, stop_time]:", len(bad), "in cells", dict(Counter(bad.cell)))
print(bad[["cell", "id", "start_time", "stop_time", "pole_in_time"]].head(3).to_string(index=False))
print("Whole-cell photostimulus columns: periods", set(wtr.photo_stim_period), "powers", set(map(str, wtr.photo_stim_power)),
      "| stim_present fraction", round(float(wtr.pi.mean()), 3))
Extracellular trial rows by outcome: {'correct': 19315, 'early lick': 6457, 'incorrect': 8246, 'N/A': 5375, 'no response': 246} | rows without pole times (dropped): 5369
Task trials by type and outcome:
response        N/A  correct  early lick  incorrect  no response
type                                                            
lick left         0     9684        3311       4337          120
lick right        0     9631        3146       3909          126
non-performing    6        0           0          0            0

pole_out - pole_in (s), quantiles 1/50/99%: [1.3  1.3  3.03]
cue - pole_in (s), quantiles 1/50/99%: [2.6  2.6  5.69]
Delay (cue - pole_in - 1.3 s) within 0.05 s of 1.3 s: 0.814 | of 1.2 s: 0.0
Trial duration (stop - start, s), quantiles 1/50/99%: [ 7.82  8.98 13.98]
Go cue duration (s): [0.1 0.1 0.1]

End of the stored spikes in each trial (last spike of any unit of the session), by delay length (s):
             trials  after_pole_q10  after_pole_median  after_pole_q90  after_cue_median
delay_bin                                                                               
(0.0, 1.35]   27914            4.73               4.84            8.35              2.24
(1.35, 2.0]    2314            4.72               4.83            8.05              1.98
(2.0, 3.0]     3007            4.73               4.83            9.07              1.16
(3.0, 10.0]    1005            4.72               4.81            4.91             -0.20
Trials with delay > 2 s: 4036 | histogram of the stored end after the go cue (s), 0.5 s bins: {Interval(-3.5, -3.0, closed='right'): 12, Interval(-3.0, -2.5, closed='right'): 17, Interval(-2.5, -2.0, closed='right'): 39, Interval(-2.0, -1.5, closed='right'): 68, Interval(-1.5, -1.0, closed='right'): 84, Interval(-1.0, -0.5, closed='right'): 132, Interval(-0.5, 0.0, closed='right'): 213, Interval(0.0, 0.5, closed='right'): 315, Interval(0.5, 1.0, closed='right'): 788, Interval(1.0, 1.5, closed='right'): 1653, Interval(1.5, 2.0, closed='right'): 71, Interval(2.0, 2.5, closed='right'): 0, Interval(2.5, 3.0, closed='right'): 0, Interval(3.0, 3.5, closed='right'): 0, Interval(3.5, 4.0, closed='right'): 0}
Task trials whose delay epoch ends after the stored spikes (counted as missing): 1142 (3.3%) | of trials with a 1.3 s delay: 406
Task trials whose R1 ends after the stored spikes (counted as missing): 3439 (10.0%) | of trials with a 1.3 s delay: 421
Task trials whose R2 ends after the stored spikes (counted as missing): 3980 (11.6%) | of trials with a 1.3 s delay: 432
Task trials whose 20 to 120 ms window ends after the stored spikes (counted as missing): 526 (1.5%) | of trials with a 1.3 s delay: 404
Correct and incorrect trials whose R1 ends after the stored spikes, by region:
 {'ALM': '221 of 8991', 'SNr': '19 of 3573', 'Thalamus': '173 of 14997'} | by region, trials with a delay above 1.35 s: {'ALM': 0, 'SNr': 0, 'Thalamus': 0}

Whole-cell trials by type and outcome:
response        correct  early lick  incorrect  no response
type                                                       
lick left           977           0        188            0
lick right          847           0        344            0
non-performing        0         256          0           41
Whole-cell pole_out - pole_in (s): [1.4   1.401 2.301] | cue - pole_in: [2.6   2.601 3.973]
Whole-cell rows whose pole onset is outside [start_time, stop_time]: 85 in cells {'cell_21_1': 85}
     cell  id  start_time  stop_time  pole_in_time
cell_21_1  94    774.0480   781.9250       12.0164
cell_21_1 264     11.4447    21.8488       22.4208
cell_21_1 265     21.8488    30.0682       30.6402
Whole-cell photostimulus columns: periods {''} powers {''} | stim_present fraction 0.397

Trial types are 'lick left', 'lick right' and 'non-performing'; contra trials are taken as 'lick right' (left hemisphere, Fig. 1a). 5375 extracellular rows have no outcome ('N/A', type 'non-performing'); 5369 of them have no pole times and are dropped, and the other 6 enter no analysis. In the extracellular files the delay (go cue minus 1.3 s after pole onset) is 1.3 s in 81% of trials and never 1.2 s; the rest are longer (up to 4.4 s at the 99th percentile). pole_out_time is 1.3 s after pole_in_time. Trials last about 9 s. In the whole-cell files pole_out_time is 1.4 s after pole_in_time and the go cue 2.6 s after it. One whole-cell trial table is not in time order and has a row whose start time (774 s) does not contain its pole onset (12 s). The whole-cell trial tables leave every photostimulus column empty; stim_present marks 30 to 50% of trials, the "25-50%" of the Methods for Fig. 3g and 4, and is read as the photostimulus flag (its effect is shown below).

The end of the stored spikes is fixed to pole onset: its median is 4.81 to 4.84 s after pole onset whatever the delay, so it falls 2.2 s after the go cue in trials with a 1.3 s delay and before the go cue in trials with a delay above 3 s (table). Before this correction, such windows were counted with the spikes they held, which biased their counts low. Every correct or incorrect trial has a 1.3 s delay; the longer delays occur only in lick-early and no-response trials, which no analysis uses. The correction therefore touches only the kept trials whose stored spikes end early: 221 of 8991 in ALM, 173 of 14997 in thalamus and 19 of 3573 in SNr for R1.

In [7]:
# Clock check, extracellular: the photostimulus effect must start at the onset the trial table gives
# (1.3 s after pole onset), and trial types must be decodable with true but not shifted labels.
t_ms = loop.psth_time_ms()
checks = [("VGAT thalamus, thalamus photostim.", (units.genotype == "VGAT-ChR2-EYFP") & (units.region == "Thalamus"), ["Thalamus:delay:2.23"]),
          ("VGAT ALM, thalamus photostim.", (units.genotype == "VGAT-ChR2-EYFP") & (units.region == "ALM"), ["Thalamus:delay:10"]),
          ("PV ALM, thalamus photostim. 10 mW", (units.genotype == "Ai32 x PV-Cre") & (units.region == "ALM") & (units.ogen_site == "Thalamus"), ["Thalamus:delay:10"]),
          ("PV thalamus, ALM photoinh. 1.5 mW", (units.genotype == "Ai32 x PV-Cre") & (units.region == "Thalamus"), ["ALM:delay:1.5"]),
          ("PV SNr, ALM photoinh. 1.5 mW", units.region == "SNr", ["ALM:delay:1.5"]),
          ("PV ALM, ALM photoinh. 1.5 mW", (units.genotype == "Ai32 x PV-Cre") & (units.region == "ALM") & (units.ogen_site == "ALM"), ["ALM:delay:1.5"])]
rows = []
for name, sel, st in checks:
    c, p = loop.population_psth(sessions, units[sel], st)
    mc, mp = np.nanmean(c, 0), np.nanmean(p, 0)
    row = {"group": name, "units": int(sel.sum())}
    for lo in (-50, -20, -10, 0, 5, 10, 15, 20, 30, 50, 100):
        k = (t_ms >= lo) & (t_ms < lo + 5 if lo >= 0 else t_ms < lo + 10 if lo == -20 or lo == -10 else t_ms < lo + 30)
        row[f"{lo}"] = round(mp[k].mean() / mc[k].mean(), 2)
    rows.append(row)
print("Population rate under photostimulus / control, in windows starting at the given ms after the onset"
      " (5 ms windows from 0 on; -50 is -50 to -20, -20 and -10 are 10 ms):")
print(pd.DataFrame(rows).to_string(index=False))

dec = []
for i, s in enumerate(sessions):
    t = s["trials"]
    m = (t.response == "correct").values & (t.stim == "none").values
    y = t.contra.values[m]
    y_shift = np.roll(t.contra.values, 1)[m]
    c = s["counts"]["delay"][:, m]
    true = np.mean([loop.ttest(u[y], u[~y], True) < 0.05 for u in c])
    shift = np.mean([loop.ttest(u[y_shift], u[~y_shift], True) < 0.05 for u in c])
    dec.append((s["meta"]["region"], true, shift))
dec = pd.DataFrame(dec, columns=["region", "true", "shifted"])
dec["no_photostim"] = [s["meta"]["ogen_site"] is None for s in sessions]
print("\nFraction of units with delay-epoch contra/ipsi difference (t-test p < 0.05, correct control trials), per session:")
print(dec.groupby("region").agg(sessions=("true", "size"), true_median=("true", "median"), shifted_median=("shifted", "median"),
                                true_gt_shifted=("true", lambda x: int((x > dec.loc[x.index, "shifted"]).sum()))).round(3).to_string())
d0 = dec[dec.no_photostim]
print("Sessions without photostimulus (Gad2, C57BL6):", len(d0), "| true > shifted in", int((d0.true > d0.shifted).sum()),
      "| pooled fraction true", round(d0.true.mean(), 3), "shifted", round(d0.shifted.mean(), 3))
Population rate under photostimulus / control, in windows starting at the given ms after the onset (5 ms windows from 0 on; -50 is -50 to -20, -20 and -10 are 10 ms):
                             group  units  -50  -20  -10    0    5   10   15   20   30   50  100
VGAT thalamus, thalamus photostim.    150 1.02 0.98 1.02 0.68 0.33 0.24 0.23 0.19 0.21 0.18 0.20
     VGAT ALM, thalamus photostim.    341 0.99 0.90 1.00 0.93 0.86 0.38 0.15 0.08 0.03 0.01 0.00
 PV ALM, thalamus photostim. 10 mW    434 1.02 0.86 0.95 1.22 0.77 0.82 0.81 0.65 0.17 0.15 0.27
 PV thalamus, ALM photoinh. 1.5 mW    451 0.98 1.03 0.93 0.95 1.00 1.00 0.92 0.68 0.54 0.47 0.61
      PV SNr, ALM photoinh. 1.5 mW    181 1.03 1.01 1.03 1.10 1.03 0.95 0.97 0.97 0.96 0.98 0.93
      PV ALM, ALM photoinh. 1.5 mW    191 1.09 0.90 0.88 1.28 1.24 1.54 1.76 1.11 0.78 0.21 0.15
Fraction of units with delay-epoch contra/ipsi difference (t-test p < 0.05, correct control trials), per session:
          sessions  true_median  shifted_median  true_gt_shifted
region                                                          
ALM             47        0.361           0.100               44
SNr             18        0.392           0.174               14
Thalamus        72        0.231           0.080               53
Sessions without photostimulus (Gad2, C57BL6): 21 | true > shifted in 16 | pooled fraction true 0.242 shifted 0.081

In the extracellular files the photostimulus effect starts where the trial table puts the onset, 1.3 s after pole onset: VGAT thalamic units fall within the first 5 ms, ALM units 10 to 15 ms later, and VM/VAL units under ALM photoinhibition from about 20 ms; before the onset the ratio is near 1. More units distinguish trial types in the delay epoch with true labels than with labels shifted by one trial in 44 of 47 ALM, 14 of 18 SNr and 53 of 72 thalamic sessions, and in 16 of the 21 sessions without a photostimulus (table). The spike times share the clock of the trial tables; this is shown for every group with a photostimulus, and through decoding for the sessions without one (Gad2 and C57BL6 thalamus).

In [8]:
# Whole-cell checks: units, current, spikes, and where the photostimulus effect sits in the trial.
wm = pd.DataFrame([{"cell": c["meta"]["cell"], "group": c["meta"]["description"].replace("ALM whole cell recording during ", ""),
                    "unit": c["meta"]["vm_unit"], "conversion": c["meta"]["vm_conversion"],
                    "vm_min": round(c["meta"]["vm_range"][0], 1), "vm_max": round(c["meta"]["vm_range"][1], 1),
                    "spikes": c["meta"]["n_spikes"], "kink_found": round(float(np.mean(~np.isnan(c["meta"]["threshold_mV"]))), 3),
                    "clip_vs_deposited_median_abs_mV": round(c["meta"]["clip_vs_deposited_mad"], 3),
                    "current_nonzero": round(c["meta"]["frac_current_nonzero"], 3),
                    "kept_trials": int(c["trials"].response.isin(loop.KEEP).sum())} for c in cells])
print(wm.to_string(index=False))
cur_tr = pd.concat([c["trials"][["current_nA_E"]].assign(cell=c["meta"]["cell"]) for c in cells])
print("Mean injected current (nA) around the photostimulus, per trial: quantiles 0/50/100%",
      np.round(np.percentile(cur_tr.current_nA_E, [0, 50, 100]), 3), "| trials below -0.05 nA:", int((cur_tr.current_nA_E < -0.05).sum()),
      "in cells", sorted(set(cur_tr.cell[cur_tr.current_nA_E < -0.05])))
lz = pd.DataFrame([{"cell": c["meta"]["cell"], "group": c["meta"]["description"].replace("ALM whole cell recording during ", ""),
                    "series": c["meta"]["laser_series"][0][:12], "unit": c["meta"]["laser_unit"], "conversion": c["meta"]["laser_conversion"],
                    "max": round(c["meta"]["laser_max"], 2), "stim_trials": int(c["trials"].pi.sum()),
                    "stim_with_laser": int((c["trials"].pi & c["trials"].laser_on.notna()).sum()),
                    "ctrl_with_laser": int((~c["trials"].pi & c["trials"].laser_on.notna()).sum()),
                    "onset_after_pole_in_median": round(c["meta"]["laser_lag_from_pole"], 4),
                    "onset_after_pole_out_median": round(float(np.nanmedian((c["trials"].laser_on - c["trials"].pole_out_time)[c["trials"].pi])), 4),
                    "stim_onsets_off_median_by_20ms": int((np.abs(c["trials"].laser_on - c["trials"].pole_in_time - c["meta"]["laser_lag_from_pole"]) > 0.02)[c["trials"].pi].sum()),
                    "onset_1pct_minus_5pct_ms": round(float(np.nanmedian((c["trials"]["laser_on_0.01"] - c["trials"].laser_on)[c["trials"].pi])) * 1000, 2),
                    "onset_20pct_minus_5pct_ms": round(float(np.nanmedian((c["trials"]["laser_on_0.2"] - c["trials"].laser_on)[c["trials"].pi])) * 1000, 2),
                    "duration_s": round(float(np.nanmedian((c["trials"].laser_off - c["trials"].laser_on)[c["trials"].pi])), 3),
                    "end_after_cue_s": round(float(np.nanmedian((c["trials"].laser_off - c["trials"].cue)[c["trials"].pi])), 3),
                    "peak_median": round(float(np.nanmedian(c["trials"].laser_peak[c["trials"].pi])), 2)} for c in cells])
print("\nDeposited laser trace (stimulus/presentation/photostim_on_*, OptogeneticSeries), per cell; onset at 5% of the file's maximum:")
print(lz.to_string(index=False))
print("By group: onset after pole_in_time (s), median per cell:", lz.groupby("group").onset_after_pole_in_median.agg(["min", "max"]).to_dict("index"))
ex = wtr[~wtr.pi & wtr.laser_on.notna()]
print("Control trials with a laser pulse:", ex[["cell", "id", "response"]].to_dict("records"))
lk = wtr[wtr.response == "correct"]
print("Correct whole-cell trials with a larger lick-trace range after the go cue than before:",
      round(float(np.mean(lk.lick_ptp_after_cue > lk.lick_ptp_before_cue)), 3), "of", len(lk))

wide_t = np.arange(loop.WIDE_SPAN[0], loop.WIDE_SPAN[1], 0.001)
diffs = {}
for c in cells:
    t = c["trials"]
    k = t.response.isin(loop.KEEP).values
    g = c["meta"]["description"].replace("ALM whole cell recording during ", "")
    d = c["wide"][k & t.pi.values].mean(0) - c["wide"][k & ~t.pi.values].mean(0)
    diffs.setdefault(g, []).append(d)
print("\nMean Vm, photostimulus minus control trials (deposited spike-removed trace), by time from pole onset (s):")
rows = []
for g, ds in diffs.items():
    m = np.mean(ds, 0)
    rows.append({"group": g, "cells": len(ds), **{f"{x:.2f}": round(float(m[(wide_t >= x) & (wide_t < x + 0.02)].mean()), 1)
                                                for x in (1.2, 1.3, 1.32, 1.4, 1.44, 1.46, 1.48, 1.5, 1.52, 1.6, 2.0, 2.5, 2.7)}})
print(pd.DataFrame(rows).to_string(index=False))
first = []
for c in cells:
    if "thalamus" not in c["meta"]["description"]:
        continue
    t = c["trials"]
    k = t.response.isin(loop.KEEP).values
    d = c["wide"][k & t.pi.values].mean(0) - c["wide"][k & ~t.pi.values].mean(0)
    base = d[wide_t < 1.25]
    hit = np.flatnonzero((np.abs(d - base.mean()) > max(3 * base.std(), 2)) & (wide_t > 1.25))
    po = float(np.median(t.pole_out_time - t.pole_in_time))
    first.append((c["meta"]["cell"], round(wide_t[hit[0]], 3) if len(hit) else np.nan, round(po, 3)))
first = pd.DataFrame(first, columns=["cell", "first_change_s_from_pole_onset", "pole_out_s_from_pole_onset"])
print("\nThalamus photoinhibition cells: first time the difference exceeds 3 SD of its value before 1.25 s (and 2 mV):")
print(first.to_string(index=False))
print("Median:", first.first_change_s_from_pole_onset.median(), "| laser onset of these cells, median after pole onset:",
      round(float(lz[lz.group == "thalamus photoinhibition"].onset_after_pole_in_median.median()), 4))
print("Dashed lines: E (1.3 s, black), M (1.5 s, grey), laser onset of the thalamus cells (red)")
fig, ax = plt.subplots(figsize=(7, 3))
for g, ds in diffs.items():
    ax.plot(wide_t, np.mean(ds, 0), label=f"{g} ({len(ds)} cells)")
for x, col in ((1.3, "k"), (1.5, "grey"), (float(lz[lz.group == "thalamus photoinhibition"].onset_after_pole_in_median.median()), "tab:red")):
    ax.axvline(x, ls="--", c=col, lw=0.8)
ax.set_xlim(1.0, 3.0)
ax.set_xlabel("time from pole onset (s)")
ax.set_ylabel("photostim. - control Vm (mV)")
ax.legend(fontsize=7)
plt.show()
print("Range plotted:", round(min(np.mean(ds, 0).min() for ds in diffs.values()), 1), "to",
      round(max(np.mean(ds, 0).max() for ds in diffs.values()), 1), "mV")
     cell                      group unit  conversion  vm_min  vm_max  spikes  kink_found  clip_vs_deposited_median_abs_mV  current_nonzero  kept_trials
cell_20_1         M1 photoinhibition   mV       0.001   -95.0     3.7    8399       0.808                              0.0            0.011          100
cell_21_1         M1 photoinhibition   mV       0.001   -90.6    21.8   20842       0.928                              0.0            0.011          172
cell_22_1         M1 photoinhibition   mV       0.001   -86.1     9.9    3002       0.932                              0.0            0.010           43
cell_23_1         M1 photoinhibition   mV       0.001   -86.7     3.2    1243       0.970                              0.0            0.010           33
cell_25_1         M1 photoinhibition   mV       0.001   -99.2    14.4    9301       0.984                              0.0            0.010           93
cell_29_1         M1 photoinhibition   mV       0.001   -79.0    12.6    4578       0.942                              0.0            0.010           43
cell_55_1   thalamus photoinhibition   mV       0.001   -81.3    13.2    1479       0.749                              0.0            0.010           75
cell_56_1   thalamus photoinhibition   mV       0.001   -77.6    29.6    2745       0.909                              0.0            0.010           83
cell_57_1   thalamus photoinhibition   mV       0.001  -107.9    10.6    1670       0.879                              0.0            0.010           45
cell_58_1   thalamus photoinhibition   mV       0.001   -87.0    32.4    1426       0.875                              0.0            0.010           48
cell_59_1   thalamus photoinhibition   mV       0.001   -79.4    37.7    2780       0.917                              0.0            0.010           57
cell_60_1   thalamus photoinhibition   mV       0.001  -107.9    23.0    1932       0.775                              0.0            0.010           71
cell_44_1         M1 photoinhibition   mV       0.001   -69.5    18.8    6777       0.993                              0.0            0.010           46
cell_45_1         M1 photoinhibition   mV       0.001   -91.3    25.6    3767       0.965                              0.0            0.010           49
cell_46_1         M1 photoinhibition   mV       0.001   -70.8    33.8    7862       0.965                              0.0            0.010           74
cell_45_2 contra ALM photoinhibition   mV       0.001   -84.2    14.0    3187       0.909                              0.0            0.010           48
cell_46_2 contra ALM photoinhibition   mV       0.001   -78.3    13.2    6810       0.960                              0.0            0.010           69
cell_40_2         M1 photoinhibition   mV       0.001   -74.0    34.5    2051       0.934                              0.0            0.010           86
cell_39_1 contra ALM photoinhibition   mV       0.001   -61.2    18.7    4120       0.992                              0.0            0.010           44
cell_40_1 contra ALM photoinhibition   mV       0.001   -87.9   -27.7     931       0.838                              0.0            0.010           44
cell_30_2         M1 photoinhibition   mV       0.001  -100.8     7.4     653       0.963                              0.0            0.009           38
cell_30_1 contra ALM photoinhibition   mV       0.001   -86.8    20.9    3264       0.970                              0.0            0.010          119
cell_31_1 contra ALM photoinhibition   mV       0.001   -71.6    30.0    4718       0.988                              0.0            0.010           70
cell_32_1 contra ALM photoinhibition   mV       0.001   -72.7     3.2    5853       0.988                              0.0            0.011           39
cell_34_1 contra ALM photoinhibition   mV       0.001   -86.7    30.5    2576       0.973                              0.0            0.010           93
cell_35_1 contra ALM photoinhibition   mV       0.001  -107.9    28.0    1937       0.877                              0.0            0.010           36
cell_47_1   thalamus photoinhibition   mV       0.001   -96.4    30.7    3931       0.398                              0.0            0.010           61
cell_49_1   thalamus photoinhibition   mV       0.001   -95.4    12.8    2297       0.932                              0.0            0.010           23
cell_50_1   thalamus photoinhibition   mV       0.001   -75.7    29.0    9756       0.874                              0.0            0.010           82
cell_51_1   thalamus photoinhibition   mV       0.001  -107.9    27.8    6750       0.949                              0.0            0.010          104
cell_52_1   thalamus photoinhibition   mV       0.001   -75.9    36.0    8372       0.979                              0.0            0.010          121
cell_53_1   thalamus photoinhibition   mV       0.001   -65.8    19.9    3736       0.977                              0.0            0.010           28
cell_64_1   thalamus photoinhibition   mV       0.001   -88.9    27.1    1437       0.896                              0.0            0.010           55
cell_65_1   thalamus photoinhibition   mV       0.001   -80.2    39.5    2752       0.939                              0.0            0.010           66
cell_66_1   thalamus photoinhibition   mV       0.001   -77.3    43.4    1534       0.662                              0.0            0.010           57
cell_73_2   thalamus photoinhibition   mV       0.001   -77.8     7.0    1907       0.918                              0.0            0.010           41
Mean injected current (nA) around the photostimulus, per trial: quantiles 0/50/100% [-0. -0.  0.] | trials below -0.05 nA: 0 in cells []

Deposited laser trace (stimulus/presentation/photostim_on_*, OptogeneticSeries), per cell; onset at 5% of the file's maximum:
     cell                      group       series  unit  conversion   max  stim_trials  stim_with_laser  ctrl_with_laser  onset_after_pole_in_median  onset_after_pole_out_median  stim_onsets_off_median_by_20ms  onset_1pct_minus_5pct_ms  onset_20pct_minus_5pct_ms  duration_s  end_after_cue_s  peak_median
cell_20_1         M1 photoinhibition photostim_on watts       0.001  3.01           68               68                0                      1.4026                       0.0019                               8                     -1.00                       1.85       1.193           -0.005         3.01
cell_21_1         M1 photoinhibition photostim_on watts       0.001  4.28           87               87                1                      1.4025                       0.0019                               4                     -1.15                       2.30       1.192           -0.006         3.00
cell_22_1         M1 photoinhibition photostim_on watts       0.001  3.00           11               11                0                      1.4026                       0.0017                               0                     -1.00                       1.85       1.193           -0.005         3.00
cell_23_1         M1 photoinhibition photostim_on watts       0.001  3.00            4                4                0                      1.4025                       0.0019                               0                     -1.00                       1.80       1.193           -0.005         3.00
cell_25_1         M1 photoinhibition photostim_on watts       0.001  3.00           47               47                0                      1.4026                       0.0019                               2                     -1.00                       1.85       1.193           -0.005         3.00
cell_29_1         M1 photoinhibition photostim_on watts       0.001  2.99           24               24                0                      1.4025                       0.0018                               1                     -1.00                       1.85       1.193           -0.005         2.99
cell_55_1   thalamus photoinhibition photostim_on watts       0.001 10.76           28               28                0                      1.4727                       0.0718                               0                      0.00                       0.00       1.242            0.114        10.00
cell_56_1   thalamus photoinhibition photostim_on watts       0.001 10.81           31               31                0                      1.4724                       0.0718                               0                      0.00                       0.00       1.242            0.114        10.00
cell_57_1   thalamus photoinhibition photostim_on watts       0.001 10.43           18               18                0                      1.4725                       0.0719                               1                      0.00                       0.00       1.242            0.114        10.01
cell_58_1   thalamus photoinhibition photostim_on watts       0.001 10.01           19               19                0                      1.4728                       0.0720                               3                      0.00                       0.00       1.242            0.114        10.01
cell_59_1   thalamus photoinhibition photostim_on watts       0.001 10.78           24               24                0                      1.4725                       0.0718                               0                      0.00                       0.00       1.242            0.114        10.01
cell_60_1   thalamus photoinhibition photostim_on watts       0.001 10.38           33               33                0                      1.4725                       0.0719                               4                      0.00                       0.00       1.242            0.114        10.01
cell_44_1         M1 photoinhibition photostim_on watts       0.001  3.00           19               19                0                      1.4744                       0.0736                               1                     -1.05                       1.90       1.237            0.110         3.00
cell_45_1         M1 photoinhibition photostim_on watts       0.001  3.00           26               26                0                      1.4743                       0.0738                               1                     -1.05                       1.90       1.237            0.110         3.00
cell_46_1         M1 photoinhibition photostim_on watts       0.001  3.00           44               44                0                      1.4744                       0.0738                               4                     -1.05                       1.90       1.237            0.110         3.00
cell_45_2 contra ALM photoinhibition photostim_on watts       0.001  3.00           30               30                0                      1.4745                       0.0738                               4                     -1.08                       2.05       1.237            0.110         3.00
cell_46_2 contra ALM photoinhibition photostim_on watts       0.001  3.00           42               42                0                      1.4744                       0.0737                               5                     -1.10                       2.05       1.237            0.110         3.00
cell_40_2         M1 photoinhibition photostim_on watts       0.001  3.00           40               40                0                      1.4744                       0.0738                               1                     -1.05                       1.90       1.237            0.110         3.00
cell_39_1 contra ALM photoinhibition photostim_on watts       0.001  2.98           18               18                0                      1.4743                       0.0735                               0                     -1.20                       2.05       1.237            0.110         2.98
cell_40_1 contra ALM photoinhibition photostim_on watts       0.001  3.00           19               19                0                      1.4744                       0.0736                               0                     -1.05                       2.05       1.237            0.110         3.00
cell_30_2         M1 photoinhibition photostim_on watts       0.001  3.00           17               17                0                      1.4744                       0.0738                               1                     -1.05                       1.90       1.237            0.110         3.00
cell_30_1 contra ALM photoinhibition photostim_on watts       0.001  3.00           46               46                0                      1.4744                       0.0739                               2                     -1.05                       2.05       1.237            0.110         3.00
cell_31_1 contra ALM photoinhibition photostim_on watts       0.001  3.00           36               36                0                      1.4744                       0.0737                               1                     -1.13                       2.05       1.237            0.110         3.00
cell_32_1 contra ALM photoinhibition photostim_on watts       0.001  3.00           20               20                0                      1.4744                       0.0738                               0                     -1.05                       2.05       1.237            0.110         3.00
cell_34_1 contra ALM photoinhibition photostim_on watts       0.001  4.58           42               42                0                      1.4749                       0.0743                               1                     -1.35                       2.45       1.235            0.109         3.00
cell_35_1 contra ALM photoinhibition photostim_on watts       0.001  3.00           18               18                0                      1.4745                       0.0738                               2                     -1.05                       2.10       1.237            0.110         3.00
cell_47_1   thalamus photoinhibition photostim_on watts       0.001 10.70           14               14                0                      1.4727                       0.0719                               0                      0.00                       0.00       1.242            0.114        10.01
cell_49_1   thalamus photoinhibition photostim_on watts       0.001 10.00           11               11                0                      1.4724                       0.0716                               0                      0.00                       0.00       1.243            0.114        10.00
cell_50_1   thalamus photoinhibition photostim_on watts       0.001 10.62           35               35                0                      1.4724                       0.0720                               1                      0.00                       0.00       1.242            0.114        10.06
cell_51_1   thalamus photoinhibition photostim_on watts       0.001 10.73           40               40                0                      1.4725                       0.0718                               1                      0.00                       0.00       1.242            0.114        10.01
cell_52_1   thalamus photoinhibition photostim_on watts       0.001 10.82           34               34                0                      1.4723                       0.0718                               0                      0.00                       0.00       1.242            0.114        10.00
cell_53_1   thalamus photoinhibition photostim_on watts       0.001 10.59           13               13                0                      1.4726                       0.0718                               0                      0.00                       0.00       1.242            0.114        10.00
cell_64_1   thalamus photoinhibition photostim_on watts       0.001 10.04           20               20                0                      1.4725                       0.0718                               0                      0.00                       0.00       1.243            0.114        10.00
cell_65_1   thalamus photoinhibition photostim_on watts       0.001 10.01           26               26                0                      1.4726                       0.0717                               0                      0.00                       0.00       1.243            0.114        10.00
cell_66_1   thalamus photoinhibition photostim_on watts       0.001 10.81           29               29                0                      1.4726                       0.0718                               2                      0.00                       0.00       1.242            0.114        10.00
cell_73_2   thalamus photoinhibition photostim_on watts       0.001 10.01           20               20                0                      1.4725                       0.0717                               0                      0.00                       0.00       1.243            0.114        10.00
By group: onset after pole_in_time (s), median per cell: {'M1 photoinhibition': {'min': 1.4025, 'max': 1.4744}, 'contra ALM photoinhibition': {'min': 1.4743, 'max': 1.4749}, 'thalamus photoinhibition': {'min': 1.4723, 'max': 1.4728}}
Control trials with a laser pulse: [{'cell': 'cell_21_1', 'id': 349, 'response': 'incorrect'}]
Correct whole-cell trials with a larger lick-trace range after the go cue than before: 0.998 of 1824

Mean Vm, photostimulus minus control trials (deposited spike-removed trace), by time from pole onset (s):
                     group  cells  1.20  1.30  1.32  1.40  1.44  1.46  1.48  1.50  1.52  1.60  2.00  2.50  2.70
        M1 photoinhibition     11   0.3  -0.1  -0.1  -0.0  -1.3  -1.1  -1.3  -2.3  -2.8  -2.2  -1.1  -0.8   0.0
  thalamus photoinhibition     16  -0.0   0.1   0.2   0.2  -0.1  -0.0  -2.4  -8.5 -13.3 -18.4 -12.7 -16.5  -1.1
contra ALM photoinhibition      9   0.8   0.9   0.8   1.0   0.6   0.8   0.7  -0.9  -1.6  -1.6   0.3   0.1   1.1

Thalamus photoinhibition cells: first time the difference exceeds 3 SD of its value before 1.25 s (and 2 mV):
     cell  first_change_s_from_pole_onset  pole_out_s_from_pole_onset
cell_55_1                           1.493                       1.401
cell_56_1                           1.494                       1.401
cell_57_1                           1.505                       1.401
cell_58_1                           1.469                       1.401
cell_59_1                           1.485                       1.401
cell_60_1                           1.489                       1.401
cell_47_1                           1.486                       1.401
cell_49_1                           1.351                       1.401
cell_50_1                           1.496                       1.401
cell_51_1                           1.493                       1.401
cell_52_1                           1.502                       1.401
cell_53_1                           1.504                       1.401
cell_64_1                           1.501                       1.401
cell_65_1                           1.494                       1.401
cell_66_1                           1.488                       1.401
cell_73_2                           1.490                       1.401
Median: 1.493 | laser onset of these cells, median after pole onset: 1.4725
Dashed lines: E (1.3 s, black), M (1.5 s, grey), laser onset of the thalamus cells (red)
No description has been provided for this image
Range plotted: -18.4 to 2.3 mV

The whole-cell Vm is stored with unit 'mV' and conversion 0.001, but the values are already in mV (minimum -61 to -108 mV, spikes peaking up to +43 mV); applying the conversion, as NWB prescribes, would give values a thousand times too small. The injected current around the photostimulus is 0 nA in every trial. The spike clipping of convention V, computed here from the raw trace, leaves the trace equal to the deposited spike-removed trace (median absolute difference 0 mV in every cell), so the deposited trace is clipped by the same rule. Licks follow the go cue in the lick traces.

The whole-cell files hold the laser trace, as an OptogeneticSeries (stimulus/presentation/photostim_on_*, 20 kHz, unit 'watts' with conversion 0.001, so the values are in mW): a step to 10 mW in the 16 thalamus photoinhibition cells and a sinusoid peaking at 3 mW (1.5 mW mean) in the 20 cortical photoinhibition cells. Before the first verification the loader read only general/optogenetics and this notebook said the files record no laser time; that was wrong. The trace is present in every stim_present trial and in one control trial (cell_21_1, an incorrect trial). The laser starts 1.4725 s after pole_in_time (0.072 s after pole_out_time) in the thalamus cells, 1.474 s after it in 14 cortical cells and 1.4026 s after it (0.002 s after pole_out_time) in the six M1 cells of anm300476. It lasts 1.19 to 1.24 s and ends between 5 ms before and 114 ms after the go cue. In 0 to 8 photostimulus trials per cell it starts more than 20 ms from the cell's median; reading L uses each trial's own onset. Onsets taken at 1% or 20% of the maximum, in place of 5%, differ by 0 ms (step) or 1.0 to 2.5 ms (sinusoid).

Neither onset of the claims file is the laser onset: in the thalamus cells E (1.3 s after pole onset) is 0.17 s before it and M (pole_out_time + 0.1 s, 1.5 s) 28 ms after it. Thalamus photoinhibition hyperpolarizes ALM neurons from a median 1.493 s after pole onset (first crossing of 3 SD and 2 mV on 1 ms samples; 1.47 to 1.51 s in 15 of 16 cells), 20 ms after the laser onset by this coarse check. Under E the 20 to 120 ms window (1.32 to 1.42 s) lies before the change in all three groups (table: 0.2 mV for thalamus photoinhibition at 1.32 and 1.40 s). Under M (1.52 to 1.62 s) and L (1.49 to 1.59 s) it lies inside the change. The claims file (answer of 2026-10-20) gives E and M as readings, because it took the files to hold no laser time. Reading L, the onset of the deposited laser trace, is shown here as a third reading, and question 7 asks whether it should be used. Control trials are aligned at the cell's median laser onset. The extracellular files hold no laser trace; there the onset is the delay onset of the trial table, which the clock check above supports.

Selections and readings used by several claims¶

Unit classes (convention C of the claims file): P1 applies the Methods' width thresholds to the trough-to-peak width of the deposited mean waveform (ALM pyramidal > 0.6 ms, thalamic > 0.5 ms, SNr GABAergic < 0.45 ms); P2 uses the files' cell_type label ('Wide width spiking' for ALM pyramidal and thalamic units; 'Narrow width spiking' for SNr GABAergic units, as convention C says; before the first verification this reading took every SNr unit not labelled wide); P3, for the thalamic claims of Fig. 2 and 6 only, takes all thalamic units regardless of width (VM26). VM/VAL: reading L1 (a VM/VAL label in the dataset) does not exist, as every thalamic unit is labelled 'Thalamus'; reading L2 is within 0.4 mm of ML 0.85, DV -4.0 mm in the coronal plane.

Selectivity (convention S) is computed once per reading: trials (control only, or all), response window (R1, R2), t-test (Student, Welch) and outcomes (c1 correct only, c2 correct and incorrect), 16 readings.

In [9]:
alm = units[units.region == "ALM"]
thal = units[units.region == "Thalamus"]
snr = units[units.region == "SNr"]
PYR = {"P1": alm[alm.width_ms > 0.6], "P2": alm[alm.cell_type == "Wide width spiking"]}
THP = {"P1": thal[thal.width_ms > 0.5], "P2": thal[thal.cell_type == "Wide width spiking"]}
GABA = {"P1": snr[snr.width_ms < 0.45], "P2": snr[snr.cell_type == "Narrow width spiking"]}
VMVAL = {p: d[d.vmval_d < 0.4] for p, d in THP.items()}
# Convention C, reading P3: all thalamic units regardless of width, for the thalamic claims of Fig. 2 and 6 only.
VM26 = {**VMVAL, "P3": thal[thal.vmval_d < 0.4]}
SEL_READINGS = [(ts, r, ev, oc) for ts in ("control", "all") for r in ("R1", "R2") for ev in (True, False)
                for oc in (("correct",), ("correct", "incorrect"))]


def sel_key(ts, r, ev, oc):
    return f"{ts}/{r}/{'Student' if ev else 'Welch'}/{'c1' if len(oc) == 1 else 'c2'}"


t0 = time.time()
SEL = {sel_key(*k): loop.selectivity_table(sessions, units, resp=k[1], equal_var=k[2], outcomes=k[3], trials_sel=k[0])
       for k in SEL_READINGS}
print(f"selectivity under {len(SEL)} readings for {len(units)} units in {time.time() - t0:.0f} s")
print("Units per class:", {f"ALM pyramidal {p}": len(d) for p, d in PYR.items()},
      {f"thalamic {p}": len(d) for p, d in THP.items()}, {f"VM/VAL {p}": len(d) for p, d in VM26.items()},
      {f"SNr GABAergic {p}": len(d) for p, d in GABA.items()})
selectivity under 16 readings for 1936 units in 8 s
Units per class: {'ALM pyramidal P1': 577, 'ALM pyramidal P2': 810} {'thalamic P1': 148, 'thalamic P2': 682} {'VM/VAL P1': 20, 'VM/VAL P2': 222, 'VM/VAL P3': 259} {'SNr GABAergic P1': 171, 'SNr GABAergic P2': 146}

task-performance¶

Mice performed the delayed-response task at 77.6% correct on average, with 10.3% lick-early trials and 1.1% no-response trials.

Readings of the criterion: (a) all trials of all sessions pooled, (b) mean over sessions, (c) control trials only, pooled and per session. Percent correct excludes lick-early and no-response trials; those two are fractions of all task trials. Sessions are every behavioural recording in the dandiset (extracellular sessions and whole-cell recordings), shown also by kind.

In [10]:
prow = []
for s in sessions:
    t = s["trials"]
    prow.append({"kind": "extracellular", "subject": s["meta"]["subject"], "resp": t.response.values, "ctrl": (t.stim == "none").values})
for c in cells:
    t = c["trials"]
    prow.append({"kind": "whole-cell", "subject": c["meta"]["subject"], "resp": t.response.values, "ctrl": ~t.pi.values})


def perf(resp):
    n = len(resp)
    cor, inc = (resp == "correct").sum(), (resp == "incorrect").sum()
    return {"n": n, "correct": 100 * cor / (cor + inc), "early": 100 * (resp == "early lick").sum() / n,
            "noresp": 100 * (resp == "no response").sum() / n}


out = []
for kinds in (("extracellular", "whole-cell"), ("extracellular",), ("whole-cell",)):
    sel = [r for r in prow if r["kind"] in kinds]
    for reading, use_ctrl in (("a/b all trials", False), ("c control trials", True)):
        per = pd.DataFrame([perf(r["resp"][r["ctrl"]] if use_ctrl else r["resp"]) for r in sel])
        pooled = perf(np.concatenate([r["resp"][r["ctrl"]] if use_ctrl else r["resp"] for r in sel]))
        out.append({"files": "+".join(kinds), "trials": reading, "how": "pooled", "sessions": len(sel), "trials_n": pooled["n"],
                    "correct_%": pooled["correct"], "lick_early_%": pooled["early"], "no_response_%": pooled["noresp"]})
        out.append({"files": "+".join(kinds), "trials": reading, "how": "mean over sessions", "sessions": len(sel), "trials_n": int(per.n.sum()),
                    "correct_%": per.correct.mean(), "lick_early_%": per.early.mean(), "no_response_%": per.noresp.mean()})
perf_tab = pd.DataFrame(out)
perf_tab["within_tol"] = ((perf_tab["correct_%"] - 77.6).abs() <= 7.76) & ((perf_tab["lick_early_%"] - 10.3).abs() <= 1.03) & \
    ((perf_tab["no_response_%"] - 1.1).abs() <= 0.11)
print(perf_tab.round(2).to_string(index=False))
print("Paper: 77.6 +/- 7.76 % correct, 10.3 +/- 1.03 % lick early, 1.1 +/- 0.11 % no response")
by_mouse = pd.DataFrame([{"subject": r["subject"], **perf(r["resp"])} for r in prow]).groupby("subject")[["correct", "early", "noresp"]].mean()
print("\nPer mouse (mean over its sessions, all trials): correct", by_mouse.correct.round(1).min(), "to", by_mouse.correct.round(1).max(),
      "| lick early", by_mouse.early.round(1).min(), "to", by_mouse.early.round(1).max(), "| no response", by_mouse.noresp.round(2).min(), "to", by_mouse.noresp.round(2).max())
                   files           trials                how  sessions  trials_n  correct_%  lick_early_%  no_response_%  within_tol
extracellular+whole-cell   a/b all trials             pooled       173     36923      70.66         18.18           0.78       False
extracellular+whole-cell   a/b all trials mean over sessions       173     36923      71.48         15.91           0.98       False
extracellular+whole-cell c control trials             pooled       173     29482      74.20         17.08           0.73       False
extracellular+whole-cell c control trials mean over sessions       173     29482      75.46         14.66           0.90       False
           extracellular   a/b all trials             pooled       137     34270      70.08         18.84           0.72       False
           extracellular   a/b all trials mean over sessions       137     34270      69.85         17.81           0.87       False
           extracellular c control trials             pooled       137     27882      73.69         17.58           0.71       False
           extracellular c control trials mean over sessions       137     27882      73.35         16.43           0.89       False
              whole-cell   a/b all trials             pooled        36      2653      77.42          9.65           1.55       False
              whole-cell   a/b all trials mean over sessions        36      2653      77.65          8.68           1.43       False
              whole-cell c control trials             pooled        36      1600      82.33          8.38           1.06       False
              whole-cell c control trials mean over sessions        36      1600      83.47          7.93           0.96       False
Paper: 77.6 +/- 7.76 % correct, 10.3 +/- 1.03 % lick early, 1.1 +/- 0.11 % no response
Per mouse (mean over its sessions, all trials): correct 57.6 to 86.8 | lick early 3.6 to 37.2 | no response 0.0 to 4.5

Result: not reproduced. Over all 173 behavioural recordings, percent correct is 70.7% (all trials pooled) to 75.5% (control trials, mean over sessions), within 77.6 +/- 7.8%, but lick-early trials are 14.7 to 18.2% against 10.3 +/- 1.0%, and no-response trials 0.73 to 0.98% against 1.1 +/- 0.11%. No reading puts all three within tolerance, and two of the three values are outside it under every reading of the full set of recordings. The whole-cell recordings alone come closest (77.4 to 83.5% correct, 7.9 to 9.7% lick early, 0.96 to 1.55% no response), with at most two values within tolerance. The dandiset holds recording sessions only, not the behaviour sessions the paper's averages may include. (Partially reproduced before the first verification; changed on the verifier's reading that no reading puts all three values within tolerance.)

fig1c-alm-photoinhibition-bias¶

Unilateral photoinhibition of ALM during the delay epoch biased responses to the ipsilateral side, lowering performance on contra trials and raising it on ipsi trials.

The dandiset has no behaviour-only sessions; the test uses the behavioural trials of the 66 recording sessions in PV-Cre x Ai32 mice with left-ALM photoinhibition in the delay epoch (ALM, thalamic and SNr recordings, 13 mice). Main reading: photoinhibition trials at 1.5 mW (the Methods' power); variant: all delay-epoch powers (1.5 and 0.75/0.79 mW), outside the condition by convention P (answer of 2026-10-20). Per session, fraction correct with lick-early and no-response trials excluded; two-sided paired t-test over sessions.

In [11]:
def fig1c(stims):
    rows = []
    for s in sessions:
        m = s["meta"]
        if m["genotype"] != "Ai32 x PV-Cre" or m["ogen_site"] != "ALM":
            continue
        t = s["trials"]
        k = t.response.isin(loop.KEEP).values
        r = {"subject": m["subject"], "region": m["region"]}
        for side, con in (("contra", True), ("ipsi", False)):
            for cond, msk in (("ctrl", (t.stim == "none").values), ("pi", t.stim.isin(stims).values)):
                sel = k & msk & (t.contra.values == con)
                r[f"{side}_{cond}"] = (t.response.values[sel] == "correct").mean() if sel.any() else np.nan
                r[f"n_{side}_{cond}"] = int(sel.sum())
        rows.append(r)
    return pd.DataFrame(rows)


for name, stims in (("1.5 mW", ["ALM:delay:1.5"]), ("all delay powers", ["ALM:delay:1.5", "ALM:delay:0.79", "ALM:delay:0.75"])):
    d = fig1c(stims)
    full = d.dropna(subset=["contra_ctrl", "contra_pi", "ipsi_ctrl", "ipsi_pi"])
    print(f"--- {name}: {len(full)} of {len(d)} sessions with all four cells, {full.subject.nunique()} mice;"
          f" photoinhibition trials per session median {int((full.n_contra_pi + full.n_ipsi_pi).median())}")
    for side in ("contra", "ipsi"):
        tt = stats.ttest_rel(full[f"{side}_pi"], full[f"{side}_ctrl"])
        print(f"{side}: control {full[side + '_ctrl'].mean():.3f}, photoinhibition {full[side + '_pi'].mean():.3f}, "
              f"change {(full[side + '_pi'] - full[side + '_ctrl']).mean():+.3f} (sessions with an increase "
              f"{int((full[side + '_pi'] > full[side + '_ctrl']).sum())}/{len(full)}), paired t = {tt.statistic:.2f}, p = {tt.pvalue:.2g}")
    if name == "1.5 mW":
        print("Per mouse (means over sessions):")
        print(full.groupby("subject")[["contra_ctrl", "contra_pi", "ipsi_ctrl", "ipsi_pi"]].mean().round(3).assign(
            sessions=full.groupby("subject").size()).to_string())
        print("By recorded region:")
        print(full.groupby("region")[["contra_ctrl", "contra_pi", "ipsi_ctrl", "ipsi_pi"]].mean().round(3).to_string())
--- 1.5 mW: 66 of 66 sessions with all four cells, 11 mice; photoinhibition trials per session median 41
contra: control 0.774, photoinhibition 0.368, change -0.405 (sessions with an increase 0/66), paired t = -16.67, p = 3.6e-25
ipsi: control 0.673, photoinhibition 0.744, change +0.071 (sessions with an increase 46/66), paired t = 3.99, p = 0.00017
Per mouse (means over sessions):
             contra_ctrl  contra_pi  ipsi_ctrl  ipsi_pi  sessions
subject                                                          
anm00234218        0.800      0.301      0.573    0.671         4
anm00239123        0.730      0.334      0.673    0.715         3
anm00260487        0.726      0.317      0.688    0.741        11
anm00260488        0.751      0.326      0.635    0.771         6
anm00260490        0.665      0.383      0.594    0.699         7
anm00260491        0.670      0.442      0.490    0.667         3
anm00261334        0.880      0.514      0.686    0.728         5
anm00261335        0.803      0.446      0.648    0.657         9
anm00261336        0.810      0.641      0.782    0.761         6
anm00264941        0.725      0.333      0.647    0.833         1
anm00264943        0.847      0.173      0.775    0.878        11
By recorded region:
          contra_ctrl  contra_pi  ipsi_ctrl  ipsi_pi
region                                              
ALM             0.817      0.203      0.753    0.874
SNr             0.832      0.534      0.707    0.709
Thalamus        0.739      0.327      0.643    0.734
--- all delay powers: 66 of 66 sessions with all four cells, 11 mice; photoinhibition trials per session median 44
contra: control 0.774, photoinhibition 0.418, change -0.356 (sessions with an increase 0/66), paired t = -16.59, p = 4.7e-25
ipsi: control 0.673, photoinhibition 0.735, change +0.062 (sessions with an increase 44/66), paired t = 3.64, p = 0.00054

Result: reproduced. In 66 recording sessions of 11 PV-Cre x Ai32 mice, ALM photoinhibition at 1.5 mW lowers contra performance from 0.774 to 0.368 (paired t = -16.67, p = 3.6e-25; no session increases) and raises ipsi performance from 0.673 to 0.744 (t = 3.99, p = 0.00017; 46 of 66 sessions increase). Both hold at p < 0.001, and with all powers pooled (p = 4.7e-25 and 0.00054). These are the behavioural trials of recording sessions, not the paper's 84 behaviour sessions.

alm-unit-classes¶

Of 1214 ALM units, 1006 were putative pyramidal neurons (spike width > 0.6 ms), 166 putative fast-spiking (< 0.4 ms) and 42 unclassified; the spike-width distribution was bimodal.

In [12]:
w = alm.width_ms
cnt = {"units": len(alm), "< 0.4 ms": int((w < 0.4).sum()), "0.4 to 0.6 ms": int(((w >= 0.4) & (w <= 0.6)).sum()), "> 0.6 ms": int((w > 0.6).sum())}
print("P1, computed widths:", cnt)
print("P2, file labels:", alm.cell_type.value_counts().to_dict())
print("Paper: 1214 +/- 121 units, 1006 +/- 101 pyramidal, 166 +/- 17 fast-spiking (42 unclassified)")
print("Scaled to the paper's total (x 1214/966): > 0.6 ms", round(cnt["> 0.6 ms"] * 1214 / len(alm)), "| wide label",
      round((alm.cell_type == "Wide width spiking").sum() * 1214 / len(alm)), "| < 0.4 ms", round(cnt["< 0.4 ms"] * 1214 / len(alm)),
      "| narrow label", round((alm.cell_type == "Narrow width spiking").sum() * 1214 / len(alm)))
print("Fractions: > 0.6 ms", round(cnt["> 0.6 ms"] / len(alm), 3), "| wide label", round((alm.cell_type == "Wide width spiking").mean(), 3),
      "| paper pyramidal", round(1006 / 1214, 3), "; < 0.4 ms", round(cnt["< 0.4 ms"] / len(alm), 3), "| narrow label",
      round((alm.cell_type == "Narrow width spiking").mean(), 3), "| paper FS", round(166 / 1214, 3))
print("\nHistogram of computed widths (ms): count per 0.04 ms step")
print(w.round(2).value_counts().sort_index().to_string())
print("Units > 0.6 ms whose peak is the last waveform sample:", int(((w > 0.6) & alm.peak_last).sum()), "of", cnt["> 0.6 ms"],
      "| units 0.4 to 0.6 ms with the peak at the last sample:", int(((w >= 0.4) & (w <= 0.6) & alm.peak_last).sum()))
print("Per session: ALM units", alm.groupby("session").size().describe()[["min", "50%", "max"]].to_dict())
fig, ax = plt.subplots(figsize=(5, 2.5))
ax.hist(w, bins=np.arange(0.06, 0.78, 0.04), color="0.5")
ax.set_xlabel("trough-to-peak width (ms), deposited waveform")
ax.set_ylabel("ALM units")
plt.show()
print("All", len(w), "widths within the axes (0.06 to 0.78 ms)")
P1, computed widths: {'units': 966, '< 0.4 ms': 127, '0.4 to 0.6 ms': 262, '> 0.6 ms': 577}
P2, file labels: {'Wide width spiking': 810, 'Narrow width spiking': 121, 'Cannot be determined': 35}
Paper: 1214 +/- 121 units, 1006 +/- 101 pyramidal, 166 +/- 17 fast-spiking (42 unclassified)
Scaled to the paper's total (x 1214/966): > 0.6 ms 725 | wide label 1018 | < 0.4 ms 160 | narrow label 152
Fractions: > 0.6 ms 0.597 | wide label 0.839 | paper pyramidal 0.829 ; < 0.4 ms 0.131 | narrow label 0.125 | paper FS 0.137

Histogram of computed widths (ms): count per 0.04 ms step
width_ms
0.12      2
0.16      7
0.20     16
0.24     14
0.28     62
0.32     22
0.36      4
0.40      9
0.44     16
0.48     47
0.52    117
0.56      5
0.60     68
0.64     61
0.68    267
0.72    249
Units > 0.6 ms whose peak is the last waveform sample: 514 of 577 | units 0.4 to 0.6 ms with the peak at the last sample: 115
Per session: ALM units {'min': 3.0, '50%': 20.0, 'max': 46.0}
No description has been provided for this image
All 966 widths within the axes (0.06 to 0.78 ms)

Result: not reproduced. The dandiset holds 966 ALM units (paper 1214 +/- 121). The file labels give 810 wide and 121 narrow units (35 undetermined), fractions 0.839 and 0.125 against the paper's 0.829 and 0.137. Computed widths give 577 units above 0.6 ms and 127 below 0.4 ms, because the deposited waveforms are too short (514 of the 577 have their peak at the last sample). No count is within tolerance under either reading; P1 is the Methods' rule, and it fails because of the waveforms, not the units. The width histogram has two modes, at 0.28 ms (62 units) and 0.68 to 0.72 ms (267 and 249), with a trough at 0.36 ms (4 units).

The criterion has no partial clause, and no reading meets it in full (see Changes of outcome, before the Summary). The third verification round agreed.

fig2e-alm-selectivity¶

Most ALM putative pyramidal neurons (70%, 704/1006) distinguished trial types; 145 had preparatory activity only, 272 peri-movement selectivity only and 287 both.

Every reading of the criterion (trials control or all; R1, R2; Student, Welch; c1, c2), for both unit readings P1 and P2.

In [13]:
def sel_counts(idx, key):
    d = SEL[key].loc[idx]
    return {"n": len(d), "selective": int(d.selective.sum()), "prep_only": int((d.kind == "prep_only").sum()),
            "peri_only": int((d.kind == "peri_only").sum()), "both": int((d.kind == "both").sum()),
            "contra_pref": int((d.selective & d.contra_pref).sum())}


rows = []
for p, d in PYR.items():
    for k in SEL:
        rows.append({"units": p, "reading": k, **sel_counts(d.index, k)})
f2e = pd.DataFrame(rows)
f2e["frac_selective"] = (f2e.selective / f2e.n).round(3)
f2e["within_tol"] = ((f2e.selective - 704).abs() <= 70) & ((f2e.prep_only - 145).abs() <= 15) & \
    ((f2e.peri_only - 272).abs() <= 27) & ((f2e.both - 287).abs() <= 29)
for col, ref in (("selective", 704), ("prep_only", 145), ("peri_only", 272), ("both", 287)):
    f2e[col + "_scaled"] = (f2e[col] * 1006 / f2e.n).round(0)
print(f2e.to_string(index=False))
print("Paper: 704/1006 selective (0.70), 145 prep only, 272 peri only, 287 both")
print("Readings with all four counts within tolerance:", int(f2e.within_tol.sum()), "of", len(f2e))
k0 = "control/R1/Student/c1"
print(f"\nBy mouse ({k0}, P2):")
d = SEL[k0].loc[PYR["P2"].index].join(PYR["P2"][["subject", "genotype"]])
print(d.groupby(["genotype", "subject"]).agg(n=("selective", "size"), selective=("selective", "mean")).round(3).to_string())
units               reading   n  selective  prep_only  peri_only  both  contra_pref  frac_selective  within_tol  selective_scaled  prep_only_scaled  peri_only_scaled  both_scaled
   P1 control/R1/Student/c1 577        398         95        154   149          201           0.690       False             694.0             166.0             268.0        260.0
   P1 control/R1/Student/c2 577        360         90        141   129          183           0.624       False             628.0             157.0             246.0        225.0
   P1   control/R1/Welch/c1 577        398         91        149   158          197           0.690       False             694.0             159.0             260.0        275.0
   P1   control/R1/Welch/c2 577        363         90        145   128          181           0.629       False             633.0             157.0             253.0        223.0
   P1 control/R2/Student/c1 577        393         93        149   151          202           0.681       False             685.0             162.0             260.0        263.0
   P1 control/R2/Student/c2 577        365         87        146   132          194           0.633       False             636.0             152.0             255.0        230.0
   P1   control/R2/Welch/c1 577        399         90        150   159          202           0.692       False             696.0             157.0             262.0        277.0
   P1   control/R2/Welch/c2 577        370         91        152   127          192           0.641       False             645.0             159.0             265.0        221.0
   P1     all/R1/Student/c1 577        413         95        146   172          213           0.716       False             720.0             166.0             255.0        300.0
   P1     all/R1/Student/c2 577        360         93        142   125          182           0.624       False             628.0             162.0             248.0        218.0
   P1       all/R1/Welch/c1 577        411         90        149   172          210           0.712       False             717.0             157.0             260.0        300.0
   P1       all/R1/Welch/c2 577        367         94        144   129          183           0.636       False             640.0             164.0             251.0        225.0
   P1     all/R2/Student/c1 577        417         98        150   169          214           0.723       False             727.0             171.0             262.0        295.0
   P1     all/R2/Student/c2 577        367         91        149   127          192           0.636       False             640.0             159.0             260.0        221.0
   P1       all/R2/Welch/c1 577        410         95        148   167          209           0.711       False             715.0             166.0             258.0        291.0
   P1       all/R2/Welch/c2 577        373         93        150   130          192           0.646       False             650.0             162.0             262.0        227.0
   P2 control/R1/Student/c1 810        571        132        222   217          297           0.705       False             709.0             164.0             276.0        270.0
   P2 control/R1/Student/c2 810        517        128        203   186          272           0.638       False             642.0             159.0             252.0        231.0
   P2   control/R1/Welch/c1 810        571        129        218   224          296           0.705       False             709.0             160.0             271.0        278.0
   P2   control/R1/Welch/c2 810        521        129        206   186          274           0.643       False             647.0             160.0             256.0        231.0
   P2 control/R2/Student/c1 810        565        127        216   222          298           0.698       False             702.0             158.0             268.0        276.0
   P2 control/R2/Student/c2 810        519        124        205   190          279           0.641       False             645.0             154.0             255.0        236.0
   P2   control/R2/Welch/c1 810        572        126        219   227          302           0.706       False             710.0             156.0             272.0        282.0
   P2   control/R2/Welch/c2 810        526        126        211   189          281           0.649       False             653.0             156.0             262.0        235.0
   P2     all/R1/Student/c1 810        589        133        207   249          318           0.727       False             732.0             165.0             257.0        309.0
   P2     all/R1/Student/c2 810        514        131        199   184          272           0.635       False             638.0             163.0             247.0        229.0
   P2       all/R1/Welch/c1 810        586        126        213   247          313           0.723       False             728.0             156.0             265.0        307.0
   P2       all/R1/Welch/c2 810        521        127        208   186          275           0.643       False             647.0             158.0             258.0        231.0
   P2     all/R2/Student/c1 810        594        134        212   248          320           0.733       False             738.0             166.0             263.0        308.0
   P2     all/R2/Student/c2 810        523        129        208   186          284           0.646       False             650.0             160.0             258.0        231.0
   P2       all/R2/Welch/c1 810        587        130        214   243          313           0.725       False             729.0             161.0             266.0        302.0
   P2       all/R2/Welch/c2 810        528        126        215   187          285           0.652       False             656.0             156.0             267.0        232.0
Paper: 704/1006 selective (0.70), 145 prep only, 272 peri only, 287 both
Readings with all four counts within tolerance: 0 of 32

By mouse (control/R1/Student/c1, P2):
                              n  selective
genotype       subject                    
Ai32 x PV-Cre  anm00261335   29      0.690
               anm00264941    6      0.833
               anm00264942   76      0.803
               anm00264943  130      0.685
               anm00264944   86      0.674
               anm00267975  108      0.657
               anm00279338   91      0.451
VGAT-ChR2-EYFP anm00322805   69      0.812
               anm00322807  165      0.782
               anm00323634   50      0.820

Result: not reproduced. With the file labels (P2, 810 units) and the first selectivity reading, 571 units (70.5%) are selective against 70% in the paper: 132 preparatory only, 222 peri-movement only and 217 both, which scaled to 1006 units give 164, 276 and 270 against 145, 272 and 287. The selective fraction ranges from 0.62 to 0.73 over all 32 readings. No reading puts the four counts within tolerance, because the dandiset holds 810 (P2) or 577 (P1) putative pyramidal units against the paper's 1006.

The criterion has no partial clause, and no reading meets it in full (see Changes of outcome, before the Summary). The third verification round agreed.

fig2e-alm-contra-ipsi-balance¶

Approximately equal numbers of selective ALM neurons preferred contra and ipsi movements.

Readings: (a) two-sided binomial test of the contra count against one half does not reject at p < 0.05; (b) the contra fraction lies within 0.45 to 0.55. Under each reading of fig2e-alm-selectivity.

In [14]:
bal = f2e[["units", "reading", "selective", "contra_pref"]].copy()
bal["contra_frac"] = (bal.contra_pref / bal.selective).round(3)
bal["binom_p"] = [stats.binomtest(int(c), int(n), 0.5).pvalue for c, n in zip(bal.contra_pref, bal.selective)]
bal["a_binomial_holds"] = bal.binom_p >= 0.05
bal["b_fraction_holds"] = bal.contra_frac.between(0.45, 0.55)
print(bal.round(4).to_string(index=False))
print("Readings where (a) holds:", int(bal.a_binomial_holds.sum()), "| (b) holds:", int(bal.b_fraction_holds.sum()), "| of", len(bal))
print("Contra fraction range:", bal.contra_frac.min(), "to", bal.contra_frac.max())
units               reading  selective  contra_pref  contra_frac  binom_p  a_binomial_holds  b_fraction_holds
   P1 control/R1/Student/c1        398          201        0.505   0.8805              True              True
   P1 control/R1/Student/c2        360          183        0.508   0.7922              True              True
   P1   control/R1/Welch/c1        398          197        0.495   0.8805              True              True
   P1   control/R1/Welch/c2        363          181        0.499   1.0000              True              True
   P1 control/R2/Student/c1        393          202        0.514   0.6140              True              True
   P1 control/R2/Student/c2        365          194        0.532   0.2495              True              True
   P1   control/R2/Welch/c1        399          202        0.506   0.8413              True              True
   P1   control/R2/Welch/c2        370          192        0.519   0.4992              True              True
   P1     all/R1/Student/c1        413          213        0.516   0.5549              True              True
   P1     all/R1/Student/c2        360          182        0.506   0.8744              True              True
   P1       all/R1/Welch/c1        411          210        0.511   0.6932              True              True
   P1       all/R1/Welch/c2        367          183        0.499   1.0000              True              True
   P1     all/R2/Student/c1        417          214        0.513   0.6244              True              True
   P1     all/R2/Student/c2        367          192        0.523   0.4036              True              True
   P1       all/R2/Welch/c1        410          209        0.510   0.7296              True              True
   P1       all/R2/Welch/c2        373          192        0.515   0.6047              True              True
   P2 control/R1/Student/c1        571          297        0.520   0.3572              True              True
   P2 control/R1/Student/c2        517          272        0.526   0.2528              True              True
   P2   control/R1/Welch/c1        571          296        0.518   0.4026              True              True
   P2   control/R1/Welch/c2        521          274        0.526   0.2546              True              True
   P2 control/R2/Student/c1        565          298        0.527   0.2069              True              True
   P2 control/R2/Student/c2        519          279        0.538   0.0952              True              True
   P2   control/R2/Welch/c1        572          302        0.528   0.1949              True              True
   P2   control/R2/Welch/c2        526          281        0.534   0.1269              True              True
   P2     all/R1/Student/c1        589          318        0.540   0.0579              True              True
   P2     all/R1/Student/c2        514          272        0.529   0.2008              True              True
   P2       all/R1/Welch/c1        586          313        0.534   0.1071              True              True
   P2       all/R1/Welch/c2        521          275        0.528   0.2199              True              True
   P2     all/R2/Student/c1        594          320        0.539   0.0647              True              True
   P2     all/R2/Student/c2        523          284        0.543   0.0543              True              True
   P2       all/R2/Welch/c1        587          313        0.533   0.1167              True              True
   P2       all/R2/Welch/c2        528          285        0.540   0.0743              True              True
Readings where (a) holds: 32 | (b) holds: 32 | of 32
Contra fraction range: 0.495 to 0.543

Result: reproduced. Under all 32 readings the contra-preferring fraction of selective ALM neurons is 0.495 to 0.543, and the binomial test does not reject one half: both readings of the criterion hold in 32 of 32.

thalamus-unit-classes¶

Of 790 thalamic units, 672 were putative thalamic neurons (spike width > 0.5 ms) and 313 lay within 0.4 mm of the VM/VAL centre; 295 VM/VAL units were analysed.

In [15]:
near = thal.vmval_d < 0.4
print("Thalamic units:", len(thal), "(paper 790 +/- 79)")
for p, d in THP.items():
    print(f"{p}: putative thalamic {len(d)} (paper 672 +/- 67); within 0.4 mm (L2), all units {int(near.sum())} (paper 313 +/- 31);"
          f" putative and within 0.4 mm {len(VMVAL[p])} (paper 295 +/- 30)")
print("L1: thalamic location labels in the files:", Counter(s["meta"]["eg_location"].get("brain_subregion") for s in sessions if s["meta"]["region"] == "Thalamus"))
print("\nDistance from the L2 centre (mm), all thalamic units: quantiles 0/10/50/90/100%",
      np.round(np.percentile(thal.vmval_d, [0, 10, 50, 90, 100]), 2))
print("Units within 0.4, 0.5, 0.6, 0.8, 1.0 mm:", [int((thal.vmval_d < r).sum()) for r in (0.4, 0.5, 0.6, 0.8, 1.0)])
print("By group (genotype, all units / within 0.4 mm):")
print(thal.assign(near=near).groupby("genotype").agg(units=("near", "size"), within_04=("near", "sum")).to_string())
print("Computed width of thalamic units (ms):", thal.width_ms.round(2).value_counts().sort_index().to_dict())
Thalamic units: 789 (paper 790 +/- 79)
P1: putative thalamic 148 (paper 672 +/- 67); within 0.4 mm (L2), all units 259 (paper 313 +/- 31); putative and within 0.4 mm 20 (paper 295 +/- 30)
P2: putative thalamic 682 (paper 672 +/- 67); within 0.4 mm (L2), all units 259 (paper 313 +/- 31); putative and within 0.4 mm 222 (paper 295 +/- 30)
L1: thalamic location labels in the files: Counter({'N/A': 72})

Distance from the L2 centre (mm), all thalamic units: quantiles 0/10/50/90/100% [0.02 0.22 0.5  1.08 1.66]
Units within 0.4, 0.5, 0.6, 0.8, 1.0 mm: [259, 383, 476, 612, 675]
By group (genotype, all units / within 0.4 mm):
                  units  within_04
genotype                          
Ai32 x PV-Cre       451        205
Ai35D x GAD2_Cre     84         15
C57BL6              104         39
VGAT-ChR2-EYFP      150          0
Computed width of thalamic units (ms): {0.08: 2, 0.12: 7, 0.16: 3, 0.2: 10, 0.24: 20, 0.28: 7, 0.32: 38, 0.36: 94, 0.4: 49, 0.44: 226, 0.48: 185, 0.52: 52, 0.56: 32, 0.6: 40, 0.64: 9, 0.68: 15}

Result: not reproduced. The dandiset holds 789 thalamic units (paper 790) and, by file label (P2), 682 putative thalamic units (paper 672 +/- 67). The location counts are below tolerance: 259 units lie within 0.4 mm of the L2 centre (313 +/- 31) and 222 putative units among them (295 +/- 30). The files have no VM/VAL label (reading L1), and the L2 centre is a proxy. By computed width (P1) only 148 units exceed 0.5 ms, an effect of the short waveforms.

The criterion has no partial clause, and no reading meets it in full (see Changes of outcome, before the Summary). The third verification round agreed.

fig2f-vmval-selectivity¶

A majority of VM/VAL neurons (69%, 204/295) distinguished trial types, a fraction indistinguishable from ALM; 43 had preparatory activity only, 82 peri-movement selectivity only and 79 both, a distribution similar to ALM.

VM/VAL units of thalamus-unit-classes (L2), under every selectivity reading and P1, P2, and P3 (all VM/VAL units, compared with ALM P1 and P2). Chi-squared tests against ALM pyramidal units under the same readings: 2 x 2 (selective or not), and for the types (i) 2 x 4 with non-selective as a class, (ii) 2 x 3 among selective neurons.

In [16]:
rows = []
for p, pa in (("P1", "P1"), ("P2", "P2"), ("P3", "P1"), ("P3", "P2")):
    for k in SEL:
        v, a = sel_counts(VM26[p].index, k), sel_counts(PYR[pa].index, k)
        chi_sel = stats.chi2_contingency([[v["selective"], v["n"] - v["selective"]], [a["selective"], a["n"] - a["selective"]]])[1]
        t4 = [[v["prep_only"], v["peri_only"], v["both"], v["n"] - v["selective"]], [a["prep_only"], a["peri_only"], a["both"], a["n"] - a["selective"]]]
        chi4 = stats.chi2_contingency(t4)[1]
        chi3 = stats.chi2_contingency([r[:3] for r in t4])[1]
        rows.append({"units": p, "alm_units": pa, "reading": k, **{x: v[x] for x in ("n", "selective", "prep_only", "peri_only", "both")},
                     "frac": round(v["selective"] / v["n"], 3), "alm_frac": round(a["selective"] / a["n"], 3),
                     "p_chi_selective": chi_sel, "p_chi_2x4": chi4, "p_chi_2x3": chi3})
f2f = pd.DataFrame(rows)
f2f["counts_within_tol"] = ((f2f.selective - 204).abs() <= 20) & ((f2f.prep_only - 43).abs() <= 4.3) & \
    ((f2f.peri_only - 82).abs() <= 8.2) & ((f2f.both - 79).abs() <= 7.9)
f2f["chi_ok_i"] = (f2f.p_chi_selective >= 0.05) & (f2f.p_chi_2x4 >= 0.05)
f2f["chi_ok_ii"] = (f2f.p_chi_selective >= 0.05) & (f2f.p_chi_2x3 >= 0.05)
print(f2f.round(4).to_string(index=False))
print("Paper: 204/295 (0.69), 43, 82, 79; chi-squared p = 0.79 (fraction), p > 0.5 (types)")
print("Readings with counts within tolerance:", int(f2f.counts_within_tol.sum()), "| with both chi-squared tests p >= 0.05 (i):",
      int(f2f.chi_ok_i.sum()), "(ii):", int(f2f.chi_ok_ii.sum()), "| all of counts and (i) or (ii):",
      int((f2f.counts_within_tol & (f2f.chi_ok_i | f2f.chi_ok_ii)).sum()), "of", len(f2f))
print("\nBy VM/VAL unit reading (ALM reading in brackets): selective fraction range, readings with counts within tolerance,"
      " readings with the 2 x 2 test p >= 0.05, with (i) and with (ii) holding")
print(f2f.groupby(["units", "alm_units"]).agg(frac_min=("frac", "min"), frac_max=("frac", "max"), n=("n", "first"),
                                             counts_ok=("counts_within_tol", "sum"), chi_sel_ok=("p_chi_selective", lambda x: int((x >= 0.05).sum())),
                                             ok_i=("chi_ok_i", "sum"), ok_ii=("chi_ok_ii", "sum"), readings=("frac", "size")).to_string())
print("Scaled to 295 units: selective", (f2f.selective * 295 / f2f.n).round(0).min(), "to", (f2f.selective * 295 / f2f.n).round(0).max())
units alm_units               reading   n  selective  prep_only  peri_only  both  frac  alm_frac  p_chi_selective  p_chi_2x4  p_chi_2x3  counts_within_tol  chi_ok_i  chi_ok_ii
   P1        P1 control/R1/Student/c1  20         13          3          7     3 0.650     0.690           0.8950     0.6805     0.4860              False      True       True
   P1        P1 control/R1/Student/c2  20         14          3          7     4 0.700     0.624           0.6481     0.7477     0.7158              False      True       True
   P1        P1   control/R1/Welch/c1  20         14          4          7     3 0.700     0.690           1.0000     0.5837     0.3848              False      True       True
   P1        P1   control/R1/Welch/c2  20         14          3          7     4 0.700     0.629           0.6816     0.7893     0.7512              False      True       True
   P1        P1 control/R2/Student/c1  20         14          3          8     3 0.700     0.681           1.0000     0.4846     0.3079              False      True       True
   P1        P1 control/R2/Student/c2  20         12          2          5     5 0.600     0.633           0.9512     0.9343     0.8362              False      True       True
   P1        P1   control/R2/Welch/c1  20         15          4          8     3 0.750     0.692           0.7557     0.3902     0.2863              False      True       True
   P1        P1   control/R2/Welch/c2  20         12          2          5     5 0.600     0.641           0.8880     0.8973     0.7857              False      True       True
   P1        P1     all/R1/Student/c1  20         15          3          6     6 0.750     0.716           0.9350     0.9650     0.9257              False      True       True
   P1        P1     all/R1/Student/c2  20         12          2          4     6 0.600     0.624           1.0000     0.7377     0.5320              False      True       True
   P1        P1       all/R1/Welch/c1  20         15          3          6     6 0.750     0.712           0.9084     0.9725     0.9553              False      True       True
   P1        P1       all/R1/Welch/c2  20         12          2          4     6 0.600     0.636           0.9259     0.7445     0.5515              False      True       True
   P1        P1     all/R2/Student/c1  20         14          2          5     7 0.700     0.723           1.0000     0.8447     0.6724              False      True       True
   P1        P1     all/R2/Student/c2  20         12          2          4     6 0.600     0.636           0.9259     0.7311     0.5353              False      True       True
   P1        P1       all/R2/Welch/c1  20         14          2          5     7 0.700     0.711           1.0000     0.8611     0.6869              False      True       True
   P1        P1       all/R2/Welch/c2  20         12          2          4     6 0.600     0.646           0.8500     0.7256     0.5448              False      True       True
   P2        P2 control/R1/Student/c1 222        149         38         75    36 0.671     0.705           0.3745     0.0110     0.0053              False     False      False
   P2        P2 control/R1/Student/c2 222        133         44         65    24 0.599     0.638           0.3210     0.0010     0.0004              False     False      False
   P2        P2   control/R1/Welch/c1 222        149         39         75    35 0.671     0.705           0.3745     0.0034     0.0014              False     False      False
   P2        P2   control/R1/Welch/c2 222        132         43         65    24 0.595     0.643           0.2103     0.0011     0.0006              False     False      False
   P2        P2 control/R2/Student/c1 222        150         38         76    36 0.676     0.698           0.5870     0.0052     0.0018              False     False      False
   P2        P2 control/R2/Student/c2 222        133         45         65    23 0.599     0.641           0.2886     0.0003     0.0001              False     False      False
   P2        P2   control/R2/Welch/c1 222        150         39         76    35 0.676     0.706           0.4263     0.0023     0.0009              False     False      False
   P2        P2   control/R2/Welch/c2 222        130         43         63    24 0.586     0.649           0.0947     0.0007     0.0006              False     False      False
   P2        P2     all/R1/Student/c1 222        149         35         74    40 0.671     0.727           0.1203     0.0012     0.0010              False     False      False
   P2        P2     all/R1/Student/c2 222        138         46         66    26 0.622     0.635           0.7827     0.0025     0.0007              False     False      False
   P2        P2       all/R1/Welch/c1 222        150         35         75    40 0.676     0.723           0.1899     0.0021     0.0014              False     False      False
   P2        P2       all/R1/Welch/c2 222        138         46         66    26 0.622     0.643           0.6070     0.0021     0.0007              False     False      False
   P2        P2     all/R2/Student/c1 222        150         35         75    40 0.676     0.733           0.1069     0.0013     0.0012              False     False      False
   P2        P2     all/R2/Student/c2 222        138         46         66    26 0.622     0.646           0.5600     0.0023     0.0008              False     False      False
   P2        P2       all/R2/Welch/c1 222        151         35         76    40 0.680     0.725           0.2233     0.0027     0.0016              False     False      False
   P2        P2       all/R2/Welch/c2 222        139         47         67    25 0.626     0.652           0.5280     0.0010     0.0003              False     False      False
   P3        P1 control/R1/Student/c1 259        174         40         89    45 0.672     0.690           0.6627     0.0242     0.0098              False     False      False
   P3        P1 control/R1/Student/c2 259        162         48         79    35 0.625     0.624           1.0000     0.0144     0.0051              False     False      False
   P3        P1   control/R1/Welch/c1 259        174         41         88    45 0.672     0.690           0.6627     0.0083     0.0030              False     False      False
   P3        P1   control/R1/Welch/c2 259        161         47         79    35 0.622     0.629           0.8967     0.0228     0.0084              False     False      False
   P3        P1 control/R2/Student/c1 259        175         40         90    45 0.676     0.681           0.9398     0.0120     0.0042              False     False      False
   P3        P1 control/R2/Student/c2 259        159         49         76    34 0.614     0.633           0.6606     0.0096     0.0035              False     False      False
   P3        P1   control/R2/Welch/c1 259        176         42         90    44 0.680     0.692           0.7912     0.0044     0.0014              False     False      False
   P3        P1   control/R2/Welch/c2 259        156         47         74    35 0.602     0.641           0.3172     0.0397     0.0254              False     False      False
   P3        P1     all/R1/Student/c1 259        175         37         87    51 0.676     0.716           0.2749     0.0052     0.0029              False     False      False
   P3        P1     all/R1/Student/c2 259        166         50         80    36 0.641     0.624           0.6940     0.0239     0.0104              False     False      False
   P3        P1       all/R1/Welch/c1 259        176         37         87    52 0.680     0.712           0.3809     0.0118     0.0059              False     False      False
   P3        P1       all/R1/Welch/c2 259        166         50         80    36 0.641     0.636           0.9538     0.0205     0.0077              False     False      False
   P3        P1     all/R2/Student/c1 259        176         37         88    51 0.680     0.723           0.2346     0.0067     0.0044              False     False      False
   P3        P1     all/R2/Student/c2 259        164         50         78    36 0.633     0.636           0.9990     0.0356     0.0137              False     False      False
   P3        P1       all/R2/Welch/c1 259        177         37         88    52 0.683     0.711           0.4760     0.0132     0.0059              False     False      False
   P3        P1       all/R2/Welch/c2 259        165         51         79    35 0.637     0.646           0.8542     0.0181     0.0066              False     False      False
   P3        P2 control/R1/Student/c1 259        174         40         89    45 0.672     0.705           0.3513     0.0109     0.0055              False     False      False
   P3        P2 control/R1/Student/c2 259        162         48         79    35 0.625     0.638           0.7657     0.0087     0.0030              False     False      False
   P3        P2   control/R1/Welch/c1 259        174         41         88    45 0.672     0.705           0.3513     0.0062     0.0030              False     False      False
   P3        P2   control/R1/Welch/c2 259        161         47         79    35 0.622     0.643           0.5789     0.0106     0.0041              False     False      False
   P3        P2 control/R2/Student/c1 259        175         40         90    45 0.676     0.698           0.5579     0.0053     0.0020              False     False      False
   P3        P2 control/R2/Student/c2 259        159         49         76    34 0.614     0.641           0.4798     0.0043     0.0016              False     False      False
   P3        P2   control/R2/Welch/c1 259        176         42         90    44 0.680     0.706           0.4616     0.0029     0.0011              False     False      False
   P3        P2   control/R2/Welch/c2 259        156         47         74    35 0.602     0.649           0.1944     0.0092     0.0067              False     False      False
   P3        P2     all/R1/Student/c1 259        175         37         87    51 0.676     0.727           0.1290     0.0014     0.0012              False     False      False
   P3        P2     all/R1/Student/c2 259        166         50         80    36 0.641     0.635           0.9116     0.0090     0.0032              False     False      False
   P3        P2       all/R1/Welch/c1 259        176         37         87    52 0.680     0.723           0.2002     0.0049     0.0034              False     False      False
   P3        P2       all/R1/Welch/c2 259        166         50         80    36 0.641     0.643           1.0000     0.0102     0.0035              False     False      False
   P3        P2     all/R2/Student/c1 259        176         37         88    51 0.680     0.733           0.1097     0.0016     0.0015              False     False      False
   P3        P2     all/R2/Student/c2 259        164         50         78    36 0.633     0.646           0.7717     0.0139     0.0050              False     False      False
   P3        P2       all/R2/Welch/c1 259        177         37         88    52 0.683     0.725           0.2294     0.0058     0.0036              False     False      False
   P3        P2       all/R2/Welch/c2 259        165         51         79    35 0.637     0.652           0.7196     0.0076     0.0026              False     False      False
Paper: 204/295 (0.69), 43, 82, 79; chi-squared p = 0.79 (fraction), p > 0.5 (types)
Readings with counts within tolerance: 0 | with both chi-squared tests p >= 0.05 (i): 16 (ii): 16 | all of counts and (i) or (ii): 0 of 64

By VM/VAL unit reading (ALM reading in brackets): selective fraction range, readings with counts within tolerance, readings with the 2 x 2 test p >= 0.05, with (i) and with (ii) holding
                 frac_min  frac_max    n  counts_ok  chi_sel_ok  ok_i  ok_ii  readings
units alm_units                                                                       
P1    P1            0.600     0.750   20          0          16    16     16        16
P2    P2            0.586     0.680  222          0          16     0      0        16
P3    P1            0.602     0.683  259          0          16     0      0        16
      P2            0.602     0.683  259          0          16     0      0        16
Scaled to 295 units: selective 173.0 to 221.0

Result: not reproduced. With P2, 149 of 222 VM/VAL units (67%) are selective under the first reading (paper 204/295, 69%), and the fraction does not differ from ALM's 70.5% (chi-squared p = 0.37). The selectivity types differ from ALM in all 16 P2 readings (both type tests p < 0.05; first reading 38 preparatory only, 75 peri-movement only, 36 both, p = 0.011 and 0.0053), where the paper finds p > 0.5. With P3 (all 259 VM/VAL units), 174 are selective under the first reading (67%; 156 to 177 over the readings, below 204 +/- 20), the fraction does not differ from ALM in any reading, and the types differ from ALM in all 32 readings (first reading 40, 89, 45; p = 0.024 and 0.0098 against ALM P1). The counts are below tolerance in every reading; with P1 only 20 units qualify, and their types do not differ from ALM. The selective fraction holds; the type distribution holds only on the 20 P1 units.

The criterion has no partial clause, and no reading meets it in full (see Changes of outcome, before the Summary). The third verification round agreed.

fig3-alm-collapse¶

Strong photoinhibition of thalALM (VGAT-ChR2-EYFP) decreased ALM activity to 6% of control, inhibiting 309 of 314 neurons (155 significantly) and significantly activating none.

ALM putative pyramidal units of the VGAT-ChR2-EYFP sessions (thalamus photostimulus, 10 mW, delay epoch), at least 5 photostimulus trials; 20 to 120 ms after onset; readings T1 (correct and incorrect) and T2 (correct only), Q1 to Q3, Student and Welch, P1 and P2. Variant, not part of the criterion: the ALM sessions of PV-Cre x Ai32 mice with thalamic photostimulation at 10 mW, which the answer of 2026-10-20 places outside Fig. 3.

In [17]:
T_READ = {"T1": ("correct", "incorrect"), "T2": ("correct",)}


def effect_table(sel_units, stims, window="pw", min_trials=5, extra=None):
    rows, keep = [], {}
    for p, d in sel_units.items():
        for tname, oc in T_READ.items():
            for ev in (True, False):
                df = loop.photo_effect(sessions, d, stims, oc, window, min_trials, ev)
                keep[(p, tname, ev)] = df
                rows.append({"units": p, "trials": tname, "test": "Student" if ev else "Welch", **loop.effect_counts(df),
                             **{k: round(v, 2) if isinstance(v, float) else v for k, v in loop.ratio_readings(df).items()},
                             "mice": d.loc[df.index].subject.nunique()})
    return pd.DataFrame(rows), keep


vg_alm = {p: d[d.genotype == "VGAT-ChR2-EYFP"] for p, d in PYR.items()}
f3, F3 = effect_table(vg_alm, "Thalamus:delay:10")
for q in ("Q1", "Q2", "Q3"):
    f3[f"within_tol_{q}"] = ((f3[q] - 6).abs() <= 0.6) & ((f3.n - 314).abs() <= 31) & ((f3.inhibited - 309).abs() <= 31) & \
        ((f3.activated - 3).abs() <= 0.3) & ((f3.sig_inhibited - 155).abs() <= 16) & (f3.sig_activated == 0)
print(f3.to_string(index=False))
print("Paper: 6% of control; 314 neurons, 309 inhibited, 3 activated, 155 significantly inhibited, 0 significantly activated")
print("Readings within tolerance on all values:", int(f3[[c for c in f3 if c.startswith("within_tol")]].any(axis=1).sum()), "of", len(f3))
print("Partial condition (activity falls, inhibited > activated, none significantly activated) in every reading:",
      bool(((f3.Q1 < 100) & (f3.inhibited > f3.activated) & (f3.sig_activated == 0)).all()))
d = F3[("P2", "T1", True)].join(units[["subject"]])
print("\nBy mouse (P2, T1, Student):")
print(d.groupby("subject").agg(n=("delta", "size"), inhibited=("delta", lambda x: int((x < 0).sum())),
                               rate_ctrl=("rate_ctrl", "mean"), rate_pi=("rate_pi", "mean")).round(2).to_string())
pv_alm = {p: d[(d.genotype == "Ai32 x PV-Cre") & (d.ogen_site == "Thalamus")] for p, d in PYR.items()}
v3, _ = effect_table(pv_alm, "Thalamus:delay:10")
print("\nVariant, PV-Cre x Ai32 ALM sessions with thalamic photostimulation at 10 mW:")
print(v3.to_string(index=False))
both = {p: pd.concat([vg_alm[p], pv_alm[p]]) for p in PYR}
v3b, _ = effect_table(both, "Thalamus:delay:10")
print("Variant, VGAT and PV-Cre x Ai32 together at 10 mW:")
print(v3b.to_string(index=False))
units trials    test   n  inhibited  activated  unchanged  sig_inhibited  sig_activated       Q1       Q2  Q3  n_ratio_undefined  mice  within_tol_Q1  within_tol_Q2  within_tol_Q3
   P1     T1 Student 234        230          2          2            109              0 2.368752 5.211661 0.0                  2     3          False          False          False
   P1     T1   Welch 234        230          2          2            186              0 2.368752 5.211661 0.0                  2     3          False          False          False
   P1     T2 Student 230        222          4          4             75              0 2.466225 5.241414 0.0                  4     3          False          False          False
   P1     T2   Welch 230        222          4          4            171              0 2.466225 5.241414 0.0                  4     3          False          False          False
   P2     T1 Student 261        256          2          3            127              0 2.147048 5.050987 0.0                  3     3          False          False          False
   P2     T1   Welch 261        256          2          3            208              0 2.147048 5.050987 0.0                  3     3          False          False          False
   P2     T2 Student 256        247          4          5             86              0 2.289574 5.090505 0.0                  5     3          False          False          False
   P2     T2   Welch 256        247          4          5            194              0 2.289574 5.090505 0.0                  5     3          False          False          False
Paper: 6% of control; 314 neurons, 309 inhibited, 3 activated, 155 significantly inhibited, 0 significantly activated
Readings within tolerance on all values: 0 of 8
Partial condition (activity falls, inhibited > activated, none significantly activated) in every reading: True

By mouse (P2, T1, Student):
               n  inhibited  rate_ctrl  rate_pi
subject                                        
anm00322805   69         67       5.26     0.13
anm00322807  142        139       4.04     0.04
anm00323634   50         50       2.92     0.17
Variant, PV-Cre x Ai32 ALM sessions with thalamic photostimulation at 10 mW:
units trials    test   n  inhibited  activated  unchanged  sig_inhibited  sig_activated    Q1    Q2  Q3  n_ratio_undefined  mice
   P1     T1 Student 233        196         21         16             50              4 21.25 89.63 0.0                 16     4
   P1     T1   Welch 233        196         21         16            157              3 21.25 89.63 0.0                 16     4
   P1     T2 Student 130        115          4         11             15              2 12.89 26.01 0.0                 11     3
   P1     T2   Welch 130        115          4         11             88              1 12.89 26.01 0.0                 11     3
   P2     T1 Student 261        221         24         16             64              7 21.65 84.98 0.0                 16     4
   P2     T1   Welch 261        221         24         16            181              5 21.65 84.98 0.0                 16     4
   P2     T2 Student 149        132          6         11             23              4 15.77 27.88 0.0                 11     3
   P2     T2   Welch 149        132          6         11            102              3 15.77 27.88 0.0                 11     3
Variant, VGAT and PV-Cre x Ai32 together at 10 mW:
units trials    test   n  inhibited  activated  unchanged  sig_inhibited  sig_activated    Q1    Q2  Q3  n_ratio_undefined  mice
   P1     T1 Student 467        426         23         18            159              4 10.71 46.01 0.0                 18     7
   P1     T1   Welch 467        426         23         18            343              3 10.71 46.01 0.0                 18     7
   P1     T2 Student 360        337          8         15             90              2  5.48 12.41 0.0                 15     6
   P1     T2   Welch 360        337          8         15            259              1  5.48 12.41 0.0                 15     6
   P2     T1 Student 522        477         26         19            191              7 11.08 43.98 0.0                 19     7
   P2     T1   Welch 522        477         26         19            389              5 11.08 43.98 0.0                 19     7
   P2     T2 Student 405        379         10         16            109              4  6.54 13.17 0.0                 16     6
   P2     T2   Welch 405        379         10         16            296              3  6.54 13.17 0.0                 16     6

Result: partially reproduced. In 261 VGAT ALM putative pyramidal units (P2; 234 with P1) from 3 mice, thalamus photoinhibition lowers activity to 2.1 to 2.5% (Q1) or 5.1 to 5.2% (Q2) of control, against 6 +/- 0.6%. With P2 and correct and incorrect trials, 256 of 261 units are inhibited, 2 activated, 127 (Student) or 208 (Welch) significantly inhibited and none significantly activated. The number of units (230 to 261) is below 314 +/- 31, and no reading puts all values within tolerance. The criterion's partial condition (activity falls, inhibited outnumber activated, none significantly activated) holds in every reading. In the variant with the PV-Cre x Ai32 sessions at 10 mW, activity falls to 21.7% (P2, T1) and 7 units are significantly activated.

fig3d-all-layers¶

Thalamus photoinhibition reduced ALM activity across all cortical layers.

Units of fig3-alm-collapse; depth is -unit_y (mm). Bins (a) 100 um, (b) 200 um; modulated (m1) by the sign of the change, (m2) significant by convention P. Per bin, inhibited against activated neurons, and the population rate ratio.

In [18]:
rows = []
for p in ("P1", "P2"):
    for tname in T_READ:
        for mod, ev in (("m1", True), ("m2 Student", True), ("m2 Welch", False)):
            df = F3[(p, tname, ev)].join(units[["dv"]])
            depth = -df.dv * 1000
            for bw in (100, 200):
                b = (depth // bw * bw).astype(int)
                for lo, g in df.groupby(b):
                    sel = g.sig if mod != "m1" else np.ones(len(g), bool)
                    inh, act = int(((g.delta < 0) & sel).sum()), int(((g.delta > 0) & sel).sum())
                    rows.append({"units": p, "trials": tname, "bin_um": bw, "modulated": mod, "depth_from_um": lo, "neurons": len(g),
                                 "inhibited": inh, "activated": act, "rate_ratio": round(g.rate_pi.mean() / g.rate_ctrl.mean(), 3)})
f3d = pd.DataFrame(rows)
f3d["inh_gt_act"] = f3d.inhibited > f3d.activated
summary = f3d.groupby(["units", "trials", "bin_um", "modulated"]).agg(bins=("neurons", "size"), bins_ok=("inh_gt_act", "sum"),
                                                                   max_ratio=("rate_ratio", "max")).reset_index()
print(summary.to_string(index=False))
print("\nBins where inhibited do not outnumber activated:")
print(f3d[~f3d.inh_gt_act].to_string(index=False))
print("Depth (-unit_y, um) of these units: range", int(-units.loc[F3[("P2", "T1", True)].index].dv.max() * 1000), "to",
      int(-units.loc[F3[("P2", "T1", True)].index].dv.min() * 1000))
print("\nPer 100 um bin (P2, T1, m1):")
print(f3d[(f3d.units == "P2") & (f3d.trials == "T1") & (f3d.bin_um == 100) & (f3d.modulated == "m1")].to_string(index=False))
units trials  bin_um  modulated  bins  bins_ok  max_ratio
   P1     T1     100         m1    12       12      0.205
   P1     T1     100 m2 Student    12       10      0.205
   P1     T1     100   m2 Welch    12       11      0.205
   P1     T1     200         m1     7        7      0.205
   P1     T1     200 m2 Student     7        6      0.205
   P1     T1     200   m2 Welch     7        6      0.205
   P1     T2     100         m1    12       12      0.163
   P1     T2     100 m2 Student    12        9      0.163
   P1     T2     100   m2 Welch    12       11      0.163
   P1     T2     200         m1     7        7      0.163
   P1     T2     200 m2 Student     7        5      0.163
   P1     T2     200   m2 Welch     7        6      0.163
   P2     T1     100         m1    12       12      0.205
   P2     T1     100 m2 Student    12       10      0.205
   P2     T1     100   m2 Welch    12       11      0.205
   P2     T1     200         m1     7        7      0.205
   P2     T1     200 m2 Student     7        6      0.205
   P2     T1     200   m2 Welch     7        6      0.205
   P2     T2     100         m1    12       12      0.163
   P2     T2     100 m2 Student    12        9      0.163
   P2     T2     100   m2 Welch    12       11      0.163
   P2     T2     200         m1     7        7      0.163
   P2     T2     200 m2 Student     7        5      0.163
   P2     T2     200   m2 Welch     7        6      0.163

Bins where inhibited do not outnumber activated:
units trials  bin_um  modulated  depth_from_um  neurons  inhibited  activated  rate_ratio  inh_gt_act
   P1     T1     100 m2 Student           1100        1          0          0       0.000       False
   P1     T1     100 m2 Student           1200        1          0          0       0.000       False
   P1     T1     200 m2 Student           1200        1          0          0       0.000       False
   P1     T1     100   m2 Welch           1200        1          0          0       0.000       False
   P1     T1     200   m2 Welch           1200        1          0          0       0.000       False
   P1     T2     100 m2 Student            100        4          0          0       0.163       False
   P1     T2     100 m2 Student           1100        1          0          0       0.000       False
   P1     T2     100 m2 Student           1200        1          0          0       0.000       False
   P1     T2     200 m2 Student              0        4          0          0       0.163       False
   P1     T2     200 m2 Student           1200        1          0          0       0.000       False
   P1     T2     100   m2 Welch           1200        1          0          0       0.000       False
   P1     T2     200   m2 Welch           1200        1          0          0       0.000       False
   P2     T1     100 m2 Student           1100        1          0          0       0.000       False
   P2     T1     100 m2 Student           1200        1          0          0       0.000       False
   P2     T1     200 m2 Student           1200        1          0          0       0.000       False
   P2     T1     100   m2 Welch           1200        1          0          0       0.000       False
   P2     T1     200   m2 Welch           1200        1          0          0       0.000       False
   P2     T2     100 m2 Student            100        4          0          0       0.163       False
   P2     T2     100 m2 Student           1100        1          0          0       0.000       False
   P2     T2     100 m2 Student           1200        1          0          0       0.000       False
   P2     T2     200 m2 Student              0        4          0          0       0.163       False
   P2     T2     200 m2 Student           1200        1          0          0       0.000       False
   P2     T2     100   m2 Welch           1200        1          0          0       0.000       False
   P2     T2     200   m2 Welch           1200        1          0          0       0.000       False
Depth (-unit_y, um) of these units: range 101 to 1212

Per 100 um bin (P2, T1, m1):
units trials  bin_um modulated  depth_from_um  neurons  inhibited  activated  rate_ratio  inh_gt_act
   P2     T1     100        m1            100        4          3          1       0.205        True
   P2     T1     100        m1            200       12         12          0       0.020        True
   P2     T1     100        m1            300       20         20          0       0.047        True
   P2     T1     100        m1            400       29         29          0       0.012        True
   P2     T1     100        m1            500       43         43          0       0.029        True
   P2     T1     100        m1            600       53         52          0       0.012        True
   P2     T1     100        m1            700       46         44          1       0.026        True
   P2     T1     100        m1            800       31         30          0       0.011        True
   P2     T1     100        m1            900       13         13          0       0.005        True
   P2     T1     100        m1           1000        8          8          0       0.026        True
   P2     T1     100        m1           1100        1          1          0       0.000        True
   P2     T1     100        m1           1200        1          1          0       0.000        True

Result: blocked (methods underspecified). Counting by the sign of the change (m1), inhibited neurons outnumber activated ones in every depth bin under every reading (12 of 12 bins of 100 um, 7 of 7 of 200 um), and the population rate under photoinhibition is at most 0.205 of control in any bin. Counting significant changes (m2), 1 to 3 bins fail with Student's test and 1 with Welch's, each holding 1 to 4 neurons with no significant change in either direction (0 against 0). The criterion asks every reading to agree, so the claim is blocked as it directs. The reduction itself is seen at every depth sampled (101 to 1212 um of -unit_y). The files describe unit_y only as "y-coordinate of this unit (mm)", so whether it is depth below the pia is not stated.

fig3b-selectivity-types-equally-inhibited¶

ALM neurons with preparatory activity, peri-movement selectivity or both were equally inhibited by thalamus photoinhibition.

A claim of absence, on the paper's test: two-sided t-tests between each pair of the three groups, measures (a) rate ratio and (b) rate difference, for the neurons of fig3-alm-collapse. Shown under every selectivity reading, both trial readings and P1, P2 (Student's t-test for the group comparison; Welch shown as a count).

In [19]:
rows = []
for p in ("P1", "P2"):
    for tname in T_READ:
        eff = F3[(p, tname, True)]
        for k in SEL:
            kind = SEL[k].loc[eff.index, "kind"]
            for meas in ("ratio", "delta"):
                g = {n: eff[meas][kind == n].dropna() for n in ("prep_only", "peri_only", "both")}
                ps = {f"{a}-{b}": stats.ttest_ind(g[a], g[b]).pvalue for a, b in (("prep_only", "peri_only"), ("prep_only", "both"), ("peri_only", "both"))}
                pw = [stats.ttest_ind(g[a], g[b], equal_var=False).pvalue for a, b in (("prep_only", "peri_only"), ("prep_only", "both"), ("peri_only", "both"))]
                rows.append({"units": p, "trials": tname, "sel_reading": k, "measure": meas, **{f"n_{n}": len(v) for n, v in g.items()},
                             **{f"mean_{n}": round(v.mean(), 3) for n, v in g.items()}, **{f"p_{a}": round(v, 4) for a, v in ps.items()},
                             "min_p": round(min(ps.values()), 4), "min_p_welch": round(min(pw), 4)})
f3b = pd.DataFrame(rows)
print(f3b[f3b.sel_reading == "control/R1/Student/c1"].to_string(index=False))
agg = f3b.groupby(["units", "trials", "measure"]).agg(readings=("min_p", "size"), any_pair_p_lt_05=("min_p", lambda x: int((x < 0.05).sum())),
                                                     min_p=("min_p", "min"), max_min_p=("min_p", "max"),
                                                     welch_lt_05=("min_p_welch", lambda x: int((x < 0.05).sum()))).reset_index()
print("\nOver the 16 selectivity readings:")
print(agg.to_string(index=False))
print("Readings (all combinations) where a pair differs at p < 0.05 under both measures:",
      int((f3b.pivot_table(index=["units", "trials", "sel_reading"], columns="measure", values="min_p") < 0.05).all(axis=1).sum()),
      "of", len(f3b) // 2)
units trials           sel_reading measure  n_prep_only  n_peri_only  n_both  mean_prep_only  mean_peri_only  mean_both  p_prep_only-peri_only  p_prep_only-both  p_peri_only-both  min_p  min_p_welch
   P1     T1 control/R1/Student/c1   ratio           51           49      81           0.133           0.042      0.023                 0.1266            0.0158            0.3636 0.0158       0.0527
   P1     T1 control/R1/Student/c1   delta           51           50      81          -4.291          -1.578     -7.035                 0.0050            0.0598            0.0000 0.0000       0.0000
   P1     T2 control/R1/Student/c1   ratio           49           48      81           0.132           0.048      0.023                 0.2678            0.0574            0.4035 0.0574       0.1276
   P1     T2 control/R1/Student/c1   delta           49           49      81          -4.293          -1.636     -7.096                 0.0075            0.0597            0.0000 0.0000       0.0000
   P2     T1 control/R1/Student/c1   ratio           53           54      99           0.128           0.045      0.024                 0.1380            0.0104            0.2652 0.0104       0.0550
   P2     T1 control/R1/Student/c1   delta           53           55      99          -4.447          -1.632     -6.811                 0.0027            0.0781            0.0000 0.0000       0.0000
   P2     T2 control/R1/Student/c1   ratio           50           53      99           0.129           0.056      0.019                 0.3142            0.0316            0.1696 0.0316       0.1130
   P2     T2 control/R1/Student/c1   delta           50           54      99          -4.546          -1.675     -6.834                 0.0032            0.0969            0.0000 0.0000       0.0000

Over the 16 selectivity readings:
units trials measure  readings  any_pair_p_lt_05  min_p  max_min_p  welch_lt_05
   P1     T1   delta        16                16 0.0000     0.0009           16
   P1     T1   ratio        16                 4 0.0158     0.4567            0
   P1     T2   delta        16                16 0.0000     0.0011           16
   P1     T2   ratio        16                 2 0.0244     0.6575            0
   P2     T1   delta        16                16 0.0000     0.0006           16
   P2     T1   ratio        16                 4 0.0104     0.5181            0
   P2     T2   delta        16                16 0.0000     0.0007           16
   P2     T2   ratio        16                 3 0.0196     0.7587            0
Readings (all combinations) where a pair differs at p < 0.05 under both measures: 13 of 64

Result: blocked (methods underspecified). Under the first selectivity reading both measures find a difference between groups: the rate difference (p < 0.0001 between peri-movement-only and both) and the rate ratio (p = 0.016 with P1, 0.010 with P2, T1). Over all readings the difference measure finds one in all 64 combinations and the ratio measure in 13, so the two measures disagree in most readings, which the criterion calls methods underspecified. No reading supports equal inhibition under the difference measure.

fig3f-thalamus-silenced¶

Strong photoinhibition in VGAT-ChR2-EYFP mice abolished thalALM activity nearly completely, to 2% of control.

Thalamic units of the VGAT-ChR2-EYFP thalamic sessions (thalamus photostimulus in the delay epoch; the files give 2.23 mW). Readings (a) all putative thalamic units, (b) those in VM/VAL (L2); 20 to 120 ms; T1, T2; Q1 to Q3. The session photostimulated in the sample epoch has no delay photostimulus trials and drops out under the 5-trial rule.

In [20]:
vg_th = {p: d[d.genotype == "VGAT-ChR2-EYFP"] for p, d in THP.items()}
vg_th_all = {"all units": thal[thal.genotype == "VGAT-ChR2-EYFP"]}
f3f, F3F = effect_table({**vg_th, **vg_th_all}, "Thalamus:delay:2.23")
for q in ("Q1", "Q2", "Q3"):
    f3f[f"within_tol_{q}"] = ((f3f[q] - 2).abs() <= 0.2) & ((f3f.n - 148).abs() <= 15)
print("(a) putative thalamic units (and all units):")
print(f3f.to_string(index=False))
print("(b) VM/VAL (L2): VGAT thalamic units within 0.4 mm of the centre:", int((vg_th_all["all units"].vmval_d < 0.4).sum()),
      "| distance range (mm):", round(vg_th_all["all units"].vmval_d.min(), 2), "to", round(vg_th_all["all units"].vmval_d.max(), 2))
print("Paper: 2% of control, n = 148")
print("Any reading within tolerance:", bool(f3f[[c for c in f3f if c.startswith("within_tol")]].any(axis=None)))
d = F3F[("all units", "T1", True)]
print("Ratio in the window 20-120 ms, all units T1, per unit: quantiles 10/50/90%", np.round(np.nanpercentile(d.ratio, [10, 50, 90]), 3),
      "| units", len(d), "| per mouse Q1:",
      {s: round(100 * g.rate_pi.mean() / g.rate_ctrl.mean(), 1) for s, g in d.join(units[["subject"]]).groupby("subject")})
(a) putative thalamic units (and all units):
    units trials    test   n  inhibited  activated  unchanged  sig_inhibited  sig_activated    Q1   Q2  Q3  n_ratio_undefined  mice  within_tol_Q1  within_tol_Q2  within_tol_Q3
       P1     T1 Student  93         93          0          0             83              0  1.11 1.40 0.0                  0     2          False          False          False
       P1     T1   Welch  93         93          0          0             89              0  1.11 1.40 0.0                  0     2          False          False          False
       P1     T2 Student  89         89          0          0             69              0  0.91 1.03 0.0                  0     2          False          False          False
       P1     T2   Welch  89         89          0          0             84              0  0.91 1.03 0.0                  0     2          False          False          False
       P2     T1 Student 113        113          0          0            101              0  1.11 1.23 0.0                  0     2          False          False          False
       P2     T1   Welch 113        113          0          0            109              0  1.11 1.23 0.0                  0     2          False          False          False
       P2     T2 Student 109        109          0          0             86              0  0.92 0.91 0.0                  0     2          False          False          False
       P2     T2   Welch 109        109          0          0            103              0  0.92 0.91 0.0                  0     2          False          False          False
all units     T1 Student 134        133          1          0            120              1 18.17 7.64 0.0                  0     2          False          False          False
all units     T1   Welch 134        133          1          0            129              1 18.17 7.64 0.0                  0     2          False          False          False
all units     T2 Student 130        129          1          0            102              1 18.43 7.48 0.0                  0     2          False          False          False
all units     T2   Welch 130        129          1          0            123              1 18.43 7.48 0.0                  0     2          False          False          False
(b) VM/VAL (L2): VGAT thalamic units within 0.4 mm of the centre: 0 | distance range (mm): 0.46 to 1.37
Paper: 2% of control, n = 148
Any reading within tolerance: False
Ratio in the window 20-120 ms, all units T1, per unit: quantiles 10/50/90% [0.    0.    0.023] | units 134 | per mouse Q1: {'anm00313106': np.float64(1.8), 'anm00313111': np.float64(35.2)}

Result: not reproduced. Putative thalamic units of the VGAT sessions fall to 1.1% (T1) or 0.9% (T2) of control (Q1; Q2 0.9 to 1.4%), on 113 units (P2) or 93 (P1) against 148 +/- 15; none is activated, and 101 of 113 are significantly inhibited (P2, T1, Student). With all units (134 under T1) the count is within tolerance but narrow units raise Q1 to 18%. The silencing is nearly complete, as the paper says, but the 2% and the unit count are not both within tolerance under any reading. No VGAT thalamic unit lies within 0.4 mm of the L2 centre, so reading (b) has no units.

The criterion has no partial clause, and no reading meets it in full (see Changes of outcome, before the Summary). The third verification round agreed.

vgat-thalamus-reduction¶

In VGAT-ChR2-EYFP mice, thalamus photoinhibition reduced activity 0.5 to 1.1 mm from the fibre tip to 15.9% of control.

Putative thalamic units of the VGAT thalamic sessions, at 0.5 to 1.1 mm from the fibre. The files give one photostimulus site for every session (AP -1.5, ML 0.9, DV -4.1 mm), a nominal coordinate; distance from it is computed in 3 dimensions and in the coronal plane (ML, DV). Windows W1 (whole delay epoch) and W2 (20 to 120 ms), T1, T2, Q1 to Q3.

In [21]:
fib = np.array([0.9, -4.1, -1.5])
rows = []
for p, d in {**vg_th, **vg_th_all}.items():
    d3 = np.sqrt((d.ml.abs() - fib[0]) ** 2 + (d.dv - fib[1]) ** 2 + (d.ap - fib[2]) ** 2)
    d2 = np.hypot(d.ml.abs() - fib[0], d.dv - fib[1])
    for dname, dist in (("3D", d3), ("coronal", d2)):
        sub = d[(dist >= 0.5) & (dist <= 1.1)]
        groups = np.select([dist < 0.7, dist < 0.9], ["0.6", "0.8"], "1.0")
        for wname, win, mx in (("W1", "delay", None), ("W2", "pw", None), ("variant: W1, 1.3 s delays only", "delay", 1.35)):
            for tname, oc in T_READ.items():
                df = loop.photo_effect(sessions, sub, "Thalamus:delay:2.23", oc, win, 5, True, max_delay=mx)
                r = loop.ratio_readings(df)
                rows.append({"units": p, "distance": dname, "window": wname, "trials": tname, "n": len(df),
                             "Q1": round(r["Q1"], 1), "Q2": round(r["Q2"], 1), "Q3": round(r["Q3"], 1),
                             "n_by_0.6/0.8/1.0": tuple(int(((groups == g) & (dist >= 0.5) & (dist <= 1.1)).sum()) for g in ("0.6", "0.8", "1.0"))})
vg2 = pd.DataFrame(rows)
vg2["within_tol"] = vg2[["Q1", "Q2", "Q3"]].sub(15.9).abs().le(9.3).any(axis=1)
print(vg2.to_string(index=False))
print("Paper: 15.9 +/- 9.3 % (n = 34, 42, 38 at 0.6, 0.8, 1.0 mm)")
print("Readings within tolerance:", int(vg2[vg2.window.isin(["W1", "W2"])].within_tol.sum()), "of", int(vg2.window.isin(["W1", "W2"]).sum()),
      "| variant rows within tolerance:", int(vg2[~vg2.window.isin(["W1", "W2"])].within_tol.sum()), "of", int((~vg2.window.isin(["W1", "W2"])).sum()))

# delay lengths in these sessions, and the ratio across the delay in 100 ms bins
vs = sorted(set(vg_th_all["all units"].session))
vt = pd.concat([sessions[i]["trials"] for i in vs])
k = vt.response.isin(loop.KEEP)
print("\nVGAT thalamic sessions, kept trials: delay length (s) quantiles 0/25/50/75/90/100%, photostimulus trials",
      np.round(np.percentile(vt.delay_s[k & (vt.stim == "Thalamus:delay:2.23")], [0, 25, 50, 75, 90, 100]), 2),
      "| control trials", np.round(np.percentile(vt.delay_s[k & (vt.stim == "none")], [0, 25, 50, 75, 90, 100]), 2))
print("Fraction of photostimulus trials with a delay of 1.3 s:", round(float(np.mean(np.abs(vt.delay_s[k & (vt.stim == "Thalamus:delay:2.23")] - 1.3) < 0.05)), 3))
d = vg_th["P2"]
d3 = np.sqrt((d.ml.abs() - fib[0]) ** 2 + (d.dv - fib[1]) ** 2 + (d.ap - fib[2]) ** 2)
sub = d[(d3 >= 0.5) & (d3 <= 1.1)]
tcb = loop.TC_SPAN[0] + loop.BIN_S * np.arange(int(round((loop.TC_SPAN[1] - loop.TC_SPAN[0]) / loop.BIN_S)))
binrows = []
for dname, lo, hi in (("1.3 s delay", 0, 1.35), ("delay > 1.35 s", 1.35, 99)):
    rc, rp = [], []
    for r in sub.itertuples():
        s = sessions[r.session]
        t = s["trials"]
        m = t.response.isin(loop.KEEP).values & s["valid"][r.unit] & t.tc_ok.values & (t.delay_s.values > lo) & (t.delay_s.values <= hi)
        c_, p_ = m & (t.stim == "none").values, m & (t.stim == "Thalamus:delay:2.23").values
        if p_.sum() < 1 or c_.sum() < 1:
            continue
        rc.append(s["tc"][r.unit][c_].mean(0) / loop.BIN_S)
        rp.append(s["tc"][r.unit][p_].mean(0) / loop.BIN_S)
    if not rc:
        binrows.append({"trials": dname, "units": 0})
        continue
    rc, rp = np.array(rc), np.array(rp)
    q1 = 100 * rp.mean(0) / rc.mean(0)
    binrows.append({"trials": dname, "units": len(rc), **{f"{x:.1f}": round(float(q1[np.argmin(np.abs(tcb - x))]), 1) for x in np.arange(1.0, 4.05, 0.2)}})
print("\nPutative thalamic units (P2) 0.5 to 1.1 mm (3D) from the site, T1: photostimulus / control population rate (Q1, %) in the 100 ms bin"
      " starting at the given time after pole onset (delay onset 1.3 s):")
print(pd.DataFrame(binrows).to_string(index=False))
d = vg_th_all["all units"]
print("Distance of VGAT thalamic units from the site (3D, mm): quantiles 0/50/100%",
      np.round(np.percentile(np.sqrt((d.ml.abs() - fib[0]) ** 2 + (d.dv - fib[1]) ** 2 + (d.ap - fib[2]) ** 2), [0, 50, 100]), 2))
    units distance                         window trials  n   Q1   Q2   Q3 n_by_0.6/0.8/1.0  within_tol
       P1       3D                             W1     T1 66 18.4 41.9 18.4     (23, 21, 31)        True
       P1       3D                             W1     T2 63 20.3 51.2 19.3     (23, 21, 31)        True
       P1       3D                             W2     T1 66  1.5  2.0  0.0     (23, 21, 31)       False
       P1       3D                             W2     T2 63  1.2  1.5  0.0     (23, 21, 31)       False
       P1       3D variant: W1, 1.3 s delays only     T1 66 18.4 41.9 18.4     (23, 21, 31)        True
       P1       3D variant: W1, 1.3 s delays only     T2 63 20.3 51.2 19.3     (23, 21, 31)        True
       P1  coronal                             W1     T1 66 18.4 41.9 18.4     (23, 21, 31)        True
       P1  coronal                             W1     T2 63 20.3 51.2 19.3     (23, 21, 31)        True
       P1  coronal                             W2     T1 66  1.5  2.0  0.0     (23, 21, 31)       False
       P1  coronal                             W2     T2 63  1.2  1.5  0.0     (23, 21, 31)       False
       P1  coronal variant: W1, 1.3 s delays only     T1 66 18.4 41.9 18.4     (23, 21, 31)        True
       P1  coronal variant: W1, 1.3 s delays only     T2 63 20.3 51.2 19.3     (23, 21, 31)        True
       P2       3D                             W1     T1 79 17.0 37.5 16.8     (24, 24, 42)        True
       P2       3D                             W1     T2 76 18.6 45.5 16.5     (24, 24, 42)        True
       P2       3D                             W2     T1 79  1.4  1.7  0.0     (24, 24, 42)       False
       P2       3D                             W2     T2 76  1.2  1.3  0.0     (24, 24, 42)       False
       P2       3D variant: W1, 1.3 s delays only     T1 79 17.0 37.5 16.8     (24, 24, 42)        True
       P2       3D variant: W1, 1.3 s delays only     T2 76 18.6 45.5 16.5     (24, 24, 42)        True
       P2  coronal                             W1     T1 79 17.0 37.5 16.8     (24, 24, 42)        True
       P2  coronal                             W1     T2 76 18.6 45.5 16.5     (24, 24, 42)        True
       P2  coronal                             W2     T1 79  1.4  1.7  0.0     (24, 24, 42)       False
       P2  coronal                             W2     T2 76  1.2  1.3  0.0     (24, 24, 42)       False
       P2  coronal variant: W1, 1.3 s delays only     T1 79 17.0 37.5 16.8     (24, 24, 42)        True
       P2  coronal variant: W1, 1.3 s delays only     T2 76 18.6 45.5 16.5     (24, 24, 42)        True
all units       3D                             W1     T1 87 15.8 34.9 13.4     (26, 26, 48)        True
all units       3D                             W1     T2 84 17.2 42.0 15.0     (26, 26, 48)        True
all units       3D                             W2     T1 87  1.5  1.8  0.0     (26, 26, 48)       False
all units       3D                             W2     T2 84  1.2  1.3  0.0     (26, 26, 48)       False
all units       3D variant: W1, 1.3 s delays only     T1 87 15.8 34.9 13.4     (26, 26, 48)        True
all units       3D variant: W1, 1.3 s delays only     T2 84 17.2 42.0 15.0     (26, 26, 48)        True
all units  coronal                             W1     T1 87 15.8 34.9 13.4     (26, 26, 48)        True
all units  coronal                             W1     T2 84 17.2 42.0 15.0     (26, 26, 48)        True
all units  coronal                             W2     T1 87  1.5  1.8  0.0     (26, 26, 48)       False
all units  coronal                             W2     T2 84  1.2  1.3  0.0     (26, 26, 48)       False
all units  coronal variant: W1, 1.3 s delays only     T1 87 15.8 34.9 13.4     (26, 26, 48)        True
all units  coronal variant: W1, 1.3 s delays only     T2 84 17.2 42.0 15.0     (26, 26, 48)        True
Paper: 15.9 +/- 9.3 % (n = 34, 42, 38 at 0.6, 0.8, 1.0 mm)
Readings within tolerance: 12 of 24 | variant rows within tolerance: 12 of 12

VGAT thalamic sessions, kept trials: delay length (s) quantiles 0/25/50/75/90/100%, photostimulus trials [1.3  1.3  1.3  1.3  1.3  1.31] | control trials [1.3  1.3  1.3  1.3  1.3  1.31]
Fraction of photostimulus trials with a delay of 1.3 s: 1.0

Putative thalamic units (P2) 0.5 to 1.1 mm (3D) from the site, T1: photostimulus / control population rate (Q1, %) in the 100 ms bin starting at the given time after pole onset (delay onset 1.3 s):
        trials  units   1.0   1.2  1.4  1.6  1.8  2.0  2.2  2.4  2.6   2.8   3.0   3.2   3.4   3.6   3.8   4.0
   1.3 s delay     79 104.0 104.0 21.6 23.7 19.4 11.2 10.1  9.1 99.7 103.8 115.7 112.6 116.9 110.4 112.2 105.2
delay > 1.35 s      0   NaN   NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
Distance of VGAT thalamic units from the site (3D, mm): quantiles 0/50/100% [0.4  0.98 1.38]

Result: reproduced. Over the whole photostimulus (W1), putative thalamic units 0.5 to 1.1 mm from the fibre site fall to 17.0 to 20.3% (Q1) or 16.5 to 19.3% (Q3) of control, within 15.9 +/- 9.3%; Q2 is 37.5 to 51.2%. In the 20 to 120 ms window (W2) they fall to 1.2 to 1.5% (Q1). Every trial of the VGAT thalamic sessions has a 1.3 s delay, so W1 ends with the delay epoch and holds no time after the photostimulus; restricting W1 to 1.3 s delays changes nothing. In 100 ms bins the ratio is 21.6% in the first bin after 1.4 s, falls to 9 to 11% by the end of the delay and returns to 100% in the first bin of the response epoch: activity, silenced at first (W2), partly recovers during the photostimulus. 63 to 79 units qualify against the paper's 114, the site is one nominal coordinate for all sessions, so the distances are approximate, and the files give the power as 2.23 mW where the paper gives 10 mW.

fig3-onset-latencies¶

Photoinhibition reduced thalALM activity 2.5 ms after photostimulus onset, and ALM spike rates were reduced 8.2 ms after onset, a latency difference consistent with direct thalamocortical drive.

Convention O on population PSTHs (1 ms bins), readings O1 and O2, T1 and T2; the thalamic population of fig3f-thalamus-silenced (putative thalamic units, reading a) and the ALM population of fig3-alm-collapse, both with at least 5 photostimulus trials; SEM from 1000 resamplings of units. P1 and P2.

In [22]:
rng = np.random.default_rng(301)


def onset_rows(label, sel, stims, direction=-1, flip=None):
    rows = []
    if len(sel) == 0:
        return [{"population": label, "n": 0}]
    for tname, oc in T_READ.items():
        c, p = loop.population_psth(sessions, sel, stims, oc)
        if flip is not None:
            p = np.where(flip[:, None], 2 * c - p, p)
        for rd in ("O1", "O2"):
            est, sem, nan = loop.bootstrap_onset(c, p, rd, rng, 1000, direction)
            rows.append({"population": label, "n": len(sel), "trials": tname, "reading": rd, "onset_ms": est, "sem_ms": round(sem, 2),
                         "boot_no_onset": nan})
    return rows


rows = []
for p in ("P1", "P2"):
    th_units = vg_th[p].loc[F3F[(p, "T1", True)].index]
    alm_units = vg_alm[p].loc[F3[(p, "T1", True)].index]
    rows += onset_rows(f"thalamus VGAT {p}", th_units, "Thalamus:delay:2.23")
    rows += onset_rows(f"ALM VGAT {p}", alm_units, "Thalamus:delay:10")
on3 = pd.DataFrame(rows)
print(on3.to_string(index=False))
print("Paper: thalamus 2.5 +/- 0.8 ms, ALM 8.2 +/- 1.5 ms")
w = on3.pivot_table(index=["trials", "reading"], columns="population", values="onset_ms")
for p in ("P1", "P2"):
    ok = (w[f"thalamus VGAT {p}"].sub(2.5).abs() <= 0.8) & (w[f"ALM VGAT {p}"].sub(8.2).abs() <= 1.5) & (w[f"ALM VGAT {p}"] > w[f"thalamus VGAT {p}"])
    print(p, "readings with both onsets within tolerance and ALM later:", ok[ok].index.tolist())
# Reliability of the onset rule (convention O as implemented): photostimulus PSTHs simulated from each unit's own control
# PSTH and number of photostimulus trials, with no effect (any onset is false) or with a step to 20% of control at 8 ms.
rng_c = np.random.default_rng(302)
rel = []
for nm, sel, st in (("thalamus VGAT P2", vg_th["P2"].loc[F3F[("P2", "T1", True)].index], "Thalamus:delay:2.23"),
                    ("ALM VGAT P2", vg_alm["P2"].loc[F3[("P2", "T1", True)].index], "Thalamus:delay:10")):
    cu, _, npi = loop.population_psth(sessions, sel, st, loop.KEEP, with_n=True)
    for rd in ("O1", "O2"):
        nul = loop.onset_reliability(cu, npi, rd, rng_c, 200)
        stp = loop.onset_reliability(cu, npi, rd, rng_c, 200, step_ms=8, step_ratio=0.2)
        rel.append({"population": nm, "reading": rd, "null: runs with an onset": float(np.mean(~np.isnan(nul))),
                    "null: onset < 10 ms": float(np.mean(nul < 10)), "null: onset < 20 ms": float(np.mean(nul < 20)),
                    "step at 8 ms: median onset": float(np.nanmedian(stp)), "step: onset < 8 ms": float(np.mean(stp < 8)),
                    "step: onset 6.5 to 9.5 ms": float(np.mean((stp >= 6.5) & (stp <= 9.5)))})
print("\nOnset rule on simulated data (200 runs each; T1 populations):")
print(pd.DataFrame(rel).round(3).to_string(index=False))
t_ms = loop.psth_time_ms()
c, pp = loop.population_psth(sessions, vg_th["P2"].loc[F3F[("P2", "T1", True)].index], "Thalamus:delay:2.23")
c2, pp2 = loop.population_psth(sessions, vg_alm["P2"].loc[F3[("P2", "T1", True)].index], "Thalamus:delay:10")
fig, axs = plt.subplots(1, 2, figsize=(9, 2.8))
for ax, (cc, ppp, nm) in zip(axs, ((c, pp, "thalamus (VGAT)"), (c2, pp2, "ALM (VGAT)"))):
    k = (t_ms > -20) & (t_ms < 40)
    ax.plot(t_ms[k], np.nanmean(cc, 0)[k], "k", label="control")
    ax.plot(t_ms[k], np.nanmean(ppp, 0)[k], "b", label="photostim.")
    ax.set_title(nm, fontsize=9)
    ax.set_xlabel("ms from photostimulus onset")
axs[0].set_ylabel("spikes/s (1 ms bins)")
axs[0].legend(fontsize=7)
plt.show()
print("Plotted range (spikes/s): thalamus", round(np.nanmean(pp, 0)[k].min(), 1), "to", round(np.nanmean(c, 0)[k].max(), 1),
      "| ALM", round(np.nanmean(pp2, 0)[k].min(), 1), "to", round(np.nanmean(c2, 0)[k].max(), 1))
      population   n trials reading  onset_ms  sem_ms  boot_no_onset
thalamus VGAT P1  93     T1      O1       2.0    1.24              0
thalamus VGAT P1  93     T1      O2       2.0    1.08              0
thalamus VGAT P1  93     T2      O1       2.0    1.53              0
thalamus VGAT P1  93     T2      O2       2.0    1.49              0
     ALM VGAT P1 234     T1      O1       0.0    4.31              0
     ALM VGAT P1 234     T1      O2       9.0    3.68              0
     ALM VGAT P1 234     T2      O1       0.0    4.24              0
     ALM VGAT P1 234     T2      O2       6.0    3.31              0
thalamus VGAT P2 113     T1      O1       1.0    0.96              0
thalamus VGAT P2 113     T1      O2       2.0    0.96              0
thalamus VGAT P2 113     T2      O1       2.0    0.95              0
thalamus VGAT P2 113     T2      O2       2.0    1.20              0
     ALM VGAT P2 261     T1      O1       0.0    3.72              0
     ALM VGAT P2 261     T1      O2       7.0    3.16              0
     ALM VGAT P2 261     T2      O1       6.0    3.08              0
     ALM VGAT P2 261     T2      O2       6.0    2.51              0
Paper: thalamus 2.5 +/- 0.8 ms, ALM 8.2 +/- 1.5 ms
P1 readings with both onsets within tolerance and ALM later: [('T1', 'O2')]
P2 readings with both onsets within tolerance and ALM later: [('T1', 'O2')]
Onset rule on simulated data (200 runs each; T1 populations):
      population reading  null: runs with an onset  null: onset < 10 ms  null: onset < 20 ms  step at 8 ms: median onset  step: onset < 8 ms  step: onset 6.5 to 9.5 ms
thalamus VGAT P2      O1                       1.0                0.355                0.605                         8.0               0.255                      0.750
thalamus VGAT P2      O2                       1.0                0.380                0.680                         8.0               0.210                      0.825
     ALM VGAT P2      O1                       1.0                0.475                0.690                         8.0               0.430                      0.595
     ALM VGAT P2      O2                       1.0                0.300                0.510                         8.0               0.185                      0.835
No description has been provided for this image
Plotted range (spikes/s): thalamus 0.0 to 12.1 | ALM 0.0 to 5.3

Result: reproduced. Under reading O2 with correct and incorrect trials (T1), the thalamic onset is 2.0 ms (SEM 1.08 with P1, 0.96 with P2) and the ALM onset 9.0 ms (P1, SEM 3.68) or 7.0 ms (P2, SEM 3.16), within 2.5 +/- 0.8 and 8.2 +/- 1.5 ms, with ALM later. The other readings fail: under O1 the ALM onset is 0 ms in three of four cases (the first 1 ms bin already lies 3 SD below control), and under T2 with O2 it is 6 ms. The pass rests on one reading of four and the rule is fragile: on photostimulus PSTHs simulated from each unit's control PSTH with no effect, it still reports an onset in every run, below 10 ms in 30 to 48% of them; with a simulated step at 8 ms it reports an onset before 8 ms in 18 to 43% of runs and within 6.5 to 9.5 ms in 60 to 84%. The ALM onset of 0 ms under O1 is such a false onset. The bootstrap SEMs of the ALM onset under T1 and O2 (3.2 and 3.7 ms) are twice the paper's 1.5 ms.

fig6c-vmval-reduced¶

ALM photoinhibition decreased the activity of VM/VAL neurons to 25% of control, inhibiting 190 of 201 neurons (139 significantly) and significantly activating none.

VM/VAL putative thalamic units (L2) of the PV-Cre x Ai32 thalamic sessions, ALM photoinhibition at 1.5 mW in the delay epoch, at least 5 trials; T1, T2, Q1 to Q3, Student and Welch, P1 and P2. P3 (all VM/VAL units regardless of width) as a further unit reading. Variant: all ALM photoinhibition powers (1.5 and 0.79 mW).

In [23]:
pv_vm = {p: d[(d.genotype == "Ai32 x PV-Cre")] for p, d in VM26.items()}
f6, F6 = effect_table(pv_vm, "ALM:delay:1.5")
for q in ("Q1", "Q2", "Q3"):
    f6[f"within_tol_{q}"] = ((f6[q] - 25).abs() <= 2.5) & ((f6.n - 201).abs() <= 20) & ((f6.inhibited - 190).abs() <= 19) & \
        ((f6.activated - 11).abs() <= 1.1) & ((f6.sig_inhibited - 139).abs() <= 14) & (f6.sig_activated == 0)
print(f6.to_string(index=False))
print("Paper: 25% of control; 201 neurons, 190 inhibited, 11 activated, 139 significantly inhibited, 0 significantly activated")
print("Readings within tolerance on all values:", int(f6[[c for c in f6 if c.startswith("within_tol")]].any(axis=1).sum()), "of", len(f6))
part6 = (f6.Q1 < 100) & (f6.inhibited > f6.activated) & (f6.sig_activated == 0)
print("Partial condition in every reading:", bool(part6.all()), "| readings where it holds, by units:", f6[part6].groupby("units").size().to_dict())
v6, _ = effect_table(pv_vm, ["ALM:delay:1.5", "ALM:delay:0.79"])
print("\nVariant, all ALM powers:")
print(v6.to_string(index=False))
d = F6[("P2", "T1", True)].join(units[["subject"]])
print("\nBy mouse (P2, T1, Student):")
print(d.groupby("subject").agg(n=("delta", "size"), inhibited=("delta", lambda x: int((x < 0).sum())), sig_inh=("sig", "sum"),
                               rate_ctrl=("rate_ctrl", "mean"), rate_pi=("rate_pi", "mean")).round(2).to_string())
units trials    test   n  inhibited  activated  unchanged  sig_inhibited  sig_activated        Q1        Q2        Q3  n_ratio_undefined  mice  within_tol_Q1  within_tol_Q2  within_tol_Q3
   P1     T1 Student  15         12          3          0              7              0 50.022751 57.536102 45.518208                  0     6          False          False          False
   P1     T1   Welch  15         12          3          0              7              0 50.022751 57.536102 45.518208                  0     6          False          False          False
   P1     T2 Student  15         11          4          0              6              0 43.019531 51.445492 37.904472                  0     6          False          False          False
   P1     T2   Welch  15         11          4          0              8              0 43.019531 51.445492 37.904472                  0     6          False          False          False
   P2     T1 Student 172        151         21          0             99              2 47.450802 46.522335 36.436440                  0     7          False          False          False
   P2     T1   Welch 172        151         21          0            105              2 47.450802 46.522335 36.436440                  0     7          False          False          False
   P2     T2 Student 163        136         27          0             77              1 46.173172 45.253078 29.946522                  0     7          False          False          False
   P2     T2   Welch 163        136         27          0            102              1 46.173172 45.253078 29.946522                  0     7          False          False          False
   P3     T1 Student 201        173         28          0            107              5 55.930027 51.027489 40.000000                  0     7          False          False          False
   P3     T1   Welch 201        173         28          0            117              4 55.930027 51.027489 40.000000                  0     7          False          False          False
   P3     T2 Student 190        157         33          0             85              2 53.376141 49.018391 36.960785                  0     7          False          False          False
   P3     T2   Welch 190        157         33          0            111              2 53.376141 49.018391 36.960785                  0     7          False          False          False
Paper: 25% of control; 201 neurons, 190 inhibited, 11 activated, 139 significantly inhibited, 0 significantly activated
Readings within tolerance on all values: 0 of 12
Partial condition in every reading: False | readings where it holds, by units: {'P1': 4}
Variant, all ALM powers:
units trials    test   n  inhibited  activated  unchanged  sig_inhibited  sig_activated        Q1        Q2        Q3  n_ratio_undefined  mice
   P1     T1 Student  15         11          4          0              6              0 61.777534 68.751122 65.024635                  0     6
   P1     T1   Welch  15         11          4          0              6              0 61.777534 68.751122 65.024635                  0     6
   P1     T2 Student  15         10          5          0              6              0 55.967133 63.710762 54.321808                  0     6
   P1     T2   Welch  15         10          5          0              7              0 55.967133 63.710762 54.321808                  0     6
   P2     T1 Student 173        148         25          0             87              2 57.693043 56.443779 51.241833                  0     7
   P2     T1   Welch 173        148         25          0             91              2 57.693043 56.443779 51.241833                  0     7
   P2     T2 Student 170        140         30          0             71              1 58.263138 56.436657 52.397762                  0     7
   P2     T2   Welch 170        140         30          0             85              1 58.263138 56.436657 52.397762                  0     7
   P3     T1 Student 203        170         33          0             93              5 64.935181 60.717876 59.815323                  0     7
   P3     T1   Welch 203        170         33          0            101              4 64.935181 60.717876 59.815323                  0     7
   P3     T2 Student 199        162         37          0             76              2 64.274574 59.808064 55.367233                  0     7
   P3     T2   Welch 199        162         37          0             91              2 64.274574 59.808064 55.367233                  0     7

By mouse (P2, T1, Student):
              n  inhibited  sig_inh  rate_ctrl  rate_pi
subject                                                
anm00234218  20         19       15      11.89     3.73
anm00239123   2          1        0      10.01     8.34
anm00260487  52         47       40       9.88     4.00
anm00260488  28         21       12      10.26     6.87
anm00260490  26         21        9      10.13     5.99
anm00260491   1          1        1       6.60     3.62
anm00264943  43         41       24      11.82     5.13

Result: not reproduced. In 172 VM/VAL putative units (P2, T1; 15 with P1) from 7 mice, ALM photoinhibition at 1.5 mW lowers activity to 47.5% (Q1), 46.5% (Q2) or 36.4% (Q3) of control, against 25%: 151 are inhibited, 21 activated, 99 (Student) or 105 (Welch) significantly inhibited and 2 significantly activated. With P3 (all VM/VAL units, T1) 201 units qualify, the paper's n, and 173 are inhibited (190 +/- 19), but activity falls only to 55.9% (Q1) or 40.0% (Q3), 28 are activated and 4 or 5 significantly activated. No reading puts every value within tolerance, and the partial condition fails because under P2 and P3 1 to 5 units are significantly activated (it holds in the 4 P1 readings only). The reduction is present, about half as deep as the paper's.

fig6b-selectivity-types-equally-inhibited¶

VM/VAL neurons selective during the sample, delay or response epochs were equally inhibited by ALM photoinhibition.

Neurons of fig6c-vmval-reduced. Groups (a) preparatory only, peri-movement only, both; (b) selective in the sample, the delay, the response epoch (overlapping). Measures ratio and difference; two-sided t-tests between each pair; every selectivity reading, T1 and T2, P1, P2 and P3.

In [24]:
rows = []
for p in ("P1", "P2", "P3"):
    for tname in T_READ:
        eff = F6[(p, tname, True)]
        for k in SEL:
            st = SEL[k].loc[eff.index]
            grp_a = {n: st.kind == n for n in ("prep_only", "peri_only", "both")}
            grp_b = {"sample": st.p_sample < 0.05, "delay": st.p_delay < 0.05, "response": st.p_resp < 0.05}
            for gname, grp in (("a", grp_a), ("b", grp_b)):
                for meas in ("ratio", "delta"):
                    g = {n: eff[meas][m].dropna() for n, m in grp.items()}
                    names = list(g)
                    ps = [stats.ttest_ind(g[x], g[y]).pvalue if min(len(g[x]), len(g[y])) > 1 else np.nan
                          for i, x in enumerate(names) for y in names[i + 1:]]
                    rows.append({"units": p, "trials": tname, "sel_reading": k, "groups": gname, "measure": meas,
                                 "n": tuple(len(v) for v in g.values()), "means": tuple(round(v.mean(), 2) for v in g.values()),
                                 "min_p": np.nanmin(ps) if np.isfinite(ps).any() else np.nan})
f6b = pd.DataFrame(rows)
print(f6b[(f6b.sel_reading == "control/R1/Student/c1")].to_string(index=False))
agg = f6b.groupby(["units", "trials", "groups", "measure"]).agg(readings=("min_p", "size"), pair_p_lt_05=("min_p", lambda x: int((x < 0.05).sum())),
                                                               min_p=("min_p", "min")).reset_index()
print("\nOver the 16 selectivity readings:")
print(agg.round(4).to_string(index=False))
units trials           sel_reading groups measure             n                  means    min_p
   P1     T1 control/R1/Student/c1      a   ratio     (3, 5, 1)     (0.21, 0.83, 0.37) 0.140760
   P1     T1 control/R1/Student/c1      a   delta     (3, 5, 1)  (-9.94, -2.36, -5.02) 0.098936
   P1     T1 control/R1/Student/c1      b   ratio     (2, 4, 6)     (0.09, 0.25, 0.75) 0.129032
   P1     T1 control/R1/Student/c1      b   delta     (2, 4, 6)  (-10.64, -8.71, -2.8) 0.100106
   P1     T2 control/R1/Student/c1      a   ratio     (3, 5, 1)     (0.16, 0.84, 0.38) 0.073640
   P1     T2 control/R1/Student/c1      a   delta     (3, 5, 1) (-12.58, -2.15, -4.47) 0.035060
   P1     T2 control/R1/Student/c1      b   ratio     (2, 4, 6)      (0.1, 0.21, 0.76) 0.070154
   P1     T2 control/R1/Student/c1      b   delta     (2, 4, 6) (-11.6, -10.55, -2.54) 0.045526
   P2     T1 control/R1/Student/c1      a   ratio  (29, 53, 31)     (0.32, 0.54, 0.37) 0.042351
   P2     T1 control/R1/Student/c1      a   delta  (29, 53, 31)  (-7.83, -4.17, -7.24) 0.002698
   P2     T1 control/R1/Student/c1      b   ratio  (33, 40, 84)     (0.38, 0.35, 0.48) 0.170284
   P2     T1 control/R1/Student/c1      b   delta  (33, 40, 84)   (-6.77, -8.02, -5.3) 0.015391
   P2     T2 control/R1/Student/c1      a   ratio  (28, 49, 30)      (0.3, 0.56, 0.38) 0.034153
   P2     T2 control/R1/Student/c1      a   delta  (28, 49, 30)  (-8.41, -4.03, -7.26) 0.002514
   P2     T2 control/R1/Student/c1      b   ratio  (32, 39, 79)     (0.39, 0.35, 0.49) 0.162201
   P2     T2 control/R1/Student/c1      b   delta  (32, 39, 79)   (-6.9, -8.53, -5.26) 0.010743
   P3     T1 control/R1/Student/c1      a   ratio  (30, 63, 39)     (0.31, 0.58, 0.48) 0.011654
   P3     T1 control/R1/Student/c1      a   delta  (30, 63, 39)  (-7.74, -4.09, -5.92) 0.001411
   P3     T1 control/R1/Student/c1      b   ratio (35, 49, 102)     (0.43, 0.44, 0.54) 0.233433
   P3     T1 control/R1/Student/c1      b   delta (35, 49, 102)  (-6.18, -6.79, -4.79) 0.052089
   P3     T2 control/R1/Student/c1      a   ratio  (29, 58, 38)     (0.29, 0.59, 0.48) 0.011077
   P3     T2 control/R1/Student/c1      a   delta  (29, 58, 38)  (-8.33, -4.17, -6.13) 0.002264
   P3     T2 control/R1/Student/c1      b   ratio  (34, 48, 96)     (0.44, 0.42, 0.54) 0.190564
   P3     T2 control/R1/Student/c1      b   delta  (34, 48, 96)  (-6.31, -7.37, -4.94) 0.035557

Over the 16 selectivity readings:
units trials groups measure  readings  pair_p_lt_05  min_p
   P1     T1      a   delta        16            10 0.0013
   P1     T1      a   ratio        16             8 0.0002
   P1     T1      b   delta        16             4 0.0294
   P1     T1      b   ratio        16             0 0.1050
   P1     T2      a   delta        16            11 0.0002
   P1     T2      a   ratio        16             9 0.0003
   P1     T2      b   delta        16             5 0.0235
   P1     T2      b   ratio        16             1 0.0462
   P2     T1      a   delta        16            16 0.0022
   P2     T1      a   ratio        16             7 0.0052
   P2     T1      b   delta        16             6 0.0154
   P2     T1      b   ratio        16             0 0.1180
   P2     T2      a   delta        16            16 0.0011
   P2     T2      a   ratio        16             8 0.0216
   P2     T2      b   delta        16            10 0.0107
   P2     T2      b   ratio        16             0 0.1496
   P3     T1      a   delta        16            11 0.0005
   P3     T1      a   ratio        16             7 0.0061
   P3     T1      b   delta        16             1 0.0450
   P3     T1      b   ratio        16             0 0.1239
   P3     T2      a   delta        16            10 0.0003
   P3     T2      a   ratio        16             8 0.0028
   P3     T2      b   delta        16             5 0.0328
   P3     T2      b   ratio        16             0 0.1151

Result: blocked (methods underspecified). With groups (a), a pair differs at p < 0.05 in 10 to 16 of the 16 selectivity readings for the rate difference and 7 to 9 for the ratio; with groups (b), in 1 to 10 readings for the difference and 0 or 1 for the ratio (P1, P2 and P3). The readings neither all find nor all miss a difference, which the criterion calls methods underspecified.

fig6c-unmodulated-less-selective¶

The few VM/VAL neurons not changed by ALM photoinhibition were significantly less selective in the delay epoch, while neurons strongly reduced by it carried trial-type information; the change of rate and delay selectivity were negatively related (regression slope -0.73, r -0.33).

Neurons of fig6c-vmval-reduced split by the significance of their change. Delay selectivity on correct control trials, (a) |contra - ipsi| rate, (b) preferred minus non-preferred rate (preference by total count, convention S). Two-sided t-test; regression (i) selectivity on change, (ii) change on selectivity. P1, P2 and P3.

In [25]:
rows = []
for p in ("P1", "P2", "P3"):
    for tname in T_READ:
        for ev in (True, False):
            eff = F6[(p, tname, ev)]
            rc, ri = [], []
            for idx in eff.index:
                r = units.loc[idx]
                s = sessions[r.session]
                t = s["trials"]
                m = (t.response == "correct").values & (t.stim == "none").values
                c = s["counts"]["delay"][r.unit] / t.delay_s.values
                rc.append(np.nanmean(c[m & t.contra.values]))
                ri.append(np.nanmean(c[m & ~t.contra.values]))
            rc, ri = np.array(rc), np.array(ri)
            pref = SEL["control/R1/Student/c1"].loc[eff.index, "contra_pref"].values
            sel = {"a": np.abs(rc - ri), "b": np.where(pref, rc - ri, ri - rc)}
            for sname, sv in sel.items():
                tt = stats.ttest_ind(sv[eff.sig.values], sv[~eff.sig.values], equal_var=ev)
                for ax in ("i", "ii"):
                    x, y = (eff.delta.values, sv) if ax == "i" else (sv, eff.delta.values)
                    lr = stats.linregress(x, y)
                    rows.append({"units": p, "trials": tname, "test": "Student" if ev else "Welch", "selectivity": sname, "axes": ax,
                                 "n_sig": int(eff.sig.sum()), "n_not": int((~eff.sig).sum()),
                                 "sel_sig": round(sv[eff.sig.values].mean(), 2), "sel_not": round(sv[~eff.sig.values].mean(), 2),
                                 "t_p": tt.pvalue, "slope": round(lr.slope, 3), "r": round(lr.rvalue, 3)})
f6u = pd.DataFrame(rows)
f6u["group_ok"] = (f6u.sel_not < f6u.sel_sig) & (f6u.t_p < 0.05)
f6u["within_tol"] = f6u.group_ok & ((f6u.slope + 0.73).abs() <= 0.073) & ((f6u.r + 0.33).abs() <= 0.033)
f6u["partial"] = f6u.group_ok & (f6u.r < 0)
print(f6u.round(4).to_string(index=False))
print("Paper: P = 0.002; slope -0.73, r -0.33")
print("Readings reproduced:", int(f6u.within_tol.sum()), "| partial:", int(f6u.partial.sum()), "| group difference holds:",
      int(f6u.group_ok.sum()), "of", len(f6u))
print(f6u.groupby("units").agg(readings=("r", "size"), group_ok=("group_ok", "sum"), partial=("partial", "sum"), within_tol=("within_tol", "sum"),
                               r_min=("r", "min"), r_max=("r", "max")).to_string())
units trials    test selectivity axes  n_sig  n_not  sel_sig  sel_not    t_p  slope      r  group_ok  within_tol  partial
   P1     T1 Student           a    i      7      8     2.98     0.72 0.0771 -0.195 -0.445     False       False    False
   P1     T1 Student           a   ii      7      8     2.98     0.72 0.0771 -1.016 -0.445     False       False    False
   P1     T1 Student           b    i      7      8     2.87    -0.03 0.0382 -0.254 -0.520      True       False     True
   P1     T1 Student           b   ii      7      8     2.87    -0.03 0.0382 -1.065 -0.520      True       False     True
   P1     T1   Welch           a    i      7      8     2.98     0.72 0.1209 -0.195 -0.445     False       False    False
   P1     T1   Welch           a   ii      7      8     2.98     0.72 0.1209 -1.016 -0.445     False       False    False
   P1     T1   Welch           b    i      7      8     2.87    -0.03 0.0680 -0.254 -0.520     False       False    False
   P1     T1   Welch           b   ii      7      8     2.87    -0.03 0.0680 -1.065 -0.520     False       False    False
   P1     T2 Student           a    i      6      9     2.94     1.00 0.1454 -0.187 -0.464     False       False    False
   P1     T2 Student           a   ii      6      9     2.94     1.00 0.1454 -1.151 -0.464     False       False    False
   P1     T2 Student           b    i      6      9     2.80     0.34 0.0920 -0.251 -0.558     False       False    False
   P1     T2 Student           b   ii      6      9     2.80     0.34 0.0920 -1.241 -0.558     False       False    False
   P1     T2   Welch           a    i      8      7     2.81     0.59 0.0829 -0.187 -0.464     False       False    False
   P1     T2   Welch           a   ii      8      7     2.81     0.59 0.0829 -1.151 -0.464     False       False    False
   P1     T2   Welch           b    i      8      7     2.71    -0.26 0.0345 -0.251 -0.558      True       False     True
   P1     T2   Welch           b   ii      8      7     2.71    -0.26 0.0345 -1.241 -0.558      True       False     True
   P2     T1 Student           a    i    101     71     1.77     1.13 0.0030 -0.074 -0.278      True       False     True
   P2     T1 Student           a   ii    101     71     1.77     1.13 0.0030 -1.048 -0.278      True       False     True
   P2     T1 Student           b    i    101     71     1.12     0.39 0.0130 -0.081 -0.226      True       False     True
   P2     T1 Student           b   ii    101     71     1.12     0.39 0.0130 -0.631 -0.226      True       False     True
   P2     T1   Welch           a    i    107     65     1.72     1.17 0.0058 -0.074 -0.278      True       False     True
   P2     T1   Welch           a   ii    107     65     1.72     1.17 0.0058 -1.048 -0.278      True       False     True
   P2     T1   Welch           b    i    107     65     1.02     0.48 0.0461 -0.081 -0.226      True       False     True
   P2     T1   Welch           b   ii    107     65     1.02     0.48 0.0461 -0.631 -0.226      True       False     True
   P2     T2 Student           a    i     78     85     1.83     1.23 0.0063 -0.068 -0.284      True       False     True
   P2     T2 Student           a   ii     78     85     1.83     1.23 0.0063 -1.183 -0.284      True       False     True
   P2     T2 Student           b    i     78     85     1.22     0.46 0.0109 -0.091 -0.282      True       False     True
   P2     T2 Student           b   ii     78     85     1.22     0.46 0.0109 -0.875 -0.282      True       False     True
   P2     T2   Welch           a    i    103     60     1.75     1.12 0.0021 -0.068 -0.284      True       False     True
   P2     T2   Welch           a   ii    103     60     1.75     1.12 0.0021 -1.183 -0.284      True       False     True
   P2     T2   Welch           b    i    103     60     1.10     0.35 0.0085 -0.091 -0.282      True       False     True
   P2     T2   Welch           b   ii    103     60     1.10     0.35 0.0085 -0.875 -0.282      True       False     True
   P3     T1 Student           a    i    112     89     1.81     1.21 0.0031 -0.048 -0.181      True       False     True
   P3     T1 Student           a   ii    112     89     1.81     1.21 0.0031 -0.683 -0.181      True       False     True
   P3     T1 Student           b    i    112     89     1.15     0.54 0.0238 -0.051 -0.142      True       False     True
   P3     T1 Student           b   ii    112     89     1.15     0.54 0.0238 -0.400 -0.142      True       False     True
   P3     T1   Welch           a    i    121     80     1.76     1.23 0.0056 -0.048 -0.181      True       False     True
   P3     T1   Welch           a   ii    121     80     1.76     1.23 0.0056 -0.683 -0.181      True       False     True
   P3     T1   Welch           b    i    121     80     1.08     0.57 0.0492 -0.051 -0.142      True       False     True
   P3     T1   Welch           b   ii    121     80     1.08     0.57 0.0492 -0.400 -0.142      True       False     True
   P3     T2 Student           a    i     87    103     1.81     1.36 0.0308 -0.049 -0.201      True       False     True
   P3     T2 Student           a   ii     87    103     1.81     1.36 0.0308 -0.819 -0.201      True       False     True
   P3     T2 Student           b    i     87    103     1.18     0.67 0.0710 -0.062 -0.189     False       False    False
   P3     T2 Student           b   ii     87    103     1.18     0.67 0.0710 -0.574 -0.189     False       False    False
   P3     T2   Welch           a    i    113     77     1.74     1.31 0.0353 -0.049 -0.201      True       False     True
   P3     T2   Welch           a   ii    113     77     1.74     1.31 0.0353 -0.819 -0.201      True       False     True
   P3     T2   Welch           b    i    113     77     1.08     0.63 0.1063 -0.062 -0.189     False       False    False
   P3     T2   Welch           b   ii    113     77     1.08     0.63 0.1063 -0.574 -0.189     False       False    False
Paper: P = 0.002; slope -0.73, r -0.33
Readings reproduced: 0 | partial: 32 | group difference holds: 32 of 48
       readings  group_ok  partial  within_tol  r_min  r_max
units                                                       
P1           16         4        4           0 -0.558 -0.445
P2           16        16       16           0 -0.284 -0.226
P3           16        12       12           0 -0.201 -0.142

Result: partially reproduced. With P2 and correct and incorrect trials, the 71 neurons not significantly changed (Student) are less selective in the delay epoch than the 101 changed ones (|contra - ipsi| 1.13 against 1.77 spikes/s, p = 0.0030; the paper's P = 0.002), and the change of rate and delay selectivity are negatively correlated (r = -0.278 against -0.33 +/- 0.033; slope -0.074 with selectivity on change, -1.048 with change on selectivity, against -0.73). The group difference and a negative r hold in all 16 P2 readings, 12 of 16 P3 readings (r -0.142 to -0.201) and 4 of 16 P1 readings (P1 has 15 neurons); slope and r are out of tolerance in every reading.

fig6d-localized¶

The reduction of thalamic activity by ALM photoinhibition was mainly limited to VM/VAL; neurons within 1.0 mm of the VM/VAL centre were inhibited to 36% of control, and neurons farther away less.

Thalamic units of the PV-Cre x Ai32 thalamic sessions (ALM photoinhibition 1.5 mW), at least 5 trials, grouped by distance from the L2 centre. Units (u1) putative thalamic (P1, P2), (u2) all, which is reading P3; windows (w1) 20 to 120 ms, (w2) 0 to 100 ms; ratio Q1 to Q3; T1, T2.

In [26]:
pv_th = thal[thal.genotype == "Ai32 x PV-Cre"]
sets = {"u1-P1": pv_th[pv_th.width_ms > 0.5], "u1-P2": pv_th[pv_th.cell_type == "Wide width spiking"], "u2 (P3)": pv_th}
rows = []
for uname, d in sets.items():
    for wname, win in (("w1", "pw"), ("w2", "pw0")):
        for tname, oc in T_READ.items():
            df = loop.photo_effect(sessions, d, "ALM:delay:1.5", oc, win, 5, True)
            dist = units.loc[df.index, "vmval_d"]
            g = {"<0.5": df[dist < 0.5], "0.5-1.0": df[(dist >= 0.5) & (dist < 1.0)], ">=1.0": df[dist >= 1.0], "<1.0": df[dist < 1.0]}
            r = {k: loop.ratio_readings(v) for k, v in g.items()}
            rows.append({"units": uname, "window": wname, "trials": tname, "n<0.5": len(g["<0.5"]), "n0.5-1": len(g["0.5-1.0"]),
                         "n>=1": len(g[">=1.0"]), **{f"{q}<1.0": round(r["<1.0"][q], 1) for q in ("Q1", "Q2", "Q3")},
                         **{f"Q1{k}": round(r[k]["Q1"], 1) for k in ("<0.5", "0.5-1.0", ">=1.0")},
                         **{f"Q2{k}": round(r[k]["Q2"], 1) for k in ("<0.5", ">=1.0")}})
f6d = pd.DataFrame(rows)
cnt_ok = ((f6d["n<0.5"] - 250).abs() <= 25) & ((f6d["n0.5-1"] - 160).abs() <= 16) & ((f6d["n>=1"] - 46).abs() <= 4.6)
f6d["counts_ok"] = cnt_ok
f6d["value_ok_any_Q"] = f6d[["Q1<1.0", "Q2<1.0", "Q3<1.0"]].sub(36).abs().le(3.6).any(axis=1)
f6d["near_lower_than_far_Q1"] = f6d["Q1<0.5"] < f6d["Q1>=1.0"]
print(f6d.to_string(index=False))
print("Paper: 36% within 1.0 mm; n = 250 (< 0.5 mm), 160 (0.5 to 1.0), 46 (>= 1.0)")
print("Readings with counts, value and order all holding:", int((f6d.counts_ok & f6d.value_ok_any_Q & f6d.near_lower_than_far_Q1).sum()), "of", len(f6d))
  units window trials  n<0.5  n0.5-1  n>=1    Q1<1.0    Q2<1.0    Q3<1.0    Q1<0.5  Q10.5-1.0   Q1>=1.0    Q2<0.5    Q2>=1.0  counts_ok  value_ok_any_Q  near_lower_than_far_Q1
  u1-P1     w1     T1     23       6     0 50.700001 56.900002 48.900002 49.500000  54.299999       NaN 56.200001        NaN      False           False                   False
  u1-P1     w1     T2     23       6     0 45.299999 52.299999 49.500000 46.099998  43.099998       NaN 54.500000        NaN      False           False                   False
  u1-P1     w2     T1     23       6     0 60.599998 65.900002 66.699997 59.000000  65.599998       NaN 62.799999        NaN      False           False                   False
  u1-P1     w2     T2     23       6     0 57.700001 59.799999 52.299999 59.200001  53.200001       NaN 63.400002        NaN      False           False                   False
  u1-P2     w1     T1    250     111    26 53.400002 53.299999 45.500000 48.000000  64.699997 84.900002 48.099998 104.500000      False           False                    True
  u1-P2     w1     T2    240     110    26 52.599998 53.500000 39.599998 47.799999  62.299999 81.400002 48.299999  89.199997      False            True                    True
  u1-P2     w2     T1    250     111    26 59.200001 58.700001 51.500000 54.000000  69.900002 86.900002 54.299999  95.500000      False           False                    True
  u1-P2     w2     T2    240     110    26 57.799999 57.400002 51.799999 53.099998  67.500000 81.300003 53.599998  86.400002      False           False                    True
u2 (P3)     w1     T1    286     132    27 58.299999 56.299999 48.200001 55.000000  65.400002 85.300003 51.900002 104.599998      False           False                    True
u2 (P3)     w1     T2    273     131    27 56.400002 55.900002 44.200001 53.200001  63.200001 82.900002 50.900002 102.199997      False           False                    True
u2 (P3)     w2     T1    286     132    27 63.299999 61.299999 55.200001 60.299999  69.599998 86.000000 57.799999  93.900002      False           False                    True
u2 (P3)     w2     T2    273     131    27 61.099998 59.599998 53.299999 58.200001  67.099998 81.199997 56.500000  85.900002      False           False                    True
Paper: 36% within 1.0 mm; n = 250 (< 0.5 mm), 160 (0.5 to 1.0), 46 (>= 1.0)
Readings with counts, value and order all holding: 0 of 12

Result: not reproduced. With P2 and the 20 to 120 ms window, ALM photoinhibition lowers thalamic activity to 48% (Q1) within 0.5 mm of the L2 centre, 62 to 65% at 0.5 to 1.0 mm and 81 to 85% at 1.0 mm or more: the reduction is concentrated near the centre. Within 1.0 mm it is to 52.6 to 53.4% (Q1) or 39.6 to 45.5% (Q3); only Q3 with correct trials (39.6%) is within 36 +/- 3.6%. With all units (u2, reading P3 of the answer) it is to 56.4 to 58.3% (Q1) or 44.2 to 48.2% (Q3). Near the centre the group counts (240 to 286) are within 250 +/- 25 except 286 (all units, correct and incorrect trials); farther away they (110 to 132, and 26 or 27) are below the paper's 160 and 46 in every reading, so no reading meets the whole criterion.

The criterion has no partial clause, and no reading meets it in full (see Changes of outcome, before the Summary). The third verification round agreed.

vm1-photoinhibition-no-effect¶

Photoinhibiting vibrissal M1 did not reduce thalALM activity (Results), or reduced VM/VAL activity less than ALM photoinhibition in the same neurons (Extended Data Fig. 8g legend).

The dandiset names no vM1 site. In the six thalamic sessions of mouse anm00264943, photostimulation at galvo position (0.5, 0.5) mm is interleaved with ALM photoinhibition, which fits the interleaved design of Extended Data Fig. 8f, g; it is taken here as the vM1 condition, an assumption the files cannot confirm. The paper has 46 cells from 3 mice; here 1 mouse. (a) paired t-test over neurons of the rate under vM1 photoinhibition against control; (b) paired t-test of the reduction under vM1 against the reduction under ALM photoinhibition. ALM photoinhibition at 1.5 mW (convention P, answer of 2026-10-20); variants, not judged: ALM at 0.79 mW (the power of the (0.5, 0.5) trials) and both powers. Window 20 to 120 ms; T1 and T2; VM/VAL (L2) under P1, P2 and P3, and, as variants, all putative and all units of the mouse.

In [27]:
m3 = thal[thal.subject == "anm00264943"]
sets = {"VM/VAL P1": m3[(m3.width_ms > 0.5) & (m3.vmval_d < 0.4)], "VM/VAL P2": m3[(m3.cell_type == "Wide width spiking") & (m3.vmval_d < 0.4)],
        "VM/VAL P3": m3[m3.vmval_d < 0.4], "putative P2": m3[m3.cell_type == "Wide width spiking"], "all": m3}
rows = []
for sname, d in sets.items():
    for tname, oc in T_READ.items():
        v = loop.photo_effect(sessions, d, "site0.5:delay:0.79", oc, "pw", 5, True)
        for aname, astim in (("ALM 1.5", "ALM:delay:1.5"), ("variant ALM 0.79", "ALM:delay:0.79"), ("variant ALM both", ["ALM:delay:0.79", "ALM:delay:1.5"])):
            a = loop.photo_effect(sessions, d, astim, oc, "pw", 5, True)
            j = v.index.intersection(a.index)
            if len(j) < 3:
                rows.append({"units": sname, "trials": tname, "alm": aname, "n": len(j)})
                continue
            pa = stats.ttest_rel(v.loc[j, "rate_pi"], v.loc[j, "rate_ctrl"])
            pb = stats.ttest_rel(-v.loc[j, "delta"], -a.loc[j, "delta"])
            rows.append({"units": sname, "trials": tname, "alm": aname, "n": len(j),
                         "ctrl": round(v.loc[j, "rate_ctrl"].mean(), 2), "vM1": round(v.loc[j, "rate_pi"].mean(), 2), "ALM": round(a.loc[j, "rate_pi"].mean(), 2),
                         "vM1_Q1": round(100 * v.loc[j, "rate_pi"].mean() / v.loc[j, "rate_ctrl"].mean(), 1),
                         "ALM_Q1": round(100 * a.loc[j, "rate_pi"].mean() / a.loc[j, "rate_ctrl"].mean(), 1),
                         "vM1_Q3": round(100 * v.loc[j, "ratio"].median(), 1), "ALM_Q3": round(100 * a.loc[j, "ratio"].median(), 1),
                         "a_p": pa.pvalue, "a_vM1_reduces": bool(v.loc[j, "delta"].mean() < 0 and pa.pvalue < 0.05),
                         "b_p": pb.pvalue, "b_vM1_less": bool((-v.loc[j, "delta"]).mean() < (-a.loc[j, "delta"]).mean() and pb.pvalue < 0.05)})
vm1 = pd.DataFrame(rows)
print(vm1.round(4).to_string(index=False))
m15 = vm1[vm1.alm == "ALM 1.5"]
print("ALM at 1.5 mW (convention P): rows where (a) no significant reduction under the (0.5, 0.5) site holds:",
      m15[~m15.a_vM1_reduces][["units", "trials"]].values.tolist(), "| where (b) holds:", m15[m15.b_vM1_less][["units", "trials"]].values.tolist())
print("Sessions of anm00264943 with (0.5, 0.5) trials:", sum(1 for s in sessions if (s["trials"].stim == "site0.5:delay:0.79").any()),
      "| trials:", sum(int((s["trials"].stim == "site0.5:delay:0.79").sum()) for s in sessions))
      units trials              alm  n  ctrl   vM1   ALM    vM1_Q1     ALM_Q1    vM1_Q3     ALM_Q3    a_p  a_vM1_reduces    b_p  b_vM1_less
  VM/VAL P1     T1          ALM 1.5  3 11.68  6.99  3.37 59.799999  28.900000 60.599998   7.700000 0.0706          False 0.3173       False
  VM/VAL P1     T1 variant ALM 0.79  3 11.68  6.99 13.77 59.799999 117.900002 60.599998 119.599998 0.0706          False 0.0537       False
  VM/VAL P1     T1 variant ALM both  3 11.68  6.99  9.39 59.799999  80.400002 60.599998  90.199997 0.0706          False 0.0833       False
  VM/VAL P1     T2          ALM 1.5  3 11.95  7.45  2.51 62.299999  21.000000 58.200001  10.600000 0.1030          False 0.1572       False
  VM/VAL P1     T2 variant ALM 0.79  3 11.95  7.45 13.32 62.299999 111.500000 58.200001 106.000000 0.1030          False 0.0300       False
  VM/VAL P1     T2 variant ALM both  3 11.95  7.45  9.44 62.299999  79.000000 58.200001  91.000000 0.1030          False 0.1750       False
  VM/VAL P2     T1          ALM 1.5 41 12.19 10.93  5.28 89.599998  43.299999 82.400002  32.700001 0.0583          False 0.0000        True
  VM/VAL P2     T1 variant ALM 0.79 42 12.19 10.87 11.16 89.199997  91.599998 82.300003  88.800003 0.0450           True 0.7256       False
  VM/VAL P2     T1 variant ALM both 42 12.19 10.87  8.48 89.199997  69.599998 82.300003  69.000000 0.0450           True 0.0012        True
  VM/VAL P2     T2          ALM 1.5 36 12.16 11.77  4.98 96.800003  41.000000 92.900002  25.000000 0.6197          False 0.0000        True
  VM/VAL P2     T2 variant ALM 0.79 37 12.30 11.99 11.54 97.500000  93.900002 97.400002  87.900002 0.6935          False 0.6450       False
  VM/VAL P2     T2 variant ALM both 37 12.30 11.99  9.16 97.500000  74.500000 97.400002  69.400002 0.6935          False 0.0016        True
  VM/VAL P3     T1          ALM 1.5 48 12.89 11.66  6.41 90.400002  49.700001 82.699997  35.700001 0.0404           True 0.0000        True
  VM/VAL P3     T1 variant ALM 0.79 49 12.87 11.59 12.05 90.099998  93.599998 82.400002  90.199997 0.0312           True 0.5184       False
  VM/VAL P3     T1 variant ALM both 49 12.87 11.59  9.46 90.099998  73.500000 82.400002  70.400002 0.0312           True 0.0010        True
  VM/VAL P3     T2          ALM 1.5 41 13.02 12.53  5.92 96.199997  45.500000 97.400002  25.299999 0.5017          False 0.0000        True
  VM/VAL P3     T2 variant ALM 0.79 42 13.12 12.71 12.45 96.900002  94.800003 98.099998  89.400002 0.5663          False 0.7614       False
  VM/VAL P3     T2 variant ALM both 42 13.12 12.71 10.01 96.900002  76.300003 98.099998  69.400002 0.5663          False 0.0009        True
putative P2     T1          ALM 1.5 60 11.52  9.85  4.86 85.500000  42.200001 80.400002  29.799999 0.0020           True 0.0000        True
putative P2     T1 variant ALM 0.79 61 11.53  9.83 10.87 85.300003  94.300003 80.199997  90.199997 0.0014           True 0.1140       False
putative P2     T1 variant ALM both 61 11.53  9.83  8.24 85.300003  71.500000 80.199997  71.400002 0.0014           True 0.0050        True
putative P2     T2          ALM 1.5 54 11.50 10.39  4.64 90.400002  40.299999 83.000000  24.200001 0.0769          False 0.0000        True
putative P2     T2 variant ALM 0.79 56 11.62 10.48 11.13 90.199997  95.800003 83.000000  95.900002 0.0655          False 0.4081       False
putative P2     T2 variant ALM both 56 11.62 10.48  8.73 90.199997  75.099998 83.000000  69.400002 0.0655          False 0.0110        True
        all     T1          ALM 1.5 67 12.09 10.48  5.71 86.699997  47.200001 80.599998  32.700001 0.0014           True 0.0000        True
        all     T1 variant ALM 0.79 68 12.09 10.46 11.54 86.500000  95.500000 80.400002  91.000000 0.0010           True 0.0671       False
        all     T1 variant ALM both 68 12.09 10.46  8.96 86.500000  74.199997 80.400002  72.599998 0.0010           True 0.0040        True
        all     T2          ALM 1.5 59 12.16 11.04  5.32 90.800003  43.799999 83.099998  25.299999 0.0603          False 0.0000        True
        all     T2 variant ALM 0.79 61 12.24 11.10 11.79 90.699997  96.300003 83.099998  95.500000 0.0514          False 0.3464       False
        all     T2 variant ALM both 61 12.24 11.10  9.35 90.699997  76.400002 83.099998  69.500000 0.0514          False 0.0066        True
ALM at 1.5 mW (convention P): rows where (a) no significant reduction under the (0.5, 0.5) site holds: [['VM/VAL P1', 'T1'], ['VM/VAL P1', 'T2'], ['VM/VAL P2', 'T1'], ['VM/VAL P2', 'T2'], ['VM/VAL P3', 'T2'], ['putative P2', 'T2'], ['all', 'T2']] | where (b) holds: [['VM/VAL P2', 'T1'], ['VM/VAL P2', 'T2'], ['VM/VAL P3', 'T1'], ['VM/VAL P3', 'T2'], ['putative P2', 'T1'], ['putative P2', 'T2'], ['all', 'T1'], ['all', 'T2']]
Sessions of anm00264943 with (0.5, 0.5) trials: 6 | trials: 127

Result: blocked (metadata insufficient). The site at galvo (0.5, 0.5) mm is not named in the files, and the answer of 2026-10-20 says the paper does not say which condition is vM1. Taking it as vM1 and comparing with ALM at 1.5 mW, as the answer fixes: in 41 VM/VAL units (P2, T1) of one mouse it lowers activity to 89.6% of control (Q1; paired p = 0.058; T2 96.8%, p = 0.62), and ALM photoinhibition lowers the same units to 43.3%, a larger reduction (p < 0.0001). (a) and (b) hold together under P2 with T1 and T2 and under P3 with T2; under P3 with T1 (48 units) the (0.5, 0.5) site reduces activity significantly (90.4%, p = 0.040), so (a) fails there; under P1 only 3 units enter. In the variant with ALM at 0.79 mW the ALM reduction (91.6%, P2, T1) is no larger (p = 0.73). The paper's 46 cells come from 3 mice, these from 1.

snr-photoinhibition¶

ALM photoinhibition changed only a small fraction of SNr GABAergic neurons (48/181 significantly inhibited, 23/181 activated), more decreasing than increasing, and reduced SNr activity overall by 3.6 spikes per s (8.3%), which argues against SNr mediating the thalamic reduction.

SNr units of the dandiset (181; the paper's 46 wider units are not deposited, see snr-unit-properties) under P1 (< 0.45 ms, 171 units) and P2 (label 'Narrow width spiking', 146 units), and all 181 as a variant; ALM photoinhibition 1.5 mW, 20 to 120 ms; minimum photostimulus trials (a) none, (b) 5; T1, T2; Student, Welch. Bootstrap over neurons, 10000 rounds; p is the fraction of rounds with at least as many up- as down-modulated neurons.

In [28]:
rng = np.random.default_rng(601)
GABA["all 181"] = snr
rows, SNR = [], {}
for p, d in GABA.items():
    for mt in (0, 5):
        for tname, oc in T_READ.items():
            for ev in (True, False):
                df = loop.photo_effect(sessions, d, "ALM:delay:1.5", oc, "pw", mt, ev)
                SNR[(p, mt, tname, ev)] = df
                down = (df.sig & (df.delta < 0)).values
                up = (df.sig & (df.delta > 0)).values
                k = rng.integers(0, len(df), (10000, len(df)))
                pb = float(np.mean(up[k].sum(1) >= down[k].sum(1)))
                red = df.rate_ctrl.mean() - df.rate_pi.mean()
                rows.append({"units": p, "min_trials": mt, "trials": tname, "test": "Student" if ev else "Welch", "n": len(df),
                             "sig_inhibited": int(down.sum()), "sig_activated": int(up.sum()), "reduction": round(red, 2),
                             "reduction_%": round(100 * red / df.rate_ctrl.mean(), 2), "rate_ctrl": round(df.rate_ctrl.mean(), 2), "boot_p": pb,
                             "p_nan": int(df.p.isna().sum())})
sn = pd.DataFrame(rows)
sn["within_tol"] = ((sn.n - 181).abs() <= 18) & ((sn.sig_inhibited - 48).abs() <= 4.8) & ((sn.sig_activated - 23).abs() <= 2.3) & \
    ((sn.reduction - 3.6).abs() <= 0.36) & ((sn["reduction_%"] - 8.3).abs() <= 0.83) & (sn.boot_p < 0.01)
print(sn.to_string(index=False))
print("Paper: 227 SNr units, 181 putative GABAergic; 48 inhibited, 23 activated; reduction 3.6 spikes/s (8.3%); bootstrap p < 0.01")
print("SNr units in the dandiset:", len(snr), "(paper 227 +/- 23)")
print("Readings within tolerance:", int(sn.within_tol.sum()), "of", len(sn))
d = SNR[("P2", 5, "T1", True)].join(units[["subject"]])
print("\nBy mouse (P2, 5 trials, T1, Student):")
print(d.groupby("subject").agg(n=("delta", "size"), sig_inh=("sig", lambda x: int((x & (d.loc[x.index, "delta"] < 0)).sum())),
                               sig_act=("sig", lambda x: int((x & (d.loc[x.index, "delta"] > 0)).sum())),
                               ctrl=("rate_ctrl", "mean"), pi=("rate_pi", "mean")).round(2).to_string())
  units  min_trials trials    test   n  sig_inhibited  sig_activated  reduction  reduction_%  rate_ctrl  boot_p  p_nan  within_tol
     P1           0     T1 Student 171             45             21       2.33         5.97  39.009998  0.0009      0       False
     P1           0     T1   Welch 171             50             21       2.33         5.97  39.009998  0.0003      0       False
     P1           0     T2 Student 171             36             18       2.40         6.12  39.209999  0.0075      4       False
     P1           0     T2   Welch 171             41             17       2.40         6.12  39.209999  0.0014      4       False
     P1           5     T1 Student 170             44             21       2.25         5.77  39.080002  0.0019      0       False
     P1           5     T1   Welch 170             50             21       2.25         5.77  39.080002  0.0003      0       False
     P1           5     T2 Student 166             36             18       2.44         6.26  38.950001  0.0074      0       False
     P1           5     T2   Welch 166             41             17       2.44         6.26  38.950001  0.0005      0       False
     P2           0     T1 Student 146             35             18       2.68         6.49  41.279999  0.0087      0       False
     P2           0     T1   Welch 146             40             18       2.68         6.49  41.279999  0.0020      0       False
     P2           0     T2 Student 146             31             15       2.76         6.64  41.520000  0.0102      3       False
     P2           0     T2   Welch 146             36             14       2.76         6.64  41.520000  0.0014      3       False
     P2           5     T1 Student 146             35             18       2.68         6.49  41.279999  0.0105      0       False
     P2           5     T1   Welch 146             40             18       2.68         6.49  41.279999  0.0022      0       False
     P2           5     T2 Student 142             31             15       2.98         7.23  41.180000  0.0080      0       False
     P2           5     T2   Welch 142             36             14       2.98         7.23  41.180000  0.0009      0       False
all 181           0     T1 Student 181             46             23       2.17         5.76  37.650002  0.0030      0       False
all 181           0     T1   Welch 181             50             22       2.17         5.76  37.650002  0.0004      0       False
all 181           0     T2 Student 181             36             20       2.21         5.84  37.840000  0.0191      4       False
all 181           0     T2   Welch 181             41             18       2.21         5.84  37.840000  0.0013      4       False
all 181           5     T1 Student 180             45             23       2.10         5.57  37.709999  0.0030      0       False
all 181           5     T1   Welch 180             50             22       2.10         5.57  37.709999  0.0003      0       False
all 181           5     T2 Student 176             36             20       2.24         5.97  37.549999  0.0163      0       False
all 181           5     T2   Welch 176             41             18       2.24         5.97  37.549999  0.0007      0       False
Paper: 227 SNr units, 181 putative GABAergic; 48 inhibited, 23 activated; reduction 3.6 spikes/s (8.3%); bootstrap p < 0.01
SNr units in the dandiset: 181 (paper 227 +/- 23)
Readings within tolerance: 0 of 24

By mouse (P2, 5 trials, T1, Student):
              n  sig_inh  sig_act       ctrl         pi
subject                                                
anm00261334  36        5        2  39.680000  36.459999
anm00261335  49        9       11  35.950001  35.410000
anm00261336  61       21        5  46.500000  42.419998

Result: not reproduced. The dandiset holds 181 SNr units, 171 under P1 and 146 under P2 (the 'Narrow width spiking' label); the paper's 46 wider units are not deposited (snr-unit-properties). Under P1 with correct and incorrect trials, 44 to 50 units are significantly inhibited and 21 activated (paper 48 and 23), and more decrease than increase (bootstrap p = 0.0003 to 0.0019); under P2, 35 to 40 and 18 (p = 0.0020 to 0.0105). The overall reduction is 2.25 to 2.44 spikes/s (5.8 to 6.3% of control) under P1 and 2.68 to 2.98 spikes/s (6.5 to 7.2%) under P2, against 3.6 spikes/s (8.3%), out of tolerance in every reading. Under P1 the counts and the test agree with the paper; the reduction is weaker.

The criterion has no partial clause, and no reading meets it in full (see Changes of outcome, before the Summary). The third verification round agreed.

snr-unit-properties¶

Putative GABAergic SNr neurons had high spike rates (40.9 spikes per s) compared with the other SNr units (23.4), and most of them (152/181) were selective for trial type, like ALM and VM/VAL.

Mean rate per unit, (a) over the session (spikes over the time from the first trial start to the last trial end), (b) within trials (spikes in trials over the summed trial durations); then the mean over units. Selectivity by convention S under every reading.

In [29]:
rate_a = pd.Series(snr.n_spikes.values / (snr.last_spike - snr.first_spike).values, index=snr.index)
rate_b = pd.Series([np.nansum(sessions[r.session]["counts"]["trial"][r.unit]) /
                    (sessions[r.session]["trials"].stop_time - sessions[r.session]["trials"].start_time)[sessions[r.session]["valid"][r.unit]].sum()
                    for r in snr.itertuples()], index=snr.index)
rate_s = pd.Series([np.nansum(sessions[r.session]["counts"]["stored"][r.unit]) /
                    (sessions[r.session]["trials"].stored_end - sessions[r.session]["trials"].start_time)[sessions[r.session]["valid"][r.unit]].sum()
                    for r in snr.itertuples()], index=snr.index)
rate_w = pd.Series([np.nanmean(sessions[r.session]["counts"]["sample"][r.unit]) / loop.SAMPLE_S for r in snr.itertuples()], index=snr.index)
rows = []
for p in ("P1", "P2"):
    g = GABA[p].index
    o = snr.index.difference(g)
    for rname, rv in (("a session (unit's span)", rate_a), ("b trials", rate_b), ("variant: stored part of trials", rate_s),
                      ("variant: sample epoch", rate_w)):
        rows.append({"units": p, "rate": rname, "n_gaba": len(g), "gaba_mean": round(rv[g].mean(), 2), "gaba_sd": round(rv[g].std(), 2),
                     "n_other": len(o), "other_mean": round(rv[o].mean(), 2) if len(o) else np.nan, "other_sd": round(rv[o].std(), 2) if len(o) > 1 else np.nan})
print(pd.DataFrame(rows).to_string(index=False))
print("Paper: 40.9 +/- 21.5 (n = 181) against 23.4 +/- 17.0 (n = 46)")
sel_rows = [{"units": p, "reading": k, "n": len(GABA[p]), "selective": int(SEL[k].loc[GABA[p].index, "selective"].sum())} for p in ("P1", "P2") for k in SEL]
sel_rows = pd.DataFrame(sel_rows)
sel_rows["within_tol"] = (sel_rows.selective - 152).abs() <= 15
print(sel_rows.to_string(index=False))
print("Paper: 152/181 selective")
units                           rate  n_gaba  gaba_mean  gaba_sd  n_other  other_mean  other_sd
   P1        a session (unit's span)     171  20.770000    11.22       10        7.58      5.48
   P1                       b trials     171  20.710000    11.20       10        7.56      5.46
   P1 variant: stored part of trials     171  35.960000    19.35       10       13.07      9.48
   P1          variant: sample epoch     171  37.250000    19.99       10       13.86      9.81
   P2        a session (unit's span)     146  22.020000    11.03       35       11.80      8.96
   P2                       b trials     146  21.960000    11.02       35       11.77      8.93
   P2 variant: stored part of trials     146  38.130000    19.04       35       20.34     15.28
   P2          variant: sample epoch     146  39.299999    19.68       35       22.01     16.60
Paper: 40.9 +/- 21.5 (n = 181) against 23.4 +/- 17.0 (n = 46)
units               reading   n  selective  within_tol
   P1 control/R1/Student/c1 171        139        True
   P1 control/R1/Student/c2 171        133       False
   P1   control/R1/Welch/c1 171        137        True
   P1   control/R1/Welch/c2 171        133       False
   P1 control/R2/Student/c1 171        141        True
   P1 control/R2/Student/c2 171        135       False
   P1   control/R2/Welch/c1 171        140        True
   P1   control/R2/Welch/c2 171        134       False
   P1     all/R1/Student/c1 171        142        True
   P1     all/R1/Student/c2 171        134       False
   P1       all/R1/Welch/c1 171        140        True
   P1       all/R1/Welch/c2 171        134       False
   P1     all/R2/Student/c1 171        143        True
   P1     all/R2/Student/c2 171        134       False
   P1       all/R2/Welch/c1 171        143        True
   P1       all/R2/Welch/c2 171        133       False
   P2 control/R1/Student/c1 146        120       False
   P2 control/R1/Student/c2 146        117       False
   P2   control/R1/Welch/c1 146        119       False
   P2   control/R1/Welch/c2 146        117       False
   P2 control/R2/Student/c1 146        121       False
   P2 control/R2/Student/c2 146        118       False
   P2   control/R2/Welch/c1 146        121       False
   P2   control/R2/Welch/c2 146        117       False
   P2     all/R1/Student/c1 146        122       False
   P2     all/R1/Student/c2 146        115       False
   P2       all/R1/Welch/c1 146        120       False
   P2       all/R1/Welch/c2 146        115       False
   P2     all/R2/Student/c1 146        122       False
   P2     all/R2/Student/c2 146        115       False
   P2       all/R2/Welch/c1 146        122       False
   P2       all/R2/Welch/c2 146        114       False
Paper: 152/181 selective

Result: blocked (data missing). Spikes are stored for only about 5 s of each 9 s trial, so neither reading of the mean rate can be computed as defined; as computed, both give 20.7 (P1) or 22.0 (P2) spikes/s for the putative GABAergic units against 40.9, biased low because they divide by time with no stored spikes. Over the stored part of each trial (a variant, not deciding) the same units fire 36.0 (P1) or 38.1 (P2) spikes/s, and the other units 13.1 (10 units, P1) or 20.3 (35 units, P2) against 23.4. Only 10 (P1) or 35 (P2) other SNr units are deposited, against 46, and under P2 most of them are labelled 'Cannot be determined'. The selectivity count can be tested: 139 of 171 units (P1) are selective under the first reading, within 152 +/- 15 (137 to 143 in the eight c1 readings); under P2, 114 to 122 of 146, below it.

fig6e-onset-latencies¶

After ALM photoinhibition onset, ALM pyramidal neurons were silenced after 8.1 ms and VM/VAL activity reduced after 10.9 ms; SNr neurons changed later, after 15.2 ms.

Convention O (O1, O2), T1 and T2, bootstrap SEM (1000). Populations: ALM putative pyramidal units of the PV-Cre x Ai32 ALM sessions with ALM photoinhibition at 1.5 mW (at least 5 trials; the paper has 256), VM/VAL units of fig6c-vmval-reduced (P1, P2, and P3 with the ALM P1 or P2 population), and the significantly modulated SNr units of snr-photoinhibition (P2, 5 trials, T1, Student): (a) inhibited only, (b) inhibited and activated with the sign of the activated flipped. Readings (d1) onsets from photostimulus onset; (d2) SNr and VM/VAL onsets minus the ALM onset.

In [30]:
rng = np.random.default_rng(602)
rows = []
for p in ("P1", "P2"):
    pa = PYR[p][(PYR[p].genotype == "Ai32 x PV-Cre") & (PYR[p].ogen_site == "ALM")]
    pa = pa.loc[loop.photo_effect(sessions, pa, "ALM:delay:1.5", loop.KEEP, "pw", 5).index]
    rows += onset_rows(f"ALM PV {p}", pa, "ALM:delay:1.5")
    vm = pv_vm[p].loc[F6[(p, "T1", True)].index]
    rows += onset_rows(f"VM/VAL {p}", vm, "ALM:delay:1.5")
sd = SNR[("P2", 5, "T1", True)]
inh = sd[sd.sig & (sd.delta < 0)]
mod = sd[sd.sig]
rows += onset_rows("SNr inhibited (a)", snr.loc[inh.index], "ALM:delay:1.5")
rows += onset_rows("SNr modulated, flipped (b)", snr.loc[mod.index], "ALM:delay:1.5", -1, flip=(mod.delta > 0).values)
rows += onset_rows("VM/VAL P3", pv_vm["P3"].loc[F6[("P3", "T1", True)].index], "ALM:delay:1.5")
on6 = pd.DataFrame(rows)
print(on6.to_string(index=False))
print("Paper: ALM 8.1 +/- 1.2 ms (n = 256), VM/VAL 10.9 +/- 2.9 ms (n = 201), SNr 15.2 +/- 4.6 ms (48 inhibited)")
w = on6.pivot_table(index=["trials", "reading"], columns="population", values="onset_ms")
res = []
for p, pv in (("P1", "P1"), ("P2", "P2"), ("P1", "P3"), ("P2", "P3")):
    for sn_ in ("SNr inhibited (a)", "SNr modulated, flipped (b)"):
        for d in ("d1", "d2"):
            if f"ALM PV {p}" not in w or f"VM/VAL {pv}" not in w:
                res.append({"units": p, "vmval_units": pv, "snr": sn_, "reading": d, "rows_ok": "no ALM or VM/VAL population"})
                continue
            a_, v_, s_ = w[f"ALM PV {p}"], w[f"VM/VAL {pv}"], w[sn_]
            if d == "d2":
                v_, s_ = v_ - a_, s_ - a_
            ok = (a_.sub(8.1).abs() <= 1.2) & (v_.sub(10.9).abs() <= 2.9) & (s_.sub(15.2).abs() <= 4.6) & (s_ > v_) & (s_ > a_ if d == "d1" else True)
            res.append({"units": p, "vmval_units": pv, "snr": sn_, "reading": d, "rows_ok": ok[ok].index.tolist()})
print(pd.DataFrame(res).to_string(index=False))
                population   n trials reading  onset_ms  sem_ms  boot_no_onset
                 ALM PV P1   0    NaN     NaN       NaN     NaN            NaN
                 VM/VAL P1  15     T1      O1      20.0    8.44            0.0
                 VM/VAL P1  15     T1      O2      22.0    7.20          592.0
                 VM/VAL P1  15     T2      O1       7.0   10.32            0.0
                 VM/VAL P1  15     T2      O2       7.0    2.28          967.0
                 ALM PV P2 151     T1      O1       7.0    2.33            0.0
                 ALM PV P2 151     T1      O2       7.0    2.22            0.0
                 ALM PV P2 151     T2      O1       6.0    2.45            0.0
                 ALM PV P2 151     T2      O2       7.0    2.17            1.0
                 VM/VAL P2 172     T1      O1      14.0    5.75            0.0
                 VM/VAL P2 172     T1      O2      14.0    6.29            0.0
                 VM/VAL P2 172     T2      O1       4.0    4.44            0.0
                 VM/VAL P2 172     T2      O2       4.0    5.43            0.0
         SNr inhibited (a)  35     T1      O1      12.0    6.09            0.0
         SNr inhibited (a)  35     T1      O2      31.0   11.44            0.0
         SNr inhibited (a)  35     T2      O1      12.0    5.93            0.0
         SNr inhibited (a)  35     T2      O2      32.0   10.67            0.0
SNr modulated, flipped (b)  53     T1      O1      20.0    6.26            0.0
SNr modulated, flipped (b)  53     T1      O2      27.0    7.35            0.0
SNr modulated, flipped (b)  53     T2      O1      12.0    6.56            0.0
SNr modulated, flipped (b)  53     T2      O2      27.0    8.64            0.0
                 VM/VAL P3 201     T1      O1      14.0    6.57            0.0
                 VM/VAL P3 201     T1      O2      14.0    6.49            0.0
                 VM/VAL P3 201     T2      O1       7.0    5.76            0.0
                 VM/VAL P3 201     T2      O2      14.0    5.99            0.0
Paper: ALM 8.1 +/- 1.2 ms (n = 256), VM/VAL 10.9 +/- 2.9 ms (n = 201), SNr 15.2 +/- 4.6 ms (48 inhibited)
units vmval_units                        snr reading                     rows_ok
   P1          P1          SNr inhibited (a)      d1 no ALM or VM/VAL population
   P1          P1          SNr inhibited (a)      d2 no ALM or VM/VAL population
   P1          P1 SNr modulated, flipped (b)      d1 no ALM or VM/VAL population
   P1          P1 SNr modulated, flipped (b)      d2 no ALM or VM/VAL population
   P2          P2          SNr inhibited (a)      d1                          []
   P2          P2          SNr inhibited (a)      d2                          []
   P2          P2 SNr modulated, flipped (b)      d1                          []
   P2          P2 SNr modulated, flipped (b)      d2                          []
   P1          P3          SNr inhibited (a)      d1 no ALM or VM/VAL population
   P1          P3          SNr inhibited (a)      d2 no ALM or VM/VAL population
   P1          P3 SNr modulated, flipped (b)      d1 no ALM or VM/VAL population
   P1          P3 SNr modulated, flipped (b)      d2 no ALM or VM/VAL population
   P2          P3          SNr inhibited (a)      d1                          []
   P2          P3          SNr inhibited (a)      d2                          []
   P2          P3 SNr modulated, flipped (b)      d1                          []
   P2          P3 SNr modulated, flipped (b)      d2                          []

Result: not reproduced. ALM putative pyramidal units of the PV-Cre x Ai32 ALM sessions with ALM photoinhibition number 151 with P2 and none with P1 (all computed widths in those sessions are 0.6 ms or less), against 256; their onset is 6 or 7 ms (8.1 +/- 1.2). VM/VAL onsets are 14 ms (T1) or 4 ms (T2) with P2 and 14 ms (T1) or 7 to 14 ms (T2) with P3 (201 units), against 10.9 +/- 2.9, and SNr onsets 12 to 32 ms (P2 SNr units, 35 inhibited) against 15.2 +/- 4.6. No reading puts all three within tolerance with SNr latest.

selectivity-time-course¶

In ALM and in VM/VAL, population selectivity emerged in the sample epoch and increased throughout the delay epoch; it peaked at the beginning of the response epoch in ALM and during the response epoch in VM/VAL.

Extended Data Fig. 4c: per neuron, the preferred trial type from spike counts (sample, delay and response epochs, R1) in a random half of the correct trials, selectivity as preferred minus non-preferred rate in the other half, 200 ms windows stepped by 100 ms, SEM by bootstrapping over neurons (1000). Neurons (a) all, (b) selective (reading control/R1/Student/c1, the first of each list). Trials: readings (t1) correct control trials and (t2) all correct trials (answer of 2026-10-20). VM/VAL units under P1, P2 and P3 (all VM/VAL units). Only trials with a 1.3 s delay enter, so that the epochs align. "Emerged": mean above twice its SEM in a window inside the sample epoch; "increased": last 200 ms of the delay above the first; the maximum is located.

In [31]:
rng = np.random.default_rng(701)
tc_t = loop.TC_SPAN[0] + loop.BIN_S * np.arange(int(round((loop.TC_SPAN[1] - loop.TC_SPAN[0]) / loop.BIN_S)))
win_t = tc_t[:-1] + 0.1        # centre of each 200 ms window (two 100 ms bins)


def time_course(sel, ctrl_only):
    out = []
    for r in sel.itertuples():
        s = sessions[r.session]
        t = s["trials"]
        m = (t.response == "correct").values & (np.abs(t.delay_s.values - 1.3) < 0.05) & s["valid"][r.unit] & t.tc_ok.values
        if ctrl_only:
            m = m & (t.stim == "none").values
        ci, ii = np.flatnonzero(m & t.contra.values), np.flatnonzero(m & ~t.contra.values)
        if len(ci) < 4 or len(ii) < 4:
            continue
        ci, ii = rng.permutation(ci), rng.permutation(ii)
        ca, cb, ia, ib = ci[: len(ci) // 2], ci[len(ci) // 2:], ii[: len(ii) // 2], ii[len(ii) // 2:]
        tot = s["counts"]["sample"][r.unit] + s["counts"]["delay"][r.unit] + s["counts"]["R1"][r.unit]
        pref_c = tot[ca].mean() >= tot[ia].mean()
        x = s["tc"][r.unit].astype(float)
        w2 = (x[:, :-1] + x[:, 1:]) / 0.2
        sel_ = w2[cb].mean(0) - w2[ib].mean(0)
        out.append(sel_ if pref_c else -sel_)
    return np.array(out)


rows = []
curves = {}
for area, base in (("ALM P1", PYR["P1"]), ("ALM P2", PYR["P2"]), ("VM/VAL P1", VMVAL["P1"]), ("VM/VAL P2", VMVAL["P2"]),
                   ("VM/VAL P3", VM26["P3"])):
    for nsel in ("a", "b"):
        sel = base if nsel == "a" else base[SEL["control/R1/Student/c1"].loc[base.index, "selective"]]
        for ctrl_only in (True, False):
            tc = time_course(sel, ctrl_only)
            mean = tc.mean(0)
            boot = np.array([tc[rng.integers(0, len(tc), len(tc))].mean(0) for _ in range(1000)])
            sem = boot.std(0)
            in_sample = (win_t - 0.1 >= 0) & (win_t + 0.1 <= 1.3)
            emerged = bool((mean[in_sample] > 2 * sem[in_sample]).any())
            first_d = np.argmin(np.abs(win_t - 1.4))
            last_d = np.argmin(np.abs(win_t - 2.5))
            imax = int(np.argmax(mean))
            tmax = win_t[imax]
            epoch = "sample" if tmax < 1.3 else "delay" if tmax < 2.6 else "response"
            curves[(area, nsel, ctrl_only)] = (mean, sem)
            rows.append({"area": area, "neurons": nsel, "trials": "t1 correct control" if ctrl_only else "t2 all correct", "n": len(tc),
                         "first_emerging_window_s": round(float(win_t[in_sample][mean[in_sample] > 2 * sem[in_sample]][0]), 2) if emerged else np.nan,
                         "emerged_in_sample": emerged, "delay_first": round(mean[first_d], 2), "delay_last": round(mean[last_d], 2),
                         "increased": bool(mean[last_d] > mean[first_d]), "max_at_s": round(float(tmax), 2), "max_epoch": epoch,
                         "max_within_first_200ms_of_response": bool(2.6 <= tmax <= 2.8), "max_value": round(float(mean[imax]), 2)})
stc = pd.DataFrame(rows)
print(stc.to_string(index=False))
print("Time from pole onset: sample 0 to 1.3 s, delay 1.3 to 2.6 s, response from 2.6 s; window centres from",
      round(win_t[0], 2), "to", round(win_t[-1], 2), "s")
ok = stc.emerged_in_sample & stc.increased & (stc.max_epoch == "response")
print("Rows meeting all three:", stc[ok][["area", "neurons", "trials"]].values.tolist())
print("Readings (unit reading, neurons, trials) meeting all three in both ALM and VM/VAL:",
      [(pa, pv, nsel, tr) for pa in ("ALM P1", "ALM P2") for pv in ("VM/VAL P1", "VM/VAL P2", "VM/VAL P3") for nsel in ("a", "b")
       for tr in ("t1 correct control", "t2 all correct")
       if ok[(stc.area == pa) & (stc.neurons == nsel) & (stc.trials == tr)].all() and ok[(stc.area == pv) & (stc.neurons == nsel) & (stc.trials == tr)].all()])
fig, ax = plt.subplots(figsize=(7, 2.8))
for key, col in ((("ALM P2", "a", True), "k"), (("VM/VAL P2", "a", True), "tab:blue")):
    m, se = curves[key]
    ax.plot(win_t, m, color=col, label=f"{key[0]} (all neurons, control)")
    ax.fill_between(win_t, m - se, m + se, color=col, alpha=0.2)
for x in (0, 1.3, 2.6):
    ax.axvline(x, ls="--", c="grey", lw=0.7)
ax.set_xlabel("s from pole onset")
ax.set_ylabel("selectivity (spikes/s)")
ax.legend(fontsize=7)
plt.show()
print("Plotted range (spikes/s):", round(min(curves[k][0].min() for k in (("ALM P2", "a", True), ("VM/VAL P2", "a", True))), 2), "to",
      round(max(curves[k][0].max() for k in (("ALM P2", "a", True), ("VM/VAL P2", "a", True))), 2))
     area neurons             trials   n  first_emerging_window_s  emerged_in_sample  delay_first  delay_last  increased  max_at_s max_epoch  max_within_first_200ms_of_response  max_value
   ALM P1       a t1 correct control 577                      0.1               True         1.03        1.02      False       3.2  response                               False       2.17
   ALM P1       a     t2 all correct 577                      0.1               True         1.00        1.05       True       3.0  response                               False       2.26
   ALM P1       b t1 correct control 398                      0.1               True         1.57        1.65       True       3.1  response                               False       3.15
   ALM P1       b     t2 all correct 398                      0.1               True         1.30        1.50       True       3.1  response                               False       3.26
   ALM P2       a t1 correct control 810                      0.1               True         0.82        1.15       True       3.0  response                               False       2.38
   ALM P2       a     t2 all correct 810                      0.1               True         0.85        1.10       True       3.0  response                               False       2.31
   ALM P2       b t1 correct control 571                      0.1               True         1.33        1.69       True       3.0  response                               False       3.19
   ALM P2       b     t2 all correct 571                      0.2               True         1.09        1.34       True       3.0  response                               False       3.24
VM/VAL P1       a t1 correct control  20                      0.5               True         1.71        1.05      False       3.1  response                               False       5.49
VM/VAL P1       a     t2 all correct  20                      0.8               True         1.90        1.43      False       3.1  response                               False       6.16
VM/VAL P1       b t1 correct control  13                      NaN              False         3.22        2.03      False       3.0  response                               False       7.95
VM/VAL P1       b     t2 all correct  13                      0.2               True         3.09        2.31      False       3.0  response                               False       7.40
VM/VAL P2       a t1 correct control 220                      0.2               True         0.83        0.17      False       3.4  response                               False       2.75
VM/VAL P2       a     t2 all correct 221                      0.3               True         0.54        0.41      False       3.1  response                               False       2.26
VM/VAL P2       b t1 correct control 149                      0.2               True         0.98        0.59      False       3.3  response                               False       3.62
VM/VAL P2       b     t2 all correct 149                      0.1               True         1.09        0.94      False       3.4  response                               False       3.63
VM/VAL P3       a t1 correct control 257                      0.5               True         0.57        0.53      False       3.3  response                               False       2.68
VM/VAL P3       a     t2 all correct 258                      0.3               True        -0.05        0.38       True       3.3  response                               False       2.85
VM/VAL P3       b t1 correct control 174                      0.1               True         0.42        0.57       True       3.0  response                               False       4.25
VM/VAL P3       b     t2 all correct 174                      0.2               True         0.65        0.80       True       3.3  response                               False       4.25
Time from pole onset: sample 0 to 1.3 s, delay 1.3 to 2.6 s, response from 2.6 s; window centres from -0.4 to 4.0 s
Rows meeting all three: [['ALM P1', 'a', 't2 all correct'], ['ALM P1', 'b', 't1 correct control'], ['ALM P1', 'b', 't2 all correct'], ['ALM P2', 'a', 't1 correct control'], ['ALM P2', 'a', 't2 all correct'], ['ALM P2', 'b', 't1 correct control'], ['ALM P2', 'b', 't2 all correct'], ['VM/VAL P3', 'a', 't2 all correct'], ['VM/VAL P3', 'b', 't1 correct control'], ['VM/VAL P3', 'b', 't2 all correct']]
Readings (unit reading, neurons, trials) meeting all three in both ALM and VM/VAL: [('ALM P1', 'VM/VAL P3', 'a', 't2 all correct'), ('ALM P1', 'VM/VAL P3', 'b', 't1 correct control'), ('ALM P1', 'VM/VAL P3', 'b', 't2 all correct'), ('ALM P2', 'VM/VAL P3', 'a', 't2 all correct'), ('ALM P2', 'VM/VAL P3', 'b', 't1 correct control'), ('ALM P2', 'VM/VAL P3', 'b', 't2 all correct')]
No description has been provided for this image
Plotted range (spikes/s): -0.3 to 2.75

Result: reproduced. Under P3 for VM/VAL (all 258 VM/VAL units, all correct trials, t2) with ALM P2 (810 units, t2), both areas meet the criterion: selectivity emerges in the sample epoch (first window above twice its SEM centred at 0.1 s in ALM, 0.3 s in VM/VAL), is higher at the end of the delay than at its start (ALM 0.85 to 1.10, VM/VAL -0.05 to 0.38 spikes/s), and peaks in the response epoch (3.0 and 3.3 s). Six combinations of readings meet it in both areas, all with VM/VAL P3 (all neurons with t2, selective neurons with t1 and t2) and ALM P1 or P2. With P1 or P2, VM/VAL selectivity is lower at the end of the delay than at its start in every reading (P2, all neurons, t1: 0.83 against 0.17), and with P3, all neurons and t1 as well (0.57 against 0.53), so the delay increase in VM/VAL holds in 3 of 12 VM/VAL readings. The ALM peak lies 0.4 to 0.6 s after the go cue, not within its first 200 ms. Only trials whose spikes are stored to 4.1 s after pole onset enter.

wc-near-threshold¶

During the delay epoch the mean membrane potential of ALM neurons was close to spike threshold, 12.7 mV below it on average.

All 36 whole-cell recordings (each has more than 20 kept trials). Threshold: Vm at the kink of convention V, mean over the cell's spikes (all spikes in the recording). Basal Vm: (a) 0 to 0.5 s before trial onset (start_time), kept trials; (b) the delay epoch of kept control trials, spikes clipped. Per cell threshold minus basal, then the mean over cells with its SEM. Variants: the deposited kink (first sample of each clipped stretch plus 0.5 ms), and (a) without cell_21_1, whose trial start times are shifted by one row.

In [32]:
rows = []
for c in cells:
    t = c["trials"]
    k = t.response.isin(loop.KEEP).values
    rows.append({"cell": c["meta"]["cell"], "subject": c["meta"]["subject"],
                 "group": c["meta"]["description"].replace("ALM whole cell recording during ", ""), "kept_trials": int(k.sum()),
                 "spikes": c["meta"]["n_spikes"], "kink_at_window_start": round(float(np.mean(c["meta"]["kink_at_edge"])), 3),
                 "threshold": np.nanmean(c["meta"]["threshold_mV"]),
                 "threshold_kink_not_at_start": np.nanmean(c["meta"]["threshold_mV"][~c["meta"]["kink_at_edge"]]),
                 "threshold_deposited_kink": np.nanmean(c["meta"]["deposited_kink_mV"]),
                 "basal_a": np.nanmean(t.basal_vm[k]), "basal_b": np.nanmean(t.delay_vm[k & ~t.pi.values])})
wt = pd.DataFrame(rows)
wt["a"] = wt.threshold - wt.basal_a
wt["b"] = wt.threshold - wt.basal_b
wt["a_dep"] = wt.threshold_deposited_kink - wt.basal_a
wt["b_dep"] = wt.threshold_deposited_kink - wt.basal_b
wt["a_not_edge"] = wt.threshold_kink_not_at_start - wt.basal_a
print(wt.round(2).to_string(index=False))
res = []
for col in ("a", "b", "a_dep", "b_dep", "a_not_edge"):
    for nm, d in (("all cells", wt), ("without cell_21_1", wt[wt.cell != "cell_21_1"])):
        res.append({"reading": col, "cells": nm, "n": len(d), "mean_mV": round(d[col].mean(), 2), "sem_mV": round(d[col].std(ddof=1) / np.sqrt(len(d)), 2),
                    "within_tol": abs(d[col].mean() - 12.7) <= 0.7})
res = pd.DataFrame(res)
print(res.to_string(index=False))
print("Paper: 12.7 +/- 0.7 mV, n = 60 cells (60 +/- 6)")
print("Spikes whose kink is the first sample searched (1.5 ms before the peak), per cell: quantiles 0/50/100%",
      np.round(np.percentile(wt.kink_at_window_start, [0, 50, 100]), 3), "| over all spikes:",
      round(float(np.concatenate([c["meta"]["kink_at_edge"] for c in cells]).mean()), 3))
print("By group, reading a:", wt.groupby("group")["a"].mean().round(2).to_dict(), "| reading b:", wt.groupby("group")["b"].mean().round(2).to_dict())
     cell   subject                      group  kept_trials  spikes  kink_at_window_start  threshold  threshold_kink_not_at_start  threshold_deposited_kink  basal_a  basal_b     a     b  a_dep  b_dep  a_not_edge
cell_20_1 anm300476         M1 photoinhibition          100    8399                  0.01     -43.37                       -43.37                    -44.21   -48.10   -46.54  4.73  3.17   3.88   2.33        4.72
cell_21_1 anm300476         M1 photoinhibition          172   20842                  0.04     -43.76                       -43.58                    -44.09   -47.88   -45.50  4.12  1.74   3.78   1.40        4.30
cell_22_1 anm300476         M1 photoinhibition           43    3002                  0.01     -42.82                       -42.82                    -42.94   -47.15   -49.11  4.33  6.28   4.21   6.16        4.33
cell_23_1 anm300476         M1 photoinhibition           33    1243                  0.01     -45.71                       -45.69                    -45.21   -54.15   -53.57  8.44  7.86   8.94   8.36        8.46
cell_25_1 anm300476         M1 photoinhibition           93    9301                  0.07     -49.98                       -49.64                    -50.13   -51.22   -54.10  1.24  4.13   1.09   3.97        1.58
cell_29_1 anm300476         M1 photoinhibition           43    4578                  0.01     -41.44                       -41.43                    -41.51   -45.52   -46.36  4.09  4.92   4.01   4.85        4.09
cell_55_1 anm322808   thalamus photoinhibition           75    1479                  0.01     -51.69                       -51.70                    -52.40   -59.13   -57.23  7.43  5.53   6.72   4.82        7.43
cell_56_1 anm322808   thalamus photoinhibition           83    2745                  0.01     -40.86                       -40.86                    -41.71   -53.57   -51.67 12.71 10.80  11.87   9.96       12.71
cell_57_1 anm322808   thalamus photoinhibition           45    1670                  0.01     -41.21                       -41.16                    -41.78   -49.22   -49.64  8.01  8.44   7.44   7.86        8.06
cell_58_1 anm322808   thalamus photoinhibition           48    1426                  0.01     -46.95                       -46.90                    -47.94   -53.68   -53.16  6.73  6.20   5.75   5.22        6.79
cell_59_1 anm322808   thalamus photoinhibition           57    2780                  0.01     -43.59                       -43.58                    -44.10   -52.51   -49.54  8.92  5.95   8.40   5.44        8.92
cell_60_1 anm322808   thalamus photoinhibition           71    1932                  0.01     -52.12                       -52.07                    -53.44   -58.57   -57.93  6.45  5.82   5.13   4.50        6.50
cell_44_1 anm323951         M1 photoinhibition           46    6777                  0.01     -32.27                       -32.26                    -31.88   -37.34   -37.24  5.07  4.97   5.46   5.36        5.08
cell_45_1 anm323951         M1 photoinhibition           49    3767                  0.01     -38.37                       -38.38                    -38.75   -48.70   -48.71 10.32 10.33   9.95   9.96       10.32
cell_46_1 anm323951         M1 photoinhibition           74    7862                  0.01     -40.34                       -40.33                    -40.51   -47.03   -46.67  6.70  6.34   6.52   6.16        6.70
cell_45_2 anm323951 contra ALM photoinhibition           48    3187                  0.01     -35.55                       -35.51                    -36.41   -44.07   -42.37  8.52  6.82   7.66   5.96        8.55
cell_46_2 anm323951 contra ALM photoinhibition           69    6810                  0.01     -38.37                       -38.35                    -38.64   -44.40   -44.03  6.03  5.66   5.76   5.39        6.05
cell_40_2 anm323952         M1 photoinhibition           86    2051                  0.01     -40.26                       -40.24                    -40.81   -51.17   -48.80 10.91  8.53  10.37   7.99       10.93
cell_39_1 anm323952 contra ALM photoinhibition           44    4120                  0.03     -38.35                       -38.24                    -37.38   -43.33   -43.89  4.98  5.55   5.95   6.51        5.09
cell_40_1 anm323952 contra ALM photoinhibition           44     931                  0.01     -51.84                       -51.76                    -52.18   -60.18   -58.98  8.34  7.15   8.00   6.80        8.42
cell_30_2 anm323953         M1 photoinhibition           38     653                  0.01     -41.28                       -41.08                    -38.31   -47.95   -46.04  6.67  4.76   9.64   7.73        6.87
cell_30_1 anm323953 contra ALM photoinhibition          119    3264                  0.01     -50.27                       -50.25                    -49.18   -56.77   -54.21  6.51  3.94   7.59   5.02        6.53
cell_31_1 anm323953 contra ALM photoinhibition           70    4718                  0.01     -33.53                       -33.49                    -33.01   -38.56   -39.14  5.03  5.61   5.56   6.13        5.07
cell_32_1 anm323953 contra ALM photoinhibition           39    5853                  0.01     -43.27                       -43.31                    -43.02   -47.84   -47.21  4.56  3.94   4.82   4.19        4.53
cell_34_1 anm323953 contra ALM photoinhibition           93    2576                  0.01     -48.93                       -48.89                    -47.63   -53.78   -55.89  4.85  6.96   6.14   8.26        4.88
cell_35_1 anm323953 contra ALM photoinhibition           36    1937                  0.01     -44.51                       -44.44                    -45.12   -53.20   -54.45  8.69  9.94   8.07   9.33        8.76
cell_47_1 anm324791   thalamus photoinhibition           61    3931                  0.00     -53.61                       -53.56                    -57.57   -63.91   -62.12 10.30  8.51   6.34   4.55       10.35
cell_49_1 anm324791   thalamus photoinhibition           23    2297                  0.01     -40.48                       -40.46                    -40.87   -48.71   -47.58  8.24  7.11   7.84   6.71        8.25
cell_50_1 anm324791   thalamus photoinhibition           82    9756                  0.01     -36.28                       -36.26                    -37.35   -46.49   -43.42 10.20  7.13   9.14   6.07       10.23
cell_51_1 anm324791   thalamus photoinhibition          104    6750                  0.01     -36.31                       -36.30                    -36.35   -43.91   -44.90  7.60  8.60   7.55   8.55        7.61
cell_52_1 anm324791   thalamus photoinhibition          121    8372                  0.01     -36.74                       -36.73                    -36.73   -45.78   -43.57  9.04  6.83   9.04   6.84        9.05
cell_53_1 anm324791   thalamus photoinhibition           28    3736                  0.01     -41.29                       -41.29                    -41.37   -46.14   -45.53  4.85  4.24   4.77   4.16        4.85
cell_64_1 anm324792   thalamus photoinhibition           55    1437                  0.01     -43.63                       -43.62                    -44.11   -52.97   -52.46  9.35  8.84   8.87   8.35        9.35
cell_65_1 anm324792   thalamus photoinhibition           66    2752                  0.01     -39.71                       -39.69                    -40.06   -48.91   -48.85  9.20  9.14   8.85   8.79        9.21
cell_66_1 anm324792   thalamus photoinhibition           57    1534                  0.00     -49.42                       -49.43                    -51.79   -53.42   -53.87  4.01  4.45   1.64   2.08        3.99
cell_73_2 anm324792   thalamus photoinhibition           41    1907                  0.01     -35.10                       -35.05                    -35.67   -46.65   -41.35 11.55  6.25  10.98   5.68       11.61
   reading             cells  n  mean_mV  sem_mV  within_tol
         a         all cells 36     7.19    0.43       False
         a without cell_21_1 35     7.27    0.43       False
         b         all cells 36     6.46    0.35       False
         b without cell_21_1 35     6.59    0.33       False
     a_dep         all cells 36     6.88    0.41       False
     a_dep without cell_21_1 35     6.97    0.42       False
     b_dep         all cells 36     6.15    0.35       False
     b_dep without cell_21_1 35     6.29    0.33       False
a_not_edge         all cells 36     7.23    0.42       False
a_not_edge without cell_21_1 35     7.31    0.43       False
Paper: 12.7 +/- 0.7 mV, n = 60 cells (60 +/- 6)
Spikes whose kink is the first sample searched (1.5 ms before the peak), per cell: quantiles 0/50/100% [0.004 0.008 0.068] | over all spikes: 0.017
By group, reading a: {'M1 photoinhibition': 6.06, 'contra ALM photoinhibition': 6.39, 'thalamus photoinhibition': 8.41} | reading b: {'M1 photoinhibition': 5.73, 'contra ALM photoinhibition': 6.17, 'thalamus photoinhibition': 7.11}

Result: not reproduced. In the 36 deposited cells (paper 60), threshold minus basal Vm is 7.19 +/- 0.43 mV with the Methods' baseline (a) and 6.46 +/- 0.35 mV with the delay epoch (b), against 12.7 +/- 0.7 mV; with the deposited kink, 6.88 and 6.15 mV. Leaving out cell_21_1 changes these by at most 0.14 mV. The kink is the first sample searched (1.5 ms before the peak) in 1.7% of spikes (0.4 to 6.8% per cell); leaving those spikes out gives 7.23 mV. Neither the value nor the number of cells is within tolerance.

Whole-cell photoinhibition: wc-thalamus-hyperpolarization, wc-m1-small-effect, wc-contra-alm-small-effect, thalamus-stronger-than-cortex¶

wc-thalamus-hyperpolarization: Thalamus photoinhibition hyperpolarized ALM neurons by 18.7 mV, preventing spiking, with an onset 7.9 ms after photostimulus onset.

wc-m1-small-effect: Photoinhibition of M1 during the delay epoch caused only a slight hyperpolarization (3.3 mV) and a small drop in spike rate (1.4 spikes per s) in ALM neurons.

wc-contra-alm-small-effect: Photoinhibition of contralateral ALM barely changed the membrane potential of ALM neurons (1.4 mV).

thalamus-stronger-than-cortex: thalALM drives ALM more strongly than M1 or contralateral ALM, the other reciprocally connected structures tested.

The claims file (answer of 2026-10-20) gives two readings of the photostimulus onset: E, 1.3 s after pole_in_time, and M, 0.1 s after pole_out_time. The files also hold the laser trace (data check), whose onset is reading L, shown here pending question 7. Each measure is computed under all three. Per cell: mean Vm (spikes clipped) 20 to 120 ms after the onset, photostimulus minus control kept trials, and the spike rate in the same window; then mean and SEM over cells. Onsets by convention V (V1 on the cell-mean trace, SEM from 1000 resamplings of cells; V2 the mean of per-cell onsets) are shown under every reading; the claims file says the 7.9 ms latency needs the laser time, which none of its readings gives, so the onset is not judged; it is shown under L pending question 7.

In [33]:
rng = np.random.default_rng(801)
GROUPS = {"thalamus": "thalamus photoinhibition", "M1": "M1 photoinhibition", "contra ALM": "contra ALM photoinhibition"}
rows, per_cell, cell_rows = [], {}, []
for reading in loop.WC_ONSETS:
    for g, desc in GROUPS.items():
        cs = [c for c in cells if c["meta"]["description"].endswith(desc)]
        dv, dsp, mean_tr, sp_c, sp_p = [], [], [], [], []
        onsets = []
        for c in cs:
            t = c["trials"]
            k = t.response.isin(loop.KEEP).values
            pi, ct = k & t.pi.values, k & ~t.pi.values
            dv.append(t[f"vm_pw_{reading}"][pi].mean() - t[f"vm_pw_{reading}"][ct].mean())
            dsp.append((t[f"spikes_pw_{reading}"][pi].mean() - t[f"spikes_pw_{reading}"][ct].mean()) / (loop.PW[1] - loop.PW[0]))
            sp_c.append(t[f"spikes_pw_{reading}"][ct].mean() / (loop.PW[1] - loop.PW[0]))
            sp_p.append(t[f"spikes_pw_{reading}"][pi].mean() / (loop.PW[1] - loop.PW[0]))
            tr = c["trace"][reading][pi].mean(0)
            mean_tr.append(tr)
            onsets.append(loop.vm_onset_ms(tr))
            cell_rows.append({"onset_reading": reading, "group": g, "cell": c["meta"]["cell"], "subject": c["meta"]["subject"],
                              "dVm": round(dv[-1], 2), "dRate": round(dsp[-1], 2), "onset_ms": onsets[-1]})
        dv, dsp, mean_tr, onsets = np.array(dv), np.array(dsp), np.array(mean_tr), np.array(onsets)
        per_cell[(reading, g)] = dv
        v1 = loop.vm_onset_ms(mean_tr.mean(0))
        boot = [loop.vm_onset_ms(mean_tr[rng.integers(0, len(cs), len(cs))].mean(0)) for _ in range(1000)]
        rows.append({"onset_reading": reading, "group": g, "cells": len(cs), "dVm_mean": round(dv.mean(), 2),
                     "dVm_sem": round(dv.std(ddof=1) / np.sqrt(len(dv)), 2), "dRate_mean": round(dsp.mean(), 2),
                     "dRate_sem": round(dsp.std(ddof=1) / np.sqrt(len(dsp)), 2), "rate_ctrl": round(np.mean(sp_c), 2), "rate_pi": round(np.mean(sp_p), 2), "V1_onset_ms": v1, "V1_sem": round(float(np.nanstd(boot)), 2),
                     "V2_onset_ms": round(float(np.nanmean(onsets)), 2), "V2_sem": round(float(np.nanstd(onsets, ddof=1) / np.sqrt(np.sum(~np.isnan(onsets)))), 2),
                     "cells_without_onset": int(np.isnan(onsets).sum())})
wcp = pd.DataFrame(rows)
print(wcp.to_string(index=False))
print("Paper: thalamus -18.7 +/- 1.1 mV, onset 7.9 +/- 1.7 ms (n = 16); M1 -3.3 +/- 1.0 mV and -1.4 +/- 0.6 spikes/s (n = 11);"
      " contra ALM -1.4 +/- 0.5 mV (n = 9)")
tol = {"thalamus": [("dVm_mean", -18.7, 1.1), ("V1_onset_ms", 7.9, 1.7), ("V2_onset_ms", 7.9, 1.7)],
       "M1": [("dVm_mean", -3.3, 1.0), ("dRate_mean", -1.4, 0.6)], "contra ALM": [("dVm_mean", -1.4, 0.5)]}
print("\nWithin tolerance, per onset reading (the thalamus onset of 7.9 ms is shown only under L, the laser trace, which the claims file does not list; E and M cannot judge it):")
for _, r in wcp.iterrows():
    print(r.onset_reading, r.group, {q: bool(abs(r[q] - v) <= e) for q, v, e in tol[r.group] if r.onset_reading == "L" or "onset" not in q})
pc = pd.DataFrame(cell_rows)
print("\nPer cell under L:")
print(pc[pc.onset_reading == "L"].drop(columns="onset_reading").to_string(index=False))
print("By mouse under L (mean dVm):", pc[pc.onset_reading == "L"].groupby(["group", "subject"]).dVm.agg(["size", "mean"]).round(2).to_dict("index"))
wl = wcp[wcp.onset_reading == "L"].set_index("group")
print("\nindirect-pathway-too-slow, the part the dandiset holds: ALM Vm onset after M1 photoinhibition under L, V1",
      wl.loc["M1", "V1_onset_ms"], "+/-", wl.loc["M1", "V1_sem"], "ms, V2", wl.loc["M1", "V2_onset_ms"], "+/-", wl.loc["M1", "V2_sem"],
      "ms (paper 13.9 +/- 3.2); no M1 neurons are deposited")
print("\nthalamus-stronger-than-cortex, per reading: (a) thalamus mean more negative than M1 and contra ALM; (b) as (a), two-sided t-tests over cells")
for reading in loop.WC_ONSETS:
    th, m1, ca = per_cell[(reading, "thalamus")], per_cell[(reading, "M1")], per_cell[(reading, "contra ALM")]
    out = {"reading": reading, "a": bool(th.mean() < m1.mean() and th.mean() < ca.mean())}
    for ev in (True, False):
        p1 = stats.ttest_ind(th, m1, equal_var=ev).pvalue
        p2 = stats.ttest_ind(th, ca, equal_var=ev).pvalue
        out[f"p_vs_M1_{'Student' if ev else 'Welch'}"] = p1
        out[f"p_vs_contra_{'Student' if ev else 'Welch'}"] = p2
    print(out)
onset_reading      group  cells  dVm_mean  dVm_sem  dRate_mean  dRate_sem  rate_ctrl  rate_pi  V1_onset_ms  V1_sem  V2_onset_ms  V2_sem  cells_without_onset
            E   thalamus     16      0.31     0.52       -0.09       0.30       3.16     3.07         5.90   18.14        18.79    4.75                    1
            E         M1     11     -0.09     0.42        0.94       1.36       5.36     6.30       127.85   47.61        19.38    7.11                    1
            E contra ALM      9      0.86     0.41       -0.75       0.68       5.28     4.53         9.15   32.81        53.20   20.82                    2
            M   thalamus     16    -16.83     1.24       -3.08       0.99       3.14     0.06         9.05    0.55         9.33    0.67                    0
            M         M1     11     -2.75     1.30        0.76       1.29       4.99     5.75         2.40   13.88        27.07   12.53                    1
            M contra ALM      9     -1.60     0.64       -2.19       1.30       4.79     2.60         6.45    4.78        14.79    4.48                    1
            L   thalamus     16    -13.68     1.14       -3.10       1.03       3.24     0.14         0.40    3.27         9.60    1.98                    0
            L         M1     11     -3.26     1.08       -0.01       1.16       4.82     4.81         8.70    4.60        27.30    6.61                    0
            L contra ALM      9     -1.38     0.58       -2.08       1.31       4.57     2.50        23.70    2.66        19.68    2.46                    0
Paper: thalamus -18.7 +/- 1.1 mV, onset 7.9 +/- 1.7 ms (n = 16); M1 -3.3 +/- 1.0 mV and -1.4 +/- 0.6 spikes/s (n = 11); contra ALM -1.4 +/- 0.5 mV (n = 9)

Within tolerance, per onset reading (the thalamus onset of 7.9 ms is shown only under L, the laser trace, which the claims file does not list; E and M cannot judge it):
E thalamus {'dVm_mean': False}
E M1 {'dVm_mean': False, 'dRate_mean': False}
E contra ALM {'dVm_mean': False}
M thalamus {'dVm_mean': False}
M M1 {'dVm_mean': True, 'dRate_mean': False}
M contra ALM {'dVm_mean': True}
L thalamus {'dVm_mean': False, 'V1_onset_ms': False, 'V2_onset_ms': True}
L M1 {'dVm_mean': True, 'dRate_mean': False}
L contra ALM {'dVm_mean': True}

Per cell under L:
     group      cell   subject    dVm  dRate  onset_ms
  thalamus cell_55_1 anm322808  -9.48   0.00      0.40
  thalamus cell_56_1 anm322808 -13.22  -2.19     17.70
  thalamus cell_57_1 anm322808  -6.22  -0.36      6.05
  thalamus cell_58_1 anm322808 -20.38  -1.25     11.05
  thalamus cell_59_1 anm322808 -21.72  -2.35      8.55
  thalamus cell_60_1 anm322808 -15.48   0.00      0.40
  thalamus cell_47_1 anm324791 -12.07  -0.21     16.85
  thalamus cell_49_1 anm324791 -17.65  -5.71      0.45
  thalamus cell_50_1 anm324791 -18.18  -9.90     14.75
  thalamus cell_51_1 anm324791 -12.63  -1.67     11.65
  thalamus cell_52_1 anm324791 -13.98  -8.33     20.75
  thalamus cell_53_1 anm324791 -11.29 -13.33     24.50
  thalamus cell_64_1 anm324792  -4.69   0.02      0.40
  thalamus cell_65_1 anm324792 -13.99   0.00     11.60
  thalamus cell_66_1 anm324792 -14.29  -0.56      8.05
  thalamus cell_73_2 anm324792 -13.64  -3.75      0.40
        M1 cell_20_1 anm300476  -3.11  -2.79     18.25
        M1 cell_21_1 anm300476  -3.51   4.60     29.75
        M1 cell_22_1 anm300476  -0.01  -0.43     23.80
        M1 cell_23_1 anm300476  -3.93  -1.72     24.45
        M1 cell_25_1 anm300476   0.10   8.24     16.40
        M1 cell_29_1 anm300476   1.02   1.01     18.40
        M1 cell_44_1 anm323951  -0.96   0.20     90.00
        M1 cell_45_1 anm323951  -8.39  -6.67     21.15
        M1 cell_46_1 anm323951  -1.24  -1.26     32.70
        M1 cell_40_2 anm323952  -9.96  -0.40      6.80
        M1 cell_30_2 anm323953  -5.90  -0.87     18.55
contra ALM cell_45_2 anm323951  -1.99  -2.08     29.45
contra ALM cell_46_2 anm323951  -0.62   1.05     14.35
contra ALM cell_39_1 anm323952   0.15  -8.63     15.35
contra ALM cell_40_1 anm323952  -2.69   0.00     26.20
contra ALM cell_30_1 anm323953  -4.21  -0.57     21.15
contra ALM cell_31_1 anm323953   0.97   0.90     20.30
contra ALM cell_32_1 anm323953  -1.14  -8.98      4.65
contra ALM cell_34_1 anm323953  -3.16  -0.36     21.60
contra ALM cell_35_1 anm323953   0.30   0.00     24.05
By mouse under L (mean dVm): {('M1', 'anm300476'): {'size': 6, 'mean': -1.57}, ('M1', 'anm323951'): {'size': 3, 'mean': -3.53}, ('M1', 'anm323952'): {'size': 1, 'mean': -9.96}, ('M1', 'anm323953'): {'size': 1, 'mean': -5.9}, ('contra ALM', 'anm323951'): {'size': 2, 'mean': -1.3}, ('contra ALM', 'anm323952'): {'size': 2, 'mean': -1.27}, ('contra ALM', 'anm323953'): {'size': 5, 'mean': -1.45}, ('thalamus', 'anm322808'): {'size': 6, 'mean': -14.42}, ('thalamus', 'anm324791'): {'size': 6, 'mean': -14.3}, ('thalamus', 'anm324792'): {'size': 4, 'mean': -11.65}}

indirect-pathway-too-slow, the part the dandiset holds: ALM Vm onset after M1 photoinhibition under L, V1 8.7 +/- 4.6 ms, V2 27.3 +/- 6.61 ms (paper 13.9 +/- 3.2); no M1 neurons are deposited

thalamus-stronger-than-cortex, per reading: (a) thalamus mean more negative than M1 and contra ALM; (b) as (a), two-sided t-tests over cells
{'reading': 'E', 'a': False, 'p_vs_M1_Student': np.float64(0.5843269846903805), 'p_vs_contra_Student': np.float64(0.4735437434688235), 'p_vs_M1_Welch': np.float64(0.556445035758204), 'p_vs_contra_Welch': np.float64(0.4091498760592985)}
{'reading': 'M', 'a': True, 'p_vs_M1_Student': np.float64(5.235938752095844e-08), 'p_vs_contra_Student': np.float64(7.851743860033135e-09), 'p_vs_M1_Welch': np.float64(5.046219327045784e-08), 'p_vs_contra_Welch': np.float64(3.41188328278441e-10)}
{'reading': 'L', 'a': True, 'p_vs_M1_Student': np.float64(1.2611897901878665e-06), 'p_vs_contra_Student': np.float64(8.080084514863154e-08), 'p_vs_M1_Welch': np.float64(6.725331963528889e-07), 'p_vs_contra_Welch': np.float64(3.719981175503937e-09)}

Result: wc-thalamus-hyperpolarization not reproduced; wc-m1-small-effect not reproduced; wc-contra-alm-small-effect reproduced; thalamus-stronger-than-cortex reproduced. Under onset E the window lies before the change (data check) and no value is within tolerance: thalamus photoinhibition changes Vm by +0.31 mV, M1 by -0.09 mV and +0.94 spikes/s, contralateral ALM by +0.86 mV, and thalamus is not more negative than the others (p = 0.41 to 0.58).

Under the laser onset (L), thalamus photoinhibition hyperpolarizes ALM neurons by -13.68 +/- 1.14 mV, outside -18.7 +/- 1.1, and spiking stops (3.24 to 0.14 spikes/s); every one of the 16 cells hyperpolarizes (-4.7 to -21.7 mV). The onset is 9.60 +/- 1.98 ms by V2, within 7.9 +/- 1.7, and 0.40 ms by V1, which is not (five cells give 0.40 to 0.45 ms, at the laser onset itself). Under M, whose window starts 28 ms later in these cells, the change is -16.83 +/- 1.24 mV, also outside. The hyperpolarization and the loss of spiking are present at 73% (L) or 90% (M) of the paper's size; no reading puts both values within tolerance.

M1 photoinhibition changes Vm by -3.26 +/- 1.08 mV under L (-2.75 under M), within -3.3 +/- 1.0, and the spike rate by -0.01 +/- 1.16 spikes/s under L (+0.76 under M), outside -1.4 +/- 0.6: the slight hyperpolarization holds, the drop in spike rate is not seen. Contralateral ALM photoinhibition changes Vm by -1.38 +/- 0.58 mV under L and -1.60 +/- 0.64 under M, within -1.4 +/- 0.5. Thalamus photoinhibition hyperpolarizes more than M1 or contralateral ALM photoinhibition under L (p = 1.3e-6 and 8.1e-8, Student; 6.7e-7 and 3.7e-9, Welch) and under M (p = 5e-8 and 8e-9, Student), so readings (a) and (b) both hold. The outcomes are the same under M and under L.

Neither wc-thalamus-hyperpolarization nor wc-m1-small-effect has a partial clause, and no reading meets either criterion in full (see Changes of outcome, before the Summary). The third verification round agreed.

For indirect-pathway-too-slow (blocked: no M1 neurons are deposited), the ALM onset after M1 photoinhibition under L is 8.7 +/- 4.6 ms (V1) or 27.3 +/- 6.6 ms (V2), against 13.9 +/- 3.2.

Claims blocked from the start¶

Claim Reason Where looked
fig1d-thalamus-photoinhibition-bias data missing The only Gad2 sessions (Ai35D x GAD2_Cre, 9 thalamic recordings) carry no photostimulus trial; there are no behaviour-only sessions.
gad2-thalamus-reduction metadata insufficient The 84 units of the Gad2 sessions match the n of Extended Data Fig. 2c, but no trial is marked as photostimulated (period 'N/A', power 0 everywhere).
muscimol-vmval-bias data missing No muscimol sessions, no infusion metadata.
wc-loss-of-excitation data missing No non-behaving recordings and no current-injection experiments with TRN photostimulation (all 36 cells are behaving; the injected current is a holding current).
indirect-pathway-too-slow data missing No whole-cell recordings of M1 neurons (every cell is in ALM). Its other onset, ALM after M1 photoinhibition, is shown under the laser onset in the whole-cell section; the claim needs both.
conduction-delay data missing No Olig3-cre x Ai32 recordings.
latency-model-t3 methods underspecified A simulation whose parameters are in the Supplementary Information, not in the text the claims were written from.
fig5-weak-photoinhibition-rates data missing No ALM session with 0.5 mW thalamus photoinhibition (VGAT ALM sessions use 10 mW only); the dandiset holds 966 of the 1214 ALM units, consistent with the Fig. 5 sessions (JRclust sorting) being absent.
fig5c-selectivity-reduced data missing Depends on fig5-weak-photoinhibition-rates.
network-models methods underspecified A modelling result specified in the Supplementary Information.
anatomy-reciprocal-thalamus data missing No histology or cell counts in the dandiset.
alm-gabaergic-no-thalamic-projection data missing No histology in the dandiset.
In [34]:
print("Genotypes in the extracellular files:", dict(Counter(s["meta"]["genotype"] for s in sessions)))
print("Genotypes in the whole-cell files:", dict(Counter(c["meta"]["genotype"] for c in cells)))
gad = [s for s in sessions if "GAD2" in s["meta"]["genotype"]]
print("Gad2 sessions:", len(gad), "| units:", sum(len(s["units"]) for s in gad), "| photostimulus labels:",
      dict(Counter(x for s in gad for x in s["trials"].stim)), "| photostimulus sites:", {s["meta"]["ogen_site"] for s in gad})
print("Photostimulus powers in ALM sessions with thalamic photostimulation:",
      dict(Counter((s["meta"]["genotype"], x) for s in sessions if s["meta"]["region"] == "ALM" and s["meta"]["ogen_site"] == "Thalamus"
                   for x in s["trials"].stim if x != "none")))
print("Whole-cell recording locations:", dict(Counter(c["meta"]["cell_location"].get("brain_region") for c in cells)),
      "| descriptions:", dict(Counter(c["meta"]["description"] for c in cells)))
print("Session descriptions (extracellular):", dict(Counter(s["meta"]["path"].split("_")[-1] for s in sessions)))
st_alm = pd.to_datetime(pd.Series([s["meta"]["session_start"][:19] for s in sessions if s["meta"]["region"] == "ALM"]))
print("ALM sessions: session_start_time from", st_alm.min(), "to", st_alm.max(), "| distinct dates", st_alm.dt.date.nunique(),
      "| ALM sessions per mouse:", dict(Counter(s["meta"]["subject"] for s in sessions if s["meta"]["region"] == "ALM")))
print("Units table description:", {s["meta"]["units_description"] for s in sessions}, "| unit_y description:", {s["meta"]["unit_y_description"] for s in sessions})
Genotypes in the extracellular files: {'Ai35D x GAD2_Cre': 9, 'Ai32 x PV-Cre': 87, 'C57BL6': 12, 'VGAT-ChR2-EYFP': 29}
Genotypes in the whole-cell files: {'Ai32 x PV-Cre': 20, 'VGAT-ChR2-EYFP': 16}
Gad2 sessions: 9 | units: 84 | photostimulus labels: {'none': 2993} | photostimulus sites: {None}
Photostimulus powers in ALM sessions with thalamic photostimulation: {('Ai32 x PV-Cre', 'Thalamus:delay:10'): 531, ('Ai32 x PV-Cre', 'Thalamus:delay:22.5'): 380, ('Ai32 x PV-Cre', 'Thalamus:delay:45'): 115, ('VGAT-ChR2-EYFP', 'Thalamus:delay:10'): 891}
Whole-cell recording locations: {'ALM': 36} | descriptions: {'ALM whole cell recording during M1 photoinhibition': 11, 'ALM whole cell recording during thalamus photoinhibition': 16, 'ALM whole cell recording during contra ALM photoinhibition': 9}
Session descriptions (extracellular): {'ecephys.nwb': 21, 'ecephys+ogen.nwb': 116}
ALM sessions: session_start_time from 2017-06-27 09:38:44 to 2017-06-27 09:43:22 | distinct dates 1 | ALM sessions per mouse: {'anm00261335': 2, 'anm00264941': 1, 'anm00264942': 6, 'anm00264943': 5, 'anm00264944': 5, 'anm00267975': 6, 'anm00279338': 4, 'anm00322805': 5, 'anm00322807': 8, 'anm00323634': 5}
Units table description: {'Autogenerated by NWBFile'} | unit_y description: {'y-coordinate of this unit (mm)'}

Changes of outcome¶

The second verification found that nine claims were given partially reproduced under criteria that have no partial clause: each says only "Reproduced when ...". The cell below counts, for each of them, the readings of the claims file that meet the whole criterion, from the tables above. Reading L of the whole-cell claims (the laser trace, question 7) is not in the claims file and is counted apart.

In [35]:
# Readings that meet the whole criterion, per claim whose criterion has no partial clause.
full = {}
cls = {"P1": (len(alm), len(PYR["P1"]), int((alm.width_ms < 0.4).sum())),
       "P2": (len(alm), len(PYR["P2"]), int((alm.cell_type == "Narrow width spiking").sum()))}
ok = [all(abs(v - r) <= e for v, (r, e) in zip(c, ((1214, 121), (1006, 101), (166, 17)))) for c in cls.values()]
full["alm-unit-classes"] = (sum(ok), len(ok))
# L1 has no label in the files, so only L2 can be counted.
ok = [all(abs(v - r) <= e for v, (r, e) in zip((len(thal), len(THP[p]), int((thal.vmval_d < 0.4).sum()), len(VMVAL[p])),
                                               ((790, 79), (672, 67), (313, 31), (295, 30)))) for p in THP]
full["thalamus-unit-classes"] = (sum(ok), len(ok))
full["fig2e-alm-selectivity"] = (int(f2e.within_tol.sum()), len(f2e))
full["fig2f-vmval-selectivity"] = (int((f2f.counts_within_tol & (f2f.chi_ok_i | f2f.chi_ok_ii)).sum()), len(f2f))
f3f_r = f3f[f3f.units.isin(["P1", "P2"])]
full["fig3f-thalamus-silenced"] = (int(f3f_r[[c for c in f3f_r if c.startswith("within_tol")]].any(axis=1).sum()), len(f3f_r))
full["fig6d-localized"] = (int((f6d.counts_ok & f6d.value_ok_any_Q & f6d.near_lower_than_far_Q1).sum()), len(f6d))
sn_r = sn[sn.units.isin(["P1", "P2"])]
full["snr-photoinhibition"] = (int(sn_r.within_tol.sum()), len(sn_r))
for claim, group, checks in (("wc-thalamus-hyperpolarization", "thalamus", [("dVm_mean", -18.7, 1.1)]),
                             ("wc-m1-small-effect", "M1", [("dVm_mean", -3.3, 1.0), ("dRate_mean", -1.4, 0.6)])):
    for reading in ("E", "M", "L"):
        r = wcp[(wcp.onset_reading == reading) & (wcp.group == group)].iloc[0]
        print(claim, reading, {q: (r[q], bool(abs(r[q] - v) <= e)) for q, v, e in checks})
    # The Vm change is a necessary part of either criterion; the 7.9 ms onset cannot be judged under E or M.
    ok = [all(abs(wcp[(wcp.onset_reading == rd) & (wcp.group == group)].iloc[0][q] - v) <= e for q, v, e in checks) for rd in ("E", "M")]
    full[claim] = (sum(ok), len(ok))
print()
for claim, (n_ok, n) in full.items():
    print(f"{claim}: {n_ok} of {n} readings meet the whole criterion")
wc-thalamus-hyperpolarization E {'dVm_mean': (np.float64(0.31), False)}
wc-thalamus-hyperpolarization M {'dVm_mean': (np.float64(-16.83), False)}
wc-thalamus-hyperpolarization L {'dVm_mean': (np.float64(-13.68), False)}
wc-m1-small-effect E {'dVm_mean': (np.float64(-0.09), False), 'dRate_mean': (np.float64(0.94), False)}
wc-m1-small-effect M {'dVm_mean': (np.float64(-2.75), True), 'dRate_mean': (np.float64(0.76), False)}
wc-m1-small-effect L {'dVm_mean': (np.float64(-3.26), True), 'dRate_mean': (np.float64(-0.01), False)}

alm-unit-classes: 0 of 2 readings meet the whole criterion
thalamus-unit-classes: 0 of 2 readings meet the whole criterion
fig2e-alm-selectivity: 0 of 32 readings meet the whole criterion
fig2f-vmval-selectivity: 0 of 64 readings meet the whole criterion
fig3f-thalamus-silenced: 0 of 8 readings meet the whole criterion
fig6d-localized: 0 of 12 readings meet the whole criterion
snr-photoinhibition: 0 of 16 readings meet the whole criterion
wc-thalamus-hyperpolarization: 0 of 2 readings meet the whole criterion
wc-m1-small-effect: 0 of 2 readings meet the whole criterion

No reading of the claims file meets the whole criterion of any of the nine claims. For wc-thalamus-hyperpolarization the Vm change alone is outside tolerance under E and M (and under L, which is not a reading of the claims file), so the onset, which no listed reading can judge, does not bear on the outcome; for wc-m1-small-effect the spike-rate change is outside tolerance under every onset. Partial agreement (class fractions, selective fractions, near-complete silencing, the order of the distance groups, the SNr counts under P1, the Vm change of M1 photoinhibition) is not an outcome these criteria define. The outcome of each of the nine claims was proposed to change from partially reproduced to not reproduced after the second verification; the third verification round agreed with all nine, and each is now not reproduced.

Summary¶

Claim Outcome
task-performance not reproduced
fig1c-alm-photoinhibition-bias reproduced
fig1d-thalamus-photoinhibition-bias blocked: data missing
gad2-thalamus-reduction blocked: metadata insufficient
vgat-thalamus-reduction reproduced
muscimol-vmval-bias blocked: data missing
alm-unit-classes not reproduced
fig2e-alm-selectivity not reproduced
fig2e-alm-contra-ipsi-balance reproduced
thalamus-unit-classes not reproduced
fig2f-vmval-selectivity not reproduced
fig3-alm-collapse partially reproduced
fig3d-all-layers blocked: methods underspecified
fig3b-selectivity-types-equally-inhibited blocked: methods underspecified
fig3f-thalamus-silenced not reproduced
fig3-onset-latencies reproduced
wc-near-threshold not reproduced
wc-thalamus-hyperpolarization not reproduced
wc-loss-of-excitation blocked: data missing
wc-m1-small-effect not reproduced
wc-contra-alm-small-effect reproduced
thalamus-stronger-than-cortex reproduced
indirect-pathway-too-slow blocked: data missing
conduction-delay blocked: data missing
latency-model-t3 blocked: methods underspecified
fig5-weak-photoinhibition-rates blocked: data missing
fig5c-selectivity-reduced blocked: data missing
network-models blocked: methods underspecified
fig6c-vmval-reduced not reproduced
fig6b-selectivity-types-equally-inhibited blocked: methods underspecified
fig6c-unmodulated-less-selective partially reproduced
fig6d-localized not reproduced
vm1-photoinhibition-no-effect blocked: metadata insufficient
fig6e-onset-latencies not reproduced
snr-photoinhibition not reproduced
snr-unit-properties blocked: data missing (selectivity part within tolerance under P1)
anatomy-reciprocal-thalamus blocked: data missing
selectivity-time-course reproduced
alm-gabaergic-no-thalamic-projection blocked: data missing

7 reproduced, 2 partially reproduced, 13 not reproduced, 17 blocked. Nine claims, whose criteria have no partial clause and which no reading meets in full, were changed from partially reproduced to not reproduced after the third verification round agreed (see Changes of outcome above).

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. Unit classes are run under the readings of convention C: widths computed on the deposited waveforms (P1, the Methods' rule), which are too short for the width thresholds, and the files' labels (P2), which match the paper's class sizes; for the thalamic claims of Fig. 2 and 6, all units (P3) as well. Each unit's trials are taken as those from the trial holding its first spike to the trial holding its last, as the files give no observation interval per unit, and a window that ends after a trial's stored spikes is counted as missing for that trial. Behaviour is measured in the recording sessions, not in behaviour sessions. The VM/VAL centre is the claims file's proxy (reading L2). Distances from the thalamic fibre use the files' single nominal site. The whole-cell claims are judged under the two onsets the claims file allows (E and M) and under the onset of the deposited laser trace (L), which the claims file did not know of (question 7); the outcomes are the same under M and L, nothing holds under E, and the onset latency of 7.9 ms cannot be judged under E or M, the readings the claims file lists; under L, shown pending question 7, it is 9.60 ms by V2 and 0.40 ms by V1. The (0.5, 0.5) galvo site is taken as vM1 only to show what the data give, compared with ALM at 1.5 mW.

What was found about the dataset.

  • The dandiset holds 966 of the paper's 1214 ALM units (47 of 57 sessions), 789 of 790 thalamic units and 181 of 227 SNr units (apparently only the putative GABAergic ones: 171 of the 181 by computed width, 146 by the files' label). Behaviour-only, muscimol, weak photoinhibition (Fig. 5), non-behaving and M1 whole-cell recordings and histology are absent.
  • The mean waveforms are cut short (29 to 38 samples at 25 kHz), so trough-to-peak widths longer than about 0.5 ms cannot be measured; the cell_type labels carry the classification instead, without a stated rule.
  • Spikes are stored only from the trial start to about 4.8 s after pole onset, although trials last about 9 s, so in trials with long delays the response epoch is not stored; most units hold spikes over only part of their session, with no per-unit observation interval.
  • The whole-cell trial tables leave the photostimulus columns empty; the laser time is in an OptogeneticSeries described only as 'no description'. It starts between the two delay onsets the trial times allow, 0.10 to 0.17 s after E and 0.03 to 0.10 s before M (1.40 s after pole onset in one mouse, 1.47 s in the others). One whole-cell trial table has start and stop times shifted by one row. The Vm conversion (0.001 with unit 'mV') contradicts the values, which are in mV.
  • Every electrode group, in thalamus and SNr too, carries the ALM coordinates; the SNr units of one mouse are at AP -1.56 mm; there is no VM/VAL location label; unit_y has no stated reference, so whether it is depth below the pia is not said. Session start times are the date of conversion (all on 2017-06-27), not of recording, so the missing ALM sessions cannot be identified by date.
  • The Gad2 sessions (genotype given as Ai35D x GAD2_Cre, an Arch line, where the paper used Gad2-IRES-Cre with ChR2 in TRN) carry no photostimulus trial, though their 84 units match the optrode units of Extended Data Fig. 2c. The VGAT thalamic sessions give 2.23 mW where the paper gives 10 mW. PV-Cre x Ai32 ALM sessions with thalamic photostimulation at 10 to 45 mW and C57BL6 thalamic sessions are not described in the paper; the (0.5, 0.5) photostimulation site is not named.
In [36]:
print(f"Total run time: {time.time() - started:.0f} s")
Total run time: 464 s