mth5.io.zen

Submodules

Classes

Z3DHeader

Read header information from a Z3D file and make each metadata entry an attribute.

Z3DSchedule

Parser for Z3D file schedule information and metadata.

Z3DMetadata

Read metadata information from a Z3D file and make each metadata entry an attribute.

Z3D

A class for reading and processing Z3D files output by Zen data loggers.

CoilResponse

Read ANT4 coil calibration files from Zonge (amtant.cal).

Z3DCollection

Collection manager for Z3D file operations and metadata processing.

Functions

read_z3d(→ mth5.timeseries.ChannelTS | None)

Read a Z3D file and return a ChannelTS object.

Package Contents

class mth5.io.zen.Z3DHeader(fn: str | pathlib.Path | None = None, fid: BinaryIO | None = None, **kwargs: Any)[source]

Read header information from a Z3D file and make each metadata entry an attribute.

Parameters:
  • fn (str or pathlib.Path, optional) – Full path to Z3D file.

  • fid (BinaryIO, optional) – File object (e.g., open(Z3Dfile, ‘rb’)).

  • **kwargs (dict) – Additional keyword arguments to set as attributes.

_header_len

Length of header in bits (512).

Type:

int

ad_gain

Gain of channel.

Type:

float or None

ad_rate

Sampling rate in Hz.

Type:

float or None

alt

Altitude of the station (not reliable).

Type:

float or None

attenchannelsmask

Attenuation channels mask.

Type:

str or None

box_number

ZEN box number.

Type:

float or None

box_serial

ZEN box serial number.

Type:

str or None

channel

Channel number of the file.

Type:

float or None

channelserial

Serial number of the channel board.

Type:

str or None

ch_factor

Channel factor (default 9.536743164062e-10).

Type:

float

channelgain

Channel gain (default 1.0).

Type:

float

duty

Duty cycle of the transmitter.

Type:

float or None

fid

File object.

Type:

BinaryIO or None

fn

Full path to Z3D file.

Type:

str or pathlib.Path or None

fpga_buildnum

Build number of one of the boards.

Type:

float or None

gpsweek

GPS week (default 1740).

Type:

int

header_str

Full header string.

Type:

bytes or None

lat

Latitude of station in degrees.

Type:

float or None

logterminal

Log terminal setting.

Type:

str or None

long

Longitude of the station in degrees.

Type:

float or None

main_hex_buildnum

Build number of the ZEN box in hexadecimal.

Type:

float or None

numsats

Number of GPS satellites.

Type:

float or None

old_version

Whether this is an old version Z3D file (default False).

Type:

bool

period

Period of the transmitter.

Type:

float or None

tx_duty

Transmitter duty cycle.

Type:

float or None

tx_freq

Transmitter frequency.

Type:

float or None

version

Version of the firmware.

Type:

float or None

Examples

>>> from mth5.io.zen import Z3DHeader
>>> Z3Dfn = r"/home/mt/mt01/mt01_20150522_080000_256_EX.Z3D"
>>> header_obj = Z3DHeader(fn=Z3Dfn)
>>> header_obj.read_header()
logger
fn: str | pathlib.Path | None = None
fid: BinaryIO | None = None
header_str: bytes | None = None
ad_gain: float | None = None
ad_rate: float | None = None
alt: float | None = None
attenchannelsmask: str | None = None
box_number: float | None = None
box_serial: str | None = None
channel: float | None = None
channelserial: str | None = None
duty: float | None = None
fpga_buildnum: float | None = None
gpsweek: int = 1740
lat: float | None = None
logterminal: str | None = None
long: float | None = None
main_hex_buildnum: float | None = None
numsats: float | None = None
period: float | None = None
tx_duty: float | None = None
tx_freq: float | None = None
version: float | None = None
old_version: bool = False
ch_factor: float = 9.536743164062e-10
channelgain: float = 1.0
property data_logger: str

Data logger name as ZEN{box_number}.

Returns:

Data logger name formatted as ‘ZEN’ followed by zero-padded box number.

Return type:

str

Raises:

TypeError – If box_number is None or cannot be converted to int.

read_header(fn: str | pathlib.Path | None = None, fid: BinaryIO | None = None) None[source]

Read the header information into appropriate attributes.

Parses the header information from a Z3D file and populates the object’s attributes with the extracted values. Supports both modern and legacy Z3D file formats.

Parameters:
  • fn (str or pathlib.Path, optional) – Full path to Z3D file. If None, uses the instance’s fn attribute.

  • fid (BinaryIO, optional) – File object (e.g., open(Z3Dfile, ‘rb’)). If None, uses the instance’s fid attribute or opens the file specified by fn.

Raises:

UnicodeDecodeError – If header bytes cannot be decoded as text.

Notes

This method reads the first 512 bytes of the Z3D file as the header. It supports two formats:

  1. Modern format: key=value pairs separated by newlines

  2. Legacy format: comma-separated key:value pairs

The method automatically detects legacy format and sets old_version=True.

Coordinate values (lat/long) are automatically converted from radians to degrees, with validation to ensure they fall within valid ranges.

Examples

>>> header_obj = Z3DHeader()
>>> header_obj.read_header("/path/to/file.Z3D")
>>> with open("/path/to/file.Z3D", "rb") as fid:
...     header_obj.read_header(fid=fid)
convert_value(key_string: str, value_string: str) float | str[source]

