modusa 0.4.11__py3-none-any.whl → 0.4.13__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 CHANGED
@@ -8,4 +8,4 @@ from modusa.tools import play, convert, record, save
8
8
  from modusa.tools import download
9
9
  from modusa.tools import load, load_ann
10
10
 
11
- __version__ = "0.4.11"
11
+ __version__ = "0.4.13"
@@ -6,16 +6,15 @@
6
6
  # Email: ankit0.anand0@gmail.com
7
7
  #---------------------------------
8
8
 
9
- from pathlib import Path
10
-
11
9
  def load_ann(path, clip=None):
12
10
  """
13
- Load annotation from audatity label text file.
11
+ Load annotation from audatity label
12
+ text file and also ctm file.
14
13
 
15
14
  Parameters
16
15
  ----------
17
16
  path: str
18
- - label text file path.
17
+ - label text/ctm file path.
19
18
  clip: tuple[number, number] | number | None
20
19
  - Incase you clipped the audio signal, this parameter will help clip the annotation.
21
20
  - If you clip the audio, say from (10, 20), set the clip to (10, 20).
@@ -25,12 +24,23 @@ def load_ann(path, clip=None):
25
24
  -------
26
25
  list[tuple, ...]
27
26
  - annotation data structure
28
- - [(start, end, tag), ...]
27
+ - [(start, end, label), ...]
29
28
  """
29
+ from pathlib import Path
30
30
 
31
31
  if not isinstance(path, (str, Path)):
32
32
  raise ValueError(f"`path` must be one of (str, Path), got {type(path)}")
33
33
 
34
+ # Convert to Path object
35
+ path = Path(path)
36
+
37
+ # Check if the path exists
38
+ if not path.exists():
39
+ raise FileExistsError(f"{path} does not exist")
40
+
41
+ ann = [] # This will store the annotation
42
+
43
+ # Clipping the annotation to match with the clipped audio
34
44
  if clip is not None:
35
45
  # Map clip input to the right format
36
46
  if isinstance(clip, int or float):
@@ -40,26 +50,56 @@ def load_ann(path, clip=None):
40
50
  else:
41
51
  raise ValueError(f"Invalid clip type or length: {type(clip)}, len={len(clip)}")
42
52
 
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)
53
+ if path.suffix == ".txt":
54
+ with open(str(path), "r") as f:
55
+ lines = [line.rstrip("\n") for line in f]
56
+ for line in lines:
57
+ start, end, label = line.split("\t")
58
+ start, end = float(start), float(end)
59
+
60
+ # Incase user has clipped the audio signal, we adjust the annotation
61
+ # to match the clipped audio
62
+ if clip is not None:
63
+ offset = clip[0]
64
+ # Clamp annotation to clip boundaries
65
+ new_start = max(start, clip[0]) - offset
66
+ new_end = min(end, clip[1]) - offset
67
+
68
+ # only keep if there's still overlap
69
+ if new_start < new_end:
70
+ ann.append((new_start, new_end, label))
71
+ else:
72
+ ann.append((start, end, label))
73
+
74
+ elif path.suffix == ".ctm":
75
+ with open(str(path), "r") as f:
76
+ content = f.read().split("\n")
50
77
 
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
78
+ for c in content:
79
+ c = c.strip()
80
+ if c == "": # Handle empty line usually at the end of the ctm file
81
+ continue
82
+ elif len(c.split(" ")) != 5:
83
+ warnings.warn(f" '{c}' is not a standard ctm line.")
84
+ if len(c.split(" ")) == 5:
85
+ _, _, start, dur, label = c.split(" ")
86
+ start, dur = float(start), float(dur)
87
+ end = start + dur
58
88
 
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))
89
+ # Incase user has clipped the audio signal, we adjust the annotation
90
+ # to match the clipped audio
91
+ if clip is not None:
92
+ offset = clip[0]
93
+ # Clamp annotation to clip boundaries
94
+ new_start = max(start, clip[0]) - offset
95
+ new_end = min(end, clip[1]) - offset
96
+
97
+ # only keep if there's still overlap
98
+ if new_start < new_end:
99
+ ann.append((new_start, new_end, label))
100
+ else:
101
+ ann.append((start, end, label))
64
102
 
103
+ else:
104
+ raise Exception(f"Unsupported file type {path.suffix}")
65
105
  return ann
modusa/tools/plotter.py CHANGED
@@ -32,8 +32,7 @@ def _load_devanagari_font():
32
32
 
33
33
  # Set as default rcParam
34
34
  mpl.rcParams['font.family'] = hindi_font.get_name()
