Reproducing Lefebvre et al. (2008), Figure 9, from CRCNS ret-1¶
Paper. Lefebvre JL, Zhang Y, Meister M, Wang X, Sanes JR (2008). Gamma-Protocadherins regulate neuronal survival but are dispensable for circuit formation in retina. Development 135:4141-4151. doi:10.1242/dev.027912. The claims file was written from the NIH author manuscript in PubMed Central (PMC2644426), with its Methods, Results, Discussion and figure legends; the supplementary figures were not available to it. The paper links no analysis code.
Data set. CRCNS ret-1, "Multi-electrode recordings from retinal ganglion cells" (Zhang, Asari
and Meister 2014), doi:10.6080/K0RF5RZT, read from the public
S3 bucket crcnsarchive under ret-1/. CRCNS data sets are not versioned, so the version is
recorded as unversioned. There is one form of the data set to choose: the paper (2008) predates
it and cites none, and the bucket holds one zip file, crcns_ret-1.zip (71,871,914 bytes), whose
MD5 in the data set's checksums.md5 is 4b9390ddc51c72d6f66563cb02e48fe8; the data check
below streams the zip and confirms that sum, and lists the CRC-32 of every member read, so that a
later change is detectable. The description is version 0.8 (2 September 2014) and the files in
the zip are dated 2014. The zip is opened in place over range requests; nothing is written to disk.
What the data set holds. Spike times of 325 sorted units from 16 isolated retinas (5 dates in 2008), each file labelled with a genotype, and their responses to binary white noise only: flickering vertical and horizontal bars and checkerboards, drawn from the RAN1 generator whose bits are in the zip. It holds none of the histology of Figures 1 to 8, and none of the flashing spots, flashes, moving bars or gratings of Figure 9A to 9C.
Outside inputs. None.
| Claim | Tested here |
|---|---|
| fig1-broad-expression, fig2-postnatal-localization, fig3-synaptic-localization, s1-chx10-recombination, fig4h-inl-ipl-thinner, fig4-alleles-equivalent, fig4i-cell-type-loss, fig5-postnatal-onset, fig5-increased-apoptosis, fig6f-amacrine-loss-central, fig6f-neighbours, fig7-laminar-targeting, fig8ad-bax-rescue, fig8el-synapse-density, fig8mn-bax-laminar | Blocked: histology, not in the data set |
| fig9a-response-variety, fig9c-on-off-index | Blocked: no flashing-spot recordings |
| fig9-rod-cone | Blocked: no flashes of two intensities |
| fig9b-direction-selective | Blocked: no moving gratings or bars |
| fig9-cell-counts | Tested |
| fig9d-rf-size-similar | Tested |
| s3-receptive-field-surrounds | Tested |
| fig9e-slower-time-course | Tested |
| fig9f-lower-firing-rate | Tested |
| fig9g-threshold-unaltered | Tested |
| fig9h-gain-reduced | Tested |
Which bar recording. The paper names bars of 8.3 or 16.6 um but not their orientation, nor what
is done when a retina has more than one such recording. This was asked
(questions/crcns-ret-1.yaml); the reader found that the paper does not say, and the claims file
now names three readings in the criterion of fig9d-rf-size-similar and requires every claim on the
bars to be judged under all three: (A) the first vertical-bar recording of each retina at 8.3 or
16.6 um, (B) all its vertical-bar recordings at those widths pooled, spikes and frames together,
(C) its horizontal-bar recording where it has one, otherwise as A.
import hashlib
import io
import re
import time
import warnings
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import pypdf
import requests
from scipy import stats
import ret1
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()
z = ret1.open_zip()
retinas = ret1.load_retinas(z)
by_name = {R["retina"]: R for R in retinas}
nbits = max((r["x"] // r["dx"]) * (r["y"] // r["dy"]) * r["nframes"] for R in retinas for r in R["recordings"])
bits = ret1.ran1_bits(z, nbits)
print(f"CRCNS {ret1.DATASET_ID} ({ret1.VERSION}, doi:{ret1.DATASET_DOI}): {len(retinas)} retina files and "
f"{nbits:,} stimulus bits loaded in {time.time() - started:.0f} s")
CRCNS ret-1 (unversioned, doi:10.6080/K0RF5RZT): 16 retina files and 276,166,656 stimulus bits loaded in 4 s
Data check¶
Each check of the description against the values is stated under its output.
# Integrity of the zip: its MD5, streamed in memory, against the data set's checksums.md5.
sums = dict(line.split()[::-1] for line in ret1.read_text("checksums.md5").splitlines() if line.strip())
md5 = hashlib.md5()
with requests.get(ret1.BASE_URL + ret1.ZIP_NAME, stream=True, timeout=120) as r:
for chunk in r.iter_content(2**20):
md5.update(chunk)
print("checksums.md5:", sums)
print("MD5 of", ret1.ZIP_NAME, "as streamed:", md5.hexdigest(), "; matches checksums.md5:",
md5.hexdigest() == sums[ret1.ZIP_NAME] == ret1.ZIP_MD5)
print("\nMembers read (size in bytes and CRC-32 from the zip directory):")
for info in z.infolist():
if info.filename.startswith(ret1.PREFIX) and not info.is_dir():
print(f" {info.filename:40s} {info.file_size:>10,d} {info.CRC:08x}")
checksums.md5: {'crcns_ret-1.zip': '4b9390ddc51c72d6f66563cb02e48fe8', 'docs/crcns_ret-1_data_description.docx': '1b66fe25386b4d1cc14e66b6f719a985', 'docs/crcns_ret-1_data_description.pdf': 'eca35a17912488ad1ddf1e5231005aa5', 'filelist.txt': 'f7edda46d58d4b57d71f40b8bffc1a0c'}
MD5 of crcns_ret-1.zip as streamed: 4b9390ddc51c72d6f66563cb02e48fe8 ; matches checksums.md5: True
Members read (size in bytes and CRC-32 from the zip directory):
crcns_ret-1/Analysis_example.m 2,729 6ea8dd24
crcns_ret-1/Data/20080516_R1.mat 1,515,345 531bd383
crcns_ret-1/Data/20080516_R2.mat 4,462,406 b9f975a5
crcns_ret-1/Data/20080606_R1.mat 217,459 4685c94c
crcns_ret-1/Data/20080606_R2.mat 425,996 815618ca
crcns_ret-1/Data/20080606_R3.mat 112,553 b5feea39
crcns_ret-1/Data/20080624_R1.mat 6,263,599 ba9d6008
crcns_ret-1/Data/20080624_R2.mat 1,950,808 f5225245
crcns_ret-1/Data/20080624_R3.mat 1,619,650 76043d56
crcns_ret-1/Data/20080628_R2.mat 2,376,244 f958f564
crcns_ret-1/Data/20080628_R3.mat 1,478,450 eb92fe7b
crcns_ret-1/Data/20080628_R4.mat 1,854,783 496142bb
crcns_ret-1/Data/20080628_R5.mat 4,919,162 a8593154
crcns_ret-1/Data/20080628_R6.mat 4,834,679 2fffe4cf
crcns_ret-1/Data/20080628_R7.mat 617,052 1b221e72
crcns_ret-1/Data/20080702_R1.mat 392,296 4a891e3a
crcns_ret-1/Data/20080702_R4.mat 1,303,684 ebfeee29
crcns_ret-1/ran1.bin 37,500,000 80344e62
crcns_ret-1/ran1.m 1,735 62a6ec01
crcns_ret-1/README.txt 129 0693eaed
# The description's table of retinas against the files.
pdf = pypdf.PdfReader(io.BytesIO(requests.get(ret1.BASE_URL + "docs/crcns_ret-1_data_description.pdf", timeout=60).content))
text = "\n".join(p.extract_text() for p in pdf.pages)
described = {m[0]: (int(m[1]), m[2].strip()) for m in re.findall(r"(\d{8}_R\d)\s*\(\s*(\d+) cells\):\s*([^\n]+)", text)}
info = pd.DataFrame([{
"retina": R["retina"], "label": R["animal"], "group": ret1.group(R["animal"]), "cells": R["ncell"],
"described_cells": described.get(R["retina"], (None, None))[0],
"described_label": described.get(R["retina"], (None, None))[1],
"recordings": len(R["recordings"]),
"stimuli": ", ".join(f"{ret1.kind(r)} {ret1.bar_width_um(r) if ret1.kind(r) != 'checker' else r['dx'] * r['pixelsize']:.1f} um "
f"{r['frame'] * 1000:.2f} ms x {r['nframes']}" for r in R["recordings"]),
} for R in retinas])
print(info.to_string(index=False))
print("\nRetinas in the description:", len(described), "; files:", len(retinas))
print("Cell counts and labels agree with the description for every retina:",
bool((info.cells == info.described_cells).all() and (info.label == info.described_label).all()))
print("\nCells by label:"); print(info.groupby("label").cells.agg(["count", "sum"]).rename(columns={"count": "retinas", "sum": "cells"}).to_string())
print("\nCells by group used here (mutant = KO without Bax, control = WT):")
print(info.groupby("group").cells.agg(["count", "sum"]).rename(columns={"count": "retinas", "sum": "cells"}).to_string())
print("\nStimulus types in the data set:", sorted({r["type"] for R in retinas for r in R["recordings"]}))
print("Seeds:", sorted({r["seed"] for R in retinas for r in R["recordings"]}), "; pixel sizes (um):",
sorted({r["pixelsize"] for R in retinas for r in R["recordings"]}))
print("Frame lengths (ms):", sorted({round(r["frame"] * 1000, 3) for R in retinas for r in R["recordings"]}))
print("Experimenter:", sorted({R["experimenter"] for R in retinas}), "; dates:", sorted({R["date"] for R in retinas}))
retina label group cells described_cells described_label recordings stimuli
20080516_R1 KO (pax6) mutant 7 7 KO (pax6) 3 vbars 8.3 um 16.67 ms x 89899, checker 83.0 um 16.67 ms x 89898, hbars 8.3 um 16.67 ms x 89897
20080516_R2 KO (pax6) mutant 34 34 KO (pax6) 3 vbars 8.3 um 16.67 ms x 96057, hbars 8.3 um 16.67 ms x 89894, checker 83.0 um 16.67 ms x 89890
20080606_R1 KO (chx10) mutant 4 4 KO (chx10) 3 vbars 8.3 um 16.67 ms x 71879, hbars 8.3 um 16.67 ms x 71873, checker 83.0 um 16.67 ms x 71836
20080606_R2 KO (chx10) mutant 6 6 KO (chx10) 3 vbars 8.3 um 16.67 ms x 71397, checker 83.0 um 16.67 ms x 71877, hbars 8.3 um 16.67 ms x 71872
20080606_R3 KO (chx10) mutant 1 1 KO (chx10) 3 vbars 8.3 um 16.67 ms x 71909, hbars 8.3 um 16.67 ms x 71908, checker 83.0 um 16.67 ms x 71918
20080624_R1 WT (chx10 het) control 37 37 WT (chx10 het) 3 vbars 16.6 um 16.67 ms x 53877, hbars 16.6 um 16.67 ms x 53585, checker 83.0 um 16.67 ms x 53902
20080624_R2 KO (chx10) mutant 26 26 KO (chx10) 3 vbars 16.6 um 16.67 ms x 53560, vbars 16.6 um 16.67 ms x 53933, checker 83.0 um 16.67 ms x 53911
20080624_R3 KO (chx10) mutant 38 38 KO (chx10) 3 vbars 16.6 um 16.67 ms x 53923, checker 83.0 um 16.67 ms x 53936, vbars 41.5 um 16.67 ms x 35926
20080628_R2 KO (pax6) mutant 40 40 KO (pax6) 1 vbars 16.6 um 16.67 ms x 71762
20080628_R3 KO (pax6) mutant 32 32 KO (pax6) 2 vbars 16.6 um 16.67 ms x 71916, checker 66.4 um 33.34 ms x 35953
20080628_R4 WT (chx10 het) control 15 15 WT (chx10 het) 2 vbars 16.6 um 16.67 ms x 89903, checker 66.4 um 33.34 ms x 44926
20080628_R5 WT (chx10 het) control 43 43 WT (chx10 het) 2 vbars 16.6 um 16.67 ms x 71864, checker 66.4 um 33.34 ms x 35983
20080628_R6 WT (pax6 het) control 13 13 WT (pax6 het) 2 vbars 16.6 um 16.67 ms x 89736, checker 66.4 um 33.34 ms x 44961
20080628_R7 WT (pax6 het) control 14 14 WT (pax6 het) 1 vbars 16.6 um 16.67 ms x 89918
20080702_R1 KO bax -/- (chx10) bax 3 3 KO bax -/- (chx10) 2 vbars 16.6 um 16.67 ms x 89902, checker 66.4 um 33.34 ms x 44948
20080702_R4 KO (chx10) mutant 12 12 KO (chx10) 2 vbars 16.6 um 16.67 ms x 89895, checker 66.4 um 33.34 ms x 44949
Retinas in the description: 16 ; files: 16
Cell counts and labels agree with the description for every retina: True
Cells by label:
retinas cells
label
KO (chx10) 6 87
KO (pax6) 4 113
KO bax -/- (chx10) 1 3
WT (chx10 het) 3 95
WT (pax6 het) 2 27
Cells by group used here (mutant = KO without Bax, control = WT):
retinas cells
group
bax 1 3
control 5 122
mutant 10 200
Stimulus types in the data set: ['binarywhitenoise']
Seeds: [-10000] ; pixel sizes (um): [8.3]
Frame lengths (ms): [16.665, 16.669, 16.672, 33.344]
Experimenter: ['Yifeng Zhang, Markus Meister lab, Harvard University'] ; dates: ['20080516', '20080606', '20080624', '20080628', '20080702']
The 16 files match the description's table in cell counts and genotype labels. Every recording is binary white noise drawn from RAN1 with seed -10000: vertical bars (full height), horizontal bars (full width) or checkerboards. There are no flashing spots, flashes of different intensity, moving bars or drifting gratings, so the stimuli of Figure 9A, 9B and 9C and of the rod and cone test are not in the data set. The pixel size is 8.3 um as stated, so the bars are 8.3, 16.6 and (one recording) 41.5 um wide, the widths the Methods give except the last. Frames last 16.67 ms (60 Hz) for the bars, as the Methods state, and 33.3 ms for some checkerboards; two recordings of 20080702 state 16.665 and 16.669 ms.
The labels give 200 mutant cells in 10 retinas (Chx10-Cre 87, Pax6-Cre 113), 3 cells from one Bax -/- mutant retina, and 122 control cells in 5 retinas, 95 of them labelled "chx10 het". The paper's Figure 9 has 115 mutant and 143 control cells, and names its controls Pax6-Cre; Pcdh-gamma +/f-del or Pcdh-gamma f-del/f-del without Cre; it names no Chx10-Cre heterozygous controls. The files do not say which part of the Pax6-Cre retinas was recorded (the paper used their peripheral region only), nor the age of the mice, nor the allele.
# ran1.bin against the RAN1 generator of ran1.m, and the bit order.
check = ret1.ran1(-10000, 20000) >= 0.5
with z.open(ret1.PREFIX + "ran1.bin") as f:
raw = np.frombuffer(f.read(2500), dtype=np.uint8)
for order in ("little", "big"):
agree = (np.unpackbits(raw, bitorder=order)[:20000].astype(bool) == check).mean()
print(f"first 20000 bits, {order}-endian bit order: {agree:.4f} agree with RAN1(seed -10000) >= 0.5")
print("ran1.bin holds", z.getinfo(ret1.PREFIX + "ran1.bin").file_size * 8, "bits; the longest stimulus needs", nbits)
first 20000 bits, little-endian bit order: 1.0000 agree with RAN1(seed -10000) >= 0.5 first 20000 bits, big-endian bit order: 0.4981 agree with RAN1(seed -10000) >= 0.5 ran1.bin holds 300000000 bits; the longest stimulus needs 276166656
# Spike times: units, order, and range against the stimulus window.
rows = []
for R in retinas:
for rec in R["recordings"]:
end = rec["onset"] + rec["nframes"] * rec["frame"]
parts = ret1.split_trains(rec)
tails = [tl for _, tl in parts if len(tl)]
allt = np.concatenate([t for t in rec["spikes"] if len(t)])
rows.append({"retina": R["retina"], "rec": rec["index"], "kind": ret1.kind(rec), "onset_s": round(rec["onset"], 2),
"stim_end_s": round(end, 1), "first_spike_s": round(allt.min(), 3), "last_spike_s": round(allt.max(), 1),
"spikes_after_end": int((allt > end).sum()),
"unsorted_trains": len(tails), "head_ends_s": round(max((h.max() for h, tl in parts if len(tl)), default=np.nan), 1),
"tail_span_s": (f"{min(t.min() for t in tails):.1f}-{max(t.max() for t in tails):.1f}" if tails else ""),
"tail_spikes": int(sum(len(t) for t in tails))})
spk = pd.DataFrame(rows)
print(spk.to_string(index=False))
print("\nRecordings with out-of-order spike times:", int((spk.unsorted_trains > 0).sum()), "of", len(spk),
"; trains affected:", int(spk.unsorted_trains.sum()), "; spikes in the out-of-order segments:", int(spk.tail_spikes.sum()))
retina rec kind onset_s stim_end_s first_spike_s last_spike_s spikes_after_end unsorted_trains head_ends_s tail_span_s tail_spikes 20080516_R1 0 vbars 1.24 1500.0 0.022 1500.0 0 0 NaN 0 20080516_R1 1 checker 1.25 1500.0 0.029 1499.9 0 0 NaN 0 20080516_R1 2 hbars 1.26 1500.0 0.032 1500.0 0 0 NaN 0 20080516_R2 0 vbars 1.06 1602.5 0.068 1602.5 0 0 NaN 0 20080516_R2 1 hbars 1.32 1500.0 0.014 1500.0 0 0 NaN 0 20080516_R2 2 checker 1.39 1500.0 0.005 1500.0 0 0 NaN 0 20080606_R1 0 vbars 1.66 1200.0 0.321 1200.0 0 0 NaN 0 20080606_R1 1 hbars 1.75 1200.0 0.180 1199.8 0 0 NaN 0 20080606_R1 2 checker 2.38 1200.0 0.371 1200.0 0 0 NaN 0 20080606_R2 0 vbars 9.69 1200.0 0.123 1200.0 0 0 NaN 0 20080606_R2 1 checker 1.69 1200.0 0.174 1199.9 0 0 NaN 0 20080606_R2 2 hbars 1.77 1200.0 0.047 1200.0 0 0 NaN 0 20080606_R3 0 vbars 1.16 1200.0 0.079 1199.5 0 0 NaN 0 20080606_R3 1 hbars 1.18 1200.0 0.069 1199.9 0 0 NaN 0 20080606_R3 2 checker 1.00 1200.0 0.097 1199.9 0 0 NaN 0 20080624_R1 0 vbars 1.78 900.0 0.003 900.0 0 0 NaN 0 20080624_R1 1 hbars 6.65 900.0 0.002 900.0 0 0 NaN 0 20080624_R1 2 checker 1.37 900.0 0.002 900.0 0 0 NaN 0 20080624_R2 0 vbars 1.06 894.0 0.002 880.0 0 0 NaN 0 20080624_R2 1 vbars 0.85 900.0 0.004 900.0 0 0 NaN 0 20080624_R2 2 checker 1.22 900.0 0.002 900.0 0 0 NaN 0 20080624_R3 0 vbars 1.01 900.0 0.009 900.0 0 0 NaN 0 20080624_R3 1 checker 0.80 900.0 0.002 900.0 0 0 NaN 0 20080624_R3 2 vbars 1.05 600.0 0.019 600.0 0 0 NaN 0 20080628_R2 0 vbars 3.60 1200.0 0.002 1200.0 0 0 NaN 0 20080628_R3 0 vbars 1.04 1200.0 0.009 1200.0 0 0 NaN 0 20080628_R3 1 checker 1.23 1200.0 0.003 1200.0 0 0 NaN 0 20080628_R4 0 vbars 1.17 1500.0 0.024 1499.9 0 14 1440.0 720.0-780.0 6298 20080628_R4 1 checker 2.02 1500.0 0.004 1440.0 0 15 1440.0 720.0-780.0 7960 20080628_R5 0 vbars 1.90 1200.0 0.003 1200.0 0 0 NaN 0 20080628_R5 1 checker 1.21 1201.0 0.001 1200.0 0 15 1200.0 2.0-2.1 28 20080628_R6 0 vbars 0.94 1497.0 0.002 1499.9 44 11 1440.0 720.0-780.0 16158 20080628_R6 1 checker 0.84 1500.0 0.004 1440.0 0 13 1440.0 720.0-780.0 20303 20080628_R7 0 vbars 0.92 1500.0 0.328 1500.0 0 0 NaN 0 20080702_R1 0 vbars 1.17 1499.8 0.390 1499.9 2 2 1439.8 720.0-779.6 943 20080702_R1 1 checker 1.28 1500.0 0.061 1439.9 0 3 1439.9 720.0-779.8 1422 20080702_R4 0 vbars 1.31 1499.4 0.013 1440.0 0 12 1440.0 720.0-780.0 4968 20080702_R4 1 checker 1.26 1500.0 0.003 1440.0 0 12 1440.0 720.0-780.0 5077 Recordings with out-of-order spike times: 9 of 38 ; trains affected: 97 ; spikes in the out-of-order segments: 63157
# Where do the out-of-order segments belong? STA of the tail spikes alone, at their stored times and
# moved by 720 s (to 1440-1500 s, the part of the recording that has no spikes otherwise).
def peak_ratios(rec, trains, nlag=15):
r = dict(rec); r["spikes"] = trains
S, C = ret1.stimulus(r, bits), ret1.counts(r)
h, n = ret1.sta(S, C, nlag)
hn, _ = ret1.sta(S, np.roll(C, C.shape[0] // 2, axis=0), nlag)
with np.errstate(invalid="ignore"):
return np.abs(h).reshape(len(n), -1).max(1) / np.abs(hn).reshape(len(n), -1).max(1), n
tail_rows = []
for R in retinas:
rec = R["recordings"][0]
parts = ret1.split_trains(rec)
if ret1.kind(rec) == "checker" or not any(len(tl) for _, tl in parts):
continue
stored, n = peak_ratios(rec, [tl for _, tl in parts])
moved, _ = peak_ratios(rec, [tl + 720.0 for _, tl in parts])
ok = n >= 50
tail_rows.append({"retina": R["retina"], "rec": rec["index"], "cells_with_50_tail_spikes": int(ok.sum()),
"median_ratio_stored": round(float(np.median(stored[ok])), 2), "median_ratio_moved_720s": round(float(np.median(moved[ok])), 2),
"cells_higher_when_moved": int((moved[ok] > stored[ok]).sum())})
print(pd.DataFrame(tail_rows).to_string(index=False))
print("\nTrains without an out-of-order segment in the same recordings: spikes in 1440-1500 s and in 720-780 s")
for R in retinas:
for rec in R["recordings"]:
parts = ret1.split_trains(rec)
if any(len(tl) for _, tl in parts) and rec["nframes"] * rec["frame"] > 1450:
for c, (h, tl) in enumerate(parts):
if not len(tl):
print(f" {R['retina']} rec {rec['index']} unit {c}: {int((h > 1440).sum())} and {int(((h > 720) & (h < 780)).sum())}")
retina rec cells_with_50_tail_spikes median_ratio_stored median_ratio_moved_720s cells_higher_when_moved 20080628_R4 0 13 0.97 1.31 9 20080628_R6 0 11 1.09 1.34 10 20080702_R1 0 2 0.84 1.01 2 20080702_R4 0 12 0.96 1.01 8 Trains without an out-of-order segment in the same recordings: spikes in 1440-1500 s and in 720-780 s 20080628_R4 rec 0 unit 2: 755 and 729 20080628_R6 rec 0 unit 1: 1155 and 1187 20080628_R6 rec 0 unit 2: 1452 and 1427 20080702_R1 rec 0 unit 0: 554 and 583
Spike times are in seconds from the start of each recording and begin before the stimulus onset (about 1 s), as the example script assumes. In the 8 recordings of 20080628_R4 and R6 and of 20080702_R1 and R4 (vertical bars and checkerboards, each of 1500 s), almost every train is out of order: it runs from 0 to 1440 s and then holds a second segment of spikes between 720 and 780 s, though the stimulus runs to 1500 s. The few trains in these recordings that are in order have spikes between 1440 and 1500 s, about as many as between 720 and 780 s (list above). Moved by 720 s, to 1440 to 1500 s, these segments give higher STA peaks over the null than where they are stored, in most cells of the larger retinas (table above). The segments are consistent with the last minute of each recording stored with the wrong offset, but this is not proven. The main analysis uses the spike times as deposited; a variant moves the segments. (One checkerboard recording, 20080628_R5, has 1 or 2 spikes near 2 s out of order in several cells; it is not used.)
# Units sorted twice: pairs with more than half of the smaller train's spikes within 0.5 ms of the other's.
dups = []
for R in retinas:
for rec in R["recordings"]:
for a, b, f in ret1.duplicate_pairs(rec):
dups.append({"retina": R["retina"], "rec": rec["index"], "group": ret1.group(R["animal"]), "unit_a": a, "unit_b": b, "coincident": round(f, 3)})
dups = pd.DataFrame(dups)
pairs = dups.groupby(["retina", "group", "unit_a", "unit_b"]).coincident.agg(["min", "max", "count"]).reset_index()
print(pairs.to_string(index=False))
print("\nDistinct pairs:", len(pairs), "; by group:", pairs.groupby("group").size().to_dict())
# Each pair in the first vertical-bar recording, and the second unit dropped in the variant
first_vb = {R["retina"]: ret1.bar_recordings(R, "A")[0]["index"] for R in retinas}
drop = set()
for _, p in dups.iterrows():
if p.rec == first_vb[p.retina]:
drop.add((p.retina, int(p.unit_b)))
print("Units dropped in the variant without duplicates (second of each pair in the vertical-bar recording):", len(drop))
seen = {}
for R in retinas:
for rec in R["recordings"]:
for c, t in enumerate(rec["spikes"]):
if len(t):
seen.setdefault(hashlib.md5(np.sort(t).round(4).tobytes()).hexdigest(), []).append((R["retina"], rec["index"], c))
print("Spike trains that occur more than once, across all files, recordings and units:", sum(len(v) > 1 for v in seen.values()))
retina group unit_a unit_b min max count
20080516_R2 mutant 9 11 0.985 0.994 3
20080516_R2 mutant 27 32 0.969 0.989 3
20080606_R2 mutant 3 4 0.925 0.975 2
20080624_R2 mutant 11 20 0.970 0.999 3
20080624_R3 mutant 22 25 0.963 0.982 3
20080624_R3 mutant 24 28 0.958 0.969 3
20080624_R3 mutant 24 37 0.936 0.954 3
20080624_R3 mutant 26 31 0.998 1.000 3
20080624_R3 mutant 28 37 0.931 0.970 3
20080628_R2 mutant 2 4 0.924 0.924 1
20080628_R2 mutant 22 26 0.955 0.955 1
20080628_R3 mutant 13 18 0.993 0.997 2
20080628_R5 control 13 14 0.996 0.998 2
20080628_R5 control 25 31 0.949 0.954 2
20080628_R5 control 26 30 0.891 0.929 2
20080628_R5 control 28 29 0.702 0.722 2
Distinct pairs: 16 ; by group: {'control': 4, 'mutant': 12}
Units dropped in the variant without duplicates (second of each pair in the vertical-bar recording): 15
Spike trains that occur more than once, across all files, recordings and units: 0
No recording is deposited twice: no spike train repeats across files or units. Within recordings, the pairs above share 70 to 100% of their spikes within 0.5 ms in every recording of the retina, so each pair is most likely one neuron sorted twice. All units are kept in the main analysis, as the claims count all units; a variant drops the second unit of each pair.
# Clock: does the stimulus, rebuilt from its onset and frame length, line up with the spikes? Per
# recording, the STA peak over that of a null STA (spike counts circularly shifted by half the
# recording), and the lag of the STA peak. A response aligned to the stimulus gives ratios well
# above 1 at a consistent lag; misaligned timing gives ratios near 1.
clock = []
for R in retinas:
for rec in R["recordings"]:
if ret1.kind(rec) == "checker" and R["retina"] not in ("20080702_R4", "20080702_R1", "20080606_R1", "20080606_R2", "20080606_R3"):
continue
ratio, n = peak_ratios(rec, rec["spikes"], nlag=ret1.STA_FRAMES)
S, C = ret1.stimulus(rec, bits), ret1.counts(rec)
h, _ = ret1.sta(S, C)
lag_ms = np.array([(np.unravel_index(np.nanargmax(np.abs(x)), x.shape)[1] + 0.5) * rec["frame"] * 1000 if n[i] else np.nan
for i, x in enumerate(h)])
clock.append({"retina": R["retina"], "group": ret1.group(R["animal"]), "rec": rec["index"], "kind": ret1.kind(rec),
"cells": len(n), "median_ratio": round(float(np.nanmedian(ratio)), 2), "cells_ratio_above_2": int((ratio > 2).sum()),
"median_peak_lag_ms": round(float(np.nanmedian(lag_ms)), 0)})
clock = pd.DataFrame(clock)
print(clock.to_string(index=False))
retina group rec kind cells median_ratio cells_ratio_above_2 median_peak_lag_ms 20080516_R1 mutant 0 vbars 7 2.15 4 125.0 20080516_R1 mutant 2 hbars 7 1.21 1 142.0 20080516_R2 mutant 0 vbars 34 1.94 16 142.0 20080516_R2 mutant 1 hbars 34 1.73 14 142.0 20080606_R1 mutant 0 vbars 4 1.46 0 142.0 20080606_R1 mutant 1 hbars 4 1.20 0 133.0 20080606_R1 mutant 2 checker 4 1.43 1 125.0 20080606_R2 mutant 0 vbars 6 1.27 0 167.0 20080606_R2 mutant 1 checker 6 1.95 2 167.0 20080606_R2 mutant 2 hbars 6 1.14 0 150.0 20080606_R3 mutant 0 vbars 1 1.31 0 458.0 20080606_R3 mutant 1 hbars 1 1.18 0 192.0 20080606_R3 mutant 2 checker 1 1.61 0 158.0 20080624_R1 control 0 vbars 37 3.63 30 108.0 20080624_R1 control 1 hbars 37 2.83 26 108.0 20080624_R2 mutant 0 vbars 26 1.19 4 125.0 20080624_R2 mutant 1 vbars 26 1.92 12 117.0 20080624_R3 mutant 0 vbars 38 1.83 18 125.0 20080624_R3 mutant 2 vbars 38 2.40 24 125.0 20080628_R2 mutant 0 vbars 40 5.13 38 108.0 20080628_R3 mutant 0 vbars 32 1.75 13 142.0 20080628_R4 control 0 vbars 15 4.76 12 108.0 20080628_R5 control 0 vbars 43 4.05 38 125.0 20080628_R6 control 0 vbars 13 6.80 13 92.0 20080628_R7 control 0 vbars 14 4.50 14 108.0 20080702_R1 bax 0 vbars 3 2.27 2 225.0 20080702_R1 bax 1 checker 3 4.95 2 150.0 20080702_R4 mutant 0 vbars 12 0.96 0 283.0 20080702_R4 mutant 1 checker 12 3.88 12 150.0
For most bar recordings the STA peaks lie well above the null at lags of about 100 to 140 ms, so the stimulus as rebuilt shares the clock of the spikes. The vertical bars of 20080702_R4 are the exception: with the stated frame none of its 12 cells has an STA above the null (median ratio about 1), while the same cells give clear STAs to the checkerboard of the same retina. The search below shows why.
# Alignment search. (1) The frame length: the two vertical-bar recordings of 20080702 state 16.665
# and 16.669 ms, where every other bar recording states 16.672 ms; scan it in steps of 0.001 ms.
# (2) The onset: STAs at lags from -2 s to +2.5 s (moving the onset by k frames moves the window of
# lags by k), for the weak 20080606 retinas and 20080702_R4. Per lag, the median over cells of the
# STA's largest |value| at that lag over the null's peak; an aligned recording peaks at 100 to 140 ms.
bar_frames = pd.Series({(R["retina"], rec["index"]): rec["frame"] for R in retinas for rec in R["recordings"] if ret1.kind(rec) != "checker"})
common = float(bar_frames.median())
off = bar_frames[(bar_frames - common).abs() > 1e-6]
print(f"Stated frame of the {len(bar_frames)} bar recordings: median {common * 1000:.4f} ms; "
f"{len(bar_frames) - len(off)} within 0.001 ms of it; the others: {(off * 1000).round(4).to_dict()}")
print("Checkerboard frames of 20080702, halved (ms):",
{R["retina"]: round(r["frame"] / 2 * 1000, 4) for R in retinas if R["retina"].startswith("20080702") for r in R["recordings"] if ret1.kind(r) == "checker"})
def lag_profile(rec, frame, lags, nlag=ret1.STA_FRAMES):
"""Per lag, the median over cells of max |STA| over bars at that lag, over the null STA's peak."""
r = dict(rec); r["frame"] = frame
S, C = ret1.stimulus(r, bits), ret1.counts(r)
a = np.abs(ret1.wide_sta(S, C, lags)).max(axis=1)
hn = ret1.wide_sta(S, np.roll(C, C.shape[0] // 2, axis=0), np.arange(nlag))
pn = np.abs(hn).reshape(len(hn), -1).max(axis=1)
return np.median(a / pn[:, None], axis=0), a / pn[:, None]
scan = []
for (name, i), fr in off.items():
rec = by_name[name]["recordings"][i]
for f in [fr] + list(np.arange(16.664, 16.6765, 0.001) / 1000) + [common]:
_, a = lag_profile(rec, f, np.arange(ret1.STA_FRAMES))
scan.append({"retina": name, "rec": i, "frame_ms": round(f * 1000, 4), "stated": f == fr, "common": f == common,
"median_peak_ratio": round(float(np.median(a.max(axis=1))), 2), "cells_ratio_above_2": int((a.max(axis=1) > 2).sum()), "cells": len(a)})
scan = pd.DataFrame(scan)
print("\nFrame scan, onset as stated:"); print(scan.to_string(index=False))
lags = np.arange(-120, 150)
onset = []
for name in ("20080606_R1", "20080606_R2", "20080606_R3", "20080702_R4"):
for rec in by_name[name]["recordings"]:
for label, f in (("stated", rec["frame"]), ("common", common)):
if label == "common" and (ret1.kind(rec) == "checker" or abs(rec["frame"] - common) < 1e-6):
continue
prof, _ = lag_profile(rec, f, lags)
k = int(np.argmax(prof))
far = prof[np.abs(lags - lags[k]) > 30]
onset.append({"retina": name, "rec": rec["index"], "kind": ret1.kind(rec), "frame": label, "cells": by_name[name]["ncell"],
"peak_lag_ms": round((lags[k] + 0.5) * f * 1000), "profile_at_peak": round(float(prof[k]), 2),
"max_beyond_0.5s_of_peak": round(float(far.max()), 2), "median_over_lags": round(float(np.median(prof)), 2)})
print("\nOnset search, lags -2 to +2.5 s:"); print(pd.DataFrame(onset).to_string(index=False))
Stated frame of the 24 bar recordings: median 16.6718 ms; 22 within 0.001 ms of it; the others: {('20080702_R1', 0): 16.6691, ('20080702_R4', 0): 16.6653}
Checkerboard frames of 20080702, halved (ms): {'20080702_R1': 16.6718, '20080702_R4': 16.6718}
Frame scan, onset as stated:
retina rec frame_ms stated common median_peak_ratio cells_ratio_above_2 cells
20080702_R1 0 16.6691 True False 2.27 2 3
20080702_R1 0 16.6640 False False 1.10 0 3
20080702_R1 0 16.6650 False False 1.23 0 3
20080702_R1 0 16.6660 False False 1.52 0 3
20080702_R1 0 16.6670 False False 1.55 0 3
20080702_R1 0 16.6680 False False 1.59 0 3
20080702_R1 0 16.6690 False False 2.18 2 3
20080702_R1 0 16.6700 False False 2.38 2 3
20080702_R1 0 16.6710 False False 3.54 2 3
20080702_R1 0 16.6720 False False 4.16 2 3
20080702_R1 0 16.6730 False False 3.57 2 3
20080702_R1 0 16.6740 False False 2.05 2 3
20080702_R1 0 16.6750 False False 1.31 0 3
20080702_R1 0 16.6760 False False 1.26 0 3
20080702_R1 0 16.6718 False True 4.17 2 3
20080702_R4 0 16.6653 True False 0.96 0 12
20080702_R4 0 16.6640 False False 1.02 0 12
20080702_R4 0 16.6650 False False 1.02 0 12
20080702_R4 0 16.6660 False False 1.02 0 12
20080702_R4 0 16.6670 False False 1.06 0 12
20080702_R4 0 16.6680 False False 1.31 0 12
20080702_R4 0 16.6690 False False 1.65 2 12
20080702_R4 0 16.6700 False False 2.18 7 12
20080702_R4 0 16.6710 False False 2.79 10 12
20080702_R4 0 16.6720 False False 2.76 10 12
20080702_R4 0 16.6730 False False 2.42 8 12
20080702_R4 0 16.6740 False False 2.09 7 12
20080702_R4 0 16.6750 False False 1.44 2 12
20080702_R4 0 16.6760 False False 1.30 1 12
20080702_R4 0 16.6718 False True 2.57 10 12
Onset search, lags -2 to +2.5 s:
retina rec kind frame cells peak_lag_ms profile_at_peak max_beyond_0.5s_of_peak median_over_lags
20080606_R1 0 vbars stated 4 158 1.45 0.95 0.80
20080606_R1 1 hbars stated 4 142 1.08 0.90 0.76
20080606_R1 2 checker stated 4 125 1.37 0.97 0.81
20080606_R2 0 vbars stated 6 158 1.21 0.98 0.83
20080606_R2 1 checker stated 6 175 1.95 0.87 0.78
20080606_R2 2 hbars stated 6 142 1.07 0.97 0.79
20080606_R3 0 vbars stated 1 -1242 1.38 1.31 0.87
20080606_R3 1 hbars stated 1 192 1.18 1.09 0.74
20080606_R3 2 checker stated 1 158 1.61 1.18 0.84
20080702_R4 0 vbars stated 12 775 1.11 0.84 0.74
20080702_R4 0 vbars common 12 158 2.52 0.83 0.75
20080702_R4 1 checker stated 12 150 3.74 0.89 0.83
The stated frames of the two 20080702 vertical-bar recordings (16.6653 and 16.6691 ms) are not those of the stimulus. Over about 90,000 frames, a frame 0.0065 ms too short drifts by about 0.6 s, which smears the STA. The scan peaks at 16.671 to 16.672 ms in both recordings (20080702_R4: median ratio 2.79 and 2.76, against 0.96 at the stated frame; 20080702_R1: 3.54 and 4.16, against 2.27). That is the frame of the other 22 bar recordings (median 16.6718 ms), and half the checkerboard frame of the same two retinas. The data are trusted over the description: from here on these two recordings use 16.6718 ms, and a variant keeps the stated frames. With it, the lag profile of 20080702_R4 peaks at 158 ms; with the stated frame it has no peak (its largest value, 1.11, is at 775 ms).
The onset search finds no better alignment for the 20080606 retinas (all mutant). In every bar and checkerboard recording of 20080606_R1 and R2 the profile peaks at 125 to 175 ms, above its largest value more than 0.5 s from the peak. The single cell of 20080606_R3 has no clear peak in its bar recordings (largest value 1.38 at -1242 ms in the vertical bars, against 1.31 within the stated window), but its checkerboard profile peaks at 158 ms. So the weak STAs of these retinas are weak responses at the stated onset, not a misalignment that a shift of up to 2 s would repair.
# The correction used from here on: the two 20080702 vertical-bar recordings take the frame of the
# other bar recordings; the stated frame is kept for the variant "frames as deposited".
for R in retinas:
for rec in R["recordings"]:
rec["frame_stated"] = rec["frame"]
if ret1.kind(rec) != "checker" and abs(rec["frame"] - common) > 1e-6:
rec["frame"] = common
ratio, n = peak_ratios(rec, rec["spikes"], nlag=ret1.STA_FRAMES)
print(f"{R['retina']} rec {rec['index']}: frame {rec['frame_stated'] * 1000:.4f} -> {common * 1000:.4f} ms; "
f"STA peak ratio median {np.nanmedian(ratio):.2f}, above 2 in {int((ratio > 2).sum())} of {len(ratio)} cells")
20080702_R1 rec 0: frame 16.6691 -> 16.6718 ms; STA peak ratio median 4.20, above 2 in 2 of 3 cells
20080702_R4 rec 0: frame 16.6653 -> 16.6718 ms; STA peak ratio median 2.57, above 2 in 10 of 12 cells
Measures¶
Every per-cell measure, under each of the claims file's readings of which bar recording is used (A, B, C; fig9d-rf-size-similar), and, under reading A, with the out-of-order spike segments moved by 720 s and, under each of A, B and C, with the frames of the 20080702 bar recordings as deposited. The Bax -/- retina (3 cells) is measured but belongs to neither group: the paper did not use Bax double mutants for Figure 9, and the claims define the groups without them.
t0 = time.time()
rows = []
for reading in ret1.READINGS:
for R in retinas:
for d in ret1.measure_retina(R, ret1.bar_recordings(R, reading), bits):
rows.append({"reading": reading, **d})
for R in retinas:
recs = [ret1.with_tail_shift(r, 720.0) for r in ret1.bar_recordings(R, "A")]
for d in ret1.measure_retina(R, recs, bits):
rows.append({"reading": "A, segments moved", **d})
for reading in ret1.READINGS:
label = f"{reading}, frames as deposited"
for R in retinas:
recs = ret1.bar_recordings(R, reading)
if any(r["frame"] != r["frame_stated"] for r in recs):
for d in ret1.measure_retina(R, [dict(r, frame=r["frame_stated"]) for r in recs], bits):
rows.append({"reading": label, **d})
fixed = {r["retina"] for r in rows if r["reading"] == label}
rows += [dict(r, reading=label) for r in rows if r["reading"] == reading and r["retina"] not in fixed]
cells = pd.DataFrame(rows)
cells["duplicate"] = [(r, c) in drop for r, c in zip(cells.retina, cells.cell)]
print(f"measured in {time.time() - t0:.0f} s")
print(cells.groupby(["reading", "group"]).agg(cells=("cell", "size"), no_spikes=("spikes_sta", lambda s: int((s == 0).sum())),
bar_um=("bar_um", lambda s: sorted(s.unique())), kind=("kind", lambda s: sorted(s.unique()))).to_string())
num = ["rate_hz", "peak_ratio", "fwhm_svd", "fwhm_peak", "ttp_svd_frame", "ttp_peak_frame", "theta_frame_continuous", "gain_frame_continuous"]
print("\nRanges under reading A (min, max):")
print(cells[cells.reading == "A"].groupby("group")[num].agg(["min", "max"]).T.round(3).to_string())
measured in 171 s
cells no_spikes bar_um kind
reading group
A bax 3 0 [16.6] [vbars]
control 122 0 [16.6] [vbars]
mutant 200 0 [8.3, 16.6] [vbars]
A, frames as deposited bax 3 0 [16.6] [vbars]
control 122 0 [16.6] [vbars]
mutant 200 0 [8.3, 16.6] [vbars]
A, segments moved bax 3 0 [16.6] [vbars]
control 122 0 [16.6] [vbars]
mutant 200 0 [8.3, 16.6] [vbars]
B bax 3 0 [16.6] [vbars]
control 122 0 [16.6] [vbars]
mutant 200 0 [8.3, 16.6] [vbars]
B, frames as deposited bax 3 0 [16.6] [vbars]
control 122 0 [16.6] [vbars]
mutant 200 0 [8.3, 16.6] [vbars]
C bax 3 0 [16.6] [vbars]
control 122 0 [16.6] [hbars, vbars]
mutant 200 0 [8.3, 16.6] [hbars, vbars]
C, frames as deposited bax 3 0 [16.6] [vbars]
control 122 0 [16.6] [hbars, vbars]
mutant 200 0 [8.3, 16.6] [hbars, vbars]
Ranges under reading A (min, max):
group bax control mutant
rate_hz min 1.922 0.356 0.365
max 15.315 38.917 26.592
peak_ratio min 1.226 1.066 0.860
max 5.771 9.771 8.803
fwhm_svd min 85.326 37.533 18.573
max 212.460 332.208 331.200
fwhm_peak min 32.903 25.442 8.506
max 222.887 313.217 244.335
ttp_svd_frame min 0.142 0.075 0.042
max 0.192 0.308 0.492
ttp_peak_frame min 0.142 0.075 0.008
max 0.175 0.275 0.458
theta_frame_continuous min -0.227 -1.744 -1.075
max 1.275 2.313 2.263
gain_frame_continuous min 18.553 13.074 13.863
max 23.338 63.192 69.991
GROUPS = ("mutant", "control")
CI = ("binomial", "dkw", "bootstrap")
def split(df, col):
return df[df.group == "mutant"][col].to_numpy(float), df[df.group == "control"][col].to_numpy(float)
def judge(df, cols, rng, label=None):
"""For each measure column and CI reading: medians, KS test, and whether the 95% bands separate."""
out = []
for col in cols:
m, c = split(df, col)
m, c = m[np.isfinite(m)], c[np.isfinite(c)]
ks = stats.ks_2samp(m, c)
for ci in CI:
r = ret1.compare_bands(m, c, ci, rng)
out.append({**({"variant": label} if label else {}), "measure": col, "ci": ci, "n_mut": r["n_mutant"], "n_ctl": r["n_control"],
"median_mut": np.median(m), "median_ctl": np.median(c), "ks_p": ks.pvalue,
"separate": r["separate"], "mutant_larger_pts": r["mutant_right"], "mutant_smaller_pts": r["mutant_left"],
"sep_range": (f"{r['range'][0]:.3g} to {r['range'][1]:.3g}" if r["range"] else "")})
return pd.DataFrame(out)
def by_retina(df, cols):
return df[df.group.isin(GROUPS)].groupby(["group", "retina"])[cols].agg(["median", "size"]).round(3)
def variants(rng, cols):
"""The same comparison, reading A, on subsets and on the corrected spike times."""
A = cells[cells.reading == "A"]
sets = {
"all units (main)": A,
"without duplicate units": A[~A.duplicate],
"without 20080702_R4": A[A.retina != "20080702_R4"],
"out-of-order segments moved 720 s": cells[cells.reading == "A, segments moved"],
"20080702 frames as deposited": cells[cells.reading == "A, frames as deposited"],
"mutant Chx10-Cre only": A[(A.group == "control") | A.animal.str.contains("chx10") & (A.group == "mutant")],
"mutant Pax6-Cre only": A[(A.group == "control") | A.animal.str.contains("pax6") & (A.group == "mutant")],
"control Pax6-Cre het only": A[(A.group == "mutant") | (A.animal == "WT (pax6 het)")],
"cells with STA peak ratio above 2": A[A.peak_ratio > 2],
"16.6 um bars only": A[A.bar_um == 16.6],
}
return pd.concat([judge(d[d.group.isin(GROUPS)], cols, rng, label=k) for k, d in sets.items()], ignore_index=True)
def ecdf_plot(ax, df, col, title, xlabel, scale=1.0):
for g, colour in (("mutant", "tab:red"), ("control", "black")):
v = np.sort(df[df.group == g][col].dropna().to_numpy() * scale)
ax.step(v, np.arange(1, len(v) + 1) / len(v), where="post", color=colour, label=f"{g} ({len(v)})")
lo, hi = ret1.band(v, v, "binomial")
ax.fill_between(v, lo, hi, step="post", color=colour, alpha=0.15)
ax.set_title(title, fontsize=9); ax.set_xlabel(xlabel); ax.set_ylabel("cumulative fraction"); ax.legend(fontsize=8)
def separating_points(m, c, ci, rng):
"""Every value where the two bands separate: the cells at or below it in each group and the bands."""
m, c = m[np.isfinite(m)], c[np.isfinite(c)]
grid = np.unique(np.concatenate([m, c]))
lm, hm = ret1.band(m, grid, ci, rng)
lc, hc = ret1.band(c, grid, ci, rng)
sep = (hm < lc) | (hc < lm)
return pd.DataFrame({"value": grid[sep], "mutant_at_or_below": np.searchsorted(np.sort(m), grid[sep], "right"), "n_mut": len(m),
"control_at_or_below": np.searchsorted(np.sort(c), grid[sep], "right"), "n_ctl": len(c),
"mutant_band": [f"{a:.3f}-{b:.3f}" for a, b in zip(lm[sep], hm[sep])],
"control_band": [f"{a:.3f}-{b:.3f}" for a, b in zip(lc[sep], hc[sep])],
"direction": np.where(hm[sep] < lc[sep], "mutant larger", "mutant smaller")})
The bands under shuffled labels¶
How often do the bands separate when the groups do not differ? For the main measures of the claims (reading A), the group labels are shuffled over the 322 cells, keeping the group sizes, 200 times, and the bands compared as in the claims. This is the rate at which "the bands separate" is met by chance under each band reading, with these cells' values.
rng = np.random.default_rng(900)
A = cells[(cells.reading == "A") & cells.group.isin(GROUPS)]
null_cols = ["fwhm_svd", "ttp_svd_frame", "ttp_peak_frame", "rate_hz", "theta_frame_continuous", "theta_binned_printed",
"gain_frame_printed", "gain_frame_continuous"]
NSHUF = 200
t0 = time.time()
rows = []
for col in null_cols:
x = A[col].to_numpy(float)
is_mut = (A.group == "mutant").to_numpy()
for ci in CI:
sep = 0
for _ in range(NSHUF):
lab = rng.permutation(is_mut)
sep += ret1.compare_bands(x[lab], x[~lab], ci, rng)["separate"]
rows.append({"measure": col, "ci": ci, "shuffles": NSHUF, "separate": sep, "rate": sep / NSHUF})
null_rates = pd.DataFrame(rows)
print(null_rates.pivot(index="measure", columns="ci", values="rate").round(3).to_string())
print(f"\nRate over all measures: {null_rates.groupby('ci').separate.sum().div(null_rates.groupby('ci').shuffles.sum()).round(3).to_dict()}"
f"; {time.time() - t0:.0f} s")
ci binomial bootstrap dkw
measure
fwhm_svd 0.380 0.450 0.0
gain_frame_continuous 0.360 0.435 0.0
gain_frame_printed 0.425 0.330 0.0
rate_hz 0.380 0.390 0.0
theta_binned_printed 0.345 0.415 0.0
theta_frame_continuous 0.380 0.390 0.0
ttp_peak_frame 0.255 0.290 0.0
ttp_svd_frame 0.300 0.260 0.0
Rate over all measures: {'binomial': 0.353, 'bootstrap': 0.37, 'dkw': 0.0}; 100 s
Under shuffled labels the binomial bands separate in 26 to 43% of shuffles, depending on the measure (35% over all), the bootstrap bands in 26 to 45% (37%), and the DKW bands in none of 1600. Both pointwise bands have zero width where a group's cumulative fraction is 0 or 1, so a few cells beyond the other group's range are enough to separate them. A separation under the binomial or bootstrap band alone is therefore weak evidence of a difference, and an overlap under every band reading, which the claims of absence require, fails for about a third of pairs of samples drawn from one distribution. The criteria are the claims file's and are applied as written; each conclusion below says whether its result holds under the DKW band.
fig9-cell-counts¶
Figure 9C to 9H report 115 RGCs from mutant retinas and 143 RGCs from control retinas. Expected 115 (tolerance 11.5) mutant and 143 (14.3) control cells, counted as the units of the data set's mutant and control recordings, all units and units with a flicker response.
A = cells[cells.reading == "A"]
counts = pd.DataFrame({
"all units": A.groupby("group").size(),
"units with spikes in the bar recording": A[A.spikes_sta > 0].groupby("group").size(),
"STA peak ratio above 1.5": A[A.peak_ratio > 1.5].groupby("group").size(),
"STA peak ratio above 2": A[A.peak_ratio > 2].groupby("group").size(),
"all units without duplicates": A[~A.duplicate].groupby("group").size(),
}).fillna(0).astype(int)
counts.loc["mutant + bax"] = counts.loc["mutant"] + counts.loc["bax"]
print(counts.to_string())
print("\nExpected: mutant 115 (103.5 to 126.5), control 143 (128.7 to 157.3)")
print("Mutant cells by Cre line:", A[A.group == "mutant"].animal.value_counts().to_dict())
print("Control cells by label:", A[A.group == "control"].animal.value_counts().to_dict())
print("No count of control units can exceed", int(counts.loc["control", "all units"]), "(all control units), below the lower bound 128.7")
all units units with spikes in the bar recording STA peak ratio above 1.5 STA peak ratio above 2 all units without duplicates
group
bax 3 3 2 2 3
control 122 122 113 107 118
mutant 200 200 138 103 189
mutant + bax 203 203 140 105 192
Expected: mutant 115 (103.5 to 126.5), control 143 (128.7 to 157.3)
Mutant cells by Cre line: {'KO (pax6)': 113, 'KO (chx10)': 87}
Control cells by label: {'WT (chx10 het)': 95, 'WT (pax6 het)': 27}
No count of control units can exceed 122 (all control units), below the lower bound 128.7
# Per retina: label, Cre line, units, bar width of reading A, and units with clear STAs. The data
# set gives no region of the Pax6-Cre retinas, so the paper's peripheral subset cannot be formed.
per_retina = A.groupby(["group", "animal", "retina"]).agg(units=("cell", "size"), bar_um=("bar_um", "first"),
ratio_above_1_5=("peak_ratio", lambda s: int((s > 1.5).sum())),
ratio_above_2=("peak_ratio", lambda s: int((s > 2).sum())))
print(per_retina.to_string())
print("\nBy label:"); print(per_retina.drop(columns="bar_um").groupby(["group", "animal"]).sum().to_string())
units bar_um ratio_above_1_5 ratio_above_2
group animal retina
bax KO bax -/- (chx10) 20080702_R1 3 16.6 2 2
control WT (chx10 het) 20080624_R1 37 16.6 33 30
20080628_R4 15 16.6 13 12
20080628_R5 43 16.6 40 38
WT (pax6 het) 20080628_R6 13 16.6 13 13
20080628_R7 14 16.6 14 14
mutant KO (chx10) 20080606_R1 4 8.3 2 0
20080606_R2 6 8.3 2 0
20080606_R3 1 8.3 0 0
20080624_R2 26 16.6 5 4
20080624_R3 38 16.6 27 18
20080702_R4 12 16.6 12 10
KO (pax6) 20080516_R1 7 8.3 6 4
20080516_R2 34 8.3 27 16
20080628_R2 40 16.6 38 38
20080628_R3 32 16.6 19 13
By label:
units ratio_above_1_5 ratio_above_2
group animal
bax KO bax -/- (chx10) 3 2 2
control WT (chx10 het) 95 86 80
WT (pax6 het) 27 27 27
mutant KO (chx10) 87 48 32
KO (pax6) 113 90 71
Result: not reproduced. The data set's labels give 200 mutant units (87 Chx10-Cre, 113 Pax6-Cre) and 122 control units (95 "WT (chx10 het)", 27 "WT (pax6 het)"), against 115 (103.5 to 126.5) and 143 (128.7 to 157.3). Units whose STA peak is more than 1.5 times the null's, a threshold chosen here, number 138 mutant and 113 control; more than 2 times, 103 and 107. Neither mutant count shown is inside its tolerance (103 is just below 103.5), but the mutant count falls from 138 to 103 between the two thresholds, so a threshold between them could put it inside; with the 20080702 frames as deposited the count above 1.5 is 126, inside it (cell 58). The control count cannot get there: no count of control units can exceed 122, below the lower bound. So the counts miss under any reading of "units with a flicker response" because of the control count. The 3 units of the Bax -/- retina are in neither group. The files give each unit's retina and label but not the region recorded in the Pax6-Cre retinas, so the per-retina table cannot be matched to the paper's peripheral subset.
fig9d-rf-size-similar¶
Receptive field centre size varies greatly among RGCs, but its distribution is similar in control and mutant retinas.
FWHM of |b(x)| (um), under the two separations of h and the three band readings, and the three readings of which bar recording is used. A claim of absence: reproduced when the bands overlap under every combination.
rng = np.random.default_rng(904)
fw = pd.concat([judge(cells[(cells.reading == rd) & cells.group.isin(GROUPS)], ["fwhm_svd", "fwhm_peak"], rng).assign(recording=rd)
for rd in ret1.READINGS], ignore_index=True)
print(fw.round(4).to_string(index=False))
print("\nCombinations:", len(fw), "; bands separate in", int(fw.separate.sum()),
"; of these with mutant at smaller sizes:", int((fw.separate & (fw.mutant_smaller_pts > 0) & (fw.mutant_larger_pts == 0)).sum()))
print("\nSpread (5th to 95th percentile, um), reading A, svd:")
for g in GROUPS:
v = cells[(cells.reading == "A") & (cells.group == g)].fwhm_svd.dropna()
print(f" {g}: {v.quantile(0.05):.1f} to {v.quantile(0.95):.1f}; cells at one bar width or less: {(v <= cells[(cells.reading == 'A') & (cells.group == g)].bar_um.loc[v.index]).sum()} of {len(v)}")
print("\nBy retina (reading A):")
print(by_retina(cells[cells.reading == "A"], ["fwhm_svd", "fwhm_peak", "bar_um"]).to_string())
# Reading B with the 20080702 frames as deposited. Those retinas have one vertical-bar recording, so
# their rows under B are those of reading A.
print("\nVertical-bar recordings under reading B, 20080702:", {n: len(ret1.bar_recordings(by_name[n], "B")) for n in ("20080702_R1", "20080702_R4")})
B_dep = pd.concat([cells[(cells.reading == "B") & ~cells.retina.str.startswith("20080702")],
cells[(cells.reading == "A, frames as deposited") & cells.retina.str.startswith("20080702")]])
print("Reading B, 20080702 frames as deposited:")
print(judge(B_dep[B_dep.group.isin(GROUPS)], ["fwhm_svd", "fwhm_peak"], rng).round(4).to_string(index=False))
measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range recording
fwhm_svd binomial 200 122 121.7268 156.1976 0.000 True 0 213 21.1 to 165 A
fwhm_svd dkw 200 122 121.7268 156.1976 0.000 True 0 71 87 to 130 A
fwhm_svd bootstrap 200 122 121.7268 156.1976 0.000 True 0 214 21.1 to 166 A
fwhm_peak binomial 200 122 97.2946 150.7827 0.000 True 0 259 9.24 to 171 A
fwhm_peak dkw 200 122 97.2946 150.7827 0.000 True 0 194 52.2 to 163 A
fwhm_peak bootstrap 200 122 97.2946 150.7827 0.000 True 0 256 9.24 to 170 A
fwhm_svd binomial 200 122 134.0787 156.1976 0.004 True 0 113 29.9 to 130 B
fwhm_svd dkw 200 122 134.0787 156.1976 0.004 False 0 0 B
fwhm_svd bootstrap 200 122 134.0787 156.1976 0.004 True 0 116 29.9 to 130 B
fwhm_peak binomial 200 122 103.9830 150.7827 0.000 True 0 251 9.24 to 168 B
fwhm_peak dkw 200 122 103.9830 150.7827 0.000 True 0 178 62 to 158 B
fwhm_peak bootstrap 200 122 103.9830 150.7827 0.000 True 0 251 9.24 to 168 B
fwhm_svd binomial 200 122 123.7236 166.5035 0.000 True 0 278 13.1 to 225 C
fwhm_svd dkw 200 122 123.7236 166.5035 0.000 True 0 165 87 to 172 C
fwhm_svd bootstrap 200 122 123.7236 166.5035 0.000 True 0 282 13.1 to 227 C
fwhm_peak binomial 200 122 92.7563 153.3028 0.000 True 0 305 9.96 to 253 C
fwhm_peak dkw 200 122 92.7563 153.3028 0.000 True 0 200 51.2 to 181 C
fwhm_peak bootstrap 200 122 92.7563 153.3028 0.000 True 0 304 9.96 to 253 C
Combinations: 18 ; bands separate in 17 ; of these with mutant at smaller sizes: 17
Spread (5th to 95th percentile, um), reading A, svd:
mutant: 25.6 to 247.1; cells at one bar width or less: 0 of 200
control: 90.5 to 256.8; cells at one bar width or less: 0 of 122
By retina (reading A):
fwhm_svd fwhm_peak bar_um
median size median size median size
group retina
control 20080624_R1 162.106 37 151.074 37 16.6 37
20080628_R4 140.100 15 138.748 15 16.6 15
20080628_R5 143.379 43 151.525 43 16.6 43
20080628_R6 151.228 13 148.539 13 16.6 13
20080628_R7 165.750 14 151.890 14 16.6 14
mutant 20080516_R1 118.219 7 115.749 7 8.3 7
20080516_R2 100.431 34 80.614 34 8.3 34
20080606_R1 115.284 4 58.826 4 8.3 4
20080606_R2 62.706 6 28.035 6 8.3 6
20080606_R3 256.558 1 10.596 1 8.3 1
20080624_R2 31.397 26 66.750 26 16.6 26
20080624_R3 123.712 38 95.469 38 16.6 38
20080628_R2 149.767 40 134.806 40 16.6 40
20080628_R3 122.305 32 91.105 32 16.6 32
20080702_R4 168.418 12 136.375 12 16.6 12
Vertical-bar recordings under reading B, 20080702: {'20080702_R1': 1, '20080702_R4': 1}
Reading B, 20080702 frames as deposited:
measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range
fwhm_svd binomial 200 122 123.1735 156.1976 0.0002 True 0 201 21.2 to 162
fwhm_svd dkw 200 122 123.1735 156.1976 0.0002 True 0 23 98.6 to 127
fwhm_svd bootstrap 200 122 123.1735 156.1976 0.0002 True 0 196 21.2 to 162
fwhm_peak binomial 200 122 98.4117 150.7827 0.0000 True 0 253 9.24 to 169
fwhm_peak dkw 200 122 98.4117 150.7827 0.0000 True 0 185 51.6 to 161
fwhm_peak bootstrap 200 122 98.4117 150.7827 0.0000 True 0 256 9.24 to 243
rng = np.random.default_rng(9041)
v = variants(rng, ["fwhm_svd", "fwhm_peak"])
print(v.round(4).to_string(index=False))
fig, axes = plt.subplots(1, 2, figsize=(10, 3.5))
A = cells[cells.reading == "A"]
ecdf_plot(axes[0], A, "fwhm_svd", "Centre FWHM, reading A, svd (binomial band)", "um")
ecdf_plot(axes[1], A[A.peak_ratio > 2], "fwhm_svd", "Same, cells with STA peak ratio above 2", "um")
for ax in axes: ax.set_xlim(0, 600)
plt.tight_layout(); plt.show()
print("Cells beyond 600 um (not shown):", int((A.fwhm_svd > 600).sum()), "; all units:", int(A.fwhm_svd.notna().sum()))
variant measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range
all units (main) fwhm_svd binomial 200 122 121.7268 156.1976 0.0000 True 0 213 21.1 to 165
all units (main) fwhm_svd dkw 200 122 121.7268 156.1976 0.0000 True 0 71 87 to 130
all units (main) fwhm_svd bootstrap 200 122 121.7268 156.1976 0.0000 True 0 211 21.1 to 165
all units (main) fwhm_peak binomial 200 122 97.2946 150.7827 0.0000 True 0 259 9.24 to 171
all units (main) fwhm_peak dkw 200 122 97.2946 150.7827 0.0000 True 0 194 52.2 to 163
all units (main) fwhm_peak bootstrap 200 122 97.2946 150.7827 0.0000 True 0 260 9.24 to 171
without duplicate units fwhm_svd binomial 189 118 119.8722 156.1976 0.0000 True 0 204 21.1 to 165
without duplicate units fwhm_svd dkw 189 118 119.8722 156.1976 0.0000 True 0 82 89.4 to 135
without duplicate units fwhm_svd bootstrap 189 118 119.8722 156.1976 0.0000 True 0 200 21.1 to 163
without duplicate units fwhm_peak binomial 189 118 95.7768 150.7827 0.0000 True 0 250 9.58 to 172
without duplicate units fwhm_peak dkw 189 118 95.7768 150.7827 0.0000 True 0 186 51.7 to 163
without duplicate units fwhm_peak bootstrap 189 118 95.7768 150.7827 0.0000 True 0 250 9.58 to 172
without 20080702_R4 fwhm_svd binomial 188 122 120.0263 156.1976 0.0000 True 0 210 21.1 to 170
without 20080702_R4 fwhm_svd dkw 188 122 120.0263 156.1976 0.0000 True 0 94 85.8 to 135
without 20080702_R4 fwhm_svd bootstrap 188 122 120.0263 156.1976 0.0000 True 0 212 21.1 to 170
without 20080702_R4 fwhm_peak binomial 188 122 95.9202 150.7827 0.0000 True 0 245 9.24 to 170
without 20080702_R4 fwhm_peak dkw 188 122 95.9202 150.7827 0.0000 True 0 185 51.6 to 162
without 20080702_R4 fwhm_peak bootstrap 188 122 95.9202 150.7827 0.0000 True 0 246 9.24 to 170
out-of-order segments moved 720 s fwhm_svd binomial 200 122 121.7268 155.8848 0.0000 True 0 208 21.1 to 163
out-of-order segments moved 720 s fwhm_svd dkw 200 122 121.7268 155.8848 0.0000 True 0 72 87 to 133
out-of-order segments moved 720 s fwhm_svd bootstrap 200 122 121.7268 155.8848 0.0000 True 0 208 21.1 to 163
out-of-order segments moved 720 s fwhm_peak binomial 200 122 97.2946 149.9259 0.0000 True 0 260 9.24 to 171
out-of-order segments moved 720 s fwhm_peak dkw 200 122 97.2946 149.9259 0.0000 True 0 194 53.4 to 163
out-of-order segments moved 720 s fwhm_peak bootstrap 200 122 97.2946 149.9259 0.0000 True 0 260 9.24 to 171
20080702 frames as deposited fwhm_svd binomial 200 122 116.4118 156.1976 0.0000 True 0 225 20.2 to 171
20080702 frames as deposited fwhm_svd dkw 200 122 116.4118 156.1976 0.0000 True 0 145 80.5 to 156
20080702 frames as deposited fwhm_svd bootstrap 200 122 116.4118 156.1976 0.0000 True 0 226 20.2 to 171
20080702 frames as deposited fwhm_peak binomial 200 122 93.6992 150.7827 0.0000 True 0 262 9.24 to 172
20080702 frames as deposited fwhm_peak dkw 200 122 93.6992 150.7827 0.0000 True 0 200 37.8 to 163
20080702 frames as deposited fwhm_peak bootstrap 200 122 93.6992 150.7827 0.0000 True 0 261 9.24 to 172
mutant Chx10-Cre only fwhm_svd binomial 87 122 114.5764 156.1976 0.0000 True 0 147 21.1 to 172
mutant Chx10-Cre only fwhm_svd dkw 87 122 114.5764 156.1976 0.0000 True 0 63 75 to 131
mutant Chx10-Cre only fwhm_svd bootstrap 87 122 114.5764 156.1976 0.0000 True 0 148 21.1 to 173
mutant Chx10-Cre only fwhm_peak binomial 87 122 91.3770 150.7827 0.0000 True 0 188 9.24 to 244
mutant Chx10-Cre only fwhm_peak dkw 87 122 91.3770 150.7827 0.0000 True 0 136 54.2 to 166
mutant Chx10-Cre only fwhm_peak bootstrap 87 122 91.3770 150.7827 0.0000 True 0 188 9.24 to 244
mutant Pax6-Cre only fwhm_svd binomial 113 122 127.4004 156.1976 0.0042 True 0 66 84.1 to 130
mutant Pax6-Cre only fwhm_svd dkw 113 122 127.4004 156.1976 0.0042 False 0 0
mutant Pax6-Cre only fwhm_svd bootstrap 113 122 127.4004 156.1976 0.0042 True 0 68 84.1 to 129
mutant Pax6-Cre only fwhm_peak binomial 113 122 100.2286 150.7827 0.0000 True 0 157 13.8 to 159
mutant Pax6-Cre only fwhm_peak dkw 113 122 100.2286 150.7827 0.0000 True 0 96 86.3 to 151
mutant Pax6-Cre only fwhm_peak bootstrap 113 122 100.2286 150.7827 0.0000 True 0 157 13.8 to 159
control Pax6-Cre het only fwhm_svd binomial 200 27 121.7268 157.1924 0.0004 True 10 141 21.1 to 272
control Pax6-Cre het only fwhm_svd dkw 200 27 121.7268 157.1924 0.0004 True 0 20 117 to 130
control Pax6-Cre het only fwhm_svd bootstrap 200 27 121.7268 157.1924 0.0004 True 10 139 21.1 to 272
control Pax6-Cre het only fwhm_peak binomial 200 27 97.2946 150.4913 0.0000 True 20 180 9.24 to 239
control Pax6-Cre het only fwhm_peak dkw 200 27 97.2946 150.4913 0.0000 True 0 103 78.4 to 149
control Pax6-Cre het only fwhm_peak bootstrap 200 27 97.2946 150.4913 0.0000 True 20 180 9.24 to 239
cells with STA peak ratio above 2 fwhm_svd binomial 103 107 145.2719 158.1369 0.1883 True 0 8 81.6 to 101
cells with STA peak ratio above 2 fwhm_svd dkw 103 107 145.2719 158.1369 0.1883 False 0 0
cells with STA peak ratio above 2 fwhm_svd bootstrap 103 107 145.2719 158.1369 0.1883 True 0 11 81.6 to 100
cells with STA peak ratio above 2 fwhm_peak binomial 103 107 129.6062 153.2891 0.0034 True 0 86 51.7 to 154
cells with STA peak ratio above 2 fwhm_peak dkw 103 107 129.6062 153.2891 0.0034 False 0 0
cells with STA peak ratio above 2 fwhm_peak bootstrap 103 107 129.6062 153.2891 0.0034 True 0 91 51.7 to 157
16.6 um bars only fwhm_svd binomial 148 122 125.1384 156.1976 0.0014 True 0 137 21.1 to 162
16.6 um bars only fwhm_svd dkw 148 122 125.1384 156.1976 0.0014 False 0 0
16.6 um bars only fwhm_svd bootstrap 148 122 125.1384 156.1976 0.0014 True 0 143 21.1 to 162
16.6 um bars only fwhm_peak binomial 148 122 101.5605 150.7827 0.0000 True 0 210 21.8 to 169
16.6 um bars only fwhm_peak dkw 148 122 101.5605 150.7827 0.0000 True 0 151 67.2 to 161
16.6 um bars only fwhm_peak bootstrap 148 122 101.5605 150.7827 0.0000 True 0 209 21.8 to 168
Cells beyond 600 um (not shown): 0 ; all units: 325
# Example b(x) and a(t) (svd, reading A): in each group the cell with the largest STA peak ratio,
# the median cell of those above 2, and the median cell of those below 1.5.
def sta_of(retina, cell):
rec = ret1.bar_recordings(by_name[retina], "A")[0]
h, _ = ret1.sta(ret1.stimulus(rec, bits), ret1.counts(rec)[:, [cell]])
return h[0], rec
A = cells[(cells.reading == "A") & cells.group.isin(GROUPS)]
picks = []
for g in GROUPS:
x = A[A.group == g].sort_values("peak_ratio")
strong, weak = x[x.peak_ratio > 2], x[x.peak_ratio < 1.5]
picks += [("largest ratio", x.iloc[-1]), ("median of ratio > 2", strong.iloc[len(strong) // 2]), ("median of ratio < 1.5", weak.iloc[len(weak) // 2])]
fig, axes = plt.subplots(2, 6, figsize=(16, 5))
rows = []
for k, (label, c) in enumerate(picks):
h, rec = sta_of(c.retina, int(c.cell))
b, a = ret1.separate(h, "svd")
colour = "tab:red" if c.group == "mutant" else "black"
axes[0, k].plot(np.arange(len(b)) * c.bar_um, b, color=colour)
axes[0, k].set_title(f"{c.group}, {label}\n{c.retina} #{int(c.cell)}, ratio {c.peak_ratio:.2f}", fontsize=8)
axes[0, k].set_xlabel("position (um)")
axes[1, k].plot((np.arange(len(a)) + 0.5) * rec["frame"] * 1000, a, color=colour)
axes[1, k].set_xlabel("time before spike (ms)")
rows.append({"group": c.group, "pick": label, "retina": c.retina, "cell": int(c.cell), "peak_ratio": round(c.peak_ratio, 2),
"spikes": int(c.spikes_sta), "fwhm_um": round(c.fwhm_svd, 1), "ttp_ms": round(c.ttp_svd_frame * 1000, 1),
"surround_20": bool(c.surround_svd_20), "b_range": f"{b.min():.3g} to {b.max():.3g}", "a_range": f"{a.min():.3g} to {a.max():.3g}"})
axes[0, 0].set_ylabel("b(x)"); axes[1, 0].set_ylabel("a(t)")
plt.tight_layout(); plt.show()
print(pd.DataFrame(rows).to_string(index=False))
print("Axes are scaled to the data; no value is outside them.")
group pick retina cell peak_ratio spikes fwhm_um ttp_ms surround_20 b_range a_range mutant largest ratio 20080628_R2 7 8.80 11671 127.4 108.4 False -0.0459 to 0.559 -0.126 to 0.525 mutant median of ratio > 2 20080628_R3 24 3.35 5610 92.2 125.0 False -0.43 to 0.0686 -0.192 to 0.406 mutant median of ratio < 1.5 20080606_R2 3 1.20 3739 62.9 191.7 True -0.149 to 0.0746 -0.241 to 0.335 control largest ratio 20080628_R6 12 9.77 42812 111.1 91.7 False -0.0274 to 0.316 -0.144 to 0.578 control median of ratio > 2 20080628_R5 9 4.39 14730 124.8 108.4 False -0.289 to 0.0302 -0.2 to 0.554 control median of ratio < 1.5 20080624_R1 7 1.19 6754 37.5 275.1 True -0.177 to 0.13 0.0725 to 0.262 Axes are scaled to the data; no value is outside them.
Result: blocked (methods_underspecified). The outcome rests on one combination. The bands separate, with the mutant centres smaller, in 17 of the 18 combinations; only under reading B with the svd separation do the DKW bands overlap (medians 134 against 156 um, KS p = 0.004). With the 20080702 frames as deposited that combination separates too and all 18 separate (cell 56), which would give not reproduced. So the outcome turns on the frame correction of cell 16 and on one borderline DKW comparison. Under reading A, svd, the medians are 122 against 156 um (KS p below 1e-4). Much of the difference comes from mutant cells with weak STAs. Among cells whose STA peak is more than twice the null's (103 mutant, 107 control under reading A) the medians are 145 and 158 um (KS p = 0.19); the binomial and bootstrap bands separate only between 82 and 101 um, and the DKW bands overlap. Over the three readings in that subset, 13 of 18 combinations separate and 1 of the 6 DKW ones (reading C, peak). With the 16.6 um bars alone 16 of 18 separate, the svd DKW bands overlapping under readings A and B. The svd DKW bands also overlap with the Pax6-Cre mutants alone (reading A). In the example STAs, the two cells with ratios below 1.5 have centres of 63 and 38 um, narrower than the four cells with clear STAs (92 to 127 um). Under shuffled labels the binomial and bootstrap bands of this measure separate in 38 and 45% of shuffles, the DKW band in none.
s3-receptive-field-surrounds¶
Some control and mutant RGCs have receptive field surrounds of opposite sign to the centre, so lateral inhibition functions in mutant circuits.
A lobe of b(x) of opposite sign to the centre on both flanks, deeper than 10% (a) or 20% (b) of the centre peak. Reproduced when, under every combination of the two depths, the two separations and the three recording readings, at least one mutant and one control cell have one. The same rule applied to the null STA (spike counts shifted by half the recording) is shown as the reference for noise.
rows = []
for rd in ret1.READINGS:
d = cells[(cells.reading == rd) & cells.group.isin(GROUPS)]
for sep in ("svd", "peak"):
for frac in (10, 20):
for g in GROUPS:
x = d[d.group == g]
strong = x[x.peak_ratio > 2]
rows.append({"recording": rd, "separation": sep, "depth_pct": frac, "group": g, "cells": len(x),
"with_surround": int(x[f"surround_{sep}_{frac}"].sum()),
"null_with_surround": int(x[f"null_surround_{sep}_{frac}"].sum()),
"ratio_above_2": len(strong), "ratio_above_2_with_surround": int(strong[f"surround_{sep}_{frac}"].sum())})
sur = pd.DataFrame(rows)
print(sur.to_string(index=False))
ok = sur.groupby(["recording", "separation", "depth_pct"]).with_surround.min()
print("\nReadings in which both groups have at least one cell with a surround:", int((ok > 0).sum()), "of", len(ok))
print("By retina (reading A, svd, 20%):")
A = cells[(cells.reading == "A") & cells.group.isin(GROUPS)]
print(A.groupby(["group", "retina"]).agg(cells=("cell", "size"), surround=("surround_svd_20", "sum"), null=("null_surround_svd_20", "sum")).to_string())
recording separation depth_pct group cells with_surround null_with_surround ratio_above_2 ratio_above_2_with_surround
A svd 10 mutant 200 165 198 103 68
A svd 10 control 122 63 119 107 48
A svd 20 mutant 200 90 197 103 7
A svd 20 control 122 16 119 107 4
A peak 10 mutant 200 186 197 103 89
A peak 10 control 122 105 121 107 90
A peak 20 mutant 200 132 194 103 35
A peak 20 control 122 35 121 107 20
B svd 10 mutant 200 161 198 115 76
B svd 10 control 122 63 119 107 48
B svd 20 mutant 200 77 198 115 9
B svd 20 control 122 16 119 107 4
B peak 10 mutant 200 184 198 115 99
B peak 10 control 122 105 121 107 90
B peak 20 mutant 200 124 194 115 39
B peak 20 control 122 35 121 107 20
C svd 10 mutant 200 165 197 98 63
C svd 10 control 122 71 120 103 52
C svd 20 mutant 200 102 196 98 8
C svd 20 control 122 21 120 103 5
C peak 10 mutant 200 186 196 98 84
C peak 10 control 122 106 120 103 87
C peak 20 mutant 200 139 194 98 37
C peak 20 control 122 36 120 103 17
Readings in which both groups have at least one cell with a surround: 12 of 12
By retina (reading A, svd, 20%):
cells surround null
group retina
control 20080624_R1 37 9 36
20080628_R4 15 3 14
20080628_R5 43 4 42
20080628_R6 13 0 13
20080628_R7 14 0 14
mutant 20080516_R1 7 1 7
20080516_R2 34 15 34
20080606_R1 4 4 4
20080606_R2 6 5 6
20080606_R3 1 1 1
20080624_R2 26 24 25
20080624_R3 38 22 38
20080628_R2 40 3 38
20080628_R3 32 15 32
20080702_R4 12 0 12
Result: reproduced by the criterion, but the test does not show surrounds. In all 12 readings at least one mutant and one control cell have a lobe of opposite sign on both flanks (reading A, svd, 20%: 90 of 200 mutant and 16 of 122 control cells). The same rule applied to null STAs (spike counts shifted by half the recording) is met by 194 to 198 of 200 mutant and 119 to 121 of 122 control cells, so noise alone meets it. Among cells with STA peak ratio above 2, at least 7 mutant and 4 control cells meet it at 20% in every reading. In the example STAs, both cells with ratios below 1.5 meet the rule at 20% and none of the four with clear STAs does. The result is no evidence for or against surrounds.
fig9e-slower-time-course¶
The time course of the light response is significantly slower in mutant retina, measured as the time to peak of the temporal integration function a(t).
Time to peak (s) of a(t), under both separations, both peak readings, the three band readings and the three recording readings. Reproduced when under every combination the bands separate with the mutant curve at longer times.
rng = np.random.default_rng(905)
tcols = [f"ttp_{s}_{p}" for s in ("svd", "peak") for p in ("frame", "parabolic")]
tt = pd.concat([judge(cells[(cells.reading == rd) & cells.group.isin(GROUPS)], tcols, rng).assign(recording=rd)
for rd in ret1.READINGS], ignore_index=True)
print(tt.round(4).to_string(index=False))
slower = tt.separate & (tt.mutant_larger_pts > 0) & (tt.mutant_smaller_pts == 0)
print("\nCombinations:", len(tt), "; separate with mutant at longer times:", int(slower.sum()),
"; separate the other way:", int((tt.separate & (tt.mutant_smaller_pts > 0)).sum()), "; overlap:", int((~tt.separate).sum()))
print("Median difference, mutant minus control (ms), range over combinations:",
f"{(tt.median_mut - tt.median_ctl).min() * 1000:.1f} to {(tt.median_mut - tt.median_ctl).max() * 1000:.1f}; KS p at most {tt.ks_p.max():.2g}")
print("Combinations that also separate the other way:")
print(tt[tt.separate & (tt.mutant_smaller_pts > 0)][["recording", "measure", "ci", "mutant_larger_pts", "mutant_smaller_pts", "sep_range"]].to_string(index=False))
for rd in ret1.READINGS:
d = cells[(cells.reading == rd) & cells.group.isin(GROUPS)]
fast = d[d.ttp_peak_frame < 0.03]
print(f" reading {rd}: cells with time to peak (peak separation, frame) below 30 ms: "
f"{fast.groupby('group').size().to_dict()}; their STA peak ratios {np.round(np.sort(fast.peak_ratio.to_numpy()), 2).tolist()}")
print("\nBy retina (reading A):")
print(by_retina(cells[cells.reading == "A"], ["ttp_svd_frame", "ttp_svd_parabolic"]).to_string())
measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range recording
ttp_svd_frame binomial 200 122 0.1250 0.1084 0.0 True 75 0 0.075 to 0.342 A
ttp_svd_frame dkw 200 122 0.1250 0.1084 0.0 True 40 0 0.0917 to 0.158 A
ttp_svd_frame bootstrap 200 122 0.1250 0.1084 0.0 True 75 0 0.075 to 0.342 A
ttp_svd_parabolic binomial 200 122 0.1328 0.1111 0.0 True 301 0 0.0813 to 0.342 A
ttp_svd_parabolic dkw 200 122 0.1328 0.1111 0.0 True 226 0 0.0974 to 0.158 A
ttp_svd_parabolic bootstrap 200 122 0.1328 0.1111 0.0 True 302 0 0.0812 to 0.342 A
ttp_peak_frame binomial 200 122 0.1250 0.1084 0.0 True 68 0 0.0917 to 0.292 A
ttp_peak_frame dkw 200 122 0.1250 0.1084 0.0 True 33 0 0.0917 to 0.142 A
ttp_peak_frame bootstrap 200 122 0.1250 0.1084 0.0 True 67 0 0.0917 to 0.292 A
ttp_peak_parabolic binomial 200 122 0.1265 0.1094 0.0 True 301 0 0.0889 to 0.292 A
ttp_peak_parabolic dkw 200 122 0.1265 0.1094 0.0 True 212 0 0.0995 to 0.152 A
ttp_peak_parabolic bootstrap 200 122 0.1265 0.1094 0.0 True 301 0 0.0893 to 0.292 A
ttp_svd_frame binomial 200 122 0.1250 0.1084 0.0 True 70 0 0.075 to 0.325 B
ttp_svd_frame dkw 200 122 0.1250 0.1084 0.0 True 37 0 0.0917 to 0.158 B
ttp_svd_frame bootstrap 200 122 0.1250 0.1084 0.0 True 70 0 0.075 to 0.325 B
ttp_svd_parabolic binomial 200 122 0.1298 0.1111 0.0 True 296 0 0.0819 to 0.321 B
ttp_svd_parabolic dkw 200 122 0.1298 0.1111 0.0 True 224 0 0.0982 to 0.155 B
ttp_svd_parabolic bootstrap 200 122 0.1298 0.1111 0.0 True 296 0 0.0819 to 0.321 B
ttp_peak_frame binomial 200 122 0.1250 0.1084 0.0 True 67 0 0.0917 to 0.292 B
ttp_peak_frame dkw 200 122 0.1250 0.1084 0.0 True 34 0 0.0917 to 0.158 B
ttp_peak_frame bootstrap 200 122 0.1250 0.1084 0.0 True 68 0 0.0917 to 0.292 B
ttp_peak_parabolic binomial 200 122 0.1261 0.1094 0.0 True 301 0 0.0854 to 0.291 B
ttp_peak_parabolic dkw 200 122 0.1261 0.1094 0.0 True 215 0 0.0993 to 0.153 B
ttp_peak_parabolic bootstrap 200 122 0.1261 0.1094 0.0 True 303 0 0.082 to 0.291 B
ttp_svd_frame binomial 200 122 0.1417 0.1084 0.0 True 72 0 0.0917 to 0.242 C
ttp_svd_frame dkw 200 122 0.1417 0.1084 0.0 True 44 0 0.0917 to 0.158 C
ttp_svd_frame bootstrap 200 122 0.1417 0.1084 0.0 True 72 0 0.0917 to 0.242 C
ttp_svd_parabolic binomial 200 122 0.1357 0.1118 0.0 True 296 0 0.0844 to 0.244 C
ttp_svd_parabolic dkw 200 122 0.1357 0.1118 0.0 True 223 0 0.0994 to 0.159 C
ttp_svd_parabolic bootstrap 200 122 0.1357 0.1118 0.0 True 297 0 0.0836 to 0.244 C
ttp_peak_frame binomial 200 122 0.1250 0.1084 0.0 True 72 0 0.0917 to 0.292 C
ttp_peak_frame dkw 200 122 0.1250 0.1084 0.0 True 38 0 0.0917 to 0.158 C
ttp_peak_frame bootstrap 200 122 0.1250 0.1084 0.0 True 73 0 0.0917 to 0.292 C
ttp_peak_parabolic binomial 200 122 0.1285 0.1095 0.0 True 303 0 0.0912 to 0.291 C
ttp_peak_parabolic dkw 200 122 0.1285 0.1095 0.0 True 218 0 0.1 to 0.158 C
ttp_peak_parabolic bootstrap 200 122 0.1285 0.1095 0.0 True 304 0 0.0906 to 0.291 C
Combinations: 36 ; separate with mutant at longer times: 36 ; separate the other way: 0 ; overlap: 0
Median difference, mutant minus control (ms), range over combinations: 16.7 to 33.3; KS p at most 6.1e-10
Combinations that also separate the other way:
Empty DataFrame
Columns: [recording, measure, ci, mutant_larger_pts, mutant_smaller_pts, sep_range]
Index: []
reading A: cells with time to peak (peak separation, frame) below 30 ms: {'mutant': 2}; their STA peak ratios [0.86, 1.05]
reading B: cells with time to peak (peak separation, frame) below 30 ms: {'mutant': 1}; their STA peak ratios [0.86]
reading C: cells with time to peak (peak separation, frame) below 30 ms: {'mutant': 2}; their STA peak ratios [0.9, 1.05]
By retina (reading A):
ttp_svd_frame ttp_svd_parabolic
median size median size
group retina
control 20080624_R1 0.108 37 0.103 37
20080628_R4 0.108 15 0.116 15
20080628_R5 0.125 43 0.122 43
20080628_R6 0.092 13 0.093 13
20080628_R7 0.108 14 0.107 14
mutant 20080516_R1 0.125 7 0.118 7
20080516_R2 0.142 34 0.143 34
20080606_R1 0.142 4 0.147 4
20080606_R2 0.167 6 0.169 6
20080606_R3 0.175 1 0.176 1
20080624_R2 0.133 26 0.135 26
20080624_R3 0.125 38 0.132 38
20080628_R2 0.108 40 0.112 40
20080628_R3 0.142 32 0.135 32
20080702_R4 0.158 12 0.164 12
# The values where the bands separate the other way (mutant earlier), with the cells behind them.
rng = np.random.default_rng(9052)
other = tt[tt.separate & (tt.mutant_smaller_pts > 0)]
print("Combinations that separate the other way:", len(other))
for _, r in other.iterrows():
d = cells[(cells.reading == r.recording) & cells.group.isin(GROUPS)]
m, c = split(d, r.measure)
pts = separating_points(m, c, r.ci, rng)
print(f"reading {r.recording}, {r.measure}, {r.ci}:")
print(pts[pts.direction == "mutant smaller"].assign(value=lambda x: (x.value * 1000).round(1)).rename(columns={"value": "value_ms"}).to_string(index=False))
Combinations that separate the other way: 0
rng = np.random.default_rng(9051)
v = variants(rng, ["ttp_svd_frame", "ttp_svd_parabolic"])
print(v.round(4).to_string(index=False))
fig, ax = plt.subplots(figsize=(5, 3.5))
A = cells[cells.reading == "A"]
ecdf_plot(ax, A, "ttp_svd_parabolic", "Time to peak of a(t), reading A, svd, parabolic", "ms", scale=1000)
plt.tight_layout(); plt.show()
print("Range shown (ms):", round(A.ttp_svd_parabolic.min() * 1000, 1), "to", round(A.ttp_svd_parabolic.max() * 1000, 1))
variant measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range
all units (main) ttp_svd_frame binomial 200 122 0.1250 0.1084 0.0 True 75 0 0.075 to 0.342
all units (main) ttp_svd_frame dkw 200 122 0.1250 0.1084 0.0 True 40 0 0.0917 to 0.158
all units (main) ttp_svd_frame bootstrap 200 122 0.1250 0.1084 0.0 True 75 0 0.075 to 0.342
all units (main) ttp_svd_parabolic binomial 200 122 0.1328 0.1111 0.0 True 301 0 0.0813 to 0.342
all units (main) ttp_svd_parabolic dkw 200 122 0.1328 0.1111 0.0 True 226 0 0.0974 to 0.158
all units (main) ttp_svd_parabolic bootstrap 200 122 0.1328 0.1111 0.0 True 302 0 0.0812 to 0.342
without duplicate units ttp_svd_frame binomial 189 118 0.1250 0.1084 0.0 True 75 0 0.075 to 0.342
without duplicate units ttp_svd_frame dkw 189 118 0.1250 0.1084 0.0 True 40 0 0.0917 to 0.158
without duplicate units ttp_svd_frame bootstrap 189 118 0.1250 0.1084 0.0 True 74 0 0.075 to 0.342
without duplicate units ttp_svd_parabolic binomial 189 118 0.1332 0.1101 0.0 True 287 0 0.0813 to 0.342
without duplicate units ttp_svd_parabolic dkw 189 118 0.1332 0.1101 0.0 True 212 0 0.0974 to 0.157
without duplicate units ttp_svd_parabolic bootstrap 189 118 0.1332 0.1101 0.0 True 287 0 0.0812 to 0.342
without 20080702_R4 ttp_svd_frame binomial 188 122 0.1250 0.1084 0.0 True 72 0 0.075 to 0.342
without 20080702_R4 ttp_svd_frame dkw 188 122 0.1250 0.1084 0.0 True 35 0 0.0917 to 0.142
without 20080702_R4 ttp_svd_frame bootstrap 188 122 0.1250 0.1084 0.0 True 72 0 0.075 to 0.342
without 20080702_R4 ttp_svd_parabolic binomial 188 122 0.1298 0.1111 0.0 True 290 0 0.0813 to 0.342
without 20080702_R4 ttp_svd_parabolic dkw 188 122 0.1298 0.1111 0.0 True 211 0 0.0982 to 0.154
without 20080702_R4 ttp_svd_parabolic bootstrap 188 122 0.1298 0.1111 0.0 True 291 0 0.0812 to 0.342
out-of-order segments moved 720 s ttp_svd_frame binomial 200 122 0.1250 0.1084 0.0 True 74 0 0.075 to 0.342
out-of-order segments moved 720 s ttp_svd_frame dkw 200 122 0.1250 0.1084 0.0 True 39 0 0.0917 to 0.158
out-of-order segments moved 720 s ttp_svd_frame bootstrap 200 122 0.1250 0.1084 0.0 True 75 0 0.075 to 0.342
out-of-order segments moved 720 s ttp_svd_parabolic binomial 200 122 0.1328 0.1111 0.0 True 301 0 0.0813 to 0.342
out-of-order segments moved 720 s ttp_svd_parabolic dkw 200 122 0.1328 0.1111 0.0 True 227 0 0.0972 to 0.158
out-of-order segments moved 720 s ttp_svd_parabolic bootstrap 200 122 0.1328 0.1111 0.0 True 302 0 0.0809 to 0.342
20080702 frames as deposited ttp_svd_frame binomial 200 122 0.1250 0.1084 0.0 True 87 0 0.075 to 0.392
20080702 frames as deposited ttp_svd_frame dkw 200 122 0.1250 0.1084 0.0 True 41 0 0.0917 to 0.158
20080702 frames as deposited ttp_svd_frame bootstrap 200 122 0.1250 0.1084 0.0 True 87 0 0.075 to 0.392
20080702 frames as deposited ttp_svd_parabolic binomial 200 122 0.1328 0.1111 0.0 True 311 0 0.0813 to 0.389
20080702 frames as deposited ttp_svd_parabolic dkw 200 122 0.1328 0.1111 0.0 True 226 0 0.0974 to 0.16
20080702 frames as deposited ttp_svd_parabolic bootstrap 200 122 0.1328 0.1111 0.0 True 312 0 0.0812 to 0.389
mutant Chx10-Cre only ttp_svd_frame binomial 87 122 0.1417 0.1084 0.0 True 52 0 0.0917 to 0.342
mutant Chx10-Cre only ttp_svd_frame dkw 87 122 0.1417 0.1084 0.0 True 27 0 0.0917 to 0.158
mutant Chx10-Cre only ttp_svd_frame bootstrap 87 122 0.1417 0.1084 0.0 True 53 0 0.0917 to 0.342
mutant Chx10-Cre only ttp_svd_parabolic binomial 87 122 0.1458 0.1111 0.0 True 190 0 0.0879 to 0.342
mutant Chx10-Cre only ttp_svd_parabolic dkw 87 122 0.1458 0.1111 0.0 True 140 0 0.0989 to 0.16
mutant Chx10-Cre only ttp_svd_parabolic bootstrap 87 122 0.1458 0.1111 0.0 True 190 0 0.0844 to 0.336
mutant Pax6-Cre only ttp_svd_frame binomial 113 122 0.1250 0.1084 0.0 True 37 0 0.075 to 0.158
mutant Pax6-Cre only ttp_svd_frame dkw 113 122 0.1250 0.1084 0.0 True 12 0 0.0917 to 0.125
mutant Pax6-Cre only ttp_svd_frame bootstrap 113 122 0.1250 0.1084 0.0 True 38 0 0.075 to 0.208
mutant Pax6-Cre only ttp_svd_parabolic binomial 113 122 0.1276 0.1111 0.0 True 216 0 0.0797 to 0.204
mutant Pax6-Cre only ttp_svd_parabolic dkw 113 122 0.1276 0.1111 0.0 True 124 0 0.0998 to 0.133
mutant Pax6-Cre only ttp_svd_parabolic bootstrap 113 122 0.1276 0.1111 0.0 True 218 0 0.0797 to 0.205
control Pax6-Cre het only ttp_svd_frame binomial 200 27 0.1250 0.0917 0.0 True 62 0 0.0917 to 0.342
control Pax6-Cre het only ttp_svd_frame dkw 200 27 0.1250 0.0917 0.0 True 28 0 0.0917 to 0.142
control Pax6-Cre het only ttp_svd_frame bootstrap 200 27 0.1250 0.0917 0.0 True 63 0 0.075 to 0.342
control Pax6-Cre het only ttp_svd_parabolic binomial 200 27 0.1328 0.0990 0.0 True 217 0 0.0902 to 0.342
control Pax6-Cre het only ttp_svd_parabolic dkw 200 27 0.1328 0.0990 0.0 True 137 0 0.0974 to 0.144
control Pax6-Cre het only ttp_svd_parabolic bootstrap 200 27 0.1328 0.0990 0.0 True 219 0 0.0819 to 0.342
cells with STA peak ratio above 2 ttp_svd_frame binomial 103 107 0.1250 0.1084 0.0 True 44 0 0.075 to 0.175
cells with STA peak ratio above 2 ttp_svd_frame dkw 103 107 0.1250 0.1084 0.0 True 11 0 0.0917 to 0.125
cells with STA peak ratio above 2 ttp_svd_frame bootstrap 103 107 0.1250 0.1084 0.0 True 44 0 0.075 to 0.175
cells with STA peak ratio above 2 ttp_svd_parabolic binomial 103 107 0.1225 0.1102 0.0 True 200 0 0.0804 to 0.169
cells with STA peak ratio above 2 ttp_svd_parabolic dkw 103 107 0.1225 0.1102 0.0 True 85 0 0.0989 to 0.128
cells with STA peak ratio above 2 ttp_svd_parabolic bootstrap 103 107 0.1225 0.1102 0.0 True 199 0 0.0804 to 0.169
16.6 um bars only ttp_svd_frame binomial 148 122 0.1250 0.1084 0.0 True 57 0 0.075 to 0.342
16.6 um bars only ttp_svd_frame dkw 148 122 0.1250 0.1084 0.0 True 29 0 0.0917 to 0.158
16.6 um bars only ttp_svd_frame bootstrap 148 122 0.1250 0.1084 0.0 True 57 0 0.075 to 0.342
16.6 um bars only ttp_svd_parabolic binomial 148 122 0.1289 0.1111 0.0 True 250 0 0.0816 to 0.342
16.6 um bars only ttp_svd_parabolic dkw 148 122 0.1289 0.1111 0.0 True 176 0 0.099 to 0.154
16.6 um bars only ttp_svd_parabolic bootstrap 148 122 0.1289 0.1111 0.0 True 250 0 0.0813 to 0.342
Range shown (ms): 38.0 to 491.8
Result: reproduced. In all 36 combinations the 95% bands separate with the mutant curve at longer times, and in none do they separate the other way. The mutant medians exceed the control medians by 16.7 to 33.3 ms (reading A, svd, frame: 125 against 108 ms; KS p at most 6e-10). Two mutant cells peak below 30 ms under reading A (STA peak ratios 0.86 and 1.05, no measurable receptive field), too few to separate the bands. The separation holds under the DKW band, which never separated under shuffled labels, and in every variant under reading A, including each Cre line alone and the Pax6-Cre heterozygous controls alone. Over all three readings (cell 56) all 36 combinations separate with the mutant curve later among cells with clear STAs, with 16.6 um bars alone and with the 20080702 frames as deposited. With the frames as deposited, 8 of them (binomial and bootstrap, peak separation, readings A and C) also hold 1 or 2 values where the bands separate the other way; the DKW bands never do.
fig9f-lower-firing-rate¶
Mutant RGCs fire at much lower rates than control RGCs in response to flickering gratings.
Spike count over the duration of the flicker stimulus, per cell. Reproduced when the mutant curve lies at lower rates and the bands separate under every combination of the band readings and the recording readings; under reading B, the spike count and duration of the pooled recordings.
rng = np.random.default_rng(906)
fr = pd.concat([judge(cells[(cells.reading == rd) & cells.group.isin(GROUPS)], ["rate_hz"], rng).assign(recording=rd)
for rd in ret1.READINGS], ignore_index=True)
fr["median_ratio_mut_ctl"] = fr.median_mut / fr.median_ctl
print(fr.round(4).to_string(index=False))
lower = fr.separate & (fr.mutant_smaller_pts > 0) & (fr.mutant_larger_pts == 0)
print("\nCombinations:", len(fr), "; separate with mutant at lower rates:", int(lower.sum()))
print("\nBy retina (reading A):")
print(by_retina(cells[cells.reading == "A"], ["rate_hz"]).to_string())
measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range recording median_ratio_mut_ctl
rate_hz binomial 200 122 3.8185 9.0175 0.0 True 0 305 0.716 to 30.7 A 0.4235
rate_hz dkw 200 122 3.8185 9.0175 0.0 True 0 171 2.57 to 14.8 A 0.4235
rate_hz bootstrap 200 122 3.8185 9.0175 0.0 True 0 306 0.693 to 30.7 A 0.4235
rate_hz binomial 200 122 4.0306 9.0175 0.0 True 0 302 0.768 to 30.7 B 0.4470
rate_hz dkw 200 122 4.0306 9.0175 0.0 True 0 148 3.37 to 14.1 B 0.4470
rate_hz bootstrap 200 122 4.0306 9.0175 0.0 True 0 303 0.693 to 30.7 B 0.4470
rate_hz binomial 200 122 3.4295 8.9467 0.0 True 0 300 0.679 to 28.6 C 0.3833
rate_hz dkw 200 122 3.4295 8.9467 0.0 True 0 207 1.88 to 16.6 C 0.3833
rate_hz bootstrap 200 122 3.4295 8.9467 0.0 True 0 300 0.679 to 28.6 C 0.3833
Combinations: 9 ; separate with mutant at lower rates: 9
By retina (reading A):
rate_hz
median size
group retina
control 20080624_R1 11.899 37
20080628_R4 3.784 15
20080628_R5 7.579 43
20080628_R6 23.573 13
20080628_R7 4.962 14
mutant 20080516_R1 15.854 7
20080516_R2 4.881 34
20080606_R1 2.052 4
20080606_R2 2.859 6
20080606_R3 5.785 1
20080624_R2 1.946 26
20080624_R3 2.804 38
20080628_R2 10.548 40
20080628_R3 2.479 32
20080702_R4 6.372 12
rng = np.random.default_rng(9061)
v = variants(rng, ["rate_hz"])
v["median_ratio_mut_ctl"] = v.median_mut / v.median_ctl
print(v.round(4).to_string(index=False))
fig, ax = plt.subplots(figsize=(5, 3.5))
A = cells[cells.reading == "A"]
ecdf_plot(ax, A, "rate_hz", "Firing rate during flickering bars, reading A", "Hz")
ax.set_xscale("log"); plt.tight_layout(); plt.show()
print("Range (Hz):", round(A.rate_hz.min(), 3), "to", round(A.rate_hz.max(), 1), "; cells at 0 Hz (not on the log axis):", int((A.rate_hz == 0).sum()))
variant measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range median_ratio_mut_ctl
all units (main) rate_hz binomial 200 122 3.8185 9.0175 0.0000 True 0 305 0.716 to 30.7 0.4235
all units (main) rate_hz dkw 200 122 3.8185 9.0175 0.0000 True 0 171 2.57 to 14.8 0.4235
all units (main) rate_hz bootstrap 200 122 3.8185 9.0175 0.0000 True 0 306 0.693 to 30.7 0.4235
without duplicate units rate_hz binomial 189 118 3.7115 9.1461 0.0000 True 0 291 0.716 to 30.7 0.4058
without duplicate units rate_hz dkw 189 118 3.7115 9.1461 0.0000 True 0 170 2.11 to 15 0.4058
without duplicate units rate_hz bootstrap 189 118 3.7115 9.1461 0.0000 True 0 292 0.693 to 30.7 0.4058
without 20080702_R4 rate_hz binomial 188 122 3.6676 9.0175 0.0000 True 0 294 0.768 to 30.7 0.4067
without 20080702_R4 rate_hz dkw 188 122 3.6676 9.0175 0.0000 True 0 163 2.57 to 14.1 0.4067
without 20080702_R4 rate_hz bootstrap 188 122 3.6676 9.0175 0.0000 True 0 295 0.716 to 30.7 0.4067
out-of-order segments moved 720 s rate_hz binomial 200 122 3.8185 9.0175 0.0000 True 0 305 0.716 to 30.7 0.4235
out-of-order segments moved 720 s rate_hz dkw 200 122 3.8185 9.0175 0.0000 True 0 171 2.57 to 14.8 0.4235
out-of-order segments moved 720 s rate_hz bootstrap 200 122 3.8185 9.0175 0.0000 True 0 306 0.693 to 30.7 0.4235
20080702 frames as deposited rate_hz binomial 200 122 3.8185 9.0175 0.0000 True 0 305 0.716 to 30.7 0.4235
20080702 frames as deposited rate_hz dkw 200 122 3.8185 9.0175 0.0000 True 0 171 2.57 to 14.8 0.4235
20080702 frames as deposited rate_hz bootstrap 200 122 3.8185 9.0175 0.0000 True 0 305 0.694 to 30.7 0.4235
mutant Chx10-Cre only rate_hz binomial 87 122 2.5529 9.0175 0.0000 True 0 189 1.1 to 30.7 0.2831
mutant Chx10-Cre only rate_hz dkw 87 122 2.5529 9.0175 0.0000 True 0 131 1.96 to 15 0.2831
mutant Chx10-Cre only rate_hz bootstrap 87 122 2.5529 9.0175 0.0000 True 0 190 0.984 to 30.7 0.2831
mutant Pax6-Cre only rate_hz binomial 113 122 6.1428 9.0175 0.0287 True 0 80 0.795 to 30.7 0.6812
mutant Pax6-Cre only rate_hz dkw 113 122 6.1428 9.0175 0.0287 False 0 0 0.6812
mutant Pax6-Cre only rate_hz bootstrap 113 122 6.1428 9.0175 0.0287 True 0 80 0.768 to 30.7 0.6812
control Pax6-Cre het only rate_hz binomial 200 27 3.8185 9.3650 0.0007 True 0 219 0.44 to 28.6 0.4077
control Pax6-Cre het only rate_hz dkw 200 27 3.8185 9.3650 0.0007 True 0 15 4.08 to 17.2 0.4077
control Pax6-Cre het only rate_hz bootstrap 200 27 3.8185 9.3650 0.0007 True 0 218 0.44 to 28.6 0.4077
cells with STA peak ratio above 2 rate_hz binomial 103 107 6.0933 9.1971 0.0156 True 0 67 4.05 to 30.7 0.6625
cells with STA peak ratio above 2 rate_hz dkw 103 107 6.0933 9.1971 0.0156 False 0 0 0.6625
cells with STA peak ratio above 2 rate_hz bootstrap 103 107 6.0933 9.1971 0.0156 True 0 65 4.03 to 30.7 0.6625
16.6 um bars only rate_hz binomial 148 122 3.4363 9.0175 0.0000 True 0 255 0.768 to 30.7 0.3811
16.6 um bars only rate_hz dkw 148 122 3.4363 9.0175 0.0000 True 0 146 2.27 to 14.6 0.3811
16.6 um bars only rate_hz bootstrap 148 122 3.4363 9.0175 0.0000 True 0 256 0.716 to 30.7 0.3811
Range (Hz): 0.356 to 38.9 ; cells at 0 Hz (not on the log axis): 0
Result: reproduced. In all 9 combinations the bands separate with the mutant curve at lower rates, under the DKW band too. Under reading A the mutant median is 3.82 Hz against 9.02 Hz for controls (ratio 0.42; 0.38 to 0.45 over the readings). By retina the mutant medians range from 1.9 to 15.9 Hz and the control medians from 3.8 to 23.6 Hz. Every variant gives a lower mutant median. With the Pax6-Cre mutants alone (ratio 0.68), and in the cells with clear STAs (0.66), the DKW bands overlap while the binomial and bootstrap bands still separate; those two bands separate in 38 and 39% of label shuffles for this measure. With the Pax6-Cre heterozygous controls alone (ratio 0.41) the DKW bands separate. Over the three readings (cell 56), the cells with clear STAs give 6 of 9 combinations separating and no DKW one, which the criterion would call blocked. The outcome holds on all units, which is how the claims file reads the groups, and depends on that reading. With the frames as deposited and with 16.6 um bars alone all 9 separate.
fig9g-threshold-unaltered¶
In a Linear-Nonlinear model fitted to the flicker responses, the response threshold of mutant RGCs is unaltered.
Theta (in units of the generator's standard deviation), under both fits, both forms, the three band readings and the three recording readings. A claim of absence: reproduced when the bands overlap under every combination.
rng = np.random.default_rng(907)
lcols = [f"theta_{f}_{m}" for f in ("frame", "binned") for m in ("printed", "continuous")]
th = pd.concat([judge(cells[(cells.reading == rd) & cells.group.isin(GROUPS)], lcols, rng).assign(recording=rd)
for rd in ret1.READINGS], ignore_index=True)
print(th.round(4).to_string(index=False))
print("\nCombinations:", len(th), "; bands separate:", int(th.separate.sum()),
"; with mutant at higher thresholds:", int((th.separate & (th.mutant_larger_pts > 0) & (th.mutant_smaller_pts == 0)).sum()),
"; overlap:", int((~th.separate).sum()))
A = cells[(cells.reading == "A") & cells.group.isin(GROUPS)]
print("LN fits with no value (no spikes):", int(A.theta_frame_printed.isna().sum()), "of", len(A))
print("\nBy retina (reading A):")
print(by_retina(cells[cells.reading == "A"], ["theta_frame_continuous", "theta_binned_continuous"]).to_string())
measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range recording
theta_frame_printed binomial 200 122 1.6851 0.0072 0.0000 True 269 0 -2.26 to 2.24 A
theta_frame_printed dkw 200 122 1.6851 0.0072 0.0000 True 108 0 0.0042 to 1.82 A
theta_frame_printed bootstrap 200 122 1.6851 0.0072 0.0000 True 271 0 -2.27 to 2.25 A
theta_frame_continuous binomial 200 122 1.1227 0.4360 0.0000 True 264 0 -0.844 to 1.59 A
theta_frame_continuous dkw 200 122 1.1227 0.4360 0.0000 True 151 0 0.0434 to 1.39 A
theta_frame_continuous bootstrap 200 122 1.1227 0.4360 0.0000 True 264 0 -0.893 to 1.59 A
theta_binned_printed binomial 200 122 1.8253 -0.0226 0.0000 True 247 0 -1.73 to 1.93 A
theta_binned_printed dkw 200 122 1.8253 -0.0226 0.0000 True 130 0 -0.0311 to 1.85 A
theta_binned_printed bootstrap 200 122 1.8253 -0.0226 0.0000 True 245 0 -1.73 to 1.93 A
theta_binned_continuous binomial 200 122 1.0044 0.4730 0.0000 True 296 0 -1.04 to 1.88 A
theta_binned_continuous dkw 200 122 1.0044 0.4730 0.0000 True 153 0 -0.0278 to 1.22 A
theta_binned_continuous bootstrap 200 122 1.0044 0.4730 0.0000 True 297 0 -1.04 to 1.88 A
theta_frame_printed binomial 200 122 1.4066 0.0072 0.0002 True 201 0 -2.26 to 2.18 B
theta_frame_printed dkw 200 122 1.4066 0.0072 0.0002 True 33 0 0.00959 to 1.33 B
theta_frame_printed bootstrap 200 122 1.4066 0.0072 0.0002 True 198 0 -2.27 to 2.18 B
theta_frame_continuous binomial 200 122 0.9320 0.4360 0.0000 True 216 0 -0.844 to 1.49 B
theta_frame_continuous dkw 200 122 0.9320 0.4360 0.0000 True 71 0 0.282 to 0.767 B
theta_frame_continuous bootstrap 200 122 0.9320 0.4360 0.0000 True 219 0 -0.893 to 1.5 B
theta_binned_printed binomial 200 122 1.2974 -0.0226 0.0001 True 223 0 -1.73 to 1.93 B
theta_binned_printed dkw 200 122 1.2974 -0.0226 0.0001 True 22 0 -0.013 to 1.29 B
theta_binned_printed bootstrap 200 122 1.2974 -0.0226 0.0001 True 217 0 -1.73 to 1.93 B
theta_binned_continuous binomial 200 122 0.8068 0.4730 0.0000 True 247 0 -1.04 to 1.87 B
theta_binned_continuous dkw 200 122 0.8068 0.4730 0.0000 True 65 0 0.206 to 0.778 B
theta_binned_continuous bootstrap 200 122 0.8068 0.4730 0.0000 True 246 0 -1.04 to 1.87 B
theta_frame_printed binomial 200 122 1.6958 0.0074 0.0000 True 263 0 -2.27 to 2.24 C
theta_frame_printed dkw 200 122 1.6958 0.0074 0.0000 True 133 0 0.0042 to 2.14 C
theta_frame_printed bootstrap 200 122 1.6958 0.0074 0.0000 True 263 0 -2.27 to 2.24 C
theta_frame_continuous binomial 200 122 1.1852 0.3828 0.0000 True 262 0 -0.818 to 1.66 C
theta_frame_continuous dkw 200 122 1.1852 0.3828 0.0000 True 196 0 -0.208 to 1.43 C
theta_frame_continuous bootstrap 200 122 1.1852 0.3828 0.0000 True 266 0 -0.844 to 1.66 C
theta_binned_printed binomial 200 122 1.8190 -0.0176 0.0000 True 220 0 -0.0303 to 1.9 C
theta_binned_printed dkw 200 122 1.8190 -0.0176 0.0000 True 104 0 -0.0165 to 1.84 C
theta_binned_printed bootstrap 200 122 1.8190 -0.0176 0.0000 True 233 0 -0.0322 to 1.9 C
theta_binned_continuous binomial 200 122 1.0153 0.3546 0.0000 True 300 0 -1.05 to 1.87 C
theta_binned_continuous dkw 200 122 1.0153 0.3546 0.0000 True 173 0 -0.275 to 1.24 C
theta_binned_continuous bootstrap 200 122 1.0153 0.3546 0.0000 True 303 0 -1.05 to 1.87 C
Combinations: 36 ; bands separate: 36 ; with mutant at higher thresholds: 36 ; overlap: 0
LN fits with no value (no spikes): 0 of 322
By retina (reading A):
theta_frame_continuous theta_binned_continuous
median size median size
group retina
control 20080624_R1 0.283 37 0.206 37
20080628_R4 1.157 15 1.019 15
20080628_R5 0.544 43 0.488 43
20080628_R6 -0.537 13 -0.548 13
20080628_R7 0.862 14 0.807 14
mutant 20080516_R1 0.221 7 0.221 7
20080516_R2 1.110 34 0.998 34
20080606_R1 1.270 4 1.247 4
20080606_R2 1.416 6 1.244 6
20080606_R3 0.613 1 0.616 1
20080624_R2 1.430 26 1.253 26
20080624_R3 1.213 38 1.237 38
20080628_R2 0.417 40 0.466 40
20080628_R3 1.284 32 1.262 32
20080702_R4 0.866 12 0.800 12
# LN fits whose theta is the first or last value of its search grid, by reading, group, fit and form,
# with those at the top (last value) and at the bottom (first value) counted apart.
rows = []
for rd in ret1.READINGS:
d = cells[(cells.reading == rd) & cells.group.isin(GROUPS)]
for f in ("frame", "binned"):
for m in ("printed", "continuous"):
for g in GROUPS:
x = d[d.group == g]
th = x[f"theta_{f}_{m}"]
rows.append({"recording": rd, "fit": f, "form": m, "group": g, "fits": int(th.notna().sum()),
"at_grid_edge": int(x[f"theta_edge_{f}_{m}"].sum()), "at_top": int(x[f"theta_edge_top_{f}_{m}"].sum()),
"at_bottom": int(x[f"theta_edge_{f}_{m}"].sum() - x[f"theta_edge_top_{f}_{m}"].sum()),
"median_theta_at_top": round(float(th[x[f"theta_edge_top_{f}_{m}"].astype(bool)].median()), 2),
"median_theta": round(float(th.median()), 2),
"max_theta": round(float(th.max()), 2)})
edges = pd.DataFrame(rows)
print(edges.to_string(index=False))
print("\nWithout the fits at a grid edge (reading A):")
A = cells[(cells.reading == "A") & cells.group.isin(GROUPS)]
rng = np.random.default_rng(9072)
print(pd.concat([judge(A[~A[f"theta_edge_{c[6:]}"]], [c], rng) for c in lcols], ignore_index=True).round(4).to_string(index=False))
recording fit form group fits at_grid_edge at_top at_bottom median_theta_at_top median_theta max_theta
A frame printed mutant 200 21 20 1 2.64 1.69 2.79
A frame printed control 122 17 7 10 2.53 0.01 2.79
A frame continuous mutant 200 1 1 0 2.26 1.12 2.26
A frame continuous control 122 1 1 0 2.31 0.44 2.31
A binned printed mutant 200 107 107 0 1.86 1.83 1.95
A binned printed control 122 39 33 6 1.86 -0.02 1.93
A binned continuous mutant 200 38 38 0 1.85 1.00 1.90
A binned continuous control 122 7 6 1 1.83 0.47 1.87
B frame printed mutant 200 18 17 1 2.62 1.41 2.79
B frame printed control 122 17 7 10 2.53 0.01 2.79
B frame continuous mutant 200 1 1 0 2.26 0.93 2.26
B frame continuous control 122 1 1 0 2.31 0.44 2.31
B binned printed mutant 200 89 89 0 1.86 1.30 1.95
B binned printed control 122 39 33 6 1.86 -0.02 1.93
B binned continuous mutant 200 31 31 0 1.84 0.81 1.90
B binned continuous control 122 7 6 1 1.83 0.47 1.87
C frame printed mutant 200 29 28 1 2.62 1.70 2.97
C frame printed control 122 18 9 9 2.53 0.01 2.79
C frame continuous mutant 200 4 4 0 2.24 1.19 2.33
C frame continuous control 122 2 2 0 2.27 0.38 2.31
C binned printed mutant 200 111 111 0 1.86 1.82 1.91
C binned printed control 122 34 32 2 1.85 -0.02 1.90
C binned continuous mutant 200 43 43 0 1.84 1.02 1.88
C binned continuous control 122 8 7 1 1.83 0.35 1.87
Without the fits at a grid edge (reading A):
measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range
theta_frame_printed binomial 179 105 1.5772 0.0076 0.0000 True 227 0 -0.0105 to 2.28
theta_frame_printed dkw 179 105 1.5772 0.0076 0.0000 True 57 0 0.00959 to 1.69
theta_frame_printed bootstrap 179 105 1.5772 0.0076 0.0000 True 227 0 -0.0105 to 2.28
theta_frame_continuous binomial 199 121 1.1197 0.4291 0.0000 True 266 0 -0.844 to 1.6
theta_frame_continuous dkw 199 121 1.1197 0.4291 0.0000 True 155 0 0.0377 to 1.39
theta_frame_continuous bootstrap 199 121 1.1197 0.4291 0.0000 True 266 0 -0.893 to 1.6
theta_binned_printed binomial 93 83 -0.0274 -0.0308 0.2107 True 1 0 1.29 to 1.29
theta_binned_printed dkw 93 83 -0.0274 -0.0308 0.2107 False 0 0
theta_binned_printed bootstrap 93 83 -0.0274 -0.0308 0.2107 False 0 0
theta_binned_continuous binomial 162 115 0.8068 0.3565 0.0000 True 199 0 -0.845 to 1.21
theta_binned_continuous dkw 162 115 0.8068 0.3565 0.0000 True 54 0 0.206 to 0.798
theta_binned_continuous bootstrap 162 115 0.8068 0.3565 0.0000 True 196 0 -0.848 to 1.21
rng = np.random.default_rng(9071)
v = variants(rng, ["theta_frame_continuous", "theta_binned_printed"])
print(v.round(4).to_string(index=False))
fig, axes = plt.subplots(1, 2, figsize=(10, 3.5))
A = cells[cells.reading == "A"]
ecdf_plot(axes[0], A, "theta_frame_continuous", "Threshold, frame fit, continuous form", "theta (SD of y)")
ecdf_plot(axes[1], A, "theta_binned_printed", "Threshold, binned fit, printed form", "theta (SD of y)")
plt.tight_layout(); plt.show()
print("Ranges:", A.theta_frame_continuous.agg(["min", "max"]).round(2).tolist(), A.theta_binned_printed.agg(["min", "max"]).round(2).tolist())
variant measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range
all units (main) theta_frame_continuous binomial 200 122 1.1227 0.4360 0.0000 True 264 0 -0.844 to 1.59
all units (main) theta_frame_continuous dkw 200 122 1.1227 0.4360 0.0000 True 151 0 0.0434 to 1.39
all units (main) theta_frame_continuous bootstrap 200 122 1.1227 0.4360 0.0000 True 265 0 -0.893 to 1.59
all units (main) theta_binned_printed binomial 200 122 1.8253 -0.0226 0.0000 True 247 0 -1.73 to 1.93
all units (main) theta_binned_printed dkw 200 122 1.8253 -0.0226 0.0000 True 130 0 -0.0311 to 1.85
all units (main) theta_binned_printed bootstrap 200 122 1.8253 -0.0226 0.0000 True 250 0 -1.73 to 1.93
without duplicate units theta_frame_continuous binomial 189 118 1.1257 0.4046 0.0000 True 256 0 -0.844 to 1.66
without duplicate units theta_frame_continuous dkw 189 118 1.1257 0.4046 0.0000 True 142 0 0.0377 to 1.39
without duplicate units theta_frame_continuous bootstrap 189 118 1.1257 0.4046 0.0000 True 259 0 -0.893 to 1.68
without duplicate units theta_binned_printed binomial 189 118 1.8233 -0.0226 0.0000 True 225 0 -1.73 to 1.93
without duplicate units theta_binned_printed dkw 189 118 1.8233 -0.0226 0.0000 True 121 0 -0.0308 to 1.84
without duplicate units theta_binned_printed bootstrap 189 118 1.8233 -0.0226 0.0000 True 224 0 -1.73 to 1.93
without 20080702_R4 theta_frame_continuous binomial 188 122 1.1291 0.4360 0.0000 True 254 0 -0.844 to 1.59
without 20080702_R4 theta_frame_continuous dkw 188 122 1.1291 0.4360 0.0000 True 148 0 0.0377 to 1.26
without 20080702_R4 theta_frame_continuous bootstrap 188 122 1.1291 0.4360 0.0000 True 254 0 -0.844 to 1.59
without 20080702_R4 theta_binned_printed binomial 188 122 1.8308 -0.0226 0.0000 True 239 0 -1.73 to 1.93
without 20080702_R4 theta_binned_printed dkw 188 122 1.8308 -0.0226 0.0000 True 103 0 -0.0234 to 1.85
without 20080702_R4 theta_binned_printed bootstrap 188 122 1.8308 -0.0226 0.0000 True 235 0 -1.73 to 1.93
out-of-order segments moved 720 s theta_frame_continuous binomial 200 122 1.1227 0.4360 0.0000 True 268 0 -0.844 to 1.6
out-of-order segments moved 720 s theta_frame_continuous dkw 200 122 1.1227 0.4360 0.0000 True 153 0 0.0209 to 1.39
out-of-order segments moved 720 s theta_frame_continuous bootstrap 200 122 1.1227 0.4360 0.0000 True 270 0 -0.893 to 1.63
out-of-order segments moved 720 s theta_binned_printed binomial 200 122 1.8266 -0.0230 0.0000 True 249 0 -1.73 to 1.93
out-of-order segments moved 720 s theta_binned_printed dkw 200 122 1.8266 -0.0230 0.0000 True 128 0 -0.032 to 1.85
out-of-order segments moved 720 s theta_binned_printed bootstrap 200 122 1.8266 -0.0230 0.0000 True 249 0 -1.73 to 1.93
20080702 frames as deposited theta_frame_continuous binomial 200 122 1.1227 0.4360 0.0000 True 264 0 -0.844 to 1.59
20080702 frames as deposited theta_frame_continuous dkw 200 122 1.1227 0.4360 0.0000 True 153 0 0.0434 to 1.39
20080702 frames as deposited theta_frame_continuous bootstrap 200 122 1.1227 0.4360 0.0000 True 266 0 -0.893 to 1.6
20080702 frames as deposited theta_binned_printed binomial 200 122 1.8127 -0.0226 0.0000 True 247 0 -1.73 to 1.93
20080702 frames as deposited theta_binned_printed dkw 200 122 1.8127 -0.0226 0.0000 True 134 0 -0.0311 to 1.85
20080702 frames as deposited theta_binned_printed bootstrap 200 122 1.8127 -0.0226 0.0000 True 246 0 -1.73 to 1.93
mutant Chx10-Cre only theta_frame_continuous binomial 87 122 1.3005 0.4360 0.0000 True 173 0 -1.03 to 1.55
mutant Chx10-Cre only theta_frame_continuous dkw 87 122 1.3005 0.4360 0.0000 True 121 0 0.0377 to 1.41
mutant Chx10-Cre only theta_frame_continuous bootstrap 87 122 1.3005 0.4360 0.0000 True 170 0 -1.03 to 1.52
mutant Chx10-Cre only theta_binned_printed binomial 87 122 1.8573 -0.0226 0.0000 True 195 0 -1.73 to 1.93
mutant Chx10-Cre only theta_binned_printed dkw 87 122 1.8573 -0.0226 0.0000 True 128 0 -0.0346 to 1.86
mutant Chx10-Cre only theta_binned_printed bootstrap 87 122 1.8573 -0.0226 0.0000 True 196 0 -1.73 to 1.93
mutant Pax6-Cre only theta_frame_continuous binomial 113 122 0.9215 0.4360 0.0040 True 121 0 -0.743 to 1.55
mutant Pax6-Cre only theta_frame_continuous dkw 113 122 0.9215 0.4360 0.0040 False 0 0
mutant Pax6-Cre only theta_frame_continuous bootstrap 113 122 0.9215 0.4360 0.0040 True 117 0 -0.743 to 1.56
mutant Pax6-Cre only theta_binned_printed binomial 113 122 1.2908 -0.0226 0.0250 True 16 0 -1.73 to 1.83
mutant Pax6-Cre only theta_binned_printed dkw 113 122 1.2908 -0.0226 0.0250 False 0 0
mutant Pax6-Cre only theta_binned_printed bootstrap 113 122 1.2908 -0.0226 0.0250 True 17 0 -1.73 to 1.83
control Pax6-Cre het only theta_frame_continuous binomial 200 27 1.1227 0.3306 0.0021 True 198 0 -0.686 to 2.03
control Pax6-Cre het only theta_frame_continuous dkw 200 27 1.1227 0.3306 0.0021 True 9 0 -0.208 to 0.849
control Pax6-Cre het only theta_frame_continuous bootstrap 200 27 1.1227 0.3306 0.0021 True 192 0 -0.686 to 2.03
control Pax6-Cre het only theta_binned_printed binomial 200 27 1.8253 -0.0171 0.0023 True 120 0 -0.0135 to 1.93
control Pax6-Cre het only theta_binned_printed dkw 200 27 1.8253 -0.0171 0.0023 True 3 0 1.03 to 1.29
control Pax6-Cre het only theta_binned_printed bootstrap 200 27 1.8253 -0.0171 0.0023 True 123 0 -0.0135 to 1.93
cells with STA peak ratio above 2 theta_frame_continuous binomial 103 107 0.8643 0.4116 0.0025 True 63 0 -0.686 to 0.851
cells with STA peak ratio above 2 theta_frame_continuous dkw 103 107 0.8643 0.4116 0.0025 False 0 0
cells with STA peak ratio above 2 theta_frame_continuous bootstrap 103 107 0.8643 0.4116 0.0025 True 65 0 -0.686 to 0.849
cells with STA peak ratio above 2 theta_binned_printed binomial 103 107 1.2928 -0.0271 0.0070 True 60 0 -1.73 to 1.9
cells with STA peak ratio above 2 theta_binned_printed dkw 103 107 1.2928 -0.0271 0.0070 False 0 0
cells with STA peak ratio above 2 theta_binned_printed bootstrap 103 107 1.2928 -0.0271 0.0070 True 76 0 -1.73 to 1.9
16.6 um bars only theta_frame_continuous binomial 148 122 1.1227 0.4360 0.0000 True 220 0 -0.816 to 1.58
16.6 um bars only theta_frame_continuous dkw 148 122 1.1227 0.4360 0.0000 True 120 0 0.0434 to 1.2
16.6 um bars only theta_frame_continuous bootstrap 148 122 1.1227 0.4360 0.0000 True 221 0 -0.844 to 1.58
16.6 um bars only theta_binned_printed binomial 148 122 1.8128 -0.0226 0.0000 True 171 0 -1.73 to 1.86
16.6 um bars only theta_binned_printed dkw 148 122 1.8128 -0.0226 0.0000 True 105 0 -0.0311 to 1.84
16.6 um bars only theta_binned_printed bootstrap 148 122 1.8128 -0.0226 0.0000 True 178 0 -1.73 to 1.86
Ranges: [-1.74, 2.31] [-1.75, 1.95]
Result: not reproduced. The paper finds the threshold unaltered. Here the bands separate in all 36 combinations, with mutant thresholds higher, under the DKW band too (reading A, frame fit: median 1.12 against 0.44 SD of the generator in the continuous form, 1.69 against 0.01 in the printed form). Part of this comes from mutant cells with weak STAs, whose generator predicts little of the rate. Among cells with clear STAs the medians are 0.86 against 0.41 (frame fit, continuous form, reading A); over the three readings in that subset 24 of 36 combinations separate (23 with mutant thresholds higher, 1 with values both ways) and no DKW one does (cell 56), which the criterion would call blocked. The outcome holds on all units, which is how the claims file reads the groups, and depends on that reading. With the frames as deposited and with 16.6 um bars alone all 36 separate. The binned fit in the printed form often stops at the last value of its theta grid, the split between its two highest bins of y (reading A: all 107 of the 107 mutant edge fits, of 200, median theta 1.86; 33 of the 39 control edge fits, of 122, with 6 at the first value). Why these fits reach the top is not shown here. Without the edge fits its medians are -0.03 and -0.03 (KS p = 0.21) and its DKW and bootstrap bands overlap, but that comparison removes most of the high mutant fits by construction, so it says nothing on whether the threshold is unaltered. The frame fit in the continuous form has 1 fit per group at an edge, both at the top, and separates under every band. With the Pax6-Cre heterozygous controls alone the DKW bands still separate, narrowly.
fig9h-gain-reduced¶
In the same Linear-Nonlinear model, the gain of mutant RGCs is reduced.
G (Hz per standard deviation of the generator) from the same fits, under the same readings. Reproduced when under every combination of the band, recording, fit and form readings the mutant curve lies at lower gains and the bands separate.
rng = np.random.default_rng(908)
gcols = [f"gain_{f}_{m}" for f in ("frame", "binned") for m in ("printed", "continuous")]
gn = pd.concat([judge(cells[(cells.reading == rd) & cells.group.isin(GROUPS)], gcols, rng).assign(recording=rd)
for rd in ret1.READINGS], ignore_index=True)
gn["median_ratio_mut_ctl"] = gn.median_mut / gn.median_ctl
print(gn.round(4).to_string(index=False))
lower = gn.separate & (gn.mutant_smaller_pts > 0) & (gn.mutant_larger_pts == 0)
print("\nCombinations:", len(gn), "; separate with mutant at lower gains:", int(lower.sum()),
"; separate the other way:", int((gn.separate & (gn.mutant_larger_pts > 0)).sum()), "; overlap:", int((~gn.separate).sum()))
print("By form, combinations with mutant lower and separate:", gn.assign(lower=lower).groupby(gn.measure.str.split("_").str[-1]).lower.agg(["sum", "size"]).to_dict())
print("\nBy retina (reading A):")
print(by_retina(cells[cells.reading == "A"], ["gain_frame_printed", "gain_frame_continuous"]).to_string())
measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range recording median_ratio_mut_ctl
gain_frame_printed binomial 200 122 18.3939 23.0846 0.0001 True 0 166 14.8 to 26.3 A 0.7968
gain_frame_printed dkw 200 122 18.3939 23.0846 0.0001 True 0 46 17.3 to 22.2 A 0.7968
gain_frame_printed bootstrap 200 122 18.3939 23.0846 0.0001 True 0 164 15 to 26 A 0.7968
gain_frame_continuous binomial 200 122 30.4332 30.7532 0.7637 False 0 0 A 0.9896
gain_frame_continuous dkw 200 122 30.4332 30.7532 0.7637 False 0 0 A 0.9896
gain_frame_continuous bootstrap 200 122 30.4332 30.7532 0.7637 True 1 0 15.6 to 15.6 A 0.9896
gain_binned_printed binomial 200 122 15.6953 21.1266 0.0000 True 0 254 5.9 to 27.4 A 0.7429
gain_binned_printed dkw 200 122 15.6953 21.1266 0.0000 True 0 123 12.7 to 21.2 A 0.7429
gain_binned_printed bootstrap 200 122 15.6953 21.1266 0.0000 True 0 258 5.9 to 27.7 A 0.7429
gain_binned_continuous binomial 200 122 30.3400 29.2195 0.3818 True 1 0 41.5 to 41.5 A 1.0383
gain_binned_continuous dkw 200 122 30.3400 29.2195 0.3818 False 0 0 A 1.0383
gain_binned_continuous bootstrap 200 122 30.3400 29.2195 0.3818 True 2 0 15.9 to 41.5 A 1.0383
gain_frame_printed binomial 200 122 17.7534 23.0846 0.0000 True 0 231 7.49 to 26.3 B 0.7691
gain_frame_printed dkw 200 122 17.7534 23.0846 0.0000 True 0 91 15.4 to 22.3 B 0.7691
gain_frame_printed bootstrap 200 122 17.7534 23.0846 0.0000 True 0 228 7.49 to 27.9 B 0.7691
gain_frame_continuous binomial 200 122 28.7185 30.7532 0.3655 True 0 9 11.1 to 20.2 B 0.9338
gain_frame_continuous dkw 200 122 28.7185 30.7532 0.3655 False 0 0 B 0.9338
gain_frame_continuous bootstrap 200 122 28.7185 30.7532 0.3655 True 0 10 11.1 to 20.2 B 0.9338
gain_binned_printed binomial 200 122 14.9360 21.1266 0.0000 True 0 254 6.12 to 27.4 B 0.7070
gain_binned_printed dkw 200 122 14.9360 21.1266 0.0000 True 0 124 12.3 to 21.2 B 0.7070
gain_binned_printed bootstrap 200 122 14.9360 21.1266 0.0000 True 0 256 5.9 to 27.6 B 0.7070
gain_binned_continuous binomial 200 122 28.8554 29.2195 0.1860 True 0 19 10.2 to 18.7 B 0.9875
gain_binned_continuous dkw 200 122 28.8554 29.2195 0.1860 False 0 0 B 0.9875
gain_binned_continuous bootstrap 200 122 28.8554 29.2195 0.1860 True 0 19 10.2 to 18.7 B 0.9875
gain_frame_printed binomial 200 122 18.0157 22.4145 0.0000 True 0 193 14.7 to 27.9 C 0.8038
gain_frame_printed dkw 200 122 18.0157 22.4145 0.0000 True 0 86 16.2 to 22.3 C 0.8038
gain_frame_printed bootstrap 200 122 18.0157 22.4145 0.0000 True 0 188 14.7 to 27.9 C 0.8038
gain_frame_continuous binomial 200 122 29.0327 29.2187 0.1163 True 4 0 21.2 to 21.3 C 0.9936
gain_frame_continuous dkw 200 122 29.0327 29.2187 0.1163 False 0 0 C 0.9936
gain_frame_continuous bootstrap 200 122 29.0327 29.2187 0.1163 True 7 0 21.1 to 24.9 C 0.9936
gain_binned_printed binomial 200 122 14.0553 20.8431 0.0000 True 0 264 5.86 to 28.6 C 0.6743
gain_binned_printed dkw 200 122 14.0553 20.8431 0.0000 True 0 144 12.3 to 22 C 0.6743
gain_binned_printed bootstrap 200 122 14.0553 20.8431 0.0000 True 0 264 5.86 to 28.6 C 0.6743
gain_binned_continuous binomial 200 122 28.7897 27.7145 0.1450 False 0 0 C 1.0388
gain_binned_continuous dkw 200 122 28.7897 27.7145 0.1450 False 0 0 C 1.0388
gain_binned_continuous bootstrap 200 122 28.7897 27.7145 0.1450 False 0 0 C 1.0388
Combinations: 36 ; separate with mutant at lower gains: 22 ; separate the other way: 5 ; overlap: 9
By form, combinations with mutant lower and separate: {'sum': {'continuous': 4, 'printed': 18}, 'size': {'continuous': 18, 'printed': 18}}
By retina (reading A):
gain_frame_printed gain_frame_continuous
median size median size
group retina
control 20080624_R1 23.435 37 27.923 37
20080628_R4 24.274 15 32.286 15
20080628_R5 22.444 43 34.146 43
20080628_R6 28.927 13 28.591 13
20080628_R7 22.371 14 36.061 14
mutant 20080516_R1 25.886 7 31.695 7
20080516_R2 23.421 34 33.087 34
20080606_R1 15.872 4 28.144 4
20080606_R2 18.888 6 26.881 6
20080606_R3 17.156 1 26.424 1
20080624_R2 16.125 26 29.970 26
20080624_R3 15.600 38 28.080 38
20080628_R2 25.503 40 36.642 40
20080628_R3 14.703 32 26.354 32
20080702_R4 23.120 12 34.621 12
# The continuous-form combinations that separate, with the cells behind each separating value.
rng = np.random.default_rng(9082)
cont = gn[gn.separate & gn.measure.str.endswith("continuous")]
print("Continuous-form combinations that separate:", len(cont))
for _, r in cont.iterrows():
d = cells[(cells.reading == r.recording) & cells.group.isin(GROUPS)]
m, c = split(d, r.measure)
pts = separating_points(m, c, r.ci, rng)
print(f"reading {r.recording}, {r.measure}, {r.ci}: {len(pts)} values")
print(pts.round(2).to_string(index=False))
Continuous-form combinations that separate: 9 reading A, gain_frame_continuous, bootstrap: 1 values value mutant_at_or_below n_mut control_at_or_below n_ctl mutant_band control_band direction 15.6 1 200 6 122 0.000-0.015 0.016-0.090 mutant larger reading A, gain_binned_continuous, binomial: 1 values value mutant_at_or_below n_mut control_at_or_below n_ctl mutant_band control_band direction 41.46 165 200 113 122 0.772-0.878 0.880-0.973 mutant larger reading A, gain_binned_continuous, bootstrap: 2 values value mutant_at_or_below n_mut control_at_or_below n_ctl mutant_band control_band direction 15.85 1 200 6 122 0.000-0.015 0.016-0.090 mutant larger 41.46 165 200 113 122 0.770-0.875 0.877-0.967 mutant larger reading B, gain_frame_continuous, binomial: 9 values value mutant_at_or_below n_mut control_at_or_below n_ctl mutant_band control_band direction 11.13 4 200 0 122 0.001-0.039 0.000-0.000 mutant smaller 11.56 5 200 0 122 0.003-0.047 0.000-0.000 mutant smaller 11.66 6 200 0 122 0.006-0.054 0.000-0.000 mutant smaller 12.01 7 200 0 122 0.010-0.060 0.000-0.000 mutant smaller 12.51 8 200 0 122 0.013-0.067 0.000-0.000 mutant smaller 12.65 9 200 0 122 0.016-0.074 0.000-0.000 mutant smaller 12.70 10 200 0 122 0.020-0.080 0.000-0.000 mutant smaller 12.86 11 200 0 122 0.023-0.087 0.000-0.000 mutant smaller 20.24 37 200 10 122 0.131-0.239 0.033-0.131 mutant smaller
reading B, gain_frame_continuous, bootstrap: 9 values value mutant_at_or_below n_mut control_at_or_below n_ctl mutant_band control_band direction 11.13 4 200 0 122 0.005-0.040 0.000-0.000 mutant smaller 11.56 5 200 0 122 0.005-0.050 0.000-0.000 mutant smaller 11.66 6 200 0 122 0.010-0.055 0.000-0.000 mutant smaller 12.01 7 200 0 122 0.010-0.060 0.000-0.000 mutant smaller 12.51 8 200 0 122 0.015-0.070 0.000-0.000 mutant smaller 12.65 9 200 0 122 0.020-0.080 0.000-0.000 mutant smaller 12.70 10 200 0 122 0.020-0.085 0.000-0.000 mutant smaller 12.86 11 200 0 122 0.025-0.090 0.000-0.000 mutant smaller 13.07 11 200 1 122 0.025-0.090 0.000-0.025 mutant smaller reading B, gain_binned_continuous, binomial: 19 values value mutant_at_or_below n_mut control_at_or_below n_ctl mutant_band control_band direction 10.21 4 200 0 122 0.001-0.039 0.000-0.000 mutant smaller 10.59 5 200 0 122 0.003-0.047 0.000-0.000 mutant smaller 11.08 6 200 0 122 0.006-0.054 0.000-0.000 mutant smaller 11.44 7 200 0 122 0.010-0.060 0.000-0.000 mutant smaller 11.48 8 200 0 122 0.013-0.067 0.000-0.000 mutant smaller 12.03 9 200 0 122 0.016-0.074 0.000-0.000 mutant smaller 12.15 10 200 0 122 0.020-0.080 0.000-0.000 mutant smaller 12.40 11 200 0 122 0.023-0.087 0.000-0.000 mutant smaller 12.48 12 200 0 122 0.027-0.093 0.000-0.000 mutant smaller 12.78 13 200 0 122 0.031-0.099 0.000-0.000 mutant smaller 13.02 13 200 1 122 0.031-0.099 0.000-0.024 mutant smaller 13.53 14 200 1 122 0.035-0.105 0.000-0.024 mutant smaller 14.86 19 200 3 122 0.054-0.136 0.000-0.052 mutant smaller 15.02 20 200 3 122 0.058-0.142 0.000-0.052 mutant smaller 18.05 35 200 9 122 0.122-0.228 0.027-0.120 mutant smaller 18.12 36 200 9 122 0.127-0.233 0.027-0.120 mutant smaller 18.60 37 200 9 122 0.131-0.239 0.027-0.120 mutant smaller 18.64 37 200 10 122 0.131-0.239 0.033-0.131 mutant smaller 18.68 38 200 10 122 0.136-0.244 0.033-0.131 mutant smaller reading B, gain_binned_continuous, bootstrap: 17 values value mutant_at_or_below n_mut control_at_or_below n_ctl mutant_band control_band direction 10.21 4 200 0 122 0.005-0.040 0.000-0.000 mutant smaller 10.59 5 200 0 122 0.005-0.045 0.000-0.000 mutant smaller 11.08 6 200 0 122 0.010-0.055 0.000-0.000 mutant smaller 11.44 7 200 0 122 0.010-0.065 0.000-0.000 mutant smaller 11.48 8 200 0 122 0.015-0.070 0.000-0.000 mutant smaller 12.03 9 200 0 122 0.020-0.075 0.000-0.000 mutant smaller 12.15 10 200 0 122 0.020-0.080 0.000-0.000 mutant smaller 12.40 11 200 0 122 0.025-0.085 0.000-0.000 mutant smaller 12.48 12 200 0 122 0.025-0.090 0.000-0.000 mutant smaller 12.78 13 200 0 122 0.030-0.095 0.000-0.000 mutant smaller 13.02 13 200 1 122 0.030-0.095 0.000-0.025 mutant smaller 13.53 14 200 1 122 0.035-0.105 0.000-0.025 mutant smaller 15.02 20 200 3 122 0.060-0.140 0.000-0.057 mutant smaller 18.05 35 200 9 122 0.125-0.225 0.033-0.123 mutant smaller 18.12 36 200 9 122 0.125-0.230 0.033-0.123 mutant smaller 18.60 37 200 9 122 0.130-0.240 0.033-0.123 mutant smaller 18.68 38 200 10 122 0.135-0.245 0.041-0.131 mutant smaller reading C, gain_frame_continuous, binomial: 4 values value mutant_at_or_below n_mut control_at_or_below n_ctl mutant_band control_band direction 21.15 16 200 23 122 0.042-0.118 0.119-0.258 mutant larger 21.24 17 200 24 122 0.046-0.124 0.126-0.267 mutant larger 21.29 17 200 25 122 0.046-0.124 0.133-0.277 mutant larger 21.30 18 200 25 122 0.050-0.130 0.133-0.277 mutant larger reading C, gain_frame_continuous, bootstrap: 5 values value mutant_at_or_below n_mut control_at_or_below n_ctl mutant_band control_band direction 21.15 16 200 23 122 0.045-0.120 0.123-0.262 mutant larger 21.24 17 200 24 122 0.050-0.125 0.131-0.270 mutant larger 21.29 17 200 25 122 0.050-0.125 0.139-0.279 mutant larger 21.30 18 200 25 122 0.055-0.130 0.139-0.279 mutant larger 21.35 19 200 25 122 0.060-0.135 0.139-0.279 mutant larger
# The fits on synthetic cells of known parameters: generator y ~ N(0, 1) over 90,000 frames of
# 16.67 ms, Poisson spikes at B + G (y - theta) above theta (continuous form) or B + G y (printed),
# B = 2 Hz, G = 20 Hz per SD, theta from 0 to 1.5; 20 cells per setting.
rng = np.random.default_rng(9083)
rows = []
for true_form in ("continuous", "printed"):
for theta in (0.0, 0.5, 1.0, 1.5):
fits = {(f, m): [] for f in ("frame", "binned") for m in ("printed", "continuous")}
for _ in range(20):
y = rng.standard_normal(90000)
rate = 2.0 + np.where(y >= theta, 20.0 * (y - theta if true_form == "continuous" else y), 0.0)
r = rng.poisson(np.clip(rate, 0, None) * 0.01667) / 0.01667
for (f, m) in fits:
fits[(f, m)].append(ret1.fit_ln(y, r, f, m))
for (f, m), ps in fits.items():
rows.append({"true_form": true_form, "true_theta": theta, "fit": f, "form": m,
"theta_median": round(float(np.median([p["theta"] for p in ps])), 2), "G_median": round(float(np.median([p["G"] for p in ps])), 1),
"at_edge": sum(p["edge"] for p in ps)})
print(pd.DataFrame(rows).to_string(index=False))
true_form true_theta fit form theta_median G_median at_edge continuous 0.0 frame printed 0.01 20.0 0 continuous 0.0 frame continuous 0.00 20.0 0 continuous 0.0 binned printed -0.00 20.0 0 continuous 0.0 binned continuous -0.00 20.0 0 continuous 0.5 frame printed 0.75 13.4 0 continuous 0.5 frame continuous 0.50 20.0 0 continuous 0.5 binned printed 0.68 13.2 0 continuous 0.5 binned continuous 0.53 20.4 0 continuous 1.0 frame printed 1.34 9.4 0 continuous 1.0 frame continuous 1.00 20.2 0 continuous 1.0 binned printed 1.30 8.9 0 continuous 1.0 binned continuous 1.04 21.2 0 continuous 1.5 frame printed 1.82 6.7 0 continuous 1.5 frame continuous 1.48 19.3 0 continuous 1.5 binned printed 1.76 5.4 20 continuous 1.5 binned continuous 1.76 36.0 20 printed 0.0 frame printed -0.00 20.0 0 printed 0.0 frame continuous -0.00 20.0 0 printed 0.0 binned printed -0.00 20.0 0 printed 0.0 binned continuous -0.00 20.0 0 printed 0.5 frame printed 0.50 20.0 0 printed 0.5 frame continuous 0.21 23.2 0 printed 0.5 binned printed 0.53 19.9 0 printed 0.5 binned continuous 0.26 24.1 0 printed 1.0 frame printed 0.99 20.0 0 printed 1.0 frame continuous 0.64 30.8 0 printed 1.0 binned printed 1.04 20.0 0 printed 1.0 binned continuous 0.68 32.5 0 printed 1.5 frame printed 1.48 19.7 0 printed 1.5 frame continuous 1.13 41.7 0 printed 1.5 binned printed 1.76 19.8 20 printed 1.5 binned continuous 1.30 54.7 0
rng = np.random.default_rng(9081)
v = variants(rng, ["gain_frame_printed", "gain_frame_continuous"])
v["median_ratio_mut_ctl"] = v.median_mut / v.median_ctl
print(v.round(4).to_string(index=False))
fig, axes = plt.subplots(1, 2, figsize=(10, 3.5))
A = cells[cells.reading == "A"]
ecdf_plot(axes[0], A, "gain_frame_printed", "Gain, frame fit, printed form", "G (Hz per SD of y)")
ecdf_plot(axes[1], A, "gain_frame_continuous", "Gain, frame fit, continuous form", "G (Hz per SD of y)")
for ax in axes: ax.set_xlim(-5, 150)
plt.tight_layout(); plt.show()
print("Ranges:", A.gain_frame_printed.agg(["min", "max"]).round(1).tolist(), A.gain_frame_continuous.agg(["min", "max"]).round(1).tolist(),
"; cells outside -5 to 150 (printed, continuous):", int(((A.gain_frame_printed < -5) | (A.gain_frame_printed > 150)).sum()),
int(((A.gain_frame_continuous < -5) | (A.gain_frame_continuous > 150)).sum()))
variant measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range median_ratio_mut_ctl
all units (main) gain_frame_printed binomial 200 122 18.3939 23.0846 0.0001 True 0 166 14.8 to 26.3 0.7968
all units (main) gain_frame_printed dkw 200 122 18.3939 23.0846 0.0001 True 0 46 17.3 to 22.2 0.7968
all units (main) gain_frame_printed bootstrap 200 122 18.3939 23.0846 0.0001 True 0 168 15.2 to 27.9 0.7968
all units (main) gain_frame_continuous binomial 200 122 30.4332 30.7532 0.7637 False 0 0 0.9896
all units (main) gain_frame_continuous dkw 200 122 30.4332 30.7532 0.7637 False 0 0 0.9896
all units (main) gain_frame_continuous bootstrap 200 122 30.4332 30.7532 0.7637 True 1 0 15.6 to 15.6 0.9896
without duplicate units gain_frame_printed binomial 189 118 18.3131 23.1184 0.0001 True 0 176 14.8 to 27.9 0.7921
without duplicate units gain_frame_printed dkw 189 118 18.3131 23.1184 0.0001 True 0 46 17.4 to 22.2 0.7921
without duplicate units gain_frame_printed bootstrap 189 118 18.3131 23.1184 0.0001 True 0 177 15.3 to 28 0.7921
without duplicate units gain_frame_continuous binomial 189 118 29.6133 30.4044 0.8093 False 0 0 0.9740
without duplicate units gain_frame_continuous dkw 189 118 29.6133 30.4044 0.8093 False 0 0 0.9740
without duplicate units gain_frame_continuous bootstrap 189 118 29.6133 30.4044 0.8093 True 1 0 15.6 to 15.6 0.9740
without 20080702_R4 gain_frame_printed binomial 188 122 18.2392 23.0846 0.0000 True 0 165 14.7 to 26.3 0.7901
without 20080702_R4 gain_frame_printed dkw 188 122 18.2392 23.0846 0.0000 True 0 72 16.5 to 22.2 0.7901
without 20080702_R4 gain_frame_printed bootstrap 188 122 18.2392 23.0846 0.0000 True 0 166 14.7 to 27.3 0.7901
without 20080702_R4 gain_frame_continuous binomial 188 122 29.9566 30.7532 0.7867 False 0 0 0.9741
without 20080702_R4 gain_frame_continuous dkw 188 122 29.9566 30.7532 0.7867 False 0 0 0.9741
without 20080702_R4 gain_frame_continuous bootstrap 188 122 29.9566 30.7532 0.7867 True 1 0 15.6 to 15.6 0.9741
out-of-order segments moved 720 s gain_frame_printed binomial 200 122 18.3939 23.1780 0.0001 True 0 174 14.7 to 27.9 0.7936
out-of-order segments moved 720 s gain_frame_printed dkw 200 122 18.3939 23.1780 0.0001 True 0 44 16.8 to 21.9 0.7936
out-of-order segments moved 720 s gain_frame_printed bootstrap 200 122 18.3939 23.1780 0.0001 True 0 175 14.7 to 27.9 0.7936
out-of-order segments moved 720 s gain_frame_continuous binomial 200 122 30.3631 30.7090 0.7637 False 0 0 0.9887
out-of-order segments moved 720 s gain_frame_continuous dkw 200 122 30.3631 30.7090 0.7637 False 0 0 0.9887
out-of-order segments moved 720 s gain_frame_continuous bootstrap 200 122 30.3631 30.7090 0.7637 True 1 0 15.6 to 15.6 0.9887
20080702 frames as deposited gain_frame_printed binomial 200 122 17.8817 23.0846 0.0000 True 0 183 14.7 to 27.9 0.7746
20080702 frames as deposited gain_frame_printed dkw 200 122 17.8817 23.0846 0.0000 True 0 89 16.2 to 22.8 0.7746
20080702 frames as deposited gain_frame_printed bootstrap 200 122 17.8817 23.0846 0.0000 True 0 182 14.8 to 27.9 0.7746
20080702 frames as deposited gain_frame_continuous binomial 200 122 29.4974 30.7532 0.8887 False 0 0 0.9592
20080702 frames as deposited gain_frame_continuous dkw 200 122 29.4974 30.7532 0.8887 False 0 0 0.9592
20080702 frames as deposited gain_frame_continuous bootstrap 200 122 29.4974 30.7532 0.8887 False 0 0 0.9592
mutant Chx10-Cre only gain_frame_printed binomial 87 122 16.2087 23.0846 0.0000 True 0 166 14.8 to 37.3 0.7021
mutant Chx10-Cre only gain_frame_printed dkw 87 122 16.2087 23.0846 0.0000 True 0 100 15.9 to 27.3 0.7021
mutant Chx10-Cre only gain_frame_printed bootstrap 87 122 16.2087 23.0846 0.0000 True 0 165 14.8 to 37.3 0.7021
mutant Chx10-Cre only gain_frame_continuous binomial 87 122 28.7152 30.7532 0.2061 True 4 1 15.2 to 57.6 0.9337
mutant Chx10-Cre only gain_frame_continuous dkw 87 122 28.7152 30.7532 0.2061 False 0 0 0.9337
mutant Chx10-Cre only gain_frame_continuous bootstrap 87 122 28.7152 30.7532 0.2061 True 4 2 15.2 to 57.6 0.9337
mutant Pax6-Cre only gain_frame_printed binomial 113 122 21.5521 23.0846 0.2678 False 0 0 0.9336
mutant Pax6-Cre only gain_frame_printed dkw 113 122 21.5521 23.0846 0.2678 False 0 0 0.9336
mutant Pax6-Cre only gain_frame_printed bootstrap 113 122 21.5521 23.0846 0.2678 False 0 0 0.9336
mutant Pax6-Cre only gain_frame_continuous binomial 113 122 33.0070 30.7532 0.2875 False 0 0 1.0733
mutant Pax6-Cre only gain_frame_continuous dkw 113 122 33.0070 30.7532 0.2875 False 0 0 1.0733
mutant Pax6-Cre only gain_frame_continuous bootstrap 113 122 33.0070 30.7532 0.2875 False 0 0 1.0733
control Pax6-Cre het only gain_frame_printed binomial 200 27 18.3939 22.9835 0.0128 True 0 57 11.8 to 22.5 0.8003
control Pax6-Cre het only gain_frame_printed dkw 200 27 18.3939 22.9835 0.0128 False 0 0 0.8003
control Pax6-Cre het only gain_frame_printed bootstrap 200 27 18.3939 22.9835 0.0128 True 0 53 11.8 to 22.4 0.8003
control Pax6-Cre het only gain_frame_continuous binomial 200 27 30.4332 30.1300 0.6234 False 0 0 1.0101
control Pax6-Cre het only gain_frame_continuous dkw 200 27 30.4332 30.1300 0.6234 False 0 0 1.0101
control Pax6-Cre het only gain_frame_continuous bootstrap 200 27 30.4332 30.1300 0.6234 False 0 0 1.0101
cells with STA peak ratio above 2 gain_frame_printed binomial 103 107 23.0563 23.4351 0.2642 False 0 0 0.9838
cells with STA peak ratio above 2 gain_frame_printed dkw 103 107 23.0563 23.4351 0.2642 False 0 0 0.9838
cells with STA peak ratio above 2 gain_frame_printed bootstrap 103 107 23.0563 23.4351 0.2642 False 0 0 0.9838
cells with STA peak ratio above 2 gain_frame_continuous binomial 103 107 33.0904 30.9989 0.2427 False 0 0 1.0675
cells with STA peak ratio above 2 gain_frame_continuous dkw 103 107 33.0904 30.9989 0.2427 False 0 0 1.0675
cells with STA peak ratio above 2 gain_frame_continuous bootstrap 103 107 33.0904 30.9989 0.2427 False 0 0 1.0675
16.6 um bars only gain_frame_printed binomial 148 122 17.7534 23.0846 0.0000 True 0 173 14.4 to 28.1 0.7691
16.6 um bars only gain_frame_printed dkw 148 122 17.7534 23.0846 0.0000 True 0 88 16 to 24.2 0.7691
16.6 um bars only gain_frame_printed bootstrap 148 122 17.7534 23.0846 0.0000 True 0 171 14.7 to 28.1 0.7691
16.6 um bars only gain_frame_continuous binomial 148 122 29.4974 30.7532 0.8479 True 0 1 57.6 to 57.6 0.9592
16.6 um bars only gain_frame_continuous dkw 148 122 29.4974 30.7532 0.8479 False 0 0 0.9592
16.6 um bars only gain_frame_continuous bootstrap 148 122 29.4974 30.7532 0.8479 True 0 1 57.6 to 57.6 0.9592
Ranges: [10.4, 41.8] [13.1, 70.0] ; cells outside -5 to 150 (printed, continuous): 0 0
Result: blocked (methods_underspecified). The readings of the nonlinearity's form disagree. With the printed form (B + G y above theta), the bands separate with mutant gains lower in all 18 combinations (reading A, frame fit: median 18.4 against 23.1 Hz per SD, ratio 0.80). With the continuous form (B + G (y - theta)), they overlap in 9 of 18, separate with mutant gains lower in 4 (reading B, binomial and bootstrap) and separate the other way in 5 (readings A and C). The medians are close (reading A, frame fit: 30.4 against 30.8, KS p = 0.76) and the DKW bands overlap in all 6 continuous-form combinations. Under reading B the separating values lie among the lowest gains (10 to 21 Hz per SD), and the first 8 to 10 of each lie among the 4 to 13 mutant gains below the lowest control gain, where the control band has zero width. Under reading A, frame fit, bootstrap, the one separating value (15.6) has 1 mutant against 6 control cells at or below it. The other separations the other way lie inside the distributions: under reading A, binned fit, at 41.46, with 165 of 200 mutant and 113 of 122 control cells at or below it; under reading C, frame fit, near 21.2, with 16 to 19 mutant against 23 to 25 control cells. Among cells with clear STAs neither form gives lower mutant gains under reading A (printed 23.1 against 23.4, continuous 33.1 against 31.0); over the three readings in that subset the printed form separates with mutant gains lower in 6 of 18 combinations (readings B and C) and the continuous form in 4, with 6 the other way and no DKW separation (cell 56), so the outcome there is blocked too. On synthetic cells that follow the continuous form, the printed-form fit returns a higher theta and a lower gain than the truth (true theta 0.5 and G 20: frame fit 0.75 and 13.4). So part of the printed-form gain reduction may mirror the higher mutant thresholds of fig9g-threshold-unaltered.
Every claim under the variants that bear on it, and all readings¶
Three variants are run here under all three recording readings (A, B, C), for every combination of each tested claim: the frames of the 20080702 bar recordings as deposited, the units whose STA peak is more than twice the null's (a threshold chosen here; the claims file uses all units), and the 16.6 um bar recordings alone. For each claim the table gives the combinations whose bands separate, by direction, and the DKW combinations that separate. The main analysis (frames corrected, all units) is computed again with the same seed for comparison; the claim sections above hold its tables.
CLAIM_COLS = {
"fig9d-rf-size-similar": ["fwhm_svd", "fwhm_peak"],
"fig9e-slower-time-course": [f"ttp_{s}_{p}" for s in ("svd", "peak") for p in ("frame", "parabolic")],
"fig9f-lower-firing-rate": ["rate_hz"],
"fig9g-threshold-unaltered": [f"theta_{f}_{m}" for f in ("frame", "binned") for m in ("printed", "continuous")],
"fig9h-gain-reduced": [f"gain_{f}_{m}" for f in ("frame", "binned") for m in ("printed", "continuous")],
}
ALL_COLS = sum(CLAIM_COLS.values(), [])
def tally(res):
"""Per claim: combinations, those whose bands separate, by direction, and the DKW ones that separate."""
out = []
for claim, cols in CLAIM_COLS.items():
r = res[res.measure.isin(cols)]
s = r[r.separate]
out.append({"claim": claim, "combinations": len(r), "separate": len(s),
"mutant_larger_only": int(((s.mutant_larger_pts > 0) & (s.mutant_smaller_pts == 0)).sum()),
"mutant_smaller_only": int(((s.mutant_smaller_pts > 0) & (s.mutant_larger_pts == 0)).sum()),
"both_ways": int(((s.mutant_larger_pts > 0) & (s.mutant_smaller_pts > 0)).sum()),
"dkw_separate": f"{int(s.ci.eq('dkw').sum())} of {int(r.ci.eq('dkw').sum())}"})
return pd.DataFrame(out)
def all_readings(select, seed):
rng = np.random.default_rng(seed)
return pd.concat([judge(select(rd), ALL_COLS, rng).assign(recording=rd) for rd in ret1.READINGS], ignore_index=True)
def main_set(rd):
return cells[(cells.reading == rd) & cells.group.isin(GROUPS)]
variant_sets = {
"main analysis (frames corrected, all units)": main_set,
"20080702 frames as deposited": lambda rd: cells[(cells.reading == f"{rd}, frames as deposited") & cells.group.isin(GROUPS)],
"cells with STA peak ratio above 2": lambda rd: main_set(rd)[main_set(rd).peak_ratio > 2],
"16.6 um bars only": lambda rd: main_set(rd)[main_set(rd).bar_um == 16.6],
}
variant_results = {k: all_readings(f, 910) for k, f in variant_sets.items()}
for k, res in variant_results.items():
print(f"\n{k}:")
print(tally(res).to_string(index=False))
main analysis (frames corrected, all units):
claim combinations separate mutant_larger_only mutant_smaller_only both_ways dkw_separate
fig9d-rf-size-similar 18 17 0 17 0 5 of 6
fig9e-slower-time-course 36 36 36 0 0 12 of 12
fig9f-lower-firing-rate 9 9 0 9 0 3 of 3
fig9g-threshold-unaltered 36 36 36 0 0 12 of 12
fig9h-gain-reduced 36 27 5 22 0 6 of 12
20080702 frames as deposited:
claim combinations separate mutant_larger_only mutant_smaller_only both_ways dkw_separate
fig9d-rf-size-similar 18 18 0 18 0 6 of 6
fig9e-slower-time-course 36 36 28 0 8 12 of 12
fig9f-lower-firing-rate 9 9 0 9 0 3 of 3
fig9g-threshold-unaltered 36 36 36 0 0 12 of 12
fig9h-gain-reduced 36 22 0 22 0 6 of 12
cells with STA peak ratio above 2:
claim combinations separate mutant_larger_only mutant_smaller_only both_ways dkw_separate
fig9d-rf-size-similar 18 13 0 13 0 1 of 6
fig9e-slower-time-course 36 36 36 0 0 12 of 12
fig9f-lower-firing-rate 9 6 0 6 0 0 of 3
fig9g-threshold-unaltered 36 24 23 0 1 0 of 12
fig9h-gain-reduced 36 16 6 10 0 0 of 12
16.6 um bars only:
claim combinations separate mutant_larger_only mutant_smaller_only both_ways dkw_separate
fig9d-rf-size-similar 18 16 0 16 0 4 of 6
fig9e-slower-time-course 36 36 36 0 0 12 of 12
fig9f-lower-firing-rate 9 9 0 9 0 3 of 3
fig9g-threshold-unaltered 36 36 36 0 0 12 of 12
fig9h-gain-reduced 36 27 0 23 4 6 of 12
# The full tables of the variants, every combination.
for k, res in list(variant_results.items())[1:]:
print(f"\n{k}:")
print(res[["recording", "measure", "ci", "n_mut", "n_ctl", "median_mut", "median_ctl", "ks_p", "separate",
"mutant_larger_pts", "mutant_smaller_pts", "sep_range"]].round(4).to_string(index=False))
20080702 frames as deposited:
recording measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range
A fwhm_svd binomial 200 122 116.4118 156.1976 0.0000 True 0 225 20.2 to 171
A fwhm_svd dkw 200 122 116.4118 156.1976 0.0000 True 0 145 80.5 to 156
A fwhm_svd bootstrap 200 122 116.4118 156.1976 0.0000 True 0 225 20.2 to 171
A fwhm_peak binomial 200 122 93.6992 150.7827 0.0000 True 0 262 9.24 to 172
A fwhm_peak dkw 200 122 93.6992 150.7827 0.0000 True 0 200 37.8 to 163
A fwhm_peak bootstrap 200 122 93.6992 150.7827 0.0000 True 0 261 9.24 to 172
A ttp_svd_frame binomial 200 122 0.1250 0.1084 0.0000 True 87 0 0.075 to 0.392
A ttp_svd_frame dkw 200 122 0.1250 0.1084 0.0000 True 41 0 0.0917 to 0.158
A ttp_svd_frame bootstrap 200 122 0.1250 0.1084 0.0000 True 87 0 0.075 to 0.392
A ttp_svd_parabolic binomial 200 122 0.1328 0.1111 0.0000 True 311 0 0.0813 to 0.389
A ttp_svd_parabolic dkw 200 122 0.1328 0.1111 0.0000 True 226 0 0.0974 to 0.16
A ttp_svd_parabolic bootstrap 200 122 0.1328 0.1111 0.0000 True 312 0 0.0812 to 0.389
A ttp_peak_frame binomial 200 122 0.1250 0.1084 0.0000 True 76 1 0.025 to 0.392
A ttp_peak_frame dkw 200 122 0.1250 0.1084 0.0000 True 31 0 0.0917 to 0.142
A ttp_peak_frame bootstrap 200 122 0.1250 0.1084 0.0000 True 76 1 0.025 to 0.392
A ttp_peak_parabolic binomial 200 122 0.1258 0.1094 0.0000 True 301 1 0.028 to 0.395
A ttp_peak_parabolic dkw 200 122 0.1258 0.1094 0.0000 True 207 0 0.1 to 0.152
A ttp_peak_parabolic bootstrap 200 122 0.1258 0.1094 0.0000 True 300 1 0.028 to 0.395
A rate_hz binomial 200 122 3.8185 9.0175 0.0000 True 0 305 0.716 to 30.7
A rate_hz dkw 200 122 3.8185 9.0175 0.0000 True 0 171 2.57 to 14.8
A rate_hz bootstrap 200 122 3.8185 9.0175 0.0000 True 0 307 0.633 to 30.7
A theta_frame_printed binomial 200 122 1.6851 0.0072 0.0000 True 270 0 -2.26 to 2.25
A theta_frame_printed dkw 200 122 1.6851 0.0072 0.0000 True 104 0 0.00497 to 1.82
A theta_frame_printed bootstrap 200 122 1.6851 0.0072 0.0000 True 274 0 -2.27 to 2.26
A theta_frame_continuous binomial 200 122 1.1227 0.4360 0.0000 True 264 0 -0.844 to 1.59
A theta_frame_continuous dkw 200 122 1.1227 0.4360 0.0000 True 153 0 0.0434 to 1.39
A theta_frame_continuous bootstrap 200 122 1.1227 0.4360 0.0000 True 266 0 -0.893 to 1.66
A theta_binned_printed binomial 200 122 1.8127 -0.0226 0.0000 True 247 0 -1.73 to 1.93
A theta_binned_printed dkw 200 122 1.8127 -0.0226 0.0000 True 134 0 -0.0311 to 1.85
A theta_binned_printed bootstrap 200 122 1.8127 -0.0226 0.0000 True 251 0 -1.73 to 1.93
A theta_binned_continuous binomial 200 122 1.0044 0.4730 0.0000 True 291 0 -1.04 to 1.88
A theta_binned_continuous dkw 200 122 1.0044 0.4730 0.0000 True 151 0 0.0917 to 1.22
A theta_binned_continuous bootstrap 200 122 1.0044 0.4730 0.0000 True 296 0 -1.04 to 1.88
A gain_frame_printed binomial 200 122 17.8817 23.0846 0.0000 True 0 183 14.7 to 27.9
A gain_frame_printed dkw 200 122 17.8817 23.0846 0.0000 True 0 89 16.2 to 22.8
A gain_frame_printed bootstrap 200 122 17.8817 23.0846 0.0000 True 0 190 14.7 to 27.9
A gain_frame_continuous binomial 200 122 29.4974 30.7532 0.8887 False 0 0
A gain_frame_continuous dkw 200 122 29.4974 30.7532 0.8887 False 0 0
A gain_frame_continuous bootstrap 200 122 29.4974 30.7532 0.8887 False 0 0
A gain_binned_printed binomial 200 122 14.9465 21.1266 0.0000 True 0 254 5.9 to 27.4
A gain_binned_printed dkw 200 122 14.9465 21.1266 0.0000 True 0 139 12.7 to 22
A gain_binned_printed bootstrap 200 122 14.9465 21.1266 0.0000 True 0 259 5.34 to 27.7
A gain_binned_continuous binomial 200 122 29.5144 29.2195 0.6607 False 0 0
A gain_binned_continuous dkw 200 122 29.5144 29.2195 0.6607 False 0 0
A gain_binned_continuous bootstrap 200 122 29.5144 29.2195 0.6607 False 0 0
B fwhm_svd binomial 200 122 123.1735 156.1976 0.0002 True 0 201 21.2 to 162
B fwhm_svd dkw 200 122 123.1735 156.1976 0.0002 True 0 23 98.6 to 127
B fwhm_svd bootstrap 200 122 123.1735 156.1976 0.0002 True 0 205 21.2 to 165
B fwhm_peak binomial 200 122 98.4117 150.7827 0.0000 True 0 253 9.24 to 169
B fwhm_peak dkw 200 122 98.4117 150.7827 0.0000 True 0 185 51.6 to 161
B fwhm_peak bootstrap 200 122 98.4117 150.7827 0.0000 True 0 253 9.24 to 170
B ttp_svd_frame binomial 200 122 0.1250 0.1084 0.0000 True 80 0 0.075 to 0.358
B ttp_svd_frame dkw 200 122 0.1250 0.1084 0.0000 True 37 0 0.0917 to 0.158
B ttp_svd_frame bootstrap 200 122 0.1250 0.1084 0.0000 True 81 0 0.075 to 0.358
B ttp_svd_parabolic binomial 200 122 0.1298 0.1111 0.0000 True 304 0 0.0819 to 0.356
B ttp_svd_parabolic dkw 200 122 0.1298 0.1111 0.0000 True 224 0 0.0982 to 0.156
B ttp_svd_parabolic bootstrap 200 122 0.1298 0.1111 0.0000 True 304 0 0.0819 to 0.346
B ttp_peak_frame binomial 200 122 0.1250 0.1084 0.0000 True 75 0 0.0917 to 0.392
B ttp_peak_frame dkw 200 122 0.1250 0.1084 0.0000 True 33 0 0.0917 to 0.158
B ttp_peak_frame bootstrap 200 122 0.1250 0.1084 0.0000 True 76 0 0.0917 to 0.392
B ttp_peak_parabolic binomial 200 122 0.1254 0.1094 0.0000 True 302 0 0.09 to 0.387
B ttp_peak_parabolic dkw 200 122 0.1254 0.1094 0.0000 True 212 0 0.0995 to 0.153
B ttp_peak_parabolic bootstrap 200 122 0.1254 0.1094 0.0000 True 305 0 0.0889 to 0.387
B rate_hz binomial 200 122 4.0306 9.0175 0.0000 True 0 302 0.768 to 30.7
B rate_hz dkw 200 122 4.0306 9.0175 0.0000 True 0 148 3.37 to 14.1
B rate_hz bootstrap 200 122 4.0306 9.0175 0.0000 True 0 300 0.694 to 30.7
B theta_frame_printed binomial 200 122 1.4026 0.0072 0.0004 True 196 0 -2.26 to 2.18
B theta_frame_printed dkw 200 122 1.4026 0.0072 0.0004 True 10 0 0.00984 to 1.28
B theta_frame_printed bootstrap 200 122 1.4026 0.0072 0.0004 True 193 0 -2.27 to 2.18
B theta_frame_continuous binomial 200 122 0.9320 0.4360 0.0000 True 216 0 -0.844 to 1.49
B theta_frame_continuous dkw 200 122 0.9320 0.4360 0.0000 True 66 0 0.282 to 0.767
B theta_frame_continuous bootstrap 200 122 0.9320 0.4360 0.0000 True 221 0 -0.893 to 1.5
B theta_binned_printed binomial 200 122 1.2945 -0.0226 0.0004 True 212 0 -1.73 to 1.93
B theta_binned_printed dkw 200 122 1.2945 -0.0226 0.0004 True 8 0 -0.013 to -0.0046
B theta_binned_printed bootstrap 200 122 1.2945 -0.0226 0.0004 True 194 0 -1.73 to 1.9
B theta_binned_continuous binomial 200 122 0.8068 0.4730 0.0000 True 240 0 -1.04 to 1.87
B theta_binned_continuous dkw 200 122 0.8068 0.4730 0.0000 True 57 0 0.219 to 0.648
B theta_binned_continuous bootstrap 200 122 0.8068 0.4730 0.0000 True 239 0 -1.04 to 1.87
B gain_frame_printed binomial 200 122 17.2941 23.0846 0.0000 True 0 243 7.49 to 27.9
B gain_frame_printed dkw 200 122 17.2941 23.0846 0.0000 True 0 115 15.2 to 23
B gain_frame_printed bootstrap 200 122 17.2941 23.0846 0.0000 True 0 240 7.49 to 27.9
B gain_frame_continuous binomial 200 122 28.4943 30.7532 0.2622 True 0 20 11.1 to 20.1
B gain_frame_continuous dkw 200 122 28.4943 30.7532 0.2622 False 0 0
B gain_frame_continuous bootstrap 200 122 28.4943 30.7532 0.2622 True 0 22 11.1 to 20.5
B gain_binned_printed binomial 200 122 14.1570 21.1266 0.0000 True 0 254 6.12 to 27.4
B gain_binned_printed dkw 200 122 14.1570 21.1266 0.0000 True 0 142 11.7 to 22
B gain_binned_printed bootstrap 200 122 14.1570 21.1266 0.0000 True 0 255 5.49 to 27.4
B gain_binned_continuous binomial 200 122 28.2936 29.2195 0.1532 True 0 28 10.2 to 21.2
B gain_binned_continuous dkw 200 122 28.2936 29.2195 0.1532 False 0 0
B gain_binned_continuous bootstrap 200 122 28.2936 29.2195 0.1532 True 0 29 10.2 to 21.2
C fwhm_svd binomial 200 122 117.0516 166.5035 0.0000 True 0 285 13.1 to 227
C fwhm_svd dkw 200 122 117.0516 166.5035 0.0000 True 0 187 71.1 to 180
C fwhm_svd bootstrap 200 122 117.0516 166.5035 0.0000 True 0 284 13.1 to 227
C fwhm_peak binomial 200 122 84.6751 153.3028 0.0000 True 0 305 9.96 to 253
C fwhm_peak dkw 200 122 84.6751 153.3028 0.0000 True 0 215 30.1 to 181
C fwhm_peak bootstrap 200 122 84.6751 153.3028 0.0000 True 0 306 9.96 to 253
C ttp_svd_frame binomial 200 122 0.1417 0.1084 0.0000 True 80 0 0.0917 to 0.342
C ttp_svd_frame dkw 200 122 0.1417 0.1084 0.0000 True 44 0 0.0917 to 0.158
C ttp_svd_frame bootstrap 200 122 0.1417 0.1084 0.0000 True 81 0 0.0917 to 0.342
C ttp_svd_parabolic binomial 200 122 0.1357 0.1118 0.0000 True 300 0 0.0844 to 0.336
C ttp_svd_parabolic dkw 200 122 0.1357 0.1118 0.0000 True 223 0 0.0994 to 0.16
C ttp_svd_parabolic bootstrap 200 122 0.1357 0.1118 0.0000 True 303 0 0.0836 to 0.346
C ttp_peak_frame binomial 200 122 0.1250 0.1084 0.0000 True 75 2 0.025 to 0.392
C ttp_peak_frame dkw 200 122 0.1250 0.1084 0.0000 True 39 0 0.0917 to 0.158
C ttp_peak_frame bootstrap 200 122 0.1250 0.1084 0.0000 True 76 2 0.025 to 0.392
C ttp_peak_parabolic binomial 200 122 0.1281 0.1095 0.0000 True 298 2 0.0283 to 0.387
C ttp_peak_parabolic dkw 200 122 0.1281 0.1095 0.0000 True 217 0 0.1 to 0.159
C ttp_peak_parabolic bootstrap 200 122 0.1281 0.1095 0.0000 True 300 2 0.0283 to 0.387
C rate_hz binomial 200 122 3.4301 8.9467 0.0000 True 0 300 0.679 to 28.6
C rate_hz dkw 200 122 3.4301 8.9467 0.0000 True 0 207 1.88 to 16.6
C rate_hz bootstrap 200 122 3.4301 8.9467 0.0000 True 0 300 0.679 to 28.6
C theta_frame_printed binomial 200 122 1.6958 0.0074 0.0000 True 266 0 -2.27 to 2.24
C theta_frame_printed dkw 200 122 1.6958 0.0074 0.0000 True 130 0 0.0043 to 2.14
C theta_frame_printed bootstrap 200 122 1.6958 0.0074 0.0000 True 265 0 -2.27 to 2.24
C theta_frame_continuous binomial 200 122 1.1852 0.3828 0.0000 True 263 0 -0.818 to 1.71
C theta_frame_continuous dkw 200 122 1.1852 0.3828 0.0000 True 192 0 -0.184 to 1.43
C theta_frame_continuous bootstrap 200 122 1.1852 0.3828 0.0000 True 266 0 -0.844 to 1.71
C theta_binned_printed binomial 200 122 1.8123 -0.0176 0.0000 True 224 0 -0.0303 to 1.9
C theta_binned_printed dkw 200 122 1.8123 -0.0176 0.0000 True 106 0 -0.0182 to 1.84
C theta_binned_printed bootstrap 200 122 1.8123 -0.0176 0.0000 True 228 0 -0.0311 to 1.9
C theta_binned_continuous binomial 200 122 1.0153 0.3546 0.0000 True 300 0 -1.05 to 1.87
C theta_binned_continuous dkw 200 122 1.0153 0.3546 0.0000 True 170 0 -0.275 to 1.24
C theta_binned_continuous bootstrap 200 122 1.0153 0.3546 0.0000 True 300 0 -1.05 to 1.87
C gain_frame_printed binomial 200 122 17.4357 22.4145 0.0000 True 0 197 14.6 to 27.9
C gain_frame_printed dkw 200 122 17.4357 22.4145 0.0000 True 0 109 16 to 24.7
C gain_frame_printed bootstrap 200 122 17.4357 22.4145 0.0000 True 0 198 14.6 to 27.9
C gain_frame_continuous binomial 200 122 28.9810 29.2187 0.1736 False 0 0
C gain_frame_continuous dkw 200 122 28.9810 29.2187 0.1736 False 0 0
C gain_frame_continuous bootstrap 200 122 28.9810 29.2187 0.1736 False 0 0
C gain_binned_printed binomial 200 122 13.9245 20.8431 0.0000 True 0 264 5.7 to 28.6
C gain_binned_printed dkw 200 122 13.9245 20.8431 0.0000 True 0 154 12.2 to 24.3
C gain_binned_printed bootstrap 200 122 13.9245 20.8431 0.0000 True 0 264 5.7 to 28.6
C gain_binned_continuous binomial 200 122 28.3172 27.7145 0.2548 False 0 0
C gain_binned_continuous dkw 200 122 28.3172 27.7145 0.2548 False 0 0
C gain_binned_continuous bootstrap 200 122 28.3172 27.7145 0.2548 False 0 0
cells with STA peak ratio above 2:
recording measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range
A fwhm_svd binomial 103 107 145.2719 158.1369 0.1883 True 0 8 81.6 to 101
A fwhm_svd dkw 103 107 145.2719 158.1369 0.1883 False 0 0
A fwhm_svd bootstrap 103 107 145.2719 158.1369 0.1883 True 0 10 81.6 to 101
A fwhm_peak binomial 103 107 129.6062 153.2891 0.0034 True 0 86 51.7 to 154
A fwhm_peak dkw 103 107 129.6062 153.2891 0.0034 False 0 0
A fwhm_peak bootstrap 103 107 129.6062 153.2891 0.0034 True 0 86 51.7 to 154
A ttp_svd_frame binomial 103 107 0.1250 0.1084 0.0000 True 44 0 0.075 to 0.175
A ttp_svd_frame dkw 103 107 0.1250 0.1084 0.0000 True 11 0 0.0917 to 0.125
A ttp_svd_frame bootstrap 103 107 0.1250 0.1084 0.0000 True 42 0 0.075 to 0.175
A ttp_svd_parabolic binomial 103 107 0.1225 0.1102 0.0000 True 200 0 0.0804 to 0.169
A ttp_svd_parabolic dkw 103 107 0.1225 0.1102 0.0000 True 85 0 0.0989 to 0.128
A ttp_svd_parabolic bootstrap 103 107 0.1225 0.1102 0.0000 True 199 0 0.0804 to 0.169
A ttp_peak_frame binomial 103 107 0.1250 0.1084 0.0000 True 34 0 0.075 to 0.158
A ttp_peak_frame dkw 103 107 0.1250 0.1084 0.0000 True 8 0 0.108 to 0.125
A ttp_peak_frame bootstrap 103 107 0.1250 0.1084 0.0000 True 35 0 0.075 to 0.158
A ttp_peak_parabolic binomial 103 107 0.1221 0.1089 0.0000 True 189 0 0.0789 to 0.178
A ttp_peak_parabolic dkw 103 107 0.1221 0.1089 0.0000 True 85 0 0.1 to 0.123
A ttp_peak_parabolic bootstrap 103 107 0.1221 0.1089 0.0000 True 194 0 0.0789 to 0.178
A rate_hz binomial 103 107 6.0933 9.1971 0.0156 True 0 67 4.05 to 30.7
A rate_hz dkw 103 107 6.0933 9.1971 0.0156 False 0 0
A rate_hz bootstrap 103 107 6.0933 9.1971 0.0156 True 0 70 4.03 to 30.7
A theta_frame_printed binomial 103 107 1.3382 0.0067 0.0048 True 72 0 -0.0119 to 1.41
A theta_frame_printed dkw 103 107 1.3382 0.0067 0.0048 False 0 0
A theta_frame_printed bootstrap 103 107 1.3382 0.0067 0.0048 True 72 0 -0.0119 to 1.34
A theta_frame_continuous binomial 103 107 0.8643 0.4116 0.0025 True 63 0 -0.686 to 0.851
A theta_frame_continuous dkw 103 107 0.8643 0.4116 0.0025 False 0 0
A theta_frame_continuous bootstrap 103 107 0.8643 0.4116 0.0025 True 60 0 -0.686 to 0.941
A theta_binned_printed binomial 103 107 1.2928 -0.0271 0.0070 True 60 0 -1.73 to 1.9
A theta_binned_printed dkw 103 107 1.2928 -0.0271 0.0070 False 0 0
A theta_binned_printed bootstrap 103 107 1.2928 -0.0271 0.0070 True 65 0 -1.73 to 1.9
A theta_binned_continuous binomial 103 107 0.7999 0.3586 0.0042 True 61 0 -1.04 to 1.87
A theta_binned_continuous dkw 103 107 0.7999 0.3586 0.0042 False 0 0
A theta_binned_continuous bootstrap 103 107 0.7999 0.3586 0.0042 True 58 0 -1.04 to 1.87
A gain_frame_printed binomial 103 107 23.0563 23.4351 0.2642 False 0 0
A gain_frame_printed dkw 103 107 23.0563 23.4351 0.2642 False 0 0
A gain_frame_printed bootstrap 103 107 23.0563 23.4351 0.2642 False 0 0
A gain_frame_continuous binomial 103 107 33.0904 30.9989 0.2427 False 0 0
A gain_frame_continuous dkw 103 107 33.0904 30.9989 0.2427 False 0 0
A gain_frame_continuous bootstrap 103 107 33.0904 30.9989 0.2427 False 0 0
A gain_binned_printed binomial 103 107 20.2302 21.9816 0.1591 False 0 0
A gain_binned_printed dkw 103 107 20.2302 21.9816 0.1591 False 0 0
A gain_binned_printed bootstrap 103 107 20.2302 21.9816 0.1591 False 0 0
A gain_binned_continuous binomial 103 107 31.7362 29.9406 0.1191 True 6 0 40 to 41.8
A gain_binned_continuous dkw 103 107 31.7362 29.9406 0.1191 False 0 0
A gain_binned_continuous bootstrap 103 107 31.7362 29.9406 0.1191 True 7 0 40 to 41.8
B fwhm_svd binomial 115 107 147.8004 158.1369 0.3233 True 0 4 81.6 to 87
B fwhm_svd dkw 115 107 147.8004 158.1369 0.3233 False 0 0
B fwhm_svd bootstrap 115 107 147.8004 158.1369 0.3233 True 0 6 81.6 to 100
B fwhm_peak binomial 115 107 132.6940 153.2891 0.0104 True 0 68 51.7 to 153
B fwhm_peak dkw 115 107 132.6940 153.2891 0.0104 False 0 0
B fwhm_peak bootstrap 115 107 132.6940 153.2891 0.0104 True 0 73 51.7 to 154
B ttp_svd_frame binomial 115 107 0.1250 0.1084 0.0000 True 43 0 0.075 to 0.175
B ttp_svd_frame dkw 115 107 0.1250 0.1084 0.0000 True 11 0 0.0917 to 0.125
B ttp_svd_frame bootstrap 115 107 0.1250 0.1084 0.0000 True 41 0 0.075 to 0.175
B ttp_svd_parabolic binomial 115 107 0.1213 0.1102 0.0000 True 212 0 0.0804 to 0.175
B ttp_svd_parabolic dkw 115 107 0.1213 0.1102 0.0000 True 61 0 0.0987 to 0.12
B ttp_svd_parabolic bootstrap 115 107 0.1213 0.1102 0.0000 True 208 0 0.0804 to 0.175
B ttp_peak_frame binomial 115 107 0.1250 0.1084 0.0000 True 40 0 0.075 to 0.158
B ttp_peak_frame dkw 115 107 0.1250 0.1084 0.0000 True 8 0 0.108 to 0.125
B ttp_peak_frame bootstrap 115 107 0.1250 0.1084 0.0000 True 36 0 0.075 to 0.158
B ttp_peak_parabolic binomial 115 107 0.1214 0.1089 0.0000 True 204 0 0.0789 to 0.179
B ttp_peak_parabolic dkw 115 107 0.1214 0.1089 0.0000 True 72 0 0.1 to 0.121
B ttp_peak_parabolic bootstrap 115 107 0.1214 0.1089 0.0000 True 205 0 0.0789 to 0.179
B rate_hz binomial 115 107 5.7439 9.1971 0.0054 True 0 120 3.95 to 30.7
B rate_hz dkw 115 107 5.7439 9.1971 0.0054 False 0 0
B rate_hz bootstrap 115 107 5.7439 9.1971 0.0054 True 0 123 3.93 to 30.7
B theta_frame_printed binomial 115 107 1.1466 0.0067 0.0280 True 44 0 -0.0119 to 1.33
B theta_frame_printed dkw 115 107 1.1466 0.0067 0.0280 False 0 0
B theta_frame_printed bootstrap 115 107 1.1466 0.0067 0.0280 True 45 0 -2.22 to 1.33
B theta_frame_continuous binomial 115 107 0.7737 0.4116 0.0013 True 62 0 -0.686 to 0.682
B theta_frame_continuous dkw 115 107 0.7737 0.4116 0.0013 False 0 0
B theta_frame_continuous bootstrap 115 107 0.7737 0.4116 0.0013 True 62 0 -0.686 to 0.737
B theta_binned_printed binomial 115 107 1.0182 -0.0271 0.0272 True 21 0 -1.73 to 1.9
B theta_binned_printed dkw 115 107 1.0182 -0.0271 0.0272 False 0 0
B theta_binned_printed bootstrap 115 107 1.0182 -0.0271 0.0272 True 22 0 -1.73 to 1.9
B theta_binned_continuous binomial 115 107 0.7807 0.3586 0.0053 True 54 0 -1.04 to 0.638
B theta_binned_continuous dkw 115 107 0.7807 0.3586 0.0053 False 0 0
B theta_binned_continuous bootstrap 115 107 0.7807 0.3586 0.0053 True 62 0 -1.04 to 0.643
B gain_frame_printed binomial 115 107 21.5521 23.4351 0.0102 True 0 63 8.93 to 19.3
B gain_frame_printed dkw 115 107 21.5521 23.4351 0.0102 False 0 0
B gain_frame_printed bootstrap 115 107 21.5521 23.4351 0.0102 True 0 65 8.93 to 19.4
B gain_frame_continuous binomial 115 107 31.0442 30.9989 0.4704 True 0 2 12.9 to 18.7
B gain_frame_continuous dkw 115 107 31.0442 30.9989 0.4704 False 0 0
B gain_frame_continuous bootstrap 115 107 31.0442 30.9989 0.4704 True 0 1 12.9 to 12.9
B gain_binned_printed binomial 115 107 19.0982 21.9816 0.0058 True 0 65 10.2 to 18.5
B gain_binned_printed dkw 115 107 19.0982 21.9816 0.0058 False 0 0
B gain_binned_printed bootstrap 115 107 19.0982 21.9816 0.0058 True 0 69 9.95 to 18.8
B gain_binned_continuous binomial 115 107 30.4925 29.9406 0.4041 True 0 3 12.5 to 13.5
B gain_binned_continuous dkw 115 107 30.4925 29.9406 0.4041 False 0 0
B gain_binned_continuous bootstrap 115 107 30.4925 29.9406 0.4041 True 0 3 12.5 to 13.5
C fwhm_svd binomial 98 103 144.6535 170.8004 0.0066 True 0 60 81.6 to 171
C fwhm_svd dkw 98 103 144.6535 170.8004 0.0066 False 0 0
C fwhm_svd bootstrap 98 103 144.6535 170.8004 0.0066 True 0 61 81.6 to 198
C fwhm_peak binomial 98 103 128.2135 160.3560 0.0000 True 0 146 52.7 to 253
C fwhm_peak dkw 98 103 128.2135 160.3560 0.0000 True 0 39 115 to 163
C fwhm_peak bootstrap 98 103 128.2135 160.3560 0.0000 True 0 147 52.7 to 253
C ttp_svd_frame binomial 98 103 0.1250 0.1084 0.0000 True 42 0 0.075 to 0.175
C ttp_svd_frame dkw 98 103 0.1250 0.1084 0.0000 True 18 0 0.0917 to 0.125
C ttp_svd_frame bootstrap 98 103 0.1250 0.1084 0.0000 True 41 0 0.0917 to 0.175
C ttp_svd_parabolic binomial 98 103 0.1226 0.1100 0.0000 True 194 0 0.0819 to 0.169
C ttp_svd_parabolic dkw 98 103 0.1226 0.1100 0.0000 True 104 0 0.0998 to 0.128
C ttp_svd_parabolic bootstrap 98 103 0.1226 0.1100 0.0000 True 194 0 0.0819 to 0.169
C ttp_peak_frame binomial 98 103 0.1250 0.1084 0.0000 True 42 0 0.075 to 0.175
C ttp_peak_frame dkw 98 103 0.1250 0.1084 0.0000 True 10 0 0.108 to 0.125
C ttp_peak_frame bootstrap 98 103 0.1250 0.1084 0.0000 True 43 0 0.075 to 0.175
C ttp_peak_parabolic binomial 98 103 0.1233 0.1093 0.0000 True 194 0 0.082 to 0.172
C ttp_peak_parabolic dkw 98 103 0.1233 0.1093 0.0000 True 101 0 0.101 to 0.127
C ttp_peak_parabolic bootstrap 98 103 0.1233 0.1093 0.0000 True 194 0 0.082 to 0.172
C rate_hz binomial 98 103 5.9186 9.3650 0.0038 True 0 128 2.02 to 28.6
C rate_hz dkw 98 103 5.9186 9.3650 0.0038 False 0 0
C rate_hz bootstrap 98 103 5.9186 9.3650 0.0038 True 0 117 2.03 to 28.6
C theta_frame_printed binomial 98 103 1.3375 0.0053 0.0030 True 85 0 -0.0119 to 1.69
C theta_frame_printed dkw 98 103 1.3375 0.0053 0.0030 False 0 0
C theta_frame_printed bootstrap 98 103 1.3375 0.0053 0.0030 True 82 0 -0.0119 to 1.58
C theta_frame_continuous binomial 98 103 0.8578 0.3541 0.0015 True 102 0 -0.683 to 0.864
C theta_frame_continuous dkw 98 103 0.8578 0.3541 0.0015 False 0 0
C theta_frame_continuous bootstrap 98 103 0.8578 0.3541 0.0015 True 99 0 -0.683 to 0.851
C theta_binned_printed binomial 98 103 1.2919 -0.0218 0.0044 True 53 0 -0.0135 to 1.9
C theta_binned_printed dkw 98 103 1.2919 -0.0218 0.0044 False 0 0
C theta_binned_printed bootstrap 98 103 1.2919 -0.0218 0.0044 True 56 1 -0.0476 to 1.9
C theta_binned_continuous binomial 98 103 0.7989 0.3418 0.0042 True 113 0 -0.685 to 1.87
C theta_binned_continuous dkw 98 103 0.7989 0.3418 0.0042 False 0 0
C theta_binned_continuous bootstrap 98 103 0.7989 0.3418 0.0042 True 110 0 -0.685 to 1.87
C gain_frame_printed binomial 98 103 21.9367 23.2075 0.1175 False 0 0
C gain_frame_printed dkw 98 103 21.9367 23.2075 0.1175 False 0 0
C gain_frame_printed bootstrap 98 103 21.9367 23.2075 0.1175 False 0 0
C gain_frame_continuous binomial 98 103 33.0747 30.9363 0.0477 True 9 0 24.1 to 25.8
C gain_frame_continuous dkw 98 103 33.0747 30.9363 0.0477 False 0 0
C gain_frame_continuous bootstrap 98 103 33.0747 30.9363 0.0477 True 8 0 24 to 25.7
C gain_binned_printed binomial 98 103 19.8337 21.9816 0.0123 True 0 29 13.3 to 18.4
C gain_binned_printed dkw 98 103 19.8337 21.9816 0.0123 False 0 0
C gain_binned_printed bootstrap 98 103 19.8337 21.9816 0.0123 True 0 25 13.3 to 17.2
C gain_binned_continuous binomial 98 103 31.0752 29.2119 0.0311 True 23 0 22.9 to 41.5
C gain_binned_continuous dkw 98 103 31.0752 29.2119 0.0311 False 0 0
C gain_binned_continuous bootstrap 98 103 31.0752 29.2119 0.0311 True 23 0 22.7 to 41.5
16.6 um bars only:
recording measure ci n_mut n_ctl median_mut median_ctl ks_p separate mutant_larger_pts mutant_smaller_pts sep_range
A fwhm_svd binomial 148 122 125.1384 156.1976 0.0014 True 0 137 21.1 to 162
A fwhm_svd dkw 148 122 125.1384 156.1976 0.0014 False 0 0
A fwhm_svd bootstrap 148 122 125.1384 156.1976 0.0014 True 0 139 21.1 to 162
A fwhm_peak binomial 148 122 101.5605 150.7827 0.0000 True 0 210 21.8 to 169
A fwhm_peak dkw 148 122 101.5605 150.7827 0.0000 True 0 151 67.2 to 161
A fwhm_peak bootstrap 148 122 101.5605 150.7827 0.0000 True 0 210 21.8 to 169
A ttp_svd_frame binomial 148 122 0.1250 0.1084 0.0000 True 57 0 0.075 to 0.342
A ttp_svd_frame dkw 148 122 0.1250 0.1084 0.0000 True 29 0 0.0917 to 0.158
A ttp_svd_frame bootstrap 148 122 0.1250 0.1084 0.0000 True 57 0 0.075 to 0.342
A ttp_svd_parabolic binomial 148 122 0.1289 0.1111 0.0000 True 250 0 0.0816 to 0.342
A ttp_svd_parabolic dkw 148 122 0.1289 0.1111 0.0000 True 176 0 0.099 to 0.154
A ttp_svd_parabolic bootstrap 148 122 0.1289 0.1111 0.0000 True 250 0 0.0816 to 0.342
A ttp_peak_frame binomial 148 122 0.1250 0.1084 0.0000 True 46 0 0.0917 to 0.192
A ttp_peak_frame dkw 148 122 0.1250 0.1084 0.0000 True 24 0 0.0917 to 0.142
A ttp_peak_frame bootstrap 148 122 0.1250 0.1084 0.0000 True 47 0 0.0917 to 0.208
A ttp_peak_parabolic binomial 148 122 0.1252 0.1094 0.0000 True 246 0 0.0889 to 0.194
A ttp_peak_parabolic dkw 148 122 0.1252 0.1094 0.0000 True 153 0 0.101 to 0.141
A ttp_peak_parabolic bootstrap 148 122 0.1252 0.1094 0.0000 True 247 0 0.0889 to 0.202
A rate_hz binomial 148 122 3.4363 9.0175 0.0000 True 0 255 0.768 to 30.7
A rate_hz dkw 148 122 3.4363 9.0175 0.0000 True 0 146 2.27 to 14.6
A rate_hz bootstrap 148 122 3.4363 9.0175 0.0000 True 0 254 0.775 to 30.7
A theta_frame_printed binomial 148 122 1.6683 0.0072 0.0000 True 223 0 -2.25 to 2.2
A theta_frame_printed dkw 148 122 1.6683 0.0072 0.0000 True 81 0 0.00467 to 1.8
A theta_frame_printed bootstrap 148 122 1.6683 0.0072 0.0000 True 223 0 -2.26 to 2.19
A theta_frame_continuous binomial 148 122 1.1227 0.4360 0.0000 True 220 0 -0.816 to 1.58
A theta_frame_continuous dkw 148 122 1.1227 0.4360 0.0000 True 120 0 0.0434 to 1.2
A theta_frame_continuous bootstrap 148 122 1.1227 0.4360 0.0000 True 221 0 -0.844 to 1.58
A theta_binned_printed binomial 148 122 1.8128 -0.0226 0.0000 True 171 0 -1.73 to 1.86
A theta_binned_printed dkw 148 122 1.8128 -0.0226 0.0000 True 105 0 -0.0311 to 1.84
A theta_binned_printed bootstrap 148 122 1.8128 -0.0226 0.0000 True 173 0 -1.73 to 1.86
A theta_binned_continuous binomial 148 122 1.0099 0.4730 0.0000 True 248 0 -1.04 to 1.87
A theta_binned_continuous dkw 148 122 1.0099 0.4730 0.0000 True 125 0 0.0917 to 1.22
A theta_binned_continuous bootstrap 148 122 1.0099 0.4730 0.0000 True 246 0 -1.04 to 1.84
A gain_frame_printed binomial 148 122 17.7534 23.0846 0.0000 True 0 173 14.4 to 28.1
A gain_frame_printed dkw 148 122 17.7534 23.0846 0.0000 True 0 88 16 to 24.2
A gain_frame_printed bootstrap 148 122 17.7534 23.0846 0.0000 True 0 175 14.4 to 28.2
A gain_frame_continuous binomial 148 122 29.4974 30.7532 0.8479 True 0 1 57.6 to 57.6
A gain_frame_continuous dkw 148 122 29.4974 30.7532 0.8479 False 0 0
A gain_frame_continuous bootstrap 148 122 29.4974 30.7532 0.8479 False 0 0
A gain_binned_printed binomial 148 122 13.9245 21.1266 0.0000 True 0 216 6.37 to 27.9
A gain_binned_printed dkw 148 122 13.9245 21.1266 0.0000 True 0 118 12.5 to 22
A gain_binned_printed bootstrap 148 122 13.9245 21.1266 0.0000 True 0 217 5.9 to 28
A gain_binned_continuous binomial 148 122 29.6468 29.2195 0.5071 False 0 0
A gain_binned_continuous dkw 148 122 29.6468 29.2195 0.5071 False 0 0
A gain_binned_continuous bootstrap 148 122 29.6468 29.2195 0.5071 False 0 0
B fwhm_svd binomial 148 122 141.8281 156.1976 0.1207 True 0 1 87 to 87
B fwhm_svd dkw 148 122 141.8281 156.1976 0.1207 False 0 0
B fwhm_svd bootstrap 148 122 141.8281 156.1976 0.1207 True 0 3 87 to 100
B fwhm_peak binomial 148 122 112.7289 150.7827 0.0000 True 0 188 23.2 to 168
B fwhm_peak dkw 148 122 112.7289 150.7827 0.0000 True 0 87 98.4 to 153
B fwhm_peak bootstrap 148 122 112.7289 150.7827 0.0000 True 0 190 23.2 to 166
B ttp_svd_frame binomial 148 122 0.1250 0.1084 0.0000 True 51 0 0.0917 to 0.308
B ttp_svd_frame dkw 148 122 0.1250 0.1084 0.0000 True 27 0 0.0917 to 0.142
B ttp_svd_frame bootstrap 148 122 0.1250 0.1084 0.0000 True 50 0 0.0917 to 0.308
B ttp_svd_parabolic binomial 148 122 0.1245 0.1111 0.0000 True 242 0 0.0844 to 0.309
B ttp_svd_parabolic dkw 148 122 0.1245 0.1111 0.0000 True 161 0 0.099 to 0.144
B ttp_svd_parabolic bootstrap 148 122 0.1245 0.1111 0.0000 True 242 0 0.0844 to 0.309
B ttp_peak_frame binomial 148 122 0.1250 0.1084 0.0000 True 47 0 0.0917 to 0.192
B ttp_peak_frame dkw 148 122 0.1250 0.1084 0.0000 True 25 0 0.0917 to 0.142
B ttp_peak_frame bootstrap 148 122 0.1250 0.1084 0.0000 True 48 0 0.0917 to 0.208
B ttp_peak_parabolic binomial 148 122 0.1248 0.1094 0.0000 True 252 0 0.0789 to 0.194
B ttp_peak_parabolic dkw 148 122 0.1248 0.1094 0.0000 True 159 0 0.1 to 0.142
B ttp_peak_parabolic bootstrap 148 122 0.1248 0.1094 0.0000 True 252 0 0.0789 to 0.194
B rate_hz binomial 148 122 3.9628 9.0175 0.0000 True 0 248 0.775 to 30.7
B rate_hz dkw 148 122 3.9628 9.0175 0.0000 True 0 125 3.43 to 14.6
B rate_hz bootstrap 148 122 3.9628 9.0175 0.0000 True 0 250 0.768 to 30.7
B theta_frame_printed binomial 148 122 1.3341 0.0072 0.0009 True 121 0 -2.25 to 1.34
B theta_frame_printed dkw 148 122 1.3341 0.0072 0.0009 True 1 0 0.0122 to 0.0122
B theta_frame_printed bootstrap 148 122 1.3341 0.0072 0.0009 True 119 0 -2.26 to 1.34
B theta_frame_continuous binomial 148 122 0.8656 0.4360 0.0000 True 142 0 -0.816 to 0.851
B theta_frame_continuous dkw 148 122 0.8656 0.4360 0.0000 True 38 0 0.283 to 0.725
B theta_frame_continuous bootstrap 148 122 0.8656 0.4360 0.0000 True 144 0 -0.844 to 1.39
B theta_binned_printed binomial 148 122 1.2937 -0.0226 0.0008 True 111 0 -1.73 to 1.3
B theta_binned_printed dkw 148 122 1.2937 -0.0226 0.0008 True 1 0 -0.00694 to -0.00694
B theta_binned_printed bootstrap 148 122 1.2937 -0.0226 0.0008 True 109 0 -1.73 to 1.3
B theta_binned_continuous binomial 148 122 0.8014 0.4730 0.0000 True 151 0 -1.04 to 1.84
B theta_binned_continuous dkw 148 122 0.8014 0.4730 0.0000 True 31 0 0.232 to 0.638
B theta_binned_continuous bootstrap 148 122 0.8014 0.4730 0.0000 True 158 0 -1.04 to 1.84
B gain_frame_printed binomial 148 122 15.8546 23.0846 0.0000 True 0 218 7.49 to 28.1
B gain_frame_printed dkw 148 122 15.8546 23.0846 0.0000 True 0 117 14.2 to 24.2
B gain_frame_printed bootstrap 148 122 15.8546 23.0846 0.0000 True 0 218 7.49 to 28.1
B gain_frame_continuous binomial 148 122 28.3299 30.7532 0.0927 True 0 29 11.1 to 57.6
B gain_frame_continuous dkw 148 122 28.3299 30.7532 0.0927 False 0 0
B gain_frame_continuous bootstrap 148 122 28.3299 30.7532 0.0927 True 0 27 11.1 to 57.6
B gain_binned_printed binomial 148 122 13.7352 21.1266 0.0000 True 0 217 6.27 to 27.9
B gain_binned_printed dkw 148 122 13.7352 21.1266 0.0000 True 0 124 10.8 to 22
B gain_binned_printed bootstrap 148 122 13.7352 21.1266 0.0000 True 0 218 6.12 to 27.9
B gain_binned_continuous binomial 148 122 27.9099 29.2195 0.0260 True 0 64 10.2 to 22.1
B gain_binned_continuous dkw 148 122 27.9099 29.2195 0.0260 False 0 0
B gain_binned_continuous bootstrap 148 122 27.9099 29.2195 0.0260 True 0 63 10.2 to 22.1
C fwhm_svd binomial 148 122 125.1384 166.5035 0.0001 True 0 193 21.1 to 201
C fwhm_svd dkw 148 122 125.1384 166.5035 0.0001 True 0 42 98.6 to 163
C fwhm_svd bootstrap 148 122 125.1384 166.5035 0.0001 True 0 190 21.1 to 200
C fwhm_peak binomial 148 122 101.5605 153.3028 0.0000 True 0 220 28.6 to 253
C fwhm_peak dkw 148 122 101.5605 153.3028 0.0000 True 0 141 72.1 to 166
C fwhm_peak bootstrap 148 122 101.5605 153.3028 0.0000 True 0 224 29.2 to 253
C ttp_svd_frame binomial 148 122 0.1250 0.1084 0.0000 True 51 0 0.0917 to 0.225
C ttp_svd_frame dkw 148 122 0.1250 0.1084 0.0000 True 29 0 0.0917 to 0.158
C ttp_svd_frame bootstrap 148 122 0.1250 0.1084 0.0000 True 49 0 0.0917 to 0.208
C ttp_svd_parabolic binomial 148 122 0.1289 0.1118 0.0000 True 245 0 0.0846 to 0.228
C ttp_svd_parabolic dkw 148 122 0.1289 0.1118 0.0000 True 177 0 0.0998 to 0.154
C ttp_svd_parabolic bootstrap 148 122 0.1289 0.1118 0.0000 True 245 0 0.0846 to 0.228
C ttp_peak_frame binomial 148 122 0.1250 0.1084 0.0000 True 51 0 0.0917 to 0.242
C ttp_peak_frame dkw 148 122 0.1250 0.1084 0.0000 True 24 0 0.108 to 0.142
C ttp_peak_frame bootstrap 148 122 0.1250 0.1084 0.0000 True 51 0 0.0917 to 0.242
C ttp_peak_parabolic binomial 148 122 0.1252 0.1095 0.0000 True 255 0 0.09 to 0.243
C ttp_peak_parabolic dkw 148 122 0.1252 0.1095 0.0000 True 168 0 0.101 to 0.143
C ttp_peak_parabolic bootstrap 148 122 0.1252 0.1095 0.0000 True 255 0 0.09 to 0.243
C rate_hz binomial 148 122 3.4363 8.9467 0.0000 True 0 249 0.807 to 28.6
C rate_hz dkw 148 122 3.4363 8.9467 0.0000 True 0 146 2.55 to 14.6
C rate_hz bootstrap 148 122 3.4363 8.9467 0.0000 True 0 248 0.807 to 28.6
C theta_frame_printed binomial 148 122 1.6683 0.0074 0.0000 True 217 0 -2.27 to 2.18
C theta_frame_printed dkw 148 122 1.6683 0.0074 0.0000 True 88 0 0.00433 to 1.82
C theta_frame_printed bootstrap 148 122 1.6683 0.0074 0.0000 True 218 0 -2.27 to 2.18
C theta_frame_continuous binomial 148 122 1.1227 0.3828 0.0000 True 215 0 -0.713 to 1.55
C theta_frame_continuous dkw 148 122 1.1227 0.3828 0.0000 True 117 0 0.0434 to 1.2
C theta_frame_continuous bootstrap 148 122 1.1227 0.3828 0.0000 True 213 0 -0.818 to 1.55
C theta_binned_printed binomial 148 122 1.8128 -0.0176 0.0000 True 176 0 -0.0303 to 1.9
C theta_binned_printed dkw 148 122 1.8128 -0.0176 0.0000 True 79 0 -0.0135 to 1.84
C theta_binned_printed bootstrap 148 122 1.8128 -0.0176 0.0000 True 181 0 -0.0303 to 1.9
C theta_binned_continuous binomial 148 122 1.0099 0.3546 0.0000 True 245 0 -1.05 to 1.87
C theta_binned_continuous dkw 148 122 1.0099 0.3546 0.0000 True 129 0 0.0917 to 1.23
C theta_binned_continuous bootstrap 148 122 1.0099 0.3546 0.0000 True 246 0 -1.05 to 1.87
C gain_frame_printed binomial 148 122 17.7534 22.4145 0.0000 True 0 153 14.8 to 27.9
C gain_frame_printed dkw 148 122 17.7534 22.4145 0.0000 True 0 59 16.2 to 22.2
C gain_frame_printed bootstrap 148 122 17.7534 22.4145 0.0000 True 0 146 15 to 27.9
C gain_frame_continuous binomial 148 122 29.4974 29.2187 0.0927 True 9 1 13.5 to 57.6
C gain_frame_continuous dkw 148 122 29.4974 29.2187 0.0927 False 0 0
C gain_frame_continuous bootstrap 148 122 29.4974 29.2187 0.0927 True 9 1 13.5 to 57.6
C gain_binned_printed binomial 148 122 13.9245 20.8431 0.0000 True 0 206 6.58 to 27.4
C gain_binned_printed dkw 148 122 13.9245 20.8431 0.0000 True 0 104 13.2 to 21.6
C gain_binned_printed bootstrap 148 122 13.9245 20.8431 0.0000 True 0 205 6.58 to 27.6
C gain_binned_continuous binomial 148 122 29.6468 27.7145 0.1714 True 2 1 13.5 to 62.5
C gain_binned_continuous dkw 148 122 29.6468 27.7145 0.1714 False 0 0
C gain_binned_continuous bootstrap 148 122 29.6468 27.7145 0.1714 True 3 1 13.5 to 62.5
# The other two tested claims with the frames as deposited. fig9-cell-counts: units above each STA
# threshold (reading A). s3-receptive-field-surrounds: units meeting the rule, fewest over the 12 readings.
dep = cells[cells.reading.str.endswith("frames as deposited") & cells.group.isin(GROUPS)]
dA = dep[dep.reading == "A, frames as deposited"]
print(pd.DataFrame({"STA peak ratio above 1.5": dA[dA.peak_ratio > 1.5].groupby("group").size(),
"STA peak ratio above 2": dA[dA.peak_ratio > 2].groupby("group").size()}).to_string())
s3 = [{"recording": rd, "sep": sep, "depth": frac, "group": g, "meet": int(x[f"surround_{sep}_{frac}"].sum())}
for rd in ret1.READINGS for sep in ("svd", "peak") for frac in (10, 20) for g in GROUPS
for x in [dep[(dep.reading == f"{rd}, frames as deposited") & (dep.group == g)]]]
print(pd.DataFrame(s3).groupby("group").meet.agg(["min", "max"]).to_string())
print(f"Run time of the notebook: {(time.time() - started) / 60:.1f} min")
STA peak ratio above 1.5 STA peak ratio above 2
group
control 113 107
mutant 126 93
min max
group
control 16 106
mutant 89 186
Run time of the notebook: 9.3 min
With the 20080702 frames as deposited, every claim gives the outcome of the main analysis except fig9d-rf-size-similar, whose 18 combinations then all separate (not reproduced); fig9e gains 8 combinations with values both ways, and the continuous-form gains of fig9h separate in 4 of 18 (all with mutant gains lower) in place of 9. With the 16.6 um bars alone the outcomes of fig9d to fig9h are those of the main analysis. Among the cells with clear STAs, fig9d-rf-size-similar and fig9h-gain-reduced stay blocked and fig9e-slower-time-course stays reproduced, but fig9f-lower-firing-rate and fig9g-threshold-unaltered would be blocked: no DKW band separates. The claims file reads the groups as all units, so the outcomes are given on all units. The same STA threshold gives 103 mutant and 107 control cells, nearest the paper's counts, but the paper does not say it selected cells this way. With the frames as deposited 126 mutant and 113 control units have STA peaks above 1.5 times the null's, and both groups have units meeting the surround rule in every reading.
Summary¶
| Claim | Outcome |
|---|---|
| 15 histology claims (Figures 1 to 8, Supplementary Figure 1) | Blocked: data missing |
| fig9a-response-variety, fig9c-on-off-index, fig9-rod-cone, fig9b-direction-selective | Blocked: data missing |
| fig9-cell-counts: 115 mutant and 143 control cells | Not reproduced (200 and 122) |
| fig9d-rf-size-similar: centre size similar | Blocked: methods underspecified (17 of 18 combinations separate, mutant smaller) |
| s3-receptive-field-surrounds | Reproduced by the criterion; the rule is met by noise |
| fig9e-slower-time-course | Reproduced |
| fig9f-lower-firing-rate | Reproduced |
| fig9g-threshold-unaltered | Not reproduced (mutant higher) |
| fig9h-gain-reduced | Blocked: methods underspecified (the forms of the nonlinearity disagree) |
A failure to reproduce here may be a failure of this attempt, not of the paper: see the reasoning and the differences from the paper's method.
How the analysis differs from the paper's¶
- The groups are the data set's labels. They hold 200 mutant and 122 control units, where the paper has 115 and 143. The control retinas are mostly labelled "WT (chx10 het)", a genotype the paper does not list among its controls. The files do not say which region of the Pax6-Cre retinas was recorded, so the mutant group cannot be restricted to the periphery as the paper's was. The Bax -/- retina is left out, as the paper did not use Bax mutants for Figure 9.
- All units are used, as the claims file reads the legend's counts; the paper does not say whether it kept every unit. Many mutant units have weak or no receptive fields (STA peak below twice that of the null in 97 of 200 mutant units and 15 of 122 control units). Their noisy STAs give small centres, a high LN threshold and a low printed-form gain, and they carry much of the differences in Figure 9D, 9F, 9G and 9H. Among the units with STA peaks above twice the null's (103 mutant, 107 control under reading A), no DKW band separates for fig9f or fig9g, so on that subset both would be blocked; the outcomes of fig9f-lower-firing-rate and fig9g-threshold-unaltered depend on keeping every unit, as the claims file reads the groups. fig9e-slower-time-course holds on the subset, and fig9d and fig9h stay blocked.
- The stimulus of the two 20080702 vertical-bar recordings is rebuilt with the frame of the other bar recordings (16.6718 ms), not the stated one, as the frame scan shows; a variant keeps the stated frames. Under all three readings, it changes the outcome of fig9d-rf-size-similar only (with the stated frames all 18 of its combinations separate, which would give not reproduced), so that outcome rests on the correction and on one borderline DKW comparison.
- The paper does not say which bar recording is used. The claims file, after the question was answered, names three readings (A, B, C); all three were run. They agree on every outcome but that of fig9d-rf-size-similar, whose DKW band under reading B (svd) overlaps.
- The 95% bands are built in the three ways the claims file names, as the paper does not say how its bands were made. Under shuffled labels the two pointwise bands separate in about 35% of comparisons and the DKW band in none, so the criteria's "overlap under every reading" is hard to meet for any pair of groups of this size. The LN fit and the separation of h follow the claims file's readings.
- The mutant retinas include all 8.3 um bar recordings; all control retinas were stimulated with 16.6 um bars. With the 16.6 um recordings alone the outcomes of fig9d to fig9h are unchanged, though the svd DKW bands of fig9d then overlap under readings A and B, not only B.
What was found about the data set¶
- It holds only the white-noise part of Figure 9: none of the histology of Figures 1 to 8, and no flashing spots, flashes, moving bars or gratings (Figure 9A to 9C).
- Its unit counts (200 mutant, 122 control) and control genotypes differ from the paper's Figure 9 (115 and 143). The data set does not say how its units relate to the paper's.
- In the 8 recordings of four retinas (20080628_R4 and R6, 20080702_R1 and R4), 82 of 86 spike trains run to 1440 s and then hold a second segment between 720 and 780 s, so they are not sorted. This is consistent with their last minute (1440 to 1500 s) stored with a 720 s offset in place of 1440 s.
- The frame lengths stated for the vertical-bar recordings of 20080702_R1 and 20080702_R4 (16.6691 and 16.6653 ms) are not those of the stimulus. Rebuilt with them, the bars of 20080702_R4 give no STA in any of its 12 units; rebuilt with 16.6718 ms, the frame of every other bar recording and half the checkerboard frame of the same retinas, 10 of the 12 have STA peaks above twice the null's.
- 16 pairs of units share 70 to 100% of their spikes within 0.5 ms, most likely single neurons sorted twice.
- The files do not give the age, the Pcdh-gamma allele, the recorded region of the Pax6-Cre retinas, or which units are ganglion cells of which type.
ran1.binmatches the RAN1 generator ofran1.mwith seed -10000, read least significant bit first, and the description's table of retinas, cells and labels matches the files.