hea-bench 2.6.2__tar.gz → 2.7.2__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.
- {hea_bench-2.6.2 → hea_bench-2.7.2}/CHANGELOG.md +156 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/CITATION.cff +1 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/PKG-INFO +75 -40
- {hea_bench-2.6.2 → hea_bench-2.7.2}/README.md +66 -38
- {hea_bench-2.6.2 → hea_bench-2.7.2}/data/raw/README.md +1 -1
- hea_bench-2.7.2/data/raw/borg2020/MPEA_dataset.csv +1546 -0
- hea_bench-2.7.2/data/raw/chizhevskiy2026/UPSTREAM_README.md +66 -0
- hea_bench-2.7.2/data/raw/chizhevskiy2026/database_of_HEAs.csv +12428 -0
- hea_bench-2.7.2/data/raw/pei2020/pei2020_alloys_phases.csv +1253 -0
- hea_bench-2.7.2/data/raw/peivaste/fetch.py +80 -0
- hea_bench-2.7.2/docs/benchmark-baselines.json +1137 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/llms.txt +43 -26
- {hea_bench-2.6.2 → hea_bench-2.7.2}/pyproject.toml +51 -9
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/__init__.py +5 -2
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/_json.py +15 -0
- hea_bench-2.7.2/src/hea_bench/_model_cache.py +46 -0
- hea_bench-2.7.2/src/hea_bench/_overrides.py +24 -0
- hea_bench-2.7.2/src/hea_bench/_paths.py +66 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/consolidate.py +24 -16
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/corpus.py +5 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/loaders/chizhevskiy2026.py +6 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/composition.py +84 -21
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/corpus/__init__.py +121 -21
- hea_bench-2.7.2/src/hea_bench/custom.py +136 -0
- hea_bench-2.7.2/src/hea_bench/descriptors/_tables.py +28 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/backend.py +2 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/pair_enthalpies.py +5 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/elastic.py +2 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/electronegativity.py +10 -5
- hea_bench-2.7.2/src/hea_bench/descriptors/elements.py +132 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/entropy.py +2 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/gamma.py +4 -3
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/lam.py +2 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/melting.py +4 -3
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/miedema.py +14 -3
- hea_bench-2.7.2/src/hea_bench/descriptors/miedema_decomposition.py +303 -0
- hea_bench-2.7.2/src/hea_bench/descriptors/omega.py +168 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/phi.py +9 -3
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/size.py +5 -4
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/vec.py +4 -3
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/design/search.py +31 -3
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/mcp_server.py +602 -179
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/__init__.py +2 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/borg.py +2 -2
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/hardness.py +9 -2
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/tier_a.py +4 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/guo_vec.py +32 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/king_phi.py +2 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/senkov_kappa.py +38 -2
- hea_bench-2.7.2/src/hea_bench/rules/sheikh_ductility.py +58 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/tsai_sigma.py +2 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/yang_omega.py +2 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/ye_phi.py +2 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/yeh_smix.py +2 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/zhang_delta.py +2 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/uncertainty/applicability.py +4 -2
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/uncertainty/coverage.py +10 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/uncertainty/phase.py +31 -6
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/webapp.py +82 -49
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/app_smoke.cjs +91 -9
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/_sync_js_provenance.py +4 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/_sync_js_tables.py +5 -45
- hea_bench-2.7.2/tests/data/feature_parity.json +544 -0
- hea_bench-2.7.2/tests/data/formula_parity_cases.json +40 -0
- hea_bench-2.7.2/tests/package_smoke.py +165 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_app_smoke.py +6 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_applicability.py +2 -2
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_benchmark_corpus.py +1 -2
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_chizhevskiy_loader.py +4 -3
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_composition.py +61 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_conformal.py +26 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_corpus.py +38 -2
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_design_search.py +21 -0
- hea_bench-2.7.2/tests/test_desktop_smoke.py +79 -0
- hea_bench-2.6.2/tests/test_app_parity.py → hea_bench-2.7.2/tests/test_feature_parity.py +58 -19
- hea_bench-2.7.2/tests/test_installed_package.py +88 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_kappa_sigma_ductility.py +27 -0
- hea_bench-2.7.2/tests/test_mcp_app_features.py +227 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_mcp_expansion.py +1 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_mcp_server.py +12 -9
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_provenance_data.py +15 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_web_miedema.py +43 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_web_parity.py +53 -6
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_webapp.py +48 -1
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/web_engine_snapshot.cjs +6 -2
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/web_parity_snapshot.cjs +15 -2
- {hea_bench-2.6.2 → hea_bench-2.7.2}/web/README.md +27 -18
- hea_bench-2.6.2/src/hea_bench/descriptors/omega.py +0 -77
- hea_bench-2.6.2/src/hea_bench/rules/sheikh_ductility.py +0 -42
- hea_bench-2.6.2/tests/data/app_parity.json +0 -251
- {hea_bench-2.6.2 → hea_bench-2.7.2}/.gitignore +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/LICENSE +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/data/raw/borg2020/README.md +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/data/raw/chizhevskiy2026/README.md +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/data/raw/pei2020/README.md +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/data/raw/peivaste/README.md +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/examples/README.md +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/__init__.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/baselines.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/evaluate.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/frozen.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/loaders/__init__.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/loaders/borg2020.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/loaders/pei2020.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/loaders/peivaste.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/metrics.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/splits.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/benchmark/taxonomy.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/ceramics/__init__.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/cli.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/constants.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/__init__.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/LICENSE.matminer.txt +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/README.md +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/__init__.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/elemental.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/mechanics.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/miedema_parameters.csv +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/pair_enthalpies.tsv +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/descriptors/data/provenance.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/design/__init__.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/design/campaign.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/design/constraints.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/__init__.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/_data.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/data/LICENSE.pymatgen.txt +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/data/README.md +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/data/oxide_elements.json +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/descriptors.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/families.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/radii.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/oxides/states.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/data/__init__.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/data/atomic_masses.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/properties/data/element_prices.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/rules/__init__.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/uncertainty/__init__.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/uncertainty/conformal.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/src/hea_bench/uncertainty/splitting.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/__init__.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/conftest.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/_build_parity_cases.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/_sync_js_oxide_tables.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/_vendor_oxide_data.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/web_engine_calls.json +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/web_oxide_parity_cases.json +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/web_parity_cases.json +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/data/web_properties_parity_cases.json +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_benchmark_evaluate.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_benchmark_metrics.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_benchmark_splits.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_campaign.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_ceramics.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_cli.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_consolidate_errors.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_descriptor_backend.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_descriptors_simple.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_elastic.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_element_expansion.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_entropy.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_lambda_gamma.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_mechanics_data.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_miedema_and_omega.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_oxides.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_pair_enthalpies.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_phi.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_phi_rules.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_properties_borg.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_properties_cost.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_properties_hardness.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_properties_tier_a.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_rules.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_smoke.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_version_sync.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_web_engine.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_web_oxides_parity.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_web_properties_parity.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/test_yang_zhang_anchors.py +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/web_miedema_snapshot.cjs +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/web_oxides_snapshot.cjs +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/tests/web_properties_snapshot.cjs +0 -0
- {hea_bench-2.6.2 → hea_bench-2.7.2}/web/mathjax/LICENSE +0 -0
|
@@ -10,6 +10,162 @@ The format is loosely based on
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [2.7.2] — 2026-10-06
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- The landing page said the Dataset tab holds 7,783 alloys, the size of
|
|
18
|
+
corpus v0.1.0. The tab has opened on v0.2.0, 10,290 alloys, since
|
|
19
|
+
2.7.0. A test now ties that number to the corpus the tab opens.
|
|
20
|
+
- Documentation that still called corpus v0.2.0 opt-in, or called the
|
|
21
|
+
Chizhevskiy rows in group notation unparseable, now matches 2.7.1.
|
|
22
|
+
Those rows parse, and the loader keeps them out because v0.2.0 is
|
|
23
|
+
frozen.
|
|
24
|
+
|
|
25
|
+
## [2.7.1] — 2026-10-06
|
|
26
|
+
|
|
27
|
+
2.7.1 is the first published 2.7 release. GitHub refused the v2.7.0 tag
|
|
28
|
+
push, so 2.7.0 reached only the web site. 2.7.1 contains everything
|
|
29
|
+
listed under 2.7.0 plus the changes below, which answer an outside
|
|
30
|
+
review of the app and the library.
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- **Every function that takes a composition also takes a formula
|
|
35
|
+
string.** `hb.smix("CoCrFeMnNi")` raised `AttributeError` before and
|
|
36
|
+
now equals `hb.smix(hb.parse_formula("CoCrFeMnNi"))`. A test fails for
|
|
37
|
+
any public composition function that does not accept a formula.
|
|
38
|
+
- **Group notation**, in all four parts. `(CoCrFeNi)95Al5` is 95 parts
|
|
39
|
+
equimolar CoCrFeNi plus 5 parts Al, the usual HEA convention, and
|
|
40
|
+
groups nest. Repeated elements add up, so `CoCrFeNiNi` is Ni at
|
|
41
|
+
40 at.%. The app now uses the library's parser, and a shared case list
|
|
42
|
+
keeps the Python and browser parsers identical.
|
|
43
|
+
- **Rule notes.** Guo VEC flags a VEC within 0.2 of its 8.0 or 6.87
|
|
44
|
+
cutoff (`guo_vec.boundary_note`), where the published data scatter.
|
|
45
|
+
The verdict itself is unchanged, because the benchmark measures it.
|
|
46
|
+
Senkov κ names the pair it takes ΔH_IM from (`im_pair`) and adds a
|
|
47
|
+
note when that pair has an element under 10 at.%, because κ does not
|
|
48
|
+
weight the pair by amount.
|
|
49
|
+
- **Composition search shows each candidate's predicted phase**, the
|
|
50
|
+
four-class prediction set, in the library, the MCP `design_search`
|
|
51
|
+
tool and the app. The app's example search now caps Al at 20 at.% and
|
|
52
|
+
uses 4 or 5 elements, so it no longer opens on alloys of 40 to 70%
|
|
53
|
+
Al.
|
|
54
|
+
- `predict_phase_set` reports the coverage the coverage study measured
|
|
55
|
+
for corpus v0.1.0 at the chosen confidence, inside and outside the
|
|
56
|
+
dataset's range (`measured_coverage`).
|
|
57
|
+
|
|
58
|
+
### Changed
|
|
59
|
+
|
|
60
|
+
- **Sheikh ductility returns `not_applicable` for any alloy with an
|
|
61
|
+
element outside Ti, Zr, Hf, V, Nb, Ta, Cr, Mo and W**, the refractory
|
|
62
|
+
alloys the screen was built on. It used to give a verdict for alloys
|
|
63
|
+
such as CoCrFeMnNi.
|
|
64
|
+
- The domain flag reads "Inside the dataset's range?" instead of
|
|
65
|
+
"Resembles the dataset?". Inside the range it gives the measured
|
|
66
|
+
coverage of the 90% sets on unseen alloy systems (87.5% for single
|
|
67
|
+
versus multi-phase, 82.9% for the structure), so a yes is not read as
|
|
68
|
+
a promise of accuracy.
|
|
69
|
+
- **The desktop app starts its engine by itself.** The engine has always
|
|
70
|
+
been inside the exe. The app now also fetches the Peivaste source file
|
|
71
|
+
by itself the first time it is online, checks it and keeps it, so the
|
|
72
|
+
whole app works offline after that. That file cannot ship inside the
|
|
73
|
+
exe until its authors license it for redistribution. Until the app
|
|
74
|
+
has been online once, the hardness prediction still works, because it
|
|
75
|
+
needs only data inside the app, and the phase and dataset cards say
|
|
76
|
+
what they are waiting for. The website's Start button behaves the
|
|
77
|
+
same way.
|
|
78
|
+
- The Benchmark tab leads with each model's two scores and the gap.
|
|
79
|
+
- The app's footer says "Runs on this device" instead of "Offline",
|
|
80
|
+
which read like a warning.
|
|
81
|
+
|
|
82
|
+
### Fixed
|
|
83
|
+
|
|
84
|
+
- A permalink always opens in alloy mode, even when the page was last
|
|
85
|
+
in Oxides mode.
|
|
86
|
+
- A formula that fails to parse clears the previous results instead of
|
|
87
|
+
leaving them up beside the error.
|
|
88
|
+
- The app merges repeated elements (`CoCrFeNiNi`) instead of rejecting
|
|
89
|
+
them as duplicates.
|
|
90
|
+
- Amounts with more than two decimals reach the result, its result ID
|
|
91
|
+
and the permalink unrounded. The table's 0.01 at.% display rounding
|
|
92
|
+
used to change them.
|
|
93
|
+
- The calculator shows one melting-temperature card, in K and °C,
|
|
94
|
+
instead of two.
|
|
95
|
+
- The release bot retries the tag push, which GitHub refused once for
|
|
96
|
+
v2.7.0.
|
|
97
|
+
|
|
98
|
+
The experimental corpus is unchanged. The Chizhevskiy loader keeps rows
|
|
99
|
+
written in group notation out, so corpus v0.2.0 stays byte-identical,
|
|
100
|
+
and adding them is left for a future corpus version.
|
|
101
|
+
|
|
102
|
+
## [2.7.0] — 2026-10-06
|
|
103
|
+
|
|
104
|
+
### Added
|
|
105
|
+
|
|
106
|
+
- **Every feature is now in all four parts**: the Python package, the
|
|
107
|
+
MCP server, the website and the desktop app. A person only needs to
|
|
108
|
+
pick one of them. This is a standing project rule from now on, and CI
|
|
109
|
+
enforces it (see the last item below).
|
|
110
|
+
- **The MCP server has every feature of the package: 24 tools, up from
|
|
111
|
+
13.** New tools: `ceramic_report`, `element_data`, `corpus_build`,
|
|
112
|
+
`corpus_export`, `measured_properties`, `predict_phase_set`,
|
|
113
|
+
`benchmark_summary`, `benchmark_run`, `benchmark_folds`,
|
|
114
|
+
`benchmark_score` and `coverage_study`. `alloy_descriptors` now
|
|
115
|
+
returns the Miedema formation enthalpies, and `alloy_descriptors`,
|
|
116
|
+
`alloy_rules` and `omega_sensitivity` accept custom elements and pair
|
|
117
|
+
enthalpies. `campaign_suggest` also accepts a campaign inline. The
|
|
118
|
+
server moves to the official MCP Python SDK 2.x (`mcp>=2.3,<3`), and
|
|
119
|
+
the `mcp` extra now includes scikit-learn, so hardness, phase sets and
|
|
120
|
+
campaigns work from a registry install.
|
|
121
|
+
- **The dataset works from a plain pip install.** The wheel ships the
|
|
122
|
+
openly licensed source datasets, and `hea_bench.corpus.build_corpus()`
|
|
123
|
+
downloads the one file that declares no license (Peivaste), checks its
|
|
124
|
+
SHA-256 and builds every corpus version in a per-user folder. The MCP
|
|
125
|
+
`corpus_build` tool does the same.
|
|
126
|
+
- **Library functions for what only the apps had:**
|
|
127
|
+
`hea_bench.custom_data()` (your own elements and pair enthalpies, for
|
|
128
|
+
any descriptor or rule), `hea_bench.omega_sensitivity()`,
|
|
129
|
+
`hea_bench.descriptors.miedema_decomposition` and
|
|
130
|
+
`hea_bench.descriptors.elements.element_data()`.
|
|
131
|
+
- `pip install "hea-bench[all]"` installs everything. Python 3.13 and
|
|
132
|
+
3.14 are now tested and declared.
|
|
133
|
+
- New checks that keep the four parts equal.
|
|
134
|
+
`tests/test_feature_parity.py` (formerly `test_app_parity.py`) fails CI
|
|
135
|
+
unless every feature has its library function, its MCP tool, a working
|
|
136
|
+
app surface and tests. The CI `package` job builds the wheel, installs
|
|
137
|
+
it fresh and calls every MCP tool over stdio
|
|
138
|
+
(`tests/test_installed_package.py`, also run by the pre-push
|
|
139
|
+
preflight). The release `desktop-build` job uses every tab inside the
|
|
140
|
+
built exe before attaching it (`tests/test_desktop_smoke.py`). The
|
|
141
|
+
preflight also checks that the MCP container image receives every file
|
|
142
|
+
the wheel bundles.
|
|
143
|
+
|
|
144
|
+
### Changed
|
|
145
|
+
|
|
146
|
+
- **The app is much smoother.** It keeps its fitted models (hardness,
|
|
147
|
+
phase sets, the dataset check) in the browser between visits, so a
|
|
148
|
+
returning visitor gets predictions about a second after the engine
|
|
149
|
+
starts instead of waiting about 18 seconds for refits. The engine
|
|
150
|
+
prepares models in the background while the page is idle, starts by
|
|
151
|
+
itself for returning visitors, and long tables no longer stall tab
|
|
152
|
+
switches.
|
|
153
|
+
- **The dataset opens on corpus v0.2.0, the largest (10,290 alloys)**,
|
|
154
|
+
in `load_corpus()`, the app's Dataset tab and the MCP corpus tools.
|
|
155
|
+
The benchmark, the phase predictions and the domain flag stay on the
|
|
156
|
+
reference corpus v0.1.0, so every published number is unchanged.
|
|
157
|
+
- The in-app engine runs Pyodide 0.29.5 (was 0.29.3), the desktop app
|
|
158
|
+
uses Tauri 2.12.1 (was 2.11.2) without the unused logging plugin, the
|
|
159
|
+
MCP container image uses Python 3.13, and every GitHub Action is on
|
|
160
|
+
its current major version.
|
|
161
|
+
|
|
162
|
+
### Fixed
|
|
163
|
+
|
|
164
|
+
- The data-file fingerprints the app shows now match the ones the
|
|
165
|
+
library reports on every platform. They were computed from a Windows
|
|
166
|
+
checkout's line endings; they now use the bytes git stores. The data
|
|
167
|
+
itself is unchanged.
|
|
168
|
+
|
|
13
169
|
## [2.6.2] — 2026-10-06
|
|
14
170
|
|
|
15
171
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: hea-bench
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.2
|
|
4
4
|
Summary: An open, interpretable calculator of high-entropy-alloy and high-entropy-oxide thermodynamic and geometric descriptors plus the canonical empirical phase-prediction rules.
|
|
5
5
|
Project-URL: Homepage, https://dfieser.github.io/hea-bench/
|
|
6
6
|
Project-URL: Repository, https://github.com/dfieser/hea-bench
|
|
@@ -19,19 +19,26 @@ Classifier: Programming Language :: Python :: 3
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
24
|
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
23
25
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
24
26
|
Requires-Python: >=3.10
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: mcp<3,>=2.3; extra == 'all'
|
|
29
|
+
Requires-Dist: scikit-learn~=1.7.2; extra == 'all'
|
|
25
30
|
Provides-Extra: benchmark
|
|
26
31
|
Requires-Dist: scikit-learn~=1.7.2; extra == 'benchmark'
|
|
27
32
|
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
28
34
|
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
29
35
|
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
30
36
|
Requires-Dist: ruff~=0.15.0; extra == 'dev'
|
|
31
37
|
Provides-Extra: interop
|
|
32
38
|
Requires-Dist: heacalculator~=2.0.1; extra == 'interop'
|
|
33
39
|
Provides-Extra: mcp
|
|
34
|
-
Requires-Dist: mcp<2
|
|
40
|
+
Requires-Dist: mcp<3,>=2.3; extra == 'mcp'
|
|
41
|
+
Requires-Dist: scikit-learn~=1.7.2; extra == 'mcp'
|
|
35
42
|
Provides-Extra: properties
|
|
36
43
|
Requires-Dist: scikit-learn~=1.7.2; extra == 'properties'
|
|
37
44
|
Description-Content-Type: text/markdown
|
|
@@ -90,10 +97,13 @@ For any composition it reports:
|
|
|
90
97
|
Yang–Zhang Ω, Pauling electronegativity mismatch Δχ, Mansoori excess
|
|
91
98
|
entropy S<sub>E</sub>, ΔG<sub>ss</sub>, ΔG<sub>max</sub>, King Φ, Ye φ.
|
|
92
99
|
- **Phase-prediction rules:** Yeh entropy, Zhang δ, Guo–Liu VEC,
|
|
93
|
-
Yang–Zhang Ω, King Φ, Ye
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
structural, and
|
|
100
|
+
Yang–Zhang Ω, King Φ, Ye φ, Senkov–Miracle κ, the Tsai σ-phase
|
|
101
|
+
window and Sheikh ductility.
|
|
102
|
+
- **Miedema formation enthalpies:** compound / solid-solution /
|
|
103
|
+
amorphous, decomposed into chemical, elastic, structural, and
|
|
104
|
+
topological terms.
|
|
105
|
+
- **Your own elements and pair values:** any descriptor or rule, for a
|
|
106
|
+
composition with an element or pair enthalpy that is not tabulated.
|
|
97
107
|
- **High-entropy oxides** (`hea_bench.oxides` + the apps' Oxides mode):
|
|
98
108
|
rock-salt, perovskite, fluorite, and pyrochlore formability
|
|
99
109
|
descriptors over Shannon ionic radii with automatic charge-balance
|
|
@@ -125,16 +135,27 @@ flowchart LR
|
|
|
125
135
|
D --> E
|
|
126
136
|
```
|
|
127
137
|
|
|
128
|
-
## Four ways to run it
|
|
138
|
+
## Four ways to run it, each with every feature
|
|
129
139
|
|
|
130
|
-
|
|
|
140
|
+
| Part | Where | Best for |
|
|
131
141
|
|---|---|---|
|
|
132
|
-
| **
|
|
133
|
-
| **
|
|
134
|
-
| **
|
|
135
|
-
| **MCP server for AI agents** | `pip install "hea-bench[mcp]"`, then `hea-bench-mcp` |
|
|
136
|
-
|
|
137
|
-
|
|
142
|
+
| **Web app** | <https://dfieser.github.io/hea-bench/> | anyone, no install |
|
|
143
|
+
| **Desktop app** | one portable `.exe`, [download (no install)](https://github.com/dfieser/hea-bench/releases/latest/download/HEA-Bench.exe), the same app in its own window, engine inside, works offline | Windows users who want it local |
|
|
144
|
+
| **Python library + CLI** | `pip install "hea-bench[all]"` | scripts and notebooks |
|
|
145
|
+
| **MCP server for AI agents** | `pip install "hea-bench[mcp]"`, then `hea-bench-mcp` | Claude, Cursor and other MCP clients, as 24 tools |
|
|
146
|
+
|
|
147
|
+
Every feature is in all four parts, so pick whichever suits you and you
|
|
148
|
+
lose nothing. That is a standing project rule, and CI enforces it:
|
|
149
|
+
`tests/test_feature_parity.py` fails whenever a public feature lacks
|
|
150
|
+
its library function, its MCP tool or a working app surface, a headless
|
|
151
|
+
browser uses every tab of the built site, the built desktop exe goes
|
|
152
|
+
through the same steps before it is attached to a release, and a
|
|
153
|
+
freshly installed wheel answers every MCP tool. `pip install
|
|
154
|
+
hea-bench` alone has no dependencies and covers everything except the
|
|
155
|
+
fitted models and the MCP server; the `[all]` extra adds scikit-learn
|
|
156
|
+
and the MCP SDK for those.
|
|
157
|
+
|
|
158
|
+
All four share **one calculation core**. The browser/desktop
|
|
138
159
|
core (`web/hea-calculator-core.js`) is a pure-JS port of the Python
|
|
139
160
|
library, and `tests/test_web_parity.py` guarantees the two match on all
|
|
140
161
|
1484 binary pairs and the canonical multi-element fixtures, while
|
|
@@ -143,10 +164,7 @@ down to identical warning messages. The app's Dataset, Design and
|
|
|
143
164
|
Benchmark tabs and its predictions panel run the Python package itself,
|
|
144
165
|
unchanged, inside the page (Pyodide, `web/hea-engine-worker.js`), and
|
|
145
166
|
`tests/test_web_engine.py` checks that it returns exactly what CPython
|
|
146
|
-
returns.
|
|
147
|
-
feature has no working app surface, so the app never falls behind the
|
|
148
|
-
library, and before every release a headless browser uses every tab of
|
|
149
|
-
the built site the way a person would.
|
|
167
|
+
returns.
|
|
150
168
|
|
|
151
169
|
## Quick start (Python)
|
|
152
170
|
|
|
@@ -260,18 +278,22 @@ ceramics datasets: [docs/ceramics.md](docs/ceramics.md).
|
|
|
260
278
|
## Quick start (AI agents, MCP)
|
|
261
279
|
|
|
262
280
|
LLM agents hallucinate descriptor values; this server grounds them.
|
|
263
|
-
`hea_bench.mcp_server` exposes the
|
|
264
|
-
[Model Context Protocol](https://modelcontextprotocol.io/) as
|
|
265
|
-
deterministic tools
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
`
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
281
|
+
`hea_bench.mcp_server` exposes every feature of the package over the
|
|
282
|
+
[Model Context Protocol](https://modelcontextprotocol.io/) as 24
|
|
283
|
+
deterministic tools. The calculator: `parse_composition`, batch
|
|
284
|
+
`alloy_descriptors` (with the Miedema enthalpies) and `alloy_rules`,
|
|
285
|
+
both taking custom elements and pair values, `omega_sensitivity`,
|
|
286
|
+
`oxide_report`, `ceramic_report`, `element_data` and
|
|
287
|
+
`element_coverage`. The dataset: `corpus_build` (once, to build the
|
|
288
|
+
corpus locally), `corpus_query`, `corpus_describe`, `corpus_export` and
|
|
289
|
+
`measured_properties`. Predictions: `predict_properties` with
|
|
290
|
+
intervals and `predict_phase_set` with prediction sets, both carrying
|
|
291
|
+
the domain flag, and `check_applicability`. Design:
|
|
292
|
+
`design_search`, with hard caps on palette, step and candidate count,
|
|
293
|
+
and `campaign_suggest`, on a campaign file or an inline campaign. The
|
|
294
|
+
benchmark: `benchmark_summary`, `benchmark_run`, `benchmark_folds`,
|
|
295
|
+
`benchmark_score` and `coverage_study`. And `about`. Every response
|
|
296
|
+
carries units or uncertainty fields, citation keys
|
|
275
297
|
where a parametrization is involved, and the library version, so an
|
|
276
298
|
agent's reasoning trace contains auditable receipts rather than bare
|
|
277
299
|
floats; `about()` reports which capabilities are available in the
|
|
@@ -358,10 +380,13 @@ Li et al., *Commun. Mater.* **6**:9 (2025),
|
|
|
358
380
|
Baselines, split digests, and full provenance:
|
|
359
381
|
[`docs/benchmark-baselines.md`](./docs/benchmark-baselines.md).
|
|
360
382
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
383
|
+
The corpus is built on your machine, once, because its largest source
|
|
384
|
+
dataset declares no license and is never redistributed (see
|
|
385
|
+
[`data/raw/README.md`](./data/raw/README.md)).
|
|
386
|
+
`hea_bench.corpus.build_corpus()` downloads that file from its authors'
|
|
387
|
+
repository, accepts it only if its pinned SHA-256 matches, and builds
|
|
388
|
+
every corpus version. The apps and the MCP server's `corpus_build` tool
|
|
389
|
+
do the same.
|
|
365
390
|
|
|
366
391
|
## The corpus as a standalone product
|
|
367
392
|
|
|
@@ -371,7 +396,7 @@ addressable directly, with no task or split machinery involved:
|
|
|
371
396
|
```python
|
|
372
397
|
from hea_bench.corpus import load_corpus
|
|
373
398
|
|
|
374
|
-
corpus = load_corpus() # v0.
|
|
399
|
+
corpus = load_corpus() # v0.2.0 (10,290 alloys), every row, full provenance
|
|
375
400
|
corpus.describe() # counts, families, agreement rate
|
|
376
401
|
al_bcc = corpus.query(contains=["Al"], phase="BCC", descriptor_ready=True)
|
|
377
402
|
al_bcc.rows[0].raw_labels # each source's verbatim reported phase
|
|
@@ -383,8 +408,11 @@ processing route and primary-literature DOI where available, and
|
|
|
383
408
|
upstream record identifiers, so a label can be audited without leaving
|
|
384
409
|
the package. Provenance chains, per-source license status,
|
|
385
410
|
harmonization rules, and known limitations are documented in the
|
|
386
|
-
[corpus card](docs/corpus-card.md).
|
|
387
|
-
|
|
411
|
+
[corpus card](docs/corpus-card.md). `load_corpus()` opens the largest
|
|
412
|
+
version, v0.2.0, which adds the LLM-extracted Chizhevskiy database.
|
|
413
|
+
`load_corpus(version="0.1.0")` is the hand-curated reference (7,783
|
|
414
|
+
alloys) that the benchmark, the phase predictions and the domain flag
|
|
415
|
+
always use, so every published number stays put.
|
|
388
416
|
|
|
389
417
|
## Uncertainty and domain of applicability
|
|
390
418
|
|
|
@@ -398,7 +426,7 @@ guarantee's exchangeability assumption plausibly holds for your query:
|
|
|
398
426
|
from hea_bench.corpus import load_corpus
|
|
399
427
|
from hea_bench.uncertainty import ConformalClassifier, fit_domain
|
|
400
428
|
|
|
401
|
-
domain = fit_domain(load_corpus())
|
|
429
|
+
domain = fit_domain(load_corpus(version="0.1.0"))
|
|
402
430
|
domain.novelty({"Hf": 0.2, "Nb": 0.2, "Ta": 0.2, "Ti": 0.2, "Zr": 0.2})
|
|
403
431
|
# {'element_set_seen': True, 'family_count': ..., 'nearest_family_distance': 0.0,
|
|
404
432
|
# 'descriptor_distance': ..., 'element_coverage': True, 'in_domain': True, ...}
|
|
@@ -517,11 +545,18 @@ the number does not, so read Ω qualitatively in that regime.
|
|
|
517
545
|
hea-bench/
|
|
518
546
|
├── src/hea_bench/
|
|
519
547
|
│ ├── descriptors/ ΔS_mix, δ, VEC, T_m, ΔH_mix, Ω, S_E, φ + data tables
|
|
520
|
-
│ ├── rules/ the
|
|
548
|
+
│ ├── rules/ the nine empirical phase-prediction rules
|
|
521
549
|
│ ├── oxides/ HEO module: families, oxidation-state solver,
|
|
522
550
|
│ │ Shannon radii (94 elements, vendored from pymatgen)
|
|
551
|
+
│ ├── ceramics/ carbides, nitrides, diborides
|
|
552
|
+
│ ├── corpus/ the experimental corpus: build_corpus, load_corpus
|
|
523
553
|
│ ├── benchmark/ frozen family-grouped + random paired splits and evaluation
|
|
524
|
-
│
|
|
554
|
+
│ ├── properties/ density, melting point, cost, hardness
|
|
555
|
+
│ ├── uncertainty/ conformal sets and intervals, phase sets, domain flag
|
|
556
|
+
│ ├── design/ composition search and campaigns
|
|
557
|
+
│ ├── mcp_server.py the MCP server (hea-bench-mcp)
|
|
558
|
+
│ ├── webapp.py the bridge the in-page engine calls
|
|
559
|
+
│ ├── custom.py custom elements and pair values
|
|
525
560
|
│ ├── composition.py formula parser, normalizer
|
|
526
561
|
│ ├── constants.py R = 8.314
|
|
527
562
|
│ └── cli.py command-line entry point
|
|
@@ -52,10 +52,13 @@ For any composition it reports:
|
|
|
52
52
|
Yang–Zhang Ω, Pauling electronegativity mismatch Δχ, Mansoori excess
|
|
53
53
|
entropy S<sub>E</sub>, ΔG<sub>ss</sub>, ΔG<sub>max</sub>, King Φ, Ye φ.
|
|
54
54
|
- **Phase-prediction rules:** Yeh entropy, Zhang δ, Guo–Liu VEC,
|
|
55
|
-
Yang–Zhang Ω, King Φ, Ye
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
structural, and
|
|
55
|
+
Yang–Zhang Ω, King Φ, Ye φ, Senkov–Miracle κ, the Tsai σ-phase
|
|
56
|
+
window and Sheikh ductility.
|
|
57
|
+
- **Miedema formation enthalpies:** compound / solid-solution /
|
|
58
|
+
amorphous, decomposed into chemical, elastic, structural, and
|
|
59
|
+
topological terms.
|
|
60
|
+
- **Your own elements and pair values:** any descriptor or rule, for a
|
|
61
|
+
composition with an element or pair enthalpy that is not tabulated.
|
|
59
62
|
- **High-entropy oxides** (`hea_bench.oxides` + the apps' Oxides mode):
|
|
60
63
|
rock-salt, perovskite, fluorite, and pyrochlore formability
|
|
61
64
|
descriptors over Shannon ionic radii with automatic charge-balance
|
|
@@ -87,16 +90,27 @@ flowchart LR
|
|
|
87
90
|
D --> E
|
|
88
91
|
```
|
|
89
92
|
|
|
90
|
-
## Four ways to run it
|
|
93
|
+
## Four ways to run it, each with every feature
|
|
91
94
|
|
|
92
|
-
|
|
|
95
|
+
| Part | Where | Best for |
|
|
93
96
|
|---|---|---|
|
|
94
|
-
| **
|
|
95
|
-
| **
|
|
96
|
-
| **
|
|
97
|
-
| **MCP server for AI agents** | `pip install "hea-bench[mcp]"`, then `hea-bench-mcp` |
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
| **Web app** | <https://dfieser.github.io/hea-bench/> | anyone, no install |
|
|
98
|
+
| **Desktop app** | one portable `.exe`, [download (no install)](https://github.com/dfieser/hea-bench/releases/latest/download/HEA-Bench.exe), the same app in its own window, engine inside, works offline | Windows users who want it local |
|
|
99
|
+
| **Python library + CLI** | `pip install "hea-bench[all]"` | scripts and notebooks |
|
|
100
|
+
| **MCP server for AI agents** | `pip install "hea-bench[mcp]"`, then `hea-bench-mcp` | Claude, Cursor and other MCP clients, as 24 tools |
|
|
101
|
+
|
|
102
|
+
Every feature is in all four parts, so pick whichever suits you and you
|
|
103
|
+
lose nothing. That is a standing project rule, and CI enforces it:
|
|
104
|
+
`tests/test_feature_parity.py` fails whenever a public feature lacks
|
|
105
|
+
its library function, its MCP tool or a working app surface, a headless
|
|
106
|
+
browser uses every tab of the built site, the built desktop exe goes
|
|
107
|
+
through the same steps before it is attached to a release, and a
|
|
108
|
+
freshly installed wheel answers every MCP tool. `pip install
|
|
109
|
+
hea-bench` alone has no dependencies and covers everything except the
|
|
110
|
+
fitted models and the MCP server; the `[all]` extra adds scikit-learn
|
|
111
|
+
and the MCP SDK for those.
|
|
112
|
+
|
|
113
|
+
All four share **one calculation core**. The browser/desktop
|
|
100
114
|
core (`web/hea-calculator-core.js`) is a pure-JS port of the Python
|
|
101
115
|
library, and `tests/test_web_parity.py` guarantees the two match on all
|
|
102
116
|
1484 binary pairs and the canonical multi-element fixtures, while
|
|
@@ -105,10 +119,7 @@ down to identical warning messages. The app's Dataset, Design and
|
|
|
105
119
|
Benchmark tabs and its predictions panel run the Python package itself,
|
|
106
120
|
unchanged, inside the page (Pyodide, `web/hea-engine-worker.js`), and
|
|
107
121
|
`tests/test_web_engine.py` checks that it returns exactly what CPython
|
|
108
|
-
returns.
|
|
109
|
-
feature has no working app surface, so the app never falls behind the
|
|
110
|
-
library, and before every release a headless browser uses every tab of
|
|
111
|
-
the built site the way a person would.
|
|
122
|
+
returns.
|
|
112
123
|
|
|
113
124
|
## Quick start (Python)
|
|
114
125
|
|
|
@@ -222,18 +233,22 @@ ceramics datasets: [docs/ceramics.md](docs/ceramics.md).
|
|
|
222
233
|
## Quick start (AI agents, MCP)
|
|
223
234
|
|
|
224
235
|
LLM agents hallucinate descriptor values; this server grounds them.
|
|
225
|
-
`hea_bench.mcp_server` exposes the
|
|
226
|
-
[Model Context Protocol](https://modelcontextprotocol.io/) as
|
|
227
|
-
deterministic tools
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
`
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
236
|
+
`hea_bench.mcp_server` exposes every feature of the package over the
|
|
237
|
+
[Model Context Protocol](https://modelcontextprotocol.io/) as 24
|
|
238
|
+
deterministic tools. The calculator: `parse_composition`, batch
|
|
239
|
+
`alloy_descriptors` (with the Miedema enthalpies) and `alloy_rules`,
|
|
240
|
+
both taking custom elements and pair values, `omega_sensitivity`,
|
|
241
|
+
`oxide_report`, `ceramic_report`, `element_data` and
|
|
242
|
+
`element_coverage`. The dataset: `corpus_build` (once, to build the
|
|
243
|
+
corpus locally), `corpus_query`, `corpus_describe`, `corpus_export` and
|
|
244
|
+
`measured_properties`. Predictions: `predict_properties` with
|
|
245
|
+
intervals and `predict_phase_set` with prediction sets, both carrying
|
|
246
|
+
the domain flag, and `check_applicability`. Design:
|
|
247
|
+
`design_search`, with hard caps on palette, step and candidate count,
|
|
248
|
+
and `campaign_suggest`, on a campaign file or an inline campaign. The
|
|
249
|
+
benchmark: `benchmark_summary`, `benchmark_run`, `benchmark_folds`,
|
|
250
|
+
`benchmark_score` and `coverage_study`. And `about`. Every response
|
|
251
|
+
carries units or uncertainty fields, citation keys
|
|
237
252
|
where a parametrization is involved, and the library version, so an
|
|
238
253
|
agent's reasoning trace contains auditable receipts rather than bare
|
|
239
254
|
floats; `about()` reports which capabilities are available in the
|
|
@@ -320,10 +335,13 @@ Li et al., *Commun. Mater.* **6**:9 (2025),
|
|
|
320
335
|
Baselines, split digests, and full provenance:
|
|
321
336
|
[`docs/benchmark-baselines.md`](./docs/benchmark-baselines.md).
|
|
322
337
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
338
|
+
The corpus is built on your machine, once, because its largest source
|
|
339
|
+
dataset declares no license and is never redistributed (see
|
|
340
|
+
[`data/raw/README.md`](./data/raw/README.md)).
|
|
341
|
+
`hea_bench.corpus.build_corpus()` downloads that file from its authors'
|
|
342
|
+
repository, accepts it only if its pinned SHA-256 matches, and builds
|
|
343
|
+
every corpus version. The apps and the MCP server's `corpus_build` tool
|
|
344
|
+
do the same.
|
|
327
345
|
|
|
328
346
|
## The corpus as a standalone product
|
|
329
347
|
|
|
@@ -333,7 +351,7 @@ addressable directly, with no task or split machinery involved:
|
|
|
333
351
|
```python
|
|
334
352
|
from hea_bench.corpus import load_corpus
|
|
335
353
|
|
|
336
|
-
corpus = load_corpus() # v0.
|
|
354
|
+
corpus = load_corpus() # v0.2.0 (10,290 alloys), every row, full provenance
|
|
337
355
|
corpus.describe() # counts, families, agreement rate
|
|
338
356
|
al_bcc = corpus.query(contains=["Al"], phase="BCC", descriptor_ready=True)
|
|
339
357
|
al_bcc.rows[0].raw_labels # each source's verbatim reported phase
|
|
@@ -345,8 +363,11 @@ processing route and primary-literature DOI where available, and
|
|
|
345
363
|
upstream record identifiers, so a label can be audited without leaving
|
|
346
364
|
the package. Provenance chains, per-source license status,
|
|
347
365
|
harmonization rules, and known limitations are documented in the
|
|
348
|
-
[corpus card](docs/corpus-card.md).
|
|
349
|
-
|
|
366
|
+
[corpus card](docs/corpus-card.md). `load_corpus()` opens the largest
|
|
367
|
+
version, v0.2.0, which adds the LLM-extracted Chizhevskiy database.
|
|
368
|
+
`load_corpus(version="0.1.0")` is the hand-curated reference (7,783
|
|
369
|
+
alloys) that the benchmark, the phase predictions and the domain flag
|
|
370
|
+
always use, so every published number stays put.
|
|
350
371
|
|
|
351
372
|
## Uncertainty and domain of applicability
|
|
352
373
|
|
|
@@ -360,7 +381,7 @@ guarantee's exchangeability assumption plausibly holds for your query:
|
|
|
360
381
|
from hea_bench.corpus import load_corpus
|
|
361
382
|
from hea_bench.uncertainty import ConformalClassifier, fit_domain
|
|
362
383
|
|
|
363
|
-
domain = fit_domain(load_corpus())
|
|
384
|
+
domain = fit_domain(load_corpus(version="0.1.0"))
|
|
364
385
|
domain.novelty({"Hf": 0.2, "Nb": 0.2, "Ta": 0.2, "Ti": 0.2, "Zr": 0.2})
|
|
365
386
|
# {'element_set_seen': True, 'family_count': ..., 'nearest_family_distance': 0.0,
|
|
366
387
|
# 'descriptor_distance': ..., 'element_coverage': True, 'in_domain': True, ...}
|
|
@@ -479,11 +500,18 @@ the number does not, so read Ω qualitatively in that regime.
|
|
|
479
500
|
hea-bench/
|
|
480
501
|
├── src/hea_bench/
|
|
481
502
|
│ ├── descriptors/ ΔS_mix, δ, VEC, T_m, ΔH_mix, Ω, S_E, φ + data tables
|
|
482
|
-
│ ├── rules/ the
|
|
503
|
+
│ ├── rules/ the nine empirical phase-prediction rules
|
|
483
504
|
│ ├── oxides/ HEO module: families, oxidation-state solver,
|
|
484
505
|
│ │ Shannon radii (94 elements, vendored from pymatgen)
|
|
506
|
+
│ ├── ceramics/ carbides, nitrides, diborides
|
|
507
|
+
│ ├── corpus/ the experimental corpus: build_corpus, load_corpus
|
|
485
508
|
│ ├── benchmark/ frozen family-grouped + random paired splits and evaluation
|
|
486
|
-
│
|
|
509
|
+
│ ├── properties/ density, melting point, cost, hardness
|
|
510
|
+
│ ├── uncertainty/ conformal sets and intervals, phase sets, domain flag
|
|
511
|
+
│ ├── design/ composition search and campaigns
|
|
512
|
+
│ ├── mcp_server.py the MCP server (hea-bench-mcp)
|
|
513
|
+
│ ├── webapp.py the bridge the in-page engine calls
|
|
514
|
+
│ ├── custom.py custom elements and pair values
|
|
487
515
|
│ ├── composition.py formula parser, normalizer
|
|
488
516
|
│ ├── constants.py R = 8.314
|
|
489
517
|
│ └── cli.py command-line entry point
|
|
@@ -36,7 +36,7 @@ date and neither repository declared a license.
|
|
|
36
36
|
| [`borg2020/`](borg2020/) | Borg *et al.* 2020 (*Sci. Data* 7, 430) | **CC-BY-4.0** (figshare deposit explicitly licensed) | ✓ **Mirrored 2026-05-20.** 1,545 measurement rows / 740 unique (formula, processing) alloys / 23 columns including phase, processing, mechanical properties, and per-row source DOI. The canonical backbone of the benchmark. |
|
|
37
37
|
| [`pei2020/`](pei2020/) | Pei *et al.* 2020 (*npj Comput. Mater.* 6, 50) | **CC-BY-4.0** (Crossref-confirmed, `tdm` and `vor`, zero delay) | ✓ **Mirrored 2026-05-20.** 1,252 rows, 2 columns (Alloy, Phase), four phase labels (bcc/fcc/hcp/multi-phase). 1,208 unique formulas load after deduplicating 43 repeated formulas and rejecting the malformed `Ta_Th` entry at row 1251. |
|
|
38
38
|
| [`peivaste/`](peivaste/) | Iman-Peivaste/ML_HEAs_Phase_Dataset (GitHub) + companion Sci. Rep. 13, 22556 (2023) by same authors | **None.** No LICENSE file on the data repository, re-confirmed 2026-08-10. The *Sci. Rep.* article is CC-BY, the GitHub dataset is not covered by it. | **Pointer-only.** `fetch.py` provided, CSV gitignored. Largest single contributor to the corpus, which is why the corpus as a whole cannot be redistributed. |
|
|
39
|
-
| [`chizhevskiy2026/`](chizhevskiy2026/) | Chizhevskiy *et al.* 2026 (*Sci. Data* 13, 612), repo Vladimirchizh/hea_database | **CC-BY-4.0**, resolved 2026-08-10: the maintainer merged [hea_database#2](https://github.com/Vladimirchizh/hea_database/pull/2) adding a LICENSE file (GitHub license detection confirms CC-BY-4.0). | ✓ **Mirrored 2026-08-10**, byte-identical to upstream at the pinned SHA-256. 12,427 LLM-extracted records, 2,974 unique
|
|
39
|
+
| [`chizhevskiy2026/`](chizhevskiy2026/) | Chizhevskiy *et al.* 2026 (*Sci. Data* 13, 612), repo Vladimirchizh/hea_database | **CC-BY-4.0**, resolved 2026-08-10: the maintainer merged [hea_database#2](https://github.com/Vladimirchizh/hea_database/pull/2) adding a LICENSE file (GitHub license detection confirms CC-BY-4.0). | ✓ **Mirrored 2026-08-10**, byte-identical to upstream at the pinned SHA-256. 12,427 LLM-extracted records, 2,974 unique alloys in plain formulas (rows in group notation stay out, because v0.2.0 is frozen). Feeds corpus **v0.2.0 only**; v0.1.0 is frozen without it. Its labels agree with the v0.1.0 consensus on only ~70% of overlapping alloys, so disagreements are quarantined as conflicts. Browsing opens on v0.2.0 since 2.7.0, and v0.1.0 stays the reference corpus for the benchmark, the phase predictions and the domain flag. |
|
|
40
40
|
| [`couzinie2018/`](couzinie2018/) | Couzinié *et al.* 2018 (*Data in Brief* 21, 1622) | CC-BY-4.0 | Acquisition stalled. Elsevier CDN supplementary files are mis-attributed, and the content is mostly subsumed by Borg anyway. **Deprioritized.** See README for log. |
|
|
41
41
|
| (planned) `miracle_senkov2017/` | Miracle & Senkov 2017 (*Acta Mater.* 122, 448) | Elsevier, to be determined | Not yet attempted |
|
|
42
42
|
| (planned) `witman/` | mwitman1/HEAphaseML (GitHub) | To be determined | Not yet attempted |
|