Skip to content

Commit eb12217

Browse files
committed
better Key.unit formatting: replace unicode sup/superscripts with <sup>/<sub>+ASCII
- Improve unit formatting in enums.py to include HTML tags for sub/superscripts - keys.yml replace ASCII middle dot with proper Unicode character - Adjust border width in ptable_plotly.py for better visualization - more tests in test_enums.py and test_ptable_plotly.py
1 parent f834b78 commit eb12217

File tree

6 files changed

+250
-39
lines changed

6 files changed

+250
-39
lines changed

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ repos:
1717
types_or: [python, jupyter]
1818

1919
- repo: https://github.com/pre-commit/mirrors-mypy
20-
rev: v1.13.0
20+
rev: v1.14.0
2121
hooks:
2222
- id: mypy
2323
additional_dependencies: [types-requests, types-PyYAML]

pymatviz/enums.py

+73-2
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,78 @@ def label(self) -> str:
152152

153153
@property
154154
def unit(self) -> str | None:
155-
"""Unit associated with the key."""
156-
return _keys[self.value].get("unit")
155+
"""Unit associated with the key with HTML tags for sub/superscripts."""
156+
if not (unit := _keys[self.value].get("unit")):
157+
return None
158+
159+
# Map Unicode characters to their ASCII equivalents
160+
superscript_map = {
161+
"⁰": "0",
162+
"¹": "1",
163+
"²": "2",
164+
"³": "3",
165+
"⁴": "4",
166+
"⁵": "5",
167+
"⁶": "6",
168+
"⁷": "7",
169+
"⁸": "8",
170+
"⁹": "9",
171+
"⁻": "-",
172+
"½": "1/2",
173+
}
174+
subscript_map = {
175+
"₀": "0",
176+
"₁": "1",
177+
"₂": "2",
178+
"₃": "3",
179+
"₄": "4",
180+
"₅": "5",
181+
"₆": "6",
182+
"₇": "7",
183+
"₈": "8",
184+
"₉": "9",
185+
"₋": "-",
186+
"½": "1/2",
187+
}
188+
189+
# Process character by character
190+
html_str = ""
191+
in_super = in_sub = False
192+
193+
idx = 0
194+
while idx < len(unit):
195+
char = unit[idx]
196+
197+
# Check if character is superscript
198+
if new_char := superscript_map.get(char):
199+
if not in_super:
200+
html_str += "<sup>"
201+
in_super = True
202+
html_str += new_char
203+
# Check if character is subscript
204+
elif new_char := subscript_map.get(char):
205+
if not in_sub:
206+
html_str += "<sub>"
207+
in_sub = True
208+
html_str += new_char
209+
else:
210+
# Close any open tags
211+
if in_super:
212+
html_str += "</sup>"
213+
in_super = False
214+
if in_sub:
215+
html_str += "</sub>"
216+
in_sub = False
217+
html_str += char
218+
idx += 1
219+
220+
# Close any remaining open tags
221+
if in_super:
222+
html_str += "</sup>"
223+
if in_sub:
224+
html_str += "</sub>"
225+
226+
return html_str
157227

158228
@property
159229
def category(self) -> str:
@@ -296,6 +366,7 @@ def __reduce_ex__(self, proto: object) -> tuple[type, tuple[str]]:
296366
cohesive_energy_per_atom = "cohesive_energy_per_atom"
297367
heat_of_formation = "heat_of_formation"
298368
heat_of_reaction = "heat_of_reaction"
369+
e_form = "e_form"
299370
e_form_per_atom = "e_form_per_atom"
300371
e_form_pred = "e_form_pred"
301372
e_form_true = "e_form_true"

pymatviz/keys.yml

+17-11
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ electronic:
151151
mobility:
152152
label: Carrier Mobility
153153
symbol: μ
154-
unit: cm²/V·s
154+
unit: cm²/Vs
155155
effective_mass:
156156
label: Effective Mass
157157
symbol: m<sub>e</sub>
@@ -184,11 +184,11 @@ electronic:
184184
electron_mobility:
185185
label: Electron Mobility
186186
symbol: μ<sub>e</sub>
187-
unit: cm²/V·s
187+
unit: cm²/Vs
188188
hole_mobility:
189189
label: Hole Mobility
190190
symbol: μ<sub>h</sub>
191-
unit: cm²/V·s
191+
unit: cm²/Vs
192192

