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

Last change on this file since 4412 was 4412, checked in by nick, 18 years ago

small change to screen_catcher

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