Changeset 4341


Ignore:
Timestamp:
Mar 29, 2007, 5:54:23 PM (18 years ago)
Author:
ole
Message:

Refactored file_function so that instances of domain is no longer pass into cached internal function _file_function. This should fix the issues with caching for good (I hope).

All tests pass.

Location:
anuga_core/source/anuga
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • anuga_core/source/anuga/abstract_2d_finite_volumes/test_util.py

    r4306 r4341  
    12931293#-------------------------------------------------------------
    12941294if __name__ == "__main__":
    1295     #suite = unittest.makeSuite(Test_Util,'test')
    1296     suite = unittest.makeSuite(Test_Util,'test_get_data_from_file')
     1295    suite = unittest.makeSuite(Test_Util,'test')
     1296    #suite = unittest.makeSuite(Test_Util,'test_get_data_from_file')
    12971297    runner = unittest.TextTestRunner()
    12981298    runner.run(suite)
  • anuga_core/source/anuga/abstract_2d_finite_volumes/util.py

    r4338 r4341  
    5050    quantities - the name of the quantity to be interpolated or a
    5151                 list of quantity names. The resulting function will return
    52                  a tuple of values - one for each quantity 
     52                 a tuple of values - one for each quantity
     53                 If quantities are None, domain's conserved quantities
     54                 are used.
    5355
    5456    interpolation_points - list of absolute UTM coordinates for points (N x 2)
     
    6365
    6466
     67    #FIXME (OLE): Should check origin of domain against that of file
     68    #In fact, this is where origin should be converted to that of domain
     69    #Also, check that file covers domain fully.
     70
     71    #Take into account:
     72    #- domain's georef
     73    #- sww file's georef
     74    #- interpolation points as absolute UTM coordinates
     75
     76
     77
     78
     79    # Use domain's conserved_quantity names as defaults
     80    if domain is not None:   
     81        if quantities is None:
     82            quantities = domain.conserved_quantities
     83           
     84        domain_starttime = domain.starttime
     85    else:
     86        domain_starttime = None
     87
     88
    6589    # Build arguments and keyword arguments for use with caching or apply.
    6690    args = (filename,)
    67    
    68     kwargs = {'domain': domain,
    69               'quantities': quantities,
     91
     92
     93    # FIXME (Ole): Caching this function will not work well
     94    # if domain is passed in as instances change hash code.
     95    # Instead we pass in those attributes that are needed (and return them
     96    # if modified)
     97    kwargs = {'quantities': quantities,
    7098              'interpolation_points': interpolation_points,
     99              'domain_starttime': domain_starttime,
    71100              'time_thinning': time_thinning,                   
    72101              'verbose': verbose}
     
    82111            raise msg
    83112
    84         f = cache(_file_function,
    85                   args, kwargs,
    86                   dependencies=[filename],
    87                   compression=False,                 
    88                   verbose=verbose)
     113        f, starttime = cache(_file_function,
     114                             args, kwargs,
     115                             dependencies=[filename],
     116                             compression=False,                 
     117                             verbose=verbose)
    89118
    90119    else:
    91         f = apply(_file_function,
    92                   args, kwargs)
     120        f, starttime = apply(_file_function,
     121                             args, kwargs)
    93122
    94123
    95124    #FIXME (Ole): Pass cache arguments, such as compression, in some sort of
    96125    #structure
    97        
    98 
    99     return f
    100 
    101 
    102 
    103 def _file_function(filename,
    104                    domain=None,
    105                    quantities=None,
    106                    interpolation_points=None,
    107                    time_thinning=1,                                               
    108                    verbose=False):
    109     """Internal function
    110    
    111     See file_function for documentatiton
    112     """
    113    
    114 
    115     #FIXME (OLE): Should check origin of domain against that of file
    116     #In fact, this is where origin should be converted to that of domain
    117     #Also, check that file covers domain fully.
    118 
    119     #Take into account:
    120     #- domain's georef
    121     #- sww file's georef
    122     #- interpolation points as absolute UTM coordinates
    123 
    124 
    125     assert type(filename) == type(''),\
    126                'First argument to File_function must be a string'
    127 
    128     try:
    129         fid = open(filename)
    130     except Exception, e:
    131         msg = 'File "%s" could not be opened: Error="%s"'\
    132                   %(filename, e)
    133         raise msg
    134 
    135     line = fid.readline()
    136     fid.close()
    137 
    138     if quantities is None:
    139         if domain is not None:
    140             quantities = domain.conserved_quantities
    141 
    142 
    143 
    144     if line[:3] == 'CDF':
    145         return get_netcdf_file_function(filename, domain, quantities,
    146                                         interpolation_points,
    147                                         time_thinning=time_thinning,
    148                                         verbose=verbose)
    149     else:
    150         raise 'Must be a NetCDF File'
    151 
    152 
    153 
    154 def get_netcdf_file_function(filename,
    155                              domain=None,
    156                              quantity_names=None,
    157                              interpolation_points=None,
    158                              time_thinning=1,                             
    159                              verbose=False):
    160     """Read time history of spatial data from NetCDF sww file and
    161     return a callable object f(t,x,y)
    162     which will return interpolated values based on the input file.
    163 
    164     If domain is specified, model time (domain.starttime)
    165     will be checked and possibly modified
    166    
    167     All times are assumed to be in UTC
    168 
    169     See Interpolation function for further documetation
    170    
    171     """
    172    
    173    
    174     #FIXME: Check that model origin is the same as file's origin
    175     #(both in UTM coordinates)
    176     #If not - modify those from file to match domain
    177     #Take this code from e.g. dem2pts in data_manager.py
    178     #FIXME: Use geo_reference to read and write xllcorner...
    179        
    180 
    181     #FIXME: Maybe move caching out to this level rather than at the
    182     #Interpolation_function level (below)
    183 
    184     import time, calendar, types
    185     from anuga.config import time_format
    186     from Scientific.IO.NetCDF import NetCDFFile
    187     from Numeric import array, zeros, Float, alltrue, concatenate, reshape
    188 
    189     #Open NetCDF file
    190     if verbose: print 'Reading', filename
    191     fid = NetCDFFile(filename, 'r')
    192 
    193     if type(quantity_names) == types.StringType:
    194         quantity_names = [quantity_names]       
    195    
    196     if quantity_names is None or len(quantity_names) < 1:
    197         #If no quantities are specified get quantities from file
    198         #x, y, time are assumed as the independent variables so
    199         #they are excluded as potentiol quantities
    200         quantity_names = []
    201         for name in fid.variables.keys():
    202             if name not in ['x', 'y', 'time']:
    203                 quantity_names.append(name)
    204 
    205     if len(quantity_names) < 1:               
    206         msg = 'ERROR: At least one independent value must be specified'
    207         raise msg
    208 
    209 
    210     if interpolation_points is not None:
    211         interpolation_points = ensure_absolute(interpolation_points)
    212         msg = 'Points must by N x 2. I got %d' %interpolation_points.shape[1]
    213         assert interpolation_points.shape[1] == 2, msg
    214 
    215 
    216     #Now assert that requested quantitites (and the independent ones)
    217     #are present in file
    218     missing = []
    219     for quantity in ['time'] + quantity_names:
    220         if not fid.variables.has_key(quantity):
    221             missing.append(quantity)
    222 
    223     if len(missing) > 0:
    224         msg = 'Quantities %s could not be found in file %s'\
    225               %(str(missing), filename)
    226         fid.close()
    227         raise Exception, msg
    228 
    229     #Decide whether this data has a spatial dimension
    230     spatial = True
    231     for quantity in ['x', 'y']:
    232         if not fid.variables.has_key(quantity):
    233             spatial = False
    234 
    235     if filename[-3:] == 'tms' and spatial is True:
    236         msg = 'Files of type tms must not contain spatial information'
    237         raise msg
    238 
    239     if filename[-3:] == 'sww' and spatial is False:
    240         msg = 'Files of type sww must contain spatial information'       
    241         raise msg       
    242 
    243     #Get first timestep
    244     try:
    245         starttime = fid.starttime[0]
    246     except ValueError:
    247         msg = 'Could not read starttime from file %s' %filename
    248         raise msg
    249 
    250     #Get variables
    251     #if verbose: print 'Get variables'   
    252     time = fid.variables['time'][:]   
    253 
    254     # Get time independent stuff
    255     if spatial:
    256         #Get origin
    257         xllcorner = fid.xllcorner[0]
    258         yllcorner = fid.yllcorner[0]
    259         zone = fid.zone[0]       
    260 
    261         x = fid.variables['x'][:]
    262         y = fid.variables['y'][:]
    263         triangles = fid.variables['volumes'][:]
    264 
    265         x = reshape(x, (len(x),1))
    266         y = reshape(y, (len(y),1))
    267         vertex_coordinates = concatenate((x,y), axis=1) #m x 2 array
    268 
    269         if interpolation_points is not None:
    270             #Adjust for georef
    271             interpolation_points[:,0] -= xllcorner
    272             interpolation_points[:,1] -= yllcorner       
    273        
    274 
    275126
    276127
    277128    if domain is not None:
    278         #Update domain.startime if it is *earlier* than starttime
     129        #Update domain.startime if it is *earlier* than starttime from file
    279130        if starttime > domain.starttime:
    280131            msg = 'WARNING: Start time as specified in domain (%f)'\
     
    289140               %domain.starttime
    290141
    291 
    292         #If domain.startime is *later* than starttime,
     142    return f
     143
     144
     145
     146def _file_function(filename,
     147                   quantities=None,
     148                   interpolation_points=None,
     149                   domain_starttime=None,
     150                   time_thinning=1,
     151                   verbose=False):
     152    """Internal function
     153   
     154    See file_function for documentatiton
     155    """
     156   
     157
     158    assert type(filename) == type(''),\
     159               'First argument to File_function must be a string'
     160
     161    try:
     162        fid = open(filename)
     163    except Exception, e:
     164        msg = 'File "%s" could not be opened: Error="%s"'\
     165                  %(filename, e)
     166        raise msg
     167
     168    line = fid.readline()
     169    fid.close()
     170
     171
     172    if line[:3] == 'CDF':
     173        return get_netcdf_file_function(filename,
     174                                        quantities,
     175                                        interpolation_points,
     176                                        domain_starttime,
     177                                        time_thinning=time_thinning,
     178                                        verbose=verbose)
     179    else:
     180        raise 'Must be a NetCDF File'
     181
     182
     183
     184def get_netcdf_file_function(filename,
     185                             quantity_names=None,
     186                             interpolation_points=None,
     187                             domain_starttime=None,                           
     188                             time_thinning=1,                             
     189                             verbose=False):
     190    """Read time history of spatial data from NetCDF sww file and
     191    return a callable object f(t,x,y)
     192    which will return interpolated values based on the input file.
     193
     194    Model time (domain_starttime)
     195    will be checked, possibly modified and returned
     196   
     197    All times are assumed to be in UTC
     198
     199    See Interpolation function for further documetation
     200   
     201    """
     202   
     203   
     204    #FIXME: Check that model origin is the same as file's origin
     205    #(both in UTM coordinates)
     206    #If not - modify those from file to match domain
     207    #(origin should be passed in)
     208    #Take this code from e.g. dem2pts in data_manager.py
     209    #FIXME: Use geo_reference to read and write xllcorner...
     210       
     211
     212    import time, calendar, types
     213    from anuga.config import time_format
     214    from Scientific.IO.NetCDF import NetCDFFile
     215    from Numeric import array, zeros, Float, alltrue, concatenate, reshape
     216
     217    #Open NetCDF file
     218    if verbose: print 'Reading', filename
     219    fid = NetCDFFile(filename, 'r')
     220
     221    if type(quantity_names) == types.StringType:
     222        quantity_names = [quantity_names]       
     223   
     224    if quantity_names is None or len(quantity_names) < 1:
     225        #If no quantities are specified get quantities from file
     226        #x, y, time are assumed as the independent variables so
     227        #they are excluded as potentiol quantities
     228        quantity_names = []
     229        for name in fid.variables.keys():
     230            if name not in ['x', 'y', 'time']:
     231                quantity_names.append(name)
     232
     233    if len(quantity_names) < 1:               
     234        msg = 'ERROR: At least one independent value must be specified'
     235        raise msg
     236
     237
     238    if interpolation_points is not None:
     239        interpolation_points = ensure_absolute(interpolation_points)
     240        msg = 'Points must by N x 2. I got %d' %interpolation_points.shape[1]
     241        assert interpolation_points.shape[1] == 2, msg
     242
     243
     244    #Now assert that requested quantitites (and the independent ones)
     245    #are present in file
     246    missing = []
     247    for quantity in ['time'] + quantity_names:
     248        if not fid.variables.has_key(quantity):
     249            missing.append(quantity)
     250
     251    if len(missing) > 0:
     252        msg = 'Quantities %s could not be found in file %s'\
     253              %(str(missing), filename)
     254        fid.close()
     255        raise Exception, msg
     256
     257    #Decide whether this data has a spatial dimension
     258    spatial = True
     259    for quantity in ['x', 'y']:
     260        if not fid.variables.has_key(quantity):
     261            spatial = False
     262
     263    if filename[-3:] == 'tms' and spatial is True:
     264        msg = 'Files of type tms must not contain spatial information'
     265        raise msg
     266
     267    if filename[-3:] == 'sww' and spatial is False:
     268        msg = 'Files of type sww must contain spatial information'       
     269        raise msg       
     270
     271    #Get first timestep
     272    try:
     273        starttime = fid.starttime[0]
     274    except ValueError:
     275        msg = 'Could not read starttime from file %s' %filename
     276        raise msg
     277
     278    #Get variables
     279    #if verbose: print 'Get variables'   
     280    time = fid.variables['time'][:]   
     281
     282    # Get time independent stuff
     283    if spatial:
     284        #Get origin
     285        xllcorner = fid.xllcorner[0]
     286        yllcorner = fid.yllcorner[0]
     287        zone = fid.zone[0]       
     288
     289        x = fid.variables['x'][:]
     290        y = fid.variables['y'][:]
     291        triangles = fid.variables['volumes'][:]
     292
     293        x = reshape(x, (len(x),1))
     294        y = reshape(y, (len(y),1))
     295        vertex_coordinates = concatenate((x,y), axis=1) #m x 2 array
     296
     297        if interpolation_points is not None:
     298            #Adjust for georef
     299            interpolation_points[:,0] -= xllcorner
     300            interpolation_points[:,1] -= yllcorner       
     301       
     302
     303
     304
     305    if domain_starttime is not None:
     306
     307        #If domain_startime is *later* than starttime,
    293308        #move time back - relative to domain's time
    294         if domain.starttime > starttime:
    295             time = time - domain.starttime + starttime
     309        if domain_starttime > starttime:
     310            time = time - domain_starttime + starttime
    296311
    297312        #FIXME Use method in geo to reconcile
     
    325340        vertex_coordinates = triangles = interpolation_points = None         
    326341
     342
     343    # Return Interpolation_function instance as well as
     344    # starttime for use to possible modify that of domain
    327345    return Interpolation_function(time,
    328346                                  quantities,
     
    332350                                  interpolation_points,
    333351                                  time_thinning=time_thinning,
    334                                   verbose=verbose)
     352                                  verbose=verbose), starttime
     353
     354    # NOTE (Ole): Caching Interpolation function is too slow as
     355    # the very long parameters need to be hashed.
     356
     357
     358
    335359
    336360
  • anuga_core/source/anuga/utilities/numerical_tools.py

    r4249 r4341  
    163163
    164164    x = ensure_numeric(x)
    165     y = ensure_numeric(y)       
    166     assert(len(x)==len(y))
     165    y = ensure_numeric(y)
     166    msg = 'Lengths must be equal: len(x) == %d, len(y) == %d' %(len(x), len(y))
     167    assert(len(x)==len(y)), msg
    167168
    168169    N = len(x)
Note: See TracChangeset for help on using the changeset viewer.