def mixing_ratio_to_specific_humidity(mixing_ratios_kg_kg01):
    """Converts one or more mixing ratios to specific humidities.

    :param mixing_ratios_kg_kg01: numpy array of mixing ratios (kg per kg).
    :return: specific_humidities_kg_kg01: equivalent-size numpy array of
        specific humidities (kg per kg).
    """

    error_checking.assert_is_real_numpy_array(mixing_ratios_kg_kg01)
    return mixing_ratios_kg_kg01 / (1 + mixing_ratios_kg_kg01)
def fahrenheit_to_celsius(temperatures_deg_f):
    """Converts temperatures from Fahrenheit (deg F) to Celsius (deg C).

    :param temperatures_deg_f: numpy array of temperatures in deg F.
    :return: temperatures_deg_c: equivalent-size numpy array of temperatures in
        deg C.
    """

    error_checking.assert_is_real_numpy_array(temperatures_deg_f)
    return ((temperatures_deg_f + FAHRENHEIT_TO_CELSIUS_ADDEND) *
            FAHRENHEIT_TO_CELSIUS_RATIO)
def specific_humidity_to_mixing_ratio(specific_humidities_kg_kg01):
    """Converts one or more specific humidities to mixing ratios.

    :param specific_humidities_kg_kg01: numpy array of specific humidities
        (kg per kg).
    :return: mixing_ratios_kg_kg01: equivalent-size numpy array of mixing ratios
        (kg per kg).
    """

    error_checking.assert_is_real_numpy_array(specific_humidities_kg_kg01)
    return specific_humidities_kg_kg01 / (1 - specific_humidities_kg_kg01)
def celsius_to_fahrenheit(temperatures_deg_c):
    """Converts temperatures from Celsius (deg C) to Fahrenheit (deg F).

    :param temperatures_deg_c: numpy array of temperatures in deg C.
    :return: temperatures_deg_f: equivalent-size numpy array of temperatures in
        deg F.
    """

    error_checking.assert_is_real_numpy_array(temperatures_deg_c)
    return (temperatures_deg_c /
            FAHRENHEIT_TO_CELSIUS_RATIO) - FAHRENHEIT_TO_CELSIUS_ADDEND
Beispiel #5
0
def get_echo_tops(reflectivity_matrix_dbz, grid_point_heights_m_asl,
                  critical_reflectivity_dbz):
    """Finds echo top at each horizontal location.

    "Echo top" = maximum height with >= critical reflectivity.

    M = number of rows (unique grid-point latitudes)
    N = number of columns (unique grid-point longitudes)
    H = number of height levels (unique grid-point heights)

    :param reflectivity_matrix_dbz: H-by-M-by-N matrix of reflectivities.
    :param grid_point_heights_m_asl: length-H numpy array of grid-point heights
        (metres above sea level).  Must be sorted in ascending order, which
        means that height must increase with the first index of
        reflectivity_matrix_dbz.
    :param critical_reflectivity_dbz: Critical reflectivity.
    :return: echo_top_matrix_m_asl: M-by-N matrix of echo tops (metres above sea
        level).
    :raises: ValueError: grid_point_heights_m_asl not sorted in ascending
        order.
    """

    error_checking.assert_is_numpy_array(reflectivity_matrix_dbz,
                                         num_dimensions=3)
    error_checking.assert_is_real_numpy_array(reflectivity_matrix_dbz)
    error_checking.assert_is_greater(critical_reflectivity_dbz, 0.)

    num_grid_heights = reflectivity_matrix_dbz.shape[0]
    num_grid_rows = reflectivity_matrix_dbz.shape[1]
    num_grid_columns = reflectivity_matrix_dbz.shape[2]

    error_checking.assert_is_numpy_array(grid_point_heights_m_asl,
                                         exact_dimensions=numpy.array(
                                             [num_grid_heights]))
    error_checking.assert_is_geq_numpy_array(grid_point_heights_m_asl, 0.)

    sorted_heights_m_asl = numpy.sort(grid_point_heights_m_asl)
    if not numpy.array_equal(sorted_heights_m_asl, grid_point_heights_m_asl):
        raise ValueError('grid_point_heights_m_asl are not sorted in '
                         'ascending order.')

    echo_top_matrix_m_asl = numpy.full((num_grid_rows, num_grid_columns),
                                       numpy.nan)
    for i in range(num_grid_rows):
        for j in range(num_grid_columns):
            echo_top_matrix_m_asl[i, j] = (
                radar_utils.get_echo_top_single_column(
                    reflectivities_dbz=reflectivity_matrix_dbz[:, i, j],
                    heights_m_asl=grid_point_heights_m_asl,
                    critical_reflectivity_dbz=critical_reflectivity_dbz,
                    check_args=False))

    return echo_top_matrix_m_asl
