Audit conditional PN recruitment and graded APL source timing
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
"""Register fixed conditional audit before reading PN contribution results."""
|
||||
from datetime import datetime, timezone
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from context import (ROOT, MODEL, EXP, AH, AH_MODEL, AG, AG_MODEL, META, COEFF,
|
||||
GROUPS, read, save, digest, sources, integrity, load_module)
|
||||
|
||||
|
||||
def main():
|
||||
assert not EXP.exists() or not any(EXP.iterdir()), 'Populated audit directory must not be reused'
|
||||
assert read(AH / 'audit/final-status.json')['status'] == 'PASS-CONDITIONAL-KC-DRIVE-AUDIT'
|
||||
assert read(AG / 'audit/final-status.json')['numerical_gate_pass']
|
||||
for sub in ('protocol', 'regression', 'trials', 'audit', 'logs'):
|
||||
(EXP / sub).mkdir(parents=True, exist_ok=False)
|
||||
test_command = [sys.executable, '-B', '-m', 'unittest', '-v',
|
||||
'test_pn_observer', 'test_apl_sources', 'test_structure_metrics', 'test_harness',
|
||||
'test_validate_events', 'test_publication']
|
||||
tested = subprocess.run(test_command, cwd=MODEL, capture_output=True, text=True)
|
||||
with (EXP / 'regression/unit-tests.log').open('x') as f:
|
||||
f.write(tested.stdout + tested.stderr)
|
||||
save(EXP / 'regression/unit-tests.json', dict(command=test_command, exit_code=tested.returncode,
|
||||
pass_all=tested.returncode == 0, sha256=digest(EXP / 'regression/unit-tests.log')))
|
||||
assert tested.returncode == 0
|
||||
paths = [AH / 'manifest.json', AH / 'checksums.sha256', AH_MODEL / 'manifest.json',
|
||||
AH_MODEL / 'checksums.sha256', AH_MODEL / 'replay_core.py', AH_MODEL / 'populations.py',
|
||||
AG / 'manifest.json', AG / 'checksums.sha256', AG_MODEL / 'manifest.json',
|
||||
AG_MODEL / 'checksums.sha256', META, COEFF,
|
||||
ROOT / 'datasets/male-cns-v1.0/processed/neuron-only/gpu/csr-weights.int64.npy']
|
||||
save(EXP / 'protocol/preregistered.json', dict(
|
||||
timestamp_utc=datetime.now(timezone.utc).isoformat(), sources=sources(),
|
||||
inputs=[dict(path=str(p.relative_to(ROOT)), sha256=digest(p)) for p in paths],
|
||||
parent_commit=subprocess.check_output(['git', '-C', str(ROOT), 'rev-parse', 'HEAD'], text=True).strip(),
|
||||
scope='Post-outcome conditional PN/APL source audit; no new whole-brain simulation or learning',
|
||||
previous_KC_outcome_known=True, before_PN_contribution_accounting=True,
|
||||
new_GPU_use=False, max_threads=4, output_budget_bytes=2 * 1024**3,
|
||||
per_trial_first_arrival_row_limit=1000000, truncation_allowed=False,
|
||||
exact_gate='All PN events/counts/final v,g,ref; fixture pre/post histories; 12 deterministic accounting repeats',
|
||||
APL_gate='Source float64 mathematical accounting within prior standard-float32 analytic roundoff bounds; not CUDA bitwise replay',
|
||||
hypotheses={
|
||||
'temporal_precedence': 'For every trial and every KC first spike, non-design PN spike must be strictly earlier; equals/after/absent retained',
|
||||
'direct_PN_KC_arrival': 'PN source tick+18 strictly less than KC first spike; same tick arrival is after threshold',
|
||||
'APL_source_precedence': 'Group h write at tick s affects only KC threshold ticks greater than s',
|
||||
'APL_share': 'Cumulative group shares are descriptive float64; no accumulated source-share error bound or robust-majority claim',
|
||||
'odor_structure': 'Fixed 686-dimensional counts; secondary fixed outside-six-odor-design-union subset; no activity-fraction or learning gate'},
|
||||
attribution_limits=['Accepted edge antecedents are not proof of single-neuron necessity or intervention causality',
|
||||
'Non-design means not in static design targets; does not mean noise or biologically incorrect',
|
||||
'Source-V lanes are non-feedback accounting with initial/constant/request/reset/roundoff lanes',
|
||||
'APL input matrix is legacy nonnegative raw-contact-normalized engineering mapping, not signed LIF current',
|
||||
'No CAL per-tick target state was independently saved; final states and events only',
|
||||
'Fixtures generated h for 4064 KC but applied only to fixture KC'],
|
||||
python=sys.version, numpy=np.__version__, pandas=pd.__version__, machine=platform.machine(),
|
||||
longdouble_mantissa_bits=int(np.finfo(np.longdouble).nmant)))
|
||||
save(EXP / 'regression/old-integrity-before.json', integrity())
|
||||
population = load_module('frozen_population_ai', AH_MODEL / 'populations.py')
|
||||
assert digest(META) == population.METADATA_SHA256
|
||||
meta = pd.read_parquet(META).sort_values('neuron_idx').reset_index(drop=True)
|
||||
labels, report = population.classify(meta)
|
||||
assert report['pass_all']
|
||||
for name, count in (('ALLN', 420), ('ALIN', 24), ('ALON', 14), ('olfactory', 2639)):
|
||||
selected = (meta.annotation_class == name).fillna(False).to_numpy(dtype=bool)
|
||||
assert int(selected.sum()) == count and np.all(labels[selected] == 'other')
|
||||
labels[selected] = 'olfactory_sensory' if name == 'olfactory' else name
|
||||
assert set(np.unique(labels)).issubset(GROUPS)
|
||||
for label, fname, count in (('KC', 'kc_globals.npy', 4064), ('APL', 'apl_globals.npy', 2), ('ALPN', 'pn_globals.npy', 686)):
|
||||
observed = np.flatnonzero(labels == label).astype(np.int32)
|
||||
assert len(observed) == count and np.array_equal(observed, np.load(AG / 'apl-bundle' / fname))
|
||||
report.update(refined_exact_class_counts={label: int((labels == label).sum()) for label in GROUPS},
|
||||
refinement='AH anatomical classifier, then exact ALLN/ALIN/ALON/olfactory classes split only from other; no name-prefix guessing')
|
||||
save(EXP / 'protocol/population-audit.json', report)
|
||||
save(EXP / 'protocol/metadata-schema.json', {c: dict(dtype=str(meta[c].dtype), nulls=int(meta[c].isna().sum())) for c in meta})
|
||||
meta[['neuron_idx', 'body_id', 'annotation_class', 'annotation_type', 'neurotransmitter']].assign(
|
||||
audit_source_group=labels).to_parquet(EXP / 'protocol/neuron-source-groups.parquet', index=False)
|
||||
inventory = [dict(case=name, repeat=0, kind='fixture') for name in read(AG_MODEL / 'config.json')['fixtures']]
|
||||
for row in read(AG / 'protocol/calibration-cases.json'):
|
||||
inventory.append(dict(case=row['name'], repeat=0, kind='calibration'))
|
||||
if row['seed'] == 51101:
|
||||
inventory.append(dict(case=row['name'], repeat=1, kind='calibration'))
|
||||
assert len(inventory) == len({(r['case'], r['repeat']) for r in inventory}) == 80
|
||||
for row in inventory:
|
||||
source = AG / 'gpu' / (row['case'] + '-r' + str(row['repeat']))
|
||||
assert read(source / 'summary.json')['complete']
|
||||
row['source'] = str(source.relative_to(ROOT))
|
||||
save(EXP / 'protocol/inventory.json', inventory)
|
||||
save(EXP / 'protocol/prepared-hashes.json', [dict(path=str(p.relative_to(EXP)), sha256=digest(p))
|
||||
for p in sorted((EXP / 'protocol').iterdir()) if p.is_file() and p.name != 'prepared-hashes.json'])
|
||||
print('REGISTERED fixed 80 existing records; no new brain simulation', flush=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user