mth5.io.phoenix.readers

Submodules

Classes

Header

Phoenix Geophysics MTU-5C binary header reader and parser.

PhoenixCalibration

Phoenix Geophysics calibration data reader and filter manager.

TSReaderBase

Generic reader that all other readers will inherit.

NativeReader

Native sampling rate 'Raw' time series reader class.

DecimatedSegmentedReader

Class to create a streamer for segmented decimated time series.

DecimatedContinuousReader

Class to create a streamer for continuous decimated time series.

PhoenixConfig

Phoenix Geophysics configuration file reader and metadata container.

PhoenixReceiverMetadata

Container for Phoenix Geophysics recmeta.json metadata files.

MTUTable

MTUTSN

Reader for legacy Phoenix MTU-5A instrument time series binary files.

Package Contents

class mth5.io.phoenix.readers.Header(**kwargs: Any)[source]

Phoenix Geophysics MTU-5C binary header reader and parser.

This class reads and parses the 128-byte binary header from Phoenix Geophysics MTU-5C data files. The header contains instrument configuration, GPS location, timing information, and recording parameters essential for proper data interpretation.

The header format is fixed at 128 bytes and contains information about: - Instrument type and serial number - Recording parameters (sample rate, channel configuration) - GPS location and timing information - Hardware configuration and gain settings - Data quality metrics (saturated/missing frames)

Parameters:

**kwargs (Any) – Additional keyword arguments to set as instance attributes.

logger

Logger instance for debugging and error reporting.

Type:

loguru.Logger

report_hw_sat

Flag to control hardware saturation reporting.

Type:

bool, default False

header_length

Length of the binary header in bytes.

Type:

int, default 128

ad_plus_minus_range

Differential voltage range of the A/D converter (board dependent).

Type:

float, default 5.0

channel_map

Mapping from channel IDs to channel names.

Type:

dict[int, str]

channel_azimuths

Mapping from channel names to azimuth angles in degrees.

Type:

dict[str, int]

Examples

>>> with open("phoenix_data.bin", "rb") as f:
...     header = Header()
...     header.unpack_header(f)
...     print(f"Sample rate: {header.sample_rate}")
...     print(f"GPS location: {header.gps_lat}, {header.gps_long}")
logger: loguru.Logger
report_hw_sat: bool = False
property header_length: int

Length of the header in bytes.

Returns:

Header length in bytes.

Return type:

int

ad_plus_minus_range: float = 5.0
channel_map: dict[int, str]
channel_azimuths: dict[str, int]
property file_type: int | None

File type indicator from binary header.

Returns:

File type identifier, or None if no header is loaded.

Return type:

int or None

property file_version: int | None

File version from binary header.

Returns:

File version identifier, or None if no header is loaded.

Return type:

int or None

property instrument_type: str | None

Instrument type string from binary header.

Returns:

Cleaned instrument type string, or None if no header is loaded.

Return type:

str or None

property instrument_serial_number: str | None

Instrument serial number from binary header.

Returns:

Decoded instrument serial number, or None if no header is loaded.

Return type:

str or None

property recording_id: int | None

Recording identifier from binary header or cached value.

Returns:

Recording ID as integer, or None if not available.

Return type:

int or None

property recording_start_time: mt_metadata.common.mttime.MTime | None

Recording start time from GPS timestamp.

The actual data recording starts 1 second after the set start time. This is caused by the data logger starting up and initializing filter. This is taken care of in the segment start time.

See https://github.com/kujaku11/PhoenixGeoPy/tree/main/Docs for more information.

The time recorded is GPS time.

Returns:

GPS start time, or None if recording ID is not available.

Return type:

MTime or None

property channel_id: int | None

Channel identifier from binary header or cached value.

Returns:

Channel ID, or None if not available.

Return type:

int or None

property file_sequence: int | None

File sequence number from binary header.

Returns:

File sequence number, or None if no header is loaded.

Return type:

int or None

property frag_period: int | None

Fragment period from binary header.

Returns:

Fragment period, or None if no header is loaded.

Return type:

int or None

property ch_board_model: str | None

Channel board model string from binary header.

Returns:

Board model string, or None if no header is loaded.

Return type:

str or None

property board_model_main: str | None

Main board model identifier.

Returns:

Main board model (first 5 characters), or None if not available.

Return type:

str or None

property board_model_revision: str | None

Board model revision identifier.

Returns:

Board revision (character 6), or None if not available.

Return type:

str or None

property ch_board_serial: int

Channel board serial number from binary header.

Returns:

Board serial number as integer, or 0 if not available or invalid.

Return type:

int

property ch_firmware: int | None

Channel firmware version from binary header.

Returns:

Firmware version, or None if no header is loaded.

Return type:

int or None

property hardware_configuration: tuple[Any, Ellipsis] | None

Hardware configuration bytes from binary header.

Returns:

Hardware configuration data, or None if no header is loaded.

Return type:

tuple of Any or None

property channel_type: str | None

Channel type determined from hardware configuration.

Returns:

‘E’ for electric, ‘H’ for magnetic, or None if no header.

Return type:

str or None

property detected_channel_type: str | None

Channel type detected by electronics.

This normally matches channel_type, but used in electronics design and testing.

Returns:

‘E’ for electric, ‘H’ for magnetic, or None if no header.

Return type:

str or None

property lp_frequency: int | None

Low-pass filter frequency based on hardware configuration.

Returns:

Filter frequency in Hz, or None if no header.

Return type:

int or None

property preamp_gain: float

Pre-amplifier gain factor.

Returns:

Gain factor, default 1.0.

Return type:

float

Raises:

Exception – If channel type is not determined before calculating gain.

property channel_main_gain: float

Main gain of the board.

Returns:

Main gain factor.

Return type:

float

property intrinsic_circuitry_gain: float

Intrinsic circuitry gain based on sensor range configuration.

This function adjusts the intrinsic circuitry gain based on the sensor range configuration in the configuration fingerprint.

For the Electric channel, calibration path, or H-legacy sensors all go through a 1/4 gain stage, and then they get a virtual x2 gain from Single-ended-diff before the A/D. In the case of newer sensors (differential) instead of a 1/4 gain stage, there is only a 1/2 gain stage.

Therefore, in the E, cal and legacy sensor case the circuitry gain is 1/2, while for newer sensors it is 1.

Returns:

Intrinsic gain factor.

Return type:

float

Raises:

Exception – If channel type is not determined before calculating gain.

Notes

Circuitry Gain not directly configurable by the user.

property attenuator_gain: float

Attenuator gain factor.

Returns:

Attenuator gain factor, default 1.0.

Return type:

float

Raises:

Exception – If channel type is not determined before calculating gain.

property total_selectable_gain: float

Total gain that is selectable by the user.

Combines attenuator, preamp, and main channel gains.

Returns:

Total selectable gain factor.

Return type:

float

property total_circuitry_gain: float

Total board gain including both intrinsic and user-selectable gains.

Returns:

Total circuitry gain factor.

Return type:

float

property sample_rate_base: int | None

Base sample rate from binary header.

Returns:

Base sample rate, or None if no header.

Return type:

int or None

