from itertools import product def run(load,check): reg=load('C286_DATA.json')['target_register'];basepairs=[] for p in load('C414_DATA.json')['source_pairs']: level=p['levels'][0] for ui,li in product(level['upper_record_indices'],level['lower_record_indices']): if reg[ui]['role']=='Flood start' and reg[li]['role']=='Noah death':basepairs.append((ui,li)) keys=['tradition','gear','Cainan','Terah60','full430'];rows=[] for ui,li in basepairs: u,l=reg[ui],reg[li];uc={k:u[k] for k in keys};lc={k:l[k] for k in keys};ups=[i for i,r in enumerate(reg) if all(r[k]==v for k,v in uc.items())];lows=[i for i,r in enumerate(reg) if all(r[k]==v for k,v in lc.items()) and (r['role'].startswith('Flood') or r.get('rail')==l.get('rail'))];hits=[] for a,z in product(ups,lows): if reg[a]['center']-reg[z]['center']==1058:hits.append({'upper_record_index':a,'lower_record_index':z,'upper_role':reg[a]['role'],'lower_role':reg[z]['role'],'upper':reg[a]['center'],'lower':reg[z]['center'],'upper_rail':reg[a].get('rail'),'lower_rail':reg[z].get('rail')}) check('seed retained '+str((ui,li)),any(h['upper_record_index']==ui and h['lower_record_index']==li for h in hits)) offsets=[] for a,z in product(ups,lows): if reg[a]['role']==reg[z]['role']:offsets.append({'role':reg[a]['role'],'upper_rail':reg[a].get('rail'),'lower_rail':reg[z].get('rail'),'difference':reg[a]['center']-reg[z]['center']}) rows.append({'seed_record_indices':[ui,li],'upper_seed':u,'lower_seed':l,'upper_context':uc,'lower_context':lc,'upper_context_record_indices':ups,'lower_context_record_indices':lows,'context_pair_trials':len(ups)*len(lows),'all_same_context_2K_hits':hits,'same_role_offsets':offsets}) check('closed C414 class size',len(rows)==16) return {'step':'C424','cases':rows,'counts':{'labelled_seed_pairs':len(rows),'coordinate_seed_pairs':len({(r['upper_seed']['center'],r['lower_seed']['center']) for r in rows}),'same_context_station_pair_trials':sum(r['context_pair_trials'] for r in rows),'additional_2K_station_pairs':sum(len(r['all_same_context_2K_hits'])-1 for r in rows)},'interpretation':'The Flood context carries no person rail. Both existing SP person rails are tested explicitly when SP is the upper tradition; lower Noah-death rail is retained. Source membership of the seed is separate from any additional station correspondence.'}