modusa 0.4.29__py3-none-any.whl → 0.4.30__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.
- modusa/__init__.py +9 -8
- modusa/tools/__init__.py +7 -2
- modusa/tools/ann_saver.py +30 -0
- modusa/tools/audio_recorder.py +0 -1
- modusa/tools/youtube_downloader.py +1 -4
- {modusa-0.4.29.dist-info → modusa-0.4.30.dist-info}/METADATA +2 -2
- modusa-0.4.30.dist-info/RECORD +21 -0
- pyproject.toml +2 -2
- modusa/config.py +0 -18
- modusa/decorators.py +0 -176
- modusa/devtools/generate_docs_source.py +0 -92
- modusa/devtools/generate_template.py +0 -144
- modusa/devtools/list_authors.py +0 -2
- modusa/devtools/list_plugins.py +0 -60
- modusa/devtools/main.py +0 -45
- modusa/devtools/templates/generator.py +0 -24
- modusa/devtools/templates/io.py +0 -24
- modusa/devtools/templates/model.py +0 -47
- modusa/devtools/templates/plugin.py +0 -41
- modusa/devtools/templates/test.py +0 -10
- modusa/devtools/templates/tool.py +0 -24
- modusa/generators/__init__.py +0 -13
- modusa/generators/audio.py +0 -188
- modusa/generators/audio_waveforms.py +0 -236
- modusa/generators/base.py +0 -29
- modusa/generators/ftds.py +0 -298
- modusa/generators/s1d.py +0 -270
- modusa/generators/s2d.py +0 -300
- modusa/generators/s_ax.py +0 -102
- modusa/generators/t_ax.py +0 -64
- modusa/generators/tds.py +0 -267
- modusa/models/__init__.py +0 -14
- modusa/models/audio.py +0 -90
- modusa/models/base.py +0 -70
- modusa/models/data.py +0 -457
- modusa/models/ftds.py +0 -584
- modusa/models/s1d.py +0 -578
- modusa/models/s2d.py +0 -619
- modusa/models/s_ax.py +0 -448
- modusa/models/t_ax.py +0 -335
- modusa/models/tds.py +0 -465
- modusa/plugins/__init__.py +0 -3
- modusa/plugins/base.py +0 -100
- modusa/tools/_plotter_old.py +0 -629
- modusa/tools/audio_saver.py +0 -30
- modusa/tools/base.py +0 -43
- modusa/tools/math_ops.py +0 -335
- modusa/utils/__init__.py +0 -1
- modusa/utils/config.py +0 -25
- modusa/utils/excp.py +0 -49
- modusa/utils/logger.py +0 -18
- modusa/utils/np_func_cat.py +0 -44
- modusa/utils/plot.py +0 -142
- modusa-0.4.29.dist-info/RECORD +0 -65
- {modusa-0.4.29.dist-info → modusa-0.4.30.dist-info}/WHEEL +0 -0
- {modusa-0.4.29.dist-info → modusa-0.4.30.dist-info}/entry_points.txt +0 -0
- {modusa-0.4.29.dist-info → modusa-0.4.30.dist-info}/licenses/LICENSE.md +0 -0
modusa/models/s1d.py
DELETED
@@ -1,578 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
|
3
|
-
|
4
|
-
from modusa import excp
|
5
|
-
from modusa.decorators import immutable_property, validate_args_type
|
6
|
-
from .base import ModusaSignal
|
7
|
-
from .data import Data
|
8
|
-
from .s_ax import SAx
|
9
|
-
from .t_ax import TAx
|
10
|
-
from modusa.tools.math_ops import MathOps
|
11
|
-
from typing import Self, Any, Callable
|
12
|
-
from types import NoneType
|
13
|
-
import numpy as np
|
14
|
-
import matplotlib.pyplot as plt
|
15
|
-
import copy
|
16
|
-
|
17
|
-
class S1D(ModusaSignal):
|
18
|
-
"""
|
19
|
-
Space to represent any 1D Signal.
|
20
|
-
|
21
|
-
Note
|
22
|
-
----
|
23
|
-
- Use :class:`~modusa.generators.s1d.S1DGen` API to instantiate this class.
|
24
|
-
- The signal can have uniform/non-uniform axis.
|
25
|
-
|
26
|
-
|
27
|
-
Parameters
|
28
|
-
----------
|
29
|
-
data: Data
|
30
|
-
- Data object holding the main array.
|
31
|
-
sax: SAx
|
32
|
-
- Axis for the signal.
|
33
|
-
title: str
|
34
|
-
- Title for the signal.
|
35
|
-
- Default: None => ''
|
36
|
-
- This is used as the title while plotting.
|
37
|
-
"""
|
38
|
-
|
39
|
-
#--------Meta Information----------
|
40
|
-
_name = "Signal 1D"
|
41
|
-
_nickname = "signal" # This is to be used in repr/str methods
|
42
|
-
_description = "Space to represent any 1D Signal."
|
43
|
-
_author_name = "Ankit Anand"
|
44
|
-
_author_email = "ankit0.anand0@gmail.com"
|
45
|
-
_created_at = "2025-07-20"
|
46
|
-
#----------------------------------
|
47
|
-
|
48
|
-
def __init__(self, y, x, title = None):
|
49
|
-
super().__init__() # Instantiating `ModusaSignal` class
|
50
|
-
|
51
|
-
if not (isinstance(y, Data) and isinstance(x, SAx)):
|
52
|
-
raise TypeError(f"`y` must be `Data` instance and `x` must be `SAx` instance, got {type(y)} and {type(x)}")
|
53
|
-
|
54
|
-
assert y.ndim == 1
|
55
|
-
assert y.shape == x.shape, f"y and x shape must match"
|
56
|
-
|
57
|
-
# All these are private and we do not expose it to users directly.
|
58
|
-
self._y = y
|
59
|
-
self._x = x
|
60
|
-
self._title = title or self._name
|
61
|
-
|
62
|
-
|
63
|
-
#-----------------------------------
|
64
|
-
# Properties (User Facing)
|
65
|
-
#-----------------------------------
|
66
|
-
|
67
|
-
@property
|
68
|
-
def y(self) -> Data:
|
69
|
-
return self._y
|
70
|
-
|
71
|
-
@property
|
72
|
-
def x(self) -> SAx:
|
73
|
-
return self._x
|
74
|
-
|
75
|
-
@property
|
76
|
-
def title(self) -> str:
|
77
|
-
return self._title
|
78
|
-
|
79
|
-
@property
|
80
|
-
def shape(self) -> tuple:
|
81
|
-
return self.y.shape
|
82
|
-
|
83
|
-
@property
|
84
|
-
def ndim(self) -> int:
|
85
|
-
return self.y.ndim # Should be 1
|
86
|
-
|
87
|
-
@property
|
88
|
-
def size(self) -> int:
|
89
|
-
return self.y.size
|
90
|
-
|
91
|
-
#===================================
|
92
|
-
|
93
|
-
#-------------------------------
|
94
|
-
# NumPy Protocol
|
95
|
-
#-------------------------------
|
96
|
-
|
97
|
-
def __array__(self, dtype=None) -> np.ndarray:
|
98
|
-
return np.asarray(self.y.values, dtype=dtype)
|
99
|
-
|
100
|
-
def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
|
101
|
-
"""
|
102
|
-
Supports NumPy universal functions on the Signal1D object.
|
103
|
-
"""
|
104
|
-
from .data import Data # Ensure this is the same Data class you're using
|
105
|
-
from modusa.utils import np_func_cat as nfc
|
106
|
-
|
107
|
-
raw_inputs = [
|
108
|
-
np.asarray(obj.y) if isinstance(obj, type(self)) else obj
|
109
|
-
for obj in inputs
|
110
|
-
]
|
111
|
-
|
112
|
-
result = getattr(ufunc, method)(*raw_inputs, **kwargs)
|
113
|
-
|
114
|
-
y = Data(values=result, label=None) # label=None or you could copy from self.y.label
|
115
|
-
x = self.x.copy()
|
116
|
-
|
117
|
-
if y.shape != x.shape:
|
118
|
-
raise ValueError(f"`{ufunc.__name__}` caused shape mismatch between data and axis, please create a github issue")
|
119
|
-
|
120
|
-
return self.__class__(y=y, x=x, title=self.title)
|
121
|
-
|
122
|
-
def __array_function__(self, func, types, args, kwargs):
|
123
|
-
"""
|
124
|
-
Additional numpy function support.
|
125
|
-
"""
|
126
|
-
from modusa.utils import np_func_cat as nfc
|
127
|
-
|
128
|
-
if not all(issubclass(t, type(self)) for t in types):
|
129
|
-
return NotImplemented
|
130
|
-
|
131
|
-
# Not supporting concatenate like operations as axis any random axis can't be concatenated
|
132
|
-
if func in nfc.CONCAT_FUNCS:
|
133
|
-
raise NotImplementedError(f"`{func.__name__}` is not yet tested on modusa signal, please create a GitHub issue.")
|
134
|
-
|
135
|
-
# Single signal input expected
|
136
|
-
signal = args[0]
|
137
|
-
result: Data = func(signal.y, **kwargs)
|
138
|
-
axis = kwargs.get("axis", None)
|
139
|
-
keepdims = kwargs.get("keepdims", None)
|
140
|
-
|
141
|
-
if func in nfc.REDUCTION_FUNCS:
|
142
|
-
if keepdims is None or keepdims is True: # Default state is True => return 1D signal by wrapping the scalar
|
143
|
-
from .s_ax import SAx
|
144
|
-
dummy_x = SAx(0, "")
|
145
|
-
return self.__class__(y=result, x=dummy_x, title=signal.title)
|
146
|
-
elif keepdims is False: # Return Data
|
147
|
-
from .data import Data
|
148
|
-
return Data(values=result, label=None)
|
149
|
-
|
150
|
-
elif func in nfc.X_NEEDS_ADJUSTMENT_FUNCS:
|
151
|
-
# You must define logic for adjusting x
|
152
|
-
raise NotImplementedError(f"{func.__name__} requires x-axis adjustment logic.")
|
153
|
-
|
154
|
-
else:
|
155
|
-
raise NotImplementedError(f"`{func.__name__}` is not yet tested on modusa signal, please create a GitHub issue.")
|
156
|
-
|
157
|
-
#================================
|
158
|
-
|
159
|
-
#-------------------------------
|
160
|
-
# Indexing
|
161
|
-
#-------------------------------
|
162
|
-
|
163
|
-
def __getitem__(self, key):
|
164
|
-
"""
|
165
|
-
Return a sliced or indexed view of the data.
|
166
|
-
|
167
|
-
Parameters
|
168
|
-
----------
|
169
|
-
key : int | slice | S1D
|
170
|
-
- Index to apply to the values.
|
171
|
-
|
172
|
-
Returns
|
173
|
-
-------
|
174
|
-
S1D
|
175
|
-
A new S1D object with sliced values and same meta data.
|
176
|
-
"""
|
177
|
-
|
178
|
-
if not isinstance(key, (int, slice)):
|
179
|
-
raise TypeError(f"Invalid key type: {type(key)}")
|
180
|
-
|
181
|
-
sliced_y = self.y[key]
|
182
|
-
sliced_x = self.x[key]
|
183
|
-
|
184
|
-
return self.__class__(y=sliced_y, x=sliced_x, title=self.title)
|
185
|
-
|
186
|
-
def __setitem__(self, key, value):
|
187
|
-
"""
|
188
|
-
Set values at the specified index.
|
189
|
-
|
190
|
-
Parameters
|
191
|
-
----------
|
192
|
-
key : int | slice | array-like | boolean array | S1D
|
193
|
-
Index to apply to the values.
|
194
|
-
value : int | float | array-like
|
195
|
-
Value(s) to set.
|
196
|
-
"""
|
197
|
-
|
198
|
-
if not isinstance(key, (int, slice)):
|
199
|
-
raise TypeError(f"Invalid key type: {type(key)}")
|
200
|
-
|
201
|
-
self.y[key] = value # In-place assignment
|
202
|
-
|
203
|
-
#===================================
|
204
|
-
|
205
|
-
#-------------------------------
|
206
|
-
# Basic arithmetic operations
|
207
|
-
#-------------------------------
|
208
|
-
def __add__(self, other):
|
209
|
-
if isinstance(other, type(self)):
|
210
|
-
if not self.has_same_axis_as(other):
|
211
|
-
raise ValueError("Axes are not aligned for the operation.")
|
212
|
-
return np.add(self, other)
|
213
|
-
|
214
|
-
def __radd__(self, other):
|
215
|
-
if isinstance(other, type(self)):
|
216
|
-
if not self.has_same_axis_as(other):
|
217
|
-
raise ValueError("Axes are not aligned for the operation.")
|
218
|
-
return np.add(other, self)
|
219
|
-
|
220
|
-
def __sub__(self, other):
|
221
|
-
if isinstance(other, type(self)):
|
222
|
-
if not self.has_same_axis_as(other):
|
223
|
-
raise ValueError("Axes are not aligned for the operation.")
|
224
|
-
return np.subtract(self, other)
|
225
|
-
|
226
|
-
def __rsub__(self, other):
|
227
|
-
if isinstance(other, type(self)):
|
228
|
-
if not self.has_same_axis_as(other):
|
229
|
-
raise ValueError("Axes are not aligned for the operation.")
|
230
|
-
return np.subtract(other, self)
|
231
|
-
|
232
|
-
def __mul__(self, other):
|
233
|
-
if isinstance(other, type(self)):
|
234
|
-
if not self.has_same_axis_as(other):
|
235
|
-
raise ValueError("Axes are not aligned for the operation.")
|
236
|
-
return np.multiply(self, other)
|
237
|
-
|
238
|
-
def __rmul__(self, other):
|
239
|
-
if isinstance(other, type(self)):
|
240
|
-
if not self.has_same_axis_as(other):
|
241
|
-
raise ValueError("Axes are not aligned for the operation.")
|
242
|
-
return np.multiply(other, self)
|
243
|
-
|
244
|
-
def __truediv__(self, other):
|
245
|
-
if isinstance(other, type(self)):
|
246
|
-
if not self.has_same_axis_as(other):
|
247
|
-
raise ValueError("Axes are not aligned for the operation.")
|
248
|
-
return np.divide(self, other)
|
249
|
-
|
250
|
-
def __rtruediv__(self, other):
|
251
|
-
if isinstance(other, type(self)):
|
252
|
-
if not self.has_same_axis_as(other):
|
253
|
-
raise ValueError("Axes are not aligned for the operation.")
|
254
|
-
return np.divide(other, self)
|
255
|
-
|
256
|
-
def __floordiv__(self, other):
|
257
|
-
if isinstance(other, type(self)):
|
258
|
-
if not self.has_same_axis_as(other):
|
259
|
-
raise ValueError("Axes are not aligned for the operation.")
|
260
|
-
return np.floor_divide(self, other)
|
261
|
-
|
262
|
-
def __rfloordiv__(self, other):
|
263
|
-
if not self.has_same_axis_as(other):
|
264
|
-
raise ValueError("Axes are not aligned for the operation.")
|
265
|
-
return np.floor_divide(other, self)
|
266
|
-
|
267
|
-
def __pow__(self, other):
|
268
|
-
if isinstance(other, type(self)):
|
269
|
-
if not self.has_same_axis_as(other):
|
270
|
-
raise ValueError("Axes are not aligned for the operation.")
|
271
|
-
return np.power(self, other)
|
272
|
-
|
273
|
-
def __rpow__(self, other):
|
274
|
-
if isinstance(other, type(self)):
|
275
|
-
if not self.has_same_axis_as(other):
|
276
|
-
raise ValueError("Axes are not aligned for the operation.")
|
277
|
-
return np.power(other, self)
|
278
|
-
|
279
|
-
#===============================
|
280
|
-
|
281
|
-
|
282
|
-
#-------------------------------
|
283
|
-
# Basic comparison operations
|
284
|
-
#-------------------------------
|
285
|
-
def __eq__(self, other):
|
286
|
-
return np.equal(self, other)
|
287
|
-
|
288
|
-
def __ne__(self, other):
|
289
|
-
return np.not_equal(self, other)
|
290
|
-
|
291
|
-
def __lt__(self, other):
|
292
|
-
return np.less(self, other)
|
293
|
-
|
294
|
-
def __le__(self, other):
|
295
|
-
return np.less_equal(self, other)
|
296
|
-
|
297
|
-
def __gt__(self, other):
|
298
|
-
return np.greater(self, other)
|
299
|
-
|
300
|
-
def __ge__(self, other):
|
301
|
-
return np.greater_equal(self, other)
|
302
|
-
|
303
|
-
#===============================
|
304
|
-
|
305
|
-
|
306
|
-
#-----------------------------------
|
307
|
-
# Utility Methods
|
308
|
-
#-----------------------------------
|
309
|
-
|
310
|
-
def unpack(self):
|
311
|
-
"""
|
312
|
-
Unpacks the object into easy to work
|
313
|
-
with data structures.
|
314
|
-
|
315
|
-
Returns
|
316
|
-
-------
|
317
|
-
(np.ndarray, np.ndarray)
|
318
|
-
- y: Signal data array.
|
319
|
-
- x: Signal axis array.
|
320
|
-
"""
|
321
|
-
|
322
|
-
y = self.y.values
|
323
|
-
x = self.x.values
|
324
|
-
|
325
|
-
return (y, x)
|
326
|
-
|
327
|
-
def copy(self) -> Self:
|
328
|
-
"""
|
329
|
-
Returns a new copy of the signal.
|
330
|
-
|
331
|
-
Returns
|
332
|
-
-------
|
333
|
-
Self
|
334
|
-
A new copy of the object.
|
335
|
-
"""
|
336
|
-
copied_y = self.y.copy()
|
337
|
-
copied_x = self.x.copy()
|
338
|
-
title = self.title # Immutable, hence no need to copy
|
339
|
-
|
340
|
-
return self.__class__(y=copied_y, x=copied_x, title=title)
|
341
|
-
|
342
|
-
def set_meta_info(self, title=None, y_label=None, x_label=None) -> None:
|
343
|
-
"""
|
344
|
-
Set meta info about the signal.
|
345
|
-
|
346
|
-
Parameters
|
347
|
-
----------
|
348
|
-
title: str
|
349
|
-
- Title for the signal
|
350
|
-
- e.g. "Speedometer"
|
351
|
-
y_label: str
|
352
|
-
- Label for the y-axis.
|
353
|
-
- e.g. "Speeed (m/s)"
|
354
|
-
x_label: str
|
355
|
-
- Label for the x-axis.
|
356
|
-
- e.g. "Distance (m)"
|
357
|
-
"""
|
358
|
-
|
359
|
-
y, x = self.y, self.x
|
360
|
-
|
361
|
-
new_title = str(title) if title is not None else self.title
|
362
|
-
new_y_label = str(y_label) if y_label is not None else y.label
|
363
|
-
new_x_label = str(x_label) if x_label is not None else x.label
|
364
|
-
|
365
|
-
# We create a new copy of the data and axis
|
366
|
-
new_y = y.__class__(values=y.values().copy(), label=y_label)
|
367
|
-
new_x = x.__class__(values=x.values().copy(), label=x_label)
|
368
|
-
|
369
|
-
return self.__class__(y=new_y, x=new_x, title=title)
|
370
|
-
|
371
|
-
|
372
|
-
def is_same_as(self, other: Self) -> bool:
|
373
|
-
"""
|
374
|
-
Check if two `S1D` instances are equal.
|
375
|
-
"""
|
376
|
-
|
377
|
-
if not isinstance(other, type(self)):
|
378
|
-
return False
|
379
|
-
|
380
|
-
if not self.y.is_same_as(other.y):
|
381
|
-
return False
|
382
|
-
|
383
|
-
if not self.x.is_same_as(other.x):
|
384
|
-
return False
|
385
|
-
|
386
|
-
return True
|
387
|
-
|
388
|
-
def has_same_axis_as(self, other) -> bool:
|
389
|
-
"""
|
390
|
-
Check if two 'S1D' instances have same
|
391
|
-
axis. Many operations need to satify this.
|
392
|
-
"""
|
393
|
-
return self.x.is_same_as(other.x)
|
394
|
-
|
395
|
-
def mask(self, condition, set_to=None) -> Self:
|
396
|
-
"""
|
397
|
-
Mask the signal based on condition and
|
398
|
-
the values can be set.
|
399
|
-
|
400
|
-
Parameters
|
401
|
-
----------
|
402
|
-
condition: Callable
|
403
|
-
- Condition function to apply on values of the signal.
|
404
|
-
- E.g. lambda x: x > 10
|
405
|
-
set_to: Number
|
406
|
-
- Number to replace the masked position values.
|
407
|
-
|
408
|
-
Returns
|
409
|
-
-------
|
410
|
-
S1D
|
411
|
-
Masked Signal
|
412
|
-
"""
|
413
|
-
|
414
|
-
mask = condition(self)
|
415
|
-
new_val = set_to
|
416
|
-
|
417
|
-
if set_to is None: # Return the mask as the same signal but with booleans
|
418
|
-
return mask
|
419
|
-
|
420
|
-
else:
|
421
|
-
# We apply the mask and update the signal data
|
422
|
-
new_data = self.y.mask(condition=condition, set_to=new_val)
|
423
|
-
|
424
|
-
# Since we're just updating the data, there is no change in the axis
|
425
|
-
return self.__class__(y=new_data, x=self.x.copy(), title=self.title)
|
426
|
-
|
427
|
-
#===================================
|
428
|
-
|
429
|
-
#-----------------------------------
|
430
|
-
# Tools
|
431
|
-
#-----------------------------------
|
432
|
-
|
433
|
-
def plot(
|
434
|
-
self,
|
435
|
-
ax = None,
|
436
|
-
fmt: str = "k-",
|
437
|
-
title = None,
|
438
|
-
y_label = None,
|
439
|
-
x_label = None,
|
440
|
-
y_lim = None,
|
441
|
-
x_lim = None,
|
442
|
-
highlight_regions = None,
|
443
|
-
vlines = None,
|
444
|
-
hlines = None,
|
445
|
-
legend = None,
|
446
|
-
show_grid = True,
|
447
|
-
show_stem = False,
|
448
|
-
) -> plt.Figure | None:
|
449
|
-
"""
|
450
|
-
Plot the signal.
|
451
|
-
|
452
|
-
.. code-block:: python
|
453
|
-
|
454
|
-
import modusa as ms
|
455
|
-
import numpy as np
|
456
|
-
signal = ms.S1D(data=np.random.random(100), data_label="My data (unit)", title="My Random Signal")
|
457
|
-
display(signal.plot())
|
458
|
-
|
459
|
-
Parameters
|
460
|
-
----------
|
461
|
-
ax : matplotlib.axes.Axes | None
|
462
|
-
- If you want to plot the signal on a given matplotlib axes, you can pass the ax here. We do not return any figure in this case.
|
463
|
-
- If not passed, we create a new figure, plots the signal on it and then return the figure.
|
464
|
-
fmt : str
|
465
|
-
- Format of the plot as per matplotlib standards (Eg. "k-" or "blue--o)
|
466
|
-
- Default is "k-"
|
467
|
-
title : str | None
|
468
|
-
- Title for the plot.
|
469
|
-
- If not passed, we use the default set during signal instantiation.
|
470
|
-
y_label : str | None
|
471
|
-
- Label for the y-axis.
|
472
|
-
- If not passed, we use the default set during signal instantiation.
|
473
|
-
x_label : str | None
|
474
|
-
- Label for the x-axis.
|
475
|
-
- If not passed, we use the default set during signal instantiation.
|
476
|
-
y_lim : tuple[float, float] | None
|
477
|
-
- Limits for the y-axis.
|
478
|
-
x_lim : tuple[float, float] | None
|
479
|
-
- Limits for the x-axis.
|
480
|
-
highlight_regions : list[tuple[float, float, str]] | None
|
481
|
-
- List of time intervals to highlight on the plot.
|
482
|
-
- [(start, end, 'tag')]
|
483
|
-
vlines: list[float]
|
484
|
-
- List of x values to draw vertical lines.
|
485
|
-
- e.g. [10, 13.5]
|
486
|
-
hlines: list[float]
|
487
|
-
- List of data values to draw horizontal lines.
|
488
|
-
- e.g. [10, 13.5]
|
489
|
-
show_grid: bool
|
490
|
-
- If true, shows grid.
|
491
|
-
- Default: True
|
492
|
-
show_stem : bool
|
493
|
-
- If True, use a stem plot instead of a continuous line.
|
494
|
-
- Autorejects if signal is too large.
|
495
|
-
legend : str | tuple[str, str] | None
|
496
|
-
- If provided, adds a legend at the specified location.
|
497
|
-
- e.g., "signal" -> gets converted into ("signal", "best")
|
498
|
-
- e.g. ("signal", "upper right")
|
499
|
-
|
500
|
-
Returns
|
501
|
-
-------
|
502
|
-
matplotlib.figure.Figure | None
|
503
|
-
- The figure object containing the plot.
|
504
|
-
- None in case an axis is provided.
|
505
|
-
|
506
|
-
See Also
|
507
|
-
--------
|
508
|
-
modusa.tools.plotter.Plotter
|
509
|
-
"""
|
510
|
-
|
511
|
-
from modusa.tools.plotter import Plotter
|
512
|
-
|
513
|
-
y: Data = self._y
|
514
|
-
x: SAx = self._x
|
515
|
-
y_val = y._values
|
516
|
-
x_val = x._values
|
517
|
-
|
518
|
-
if y_label is None: y_label = self._y._label
|
519
|
-
if x_label is None: x_label = self._x._label
|
520
|
-
if title is None: title = self.title
|
521
|
-
|
522
|
-
fig: plt.Figure | None = Plotter.plot_signal(y=y_val, x=x_val, ax=ax, fmt=fmt, title=title, y_label=y_label, x_label=x_label, y_lim=y_lim, x_lim=x_lim, highlight_regions=highlight_regions, vlines=vlines, hlines=hlines, show_grid=show_grid, show_stem=show_stem, legend=legend)
|
523
|
-
|
524
|
-
return fig
|
525
|
-
|
526
|
-
#===================================
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
#----------------------------------
|
531
|
-
# Information
|
532
|
-
#----------------------------------
|
533
|
-
|
534
|
-
def print_info(self) -> None:
|
535
|
-
"""Prints info about the audio."""
|
536
|
-
print("-" * 50)
|
537
|
-
print(f"{'Title'}: {self._title}")
|
538
|
-
print("-" * 50)
|
539
|
-
print(f"{'Type':<20}: {self.__class__.__name__}")
|
540
|
-
print(f"{'Shape':<20}: {self.shape}")
|
541
|
-
|
542
|
-
# Inheritance chain
|
543
|
-
cls_chain = " → ".join(cls.__name__ for cls in reversed(self.__class__.__mro__[:-1]))
|
544
|
-
print(f"{'Inheritance':<20}: {cls_chain}")
|
545
|
-
print("=" * 50)
|
546
|
-
|
547
|
-
def __str__(self):
|
548
|
-
y, x = self._y, self._x
|
549
|
-
y_label = y._label
|
550
|
-
y_val = y._values
|
551
|
-
shape = self.shape
|
552
|
-
|
553
|
-
|
554
|
-
arr_str = np.array2string(
|
555
|
-
y_val,
|
556
|
-
separator=", ",
|
557
|
-
threshold=30, # limit number of elements shown
|
558
|
-
edgeitems=2, # show first/last 3 rows and columns
|
559
|
-
max_line_width=120, # avoid wrapping
|
560
|
-
)
|
561
|
-
|
562
|
-
return f"{self._nickname}({arr_str})"
|
563
|
-
|
564
|
-
def __repr__(self):
|
565
|
-
y, x = self._y, self._x
|
566
|
-
y_label = y._label
|
567
|
-
y_val = y._values
|
568
|
-
shape = self.shape
|
569
|
-
|
570
|
-
arr_str = np.array2string(
|
571
|
-
y_val,
|
572
|
-
separator=", ",
|
573
|
-
threshold=30, # limit number of elements shown
|
574
|
-
edgeitems=2, # show first/last 3 rows and columns
|
575
|
-
max_line_width=120, # avoid wrapping
|
576
|
-
)
|
577
|
-
return f"{self._nickname}({arr_str})"
|
578
|
-
#===================================
|