35
-
36
- _load_devanagari_font()
35
+
37
36
  #==============
38
37
 
39
38
  class Fig:
@@ -71,6 +70,8 @@ class Fig:
71
70
 
72
71
  def __init__(self, arrangement="asm", xlim=None, width=16, dark_mode=False, abc=False, fig_num=None):
73
72
 
73
+ _load_devanagari_font()
74
+
74
75
  if dark_mode:
75
76
  plt.style.use("dark_background")
76
77
  else: # We do not reset to default as it changes other params leading to unexpected behaviour
@@ -1,17 +1,18 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modusa
3
- Version: 0.4.11
3
+ Version: 0.4.13
4
4
  Summary: A modular signal analysis python library.
5
5
  Author-Email: Ankit Anand <ankit0.anand0@gmail.com>
6
6
  License: MIT
7
- Requires-Python: >=3.10
7
+ Requires-Python: >=3.11
8
8
  Requires-Dist: numpy>=2.2.6
9
9
  Requires-Dist: matplotlib>=3.10.3
10
10
  Requires-Dist: yt-dlp==2025.9.23
11
- Requires-Dist: librosa==0.11.0
12
- Requires-Dist: IPython>=8.0.0
11
+ Requires-Dist: IPython>=9.5.0
13
12
  Requires-Dist: sounddevice>=0.5.2
14
13
  Requires-Dist: ipywidgets>=8.1.7
14
+ Requires-Dist: soundfile>=0.13.1
15
+ Requires-Dist: scipy>=1.16.2
15
16
  Description-Content-Type: text/markdown
16
17
 
17
18
  # modusa
@@ -1,9 +1,8 @@
1
- modusa-0.4.11.dist-info/METADATA,sha256=GQJBql-HC1fpDAlytXqq1HTdtdi9A8kv9c_hzR_O88Y,1436
2
- modusa-0.4.11.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
- modusa-0.4.11.dist-info/entry_points.txt,sha256=fmKpleVXj6CdaBVL14WoEy6xx7JQCs85jvzwTi3lePM,73
4
- modusa-0.4.11.dist-info/licenses/LICENSE.md,sha256=JTaXAjx5awk76VArKCx5dUW8vmLEWsL_ZlR7-umaHbA,1078
5
- modusa/.DS_Store,sha256=b3Lw2RBGnDArqCyxps1EmN2oazEM0wnzg3BgurdE0_M,8196
6
- modusa/__init__.py,sha256=aT34Vb865dIq8YB7NY54hlELuU0KCBliduPkKJLqMCs,318
1
+ modusa-0.4.13.dist-info/METADATA,sha256=I-DMQGxex48XuGuSc-9LVg4Q10eO8eLN0GLI9Yln-bU,1467
2
+ modusa-0.4.13.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
+ modusa-0.4.13.dist-info/entry_points.txt,sha256=fmKpleVXj6CdaBVL14WoEy6xx7JQCs85jvzwTi3lePM,73
4
+ modusa-0.4.13.dist-info/licenses/LICENSE.md,sha256=JTaXAjx5awk76VArKCx5dUW8vmLEWsL_ZlR7-umaHbA,1078
5
+ modusa/__init__.py,sha256=OJew7gBTATXtYr813FALjhEni7uV1ksMu2BuYzLLZdc,318
7
6
  modusa/config.py,sha256=bTqK4t00FZqERVITrxW_q284aDDJAa9aMSfFknfR-oU,280
8
7
  modusa/decorators.py,sha256=8zeNX_wE37O6Vp0ysR4-WCZaEL8mq8dyCF_I5DHOzks,5905
9
8
  modusa/devtools/generate_docs_source.py,sha256=UDflHsk-Yh9-3YJTVBzKL32y8hcxiRgAlFEBTMiDqwM,3301
@@ -29,7 +28,6 @@ modusa/generators/s_ax.py,sha256=4CTFp_KwYnl4HDno-ATpTXOfKR9WEVOV45nwuk2OoVk,222
29
28
  modusa/generators/t_ax.py,sha256=X-XOJuGWw99dPAVsCVzNTfBFr81Vw56aZlGDmcl5q3k,1478
30
29
  modusa/generators/tds.py,sha256=eGvzcjXyWaw5NVzM3D098r3xkoMcX8Ma9YoDUdL30Mo,5960
31
30
  modusa/models/__init__.py,sha256=G8sNOnBnTKqPmC4Z46ximBhc_pfBOF_G6AIfxT8DFzw,271
