spectre-core 0.0.22__py3-none-any.whl → 0.0.24__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.
Files changed (78) hide show
  1. spectre_core/__init__.py +5 -0
  2. spectre_core/_file_io/__init__.py +4 -4
  3. spectre_core/_file_io/file_handlers.py +60 -106
  4. spectre_core/batches/__init__.py +20 -3
  5. spectre_core/batches/_base.py +85 -134
  6. spectre_core/batches/_batches.py +55 -99
  7. spectre_core/batches/_factory.py +21 -20
  8. spectre_core/batches/_register.py +8 -8
  9. spectre_core/batches/plugins/_batch_keys.py +7 -6
  10. spectre_core/batches/plugins/_callisto.py +65 -97
  11. spectre_core/batches/plugins/_iq_stream.py +105 -169
  12. spectre_core/capture_configs/__init__.py +46 -17
  13. spectre_core/capture_configs/_capture_config.py +25 -52
  14. spectre_core/capture_configs/_capture_modes.py +8 -6
  15. spectre_core/capture_configs/_capture_templates.py +50 -110
  16. spectre_core/capture_configs/_parameters.py +37 -74
  17. spectre_core/capture_configs/_pconstraints.py +40 -40
  18. spectre_core/capture_configs/_pnames.py +36 -34
  19. spectre_core/capture_configs/_ptemplates.py +260 -347
  20. spectre_core/capture_configs/_pvalidators.py +99 -102
  21. spectre_core/config/__init__.py +19 -8
  22. spectre_core/config/_paths.py +25 -47
  23. spectre_core/config/_time_formats.py +6 -5
  24. spectre_core/exceptions.py +38 -0
  25. spectre_core/jobs/__init__.py +3 -6
  26. spectre_core/jobs/_duration.py +12 -0
  27. spectre_core/jobs/_jobs.py +72 -43
  28. spectre_core/jobs/_workers.py +55 -105
  29. spectre_core/logs/__init__.py +7 -2
  30. spectre_core/logs/_configure.py +13 -17
  31. spectre_core/logs/_decorators.py +6 -4
  32. spectre_core/logs/_logs.py +37 -89
  33. spectre_core/logs/_process_types.py +5 -3
  34. spectre_core/plotting/__init__.py +19 -3
  35. spectre_core/plotting/_base.py +112 -177
  36. spectre_core/plotting/_format.py +10 -8
  37. spectre_core/plotting/_panel_names.py +7 -5
  38. spectre_core/plotting/_panel_stack.py +138 -130
  39. spectre_core/plotting/_panels.py +152 -162
  40. spectre_core/post_processing/__init__.py +6 -3
  41. spectre_core/post_processing/_base.py +41 -55
  42. spectre_core/post_processing/_factory.py +14 -11
  43. spectre_core/post_processing/_post_processor.py +16 -12
  44. spectre_core/post_processing/_register.py +10 -7
  45. spectre_core/post_processing/plugins/_event_handler_keys.py +4 -3
  46. spectre_core/post_processing/plugins/_fixed_center_frequency.py +54 -47
  47. spectre_core/post_processing/plugins/_swept_center_frequency.py +199 -174
  48. spectre_core/receivers/__init__.py +9 -2
  49. spectre_core/receivers/_base.py +82 -148
  50. spectre_core/receivers/_factory.py +20 -30
  51. spectre_core/receivers/_register.py +7 -10
  52. spectre_core/receivers/_spec_names.py +17 -15
  53. spectre_core/receivers/plugins/_b200mini.py +47 -60
  54. spectre_core/receivers/plugins/_receiver_names.py +8 -6
  55. spectre_core/receivers/plugins/_rsp1a.py +44 -40
  56. spectre_core/receivers/plugins/_rspduo.py +59 -44
  57. spectre_core/receivers/plugins/_sdrplay_receiver.py +67 -83
  58. spectre_core/receivers/plugins/_test.py +136 -129
  59. spectre_core/receivers/plugins/_usrp.py +93 -85
  60. spectre_core/receivers/plugins/gr/__init__.py +1 -1
  61. spectre_core/receivers/plugins/gr/_base.py +14 -22
  62. spectre_core/receivers/plugins/gr/_rsp1a.py +53 -60
  63. spectre_core/receivers/plugins/gr/_rspduo.py +77 -89
  64. spectre_core/receivers/plugins/gr/_test.py +49 -57
  65. spectre_core/receivers/plugins/gr/_usrp.py +61 -59
  66. spectre_core/spectrograms/__init__.py +21 -13
  67. spectre_core/spectrograms/_analytical.py +108 -99
  68. spectre_core/spectrograms/_array_operations.py +39 -46
  69. spectre_core/spectrograms/_spectrogram.py +293 -324
  70. spectre_core/spectrograms/_transform.py +106 -73
  71. spectre_core/wgetting/__init__.py +1 -3
  72. spectre_core/wgetting/_callisto.py +87 -93
  73. {spectre_core-0.0.22.dist-info → spectre_core-0.0.24.dist-info}/METADATA +9 -23
  74. spectre_core-0.0.24.dist-info/RECORD +79 -0
  75. {spectre_core-0.0.22.dist-info → spectre_core-0.0.24.dist-info}/WHEEL +1 -1
  76. spectre_core-0.0.22.dist-info/RECORD +0 -78
  77. {spectre_core-0.0.22.dist-info → spectre_core-0.0.24.dist-info}/licenses/LICENSE +0 -0
  78. {spectre_core-0.0.22.dist-info → spectre_core-0.0.24.dist-info}/top_level.txt +0 -0
