Yuan (Cyrus) Chiang commited on
Commit
f9d3b3b
·
unverified ·
1 Parent(s): 92e3c26

Add homonuclear diatomic rank (#8)

Browse files

* add homonuclear diatomic rank

* formatting

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 = [pd.read_json(DATA_DIR / MODELS[model].get("family") / "homonuclear-diatomics.json") for model in MODELS]
 
 
 
14
  df = pd.concat(dfs, ignore_index=True)
15
 
16
 
17
- table = pd.DataFrame(columns=[
18
- "Model",
19
- "Element Coverage",
20
- # "No. of reversed forces",
21
- # "Energy-consistent forces",
22
- "Prediction",
23
- "NVT",
24
- "NPT",
25
- "Code",
26
- "Paper",
27
- "First Release",
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("MLIP Arena is currently in **pre-alpha**. The results are not stable. Please interpret them with care.", icon="⚠️")
57
- st.info("Contributions are welcome. For more information, visit https://github.com/atomind-ai/mlip-arena.", icon="🤗")
 
 
 
 
 
 
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
- """, unsafe_allow_html=True)
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
- if TASKS[task]['rank-page'] is None:
92
- st.write("Rank for this task is not available yet")
93
- continue
 
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, 'get_rank_page'):
101
- task_module.get_rank_page()
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
- def get_rank_page():
4
- # st.markdown("""HIHI""")
5
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- # def plot():
8
- # pass
9
 
10
- # if __name__ == '__main__':
11
- # pass
 
 
 
 
 
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