modusa 0.2.22__py3-none-any.whl → 0.3__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 (70) hide show
  1. modusa/.DS_Store +0 -0
  2. modusa/__init__.py +8 -1
  3. modusa/decorators.py +4 -4
  4. modusa/devtools/generate_docs_source.py +96 -0
  5. modusa/devtools/generate_template.py +13 -13
  6. modusa/devtools/main.py +4 -3
  7. modusa/devtools/templates/generator.py +1 -1
  8. modusa/devtools/templates/io.py +1 -1
  9. modusa/devtools/templates/{signal.py → model.py} +18 -11
  10. modusa/devtools/templates/plugin.py +1 -1
  11. modusa/devtools/templates/test.py +2 -3
  12. modusa/devtools/templates/{engine.py → tool.py} +3 -8
  13. modusa/generators/__init__.py +9 -1
  14. modusa/generators/audio.py +188 -0
  15. modusa/generators/audio_waveforms.py +22 -13
  16. modusa/generators/base.py +1 -1
  17. modusa/generators/ftds.py +298 -0
  18. modusa/generators/s1d.py +270 -0
  19. modusa/generators/s2d.py +300 -0
  20. modusa/generators/s_ax.py +102 -0
  21. modusa/generators/t_ax.py +64 -0
  22. modusa/generators/tds.py +267 -0
  23. modusa/main.py +0 -30
  24. modusa/models/__init__.py +14 -0
  25. modusa/models/__pycache__/signal1D.cpython-312.pyc.4443461152 +0 -0
  26. modusa/models/audio.py +90 -0
  27. modusa/models/base.py +70 -0
  28. modusa/models/data.py +457 -0
  29. modusa/models/ftds.py +584 -0
  30. modusa/models/s1d.py +578 -0
  31. modusa/models/s2d.py +619 -0
  32. modusa/models/s_ax.py +448 -0
  33. modusa/models/t_ax.py +335 -0
  34. modusa/models/tds.py +465 -0
  35. modusa/plugins/__init__.py +3 -1
  36. modusa/tmp.py +98 -0
  37. modusa/tools/__init__.py +7 -0
  38. modusa/tools/audio_converter.py +73 -0
  39. modusa/tools/audio_loader.py +90 -0
  40. modusa/tools/audio_player.py +89 -0
  41. modusa/tools/base.py +43 -0
  42. modusa/tools/math_ops.py +335 -0
  43. modusa/tools/plotter.py +351 -0
  44. modusa/tools/youtube_downloader.py +72 -0
  45. modusa/utils/excp.py +15 -42
  46. modusa/utils/np_func_cat.py +44 -0
  47. modusa/utils/plot.py +142 -0
  48. {modusa-0.2.22.dist-info → modusa-0.3.dist-info}/METADATA +5 -16
  49. modusa-0.3.dist-info/RECORD +60 -0
  50. modusa/engines/.DS_Store +0 -0
  51. modusa/engines/__init__.py +0 -3
  52. modusa/engines/base.py +0 -14
  53. modusa/io/__init__.py +0 -9
  54. modusa/io/audio_converter.py +0 -76
  55. modusa/io/audio_loader.py +0 -214
  56. modusa/io/audio_player.py +0 -72
  57. modusa/io/base.py +0 -43
  58. modusa/io/plotter.py +0 -430
  59. modusa/io/youtube_downloader.py +0 -139
  60. modusa/signals/__init__.py +0 -7
  61. modusa/signals/audio_signal.py +0 -483
  62. modusa/signals/base.py +0 -34
  63. modusa/signals/frequency_domain_signal.py +0 -329
  64. modusa/signals/signal_ops.py +0 -158
  65. modusa/signals/spectrogram.py +0 -465
  66. modusa/signals/time_domain_signal.py +0 -309
  67. modusa-0.2.22.dist-info/RECORD +0 -47
  68. {modusa-0.2.22.dist-info → modusa-0.3.dist-info}/WHEEL +0 -0
  69. {modusa-0.2.22.dist-info → modusa-0.3.dist-info}/entry_points.txt +0 -0
  70. {modusa-0.2.22.dist-info → modusa-0.3.dist-info}/licenses/LICENSE.md +0 -0
