Spaces:
Running
Running
Yuan (Cyrus) Chiang
commited on
Add homonuclear diatomic rank (#8)
Browse files* add homonuclear diatomic rank
* formatting
- serve/leaderboard.py +42 -32
- serve/ranks/homonuclear-diatomics.py +130 -7
serve/leaderboard.py
CHANGED
@@ -1,3 +1,4 @@
|
|
|
|
1 |
from pathlib import Path
|
2 |
|
3 |
import pandas as pd
|
@@ -6,26 +7,29 @@ import streamlit as st
|
|
6 |
from mlip_arena.models import REGISTRY as MODELS
|
7 |
from mlip_arena.tasks import REGISTRY as TASKS
|
8 |
|
9 |
-
import importlib
|
10 |
-
|
11 |
DATA_DIR = Path("mlip_arena/tasks/diatomics")
|
12 |
|
13 |
-
dfs = [
|
|
|
|
|
|
|
14 |
df = pd.concat(dfs, ignore_index=True)
|
15 |
|
16 |
|
17 |
-
table = pd.DataFrame(
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
|
|
|
|
29 |
|
30 |
for model in MODELS:
|
31 |
rows = df[df["method"] == model]
|
@@ -48,22 +52,27 @@ table.set_index("Model", inplace=True)
|
|
48 |
|
49 |
|
50 |
s = table.style.background_gradient(
|
51 |
-
cmap="PuRd",
|
52 |
-
subset=["Element Coverage"],
|
53 |
-
vmin=0, vmax=120
|
54 |
)
|
55 |
|
56 |
-
st.warning(
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
|
59 |
st.markdown(
|
60 |
-
"""
|
61 |
<h1 style='text-align: center;'>⚔️ MLIP Arena Leaderboard ⚔️</h1>
|
62 |
|
63 |
MLIP Arena is a platform for benchmarking foundation machine learning interatomic potentials (MLIPs), mainly for disclosing the learned physics and chemistry of the models and their performance on molecular dynamics (MD) simulations.
|
64 |
The benchmarks are designed to evaluate the readiness and reliability of open-source, open-weight models to reproduce the qualitatively or quantitatively correct physics.
|
65 |
-
""",
|
66 |
-
|
|
|
67 |
|
68 |
|
69 |
st.dataframe(
|
@@ -85,19 +94,20 @@ st.dataframe(
|
|
85 |
|
86 |
|
87 |
for task in TASKS:
|
|
|
|
|
88 |
|
89 |
st.header(task, divider=True)
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
|
|
94 |
|
95 |
task_module = importlib.import_module(f"ranks.{TASKS[task]['rank-page']}")
|
96 |
|
97 |
-
# task_module = importlib.import_module(f".ranks", TASKS[task]["task-page"])
|
98 |
-
|
99 |
# Call the function from the imported module
|
100 |
-
if hasattr(task_module,
|
101 |
-
task_module.
|
102 |
else:
|
103 |
-
st.write("Results for the task are not available yet.")
|
|
|
1 |
+
import importlib
|
2 |
from pathlib import Path
|
3 |
|
4 |
import pandas as pd
|
|
|
7 |
from mlip_arena.models import REGISTRY as MODELS
|
8 |
from mlip_arena.tasks import REGISTRY as TASKS
|
9 |
|
|
|
|
|
10 |
DATA_DIR = Path("mlip_arena/tasks/diatomics")
|
11 |
|
12 |
+
dfs = [
|
13 |
+
pd.read_json(DATA_DIR / MODELS[model].get("family") / "homonuclear-diatomics.json")
|
14 |
+
for model in MODELS
|
15 |
+
]
|
16 |
df = pd.concat(dfs, ignore_index=True)
|
17 |
|
18 |
|
19 |
+
table = pd.DataFrame(
|
20 |
+
columns=[
|
21 |
+
"Model",
|
22 |
+
"Element Coverage",
|
23 |
+
# "No. of reversed forces",
|
24 |
+
# "Energy-consistent forces",
|
25 |
+
"Prediction",
|
26 |
+
"NVT",
|
27 |
+
"NPT",
|
28 |
+
"Code",
|
29 |
+
"Paper",
|
30 |
+
"First Release",
|
31 |
+
]
|
32 |
+
)
|
33 |
|
34 |
for model in MODELS:
|
35 |
rows = df[df["method"] == model]
|
|
|
52 |
|
53 |
|
54 |
s = table.style.background_gradient(
|
55 |
+
cmap="PuRd", subset=["Element Coverage"], vmin=0, vmax=120
|
|
|
|
|
56 |
)
|
57 |
|
58 |
+
st.warning(
|
59 |
+
"MLIP Arena is currently in **pre-alpha**. The results are not stable. Please interpret them with care.",
|
60 |
+
icon="⚠️",
|
61 |
+
)
|
62 |
+
st.info(
|
63 |
+
"Contributions are welcome. For more information, visit https://github.com/atomind-ai/mlip-arena.",
|
64 |
+
icon="🤗",
|
65 |
+
)
|
66 |
|
67 |
st.markdown(
|
68 |
+
"""
|
69 |
<h1 style='text-align: center;'>⚔️ MLIP Arena Leaderboard ⚔️</h1>
|
70 |
|
71 |
MLIP Arena is a platform for benchmarking foundation machine learning interatomic potentials (MLIPs), mainly for disclosing the learned physics and chemistry of the models and their performance on molecular dynamics (MD) simulations.
|
72 |
The benchmarks are designed to evaluate the readiness and reliability of open-source, open-weight models to reproduce the qualitatively or quantitatively correct physics.
|
73 |
+
""",
|
74 |
+
unsafe_allow_html=True,
|
75 |
+
)
|
76 |
|
77 |
|
78 |
st.dataframe(
|
|
|
94 |
|
95 |
|
96 |
for task in TASKS:
|
97 |
+
if TASKS[task]["rank-page"] is None:
|
98 |
+
continue
|
99 |
|
100 |
st.header(task, divider=True)
|
101 |
+
st.page_link(
|
102 |
+
f"tasks/{TASKS[task]['task-page']}.py",
|
103 |
+
label="Link to task page",
|
104 |
+
icon=":material/link:",
|
105 |
+
)
|
106 |
|
107 |
task_module = importlib.import_module(f"ranks.{TASKS[task]['rank-page']}")
|
108 |
|
|
|
|
|
109 |
# Call the function from the imported module
|
110 |
+
if hasattr(task_module, "render"):
|
111 |
+
task_module.render()
|
112 |
else:
|
113 |
+
st.write("Results for the task are not available yet.")
|
serve/ranks/homonuclear-diatomics.py
CHANGED
@@ -1,11 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
-
|
4 |
-
|
5 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
-
# def plot():
|
8 |
-
# pass
|
9 |
|
10 |
-
|
11 |
-
|
|
|
|
|
|
|
|
|
|
1 |
+
from pathlib import Path
|
2 |
+
|
3 |
+
import numpy as np
|
4 |
+
import pandas as pd
|
5 |
+
import plotly.colors as pcolors
|
6 |
+
import plotly.graph_objects as go
|
7 |
import streamlit as st
|
8 |
+
from ase.data import chemical_symbols
|
9 |
+
from plotly.subplots import make_subplots
|
10 |
+
from scipy.interpolate import CubicSpline
|
11 |
+
|
12 |
+
from mlip_arena.models import REGISTRY as MODELS
|
13 |
+
|
14 |
+
valid_models = [
|
15 |
+
model
|
16 |
+
for model, metadata in MODELS.items()
|
17 |
+
if Path(__file__).stem in metadata.get("gpu-tasks", [])
|
18 |
+
]
|
19 |
+
|
20 |
+
DATA_DIR = Path("mlip_arena/tasks/diatomics")
|
21 |
+
|
22 |
+
dfs = [
|
23 |
+
pd.read_json(DATA_DIR / MODELS[model].get("family") / "homonuclear-diatomics.json")
|
24 |
+
for model in valid_models
|
25 |
+
]
|
26 |
+
df = pd.concat(dfs, ignore_index=True)
|
27 |
+
|
28 |
+
table = pd.DataFrame()
|
29 |
+
|
30 |
+
for model in valid_models:
|
31 |
+
rows = df[df["method"] == model]
|
32 |
+
metadata = MODELS.get(model, {})
|
33 |
+
|
34 |
+
new_row = {
|
35 |
+
"Model": model,
|
36 |
+
"Conservation deviation [eV/Å]": rows["conservation-deviation"].mean(),
|
37 |
+
"Spearman's coeff. (Energy - repulsion)": rows[
|
38 |
+
"spearman-repulsion-energy"
|
39 |
+
].mean(),
|
40 |
+
"Spearman's coeff. (Force - descending)": rows[
|
41 |
+
"spearman-descending-force"
|
42 |
+
].mean(),
|
43 |
+
"Tortuosity": rows["tortuosity"].mean(),
|
44 |
+
"Energy jump [eV]": rows["energy-jump"].mean(),
|
45 |
+
"Force flips": rows["force-flip-times"].mean(),
|
46 |
+
"Spearman's coeff. (Energy - attraction)": rows[
|
47 |
+
"spearman-attraction-energy"
|
48 |
+
].mean(),
|
49 |
+
"Spearman's coeff. (Force - ascending)": rows[
|
50 |
+
"spearman-ascending-force"
|
51 |
+
].mean(),
|
52 |
+
}
|
53 |
+
|
54 |
+
table = pd.concat([table, pd.DataFrame([new_row])], ignore_index=True)
|
55 |
+
|
56 |
+
table.set_index("Model", inplace=True)
|
57 |
+
|
58 |
+
table.sort_values("Conservation deviation [eV/Å]", ascending=True, inplace=True)
|
59 |
+
table["Rank"] = np.argsort(table["Conservation deviation [eV/Å]"].to_numpy())
|
60 |
+
|
61 |
+
table.sort_values(
|
62 |
+
"Spearman's coeff. (Energy - repulsion)", ascending=True, inplace=True
|
63 |
+
)
|
64 |
+
table["Rank"] += np.argsort(table["Spearman's coeff. (Energy - repulsion)"].to_numpy())
|
65 |
+
|
66 |
+
table.sort_values(
|
67 |
+
"Spearman's coeff. (Force - descending)", ascending=True, inplace=True
|
68 |
+
)
|
69 |
+
table["Rank"] += np.argsort(table["Spearman's coeff. (Force - descending)"].to_numpy())
|
70 |
+
|
71 |
+
table.sort_values("Tortuosity", ascending=True, inplace=True)
|
72 |
+
table["Rank"] += np.argsort(table["Tortuosity"].to_numpy())
|
73 |
+
|
74 |
+
table.sort_values("Energy jump [eV]", ascending=True, inplace=True)
|
75 |
+
table["Rank"] += np.argsort(table["Energy jump [eV]"].to_numpy())
|
76 |
+
|
77 |
+
table.sort_values("Force flips", ascending=True, inplace=True)
|
78 |
+
table["Rank"] += np.argsort(table["Force flips"].to_numpy())
|
79 |
+
|
80 |
+
table.sort_values("Rank", ascending=True, inplace=True)
|
81 |
+
|
82 |
+
table["Rank aggr."] = table["Rank"]
|
83 |
+
|
84 |
+
table["Rank"] = np.argsort(table["Rank"].to_numpy()) + 1
|
85 |
+
|
86 |
+
# table.drop(columns=["rank"], inplace=True)
|
87 |
+
# table = table.rename(columns={"Rank": "Rank Aggr."})
|
88 |
+
|
89 |
+
table = table.reindex(
|
90 |
+
columns=[
|
91 |
+
"Rank",
|
92 |
+
"Rank aggr.",
|
93 |
+
"Conservation deviation [eV/Å]",
|
94 |
+
"Spearman's coeff. (Energy - repulsion)",
|
95 |
+
"Spearman's coeff. (Force - descending)",
|
96 |
+
"Tortuosity",
|
97 |
+
"Energy jump [eV]",
|
98 |
+
"Force flips",
|
99 |
+
"Spearman's coeff. (Energy - attraction)",
|
100 |
+
"Spearman's coeff. (Force - ascending)",
|
101 |
+
]
|
102 |
+
)
|
103 |
|
104 |
+
s = (
|
105 |
+
table.style.background_gradient(
|
106 |
+
cmap="viridis_r",
|
107 |
+
subset=["Conservation deviation [eV/Å]"],
|
108 |
+
gmap=np.log(table["Conservation deviation [eV/Å]"].to_numpy()),
|
109 |
+
)
|
110 |
+
.background_gradient(
|
111 |
+
cmap="Reds",
|
112 |
+
subset=[
|
113 |
+
"Spearman's coeff. (Energy - repulsion)",
|
114 |
+
"Spearman's coeff. (Force - descending)",
|
115 |
+
],
|
116 |
+
# vmin=-1, vmax=-0.5
|
117 |
+
)
|
118 |
+
.background_gradient(
|
119 |
+
cmap="RdPu",
|
120 |
+
subset=["Tortuosity", "Energy jump [eV]", "Force flips"],
|
121 |
+
)
|
122 |
+
.background_gradient(
|
123 |
+
cmap="Blues",
|
124 |
+
subset=["Rank", "Rank aggr."],
|
125 |
+
)
|
126 |
+
)
|
127 |
|
|
|
|
|
128 |
|
129 |
+
def render():
|
130 |
+
st.dataframe(
|
131 |
+
s,
|
132 |
+
use_container_width=True,
|
133 |
+
)
|
134 |
+
# return table
|