NCCOOS Trac Projects: Top | Web | Platforms | Processing | Viz | Sprints | Sandbox | (Wind)

root/raw2proc/trunk/raw2proc/proc_codar_totals.py

Revision 336 (checked in by haines, 14 years ago)

added CODAR Total processing

Line 
1 #!/usr/bin/env python
2 # Last modified:  Time-stamp: <2010-07-30 12:57:22 haines>
3 """
4 how to parse data, and assert what data and info goes into
5 creating and updating monthly netcdf files
6
7 CODAR SeaSonde Total Sea Surface Currents (LLUV TOT4)
8
9 parser : sample date and time from header (%TimeStamp:)
10          table time version (%TableType:)
11 creator : lat, lon, z, time, u(time, lat, lon), v(time, lat, lon),
12 updater : time, u(time, lat, lon), v(time, lat, lon),
13
14 Check that grid that totals are calculated over has not changed.
15 (%Origin, %GridAxis, %GridAxisType, %GridSpacing all the same)
16
17 Examples
18 --------
19
20 >> (parse, create, update) = load_processors(module_name_without_dot_py)
21 For example,
22 >> (parse, create, update) = load_processors('proc_rdi_logdata_adcp')
23 or
24 >> si = get_config(cn+'.sensor_info')
25 >> (parse, create, update) = load_processors(si['adcp']['proc_module'])
26
27 Then use the generic name of processor to parse data, create or update
28 monthly output file
29
30 >> lines = load_data(filename)
31 >> data = parse(platform_info, sensor_info, lines)
32 >> create(platform_info, sensor_info, data)
33 or
34 >> update(platform_info, sensor_info, data)
35
36 """
37
38 from raw2proc import *
39 from procutil import *
40 from ncutil import *
41
42 now_dt = datetime.utcnow()
43 now_dt.replace(microsecond=0)
44
45 def parser(platform_info, sensor_info, lines):
46     """
47     parse and assign data to variables from CODAR Totals LLUV format
48
49     Notes
50     -----
51     1. Requires grid definition obtained from sensor_info
52     For best coverage of totals, this includes overlapping foot print of HATY, DUCK, LISL and CEDR
53     
54     """
55
56     import numpy
57     from datetime import datetime
58     from time import strptime
59     from StringIO import StringIO
60     from matplotlib.mlab import griddata
61
62     # define the lat/lon grid based on 6km resolution
63     minlat, maxlat = platform_info['lat'] # (34.5, 38)
64     minlon, maxlon = platform_info['lon'] # (-76, -73.)
65     nlat = platform_info['nlat']
66     nlon = platform_info['nlon']
67     yi = numpy.linspace(minlat, maxlat, nlat)
68     xi = numpy.linspace(minlon, maxlon, nlon)
69
70     data = {
71         'dt' : numpy.array(numpy.ones((1,), dtype=object)*numpy.nan),
72         'time' : numpy.array(numpy.ones((1,), dtype=long)*numpy.nan),
73         'lon' : numpy.array(numpy.ones((nlon,), dtype=float)*numpy.nan),
74         'lat' : numpy.array(numpy.ones((nlat,), dtype=float)*numpy.nan),
75         'u' : numpy.array(numpy.ones((1,nlon,nlat), dtype=float)*numpy.nan),
76         'v' : numpy.array(numpy.ones((1,nlon,nlat), dtype=float)*numpy.nan),
77         }
78
79     sample_dt, ftype, ncol, nrow = (None, None, None, None)
80     # read header that match '%(k): (v)\n' pairs on each line
81     m = re.findall(r'^(%.*):\s*(.*)$', ''.join(lines), re.MULTILINE)
82     for k,v in m:
83         if k == '%TimeStamp':
84             sample_dt = scanf_datetime(v, fmt='%Y %m %d %H %M %S')           
85         elif k == '%TableType':
86             ftype = v
87         elif k == '%TableColumns':
88             ncol = int(v)
89         elif k == '%TableRows':
90             nrow = int(v)
91
92     if nrow:
93         # read data from string of lines but make it behave like a file object with StringIO
94         s = StringIO(''.join(lines))
95         s.seek(0) # ensures start posn of file
96         d = numpy.loadtxt(s, comments='%')
97         # lat, lon, u, v = numpy.loadtxt(s, usecols=(0,1,2,3), comments='%', unpack=True)
98         if 'TOT4' in ftype:
99             lon = d[:,0]
100             lat = d[:,1]
101             wu = d[:,2]
102             wv = d[:,3]
103             gridflag = d[:,4]
104             wu_std_qual = d[:,5]
105             wv_std_qual = d[:,6]
106             cov_qual = d[:,7]
107             x_dist = d[:,8]
108             y_dist = d[:,9]
109             rang = d[:,10]
110             bearing = d[:,11]
111             vel_mag = d[:,12]
112             vel_dir = d[:,13]
113             s1 = d[:,14]
114             s2 = d[:,15]
115             s3 = d[:,16]
116             s4 = d[:,17]
117             s5 = d[:,18]
118             s6 = d[:,19]
119
120             uim = griddata(lon, lat, wu, xi, yi)
121             vim = griddata(lon, lat, wv, xi, yi)
122             # returned masked array as an ndarray with masked values filled with fill_value
123             ui = uim.filled(fill_value=numpy.nan)
124             vi = vim.filled(fill_value=numpy.nan)
125
126     # ---------------------------------------------------------------
127
128     i = 0
129     data['dt'][i] =  sample_dt #
130     data['time'][i] =  dt2es(sample_dt) #
131     data['lon'] = xi # new longitude grid
132     data['lat'] = yi # new latitude grid
133
134     if nrow:
135         # use transpose so order is (time, x, y) for netcdf convention
136         data['u'][i] = ui.T # u-component of water velocity (cm/s)
137         data['v'][i] = vi.T # v-component of water velocity
138
139     return data
140
141 def creator(platform_info, sensor_info, data):
142     #
143     #
144     title_str = sensor_info['description']+' at '+ platform_info['location']
145     global_atts = {
146         'title' : title_str,
147         'institution' : 'University of North Carolina at Chapel Hill (UNC-CH)',
148         'institution_url' : 'http://nccoos.unc.edu',
149         'institution_dods_url' : 'http://nccoos.unc.edu',
150         'metadata_url' : 'http://nccoos.unc.edu',
151         'references' : 'http://nccoos.unc.edu',
152         'contact' : 'Sara Haines (haines@email.unc.edu)',
153         #
154         'source' : 'surface current observation',
155         'history' : 'raw2proc using ' + sensor_info['process_module'],
156         'comment' : 'File created using pycdf'+pycdfVersion()+' and numpy '+pycdfArrayPkg(),
157         # conventions
158         'Conventions' : 'CF-1.0; SEACOOS-CDL-v2.0',
159         # SEACOOS CDL codes
160         'format_category_code' : 'fixed-map',
161         'institution_code' : platform_info['institution'],
162         'platform_code' : platform_info['id'],
163         'package_code' : sensor_info['id'],
164         # institution specific
165         'project' : 'North Carolina Coastal Ocean Observing System (NCCOOS)',
166         'project_url' : 'http://nccoos.org',
167         # timeframe of data contained in file yyyy-mm-dd HH:MM:SS
168         'start_date' : data['dt'][0].strftime("%Y-%m-%d %H:%M:%S"),
169         'end_date' : data['dt'][-1].strftime("%Y-%m-%d %H:%M:%S"),
170         'release_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
171         #
172         'creation_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
173         'modification_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
174         'process_level' : 'level1',
175         #
176         # must type match to data (e.g. fillvalue is real if data is real)
177         '_FillValue' : numpy.nan,
178         }
179
180     var_atts = {
181         # coordinate variables
182         'time' : {'short_name': 'time',
183                   'long_name': 'Time',
184                   'standard_name': 'time',
185                   'units': 'seconds since 1970-1-1 00:00:00 -0', # UTC
186                   'axis': 'T',
187                   },
188         'lat' : {'short_name': 'lat',
189              'long_name': 'Latitude',
190              'standard_name': 'latitude',
191              'reference':'geographic coordinates',
192              'units': 'degrees_north',
193              'valid_range':(-90.,90.),
194              'axis': 'Y',
195              },
196         'lon' : {'short_name': 'lon',
197                  'long_name': 'Longitude',
198                  'standard_name': 'longitude',
199                  'reference':'geographic coordinates',
200                  'units': 'degrees_east',
201                  'valid_range':(-180.,180.),
202                  'axis': 'Y',
203                  },
204         'z' : {'short_name': 'z',
205                'long_name': 'Height',
206                'standard_name': 'height',
207                'reference':'zero at sea-surface',
208                'units': 'm',
209                'axis': 'Z',
210                },
211         # data variables
212         'u' : {'short_name': 'u',
213                'long_name': 'E/W component of current',
214                'standard_name': 'eastward_current',
215                'units': 'cm sec-1',
216                'reference' : 'clockwise from True East',
217                 },
218         'v' : {'short_name': 'v',
219                'long_name': 'N/S component of current',
220                'standard_name': 'northward_current',
221                'units': 'cm sec-1',
222                'reference' : 'clockwise from True North',
223                 },
224         }
225
226    
227     # dimension names use tuple so order of initialization is maintained
228     dim_inits = (
229         ('ntime', NC.UNLIMITED),
230         ('nlat', platform_info['nlat']),
231         ('nlon', platform_info['nlon']),
232         ('nz', 1),
233         )
234    
235     # using tuple of tuples so order of initialization is maintained
236     # using dict for attributes order of init not important
237     # use dimension names not values
238     # (varName, varType, (dimName1, [dimName2], ...))
239     var_inits = (
240         # coordinate variables
241         ('time', NC.INT, ('ntime',)),
242         ('lat', NC.FLOAT, ('nlat',)),
243         ('lon', NC.FLOAT, ('nlon',)),
244         ('z',  NC.FLOAT, ('nz',)),
245         # data variables
246         ('u', NC.FLOAT, ('ntime','nlon','nlat')),
247         ('v', NC.FLOAT, ('ntime','nlon','nlat')),
248         )
249    
250     # subset data only to month being processed (see raw2proc.process())
251     i = data['in']
252
253     # var data
254     var_data = (
255         ('lat', data['lat']),
256         ('lon', data['lon']),
257         ('z', 0.),
258         #
259         ('time', data['time'][i]),
260         ('u', data['u'][i]),
261         ('v', data['v'][i]),
262         )
263
264     return (global_atts, var_atts, dim_inits, var_inits, var_data)
265
266 def updater(platform_info, sensor_info, data):
267     #
268     global_atts = {
269         # update times of data contained in file (yyyy-mm-dd HH:MM:SS)
270         # last date in monthly file
271         'end_date' : data['dt'][-1].strftime("%Y-%m-%d %H:%M:%S"),
272         'release_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
273         #
274         'modification_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
275         }
276
277     # data variables
278     # update any variable attributes like range, min, max
279     var_atts = {}
280     # var_atts = {
281     #    'u': {'max': max(data.u),
282     #          'min': min(data.v),
283     #          },
284     #    'v': {'max': max(data.u),
285     #          'min': min(data.v),
286     #          },
287     #    }
288     
289     # subset data only to month being processed (see raw2proc.process())
290     i = data['in']
291
292     # data
293     var_data = (
294         ('time', data['time'][i]),
295         ('u', data['u'][i]),
296         ('v', data['v'][i]),
297        )
298
299     return (global_atts, var_atts, var_data)
300
301 #
302
Note: See TracBrowser for help on using the browser.