@@ -1,309 +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 modusa.signals.base import ModusaSignal
7
- from typing import Self, Any
8
- import numpy as np
9
- import matplotlib.pyplot as plt
10
-
11
- class TimeDomainSignal(ModusaSignal):
12
- """
13
- Initialize a uniformly sampled 1D time-domain signal.
14
-
15
- This class is specifically designed to hold 1D signals that result
16
- from slicing a 2D representation like a spectrogram. For example,
17
- if you have a spectrogram `S` and you perform `S[10, :]`, the result
18
- is a 1D signal over time, this class provides a clean and consistent
19
- way to handle such slices.
20
-
21
- Parameters
22
- ----------
23
- y : np.ndarray
24
- The 1D signal values sampled uniformly over time.
25
- sr : float
26
- The sampling rate in Hz (samples per second).
27
- t0 : float, optional
28
- The starting time of the signal in seconds (default is 0.0).
29
- title : str, optional
30
- An optional title used for labeling or plotting purposes.
31
- """
32
-
33
-
34
- #--------Meta Information----------
35
- _name = "Time Domain Signal"
36
- _description = ""
37
- _author_name = "Ankit Anand"
38
- _author_email = "ankit0.anand0@gmail.com"
39
- _created_at = "2025-07-09"
40
- #----------------------------------
41
-
42
- @validate_args_type()
43
- def __init__(self, y: np.ndarray, sr: float, t0: float = 0.0, title: str | None = None):
44
- super().__init__() # Instantiating `ModusaSignal` class
45
-
46
- self._y = y
47
- self._sr = sr
48
- self._t0 = t0
49
- self.title = title or self._name # This title will be used as plot title by default
50
-
51
-
52
- #----------------------
53
- # Properties
54
- #----------------------
55
-
56
- @immutable_property("Create a new object instead.")
57
- def y(self) -> np.ndarray:
58
- return self._y
59
-
60
- @immutable_property("Create a new object instead.")
61
- def sr(self) -> np.ndarray:
62
- return self._sr
63
-
64
- @immutable_property("Create a new object instead.")
65
- def t0(self) -> np.ndarray:
66
- """"""
67
- return self._t0
68
-
69
- @immutable_property("Create a new object instead.")
70
- def t(self) -> np.ndarray:
71
- return self.t0 + np.arange(len(self._y)) / self.sr
72
-
73
- def __len__(self):
74
- return len(self._y)
75
-
76
- #----------------------
77
- # Tools
78
- #----------------------
79
-
80
- def __getitem__(self, key: slice) -> Self:
81
- sliced_y = self._y[key]
82
- t0_new = self.t[key.start] if key.start is not None else self.t0
83
- return TimeDomainSignal(y=sliced_y, sr=self.sr, t0=t0_new, title=self.title)
84
-
85
- @validate_args_type()
86
- def plot(
87
- self,
88
- scale_y: tuple[float, float] | None = None,
89
- ax: plt.Axes | None = None,
90
- color: str = "b",
91
- marker: str | None = None,
92
- linestyle: str | None = None,
93
- stem: bool | None = False,
94
- legend_loc: str | None = None,
95
- title: str | None = None,
96
- ylabel: str | None = "Amplitude",
97
- xlabel: str | None = "Time (sec)",
98
- ylim: tuple[float, float] | None = None,
99
- xlim: tuple[float, float] | None = None,
100
- highlight: list[tuple[float, float]] | None = None,
101
- ) -> plt.Figure:
102
- """
103
- Plot the time-domain signal.
104
-
105
- .. code-block:: python
106
-
107
- signal.plot(color='g', marker='o', stem=True)
108
-
109
- Parameters
110
- ----------
111
- scale_y : tuple[float, float], optional
112
- Min-max values to scale the y-axis data.
113
- ax : matplotlib.axes.Axes, optional
114
- Axes to plot on; if None, creates a new figure.
115
- color : str, default='b'
116
- Line or stem color.
117
- marker : str, optional
118
- Marker style for each data point.
119
- linestyle : str, optional
120
- Line style to use if not using stem plot.
121
- stem : bool, default=False
122
- Whether to draw a stem plot instead of a line plot.
123
- legend_loc : str, optional
124
- If given, adds a legend at the specified location.
125
-
126
- Returns
127
- -------
128
- matplotlib.axes.Axes
129
- The axes object containing the plot.
130
-
131
- Note
132
- ----
133
- This is useful for visualizing 1D signals obtained from time slices of spectrograms.
134
- """
135
-
136
- from modusa.io import Plotter
137
-
138
- title = title or self.title
139
-
140
- fig: plt.Figure | None = Plotter.plot_signal(y=self.y, x=self.t, scale_y=scale_y, ax=ax, color=color, marker=marker, linestyle=linestyle, stem=stem, legend_loc=legend_loc, title=title, ylabel=ylabel, xlabel=xlabel, ylim=ylim, xlim=xlim, highlight=highlight)
141
-
142
- return fig
143
-
144
- #----------------------------
145
- # Math ops
146
- #----------------------------
147
-
148
- def __array__(self, dtype=None):
149
- return np.asarray(self.y, dtype=dtype)
150
-
151
- def __add__(self, other):
152
- other_data = other.y if isinstance(other, self.__class__) else other
153
- result = np.add(self.y, other_data)
154
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
155
-
156
- def __radd__(self, other):
157
- result = np.add(other, self.y)
158
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
159
-
160
- def __sub__(self, other):
161
- other_data = other.y if isinstance(other, self.__class__) else other
162
- result = np.subtract(self.y, other_data)
163
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
164
-
165
- def __rsub__(self, other):
166
- result = np.subtract(other, self.y)
167
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
168
-
169
- def __mul__(self, other):
170
- other_data = other.y if isinstance(other, self.__class__) else other
171
- result = np.multiply(self.y, other_data)
172
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
173
-
174
- def __rmul__(self, other):
175
- result = np.multiply(other, self.y)
176
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
177
-
178
- def __truediv__(self, other):
179
- other_data = other.y if isinstance(other, self.__class__) else other
180
- result = np.true_divide(self.y, other_data)
181
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
182
-
183
- def __rtruediv__(self, other):
184
- result = np.true_divide(other, self.y)
185
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
186
-
187
- def __floordiv__(self, other):
188
- other_data = other.y if isinstance(other, self.__class__) else other
189
- result = np.floor_divide(self.y, other_data)
190
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
191
-
192
- def __rfloordiv__(self, other):
193
- result = np.floor_divide(other, self.y)
194
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
195
-
196
- def __pow__(self, other):
197
- other_data = other.y if isinstance(other, self.__class__) else other
198
- result = np.power(self.y, other_data)
199
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
200
-
201
- def __rpow__(self, other):
202
- result = np.power(other, self.y)
203
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
204
-
205
- def __abs__(self):
206
- result = np.abs(self.y)
207
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
208
-
209
-
210
- #--------------------------
211
- # Other signal ops
212
- #--------------------------
213
- def sin(self) -> Self:
214
- """Compute the element-wise sine of the signal data."""
215
- result = np.sin(self.y)
216
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
217
-
218
- def cos(self) -> Self:
219
- """Compute the element-wise cosine of the signal data."""
220
- result = np.cos(self.y)
221
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
222
-
223
- def exp(self) -> Self:
224
- """Compute the element-wise exponential of the signal data."""
225
- result = np.exp(self.y)
226
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
227
-
228
- def tanh(self) -> Self:
229
- """Compute the element-wise hyperbolic tangent of the signal data."""
230
- result = np.tanh(self.y)
231
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
232
-
233
- def log(self) -> Self:
234
- """Compute the element-wise natural logarithm of the signal data."""
235
- result = np.log(self.y)
236
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
237
-
238
- def log1p(self) -> Self:
239
- """Compute the element-wise natural logarithm of (1 + signal data)."""
240
- result = np.log1p(self.y)
241
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
242
-
243
- def log10(self) -> Self:
244
- """Compute the element-wise base-10 logarithm of the signal data."""
245
- result = np.log10(self.y)
246
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
247
-
248
- def log2(self) -> Self:
249
- """Compute the element-wise base-2 logarithm of the signal data."""
250
- result = np.log2(self.y)
251
- return self.__class__(y=result, sr=self.sr, t0=self.t0, title=self.title)
252
-
253
-
254
- #--------------------------
255
- # Aggregation signal ops
256
- #--------------------------
257
- def mean(self) -> float:
258
- """Compute the mean of the signal data."""
259
- return float(np.mean(self.y))
260
-
261
- def std(self) -> float:
262
- """Compute the standard deviation of the signal data."""
263
- return float(np.std(self.y))
264
-
265
- def min(self) -> float:
266
- """Compute the minimum value in the signal data."""
267
- return float(np.min(self.y))
268
-
269
- def max(self) -> float:
270
- """Compute the maximum value in the signal data."""
271
- return float(np.max(self.y))
272
-
273
- def sum(self) -> float:
274
- """Compute the sum of the signal data."""
275
- return float(np.sum(self.y))
276
-
277
- #-----------------------------------
278
- # Repr
279
- #-----------------------------------
280
-
281
- def __str__(self):
282
- cls = self.__class__.__name__
283
- data = self.y
284
-
285
- arr_str = np.array2string(
286
- data,
287
- separator=", ",
288
- threshold=50, # limit number of elements shown
289
- edgeitems=3, # show first/last 3 rows and columns
290
- max_line_width=120, # avoid wrapping
291
- formatter={'float_kind': lambda x: f"{x:.4g}"}
292
- )
293
-
294
- return f"Signal({arr_str}, shape={data.shape}, kind={cls})"
295
-
296
- def __repr__(self):
297
- cls = self.__class__.__name__
298
- data = self.y
299
-
300
- arr_str = np.array2string(
301
- data,
302
- separator=", ",
303
- threshold=50, # limit number of elements shown
304
- edgeitems=3, # show first/last 3 rows and columns
305
- max_line_width=120, # avoid wrapping
306
- formatter={'float_kind': lambda x: f"{x:.4g}"}
307
- )
308
-
309
- return f"Signal({arr_str}, shape={data.shape}, kind={cls})"
@@ -1,47 +0,0 @@
1
- modusa-0.2.22.dist-info/METADATA,sha256=0tgrUqyQsTextWxCHxNmuorCKRv96CZZ72OuCf3SOXg,1505
2
- modusa-0.2.22.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
- modusa-0.2.22.dist-info/entry_points.txt,sha256=fmKpleVXj6CdaBVL14WoEy6xx7JQCs85jvzwTi3lePM,73
4
- modusa-0.2.22.dist-info/licenses/LICENSE.md,sha256=JTaXAjx5awk76VArKCx5dUW8vmLEWsL_ZlR7-umaHbA,1078
5
- modusa/.DS_Store,sha256=Q0eG2RQNYtV4qa5BYj_GznvlEBpNdebi6ZTIR-a7AhU,6148
6
- modusa/__init__.py,sha256=bfQKVSpAXlKmKvMRIU6WSRQW2qoJsaZsdNJ8E69ghn0,37
7
- modusa/config.py,sha256=bTqK4t00FZqERVITrxW_q284aDDJAa9aMSfFknfR-oU,280
8
- modusa/decorators.py,sha256=kGadBm1UzAuWjc4tw9ycOkUm3xP6q-jebGo5yjk_Aqs,5909
9
- modusa/devtools/generate_template.py,sha256=1WTMIHvBoa42Ow3g2HvYKVNSBxLB6JLGXhs-7G7zi28,5225
10
- modusa/devtools/list_authors.py,sha256=FWBQKOLznVthvMYMASrx2Gw5lqKHEOccQpBisDZ53Dw,24
11
- modusa/devtools/list_plugins.py,sha256=g-R5hoaCzHfClY_Sfa788IQ9CAKzQGTfyqmthXDZQqw,1729
12
- modusa/devtools/main.py,sha256=Me7nkn-oaaxIVuj1aJ5dCq3CB8xODH6i2kqE_pAFmXQ,1836
13
- modusa/devtools/templates/engine.py,sha256=fmUhvgOpmNtJ5zbYDonyLVjRDzUnVCRzDWY6WeSeiVY,514
14
- modusa/devtools/templates/generator.py,sha256=tf2k2L9RF5S9iJmqPD5AFETJKvqL5XknqK3sR6n2ceQ,444
15
- modusa/devtools/templates/io.py,sha256=jcO4vAH8iiw6uvwy2aEbsBeNnQOj5VaU_VrQvhJflRA,383
16
- modusa/devtools/templates/plugin.py,sha256=HNoN0S63ahk83EPup_15pbfOY5_kFfnLF63U3vWOMp8,863
17
- modusa/devtools/templates/signal.py,sha256=Jqdq38W6ye2cf499oGXWlpCVH4Nmoo1jNfPYgdVLseA,775
18
- modusa/devtools/templates/test.py,sha256=OXEeIGW1D8g3a0jLyweNBpwfAQkkClhiIAEI6x0CooU,266
19
- modusa/engines/.DS_Store,sha256=1lFlJ5EFymdzGAUAaI30vcaaLHt3F1LwpG7xILf9jsM,6148
20
- modusa/engines/__init__.py,sha256=HtXuC9NWIo6faKTmbalxNvw2CTtiGrsPly7i08GlHVg,54
21
- modusa/engines/base.py,sha256=gHeGTbvcPhTxwUwt16OLpepMkbG40rv19vs8tN8xqgA,297
22
- modusa/generators/__init__.py,sha256=vcu5uk1hP637bmPTAiyb0LQ_vkFwgp4r-A1hAHR4zfo,110
23
- modusa/generators/audio_waveforms.py,sha256=qWg9TUVux8Abxmxa7EjCB_Pt88UFC6bJBqvYRWz8MTg,5868
24
- modusa/generators/base.py,sha256=QTb-8F19DmoCwLS7Mn9MdugOMZ_22suuTBFrmpyE7LM,934
25
- modusa/io/__init__.py,sha256=2Jg44klIAjbgLCn4faXXug_4nW-UiMsOH4Z3g0VGxWw,250
26
- modusa/io/audio_converter.py,sha256=CjsuvdjpHAuwJFjFNCHSzge-i07zW6U-cnb0EIYhMC0,1877
27
- modusa/io/audio_loader.py,sha256=o_tAFZaGVm62z59Yinzf2z6Gp_lujRoSWk1GHCaeOlI,4903
28
- modusa/io/audio_player.py,sha256=5BrYx1YyTYUybroJSNaZ5n7ABgKWeP4zBCLfhyQYPBE,1626
29
- modusa/io/base.py,sha256=GOMvpicWWLWXoxm4nLwqq_0hWmXWzYAPLVx-CbthCsQ,1291
30
- modusa/io/plotter.py,sha256=VViXHuIugAQDcTkSWjbrymrMrQOKVw97jqsd4-kWl_8,11920
31
- modusa/io/youtube_downloader.py,sha256=7Ah3JCHZTdL47v3m6KthYt80QOm40dDp2qAT2fChgFA,3444
32
- modusa/main.py,sha256=YeNg_GX3pzP4qNNU7CItCkWt5eOCHhnWLENFcQFlgfc,538
33
- modusa/plugins/__init__.py,sha256=OB-b_GnUnTkECn1fwxl844UBmiui3mSWIvhBqMZY7Tc,22
34
- modusa/plugins/base.py,sha256=Bh_1Bja7fOymFsCgwhXDbV6ys3D8muNrPwrfDrG_G_A,2382
35
- modusa/signals/__init__.py,sha256=TZujCd50gGnO-r27Tv6hrzNl8zBsMIMFwYCeIwszMjc,237
36
- modusa/signals/audio_signal.py,sha256=DvjQUjja9s3nrAHM7H_3z5DVC0nha0Az2D1025q5upk,15750
37
- modusa/signals/base.py,sha256=UdwOTlIHvXjpuCBwE-IcCQBL0F-wuhQpD6aOvI8FvXE,795
38
- modusa/signals/frequency_domain_signal.py,sha256=wS7MN6y56BDInNgtnkIB3XNsxDS_TNmewqS-A31MJmY,11192
39
- modusa/signals/signal_ops.py,sha256=tpbZs10NVkT4Y7nsIhqGEP4Y6T8JZ07PiKxF34fYu-I,4685
40
- modusa/signals/spectrogram.py,sha256=Rbt7AVHuRjRLjHXaoUtaT_uG-CCK6Tc9_P9apH2Oczk,14443
41
- modusa/signals/time_domain_signal.py,sha256=SOiBVhvsZcctYOGLLtnXXK5IT9wOTO-S4_K0DPWPr-Y,9751
42
- modusa/utils/.DS_Store,sha256=nLXMwF7QJNuglLI_Gk74F7vl5Dyus2Wd74Mgowijmdo,6148
43
- modusa/utils/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
44
- modusa/utils/config.py,sha256=cuGbqbovx5WDQq5rw3hIKcv3CnE5NttjacSOWnP1yu4,576
45
- modusa/utils/excp.py,sha256=_NLfR1AKU4dOpK-OF0NaChYjaVBCcq1VmSd_dkOexi4,1235
46
- modusa/utils/logger.py,sha256=K0rsnObeNKCxlNeSnVnJeRhgfmob6riB2uyU7h3dDmA,571
47
- modusa-0.2.22.dist-info/RECORD,,
File without changes