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

Last change on this file since 4320 was 4320, checked in by sexton, 17 years ago

new earthquake source function (converted fortran to python), plus new figures for slide report

File size: 52.2 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        file0 = file_loc[j]+'gauges_t0.csv'
1063        fid_0 = open(file0, 'w')
1064        ##### loop over each gauge #####
1065        for k in gauge_index:
1066            g = gauges[k]
1067            if verbose: print 'Gauge %d of %d' %(k, len(gauges))
1068            min_stage = 10
1069            max_stage = 0
1070            max_momentum = 0
1071            max_speed = 0
1072            max_depth = 0
1073            gaugeloc = locations[k]
1074            thisfile = file_loc[j]+sep+'gauges_time_series'+'_'+gaugeloc+'.csv'
1075            fid_out = open(thisfile, 'w')
1076            s = 'Time, Stage, Momentum, Speed, Elevation, xmom, ymom \n'
1077            fid_out.write(s)
1078           
1079            #### generate quantities #######
1080            for i, t in enumerate(f.get_time()):
1081                if time_min <= t <= time_max:
1082                    w = f(t, point_id = k)[0]
1083                    z = f(t, point_id = k)[1]
1084                    uh = f(t, point_id = k)[2]
1085                    vh = f(t, point_id = k)[3]
1086                    depth = w-z     
1087                    m = sqrt(uh*uh + vh*vh)
1088                    if depth < 0.001:
1089                        vel = 0.0
1090                    else:
1091                        vel = m / (depth + 1.e-6/depth) 
1092                    #bearing = calc_bearing(uh, vh)
1093                    model_time[i,k,j] = t/60.0
1094                    stages[i,k,j] = w
1095                    elevations[i,k,j] = z
1096                    xmom[i,k,j] = uh
1097                    ymom[i,k,j] = vh
1098                    momenta[i,k,j] = m
1099                    speed[i,k,j] = vel
1100                    #bearings[i,k,j] = bearing
1101                    depths[i,k,j] = depth
1102                    thisgauge = gauges[k]
1103                    eastings[i,k,j] = thisgauge[0]
1104                    s = '%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n' %(t, w, m, vel, z, uh, vh)
1105                    fid_out.write(s)
1106                    if t == 0:
1107                        s = '%.2f, %.2f, %.2f\n' %(g[0], g[1], w)
1108                        fid_0.write(s)
1109                    if t/60.0 <= 13920: tindex = i
1110                    if w > max_stage: max_stage = w
1111                    if w < min_stage: min_stage = w
1112                    if m > max_momentum: max_momentum = m
1113                    if vel > max_speed: max_speed = vel
1114                    if z > 0 and depth > max_depth: max_depth = depth
1115                   
1116                   
1117            s = '%.2f, %.2f, %.2f, %.2f, %s\n' %(max_stage, min_stage, z, thisgauge[0], leg_label[j])
1118            fid_compare.write(s)
1119            max_stages.append(max_stage)
1120            min_stages.append(min_stage)
1121            max_momentums.append(max_momentum)
1122            max_speeds.append(max_speed)
1123            max_depths.append(max_depth)
1124            #### finished generating quantities for each swwfile #####
1125       
1126        model_time_plot3d[:,:] = model_time[:,:,j]
1127        stages_plot3d[:,:] = stages[:,:,j]
1128        eastings_plot3d[:,] = eastings[:,:,j]
1129           
1130        if surface is  True:
1131            print 'Printing surface figure'
1132            for i in range(2):
1133                fig = p1.figure(10)
1134                ax = p3.Axes3D(fig)
1135                if len(gauges) > 80:
1136                    ax.plot_surface(model_time[:,:,j],eastings[:,:,j],stages[:,:,j])
1137                else:
1138                    #ax.plot_wireframe(model_time[:,:,j],eastings[:,:,j],stages[:,:,j])
1139                    ax.plot3D(ravel(eastings[:,:,j]),ravel(model_time[:,:,j]),ravel(stages[:,:,j]))
1140                ax.set_xlabel('time')
1141                ax.set_ylabel('x')
1142                ax.set_zlabel('stage')
1143                fig.add_axes(ax)
1144                p1.show()
1145                surfacefig = 'solution_surface%s' %leg_label[j]
1146                p1.savefig(surfacefig)
1147                p1.close()
1148           
1149    #### finished generating quantities for all swwfiles #####
1150
1151    # x profile for given time
1152    if surface is True:
1153        figure(11)
1154        plot(eastings[tindex,:,j],stages[tindex,:,j])
1155        xlabel('x')
1156        ylabel('stage')
1157        profilefig = 'solution_xprofile' 
1158        savefig('profilefig')
1159
1160    elev_output = []
1161    if generate_fig is True:
1162        depth_axis = axis([time_min/60.0, time_max/60.0, -0.1, max(max_depths)*1.1])
1163        stage_axis = axis([time_min/60.0, time_max/60.0, min(min_stages), max(max_stages)*1.1])
1164        #stage_axis = axis([50.0, time_max/60.0, -3.0, 2.0])
1165        vel_axis = axis([time_min/60.0, time_max/60.0, min(max_speeds), max(max_speeds)*1.1])
1166        mom_axis = axis([time_min/60.0, time_max/60.0, min(max_momentums), max(max_momentums)*1.1])
1167        cstr = ['g', 'r', 'b', 'c', 'm', 'y', 'k']
1168        nn = len(plot_quantity)
1169        no_cols = 2
1170       
1171        if len(label_id) > 1: graphname_report = []
1172        pp = 1
1173        div = 11.
1174        cc = 0
1175        for k in gauge_index:
1176            g = gauges[k]
1177            count1 = 0
1178            if report == True and len(label_id) > 1:
1179                s = '\\begin{figure}[ht] \n \\centering \n \\begin{tabular}{cc} \n'
1180                fid.write(s)
1181            if len(label_id) > 1: graphname_report = []
1182            #### generate figures for each gauge ####
1183            for j, f in enumerate(f_list):
1184                ion()
1185                hold(True)
1186                count = 0
1187                where1 = 0
1188                where2 = 0
1189                word_quantity = ''
1190                if report == True and len(label_id) == 1:
1191                    s = '\\begin{figure}[hbt] \n \\centering \n \\begin{tabular}{cc} \n'
1192                    fid.write(s)
1193                   
1194                for which_quantity in plot_quantity:
1195                    count += 1
1196                    where1 += 1
1197                    figure(count, frameon = False)
1198                    if which_quantity == 'depth':
1199                        plot(model_time[0:n[j]-1,k,j], depths[0:n[j]-1,k,j], '-', c = cstr[j])
1200                        units = 'm'
1201                        axis(depth_axis)
1202                    if which_quantity == 'stage':
1203                        if elevations[0,k,j] <= 0:
1204                            plot(model_time[0:n[j]-1,k,j], stages[0:n[j]-1,k,j], '-', c = cstr[j])
1205                            axis(stage_axis)
1206                        else:
1207                            plot(model_time[0:n[j]-1,k,j], depths[0:n[j]-1,k,j], '-', c = cstr[j])
1208                            #axis(depth_axis)                 
1209                        units = 'm'
1210                    if which_quantity == 'momentum':
1211                        plot(model_time[0:n[j]-1,k,j], momenta[0:n[j]-1,k,j], '-', c = cstr[j])
1212                        axis(mom_axis)
1213                        units = 'm^2 / sec'
1214                    if which_quantity == 'xmomentum':
1215                        plot(model_time[0:n[j]-1,k,j], xmom[0:n[j]-1,k,j], '-', c = cstr[j])
1216                        axis(mom_axis)
1217                        units = 'm^2 / sec'
1218                    if which_quantity == 'ymomentum':
1219                        plot(model_time[0:n[j]-1,k,j], ymom[0:n[j]-1,k,j], '-', c = cstr[j])
1220                        axis(mom_axis)
1221                        units = 'm^2 / sec'
1222                    if which_quantity == 'speed':
1223                        plot(model_time[0:n[j]-1,k,j], speed[0:n[j]-1,k,j], '-', c = cstr[j])
1224                        axis(vel_axis)
1225                        units = 'm / sec'
1226                    if which_quantity == 'bearing':
1227                        due_east = 90.0*ones(shape(model_time[0:n[j]-1,k,j],Float))
1228                        due_west = 270.0*ones(shape(model_time[0:n[j]-1,k,j],Float))
1229                        plot(model_time[0:n[j]-1,k,j], bearings, '-', 
1230                             model_time[0:n[j]-1,k,j], due_west, '-.', 
1231                             model_time[0:n[j]-1,k,j], due_east, '-.')
1232                        units = 'degrees from North'
1233                        ax = axis([time_min, time_max, 0.0, 360.0])
1234                        legend(('Bearing','West','East'))
1235
1236                    xlabel('time (mins)')
1237                    if which_quantity == 'stage' and elevations[0:n[j]-1,k,j] > 0:
1238                        ylabel('%s (%s)' %('depth', units))
1239                    else:
1240                        ylabel('%s (%s)' %(which_quantity, units))
1241                    if len(label_id) > 1: legend((leg_label),loc='upper right')
1242
1243                    gaugeloc1 = gaugeloc.replace(' ','')
1244                    #gaugeloc2 = gaugeloc1.replace('_','')
1245                    gaugeloc2 = locations[k].replace(' ','')
1246                    graphname = '%sgauge%s_%s' %(file_loc[j], gaugeloc2, which_quantity)
1247
1248                    if report == True and len(label_id) > 1:
1249                        figdir = getcwd()+sep+'report_figures'+sep
1250                        if access(figdir,F_OK) == 0 :
1251                            mkdir (figdir)
1252                        latex_file_loc = figdir.replace(sep,altsep) 
1253                        graphname_latex = '%sgauge%s%s' %(latex_file_loc, gaugeloc2, which_quantity) # storing files in production directory   
1254                        graphname_report_input = '%sgauge%s%s' %('..'+altsep+'report_figures'+altsep, gaugeloc2, which_quantity) # giving location in latex output file
1255                        graphname_report.append(graphname_report_input)
1256                       
1257                        savefig(graphname_latex) # save figures in production directory for report generation
1258
1259                    if report == True:
1260
1261                        figdir = getcwd()+sep+'report_figures'+sep
1262                        if access(figdir,F_OK) == 0 :
1263                            mkdir (figdir)
1264                        latex_file_loc = figdir.replace(sep,altsep)   
1265
1266                        if len(label_id) == 1: 
1267                            graphname_latex = '%sgauge%s%s%s' %(latex_file_loc, gaugeloc2, which_quantity, label_id2) # storing files in production directory 
1268                            graphname_report = '%sgauge%s%s%s' %('..'+altsep+'report_figures'+altsep, gaugeloc2, which_quantity, label_id2) # giving location in latex output file
1269                            s = '\includegraphics[width=0.49\linewidth, height=50mm]{%s%s}' %(graphname_report, '.png')
1270                            fid.write(s)
1271                            if where1 % 2 == 0:
1272                                s = '\\\\ \n'
1273                                where1 = 0
1274                            else:
1275                                s = '& \n'
1276                            fid.write(s)
1277                            savefig(graphname_latex)
1278                   
1279                    if title_on == True:
1280                        title('%s scenario: %s at %s gauge' %(label_id, which_quantity, gaugeloc2))
1281                        #title('Gauge %s (MOST elevation %.2f, ANUGA elevation %.2f)' %(gaugeloc2, elevations[10,k,0], elevations[10,k,1] ))
1282
1283                    savefig(graphname) # save figures with sww file
1284
1285                if report == True and len(label_id) == 1:
1286                    for i in range(nn-1):
1287                        if nn > 2:
1288                            if plot_quantity[i] == 'stage' and elevations[0,k,j] > 0:
1289                                word_quantity += 'depth' + ', '
1290                            else:
1291                                word_quantity += plot_quantity[i] + ', '
1292                        else:
1293                            if plot_quantity[i] == 'stage' and elevations[0,k,j] > 0:
1294                                word_quantity += 'depth' + ', '
1295                            else:
1296                                word_quantity += plot_quantity[i]
1297                       
1298                    if plot_quantity[nn-1] == 'stage' and elevations[0,k,j] > 0:
1299                        word_quantity += ' and ' + 'depth'
1300                    else:
1301                        word_quantity += ' and ' + plot_quantity[nn-1]
1302                    caption = 'Time series for %s at %s location (elevation %.2fm)' %(word_quantity, locations[k], elev[k]) #gaugeloc.replace('_',' '))
1303                    if elev[k] == 0.0:
1304                        caption = 'Time series for %s at %s location (elevation %.2fm)' %(word_quantity, locations[k], elevations[0,k,j])
1305                        east = gauges[0]
1306                        north = gauges[1]
1307                        elev_output.append([locations[k],east,north,elevations[0,k,j]])
1308                    label = '%sgauge%s' %(label_id2, gaugeloc2)
1309                    s = '\end{tabular} \n \\caption{%s} \n \label{fig:%s} \n \end{figure} \n \n' %(caption, label)
1310                    fid.write(s)
1311                    cc += 1
1312                    if cc % 6 == 0: fid.write('\\clearpage \n')
1313                    savefig(graphname_latex)               
1314                   
1315            if report == True and len(label_id) > 1:
1316                for i in range(nn-1):
1317                    if nn > 2:
1318                        if plot_quantity[i] == 'stage' and elevations[0,k,j] > 0:
1319                            word_quantity += 'depth' + ','
1320                        else:
1321                            word_quantity += plot_quantity[i] + ', '
1322                    else:
1323                        if plot_quantity[i] == 'stage' and elevations[0,k,j] > 0:
1324                            word_quantity += 'depth'
1325                        else:
1326                            word_quantity += plot_quantity[i]
1327                    where1 = 0
1328                    count1 += 1
1329                    index = j*len(plot_quantity)
1330                    for which_quantity in plot_quantity:
1331                        where1 += 1
1332                        s = '\includegraphics[width=0.49\linewidth, height=50mm]{%s%s}' %(graphname_report[index], '.png')
1333                        index += 1
1334                        fid.write(s)
1335                        if where1 % 2 == 0:
1336                            s = '\\\\ \n'
1337                            where1 = 0
1338                        else:
1339                            s = '& \n'
1340                        fid.write(s)
1341                word_quantity += ' and ' + plot_quantity[nn-1]           
1342                label = 'gauge%s' %(gaugeloc2) 
1343                caption = 'Time series for %s at %s location (elevation %.2fm)' %(word_quantity, locations[k], elev[k])
1344                if elev[k] == 0.0:
1345                        caption = 'Time series for %s at %s location (elevation %.2fm)' %(word_quantity, locations[k], elevations[0,k,j])
1346                        thisgauge = gauges[k]
1347                        east = thisgauge[0]
1348                        north = thisgauge[1]
1349                        elev_output.append([locations[k],east,north,elevations[0,k,j]])
1350                       
1351                s = '\end{tabular} \n \\caption{%s} \n \label{fig:%s} \n \end{figure} \n \n' %(caption, label)
1352                fid.write(s)
1353                if float((k+1)/div - pp) == 0.:
1354                    fid.write('\\clearpage \n')
1355                    pp += 1
1356               
1357                #### finished generating figures ###
1358
1359            close('all')
1360       
1361    return texfile2, elev_output
1362
1363# FIXME (DSG): Add unit test, make general, not just 2 files,
1364# but any number of files.
1365def copy_code_files(dir_name, filename1, filename2):
1366    """Copies "filename1" and "filename2" to "dir_name". Very useful for
1367    information management """
1368
1369    if access(dir_name,F_OK) == 0:
1370        print 'Make directory %s' %dir_name
1371        mkdir (dir_name,0777)
1372    copy(filename1, dir_name + sep + basename(filename1))
1373    copy(filename2, dir_name + sep + basename(filename2))
1374#    copy (__file__, project.output_run_time_dir + basename(__file__))
1375    print 'Files %s and %s copied' %(filename1, filename2)
1376
1377
1378def add_directories(root_directory, directories):
1379    """
1380    Add the first directory in directories to root_directory.
1381    Then add the second
1382    direcotory to the first directory and so on.
1383
1384    Return the path of the final directory.
1385
1386    This is handy for specifying and creating a directory where data will go.
1387    """
1388    dir = root_directory
1389    for new_dir in directories:
1390        dir = os.path.join(dir, new_dir)
1391        if not access(dir,F_OK):
1392            mkdir (dir)
1393    return dir
1394
1395def get_data_from_file(filename,separator_value = ','):
1396    """
1397    Read in data information from file
1398    NOTE: wont deal with columns with different lenghts and there must be
1399    no blank lines at the end.
1400    """
1401    from os import sep, getcwd, access, F_OK, mkdir
1402    from Numeric import array, resize,shape,Float
1403    import string
1404    fid = open(filename)
1405    lines = fid.readlines()
1406   
1407    fid.close()
1408   
1409    header_line = lines[0]
1410    header_fields = header_line.split(separator_value)
1411
1412    #array to store data, number in there is to allow float...
1413    #i'm sure there is a better way!
1414    data=array([],typecode=Float)
1415    data=resize(data,((len(lines)-1),len(header_fields)))
1416#    print 'number of fields',range(len(header_fields))
1417#    print 'number of lines',len(lines), shape(data)
1418#    print'data',data[1,1],header_line
1419
1420    array_number = 0
1421    line_number = 1
1422    while line_number < (len(lines)):
1423        for i in range(len(header_fields)): 
1424            #this get line below the header, explaining the +1
1425            #and also the line_number can be used as the array index
1426            fields = lines[line_number].split(separator_value)
1427            #assign to array
1428            data[array_number,i] = float(fields[i])
1429           
1430        line_number = line_number +1
1431        array_number = array_number +1
1432       
1433    return header_fields, data
1434
1435
1436
Note: See TracBrowser for help on using the repository browser.