import os, re, glob, csv, sys
import numpy as np
ROOT="<directory of the runs>"
def load(f, delim=None):
    rows=[]
    for line in open(f):
        if line.startswith('#') or not line.strip(): continue
        try: rows.append([float(x) for x in (line.split(delim) if delim else line.split())])
        except ValueError: pass
    n=max(len(r) for r in rows); rows=[r for r in rows if len(r)==n]
    return np.array(rows)
def inp_info(f):
    t=open(f).read(); d={}
    m=re.search(r'^Laser:.*\n\s*(\w+),\s*([\d.eE+-]+),\s*([\d.]+) OptCyc,\s*([\d.]+)',t,re.M)
    d['shape'],d['I']=m.group(1),float(m.group(2)); d['fwhm_cyc']=float(m.group(3)); d['lam']=float(m.group(4))
    d['box']=float(re.search(r'#define BOX ([\d.]+)',t).group(1))
    d['theta']=float(re.search(r'^ECS,Rn,([\d.]+)',t,re.M).group(1))
    d['state']=int(re.search(r'^Initial: state=(\d+)',t,re.M).group(1))
    d['eta']=int(re.search(r'^ Eta,(\d+)',t,re.M).group(1))
    d['phi']=re.search(r'^ Phi,(.*)$',t,re.M).group(1)
    d['fixStep']=float(t.strip().split(',')[-1])
    return d
out=[]
for fam_dir in ["ar_intensity_scan","he_intensity_scan"]:
    for inp in sorted(glob.glob(f"{ROOT}/{fam_dir}/*_[0-9][0-9].inp")):
        name=os.path.basename(inp)[:-4]; rd=f"{ROOT}/{fam_dir}/{name}/0000"
        d=inp_info(inp); d['name']=name; d['family']=name.rsplit('_',1)[0]
        d['completed']= os.path.isfile(rd+"/log") and 'run completed' in open(rd+"/log").read()
        d['nruns']=len(glob.glob(f"{ROOT}/{fam_dir}/{name}/0*"))
        if os.path.isfile(rd+"/expec"):
            e=load(rd+"/expec")
            d['t0'],d['t1']=e[0,0],e[-1,0]; d['H0_init']=e[0,3]; d['H0_final']=e[-1,3]
            d['norm_loss']=1-e[-1,2]; d['chi_loss']=1-e[-1,4]; d['nexpec']=len(e)
            # rate of change of chi over last interval
            if len(e)>3 and e[-1,0]==e[-2,0]: e=e[:-1]
            if len(e)>1: d['chi_loss_prev']=1-e[-2,4]; d['norm_loss_prev']=1-e[-2,2]; d['dt_prev']=e[-1,0]-e[-2,0]
        if os.path.isfile(rd+"/Laser"):
            L=load(rd+"/Laser"); d['Epeak']=np.abs(L[:,5]).max(); d['Apeak']=np.abs(L[:,4]).max()
            d['laser_t0'],d['laser_t1']=L[0,0],L[-1,0]
            d['E_at_end']=abs(L[-1,5]); 
        if os.path.isfile(rd+"/spec_total"):
            s=load(rd+"/spec_total",',') ; k=s[:,0]; sg=s[:,1]
            d['isurff']=np.trapezoid(sg*k*k,k); d['kmax']=k[-1]; d['spec_tail_frac']=(sg[-1]*k[-1]**2)/ (sg*k*k).max()
        w=rd+"/WARNINGS"
        d['warnings']=' | '.join(l.strip() for l in open(w) if re.match(r'\s+\d+:',l)) if os.path.isfile(w) else ''
        out.append(d)
keys=['family','name','shape','I','box','theta','eta','state','fixStep','completed','nruns','t0','t1','H0_init','H0_final','Epeak','Apeak','E_at_end','chi_loss','norm_loss','chi_loss_prev','norm_loss_prev','dt_prev','isurff','kmax','spec_tail_frac','nexpec','warnings']
with open("all_runs.csv","w",newline='') as f:
    w=csv.DictWriter(f,keys,extrasaction='ignore'); w.writeheader(); [w.writerow(d) for d in out]
for d in out:
    print(f"{d['name']:16s} {d['shape']:5s} I={d['I']:.4e} box={d['box']:.0f} th={d['theta']} st={d['state']} dt={d['fixStep']} done={d['completed']} n={d['nruns']} t=[{d.get('t0',0):.1f},{d.get('t1',0):.1f}] H0={d.get('H0_init',float('nan')):.6f}->{d.get('H0_final',float('nan')):.5f} Epk={d.get('Epeak',float('nan')):.5f} E0nom={np.sqrt(d['I']/3.50945e16):.5f} chi={d.get('chi_loss',float('nan')):.4e} norm={d.get('norm_loss',float('nan')):.4e} chiprev={d.get('chi_loss_prev',float('nan')):.4e} is={d.get('isurff',float('nan')):.4e} kmax={d.get('kmax',float('nan')):.2f} tail={d.get('spec_tail_frac',float('nan')):.1e} nexp={d.get('nexpec')} W:{d['warnings'][:60]}")
