Exemplo n.º 1
0
def generate_nat_earth_centroids(res_as=360, path=None, dist_coast=False):
    """For reproducibility, this is the function that generates the centroids
        files in `NATEARTH_CENTROIDS`. These files are provided with CLIMADA
        so that this function should never be called!

    Parameters:
        res_as (int): Resolution of file in arc-seconds. Default: 360.
        path (str, optional): If set, write resulting hdf5 file here instead of
            the default location.
        dist_coast (bool): If true, read distance from a NASA dataset
            (see util.coordinates.dist_to_coast_nasa)
    """
    if path is None and res_as not in [150, 360]:
        raise ValueError("Only 150 and 360 arc-seconds are supported!")

    res_deg = res_as / 3600
    lat_dim = np.arange(-90 + res_deg, 90, res_deg)
    lon_dim = np.arange(-180 + res_deg, 180 + res_deg, res_deg)
    lon, lat = [ar.ravel() for ar in np.meshgrid(lon_dim, lat_dim)]
    natids = np.uint16(get_country_code(lat, lon, gridded=False))

    cen = Centroids()
    cen.set_lat_lon(lat, lon)
    cen.region_id = natids
    cen.set_lat_lon_to_meta()
    cen.lat = np.array([])
    cen.lon = np.array([])

    if path is None:
        path = NATEARTH_CENTROIDS[res_as]

    if dist_coast:
        cen.set_dist_coast(precomputed=True, signed=False)
        cen.dist_coast = np.float16(cen.dist_coast)
    cen.write_hdf5(path)
    def test_country_code_pass(self):
        """ Test set_region_id """

        lon = np.array([
            -59.6250000000000, -59.6250000000000, -59.6250000000000,
            -59.5416666666667, -59.5416666666667, -59.4583333333333,
            -60.2083333333333, -60.2083333333333
        ])
        lat = np.array([
            13.125, 13.20833333, 13.29166667, 13.125, 13.20833333, 13.125,
            12.625, 12.70833333
        ])
        region_id = get_country_code(lat, lon)
        region_id_OSLO = get_country_code([59.91], [10.75])
        self.assertEqual(np.count_nonzero(region_id), 6)
        self.assertTrue(np.allclose(region_id[:6],
                                    np.ones(6) * 52))  # 052 for barbados
        self.assertEqual(region_id_OSLO, np.array(578))  # 578 for Norway
Exemplo n.º 3
0
    def test_country_code_pass(self):
        """Test set_region_id"""

        lon = np.array([
            -59.6250000000000, -59.6250000000000, -59.6250000000000,
            -59.5416666666667, -59.5416666666667, -59.4583333333333,
            -60.2083333333333, -60.2083333333333
        ])
        lat = np.array([
            13.125, 13.20833333, 13.29166667, 13.125, 13.20833333, 13.125,
            12.625, 12.70833333
        ])
        for gridded in [True, False]:
            region_id = get_country_code(lat, lon, gridded=gridded)
            region_id_OSLO = get_country_code(59.91, 10.75, gridded=gridded)
            self.assertEqual(np.count_nonzero(region_id), 6)
            # 052 for barbados
            self.assertTrue(np.all(region_id[:6] == 52))
            # 578 for Norway
            self.assertEqual(region_id_OSLO, np.array([578]))
Exemplo n.º 4
0
    def set_region_id(self, scheduler=None):
        """Set region_id as country ISO numeric code attribute for every pixel
        or point

        Parameters:
            scheduler (str): used for dask map_partitions. “threads”,
                “synchronous” or “processes”
        """
        ne_geom = self._ne_crs_geom(scheduler)
        LOGGER.debug('Setting region_id %s points.', str(self.lat.size))
        self.region_id = get_country_code(ne_geom.geometry[:].y.values,
                                          ne_geom.geometry[:].x.values)
