Pulse Transitions Library
Github Repo: pulse_transitions
Over the past few months, I’ve found myself repeatedly needing step response analysis for control systems, TDR work, pulsed light sources, photoreceivers, and flash lidar applications. Matlab has a solid set of tools, but nothing equivalent existed in Python so here’s that library.
The control library has a step_info
function, but it’s built around transfer functions rather than real waveforms.

Second order transfer function analysis plot
matpulse: Pulse Transition Library Inspired
I haven’t gotten to the multiple transitions yet but the pulse analysis functions are done.
The library has a matpulse
module that tries to stay as close to the Matlab interface as python can. The same functionality with more reasonable naming schemes are available in the main namespace.
Function | Description | Implemented? | |
---|---|---|---|
midcross | Mid-reference level crossing for bilevel waveform | ☑️ | |
statelevels | State-level estimation for bilevel waveform with histogram method | ☑️ | |
falltime | Fall time of negative-going bilevel waveform transitions | ☑️ | |
overshoot | Overshoot metrics of bilevel waveform transitions | ☑️ | |
risetime | Rise time of positive-going bilevel waveform transitions | ☑️ | |
settlingtime | Settling time for bilevel waveform | ☑️ | |
slewrate | Slew rate of bilevel waveform | ☑️ | |
undershoot | Undershoot metrics of bilevel waveform transitions | ☑️ | |
dutycycle | Duty cycle of pulse waveform | ❌ | |
pulseperiod | Period of bilevel pulse | ❌ | |
pulsesep | Separation between bilevel waveform pulses | ❌ | |
pulsewidth | Bilevel waveform pulse width | ❌ |
Example Use
import numpy as np
from scipy.signal import lsim
from scipy.signal import lti
from pulse_transitions import detect_edges
from pulse_transitions import detect_signal_levels
from pulse_transitions import get_edge_metrics
def generate_step_response(t, damping=0.2, freq=10):
wn = freq * 2 * np.pi # Natural frequency
num = [wn**2]
den = [1, 2*damping*wn, wn**2]
system = lti(num, den)
u = np.where(t < 0, 0, 1)
t_shift = t - min(t)
t_out, y_out, _ = lsim(system, U=u, T=t_shift)
return t, y_out
# Generate data
t = np.linspace(-0.25, 1, 1000)
t_out, y = generate_step_response(t, freq=25/(max(t)))
threshold_fractions=(0.1, 0.9)
# Estimate levels (e.g. using histogram or endpoints)
levels = detect_signal_levels(x=t, y=y, method="histogram")
low, high = levels
# Detect edges
edge = detect_edges(t, y, levels=levels, thresholds=threshold_fractions)[0]
# Compute overshoot / undershoot
metrics = get_edge_metrics(x=t, y=y, thresholds=threshold_fractions, levels=levels)
There was some effort made to make this an easy library to use. Have a look and try it out!
If you try it out and have thoughts (missing features, better algorithms, or bugs), I’d love to hear them.