def dewpoint_to_vapour_pressure(dewpoints_kelvins, temperatures_kelvins,
                                total_pressures_pascals):
    """Converts each dewpoint to vapour pressure.

    Source:
    https://content.meteoblue.com/hu/specifications/weather-variables/humidity

    :param dewpoints_kelvins: numpy array (any shape) of dewpoints.
    :param temperatures_kelvins: numpy array (same shape) of temperatures.
    :param total_pressures_pascals: numpy array (same shape) of total air
        pressures.
    :return: vapour_pressures_pascals: numpy array (same shape) of vapour
        pressures.
    """

    error_checking.assert_is_geq_numpy_array(
        dewpoints_kelvins, 0., allow_nan=True
    )
    error_checking.assert_is_geq_numpy_array(
        temperatures_kelvins, 0., allow_nan=True
    )
    error_checking.assert_is_numpy_array(
        temperatures_kelvins,
        exact_dimensions=numpy.array(dewpoints_kelvins.shape, dtype=int)
    )
    error_checking.assert_is_geq_numpy_array(
        total_pressures_pascals, 0., allow_nan=True
    )
    error_checking.assert_is_numpy_array(
        total_pressures_pascals,
        exact_dimensions=numpy.array(dewpoints_kelvins.shape, dtype=int)
    )

    dewpoints_deg_c = temperature_conv.kelvins_to_celsius(dewpoints_kelvins)
    temperatures_deg_c = temperature_conv.kelvins_to_celsius(
        temperatures_kelvins
    )

    numerator_coeffs = numpy.full(
        temperatures_deg_c.shape, MAGNUS_NUMERATOR_COEFF_WATER
    )
    numerator_coeffs[temperatures_deg_c < 0] = MAGNUS_NUMERATOR_COEFF_ICE
    numerators = numerator_coeffs * dewpoints_deg_c

    denominator_coeffs = numpy.full(
        temperatures_deg_c.shape, MAGNUS_DENOMINATOR_COEFF_WATER
    )
    denominator_coeffs[temperatures_deg_c < 0] = MAGNUS_DENOMINATOR_COEFF_ICE
    denominators = denominator_coeffs + dewpoints_deg_c

    vapour_pressures_pascals = (
        BASE_VAPOUR_PRESSURE_PASCALS * numpy.exp(numerators / denominators)
    )

    vapour_pressures_pascals[
        numpy.invert(numpy.isfinite(vapour_pressures_pascals))
    ] = 0.

    vapour_pressures_pascals[denominators <= 0] = 0.
    return numpy.minimum(vapour_pressures_pascals, total_pressures_pascals)
Ejemplo n.º 2
0
    def test_kelvins_to_celsius(self):
        """Ensures correct output from kelvins_to_celsius."""

        these_temperatures_deg_c = temperature_conversions.kelvins_to_celsius(
            TEMPERATURES_KELVINS)
        self.assertTrue(
            numpy.allclose(these_temperatures_deg_c,
                           TEMPERATURES_DEG_C,
                           atol=TOLERANCE))
def vapour_pressure_to_dewpoint(vapour_pressures_pascals, temperatures_kelvins):
    """Converts each vapour pressure to dewpoint.

    Source:
    https://content.meteoblue.com/hu/specifications/weather-variables/humidity

    :param vapour_pressures_pascals: numpy array (any shape) of vapour
        pressures.
    :param temperatures_kelvins: numpy array (same shape) of temperatures.
    :return: dewpoints_kelvins: numpy array (same shape) of dewpoints.
    """

    error_checking.assert_is_geq_numpy_array(
        vapour_pressures_pascals, 0., allow_nan=True
    )
    error_checking.assert_is_geq_numpy_array(
        temperatures_kelvins, 0., allow_nan=True
    )
    error_checking.assert_is_numpy_array(
        temperatures_kelvins,
        exact_dimensions=numpy.array(vapour_pressures_pascals.shape, dtype=int)
    )

    logarithms = numpy.log(
        vapour_pressures_pascals / BASE_VAPOUR_PRESSURE_PASCALS
    )

    temperatures_deg_c = temperature_conv.kelvins_to_celsius(
        temperatures_kelvins
    )

    numerator_coeffs = numpy.full(
        temperatures_deg_c.shape, MAGNUS_DENOMINATOR_COEFF_WATER
    )
    numerator_coeffs[temperatures_deg_c < 0] = MAGNUS_DENOMINATOR_COEFF_ICE
    numerators = numerator_coeffs * logarithms

    denominator_coeffs = numpy.full(
        temperatures_deg_c.shape, MAGNUS_NUMERATOR_COEFF_WATER
    )
    denominator_coeffs[temperatures_deg_c < 0] = MAGNUS_NUMERATOR_COEFF_ICE
    denominators = denominator_coeffs - logarithms

    dewpoints_deg_c = numerators / denominators
    dewpoints_kelvins = temperature_conv.celsius_to_kelvins(dewpoints_deg_c)

    dewpoints_kelvins[numpy.invert(numpy.isfinite(dewpoints_kelvins))] = 0.
    dewpoints_kelvins[dewpoints_deg_c + numerator_coeffs < 0] = 0.

    return dewpoints_kelvins
