43 lines
2.6 KiB
Python
43 lines
2.6 KiB
Python
"""Orthogonal evidence axes. Never converts predicted dopamine to DAN identity."""
|
|
import numpy as np
|
|
import pandas as pd
|
|
|
|
def roles(meta, mapped_dan_ids=()):
|
|
required=['neuron_idx','body_id','annotation_class','annotation_type','neurotransmitter','nt_ground_truth']
|
|
missing=set(required)-set(meta.columns)
|
|
if missing:raise ValueError(f'Missing actual schema columns: {sorted(missing)}')
|
|
out=meta[required].copy()
|
|
cls=meta.annotation_class.fillna('');typ=meta.annotation_type.fillna('')
|
|
nt=meta.neurotransmitter.fillna('').str.strip().str.lower()
|
|
out['metadata_dopamine']=nt.eq('dopamine')
|
|
out['annotation_DAN']=cls.eq('DAN')
|
|
out['annotation_DPM']=typ.eq('DPM')
|
|
out['has_frozen_MB_DAN_mapping']=meta.neuron_idx.isin(mapped_dan_ids)
|
|
out['has_raw_ground_truth']=meta.nt_ground_truth.notna() & meta.nt_ground_truth.fillna('').ne('')
|
|
out['identity_conflict']=out.annotation_DAN & out.annotation_DPM
|
|
out['role_group']='other_annotation'
|
|
out.loc[cls.isin(['ALPN','olfactory']),'role_group']='PN_olfactory_annotation'
|
|
out.loc[cls.eq('Kenyon_Cell'),'role_group']='KC_annotation'
|
|
out.loc[cls.eq('MBON'),'role_group']='MBON_annotation'
|
|
out.loc[typ.eq('APL'),'role_group']='APL_annotation'
|
|
other_dop=out.metadata_dopamine & ~out.annotation_DAN & ~out.annotation_DPM
|
|
# Preserve separate evidence booleans even when the reporting group is disjoint.
|
|
out.loc[other_dop & out.role_group.eq('other_annotation'),'role_group']='dopamine_metadata_role_unknown'
|
|
out.loc[out.annotation_DAN,'role_group']='DAN_annotation'
|
|
out.loc[out.annotation_DPM,'role_group']='DPM_annotation'
|
|
out.loc[out.identity_conflict,'role_group']='identity_conflict_unknown'
|
|
return out
|
|
|
|
def self_test():
|
|
x=pd.DataFrame({'neuron_idx':np.arange(5,dtype=np.int32),'body_id':np.arange(5,dtype=np.uint64),
|
|
'annotation_class':[None,'DAN',None,'DAN',None],'annotation_type':['DPM','PAM15',None,'DPM','PAM-not-proof'],
|
|
'neurotransmitter':['dopamine']*5,'nt_ground_truth':[None]*5})
|
|
y=roles(x,[1])
|
|
assert y.annotation_DAN.tolist()==[False,True,False,True,False]
|
|
assert y.role_group.tolist()==['DPM_annotation','DAN_annotation','dopamine_metadata_role_unknown','identity_conflict_unknown','dopamine_metadata_role_unknown']
|
|
assert not y.has_raw_ground_truth.any() and y.has_frozen_MB_DAN_mapping.tolist()==[False,True,False,False,False]
|
|
try:roles(x.drop(columns='nt_ground_truth'))
|
|
except ValueError:pass
|
|
else:raise AssertionError('Missing schema must fail')
|
|
return {'pass':True,'DPM_not_inferred_DAN':True,'PAM_name_not_identity_proof':True,'unknown_retained':True,'conflict_flagged':True,'schema_fail_closed':True}
|