Source code for ossdbs.stimulation_signals.triangle_signal

# Copyright 2023, 2024 Julius Zimmermann
# SPDX-License-Identifier: GPL-3.0-or-later

import numpy as np

from .signal import TimeDomainSignal


[docs]class TriangleSignal(TimeDomainSignal): """Represents a triangular signal. Parameters ---------- frequency : float Frequency [Hz] of the signal. pulse_width : float Relative pulse width of one period. counter_pulse_width: float Relative width of counter pulse of one period. inter_pulse_width: float Relative width between pulse and counter pulse of one period. """
[docs] def get_time_domain_signal(self, dt: float, timesteps: int) -> np.ndarray: """Build time domain signal. Parameters ---------- dt : float Time difference of the signal. timesteps : int Number of steps in the signal. """ if np.isclose(dt, 0.0): raise ValueError("Choose a timestep dt larger than zero.") signal = np.zeros(timesteps) period = 1.0 / self.frequency # use offset for visualization offset = round(self._pulse_width / dt) while offset < timesteps: self._generate_time_domain_signal( signal, offset, self._pulse_width, self.amplitude, dt ) if not np.isclose(self._counter_pulse_width, 0.0): counter_pulse_start_index = offset + round( self._pulse_width / dt + self._inter_pulse_width / dt ) self._generate_time_domain_signal( signal, counter_pulse_start_index, self._counter_pulse_width, -self._counter_amplitude, dt, ) offset += round(period / dt) return signal
def _generate_time_domain_signal( self, signal: np.array, start_index: int, width: float, amplitude: float, dt: float, ): pulse_duration = round(width / dt) for i in range(pulse_duration): if start_index + i < len(signal): if i <= pulse_duration / 2: signal[start_index + i] = amplitude * (i / pulse_duration) * 2 else: signal[start_index + i] = amplitude * (1 - (i / pulse_duration)) * 2