property sample_rate_exp: int | None

Sample rate exponent from binary header.

Returns:

Sample rate exponent, or None if no header.

Return type:

int or None

property sample_rate: float | None

Calculated sample rate.

Returns:

Sample rate in Hz, or None if no header.

Return type:

float or None

property bytes_per_sample: int | None

Number of bytes per sample.

Returns:

Bytes per sample, or None if no header.

Return type:

int or None

property frame_size: int | None

Frame size from binary header.

Returns:

Frame size value, or None if no header.

Return type:

int or None

Data footer extracted from frame size.

Returns:

Data footer value, or None if no frame size.

Return type:

int or None

property frame_size_bytes: int | None

Frame size in bytes.

Returns:

Frame size in bytes, or None if no frame size.

Return type:

int or None

property decimation_node_id: int | None

Decimation node identifier.

Returns:

Decimation node ID, or None if no header.

Return type:

int or None

property frame_rollover_count: int | None

Frame rollover count.

Returns:

Rollover count, or None if no header.

Return type:

int or None

property gps_long: float | None

GPS longitude.

Returns:

Longitude in degrees, or None if no header.

Return type:

float or None

property gps_lat: float | None

GPS latitude.

Returns:

Latitude in degrees, or None if no header.

Return type:

float or None

property gps_elevation: float | None

GPS elevation.

Returns:

Elevation in meters, or None if no header.

Return type:

float or None

property gps_horizontal_accuracy: float | None

GPS horizontal accuracy.

Returns:

Horizontal accuracy in meters (converted from millimeters), or None if no header.

Return type:

float or None

property gps_vertical_accuracy: float | None

GPS vertical accuracy.

Returns:

Vertical accuracy in meters (converted from millimeters), or None if no header.

Return type:

float or None

property timing_status: tuple[Any, Ellipsis] | None

Timing status information.

Returns:

Timing status data, or None if no header.

Return type:

tuple of Any or None

property timing_flags: Any | None

Timing flags from timing status.

Returns:

Timing flags, or None if no timing status.

Return type:

Any or None

property timing_sat_count: Any | None

Satellite count from timing status.

Returns:

Satellite count, or None if no timing status.

Return type:

Any or None

property timing_stability: Any | None

Timing stability from timing status.

Returns:

Timing stability value, or None if no timing status.

Return type:

Any or None

property future1: Any | None

Future field 1 (reserved).

Returns:

Future field value, or None if no header.

Return type:

Any or None

property future2: Any | None

Future field 2 (reserved).

Returns:

Future field value, or None if no header.

Return type:

Any or None

property saturated_frames: int | None

Number of saturated frames.

Returns:

Saturated frame count, or None if no header.

Return type:

int or None

property missing_frames: int | None

Number of missing frames.

Returns:

Missing frame count, or None if no header.

Return type:

int or None

property battery_voltage_v: float | None

Battery voltage in volts.

Returns:

Battery voltage in volts (converted from millivolts), or None if no header.

Return type:

float or None

property min_signal: Any | None

Minimum signal value.

Returns:

Minimum signal value, or None if no header.

Return type:

Any or None

property max_signal: Any | None

Maximum signal value.

Returns:

Maximum signal value, or None if no header.

Return type:

Any or None

unpack_header(stream: BinaryIO) None[source]

Read and unpack binary header from stream.

Parameters:

stream (BinaryIO) – Binary stream to read header from.

get_channel_metadata() mt_metadata.timeseries.Magnetic | mt_metadata.timeseries.Electric[source]

Translate metadata to channel metadata.

Returns:

Channel metadata object populated with header data.

Return type:

Magnetic or Electric

Raises:
  • KeyError – If channel ID is not found in channel map.

  • ValueError – If required fields are None or invalid.

get_run_metadata() mt_metadata.timeseries.Run[source]

Translate to run metadata.

Returns:

Run metadata object populated with header data.

Return type:

Run

Raises:

ValueError – If required fields are None.

get_station_metadata() mt_metadata.timeseries.Station[source]

Translate to station metadata.

Returns:

Station metadata object populated with header data.

Return type:

Station

class mth5.io.phoenix.readers.PhoenixCalibration(cal_fn: str | pathlib.Path | None = None, **kwargs: Any)[source]

Phoenix Geophysics calibration data reader and filter manager.

This class reads Phoenix calibration files in JSON format and provides access to frequency response filters for different channels and lowpass filter settings. It supports both receiver and sensor calibration files.

Parameters:
  • cal_fn (str or pathlib.Path, optional) – Path to the calibration file to read. If provided, the file will be loaded automatically during initialization.

  • **kwargs (Any) – Additional keyword arguments that will be set as instance attributes.

obj

The parsed calibration object containing all calibration data.

Type:

Any or None

obj: Any = None
property cal_fn: pathlib.Path

Path to the calibration file.

Returns:

The path to the calibration file.

Return type:

pathlib.Path

property calibration_date: mt_metadata.common.mttime.MTime | None

Get the calibration date from the loaded calibration data.

Returns:

The calibration date as an MTime object, or None if no data is loaded.

Return type:

MTime or None

get_max_freq(freq: numpy.typing.NDArray[numpy.floating] | list[float] | numpy.ndarray) int[source]

Calculate the maximum frequency for filter naming.

Determines the power-of-10 frequency limit based on the maximum frequency in the input array. Used to name filters as {channel}_{max_freq}hz_lowpass.

Parameters:

freq (numpy.ndarray) – Array of frequency values in Hz.

Returns:

The power-of-10 frequency limit (e.g., 1000 for frequencies up to 9999 Hz).

Return type:

int

Examples

>>> cal = PhoenixCalibration()
>>> freq = np.array([1.0, 10.0, 100.0, 1500.0])
>>> cal.get_max_freq(freq)
1000
property base_filter_name: str | None

Generate the base filter name from instrument information.

Creates a standardized filter name prefix based on the instrument type, model, and serial number from the calibration data.

Returns:

Base filter name in format “{instrument_type}_{instrument_model}_{serial}” converted to lowercase, or None if no data is loaded.

Return type:

str or None

Examples

>>> cal = PhoenixCalibration("calibration.json")
>>> cal.base_filter_name
'mtu-5c_rmt03-j_666'
get_filter_lp_name(channel: str, max_freq: int) str[source]

Generate a lowpass filter name for a specific channel and frequency.

Creates a standardized filter name for receiver calibration filters in the format: {base_filter_name}_{channel}_{max_freq}hz_lowpass

Parameters:
  • channel (str) – Channel identifier (e.g., ‘e1’, ‘h2’).

  • max_freq (int) – Maximum frequency in Hz for the lowpass filter.

Returns:

Complete lowpass filter name in lowercase.

Return type:

str

Examples

>>> cal = PhoenixCalibration("calibration.json")
>>> cal.get_filter_lp_name("e1", 1000)
'mtu-5c_rmt03-j_666_e1_1000hz_lowpass'
get_filter_sensor_name(sensor: str) str[source]

Generate a sensor filter name for a specific sensor.

Creates a standardized filter name for sensor calibration filters in the format: {base_filter_name}_{sensor}

Parameters:

