"""Summarize measured Phase 4R results; does not run or alter the brain.""" from pathlib import Path import json import pandas as pd import numpy as np root=Path('/data/digital-drosophila/experiments/phase4r-timing-audit') read=lambda p:json.loads((root/p).read_text()) r=read('audit/results.json') f=pd.read_parquet(root/'fixed-event/ratios.parquet') h=pd.read_parquet(root/'timing/KC-histograms.parquet') e=pd.read_parquet(root/'network-effects/credit-decomposition.parquet') ages=pd.read_parquet(root/'timing/edge-age-at-90ms.parquet') timing=[] for (split,label),g in h[h.condition=='no_external_US'].groupby(['split','label']): hist=g.groupby('start_ms').compartment_source_spikes.mean() a=ages[(ages.split==split)&(ages.label==label)&(ages.window_ms==5)] valid=a.age_at_US_ms.dropna() timing.append({'split':split,'label':label,'peak_bin_start_ms':float(hist.idxmax()), 'peak_spikes_per_5ms':float(hist.max()),'spikes_85_90ms':float(hist.get(85,0)), 'fraction_events_first30ms':float(hist[hist.index<30].sum()/hist.sum()), 'median_last_spike_age_at_US_ms_edge_weighted':float(valid.median()) if len(valid) else None, 'p10_last_spike_age_ms':float(valid.quantile(.1)) if len(valid) else None, 'fraction_edges_recent_20ms':float((a.age_at_US_ms<=20).mean())}) paired=[] for (split,condition,w),g in e.groupby(['split','condition','window_ms']): paired.append({'split':split,'condition':condition,'window_ms':int(w), 'changed_event_streams':int((~g.KC_event_stream_exact_vs_noUS).sum()),'trials':len(g), 'mean_absolute_feedback_credit':float(g.network_feedback_credit_difference.abs().mean()), 'max_absolute_feedback_credit':float(g.network_feedback_credit_difference.abs().max()), 'mean_KC_count_L1':float(g.KC_count_L1_vs_noUS.mean())}) q=read('regression/phase4q-reproduction.json');rr=read('regression/full-runtime-10-repeat.json');fr=read('regression/five-frozen-trials.json') ratios=pd.DataFrame(r['same_event_ratios']);held=ratios[ratios.split=='heldout'] notes=[ 'Phase 4Q failure reproduced only for its declared timing protocol; it is not evidence against all local credit rules.', 'Early target-KC activity and late 90ms reinforcement are measured associations. No APL ablation was authorized, so APL causation remains unresolved.', 'The exact uniform-time expectations remove random-US sampling noise on the same KC event stream.', 'US=0..120ms versus 30..110ms is a protocol difference, not an event-energy mismatch. Both use one forced spike per selected DAN.', 'The same 1.8ms delay on KC and DAN leaves relative timing unchanged. Counting only KC arrival is a different gate convention.', 'Pre-existing Phase 4Q controls were offline algebraic tests. This audit adds recorded events, disk checkpoint restoration, real full-runtime repeats and frozen reference comparisons.', 'No timing/eligibility candidate was selected. Independent heldout seeds replicate diagnosis; heldout odor generalization was not tested.' ] out={'status':'COMPLETED-DIAGNOSTIC-NO-CANDIDATE','timing':timing,'fixed_event_ratios':r['same_event_ratios'], 'paired_network_effects':paired,'phase4q_reproduced_exact':q['all_event_and_credit_exact'], 'full_runtime_ten_repeats_exact':rr['all_exact'],'five_reference_trials_two_repeats_exact':fr['all_exact'], 'symmetric_delay_exact':r['symmetric_delay_exact'],'interpretation_limits':notes, 'heldout_all_windows_ratio_below_one_Q':bool((held.ratio_Q<1).all()), 'heldout_all_windows_ratio_below_one_N':bool((held.ratio_N<1).all()), 'candidate_generated':False,'training_run':False,'next_phase_started':False, 'performance':read('performance/summary.json')} out['mechanism_labels']=['KC-US-TIMING-MISMATCH-SUPPORTED','RANDOM-TIMING-DISTRIBUTION-EFFECT-CONFIRMED', 'CURRENT-GATE-CREDIT-UNCHANGED-BY-DAN-FEEDBACK','FROZEN-RUNTIME-REGRESSION-PASS'] out['next_step']='Pre-register stimulus and reinforcement timing using independent calibration data; keep brain and learning magnitude frozen. Do not select an optimum from heldout results.' out['important_qualification']='Heldout 5ms/10ms credit exceeds the narrower random-N expectation (2.649x/1.338x), but calibration does not replicate this and all ratios remain below the prior 3x gate.' controls=read('regression/offline-controls.json') out['offline_controls_all_pass']=all(all(v for k,v in row.items() if k!='window_ms') for row in controls['rows']) (root/'audit/mechanism-summary.json').write_text(json.dumps(out,indent=2,sort_keys=True)+'\n') lines=['# Phase 4R — KC–US timing audit','', 'Status: COMPLETED-DIAGNOSTIC-NO-CANDIDATE. No training, new timing selection, weight update or next phase.','', '## Fixed-event matched/random ratio','', '| Seed split | Window (ms) | Random [0,120) | Random [30,110] |', '|---|---:|---:|---:|'] for x in r['same_event_ratios']: lines.append(f"| {x['split']} | {x['window_ms']} | {x['ratio_Q']:.6f} | {x['ratio_N']:.6f} |") lines+=['','## Actual target-compartment KC timing',''] for x in timing:lines.append('- '+json.dumps(x)) lines+=['','## Verification','',f"- Phase 4Q events and credit reproduced: {out['phase4q_reproduced_exact']}", f"- Ten full-runtime repeat runs exact: {rr['all_exact']}",f"- Five frozen trials, two repeats each: {fr['all_exact']}", f"- Equal delay on both pathways preserves relative timing: {r['symmetric_delay_exact']}",'', '## Interpretation and limits','']+['- '+x for x in notes]+['- '+out['important_qualification']] lines+=['','![Timing audit](../figures/timing-audit.png)','', 'Final integrity verification is recorded separately in audit/frozen-integrity.json and the root checksums.sha256.'] (root/'audit/REPORT.md').write_text('\n'.join(lines)+'\n') print(json.dumps(out,indent=2))