import json,math,csv,statistics
from pathlib import Path
p=Path(__file__).parent;b=p/'bundle';r=p/'rerun/results';e=p/'evidence';e.mkdir(exist_ok=True)
claim=json.loads((b/'claims.json').read_text())[0]
def get(root,key):
 f,*keys=key.split('.');v=json.loads((root/(f+'.json')).read_text())
 for k in keys:v=v[k]
 return v
checks=[]
for item in claim['evidence']:
 k=item['result'];a=get(b/'results',k);z=get(r,k);tol=item.get('tolerance',0)
 ok=(type(a)==type(z) and a==z) if isinstance(a,(str,bool)) else (abs(a-z)<=tol)
 checks.append({'result':k,'expected':a,'actual':z,'tolerance':tol,'matches':ok})
(e/'comparisons.json').write_text(json.dumps(checks,indent=2));assert all(x['matches'] for x in checks)
# Independent average ranks and Spearman on the regenerated aggregate table.
rows=list(csv.DictReader((r/'per_subclass.csv').open()))
def ranks(xs):
 o=sorted(range(len(xs)),key=xs.__getitem__);out=[0.]*len(xs);i=0
 while i<len(o):
  j=i+1
  while j<len(o) and xs[o[j]]==xs[o[i]]:j+=1
  for k in range(i,j):out[o[k]]=(i+j+1)/2
  i=j
 return out
a=ranks([float(t['E']) for t in rows]);z=ranks([float(t['excess']) for t in rows]);ma=statistics.mean(a);mz=statistics.mean(z)
rho=sum((x-ma)*(y-mz) for x,y in zip(a,z))/math.sqrt(sum((x-ma)**2 for x in a)*sum((y-mz)**2 for y in z))
assert abs(rho-get(r,'R1.rho'))<1e-7
summary={'evidence_fields_checked':len(checks),'all_match':True,'independent_aggregate_rho':rho,'n_subclasses':len(rows),'neuron_count_from_subclasses':sum(int(t['n_analysed']) for t in rows),'scope':'Full supplied analysis rerun from supplied compact inputs, plus independent rank-correlation and count arithmetic; upstream multi-gigabyte source preprocessing not rebuilt.'}
(e/'independent-check.json').write_text(json.dumps(summary,indent=2));print(summary)
