source: trunk/anuga_core/source/anuga/file_conversion/dem2pts.py @ 7841

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

Refactorings to allow tests to pass.

File size: 7.9 KB
Line 
1# external modules
2import numpy as num
3
4# ANUGA modules
5import anuga.utilities.log as log
6from anuga.config import netcdf_mode_r, netcdf_mode_w, netcdf_mode_a, \
7                            netcdf_float
8
9from asc2dem import asc2dem
10                           
11
12def dem2pts(name_in, name_out=None,
13            easting_min=None, easting_max=None,
14            northing_min=None, northing_max=None,
15            use_cache=False, verbose=False,):
16    """Read Digitial Elevation model from the following NetCDF format (.dem)
17
18    Example:
19
20    ncols         3121
21    nrows         1800
22    xllcorner     722000
23    yllcorner     5893000
24    cellsize      25
25    NODATA_value  -9999
26    138.3698 137.4194 136.5062 135.5558 ..........
27
28    name_in may be a .asc or .dem file to be converted.
29
30    Convert to NetCDF pts format which is
31
32    points:  (Nx2) float array
33    elevation: N float array
34    """
35
36    kwargs = {'name_out': name_out,
37              'easting_min': easting_min,
38              'easting_max': easting_max,
39              'northing_min': northing_min,
40              'northing_max': northing_max,
41              'verbose': verbose}
42
43    if use_cache is True:
44        from caching import cache
45        result = cache(_dem2pts, name_in, kwargs,
46                       dependencies = [name_in],
47                       verbose = verbose)
48
49    else:
50        result = apply(_dem2pts, [name_in], kwargs)
51
52    return result
53
54
55##
56# @brief
57# @param basename_in
58# @param basename_out
59# @param verbose
60# @param easting_min
61# @param easting_max
62# @param northing_min
63# @param northing_max
64def _dem2pts(name_in, name_out=None, verbose=False,
65            easting_min=None, easting_max=None,
66            northing_min=None, northing_max=None):
67    """Read Digitial Elevation model from the following NetCDF format (.dem)
68
69    Internal function. See public function dem2pts for details.
70    """
71
72    # FIXME: Can this be written feasibly using write_pts?
73
74    import os
75    from Scientific.IO.NetCDF import NetCDFFile
76
77    root = name_in[:-4]
78
79    if name_in[-4:] == '.asc':
80        intermediate = root + '.dem'
81        if verbose:
82            log.critical('Preconvert %s from asc to %s' % \
83                                    (name_in, intermediate))
84        asc2dem(name_in)
85        name_in = intermediate
86    elif name_in[-4:] != '.dem':
87        raise IOError('Input file %s should be of type .asc or .dem.' % name_in)
88
89    if name_out != None and basename_out[-4:] != '.pts':
90        raise IOError('Input file %s should be of type .pts.' % name_out)
91
92    # Get NetCDF
93    infile = NetCDFFile(name_in, netcdf_mode_r) 
94
95    if verbose: log.critical('Reading DEM from %s' % (name_in))
96
97    ncols = infile.ncols[0]
98    nrows = infile.nrows[0]
99    xllcorner = infile.xllcorner[0]  # Easting of lower left corner
100    yllcorner = infile.yllcorner[0]  # Northing of lower left corner
101    cellsize = infile.cellsize[0]
102    NODATA_value = infile.NODATA_value[0]
103    dem_elevation = infile.variables['elevation']
104
105    zone = infile.zone[0]
106    false_easting = infile.false_easting[0]
107    false_northing = infile.false_northing[0]
108
109    # Text strings
110    projection = infile.projection
111    datum = infile.datum
112    units = infile.units
113
114    # Get output file
115    if name_out == None:
116        ptsname = root + '.pts'
117    else:
118        ptsname = name_out
119
120    if verbose: log.critical('Store to NetCDF file %s' % ptsname)
121
122    # NetCDF file definition
123    outfile = NetCDFFile(ptsname, netcdf_mode_w)
124
125    # Create new file
126    outfile.institution = 'Geoscience Australia'
127    outfile.description = 'NetCDF pts format for compact and portable ' \
128                          'storage of spatial point data'
129
130    # Assign default values
131    if easting_min is None: easting_min = xllcorner
132    if easting_max is None: easting_max = xllcorner + ncols*cellsize
133    if northing_min is None: northing_min = yllcorner
134    if northing_max is None: northing_max = yllcorner + nrows*cellsize
135
136    # Compute offsets to update georeferencing
137    easting_offset = xllcorner - easting_min
138    northing_offset = yllcorner - northing_min
139
140    # Georeferencing
141    outfile.zone = zone
142    outfile.xllcorner = easting_min # Easting of lower left corner
143    outfile.yllcorner = northing_min # Northing of lower left corner
144    outfile.false_easting = false_easting
145    outfile.false_northing = false_northing
146
147    outfile.projection = projection
148    outfile.datum = datum
149    outfile.units = units
150
151    # Grid info (FIXME: probably not going to be used, but heck)
152    outfile.ncols = ncols
153    outfile.nrows = nrows
154
155    dem_elevation_r = num.reshape(dem_elevation, (nrows, ncols))
156    totalnopoints = nrows*ncols
157
158    # Calculating number of NODATA_values for each row in clipped region
159    # FIXME: use array operations to do faster
160    nn = 0
161    k = 0
162    i1_0 = 0
163    j1_0 = 0
164    thisj = 0
165    thisi = 0
166    for i in range(nrows):
167        y = (nrows-i-1)*cellsize + yllcorner
168        for j in range(ncols):
169            x = j*cellsize + xllcorner
170            if easting_min <= x <= easting_max \
171               and northing_min <= y <= northing_max:
172                thisj = j
173                thisi = i
174                if dem_elevation_r[i,j] == NODATA_value:
175                    nn += 1
176
177                if k == 0:
178                    i1_0 = i
179                    j1_0 = j
180
181                k += 1
182
183    index1 = j1_0
184    index2 = thisj
185
186    # Dimension definitions
187    nrows_in_bounding_box = int(round((northing_max-northing_min)/cellsize))
188    ncols_in_bounding_box = int(round((easting_max-easting_min)/cellsize))
189
190    clippednopoints = (thisi+1-i1_0)*(thisj+1-j1_0)
191    nopoints = clippednopoints-nn
192
193    clipped_dem_elev = dem_elevation_r[i1_0:thisi+1,j1_0:thisj+1]
194
195    if verbose:
196        log.critical('There are %d values in the elevation' % totalnopoints)
197        log.critical('There are %d values in the clipped elevation'
198                     % clippednopoints)
199        log.critical('There are %d NODATA_values in the clipped elevation' % nn)
200
201    outfile.createDimension('number_of_points', nopoints)
202    outfile.createDimension('number_of_dimensions', 2) #This is 2d data
203
204    # Variable definitions
205    outfile.createVariable('points', netcdf_float, ('number_of_points',
206                                                    'number_of_dimensions'))
207    outfile.createVariable('elevation', netcdf_float, ('number_of_points',))
208
209    # Get handles to the variables
210    points = outfile.variables['points']
211    elevation = outfile.variables['elevation']
212
213    lenv = index2-index1+1
214
215    # Store data
216    global_index = 0
217    # for i in range(nrows):
218    for i in range(i1_0, thisi+1, 1):
219        if verbose and i % ((nrows+10)/10) == 0:
220            log.critical('Processing row %d of %d' % (i, nrows))
221
222        lower_index = global_index
223
224        v = dem_elevation_r[i,index1:index2+1]
225        no_NODATA = num.sum(v == NODATA_value)
226        if no_NODATA > 0:
227            newcols = lenv - no_NODATA  # ncols_in_bounding_box - no_NODATA
228        else:
229            newcols = lenv              # ncols_in_bounding_box
230
231        telev = num.zeros(newcols, num.float)
232        tpoints = num.zeros((newcols, 2), num.float)
233
234        local_index = 0
235
236        y = (nrows-i-1)*cellsize + yllcorner
237        #for j in range(ncols):
238        for j in range(j1_0,index2+1,1):
239            x = j*cellsize + xllcorner
240            if easting_min <= x <= easting_max \
241               and northing_min <= y <= northing_max \
242               and dem_elevation_r[i,j] != NODATA_value:
243                tpoints[local_index, :] = [x-easting_min, y-northing_min]
244                telev[local_index] = dem_elevation_r[i, j]
245                global_index += 1
246                local_index += 1
247
248        upper_index = global_index
249
250        if upper_index == lower_index + newcols:
251            points[lower_index:upper_index, :] = tpoints
252            elevation[lower_index:upper_index] = telev
253
254    assert global_index == nopoints, 'index not equal to number of points'
255
256    infile.close()
257    outfile.close()
258
Note: See TracBrowser for help on using the repository browser.