Skip to content

Commit c228b74

Browse files
committed
Test example scripts with uv run in CI (#286)
* mv examples/dataset_exploration/* examples/ * use faster uv run to test example scripts in CI * fix find-example-scripts * try uv run --with-editable * add python-dotenv dep to assets/scripts/track_pymatviz_citations.py * skip umap example for now
1 parent f1710b4 commit c228b74

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+70
-1453
lines changed

.github/workflows/test.yml

+10-10
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ jobs:
3030
test-cmd: pytest --durations 20 --cov-branch --cov-report=xml --cov pymatviz --splits 4 --group ${{ matrix.split }} --splitting-algorithm least_duration
3131
upload-coverage: strict
3232

33-
find-scripts:
33+
find-example-scripts:
3434
runs-on: ubuntu-latest
3535
outputs:
36-
script_list: ${{ steps.set-matrix.outputs.script_list }}
36+
example_scripts: ${{ steps.set-matrix.outputs.example_scripts }}
3737
steps:
3838
- name: Check out repository
3939
uses: actions/checkout@v4
@@ -42,26 +42,26 @@ jobs:
4242
id: set-matrix
4343
run: |
4444
SCRIPTS=$(find assets/scripts -name "*.py" | jq -R -s -c 'split("\n")[:-1]')
45-
echo "script_list=$SCRIPTS" >> $GITHUB_OUTPUT
45+
echo "example_scripts=$SCRIPTS" >> $GITHUB_OUTPUT
4646
47-
test-scripts:
48-
needs: find-scripts
47+
test-example-scripts:
48+
needs: find-example-scripts
4949
runs-on: ubuntu-latest
5050
strategy:
5151
fail-fast: false
5252
matrix:
53-
script: ${{fromJson(needs.find-scripts.outputs.script_list)}}
53+
example_script: ${{fromJson(needs.find-example-scripts.outputs.example_scripts)}}
5454
steps:
5555
- name: Check out repository
5656
uses: actions/checkout@v4
5757

5858
- name: Set up Python
5959
uses: actions/setup-python@v5
6060
with:
61-
python-version: "3.10"
61+
python-version: 3.11
6262

63-
- name: Install package and dependencies
64-
run: pip install -e .[make-assets,cluster]
63+
- name: Set up uv
64+
uses: astral-sh/setup-uv@v2
6565

6666
- name: Run script
67-
run: python ${{ matrix.script }}
67+
run: uv run --with-editable .[make-assets] ${{ matrix.example_script }}

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ build/
77
examples/*.html
88
examples/**/*.json.gz
99
examples/**/*.json.xz
10+
examples/**/*.csv.*
1011
examples/**/*.pt
11-
examples/dataset_exploration/**/*.pdf
12+
examples/**/*.pdf
1213
gnome
1314
assets/scripts/pmv-used-by-list-*.yaml*
1415
*.archive

.pre-commit-config.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ repos:
3838
exclude: ^assets/.+\.(svg|html)$
3939
- id: mixed-line-ending
4040
- id: trailing-whitespace
41+
- id: check-added-large-files
42+
args: [--maxkb=1024]
4143

4244
- repo: https://github.com/codespell-project/codespell
4345
rev: v2.4.1

assets/scripts/brillouin/brillouin_zone_3d.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# /// script
2+
# dependencies = [
3+
# "seekpath>=2.1",
4+
# ]
5+
# ///
6+
7+
18
# %%
29
from glob import glob
310

@@ -12,7 +19,7 @@
1219
tuple(
1320
path.split("/")[-1].replace(".json.gz", "").rsplit("-", maxsplit=2)
1421
): Structure.from_file(path)
15-
for path in glob(f"{TEST_FILES}/structures/*-*-*-*.json.gz")
22+
for path in glob(f"{TEST_FILES}/structures/mp-*-*-*.json.gz")
1623
}
1724

1825

assets/scripts/classify/precision_recall_curve.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import pymatviz as pmv
66

77

8-
pmv.set_plotly_template("pymatviz_dark")
8+
pmv.set_plotly_template("pymatviz_white")
99

1010
# Random classification data
1111
np_rng = np.random.default_rng(seed=0)

