Source code for pymgipsim.InputGeneration.signal

from collections.abc import Iterable
import numpy as np
from dataclasses import dataclass, field


from .waves import create_square_wave


[docs] @dataclass class Events: """ Stores a series of (duration, magnitude, start time) triplets that uniquely define events which can either be measurement or input. Events from a scenario file are cast into Events dataclass and vice-versa. Note: For measurements, duration field is empty array as it is uninterpretable. Attributes: magnitude (Iterable) : Defines the magnitudes of the events. start_time (Iterable) : Defines the start times of the events in Unix timestamps [min]. duration (Iterable) : Defines the duration of the events [min]. """ magnitude: np.ndarray = field(default_factory=lambda: np.array([[]], dtype=float)) start_time: np.ndarray = field(default_factory=lambda: np.array([[]], dtype=float)) duration: np.ndarray = field(default_factory=lambda: np.array([[]], dtype=float)) def __post_init__(self): self.magnitude = np.asarray(self.magnitude).astype(float) self.duration = np.asarray(self.duration).astype(float) self.start_time = np.asarray(self.start_time).astype(float) if self.duration.size: assert not np.any(self.duration < 0) assert (self.magnitude.shape[0] == self.start_time.shape[0] == self.duration.shape[0] and self.magnitude.shape[1] == self.start_time.shape[1] == self.duration.shape[1]) else: assert (self.magnitude.shape[0] == self.start_time.shape[0] and self.magnitude.shape[1] == self.start_time.shape[1]) assert not np.any(self.start_time < 0) assert not np.any(self.magnitude < 0)
[docs] def as_dict(self): """ Function to make the translation between the JSON scenario file and class smooth. """ self.magnitude = self.magnitude.tolist() self.start_time = self.start_time.tolist() self.duration = self.duration.tolist() return self
[docs] class Signal(Events): """ Extends the Events class with sampled signal. Sampled square wave is generated based on the events information to use directly in solving the differential equations. Attributes: sampled_signal (np.ndarray) : 2D numpy array, 1st dim: subjects, 2nd dim: timestep in the simulation horizon. """ def __init__( self, time: np.ndarray = np.array([], dtype=float), magnitude: Iterable = np.array([[]], dtype=float), start_time: Iterable = np.array([[]], dtype=float), duration: Iterable = np.array([[]], dtype=float), sampling_time: float = 1, ): """ Initializes an instance of InputClass. Parameters: - time: np.ndarray Time array for the signal. - magnitude: tuple Tuple containing magnitude information for creating the signal. - start_time: tuple Tuple containing start time information for creating the signal. - duration: tuple Tuple containing duration information for creating the signal. - sampling_time: float Sampling time for the signal. """ super().__init__(magnitude, start_time, duration) self.time = time self.sampling_time = sampling_time self.magnitude = np.stack(self.magnitude, axis=0) self.start_time = np.stack(self.start_time, axis=0) self.duration = np.stack(self.duration, axis=0) # Initialize signal_openloop using the __create_signal method self.sampled_signal = Signal.__create_signal(time, self.start_time, self.duration, self.magnitude, sampling_time ) @staticmethod def __create_signal( time: np.ndarray, start_times: np.ndarray, durations: np.ndarray, amounts: np.ndarray, sampling_time: float, ) -> np.ndarray: """ Static method to create a signal based on provided input parameters. Parameters: - time: np.ndarray Time array for the signal. - start_times: np.ndarray Array of start times for each event. - durations: np.ndarray Array of durations for each event. - amounts: np.ndarray Array of amounts for each event. - sampling_time: float Sampling time for the signal. Returns: - np.ndarray 3D array representing the generated scenario signal. """ return create_square_wave(time, start_times, durations, amounts, sampling_time)