Beispiel #6
0
def rowcol_to_latlng(grid_rows, grid_columns, nw_grid_point_lat_deg,
                     nw_grid_point_lng_deg, lat_spacing_deg, lng_spacing_deg):
    """Converts radar coordinates from row-column to lat-long.

    P = number of input grid points

    :param grid_rows: length-P numpy array with row indices of grid points
        (increasing from north to south).
    :param grid_columns: length-P numpy array with column indices of grid points
        (increasing from west to east).
    :param nw_grid_point_lat_deg: Latitude (deg N) of northwesternmost grid
        point.
    :param nw_grid_point_lng_deg: Longitude (deg E) of northwesternmost grid
        point.
    :param lat_spacing_deg: Spacing (deg N) between meridionally adjacent grid
        points.
    :param lng_spacing_deg: Spacing (deg E) between zonally adjacent grid
        points.
    :return: latitudes_deg: length-P numpy array with latitudes (deg N) of grid
        points.
    :return: longitudes_deg: length-P numpy array with longitudes (deg E) of
        grid points.
    """

    error_checking.assert_is_real_numpy_array(grid_rows)
    error_checking.assert_is_geq_numpy_array(grid_rows, -0.5, allow_nan=True)
    error_checking.assert_is_numpy_array(grid_rows, num_dimensions=1)
    num_points = len(grid_rows)

    error_checking.assert_is_real_numpy_array(grid_columns)
    error_checking.assert_is_geq_numpy_array(grid_columns,
                                             -0.5,
                                             allow_nan=True)
    error_checking.assert_is_numpy_array(grid_columns,
                                         exact_dimensions=numpy.array(
                                             [num_points]))

    error_checking.assert_is_valid_latitude(nw_grid_point_lat_deg)
    nw_grid_point_lng_deg = lng_conversion.convert_lng_positive_in_west(
        nw_grid_point_lng_deg, allow_nan=False)

    error_checking.assert_is_greater(lat_spacing_deg, 0.)
    error_checking.assert_is_greater(lng_spacing_deg, 0.)

    latitudes_deg = rounder.round_to_nearest(
        nw_grid_point_lat_deg - lat_spacing_deg * grid_rows,
        lat_spacing_deg / 2)
    longitudes_deg = rounder.round_to_nearest(
        nw_grid_point_lng_deg + lng_spacing_deg * grid_columns,
        lng_spacing_deg / 2)
    return latitudes_deg, lng_conversion.convert_lng_positive_in_west(
        longitudes_deg, allow_nan=True)
Beispiel #7
0
def latlng_field_grid_points_to_edges(field_matrix=None,
                                      min_latitude_deg=None,
                                      min_longitude_deg=None,
                                      lat_spacing_deg=None,
                                      lng_spacing_deg=None):
    """Re-references lat-long field from grid points to edges.

    M = number of rows (unique grid-point latitudes)
    N = number of columns (unique grid-point longitudes)

    :param field_matrix: M-by-N numpy array with values of some variable
        (examples: temperature, radar reflectivity, etc.).  Latitude should
        increase while traveling down a column, and longitude should increase
        while traveling right across a row.
    :param min_latitude_deg: See documentation for get_latlng_grid_points.
    :param min_longitude_deg: See documentation for get_latlng_grid_points.
    :param lat_spacing_deg: See documentation for get_latlng_grid_points.
    :param lng_spacing_deg: See documentation for get_latlng_grid_points.
    :param num_rows: See documentation for get_latlng_grid_points.
    :param num_columns: See documentation for get_latlng_grid_points.
    :return: field_matrix: Same as input, except that dimensions are now (M + 1)
        by (N + 1).  The last row and last column contain only NaN's.
    :return: grid_cell_edge_latitudes_deg: length-(M + 1) numpy array with
        latitudes of grid-cell edges (deg N).
    :return: grid_cell_edge_longitudes_deg: length-(N + 1) numpy array with
        longitudes of grid-cell edges (deg E).
    """

    error_checking.assert_is_real_numpy_array(field_matrix)
    error_checking.assert_is_numpy_array(field_matrix, num_dimensions=2)

    num_rows = field_matrix.shape[0]
    num_columns = field_matrix.shape[1]

    (grid_cell_edge_latitudes_deg,
     grid_cell_edge_longitudes_deg) = get_latlng_grid_cell_edges(
         min_latitude_deg=min_latitude_deg,
         min_longitude_deg=min_longitude_deg,
         lat_spacing_deg=lat_spacing_deg,
         lng_spacing_deg=lng_spacing_deg,
         num_rows=num_rows,
         num_columns=num_columns)

    nan_row = numpy.full((1, num_columns), numpy.nan)
    field_matrix = numpy.vstack((field_matrix, nan_row))

    nan_column = numpy.full((num_rows + 1, 1), numpy.nan)
    field_matrix = numpy.hstack((field_matrix, nan_column))

    return (field_matrix, grid_cell_edge_latitudes_deg,
            grid_cell_edge_longitudes_deg)
