Source code for

Functions for reading NEXRAD Level 3 products.


import numpy as np

from ..config import FileMetadata, get_fillvalue
from ..core.radar import Radar
from .common import _test_arguments, make_time_unit_str, prepare_for_read
from .nexrad_level3 import NEXRADLevel3File

[docs]def read_nexrad_level3( filename, field_names=None, additional_metadata=None, file_field_names=False, exclude_fields=None, include_fields=None, storage_options={"anon": True}, **kwargs ): """ Read a NEXRAD Level 3 product. Parameters ---------- filename : str Filename of NEXRAD Level 3 product file. The files hosted by at the NOAA National Climate Data Center [1]_ as well as on the NWS WSR-88D Level III Data Collection and Distribution Network have been tests. Other NEXRAD Level 3 files may or may not work. A file-like object pointing to the beginning of such a file is also supported [2]_. field_names : dict, optional Dictionary mapping NEXRAD level 3 product number to radar field names. If the product number of the file does not appear in this dictionary or has a value of None it will not be placed in the radar.fields dictionary. A value of None, the default, will use the mapping defined in the metadata configuration file. additional_metadata : dict of dicts, optional Dictionary of dictionaries to retrieve metadata from during this read. This metadata is not used during any successive file reads unless explicitly included. A value of None, the default, will not introduct any addition metadata and the file specific or default metadata as specified by the metadata configuration file will be used. file_field_names : bool, optional True to use the product number for the field name. In this case the field_names parameter is ignored. The field dictionary will likely only have a 'data' key, unless the fields are defined in `additional_metadata`. exclude_fields : list or None, optional List of fields to exclude from the radar object. This is applied after the `file_field_names` and `field_names` parameters. Set to None to include all fields specified by include_fields. include_fields : list or None, optional List of fields to include from the radar object. This is applied after the `file_field_names` and `field_names` parameters. Set to None to include all fields not specified by exclude_fields. **kwargs Additional keyword arguments to pass to fsspec to open the dataset Returns ------- radar : Radar Radar object containing all moments and sweeps/cuts in the volume. Gates not collected are masked in the field data. References ---------- .. [1] .. [2] """ # test for non empty kwargs _test_arguments(kwargs) # create metadata retrieval object filemetadata = FileMetadata( "nexrad_level3", field_names, additional_metadata, file_field_names, exclude_fields, include_fields, ) # open the file nfile = NEXRADLevel3File( prepare_for_read(filename, storage_options=storage_options) ) nradials = nfile.packet_header["nradials"] msg_code = nfile.msg_header["code"] # time time = filemetadata("time") time_start = nfile.get_volume_start_datetime() time["units"] = make_time_unit_str(time_start) time["data"] = np.zeros((nradials,), dtype="float64") # range _range = filemetadata("range") _range["data"] = nfile.get_range() _range["meters_to_center_of_first_gate"] = _range["data"][0] _range["meters_between_gates"] = _range["data"][1] - _range["data"][0] # fields fields = {} field_name = filemetadata.get_field_name(msg_code) if field_name is None: fields = {} else: dic = filemetadata(field_name) dic["_FillValue"] = get_fillvalue() dic["data"] = nfile.get_data() fields = {field_name: dic} # metadata metadata = filemetadata("metadata") metadata["original_container"] = "NEXRAD Level 3" # scan_type scan_type = "ppi" # latitude, longitude, altitude latitude = filemetadata("latitude") longitude = filemetadata("longitude") altitude = filemetadata("altitude") lat, lon, height = nfile.get_location() # Nexrad altitude is in feet, convert to meters unless user's # default config has units in feet. if altitude["units"] == "meters": height = height * 0.3048 latitude["data"] = np.array([lat], dtype="float64") longitude["data"] = np.array([lon], dtype="float64") altitude["data"] = np.array([height], dtype="float64") # sweep_number, sweep_mode, fixed_angle, sweep_start_ray_index # sweep_end_ray_index sweep_number = filemetadata("sweep_number") sweep_mode = filemetadata("sweep_mode") sweep_start_ray_index = filemetadata("sweep_start_ray_index") sweep_end_ray_index = filemetadata("sweep_end_ray_index") sweep_number["data"] = np.array([0], dtype="int32") sweep_mode["data"] = np.array(1 * ["azimuth_surveillance"], dtype="S") sweep_start_ray_index["data"] = np.array([0], dtype="int32") sweep_end_ray_index["data"] = np.array([nradials - 1], dtype="int32") # azimuth, elevation, fixed_angle azimuth = filemetadata("azimuth") elevation = filemetadata("elevation") fixed_angle = filemetadata("fixed_angle") azimuth["data"] = nfile.get_azimuth() elev = nfile.get_elevation() elevation["data"] = np.ones((nradials,), dtype="float32") * elev fixed_angle["data"] = np.array([elev], dtype="float32") nfile.close() return Radar( time, _range, fields, metadata, scan_type, latitude, longitude, altitude, sweep_number, sweep_mode, fixed_angle, sweep_start_ray_index, sweep_end_ray_index, azimuth, elevation, instrument_parameters=None, )