API Reference

Data loading is handled by the mojito package (mojito.reader.MojitoL1File). This package focuses exclusively on the signal processing steps applied to that data.

Signal Processing

class MojitoProcessor.SigProcessing.SignalProcessor(data, fs, t0=None)[source]

Bases: object

Signal processor for multi-channel time series data.

Handles filtering, downsampling, trimming, and windowing while automatically tracking sampling parameters (fs, N, T, dt).

Parameters:
  • data (dict) – Dictionary of channel data, e.g., {‘X’: array, ‘Y’: array, ‘Z’: array}

  • fs (float) – Sampling frequency in Hz

data

Current processed data (updated after each operation). Includes a 't' key giving the time array [t0, t0+dt, ..., t0+(N-1)*dt] in seconds (or [0, dt, ..., (N-1)*dt] when t0 is None).

Type:

dict

fs

Current sampling frequency in Hz

Type:

float

N

Current number of samples per channel

Type:

int

T

Current duration in seconds

Type:

float

dt

Current sampling period in seconds

Type:

float

t

Time array [t0, t0+dt, ..., t0+(N-1)*dt] in seconds.

Type:

ndarray

channels

List of channel names

Type:

list

Example

>>> sp = SignalProcessor({'X': x_data, 'Y': y_data}, fs=4.0)
>>> filtered = sp.filter(low=1e-4, high=1.0, order=6)
>>> trimmed = sp.trim(fraction=0.02)  # Trim 2% total (1% each end)
>>> windowed = sp.apply_window(window='tukey', alpha=0.05)
>>> t = sp.data['t']   # time array [t0, t0+dt, ..., t0+(N-1)*dt]
apply_window(window='tukey', **window_params)[source]

Apply window function to all channels.

Parameters:
  • window (str, optional) – Window type: ‘tukey’, ‘blackmanharris’, ‘hann’, ‘hamming’, ‘blackman’, ‘planck’ (default: ‘tukey’)

  • **window_params – Additional parameters for window function. For ‘tukey’: alpha (default: 0.05) For ‘planck’: alpha (default: 0.05) Other windows typically don’t need parameters.

Returns:

windowed_data – Dictionary of windowed channel data

Return type:

dict

Examples

>>> sp.apply_window('tukey', alpha=0.05)
>>> sp.apply_window('blackmanharris')
>>> sp.apply_window('hann')
property data: dict

Channel data as a dict, including a 't' key for the time array.

The time array is t0 + np.arange(N) * dt (seconds). When t0 is None, the array starts from 0.

Returns:

All channel arrays plus 't'.

Return type:

dict

downsample(target_fs, window=('kaiser', 31.0), padtype='line')[source]

Resample all channels to a target sampling rate using polyphase filtering.

Uses scipy.signal.resample_poly which applies a zero-phase FIR anti-aliasing filter via polyphase decomposition. Accepts arbitrary rational target rates (e.g., 4 Hz -> 0.4 Hz), unlike decimate which requires an integer factor.

Parameters:
  • target_fs (float) – Desired output sampling frequency in Hz. Must be positive and less than or equal to the current sampling frequency (this method is a downsampler).

  • window (tuple or array_like, optional) – Window specification passed to scipy.signal.resample_poly for FIR anti-aliasing filter design. Default ('kaiser', 5.0) is scipy’s own default and gives good stopband attenuation.

  • padtype (str, optional) – Edge-padding strategy. Options: 'line' (default), 'constant', 'mean', 'median', 'maximum', 'minimum'. 'line' extends the signal linearly from each end, reducing edge transients for slowly-varying data such as LISA TDI channels.

Return type:

Tuple[Dict[str, ndarray], float]

Returns:

  • resampled_data (dict) – Dictionary mapping channel names to resampled 1D arrays.

  • new_fs (float) – Actual output sampling frequency in Hz (exact rational result self.fs * up / down).

Raises:
  • ValueError – If target_fs is not positive.

  • ValueError – If target_fs exceeds the current sampling frequency.

  • ValueError – If the rational approximation of target_fs / self.fs produces up == 0.

Notes

The up/down integers are computed via:

ratio = Fraction(target_fs / self.fs).limit_denominator(10000)
up, down = ratio.numerator, ratio.denominator

Common use cases from 4 Hz source data:

  • 4 Hz -> 1 Hz: up=1, down=4

  • 4 Hz -> 0.4 Hz: up=1, down=10

  • 4 Hz -> 2 Hz: up=1, down=2

  • 4 Hz -> 3 Hz: up=3, down=4

Examples

>>> sp = SignalProcessor({'X': x_data, 'Y': y_data}, fs=4.0)
>>> sp.filter(low=5e-6, order=2)
>>> sp.trim(fraction=0.022)  # Trim 2.2% total
>>> resampled, new_fs = sp.downsample(target_fs=1.0)
>>> print(new_fs)   # 1.0
fft()[source]

Compute the one-sided complex FFT spectrum for each channel.

The data is assumed to have already been windowed (e.g. by apply_window()), so no additional window is applied here. Returns raw complex amplitudes from numpy.fft.rfft.

Return type:

Tuple[ndarray, Dict[str, ndarray]]

