Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Python 3.12 #870

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from

Upgrade eccodes and cfgrib versions

44d2e2c
Select commit
Loading
Failed to load commit list.
Draft

Upgrade to Python 3.12 #870

Upgrade eccodes and cfgrib versions
44d2e2c
Select commit
Loading
Failed to load commit list.
Jenkins - WCR / Tests / Declarative: Post Actions failed Aug 7, 2024 in 0s

failed: 22, passed: 202

Send us feedback

Details

climada_petals.hazard.emulator.test.test_geo.TestGeo.test_hazregion_centroids

AssertionError: 0 != 2
Stack trace
self = <climada_petals.hazard.emulator.test.test_geo.TestGeo testMethod=test_hazregion_centroids>

    def test_hazregion_centroids(self):
        """Test HazRegion.centroids method"""
        reg = geo.HazRegion(country="MLT")
        cen = reg.centroids()
>       self.assertEqual(cen.lat.size, 2)
E       AssertionError: 0 != 2

../../../../petals_install_env/workspace/climada_petals/hazard/emulator/test/test_geo.py:74: AssertionError

climada_petals.hazard.test.test_flood.TestRiverFlood.test_flooded_area

AttributeError: 'Centroids' object has no attribute 'get_meta'
Stack trace
self = <climada_petals.hazard.test.test_flood.TestRiverFlood testMethod=test_flooded_area>

    def test_flooded_area(self):
    
>       testRFset = RiverFlood.from_nc(countries=['DEU', 'CHE'], dph_path=HAZ_DEMO_FLDDPH,
                              frc_path=HAZ_DEMO_FLDFRC, ISINatIDGrid=True)

../../../../petals_install_env/workspace/climada_petals/hazard/test/test_flood.py:210: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'climada_petals.hazard.river_flood.RiverFlood'>
dph_path = PosixPath('/var/lib/jenkins/climada/demo/data/flddph_2000_DEMO.nc')
frc_path = PosixPath('/var/lib/jenkins/climada/demo/data/fldfrc_2000_DEMO.nc')
origin = False, centroids = None, countries = ['DEU', 'CHE'], reg = None
shape = None, ISINatIDGrid = True, years = [2000]

    @classmethod
    def from_nc(cls, dph_path=None, frc_path=None, origin=False,
                centroids=None, countries=None, reg=None, shape=None, ISINatIDGrid=False,
                years=None):
        """Wrapper to fill hazard from nc_flood file
    
        Parameters
        ----------
        dph_path : str, optional
            Flood file to read (depth)
        frc_path : str, optional
            Flood file to read (fraction)
        origin : bool, optional
            Historical or probabilistic event. Default: False
        centroids : Centroids, optional
            centroids to extract
        countries : list of str, optional
            If `reg` is None, use this selection of countries (ISO3). Default: None
        reg : list of str, optional
            Use region code to consider whole areas. If not None, countries and centroids
            are ignored. Default: None
        shape : str or Path, optional
            If `reg` and `countries` are None, use the first geometry in this shape file to cut
            out the area of interest. Default: None
        ISINatIDGrid : bool, optional
            Indicates whether ISIMIP_NatIDGrid is used. Default: False
        years : list of int
            Years that are considered. Default: None
    
        Returns
        -------
        haz : RiverFlood instance
    
        Raises
        ------
        NameError
        """
        if years is None:
            years = [2000]
        if dph_path is None:
            raise NameError('No flood-depth-path set')
        if frc_path is None:
            raise NameError('No flood-fraction-path set')
        if not Path(dph_path).exists():
            raise NameError('Invalid flood-file path %s' % dph_path)
        if not Path(frc_path).exists():
            raise NameError('Invalid flood-file path %s' % frc_path)
    
        with xr.open_dataset(dph_path) as flood_dph:
            time = pd.to_datetime(flood_dph["time"].values)
    
        event_index = np.where(np.isin(time.year, years))[0]
        if len(event_index) == 0:
            raise AttributeError(f'No events found for selected {years}')
        bands = event_index + 1
    
        if countries or reg:
            # centroids as points
            if ISINatIDGrid:
    
                dest_centroids = RiverFlood._select_exact_area(countries, reg)[0]
>               centroids_meta = dest_centroids.get_meta()
E               AttributeError: 'Centroids' object has no attribute 'get_meta'

../../../../petals_install_env/workspace/climada_petals/hazard/river_flood.py:139: AttributeError

climada_petals.hazard.test.test_flood.TestRiverFlood.test_isimip_country_flood

AttributeError: 'Centroids' object has no attribute 'get_meta'
Stack trace
self = <climada_petals.hazard.test.test_flood.TestRiverFlood testMethod=test_isimip_country_flood>

    def test_isimip_country_flood(self):
>       rf = RiverFlood.from_nc(dph_path=HAZ_DEMO_FLDDPH, frc_path=HAZ_DEMO_FLDFRC,
                       countries=['DEU'], ISINatIDGrid=True)

../../../../petals_install_env/workspace/climada_petals/hazard/test/test_flood.py:93: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'climada_petals.hazard.river_flood.RiverFlood'>
dph_path = PosixPath('/var/lib/jenkins/climada/demo/data/flddph_2000_DEMO.nc')
frc_path = PosixPath('/var/lib/jenkins/climada/demo/data/fldfrc_2000_DEMO.nc')
origin = False, centroids = None, countries = ['DEU'], reg = None, shape = None
ISINatIDGrid = True, years = [2000]

    @classmethod
    def from_nc(cls, dph_path=None, frc_path=None, origin=False,
                centroids=None, countries=None, reg=None, shape=None, ISINatIDGrid=False,
                years=None):
        """Wrapper to fill hazard from nc_flood file
    
        Parameters
        ----------
        dph_path : str, optional
            Flood file to read (depth)
        frc_path : str, optional
            Flood file to read (fraction)
        origin : bool, optional
            Historical or probabilistic event. Default: False
        centroids : Centroids, optional
            centroids to extract
        countries : list of str, optional
            If `reg` is None, use this selection of countries (ISO3). Default: None
        reg : list of str, optional
            Use region code to consider whole areas. If not None, countries and centroids
            are ignored. Default: None
        shape : str or Path, optional
            If `reg` and `countries` are None, use the first geometry in this shape file to cut
            out the area of interest. Default: None
        ISINatIDGrid : bool, optional
            Indicates whether ISIMIP_NatIDGrid is used. Default: False
        years : list of int
            Years that are considered. Default: None
    
        Returns
        -------
        haz : RiverFlood instance
    
        Raises
        ------
        NameError
        """
        if years is None:
            years = [2000]
        if dph_path is None:
            raise NameError('No flood-depth-path set')
        if frc_path is None:
            raise NameError('No flood-fraction-path set')
        if not Path(dph_path).exists():
            raise NameError('Invalid flood-file path %s' % dph_path)
        if not Path(frc_path).exists():
            raise NameError('Invalid flood-file path %s' % frc_path)
    
        with xr.open_dataset(dph_path) as flood_dph:
            time = pd.to_datetime(flood_dph["time"].values)
    
        event_index = np.where(np.isin(time.year, years))[0]
        if len(event_index) == 0:
            raise AttributeError(f'No events found for selected {years}')
        bands = event_index + 1
    
        if countries or reg:
            # centroids as points
            if ISINatIDGrid:
    
                dest_centroids = RiverFlood._select_exact_area(countries, reg)[0]
