-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathpy_pkg_treemap.py
More file actions
153 lines (125 loc) · 5.69 KB
/
py_pkg_treemap.py
File metadata and controls
153 lines (125 loc) · 5.69 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
"""Demonstrate treemap visualizations of Python package structures.
This script shows how to create interactive treemaps visualizing module
structures of Python packages using the pmv.py_pkg_treemap function.
"""
# %%
from __future__ import annotations
import numpy as np
import plotly.express as px
import pymatgen
import pymatviz as pmv
pmv.set_plotly_template("plotly_white")
# %% Single packages with default settings
for pkg in ("pymatviz", np): # Mix strings and module objects
fig = pmv.py_pkg_treemap(pkg)
pkg_name = str(getattr(pkg, "__name__", pkg))
fig.layout.title.update(text=f"{pkg_name} Package Structure", font_size=20, x=0.5)
fig.show()
pmv.io.save_and_compress_svg(fig, f"py-pkg-treemap-{pkg_name.replace('_', '-')}")
# %% Compare multiple packages (with file/module filtering via cell_size_fn)
fig = pmv.py_pkg_treemap(
packages := ("pymatviz", np),
show_counts="value+percent",
# Only include files with at least 50 lines
cell_size_fn=lambda cell: cell.line_count if cell.line_count >= 50 else 0,
)
# Add customizations: rounded corners and custom hover
fig.update_traces(
marker=dict(cornerradius=5),
hovertemplate="<b>%{label}</b><br>Lines: %{value}<br>Percentage: "
"%{percentRoot:.1%} of total<extra></extra>",
)
pkg_names = [getattr(pkg, "__name__", pkg) for pkg in packages]
title = f"Comparing Package Structure: {', '.join(map(str, pkg_names))}"
fig.layout.title.update(text=title, x=0.5, font_size=20)
fig.show()
pmv.io.save_and_compress_svg(fig, "py-pkg-treemap-multiple")
# %% Different ways to group packages
for group_by, clr_scheme in (
("file", px.colors.qualitative.Set2),
("directory", px.colors.qualitative.Pastel1),
("module", px.colors.qualitative.Set3),
):
fig = pmv.py_pkg_treemap(
"pymatviz",
group_by=group_by,
show_counts="value",
color_discrete_sequence=clr_scheme,
# Only include files with at least 20 lines
cell_size_fn=lambda cell: cell.line_count if cell.line_count >= 20 else 0,
)
title = f"pymatviz Package Structure - Grouped by {group_by}"
fig.layout.title.update(text=title, x=0.5, y=0.97, font_size=18)
fig.show()
# %% Custom formatting of package names and line counts
def custom_module_formatter(module: str, count: int, _total: int) -> str:
"""Custom formatter that emphasizes the module name."""
return f"{module.upper()} [{count:,} lines]"
fig = pmv.py_pkg_treemap(
("numpy", "pymatviz"),
cell_text_fn=custom_module_formatter,
color_discrete_sequence=px.colors.qualitative.Bold,
)
fig.update_layout(
title=dict(text="Custom Package Name Formatting", x=0.5, y=0.97, font_size=18),
)
fig.show()
# %% Custom cell sizing by functions, classes, and methods
fig_custom_size = pmv.py_pkg_treemap(
"pymatviz",
cell_size_fn=lambda cell: cell.n_functions + cell.n_classes + cell.n_methods,
show_counts="value", # Show the custom calculated value
)
title = "pymatviz: Cell size by (functions + classes + methods)"
fig_custom_size.layout.title.update(text=title, x=0.5, y=0.97, font_size=18)
fig_custom_size.update_traces(
hovertemplate="<b>%{label}</b><br>" # Use label from path
"Classes: %{customdata[4]:,}<br>" # n_classes is at customdata[4]
"Functions: %{customdata[5]:,}<br>" # n_functions is at customdata[5]
"Methods: %{customdata[9]:,}<br>" # n_methods is at customdata[9]
"Lines: %{customdata[11]:,}<br>" # line_count is at customdata[11]
"Cell Value (Func+Class+Meth): %{value:,}<br>" # value is the result of calculator
"<extra></extra>",
)
fig_custom_size.show()
# %% pymatviz treemap with coverage heatmap (cell size by lines, color by test coverage)
coverage_data_file = "https://github.com/janosh/pymatviz/releases/download/v0.17.5/2026-03-31-pymatviz-coverage.json"
fig_cov = pmv.py_pkg_treemap(
"pymatviz",
color_by="coverage",
coverage_data_file=coverage_data_file,
cell_size_fn=lambda cell: cell.line_count if cell.line_count >= 20 else 0,
show_counts="value",
color_continuous_scale="RdYlGn", # Red-Yellow-Green scale for coverage
)
title = "pymatviz: Coverage Heatmap (Cell size by lines, Color by test coverage)"
fig_cov.layout.title.update(text=title, x=0.5, y=0.97, font_size=18)
fig_cov.show()
pmv.io.save_and_compress_svg(fig_cov, "py-pkg-treemap-pymatviz-coverage")
# %% pymatgen treemap with coverage heatmap and manual color range (0-100%)
coverage_data_file = "https://github.com/user-attachments/files/21545087/2025-07-31-pymatgen-coverage.json"
# coverage_data_file = f"{pmv.ROOT}/tmp/2025-07-31-pymatgen-coverage.json"
# Namespace packages have their own repos and coverage reports, so they show
# as 0% coverage here which is misleading. Exclude them.
NAMESPACE_PKGS = {"analysis.defects", "analysis.diffusion"}
def _pmg_cell_size(cell: pmv.treemap.py_pkg.ModuleStats) -> int:
"""Filter out namespace packages and tiny files."""
dotted = f".{cell.full_module}."
if any(f".{ns_pkg}." in dotted for ns_pkg in NAMESPACE_PKGS):
return 0
return cell.line_count if cell.line_count >= 20 else 0
fig_cov_range = pmv.py_pkg_treemap(
pymatgen,
color_by="coverage",
coverage_data_file=coverage_data_file, # Use existing coverage data
color_range=(0, 100), # Manual range: 0% (red) to 100% (green)
cell_size_fn=_pmg_cell_size,
show_counts="value",
color_continuous_scale="RdYlGn", # Red-Yellow-Green scale for coverage
max_module_depth=3,
min_lines_for_split=500, # only expand if every child has >=500 lines
max_children_for_split=5, # only expand if parent has <=5 children
)
fig_cov_range.layout.margin = dict(l=0, r=0, b=0, t=0)
fig_cov_range.show()
pmv.io.save_and_compress_svg(fig_cov_range, "py-pkg-treemap-pymatgen-coverage")