source: inundation/pyvolution/ermapper_grids.py @ 1869

Last change on this file since 1869 was 1835, checked in by ole, 19 years ago

Implemented tms file format (like sww without x, y)
Fixed broken test in sww2ers

File size: 9.3 KB
Line 
1#!/usr/bin/env python
2
3# from os import open, write, read
4import Numeric
5
6def write_ermapper_grid(ofile, data, header = {}):
7    """
8    write_ermapper_grid(ofile, data, header = {}):
9   
10    Function to write a 2D Numeric array to an ERMapper grid.  There are a series of conventions adopted within
11    this code, specifically:
12    1)  The registration coordinate for the data is the SW (or lower-left) corner of the data
13    2)  The registration coordinates refer to cell centres
14    3)  The data is a 2D Numeric array with the NW-most data in element (0,0) and the SE-most data in element (N,M)
15        where N is the last line and M is the last column
16    4)  There has been no testng of the use of a rotated grid.  Best to keep data in an NS orientation
17   
18    Input Parameters:
19    ofile:      string - filename for output (note the output will consist of two files
20                ofile and ofile.ers.  Either of these can be entered into this function
21    data:       Numeric.array - 2D array containing the data to be output to the grid
22    header:     dictionary - contains spatial information about the grid, in particular:
23                    header['datum'] datum for the data ('"GDA94"')
24                    header['projection'] - either '"GEOGRAPHIC"' or '"PROJECTED"'
25                    header['coordinatetype'] - either 'EN' (for eastings/northings) or
26                                                      'LL' (for lat/long)
27                    header['rotation'] - rotation of grid ('0:0:0.0')
28                    header['celltype'] - data type for writing data ('IEEE4ByteReal')
29                    header['nullcellvalue'] - value for null cells ('-99999')
30                    header['xdimension'] - cell size in x-dir in units dictated by 'coordinatetype' ('100')
31                    header['registrationcellx'] == '0'
32                    header['ydimension'] - cell size in y-dir in units dictated by 'coordinatetype' ('100')
33                    header['longitude'] - co-ordinate of registration cell ('0:0:0')
34                    header['latitude'] - co-ordinate of registration line ('0:0:0')
35                    header['nrofbands'] - number of bands ('1')
36                    header['value'] - name of grid ('"Default_Band"')
37
38                    Some entries are determined automatically from the data
39                    header['nroflines'] - number of lines in data
40                    header['nrofcellsperline'] - number of columns in data
41                    header['registrationcelly'] == last line of data
42    """
43    # extract filenames for header and data files from ofile
44    ers_index = ofile.find('.ers')
45    if ers_index > 0:
46        data_file = ofile[0:ers_index]
47        header_file = ofile
48    else:
49        data_file = ofile
50        header_file = ofile + '.ers'
51
52
53    # Check that the data is a 2 dimensional array
54    data_size = Numeric.shape(data)
55    assert len(data_size) == 2
56   
57    header['nroflines'] = str(data_size[0])
58    header['nrofcellsperline'] = str(data_size[1])
59
60    write_ermapper_data(data,data_file)
61    write_ermapper_header(header_file,header)
62   
63def read_ermapper_grid(ifile):
64
65    ers_index = ifile.find('.ers')
66    if ers_index > 0:
67        data_file = ifile[0:ers_index]
68        header_file = ifile
69    else:
70        data_file = ifile
71        header_file = ifile + '.ers'
72       
73    header = read_ermapper_header(header_file)
74
75    nroflines = int(header['nroflines'])
76    nrofcellsperlines = int(header['nrofcellsperline'])
77    data = read_ermapper_data(data_file)
78    data = Numeric.reshape(data,(nroflines,nrofcellsperlines))
79    return data
80   
81
82def write_ermapper_header(ofile, header = {}):
83   
84    header = create_default_header(header)
85    # Determine if the dataset is in lats/longs or eastings/northings and set header parameters
86    # accordingly
87    if header['coordinatetype'] == 'LL':
88        X_Class = 'Longitude'
89        Y_Class = 'Latitude'
90    elif header['coordinatetype'] == 'EN':
91        X_Class = 'Eastings'
92        Y_Class = 'Northings'
93
94    # open the header file for writing to
95    fid = open(ofile,'wt')
96
97    # Begin writing the header
98    fid.write('DatasetHeader Begin\n')
99    fid.write('\tVersion\t\t= "6.4"\n')
100    fid.write('\tDatasetType\t= ERStorage\n')
101    fid.write('\tDataType\t= Raster\n')
102    fid.write('\tByteOrder\t= LSBFirst\n')
103
104    # Write the coordinate space information
105    fid.write('\tCoordinateSpace Begin\n')
106    fid.write('\t\tDatum\t\t\t = ' + header['datum'] + '\n')
107    fid.write('\t\tProjection\t\t = ' + header['projection'] + '\n')
108    fid.write('\t\tCoordinateType\t = ' + header['coordinatetype'] + '\n')
109    fid.write('\t\tRotation\t\t = ' + header['rotation'] + '\n')
110    fid.write('\t\tUnits\t\t = ' + header['units'] + '\n')
111    fid.write('\tCoordinateSpace End\n')
112
113    # Write the raster information
114    fid.write('\tRasterInfo Begin\n')
115    fid.write('\t\tCellType\t\t\t = ' + header['celltype'] + '\n')
116    fid.write('\t\tNullCellValue\t\t = ' + header['nullcellvalue'] + '\n')
117    fid.write('\t\tRegistrationCellX\t\t = ' + header['registrationcellx'] +'\n')
118    fid.write('\t\tRegistrationCellY\t\t = ' + header['registrationcelly'] +'\n')
119    # Write the cellsize information
120    fid.write('\t\tCellInfo Begin\n')
121    fid.write('\t\t\tXDimension\t\t\t = ' + header['xdimension'] + '\n')
122    fid.write('\t\t\tYDimension\t\t\t = ' + header['ydimension'] + '\n')
123    fid.write('\t\tCellInfo End\n')
124    # Continue with wrting the raster information
125    fid.write('\t\tNrOfLines\t\t\t = ' + header['nroflines'] + '\n')
126    fid.write('\t\tNrOfCellsPerLine\t = ' + header['nrofcellsperline'] + '\n')
127    # Write the registration coordinate information
128    fid.write('\t\tRegistrationCoord Begin\n')
129    ###print X_Class
130    fid.write('\t\t\t' + X_Class + '\t\t\t = ' + header[X_Class.lower()] + '\n')
131    fid.write('\t\t\t' + Y_Class + '\t\t\t = ' + header[Y_Class.lower()] + '\n')
132    fid.write('\t\tRegistrationCoord End\n')
133    # Continue with wrting the raster information
134    fid.write('\t\tNrOfBands\t\t\t = ' + header['nrofbands'] + '\n')
135    fid.write('\t\tBandID Begin\n')
136    fid.write('\t\t\tValue\t\t\t\t = ' + header['value'] + '\n')
137    fid.write('\t\tBandID End\n')
138    fid.write('\tRasterInfo End\n')
139    fid.write('DatasetHeader End\n')
140   
141    fid.close
142
143def read_ermapper_header(ifile):
144    # function for reading an ERMapper header from file
145    header = {}
146
147    fid = open(ifile,'rt')
148    header_string = fid.readlines()
149    fid.close()
150
151    for line in header_string:
152        if line.find('=') > 0:
153            tmp_string = line.strip().split('=')
154            header[tmp_string[0].strip().lower()]= tmp_string[1].strip()
155
156    return header                     
157
158def write_ermapper_data(grid, ofile, data_format = Numeric.Float32):
159    # Convert the array to data_format (default format is Float32)
160    grid_as_float = grid.astype(data_format)
161
162    # Convert array to a string for writing to output file
163    output_string = grid_as_float.tostring()
164
165    # open output file in a binary format and write the output string
166    fid = open(ofile,'wb')
167    fid.write(output_string)
168    fid.close()
169
170
171def read_ermapper_data(ifile, data_format = Numeric.Float32):
172    # open input file in a binary format and read the input string
173    fid = open(ifile,'rb')
174    input_string = fid.read()
175    fid.close()
176
177    # convert input string to required format (Note default format is Numeric.Float32)
178    grid_as_float = Numeric.fromstring(input_string,data_format)
179    return grid_as_float
180
181def create_default_header(header = {}):
182    # fill any blanks in a header dictionary with default values
183    # input parameters:
184    # header:   a dictionary containing fields that are not meant
185    #           to be filled with default values
186   
187 
188    if not header.has_key('datum'):
189        header['datum'] = '"GDA94"'
190    if not header.has_key('projection'):
191        header['projection'] = '"GEOGRAPHIC"'       
192    if not header.has_key('coordinatetype'):
193        header['coordinatetype'] = 'LL'
194    if not header.has_key('rotation'):
195        header['rotation'] = '0:0:0.0'
196    if not header.has_key('units'):
197        header['units'] = '"METERS"'
198    if not header.has_key('celltype'):
199        header['celltype'] = 'IEEE4ByteReal'
200    if not header.has_key('nullcellvalue'):
201        header['nullcellvalue'] = '-99999'
202    if not header.has_key('xdimension'):
203        header['xdimension'] = '100'
204    if not header.has_key('latitude'):
205        header['latitude'] = '0:0:0'
206    if not header.has_key('longitude'):
207        header['longitude'] = '0:0:0'       
208    if not header.has_key('ydimension'):
209        header['ydimension'] = '100'
210    if not header.has_key('nroflines'):
211        header['nroflines'] = '3'   
212    if not header.has_key('nrofcellsperline'):
213        header['nrofcellsperline'] = '4'
214    if not header.has_key('registrationcellx'):
215        header['registrationcellx'] = '0'
216    if not header.has_key('registrationcelly'):
217        header['registrationcelly'] = str(int(header['nroflines'])-1)
218    if not header.has_key('nrofbands'):
219        header['nrofbands'] = '1'
220    if not header.has_key('value'):
221        header['value'] = '"Default_Band"'
222
223
224    return header   
225                         
226   
227
228
229   
Note: See TracBrowser for help on using the repository browser.