modusa 0.4.28__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.
Files changed (58) hide show
  1. modusa/__init__.py +9 -8
  2. modusa/tools/__init__.py +7 -2
  3. modusa/tools/ann_saver.py +30 -0
  4. modusa/tools/audio_recorder.py +0 -1
  5. modusa/tools/synth.py +2 -0
  6. modusa/tools/youtube_downloader.py +1 -4
  7. {modusa-0.4.28.dist-info → modusa-0.4.30.dist-info}/METADATA +2 -2
  8. modusa-0.4.30.dist-info/RECORD +21 -0
  9. pyproject.toml +2 -2
  10. modusa/config.py +0 -18
  11. modusa/decorators.py +0 -176
  12. modusa/devtools/generate_docs_source.py +0 -92
  13. modusa/devtools/generate_template.py +0 -144
  14. modusa/devtools/list_authors.py +0 -2
  15. modusa/devtools/list_plugins.py +0 -60
  16. modusa/devtools/main.py +0 -45
  17. modusa/devtools/templates/generator.py +0 -24
  18. modusa/devtools/templates/io.py +0 -24
  19. modusa/devtools/templates/model.py +0 -47
  20. modusa/devtools/templates/plugin.py +0 -41
  21. modusa/devtools/templates/test.py +0 -10
  22. modusa/devtools/templates/tool.py +0 -24
  23. modusa/generators/__init__.py +0 -13
  24. modusa/generators/audio.py +0 -188
  25. modusa/generators/audio_waveforms.py +0 -236
  26. modusa/generators/base.py +0 -29
  27. modusa/generators/ftds.py +0 -298
  28. modusa/generators/s1d.py +0 -270
  29. modusa/generators/s2d.py +0 -300
  30. modusa/generators/s_ax.py +0 -102
  31. modusa/generators/t_ax.py +0 -64
  32. modusa/generators/tds.py +0 -267
  33. modusa/models/__init__.py +0 -14
  34. modusa/models/audio.py +0 -90
  35. modusa/models/base.py +0 -70
  36. modusa/models/data.py +0 -457
  37. modusa/models/ftds.py +0 -584
  38. modusa/models/s1d.py +0 -578
  39. modusa/models/s2d.py +0 -619
  40. modusa/models/s_ax.py +0 -448
  41. modusa/models/t_ax.py +0 -335
  42. modusa/models/tds.py +0 -465
  43. modusa/plugins/__init__.py +0 -3
  44. modusa/plugins/base.py +0 -100
  45. modusa/tools/_plotter_old.py +0 -629
  46. modusa/tools/audio_saver.py +0 -30
  47. modusa/tools/base.py +0 -43
  48. modusa/tools/math_ops.py +0 -335
  49. modusa/utils/__init__.py +0 -1
  50. modusa/utils/config.py +0 -25
  51. modusa/utils/excp.py +0 -49
  52. modusa/utils/logger.py +0 -18
  53. modusa/utils/np_func_cat.py +0 -44
  54. modusa/utils/plot.py +0 -142
  55. modusa-0.4.28.dist-info/RECORD +0 -65
  56. {modusa-0.4.28.dist-info → modusa-0.4.30.dist-info}/WHEEL +0 -0
  57. {modusa-0.4.28.dist-info → modusa-0.4.30.dist-info}/entry_points.txt +0 -0
  58. {modusa-0.4.28.dist-info → modusa-0.4.30.dist-info}/licenses/LICENSE.md +0 -0
