"""Preregistered independent fixed-US stability test. Frozen brain, no learning.""" from pathlib import Path import argparse import json import time import numpy as np import pandas as pd import torch import yaml import phase4p import phase4p_finalize import phase4s from phase4p_revalidate import DeterministicAPLSim,door_inputs,make_drive from phase4r import save,digest,arrhash,curves from phase4q import last_spike_trace,v2_trace,edge_elig from phase4h_audit import verify_checksum def checks(cfg): sc=yaml.safe_load((Path(cfg['source_model'])/'phase4s.yaml').read_text()) out=phase4s.checks(sc) for key in ('source_root','source_model'): root=Path(cfg[key]);out[key]=verify_checksum(root,root/'checksums.sha256') assert all(x['passed'] for x in out.values()) return out def gate(rows,cfg,w,u): f=pd.DataFrame(rows);f=f[(f.window_ms==w)&(f.US_ms==u)];out=[] for odor,g in f.groupby('odor_id',sort=True): den=float(g.random_expectation.mean());rat=float(g.matched.mean()/den) if den else None q=float(np.quantile(g.ratio,0.2));n=int((g.ratio>=cfg['timing_gate']['ratio']).sum()) out.append({'odor_id':odor,'n':len(g),'qualifying':n,'ratio_of_means':rat,'q20_ratio':q, 'zero_credit':int((g.matched==0).sum()),'mean_credit':float(g.matched.mean()), 'pass':bool(den>0 and rat>=cfg['timing_gate']['mean_ratio_each_odor'] and n/len(g)>=cfg['timing_gate']['qualifying_fraction_each_odor'])}) return {'window_ms':int(w),'US_ms':int(u),'tau_ms':float(w/3),'odors':out, 'score':min(x['q20_ratio'] for x in out),'pass':bool(out and all(x['pass'] for x in out))} def controls(w,u,dt,root): lookup=np.arange(3,dtype=np.int32);us=round(u/dt);tau=w/3 def calc(ss,nn,gate=us):return last_spike_trace(np.array(ss,np.int32),np.array(nn,np.int32),lookup,gate,w,tau,dt)[0] recent=calc([us-1],[0]);future=calc([us+1],[0]);old=calc([0],[0],round((w+10)/dt)) unrelated=edge_elig(recent,np.array([0,1,2]),np.zeros(3,bool)) d0=edge_elig(recent,np.array([0,1,2]),np.ones(3,bool),teaching=False) base=calc([us-1,us],[0,1]);shift=last_spike_trace(np.array([us+17,us+18]),np.array([0,1]),lookup,us+18,w,tau,dt)[0] path=root/'trace-checkpoint.npz';np.savez(path,trace=base) tests={'recent_positive':bool(recent[0]>0),'inactive_zero':bool(recent[1]==0), 'future_zero':bool(not future.any()),'distant_zero':bool(not old.any()), 'unrelated_zero':bool(not unrelated.any()),'D0_zero':bool(not d0.any()), 'same_step_one':bool(base[1]==1),'both_arrivals_shift_exact':bool(np.array_equal(base,shift)), 'disk_checkpoint_exact':bool(np.array_equal(base,np.load(path)['trace'])), 'repeated_algebra_exact':all(np.array_equal(base,calc([us-1,us],[0,1])) for _ in range(10))} save(root/'unit-tests.json',{'scope':'Algebraic controls; not physiological simulations','tests':tests,'pass':all(tests.values())}) assert all(tests.values()) def run(cfg,exp,model): for d in ('protocol','calibration','validation','events','regression','performance'):(exp/d).mkdir(parents=True,exist_ok=True) assert not (exp/'protocol/preregistered.json').exists(),'Refusing overwrite' audit=json.loads((exp/'audit/summary.json').read_text());assert audit['all_zero_trials_explained_by_event_timing'] pre=checks(cfg);save(exp/'protocol/preflight.json',pre) ocfg,panel,vectors,selection,mapping=door_inputs() cal=panel[panel.split=='calibration'].iloc[:2] formal={selection['ODOR_A']['odor_id'],selection['ODOR_B']['odor_id']} novel=panel[(panel.split=='heldout')&~panel.odor_id.isin(formal)] assert len(cal)==2 and len(novel)==4 and not set(cal.odor_id)&set(novel.odor_id) odors=pd.concat([cal,novel]).reset_index(drop=True) seedsets=[{int(s)+i*cfg['odor_seed_offset'] for i in range(len(odors)) for s in cfg[k]} for k in ('calibration_seeds','validation_seeds')] assert seedsets[0].isdisjoint(seedsets[1]) prereg={'config':cfg,'odors':odors[['odor_id','odor_name','split']].to_dict('records'), 'created_before_new_simulations':True,'sources':{p.name:digest(p) for p in model.glob('phase4t*') if p.is_file()}, 'historical_4S_used_only_for_hypothesis':True,'new_heldout_not_used_for_selection':True} save(exp/'protocol/preregistered.json',prereg) pcfg=yaml.safe_load((Path(cfg['runtime_root'])/'phase4p.yaml').read_text()) rt=phase4p.CanonicalRuntime(pcfg,Path(cfg['runtime_root']),exp);sim=DeterministicAPLSim(rt) lookup=np.full(sim.n,-1,np.int32);lookup[sim.kc]=np.arange(len(sim.kc)) identity=sim.identity;assert len(identity)==14232 target=identity.compartment.eq(cfg['target_compartment']).to_numpy() loc=lookup[identity.source_neuron_idx.to_numpy()] multi=np.bincount(loc[target],minlength=len(sim.kc)).astype(np.float32) duration=cfg['duration_ms'];nsteps=round(duration/sim.dt);dan=sim.dan_targets(cfg['matched_DAN'],cfg['target_compartment']) start=time.perf_counter();torch.cuda.reset_peak_memory_stats();records=[];live=[];repeats=[] def trial(oi,seed,split,ws,us): odor=odors.iloc[oi];t,rates=make_drive(ocfg,panel,vectors,selection,mapping,odor.odor_id,'physiological') actual=seed+oi*cfg['odor_seed_offset'] r=sim.run(t,rates,actual,duration,collect_events=True);assert r['finite'] phase4s.persist_run(exp,f'{split}-{oi}-{seed}',r) c=curves(r,lookup,multi,ws,sim.dt,nsteps) for wi,w in enumerate(ws): den=float(c[wi].mean()) for u in us: m=float(c[wi][round(u/sim.dt)]) records.append({'split':split,'odor_id':odor.odor_id,'odor_index':oi,'seed':seed,'actual_seed':actual, 'window_ms':w,'US_ms':u,'matched':m,'random_expectation':den,'ratio':m/den if den else 0.}) return r,t,rates,actual for oi in range(len(cal)): for seed in cfg['calibration_seeds']:trial(oi,seed,'calibration',cfg['windows_ms'],cfg['candidate_US_ms']) print(json.dumps({'stage':'calibration','odor_index':oi,'seeds':len(cfg['calibration_seeds'])}),flush=True) grid=[gate(records,cfg,w,u) for w in cfg['windows_ms'] for u in cfg['candidate_US_ms']] good=[x for x in grid if x['pass']] chosen=sorted(good,key=lambda x:(-x['score'],x['window_ms'],x['US_ms']))[0] if good else None pd.DataFrame(records).to_parquet(exp/'calibration/grid.parquet',index=False) save(exp/'calibration/selection.json',{'grid':grid,'chosen':chosen,'selected_before_validation':True}) print(json.dumps({'selected':chosen}),flush=True) summary={'phase':'4T','P0_diagnosis_pass':True,'calibration':chosen,'seed_validation':None,'odor_validation':None, 'timing_gate_pass':False,'credit_specificity_pass':False,'formal_training_run':False,'memory_claim':False} if chosen: w=chosen['window_ms'];u=chosen['US_ms'];us=round(u/sim.dt);controls(w,u,sim.dt,exp/'regression') for oi in range(len(odors)): split='seed_validation' if oi