Changeset 976


Ignore:
Timestamp:
Mar 1, 2005, 12:16:51 PM (20 years ago)
Author:
ole
Message:

Made least squares work with different coordinate systems for data p;oints and mesh

Location:
inundation/ga/storm_surge/pyvolution
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • inundation/ga/storm_surge/pyvolution/general_mesh.py

    r849 r976  
    4848    """
    4949
    50     def __init__(self, coordinates, triangles):
     50    def __init__(self, coordinates, triangles, origin = None):
    5151        """
    5252        Build triangles from x,y coordinates (sequence of 2-tuples or
    5353        Mx2 Numeric array of floats) and triangles (sequence of 3-tuples
    5454        or Nx3 Numeric array of non-negative integers).
     55
     56        origin is a 3-tuple consisting of UTM zone, easting and northing.
     57        If specified coordinates are assumed to be relative to this origin.
    5558        """
    5659
     
    5962        self.triangles = array(triangles).astype(Int)
    6063        self.coordinates = array(coordinates)
     64
     65        self.origin = origin
    6166
    6267        #Input checks
  • inundation/ga/storm_surge/pyvolution/least_squares.py

    r968 r976  
    5959def fit_to_mesh_file(mesh_file, point_file, mesh_output_file,
    6060                     alpha=DEFAULT_ALPHA, verbose= False,
    61                      expand_search = False):
     61                     expand_search = False,
     62                     origin = None,
     63                     mesh_origin=None):
    6264    """
    6365    Given a mesh file (tsh) and a point attribute file (xya), fit
    6466    point attributes to the mesh and write a mesh file with the
    6567    results.
     68   
     69    If origin is not None it is assumed to be
     70    a 5-tuple with geo referenced
     71    UTM coordinates (zone, easting, northing, false_easting, false_northing)
     72   
     73    mesh_origin is the same but refers to the input tsh file.
     74    FIXME: When that format contains it own origin, this parameter can go.
    6675    """
     76   
    6777    from load_mesh.loadASCII import mesh_file_to_mesh_dictionary, \
    6878                 load_points_file, export_triangulation_file, \
    6979                 concatinate_attributelist
     80   
    7081    # load in the .tsh file
    7182    mesh_dict = mesh_file_to_mesh_dictionary(mesh_file)
     
    7889   
    7990    # load in the .xya file
     91    #FIXME (Ole): Maybe data origin should be extracted here
    8092    try:
    8193        point_dict = load_points_file(point_file,delimiter = ',')
     
    8496    point_coordinates = point_dict['pointlist']
    8597    title_list,point_attributes = concatinate_attributelist(point_dict['attributelist']) 
    86     if verbose:print "points file loaded"
     98    if verbose: print "points file loaded"
     99
     100
     101   
    87102    if verbose:print "fitting to mesh"
    88103    f = fit_to_mesh(vertex_coordinates,
     
    216231                 verbose = False,
    217232                 expand_search = True,
    218                  max_points_per_cell = 30):
     233                 max_points_per_cell = 30,
     234                 mesh_origin = None,
     235                 data_origin = None):
    219236
    220237       
     
    236253
    237254          alpha: Smoothing parameter
     255
     256          data_origin and mesh_origin are 3-tuples consisting of
     257          UTM zone, easting and northing. If specified
     258          point coordinates and vertex coordinates are assumed to be
     259          relative to their respective origins.
    238260         
    239261        """
    240262
    241263        #Convert input to Numeric arrays
     264        triangles = array(triangles).astype(Int)
    242265        vertex_coordinates = array(vertex_coordinates).astype(Float)
    243         triangles = array(triangles).astype(Int)               
    244        
     266
    245267        #Build underlying mesh
    246268        if verbose: print 'Building mesh'
    247         self.mesh = General_mesh(vertex_coordinates, triangles)
     269        self.mesh = General_mesh(vertex_coordinates, triangles,
     270                                 origin = mesh_origin)
     271        self.data_origin = data_origin
    248272
    249273        #Smoothing parameter
     
    254278                                        verbose = verbose,
    255279                                        expand_search = expand_search,
    256                                    max_points_per_cell = max_points_per_cell)
    257        
    258 
    259     def set_point_coordinates(self, point_coordinates):
     280                                        max_points_per_cell =\
     281                                        max_points_per_cell,
     282                                        data_origin = data_origin)
     283       
     284
     285    def set_point_coordinates(self, point_coordinates,
     286                              data_origin = None):
    260287        """
    261288        A public interface to setting the point co-ordinates.
    262289        """
    263         self.build_coefficient_matrix_B(point_coordinates)
     290        self.build_coefficient_matrix_B(point_coordinates, data_origin)
    264291       
    265292    def build_coefficient_matrix_B(self, point_coordinates=None,
    266293                                   verbose = False, expand_search = True,
    267                                    max_points_per_cell=30):
     294                                   max_points_per_cell=30,
     295                                   data_origin = None):
    268296        """Build final coefficient matrix"""
    269297       
     
    273301            self.build_smoothing_matrix_D()
    274302       
    275         if point_coordinates:
     303        if point_coordinates is not None:
     304           
    276305            if verbose: print 'Building interpolation matrix'         
    277306            self.build_interpolation_matrix_A(point_coordinates,
    278307                                              verbose = verbose,
    279308                                              expand_search = expand_search,
    280                                    max_points_per_cell = max_points_per_cell)
     309                                              max_points_per_cell =\
     310                                              max_points_per_cell,
     311                                              data_origin = data_origin)
    281312
    282313            if self.alpha <> 0:
     
    290321    def build_interpolation_matrix_A(self, point_coordinates,
    291322                                     verbose = False, expand_search = True,
    292                                      max_points_per_cell=30):
     323                                     max_points_per_cell=30,
     324                                     data_origin = None):
    293325        """Build n x m interpolation matrix, where
    294326        n is the number of data points and
     
    296328
    297329        This algorithm uses a quad tree data structure for fast binning of data points
     330        origin is a 3-tuple consisting of UTM zone, easting and northing.
     331        If specified coordinates are assumed to be relative to this origin.
     332
     333        This one will override any data_origin that may be specified in
     334        interpolation instance
     335
    298336        """
    299337
    300338        from quad import build_quadtree
    301        
    302         #Convert input to Numeric arrays
     339
     340        if data_origin is None:
     341            data_origin = self.data_origin #Use the one from
     342                                           #interpolation instance
     343       
     344        #Convert input to Numeric arrays just in case.
    303345        point_coordinates = array(point_coordinates).astype(Float)
     346
     347
     348        #Shift data points to same origin as mesh (if specified)
     349        mesh_origin = self.mesh.origin
     350        if point_coordinates is not None:
     351            if data_origin is not None:
     352                if mesh_origin is not None:
     353
     354                    #Transformation:
     355                    #
     356                    #Let x_0 be the reference point of the point coordinates
     357                    #and xi_0 the reference point of the mesh.
     358                    #
     359                    #A point coordinate (x + x_0) is then made relative
     360                    #to xi_0 by
     361                    #
     362                    # x_new = x + x_0 - xi_0
     363                    #
     364                    #and similarly for eta
     365                   
     366                    x_offset = data_origin[1] - mesh_origin[1]
     367                    y_offset = data_origin[2] - mesh_origin[2]
     368                else: #Shift back to a zero origin
     369                    x_offset = data_origin[1]
     370                    y_offset = data_origin[2]               
     371                   
     372                point_coordinates[:,0] += x_offset
     373                point_coordinates[:,1] += y_offset           
     374            else:
     375                if mesh_origin is not None:
     376                    #Use mesh origin for data points
     377                    point_coordinates[:,0] -= mesh_origin[1]
     378                    point_coordinates[:,1] -= mesh_origin[2]
     379
     380
     381
     382
    304383       
    305384        #Build n x m interpolation matrix       
     
    307386        n = point_coordinates.shape[0]     #Nbr of data points
    308387
     388        if verbose: print 'Number of datapoints: %d' %n
     389        if verbose: print 'Number of basis functions: %d' %m
    309390       
    310391        #FIXME (Ole): We should use CSR here since mat-mat mult is now OK.
     
    322403            #For each data_coordinate point
    323404
    324             #if verbose: print 'Doing %d of %d' %(i, n)
     405            if verbose and i%((n+10)/10)==0: print 'Doing %d of %d' %(i, n)
    325406
    326407            x = point_coordinates[i]
     
    656737            #Build n x m interpolation matrix       
    657738            m = self.mesh.coordinates.shape[0] #Number of vertices
    658             n = z.shape[1]               #Number of data points         
     739            n = z.shape[1]                     #Number of data points         
    659740
    660741            f = zeros((m,n), Float) #Resulting columns
  • inundation/ga/storm_surge/pyvolution/test_least_squares.py

    r969 r976  
    878878
    879879
     880    def test_fit_and_interpolation_with_different_origins(self):
     881        """Fit a surface to one set of points. Then interpolate that surface
     882        using another set of points.
     883        This test tests situtaion where points and mesh belong to a different
     884        coordinate system as defined by origin.
     885        """
     886        from mesh import Mesh
     887
     888        #Setup mesh used to represent fitted function
     889        a = [0.0, 0.0]
     890        b = [0.0, 2.0]
     891        c = [2.0, 0.0]
     892        d = [0.0, 4.0]
     893        e = [2.0, 2.0]
     894        f = [4.0, 0.0]
     895
     896        points = [a, b, c, d, e, f]
     897        #bac, bce, ecf, dbe, daf, dae
     898        triangles = [[1,0,2], [1,2,4], [4,2,5], [3,1,4]]
     899
     900        #Datapoints to fit from
     901        data_points1 = [[ 0.66666667, 0.66666667],
     902                        [ 1.33333333, 1.33333333],
     903                        [ 2.66666667, 0.66666667],
     904                        [ 0.66666667, 2.66666667],
     905                        [ 0.0, 1.0],
     906                        [ 0.0, 3.0],
     907                        [ 1.0, 0.0],
     908                        [ 1.0, 1.0],
     909                        [ 1.0, 2.0],
     910                        [ 1.0, 3.0],                                         
     911                        [ 2.0, 1.0],
     912                        [ 3.0, 0.0],
     913                        [ 3.0, 1.0]]
     914
     915
     916        #First check that things are OK when using same origin
     917        mesh_origin = (56, 290000, 618000) #zone, easting, northing
     918        data_origin = (56, 290000, 618000) #zone, easting, northing
     919
     920
     921        #Fit surface to mesh
     922        interp = Interpolation(points, triangles, data_points1,
     923                               alpha=0.0,
     924                               data_origin = data_origin,
     925                               mesh_origin = mesh_origin)
     926       
     927        z = linear_function(data_points1) #Example z-values
     928        f = interp.fit(z)                 #Fitted values at vertices
     929
     930
     931        #New datapoints where interpolated values are sought
     932        data_points2 = [[ 0.0, 0.0],
     933                        [ 0.5, 0.5],
     934                        [ 0.7, 0.7],
     935                        [ 1.0, 0.5],
     936                        [ 2.0, 0.4],
     937                        [ 2.8, 1.2]]                                         
     938       
     939
     940        #Build new A matrix based on new points
     941        interp.build_interpolation_matrix_A(data_points2)
     942
     943        #Interpolate using fitted surface
     944        z1 = interp.interpolate(f)
     945
     946        #Desired result
     947        answer = linear_function(data_points2)
     948        assert allclose(z1, answer)
     949
     950
     951        ##############################################
     952
     953        #Then check situtaion where points are relative to a different
     954        #origin (same zone, though, until we figure that out (FIXME))
     955       
     956        mesh_origin = (56, 290000, 618000) #zone, easting, northing
     957        data_origin = (56, 10000, 10000) #zone, easting, northing
     958
     959        #Shift datapoints according to new origin
     960
     961        for k in range(len(data_points1)):
     962            data_points1[k][0] += mesh_origin[1] - data_origin[1]
     963            data_points1[k][1] += mesh_origin[2] - data_origin[2]
     964
     965        for k in range(len(data_points2)):
     966            data_points2[k][0] += mesh_origin[1] - data_origin[1]
     967            data_points2[k][1] += mesh_origin[2] - data_origin[2]           
     968
     969
     970       
     971        #Fit surface to mesh
     972        interp = Interpolation(points, triangles, data_points1,
     973                               alpha=0.0,
     974                               data_origin = data_origin,
     975                               mesh_origin = mesh_origin)
     976       
     977        f1 = interp.fit(z) #Fitted values at vertices (using same z as before)
     978
     979        assert allclose(f,f1), 'Fit should have been unaltered'
     980
     981
     982        #Build new A matrix based on new points
     983        interp.build_interpolation_matrix_A(data_points2)
     984
     985        #Interpolate using fitted surface
     986        z1 = interp.interpolate(f)
     987        assert allclose(z1, answer)
     988
     989
    880990
    881991    def test_fit_to_mesh_file(self):
Note: See TracChangeset for help on using the changeset viewer.