late_perceptual_significance.py notebook + Snakefile rule -> site_results.parquet + population headline
- Dominant language
- Jupyter Notebook
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
## Parent
Plan: `docs/superpowers/plans/2026-07-20-causal46-late-perceptual-significance.md` (Step 3 + Step 5 rule). The core vertical slice — end-to-end runnable via smoke snakemake.
## What to build
A new notebook `notebooks/causal46_joined/late_perceptual_significance.py` (Jupytext percent-format) plus a `late_perceptual_significance` Snakemake rule, that turns the persisted B4 bootstrap into a per-cell late within-completion percept significance test and a population-level headline.
Per cell over the **full 187 powered B4 cells** `(subject, electrode_idx, phoneme_pair, word_end)`:
- Build post-acoustic candidate windows: `smin >= phon_smax`, `smax <= round((OFFSET_DICT[we] + 0.1 - epoch_tmin) * epoch_sfreq)` (D4 — matches existing window logic).
- Form the observed curve (median over replicates of `mean_diff_raw` per window — two-tailed signed `/n/-/d/`, raw, D1) and the R coherent null curves (recovered signed `null_raw`, or `|.|` for two-tailed) from `b4_bootstrap.parquet`.
- Compute `tfce_max_abs`, two-tailed `tfce_emp_p` (max-TFCE null, via #9 helpers), the knob-free integral robustness stat/p (D3), and the optional split-half sign-agreement column (D7).
- Drop tied cells from the gate but keep them in the parquet with `is_tied=True` (D2).
- BH-FDR over the 187 `tfce_emp_p`; count-vs-null headline vs `Binomial(187, 0.05)` (D5). Same per-cell p-values feed both operating points — one pass.
- Join read-only `manual_behav_late` for later calibration use (D6).
Emits `outputs/causal46_joined/late_perceptual_significance/site_results.parquet` (schema per plan Outputs) and a basic `population_summary.pdf` carrying the count-vs-null headline + BH-FDR survivor count.
## Acceptance criteria
- [ ] `site_results.parquet` has one row per powered B4 cell with all columns in the plan's Outputs schema (`tfce_peak`, `tfce_max_abs`, `tfce_emp_p`, `tfce_gate_pass`, `tfce_p_fdr`, `tfce_fdr_pass`, `integral_stat`, `integral_emp_p`, `splithalf_sign_agree`, `is_tied`, `manual_behav_late`, window bounds).
- [ ] Grid validated (contiguous, stride == window_size) reusing existing assertions; per-cell row-count == R x n_windows asserted.
- [ ] Population headline computed: count with uncorrected TFCE p<0.05 vs Binomial(187, 0.05), plus BH-FDR survivor count. Family = 187, not 84.
- [ ] `late_perceptual_significance` Snakemake rule added (inputs `b4_bootstrap.parquet`, `b4_per_cell.parquet`; outputs the parquet + PDF); notebook params match the Snakefile `run_notebook`.
- [ ] Runs clean end-to-end under the smoke config: `CONFIG_FILE=config.smoke.yaml uv run snakemake --configfile config.smoke.yaml -j1` (via `uv run`; `snakemake -n` dry-run clean).
## Blocked by
- #8 (tied-cell audit — confirms the null is usable / drop-and-document)
- #9 (TFCE + max-null helpers in `_windows.py`)
Contributor guide
No contributing guide indexed for this repository
Research direction
Read the parent plan and inspect the existing B4 inputs, #8 tied-cell audit, and #9 helpers before starting. Add notebooks/causal46_joined/late_perceptual_significance.py and the matching Snakefile rule using b4_bootstrap.parquet and b4_per_cell.parquet. Done means the parquet and population_summary.pdf are produced and the smoke Snakemake command completes cleanly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- jupyter-notebook, python
- Domain
- build-system, data
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100