#!/usr/bin/env python3 """Candidate 008, frozen five-offset perturbation diagnostic (no model fitting).""" from ceb_behavior_pilot import ROOT,CACHE,Interpreter,resample_poly,sf,np,pd,math import json def main(): sample=pd.read_csv(ROOT/'results/003_pilot_sample.csv') sample=sample[sample.event_duration<=1.2] labels=(CACHE/'v1_5_1_BirdNET_GLOBAL_6K_V2.4_Labels_en_uk.txt').read_text().splitlines() mapping={s.split('_')[0]:i for i,s in enumerate(labels)} model=Interpreter(model_path=str(CACHE/'v1_5_1_BirdNET_GLOBAL_6K_V2.4_Model_FP32.tflite'),num_threads=1) model.allocate_tensors();inp=model.get_input_details()[0];out=model.get_output_details()[0] rows=[] for file,group in sample.groupby('filepath'): audio,rate=sf.read(CACHE/'ceb_test_audio'/file,dtype='float32',always_2d=True) audio=audio.mean(axis=1);gcd=math.gcd(rate,48000) audio=resample_poly(audio,48000//gcd,rate//gcd).astype(np.float32) for e in group.to_dict('records'): start=round(e['start']*48000);original=audio[start:start+144000] for mode in ['circular','source']: for shift in [-.6,-.3,0.,.3,.6]: offset=round(shift*48000) chunk=np.roll(original,offset) if mode=='circular' else audio[start+offset:start+offset+144000] assert len(chunk)==144000 model.set_tensor(inp['index'],chunk[None,:]);model.invoke() logit=float(model.get_tensor(out['index'])[0,mapping[e['species']]]) rows.append(dict(event_id=e['event_id'],filepath=file,species=e['species'],voc=e['voc'],duration=e['event_duration'],mode=mode,shift=shift,score=float(1/(1+np.exp(-np.clip(logit,-15,15)))))) df=pd.DataFrame(rows);df.to_csv(ROOT/'results/008_alignment_predictions.csv',index=False) summaries=[] for mode,g in df.groupby('mode'): limits=g.groupby('event_id').score.agg(['min','max']) summaries.append(dict(mode=mode,events=len(limits),species=g.species.nunique(),files=g.filepath.nunique(), crosses_01=int(((limits['min']<.1)&(limits['max']>=.1)).sum()), crosses_05=int(((limits['min']<.5)&(limits['max']>=.5)).sum()), median_score_range=float((limits['max']-limits['min']).median()))) (ROOT/'results/008_alignment_summary.json').write_text(json.dumps(summaries,indent=2)+'\n') print(json.dumps(summaries,indent=2)) if __name__=='__main__':main()