modusa/models/s_ax.py DELETED
@@ -1,448 +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 ModusaSignalAxis
7
- from .data import Data
8
- from modusa.tools.math_ops import MathOps
9
- from typing import Self, Any, Callable
10
- import numpy as np
11
- import matplotlib.pyplot as plt
12
-
13
- class SAx(ModusaSignalAxis):
14
- """
15
- Space to represent any signal's axis.
16
-
17
- Parameters
18
- ----------
19
- values: array-like
20
- - Any array-like object on which np.asarray can be applied.
21
- label: str
22
- - Label for the axis.
23
- - Default: None => ''
24
-
25
- Note
26
- ----
27
- - Use :class:`~modusa.generators.s_ax.SAxGen` API to instantiate this class.
28
- - It can be uniform/non-uniform.
29
- - It is numpy compatible, so you can use numpy methods directly on this class object.
30
- - Since the object of this class represents an axis, any mathematical operations on it will result in another object of :class:`~modusa.models.s1d.S1D` class with `y` being the result of the operation and `x` being the axis itself.
31
- """
32
-
33
- #--------Meta Information----------
34
- _name = "Signal Axis"
35
- _nickname = "axis" # This is to be used in repr/str methods
36
- _description = "Axis for different types of signals."
37
- _author_name = "Ankit Anand"
38
- _author_email = "ankit0.anand0@gmail.com"
39
- _created_at = "2025-07-20"
40
- #----------------------------------
41
-
42
- @validate_args_type()
43
- def __init__(self, values, label = None):
44
-
45
- super().__init__() # Instantiating `ModusaSignalAxis` class
46
-
47
- values = np.asarray(values)
48
- if values.ndim == 0:
49
- values = np.asarray([values])
50
-
51
- assert values.ndim == 1
52
-
53
- self._values = values
54
- self._label = label or ""
55
-
56
- #-----------------------------------
57
- # Properties (User Facing)
58
- #-----------------------------------
59
-
60
- @property
61
- def values(self) -> np.ndarray:
62
- return self._values
63
-
64
- @property
65
- def label(self) -> str:
66
- return self._label
67
-
68
- @property
69
- def shape(self) -> tuple:
70
- return self.values.shape
71
-
72
- @property
73
- def ndim(self) -> int:
74
- return self.values.ndim # Should be 1
75
-
76
- @property
77
- def size(self) -> int:
78
- return self.values.size
79
-
80
- #====================================
81
-
82
- #------------------------------------
83
- # Utility methods
84
- #------------------------------------
85
-
86
- def is_same_as(self, other) -> bool:
87
- """
88
- Compare it with another SAx object.
89
-
90
- Parameters
91
- ----------
92
- other: SAx
93
- Another object to compare with.
94
-
95
- Returns
96
- -------
97
- bool
98
- True if same ow False
99
-
100
- Note
101
- ----
102
- - We check the shape and all the values.
103
- - We are not checking the labels for now.
104
- """
105
-
106
- if other.size == 1: # Meaning it is scalar
107
- return True
108
-
109
- axis1_arr = np.asarray(self)
110
- axis2_arr = np.asarray(other)
111
-
112
- if not isinstance(axis2_arr, type(axis1_arr)):
113
- return False
114
- if axis1_arr.shape != axis2_arr.shape:
115
- return False
116
- if not np.allclose(axis1_arr, axis2_arr):
117
- return False
118
-
119
- return True
120
-
121
- def copy(self) -> Self:
122
- """
123
- Return a new copy of SAx object.
124
-
125
- Returns
126
- -------
127
- SAx
128
- A new copy of the SAx object.
129
- """
130
- copied_values = np.asarray(self).copy()
131
- copied_label = self.label
132
-
133
- return self.__class__(values=copied_values, label=copied_label)
134
-
135
- def set_meta_info(self, label):
136
- """
137
- Set meta info for the axis.
138
-
139
- .. code-block:: python
140
-
141
- import modusa as ms
142
- x = ms.sax.linear(100, 10)
143
- print(x)
144
- x = x.set_meta_info("My Axis (unit)")
145
- print(x)
146
-
147
- # I personally prefer setting it inline
148
- x = ms.sax.linear(100, 10).set_meta_info("My Axis (unit)")
149
- print(x)
150
-
151
- Parameters
152
- ----------
153
- label: str
154
- Label for the axis (e.g. "Time (sec)").
155
- Returns
156
- -------
157
- Self
158
- A new Self instance with new label.
159
- """
160
-
161
- if label is None:
162
- return self
163
- else:
164
- return self.__class__(values=self.values.copy(), label=label)
165
-
166
-
167
- def index_of(self, value) -> int:
168
- """
169
- Return the index whose value is closest
170
- to `value`.
171
-
172
- Parameters
173
- ----------
174
- value: float
175
- value to find the index of.
176
-
177
- Returns
178
- -------
179
- int
180
- Index with value closest to the `value`
181
- """
182
- from .data import Data
183
-
184
- idx = np.argmin(np.abs(self.values - value))
185
-
186
- return Data(values=idx, label=None)
187
-
188
- #====================================
189
-
190
- #-------------------------------
191
- # NumPy Protocol
192
- #-------------------------------
193
-
194
- def __array__(self, dtype=None) -> np.ndarray:
195
- return np.asarray(self.values, dtype=dtype)
196
-
197
- def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
198
- """
199
- Provides operation support for the universal functions
200
- on the Data object.
201
- """
202
- from .s1d import S1D
203
- from .data import Data
204
-
205
- raw_inputs = [x.values if isinstance(x, type(self)) else x for x in inputs]
206
-
207
- # Call the actual ufunc
208
- result = getattr(ufunc, method)(*raw_inputs, **kwargs)
209
-
210
- if isinstance(result, (np.ndarray, np.generic)):
211
- y = Data(values=result, label=None)
212
- x = self
213
- return S1D(y=y, x=x, title=None)
214
- else:
215
- return result
216
-
217
- def __array_function__(self, func, types, args, kwargs):
218
- """
219
- Additional numpy function support.
220
- """
221
- from modusa.utils import np_func_cat as nfc
222
- from .data import Data
223
-
224
- if not all(issubclass(t, type(self)) for t in types):
225
- return NotImplemented
226
-
227
- # Not supporting concatenate like operations as axis any random axis can't be concatenated
228
- if func in nfc.CONCAT_FUNCS:
229
- raise NotImplementedError(f"`{func.__name__}` is not yet tested on modusa signal, please create a GitHub issue.")
230
-
231
- # Single signal input expected
232
- x = args[0]
233
- x_arr = np.asarray(x)
234
- result = func(x_arr, **kwargs)
235
-
236
- if func in nfc.REDUCTION_FUNCS:
237
- # If the number of dimensions is reduced
238
- if result.ndim == 0:
239
- return Data(values=result, label=None)
240
- else:
241
- raise RuntimeError(f"Unexpected result: `result` has more than 0 dimensions, {result.ndim}")
242
-
243
- elif func in nfc.X_NEEDS_ADJUSTMENT_FUNCS:
244
- # You must define logic for adjusting x
245
- raise NotImplementedError(f"{func.__name__} requires x-axis adjustment logic.")
246
-
247
- else:
248
- raise NotImplementedError(f"`{func.__name__}` is not yet tested on modusa signal, please create a GitHub issue.")
249
-
250
- #================================
251
-
252
-
253
- #------------------------------------
254
- # Visualisation
255
- #------------------------------------
256
-
257
- def plot(self, ax = None, fmt = "b-", show_stem=False):
258
- """
259
- Plot the axis values. This is useful to analyse
260
- the axis if it is linear or follows some other
261
- trend.
262
-
263
- .. code-block:: python
264
-
265
- import modusa as ms
266
- x = ms.sax.linear(100, 10)
267
- x.plot()
268
-
269
- Parameters
270
- ----------
271
- ax: plt.Axes | None
272
- - Incase, you want to plot it on your defined matplot ax.
273
- - If not provided, We create a new figure and return that.
274
- fmt: str
275
- - Matplotlib fmt for setting different colors and styles for the plot.
276
- - General fmt is [color][marker][line], e.g. "bo:"
277
- - Useful while plotting multiple SAx instances on the same plot.
278
-
279
- Returns
280
- -------
281
- plt.Figure | None
282
- - Figure if ax is None.
283
- - None is ax is not None.
284
- """
285
- from modusa.tools.plotter import Plotter
286
-
287
- fig: plt.Figure | None = Plotter.plot_signal(y=self.values, x=np.arange(len(self)), ax=ax, fmt=fmt, title=self.label, y_label=self.label, x_label="Index", show_stem=show_stem)
288
-
289
- return fig
290
- #====================================
291
-
292
- #-----------------------------------
293
- # Indexing
294
- #-----------------------------------
295
-
296
- def __getitem__(self, key) -> Self:
297
- """
298
- Defining how to index SAx instance.
299
-
300
- .. code-block:: python
301
-
302
- import modusa as ms
303
- x = ms.sax.linear(100, 10)
304
- print(x)
305
- print(x[10:20])
306
-
307
- Parameters
308
- ----------
309
- key: int | slice
310
- What can go inside the square bracket [] for indexing.
311
-
312
- Returns
313
- -------
314
- SAx:
315
- Sliced instance of the axis.
316
- """
317
-
318
- from .s1d import S1D
319
-
320
- if not isinstance(key, (int, slice, tuple)):
321
- raise TypeError(f"Invalid key type {type(key)}")
322
-
323
- sliced_values = self.values[key]
324
-
325
- # If the number of dimensions is reduced, add back singleton dims
326
- while np.ndim(sliced_values) < self.ndim:
327
- sliced_values = np.expand_dims(sliced_values, axis=0)
328
-
329
- return self.__class__(values=sliced_values, label=self.label)
330
-
331
-
332
- def __setitem__(self, key, value):
333
- """
334
- Raises error if trying to set values
335
- of an axis.
336
-
337
- Meaningful axis are not meant to be altered.
338
- """
339
- raise TypeError("Axis do not support item assignment.")
340
-
341
- #===============================
342
-
343
- #-------------------------------
344
- # Basic arithmetic operations
345
- #-------------------------------
346
- def __add__(self, other):
347
- return np.add(self, other)
348
-
349
- def __radd__(self, other):
350
- return np.add(other, self)
351
-
352
- def __sub__(self, other):
353
- return np.subtract(self, other)
354
-
355
- def __rsub__(self, other):
356
- return np.subtract(other, self)
357
-
358
- def __mul__(self, other):
359
- return np.multiply(self, other)
360
-
361
- def __rmul__(self, other):
362
- return np.multiply(other, self)
363
-
364
- def __truediv__(self, other):
365
- return np.divide(self, other)
366
-
367
- def __rtruediv__(self, other):
368
- return np.divide(other, self)
369
-
370
- def __floordiv__(self, other):
371
- return np.floor_divide(self, other)
372
-
373
- def __rfloordiv__(self, other):
374
- return np.floor_divide(other, self)
375
-
376
- def __pow__(self, other):
377
- return np.power(self, other)
378
-
379
- def __rpow__(self, other):
380
- return np.power(other, self)
381
-
382
- #===============================
383
-
384
-
385
- #-------------------------------
386
- # Basic comparison operations
387
- #-------------------------------
388
- def __eq__(self, other):
389
- return np.equal(self, other)
390
-
391
- def __ne__(self, other):
392
- return np.not_equal(self, other)
393
-
394
- def __lt__(self, other):
395
- return np.less(self, other)
396
-
397
- def __le__(self, other):
398
- return np.less_equal(self, other)
399
-
400
- def __gt__(self, other):
401
- return np.greater(self, other)
402
-
403
- def __ge__(self, other):
404
- return np.greater_equal(self, other)
405
-
406
- #===============================
407
-
408
- #----------------------------------
409
- # Information
410
- #----------------------------------
411
-
412
- def print_info(self) -> None:
413
- """
414
- Prints info about the SAx instance.
415
-
416
- .. code-block:: python
417
-
418
- import modusa as ms
419
- # For SAx
420
- x = ms.sax.linear(100, 10)
421
- x.print_info()
422
- # For TAx
423
- x = ms.tax.linear(100, 10)
424
- x.print_info()
425
-
426
- Returns
427
- -------
428
- None
429
- """
430
- print("-" * 50)
431
- print("Axis Info")
432
- print("-" * 50)
433
- print(f"{'Label':<20}: {self.label}")
434
- print(f"{'Shape':<20}: {self.shape}")
435
- # Inheritance chain
436
- cls_chain = " → ".join(cls.__name__ for cls in reversed(self.__class__.__mro__[:-1]))
437
- print(f"{'Inheritance':<20}: {cls_chain}")
438
- print("=" * 50)
439
-
440
- def __str__(self):
441
- arr_str = np.array2string(self.values, separator=", ", threshold=30, edgeitems=3, max_line_width=120)
442
- return f"{self._nickname}({arr_str})"
443
-
444
- def __repr__(self):
445
- arr_str = np.array2string(self.values, separator=", ", threshold=30, edgeitems=3, max_line_width=120)
446
- return f"{self._nickname}({arr_str})"
447
- #===================================
448
-