modusa 0.3.45__tar.gz → 0.3.47__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.
- {modusa-0.3.45 → modusa-0.3.47}/PKG-INFO +1 -1
- {modusa-0.3.45 → modusa-0.3.47}/pyproject.toml +1 -1
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/__init__.py +1 -1
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/tools/__init__.py +1 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/tools/plotter.py +417 -13
- {modusa-0.3.45 → modusa-0.3.47}/LICENSE.md +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/README.md +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/.DS_Store +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/config.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/decorators.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/devtools/generate_docs_source.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/devtools/generate_template.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/devtools/list_authors.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/devtools/list_plugins.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/devtools/main.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/devtools/templates/generator.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/devtools/templates/io.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/devtools/templates/model.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/devtools/templates/plugin.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/devtools/templates/test.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/devtools/templates/tool.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/fonts/NotoSansDevanagari-Regular.ttf +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/generators/__init__.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/generators/audio.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/generators/audio_waveforms.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/generators/base.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/generators/ftds.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/generators/s1d.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/generators/s2d.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/generators/s_ax.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/generators/t_ax.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/generators/tds.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/models/__init__.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/models/__pycache__/signal1D.cpython-312.pyc.4443461152 +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/models/audio.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/models/base.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/models/data.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/models/ftds.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/models/s1d.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/models/s2d.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/models/s_ax.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/models/t_ax.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/models/tds.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/plugins/__init__.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/plugins/base.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/tools/_plotter_old.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/tools/ann_loader.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/tools/audio_converter.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/tools/audio_loader.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/tools/audio_player.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/tools/audio_recorder.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/tools/base.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/tools/math_ops.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/tools/youtube_downloader.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/utils/.DS_Store +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/utils/__init__.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/utils/config.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/utils/excp.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/utils/logger.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/utils/np_func_cat.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/src/modusa/utils/plot.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/__init__.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/data/song1.mp3 +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/data/song1.wav +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_generators/audio_waveform.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_generators/test_audio.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_generators/test_ftds.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_generators/test_s1d.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_generators/test_s2d.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_generators/test_s_ax.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_generators/test_signal.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_generators/test_signal_generator.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_generators/test_t_ax.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_generators/test_tds.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_io/audio_player.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_io/plotter.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_models/test_data.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_models/test_t_ax.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_plugins/youtube_audio_loader.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_signals/frequency_domain_signal.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_signals/spectrogram.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_signals/test_axis.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_signals/test_feature_time_domain_signal.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_signals/test_frequency_time_domain_signal.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_signals/test_signal1D.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_signals/test_signal2D.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_signals/test_time_domain_signal.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_signals/test_u_ax.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_signals/test_window_signal.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_signals/time_domain_signal.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_tools/test_audio_converter.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_tools/test_fourier_tranform.py +0 -0
- {modusa-0.3.45 → modusa-0.3.47}/tests/test_tools/test_math_ops.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from modusa.utils import excp, config
|
|
2
2
|
|
|
3
3
|
#=====Giving access to plot functions to plot multiple signals.=====
|
|
4
|
-
from modusa.tools import fig1d, fig2d, plot_dist
|
|
4
|
+
from modusa.tools import fig1d, fig2d, plot_dist, fig
|
|
5
5
|
#=====
|
|
6
6
|
|
|
7
7
|
from modusa.tools import play, convert, record
|
|
@@ -65,9 +65,11 @@ class Figure1D:
|
|
|
65
65
|
- Default: None
|
|
66
66
|
"""
|
|
67
67
|
|
|
68
|
-
def __init__(self, n_aux_subplots=0, xlim=None, ylim=None):
|
|
68
|
+
def __init__(self, n_aux_subplots=0, xlim=None, ylim=None, sharex=None):
|
|
69
69
|
self._n_aux_subplots: int = n_aux_subplots
|
|
70
70
|
self._active_subplot_idx: int = 1 # Any addition will happen on this subplot (0 is reserved for reference axis)
|
|
71
|
+
if sharex is not None:
|
|
72
|
+
xlim = sharex._xlim
|
|
71
73
|
self._xlim = xlim # Many add functions depend on this, so we fix it while instantiating the class
|
|
72
74
|
self._ylim = ylim
|
|
73
75
|
self._subplots, self._fig = self._generate_subplots() # Will contain all the subplots (list, fig)
|
|
@@ -109,16 +111,18 @@ class Figure1D:
|
|
|
109
111
|
|
|
110
112
|
# Add subplots
|
|
111
113
|
subplots_list = []
|
|
114
|
+
|
|
112
115
|
ref_subplot = fig.add_subplot(gs[0, 0])
|
|
113
116
|
ref_subplot.axis("off")
|
|
114
117
|
subplots_list.append(ref_subplot)
|
|
115
118
|
|
|
116
119
|
for i in range(1, n_subplots):
|
|
117
120
|
subplots_list.append(fig.add_subplot(gs[i, 0], sharex=ref_subplot))
|
|
118
|
-
|
|
121
|
+
|
|
119
122
|
for i in range(n_subplots - 1):
|
|
120
123
|
subplots_list[i].tick_params(left=False, bottom=False, labelleft=False, labelbottom=False)
|
|
121
124
|
|
|
125
|
+
|
|
122
126
|
# Set xlim
|
|
123
127
|
if self._xlim is not None: # xlim should be applied on reference subplot, rest all sharex
|
|
124
128
|
ref_subplot.set_xlim(self._xlim)
|
|
@@ -301,7 +305,7 @@ class Figure1D:
|
|
|
301
305
|
# remove duplicates if needed
|
|
302
306
|
fig.legend(all_handles, all_labels, loc='upper right', bbox_to_anchor=(0.9, ypos), ncol=2, frameon=True, bbox_transform=fig.transFigure)
|
|
303
307
|
|
|
304
|
-
def add_meta_info(self, title=None, ylabel=None, xlabel=None):
|
|
308
|
+
def add_meta_info(self, title=None, ylabel=None, xlabel=None, ts=13, ls=11):
|
|
305
309
|
"""
|
|
306
310
|
Add meta info to the figure.
|
|
307
311
|
|
|
@@ -318,7 +322,12 @@ class Figure1D:
|
|
|
318
322
|
- x label of the signal.
|
|
319
323
|
- It will only appear in the signal subplot.
|
|
320
324
|
- Default: None
|
|
321
|
-
|
|
325
|
+
ts: Number
|
|
326
|
+
- Title size
|
|
327
|
+
- Default: 10
|
|
328
|
+
ls: Number
|
|
329
|
+
- Label size.
|
|
330
|
+
- Default: 10
|
|
322
331
|
Returns
|
|
323
332
|
-------
|
|
324
333
|
None
|
|
@@ -330,11 +339,11 @@ class Figure1D:
|
|
|
330
339
|
signal_subplot = subplots[-1]
|
|
331
340
|
|
|
332
341
|
if title is not None:
|
|
333
|
-
ref_subplot.set_title(title, pad=10, size=
|
|
342
|
+
ref_subplot.set_title(title, pad=10, size=ts)
|
|
334
343
|
if ylabel is not None:
|
|
335
|
-
signal_subplot.set_ylabel(ylabel, size=
|
|
344
|
+
signal_subplot.set_ylabel(ylabel, size=ls)
|
|
336
345
|
if xlabel is not None:
|
|
337
|
-
signal_subplot.set_xlabel(xlabel, size=
|
|
346
|
+
signal_subplot.set_xlabel(xlabel, size=ls)
|
|
338
347
|
|
|
339
348
|
|
|
340
349
|
def save(self, path="./figure.png"):
|
|
@@ -383,9 +392,11 @@ class Figure2D:
|
|
|
383
392
|
- Default: None
|
|
384
393
|
"""
|
|
385
394
|
|
|
386
|
-
def __init__(self, n_aux_subplots=0, xlim=None, ylim=None):
|
|
395
|
+
def __init__(self, n_aux_subplots=0, xlim=None, ylim=None, sharex=None):
|
|
387
396
|
self._n_aux_subplots: int = n_aux_subplots
|
|
388
397
|
self._active_subplot_idx: int = 1 # Any addition will happen on this subplot (0 is reserved for reference axis)
|
|
398
|
+
if sharex is not None:
|
|
399
|
+
xlim = sharex._xlim
|
|
389
400
|
self._xlim = xlim # Many add functions depend on this, so we fix it while instantiating the class
|
|
390
401
|
self._ylim = ylim
|
|
391
402
|
self._subplots, self._fig = self._generate_subplots() # Will contain all the subplots (list, fig)
|
|
@@ -466,6 +477,7 @@ class Figure2D:
|
|
|
466
477
|
ref_subplot = fig.add_subplot(gs[0, 0])
|
|
467
478
|
ref_subplot.axis("off")
|
|
468
479
|
subplots_list.append(ref_subplot)
|
|
480
|
+
|
|
469
481
|
|
|
470
482
|
for i in range(1, n_subplots):
|
|
471
483
|
subplots_list.append(fig.add_subplot(gs[i, 0], sharex=ref_subplot))
|
|
@@ -693,7 +705,7 @@ class Figure2D:
|
|
|
693
705
|
# remove duplicates if needed
|
|
694
706
|
fig.legend(all_handles, all_labels, loc='upper right', bbox_to_anchor=(0.9, ypos), ncol=2, frameon=True, bbox_transform=fig.transFigure)
|
|
695
707
|
|
|
696
|
-
def add_meta_info(self, title=None, ylabel=None, xlabel=None):
|
|
708
|
+
def add_meta_info(self, title=None, ylabel=None, xlabel=None, ts=13, ls=11):
|
|
697
709
|
"""
|
|
698
710
|
Add meta info to the figure.
|
|
699
711
|
|
|
@@ -710,6 +722,12 @@ class Figure2D:
|
|
|
710
722
|
- x label of the signal.
|
|
711
723
|
- It will only appear in the signal subplot.
|
|
712
724
|
- Default: None
|
|
725
|
+
ts: Number
|
|
726
|
+
- Title size
|
|
727
|
+
- Default: 10
|
|
728
|
+
ls: Number
|
|
729
|
+
- Label size.
|
|
730
|
+
- Default: 10
|
|
713
731
|
|
|
714
732
|
Returns
|
|
715
733
|
-------
|
|
@@ -722,11 +740,11 @@ class Figure2D:
|
|
|
722
740
|
signal_subplot = subplots[-1]
|
|
723
741
|
|
|
724
742
|
if title is not None:
|
|
725
|
-
ref_subplot.set_title(title, pad=10, size=
|
|
743
|
+
ref_subplot.set_title(title, pad=10, size=ts)
|
|
726
744
|
if ylabel is not None:
|
|
727
|
-
signal_subplot.set_ylabel(ylabel, size=
|
|
745
|
+
signal_subplot.set_ylabel(ylabel, size=ls)
|
|
728
746
|
if xlabel is not None:
|
|
729
|
-
signal_subplot.set_xlabel(xlabel, size=
|
|
747
|
+
signal_subplot.set_xlabel(xlabel, size=ls)
|
|
730
748
|
|
|
731
749
|
def save(self, path="./figure.png"):
|
|
732
750
|
"""
|
|
@@ -889,4 +907,390 @@ def plot_dist(*args, ann=None, xlim=None, ylim=None, ylabel=None, xlabel=None, t
|
|
|
889
907
|
|
|
890
908
|
fig.subplots_adjust(hspace=0.01, wspace=0.05)
|
|
891
909
|
plt.close()
|
|
892
|
-
return fig
|
|
910
|
+
return fig
|
|
911
|
+
|
|
912
|
+
|
|
913
|
+
class Fig:
|
|
914
|
+
"""
|
|
915
|
+
|
|
916
|
+
"""
|
|
917
|
+
|
|
918
|
+
def __init__(self, arrangement="asm", title="Untitled", xlabel="Time (sec)", xlim=None):
|
|
919
|
+
|
|
920
|
+
self._xlim = xlim
|
|
921
|
+
self._curr_row_idx = 1 # Starting from 1 because row 0 is reserved for reference subplot
|
|
922
|
+
self._curr_color_idx = 0 # So that we have different color across all the subplots to avoid legend confusion
|
|
923
|
+
|
|
924
|
+
# Subplot setup
|
|
925
|
+
self._fig, self._axs = self._generate_subplots(arrangement, title, xlabel) # This will fill in the all the above variables
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
def _get_curr_row(self):
|
|
929
|
+
"""
|
|
930
|
+
Get the active row where you can add
|
|
931
|
+
either annotations or events.
|
|
932
|
+
"""
|
|
933
|
+
curr_row = self._axs[self._curr_row_idx]
|
|
934
|
+
self._curr_row_idx += 1
|
|
935
|
+
|
|
936
|
+
return curr_row
|
|
937
|
+
|
|
938
|
+
def _get_new_color(self):
|
|
939
|
+
"""
|
|
940
|
+
Get a new color for different lines.
|
|
941
|
+
"""
|
|
942
|
+
colors = plt.rcParams['axes.prop_cycle'].by_key()['color']
|
|
943
|
+
self._curr_color_idx += 1
|
|
944
|
+
|
|
945
|
+
return colors[self._curr_color_idx]
|
|
946
|
+
|
|
947
|
+
def _calculate_extent(self, x, y):
|
|
948
|
+
# Handle spacing safely
|
|
949
|
+
if len(x) > 1:
|
|
950
|
+
dx = x[1] - x[0]
|
|
951
|
+
else:
|
|
952
|
+
dx = 1 # Default spacing for single value
|
|
953
|
+
if len(y) > 1:
|
|
954
|
+
dy = y[1] - y[0]
|
|
955
|
+
else:
|
|
956
|
+
dy = 1 # Default spacing for single value
|
|
957
|
+
|
|
958
|
+
return [x[0] - dx / 2, x[-1] + dx / 2, y[0] - dy / 2, y[-1] + dy / 2]
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
def _generate_subplots(self, arrangement, title, xlabel):
|
|
962
|
+
"""
|
|
963
|
+
Generate subplots based on the configuration.
|
|
964
|
+
"""
|
|
965
|
+
|
|
966
|
+
xlim = self._xlim
|
|
967
|
+
|
|
968
|
+
n_aux_sp = arrangement.count("a")
|
|
969
|
+
n_signal_sp = arrangement.count("s")
|
|
970
|
+
n_matrix_sp = arrangement.count("m")
|
|
971
|
+
n_sp = 1 + n_aux_sp + n_signal_sp + n_matrix_sp # +1 is for the first reference subplot
|
|
972
|
+
|
|
973
|
+
# Decide heights of different subplots type
|
|
974
|
+
height = {}
|
|
975
|
+
height["r"] = 0.0 # Reference height
|
|
976
|
+
height["a"] = 0.4 # Aux height
|
|
977
|
+
height["s"] = 2.0 # Signal height
|
|
978
|
+
height["m"] = 4.0 # Matrix height
|
|
979
|
+
cbar_width = 0.01
|
|
980
|
+
|
|
981
|
+
arrangement = "r" + arrangement # "r" is to include the reference
|
|
982
|
+
|
|
983
|
+
# Calculate height ratios list based on the arrangement
|
|
984
|
+
for char in arrangement:
|
|
985
|
+
height_ratios = [height[char] for char in arrangement]
|
|
986
|
+
|
|
987
|
+
# Calculate total fig height
|
|
988
|
+
fig_height = height["r"] + (n_aux_sp * height["a"]) + (n_signal_sp * height["s"]) + (n_matrix_sp * height["m"])
|
|
989
|
+
|
|
990
|
+
# Create figure and axs
|
|
991
|
+
fig, axs = plt.subplots(n_sp, 2, figsize=(16, fig_height), height_ratios=height_ratios, width_ratios=[1, cbar_width])
|
|
992
|
+
|
|
993
|
+
for i, char in enumerate(arrangement): # For each of the subplots, we modify the layout accordingly
|
|
994
|
+
if char == "r":
|
|
995
|
+
axs[i, 0].axis("off")
|
|
996
|
+
axs[i, 1].axis("off")
|
|
997
|
+
elif char == "a": # Remove ticks and labels from all the aux subplots
|
|
998
|
+
axs[i, 0].tick_params(left=False, bottom=False, labelleft=False, labelbottom=False)
|
|
999
|
+
axs[i, 0].grid(True, linestyle=':', linewidth=0.7, color='gray', alpha=0.7)
|
|
1000
|
+
axs[i, 1].axis("off")
|
|
1001
|
+
elif char == "s":
|
|
1002
|
+
axs[i, 0].tick_params(bottom=False, labelbottom=False)
|
|
1003
|
+
axs[i, 0].grid(True, linestyle=':', linewidth=0.7, color='gray', alpha=0.7)
|
|
1004
|
+
axs[i, 1].axis("off")
|
|
1005
|
+
elif char == "m":
|
|
1006
|
+
axs[i, 0].grid(True, linestyle=':', linewidth=0.7, color='gray', alpha=0.7)
|
|
1007
|
+
axs[i, 0].tick_params(bottom=False, labelbottom=False)
|
|
1008
|
+
|
|
1009
|
+
axs[i, 0].sharex(axs[0, 0])
|
|
1010
|
+
|
|
1011
|
+
axs[-1, 0].tick_params(bottom=True, labelbottom=True)
|
|
1012
|
+
|
|
1013
|
+
# xlim should be applied on reference subplot, rest all subplots will automatically adjust
|
|
1014
|
+
if xlim is not None:
|
|
1015
|
+
axs[0, 0].set_xlim(xlim)
|
|
1016
|
+
|
|
1017
|
+
# Set title and label
|
|
1018
|
+
if title is not None:
|
|
1019
|
+
axs[0, 0].set_title(title)
|
|
1020
|
+
if xlabel is not None:
|
|
1021
|
+
axs[-1, 0].set_xlabel(xlabel)
|
|
1022
|
+
|
|
1023
|
+
fig.subplots_adjust(hspace=0.2, wspace=0.05)
|
|
1024
|
+
|
|
1025
|
+
return fig, axs
|
|
1026
|
+
|
|
1027
|
+
def add_signal(self, y, x=None, c=None, ls=None, lw=None, m=None, ms=3, label=None, ylabel=None, ylim=None, ax=None):
|
|
1028
|
+
"""
|
|
1029
|
+
Add signal to the figure.
|
|
1030
|
+
|
|
1031
|
+
Parameters
|
|
1032
|
+
----------
|
|
1033
|
+
y: np.ndarray
|
|
1034
|
+
- Signal y values.
|
|
1035
|
+
x: np.ndarray | None
|
|
1036
|
+
- Signal x values.
|
|
1037
|
+
- Default: None (indices will be used)
|
|
1038
|
+
c: str
|
|
1039
|
+
- Color of the line.
|
|
1040
|
+
- Default: None
|
|
1041
|
+
ls: str
|
|
1042
|
+
- Linestyle
|
|
1043
|
+
- Default: None
|
|
1044
|
+
lw: Number
|
|
1045
|
+
- Linewidth
|
|
1046
|
+
- Default: None
|
|
1047
|
+
m: str
|
|
1048
|
+
- Marker
|
|
1049
|
+
- Default: None
|
|
1050
|
+
ms: number
|
|
1051
|
+
- Markersize
|
|
1052
|
+
- Default: 3
|
|
1053
|
+
label: str
|
|
1054
|
+
- Label for the plot.
|
|
1055
|
+
- Legend will use this.
|
|
1056
|
+
- Default: None
|
|
1057
|
+
ylabel: str
|
|
1058
|
+
- y-label for the plot.
|
|
1059
|
+
- Default: None
|
|
1060
|
+
ylim: tuple
|
|
1061
|
+
- y-lim for the plot.
|
|
1062
|
+
- Default: None
|
|
1063
|
+
ax: int
|
|
1064
|
+
- Which specific axis to plot (1, 2, 3, ...)
|
|
1065
|
+
- None
|
|
1066
|
+
|
|
1067
|
+
Returns
|
|
1068
|
+
-------
|
|
1069
|
+
None
|
|
1070
|
+
"""
|
|
1071
|
+
|
|
1072
|
+
curr_row = self._get_curr_row() if ax is None else self._axs[ax]
|
|
1073
|
+
|
|
1074
|
+
if x is None: x = np.arange(y.size)
|
|
1075
|
+
|
|
1076
|
+
if c is None: c = self._get_new_color()
|
|
1077
|
+
|
|
1078
|
+
curr_row[0].plot(x, y, color=c, linestyle=ls, linewidth=lw, marker=m, markersize=ms, label=label)
|
|
1079
|
+
|
|
1080
|
+
if ylabel is not None: curr_row[0].set_ylabel(ylabel)
|
|
1081
|
+
|
|
1082
|
+
if ylim is not None: curr_row[0].set_ylim(ylim)
|
|
1083
|
+
|
|
1084
|
+
def add_matrix(self, M, y=None, x=None, c="gray_r", o="lower", label=None, ylabel=None, ylim=None, cbar=True, ax=None):
|
|
1085
|
+
"""
|
|
1086
|
+
Add matrix to the figure.
|
|
1087
|
+
|
|
1088
|
+
Parameters
|
|
1089
|
+
----------
|
|
1090
|
+
M: np.ndarray
|
|
1091
|
+
- Matrix (2D) array
|
|
1092
|
+
y: np.ndarray | None
|
|
1093
|
+
- y axis values.
|
|
1094
|
+
x: np.ndarray | None (indices will be used)
|
|
1095
|
+
- x axis values.
|
|
1096
|
+
- Default: None (indices will be used)
|
|
1097
|
+
c: str
|
|
1098
|
+
- cmap for the matrix.
|
|
1099
|
+
- Default: None
|
|
1100
|
+
o: str
|
|
1101
|
+
- origin
|
|
1102
|
+
- Default: "lower"
|
|
1103
|
+
label: str
|
|
1104
|
+
- Label for the plot.
|
|
1105
|
+
- Legend will use this.
|
|
1106
|
+
- Default: "Signal"
|
|
1107
|
+
ylabel: str
|
|
1108
|
+
- y-label for the plot.
|
|
1109
|
+
- Default: None
|
|
1110
|
+
ylim: tuple
|
|
1111
|
+
- y-lim for the plot.
|
|
1112
|
+
- Default: None
|
|
1113
|
+
cbar: bool
|
|
1114
|
+
- Show colorbar
|
|
1115
|
+
- Default: True
|
|
1116
|
+
ax: int
|
|
1117
|
+
- Which specific axis to plot (1, 2, 3, ...)
|
|
1118
|
+
- None
|
|
1119
|
+
|
|
1120
|
+
Returns
|
|
1121
|
+
-------
|
|
1122
|
+
None
|
|
1123
|
+
"""
|
|
1124
|
+
if x is None: x = np.arange(M.shape[1])
|
|
1125
|
+
if y is None: y = np.arange(M.shape[0])
|
|
1126
|
+
|
|
1127
|
+
curr_row = self._get_curr_row() if ax is None else self._axs[ax]
|
|
1128
|
+
|
|
1129
|
+
extent = self._calculate_extent(x, y)
|
|
1130
|
+
im = curr_row[0].imshow(M, aspect="auto", origin=o, cmap=c, extent=extent)
|
|
1131
|
+
|
|
1132
|
+
if ylabel is not None: curr_row[0].set_ylabel(ylabel)
|
|
1133
|
+
|
|
1134
|
+
if ylim is not None: curr_row[0].set_ylim(ylim)
|
|
1135
|
+
|
|
1136
|
+
if cbar is True:
|
|
1137
|
+
cbar = plt.colorbar(im, cax=curr_row[1])
|
|
1138
|
+
if label is not None:
|
|
1139
|
+
cbar.set_label(label, labelpad=5)
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
def add_events(self, events, c=None, ls=None, lw=None, label=None, ax=None):
|
|
1143
|
+
"""
|
|
1144
|
+
Add events to the figure.
|
|
1145
|
+
|
|
1146
|
+
Parameters
|
|
1147
|
+
----------
|
|
1148
|
+
events: np.ndarray
|
|
1149
|
+
- All the event marker values.
|
|
1150
|
+
c: str
|
|
1151
|
+
- Color of the event marker.
|
|
1152
|
+
- Default: "k"
|
|
1153
|
+
ls: str
|
|
1154
|
+
- Line style.
|
|
1155
|
+
- Default: "-"
|
|
1156
|
+
lw: float
|
|
1157
|
+
- Linewidth.
|
|
1158
|
+
- Default: 1.5
|
|
1159
|
+
label: str
|
|
1160
|
+
- Label for the event type.
|
|
1161
|
+
- This will appear in the legend.
|
|
1162
|
+
- Default: "Event label"
|
|
1163
|
+
ax: int
|
|
1164
|
+
- Which specific axis to plot (1, 2, 3, ...)
|
|
1165
|
+
- None
|
|
1166
|
+
|
|
1167
|
+
Returns
|
|
1168
|
+
-------
|
|
1169
|
+
None
|
|
1170
|
+
"""
|
|
1171
|
+
|
|
1172
|
+
curr_row = self._get_curr_row() if ax is None else self._axs[ax]
|
|
1173
|
+
|
|
1174
|
+
if c is None: c = self._get_new_color()
|
|
1175
|
+
|
|
1176
|
+
xlim = self._xlim
|
|
1177
|
+
|
|
1178
|
+
for i, event in enumerate(events):
|
|
1179
|
+
if xlim is not None:
|
|
1180
|
+
if xlim[0] <= event <= xlim[1]:
|
|
1181
|
+
if i == 0: # Label should be set only once for all the events
|
|
1182
|
+
curr_row[0].axvline(x=event, color=c, linestyle=ls, linewidth=lw, label=label)
|
|
1183
|
+
else:
|
|
1184
|
+
curr_row[0].axvline(x=event, color=c, linestyle=ls, linewidth=lw)
|
|
1185
|
+
else:
|
|
1186
|
+
if i == 0: # Label should be set only once for all the events
|
|
1187
|
+
curr_row[0].axvline(x=event, color=c, linestyle=ls, linewidth=lw, label=label)
|
|
1188
|
+
else:
|
|
1189
|
+
curr_row[0].axvline(x=event, color=c, linestyle=ls, linewidth=lw)
|
|
1190
|
+
|
|
1191
|
+
def add_annotation(self, ann, ax=None):
|
|
1192
|
+
"""
|
|
1193
|
+
Add annotation to the figure.
|
|
1194
|
+
|
|
1195
|
+
Parameters
|
|
1196
|
+
----------
|
|
1197
|
+
ann : list[tuple[Number, Number, str]] | None
|
|
1198
|
+
- A list of annotation spans. Each tuple should be (start, end, label).
|
|
1199
|
+
- Default: None (no annotations).
|
|
1200
|
+
ax: int
|
|
1201
|
+
- Which specific axis to plot (1, 2, 3, ...)
|
|
1202
|
+
- None
|
|
1203
|
+
Returns
|
|
1204
|
+
-------
|
|
1205
|
+
None
|
|
1206
|
+
"""
|
|
1207
|
+
curr_row = self._get_curr_row() if ax is None else self._axs[ax]
|
|
1208
|
+
|
|
1209
|
+
xlim = self._xlim
|
|
1210
|
+
|
|
1211
|
+
for i, (start, end, tag) in enumerate(ann):
|
|
1212
|
+
# We make sure that we only plot annotation that are within the x range of the current view
|
|
1213
|
+
if xlim is not None:
|
|
1214
|
+
if start >= xlim[1] or end <= xlim[0]:
|
|
1215
|
+
continue
|
|
1216
|
+
|
|
1217
|
+
# Clip boundaries to xlim
|
|
1218
|
+
start = max(start, xlim[0])
|
|
1219
|
+
end = min(end, xlim[1])
|
|
1220
|
+
|
|
1221
|
+
box_colors = ["gray", "lightgray"] # Alternates color between two
|
|
1222
|
+
box_color = box_colors[i % 2]
|
|
1223
|
+
|
|
1224
|
+
width = end - start
|
|
1225
|
+
rect = Rectangle((start, 0), width, 1, facecolor=box_color, edgecolor="black", alpha=0.7)
|
|
1226
|
+
curr_row[0].add_patch(rect)
|
|
1227
|
+
|
|
1228
|
+
text_obj = curr_row[0].text(
|
|
1229
|
+
(start + end) / 2, 0.5, tag,
|
|
1230
|
+
ha='center', va='center',
|
|
1231
|
+
fontsize=10, color="black", fontweight='bold', zorder=10, clip_on=True
|
|
1232
|
+
)
|
|
1233
|
+
|
|
1234
|
+
text_obj.set_clip_path(rect)
|
|
1235
|
+
else:
|
|
1236
|
+
box_colors = ["gray", "lightgray"] # Alternates color between two
|
|
1237
|
+
box_color = box_colors[i % 2]
|
|
1238
|
+
|
|
1239
|
+
width = end - start
|
|
1240
|
+
rect = Rectangle((start, 0), width, 1, facecolor=box_color, edgecolor="black", alpha=0.7)
|
|
1241
|
+
curr_row[0].add_patch(rect)
|
|
1242
|
+
|
|
1243
|
+
text_obj = curr_row[0].text(
|
|
1244
|
+
(start + end) / 2, 0.5, tag,
|
|
1245
|
+
ha='center', va='center',
|
|
1246
|
+
fontsize=10, color="black", fontweight='bold', zorder=10, clip_on=True
|
|
1247
|
+
)
|
|
1248
|
+
|
|
1249
|
+
text_obj.set_clip_path(rect)
|
|
1250
|
+
|
|
1251
|
+
def add_legend(self, ypos=1.0):
|
|
1252
|
+
"""
|
|
1253
|
+
Add legend to the figure.
|
|
1254
|
+
|
|
1255
|
+
Parameters
|
|
1256
|
+
----------
|
|
1257
|
+
ypos: float
|
|
1258
|
+
- y position from the top.
|
|
1259
|
+
- > 1 to push it higher, < 1 to push it lower
|
|
1260
|
+
- Default: 1.3
|
|
1261
|
+
|
|
1262
|
+
Returns
|
|
1263
|
+
-------
|
|
1264
|
+
None
|
|
1265
|
+
"""
|
|
1266
|
+
axs = self._axs
|
|
1267
|
+
fig = self._fig
|
|
1268
|
+
|
|
1269
|
+
all_handles, all_labels = [], []
|
|
1270
|
+
|
|
1271
|
+
for ax in axs:
|
|
1272
|
+
handles, labels = ax[0].get_legend_handles_labels()
|
|
1273
|
+
all_handles.extend(handles)
|
|
1274
|
+
all_labels.extend(labels)
|
|
1275
|
+
|
|
1276
|
+
# remove duplicates if needed
|
|
1277
|
+
fig.legend(all_handles, all_labels, loc='upper right', bbox_to_anchor=(0.95, ypos), ncol=2, frameon=True, bbox_transform=fig.transFigure)
|
|
1278
|
+
|
|
1279
|
+
def save(self, path="./figure.png"):
|
|
1280
|
+
"""
|
|
1281
|
+
Save the figure.
|
|
1282
|
+
|
|
1283
|
+
Parameters
|
|
1284
|
+
----------
|
|
1285
|
+
path: str
|
|
1286
|
+
- Path to the output file.
|
|
1287
|
+
|
|
1288
|
+
Returns
|
|
1289
|
+
-------
|
|
1290
|
+
None
|
|
1291
|
+
"""
|
|
1292
|
+
fig = self._fig
|
|
1293
|
+
fig.savefig(path, bbox_inches="tight")
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modusa-0.3.45 → modusa-0.3.47}/src/modusa/models/__pycache__/signal1D.cpython-312.pyc.4443461152
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|