Ejemplo n.º 1
0
def read_uf(filename,
            field_names=None,
            additional_metadata=None,
            file_field_names=False,
            exclude_fields=None,
            delay_field_loading=False,
            **kwargs):
    """
    Read a UF File.

    Parameters
    ----------
    filename : str or file-like
        Name of Universal format file to read data from.
    field_names : dict, optional
        Dictionary mapping UF data type names to radar field names. If a
        data type found in 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
        Py-ART 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 Py-ART configuration file will be used.
    file_field_names : bool, optional
        True to force the use of the field names from the file in which
        case the `field_names` parameter is ignored. False will use to
        `field_names` parameter to rename fields.
    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.
    delay_field_loading : bool
        This option is not implemented in the function but included for
        compatability.

    Returns
    -------
    radar : Radar
        Radar object.

    """
    # test for non empty kwargs
    _test_arguments(kwargs)

    # create metadata retrieval object
    filemetadata = FileMetadata('uf', field_names, additional_metadata,
                                file_field_names, exclude_fields)

    # Open UF file and get handle
    ufile = UFFile(filename)
    first_ray = ufile.rays[0]

    # time
    dts = ufile.get_datetimes()
    units = make_time_unit_str(min(dts))
    time = filemetadata('time')
    time['units'] = units
    time['data'] = date2num(dts, units).astype('float32')

    # range
    _range = filemetadata('range')
    # assume that the number of gates and spacing from the first ray is
    # representative of the entire volume
    field_header = first_ray.field_headers[0]
    ngates = field_header['nbins']
    start = field_header['range_start_m']
    step = field_header['range_spacing_m']
    # this gives distances to the start of each gate, add step/2 for center
    _range['data'] = np.arange(ngates, dtype='float32') * step + start
    _range['meters_to_center_of_first_gate'] = start
    _range['meters_between_gates'] = step

    # latitude, longitude and altitude
    latitude = filemetadata('latitude')
    longitude = filemetadata('longitude')
    altitude = filemetadata('altitude')
    lat, lon, height = first_ray.get_location()
    latitude['data'] = np.array([lat], dtype='float64')
    longitude['data'] = np.array([lon], dtype='float64')
    altitude['data'] = np.array([height], dtype='float64')

    # metadata
    metadata = filemetadata('metadata')
    metadata['original_container'] = 'UF'
    metadata['site_name'] = first_ray.mandatory_header['site_name']
    metadata['radar_name'] = first_ray.mandatory_header['radar_name']

    # sweep_start_ray_index, sweep_end_ray_index
    sweep_start_ray_index = filemetadata('sweep_start_ray_index')
    sweep_end_ray_index = filemetadata('sweep_end_ray_index')
    sweep_start_ray_index['data'] = ufile.first_ray_in_sweep
    sweep_end_ray_index['data'] = ufile.last_ray_in_sweep

    # sweep number
    sweep_number = filemetadata('sweep_number')
    sweep_number['data'] = np.arange(ufile.nsweeps, dtype='int32')

    # sweep_type
    scan_type = _UF_SWEEP_MODES[first_ray.mandatory_header['sweep_mode']]

    # sweep_mode
    sweep_mode = filemetadata('sweep_mode')
    sweep_mode['data'] = np.array(ufile.nsweeps * [_SWEEP_MODE_STR[scan_type]])

    # elevation
    elevation = filemetadata('elevation')
    elevation['data'] = ufile.get_elevations()

    # azimuth
    azimuth = filemetadata('azimuth')
    azimuth['data'] = ufile.get_azimuths()

    # fixed_angle
    fixed_angle = filemetadata('fixed_angle')
    fixed_angle['data'] = ufile.get_sweep_fixed_angles()

    # fields
    fields = {}
    for uf_field_number, uf_field_dic in enumerate(first_ray.field_positions):
        uf_field_name = uf_field_dic['data_type']
        field_name = filemetadata.get_field_name(uf_field_name)
        if field_name is None:
            continue
        field_dic = filemetadata(field_name)
        field_dic['data'] = ufile.get_field_data(uf_field_number)
        field_dic['_FillValue'] = get_fillvalue()
        fields[field_name] = field_dic

    # instrument_parameters
    instrument_parameters = _get_instrument_parameters(ufile, filemetadata)

    # scan rate
    scan_rate = filemetadata('scan_rate')
    scan_rate['data'] = ufile.get_sweep_rates()

    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,
                 scan_rate=scan_rate,
                 instrument_parameters=instrument_parameters)