def project_xy_to_latlng(x_coords_metres,
                         y_coords_metres,
                         projection_object=None,
                         false_easting_metres=0.,
                         false_northing_metres=0.):
    """Converts from projection (x-y) to lat-long coordinates.

    P = number of points

    :param x_coords_metres: length-P numpy array of x-coordinates.
    :param y_coords_metres: length-P numpy array of y-coordinates.
    :param projection_object: Projection object created by `pyproj.Proj`.
    :param false_easting_metres: False easting.  Will be subtracted from all x-
        coordinates before conversion.
    :param false_northing_metres: False northing.  Will be subtracted from all
        y-coordinates before conversion.
    :return: latitudes_deg: length-P numpy array of latitudes (deg N).
    :return: longitudes_deg: length-P numpy array of longitudes (deg E).
    """

    error_checking.assert_is_real_numpy_array(x_coords_metres)

    shape_of_coord_arrays = x_coords_metres.shape
    error_checking.assert_is_numpy_array(
        y_coords_metres, exact_dimensions=numpy.asarray(shape_of_coord_arrays))
    error_checking.assert_is_real_numpy_array(y_coords_metres)

    error_checking.assert_is_not_nan(false_easting_metres)
    error_checking.assert_is_not_nan(false_northing_metres)

    (longitudes_deg, latitudes_deg) = projection_object(
        x_coords_metres - false_easting_metres,
        y_coords_metres - false_northing_metres,
        inverse=True)

    num_points = x_coords_metres.size
    nan_flags = numpy.logical_or(
        numpy.isnan(numpy.reshape(x_coords_metres, num_points)),
        numpy.isnan(numpy.reshape(y_coords_metres, num_points)))
    nan_indices = numpy.where(nan_flags)[0]

    latitudes_deg_flat = numpy.reshape(latitudes_deg, num_points)
    latitudes_deg_flat[nan_indices] = numpy.nan

    longitudes_deg_flat = numpy.reshape(longitudes_deg, num_points)
    longitudes_deg_flat[nan_indices] = numpy.nan
    longitudes_deg_flat = lng_conversion.convert_lng_positive_in_west(
        longitudes_deg_flat, allow_nan=True)

    return (numpy.reshape(latitudes_deg_flat, shape_of_coord_arrays),
            numpy.reshape(longitudes_deg_flat, shape_of_coord_arrays))
def add_colour_bar(axes_object,
                   values_to_colour=None,
                   colour_map=None,
                   colour_norm_object=None,
                   orientation=DEFAULT_COLOUR_BAR_ORIENTATION,
                   extend_min=True,
                   extend_max=True):
    """Adds colour bar to existing plot.

    :param axes_object: Instance of `matplotlib.axes._subplots.AxesSubplot`.
    :param values_to_colour: numpy array of values to which the colour map will
        be applied.
    :param colour_map: Instance of `matplotlib.pyplot.cm`.
    :param colour_norm_object: Instance of `matplotlib.colors.Normalize`.
    :param orientation: Orientation (either "horizontal" or "vertical").
    :param extend_min: Boolean flag.  If extend_min = True, will add arrow to
        bottom end of colour bar.  Otherwise, bottom of colour bar will be
        rectangular.
    :param extend_max: Same as extend_min, but for upper end of colour bar.
    :return: colour_bar_object: Instance of `matplotlib.pyplot.colorbar` created
        by this method.
    """

    error_checking.assert_is_real_numpy_array(values_to_colour)
    error_checking.assert_is_boolean(extend_min)
    error_checking.assert_is_boolean(extend_max)

    scalar_mappable_object = pyplot.cm.ScalarMappable(cmap=colour_map,
                                                      norm=colour_norm_object)
    scalar_mappable_object.set_array(values_to_colour)

    if extend_min and extend_max:
        extend_argument = 'both'
    elif extend_min:
        extend_argument = 'min'
    elif extend_max:
        extend_argument = 'max'
    else:
        extend_argument = 'neither'

    if orientation == 'horizontal':
        this_padding = PADDING_FOR_HORIZ_COLOUR_BAR
    else:
        this_padding = PADDING_FOR_VERTICAL_COLOUR_BAR

    return pyplot.colorbar(ax=axes_object,
                           mappable=scalar_mappable_object,
                           orientation=orientation,
                           pad=this_padding,
                           extend=extend_argument)