32
- modusa/models/__pycache__/signal1D.cpython-312.pyc.4443461152,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
31
  modusa/models/audio.py,sha256=IcNx3h8tb5Jt6KZug_TQKM5iufVk3i7Ug37iKG4gsJ0,2411
34
32
  modusa/models/base.py,sha256=1qAXj69VsmrjGqShl5b27Jvt7OADHmPY0L9fBtpB_1E,1621
35
33
  modusa/models/data.py,sha256=ds5zM0NOCwGImdxNdx27OnVpgKZ6kXUJMYBUqFWshXY,11368
@@ -43,7 +41,7 @@ modusa/plugins/__init__.py,sha256=r1Bf5mnrVKRIwxboutY1iGzDy4EPQhqpk1kSW7iJj_Q,54
43
41
  modusa/plugins/base.py,sha256=Bh_1Bja7fOymFsCgwhXDbV6ys3D8muNrPwrfDrG_G_A,2382
44
42
  modusa/tools/__init__.py,sha256=q4d7J4xGraVLVLsk4h1OcWvi19FXd7DbJrGdUAOn5Es,336
45
43
  modusa/tools/_plotter_old.py,sha256=KGow7mihA2H1WNq7s5bpivhCgGo2qVIeDaO6iabpsrg,19294
46
- modusa/tools/ann_loader.py,sha256=GWiX7v4CxyAECthmtBAaSMMqsjo1YaVfRA9u-CtTTFM,1718
44
+ modusa/tools/ann_loader.py,sha256=EMV6lTm1IeTjvWjvagDgwosux9IV6MZkVdUMzVft9Pc,3017
47
45
  modusa/tools/audio_converter.py,sha256=415qBoPm2sBIuBSI7m1XBKm0AbmVmPydIPPr-uO8D3c,1778
48
46
  modusa/tools/audio_loader.py,sha256=n9Q9t_GmlE8AtioVwRcXX3rnd6PkbGTx-hAoNgUnNOQ,2780
49
47
  modusa/tools/audio_player.py,sha256=pXKaNsDbqhCVbrMx5QRv7aC2IPMJFY5POAG60f-1LmU,2901
@@ -51,13 +49,12 @@ modusa/tools/audio_recorder.py,sha256=K_LGqsPdjTdf3figEZTSQLmgMzYWgz18HTO8C1j5fE
51
49
  modusa/tools/audio_saver.py,sha256=ldzfr_AydsHTnKbxmBLJblN-hLzTmOlppOm306xI4Ug,510
52
50
  modusa/tools/base.py,sha256=C0ESJ0mIfjjRlAkRbSetNtMoOfS6IrHBjexRp3l_Mh4,1293
53
51
  modusa/tools/math_ops.py,sha256=ZZ7U4DgqT7cOeE7_Lzi_Qq-48WYfwR9_osbZwTmE9eg,8690
54
- modusa/tools/plotter.py,sha256=yjnP_oQR2Z5o238sfrNco-wweDJQ-8wawHvTJER9sYc,29960
52
+ modusa/tools/plotter.py,sha256=VwHWxQ9t5oP20cHaALMwFsE_fqSUhl_9KDufucTCodw,29964
55
53
  modusa/tools/youtube_downloader.py,sha256=hB_X8-7nOHXOlxg6vv3wyhBLoAsWyomrULP6_uCQL7s,1698
56
- modusa/utils/.DS_Store,sha256=nLXMwF7QJNuglLI_Gk74F7vl5Dyus2Wd74Mgowijmdo,6148
57
54
  modusa/utils/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
58
55
  modusa/utils/config.py,sha256=cuGbqbovx5WDQq5rw3hIKcv3CnE5NttjacSOWnP1yu4,576
59
56
  modusa/utils/excp.py,sha256=L9vhaGjKpv9viJYdmC9n5ndmk2GVbUBuFyZyhAQZmWY,906
60
57
  modusa/utils/logger.py,sha256=K0rsnObeNKCxlNeSnVnJeRhgfmob6riB2uyU7h3dDmA,571
61
58
  modusa/utils/np_func_cat.py,sha256=TyIFgRc6bARRMDnZxlVURO5Z0I-GWhxRONYyIv-Vwxs,1007
62
59
  modusa/utils/plot.py,sha256=s_vNdxvKfwxEngvJPgrF1PcmxZNnNaaXPViHWjyjJ-c,5335
63
- modusa-0.4.11.dist-info/RECORD,,
60
+ modusa-0.4.13.dist-info/RECORD,,
modusa/.DS_Store DELETED
Binary file
modusa/utils/.DS_Store DELETED
Binary file