def soundings_to_metpy_dictionaries(sounding_matrix,
                                    field_names,
                                    height_levels_m_agl=None,
                                    storm_elevations_m_asl=None):
    """Converts soundings to format required by MetPy.

    If `sounding_matrix` contains pressures, `height_levels_m_agl` and
    `storm_elevations_m_asl` will not be used.

    Otherwise, `height_levels_m_agl` and `storm_elevations_m_asl` will be used
    to estimate the pressure levels for each sounding.

    :param sounding_matrix: numpy array (E x H_s x F_s) of soundings.
    :param field_names: list (length F_s) of field names, in the order that they
        appear in `sounding_matrix`.
    :param height_levels_m_agl: numpy array (length H_s) of height levels
        (metres above ground level), in the order that they appear in
        `sounding_matrix`.
    :param storm_elevations_m_asl: length-E numpy array of storm elevations
        (metres above sea level).
    :return: list_of_metpy_dictionaries: length-E list of dictionaries.  The
        format of each dictionary is described in the input doc for
        `sounding_plotting.plot_sounding`.
    """

    error_checking.assert_is_string_list(field_names)
    error_checking.assert_is_numpy_array(numpy.array(field_names),
                                         num_dimensions=1)
    check_soundings(sounding_matrix=sounding_matrix,
                    num_fields=len(field_names))

    try:
        pressure_index = field_names.index(soundings.PRESSURE_NAME)
        pressure_matrix_pascals = sounding_matrix[..., pressure_index]
    except ValueError:
        error_checking.assert_is_geq_numpy_array(height_levels_m_agl, 0)
        error_checking.assert_is_numpy_array(height_levels_m_agl,
                                             num_dimensions=1)

        error_checking.assert_is_numpy_array_without_nan(
            storm_elevations_m_asl)
        error_checking.assert_is_numpy_array(storm_elevations_m_asl,
                                             num_dimensions=1)

        num_height_levels = len(height_levels_m_agl)
        num_examples = len(storm_elevations_m_asl)
        check_soundings(sounding_matrix=sounding_matrix,
                        num_examples=num_examples,
                        num_height_levels=num_height_levels)

        height_matrix_m_asl = numpy.full((num_examples, num_height_levels),
                                         numpy.nan)
        for i in range(num_examples):
            height_matrix_m_asl[i, ...] = (height_levels_m_agl +
                                           storm_elevations_m_asl[i])

        pressure_matrix_pascals = standard_atmo.height_to_pressure(
            height_matrix_m_asl)

    try:
        temperature_index = field_names.index(soundings.TEMPERATURE_NAME)
        temperature_matrix_kelvins = sounding_matrix[..., temperature_index]
    except ValueError:
        virtual_pot_temp_index = field_names.index(
            soundings.VIRTUAL_POTENTIAL_TEMPERATURE_NAME)
        temperature_matrix_kelvins = (
            temperature_conversions.temperatures_from_potential_temperatures(
                potential_temperatures_kelvins=sounding_matrix[
                    ..., virtual_pot_temp_index],
                total_pressures_pascals=pressure_matrix_pascals))

    try:
        specific_humidity_index = field_names.index(
            soundings.SPECIFIC_HUMIDITY_NAME)
        dewpoint_matrix_kelvins = (
            moisture_conversions.specific_humidity_to_dewpoint(
                specific_humidities_kg_kg01=sounding_matrix[
                    ..., specific_humidity_index],
                total_pressures_pascals=pressure_matrix_pascals))
    except ValueError:
        relative_humidity_index = field_names.index(
            soundings.RELATIVE_HUMIDITY_NAME)
        dewpoint_matrix_kelvins = (
            moisture_conversions.relative_humidity_to_dewpoint(
                relative_humidities=sounding_matrix[...,
                                                    relative_humidity_index],
                temperatures_kelvins=temperature_matrix_kelvins,
                total_pressures_pascals=pressure_matrix_pascals))

    temperature_matrix_celsius = temperature_conversions.kelvins_to_celsius(
        temperature_matrix_kelvins)
    dewpoint_matrix_celsius = temperature_conversions.kelvins_to_celsius(
        dewpoint_matrix_kelvins)

    try:
        u_wind_index = field_names.index(soundings.U_WIND_NAME)
        v_wind_index = field_names.index(soundings.V_WIND_NAME)
        include_wind = True
    except ValueError:
        include_wind = False

    num_examples = sounding_matrix.shape[0]
    list_of_metpy_dictionaries = [None] * num_examples

    for i in range(num_examples):
        list_of_metpy_dictionaries[i] = {
            soundings.PRESSURE_COLUMN_METPY:
            pressure_matrix_pascals[i, :] * PASCALS_TO_MB,
            soundings.TEMPERATURE_COLUMN_METPY:
            temperature_matrix_celsius[i, :],
            soundings.DEWPOINT_COLUMN_METPY: dewpoint_matrix_celsius[i, :],
        }

        if include_wind:
            list_of_metpy_dictionaries[i].update({
                soundings.U_WIND_COLUMN_METPY:
                (sounding_matrix[i, ..., u_wind_index] *
                 METRES_PER_SECOND_TO_KT),
                soundings.V_WIND_COLUMN_METPY:
                (sounding_matrix[i, ..., v_wind_index] *
                 METRES_PER_SECOND_TO_KT)
            })

    return list_of_metpy_dictionaries
