from binfile import BinFile
from collections import OrderedDict
[docs]class ARPSModelObsFile(BinFile):
"""
Read an ARPS EnKF model observation file (such as that created by arpsenkf
or postinnov).
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).
mpi_config (tuple): A tuple containing the MPI configuration of the run that generated this file. Defaults to
(1, 1), signifying no MPI.
mode (str): Read/write mode for this file. The default is 'r' for reading, currently the only supported option.
Attributes:
timestamp (datetime): The valid time for the data in the file.
n_tilts (int): Number of elevation angles in the file.
n_gridx (int): Number of grid points in the x direction.
n_gridy (int): Number of grid points in the y direction.
radar_id (str): 4-character ID for the radar.
radar_lat (float): Latitude of the radar.
radar_lon (float): Longitude of the radar.
radar_x (float): x coordinate of the radar on the domain.
radar_y (float): y coordinate of the radar on the domain.
d_azim (float): Azimuthal spacing of the raw data.
range_min (float): Minimum range of the raw data.
range_max (float): Maximum range of the raw data.
elevations (np.array): List of elevation angles in the file.
"""
# Header block definitions (ordered dictionaries of field names and data types)
_amof_time = OrderedDict(
[('timestamp', 'i'), ('year', 'i'), ('month', 'i'), ('day', 'i'), ('hour', 'i'), ('minute', 'i'),
('second', 'i')]
)
_amof_dimensions = OrderedDict([('n_tilts', 'i'), ('n_gridx', 'i'), ('n_gridy', 'i')])
_amof_radar_name = OrderedDict([('radar_id', '4s')])
_amof_location = OrderedDict(
[('radar_lat', 'f'), ('radar_lon', 'f'), ('radar_x', 'f'), ('radar_y', 'f'), ('radar_alt', 'f')]
)
_amof_radar_meta = OrderedDict([('d_azim', 'f'), ('range_min', 'f'), ('range_max', 'f')])
def __init__(self, file_name, vars=('vr', 'Z'), mpi_config=(1, 1), mode='r'):
"""
Constructor for the ARPSModelObsFile class
"""
super(ARPSModelObsFile, self).__init__(file_name, mode, byteorder='>')
self._mpi = mpi_config
self._var_names = vars
if 'r' in mode:
self._read_headers()
self._read_data()
return
def _read_headers(self):
# Read all header blocks
for block in [_AMOF._amof_time,
_AMOF._amof_dimensions,
_AMOF._amof_radar_name,
_AMOF._amof_location,
_AMOF._amof_radar_meta]:
self._read_block(block, self.__dict__, fortran=True)
return
def _read_data(self):
self.elevations = self._read_grid('f', (self.n_tilts,), fortran=True)
block_size = self._peek('i')
if block_size != self.n_tilts * self.n_gridx * self.n_gridy * 4:
self.sd_nx = self.n_gridx
self.sd_ny = self.n_gridy
self.n_gridx, self.n_gridy = self._subdomain_to_full(self._mpi)
self.height = self._read_grid('f', (self.n_gridx, self.n_gridy, self.n_tilts), fortran=True).T
self.range = self._read_grid('f', (self.n_gridx, self.n_gridy, self.n_tilts), fortran=True).T
vars = self._read_grid('f', (self.n_gridx, self.n_gridy, self.n_tilts, len(self._var_names)), fortran=True).T
self._variables = dict(zip(self._var_names, vars))
return
def _subdomain_to_full(self, mpi_config):
nproc_x, nproc_y = mpi_config
nx = nproc_x * (self.sd_nx - 3) + 3
ny = nproc_y * (self.sd_ny - 3) + 3
return nx, ny
[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), 'r' (slant range), or
any of the names passed to the `vars` keyword argument in :py:meth:`ARPSModelObsFile.__init__()`.
Returns:
A three-dimensional numpy array (NTILT :math:`\\times` NY :math:`\\times` NX)
"""
if var_name == 'z':
var = self.height
elif var_name == 'r':
var = self.range
elif var_name in self._variables:
var = self._variables[var_name]
else:
raise ValueError("Variable name %s was not given" % var_name)
return var
# Alias to _AMOF to make accessing the format dictionaries easier.
_AMOF = ARPSModelObsFile
if __name__ == "__main__":
ad = ARPSModelObsFile("/caps2/tsupinie/05June2009/1km-sfc-diff/KCYSan014400", mpi_config=(2, 12))
print ad['Z'].max(), ad['Z'].min()