@@ -2,28 +2,30 @@
2
2
  # This file is part of SPECTRE
3
3
  # SPDX-License-Identifier: GPL-3.0-or-later
4
4
 
5
- from typing import TypeVar, Tuple, Iterator, Optional
5
+ from typing import TypeVar, Tuple, Iterator, Optional, Literal
6
6
  from datetime import datetime
7
7
 
8
8
  from matplotlib.colors import LogNorm
9
9
  from matplotlib import cm
10
+ from matplotlib.colorbar import Colorbar
10
11
  import numpy as np
11
12
  import numpy.typing as npt
12
13
 
13
14
  from spectre_core.spectrograms import Spectrogram, FrequencyCut, TimeCut
14
- from ._base import BaseSpectrumPanel, BaseTimeSeriesPanel
15
+ from ._base import BasePanel, BaseTimeSeriesPanel, XAxisType
15
16
  from ._panel_names import PanelName
16
17
 
17
18
 
18
- T = TypeVar('T')
19
+ T = TypeVar("T")
20
+
21
+
19
22
  def _bind_to_colors(
20
- values: list[T],
21
- cmap: str = "winter"
22
- ) -> Iterator[Tuple[T, npt.NDArray[np.float32]]]:
23
+ values: list[T], cmap: str = "winter"
24
+ ) -> Iterator[Tuple[T, npt.NDArray[np.float32]]]:
23
25
  """
24
26
  Assign RGBA colors to a list of values using a colormap.
25
27
 
26
- Each value is mapped linearly to a subset of the unit interval and then converted
28
+ Each value is mapped linearly to a subset of the unit interval and then converted
27
29
  to an RGBA color using the specified colormap.
28
30
 
29
31
  :param values: List of values to map to colors.
@@ -35,65 +37,74 @@ def _bind_to_colors(
35
37
  return zip(values, rgbas)
36
38
 
37
39
 
38
- class FrequencyCutsPanel(BaseSpectrumPanel):
40
+ class FrequencyCutsPanel(BasePanel):
39
41
  """
40
42
  Panel for visualising spectrogram data as frequency cuts.
41
43
 
