source: trunk/anuga_core/source/anuga/file_conversion/urs2sww.py @ 7758

Last change on this file since 7758 was 7758, checked in by hudson, 14 years ago

Added extra file conversion classes to file_conversion.

File size: 7.6 KB
Line 
1################################################################################
2# CONVERTING UNGRIDDED URS DATA TO AN SWW FILE
3################################################################################
4
5WAVEHEIGHT_MUX_LABEL = '-z-mux'
6EAST_VELOCITY_LABEL =  '-e-mux'
7NORTH_VELOCITY_LABEL =  '-n-mux'
8
9##
10# @brief Convert URS file(s) (wave prop) to an SWW file.
11# @param basename_in Stem of the input filenames.
12# @param basename_out Path to the output SWW file.
13# @param verbose True if this function is to be verbose.
14# @param mint
15# @param maxt
16# @param mean_stage
17# @param origin Tuple with geo-ref UTM coordinates (zone, easting, northing).
18# @param hole_points_UTM
19# @param zscale
20# @note Also convert latitude and longitude to UTM. All coordinates are
21#       assumed to be given in the GDA94 datum.
22# @note Input filename stem has suffixes '-z-mux', '-e-mux' and '-n-mux'
23#       added for relative height, x-velocity and y-velocity respectively.
24def urs2sww(basename_in='o', basename_out=None, verbose=False,
25                      mint=None, maxt=None,
26                      mean_stage=0,
27                      origin=None,
28                      hole_points_UTM=None,
29                      zscale=1):
30    """
31    Convert URS C binary format for wave propagation to
32    sww format native to abstract_2d_finite_volumes.
33
34    Specify only basename_in and read files of the form
35    basefilename-z-mux, basefilename-e-mux and
36    basefilename-n-mux containing relative height,
37    x-velocity and y-velocity, respectively.
38
39    Also convert latitude and longitude to UTM. All coordinates are
40    assumed to be given in the GDA94 datum. The latitude and longitude
41    information is assumed ungridded grid.
42
43    min's and max's: If omitted - full extend is used.
44    To include a value min ans max may equal it.
45    Lat and lon are assumed to be in decimal degrees.
46
47    origin is a 3-tuple with geo referenced
48    UTM coordinates (zone, easting, northing)
49    It will be the origin of the sww file. This shouldn't be used,
50    since all of anuga should be able to handle an arbitary origin.
51    The mux point info is NOT relative to this origin.
52
53    URS C binary format has data organised as TIME, LONGITUDE, LATITUDE
54    which means that latitude is the fastest
55    varying dimension (row major order, so to speak)
56
57    In URS C binary the latitudes and longitudes are in assending order.
58
59    Note, interpolations of the resulting sww file will be different
60    from results of urs2sww.  This is due to the interpolation
61    function used, and the different grid structure between urs2sww
62    and this function.
63
64    Interpolating data that has an underlying gridded source can
65    easily end up with different values, depending on the underlying
66    mesh.
67
68    consider these 4 points
69    50  -50
70
71    0     0
72
73    The grid can be
74     -
75    |\|   A
76     -
77     or;
78      -
79     |/|  B
80      -
81
82    If a point is just below the center of the midpoint, it will have a
83    +ve value in grid A and a -ve value in grid B.
84    """
85
86    from anuga.mesh_engine.mesh_engine import NoTrianglesError
87    from anuga.pmesh.mesh import Mesh
88
89    files_in = [basename_in + WAVEHEIGHT_MUX_LABEL,
90                basename_in + EAST_VELOCITY_LABEL,
91                basename_in + NORTH_VELOCITY_LABEL]
92    quantities = ['HA','UA','VA']
93
94    # instantiate urs_points of the three mux files.
95    mux = {}
96    for quantity, file in map(None, quantities, files_in):
97        mux[quantity] = Urs_points(file)
98
99    # Could check that the depth is the same. (hashing)
100
101    # handle to a mux file to do depth stuff
102    a_mux = mux[quantities[0]]
103
104    # Convert to utm
105    lat = a_mux.lonlatdep[:,1]
106    long = a_mux.lonlatdep[:,0]
107    points_utm, zone = convert_from_latlon_to_utm(latitudes=lat,
108                                                  longitudes=long)
109
110    elevation = a_mux.lonlatdep[:,2] * -1
111
112    # grid (create a mesh from the selected points)
113    # This mesh has a problem.  Triangles are streched over ungridded areas.
114    # If these areas could be described as holes in pmesh, that would be great.
115
116    # I can't just get the user to selection a point in the middle.
117    # A boundary is needed around these points.
118    # But if the zone of points is obvious enough auto-segment should do
119    # a good boundary.
120    mesh = Mesh()
121    mesh.add_vertices(points_utm)
122    mesh.auto_segment(smooth_indents=True, expand_pinch=True)
123
124    # To try and avoid alpha shape 'hugging' too much
125    mesh.auto_segment(mesh.shape.get_alpha() * 1.1)
126    if hole_points_UTM is not None:
127        point = ensure_absolute(hole_points_UTM)
128        mesh.add_hole(point[0], point[1])
129
130    try:
131        mesh.generate_mesh(minimum_triangle_angle=0.0, verbose=False)
132    except NoTrianglesError:
133        # This is a bit of a hack, going in and changing the data structure.
134        mesh.holes = []
135        mesh.generate_mesh(minimum_triangle_angle=0.0, verbose=False)
136
137    mesh_dic = mesh.Mesh2MeshList()
138
139    #mesh.export_mesh_file(basename_in + '_168.tsh')
140    #import sys; sys.exit()
141    # These are the times of the mux file
142    mux_times = []
143    for i in range(a_mux.time_step_count):
144        mux_times.append(a_mux.time_step * i)
145    (mux_times_start_i, mux_times_fin_i) = mux2sww_time(mux_times, mint, maxt)
146    times = mux_times[mux_times_start_i:mux_times_fin_i]
147
148    if mux_times_start_i == mux_times_fin_i:
149        # Close the mux files
150        for quantity, file in map(None, quantities, files_in):
151            mux[quantity].close()
152        msg = "Due to mint and maxt there's no time info in the boundary SWW."
153        raise Exception, msg
154
155    # If this raise is removed there is currently no downstream errors
156
157    points_utm=ensure_numeric(points_utm)
158    assert num.alltrue(ensure_numeric(mesh_dic['generatedpointlist'])
159                       == ensure_numeric(points_utm))
160
161    volumes = mesh_dic['generatedtrianglelist']
162
163    # Write sww intro and grid stuff.
164    if basename_out is None:
165        swwname = basename_in + '.sww'
166    else:
167        swwname = basename_out + '.sww'
168
169    if verbose: log.critical('Output to %s' % swwname)
170
171    outfile = NetCDFFile(swwname, netcdf_mode_w)
172
173    # For a different way of doing this, check out tsh2sww
174    # work out sww_times and the index range this covers
175    sww = Write_sww(['elevation'], ['stage', 'xmomentum', 'ymomentum'])
176    sww.store_header(outfile, times, len(volumes), len(points_utm),
177                     verbose=verbose, sww_precision=netcdf_float)
178    outfile.mean_stage = mean_stage
179    outfile.zscale = zscale
180
181    sww.store_triangulation(outfile, points_utm, volumes,
182                            zone, 
183                            new_origin=origin,
184                            verbose=verbose)
185    sww.store_static_quantities(outfile, elevation=elevation)
186
187    if verbose: log.critical('Converting quantities')
188
189    # Read in a time slice from each mux file and write it to the SWW file
190    j = 0
191    for ha, ua, va in map(None, mux['HA'], mux['UA'], mux['VA']):
192        if j >= mux_times_start_i and j < mux_times_fin_i:
193            stage = zscale*ha + mean_stage
194            h = stage - elevation
195            xmomentum = ua*h
196            ymomentum = -1 * va * h # -1 since in mux files south is positive.
197            sww.store_quantities(outfile,
198                                 slice_index=j-mux_times_start_i,
199                                 verbose=verbose,
200                                 stage=stage,
201                                 xmomentum=xmomentum,
202                                 ymomentum=ymomentum,
203                                 sww_precision=num.float)
204        j += 1
205
206    if verbose: sww.verbose_quantities(outfile)
207
208    outfile.close()
209
210    # Do some conversions while writing the sww file
Note: See TracBrowser for help on using the repository browser.