Ejemplo n.º 2
0
def read_sband_archive(filename,
                       field_names=None,
                       additional_metadata=None,
                       file_field_names=False,
                       exclude_fields=None,
                       delay_field_loading=False,
                       station=None,
                       scans=None,
                       linear_interp=True,
                       **kwargs):
    """
    Read a S band Archive file.

    Parameters
    ----------
    filename : str
        Filename of S band Archive file.  
    field_names : dict, optional
        Dictionary mapping S band moments to radar field names. If a
        data type found in 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 S band field names for the field names. If 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.
    delay_field_loading : bool, optional
        True to delay loading of field data from the file until the 'data'
        key in a particular field dictionary is accessed.  In this case
        the field attribute of the returned Radar object will contain
        LazyLoadDict objects not dict objects.
    station : tuple or None, optional
        Three float tuple, include latitude, longitude and height of S band radar,
        first latitude, second longitude, third height (units: metre)
    scans : list or None, optional
        Read only specified scans from the file.  None (the default) will read
        all scans.
    linear_interp : bool, optional
        True (the default) to perform linear interpolation between valid pairs
        of gates in low resolution rays in files mixed resolution rays.
        False will perform a nearest neighbor interpolation.  This parameter is
        not used if the resolution of all rays in the file or requested sweeps
        is constant.

    Returns
    -------
    radar : Radar
        Radar object containing all moments and sweeps/cuts in the volume.
        Gates not collected are masked in the field data.

    """
    # test for non empty kwargs
    _test_arguments(kwargs)

    # create metadata retrieval object
    filemetadata = FileMetadata('nexrad_archive', field_names,
                                additional_metadata, file_field_names,
                                exclude_fields)

    # open the file and retrieve scan information
    nfile = SbandRadarFile(prepare_for_read(filename))
    scan_info = nfile.scan_info(scans)

    # time
    time = filemetadata('time')
    time_start, _time = nfile.get_times(scans)
    time['data'] = _time
    time['units'] = make_time_unit_str(time_start)

    # range
    _range = filemetadata('range')
    first_gate, gate_spacing, last_gate = _find_range_params(
        scan_info, filemetadata)
    _range['data'] = np.arange(first_gate, last_gate, gate_spacing, 'float32')
    _range['meters_to_center_of_first_gate'] = float(first_gate)
    _range['meters_between_gates'] = float(gate_spacing)

    # metadata
    metadata = filemetadata('metadata')
    metadata['original_container'] = 'S band'
    vcp_pattern = nfile.get_vcp_pattern()
    if vcp_pattern is not None:
        metadata['vcp_pattern'] = vcp_pattern

    # scan_type
    scan_type = 'ppi'

    # latitude, longitude, altitude
    latitude = filemetadata('latitude')
    longitude = filemetadata('longitude')
    altitude = filemetadata('altitude')

    if station is None:
        lat, lon, alt = 0, 0, 0
    else:
        lat, lon, alt = station

    latitude['data'] = np.array([lat], dtype='float64')
    longitude['data'] = np.array([lon], dtype='float64')
    altitude['data'] = np.array([alt], 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')

    if scans is None:
        nsweeps = int(nfile.nscans)
    else:
        nsweeps = len(scans)
    sweep_number['data'] = np.arange(nsweeps, dtype='int32')
    sweep_mode['data'] = np.array(nsweeps * ['azimuth_surveillance'],
                                  dtype='S')

    rays_per_scan = [s['nrays'] for s in scan_info]
    sweep_end_ray_index['data'] = np.cumsum(rays_per_scan, dtype='int32') - 1

    rays_per_scan.insert(0, 0)
    sweep_start_ray_index['data'] = np.cumsum(rays_per_scan[:-1],
                                              dtype='int32')

    # azimuth, elevation, fixed_angle
    azimuth = filemetadata('azimuth')
    elevation = filemetadata('elevation')
    fixed_angle = filemetadata('fixed_angle')
    azimuth['data'] = nfile.get_azimuth_angles(scans)
    elevation['data'] = nfile.get_elevation_angles(scans).astype('float32')
    fixed_angle['data'] = nfile.get_target_angles(scans)

    # fields
    max_ngates = len(_range['data'])
    available_moments = set([m for scan in scan_info for m in scan['moments']])
    interpolate = _find_scans_to_interp(scan_info, first_gate, gate_spacing,
                                        filemetadata)

    fields = {}
    for moment in available_moments:
        field_name = filemetadata.get_field_name(moment)
        if field_name is None:
            continue
        dic = filemetadata(field_name)
        dic['_FillValue'] = get_fillvalue()

        if delay_field_loading and moment not in interpolate:
            dic = LazyLoadDict(dic)
            data_call = _NEXRADLevel2StagedField(nfile, moment, max_ngates,
                                                 scans)
            dic.set_lazy('data', data_call)
        else:
            mdata = nfile.get_data(moment, max_ngates, scans=scans)
            if moment in interpolate:
                interp_scans = interpolate[moment]
                warnings.warn(
                    "Gate spacing is not constant, interpolating data in " +
                    "scans %s for moment %s." % (interp_scans, moment),
                    UserWarning)
                for scan in interp_scans:
                    idx = scan_info[scan]['moments'].index(moment)
                    moment_ngates = scan_info[scan]['ngates'][idx]
                    start = sweep_start_ray_index['data'][scan]
                    end = sweep_end_ray_index['data'][scan]
                    _interpolate_scan(mdata, start, end, moment_ngates,
                                      linear_interp)
            dic['data'] = mdata
        fields[field_name] = dic

    # instrument_parameters
    nyquist_velocity = filemetadata('nyquist_velocity')
    unambiguous_range = filemetadata('unambiguous_range')
    nyquist_velocity['data'] = nfile.get_nyquist_vel(scans).astype('float32')
    unambiguous_range['data'] = (
        nfile.get_unambigous_range(scans).astype('float32'))

    instrument_parameters = {
        'unambiguous_range': unambiguous_range,
        'nyquist_velocity': nyquist_velocity,
    }

    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=instrument_parameters)
