def test_bigger(self): """test_bigger test larger mesh """ points, vertices, boundary = rectangular(4, 4, 1, 1) mesh = Mesh(points, vertices, boundary) #Test that points are arranged in a counter clock wise order mesh.check_integrity() root = MeshQuadtree(mesh) root.set_last_triangle() for x in [[0.6, 0.3], [0.1, 0.2], [0.7,0.7], [0.1,0.9], [0.4,0.6], [0.9,0.1], [10, 3]]: found, s0, s1, s2, k = root.search_fast(ensure_numeric(x)) if k >= 0: V = mesh.get_vertex_coordinates(k) # nodes for triangle k assert is_inside_polygon(x, V) assert found is True #print k, x else: assert found is False
def build_submesh(nodes, triangles, boundary, quantities, triangles_per_proc, parameters = None): # Temporarily build the mesh to find the neighbouring # triangles and true boundary polygon\ mesh = Mesh(nodes, triangles, boundary) boundary_polygon = mesh.get_boundary_polygon() # Subdivide into non-overlapping partitions submeshf = submesh_full(mesh, triangles_per_proc) # Add any extra ghost boundary layer information submeshg = submesh_ghost(submeshf, mesh, triangles_per_proc, parameters) # Order the quantities information to be the same as the triangle # information submesh = submesh_quantities(submeshg, quantities, \ triangles_per_proc) submesh["boundary_polygon"] = boundary_polygon return submesh
def test_large(self): """test_larger mesh and different quad trees """ points, vertices, boundary = rectangular(10, 12, 1, 1) mesh = Mesh(points, vertices, boundary) #Test that points are arranged in a counter clock wise order mesh.check_integrity() root = MeshQuadtree(mesh) root.set_last_triangle() #print m, root.show() for x in [[0.6, 0.3], [0.1, 0.2], [0.7,0.7], [0.1,0.9], [0.4,0.6], [0.9,0.1], [10, 3]]: found, s0, s1, s2, k = root.search_fast(x) if k >= 0: V = mesh.get_vertex_coordinates(k) # nodes for triangle k assert is_inside_triangle(x, V, closed=True) assert is_inside_polygon(x, V) assert found is True else: assert found is False if k == 0: return
def get_matrix_A(fn, gauge_name): # points to read information from point_reader = reader(file(gauge_name)) points = [] point_name = [] for i, row in enumerate(point_reader): if i == 0: for j, value in enumerate(row): if value.strip() == 'easting': easting = j if value.strip() == 'northing': northing = j if value.strip() == 'name': name = j if value.strip() == 'elevation': elevation = j else: #points.append([float(row[easting]),float(row[northing])]) points.append([float(row[easting]), float(row[northing])]) point_name.append(row[name]) points_array = np.array(points, np.float) dim_gauge = int(np.sqrt(points_array.shape[0])) interpolation_points = ensure_absolute(points_array) # read the sww file to extract something fid = NetCDFFile(fn, netcdf_mode_r) xllcorner = fid.xllcorner yllcorner = fid.yllcorner zone = fid.zone x = fid.variables['x'][:] y = fid.variables['y'][:] triangles = fid.variables['volumes'][:] x = np.reshape(x, (len(x), 1)) y = np.reshape(y, (len(y), 1)) vertex_coordinates = np.concatenate((x, y), axis=1) ele = fid.variables['elevation'][:] fid.close() vertex_coordinates = ensure_absolute(vertex_coordinates) triangles = ensure_numeric(triangles) interpolation_points = ensure_numeric(interpolation_points) interpolation_points[:, 0] -= xllcorner interpolation_points[:, 1] -= yllcorner mesh = Mesh(vertex_coordinates, triangles) mesh_boundary_polygon = mesh.get_boundary_polygon() indices = outside_polygon(interpolation_points, mesh_boundary_polygon) interp = Interpolate(vertex_coordinates, triangles) matrix_A, inside_poly_indices, outside_poly_indices, centroids = interp._build_interpolation_matrix_A( interpolation_points, output_centroids=False, verbose=False) ele = matrix_A * ele ele = np.asarray(ele) ele = ele.reshape((100, 100)) return ele, matrix_A
def test_small(self): """test_small: Two triangles """ points, vertices, boundary = rectangular(1, 1, 1, 1) mesh = Mesh(points, vertices, boundary) #Test that points are arranged in a counter clock wise order mesh.check_integrity() root = MeshQuadtree(mesh) root.set_last_triangle() x = [0.2, 0.7] found, s0, s1, s2, k = root.search_fast(x) assert k == 1 # Triangle one assert found is True
def test_off_and_boundary(self): """test_off: Test a point off the mesh """ points, vertices, boundary = rectangular(1, 1, 1, 1) mesh = Mesh(points, vertices, boundary) #Test that points are arranged in a counter clock wise order mesh.check_integrity() root = MeshQuadtree(mesh) root.set_last_triangle() found, s0, s1, s2, k = root.search_fast([-0.2, 10.7]) assert found is False found, s0, s1, s2, k = root.search_fast([0, 0]) assert found is True
def test_underlying_function(self): """test_larger mesh and different quad trees """ return points, vertices, boundary = rectangular(2, 2, 1, 1) mesh = Mesh(points, vertices, boundary) root = MeshQuadtree(mesh) root.set_last_triangle() # One point x = ensure_numeric([0.5, 0.5]) found, sigma0, sigma1, sigma2, k = \ root._search_triangles_of_vertices(root.search(x), x) if k >= 0: V = mesh.get_vertex_coordinates(k) # nodes for triangle k assert is_inside_polygon(x, V) assert found is True else: assert found is False # More points for x in [[0.6, 0.3], [0.1, 0.2], [0.7,0.7], [0.1,0.9], [0.4,0.6], [0.9,0.1], [10, 3]]: triangles = root.search(x) #print x, candidate_vertices found, sigma0, sigma1, sigma2, k = \ root._search_triangles_of_vertices(triangles, ensure_numeric(x)) if k >= 0: V = mesh.get_vertex_coordinates(k) # nodes for triangle k assert is_inside_polygon(x, V) assert found is True else: assert found is False
def expanding_search(self): """test_larger mesh and different quad trees """ p0 = [2,1] p1 = [4,1] p2 = [4.,4] p3 = [2,4] p4 = [5,4] p5 = [-1,-1] p6 = [1,-1] p7 = [1,1] p8 = [-1,1] points = [p0,p1,p2, p3,p4,p5,p6,p7,p8] # vertices = [[0,1,2],[0,2,3],[1,4,2],[5,6,7], [5,7,8]] mesh = Mesh(points, vertices) # Don't do this, want to control the max and mins #root = build_quadtree(mesh, max_points_per_cell=4) root = Cell(-3, 9, -3, 9, max_points_per_cell = 4) #Insert indices of all vertices root.insert( list(range(mesh.number_of_nodes)) ) #Build quad tree and return root.split() # One point #x = [3.5, 1.5] x = [2.5, 1.5] element_found, sigma0, sigma1, sigma2, k = root.search_fast(x) # One point x = [3.00005, 2.999994] element_found, sigma0, sigma1, sigma2, k = root.search_fast(x) assert element_found is True assert k == 1
def _fit_to_mesh(point_coordinates, vertex_coordinates=None, triangles=None, mesh=None, point_attributes=None, alpha=DEFAULT_ALPHA, verbose=False, mesh_origin=None, data_origin=None, max_read_lines=None, attribute_name=None, cg_precon='Jacobi', use_c_cg=True): """ Fit a smooth surface to a triangulation, given data points with attributes. Inputs: vertex_coordinates: List of coordinate pairs [xi, eta] of points constituting a mesh (or an m x 2 numeric array or a geospatial object) Points may appear multiple times (e.g. if vertices have discontinuities) triangles: List of 3-tuples (or a numeric array) of integers representing indices of all vertices in the mesh. point_coordinates: List of coordinate pairs [x, y] of data points (or an nx2 numeric array). This can also be a .csv/.txt/.pts file name. alpha: Smoothing parameter. mesh_origin: A geo_reference object or 3-tuples consisting of UTM zone, easting and northing. If specified vertex coordinates are assumed to be relative to their respective origins. point_attributes: Vector or array of data at the point_coordinates. """ if mesh is None: # FIXME(DSG): Throw errors if triangles or vertex_coordinates # are None #Convert input to numeric arrays triangles = ensure_numeric(triangles, num.int) vertex_coordinates = ensure_absolute(vertex_coordinates, geo_reference=mesh_origin) if verbose: log.critical('_fit_to_mesh: Building mesh') mesh = Mesh(vertex_coordinates, triangles) # Don't need this as we have just created the mesh #mesh.check_integrity() interp = Fit(mesh=mesh, verbose=verbose, alpha=alpha, cg_precon=cg_precon, use_c_cg=use_c_cg) vertex_attributes = interp.fit(point_coordinates, point_attributes, point_origin=data_origin, max_read_lines=max_read_lines, attribute_name=attribute_name, verbose=verbose) # Add the value checking stuff that's in least squares. # Maybe this stuff should get pushed down into Fit. # at least be a method of Fit. # Or intigrate it into the fit method, saving teh max and min's # as att's. return vertex_attributes
def __init__(self, time, quantities, quantity_names=None, vertex_coordinates=None, triangles=None, interpolation_points=None, time_thinning=1, verbose=False, gauge_neighbour_id=None, output_centroids=False): """Initialise object and build spatial interpolation if required Time_thinning_number controls how many timesteps to use. Only timesteps with index%time_thinning_number == 0 will used, or in other words a value of 3, say, will cause the algorithm to use every third time step. """ from anuga.config import time_format if verbose is True: log.critical('Interpolation_function: input checks') # Check temporal info time = ensure_numeric(time) if not num.alltrue(time[1:] - time[:-1] >= 0): # This message is time consuming to form due to the conversion of msg = 'Time must be a monotonuosly increasing sequence %s' % time raise Exception(msg) # Check if quantities is a single array only if not isinstance(quantities, dict): quantities = ensure_numeric(quantities) quantity_names = ['Attribute'] # Make it a dictionary quantities = {quantity_names[0]: quantities} # Use keys if no names are specified if quantity_names is None: quantity_names = list(quantities.keys()) # Check spatial info if vertex_coordinates is None: self.spatial = False else: # FIXME (Ole): Try ensure_numeric here - # this function knows nothing about georefering. vertex_coordinates = ensure_absolute(vertex_coordinates) if triangles is not None: triangles = ensure_numeric(triangles) self.spatial = True if verbose is True: log.critical('Interpolation_function: thinning by %d' % time_thinning) # Thin timesteps if needed # Note array() is used to make the thinned arrays contiguous in memory self.time = num.array(time[::time_thinning]) for name in quantity_names: if len(quantities[name].shape) == 2: quantities[name] = num.array( quantities[name][::time_thinning, :]) if verbose is True: log.critical('Interpolation_function: precomputing') # Save for use with statistics self.quantities_range = {} for name in quantity_names: q = quantities[name][:].flatten() self.quantities_range[name] = [min(q), max(q)] self.quantity_names = quantity_names self.vertex_coordinates = vertex_coordinates self.interpolation_points = interpolation_points self.index = 0 # Initial time index self.precomputed_values = {} self.centroids = [] # Precomputed spatial interpolation if requested if interpolation_points is not None: #no longer true. sts files have spatial = True but #if self.spatial is False: # raise Exception('Triangles and vertex_coordinates must be specified') # try: self.interpolation_points = \ interpolation_points = ensure_numeric(interpolation_points) except: msg = 'Interpolation points must be an N x 2 numeric array ' \ 'or a list of points\n' msg += 'Got: %s.' % (str(self.interpolation_points)[:60] + '...') raise Exception(msg) # Ensure 'mesh_boundary_polygon' is defined mesh_boundary_polygon = None if triangles is not None and vertex_coordinates is not None: # Check that all interpolation points fall within # mesh boundary as defined by triangles and vertex_coordinates. from anuga.abstract_2d_finite_volumes.neighbour_mesh import Mesh from anuga.geometry.polygon import outside_polygon # Create temporary mesh object from mesh info passed # into this function. mesh = Mesh(vertex_coordinates, triangles) mesh_boundary_polygon = mesh.get_boundary_polygon() indices = outside_polygon(interpolation_points, mesh_boundary_polygon) # Record result #self.mesh_boundary_polygon = mesh_boundary_polygon self.indices_outside_mesh = indices # Report if len(indices) > 0: msg = 'Interpolation points in Interpolation function fall ' msg += 'outside specified mesh. Offending points:\n' out_interp_pts = [] for i in indices: msg += '%d: %s\n' % (i, interpolation_points[i]) out_interp_pts.append( ensure_numeric(interpolation_points[i])) if verbose is True: import sys from anuga.geometry.polygon import plot_polygons title = ('Interpolation points fall ' 'outside specified mesh') plot_polygons([ mesh_boundary_polygon, interpolation_points, out_interp_pts ], ['line', 'point', 'outside'], figname='points_boundary_out', label=title) # Joaquim Luis suggested this as an Exception, so # that the user can now what the problem is rather than # looking for NaN's. However, NANs are handy as they can # be ignored leaving good points for continued processing. if verbose: log.critical(msg) #raise Exception(msg) elif triangles is None and vertex_coordinates is not None: #jj #Dealing with sts file pass else: raise Exception( 'Sww file function requires both triangles and ' 'vertex_coordinates. sts file file function ' 'requires the latter.') # Plot boundary and interpolation points, # but only if if 'mesh_boundary_polygon' has data. if verbose is True and mesh_boundary_polygon is not None: import sys if sys.platform == 'win32': from anuga.geometry.polygon import plot_polygons title = ('Interpolation function: ' 'Polygon and interpolation points') plot_polygons( [mesh_boundary_polygon, interpolation_points], ['line', 'point'], figname='points_boundary', label=title) m = len(self.interpolation_points) p = len(self.time) for name in quantity_names: self.precomputed_values[name] = num.zeros((p, m), num.float) if verbose is True: log.critical('Build interpolator') # Build interpolator if triangles is not None and vertex_coordinates is not None: if verbose: msg = 'Building interpolation matrix from source mesh ' msg += '(%d vertices, %d triangles)' \ % (vertex_coordinates.shape[0], triangles.shape[0]) log.critical(msg) # This one is no longer needed for STS files interpol = Interpolate(vertex_coordinates, triangles, verbose=verbose) elif triangles is None and vertex_coordinates is not None: if verbose: log.critical('Interpolation from STS file') if verbose: log.critical( 'Interpolating (%d interpolation points, %d timesteps).' % (self.interpolation_points.shape[0], self.time.shape[0])) if time_thinning > 1: log.critical('Timesteps were thinned by a factor of %d' % time_thinning) else: log.critical() for i, t in enumerate(self.time): # Interpolate quantities at this timestep #if verbose and i%((p+10)/10) == 0: if verbose: log.critical(' time step %d of %d' % (i, p)) for name in quantity_names: if len(quantities[name].shape) == 2: Q = quantities[name][i, :] # Quantities at timestep i else: Q = quantities[name][:] # No time dependency #if verbose and i%((p+10)/10) == 0: if verbose: log.critical(' quantity %s, size=%d' % (name, len(Q))) # Interpolate if triangles is not None and vertex_coordinates is not None: result = interpol.interpolate(Q, point_coordinates=\ self.interpolation_points, verbose=False, output_centroids=output_centroids) self.centroids = interpol.centroids elif triangles is None and vertex_coordinates is not None: result = interpolate_polyline(Q, vertex_coordinates, gauge_neighbour_id, interpolation_points=\ self.interpolation_points) #assert len(result), len(interpolation_points) self.precomputed_values[name][i, :] = result # Report if verbose: log.critical(self.statistics()) else: # Store quantitites as is for name in quantity_names: self.precomputed_values[name] = quantities[name]
def __init__(self, time, quantities, quantity_names=None, vertex_coordinates=None, triangles=None, interpolation_points=None, time_thinning=1, verbose=False, gauge_neighbour_id=None, output_centroids=False): """Initialise object and build spatial interpolation if required Time_thinning_number controls how many timesteps to use. Only timesteps with index%time_thinning_number == 0 will used, or in other words a value of 3, say, will cause the algorithm to use every third time step. """ from anuga.config import time_format if verbose is True: log.critical('Interpolation_function: input checks') # Check temporal info time = ensure_numeric(time) if not num.alltrue(time[1:] - time[:-1] >= 0): # This message is time consuming to form due to the conversion of msg = 'Time must be a monotonuosly increasing sequence %s' % time raise Exception(msg) # Check if quantities is a single array only if not isinstance(quantities, dict): quantities = ensure_numeric(quantities) quantity_names = ['Attribute'] # Make it a dictionary quantities = {quantity_names[0]: quantities} # Use keys if no names are specified if quantity_names is None: quantity_names = quantities.keys() # Check spatial info if vertex_coordinates is None: self.spatial = False else: # FIXME (Ole): Try ensure_numeric here - # this function knows nothing about georefering. vertex_coordinates = ensure_absolute(vertex_coordinates) if triangles is not None: triangles = ensure_numeric(triangles) self.spatial = True if verbose is True: log.critical('Interpolation_function: thinning by %d' % time_thinning) # Thin timesteps if needed # Note array() is used to make the thinned arrays contiguous in memory self.time = num.array(time[::time_thinning]) for name in quantity_names: if len(quantities[name].shape) == 2: quantities[name] = num.array(quantities[name][::time_thinning,:]) if verbose is True: log.critical('Interpolation_function: precomputing') # Save for use with statistics self.quantities_range = {} for name in quantity_names: q = quantities[name][:].flatten() self.quantities_range[name] = [min(q), max(q)] self.quantity_names = quantity_names self.vertex_coordinates = vertex_coordinates self.interpolation_points = interpolation_points self.index = 0 # Initial time index self.precomputed_values = {} self.centroids = [] # Precomputed spatial interpolation if requested if interpolation_points is not None: #no longer true. sts files have spatial = True but #if self.spatial is False: # raise Exception('Triangles and vertex_coordinates must be specified') # try: self.interpolation_points = \ interpolation_points = ensure_numeric(interpolation_points) except: msg = 'Interpolation points must be an N x 2 numeric array ' \ 'or a list of points\n' msg += 'Got: %s.' %(str(self.interpolation_points)[:60] + '...') raise Exception(msg) # Ensure 'mesh_boundary_polygon' is defined mesh_boundary_polygon = None if triangles is not None and vertex_coordinates is not None: # Check that all interpolation points fall within # mesh boundary as defined by triangles and vertex_coordinates. from anuga.abstract_2d_finite_volumes.neighbour_mesh import Mesh from anuga.geometry.polygon import outside_polygon # Create temporary mesh object from mesh info passed # into this function. mesh = Mesh(vertex_coordinates, triangles) mesh_boundary_polygon = mesh.get_boundary_polygon() indices = outside_polygon(interpolation_points, mesh_boundary_polygon) # Record result #self.mesh_boundary_polygon = mesh_boundary_polygon self.indices_outside_mesh = indices # Report if len(indices) > 0: msg = 'Interpolation points in Interpolation function fall ' msg += 'outside specified mesh. Offending points:\n' out_interp_pts = [] for i in indices: msg += '%d: %s\n' % (i, interpolation_points[i]) out_interp_pts.append( ensure_numeric(interpolation_points[i])) if verbose is True: import sys from anuga.geometry.polygon import plot_polygons title = ('Interpolation points fall ' 'outside specified mesh') plot_polygons([mesh_boundary_polygon, interpolation_points, out_interp_pts], ['line', 'point', 'outside'], figname='points_boundary_out', label=title) # Joaquim Luis suggested this as an Exception, so # that the user can now what the problem is rather than # looking for NaN's. However, NANs are handy as they can # be ignored leaving good points for continued processing. if verbose: log.critical(msg) #raise Exception(msg) elif triangles is None and vertex_coordinates is not None: #jj #Dealing with sts file pass else: raise Exception('Sww file function requires both triangles and ' 'vertex_coordinates. sts file file function ' 'requires the latter.') # Plot boundary and interpolation points, # but only if if 'mesh_boundary_polygon' has data. if verbose is True and mesh_boundary_polygon is not None: import sys if sys.platform == 'win32': from anuga.geometry.polygon import plot_polygons title = ('Interpolation function: ' 'Polygon and interpolation points') plot_polygons([mesh_boundary_polygon, interpolation_points], ['line', 'point'], figname='points_boundary', label=title) m = len(self.interpolation_points) p = len(self.time) for name in quantity_names: self.precomputed_values[name] = num.zeros((p, m), num.float) if verbose is True: log.critical('Build interpolator') # Build interpolator if triangles is not None and vertex_coordinates is not None: if verbose: msg = 'Building interpolation matrix from source mesh ' msg += '(%d vertices, %d triangles)' \ % (vertex_coordinates.shape[0], triangles.shape[0]) log.critical(msg) # This one is no longer needed for STS files interpol = Interpolate(vertex_coordinates, triangles, verbose=verbose) elif triangles is None and vertex_coordinates is not None: if verbose: log.critical('Interpolation from STS file') if verbose: log.critical('Interpolating (%d interpolation points, %d timesteps).' % (self.interpolation_points.shape[0], self.time.shape[0])) if time_thinning > 1: log.critical('Timesteps were thinned by a factor of %d' % time_thinning) else: log.critical() for i, t in enumerate(self.time): # Interpolate quantities at this timestep #if verbose and i%((p+10)/10) == 0: if verbose: log.critical(' time step %d of %d' % (i, p)) for name in quantity_names: if len(quantities[name].shape) == 2: Q = quantities[name][i,:] # Quantities at timestep i else: Q = quantities[name][:] # No time dependency #if verbose and i%((p+10)/10) == 0: if verbose: log.critical(' quantity %s, size=%d' % (name, len(Q))) # Interpolate if triangles is not None and vertex_coordinates is not None: result = interpol.interpolate(Q, point_coordinates=\ self.interpolation_points, verbose=False, output_centroids=output_centroids) self.centroids = interpol.centroids elif triangles is None and vertex_coordinates is not None: result = interpolate_polyline(Q, vertex_coordinates, gauge_neighbour_id, interpolation_points=\ self.interpolation_points) #assert len(result), len(interpolation_points) self.precomputed_values[name][i, :] = result # Report if verbose: log.critical(self.statistics()) else: # Store quantitites as is for name in quantity_names: self.precomputed_values[name] = quantities[name]
def __init__(self, vertex_coordinates=None, triangles=None, mesh=None, mesh_origin=None, verbose=False): """ Build interpolation matrix mapping from function values at vertices to function values at data points Pass in a mesh instance or vertex_coordinates and triangles and optionally mesh_origin Inputs: vertex_coordinates: List of coordinate pairs [xi, eta] of points constituting a mesh (or an m x 2 numeric array or a geospatial object) Points may appear multiple times (e.g. if vertices have discontinuities) triangles: List of 3-tuples (or a numeric array) of integers representing indices of all vertices in the mesh. mesh: A mesh instance describing the mesh. mesh_origin: A geo_reference object or 3-tuples consisting of UTM zone, easting and northing. If specified vertex coordinates are assumed to be relative to their respective origins. Note: Don't supply a vertex coords as a geospatial object and a mesh origin, since geospatial has its own mesh origin. """ # NOTE PADARN: The Fit_Interpolate class now uses a the c based # quad tree to store triangles, rather than the python based tree. # The tree is still stored at self.root. However, the subtrees of # the new quad tree can not be directly accessed by python as # was previously possible. # Most of the previous functionality has been preserved. global build_quadtree_time if mesh is None: if vertex_coordinates is not None and triangles is not None: # Fixme (DSG) Throw errors if triangles or vertex_coordinates # are None # Convert input to numeric arrays triangles = ensure_numeric(triangles, num.int) vertex_coordinates = ensure_absolute(vertex_coordinates, geo_reference=mesh_origin) if verbose: log.critical('FitInterpolate: Building mesh') self.mesh = Mesh(vertex_coordinates, triangles) #self.mesh.check_integrity() # Time consuming else: self.mesh = None else: self.mesh = mesh if self.mesh is not None: if verbose: log.critical('FitInterpolate: Building quad tree') #This stores indices of vertices t0 = time.time() self.root = MeshQuadtree(self.mesh, verbose=verbose) build_quadtree_time = time.time() - t0