def test_last_year_pass(self): """ Test last_year """ ordinal_date = [dt.datetime.toordinal(dt.datetime(2018, 4, 6)), dt.datetime.toordinal(dt.datetime(1918, 4, 6)), dt.datetime.toordinal(dt.datetime(2019, 1, 1))] self.assertEqual(u_dt.last_year(ordinal_date), 2019) self.assertEqual(u_dt.last_year(np.array(ordinal_date)), 2019)
def generate_prob_storms(self, reg_id=528, spatial_shift=4, ssi_args={}, **kwargs): """ Generates a new hazard set with one original and 29 probabilistic storms per historic storm. This represents a partial implementation of the Monte-Carlo method described in section 2.2 of Schwierz et al. (2010), doi:10.1007/s10584-009-9712-1. It omits the rotation of the storm footprints, as well as the pseudo- random alterations to the intensity. In a first step, the original intensity and five additional intensities are saved to an array. In a second step, those 6 possible intensity levels are shifted by n raster pixels into each direction (N/S/E/W). Caveats: - Memory safety is an issue; trial with the entire dataset resulted in 60GB of swap memory being used... - Can only use numeric region_id for country selection - Drops event names as provided by WISC Parameters: region_id (int, list of ints, or None): iso_n3 code of the countries we want the generated hazard set to be returned for. spatial_shift (int): amount of raster pixels to shift by ssi_args (dict): A dictionary of arguments passed to calc_ssi **kwargs: keyword arguments passed on to self._hist2prob() Returns: new_haz (StormEurope): A new hazard set for the given country. Centroid attributes are preserved. self.orig attribute is set to True for original storms (event_id ending in 00). Also contains a ssi_prob attribute, """ # bool vector selecting the targeted centroids if reg_id is not None: if self.centroids.region_id.size == 0: self.centroids.set_region_id() if not isinstance(reg_id, list): reg_id = [reg_id] sel_cen = np.isin(self.centroids.region_id, reg_id) else: # shifting truncates valid centroids sel_cen = np.zeros(self.centroids.shape_grid, bool) sel_cen[spatial_shift:-spatial_shift, spatial_shift:-spatial_shift] = True sel_cen = sel_cen.reshape(self.centroids.size) # init probabilistic array n_out = N_PROB_EVENTS * self.size intensity_prob = sparse.lil_matrix((n_out, np.count_nonzero(sel_cen))) ssi = np.zeros(n_out) LOGGER.info('Commencing probabilistic calculations') for index, intensity1d in enumerate(self.intensity): # indices for return matrix start = index * N_PROB_EVENTS end = (index + 1) * N_PROB_EVENTS intensity_prob[start:end, :], ssi[start:end] =\ self._hist2prob( intensity1d, sel_cen, spatial_shift, ssi_args, **kwargs, ) LOGGER.info('Generating new StormEurope instance') new_haz = StormEurope() new_haz.intensity = sparse.csr_matrix(intensity_prob) new_haz.ssi_full_area = ssi # don't use synthetic dates; just repeat the historic dates new_haz.date = np.repeat(self.date, N_PROB_EVENTS) # subsetting centroids new_haz.centroids = self.centroids.select(sel_cen=sel_cen) # construct new event ids base = np.repeat((self.event_id * 100), N_PROB_EVENTS) synth_id = np.tile(np.arange(N_PROB_EVENTS), self.size) new_haz.event_id = base + synth_id # frequency still based on the historic number of years new_haz.frequency = np.divide(np.ones_like( new_haz.event_id), (last_year(self.date) - first_year(self.date))) self.tag = TagHazard( HAZ_TYPE, 'Hazard set not saved by default', description='WISC probabilistic hazard set using Schwierz et al.') new_haz.fraction = new_haz.intensity.copy().tocsr() new_haz.fraction.data.fill(1) new_haz.orig = (new_haz.event_id % 100 == 0) new_haz.check() return new_haz
def read_footprints(self, path, description=None, ref_raster=None, centroids=None, files_omit='fp_era20c_1990012515_701_0.nc'): """ Clear instance and read WISC footprints into it. Read Assumes that all footprints have the same coordinates as the first file listed/first file in dir. Parameters: path (str, list(str)): A location in the filesystem. Either a path to a single netCDF WISC footprint, or a folder containing only footprints, or a globbing pattern to one or more footprints. description (str, optional): description of the events, defaults to 'WISC historical hazard set' ref_raster (str, optional): Reference netCDF file from which to construct a new barebones Centroids instance. Defaults to the first file in path. centroids (Centroids, optional): A Centroids struct, overriding ref_raster files_omit (str, list(str), optional): List of files to omit; defaults to one duplicate storm present in the WISC set as of 2018-09-10. """ self.clear() file_names = get_file_names(path) if ref_raster is not None and centroids is not None: LOGGER.warning('Overriding ref_raster with centroids') if centroids is not None: pass elif ref_raster is not None: centroids = self._centroids_from_nc(ref_raster) elif ref_raster is None: centroids = self._centroids_from_nc(file_names[0]) if isinstance(files_omit, str): files_omit = [files_omit] LOGGER.info('Commencing to iterate over netCDF files.') for file_name in file_names: if any(fo in file_name for fo in files_omit): LOGGER.info("Omitting file %s", file_name) continue new_haz = self._read_one_nc(file_name, centroids) if new_haz is not None: self.append(new_haz) self.event_id = np.arange(1, len(self.event_id) + 1) self.frequency = np.divide(np.ones_like( self.date), (last_year(self.date) - first_year(self.date))) self.tag = TagHazard(HAZ_TYPE, 'Hazard set not saved by default', description='WISC historical hazard set.') if description is not None: self.tag.description = description
def from_footprints(cls, path, description=None, ref_raster=None, centroids=None, files_omit='fp_era20c_1990012515_701_0.nc', combine_threshold=None, intensity_thres=None): """Create new StormEurope object from WISC footprints. Assumes that all footprints have the same coordinates as the first file listed/first file in dir. Parameters ---------- path : str, list(str) A location in the filesystem. Either a path to a single netCDF WISC footprint, or a folder containing only footprints, or a globbing pattern to one or more footprints. description : str, optional description of the events, defaults to 'WISC historical hazard set' ref_raster : str, optional Reference netCDF file from which to construct a new barebones Centroids instance. Defaults to the first file in path. centroids : Centroids, optional A Centroids struct, overriding ref_raster files_omit : str, list(str), optional List of files to omit; defaults to one duplicate storm present in the WISC set as of 2018-09-10. combine_threshold : int, optional threshold for combining events in number of days. if the difference of the dates (self.date) of two events is smaller or equal to this threshold, the two events are combined into one. Default is None, Advised for WISC is 2 intensity_thres : float, optional Intensity threshold for storage in m/s. Default: class attribute StormEurope.intensity_thres (same as used by WISC SSI calculations) Returns ------- haz : StormEurope StormEurope object with data from WISC footprints. """ intensity_thres = cls.intensity_thres if intensity_thres is None else intensity_thres file_names = get_file_names(path) if ref_raster is not None and centroids is not None: LOGGER.warning('Overriding ref_raster with centroids') if centroids is not None: pass elif ref_raster is not None: centroids = cls._centroids_from_nc(ref_raster) elif ref_raster is None: centroids = cls._centroids_from_nc(file_names[0]) if isinstance(files_omit, str): files_omit = [files_omit] LOGGER.info('Commencing to iterate over netCDF files.') haz = cls() for file_name in file_names: if any(fo in file_name for fo in files_omit): LOGGER.info("Omitting file %s", file_name) continue new_haz = cls._read_one_nc(file_name, centroids, intensity_thres) if new_haz is not None: haz.append(new_haz) haz.event_id = np.arange(1, len(haz.event_id) + 1) haz.frequency = np.divide( np.ones_like(haz.date), np.max([(last_year(haz.date) - first_year(haz.date)), 1])) haz.tag = TagHazard(HAZ_TYPE, 'Hazard set not saved by default', description='WISC historical hazard set.') if description is not None: haz.tag.description = description if combine_threshold is not None: LOGGER.info('Combining events with small difference in date.') difference_date = np.diff(haz.date) for event_id_i in haz.event_id[np.append( difference_date <= combine_threshold, False)]: event_ids = [event_id_i, event_id_i + 1] haz._combine_events(event_ids) return haz