Source code for mth5.io.zen.z3d_header
# -*- coding: utf-8 -*-
"""
====================
Zen Header
====================
* Tools for reading and writing files for Zen and processing software
* Tools for copying data from SD cards
* Tools for copying schedules to SD cards
Created on Tue Jun 11 10:53:23 2013
Updated August 2020 (JP)
:copyright:
Jared Peacock (jpeacock@usgs.gov)
:license:
MIT
"""
# ==============================================================================
import logging
import numpy as np
# ==============================================================================
[docs]class Z3DHeader:
"""
Read in the header information of a Z3D file and make each metadata
entry an attirbute.
:param fn: full path to Z3D file
:type fn: string or :class:`pathlib.Path`
:param fid: file object ex. open(Z3Dfile, 'rb')
:type fid: file
======================== ==================================================
Attributes Definition
======================== ==================================================
_header_len lenght of header in bits (512)
ad_gain gain of channel
ad_rate sampling rate in Hz
alt altitude of the station (not reliable)
attenchannelsmask not sure
box_number ZEN box number
box_serial ZEN box serial number
channel channel number of the file
channelserial serial number of the channel board
duty duty cycle of the transmitter
fpga_buildnum build number of one of the boards
gpsweek GPS week
header_str full header string
lat latitude of station
logterminal not sure
long longitude of the station
main_hex_buildnum build number of the ZEN box in hexidecimal
numsats number of gps satelites
period period of the transmitter
tx_duty transmitter duty cycle
tx_freq transmitter frequency
version version of the firmware
======================== ==================================================
:Example:
>>> import mtpy.usgs.zen as zen
>>> Z3Dfn = r"/home/mt/mt01/mt01_20150522_080000_256_EX.Z3D"
>>> header_obj = zen.Z3DHeader()
>>> header_obj.read_header()
"""
def __init__(self, fn=None, fid=None, **kwargs):
self.logger = logging.getLogger(
f"{__name__}.{self.__class__.__name__}"
)
self.fn = fn
self.fid = fid
self.header_str = None
self._header_len = 512
self.ad_gain = None
self.ad_rate = None
self.alt = None
self.attenchannelsmask = None
self.box_number = None
self.box_serial = None
self.channel = None
self.channelserial = None
self.duty = None
self.fpga_buildnum = None
self.gpsweek = 1740
self.lat = None
self.logterminal = None
self.long = None
self.main_hex_buildnum = None
self.numsats = None
self.period = None
self.tx_duty = None
self.tx_freq = None
self.version = None
self.old_version = False
self.ch_factor = 9.536743164062e-10
self.channelgain = 1.0
for key in kwargs:
setattr(self, key, kwargs[key])
@property
def data_logger(self):
"""Data logger name as ZEN{box_number}"""
return "ZEN{0:03}".format(int(self.box_number))
[docs] def read_header(self, fn=None, fid=None):
"""
Read the header information into appropriate attributes
:param fn: full path to Z3D file
:type fn: string or :class:`pathlib.Path`
:param fid: file object ex. open(Z3Dfile, 'rb')
:type fid: file
:Example:
>>> import mtpy.usgs.zen as zen
>>> Z3Dfn = r"/home/mt/mt01/mt01_20150522_080000_256_EX.Z3D"
>>> header_obj = zen.Z3DHeader()
>>> header_obj.read_header()
"""
if fn is not None:
self.fn = fn
if fid is not None:
self.fid = fid
if self.fn is None and self.fid is None:
self.logger.warning("No Z3D file to read.")
elif self.fn is None:
if self.fid is not None:
self.fid.seek(0)
self.header_str = self.fid.read(self._header_len)
elif self.fn is not None:
if self.fid is None:
self.fid = open(self.fn, "rb")
self.header_str = self.fid.read(self._header_len)
else:
self.fid.seek(0)
self.header_str = self.fid.read(self._header_len)
header_list = self.header_str.split(b"\n")
for h_str in header_list:
h_str = h_str.decode()
if h_str.find("=") > 0:
h_list = h_str.split("=")
h_key = h_list[0].strip().lower()
h_key = (
h_key.replace(" ", "_").replace("/", "").replace(".", "_")
)
h_value = self.convert_value(h_key, h_list[1].strip())
setattr(self, h_key, h_value)
elif len(h_str) == 0:
continue
# need to adjust for older versions of z3d files
elif h_str.count(",") > 1:
self.old_version = True
if h_str.find("Schedule") >= 0:
h_str = h_str.replace(",", "T", 1)
for hh in h_str.split(","):
if hh.find(";") > 0:
m_key, m_value = hh.split(";")[1].split(":")
elif len(hh.split(":", 1)) == 2:
m_key, m_value = hh.split(":", 1)
else:
self.logger.warning("found %s", hh)
m_key = (
m_key.strip()
.lower()
.replace(" ", "_")
.replace("/", "")
.replace(".", "_")
)
m_value = self.convert_value(m_key, m_value.strip())
setattr(self, m_key, m_value)
[docs] def convert_value(self, key_string, value_string):
"""
convert the value to the appropriate units given the key
"""
try:
return_value = float(value_string)
except ValueError:
return_value = value_string
if key_string.lower() in ["lat", "lon", "long"]:
return_value = np.rad2deg(float(value_string))
if "lat" in key_string.lower():
if abs(return_value) > 90:
return_value = 0.0
elif "lon" in key_string.lower():
if abs(return_value) > 180:
return_value = 0.0
return return_value