modusa 0.3.74__tar.gz → 0.3.76__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.74 → modusa-0.3.76}/PKG-INFO +1 -1
  2. {modusa-0.3.74 → modusa-0.3.76}/pyproject.toml +1 -1
  3. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/__init__.py +1 -1
  4. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/tools/__init__.py +1 -0
  5. modusa-0.3.76/src/modusa/tools/audio_saver.py +30 -0
  6. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/tools/plotter.py +42 -28
  7. {modusa-0.3.74 → modusa-0.3.76}/LICENSE.md +0 -0
  8. {modusa-0.3.74 → modusa-0.3.76}/README.md +0 -0
  9. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/.DS_Store +0 -0
  10. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/config.py +0 -0
  11. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/decorators.py +0 -0
  12. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/devtools/generate_docs_source.py +0 -0
  13. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/devtools/generate_template.py +0 -0
  14. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/devtools/list_authors.py +0 -0
  15. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/devtools/list_plugins.py +0 -0
  16. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/devtools/main.py +0 -0
  17. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/devtools/templates/generator.py +0 -0
  18. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/devtools/templates/io.py +0 -0
  19. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/devtools/templates/model.py +0 -0
  20. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/devtools/templates/plugin.py +0 -0
  21. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/devtools/templates/test.py +0 -0
  22. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/devtools/templates/tool.py +0 -0
  23. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/fonts/NotoSansDevanagari-Regular.ttf +0 -0
  24. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/generators/__init__.py +0 -0
  25. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/generators/audio.py +0 -0
  26. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/generators/audio_waveforms.py +0 -0
  27. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/generators/base.py +0 -0
  28. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/generators/ftds.py +0 -0
  29. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/generators/s1d.py +0 -0
  30. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/generators/s2d.py +0 -0
  31. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/generators/s_ax.py +0 -0
  32. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/generators/t_ax.py +0 -0
  33. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/generators/tds.py +0 -0
  34. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/models/__init__.py +0 -0
  35. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/models/__pycache__/signal1D.cpython-312.pyc.4443461152 +0 -0
  36. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/models/audio.py +0 -0
  37. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/models/base.py +0 -0
  38. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/models/data.py +0 -0
  39. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/models/ftds.py +0 -0
  40. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/models/s1d.py +0 -0
  41. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/models/s2d.py +0 -0
  42. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/models/s_ax.py +0 -0
  43. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/models/t_ax.py +0 -0
  44. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/models/tds.py +0 -0
  45. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/plugins/__init__.py +0 -0
  46. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/plugins/base.py +0 -0
  47. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/tools/_plotter_old.py +0 -0
  48. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/tools/ann_loader.py +0 -0
  49. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/tools/audio_converter.py +0 -0
  50. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/tools/audio_loader.py +0 -0
  51. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/tools/audio_player.py +0 -0
  52. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/tools/audio_recorder.py +0 -0
  53. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/tools/base.py +0 -0
  54. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/tools/math_ops.py +0 -0
  55. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/tools/youtube_downloader.py +0 -0
  56. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/utils/.DS_Store +0 -0
  57. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/utils/__init__.py +0 -0
  58. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/utils/config.py +0 -0
  59. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/utils/excp.py +0 -0
  60. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/utils/logger.py +0 -0
  61. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/utils/np_func_cat.py +0 -0
  62. {modusa-0.3.74 → modusa-0.3.76}/src/modusa/utils/plot.py +0 -0
  63. {modusa-0.3.74 → modusa-0.3.76}/tests/__init__.py +0 -0
  64. {modusa-0.3.74 → modusa-0.3.76}/tests/data/song1.mp3 +0 -0
  65. {modusa-0.3.74 → modusa-0.3.76}/tests/data/song1.wav +0 -0
  66. {modusa-0.3.74 → modusa-0.3.76}/tests/test_generators/audio_waveform.py +0 -0
  67. {modusa-0.3.74 → modusa-0.3.76}/tests/test_generators/test_audio.py +0 -0
  68. {modusa-0.3.74 → modusa-0.3.76}/tests/test_generators/test_ftds.py +0 -0
  69. {modusa-0.3.74 → modusa-0.3.76}/tests/test_generators/test_s1d.py +0 -0
  70. {modusa-0.3.74 → modusa-0.3.76}/tests/test_generators/test_s2d.py +0 -0
  71. {modusa-0.3.74 → modusa-0.3.76}/tests/test_generators/test_s_ax.py +0 -0
  72. {modusa-0.3.74 → modusa-0.3.76}/tests/test_generators/test_signal.py +0 -0
  73. {modusa-0.3.74 → modusa-0.3.76}/tests/test_generators/test_signal_generator.py +0 -0
  74. {modusa-0.3.74 → modusa-0.3.76}/tests/test_generators/test_t_ax.py +0 -0
  75. {modusa-0.3.74 → modusa-0.3.76}/tests/test_generators/test_tds.py +0 -0
  76. {modusa-0.3.74 → modusa-0.3.76}/tests/test_io/audio_player.py +0 -0
  77. {modusa-0.3.74 → modusa-0.3.76}/tests/test_io/plotter.py +0 -0
  78. {modusa-0.3.74 → modusa-0.3.76}/tests/test_models/test_data.py +0 -0
  79. {modusa-0.3.74 → modusa-0.3.76}/tests/test_models/test_t_ax.py +0 -0
  80. {modusa-0.3.74 → modusa-0.3.76}/tests/test_plugins/youtube_audio_loader.py +0 -0
  81. {modusa-0.3.74 → modusa-0.3.76}/tests/test_signals/frequency_domain_signal.py +0 -0
  82. {modusa-0.3.74 → modusa-0.3.76}/tests/test_signals/spectrogram.py +0 -0
  83. {modusa-0.3.74 → modusa-0.3.76}/tests/test_signals/test_axis.py +0 -0
  84. {modusa-0.3.74 → modusa-0.3.76}/tests/test_signals/test_feature_time_domain_signal.py +0 -0
  85. {modusa-0.3.74 → modusa-0.3.76}/tests/test_signals/test_frequency_time_domain_signal.py +0 -0
  86. {modusa-0.3.74 → modusa-0.3.76}/tests/test_signals/test_signal1D.py +0 -0
  87. {modusa-0.3.74 → modusa-0.3.76}/tests/test_signals/test_signal2D.py +0 -0
  88. {modusa-0.3.74 → modusa-0.3.76}/tests/test_signals/test_time_domain_signal.py +0 -0
  89. {modusa-0.3.74 → modusa-0.3.76}/tests/test_signals/test_u_ax.py +0 -0
  90. {modusa-0.3.74 → modusa-0.3.76}/tests/test_signals/test_window_signal.py +0 -0
  91. {modusa-0.3.74 → modusa-0.3.76}/tests/test_signals/time_domain_signal.py +0 -0
  92. {modusa-0.3.74 → modusa-0.3.76}/tests/test_tools/test_audio_converter.py +0 -0
  93. {modusa-0.3.74 → modusa-0.3.76}/tests/test_tools/test_fourier_tranform.py +0 -0
  94. {modusa-0.3.74 → modusa-0.3.76}/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.74
