def set_area_pixel(self, min_resol=1.0e-8, scheduler=None): """Set area_pixel attribute for every pixel or point. area in m*m Parameters: min_resol (float, optional): if centroids are points, use this minimum resolution in lat and lon. Default: 1.0e-8 scheduler (str): used for dask map_partitions. “threads”, “synchronous” or “processes” """ if self.meta: if hasattr(self.meta['crs'], 'linear_units') and \ str.lower(self.meta['crs'].linear_units) in ['m', 'metre', 'meter']: self.area_pixel = np.zeros((self.meta['height'], self.meta['width'])) self.area_pixel *= abs(self.meta['transform'].a) * abs(self.meta['transform'].e) return if abs(abs(self.meta['transform'].a) - abs(self.meta['transform'].e)) > 1.0e-5: LOGGER.error('Area can not be computed for not squared pixels.') raise ValueError res = self.meta['transform'].a else: res = get_resolution(self.lat, self.lon, min_resol=min_resol) res = np.abs(res).min() self.set_geometry_points(scheduler) LOGGER.debug('Setting area_pixel %s points.', str(self.lat.size)) xy_pixels = self.geometry.buffer(res / 2).envelope is_cea = ('units' in self.geometry.crs and self.geometry.crs['units'] in ['m', 'metre', 'meter'] or equal_crs(self.geometry.crs, {'proj': 'cea'})) if is_cea: self.area_pixel = xy_pixels.area.values else: self.area_pixel = xy_pixels.to_crs(crs={'proj': 'cea'}).area.values
def set_area_pixel(self): """ Set area_pixel attribute for every pixel or point. area in m*m """ if self.meta: if hasattr(self.meta['crs'], 'linear_units') and \ str.lower(self.meta['crs'].linear_units) in ['m', 'metre', 'meter']: self.area_pixel = np.zeros( (self.meta['height'], self.meta['width'])) self.area_pixel *= abs(self.meta['transform'].a) * abs( self.meta['transform'].e) return if abs( abs(self.meta['transform'].a) - abs(self.meta['transform'].e)) > 1.0e-5: LOGGER.error( 'Area can not be computed for not squared pixels.') raise ValueError res = self.meta['transform'].a else: res = min(get_resolution(self.lat, self.lon)) self._set_geometry_points() LOGGER.debug('Setting area_pixel %s points.', str(self.lat.size)) xy_pixels = self.geometry.buffer(res / 2).envelope if ('units' in self.geometry.crs and \ self.geometry.crs['units'] in ['m', 'metre', 'meter']) or \ self.geometry.crs == {'proj':'cea'}: self.area_pixel = xy_pixels.area.values else: self.area_pixel = xy_pixels.to_crs(crs={'proj': 'cea'}).area.values
def plot(self, axis=None, **kwargs): """Plot centroids scatter points over earth. Parameters ---------- axis : matplotlib.axes._subplots.AxesSubplot, optional axis to use kwargs : optional arguments for scatter matplotlib function Returns ------- axis : matplotlib.axes._subplots.AxesSubplot """ if self.meta and not self.coord.size: self.set_meta_to_lat_lon() pad = np.abs(u_coord.get_resolution(self.lat, self.lon)).min() proj_data, _ = u_plot.get_transformation(self.crs) proj_plot = proj_data if isinstance(proj_data, ccrs.PlateCarree): # use different projections for plot and data to shift the central lon in the plot xmin, ymin, xmax, ymax = u_coord.latlon_bounds(self.lat, self.lon, buffer=pad) proj_plot = ccrs.PlateCarree(central_longitude=0.5 * (xmin + xmax)) else: xmin, ymin, xmax, ymax = (self.lon.min() - pad, self.lat.min() - pad, self.lon.max() + pad, self.lat.max() + pad) if not axis: _, axis = u_plot.make_map(proj=proj_plot) axis.set_extent((xmin, xmax, ymin, ymax), crs=proj_data) u_plot.add_shapes(axis) axis.scatter(self.lon, self.lat, transform=proj_data, **kwargs) return axis
def plot_raster(self, res=None, raster_res=None, save_tiff=None, raster_f=lambda x: np.log10((np.fmax(x+1, 1))), label='value (log10)', **kwargs): """ Generate raster from points geometry and plot it using log10 scale: np.log10((np.fmax(raster+1, 1))). Parameters: res (float, optional): resolution of current data in units of latitude and longitude, approximated if not provided. raster_res (float, optional): desired resolution of the raster save_tiff (str, optional): file name to save the raster in tiff format, if provided raster_f (lambda function): transformation to use to data. Default: log10 adding 1. label (str): colorbar label kwargs (optional): arguments for imshow matplotlib function Returns: matplotlib.figure.Figure, cartopy.mpl.geoaxes.GeoAxesSubplot """ if not 'geometry' in self.columns: self.set_geometry_points() crs_epsg, crs_unit = self._get_transformation() if not res: res= min(get_resolution(self.latitude.values, self.longitude.values)) if not raster_res: raster_res = res LOGGER.info('Raster from resolution %s%s to %s%s.', res, crs_unit, raster_res, crs_unit) exp_poly = self[['value']].set_geometry(self.buffer(res/2).envelope) # construct raster xmin, ymin, xmax, ymax = self.total_bounds rows, cols, ras_trans = points_to_raster((xmin, ymin, xmax, ymax), raster_res) raster = rasterize([(x, val) for (x, val) in zip(exp_poly.geometry, exp_poly.value)], out_shape=(rows, cols), transform=ras_trans, fill=0, all_touched=True, dtype=rasterio.float32, ) # save tiff if save_tiff is not None: ras_tiff = rasterio.open(save_tiff, 'w', driver='GTiff', \ height=raster.shape[0], width=raster.shape[1], count=1, \ dtype=np.float32, crs=self.crs, transform=ras_trans) ras_tiff.write(raster.astype(np.float32), 1) ras_tiff.close() # make plot fig, axis = u_plot.make_map(proj=crs_epsg) cbar_ax = fig.add_axes([0.99, 0.238, 0.03, 0.525]) fig.subplots_adjust(hspace=0, wspace=0) axis[0, 0].set_extent([max(xmin, crs_epsg.x_limits[0]), min(xmax, crs_epsg.x_limits[1]), max(ymin, crs_epsg.y_limits[0]), min(ymax, crs_epsg.y_limits[1])], crs_epsg) u_plot.add_shapes(axis[0, 0]) imag = axis[0, 0].imshow(raster_f(raster), **kwargs, origin='upper', extent=[xmin, xmax, ymin, ymax], transform=crs_epsg) plt.colorbar(imag, cax=cbar_ax, label=label) plt.draw() posn = axis[0, 0].get_position() cbar_ax.set_position([posn.x0 + posn.width + 0.01, posn.y0, 0.04, posn.height]) return fig, axis
def test_get_resolution_pass(self): """ Test _get_resolution method """ lat = np.array([13.125, 13.20833333, 13.29166667, 13.125, 13.20833333, 13.125, 12.625, 12.70833333, 12.79166667, 12.875, 12.95833333, 13.04166667]) lon = np.array([-59.6250000000000,-59.6250000000000,-59.6250000000000,-59.5416666666667, -59.5416666666667,-59.4583333333333,-60.2083333333333,-60.2083333333333, -60.2083333333333,-60.2083333333333,-60.2083333333333,-60.2083333333333]) res_lat, res_lon = get_resolution(lat, lon) self.assertAlmostEqual(min(res_lat, res_lon), 0.0833333333333)
def _fraction_on_land(centroids, topo_path): """Determine fraction of each centroid cell that is on land. Typically, the resolution of the provided DEM data set is much higher than the resolution of the centroids so that the centroid cells might be partly above and partly below sea level. This function computes for each centroid cell the fraction of its area that is on land. Parameters ---------- centroids : Centroids Centroids to consider topo_path : str Path to a raster file containing gridded elevation data. Returns ------- fractions : ndarray of shape (ncentroids,) For each centroid, the fraction of it's cell area that is on land according to the DEM. """ bounds = np.array(centroids.total_bounds) shape = [0, 0] if centroids.meta: shape = centroids.shape cen_trans = centroids.meta['transform'] else: shape[0], shape[1], cen_trans = u_coord.pts_to_raster_meta( bounds, min(u_coord.get_resolution(centroids.lat, centroids.lon))) read_raster_buffer = 0.5 * max(np.abs(cen_trans[0]), np.abs(cen_trans[4])) bounds += read_raster_buffer * np.array([-1., -1., 1., 1.]) on_land, dem_trans = u_coord.read_raster_bounds(topo_path, bounds) on_land = (on_land > 0).astype(np.float64) with rasterio.open(topo_path, 'r') as src: dem_crs = src.crs dem_nodata = src.nodata fractions = np.zeros(shape, dtype=np.float64) rasterio.warp.reproject(source=on_land, destination=fractions, src_transform=dem_trans, src_crs=dem_crs, dst_transform=cen_trans, dst_crs=centroids.crs, resampling=rasterio.warp.Resampling.average, src_nodata=dem_nodata, dst_nodata=0.0) if not centroids.meta: x_i = ((centroids.lon - cen_trans[2]) / cen_trans[0]).astype(int) y_i = ((centroids.lat - cen_trans[5]) / cen_trans[4]).astype(int) fractions = fractions[y_i, x_i] return fractions.reshape(-1)
def set_lat_lon_to_meta(self): """ Compute meta from lat and lon values. To match the existing lat and lon, lat and lon need to start from the upper left corner!!""" self.meta = dict() res = min(get_resolution(self.lat, self.lon)) rows, cols, ras_trans = points_to_raster(self.total_bounds, res) LOGGER.debug('Resolution points: %s', str(res)) self.meta = { 'width': cols, 'height': rows, 'crs': self.crs, 'transform': ras_trans }
def set_lat_lon_to_meta(self, min_resol=1.0e-8): """Compute meta from lat and lon values. Parameters: min_resol (float, optional): minimum centroids resolution to use in the raster. Default: 1.0e-8. """ res = get_resolution(self.lon, self.lat, min_resol=min_resol) rows, cols, ras_trans = pts_to_raster_meta(self.total_bounds, res) LOGGER.debug('Resolution points: %s', str(res)) self.meta = { 'width': cols, 'height': rows, 'crs': self.crs, 'transform': ras_trans, }
def set_area_approx(self, min_resol=1.0e-8): """Set `area_pixel` attribute for every pixel or point (approximate area in m*m). Values are differentiated per latitude. Faster than `set_area_pixel`. Parameters ---------- min_resol : float, optional if centroids are points, use this minimum resolution in lat and lon. Default: 1.0e-8 """ if self.meta: if hasattr(self.meta['crs'], 'linear_units') and \ str.lower(self.meta['crs'].linear_units) in ['m', 'metre', 'meter']: self.area_pixel = np.zeros( (self.meta['height'], self.meta['width'])) self.area_pixel *= abs(self.meta['transform'].a) * abs( self.meta['transform'].e) return res_lat, res_lon = self.meta['transform'].e, self.meta[ 'transform'].a lat_unique = np.arange( self.meta['transform'].f + res_lat / 2, self.meta['transform'].f + self.meta['height'] * res_lat, res_lat) lon_unique_len = self.meta['width'] res_lat = abs(res_lat) else: res_lat, res_lon = np.abs( u_coord.get_resolution(self.lat, self.lon, min_resol=min_resol)) lat_unique = np.array(np.unique(self.lat)) lon_unique_len = len(np.unique(self.lon)) if PROJ_CEA == self.geometry.crs: self.area_pixel = np.repeat(res_lat * res_lon, lon_unique_len) return LOGGER.debug('Setting area_pixel approx %s points.', str(self.lat.size)) res_lat = res_lat * ONE_LAT_KM * 1000 res_lon = res_lon * ONE_LAT_KM * 1000 * np.cos(np.radians(lat_unique)) area_approx = np.repeat(res_lat * res_lon, lon_unique_len) if area_approx.size == self.size: self.area_pixel = area_approx else: LOGGER.error('Pixel area of points can not be computed.') raise ValueError
def set_lat_lon_to_meta(self, min_resol=1.0e-8): """ Compute meta from lat and lon values. To match the existing lat and lon, lat and lon need to start from the upper left corner!! Parameter: min_resol (float, optional): minimum centroids resolution to use in the raster. Default: 1.0e-8. """ self.meta = dict() res = min(get_resolution(self.lat, self.lon, min_resol)) rows, cols, ras_trans = pts_to_raster_meta(self.total_bounds, res) LOGGER.debug('Resolution points: %s', str(res)) self.meta = { 'width': cols, 'height': rows, 'crs': self.crs, 'transform': ras_trans }
def _centroids_resolution(centroids): """ Return resolution of the centroids in their units Parameters: centroids (Centroids): centroids instance Returns: float """ if centroids.meta: res_centr = abs(centroids.meta['transform'][4]), \ centroids.meta['transform'][0] else: res_centr = get_resolution(centroids.lat, centroids.lon) if abs(abs(res_centr[0]) - abs(res_centr[1])) > 1.0e-6: LOGGER.warning('Centroids do not represent regular pixels %s.', str(res_centr)) return (res_centr[0] + res_centr[1])/2 return res_centr[0]
def set_area_approx(self, min_resol=1.0e-8): """ Computes approximated area_pixel values: differentiated per latitude. area in m*m. Faster than set_area_pixel Parameter: min_resol (float, optional): if centroids are points, use this minimum resolution in lat and lon. Default: 1.0e-8 """ if self.meta: if hasattr(self.meta['crs'], 'linear_units') and \ str.lower(self.meta['crs'].linear_units) in ['m', 'metre', 'meter']: self.area_pixel = np.zeros( (self.meta['height'], self.meta['width'])) self.area_pixel *= abs(self.meta['transform'].a) * abs( self.meta['transform'].e) return res_lat, res_lon = self.meta['transform'].e, self.meta[ 'transform'].a lat_unique = np.arange(self.meta['transform'].f + res_lat/2, \ self.meta['transform'].f + self.meta['height'] * res_lat, res_lat) lon_unique_len = self.meta['width'] res_lat = abs(res_lat) else: res_lat, res_lon = get_resolution(self.lat, self.lon, min_resol) lat_unique = np.array(np.unique(self.lat)) lon_unique_len = len(np.unique(self.lon)) if ('units' in self.geometry.crs and \ self.geometry.crs['units'] in ['m', 'metre', 'meter']) or \ equal_crs(self.geometry.crs, {'proj':'cea'}): self.area_pixel = np.repeat(res_lat * res_lon, lon_unique_len) return LOGGER.debug('Setting area_pixel approx %s points.', str(self.lat.size)) res_lat = res_lat * ONE_LAT_KM * 1000 res_lon = res_lon * ONE_LAT_KM * 1000 * np.cos(np.radians(lat_unique)) area_approx = np.repeat(res_lat * res_lon, lon_unique_len) if area_approx.size == self.size: self.area_pixel = area_approx else: LOGGER.error('Pixel area of points can not be computed.') raise ValueError
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
def _surge_decay(inten_surge, centroids, dem_product, set_fraction, min_resol, \ add_sea_level_rise): """ Substract DEM height and decay factor from initial surge height and computes corresponding fraction matrix. Parameter: inten_surge (sparse.csr_matrix): initial surge height in m centroids (Centroids): centroids, either raster or points dem_product (str): DEM to use: 'SRTM1' (30m) or 'SRTM3' (90m) set_fraction (bool, optional): set fraction matrix different to ones. Default: True min_resol (float, optional): minimum points centroids resolution to use when interpolating DEM data. Used in get_resolution method. If get_resolution(centroids.lat, centroids.lon) gives a too low number, set this parameter to the right centroids resolution. Default: 1.0e-8. add_sea_level_rise (float): sea level rise in meters to be added to surge Returns: inten_surge (sparse.csr_matrix), fract_surge (sparse.csr_matrix) """ import elevation inland_decay = _calc_inland_decay(centroids) # substract event by event to avoid to densificate all the matrix inten_surge = _substract_sparse_surge(inten_surge, centroids.elevation, \ inland_decay, add_sea_level_rise) # if set_fraction: fraction is fraction of centroids of DEM on land in # given centroids cell. Else fraction is ones where intensity. if set_fraction: bounds = np.array(centroids.total_bounds) if centroids.meta: shape = centroids.shape ras_trans = centroids.meta['transform'] else: shape = [0, 0] shape[0], shape[1], ras_trans = pts_to_raster_meta(bounds, \ min(get_resolution(centroids.lat, centroids.lon, min_resol))) bounds += np.array([-.05, -.05, .05, .05]) elevation.clip(bounds, output=TMP_ELEVATION_FILE, product=dem_product, max_download_tiles=MAX_DEM_TILES_DOWN) fract_surge = np.zeros(shape) with rasterio.open(TMP_ELEVATION_FILE, 'r') as src: on_land = src.read(1) on_land[on_land > 0] = 1 # 1 land on_land[on_land <= 0] = 0 # 0 water on_land[on_land == src.nodata] = 0 # 0 nodata reproject(source=on_land, destination=fract_surge, src_transform=src.transform, src_crs=src.crs, dst_transform=ras_trans, dst_crs=centroids.crs, resampling=Resampling.average, src_nodata=src.nodata, dst_nodata=src.nodata) if centroids.meta: fract_surge = csr_matrix(fract_surge.flatten()) fract_surge = csr_matrix(np.ones([inten_surge.shape[0], 1 ])) * fract_surge else: x_i = ((centroids.lon - ras_trans[2]) / ras_trans[0]).astype(int) y_i = ((centroids.lat - ras_trans[5]) / ras_trans[4]).astype(int) fract_surge = csr_matrix(fract_surge[y_i, x_i]) else: fract_surge = inten_surge.copy() fract_surge.data.fill(1) return inten_surge, fract_surge