Files
digital-drosophila/models/male-cns-lif/mb-credit-transfer-audit-v1/prepare.py
T
2026-09-30 13:58:39 +08:00

137 lines
9.6 KiB
Python

"""Preregister all AK trials before credit/MBON outcomes; never train."""
from datetime import datetime, timezone
import platform
import shutil
import subprocess
import sys
import numpy as np
import pandas as pd
import yaml
from context import (ROOT, MODEL, EXP, AK, H, AG, META, CORE, COEFF, CFG, PINS,
read, save, digest, sources, integrity, write_npz)
def main():
assert not EXP.exists() or (EXP.is_dir() and not any(EXP.iterdir())), 'Populated experiment exists: preserve it, do not regenerate'
assert shutil.disk_usage(EXP.parent).free > CFG['output_budget_bytes'] + 10 * 1024**3
for relative, expected in PINS.items():
assert digest(ROOT / relative) == expected, relative
assert read(AK / 'audit/final-status.json')['status'] == 'PASS-FROZEN-D18-INDEPENDENT-VALIDATION'
assert not CFG['training'] and not CFG['candidate_generation']
jc = yaml.safe_load((ROOT / 'models/male-cns-lif/mb-physiology-v1/phase4j.yaml').read_text())
j = jc['eligibility_v2']
assert j['kc_trace_tau_ms'] == CFG['kc_trace_tau_ms'] and j['trace_cap'] == CFG['trace_cap']
assert j['max_fractional_depression'] == CFG['conditional_depression_fraction'] == .25
assert jc['direct_kc']['dan_time_ms'] / CFG['dt_ms'] == CFG['virtual_gate_tick']
inventory = read(AK / 'protocol/validation-cases.json')
assert len(inventory) == CFG['primary_trials']
seeds = sorted({r['seed'] for r in inventory})
assert len(seeds) == 5
planned = []
for row in inventory:
for repeat in (0, 1) if row['seed'] == seeds[0] else (0,):
planned.append(dict(row, repeat=repeat))
assert len(planned) == CFG['primary_trials'] + CFG['technical_repeats']
inputs = dict(PINS)
h_manifest = {line.split(' ', 1)[1]: line.split(' ', 1)[0]
for line in (H / 'manifests/checksums.sha256').read_text().splitlines()}
static_h = ('plastic-mask/plastic-edge-candidates.parquet', 'plastic-mask/plastic-edge-ids.int64.npy',
'plastic-mask/plastic-edge-mask.bool.npy', 'mappings/dan-to-mbon-confirmed.parquet',
'mappings/mbon-to-compartment.parquet', 'mappings/kc-to-mbon-actual-edges.parquet')
for rel in static_h:
assert digest(H / rel) == h_manifest[rel]
inputs[(H / rel).relative_to(ROOT).as_posix()] = h_manifest[rel]
for row in planned:
case = AK / 'cases' / row['cohort'] / row['name']
trial = AK / 'gpu' / row['cohort'] / (row['name'] + '-r' + str(row['repeat']))
for p in (case / 'spec.json', case / 'requests.npz', trial / 'state.npz', trial / 'summary.json'):
inputs[p.relative_to(ROOT).as_posix()] = digest(p)
paths = [COEFF] + list((AG / 'graphs/full').glob('*.npy')) + list((AG / 'apl-bundle').glob('*.npy'))
raw_path = ROOT / 'datasets/male-cns-v1.0/processed/neuron-only/gpu/csr-weights.int64.npy'
for p in paths + [raw_path]:
inputs[p.relative_to(ROOT).as_posix()] = digest(p)
for name in ('protocol', 'trials', 'audit', 'regression', 'logs', 'pairs'):
(EXP / name).mkdir(parents=True, exist_ok=False)
test = subprocess.run([sys.executable, '-B', '-m', 'unittest', 'discover', '-v', '-s', str(MODEL)],
cwd=MODEL, text=True, capture_output=True)
with (EXP / 'regression/unit-tests.log').open('x', encoding='utf-8') as f:
f.write(test.stdout + test.stderr)
assert test.returncode == 0, 'Unit tests failed; preserve incomplete experiment'
assert 'skipped=' not in test.stderr, 'Server arithmetic comparison must not be skipped'
save(EXP / 'protocol/preregistered.json', dict(timestamp_utc=datetime.now(timezone.utc).isoformat(),
sources=sources(), config=CFG, inputs=[dict(path=k, sha256=v) for k, v in sorted(inputs.items())],
parent_commit=subprocess.check_output(['git', '-C', str(ROOT), 'rev-parse', 'HEAD'], text=True).strip(),
planned=planned, prior_AK_representation_known=True, before_new_credit_and_MBON_outcomes=True,
training=False, learning_achieved=False, virtual_gate_is_dopamine_measurement=False,
MBON_recurrent_and_all_other_presynaptic_events_clamped=True,
expected_functional_effect_not_a_preregistered_learning_gate=True,
python=sys.version, platform=platform.platform(), numpy=np.__version__))
save(EXP / 'regression/old-integrity-before.json', integrity())
meta = pd.read_parquet(META).sort_values('neuron_idx').reset_index(drop=True)
assert np.array_equal(meta.neuron_idx, np.arange(CFG['neurons'], dtype=np.int32))
kc = np.flatnonzero(meta.annotation_class.eq('Kenyon_Cell')).astype(np.int32)
mbon = np.flatnonzero(meta.annotation_class.eq('MBON')).astype(np.int32)
apl = np.flatnonzero(meta.annotation_type.eq('APL')).astype(np.int32)
assert len(kc) == 4064 and len(mbon) == 97
assert np.array_equal(kc, np.load(AG / 'apl-bundle/kc_globals.npy'))
assert np.array_equal(apl, np.load(AG / 'apl-bundle/apl_globals.npy'))
folder = AG / 'graphs/full'
arrays = {k: np.load(folder / (k + '.npy'), mmap_mode='r') for k in ('nodes', 'src', 'dst', 'edge_id', 'weights')}
assert np.array_equal(arrays['nodes'], np.arange(CFG['neurons'], dtype=np.int32))
assert np.array_equal(arrays['edge_id'], np.arange(CFG['edges'], dtype=np.int64))
raw = np.load(raw_path, mmap_mode='r')
candidate = pd.read_parquet(H / static_h[0])
ids = np.load(H / static_h[1]); mask = np.load(H / static_h[2])
assert ids.dtype == np.int64 and ids.shape == (CFG['candidate_edges'],)
assert np.array_equal(candidate.edge_id, ids) and np.array_equal(np.flatnonzero(mask), ids)
for prefix, key in (('source', 'src'), ('target', 'dst')):
assert np.array_equal(candidate[prefix + '_neuron_idx'], arrays[key][ids])
assert np.array_equal(candidate[prefix + '_body_id'], meta.iloc[arrays[key][ids]].body_id)
assert np.array_equal(candidate.raw_synapse_count, raw[ids])
assert np.isin(candidate.source_neuron_idx, kc).all() and np.isin(candidate.target_neuron_idx, mbon).all()
assert (candidate.plasticity_polarity == -1).all() and candidate.target_compartment_verbatim.notna().all()
confirmed = pd.read_parquet(H / static_h[3])
assert confirmed.exact_compartment_match.all()
assert np.array_equal(confirmed.source_compartment_verbatim, confirmed.target_compartment_verbatim)
for row in confirmed.itertuples():
assert arrays['src'][row.edge_id] == row.source_neuron_idx and arrays['dst'][row.edge_id] == row.target_neuron_idx
assert raw[row.edge_id] == row.raw_synapse_count and meta.iloc[row.source_neuron_idx].annotation_class == 'DAN'
assert set(candidate.target_neuron_idx).issubset(set(confirmed.target_neuron_idx))
compartments = pd.read_parquet(H / static_h[4]).sort_values('neuron_idx').reset_index(drop=True)
assert np.array_equal(compartments.neuron_idx, mbon)
compartments.to_parquet(EXP / 'protocol/mbon-metadata.parquet', index=False)
candidate.to_parquet(EXP / 'protocol/candidate-static.parquet', index=False)
lookup = np.full(CFG['neurons'], -1, np.int32); lookup[mbon] = np.arange(len(mbon), dtype=np.int32)
selected = np.flatnonzero(lookup[arrays['dst']] >= 0)
src, dst = arrays['src'][selected], lookup[arrays['dst'][selected]]
weights = arrays['weights'][selected].copy()
assert weights.dtype == np.float64 and raw.dtype == np.int64
weights[np.isin(src, apl)] = 0.0
is_candidate = mask[selected]
assert int(is_candidate.sum()) == CFG['candidate_edges'] and (weights[is_candidate] > 0).all()
groups = np.full(len(selected), CFG['groups'].index('other'), np.int32)
for name, chosen in (('nonplastic_KC', np.isin(src, kc)), ('DAN', meta.iloc[src].annotation_class.eq('DAN').to_numpy()),
('MBON', np.isin(src, mbon)), ('APL', np.isin(src, apl)), ('plastic_KC', is_candidate)):
groups[chosen] = CFG['groups'].index(name)
kcall = pd.read_parquet(H / static_h[5])
assert np.array_equal(selected[np.isin(src, kc)], kcall.edge_id.to_numpy())
assert np.array_equal(raw[kcall.edge_id.to_numpy()], kcall.raw_synapse_count.to_numpy())
write_npz(EXP / 'protocol/incoming.npz', src_global=src, dst_local=dst, edge_id=selected.astype(np.int64),
weights=weights, raw_contacts=raw[selected], groups=groups, is_candidate=is_candidate,
targets=mbon, kc_globals=kc, edge_source_local=np.searchsorted(kc, candidate.source_neuron_idx).astype(np.int32))
save(EXP / 'protocol/graph-audit.json', dict(neurons=len(meta), all_edges=CFG['edges'], KC=len(kc), MBON=len(mbon),
all_MBON_incoming_edges=len(selected), all_KC_MBON_edges=len(kcall), candidate_edges=len(ids),
candidate_targets=int(candidate.target_neuron_idx.nunique()), confirmed_DAN_MBON_edges=len(confirmed),
compartments={str(c): dict(edges=len(g), targets=int(g.target_neuron_idx.nunique()), sources=int(g.source_neuron_idx.nunique()))
for c, g in candidate.groupby('target_compartment_verbatim')},
fast_APL_incoming_edges_zeroed=int(np.isin(src, apl).sum()), groups={name: int((groups == i).sum()) for i, name in enumerate(CFG['groups'])},
mask_all_edges_identity_verified=True, mapping_basis='Frozen explicit annotation token + real DAN-to-MBON edge; not synapse ROI',
feedback_neuron_class_not_inferred=True, weight_units='float64 SI volts; not measured conductance'))
save(EXP / 'protocol/prepared-hashes.json', [dict(path=p.relative_to(EXP).as_posix(), bytes=p.stat().st_size, sha256=digest(p))
for p in sorted((EXP / 'protocol').iterdir()) if p.is_file() and p.name != 'prepared-hashes.json'])
print('PREREGISTERED 120 primary +24 repeats; static edge identities validated; no new trajectory or training', flush=True)
if __name__ == '__main__':
main()