sensor (str) – Sensor identifier or serial number.

Returns:

Complete sensor filter name in lowercase.

Return type:

str

Examples

>>> cal = PhoenixCalibration("calibration.json")
>>> cal.get_filter_sensor_name("sensor123")
'mtu-5c_rmt03-j_666_sensor123'
read(cal_fn: str | pathlib.Path | None = None) None[source]

Read and parse a Phoenix calibration file.

Loads calibration data from a JSON file and creates frequency response filters for each channel and frequency band. The method creates channel attributes (e.g., self.e1, self.h2) containing either: - Dictionary of filters by frequency (receiver calibration) - Single filter object (sensor calibration)

Parameters:

cal_fn (str, pathlib.Path, or None, optional) – Path to the calibration file to read. If None, uses the previously set calibration file path.

Raises:

IOError – If the calibration file cannot be found or read.

Notes

The method automatically determines calibration type based on file_type: - “receiver calibration”: Creates multiple filters per channel by frequency - “sensor calibration”: Creates single filter per channel

get_filter(channel: str, filter_name: str | int) mt_metadata.timeseries.filters.FrequencyResponseTableFilter[source]

Get the frequency response filter for a specific channel and filter.

Retrieves the lowpass filter for the given channel and filter specification. The method automatically handles both string and integer filter names.

Parameters:
  • channel (str) – Channel identifier (e.g., ‘e1’, ‘h2’, ‘h3’).

  • filter_name (str or int) – Filter specification, typically the lowpass frequency in Hz (e.g., 1000, ‘100’, 10000).

Returns:

The frequency response filter object containing the calibration data for the specified channel and filter.

Return type:

FrequencyResponseTableFilter

Raises:
  • AttributeError – If the specified channel is not found in the calibration data.

  • KeyError – If the specified filter is not found for the given channel.

Examples

>>> cal = PhoenixCalibration("calibration.json")
>>> filt = cal.get_filter("e1", 1000)
>>> print(f"Filter name: {filt.name}")
>>> print(f"Frequency points: {len(filt.frequencies)}")
class mth5.io.phoenix.readers.TSReaderBase(path: str | pathlib.Path, num_files: int = 1, header_length: int = 128, report_hw_sat: bool = False, **kwargs)[source]

Bases: mth5.io.phoenix.readers.header.Header

Generic reader that all other readers will inherit.

This base class provides common functionality for reading Phoenix Geophysics time series data files, including header parsing, file sequence management, and metadata handling.

Parameters:
  • path (str or Path) – Path to the time series file

  • num_files (int, optional) – Number of files in the sequence, by default 1

  • header_length (int, optional) – Length of file header in bytes, by default 128

  • report_hw_sat (bool, optional) – Whether to report hardware saturation, by default False

  • **kwargs – Additional keyword arguments passed to parent Header class

stream

File stream for reading binary data

Type:

BinaryIO or None

base_path

Path to the current file

Type:

Path

last_seq

Last sequence number in the file sequence

Type:

int

rx_metadata

Receiver metadata object

Type:

PhoenixReceiverMetadata or None

logger
property base_path: pathlib.Path

Full path of the file.

Returns:

Full path to the file

Return type:

Path

last_seq
stream = None
rx_metadata = None
property base_dir: pathlib.Path

Parent directory of the file.

Returns:

Parent directory of the file

Return type:

Path

property file_name: str

Name of the file.

Returns:

Name of the file

Return type:

str

property file_extension: str

File extension.

Returns:

File extension including the dot

Return type:

str

property instrument_id: str

Instrument ID extracted from filename.

Returns:

Instrument identifier

Return type:

str

property seq: int

Sequence number of the file.

Returns:

Sequence number extracted from filename or set value

Return type:

int

property file_size: int

File size in bytes.

Returns:

Size of the file in bytes

Return type:

int

property max_samples: int

Maximum number of samples in a file.

Calculated as: (total number of bytes - header length) / frame size * n samples per frame

Returns:

Maximum number of samples in the file

Return type:

int

property sequence_list: list[pathlib.Path]

Get all the files in the sequence sorted by sequence number.

Returns:

List of Path objects for all files in the sequence

Return type:

list[Path]

property config_file_path: pathlib.Path | None

Path to the config.json file.

Returns:

Path to config file if it exists, None otherwise

Return type:

Path or None

property recmeta_file_path: pathlib.Path | None

Path to the recmeta.json file.

Returns:

Path to recmeta file if it exists, None otherwise

Return type:

Path or None

open_next() bool[source]

Open the next file in the sequence.

Returns:

True if next file is now open, False if it is not

Return type:

bool

open_file_seq(file_seq_num: int | None = None) bool[source]

Open a file in the sequence given the sequence number.

Parameters:

file_seq_num (int, optional) – Sequence number to open, by default None

Returns:

True if file is now open, False if it is not

Return type:

bool

close() None[source]

Close the file stream.

get_config_object() mth5.io.phoenix.readers.config.PhoenixConfig | None[source]

Read a config file into an object.

Returns:

Configuration object if config file exists, None otherwise

Return type:

PhoenixConfig or None

get_receiver_metadata_object() None[source]

Read recmeta.json into an object and store in rx_metadata attribute.

get_lowpass_filter_name() str | None[source]

Get the lowpass filter used by the receiver pre-decimation.

Returns:

Name of the lowpass filter if available, None otherwise

Return type:

str or None

update_channel_map_from_recmeta() None[source]

Update channel map from recmeta.json file.

property channel_metadata: Any

Channel metadata updated from recmeta.

Returns:

Channel metadata object

Return type:

Any

property run_metadata: Any

Run metadata updated from recmeta.

Returns:

Run metadata object

Return type:

Any

property station_metadata: Any

Station metadata updated from recmeta.

Returns:

Station metadata object

Return type:

Any

get_receiver_lowpass_filter(rxcal_fn: str | pathlib.Path) Any[source]

Get receiver lowpass filter from the rxcal.json file.

Parameters:

rxcal_fn (str or Path) – Path to the receiver calibration file

Returns:

Filter object from calibration file

Return type:

Any

Raises:

ValueError – If the lowpass filter name cannot be found

get_dipole_filter() mt_metadata.timeseries.filters.CoefficientFilter | None[source]

Get dipole filter for electric field channels.

Returns:

Dipole filter if channel has dipole length, None otherwise

Return type:

CoefficientFilter or None

get_sensor_filter(scal_fn: str | pathlib.Path) Any[source]

Get sensor filter from calibration file.

Parameters:

scal_fn (str or Path) – Path to sensor calibration file

Returns:

Sensor filter object

Return type:

Any

Notes

This method is not implemented yet.

get_v_to_mv_filter() mt_metadata.timeseries.filters.CoefficientFilter[source]

Create a filter to convert units from volts to millivolts.

Returns:

Filter that converts volts to millivolts with gain of 1000

Return type:

CoefficientFilter

get_channel_response(rxcal_fn: str | pathlib.Path | None = None, scal_fn: str | pathlib.Path | None = None) mt_metadata.timeseries.filters.ChannelResponse[source]

Get the channel response filter.