assets/scripts/cluster/composition/cluster_compositions_matbench.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
Resulting plots are colored by target property of each dataset.
44
"""
55

6+
# /// script
7+
# dependencies = [
8+
# "matminer>=0.9.1",
9+
# "umap-learn>=0.5",
10+
# ]
11+
# ///
12+
613
from __future__ import annotations
714

815
import gzip
@@ -163,8 +170,9 @@ def process_dataset(
163170
(*mb_steels, "magpie", "pca", 2, dict(x=0.01, xanchor="left")),
164171
# 2. Steels with t-SNE (2D) - shows non-linear clustering
165172
(*mb_steels, "magpie", "tsne", 2, dict(x=0.01, xanchor="left")),
173+
# TODO umap-learn seemingly not installed by uv run in CI, fix later
166174
# 3. JDFT2D with UMAP (2D) - shows modern non-linear projection
167-
(*mb_jdft2d, "magpie", "umap", 2, dict(x=0.01, xanchor="left")),
175+
# (*mb_jdft2d, "magpie", "umap", 2, dict(x=0.01, xanchor="left")),
168176
# 4. JDFT2D with one-hot encoding and PCA (3D) - shows raw element relationships
169177
(*mb_jdft2d, "one-hot", "pca", 3, dict()),
170178
# 5. Steels with Matscholar embedding and t-SNE (3D) - shows advanced embedding
+14-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# %%
22
import pandas as pd
3-
from mp_api.client import MPRester
4-
from mp_api.client.core import MPRestError
3+
from matminer.datasets import load_dataset
54

65
import pymatviz as pmv
76
from pymatviz.enums import Key
@@ -11,31 +10,28 @@
1110

1211

1312
# %% Sankey diagram of crystal systems and space groups
14-
try:
15-
with MPRester(use_document_model=False) as mpr:
16-
fields = [Key.mat_id, "symmetry.crystal_system", "symmetry.symbol"]
17-
docs = mpr.materials.summary.search(
18-
num_elements=(1, 3), fields=fields, num_chunks=30, chunk_size=1000
19-
)
20-
except MPRestError:
21-
raise SystemExit(0) from None
13+
data_name = "matbench_phonons"
14+
df_phonons = load_dataset(data_name)
2215

16+
df_sym = pd.DataFrame(
17+
struct.get_symmetry_dataset(backend="moyopy", return_raw_dataset=True).as_dict()
18+
for struct in df_phonons[Key.structure]
19+
).rename(columns={"number": Key.spg_num})
20+
df_sym[Key.crystal_system] = df_sym[Key.spg_num].map(pmv.utils.spg_to_crystal_sys)
2321

24-
# %%
25-
df_mp = pd.json_normalize(docs).set_index(Key.mat_id)
26-
df_mp.columns = [Key.crystal_system, Key.spg_symbol]
2722

28-
frequent_symbols = df_mp[Key.spg_symbol].value_counts().nlargest(20).index
23+
# %%
24+
frequent_symbols = df_sym[Key.spg_num].value_counts().nlargest(20).index
2925

30-
df_spg = df_mp.query(f"{Key.spg_symbol} in @frequent_symbols")
26+
df_spg = df_sym.query(f"{Key.spg_num} in @frequent_symbols")
3127

3228

3329
# %%
3430
fig = pmv.sankey_from_2_df_cols(
35-
df_spg, [Key.crystal_system, Key.spg_symbol], labels_with_counts="percent"
31+
df_spg, [Key.crystal_system, Key.spg_num], labels_with_counts="percent"
3632
)
37-
title = "Common Space Groups in Materials Project"
33+
title = f"Common Space Groups in {data_name}"
3834
fig.layout.title = dict(text=title, x=0.5, y=0.95)
3935
fig.layout.margin.t = 50
4036
fig.show()
41-
pmv.io.save_and_compress_svg(fig, "sankey-crystal-sys-to-spg-symbol")
37+
pmv.io.save_and_compress_svg(fig, f"sankey-{data_name}")

assets/scripts/structure_viz/structure_2d.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import matplotlib.pyplot as plt
66
from matminer.datasets import load_dataset
7-
from mp_api.client import MPRester
87
from pymatgen.core import Structure
98

109
import pymatviz as pmv
@@ -29,7 +28,7 @@
2928
fig.show()
3029

3130

32-
# %% Plot some disordered structures in 2D
31+
# %% 2D plots of disordered structures
3332
struct_mp_ids = ("mp-19017", "mp-12712")
3433
structure_dir = f"{TEST_FILES}/structures"
3534

@@ -41,6 +40,7 @@
4140
raise FileNotFoundError(
4241
f"structure for {mp_id} not found, run this script locally to fetch it."
4342
)
43+
from mp_api.client import MPRester
4444

4545
struct: Structure = MPRester().get_structure_by_material_id(
4646
mp_id, conventional_unit_cell=True

assets/scripts/sunburst/chem_sys_sunburst.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@
6262

6363
# %% Load the Ward metallic glasses https://pubs.acs.org/doi/10.1021/acs.chemmater.6b04153
6464
data_path = "ward_metallic_glasses/ward-metallic-glasses.csv.xz"
65-
df_mg = pd.read_csv(
66-
f"{ROOT}/examples/dataset_exploration/{data_path}", na_values=()
67-
).query("comment.isna()")
65+
df_mg = pd.read_csv(f"{ROOT}/examples/{data_path}", na_values=()).query(
66+
"comment.isna()"
67+
)
6868

6969
fig = pmv.chem_sys_sunburst(
7070
df_mg[Key.composition],

assets/scripts/track_pymatviz_citations.py

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# dependencies = [
1212
# "google-search-results>=2.4.2",
1313
# "pyyaml>=6.0.2",
14+
# "python-dotenv>=1.1",
1415
# ]
1516
# ///
1617

assets/scripts/treemap/chem_sys_treemap.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636

3737
# %% Load the Ward metallic glass dataset https://pubs.acs.org/doi/10.1021/acs.chemmater.6b04153
38-
csv_path = f"{ROOT}/examples/dataset_exploration/ward_metallic_glasses/ward-metallic-glasses.csv.xz" # noqa: E501
38+
csv_path = f"{ROOT}/examples/ward_metallic_glasses/ward-metallic-glasses.csv.xz"
3939
df_mg = pd.read_csv(csv_path, na_values=()).query("comment.isna()")
4040

4141
fig = pmv.chem_sys_treemap(

examples/compare_elastic_constants.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@
1919
from emmet.core.elasticity import ElasticityDoc
2020
from mace.calculators import mace_mp
2121
from matcalc.elasticity import ElasticityCalc
22-
from mp_api.client import MPRester
2322
from tqdm import tqdm
2423

2524
import pymatviz as pmv
2625

2726

27+
try:
28+
from mp_api.client import MPRester
29+
except ImportError:
30+
raise SystemExit(0) from None
31+
2832
pmv.set_plotly_template("pymatviz_white")
2933
checkpoint = "https://github.com/ACEsuit/mace-mp/releases/download/mace_matpes_0/MACE-matpes-pbe-omat-ft.model"
3034

0 commit comments

Comments
 (0)