Changeset 820 for inundation/ga


Ignore:
Timestamp:
Feb 1, 2005, 5:06:54 AM (20 years ago)
Author:
ole
Message:

Implemented xya2rectangular and tested it

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

Legend:

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

    r797 r820  
    143143    return vertex_attributes
    144144
     145   
     146   
     147def xya2rectangular(xya_name, M, N, alpha = DEFAULT_ALPHA):
     148    """Fits attributes from xya file to MxN rectangular mesh
     149   
     150    Read xya file and create rectangular mesh of resolution MxN such that
     151    it covers all points specified in xya file.
     152   
     153    FIXME: This may be a temporary function until we decide on
     154    netcdf formats etc
     155    """   
     156   
     157    import util, mesh_factory
     158   
     159    points, attributes = util.read_xya(xya_name)
     160   
     161    #Find extent
     162    max_x = min_x = points[0][0]
     163    max_y = min_y = points[0][1]
     164    for point in points[1:]:
     165        x = point[0]
     166        if x > max_x: max_x = x
     167        if x < min_x: min_x = x           
     168        y = point[1]
     169        if y > max_y: max_y = y
     170        if y < min_y: min_y = y           
     171   
     172    #Create appropriate mesh
     173    vertex_coordinates, triangles, boundary =\
     174         mesh_factory.rectangular(M, N, max_x-min_x, max_y-min_y,
     175                                (min_x, min_y))
     176
     177    #Fit attributes to mesh     
     178    vertex_attributes = fit_to_mesh(vertex_coordinates,
     179                        triangles,
     180                        points,
     181                        attributes, alpha=alpha)
     182
     183
     184         
     185    return vertex_coordinates, triangles, boundary, vertex_attributes
     186                         
     187   
    145188
    146189class Interpolation:
     
    548591        if n<m and self.alpha == 0.0:
    549592            msg = 'ERROR (least_squares): Too few data points\n'
    550             msg += 'There only %d data points. Need at least %d\n' %(n,m)
    551             msg += 'Alternatively, increase smoothing parameter alpha'
     593            msg += 'There are only %d data points and alpha == 0. ' %n
     594            msg += 'Need at least %d\n' %m
     595            msg += 'Alternatively, set smoothing parameter alpha to a small '
     596            msg += 'positive value,\ne.g. 1.0e-3.'
    552597            raise msg
    553598
  • inundation/ga/storm_surge/pyvolution/mesh_factory.py

    r543 r820  
    131131    return points, elements, boundary       
    132132
    133 #OLD FORMULA FOR SETTING BOUNDARY TAGS - OBSOLETE NOW             
    134 #     for id, face in M.boundary:
    135 
    136 #         e = element_class.instances[id]
    137 #         x0, y0, x1, y1, x2, y2 = e.get_instance_vertex_coordinates()
    138 
    139 #         if face==2:
    140 #             #Left or right#
    141 #             if abs(x0-origin[0]) < epsilon:
    142 #                 M.boundary[(id,face)] = 'left'           
    143 #             elif abs(origin[0]+lenx-x0) < epsilon:
    144 #                 M.boundary[(id,face)] = 'right'
    145 #             else:
    146 #                 print face, id, id%m, m, n
    147 #                 raise 'Left or Right Unknown boundary'                           
    148 #         elif face==1:
    149 #             #Top or bottom
    150 #             if x0 > 0.25*lenx and abs(y0-a1-a2*x0-origin[1]) < epsilon or\
    151 #                x0 <= 0.25*lenx and abs(y0-origin[1]) < epsilon:           
    152 #                    M.boundary[(id,face)] = 'bottom'
    153 #             elif abs(origin[1]+leny-y0) < epsilon:
    154 #                 M.boundary[(id,face)] = 'top'
    155 #             else:
    156 #                 print face, id, id%m, m, n
    157 #                 raise 'Top or Bottom Unknown boundary' 
    158 #         else:
    159 #             print face, id, id%m, m, n
    160 #             raise 'Unknown boundary'         
    161 #   
    162 #     return M
    163 
    164 
    165 
    166133
    167134def circular(m, n, radius=1.0, center = (0.0, 0.0)):
     
    394361    return points, elements                             
    395362
    396 
    397 
    398 # def contracting_channel_mesh(m, n, x1 = 0.0, x2 = 1./3., x3 = 2./3., x4 = 1.0,
    399 #                             y1 =0.0, y4 = -1./4., y8 = 1.0,
    400 #                              origin = (0.0, 0.0), point_class=Point,
    401 #                              element_class=Triangle, mesh_class=Mesh):
    402 #     """Setup a oblique grid of triangles
    403 #     with m segments in the x-direction and n segments in the y-direction
    404 
    405 #     Triangle refers to the actual class or subclass to be instantiated:
    406 #     e.g. if Volume is a subclass of Triangle,
    407 #     this function can be invoked with the keywords
    408 #       oblique_mesh(...,Triangle=Volume, Mesh=Domain)
    409 #     """
    410 
    411 #     from Numeric import array
    412 #     from visual import rate#
    413 
    414 #     import math
    415 
    416 #     from config import epsilon
    417 
    418 #     E = m*n*2        #Number of triangular elements
    419 #     P = (m+1)*(n+1)  #Number of initial vertices
    420 
    421 #     initialise_consecutive_datastructure(P+E, E,
    422 #                                          point_class,
    423 #                                          element_class,
    424 #                                          mesh_class)
    425 
    426 #     deltax = (x4 - x1)/float(m)
    427 #     deltay = (y8 - y1)/float(n)
    428 #     a = y4 - y1
    429    
    430 #     if y8 - a <= y1 + a:
    431 #         print a,y1,y4
    432 #         raise 'Constriction is too large reduce a'
    433            
    434 #     y2 = y1
    435 #     y3 = y4
    436 #     x5 = x4
    437 #     y5 = y8 - a
    438 #     x6 = x3
    439 #     y6 = y5
    440 #     x7 = x2
    441 #     y7 = y8
    442 #     x8 = x1
    443    
    444 #     a2 = a/(x3 - x2)
    445 #     a1 = a - a*x3/(x3 - x2)
    446 #     a4 = (-a + a2*(x7 - x6))/(x6 - x7)/y7
    447 #     a3 = (y7 - a1 - x7*a2 - a4*x7*y7)/y7
    448    
    449 #     # Dictionary of vertex objects
    450 #     vertices = {}
    451 
    452 #     for i in range(m+1):
    453 #         x = deltax*i
    454 #         for j in range(n+1):     
    455 #             y = deltay*j
    456 #             if x > x2:
    457 #                 if x < x3:
    458 #                     y = a1 + a2*x + a3*y + a4*x*y
    459 #                 else:
    460 #                     y = a + y*(y5 - y4)/(y8 - y1)   
    461                
    462 #             vertices[i,j] = Point(x + origin[0],y + origin[1])
    463 
    464 #     # Construct 2 elements per element       
    465 #     elements = []
    466 #     for i in range(m):
    467 #         for j in range(n):
    468 #             v1 = vertices[i,j+1]
    469 #             v2 = vertices[i,j]           
    470 #             v3 = vertices[i+1,j+1]           
    471 #             v4 = vertices[i+1,j]
    472  
    473 #             elements.append(element_class(v4,v3,v2)) #Lower               
    474 #             elements.append(element_class(v1,v2,v3)) #Upper   
    475 
    476 #     M = mesh_class(elements)
    477 
    478 #     #Set a default tagging
    479 
    480 #     for id, face in M.boundary:
    481 
    482 #         e = element_class.instances[id]
    483 #         x_0, y_0, x_1, y_1, x_2, y_2 = e.get_instance_vertex_coordinates()
    484 #         lenx = x4 - x1
    485 #         if face==2:
    486 #             #Left or right#
    487 #             if abs(x_0-origin[0]) < epsilon:
    488 #                 M.boundary[(id,face)] = 'left'           
    489 #             elif abs(origin[0]+lenx-x_0) < epsilon:
    490 #                 M.boundary[(id,face)] = 'right'
    491 #             else:
    492 #                 print face, id, id%m, m, n
    493 #                 raise 'Left or Right Unknown boundary'                           
    494 #         elif face==1:
    495 #             #Top or bottom
    496 #             if x_0 <= x2 and abs(y_0-y1-origin[1]) < epsilon or\
    497 #                x_0 > x3 and abs(y_0-y3-origin[1]) < epsilon or\
    498 #                x_0 >  x2 and x_0 <= x3 and abs(y_0-(y2+(y3-y2)*(x_0-x2)/(x3-x2)+origin[1])) < epsilon:           
    499 #                 M.boundary[(id,face)] = 'bottom'
    500 #             elif x_0 <= x7 and abs(y_0-y8-origin[1]) < epsilon or\
    501 #                x_0 > x6 and abs(y_0-y6-origin[1]) < epsilon or\
    502 #                x_0 > x7 and x_0 <= x6 and abs(y_0-(y7+(y6-y7)*(x_0-x7)/(x6-x7)+origin[1])) < epsilon:           
    503 #                 M.boundary[(id,face)] = 'top'
    504 #             else:
    505 #                 print face, id, id%m, m, n
    506 #                 raise 'Top or Bottom Unknown boundary' 
    507 #         else:
    508 #             print face, id, id%m, m, n
    509 #             raise 'Unknown boundary'         
    510 
    511            
    512 #       #  print id, face, M.boundary[(id,face)],x_0,y_0,x_1,y_1,x_2,y_2
    513    
    514 #     return M
    515 
    516 
    517 
    518363# #Map from edge number to indices of associated vertices
    519364# edge_map = ((1,2), (0,2), (0,1))
  • inundation/ga/storm_surge/pyvolution/test_least_squares.py

    r705 r820  
    488488
    489489
     490       
     491    def test_xya2rectangular(self):
     492
     493        import time, os
     494        FN = 'xyatest' + str(time.time()) + '.xya'
     495        fid = open(FN, 'w')
     496        fid.write('%f %f %f %f\n' %(1,1,2,4) )
     497        fid.write('%f %f %f %f\n' %(1,3,4,8) )
     498        fid.write('%f %f %f %f\n' %(3,1,4,8) )         
     499        fid.close()
     500       
     501        points, triangles, boundary, attributes = xya2rectangular(FN, 4, 4)
     502       
     503       
     504       
     505
     506        z1 = [2, 4]
     507        z2 = [4, 8]
     508        z3 = [4, 8]
     509        data_coords = [ [1,1], [1,3], [3,1] ]
     510        z = [z1, z2, z3]
     511
     512        ref = fit_to_mesh(points, triangles, data_coords, z)           
     513       
     514        assert allclose(attributes, ref)
     515
     516       
     517       
    490518
    491519    #Tests of smoothing matrix   
  • inundation/ga/storm_surge/pyvolution/test_util.py

    r799 r820  
    336336        assert allclose( 2*sin(120*pi/600)/3 + sin(60*pi/600)/3, q[2] )
    337337       
     338
     339    def test_xya(self):
     340        import time, os
     341        FN = 'xyatest' + str(time.time()) + '.xya'
     342        fid = open(FN, 'w')
     343        fid.write('%f %f %f %f %f\n' %(0,1,10,20,30) )
     344        fid.write('%f %f %f %f %f\n' %(1,0,30,20,10) )
     345        fid.write('%f %f %f %f %f\n' %(1,1,40.2,40.3,40.4) )           
     346        fid.close()
     347       
     348        points, attributes = read_xya(FN)
     349       
     350        assert allclose(points, [ [0,1], [1,0], [1,1] ])
     351        assert allclose(attributes, [ [10,20,30], [30,20,10],
     352                [40.2,40.3,40.4] ])
     353       
     354        os.remove(FN)
    338355       
    339356       
  • inundation/ga/storm_surge/pyvolution/util.py

    r799 r820  
    8080      return False 
    8181   
     82             
     83class File_function:
     84    """Read time series from file and return a callable object:
     85    f(t,x,y)
     86    which will return interpolated values based on the input file.
     87
     88    The file format is assumed to be either two fields separated by a comma:
     89
     90        time [DD/MM/YY hh:mm:ss], value0 value1 value2 ...
     91
     92    or four comma separated fields
     93
     94        time [DD/MM/YY hh:mm:ss], x, y, value0 value1 value2 ...
     95
     96    In either case, the callable object will return a tuple of
     97    interpolated values, one each value stated in the file.
     98
     99   
     100    E.g
     101
     102      31/08/04 00:00:00, 1.328223 0 0
     103      31/08/04 00:15:00, 1.292912 0 0
     104
     105    will provide a time dependent function f(t,x=None,y=None),
     106    ignoring x and y, which returns three values per call.
     107
     108   
     109    NOTE: At this stage the function is assumed to depend on
     110    time only, i.e  no spatial dependency!!!!!
     111    When that is need we can use the least_squares interpolation.
     112    """
     113
     114   
     115    def __init__(self, filename, domain=None):
     116        """Initialise callable object from a file.
     117        See docstring for class File_function
     118
     119        If domain is specified, model time (domain,starttime)
     120        will be checked and possibly modified
     121
     122        ALl times are assumed to be in UTC
     123        """
     124
     125        import time, calendar
     126        from Numeric import array
     127        from config import time_format
     128
     129        assert type(filename) == type(''),\
     130               'First argument to File_function must be a string'
     131
     132
     133        try:
     134            fid = open(filename)
     135        except Exception, e:
     136            msg = 'File "%s" could not be opened: Error="%s"'\
     137                  %(filename, e)
     138            raise msg
     139
     140
     141        line = fid.readline()
     142        fid.close()
     143        fields = line.split(',')
     144        msg = 'File %s must have the format date, value0 value1 value2 ...'
     145        msg += ' or date, x, y, value0 value1 value2 ...'
     146        mode = len(fields)
     147        assert mode in [2,4], msg
     148
     149        try:
     150            starttime = calendar.timegm(time.strptime(fields[0], time_format))
     151        except ValueError:   
     152            msg = 'First field in file %s must be' %filename
     153            msg += ' date-time with format %s.\n' %time_format
     154            msg += 'I got %s instead.' %fields[0]
     155            raise msg
     156
     157
     158        #Split values
     159        values = []
     160        for value in fields[mode-1].split():
     161            values.append(float(value))
     162
     163        q = array(values)
     164       
     165        msg = 'ERROR: File must contain at least one independent value'
     166        assert len(q.shape) == 1, msg
     167           
     168        self.number_of_values = len(q)
     169
     170        self.filename = filename
     171        self.starttime = starttime
     172        self.domain = domain
     173
     174        if domain is not None:
     175            if domain.starttime is None:
     176                domain.starttime = self.starttime
     177            else:
     178                msg = 'WARNING: Start time as specified in domain (%s)'\
     179                      %domain.starttime
     180                msg += ' is earlier than the starttime of file %s: %s.'\
     181                         %(self.filename, self.starttime)
     182                msg += 'Modifying starttime accordingly.'
     183                if self.starttime > domain.starttime:
     184                    #FIXME: Print depending on some verbosity setting
     185                    #print msg
     186                    domain.starttime = self.starttime #Modifying model time
     187
     188        if mode == 2:       
     189            self.read_times() #Now read all times in.
     190        else:
     191            raise 'x,y dependecy not yet implemented'
     192
     193       
     194    def read_times(self):
     195        """Read time and values
     196        """
     197        from Numeric import zeros, Float, alltrue
     198        from config import time_format
     199        import time, calendar
     200       
     201        fid = open(self.filename)       
     202        lines = fid.readlines()
     203        fid.close()
     204       
     205        N = len(lines)
     206        d = self.number_of_values
     207
     208        T = zeros(N, Float)       #Time
     209        Q = zeros((N, d), Float)  #Values
     210       
     211        for i, line in enumerate(lines):
     212            fields = line.split(',')
     213            realtime = calendar.timegm(time.strptime(fields[0], time_format))
     214
     215            T[i] = realtime - self.starttime
     216
     217            for j, value in enumerate(fields[1].split()):
     218                Q[i, j] = float(value)
     219
     220        msg = 'File %s must list time as a monotonuosly ' %self.filename
     221        msg += 'increasing sequence'
     222        assert alltrue( T[1:] - T[:-1] > 0 ), msg
     223
     224        self.T = T     #Time
     225        self.Q = Q     #Values
     226        self.index = 0 #Initial index
     227
     228       
     229    def __repr__(self):
     230        return 'File function'
     231
     232       
     233
     234    def __call__(self, t, x=None, y=None):
     235        """Evaluate f(t,x,y)
     236
     237        FIXME: x, y dependency not yet implemented except that
     238        result is a vector of same length as x and y
     239        """
     240
     241        from math import pi, cos, sin, sqrt
     242       
     243
     244        #Find time tau such that
     245        #
     246        # domain.starttime + t == self.starttime + tau
     247       
     248        if self.domain is not None:
     249            tau = self.domain.starttime-self.starttime+t
     250        else:
     251            tau = t
     252       
     253               
     254        msg = 'Time interval derived from file %s (%s:%s) does not match model time: %s'\
     255              %(self.filename, self.T[0], self.T[1], tau)
     256        if tau < self.T[0]: raise msg
     257        if tau > self.T[-1]: raise msg       
     258
     259        oldindex = self.index
     260
     261        #Find slot
     262        while tau > self.T[self.index]: self.index += 1
     263        while tau < self.T[self.index]: self.index -= 1
     264
     265        #t is now between index and index+1
     266        ratio = (tau - self.T[self.index])/\
     267                (self.T[self.index+1] - self.T[self.index])
     268
     269        #Compute interpolated values
     270        q = self.Q[self.index,:] +\
     271            ratio*(self.Q[self.index+1,:] - self.Q[self.index,:])
     272
     273        #Return vector of interpolated values
     274        if x == None and y == None:
     275            return q
     276        else:
     277            from Numeric import ones, Float
     278            #Create one constant column for each value
     279            N = len(x)
     280            assert len(y) == N, 'x and y must have same length'
     281
     282            res = []
     283            for col in q:
     284                res.append(col*ones(N, Float))
     285           
     286            return res
     287
     288def read_xya(file_name):
     289    """Read simple xya file, no header, just
     290    x y [attributes]
     291    separated by whitespace
     292   
     293    Return list of points and list of attributes
     294    """
     295   
     296    fid = open(file_name)
     297    lines = fid.readlines()
     298   
     299    points = []
     300    attributes = []
     301    for line in lines:
     302        fields = line.strip().split()
     303       
     304        points.append( (float(fields[0]),  float(fields[1])) )
     305        attributes.append( [float(z) for z in fields[2:] ] )
     306       
     307    return points, attributes
     308   
     309
     310#####################################
     311#POLYFON STUFF
     312#
     313#FIXME: ALl these should be put into new module polygon.py
    82314
    83315def inside_polygon(point, polygon, closed = True):
     
    286518
    287519    return polygon     
    288              
    289              
    290 class File_function:
    291     """Read time series from file and return a callable object:
    292     f(t,x,y)
    293     which will return interpolated values based on the input file.
    294 
    295     The file format is assumed to be either two fields separated by a comma:
    296 
    297         time [DD/MM/YY hh:mm:ss], value0 value1 value2 ...
    298 
    299     or four comma separated fields
    300 
    301         time [DD/MM/YY hh:mm:ss], x, y, value0 value1 value2 ...
    302 
    303     In either case, the callable object will return a tuple of
    304     interpolated values, one each value stated in the file.
    305 
    306    
    307     E.g
    308 
    309       31/08/04 00:00:00, 1.328223 0 0
    310       31/08/04 00:15:00, 1.292912 0 0
    311 
    312     will provide a time dependent function f(t,x=None,y=None),
    313     ignoring x and y, which returns three values per call.
    314 
    315    
    316     NOTE: At this stage the function is assumed to depend on
    317     time only, i.e  no spatial dependency!!!!!
    318     When that is need we can use the least_squares interpolation.
    319     """
    320 
    321    
    322     def __init__(self, filename, domain=None):
    323         """Initialise callable object from a file.
    324         See docstring for class File_function
    325 
    326         If domain is specified, model time (domain,starttime)
    327         will be checked and possibly modified
    328 
    329         ALl times are assumed to be in UTC
    330         """
    331 
    332         import time, calendar
    333         from Numeric import array
    334         from config import time_format
    335 
    336         assert type(filename) == type(''),\
    337                'First argument to File_function must be a string'
    338 
    339 
    340         try:
    341             fid = open(filename)
    342         except Exception, e:
    343             msg = 'File "%s" could not be opened: Error="%s"'\
    344                   %(filename, e)
    345             raise msg
    346 
    347 
    348         line = fid.readline()
    349         fid.close()
    350         fields = line.split(',')
    351         msg = 'File %s must have the format date, value0 value1 value2 ...'
    352         msg += ' or date, x, y, value0 value1 value2 ...'
    353         mode = len(fields)
    354         assert mode in [2,4], msg
    355 
    356         try:
    357             starttime = calendar.timegm(time.strptime(fields[0], time_format))
    358         except ValueError:   
    359             msg = 'First field in file %s must be' %filename
    360             msg += ' date-time with format %s.\n' %time_format
    361             msg += 'I got %s instead.' %fields[0]
    362             raise msg
    363 
    364 
    365         #Split values
    366         values = []
    367         for value in fields[mode-1].split():
    368             values.append(float(value))
    369 
    370         q = array(values)
    371        
    372         msg = 'ERROR: File must contain at least one independent value'
    373         assert len(q.shape) == 1, msg
    374            
    375         self.number_of_values = len(q)
    376 
    377         self.filename = filename
    378         self.starttime = starttime
    379         self.domain = domain
    380 
    381         if domain is not None:
    382             if domain.starttime is None:
    383                 domain.starttime = self.starttime
    384             else:
    385                 msg = 'WARNING: Start time as specified in domain (%s)'\
    386                       %domain.starttime
    387                 msg += ' is earlier than the starttime of file %s: %s.'\
    388                          %(self.filename, self.starttime)
    389                 msg += 'Modifying starttime accordingly.'
    390                 if self.starttime > domain.starttime:
    391                     #FIXME: Print depending on some verbosity setting
    392                     #print msg
    393                     domain.starttime = self.starttime #Modifying model time
    394 
    395         if mode == 2:       
    396             self.read_times() #Now read all times in.
    397         else:
    398             raise 'x,y dependecy not yet implemented'
    399 
    400        
    401     def read_times(self):
    402         """Read time and values
    403         """
    404         from Numeric import zeros, Float, alltrue
    405         from config import time_format
    406         import time, calendar
    407        
    408         fid = open(self.filename)       
    409         lines = fid.readlines()
    410         fid.close()
    411        
    412         N = len(lines)
    413         d = self.number_of_values
    414 
    415         T = zeros(N, Float)       #Time
    416         Q = zeros((N, d), Float)  #Values
    417        
    418         for i, line in enumerate(lines):
    419             fields = line.split(',')
    420             realtime = calendar.timegm(time.strptime(fields[0], time_format))
    421 
    422             T[i] = realtime - self.starttime
    423 
    424             for j, value in enumerate(fields[1].split()):
    425                 Q[i, j] = float(value)
    426 
    427         msg = 'File %s must list time as a monotonuosly ' %self.filename
    428         msg += 'increasing sequence'
    429         assert alltrue( T[1:] - T[:-1] > 0 ), msg
    430 
    431         self.T = T     #Time
    432         self.Q = Q     #Values
    433         self.index = 0 #Initial index
    434 
    435        
    436     def __repr__(self):
    437         return 'File function'
    438 
    439        
    440 
    441     def __call__(self, t, x=None, y=None):
    442         """Evaluate f(t,x,y)
    443 
    444         FIXME: x, y dependency not yet implemented except that
    445         result is a vector of same length as x and y
    446         """
    447 
    448         from math import pi, cos, sin, sqrt
    449        
    450 
    451         #Find time tau such that
    452         #
    453         # domain.starttime + t == self.starttime + tau
    454        
    455         if self.domain is not None:
    456             tau = self.domain.starttime-self.starttime+t
    457         else:
    458             tau = t
    459        
    460                
    461         msg = 'Time interval derived from file %s (%s:%s) does not match model time: %s'\
    462               %(self.filename, self.T[0], self.T[1], tau)
    463         if tau < self.T[0]: raise msg
    464         if tau > self.T[-1]: raise msg       
    465 
    466         oldindex = self.index
    467 
    468         #Find slot
    469         while tau > self.T[self.index]: self.index += 1
    470         while tau < self.T[self.index]: self.index -= 1
    471 
    472         #t is now between index and index+1
    473         ratio = (tau - self.T[self.index])/\
    474                 (self.T[self.index+1] - self.T[self.index])
    475 
    476         #Compute interpolated values
    477         q = self.Q[self.index,:] +\
    478             ratio*(self.Q[self.index+1,:] - self.Q[self.index,:])
    479 
    480         #Return vector of interpolated values
    481         if x == None and y == None:
    482             return q
    483         else:
    484             from Numeric import ones, Float
    485             #Create one constant column for each value
    486             N = len(x)
    487             assert len(y) == N, 'x and y must have same length'
    488 
    489             res = []
    490             for col in q:
    491                 res.append(col*ones(N, Float))
    492            
    493             return res
    494    
    495 
     520   
    496521def populate_polygon(polygon, number_of_points, seed = None):
    497522    """Populate given polygon with uniformly distributed points.
Note: See TracChangeset for help on using the changeset viewer.