Parameters:
  • rxcal_fn (str, Path or None, optional) – Path to receiver calibration file, by default None

  • scal_fn (str, Path or None, optional) – Path to sensor calibration file, by default None

Returns:

Complete channel response filter chain

Return type:

ChannelResponse

class mth5.io.phoenix.readers.NativeReader(path: str | pathlib.Path, num_files: int = 1, scale_to: int = AD_INPUT_VOLTS, header_length: int = 128, last_frame: int = 0, ad_plus_minus_range: float = 5.0, channel_type: str = 'E', report_hw_sat: bool = False, **kwargs)[source]

Bases: mth5.io.phoenix.readers.TSReaderBase

Native sampling rate ‘Raw’ time series reader class.

This class reads native binary (.bin) files from Phoenix Geophysics MTU-5C instruments. The files are formatted with a header of 128 bytes followed by frames of 64 bytes each. Each frame contains 20 x 3-byte (24-bit) data points plus a 4-byte footer.

Parameters:
  • path (str or Path) – Path to the time series file

  • num_files (int, optional) – Number of files in the sequence, by default 1

  • scale_to (int, optional) – Data scaling mode (AD_IN_AD_UNITS, AD_INPUT_VOLTS, or INSTRUMENT_INPUT_VOLTS), by default AD_INPUT_VOLTS

  • header_length (int, optional) – Length of file header in bytes, by default 128

  • last_frame (int, optional) – Last frame number seen by the streamer, by default 0

  • ad_plus_minus_range (float, optional) – ADC plus/minus range in volts, by default 5.0

  • channel_type (str, optional) – Channel type identifier, by default “E”

  • report_hw_sat (bool, optional) – Whether to report hardware saturation, by default False

  • **kwargs – Additional keyword arguments passed to parent TSReaderBase class

last_frame

Last frame number processed

Type:

int

data_scaling

Current data scaling mode

Type:

int

ad_plus_minus_range

ADC voltage range

Type:

float

input_plusminus_range

Input voltage range after gain correction

Type:

float

scale_factor

Calculated scaling factor for data conversion

Type:

float

footer_idx_samp_mask

Bit mask for frame index in footer

Type:

int

footer_sat_mask

Bit mask for saturation count in footer

Type:

int

last_frame = 0
header_length = 128

Length of the header in bytes.

Returns:

Header length in bytes.

Return type:

int

data_scaling = 1
ad_plus_minus_range = 5.0
input_plusminus_range
scale_factor = 256
footer_idx_samp_mask = 0
footer_sat_mask = 0
read_frames(num_frames: int) numpy.ndarray[source]

Read the given number of frames from the data stream.

Note

The seek position is not reset, so iterating this method will read from the last position in the stream.

Parameters:

num_frames (int) – Number of frames to read

Returns:

Scaled data from the given number of frames with dtype float64

Return type:

np.ndarray

property npts_per_frame: int

Get the number of data points per frame.

Returns:

Number of data points per frame (frame size - 4 footer bytes) / 3 bytes per sample

Return type:

int

read() tuple[numpy.ndarray, numpy.ndarray][source]

Read the full data file using memory mapping and stride tricks.

Note

This uses numpy.lib.stride_tricks.as_strided which can be unstable if the bytes are not the correct length. See notes by numpy.

The solution is adapted from: https://stackoverflow.com/questions/12080279/how-do-i-create-a-numpy-dtype-that-includes-24-bit-integers

Returns:

Scaled time series data and footer data as (data, footer)

Return type:

tuple[np.ndarray, np.ndarray]

read_sequence(start: int = 0, end: int | None = None) tuple[numpy.ndarray, numpy.ndarray][source]

Read a sequence of files into a single array.

Parameters:
  • start (int, optional) – Sequence start index, by default 0

  • end (int or None, optional) – Sequence end index, by default None

Returns:

Scaled time series data and footer data as (data, footer) - data: np.ndarray with dtype float32 - footer: np.ndarray with dtype int32

Return type:

tuple[np.ndarray, np.ndarray]

skip_frames(num_frames: int) bool[source]

Skip frames in the data stream.

Parameters:

num_frames (int) – Number of frames to skip

Returns:

True if skip completed successfully, False if end of file reached

Return type:

bool

to_channel_ts(rxcal_fn: str | pathlib.Path | None = None, scal_fn: str | pathlib.Path | None = None) mth5.timeseries.ChannelTS[source]

Convert to a ChannelTS object.

Parameters:
  • rxcal_fn (str, Path or None, optional) – Path to receiver calibration file, by default None

  • scal_fn (str, Path or None, optional) – Path to sensor calibration file, by default None

Returns:

Channel time series object with data, metadata, and calibration

Return type:

ChannelTS

class mth5.io.phoenix.readers.DecimatedSegmentedReader(path: str | pathlib.Path, num_files: int = 1, report_hw_sat: bool = False, **kwargs)[source]

Bases: mth5.io.phoenix.readers.TSReaderBase

Class to create a streamer for segmented decimated time series.

This reader handles segmented decimated time series files such as ‘td_24k’. These files have sub headers containing metadata for each segment.

Parameters:
  • path (str or Path) – Path to the time series file

  • num_files (int, optional) – Number of files in the sequence, by default 1

  • report_hw_sat (bool, optional) – Whether to report hardware saturation, by default False

  • **kwargs – Additional keyword arguments passed to parent TSReaderBase class

sub_header

SubHeader instance for parsing segment headers

Type:

SubHeader

subheader

Dictionary for additional subheader information

Type:

dict

sub_header
subheader
read_segment(metadata_only: bool = False) Segment[source]

Read a single segment from the file.

Parameters:

metadata_only (bool, optional) – If True, only read metadata without loading data, by default False

Returns:

Segment object containing data and metadata

Return type:

Segment

Raises:

ValueError – If stream is not available

to_channel_ts(rxcal_fn: str | pathlib.Path | None = None, scal_fn: str | pathlib.Path | None = None) mth5.timeseries.ChannelTS[source]

Convert to a ChannelTS object.

Parameters:
  • rxcal_fn (str, Path or None, optional) – Path to receiver calibration file, by default None

  • scal_fn (str, Path or None, optional) – Path to sensor calibration file, by default None

Returns:

Channel time series object with data, metadata, and calibration

Return type:

ChannelTS

class mth5.io.phoenix.readers.DecimatedContinuousReader(path: str | pathlib.Path, num_files: int = 1, report_hw_sat: bool = False, **kwargs)[source]

Bases: mth5.io.phoenix.readers.TSReaderBase

Class to create a streamer for continuous decimated time series.

This reader handles continuous decimated time series files such as ‘td_150’, ‘td_30’. These files have no sub header information.

Parameters:
  • path (str or Path) – Path to the time series file

  • num_files (int, optional) – Number of files in the sequence, by default 1

  • report_hw_sat (bool, optional) – Whether to report hardware saturation, by default False

  • **kwargs – Additional keyword arguments passed to parent TSReaderBase class

subheader

Empty dictionary as these files have no sub header information

Type:

dict

data_size

Size of the data sequence when read

Type:

int or None

