Yuan (Cyrus) Chiang commited on
Commit
3397e50
·
unverified ·
1 Parent(s): 75ac94f

Add eSEN EOS (#59, #56)

Browse files

Add eSEN EOS and EV scan results following #56

Files changed (46) hide show
  1. .gitattributes +7 -0
  2. .github/workflows/sync-hf.yaml +1 -1
  3. .github/workflows/test.yaml +39 -11
  4. examples/eos_bulk/CHGNet_processed.parquet +2 -2
  5. examples/eos_bulk/M3GNet_processed.parquet +2 -2
  6. examples/eos_bulk/MACE-MP(M)_processed.parquet +2 -2
  7. examples/eos_bulk/MACE-MPA_processed.parquet +2 -2
  8. examples/eos_bulk/MatterSim_processed.parquet +2 -2
  9. examples/eos_bulk/ORBv2_processed.parquet +2 -2
  10. examples/eos_bulk/SevenNet_processed.parquet +2 -2
  11. examples/eos_bulk/eSEN.parquet +3 -0
  12. examples/eos_bulk/eSEN_processed.parquet +3 -0
  13. examples/eos_bulk/run.py +107 -72
  14. examples/eos_bulk/summary.csv +8 -7
  15. examples/eos_bulk/summary.tex +8 -7
  16. examples/mof/CHGNet.pkl +0 -0
  17. examples/mof/M3GNet.pkl +0 -0
  18. examples/mof/MACE-MP(M).pkl +0 -0
  19. examples/mof/MACE-MPA.pkl +0 -0
  20. examples/mof/MatterSim.pkl +0 -0
  21. examples/mof/ORBv2.pkl +0 -0
  22. examples/mof/classification/M3GNet.pkl +3 -0
  23. examples/mof/classification/MACE-MP(M).pkl +3 -0
  24. examples/mof/classification/MACE-MPA.pkl +3 -0
  25. examples/mof/classification/MatterSim.pkl +3 -0
  26. examples/mof/classification/ORBv2.pkl +3 -0
  27. examples/mof/classification/SevenNet.pkl +3 -0
  28. examples/mof/classification/analysis.ipynb +380 -0
  29. examples/mof/classification/input.pkl +3 -0
  30. examples/mof/classification/mof-misclassification_margin.pdf +0 -0
  31. examples/wbm_ev/ALIGNN_processed.parquet +2 -2
  32. examples/wbm_ev/CHGNet_processed.parquet +2 -2
  33. examples/wbm_ev/M3GNet_processed.parquet +2 -2
  34. examples/wbm_ev/MACE-MP(M)_processed.parquet +2 -2
  35. examples/wbm_ev/MACE-MPA_processed.parquet +2 -2
  36. examples/wbm_ev/MatterSim_processed.parquet +2 -2
  37. examples/wbm_ev/ORBv2_processed.parquet +2 -2
  38. examples/wbm_ev/SevenNet_processed.parquet +2 -2
  39. examples/wbm_ev/eSEN.parquet +3 -0
  40. examples/wbm_ev/eSEN_processed.parquet +3 -0
  41. examples/wbm_ev/eqV2(OMat)_processed.parquet +2 -2
  42. examples/wbm_ev/run.py +38 -38
  43. examples/wbm_ev/summary.csv +10 -9
  44. examples/wbm_ev/summary.tex +10 -9
  45. mlip_arena/models/registry.yaml +4 -2
  46. pyproject.toml +3 -3
.gitattributes CHANGED
@@ -1,3 +1,10 @@
1
  *.json filter=lfs diff=lfs merge=lfs -text
2
  *.parquet filter=lfs diff=lfs merge=lfs -text
3
  *.db filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
1
  *.json filter=lfs diff=lfs merge=lfs -text
2
  *.parquet filter=lfs diff=lfs merge=lfs -text
3
  *.db filter=lfs diff=lfs merge=lfs -text
4
+ examples/mof/classification/SevenNet.pkl filter=lfs diff=lfs merge=lfs -text
5
+ examples/mof/classification/input.pkl filter=lfs diff=lfs merge=lfs -text
6
+ examples/mof/classification/M3GNet.pkl filter=lfs diff=lfs merge=lfs -text
7
+ examples/mof/classification/MACE-MPA.pkl filter=lfs diff=lfs merge=lfs -text
8
+ examples/mof/classification/MACE-MP(M).pkl filter=lfs diff=lfs merge=lfs -text
9
+ examples/mof/classification/MatterSim.pkl filter=lfs diff=lfs merge=lfs -text
10
+ examples/mof/classification/ORBv2.pkl filter=lfs diff=lfs merge=lfs -text
.github/workflows/sync-hf.yaml CHANGED
@@ -12,7 +12,7 @@ jobs:
12
  if: ${{ github.event.workflow_run.conclusion == 'success' }}
13
  runs-on: ubuntu-latest
14
  steps:
15
- - uses: actions/checkout@v3
16
  with:
17
  fetch-depth: 0
18
  lfs: true
 
12
  if: ${{ github.event.workflow_run.conclusion == 'success' }}
13
  runs-on: ubuntu-latest
14
  steps:
15
+ - uses: actions/checkout@v4
16
  with:
17
  fetch-depth: 0
18
  lfs: true
.github/workflows/test.yaml CHANGED
@@ -14,14 +14,15 @@ jobs:
14
  runs-on: ubuntu-latest
15
 
16
  strategy:
17
- # max-parallel: 2
18
  matrix:
19
  python-version: ["3.10", "3.11", "3.12"]
20
-
21
 
22
  steps:
23
- - name: Checkout repository
24
  uses: actions/checkout@v4
 
 
 
25
 
26
  - name: Install uv
27
  uses: astral-sh/setup-uv@v6
@@ -36,22 +37,49 @@ jobs:
36
  python-version: ${{ matrix.python-version }}
37
 
38
  - name: Install dependencies
39
- run: |
40
- bash scripts/install-linux.sh
41
 
42
  - name: List dependencies
43
  run: pip list
44
-
45
- - name: Login huggingface
46
- # if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
47
  env:
48
  HF_TOKEN: ${{ secrets.HF_TOKEN_READ_ONLY }}
49
- run:
50
- huggingface-cli login --token $HF_TOKEN
51
 
52
  - name: Run tests
53
  env:
54
  PREFECT_API_KEY: ${{ secrets.PREFECT_API_KEY }}
55
  PREFECT_API_URL: ${{ secrets.PREFECT_API_URL }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  run: |
57
- pytest -vra -n 5 --dist=loadscope tests
 
14
  runs-on: ubuntu-latest
15
 
16
  strategy:
 
17
  matrix:
18
  python-version: ["3.10", "3.11", "3.12"]
 
19
 
20
  steps:
21
+ - name: Checkout PR with full history
22
  uses: actions/checkout@v4
23
+ with:
24
+ lfs: true
25
+ fetch-depth: 0
26
 
27
  - name: Install uv
28
  uses: astral-sh/setup-uv@v6
 
37
  python-version: ${{ matrix.python-version }}
38
 
39
  - name: Install dependencies
40
+ run: bash scripts/install-linux.sh
 
41
 
42
  - name: List dependencies
43
  run: pip list
44
+
45
+ - name: Login to Hugging Face
 
46
  env:
47
  HF_TOKEN: ${{ secrets.HF_TOKEN_READ_ONLY }}
48
+ run: huggingface-cli login --token $HF_TOKEN
 
49
 
50
  - name: Run tests
51
  env:
52
  PREFECT_API_KEY: ${{ secrets.PREFECT_API_KEY }}
53
  PREFECT_API_URL: ${{ secrets.PREFECT_API_URL }}
54
+ run: pytest -vra -n 5 --dist=loadscope tests
55
+
56
+ - name: Squash commits and trial push to Hugging Face
57
+ if: github.event_name == 'pull_request'
58
+ id: trial_push
59
+ env:
60
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
61
+ TRIAL_BRANCH: trial-sync-${{ github.sha }}
62
+ run: |
63
+ # Configure Git user identity
64
+ git config user.name "github-actions[ci]"
65
+ git config user.email "github-actions[ci]@users.noreply.github.com"
66
+
67
+ # Rebase and squash all PR commits into one
68
+ BASE=$(git merge-base origin/main HEAD)
69
+ git reset --soft $BASE
70
+ git commit -m "Squashed commit from PR #${{ github.event.pull_request.number }}"
71
+
72
+ # Setup LFS
73
+ git lfs fetch
74
+ git lfs checkout
75
+
76
+ # Push to temporary branch on Hugging Face
77
+ git push -f https://HF_USERNAME:$HF_TOKEN@huggingface.co/spaces/atomind/mlip-arena HEAD:refs/heads/$TRIAL_BRANCH
78
+
79
+ - name: Delete trial branch from Hugging Face
80
+ if: steps.trial_push.outcome == 'success'
81
+ env:
82
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
83
+ TRIAL_BRANCH: trial-sync-${{ github.sha }}
84
  run: |
85
+ git push https://HF_USERNAME:$HF_TOKEN@huggingface.co/spaces/atomind/mlip-arena --delete $TRIAL_BRANCH || true
examples/eos_bulk/CHGNet_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:d6fbea63f9035e376bb5ac7db38175102ab3f96a0f8758cc3e9931424f829ac0
3
- size 357919
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0416eeed1748994b67e8f6e9768a5f1d2a77c19f9512bc408f9b39ca3c19e3d4
3
+ size 358042
examples/eos_bulk/M3GNet_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:18ea51bf19c5e011e170a3229bbd63ce675a725c364e0cffb71de95459f8629e
3
- size 379859
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1a34f8148f771f0b751f01ccc9d260fd5ae48b625b979ec2112e008c82c59a08
3
+ size 379982
examples/eos_bulk/MACE-MP(M)_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:2f492125c87400fee013d32904ee97df49a07d321bd393f9335c7bf4258fe159
3
- size 371004
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:73e2b8ad6d5e114c1c0fea4697b17810182d0b273185512cb40fa894ea30b4c3
3
+ size 371128
examples/eos_bulk/MACE-MPA_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:34bd9ae08656e374263820774f49e91a964aa8b2aeade4150cf62cfc08bb37f6
3
- size 365289
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:819bc0c721e99df8dda0a4c6df565deb96736ecc5ceefefe300e5b72b7d6312f
3
+ size 365412
examples/eos_bulk/MatterSim_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:cca22b5db67dae59602adfb8c42a80da90b39c4e95af89ef918813351b422119
3
- size 320962
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c707ffb285f03a5c7d1486a6998c787088f07a97b206585b17839fff4fab49b4
3
+ size 321086
examples/eos_bulk/ORBv2_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:c90e61645c83f2452bcd90ef9132c46266896217fe1dea9cca8e0d124d73821a
3
- size 227929
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f794da83d1031823577b085c480f7d285520c086bdd0e7e6e7acb7a5a2457329
3
+ size 228052
examples/eos_bulk/SevenNet_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:5cc03d9af93c001f3fa441b50f058506e13c0aa7cb3d329275e68f5ed80dc3e6
3
- size 364846
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a9aab95402aa62169ba6f1e12a7774362b3e5cc027f5c556de734783e6d6f29b
3
+ size 364969
examples/eos_bulk/eSEN.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4503e17151b7376bbd88dc8c4767747e7290e8eae898e050b0a231a5c447e3e6
3
+ size 427652
examples/eos_bulk/eSEN_processed.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3d12b36a2bd465e16ada4363e31756d5de5d41dd890d0e88e8ca86b76dd66336
3
+ size 313235
examples/eos_bulk/run.py CHANGED
@@ -1,57 +1,70 @@
1
- import functools
2
  from pathlib import Path
3
 
4
  import pandas as pd
 
5
  from ase.db import connect
6
  from dask.distributed import Client
7
  from dask_jobqueue import SLURMCluster
8
- from prefect import Task, flow, task
9
- from prefect.client.schemas.objects import TaskRun
10
- from prefect.states import State
11
  from prefect_dask import DaskTaskRunner
12
 
13
  from mlip_arena.models import REGISTRY, MLIPEnum
14
- from mlip_arena.tasks.eos import run as EOS
15
- from mlip_arena.tasks.optimize import run as OPT
16
  from mlip_arena.tasks.utils import get_calculator
17
 
18
 
19
  @task
20
  def load_wbm_structures():
21
  """
22
- Load the WBM structures from a ASE DB file.
 
 
 
 
 
 
 
23
  """
24
  with connect("../wbm_structures.db") as db:
25
  for row in db.select():
26
  yield row.toatoms(add_additional_information=True)
27
 
28
 
29
- def save_result(
30
- tsk: Task,
31
- run: TaskRun,
32
- state: State,
33
- model_name: str,
34
- id: str,
35
- ):
36
- result = run.state.result()
37
 
38
- assert isinstance(result, dict)
39
 
40
- result["method"] = model_name
41
- result["id"] = id
42
- result.pop("atoms", None)
43
 
44
- fpath = Path(f"{model_name}")
45
- fpath.mkdir(exist_ok=True)
46
 
47
- fpath = fpath / f"{result['id']}.pkl"
48
 
49
- df = pd.DataFrame([result])
50
- df.to_pickle(fpath)
51
 
52
 
53
- @task
54
- def eos_bulk(atoms, model):
 
 
 
 
 
 
 
55
 
56
  calculator = get_calculator(
57
  model
@@ -67,14 +80,13 @@ def eos_bulk(atoms, model):
67
  fmax=0.1,
68
  ),
69
  )
70
-
71
- return EOS.with_options(
72
  refresh_cache=True,
73
- on_completion=[functools.partial(
74
- save_result,
75
- model_name=model.name,
76
- id=atoms.info["key_value_pairs"]["wbm_id"],
77
- )],
78
  )(
79
  atoms=result["atoms"],
80
  calculator=calculator,
@@ -84,52 +96,75 @@ def eos_bulk(atoms, model):
84
  concurrent=False
85
  )
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
  @flow
89
- def run_all():
90
  futures = []
91
  for atoms in load_wbm_structures():
92
- for model in MLIPEnum:
93
- if "eos_bulk" not in REGISTRY[model.name].get("gpu-tasks", []):
94
- continue
95
- result = eos_bulk.submit(atoms, model)
 
 
 
 
96
  futures.append(result)
 
 
 
97
  return [f.result(raise_on_failure=False) for f in futures]
98
 
99
 
100
- nodes_per_alloc = 1
101
- gpus_per_alloc = 1
102
- ntasks = 1
103
-
104
- cluster_kwargs = dict(
105
- cores=4,
106
- memory="64 GB",
107
- shebang="#!/bin/bash",
108
- account="m3828",
109
- walltime="00:50:00",
110
- job_mem="0",
111
- job_script_prologue=[
112
- "source ~/.bashrc",
113
- "module load python",
114
- "source activate /pscratch/sd/c/cyrusyc/.conda/mlip-arena",
115
- ],
116
- job_directives_skip=["-n", "--cpus-per-task", "-J"],
117
- job_extra_directives=[
118
- "-J eos_bulk",
119
- "-q regular",
120
- f"-N {nodes_per_alloc}",
121
- "-C gpu",
122
- f"-G {gpus_per_alloc}",
123
- "--exclusive",
124
- ],
125
- )
 
 
126
 
127
- cluster = SLURMCluster(**cluster_kwargs)
128
- print(cluster.job_script())
129
- cluster.adapt(minimum_jobs=20, maximum_jobs=40)
130
- client = Client(cluster)
131
 
132
- run_all.with_options(
133
- task_runner=DaskTaskRunner(address=client.scheduler.address),
134
- log_prints=True,
135
- )()
 
1
+ # import functools
2
  from pathlib import Path
3
 
4
  import pandas as pd
5
+ from ase import Atoms
6
  from ase.db import connect
7
  from dask.distributed import Client
8
  from dask_jobqueue import SLURMCluster
9
+ from prefect import flow, task
10
+ from prefect.cache_policies import INPUTS, TASK_SOURCE
11
+ from prefect.runtime import task_run
12
  from prefect_dask import DaskTaskRunner
13
 
14
  from mlip_arena.models import REGISTRY, MLIPEnum
 
 
15
  from mlip_arena.tasks.utils import get_calculator
16
 
17
 
18
  @task
19
  def load_wbm_structures():
20
  """
21
+ Load the WBM structures from an ASE database file.
22
+
23
+ Reads structures from 'wbm_structures.db' and yields them as ASE Atoms objects
24
+ with additional metadata preserved from the database.
25
+
26
+ Yields:
27
+ ase.Atoms: Individual atomic structures from the WBM database with preserved
28
+ metadata in the .info dictionary.
29
  """
30
  with connect("../wbm_structures.db") as db:
31
  for row in db.select():
32
  yield row.toatoms(add_additional_information=True)
33
 
34
 
35
+ # def save_result(
36
+ # tsk: Task,
37
+ # run: TaskRun,
38
+ # state: State,
39
+ # model_name: str,
40
+ # id: str,
41
+ # ):
42
+ # result = run.state.result()
43
 
44
+ # assert isinstance(result, dict)
45
 
46
+ # result["method"] = model_name
47
+ # result["id"] = id
48
+ # result.pop("atoms", None)
49
 
50
+ # fpath = Path(f"{model_name}")
51
+ # fpath.mkdir(exist_ok=True)
52
 
53
+ # fpath = fpath / f"{result['id']}.pkl"
54
 
55
+ # df = pd.DataFrame([result])
56
+ # df.to_pickle(fpath)
57
 
58
 
59
+ @task(
60
+ name="EOS bulk - WBM",
61
+ task_run_name=lambda: f"{task_run.task_name}: {task_run.parameters['atoms'].get_chemical_formula()} - {task_run.parameters['model'].name}",
62
+ cache_policy=TASK_SOURCE + INPUTS,
63
+ )
64
+ def eos_bulk(atoms: Atoms, model: MLIPEnum):
65
+
66
+ from mlip_arena.tasks.eos import run as EOS
67
+ from mlip_arena.tasks.optimize import run as OPT
68
 
69
  calculator = get_calculator(
70
  model
 
80
  fmax=0.1,
81
  ),
82
  )