42
- This panel plots spectrums corresponding to specific time instances
43
- in the spectrogram. Each cut is drawn as a line plot, optionally normalized
44
+ This panel plots spectrums corresponding to specific time instances
45
+ in the spectrogram. Each cut is drawn as a line plot, optionally normalized
44
46
  or converted to decibels above the background.
45
47
  """
48
+
46
49
  def __init__(
47
- self,
48
- spectrogram: Spectrogram,
50
+ self,
51
+ spectrogram: Spectrogram,
49
52
  *times: float | str,
50
53
  dBb: bool = False,
51
- peak_normalise: bool = False
54
+ peak_normalise: bool = False,
52
55
  ) -> None:
53
56
  """Initialise an instance of `FrequencyCutsPanel`.
54
57
 
55
58
  :param spectrogram: The spectrogram to be visualised.
56
- :param *times: Times at which to take frequency cuts. Can be floats (relative time) or
59
+ :param *times: Times at which to take frequency cuts. Can be floats (relative time) or
57
60
  strings (formatted datetimes).
58
61
  :param dBb: If True, plots the spectrums in decibels above the background. Defaults to False.
59
- :param peak_normalise: If True, normalizes each spectrum such that its peak value is 1.
62
+ :param peak_normalise: If True, normalizes each spectrum such that its peak value is 1.
60
63
  Ignored if `dBb` is True. Defaults to False.
61
64
  """
62
- super().__init__(PanelName.FREQUENCY_CUTS,
63
- spectrogram)
64
-
65
+ super().__init__(PanelName.FREQUENCY_CUTS, spectrogram)
66
+
65
67
  if len(times) == 0:
66
- raise ValueError(f"You must specify the time of at least one cut in `*times`")
68
+ raise ValueError(
69
+ f"You must specify the time of at least one cut in `*times`"
70
+ )
67
71
  self._times = times
68
-
72
+
69
73
  self._dBb = dBb
70
74
  self._peak_normalise = peak_normalise
71
75
  self._frequency_cuts: dict[float | datetime, FrequencyCut] = {}
72
76
 
77
+ @property
78
+ def xaxis_type(self) -> Literal[XAxisType.FREQUENCY]:
79
+ return XAxisType.FREQUENCY
73
80
 
74
- def get_frequency_cuts(
75
- self
76
- ) -> dict[float | datetime, FrequencyCut]:
81
+ @property
82
+ def frequencies(self) -> npt.NDArray[np.float32]:
83
+ """The physical frequencies assigned to each spectral component."""
84
+ return self._spectrogram.frequencies
85
+
86
+ def annotate_xaxis(self) -> None:
87
+ """Annotate the x-axis assuming frequency in units of Hz."""
88
+ self._get_ax().set_xlabel("Frequency [Hz]")
89
+
90
+ def get_frequency_cuts(self) -> dict[float | datetime, FrequencyCut]:
77
91
  """
78
92
  Get the frequency cuts for the specified times.
79
93
 
80
- Computes and caches the spectrum for each requested time. The results are
94
+ Computes and caches the spectrum for each requested time. The results are
81
95
  stored as a mapping from time to the corresponding `FrequencyCut`.
82
96
 
83
97
  :return: A dictionary mapping each time to its corresponding frequency cut.
84
98
  """
85
99
  if not self._frequency_cuts:
86
100
  for time in self._times:
87
- frequency_cut = self._spectrogram.get_frequency_cut(time,
88
- dBb=self._dBb,
89
- peak_normalise=self._peak_normalise)
101
+ frequency_cut = self._spectrogram.get_frequency_cut(
102
+ time, dBb=self._dBb, peak_normalise=self._peak_normalise
103
+ )
90
104
  self._frequency_cuts[frequency_cut.time] = frequency_cut
91
105
  return self._frequency_cuts
92
-
93
106
 
94
- def get_cut_times(
95
- self
96
- ) -> list[float | datetime]:
107
+ def get_cut_times(self) -> list[float | datetime]:
97
108
  """