Convert the value to the appropriate units given the key.

Converts string values to appropriate types based on the key name. Special handling is provided for latitude and longitude values, which are converted from radians to degrees with validation.

Parameters:
  • key_string (str) – The metadata key name, used to determine conversion type.

  • value_string (str) – The string value to convert.

Returns:

Converted value. Returns float for numeric values, str for non-numeric values. Latitude and longitude values are converted from radians to degrees.

Return type:

float or str

Notes

  • Attempts to convert all values to float first

  • If conversion fails, returns original string

  • For keys containing ‘lat’, ‘lon’, or ‘long’: - Converts from radians to degrees using np.rad2deg - Validates latitude range (±90°), sets to 0.0 if invalid - Validates longitude range (±180°), sets to 0.0 if invalid

Examples

>>> header = Z3DHeader()
>>> header.convert_value("version", "4147")
4147.0
>>> header.convert_value("lat", "0.706816081")  # radians
40.49757833327694  # degrees
>>> header.convert_value("channelserial", "0xD474777C")
'0xD474777C'
class mth5.io.zen.Z3DSchedule(fn: str | pathlib.Path | None = None, fid: BinaryIO | None = None, **kwargs: Any)[source]

Parser for Z3D file schedule information and metadata.

Reads schedule information from Z3D files and creates object attributes for each metadata entry. Schedule data is stored at byte offset 512 in Z3D files and contains recording parameters, timing information, and instrument configuration settings.

The class preserves the original capitalization from the Z3D file format and provides automatic parsing of key-value pairs in the schedule section.

Parameters:
  • fn (Union[str, Path], optional) – Full path to Z3D file to read schedule information from. Can be string path or pathlib.Path object.

  • fid (BinaryIO, optional) – Open file object for reading Z3D file in binary mode. Example: open(‘file.z3d’, ‘rb’)

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

AutoGain

Auto gain setting for the recording channel [‘Y’ or ‘N’].

Type:

str or None

Comment

User comments or notes for the schedule configuration.

Type:

str or None

Date

Date when the schedule action was started in YYYY-MM-DD format.

Type:

str or None

Duty

Duty cycle percentage of the transmitter (0-100).

Type:

str or None

FFTStacks

Number of FFT stacks used by the transmitter.

Type:

str or None

Filename

Original filename that the ZEN instrument assigns to the recording.

Type:

str or None

Gain

Gain setting for the recording channel (e.g., ‘1.0000’).

Type:

str or None

Log

Data logging enabled flag [‘Y’ or ‘N’].

Type:

str or None

NewFile

Create new file for recording flag [‘Y’ or ‘N’].

Type:

str or None

Period

Base period setting for the transmitter in seconds.

Type:

str or None

RadioOn

Radio communication enabled flag [‘Y’, ‘N’, or ‘X’].

Type:

str or None

SR

Sampling rate in Hz (originally ‘S/R’ in file, converted to ‘SR’).

Type:

str or None

SamplesPerAcq

Number of samples per acquisition for transmitter mode.

Type:

str or None

Sleep

Sleep mode enabled flag [‘Y’ or ‘N’].

Type:

str or None

Sync

GPS synchronization enabled flag [‘Y’ or ‘N’].

Type:

str or None

Time

Time when the schedule action started in HH:MM:SS format (GPS time).

Type:

str or None

initial_start

Parsed start time as MTime object with GPS time flag enabled. Combines Date and Time attributes for timestamp calculation.

Type:

MTime

fn

Path to the Z3D file being processed.

Type:

Union[str, Path] or None

fid

File object for reading the Z3D file.

Type:

BinaryIO or None

meta_string

Raw schedule metadata string read from the file.

Type:

bytes or None

_header_len

Length of Z3D file header in bytes (512).

Type:

int

_schedule_metadata_len

Length of schedule metadata section in bytes (512).

Type:

int

logger

Loguru logger instance for debugging and status messages.

Type:

Logger

Notes

The Z3D file format stores schedule information at a fixed offset of 512 bytes from the beginning of the file. The schedule section is also 512 bytes long and contains key-value pairs in the format “Schedule.key = value”.

All schedule values are stored as strings to preserve the original format from the Z3D file. Boolean-like values use ‘Y’/’N’ convention.

The initial_start attribute automatically converts Date and Time into a GPS-corrected MTime object for accurate timestamp handling.

Examples

Read schedule from file path:

>>> from mth5.io.zen import Z3DSchedule
>>> from pathlib import Path
>>>
>>> # Using filename
>>> schedule = Z3DSchedule(fn="recording.z3d")
>>> schedule.read_schedule()
>>> print(f"Sampling rate: {schedule.SR} Hz")
>>> print(f"Start time: {schedule.initial_start}")

Read schedule from file object:

>>> with open("recording.z3d", "rb") as fid:
...     schedule = Z3DSchedule(fid=fid)
...     schedule.read_schedule()
...     print(f"Date: {schedule.Date}, Time: {schedule.Time}")
...     print(f"GPS Sync: {schedule.Sync}")

Access schedule attributes:

