def test_wrong_method_fail(self): ''' Check exception is thrown when wrong method is given''' with self.assertLogs('climada.util.interpolation', level='ERROR') as cm: interp.interpol_index(np.ones((10, 2)), np.ones((7, 2)), 'method') self.assertIn('Interpolation using method' + \ ' with distance haversine is not supported.', cm.output[0])
def test_wrong_method_fail(self): """Check exception is thrown when wrong method is given""" with self.assertRaises(ValueError) as cm: u_interp.interpol_index(np.ones((10, 2)), np.ones((7, 2)), 'method') self.assertIn( 'Interpolation using method with distance haversine is not supported.', str(cm.exception))
def test_wrong_distance_fail(self): """Check exception is thrown when wrong distance is given""" with self.assertRaises(ValueError) as cm: u_interp.interpol_index(np.ones((10, 2)), np.ones((7, 2)), distance='distance') self.assertIn( 'Interpolation using NN with distance distance is not supported.', str(cm.exception))
def test_wrong_coord_fail(self): """Check exception is thrown when coordinates missing one dimension""" with self.assertRaises(IndexError): interp.interpol_index(np.ones((10, 2)), np.ones((7, 1)), distance='approx') with self.assertRaises(ValueError): interp.interpol_index(np.ones((10, 2)), np.ones((7, 1)), distance='haversine')
def test_wrong_distance_fail(self): """Check exception is thrown when wrong distance is given""" with self.assertLogs('climada.util.interpolation', level='ERROR') as cm: interp.interpol_index(np.ones((10, 2)), np.ones((7, 2)), distance='distance') self.assertIn( 'Interpolation using NN with distance distance is not supported.', cm.output[0])
def test_wrong_centroid_fail(self): ''' Check exception is thrown when centroids missing one dimension''' with self.assertRaises(IndexError): interp.interpol_index(np.ones((10, 1)), np.ones((7, 2)), distance='approx') with self.assertRaises(ValueError): interp.interpol_index(np.ones((10, 1)), np.ones((7, 2)), distance='haversine')
def normal_pass(self, dist): """Checking result against matlab climada_demo_step_by_step""" # Load input exposures, centroids = def_input_values() # Interpolate with default threshold neighbors = interp.interpol_index(centroids, exposures, 'NN', dist) # Reference output ref_neighbors = def_ref() # Check results self.assertEqual(exposures.shape[0], len(neighbors)) self.assertTrue(np.array_equal(neighbors, ref_neighbors))
def assign_centroids(self, hazard, method='NN', distance='haversine', threshold=100): """Assign for each exposure coordinate closest hazard coordinate. -1 used for disatances > threshold in point distances. If raster hazard, -1 used for centroids outside raster. Parameters: hazard (Hazard): hazard to match (with raster or vector centroids) method (str, optional): interpolation method to use in vector hazard. Nearest neighbor (NN) default distance (str, optional): distance to use in vector hazard. Haversine default threshold (float): distance threshold in km over which no neighbor will be found in vector hazard. Those are assigned with a -1. Default 100 km. """ LOGGER.info('Matching %s exposures with %s centroids.', str(self.shape[0]), str(hazard.centroids.size)) if not co.equal_crs(self.crs, hazard.centroids.crs): LOGGER.error('Set hazard and exposure to same CRS first!') raise ValueError if hazard.centroids.meta: x_i = ((self.longitude.values - hazard.centroids.meta['transform'][2]) / hazard.centroids.meta['transform'][0]).astype(int) y_i = ((self.latitude.values - hazard.centroids.meta['transform'][5]) / hazard.centroids.meta['transform'][4]).astype(int) assigned = y_i * hazard.centroids.meta['width'] + x_i assigned[assigned < 0] = -1 assigned[assigned >= hazard.centroids.size] = -1 else: coord = np.stack([self.latitude.values, self.longitude.values], axis=1) if np.array_equal(coord, hazard.centroids.coord): assigned = np.arange(self.shape[0]) else: assigned = interpol_index(hazard.centroids.coord, coord, method=method, distance=distance, threshold=threshold) self[INDICATOR_CENTR + hazard.tag.haz_type] = assigned
def repeat_coord_pass(self, dist): """Check that exposures with the same coordinates have same neighbors""" # Load input exposures, centroids = def_input_values() # Repeat a coordinate exposures[2, :] = exposures[0, :] # Interpolate with default threshold neighbors = interp.interpol_index(centroids, exposures, 'NN', dist) # Check output neighbors have same size as coordinates self.assertEqual(len(neighbors), exposures.shape[0]) # Check copied coordinates have same neighbors self.assertEqual(neighbors[2], neighbors[0])
def normal_warning(self, dist): """Checking that a warning is raised when minimum distance greater than threshold""" # Load input exposures, centroids = def_input_values() # Interpolate with lower threshold to raise warnings threshold = 50 with self.assertLogs('climada.util.interpolation', level='INFO') as cm: neighbors = interp.interpol_index(centroids, exposures, 'NN', dist, threshold=threshold) self.assertIn("Distance to closest centroid", cm.output[0]) ref_neighbors = def_ref_50() self.assertTrue(np.array_equal(neighbors, ref_neighbors))
def set_flooded_area_cut(self, coordinates, centr_indices=None): """ Calculates flooded area for any window given with coordinates or from indices of hazard centroids. sets yearly flooded area and per event Parameters: coordinates(2d array): coordinates of window centr_indices(1d array): indices of hazard centroid Raises: MemoryError """ if centr_indices is None: centr_indices = interpol_index(self.centroids.coord, coordinates) self.centroids.set_area_pixel() area_centr = self.centroids.area_pixel[centr_indices] event_years = np.array([ date.fromordinal(self.date[i]).year for i in range(len(self.date)) ]) years = np.unique(event_years) year_ev_mk = self._annual_event_mask(event_years, years) try: self.fla_ev_centr = np.zeros((self._n_events, len(centr_indices))) self.fla_ann_centr = np.zeros((len(years), len(centr_indices))) self.fla_ev_centr = np.array( np.multiply(self.fraction[:, centr_indices].todense(), area_centr)) self.fla_event = np.sum(self.fla_ev_centr, axis=1) for year_ind in range(len(years)): self.fla_ann_centr[year_ind, :] = \ np.sum(self.fla_ev_centr[year_ev_mk[year_ind, :], :], axis=0) self.fla_annual = np.sum(self.fla_ann_centr, axis=1) self.fla_ann_av = np.mean(self.fla_annual) self.fla_ev_av = np.mean(self.fla_event) except MemoryError: self.fla_ev_centr = None self.fla_event = None self.fla_ann_centr = None self.fla_annual = None self.fla_ann_av = None self.fla_ev_av = None LOGGER.warning('Number of events and slected area exceed ' + 'memory capacities, area has not been calculated,' + ' attributes set to None')
def assign_centroids(self, hazard, method='NN', distance='haversine', threshold=100): """ Assign for each exposure coordinate closest hazard coordinate Parameters: hazard (Hazard): hazard to match method (str, optional): interpolation method to use. Nearest neighbor (NN) default distance (str, optional): distance to use. Haversine default threshold (float): distance threshold in km over which no neighbor will be found. Those are assigned with a -1 index. Default 100 """ LOGGER.info('Matching %s exposures with %s centroids.', str(self.shape[0]), str(hazard.centroids.size)) coord = np.stack([self.latitude.values, self.longitude.values], axis=1) if np.array_equal(coord, hazard.centroids.coord): assigned = np.arange(self.shape[0]) else: assigned = interpol_index(hazard.centroids.coord, coord, \ method=method, distance=distance, threshold=threshold) self[INDICATOR_CENTR + hazard.tag.haz_type] = assigned
def assign_centroids(self, hazard, method='NN', distance='haversine', threshold=100): """Assign for each exposure coordinate closest hazard coordinate. -1 used for disatances > threshold in point distances. If raster hazard, -1 used for centroids outside raster. Parameters: hazard (Hazard): hazard to match (with raster or vector centroids) method (str, optional): interpolation method to use in vector hazard. Nearest neighbor (NN) default distance (str, optional): distance to use in vector hazard. Haversine default threshold (float): distance threshold in km over which no neighbor will be found in vector hazard. Those are assigned with a -1. Default 100 km. """ LOGGER.info('Matching %s exposures with %s centroids.', str(self.gdf.shape[0]), str(hazard.centroids.size)) if not u_coord.equal_crs(self.crs, hazard.centroids.crs): LOGGER.error('Set hazard and exposure to same CRS first!') raise ValueError if hazard.centroids.meta: xres, _, xmin, _, yres, ymin = hazard.centroids.meta[ 'transform'][:6] xmin, ymin = xmin + 0.5 * xres, ymin + 0.5 * yres x_i = np.round( (self.gdf.longitude.values - xmin) / xres).astype(int) y_i = np.round( (self.gdf.latitude.values - ymin) / yres).astype(int) assigned = y_i * hazard.centroids.meta['width'] + x_i assigned[(x_i < 0) | (x_i >= hazard.centroids.meta['width'])] = -1 assigned[(y_i < 0) | (y_i >= hazard.centroids.meta['height'])] = -1 else: coord = np.stack( [self.gdf.latitude.values, self.gdf.longitude.values], axis=1) haz_coord = hazard.centroids.coord if np.array_equal(coord, haz_coord): assigned = np.arange(self.gdf.shape[0]) else: # pairs of floats can be sorted (lexicographically) in NumPy coord_view = coord.view(dtype='float64,float64').reshape(-1) haz_coord_view = haz_coord.view( dtype='float64,float64').reshape(-1) # assign each hazard coordinate to an element in coord using searchsorted coord_sorter = np.argsort(coord_view) haz_assign_idx = np.fmin( coord_sorter.size - 1, np.searchsorted(coord_view, haz_coord_view, side="left", sorter=coord_sorter)) haz_assign_idx = coord_sorter[haz_assign_idx] # determine which of the assignements match exactly haz_match_idx = ( coord_view[haz_assign_idx] == haz_coord_view).nonzero()[0] assigned = np.full_like(coord_sorter, -1) assigned[haz_assign_idx[haz_match_idx]] = haz_match_idx # assign remaining coordinates to their geographically nearest neighbor if haz_match_idx.size != coord_view.size: not_assigned_mask = (assigned == -1) assigned[not_assigned_mask] = interpol_index( haz_coord, coord[not_assigned_mask], method=method, distance=distance, threshold=threshold) self.gdf[INDICATOR_CENTR + hazard.tag.haz_type] = assigned