Pulse Transitions Library

A Python library for analyzing step and pulse responses, inspired by Matlab’s pulse and transition metrics.

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.

FunctionDescriptionImplemented?
midcrossMid-reference level crossing for bilevel waveform☑️
statelevelsState-level estimation for bilevel waveform with histogram method☑️
falltimeFall time of negative-going bilevel waveform transitions☑️
overshootOvershoot metrics of bilevel waveform transitions☑️
risetimeRise time of positive-going bilevel waveform transitions☑️
settlingtimeSettling time for bilevel waveform☑️
slewrateSlew rate of bilevel waveform☑️
undershootUndershoot metrics of bilevel waveform transitions☑️
dutycycleDuty cycle of pulse waveform
pulseperiodPeriod of bilevel pulse
pulsesepSeparation between bilevel waveform pulses
pulsewidthBilevel 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.