modusa 0.3.28__py3-none-any.whl → 0.3.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.
modusa/tools/plotter.py CHANGED
@@ -27,7 +27,7 @@ def _calculate_extent(x, y):
27
27
  ]
28
28
 
29
29
  #======== 1D ===========
30
- def plot1d(*args, ann=None, events=None, xlim=None, ylim=None, xlabel=None, ylabel=None, title=None, legend=None, show_grid=False):
30
+ def plot1d(*args, ann=None, events=None, xlim=None, ylim=None, xlabel=None, ylabel=None, title=None, legend=None, show_grid=False, show_stem=False):
31
31
  """
32
32
  Plots a 1D signal using matplotlib.
33
33
 
@@ -75,6 +75,9 @@ def plot1d(*args, ann=None, events=None, xlim=None, ylim=None, xlabel=None, ylab
75
75
  show_grid: bool
76
76
  - If you want to show the grid.
77
77
  - Default: False
78
+ show_stem: bool:
79
+ - If you want stem plot.
80
+ - Default: False
78
81
 
79
82
  Returns
80
83
  -------
@@ -85,6 +88,7 @@ def plot1d(*args, ann=None, events=None, xlim=None, ylim=None, xlabel=None, ylab
85
88
  for arg in args:
86
89
  if len(arg) not in [1, 2]: # 1 if it just provides values, 2 if it provided axis as well
87
90
  raise ValueError(f"1D signal needs to have max 2 arrays (y, x) or simply (y, )")
91
+
88
92
  if isinstance(legend, str): legend = (legend, )
89
93
 
90
94
  if legend is not None:
@@ -111,27 +115,52 @@ def plot1d(*args, ann=None, events=None, xlim=None, ylim=None, xlabel=None, ylab
111
115
  for i, signal in enumerate(args):
112
116
  if len(signal) == 1:
113
117
  y = signal[0]
118
+ x = np.arange(y.size)
114
119
  if legend is not None:
115
- signal_ax.plot(y, label=legend[i])
120
+ if show_stem is True:
121
+ markerline, stemlines, baseline = signal_ax.stem(x, y, label=legend[i])
122
+ markerline.set_color(colors[i])
123
+ stemlines.set_color(colors[i])
124
+ baseline.set_color("k")
125
+ else:
126
+ signal_ax.plot(x, y, color=colors[i], label=legend[i])
116
127
  else:
117
- signal_ax.plot(y)
128
+ if show_stem is True:
129
+ markerline, stemlines, baseline = signal_ax.stem(x, y)
130
+ markerline.set_color(colors[i])
131
+ stemlines.set_color(colors[i])
132
+ baseline.set_color("k")
133
+ else:
134
+ signal_ax.plot(x, y, color=colors[i])
135
+
118
136
  elif len(signal) == 2:
119
137
  y, x = signal[0], signal[1]
120
138
  if legend is not None:
121
- signal_ax.plot(x, y, label=legend[i])
139
+ if show_stem is True:
140
+ signal_ax.stem(x, y, linefmt=f"{colors[i]}-", markerfmt=f"{colors[i]}o", basefmt="k-", label=legend[i])
141
+ else:
142
+ signal_ax.plot(x, y, color=colors[i], label=legend[i])
122
143
  else:
123
- signal_ax.plot(x, y)
144
+ if show_stem is True:
145
+ signal_ax.stem(x, y, linefmt=f"{colors[i]}-", markerfmt=f"{colors[i]}o", basefmt="k-")
146
+ else:
147
+ signal_ax.plot(x, y, color=colors[i])
124
148
 
125
149
  # Add annotations
126
150
  if ann is not None:
127
- annotation_ax.set_ylim(0, 1)
151
+ annotation_ax.set_ylim(0, 1) # For consistent layout
152
+ # Determine visible x-range
153
+ x_view_min = xlim[0] if xlim is not None else np.min(x)
154
+ x_view_max = xlim[1] if xlim is not None else np.max(x)
155
+
128
156
  for i, (start, end, tag) in enumerate(ann):
129
- if xlim is not None:
130
- if end < xlim[0] or start > xlim[1]:
131
- continue # Skip out-of-view regions
132
- # Clip boundaries to xlim
133
- start = max(start, xlim[0])
134
- end = min(end, xlim[1])
157
+ # We make sure that we only plot annotation that are within the x range of the current view
158
+ if start >= x_view_max or end <= x_view_min:
159
+ continue
160
+
161
+ # Clip boundaries to xlim
162
+ start = max(start, x_view_min)
163
+ end = min(end, x_view_max)
135
164
 
136
165
  color = colors[i % len(colors)]
137
166
  width = end - start
@@ -159,7 +188,7 @@ def plot1d(*args, ann=None, events=None, xlim=None, ylim=None, xlabel=None, ylab
159
188
  # Add legend
160
189
  if legend is not None:
161
190
  handles, labels = signal_ax.get_legend_handles_labels()
162
- fig.legend(handles, labels, loc='upper right', bbox_to_anchor=(0.9, 1.2), ncol=len(legend), frameon=False)
191
+ fig.legend(handles, labels, loc='upper right', bbox_to_anchor=(0.9, 1.2), ncol=len(legend), frameon=True)
163
192
 
164
193
  # Set title, labels
165
194
  if title is not None:
@@ -315,14 +344,19 @@ def plot2d(*args, ann=None, events=None, xlim=None, ylim=None, origin="lower", M
315
344
 
316
345
  # Add annotations
317
346
  if ann is not None:
318
- annotation_ax.set_ylim(0, 1)
347
+ annotation_ax.set_ylim(0, 1) # For consistent layout
348
+ # Determine visible x-range
349
+ x_view_min = xlim[0] if xlim is not None else np.min(x)
350
+ x_view_max = xlim[1] if xlim is not None else np.max(x)
351
+
319
352
  for i, (start, end, tag) in enumerate(ann):
320
- if xlim is not None:
321
- if end < xlim[0] or start > xlim[1]:
322
- continue # Skip out-of-view regions
323
- # Clip boundaries to xlim
324
- start = max(start, xlim[0])
325
- end = min(end, xlim[1])
353
+ # We make sure that we only plot annotation that are within the x range of the current view
354
+ if start >= x_view_max or end <= x_view_min:
355
+ continue
356
+
357
+ # Clip boundaries to xlim
358
+ start = max(start, x_view_min)
359
+ end = min(end, x_view_max)
326
360
 
327
361
  color = colors[i % len(colors)]
328
362
  width = end - start
@@ -451,11 +485,11 @@ def plot_dist(*args, ann=None, xlim=None, ylim=None, ylabel=None, xlabel=None, t
451
485
  from scipy.stats import gaussian_kde
452
486
 
453
487
  if isinstance(legend, str):
454
- legend = (legend, )
488
+ legend = (legend, )
455
489
 
456
490
  if legend is not None:
457
- if len(legend) < len(args):
458
- raise ValueError(f"Legend should be provided for each signal.")
491
+ if len(legend) < len(args):
492
+ raise ValueError(f"Legend should be provided for each signal.")
459
493
 
460
494
  # Create figure
461
495
  fig = plt.figure(figsize=(16, 4))
@@ -468,66 +502,70 @@ def plot_dist(*args, ann=None, xlim=None, ylim=None, ylabel=None, xlabel=None, t
468
502
 
469
503
  # Set limits
470
504
  if xlim is not None:
471
- dist_ax.set_xlim(xlim)
505
+ dist_ax.set_xlim(xlim)
472
506
 
473
507
  if ylim is not None:
474
- dist_ax.set_ylim(ylim)
508
+ dist_ax.set_ylim(ylim)
475
509
 
476
510
  # Add plot
477
511
  for i, data in enumerate(args):
478
- # Fit gaussian to the data
479
- kde = gaussian_kde(data)
480
-
481
- # Create points to evaluate KDE
482
- x_vals = np.linspace(min(data), max(data), npoints)
483
- y_vals = kde(x_vals)
484
-
485
- if legend is not None:
486
- dist_ax.plot(x_vals, y_vals, color=colors[i], label=legend[i])
487
- if show_hist is True:
488
- dist_ax.hist(data, bins=bins, density=True, alpha=0.3, facecolor=colors[i], edgecolor='black', label=legend[i])
489
- else:
490
- dist_ax.plot(x_vals, y_vals, color=colors[i])
491
- if show_hist is True:
492
- dist_ax.hist(data, bins=bins, density=True, alpha=0.3, facecolor=colors[i], edgecolor='black')
512
+ # Fit gaussian to the data
513
+ kde = gaussian_kde(data)
514
+
515
+ # Create points to evaluate KDE
516
+ x = np.linspace(np.min(data), np.max(data), npoints)
517
+ y = kde(x)
518
+
519
+ if legend is not None:
520
+ dist_ax.plot(x, y, color=colors[i], label=legend[i])
521
+ if show_hist is True:
522
+ dist_ax.hist(data, bins=bins, density=True, alpha=0.3, facecolor=colors[i], edgecolor='black', label=legend[i])
523
+ else:
524
+ dist_ax.plot(x, y, color=colors[i])
525
+ if show_hist is True:
526
+ dist_ax.hist(data, bins=bins, density=True, alpha=0.3, facecolor=colors[i], edgecolor='black')
493
527
 
494
528
  # Add annotations
495
529
  if ann is not None:
496
- annotation_ax.set_ylim(0, 1)
497
- for i, (start, end, tag) in enumerate(ann):
498
- if xlim is not None:
499
- if end < xlim[0] or start > xlim[1]:
500
- continue # Skip out-of-view regions
501
- # Clip boundaries to xlim
502
- start = max(start, xlim[0])
503
- end = min(end, xlim[1])
504
-
505
- color = colors[i % len(colors)]
506
- width = end - start
507
- rect = Rectangle((start, 0), width, 1, color=color, alpha=0.7)
508
- annotation_ax.add_patch(rect)
530
+ annotation_ax.set_ylim(0, 1) # For consistent layout
531
+ # Determine visible x-range
532
+ x_view_min = xlim[0] if xlim is not None else np.min(x)
533
+ x_view_max = xlim[1] if xlim is not None else np.max(x)
534
+ for i, (start, end, tag) in enumerate(ann):
535
+ # We make sure that we only plot annotation that are within the x range of the current view
536
+ if start >= x_view_max or end <= x_view_min:
537
+ continue
538
+
539
+ # Clip boundaries to xlim
540
+ start = max(start, x_view_min)
541
+ end = min(end, x_view_max)
509
542
 
510
- text_obj = annotation_ax.text((start + end) / 2, 0.5, tag, ha='center', va='center', fontsize=10, color='white', fontweight='bold', zorder=10, clip_on=True)
511
- text_obj.set_clip_path(rect)
543
+ color = colors[i % len(colors)]
544
+ width = end - start
545
+ rect = Rectangle((start, 0), width, 1, color=color, alpha=0.7)
546
+ annotation_ax.add_patch(rect)
547
+
548
+ text_obj = annotation_ax.text((start + end) / 2, 0.5, tag, ha='center', va='center', fontsize=10, color='white', fontweight='bold', zorder=10, clip_on=True)
549
+ text_obj.set_clip_path(rect)
512
550
 
513
551
  # Add legend
514
552
  if legend is not None:
515
- handles, labels = dist_ax.get_legend_handles_labels()
516
- fig.legend(handles, labels, loc='upper right', bbox_to_anchor=(0.9, 1.1), ncol=len(legend), frameon=True)
553
+ handles, labels = dist_ax.get_legend_handles_labels()
554
+ fig.legend(handles, labels, loc='upper right', bbox_to_anchor=(0.9, 1.1), ncol=len(legend), frameon=True)
517
555
 
518
556
  # Set title, labels
519
557
  if title is not None:
520
- annotation_ax.set_title(title, pad=10, size=11)
558
+ annotation_ax.set_title(title, pad=10, size=11)
521
559
  if xlabel is not None:
522
- dist_ax.set_xlabel(xlabel)
560
+ dist_ax.set_xlabel(xlabel)
523
561
  if ylabel is not None:
524
- dist_ax.set_ylabel(ylabel)
562
+ dist_ax.set_ylabel(ylabel)
525
563
 
526
564
  # Remove the boundaries and ticks from annotation axis
527
565
  if ann is not None:
528
- annotation_ax.tick_params(left=False, bottom=False, labelleft=False, labelbottom=False)
566
+ annotation_ax.tick_params(left=False, bottom=False, labelleft=False, labelbottom=False)
529
567
  else:
530
- annotation_ax.axis("off")
568
+ annotation_ax.axis("off")
531
569
 
532
570
  fig.subplots_adjust(hspace=0.01, wspace=0.05)
533
571
  plt.close()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modusa
3
- Version: 0.3.28
3
+ Version: 0.3.30
4
4
  Summary: A modular signal analysis python library.
5
5
  Author-Email: Ankit Anand <ankit0.anand0@gmail.com>
6
6
  License: MIT
@@ -1,7 +1,7 @@
1
- modusa-0.3.28.dist-info/METADATA,sha256=wNR4dM9jMye2V4s7H9zhtD6k9w6B8kUdlzGQdxbINvc,1369
2
- modusa-0.3.28.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
- modusa-0.3.28.dist-info/entry_points.txt,sha256=fmKpleVXj6CdaBVL14WoEy6xx7JQCs85jvzwTi3lePM,73
4
- modusa-0.3.28.dist-info/licenses/LICENSE.md,sha256=JTaXAjx5awk76VArKCx5dUW8vmLEWsL_ZlR7-umaHbA,1078
1
+ modusa-0.3.30.dist-info/METADATA,sha256=ue8QCA3HR90-JBEZkGmfM-up5D6tFqn88u2QqGrdHd8,1369
2
+ modusa-0.3.30.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
+ modusa-0.3.30.dist-info/entry_points.txt,sha256=fmKpleVXj6CdaBVL14WoEy6xx7JQCs85jvzwTi3lePM,73
4
+ modusa-0.3.30.dist-info/licenses/LICENSE.md,sha256=JTaXAjx5awk76VArKCx5dUW8vmLEWsL_ZlR7-umaHbA,1078
5
5
  modusa/.DS_Store,sha256=_gm6qJREwfMi8dE7n5S89_RG46u5t3xHyD-smNhtNoM,6148
6
6
  modusa/__init__.py,sha256=uq6kORFFAODiCMGmOLWO0shE8-dVFWf5gmV8wxekmnk,280
7
7
  modusa/config.py,sha256=bTqK4t00FZqERVITrxW_q284aDDJAa9aMSfFknfR-oU,280
@@ -47,7 +47,7 @@ modusa/tools/audio_loader.py,sha256=DrCzq0pdiQrUDIG-deLJGcu8EaylO5yRtwT4lr8WSf8,
47
47
  modusa/tools/audio_player.py,sha256=GP04TWW4jBwQBjANkfR_cJtEy7cIhvbu8RTwnf9hD6E,2817
48
48
  modusa/tools/base.py,sha256=C0ESJ0mIfjjRlAkRbSetNtMoOfS6IrHBjexRp3l_Mh4,1293
49
49
  modusa/tools/math_ops.py,sha256=ZZ7U4DgqT7cOeE7_Lzi_Qq-48WYfwR9_osbZwTmE9eg,8690
50
- modusa/tools/plotter.py,sha256=Pfj24jl-WHgdfPI-f4J_XLpMyed6OHkwAvtuIBKoAEw,16016
50
+ modusa/tools/plotter.py,sha256=rIv5TmKtr9uliRcLNRjmejwvIixZqpUf4_dtqSlx2Hg,17510
51
51
  modusa/tools/youtube_downloader.py,sha256=hB_X8-7nOHXOlxg6vv3wyhBLoAsWyomrULP6_uCQL7s,1698
52
52
  modusa/utils/.DS_Store,sha256=nLXMwF7QJNuglLI_Gk74F7vl5Dyus2Wd74Mgowijmdo,6148
53
53
  modusa/utils/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
@@ -56,4 +56,4 @@ modusa/utils/excp.py,sha256=L9vhaGjKpv9viJYdmC9n5ndmk2GVbUBuFyZyhAQZmWY,906
56
56
  modusa/utils/logger.py,sha256=K0rsnObeNKCxlNeSnVnJeRhgfmob6riB2uyU7h3dDmA,571
57
57
  modusa/utils/np_func_cat.py,sha256=TyIFgRc6bARRMDnZxlVURO5Z0I-GWhxRONYyIv-Vwxs,1007
58
58
  modusa/utils/plot.py,sha256=s_vNdxvKfwxEngvJPgrF1PcmxZNnNaaXPViHWjyjJ-c,5335
59
- modusa-0.3.28.dist-info/RECORD,,
59
+ modusa-0.3.30.dist-info/RECORD,,