Returns:

  • freqs (ndarray) – Frequency array in Hz, shape (N//2 + 1,).

  • ffts (dict) – Dictionary mapping channel names to complex FFT arrays, each with shape (N//2 + 1,).

Examples

>>> freqs, ffts = sp.fft()
>>> plt.loglog(freqs[1:], np.abs(ffts['X'][1:]))
filter(*, low=None, high=None, order=2, filter_type='butterworth', zero_phase=True)[source]

Apply filter to all channels (auto-detects highpass/lowpass/bandpass).

Automatically determines filter type based on provided cutoff frequencies: - Only low set: highpass filter - Only high set: lowpass filter - Both low and high set: bandpass filter

Parameters:
  • low (float, optional) – Lower cutoff frequency in Hz (highpass)

  • high (float, optional) – Upper cutoff frequency in Hz (lowpass)

  • order (int, optional) – Filter order (default: 6)

  • filter_type (str, optional) – Filter type: ‘butterworth’, ‘chebyshev1’, ‘chebyshev2’, ‘bessel’ (default: ‘butterworth’)

  • zero_phase (bool, optional) – Use zero-phase filtering (filtfilt) if True, else single-pass (default: True)

Returns:

filtered_data – Dictionary of filtered channel data

Return type:

dict

Raises:

ValueError – If neither low nor high is provided

Examples

>>> # Highpass only
>>> sp.filter(low=5e-6, order=2)
>>> # Lowpass only
>>> sp.filter(high=0.1, order=2)
>>> # Bandpass
>>> sp.filter(low=1e-4, high=0.1, order=6)
get_params()[source]

Get current signal parameters.

Returns:

params – Dictionary containing fs, N, T, dt, and channels

Return type:

dict

periodogram()[source]

Compute the one-sided power spectral density for each channel.

The data is assumed to have already been windowed (e.g. by apply_window()), so no additional window is applied here.

Normalisation follows Parseval’s theorem: the integral of the one-sided PSD over positive frequencies equals the mean square of the signal.

Return type:

Tuple[ndarray, Dict[str, ndarray]]

Returns:

  • freqs (ndarray) – Frequency array in Hz, shape (N//2 + 1,).

  • psds (dict) – Dictionary mapping channel names to one-sided PSD arrays (units²/Hz), each with the same shape as freqs.

Examples

>>> freqs, psds = sp.periodogram()
>>> plt.loglog(freqs[1:], psds['X'][1:])
property t: ndarray

Time array [t0, t0+dt, ..., t0+(N-1)*dt] in seconds.

to_aet()[source]

Transform XYZ Michelson channels to noise-orthogonal AET channels.

Uses the standard equal-arm combination:

A = (Z - X) / sqrt(2)
E = (X - 2Y + Z) / sqrt(6)
T = (X + Y + Z) / sqrt(3)

Returns a new SignalProcessor with channels ['A', 'E', 'T'], inheriting fs, t0, and all derived parameters from the original.

Returns:

New processor with AET channel data.

Return type:

SignalProcessor

Raises:

ValueError – If any of the channels 'X', 'Y', 'Z' are missing.

Examples

>>> sp_xyz = processed_segments['segment0']
>>> sp_aet = sp_xyz.to_aet()
>>> freqs, psds = sp_aet.periodogram()
trim(fraction)[source]

Trim data by removing a fraction of the dataset.

Parameters:

fraction (float) – Total fraction of data to remove (e.g., 0.01 = 1%).

Returns:

trimmed_data – Dictionary of trimmed channel data

Return type:

dict

Raises:

ValueError – If fraction is not in range [0, 1] or would remove all data

Examples

>>> # Trim 2% total (1% from each end)
>>> sp.trim(fraction=0.02)
>>> # Trim 5% from start only
>>> sp.trim(fraction=0.05)
MojitoProcessor.SigProcessing.process_pipeline(data, channels=None, *, filter_kwargs=None, downsample_kwargs=None, trim_kwargs=None, truncate_kwargs=None, window_kwargs=None)[source]

Run the full TDI data processing pipeline on a MojitoData object.

Applies the following steps in order:

  1. Filter — band-pass (if lowpass_cutoff given) or high-pass only

  2. Downsample — polyphase resampling to target_fs (optional)

  3. Trim — removes edge artefacts introduced by the filter from both ends

  4. Truncate — selects the first truncate_days of the processed data

  5. Window — tapers edges to reduce spectral leakage

Pipeline progress is emitted at logging.INFO level via the MojitoUtils.SigProcessing logger.

Parameters:
  • data (MojitoData) – Loaded LISA L1 data object (from load_mojito_l1). Must have data.tdis (dict of channel arrays) and data.fs (sampling rate).

  • channels (list of str, optional) – TDI channels to process. Default ['X', 'Y', 'Z'].

  • filter_kwargs (dict, optional) – Filter parameters. Keys: - highpass_cutoff (float): High-pass cutoff in Hz (default: 5e-6) - lowpass_cutoff (float, optional): Low-pass cutoff for band-pass - order (int): Filter order (default: 2) - filter_type (str): Filter type (default: ‘butterworth’)

  • downsample_kwargs (dict, optional) – Downsampling parameters. Keys: - target_fs (float): Target sampling rate in Hz - kaiser_window (float): Kaiser window beta parameter (default: 31.0)

  • trim_kwargs (dict, optional) – Trimming parameters. Omit (or pass None) to skip trimming. Keys: - fraction (float): Fraction to trim from each end (default: 0.0)

  • truncate_kwargs (dict, optional) – Segmentation parameters. Keys: - days (float): Segment length in days (default: 4.0) Dataset is split into non-overlapping segments of this length. Each segment is independently windowed. Set to None to disable segmentation (returns single segment with full dataset). Note: Remainder samples shorter than a full segment are discarded.

  • window_kwargs (dict, optional) – Windowing parameters. Omit (or pass None) to skip windowing. Keys: - window (str): Window type - ‘tukey’, ‘hann’, etc. (default: ‘tukey’) - alpha (float): Taper fraction for Tukey window (default: 0.025)

Returns:

segments – Dictionary mapping segment names (‘segment0’, ‘segment1’, …) to SignalProcessor objects. Each segment contains windowed data ready for FFT analysis. Access via segments['segment0'].data, segments['segment0'].fs, etc.

Return type:

dict of SignalProcessor