Spaces:
Running
Running
Yuan (Cyrus) Chiang
commited on
Add eSEN EOS (#59, #56)
Browse filesAdd eSEN EOS and EV scan results following #56
- .gitattributes +7 -0
- .github/workflows/sync-hf.yaml +1 -1
- .github/workflows/test.yaml +39 -11
- examples/eos_bulk/CHGNet_processed.parquet +2 -2
- examples/eos_bulk/M3GNet_processed.parquet +2 -2
- examples/eos_bulk/MACE-MP(M)_processed.parquet +2 -2
- examples/eos_bulk/MACE-MPA_processed.parquet +2 -2
- examples/eos_bulk/MatterSim_processed.parquet +2 -2
- examples/eos_bulk/ORBv2_processed.parquet +2 -2
- examples/eos_bulk/SevenNet_processed.parquet +2 -2
- examples/eos_bulk/eSEN.parquet +3 -0
- examples/eos_bulk/eSEN_processed.parquet +3 -0
- examples/eos_bulk/run.py +107 -72
- examples/eos_bulk/summary.csv +8 -7
- examples/eos_bulk/summary.tex +8 -7
- examples/mof/CHGNet.pkl +0 -0
- examples/mof/M3GNet.pkl +0 -0
- examples/mof/MACE-MP(M).pkl +0 -0
- examples/mof/MACE-MPA.pkl +0 -0
- examples/mof/MatterSim.pkl +0 -0
- examples/mof/ORBv2.pkl +0 -0
- examples/mof/classification/M3GNet.pkl +3 -0
- examples/mof/classification/MACE-MP(M).pkl +3 -0
- examples/mof/classification/MACE-MPA.pkl +3 -0
- examples/mof/classification/MatterSim.pkl +3 -0
- examples/mof/classification/ORBv2.pkl +3 -0
- examples/mof/classification/SevenNet.pkl +3 -0
- examples/mof/classification/analysis.ipynb +380 -0
- examples/mof/classification/input.pkl +3 -0
- examples/mof/classification/mof-misclassification_margin.pdf +0 -0
- examples/wbm_ev/ALIGNN_processed.parquet +2 -2
- examples/wbm_ev/CHGNet_processed.parquet +2 -2
- examples/wbm_ev/M3GNet_processed.parquet +2 -2
- examples/wbm_ev/MACE-MP(M)_processed.parquet +2 -2
- examples/wbm_ev/MACE-MPA_processed.parquet +2 -2
- examples/wbm_ev/MatterSim_processed.parquet +2 -2
- examples/wbm_ev/ORBv2_processed.parquet +2 -2
- examples/wbm_ev/SevenNet_processed.parquet +2 -2
- examples/wbm_ev/eSEN.parquet +3 -0
- examples/wbm_ev/eSEN_processed.parquet +3 -0
- examples/wbm_ev/eqV2(OMat)_processed.parquet +2 -2
- examples/wbm_ev/run.py +38 -38
- examples/wbm_ev/summary.csv +10 -9
- examples/wbm_ev/summary.tex +10 -9
- mlip_arena/models/registry.yaml +4 -2
- 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@
|
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
|
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
|
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 |
-
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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
|
9 |
-
from prefect.
|
10 |
-
from prefect.
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
):
|
36 |
-
|
37 |
|
38 |
-
|
39 |
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
|
44 |
-
|
45 |
-
|
46 |
|
47 |
-
|
48 |
|
49 |
-
|
50 |
-
|
51 |
|
52 |
|
53 |
-
@task
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
75 |
-
|
76 |
-
|
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
|
90 |
futures = []
|
91 |
for atoms in load_wbm_structures():
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
|
|
|
|
|
|
|
|
96 |
futures.append(result)
|
|
|
|
|
|
|
97 |
return [f.result(raise_on_failure=False) for f in futures]
|
98 |
|
99 |
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
"-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
|
|
|
|
126 |
|
127 |
-
cluster = SLURMCluster(**cluster_kwargs)
|
128 |
-
print(cluster.job_script())
|
129 |
-
cluster.adapt(minimum_jobs=
|
130 |
-
client = Client(cluster)
|
131 |
|
132 |
-
|
133 |
-
|
134 |
-
|
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,
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
|
|
|
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 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
|
|
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": "iVBORw0KGgoAAAANSUhEUgAAAlgAAAGRCAYAAAC5ac09AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAqClJREFUeJzs3Xd4VGX2wPHvzKRAEhJ6R4pGepGioIQEVhBBUMqKrIJY1t7Wjot1V3Eta1n8ia4gYkWRpqAoi6F3khACKaT3OpnJJJOp9/fHJFciCaTPhJzP8+SBmbnlzDvn3jlzy/tqFEVREEIIIYQQjUbr7gCEEEIIIS42UmAJIYQQQjQyKbCEEEIIIRqZFFhCCCGEEI1MCiwhhBBCiEYmBZYQQgghRCOTAksIIYQQopF5uTsA0XAOhwObzebuMIQQQojz8vb2RqfTuTuMZiEFVgtnMpnIyMhA+osVQgjh6TQaDb179yYgIMDdoTQ5jfTk3nI5HA4SEhLw8/OjS5cuaDQad4ckhBBCVEtRFPLz8ykrKyM4OPiiP5IlR7BaMJvNhqIodOnShbZt27o7HCGEEOK8unTpQkpKCjabTQos4fkqj1w5FEeDTxVqNBp0mos76UXNHE6lcXJIK0dTWyvF4QCns2EL0WrRXORfvq1VazrTIgXWRcKhOCgsK8DqbNjF7j5abzr5da6xyNq3bx/Lli1DUVxfxI888gjz5s1r0DovJDw8nB9//JG33nqrSdfT2jmcCrmGcmyOhn05euu0dAtqc06RlZKSwrhx4xg6dCgAL7zwAmlpaZhMJh566KF6rau8vJxnn32WY8eOodVq6d27Nx9++CGBgYENeg+ifhSHA0dWFoq1YfshjY83up49qy2yKvNo+PDh2O12xo0bxz/+8Q/8/Pz46KOPeOONN0hMTFSn379/P8899xyKoqDT6XjjjTcYO3Zsg+ITojakwLpIKIqC1WlDp9Gh1dSv9w2n4sTqdJ12pJofGYWFhTzwwAP8/PPP9OjRA5vNxtGjRxsY+VnrdzrRaqXnEHdRFAWbw4lOQ72PQDmcrmW4joKdu4zQ0FDWr1+vPl6zZk09o3X55z//Sbdu3dizZw8AJ0+exG63N2iZogGcThSrDY1OC7p6fr047K4CzemEGo5iVeaRoii88MILvPjii7z55pv88MMPhIaGcuzYMcaMGUNRURH333+/us8yGAxVii8hmpJ8m11ktBotXlqvev1dqDDbtm0bc+bMoUePHoDrdtsJEyZw9OhRJk+eTEhIiHqU6aWXXmLRokXMmDGD0NBQzGYzAK+99hqhoaFMmjSJ6OhoAEaPHs2jjz7KokWLiI6OJjQ0lAkTJtT7qIZoGJ1Wg5dOW6+/hpwaPPuoQuX/k5KSuO666wgLC+Nvf/vbOfOsX7+eJ554Qn08bNgwOnbsSG5urpqT8+fPx+FwkJiYyNVXX83kyZO599576x2nqAWdFxrv+v3VpTDTaDQ8//zzbNmyhfz8fNq2bct9993Hd999B8DWrVu56aab1H1WUFAQo0ePbpK3LMQfSYElai0rK0vdUe3cuZOwsDBmz57Ns88+y4YNG9izZw+7du0iNzcXgODgYLZt28b48eP59ddfOXnyJHFxcezatYtvvvmGZcuWAaDX63n44Yf58ssvueyyywgPD+fAgQOkp6eTkJDgtvcrGt+uXbsICwsjLCyMoqKiC07/7LPP8n//93+Eh4dTXl5+zhFTq9WKj48PAIsXL2bUqFHs3LmTDh068Ouvv7Jnzx569erFzp07CQ8P57bbbuO3337jww8/bJL3J5qfj48PVquVjRs3Mm/ePK688kqOHz8OuPZZPXv2dHOEorWSU4Si1nr27KkWPFOmTGHKlCmMHTuWtLQ05syZA7iKpfT0dACuuOIKAPr06YNer+fUqVPs37+fsLAwAPUOkg4dOnDZZZcBkJyczBNPPEFZWRlJSUlkZWU151sUTeyPpwhrUnmhfWxsLHfddRcAJSUlXHfddVWOdPn4+GCxWPD19WXt2rW89NJLlJWVUVhYyP33349erycrK4vRo0dz880388orr3Drrbdy3XXXsXjx4qZ5k6JZVX7+mzZtwmKxsGbNGpKSkjh+/HiVfZYQzU0KrIuMU3Fid9bvGhSncv6Lm2fMmEFYWBj33XcfPXv2VK91GTlyJOvXrycoKAiHw4FWq+XHH3+screIoigMGjSI0NBQPvnkEwC19/mzr7v68MMPeeKJJ7j22muZPXu2dKDqBg6nAtTvQnfXvPVTXl6Ow+EgMzMTvV4PwMCBA3nrrbfo27cviqLgcDiqzDN//nzefPNN9WhoZU5+9dVX3HDDDdx99908/PDDKIqCl5cXb775JgBDhw7ltttuk2v+morDTr0zwVG3/dfy5cuZOHEiBQUFbNu2DYDDhw/z3Xff8dRTTzF58mTuv/9+evTogdFo5MyZM3KaUDQLKbAuEhqNBh+tN1anDYfiuPAMNfDRetd4G22nTp1YuXIlf/nLX9BoNGi1Wh577DEGDx7M3LlzcTqd+Pr6snHjxmrnHzFiBMHBwYSGhqLVapk6dSrPPfdclWlmzZrFo48+yqBBg3A29FZvUScajQZvnRabw4nDUf9CyVunrdet2LfeeisTJkxg0qRJtG/fHoB//etf3HfffZSXl6PT6Vi9ejWXXHKJOs+yZct45plnmDhxotrh7kMPPUTv3r1ZtGgRP/zwg9pH3JYtW1ixYgUA1113nRRXTUGrRePj7bpI3WGt92I0Pt5wns9n165dTJ48GYfDwVVXXcXIkSOr3NwwZswY7r//fpYvX86HH37IwoUL1bsIK4tsIZqa9OTegpWXl5OcnEz//v1p06aN9IMlGkz6wRINJf1gifP54/fWxUyOYF1EdBpdtd0rCFFbrsJIkkjUn0anq7F7BSFaEzlGLoQQQgjRyKTAEkIIIYRoZFJgCSGEEEI0MimwhBBCCCEamRRYQgghhBCNTAosIYQQQohGJgWWqJOUlBS6dOmijie3dOnSBi+zcvic0NBQpkyZoo43Fx4eTkhICKGhodxyyy1q794Xotfruf3225k0aRLjx49n06ZNDY6xUm5uLldffbUaa3Z29jltkp+fX2We8PBwnnzyySrPpaSkMH/+fPVxaWkpt9xyS71iqm75nqq1509NufLMM88QEhLCokWL1BEOKkn+VNXac8hgMHDllVcSEBDAyZMn1edryqGG5FZryqumIP1giTqr7XhytVFUVMT999/Pzz//TI8ePTAYDCQmJlJUVMQjjzzC//73P7p06cLXX3/Nww8/zBdffHHBZS5YsIDHH3+c6dOnU1JSwlVXXcWUKVMIDAxscLydO3dm7969aLVa1qxZw6pVq7jtttsa3CY7d+5kypQpDY6vJWjN+QPnvv+oqCgyMzPZs2cPr776KuvXr2fhwoV1WmZryh9o3Tnk5+fH1q1beeqpp9TnasqhhuZWa8urxiZHsC4iVqu1xr+zh5E437T18csvv3DnnXcCcPvtt7Nz507Cw8OZNm0as2bNYty4cURHR1c779atW7npppvo0aMHAEFBQYwePZqtW7cyZ84cunTpAsDChQs5ePDgBYfP2bFjB7169WL69OkAtGvXjuHDhxMfH1+v9/ZHOp1OHWKlpKSEoUOHArBv3z5CQkJ47rnnauwJvby8nJtvvplff/31nNd+/vlnpk+fTnh4ONdddx1z5sxh5MiRrFu3juuuu44rr7ySwsJCHA6HWtDNnDmz1r+oa8sdOdSa8gfOzZX9+/czbdo0AKZPn86+ffuqna8l5A9IDjV1Dnl7e6sxVaophxqaW56UVy2RHMG6iCxfvrzG14KDg/nLX/6iPn7rrbfOOVwM8OKLL15wPbt27SIsLAyAOXPm8Oijj7Jp0yYefPBBgoKCmDJlCuHh4ZSVlbF9+3ZiY2N55pln2LJlyznLysrKomfPnrV6vkuXLuTn59OtW7caY9uyZQuzZ8+u8lxhYeEFfznm5+fz5z//+Zznv/nmG7p3717lucjISO69916Ki4v55Zdf6N69O2fOnMHPz4+//vWvbNiwgXnz5lWZp6ysjIULF/LYY48RGhpKSkpKldfT0tK45JJLSEpKwul0snHjRj7++GO++eYbtm/fznvvvcfmzZsJDAykd+/efPHFF3z++ef85z//YdKkSed9b3XRHDnUmvOnR48e5+SKXq+v8uVeVFR0znJaSv6A5FBz7IP+qKYcamhueVJetURSYIk6q+7w/MMPP8zQoUNJTU1Vn7viiivQaDQMHjyY7OzsapfVs2dPEhISznm+R48eJCYmVnkuLy+Pzp0788svvxAREUFSUhIrVqzA29tbncZkMtGhQwf1scFgICsri8suu0x97qWXXuKxxx5TBxQG144zPDy8Vu9/1KhRHDp0iG+//Zbly5ezcuVKfH19AZg7dy4HDx48p8DavHkzs2fPJjQ09JzlxcXFcfnll6uPR4wYAbjapvL/vXr1IjU1lby8PMaNGwfAuHHj+OWXX1rcjqw154+vr+85udK9e3eMRqO6vo4dO54zn+RPVa05h6rTvn37anOopufPVlNutca8amxSYF1Eznexp/YPI9M35sWHiqLw1FNPsXLlSp555hm++uorwHWkR1EU4uPj1V9RfzRz5kwmT57M/fffT48ePTAajZw5c4aZM2cSFhbGQw89pF7/MH78eHQ6HdOmTWPatGk8/vjjWK3WKju3sWPHsn37dsLCwrDb7Tz44IO88MILrFy5ErvdzuDBg0lISOCrr75i0aJFtGvXDqj9r0er1YqPjw/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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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:
|
3 |
-
size
|
|
|
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 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
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 |
-
|
162 |
-
|
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 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
|
|
|
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 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
|
|
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.
|
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:
|
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
|
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
|
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"
|