"""Descriptive validation failures only. No new timing selection or simulation.""" from pathlib import Path import json import numpy as np import pandas as pd root=Path('/data/digital-drosophila/experiments/phase4t-timing-stability') source=Path('/data/digital-drosophila/experiments/phase4s-timing-credit') prereg=json.loads((root/'protocol/preregistered.json').read_text()) gate=json.loads((root/'validation/summary.json').read_text()) identity=pd.read_parquet(source/'protocol/frozen-edge-identity.parquet') mask=identity[identity.compartment.eq(prereg['config']['target_compartment'])] multi=mask.groupby('source_neuron_idx').size() us=round(gate['calibration']['US_ms']/.1);window=round(gate['calibration']['window_ms']/.1) rows=[] for record in pd.read_parquet(root/'validation/results.parquet').to_dict('records'): tag=f"{record['split']}-{record['odor_index']}-{record['seed']}" e=pd.read_parquet(root/'events'/f'{tag}.parquet') t=e[e.neuron_idx.isin(multi.index)] s=t.step.to_numpy();recent=t[t.step.between(us-window,us)] past=s[s<=us];after=s[s>us] rows.append({**record,'odor_name':prereg['odors'][record['odor_index']]['odor_name'], 'meets_ratio':bool(record['ratio']>=prereg['config']['timing_gate']['ratio']), 'target_active_KC':int(t.neuron_idx.nunique()),'target_spikes':len(t), 'first_target_ms':float(s.min()*.1) if len(s) else None, 'last_before_US_ms':float(past.max()*.1) if len(past) else None, 'first_after_US_ms':float(after.min()*.1) if len(after) else None, 'gate_active_KC':int(recent.neuron_idx.nunique()),'gate_spikes':len(recent), 'fraction_target_events_after_US':float((s>us).mean()) if len(s) else None}) pd.DataFrame(rows).to_parquet(root/'validation/descriptive-event-diagnosis.parquet',index=False) summary={'scope':'Post-validation descriptive only, no selection/retest', 'low_ratio_trials':[x for x in rows if not x['meets_ratio']], 'limitations':['Ratio failure may reflect small numerator and/or denominator changes.', 'No APL/circuit causation inferred; no new candidate timing selected.']} (root/'validation/descriptive-event-diagnosis.json').write_text(json.dumps(summary,indent=2,allow_nan=False)+'\n') print(json.dumps(summary,indent=2))