83
+ result = EOS.with_options(
 
84
  refresh_cache=True,
85
+ # on_completion=[functools.partial(
86
+ # save_result,
87
+ # model_name=model.name,
88
+ # id=atoms.info["key_value_pairs"]["wbm_id"],
89
+ # )],
90
  )(
91
  atoms=result["atoms"],
92
  calculator=calculator,
 
96
  concurrent=False
97
  )
98
 
99
+ result["method"] = model.name
100
+ result["id"] = atoms.info["key_value_pairs"]["wbm_id"]
101
+ result.pop("atoms", None)
102
+
103
+ fpath = Path(f"{model.name}")
104
+ fpath.mkdir(exist_ok=True)
105
+
106
+ fpath = fpath / f"{result['id']}.pkl"
107
+
108
+ df = pd.DataFrame([result])
109
+ df.to_pickle(fpath)
110
+
111
+ return df
112
+
113
 
114
  @flow
115
+ def submit_tasks():
116
  futures = []
117
  for atoms in load_wbm_structures():
118
+ model = MLIPEnum["eSEN"]
119
+ # for model in MLIPEnum:
120
+ if "eos_bulk" not in REGISTRY[model.name].get("gpu-tasks", []):
121
+ continue
122
+ try:
123
+ result = eos_bulk.with_options(
124
+ refresh_cache=True
125
+ ).submit(atoms, model)
126
  futures.append(result)
