from datetime import datetime, timedelta
from collections import OrderedDict
from binfile import BinFile
[docs]class GridTiltFile(BinFile):
"""
Read an ARPS EnKF grid-tilt formatted radar observation file.
Args:
file_name (str): The name of the file to open.
vars (list): A list containing the names and order of the variables in the file. Defaults to ['vr', 'Z'] (radial
velocity, then reflectivity).
mode (str): Read/write mode for this file. The default is 'r' for reading, 'w' for writing is also supported.
Attributes:
timestamp (datetime): The valid time for the data file.
n_tilts (int): Number of elevations in the radar data.
n_gridx (int): Number of grid points in the x direction.
n_gridy (int): Number of grid points in the y direction.
radar_name (str): Name of the radar.
radar_lat (float): Latitude of the radar.
radar_lon (float): Longitude of the radar.
radar_x (float): x coordinate of the radar location on the domain.
radar_y (float): y coordinate of the radar location on the domain.
d_azimuth (float): Azimuthal spacing for the raw radar data.
range_min (float): Minimum range for the raw radar data.
range_max (float): Maximum range for the raw radar data.
elevations (np.array): List of elevation angles.
"""
_gtf_time = OrderedDict(
[('timestamp', 'i'), ('year', 'i'), ('month', 'i'), ('day', 'i'), ('hour', 'i'), ('minute', 'i'),
('second', 'i')]
)
_gtf_dimensions = OrderedDict([('n_tilts', 'i'), ('n_gridx', 'i'), ('n_gridy', 'i')])
_gtf_name = OrderedDict([('radar_name', '10s')])
_gtf_location = OrderedDict(
[('radar_lat', 'f'), ('radar_lon', 'f'), ('radar_x', 'f'), ('radar_y', 'f'), ('radar_alt', 'f')]
)
_gtf_radar_meta = OrderedDict([('d_azimuth', 'f'), ('range_min', 'f'), ('range_max', 'f')])
def __init__(self, file_name, vars=('vr', 'Z'), mode='r'):
"""
"""
super(GridTiltFile, self).__init__(file_name, mode, byteorder='>')
self._vars = ('z', 'r') + vars
self._variables = {}
if self._mode == 'r':
try:
self._read_headers()
self._read_data()
except IOError:
raise IOError("File is either corrupt or not a column-tilt file!")
return
def _read_headers(self):
# Read all header blocks
for block in [_GTF._gtf_time,
_GTF._gtf_dimensions,
_GTF._gtf_name,
_GTF._gtf_location,
_GTF._gtf_radar_meta]:
self._read_block(block, self.__dict__, fortran=True)
self.timestamp = datetime(1970, 1, 1, 0, 0, 0) + timedelta(seconds=self.timestamp)
return
def _write_headers(self):
self.year = self.timestamp.year
self.month = self.timestamp.month
self.day = self.timestamp.day
self.hour = self.timestamp.hour
self.minute = self.timestamp.minute
self.second = self.timestamp.second
self.timestamp = int((self.timestamp - datetime(1970, 1, 1, 0, 0, 0)).total_seconds())
for block in [ _GTF._gtf_time,
_GTF._gtf_dimensions,
_GTF._gtf_name,
_GTF._gtf_location,
_GTF._gtf_radar_meta ]:
self._write_block(block, self.__dict__, fortran=True)
return
def _read_data(self):
self.elevations = self._read_grid('f', (self.n_tilts,), fortran=True)
for var in self._vars:
self._variables[var] = self._read_grid('f', (self.n_gridx, self.n_gridy, self.n_tilts), fortran=True).T
return
def _write_data(self):
self._write_grid('f', self.elevations, fortran=True)
for var in self._var_names:
self._write_grid('f', self._variables[var].T, fortran=True)
return
[docs] def close(self):
"""
Close the file. Write data if opened for writing.
"""
if self._mode == 'w':
self._write_headers()
self._write_data()
super(GridTiltFile, self).close()
[docs] def __getitem__(self, var_name):
"""
Retrieve data from the file.
Args:
var_name (str): Name of the variable to retrieve. Acceptable values are 'z' (height in meters), 'r' (slant
range in meters), or any of the names passed to the `vars` keyword argument in :py:meth:`GridTiltFile.__init__()`.
Returns:
A three-dimensional numpy array (NTILT :math:`\\times` NY :math:`\\times` NX)
Examples:
>>> gtf = GridTiltFile("/path/to/gridtiltfile/KTLX.20110524.210000")
>>> gtf['Z'].max() # Pull the reflectivity out of the file and take the maximum.
68.41645
"""
try:
return self._variables[var_name]
except KeyError:
raise ValueError("Variable '%s' not found in file." % var_name)
[docs] def __setitem__(self, var_name, data):
"""
Set data in the file.
Args:
var_name (str): Name of the variable to set. Use 'z' for height and 'r' for slant range.
data (np.array): The data put into the file. Must be the same shape as the rest of the variables.
Examples:
>>> gtf = GridTiltFile("/path/to/gridtiltfile/KTLX.20110524.210000")
>>> gtf['Z'] = new_reflectivity_data
"""
if var_name not in self._variables:
raise ValueError("Variable '%s' not found in file." % var_name)
if data.shape != self._variables[var_name].shape:
raise ValueError("Variable '%s' not the same shape as the rest of the file" % var_name)
self._variables[var_name] = data
#Alias to _GTF to make it easier to access the format dictionaries
_GTF = GridTiltFile
if __name__ == "__main__":
gtf = GridTiltFile("/data6/tsupinie/goshen/qc/manual/1km/KFTG.20090605.215129")
print gtf['Z'].max(), gtf['Z'].min()