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
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]))
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)
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