Skip to content

Commit

Permalink
spglib to moyo (#275)
Browse files Browse the repository at this point in the history
* remove `get_cbar_label_formatter()` from `utils/plotting.py`

- Remove corresponding import and test cases

* import `calculate_rdf` in RDF module's `__init__.py`

- Update test case in `test_both_powerups.py` to use `add_scatter` instead of `add_trace`
- Minor SVG asset updates for element pair RDFs

* swap spglib for moyopy in example notebooks

plus minor refactors

* more spglib for moyopy swapping

- Update structure visualization scripts to use moyopy for space group number retrieval
- Modify spacegroup_sunburst and spacegroup_bar to work with moyopy
- Add mapping for Hermann-Maguin short symbols to space group numbers
- Remove commented-out SVG saving in sunburst script

* fix pymatgen SpaceGroup circular import error

materialsproject/pymatgen#4309

examples/matbench_perovskites_eda.ipynb remove ipynb cell output with huge line count

* breaking: rename `crystal_sys_from_spg_num()` to `spg_to_crystal_sys()`

- now also supports converting space group symbols to crystal systems, not just numbers
- Create `spg_num_to_from_symbol()` for bidirectional space group number/symbol conversion
- bump moyopy to 0.4.1
- Modify scripts to use new utility functions across various dataset exploration examples
  • Loading branch information
janosh authored Mar 1, 2025
1 parent 73a7faa commit afcbdb8
Show file tree
Hide file tree
Showing 33 changed files with 339 additions and 394 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
with:
os: ${{ matrix.os }}
python-version: "3.10"
install-cmd: uv pip install -e '.[test,brillouin,symmetry]' --system
install-cmd: uv pip install -e '.[test,brillouin]' --system
# pytest-split distributes work load so parallel jobs finish in similar time
# update durations file with `pytest --store-durations --durations-path tests/files/.pytest-split-durations`
test-cmd: pytest --durations 20 --cov-branch --cov-report=xml --cov pymatviz --splits 4 --group ${{ matrix.split }} --splitting-algorithm least_duration
Expand Down Expand Up @@ -61,7 +61,7 @@ jobs:
python-version: "3.10"

- name: Install package and dependencies
run: pip install -e .[make-assets,symmetry]
run: pip install -e .[make-assets]

- name: Run script
run: python ${{ matrix.script }}
16 changes: 7 additions & 9 deletions assets/scripts/bar/spacegroup_bar.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# %%
import pandas as pd
from matminer.datasets import load_dataset
from moyopy import SpaceGroupType
from tqdm import tqdm

import pymatviz as pmv
from pymatviz.enums import Key
Expand All @@ -13,13 +12,12 @@
# %%
df_phonons = load_dataset("matbench_phonons")

df_phonons[Key.spg_num] = [
struct.get_symmetry_dataset(backend="moyopy", return_raw_dataset=True).number
for struct in tqdm(df_phonons[Key.structure], desc="Getting spacegroups")
]
df_phonons[Key.spg_symbol] = [
SpaceGroupType(spg_num).hm_short for spg_num in df_phonons[Key.spg_num]
]
df_sym = pd.DataFrame(
struct.get_symmetry_dataset(backend="moyopy", return_raw_dataset=True).as_dict()
for struct in df_phonons[Key.structure]
)
df_phonons[Key.spg_num] = df_sym["number"]
df_phonons[Key.spg_symbol] = df_sym["number"].map(pmv.utils.spg_num_to_from_symbol)


# %% Spacegroup histograms
Expand Down
18 changes: 9 additions & 9 deletions assets/scripts/ptable_plotly/ptable_heatmap_plotly.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from matminer.datasets import load_dataset

import pymatviz as pmv
from pymatviz import df_ptable
from pymatviz.enums import ElemCountMode, Key


Expand All @@ -18,9 +17,9 @@

# %% Plotly interactive periodic table heatmap
fig = pmv.ptable_heatmap_plotly(
df_ptable[Key.atomic_mass],
pmv.df_ptable[Key.atomic_mass],
hover_props=[Key.atomic_mass, Key.atomic_number],
hover_data="density = " + df_ptable[Key.density].astype(str) + " g/cm^3",
hover_data="density = " + pmv.df_ptable[Key.density].astype(str) + " g/cm^3",
show_values=False,
)
fig.layout.title = dict(text="<b>Atomic mass heatmap</b>", x=0.4, y=0.94, font_size=20)
Expand Down Expand Up @@ -49,11 +48,11 @@

# %% ex 1: Electronegativity Heatmap with Custom Hover Data
fig = pmv.ptable_heatmap_plotly(
df_ptable[Key.electronegativity],
pmv.df_ptable[Key.electronegativity],
colorscale="Viridis",
hover_props=["atomic_mass", "melting_point"],
hover_data={
el: f"Fun fact about {el}!" for el in df_ptable[Key.electronegativity].index
el: f"Fun fact about {el}!" for el in pmv.df_ptable[Key.electronegativity].index
},
font_colors=["white", "black"],
colorbar=dict(title="Electronegativity", orientation="v"),
Expand All @@ -64,7 +63,7 @@

# %% ex 2: Log-scale Abundance with Excluded Elements
fig = pmv.ptable_heatmap_plotly(
df_ptable[Key.specific_heat_capacity].dropna(),
pmv.df_ptable[Key.specific_heat_capacity].dropna(),
# colorscale="YlOrRd",
log=True,
font_colors=["black"],
Expand All @@ -80,7 +79,7 @@

# %% ex 3: Fictional Data with Percent Mode and Custom Color Scale
rand_data = {
elem: np.random.default_rng(seed=0).random() * 100 for elem in df_ptable.index
elem: np.random.default_rng(seed=0).random() * 100 for elem in pmv.df_ptable.index
}
custom_colorscale = [
(0, "rgb(0,0,255)"),
Expand Down Expand Up @@ -116,10 +115,11 @@

# %% ex 5: Atomic Radius with Custom Hover and Label Mapping
fig = pmv.ptable_heatmap_plotly(
df_ptable[Key.atomic_radius],
pmv.df_ptable[Key.atomic_radius],
colorscale="RdYlBu",
hover_data={
elem: f"{radius} pm" for elem, radius in df_ptable[Key.atomic_radius].items()
elem: f"{radius} pm"
for elem, radius in pmv.df_ptable[Key.atomic_radius].items()
},
font_colors=["black"],
colorbar=dict(title="Atomic Radius (pm)"),
Expand Down
4 changes: 2 additions & 2 deletions assets/scripts/structure_viz/structure_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@
site.species = {"Zr": 0.5, "Hf": 0.5}

ax = cast(plt.Axes, pmv.structure_2d(struct))
_, spacegroup = struct.get_space_group_info()
spg_num = struct.get_symmetry_dataset(backend="moyopy")["number"]

formula = struct.formula.replace(" ", "")
text = f"{formula}\ndisordered {mp_id}, {spacegroup = }"
text = f"{formula}\ndisordered {mp_id}, {spg_num = }"
href = f"https://materialsproject.org/materials/{mp_id}"
ax.text(
0.5, 1, text, url=href, ha="center", transform=ax.transAxes, fontweight="bold"
Expand Down
15 changes: 11 additions & 4 deletions assets/scripts/sunburst/spacegroup_sunburst.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,25 @@
# %%
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])
df_phonons[Key.spg_num] = [
struct.get_symmetry_dataset(backend="moyopy", return_raw_dataset=True).number
for struct in tqdm(df_phonons[Key.structure])
]

df_phonons[Key.spg_symbol] = df_phonons[Key.spg_num].map(
pmv.utils.spg_num_to_from_symbol
)


# %% Sunburst Plots
fig = pmv.spacegroup_sunburst(df_phonons[Key.spg_num], show_counts="percent")
title = "Matbench Phonons Spacegroup Sunburst"
fig.layout.title = dict(text=f"<b>{title}</b>", x=0.5, y=0.96, font_size=18)
pmv.io.save_and_compress_svg(fig, "spg-num-sunburst")
fig.show()
# pmv.io.save_and_compress_svg(fig, "spg-num-sunburst")

fig = pmv.spacegroup_sunburst(df_phonons[Key.spg_symbol], show_counts="percent")
title = "Matbench Phonons Spacegroup Symbols Sunburst"
fig.layout.title = dict(text=f"<b>{title}</b>", x=0.5, y=0.96, font_size=18)
pmv.io.save_and_compress_svg(fig, "spg-symbol-sunburst")
fig.show()
# pmv.io.save_and_compress_svg(fig, "spg-symbol-sunburst")
6 changes: 1 addition & 5 deletions examples/dataset_exploration/camd_2022/explore_camd_2022.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@

import pandas as pd
import requests
from moyopy import SpaceGroupType

import pymatviz as pmv
from pymatviz.enums import Key


# %% Download data (if needed)
Expand Down Expand Up @@ -56,8 +54,6 @@


# %%
df_camd[Key.spg_num] = [SpaceGroupType(spg).number for spg in df_camd.space_group]

fig = pmv.spacegroup_sunburst(df_camd[Key.spg_num], show_counts="percent")
fig = pmv.spacegroup_sunburst(df_camd.space_group, show_counts="percent")
pmv.save_fig(fig, "camd-2022-spacegroup-sunburst.pdf")
fig.show()
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@
]
df_diel[n_wyckoff_pos_key] = df_diel[proto_label_key].map(count_wyckoff_positions)

df_diel[Key.crystal_system] = df_diel[Key.spg_num].map(
pmv.utils.crystal_sys_from_spg_num
)
df_diel[Key.crystal_system] = df_diel[Key.spg_num].map(pmv.utils.spg_to_crystal_sys)

df_diel[Key.volume] = [x.volume for x in df_diel[Key.structure]]
df_diel[Key.formula] = [x.formula for x in df_diel[Key.structure]]
Expand All @@ -61,7 +59,7 @@
fig = pmv.spacegroup_bar(df_diel[Key.spg_num])
fig.layout.title.update(text="<b>Space group histogram</b>")
fig.layout.margin.update(b=10, l=10, r=10, t=50)
# pmv.save_fig(ax, "dielectric-spacegroup-hist.pdf")
# pmv.save_fig(fig, "dielectric-spacegroup-hist.pdf")
fig.show()


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
fig.layout.title.update(text=title, x=0.5)
fig.layout.showlegend = False
fig.show()
# pmv.save_fig(ax, "jdft2d-exfoliation-energy-hist.pdf")
# pmv.save_fig(fig, "jdft2d-exfoliation-energy-hist.pdf")


# %%
Expand All @@ -56,12 +56,12 @@
fig.layout.title.update(text=title, y=0.98)
fig.layout.margin.update(b=10, l=10, r=10, t=70)
fig.show()
# pmv.save_fig(ax, "jdft2d-spacegroup-hist.pdf")
# pmv.save_fig(fig, "jdft2d-spacegroup-hist.pdf")


# %%
fig = pmv.spacegroup_sunburst(df_2d[Key.spg_num], show_counts="percent")
fig.layout.title.update(text="Spacegroup sunburst of the JARVIS DFT 2D dataset", x=0.5)
fig.layout.margin.update(b=0, l=0, r=0, t=40)
fig.show()
# fig.write_image("jdft2d-spacegroup-sunburst.pdf")
# pmv.save_fig(fig, "jdft2d-spacegroup-sunburst.pdf")
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
from time import perf_counter

import numpy as np
import pandas as pd
import plotly.express as px
from aviary.wren.utils import (
from matbench_discovery.structure.prototype import (
count_wyckoff_positions,
get_protostructure_label_from_spglib,
get_protostructure_label,
)
from matminer.datasets import load_dataset
from pymatgen.core import Structure
Expand All @@ -30,36 +31,33 @@
df_grvh = load_dataset("matbench_log_gvrh")
df_kvrh = load_dataset("matbench_log_kvrh")

# getting space group symbols and numbers for 10,987 structures takes about 45 sec
df_grvh[[Key.spg_symbol, Key.spg_num]] = [
struct.get_space_group_info()
for struct in tqdm(
df_grvh[Key.structure], desc="Getting matbench_log_gvrh spacegroups"
)
]
df_grvh[Key.crystal_system] = df_grvh[Key.spg_num].map(
pmv.utils.crystal_sys_from_spg_num
df_sym = pd.DataFrame(
struct.get_symmetry_dataset(backend="moyopy", return_raw_dataset=True).as_dict()
for struct in df_grvh[Key.structure]
)
df_sym[Key.crystal_system] = df_sym["number"].map(pmv.utils.spg_to_crystal_sys)
df_grvh[Key.protostructure] = [
get_protostructure_label(struct)
for struct in tqdm(df_grvh[Key.structure], desc="matbench_log_gvrh Wyckoff strings")
]
df_kvrh[Key.protostructure] = df_grvh[Key.protostructure]

for df in (df_grvh, df_kvrh):
df[[Key.spg_num, Key.wyckoff_symbols]] = df_sym[["number", "wyckoffs"]]
df[Key.crystal_system] = df_sym[Key.crystal_system]

df_grvh[Key.wyckoff] = [
get_protostructure_label_from_spglib(struct)
for struct in tqdm(
df_grvh[Key.structure], desc="Getting matbench_log_gvrh Wyckoff strings"
)
]
df_grvh[Key.n_wyckoff_pos] = df_grvh.wyckoff.map(count_wyckoff_positions)
df_grvh[Key.formula] = [x.formula for x in df_grvh[Key.structure]]
df[Key.n_wyckoff_pos] = df[Key.protostructure].map(count_wyckoff_positions)
df[Key.formula] = [x.formula for x in df[Key.structure]]


# %%
print("Number of materials with shear modulus of 0:")
print(sum(df_grvh["log10(G_VRH)"] == 0)) # sum is 31
print(sum(df_grvh["log10(G_VRH)"] == 0)) # expect 31


# %%
print("Number of materials with bulk modulus of 0:")
print(sum(df_kvrh["log10(K_VRH)"] == 0)) # sum is 14
print(sum(df_kvrh["log10(K_VRH)"] == 0)) # expect 14


# %%
Expand All @@ -78,7 +76,7 @@
fig.layout.title.update(text=title, x=0.5)
fig.layout.showlegend = False
fig.show()
# pmv.save_fig(ax, "log_gvrh-volume-hist.pdf")
# pmv.save_fig(fig, "gvrh-volume-hist.pdf")


# %%
Expand Down Expand Up @@ -137,7 +135,7 @@ def has_isolated_atom(crystal: Structure, radius: float = 5) -> bool:
title = "<b>Element counts in the Matbench<br>bulk/shear modulus datasets</b>"
fig.layout.title.update(text=title)
fig.show()
# pmv.save_fig(fig, "log_gvrh-ptable-heatmap.pdf")
# pmv.save_fig(fig, "gvrh-ptable-heatmap.pdf")


# %%
Expand All @@ -147,14 +145,14 @@ def has_isolated_atom(crystal: Structure, radius: float = 5) -> bool:
text="Spacegroup histogram of the Matbench bulk/shear modulus datasets"
)
fig.show()
# pmv.save_fig(ax, "log_gvrh-spacegroup-hist.pdf")
# pmv.save_fig(fig, "gvrh-spacegroup-hist.pdf")


# %%
fig = pmv.spacegroup_sunburst(df_grvh[Key.spg_num], show_counts="percent")
title = "Spacegroup sunburst of the Matbench bulk/shear modulus datasets"
fig.layout.title.update(text=title, x=0.5)
# fig.write_image("log_gvrh-spacegroup-sunburst.pdf")
# pmv.save_fig(fig, "gvrh-spacegroup-sunburst.pdf")
fig.show()


Expand Down Expand Up @@ -199,4 +197,4 @@ def rgb_color(val: float, max_val: float) -> str:
fig.layout.update(width=1000, height=400)
fig.layout.xaxis = dict(tickvals=list(range(7)), ticktext=list(x_ticks.values()))
fig.show()
# fig.write_image("log_grvh-violin-num-wyckoffs.pdf")
# pmv.save_fig(fig, "grvh-violin-num-wyckoffs.pdf")
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
fig.layout.title.update(text=title, x=0.5)
fig.layout.showlegend = False
fig.show()
# pmv.save_fig(ax, "mp_e_form_hist.pdf")
# pmv.save_fig(fig, "mp-e-form-hist.pdf")


# %%
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
fig.layout.title.update(text=title, x=0.5)
fig.layout.showlegend = False
fig.show()
# pmv.save_fig(ax, "pbe_gap_hist.pdf")
# pmv.save_fig(fig, "pbe-gap-hist.pdf")


# %%
Expand All @@ -47,4 +47,4 @@
fig.layout.title.update(text=title, x=0.5)
fig.layout.showlegend = False
fig.show()
# pmv.save_fig(ax, "volume_per_atom_hist.pdf")
# pmv.save_fig(fig, "volume-per-atom-hist.pdf")
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,15 @@

df_perov[Key.formula] = df_perov[Key.structure].map(lambda cryst: cryst.formula)

df_perov[Key.crystal_system] = df_perov[Key.spg_num].map(
pmv.utils.crystal_sys_from_spg_num
)
df_perov[Key.crystal_system] = df_perov[Key.spg_num].map(pmv.utils.spg_to_crystal_sys)


# %%
fig = pmv.structure_2d_plotly(df_perov[Key.structure].iloc[:12])
fig.layout.title.update(text="Perovskite structures in Matbench Perovskites dataset")
fig.layout.paper_bgcolor = "white"
fig.show()
# pmv.save_fig(ax, "perovskite-structures-2d.pdf")
# pmv.save_fig(fig, "perovskite-structures-2d.pdf")


# %%
Expand All @@ -51,7 +49,7 @@
)
fig.layout.showlegend = False
fig.show()
# pmv.save_fig(ax, "perovskites-e_form-hist.pdf")
# pmv.save_fig(fig, "perovskites-e_form-hist.pdf")


# %%
Expand All @@ -67,7 +65,7 @@
pmv.powerups.annotate_bars(fig, v_offset=250)

fig.show()
# pmv.save_fig(ax, "perovskites-crystal-system-counts.pdf")
# pmv.save_fig(fig, "perovskites-crystal-system-counts.pdf")


# %%
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
text="Last phonon DOS peak histogram of Matbench Phonons dataset"
)
fig.show()
# pmv.save_fig(ax, "phonons-last-dos-peak-hist.pdf")
# pmv.save_fig(fig, "phonons-last-dos-peak-hist.pdf")


# %%
Expand Down
Loading

0 comments on commit afcbdb8

Please sign in to comment.