-
Notifications
You must be signed in to change notification settings - Fork 42
Add CMRAds200 adsorption energies benchmarks #461
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
benshi97
wants to merge
17
commits into
ddmms:main
Choose a base branch
from
benshi97:TM_surf
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 10 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
ce0e4d0
CMRAds calculation scripts
c059fb6
Rename to CMRAds
94d8311
Delete calc_adsorption_energies
1081fc5
uv lock
59e0739
import typing
benshi97 a3815ec
Add analysis
benshi97 7a24a3d
rename category to metal
benshi97 bb985de
Merge remote-tracking branch 'origin/main' into TM_surf
benshi97 761c77c
Fix lint
benshi97 30844ac
clean up
benshi97 6228bac
Remove generated files from PR
benshi97 a7edc3a
Remove generated files from PR
benshi97 89e0cc6
reset models.yml
benshi97 d22eee7
Update ml_peg/analysis/surfaces/CMRAds200/analyse_CMRAds200.py
benshi97 2ea5c84
Update ml_peg/analysis/surfaces/CMRAds200/analyse_CMRAds200.py
benshi97 e2750d8
Update ml_peg/app/surfaces/CMRAds200/app_CMRAds200.py
benshi97 c552b22
Add spin and charge
benshi97 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
169 changes: 169 additions & 0 deletions
169
ml_peg/analysis/surfaces/CMRAds200/analyse_CMRAds200.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,169 @@ | ||
| """Analyse CMRAds200 benchmark.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from pathlib import Path | ||
|
|
||
| from ase.io import read, write | ||
| import pytest | ||
|
|
||
| from ml_peg.analysis.utils.decorators import build_table, plot_parity | ||
| from ml_peg.analysis.utils.utils import ( | ||
| build_dispersion_name_map, | ||
| load_metrics_config, | ||
| mae, | ||
| ) | ||
| from ml_peg.app import APP_ROOT | ||
| from ml_peg.calcs import CALCS_ROOT | ||
| from ml_peg.models.get_models import get_model_names | ||
| from ml_peg.models.models import current_models | ||
|
|
||
| MODELS = get_model_names(current_models) | ||
| DISPERSION_NAME_MAP = build_dispersion_name_map(MODELS) | ||
| CALC_PATH = CALCS_ROOT / "surfaces" / "CMRAds200" / "outputs" | ||
| OUT_PATH = APP_ROOT / "data" / "surfaces" / "CMRAds200" | ||
|
|
||
| METRICS_CONFIG_PATH = Path(__file__).with_name("metrics.yml") | ||
| DEFAULT_THRESHOLDS, DEFAULT_TOOLTIPS, _ = load_metrics_config(METRICS_CONFIG_PATH) | ||
|
|
||
|
|
||
| def labels() -> list: | ||
| """ | ||
| Get list of labels. | ||
|
|
||
| Returns | ||
| ------- | ||
| list | ||
| List of all energy labels. | ||
| """ | ||
| structs = read(CALC_PATH / "mol_surface_structs.extxyz", index=":") | ||
| return [struct.info["sys_formula"] for struct in structs] | ||
|
|
||
|
|
||
| def system_names() -> list: | ||
| """ | ||
| Get list of system names. | ||
|
|
||
| Returns | ||
| ------- | ||
| list | ||
| List of all system names. | ||
| """ | ||
| for model_name in MODELS: | ||
| model_dir = CALC_PATH / model_name | ||
| if model_dir.exists(): | ||
| structs = read(model_dir / "mol_surface_structs.extxyz", index=":") | ||
| system_names = [struct.info["sys_formula"] for struct in structs] | ||
| break | ||
| return system_names | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| @plot_parity( | ||
| filename=OUT_PATH / "figure_adsorption_energies.json", | ||
| title="Adsorption energies", | ||
| x_label="Predicted adsorption energy / eV", | ||
| y_label="Reference adsorption energy / eV", | ||
| hoverdata={ | ||
| "System": system_names(), | ||
| }, | ||
| ) | ||
| def adsorption_energies() -> dict[str, list]: | ||
| """ | ||
| Get adsorption energies for all systems. | ||
|
|
||
| Returns | ||
| ------- | ||
| dict[str, list] | ||
| Dictionary of all reference and predicted adsorption energies. | ||
| """ | ||
| results = {"ref": []} | {mlip: [] for mlip in MODELS} | ||
| ref_stored = False | ||
|
|
||
| for model_name in MODELS: | ||
| model_dir = CALC_PATH / model_name | ||
| if not model_dir.exists(): | ||
| results[model_name] = [] | ||
| continue | ||
| mol_surface_list = read(model_dir / "mol_surface_structs.extxyz", index=":") | ||
| for _mol_surface_idx, mol_surface in enumerate( | ||
| mol_surface_list | ||
| ): # sorted(model_dir.glob("*.xyz")): | ||
| system_name = mol_surface.info["sys_formula"] | ||
|
|
||
| # Get pre-calculated adsorption energies | ||
| pred_ads_energy = mol_surface.info["pred_adsorption_energy"] | ||
| results[model_name].append(pred_ads_energy) | ||
|
|
||
| if not ref_stored: | ||
| ref_ads_energy = mol_surface.info["PBE_adsorption_energy"] | ||
| results["ref"].append(ref_ads_energy) | ||
|
|
||
| # Write molecule-surface structure to app data | ||
| structs_dir = OUT_PATH / model_name | ||
| structs_dir.mkdir(parents=True, exist_ok=True) | ||
| write(structs_dir / f"{system_name}.xyz", mol_surface) | ||
|
benshi97 marked this conversation as resolved.
Outdated
|
||
|
|
||
| ref_stored = True | ||
| return results | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def cmrads_mae(adsorption_energies) -> dict[str, float]: | ||
| """ | ||
| Get mean absolute error for adsorption energies. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| adsorption_energies | ||
| Dictionary of reference and predicted adsorption energies. | ||
|
|
||
| Returns | ||
| ------- | ||
| dict[str, float] | ||
| Dictionary of predicted adsorption energy errors for all models. | ||
| """ | ||
| results = {} | ||
| for model_name in MODELS: | ||
| results[model_name] = mae( | ||
| adsorption_energies["ref"], adsorption_energies[model_name] | ||
| ) | ||
| return results | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| @build_table( | ||
| filename=OUT_PATH / "cmrads_metrics_table.json", | ||
| metric_tooltips=DEFAULT_TOOLTIPS, | ||
| thresholds=DEFAULT_THRESHOLDS, | ||
| mlip_name_map=DISPERSION_NAME_MAP, | ||
| ) | ||
| def metrics(cmrads_mae: dict[str, float]) -> dict[str, dict]: | ||
| """ | ||
| Get all CMRAds200 metrics. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| cmrads_mae | ||
| Mean absolute errors for all models. | ||
|
|
||
| Returns | ||
| ------- | ||
| dict[str, dict] | ||
| Metric names and values for all models. | ||
| """ | ||
| return { | ||
| "MAE": cmrads_mae, | ||
| } | ||
|
|
||
|
|
||
| def test_cmrads200(metrics: dict[str, dict]) -> None: | ||
| """ | ||
| Run CMRAds200 test. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| metrics | ||
| All CMRAds200 metrics. | ||
| """ | ||
| return | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| metrics: | ||
| MAE: | ||
| good: 0.10 | ||
| bad: 0.60 | ||
| unit: eV | ||
| tooltip: Mean Absolute Error | ||
| level_of_theory: PBE |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| """Run CMRAds200 app.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from dash import Dash | ||
| from dash.html import Div | ||
|
|
||
| from ml_peg.app import APP_ROOT | ||
| from ml_peg.app.base_app import BaseApp | ||
| from ml_peg.app.utils.build_callbacks import ( | ||
| plot_from_table_column, | ||
| struct_from_scatter, | ||
| ) | ||
| from ml_peg.app.utils.load import read_plot | ||
| from ml_peg.models.get_models import get_model_names | ||
| from ml_peg.models.models import current_models | ||
|
|
||
| # Get all models | ||
| MODELS = get_model_names(current_models) | ||
| BENCHMARK_NAME = "CMRAds200" | ||
| DOCS_URL = ( | ||
| "https://ddmms.github.io/ml-peg/user_guide/benchmarks/surfaces.html#cmrads200" | ||
| ) | ||
| DATA_PATH = APP_ROOT / "data" / "surfaces" / "CMRAds200" | ||
|
|
||
|
|
||
| class CMRAds200App(BaseApp): | ||
| """CMRAds200 benchmark app layout and callbacks.""" | ||
|
|
||
| def register_callbacks(self) -> None: | ||
| """Register callbacks to app.""" | ||
| scatter = read_plot( | ||
| DATA_PATH / "figure_adsorption_energies.json", | ||
| id=f"{BENCHMARK_NAME}-figure", | ||
| ) | ||
|
|
||
| structs_dir = DATA_PATH / MODELS[0] | ||
|
|
||
| # Assets dir will be parent directory | ||
| structs = [ | ||
| f"/assets/surfaces/CMRAds200/{MODELS[0]}/{struct_file.stem}.xyz" | ||
| for struct_file in sorted(structs_dir.glob("*.xyz")) | ||
|
benshi97 marked this conversation as resolved.
Outdated
|
||
| ] | ||
|
|
||
| plot_from_table_column( | ||
| table_id=self.table_id, | ||
| plot_id=f"{BENCHMARK_NAME}-figure-placeholder", | ||
| column_to_plot={"MAE": scatter}, | ||
| ) | ||
|
|
||
| struct_from_scatter( | ||
| scatter_id=f"{BENCHMARK_NAME}-figure", | ||
| struct_id=f"{BENCHMARK_NAME}-struct-placeholder", | ||
| structs=structs, | ||
| mode="traj", | ||
| ) | ||
|
|
||
|
|
||
| def get_app() -> CMRAds200App: | ||
| """ | ||
| Get CMRAds200 benchmark app layout and callback registration. | ||
|
|
||
| Returns | ||
| ------- | ||
| CMRAds200App | ||
| Benchmark layout and callback registration. | ||
| """ | ||
| return CMRAds200App( | ||
| name=BENCHMARK_NAME, | ||
| description=( | ||
| "Performance in predicting adsorption energies for 200 " | ||
| "adsorbate-surface systems." | ||
| ), | ||
| docs_url=DOCS_URL, | ||
| table_path=DATA_PATH / "cmrads_metrics_table.json", | ||
| extra_components=[ | ||
| Div(id=f"{BENCHMARK_NAME}-figure-placeholder"), | ||
| Div(id=f"{BENCHMARK_NAME}-struct-placeholder"), | ||
| ], | ||
| ) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| # Create Dash app | ||
| full_app = Dash(__name__, assets_folder=DATA_PATH.parent.parent) | ||
|
|
||
| # Construct layout and register callbacks | ||
| cmrads200_app = get_app() | ||
| full_app.layout = cmrads200_app.layout | ||
| cmrads200_app.register_callbacks() | ||
|
|
||
| # Run app | ||
| full_app.run(port=8056, debug=True) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.