193193
thermodynamic:
194194
energy:
@@ -248,6 +248,11 @@ thermodynamic:
248248
symbol: E<sub>coh</sub>/N<sub>atoms</sub>
249249
unit: eV/atom
250250
description: Energy required to break crystal into isolated neutral atoms
251+
e_form:
252+
label: E<sub>form</sub>
253+
symbol: E<sub>form</sub>
254+
unit: eV/atom
255+
description: All-atoms formation energy relative to constituent element reference states
251256
e_form_per_atom:
252257
label: E<sub>form</sub>
253258
symbol: E<sub>form</sub>/N<sub>atoms</sub>
@@ -354,35 +359,35 @@ mechanical:
354359
fracture_toughness:
355360
label: Fracture Toughness
356361
symbol: K<sub>IC</sub>
357-
unit: MPa·m<sup>1/2</sup>
362+
unit: MPa⋅m½
358363
sound_velocity:
359364
label: Sound Velocity
360365
symbol: v<sub>s</sub>
361366
unit: m/s
362367
thermal_conductivity:
363368
label: Thermal Conductivity
364369
symbol: κ
365-
unit: W/m·K
370+
unit: W/mK
366371
thermal_expansion:
367372
label: Thermal Expansion
368373
symbol: α
369374
unit: 1/K
370375
lattice_thermal_conductivity:
371376
label: Lattice Thermal Conductivity
372377
symbol: κ<sub>lattice</sub>
373-
unit: W/m·K
378+
unit: W/mK
374379
electronic_thermal_conductivity:
375380
label: Electronic Thermal Conductivity
376381
symbol: κ<sub>electronic</sub>
377-
unit: W/m·K
382+
unit: W/mK
378383
heat_capacity:
379384
label: Heat Capacity
380385
symbol: C<sub>V</sub>
381386
unit: J/K
382387
specific_heat_capacity:
383388
label: Specific Heat Capacity
384389
symbol: c<sub>p</sub>
385-
unit: J/kg·K
390+
unit: J/kgK
386391
thermal_expansion_coefficient:
387392
label: Thermal Expansion Coefficient
388393
symbol: α<sub>thermal</sub>
@@ -398,7 +403,7 @@ mechanical:
398403
viscosity:
399404
label: Viscosity
400405
symbol: η
401-
unit: Pa·s
406+
unit: Pas
402407
strain:
403408
label: Strain
404409
symbol: ε
@@ -456,7 +461,7 @@ thermal:
456461
thermal_resistivity:
457462
label: Thermal Resistivity
458463
symbol: ρ<sub>th</sub>
459-
unit: K·m/W
464+
unit: Km/W
460465
description: Resistance to heat flow, inverse of thermal conductivity
461466
thermal_time_constant:
462467
label: Thermal Time Constant
@@ -473,7 +478,7 @@ magnetic:
473478
magnetic_moment:
474479
label: Magnetic Moment
475480
symbol: μ<sub>B</sub>
476-
unit: μB
481+
unit: μ<sub>B</sub>
477482
magmoms:
478483
label: Magnetic Moments
479484
symbol: μ
@@ -1134,6 +1139,7 @@ metrics:
11341139
volume_error:
11351140
label: Volume Error
11361141
symbol: V<sub>err</sub>
1142+
unit: ų
11371143
max_force_error:
11381144
label: Max Force Error
11391145
max_stress_error:

pymatviz/ptable/ptable_plotly.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ def ptable_heatmap_plotly(
312312
if border is not False:
313313
border = border or {}
314314
border_color = border.pop("color", "darkgray")
315-
border_width = border.pop("width", 2)
315+
border_width = border.pop("width", 0.5)
316316

317317
common_kwargs = dict(
318318
z=np.where(tile_texts, 1, np.nan), showscale=False, hoverinfo="none"

tests/ptable/plotly/test_ptable_plotly.py

+41
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,44 @@ def custom_colorscale(_element_symbol: str, _value: float, split_idx: int) -> st
170170
for trace in fig.data:
171171
# Each element tile should have a color array with custom colors
172172
assert trace.fillcolor in {"rgb(255,0,0)", "rgb(0,0,255)"}
173+
174+
175+
def test_ptable_heatmap_plotly_colorbar() -> None:
176+
"""Test colorbar customization in ptable_heatmap_plotly."""
177+
data = {"Fe": 1.234, "O": 5.678}
178+
179+
# Test colorbar title and formatting
180+
colorbar = dict(
181+
title="Test Title", tickformat=".2f", orientation="v", len=0.8, x=1.1
182+
)
183+
184+
fig = pmv.ptable_heatmap_plotly(data, colorbar=colorbar)
185+
186+
# Get the colorbar from the figure
187+
colorbar_trace = next(trace for trace in fig.data if hasattr(trace, "colorbar"))
188+
actual_colorbar = colorbar_trace.colorbar
189+
190+
# Check colorbar properties were set correctly
191+
assert actual_colorbar.title.text == "<br><br>Test Title"
192+
assert actual_colorbar.tickformat == ".2f"
193+
assert actual_colorbar.orientation == "v"
194+
assert actual_colorbar.len == 0.8
195+
assert actual_colorbar.x == 1.1
196+
197+
# Test horizontal colorbar title formatting
198+
h_colorbar = dict(title="Horizontal Title", orientation="h", y=0.8)
199+
200+
fig = pmv.ptable_heatmap_plotly(data, colorbar=h_colorbar)
201+
h_colorbar_trace = next(trace for trace in fig.data if hasattr(trace, "colorbar"))
202+
actual_h_colorbar = h_colorbar_trace.colorbar
203+
204+
# Check horizontal colorbar properties
205+
assert (
206+
actual_h_colorbar.title.text == "Horizontal Title<br>"
207+
) # Horizontal title has break after
208+
assert actual_h_colorbar.orientation == "h"
209+
assert actual_h_colorbar.y == 0.8
210+
211+
# Test disabling colorbar
212+
fig = pmv.ptable_heatmap_plotly(data, show_scale=False)
213+
assert not any(trace.showscale for trace in fig.data)

0 commit comments

Comments
 (0)