subheader
data_size: int | None = None
property segment_start_time: mt_metadata.common.mttime.MTime

Estimate the segment start time based on sequence number.

The first sequence starts 1 second later than the set start time due to initiation within the data logger.

Returns:

Start time of the recording segment

Return type:

MTime

property segment_end_time: mt_metadata.common.mttime.MTime

Estimate end time of the segment.

The first sequence starts 1 second later than the set start time due to initiation within the data logger.

Returns:

Estimated end time from number of samples

Return type:

MTime

property sequence_start: mt_metadata.common.mttime.MTime

Get the sequence start time.

Returns:

Start time of the sequence

Return type:

MTime

property sequence_end: mt_metadata.common.mttime.MTime

Get the sequence end time.

Returns:

End time of the sequence based on data size or max samples

Return type:

MTime

read() numpy.ndarray[source]

Read in the full data from the current file.

Returns:

Single channel data array with dtype float32

Return type:

np.ndarray

read_sequence(start: int = 0, end: int | None = None) numpy.ndarray[source]

Read a sequence of files.

Parameters:
  • start (int, optional) – Starting index in the sequence, by default 0

  • end (int or None, optional) – Ending index in the sequence to read, by default None

Returns:

Data within the given sequence range as float32 array

Return type:

np.ndarray

to_channel_ts(rxcal_fn: str | pathlib.Path | None = None, scal_fn: str | pathlib.Path | None = None) mth5.timeseries.ChannelTS[source]

Convert to a ChannelTS object.

Parameters:
  • rxcal_fn (str, Path or None, optional) – Path to receiver calibration file, by default None

  • scal_fn (str, Path or None, optional) – Path to sensor calibration file, by default None

Returns:

Channel time series object with data, metadata, and calibration

Return type:

ChannelTS

class mth5.io.phoenix.readers.PhoenixConfig(fn: str | pathlib.Path | None = None, **kwargs: Any)[source]

Phoenix Geophysics configuration file reader and metadata container.

This class reads and provides access to Phoenix MTU-5C instrument configuration data stored in JSON format. The configuration file contains recording parameters, instrument settings, and metadata used to control data acquisition.

Parameters:
  • fn (str, pathlib.Path, or None, optional) – Path to the Phoenix configuration file (typically config.json). If provided, the file will be validated for existence.

  • **kwargs (Any) – Additional keyword arguments (currently unused).

fn

Path to the configuration file.

Type:

pathlib.Path or None

obj

Parsed configuration object containing all settings.

Type:

Any or None

logger

Logger instance for debugging and error reporting.

Type:

loguru.Logger

Examples

>>> config = PhoenixConfig("config.json")
>>> config.read()
>>> station = config.station_metadata()
>>> print(f"Station ID: {station.id}")
obj: Any = None
logger: loguru.Logger
property fn: pathlib.Path | None

Path to the Phoenix configuration file.

Returns:

The path to the configuration file, or None if not set.

Return type:

pathlib.Path or None

read(fn: str | pathlib.Path | None = None) None[source]

Read and parse a Phoenix configuration file.

Loads and parses a Phoenix MTU-5C configuration file in JSON format. The parsed configuration is stored in the obj attribute and provides access to all recording parameters and instrument settings.

Parameters:

fn (str, pathlib.Path, or None, optional) – Path to the configuration file to read. If None, uses the previously set file path from the fn property.

Raises:
  • ValueError – If no file path is provided and none was previously set.

  • IOError – If the configuration file cannot be read or parsed.

Notes

The configuration file should be in Phoenix JSON format containing recording parameters, instrument settings, and metadata.

has_obj() bool[source]

Check if configuration data has been loaded.

Returns:

True if configuration data is loaded, False otherwise.

Return type:

bool

property auto_power_enabled: Any | None

Auto power enabled setting from configuration.

Returns:

The auto power enabled setting, or None if no configuration is loaded.

Return type:

Any or None

property config: Any | None

Main configuration section from the configuration file.

Returns:

The first configuration object containing recording parameters, or None if no configuration is loaded.

Return type:

Any or None

property empower_version: Any | None

EMPower software version from configuration.

Returns:

The EMPower software version, or None if no configuration is loaded.

Return type:

Any or None

property mtc150_reset: Any | None

MTC150 reset setting from configuration.

Returns:

The MTC150 reset setting, or None if no configuration is loaded.

Return type:

Any or None

property network: Any | None

Network configuration from configuration file.

Returns:

The network configuration settings, or None if no configuration is loaded.

Return type:

Any or None

property receiver: Any | None

Receiver configuration from configuration file.

Returns:

The receiver configuration settings, or None if no configuration is loaded.

Return type:

Any or None

property schedule: Any | None

Recording schedule from configuration file.

Returns:

The recording schedule configuration, or None if no configuration is loaded.

Return type:

Any or None

property surveyTechnique: Any | None

Survey technique setting from configuration file.

Returns:

The survey technique setting, or None if no configuration is loaded.

Return type:

Any or None

property timezone: Any | None

Timezone setting from configuration file.

Returns:

The timezone setting, or None if no configuration is loaded.

Return type:

Any or None

property timezone_offset: Any | None

Timezone offset from configuration file.

Returns:

The timezone offset in hours, or None if no configuration is loaded.

Return type:

Any or None

property version: Any | None

Configuration file version from configuration file.

Returns:

The configuration file version, or None if no configuration is loaded.

Return type:

Any or None

station_metadata() mt_metadata.timeseries.Station[source]

Create a Station metadata object from configuration data.

Extracts station information from the loaded configuration and creates a standardized Station metadata object with basic station parameters.

Returns:

A Station metadata object populated with configuration data including station ID, operator information, company name, and notes.

Return type:

Station

Raises:

AttributeError – If no configuration is loaded or required fields are missing.

Notes

The method extracts the following information from config.layout: - Station_Name -> station.id - Operator -> station.acquired_by.name - Company_Name -> station.acquired_by.organization - Notes -> station.comments

Examples

>>> config = PhoenixConfig("config.json")
>>> config.read()
>>> station = config.station_metadata()
>>> print(f"Station: {station.id}")
class mth5.io.phoenix.readers.PhoenixReceiverMetadata(fn: str | pathlib.Path | None = None, **kwargs: Any)[source]

Container for Phoenix Geophysics recmeta.json metadata files.

This class reads and parses receiver metadata from JSON configuration files used to control Phoenix Geophysics MTU-5C data recording systems. It provides methods to extract channel configurations, instrument settings, and convert them to standardized metadata objects.

Parameters:
  • fn (str, Path, or None, optional) – Path to the recmeta.json file. If provided, the file will be read automatically during initialization.

  • **kwargs – Additional keyword arguments (currently unused).

fn

Path to the metadata file.

Type:

Path or None

obj

Parsed JSON content as a SimpleNamespace object.

Type:

SimpleNamespace or None

logger

Logger instance for error reporting.

Type:

loguru.Logger

Raises:

IOError – If the specified file does not exist.

Examples

>>> metadata = PhoenixReceiverMetadata("recmeta.json")
>>> channel_map = metadata.channel_map
>>> e1_config = metadata.e1_metadata

Notes

