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

root/raw2proc/trunk/raw2proc/proc_rdi_logdata_adcp.py

Revision 125 (checked in by haines, 16 years ago)

added short_names to proc_rdi_logdata_adcp

Line 
1 #!/usr/bin/env python
2 # Last modified:  Time-stamp: <2008-03-20 16:27:50 haines>
3 """
4 how to parse data, and assert what data and info goes into
5 creating and updating monthly netcdf files
6
7 RDI/Wavesmon processed adcp current profile data
8
9 parser : sample date and time, ensemble number, currents
10          and wave summary output from WavesMon software
11 creator : lat, lon, z, time, ens, u, v
12 updator : time, ens, u, v
13
14
15 Examples
16 --------
17
18 >> (parse, create, update) = load_processors('proc_rdi_logdata_adcp')
19 or
20 >> si = get_config(cn+'.sensor_info')
21 >> (parse, create, update) = load_processors(si['adcp']['proc_module'])
22
23 >> lines = load_data(filename)
24 >> data = parse(platform_info, sensor_info, lines)
25 >> create(platform_info, sensor_info, data) or
26 >> update(platform_info, sensor_info, data)
27
28 """
29
30
31 from raw2proc import *
32 from procutil import *
33 from ncutil import *
34
35 now_dt = datetime.utcnow()
36 now_dt.replace(microsecond=0)
37
38 def parser(platform_info, sensor_info, lines):
39     """
40     parse and assign currents data from RDI ADCP Log Data
41
42     """
43  
44     i = 0
45    
46     for line in lines:
47         # split line and parse float and integers
48         rdi = []
49         sw = re.split(',', line)
50         for s in sw:
51             m = re.search(REAL_RE_STR, s)
52             if m:
53                 rdi.append(float(m.groups()[0]))
54
55         # assign specific fields
56         n = len(rdi)
57         burst_num = int(rdi[0]) # Ensemble Number
58
59         # get sample datetime from data
60         sample_str = '%02d-%02d-%02d %02d:%02d:%02d' % tuple(rdi[1:7])
61         if  sensor_info['utc_offset']:
62             sample_dt = scanf_datetime(sample_str, fmt='%y-%m-%d %H:%M:%S') + \
63                         timedelta(hours=sensor_info['utc_offset'])
64         else:
65             sample_dt = scanf_datetime(sample_str, fmt='%y-%m-%d %H:%M:%S')
66         #   datetime(*strptime(sample_str, "%y-%m-%d %H:%M:%S")[0:6])
67
68         # get sample datetime from filename
69         # compare with datetime from filename
70
71         sig_wave_ht = rdi[8]         # Significant Wave Height (Hs, meters)
72         peak_wave_period = rdi[9]    # Peak Wave Period (Tp, sec)
73         peak_wave_dir = rdi[10]      # Peak Wave Direction (deg N)
74         max_wave_ht = rdi[12]        # Maximum Wave Height (Hmax, meters)
75         max_wave_period = rdi[13]    # Maximum Wave Period (Tmax, sec)
76
77         water_depth = rdi[11]/1000   # Water Depth (meters) (based on ADCP backscatter or input config??)
78         nbins = int(rdi[14])         # Number of bins
79
80         current_spd = numpy.array(rdi[15::2]) # starting at idx=15 skip=2 to end
81         current_dir = numpy.array(rdi[16::2]) # starting at idx=16 skip=2 to end
82
83         if nbins!=sensor_info['nbins']:
84             print 'Number of bins reported in data ('+ \
85                   str(nbins)+') does not match config number ('+ \
86                   str(sensor_info['nbins'])+')'
87
88         if len(current_spd)!=nbins or len(current_dir)!=nbins:
89             print 'Data length does not match number of bins in data'
90
91         ibad = (current_spd==-32768) | (current_dir==-32768)
92         current_spd[ibad] = numpy.nan
93         current_dir[ibad] = numpy.nan
94
95         # these items can also be teased out of raw adcp but for now get from config file
96         th = sensor_info['transducer_ht']  # Transducer height above bottom (meters)
97         bh = sensor_info['blanking_ht']    # Blanking height above Transducer (meters)
98         bin_size = sensor_info['bin_size'] # Bin Size (meters)
99
100         # compute height for each bin above the bottom
101         bins = numpy.arange(1,nbins+1)
102         bin_habs = (bins*bin_size+bin_size/2)+th+bh
103
104         # compute water mask
105         # Using George Voulgaris' method based on water depth
106         # minus half of the significant wave height (Hs)
107         # and computed habs
108         # if positive is up, what's less than zero depth?
109         bin_depths =  bin_habs-(water_depth-sig_wave_ht/2)
110         iwater = bin_depths+bin_size/2 < 0
111
112         z = bin_habs
113         # check that length of bin_depths is equal to nbins
114         u = numpy.ones(nbins)*numpy.nan
115         v = numpy.ones(nbins)*numpy.nan
116
117         u[iwater] = current_spd[iwater]*numpy.sin(current_dir[iwater]*numpy.pi/180)
118         v[iwater] = current_spd[iwater]*numpy.cos(current_dir[iwater]*numpy.pi/180)
119
120         # set up dict of data if first line
121         if i==0:
122             data = {
123                 'en' : numpy.array(numpy.ones((len(lines),), dtype=int)*numpy.nan),
124                 'dt' : numpy.array(numpy.ones((len(lines),), dtype=object)*numpy.nan),
125                 'time' : numpy.array(numpy.ones((len(lines),), dtype=long)*numpy.nan),
126                 'z' : numpy.array(numpy.ones((nbins,), dtype=float)*numpy.nan),
127                 'u' : numpy.array(numpy.ones((len(lines),nbins), dtype=float)*numpy.nan),
128                 'v' : numpy.array(numpy.ones((len(lines),nbins), dtype=float)*numpy.nan),
129                 'water_depth' : numpy.array(numpy.ones((len(lines)), dtype=float)*numpy.nan),
130                 }
131        
132         data['en'][i] = burst_num
133         data['dt'][i] = sample_dt # sample datetime
134         data['time'][i] = dt2es(sample_dt) # sample time in epoch seconds
135         data['z'] =  z
136         data['u'][i] =  u
137         data['v'][i] =  v
138         data['water_depth'][i] = water_depth
139         i = i+1
140
141     return data
142
143 def creator(platform_info, sensor_info, data):
144     #
145     #
146     title_str = sensor_info['description']+' at '+ platform_info['location']
147     global_atts = {
148         'title' : title_str,
149         'institution' : 'Unversity of North Carolina at Chapel Hill (UNC-CH)',
150         'institution_url' : 'http://nccoos.unc.edu',
151         'institution_dods_url' : 'http://nccoos.unc.edu',
152         'metadata_url' : 'http://nccoos.unc.edu',
153         'references' : 'http://nccoos.unc.edu',
154         'contact' : 'Sara Haines (haines@email.unc.edu)',
155         #
156         'source' : 'fixed-profiler (acoustic doppler) observation',
157         'history' : 'raw2proc using ' + sensor_info['process_module'],
158         'comment' : 'File created using pycdf'+pycdfVersion()+' and numpy '+pycdfArrayPkg(),
159         # conventions
160         'Conventions' : 'CF-1.0; SEACOOS-CDL-v2.0',
161         # SEACOOS CDL codes
162         'format_category_code' : 'fixed-profiler',
163         'institution_code' : platform_info['institution'],
164         'platform_code' : platform_info['id'],
165         'package_code' : sensor_info['id'],
166         # institution specific
167         'project' : 'North Carolina Coastal Ocean Observing System (NCCOOS)',
168         'project_url' : 'http://nccoos.unc.edu',
169         # timeframe of data contained in file yyyy-mm-dd HH:MM:SS
170         # first date in monthly file
171         'start_date' : data['dt'][0].strftime("%Y-%m-%d %H:%M:%S"),
172         # last date in monthly file
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' : -99999.,
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': 'Longtitude',
202                  'standard_name': 'longtitude',
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         'en' : {'short_name' : 'en',
217                 'long_name': 'Ensemble Number',
218                  'standard_name': 'ensemble_number',                         
219                  'units': 'None',
220                  },
221         'u': {'short_name' : 'u',
222               'long_name': 'East/West Component of Current',
223               'standard_name': 'eastward_current',
224               'units': 'm s-1',
225               'reference': 'clockwise from True East',
226               },
227         'v': {'short_name' : 'v',
228               'long_name': 'North/South Component of Current',
229               'standard_name': 'northward_current',                         
230               'units': 'm s-1',
231               'reference': 'clockwise from True North',
232               },
233         'water_depth': {'short_name': 'wd',
234                         'long_name': 'Water Depth',
235                         'standard_name': 'water_depth',                         
236                         'units': 'm',
237                         },
238         }
239
240
241     # dimension names use tuple so order of initialization is maintained
242     dim_inits = (
243         ('ntime', NC.UNLIMITED),
244         ('nlat', 1),
245         ('nlon', 1),
246         ('nz', sensor_info['nbins'])
247         )
248    
249     # using tuple of tuples so order of initialization is maintained
250     # using dict for attributes order of init not important
251     # use dimension names not values
252     # (varName, varType, (dimName1, [dimName2], ...))
253     var_inits = (
254         # coordinate variables
255         ('time', NC.INT, ('ntime',)),
256         ('lat', NC.FLOAT, ('nlat',)),
257         ('lon', NC.FLOAT, ('nlon',)),
258         ('z',  NC.FLOAT, ('nz',)),
259         # data variables
260         ('en', NC.INT, ('ntime', )),
261         ('u', NC.FLOAT, ('ntime', 'nz')),
262         ('v', NC.FLOAT, ('ntime', 'nz')),
263         ('water_depth', NC.FLOAT, ('ntime',)),
264         )
265
266     # subset data only to month being processed (see raw2proc.process())
267     i = data['in']
268    
269     # var data
270     var_data = (
271         ('lat',  platform_info['lat']),
272         ('lon', platform_info['lon']),
273         ('z', data['z']),
274         #
275         ('time', data['time'][i]),
276         ('en', data['en'][i]),
277         ('u', data['u'][i]),
278         ('v', data['v'][i]),
279         ('water_depth', data['water_depth'][i]),
280         )
281
282     return (global_atts, var_atts, dim_inits, var_inits, var_data)
283
284 def updater(platform_info, sensor_info, data):
285     #
286     global_atts = {
287         # update times of data contained in file (yyyy-mm-dd HH:MM:SS)
288         # last date in monthly file
289         'end_date' : data['dt'][-1].strftime("%Y-%m-%d %H:%M:%S"),
290         'release_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
291         #
292         'modification_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
293         }
294
295     # data variables
296     # update any variable attributes like range, min, max
297     var_atts = {}
298     # var_atts = {
299     #    'u': {'max': max(data.u),
300     #          'min': min(data.v),
301     #          },
302     #    'v': {'max': max(data.u),
303     #          'min': min(data.v),
304     #          },
305     #    }
306    
307     # subset data only to month being processed (see raw2proc.process())
308     i = data['in']
309
310     # data
311     var_data = (
312         ('time', data['time'][i]),
313         ('en', data['en'][i]),
314         ('u', data['u'][i]),
315         ('v', data['v'][i]),
316         ('water_depth', data['water_depth'][i]),
317         )
318
319     return (global_atts, var_atts, var_data)
320 #
Note: See TracBrowser for help on using the browser.