Beispiel #10
0
def round_to_half_integer(input_value):
    """Rounds numbers to nearest half-integer that is not also an integer.

    :param input_value: Either numpy array of real numbers or scalar real
        number.
    :return: output_value: Same as input_value, except rounded.
    """

    if isinstance(input_value, collections.Iterable):
        error_checking.assert_is_real_numpy_array(input_value)
    else:
        error_checking.assert_is_real_number(input_value)

    return numpy.round(input_value + 0.5) - 0.5
Beispiel #11
0
def find_invalid_latitudes(latitudes_deg):
    """Returns array indices of invalid latitudes.

    :param latitudes_deg: 1-D numpy array of latitudes (deg N).
    :return: invalid_indices: 1-D numpy array with array indices of invalid
        latitudes.
    """

    error_checking.assert_is_real_numpy_array(latitudes_deg)
    error_checking.assert_is_numpy_array(latitudes_deg, num_dimensions=1)

    valid_flags = numpy.logical_and(latitudes_deg >= MIN_LATITUDE_DEG,
                                    latitudes_deg <= MAX_LATITUDE_DEG)
    return numpy.where(numpy.invert(valid_flags))[0]
Beispiel #12
0
def xy_field_grid_points_to_edges(field_matrix=None,
                                  x_min_metres=None,
                                  y_min_metres=None,
                                  x_spacing_metres=None,
                                  y_spacing_metres=None):
    """Re-references x-y field from grid points to edges.

    M = number of rows (unique grid-point x-coordinates)
    N = number of columns (unique grid-point y-coordinates)

    :param field_matrix: M-by-N numpy array with values of some variable
        (examples: temperature, radar reflectivity, etc.).  y should increase
        while traveling down a column, and x should increase while traveling
        right across a row.
    :param x_min_metres: Minimum x-coordinate over all grid points.
    :param y_min_metres: Minimum y-coordinate over all grid points.
    :param x_spacing_metres: Spacing between adjacent grid points in x-
        direction.
    :param y_spacing_metres: Spacing between adjacent grid points in y-
        direction.
    :return: field_matrix: Same as input, except that dimensions are now (M + 1)
        by (N + 1).  The last row and last column contain only NaN's.
    :return: grid_cell_edge_x_metres: length-(N + 1) numpy array with x-
        coordinates of grid-cell edges.
    :return: grid_cell_edge_y_metres: length-(M + 1) numpy array with y-
        coordinates of grid-cell edges.
    """

    error_checking.assert_is_real_numpy_array(field_matrix)
    error_checking.assert_is_numpy_array(field_matrix, num_dimensions=2)

    num_rows = field_matrix.shape[0]
    num_columns = field_matrix.shape[1]

    grid_cell_edge_x_metres, grid_cell_edge_y_metres = get_xy_grid_cell_edges(
        x_min_metres=x_min_metres,
        y_min_metres=y_min_metres,
        x_spacing_metres=x_spacing_metres,
        y_spacing_metres=y_spacing_metres,
        num_rows=num_rows,
        num_columns=num_columns)

    nan_row = numpy.full((1, num_columns), numpy.nan)
    field_matrix = numpy.vstack((field_matrix, nan_row))

    nan_column = numpy.full((num_rows + 1, 1), numpy.nan)
    field_matrix = numpy.hstack((field_matrix, nan_column))

    return field_matrix, grid_cell_edge_x_metres, grid_cell_edge_y_metres
Beispiel #13
0
def get_spatial_statistics(radar_field,
                           statistic_names=DEFAULT_STATISTIC_NAMES,
                           percentile_levels=DEFAULT_PERCENTILE_LEVELS):
    """Computes spatial statistics for a single radar field.

    "Single field" = one variable at one elevation, one time step, many spatial
    locations.

    Radar field may have any number of dimensions (1-D, 2-D, etc.).

    N = number of non-percentile-based statistics
    P = number of percentile levels

    :param radar_field: numpy array.  Each position in the array should be a
        different spatial location.
    :param statistic_names: length-N list of non-percentile-based statistics.
    :param percentile_levels: length-P numpy array of percentile levels.
    :return: statistic_values: length-N numpy with values of non-percentile-
        based statistics.
    :return: percentile_values: length-P numpy array of percentiles.
    """

    error_checking.assert_is_real_numpy_array(radar_field)
    percentile_levels = _check_statistic_params(statistic_names,
                                                percentile_levels)

    num_statistics = len(statistic_names)
    statistic_values = numpy.full(num_statistics, numpy.nan)
    for i in range(num_statistics):
        if statistic_names[i] == AVERAGE_NAME:
            statistic_values[i] = numpy.nanmean(radar_field)
        elif statistic_names[i] == STANDARD_DEVIATION_NAME:
            statistic_values[i] = numpy.nanstd(radar_field, ddof=1)
        elif statistic_names[i] == SKEWNESS_NAME:
            statistic_values[i] = scipy.stats.skew(radar_field,
                                                   bias=False,
                                                   nan_policy='omit',
                                                   axis=None)
        elif statistic_names[i] == KURTOSIS_NAME:
            statistic_values[i] = scipy.stats.kurtosis(radar_field,
                                                       fisher=True,
                                                       bias=False,
                                                       nan_policy='omit',
                                                       axis=None)

    percentile_values = numpy.nanpercentile(radar_field,
                                            percentile_levels,
                                            interpolation='linear')
    return statistic_values, percentile_values
