Files
digital-drosophila/models/male-cns-lif/terminal-scope-diagnostic-v1/diagnostic.py
T
2026-09-30 00:27:22 +08:00

370 lines
28 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""New-path-only Phase 4AB scope diagnostics; never edits frozen scientific files."""
import argparse
from datetime import datetime, timezone
import json
import os
from pathlib import Path
import subprocess
import sys
import time
import urllib.request
import numpy as np
import pandas as pd
import yaml
from scope import contact_scope, edge_ids_for_pairs, blocked_weights
def load_context():
cfg = yaml.safe_load(Path(__file__).with_name('config.yaml').read_text())
root = Path(cfg['root']); model = root/cfg['model']; exp = root/cfg['experiment']
sys.path.insert(0, str(root/cfg['prior_model']))
from audit import save, digest, immutable_check, seal
return cfg, root, model, exp, save, digest, immutable_check, seal
def manifest_check(folder, digest):
manifest = folder/'manifest.json'
rows = json.loads(manifest.read_text())['files']
bad = []
for row in rows:
path = folder/row['path']
if not path.is_file() or path.stat().st_size != row['bytes'] or digest(path) != row['sha256']:
bad.append(row['path'])
return {'pass': not bad, 'checked': len(rows), 'mismatches': bad,
'manifest_sha256': digest(manifest), 'checksums_sha256': digest(folder/'checksums.sha256')}
def integrity(cfg, root, digest, immutable_check):
result = {'original': immutable_check(root, root/cfg['snapshot'], cfg['workers'])}
for key in ('prior_model', 'prior_experiment'):
result[key] = manifest_check(root/cfg[key], digest)
assert all(x['pass'] for x in result.values()), result
return result
def queues():
out = []
for port in (8188, 8189, 8190):
with urllib.request.urlopen(f'http://192.168.10.51:{port}/queue', timeout=5) as r:
q = json.load(r)
out.append({'port': port, 'running': len(q['queue_running']), 'pending': len(q['queue_pending'])})
assert all(x['running'] == x['pending'] == 0 for x in out), 'ComfyUI busy: defer, never evict'
return out
def prepare():
cfg, root, model, exp, save, digest, immutable_check, _ = load_context()
assert exp.parent == root/'experiments' and model.parent == root/'models/male-cns-lif'
if exp.exists() and any(exp.iterdir()): raise RuntimeError('Refusing nonempty experiment')
exp.mkdir(exist_ok=True)
for d in ('protocol', 'audit', 'masks', 'events', 'states', 'observations', 'requests', 'replay', 'regression', 'performance'):
(exp/d).mkdir()
save(exp/'protocol/preregistered.json', {'config': cfg, 'before_analysis': True,
'timestamp_utc': datetime.now(timezone.utc).isoformat(),
'parent_commit': subprocess.check_output(['git', '-C', str(root), 'rev-parse', 'HEAD'], text=True).strip(),
'source_hashes': {p.name: digest(p) for p in sorted(model.iterdir()) if p.is_file()}})
save(exp/'regression/preflight.json', integrity(cfg, root, digest, immutable_check))
can = root/cfg['canonical']; prior = root/cfg['prior_experiment']
m = pd.read_parquet(can/'neuron-index/unified-metadata.parquet').sort_values('neuron_idx').reset_index(drop=True)
ptr = np.load(can/'gpu/csr-indptr.int64.npy', mmap_mode='r')
dst = np.load(can/'gpu/csr-indices.int32.npy', mmap_mode='r')
raw = np.load(can/'gpu/csr-weights.int64.npy', mmap_mode='r')
assert len(m) == 166700 and len(dst) == 25582938 and int(raw.sum()) == 124177617
assert m.body_id.dtype == np.uint64 and np.array_equal(m.neuron_idx, np.arange(len(m)))
src = np.repeat(np.arange(len(m), dtype=np.int32), np.diff(ptr))
apl = np.flatnonzero(m.annotation_type.eq('APL')); pn = np.flatnonzero(m.annotation_class.eq('ALPN'))
kc = np.flatnonzero(m.annotation_class.eq('Kenyon_Cell'))
contacts = pd.read_parquet(prior/'localization/APL-incident.parquet')
ap = contacts[contacts.source_neuron_idx.isin(apl) & contacts.target_neuron_idx.isin(pn)].copy()
pk = pd.read_parquet(prior/'localization/APL-target-PN-to-KC.parquet')
assert len(ap) == 4600 and ap.target_neuron_idx.nunique() == 259 and len(pk) == 385229
assert pk.source_neuron_idx.isin(pn).all() and pk.target_neuron_idx.isin(kc).all()
pairs, allowed, keep = contact_scope(ap, pk, cfg['roi_labels'])
ids = edge_ids_for_pairs(pairs, ptr, dst)
assert np.array_equal(raw[ids], pairs.raw_partner_count)
full_expected = np.flatnonzero(np.isin(src, ap.target_neuron_idx.unique()) & np.isin(dst, kc))
assert np.array_equal(np.sort(ids), full_expected), 'Missing whole PN->KC pairs'
pairs['edge_id'] = ids
pairs['source_body_id'] = m.body_id.to_numpy()[pairs.source_neuron_idx]
pairs['target_body_id'] = m.body_id.to_numpy()[pairs.target_neuron_idx]
ca = pairs[pairs.blocked_contact_count > 0].sort_values('edge_id').copy()
eligible = np.sort(ca.source_neuron_idx.unique()).astype(np.int32)
all_pk = np.flatnonzero(np.isin(src, eligible) & np.isin(dst, kc))
whole = np.flatnonzero(np.isin(src, eligible))
assert set(ca.edge_id).issubset(all_pk) and set(all_pk).issubset(whole)
assert not np.any(np.isin(src[ca.edge_id], apl)) and not np.any(ca.retained_contact_count < 0)
for name, eids, count in [
('calyx_PN_KC_contact_block', ca.edge_id.to_numpy(np.int64), ca.blocked_contact_count.to_numpy(np.int64)),
('all_PN_KC_block', all_pk, raw[all_pk]), ('whole_PN_output_block', whole, raw[whole])]:
frame = pd.DataFrame({'edge_id': eids, 'source_neuron_idx': src[eids], 'target_neuron_idx': dst[eids],
'raw_synapse_count': raw[eids], 'blocked_contact_count': count})
frame['source_body_id'] = m.body_id.to_numpy()[src[eids]]
frame['target_body_id'] = m.body_id.to_numpy()[dst[eids]]
frame.to_parquet(exp/'masks'/f'{name}.parquet', index=False)
pairs.to_parquet(exp/'audit/all-PN-KC-contact-partitions.parquet', index=False)
allowed.to_parquet(exp/'audit/observed-APL-PN-ROI-pairs.parquet', index=False)
pns = m.iloc[np.sort(ap.target_neuron_idx.unique().astype(np.int32))].copy()
pns['eligible_for_diagnostic'] = pns.neuron_idx.isin(eligible)
pns.to_parquet(exp/'audit/all-259-APL-target-PNs.parquet', index=False)
roi = pk.assign(in_scope=keep).groupby(['primary_post', 'in_scope'], observed=True, dropna=False).size().reset_index(name='contacts')
roi.to_csv(exp/'audit/ROI-partition.csv', index=False)
summary = {'neurons': len(m), 'edges': len(dst), 'raw_contacts': int(raw.sum()), 'APL_target_PNs': len(pns),
'eligible_PNs': len(eligible), 'ineligible_PNs': int((~pns.eligible_for_diagnostic).sum()),
'calyx_mask_edges': len(ca), 'calyx_blocked_contacts': int(ca.blocked_contact_count.sum()),
'calyx_affected_KCs': int(ca.target_neuron_idx.nunique()), 'mixed_CA_nonCA_edges': int((ca.retained_contact_count > 0).sum()),
'calyx_other_contacts_retained_on_affected_edges': int(ca.retained_contact_count.sum()),
'all_PN_KC_edges': len(all_pk), 'all_PN_KC_contacts': int(raw[all_pk].sum()),
'whole_PN_edges': len(whole), 'whole_PN_contacts': int(raw[whole].sum()),
'unknown_ROI_contacts_in_original_PN_KC': int(pk.primary_post.eq('CentralBrain-unspecified').sum()),
'unknown_contacts_relabelled': 0, 'same_bouton_confirmed': False, 'biophysical_coefficient_known': False}
save(exp/'audit/scope-summary.json', summary)
inputs = [prior/'localization/APL-incident.parquet', prior/'localization/APL-target-PN-to-KC.parquet',
prior/'external-resources/synaptic-partners/download-verification.json',
can/'neuron-index/unified-metadata.parquet'] + list((can/'gpu').glob('csr-*.npy'))
save(exp/'protocol/input-hashes.json', [{'path': str(p.relative_to(root)), 'sha256': digest(p), 'bytes': p.stat().st_size} for p in inputs])
save(exp/'protocol/mask-hashes.json', {p.name: digest(p) for p in sorted((exp/'masks').iterdir())})
print(json.dumps(summary), flush=True)
def run():
cfg, root, model, exp, save, digest, _, _ = load_context()
pre = json.loads((exp/'protocol/preregistered.json').read_text())
assert all(digest(model/n) == h for n, h in pre['source_hashes'].items()), 'Source changed since preregistration'
assert not (exp/'regression/run-start.json').exists(), 'Refusing rerun into existing outputs'
assert all(digest(exp/'masks'/n) == h for n, h in json.loads((exp/'protocol/mask-hashes.json').read_text()).items())
q = queues(); runtime = root/cfg['runtime']
pc = yaml.safe_load((runtime/'phase4p.yaml').read_text())
os.environ['CUDA_VISIBLE_DEVICES'] = pc['device']['visible_gpu_uuid']
os.environ['CUDA_HOME'] = '/usr/local/cuda'; os.environ['TORCH_CUDA_ARCH_LIST'] = '8.9'; os.environ['MAX_JOBS'] = '2'
os.environ['PATH'] = str(root/'models/male-cns-lif/.venv/bin') + ':/usr/local/cuda/bin:' + os.environ['PATH']
sys.path.insert(0, str(root/'models/male-cns-lif')); sys.path.insert(0, str(runtime))
import torch
import phase4p, phase4v, phase4z
from phase4p_revalidate import DeterministicAPLSim, door_inputs, make_drive
from phase4r import arrhash
free, total = torch.cuda.mem_get_info(); assert free > 2*1024**3
save(exp/'regression/run-start.json', {'ComfyUI_queues': q, 'free_VRAM': free, 'total_VRAM': total,
'device': torch.cuda.get_device_name(), 'timestamp_utc': datetime.now(timezone.utc).isoformat()})
start = time.perf_counter(); torch.cuda.reset_peak_memory_stats()
rt = phase4p.CanonicalRuntime(pc, runtime, exp)
sim = DeterministicAPLSim(rt); sim.install(None)
assert len(sim.identity) == 14232 and sim.n == 166700 and len(rt.raw_np) == 25582938 and rt.delay_steps == 18
frozen = rt.weights.cpu().numpy().copy(); anatomical_hash = arrhash(rt.raw_np)
original_install = sim.install
apl_input_hash = arrhash(sim.input_gpu.cpu().numpy(), sim.output_gpu.cpu().numpy())
base_hash = arrhash(sim.base.cpu().numpy())
masks = {n: pd.read_parquet(exp/'masks'/f'{n}.parquet') for n in cfg['conditions'][1:]}
updates = {}
for name, mask in masks.items():
ids = mask.edge_id.to_numpy(np.int64)
values = blocked_weights(frozen[ids], rt.raw_np[ids], mask.blocked_contact_count.to_numpy(np.int64))
assert np.all(np.abs(values) <= np.abs(frozen[ids]))
updates[name] = (torch.as_tensor(ids, device=rt.device), torch.as_tensor(values, device=rt.device))
mask.assign(frozen_effective_weight=frozen[ids], diagnostic_effective_weight=values,
diagnostic_delta=(values.astype(float)-frozen[ids])).to_parquet(exp/'audit'/f'{name}-effective-overlay.parquet', index=False)
condition = 'frozen_reference'
def install(E):
assert E is None, 'No learning allowed'
original_install(None)
if condition != 'frozen_reference':
ix, values = updates[condition]; rt.weights[ix] = values
sim.install = install
vc = yaml.safe_load((root/cfg['input_model']/'phase4v.yaml').read_text())
assert vc['short_duration_ms'] == 120 and vc['observation_duration_ms'] == 1000
oldwatch = json.loads((root/cfg['event_prior']/'protocol/watched.json').read_text())
watch = np.asarray(oldwatch['all_watched'], np.int32)
targetkc = np.unique(sim.identity.loc[sim.identity.compartment.eq(vc['target_compartment']), 'source_neuron_idx'].to_numpy(np.int32))
oc, panel, vectors, selection, mapping = door_inputs(); panel = panel[panel.split == 'calibration'].reset_index(drop=True)
assert len(panel) == 6
save(exp/'protocol/calibration-panel.json', panel.to_dict('records'))
codes = phase4z.role_codes(sim.meta)
trials, regress, request_summary, populations, watched, hashes = [], [], [], [], [], []
baseline0 = None
try:
for oi in cfg['odor_indices']:
odor = panel.iloc[oi]
targets, rates = make_drive(oc, panel, vectors, selection, mapping, odor.odor_id, 'physiological')
forcing_seed = vc['seed_namespace'] + oi*vc['odor_seed_offset'] + cfg['seed']
force = phase4v.forcing(sim, targets, rates, forcing_seed, vc, 'offset'); ff = force.cpu().numpy()
hashes.append({'odor_index': oi, 'seed': forcing_seed, 'forcing': arrhash(ff), 'targets_rates': arrhash(targets, rates)})
np.savez_compressed(exp/'requests'/f'{oi}-scheduled.npz', forcing=ff, targets=targets, rates=rates)
requests0 = None
for condition in cfg['conditions']:
queues(); name = f'{oi}-{cfg["seed"]}-{condition}'
obs = phase4z.Observer(rt, watch, ff, targets); obs.attach()
try: result = phase4v.observed(sim, targets, force, targetkc, vc)
finally: obs.detach()
assert result['finite'] and np.isfinite(result['final_v']).all() and np.isfinite(result['final_g']).all()
ev = obs.events(); states = np.asarray(obs.states); req = pd.DataFrame(obs.request_rows)
assert len(req) == int(ff.sum())
assert np.array_equal(np.bincount(ev.neuron_idx, minlength=sim.n), result['counts'])
expected_weights = frozen.copy()
if condition != 'frozen_reference':
ids = masks[condition].edge_id.to_numpy(np.int64)
expected_weights[ids] = updates[condition][1].cpu().numpy()
assert np.array_equal(rt.weights.cpu().numpy(), expected_weights), 'Undeclared weight change'
row = {'trial': name, 'declared_weight_scope_exact': True}
if condition == 'frozen_reference':
old_ev = pd.read_parquet(root/cfg['event_prior']/'events'/f'{name}-whole-brain.parquet')
old_state = np.load(root/cfg['event_prior']/'states'/f'{name}-watched.npz')
old_final = np.load(root/cfg['state_prior']/'states'/f'{name}.npz')
row['prior_exact'] = {'events': ev.equals(old_ev), 'watched_states': np.array_equal(states, old_state['state']),
**{key: bool(np.array_equal(result[key], old_final[key])) for key in ('counts', 'final_v', 'final_g', 'trace')}}
assert all(row['prior_exact'].values()), row
requests0 = req
if oi == cfg['repeat_odor_index']: baseline0 = ev, states, req, result
paired = requests0.merge(req, on=['step', 'neuron_idx'], suffixes=('_ref', '_diagnostic'), validate='one_to_one', how='outer', indicator=True)
assert paired['_merge'].eq('both').all()
request_summary.append({'trial': name, 'scheduled': len(req), 'identical_request_keys': True,
'accepted': int(req.status.eq('accepted').sum()), 'blocked': int(req.status.eq('blocked').sum()), 'preexisting': int(req.status.eq('preexisting').sum()),
'status_differences_vs_reference': int((paired.status_ref != paired.status_diagnostic).sum()),
'actual_output_differences_vs_reference': int((paired.actual_output_spike_ref != paired.actual_output_spike_diagnostic).sum())})
late = ev[ev.step >= round(cfg['late_start_ms']/rt.dt)]
period_count = np.bincount(late.neuron_idx, minlength=sim.n)
for code in np.unique(codes):
nodes = np.flatnonzero(codes == code)
populations.append({'trial': name, 'population': str(code), 'neurons': len(nodes), 'active': int((result['counts'][nodes] > 0).sum()),
'spikes': int(result['counts'][nodes].sum()), 'late_spikes': int(period_count[nodes].sum())})
for node in watch:
watched.append({'trial': name, 'neuron_idx': int(node), 'body_id': int(sim.meta.iloc[node].body_id),
'type': str(sim.meta.iloc[node].annotation_type), 'population': str(codes[node]),
'spikes': int(result['counts'][node]), 'late_spikes': int(period_count[node]),
'late_rate_hz': float(period_count[node]/((1000-cfg['late_start_ms'])/1000))})
trials.append({'trial': name, 'odor_index': oi, 'odor_name': str(odor.odor_name), 'seed': cfg['seed'], 'condition': condition,
'whole_spikes': len(ev), 'KC_active': int(np.count_nonzero(result['counts'][sim.kc])),
'KC_active_fraction': float(np.count_nonzero(result['counts'][sim.kc])/len(sim.kc)),
'KC_spikes': int(result['counts'][sim.kc].sum()), 'KC_late_spikes': int(period_count[sim.kc].sum()),
'KC82312_late_spikes': int(period_count[cfg['target_KC']]), 'VA6_late_spikes': int(period_count[cfg['watched_VA6']]),
'finite': True, 'wall_seconds': result['wall_seconds'], 'biological_ms': 1000})
ev.to_parquet(exp/'events'/f'{name}.parquet', index=False)
req.to_parquet(exp/'requests'/f'{name}.parquet', index=False)
pd.DataFrame(result['samples']).to_parquet(exp/'observations'/f'{name}.parquet', index=False)
np.savez_compressed(exp/'states'/f'{name}.npz', counts=result['counts'], final_v=result['final_v'], final_g=result['final_g'], trace=result['trace'])
np.savez_compressed(exp/'states'/f'{name}-watched.npz', state=states, watch=watch)
if oi == cfg['repeat_odor_index']:
queues(); again = phase4z.Observer(rt, watch, ff, targets); again.attach()
try: repeat = phase4v.observed(sim, targets, force, targetkc, vc)
finally: again.detach()
row['repeat_exact'] = {'events': ev.equals(again.events()), 'states': np.array_equal(states, again.states),
'requests': req.equals(pd.DataFrame(again.request_rows)),
**{key: bool(np.array_equal(result[key], repeat[key])) for key in ('counts', 'final_v', 'final_g', 'trace')}}
assert all(row['repeat_exact'].values()), row
regress.append(row); save(exp/'regression'/f'{name}.json', row)
print(json.dumps(trials[-1]), flush=True)
# Fixed-event replay is an independent direct-operator check, not the dynamic whole-brain result.
replay_check(cfg, exp, sim, masks, frozen, baseline0, watch, phase4z, save)
finally:
sim.install = original_install; original_install(None)
assert np.array_equal(rt.weights.cpu().numpy(), frozen)
assert arrhash(rt.raw_np) == anatomical_hash and arrhash(sim.base.cpu().numpy()) == base_hash
assert arrhash(sim.input_gpu.cpu().numpy(), sim.output_gpu.cpu().numpy()) == apl_input_hash
save(exp/'regression/restored.json', {'base': True, 'raw': True, 'APL_matrices': True, 'frozen_effective_weights': True})
for name, rows in [('trials', trials), ('request-comparison', request_summary), ('population-counts', populations), ('watched-counts', watched)]:
pd.DataFrame(rows).to_csv(exp/'audit'/f'{name}.csv', index=False)
save(exp/'protocol/forcing-hashes.json', hashes)
# Separate reference trials do not include the graded APL overlay, exactly as archived.
rt.weights.copy_(sim.base)
reference = []
for spec in pc['reference_trials']:
queues(); ref = root/'experiments/phase4p-deterministic-runtime/phase4c-v2/reference'/spec['name']
ev = pd.read_parquet(ref/'spike-events.parquet')
expected = {'step': ev.step.to_numpy(), 'neuron_idx': ev.neuron_idx.to_numpy(),
'counts': np.load(ref/'per-neuron-spike-counts.int32.npy'), 'v': np.load(ref/'final-voltage.float32.npy'), 'g': np.load(ref/'final-g.float32.npy')}
r = rt.run(np.flatnonzero(rt.pops[spec['population']]), spec['rate_hz'], spec['seed'], spec['duration_ms'])
eq = {key: bool(np.array_equal(r[key], value)) for key, value in expected.items()}
assert all(eq.values()), eq
reference.append({'trial': spec['name'], 'exact': eq, 'wall_seconds': r['metrics']['wall_seconds']})
original_install(None)
save(exp/'regression/five-frozen-trials.json', {'pass': True, 'trials': reference, 'original_v1_preserved': True, 'oracle': 'frozen deterministic-v2'})
save(exp/'performance/summary.json', {'wall_seconds_including_build': time.perf_counter()-start,
'peak_VRAM_bytes': int(torch.cuda.max_memory_allocated()), 'device': torch.cuda.get_device_name(),
'diagnostic_overhead_included': True, 'not_runtime_benchmark': True, 'ComfyUI_models_unloaded': False})
save(exp/'audit/run-complete.json', {'trials': len(trials), 'exact_repeat_trials': 4, 'old_trial_reproductions': 6,
'frozen_reference_trials': 5, 'all_finite': True, 'candidate': False, 'training': False})
def replay_check(cfg, exp, sim, masks, frozen, baseline, watch, phase4z, save):
ev, state, req, result = baseline; rt = sim.rt; T = len(state)
ids = np.flatnonzero(np.isin(rt.indices_np, watch))
edges = pd.DataFrame({'edge_id': ids, 'source_neuron_idx': sim.sources[ids], 'target_neuron_idx': rt.indices_np[ids], 'weight': frozen[ids]})
arrivals = ev.merge(edges, left_on='neuron_idx', right_on='source_neuron_idx')
arrivals['arrival_step'] = arrivals.step + rt.delay_steps
arrivals = arrivals[arrivals.arrival_step < T].sort_values(['target_neuron_idx', 'arrival_step', 'edge_id'], kind='stable')
rows = []
for wi, node in enumerate(watch):
subset = arrivals[arrivals.target_neuron_idx == node].copy()
after = np.r_[state[1:, 1, wi], result['final_g'][node]]
overlay = after.astype(float)-state[:, 5, wi].astype(float)
request = np.zeros(T, bool); rq = req[req.neuron_idx == node]; request[rq.step.to_numpy(np.int32)] = True
base_arrival = state[:, 3, wi]
for name in cfg['conditions']:
weights = subset.weight.to_numpy(np.float32).copy()
if name != 'frozen_reference':
frame = masks[name]; eids = frame.edge_id.to_numpy(np.int64)
values = blocked_weights(frozen[eids], rt.raw_np[eids], frame.blocked_contact_count.to_numpy(np.int64))
lookup = pd.Series(values, index=eids)
mapped = subset.edge_id.map(lookup); keep = mapped.notna().to_numpy()
weights[keep] = mapped[keep].to_numpy(np.float32)
subset['diagnostic_weight'] = weights
a = np.zeros(T, np.float32)
for step, group in subset.groupby('arrival_step', sort=False):
a[int(step)] = np.cumsum(group.diagnostic_weight.to_numpy(np.float32), dtype=np.float32)[-1]
rr = phase4z.replay(a, overlay, request, rt)
if name == 'frozen_reference':
exact = np.array_equal(a, base_arrival) and np.array_equal(rr[0], ev.loc[ev.neuron_idx == node, 'step']) and np.array_equal(rr[1], state[:, 4:7, wi])
assert exact and rr[2] == result['final_v'][node] and rr[3] == result['final_g'][node]
unchanged = np.array_equal(a, base_arrival)
if name == 'calyx_PN_KC_contact_block' and node not in sim.kc: assert unchanged
rows.append({'condition': name, 'neuron_idx': int(node), 'arrival_unchanged': bool(unchanged),
'arrival_L1_difference': float(np.abs(a.astype(float)-base_arrival).sum()),
'conditional_late_spikes': int((rr[0] >= round(cfg['late_start_ms']/rt.dt)).sum()),
'all_other_recorded_events_and_APL_fixed': True, 'whole_brain_causality_claim': False})
pd.DataFrame(rows).to_csv(exp/'replay/fixed-event-scope.csv', index=False)
save(exp/'regression/fixed-event-replay.json', {'baseline_exact_neurons': len(watch), 'terminal_nonKC_arrivals_exact': True})
def finalize():
cfg, root, model, exp, save, digest, immutable_check, seal = load_context()
assert (exp/'audit/run-complete.json').exists()
pre = json.loads((exp/'protocol/preregistered.json').read_text())
assert all(digest(model/n) == h for n, h in pre['source_hashes'].items())
post = integrity(cfg, root, digest, immutable_check)
assert post == json.loads((exp/'regression/preflight.json').read_text())
save(exp/'regression/final-integrity.json', post)
q = queues(); save(exp/'audit/final-service-health.json', {'ComfyUI_queues': q, 'services_stopped': False})
trials = pd.read_csv(exp/'audit/trials.csv'); scope = json.loads((exp/'audit/scope-summary.json').read_text())
requests = pd.read_csv(exp/'audit/request-comparison.csv')
lines = ['# Phase 4AB — calyx contact-scope diagnostic', '',
'Status: COMPLETE-SCOPE-COUNTERFACTUAL / NO-DYNAMICS-CANDIDATE.',
'Diagnostic interventions only; no calibrated biological inhibition, no training, no parameter winner.', '',
f"Eligible PNs: {scope['eligible_PNs']}/259. CA mask: {scope['calyx_mask_edges']} edges / {scope['calyx_blocked_contacts']} contacts.",
f"Affected KCs: {scope['calyx_affected_KCs']}. Mixed-ROI affected edges: {scope['mixed_CA_nonCA_edges']}; retained other contacts: {scope['calyx_other_contacts_retained_on_affected_edges']}.",
f"Broader PN→KC control: {scope['all_PN_KC_edges']} edges / {scope['all_PN_KC_contacts']} contacts. All-fast-PN-output control: {scope['whole_PN_edges']} edges / {scope['whole_PN_contacts']} contacts.", '',
'| Odor | Condition | Active KC | KC late spikes | KC82312 late | VA6 late |',
'|---|---|---:|---:|---:|---:|']
for r in trials.itertuples():
lines.append(f'| {r.odor_name} | {r.condition} | {r.KC_active} | {r.KC_late_spikes} | {r.KC82312_late_spikes} | {r.VA6_late_spikes} |')
lines += ['', 'Late means 500–1,000 ms; 120 ms old calibration odor input; one seed, six old odors. No held-out generalization claim.',
f"Identical scheduled requests across conditions. Delivered request-associated output differences versus reference: {int(requests.actual_output_differences_vs_reference.sum())} (summed over all comparisons). See per-trial table; this is state/refractory feedback, not a changed RNG.", '',
'## Interpretation limits', '',
'CA selection uses exact primary_post labels plus matched APL→PN/ROI metadata, not bouton identities or inferred receptors. Unknown ROIs are not reclassified.',
'Whole-PN control removes fast output, not somatic spikes or the frozen graded APL input. It is not a complete PN knockout.',
'Reduction/silencing is not restored information or associative memory. No condition becomes a formal model. Fixed-event replay freezes other recorded events/APL; dynamic trials allow natural recurrent feedback.',
'Local-inhibition motivation: [Prisco et al.](https://doi.org/10.7554/eLife.74172), [Amin et al.](https://doi.org/10.7554/eLife.56954). These sources do not establish the complete-block operator as physiological.', '',
'## Verification', '',
'Six original trials reproduced exactly (whole spike events, watched state and final counts/V/g). Four first-odor repeats exact. Five deterministic-v2 frozen reference trials exact. Finite state throughout.',
'Original 230,239 files and both Phase 4AA manifests rechecked before/after. Base CSR/count/sign, frozen LIF/APL, eligibility-v2 and 14,232 plastic mask preserved.',
'Timing includes diagnostic CPU/GPU observation overhead and is not a runtime speed benchmark. ComfyUI was not stopped or unloaded.',
'Top-level acceptance gates remain 5/10 (50%); anatomical diagnosis is not evidence of learning success.']
(exp/'REPORT.md').write_text('\n'.join(lines)+'\n', encoding='utf-8')
save(exp/'audit/final-summary.json', {'status': 'COMPLETE-SCOPE-COUNTERFACTUAL / NO-DYNAMICS-CANDIDATE',
'integrity_pass': True, 'reference_pass': True, 'scope': scope, 'candidate': False, 'training': False,
'preserved_acceptance_gates': '5/10', 'frozen_baseline_modified': False})
for folder in (model, exp):
count = seal(folder); assert manifest_check(folder, digest)['pass']; print('SEALED', folder, count, flush=True)
if __name__ == '__main__':
parser = argparse.ArgumentParser(); parser.add_argument('task', choices=['prepare', 'run', 'finalize'])
globals()[parser.parse_args().task]()