Ejemplo n.º 5
0
def plot_predictors(
        example_dict, example_index, predictor_names, predictor_colours,
        predictor_line_widths, predictor_line_styles, use_log_scale,
        include_units=True, handle_dict=None):
    """Plots several predictors on the same set of axes.

    P = number of predictors to plot (must all be profiles)

    :param example_dict: See doc for `example_io.read_file`.
    :param example_index: Will plot the [i]th example, where
        i = `example_index`.
    :param predictor_names: length-P list with names of predictors to plot.
    :param predictor_colours: length-P list of colours (each colour in any
        format accepted by matplotlib).
    :param predictor_line_widths: length-P numpy array of line widths.
    :param predictor_line_styles: length-P list of line styles (each style in
        any format accepted by matplotlib).
    :param use_log_scale: Boolean flag.  If True, will plot height (y-axis) in
        logarithmic scale.  If False, will plot height in linear scale.
    :param include_units: Boolean flag.  If True, axis titles will include units
        and values will be converted from default to plotting units.  If False,
        axis titles will *not* include units and this method will *not* convert
        units.
    :param handle_dict: See output doc.  If None, will create new figure on the
        fly.
    :return: handle_dict: Dictionary with the following keys.
    handle_dict['figure_object']: Figure handle (instance of
        `matplotlib.figure.Figure`).
    handle_dict['axes_objects']: length-P list of axes handles (each an instance
        of `matplotlib.axes._subplots.AxesSubplot`).
    """

    # Check input args.
    error_checking.assert_is_integer(example_index)
    error_checking.assert_is_geq(example_index, 0)
    error_checking.assert_is_boolean(use_log_scale)
    error_checking.assert_is_boolean(include_units)

    error_checking.assert_is_string_list(predictor_names)
    num_predictors = len(predictor_names)
    error_checking.assert_is_leq(num_predictors, 4)

    for k in range(num_predictors):
        assert predictor_names[k] in example_utils.ALL_PREDICTOR_NAMES
        # assert predictor_names[k] in example_utils.ALL_VECTOR_PREDICTOR_NAMES

    assert len(predictor_colours) == num_predictors
    assert len(predictor_line_widths) == num_predictors
    assert len(predictor_line_styles) == num_predictors

    # Housekeeping.
    _set_font_size(FANCY_FONT_SIZE)

    if handle_dict is None:
        figure_object, first_axes_object = pyplot.subplots(
            1, 1,
            figsize=(FANCY_FIGURE_WIDTH_INCHES, FANCY_FIGURE_HEIGHT_INCHES)
        )

        axes_objects = [first_axes_object]
        figure_object.subplots_adjust(bottom=0.75)

        if use_log_scale:
            pyplot.yscale('log')

        for k in range(1, num_predictors):
            axes_objects.append(axes_objects[0].twiny())

            if k == 2:
                axes_objects[k].spines['top'].set_position(('axes', 1.15))
                _make_spines_invisible(axes_objects[k])
                axes_objects[k].spines['top'].set_visible(True)

            if k == 3:
                axes_objects[k].xaxis.set_ticks_position('bottom')
                axes_objects[k].xaxis.set_label_position('bottom')
                axes_objects[k].spines['bottom'].set_position(('axes', -0.15))
                _make_spines_invisible(axes_objects[k])
                axes_objects[k].spines['bottom'].set_visible(True)
    else:
        figure_object = handle_dict[FIGURE_HANDLE_KEY]
        axes_objects = handle_dict[AXES_OBJECTS_KEY]

    heights_km_agl = METRES_TO_KM * example_dict[example_utils.HEIGHTS_KEY]
    tick_mark_dict = dict(size=4, width=1.5)

    for k in range(num_predictors):
        if predictor_names[k] in example_utils.ALL_SCALAR_PREDICTOR_NAMES:

            # TODO(thunderhoser): This is a HACK to deal with saliency maps.
            j = example_dict[example_utils.SCALAR_PREDICTOR_NAMES_KEY].index(
                predictor_names[k]
            )
            these_predictor_values = (
                example_dict[example_utils.SCALAR_PREDICTOR_VALS_KEY][
                    example_index, :, j
                ]
            )
        else:
            these_predictor_values = example_utils.get_field_from_dict(
                example_dict=example_dict, field_name=predictor_names[k]
            )[example_index, ...]

        if include_units:
            if predictor_names[k] == example_utils.TEMPERATURE_NAME:
                these_predictor_values = temperature_conv.kelvins_to_celsius(
                    these_predictor_values
                )
            else:
                these_predictor_values = (
                    PREDICTOR_NAME_TO_CONV_FACTOR[predictor_names[k]] *
                    these_predictor_values
                )

        axes_objects[k].plot(
            these_predictor_values, heights_km_agl, color=predictor_colours[k],
            linewidth=predictor_line_widths[k],
            linestyle=predictor_line_styles[k]
        )

        x_label_string = copy.deepcopy(
            PREDICTOR_NAME_TO_VERBOSE[predictor_names[k]]
        )
        if not include_units:
            x_label_string = x_label_string.split(' (')[0]

        axes_objects[k].set_xlabel(x_label_string)
        axes_objects[k].xaxis.label.set_color(predictor_colours[k])
        axes_objects[k].tick_params(
            axis='x', colors=predictor_colours[k], **tick_mark_dict
        )

    axes_objects[0].set_ylabel('Height (km AGL)')
    axes_objects[0].set_ylim([
        numpy.min(heights_km_agl), numpy.max(heights_km_agl)
    ])

    height_strings = create_height_labels(
        tick_values_km_agl=axes_objects[0].get_yticks(),
        use_log_scale=use_log_scale
    )
    axes_objects[0].set_yticklabels(height_strings)
    axes_objects[0].tick_params(axis='y', **tick_mark_dict)

    return {
        FIGURE_HANDLE_KEY: figure_object,
        AXES_OBJECTS_KEY: axes_objects
    }
    STORM_ELEVATIONS_M_ASL[1] + HEIGHT_LEVELS_M_AGL)
