def test_multi_poly_lookup(): # A simple quad grid nodes = np.array( [ [0.0, 0.0], # 0 [0.0, 2.0], # 1 [2.0, 0.0], # 2 [2.0, 2.0], # 3 [4.0, 0.0], # 4 [4.0, 2.0], # 5 [6.0, 0.0], # 6 [6.0, 2.0], # 7 [0.0, 4.0], # 8 [2.0, 4.0], # 9 [4.0, 4.0], # 10 [6.0, 4.0], # 11 ] ) faces = np.array([[0, 8, 9, 5, 2], [9, 11, 7, 5, -1], [4, 7, 6, -1, -1]], dtype=np.intc) tree = CellTree(nodes, faces, num_buckets=2, cells_per_leaf=1) point = np.array([1.0, 1.0]) # in POLY 1 result = tree.locate(point) assert result == 0 point[0] = 5.0 # tri 2 result = tree.locate(point) assert result == 2 point[1] = 3.0 result = tree.locate(point) assert result == 1 point[0] = -1.0 # out of grid result = tree.locate(point) assert result == -1
def test_poly_lookup(): # A simple quad grid nodes = np.array([[0.0,0.0], [0.0,2.0], [2.0,0.0], [2.0,2.0], [4.0,0.0], [4.0,2.0], [6.0,0.0], [6.0,2.0] ]) faces = np.array([[0, 2, 3, 1], [4, 6, 7, 5], ], dtype = np.intc) print(faces) print(faces.dtype) tree = CellTree(nodes, faces, 2, 1) point = np.array([1.,1.]) #in triangle 1 result = tree.find_poly(point) assert result == 0 point[0] = 5.0 # tri 2 result = tree.find_poly(point) assert result == 1 point[0] = -1.0 # out of grid result = tree.find_poly(point) assert result == -1
def test_edge_cases(): nodes = np.array([[0.0, 0.0], [2.0, 0.0], [2.0, 2.0], [0.0, 2.0], [1.0, 1.0]]) faces1 = np.array([[0, 1, 3], [1, 2, 3]], dtype=np.intc) faces2 = np.array([[0, 1, 3], [1, 2, 4], [2, 4, 3]], dtype=np.intc) tree1 = CellTree(nodes, faces1) tree2 = CellTree(nodes, faces2)
def test_triangle_lookup(): tree = CellTree(nodes, faces) point = np.array([1., 1.]) # in triangle 1 result = tree.locate(point) assert result == 0 point[0] = 2.0 # tri 2 result = tree.locate(point) assert result == 1 point[0] = -1.0 # out of grid result = tree.locate(point) assert result == -1
def test_triangle_lookup(): tree = CellTree(nodes, faces) point = np.array([1.0, 1.0]) # in triangle 1 result = tree.locate(point) assert result == 0 point[0] = 2.0 # tri 2 result = tree.locate(point) assert result == 1 point[0] = -1.0 # out of grid result = tree.locate(point) assert result == -1
def test_triangle_lookup(): tree = CellTree(nodes, faces, 2, 1) point = np.array([1.,1.]) #in triangle 1 result = tree.find_poly(point) assert result == 0 point[0] = 2.0 # tri 2 result = tree.find_poly(point) assert result == 1 point[0] = -1.0 # out of grid result = tree.find_poly(point) assert result == -1
def test_multipoint(): tree = CellTree(nodes21, faces21) points = [ (4.2, 3.0), (7.7, 13.5), (3.4, 7.000000001), (7.0, 5.0), # out of bounds points (8.66, 10.99), (7.3, 0.74), (2.5, 5.5), (9.8, 12.3), ] correct_indexes = (1, 20, 7, -1, -1, -1, -1, -1) ind = tree.multi_locate(points) assert np.array_equal(ind, correct_indexes)
def test_shape_error(): nodes = [(1, 2, 3), (3, 4, 5), (4, 5, 6)] faces = [ [0, 1, 2], [1, 3, 2], ] with pytest.raises(ValueError): # nodes is wrong shape tree = CellTree(nodes, faces) tree = CellTree(nodes2, (2, 3, 4, 5)) tree = CellTree(nodes2, ((2, 3, 4, 5), (1, 2, 3, 4, 5), (1, 2, 3, 4, 5)))
def test_poly_lookup(): # A simple quad grid nodes = np.array([ [0.0, 0.0], #0 [0.0, 2.0], #1 [2.0, 0.0], #2 [2.0, 2.0], #3 [4.0, 0.0], #4 [4.0, 2.0], #5 [6.0, 0.0], #6 [6.0, 2.0], #7 [0.0, 4.0], #8 [2.0, 4.0], #9 [4.0, 4.0], #10 [6.0, 4.0] #11 ]) #quads faces1 = np.array([ [0, 2, 3, 1], [4, 6, 7, 5], ], dtype=np.intc) #Pentas faces2 = np.array([ [0, 8, 9, 5, 2], [9, 11, 6, 2, 5], ], dtype=np.intc) tree1 = CellTree(nodes, faces1, num_buckets=2, cells_per_leaf=1) point = np.array([1., 1.]) # in triangle 1 result = tree1.locate(point) assert result == 0 point[0] = 5.0 # tri 2 result = tree1.locate(point) assert result == 1 point[0] = -1.0 # out of grid result = tree1.locate(point) assert result == -1 tree2 = CellTree(nodes, faces2, num_buckets=2, cells_per_leaf=1) point = np.array([1., 2.]) # in triangle 1 result = tree2.locate(point) assert result == 0 point[0] = 5.0 # tri 2 result = tree2.locate(point) assert result == 1 point[0] = -1.0 # out of grid result = tree2.locate(point) assert result == -1
def test_build_tree_from_coords(): """ this tests using a structured grid with cell coordinates converting it to a flattened grid with nodes and cells defined as indexes to those nodes as much as anything else, this surves as example code for how to do that. """ x, y = curv_grid(n_x=3, n_y=3, center=(0.0, 0.0), min_radius=9.0, max_radius=18.0, angle=np.pi / 4.0 ) nodes, faces = nodes_from_coords(x, y) # these range from (30., 20.) to (31.1, 21.1) tree = CellTree(nodes, faces) # try to find some points # points outside the domain: result = tree.locate([(0.0, 0.0), (19.0, 5.0), (17.0, -1.0), (9.0, 10.0), ], ) assert np.all(result == -1) # points inside the domain result = tree.locate([(10.0, 1.0), (9.0, 3.0), (8.0, 6.0), (13.0, 1.0), (12.0, 4.0), (11.0, 7.0), (16.0, 1.0), (15.0, 8.0), (13.0, 11.0), ] ) assert np.array_equal(result, [0, 1, 2, 3, 4, 5, 6, 7, 8])
def test_multipoint(): tree = CellTree(nodes21, faces21) points = [ (4.2, 3.0), (7.7, 13.5), (3.4, 7.000000001), (7.0, 5.0), # out of bounds points (8.66, 10.99), (7.3, 0.74), (2.5, 5.5), (9.8, 12.3), ] correct_indexes = (1, 20, 7, -1, -1, -1, -1, -1) ind = tree.locate(points) assert np.array_equal(ind, correct_indexes)
def test_types(): """ It should auto-cast the types to the right types for you """ nodes = np.array(nodes2, dtype=np.float32) faces = np.array(faces2, dtype=np.int64) tree = CellTree(nodes, faces) assert True
def test_init(): """ can a tree be initialized """ # with defaults tree = CellTree(nodes, faces) # with everything specified tree = CellTree(nodes, faces, num_buckets=2, cells_per_leaf=1) # with num_buckets tree = CellTree(nodes, faces, num_buckets=4) # with cells_per_leaf tree = CellTree(nodes, faces, cells_per_leaf=2) assert True
def build_celltree(self): """ Tries to build the celltree for the current UGrid. Will fail if nodes or faces is not defined. """ from cell_tree2d import CellTree if self.nodes is None or self.faces is None: raise ValueError( "Nodes and faces must be defined in order to create and use CellTree") self._tree = CellTree(self.nodes, self.faces)
def build_celltree(self): """ Tries to build the celltree for the current UGrid. Will fail if nodes or faces is not defined. """ try: from cell_tree2d import CellTree except ImportError: raise ImportError("the cell_tree2d package must be installed to " "use the celltree search:\n" "https://github.com/NOAA-ORR-ERD/cell_tree2d/") self._tree = CellTree(self.nodes, self.faces)
def test_multi_poly_lookup(): # A simple quad grid nodes = np.array([ [0.0, 0.0], #0 [0.0, 2.0], #1 [2.0, 0.0], #2 [2.0, 2.0], #3 [4.0, 0.0], #4 [4.0, 2.0], #5 [6.0, 0.0], #6 [6.0, 2.0], #7 [0.0, 4.0], #8 [2.0, 4.0], #9 [4.0, 4.0], #10 [6.0, 4.0] #11 ]) faces = np.array([[0, 8, 9, 5, 2], [9, 11, 7, 5, -1], [4, 7, 6, -1, -1]], dtype=np.intc) tree = CellTree(nodes, faces, num_buckets=2, cells_per_leaf=1) point = np.array([1., 1.]) # in POLY 1 result = tree.locate(point) assert result == 0 point[0] = 5.0 # tri 2 result = tree.locate(point) assert result == 2 point[1] = 3.0 result = tree.locate(point) assert result == 1 point[0] = -1.0 # out of grid result = tree.locate(point) assert result == -1
def build_celltree(self, grid='node'): """ Tries to build the celltree for grid defined by the node coordinates of the specified grid. :param grid: which grid to biuld the celltree for. options are: 'node', 'edge1', 'edge2', 'center' """ if not hasattr(self, '_ind_memo_dict'): self._ind_memo_dict = { 'node': None, 'edge1': None, 'edge2': None, 'center': None } if not hasattr(self, '_cell_trees'): self._cell_trees = { 'node': None, 'edge1': None, 'edge2': None, 'center': None } try: from cell_tree2d import CellTree except ImportError: raise ImportError( "the cell_tree2d package must be installed to use the " "celltree search:\n" "https://github.com/NOAA-ORR-ERD/cell_tree2d/") lon, lat = self._get_grid_vars(grid) if lon is None or lat is None: raise ValueError( "{0}_lon and {0}_lat must be defined in order to create and " "use CellTree for this grid".format(grid)) lin_nodes = np.ascontiguousarray( np.column_stack( (lon[:].reshape(-1), lat[:].reshape(-1)))).astype(np.float64) y_size = lon.shape[0] x_size = lon.shape[1] lin_faces = np.array([ np.array([[x, x + 1, x + x_size + 1, x + x_size] for x in range(0, x_size - 1, 1)]) + y * x_size for y in range(0, y_size - 1) ]) lin_faces = np.ascontiguousarray( lin_faces.reshape(-1, 4).astype(np.int32)) self._cell_trees[grid] = (CellTree(lin_nodes, lin_faces), lin_nodes, lin_faces)
def test_poly_lookup(): # A simple quad grid nodes = np.array( [ [0.0, 0.0], # 0 [0.0, 2.0], # 1 [2.0, 0.0], # 2 [2.0, 2.0], # 3 [4.0, 0.0], # 4 [4.0, 2.0], # 5 [6.0, 0.0], # 6 [6.0, 2.0], # 7 [0.0, 4.0], # 8 [2.0, 4.0], # 9 [4.0, 4.0], # 10 [6.0, 4.0], # 11 ] ) # quads faces1 = np.array([[0, 2, 3, 1], [4, 6, 7, 5]], dtype=np.intc) # Pentas faces2 = np.array([[0, 8, 9, 5, 2], [9, 11, 6, 2, 5]], dtype=np.intc) tree1 = CellTree(nodes, faces1, num_buckets=2, cells_per_leaf=1) point = np.array([1.0, 1.0]) # in triangle 1 result = tree1.locate(point) assert result == 0 point[0] = 5.0 # tri 2 result = tree1.locate(point) assert result == 1 point[0] = -1.0 # out of grid result = tree1.locate(point) assert result == -1 tree2 = CellTree(nodes, faces2, num_buckets=2, cells_per_leaf=1) point = np.array([1.0, 2.0]) # in triangle 1 result = tree2.locate(point) assert result == 0 point[0] = 5.0 # tri 2 result = tree2.locate(point) assert result == 1 point[0] = -1.0 # out of grid result = tree2.locate(point) assert result == -1
def build_celltree(self, grid='node', use_mask=True): """ Tries to build the celltree for grid defined by the node coordinates of the specified grid. :param grid: which grid to biuld the celltree for. options are: 'node', 'edge1', 'edge2', 'center' """ if not hasattr(self, '_ind_memo_dict'): self._ind_memo_dict = {'node': None, 'edge1': None, 'edge2': None, 'center': None} if not hasattr(self, '_cell_trees'): self._cell_trees = {'node': None, 'edge1': None, 'edge2': None, 'center': None} if not hasattr(self, '_masks'): self._masks = {'node':None, 'center':None, 'edge1':None, 'edge2':None} try: from cell_tree2d import CellTree except ImportError: raise ImportError("the cell_tree2d package must be installed to use the " "celltree search:\n" "https://github.com/NOAA-ORR-ERD/cell_tree2d/") lon, lat = self._get_grid_vars(grid) geo_mask = self._get_geo_mask(grid) if lon is None or lat is None: raise ValueError("{0}_lon and {0}_lat must be defined in order to create and " "use CellTree for this grid".format(grid)) if geo_mask is not None and use_mask: # Geometry has an external mask that needs to be applied. lon = lon[:].copy() lat = lat[:].copy() mask = gen_mask(geo_mask, add_boundary=self.use_masked_boundary) lon.mask = mask lat.mask = mask masked_faces_idxs = np.zeros_like(mask, dtype=np.int32) masked_faces_idxs[mask] = -1 tmp = np.where(~mask.ravel())[0] masked_faces_idxs[~mask] = np.arange(0,len(tmp)) lin_faces = np.full(shape=(lon[0:-1,0:-1].size,4), fill_value=-1, dtype=np.int32) lin_faces[:,0] = np.ravel(masked_faces_idxs[0:-1, 0:-1]) lin_faces[:,1] = np.ravel(masked_faces_idxs[0:-1, 1:]) lin_faces[:,2] = np.ravel(masked_faces_idxs[1:, 1:]) lin_faces[:,3] = np.ravel(masked_faces_idxs[1:, 0:-1]) faces_mask = np.any(lin_faces == -1, axis=1) lin_faces[faces_mask] = [-1,-1,-1,-1] lin_faces = np.ma.masked_less(lin_faces, 0).compressed().reshape(-1,4) #need to make a reversal_array. This is an array of the same length #as the unmasked nodes that contains the 'true' index of the #unmasked node. When CellTree gives back an index, it's 'true' #index is discovered using this array reversal_array = np.where(~faces_mask)[0].astype(np.int32) #append a -1 to preserve -1 entries when back-translating the indices reversal_array = np.concatenate((reversal_array, np.array([-1,]))) self._masks[grid] = (mask, reversal_array) else: self._masks[grid] = None y_size = lon.shape[0] x_size = lon.shape[1] lin_faces = np.array([np.array([[x, x + 1, x + x_size + 1, x + x_size] for x in range(0, x_size - 1, 1)]) + y * x_size for y in range (0, y_size - 1)]) lin_faces = np.ascontiguousarray(lin_faces.reshape(-1, 4).astype(np.int32)) if isinstance(lon, np.ma.MaskedArray) and lon.mask is not False and use_mask: lin_nodes = np.ascontiguousarray(np.column_stack((np.ma.compressed(lon[:]), np.ma.compressed(lat[:]))).reshape(-1, 2).astype(np.float64)) else: lin_nodes = np.ascontiguousarray(np.stack((lon, lat), axis=-1).reshape(-1, 2).astype(np.float64)) self._cell_trees[grid] = (CellTree(lin_nodes, lin_faces), lin_nodes, lin_faces)
def test_lists(): """ python lists should get converted to numpy arrays """ tree = CellTree(nodes2, faces2) assert True
def test_bounds_errors(): with pytest.raises(ValueError): tree = CellTree(nodes, faces, cells_per_leaf=-1) with pytest.raises(ValueError): tree = CellTree(nodes, faces, num_buckets=0)