>>> schedule = Z3DSchedule()
>>> schedule.read_schedule(fn="recording.z3d")
>>>
>>> # Check recording configuration
>>> if schedule.Sync == 'Y':
...     print("GPS synchronization enabled")
>>> if schedule.Log == 'Y':
...     print("Data logging enabled")
>>>
>>> # Get numeric values (stored as strings)
>>> sample_rate = float(schedule.SR) if schedule.SR else 0
>>> gain_value = float(schedule.Gain) if schedule.Gain else 1.0
logger
fn: str | pathlib.Path | None = None
fid: BinaryIO | None = None
meta_string: bytes | None = None
AutoGain: str | None = None
Comment: str | None = None
Date: str | None = None
Duty: str | None = None
FFTStacks: str | None = None
Filename: str | None = None
Gain: str | None = None
Log: str | None = None
NewFile: str | None = None
Period: str | None = None
RadioOn: str | None = None
SR: str | None = None
SamplesPerAcq: str | None = None
Sleep: str | None = None
Sync: str | None = None
Time: str | None = None
initial_start: mt_metadata.common.mttime.MTime
read_schedule(fn: str | pathlib.Path | None = None, fid: BinaryIO | None = None) None[source]

Read and parse schedule metadata from Z3D file.

Reads the schedule information section from a Z3D file starting at byte offset 512 (after the header) and parses key-value pairs to populate object attributes. Automatically creates an MTime object for the initial start time using GPS time correction.

Parameters:
  • fn (Union[str, Path], optional) – Path to Z3D file to read. Overrides instance fn if provided. Can be string path or pathlib.Path object.

  • fid (BinaryIO, optional) – Open file object for reading Z3D file. Overrides instance fid if provided. Must be opened in binary mode (‘rb’).

Raises:
  • UnicodeDecodeError – If schedule metadata cannot be decoded as UTF-8 text.

  • IndexError – If schedule lines don’t match expected “Schedule.key = value” format.

  • ValueError – If Date/Time values cannot be parsed into valid MTime object.

Notes

The method performs the following steps: 1. Determines file source (fn parameter, fid parameter, or instance attributes) 2. Seeks to byte offset 512 (after Z3D header) 3. Reads 512 bytes of schedule metadata 4. Splits metadata into lines and parses key-value pairs 5. Sets object attributes for each parsed schedule entry 6. Creates MTime object from Date and Time with GPS correction

Schedule entries must follow the format “Schedule.key = value”. The “Schedule.” prefix is removed and “/” characters in keys are stripped (e.g., “S/R” becomes “SR”).

If both Date and Time are present, they are combined into an MTime object with GPS time correction applied automatically.

Examples

Read from file path:

>>> schedule = Z3DSchedule()
>>> schedule.read_schedule(fn="recording.z3d")
>>> print(f"Sampling rate: {schedule.SR}")

Read from open file object:

>>> with open("recording.z3d", "rb") as fid:
...     schedule = Z3DSchedule()
...     schedule.read_schedule(fid=fid)
...     print(f"GPS sync: {schedule.Sync}")

Read using instance attributes:

>>> schedule = Z3DSchedule(fn="recording.z3d")
>>> schedule.read_schedule()  # Uses instance fn
>>> print(f"Start time: {schedule.initial_start}")
class mth5.io.zen.Z3DMetadata(fn: str | pathlib.Path | None = None, fid: BinaryIO | None = None, **kwargs: Any)[source]

Read metadata information from a Z3D file and make each metadata entry an attribute.

The attributes are left in capitalization of the Z3D file format.

Parameters:
  • fn (str or pathlib.Path, optional) – Full path to Z3D file.

  • fid (BinaryIO, optional) – File object (e.g., open(Z3Dfile, ‘rb’)).

  • **kwargs (dict) – Additional keyword arguments to set as attributes.

_header_length

Length of header in bits (512).

Type:

int

_metadata_length

Length of metadata blocks (512).

Type:

int

_schedule_metadata_len

Length of schedule meta data (512).

Type:

int

board_cal

Board calibration array with frequency, rate, amplitude, phase.

Type:

np.ndarray or None

cal_ant

Antenna calibration information.

Type:

str or None

cal_board

Board calibration dictionary.

Type:

dict or None

cal_ver

Calibration version.

Type:

str or None

ch_azimuth

Channel azimuth.

Type:

str or None

ch_cmp

Channel component.

Type:

str or None

ch_length

Channel length (or number of coils).

Type:

str or None

ch_number

Channel number on the ZEN board.

Type:

str or None

ch_xyz1

Channel xyz location.

Type:

str or None

ch_xyz2

Channel xyz location.

Type:

str or None

ch_cres

Channel resistance.

Type:

str or None

coil_cal

Coil calibration array (frequency, amplitude, phase).

Type:

np.ndarray or None

fid

File object.

Type:

BinaryIO or None

find_metadata

Boolean flag for finding metadata.

Type:

bool

fn

Full path to Z3D file.

Type:

str or pathlib.Path or None

gdp_operator

Operator of the survey.

Type:

str or None

gdp_progver

Program version.

Type:

str or None

gdp_temp

GDP temperature.

Type:

str or None

gdp_volt

GDP voltage.

Type:

str or None

job_by

Job performed by.

Type:

str or None

job_for

Job for.

Type:

str or None

job_name