98
109
  Get the exact times of the frequency cuts.
99
110
 
@@ -103,40 +114,36 @@ class FrequencyCutsPanel(BaseSpectrumPanel):
103
114
  """
104
115
  frequency_cuts = self.get_frequency_cuts()
105
116
  return list(frequency_cuts.keys())
106
-
107
117
 
108
- def draw(
109
- self
110
- ) -> None:
118
+ def draw(self) -> None:
111
119
  """Draw the frequency cuts onto the panel."""
112
120
  frequency_cuts = self.get_frequency_cuts()
113
121
  for time, color in self.bind_to_colors():
114
122
  frequency_cut = frequency_cuts[time]
115
- self.ax.step(self.frequencies, # convert to MHz
116
- frequency_cut.cut,
117
- where='mid',
118
- color = color)
119
-
120
-
121
- def annotate_yaxis(
122
- self
123
- ) -> None:
123
+ self._get_ax().step(
124
+ self.frequencies, # convert to MHz
125
+ frequency_cut.cut,
126
+ where="mid",
127
+ color=color,
128
+ )
129
+
130
+ def annotate_yaxis(self) -> None:
124
131
  """Annotate the y-axis of the panel based on the current state.
125
132
 
126
133
  The y-axis label reflects whether the data is in decibels above the background (`dBb`),
127
134
  normalized to peak values, or in the original units of the spectrogram.
128
135
  """
136
+ ax = self._get_ax()
129
137
  if self._dBb:
130
- self.ax.set_ylabel('dBb')
138
+ ax.set_ylabel("dBb")
131
139
  elif self._peak_normalise:
132
140
  # no y-axis label if we are peak normalising
133
- return
141
+ return
134
142
  else:
135
- self.ax.set_ylabel(f'{self._spectrogram.spectrum_unit.value.capitalize()}')
143
+ ax.set_ylabel(f"{self._spectrogram.spectrum_unit.value.capitalize()}")
136
144
 
137
-
138
145
  def bind_to_colors(
139
- self
146
+ self,
140
147
  ) -> Iterator[Tuple[float | datetime, npt.NDArray[np.float32]]]:
141
148
  """
142
149
  Bind each frequency cut time to an RGBA color.
@@ -145,73 +152,73 @@ class FrequencyCutsPanel(BaseSpectrumPanel):
145
152
 
146
153
  :return: An iterator of tuples, each containing a cut time and its corresponding RGBA color.
147
154
  """
148
- return _bind_to_colors(self.get_cut_times(), cmap = self.panel_format.line_cmap)
149
-
150
-
155
+ return _bind_to_colors(
156
+ self.get_cut_times(), cmap=self.get_panel_format().line_cmap
157
+ )
158
+
159
+
151
160
  class TimeCutsPanel(BaseTimeSeriesPanel):
152
161
  """
153
162
  Panel for visualising spectrogram data as time series of spectral components.
154
163
 
155
- This panel plots the time evolution of spectral components at specific
156
- frequencies in the spectrogram. Each time series is drawn as a line plot,
164
+ This panel plots the time evolution of spectral components at specific
165
+ frequencies in the spectrogram. Each time series is drawn as a line plot,
157
166
  optionally normalized, background-subtracted, or converted to decibels above the background.
158
167
  """
168
+
159
169
  def __init__(
160
- self,
161
- spectrogram: Spectrogram,
170
+ self,
171
+ spectrogram: Spectrogram,
162
172
  *frequencies: float,
163
173
  dBb: bool = False,
164
174
  peak_normalise: bool = False,
165
- background_subtract: bool = False
175
+ background_subtract: bool = False,
166
176
  ) -> None:
167
177
  """Initialise an instance of `TimeCutsPanel`.
168
178
 
169
179
  :param spectrogram: The spectrogram to be visualised.
170
180
  :param *frequencies: Frequencies at which to extract time series.