Ejemplo n.º 3
0
def read_sipam_cappi(filename,
                     exclude_fields=[
                         "start_time",
                         "stop_time",
                         "time_bounds",
                         "x0",
                         "y0",
                         "lat0",
                         "lon0",
                         "z0",
                         "grid_mapping_0",
                     ],
                     include_fields=None,
                     **kwargs):
    """
    Read a netCDF grid file produced by Py-ART.

    Parameters
    ----------
    filename : str
        Filename of netCDF grid file to read. This file must have been
        produced by :py:func:`write_grid` or have identical layout.

    Other Parameters
    ----------------
    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.

    Returns
    -------
    grid : Grid
        Grid object containing gridded data.

    """
    # test for non empty kwargs
    _test_arguments(kwargs)

    if exclude_fields is None:
        exclude_fields = []

    reserved_variables = [
        "time",
        "x",
        "y",
        "z",
        "origin_latitude",
        "origin_longitude",
        "origin_altitude",
        "point_x",
        "point_y",
        "point_z",
        "projection",
        "point_latitude",
        "point_longitude",
        "point_altitude",
        "radar_latitude",
        "radar_longitude",
        "radar_altitude",
        "radar_name",
        "radar_time",
        "base_time",
        "time_offset",
        "ProjectionCoordinateSystem",
    ]

    dset = netCDF4.Dataset(filename, mode="r")

    # metadata
    metadata = dict([(k, getattr(dset, k)) for k in dset.ncattrs()])

    # required reserved variables
    time = _ncvar_to_dict(dset.variables["time"])
    origin_latitude = {
        "data":
        [dset.variables["grid_mapping_0"].latitude_of_projection_origin],
        "long_name": "Latitude of projection origin",
        "units": "degree_N",
    }
    origin_longitude = {
        "data":
        [dset.variables["grid_mapping_0"].longitude_of_projection_origin],
        "long_name": "Longitude of projection origin",
        "units": "degree_E",
    }
    origin_altitude = None
    x = _ncvar_to_dict(dset.variables["x0"])
    x["data"] = x["data"] * 1000
    x["units"] = "m"
    y = _ncvar_to_dict(dset.variables["y0"])
    y["data"] = y["data"] * 1000
    y["units"] = "m"
    z = _ncvar_to_dict(dset.variables["z0"])
    z["data"] = z["data"] * 1000
    z["units"] = "m"

    # projection
    projection = {"data": [], "proj": "aeqd", "_include_lon_0_lat_0": "true"}
    projection.pop("data")
    # map _include_lon_0_lat_0 key to bool type
    if "_include_lon_0_lat_0" in projection:
        v = projection["_include_lon_0_lat_0"]
        projection["_include_lon_0_lat_0"] = {"true": True, "false": False}[v]

    # read in the fields
    fields = {}

    # fields in the file has a shape of (1, nz, ny, nx) with the leading 1
    # indicating time but should shaped (nz, ny, nx) in the Grid object
    field_shape = tuple([len(dset.dimensions[d]) for d in ["z0", "y0", "x0"]])
    field_shape_with_time = (1, ) + field_shape

    # check all non-reserved variables, those with the correct shape
    # are added to the field dictionary, if a wrong sized field is
    # detected a warning is raised
    field_keys = [k for k in dset.variables if k not in reserved_variables]
    for field in field_keys:
        if field in exclude_fields:
            continue
        if include_fields is not None:
            if field not in include_fields:
                continue
        field_dic = _ncvar_to_dict(dset.variables[field])
        if field_dic["data"].shape == field_shape_with_time:
            field_dic["data"].shape = field_shape
            fields[field] = field_dic
        else:
            bad_shape = field_dic["data"].shape
            warnings.warn("Field %s skipped due to incorrect shape %s" %
                          (field, bad_shape))

    # radar_ variables
    if "radar_latitude" in dset.variables:
        radar_latitude = _ncvar_to_dict(dset.variables["radar_latitude"])
    else:
        radar_latitude = {
            "long_name": "Latitude of radars used to make the grid.",
            "units": "degrees_north",
            "data": np.array([-3.1493]),
        }

    if "radar_longitude" in dset.variables:
        radar_longitude = _ncvar_to_dict(dset.variables["radar_longitude"])
    else:
        radar_longitude = {
            "long_name": "Longitude of radars used to make the grid.",
            "units": "degrees_east",
            "data": np.array([-59.992]),
        }

    if "radar_altitude" in dset.variables:
        radar_altitude = _ncvar_to_dict(dset.variables["radar_altitude"])
    else:
        radar_altitude = {
            "long_name": "Altitude of radars used to make the grid.",
            "units": "m",
            "data": np.array([102.4]),
        }

    if "radar_name" in dset.variables:
        radar_name = _ncvar_to_dict(dset.variables["radar_name"])
    else:
        radar_name = {
            "long_name": "Name of radar used to make the grid",
            "data": np.array(["SIPAM"], dtype="<U1"),
        }

    if "radar_time" in dset.variables:
        radar_time = _ncvar_to_dict(dset.variables["radar_time"])
    else:
        radar_time = None

    dset.close()

    return Grid(
        time,
        fields,
        metadata,
        origin_latitude,
        origin_longitude,
        origin_altitude,
        x,
        y,
        z,
        projection=projection,
        radar_latitude=radar_latitude,
        radar_longitude=radar_longitude,
        radar_altitude=radar_altitude,
        radar_name=radar_name,
        radar_time=radar_time,
    )