Job name.

Type:

str or None

job_number

Job number.

Type:

str or None

line_name

Survey line name.

Type:

str or None

m_tell

Location in the file where the last metadata block was found.

Type:

int

notes

Additional notes from metadata.

Type:

str or None

rx_aspace

Electrode spacing.

Type:

str or None

rx_sspace

Receiver spacing.

Type:

str or None

rx_xazimuth

X azimuth of electrode.

Type:

str or None

rx_xyz0

Receiver xyz coordinates.

Type:

str or None

rx_yazimuth

Y azimuth of electrode.

Type:

str or None

rx_zpositive

Z positive direction (default ‘down’).

Type:

str

station

Station name.

Type:

str or None

survey_type

Type of survey.

Type:

str or None

unit_length

Length units (m).

Type:

str or None

count

Counter for metadata blocks read.

Type:

int

Examples

>>> from mth5.io.zen import Z3DMetadata
>>> Z3Dfn = r"/home/mt/mt01/mt01_20150522_080000_256_EX.Z3D"
>>> header_obj = Z3DMetadata(fn=Z3Dfn)
>>> header_obj.read_metadata()
logger
fn: str | pathlib.Path | None = None
fid: BinaryIO | None = None
find_metadata: bool = True
board_cal: list | numpy.ndarray | None = None
coil_cal: list | numpy.ndarray | None = None
m_tell: int = 0
cal_ant: str | None = None
cal_board: Dict[str, Any] | None = None
cal_ver: str | None = None
ch_azimuth: str | None = None
ch_cmp: str | None = None
ch_length: str | None = None
ch_number: str | None = None
ch_xyz1: str | None = None
ch_xyz2: str | None = None
ch_cres: str | None = None
gdp_operator: str | None = None
gdp_progver: str | None = None
gdp_volt: str | None = None
gdp_temp: str | None = None
job_by: str | None = None
job_for: str | None = None
job_name: str | None = None
job_number: str | None = None
rx_aspace: str | None = None
rx_sspace: str | None = None
rx_xazimuth: str | None = None
rx_xyz0: str | None = None
rx_yazimuth: str | None = None
rx_zpositive: str = 'down'
line_name: str | None = None
survey_type: str | None = None
unit_length: str | None = None
station: str | None = None
count: int = 0
notes: str | None = None
read_metadata(fn: str | pathlib.Path | None = None, fid: BinaryIO | None = None) None[source]

Read metadata from Z3D file.

Parses the metadata blocks in a Z3D file and populates the object’s attributes with the extracted values. Also reads calibration data for both board and coil calibrations.

Parameters:
  • fn (str or pathlib.Path, optional) – Full path to file. If None, uses the instance’s fn attribute.

  • fid (BinaryIO, optional) – Open file object. If None, uses the instance’s fid attribute or opens the file specified by fn.

Raises:

UnicodeDecodeError – If metadata blocks cannot be decoded as text.

Notes

This method reads metadata blocks sequentially from the Z3D file, starting after the header and schedule metadata sections. It processes:

  • Standard metadata records with key=value pairs

  • Board calibration data (cal.brd format)

  • Coil calibration data (cal.ant format)

  • Calibration data blocks (caldata format)

The method automatically determines the station name from available metadata fields in the following priority: 1. line_name + rx_xyz0 (first coordinate) 2. rx_stn 3. ch_stn

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

A class for reading and processing Z3D files output by Zen data loggers.

This class handles the parsing of Z3D binary files which contain GPS-stamped time series data from magnetotelluric measurements. It provides methods for reading file headers, metadata, schedule information, and time series data, as well as converting between different units and formats.

Parameters:
  • fn (str or Path, optional) – Full path to the .Z3D file to be read. Default is None.

  • **kwargs (dict) –

    Additional keyword arguments including: - stamp_len : int, default 64

    GPS stamp length in bits

fn

Path to the Z3D file

Type:

Path or None

calibration_fn

Path to calibration file

Type:

str or None

header

Header information object

Type:

Z3DHeader

schedule

Schedule information object

Type:

Z3DSchedule

metadata

Metadata information object

Type:

Z3DMetadata

gps_stamps

Array of GPS time stamps

Type:

numpy.ndarray or None

time_series

Time series data array

Type:

numpy.ndarray or None

sample_rate

Data sampling rate in Hz

Type:

float or None

units

Data units, default ‘counts’

Type:

str

Notes

GPS data type is formatted as:

numpy.dtype([('flag0', numpy.int32),
             ('flag1', numpy.int32),
             ('time', numpy.int32),
             ('lat', numpy.float64),
             ('lon', numpy.float64),
             ('num_sat', numpy.int32),
             ('gps_sens', numpy.int32),
             ('temperature', numpy.float32),
             ('voltage', numpy.float32),
             ('num_fpga', numpy.int32),
             ('num_adc', numpy.int32),
             ('pps_count', numpy.int32),
             ('dac_tune', numpy.int32),
             ('block_len', numpy.int32)])

Examples

>>> from mth5.io.zen import Z3D
>>> z3d = Z3D(r"/path/to/data/station_20150522_080000_256_EX.Z3D")
>>> z3d.read_z3d()
>>> print(f"Found {z3d.gps_stamps.shape[0]} GPS time stamps")
>>> print(f"Found {z3d.time_series.size} data points")
logger
property fn: pathlib.Path | None