127
+ except Exception:
128
+ # print(f"Failed to submit task for {model.name}: {e}")
129
+ continue
130
  return [f.result(raise_on_failure=False) for f in futures]
131
 
132
 
133
+ if __name__ == "__main__":
134
+ nodes_per_alloc = 1
135
+ gpus_per_alloc = 1
136
+ ntasks = 1
137
+
138
+ cluster_kwargs = dict(
139
+ cores=1,
140
+ memory="64 GB",
141
+ shebang="#!/bin/bash",
142
+ account="m3828",
143
+ walltime="00:30:00",
144
+ job_mem="0",
145
+ job_script_prologue=[
146
+ "source ~/.bashrc",
147
+ "module load python",
148
+ "module load cudatoolkit/12.4",
149
+ "source activate /pscratch/sd/c/cyrusyc/.conda/dev",
150
+ ],
151
+ job_directives_skip=["-n", "--cpus-per-task", "-J"],
152
+ job_extra_directives=[
153
+ "-J eos_bulk",
154
+ "-q regular",
155
+ f"-N {nodes_per_alloc}",
156
+ "-C gpu",
157
+ f"-G {gpus_per_alloc}",
158
+ # "--exclusive",
159
+ ],
160
+ )
161
 
162
+ cluster = SLURMCluster(**cluster_kwargs)
163
+ print(cluster.job_script())
164
+ cluster.adapt(minimum_jobs=50, maximum_jobs=50)
165
+ client = Client(cluster)
166
 
167
+ submit_tasks.with_options(
168
+ task_runner=DaskTaskRunner(address=client.scheduler.address),
169
+ log_prints=True,
170
+ )()
examples/eos_bulk/summary.csv CHANGED
@@ -1,8 +1,9 @@
1
  model,rank,rank-aggregation,energy-diff-flip-times,tortuosity,spearman-compression-energy,spearman-compression-derivative,spearman-tension-energy,missing
2
- MACE-MPA,1,6,1.0370741482965933,1.005455197941088,-0.9993684338373716,0.9963320580555048,0.993186372745491,2
3
- MACE-MP(M),2,16,1.042211055276382,1.008986842539345,-0.999329983249581,0.9941160347190496,0.9915857612939804,5
4
- MatterSim,3,18,1.045135406218656,1.0060900449752808,-0.99734962463147,0.9927904926901917,0.9880977115916667,3
5
- CHGNet,4,22,1.1053159478435306,1.014753469076796,-0.9964985866690981,0.9929971733381963,0.9866417434120545,3
6
- SevenNet,5,27,1.1093279839518555,1.0186969977862483,-0.9981277164827815,0.9889121911188109,0.9859580417030127,3
7
- M3GNet,6,33,1.1748743718592964,1.0175007963267957,-0.9963209989340641,0.9897426526572255,0.9801690217498693,5
8
- ORBv2,7,42,1.3162134944612287,1.0374718753890275,-0.9918459519667977,0.9701425127407,0.9637462235649547,7
 
 
1
  model,rank,rank-aggregation,energy-diff-flip-times,tortuosity,spearman-compression-energy,spearman-compression-derivative,spearman-tension-energy,missing
2
+ MACE-MPA,1,7,1.0370741482965933,1.005455197941088,-0.9993684338373716,0.9963320580555048,0.993186372745491,2
3
+ eSEN,2,15,1.042211055276382,1.0082267858369258,-0.9993299832495811,0.9968570123343992,0.9920968478757424,5
4
+ MACE-MP(M),3,20,1.042211055276382,1.008986842539345,-0.999329983249581,0.9941160347190496,0.9915857612939804,5
5
+ MatterSim,4,22,1.045135406218656,1.0060900449752808,-0.99734962463147,0.9927904926901917,0.9880977115916667,3
6
+ CHGNet,5,27,1.1053159478435306,1.014753469076796,-0.9964985866690981,0.9929971733381963,0.9866417434120545,3
7
+ SevenNet,6,32,1.1093279839518555,1.0186969977862483,-0.9981277164827815,0.9889121911188109,0.9859580417030127,3
8
+ M3GNet,7,38,1.1748743718592964,1.0175007963267957,-0.9963209989340641,0.9897426526572255,0.9801690217498693,5
9
+ ORBv2,8,48,1.3162134944612287,1.0374718753890275,-0.9918459519667977,0.9701425127407,0.9637462235649547,7
examples/eos_bulk/summary.tex CHANGED
@@ -2,12 +2,13 @@
2
  \toprule
3
  model & rank & rank-aggregation & energy-diff-flip-times & tortuosity & spearman-compression-energy & spearman-compression-derivative & spearman-tension-energy & missing \\
4
  \midrule
5
- MACE-MPA & 1 & 6 & 1.037074 & 1.005455 & -0.999368 & 0.996332 & 0.993186 & 2 \\
6
- MACE-MP(M) & 2 & 16 & 1.042211 & 1.008987 & -0.999330 & 0.994116 & 0.991586 & 5 \\
7
- MatterSim & 3 & 18 & 1.045135 & 1.006090 & -0.997350 & 0.992790 & 0.988098 & 3 \\
8
- CHGNet & 4 & 22 & 1.105316 & 1.014753 & -0.996499 & 0.992997 & 0.986642 & 3 \\
9
- SevenNet & 5 & 27 & 1.109328 & 1.018697 & -0.998128 & 0.988912 & 0.985958 & 3 \\
10
- M3GNet & 6 & 33 & 1.174874 & 1.017501 & -0.996321 & 0.989743 & 0.980169 & 5 \\
11
- ORBv2 & 7 & 42 & 1.316213 & 1.037472 & -0.991846 & 0.970143 & 0.963746 & 7 \\
 