Beispiel #14
0
def rotate_winds(u_winds_grid_relative_m_s01=None,
                 v_winds_grid_relative_m_s01=None,
                 rotation_angle_cosines=None,
                 rotation_angle_sines=None):
    """Rotates wind vectors from grid-relative to Earth-relative.

    The equation is as follows, where alpha is the rotation angle.

    u_Earth = u_grid * cos(alpha) + v_grid * sin(alpha)
    v_Earth = v_grid * cos(alpha) - u_grid * sin(alpha)

    :param u_winds_grid_relative_m_s01: numpy array of grid-relative u-winds
        (towards positive x-direction).
    :param v_winds_grid_relative_m_s01: equivalent-shape numpy array of grid-
        relative v-winds (towards positive y-direction).
    :param rotation_angle_cosines: equivalent-shape numpy array with cosines of
        rotation angles.
    :param rotation_angle_sines: equivalent-shape numpy array with sines of
        rotation angles.
    :return: u_winds_earth_relative_m_s01: equivalent-shape numpy array of
        Earth-relative (northward) u-winds.
    :return: v_winds_earth_relative_m_s01: equivalent-shape numpy array of
        Earth-relative (eastward) v-winds.
    """

    error_checking.assert_is_real_numpy_array(u_winds_grid_relative_m_s01)
    array_dimensions = numpy.asarray(u_winds_grid_relative_m_s01.shape)

    error_checking.assert_is_real_numpy_array(v_winds_grid_relative_m_s01)
    error_checking.assert_is_numpy_array(v_winds_grid_relative_m_s01,
                                         exact_dimensions=array_dimensions)

    error_checking.assert_is_geq_numpy_array(rotation_angle_cosines, -1)
    error_checking.assert_is_leq_numpy_array(rotation_angle_cosines, 1)
    error_checking.assert_is_numpy_array(rotation_angle_cosines,
                                         exact_dimensions=array_dimensions)

    error_checking.assert_is_geq_numpy_array(rotation_angle_sines, -1)
    error_checking.assert_is_leq_numpy_array(rotation_angle_sines, 1)
    error_checking.assert_is_numpy_array(rotation_angle_sines,
                                         exact_dimensions=array_dimensions)

    u_winds_earth_relative_m_s01 = (
        rotation_angle_cosines * u_winds_grid_relative_m_s01 +
        rotation_angle_sines * v_winds_grid_relative_m_s01)
    v_winds_earth_relative_m_s01 = (
        rotation_angle_cosines * v_winds_grid_relative_m_s01 -
        rotation_angle_sines * u_winds_grid_relative_m_s01)
    return u_winds_earth_relative_m_s01, v_winds_earth_relative_m_s01
def vapour_pressure_to_dewpoint(vapour_pressures_pascals):
    """Converts one or more vapour pressures to dewpoints.

    :param vapour_pressures_pascals: numpy array of vapour pressures (Pa).
    :return: dewpoints_kelvins: equivalent-size numpy array of dewpoints (K).
    """

    error_checking.assert_is_real_numpy_array(vapour_pressures_pascals)

    log_coefficient = (WATER_VAPOUR_GAS_CONSTANT_J_KG01_K01 /
                       LATENT_HEAT_OF_CONDENSATION_J_KG01)
    logarithms = numpy.log(vapour_pressures_pascals /
                           BASE_VAPOUR_PRESSURE_PASCALS)

    return (BASE_TEMPERATURE_KELVINS**-1 - log_coefficient * logarithms)**-1
def split_array_by_nan(input_array):
    """Splits numpy array into list of contiguous subarrays without NaN.

    :param input_array: 1-D numpy array.
    :return: list_of_arrays: 1-D list of 1-D numpy arrays.  Each numpy array is
        without NaN.
    """

    error_checking.assert_is_real_numpy_array(input_array)
    error_checking.assert_is_numpy_array(input_array, num_dimensions=1)

    return [
        input_array[i] for i in
        numpy.ma.clump_unmasked(numpy.ma.masked_invalid(input_array))
    ]
