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
NNInfo = index_qFun.query(gridXY_array, k=k_nearest_neighbours) # Weights for interpolation nn_wts = 1./(NNInfo[0]+1.0e-100) nn_inds = NNInfo[1] def myInterpFun(quantity): denom = 0. num = 0. for i in range(k_nearest_neighbours): denom += nn_wts[:,i] num += quantity[nn_inds[:,i]]*nn_wts[:,i] return (num/denom) if(bounding_polygon is not None): # Find points to exclude (i.e. outside the bounding polygon) from anuga.geometry.polygon import outside_polygon cut_points = outside_polygon(gridXY_array, bounding_polygon) # Loop over all output quantities and produce the output for myTSindex, myTSi in enumerate(myTimeStep): if(verbose): print 'Reduction = ', myTSi for output_quantity in output_quantities: if (verbose): print output_quantity if(myTSi is not 'max'): myTS = myTSi else: # We have already extracted the max, and e.g. # p2.stage is an array of dimension (1, number_of_pointS). myTS = 0
# Remove loners from vertex_points, volumes here vertex_points, volumes = remove_lone_verts(vertex_points, volumes) # export_mesh_file('monkey.tsh',{'vertices':vertex_points, 'triangles':volumes}) interp = Interpolate(vertex_points, volumes, verbose=verbose) log.debug('Interpolating') # Interpolate using quantity values grid_values = interp.interpolate(result, grid_points).flatten() log.debug('Interpolated values are in [%f, %f]' % (num.min(grid_values), num.max(grid_values))) # Assign NODATA_value to all points outside bounding polygon (from interpolation mesh) P = interp.mesh.get_boundary_polygon() outside_indices = outside_polygon(grid_points, P, closed=True) for i in outside_indices: grid_values[i] = NODATA_value if out_ext == '.ers': # setup ERS header information grid_values = num.reshape(grid_values, (nrows, ncols)) header = {} header['datum'] = '"%s"' % datum # FIXME The use of hardwired UTM and zone number needs to be made optional # FIXME Also need an automatic test for coordinate type (i.e. EN or LL) header['projection'] = '"UTM-%s"' % str(zone) header['coordinatetype'] = 'EN' if header['coordinatetype'] == 'LL': header['longitude'] = str(newxllcorner)
NNInfo = index_qFun.query(gridXY_array, k=k_nearest_neighbours) # Weights for interpolation nn_wts = 1./(NNInfo[0]+1.0e-100) nn_inds = NNInfo[1] def myInterpFun(quantity): denom = 0. num = 0. for i in range(k_nearest_neighbours): denom += nn_wts[:,i] num += quantity[nn_inds[:,i]]*nn_wts[:,i] return (num/denom) if(bounding_polygon is not None): # Find points to exclude (i.e. outside the bounding polygon) from anuga.geometry.polygon import outside_polygon cut_points = outside_polygon(gridXY_array, bounding_polygon) #print cut_points.shape #cut_points=(nxutils.points_inside_poly(gridXY_array, bounding_polygon)==False).nonzero()[0] # Loop over all output quantities and produce the output for myTSindex, myTSi in enumerate(myTimeStep): if(verbose): print 'Reduction = ', myTSi for output_quantity in output_quantities: if (verbose): print output_quantity if(myTSi is not 'max'): myTS=myTSi else: # We have already extracted the max, and e.g.
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]
assert len(vertex_points.shape) == 2 # Interpolate from anuga.fit_interpolate.interpolate import Interpolate interp = Interpolate(vertex_points, volumes, verbose=verbose) # Interpolate using quantity values if verbose: log.critical('Interpolating') interpolated_values = interp.interpolate(q, data_points).flatten() if verbose: log.critical( 'Interpolated values are in [%f, %f]' % (num.min(interpolated_values), num.max(interpolated_values))) # Assign NODATA_value to all points outside bounding polygon # (from interpolation mesh) P = interp.mesh.get_boundary_polygon() outside_indices = outside_polygon(data_points, P, closed=True) for i in outside_indices: interpolated_values[i] = NODATA_value # Store results G = Geospatial_data(data_points=data_points, attributes=interpolated_values) G.export_points_file(name_out, absolute=True) fid.close()
assert len(vertex_points.shape) == 2 # Interpolate from anuga.fit_interpolate.interpolate import Interpolate interp = Interpolate(vertex_points, volumes, verbose=verbose) # Interpolate using quantity values if verbose: log.critical('Interpolating') interpolated_values = interp.interpolate(q, data_points).flatten() if verbose: log.critical('Interpolated values are in [%f, %f]' % (num.min(interpolated_values), num.max(interpolated_values))) # Assign NODATA_value to all points outside bounding polygon # (from interpolation mesh) P = interp.mesh.get_boundary_polygon() outside_indices = outside_polygon(data_points, P, closed=True) for i in outside_indices: interpolated_values[i] = NODATA_value # Store results G = Geospatial_data(data_points=data_points, attributes=interpolated_values) G.export_points_file(name_out, absolute = True) fid.close()
def sww2pts(name_in, name_out=None, data_points=None, quantity=None, timestep=None, reduction=None, NODATA_value=-9999, verbose=False, origin=None): """Read SWW file and convert to interpolated values at selected points The parameter 'quantity' must be the name of an existing quantity or an expression involving existing quantities. The default is 'elevation'. if timestep (an index) is given, output quantity at that timestep. if reduction is given use that to reduce quantity over all timesteps. data_points (Nx2 array) give locations of points where quantity is to be computed. """ import sys from anuga.geometry.polygon import inside_polygon, outside_polygon from anuga.abstract_2d_finite_volumes.util import \ apply_expression_to_dictionary from anuga.geospatial_data.geospatial_data import Geospatial_data if quantity is None: quantity = 'elevation' if reduction is None: reduction = max basename_in, in_ext = os.path.splitext(name_in) if name_out != None: basename_out, out_ext = os.path.splitext(name_out) else: basename_out = basename_in + '_%s' % quantity out_ext = '.pts' name_out = basename_out + out_ext if in_ext != '.sww': raise IOError('Input format for %s must be .sww' % name_in) if out_ext != '.pts': raise IOError('Output format for %s must be .pts' % name_out) # Read sww file if verbose: log.critical('Reading from %s' % name_in) from anuga.file.netcdf import NetCDFFile fid = NetCDFFile(name_in) # Get extent and reference x = fid.variables['x'][:] y = fid.variables['y'][:] volumes = fid.variables['volumes'][:] try: # works with netcdf4 number_of_timesteps = len(fid.dimensions['number_of_timesteps']) number_of_points = len(fid.dimensions['number_of_points']) except: #works with scientific.io.netcdf number_of_timesteps = fid.dimensions['number_of_timesteps'] number_of_points = fid.dimensions['number_of_points'] if origin is None: # Get geo_reference # sww files don't have to have a geo_ref try: geo_reference = Geo_reference(NetCDFObject=fid) except AttributeError as e: geo_reference = Geo_reference() # Default georef object xllcorner = geo_reference.get_xllcorner() yllcorner = geo_reference.get_yllcorner() zone = geo_reference.get_zone() else: zone = origin[0] xllcorner = origin[1] yllcorner = origin[2] # FIXME: Refactor using code from file_function.statistics # Something like print swwstats(swwname) if verbose: x = fid.variables['x'][:] y = fid.variables['y'][:] times = fid.variables['time'][:] log.critical('------------------------------------------------') log.critical('Statistics of SWW file:') log.critical(' Name: %s' % swwfile) log.critical(' Reference:') log.critical(' Lower left corner: [%f, %f]' % (xllcorner, yllcorner)) log.critical(' Start time: %f' % fid.starttime[0]) log.critical(' Extent:') log.critical(' x [m] in [%f, %f], len(x) == %d' % (num.min(x), num.max(x), len(x.flat))) log.critical(' y [m] in [%f, %f], len(y) == %d' % (num.min(y), num.max(y), len(y.flat))) log.critical(' t [s] in [%f, %f], len(t) == %d' % (min(times), max(times), len(times))) log.critical(' Quantities [SI units]:') for name in ['stage', 'xmomentum', 'ymomentum', 'elevation']: q = fid.variables[name][:].flat log.critical(' %s in [%f, %f]' % (name, min(q), max(q))) # Get quantity and reduce if applicable if verbose: log.critical('Processing quantity %s' % quantity) # Turn NetCDF objects into numeric arrays quantity_dict = {} for name in list(fid.variables.keys()): quantity_dict[name] = fid.variables[name][:] # Convert quantity expression to quantities found in sww file q = apply_expression_to_dictionary(quantity, quantity_dict) if len(q.shape) == 2: # q has a time component and needs to be reduced along # the temporal dimension if verbose: log.critical('Reducing quantity %s' % quantity) q_reduced = num.zeros(number_of_points, num.float) for k in range(number_of_points): q_reduced[k] = reduction(q[:, k]) q = q_reduced # Post condition: Now q has dimension: number_of_points assert len(q.shape) == 1 assert q.shape[0] == number_of_points if verbose: log.critical('Processed values for %s are in [%f, %f]' % (quantity, min(q), max(q))) # Create grid and update xll/yll corner and x,y vertex_points = num.concatenate((x[:, num.newaxis], y[:, num.newaxis]), axis=1) assert len(vertex_points.shape) == 2 # Interpolate from anuga.fit_interpolate.interpolate import Interpolate interp = Interpolate(vertex_points, volumes, verbose=verbose) # Interpolate using quantity values if verbose: log.critical('Interpolating') interpolated_values = interp.interpolate(q, data_points).flatten() if verbose: log.critical( 'Interpolated values are in [%f, %f]' % (num.min(interpolated_values), num.max(interpolated_values))) # Assign NODATA_value to all points outside bounding polygon # (from interpolation mesh) P = interp.mesh.get_boundary_polygon() outside_indices = outside_polygon(data_points, P, closed=True) for i in outside_indices: interpolated_values[i] = NODATA_value # Store results G = Geospatial_data(data_points=data_points, attributes=interpolated_values) G.export_points_file(name_out, absolute=True) fid.close()