171
181
  :param dBb: If True, returns the cuts in decibels above the background. Defaults to False.
172
- :param peak_normalise: If True, normalizes each time series so its peak value is 1.
182
+ :param peak_normalise: If True, normalizes each time series so its peak value is 1.
173
183
  Ignored if `dBb` is True. Defaults to False.
174
- :param background_subtract: If True, subtracts the background from each time series.
184
+ :param background_subtract: If True, subtracts the background from each time series.
175
185
  Ignored if `dBb` is True. Defaults to False.
176
186
  """
177
- super().__init__(PanelName.TIME_CUTS,
178
- spectrogram)
179
-
187
+ super().__init__(PanelName.TIME_CUTS, spectrogram)
188
+
180
189
  if len(frequencies) == 0:
181
- raise ValueError(f"You must specify the frequency of at least one cut in `*frequencies`.")
190
+ raise ValueError(
191
+ f"You must specify the frequency of at least one cut in `*frequencies`."
192
+ )
182
193
  self._frequencies = frequencies
183
-
194
+
184
195
  self._dBb = dBb
185
196
  self._peak_normalise = peak_normalise
186
197
  self._background_subtract = background_subtract
187
- self._time_cuts: dict[float, TimeCut] = {}
188
-
198
+ self._time_cuts: dict[float, TimeCut] = {}
189
199
 
190
- def get_time_cuts(
191
- self
192
- ) -> dict[float, TimeCut]:
200
+ def get_time_cuts(self) -> dict[float, TimeCut]:
193
201
  """
194
202
  Get the time cuts for the specified frequencies.
195
203
 
196
- Computes and caches the time series for each requested frequency. The results
204
+ Computes and caches the time series for each requested frequency. The results
197
205
  are stored as a mapping from frequency to `TimeCut`.
198
206
 
199
207
  :return: A dictionary mapping each frequency to its corresponding time cut.
200
208
  """
201
209
  if not self._time_cuts:
202
210
  for frequency in self._frequencies:
203
- time_cut = self._spectrogram.get_time_cut(frequency,
204
- dBb=self._dBb,
205
- peak_normalise=self._peak_normalise,
206
- correct_background=self._background_subtract,
207
- return_time_type=self.time_type)
211
+ time_cut = self._spectrogram.get_time_cut(
212
+ frequency,
213
+ dBb=self._dBb,
214
+ peak_normalise=self._peak_normalise,
215
+ correct_background=self._background_subtract,
216
+ return_time_type=self.get_time_type(),
217
+ )
208
218
  self._time_cuts[time_cut.frequency] = time_cut
209
219
  return self._time_cuts
210
-
211
220
 
212
- def get_frequencies(
213
- self
214
- ) -> list[float]:
221
+ def get_frequencies(self) -> list[float]:
215
222
  """
216
223
  Get the exact frequencies for the spectral components being plotted.
217
224
 
@@ -220,40 +227,29 @@ class TimeCutsPanel(BaseTimeSeriesPanel):
220
227
  time_cuts = self.get_time_cuts()
221
228
  return list(time_cuts.keys())
222
229
 
223
-
224
- def draw(
225
- self
226
- ) -> None:
230
+ def draw(self) -> None:
227
231
  """Draw the time series for each spectral component onto the panel."""
228
232
  time_cuts = self.get_time_cuts()
229
233
  for frequency, color in self.bind_to_colors():
230
234
  time_cut = time_cuts[frequency]
231
- self.ax.step(self.times,
232
- time_cut.cut,
233
- where='mid',
234
- color = color)
235
-
236
-
237
- def annotate_yaxis(
238
- self
239
- ) -> None:
235
+ self._get_ax().step(self.times, time_cut.cut, where="mid", color=color)
236
+
237
+ def annotate_yaxis(self) -> None:
240
238
  """
241
239
  Annotate the y-axis of the panel based on the current state.
242
240
 
243
241
  The y-axis label reflects whether the data is in decibels above the background (`dBb`),
244
242
  normalized to peak values, or in the original units of the spectrogram.
245
243
  """