Get the Z3D file path.

Returns:

Path to the Z3D file, or None if not set.

Return type:

Path or None

calibration_fn = None
header
schedule
metadata
gps_stamps = None
gps_flag
num_sec_to_skip = 1
units = 'digital counts'
property sample_rate: float | None

Get the sampling rate in Hz.

Returns:

Data sampling rate in samples per second, or None if not available.

Return type:

float or None

time_series = None
ch_dict
property file_size: int

Get the size of the Z3D file in bytes.

Returns:

File size in bytes, or 0 if no file is set.

Return type:

int

property n_samples: int

Get the number of data samples in the file.

Returns:

Number of data samples. Calculated from file size if time_series is not loaded, otherwise returns the actual array size.

Return type:

int

Notes

Calculation assumes 4 bytes per sample and accounts for metadata blocks. If sample_rate is available, adds buffer for GPS stamps.

property station: str | None

Get the station name.

Returns:

Station identifier name.

Return type:

str or None

property dipole_length: float

Get the dipole length for electric field measurements.

Returns:

Dipole length in meters. Calculated from electrode positions if not directly specified in metadata. Returns 0 for magnetic channels or if positions are not available.

Return type:

float

Notes

Length is calculated from xyz coordinates using Euclidean distance formula when position data is available in metadata.

property azimuth: float | None

Get the azimuth of instrument setup.

Returns:

Azimuth angle in degrees from north, or None if not available.

Return type:

float or None

property component: str

Get the channel component identifier.

Returns:

Channel component name in lowercase (e.g., ‘ex’, ‘hy’, ‘hz’).

Return type:

str

property latitude: float | None

Get the latitude in decimal degrees.

Returns:

Latitude coordinate in decimal degrees, or None if not available.

Return type:

float or None

property longitude: float | None

Get the longitude in decimal degrees.

Returns:

Longitude coordinate in decimal degrees, or None if not available.

Return type:

float or None

property elevation: float | None

Get the elevation in meters.

Returns:

Elevation above sea level in meters, or None if not available.

Return type:

float or None

property start: mt_metadata.common.mttime.MTime

Get the start time of the data.

Returns:

Start time from GPS stamps if available, otherwise scheduled time.

Return type:

MTime

property end: mt_metadata.common.mttime.MTime | float

Get the end time of the data.

Returns:

End time from GPS stamps if available, otherwise calculated from start time and number of samples.

Return type:

MTime or float

property zen_schedule: mt_metadata.common.mttime.MTime

Get the zen schedule date and time.

Returns:

Scheduled start time from header or schedule object.

Return type:

MTime

property coil_number: str | None

Get the coil number identifier.

Returns:

Coil antenna number identifier, or None if not available.

Return type:

str or None

property channel_number: int

Get the channel number.

Returns:

Channel number identifier. Maps component names to standard channel numbers or uses metadata channel number.

Return type:

int

property channel_metadata

Generate Channel metadata object from Z3D file information.

Creates either an Electric or Magnetic metadata object based on the component type, populated with channel-specific parameters, sensor information, and data statistics.

Returns:

Channel metadata object appropriate for the measurement type: - Electric: includes dipole length, AC/DC statistics - Magnetic: includes sensor details, field min/max values

Return type:

Electric or Magnetic

Notes

Electric channels (ex, ey) get dipole length and voltage statistics. Magnetic channels (hx, hy, hz) get sensor information and field strength statistics computed from the first and last seconds of data.

Examples

>>> z3d = Z3D("/path/to/file.Z3D")
>>> z3d.read_z3d()
>>> ch_meta = z3d.channel_metadata
>>> print(f"Channel component: {ch_meta.component}")
property station_metadata

Generate Station metadata object from Z3D file information.

Creates a Station metadata object populated with location and timing information extracted from the Z3D file header and metadata.

Returns:

Station metadata object with populated fields including station ID, coordinates, elevation, time period, and operator information.

Return type:

Station

Examples

>>> z3d = Z3D("/path/to/file.Z3D")
>>> z3d.read_all_info()
>>> station_meta = z3d.station_metadata
>>> print(station_meta.id)
property run_metadata

Generate Run metadata object from Z3D file information.

Creates a Run metadata object populated with data logger information, timing details, and measurement parameters extracted from the Z3D file.

Returns:

Run metadata object with populated fields including data logger details, sample rate, time period, and data type information.

Return type:

Run

Examples

>>> z3d = Z3D("/path/to/file.Z3D")
>>> z3d.read_all_info()
>>> run_meta = z3d.run_metadata
>>> print(f"Sample rate: {run_meta.sample_rate}")
property counts2mv_filter

Create a counts to milliVolt coefficient filter.

Generate a coefficient filter for converting digital counts to milliVolt using the channel factor from the Z3D file header.

Returns:

Filter object configured for counts to milliVolt conversion with gain set to the inverse of the channel factor.

Return type:

CoefficientFilter

Notes

The gain is set to 1/channel_factor because this represents the inverse operation when the instrument response has been divided from the data during processing.

Examples