Ejemplo n.º 4
0
def c98dfile_archive(filename,
                     field_names=None,
                     additional_metadata=None,
                     file_field_names=False,
                     exclude_fields=None,
                     cutnum=None,
                     delay_field_loading=False,
                     **kwargs):

    # test for non empty kwargs
    _test_arguments(kwargs)

    # create metadata retrieval object
    filemetadata = FileMetadata('c98d_archive', field_names,
                                additional_metadata, file_field_names,
                                exclude_fields)

    nfile = C98DRadFile(prepare_for_read(filename))
    #    scan_info = nfile.scan_info

    if cutnum is None:
        cutnum = nfile.scans
    else:
        cutnum = list(cutnum)

    # time
    time = filemetadata('time')
    _time = nfile.radial_info['seconds']
    time['data'] = _time
    time['units'] = nfile.get_volume_start_time

    # range
    _range = filemetadata('range')
    _range['data'] = nfile.get_range('dBZ', cutnum)
    #    _range['meters_to_center_of_first_gate'] = float(first_gate)
    #    _range['meters_between_gates'] = float(gate_spacing)

    # fields
    fields = {}
    field_names = nfile.get_moment_type
    for field_name in field_names:
        dic = filemetadata(field_name)
        for i, cn in enumerate(cutnum):
            dic['_FillValue'] = get_fillvalue()
            if i == 0:
                dic['data'] = nfile.get_data(field_name, cn)
            else:
                fndata = nfile.get_data(field_name, cn)

                if fndata.shape[1] != dic['data'].shape[1]:
                    if dic['data'].shape[1] - fndata.shape[1] > 0:
                        apps = np.ones(
                            (fndata.shape[0],
                             dic['data'].shape[1] - fndata.shape[1])) * np.nan
                    else:
                        raise ValueError('something wrong!')

                    fndata = np.c_[fndata, apps]
                dic['data'] = np.append(dic['data'], fndata, axis=0)

        fields.update({field_name: dic})

    # scan_type
    scan_type = nfile.scan_type

    # latitude, longitude, altitude
    latitude = filemetadata('latitude')
    longitude = filemetadata('longitude')
    altitude = filemetadata('altitude')

    lat, lon, height = nfile.get_location

    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.arange(nfile.cutnum, dtype='int32')
    sweep_mode['data'] = np.array(nfile.cutnum * ['azimuth_surveillance'],
                                  dtype='S')

    sweep_end_ray_index['data'] = np.array(nfile.cut_end)
    sweep_start_ray_index['data'] = np.array(nfile.cut_start)

    # azimuth, elevation, fixed_angle
    azimuth = filemetadata('azimuth')
    elevation = filemetadata('elevation')
    fixed_angle = filemetadata('fixed_angle')
    azimuth['data'] = np.array(nfile.get_azimuth)
    elevation['data'] = np.array(nfile.get_elevation)
    fixed_angle['data'] = nfile.get_target_angles

    # instrument_parameters
    nyquist_velocity = filemetadata('nyquist_velocity')
    unambiguous_range = filemetadata('unambiguous_range')
    nyquist_velocity['data'] = None
    unambiguous_range['data'] = None

    instrument_parameters = {
        'unambiguous_range': unambiguous_range,
        'nyquist_velocity': nyquist_velocity
    }

    return Radar(time,
                 _range,
                 fields,
                 filemetadata,
                 scan_type,
                 latitude,
                 longitude,
                 altitude,
                 sweep_number,
                 sweep_mode,
                 fixed_angle,
                 sweep_start_ray_index,
                 sweep_end_ray_index,
                 azimuth,
                 elevation,
                 instrument_parameters=None)
