def test_get_trimmed_array_by_mask_singleton_dimension(self): arr = np.array([[True, False, True]], dtype=bool) ret, adjust = get_trimmed_array_by_mask(arr, return_adjustments=True) self.assertEqual(ret.shape, (1, 1)) self.assertNumpyAll(ret, np.array([[False]])) arr = arr.reshape(3, 1) ret, adjust = get_trimmed_array_by_mask(arr, return_adjustments=True) self.assertEqual(ret.shape, (1, 1)) self.assertNumpyAll(ret, np.array([[False]]))
def test_get_trimmed_array_by_mask_rows_and_columns(self): arr = np.random.rand(4,4) arr = np.ma.array(arr,mask=False) arr.mask[0,:] = True arr.mask[-1,:] = True arr.mask[:,0] = True arr.mask[:,-1] = True ret = get_trimmed_array_by_mask(arr) self.assertNumpyAll(ret,arr[1:-1,1:-1]) self.assertTrue(np.may_share_memory(ret,arr)) ret,adjust = get_trimmed_array_by_mask(arr,return_adjustments=True) self.assertEqual(adjust,{'col': slice(1, -1), 'row': slice(1, -1)})
def test_get_trimmed_array_by_mask_none_masked(self): arr = np.random.rand(4,4) arr = np.ma.array(arr,mask=False) ret,adjust = get_trimmed_array_by_mask(arr,return_adjustments=True) self.assertNumpyAll(ret,arr) self.assertTrue(np.may_share_memory(ret,arr)) self.assertEqual(adjust,{'col': slice(0, None), 'row': slice(0, None)})
def test_get_trimmed_array_by_mask_interior_masked(self): arr = np.random.rand(4,4) arr = np.ma.array(arr,mask=False) arr[2,:] = True arr[1,:] = True ret = get_trimmed_array_by_mask(arr) self.assertNumpyAll(ret,arr) self.assertTrue(np.may_share_memory(ret,arr))
def test_get_trimmed_array_by_mask_row_only(self): arr = np.random.rand(4,4) arr = np.ma.array(arr,mask=False) arr.mask[0,:] = True arr.mask[-1,:] = True ret = get_trimmed_array_by_mask(arr) self.assertNumpyAll(ret,arr[1:-1,:]) self.assertTrue(np.may_share_memory(ret,arr))
def get_masking_slice(intersects_mask_value, target, apply_slice=True): """ Collective! :param intersects_mask_value: The mask to use for creating the slice indices. :type intersects_mask_value: :class:`numpy.ndarray`, dtype=bool :param target: The target slicable object to slice. :param bool apply_slice: If ``True``, apply the slice. """ raise_if_empty(target) if intersects_mask_value is None: local_slice = None else: if intersects_mask_value.all(): local_slice = None elif not intersects_mask_value.any(): shp = intersects_mask_value.shape local_slice = [(0, shp[0]), (0, shp[1])] else: _, local_slice = get_trimmed_array_by_mask(intersects_mask_value, return_adjustments=True) local_slice = [(l.start, l.stop) for l in local_slice] if local_slice is not None: offset_local_slice = [None] * len(local_slice) for idx in range(len(local_slice)): offset = target.dimensions[idx].bounds_local[0] offset_local_slice[idx] = (local_slice[idx][0] + offset, local_slice[idx][1] + offset) else: offset_local_slice = None gathered_offset_local_slices = vm.gather(offset_local_slice) if vm.rank == 0: gathered_offset_local_slices = [ g for g in gathered_offset_local_slices if g is not None ] if len(gathered_offset_local_slices) == 0: raise_empty_subset = True else: raise_empty_subset = False offset_array = np.array(gathered_offset_local_slices) global_slice = [None] * offset_array.shape[1] for idx in range(len(global_slice)): global_slice[idx] = (np.min(offset_array[:, idx, :]), np.max(offset_array[:, idx, :])) else: global_slice = None raise_empty_subset = None raise_empty_subset = vm.bcast(raise_empty_subset) if raise_empty_subset: raise EmptySubsetError global_slice = vm.bcast(global_slice) global_slice = tuple([slice(g[0], g[1]) for g in global_slice]) intersects_mask = Variable(name='mask_gather', value=intersects_mask_value, dimensions=target.dimensions, dtype=bool) if apply_slice: if vm.size_global > 1: ret = target.get_distributed_slice(global_slice) ret_mask = intersects_mask.get_distributed_slice(global_slice) else: ret = target.__getitem__(global_slice) ret_mask = intersects_mask.__getitem__(global_slice) else: ret = target ret_mask = intersects_mask return ret, ret_mask, global_slice
def test_get_trimmed_array_by_mask_all_masked(self): arr = np.random.rand(4,4) arr = np.ma.array(arr,mask=True) ret,adjust = get_trimmed_array_by_mask(arr,return_adjustments=True) self.assertEqual(ret.shape,(0,0)) self.assertEqual(adjust,{'col': slice(4, -5), 'row': slice(4, -5)})
def test_get_trimmed_array_by_mask_bad_type(self): arr = np.zeros((4,4)) with self.assertRaises(NotImplementedError): get_trimmed_array_by_mask(arr)
def test_get_trimmed_array_by_mask_by_bool(self): arr = np.zeros((4,4),dtype=bool) arr[-1,:] = True ret = get_trimmed_array_by_mask(arr) self.assertFalse(ret.any())
def get_intersects(self, polygon, return_indices=False, use_spatial_index=True, select_nearest=False): ret = copy(self) ## based on the set spatial abstraction, decide if bounds should be used ## for subsetting the row and column dimensions use_bounds = False if self.abstraction == 'point' else True if type(polygon) in (Point,MultiPoint): raise(ValueError('Only Polygons and MultiPolygons are acceptable geometry types for intersects operations.')) elif type(polygon) in (Polygon,MultiPolygon): ## for a polygon subset, first the grid is subsetted by the bounds ## of the polygon object. the intersects operations is then performed ## on the polygon/point representation as appropriate. minx,miny,maxx,maxy = polygon.bounds if self.grid is None: raise(NotImplementedError) else: ## reset the geometries ret._geom = None ## subset the grid by its bounding box ret.grid,slc = self.grid.get_subset_bbox(minx,miny,maxx,maxy, return_indices=True, use_bounds=use_bounds) ## update the unique identifier to copy the grid uid ret.uid = ret.grid.uid ## attempt to mask the polygons try: ## only use the polygons if the abstraction indicates as much ret._geom._polygon = ret.geom.polygon.get_intersects_masked(polygon, use_spatial_index=use_spatial_index) grid_mask = ret.geom.polygon.value.mask except ImproperPolygonBoundsError: ret._geom._point = ret.geom.point.get_intersects_masked(polygon, use_spatial_index=use_spatial_index) grid_mask = ret.geom.point.value.mask ## transfer the geometry mask to the grid mask ret.grid.value.mask[:,:,:] = grid_mask.copy() else: raise(NotImplementedError) ## barbed and circular geometries may result in rows and or columns being ## entirely masked. these rows and columns should be trimmed. _,adjust = get_trimmed_array_by_mask(ret.get_mask(), return_adjustments=True) ## use the adjustments to trim the returned data object ret = ret[adjust['row'], adjust['col']] if select_nearest: try: if self.abstraction == 'point': raise(ImproperPolygonBoundsError) else: target_geom = ret.geom.polygon.value except ImproperPolygonBoundsError: target_geom = ret.geom.point.value distances = {} centroid = polygon.centroid for select_nearest_index, geom in iter_array(target_geom, return_value=True): distances[centroid.distance(geom)] = select_nearest_index select_nearest_index = distances[min(distances.keys())] ret = ret[select_nearest_index[0], select_nearest_index[1]] if return_indices: ## adjust the returned slices if necessary if select_nearest: ret_slc = select_nearest_index else: ret_slc = [None, None] ret_slc[0] = get_added_slice(slc[0], adjust['row']) ret_slc[1] = get_added_slice(slc[1], adjust['col']) ret = (ret, tuple(ret_slc)) return(ret)