modusa 0.3.46__py3-none-any.whl → 0.3.47__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 +1 -1
- modusa/tools/__init__.py +1 -0
- modusa/tools/plotter.py +397 -4
- {modusa-0.3.46.dist-info → modusa-0.3.47.dist-info}/METADATA +1 -1
- {modusa-0.3.46.dist-info → modusa-0.3.47.dist-info}/RECORD +8 -8
- {modusa-0.3.46.dist-info → modusa-0.3.47.dist-info}/WHEEL +0 -0
- {modusa-0.3.46.dist-info → modusa-0.3.47.dist-info}/entry_points.txt +0 -0
- {modusa-0.3.46.dist-info → modusa-0.3.47.dist-info}/licenses/LICENSE.md +0 -0
modusa/__init__.py
CHANGED
|
@@ -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
|
modusa/tools/__init__.py
CHANGED
modusa/tools/plotter.py
CHANGED
|
@@ -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)
|
|
@@ -388,9 +392,11 @@ class Figure2D:
|
|
|
388
392
|
- Default: None
|
|
389
393
|
"""
|
|
390
394
|
|
|
391
|
-
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):
|
|
392
396
|
self._n_aux_subplots: int = n_aux_subplots
|
|
393
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
|
|
394
400
|
self._xlim = xlim # Many add functions depend on this, so we fix it while instantiating the class
|
|
395
401
|
self._ylim = ylim
|
|
396
402
|
self._subplots, self._fig = self._generate_subplots() # Will contain all the subplots (list, fig)
|
|
@@ -471,6 +477,7 @@ class Figure2D:
|
|
|
471
477
|
ref_subplot = fig.add_subplot(gs[0, 0])
|
|
472
478
|
ref_subplot.axis("off")
|
|
473
479
|
subplots_list.append(ref_subplot)
|
|
480
|
+
|
|
474
481
|
|
|
475
482
|
for i in range(1, n_subplots):
|
|
476
483
|
subplots_list.append(fig.add_subplot(gs[i, 0], sharex=ref_subplot))
|
|
@@ -900,4 +907,390 @@ def plot_dist(*args, ann=None, xlim=None, ylim=None, ylabel=None, xlabel=None, t
|
|
|
900
907
|
|
|
901
908
|
fig.subplots_adjust(hspace=0.01, wspace=0.05)
|
|
902
909
|
plt.close()
|
|
903
|
-
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
|
+
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
modusa-0.3.
|
|
2
|
-
modusa-0.3.
|
|
3
|
-
modusa-0.3.
|
|
4
|
-
modusa-0.3.
|
|
1
|
+
modusa-0.3.47.dist-info/METADATA,sha256=Bqakd2bPlWP57HVv-VH91Wf5Jr0ZpkQs5-hFHA2A1tg,1403
|
|
2
|
+
modusa-0.3.47.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
|
|
3
|
+
modusa-0.3.47.dist-info/entry_points.txt,sha256=fmKpleVXj6CdaBVL14WoEy6xx7JQCs85jvzwTi3lePM,73
|
|
4
|
+
modusa-0.3.47.dist-info/licenses/LICENSE.md,sha256=JTaXAjx5awk76VArKCx5dUW8vmLEWsL_ZlR7-umaHbA,1078
|
|
5
5
|
modusa/.DS_Store,sha256=_gm6qJREwfMi8dE7n5S89_RG46u5t3xHyD-smNhtNoM,6148
|
|
6
|
-
modusa/__init__.py,sha256=
|
|
6
|
+
modusa/__init__.py,sha256=_Fk3GxsI0GT-uhsZaHgs6p5YcIkqPGb3s78_dzFy1lE,291
|
|
7
7
|
modusa/config.py,sha256=bTqK4t00FZqERVITrxW_q284aDDJAa9aMSfFknfR-oU,280
|
|
8
8
|
modusa/decorators.py,sha256=8zeNX_wE37O6Vp0ysR4-WCZaEL8mq8dyCF_I5DHOzks,5905
|
|
9
9
|
modusa/devtools/generate_docs_source.py,sha256=UDflHsk-Yh9-3YJTVBzKL32y8hcxiRgAlFEBTMiDqwM,3301
|
|
@@ -41,7 +41,7 @@ modusa/models/t_ax.py,sha256=ZUhvZPUW1TkdZYuUd6Ucm-vsv0JqtZ9yEe3ab67Ma6w,8022
|
|
|
41
41
|
modusa/models/tds.py,sha256=FAGfibjyyE_lkEuQp-vSCuqQnopOjmy_IXqUjRlg9kc,11677
|
|
42
42
|
modusa/plugins/__init__.py,sha256=r1Bf5mnrVKRIwxboutY1iGzDy4EPQhqpk1kSW7iJj_Q,54
|
|
43
43
|
modusa/plugins/base.py,sha256=Bh_1Bja7fOymFsCgwhXDbV6ys3D8muNrPwrfDrG_G_A,2382
|
|
44
|
-
modusa/tools/__init__.py,sha256=
|
|
44
|
+
modusa/tools/__init__.py,sha256=s3Yfr4FbfZCXwfyy4uPHDfZ4lqf8XZqgH5KlKUVwQpM,373
|
|
45
45
|
modusa/tools/_plotter_old.py,sha256=KGow7mihA2H1WNq7s5bpivhCgGo2qVIeDaO6iabpsrg,19294
|
|
46
46
|
modusa/tools/ann_loader.py,sha256=RePlwD4qG6gGrD4mOJ3RDR9q_gUscCY90_R9lgFU9lM,780
|
|
47
47
|
modusa/tools/audio_converter.py,sha256=415qBoPm2sBIuBSI7m1XBKm0AbmVmPydIPPr-uO8D3c,1778
|
|
@@ -50,7 +50,7 @@ modusa/tools/audio_player.py,sha256=GP04TWW4jBwQBjANkfR_cJtEy7cIhvbu8RTwnf9hD6E,
|
|
|
50
50
|
modusa/tools/audio_recorder.py,sha256=d2fVt0Sd2tlBdb2WlUs60K4N23zuxM3KUpQqX0ifPi8,2769
|
|
51
51
|
modusa/tools/base.py,sha256=C0ESJ0mIfjjRlAkRbSetNtMoOfS6IrHBjexRp3l_Mh4,1293
|
|
52
52
|
modusa/tools/math_ops.py,sha256=ZZ7U4DgqT7cOeE7_Lzi_Qq-48WYfwR9_osbZwTmE9eg,8690
|
|
53
|
-
modusa/tools/plotter.py,sha256=
|
|
53
|
+
modusa/tools/plotter.py,sha256=Yt85kVt5kiWmmExQmupI1RpqTI6NiK0_vsDI22J9u9I,34040
|
|
54
54
|
modusa/tools/youtube_downloader.py,sha256=hB_X8-7nOHXOlxg6vv3wyhBLoAsWyomrULP6_uCQL7s,1698
|
|
55
55
|
modusa/utils/.DS_Store,sha256=nLXMwF7QJNuglLI_Gk74F7vl5Dyus2Wd74Mgowijmdo,6148
|
|
56
56
|
modusa/utils/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
|
|
@@ -59,4 +59,4 @@ modusa/utils/excp.py,sha256=L9vhaGjKpv9viJYdmC9n5ndmk2GVbUBuFyZyhAQZmWY,906
|
|
|
59
59
|
modusa/utils/logger.py,sha256=K0rsnObeNKCxlNeSnVnJeRhgfmob6riB2uyU7h3dDmA,571
|
|
60
60
|
modusa/utils/np_func_cat.py,sha256=TyIFgRc6bARRMDnZxlVURO5Z0I-GWhxRONYyIv-Vwxs,1007
|
|
61
61
|
modusa/utils/plot.py,sha256=s_vNdxvKfwxEngvJPgrF1PcmxZNnNaaXPViHWjyjJ-c,5335
|
|
62
|
-
modusa-0.3.
|
|
62
|
+
modusa-0.3.47.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|