Skip to content

Commit

Permalink
Split make_assets scripts by plot functions (#247)
Browse files Browse the repository at this point in the history
* migrate some changes

* put under dir first

* split coordination

* split histogram

* split phonon

* splig rdf

* splig scatter

* splig structure_viz and scatter

* split the rest

* split ptable

* copy random data generator

* rename powerups plotly

* remove plotly example from ptable mpl

* move assets/(asset_makers->scripts)

* mv assets/*.svg assets/svg/*.svg

* change save_and_compress_svg default output directory to assets/svg/

* restore examples/ ruff per-file-ignores

* rm assets/scripts/(scatter|uncertainty)/_random_regression_data.py

unused, left from bad merge conflict resolve

* revert ptable_heatmap_splits

* add tests/data/regression.py

* fix with_marginal_hist creating two nested coordinated axes in density_hexbin_(hex_)with_hist

* make dummy data generator modular a bit

* add config_matplotlib

* remove np_rng

* enhance description of dummy data with GPT

* migrate ptable

* migrate phonons

* relocate ptable dash app

* migrate the rest

* mv pymatviz/test/data.py to pymatviz/data/__init__.py

mv tests/test/test_data.py to tests/test_data.py

* fix test.yml find-scripts looking in wrong folder

* merge pymatviz/test/config.py into pymatviz/utils.py and rename config_matplotlib to apply_matplotlib_template

add unit test for apply_matplotlib_template()
remove unneeded plotly templates from matplotlib asset scripts

* fix asset scripts failing in CI, delete duplicate assets/scripts/powerups/powerups.py

remove unused pmv.set_plotly_template

---------

Co-authored-by: Janosh Riebesell <[email protected]>
  • Loading branch information
DanielYang59 and janosh authored Nov 19, 2024
1 parent 6dd2708 commit 4380b05
Show file tree
Hide file tree
Showing 128 changed files with 1,046 additions and 653 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ on:
workflow_dispatch:
workflow_call:

env:
MPLBACKEND: Agg # non-interactive backend for matplotlib

jobs:
tests:
strategy:
Expand All @@ -36,7 +39,7 @@ jobs:
- name: Find Python scripts
id: set-matrix
run: |
SCRIPTS=$(find examples/make_assets -name "*.py" | jq -R -s -c 'split("\n")[:-1]')
SCRIPTS=$(find assets/scripts -name "*.py" | jq -R -s -c 'split("\n")[:-1]')
echo "script_list=$SCRIPTS" >> $GITHUB_OUTPUT
test-scripts:
Expand Down
1 change: 0 additions & 1 deletion assets/density-scatter-with-hist.svg

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import pymatviz as pmv
from pymatviz.coordination import CnSplitMode
from pymatviz.enums import Key
from pymatviz.utils import TEST_FILES


Expand Down Expand Up @@ -190,44 +189,3 @@
)
fig.show()
pmv.io.save_and_compress_svg(fig, "coordination-hist-all-combined-side-by-side")


# %% Coordination vs Cutoff example for a single structure
fig = pmv.coordination_vs_cutoff_line(structures[key1])
fig.layout.title = dict(text=f"Coordination vs Cutoff: {key1}", x=0.5, y=0.98)
fig.layout.margin.t = 50
fig.show()
pmv.io.save_and_compress_svg(fig, "coordination-vs-cutoff-single")


# %% Coordination vs Cutoff example for multiple structures
fig = pmv.coordination_vs_cutoff_line(
{key1: structures[key1], key2: structures[key2], key3: structures[key3]},
strategy=(1.0, 6.0),
num_points=100,
)
fig.layout.title = dict(
text="Coordination vs Cutoff: Multiple Structures", x=0.5, y=0.98
)
fig.layout.legend.update(x=0, y=1, bgcolor="rgba(0,0,0,0)")
fig.layout.margin.t = 50
fig.show()
pmv.io.save_and_compress_svg(fig, "coordination-vs-cutoff-multiple")


# %% Coordination vs Cutoff example with custom color scheme
custom_colors = {"Pd": "red", "Zr": "blue"}
fig = pmv.coordination_vs_cutoff_line(
structures[key1], element_color_scheme=custom_colors
)
fig.layout.margin.t = 25
fig.layout.legend.update(x=0, y=1)
fig.show()
pmv.io.save_and_compress_svg(fig, "coordination-vs-cutoff-custom-colors")


# %% plot first 10 structures
fig = pmv.coordination_vs_cutoff_line(df_phonon[Key.structure][:4].tolist())
fig.layout.margin.t = 25
fig.layout.legend.update(x=0, y=1)
fig.show()
85 changes: 85 additions & 0 deletions assets/scripts/coordination/coordination_vs_cutoff_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# %%
from glob import glob

from matminer.datasets import load_dataset
from pymatgen.core import Structure
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer

import pymatviz as pmv
from pymatviz.enums import Key
from pymatviz.utils import TEST_FILES


pmv.set_plotly_template("pymatviz_white")

df_phonon = load_dataset(data_name := "matbench_phonons")


# %%
formula_spg_str = (
lambda struct: f"{struct.formula} ({struct.get_space_group_info()[1]})"
)
structures = {
formula_spg_str(struct := Structure.from_file(file)): struct
for file in (
glob(f"{TEST_FILES}/structures/*.json.gz") + glob(f"{TEST_FILES}/xrd/*.cif")
)
}
key1, key2, key3, *_ = structures

for struct in structures.values():
spga = SpacegroupAnalyzer(struct)
sym_struct = spga.get_symmetrized_structure()
# add wyckoff symbols to each site
struct.add_oxidation_state_by_guess()
wyckoff_symbols = ["n/a"] * len(struct)
for indices, symbol in zip(
sym_struct.equivalent_indices, sym_struct.wyckoff_symbols, strict=True
):
for index in indices:
wyckoff_symbols[index] = symbol
if any(sym == "n/a" for sym in wyckoff_symbols):
raise ValueError(f"{struct.formula} has n/a {wyckoff_symbols=}")

struct.add_site_property("wyckoff", wyckoff_symbols)


# %% Coordination vs Cutoff example for a single structure
fig = pmv.coordination_vs_cutoff_line(structures[key1])
fig.layout.title = dict(text=f"Coordination vs Cutoff: {key1}", x=0.5, y=0.98)
fig.layout.margin.t = 50
fig.show()
pmv.io.save_and_compress_svg(fig, "coordination-vs-cutoff-single")


# %% Coordination vs Cutoff example for multiple structures
fig = pmv.coordination_vs_cutoff_line(
{key1: structures[key1], key2: structures[key2], key3: structures[key3]},
strategy=(1.0, 6.0),
num_points=100,
)
fig.layout.title = dict(
text="Coordination vs Cutoff: Multiple Structures", x=0.5, y=0.98
)
fig.layout.legend.update(x=0, y=1, bgcolor="rgba(0,0,0,0)")
fig.layout.margin.t = 50
fig.show()
pmv.io.save_and_compress_svg(fig, "coordination-vs-cutoff-multiple")


# %% Coordination vs Cutoff example with custom color scheme
custom_colors = {"Pd": "red", "Zr": "blue"}
fig = pmv.coordination_vs_cutoff_line(
structures[key1], element_color_scheme=custom_colors
)
fig.layout.margin.t = 25
fig.layout.legend.update(x=0, y=1)
fig.show()
pmv.io.save_and_compress_svg(fig, "coordination-vs-cutoff-custom-colors")


# %% plot first 10 structures
fig = pmv.coordination_vs_cutoff_line(df_phonon[Key.structure][:4].tolist())
fig.layout.margin.t = 25
fig.layout.legend.update(x=0, y=1)
fig.show()
14 changes: 14 additions & 0 deletions assets/scripts/histogram/elements_hist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# %%
from matminer.datasets import load_dataset

import pymatviz as pmv
from pymatviz.enums import Key


# %% Histogram Plots
df_expt_gap = load_dataset("matbench_expt_gap")

ax = pmv.elements_hist(
df_expt_gap[Key.composition], keep_top=15, v_offset=200, rotation=0, fontsize=12
)
pmv.io.save_and_compress_svg(ax, "elements-hist")
21 changes: 21 additions & 0 deletions assets/scripts/histogram/histogram.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# %%
import numpy as np

import pymatviz as pmv


pmv.set_plotly_template("pymatviz_white")


# %% plot 2 Gaussians and their cumulative distribution functions
rand_regression_size = 500
np_rng = np.random.default_rng(seed=0)
gauss1 = np_rng.normal(5, 4, rand_regression_size)
gauss2 = np_rng.normal(10, 2, rand_regression_size)

fig = pmv.histogram({"Gaussian 1": gauss1, "Gaussian 2": gauss2}, bins=100)
for idx in range(len(fig.data)):
pmv.powerups.add_ecdf_line(fig, trace_idx=idx)
fig.show()

pmv.io.save_and_compress_svg(fig, "histogram-ecdf")
27 changes: 27 additions & 0 deletions assets/scripts/histogram/spacegroup_bar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# %%
from matminer.datasets import load_dataset
from tqdm import tqdm

import pymatviz as pmv
from pymatviz.enums import Key


pmv.set_plotly_template("pymatviz_white")


# %%
df_phonons = load_dataset("matbench_phonons")

df_phonons[[Key.spg_symbol, Key.spg_num]] = [
struct.get_space_group_info()
for struct in tqdm(df_phonons[Key.structure], desc="Getting spacegroups")
]


# %% Spacegroup histograms
for backend in pmv.BACKENDS:
fig = pmv.spacegroup_bar(df_phonons[Key.spg_num], backend=backend)
pmv.io.save_and_compress_svg(fig, f"spg-num-hist-{backend}")

fig = pmv.spacegroup_bar(df_phonons[Key.spg_symbol], backend=backend)
pmv.io.save_and_compress_svg(fig, f"spg-symbol-hist-{backend}")
38 changes: 38 additions & 0 deletions assets/scripts/phonons/phonon_bands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# %%
import json
from glob import glob

from monty.io import zopen
from monty.json import MontyDecoder
from pymatgen.phonon.bandstructure import PhononBandStructureSymmLine as PhononBands

import pymatviz as pmv
from pymatviz.enums import Key


# TODO: ffonons not working properly (see #195)
try:
import ffonons # noqa: F401
except ImportError:
raise SystemExit(0) from None # install ffonons to run this script


# %% Plot phonon bands and DOS
for mp_id, formula in (
("mp-2758", "Sr4Se4"),
("mp-23907", "H2"),
):
docs = {}
for path in glob(f"{pmv.utils.TEST_FILES}/phonons/{mp_id}-{formula}-*.json.lzma"):
key = path.split("-")[-1].split(".")[0]
with zopen(path) as file:
docs[key] = json.loads(file.read(), cls=MontyDecoder)

ph_bands: dict[str, PhononBands] = {
key: getattr(doc, Key.ph_band_structure) for key, doc in docs.items()
}

fig = pmv.phonon_bands(ph_bands)
fig.layout.title = dict(text=f"Phonon Bands of {formula} ({mp_id})", x=0.5, y=0.98)
fig.layout.margin = dict(l=0, r=0, b=0, t=40)
pmv.io.save_and_compress_svg(fig, f"phonon-bands-{mp_id}")
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,6 @@
key: getattr(doc, Key.ph_dos) for key, doc in docs.items()
}

fig = pmv.phonon_bands(ph_bands)
fig.layout.title = dict(text=f"Phonon Bands of {formula} ({mp_id})", x=0.5, y=0.98)
fig.layout.margin = dict(l=0, r=0, b=0, t=40)
pmv.io.save_and_compress_svg(fig, f"phonon-bands-{mp_id}")

fig = pmv.phonon_dos(ph_doses)
fig.layout.title = dict(text=f"Phonon DOS of {formula} ({mp_id})", x=0.5, y=0.98)
fig.layout.margin = dict(l=0, r=0, b=0, t=40)
pmv.io.save_and_compress_svg(fig, f"phonon-dos-{mp_id}")

fig = pmv.phonon_bands_and_dos(ph_bands, ph_doses)
fig.layout.title = dict(
text=f"Phonon Bands and DOS of {formula} ({mp_id})", x=0.5, y=0.98
Expand Down
38 changes: 38 additions & 0 deletions assets/scripts/phonons/phonon_dos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# %%
import json
from glob import glob

from monty.io import zopen
from monty.json import MontyDecoder
from pymatgen.phonon.dos import PhononDos

import pymatviz as pmv
from pymatviz.enums import Key


# TODO: ffonons not working properly (see #195)
try:
import ffonons # noqa: F401
except ImportError:
raise SystemExit(0) from None # install ffonons to run this script


# %% Plot phonon bands and DOS
for mp_id, formula in (
("mp-2758", "Sr4Se4"),
("mp-23907", "H2"),
):
docs = {}
for path in glob(f"{pmv.utils.TEST_FILES}/phonons/{mp_id}-{formula}-*.json.lzma"):
key = path.split("-")[-1].split(".")[0]
with zopen(path) as file:
docs[key] = json.loads(file.read(), cls=MontyDecoder)

ph_doses: dict[str, PhononDos] = {
key: getattr(doc, Key.ph_dos) for key, doc in docs.items()
}

fig = pmv.phonon_dos(ph_doses)
fig.layout.title = dict(text=f"Phonon DOS of {formula} ({mp_id})", x=0.5, y=0.98)
fig.layout.margin = dict(l=0, r=0, b=0, t=40)
pmv.io.save_and_compress_svg(fig, f"phonon-dos-{mp_id}")
File renamed without changes.
44 changes: 44 additions & 0 deletions assets/scripts/ptable_matplotlib/ptable_heatmap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# %%
from matminer.datasets import load_dataset

import pymatviz as pmv
from pymatviz.enums import Key


# %%
df_expt_gap = load_dataset("matbench_expt_gap")


# %% Elemental Plots
ax = pmv.ptable_heatmap(
pmv.count_elements(df_expt_gap[Key.composition]),
log=True,
return_type="axes", # TODO: change to return Figure after 2025-07-01
)
title = (
f"Elements in Matbench Experimental Band Gap ({len(df_expt_gap):,} compositions)"
)
ax.set_title(title, x=0.75, y=2.5, fontsize=18, fontweight="bold")
pmv.io.save_and_compress_svg(ax, "ptable-heatmap")


# %%
fig = pmv.ptable_heatmap(pmv.df_ptable[Key.atomic_mass], return_type="figure")
fig.suptitle("Atomic Mass Heatmap", y=0.96, fontsize=20, fontweight="bold")
pmv.io.save_and_compress_svg(fig, "ptable-heatmap-atomic-mass")


# %%
# Filter out near-zero entries
ptable_data = pmv.count_elements(df_expt_gap[Key.composition])
ptable_data = ptable_data[ptable_data > 0.01]

fig = pmv.ptable_heatmap(
ptable_data,
value_show_mode="percent",
exclude_elements=["O"],
return_type="figure",
)
title = "Elements in Matbench Experimental Band Gap (percent)"
fig.suptitle(title, y=0.96, fontsize=20, fontweight="bold")
pmv.io.save_and_compress_svg(fig, "ptable-heatmap-percent")
19 changes: 19 additions & 0 deletions assets/scripts/ptable_matplotlib/ptable_heatmap_ratio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# %%
from matminer.datasets import load_dataset

import pymatviz as pmv
from pymatviz.enums import Key


# %%
df_expt_gap = load_dataset("matbench_expt_gap")
df_steels = load_dataset("matbench_steels")


# %%
fig = pmv.ptable_heatmap_ratio(
df_expt_gap[Key.composition], df_steels[Key.composition], log=True, value_fmt=".4g"
)
title = "Element ratios in Matbench Experimental Band Gap vs Matbench Steel"
fig.suptitle(title, y=0.96, fontsize=16, fontweight="bold")
pmv.io.save_and_compress_svg(fig, "ptable-heatmap-ratio")
Loading

0 comments on commit 4380b05

Please sign in to comment.