Changeset 997


Ignore:
Timestamp:
Mar 3, 2005, 6:40:01 PM (20 years ago)
Author:
ole
Message:

Implemented precropping facility in least squares
Also optimised inside_polygon

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

Legend:

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

    r984 r997  
    3131
    3232from general_mesh import General_mesh
    33 from Numeric import zeros, array, Float, Int, dot, transpose, concatenate
     33from mesh import Mesh
     34
     35from Numeric import zeros, take, array, Float, Int, dot, transpose, concatenate
    3436from sparse import Sparse, Sparse_CSR
    3537from cg_solve import conjugate_gradient, VectorShapeError
     
    6163                     expand_search = False,
    6264                     data_origin = None,
    63                      mesh_origin = None):
     65                     mesh_origin = None,
     66                     precrop = False):
    6467    """
    6568    Given a mesh file (tsh) and a point attribute file (xya), fit
     
    111114                    expand_search = expand_search,
    112115                    data_origin = data_origin,
    113                     mesh_origin = mesh_origin)
    114     if verbose:print "finished fitting to mesh"
     116                    mesh_origin = mesh_origin,
     117                    precrop = precrop)
     118    if verbose: print "finished fitting to mesh"
    115119   
    116120    # convert array to list of lists
     
    141145                expand_search = False,
    142146                data_origin = None,
    143                 mesh_origin = None):
     147                mesh_origin = None,
     148                precrop = False):
    144149    """
    145150    Fit a smooth surface to a triangulation,
     
    175180                           expand_search = expand_search,
    176181                           data_origin = data_origin,
    177                            mesh_origin = mesh_origin)
    178                            # expand_search = False)
     182                           mesh_origin = mesh_origin,
     183                           precrop = precrop)
    179184   
    180185    vertex_attributes = interp.fit_points(point_attributes, verbose = verbose)
     
    248253                 max_points_per_cell = 30,
    249254                 mesh_origin = None,
    250                  data_origin = None):
     255                 data_origin = None,
     256                 precrop = False):
    251257
    252258       
     
    282288        #Build underlying mesh
    283289        if verbose: print 'Building mesh'
    284         self.mesh = General_mesh(vertex_coordinates, triangles,
    285                                  origin = mesh_origin)
     290        #self.mesh = General_mesh(vertex_coordinates, triangles,
     291        #FIXME: Trying the normal mesh while testing precrop
     292        self.mesh = Mesh(vertex_coordinates, triangles,
     293                         origin = mesh_origin)
    286294        self.data_origin = data_origin
     295
     296        self.point_indices = None
    287297
    288298        #Smoothing parameter
     
    295305                                        max_points_per_cell =\
    296306                                        max_points_per_cell,
    297                                         data_origin = data_origin)
     307                                        data_origin = data_origin,
     308                                        precrop = precrop)
    298309       
    299310
     
    308319                                   verbose = False, expand_search = True,
    309320                                   max_points_per_cell=30,
    310                                    data_origin = None):
     321                                   data_origin = None,
     322                                   precrop = False):
    311323        """Build final coefficient matrix"""
    312324       
     
    324336                                              max_points_per_cell =\
    325337                                              max_points_per_cell,
    326                                               data_origin = data_origin)
     338                                              data_origin = data_origin,
     339                                              precrop = precrop)
    327340
    328341            if self.alpha <> 0:
     
    337350                                     verbose = False, expand_search = True,
    338351                                     max_points_per_cell=30,
    339                                      data_origin = None):
     352                                     data_origin = None,
     353                                     precrop = False):
    340354        """Build n x m interpolation matrix, where
    341355        n is the number of data points and
     
    396410
    397411        #Remove points falling outside mesh boundary
    398         #from util import inside_polygon
    399         #P = self.mesh.get_boundary_polygon()
    400         #FIXME: TODO
     412        #This reduced one example from 1356 seconds to 825 seconds
     413        #And more could be had by writing util.inside_polygon in C
     414        if precrop is True:
     415            from Numeric import take
     416            from util import inside_polygon
     417
     418            if verbose: print 'Getting boundary polygon'
     419            P = self.mesh.get_boundary_polygon()
     420
     421            if verbose: print 'Getting indices inside mesh boundary'           
     422            indices = inside_polygon(point_coordinates, P, verbose = verbose)
     423
     424            if verbose:
     425                if len(indices) != point_coordinates.shape[0]:
     426                    print '%d points outside mesh have been cropped.'\
     427                          %(point_coordinates.shape[0] - len(indices))
     428            point_coordinates = take(point_coordinates, indices)
     429            self.point_indices = indices
    401430
    402431
     
    717746        z = array(z).astype(Float)
    718747
    719 
    720748        if len(z.shape) > 1 :
    721749            raise VectorShapeError, 'Can only deal with 1d data vector'
     750
     751        if self.point_indices is not None:
     752            #Remove values for any points that were outside mesh
     753            z = take(z, self.point_indices)
    722754       
    723755        #Compute right hand side based on data
  • inundation/ga/storm_surge/pyvolution/mesh.py

    r984 r997  
    5858   
    5959    def __init__(self, coordinates, triangles, boundary = None,
    60                  tagged_elements = None):
     60                 tagged_elements = None, origin = None):
    6161        """
    6262        Build triangles from x,y coordinates (sequence of 2-tuples or
     
    6767        from Numeric import array, zeros, Int, Float, maximum, sqrt, sum
    6868
    69         General_mesh.__init__(self, coordinates, triangles)
     69        General_mesh.__init__(self, coordinates, triangles, origin)
    7070
    7171        N = self.number_of_elements
     
    350350        """Return bounding polygon as a list of points
    351351        """
    352         from Numeric import allclose
     352        from Numeric import allclose, sqrt, array, minimum, maximum
     353   
    353354       
    354355
     
    356357        segments = {}
    357358
    358         pmin = (min(self.coordinates[:,0]), min(self.coordinates[:,1]))
     359        #pmin = (min(self.coordinates[:,0]), min(self.coordinates[:,1]))
     360        #pmax = (max(self.coordinates[:,0]), max(self.coordinates[:,1]))
     361
     362        #FIXME:Can this be written more compactly, e.g.
     363        #using minimum and maximium?
     364        pmin = array( [min(self.coordinates[:,0]),
     365                       min(self.coordinates[:,1]) ] )
     366
     367        pmax = array( [max(self.coordinates[:,0]),
     368                       max(self.coordinates[:,1]) ] )       
     369       
     370        mindist = sqrt(sum( (pmax-pmin)**2 ))
    359371        for i, edge_id in self.boundary.keys():
    360372            #Find vertex ids for boundary segment
     
    366378            B = tuple(self.get_vertex_coordinate(i, b))
    367379
     380            #Take the point closest to pmin as starting point
     381            #Note: Could be arbitrary, but nice to have
     382            #a unique way of selecting
     383            dist_A = sqrt(sum( (A-pmin)**2 ))
     384            dist_B = sqrt(sum( (B-pmin)**2 ))                         
     385
    368386            #Find minimal point
    369             if allclose(A, pmin): p0 = A
    370             if allclose(B, pmin): p0 = B               
     387            if dist_A < mindist:
     388                mindist = dist_A
     389                p0 = A
     390            if dist_B < mindist:
     391                mindist = dist_B
     392                p0 = B
     393
     394
     395            if p0 is None:
     396                raise 'Weird'
     397                p0 = A #We need a starting point (FIXME)
     398
     399                print 'A', A
     400                print 'B', B
     401                print 'pmin', pmin
     402                print
    371403
    372404            segments[A] = B
  • inundation/ga/storm_surge/pyvolution/test_least_squares.py

    r994 r997  
    301301        assert allclose(sum(interp.get_A(), axis=1), 1.0)
    302302       
    303 
    304     # this causes a memory error in scipy.sparce       
     303    def test_arbitrary_datapoints_some_outside(self):
     304        """Try arbitrary datapoints one outside the triangle.
     305        That one should be ignored
     306        """
     307
     308        from Numeric import sum
     309       
     310        a = [0.0, 0.0]
     311        b = [0.0, 2.0]
     312        c = [2.0,0.0]
     313        points = [a, b, c]
     314        vertices = [ [1,0,2] ]   #bac
     315
     316        data = [ [0.2, 1.5], [0.123, 1.768], [1.43, 0.44], [5.0, 7.0]]
     317
     318
     319        interp = Interpolation(points, vertices, data, precrop = True)
     320        assert allclose(sum(interp.get_A(), axis=1), 1.0)
     321
     322        interp = Interpolation(points, vertices, data, precrop = False)
     323        assert allclose(sum(interp.get_A(), axis=1), [1,1,1,0])
     324       
     325       
     326
     327    # this causes a memory error in scipy.sparse       
    305328    def test_more_triangles(self):
    306329       
     
    844867                        [ 1.0, 0.0],
    845868                        [ 1.0, 1.0],
     869                        [ 15, -17],   #Outside mesh
    846870                        [ 1.0, 2.0],
    847871                        [ 1.0, 3.0],                                         
     
    851875
    852876        #Fit surface to mesh
    853         interp = Interpolation(points, triangles, data_points1, alpha=0.0)
     877        interp = Interpolation(points, triangles, data_points1, alpha=0.0,
     878                               precrop = True)
    854879        z = linear_function(data_points1) #Example z-values
    855880        f = interp.fit(z)                 #Fitted values at vertices
     
    861886                        [ 0.5, 0.5],
    862887                        [ 0.7, 0.7],
     888                        [-13, 65],  #Outside
    863889                        [ 1.0, 0.5],
    864890                        [ 2.0, 0.4],
     
    866892       
    867893
    868         #Build new A matrix based on new points
    869         interp.build_interpolation_matrix_A(data_points2)
     894
     895        #Build new A matrix based on new points (without precrop)
     896        interp.build_interpolation_matrix_A(data_points2, precrop = False)
    870897
    871898        #Interpolate using fitted surface
    872899        z1 = interp.interpolate(f)
     900
     901        #import Numeric
     902        #data_points2 = Numeric.take(data_points2, interp.point_indices)
     903
     904        #Desired result (OK for points inside)
     905
     906        answer = linear_function(data_points2)
     907        import Numeric
     908        z1 = Numeric.take(z1, [0,1,2,4,5,6])
     909        answer = Numeric.take(answer, [0,1,2,4,5,6])               
     910        assert allclose(z1, answer)
     911
     912        #Build new A matrix based on new points (with precrop)
     913        interp.build_interpolation_matrix_A(data_points2, precrop = True)
     914
     915        #Interpolate using fitted surface
     916        z1 = interp.interpolate(f)
     917
     918        import Numeric
     919        data_points2 = Numeric.take(data_points2, interp.point_indices)
    873920
    874921        #Desired result
     
    11121159#-------------------------------------------------------------
    11131160if __name__ == "__main__":
    1114     #suite = unittest.makeSuite(TestCase,'test')
    1115 
    11161161    suite = unittest.makeSuite(TestCase,'test')
     1162
    11171163    #suite = unittest.makeSuite(TestCase,'test_arbitrary_datapoints')
    11181164    runner = unittest.TextTestRunner(verbosity=1)
  • inundation/ga/storm_surge/pyvolution/util.py

    r994 r997  
    901901#FIXME: ALl these should be put into new module polygon.py
    902902
    903 def inside_polygon(point, polygon, closed = True):
     903def inside_polygon(point, polygon, closed = True, verbose = False):
    904904    """Determine whether points are inside or outside a polygon
    905905   
     
    969969
    970970    N = polygon.shape[0] #Number of vertices in polygon
    971 
     971    M = points.shape[0]  #Number of points
     972   
    972973    px = polygon[:,0]
    973974    py = polygon[:,1]   
    974975
    975     #Begin algorithm
     976    #Used for an optimisation when points are far away from polgon
     977    minpx = min(px); maxpx = max(px)
     978    minpy = min(py); maxpy = max(py)   
     979
     980
     981    #Begin main loop (FIXME: It'd be crunchy to have this written in C:-)
    976982    indices = []
    977     for k in range(points.shape[0]):
     983    for k in range(M):
     984
     985        if verbose:
     986            if k %((M+10)/10)==0: print 'Doing %d of %d' %(k, M)
     987       
    978988        #for each point   
    979989        x = points[k, 0]
     
    981991
    982992        inside = False
     993
     994        #Optimisation
     995        if x > maxpx or x < minpx: continue
     996        if y > maxpy or y < minpy: continue       
     997
     998        #Check polygon
    983999        for i in range(N):
    9841000            j = (i+1)%N
Note: See TracChangeset for help on using the changeset viewer.