modusa 0.3.67__tar.gz → 0.3.69__tar.gz

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 (94) hide show
  1. {modusa-0.3.67 → modusa-0.3.69}/PKG-INFO +1 -1
  2. {modusa-0.3.67 → modusa-0.3.69}/pyproject.toml +1 -1
  3. modusa-0.3.69/src/modusa/tools/ann_loader.py +65 -0
  4. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/tools/audio_loader.py +19 -3
  5. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/tools/plotter.py +3 -3
  6. modusa-0.3.67/src/modusa/tools/ann_loader.py +0 -38
  7. {modusa-0.3.67 → modusa-0.3.69}/LICENSE.md +0 -0
  8. {modusa-0.3.67 → modusa-0.3.69}/README.md +0 -0
  9. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/.DS_Store +0 -0
  10. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/__init__.py +0 -0
  11. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/config.py +0 -0
  12. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/decorators.py +0 -0
  13. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/devtools/generate_docs_source.py +0 -0
  14. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/devtools/generate_template.py +0 -0
  15. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/devtools/list_authors.py +0 -0
  16. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/devtools/list_plugins.py +0 -0
  17. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/devtools/main.py +0 -0
  18. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/devtools/templates/generator.py +0 -0
  19. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/devtools/templates/io.py +0 -0
  20. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/devtools/templates/model.py +0 -0
  21. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/devtools/templates/plugin.py +0 -0
  22. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/devtools/templates/test.py +0 -0
  23. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/devtools/templates/tool.py +0 -0
  24. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/fonts/NotoSansDevanagari-Regular.ttf +0 -0
  25. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/generators/__init__.py +0 -0
  26. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/generators/audio.py +0 -0
  27. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/generators/audio_waveforms.py +0 -0
  28. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/generators/base.py +0 -0
  29. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/generators/ftds.py +0 -0
  30. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/generators/s1d.py +0 -0
  31. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/generators/s2d.py +0 -0
  32. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/generators/s_ax.py +0 -0
  33. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/generators/t_ax.py +0 -0
  34. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/generators/tds.py +0 -0
  35. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/models/__init__.py +0 -0
  36. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/models/__pycache__/signal1D.cpython-312.pyc.4443461152 +0 -0
  37. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/models/audio.py +0 -0
  38. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/models/base.py +0 -0
  39. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/models/data.py +0 -0
  40. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/models/ftds.py +0 -0
  41. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/models/s1d.py +0 -0
  42. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/models/s2d.py +0 -0
  43. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/models/s_ax.py +0 -0
  44. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/models/t_ax.py +0 -0
  45. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/models/tds.py +0 -0
  46. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/plugins/__init__.py +0 -0
  47. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/plugins/base.py +0 -0
  48. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/tools/__init__.py +0 -0
  49. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/tools/_plotter_old.py +0 -0
  50. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/tools/audio_converter.py +0 -0
  51. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/tools/audio_player.py +0 -0
  52. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/tools/audio_recorder.py +0 -0
  53. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/tools/base.py +0 -0
  54. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/tools/math_ops.py +0 -0
  55. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/tools/youtube_downloader.py +0 -0
  56. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/utils/.DS_Store +0 -0
  57. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/utils/__init__.py +0 -0
  58. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/utils/config.py +0 -0
  59. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/utils/excp.py +0 -0
  60. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/utils/logger.py +0 -0
  61. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/utils/np_func_cat.py +0 -0
  62. {modusa-0.3.67 → modusa-0.3.69}/src/modusa/utils/plot.py +0 -0
  63. {modusa-0.3.67 → modusa-0.3.69}/tests/__init__.py +0 -0
  64. {modusa-0.3.67 → modusa-0.3.69}/tests/data/song1.mp3 +0 -0
  65. {modusa-0.3.67 → modusa-0.3.69}/tests/data/song1.wav +0 -0
  66. {modusa-0.3.67 → modusa-0.3.69}/tests/test_generators/audio_waveform.py +0 -0
  67. {modusa-0.3.67 → modusa-0.3.69}/tests/test_generators/test_audio.py +0 -0
  68. {modusa-0.3.67 → modusa-0.3.69}/tests/test_generators/test_ftds.py +0 -0
  69. {modusa-0.3.67 → modusa-0.3.69}/tests/test_generators/test_s1d.py +0 -0
  70. {modusa-0.3.67 → modusa-0.3.69}/tests/test_generators/test_s2d.py +0 -0
  71. {modusa-0.3.67 → modusa-0.3.69}/tests/test_generators/test_s_ax.py +0 -0
  72. {modusa-0.3.67 → modusa-0.3.69}/tests/test_generators/test_signal.py +0 -0
  73. {modusa-0.3.67 → modusa-0.3.69}/tests/test_generators/test_signal_generator.py +0 -0
  74. {modusa-0.3.67 → modusa-0.3.69}/tests/test_generators/test_t_ax.py +0 -0
  75. {modusa-0.3.67 → modusa-0.3.69}/tests/test_generators/test_tds.py +0 -0
  76. {modusa-0.3.67 → modusa-0.3.69}/tests/test_io/audio_player.py +0 -0
  77. {modusa-0.3.67 → modusa-0.3.69}/tests/test_io/plotter.py +0 -0
  78. {modusa-0.3.67 → modusa-0.3.69}/tests/test_models/test_data.py +0 -0
  79. {modusa-0.3.67 → modusa-0.3.69}/tests/test_models/test_t_ax.py +0 -0
  80. {modusa-0.3.67 → modusa-0.3.69}/tests/test_plugins/youtube_audio_loader.py +0 -0
  81. {modusa-0.3.67 → modusa-0.3.69}/tests/test_signals/frequency_domain_signal.py +0 -0
  82. {modusa-0.3.67 → modusa-0.3.69}/tests/test_signals/spectrogram.py +0 -0
  83. {modusa-0.3.67 → modusa-0.3.69}/tests/test_signals/test_axis.py +0 -0
  84. {modusa-0.3.67 → modusa-0.3.69}/tests/test_signals/test_feature_time_domain_signal.py +0 -0
  85. {modusa-0.3.67 → modusa-0.3.69}/tests/test_signals/test_frequency_time_domain_signal.py +0 -0
  86. {modusa-0.3.67 → modusa-0.3.69}/tests/test_signals/test_signal1D.py +0 -0
  87. {modusa-0.3.67 → modusa-0.3.69}/tests/test_signals/test_signal2D.py +0 -0
  88. {modusa-0.3.67 → modusa-0.3.69}/tests/test_signals/test_time_domain_signal.py +0 -0
  89. {modusa-0.3.67 → modusa-0.3.69}/tests/test_signals/test_u_ax.py +0 -0
  90. {modusa-0.3.67 → modusa-0.3.69}/tests/test_signals/test_window_signal.py +0 -0
  91. {modusa-0.3.67 → modusa-0.3.69}/tests/test_signals/time_domain_signal.py +0 -0
  92. {modusa-0.3.67 → modusa-0.3.69}/tests/test_tools/test_audio_converter.py +0 -0
  93. {modusa-0.3.67 → modusa-0.3.69}/tests/test_tools/test_fourier_tranform.py +0 -0
  94. {modusa-0.3.67 → modusa-0.3.69}/tests/test_tools/test_math_ops.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modusa