Beispiel #17
0
def fill_nans(data_matrix):
    """Fills NaN's with nearest neighbours.

    This method is adapted from the method `fill`, which you can find here:
    https://stackoverflow.com/posts/9262129/revisions

    :param data_matrix: numpy array of real-valued data.
    :return: data_matrix: Same but without NaN's.
    """

    error_checking.assert_is_real_numpy_array(data_matrix)

    indices = distance_transform_edt(numpy.isnan(data_matrix),
                                     return_distances=False,
                                     return_indices=True)
    return data_matrix[tuple(indices)]
Beispiel #18
0
def _check_longitudes(longitudes_deg):
    """Finds invalid longitudes.

    N = number of longitudes.

    :param longitudes_deg: length-N numpy array of longitudes (deg E).
    :return: invalid_indices: 1-D numpy array with indices of invalid
        longitudes.
    """

    error_checking.assert_is_real_numpy_array(longitudes_deg)
    error_checking.assert_is_numpy_array(longitudes_deg, num_dimensions=1)

    valid_flags = numpy.logical_and(longitudes_deg >= MIN_LONGITUDE_DEG,
                                    longitudes_deg <= MAX_LONGITUDE_DEG)
    return numpy.where(numpy.invert(valid_flags))[0]
Beispiel #19
0
def round_to_nearest(input_value, rounding_base):
    """Rounds numbers to nearest x, where x is a positive real number.

    :param input_value: Either numpy array of real numbers or scalar real
        number.
    :param rounding_base: Numbers will be rounded to this base.
    :return: output_value: Same as input_value, except rounded.
    """

    if isinstance(input_value, collections.Iterable):
        error_checking.assert_is_real_numpy_array(input_value)
    else:
        error_checking.assert_is_real_number(input_value)

    error_checking.assert_is_greater(rounding_base, 0)
    return rounding_base * numpy.round(input_value / rounding_base)
Beispiel #20
0
def get_column_max_reflectivity(reflectivity_matrix_dbz):
    """Finds column-max reflectivity at each horizontal location.

    M = number of rows (unique grid-point latitudes)
    N = number of columns (unique grid-point longitudes)
    H = number of height levels (unique grid-point heights)

    :param reflectivity_matrix_dbz: H-by-M-by-N matrix of reflectivities.
    :return: column_max_refl_matrix_dbz: M-by-N matrix of column-max
        reflectivities.
    """

    error_checking.assert_is_numpy_array(reflectivity_matrix_dbz,
                                         num_dimensions=3)
    error_checking.assert_is_real_numpy_array(reflectivity_matrix_dbz)

    return numpy.nanmax(reflectivity_matrix_dbz, axis=0)
def dewpoint_to_vapour_pressure(dewpoints_kelvins):
    """Converts one or more dewpoints to vapour pressures.

    :param dewpoints_kelvins: numpy array of dewpoints (K).
    :return: vapour_pressures_pascals: equivalent-size numpy array of vapour
        pressures (Pa).
    """

    error_checking.assert_is_real_numpy_array(dewpoints_kelvins)

    temperature_coefficient = (LATENT_HEAT_OF_CONDENSATION_J_KG01 /
                               WATER_VAPOUR_GAS_CONSTANT_J_KG01_K01)
    temperature_diffs_kelvins = (BASE_TEMPERATURE_KELVINS**-1 -
                                 dewpoints_kelvins**-1)

    return BASE_VAPOUR_PRESSURE_PASCALS * numpy.exp(
        temperature_coefficient * temperature_diffs_kelvins)
def _check_vertex_arrays(x_coordinates, y_coordinates, allow_nan=True):
    """Checks vertex arrays for errors.

    x- and y-coordinates may be in one of three formats (see docstring at top of
    file).

    V = number of vertices

    :param x_coordinates: length-V numpy array with x-coordinates of vertices.
        The first NaN separates the exterior from the first hole, and the [i]th
        NaN separates the [i - 1]th hole from the [i]th hole.
    :param y_coordinates: Same as above, except for y-coordinates.
    :param allow_nan: Boolean flag.  If True, input arrays may contain NaN's
        (however, NaN's must occur at the exact same positions in the two
        arrays).
    :raises: ValueError: if allow_nan = True but NaN's do not occur at the same
        positions in the two arrays.
    """

    error_checking.assert_is_boolean(allow_nan)

    if allow_nan:
        error_checking.assert_is_real_numpy_array(x_coordinates)
        error_checking.assert_is_real_numpy_array(y_coordinates)
    else:
        error_checking.assert_is_numpy_array_without_nan(x_coordinates)
        error_checking.assert_is_numpy_array_without_nan(y_coordinates)

    error_checking.assert_is_numpy_array(x_coordinates, num_dimensions=1)
    num_vertices = len(x_coordinates)
    error_checking.assert_is_numpy_array(y_coordinates,
                                         exact_dimensions=numpy.array(
                                             [num_vertices]))

    x_nan_indices = numpy.where(numpy.isnan(x_coordinates))[0]
    y_nan_indices = numpy.where(numpy.isnan(y_coordinates))[0]
    if not numpy.array_equal(x_nan_indices, y_nan_indices):
        error_string = (
            '\nNaN'
            's occur at the following positions in `x_coordinates`:\n' +
            str(x_nan_indices) +
            '\nand the following positions in `y_coordinates`:\n' +
            str(y_nan_indices) + '\nNaN'
            's should occur at the same positions in the two arrays.')
        raise ValueError(error_string)
