mattergraph-benchmarks 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mattergraph_benchmarks-0.1.0/.gitignore +48 -0
- mattergraph_benchmarks-0.1.0/PKG-INFO +49 -0
- mattergraph_benchmarks-0.1.0/README.md +20 -0
- mattergraph_benchmarks-0.1.0/mattergraph_benchmarks/__init__.py +75 -0
- mattergraph_benchmarks-0.1.0/mattergraph_benchmarks/discovery_metrics.py +23 -0
- mattergraph_benchmarks-0.1.0/mattergraph_benchmarks/matbench_adapter.py +59 -0
- mattergraph_benchmarks-0.1.0/mattergraph_benchmarks/py.typed +0 -0
- mattergraph_benchmarks-0.1.0/mattergraph_benchmarks/uncertainty.py +17 -0
- mattergraph_benchmarks-0.1.0/mattergraph_benchmarks/validation_split.py +34 -0
- mattergraph_benchmarks-0.1.0/pyproject.toml +48 -0
- mattergraph_benchmarks-0.1.0/tests/test_benchmarks_optional_imports.py +21 -0
- mattergraph_benchmarks-0.1.0/tests/test_discovery_metrics.py +9 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
.mypy_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.hypothesis/
|
|
14
|
+
.coverage
|
|
15
|
+
coverage.xml
|
|
16
|
+
htmlcov/
|
|
17
|
+
|
|
18
|
+
# Docs build output
|
|
19
|
+
site/
|
|
20
|
+
|
|
21
|
+
# Env
|
|
22
|
+
.env
|
|
23
|
+
.env.local
|
|
24
|
+
*.local
|
|
25
|
+
|
|
26
|
+
# Node
|
|
27
|
+
node_modules/
|
|
28
|
+
apps/web/dist/
|
|
29
|
+
apps/web/playwright-report/
|
|
30
|
+
apps/web/test-results/
|
|
31
|
+
*.tsbuildinfo
|
|
32
|
+
.next/
|
|
33
|
+
out/
|
|
34
|
+
|
|
35
|
+
# IDE
|
|
36
|
+
.idea/
|
|
37
|
+
.vscode/
|
|
38
|
+
*.swp
|
|
39
|
+
|
|
40
|
+
# OS
|
|
41
|
+
.DS_Store
|
|
42
|
+
|
|
43
|
+
# Data artifacts (keep demo/ tracked)
|
|
44
|
+
data/cache/
|
|
45
|
+
*.sqlite3
|
|
46
|
+
|
|
47
|
+
.claude
|
|
48
|
+
apps/private-platform-ui/
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mattergraph-benchmarks
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Benchmark adapters and evaluation utilities for MatterGraph.
|
|
5
|
+
Project-URL: Homepage, https://github.com/cyrusmo/MatterGraph
|
|
6
|
+
Project-URL: Repository, https://github.com/cyrusmo/MatterGraph
|
|
7
|
+
Project-URL: Issues, https://github.com/cyrusmo/MatterGraph/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/cyrusmo/MatterGraph/blob/main/CHANGELOG.md
|
|
9
|
+
Author: MatterGraph contributors
|
|
10
|
+
License-Expression: Apache-2.0
|
|
11
|
+
Keywords: benchmarks,machine-learning,matbench,materials-science,uncertainty
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: httpx
|
|
23
|
+
Requires-Dist: mattergraph-core~=0.1.0
|
|
24
|
+
Requires-Dist: numpy>=1.24
|
|
25
|
+
Requires-Dist: pandas>=2.0
|
|
26
|
+
Requires-Dist: pymatgen>=2024.1.1
|
|
27
|
+
Requires-Dist: scikit-learn>=1.3
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# mattergraph-benchmarks
|
|
31
|
+
|
|
32
|
+
Benchmark adapters and evaluation utilities for [MatterGraph](https://github.com/cyrusmo/MatterGraph).
|
|
33
|
+
|
|
34
|
+
## What's in here
|
|
35
|
+
|
|
36
|
+
- **Discovery metrics** — ranking-quality measures (nDCG and friends) for screening workflows, where what matters is whether good candidates surface near the top.
|
|
37
|
+
- **Uncertainty** — `coverage_at_target` for checking whether predicted intervals are calibrated.
|
|
38
|
+
- **Validation splits** — stratified splitting helpers that respect composition and structure grouping.
|
|
39
|
+
- **Matbench adapter** — optional bridge to [Matbench](https://matbench.materialsproject.org/) tasks. Install `matbench` separately to enable it.
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install mattergraph-benchmarks
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## License
|
|
48
|
+
|
|
49
|
+
Apache-2.0
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# mattergraph-benchmarks
|
|
2
|
+
|
|
3
|
+
Benchmark adapters and evaluation utilities for [MatterGraph](https://github.com/cyrusmo/MatterGraph).
|
|
4
|
+
|
|
5
|
+
## What's in here
|
|
6
|
+
|
|
7
|
+
- **Discovery metrics** — ranking-quality measures (nDCG and friends) for screening workflows, where what matters is whether good candidates surface near the top.
|
|
8
|
+
- **Uncertainty** — `coverage_at_target` for checking whether predicted intervals are calibrated.
|
|
9
|
+
- **Validation splits** — stratified splitting helpers that respect composition and structure grouping.
|
|
10
|
+
- **Matbench adapter** — optional bridge to [Matbench](https://matbench.materialsproject.org/) tasks. Install `matbench` separately to enable it.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install mattergraph-benchmarks
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## License
|
|
19
|
+
|
|
20
|
+
Apache-2.0
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from importlib import import_module
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from mattergraph_benchmarks.discovery_metrics import dcg, ndcg_at_k
|
|
8
|
+
from mattergraph_benchmarks.matbench_adapter import matbench_dataframe, matbench_regression
|
|
9
|
+
from mattergraph_benchmarks.uncertainty import coverage_at_target
|
|
10
|
+
from mattergraph_benchmarks.validation_split import stratified_regression_split
|
|
11
|
+
|
|
12
|
+
_EXPORTS: dict[str, tuple[str, str, str | None]] = {
|
|
13
|
+
"matbench_dataframe": (
|
|
14
|
+
"mattergraph_benchmarks.matbench_adapter",
|
|
15
|
+
"matbench_dataframe",
|
|
16
|
+
None,
|
|
17
|
+
),
|
|
18
|
+
"matbench_regression": (
|
|
19
|
+
"mattergraph_benchmarks.matbench_adapter",
|
|
20
|
+
"matbench_regression",
|
|
21
|
+
None,
|
|
22
|
+
),
|
|
23
|
+
"ndcg_at_k": (
|
|
24
|
+
"mattergraph_benchmarks.discovery_metrics",
|
|
25
|
+
"ndcg_at_k",
|
|
26
|
+
None,
|
|
27
|
+
),
|
|
28
|
+
"dcg": (
|
|
29
|
+
"mattergraph_benchmarks.discovery_metrics",
|
|
30
|
+
"dcg",
|
|
31
|
+
None,
|
|
32
|
+
),
|
|
33
|
+
"coverage_at_target": (
|
|
34
|
+
"mattergraph_benchmarks.uncertainty",
|
|
35
|
+
"coverage_at_target",
|
|
36
|
+
None,
|
|
37
|
+
),
|
|
38
|
+
"stratified_regression_split": (
|
|
39
|
+
"mattergraph_benchmarks.validation_split",
|
|
40
|
+
"stratified_regression_split",
|
|
41
|
+
(
|
|
42
|
+
"Install the optional `scikit-learn` dependency or run "
|
|
43
|
+
"`uv sync --all-packages --group dev` to use stratified_regression_split."
|
|
44
|
+
),
|
|
45
|
+
),
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
__all__ = [
|
|
49
|
+
"matbench_dataframe",
|
|
50
|
+
"matbench_regression",
|
|
51
|
+
"ndcg_at_k",
|
|
52
|
+
"dcg",
|
|
53
|
+
"coverage_at_target",
|
|
54
|
+
"stratified_regression_split",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def __getattr__(name: str) -> Any:
|
|
59
|
+
if name not in _EXPORTS:
|
|
60
|
+
msg = f"module {__name__!r} has no attribute {name!r}"
|
|
61
|
+
raise AttributeError(msg)
|
|
62
|
+
module_name, attr_name, hint = _EXPORTS[name]
|
|
63
|
+
try:
|
|
64
|
+
module = import_module(module_name)
|
|
65
|
+
except ImportError as e:
|
|
66
|
+
if hint is None:
|
|
67
|
+
raise
|
|
68
|
+
raise ImportError(hint) from e
|
|
69
|
+
value = getattr(module, attr_name)
|
|
70
|
+
globals()[name] = value
|
|
71
|
+
return value
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def __dir__() -> list[str]:
|
|
75
|
+
return sorted(set(globals()) | set(__all__))
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from numpy.typing import ArrayLike
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def dcg(relevances: ArrayLike) -> float:
|
|
8
|
+
r = np.asarray(relevances, dtype=float)
|
|
9
|
+
if r.size == 0:
|
|
10
|
+
return 0.0
|
|
11
|
+
g = 2.0**r - 1.0
|
|
12
|
+
i = np.arange(1, len(r) + 1, dtype=float)
|
|
13
|
+
return float(np.sum(g / np.log2(i + 1)))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def ndcg_at_k(relevances: ArrayLike, k: int = 10) -> float:
|
|
17
|
+
r = np.asarray(relevances, dtype=float)[:k]
|
|
18
|
+
if r.size == 0:
|
|
19
|
+
return 0.0
|
|
20
|
+
ideal = np.sort(r)[::-1]
|
|
21
|
+
d = dcg(r)
|
|
22
|
+
i = dcg(ideal)
|
|
23
|
+
return d / i if i > 0 else 0.0
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _load_matbench_task(name: str) -> Any:
|
|
10
|
+
try:
|
|
11
|
+
from matbench.task import MatbenchTask # type: ignore[import-not-found, import-untyped]
|
|
12
|
+
except ImportError as e: # pragma: no cover
|
|
13
|
+
msg = "Install the optional `matbench` package to use the Matbench adapter."
|
|
14
|
+
raise ImportError(msg) from e
|
|
15
|
+
t = MatbenchTask(name) # type: ignore[operator]
|
|
16
|
+
t.load() # type: ignore[no-untyped-call]
|
|
17
|
+
return t
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def matbench_dataframe(task: str = "matbench_v0.1_log_gvrh") -> pd.DataFrame:
|
|
21
|
+
"""
|
|
22
|
+
Load a Matbench task into a :class:`pandas.DataFrame` with a ``target`` and ``split`` column.
|
|
23
|
+
|
|
24
|
+
The ``matbench`` package is an optional install.
|
|
25
|
+
"""
|
|
26
|
+
t = _load_matbench_task(task)
|
|
27
|
+
f = t.get_train_and_val() # type: ignore[no-untyped-call]
|
|
28
|
+
train = f[0] # type: ignore[index]
|
|
29
|
+
test = f[1] # type: ignore[index]
|
|
30
|
+
tr_x, tr_y, _ = train # type: ignore[misc]
|
|
31
|
+
te_x, te_y, _ = test # type: ignore[misc]
|
|
32
|
+
|
|
33
|
+
def _as_df(x: object, y: object, s: str) -> pd.DataFrame:
|
|
34
|
+
d = x.to_pandas() if hasattr(x, "to_pandas") else pd.DataFrame(x) # type: ignore[attr-defined, arg-type, call-overload] # noqa: E501
|
|
35
|
+
d = d.copy()
|
|
36
|
+
d["target"] = np.asarray(y).ravel()
|
|
37
|
+
d["split"] = s
|
|
38
|
+
return d
|
|
39
|
+
|
|
40
|
+
tr = _as_df(tr_x, tr_y, "train")
|
|
41
|
+
te = _as_df(te_x, te_y, "test")
|
|
42
|
+
return pd.concat([tr, te], ignore_index=True)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def matbench_regression(task: str = "matbench_v0.1_log_gvrh") -> dict[str, Any]:
|
|
46
|
+
"""Return simple numpy arrays for train/test splits of a Matbench regression task."""
|
|
47
|
+
df = matbench_dataframe(task=task)
|
|
48
|
+
train = df[df["split"] == "train"]
|
|
49
|
+
test = df[df["split"] == "test"]
|
|
50
|
+
y_tr = train["target"].to_numpy()
|
|
51
|
+
y_te = test["target"].to_numpy()
|
|
52
|
+
x_tr = train.drop(columns=["target", "split"], errors="ignore")
|
|
53
|
+
x_te = test.drop(columns=["target", "split"], errors="ignore")
|
|
54
|
+
return {
|
|
55
|
+
"train_X": x_tr,
|
|
56
|
+
"train_y": y_tr,
|
|
57
|
+
"test_X": x_te,
|
|
58
|
+
"test_y": y_te,
|
|
59
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from numpy.typing import ArrayLike
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def coverage_at_target(
|
|
8
|
+
y_true: ArrayLike,
|
|
9
|
+
y_lo: ArrayLike,
|
|
10
|
+
y_hi: ArrayLike,
|
|
11
|
+
) -> float:
|
|
12
|
+
"""Fraction of points where the interval ``[y_lo, y_hi]`` contains ``y_true``."""
|
|
13
|
+
yt = np.asarray(y_true, dtype=float).ravel()
|
|
14
|
+
lo = np.asarray(y_lo, dtype=float).ravel()
|
|
15
|
+
hi = np.asarray(y_hi, dtype=float).ravel()
|
|
16
|
+
m = (yt >= lo) & (yt <= hi)
|
|
17
|
+
return float(np.mean(m)) if m.size else 0.0
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
from numpy.typing import ArrayLike, NDArray
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _load_train_test_split() -> Any:
|
|
11
|
+
try:
|
|
12
|
+
from sklearn.model_selection import train_test_split
|
|
13
|
+
except ImportError as e:
|
|
14
|
+
msg = "Install the optional `scikit-learn` dependency to use stratified_regression_split."
|
|
15
|
+
raise ImportError(msg) from e
|
|
16
|
+
return train_test_split
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def stratified_regression_split(
|
|
20
|
+
y: ArrayLike,
|
|
21
|
+
n_bins: int = 8,
|
|
22
|
+
test_size: float = 0.2,
|
|
23
|
+
random_state: int = 0,
|
|
24
|
+
) -> tuple[NDArray[np.int_], NDArray[np.int_]]:
|
|
25
|
+
"""Bin continuous ``y`` and return train/test index arrays (stratified by bin)."""
|
|
26
|
+
train_test_split = _load_train_test_split()
|
|
27
|
+
yv = np.asarray(y, dtype=float).ravel()
|
|
28
|
+
yq, _ = pd.qcut(yv, n_bins, labels=False, retbins=True, duplicates="drop")
|
|
29
|
+
yq = np.nan_to_num(yq, nan=0.0)
|
|
30
|
+
i = np.arange(len(yv))
|
|
31
|
+
i_train, i_test = train_test_split(
|
|
32
|
+
i, test_size=test_size, random_state=random_state, stratify=yq
|
|
33
|
+
)
|
|
34
|
+
return i_train, i_test
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "mattergraph-benchmarks"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Benchmark adapters and evaluation utilities for MatterGraph."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = "Apache-2.0"
|
|
8
|
+
authors = [{ name = "MatterGraph contributors" }]
|
|
9
|
+
keywords = ["materials-science", "benchmarks", "matbench", "machine-learning", "uncertainty"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 3 - Alpha",
|
|
12
|
+
"Intended Audience :: Science/Research",
|
|
13
|
+
"Operating System :: OS Independent",
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3.10",
|
|
16
|
+
"Programming Language :: Python :: 3.11",
|
|
17
|
+
"Programming Language :: Python :: 3.12",
|
|
18
|
+
"Topic :: Scientific/Engineering :: Chemistry",
|
|
19
|
+
"Topic :: Scientific/Engineering :: Physics",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"mattergraph-core~=0.1.0",
|
|
23
|
+
"numpy>=1.24",
|
|
24
|
+
"pandas>=2.0",
|
|
25
|
+
"scikit-learn>=1.3",
|
|
26
|
+
"pymatgen>=2024.1.1",
|
|
27
|
+
"httpx",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://github.com/cyrusmo/MatterGraph"
|
|
32
|
+
Repository = "https://github.com/cyrusmo/MatterGraph"
|
|
33
|
+
Issues = "https://github.com/cyrusmo/MatterGraph/issues"
|
|
34
|
+
Changelog = "https://github.com/cyrusmo/MatterGraph/blob/main/CHANGELOG.md"
|
|
35
|
+
|
|
36
|
+
[build-system]
|
|
37
|
+
requires = ["hatchling"]
|
|
38
|
+
build-backend = "hatchling.build"
|
|
39
|
+
|
|
40
|
+
[tool.uv.sources]
|
|
41
|
+
mattergraph-core = { workspace = true }
|
|
42
|
+
|
|
43
|
+
[tool.hatch.build.targets.wheel]
|
|
44
|
+
packages = ["mattergraph_benchmarks"]
|
|
45
|
+
core-metadata-version = "2.4"
|
|
46
|
+
|
|
47
|
+
[tool.hatch.build.targets.sdist]
|
|
48
|
+
core-metadata-version = "2.4"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
|
|
3
|
+
import mattergraph_benchmarks
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_stratified_split_has_helpful_optional_dependency_error(
|
|
8
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
9
|
+
) -> None:
|
|
10
|
+
module = importlib.reload(mattergraph_benchmarks)
|
|
11
|
+
real_import_module = module.import_module
|
|
12
|
+
|
|
13
|
+
def fake_import_module(name: str, package: str | None = None) -> object:
|
|
14
|
+
if name == "mattergraph_benchmarks.validation_split":
|
|
15
|
+
raise ImportError("No module named 'sklearn'")
|
|
16
|
+
return real_import_module(name, package)
|
|
17
|
+
|
|
18
|
+
monkeypatch.setattr(module, "import_module", fake_import_module)
|
|
19
|
+
|
|
20
|
+
with pytest.raises(ImportError, match="scikit-learn"):
|
|
21
|
+
_ = module.stratified_regression_split
|