예제 #1
0
    def test_height_to_pressure(self):
        """Ensures correct output from height_to_pressure."""

        these_pressures_pascals = standard_atmo.height_to_pressure(
            HEIGHTS_M_ASL)
        self.assertTrue(
            numpy.allclose(these_pressures_pascals, PRESSURES_PASCALS))
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
예제 #3
0
def _run_experiment_one_example(example_dict, example_index, max_noise_k_day01,
                                high_res_pressures_pa, high_res_heights_m_asl,
                                first_interp_method_name,
                                second_interp_method_name, interp_fluxes,
                                output_dir_name):
    """Runs interpolation experiment for one example (one profile).

    H = number of levels in high-resolution grid

    :param example_dict: Dictionary in format returned by
        `example_io.read_file`.
    :param example_index: Will run experiment for [i]th example, where
        i = `example_index`.
    :param max_noise_k_day01: See documentation at top of file.
    :param high_res_pressures_pa: length-H numpy array of pressures (Pascals) in
        high-resolution grid.
    :param high_res_heights_m_asl: length-H numpy array of heights (metres above
        sea level) in high-resolution grid.
    :param first_interp_method_name: See documentation at top of file.
    :param second_interp_method_name: Same.
    :param interp_fluxes: Same.
    :param output_dir_name: Same.
    :return: max_difference_k_day01: Column-max difference between
        low-resolution and fake low-resolution heating rates.
    """

    example_id_string = (
        example_dict[example_utils.EXAMPLE_IDS_KEY][example_index])
    metadata_dict = example_utils.parse_example_ids([example_id_string])
    surface_height_m_asl = geodetic_utils._get_elevation(
        latitude_deg=metadata_dict[example_utils.LATITUDES_KEY][0],
        longitude_deg=metadata_dict[example_utils.LONGITUDES_KEY][0])[0]

    low_res_heights_m_agl = example_dict[example_utils.HEIGHTS_KEY]
    low_res_heights_m_asl = surface_height_m_asl + low_res_heights_m_agl
    low_res_pressures_pa = standard_atmo.height_to_pressure(
        low_res_heights_m_asl)
    low_res_heating_rates_k_day01 = example_utils.get_field_from_dict(
        example_dict=example_dict,
        field_name=example_utils.SHORTWAVE_HEATING_RATE_NAME)[example_index, :]

    if interp_fluxes:
        low_res_down_fluxes_w_m02 = example_utils.get_field_from_dict(
            example_dict=example_dict,
            field_name=example_utils.SHORTWAVE_DOWN_FLUX_NAME)[
                example_index, :]

        interp_object = interp1d(x=low_res_pressures_pa[::-1],
                                 y=low_res_down_fluxes_w_m02[::-1],
                                 kind=first_interp_method_name,
                                 bounds_error=False,
                                 fill_value='extrapolate',
                                 assume_sorted=True)
        high_res_down_fluxes_w_m02 = interp_object(high_res_pressures_pa)

        low_res_up_fluxes_w_m02 = example_utils.get_field_from_dict(
            example_dict=example_dict,
            field_name=example_utils.SHORTWAVE_UP_FLUX_NAME)[example_index, :]

        interp_object = interp1d(x=low_res_pressures_pa[::-1],
                                 y=low_res_up_fluxes_w_m02[::-1],
                                 kind=first_interp_method_name,
                                 bounds_error=False,
                                 fill_value='extrapolate',
                                 assume_sorted=True)
        high_res_up_fluxes_w_m02 = interp_object(high_res_pressures_pa)

        high_res_heating_rates_k_day01 = _fluxes_to_heating_rate(
            down_fluxes_w_m02=high_res_down_fluxes_w_m02,
            up_fluxes_w_m02=high_res_up_fluxes_w_m02,
            pressures_pa=high_res_pressures_pa)

        interp_object = interp1d(x=high_res_pressures_pa[::-1],
                                 y=high_res_down_fluxes_w_m02[::-1],
                                 kind=second_interp_method_name,
                                 bounds_error=True,
                                 assume_sorted=True)
        fake_low_res_down_fluxes_w_m02 = interp_object(low_res_pressures_pa)

        interp_object = interp1d(x=high_res_pressures_pa[::-1],
                                 y=high_res_up_fluxes_w_m02[::-1],
                                 kind=second_interp_method_name,
                                 bounds_error=True,
                                 assume_sorted=True)
        fake_low_res_up_fluxes_w_m02 = interp_object(low_res_pressures_pa)

        fake_low_res_heating_rates_k_day01 = _fluxes_to_heating_rate(
            down_fluxes_w_m02=fake_low_res_down_fluxes_w_m02,
            up_fluxes_w_m02=fake_low_res_up_fluxes_w_m02,
            pressures_pa=low_res_pressures_pa)
    else:
        interp_object = interp1d(x=low_res_pressures_pa[::-1],
                                 y=low_res_heating_rates_k_day01[::-1],
                                 kind=first_interp_method_name,
                                 bounds_error=False,
                                 fill_value='extrapolate',
                                 assume_sorted=True)
        high_res_heating_rates_k_day01 = interp_object(high_res_pressures_pa)

        noise_values_k_day01 = numpy.random.uniform(
            low=-max_noise_k_day01,
            high=max_noise_k_day01,
            size=high_res_heating_rates_k_day01.shape)
        noise_values_k_day01 *= (
            max_noise_k_day01 /
            numpy.max(numpy.absolute(noise_values_k_day01)))
        high_res_heating_rates_k_day01 += noise_values_k_day01

        interp_object = interp1d(x=high_res_pressures_pa[::-1],
                                 y=high_res_heating_rates_k_day01[::-1],
                                 kind=second_interp_method_name,
                                 bounds_error=True,
                                 assume_sorted=True)
        fake_low_res_heating_rates_k_day01 = interp_object(
            low_res_pressures_pa)

    high_res_heights_m_agl = high_res_heights_m_asl - surface_height_m_asl

    figure_object, axes_object = profile_plotting.plot_one_variable(
        values=low_res_heating_rates_k_day01,
        heights_m_agl=low_res_heights_m_agl,
        use_log_scale=True,
        line_colour=LOW_RES_COLOUR,
        line_width=LOW_RES_LINE_WIDTH)
    profile_plotting.plot_one_variable(values=high_res_heating_rates_k_day01,
                                       heights_m_agl=high_res_heights_m_agl,
                                       use_log_scale=True,
                                       line_colour=HIGH_RES_COLOUR,
                                       line_width=HIGH_RES_LINE_WIDTH,
                                       figure_object=figure_object)
    profile_plotting.plot_one_variable(
        values=fake_low_res_heating_rates_k_day01,
        heights_m_agl=low_res_heights_m_agl,
        use_log_scale=True,
        line_colour=FAKE_LOW_RES_COLOUR,
        line_width=FAKE_LOW_RES_LINE_WIDTH,
        figure_object=figure_object)

    axes_object.set_xlim(left=-0.5)
    y_max = axes_object.get_ylim()[1]
    axes_object.set_ylim(top=y_max * 1.05)

    max_difference_k_day01 = numpy.max(
        numpy.absolute(low_res_heating_rates_k_day01 -
                       fake_low_res_heating_rates_k_day01))
    title_string = (
        'Max diff between low-res and reconstructed low-res = {0:.4f} K day'
    ).format(max_difference_k_day01)

    title_string = title_string + r'$^{-1}$'
    axes_object.set_title(title_string, fontsize=20)

    output_file_name = '{0:s}/{1:s}.jpg'.format(output_dir_name,
                                                example_id_string)
    print('Saving figure to: "{0:s}"...'.format(output_file_name))
    figure_object.savefig(output_file_name,
                          dpi=FIGURE_RESOLUTION_DPI,
                          pad_inches=0,
                          bbox_inches='tight')
    pyplot.close(figure_object)

    return max_difference_k_day01