def _check_wind_directions(wind_directions_deg):
    """Finds invalid wind directions.

    N = number of observations

    :param wind_directions_deg: length-N numpy array of wind directions (degrees
        of origin).
    :return: invalid_indices: 1-D numpy array with indices of invalid
        directions.
    """

    error_checking.assert_is_real_numpy_array(wind_directions_deg)
    error_checking.assert_is_numpy_array(wind_directions_deg, num_dimensions=1)

    valid_flags = numpy.logical_and(
        wind_directions_deg >= MIN_WIND_DIRECTION_DEG,
        wind_directions_deg <= MAX_WIND_DIRECTION_DEG)
    return numpy.where(numpy.invert(valid_flags))[0]
def _check_elevations(elevations_m_asl):
    """Finds invalid surface elevations.

    N = number of elevations

    :param elevations_m_asl: length-N numpy array of elevations (metres above
        sea level).
    :return: invalid_indices: 1-D numpy array with indices of invalid surface
        elevations.  For example, if 5th and 12th elevations are invalid, this
        array will contain 4 and 11.
    """

    error_checking.assert_is_real_numpy_array(elevations_m_asl)
    error_checking.assert_is_numpy_array(elevations_m_asl, num_dimensions=1)

    valid_flags = numpy.logical_and(elevations_m_asl >= MIN_ELEVATION_M_ASL,
                                    elevations_m_asl <= MAX_ELEVATION_M_ASL)
    return numpy.where(numpy.invert(valid_flags))[0]
Beispiel #25
0
def _check_longitudes_positive_in_west(longitudes_deg):
    """Finds invalid longitudes.

    N = number of longitudes.

    :param longitudes_deg: length-N numpy array of longitudes (deg E), where
        values in western hemisphere are positive.
    :return: invalid_indices: 1-D numpy array with indices of invalid
        longitudes.
    """

    error_checking.assert_is_real_numpy_array(longitudes_deg)
    error_checking.assert_is_numpy_array(longitudes_deg, num_dimensions=1)

    valid_flags = numpy.logical_and(
        longitudes_deg >= MIN_LNG_POSITIVE_IN_WEST_DEG,
        longitudes_deg <= MAX_LNG_POSITIVE_IN_WEST_DEG)
    return numpy.where(numpy.invert(valid_flags))[0]
def temperatures_to_potential_temperatures(temperatures_kelvins,
                                           total_pressures_pascals):
    """Converts one or more temperatures to potential temperatures.

    :param temperatures_kelvins: numpy array of temperatures (K).
    :param total_pressures_pascals: equivalent-size numpy array of total air
        pressures (Pa).
    :return: potential_temperatures_kelvins: equivalent-size numpy array of
        potential temperatures (K).
    """

    error_checking.assert_is_real_numpy_array(temperatures_kelvins)
    error_checking.assert_is_real_numpy_array(total_pressures_pascals)
    temperature_dimensions = numpy.array(temperatures_kelvins.shape)
    error_checking.assert_is_numpy_array(
        total_pressures_pascals, exact_dimensions=temperature_dimensions)

    return (temperatures_kelvins *
            (REFERENCE_PRESSURE_PASCALS / total_pressures_pascals)**KAPPA)
def mixing_ratio_to_vapour_pressure(mixing_ratios_kg_kg01,
                                    total_pressures_pascals):
    """Converts one or more mixing ratios to vapour pressures.

    :param mixing_ratios_kg_kg01: numpy array of mixing ratios (kg per kg).
    :param total_pressures_pascals: equivalent-size numpy array of total air
        pressures (Pa).
    :return: vapour_pressures_pascals: equivalent-size numpy array of water
        vapour pressures (Pa).
    """

    error_checking.assert_is_real_numpy_array(mixing_ratios_kg_kg01)
    error_checking.assert_is_real_numpy_array(total_pressures_pascals)
    mixing_ratio_dimensions = numpy.asarray(mixing_ratios_kg_kg01.shape)
    error_checking.assert_is_numpy_array(
        total_pressures_pascals, exact_dimensions=mixing_ratio_dimensions)

    return (mixing_ratios_kg_kg01 *
            total_pressures_pascals) / (EPSILON + mixing_ratios_kg_kg01)
