test: implement independently reviewed rising-crossing assessor v2
This commit is contained in:
1 parent
1ca3bb89f1
commit
236994926f
3 files changed
+282
No files matched your search
@@ -0,0 +1,92 @@
|
||||
"""Versioned read-only DFG reanalysis; never overwrites a flow receipt."""
|
||||
import argparse
|
||||
import csv
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import zipfile
|
||||
import numpy as np
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||||
import periodic as frozen
|
||||
import periodic_v2 as v2
|
||||
|
||||
OFFICIAL_SHA256 = '08db59605b2f60efc512d2bbc79628ea5d1cc720c0986938a16920884a0215be'
|
||||
PREFIX = 'logs/results_cc2d_bench2_referencenew/'
|
||||
|
||||
|
||||
def sha(path): return hashlib.sha256(Path(path).read_bytes()).hexdigest()
|
||||
|
||||
|
||||
def official_reference(path):
|
||||
if sha(path) != OFFICIAL_SHA256: raise ValueError('Wrong official archive')
|
||||
with zipfile.ZipFile(path) as z:
|
||||
force = np.loadtxt(io.BytesIO(z.read(PREFIX+'bdforces_q2_lv6_dt4')))
|
||||
pressure = np.loadtxt(io.BytesIO(z.read(PREFIX+'pointvalues_q2_lv6_dt4')))
|
||||
tf=force[:,1]*10; tp=pressure[:,1]*10
|
||||
if not np.isfinite(force).all() or not np.isfinite(pressure).all():
|
||||
raise ValueError('Nonfinite official input')
|
||||
if np.any(np.diff(tf)<=0) or np.any(np.diff(tp)<=0): raise ValueError('Official time order')
|
||||
# Entire supplied interval, restricted only to shared force/pressure coverage.
|
||||
mask=(tf>=tp[0])&(tf<=tp[-1]); force=force[mask]; tf=tf[mask]
|
||||
dp=np.interp(tf,tp,pressure[:,6]-pressure[:,11])
|
||||
rows=[dict(tstar=float(t),tstar_force=float(t),cd=float(f[3]),cl=float(f[4]),dp=float(p),
|
||||
mass=1.,flux_in=1.,flux_out=1.) for t,f,p in zip(tf,force,dp)]
|
||||
cycles=v2.extract(rows,min_time=0.)
|
||||
if not cycles: raise ValueError('No complete official cycle')
|
||||
ref=cycles[-1]
|
||||
return ref,dict(archive_sha256=OFFICIAL_SHA256,selection='lv6/dt4 last complete ascending Cl=0 cycle in entire shared input coverage',
|
||||
eligible_time=[float(tf[0]),float(tf[-1])],complete_cycles=len(cycles),
|
||||
pressure='columns7 minus12, interpolated at original force times; physical time multiplied by10',
|
||||
artificial_fields='mass/flux placeholders only; official archive is not used to certify conservation')
|
||||
|
||||
|
||||
def main():
|
||||
parser=argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--official-archive',type=Path,required=True)
|
||||
parser.add_argument('--history',action='append',required=True,help='Unique label=CSV path; all cases reported')
|
||||
parser.add_argument('--output',type=Path,required=True)
|
||||
a=parser.parse_args()
|
||||
if a.output.exists(): raise ValueError('Use a new output directory')
|
||||
cases=[]; labels=set()
|
||||
reference,reference_info=official_reference(a.official_archive)
|
||||
old_ref_path=Path(frozen.__file__).parent/'data/dfg_re100/reference_cycle.json'
|
||||
old_ref=json.loads(old_ref_path.read_text())
|
||||
for item in a.history:
|
||||
label,path=item.split('=',1); path=Path(path)
|
||||
if label in labels: raise ValueError('Duplicate case label')
|
||||
labels.add(label)
|
||||
rows=[{k:float(v) for k,v in r.items()} for r in csv.DictReader(path.open())]
|
||||
source_receipt_path=path.with_name('summary.json')
|
||||
source_receipt=json.loads(source_receipt_path.read_text())
|
||||
if rows != source_receipt.get('history'):
|
||||
raise ValueError('CSV differs from original summary history')
|
||||
old=frozen.assess(rows); new=v2.assess(rows)
|
||||
for key in ('periodic', 'checks', 'cycles'):
|
||||
if old[key] != source_receipt.get(key):
|
||||
raise ValueError('Frozen reassessment differs from original summary')
|
||||
old_comparison=frozen.compare(old['cycles'][-1],old_ref) if old['cycles'] else None
|
||||
new_comparison=v2.compare(new['cycles'][-1],reference) if new['cycles'] else None
|
||||
# This is assessment of recorded observables, not proof of unrecorded population health.
|
||||
healthy=bool(rows and all(.5<=r['rho_min']<=r['rho_max']<=1.5 and 0<=r['max_mach']<=.2 for r in rows))
|
||||
cases.append(dict(label=label,input_csv_sha256=sha(path),
|
||||
original_summary_sha256=sha(source_receipt_path),
|
||||
original_identity={k:source_receipt[k] for k in ('case','collision','observation_mode','numerical_source_commit','checkout','checkout_revision','mode','status') if k in source_receipt},
|
||||
observations=len(rows),
|
||||
recorded_end_tstar=rows[-1]['tstar'] if rows else None,recorded_observations_healthy=healthy,
|
||||
frozen=old,frozen_reference=old_comparison,v2=new,v2_reference=new_comparison,
|
||||
v2_recorded_observable_agreement=bool(healthy and new['periodic'] and new_comparison and new_comparison['reference_agreement'])))
|
||||
a.output.mkdir(parents=True)
|
||||
result=dict(assessment_version=v2.VERSION,original_receipts_unchanged=True,
|
||||
phase='Every ascending Cl<0 to Cl>=0 crossing; linear interpolation, no suppression',
|
||||
gates=v2.GATES,reference_gates=v2.REFERENCE_GATES,reference=reference,reference_provenance=reference_info,
|
||||
code_sha256={Path(p).name:sha(p) for p in [__file__,v2.__file__,frozen.__file__]},
|
||||
frozen_reference_sha256=sha(old_ref_path),cases=cases)
|
||||
(a.output/'reanalysis.json').write_text(json.dumps(result,indent=2,allow_nan=False)+'\n')
|
||||
print(json.dumps([dict(case=c['label'],old_periodic=c['frozen']['periodic'],
|
||||
v2_checks=c['v2']['checks'],v2_reference=c['v2_reference'],
|
||||
recorded_observable_agreement=c['v2_recorded_observable_agreement']) for c in cases],indent=2))
|
||||
|
||||
|
||||
if __name__=='__main__': main()
|
||||
Reference in new issue
Block a user