The class supports both electric and magnetic channel configurations with automatic mapping from Phoenix-specific parameter names to standardized metadata attributes.

property fn: pathlib.Path | None

Path to the metadata file.

Returns:

Path to the recmeta.json file, or None if not set.

Return type:

Path or None

obj: types.SimpleNamespace | None = None
logger
property instrument_id: str | None

Instrument identifier from metadata.

Returns:

Instrument ID if available, None otherwise.

Return type:

str or None

read(fn: str | pathlib.Path | None = None) None[source]

Read a recmeta.json file in Phoenix format.

Parameters:

fn (str, Path, or None, optional) – Path to the JSON file. If None, uses the current fn property.

Raises:
  • IOError – If no file path is specified or file doesn’t exist.

  • ValueError – If the file cannot be parsed as JSON.

has_obj() bool[source]

Check if metadata object is loaded.

Returns:

True if metadata object exists, False otherwise.

Return type:

bool

property channel_map: dict[int, str]

Channel mapping from index to component tag.

Returns:

Dictionary mapping channel indices to component tags (lowercase).

Return type:

dict[int, str]

Raises:

AttributeError – If metadata object is not loaded or missing channel_map.

property lp_filter_base_name: str | None

Base name for low-pass filter identifiers.

Returns:

Filter base name combining receiver info, or None if not available.

Return type:

str or None

get_ch_index(tag: str) int[source]

Get channel index from component tag.

Parameters:

tag (str) – Component tag (e.g., ‘e1’, ‘h1’, etc.).

Returns:

Channel index corresponding to the tag.

Return type:

int

Raises:
  • ValueError – If the tag is not found in the channel map.

  • AttributeError – If metadata object is not loaded.

get_ch_tag(index: int) str[source]

Get component tag from channel index.

Parameters:

index (int) – Channel index.

Returns:

Component tag corresponding to the index.

Return type:

str

Raises:
  • ValueError – If the index is not found in the channel map.

  • AttributeError – If metadata object is not loaded.

property e1_metadata: mt_metadata.timeseries.Electric

Electric channel 1 metadata.

property e2_metadata: mt_metadata.timeseries.Electric

Electric channel 2 metadata.

property h1_metadata: mt_metadata.timeseries.Magnetic

Magnetic channel 1 metadata.

property h2_metadata: mt_metadata.timeseries.Magnetic

Magnetic channel 2 metadata.

property h3_metadata: mt_metadata.timeseries.Magnetic

Magnetic channel 3 metadata.

property h4_metadata: mt_metadata.timeseries.Magnetic

Magnetic channel 4 metadata.

property h5_metadata: mt_metadata.timeseries.Magnetic

Magnetic channel 5 metadata.

property h6_metadata: mt_metadata.timeseries.Magnetic

Magnetic channel 6 metadata.

get_ch_metadata(index: int) mt_metadata.timeseries.Electric | mt_metadata.timeseries.Magnetic[source]

Get channel metadata from index.

Parameters:

index (int) – Channel index.

Returns:

Channel metadata object corresponding to the index.

Return type:

Electric or Magnetic

Raises:
  • ValueError – If index is not found in channel map.

  • AttributeError – If the corresponding metadata property doesn’t exist.

property run_metadata: mt_metadata.timeseries.Run

Run metadata from receiver configuration.

Returns:

Run metadata object with data logger and timing information.

Return type:

Run

property station_metadata: mt_metadata.timeseries.Station

Station metadata from receiver configuration.

Returns:

Station metadata object with location and acquisition information.

Return type:

Station

property survey_metadata: mt_metadata.timeseries.Survey

Survey metadata from receiver configuration.

Returns:

Survey metadata object with survey information.

Return type:

Survey

class mth5.io.phoenix.readers.MTUTable(file_path: str | pathlib.Path | None = None, **kwargs)[source]

The Phoenix TBL file is a series of 25-byte blocks containing key-value pairs: - Bytes 0-11: Tag name (4-character string, null-padded) - Bytes 12-24: Value (13 bytes, mixed data types)

Values can be decoded as follows: 1. INT (4 bytes): struct.unpack(‘<i’, bytes[0:4]) - Little-endian signed int 2. DOUBLE (8 bytes): struct.unpack(‘<d’, bytes[0:8]) - Little-endian double 3. CHAR (variable): bytes.decode(‘latin-1’).strip() - Null-terminated string 4. BYTE (1 byte): struct.unpack(‘<B’, bytes[0:1]) - Unsigned byte 5. TIME (6 bytes): [sec, min, hour, day, month, year-2000] format

The TBL_TAG_TYPES dictionary maps each known tag to its data type, enabling automatic decoding via decode_tbl_value() function. Unknown tags return raw bytes.

Example usage:

# Automatic decoding: tbl_dict = get_dictionary_from_tbl(‘file.TBL’, decode_values=True)

# Manual decoding with read_tbl (legacy): info = read_tbl(‘/path’, ‘file.TBL’)

read_tbl - reads a (binary) TBL table file of the legacy Phoenix format (MTU-5A) and output the “info” metadata dictionary.

Parameters:
  • fpath – path to the tbl

  • fname – name of the tbl file (including extensions)

Returns:

output dict of the TBL metadata

Return type:

info

SITE: site name SNUM: serial number (of the box) FILE: file name recorded CMPY: company/institute of the survey SRVY: survey project name EXLN: Ex channel dipole length EYLN: Ey channel dipole length NREF: North reference (true, or magnetic north) LNGG: longitude in degree-minute format (DDD MM.MM) LATG: latitude in degree-minute format (DD MM.MM) ELEV: elevation (in metres) HXSN: Hx channel coil serial number HYSN: Hy channel coil serial number HZSN: Hz channel coil serial number STIM: starting time (UTC) ETIM: ending time (UTC) LFRQ: powerline frequency for filtering (can only be 50 or 60 Hz) HGN: final H-channel gain HGNC: H-channel gain control: HGN = PA * 2^HGNC (note: PA =

PreAmplifier gain)

EGN: final E-channel gain EGNC: E-channel gain control: HGN = PA * 2^HGNC (note: PA =

PreAmplifier gain)

HSMP: L3 and L4 time slot in second (MTU-5A) or minute (MTU-5P),

this means the instrument will record L3NS seconds for L3 and L4NS seconds for L4, for every HSMP time slot.