12
  \bottomrule
13
  \end{tabular}
 
2
  \toprule
3
  model & rank & rank-aggregation & energy-diff-flip-times & tortuosity & spearman-compression-energy & spearman-compression-derivative & spearman-tension-energy & missing \\
4
  \midrule
5
+ MACE-MPA & 1 & 7 & 1.037074 & 1.005455 & -0.999368 & 0.996332 & 0.993186 & 2 \\
6
+ eSEN & 2 & 15 & 1.042211 & 1.008227 & -0.999330 & 0.996857 & 0.992097 & 5 \\
7
+ MACE-MP(M) & 3 & 20 & 1.042211 & 1.008987 & -0.999330 & 0.994116 & 0.991586 & 5 \\
8
+ MatterSim & 4 & 22 & 1.045135 & 1.006090 & -0.997350 & 0.992790 & 0.988098 & 3 \\
9
+ CHGNet & 5 & 27 & 1.105316 & 1.014753 & -0.996499 & 0.992997 & 0.986642 & 3 \\
10
+ SevenNet & 6 & 32 & 1.109328 & 1.018697 & -0.998128 & 0.988912 & 0.985958 & 3 \\
11
+ M3GNet & 7 & 38 & 1.174874 & 1.017501 & -0.996321 & 0.989743 & 0.980169 & 5 \\
12
+ ORBv2 & 8 & 48 & 1.316213 & 1.037472 & -0.991846 & 0.970143 & 0.963746 & 7 \\
13
  \bottomrule
14
  \end{tabular}
examples/mof/CHGNet.pkl CHANGED
Binary files a/examples/mof/CHGNet.pkl and b/examples/mof/CHGNet.pkl differ
 
examples/mof/M3GNet.pkl CHANGED
Binary files a/examples/mof/M3GNet.pkl and b/examples/mof/M3GNet.pkl differ
 
examples/mof/MACE-MP(M).pkl CHANGED
Binary files a/examples/mof/MACE-MP(M).pkl and b/examples/mof/MACE-MP(M).pkl differ
 
examples/mof/MACE-MPA.pkl CHANGED
Binary files a/examples/mof/MACE-MPA.pkl and b/examples/mof/MACE-MPA.pkl differ
 
examples/mof/MatterSim.pkl CHANGED
Binary files a/examples/mof/MatterSim.pkl and b/examples/mof/MatterSim.pkl differ
 
examples/mof/ORBv2.pkl CHANGED
Binary files a/examples/mof/ORBv2.pkl and b/examples/mof/ORBv2.pkl differ
 
