mattergraph-benchmarks 0.1.0__py3-none-any.whl

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.
@@ -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,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,9 @@
1
+ mattergraph_benchmarks/__init__.py,sha256=b23gJLYVl47s4_wKDF_uziJjwKJnFRoju9XPi6N630A,1942
2
+ mattergraph_benchmarks/discovery_metrics.py,sha256=3iwMf9v-NIblv7BaznX28DUSBop70XQRgmHbfzMCUGw,545
3
+ mattergraph_benchmarks/matbench_adapter.py,sha256=wdpuV_-MSyvCInNw1_HEl_KakcSiLNVLn4n02Z6JmYA,1997
4
+ mattergraph_benchmarks/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ mattergraph_benchmarks/uncertainty.py,sha256=ESFT8FVD52nNIXRHu07oAFvuYj-lN54LL_1w_U4vJHQ,484
6
+ mattergraph_benchmarks/validation_split.py,sha256=5Z-Oz74ajXHBboxnOi5J6Zkq9qZXV1WQZr57fSUMZL4,1040
7
+ mattergraph_benchmarks-0.1.0.dist-info/METADATA,sha256=8trmHX8hECh-pjwZZ7KCUyi0riXCh3tJ8q-wxu1Xg7g,2008
8
+ mattergraph_benchmarks-0.1.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
9
+ mattergraph_benchmarks-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any