Beispiel #1
0
    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
Beispiel #2
0
 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
Beispiel #3
0
    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
Beispiel #4
0
    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)
Beispiel #7
0
 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
     }
Beispiel #8
0
    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,
        }
Beispiel #9
0
    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
Beispiel #10
0
    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
        }
Beispiel #11
0
    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]
Beispiel #12
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
Beispiel #13
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
Beispiel #14
0
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