>>> z3d = Z3D("/path/to/file.Z3D")
>>> z3d.read_all_info()
>>> filter_obj = z3d.counts2mv_filter
>>> print(f"Conversion gain: {filter_obj.gain}")
property coil_response

Make the coile response into a FAP filter

Phase must be in radians

property zen_response

Zen response, not sure the full calibration comes directly from the Z3D file, so skipping for now. Will have to read a Zen##.cal file to get the full calibration. This shouldn’t be a big issue cause it should roughly be the same for all channels and since the TF is computing the ratio they will cancel out. Though we should look more into this if just looking at calibrate time series.

property channel_response

Generate comprehensive channel response for the Z3D data.

Creates a ChannelResponse object containing all applicable filters including coil response, dipole conversion, and counts-to-milliVolt transformation.

Returns:

Channel response object with appropriate filter chain for converting raw Z3D data to physical units.

Return type:

ChannelResponse

Notes

The filter chain includes: - Coil response (for magnetic channels) or dipole filter (for electric) - Counts to milliVolt conversion filter

property dipole_filter

Create dipole conversion filter for electric field measurements.

Generate a coefficient filter for converting electric field measurements from milliVolt per kilometer to milliVolt using the dipole length.

Returns:

Filter object for dipole conversion if dipole_length is non-zero, None otherwise.

Return type:

CoefficientFilter or None

Notes

The gain is set to dipole_length/1000 to convert from mV/km to mV. This represents the physical dipole length scaling for electric field measurements.

Examples

>>> z3d = Z3D("/path/to/electric.Z3D")
>>> z3d.read_all_info()
>>> if z3d.dipole_filter is not None:
...     print(f"Dipole length: {z3d.dipole_length} m")
read_all_info() None[source]

Read header, schedule, and metadata from Z3D file.

Convenience method to read all file information in one call. Opens the file once and reads all sections sequentially.

Raises:

FileNotFoundError – If the Z3D file does not exist.

read_z3d(z3d_fn: str | pathlib.Path | None = None) None[source]

Read and parse Z3D file data.

Comprehensive method to read a Z3D file and populate all object attributes. Performs the following operations:

  1. Read file as chunks of 32-bit integers

  2. Extract and validate GPS stamps

  3. Check GPS time stamp consistency (1 second intervals)

  4. Verify data block lengths match sampling rate

  5. Convert GPS time to seconds relative to GPS week

  6. Skip initial buffered data (first 2 seconds)

  7. Populate time series array with non-zero data

Parameters:

z3d_fn (str, Path, or None, optional) – Path to Z3D file to read. If None, uses current fn attribute.

Raises:

ZenGPSError – If data is too short or GPS timing issues prevent parsing.

Examples

>>> z3d = Z3D(r"/path/to/data/station_20150522_080000_256_EX.Z3D")
>>> z3d.read_z3d()
>>> print(f"Read {z3d.time_series.size} data points")
get_gps_stamp_index(ts_data: numpy.ndarray, old_version: bool = False) list[int][source]

Locate GPS time stamp indices in time series data.

Searches for GPS flag patterns in the data array. For newer files, verifies that flag_1 follows flag_0.

Parameters:
  • ts_data (numpy.ndarray) – Time series data array containing GPS stamps.

  • old_version (bool, default False) – If True, only searches for single GPS flag (old format). If False, validates flag pairs (new format).

Returns:

List of indices where GPS stamps are located.

Return type:

list of int

trim_data() None[source]

Trim the first 2 seconds of data due to SD buffer issues.

Remove the first 2 GPS stamps and corresponding time series data to account for SD card buffering artifacts in early data.

Notes

This method may be deprecated after field testing confirms the buffer behavior is consistent across all instruments.

Deprecated since version This: method will be deprecated after field testing.

check_start_time() mt_metadata.common.mttime.MTime[source]

Validate scheduled start time against first GPS stamp.

Compare the scheduled start time from the file header with the actual first GPS timestamp to identify timing discrepancies.

Returns:

UTC start time from the first valid GPS stamp.

Return type:

MTime

Notes

Logs warnings if the difference exceeds the maximum allowed time difference (default 20 seconds).

validate_gps_time() bool[source]

Validate that GPS time stamps are consistently 1 second apart.

Returns:

True if all GPS stamps are properly spaced, False otherwise.

Return type:

bool

Notes

Logs debug information for any stamps that are more than 1 second apart.

validate_time_blocks() bool[source]

Validate GPS time stamps and verify data block lengths.

Check that each GPS stamp block contains the expected number of data points (should equal sample rate for 1-second blocks).

Returns:

True if all blocks have correct length, False otherwise.

Return type:

bool

Notes

If bad blocks are detected near the beginning (index < 5), this method will automatically skip those blocks and trim the time series data accordingly.

convert_gps_time() None[source]

Convert GPS time integers to floating point seconds.

Transform GPS time from integer format to float and convert from GPS time units to seconds relative to the GPS week.

Notes

GPS time is initially stored as integers in units of 1/1024 seconds. This method converts to floating point seconds and applies the necessary scaling factors.

convert_counts_to_mv(data: numpy.ndarray) numpy.ndarray[source]

Convert time series data from counts to milliVolt.

Parameters:

data (numpy.ndarray) – Time series data in digital counts.

Returns:

Time series data converted to milliVolt.

Return type:

