HaomingLuo's picture
Synchronize reproducibility schema and branch-attempt provenance
9e38820 verified
Raw History Blame Contribute Delete
4.81 kB
"""Explicit publication whitelist, generated summaries and figures."""
from pathlib import Path
import json,gzip,shutil,hashlib,platform,importlib.metadata
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
R=Path(__file__).resolve().parents[1]
def main():
rows=[json.loads(l) for l in (R/'data/equilibria.jsonl').open()]
dataset=R/'release/dataset';model=R/'release/model'
for root in [dataset,model]:
for d in ['src','tests','reports','assets']: (root/d).mkdir(parents=True,exist_ok=True)
for folder in ['src','tests']:
for p in (R/folder).glob('*.py'):shutil.copy2(p,root/folder/p.name)
for p in (R/'reports').glob('*.json'):shutil.copy2(p,root/'reports'/p.name)
for name in ['SCHEMA.md','requirements.txt','LICENSE-CODE','LICENSE-DATA']:shutil.copy2(R/name,root/name)
(dataset/'states').mkdir(exist_ok=True)
for split in ['train','validation','test','parameter_ood']:
with gzip.open(dataset/f'states/{split}.jsonl.gz','wt') as f:
for row in rows:
if row['split']==split:f.write(json.dumps(row,allow_nan=False,separators=(',',':'))+'\n')
(dataset/'validation').mkdir(exist_ok=True)
with gzip.open(dataset/'validation/paired_resolution.jsonl.gz','wt') as f:f.write((R/'data/paired_resolution.jsonl').read_text())
(dataset/'validation/rejected_attempts.json').write_text('[]\n')
with gzip.open(dataset/'validation/discarded_seed_attempts.jsonl.gz','wt') as f:f.write((R/'data/discarded_seed_attempts.jsonl').read_text())
native=R/'cases/fig9/outputs/003-downward-single-geometry'
for folder in ['paraview','xdmf','scientific','figures']:
shutil.copytree(native/folder,dataset/'native_fe'/folder,dirs_exist_ok=True)
for name in ['native_fe_metrics.csv','paraview_checks.json']:shutil.copy2(native/name,dataset/'native_fe'/name)
(dataset/'cases/fig9').mkdir(parents=True,exist_ok=True)
for name in ['case.py','paper_reference.py','agentfem.toml']:shutil.copy2(R/'cases/fig9'/name,dataset/'cases/fig9'/name)
shutil.copytree(R/'models',model/'models',dirs_exist_ok=True)
environment={name:importlib.metadata.version(name) for name in ['numpy','scipy','torch','safetensors','matplotlib','h5py']}
environment.update(python=platform.python_version(),platform=platform.platform(),agentfem_commit='36f4c1b06ce8a37988eea50bd139fd2d3513985d')
for root in [R,dataset,model]:(root/'reports/environment.json').write_text(json.dumps(environment,indent=2))
plt.rcParams.update({'font.family':'DejaVu Sans','text.color':'#e6efed','axes.labelcolor':'#8fa5a7','xtick.color':'#61777c','ytick.color':'#61777c'})
fig,axes=plt.subplots(1,3,figsize=(15,6),facecolor='#091317')
titles=['Driven by force','Programmed curvature','One load. Three branches.']
families=['end_load','intrinsic_curvature','microforce']
for ax,family,title in zip(axes,families,titles):
ax.set_facecolor('#091317');ax.set_aspect('equal');ax.set_xlim(-.55,1.1);ax.set_ylim(-1.05,1.05)
ax.set_xticks([]);ax.set_yticks([])
for sp in ax.spines.values():sp.set_visible(False)
ax.axhline(0,color='#244048',lw=.5);ax.axvline(0,color='#244048',lw=.5)
if family=='microforce':
chosen=[v for v in rows if v['scene_id']=='microforce_000' and v['step']==16]
else:
chosen=[v for v in rows if v['family']==family and v['path_kind']=='ramp' and v['step']==24][::5][:12]
for i,v in enumerate(chosen):
xy=np.array(v['centerline']);color='#e3ac72' if v['branch']=='straight' else '#78d6ca'
ax.plot(*xy.T,color=color,alpha=.3+.7*(i+1)/len(chosen),lw=2.2)
ax.scatter(*xy[-1],s=12,color=color,zorder=4)
ax.scatter(0,0,s=40,color='#f1f5ed',zorder=5)
ax.set_title(title,fontsize=13,loc='left',pad=20,color='#eff6f1')
fig.text(.055,.93,'AgentFEM / MORPH LAB',color='#78d6ca',fontsize=12,weight='bold')
fig.text(.055,.055,'Programmable rods 路 Equilibrium branches 路 Inverse shape design',fontsize=15,color='#f1f5ed')
fig.subplots_adjust(top=.82,bottom=.15,wspace=.14,left=.055,right=.97)
for root in [dataset,model]:fig.savefig(root/'assets/overview.png',dpi=140,facecolor=fig.get_facecolor())
plt.close(fig)
# Only original code/data/figures enter release. Never include paper PDF,
# authentication, failed-run scratch, local absolute-path execution logs.
for root in [dataset,model]:
hashes={str(p.relative_to(root)):hashlib.sha256(p.read_bytes()).hexdigest() for p in sorted(root.rglob('*')) if p.is_file() and p.name!='SHA256SUMS.json'}
(root/'SHA256SUMS.json').write_text(json.dumps(hashes,indent=2))
print('Packaged',len(rows),'states')
if __name__=='__main__':main()