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

root/raw2proc/trunk/raw2proc/proc_rdi_logdata_adcp.py

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

first commit of code

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