Exemplo n.º 5
0
    def set_from_isimip_netcdf(self, input_dir=None, filename=None, hist_mean=None,
                               bbox=None, yearrange=None, cl_model=None, scenario=None,
                               crop=None, irr=None, isimip_version=None,
                               unit=None, fn_str_var=None):

        """Wrapper to fill exposure from NetCDF file from ISIMIP. Requires historical
        mean relative cropyield module as additional input.
        Optional Parameters:
            input_dir (string): path to input data directory
            filename (string): name of the landuse data file to use,
                e.g. "histsoc_landuse-15crops_annual_1861_2005.nc""
            hist_mean (str or array): historic mean crop yield per centroid (or path)
            bbox (list of four floats): bounding box:
                [lon min, lat min, lon max, lat max]
            yearrange (int tuple): year range for exposure set
               e.g., (1990, 2010)
            scenario (string): climate change and socio economic scenario
               e.g., '1860soc', 'histsoc', '2005soc', 'rcp26soc','rcp60soc','2100rcp26soc'
            cl_model (string): abbrev. climate model (only for future projections of lu data)
               e.g., 'gfdl-esm2m', 'hadgem2-es', 'ipsl-cm5a-lr','miroc5'
            crop (string): crop type
               e.g., 'mai', 'ric', 'whe', 'soy'
            irr (string): irrigation type, default: 'combined'
                f.i 'firr' (full irrigation), 'noirr' (no irrigation) or 'combined'= firr+noirr
            isimip_version(str): 'ISIMIP2' (default) or 'ISIMIP3'
            unit (string): unit of the exposure (per year)
                f.i 't/y' (default), 'USD/y', or 'kcal/y'
            fn_str_var (string): FileName STRing depending on VARiable and
                ISIMIP simuation round

        Returns:
            Exposure
        """
        # parameters not provided in method call are set to default values:
        if irr is None:
            irr = 'combined'
        if not bbox:
            bbox = BBOX
        if not input_dir:
            input_dir = INPUT_DIR
        if hist_mean is None:
            hist_mean = HIST_MEAN_PATH
        if not fn_str_var:
            fn_str_var = FN_STR_VAR
        if (not isimip_version) or (isimip_version in ('ISIMIP2a', 'ISIMIP2b')):
            isimip_version = 'ISIMIP2'
        elif isimip_version in ('ISIMIP3a', 'ISIMIP3b'):
            isimip_version = 'ISIMIP3'
        if (not scenario) or (scenario in ('historical', 'hist')):
            scenario = 'histsoc'
        if yearrange is None:
            yearrange = YEARCHUNKS[isimip_version][scenario]['yearrange']
        if not unit:
            unit = 't/y'
        #if not soc: soc=''
        # The filename is set or other variables (cl_model, scenario) are extracted of the
        # specified filename
        if filename is None:
            yearchunk = YEARCHUNKS[isimip_version][scenario]
            # if scenario == 'histsoc' or scenario == '1860soc':
            if scenario in ('histsoc', '1860soc'):
                string = '{}_{}_{}_{}.nc'
                filepath = Path(input_dir, string.format(scenario, fn_str_var,
                                                         yearchunk['startyear'],
                                                         yearchunk['endyear']))
            else:
                string = '{}_{}_{}_{}_{}.nc'
                filepath = Path(input_dir, string.format(scenario, cl_model, fn_str_var,
                                                         yearchunk['startyear'],
                                                         yearchunk['endyear']))
        elif scenario == 'flexible':
            _, _, _, _, _, _, startyear, endyearnc = filename.split('_')
            endyear = endyearnc.split('.')[0]
            yearchunk = dict()
            yearchunk = {'yearrange': (int(startyear), int(endyear)),
                         'startyear': int(startyear), 'endyear': int(endyear)}
            filepath = Path(input_dir, filename)
        else:
            scenario, *_ = filename.split('_')
            yearchunk = YEARCHUNKS[isimip_version][scenario]
            filepath = Path(input_dir, filename)

        # Dataset is opened and data within the bbox extends is extracted
        data_set = xr.open_dataset(filepath, decode_times=False)
        [lonmin, latmin, lonmax, latmax] = bbox
        data = data_set.sel(lon=slice(lonmin, lonmax), lat=slice(latmax, latmin))

        # The latitude and longitude are set; the region_id is determined
        lon, lat = np.meshgrid(data.lon.values, data.lat.values)
        self.gdf['latitude'] = lat.flatten()
        self.gdf['longitude'] = lon.flatten()
        self.gdf['region_id'] = u_coord.get_country_code(self.gdf.latitude, self.gdf.longitude)

        # The indeces of the yearrange to be extracted are determined
        time_idx = (int(yearrange[0] - yearchunk['startyear']),
                             int(yearrange[1] - yearchunk['startyear']))

        # The area covered by a grid cell is calculated depending on the latitude
        # 1 degree = 111.12km (at the equator); resolution data: 0.5 degree;
        # longitudal distance in km = 111.12*0.5*cos(lat);
        # latitudal distance in km = 111.12*0.5;
        # area = longitudal distance * latitudal distance;
        # 1km2 = 100ha
        area = (111.12 * 0.5)**2 * np.cos(np.deg2rad(lat)) * 100

        # The area covered by a crop is calculated as the product of the fraction and
        # the grid cell size
        if irr == 'combined':
            irr_types = ['firr', 'noirr']
        else:
            irr_types = [irr]
        area_crop = dict()
        for irr_var in irr_types:
            area_crop[irr_var] = (
                getattr(
                    data, (CROP_NAME[crop])['input']+'_'+ (IRR_NAME[irr_var])['name']
                )[time_idx[0]:time_idx[1], :, :].mean(dim='time')*area
            ).values
            area_crop[irr_var] = np.nan_to_num(area_crop[irr_var]).flatten()

        # set historic mean, its latitude, and longitude:
        hist_mean_dict = dict()
        # if hist_mean is given as np.ndarray or dict,
        # code assumes it contains hist_mean as returned by relative_cropyield
        # however structured in dictionary as hist_mean_dict, with same
        # bbox extensions as the exposure:
        if isinstance(hist_mean, dict):
            if not ('firr' in hist_mean.keys() or 'noirr' in hist_mean.keys()):
                # as a dict hist_mean, needs to contain key 'firr' or 'noirr';
                # if irr=='combined', both 'firr' and 'noirr' are required.
                LOGGER.error('Invalid hist_mean provided: %s', hist_mean)
                raise ValueError('invalid hist_mean.')
            hist_mean_dict = hist_mean
            lat_mean = self.gdf.latitude.values
        elif isinstance(hist_mean, np.ndarray) or isinstance(hist_mean, list):
            hist_mean_dict[irr_types[0]] = np.array(hist_mean)
            lat_mean = self.gdf.latitude.values
        elif Path(hist_mean).is_dir(): # else if hist_mean is given as path to directory
        # The adequate file from the directory (depending on crop and irrigation) is extracted
        # and the variables hist_mean, lat_mean and lon_mean are set accordingly
            for irr_var in irr_types:
                filename = str(Path(hist_mean, 'hist_mean_%s-%s_%i-%i.hdf5' %(
                    crop, irr_var, yearrange[0], yearrange[1])))
                hist_mean_dict[irr_var] = (h5py.File(filename, 'r'))['mean'][()]
            lat_mean = (h5py.File(filename, 'r'))['lat'][()]
            lon_mean = (h5py.File(filename, 'r'))['lon'][()]
        elif Path(input_dir, hist_mean).is_file(): # file path
        # Hist_mean, lat_mean and lon_mean are extracted from the given file
            if len(irr_types) > 1:
                LOGGER.error("For irr=='combined', hist_mean can not be single file. Aborting.")
                raise ValueError('Wrong combination of parameters irr and hist_mean.')
            hist_mean = h5py.File(str(Path(input_dir, hist_mean)), 'r')
            hist_mean_dict[irr_types[0]] = hist_mean['mean'][()]
            lat_mean = hist_mean['lat'][()]
            lon_mean = hist_mean['lon'][()]
        else:
            LOGGER.error('Invalid hist_mean provided: %s', hist_mean)
            raise ValueError('invalid hist_mean.')

        # The bbox is cut out of the hist_mean data file if needed
        if len(lat_mean) != len(self.gdf.latitude.values):
            idx_mean = np.zeros(len(self.gdf.latitude.values), dtype=int)
            for i in range(len(self.gdf.latitude.values)):
                idx_mean[i] = np.where(
                    (lat_mean == self.gdf.latitude.values[i])
                    & (lon_mean == self.gdf.longitude.values[i])
                )[0][0]
        else:
            idx_mean = np.arange(0, len(lat_mean))

        # The exposure [t/y] is computed per grid cell as the product of the area covered
        # by a crop [ha] and its yield [t/ha/y]
        self.gdf['value'] = np.squeeze(area_crop[irr_types[0]] * \
                                   hist_mean_dict[irr_types[0]][idx_mean])
        self.gdf['value'] = np.nan_to_num(self.gdf.value) # replace NaN by 0.0
        for irr_val in irr_types[1:]: # add other irrigation types if irr=='combined'
            value_tmp = np.squeeze(area_crop[irr_val]*hist_mean_dict[irr_val][idx_mean])
            value_tmp = np.nan_to_num(value_tmp) # replace NaN by 0.0
            self.gdf['value'] += value_tmp
        self.tag = Tag()

        self.tag.description = ("Crop production exposure from ISIMIP " +
                                (CROP_NAME[crop])['print'] + ' ' +
                                irr + ' ' + str(yearrange[0]) + '-' + str(yearrange[-1]))
        self.value_unit = 't/y' # input unit, will be reset below if required by user
        self.crop = crop
        self.ref_year = yearrange
        try:
            rows, cols, ras_trans = pts_to_raster_meta(
                (self.gdf.longitude.min(), self.gdf.latitude.min(),
                 self.gdf.longitude.max(), self.gdf.latitude.max()),
                get_resolution(self.gdf.longitude, self.gdf.latitude))
            self.meta = {
                'width': cols,
                'height': rows,
                'crs': self.crs,
                'transform': ras_trans,
            }
        except ValueError:
            LOGGER.warning('Could not write attribute meta, because exposure'
                           ' has only 1 data point')
            self.meta = {}

        if 'USD' in unit:
            # set_value_to_usd() is called to compute the exposure in USD/y (country specific)
            self.set_value_to_usd(input_dir=input_dir)
        elif 'kcal' in unit:
            # set_value_to_kcal() is called to compute the exposure in kcal/y
            self.set_value_to_kcal()
        self.check()

        return self