source: anuga_core/source/anuga/abstract_2d_finite_volumes/util.py @ 4312

Last change on this file since 4312 was 4312, checked in by ole, 17 years ago

Created new boundary class: Field_boundary designed to replace the generic File_boundary. Field_boundary is specific to the shallow water wave equation and allows mean_stage to be specified adjusting the stage derived from the sww. This should address ticket:132.
On test was added, two updated.

File size: 51.8 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
7import anuga.utilities.polygon
8import sys
9import os
10
11from os import remove, mkdir, access, F_OK, W_OK, sep
12from os.path import exists, basename
13from warnings import warn
14from shutil import copy
15
16from anuga.geospatial_data.geospatial_data import ensure_absolute
17
18def file_function(filename,
19                  domain=None,
20                  quantities=None,
21                  interpolation_points=None,
22                  time_thinning=1,
23                  verbose=False,
24                  use_cache=False):
25    """Read time history of spatial data from NetCDF file and return
26    a callable object.
27
28    Input variables:
29   
30    filename - Name of sww or tms file
31       
32       If the file has extension 'sww' then it is assumed to be spatio-temporal
33       or temporal and the callable object will have the form f(t,x,y) or f(t)
34       depending on whether the file contains spatial data
35
36       If the file has extension 'tms' then it is assumed to be temporal only
37       and the callable object will have the form f(t)
38
39       Either form will return interpolated values based on the input file
40       using the underlying interpolation_function.
41
42    domain - Associated domain object   
43       If domain is specified, model time (domain.starttime)
44       will be checked and possibly modified.
45   
46       All times are assumed to be in UTC
47       
48       All spatial information is assumed to be in absolute UTM coordinates.
49
50    quantities - the name of the quantity to be interpolated or a
51                 list of quantity names. The resulting function will return
52                 a tuple of values - one for each quantity 
53
54    interpolation_points - list of absolute UTM coordinates for points (N x 2)
55    or geospatial object or points file name at which values are sought
56   
57    use_cache: True means that caching of intermediate result of
58               Interpolation_function is attempted
59
60   
61    See Interpolation function for further documentation
62    """
63
64
65    # Build arguments and keyword arguments for use with caching or apply.
66    args = (filename,)
67   
68    kwargs = {'domain': domain,
69              'quantities': quantities,
70              'interpolation_points': interpolation_points,
71              'time_thinning': time_thinning,                   
72              'verbose': verbose,
73              'use_cache': use_cache
74              }
75
76    #caching moved to deeper within the function to avoid caching an
77    #instance of an object, which isn't generally good.
78    f = apply(_file_function,
79                  args, kwargs)
80
81
82    #FIXME (Ole): Pass cache arguments, such as compression, in some sort of
83    #structure
84       
85
86    return f
87
88
89
90def _file_function(filename,
91                   domain=None,
92                   quantities=None,
93                   interpolation_points=None,
94                   time_thinning=1, 
95                   verbose=False,
96                   use_cache=False):
97    """Internal function
98   
99    See file_function for documentatiton
100    """
101   
102
103    #FIXME (OLE): Should check origin of domain against that of file
104    #In fact, this is where origin should be converted to that of domain
105    #Also, check that file covers domain fully.
106
107    #Take into account:
108    #- domain's georef
109    #- sww file's georef
110    #- interpolation points as absolute UTM coordinates
111
112
113    assert type(filename) == type(''),\
114               'First argument to File_function must be a string'
115
116    try:
117        fid = open(filename)
118    except Exception, e:
119        msg = 'File "%s" could not be opened: Error="%s"'\
120                  %(filename, e)
121        raise msg
122
123    line = fid.readline()
124    fid.close()
125
126    if quantities is None: 
127        if domain is not None:
128            quantities = domain.conserved_quantities
129
130
131
132    if line[:3] == 'CDF':
133        return get_netcdf_file_function(filename, domain, quantities,
134                                        interpolation_points,
135                                        time_thinning=time_thinning,
136                                        verbose=verbose,
137                                        use_cache=use_cache)
138    else:
139        raise 'Must be a NetCDF File'
140
141
142
143def get_netcdf_file_function(filename,
144                             domain=None,
145                             quantity_names=None,
146                             interpolation_points=None,
147                             time_thinning=1,                             
148                             verbose=False,
149                             use_cache=False):
150    """Read time history of spatial data from NetCDF sww file and
151    return a callable object f(t,x,y)
152    which will return interpolated values based on the input file.
153
154    If domain is specified, model time (domain.starttime)
155    will be checked and possibly modified
156   
157    All times are assumed to be in UTC
158
159    See Interpolation function for further documetation
160   
161    """
162   
163   
164    #FIXME: Check that model origin is the same as file's origin
165    #(both in UTM coordinates)
166    #If not - modify those from file to match domain
167    #Take this code from e.g. dem2pts in data_manager.py
168    #FIXME: Use geo_reference to read and write xllcorner...
169       
170
171    #FIXME: Maybe move caching out to this level rather than at the
172    #Interpolation_function level (below)
173
174    import time, calendar, types
175    from anuga.config import time_format
176    from Scientific.IO.NetCDF import NetCDFFile
177    from Numeric import array, zeros, Float, alltrue, concatenate, reshape
178
179    #Open NetCDF file
180    if verbose: print 'Reading', filename
181    fid = NetCDFFile(filename, 'r')
182
183    if type(quantity_names) == types.StringType:
184        quantity_names = [quantity_names]       
185   
186    if quantity_names is None or len(quantity_names) < 1:
187        #If no quantities are specified get quantities from file
188        #x, y, time are assumed as the independent variables so
189        #they are excluded as potentiol quantities
190        quantity_names = []
191        for name in fid.variables.keys():
192            if name not in ['x', 'y', 'time']:
193                quantity_names.append(name)
194
195    if len(quantity_names) < 1:               
196        msg = 'ERROR: At least one independent value must be specified'
197        raise msg
198
199
200    if interpolation_points is not None:
201        interpolation_points = ensure_absolute(interpolation_points)
202        msg = 'Points must by N x 2. I got %d' %interpolation_points.shape[1]
203        assert interpolation_points.shape[1] == 2, msg
204
205
206    #Now assert that requested quantitites (and the independent ones)
207    #are present in file
208    missing = []
209    for quantity in ['time'] + quantity_names:
210        if not fid.variables.has_key(quantity):
211            missing.append(quantity)
212
213    if len(missing) > 0:
214        msg = 'Quantities %s could not be found in file %s'\
215              %(str(missing), filename)
216        fid.close()
217        raise Exception, msg
218
219    #Decide whether this data has a spatial dimension
220    spatial = True
221    for quantity in ['x', 'y']:
222        if not fid.variables.has_key(quantity):
223            spatial = False
224
225    if filename[-3:] == 'tms' and spatial is True:
226        msg = 'Files of type tms must not contain spatial information'
227        raise msg
228
229    if filename[-3:] == 'sww' and spatial is False:
230        msg = 'Files of type sww must contain spatial information'       
231        raise msg       
232
233    #Get first timestep
234    try:
235        starttime = fid.starttime[0]
236    except ValueError:
237        msg = 'Could not read starttime from file %s' %filename
238        raise msg
239
240    #Get variables
241    #if verbose: print 'Get variables'   
242    time = fid.variables['time'][:]   
243
244    # Get time independent stuff
245    if spatial:
246        #Get origin
247        xllcorner = fid.xllcorner[0]
248        yllcorner = fid.yllcorner[0]
249        zone = fid.zone[0]       
250
251        x = fid.variables['x'][:]
252        y = fid.variables['y'][:]
253        triangles = fid.variables['volumes'][:]
254
255        x = reshape(x, (len(x),1))
256        y = reshape(y, (len(y),1))
257        vertex_coordinates = concatenate((x,y), axis=1) #m x 2 array
258
259        if interpolation_points is not None:
260            #Adjust for georef
261            interpolation_points[:,0] -= xllcorner
262            interpolation_points[:,1] -= yllcorner       
263       
264
265
266
267    if domain is not None:
268        #Update domain.startime if it is *earlier* than starttime
269        if starttime > domain.starttime:
270            msg = 'WARNING: Start time as specified in domain (%f)'\
271                  %domain.starttime
272            msg += ' is earlier than the starttime of file %s (%f).'\
273                     %(filename, starttime)
274            msg += ' Modifying domain starttime accordingly.'
275           
276            if verbose: print msg
277            domain.starttime = starttime #Modifying model time
278            if verbose: print 'Domain starttime is now set to %f'\
279               %domain.starttime
280
281
282        #If domain.startime is *later* than starttime,
283        #move time back - relative to domain's time
284        if domain.starttime > starttime:
285            time = time - domain.starttime + starttime
286
287        #FIXME Use method in geo to reconcile
288        #if spatial:
289        #assert domain.geo_reference.xllcorner == xllcorner
290        #assert domain.geo_reference.yllcorner == yllcorner
291        #assert domain.geo_reference.zone == zone       
292       
293    if verbose:
294        print 'File_function data obtained from: %s' %filename
295        print '  References:'
296        #print '    Datum ....' #FIXME
297        if spatial:
298            print '    Lower left corner: [%f, %f]'\
299                  %(xllcorner, yllcorner)
300        print '    Start time:   %f' %starttime               
301       
302   
303    # Produce values for desired data points at
304    # each timestep for each quantity
305    quantities = {}
306    for i, name in enumerate(quantity_names):
307        quantities[name] = fid.variables[name][:]
308    fid.close()
309   
310
311    #from least_squares import Interpolation_function
312    from anuga.fit_interpolate.interpolate import Interpolation_function
313
314    if not spatial:
315        vertex_coordinates = triangles = interpolation_points = None         
316
317   
318 
319    args = (time, quantities, quantity_names, vertex_coordinates, 
320            triangles, interpolation_points, )
321           
322    kwargs = {'time_thinning': time_thinning,
323              'verbose': verbose
324              }
325   
326#    print'CACHING FROM UTIL.py for interpolation_function', use_cache
327#    from anuga.caching import myhash
328    if use_cache is True:
329        from caching import cache
330       
331        interpolation_function = cache(Interpolation_function,
332                                       args, kwargs,
333                                       verbose=verbose,
334                                       compression=False)
335    else:
336        interpolation_function = apply(Interpolation_function,
337                                       args, kwargs)
338#    print 'myhash', myhash(interpolation_function)
339    return interpolation_function
340
341
342
343
344def multiple_replace(text, dictionary):
345    """Multiple replace of words in text
346
347    text:       String to be modified
348    dictionary: Mapping of words that are to be substituted
349
350    Python Cookbook 3.14 page 88 and page 90
351    """
352
353    import re
354   
355    #Create a regular expression from all of the dictionary keys
356    #matching only entire words
357    regex = re.compile(r'\b'+ \
358                       r'\b|\b'.join(map(re.escape, dictionary.keys()))+ \
359                       r'\b' )
360
361    #For each match, lookup the corresponding value in the dictionary
362    return regex.sub(lambda match: dictionary[match.group(0)], text)
363
364
365
366
367def apply_expression_to_dictionary(expression, dictionary):#dictionary):
368    """Apply arbitrary expression to values of dictionary
369
370    Given an expression in terms of the keys, replace key by the
371    corresponding values and evaluate.
372   
373
374    expression: Arbitrary, e.g. arithmetric, expression relating keys
375                from dictionary.
376
377    dictionary: Mapping between symbols in expression and objects that
378                will be evaluated by expression.
379                Values in dictionary must support operators given in
380                expression e.g. by overloading
381
382    due to a limitation with Numeric, this can not evaluate 0/0
383    In general, the user can fix by adding 1e-30 to the numerator.
384    SciPy core can handle this situation.
385    """
386
387    import types
388    import re
389
390    assert isinstance(expression, basestring)
391    assert type(dictionary) == types.DictType
392
393    #Convert dictionary values to textual representations suitable for eval
394    D = {}
395    for key in dictionary:
396        D[key] = 'dictionary["%s"]' %key
397
398    #Perform substitution of variables   
399    expression = multiple_replace(expression, D)
400
401    #Evaluate and return
402    try:
403        return eval(expression)
404    except NameError, e:
405        msg = 'Expression "%s" could not be evaluated: %s' %(expression, e)
406        raise NameError, msg
407    except ValueError, e:
408        msg = 'Expression "%s" could not be evaluated: %s' %(expression, e)
409        raise ValueError, msg
410   
411
412
413
414####################################
415####OBSOLETE STUFF
416
417
418def angle(v1, v2):
419    """Temporary Interface to new location"""
420
421    import anuga.utilities.numerical_tools as NT       
422   
423    msg = 'angle has moved from util.py.  '
424    msg += 'Please use "from anuga.utilities.numerical_tools import angle"'
425    warn(msg, DeprecationWarning) 
426
427    return NT.angle(v1, v2)
428   
429def anglediff(v0, v1):
430    """Temporary Interface to new location"""
431
432    import anuga.utilities.numerical_tools as NT
433   
434    msg = 'anglediff has moved from util.py.  '
435    msg += 'Please use "from anuga.utilities.numerical_tools import anglediff"'
436    warn(msg, DeprecationWarning) 
437
438    return NT.anglediff(v0, v1)   
439
440   
441def mean(x):
442    """Temporary Interface to new location"""
443
444    import anuga.utilities.numerical_tools as NT   
445   
446    msg = 'mean has moved from util.py.  '
447    msg += 'Please use "from anuga.utilities.numerical_tools import mean"'
448    warn(msg, DeprecationWarning) 
449
450    return NT.mean(x)   
451
452def point_on_line(*args, **kwargs):
453    """Temporary Interface to new location"""
454
455    msg = 'point_on_line has moved from util.py.  '
456    msg += 'Please use "from anuga.utilities.polygon import point_on_line"'
457    warn(msg, DeprecationWarning) 
458
459    return utilities.polygon.point_on_line(*args, **kwargs)     
460   
461def inside_polygon(*args, **kwargs):
462    """Temporary Interface to new location"""
463
464    print 'inside_polygon has moved from util.py.  ',
465    print 'Please use "from anuga.utilities.polygon import inside_polygon"'
466
467    return utilities.polygon.inside_polygon(*args, **kwargs)   
468   
469def outside_polygon(*args, **kwargs):
470    """Temporary Interface to new location"""
471
472    print 'outside_polygon has moved from util.py.  ',
473    print 'Please use "from anuga.utilities.polygon import outside_polygon"'
474
475    return utilities.polygon.outside_polygon(*args, **kwargs)   
476
477
478def separate_points_by_polygon(*args, **kwargs):
479    """Temporary Interface to new location"""
480
481    print 'separate_points_by_polygon has moved from util.py.  ',
482    print 'Please use "from anuga.utilities.polygon import separate_points_by_polygon"'
483
484    return utilities.polygon.separate_points_by_polygon(*args, **kwargs)   
485
486
487
488def read_polygon(*args, **kwargs):
489    """Temporary Interface to new location"""
490
491    print 'read_polygon has moved from util.py.  ',
492    print 'Please use "from anuga.utilities.polygon import read_polygon"'
493
494    return utilities.polygon.read_polygon(*args, **kwargs)   
495
496
497def populate_polygon(*args, **kwargs):
498    """Temporary Interface to new location"""
499
500    print 'populate_polygon has moved from util.py.  ',
501    print 'Please use "from anuga.utilities.polygon import populate_polygon"'
502
503    return utilities.polygon.populate_polygon(*args, **kwargs)   
504
505##################### end of obsolete stuff ? ############
506
507def start_screen_catcher(dir_name, myid='', numprocs='', extra_info='',
508                         print_to_screen=False, verbose=False):
509    """
510    Used to store screen output and errors to file, if run on multiple
511    processes eachprocessor will have its own output and error file.
512   
513    extra_info - is used as a string that can identify outputs with another
514    string eg. '_other'
515    """
516
517    dir_name = dir_name
518    if access(dir_name,W_OK) == 0:
519        if verbose: print 'Make directory %s' %dir_name
520        if verbose: print "myid", myid
521        mkdir (dir_name,0777)
522    if myid <>'':
523        myid = '_'+str(myid)
524    if numprocs <>'':
525        numprocs = '_'+str(numprocs)
526    if extra_info <>'':
527        extra_info = '_'+str(extra_info)
528    screen_output_name = dir_name + "screen_output%s%s%s.txt" %(myid,numprocs,extra_info)
529    screen_error_name = dir_name + "screen_error%s%s%s.txt" %(myid,numprocs,extra_info)
530    print screen_output_name
531    #used to catch screen output to file
532    sys.stdout = Screen_Catcher(screen_output_name)
533    sys.stderr = Screen_Catcher(screen_error_name)
534
535class Screen_Catcher:
536    """this simply catches the screen output and stores it to file defined by
537    start_screen_catcher (above)
538    """
539   
540    def __init__(self, filename):
541        self.filename = filename
542 
543        if exists(self.filename)is True:
544            remove(self.filename)
545            print'Old existing file "%s" has been deleted' %(self.filename)
546
547    def write(self, stuff):
548        fid = open(self.filename, 'a')
549        fid.write(stuff)
550#        if print_to_screen: print stuff
551
552def get_revision_number():
553    """Get the version number of the SVN
554    NOTE: This requires that the command svn is on the system PATH
555    (simply aliasing svn to the binary will not work)
556    """
557
558    # Create dummy info
559    #info = 'Revision: Version info could not be obtained.'
560    #info += 'A command line version of svn must be availbable '
561    #info += 'on the system PATH, access to the subversion '
562    #info += 'repository is necessary and the output must '
563    #info += 'contain a line starting with "Revision:"'
564   
565
566    #FIXME (Ole): Change this so that svn info is attempted first.
567    # If that fails, try to read a stored file with that same info (this would be created by e.g. the release script). Failing that, throw an exception.
568
569    #FIXME (Ole): Move this and store_version_info to utilities
570
571
572    try:
573        from anuga.stored_version_info import version_info
574    except:
575       
576        # No file available - try using Subversion
577        try:
578            fid = os.popen('svn info')
579        except:
580            msg = 'No version info stored and command "svn" is not '
581            msg += 'recognised on the system PATH. What do you want me to do?'
582            raise Exception(msg)
583        else:
584            #print 'Got version from svn'           
585            version_info = fid.read()
586    else:
587        pass
588        #print 'Got version from file'
589
590           
591    for line in version_info.split('\n'):
592        if line.startswith('Revision:'):
593            break
594
595    fields = line.split(':')
596    msg = 'Keyword "Revision" was not found anywhere in text: %s' %version_info
597    assert fields[0].startswith('Revision'), msg           
598
599    try:
600        revision_number = int(fields[1])
601    except:
602        msg = 'Revision number must be an integer. I got %s' %fields[1]
603        msg += 'Check that the command svn is on the system path' 
604        raise Exception(msg)               
605       
606    return revision_number
607
608
609def store_version_info(destination_path='.', verbose=False):
610    """Obtain current version from Subversion and store it.
611   
612    Title: store_version_info()
613
614    Author: Ole Nielsen (Ole.Nielsen@ga.gov.au)
615
616    CreationDate: January 2006
617
618    Description:
619        This function obtains current version from Subversion and stores it
620        is a Python file named 'stored_version_info.py' for use with
621        get_version_info()
622
623        If svn is not available on the system PATH, an Exception is thrown
624    """
625
626    # Note (Ole): This function should not be unit tested as it will only
627    # work when running out of the sandpit. End users downloading the
628    # ANUGA distribution would see a failure.
629    #
630    # FIXME: This function should really only be used by developers (
631    # (e.g. for creating new ANUGA releases), so maybe it should move
632    # to somewhere else.
633   
634    import config
635
636    try:
637        fid = os.popen('svn info')
638    except:
639        msg = 'Command "svn" is not recognised on the system PATH'
640        raise Exception(msg)
641    else:   
642        txt = fid.read()
643        fid.close()
644
645
646        # Determine absolute filename
647        if destination_path[-1] != os.sep:
648            destination_path += os.sep
649           
650        filename = destination_path + config.version_filename
651
652        fid = open(filename, 'w')
653
654        docstring = 'Stored version info.\n\n'
655        docstring += 'This file provides the version for distributions '
656        docstring += 'that are not accessing Subversion directly.\n'
657        docstring += 'The file is automatically generated and should not '
658        docstring += 'be modified manually.\n'
659        fid.write('"""%s"""\n\n' %docstring)
660       
661        fid.write('version_info = """\n%s"""' %txt)
662        fid.close()
663
664
665        if verbose is True:
666            print 'Version info stored to %s' %filename
667           
668   
669def sww2timeseries(swwfiles,
670                   gauge_filename,
671                   production_dirs,
672                   report = None,
673                   reportname = None,
674                   plot_quantity = None,
675                   generate_fig = False,
676                   surface = None,
677                   time_min = None,
678                   time_max = None,
679                   title_on = None,
680                   use_cache = False,
681                   verbose = False):
682   
683    """ Read sww file and plot the time series for the
684    prescribed quantities at defined gauge locations and
685    prescribed time range.
686
687    Input variables:
688
689    swwfiles        - dictionary of sww files with label_ids (used in
690                      generating latex output. It will be part of
691                      the directory name of file_loc (typically the timestamp).
692                      Helps to differentiate latex files for different simulations
693                      for a particular scenario. 
694                    - assume that all conserved quantities have been stored
695                    - assume each sww file has been simulated with same timestep
696   
697    gauge_filename  - name of file containing gauge data
698                        - easting, northing, name , elevation?
699                    - OR (this is not yet done)
700                        - structure which can be converted to a Numeric array,
701                          such as a geospatial data object
702                     
703    production_dirs -  A list of list, example {20061101_121212: '1 in 10000',
704                                                'boundaries': 'urs boundary'}
705                      this will use the second part as the label and the first part
706                      as the ?
707                     
708    report          - if True, then write figures to report_figures directory in
709                      relevant production directory
710                    - if False, figures are already stored with sww file
711                    - default to False
712
713    reportname      - name for report if wishing to generate report
714   
715    plot_quantity   - list containing quantities to plot, they must
716                      be the name of an existing quantity or one of
717                      the following possibilities
718                    - possibilities:
719                        - stage; 'stage'
720                        - depth; 'depth'
721                        - speed; calculated as absolute momentum
722                         (pointwise) divided by depth; 'speed'
723                        - bearing; calculated as the angle of the momentum
724                          vector (xmomentum, ymomentum) from the North; 'bearing'
725                        - absolute momentum; calculated as
726                          sqrt(xmomentum^2 + ymomentum^2); 'momentum'
727                        - x momentum; 'xmomentum'
728                        - y momentum; 'ymomentum'
729                    - default will be ['stage', 'speed', 'bearing']
730
731    generate_fig     - if True, generate figures as well as csv files of quantities
732                     - if False, csv files created only
733                     
734    surface          - if True, then generate solution surface with 3d plot
735                       and save to current working directory
736                     - default = False
737   
738    time_min         - beginning of user defined time range for plotting purposes
739                        - default will be first available time found in swwfile
740                       
741    time_max         - end of user defined time range for plotting purposes
742                        - default will be last available time found in swwfile
743                       
744    title_on        - if True, export standard graphics with title
745                    - if False, export standard graphics without title
746
747
748                     
749    Output:
750   
751    - time series data stored in .csv for later use if required.
752      Name = gauges_timeseries followed by gauge name
753    - latex file will be generated in same directory as where script is
754      run (usually production scenario directory.
755      Name = latexoutputlabel_id.tex
756
757    Other important information:
758   
759    It is assumed that the used has stored all the conserved quantities
760    and elevation during the scenario run, i.e.
761    ['stage', 'elevation', 'xmomentum', 'ymomentum']
762    If this has not occurred then sww2timeseries will not work.
763    """
764
765   
766    k = _sww2timeseries(swwfiles,
767                        gauge_filename,
768                        production_dirs,
769                        report,
770                        reportname,
771                        plot_quantity,
772                        generate_fig,
773                        surface,
774                        time_min,
775                        time_max,
776                        title_on,
777                        use_cache,
778                        verbose)
779
780    return k
781
782def _sww2timeseries(swwfiles,
783                    gauge_filename,
784                    production_dirs,
785                    report = None,
786                    reportname = None,
787                    plot_quantity = None,
788                    generate_fig = False,
789                    surface = None,
790                    time_min = None,
791                    time_max = None,
792                    title_on = None,
793                    use_cache = False,
794                    verbose = False):   
795       
796    assert type(gauge_filename) == type(''),\
797           'Gauge filename must be a string'
798   
799    try:
800        fid = open(gauge_filename)
801    except Exception, e:
802        msg = 'File "%s" could not be opened: Error="%s"'\
803                  %(gauge_filename, e)
804        raise msg
805
806    if report is None:
807        report = False
808       
809    if plot_quantity is None:
810        plot_quantity = ['depth', 'speed']
811    else:
812        assert type(plot_quantity) == list,\
813               'plot_quantity must be a list'
814        check_list(plot_quantity)
815
816    if surface is None:
817        surface = False
818       
819    if title_on is None:
820        title_on = True
821   
822    if verbose: print '\n Gauges obtained from: %s \n' %gauge_filename
823    gauges, locations, elev = get_gauges_from_file(gauge_filename)
824
825    sww_quantity = ['stage', 'elevation', 'xmomentum', 'ymomentum']
826
827    file_loc = []
828    f_list = []
829    label_id = []
830    leg_label = []
831    themaxT = 0.0
832    theminT = 0.0
833   
834    for swwfile in swwfiles.keys():
835
836        try:
837            fid = open(swwfile)
838        except Exception, e:
839            msg = 'File "%s" could not be opened: Error="%s"'\
840                  %(swwfile, e)
841            raise msg
842
843        f = file_function(swwfile,
844                          quantities = sww_quantity,
845                          interpolation_points = gauges,
846                          verbose = True,
847                          use_cache = use_cache)
848
849        # determine which gauges are contained in sww file
850        count = 0
851        gauge_index = []
852        print 'swwfile', swwfile
853        for k, g in enumerate(gauges):
854            if f(0.0, point_id = k)[2] > 1.0e6:
855                count += 1
856                if count == 1: print 'Gauges not contained here:'
857                print locations[k]
858            else:
859                gauge_index.append(k)
860
861        if len(gauge_index) > 0:
862            print 'Gauges contained here: \n',
863        else:
864            print 'No gauges contained here. \n'
865        for i in range(len(gauge_index)):
866             print locations[gauge_index[i]]
867             
868        index = swwfile.rfind(sep)
869        file_loc.append(swwfile[:index+1])
870        label_id.append(swwfiles[swwfile])
871        leg_label.append(production_dirs[swwfiles[swwfile]])
872       
873        f_list.append(f)
874        maxT = max(f.get_time())
875        minT = min(f.get_time())
876        if maxT > themaxT: themaxT = maxT
877        if minT > theminT: theminT = minT
878
879    if time_min is None:
880        time_min = theminT # min(T)
881    else:
882        if time_min < theminT: # min(T):
883            msg = 'Minimum time entered not correct - please try again'
884            raise Exception, msg
885
886    if time_max is None:
887        time_max = themaxT # max(T)
888    else:
889        if time_max > themaxT: # max(T):
890            msg = 'Maximum time entered not correct - please try again'
891            raise Exception, msg
892
893    if verbose and len(gauge_index) > 0: print 'Inputs OK - going to generate figures'
894
895    if len(gauge_index) <> 0:
896        texfile, elev_output = generate_figures(plot_quantity, file_loc, report, reportname, surface,
897                                                leg_label, f_list, gauges, locations, elev, gauge_index,
898                                                production_dirs, time_min, time_max, title_on, label_id,
899                                                generate_fig, verbose)
900    else:
901        texfile = ''
902        elev_output = []
903
904    return texfile, elev_output
905                         
906
907
908#Fixme - Use geospatial to read this file - it's an xya file
909#Need to include other information into this filename, so xya + Name - required for report
910def get_gauges_from_file(filename):
911    """ Read in gauge information from file
912    """
913    from os import sep, getcwd, access, F_OK, mkdir
914    fid = open(filename)
915    lines = fid.readlines()
916    fid.close()
917   
918    gauges = []
919    gaugelocation = []
920    elev = []
921    line1 = lines[0]
922    line11 = line1.split(',')
923    east_index = len(line11)+1
924    north_index = len(line11)+1
925    name_index = len(line11)+1
926    elev_index = len(line11)+1
927    for i in range(len(line11)):
928        if line11[i].strip('\n').strip(' ').lower() == 'easting': east_index = i
929        if line11[i].strip('\n').strip(' ').lower() == 'northing': north_index = i
930        if line11[i].strip('\n').strip(' ').lower() == 'name': name_index = i
931        if line11[i].strip('\n').strip(' ').lower() == 'elevation': elev_index = i
932
933    for line in lines[1:]:
934        fields = line.split(',')
935        if east_index < len(line11) and north_index < len(line11):
936            gauges.append([float(fields[east_index]), float(fields[north_index])])
937        else:
938            msg = 'WARNING: %s does not contain location information' %(filename)
939            raise Exception, msg
940        if elev_index < len(line11): elev.append(float(fields[elev_index]))
941        if name_index < len(line11):
942            loc = fields[name_index]
943            gaugelocation.append(loc.strip('\n'))
944
945    return gauges, gaugelocation, elev
946
947def check_list(quantity):
948    """ Check that input quantities in quantity list are possible
949    """
950    all_quantity = ['stage', 'depth', 'momentum', 'xmomentum',
951                    'ymomentum', 'speed', 'bearing', 'elevation']
952
953       
954                   
955    import sys
956    #if not sys.version.startswith('2.4'):
957        # Backwards compatibility
958    #   from sets import Set as set
959
960    from sets import Set as set
961           
962    for i,j in enumerate(quantity):
963        quantity[i] = quantity[i].lower()
964    p = list(set(quantity).difference(set(all_quantity)))
965    if len(p) <> 0:
966        msg = 'Quantities %s do not exist - please try again' %p
967        raise Exception, msg
968       
969    return 
970
971def calc_bearing(uh, vh):
972    """ Calculate velocity bearing from North
973    """
974    from math import atan, degrees
975   
976    angle = degrees(atan(vh/(uh+1.e-15)))
977    if (0 < angle < 90.0):
978        if vh > 0:
979            bearing = 90.0 - abs(angle)
980        if vh < 0:
981            bearing = 270.0 - abs(angle)
982    if (-90 < angle < 0):
983        if vh < 0:
984            bearing = 90.0 - abs(angle)
985        if vh > 0:
986            bearing = 270.0 - abs(angle)
987    if angle == 0: bearing = 0.0
988           
989    return bearing
990
991def generate_figures(plot_quantity, file_loc, report, reportname, surface,
992                     leg_label, f_list, gauges, locations, elev, gauge_index,
993                     production_dirs, time_min, time_max, title_on, label_id,
994                     generate_fig, verbose):
995    """ Generate figures based on required quantities and gauges for each sww file
996    """
997    from math import sqrt, atan, degrees
998    from Numeric import ones, allclose, zeros, Float, ravel
999    from os import sep, altsep, getcwd, mkdir, access, F_OK, environ
1000
1001    if generate_fig is True:
1002        from pylab import ion, hold, plot, axis, figure, legend, savefig, \
1003             xlabel, ylabel, title, close, subplot
1004   
1005        if surface is True:
1006            import pylab as p1
1007            import mpl3d.mplot3d as p3
1008       
1009    if report == True:   
1010        texdir = getcwd()+sep+'report'+sep
1011        if access(texdir,F_OK) == 0:
1012            mkdir (texdir)
1013        if len(label_id) == 1:
1014            label_id1 = label_id[0].replace(sep,'')
1015            label_id2 = label_id1.replace('_','')
1016            texfile = texdir+reportname+'%s' %(label_id2)
1017            texfile2 = reportname+'%s' %(label_id2)
1018            texfilename = texfile + '.tex'
1019            if verbose: print '\n Latex output printed to %s \n' %texfilename
1020            fid = open(texfilename, 'w')
1021        else:
1022            texfile = texdir+reportname
1023            texfile2 = reportname
1024            texfilename = texfile + '.tex' 
1025            if verbose: print '\n Latex output printed to %s \n' %texfilename
1026            fid = open(texfilename, 'w')
1027    else:
1028        texfile = ''
1029        texfile2 = ''
1030
1031    p = len(f_list)
1032    n = []
1033    n0 = 0
1034    for i in range(len(f_list)):
1035        n.append(len(f_list[i].get_time()))
1036        if n[i] > n0: n0 = n[i] 
1037    n0 = int(n0)
1038    m = len(locations)
1039    model_time = zeros((n0,m,p), Float) 
1040    stages = zeros((n0,m,p), Float)
1041    elevations = zeros((n0,m,p), Float) 
1042    momenta = zeros((n0,m,p), Float)
1043    xmom = zeros((n0,m,p), Float)
1044    ymom = zeros((n0,m,p), Float)
1045    speed = zeros((n0,m,p), Float)
1046    bearings = zeros((n0,m,p), Float)
1047    depths = zeros((n0,m,p), Float)
1048    eastings = zeros((n0,m,p), Float)
1049    min_stages = []
1050    max_stages = []
1051    max_momentums = []
1052    max_speeds = []
1053    max_depths = []
1054    model_time_plot3d = zeros((n0,m), Float)
1055    stages_plot3d = zeros((n0,m), Float)
1056    eastings_plot3d = zeros((n0,m),Float)
1057    ##### loop over each swwfile #####
1058    for j, f in enumerate(f_list):
1059        if verbose: print 'swwfile %d of %d' %(j, len(f_list))
1060        comparefile = file_loc[j]+sep+'gauges_maxmins'+'.csv'
1061        fid_compare = open(comparefile, 'w')
1062        ##### loop over each gauge #####
1063        for k in gauge_index:
1064            g = gauges[k]
1065            if verbose: print 'Gauge %d of %d' %(k, len(gauges))
1066            min_stage = 10
1067            max_stage = 0
1068            max_momentum = 0
1069            max_speed = 0
1070            max_depth = 0
1071            gaugeloc = locations[k]
1072            thisfile = file_loc[j]+sep+'gauges_time_series'+'_'+gaugeloc+'.csv'
1073            fid_out = open(thisfile, 'w')
1074            s = 'Time, Stage, Momentum, Speed, Elevation, xmom, ymom \n'
1075            fid_out.write(s)
1076           
1077            #### generate quantities #######
1078            for i, t in enumerate(f.get_time()):
1079                if time_min <= t <= time_max:
1080                    w = f(t, point_id = k)[0]
1081                    z = f(t, point_id = k)[1]
1082                    uh = f(t, point_id = k)[2]
1083                    vh = f(t, point_id = k)[3]
1084                    depth = w-z     
1085                    m = sqrt(uh*uh + vh*vh)
1086                    if depth < 0.001:
1087                        vel = 0.0
1088                    else:
1089                        vel = m / (depth + 1.e-6/depth) 
1090                    #bearing = calc_bearing(uh, vh)
1091                    model_time[i,k,j] = t/60.0
1092                    stages[i,k,j] = w
1093                    elevations[i,k,j] = z
1094                    xmom[i,k,j] = uh
1095                    ymom[i,k,j] = vh
1096                    momenta[i,k,j] = m
1097                    speed[i,k,j] = vel
1098                    #bearings[i,k,j] = bearing
1099                    depths[i,k,j] = depth
1100                    thisgauge = gauges[k]
1101                    eastings[i,k,j] = thisgauge[0]
1102                    s = '%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n' %(t, w, m, vel, z, uh, vh)
1103                    fid_out.write(s)
1104                    if t/60.0 <= 13920: tindex = i
1105                    if w > max_stage: max_stage = w
1106                    if w < min_stage: min_stage = w
1107                    if m > max_momentum: max_momentum = m
1108                    if vel > max_speed: max_speed = vel
1109                    if z > 0 and depth > max_depth: max_depth = depth
1110                   
1111                   
1112            s = '%.2f, %.2f, %.2f, %.2f, %s\n' %(max_stage, min_stage, z, thisgauge[0], leg_label[j])
1113            fid_compare.write(s)
1114            max_stages.append(max_stage)
1115            min_stages.append(min_stage)
1116            max_momentums.append(max_momentum)
1117            max_speeds.append(max_speed)
1118            max_depths.append(max_depth)
1119            #### finished generating quantities for each swwfile #####
1120       
1121        model_time_plot3d[:,:] = model_time[:,:,j]
1122        stages_plot3d[:,:] = stages[:,:,j]
1123        eastings_plot3d[:,] = eastings[:,:,j]
1124           
1125        if surface is  True:
1126            print 'Printing surface figure'
1127            for i in range(2):
1128                fig = p1.figure(10)
1129                ax = p3.Axes3D(fig)
1130                if len(gauges) > 80:
1131                    ax.plot_surface(model_time[:,:,j],eastings[:,:,j],stages[:,:,j])
1132                else:
1133                    #ax.plot_wireframe(model_time[:,:,j],eastings[:,:,j],stages[:,:,j])
1134                    ax.plot3D(ravel(eastings[:,:,j]),ravel(model_time[:,:,j]),ravel(stages[:,:,j]))
1135                ax.set_xlabel('time')
1136                ax.set_ylabel('x')
1137                ax.set_zlabel('stage')
1138                fig.add_axes(ax)
1139                p1.show()
1140                surfacefig = 'solution_surface%s' %leg_label[j]
1141                p1.savefig(surfacefig)
1142                p1.close()
1143           
1144    #### finished generating quantities for all swwfiles #####
1145
1146    # x profile for given time
1147    if surface is True:
1148        figure(11)
1149        plot(eastings[tindex,:,j],stages[tindex,:,j])
1150        xlabel('x')
1151        ylabel('stage')
1152        profilefig = 'solution_xprofile' 
1153        savefig('profilefig')
1154
1155    elev_output = []
1156    if generate_fig is True:
1157        depth_axis = axis([time_min/60.0, time_max/60.0, -0.1, max(max_depths)*1.1])
1158        stage_axis = axis([time_min/60.0, time_max/60.0, min(min_stages), max(max_stages)*1.1])
1159        vel_axis = axis([time_min/60.0, time_max/60.0, min(max_speeds), max(max_speeds)*1.1])
1160        mom_axis = axis([time_min/60.0, time_max/60.0, min(max_momentums), max(max_momentums)*1.1])
1161        cstr = ['g', 'r', 'b', 'c', 'm', 'y', 'k']
1162        nn = len(plot_quantity)
1163        no_cols = 2
1164       
1165        if len(label_id) > 1: graphname_report = []
1166        pp = 1
1167        div = 11.
1168        cc = 0
1169        for k in gauge_index:
1170            g = gauges[k]
1171            count1 = 0
1172            if report == True and len(label_id) > 1:
1173                s = '\\begin{figure}[ht] \n \\centering \n \\begin{tabular}{cc} \n'
1174                fid.write(s)
1175            if len(label_id) > 1: graphname_report = []
1176            #### generate figures for each gauge ####
1177            for j, f in enumerate(f_list):
1178                ion()
1179                hold(True)
1180                count = 0
1181                where1 = 0
1182                where2 = 0
1183                word_quantity = ''
1184                if report == True and len(label_id) == 1:
1185                    s = '\\begin{figure}[hbt] \n \\centering \n \\begin{tabular}{cc} \n'
1186                    fid.write(s)
1187                   
1188                for which_quantity in plot_quantity:
1189                    count += 1
1190                    where1 += 1
1191                    figure(count, frameon = False)
1192                    if which_quantity == 'depth':
1193                        plot(model_time[0:n[j]-1,k,j], depths[0:n[j]-1,k,j], '-', c = cstr[j])
1194                        units = 'm'
1195                        axis(depth_axis)
1196                    if which_quantity == 'stage':
1197                        if elevations[0,k,j] < 0:
1198                            plot(model_time[0:n[j]-1,k,j], stages[0:n[j]-1,k,j], '-', c = cstr[j])
1199                            axis(stage_axis)
1200                        else:
1201                            plot(model_time[0:n[j]-1,k,j], depths[0:n[j]-1,k,j], '-', c = cstr[j])
1202                            #axis(depth_axis)                 
1203                        units = 'm'
1204                    if which_quantity == 'momentum':
1205                        plot(model_time[0:n[j]-1,k,j], momenta[0:n[j]-1,k,j], '-', c = cstr[j])
1206                        axis(mom_axis)
1207                        units = 'm^2 / sec'
1208                    if which_quantity == 'xmomentum':
1209                        plot(model_time[0:n[j]-1,k,j], xmom[0:n[j]-1,k,j], '-', c = cstr[j])
1210                        axis(mom_axis)
1211                        units = 'm^2 / sec'
1212                    if which_quantity == 'ymomentum':
1213                        plot(model_time[0:n[j]-1,k,j], ymom[0:n[j]-1,k,j], '-', c = cstr[j])
1214                        axis(mom_axis)
1215                        units = 'm^2 / sec'
1216                    if which_quantity == 'speed':
1217                        plot(model_time[0:n[j]-1,k,j], speed[0:n[j]-1,k,j], '-', c = cstr[j])
1218                        axis(vel_axis)
1219                        units = 'm / sec'
1220                    if which_quantity == 'bearing':
1221                        due_east = 90.0*ones(shape(model_time[0:n[j]-1,k,j],Float))
1222                        due_west = 270.0*ones(shape(model_time[0:n[j]-1,k,j],Float))
1223                        plot(model_time[0:n[j]-1,k,j], bearings, '-', 
1224                             model_time[0:n[j]-1,k,j], due_west, '-.', 
1225                             model_time[0:n[j]-1,k,j], due_east, '-.')
1226                        units = 'degrees from North'
1227                        ax = axis([time_min, time_max, 0.0, 360.0])
1228                        legend(('Bearing','West','East'))
1229
1230                    xlabel('time (mins)')
1231                    if which_quantity == 'stage' and elevations[0:n[j]-1,k,j] > 0:
1232                        ylabel('%s (%s)' %('depth', units))
1233                    else:
1234                        ylabel('%s (%s)' %(which_quantity, units))
1235                    if len(label_id) > 1: legend((leg_label),loc='upper right')
1236
1237                    gaugeloc1 = gaugeloc.replace(' ','')
1238                    #gaugeloc2 = gaugeloc1.replace('_','')
1239                    gaugeloc2 = locations[k].replace(' ','')
1240                    graphname = '%sgauge%s_%s' %(file_loc[j], gaugeloc2, which_quantity)
1241
1242                    if report == True and len(label_id) > 1:
1243                        figdir = getcwd()+sep+'report_figures'+sep
1244                        if access(figdir,F_OK) == 0 :
1245                            mkdir (figdir)
1246                        latex_file_loc = figdir.replace(sep,altsep) 
1247                        graphname_latex = '%sgauge%s%s' %(latex_file_loc, gaugeloc2, which_quantity) # storing files in production directory   
1248                        graphname_report_input = '%sgauge%s%s' %('..'+altsep+'report_figures'+altsep, gaugeloc2, which_quantity) # giving location in latex output file
1249                        graphname_report.append(graphname_report_input)
1250                       
1251                        savefig(graphname_latex) # save figures in production directory for report generation
1252
1253                    if report == True:
1254
1255                        figdir = getcwd()+sep+'report_figures'+sep
1256                        if access(figdir,F_OK) == 0 :
1257                            mkdir (figdir)
1258                        latex_file_loc = figdir.replace(sep,altsep)   
1259
1260                        if len(label_id) == 1: 
1261                            graphname_latex = '%sgauge%s%s%s' %(latex_file_loc, gaugeloc2, which_quantity, label_id2) # storing files in production directory 
1262                            graphname_report = '%sgauge%s%s%s' %('..'+altsep+'report_figures'+altsep, gaugeloc2, which_quantity, label_id2) # giving location in latex output file
1263                            s = '\includegraphics[width=0.49\linewidth, height=50mm]{%s%s}' %(graphname_report, '.png')
1264                            fid.write(s)
1265                            if where1 % 2 == 0:
1266                                s = '\\\\ \n'
1267                                where1 = 0
1268                            else:
1269                                s = '& \n'
1270                            fid.write(s)
1271                            savefig(graphname_latex)
1272                   
1273                    if title_on == True:
1274                        title('%s scenario: %s at %s gauge' %(label_id, which_quantity, gaugeloc2))
1275
1276                    savefig(graphname) # save figures with sww file
1277
1278                if report == True and len(label_id) == 1:
1279                    for i in range(nn-1):
1280                        if nn > 2:
1281                            if plot_quantity[i] == 'stage' and elevations[0,k,j] > 0:
1282                                word_quantity += 'depth' + ', '
1283                            else:
1284                                word_quantity += plot_quantity[i] + ', '
1285                        else:
1286                            if plot_quantity[i] == 'stage' and elevations[0,k,j] > 0:
1287                                word_quantity += 'depth' + ', '
1288                            else:
1289                                word_quantity += plot_quantity[i]
1290                       
1291                    if plot_quantity[nn-1] == 'stage' and elevations[0,k,j] > 0:
1292                        word_quantity += ' and ' + 'depth'
1293                    else:
1294                        word_quantity += ' and ' + plot_quantity[nn-1]
1295                    caption = 'Time series for %s at %s location (elevation %.2fm)' %(word_quantity, locations[k], elev[k]) #gaugeloc.replace('_',' '))
1296                    if elev[k] == 0.0:
1297                        caption = 'Time series for %s at %s location (elevation %.2fm)' %(word_quantity, locations[k], elevations[0,k,j])
1298                        east = gauges[0]
1299                        north = gauges[1]
1300                        elev_output.append([locations[k],east,north,elevations[0,k,j]])
1301                    label = '%sgauge%s' %(label_id2, gaugeloc2)
1302                    s = '\end{tabular} \n \\caption{%s} \n \label{fig:%s} \n \end{figure} \n \n' %(caption, label)
1303                    fid.write(s)
1304                    cc += 1
1305                    if cc % 6 == 0: fid.write('\\clearpage \n')
1306                    savefig(graphname_latex)               
1307                   
1308            if report == True and len(label_id) > 1:
1309                for i in range(nn-1):
1310                    if nn > 2:
1311                        if plot_quantity[i] == 'stage' and elevations[0,k,j] > 0:
1312                            word_quantity += 'depth' + ','
1313                        else:
1314                            word_quantity += plot_quantity[i] + ', '
1315                    else:
1316                        if plot_quantity[i] == 'stage' and elevations[0,k,j] > 0:
1317                            word_quantity += 'depth'
1318                        else:
1319                            word_quantity += plot_quantity[i]
1320                    where1 = 0
1321                    count1 += 1
1322                    index = j*len(plot_quantity)
1323                    for which_quantity in plot_quantity:
1324                        where1 += 1
1325                        s = '\includegraphics[width=0.49\linewidth, height=50mm]{%s%s}' %(graphname_report[index], '.png')
1326                        index += 1
1327                        fid.write(s)
1328                        if where1 % 2 == 0:
1329                            s = '\\\\ \n'
1330                            where1 = 0
1331                        else:
1332                            s = '& \n'
1333                        fid.write(s)
1334                word_quantity += ' and ' + plot_quantity[nn-1]           
1335                label = 'gauge%s' %(gaugeloc2) 
1336                caption = 'Time series for %s at %s location (elevation %.2fm)' %(word_quantity, locations[k], elev[k])
1337                if elev[k] == 0.0:
1338                        caption = 'Time series for %s at %s location (elevation %.2fm)' %(word_quantity, locations[k], elevations[0,k,j])
1339                        thisgauge = gauges[k]
1340                        east = thisgauge[0]
1341                        north = thisgauge[1]
1342                        elev_output.append([locations[k],east,north,elevations[0,k,j]])
1343                       
1344                s = '\end{tabular} \n \\caption{%s} \n \label{fig:%s} \n \end{figure} \n \n' %(caption, label)
1345                fid.write(s)
1346                if float((k+1)/div - pp) == 0.:
1347                    fid.write('\\clearpage \n')
1348                    pp += 1
1349               
1350                #### finished generating figures ###
1351
1352            close('all')
1353       
1354    return texfile2, elev_output
1355
1356# FIXME (DSG): Add unit test, make general, not just 2 files,
1357# but any number of files.
1358def copy_code_files(dir_name, filename1, filename2):
1359    """Copies "filename1" and "filename2" to "dir_name". Very useful for
1360    information management """
1361
1362    if access(dir_name,F_OK) == 0:
1363        print 'Make directory %s' %dir_name
1364        mkdir (dir_name,0777)
1365    copy(filename1, dir_name + sep + basename(filename1))
1366    copy(filename2, dir_name + sep + basename(filename2))
1367#    copy (__file__, project.output_run_time_dir + basename(__file__))
1368    print 'Files %s and %s copied' %(filename1, filename2)
1369
1370
1371def add_directories(root_directory, directories):
1372    """
1373    Add the first directory in directories to root_directory.
1374    Then add the second
1375    direcotory to the first directory and so on.
1376
1377    Return the path of the final directory.
1378
1379    This is handy for specifying and creating a directory where data will go.
1380    """
1381    dir = root_directory
1382    for new_dir in directories:
1383        dir = os.path.join(dir, new_dir)
1384        if not access(dir,F_OK):
1385            mkdir (dir)
1386    return dir
1387
1388def get_data_from_file(filename,separator_value = ','):
1389    """
1390    Read in data information from file
1391    NOTE: wont deal with columns with different lenghts and there must be
1392    no blank lines at the end.
1393    """
1394    from os import sep, getcwd, access, F_OK, mkdir
1395    from Numeric import array, resize,shape,Float
1396    import string
1397    fid = open(filename)
1398    lines = fid.readlines()
1399   
1400    fid.close()
1401   
1402    header_line = lines[0]
1403    header_fields = header_line.split(separator_value)
1404
1405    #array to store data, number in there is to allow float...
1406    #i'm sure there is a better way!
1407    data=array([],typecode=Float)
1408    data=resize(data,((len(lines)-1),len(header_fields)))
1409#    print 'number of fields',range(len(header_fields))
1410#    print 'number of lines',len(lines), shape(data)
1411#    print'data',data[1,1],header_line
1412
1413    array_number = 0
1414    line_number = 1
1415    while line_number < (len(lines)):
1416        for i in range(len(header_fields)): 
1417            #this get line below the header, explaining the +1
1418            #and also the line_number can be used as the array index
1419            fields = lines[line_number].split(separator_value)
1420            #assign to array
1421            data[array_number,i] = float(fields[i])
1422           
1423        line_number = line_number +1
1424        array_number = array_number +1
1425       
1426    return header_fields, data
1427
1428
1429
Note: See TracBrowser for help on using the repository browser.