def vapour_pressure_to_mixing_ratio(vapour_pressures_pascals,
                                    total_pressures_pascals):
    """Converts one or more vapour pressures to mixing ratios.

    :param vapour_pressures_pascals: numpy array of vapour pressures (Pa).
    :param total_pressures_pascals: equivalent-size numpy array of total air
        pressures (K).
    :return: mixing_ratios_kg_kg01: equivalent-size numpy array of mixing ratios
        (kg per kg).
    """

    error_checking.assert_is_real_numpy_array(vapour_pressures_pascals)
    error_checking.assert_is_real_numpy_array(total_pressures_pascals)
    vapour_pressure_dimensions = numpy.asarray(vapour_pressures_pascals.shape)
    error_checking.assert_is_numpy_array(
        total_pressures_pascals, exact_dimensions=vapour_pressure_dimensions)

    return (vapour_pressures_pascals * EPSILON) / (total_pressures_pascals -
                                                   vapour_pressures_pascals)
Beispiel #29
0
def temperature_to_virtual_temperature(temperatures_kelvins,
                                       total_pressures_pascals,
                                       vapour_pressures_pascals):
    """Converts one or more temperatures to virtual temperatures.

    :param temperatures_kelvins: numpy array of air temperatures (K).
    :param total_pressures_pascals: equivalent-size numpy array of total air
        pressures (Pa).
    :param vapour_pressures_pascals: equivalent-size numpy array of vapour
        pressures (Pa).
    :return: virtual_temperatures_kelvins: equivalent-size numpy array of
        virtual air temperatures (K).
    """

    error_checking.assert_is_real_numpy_array(temperatures_kelvins)
    error_checking.assert_is_real_numpy_array(total_pressures_pascals)
    error_checking.assert_is_real_numpy_array(vapour_pressures_pascals)

    temperature_dimensions = numpy.asarray(temperatures_kelvins.shape)
    error_checking.assert_is_numpy_array(
        total_pressures_pascals, exact_dimensions=temperature_dimensions)
    error_checking.assert_is_numpy_array(
        vapour_pressures_pascals, exact_dimensions=temperature_dimensions)

    denominator_values = 1. - (
        (vapour_pressures_pascals / total_pressures_pascals) * (1. - EPSILON))
    return temperatures_kelvins / denominator_values
Beispiel #30
0
def find_invalid_longitudes(longitudes_deg,
                            sign_in_western_hemisphere=POSITIVE_LONGITUDE_ARG):
    """Returns array indices of invalid longitudes.

    :param longitudes_deg: 1-D numpy array of longitudes (deg E).
    :param sign_in_western_hemisphere: Required sign in western hemisphere.  May
        be "positive", "negative", or "either".
    :return: invalid_indices: 1-D numpy array with array indices of invalid
        longitudes.
    :raises: ValueError: if `sign_in_western_hemisphere` is not one of the 3
        aforelisted options.
    """

    error_checking.assert_is_real_numpy_array(longitudes_deg)
    error_checking.assert_is_numpy_array(longitudes_deg, num_dimensions=1)
    error_checking.assert_is_string(sign_in_western_hemisphere)

    if sign_in_western_hemisphere == POSITIVE_LONGITUDE_ARG:
        valid_flags = numpy.logical_and(
            longitudes_deg >= MIN_LONGITUDE_POSITIVE_IN_WEST_DEG,
            longitudes_deg <= MAX_LONGITUDE_POSITIVE_IN_WEST_DEG)
    elif sign_in_western_hemisphere == NEGATIVE_LONGITUDE_ARG:
        valid_flags = numpy.logical_and(
            longitudes_deg >= MIN_LONGITUDE_NEGATIVE_IN_WEST_DEG,
            longitudes_deg <= MAX_LONGITUDE_NEGATIVE_IN_WEST_DEG)
    elif sign_in_western_hemisphere == EITHER_SIGN_LONGITUDE_ARG:
        valid_flags = numpy.logical_and(
            longitudes_deg >= MIN_LONGITUDE_NEGATIVE_IN_WEST_DEG,
            longitudes_deg <= MAX_LONGITUDE_POSITIVE_IN_WEST_DEG)
    else:
        error_string = (
            '\n\n{0:s}Valid options for `sign_in_western_hemisphere` are listed'
            ' above and do not include "{1:s}".').format(
                str(VALID_LONGITUDE_SIGN_ARGS), sign_in_western_hemisphere)

        raise ValueError(error_string)

    return numpy.where(numpy.invert(valid_flags))[0]