examples/mof/classification/M3GNet.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6f3e954dba20470846a14796b21dceeac03c02db8613527d441f387063697efe
3
+ size 218426
examples/mof/classification/MACE-MP(M).pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2d0967389772b92764ecc9a521d83fefff9f99ac365bbd8ba643bec32313ce57
3
+ size 197302
examples/mof/classification/MACE-MPA.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2d8ca57b95e2089ea86e28b3866bc3118e0893832a0be94ca9399002440ea4e3
3
+ size 299928
examples/mof/classification/MatterSim.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e7466643aedc9c6ea0b2a34fa9227fa99eeb28c67818de077b7b5edd8d49bf47
3
+ size 298511
examples/mof/classification/ORBv2.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:69c635f37e99782d0d0f2eb413f57285df0ed4666e390a2171f4d4b2b2febf36
3
+ size 248466
examples/mof/classification/SevenNet.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f8285152e645f30facb7c53298075fd6b7483149944c98bf52f46bb1c3e62b67
3
+ size 249418
examples/mof/classification/analysis.ipynb ADDED
@@ -0,0 +1,380 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "metadata": {},
7
+ "outputs": [],
8
+ "source": [
9
+ "# %matplotlib inline\n",
10
+ "\n",
11
+ "# import pandas as pd\n",
12
+ "# import seaborn as sns\n",
13
+ "# from matplotlib import pyplot as plt\n",
14
+ "# from ase import units\n",
15
+ "# from pathlib import Path\n",
16
+ "\n",
17
+ "# from mlip_arena.models import MLIPEnum\n",
18
+ "\n",
19
+ "\n",
20
+ "# color_mapping = {\n",
21
+ "# 'DAC': '#e41a1c', # e.g., red for DAC\n",
22
+ "# 'Flue Gas': '#377eb8', # e.g., blue\n",
23
+ "# 'General': '#4daf4a' # e.g., green\n",
24
+ "# }\n",
25
+ "\n",
26
+ "# for model in MLIPEnum:\n",
27
+ "\n",
28
+ "# fpath = Path(f\"{model.name}.pkl\")\n",
29
+ "\n",
30
+ "# if not fpath.exists():\n",
31
+ "# continue\n",
32
+ "\n",
33
+ "# df = pd.read_pickle(fpath)\n",
34
+ "# df.drop_duplicates(subset=['model', 'name', 'class'], keep='last')\n",
35
+ "\n",
36
+ "# df_exploded = df.explode(['henry_coefficient', 'averaged_interaction_energy', 'heat_of_adsorption'])\n",
37
+ "# df_group = df_exploded.groupby(['model', 'name', 'class'])[['henry_coefficient', 'averaged_interaction_energy', 'heat_of_adsorption']]\n",
38
+ "# df = df_group.mean()\n",
39
+ "\n",
40
+ "# print(model, len(df))\n",
41
+ "\n",
42
+ "# df['averaged_interaction_energy'] = df['averaged_interaction_energy'] * units._e * units._Nav * 1e-3 # Convert from eV to kJ/mol\n",
43
+ "\n",
44
+ "# fig, ax = plt.subplots(figsize=(3, 3))\n",
45
+ "# sns.scatterplot(\n",
46
+ "# data=df,\n",
47
+ "# x=\"averaged_interaction_energy\",\n",
48
+ "# y=\"heat_of_adsorption\",\n",
49
+ "# hue=\"class\",\n",
50
+ "# palette=color_mapping,\n",
51
+ "# ax=ax,\n",
52
+ "# )\n",
53
+ "\n",
54
+ "# ax.set(\n",
55
+ "# title=model.name,\n",
56
+ "# # xlim=(-100, 0),\n",
57
+ "# # ylim=(-100, 0),\n",
58
+ "# xlabel='Averaged Interaction Energy (kJ/mol)',\n",
59
+ "# ylabel='Heat of Adsorption (kJ/mol)',\n",
60
+ "# aspect='equal'\n",
61
+ "# )\n",
62
+ "\n",
63
+ "# # Add horizontal dashed decision boundaries\n",
64
+ "# ax.axhline(y=-50, linestyle='--', color='gray', label='Exp. CO₂ Qst = 50 kJ/mol')\n",
65
+ "# ax.axhline(y=-35, linestyle='--', color='gray', label='Exp. CO₂ Qst = 35 kJ/mol')\n",
66
+ "\n",
67
+ "# ax.legend(\n",
68
+ "# # title='Class',\n",
69
+ "# loc='upper left',\n",
70
+ "# bbox_to_anchor=(1, 1),\n",
71
+ "# frameon=False,\n",
72
+ "# )\n",
73
+ "# plt.show()\n"
74
+ ]
75
+ },
76
+ {
77
+ "cell_type": "code",
78
+ "execution_count": null,
79
+ "metadata": {},
80
+ "outputs": [],
81
+ "source": [
82
+ "from pathlib import Path\n",
83
+ "\n",
84
+ "import pandas as pd\n",
85
+ "import plotly.colors as pcolors\n",
86
+ "import seaborn as sns\n",
87
+ "from matplotlib import pyplot as plt\n",
88
+ "\n",
89
+ "from mlip_arena.models import MLIPEnum\n",
90
+ "\n",
91
+ "mlip_methods = [\n",
92
+ " model.name\n",
93
+ " for model in MLIPEnum\n",
94
+ "]\n",
95
+ "\n",
96
+ "all_attributes = dir(pcolors.qualitative)\n",
97
+ "color_palettes = {\n",
98
+ " attr: getattr(pcolors.qualitative, attr)\n",
99
+ " for attr in all_attributes\n",
100
+ " if isinstance(getattr(pcolors.qualitative, attr), list)\n",
101
+ "}\n",
102
+ "color_palettes.pop(\"__all__\", None)\n",
103
+ "\n",
104
+ "palette_names = list(color_palettes.keys())\n",
105
+ "palette_colors = list(color_palettes.values())\n",
106
+ "palette_name = \"Plotly\"\n",
107
+ "color_sequence = color_palettes[palette_name] # type: ignore\n",
108
+ "\n",
109
+ "method_color_mapping = {\n",
110
+ " method: color_sequence[i % len(color_sequence)]\n",
111
+ " for i, method in enumerate(mlip_methods)\n",
112
+ "}"
113
+ ]
114
+ },
115
+ {
116
+ "cell_type": "code",
117
+ "execution_count": null,
118
+ "metadata": {},
119
+ "outputs": [
120
+ {
121
+ "name": "stderr",
122
+ "output_type": "stream",
123
+ "text": [
124
+ "/tmp/ipykernel_447045/3752450599.py:127: UserWarning: Attempt to set non-positive xlim on a log-scaled axis will be ignored.\n",
125
+ " ax1.set_xlim(xmin, xmax)\n"
126
+ ]
127
+ },
128
+ {
129
+ "data": {
130
+ "image/png": "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r0er1YqPjw/g+kXo5+dHSUmJupw9e/YwePDgc5azcOFCHA4H77//Po888kiV137++Weuv/569bFGo6n2/4qicNlll3H48GHmzZvHkSNHCA4OruFTqR935FBryp/qcmXEiBH8+9//ZvHixWzfvp1rrrnmnOW0lPwByaGmzqHqXH311dXmUE3Pn62m3PK0vGqJpMC6iFR+8Tf2tH909uH5IUOGMHz4cEJCQrjnnns4c+aMukMICgpi1qxZ5ObmsmrVKnJycvjwww95+eWX1WV17NiRDz/8kIULF6IoCjqdjjfffJNOnTrx3nvvMXfuXDQaDd27d+fDDz9U51u5ciXTpk3D39+/Smx333039957L5MmTSIzM5MXX3yRW265hUOHDrFnzx4MBoN6mqJyxwa1//UYGRnJk08+iU6no02bNqxevZq9e/eybNky/Pz86N+/P//4xz+qnfedd97hvvvuY/Xq1UyePBldxYC4e/bs4b777qtV2990001s2LCBSZMmERAQwBdffMGJEydqNW9tNEcOteb8qS5XvLy86NatGyEhIVxyySU1Fh0tIX9AcqipcwhgxowZREZGEhcXx7333suSJUuqzaFRo0bVO7c8La9aIo1S0xW5wuOVl5eTnJxM//79adOmjbvDqSI8PJwff/yRt956q9GXvXLlSnbs2MHEiRO5/fbbqxyOP9vtt9/OvHnzmD17Nj/99BNJSUkUFhYSHBxMWloa999/f6PdGVZXu3btYuPGjbz77rt89dVXVa5LEZI/FyL5c2GSQ/VTmVtXXnllk+SVJ39vNTYpsFowT07Upty5tXQ///wzL7zwAmvWrGHIkCHuDscjSf7UTPKndiSH6q45csuTv7camxRYLVhrSlQhhBAtX2v63pJ+sIQQQgghGpkUWEIIIYQQjUwKrIuAnOUVQgjRErSm7yvppqEF8/b2RqPRkJ+fT5cuXar0TSKEEEJ4EkVRyM/PR6PRVOk77GIlF7m3cCaTiYyMjFb1q0AIIUTLpNFo6N27NwEBAe4OpclJgXURcDgc1Y7nJYQQQngSb29vtZPci50UWEIIIYQQjUwucr8ARVEwGo1yCk4IIYQQtSYXuV9ASUkJQUFBnMo4RbvAdheeQdTIZrOx9j9rAVj414fw9fG8TuZsNitffvw+AH9bcAttW8GFmI3Narfx1jffAPDs00/j27at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",
131
+ "text/plain": [
132
+ "<Figure size 600x400 with 2 Axes>"
133
+ ]
134
+ },
135
+ "metadata": {},
136
+ "output_type": "display_data"
137
+ }
138
+ ],
139
+ "source": [
140
+ "%matplotlib inline\n",
141
+ "\n",
142
+ "import numpy as np\n",
143
+ "\n",
144
+ "from mlip_arena.models import MLIPEnum\n",
145
+ "\n",
146
+ "# Color mapping by class\n",
147
+ "color_mapping = {\n",
148
+ " \"DAC\": \"#e41a1c\",\n",
149
+ " \"Flue Gas\": \"#377eb8\",\n",
150
+ " \"General\": \"#4daf4a\"\n",
151
+ "}\n",
152
+ "\n",
153
+ "# Decision boundary thresholds\n",
154
+ "thresholds = {\n",
155
+ " \"General\": (None, 35),\n",
156
+ " \"Flue Gas\": (35, 50),\n",
157
+ " \"DAC\": (50, 100)\n",
158
+ "}\n",
159
+ "\n",
160
+ "# Collect data from all models\n",
161
+ "all_data = []\n",
162
+ "margins = []\n",
163
+ "\n",
164
+ "for model in MLIPEnum:\n",
165
+ " fpath = Path(f\"{model.name}.pkl\")\n",
166
+ " if not fpath.exists():\n",
167
+ " continue\n",
168
+ "\n",
169
+ " df = pd.read_pickle(fpath)\n",
170
+ " df = df.drop_duplicates(subset=[\"model\", \"name\", \"class\"], keep=\"last\")\n",
171
+ " df_exploded = df.explode([\"henry_coefficient\", \"averaged_interaction_energy\", \"heat_of_adsorption\"])\n",
172
+ " df_group = df_exploded.groupby([\"model\", \"name\", \"class\"])[[\"henry_coefficient\", \"averaged_interaction_energy\", \"heat_of_adsorption\"]].mean().reset_index()\n",
173
+ "\n",
174
+ " df_group[\"model_name\"] = model.name\n",
175
+ " df_group[\"neg_heat\"] = -df_group[\"heat_of_adsorption\"] # negate for log scale\n",
176
+ " df_group = df_group[df_group[\"neg_heat\"] > 0] # remove invalid values\n",
177
+ "\n",
178
+ " df_group = df_group[df_group[\"name\"] != \"MIL-96-Al\"]\n",
179
+ "\n",
180
+ " all_data.append(df_group)\n",
181
+ "\n",
182
+ " # Compute misclassification margin\n",
183
+ " def point_misclassified(row):\n",
184
+ " val = row[\"neg_heat\"]\n",
185
+ " lower, upper = thresholds[row[\"class\"]]\n",
186
+ " return (lower is not None and val < lower) or (upper is not None and val >= upper)\n",
187
+ "\n",
188
+ " misclassified = df_group[df_group.apply(point_misclassified, axis=1)]\n",
189
+ "\n",
190
+ " def distance_to_boundary(row):\n",
191
+ " val = row[\"neg_heat\"]\n",
192
+ " lower, upper = thresholds[row[\"class\"]]\n",
193
+ " distances = []\n",
194
+ " if lower is not None:\n",
195
+ " distances.append(abs(val - lower))\n",
196
+ " if upper is not None:\n",
197
+ " distances.append(abs(val - upper))\n",
198
+ " return min(distances)\n",
199
+ "\n",
200
+ " if not misclassified.empty:\n",
201
+ " num_misclassified = len(misclassified) + (18 - len(df_group))\n",
202
+ " margin = misclassified.apply(distance_to_boundary, axis=1).mean()\n",
203
+ " else:\n",
204
+ " num_misclassified = 0\n",
205
+ " margin = 0.0\n",
206
+ "\n",
207
+ " margins.append((model.name, margin, num_misclassified))\n",
208
+ "\n",
209
+ "\n",
210
+ "# Combine all into one DataFrame\n",
211
+ "combined_df = pd.concat(all_data, ignore_index=True)\n",
212
+ "margins_df = pd.DataFrame(margins, columns=[\"model_name\", \"misclassification_margin\", \"num_misclassified\"])\n",
213
+ "\n",
214
+ "# --- Plotting ---\n",
215
+ "\n",
216
+ "with plt.style.context(\"default\"):\n",
217
+ "\n",
218
+ " LARGE_SIZE = 10\n",
219
+ " MEDIUM_SIZE = 8\n",
220
+ " SMALL_SIZE = 6\n",
221
+ "\n",
222
+ " plt.rcParams.update({\n",
223
+ " \"font.size\": SMALL_SIZE,\n",
224
+ " \"axes.titlesize\": MEDIUM_SIZE,\n",
225
+ " \"axes.labelsize\": MEDIUM_SIZE,\n",
226
+ " \"xtick.labelsize\": SMALL_SIZE,\n",
227
+ " \"ytick.labelsize\": SMALL_SIZE,\n",
228
+ " \"legend.fontsize\": SMALL_SIZE,\n",
229
+ " \"figure.titlesize\": LARGE_SIZE,\n",
230
+ " })\n",
231
+ "\n",
232
+ " fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(6, 4), sharex=False, gridspec_kw={\"height_ratios\": [3, 1.5]})\n",
233
+ "\n",
234
+ " # --- Main Stripplot ---\n",
235
+ " sns.stripplot(\n",
236
+ " data=combined_df,\n",
237
+ " x=\"neg_heat\",\n",
238
+ " y=\"model_name\",\n",
239
+ " hue=\"class\",\n",
240
+ " size=2,\n",
241
+ " palette=color_mapping,\n",
242
+ " dodge=True,\n",
243
+ " jitter=0.1,\n",
244
+ " alpha=1,\n",
245
+ " ax=ax1,\n",
246
+ " )\n",
247
+ "\n",
248
+ " xmin, xmax = ax1.get_xlim()\n",
249
+ "\n",
250
+ " ax1.axvspan(xmin, 35, color=color_mapping[\"General\"], alpha=0.1, label=\"General\")\n",
251
+ " ax1.axvspan(35, 50, color=color_mapping[\"Flue Gas\"], alpha=0.1, label=\"Flue Gas\")\n",
252
+ " ax1.axvspan(50, 100, color=color_mapping[\"DAC\"], alpha=0.1, label=\"DAC\")\n",
253
+ "\n",
254
+ " ax1.axvline(x=35, linestyle=\"--\", color=\"gray\", label=\"Exp. $\\\\mathregular{CO_2}$ $Q_\\\\text{st}$ = 35 kJ/mol\")\n",
255
+ " ax1.axvline(x=50, linestyle=\"--\", color=\"gray\", label=\"Exp. $\\\\mathregular{CO_2}$ $Q_\\\\text{st}$ = 50 kJ/mol\")\n",
256
+ " ax1.axvline(x=100, linestyle=\"--\", color=\"gray\", label=\"Exp. $\\\\mathregular{CO_2}$ $Q_\\\\text{st}$ = 100 kJ/mol\")\n",
257
+ "\n",
258
+ " ax1.set_xscale(\"log\")\n",
259
+ " ax1.set_xlabel(\"Heat of $\\\\mathregular{CO_2}$ Adsorption $Q_\\\\text{st}$ [kJ/mol]\")\n",
260
+ " ax1.set_ylabel(\"\")\n",
261
+ " ax1.set_xlim(xmin, xmax)\n",
262
+ "\n",
263
+ " yticks = ax1.get_yticks()\n",
264
+ " yticks = np.array(yticks)\n",
265
+ " yticks = yticks[np.isfinite(yticks)] # Remove any NaNs\n",
266
+ "\n",
267
+ " # Draw horizontal lines between models (skip the last one)\n",
268
+ " for y in yticks[:-1] + np.diff(yticks) / 2:\n",
269
+ " ax1.axhline(y=y, color=\"gray\", linestyle=\":\", linewidth=0.7, alpha=0.5, zorder=0)\n",
270
+ "\n",
271
+ " handles, labels = ax1.get_legend_handles_labels()\n",
272
+ " legend_dict = dict(zip(labels, handles, strict=False))\n",
273
+ "\n",
274
+ " desired_order = [\n",
275
+ " \"General\", \"Exp. $\\\\mathregular{CO_2}$ $Q_\\\\text{st}$ = 35 kJ/mol\", \"Flue Gas\",\n",
276
+ " \"Exp. $\\\\mathregular{CO_2}$ $Q_\\\\text{st}$ = 50 kJ/mol\", \"DAC\", \"Exp. $\\\\mathregular{CO_2}$ $Q_\\\\text{st}$ = 100 kJ/mol\"\n",
277
+ " ]\n",
278
+ "\n",
279
+ " ordered_handles = [legend_dict[label] for label in desired_order if label in legend_dict]\n",
280
+ "\n",
281
+ " ax1.legend(\n",
282
+ " ordered_handles,\n",
283
+ " desired_order,\n",
284
+ " loc=\"lower center\",\n",
285
+ " bbox_to_anchor=(0.5, 1),\n",
286
+ " ncol=3,\n",
287
+ " frameon=True\n",
288
+ " )\n",
289
+ "\n",
290
+ "\n",
291
+ " ax1.spines[\"top\"].set_visible(False)\n",
292
+ " ax1.spines[\"right\"].set_visible(False)\n",
293
+ "\n",
294
+ " # --- Misclassification Margin Barplot ---\n",
295
+ "\n",
296
+ " # Sort by error margin\n",
297
+ " margins_df_sorted = margins_df.sort_values(by=\"misclassification_margin\", ascending=True)\n",
298
+ "\n",
299
+ " # Extract color values in order\n",
300
+ " bar_colors = [method_color_mapping[m] for m in margins_df_sorted[\"model_name\"]]\n",
301
+ "\n",
302
+ " sns.scatterplot(\n",
303
+ " data=margins_df_sorted,\n",
304
+ " x=\"num_misclassified\",\n",
305
+ " y=\"misclassification_margin\",\n",
306
+ " hue=\"model_name\",\n",
307
+ " palette=bar_colors,\n",
308
+ " ax=ax2\n",
309
+ " )\n",
310
+ "\n",
311
+ " for _, row in margins_df_sorted.iterrows():\n",
312
+ " x = row[\"num_misclassified\"]\n",
313
+ " y = row[\"misclassification_margin\"]\n",
314
+ " model = row[\"model_name\"]\n",
315
+ " color = bar_colors[margins_df_sorted[\"model_name\"].tolist().index(model)]\n",
316
+ "\n",
317
+ " ax2.text(\n",
318
+ " x+0.1,\n",
319
+ " y,\n",
320
+ " f\"{y:.2f}\",\n",
321
+ " fontsize=SMALL_SIZE,\n",
322
+ " ha=\"left\",\n",
323
+ " va=\"bottom\",\n",
324
+ " color=color,\n",
325
+ " alpha=0.9\n",
326
+ " )\n",
327
+ "\n",
328
+ " ax2.set_ylabel(\"Misclass. margin [kJ/mol]\")\n",
329
+ " ax2.set_xlabel(\"Missing + misclass. count\")\n",
330
+ " ax2.spines[\"top\"].set_visible(False)\n",
331
+ " ax2.spines[\"right\"].set_visible(False)\n",
332
+ " # ax2.set_xticklabels(margins_df_sorted[\"model_name\"], rotation=45)\n",
333
+ " ax2.set_yscale(\"log\")\n",
334
+ "\n",
335
+ " handles, labels = ax2.get_legend_handles_labels()\n",
336
+ " legend_dict = dict(zip(labels, handles, strict=False))\n",
337
+ " ax2.legend(\n",
338
+ " legend_dict.values(),\n",
339
+ " legend_dict.keys(),\n",
340
+ " loc=\"upper left\",\n",
341
+ " bbox_to_anchor=(0, 1),\n",
342
+ " ncol=3,\n",
343
+ " frameon=True\n",
344
+ " )\n",
345
+ "\n",
346
+ " plt.tight_layout()\n",
347
+ " plt.savefig(\"mof-misclassification_margin.pdf\", bbox_inches=\"tight\")\n",
348
+ " plt.show()\n"
349
+ ]
350
+ },
351
+ {
352
+ "cell_type": "code",
353
+ "execution_count": null,
354
+ "metadata": {},
355
+ "outputs": [],
356
+ "source": []
357
+ }
358
+ ],
359
+ "metadata": {
360
+ "kernelspec": {
361
+ "display_name": "mlip-arena",
362
+ "language": "python",
363
+ "name": "mlip-arena"
364
+ },
365
+ "language_info": {
366
+ "codemirror_mode": {
367
+ "name": "ipython",
368
+ "version": 3
369
+ },
370
+ "file_extension": ".py",
371
+ "mimetype": "text/x-python",
372
+ "name": "python",
373
+ "nbconvert_exporter": "python",
374
+ "pygments_lexer": "ipython3",
375
+ "version": "3.11.8"
376
+ }
377
+ },
378
+ "nbformat": 4,
379
+ "nbformat_minor": 2
380
+ }
examples/mof/classification/input.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f66941e6898e0b0dbef120b2b17bd6828a1cf4db6aad94e1fd83aaa8b21acd84
3
+ size 286336
examples/mof/classification/mof-misclassification_margin.pdf ADDED
Binary file (31.9 kB). View file
 