L3NS: L3 sample time (in second) L4NS: L4 sample time (in second) SRL3: L3 sample rate SRL4: L4 sample rate SRL5: L5 sample rate HATT: H channel attenuation (1/4.3 for MTU-5A) HNOM: H channel normalization (mA/nT) TCMB: Type of comb filter (probably used to suppress the harmonics of the

powerline noise.

TALS: Type of anti-aliasing filter LPFR: Parameter of Low-pass/VLF filter. this is a quite complicated

part as the low-pass filter is simply an R-C circuit with a switch to connect to different capacitors. To ensure enough bandwidth (proportion to 1/RC), one should use smaller capacitors with larger ground resistance.

ACDC: AC/DC coupling (DC = 0, AC = 1; MT should always be DC) FSCV: full scaling A-D converter voltage (in unit of V) ======================================================================= note: Phoenix Legacy TBL is a straight-forward parameter-value metadata file, stored in a bizarre format. The parameter tag and value are stored in a series of 25-byte data blocks, in mixed data type: the first 12 bytes are reserved for the tag name (first 4 bytes as char). The values are stored in the 13 bytes afterwards, in various formats (char, int, float, etc.).

So a good practice is to read in those blocks one by one and extract all of them. However, not every thing is useful for the metadata, so I only extract a few of them, for now.

Original author: Hao 2012.07.04 Beijing

Translated to Python and enhanced by: J. Peacock (2025-12-31)

Main changes:

  • Encapsulated in MTUTable class

  • Automatic type detection and decoding based on TBL_TAG_TYPES

  • Added properties to extract metadata as mt_metadata objects


file_path
tbl_dict: dict[str, int | float | str | bytes]
TBL_TAG_TYPES
decode_tbl_value(value_bytes: bytes, data_type: str) int | float | str | bytes[source]

Decode TBL value bytes based on the specified data type.

Parameters:
  • value_bytes (bytes) – 13 bytes from position 12-24 in the 25-byte block containing the value.

  • data_type (str) – Type of the data: ‘int’, ‘double’, ‘char’, ‘byte’, or ‘time’.

Returns:

Decoded value in appropriate Python type. Returns raw bytes if decoding fails or data_type is unrecognized.

Return type:

int or float or str or bytes

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> value = tbl.decode_tbl_value(b'š...', 'int')
>>> print(value)
1690
read_tbl() None[source]

Read and decode the TBL file, populating the tbl_dict attribute.

This method reads the TBL file specified during initialization and decodes all tag-value pairs according to their known types. The results are stored in self.tbl_dict.

Returns:

Results are stored in the tbl_dict attribute.

Return type:

None

Examples

>>> tbl = MTUTable('/data/phoenix', '1690C16C.TBL')
>>> tbl.read_tbl()
>>> print(tbl.tbl_dict['SITE'])
'10441W10'
>>> print(tbl.tbl_dict['SNUM'])
1690
property channel_keys: dict[str, int]

Get list of channel keys present in the TBL metadata.

Returns:

Dictionary of channel keys and their corresponding values found in tbl_dict (e.g., ‘CHEX’, ‘CHEY’, ‘CHHX’, etc.).

Return type:

dict[str, int]

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> tbl.read_tbl()
>>> keys = tbl.channel_keys
>>> print(keys)
{'ex': 1, 'ey': 2, 'hx': 3, 'hy': 4, 'hz': 5}
property survey_metadata: mt_metadata.timeseries.Survey

Extract survey metadata from TBL file.

Returns:

mt_metadata Survey object populated with survey-level information from the TBL file (survey ID, company/author).

Return type:

Survey

Notes

If TBL metadata has not been loaded (via read_tbl()), returns an empty Survey object with a warning.

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> tbl.read_tbl()
>>> survey = tbl.survey_metadata
>>> print(survey.id)
'MT_Survey_2024'
property station_metadata: mt_metadata.timeseries.Station

Extract station metadata from TBL file.

Returns:

mt_metadata Station object populated with station-level information including location (latitude, longitude, elevation, declination) and time period.

Return type:

Station

Notes

If TBL metadata has not been loaded (via read_tbl()), returns an empty Station object with a warning.

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> tbl.read_tbl()
>>> station = tbl.station_metadata
>>> print(station.id)
'10441W10'
>>> print(f"{station.location.latitude:.6f}")
41.006467
property run_metadata: mt_metadata.timeseries.Run

Extract run metadata from TBL file.

Returns:

mt_metadata Run object populated with data logger information and channel metadata.

Return type:

Run

Notes

If TBL metadata has not been loaded (via read_tbl()), returns an empty Run object with a warning.

The run includes all channel metadata (ex, ey, hx, hy, hz) obtained from their respective property methods.

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> tbl.read_tbl()
>>> run = tbl.run_metadata
>>> print(run.id)
'run_1690'
>>> print(run.data_logger.id)
'MTU_1690'
property ex_metadata: mt_metadata.timeseries.Electric

Extract Ex electric channel metadata from TBL file.

Returns:

mt_metadata Electric object for Ex component with dipole length, azimuth, AC/DC start values, and channel number.

Return type:

Electric

Notes

If TBL metadata has not been loaded (via read_tbl()), returns an empty Electric object with a warning.

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> tbl.read_tbl()
>>> ex = tbl.ex_metadata
>>> print(ex.dipole_length)
100.0
property ey_metadata: mt_metadata.timeseries.Electric

Extract Ey electric channel metadata from TBL file.

Returns:

mt_metadata Electric object for Ey component with dipole length, azimuth (Ex azimuth + 90°), AC/DC start values, and channel number.

Return type:

Electric

Notes

If TBL metadata has not been loaded (via read_tbl()), returns an empty Electric object with a warning.

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> tbl.read_tbl()
>>> ey = tbl.ey_metadata
>>> print(ey.dipole_length)
100.0
property hx_metadata: mt_metadata.timeseries.Magnetic

Extract Hx magnetic channel metadata from TBL file.

Returns:

mt_metadata Magnetic object for Hx component with maximum field, channel number, azimuth, and sensor serial number.

Return type:

Magnetic

Notes

If TBL metadata has not been loaded (via read_tbl()), returns an empty Magnetic object with a warning.

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> tbl.read_tbl()
>>> hx = tbl.hx_metadata
>>> print(hx.sensor.id)
'coil1693'
property hy_metadata: mt_metadata.timeseries.Magnetic

Extract Hy magnetic channel metadata from TBL file.

Returns:

mt_metadata Magnetic object for Hy component with maximum field, channel number, azimuth (Hx azimuth + 90°), and sensor serial number.

Return type:

Magnetic

Notes

If TBL metadata has not been loaded (via read_tbl()), returns an empty Magnetic object with a warning.

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> tbl.read_tbl()
>>> hy = tbl.hy_metadata
>>> print(hy.sensor.id)
'coil1694'
property hz_metadata: mt_metadata.timeseries.Magnetic

Extract Hz magnetic channel metadata from TBL file.

Returns:

mt_metadata Magnetic object for Hz component with maximum field, channel number, and sensor serial number.

Return type:

Magnetic

Notes

If TBL metadata has not been loaded (via read_tbl()), returns an empty Magnetic object with a warning.

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> tbl.read_tbl()
>>> hz = tbl.hz_metadata
>>> print(hz.sensor.id)
'coil1695'
property ex_calibration: float | None

Calculate Ex channel calibration factor.

Returns:

Calibration factor to convert raw ADC values to mV/km. Returns None if TBL metadata has not been loaded.

Return type:

float or None

Notes

The calibration factor is calculated as:

\text{cal} = \frac{\text{FSCV}}{2^{23}} \times \frac{1000}{\text{EGN}} \times \frac{1000}{\text{EXLN}}

where:

  • FSCV: Full-scale converter voltage

  • EGN: Electric channel gain

  • EXLN: Ex dipole length in meters

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> tbl.read_tbl()
>>> cal = tbl.ex_calibration
>>> print(f"{cal:.6f}")
0.000762
property ey_calibration: float | None

Calculate Ey channel calibration factor.

Returns:

Calibration factor to convert raw ADC values to mV/km. Returns None if TBL metadata has not been loaded.

Return type:

float or None

Notes

The calibration factor is calculated as:

\text{cal} = \frac{\text{FSCV}}{2^{23}} \times \frac{1000}{\text{EGN}} \times \frac{1000}{\text{EYLN}}

where:

  • FSCV: Full-scale converter voltage

  • EGN: Electric channel gain

  • EYLN: Ey dipole length in meters

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> tbl.read_tbl()
>>> cal = tbl.ey_calibration
>>> print(f"{cal:.6f}")
0.000762
property magnetic_calibration: float | None

Calculate magnetic channel calibration factor.

Returns:

Calibration factor to convert raw ADC values to nT. Returns None if TBL metadata has not been loaded.

Return type:

float or None

Notes

The calibration factor is calculated as:

\text{cal} = \frac{\text{FSCV}}{2^{23}} \times \frac{1000}{\text{HGN} \times \text{HATT} \times \text{HNOM}}

where:

  • FSCV: Full-scale converter voltage

  • HGN: Magnetic channel gain

  • HATT: Magnetic channel attenuation

  • HNOM: Magnetic channel normalization (mA/nT)

This calibration applies to all magnetic channels (Hx, Hy, Hz).

Examples

>>> tbl = MTUTable('/data', 'file.TBL')
>>> tbl.read_tbl()
>>> cal = tbl.magnetic_calibration
>>> print(f"{cal:.9f}")
0.000000229
class mth5.io.phoenix.readers.MTUTSN(file_path: str | pathlib.Path | None = None, **kwargs)[source]

Reader for legacy Phoenix MTU-5A instrument time series binary files.

Reads time series data from Phoenix MTU-5A (.TS2, .TS3, .TS4, .TS5) and V5-2000 system (.TSL, .TSH) binary files. The data consists of 24-bit signed integers organized in data blocks with headers.

Parameters:

file_path (str or Path or None, optional) – Path to the TSN file to read. If None, the reader is created without loading data. Default is None.

file_path

Path to the currently loaded TSN file.

Type:

Path or None

ts

Time series data array with shape (n_channels, n_samples).

Type:

ndarray or None

tag

Metadata dictionary containing file information.

Type:

dict

Examples

Read a TS3 file:

>>> from pathlib import Path
>>> reader = MTUTSN('data/1690C16C.TS3')
>>> print(reader.ts.shape)
(3, 86400)
>>> print(reader.tag['sample_rate'])
24

Create reader without loading data:

>>> reader = MTUTSN()
>>> reader.read('data/1690C16C.TS3')

Access metadata:

>>> reader = MTUTSN('data/1690C16C.TS4')
>>> reader.read()
>>> print(f"Channels: {reader.tag['n_ch']}")
Channels: 4
>>> print(f"Blocks: {reader.tag['n_block']}")
Blocks: 48
property file_path: pathlib.Path | None

Get the TSN file path.

ts = None
ts_metadata = None
get_sign24(x: numpy.ndarray | list | int) numpy.ndarray[source]

Convert unsigned 24-bit integers to signed integers.

Converts unsigned 24-bit values (0 to 16777215) to their signed equivalents (-8388608 to 8388607) by applying two’s complement.

Parameters:

x (ndarray or list or int) – Unsigned 24-bit integer value(s) to convert.

Returns:

Signed 24-bit integer value(s) as int32 array.

Return type:

ndarray

Examples

Convert a single positive value:

>>> reader = MTUTSN()
>>> reader.get_sign24(100)
array([100], dtype=int32)

Convert a single negative value (unsigned representation):

>>> reader.get_sign24(16777215)  # -1 in 24-bit signed
array([-1], dtype=int32)

Convert an array:

>>> values = np.array([0, 8388607, 8388608, 16777215])
>>> reader.get_sign24(values)
array([       0,  8388607, -8388608,       -1], dtype=int32)
read(file_path: str | pathlib.Path | None = None) None[source]

Read and parse a Phoenix MTU time series binary file.

Reads complete time series data from legacy Phoenix MTU-5A instrument files (.TS2, .TS3, .TS4, .TS5) or V5-2000 system files (.TSL, .TSH). Each file contains multiple data blocks with 24-bit signed integer samples organized by channel.

Parameters:

file_path (str or Path or None, optional) – Path to the TSN file to read. If None, uses the current file_path attribute. Default is None.

Returns:

  • ts (ndarray) – Time series data array with shape (n_channels, total_samples). Data type is float64. Each row represents one channel, and each column is a time sample.

  • tag (dict) – Metadata dictionary containing file information with keys:

    • ’box_number’ (int): Instrument serial number

    • ’ts_type’ (str): Instrument type (‘MTU-5’ or ‘V5-2000’)

    • ’sample_rate’ (int): Sampling frequency in Hz

    • ’n_ch’ (int): Number of channels

    • ’n_scan’ (int): Number of scans per data block

    • ’start’ (MTime): UTC timestamp of first sample

    • ’ts_length’ (float): Duration of each block in seconds

    • ’n_block’ (int): Total number of data blocks in file

Raises:
  • EOFError – If the file is empty or cannot be read.

  • ValueError – If the file has an unsupported extension or channel count.

  • FileNotFoundError – If the specified file does not exist.

Examples

Read a 3-channel TS3 file:

>>> reader = MTUTSN()
>>> ts, tag = reader.read('data/1690C16C.TS3')
>>> print(f"Shape: {ts.shape}")
Shape: (3, 86400)
>>> print(f"Sample rate: {tag['sample_rate']} Hz")
Sample rate: 24 Hz
>>> print(f"Duration: {ts.shape[1] / tag['sample_rate']:.1f} seconds")
Duration: 3600.0 seconds

Read a 4-channel TS4 file:

>>> reader = MTUTSN('data/1690C16C.TS4')
>>> print(f"Channels: {reader.tag['n_ch']}")
Channels: 4
>>> print(f"Start time: {reader.tag['start'].isoformat()}")
Start time: 2016-07-16T00:00:00+00:00

Read and process data:

>>> ts, tag = MTUTSN().read('data/station.TS5')
>>> # Calculate statistics for each channel
>>> for i in range(tag['n_ch']):
...     print(f"Ch{i} mean: {ts[i].mean():.2f}, std: {ts[i].std():.2f}")
Ch0 mean: 123.45, std: 456.78
Ch1 mean: -234.56, std: 567.89
...
to_runts(table_filepath: str | pathlib.Path | None = None, calibrate=True) mth5.timeseries.RunTS[source]

Create an MTUTable object from the TSN file and associated TBL file.

Parameters:

table_filepath (str or Path) – Path to the corresponding TBL file.

Returns:

An MTUTable object containing metadata from the TBL file.

Return type:

MTUTable

Examples

>>> reader = MTUTSN('data/1690C16C.TS3')
>>> mtu_table = reader.to_runts('data/1690C16C.TBL')
>>> print(mtu_table.metadata)
{...}