Spectrum

class pathsim.blocks.spectrum.Spectrum(freq=[], t_wait=0.0, alpha=0.0, labels=[])[source]

Bases: Block

Block for fourier spectrum analysis (basically a spectrum analyzer), computes continuous time running fourier transform (RFT) of the incoming signal.

A time threshold can be set by ‘t_wait’ to start recording data only after the simulation time is larger then the specified waiting time, i.e. ‘t - t_wait > dt’. This is useful for recording the steady state after all the transients have settled.

An exponential forgetting factor ‘alpha’ can be specified for realtime spectral analysis. It biases the spectral components exponentially to the most recent signal values by applying a single sided exponential window like this:

\[\int_0^t u(\tau) \exp(\alpha (t-\tau)) \exp(-j \omega \tau)\ d \tau\]

It is also known as the ‘exponentially forgetting transform’ (EFT) and a form of short time fourier transform (STFT). It is implemented as a 1st order statespace model

\[\dot{x} = - \alpha x + \exp(-j \omega t) u\]

where ‘u’ is the input signal and ‘x’ is the state variable that represents the complex fourier coefficient to the frequency ‘omega’. The ODE is integrated using the numerical integration engine of the block.

Example

This is how to initialize it:

import numpy as np

#linear frequencies (0Hz, DC -> 1kHz)
sp1 = Spectrum(
    freq=np.linspace(0, 1e3, 100),
    labels=['x1', 'x2'] #labels for two inputs
    )

#log frequencies (1Hz -> 1kHz)
sp2 = Spectrum(
    freq=np.logspace(0, 3, 100)
    )

#log frequencies including DC (0Hz, DC + 1Hz -> 1kHz)
sp3 = Spectrum(
    freq=np.hstack([0.0, np.logspace(0, 3, 100)])
    )

#arbitrary frequencies
sp4 = Spectrum(
    freq=np.array([0, 0.5, 20, 1e3])
    )

Note

This block is relatively slow! But it is valuable for long running simulations with few evaluation frequencies, where just FFT’ing the time series data wouldnt be efficient OR if only the evaluation at weirdly spaced frequencies is required. Otherwise its more efficient to just do an FFT on the time series recording after the simulation has finished.

Parameters:
  • freq (array[float]) – list of evaluation frequencies for RFT, can be arbitrarily spaced

  • t_wait (float) – wait time before starting RFT

  • alpha (float) – exponential forgetting factor for realtime spectrum

  • labels (list[str]) – labels for the inputs

set_solver(Solver, parent, **solver_kwargs)[source]

set the internal numerical integrator for the RFT

Parameters:
  • Solver (Solver) – numerical integration solver class

  • solver_kwargs (dict) – parameters for solver initialization

reset()[source]

Reset the blocks inputs and outputs and also its internal solver, if the block has a solver instance.

read()[source]

Read the recorded spectrum

Example

This is how to get the recorded spectrum:

import numpy as np

#linear frequencies (0Hz, DC -> 1kHz)
spc = Spectrum(
    freq=np.linspace(0, 1e3, 100),
    labels=['x1', 'x2'] #labels for two inputs
    )

#... run the simulation ...

#read the complex spectra of x1 and x2
freq, [X1, X2] = spc.read()
Returns:

  • freq (array[float]) – evaluation frequencies

  • spec (array[complex]) – complex spectrum

collect()[source]

Yield (category, id, data) tuples for recording blocks to simplify global data collection from all recording blocks.

solve(t, dt)[source]

advance solution of implicit update equation of the solver

Parameters:
  • t (float) – evaluation time

  • dt (float) – integration timestep

Returns:

error – solver residual norm

Return type:

float

step(t, dt)[source]

compute timestep update with integration engine

Parameters:
  • t (float) – evaluation time

  • dt (float) – integration timestep

Returns:

  • success (bool) – step was successful

  • error (float) – local truncation error from adaptive integrators

  • scale (float) – timestep rescale from adaptive integrators

sample(t, dt)[source]

sample time of successfull timestep for waiting period

Parameters:
  • t (float) – sampling time

  • dt (float) – integration timestep

plot(*args, **kwargs)[source]

Directly create a plot of the recorded data for visualization.

The ‘fig’ and ‘ax’ objects are accessible as attributes of the ‘Spectrum’ instance from the outside for saving, or modification, etc.

Parameters:
  • args (tuple) – args for ax.plot

  • kwargs (dict) – kwargs for ax.plot

Returns:

  • fig (matplotlib.figure) – internal figure instance

  • ax (matplotlib.axis) – internal axis instance

save(path='spectrum.csv')[source]

Save the recording of the spectrum to a csv file

Parameters:

path (str) – path where to save the recording as a csv file

update(t)[source]

update system equation for fixed point loop, here just setting the outputs

Note

Spectrum block has no passthrough, so the ‘update’ method is optimized for this case

Parameters:

t (float) – evaluation time

class pathsim.blocks.spectrum.RealtimeSpectrum(freq=[], t_wait=0.0, alpha=0.0, labels=[])[source]

Bases: Spectrum

An extension of the ‘Spectrum’ block that also initializes a realtime plotter that creates an interactive plotting window while the simulation is running.

Otherwise implements the same functionality as the regular ‘Spectrum’ block.

Note

Due to the plotting being relatively expensive, including this block slows down the simulation significantly but may still be valuable for debugging and testing.

Parameters:
  • freq (array[float]) – list of evaluation frequencies for RFT, can be arbitrarily spaced

  • t_wait (float) – wait time before starting RFT

  • alpha (float) – exponential forgetting factor for realtime spectrum

  • labels (list[str]) – labels for the inputs

step(t, dt)[source]

compute timestep update with integration engine

Parameters:
  • t (float) – evaluation time

  • dt (float) – integration timestep

Returns:

  • success (bool) – step was successful

  • error (float) – local truncation error from adaptive integrators

  • scale (float) – timestep rescale from adaptive integrators