3
+ Version: 0.3.76
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.74"
3
+ version = "0.3.76"
4
4
  description = "A modular signal analysis python library."
5
5
  authors = [
6
6
  { name = "Ankit Anand", email = "ankit0.anand0@gmail.com" },
@@ -4,6 +4,6 @@ from modusa.utils import excp, config
4
4
  from modusa.tools import plot_dist, fig
5
5
  #=====
6
6
 
7
- from modusa.tools import play, convert, record
7
+ from modusa.tools import play, convert, record, save
8
8
  from modusa.tools import download
9
9
  from modusa.tools import load, load_ann
@@ -4,6 +4,7 @@ from .audio_player import play
4
4
  from .audio_converter import convert
5
5
  from .youtube_downloader import download
6
6
  from .audio_loader import load
7
+ from .audio_saver import save
7
8
  from .ann_loader import load_ann
8
9
  from .audio_recorder import record
9
10
 
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env python3
2
+
3
+ #---------------------------------
4
+ # Author: Ankit Anand
5
+ # Date: 13/09/25
6
+ # Email: ankit0.anand0@gmail.com
7
+ #---------------------------------
8
+
9
+
10
+ def save(y, sr, out_path):
11
+ """
12
+ Saves an array as an audio file.
13
+
14
+ Parameters
15
+ ----------
16
+ y: ndarray
17
+ - Audio signal array.
18
+ sr: number [> 0]
19
+ - Sampling rate of the audio signal.
20
+ out_path: str
21
+ - Output path of the audio file.
22
+
23
+ Returns
24
+ -------
25
+ None
26
+ """
27
+
28
+ import soundfile as sf
29
+
30
+ sf.write(file=out_path, data=y, samplerate=sr)
@@ -541,24 +541,26 @@ class Fig:
541
541
  from matplotlib.patches import Rectangle
542
542
  import matplotlib.pyplot as plt
543
543
 
544
- def add_arrow(self, xy, label, text_offset=(0, 0), c="r", fontsize=12, ax=None):
544
+ def add_arrows(self, xys, labels, text_offset=(0, 0), c="r", fontsize=12, ax=None):
545
545
  """
546
- Add an arrow pointing to a specific point with a boxed label at the tail.
546
+ Add multiple arrows pointing to specific points with boxed labels at the tails.
547
547
 
548
548
  Parameters
549
549
  ----------
550
- xy : tuple[float, float]
551
- - Target point (x, y) for the arrow head.
552
- label : str
553
- - Text label at the arrow tail.
554
- text_offset : tuple[float, float]
555
- - Offset (dx, dy) for label position from arrow tail.
556
- c : str
557
- - Color for arrow and text.
558
- - Default: "r" for red
559
- fontsize : int
560
- - Font size of the label text.
561
- - Default: 12
550
+ xys : list[tuple[float, float]]
551
+ - List of target points (x, y) for the arrow heads.
552
+ labels : list[str] | str
553
+ - List of text labels at the arrow tails.
554
+ - If str, the same label is used for all points.
555
+ text_offset : tuple[float, float] | list[tuple[float, float]]
556
+ - Offset(s) (dx, dy) for label positions from arrow tails.
557
+ - If single tuple, same offset is applied to all.
558
+ c : str | list[str]
559
+ - Color(s) for arrow and text.
560
+ - If str, same color is applied to all.
561
+ fontsize : int | list[int]
562
+ - Font size(s) of the label text.
563
+ - If int, same size is applied to all.
562
564
  ax : int | None
563
565
  - Which specific axis to plot (1, 2, 3, ...).
564
566
  - If None, uses the current row.
@@ -569,21 +571,33 @@ class Fig:
569
571
  """
570
572
  curr_row = self._get_prev_row() if ax is None else self._axs[ax]
571
573
 
572
- arrowprops = dict(arrowstyle="->", color=c, lw=2)
573
- bbox = dict(boxstyle="round,pad=0.3", fc="white", ec=c, lw=1.2)
574
+ # Normalize single values into lists
575
+ n = len(xys)
576
+ if isinstance(labels, str):
577
+ labels = [labels] * n
578
+ if isinstance(text_offset, tuple):
579
+ text_offset = [text_offset] * n
580
+ if isinstance(c, str):
581
+ c = [c] * n
582
+ if isinstance(fontsize, int):
583
+ fontsize = [fontsize] * n
574
584
 
575
- text_x, text_y = xy[0] + text_offset[0], xy[1] + text_offset[1]
576
-
577
- curr_row[0].annotate(
578
- label,
579
- xy=xy, xycoords="data",
580
- xytext=(text_x, text_y), textcoords="data",
581
- arrowprops=arrowprops,
582
- fontsize=fontsize,
583
- color=c,
584
- ha="center", va="center",
585
- bbox=bbox
586
- )
585
+ for (xy, label, offset, color, fs) in zip(xys, labels, text_offset, c, fontsize):
586
+ arrowprops = dict(arrowstyle="->", color=color, lw=2)
587
+ bbox = dict(boxstyle="round,pad=0.3", fc="white", ec=color, lw=1.2)
588
+
589
+ text_x, text_y = xy[0] + offset[0], xy[1] + offset[1]
590
+
591
+ curr_row[0].annotate(
592
+ label,
593
+ xy=xy, xycoords="data",
594
+ xytext=(text_x, text_y), textcoords="data",
595
+ arrowprops=arrowprops,
596
+ fontsize=fs,
597
+ color=color,
598
+ ha="center", va="center",
599
+ bbox=bbox
600
+ )
587
601
 
588
602
  def add_legend(self, ypos=1.0):
589
603
  """
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes