File size: 4,811 Bytes
f13a251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9e38820
f13a251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
"""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()