source: inundation/pyvolution/util.py @ 2908

Last change on this file since 2908 was 2908, checked in by sexton, 18 years ago

changes to plotting polygons

File size: 30.6 KB
Line 
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
8import utilities.polygon
9from warnings import warn
10
11
12
13def file_function(filename,
14                  domain = None,
15                  quantities = None,
16                  interpolation_points = None,
17                  verbose = False,
18                  use_cache = False):
19    """Read time history of spatial data from NetCDF file and return
20    a callable object.
21
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
29
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)
32
33       Either form will return interpolated values based on the input file
34       using the underlying interpolation_function.
35
36    domain - Associated domain object   
37       If domain is specified, model time (domain.starttime)
38       will be checked and possibly modified.
39   
40       All times are assumed to be in UTC
41       
42       All spatial information is assumed to be in absolute UTM coordinates.
43
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 
47
48    interpolation_points - list of absolute UTM coordinates for points at
49    which values are sought
50   
51    use_cache: True means that caching of intermediate result of
52               Interpolation_function is attempted
53
54   
55    See Interpolation function for further documentation
56    """
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
97   
98    See file_function for documentatiton
99    """
100   
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.
105    #If we use the suggested Point_set class for interpolation points
106    #here it would be easier
107
108    #Take into account:
109    #- domain's georef
110    #- sww file's georef
111    #- interpolation points as absolute UTM coordinates
112
113
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,
135                                        interpolation_points,
136                                        verbose = verbose)
137    else:
138        raise 'Must be a NetCDF File'
139
140
141
142def get_netcdf_file_function(filename,
143                             domain=None,
144                             quantity_names=None,
145                             interpolation_points=None,
146                             verbose = False):
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
168    #FIXME: Maybe move caching out to this level rather than at the
169    #Interpolation_function level (below)
170
171    import time, calendar, types
172    from config import time_format
173    from Scientific.IO.NetCDF import NetCDFFile
174    from Numeric import array, zeros, Float, alltrue, concatenate, reshape
175    from utilities.numerical_tools import ensure_numeric   
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:
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
188        quantity_names = []
189        for name in fid.variables.keys():
190            if name not in ['x', 'y', 'time']:
191                quantity_names.append(name)
192
193    if len(quantity_names) < 1:               
194        msg = 'ERROR: At least one independent value must be specified'
195        raise msg
196
197
198    if interpolation_points is not None:
199        interpolation_points = ensure_numeric(interpolation_points, Float)
200
201
202
203    #Now assert that requested quantitites (and the independent ones)
204    #are present in file
205    missing = []
206    for quantity in ['time'] + quantity_names:
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
222    if filename[-3:] == 'tms' and spatial is True:
223        msg = 'Files of type tms must not contain spatial information'
224        raise msg
225
226    if filename[-3:] == 'sww' and spatial is False:
227        msg = 'Files of type sww must contain spatial information'       
228        raise msg       
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]
245        zone = fid.zone[0]       
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
255        if interpolation_points is not None:
256            #Adjust for georef
257            interpolation_points[:,0] -= xllcorner
258            interpolation_points[:,1] -= yllcorner       
259       
260
261
262
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
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       
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
308    #from least_squares import Interpolation_function
309    from fit_interpolate.interpolate import Interpolation_function
310
311    if not spatial:
312        vertex_coordinates = triangles = interpolation_points = None         
313
314
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
327def multiple_replace(text, dictionary):
328    """Multiple replace of words in text
329
330    text:       String to be modified
331    dictionary: Mapping of words that are to be substituted
332
333    Python Cookbook 3.14 page 88 and page 90
334    """
335
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' )
343
344    #For each match, lookup the corresponding value in the dictionary
345    return regex.sub(lambda match: dictionary[match.group(0)], text)
346
347
348
349
350def apply_expression_to_dictionary(expression, dictionary):#dictionary):
351    """Apply arbitrary expression to values of dictionary
352
353    Given an expression in terms of the keys, replace key by the
354    corresponding values and evaluate.
355   
356
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
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.
368    """
369
370    import types
371    import re
372
373    assert isinstance(expression, basestring)
374    assert type(dictionary) == types.DictType
375
376    #Convert dictionary values to textual representations suitable for eval
377    D = {}
378    for key in dictionary:
379        D[key] = 'dictionary["%s"]' %key
380
381    #Perform substitution of variables   
382    expression = multiple_replace(expression, D)
383
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
390    except ValueError, e:
391        msg = 'Expression "%s" could not be evaluated: %s' %(expression, e)
392        raise ValueError, msg
393   
394
395
396
397####################################
398####OBSOLETE STUFF
399
400
401def angle(v1, v2):
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
410    return NT.angle(v1, v2)
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
435def point_on_line(*args, **kwargs):
436    """Temporary Interface to new location"""
437
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) 
441
442    return utilities.polygon.point_on_line(*args, **kwargs)     
443   
444def inside_polygon(*args, **kwargs):
445    """Temporary Interface to new location"""
446
447    print 'inside_polygon has moved from util.py.  ',
448    print 'Please use "from utilities.polygon import inside_polygon"'
449
450    return utilities.polygon.inside_polygon(*args, **kwargs)   
451   
452def outside_polygon(*args, **kwargs):
453    """Temporary Interface to new location"""
454
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
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):
496        self.data = ''
497        self.filename = filename
498
499    def write(self, stuff):
500        fid = open(self.filename, 'w')
501        self.data = self.data + stuff
502        fid.write(self.data)
503        fid.close()
504
505
506   
507def sww2timeseries(swwfile,
508                   gauge_filename,
509                   label_id,
510                   report = None,
511                   plot_quantity = None,
512                   time_min = None,
513                   time_max = None,
514                   title_on = None,
515                   verbose = False):
516   
517    """ Read sww file and plot the time series for the
518    prescribed quantities at defined gauge locations and
519    prescribed time range.
520
521    Input variables:
522
523    swwfile         - name of sww file
524                    - assume that all conserved quantities have been stored
525                   
526    gauge_filename  - name of file containing gauge data
527                        - name, easting, northing
528                    - OR (this is not yet done)
529                        - structure which can be converted to a Numeric array,
530                          such as a geospatial data object
531                     
532    label_id        - used in generating latex output. It will be part of
533                      the directory name of file_loc (typically the timestamp).
534                      Helps to differentiate latex files for different simulations
535                      for a particular scenario.
536                     
537    report          - if True, then write figures to report_figures directory in
538                      relevant production directory
539                    - if False, figures are already stored with sww file
540                    - default to False
541   
542    plot_quantity   - list containing quantities to plot, they must
543                      be the name of an existing quantity or one of
544                      the following possibilities
545                    - possibilities:
546                        - stage; 'stage'
547                        - depth; 'depth'
548                        - velocity; calculated as absolute momentum
549                         (pointwise) divided by depth; 'velocity'
550                        - bearing; calculated as the angle of the momentum
551                          vector (xmomentum, ymomentum) from the North; 'bearing'
552                        - absolute momentum; calculated as
553                          sqrt(xmomentum^2 + ymomentum^2); 'momentum'
554                        - x momentum; 'xmomentum'
555                        - y momentum; 'ymomentum'
556                    - default will be ['stage', 'velocity', 'bearing']
557
558    time_min         - beginning of user defined time range for plotting purposes
559                        - default will be first available time found in swwfile
560                       
561    time_max         - end of user defined time range for plotting purposes
562                        - default will be last available time found in swwfile
563                       
564    title_on        - if True, export standard graphics with title
565                    - if False, export standard graphics without title
566
567
568                     
569    Output:
570   
571    - time series data stored in .csv for later use if required.
572      Name = gauges_timeseries followed by gauge name
573    - latex file will be generated in same directory as where script is
574      run (usually production scenario directory.
575      Name = latexoutputlabel_id.tex
576
577    Other important information:
578   
579    It is assumed that the used has stored all the conserved quantities
580    and elevation during the scenario run, i.e.
581    ['stage', 'elevation', 'xmomentum', 'ymomentum']
582    If this has not occurred then sww2timeseries will not work.
583                     
584    """
585
586   
587    k = _sww2timeseries(swwfile,
588                        gauge_filename,
589                        label_id,
590                        report,
591                        plot_quantity,
592                        time_min,
593                        time_max,
594                        title_on,
595                        verbose)
596
597    return k
598
599def _sww2timeseries(swwfile,
600                    gauge_filename,
601                    label_id,
602                    report = None,
603                    plot_quantity = None,
604                    time_min = None,
605                    time_max = None,
606                    title_on = None,
607                    verbose = False):   
608
609    assert type(swwfile) == type(''),\
610               'The sww filename must be a string'
611
612    try:
613        fid = open(swwfile)
614    except Exception, e:
615        msg = 'File "%s" could not be opened: Error="%s"'\
616                  %(swwfile, e)
617        raise msg
618
619    index = swwfile.rfind(sep)
620    file_loc = swwfile[:index+1]
621       
622    assert type(gauge_filename) == type(''),\
623               'Gauge filename must be a string'
624   
625    try:
626        fid = open(gauge_filename)
627    except Exception, e:
628        msg = 'File "%s" could not be opened: Error="%s"'\
629                  %(gauge_filename, e)
630        raise msg
631
632    if report is None:
633        report = False
634       
635    assert type(plot_quantity) == list,\
636               'plot_quantity must be a list'
637   
638    if plot_quantity is None:
639        plot_quantity = ['depth', 'velocity', 'bearing']
640    else:
641        check_list(plot_quantity)
642
643    if title_on is None:
644        title_on = True
645     
646    assert type(label_id) == type(''),\
647               'label_id to sww2timeseries must be a string'
648   
649    if verbose: print '\n Gauges obtained from: %s \n' %gauge_filename
650    gauges, locations = get_gauges_from_file(gauge_filename)
651
652    sww_quantity = ['stage', 'elevation', 'xmomentum', 'ymomentum']
653
654    f = file_function(swwfile,
655                      quantities = sww_quantity,
656                      interpolation_points = gauges,
657                      verbose = True,
658                      use_cache = True)
659
660    T = f.get_time()
661
662    if max(f.quantities['xmomentum']) > 1.e10:
663        msg = 'Not all conserved quantities available from sww file. \n sww2timeseries requires all conserved quantities stored in sww file'
664        raise Exception, msg
665       
666    if time_min is None:
667        time_min = min(T)
668    else:
669        if time_min < min(T):
670            msg = 'Minimum time entered not correct - please try again'
671            raise Exception, msg
672
673    if time_max is None:
674        time_max = max(T)
675    else:
676        if time_max > max(T):
677            msg = 'Maximum time entered not correct - please try again'
678            raise Exception, msg
679
680    if verbose: print 'Inputs OK - going to generate figures'
681
682    return generate_figures(plot_quantity, file_loc, report,
683                            f, gauges, locations,
684                            time_min, time_max, title_on, label_id, verbose)
685                         
686
687def get_gauges_from_file(filename):
688    fid = open(filename)
689    lines = fid.readlines()
690    fid.close()
691   
692    gauges = []
693    gaugelocation = []
694    line1 = lines[0]
695    line11 = line1.split(',')
696    for i in range(len(line11)):
697        if line11[i].strip('\n').strip(' ') == 'Easting': east_index = i
698        if line11[i].strip('\n').strip(' ') == 'Northing': north_index = i
699        if line11[i].strip('\n').strip(' ') == 'Name': name_index = i
700   
701    for line in lines[1:]:
702        fields = line.split(',')
703        gauges.append([float(fields[east_index]), float(fields[north_index])])
704        loc = fields[name_index]
705        gaugelocation.append(loc.strip('\n'))
706   
707    return gauges, gaugelocation
708
709def check_list(quantity):
710
711    all_quantity = ['stage', 'depth', 'momentum', 'xmomentum',
712                    'ymomentum', 'velocity', 'bearing', 'elevation']
713
714    p = list(set(quantity).difference(set(all_quantity)))
715    if len(p) <> 0:
716        msg = 'Quantities %s do not exist - please try again' %p
717        raise Exception, msg
718       
719    return 
720
721def calc_bearing(uh, vh):
722
723    from math import atan, degrees
724   
725    angle = degrees(atan(vh/(uh+1.e-15)))
726    if (0 < angle < 90.0):
727        if vh > 0:
728            bearing = 90.0 - abs(angle)
729        if vh < 0:
730            bearing = 270.0 - abs(angle)
731    if (-90 < angle < 0):
732        if vh < 0:
733            bearing = 90.0 - abs(angle)
734        if vh > 0:
735            bearing = 270.0 - abs(angle)
736    if angle == 0: bearing = 0.0
737           
738    return bearing
739
740def generate_figures(plot_quantity, file_loc, report, f, gauges,
741                     locations, time_min, time_max, title_on, label_id, verbose):
742
743    from math import sqrt, atan, degrees
744    from Numeric import ones
745    from os import sep, altsep, getcwd, mkdir, access, F_OK, environ
746    from pylab import ion, hold, plot, axis, figure, legend, savefig, xlabel, ylabel, title, close
747
748    filename = file_loc.split(sep)
749       
750    if report == True:
751        label_id1 = label_id.replace(sep,'')
752        label_id2 = label_id1.replace('_','')
753        texfile = 'latexoutput%s' %(label_id2)
754        texfilename = texfile + '.tex' 
755        if verbose: print '\n Latex output printed to %s \n' %texfilename
756
757        fid = open(texfilename, 'w')
758        s = '\\begin{center} \n \\begin{tabular}{|l|l|l|}\hline \n \\bf{Gauge Name} & \\bf{Easting} & \\bf{Northing} \\\\ \hline \n'
759        fid.write(s)
760        gauges1 = gauges
761        for name, gauges1 in zip(locations, gauges1):
762            east = gauges1[0]
763            north = gauges1[1]
764            s = '%s & %.2f & %.2f \\\\ \hline \n' %(name, east, north)
765            fid.write(s)
766
767        s = '\\end{tabular} \n \\end{center} \n \n'
768        fid.write(s)
769    else:
770        texfile = ''
771   
772    ##### loop over each gauge #####
773    for k, g in enumerate(gauges):
774        if verbose: print 'Gauge %d of %d' %(k, len(gauges))
775        model_time = []
776        stages = []
777        elevations = []
778        momenta = []
779        xmom = []
780        ymom = []
781        velocity = []
782        bearings = []
783        depths = []
784        max_depth = 0
785        max_momentum = 0
786        max_velocity = 0     
787       
788        #### generate quantities #######
789        for i, t in enumerate(f.get_time()): 
790
791            if time_min <= t <= time_max:
792
793                w = f(t, point_id = k)[0]
794                z = f(t, point_id = k)[1]
795                uh = f(t, point_id = k)[2]
796                vh = f(t, point_id = k)[3]
797                gaugeloc = locations[k]
798                depth = w-z
799               
800                m = sqrt(uh*uh + vh*vh)   
801                vel = m / (depth + 1.e-30) 
802                bearing = calc_bearing(uh, vh)
803
804                model_time.append(t)       
805                stages.append(w)
806                elevations.append(z)
807                xmom.append(uh)
808                ymom.append(vh)
809                momenta.append(m)
810                velocity.append(vel)
811                bearings.append(bearing)
812                depths.append(depth)
813
814                if depth > max_depth: max_depth = w-z
815                if m > max_momentum: max_momentum = m
816                if vel > max_velocity: max_velocity = vel
817
818        #### finished generating quantities #####
819               
820        #### generate figures ###
821        ion()
822        hold(False)
823
824        for i in range(len(plot_quantity)):
825            which_quantity = plot_quantity[i]
826            figure(i+1, frameon = False)
827            if which_quantity == 'depth':
828                plot(model_time, depths, '-')
829                units = 'm'
830            if which_quantity == 'stage':
831                plot(model_time, stages, '-')
832                units = 'm'
833            if which_quantity == 'momentum':
834                plot(model_time, momenta, '-')
835                units = 'm^2 / sec'
836            if which_quantity == 'xmomentum':
837                plot(model_time, xmom, '-')
838                units = 'm^2 / sec'
839            if which_quantity == 'ymomentum':
840                plot(model_time, ymom, '-')
841                units = 'm^2 / sec'
842            if which_quantity == 'velocity':
843                plot(model_time, velocity, '-')
844                units = 'm / sec'
845            if which_quantity == 'bearing':
846                due_east = 90.0*ones([len(model_time)])
847                due_west = 270.0*ones([len(model_time)])
848                plot(model_time, bearings, '-', model_time, due_west, '-.',
849                     model_time, due_east, '-.')
850                units = 'degrees from North'
851                ax = axis([time_min, time_max, 0, 360])
852                legend(('Bearing','West','East'))
853
854            xlabel('time (secs)')
855            ylabel('%s (%s)' %(which_quantity, units))
856
857            gaugeloc1 = gaugeloc.replace(' ','')
858            graphname = '%sgauge%s_%s' %(file_loc, gaugeloc1, which_quantity)
859
860            if report == True:
861
862                figdir = getcwd()+sep+'report_figures'+sep
863                if access(figdir,F_OK) == 0 :
864                    mkdir (figdir)
865                latex_file_loc = figdir.replace(sep,altsep)
866
867                # storing files in production directory
868                graphname_latex = '%sgauge%s%s%s' %(latex_file_loc, gaugeloc1, which_quantity, label_id2)
869                # giving location in latex output file
870                graphname_report = '%sgauge%s%s%s' %('report_figures'+altsep, gaugeloc1, which_quantity, label_id2)
871                       
872                label = '%s%sgauge%s' %(label_id2, which_quantity, gaugeloc1) 
873                caption = 'Time series for %s at %s gauge location' %(which_quantity, gaugeloc)
874                s = '\\begin{figure}[hbt] \n \\centerline{\includegraphics[width=100mm, height=75mm]{%s%s}} \n' %(graphname_report, '.png')
875                fid.write(s)
876                s = '\\caption{%s} \n \label{fig:%s} \n \end{figure} \n \n' %(caption, label)
877                fid.write(s)
878                savefig(graphname_latex) # save figures in production directory for report generation
879           
880            if title_on == True:
881                title('%s scenario: %s at %s gauge' %(label_id, which_quantity, gaugeloc))
882
883            savefig(graphname) # save figures with sww file
884
885   
886        thisfile = file_loc+sep+'gauges_time_series'+'_'+gaugeloc+'.csv'
887        fid_out = open(thisfile, 'w')
888        s = 'Time, Depth, Momentum, Velocity \n'
889        fid_out.write(s)
890        for i_t, i_d, i_m, i_vel in zip(model_time, depths, momenta, velocity):
891            s = '%.2f, %.2f, %.2f, %.2f\n' %(i_t, i_d, i_m, i_vel)
892            fid_out.write(s)
893           
894        #### finished generating figures ###
895
896    close('all')
897   
898    return texfile
899
900def plot_polygons(bounding_polygon,
901                  interior_polygon,
902                  figname,
903                  verbose = False):
904   
905    """ Take bounding and interior polygons and plot.
906
907    Inputs:
908
909    bounding_polygon - polygon used in create_mesh_from_regions
910   
911    interior_polygon - list of polygons used in create_mesh_from_regions
912                       
913    figname          - name to save figure to
914                   
915    """
916
917   
918    k = _plot_polygons(bounding_polygon,
919                       interior_polygon,
920                       figname,
921                       verbose)
922
923    return k
924
925def _plot_polygons(bounding_polygon,
926                   interior_polygon,
927                   figname,
928                   verbose = False):   
929
930    from pylab import ion, hold, plot, axis, figure, legend, savefig, xlabel, ylabel, title, close
931
932    assert type(bounding_polygon) == list,\
933               'bounding_polygon must be a list'
934
935    assert type(interior_polygon) == list,\
936               'interior_polygon must be a list'
937
938    ion()
939    hold(True)
940
941    x_bound, y_bound = poly_xy(bounding_polygon)
942   
943    for i in range(len(interior_polygon)):
944        x_int, y_int = poly_xy(interior_polygon[i])
945        plot(x_bound,y_bound,'r-',x_int,y_int,'r-')
946        xlabel('x')
947        ylabel('y')
948
949    savefig(figname)
950
951    close('all')
952
953    return
954
955def poly_xy(poly):
956    x = []
957    y = []
958    n = len(poly)
959    for i in range(n+1):
960        if i == n:
961            thispt = poly[0]
962        else:
963            thispt = poly[i]
964        x.append(thispt[0])
965        y.append(thispt[1])
966
967    return x, y
Note: See TracBrowser for help on using the repository browser.