Files
digital-drosophila/models/male-cns-lif/timing-stability-v1/timing_stability_diagnostics.py
T

37 lines
2.2 KiB
Python

"""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))