examples/wbm_ev/ALIGNN_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:c1d3f3d2992c02464fdc5a4d58ca05de553dffab355b08e99a46d3b6d2495d11
3
- size 368547
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:875ed54dbc8766f4cfcdfd5e6d628fca9d1a8866b1b29cd1a32be8bb966303ef
3
+ size 368670
examples/wbm_ev/CHGNet_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:50bbb0ed4ba3e8af06c2a90e927182132be1f988643dd7b6844d39fe4dd1084c
3
- size 357683
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:62fc23bf5bc94ba30c32581a8c57131a9125993a3f0e380cb3800220b197b666
3
+ size 357806
examples/wbm_ev/M3GNet_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:411b2f619314dafb34349a65d985b7b881cb21687ecb9a853da29fc21d6fa714
3
- size 357786
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fd34bfe4650c2be26e7cfd75d747885ca265cbbc7fb769222d1f7e304fbd6de3
3
+ size 357909
examples/wbm_ev/MACE-MP(M)_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:877cd9e9407f9402fc01510d051ad19db815e9794c87ee8402f306e2afafd45e
3
- size 359765
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2f54e1c2b7ec686c2a353f8092633b13e66fac8410642027ef3481aedf350b0b
3
+ size 359889
examples/wbm_ev/MACE-MPA_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:ee5167ef38acf130548c5f5cbf78fedd14b7de7df47c72d771997f4e13302c0b
3
- size 356642
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:249e8f0283dda9c87ec787ea0945a92e8ba0d4bf7b00bf823a4850283f06cfde
3
+ size 356765
examples/wbm_ev/MatterSim_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:107a30bb5541a861e4141be0db3de210ca2229a22d975f732f107f0e6afdeb0f
3
- size 356292
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1cea2cf80561a7d5f6696fccd45754df9d417bd0310f06827b9c02fc7414f278
3
+ size 356416
examples/wbm_ev/ORBv2_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:01525c5b2e37b8d930c94ee2dc257b8d7c36b24111206ba2efc499a8bc172fcd
3
- size 357949
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8e92484ae9dc84cf35ce7c4780c9a28d27fb29779fd31c3d494ac95acf54c3e8
3
+ size 358072
examples/wbm_ev/SevenNet_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:83d9c45216940262575bc7386c62f8b79bb3ac5e63b8ab33ca4307976bb9796f
3
- size 358345
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4d19ee80d1f6c13765ad134d1356a029c175b7c885035fb68380b2dd559645ad
3
+ size 358468
examples/wbm_ev/eSEN.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:841febd80ec1024fa186ab05e5f9d7c96a0605d90c4840415ecf41ac89132aee
3
+ size 410695
examples/wbm_ev/eSEN_processed.parquet ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1602624f625a7c258f76604718fec7998fa6f88400c33ca2d5116681a5e8dd9d
3
+ size 356216
examples/wbm_ev/eqV2(OMat)_processed.parquet CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:50f318dce825e939a5c24aa8789acb2952865e0c682462f99cfed204ea9fba64
3
- size 356693
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cd43459abbcb6bf33b3dfecf131a6116d799f06aeb2b9e0a6c66e5d5db2ebdd6
3
+ size 356817
examples/wbm_ev/run.py CHANGED
@@ -123,41 +123,41 @@ def submit_tasks():
123
  futures.append(result)