Ejemplo n.º 5
0
def read_sipam_cappi(filename, 
                     exclude_fields=[
                         'start_time', 'stop_time', 'time_bounds', 'x0', 'y0',
                         'lat0', 'lon0', 'z0', 'grid_mapping_0'
                        ], 
                     include_fields=None, **kwargs):
    """
    Read a netCDF grid file produced by Py-ART.

    Parameters
    ----------
    filename : str
        Filename of netCDF grid file to read. This file must have been
        produced by :py:func:`write_grid` or have identical layout.

    Other Parameters
    ----------------
    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.

    Returns
    -------
    grid : Grid
        Grid object containing gridded data.

    """
    # test for non empty kwargs
    _test_arguments(kwargs)

    if exclude_fields is None:
        exclude_fields = []

    reserved_variables = [
        'time', 'x', 'y', 'z',
        'origin_latitude', 'origin_longitude', 'origin_altitude',
        'point_x', 'point_y', 'point_z', 'projection',
        'point_latitude', 'point_longitude', 'point_altitude',
        'radar_latitude', 'radar_longitude', 'radar_altitude',
        'radar_name', 'radar_time', 'base_time', 'time_offset',
        'ProjectionCoordinateSystem']

    dset = netCDF4.Dataset(filename, mode='r')

    # metadata
    metadata = dict([(k, getattr(dset, k)) for k in dset.ncattrs()])

    # required reserved variables
    time = _ncvar_to_dict(dset.variables['time'])
    origin_latitude = {
        'data': [dset.variables['grid_mapping_0'].latitude_of_projection_origin],
        'long_name': 'Latitude of projection origin',
        'units': 'degree_N'
    }
    origin_longitude = {
        'data': [dset.variables['grid_mapping_0'].longitude_of_projection_origin],
        'long_name': 'Longitude of projection origin',
        'units': 'degree_E'
    }
    origin_altitude = None
    x = _ncvar_to_dict(dset.variables['x0'])
    x['data'] = x['data']*1000
    x['units'] = 'm'
    y = _ncvar_to_dict(dset.variables['y0'])
    y['data'] = y['data']*1000
    y['units'] = 'm'
    z = _ncvar_to_dict(dset.variables['z0'])
    z['data'] = z['data']*1000
    z['units'] = 'm'

    # projection
    projection = {
        'data': [],
        'proj': 'aeqd',
        '_include_lon_0_lat_0': 'true'
    }
    projection.pop('data')
    # map _include_lon_0_lat_0 key to bool type
    if '_include_lon_0_lat_0' in projection:
        v = projection['_include_lon_0_lat_0']
        projection['_include_lon_0_lat_0'] = {'true': True, 'false': False}[v]

    # read in the fields
    fields = {}

    # fields in the file has a shape of (1, nz, ny, nx) with the leading 1
    # indicating time but should shaped (nz, ny, nx) in the Grid object
    field_shape = tuple([len(dset.dimensions[d]) for d in ['z0', 'y0', 'x0']])
    field_shape_with_time = (1, ) + field_shape

    # check all non-reserved variables, those with the correct shape
    # are added to the field dictionary, if a wrong sized field is
    # detected a warning is raised
    field_keys = [k for k in dset.variables if k not in reserved_variables]
    for field in field_keys:
        if field in exclude_fields:
            continue
        if include_fields is not None:
            if field not in include_fields:
                continue
        field_dic = _ncvar_to_dict(dset.variables[field])
        if field_dic['data'].shape == field_shape_with_time:
            field_dic['data'].shape = field_shape
            fields[field] = field_dic
        else:
            bad_shape = field_dic['data'].shape
            warnings.warn(
                'Field %s skipped due to incorrect shape %s'
                % (field, bad_shape))

    # radar_ variables
    if 'radar_latitude' in dset.variables:
        radar_latitude = _ncvar_to_dict(dset.variables['radar_latitude'])
    else:
        radar_latitude = {
            'long_name': 'Latitude of radars used to make the grid.',
            'units': 'degrees_north',
            'data': np.array([-3.1493])}

    if 'radar_longitude' in dset.variables:
        radar_longitude = _ncvar_to_dict(dset.variables['radar_longitude'])
    else:
        radar_longitude = {
            'long_name': 'Longitude of radars used to make the grid.',
            'units': 'degrees_east',
            'data': np.array([-59.992])}

    if 'radar_altitude' in dset.variables:
        radar_altitude = _ncvar_to_dict(dset.variables['radar_altitude'])
    else:
        radar_altitude = {
            'long_name': 'Altitude of radars used to make the grid.',
            'units': 'm',
            'data': np.array([102.4])}

    if 'radar_name' in dset.variables:
        radar_name = _ncvar_to_dict(dset.variables['radar_name'])
    else:
        radar_name = {
            'long_name': 'Name of radar used to make the grid',
            'data': np.array(['SIPAM'], dtype='<U1')}

    if 'radar_time' in dset.variables:
        radar_time = _ncvar_to_dict(dset.variables['radar_time'])
    else:
        radar_time = None

    dset.close()

    return Grid(
        time, fields, metadata,
        origin_latitude, origin_longitude, origin_altitude, x, y, z,
        projection=projection,
        radar_latitude=radar_latitude, radar_longitude=radar_longitude,
        radar_altitude=radar_altitude, radar_name=radar_name,
        radar_time=radar_time)
