mth5.timeseries.channel_ts
Channel time series module for MT data.
This module provides the ChannelTS class for handling magnetotelluric (MT) time series data with comprehensive metadata management, calibration, and signal processing capabilities.
Notes
Time series are stored in xarray.DataArray for efficient operations.
Metadata follows the mt_metadata standard with Survey/Station/Run/Channel hierarchy.
Supports instrument response removal, resampling, merging, and Obspy integration.
Attributes
Classes
Time series container for a single MT channel with full metadata. |
Module Contents
- class mth5.timeseries.channel_ts.ChannelTS(channel_type: str = 'auxiliary', data: numpy.ndarray | pandas.DataFrame | pandas.Series | xarray.DataArray | list | tuple | None = None, channel_metadata: mt_metadata.timeseries.Electric | mt_metadata.timeseries.Magnetic | mt_metadata.timeseries.Auxiliary | dict | None = None, station_metadata: mt_metadata.timeseries.Station | dict | None = None, run_metadata: mt_metadata.timeseries.Run | dict | None = None, survey_metadata: mt_metadata.timeseries.Survey | dict | None = None, **kwargs: Any)[source]
Time series container for a single MT channel with full metadata.
Stores equally-spaced time series data in an xarray.DataArray with a time coordinate index. Integrates comprehensive metadata from Survey/Station/Run/Channel hierarchy and supports calibration, resampling, merging, and format conversions.
- Parameters:
channel_type ({'electric', 'magnetic', 'auxiliary'}, default 'auxiliary') – Type of the channel.
data (array-like, optional) – Time series data (numpy array, pandas DataFrame/Series, xarray.DataArray).
channel_metadata (mt_metadata.timeseries.Electric | Magnetic | Auxiliary | dict, optional) – Channel-specific metadata.
station_metadata (mt_metadata.timeseries.Station | dict, optional) – Station metadata.
run_metadata (mt_metadata.timeseries.Run | dict, optional) – Run metadata.
survey_metadata (mt_metadata.timeseries.Survey | dict, optional) – Survey metadata.
**kwargs – Additional attributes to set on the object.
Notes
End time is a derived property and cannot be set directly.
Leverages xarray for efficient interpolation, resampling, and groupby operations.
Metadata follows mt_metadata standards with automatic time period updates.
Examples
Create an auxiliary channel with synthetic data:
>>> from mth5.timeseries import ChannelTS >>> import numpy as np >>> ts_obj = ChannelTS('auxiliary') >>> ts_obj.sample_rate = 8 >>> ts_obj.start = '2020-01-01T12:00:00+00:00' >>> ts_obj.ts = np.random.randn(4096) >>> ts_obj.station_metadata.id = 'MT001' >>> ts_obj.run_metadata.id = 'MT001a' >>> ts_obj.component = 'temperature' >>> print(ts_obj)
Calibrate and remove instrument response:
>>> calibrated = ts_obj.remove_instrument_response() >>> calibrated.channel_metadata.units
- property survey_metadata: mt_metadata.timeseries.Survey[source]
Survey metadata.
- Returns:
Survey metadata with updated keys.
- Return type:
mt_metadata.timeseries.Survey
- property station_metadata: mt_metadata.timeseries.Station[source]
Station metadata.
- Returns:
Station metadata from the first station in the survey.
- Return type:
mt_metadata.timeseries.Station
- property run_metadata: mt_metadata.timeseries.Run[source]
Run metadata.
- Returns:
Run metadata from the first run in the station.
- Return type:
mt_metadata.timeseries.Run
- property channel_metadata: mt_metadata.timeseries.Electric | mt_metadata.timeseries.Magnetic | mt_metadata.timeseries.Auxiliary[source]
Channel metadata.
- Returns:
Channel metadata from the first channel in the run.
- Return type:
mt_metadata.timeseries.Electric | Magnetic | Auxiliary
- get_sample_rate_supplied_at_init(channel_metadata: mt_metadata.timeseries.Electric | mt_metadata.timeseries.Magnetic | mt_metadata.timeseries.Auxiliary | dict | None) float | None[source]
Extract sample_rate from channel_metadata if available.
- Parameters:
channel_metadata (mt_metadata.timeseries.Electric | Magnetic | Auxiliary | dict | None) – Metadata that may contain a sample_rate field.
- Returns:
Sample rate if found, otherwise None.
- Return type:
float | None
Notes
Supports nested dict structures like
{"electric": {"sample_rate": 8.0}}.
- copy(data: bool = True) ChannelTS[source]
Create a copy of the ChannelTS object.
- Parameters:
data (bool, default True) – Include data in the copy (True) or only metadata (False).
- Returns:
Copy of the channel.
- Return type:
Examples
Copy metadata structure without data:
>>> ch_copy = ts_obj.copy(data=False)
- property ts: numpy.ndarray[source]
Time series data as a numpy array.
- Returns:
The time series data.
- Return type:
numpy.ndarray
- property time_index: numpy.ndarray[source]
Time index as a numpy array.
- Returns:
Array of datetime64[ns] timestamps.
- Return type:
numpy.ndarray
- property channel_type: str[source]
Channel type.
- Returns:
Channel type: ‘Electric’, ‘Magnetic’, or ‘Auxiliary’.
- Return type:
str
- is_high_frequency(threshold_dt=0.0001)[source]
Quasi hard-coded condition to check if data are logged at more than 10kHz can be parameterized in future
- compute_sample_rate()[source]
Two cases, high_frequency (HF) data and not HF data.
# Original comment about the HF case: Taking the median(diff(timestamps)) is more accurate for high sample rates, the way pandas.date_range rounds nanoseconds is not consistent between samples, therefore taking the median provides better results if the time series is long this can be inefficient so test first
- property sample_interval[source]
Sample interval = 1 / sample_rate
- Returns:
sample interval as time distance between time samples
- Return type:
float
- property channel_response[source]
Full channel response filter
- Returns:
full channel response filter
- Return type:
mt_metadata.timeseries.filters.ChannelResponse
- get_calibrated_units()[source]
Follows the FDSN standard which has the filter stages starting with physical units to digital counts.
The channel_response is expected to have a list of filter “stages” of which the first stage has input units corresponding to the the physical quantity that the instrument measures, and the last is normally counts.
channel_response can be viewed as the chaining together of all of these filters.
Thus it is normal for channel_response.units_out will be in the same units as the archived raw time series, and for the units after the response is corrected for will be the units_in of
The units of the channel metadata are compared to the input and output units of the channel_response.
- Returns:
tuple, calibration_operation, either “mulitply” or divide”, and a string for calibrated units
- Return type:
tuple (of two strings_
- remove_instrument_response(include_decimation=False, include_delay=False, **kwargs)[source]
Remove instrument response from the given channel response filter
The order of operations is important (if applied):
detrend
zero mean
zero pad
time window
frequency window
remove response
undo time window
bandpass
- Parameters:
include_decimation (bool, optional) – Include decimation in response, defaults to True
include_delay (bool, optional) – include delay in complex response, defaults to False
kwargs
- Parameters:
plot (boolean, default True) – to plot the calibration process [ False | True ]
detrend (boolean, default True) – Remove linar trend of the time series
zero_mean (boolean, default True) – Remove the mean of the time series
zero_pad (boolean, default True) – pad the time series to the next power of 2 for efficiency
t_window (string, default None) – Time domain windown name see scipy.signal.windows for options
t_window_params – Time domain window parameters, parameters can be
found in scipy.signal.windows :type t_window_params: dictionary :param f_window: Frequency domain windown name see scipy.signal.windows for options :type f_window: string, defualt None :param f_window_params: Frequency window parameters, parameters can be found in scipy.signal.windows :type f_window_params: dictionary :param bandpass: bandpass freequency and order {“low”:, “high”:, “order”:,} :type bandpass: dictionary
- get_slice(start, end=None, n_samples=None)[source]
Get a slice from the time series given a start and end time.
Looks for >= start & <= end
Uses loc to be exact with milliseconds
- Parameters:
start (string, MTime) – start time of the slice
end (string, MTime) – end time of the slice
n_samples (integer) – number of sample to get after start time
- Returns:
slice of the channel requested
- Return type:
- decimate(new_sample_rate, inplace=False, max_decimation=8)[source]
decimate the data by using scipy.signal.decimate
- Parameters:
dec_factor (int) – decimation factor
refills ts.data with decimated data and replaces sample_rate
- resample_poly(new_sample_rate, pad_type='mean', inplace=False)[source]
Use scipy.signal.resample_poly to resample data while using an FIR filter to remove aliasing.
- Parameters:
new_sample_rate (TYPE) – DESCRIPTION
pad_type (TYPE, optional) – DESCRIPTION, defaults to “mean”
- Returns:
DESCRIPTION
- Return type:
TYPE
- merge(other, gap_method='slinear', new_sample_rate=None, resample_method='poly')[source]
merg two channels or list of channels together in the following steps
xr.combine_by_coords([original, other])
compute monotonic time index
reindex(new_time_index, method=gap_method)
If you want a different method or more control use merge
- Parameters:
other (
mth5.timeseries.ChannelTS) – Another channel- Raises:
TypeError – If input is not a ChannelTS
ValueError – if the components are different
- Returns:
Combined channel with monotonic time index and same metadata
- Return type:
- to_xarray()[source]
Returns a
xarray.DataArrayobject of the channel timeseries this way metadata from the metadata class is updated upon return.- Returns:
Returns a
xarray.DataArrayobject of the channel timeseries
this way metadata from the metadata class is updated upon return. :rtype:
xarray.DataArray>>> import numpy as np >>> from mth5.timeseries import ChannelTS >>> ex = ChannelTS("electric") >>> ex.start = "2020-01-01T12:00:00" >>> ex.sample_rate = 16 >>> ex.ts = np.random.rand(4096)
- to_obspy_trace(network_code=None, encoding=None)[source]
Convert the time series to an
obspy.core.trace.Traceobject. This will be helpful for converting between data pulled from IRIS and data going into IRIS.- Parameters:
network_code (string) – two letter code provided by FDSN DMC
- Returns:
DESCRIPTION
- Return type:
TYPE
- from_obspy_trace(obspy_trace)[source]
Fill data from an
obspy.core.Trace- Parameters:
obspy_trace (obspy.core.trace) – Obspy trace object