THIS_FIRST_MATRIX = numpy.array([[0.9, 300, -10, 5, 0.02, 310],
                                 [0.7, 285, 0, 15, 0.015, 310],
                                 [0.95, 270, 15, 20, 0.01, 325],
                                 [0.93, 260, 30, 30, 0.007, 341]])
THIS_SECOND_MATRIX = numpy.array([[0.7, 305, 0, 0, 0.015, 312.5],
                                  [0.5, 290, 15, 12.5, 0.015, 310],
                                  [0.8, 273, 25, 15, 0.012, 333],
                                  [0.9, 262, 40, 20, 0.008, 345]])
SOUNDING_MATRIX_NO_PRESSURE = numpy.stack(
    (THIS_FIRST_MATRIX, THIS_SECOND_MATRIX), axis=0)

HEIGHT_LEVELS_M_AGL = numpy.array([0, 1500, 3000, 5000], dtype=int)
STORM_ELEVATIONS_M_ASL = numpy.array([1045, 645], dtype=float)

FIRST_PRESSURES_PASCALS = standard_atmo.height_to_pressure(
    STORM_ELEVATIONS_M_ASL[0] + HEIGHT_LEVELS_M_AGL)
FIRST_PRESSURES_PASCALS = numpy.reshape(FIRST_PRESSURES_PASCALS,
                                        (len(FIRST_PRESSURES_PASCALS), 1))
THIS_FIRST_MATRIX = numpy.hstack((FIRST_PRESSURES_PASCALS, THIS_FIRST_MATRIX))

SECOND_PRESSURES_PASCALS = standard_atmo.height_to_pressure(
    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(