SECOND_PRESSURES_PASCALS = numpy.reshape(SECOND_PRESSURES_PASCALS,
                                         (len(SECOND_PRESSURES_PASCALS), 1))
THIS_SECOND_MATRIX = numpy.hstack(
    (SECOND_PRESSURES_PASCALS, THIS_SECOND_MATRIX))

SOUNDING_MATRIX_UNNORMALIZED = numpy.stack(
    (THIS_FIRST_MATRIX, THIS_SECOND_MATRIX), axis=0)

FIRST_DEWPOINTS_KELVINS = moisture_conversions.specific_humidity_to_dewpoint(
    specific_humidities_kg_kg01=THIS_FIRST_MATRIX[:, 5],
    total_pressures_pascals=THIS_FIRST_MATRIX[:, 0])

FIRST_METPY_DICT = {
    soundings.TEMPERATURE_COLUMN_METPY:
    temperature_conversions.kelvins_to_celsius(THIS_FIRST_MATRIX[:, 2]),
    soundings.U_WIND_COLUMN_METPY:
    METRES_PER_SECOND_TO_KT * THIS_FIRST_MATRIX[:, 3],
    soundings.V_WIND_COLUMN_METPY:
    METRES_PER_SECOND_TO_KT * THIS_FIRST_MATRIX[:, 4],
    soundings.DEWPOINT_COLUMN_METPY:
    temperature_conversions.kelvins_to_celsius(FIRST_DEWPOINTS_KELVINS),
    soundings.PRESSURE_COLUMN_METPY:
    THIS_FIRST_MATRIX[:, 0] * PASCALS_TO_MB
}

SECOND_DEWPOINTS_KELVINS = moisture_conversions.specific_humidity_to_dewpoint(
    specific_humidities_kg_kg01=THIS_SECOND_MATRIX[:, 5],
    total_pressures_pascals=THIS_SECOND_MATRIX[:, 0])

SECOND_METPY_DICT = {