numpy.ndarray

convert_mv_to_counts(data: numpy.ndarray) numpy.ndarray[source]

Convert time series data from milliVolt to counts.

Parameters:

data (numpy.ndarray) – Time series data in milliVolt.

Returns:

Time series data converted to digital counts.

Return type:

numpy.ndarray

Notes

Assumes no other scaling has been applied to the data.

get_gps_time(gps_int: int, gps_week: int = 0) tuple[float, int][source]

Convert GPS integer timestamp to seconds and GPS week.

Parameters:
  • gps_int (int) – Integer from the GPS time stamp line.

  • gps_week (int, default 0) – Relative GPS week. If seconds exceed one week, this is incremented.

Returns:

GPS time in seconds from beginning of GPS week, and updated GPS week.

Return type:

tuple[float, int]

Notes

GPS integers are in units of 1/1024 seconds. This method handles week rollovers when seconds exceed 604800.

get_UTC_date_time(gps_week: int, gps_time: float) mt_metadata.common.mttime.MTime[source]

Convert GPS week and time to UTC datetime.

Calculate the actual UTC date and time of measurement from GPS week number and seconds within that week.

Parameters:
  • gps_week (int) – GPS week number when data was collected.

  • gps_time (float) – Number of seconds from beginning of GPS week.

Returns:

UTC datetime object for the measurement time.

Return type:

MTime

Notes

Automatically handles GPS time rollover when seconds exceed one week (604800 seconds).

to_channelts() mth5.timeseries.ChannelTS[source]

Convert Z3D data to ChannelTS time series object.

Create a ChannelTS object populated with the time series data and all associated metadata from the Z3D file.

Returns:

Time series object with data, metadata, and instrument response.

Return type:

ChannelTS

mth5.io.zen.read_z3d(fn: str | pathlib.Path, calibration_fn: str | pathlib.Path | None = None, logger_file_handler: Any | None = None) mth5.timeseries.ChannelTS | None[source]

Read a Z3D file and return a ChannelTS object.

Convenience function to read Z3D files with error handling.

Parameters:
  • fn (str or Path) – Path to the Z3D file to read.

  • calibration_fn (str, Path, or None, optional) – Path to calibration file. Default is None.

  • logger_file_handler (optional) – Logger file handler to add to Z3D logger. Default is None.

Returns:

Time series object if successful, None if GPS timing errors occur.

Return type:

ChannelTS or None

Examples

>>> ts = read_z3d("/path/to/data/station_EX.Z3D")
>>> if ts is not None:
...     print(f"Read {ts.n_samples} samples")
class mth5.io.zen.CoilResponse(calibration_file: str | pathlib.Path | None = None, angular_frequency: bool = False)[source]

Read ANT4 coil calibration files from Zonge (amtant.cal).

This class parses a Zonge antenna calibration file and exposes a mt_metadata.timeseries.filters.FrequencyResponseTableFilter for a specified coil number.

Parameters:
  • calibration_file (str | Path | None, optional) – Path to the antenna calibration file. If provided the file will be read during initialization, by default None.

  • angular_frequency (bool, optional) – If True, reported frequencies will be converted to angular frequency (rad/s), by default False.

coil_calibrations

Mapping of coil serial numbers to a structured numpy array containing frequency, amplitude, and phase columns.

Type:

dict[str, numpy.ndarray]

Examples

>>> from mth5.mth5.io.zen.coil_response import CoilResponse
>>> cr = CoilResponse('amtant.cal')
>>> fap = cr.get_coil_response_fap(1234)
>>> print(fap.name)
logger
coil_calibrations: dict[str, numpy.ndarray]
property calibration_file
angular_frequency: bool = False
file_exists()[source]

Check to make sure the file exists

Returns:

True if it does, False if it does not

Return type:

boolean

read_antenna_file(antenna_calibration_file: str | pathlib.Path | None = None) None[source]

Read a Zonge antenna calibration file and parse coil responses.

The expected file format contains blocks starting with an “antenna” header line that provides the base frequency followed by lines with coil serial number and amplitude/phase values for the 6th and 8th harmonics.

Parameters:

antenna_calibration_file (str | Path | None, optional) – Optional path to the antenna calibration file. If provided, it overrides the instance calibration_file.

Notes

Phase values in the file are expected in milliradians and are converted to radians.

get_coil_response_fap(coil_number: int | str, extrapolate: bool = True) mt_metadata.timeseries.filters.FrequencyResponseTableFilter[source]

Read an amtant.cal file provided by Zonge.

Apparently, the file includes the 6th and 8th harmonic of the given frequency, which is a fancy way of saying f * 6 and f * 8.

Parameters:

coil_number (int or string) – ANT4 4 digit serial number

Returns:

Frequency look up table

Return type:

mt_metadata.timeseries.filters.FrequencyResponseTableFilter

extrapolate(fap: mt_metadata.timeseries.filters.FrequencyResponseTableFilter) mt_metadata.timeseries.filters.FrequencyResponseTableFilter[source]

Extrapolate a frequency/amplitude/phase table using log-linear pads.

Parameters:

fap (FrequencyResponseTableFilter) – Frequency response object to extrapolate.

Returns:

A copy of fap with low- and high-frequency extrapolated values appended.

Return type:

