gliquid 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.
- gliquid-0.1.0/.github/CODEOWNERS +2 -0
- gliquid-0.1.0/.github/dependabot.yml +27 -0
- gliquid-0.1.0/.github/workflows/release.yml +128 -0
- gliquid-0.1.0/.github/workflows/tests.yml +125 -0
- gliquid-0.1.0/.gitignore +47 -0
- gliquid-0.1.0/CHANGELOG.md +90 -0
- gliquid-0.1.0/CITATION.cff +42 -0
- gliquid-0.1.0/CONTRIBUTING.md +130 -0
- gliquid-0.1.0/LICENSE +21 -0
- gliquid-0.1.0/PKG-INFO +352 -0
- gliquid-0.1.0/README.md +295 -0
- gliquid-0.1.0/assets/digitized_pd_anatomy.png +0 -0
- gliquid-0.1.0/assets/gliq_logo_tall.png +0 -0
- gliquid-0.1.0/assets/invariant_points_and_reactions.png +0 -0
- gliquid-0.1.0/notebooks/GaRu_adjustment.ipynb +5526 -0
- gliquid-0.1.0/notebooks/PbTb_adjustment.ipynb +5565 -0
- gliquid-0.1.0/notebooks/colab_demo.ipynb +164 -0
- gliquid-0.1.0/notebooks/fitting_demo.ipynb +20010 -0
- gliquid-0.1.0/notebooks/interpolation_demo.ipynb +251 -0
- gliquid-0.1.0/pyproject.toml +208 -0
- gliquid-0.1.0/requirements/min-constraints.txt +34 -0
- gliquid-0.1.0/scripts/run_notebooks.py +217 -0
- gliquid-0.1.0/src/gliquid/__init__.py +72 -0
- gliquid-0.1.0/src/gliquid/_version.py +24 -0
- gliquid-0.1.0/src/gliquid/api.py +828 -0
- gliquid-0.1.0/src/gliquid/binary.py +2520 -0
- gliquid-0.1.0/src/gliquid/config.py +316 -0
- gliquid-0.1.0/src/gliquid/data/omegas_hcp.json +36 -0
- gliquid-0.1.0/src/gliquid/data/phase_transitions.json +9748 -0
- gliquid-0.1.0/src/gliquid/data/spurious_structures.json +173 -0
- gliquid-0.1.0/src/gliquid/hsx.py +423 -0
- gliquid-0.1.0/src/gliquid/hull_editor.py +1176 -0
- gliquid-0.1.0/src/gliquid/mpds.py +1897 -0
- gliquid-0.1.0/src/gliquid/phase.py +469 -0
- gliquid-0.1.0/src/gliquid/plotting/__init__.py +7 -0
- gliquid-0.1.0/src/gliquid/plotting/binary_figs.py +675 -0
- gliquid-0.1.0/src/gliquid/plotting/binary_tx.py +2613 -0
- gliquid-0.1.0/src/gliquid/plotting/export.py +141 -0
- gliquid-0.1.0/src/gliquid/plotting/style.py +99 -0
- gliquid-0.1.0/src/gliquid/plotting/ternary_surface.py +369 -0
- gliquid-0.1.0/src/gliquid/production_model_runner.py +609 -0
- gliquid-0.1.0/src/gliquid/shap_compat.py +200 -0
- gliquid-0.1.0/src/gliquid/solution.py +1547 -0
- gliquid-0.1.0/src/gliquid/ternary.py +1039 -0
- gliquid-0.1.0/tox.ini +138 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Keep Python dependencies up to date
|
|
4
|
+
- package-ecosystem: "pip"
|
|
5
|
+
directory: "/"
|
|
6
|
+
schedule:
|
|
7
|
+
interval: "weekly"
|
|
8
|
+
day: "monday"
|
|
9
|
+
open-pull-requests-limit: 5
|
|
10
|
+
reviewers:
|
|
11
|
+
- "willwerj"
|
|
12
|
+
ignore:
|
|
13
|
+
# These are tightly pinned for compatibility — update manually
|
|
14
|
+
- dependency-name: "scikit-learn"
|
|
15
|
+
update-types: ["version-update:semver-major", "version-update:semver-minor"]
|
|
16
|
+
- dependency-name: "xgboost"
|
|
17
|
+
update-types: ["version-update:semver-major", "version-update:semver-minor"]
|
|
18
|
+
- dependency-name: "emmet-core"
|
|
19
|
+
update-types: ["version-update:semver-major", "version-update:semver-minor"]
|
|
20
|
+
|
|
21
|
+
# Keep GitHub Actions up to date
|
|
22
|
+
- package-ecosystem: "github-actions"
|
|
23
|
+
directory: "/"
|
|
24
|
+
schedule:
|
|
25
|
+
interval: "monthly"
|
|
26
|
+
reviewers:
|
|
27
|
+
- "willwerj"
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Tagging IS the release. hatch-vcs derives the distribution version from the tag, so there
|
|
4
|
+
# is no version literal to bump in src/ -- see the release checklist in CONTRIBUTING.md.
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
tags: ['v*']
|
|
8
|
+
|
|
9
|
+
# No API token appears anywhere in this file, by design. Both publish jobs use PyPI Trusted
|
|
10
|
+
# Publishing (OIDC): GitHub mints a short-lived identity token at job runtime from
|
|
11
|
+
# `permissions: id-token: write`, and the index trusts this repository + workflow + GitHub
|
|
12
|
+
# environment. The token-based alternative (a stored __token__ password) is deliberately not
|
|
13
|
+
# used -- a leaked long-lived token is exactly what Trusted Publishing removes.
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
name: Build sdist and wheel
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
with:
|
|
25
|
+
# NOT optional, and the single most dangerous thing to get wrong in this file.
|
|
26
|
+
# hatch-vcs reads the version from git tags; the default shallow clone has none.
|
|
27
|
+
# The build would NOT fail -- it would silently emit the pyproject
|
|
28
|
+
# fallback-version (0.0.0) and publish it. That fallback is 0.0.0 rather than the
|
|
29
|
+
# release version precisely so this failure is visible in the artifact name.
|
|
30
|
+
fetch-depth: 0
|
|
31
|
+
|
|
32
|
+
- name: Set up Python
|
|
33
|
+
uses: actions/setup-python@v5
|
|
34
|
+
with:
|
|
35
|
+
python-version: "3.12"
|
|
36
|
+
|
|
37
|
+
- name: Install build tooling
|
|
38
|
+
run: |
|
|
39
|
+
python -m pip install --upgrade pip
|
|
40
|
+
pip install build twine
|
|
41
|
+
|
|
42
|
+
- name: Build
|
|
43
|
+
run: python -m build
|
|
44
|
+
|
|
45
|
+
- name: Check metadata
|
|
46
|
+
run: twine check dist/*
|
|
47
|
+
|
|
48
|
+
- name: Show built version
|
|
49
|
+
# Cheap tripwire for the fetch-depth failure above: a 0.0.0 filename here means the
|
|
50
|
+
# tag was not visible to hatch-vcs, and nothing downstream should be released.
|
|
51
|
+
run: ls -l dist/
|
|
52
|
+
|
|
53
|
+
- name: Upload distributions
|
|
54
|
+
uses: actions/upload-artifact@v4
|
|
55
|
+
with:
|
|
56
|
+
name: dist
|
|
57
|
+
path: dist/
|
|
58
|
+
if-no-files-found: error
|
|
59
|
+
|
|
60
|
+
testpypi:
|
|
61
|
+
name: Publish to TestPyPI
|
|
62
|
+
needs: [build]
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
environment: testpypi
|
|
65
|
+
permissions:
|
|
66
|
+
id-token: write # OIDC identity for Trusted Publishing; see the note at the top
|
|
67
|
+
|
|
68
|
+
steps:
|
|
69
|
+
- name: Download distributions
|
|
70
|
+
uses: actions/download-artifact@v4
|
|
71
|
+
with:
|
|
72
|
+
name: dist
|
|
73
|
+
path: dist/
|
|
74
|
+
|
|
75
|
+
- name: Publish to TestPyPI
|
|
76
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
77
|
+
with:
|
|
78
|
+
repository-url: https://test.pypi.org/legacy/
|
|
79
|
+
|
|
80
|
+
pypi:
|
|
81
|
+
name: Publish to PyPI
|
|
82
|
+
needs: [testpypi]
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
|
|
85
|
+
# LOAD-BEARING, NOT DECORATION. The `pypi` GitHub environment carries a
|
|
86
|
+
# required-reviewer protection rule, configured in the repository settings UI and not
|
|
87
|
+
# expressible in this file. That rule is the entire reason "TestPyPI first, then PyPI"
|
|
88
|
+
# is real rather than aspirational: the run pauses here until a maintainer has looked at
|
|
89
|
+
# what TestPyPI accepted and approves the deployment. Removing this line -- or deleting
|
|
90
|
+
# the environment because it "looks empty" -- turns an irreversible publish into an
|
|
91
|
+
# unattended one. PyPI cannot un-publish a version.
|
|
92
|
+
environment: pypi
|
|
93
|
+
permissions:
|
|
94
|
+
id-token: write # OIDC identity for Trusted Publishing; see the note at the top
|
|
95
|
+
|
|
96
|
+
steps:
|
|
97
|
+
- name: Download distributions
|
|
98
|
+
uses: actions/download-artifact@v4
|
|
99
|
+
with:
|
|
100
|
+
name: dist
|
|
101
|
+
path: dist/
|
|
102
|
+
|
|
103
|
+
- name: Publish to PyPI
|
|
104
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
105
|
+
|
|
106
|
+
github-release:
|
|
107
|
+
name: Create GitHub release
|
|
108
|
+
needs: [pypi]
|
|
109
|
+
runs-on: ubuntu-latest
|
|
110
|
+
permissions:
|
|
111
|
+
contents: write # required to create the release
|
|
112
|
+
|
|
113
|
+
steps:
|
|
114
|
+
- uses: actions/checkout@v4
|
|
115
|
+
with:
|
|
116
|
+
fetch-depth: 0 # see the note on the build job
|
|
117
|
+
|
|
118
|
+
- name: Download distributions
|
|
119
|
+
uses: actions/download-artifact@v4
|
|
120
|
+
with:
|
|
121
|
+
name: dist
|
|
122
|
+
path: dist/
|
|
123
|
+
|
|
124
|
+
- name: Create release and attach artifacts
|
|
125
|
+
env:
|
|
126
|
+
# The automatic, job-scoped GitHub Actions token -- not a stored credential.
|
|
127
|
+
GH_TOKEN: ${{ github.token }}
|
|
128
|
+
run: gh release create "$GITHUB_REF_NAME" dist/* --title "$GITHUB_REF_NAME" --generate-notes
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
name: Run Tests
|
|
2
|
+
|
|
3
|
+
# Every branch, not just main. This workflow previously triggered on main only, while the
|
|
4
|
+
# code being released lived ~90 commits ahead of it -- so it had never actually run against
|
|
5
|
+
# the package it guards.
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: ['**']
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [main]
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test-cached:
|
|
14
|
+
name: Cached Tests (Python ${{ matrix.python-version }})
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
strategy:
|
|
18
|
+
# One version failing must not hide the state of the other three.
|
|
19
|
+
fail-fast: false
|
|
20
|
+
matrix:
|
|
21
|
+
# Mirrors requires-python = ">=3.10,<3.14" and the tox compat matrix.
|
|
22
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
23
|
+
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
with:
|
|
27
|
+
# NOT optional. hatch-vcs derives the version from the git tag, and the default
|
|
28
|
+
# shallow clone fetches none. Getting this wrong does not fail the checkout -- it
|
|
29
|
+
# silently produces the pyproject fallback-version (0.0.0), which is why that
|
|
30
|
+
# fallback is deliberately not the release version.
|
|
31
|
+
fetch-depth: 0
|
|
32
|
+
|
|
33
|
+
- name: Set up Python
|
|
34
|
+
uses: actions/setup-python@v5
|
|
35
|
+
with:
|
|
36
|
+
python-version: ${{ matrix.python-version }}
|
|
37
|
+
|
|
38
|
+
- name: Cache pip dependencies
|
|
39
|
+
uses: actions/cache@v4
|
|
40
|
+
with:
|
|
41
|
+
path: ~/.cache/pip
|
|
42
|
+
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }}
|
|
43
|
+
restore-keys: |
|
|
44
|
+
${{ runner.os }}-pip-${{ matrix.python-version }}-
|
|
45
|
+
${{ runner.os }}-pip-
|
|
46
|
+
|
|
47
|
+
- name: Install package and test extra
|
|
48
|
+
# Install the declared extra rather than a bare `pip install pytest`, so CI
|
|
49
|
+
# exercises the same dependency set a contributor gets from CONTRIBUTING.md.
|
|
50
|
+
run: |
|
|
51
|
+
python -m pip install --upgrade pip
|
|
52
|
+
pip install -e '.[test]'
|
|
53
|
+
|
|
54
|
+
- name: Run cached tests
|
|
55
|
+
# CI is where the maintainer tier belongs, so both tiers run. The live Materials
|
|
56
|
+
# Project fetch is deselected by MARKER, not by path: test_dft_data_loading.py moved
|
|
57
|
+
# to tests_internal/ and carries `needs_network`, and the API job below runs it.
|
|
58
|
+
run: pytest tests tests_internal -v --tb=short -m "not needs_network"
|
|
59
|
+
|
|
60
|
+
test-api:
|
|
61
|
+
name: API Tests
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
needs: test-cached
|
|
64
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
65
|
+
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v4
|
|
68
|
+
with:
|
|
69
|
+
fetch-depth: 0 # see the note on the cached job
|
|
70
|
+
|
|
71
|
+
- name: Set up Python
|
|
72
|
+
uses: actions/setup-python@v5
|
|
73
|
+
with:
|
|
74
|
+
python-version: "3.12"
|
|
75
|
+
|
|
76
|
+
- name: Cache pip dependencies
|
|
77
|
+
uses: actions/cache@v4
|
|
78
|
+
with:
|
|
79
|
+
path: ~/.cache/pip
|
|
80
|
+
key: ${{ runner.os }}-pip-3.12-${{ hashFiles('pyproject.toml') }}
|
|
81
|
+
restore-keys: |
|
|
82
|
+
${{ runner.os }}-pip-3.12-
|
|
83
|
+
${{ runner.os }}-pip-
|
|
84
|
+
|
|
85
|
+
- name: Install package and test extra
|
|
86
|
+
run: |
|
|
87
|
+
python -m pip install --upgrade pip
|
|
88
|
+
pip install -e '.[test]'
|
|
89
|
+
|
|
90
|
+
- name: Run API tests
|
|
91
|
+
env:
|
|
92
|
+
NEW_MP_API_KEY: ${{ secrets.NEW_MP_API_KEY }}
|
|
93
|
+
run: pytest tests_internal/test_dft_data_loading.py -v --tb=short
|
|
94
|
+
|
|
95
|
+
lint:
|
|
96
|
+
name: Lint and Format
|
|
97
|
+
runs-on: ubuntu-latest
|
|
98
|
+
|
|
99
|
+
# NON-BLOCKING ON PURPOSE, for one cycle. `ruff format` landed in spec 04 but
|
|
100
|
+
# `ruff check` still has a backlog of findings; failing every push on it would
|
|
101
|
+
# red-wall the repo before anyone could read the list. The job exists so the backlog
|
|
102
|
+
# is VISIBLE in the checks tab. Flip this to false (or just delete the line) once the
|
|
103
|
+
# backlog is burned down -- leaving it here permanently makes the job decorative.
|
|
104
|
+
continue-on-error: true
|
|
105
|
+
|
|
106
|
+
steps:
|
|
107
|
+
- uses: actions/checkout@v4
|
|
108
|
+
with:
|
|
109
|
+
fetch-depth: 0 # see the note on the cached job
|
|
110
|
+
|
|
111
|
+
- name: Set up Python
|
|
112
|
+
uses: actions/setup-python@v5
|
|
113
|
+
with:
|
|
114
|
+
python-version: "3.12"
|
|
115
|
+
|
|
116
|
+
- name: Install package and test extra
|
|
117
|
+
run: |
|
|
118
|
+
python -m pip install --upgrade pip
|
|
119
|
+
pip install -e '.[test]'
|
|
120
|
+
|
|
121
|
+
- name: Ruff lint
|
|
122
|
+
run: ruff check src/gliquid tests tests_internal
|
|
123
|
+
|
|
124
|
+
- name: Ruff format check
|
|
125
|
+
run: ruff format --check src/gliquid tests tests_internal
|
gliquid-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
notebooks/constraint_comparison.ipynb
|
|
2
|
+
notebooks/_executed/
|
|
3
|
+
|
|
4
|
+
# tox / compat testing
|
|
5
|
+
.tox/
|
|
6
|
+
compat-test-phase1.log
|
|
7
|
+
|
|
8
|
+
# Python build / cache / packaging artifacts
|
|
9
|
+
__pycache__/
|
|
10
|
+
*.py[cod]
|
|
11
|
+
build/
|
|
12
|
+
*.egg-info/
|
|
13
|
+
# Written by the hatch-vcs build hook from the git tag; regenerated on every build.
|
|
14
|
+
src/gliquid/_version.py
|
|
15
|
+
|
|
16
|
+
# Logs
|
|
17
|
+
*.log
|
|
18
|
+
|
|
19
|
+
# Reagent knowledge-graph database (local only)
|
|
20
|
+
.reagent/
|
|
21
|
+
|
|
22
|
+
# Editor/IDE local config
|
|
23
|
+
.vscode/
|
|
24
|
+
|
|
25
|
+
# Generated data & local config (kept untracked on main)
|
|
26
|
+
# tox.ini is deliberately NOT here: the cross-version compat matrix is part of the project,
|
|
27
|
+
# and a contributor cannot reproduce it if the file is untracked.
|
|
28
|
+
.claude/
|
|
29
|
+
# requirements/ is deliberately NOT ignored: tox.ini (tracked) drives the min half of the
|
|
30
|
+
# compat matrix from requirements/min-constraints.txt, so ignoring it would leave the
|
|
31
|
+
# matrix unreproducible from a clone -- the same reason tox.ini itself is tracked.
|
|
32
|
+
CONTEXT.md
|
|
33
|
+
data/fit_results_cache_*
|
|
34
|
+
figures/benchmark_*/
|
|
35
|
+
# Per-system DFT entry caches fetched on demand from the Materials Project. A hand-picked
|
|
36
|
+
# set of these IS tracked (the fixtures the test suite reads); this pattern only stops
|
|
37
|
+
# NEWLY fetched ones showing up as untracked noise. Ignoring a path does not untrack
|
|
38
|
+
# anything already in the index, so the committed corpus is unaffected.
|
|
39
|
+
data/*_ENTRIES_MP_GGA.json
|
|
40
|
+
|
|
41
|
+
# Local secrets (API keys) - never commit
|
|
42
|
+
.env
|
|
43
|
+
.env.*
|
|
44
|
+
|
|
45
|
+
scripts/build_branch_feature_cache.py
|
|
46
|
+
tests_internal/test_branch_feature_cache.py
|
|
47
|
+
tests/_figures/
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project
|
|
6
|
+
follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). The distribution version is
|
|
7
|
+
derived from the git tag by `hatch-vcs` — tagging `vX.Y.Z` *is* the release — so nothing in the
|
|
8
|
+
source tree carries a version literal that could disagree with this file.
|
|
9
|
+
|
|
10
|
+
## [Unreleased]
|
|
11
|
+
|
|
12
|
+
## [0.1.0] - 2026-08-12
|
|
13
|
+
|
|
14
|
+
First public release. `gliquid` was developed privately before this point, so there are no
|
|
15
|
+
earlier published versions to diff against; this entry describes what the package **is** at
|
|
16
|
+
0.1.0 rather than what changed.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- **DFT-referenced binary liquid fitting** (`gliquid.binary`). `BinaryLiquid` assembles a
|
|
21
|
+
two-component system from cached Materials Project DFT entries plus a digitized experimental
|
|
22
|
+
phase diagram, and `fit_parameters()` optimizes non-ideal liquid mixing parameters against the
|
|
23
|
+
measured phase boundaries, reporting per-fit MAE. `BinaryLiquid.from_cache()` is the usual
|
|
24
|
+
entry point.
|
|
25
|
+
- **Solution models** (`gliquid.solution`). `SolutionModel` and the `RKPolyExp`
|
|
26
|
+
Redlich–Kister/exponential family, with four registered parameter formats — `linear`,
|
|
27
|
+
`combined`, `comb-exp`, `regular` — selected by name through `param_format=`, plus the
|
|
28
|
+
temperature scale `tau`.
|
|
29
|
+
- **Phase-equilibrium machinery** (`gliquid.hsx`). `HSX` and `lower_convex_hull` build the
|
|
30
|
+
enthalpy–entropy–composition lower convex hull that turns free-energy curves into phase
|
|
31
|
+
fields, liquidus/solidus boundaries and invariant points.
|
|
32
|
+
- **Ternary interpolation** (`gliquid.ternary`). `TernaryLiquidInterpolation` interpolates a
|
|
33
|
+
ternary liquid free-energy surface from three fitted binary sub-systems, with `TLIPlotter`
|
|
34
|
+
for isothermal sections and liquidus-surface views.
|
|
35
|
+
- **Unary reference database** (`gliquid.phase`). `UNARY`, `ComponentRef` and `Phase` expose
|
|
36
|
+
per-element melting points, transition temperatures and lattice stabilities used as the
|
|
37
|
+
reference states for every mixing calculation.
|
|
38
|
+
- **Experimental phase-diagram ingest** (`gliquid.mpds`). `load_mpds_data()` reads digitized
|
|
39
|
+
MPDS diagrams, and `identify_invariant_points()` extracts eutectics, peritectics and
|
|
40
|
+
congruent points from them.
|
|
41
|
+
- **Plotting layer** (`gliquid.plotting`, plus the `BLPlotter`/`TLIPlotter` façades). Plotly
|
|
42
|
+
binary T–x diagrams, convex-hull and free-energy views, ternary surfaces, a shared style/color
|
|
43
|
+
module, and figure export helpers.
|
|
44
|
+
- **Interactive hull editor** (`gliquid.hull_editor`). `ConvexHullEditor` is an `ipywidgets`
|
|
45
|
+
tool for hand-adjusting hull endpoints; the module imports on a bare install and raises a
|
|
46
|
+
message naming the `editor` extra only when one is actually constructed.
|
|
47
|
+
- **Pre-trained model runner** (`gliquid.production_model_runner`). Loads an exported L0/L1
|
|
48
|
+
model bundle, predicts from single-row frames while preserving the L1 antisymmetric
|
|
49
|
+
constraint, and renders compact SHAP force plots.
|
|
50
|
+
- **Bundled reference tables.** `phase_transitions.json`, `omegas_hcp.json` and
|
|
51
|
+
`spurious_structures.json` ship inside the wheel at `gliquid/data/`, so element free-energy
|
|
52
|
+
references work immediately after `pip install gliquid` with no external files.
|
|
53
|
+
- **External data-corpus contract** (`gliquid.config`). The per-system DFT entry caches,
|
|
54
|
+
digitized diagrams and model bundle are megabytes of per-system data that no distribution
|
|
55
|
+
carries. They are located through `set_data_dir()`, then `GLIQUID_DATA_DIR`, then a source
|
|
56
|
+
checkout's own `data/`; with none of the three available a call that needs the corpus raises
|
|
57
|
+
`ConfigError` naming both remedies rather than guessing a directory. Each shipped reference
|
|
58
|
+
table is overridden by a same-named file in the data directory when one is present.
|
|
59
|
+
- **Optional extras.** `mpds` (live MPDS downloads), `editor` (`ConvexHullEditor` widgets),
|
|
60
|
+
`models` (the exact `scikit-learn`/`xgboost` versions the serialized model artifacts were
|
|
61
|
+
pickled against), `notebook` (local Jupyter tooling), `test` (`pytest`, `ruff`).
|
|
62
|
+
- **Library-grade logging.** All output goes through the `gliquid` logger tree, one child
|
|
63
|
+
logger per module; the package installs no handlers and sets no levels, leaving that to the
|
|
64
|
+
application. `tests/test_logging_boundary.py` enforces the boundary against the source tree,
|
|
65
|
+
with two documented exemptions (`mpds.print_phase_mismatch_chart`, `hull_editor._log`).
|
|
66
|
+
- **Demonstration notebooks.** `notebooks/fitting_demo.ipynb`,
|
|
67
|
+
`notebooks/interpolation_demo.ipynb` and a Colab-ready `notebooks/colab_demo.ipynb`.
|
|
68
|
+
- **Two-tier test suite.** A public `tests/` suite plus a maintainer `tests_internal/` tier of
|
|
69
|
+
value pins, figure goldens and cache/network-gated families, with `pins`, `needs_cache`,
|
|
70
|
+
`needs_network` and `slow` markers under `--strict-markers`. See `CONTRIBUTING.md`.
|
|
71
|
+
- **Packaging.** Hatchling with `hatch-vcs`, so the version is single-sourced from the git tag;
|
|
72
|
+
Python 3.10–3.13 supported and exercised by a `tox` matrix.
|
|
73
|
+
|
|
74
|
+
### Known limitations
|
|
75
|
+
|
|
76
|
+
- **`dft_type` supports `GGA` only.** `R2SCAN` and `MIXED` remain recognized names, but neither
|
|
77
|
+
can currently be fetched, for reasons upstream of this package; both now raise a `ValueError`
|
|
78
|
+
naming the cause before any network call rather than failing obscurely mid-fetch.
|
|
79
|
+
`R2SCAN` — the Materials Project stores the thermo type as the literal `r2SCAN` while
|
|
80
|
+
`emmet.core.thermo.ThermoType.R2SCAN` is `R2SCAN`; `mp_api` validates the argument against the
|
|
81
|
+
enum and forwards that casing, so the query matches nothing and the fetch comes back empty.
|
|
82
|
+
`MIXED` — pymatgen's `MaterialsProjectDFTMixingScheme` hashes entry ids, but new-API entries
|
|
83
|
+
carry `entry_id` as a dict, raising `TypeError: unhashable type: 'dict'`; past that, its
|
|
84
|
+
r2SCAN half would be empty for the reason above, making it silently GGA-only. The bundled data
|
|
85
|
+
corpus and every published result are built on `GGA`.
|
|
86
|
+
- **An empty Materials Project fetch now raises rather than being cached.** A zero-entry result
|
|
87
|
+
used to be written out as a 2-byte `[]`, which every later read then accepted as a warm cache.
|
|
88
|
+
|
|
89
|
+
[Unreleased]: https://github.com/willwerj/gliquid_python/compare/v0.1.0...HEAD
|
|
90
|
+
[0.1.0]: https://github.com/willwerj/gliquid_python/releases/tag/v0.1.0
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it using the metadata below."
|
|
3
|
+
title: "GLiquid"
|
|
4
|
+
abstract: >-
|
|
5
|
+
A Python package for fitting DFT-referenced liquid free energies from digitized equilibrium
|
|
6
|
+
phase boundaries, and for interpolating multicomponent phase diagrams from the fitted binary
|
|
7
|
+
liquid descriptions.
|
|
8
|
+
type: software
|
|
9
|
+
# NOTE: this version is a literal and nothing derives it. The distribution version comes from
|
|
10
|
+
# the git tag via hatch-vcs, so this file and `date-released` below must be bumped BY HAND at
|
|
11
|
+
# each release -- see the release checklist in CONTRIBUTING.md.
|
|
12
|
+
version: "0.1.0"
|
|
13
|
+
date-released: "2026-08-12"
|
|
14
|
+
license: MIT
|
|
15
|
+
repository-code: "https://github.com/willwerj/gliquid_python"
|
|
16
|
+
url: "https://viz.whsunresearch.group/gliquid/interactive-matrix.html"
|
|
17
|
+
authors:
|
|
18
|
+
- given-names: Joshua
|
|
19
|
+
family-names: Willwerth
|
|
20
|
+
email: willwerj@umich.edu
|
|
21
|
+
affiliation: "University of Michigan"
|
|
22
|
+
- given-names: Abrar
|
|
23
|
+
family-names: Rauf
|
|
24
|
+
email: arauf@umich.edu
|
|
25
|
+
affiliation: "University of Michigan"
|
|
26
|
+
- given-names: Shibo
|
|
27
|
+
family-names: Tan
|
|
28
|
+
email: shibot@umich.edu
|
|
29
|
+
affiliation: "University of Michigan"
|
|
30
|
+
- given-names: Wenhao
|
|
31
|
+
family-names: Sun
|
|
32
|
+
email: whsun@umich.edu
|
|
33
|
+
affiliation: "University of Michigan"
|
|
34
|
+
keywords:
|
|
35
|
+
- "density functional theory"
|
|
36
|
+
- "thermodynamic modeling"
|
|
37
|
+
- "phase diagram"
|
|
38
|
+
- "liquidus"
|
|
39
|
+
- "solution phase"
|
|
40
|
+
- "intermetallic phase"
|
|
41
|
+
- "Materials Project"
|
|
42
|
+
- "Materials Platform for Data Science"
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Contributing to GLiquid
|
|
2
|
+
|
|
3
|
+
Pull requests are welcome. For anything larger than a bug fix, please open an issue first so
|
|
4
|
+
the change can be discussed before it is written.
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
|
|
8
|
+
Work from a clone, in an isolated environment. The convention among the maintainers is a conda
|
|
9
|
+
environment named `gliquidenv`:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
git clone https://github.com/willwerj/gliquid_python.git
|
|
13
|
+
cd gliquid_python
|
|
14
|
+
conda create --name gliquidenv python=3.10 # 3.11, 3.12 and 3.13 are also supported
|
|
15
|
+
conda activate gliquidenv
|
|
16
|
+
pip install -e .[test]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`.[test]` adds `pytest` and `ruff` on top of the runtime dependencies. Add other extras as the
|
|
20
|
+
work needs them — `.[editor]` for `ConvexHullEditor`, `.[mpds]` for live MPDS downloads,
|
|
21
|
+
`.[notebook]` for local Jupyter, `.[models]` for the exact `scikit-learn`/`xgboost` versions the
|
|
22
|
+
serialized model artifacts were pickled against.
|
|
23
|
+
|
|
24
|
+
Working from a clone also means the data corpus resolves automatically: `gliquid.config` falls
|
|
25
|
+
back to the checkout's own `data/` directory when neither `set_data_dir()` nor
|
|
26
|
+
`GLIQUID_DATA_DIR` has been used. See the README for the full resolution order.
|
|
27
|
+
|
|
28
|
+
## Running the tests
|
|
29
|
+
|
|
30
|
+
Run `pytest` from the repository root. The suite is tiered, and which tier you get depends on
|
|
31
|
+
what you pass:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pytest # the public tests/ suite -- the default, and what a contributor runs
|
|
35
|
+
pytest tests_internal # the maintainer tier: value pins, figure goldens, gated families
|
|
36
|
+
pytest tests tests_internal # everything; this is what CI runs
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
A bare `pytest` collects only `tests/` because `testpaths = ["tests"]` says so in
|
|
40
|
+
`pyproject.toml`; `tests_internal/` is tracked in git but never collected implicitly, and it is
|
|
41
|
+
excluded from the sdist.
|
|
42
|
+
|
|
43
|
+
For the fast edit/run loop, deselect the slow fits:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pytest -m "not slow"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
That is roughly a 2.7x speedup on the public suite — measured at 84.7 s against 225.7 s for the
|
|
50
|
+
full run on a maintainer machine. It is a faster loop, not an instant one; run the full suite
|
|
51
|
+
before you push.
|
|
52
|
+
|
|
53
|
+
### Markers
|
|
54
|
+
|
|
55
|
+
Four markers are declared, and `addopts = "--strict-markers"` means an undeclared or misspelled
|
|
56
|
+
one fails the run instead of silently applying no marker at all.
|
|
57
|
+
|
|
58
|
+
| marker | meaning |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| `pins` | A frozen-value characterization pin. It asserts that today's numbers equal the numbers captured when the pin was frozen. |
|
|
61
|
+
| `needs_cache` | Needs the workspace `matrix_data/` store of per-system DFT and digitized-diagram caches. **Skips**, rather than fails, on a checkout without it. |
|
|
62
|
+
| `needs_network` | Needs `NEW_MP_API_KEY` and a live Materials Project connection. |
|
|
63
|
+
| `slow` | A multi-second Nelder–Mead fit or hull build. Deselect with `-m "not slow"`. |
|
|
64
|
+
|
|
65
|
+
### Re-freezing a pin
|
|
66
|
+
|
|
67
|
+
Every pin file's module docstring names the script that froze its fixture (the freezer scripts
|
|
68
|
+
live with the maintainers' driver scripts, outside this repository). Re-freezing is a deliberate
|
|
69
|
+
act: run that script, inspect the diff in the fixture JSON, and say in the commit message *why*
|
|
70
|
+
the values moved.
|
|
71
|
+
|
|
72
|
+
**Never edit a pin to make it pass.** A pin that changed is telling you the behavior changed. If
|
|
73
|
+
that change was intended, re-freeze it through the freezer and justify it. If it was not, you
|
|
74
|
+
have found the bug the pin exists to catch.
|
|
75
|
+
|
|
76
|
+
## Formatting and linting
|
|
77
|
+
|
|
78
|
+
`ruff` is the formatter, configured in `pyproject.toml` at `line-length = 100` — not the 88
|
|
79
|
+
default, because this codebase already writes to roughly 95–100 characters and 88 would split
|
|
80
|
+
calls that read fine today.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
ruff format src/gliquid tests tests_internal # before you push
|
|
84
|
+
ruff format --check src/gliquid tests tests_internal
|
|
85
|
+
ruff check src/gliquid # advisory for now, not yet a gate
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Scattered `# noqa: WPS...` comments survive in the source. They are inherited from a retired
|
|
89
|
+
wemake-python-styleguide configuration and **are enforced by nothing today** — no tool in the
|
|
90
|
+
current setup reads them. Do not add new ones, and do not treat an existing one as evidence that
|
|
91
|
+
some rule is still active.
|
|
92
|
+
|
|
93
|
+
## The print/logging boundary
|
|
94
|
+
|
|
95
|
+
The library reports through `logging` — one `logger = logging.getLogger(__name__)` per module,
|
|
96
|
+
all children of the `gliquid` logger — and installs no handlers and sets no levels of its own.
|
|
97
|
+
Handler and level configuration belongs to the application consuming the library, not to the
|
|
98
|
+
library.
|
|
99
|
+
|
|
100
|
+
Consequently, **a bare `print()` added anywhere in `src/gliquid` fails
|
|
101
|
+
`tests/test_logging_boundary.py`.** So does a direct `sys.stdout.write` / `sys.stderr.write`, and
|
|
102
|
+
so does any call to `basicConfig`, `addHandler`, `setLevel`, `StreamHandler`, `FileHandler` or
|
|
103
|
+
`NullHandler` inside the package. The scan is over the source tree, not the import graph, so a
|
|
104
|
+
`print()` on a branch no test happens to execute is still caught.
|
|
105
|
+
|
|
106
|
+
There are exactly two documented exemptions, listed in `EXEMPT` in that test file:
|
|
107
|
+
|
|
108
|
+
- `mpds.print_phase_mismatch_chart` — the function *is* a console chart renderer; the aligned
|
|
109
|
+
monospace rows are the product, not diagnostics.
|
|
110
|
+
- `hull_editor._log` — writes into an `ipywidgets` `Output` pane. Widget UI, not logging.
|
|
111
|
+
|
|
112
|
+
Adding a third exemption requires editing that test, which is the point. If your output is
|
|
113
|
+
diagnostic, use the module logger.
|
|
114
|
+
|
|
115
|
+
## Release checklist
|
|
116
|
+
|
|
117
|
+
The distribution version is derived from the git tag by `hatch-vcs` — tagging is the release,
|
|
118
|
+
and no version literal lives in `src/`. `tests/test_version.py` enforces that.
|
|
119
|
+
|
|
120
|
+
1. **Bump `CITATION.cff` by hand.** Its `version:` and `date-released:` are literals and nothing
|
|
121
|
+
derives them; this is the one file that must be edited at every release.
|
|
122
|
+
2. **Add the `CHANGELOG.md` entry.** Move what is under `## [Unreleased]` into a new
|
|
123
|
+
`## [X.Y.Z] - YYYY-MM-DD` section and update the link definitions at the bottom.
|
|
124
|
+
3. **Commit** those two changes.
|
|
125
|
+
4. **Tag** the commit `vX.Y.Z` (SemVer, `v` prefix) and **push the tag**.
|
|
126
|
+
|
|
127
|
+
The release workflow does the rest — building the sdist and wheel from the tag and publishing
|
|
128
|
+
them. Do not hand-edit a version anywhere else; if the built artifact reports `0.0.x`, the
|
|
129
|
+
`hatch-vcs` fallback fired and the build did not see the tag. Investigate rather than
|
|
130
|
+
overriding it.
|
gliquid-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Joshua Willwerth
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|