244
+ ax = self._get_ax()
246
245
  if self._dBb:
247
- self.ax.set_ylabel('dBb')
246
+ ax.set_ylabel("dBb")
248
247
  elif self._peak_normalise:
249
- return # no y-axis label if we are peak normalising.
248
+ return # no y-axis label if we are peak normalising.
250
249
  else:
251
- self.ax.set_ylabel(f'{self._spectrogram.spectrum_unit.value.capitalize()}')
250
+ ax.set_ylabel(f"{self._spectrogram.spectrum_unit.value.capitalize()}")
252
251
 
253
-
254
- def bind_to_colors(
255
- self
256
- ) -> Iterator[Tuple[float, npt.NDArray[np.float32]]]:
252
+ def bind_to_colors(self) -> Iterator[Tuple[float, npt.NDArray[np.float32]]]:
257
253
  """
258
254
  Bind each spectral component's frequency to an RGBA color.
259
255
 
@@ -261,53 +257,60 @@ class TimeCutsPanel(BaseTimeSeriesPanel):
261
257
 
262
258
  :return: An iterator of tuples, each containing a frequency and its corresponding RGBA color.
263
259
  """
264
- return _bind_to_colors(self.get_frequencies(), cmap = self.panel_format.line_cmap)
265
-
260
+ return _bind_to_colors(
261
+ self.get_frequencies(), cmap=self.get_panel_format().line_cmap
262
+ )
263
+
266
264
 
267
265
  class IntegralOverFrequencyPanel(BaseTimeSeriesPanel):
268
266
  """Panel for visualising the spectrogram integrated over frequency.
269
267
 
270
- This panel plots the spectrogram numerically integrated over frequency as a time
271
- series. The result can be normalized to its peak value or adjusted by subtracting
268
+ This panel plots the spectrogram numerically integrated over frequency as a time
269
+ series. The result can be normalized to its peak value or adjusted by subtracting
272
270
  the background.
273
271
  """
274
- def __init__(self,
275
- spectrogram: Spectrogram,
276
- peak_normalise: bool = False,
277
- background_subtract: bool = False):
272
+
273
+ def __init__(
274
+ self,
275
+ spectrogram: Spectrogram,
276
+ peak_normalise: bool = False,
277
+ background_subtract: bool = False,
278
+ ):
278
279
  """Initialise an instance of `IntegralOverFrequencyPanel`.
279
-
280
+
280
281
  :param spectrogram: The spectrogram to be visualised.
281
282
  :param peak_normalise: If True, normalizes the integral so its peak value is 1. Defaults to False.
282
283
  :param background_subtract: If True, subtracts the background after computing the integral. Defaults to False.
283
284
  """
284
- super().__init__(PanelName.INTEGRAL_OVER_FREQUENCY,
285
- spectrogram)
285
+ super().__init__(PanelName.INTEGRAL_OVER_FREQUENCY, spectrogram)
286
286
  self._peak_normalise = peak_normalise
287
287
  self._background_subtract = background_subtract
288
288
 
289
-
290
289
  def draw(self):
291
290
  """Integrate the spectrogram over frequency and plot the result."""
292
- I = self._spectrogram.integrate_over_frequency(correct_background=self._background_subtract,
293
- peak_normalise=self._peak_normalise)
294
- self.ax.step(self.times, I, where="mid", color = self.panel_format.line_color)
295
-
291
+ I = self._spectrogram.integrate_over_frequency(
292
+ correct_background=self._background_subtract,
293
+ peak_normalise=self._peak_normalise,
294
+ )
295
+ self._get_ax().step(
296
+ self.times, I, where="mid", color=self.get_panel_format().line_color
297
+ )
296
298
 
297
299
  def annotate_yaxis(self):
298
300
  """This panel does not annotate the y-axis."""
