Skip to content

Commit 73bf7f8

Browse files
authored
Add IS_IPYTHON global (#198)
* add IS_IPYTHON global * fix outdated function names in readme * breaking: remove structure_2d()'s deprecated colors kwarg, now only elem_colors works * fix test_structure_2d_color_warning
1 parent 368bf1d commit 73bf7f8

File tree

9 files changed

+61
-48
lines changed

9 files changed

+61
-48
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ default_install_hook_types: [pre-commit, commit-msg]
88

99
repos:
1010
- repo: https://github.com/astral-sh/ruff-pre-commit
11-
rev: v0.6.3
11+
rev: v0.6.4
1212
hooks:
1313
- id: ruff
1414
args: [--fix]
@@ -88,6 +88,6 @@ repos:
8888
- typescript-eslint
8989

9090
- repo: https://github.com/RobertCraigie/pyright-python
91-
rev: v1.1.378
91+
rev: v1.1.379
9292
hooks:
9393
- id: pyright
File renamed without changes.

examples/make_assets/histogram.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,4 @@
5454
pmv.powerups.add_ecdf_line(fig, trace_idx=idx)
5555
fig.show()
5656

57-
pmv.io.save_and_compress_svg(fig, "plot-histogram-ecdf")
57+
pmv.io.save_and_compress_svg(fig, "histogram-ecdf")

pymatviz/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@
9494
pass # package not installed
9595

9696

97+
IS_IPYTHON = hasattr(__builtins__, "__IPYTHON__")
98+
9799
# define a sensible order for crystal systems across plots
98100
crystal_sys_order = (
99101
"cubic hexagonal trigonal tetragonal orthorhombic monoclinic triclinic".split()
@@ -104,7 +106,6 @@
104106
}
105107
spg_num_to_symbol = dict(sorted(spg_num_to_symbol.items())) # sort
106108

107-
108109
px.defaults.labels |= {
109110
"gap expt": "Experimental band gap (eV)",
110111
} | Key.val_label_dict()

pymatviz/structure_viz.py

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""2D plots of pymatgen structures with matplotlib.
22
3-
plot_structure_2d() and its helpers get_rot_matrix() and unit_cell_to_lines() were
3+
structure_2d() and its helpers get_rot_matrix() and unit_cell_to_lines() were
44
inspired by ASE https://wiki.fysik.dtu.dk/ase/ase/visualize/visualize.html#matplotlib.
55
"""
66

@@ -138,7 +138,6 @@ def structure_2d(
138138
n_cols: int = 4,
139139
subplot_kwargs: dict[str, Any] | None = None,
140140
subplot_title: Callable[[Structure, str | int], str] | None = None,
141-
**kwargs: Any,
142141
) -> plt.Axes | tuple[plt.Figure, np.ndarray[plt.Axes]]:
143142
"""Plot pymatgen structures in 2D with matplotlib.
144143
@@ -161,22 +160,22 @@ def structure_2d(
161160
plot_atoms(AseAtomsAdaptor().get_atoms(mp_19017), rotation="10x,10y,0z", radii=0.5)
162161
163162
# pymatviz
164-
from pymatviz import plot_structure_2d
163+
from pymatviz import structure_2d
165164
166-
plot_structure_2d(mp_19017)
165+
structure_2d(mp_19017)
167166
```
168167
169168
Multiple structures in single figure example:
170169
171170
```py
172171
from pymatgen.ext.matproj import MPRester
173-
from pymatviz import plot_structure_2d
172+
from pymatviz import structure_2d
174173
175174
structures = {
176175
(mp_id := f"mp-{idx}"): MPRester().get_structure_by_material_id(mp_id)
177176
for idx in range(1, 5)
178177
}
179-
plot_structure_2d(structures)
178+
structure_2d(structures)
180179
```
181180
182181
Args:
@@ -228,22 +227,13 @@ class used to plot chemical bonds. Allowed are edgecolor, facecolor, color,
228227
subplot titles. Receives the structure and its key or index when passed as
229228
a dict or pandas.Series. Defaults to None in which case the title is the
230229
structure's material id if available, otherwise its formula and space group.
231-
**kwargs: Unused.
232230
233231
Raises:
234232
ValueError: On invalid site_labels.
235233
236234
Returns:
237235
plt.Axes: matplotlib Axes instance with plotted structure.
238236
"""
239-
if "colors" in kwargs:
240-
warnings.warn(
241-
"plot_structure_2d's colors keyword was deprecated on 2024-07-06 and will "
242-
"be removed soon. Use 'elem_colors' instead.",
243-
DeprecationWarning,
244-
stacklevel=2,
245-
)
246-
elem_colors = kwargs.pop("colors")
247237
if isinstance(struct, Structure):
248238
ax = ax or plt.gca()
249239

@@ -382,11 +372,13 @@ class used to plot chemical bonds. Allowed are edgecolor, facecolor, color,
382372
fallback_color = "gray"
383373
face_color = elem_colors.get(elem_symbol, fallback_color)
384374
if elem_symbol not in elem_colors:
385-
warnings.warn(
386-
f"{elem_symbol=} not in colors, using {fallback_color}",
387-
UserWarning,
388-
stacklevel=2,
375+
elem_color_symbols = ", ".join(elem_colors)
376+
warn_msg = (
377+
f"{elem_symbol=} not in elem_colors, using "
378+
f"{fallback_color=}\nelement color palette specifies the "
379+
f"following elements: {elem_color_symbols}"
389380
)
381+
warnings.warn(warn_msg, UserWarning, stacklevel=2)
390382
wedge = Wedge(
391383
xy,
392384
radius,
@@ -456,7 +448,7 @@ class used to plot chemical bonds. Allowed are edgecolor, facecolor, color,
456448

457449
if show_bonds:
458450
warnings.warn(
459-
"Warning: the show_bonds feature of plot_structure_2d() is "
451+
"Warning: the show_bonds feature of structure_2d() is "
460452
"experimental. Issues and PRs with improvements welcome.",
461453
category=ExperimentalWarning,
462454
stacklevel=2,
@@ -472,8 +464,8 @@ class used to plot chemical bonds. Allowed are edgecolor, facecolor, color,
472464

473465
# If structure doesn't have any oxidation states yet, guess them from
474466
# chemical composition. Use CrystalNN and other strategies to better
475-
# estimate bond connectivity. Use getattr on site.specie since it's often a
476-
# pymatgen Element which has no oxi_state
467+
# estimate bond connectivity. Use hasattr("oxi_state") on site.specie since
468+
# it's often a pymatgen Element which has no oxi_state
477469
if not any(
478470
hasattr(getattr(site, "specie", None), "oxi_state") for site in struct
479471
):

readme.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,11 @@ See [`pymatviz/ptable/ptable_matplotlib.py`](pymatviz/ptable/ptable_matplotlib.p
7777

7878
See [`examples/mlff_phonons.ipynb`](https://github.com/janosh/pymatviz/blob/main/examples/mlff_phonons.ipynb) for usage example.
7979

80-
| [`plot_phonon_bands(bands_dict)`](pymatviz/phonons.py) | [`plot_phonon_dos(doses_dict)`](pymatviz/phonons.py) |
81-
| :------------------------------------------------------------------------: | :--------------------------------------------------------------------------: |
82-
| ![phonon-bands] | ![phonon-dos] |
83-
| [`plot_phonon_bands_and_dos(bands_dict, doses_dict)`](pymatviz/phonons.py) | [`plot_phonon_bands_and_dos(single_bands, single_dos)`](pymatviz/phonons.py) |
84-
| ![phonon-bands-and-dos-mp-2758] | ![phonon-bands-and-dos-mp-23907] |
80+
| [`phonon_bands(bands_dict)`](pymatviz/phonons.py) | [`phonon_dos(doses_dict)`](pymatviz/phonons.py) |
81+
| :-------------------------------------------------------------------: | :---------------------------------------------------------------------: |
82+
| ![phonon-bands] | ![phonon-dos] |
83+
| [`phonon_bands_and_dos(bands_dict, doses_dict)`](pymatviz/phonons.py) | [`phonon_bands_and_dos(single_bands, single_dos)`](pymatviz/phonons.py) |
84+
| ![phonon-bands-and-dos-mp-2758] | ![phonon-bands-and-dos-mp-23907] |
8585

8686
[phonon-bands]: https://github.com/janosh/pymatviz/raw/main/assets/phonon-bands-mp-2758.svg
8787
[phonon-dos]: https://github.com/janosh/pymatviz/raw/main/assets/phonon-dos-mp-2758.svg
@@ -114,9 +114,9 @@ See [`pymatviz/sankey.py`](pymatviz/sankey.py).
114114

115115
See [`pymatviz/structure_viz.py`](pymatviz/structure_viz.py). Currently structure plotting is only supported with `matplotlib` in 2d. 3d interactive plots (probably with `plotly`) are on the road map.
116116

117-
| [`plot_structure_2d(mp_19017)`](pymatviz/structure_viz.py) | [`plot_structure_2d(mp_12712)`](pymatviz/structure_viz.py) |
118-
| :--------------------------------------------------------: | :--------------------------------------------------------: |
119-
| ![struct-2d-mp-19017-Li4Mn0.8Fe1.6P4C1.6O16-disordered] | ![struct-2d-mp-12712-Hf9Zr9Pd24-disordered] |
117+
| [`structure_2d(mp_19017)`](pymatviz/structure_viz.py) | [`structure_2d(mp_12712)`](pymatviz/structure_viz.py) |
118+
| :-----------------------------------------------------: | :---------------------------------------------------: |
119+
| ![struct-2d-mp-19017-Li4Mn0.8Fe1.6P4C1.6O16-disordered] | ![struct-2d-mp-12712-Hf9Zr9Pd24-disordered] |
120120

121121
![matbench-phonons-structures-2d]
122122

@@ -129,14 +129,14 @@ See [`pymatviz/histogram.py`](pymatviz/histogram.py).
129129
| ![spg-num-hist-matplotlib] | ![spg-symbol-hist-matplotlib] |
130130
| [`spacegroup_bar([65, 134, 225, ...], backend="plotly")`](pymatviz/histogram.py) | [`spacegroup_bar(["C2/m", "P-43m", "Fm-3m", ...], backend="plotly")`](pymatviz/histogram.py) |
131131
| ![spg-num-hist-plotly] | ![spg-symbol-hist-plotly] |
132-
| [`elements_hist(compositions, log=True, bar_values='count')`](pymatviz/histogram.py) | [`plot_histogram({'key1': values1, 'key2': values2})`](pymatviz/histogram.py) |
133-
| ![elements-hist] | ![plot-histogram-ecdf] |
132+
| [`elements_hist(compositions, log=True, bar_values='count')`](pymatviz/histogram.py) | [`histogram({'key1': values1, 'key2': values2})`](pymatviz/histogram.py) |
133+
| ![elements-hist] | ![histogram-ecdf] |
134134

135135
[spg-symbol-hist-plotly]: https://github.com/janosh/pymatviz/raw/main/assets/spg-symbol-hist-plotly.svg
136136
[spg-num-hist-plotly]: https://github.com/janosh/pymatviz/raw/main/assets/spg-num-hist-plotly.svg
137137
[spg-num-hist-matplotlib]: https://github.com/janosh/pymatviz/raw/main/assets/spg-num-hist-matplotlib.svg
138138
[spg-symbol-hist-matplotlib]: https://github.com/janosh/pymatviz/raw/main/assets/spg-symbol-hist-matplotlib.svg
139-
[plot-histogram-ecdf]: https://github.com/janosh/pymatviz/raw/main/assets/plot-histogram-ecdf.svg
139+
[histogram-ecdf]: https://github.com/janosh/pymatviz/raw/main/assets/histogram-ecdf.svg
140140

141141
## Scatter Plots
142142

@@ -161,9 +161,9 @@ See [`pymatviz/scatter.py`](pymatviz/scatter.py).
161161

162162
See [`pymatviz/xrd.py`](pymatviz/xrd.py).
163163

164-
| [`plot_xrd_pattern(pattern)`](pymatviz/xrd.py) | [`plot_xrd_pattern({key1: patt1, key2: patt2})`](pymatviz/xrd.py) |
165-
| :--------------------------------------------: | :---------------------------------------------------------------: |
166-
| ![xrd-pattern] | ![xrd-pattern-multiple] |
164+
| [`xrd_pattern(pattern)`](pymatviz/xrd.py) | [`xrd_pattern({key1: patt1, key2: patt2})`](pymatviz/xrd.py) |
165+
| :---------------------------------------: | :----------------------------------------------------------: |
166+
| ![xrd-pattern] | ![xrd-pattern-multiple] |
167167

168168
[xrd-pattern]: https://github.com/janosh/pymatviz/raw/main/assets/xrd-pattern.svg
169169
[xrd-pattern-multiple]: https://github.com/janosh/pymatviz/raw/main/assets/xrd-pattern-multiple.svg

tests/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"""pymatviz tests."""
1+
"""pymatviz test suite."""

tests/test_pkg.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from importlib.metadata import version
88
from types import ModuleType
99

10-
from pymatviz import PKG_DIR, PKG_NAME, __version__
10+
from pymatviz import IS_IPYTHON, PKG_DIR, PKG_NAME, __version__
1111

1212

1313
def test_pkg_metadata() -> None:
@@ -73,3 +73,7 @@ def test_all_modules_reexported() -> None:
7373

7474
finally:
7575
sys.modules[PKG_NAME] = pymatviz
76+
77+
78+
def test_is_ipython() -> None:
79+
assert not IS_IPYTHON

tests/test_structure_viz.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from pymatgen.core import Structure
1111

1212
import pymatviz as pmv
13+
from pymatviz.colors import ELEM_COLORS_JMOL, ELEM_COLORS_VESTA
1314
from pymatviz.enums import ElemColorScheme, Key
1415

1516

@@ -165,20 +166,35 @@ def subplot_title(struct: Structure, key: str | int) -> str:
165166

166167
def test_structure_2d_color_warning() -> None:
167168
# Copernicium is not in the default color scheme
168-
copernicium = "Cn"
169-
struct = Structure(np.eye(3) * 5, [copernicium] * 2, coords=coords)
169+
elem_symbol = "Cn"
170+
struct = Structure(np.eye(3) * 5, [elem_symbol] * 2, coords=coords)
171+
fallback_color = "gray"
172+
173+
for elem_colors in ElemColorScheme:
174+
if elem_colors == ElemColorScheme.jmol:
175+
elem_color_symbols = ", ".join(ELEM_COLORS_JMOL)
176+
elif elem_colors == ElemColorScheme.vesta:
177+
elem_color_symbols = ", ".join(ELEM_COLORS_VESTA)
178+
else:
179+
raise ValueError(f"Unexpected {elem_colors=}")
170180

171-
for colors in ElemColorScheme:
172181
with pytest.warns(
173-
UserWarning, match=f"{copernicium!r} not in colors, using gray"
182+
UserWarning,
183+
match=f"{elem_symbol=} not in elem_colors, using "
184+
f"{fallback_color=}\nelement color palette specifies the "
185+
f"following elements: {elem_color_symbols}",
174186
):
175-
pmv.structure_2d(struct, elem_colors=colors)
187+
pmv.structure_2d(struct, elem_colors=elem_colors)
176188

177189
# create custom color scheme missing an element
178190
custom_colors = {"Fe": "red"}
179191
struct = Structure(np.eye(3) * 5, ["Fe", "O"], coords=coords)
180192

181-
with pytest.warns(UserWarning, match="'O' not in colors, using gray"):
193+
with pytest.warns(
194+
UserWarning,
195+
match="elem_symbol='O' not in elem_colors, using fallback_color='gray'\nelement"
196+
" color palette specifies the following elements: Fe",
197+
):
182198
pmv.structure_2d(struct, elem_colors=custom_colors)
183199

184200

0 commit comments

Comments
 (0)