Ejemplo n.º 6
0
def read_casa_netcdf(filename, **kwargs):
    """
    Read a CASA NetCDF file.

    Parameters
    ----------
    filename : str
        Name of CASA NetCDF file to read data from.

    Returns
    -------
    radar : Radar
        Radar object.

    """
    # test for non empty kwargs
    _test_arguments(kwargs)

    # create metadata retrieval object
    filemetadata = FileMetadata('casa_netcdf')

    # Open netCDF4 file
    dset = netCDF4.Dataset(filename)
    nrays = len(dset.dimensions['Radial'])
    nbins = len(dset.dimensions['Gate'])

    # latitude, longitude and altitude
    latitude = filemetadata('latitude')
    longitude = filemetadata('longitude')
    altitude = filemetadata('altitude')
    latitude['data'] = np.array([dset.Latitude], 'float64')
    longitude['data'] = np.array([dset.Longitude], 'float64')
    altitude['data'] = np.array([dset.Height], 'float64')

    # metadata
    metadata = filemetadata('metadata')
    metadata_mapping = {
        'vcp-value': 'vcp',  #not in casa
        'radarName-value': 'RadarName',
        'ConversionPlugin': 'conversion_software',  #not in casa
    }
    for netcdf_attr, metadata_key in metadata_mapping.items():
        if netcdf_attr in dset.ncattrs():
            metadata[metadata_key] = dset.getncattr(netcdf_attr)

    # sweep_start_ray_index, sweep_end_ray_index
    sweep_start_ray_index = filemetadata('sweep_start_ray_index')
    sweep_end_ray_index = filemetadata('sweep_end_ray_index')
    sweep_start_ray_index['data'] = np.array([0], dtype='int32')
    sweep_end_ray_index['data'] = np.array([nrays - 1], dtype='int32')

    # sweep number
    sweep_number = filemetadata('sweep_number')
    sweep_number['data'] = np.array([0], dtype='int32')

    # sweep_type
    scan_type = 'ppi'

    # sweep_mode, fixed_angle
    sweep_mode = filemetadata('sweep_mode')
    fixed_angle = filemetadata('fixed_angle')
    sweep_mode['data'] = np.array(1 * ['azimuth_surveillance'])
    elev_mean = np.mean(dset.variables['Elevation'])
    fixed_angle['data'] = np.array([elev_mean], dtype='float32')

    # time
    time = filemetadata('time')
    start_time = datetime.datetime.utcfromtimestamp(dset.variables['Time'][0])
    time['units'] = make_time_unit_str(start_time)
    time['data'] = np.zeros((nrays, ), dtype='float64')

    # range
    _range = filemetadata('range')
    step = dset.variables['GateWidth'][0] / 1e3
    # * len(dset.variables['GateWidth'][:]))/1e6
    _range['data'] = (np.arange(nbins, dtype='float32') * step + step / 2)
    _range['meters_to_center_of_first_gate'] = step / 2.
    _range['meters_between_gates'] = step

    # elevation
    elevation = filemetadata('elevation')
    elevation_angle = elev_mean
    elevation['data'] = np.ones((nrays, ), dtype='float32') * elevation_angle

    # azimuth
    azimuth = filemetadata('azimuth')
    azimuth['data'] = dset.variables['Azimuth'][:]

    # fields
    # Ryan Note: What is "TypeName"?

    #     field_name = dset.TypeName

    #     field_data = np.ma.array(dset.variables[field_name][:])
    #     if 'MissingData' in dset.ncattrs():
    #         field_data[field_data == dset.MissingData] = np.ma.masked
    #     if 'RangeFolded' in dset.ncattrs():
    #         field_data[field_data == dset.RangeFolded] = np.ma.masked

    #     fields = {field_name: filemetadata(field_name)}
    #     fields[field_name]['data'] = field_data
    #     fields[field_name]['units'] = dset.variables[field_name].Units
    #     fields[field_name]['_FillValue'] = get_fillvalue()

    # borrowing from d3r_gcpex_nc.py
    ncvars = dset.variables
    keys = [k for k, v in ncvars.items() if v.dimensions == ('Radial', 'Gate')]
    fields = {}
    for key in keys:
        field_name = filemetadata.get_field_name(key)
        if field_name is None:
            field_name = key
        fields[field_name] = _ncvar_to_dict(ncvars[key])

    # instrument_parameters
    instrument_parameters = {}

    if 'PRF-value' in dset.ncattrs():
        dic = filemetadata('prt')
        prt = 1. / float(dset.getncattr('PRF-value'))
        dic['data'] = np.ones((nrays, ), dtype='float32') * prt
        instrument_parameters['prt'] = dic

    if 'PulseWidth-value' in dset.ncattrs():
        dic = filemetadata('pulse_width')
        pulse_width = dset.getncattr('PulseWidth-value') * 1.e-6
        dic['data'] = np.ones((nrays, ), dtype='float32') * pulse_width
        instrument_parameters['pulse_width'] = dic

    if 'NyquistVelocity-value' in dset.ncattrs():
        dic = filemetadata('nyquist_velocity')
        nyquist_velocity = float(dset.getncattr('NyquistVelocity-value'))
        dic['data'] = np.ones((nrays, ), dtype='float32') * nyquist_velocity
        instrument_parameters['nyquist_velocity'] = dic

    if 'Beamwidth' in dset.variables:
        dic = filemetadata('radar_beam_width_h')
        dic['data'] = dset.variables['Beamwidth'][:]
        instrument_parameters['radar_beam_width_h'] = dic

    dset.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=instrument_parameters)