source: inundation/pyvolution/util.py @ 2950

Last change on this file since 2950 was 2933, checked in by ole, 19 years ago

Fixed get_version

File size: 30.2 KB
RevLine 
[1758]1"""This module contains various auxiliary function used by pyvolution.
2
3It is also a clearing house for functions that may later earn a module
4of their own.
5"""
6
7
[1911]8import utilities.polygon
[1932]9from warnings import warn
[1911]10
11
[1758]12
13def file_function(filename,
14                  domain = None,
15                  quantities = None,
[1986]16                  interpolation_points = None,
17                  verbose = False,
18                  use_cache = False):
[1835]19    """Read time history of spatial data from NetCDF file and return
20    a callable object.
[1758]21
[1905]22    Input variables:
23   
24    filename - Name of sww or tms file
25       
26       If the file has extension 'sww' then it is assumed to be spatio-temporal
27       or temporal and the callable object will have the form f(t,x,y) or f(t)
28       depending on whether the file contains spatial data
[1758]29
[1905]30       If the file has extension 'tms' then it is assumed to be temporal only
31       and the callable object will have the form f(t)
[1835]32
[1905]33       Either form will return interpolated values based on the input file
34       using the underlying interpolation_function.
[1835]35
[1905]36    domain - Associated domain object   
37       If domain is specified, model time (domain.starttime)
38       will be checked and possibly modified.
[1835]39   
[1905]40       All times are assumed to be in UTC
41       
42       All spatial information is assumed to be in absolute UTM coordinates.
[1835]43
[1905]44    quantities - the name of the quantity to be interpolated or a
45                 list of quantity names. The resulting function will return
46                 a tuple of values - one for each quantity 
[1835]47
[1905]48    interpolation_points - list of absolute UTM coordinates for points at
49    which values are sought
50   
[1986]51    use_cache: True means that caching of intermediate result of
52               Interpolation_function is attempted
[1905]53
54   
[1835]55    See Interpolation function for further documentation
[1758]56    """
[1986]57
58
59    if use_cache is True:
60        try:
61            from caching import cache
62        except:
63            msg = 'Caching was requested, but caching module'+\
64                  'could not be imported'
65            raise msg
66
67
68        f = cache(_file_function,
69                  filename,
70                  {'domain': domain,
71                   'quantities': quantities,
72                   'interpolation_points': interpolation_points,
73                   'verbose': verbose},
74                  dependencies = [filename],
75                  compression = False,
76                  verbose = verbose)
77        #FIXME (Ole): Pass cache arguments, such as compression, in some sort of
78        #structure
79       
80    else:
81        f = _file_function(filename,
82                           domain,
83                           quantities,
84                           interpolation_points,
85                           verbose)           
86
87    return f
88
89
90
91def _file_function(filename,
92                   domain = None,
93                   quantities = None,
94                   interpolation_points = None,
95                   verbose = False):
96    """Internal function
[1835]97   
[1986]98    See file_function for documentatiton
99    """
100   
[1758]101
102    #FIXME (OLE): Should check origin of domain against that of file
103    #In fact, this is where origin should be converted to that of domain
104    #Also, check that file covers domain fully.
[1859]105    #If we use the suggested Point_set class for interpolation points
106    #here it would be easier
[1758]107
[1859]108    #Take into account:
109    #- domain's georef
110    #- sww file's georef
[1884]111    #- interpolation points as absolute UTM coordinates
[1859]112
113
[1758]114    assert type(filename) == type(''),\
115               'First argument to File_function must be a string'
116
117    try:
118        fid = open(filename)
119    except Exception, e:
120        msg = 'File "%s" could not be opened: Error="%s"'\
121                  %(filename, e)
122        raise msg
123
124    line = fid.readline()
125    fid.close()
126
127    if quantities is None: 
128        if domain is not None:
129            quantities = domain.conserved_quantities
130
131
132
133    if line[:3] == 'CDF':
134        return get_netcdf_file_function(filename, domain, quantities,
[1986]135                                        interpolation_points,
136                                        verbose = verbose)
[1758]137    else:
138        raise 'Must be a NetCDF File'
139
140
141
[1986]142def get_netcdf_file_function(filename,
143                             domain=None,
144                             quantity_names=None,
145                             interpolation_points=None,
146                             verbose = False):
[1758]147    """Read time history of spatial data from NetCDF sww file and
148    return a callable object f(t,x,y)
149    which will return interpolated values based on the input file.
150
151    If domain is specified, model time (domain.starttime)
152    will be checked and possibly modified
153   
154    All times are assumed to be in UTC
155
156    See Interpolation function for further documetation
157   
158    """
159   
160   
161    #FIXME: Check that model origin is the same as file's origin
162    #(both in UTM coordinates)
163    #If not - modify those from file to match domain
164    #Take this code from e.g. dem2pts in data_manager.py
165    #FIXME: Use geo_reference to read and write xllcorner...
166       
167
[1986]168    #FIXME: Maybe move caching out to this level rather than at the
169    #Interpolation_function level (below)
170
[1758]171    import time, calendar, types
172    from config import time_format
173    from Scientific.IO.NetCDF import NetCDFFile
[1884]174    from Numeric import array, zeros, Float, alltrue, concatenate, reshape
[2516]175    from utilities.numerical_tools import ensure_numeric   
[1758]176
177    #Open NetCDF file
178    if verbose: print 'Reading', filename
179    fid = NetCDFFile(filename, 'r')
180
181    if type(quantity_names) == types.StringType:
182        quantity_names = [quantity_names]       
183   
184    if quantity_names is None or len(quantity_names) < 1:
[1819]185        #If no quantities are specified get quantities from file
186        #x, y, time are assumed as the independent variables so
187        #they are excluded as potentiol quantities
[1758]188        quantity_names = []
189        for name in fid.variables.keys():
190            if name not in ['x', 'y', 'time']:
191                quantity_names.append(name)
192
[1819]193    if len(quantity_names) < 1:               
194        msg = 'ERROR: At least one independent value must be specified'
195        raise msg
196
197
[1884]198    if interpolation_points is not None:
[1961]199        interpolation_points = ensure_numeric(interpolation_points, Float)
[1884]200
201
202
[1819]203    #Now assert that requested quantitites (and the independent ones)
204    #are present in file
[1758]205    missing = []
[1835]206    for quantity in ['time'] + quantity_names:
[1758]207        if not fid.variables.has_key(quantity):
208            missing.append(quantity)
209
210    if len(missing) > 0:
211        msg = 'Quantities %s could not be found in file %s'\
212              %(str(missing), filename)
213        fid.close()
214        raise msg
215
216    #Decide whether this data has a spatial dimension
217    spatial = True
218    for quantity in ['x', 'y']:
219        if not fid.variables.has_key(quantity):
220            spatial = False
221
[1835]222    if filename[-3:] == 'tms' and spatial is True:
223        msg = 'Files of type tms must not contain spatial information'
224        raise msg
[1758]225
[1835]226    if filename[-3:] == 'sww' and spatial is False:
227        msg = 'Files of type sww must contain spatial information'       
228        raise msg       
[1758]229
230    #Get first timestep
231    try:
232        starttime = fid.starttime[0]
233    except ValueError:
234        msg = 'Could not read starttime from file %s' %filename
235        raise msg
236
237    #Get variables
238    if verbose: print 'Get variables'   
239    time = fid.variables['time'][:]   
240
241    if spatial:
242        #Get origin
243        xllcorner = fid.xllcorner[0]
244        yllcorner = fid.yllcorner[0]
[1859]245        zone = fid.zone[0]       
[1758]246
247        x = fid.variables['x'][:]
248        y = fid.variables['y'][:]
249        triangles = fid.variables['volumes'][:]
250
251        x = reshape(x, (len(x),1))
252        y = reshape(y, (len(y),1))
253        vertex_coordinates = concatenate((x,y), axis=1) #m x 2 array
254
[1884]255        if interpolation_points is not None:
256            #Adjust for georef
257            interpolation_points[:,0] -= xllcorner
258            interpolation_points[:,1] -= yllcorner       
259       
[1758]260
[1884]261
262
[1758]263    if domain is not None:
264        #Update domain.startime if it is *earlier* than starttime
265        if starttime > domain.starttime:
266            msg = 'WARNING: Start time as specified in domain (%f)'\
267                  %domain.starttime
268            msg += ' is earlier than the starttime of file %s (%f).'\
269                     %(filename, starttime)
270            msg += ' Modifying domain starttime accordingly.'
271           
272            if verbose: print msg
273            domain.starttime = starttime #Modifying model time
274            if verbose: print 'Domain starttime is now set to %f'\
275               %domain.starttime
276
277
278        #If domain.startime is *later* than starttime,
279        #move time back - relative to domain's time
280        if domain.starttime > starttime:
281            time = time - domain.starttime + starttime
282
[1859]283        #FIXME Use method in geo to reconcile
284        #if spatial:
285        #assert domain.geo_reference.xllcorner == xllcorner
286        #assert domain.geo_reference.yllcorner == yllcorner
287        #assert domain.geo_reference.zone == zone       
288       
[1758]289    if verbose:
290        print 'File_function data obtained from: %s' %filename
291        print '  References:'
292        #print '    Datum ....' #FIXME
293        if spatial:
294            print '    Lower left corner: [%f, %f]'\
295                  %(xllcorner, yllcorner)
296        print '    Start time:   %f' %starttime               
297       
298   
299    #Produce values for desired data points at
300    #each timestep
301
302    quantities = {}
303    for i, name in enumerate(quantity_names):
304        quantities[name] = fid.variables[name][:]
305    fid.close()
306   
307
[2750]308    #from least_squares import Interpolation_function
309    from fit_interpolate.interpolate import Interpolation_function
[1758]310
311    if not spatial:
312        vertex_coordinates = triangles = interpolation_points = None         
[1986]313
314
[1758]315    return Interpolation_function(time,
316                                  quantities,
317                                  quantity_names,
318                                  vertex_coordinates,
319                                  triangles,
320                                  interpolation_points,
321                                  verbose = verbose)
322
323
324
325
326
[1927]327def multiple_replace(text, dictionary):
328    """Multiple replace of words in text
[1919]329
[1927]330    text:       String to be modified
331    dictionary: Mapping of words that are to be substituted
[1919]332
[1927]333    Python Cookbook 3.14 page 88 and page 90
334    """
[1919]335
[1927]336    import re
337   
338    #Create a regular expression from all of the dictionary keys
339    #matching only entire words
340    regex = re.compile(r'\b'+ \
341                       r'\b|\b'.join(map(re.escape, dictionary.keys()))+ \
342                       r'\b' )
[1919]343
[1927]344    #For each match, lookup the corresponding value in the dictionary
345    return regex.sub(lambda match: dictionary[match.group(0)], text)
[1919]346
347
[1927]348
349
350def apply_expression_to_dictionary(expression, dictionary):#dictionary):
351    """Apply arbitrary expression to values of dictionary
352
[1919]353    Given an expression in terms of the keys, replace key by the
354    corresponding values and evaluate.
[1927]355   
[1919]356
[1927]357    expression: Arbitrary, e.g. arithmetric, expression relating keys
358                from dictionary.
359
360    dictionary: Mapping between symbols in expression and objects that
361                will be evaluated by expression.
362                Values in dictionary must support operators given in
[2314]363                expression e.g. by overloading
364
365    due to a limitation with Numeric, this can not evaluate 0/0
366    In general, the user can fix by adding 1e-30 to the numerator.
367    SciPy core can handle this situation.
[1919]368    """
369
370    import types
[1924]371    import re
[1919]372
373    assert isinstance(expression, basestring)
[1927]374    assert type(dictionary) == types.DictType
[1919]375
[1927]376    #Convert dictionary values to textual representations suitable for eval
377    D = {}
378    for key in dictionary:
379        D[key] = 'dictionary["%s"]' %key
[1924]380
[1927]381    #Perform substitution of variables   
382    expression = multiple_replace(expression, D)
[1924]383
[1919]384    #Evaluate and return
385    try:
386        return eval(expression)
387    except NameError, e:
388        msg = 'Expression "%s" could not be evaluated: %s' %(expression, e)
389        raise NameError, msg
[2314]390    except ValueError, e:
391        msg = 'Expression "%s" could not be evaluated: %s' %(expression, e)
392        raise ValueError, msg
[1919]393   
394
395
396
[2516]397####################################
398####OBSOLETE STUFF
[1919]399
400
[2704]401def angle(v1, v2):
[2526]402    """Temporary Interface to new location"""
403
404    import utilities.numerical_tools as NT     
405   
406    msg = 'angle has moved from util.py.  '
407    msg += 'Please use "from utilities.numerical_tools import angle"'
408    warn(msg, DeprecationWarning) 
409
[2704]410    return NT.angle(v1, v2)
[2526]411   
412def anglediff(v0, v1):
413    """Temporary Interface to new location"""
414
415    import utilities.numerical_tools as NT
416   
417    msg = 'anglediff has moved from util.py.  '
418    msg += 'Please use "from utilities.numerical_tools import anglediff"'
419    warn(msg, DeprecationWarning) 
420
421    return NT.anglediff(v0, v1)   
422
423   
424def mean(x):
425    """Temporary Interface to new location"""
426
427    import utilities.numerical_tools as NT   
428   
429    msg = 'mean has moved from util.py.  '
430    msg += 'Please use "from utilities.numerical_tools import mean"'
431    warn(msg, DeprecationWarning) 
432
433    return NT.mean(x)   
434
[2516]435def point_on_line(*args, **kwargs):
436    """Temporary Interface to new location"""
[1919]437
[2516]438    msg = 'point_on_line has moved from util.py.  '
439    msg += 'Please use "from utilities.polygon import point_on_line"'
440    warn(msg, DeprecationWarning) 
[1919]441
[2516]442    return utilities.polygon.point_on_line(*args, **kwargs)     
443   
444def inside_polygon(*args, **kwargs):
445    """Temporary Interface to new location"""
[1758]446
[2516]447    print 'inside_polygon has moved from util.py.  ',
448    print 'Please use "from utilities.polygon import inside_polygon"'
[1758]449
[2516]450    return utilities.polygon.inside_polygon(*args, **kwargs)   
451   
452def outside_polygon(*args, **kwargs):
453    """Temporary Interface to new location"""
[1758]454
[2516]455    print 'outside_polygon has moved from util.py.  ',
456    print 'Please use "from utilities.polygon import outside_polygon"'
457
458    return utilities.polygon.outside_polygon(*args, **kwargs)   
459
460
461def separate_points_by_polygon(*args, **kwargs):
462    """Temporary Interface to new location"""
463
464    print 'separate_points_by_polygon has moved from util.py.  ',
465    print 'Please use "from utilities.polygon import separate_points_by_polygon"'
466
467    return utilities.polygon.separate_points_by_polygon(*args, **kwargs)   
468
469
470
471def read_polygon(*args, **kwargs):
472    """Temporary Interface to new location"""
473
474    print 'read_polygon has moved from util.py.  ',
475    print 'Please use "from utilities.polygon import read_polygon"'
476
477    return utilities.polygon.read_polygon(*args, **kwargs)   
478
479
480def populate_polygon(*args, **kwargs):
481    """Temporary Interface to new location"""
482
483    print 'populate_polygon has moved from util.py.  ',
484    print 'Please use "from utilities.polygon import populate_polygon"'
485
486    return utilities.polygon.populate_polygon(*args, **kwargs)   
487
[2701]488'''
489this simply catches the screen output and files it to a file
490'''
491from os import sep
492
493class Screen_Catcher:
494
495    def __init__(self, filename):
[2929]496#        self.data = ''
[2701]497        self.filename = filename
498
499    def write(self, stuff):
[2929]500        fid = open(self.filename, 'a')
501#        fid = open(self.filename, 'w')
502#        self.data = self.data + stuff
503        fid.write(stuff)
[2701]504        fid.close()
[2929]505       
506def get_version_info():
507    """gets the version number of the SVN
508    """
[2933]509   
[2929]510    import os, sys
[2933]511
512    # Create dummy info
513    info = 'Revision: Version info could not be obtained.'
514    info += 'A command line version of svn and access to the '
515    info += 'repository is necessary and the output must '
516    info += 'contain a line starting with "Revision:"'
517
518    try:
519        fid = os.popen('svn info')
520    except:
521        msg = 'svn is not recognised'
522        warn(msg, UserWarning)
[2929]523    else:   
[2933]524        lines = fid.readlines()
[2929]525        fid.close()
[2933]526        for line in lines:
527            if line.startswith('Revision:'):
528                info = line
529                break
530       
531    return info
[2929]532   
[2933]533    #if sys.platform == 'win32':
534    #    msg = 'does not work in Windows .... yet'
535    #    raise OSError, msg
536    #else:   
537    #    fid = os.popen('svn -info')
538    #    info = fid.readlines()
539    #    fid.close()
540    #    return info
[2929]541   
[2933]542   
[2795]543def sww2timeseries(swwfile,
544                   gauge_filename,
545                   label_id,
[2839]546                   report = None,
[2795]547                   plot_quantity = None,
548                   time_min = None,
549                   time_max = None,
550                   title_on = None,
551                   verbose = False):
552   
553    """ Read sww file and plot the time series for the
554    prescribed quantities at defined gauge locations and
555    prescribed time range.
556
557    Input variables:
558
559    swwfile         - name of sww file
560                    - assume that all conserved quantities have been stored
561                   
562    gauge_filename  - name of file containing gauge data
563                        - name, easting, northing
564                    - OR (this is not yet done)
565                        - structure which can be converted to a Numeric array,
566                          such as a geospatial data object
[2905]567                     
[2839]568    label_id        - used in generating latex output. It will be part of
569                      the directory name of file_loc (typically the timestamp).
570                      Helps to differentiate latex files for different simulations
571                      for a particular scenario.
572                     
573    report          - if True, then write figures to report_figures directory in
574                      relevant production directory
575                    - if False, figures are already stored with sww file
576                    - default to False
[2795]577   
578    plot_quantity   - list containing quantities to plot, they must
579                      be the name of an existing quantity or one of
580                      the following possibilities
581                    - possibilities:
582                        - stage; 'stage'
583                        - depth; 'depth'
584                        - velocity; calculated as absolute momentum
585                         (pointwise) divided by depth; 'velocity'
586                        - bearing; calculated as the angle of the momentum
587                          vector (xmomentum, ymomentum) from the North; 'bearing'
588                        - absolute momentum; calculated as
589                          sqrt(xmomentum^2 + ymomentum^2); 'momentum'
590                        - x momentum; 'xmomentum'
591                        - y momentum; 'ymomentum'
592                    - default will be ['stage', 'velocity', 'bearing']
593
594    time_min         - beginning of user defined time range for plotting purposes
595                        - default will be first available time found in swwfile
596                       
597    time_max         - end of user defined time range for plotting purposes
598                        - default will be last available time found in swwfile
599                       
[2839]600    title_on        - if True, export standard graphics with title
601                    - if False, export standard graphics without title
[2905]602
603
[2795]604                     
605    Output:
606   
607    - time series data stored in .csv for later use if required.
608      Name = gauges_timeseries followed by gauge name
[2839]609    - latex file will be generated in same directory as where script is
[2891]610      run (usually production scenario directory.
[2839]611      Name = latexoutputlabel_id.tex
[2795]612
613    Other important information:
614   
615    It is assumed that the used has stored all the conserved quantities
616    and elevation during the scenario run, i.e.
617    ['stage', 'elevation', 'xmomentum', 'ymomentum']
618    If this has not occurred then sww2timeseries will not work.
619                     
620    """
[2808]621
622   
[2795]623    k = _sww2timeseries(swwfile,
624                        gauge_filename,
625                        label_id,
[2839]626                        report,
[2795]627                        plot_quantity,
628                        time_min,
629                        time_max,
630                        title_on,
631                        verbose)
632
633    return k
634
635def _sww2timeseries(swwfile,
636                    gauge_filename,
637                    label_id,
[2839]638                    report = None,
[2795]639                    plot_quantity = None,
640                    time_min = None,
641                    time_max = None,
642                    title_on = None,
[2836]643                    verbose = False):   
[2795]644
645    assert type(swwfile) == type(''),\
646               'The sww filename must be a string'
647
648    try:
649        fid = open(swwfile)
650    except Exception, e:
651        msg = 'File "%s" could not be opened: Error="%s"'\
652                  %(swwfile, e)
653        raise msg
654
[2839]655    index = swwfile.rfind(sep)
656    file_loc = swwfile[:index+1]
657       
[2795]658    assert type(gauge_filename) == type(''),\
659               'Gauge filename must be a string'
660   
661    try:
662        fid = open(gauge_filename)
663    except Exception, e:
664        msg = 'File "%s" could not be opened: Error="%s"'\
665                  %(gauge_filename, e)
666        raise msg
[2839]667
668    if report is None:
669        report = False
[2795]670       
671    assert type(plot_quantity) == list,\
672               'plot_quantity must be a list'
673   
674    if plot_quantity is None:
675        plot_quantity = ['depth', 'velocity', 'bearing']
676    else:
677        check_list(plot_quantity)
678
679    if title_on is None:
680        title_on = True
[2905]681     
[2795]682    assert type(label_id) == type(''),\
683               'label_id to sww2timeseries must be a string'
684   
685    if verbose: print '\n Gauges obtained from: %s \n' %gauge_filename
686    gauges, locations = get_gauges_from_file(gauge_filename)
687
688    sww_quantity = ['stage', 'elevation', 'xmomentum', 'ymomentum']
689
690    f = file_function(swwfile,
691                      quantities = sww_quantity,
692                      interpolation_points = gauges,
693                      verbose = True,
694                      use_cache = True)
695
[2884]696    T = f.get_time()
697
[2795]698    if max(f.quantities['xmomentum']) > 1.e10:
699        msg = 'Not all conserved quantities available from sww file. \n sww2timeseries requires all conserved quantities stored in sww file'
700        raise Exception, msg
701       
702    if time_min is None:
[2884]703        time_min = min(T)
[2795]704    else:
[2884]705        if time_min < min(T):
[2795]706            msg = 'Minimum time entered not correct - please try again'
707            raise Exception, msg
708
709    if time_max is None:
[2884]710        time_max = max(T)
[2795]711    else:
[2884]712        if time_max > max(T):
[2795]713            msg = 'Maximum time entered not correct - please try again'
714            raise Exception, msg
715
716    if verbose: print 'Inputs OK - going to generate figures'
[2905]717
[2839]718    return generate_figures(plot_quantity, file_loc, report,
719                            f, gauges, locations,
[2795]720                            time_min, time_max, title_on, label_id, verbose)
721                         
722
723def get_gauges_from_file(filename):
724    fid = open(filename)
725    lines = fid.readlines()
726    fid.close()
727   
728    gauges = []
729    gaugelocation = []
730    line1 = lines[0]
731    line11 = line1.split(',')
732    for i in range(len(line11)):
733        if line11[i].strip('\n').strip(' ') == 'Easting': east_index = i
734        if line11[i].strip('\n').strip(' ') == 'Northing': north_index = i
735        if line11[i].strip('\n').strip(' ') == 'Name': name_index = i
736   
737    for line in lines[1:]:
738        fields = line.split(',')
739        gauges.append([float(fields[east_index]), float(fields[north_index])])
740        loc = fields[name_index]
741        gaugelocation.append(loc.strip('\n'))
742   
743    return gauges, gaugelocation
744
745def check_list(quantity):
746
747    all_quantity = ['stage', 'depth', 'momentum', 'xmomentum',
748                    'ymomentum', 'velocity', 'bearing', 'elevation']
749
750    p = list(set(quantity).difference(set(all_quantity)))
751    if len(p) <> 0:
752        msg = 'Quantities %s do not exist - please try again' %p
753        raise Exception, msg
754       
755    return 
756
757def calc_bearing(uh, vh):
758
759    from math import atan, degrees
760   
761    angle = degrees(atan(vh/(uh+1.e-15)))
762    if (0 < angle < 90.0):
763        if vh > 0:
764            bearing = 90.0 - abs(angle)
765        if vh < 0:
766            bearing = 270.0 - abs(angle)
767    if (-90 < angle < 0):
768        if vh < 0:
769            bearing = 90.0 - abs(angle)
770        if vh > 0:
771            bearing = 270.0 - abs(angle)
772    if angle == 0: bearing = 0.0
773           
774    return bearing
775
[2839]776def generate_figures(plot_quantity, file_loc, report, f, gauges,
[2795]777                     locations, time_min, time_max, title_on, label_id, verbose):
778
779    from math import sqrt, atan, degrees
[2836]780    from Numeric import ones
781    from os import sep, altsep, getcwd, mkdir, access, F_OK, environ
782    from pylab import ion, hold, plot, axis, figure, legend, savefig, xlabel, ylabel, title, close
[2795]783
784    filename = file_loc.split(sep)
785       
[2839]786    if report == True:
[2836]787        label_id1 = label_id.replace(sep,'')
788        label_id2 = label_id1.replace('_','')
789        texfile = 'latexoutput%s' %(label_id2)
790        texfilename = texfile + '.tex' 
[2795]791        if verbose: print '\n Latex output printed to %s \n' %texfilename
[2839]792
[2795]793        fid = open(texfilename, 'w')
794        s = '\\begin{center} \n \\begin{tabular}{|l|l|l|}\hline \n \\bf{Gauge Name} & \\bf{Easting} & \\bf{Northing} \\\\ \hline \n'
795        fid.write(s)
796        gauges1 = gauges
797        for name, gauges1 in zip(locations, gauges1):
798            east = gauges1[0]
799            north = gauges1[1]
[2918]800            s = '%s & %.2f & %.2f \\\\ \hline \n' %(name.replace('_',' '), east, north)
[2795]801            fid.write(s)
802
803        s = '\\end{tabular} \n \\end{center} \n \n'
804        fid.write(s)
805    else:
[2839]806        texfile = ''
[2918]807
808    c = 0
[2795]809    ##### loop over each gauge #####
810    for k, g in enumerate(gauges):
811        if verbose: print 'Gauge %d of %d' %(k, len(gauges))
812        model_time = []
813        stages = []
814        elevations = []
815        momenta = []
816        xmom = []
817        ymom = []
818        velocity = []
819        bearings = []
820        depths = []
821        max_depth = 0
822        max_momentum = 0
823        max_velocity = 0     
824       
825        #### generate quantities #######
[2884]826        for i, t in enumerate(f.get_time()): 
[2795]827
828            if time_min <= t <= time_max:
829
830                w = f(t, point_id = k)[0]
831                z = f(t, point_id = k)[1]
832                uh = f(t, point_id = k)[2]
833                vh = f(t, point_id = k)[3]
834                gaugeloc = locations[k]
835                depth = w-z
836               
837                m = sqrt(uh*uh + vh*vh)   
838                vel = m / (depth + 1.e-30) 
839                bearing = calc_bearing(uh, vh)
840
841                model_time.append(t)       
842                stages.append(w)
843                elevations.append(z)
844                xmom.append(uh)
845                ymom.append(vh)
846                momenta.append(m)
847                velocity.append(vel)
848                bearings.append(bearing)
849                depths.append(depth)
850
851                if depth > max_depth: max_depth = w-z
852                if m > max_momentum: max_momentum = m
853                if vel > max_velocity: max_velocity = vel
854
855        #### finished generating quantities #####
856               
857        #### generate figures ###
858        ion()
859        hold(False)
860
861        for i in range(len(plot_quantity)):
862            which_quantity = plot_quantity[i]
863            figure(i+1, frameon = False)
864            if which_quantity == 'depth':
[2836]865                plot(model_time, depths, '-')
[2795]866                units = 'm'
867            if which_quantity == 'stage':
[2836]868                plot(model_time, stages, '-')
[2795]869                units = 'm'
870            if which_quantity == 'momentum':
[2836]871                plot(model_time, momenta, '-')
[2795]872                units = 'm^2 / sec'
873            if which_quantity == 'xmomentum':
[2836]874                plot(model_time, xmom, '-')
[2795]875                units = 'm^2 / sec'
876            if which_quantity == 'ymomentum':
[2836]877                plot(model_time, ymom, '-')
[2795]878                units = 'm^2 / sec'
879            if which_quantity == 'velocity':
[2836]880                plot(model_time, velocity, '-')
[2795]881                units = 'm / sec'
882            if which_quantity == 'bearing':
883                due_east = 90.0*ones([len(model_time)])
884                due_west = 270.0*ones([len(model_time)])
[2836]885                plot(model_time, bearings, '-', model_time, due_west, '-.',
886                     model_time, due_east, '-.')
[2795]887                units = 'degrees from North'
888                ax = axis([time_min, time_max, 0, 360])
889                legend(('Bearing','West','East'))
890
891            xlabel('time (secs)')
892            ylabel('%s (%s)' %(which_quantity, units))
893
[2836]894            gaugeloc1 = gaugeloc.replace(' ','')
[2918]895            gaugeloc2 = gaugeloc1.replace('_','')
896            graphname = '%sgauge%s_%s' %(file_loc, gaugeloc2, which_quantity)
[2795]897
[2839]898            if report == True:
899
900                figdir = getcwd()+sep+'report_figures'+sep
901                if access(figdir,F_OK) == 0 :
902                    mkdir (figdir)
903                latex_file_loc = figdir.replace(sep,altsep)
904
905                # storing files in production directory
[2918]906                graphname_latex = '%sgauge%s%s%s' %(latex_file_loc, gaugeloc2, which_quantity, label_id2)
[2839]907                # giving location in latex output file
[2918]908                graphname_report = '%sgauge%s%s%s' %('report_figures'+altsep, gaugeloc2, which_quantity, label_id2)
[2839]909                       
[2918]910                label = '%s%sgauge%s' %(label_id2, which_quantity, gaugeloc2) 
911                caption = 'Time series for %s at %s gauge location' %(which_quantity, gaugeloc.replace('_',' '))
[2836]912                s = '\\begin{figure}[hbt] \n \\centerline{\includegraphics[width=100mm, height=75mm]{%s%s}} \n' %(graphname_report, '.png')
[2795]913                fid.write(s)
914                s = '\\caption{%s} \n \label{fig:%s} \n \end{figure} \n \n' %(caption, label)
915                fid.write(s)
[2918]916                c += 1
917                if c % 10 == 0: fid.write('\\clearpage \n')
[2839]918                savefig(graphname_latex) # save figures in production directory for report generation
[2799]919           
[2839]920            if title_on == True:
921                title('%s scenario: %s at %s gauge' %(label_id, which_quantity, gaugeloc))
922
923            savefig(graphname) # save figures with sww file
924
925   
[2795]926        thisfile = file_loc+sep+'gauges_time_series'+'_'+gaugeloc+'.csv'
927        fid_out = open(thisfile, 'w')
928        s = 'Time, Depth, Momentum, Velocity \n'
929        fid_out.write(s)
930        for i_t, i_d, i_m, i_vel in zip(model_time, depths, momenta, velocity):
931            s = '%.2f, %.2f, %.2f, %.2f\n' %(i_t, i_d, i_m, i_vel)
932            fid_out.write(s)
933           
934        #### finished generating figures ###
935
936    close('all')
937   
[2836]938    return texfile
Note: See TracBrowser for help on using the repository browser.