feat: 导入 IRSTD 研究代码与文档(小目标检测)

- 新增 irstd 核心包、scripts、tests、configs
- 新增研究文档:literature_review / mathematical_analysis / novelty_matrix / experiment_plan / research_decision / research_log / manuscript_outline
- 新增 evidence、results 数据与审计产物
- 新增 pyproject.toml、requirements、.gitignore
This commit is contained in:
u52f85420 committed 2026-11-01 10:10:33 +00:00
1 parent 9b4a29c4d2
commit 04bf90c09b
35 files changed
+2220 -2

No files matched your search

+46
View File
@@ -0,0 +1,46 @@
import unittest,tempfile,csv,json,subprocess,sys,os
from pathlib import Path
import numpy as np
from PIL import Image
from irstd.data import sha,read_manifest
class PipelineTests(unittest.TestCase):
def make_fixture(self,root):
rows=[];pred=root/'pred';pred.mkdir()
for i,split in enumerate(['train','dev','cal','cal','test']):
name=f'image{i}';x=np.full((9,9),i,np.uint8);x[4,4]=200+i
y=np.zeros((9,9),np.uint8);y[4,4]=255
Image.fromarray(x).save(root/(name+'.png'));Image.fromarray(y).save(root/(name+'_mask.png'))
prob=np.zeros((9,9),np.float32);prob[4,4]=.9;np.save(pred/(name+'.npy'),prob)
rows.append(dict(id=name,image=name+'.png',mask=name+'_mask.png',split=split,group='g'+str(i)))
manifest=root/'manifest.csv'
with manifest.open('w',newline='') as f:
w=csv.DictWriter(f,fieldnames=list(rows[0]));w.writeheader();w.writerows(rows)
(pred/'provenance.json').write_text(json.dumps(dict(checkpoint_sha256='synthetic_fixture_not_a_checkpoint',manifest_sha256=sha(manifest))))
return manifest,pred,rows
def run_script(self,name,args):
return subprocess.run([sys.executable,'scripts/'+name]+list(map(str,args)),capture_output=True,text=True)
def test_cpu_calibration_evaluation_and_tamper_guard(self):
with tempfile.TemporaryDirectory() as d:
root=Path(d);manifest,pred,_=self.make_fixture(root)
cert=root/'cert.json';out=root/'eval.json'
common=['--manifest',manifest,'--predictions',pred]
r=self.run_script('evaluate.py',common+['--split','cal','--calibrate','--out',cert,'--alpha','.01'])
self.assertEqual(r.returncode,0,r.stderr);self.assertTrue(json.loads(cert.read_text())['reject_all'])
r=self.run_script('evaluate.py',common+['--certificate',cert,'--out',out])
self.assertEqual(r.returncode,0,r.stderr);self.assertEqual(json.loads(out.read_text())['metrics']['Pd'],0.)
np.save(pred/'image4.npy',np.ones((9,9),np.float32))
r=self.run_script('evaluate.py',common+['--certificate',cert,'--out',root/'tampered.json'])
self.assertNotEqual(r.returncode,0);self.assertIn('invalidated',r.stderr)
def test_data_audit_cli(self):
with tempfile.TemporaryDirectory() as d:
root=Path(d);manifest,_,_=self.make_fixture(root);out=root/'audit.json'
r=self.run_script('audit_data.py',['--manifest',manifest,'--out',out])
self.assertEqual(r.returncode,0,r.stderr);report=json.loads(out.read_text())
self.assertEqual(report['area_bins']['1-4'],5);self.assertEqual(report['splits']['cal'],2)
def test_group_leakage_rejected(self):
with tempfile.TemporaryDirectory() as d:
root=Path(d);manifest,_,rows=self.make_fixture(root);rows[-1]['group']=rows[0]['group']
with manifest.open('w',newline='') as f:
w=csv.DictWriter(f,fieldnames=list(rows[0]));w.writeheader();w.writerows(rows)
with self.assertRaisesRegex(ValueError,'crosses splits'):read_manifest(manifest)