-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathchem_env_treemap.py
More file actions
163 lines (134 loc) · 5.09 KB
/
chem_env_treemap.py
File metadata and controls
163 lines (134 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
"""Coordination Number (CN) and Coordination Environment (CE) treemap examples."""
# %%
from __future__ import annotations
import gzip
import json
import os
import time
from glob import glob
from pymatgen.core import Structure
import pymatviz as pmv
from pymatviz.enums import Key
from pymatviz.utils import ROOT
from pymatviz.utils.testing import TEST_FILES
# %% Load structures
structure_dir = f"{TEST_FILES}/structures"
structures = [
Structure.from_file(file_name) for file_name in glob(f"{structure_dir}/*.json.gz")
]
# %% Example 1: Method Comparison with Performance Analysis
# Compare CrystalNN (fast) vs ChemEnv (accurate) methods with timing
test_structure = structures[2]
# Time ChemEnv method
start_time = time.perf_counter()
fig_chem_env = pmv.chem_env_treemap(test_structure, chem_env_settings="chemenv")
chem_env_time = time.perf_counter() - start_time
# Time CrystalNN method
start_time = time.perf_counter()
fig_crystal_nn = pmv.chem_env_treemap(test_structure, chem_env_settings="crystal_nn")
crystal_nn_time = time.perf_counter() - start_time
print(f"ChemEnv time: {chem_env_time:.3f} seconds")
print(f"CrystalNN time: {crystal_nn_time:.3f} seconds")
print(f"Speed improvement: {chem_env_time / crystal_nn_time:.1f}x faster")
fig_chem_env.layout.title = f"ChemEnv Analysis (Accurate) - {test_structure.formula}"
fig_crystal_nn.layout.title = f"CrystalNN Analysis (Fast) - {test_structure.formula}"
fig_chem_env.show()
fig_crystal_nn.show()
# %% Example 2: Advanced Features - Normalization, Limiting, and Custom Formatting
# Demonstrate key functional features in one comprehensive example
def custom_cn_formatter(coord_num: int | str, count: float, total: float) -> str:
"""Custom formatter showing detailed statistics."""
return f"CN-{coord_num}: {count:.1f} sites ({count / total:.1%})"
fig_advanced = pmv.chem_env_treemap(
structures[:4],
normalize=True, # Normalize counts per structure
max_cells_cn=3, # Limit to top 3 coordination numbers
max_cells_ce=2, # Limit to top 2 environments per CN
cn_formatter=custom_cn_formatter, # Custom label formatting
show_counts="value+percent", # Show both values and percentages
chem_env_settings="crystal_nn", # Use fast method for demo
)
title = (
"<b>Advanced Features Demo</b><br>"
"<sub>Normalized + Limited (Top 3 CNs, Top 2 CEs) + Custom Formatting</sub>"
)
fig_advanced.layout.title = dict(text=title, x=0.5, y=0.95, font_size=16)
fig_advanced.show()
# %% Example 3: Real-world Data - Elemental Carbon from Materials Project
# Demonstrate usage with actual crystallographic data
json_path = f"{ROOT}/tmp/mp-carbon-structures.json.gz"
if os.path.isfile(json_path):
with gzip.open(json_path, mode="rt") as file:
docs = json.load(file)
for doc in docs:
doc["structure"] = Structure.from_dict(doc["structure"])
else:
try:
from mp_api.client import MPRester
except ImportError:
# Create dummy data if Materials Project API not available
docs = [{"structure": structures[0]} for _ in range(3)]
else:
with MPRester(use_document_model=False) as mpr:
docs = mpr.materials.summary.search(
elements=["C"],
num_elements=[1, 1],
fields=[Key.mat_id, Key.structure, Key.formula_pretty],
)
with gzip.open(json_path, mode="wt") as file:
json.dump(
docs,
file,
default=lambda x: x.as_dict() if hasattr(x, "as_dict") else x,
)
fig_carbon = pmv.chem_env_treemap(
[doc["structure"] for doc in docs],
max_cells_cn=5,
max_cells_ce=4,
show_counts="value+percent",
chem_env_settings="crystal_nn",
)
title = (
"<b>Real-world Example: Elemental Carbon Structures</b><br>"
"<sub>Coordination environments in carbon allotropes from Materials Project</sub>"
)
fig_carbon.layout.title = dict(text=title, x=0.5, y=0.95, font_size=16)
fig_carbon.layout.update(height=600, width=800)
fig_carbon.show()
# %% Example 4: Styling and Interactivity
# Showcase visual customization and enhanced user interaction
fig_styled = pmv.chem_env_treemap(
structures,
max_cells_cn=4,
max_cells_ce=3,
show_counts="value",
chem_env_settings="crystal_nn",
)
# Apply comprehensive styling and interactivity
fig_styled.update_traces(
marker=dict(
cornerradius=8,
colorscale="Viridis",
line=dict(color="white", width=2),
),
textfont=dict(size=11, color="white"),
textinfo="label+value",
hovertemplate=(
"<b>%{label}</b><br>"
"Count: %{value}<br>"
"% of parent: %{percentEntry:.1%}<br>"
"% of total: %{percentRoot:.1%}<br>"
"<extra></extra>"
),
maxdepth=2,
)
title = (
"<b>Styled & Interactive Treemap</b><br>"
"<sub>Custom colors, rounded corners, enhanced hover info</sub>"
)
fig_styled.layout.title = dict(text=title, x=0.5, y=0.95, font_size=16)
fig_styled.layout.update(
height=700, width=900, font=dict(size=12), plot_bgcolor="rgba(248,249,250,0.8)"
)
fig_styled.show()
pmv.io.save_and_compress_svg(fig_styled, "chem-env-treemap-styled")