Example #1
0
def berkeley_temperature_data(grid: 'GridDimensions' = GridDimensions((10,
                                                                       20)),
                              year: int = None) -> np.array:
    """
    A data provider returning temperature data from the Berkeley Earth
    temperature dataset. Includes 100% surface and ocean coverage in
    1-degree gridded format. Data is reported for the last full year,
    in monthly sections.
    Returned in a numpy array. First index corresponds to month, with
    0 being January and 11 being December; the second index is latitude,
    with 0 being 90 and 179 being 90; the third index is longitude,
    specifications unknown.
    The data will default to a 1-by-1-degree grid, but can be converted to
    other grid dimensions through the function parameter grid. Only grids
    containing integer multiples of the original grid are supported.
    :param grid:
        The dimensions of the grid onto which the data is to be converted
    :return:
        Berkeley Earth surface temperature data on the selected grid
    """
    dataset = custom_readers.BerkeleyEarthTemperatureReader()

    if year is None:
        data = dataset.read_newest('temperature')[:]
    else:
        data = dataset.collect_timed_data('temperature', year)
    clmt = dataset.collect_untimed_data('climatology')[:]

    # Translate data from the default, 1 by 1 grid to any specified grid.
    regridded_data = _regrid_netcdf_variable(data, grid, 3)
    regridded_clmt = _regrid_netcdf_variable(clmt, grid, 3)
    grid_dims = grid.dims_by_count()

    for i in range(0, 12):
        # Store arrays locally to avoid repeatedly indexing dataset.
        data_by_month = regridded_data[i]
        clmt_by_month = regridded_clmt[i]

        for j in range(0, grid_dims[0]):
            data_by_lat = data_by_month[j]
            clmt_by_lat = clmt_by_month[j]

            for k in range(0, grid_dims[1]):
                # Only one array index required per addition instead
                # of three gives significant performance increases.
                data_by_lat[k] += clmt_by_lat[k]

    return regridded_data
Example #2
0
def landmask_albedo_data(
    temp_data: np.ndarray, grid: 'GridDimensions' = GridDimensions((10, 20))
) -> np.ndarray:
    """
    A data provider returning 1-degree gridded surface albedo data
    for land and ocean. Uses Arrhenius' albedo scheme, in which all
    land has a constant albedo, and all water likewise has a constant
    albedo. In this case clouds are ignored, although they would
    contribute to lower global average albedo.

    Data is returned in a numpy array. The first index represents
    latitude, and the second index is longitude.

    Gridded temperature data is required in the first parameter in
    order to identify which cells are covered in snow. This data
    should come from a temperature provider function that has been
    passed the same grid as this function. That is, the temperature
    data should be on the same grid as the albedo data will be
    converted to.

    The returned albedo data will have the same time granularity as the
    temperature data it is based on (i.e. monthly value if the temperature
    is reported in monthly values).

    :param temp_data:
        Gridded surface temperature data, on the same grid as the data will
        be converted to
    :param grid:
        The dimensions of the grid onto which the data will be converted
    :return:
        Surface albedo data by Arrhenius' scheme
    """
    dataset = custom_readers.BerkeleyEarthTemperatureReader()

    # Berkeley Earth dataset includes variables indicating which 1-degree
    # latitude-longitude cells are primarily land.
    land_coords = dataset.collect_untimed_data('land_mask')[:]
    # Regrid the land/ocean variable to the specified grid, if necessary.
    regridded_land_coords = _naive_regrid(land_coords, grid)
    grid_dims = grid.dims_by_count()

    # Create an array of the same size as the grid, in which to store
    # grid cell albedo values.
    albedo_mask = np.ones((len(temp_data), grid_dims[0], grid_dims[1]),
                          dtype=float)

    # (Inverse) albedo values used by Arrhenius in his model calculations.
    ocean_albedo_inverse = 0.925
    land_albedo_inverse = 1.0
    snow_albedo_inverse = 0.5

    ocean_albedo = 1 - ocean_albedo_inverse
    land_albedo = 1 - land_albedo_inverse
    snow_albedo = 1 - snow_albedo_inverse

    # Intermediate array slices are cached at each for loop iteration
    # to prevent excess array indexing.
    for i in range(len(temp_data)):
        if len(temp_data.shape) == 3:
            temp_time_segment = temp_data[i]
        else:
            temp_time_segment = temp_data[i, ..., 0, :, :]

        for j in range(grid_dims[0]):
            landmask_row = regridded_land_coords[j]
            temp_row = temp_time_segment[j]

            for k in range(grid_dims[1]):
                land_percent = landmask_row[k]
                ocean_percent = 1 - land_percent

                # Grid cells are identified as containing snow based on having
                # land at a temperature below 0 degrees celsius.
                if temp_row[k] < -15:
                    # Any land in this cell is interpreted as being covered in
                    # snow.
                    albedo_mask[i][j][k] = land_percent * snow_albedo\
                                           + ocean_percent * ocean_albedo
                else:
                    # Any land in this cell is interpreted as being uncovered.
                    albedo_mask[i][j][k] = land_percent * land_albedo\
                                           + ocean_percent * ocean_albedo

    return albedo_mask