3
- Version: 0.3.67
3
+ Version: 0.3.69
4
4
  Summary: A modular signal analysis python library.
5
5
  Author-Email: Ankit Anand <ankit0.anand0@gmail.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "modusa"
3
- version = "0.3.67"
3
+ version = "0.3.69"
4
4
  description = "A modular signal analysis python library."
5
5
  authors = [
6
6
  { name = "Ankit Anand", email = "ankit0.anand0@gmail.com" },
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env python3
2
+
3
+ #---------------------------------
4
+ # Author: Ankit Anand
5
+ # Date: 12/08/25
6
+ # Email: ankit0.anand0@gmail.com
7
+ #---------------------------------
8
+
9
+ from pathlib import Path
10
+
11
+ def load_ann(path, clip=None):
12
+ """
13
+ Load annotation from audatity label text file.
14
+
15
+ Parameters
16
+ ----------
17
+ path: str
18
+ - label text file path.
19
+ clip: tuple[number, number] | number | None
20
+ - Incase you clipped the audio signal, this parameter will help clip the annotation.
21
+ - If you clip the audio, say from (10, 20), set the clip to (10, 20).
22
+ - Default: None
23
+
24
+ Returns
25
+ -------
26
+ list[tuple, ...]
27
+ - annotation data structure
28
+ - [(start, end, tag), ...]
29
+ """
30
+
31
+ if not isinstance(path, (str, Path)):
32
+ raise ValueError(f"`path` must be one of (str, Path), got {type(path)}")
33
+
34
+ if clip is not None:
35
+ # Map clip input to the right format
36
+ if isinstance(clip, int or float):
37
+ clip = (0, clip)
38
+ elif isinstance(clip, tuple) and len(clip) > 1:
39
+ clip = (clip[0], clip[1])
40
+ else:
41
+ raise ValueError(f"Invalid clip type or length: {type(clip)}, len={len(clip)}")
42
+
43
+ ann = []
44
+
45
+ with open(str(path), "r") as f:
46
+ lines = [line.rstrip("\n") for line in f]
47
+ for line in lines:
48
+ start, end, tag = line.split("\t")
49
+ start, end = float(start), float(end)
50
+
51
+ # Incase user has clipped the audio signal, we adjust the annotation
52
+ # to match the clipped audio
53
+ if clip is not None:
54
+ offset = clip[0]
55
+ # Clamp annotation to clip boundaries
56
+ new_start = max(start, clip[0]) - offset
57
+ new_end = min(end, clip[1]) - offset
58
+
59
+ # only keep if there's still overlap
60
+ if new_start < new_end:
61
+ ann.append((new_start, new_end, tag))
62
+ else:
63
+ ann.append((start, end, tag))
64
+
65
+ return ann
@@ -10,7 +10,7 @@ from .youtube_downloader import download
10
10
  from .audio_converter import convert
11
11
 
12
12
 
13
- def load(path, sr=None):
13
+ def load(path, sr=None, clip=None):
14
14
  """
15
15
  Loads audio file from various sources.
16
16
 
@@ -19,15 +19,19 @@ def load(path, sr=None):
19
19
  import modusa as ms
20
20
  audio_fp = ms.load(
21
21
  "https://www.youtube.com/watch?v=lIpw9-Y_N0g",
22
- sr = None)
22
+ sr = None, clip=(5, 10))
23
23
 
24
24
  Parameters
25
25
  ----------
26
26
  path: str
27
27
  - Path to the audio
28
28
  - Youtube URL
29
- sr: int
29
+ sr: int | None
30
30
  - Sampling rate to load the audio in.
31
+ clip: number | tuple[number, number] | None
32
+ - Which segment of the audio you want.
33
+ - Eg., 10 => First 10 sec, (5, 10) => 5 to 10 second
34
+ - Default: None => Entire audio.
31
35
 
32
36
  Return
33
37
  ------
@@ -86,5 +90,17 @@ def load(path, sr=None):
86
90
  n_samples = int(len(audio_data) * sr / audio_sr)
87
91
  audio_data = resample(audio_data, n_samples)
88
92
  audio_sr = sr
93
+
94
+ # Clip the audio signal as per needed
95
+ if clip is not None:
96
+ # Map clip input to the right format
97
+ if isinstance(clip, int or float):
98
+ clip = (0, clip)
99
+ elif isinstance(clip, tuple) and len(clip) > 1:
100
+ clip = (clip[0], clip[1])
101
+ else:
102
+ raise ValueError(f"Invalid clip type or length: {type(clip)}, len={len(clip)}")
103
+
104
+ audio_data = audio_data[int(clip[0]*sr):int(clip[1]*sr)]
89
105
 
90
106
  return audio_data, audio_sr, title
@@ -167,14 +167,14 @@ class Fig:
167
167
  axs[i, 1].axis("off")
168
168
  elif char == "a": # Remove ticks and labels from all the aux subplots
169
169
  axs[i, 0].tick_params(left=False, bottom=False, labelleft=False, labelbottom=False)
170
- axs[i, 0].grid(True, linestyle=':', linewidth=0.7, color='gray', alpha=0.7)
170
+ axs[i, 0].grid(True, linestyle='--', linewidth=0.7, color="lightgray" ,alpha=0.6)
171
171
  axs[i, 1].axis("off")
172
172
  elif char == "s":
173
173
  axs[i, 0].tick_params(bottom=False, labelbottom=False)
174
- axs[i, 0].grid(True, linestyle=':', linewidth=0.7, color='gray', alpha=0.7)
174
+ axs[i, 0].grid(True, linestyle='--', linewidth=0.7, color="lightgray" ,alpha=0.6)
175
175
  axs[i, 1].axis("off")
176
176
  elif char == "m":
177
- axs[i, 0].grid(True, linestyle=':', linewidth=0.7, color='gray', alpha=0.7)
177
+ axs[i, 0].grid(True, linestyle='--', linewidth=0.7, color="lightgray" ,alpha=0.6)
178
178
  axs[i, 0].tick_params(bottom=False, labelbottom=False)
179
179
 
180
180
  axs[i, 0].sharex(axs[0, 0])
@@ -1,38 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- #---------------------------------
4
- # Author: Ankit Anand
5
- # Date: 12/08/25
6
- # Email: ankit0.anand0@gmail.com
7
- #---------------------------------
8
-
9
- from pathlib import Path
10
-
11
- def load_ann(path):
12
- """
13
- Load annotation from audatity label text file.
14
-
15
- Parameters
16
- ----------
17
- path: str
18
- label text file path.
19
-
20
- Returns
21
- -------
22
- list[tuple, ...]
23
- - annotation data structure
24
- - [(start, end, tag), ...]
25
- """
26
-
27
- if not isinstance(path, (str, Path)):
28
- raise ValueError(f"`path` must be one of (str, Path), got {type(path)}")
29
-
30
- ann = []
31
- with open(str(path), "r") as f:
32
- lines = [line.rstrip("\n") for line in f]
33
- for line in lines:
34
- start, end, tag = line.split("\t")
35
- start, end = float(start), float(end)
36
- ann.append((start, end, tag))
37
-
38
- return ann
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes