modusa 0.3.45__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 +417 -13
- {modusa-0.3.45.dist-info → modusa-0.3.47.dist-info}/METADATA +1 -1
- {modusa-0.3.45.dist-info → modusa-0.3.47.dist-info}/RECORD +8 -8
- {modusa-0.3.45.dist-info → modusa-0.3.47.dist-info}/WHEEL +0 -0
- {modusa-0.3.45.dist-info → modusa-0.3.47.dist-info}/entry_points.txt +0 -0
- {modusa-0.3.45.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)
         | 
| @@ -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 | 
            +
            	
         | 
| @@ -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
         |