pyart.correct.dealias — pyart-mch 0.4.1 documentation

# Source code for pyart.correct.dealias

    """
    pyart.correct.dealias
    =====================

    Front end to the University of Washington 4DD code for Doppler dealiasing.

    .. autosummary::
        :toctree: generated/

        dealias_fourdd
        _create_rsl_volume

    """

    import numpy as np

    from ..config import get_field_name, get_fillvalue, get_metadata
    try:
        from ..io import _rsl_interface
        from . import _fourdd_interface
        _FOURDD_AVAILABLE = True
    except ImportError:
        _FOURDD_AVAILABLE = False
    from ._common_dealias import _parse_gatefilter, _set_limits
    from ..exceptions import MissingOptionalDependency

    def dealias_fourdd(
            radar, last_radar=None, sonde_profile=None, gatefilter=False,
            filt=1, rsl_badval=131072.0, keep_original=False, set_limits=True,
            vel_field=None, corr_vel_field=None, last_vel_field=None,
            debug=False, max_shear=0.05, sign=1, **kwargs):
        """
        Dealias Doppler velocities using the 4DD algorithm.

        Dealias the Doppler velocities field using the University of Washington
        4DD algorithm utilizing information from a previous volume scan and/or
        sounding data. Either last_radar or sonde_profile must be provided.
        For best results provide both a previous volume scan and sounding data.
        Radar and last_radar must contain the same number of rays per sweep.

        Additional arguments are passed to
        :py:func:`_fourdd_interface.fourdd_dealias`.
        These can be used to fine tune the behavior of the FourDD algorithm.
        See the documentation of Other Parameters for details.  For the default
        values of these parameters see the documentation of
        :py:func:`_fourdd_interface.fourdd_dealias`.

        Parameters
        ----------
        radar : Radar
            Radar object to use for dealiasing. Must have a Nyquist defined in
            the instrument_parameters attribute and have a
            reflectivity_horizontal and mean_doppler_velocity fields.
        last_radar : Radar, optional
            The previous radar volume, which has been successfully
            dealiased. Using a previous volume as an initial condition can
            greatly improve the dealiasing, and represents the final dimension
            in the 4DD algorithm.
        sonde_profile : HorizontalWindProfile, optional
            Profile of horizontal winds from a sonding used for the initial
            condition of the dealiasing.

        Other Parameters
        ----------------
        gatefilter : GateFilter, optional.
            A GateFilter instance which specifies which gates should be
            ignored when performing velocity dealiasing. A value of None will
            create this filter from the radar moments using any additional
            arguments by passing them to :py:func:`moment_based_gate_filter`. The
            default value assumes all gates are valid.
        filt : int, optional
            Flag controlling Bergen and Albers filter, 1 = yes, 0 = no.
        rsl_badval : float, optional
            Value which represents a bad value in RSL.
        keep_original : bool, optional
            True to keep original doppler velocity values when the dealiasing
            procedure fails, otherwise these gates will be masked. NaN values
            are still masked.
        set_limits : bool, optional
            True to set valid_min and valid_max elements in the returned
            dictionary. False will not set these dictionary elements.
        vel_field : str, optional
            Field in radar to use as the Doppler velocities during dealiasing.
            None will use the default field name from the Py-ART configuration
            file.
        corr_vel_field : str, optional
            Name to use for the dealiased Doppler velocity field metadata. None
            will use the default field name from the Py-ART configuration file.
        last_vel_field : str, optional
            Name to use for the dealiased Doppler velocity field metadata in
            last_radar. None will use the corr_vel_field name.
        maxshear : float, optional
            Maximum vertical shear which will be incorporated into the created
            volume from the sounding data. Parameter not used when no
            sounding data is provided.
        sign : int, optional
            Sign convention which the radial velocities in the volume created
            from the sounding data will will. This should match the convention
            used in the radar data. A value of 1 represents when positive values
            velocities are towards the radar, -1 represents when negative
            velocities are towards the radar.
        compthresh : float, optional
            Fraction of the Nyquist velocity to use as a threshold when performing
            continuity (initial) dealiasing. Velocities differences above this
            threshold will not be marked as gate from which to begin unfolding
            during spatial dealiasing.
        compthresh2 : float, optional
            The same as compthresh but the value used during the second pass of
            dealiasing. This second pass is only performed in both a sounding
            and last volume are provided.
        thresh : float, optional
            Fraction of the Nyquist velocity to use as a threshold when performing
            spatial dealiasing. Horizontally adjacent gates with velocities above
            this threshold will count against assigning the gate in question the
            velocity value being tested.
        ckval : float, optional
            When the absolute value of the velocities are below this value they
            will not be marked as gates from which to begin unfolding during
            spatial dealiasing.
        stdthresh : float, optional
           Fraction of the Nyquist velocity to use as a standard deviation
           threshold in the window dealiasing portion of the algorithm.
        epsilon : float, optional
            Difference used when comparing a value to missing value, changing this
            from the default is not recommended.
        maxcount : int, optional
            Maximum allowed number of fold allowed when unfolding velocities.
        pass2 : int, optional
            Controls weather unfolded gates should be removed (a value of 0)
            or retained for unfolding during the second pass (a value of 1) when
            both a sounding volume and last volume are provided.
        rm : int, optional
            Determines what should be done with gates that are left unfolded
            after the first pass of dealiasing. A value of 1 will remove these
            gates, a value of 0 sets these gates to their initial velocity.  If
            both a sounding volume and last volume are provided this parameter is
            ignored.
        proximity : int, optional
            Number of gates and rays to include of either side of the current gate
            during window dealiasing. This value may be doubled in cases where
            a standard sized window does not capture a sufficient number of
            good valued gates.
        mingood : int, optional
            Number of good valued gates required within the window before the
            current gate will be unfolded.
        ba_mincount : int, optional
            Number of neighbors required during Bergen and Albers filter for
            a given gate to be included, must be between 1 and 8, 5 recommended.
        ba_edgecount : int, optional
            Same as ba_mincount but used at ray edges, must be between 1 and 5,
            3 recommended.
        debug : bool, optional
            Set True to return RSL Volume objects for debugging:
            usuccess, radialVelVolume, lastVelVolume, unfoldedVolume, sondVolume

        Returns
        -------
        vr_corr : dict
            Field dictionary containing dealiased Doppler velocities. Dealiased
            array is stored under the 'data' key.

        Notes
        -----
        Due to limitations in the C code do not call with sounding arrays over
        999 elements long.

        References
        ----------
        C. N. James and R. A Houze Jr, A Real-Time Four-Dimensional Doppler
        Dealising Scheme, Journal of Atmospheric and Oceanic Technology, 2001, 18,
        1674.

        """
        # check that FourDD is available (requires TRMM RSL)
        if not _FOURDD_AVAILABLE:
            raise MissingOptionalDependency(
                "Py-ART must be build with support for TRMM RSL to use"
                + " the dealias_fourdd function.")

        # verify that sounding data or last_volume is provided
        if (sonde_profile is None) and (last_radar is None):
            raise ValueError('sonde_profile or last_radar must be provided.')

        # parse the field parameters
        if vel_field is None:
            vel_field = get_field_name('velocity')
        if corr_vel_field is None:
            corr_vel_field = get_field_name('corrected_velocity')
        if last_vel_field is None:
            last_vel_field = get_field_name('corrected_velocity')

        # get fill value
        fill_value = get_fillvalue()

        # parse radar gate filter
        gatefilter = _parse_gatefilter(gatefilter, radar, **kwargs)
        excluded = gatefilter.gate_excluded

        # create RSL volumes containing the doppler velocity and
        # doppler velocity in the last radar (if provided)
        vel_volume = _create_rsl_volume(radar, vel_field, 1, rsl_badval, excluded)

        if last_radar is not None:
            last_vel_volume = _create_rsl_volume(
                last_radar, last_vel_field, 1, rsl_badval)
        else:
            last_vel_volume = None

        # create an RslVolume containing the sounding data if it available
        if sonde_profile is not None:
            # convert the sounding data to 1D float32 arrays
            height = np.ascontiguousarray(sonde_profile.height, dtype=np.float32)
            speed = np.ascontiguousarray(sonde_profile.speed, dtype=np.float32)
            wdir = np.ascontiguousarray(sonde_profile.direction, dtype=np.float32)

            if len(height) > 999:
                raise ValueError("Too many sounding heights, maximum is 999")

            success, sound_volume = _fourdd_interface.create_soundvolume(
                vel_volume, height, speed, wdir, sign, max_shear)
            if success == 0:
                raise ValueError('Error when loading sounding data.')
        else:
            sound_volume = None

        # perform dealiasing
        if debug:
            return _fourdd_interface.fourdd_dealias(
                vel_volume, last_vel_volume, sound_volume,
                filt, debug=True, **kwargs)

        _, data = _fourdd_interface.fourdd_dealias(
            vel_volume, last_vel_volume, sound_volume, filt, debug=False, **kwargs)

        # prepare data for output, set bad values and mask data
        is_bad_data = np.logical_or(np.isnan(data), data == rsl_badval)
        if keep_original:
            vel_array = radar.fields[vel_field]['data']
            data = np.where(is_bad_data, vel_array, data)
        else:
            data[is_bad_data] = fill_value
        data = np.ma.masked_equal(data, fill_value)

        # return field dictionary containing dealiased Doppler velocities
        vr_corr = get_metadata(corr_vel_field)
        vr_corr['data'] = data
        vr_corr['_FillValue'] = data.fill_value

        if set_limits:
            nyquist_vel = radar.instrument_parameters['nyquist_velocity']['data']
            _set_limits(data, nyquist_vel, vr_corr)
        return vr_corr

    def _create_rsl_volume(radar, field_name, vol_num, rsl_badval, excluded=None):
        """
        Create a RSLVolume containing data from a field in radar.
        """
        fill_value = get_fillvalue()
        fdata = np.copy(radar.fields[field_name]['data']).astype(np.float32)
        fdata = np.ma.filled(fdata, fill_value)
        is_bad = np.logical_or(fdata == fill_value, np.isnan(fdata))
        fdata[is_bad] = rsl_badval
        if excluded is not None:
            fdata[excluded] = rsl_badval
        rays_per_sweep = (radar.sweep_end_ray_index['data'] -
                          radar.sweep_start_ray_index['data'] + 1)
        rays_per_sweep = rays_per_sweep.astype(np.int32)
        rsl_volume = _rsl_interface.create_volume(fdata, rays_per_sweep, vol_num)

        # add necessary keywords if not defined
        if 'meters_between_gates' not in radar.range:
            radar.range.update({
                'meters_between_gates':
                    radar.range['data'][1]-radar.range['data'][0]})
        if 'meters_to_center_of_first_gate' not in radar.range:
            radar.range.update({
                'meters_to_center_of_first_gate': radar.range['data'][0]})
        _rsl_interface._label_volume(rsl_volume, radar)
        return rsl_volume