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

root/raw2proc/trunk/raw2proc/proc_codar_totals.py

Revision 490 (checked in by haines, 12 years ago)

update both proc_cr1000_ctd and proc_sbe37_ctd to recover more data for b2

Line 
1 #!/usr/bin/env python
2 # Last modified:  Time-stamp: <2012-05-01 10:39:23 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>2:
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        
99         if 'TOT4' in ftype:
100             lon = d[:,0]
101             lat = d[:,1]
102             wu = d[:,2]
103             wv = d[:,3]
104             gridflag = d[:,4]
105             wu_std_qual = d[:,5]
106             wv_std_qual = d[:,6]
107             cov_qual = d[:,7]
108             x_dist = d[:,8]
109             y_dist = d[:,9]
110             rang = d[:,10]
111             bearing = d[:,11]
112             vel_mag = d[:,12]
113             vel_dir = d[:,13]
114             s1 = d[:,14]
115             s2 = d[:,15]
116             s3 = d[:,16]
117             s4 = d[:,17]
118             s5 = d[:,18]
119             s6 = d[:,19]
120
121             try:
122                 uim = griddata(lon, lat, wu, xi, yi)
123                 vim = griddata(lon, lat, wv, xi, yi)
124                 # returned masked array as an ndarray with masked values filled with fill_value
125                 ui = uim.filled(fill_value=numpy.nan)
126                 vi = vim.filled(fill_value=numpy.nan)
127                 # print ui.shape
128             except IndexError:
129                 print "raw2proc:  IndexError in griddata() -- skipping data"
130
131     # ---------------------------------------------------------------
132     i = 0
133     data['dt'][i] =  sample_dt #
134     data['time'][i] =  dt2es(sample_dt) #
135     data['lon'] = xi # new longitude grid
136     data['lat'] = yi # new latitude grid
137
138     if nrow and nrow>2:
139         # use transpose so order is (time, x, y) for netcdf convention
140         data['u'][i] = ui.T # u-component of water velocity (cm/s)
141         data['v'][i] = vi.T # v-component of water velocity
142
143     return data
144
145 def creator(platform_info, sensor_info, data):
146     #
147     #
148     title_str = sensor_info['description']+' at '+ platform_info['location']
149     global_atts = {
150         'title' : title_str,
151         'institution' : 'University of North Carolina at Chapel Hill (UNC-CH)',
152         'institution_url' : 'http://nccoos.unc.edu',
153         'institution_dods_url' : 'http://nccoos.unc.edu',
154         'metadata_url' : 'http://nccoos.unc.edu',
155         'references' : 'http://nccoos.unc.edu',
156         'contact' : 'Sara Haines (haines@email.unc.edu)',
157         #
158         'source' : 'surface current observation',
159         'history' : 'raw2proc using ' + sensor_info['process_module'],
160         'comment' : 'File created using pycdf'+pycdfVersion()+' and numpy '+pycdfArrayPkg(),
161         # conventions
162         'Conventions' : 'CF-1.0; SEACOOS-CDL-v2.0',
163         # SEACOOS CDL codes
164         'format_category_code' : 'fixed-map',
165         'institution_code' : platform_info['institution'],
166         'platform_code' : platform_info['id'],
167         'package_code' : sensor_info['id'],
168         # institution specific
169         'project' : 'North Carolina Coastal Ocean Observing System (NCCOOS)',
170         'project_url' : 'http://nccoos.org',
171         # timeframe of data contained in file yyyy-mm-dd HH:MM:SS
172         'start_date' : data['dt'][0].strftime("%Y-%m-%d %H:%M:%S"),
173         'end_date' : data['dt'][-1].strftime("%Y-%m-%d %H:%M:%S"),
174         'release_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
175         #
176         'creation_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
177         'modification_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
178         'process_level' : 'level1',
179         #
180         # must type match to data (e.g. fillvalue is real if data is real)
181         '_FillValue' : numpy.nan,
182         }
183
184     var_atts = {
185         # coordinate variables
186         'time' : {'short_name': 'time',
187                   'long_name': 'Time',
188                   'standard_name': 'time',
189                   'units': 'seconds since 1970-1-1 00:00:00 -0', # UTC
190                   'axis': 'T',
191                   },
192         'lat' : {'short_name': 'lat',
193              'long_name': 'Latitude',
194              'standard_name': 'latitude',
195              'reference':'geographic coordinates',
196              'units': 'degrees_north',
197              'valid_range':(-90.,90.),
198              'axis': 'Y',
199              },
200         'lon' : {'short_name': 'lon',
201                  'long_name': 'Longitude',
202                  'standard_name': 'longitude',
203                  'reference':'geographic coordinates',
204                  'units': 'degrees_east',
205                  'valid_range':(-180.,180.),
206                  'axis': 'Y',
207                  },
208         'z' : {'short_name': 'z',
209                'long_name': 'Height',
210                'standard_name': 'height',
211                'reference':'zero at sea-surface',
212                'units': 'm',
213                'axis': 'Z',
214                },
215         # data variables
216         'u' : {'short_name': 'u',
217                'long_name': 'E/W component of current',
218                'standard_name': 'eastward_current',
219                'units': 'cm sec-1',
220                'reference' : 'clockwise from True East',
221                 },
222         'v' : {'short_name': 'v',
223                'long_name': 'N/S component of current',
224                'standard_name': 'northward_current',
225                'units': 'cm sec-1',
226                'reference' : 'clockwise from True North',
227                 },
228         }
229
230    
231     # dimension names use tuple so order of initialization is maintained
232     dim_inits = (
233         ('ntime', NC.UNLIMITED),
234         ('nlat', platform_info['nlat']),
235         ('nlon', platform_info['nlon']),
236         ('nz', 1),
237         )
238    
239     # using tuple of tuples so order of initialization is maintained
240     # using dict for attributes order of init not important
241     # use dimension names not values
242     # (varName, varType, (dimName1, [dimName2], ...))
243     var_inits = (
244         # coordinate variables
245         ('time', NC.INT, ('ntime',)),
246         ('lat', NC.FLOAT, ('nlat',)),
247         ('lon', NC.FLOAT, ('nlon',)),
248         ('z',  NC.FLOAT, ('nz',)),
249         # data variables
250         ('u', NC.FLOAT, ('ntime','nlon','nlat')),
251         ('v', NC.FLOAT, ('ntime','nlon','nlat')),
252         )
253    
254     # subset data only to month being processed (see raw2proc.process())
255     i = data['in']
256
257     # var data
258     var_data = (
259         ('lat', data['lat']),
260         ('lon', data['lon']),
261         ('z', 0.),
262         #
263         ('time', data['time'][i]),
264         ('u', data['u'][i]),
265         ('v', data['v'][i]),
266         )
267
268     return (global_atts, var_atts, dim_inits, var_inits, var_data)
269
270 def updater(platform_info, sensor_info, data):
271     #
272     global_atts = {
273         # update times of data contained in file (yyyy-mm-dd HH:MM:SS)
274         # last date in monthly file
275         'end_date' : data['dt'][-1].strftime("%Y-%m-%d %H:%M:%S"),
276         'release_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
277         #
278         'modification_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
279         }
280
281     # data variables
282     # update any variable attributes like range, min, max
283     var_atts = {}
284     # var_atts = {
285     #    'u': {'max': max(data.u),
286     #          'min': min(data.v),
287     #          },
288     #    'v': {'max': max(data.u),
289     #          'min': min(data.v),
290     #          },
291     #    }
292    
293     # subset data only to month being processed (see raw2proc.process())
294     i = data['in']
295
296     # data
297     var_data = (
298         ('time', data['time'][i]),
299         ('u', data['u'][i]),
300         ('v', data['v'][i]),
301        )
302
303     return (global_atts, var_atts, var_data)
304
305 #
Note: See TracBrowser for help on using the browser.