124
  return [f.result(raise_on_failure=False) for f in futures]
125
 
126
-
127
- nodes_per_alloc = 1
128
- gpus_per_alloc = 1
129
- ntasks = 1
130
-
131
- cluster_kwargs = dict(
132
- cores=1,
133
- memory="64 GB",
134
- processes=1,
135
- shebang="#!/bin/bash",
136
- account="m3828",
137
- walltime="00:30:00",
138
- # job_mem="0",
139
- job_script_prologue=[
140
- "source ~/.bashrc",
141
- "module load python",
142
- "source activate /pscratch/sd/c/cyrusyc/.conda/mlip-arena",
143
- ],
144
- job_directives_skip=["-n", "--cpus-per-task", "-J"],
145
- job_extra_directives=[
146
- "-J wbm_ev",
147
- "-q debug",
148
- f"-N {nodes_per_alloc}",
149
- "-C gpu",
150
- f"-G {gpus_per_alloc}",
151
- "--exclusive",
152
- ],
153
- )
154
-
155
- cluster = SLURMCluster(**cluster_kwargs)
156
- print(cluster.job_script())
157
- cluster.adapt(minimum_jobs=2, maximum_jobs=2)
158
- client = Client(cluster)
159
-
160
- submit_tasks.with_options(
161
- task_runner=DaskTaskRunner(address=client.scheduler.address),
162
- log_prints=True,
163
- )()
 
123
  futures.append(result)
124
  return [f.result(raise_on_failure=False) for f in futures]
125
 
126
+ if __name__ == "__main__":
127
+ nodes_per_alloc = 1
128
+ gpus_per_alloc = 1
129
+ ntasks = 1
130
+
131
+ cluster_kwargs = dict(
132
+ cores=1,
133
+ memory="64 GB",
134
+ processes=1,
135
+ shebang="#!/bin/bash",
136
+ account="m3828",
137
+ walltime="00:30:00",
138
+ # job_mem="0",
139
+ job_script_prologue=[
140
+ "source ~/.bashrc",
141
+ "module load python",
142
+ "source activate /pscratch/sd/c/cyrusyc/.conda/mlip-arena",
143
+ ],
144
+ job_directives_skip=["-n", "--cpus-per-task", "-J"],
145
+ job_extra_directives=[
146
+ "-J wbm_ev",
147
+ "-q debug",
148
+ f"-N {nodes_per_alloc}",
149
+ "-C gpu",
150
+ f"-G {gpus_per_alloc}",
151
+ "--exclusive",
152
+ ],
153
+ )
154
+
155
+ cluster = SLURMCluster(**cluster_kwargs)
156
+ print(cluster.job_script())
157
+ cluster.adapt(minimum_jobs=2, maximum_jobs=2)
158
+ client = Client(cluster)
159
+
160
+ submit_tasks.with_options(
161
+ task_runner=DaskTaskRunner(address=client.scheduler.address),
162
+ log_prints=True,
163
+ )()
examples/wbm_ev/summary.csv CHANGED
@@ -1,10 +1,11 @@
1
  model,rank,rank-aggregation,energy-diff-flip-times,tortuosity,spearman-compression-energy,spearman-compression-derivative,spearman-tension-energy,missing
2
- MACE-MPA,1,11,1.0,1.000675741122765,-0.9983393939393939,0.9993090909090908,0.9987181818181818,0
3
- CHGNet,2,14,1.0,1.0006287770651048,-0.9982787878787878,0.9439636363636364,0.999090909090909,0
4
- MatterSim,3,19,1.009,1.000567338639546,-0.9980969696969696,0.9997090909090908,0.9937541835359507,0
5
- eqV2(OMat),4,22,1.035,1.0008346292192054,-0.9982060606060604,0.9972242424242423,0.9986454545454545,0
6
- M3GNet,5,24,1.002,1.0020010929112253,-0.9975878787878787,0.997442424242424,0.9964676571137886,0
7
- ORBv2,6,29,1.058,1.004064906459821,-0.9977696969696969,0.970751515151515,0.9976,0
8
- SevenNet,7,33,1.034,1.0100246177550205,-0.9951636363636364,0.9465575757575757,0.9947048195608054,0
9
- MACE-MP(M),8,35,1.121,1.0807128149289842,-0.9438060606060605,0.9011878787878788,0.9987454545454546,0
10
- ALIGNN,9,46,3.909,1.3756517739089669,-0.8892069391323368,0.7602706775644651,0.862085379002138,0
 
 
1
  model,rank,rank-aggregation,energy-diff-flip-times,tortuosity,spearman-compression-energy,spearman-compression-derivative,spearman-tension-energy,missing
