"""All predeclared pairs and all trial outputs; never choose a winning odor.""" from itertools import combinations import numpy as np import pandas as pd from context import EXP, AK, CFG, read, save as _save, digest, bit_equal, write_npz as _write_npz from credit import pair_identity def load_arrays(path): with np.load(path, allow_pickle=False) as data: return {key: data[key].copy() for key in data.files} def metrics(values): values = np.asarray(values, np.float64) if not len(values): return dict(min=None, mean=None, max=None, undefined_reason='No defined denominator observations') return dict(min=float(values.min()), mean=float(values.mean()), max=float(values.max())) def primary_rows(reg): rows = [r for r in reg['planned'] if r['repeat'] == 0] assert len(rows) == CFG['primary_trials'] and len({r['name'] for r in rows}) == len(rows) return rows def run(verify_only=False): def save(path, value): if verify_only: assert read(path) == value, 'Summary JSON differs from recomputed evidence: ' + str(path) else: _save(path, value) def write_npz(path, **value): if verify_only: old = load_arrays(path) assert set(old) == set(value) and all(bit_equal(old[k], value[k]) for k in old) else: _write_npz(path, **value) reg = read(EXP / 'protocol/preregistered.json') assert read(EXP / 'audit/replays-complete.json')['pass_all'] data = load_arrays(EXP / 'protocol/incoming.npz') for row in reg['planned']: folder = EXP / 'trials' / (row['name'] + '-r' + str(row['repeat'])) hashes = read(folder / 'output-hashes.json') assert {r['path'] for r in hashes} == {p.name for p in folder.iterdir() if p.name != 'output-hashes.json'} for entry in hashes: assert digest(folder / entry['path']) == entry['sha256'] original = load_arrays(AK / 'gpu' / row['cohort'] / (row['name'] + '-r' + str(row['repeat'])) / 'state.npz') base = load_arrays(folder / 'baseline-replay.npz') selected = np.isin(original['neuron_idx'], data['targets']) assert all(bit_equal(base[k], original[k][data['targets']]) for k in ('v', 'g', 'ref', 'counts')) assert all(bit_equal(base[k], original[k][selected]) for k in ('step', 'neuron_idx')) candidate = pd.read_parquet(EXP / 'protocol/candidate-static.parquet') target_meta = pd.read_parquet(EXP / 'protocol/mbon-metadata.parquet') primary = primary_rows(reg) repeats = [] for row in reg['planned']: if row['repeat'] != 1: continue paths = [EXP / 'trials' / (row['name'] + '-r' + str(i)) for i in (0, 1)] checks = {} for filename in ('baseline-replay.npz', 'baseline-target-accounting.npz', 'baseline-edge-accounting.npz', 'conditional25-replay.npz', 'conditional25-target-accounting.npz', 'conditional25-edge-accounting.npz', 'credit.npz'): a, b = (load_arrays(p / filename) for p in paths) checks[filename] = set(a) == set(b) and all(bit_equal(a[k], b[k]) for k in a) for filename in ('baseline-accounting.json', 'conditional25-accounting.json', 'credit.json', 'sensitivity.json'): checks[filename] = read(paths[0] / filename) == read(paths[1] / filename) assert all(checks.values()), 'Repeat accounting differs: ' + row['name'] repeats.append(dict(name=row['name'], checks=checks, pass_all=True)) assert len(repeats) == CFG['technical_repeats'] save(EXP / 'audit/repeat-checks.json', dict(pass_all=True, repeats=repeats)) summaries, target_rows, trial_metrics = [], [], [] for row in primary: folder = EXP / 'trials' / (row['name'] + '-r0') report = read(folder / 'summary.json') assert report['pass_all'] and all(report['baseline_exact'].values()) summaries.append(report) targets = load_arrays(folder / 'baseline-target-accounting.npz') change = load_arrays(folder / 'conditional25-target-accounting.npz') edges = load_arrays(folder / 'baseline-edge-accounting.npz') exc = targets['accepted_positive_V'].sum(axis=1) plastic_exc = targets['accepted_positive_V'][:, 0] area_exc = targets['g_sign_integral_V_ms'][:, :, 0].sum(axis=1) area_plastic = targets['g_sign_integral_V_ms'][:, 0, 0] for i, meta in enumerate(target_meta.itertuples()): entry = dict(name=row['name'], cohort=row['cohort'], mode=row['mode'], odor_id=row['odor_id'], seed=row['seed'], neuron_idx=int(meta.neuron_idx), body_id=int(meta.body_id), annotation_type=meta.annotation_type, compartment_verbatim=meta.mb_compartment_verbatim, candidate_target=bool(np.any(candidate.target_neuron_idx.to_numpy() == meta.neuron_idx)), accepted_total_positive_V=float(exc[i]), accepted_plastic_positive_V=float(plastic_exc[i]), plastic_accepted_positive_fraction=None if exc[i] == 0 else float(plastic_exc[i] / exc[i]), positive_source_g_area_V_ms=float(area_exc[i]), plastic_positive_g_area_V_ms=float(area_plastic[i]), plastic_positive_g_area_fraction=None if area_exc[i] == 0 else float(area_plastic[i] / area_exc[i]), baseline_spikes=int(targets['spike_count'][i]), conditional25_spikes=int(change['spike_count'][i]), baseline_first_tick=int(targets['first_spike_tick'][i]), conditional25_first_tick=int(change['first_spike_tick'][i]), max_abs_V_delta_SI=float(np.max(np.abs(targets['history_v'][:, i] - change['history_v'][:, i]))), max_abs_g_delta_SI=float(np.max(np.abs(targets['history_g'][:, i] - change['history_g'][:, i])))) target_rows.append(entry) pick = data['is_candidate'] summary = dict(name=row['name'], cohort=row['cohort'], mode=row['mode'], odor_id=row['odor_id'], seed=row['seed'], plastic_due_events=int(edges['due_count'][pick].sum()), plastic_accepted_events=int(edges['accepted_count'][pick].sum()), plastic_rejected_events=int(edges['rejected_count'][pick].sum()), plastic_pending_events=int(edges['pending_after_window_count'][pick].sum()), plastic_edges_with_accepted_events=int(np.count_nonzero(edges['accepted_count'][pick])), accepted_positive_V=float(exc.sum()), plastic_accepted_positive_V=float(plastic_exc.sum()), plastic_accepted_positive_fraction=None if exc.sum() == 0 else float(plastic_exc.sum() / exc.sum()), plastic_positive_g_area_fraction=None if area_exc.sum() == 0 else float(area_plastic.sum() / area_exc.sum()), **report['sensitivity']) trial_metrics.append(summary) target_table = pd.DataFrame(target_rows) if verify_only: assert target_table.equals(pd.read_parquet(EXP / 'audit/per-MBON-primary.parquet')) else: target_table.to_parquet(EXP / 'audit/per-MBON-primary.parquet', index=False) save(EXP / 'audit/primary-trial-metrics.json', trial_metrics) pair_reports = [] for cohort in sorted({r['cohort'] for r in primary}): for mode in sorted({r['mode'] for r in primary}): rows = [r for r in primary if r['cohort'] == cohort and r['mode'] == mode] odors = sorted({r['odor_index'] for r in rows}) assert len(rows) == 30 and len(odors) == 6 traces = {}; whole = {}; ids = {} for odor in odors: series = sorted((r for r in rows if r['odor_index'] == odor), key=lambda r: r['seed']) assert len(series) == 5 ids[odor] = series[0]['odor_id'] credit = [load_arrays(EXP / 'trials' / (r['name'] + '-r0') / 'credit.npz') for r in series] traces[odor] = np.stack([c['trace_gate'] for c in credit]) whole[odor] = np.stack([(c['spike_count_total'] > 0).astype(np.float32) for c in credit]) for a, b in combinations(odors, 2): name = f'{cohort}-{mode}-{a:02d}-vs-{b:02d}' result = dict(cohort=cohort, mode=mode, odor_a=ids[a], odor_b=ids[b], odor_index_a=a, odor_index_b=b) for definition, series in (('virtual_gate900', traces), ('whole_window_auxiliary', whole)): identities = pair_identity(series[a], series[b], data['edge_source_local']) save_arrays = {k: v for k, v in identities.items() if isinstance(v, np.ndarray)} write_npz(EXP / 'pairs' / (name + '-' + definition + '.npz'), **save_arrays) summary = identities['summary'] # Historic local existence criterion only, no new overall pass rate. summary['local_specific_KC_and_edges_exist_both_sides'] = all( summary[unit]['category_counts'][side] >= 1 for unit in ('KC', 'edges') for side in ('A_specific', 'B_specific')) summary['compartments'] = {} for comp, group in candidate.groupby('target_compartment_verbatim', sort=True): sub = pair_identity(series[a], series[b], data['edge_source_local'][group.index.to_numpy()]) summary['compartments'][str(comp)] = sub['summary']['edges'] result[definition] = summary pair_reports.append(result) assert len(pair_reports) == 60 save(EXP / 'audit/pair-identities.json', pair_reports) blocks = {} for cohort in sorted({r['cohort'] for r in primary}): for mode in sorted({r['mode'] for r in primary}): trials = [r for r in trial_metrics if r['cohort'] == cohort and r['mode'] == mode] pairs = [p for p in pair_reports if p['cohort'] == cohort and p['mode'] == mode] blocks[cohort + '/' + mode] = dict(trials=len(trials), pairs=len(pairs), pairs_with_both_specific_KC_and_edge_sets=sum(p['virtual_gate900']['local_specific_KC_and_edges_exist_both_sides'] for p in pairs), KC_empty_union_pairs=sum(p['virtual_gate900']['KC']['empty_union'] for p in pairs), edge_empty_union_pairs=sum(p['virtual_gate900']['edges']['empty_union'] for p in pairs), KC_active_set_Jaccard=metrics([p['virtual_gate900']['KC']['active_set_jaccard'] for p in pairs if not p['virtual_gate900']['KC']['empty_union']]), candidate_edge_active_set_Jaccard=metrics([p['virtual_gate900']['edges']['active_set_jaccard'] for p in pairs if not p['virtual_gate900']['edges']['empty_union']]), plastic_accepted_events=metrics([r['plastic_accepted_events'] for r in trials]), plastic_fraction_of_all_MBON_accepted_positive=metrics([r['plastic_accepted_positive_fraction'] for r in trials if r['plastic_accepted_positive_fraction'] is not None]), conditional25_event_changed_trials=sum(r['event_sequence_changed'] for r in trials), conditional25_count_or_first_latency_changed_trials=sum(r['functional_count_or_first_latency_change'] for r in trials), max_abs_V_difference_SI=max(r['max_abs_V_difference_SI'] for r in trials), max_abs_g_difference_SI=max(r['max_abs_g_difference_SI'] for r in trials)) outcome = dict(arithmetic_and_coverage_pass=True, primary_trials=120, exact_repeats=24, pairs=60, blocks=blocks, candidate_generated=False, learning_achieved=False, conditioning_executed=False, scientific_overall_PASS_threshold_defined=False, maximum_observed_g_lane_roundoff_residual_SI=max(read(EXP / 'trials' / (r['name'] + '-r0') / 'baseline-accounting.json')['max_g_lane_residual_V'] for r in primary), interpretation='Read-only credit delivery and fixed conditional sensitivity; not closed-loop memory or dopamine measurement') save(EXP / 'audit/scientific-summary.json', outcome) return outcome if __name__ == '__main__': print(run(), flush=True)