299
-
300
-
301
+
302
+
301
303
  class SpectrogramPanel(BaseTimeSeriesPanel):
302
304
  """
303
305
  Panel for visualising the full spectrogram.
304
306
 
305
- This panel plots the spectrogram as a colormap, with optional log normalization or
307
+ This panel plots the spectrogram as a colormap, with optional log normalization or
306
308
  in units of decibels above the background.
307
309
  """
310
+
308
311
  def __init__(
309
- self,
310
- spectrogram: Spectrogram,
312
+ self,
313
+ spectrogram: Spectrogram,
311
314
  log_norm: bool = False,
312
315
  dBb: bool = False,
313
316
  vmin: Optional[float] = None,
@@ -321,67 +324,65 @@ class SpectrogramPanel(BaseTimeSeriesPanel):
321
324
  :param vmin: Minimum value for the colormap. Only applies if `dBb` is True. Defaults to None.
322
325
  :param vmax: Maximum value for the colormap. Only applies if `dBb` is True. Defaults to None.
323
326
  """
324
- super().__init__(PanelName.SPECTROGRAM,
325
- spectrogram)
327
+ super().__init__(PanelName.SPECTROGRAM, spectrogram)
326
328
  self._log_norm = log_norm
327
329
  self._dBb = dBb
328
330
  self._vmin = vmin
329
331
  self._vmax = vmax
330
332
 
331
-
332
333
  def _draw_dBb(self) -> None:
333
334
  """Plot the spectrogram in decibels above the background (dBb).
334
335
 
335
- This method handles plotting the spectrogram with dBb scaling, applying
336
+ This method handles plotting the spectrogram with dBb scaling, applying
336
337
  colormap bounds (`vmin` and `vmax`) and adding a colorbar to the panel.
337
338
  """
338
339
  dynamic_spectra = self._spectrogram.compute_dynamic_spectra_dBb()
339
-
340
+
340
341
  # use defaults if neither vmin or vmax is specified
341
342
  vmin = self._vmin or -1
342
- vmax = self._vmax or 2
343
+ vmax = self._vmax or 2
343
344
 
345
+ ax = self._get_ax()
344
346
  # Plot the spectrogram
345
- pcm = self.ax.pcolormesh(
347
+ pcm = ax.pcolormesh(
346
348
  self.times,
347
349
  self._spectrogram.frequencies,
348
350
  dynamic_spectra,
349
351
  vmin=vmin,
350
352
  vmax=vmax,
351
- cmap=self.panel_format.spectrogram_cmap,
353
+ cmap=self.get_panel_format().spectrogram_cmap,
352
354
  )
353
355
 
354
356
  # Add colorbar
355
357
  cbar_ticks = np.linspace(vmin, vmax, 6)
356
- cbar = self.fig.colorbar(pcm, ax=self.ax, ticks=cbar_ticks)
358
+ cbar = self._get_fig().colorbar(pcm, ax=ax, ticks=cbar_ticks)
357
359
  cbar.set_label("dBb")
358
360
 
359
-
360
361
  def _draw_normal(self) -> None:
361
362
  """Plot the spectrogram with optional logarithmic normalization.
362
363
 
363
- This method handles plotting the spectrogram without dBb scaling, using
364
+ This method handles plotting the spectrogram without dBb scaling, using
364
365
  linear or log normalization based on the `log_norm` attribute.
365
366
  """
366
367
  dynamic_spectra = self._spectrogram.dynamic_spectra
367
-
368
368
 
369
369
  if self._log_norm:
370
- norm = LogNorm(vmin=np.nanmin(dynamic_spectra[dynamic_spectra > 0]),
371
- vmax=np.nanmax(dynamic_spectra))
370
+ norm = LogNorm(
371
+ vmin=np.nanmin(dynamic_spectra[dynamic_spectra > 0]),
372
+ vmax=np.nanmax(dynamic_spectra),
373
+ )
372
374
  else:
373
375
  norm = None
374
376
 
375
377
  # Plot the spectrogram
376
- self.ax.pcolormesh(
378
+ self._get_ax().pcolormesh(
377
379
  self.times,
378
380
  self._spectrogram.frequencies,
379
381
  dynamic_spectra,
380
- cmap=self.panel_format.spectrogram_cmap,
382
+ cmap=self.get_panel_format().spectrogram_cmap,
381
383
  norm=norm,
382
384
  )
383
385
 
384
-
385
386
  def draw(self) -> None:
386
387
  """Draw the spectrogram onto the panel."""
387
388
  if self._dBb:
@@ -389,46 +390,35 @@ class SpectrogramPanel(BaseTimeSeriesPanel):
389
390
  else:
390
391
  self._draw_normal()
391
392
 
392
-
393
- def annotate_yaxis(
394
- self
395
- ) -> None:
393
+ def annotate_yaxis(self) -> None:
396
394
  """Annotate the yaxis, assuming units of Hz."""
397
- self.ax.set_ylabel('Frequency [Hz]')
395
+ self._get_ax().set_ylabel("Frequency [Hz]")
398
396
  return
399
-
400
-
401
- def overlay_time_cuts(
402
- self,
403
- cuts_panel: TimeCutsPanel
404
- ) -> None:
397
+
398
+ def overlay_time_cuts(self, cuts_panel: TimeCutsPanel) -> None:
405
399
  """
406
400
  Overlay horizontal lines on the spectrogram to indicate time cuts.
407
401
 
408
- The lines correspond to the frequencies of the cuts on a `TimeCutsPanel`.
402
+ The lines correspond to the frequencies of the cuts on a `TimeCutsPanel`.
409
403
  Colors are matched to the lines on the `TimeCutsPanel`.
410
404
 
411
405
  :param cuts_panel: The `TimeCutsPanel` containing the cut frequencies to overlay.
412
406
  """
413
407
  for frequency, color in cuts_panel.bind_to_colors():
414
- self.ax.axhline(frequency,
415
- color = color,
416
- linewidth=self.panel_format.line_width)
417
-
418
-
419
- def overlay_frequency_cuts(
420
- self,
421
- cuts_panel: FrequencyCutsPanel
422
- ) -> None:
408
+ self._get_ax().axhline(
409
+ frequency, color=color, linewidth=self.get_panel_format().line_width
410
+ )
411
+
412
+ def overlay_frequency_cuts(self, cuts_panel: FrequencyCutsPanel) -> None:
423
413
  """
424
414
  Overlay vertical lines on the spectrogram to indicate frequency cuts.
425
415
 
426
- The lines correspond to the times of the cuts on a `FrequencyCutsPanel`.
416
+ The lines correspond to the times of the cuts on a `FrequencyCutsPanel`.
427
417
  Colors are matched to the lines on the `FrequencyCutsPanel`.
428
418
 
429
419
  :param cuts_panel: The `FrequencyCutsPanel` containing the cut times to overlay.
430
420
  """
431
421
  for time, color in cuts_panel.bind_to_colors():
432
- self.ax.axvline(time,
433
- color = color,
434
- linewidth=self.panel_format.line_width)
422
+ self._get_ax().axvline(
423
+ time, color=color, linewidth=self.get_panel_format().line_width
424
+ )
@@ -11,6 +11,9 @@ from ._factory import get_event_handler, get_event_handler_cls_from_tag
11
11
  from ._post_processor import start_post_processor
12
12
 
13
13
  __all__ = [
14
- "FixedEventHandler", "SweptEventHandler", "start_post_processor",
15
- "get_event_handler", "get_event_handler_cls_from_tag"
16
- ]
14
+ "FixedEventHandler",
15
+ "SweptEventHandler",
16
+ "start_post_processor",
17
+ "get_event_handler",
18
+ "get_event_handler_cls_from_tag",
19
+ ]