Source code for semi_cr.core.trial.shapes

from abc import ABC, abstractmethod

import numpy as np


[docs] class PulseShape(ABC): """ Abstract base class for pulse shapes. """
[docs] @abstractmethod def get_shape(self) -> np.typing.NDArray[np.floating]: """ Get the value of the pulse shape. :return: The value of the pulse shape at the given time. """ pass
[docs] def integrate(self): return self.get_shape().sum()
[docs] class YizhiPulse(PulseShape): """ A pulse shape that linearly ramps up to a specified amplitude, then "asymptotically" goes on from that amplitude's complement to the negative of that amplitude, then back to zero. Sort of like this: """ def __init__(self, amplitude: float, steps: int): if amplitude > 1.0 or amplitude < 0: raise ValueError("Amplitude must be between 0 and 1.") if steps <= 0: raise ValueError("Steps must be a positive integer.") self.amplitude = amplitude self.steps = steps
[docs] def get_shape(self) -> np.typing.NDArray[np.floating]: positive_steps = self.steps // 2 negative_steps = self.steps - positive_steps amplitude_sequences_up = np.linspace(0, self.amplitude, positive_steps) amplitude_sequences_down = np.linspace(-self.amplitude, 0, negative_steps) amplitude_shape = np.concatenate((amplitude_sequences_up, amplitude_sequences_down)) # If the number of steps is odd, we need to subtract the residual amplitude in order to get a zero integral. amplitude_shape -= amplitude_shape.mean() return amplitude_shape