source: anuga_work/development/Hinwood_2008/slope.py @ 5503

Last change on this file since 5503 was 5503, checked in by duncan, 16 years ago

Current Hinwood scenario - added plotting of froude number, stage slope and time vs location for each wave

File size: 20.9 KB
RevLine 
[5413]1
2"""
3Plot up files from the Hinwood project.
4"""
5from os import sep
6import project
[5494]7from copy import deepcopy
[5413]8#from scipy import arange
[5494]9from csv import writer
[5413]10
[5494]11from Numeric import arange, array, zeros, Float, where, greater, less, \
[5503]12     compress, argmin, choose, searchsorted
[5426]13
[5413]14from anuga.fit_interpolate.interpolate import interpolate_sww2csv
[5426]15from anuga.shallow_water.data_manager import csv2dict
[5494]16from anuga.utilities.numerical_tools import ensure_numeric
[5413]17
[5494]18
19SLOPE_STR = 'stage_slopes'
20TIME_STR = 'times'
21
22TIME_BORDER = 5
23LOCATION_BORDER = .5
24
25def load_sensors(quantity_file):
[5426]26    #slope, _ = csv2dict(file_sim)
27   
28    # Read the depth file
[5494]29    dfid = open(quantity_file)
[5426]30    lines = dfid.readlines()
31    dfid.close()
[5413]32
[5426]33    title = lines.pop(0)
34    n_time = len(lines)
35    n_sensors = len(lines[0].split(','))-1  # -1 to remove time
36    dtimes = zeros(n_time, Float)  #Time
37    depths = zeros(n_time, Float)  #
38    sensors = zeros((n_time,n_sensors), Float)
[5494]39    quantity_locations = title.split(',') #(',')
40    quantity_locations.pop(0) # remove 'time'
[5426]41   
[5494]42    locations = [float(j.split(':')[0]) for j in quantity_locations]
43   
[5426]44    for i, line in enumerate(lines):
45        fields = line.split(',') #(',')
46        fields = [float(j) for j in fields]
47        dtimes[i] = fields[0]
48        sensors[i] = fields[1:] # 1: to remove time
49
50    #print "dtimes",dtimes
[5494]51    #print "locations", locations
[5426]52    #print "sensors", sensors
[5494]53    return dtimes, locations, sensors
[5426]54   
[5494]55def load_slopes(stage_file):
56    """
57    Finds the slope, wrt distance of a distance, time, quantity csv file.
58
59    returns the times and slope_locations vectors and the slopes array.
60    """
61    times, locations, sensors = load_sensors(stage_file)
62    n_slope_locations = len(locations)-1
[5426]63    n_time = len(times)
64    slope_locations = zeros(n_slope_locations, Float)  #
65    slopes = zeros((n_time,n_slope_locations), Float)
66
67    # An array of the sensor spacing values
[5494]68    delta_locations = zeros(n_slope_locations, Float)
[5426]69   
70    for i in arange(n_slope_locations):
[5494]71        delta_locations[i] = (locations[i+1] - locations[i])
[5503]72        slope_locations[i] = locations[i] + 0.5*delta_locations[i]
[5426]73   
74    for j in arange(n_time):
75        for i in arange(n_slope_locations):
[5494]76            slopes[j,i] = (sensors[j,i+1] - sensors[j,i])/delta_locations[i]
[5426]77
78    return times, slope_locations, slopes
79
[5494]80
81def graph_contours(times, x_data, z_data,
82                 y_label='Time, seconds',
83                 plot_title="slope",
84                 x_label='x location, m',
85                 save_as=None,
86                 is_interactive=False,
87                 break_xs=None,
88                 break_times=None):
89    # Do not move these imports.  Tornado doesn't have pylab
[5447]90    from pylab import meshgrid, cm, contourf, contour, ion, plot, xlabel, \
91         ylabel, close, legend, savefig, title, figure ,colorbar, show , axis
[5494]92
[5426]93    origin = 'lower'
[5447]94
[5494]95    if is_interactive:
96        ion()
97       
[5447]98    # Can't seem to reshape this info once it is in the function
[5494]99    CS = contourf(x_data, times, z_data, 10,
[5447]100                  cmap=cm.bone,
101                  origin=origin)
[5426]102   
[5494]103    #CS2 = contour(x_data, times, z_data, CS.levels[::1],
104     #             colors = 'r',
105      #            origin=origin,
106       #           hold='on')
107   
108    title(plot_title)
109    xlabel(x_label)
110    ylabel(y_label)
[5426]111
[5447]112    if break_times is not None and break_xs is not None:
113        plot(break_xs, break_times, 'ro')
114   
[5494]115   
[5426]116    # Make a colorbar for the ContourSet returned by the contourf call.
117    cbar = colorbar(CS)
[5494]118
[5426]119    # Add the contour line levels to the colorbar
[5503]120    cbar.ax.set_ylabel('stage slope')
[5426]121    #cbar.add_lines(CS2)
[5494]122         
123    if is_interactive:       
124        raw_input() # Wait for enter pressed
125       
126    if save_as is not None:
127        savefig(save_as)
128    close()  #Need to close this plot
[5426]129
[5494]130def graph_froude(times, x_data, z_data,
131                 y_label='Time, seconds',
132                 plot_title="Froude Number",
133                 x_label='x location, m',
134                 save_as=None,
135                 is_interactive=False,
136                 break_xs=None,
137                 break_times=None):
138    # Do not move these imports.  Tornado doesn't have pylab
139    from pylab import meshgrid, cm, contourf, contour, ion, plot, xlabel, \
140         ylabel, close, legend, savefig, title, figure ,colorbar, show , axis
[5426]141
[5494]142    origin = 'lower'
143
144    if is_interactive:
145        ion()
146       
147    # Can't seem to reshape this info once it is in the function
[5503]148    #CS = contourf(x_data, times, z_data, [-1,0.6,0.8,1,2,4],
149     #             colors = ('black', 'r', 'g', 'b','r'),
150      #            #cmap=cm.bone,
151       #           origin=origin)
152    CS = contourf(x_data, times, z_data, 10,
153                  #colors = ('black', 'r', 'g', 'b','r'),
154                  cmap=cm.bone,
[5494]155                  origin=origin)
[5413]156   
[5494]157    #CS2 = contour(x_data, times, z_data, CS.levels[::1],
158     #             colors = 'r',
159      #            origin=origin,
160       #           hold='on')
161   
162    title(plot_title)
163    xlabel(x_label)
164    ylabel(y_label)
165
166    if break_times is not None and break_xs is not None:
167        plot(break_xs, break_times, 'yo')
168   
169   
170    # Make a colorbar for the ContourSet returned by the contourf call.
171    cbar = colorbar(CS)
172
173    # Add the contour line levels to the colorbar
[5503]174    cbar.ax.set_ylabel('Froude Number')
[5494]175    #cbar.add_lines(CS2)
176         
177    if is_interactive:       
178        raw_input() # Wait for enter pressed
179       
180    if save_as is not None:
181        savefig(save_as)
182    close()  #Need to close this plot
183   
184def auto_graph_slopes(outputdir_tag, scenarios, is_interactive=False):
185    plot_type = ".pdf"
[5413]186    for run_data in scenarios:
[5426]187        id = run_data['scenario_id']
188        outputdir_name = id + outputdir_tag
189        pro_instance = project.Project(['data','flumes','Hinwood_2008'],
190                                       outputdir_name=outputdir_name)
191        end = id + ".csv"
[5494]192        anuga_break_times = []
193        for break_time in run_data['break_times']:
194            anuga_break_times.append( \
195                break_time -  run_data['ANUGA_start_time'])
196        stage_file = pro_instance.outputdir + "fslope_stage_" + end
[5503]197        plot_title = "Stage slope " + id + "\n file:" + \
198                     outputdir_name + "_slope_stage" + plot_type
199        print "Creating ", stage_file
[5494]200        save_as = pro_instance.plots_dir + sep + \
201                            outputdir_name + "_slope_stage" + plot_type
202        times, locations, slopes = load_slopes(stage_file)
[5503]203        #times, slopes = get_band(anuga_break_times[0]-TIME_BORDER,
204         #                          100, times, slopes, 0)
205        #locations, slopes = get_band(
206         #   min(run_data['break_xs'])- 2*LOCATION_BORDER,
207          #  100, locations, slopes, -1)
[5494]208        graph_contours(times, locations, slopes,
[5495]209                       plot_title=plot_title,
210                       break_xs=run_data['break_xs'],
211                       break_times=anuga_break_times,
212                       save_as=save_as,
[5494]213                       is_interactive=is_interactive)
214
215def auto_graph_froudes(outputdir_tag, scenarios, is_interactive=False):
[5426]216   
[5494]217    plot_type = ".pdf"
218   
219    for run_data in scenarios:
220        id = run_data['scenario_id']
221        outputdir_name = id + outputdir_tag
222        pro_instance = project.Project(['data','flumes','Hinwood_2008'],
223                                       outputdir_name=outputdir_name)
224        end = id + ".csv"
225        anuga_break_times = []
226        for break_time in run_data['break_times']:
227            anuga_break_times.append( \
228                break_time -  run_data['ANUGA_start_time'])
[5503]229        plot_title = "Froude Number" + id + "\n file:" + \
230                     outputdir_name + "_froude" + plot_type
[5494]231        froude_file = pro_instance.outputdir + "fslope_froude_" + end
[5503]232        print "Creating ", froude_file
[5494]233        save_as = pro_instance.plots_dir + sep + \
234                            outputdir_name + "_froude" + plot_type
235        dtimes, locations, sensors = load_sensors(froude_file)
236        dtimes, sensors = get_band(anuga_break_times[0]-TIME_BORDER,
237                                   100, dtimes, sensors, 0)
[5503]238        locations, sensors = get_band(
239            min(run_data['break_xs'])-LOCATION_BORDER,
240            100, locations, sensors, -1)
[5494]241        #print "dtimes", dtimes
242        #print "sensors", sensors
243        #times, slope_locations, slopes = load_slopes(stage_file)
244        graph_froude(dtimes, locations, sensors,
[5495]245                     plot_title=plot_title,
[5494]246                     break_xs=run_data['break_xs'],
247                     break_times=anuga_break_times,
248                     save_as=save_as,
249                     is_interactive=is_interactive)
250       
[5503]251def find_froude(times_froude, locations_froude, froudes_array,
252                times, locations):
253    if len(times) == 0:
254        return []
255    time_indexes = searchsorted(times_froude, times)
256    location_indexes = searchsorted(locations_froude, locations)
257
258   
259    assert len(time_indexes) == len(location_indexes)
260
261    froudes = []
262    for time_i, loc_i, time, location in map(None, time_indexes,
263                                             location_indexes,
264                                             times, locations):
265        # the time values should be the same
266        assert times_froude[time_i] == time
267
268        # The distance value should be half way between the froude locations
269        midpoint = locations_froude[loc_i-1] + \
270                   (locations_froude[loc_i]-locations_froude[loc_i-1])*0.5
271        #print "location", location
272        #print "midpoint", midpoint
273        assert location == midpoint
274        froude = froudes_array[time_i, loc_i-1] + \
275                   (froudes_array[time_i, loc_i]- \
276                    froudes_array[time_i, loc_i-1])*0.5
277        froudes.append(froude)
278               
279    return froudes
280   
281def auto_find_min_slopes(slope_tag, outputdir_tag, scenarios):
[5494]282    """
283   
284    """
285   
286    for run_data in scenarios:
287        id = run_data['scenario_id']
288        outputdir_name = id + outputdir_tag
289        pro_instance = project.Project(['data','flumes','Hinwood_2008'],
290                                       outputdir_name=outputdir_name)
291        end = id + ".csv"
292        anuga_break_times = []
293        for break_time in run_data['break_times']:
294            anuga_break_times.append( \
295                break_time -  run_data['ANUGA_start_time'])
296           
[5503]297        stage_file = pro_instance.outputdir + slope_tag + "slope_stage_" + end
298        froude_file = pro_instance.outputdir + slope_tag + "slope_froude_" + \
299                      end
[5494]300       
301        times, slope_locations, slopes = load_slopes(stage_file)
[5503]302        #print "slope_locations", slope_locations
303        times_froude, locations_froude, froudes_a = load_sensors(froude_file)
304        #print "locations_froude", locations_froude
[5494]305        waves = find_min_slopes(times, slope_locations, slopes,
306                                anuga_break_times,
307                                run_data['band_offset'])
[5503]308       
[5494]309        # write the wave info here
[5503]310        # and find the froude values
311        for i, wave in enumerate(waves):
312           
313            id = "wave_" + str(i)
314            wave_file = stage_file[:-4] + '_'+ id + ".csv"
[5494]315            print "wave_file", wave_file
[5503]316            froudes = find_froude(times_froude, locations_froude,
317                             froudes_a, wave[TIME_STR],
318                                  slope_locations)
[5494]319            wave_writer = writer(file(wave_file, "wb"))
[5503]320            wave_writer.writerow(["x location", "min slope", "Time", "Froude"])
[5494]321            wave_writer.writerows(map(None,
322                                      slope_locations,
[5503]323                                      wave[SLOPE_STR],
324                                      wave[TIME_STR],
325                                      froudes))
326
[5494]327           
[5503]328def auto_plot_froude_slopes(slope_tag, outputdir_tag, scenarios):
329    """
330   
331    """
332   
333    plot_type = ".pdf"
334   
335    for run_data in scenarios:
336        id = run_data['scenario_id']
337        outputdir_name = id + outputdir_tag
338        pro_instance = project.Project(['data','flumes','Hinwood_2008'],
339                                       outputdir_name=outputdir_name)
340
341        assert len(run_data['break_times']) == len(run_data['break_xs'])
342        assert len(run_data['break_times']) == len(run_data['break_type'])
343       
344        end = id + ".csv"
345       
346        anuga_break_times = []
347        for break_time in run_data['break_times']:
348            anuga_break_times.append( \
349                break_time -  run_data['ANUGA_start_time'])
[5494]350           
[5503]351        #run_data['break_type'] = (run_data['break_type'][0])
352        for i in range(len(run_data['break_type'])):
[5494]353           
[5503]354            wave_tag = "wave_" + str(i)
355            stage_file = pro_instance.outputdir + slope_tag + \
356                         "slope_stage_" + end
357            wave_file = stage_file[:-4] + '_'+ wave_tag + ".csv"
358            save_as = pro_instance.plots_dir + sep + \
359                            outputdir_name + "_" + wave_tag + plot_type
360            print "wave_file", wave_file
361            break_type = run_data['break_type'][i]
362            plot_title = id  + ' Wave: ' + str(i) + \
363                        " Break Type: " + break_type + '\n' + \
364                        "File: " + wave_file[34:] # not good!
365            plot_foude_slope_stage(wave_file,
366                                   anuga_break_times[i],
367                                   run_data['break_xs'][i],
368                                   plot_title=plot_title,
369                                   break_type=break_type,
370                                   save_as=save_as,
371                                   is_interactive=False)
[5494]372       
[5503]373       
[5494]374   
[5503]375def gauges_for_slope(slope_tag, outputdir_tag, scenarios):
[5494]376    """
377    This is used to create a stage file, using gauges relivent to
378    finding a slope.
[5503]379
380    It also create's a frounde file.
[5494]381    """
[5455]382    dx = 0.05
[5426]383    for run_data in scenarios:
[5413]384        point_x = arange(run_data['start_slope_x'],
385                        run_data['finish_slope_x'],
[5426]386                        dx).tolist()
[5413]387        flume_y_middle = 0.5
388        points = []
389        for gauge_x in point_x:
390            points.append([gauge_x, flume_y_middle])
391        id = run_data['scenario_id']
392   
393        basename = 'zz_' + run_data['scenario_id']
394        outputdir_name = id + outputdir_tag
395        pro_instance = project.Project(['data','flumes','Hinwood_2008'],
396                                       outputdir_name=outputdir_name)
397        end = id + ".csv"
[5494]398        interpolate_sww2csv( \
399            pro_instance.outputdir + basename +".sww",
400            points,
[5503]401            pro_instance.outputdir + slope_tag + "slope_depth_" + end,
402            pro_instance.outputdir + slope_tag + "slope_velocity_x_" + end,
403            pro_instance.outputdir + slope_tag + "slope_velocity_y_" + end,
404            pro_instance.outputdir + slope_tag + "slope_stage_" + end,
405            pro_instance.outputdir + slope_tag + "slope_froude_" + end,
[5494]406            time_thinning=1)
407
408def find_min_slopes(times, slope_locations, slopes,
[5503]409                    anuga_break_times, band_offset):
410    bands = break_times2bands(anuga_break_times, band_offset)
[5494]411
[5503]412    waves = []
[5494]413    for i,_ in enumerate(bands[0:-1]):
414        max_q, max_q_times = get_min_in_band(bands[i], bands[i+1],
415                                             times, slopes)
[5503]416        waves.append({SLOPE_STR:max_q, TIME_STR:max_q_times})
[5494]417    return waves
418
[5426]419   
[5494]420def get_band(min, max, vector, quantity_array, axis):
421    """
422    Return a band of vector and quantity, within (not including) the
423    min, max.
424
425    For a time band, set the axis to 0.
426    For a location band, set the axis to -1.
[5426]427   
[5494]428    """
[5413]429
[5494]430    SMALL_MIN = -1e10  # Not that small, but small enough
431    vector = ensure_numeric(vector)
432    quantity_array = ensure_numeric(quantity_array)
433
434    assert min > SMALL_MIN
435    no_maxs = where(less(vector,max), vector, SMALL_MIN)
436    #print "no_maxs", no_maxs
437    band_condition = greater(no_maxs, min)
438    band_vector = compress(band_condition, vector, axis=axis)
439    #print "band_time", band_time
440    #print "quantity_array", quantity_array.shape
441    band_quantity = compress(band_condition, quantity_array, axis=axis)
442    return band_vector, band_quantity
443
444def get_min_in_band(min_time, max_time, time_vector, quantity_array):
445    """
446    given a quantity array, with the 2nd axis being
447    time, represented by the time_vector, find the minimum within
448    the time band.
449
450    Assumes times are positive
451    """
452   
453    time_vector = ensure_numeric(time_vector)
454    quantity_array = ensure_numeric(quantity_array)
455
456    band_time, band_quantity  = get_band(min_time, max_time,
457                                         time_vector, quantity_array, 0)
458    #print "band_quantity",band_quantity
[5503]459    try:
460        max_quantity_indices = argmin(band_quantity, axis=0)
461    except:
462        #print "time_vector", time_vector
463        print "min_time",min_time
464        print "max_time", max_time
465        return [],[]
466       
[5494]467    #print "max_quantity_indices", max_quantity_indices
468    max_quantity_times = choose(max_quantity_indices, band_time)
469    #print "max_quantity_times", max_quantity_times
470    max_quantities = choose(max_quantity_indices, band_quantity)
471    #print "max_quantities", max_quantities
472
473    return max_quantities, max_quantity_times
474
475def break_times2bands(break_times, band_offset):
476    """
477    Break_times is a list of times, ascending.
478    bands is a list of times, being the midpoints of break_times, with a min
479    and max band added.
480    """
481    assert len(break_times)>2
482   
483    bands = [] #deepcopy(break_times)
484    bands.append(break_times[0]-0.5*(break_times[1]-break_times[0]))
485
[5503]486
[5494]487    for i,break_x in enumerate(break_times[0:-1]):
488        bands.append(break_times[i]+0.5*(break_times[i+1]-break_times[i]))
489       
490    bands.append(break_times[-1]+0.5*(break_times[-1]-break_times[-2]))
491    bands = ensure_numeric(bands)
492    bands += band_offset
493    return bands
494
[5503]495def plot_foude_slope_stage(wave_file,
496                           break_time,
497                           break_x,
498                           save_as=None,
499                           plot_title="",
500                           is_interactive=False,
501                           break_type="",
502                           use_axis=None):
503    """
504    """
505    from pylab import ion, plot, xlabel, ylabel, close, legend, \
506         savefig, title, axis, setp, subplot, grid, axvspan
507    from anuga.shallow_water.data_manager import csv2dict
508
509
510
511    # Load in the csv files and convert info from strings to floats
512    simulation, _ = csv2dict(wave_file)
513    location = [float(x) for x in simulation['x location']]
514    slope = [float(x) for x in simulation['min slope']]
515    time = [float(x) for x in simulation['Time']]
516    froude = [float(x) for x in simulation['Froude']]
517
518    min_location = min(location)
519    max_location = max(location)
520   
521    if is_interactive:
522        ion()
523    # The upper subplot
524    subplot(311)
525    l_froude = plot(location, froude)
526    #setp(l_froude, color='r')
527
528    # Add axis stuff
529    title(plot_title)
530    y_label = "Froude Number"
531    ylabel(y_label)
532    grid(True)
533    axvspan(break_x-0.001,break_x+0.001, facecolor='g')
534    axis(ymin=0, ymax=1.8)
535   
536    # The slope subplot
537    subplot(312)
538    l_slope = plot(location, slope)
539    setp(l_slope, color='r')
540
541    # Add axis stuff and legend
542    x_label = "X location, m"
543    y_label = "Stage slope"
544    #xlabel(x_label)
545    ylabel(y_label)
546    grid(True)
547    axvspan(break_x-0.001,break_x+0.001, facecolor='g')
548    axis(ymin=-0.5, ymax=0)
549
550    # The time, x location subplot
551    subplot(313)
552    l_time = plot(location, time)
553    setp(l_time, color='g')
554    #print "break_x", break_x
555    #print "break_time", break_time
556    plot([break_x], [break_time], 'yo')
557    #plot([break_x-1], [], 'yo')
558
559    # Add axis stuff and legend
560    x_label = "X location, m"
561    y_label = "time, sec"
562    xlabel(x_label)
563    ylabel(y_label)
564    grid(True)
565
566   
567    # The order defines the label
568    #legend((legend_exp, legend_sim),'upper left')
569    #legend(('Wave front'),'upper left')
570    if use_axis is not None:
571        axis(use_axis)
572   
573    if is_interactive:
574        # Wait for enter pressed
575        raw_input()
576
577    if save_as is not None:
578        savefig(save_as)
579   
580    #Need to close this plot
581    close()
582   
[5426]583#-------------------------------------------------------------
584if __name__ == "__main__":
585    """
586    """
[5455]587    from scenarios import scenarios
[5494]588    #scenarios = [scenarios[0]]
[5503]589    outputdir_tag = "_good_tri_area_0.01_limiterD"
590    slope_tag = ""
591    #outputdir_tag = "_good_tri_area_0.01_limiterC"
592    #slope_tag = "f"
[5494]593    #outputdir_tag = "_test_limiterC"
594    #scenarios = [scenarios[0]] # !!!!!!!!!!!!!!!!!!!!!!
[5503]595    #scenarios = scenarios[4:] # !!!!!!!!!!!!!!!!!!!!!!
596   
597    #gauges_for_slope(slope_tag, outputdir_tag, scenarios)
598    #auto_graph_slopes(outputdir_tag, scenarios) #, is_interactive=True)
599    #auto_find_min_slopes(slope_tag, outputdir_tag, scenarios)
600    #auto_graph_froudes(outputdir_tag, scenarios)
601    auto_plot_froude_slopes(slope_tag, outputdir_tag, scenarios)
Note: See TracBrowser for help on using the repository browser.