Source code for piel.visual.plot.signals.time.separate

from typing import Any, Tuple
from piel.types import MultiTimeSignalData, Unit
import numpy as np
from piel.visual.plot.position import create_axes_per_figure
from piel.visual.plot.core import save
import logging

logger = logging.getLogger(__name__)


[docs] def plot_multi_data_time_signal_different( multi_signal: MultiTimeSignalData, fig: Any = None, axs: Any = None, subplots_kwargs: dict = None, xlabel: str | Unit | list[Unit] = None, ylabel: str | Unit | list[Unit] | list = None, title: str | Unit | list = None, time_range_s: Tuple[float, float] = None, # Add time_range parameter labels: list[str] = None, **kwargs, ): """ Plots all rising edge signals on the same figure, but with a shared x-axis and multiple y-axes. Args: multi_signal (MultiTimeSignalData): List of rising edge signals. fig (Any): Figure object. axs (Any): Axes object. subplots_kwargs (dict): Keyword arguments to pass to create_axes_per_figure. xlabel (str | Unit | list[Unit]): Label for x-axis. ylabel (str | Unit | list[Unit] | list): Label for y-axis. title (str | Unit | list): Title for the plot. time_range_s (Tuple[float, float]): Tuple indicating the (start, end) time for the x-axis range. Returns: fig (Any), axs (Any): Figure and Axes objects. """ signal_amount = len(multi_signal) x_correction = 1 y_correction = np.repeat(1, signal_amount) if not multi_signal: raise ValueError("The multi_signal list is empty.") if xlabel is None: xlabel = r"Time $s$" elif isinstance(xlabel, str): pass elif isinstance(xlabel, Unit): x_correction = xlabel.base logger.warning( f"Data correction of 1/{x_correction} from unit definition {xlabel} will be applied on x-axis" ) xlabel = xlabel.label if ylabel is None: ylabel = np.repeat(r"Voltage $V$", signal_amount) elif isinstance(ylabel, str): pass elif isinstance(ylabel, list): pass elif isinstance(ylabel, Unit): y_correction = ylabel.base logger.warning( f"Data correction of 1/{y_correction} from unit definition {ylabel} will be applied on all y-axis." ) ylabel = ylabel.label elif isinstance(ylabel, list): # This should be a list of units i = 0 for unit_i in ylabel: if isinstance(unit_i, Unit): y_correction[i] = unit_i.base i += 1 if subplots_kwargs is None: subplots_kwargs = {} if (fig is None) or (axs is None): fig, axs = create_axes_per_figure( rows=len(multi_signal), columns=1, **subplots_kwargs ) if title is None: pass elif isinstance(title, str): fig.suptitle(title) if time_range_s is None: # Assumes at least one signal time_range_s = [min(multi_signal[0].time_s), max(multi_signal[0].time_s)] # TODO improve this time_range_s[0] = time_range_s[0] / x_correction time_range_s[1] = time_range_s[1] / x_correction i = 0 for signal in multi_signal: if (len(signal.time_s) == 0) or (signal.time_s is None): raise ValueError(f"Signal '{signal.data_name}' has an empty time_s array.") if labels is None: label_i = signal.data_name else: label_i = labels[i] time = np.array(signal.time_s) / x_correction data = np.array(signal.data) / y_correction[i] # Apply time range filtering if time_range_s: mask = (time >= time_range_s[0]) & (time <= time_range_s[1]) time = time[mask] data = data[mask] / y_correction[i] axs[i].plot(time, data, label=label_i) axs[i].set_ylabel(ylabel[i]) if isinstance(title, list): axs[i].set_title(title[i], loc="left") i += 1 fig.supxlabel(xlabel) save(fig, **kwargs) return fig, axs