75 lines
5.7 KiB
Python
75 lines
5.7 KiB
Python
"""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+=['','','',
|
||
'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))
|