>               centroids_meta = dest_centroids.get_meta()
E               AttributeError: 'Centroids' object has no attribute 'get_meta'

../../../../petals_install_env/workspace/climada_petals/hazard/river_flood.py:139: AttributeError

climada_petals.hazard.test.test_flood.TestRiverFlood.test_meta_centroids_flood

ValueError: zero-size array to reduction operation minimum which has no identity
Stack trace
self = <climada_petals.hazard.test.test_flood.TestRiverFlood testMethod=test_meta_centroids_flood>

    def test_meta_centroids_flood(self):
        min_lat, max_lat, min_lon, max_lon = 45.7, 47.8, 7.5, 10.5
        cent = Centroids.from_pnt_bounds((min_lon, min_lat, max_lon, max_lat), res=0.05)
        rf_rast = RiverFlood.from_nc(dph_path=HAZ_DEMO_FLDDPH, frc_path=HAZ_DEMO_FLDFRC,
                            centroids=cent)
        self.assertEqual(rf_rast.centroids.shape, (43, 61))
>       self.assertAlmostEqual(np.min(rf_rast.centroids.lat),
                               45.70000000000012, 4)

../../../../petals_install_env/workspace/climada_petals/hazard/test/test_flood.py:183: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../../../miniforge3/envs/climada_env/lib/python3.9/site-packages/numpy/core/fromnumeric.py:2953: in min
    return _wrapreduction(a, np.minimum, 'min', axis, None, out,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

obj = array([], dtype=float64), ufunc = <ufunc 'minimum'>, method = 'min'
axis = None, dtype = None, out = None
kwargs = {'initial': <no value>, 'keepdims': <no value>, 'where': <no value>}
passkwargs = {}

    def _wrapreduction(obj, ufunc, method, axis, dtype, out, **kwargs):
        passkwargs = {k: v for k, v in kwargs.items()
                      if v is not np._NoValue}
    
        if type(obj) is not mu.ndarray:
            try:
                reduction = getattr(obj, method)
            except AttributeError:
                pass
            else:
                # This branch is needed for reductions like any which don't
                # support a dtype.
                if dtype is not None:
                    return reduction(axis=axis, dtype=dtype, out=out, **passkwargs)
                else:
                    return reduction(axis=axis, out=out, **passkwargs)
    
>       return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
E       ValueError: zero-size array to reduction operation minimum which has no identity

../../../../../miniforge3/envs/climada_env/lib/python3.9/site-packages/numpy/core/fromnumeric.py:88: ValueError

climada_petals.hazard.test.test_landslide.TestLandslideModule.test_from_prob

AttributeError: type object 'Centroids' has no attribute 'from_meta'
Stack trace
self = <climada_petals.hazard.test.test_landslide.TestLandslideModule testMethod=test_from_prob>

    def test_from_prob(self):
        """ Test the function from_prob()"""
    
        n_years=1000
>       LS_prob = Landslide.from_prob(bbox=(8,45,11,46),
                            path_sourcefile=LS_PROB_FILE, n_years=n_years,
                            dist='binom')

../../../../petals_install_env/workspace/climada_petals/hazard/test/test_landslide.py:84: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'climada_petals.hazard.landslide.Landslide'>
bbox = (8, 45, 11, 46)
path_sourcefile = PosixPath('/var/lib/jenkins/jobs/petals_install_env/workspace/climada_petals/hazard/test/data/test_ls_prob.tif')
corr_fact = 10000000.0, n_years = 1000, dist = 'binom'

    @classmethod
    def from_prob(cls, bbox, path_sourcefile, corr_fact=10e6, n_years=500,
                    dist='poisson'):
        """
        Set probabilistic landslide hazard (fraction, intensity and
        frequency) for a defined bounding box and time period from a raster.
        The hazard data for which this function is explicitly written
        is readily provided by UNEP & the Norwegian Geotechnical Institute
        (NGI), and can be downloaded and unzipped from
        https://preview.grid.unep.ch/index.php?preview=data&events=landslides&evcat=2&lang=eng
        for precipitation-triggered landslide and from
        https://preview.grid.unep.ch/index.php?preview=data&events=landslides&evcat=1&lang=eng
        for earthquake-triggered landslides.
        It works with any similar raster file.
        Original data is given in expected annual probability and percentage
        of pixel of occurrence of a potentially destructive landslide event
        x 1000000 (so be sure to adjust this by setting the correction factor).
        More details can be found in the landslide tutorial and under above-
        mentioned links.
    
        Events are sampled from annual occurrence probabilites via binomial or
        poisson distribution. An event therefore includes all landslides
        sampled to occur within a year for the given area.
        intensity takes a binary value (occurrence or no occurrene of a LS);
        frequency is set to 1 / n_years.
    
    
        Impact functions, since they act on the intensity, should hence be in
        the form of a step function,
        defining impact for intensity 0 and (close to) 1.
    
        Parameters
        ----------
        bbox : tuple
            (minx, miny, maxx, maxy) geographic extent of interest
        path_sourcefile : str
            path to UNEP/NGI ls hazard file (.tif)
        corr_fact : float or int
            factor by which to divide the values in the original probability
            file, in case it is not scaled to [0,1]. Default is 1'000'000
        n_years : int
            sampling period
        dist : str
            distribution to sample from. 'poisson' (default) and 'binom'
    
        Returns
        -------
        haz : climada.hazard.Landslide instance
            probabilistic LS hazard
    
        See also
        --------
        sample_events()
        """
    
        haz = cls()
        # raster with occurrence probs
        meta, prob_matrix = \
            u_coord.read_raster(path_sourcefile, geometry=[shapely.geometry.box(*bbox, ccw=True)])
>       haz.centroids = Centroids.from_meta(meta)
E       AttributeError: type object 'Centroids' has no attribute 'from_meta'

../../../../petals_install_env/workspace/climada_petals/hazard/landslide.py:304: AttributeError

climada_petals.hazard.test.test_landslide.TestLandslideModule.test_set_ls_prob

AttributeError: type object 'Centroids' has no attribute 'from_meta'
Stack trace
self = <climada_petals.hazard.test.test_landslide.TestLandslideModule testMethod=test_set_ls_prob>

    def test_set_ls_prob(self):
        """ Test deprecated function set_ls_prob()"""
        LS_prob = Landslide()
        n_years=1000
>       LS_prob.set_ls_prob(bbox=(8,45,11,46),
                            path_sourcefile=LS_PROB_FILE, n_years=n_years,
                            dist='binom')

../../../../petals_install_env/workspace/climada_petals/hazard/test/test_landslide.py:143: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../../petals_install_env/workspace/climada_petals/hazard/landslide.py:328: in set_ls_prob
    self.__dict__ = Landslide.from_prob(*args, **kwargs).__dict__
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'climada_petals.hazard.landslide.Landslide'>
bbox = (8, 45, 11, 46)
path_sourcefile = PosixPath('/var/lib/jenkins/jobs/petals_install_env/workspace/climada_petals/hazard/test/data/test_ls_prob.tif')
corr_fact = 10000000.0, n_years = 1000, dist = 'binom'

    @classmethod
    def from_prob(cls, bbox, path_sourcefile, corr_fact=10e6, n_years=500,
                    dist='poisson'):
        """
        Set probabilistic landslide hazard (fraction, intensity and
        frequency) for a defined bounding box and time period from a raster.
        The hazard data for which this function is explicitly written
        is readily provided by UNEP & the Norwegian Geotechnical Institute
        (NGI), and can be downloaded and unzipped from
        https://preview.grid.unep.ch/index.php?preview=data&events=landslides&evcat=2&lang=eng
        for precipitation-triggered landslide and from
        https://preview.grid.unep.ch/index.php?preview=data&events=landslides&evcat=1&lang=eng
        for earthquake-triggered landslides.
        It works with any similar raster file.
        Original data is given in expected annual probability and percentage
        of pixel of occurrence of a potentially destructive landslide event
        x 1000000 (so be sure to adjust this by setting the correction factor).
        More details can be found in the landslide tutorial and under above-
        mentioned links.
    
        Events are sampled from annual occurrence probabilites via binomial or
        poisson distribution. An event therefore includes all landslides
        sampled to occur within a year for the given area.
        intensity takes a binary value (occurrence or no occurrene of a LS);
        frequency is set to 1 / n_years.
    
    
        Impact functions, since they act on the intensity, should hence be in
        the form of a step function,
        defining impact for intensity 0 and (close to) 1.
    
        Parameters
        ----------
        bbox : tuple
            (minx, miny, maxx, maxy) geographic extent of interest
        path_sourcefile : str
            path to UNEP/NGI ls hazard file (.tif)
        corr_fact : float or int
            factor by which to divide the values in the original probability
            file, in case it is not scaled to [0,1]. Default is 1'000'000
        n_years : int
            sampling period
        dist : str
            distribution to sample from. 'poisson' (default) and 'binom'
    
        Returns
        -------
        haz : climada.hazard.Landslide instance
            probabilistic LS hazard
    
        See also
        --------
        sample_events()
        """
    
        haz = cls()
        # raster with occurrence probs
        meta, prob_matrix = \
            u_coord.read_raster(path_sourcefile, geometry=[shapely.geometry.box(*bbox, ccw=True)])
>       haz.centroids = Centroids.from_meta(meta)
E       AttributeError: type object 'Centroids' has no attribute 'from_meta'

../../../../petals_install_env/workspace/climada_petals/hazard/landslide.py:304: AttributeError

climada_petals.hazard.test.test_relative_cropyield.TestRelativeCropyield.test_load_EU_all

AttributeError: 'Centroids' object has no attribute 'gdf'
Stack trace
self = <climada_petals.hazard.test.test_relative_cropyield.TestRelativeCropyield testMethod=test_load_EU_all>

    def test_load_EU_all(self):
        """Test defining crop potential hazard from complete demo file (Central Europe)"""
>       haz = RelativeCropyield.from_isimip_netcdf(input_dir=INPUT_DIR, yearrange=(2001, 2005),
                                   ag_model='lpjml', cl_model='ipsl-cm5a-lr', scenario='historical',
                                   soc='2005soc', co2='co2', crop='whe', irr='noirr',
                                   fn_str_var=FN_STR_DEMO)

../../../../petals_install_env/workspace/climada_petals/hazard/test/test_relative_cropyield.py:34: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'climada_petals.hazard.relative_cropyield.RelativeCropyield'>
input_dir = PosixPath('/var/lib/jenkins/climada/demo/data')
filename = 'lpjml_ipsl-cm5a-lr_ewembi_historical_2005soc_co2_yield-whe-noirr_annual_FR_DE_DEMO_1861_2005.nc'
bbox = (-180, -85, 180, 85), yearrange = (2001, 2005), ag_model = 'lpjml'
cl_model = 'ipsl-cm5a-lr', bias_corr = 'ewembi', scenario = 'historical'
soc = '2005soc', co2 = 'co2', crop = 'whe', irr = 'noirr'
fn_str_var = 'annual_FR_DE_DEMO'

    @classmethod
    def from_isimip_netcdf(cls, input_dir=None, filename=None, bbox=None,
                           yearrange=None, ag_model=None, cl_model=None, bias_corr=None,
                           scenario=None, soc=None, co2=None, crop=None,
                           irr=None, fn_str_var=None):
    
        """Wrapper to fill hazard from crop yield NetCDF file.
        Build and tested for output from ISIMIP2 and ISIMIP3, but might also work
        for other NetCDF containing gridded crop model output from other sources.
    
        Parameters
        ----------
        input_dir : Path or str
            path to input data directory,
            default: {CONFIG.exposures.crop_production.local_data}/Input/Exposure
        filename : string
            name of netcdf file in input_dir. If filename is given,
            the other parameters specifying the model run are not required!
        bbox : list of four floats
            bounding box:
            [lon min, lat min, lon max, lat max]
        yearrange : int tuple
            year range for hazard set, f.i. (1976, 2005)
        ag_model : str
            abbrev. agricultural model (only when input_dir is selected)
            f.i. 'clm-crop', 'gepic','lpjml','pepic'
        cl_model : str
            abbrev. climate model (only when input_dir is selected)
            f.i. ['gfdl-esm2m', 'hadgem2-es','ipsl-cm5a-lr','miroc5'
        bias_corr : str
            bias correction of climate forcing,
            f.i. 'ewembi' (ISIMIP2b, default) or 'w5e5' (ISIMIP3b)
        scenario : str
            climate change scenario (only when input_dir is selected)
            f.i. 'historical' or 'rcp60' or 'ISIMIP2a'
        soc : str
            socio-economic trajectory (only when input_dir is selected)
            f.i. '2005soc' or 'histsoc'
        co2 : str
            CO2 forcing scenario (only when input_dir is selected)
            f.i. 'co2' or '2005co2'
        crop : str
            crop type (only when input_dir is selected)
            f.i. 'whe', 'mai', 'soy' or 'ric'
        irr : str
            irrigation type (only when input_dir is selected)
            f.i 'noirr' or 'irr'
        fn_str_var : str
            FileName STRing depending on VARiable and
            ISIMIP simuation round
    
        Returns
        -------
        RelativeCropyield
    
        Raises
        ------
        NameError
        """
        if not fn_str_var:
            fn_str_var = FN_STR_VAR
        if scenario is None:
            scenario = 'historical'
        if bias_corr is None:
            bias_corr = 'ewembi'
        if bbox is None:
            bbox = BBOX
        if input_dir is None:
            input_dir = INPUT_DIR
        input_dir = Path(input_dir)
        if not Path(input_dir).is_dir():
            raise NameError('Input directory %s does not exist' % input_dir)
    
        # The filename is set or other variables (cl_model, scenario) are extracted of the
        # specified filename
        if filename is None:
            yearchunk = YEARCHUNKS[scenario]
            filename = '{}_{}_{}_{}_{}_{}_yield-{}-{}_{}_{}_{}.nc'.format(
                ag_model, cl_model, bias_corr, scenario, soc, co2,
                crop, irr, fn_str_var, yearchunk['startyear'], yearchunk['endyear'])
        elif scenario == 'ISIMIP2a':
            (_, _, _, _, _, _, _, crop, _, _, startyear, endyearnc) = filename.split('_')
            endyear, _ = endyearnc.split('.')
            yearchunk = dict()
            yearchunk = {'yearrange': (int(startyear), int(endyear)),
                         'startyear': int(startyear), 'endyear': int(endyear)}
        elif scenario == 'test_file':
            yearchunk = dict()
            yearchunk = {'yearrange': (1976, 2005), 'startyear': 1861,
                         'endyear': 2005, 'yearrange_mean': (1976, 2005)}
            ag_model, cl_model, _, _, soc, co2, crop_prop, *_ = filename.split('_')
            _, crop, irr = crop_prop.split('-')
        else: # get yearchunk from filename, e.g., for rcp2.6 extended and ISIMIP3
            (_, _, _, _, _, _, crop_irr, _, _, year1, year2) = filename.split('_')
            yearchunk = {'yearrange': (int(year1), int(year2.split('.')[0])),
                         'startyear': int(year1),
                         'endyear': int(year2.split('.')[0])}
            _, crop, irr = crop_irr.split('-')
    
        # if no yearrange is given, load full range from input file:
        if yearrange is None or len(yearrange) == 0:
            yearrange = yearchunk['yearrange']
    
        # define indexes of the netcdf-bands to be extracted, and the
        # corresponding event names and dates
        # corrected indexes due to the bands in input starting with the index=1
        id_bands = np.arange(yearrange[0] - yearchunk['startyear'] + 1,
                             yearrange[1] - yearchunk['startyear'] + 2).tolist()
    
        # hazard setup: set attributes
        [lonmin, latmin, lonmax, latmax] = bbox
        haz = cls.from_raster([str(Path(input_dir, filename))], band=id_bands,
                              geometry=list([shapely.geometry.box(lonmin, latmin, lonmax, latmax)]))
        haz.intensity_def = INT_DEF
        haz.intensity.data[np.isnan(haz.intensity.data)] = 0.0
        haz.intensity.todense()
        haz.crop = crop
        haz.event_name = [str(n) for n in range(int(yearrange[0]), int(yearrange[-1] + 1))]
        haz.frequency = np.ones(len(haz.event_name)) * (1 / len(haz.event_name))
        haz.fraction = haz.intensity.copy()
        haz.fraction.data.fill(1.0)
        haz.units = 't / y / ha'
        haz.date = np.array(dt.str_to_date(
            [event_ + '-01-01' for event_ in haz.event_name]))
>       haz.centroids.gdf['region_id'] = (
            coord.coord_on_land(haz.centroids.lat, haz.centroids.lon)).astype(dtype=int)
E       AttributeError: 'Centroids' object has no attribute 'gdf'

../../../../petals_install_env/workspace/climada_petals/hazard/relative_cropyield.py:249: AttributeError

climada_petals.hazard.test.test_relative_cropyield.TestRelativeCropyield.test_set_percentile_to_int

AttributeError: 'Centroids' object has no attribute 'gdf'
Stack trace
self = <climada_petals.hazard.test.test_relative_cropyield.TestRelativeCropyield testMethod=test_set_percentile_to_int>

    def test_set_percentile_to_int(self):
        """Test setting intensity to percentile of the yield"""
>       haz = RelativeCropyield.from_isimip_netcdf(input_dir=INPUT_DIR, yearrange=(2001, 2005), ag_model='lpjml',
                                cl_model='ipsl-cm5a-lr', scenario='historical', soc='2005soc',
                                co2='co2', crop='whe', irr='noirr', fn_str_var=FN_STR_DEMO)

../../../../petals_install_env/workspace/climada_petals/hazard/test/test_relative_cropyield.py:71: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'climada_petals.hazard.relative_cropyield.RelativeCropyield'>
input_dir = PosixPath('/var/lib/jenkins/climada/demo/data')
filename = 'lpjml_ipsl-cm5a-lr_ewembi_historical_2005soc_co2_yield-whe-noirr_annual_FR_DE_DEMO_1861_2005.nc'
bbox = (-180, -85, 180, 85), yearrange = (2001, 2005), ag_model = 'lpjml'
cl_model = 'ipsl-cm5a-lr', bias_corr = 'ewembi', scenario = 'historical'
soc = '2005soc', co2 = 'co2', crop = 'whe', irr = 'noirr'
fn_str_var = 'annual_FR_DE_DEMO'

    @classmethod
    def from_isimip_netcdf(cls, input_dir=None, filename=None, bbox=None,
                           yearrange=None, ag_model=None, cl_model=None, bias_corr=None,
                           scenario=None, soc=None, co2=None, crop=None,
                           irr=None, fn_str_var=None):
    
        """Wrapper to fill hazard from crop yield NetCDF file.
        Build and tested for output from ISIMIP2 and ISIMIP3, but might also work
        for other NetCDF containing gridded crop model output from other sources.
    
        Parameters
        ----------
        input_dir : Path or str
            path to input data directory,
            default: {CONFIG.exposures.crop_production.local_data}/Input/Exposure
        filename : string
            name of netcdf file in input_dir. If filename is given,
            the other parameters specifying the model run are not required!
        bbox : list of four floats
            bounding box:
            [lon min, lat min, lon max, lat max]
        yearrange : int tuple
            year range for hazard set, f.i. (1976, 2005)
        ag_model : str
            abbrev. agricultural model (only when input_dir is selected)
            f.i. 'clm-crop', 'gepic','lpjml','pepic'
        cl_model : str
            abbrev. climate model (only when input_dir is selected)
            f.i. ['gfdl-esm2m', 'hadgem2-es','ipsl-cm5a-lr','miroc5'
        bias_corr : str
            bias correction of climate forcing,
            f.i. 'ewembi' (ISIMIP2b, default) or 'w5e5' (ISIMIP3b)
        scenario : str
            climate change scenario (only when input_dir is selected)
            f.i. 'historical' or 'rcp60' or 'ISIMIP2a'
        soc : str
            socio-economic trajectory (only when input_dir is selected)
            f.i. '2005soc' or 'histsoc'
        co2 : str
            CO2 forcing scenario (only when input_dir is selected)
            f.i. 'co2' or '2005co2'
        crop : str
            crop type (only when input_dir is selected)
            f.i. 'whe', 'mai', 'soy' or 'ric'
        irr : str
            irrigation type (only when input_dir is selected)
            f.i 'noirr' or 'irr'
        fn_str_var : str
            FileName STRing depending on VARiable and
            ISIMIP simuation round
    
        Returns
        -------
        RelativeCropyield
    
        Raises
        ------
        NameError
        """
        if not fn_str_var:
            fn_str_var = FN_STR_VAR
        if scenario is None:
            scenario = 'historical'
        if bias_corr is None:
            bias_corr = 'ewembi'
        if bbox is None:
            bbox = BBOX
        if input_dir is None:
            input_dir = INPUT_DIR
        input_dir = Path(input_dir)
        if not Path(input_dir).is_dir():
            raise NameError('Input directory %s does not exist' % input_dir)
    
        # The filename is set or other variables (cl_model, scenario) are extracted of the
        # specified filename
        if filename is None:
            yearchunk = YEARCHUNKS[scenario]
            filename = '{}_{}_{}_{}_{}_{}_yield-{}-{}_{}_{}_{}.nc'.format(
                ag_model, cl_model, bias_corr, scenario, soc, co2,
                crop, irr, fn_str_var, yearchunk['startyear'], yearchunk['endyear'])
        elif scenario == 'ISIMIP2a':
            (_, _, _, _, _, _, _, crop, _, _, startyear, endyearnc) = filename.split('_')
            endyear, _ = endyearnc.split('.')
            yearchunk = dict()
            yearchunk = {'yearrange': (int(startyear), int(endyear)),
                         'startyear': int(startyear), 'endyear': int(endyear)}
        elif scenario == 'test_file':
            yearchunk = dict()
            yearchunk = {'yearrange': (1976, 2005), 'startyear': 1861,
                         'endyear': 2005, 'yearrange_mean': (1976, 2005)}
            ag_model, cl_model, _, _, soc, co2, crop_prop, *_ = filename.split('_')
            _, crop, irr = crop_prop.split('-')
        else: # get yearchunk from filename, e.g., for rcp2.6 extended and ISIMIP3
            (_, _, _, _, _, _, crop_irr, _, _, year1, year2) = filename.split('_')
            yearchunk = {'yearrange': (int(year1), int(year2.split('.')[0])),
                         'startyear': int(year1),
                         'endyear': int(year2.split('.')[0])}
            _, crop, irr = crop_irr.split('-')
    
        # if no yearrange is given, load full range from input file:
        if yearrange is None or len(yearrange) == 0:
            yearrange = yearchunk['yearrange']
    
        # define indexes of the netcdf-bands to be extracted, and the
        # corresponding event names and dates
        # corrected indexes due to the bands in input starting with the index=1
        id_bands = np.arange(yearrange[0] - yearchunk['startyear'] + 1,
                             yearrange[1] - yearchunk['startyear'] + 2).tolist()
    
        # hazard setup: set attributes
        [lonmin, latmin, lonmax, latmax] = bbox
        haz = cls.from_raster([str(Path(input_dir, filename))], band=id_bands,
                              geometry=list([shapely.geometry.box(lonmin, latmin, lonmax, latmax)]))
        haz.intensity_def = INT_DEF
        haz.intensity.data[np.isnan(haz.intensity.data)] = 0.0
        haz.intensity.todense()
        haz.crop = crop
        haz.event_name = [str(n) for n in range(int(yearrange[0]), int(yearrange[-1] + 1))]
        haz.frequency = np.ones(len(haz.event_name)) * (1 / len(haz.event_name))
        haz.fraction = haz.intensity.copy()
        haz.fraction.data.fill(1.0)
        haz.units = 't / y / ha'
        haz.date = np.array(dt.str_to_date(
            [event_ + '-01-01' for event_ in haz.event_name]))
>       haz.centroids.gdf['region_id'] = (
            coord.coord_on_land(haz.centroids.lat, haz.centroids.lon)).astype(dtype=int)
E       AttributeError: 'Centroids' object has no attribute 'gdf'

../../../../petals_install_env/workspace/climada_petals/hazard/relative_cropyield.py:249: AttributeError

climada_petals.hazard.test.test_relative_cropyield.TestRelativeCropyield.test_set_rel_yield

AttributeError: 'Centroids' object has no attribute 'gdf'
Stack trace
self = <climada_petals.hazard.test.test_relative_cropyield.TestRelativeCropyield testMethod=test_set_rel_yield>

    def test_set_rel_yield(self):
        """Test setting intensity to relativ yield"""
>       haz = RelativeCropyield.from_isimip_netcdf(input_dir=INPUT_DIR, yearrange=(2001, 2005), ag_model='lpjml',
                                cl_model='ipsl-cm5a-lr', scenario='historical', soc='2005soc',
                                co2='co2', crop='whe', irr='noirr', fn_str_var=FN_STR_DEMO)

../../../../petals_install_env/workspace/climada_petals/hazard/test/test_relative_cropyield.py:52: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'climada_petals.hazard.relative_cropyield.RelativeCropyield'>
input_dir = PosixPath('/var/lib/jenkins/climada/demo/data')
filename = 'lpjml_ipsl-cm5a-lr_ewembi_historical_2005soc_co2_yield-whe-noirr_annual_FR_DE_DEMO_1861_2005.nc'
bbox = (-180, -85, 180, 85), yearrange = (2001, 2005), ag_model = 'lpjml'
cl_model = 'ipsl-cm5a-lr', bias_corr = 'ewembi', scenario = 'historical'
soc = '2005soc', co2 = 'co2', crop = 'whe', irr = 'noirr'
fn_str_var = 'annual_FR_DE_DEMO'

    @classmethod
    def from_isimip_netcdf(cls, input_dir=None, filename=None, bbox=None,
                           yearrange=None, ag_model=None, cl_model=None, bias_corr=None,
                           scenario=None, soc=None, co2=None, crop=None,
                           irr=None, fn_str_var=None):
    
        """Wrapper to fill hazard from crop yield NetCDF file.
        Build and tested for output from ISIMIP2 and ISIMIP3, but might also work
        for other NetCDF containing gridded crop model output from other sources.
    
        Parameters
        ----------
        input_dir : Path or str
            path to input data directory,
            default: {CONFIG.exposures.crop_production.local_data}/Input/Exposure
        filename : string
            name of netcdf file in input_dir. If filename is given,
            the other parameters specifying the model run are not required!
        bbox : list of four floats
            bounding box:
            [lon min, lat min, lon max, lat max]
        yearrange : int tuple
            year range for hazard set, f.i. (1976, 2005)
        ag_model : str
            abbrev. agricultural model (only when input_dir is selected)
            f.i. 'clm-crop', 'gepic','lpjml','pepic'
        cl_model : str
            abbrev. climate model (only when input_dir is selected)
            f.i. ['gfdl-esm2m', 'hadgem2-es','ipsl-cm5a-lr','miroc5'
        bias_corr : str
            bias correction of climate forcing,
            f.i. 'ewembi' (ISIMIP2b, default) or 'w5e5' (ISIMIP3b)
        scenario : str
            climate change scenario (only when input_dir is selected)
            f.i. 'historical' or 'rcp60' or 'ISIMIP2a'
        soc : str
            socio-economic trajectory (only when input_dir is selected)
            f.i. '2005soc' or 'histsoc'
        co2 : str
            CO2 forcing scenario (only when input_dir is selected)
            f.i. 'co2' or '2005co2'
        crop : str
            crop type (only when input_dir is selected)
            f.i. 'whe', 'mai', 'soy' or 'ric'
        irr : str
            irrigation type (only when input_dir is selected)
            f.i 'noirr' or 'irr'
        fn_str_var : str
            FileName STRing depending on VARiable and
            ISIMIP simuation round
    
        Returns
        -------
        RelativeCropyield
    
        Raises
        ------
        NameError
        """
        if not fn_str_var:
            fn_str_var = FN_STR_VAR
        if scenario is None:
            scenario = 'historical'
        if bias_corr is None:
            bias_corr = 'ewembi'
        if bbox is None:
            bbox = BBOX
        if input_dir is None:
            input_dir = INPUT_DIR
        input_dir = Path(input_dir)
        if not Path(input_dir).is_dir():
            raise NameError('Input directory %s does not exist' % input_dir)
    
        # The filename is set or other variables (cl_model, scenario) are extracted of the
        # specified filename
        if filename is None:
            yearchunk = YEARCHUNKS[scenario]
            filename = '{}_{}_{}_{}_{}_{}_yield-{}-{}_{}_{}_{}.nc'.format(
                ag_model, cl_model, bias_corr, scenario, soc, co2,
                crop, irr, fn_str_var, yearchunk['startyear'], yearchunk['endyear'])
        elif scenario == 'ISIMIP2a':
            (_, _, _, _, _, _, _, crop, _, _, startyear, endyearnc) = filename.split('_')
            endyear, _ = endyearnc.split('.')
            yearchunk = dict()
            yearchunk = {'yearrange': (int(startyear), int(endyear)),
                         'startyear': int(startyear), 'endyear': int(endyear)}
        elif scenario == 'test_file':
            yearchunk = dict()
            yearchunk = {'yearrange': (1976, 2005), 'startyear': 1861,
                         'endyear': 2005, 'yearrange_mean': (1976, 2005)}
            ag_model, cl_model, _, _, soc, co2, crop_prop, *_ = filename.split('_')
            _, crop, irr = crop_prop.split('-')
        else: # get yearchunk from filename, e.g., for rcp2.6 extended and ISIMIP3
            (_, _, _, _, _, _, crop_irr, _, _, year1, year2) = filename.split('_')
            yearchunk = {'yearrange': (int(year1), int(year2.split('.')[0])),
                         'startyear': int(year1),
                         'endyear': int(year2.split('.')[0])}
            _, crop, irr = crop_irr.split('-')
    
        # if no yearrange is given, load full range from input file:
        if yearrange is None or len(yearrange) == 0:
            yearrange = yearchunk['yearrange']
    
        # define indexes of the netcdf-bands to be extracted, and the
        # corresponding event names and dates
        # corrected indexes due to the bands in input starting with the index=1
        id_bands = np.arange(yearrange[0] - yearchunk['startyear'] + 1,
                             yearrange[1] - yearchunk['startyear'] + 2).tolist()
    
        # hazard setup: set attributes
        [lonmin, latmin, lonmax, latmax] = bbox
        haz = cls.from_raster([str(Path(input_dir, filename))], band=id_bands,
                              geometry=list([shapely.geometry.box(lonmin, latmin, lonmax, latmax)]))
        haz.intensity_def = INT_DEF
        haz.intensity.data[np.isnan(haz.intensity.data)] = 0.0
        haz.intensity.todense()
        haz.crop = crop
        haz.event_name = [str(n) for n in range(int(yearrange[0]), int(yearrange[-1] + 1))]
        haz.frequency = np.ones(len(haz.event_name)) * (1 / len(haz.event_name))
        haz.fraction = haz.intensity.copy()
        haz.fraction.data.fill(1.0)
        haz.units = 't / y / ha'
        haz.date = np.array(dt.str_to_date(
            [event_ + '-01-01' for event_ in haz.event_name]))
>       haz.centroids.gdf['region_id'] = (
            coord.coord_on_land(haz.centroids.lat, haz.centroids.lon)).astype(dtype=int)
E       AttributeError: 'Centroids' object has no attribute 'gdf'

../../../../petals_install_env/workspace/climada_petals/hazard/relative_cropyield.py:249: AttributeError

climada_petals.hazard.test.test_tc_rainfield.TestModel.test_rainfield_diff_time_steps

AttributeError: 'Centroids' object has no attribute 'get_dist_coast'
Stack trace
self = <climada_petals.hazard.test.test_tc_rainfield.TestModel testMethod=test_rainfield_diff_time_steps>

    def test_rainfield_diff_time_steps(self):
        """Check that the results do not depend too much on the track's time step sizes."""
        tc_track = TCTracks.from_processed_ibtracs_csv(TEST_TRACK)
    
>       train_org = TCRain.from_tracks(tc_track)

../../../../petals_install_env/workspace/climada_petals/hazard/test/test_tc_rainfield.py:210: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'climada_petals.hazard.tc_rainfield.TCRain'>
tracks = <climada.hazard.tc_tracks.TCTracks object at 0x7f0e9eabfc10>
centroids = <climada.hazard.centroids.centr.Centroids object at 0x7f0e9eabf2b0>
pool = None, model = 'R-CLIPER', model_kwargs = None
ignore_distance_to_coast = False, store_rainrates = False, metric = 'equirect'
intensity_thres = 0.1, max_latitude = 61, max_dist_inland_km = 1000
max_dist_eye_km = 300, max_memory_gb = 8

    @classmethod
    def from_tracks(
        cls,
        tracks: TCTracks,
        centroids: Centroids = None,
        pool: Optional[pathos.pools.ProcessPool] = None,
        model: str = 'R-CLIPER',
        model_kwargs: Optional[dict] = None,
        ignore_distance_to_coast: bool = False,
        store_rainrates: bool = False,
        metric: str = "equirect",
        intensity_thres: float = DEF_INTENSITY_THRES,
        max_latitude: float = 61,
        max_dist_inland_km: float = 1000,
        max_dist_eye_km: float = DEF_MAX_DIST_EYE_KM,
        max_memory_gb: float = DEF_MAX_MEMORY_GB,
    ):
        """
        Create new TCRain instance that contains rainfields from the specified tracks
    
        This function sets the ``intensity`` attribute to contain, for each centroid,
        the total amount of rain experienced over the whole period of each TC event in mm.
        The amount of rain is set to 0 if it does not exceed the threshold ``intensity_thres``.
    
        The ``category`` attribute is set to the value of the ``category``-attribute
        of each of the given track data sets.
    
        The ``basin`` attribute is set to the genesis basin for each event, which
        is the first value of the ``basin``-variable in each of the given track data sets.
    
        Optionally, the time-dependent rain rates can be stored using the ``store_rainrates``
        function parameter (see below).
    
        Currently, two models are supported to compute the rain rates: R-CLIPER and TCR. The
        R-CLIPER model is documented in Tuleya et al. 2007. The TCR model was used by
        Zhu et al. 2013 and Emanuel 2017 for the first time and is documented in detail in
        Lu et al. 2018. This implementation of TCR includes improvements proposed in
        Feldmann et al. 2019. TCR's accuracy is much higher than R-CLIPER's at the cost of
        additional computational and data requirements.
    
        When using the TCR model make sure that your TC track data includes the along-track
        variables "t600" (temperature at 600 hPa) and "u850"/"v850" (wind speed at 850 hPa). Both
        can be extracted from reanalysis or climate model outputs. For "t600", use the value at the
        storm center. For "u850"/"v850", use the average over the 200-500 km annulus around the
        storm center. If "u850"/"v850" is missing, this implementation sets the shear component of
        the vertical velocity to 0. If "t600" is missing, the saturation specific humidity is set
        to a universal estimate of 0.01 kg/kg. Both assumptions can have a large effect on the
        results (see Lu et al. 2018).
    
        Emanuel (2017): Assessing the present and future probability of Hurricane Harvey’s
        rainfall. Proceedings of the National Academy of Sciences 114(48): 12681–12684.
        https://doi.org/10.1073/pnas.1716222114
    
        Lu et al. (2018): Assessing Hurricane Rainfall Mechanisms Using a Physics-Based Model:
        Hurricanes Isabel (2003) and Irene (2011). Journal of the Atmospheric
        Sciences 75(7): 2337–2358. https://doi.org/10.1175/JAS-D-17-0264.1
    
        Feldmann et al. (2019): Estimation of Atlantic Tropical Cyclone Rainfall Frequency in the
        United States. Journal of Applied Meteorology and Climatology 58(8): 1853–1866.
        https://doi.org/10.1175/JAMC-D-19-0011.1
    
        Tuleya et al. (2007): Evaluation of GFDL and Simple Statistical Model Rainfall Forecasts
        for U.S. Landfalling Tropical Storms. Weather and Forecasting 22(1): 56–70.
        https://doi.org/10.1175/WAF972.1
    
        Zhu et al. (2013): Estimating tropical cyclone precipitation risk in Texas. Geophysical
        Research Letters 40(23): 6225–6230. https://doi.org/10.1002/2013GL058284
    
        Parameters
        ----------
        tracks : climada.hazard.TCTracks
            Tracks of storm events.
        centroids : Centroids, optional
            Centroids where to model TC. Default: centroids at 360 arc-seconds resolution within
            tracks' bounds.
        pool : pathos.pool, optional
            Pool that will be used for parallel computation of rain fields. Default: None
        model : str, optional
            Parametric rain model to use: "R-CLIPER" (faster and requires less inputs, but
            much less accurate, statistical approach, Tuleya et al. 2007), "TCR" (physics-based
            approach, requires non-standard along-track variables, Zhu et al. 2013).
            Default: "R-CLIPER".
        model_kwargs: dict, optional
            If given, forward these kwargs to the selected model. The implementation of the
            R-CLIPER model currently does not allow modifications, so that ``model_kwargs`` is
            ignored with ``model="R-CLIPER"``. While the TCR model can be configured in several ways,
            it is usually safe to go with the default settings. Here is the complete list of
            ``model_kwargs`` and their meaning with ``model="TCR"`` (in alphabetical order):
    
            c_drag_tif : Path or str, optional
                Path to a GeoTIFF file containing gridded drag coefficients (bottom friction). If
                not specified, an ERA5-based data set provided with CLIMADA is used. Default: None
            e_precip : float, optional
                Precipitation efficiency (unitless), the fraction of the vapor flux falling to the
                surface as rainfall (Lu et al. 2018, eq. (14)). Note that we follow the MATLAB
                reference implementation and use 0.5 as a default value instead of the 0.9 that was
                proposed in Lu et al. 2018. Default: 0.5
            elevation_tif : Path or str, optional
                Path to a GeoTIFF file containing digital elevation model data (in m). If not
                specified, an SRTM-based topography at 0.1 degree resolution provided with CLIMADA
                is used. Default: None
            matlab_ref_mode : bool, optional
                This implementation is based on a (proprietary) reference implementation in MATLAB.
                However, some (minor) changes have been applied in the CLIMADA implementation
                compared to the reference:
    
                * In the computation of horizontal wind speeds, we compute the Coriolis parameter
                  from latitude. The MATLAB code assumes a constant parameter value (5e-5).
                * As a rescaling factor from surface to gradient winds, we use a factor from the
                  literature. The factor in MATLAB is very similar, but does not specify a
                  source.
                * Instead of the "specific humidity", the (somewhat simpler) formula for the
                  "mixing ratio" is used in the MATLAB code. These quantities are almost the same
                  in practice.
                * We use the approximation of the Clausius-Clapeyron equation used by the ECMWF
                  (Buck 1981) instead of the one used in the MATLAB code (Bolton 1980).
    
                Since it might be useful to have a version that replicates the behavior of the
                reference implementation, this parameter can be set to True to enforce the exact
                behavior of the reference implementation. Default: False
            max_w_foreground : float, optional
                The maximum value (in m/s) at which to clip the vertical velocity w before
                subtracting the background subsidence velocity w_rad. Default: 7.0
            min_c_drag : float, optional
                The drag coefficient is clipped to this minimum value (esp. over ocean).
                Default: 0.001
            q_950 : float, optional
                If the track data does not include "t600" values, assume this constant value of
                saturation specific humidity (in kg/kg) at 950 hPa. Default: 0.01
            res_radial_m : float, optional
                Resolution (in m) in radial direction. This is used for the computation of discrete
                derivatives of the horizontal wind fields and derived quantities. Default: 2000.0
            w_rad : float, optional
                Background subsidence velocity (in m/s) under radiative cooling. Default: 0.005
            wind_model : str, optional
                Parametric wind field model to use, see the ``TropCyclone`` class. Default: "ER11".
    
            Default: None
        ignore_distance_to_coast : boolean, optional
            If True, centroids far from coast are not ignored. Default: False.
        store_rainrates : boolean, optional
            If True, the Hazard object gets a list ``rainrates`` of sparse matrices. For each track,
            the rain rates (in mm/h) at each centroid and track position are stored in a sparse
            matrix of shape (npositions, ncentroids). Default: False.
        metric : str, optional
            Specify an approximation method to use for earth distances:
    
            * "equirect": Distance according to sinusoidal projection. Fast, but inaccurate for
              large distances and high latitudes.
            * "geosphere": Exact spherical distance. Much more accurate at all distances, but slow.
    
            Default: "equirect".
        intensity_thres : float, optional
            Rain amounts (in mm) below this threshold are stored as 0. Default: 0.1
        max_latitude : float, optional
            No rain calculation is done for centroids with latitude larger than this parameter.
            Default: 61
        max_dist_inland_km : float, optional
            No rain calculation is done for centroids with a distance (in km) to the coast larger
            than this parameter. Default: 1000
        max_dist_eye_km : float, optional
            No rain calculation is done for centroids with a distance (in km) to the
            TC center ("eye") larger than this parameter. Default: 300
        max_memory_gb : float, optional
            To avoid memory issues, the computation is done for chunks of the track sequentially.
            The chunk size is determined depending on the available memory (in GB). Note that this
            limit applies to each thread separately if a ``pool`` is used. Default: 8
    
        Returns
        -------
        TCRain
        """
        num_tracks = tracks.size
        if centroids is None:
            centroids = Centroids.from_pnt_bounds(tracks.get_bounds(), res=0.1)
    
        if ignore_distance_to_coast:
            # Select centroids with lat <= max_latitude
            [idx_centr_filter] = (np.abs(centroids.lat) <= max_latitude).nonzero()
        else:
            # Select centroids which are inside max_dist_inland_km and lat <= max_latitude
            [idx_centr_filter] = (
>               (centroids.get_dist_coast() <= max_dist_inland_km * 1000)
                & (np.abs(centroids.lat) <= max_latitude)
            ).nonzero()
E           AttributeError: 'Centroids' object has no attribute 'get_dist_coast'

../../../../petals_install_env/workspace/climada_petals/hazard/tc_rainfield.py:410: AttributeError

more test results are not shown here, view them on Jenkins