oscura 0.7.0__py3-none-any.whl → 0.10.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oscura/__init__.py +19 -19
- oscura/analyzers/__init__.py +2 -0
- oscura/analyzers/digital/extraction.py +2 -3
- oscura/analyzers/digital/quality.py +1 -1
- oscura/analyzers/digital/timing.py +1 -1
- oscura/analyzers/eye/__init__.py +5 -1
- oscura/analyzers/eye/generation.py +501 -0
- oscura/analyzers/jitter/__init__.py +6 -6
- oscura/analyzers/jitter/timing.py +419 -0
- oscura/analyzers/patterns/__init__.py +94 -0
- oscura/analyzers/patterns/reverse_engineering.py +991 -0
- oscura/analyzers/power/__init__.py +35 -12
- oscura/analyzers/power/basic.py +3 -3
- oscura/analyzers/power/soa.py +1 -1
- oscura/analyzers/power/switching.py +3 -3
- oscura/analyzers/signal_classification.py +529 -0
- oscura/analyzers/signal_integrity/sparams.py +3 -3
- oscura/analyzers/statistics/__init__.py +4 -0
- oscura/analyzers/statistics/basic.py +152 -0
- oscura/analyzers/statistics/correlation.py +47 -6
- oscura/analyzers/validation.py +1 -1
- oscura/analyzers/waveform/__init__.py +2 -0
- oscura/analyzers/waveform/measurements.py +329 -163
- oscura/analyzers/waveform/measurements_with_uncertainty.py +91 -35
- oscura/analyzers/waveform/spectral.py +498 -54
- oscura/api/dsl/commands.py +15 -6
- oscura/api/server/templates/base.html +137 -146
- oscura/api/server/templates/export.html +84 -110
- oscura/api/server/templates/home.html +248 -267
- oscura/api/server/templates/protocols.html +44 -48
- oscura/api/server/templates/reports.html +27 -35
- oscura/api/server/templates/session_detail.html +68 -78
- oscura/api/server/templates/sessions.html +62 -72
- oscura/api/server/templates/waveforms.html +54 -64
- oscura/automotive/__init__.py +1 -1
- oscura/automotive/can/session.py +1 -1
- oscura/automotive/dbc/generator.py +638 -23
- oscura/automotive/dtc/data.json +102 -17
- oscura/automotive/uds/decoder.py +99 -6
- oscura/cli/analyze.py +8 -2
- oscura/cli/batch.py +36 -5
- oscura/cli/characterize.py +18 -4
- oscura/cli/export.py +47 -5
- oscura/cli/main.py +2 -0
- oscura/cli/onboarding/wizard.py +10 -6
- oscura/cli/pipeline.py +585 -0
- oscura/cli/visualize.py +6 -4
- oscura/convenience.py +400 -32
- oscura/core/config/loader.py +0 -1
- oscura/core/measurement_result.py +286 -0
- oscura/core/progress.py +1 -1
- oscura/core/schemas/device_mapping.json +8 -2
- oscura/core/schemas/packet_format.json +24 -4
- oscura/core/schemas/protocol_definition.json +12 -2
- oscura/core/types.py +300 -199
- oscura/correlation/multi_protocol.py +1 -1
- oscura/export/legacy/__init__.py +11 -0
- oscura/export/legacy/wav.py +75 -0
- oscura/exporters/__init__.py +19 -0
- oscura/exporters/wireshark.py +809 -0
- oscura/hardware/acquisition/file.py +5 -19
- oscura/hardware/acquisition/saleae.py +10 -10
- oscura/hardware/acquisition/socketcan.py +4 -6
- oscura/hardware/acquisition/synthetic.py +1 -5
- oscura/hardware/acquisition/visa.py +6 -6
- oscura/hardware/security/side_channel_detector.py +5 -508
- oscura/inference/message_format.py +686 -1
- oscura/jupyter/display.py +2 -2
- oscura/jupyter/magic.py +3 -3
- oscura/loaders/__init__.py +17 -12
- oscura/loaders/binary.py +1 -1
- oscura/loaders/chipwhisperer.py +1 -2
- oscura/loaders/configurable.py +1 -1
- oscura/loaders/csv_loader.py +2 -2
- oscura/loaders/hdf5_loader.py +1 -1
- oscura/loaders/lazy.py +6 -1
- oscura/loaders/mmap_loader.py +0 -1
- oscura/loaders/numpy_loader.py +8 -7
- oscura/loaders/preprocessing.py +3 -5
- oscura/loaders/rigol.py +21 -7
- oscura/loaders/sigrok.py +2 -5
- oscura/loaders/tdms.py +3 -2
- oscura/loaders/tektronix.py +38 -32
- oscura/loaders/tss.py +20 -27
- oscura/loaders/vcd.py +13 -8
- oscura/loaders/wav.py +1 -6
- oscura/pipeline/__init__.py +76 -0
- oscura/pipeline/handlers/__init__.py +165 -0
- oscura/pipeline/handlers/analyzers.py +1045 -0
- oscura/pipeline/handlers/decoders.py +899 -0
- oscura/pipeline/handlers/exporters.py +1103 -0
- oscura/pipeline/handlers/filters.py +891 -0
- oscura/pipeline/handlers/loaders.py +640 -0
- oscura/pipeline/handlers/transforms.py +768 -0
- oscura/reporting/__init__.py +88 -1
- oscura/reporting/automation.py +348 -0
- oscura/reporting/citations.py +374 -0
- oscura/reporting/core.py +54 -0
- oscura/reporting/formatting/__init__.py +11 -0
- oscura/reporting/formatting/measurements.py +320 -0
- oscura/reporting/html.py +57 -0
- oscura/reporting/interpretation.py +431 -0
- oscura/reporting/summary.py +329 -0
- oscura/reporting/templates/enhanced/protocol_re.html +504 -503
- oscura/reporting/visualization.py +542 -0
- oscura/side_channel/__init__.py +38 -57
- oscura/utils/builders/signal_builder.py +5 -5
- oscura/utils/comparison/compare.py +7 -9
- oscura/utils/comparison/golden.py +1 -1
- oscura/utils/filtering/convenience.py +2 -2
- oscura/utils/math/arithmetic.py +38 -62
- oscura/utils/math/interpolation.py +20 -20
- oscura/utils/pipeline/__init__.py +4 -17
- oscura/utils/progressive.py +1 -4
- oscura/utils/triggering/edge.py +1 -1
- oscura/utils/triggering/pattern.py +2 -2
- oscura/utils/triggering/pulse.py +2 -2
- oscura/utils/triggering/window.py +3 -3
- oscura/validation/hil_testing.py +11 -11
- oscura/visualization/__init__.py +47 -284
- oscura/visualization/batch.py +160 -0
- oscura/visualization/plot.py +542 -53
- oscura/visualization/styles.py +184 -318
- oscura/workflows/__init__.py +2 -0
- oscura/workflows/batch/advanced.py +1 -1
- oscura/workflows/batch/aggregate.py +7 -8
- oscura/workflows/complete_re.py +251 -23
- oscura/workflows/digital.py +27 -4
- oscura/workflows/multi_trace.py +136 -17
- oscura/workflows/waveform.py +788 -0
- {oscura-0.7.0.dist-info → oscura-0.10.0.dist-info}/METADATA +59 -79
- {oscura-0.7.0.dist-info → oscura-0.10.0.dist-info}/RECORD +135 -149
- oscura/side_channel/dpa.py +0 -1025
- oscura/utils/optimization/__init__.py +0 -19
- oscura/utils/optimization/parallel.py +0 -443
- oscura/utils/optimization/search.py +0 -532
- oscura/utils/pipeline/base.py +0 -338
- oscura/utils/pipeline/composition.py +0 -248
- oscura/utils/pipeline/parallel.py +0 -449
- oscura/utils/pipeline/pipeline.py +0 -375
- oscura/utils/search/__init__.py +0 -16
- oscura/utils/search/anomaly.py +0 -424
- oscura/utils/search/context.py +0 -294
- oscura/utils/search/pattern.py +0 -288
- oscura/utils/storage/__init__.py +0 -61
- oscura/utils/storage/database.py +0 -1166
- oscura/visualization/accessibility.py +0 -526
- oscura/visualization/annotations.py +0 -371
- oscura/visualization/axis_scaling.py +0 -305
- oscura/visualization/colors.py +0 -451
- oscura/visualization/digital.py +0 -436
- oscura/visualization/eye.py +0 -571
- oscura/visualization/histogram.py +0 -281
- oscura/visualization/interactive.py +0 -1035
- oscura/visualization/jitter.py +0 -1042
- oscura/visualization/keyboard.py +0 -394
- oscura/visualization/layout.py +0 -400
- oscura/visualization/optimization.py +0 -1079
- oscura/visualization/palettes.py +0 -446
- oscura/visualization/power.py +0 -508
- oscura/visualization/power_extended.py +0 -955
- oscura/visualization/presets.py +0 -469
- oscura/visualization/protocols.py +0 -1246
- oscura/visualization/render.py +0 -223
- oscura/visualization/rendering.py +0 -444
- oscura/visualization/reverse_engineering.py +0 -838
- oscura/visualization/signal_integrity.py +0 -989
- oscura/visualization/specialized.py +0 -643
- oscura/visualization/spectral.py +0 -1226
- oscura/visualization/thumbnails.py +0 -340
- oscura/visualization/time_axis.py +0 -351
- oscura/visualization/waveform.py +0 -454
- {oscura-0.7.0.dist-info → oscura-0.10.0.dist-info}/WHEEL +0 -0
- {oscura-0.7.0.dist-info → oscura-0.10.0.dist-info}/entry_points.txt +0 -0
- {oscura-0.7.0.dist-info → oscura-0.10.0.dist-info}/licenses/LICENSE +0 -0
oscura/visualization/presets.py
DELETED
|
@@ -1,469 +0,0 @@
|
|
|
1
|
-
"""Comprehensive visualization presets combining styles, colors, and rendering.
|
|
2
|
-
|
|
3
|
-
This module provides integrated presets that combine style settings, color
|
|
4
|
-
palettes, and rendering configuration for different use cases.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Example:
|
|
8
|
-
>>> from oscura.visualization.presets import apply_preset
|
|
9
|
-
>>> with apply_preset("ieee_publication"):
|
|
10
|
-
... plot_waveform(signal)
|
|
11
|
-
|
|
12
|
-
References:
|
|
13
|
-
- IEEE publication standards
|
|
14
|
-
- Presentation best practices
|
|
15
|
-
- Colorblind-safe palette design
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
from __future__ import annotations
|
|
19
|
-
|
|
20
|
-
from contextlib import contextmanager
|
|
21
|
-
from dataclasses import dataclass
|
|
22
|
-
from typing import TYPE_CHECKING, Any
|
|
23
|
-
|
|
24
|
-
if TYPE_CHECKING:
|
|
25
|
-
from collections.abc import Iterator
|
|
26
|
-
|
|
27
|
-
try:
|
|
28
|
-
import matplotlib.pyplot as plt
|
|
29
|
-
|
|
30
|
-
HAS_MATPLOTLIB = True
|
|
31
|
-
except ImportError:
|
|
32
|
-
HAS_MATPLOTLIB = False
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@dataclass
|
|
36
|
-
class VisualizationPreset:
|
|
37
|
-
"""Complete visualization preset configuration.
|
|
38
|
-
|
|
39
|
-
Attributes:
|
|
40
|
-
name: Preset name
|
|
41
|
-
description: Preset description
|
|
42
|
-
style_params: Matplotlib rcParams
|
|
43
|
-
color_palette: List of colors for multi-channel plots
|
|
44
|
-
dpi: Target DPI
|
|
45
|
-
figure_size: Default figure size (width, height) in inches
|
|
46
|
-
font_family: Font family
|
|
47
|
-
colorblind_safe: Whether palette is colorblind-safe
|
|
48
|
-
print_optimized: Whether optimized for print output
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
name: str
|
|
52
|
-
description: str
|
|
53
|
-
style_params: dict[str, Any]
|
|
54
|
-
color_palette: list[str]
|
|
55
|
-
dpi: int = 96
|
|
56
|
-
figure_size: tuple[float, float] = (10, 6)
|
|
57
|
-
font_family: str = "sans-serif"
|
|
58
|
-
colorblind_safe: bool = True
|
|
59
|
-
print_optimized: bool = False
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
# IEEE Publication Preset (VIS-020)
|
|
63
|
-
IEEE_PUBLICATION_PRESET = VisualizationPreset(
|
|
64
|
-
name="ieee_publication",
|
|
65
|
-
description="IEEE publication quality (single-column, grayscale-friendly)",
|
|
66
|
-
dpi=600,
|
|
67
|
-
figure_size=(3.5, 2.5), # IEEE single-column width
|
|
68
|
-
font_family="serif",
|
|
69
|
-
colorblind_safe=True,
|
|
70
|
-
print_optimized=True,
|
|
71
|
-
color_palette=[
|
|
72
|
-
"#000000", # Black
|
|
73
|
-
"#555555", # Dark gray
|
|
74
|
-
"#AAAAAA", # Light gray
|
|
75
|
-
"#0173B2", # Blue (grayscale-safe)
|
|
76
|
-
"#DE8F05", # Orange (grayscale-safe)
|
|
77
|
-
"#029E73", # Green (grayscale-safe)
|
|
78
|
-
],
|
|
79
|
-
style_params={
|
|
80
|
-
"figure.dpi": 600,
|
|
81
|
-
"savefig.dpi": 600,
|
|
82
|
-
"savefig.format": "pdf",
|
|
83
|
-
"savefig.bbox": "tight",
|
|
84
|
-
"font.family": "serif",
|
|
85
|
-
"font.size": 8,
|
|
86
|
-
"axes.titlesize": 9,
|
|
87
|
-
"axes.labelsize": 8,
|
|
88
|
-
"xtick.labelsize": 7,
|
|
89
|
-
"ytick.labelsize": 7,
|
|
90
|
-
"legend.fontsize": 7,
|
|
91
|
-
"lines.linewidth": 0.8,
|
|
92
|
-
"lines.markersize": 3.0,
|
|
93
|
-
"axes.linewidth": 0.6,
|
|
94
|
-
"grid.linewidth": 0.4,
|
|
95
|
-
"grid.alpha": 0.3,
|
|
96
|
-
"grid.linestyle": ":",
|
|
97
|
-
"axes.grid": True,
|
|
98
|
-
"axes.axisbelow": True,
|
|
99
|
-
"xtick.major.width": 0.6,
|
|
100
|
-
"ytick.major.width": 0.6,
|
|
101
|
-
"xtick.minor.width": 0.4,
|
|
102
|
-
"ytick.minor.width": 0.4,
|
|
103
|
-
"lines.antialiased": False, # Sharper for print
|
|
104
|
-
"patch.antialiased": False,
|
|
105
|
-
"mathtext.fontset": "cm", # Computer Modern (LaTeX-like)
|
|
106
|
-
},
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
# IEEE Double-Column Preset
|
|
110
|
-
IEEE_DOUBLE_COLUMN_PRESET = VisualizationPreset(
|
|
111
|
-
name="ieee_double_column",
|
|
112
|
-
description="IEEE publication quality (double-column width)",
|
|
113
|
-
dpi=600,
|
|
114
|
-
figure_size=(7.0, 2.5), # IEEE double-column width
|
|
115
|
-
font_family="serif",
|
|
116
|
-
colorblind_safe=True,
|
|
117
|
-
print_optimized=True,
|
|
118
|
-
color_palette=IEEE_PUBLICATION_PRESET.color_palette,
|
|
119
|
-
style_params=IEEE_PUBLICATION_PRESET.style_params.copy(),
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
# Presentation Preset
|
|
123
|
-
PRESENTATION_PRESET = VisualizationPreset(
|
|
124
|
-
name="presentation",
|
|
125
|
-
description="Presentation slides (high contrast, large fonts, bold lines)",
|
|
126
|
-
dpi=96,
|
|
127
|
-
figure_size=(12, 7),
|
|
128
|
-
font_family="sans-serif",
|
|
129
|
-
colorblind_safe=True,
|
|
130
|
-
print_optimized=False,
|
|
131
|
-
color_palette=[
|
|
132
|
-
"#0173B2", # Blue
|
|
133
|
-
"#DE8F05", # Orange
|
|
134
|
-
"#029E73", # Green
|
|
135
|
-
"#CC78BC", # Purple
|
|
136
|
-
"#CA9161", # Brown
|
|
137
|
-
"#ECE133", # Yellow
|
|
138
|
-
],
|
|
139
|
-
style_params={
|
|
140
|
-
"figure.dpi": 96,
|
|
141
|
-
"font.family": "sans-serif",
|
|
142
|
-
"font.size": 18,
|
|
143
|
-
"axes.titlesize": 22,
|
|
144
|
-
"axes.labelsize": 20,
|
|
145
|
-
"xtick.labelsize": 16,
|
|
146
|
-
"ytick.labelsize": 16,
|
|
147
|
-
"legend.fontsize": 16,
|
|
148
|
-
"lines.linewidth": 3.0,
|
|
149
|
-
"lines.markersize": 10.0,
|
|
150
|
-
"axes.linewidth": 2.0,
|
|
151
|
-
"grid.linewidth": 1.0,
|
|
152
|
-
"grid.alpha": 0.4,
|
|
153
|
-
"axes.grid": True,
|
|
154
|
-
"xtick.major.width": 2.0,
|
|
155
|
-
"ytick.major.width": 2.0,
|
|
156
|
-
"xtick.major.size": 8,
|
|
157
|
-
"ytick.major.size": 8,
|
|
158
|
-
"lines.antialiased": True,
|
|
159
|
-
"patch.antialiased": True,
|
|
160
|
-
},
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
# Screen/Interactive Preset
|
|
164
|
-
SCREEN_PRESET = VisualizationPreset(
|
|
165
|
-
name="screen",
|
|
166
|
-
description="Screen viewing (vibrant colors, medium fonts, anti-aliased)",
|
|
167
|
-
dpi=96,
|
|
168
|
-
figure_size=(10, 6),
|
|
169
|
-
font_family="sans-serif",
|
|
170
|
-
colorblind_safe=True,
|
|
171
|
-
print_optimized=False,
|
|
172
|
-
color_palette=[
|
|
173
|
-
"#1F77B4", # Blue
|
|
174
|
-
"#FF7F0E", # Orange
|
|
175
|
-
"#2CA02C", # Green
|
|
176
|
-
"#D62728", # Red
|
|
177
|
-
"#9467BD", # Purple
|
|
178
|
-
"#8C564B", # Brown
|
|
179
|
-
"#E377C2", # Pink
|
|
180
|
-
"#7F7F7F", # Gray
|
|
181
|
-
],
|
|
182
|
-
style_params={
|
|
183
|
-
"figure.dpi": 96,
|
|
184
|
-
"font.family": "sans-serif",
|
|
185
|
-
"font.size": 10,
|
|
186
|
-
"axes.titlesize": 12,
|
|
187
|
-
"axes.labelsize": 10,
|
|
188
|
-
"xtick.labelsize": 9,
|
|
189
|
-
"ytick.labelsize": 9,
|
|
190
|
-
"legend.fontsize": 9,
|
|
191
|
-
"lines.linewidth": 1.5,
|
|
192
|
-
"lines.markersize": 6.0,
|
|
193
|
-
"axes.linewidth": 1.0,
|
|
194
|
-
"grid.linewidth": 0.6,
|
|
195
|
-
"grid.alpha": 0.3,
|
|
196
|
-
"axes.grid": True,
|
|
197
|
-
"lines.antialiased": True,
|
|
198
|
-
"patch.antialiased": True,
|
|
199
|
-
},
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
# Print Preset
|
|
203
|
-
PRINT_PRESET = VisualizationPreset(
|
|
204
|
-
name="print",
|
|
205
|
-
description="Print output (300 DPI, CMYK-safe colors, optimized file size)",
|
|
206
|
-
dpi=300,
|
|
207
|
-
figure_size=(8, 5),
|
|
208
|
-
font_family="serif",
|
|
209
|
-
colorblind_safe=True,
|
|
210
|
-
print_optimized=True,
|
|
211
|
-
color_palette=[
|
|
212
|
-
"#0173B2", # Blue (CMYK-safe)
|
|
213
|
-
"#DE8F05", # Orange (CMYK-safe)
|
|
214
|
-
"#029E73", # Green (CMYK-safe)
|
|
215
|
-
"#CC78BC", # Purple (CMYK-safe)
|
|
216
|
-
"#555555", # Gray (CMYK-safe)
|
|
217
|
-
],
|
|
218
|
-
style_params={
|
|
219
|
-
"figure.dpi": 300,
|
|
220
|
-
"savefig.dpi": 300,
|
|
221
|
-
"savefig.format": "pdf",
|
|
222
|
-
"font.family": "serif",
|
|
223
|
-
"font.size": 11,
|
|
224
|
-
"axes.titlesize": 13,
|
|
225
|
-
"axes.labelsize": 11,
|
|
226
|
-
"xtick.labelsize": 10,
|
|
227
|
-
"ytick.labelsize": 10,
|
|
228
|
-
"legend.fontsize": 10,
|
|
229
|
-
"lines.linewidth": 1.2,
|
|
230
|
-
"lines.markersize": 5.0,
|
|
231
|
-
"axes.linewidth": 1.0,
|
|
232
|
-
"grid.linewidth": 0.6,
|
|
233
|
-
"grid.alpha": 0.3,
|
|
234
|
-
"axes.grid": True,
|
|
235
|
-
"lines.antialiased": False, # Cleaner for print
|
|
236
|
-
"patch.antialiased": False,
|
|
237
|
-
},
|
|
238
|
-
)
|
|
239
|
-
|
|
240
|
-
# Dark Theme Preset
|
|
241
|
-
DARK_THEME_PRESET = VisualizationPreset(
|
|
242
|
-
name="dark",
|
|
243
|
-
description="Dark theme (dark background, high-contrast colors)",
|
|
244
|
-
dpi=96,
|
|
245
|
-
figure_size=(10, 6),
|
|
246
|
-
font_family="sans-serif",
|
|
247
|
-
colorblind_safe=True,
|
|
248
|
-
print_optimized=False,
|
|
249
|
-
color_palette=[
|
|
250
|
-
"#56B4E9", # Light blue
|
|
251
|
-
"#E69F00", # Orange
|
|
252
|
-
"#009E73", # Green
|
|
253
|
-
"#F0E442", # Yellow
|
|
254
|
-
"#CC79A7", # Pink
|
|
255
|
-
"#0072B2", # Blue
|
|
256
|
-
],
|
|
257
|
-
style_params={
|
|
258
|
-
"figure.dpi": 96,
|
|
259
|
-
"figure.facecolor": "#1E1E1E",
|
|
260
|
-
"axes.facecolor": "#2D2D2D",
|
|
261
|
-
"axes.edgecolor": "#CCCCCC",
|
|
262
|
-
"axes.labelcolor": "#CCCCCC",
|
|
263
|
-
"text.color": "#CCCCCC",
|
|
264
|
-
"xtick.color": "#CCCCCC",
|
|
265
|
-
"ytick.color": "#CCCCCC",
|
|
266
|
-
"grid.color": "#555555",
|
|
267
|
-
"grid.alpha": 0.5,
|
|
268
|
-
"font.family": "sans-serif",
|
|
269
|
-
"font.size": 10,
|
|
270
|
-
"lines.linewidth": 1.5,
|
|
271
|
-
"axes.grid": True,
|
|
272
|
-
"lines.antialiased": True,
|
|
273
|
-
},
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
# Preset registry
|
|
277
|
-
PRESETS: dict[str, VisualizationPreset] = {
|
|
278
|
-
"ieee_publication": IEEE_PUBLICATION_PRESET,
|
|
279
|
-
"ieee_double_column": IEEE_DOUBLE_COLUMN_PRESET,
|
|
280
|
-
"presentation": PRESENTATION_PRESET,
|
|
281
|
-
"screen": SCREEN_PRESET,
|
|
282
|
-
"print": PRINT_PRESET,
|
|
283
|
-
"dark": DARK_THEME_PRESET,
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
@contextmanager
|
|
288
|
-
def apply_preset(
|
|
289
|
-
preset: str | VisualizationPreset,
|
|
290
|
-
*,
|
|
291
|
-
overrides: dict[str, Any] | None = None,
|
|
292
|
-
) -> Iterator[VisualizationPreset]:
|
|
293
|
-
"""Apply visualization preset as context manager./VIS-024.
|
|
294
|
-
|
|
295
|
-
Combines style settings, color palette, and rendering configuration.
|
|
296
|
-
|
|
297
|
-
Args:
|
|
298
|
-
preset: Preset name or VisualizationPreset object.
|
|
299
|
-
overrides: Dictionary of rcParams to override.
|
|
300
|
-
|
|
301
|
-
Yields:
|
|
302
|
-
VisualizationPreset object for access to color palette.
|
|
303
|
-
|
|
304
|
-
Raises:
|
|
305
|
-
ValueError: If preset name is unknown.
|
|
306
|
-
ImportError: If matplotlib is not available.
|
|
307
|
-
|
|
308
|
-
Example:
|
|
309
|
-
>>> with apply_preset("ieee_publication") as preset:
|
|
310
|
-
... fig, ax = plt.subplots(figsize=preset.figure_size)
|
|
311
|
-
... ax.plot(x, y, color=preset.color_palette[0])
|
|
312
|
-
... plt.savefig("figure.pdf")
|
|
313
|
-
|
|
314
|
-
>>> # With custom overrides
|
|
315
|
-
>>> with apply_preset("screen", overrides={"font.size": 14}):
|
|
316
|
-
... plot_waveform(signal)
|
|
317
|
-
|
|
318
|
-
References:
|
|
319
|
-
VIS-020: IEEE Publication Style Preset
|
|
320
|
-
VIS-024: Plot Style Presets
|
|
321
|
-
"""
|
|
322
|
-
if not HAS_MATPLOTLIB:
|
|
323
|
-
raise ImportError("matplotlib is required for visualization presets")
|
|
324
|
-
|
|
325
|
-
# Get preset object
|
|
326
|
-
if isinstance(preset, str):
|
|
327
|
-
if preset not in PRESETS:
|
|
328
|
-
raise ValueError(f"Unknown preset: {preset}. Available: {list(PRESETS.keys())}")
|
|
329
|
-
preset_obj = PRESETS[preset]
|
|
330
|
-
else:
|
|
331
|
-
preset_obj = preset
|
|
332
|
-
|
|
333
|
-
# Build rcParams dictionary
|
|
334
|
-
# NECESSARY COPY: rc_dict is modified by .update() below.
|
|
335
|
-
# Copy prevents mutations from affecting original preset.
|
|
336
|
-
rc_dict = preset_obj.style_params.copy()
|
|
337
|
-
|
|
338
|
-
# Apply overrides
|
|
339
|
-
if overrides:
|
|
340
|
-
rc_dict.update(overrides)
|
|
341
|
-
|
|
342
|
-
# Apply as context
|
|
343
|
-
with plt.rc_context(rc_dict):
|
|
344
|
-
yield preset_obj
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
def get_preset_colors(
|
|
348
|
-
preset: str | VisualizationPreset,
|
|
349
|
-
n_colors: int | None = None,
|
|
350
|
-
) -> list[str]:
|
|
351
|
-
"""Get color palette from preset.
|
|
352
|
-
|
|
353
|
-
Args:
|
|
354
|
-
preset: Preset name or object.
|
|
355
|
-
n_colors: Number of colors to return (None = all).
|
|
356
|
-
|
|
357
|
-
Returns:
|
|
358
|
-
List of color hex codes.
|
|
359
|
-
|
|
360
|
-
Raises:
|
|
361
|
-
ValueError: If unknown preset name.
|
|
362
|
-
|
|
363
|
-
Example:
|
|
364
|
-
>>> colors = get_preset_colors("ieee_publication", n_colors=3)
|
|
365
|
-
>>> # Use colors for multi-channel plot
|
|
366
|
-
|
|
367
|
-
References:
|
|
368
|
-
VIS-023: Data-Driven Color Palette
|
|
369
|
-
VIS-024: Plot Style Presets
|
|
370
|
-
"""
|
|
371
|
-
if isinstance(preset, str):
|
|
372
|
-
if preset not in PRESETS:
|
|
373
|
-
raise ValueError(f"Unknown preset: {preset}")
|
|
374
|
-
preset_obj = PRESETS[preset]
|
|
375
|
-
else:
|
|
376
|
-
preset_obj = preset
|
|
377
|
-
|
|
378
|
-
colors = preset_obj.color_palette
|
|
379
|
-
|
|
380
|
-
if n_colors is not None:
|
|
381
|
-
if n_colors <= len(colors):
|
|
382
|
-
return colors[:n_colors]
|
|
383
|
-
else:
|
|
384
|
-
# Cycle colors if more needed
|
|
385
|
-
return [colors[i % len(colors)] for i in range(n_colors)]
|
|
386
|
-
|
|
387
|
-
return colors
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
def list_presets() -> list[str]:
|
|
391
|
-
"""Get list of available preset names.
|
|
392
|
-
|
|
393
|
-
Returns:
|
|
394
|
-
List of preset names.
|
|
395
|
-
|
|
396
|
-
Example:
|
|
397
|
-
>>> presets = list_presets()
|
|
398
|
-
>>> print(presets)
|
|
399
|
-
['ieee_publication', 'presentation', 'screen', 'print', 'dark']
|
|
400
|
-
"""
|
|
401
|
-
return list(PRESETS.keys())
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
def create_custom_preset(
|
|
405
|
-
name: str,
|
|
406
|
-
base_preset: str = "screen",
|
|
407
|
-
**kwargs: Any,
|
|
408
|
-
) -> VisualizationPreset:
|
|
409
|
-
"""Create custom preset by inheriting from base.
|
|
410
|
-
|
|
411
|
-
Args:
|
|
412
|
-
name: Name for custom preset.
|
|
413
|
-
base_preset: Base preset to inherit from.
|
|
414
|
-
**kwargs: Attributes to override.
|
|
415
|
-
|
|
416
|
-
Returns:
|
|
417
|
-
Custom VisualizationPreset object.
|
|
418
|
-
|
|
419
|
-
Raises:
|
|
420
|
-
ValueError: If base_preset is unknown.
|
|
421
|
-
|
|
422
|
-
Example:
|
|
423
|
-
>>> custom = create_custom_preset(
|
|
424
|
-
... "my_preset",
|
|
425
|
-
... base_preset="ieee_publication",
|
|
426
|
-
... figure_size=(5, 3),
|
|
427
|
-
... dpi=300,
|
|
428
|
-
... )
|
|
429
|
-
>>> with apply_preset(custom):
|
|
430
|
-
... plot_data()
|
|
431
|
-
|
|
432
|
-
References:
|
|
433
|
-
VIS-024: Plot Style Presets (custom preset creation)
|
|
434
|
-
"""
|
|
435
|
-
if base_preset not in PRESETS:
|
|
436
|
-
raise ValueError(f"Unknown base_preset: {base_preset}")
|
|
437
|
-
|
|
438
|
-
base = PRESETS[base_preset]
|
|
439
|
-
|
|
440
|
-
# Create copy with overrides
|
|
441
|
-
preset_dict = {
|
|
442
|
-
"name": name,
|
|
443
|
-
"description": kwargs.get("description", f"Custom preset based on {base_preset}"),
|
|
444
|
-
"style_params": kwargs.get("style_params", base.style_params.copy()),
|
|
445
|
-
"color_palette": kwargs.get("color_palette", base.color_palette.copy()),
|
|
446
|
-
"dpi": kwargs.get("dpi", base.dpi),
|
|
447
|
-
"figure_size": kwargs.get("figure_size", base.figure_size),
|
|
448
|
-
"font_family": kwargs.get("font_family", base.font_family),
|
|
449
|
-
"colorblind_safe": kwargs.get("colorblind_safe", base.colorblind_safe),
|
|
450
|
-
"print_optimized": kwargs.get("print_optimized", base.print_optimized),
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
return VisualizationPreset(**preset_dict)
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
__all__ = [
|
|
457
|
-
"DARK_THEME_PRESET",
|
|
458
|
-
"IEEE_DOUBLE_COLUMN_PRESET",
|
|
459
|
-
"IEEE_PUBLICATION_PRESET",
|
|
460
|
-
"PRESENTATION_PRESET",
|
|
461
|
-
"PRESETS",
|
|
462
|
-
"PRINT_PRESET",
|
|
463
|
-
"SCREEN_PRESET",
|
|
464
|
-
"VisualizationPreset",
|
|
465
|
-
"apply_preset",
|
|
466
|
-
"create_custom_preset",
|
|
467
|
-
"get_preset_colors",
|
|
468
|
-
"list_presets",
|
|
469
|
-
]
|