FrequencyResponseTableFilter

has_coil_number(coil_number: int | str | None) bool[source]

Test if coil number is in the antenna file

Parameters:

coil_number (int or string) – ANT4 serial number

Returns:

True if the coil is found, False if it is not

Return type:

boolean

class mth5.io.zen.Z3DCollection(file_path: str | pathlib.Path | None = None, **kwargs: Any)[source]

Bases: mth5.io.collection.Collection

Collection manager for Z3D file operations and metadata processing.

This class provides functionality to handle collections of Z3D files, including metadata extraction, station information management, and dataframe creation for analysis workflows.

Parameters:
  • file_path (str or Path, optional) – Path to directory containing Z3D files, by default None

  • **kwargs (dict) – Additional keyword arguments passed to parent Collection class

station_metadata_dict

Dictionary mapping station IDs to Station metadata objects

Type:

dict[str, Station]

file_ext

File extension for Z3D files (“z3d”)

Type:

str

Examples

>>> zc = Z3DCollection("/path/to/z3d/files")
>>> df = zc.to_dataframe(sample_rates=[256, 4096])
>>> print(df.head())
station_metadata_dict: dict[str, mt_metadata.timeseries.Station]
file_ext: str = 'z3d'
get_calibrations(antenna_calibration_file: str | pathlib.Path) mth5.io.zen.coil_response.CoilResponse[source]

Load coil calibration data from antenna calibration file.

Parameters:

antenna_calibration_file (str or Path) – Path to the antenna.cal file containing coil calibration data

Returns:

CoilResponse object containing calibration information for various coil serial numbers

Return type:

CoilResponse

Examples

>>> zc = Z3DCollection("/path/to/z3d/files")
>>> cal_obj = zc.get_calibrations("/path/to/antenna.cal")
>>> print(cal_obj.has_coil_number("2324"))
to_dataframe(sample_rates: list[int] = [256, 4096], run_name_zeros: int = 4, calibration_path: str | pathlib.Path | None = None) pandas.DataFrame[source]

Extract Z3D file information and create analysis-ready dataframe.

Processes all Z3D files in the collection, extracting metadata and file information to create a comprehensive dataframe suitable for magnetotelluric data analysis workflows.

Parameters:
  • sample_rates (list of int, default [256, 4096]) – Allowed sampling rates in Hz. Files with sample rates not in this list will trigger a warning and early return

  • run_name_zeros (int, default 4) – Number of zero-padding digits for run names in dataframe sorting

  • calibration_path (str or Path, optional) – Path to antenna calibration file. If None, calibration information will not be included, by default None

Returns:

Dataframe containing Z3D file information with columns: - survey: Survey/job name from Z3D metadata - station: Station identifier - run: Automatically assigned run names based on start times - start/end: ISO format timestamps for data recording period - channel_id: Channel number from Z3D file - component: Measurement component (ex, ey, hx, hy, hz) - fn: Path to Z3D file - sample_rate: Sampling frequency in Hz - file_size: Size of Z3D file in bytes - n_samples: Number of data samples in file - sequence_number: Sequential numbering within station - dipole: Dipole length in meters (for electric channels) - coil_number: Coil serial number (for magnetic channels) - latitude/longitude/elevation: Station coordinates - instrument_id: ZEN box identifier - calibration_fn: Path to calibration file if available

Return type:

pd.DataFrame

Raises:
  • AttributeError – If Z3D files contain invalid or missing required metadata

  • FileNotFoundError – If calibration_path is specified but file doesn’t exist

Examples

>>> zc = Z3DCollection("/path/to/z3d/files")
>>> df = zc.to_dataframe(sample_rates=[256, 4096],
...                      calibration_path="/path/to/antenna.cal")
>>> print(df[['station', 'component', 'sample_rate']].head())
>>> df.to_csv("/path/output/z3d_inventory.csv")

Notes

This method also populates the station_metadata_dict attribute with consolidated station metadata derived from all processed files.

assign_run_names(df: pandas.DataFrame, zeros: int = 3) pandas.DataFrame[source]

Assign standardized run names to dataframe based on start times.

Creates run names using the pattern ‘sr{sample_rate}_{block_number}’ where block_number is assigned sequentially based on unique start times within each station.

Parameters:
  • df (pd.DataFrame) – Input dataframe containing Z3D file information with at least ‘station’, ‘start’, and ‘sample_rate’ columns

  • zeros (int, default 3) – Number of zero-padding digits for block numbers in run names

Returns:

Modified dataframe with updated ‘run’ and ‘sequence_number’ columns assigned based on temporal ordering within each station

Return type:

pd.DataFrame

Examples

>>> zc = Z3DCollection()
>>> df = pd.DataFrame({
...     'station': ['001', '001', '002'],
...     'start': ['2022-01-01T10:00:00', '2022-01-01T12:00:00', '2022-01-01T10:00:00'],
...     'sample_rate': [256, 256, 4096]
... })
>>> df_with_runs = zc.assign_run_names(df, zeros=3)
>>> print(df_with_runs['run'].tolist())
['sr256_001', 'sr256_002', 'sr4096_001']

Notes

This method modifies the input dataframe in-place by updating the ‘run’ and ‘sequence_number’ columns. Start times are used to determine temporal ordering within each station.