2
+ eSEN,1,7,1.0,1.000402711291021,-0.9983393939393939,0.9999999999999999,0.9990454545454545,0
3
+ MACE-MPA,2,14,1.0,1.000675741122765,-0.9983393939393939,0.9993090909090908,0.9987181818181818,0
4
+ CHGNet,3,17,1.0,1.0006287770651048,-0.9982787878787878,0.9439636363636364,0.999090909090909,0
5
+ MatterSim,4,24,1.009,1.000567338639546,-0.9980969696969696,0.9997090909090908,0.9937541835359507,0
6
+ eqV2(OMat),5,27,1.035,1.0008346292192054,-0.9982060606060604,0.9972242424242423,0.9986454545454545,0
7
+ M3GNet,6,29,1.002,1.0020010929112253,-0.9975878787878787,0.997442424242424,0.9964676571137886,0
8
+ ORBv2,7,34,1.058,1.004064906459821,-0.9977696969696969,0.970751515151515,0.9976,0
9
+ SevenNet,8,38,1.034,1.0100246177550205,-0.9951636363636364,0.9465575757575757,0.9947048195608054,0
10
+ MACE-MP(M),9,40,1.121,1.0807128149289842,-0.9438060606060605,0.9011878787878788,0.9987454545454546,0
11
+ ALIGNN,10,51,3.909,1.3756517739089669,-0.8892069391323368,0.7602706775644651,0.862085379002138,0
examples/wbm_ev/summary.tex CHANGED
@@ -2,14 +2,15 @@
2
  \toprule
3
  model & rank & rank-aggregation & energy-diff-flip-times & tortuosity & spearman-compression-energy & spearman-compression-derivative & spearman-tension-energy & missing \\
4
  \midrule
5
- MACE-MPA & 1 & 11 & 1.000000 & 1.000676 & -0.998339 & 0.999309 & 0.998718 & 0 \\
6
- CHGNet & 2 & 14 & 1.000000 & 1.000629 & -0.998279 & 0.943964 & 0.999091 & 0 \\
7
- MatterSim & 3 & 19 & 1.009000 & 1.000567 & -0.998097 & 0.999709 & 0.993754 & 0 \\
8
- eqV2(OMat) & 4 & 22 & 1.035000 & 1.000835 & -0.998206 & 0.997224 & 0.998645 & 0 \\
9
- M3GNet & 5 & 24 & 1.002000 & 1.002001 & -0.997588 & 0.997442 & 0.996468 & 0 \\
10
- ORBv2 & 6 & 29 & 1.058000 & 1.004065 & -0.997770 & 0.970752 & 0.997600 & 0 \\
11
- SevenNet & 7 & 33 & 1.034000 & 1.010025 & -0.995164 & 0.946558 & 0.994705 & 0 \\
12
- MACE-MP(M) & 8 & 35 & 1.121000 & 1.080713 & -0.943806 & 0.901188 & 0.998745 & 0 \\
13
- ALIGNN & 9 & 46 & 3.909000 & 1.375652 & -0.889207 & 0.760271 & 0.862085 & 0 \\
 
14
  \bottomrule
15
  \end{tabular}
 
2
  \toprule
3
  model & rank & rank-aggregation & energy-diff-flip-times & tortuosity & spearman-compression-energy & spearman-compression-derivative & spearman-tension-energy & missing \\
4
  \midrule
5
+ eSEN & 1 & 7 & 1.000000 & 1.000403 & -0.998339 & 1.000000 & 0.999045 & 0 \\
6
+ MACE-MPA & 2 & 14 & 1.000000 & 1.000676 & -0.998339 & 0.999309 & 0.998718 & 0 \\
7
+ CHGNet & 3 & 17 & 1.000000 & 1.000629 & -0.998279 & 0.943964 & 0.999091 & 0 \\
8
+ MatterSim & 4 & 24 & 1.009000 & 1.000567 & -0.998097 & 0.999709 & 0.993754 & 0 \\
9
+ eqV2(OMat) & 5 & 27 & 1.035000 & 1.000835 & -0.998206 & 0.997224 & 0.998645 & 0 \\
10
+ M3GNet & 6 & 29 & 1.002000 & 1.002001 & -0.997588 & 0.997442 & 0.996468 & 0 \\
11
+ ORBv2 & 7 & 34 & 1.058000 & 1.004065 & -0.997770 & 0.970752 & 0.997600 & 0 \\
12
+ SevenNet & 8 & 38 & 1.034000 & 1.010025 & -0.995164 & 0.946558 & 0.994705 & 0 \\
13
+ MACE-MP(M) & 9 & 40 & 1.121000 & 1.080713 & -0.943806 & 0.901188 & 0.998745 & 0 \\
14
+ ALIGNN & 10 & 51 & 3.909000 & 1.375652 & -0.889207 & 0.760271 & 0.862085 & 0 \\
15
  \bottomrule
16
  \end{tabular}
mlip_arena/models/registry.yaml CHANGED
@@ -211,7 +211,7 @@ eSEN:
211
  module: externals
212
  class: eSEN
213
  family: fairchem
214
- package: fairchem-core==1.9.0
215
  checkpoint: esen_30m_oam.pt
216
  username: fairchem # HF handle
217
  last-update: 2025-04-21
@@ -222,9 +222,11 @@ eSEN:
222
  - Alexandria
223
  gpu-tasks:
224
  - homonuclear-diatomics
 
 
225
  prediction: EFS
226
  nvt: true
227
- npt: false # https://github.com/FAIR-Chem/fairchem/issues/888, https://github.com/atomind-ai/mlip-arena/issues/17
228
  date: 2025-04-14
229
  github: https://github.com/FAIR-Chem/fairchem
230
  doi: https://arxiv.org/abs/2502.12147
 
211
  module: externals
212
  class: eSEN
213
  family: fairchem
214
+ package: fairchem-core==1.10.0
215
  checkpoint: esen_30m_oam.pt
216
  username: fairchem # HF handle
217
  last-update: 2025-04-21
 
222
  - Alexandria
223
  gpu-tasks:
224
  - homonuclear-diatomics
225
+ - wbm_ev
226
+ - eos_bulk
227
  prediction: EFS
228
  nvt: true
229
+ npt: true
230
  date: 2025-04-14
231
  github: https://github.com/FAIR-Chem/fairchem
232
  doi: https://arxiv.org/abs/2502.12147
pyproject.toml CHANGED
@@ -8,7 +8,7 @@ version="0.1.0"
8
  authors=[
9
  {name="Yuan Chiang", email="cyrusyc@lbl.gov"},
10
  ]
11
- description="Fair and transparent benchmark of machine-learned interatomic potentials (MLIPs), beyond basic error metrics"
12
  readme=".github/README.md"
13
  requires-python=">=3.10"
14
  keywords=[
@@ -71,7 +71,7 @@ matgl = [
71
  ]
72
  fairchem = [
73
  "hydra-core",
74
- "fairchem-core@git+https://github.com/facebookresearch/fairchem.git#subdirectory=packages/fairchem-core",
75
  ]
76
  orb = [
77
  "orb-models==0.4.0",
@@ -174,4 +174,4 @@ ignore = [
174
  "PD901",
175
  ]
176
  fixable = ["ALL"]
177
- pydocstyle.convention = "google"
 
8
  authors=[
9
  {name="Yuan Chiang", email="cyrusyc@lbl.gov"},
10
  ]
11
+ description="Fair and transparent benchmark of machine learning interatomic potentials (MLIPs), beyond error-based regression metrics"
12
  readme=".github/README.md"
13
  requires-python=">=3.10"
14
  keywords=[
 
71
  ]
72
  fairchem = [
73
  "hydra-core",
74
+ "fairchem-core==1.10.0",
75
  ]
76
  orb = [
77
  "orb-models==0.4.0",
 
174
  "PD901",
175
  ]
176
  fixable = ["ALL"]
177
+ pydocstyle.convention = "google"