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

root/raw2proc/trunk/raw2proc/proc_cr10x_flow_v1.py

Revision 448 (checked in by cbc, 13 years ago)

Add new Billy Mitchell configs.

Line 
1 #!/usr/bin/env python
2 # Last modified:  Time-stamp: <2010-12-09 16:14:39 haines>
3 """
4 how to parse data, and assert what data and info goes into
5 creating and updating monthly netcdf files
6
7 parse data water level and flow data (pressure sensor only) collected
8 on Campbell Scientific DataLogger (loggernet) (csi)
9
10 parser : sample date and time, water_depth and flow from sontek and pressure
11
12 creator : lat, lon, z, time, rain, press_wl, press_flow
13 updator : time, rain, press_wl, press_flow
14
15
16 Examples
17 --------
18
19 >> (parse, create, update) = load_processors('proc_csi_adcp_v2')
20 or
21 >> si = get_config(cn+'.sensor_info')
22 >> (parse, create, update) = load_processors(si['adcp']['proc_module'])
23
24 >> lines = load_data(filename)
25 >> data = parse(platform_info, sensor_info, lines)
26 >> create(platform_info, sensor_info, data) or
27 >> update(platform_info, sensor_info, data)
28
29 """
30
31
32 from raw2proc import *
33 from procutil import *
34 from ncutil import *
35
36 now_dt = datetime.utcnow()
37 now_dt.replace(microsecond=0)
38
39 def parser(platform_info, sensor_info, lines):
40     """
41     From FSL (CSI datalogger program files):
42     
43     1 Output_Table  60.00 Min
44     1 1 L
45     2 Year_RTM  L
46     3 Day_RTM  L
47     4 Hour_Minute_RTM  L
48     5 H2OTempC  L
49     6 SpCond  L
50     7 DOSat  L
51     8 DOmg  L
52     9 PH  L
53     10 TURB L
54     11 PrDepthft  L
55     12 Rain  L
56     13 PrFlowcfs  L
57     14 BattVolts  L
58
59     Example data:
60     
61     1,2001,130,2000,19.27,.292,.1,.01,7.44,3.5,.123,0,12.77,0
62     1,2001,130,2100,19.17,.291,.1,.01,7.38,3.1,.119,0,12.58,0
63     1,2001,130,2200,19.06,.288,.1,.01,7.35,3.2,.12,0,12.72,0
64     1,2001,130,2300,18.89,.282,.1,.01,7.35,2.8,.127,0,12.68,0
65     1,2001,130,2400,18.68,.277,.1,.01,7.36,2.7,1.347,0,13.47,12.75
66     1,2001,131,100,18.45,.275,.1,.01,7.36,2.7,1.292,0,12.92,12.62
67
68     """
69
70     import numpy
71     from datetime import datetime
72     from time import strptime
73
74     # get sample datetime from filename
75     fn = sensor_info['fn']
76     sample_dt_start = filt_datetime(fn)
77
78     # how many samples
79     nsamp = 0
80     for line in lines:
81         m=re.search("^1,", line)
82         if m:
83             nsamp=nsamp+1
84
85     N = nsamp
86     data = {
87         'dt' : numpy.array(numpy.ones((N,), dtype=object)*numpy.nan),
88         'time' : numpy.array(numpy.ones((N,), dtype=long)*numpy.nan),
89         'rain' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
90         'press' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
91         'press_wl' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
92         'press_flow' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
93         'press_csi_ft' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
94         'press_csi_cfs' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
95         }
96
97     # sample count
98     i = 0
99
100     for line in lines:
101         csi = []
102         # split line and parse float and integers
103         m=re.search("^1,", line)
104         if m:
105             sw = re.split(',', line)
106         else:
107             continue
108
109         # split line and parse float and integers
110         sw = re.split(',', line)
111         for s in sw:
112             m = re.search(REAL_RE_STR, s)
113             if m:
114                 csi.append(float(m.groups()[0]))
115
116         if len(csi)==14:
117             # get sample datetime from data
118             yyyy = csi[1]
119             yday = csi[2]
120             (MM, HH) = math.modf(csi[3]/100.)
121             MM = math.ceil(MM*100.)
122             if (HH == 24):
123                 yday=yday+1
124                 HH = 0.
125                
126             sample_str = '%04d-%03d %02d:%02d' % (yyyy, yday, HH, MM)
127             if  sensor_info['utc_offset']:
128                 sample_dt = scanf_datetime(sample_str, fmt='%Y-%j %H:%M') + \
129                             timedelta(hours=sensor_info['utc_offset'])
130             else:
131                 sample_dt = scanf_datetime(sample_str, fmt='%Y-%j %H:%M')
132
133             data['dt'][i] = sample_dt # sample datetime
134             data['time'][i] = dt2es(sample_dt) # sample time in epoch seconds
135             #
136             # data['wtemp'][i] =  csi[4] # water temperature (C)
137             # data['cond'][i] = csi[5] # specific conductivity (mS/cm)
138             # data['do_sat'][i] = csi[6]   # saturated dissolved oxygen (% air sat)
139             # data['do_mg'][i] = csi[7]   # dissolved oxygen (mg/l)
140             # data['ph'][i] = csi[8]   # ph
141             # data['turb'][i] = csi[9] # turbidity (NTU)
142
143             # no adcp's prior to March 2005
144             # data['sontek_wl'][i] = csi[5] # sontek water level (ft)
145             # data['sontek_flow'][i] = csi[6] # sontek flow (cfs)
146
147             data['press_csi_ft'][i] = csi[10] # pressure water level (ft)
148             data['rain'][i] =  csi[11] # 15 sec rain count ??
149             data['press_csi_cfs'][i] = csi[12] # flow flow (cfs)
150             # data['battvolts'][i] = csi[13]   # battery (volts)
151             
152             i=i+1
153
154         # if-elif
155     # for line
156
157     # revert  press_csi_ft back  to raw  pressure  reading (eventually
158     # want csi to just report the  raw pressure reading so we can just
159     # do this ourselves.
160     data['press'] = (data['press_csi_ft']+1.5)/27.6778 # raw pressure (psi)
161     # convert psi to height of water column based on hydrostatic eqn
162     data['press_wl'] = data['press']*2.3059+sensor_info['press_offset'] # (feet)
163     
164     # flow based on parameter as computed by data logger
165     # data['press_flow'] = data['press_csi_cfs']
166                                 
167     # flow based on calculation from data logger but applied to offset calibration
168     # SMH does not know what equation is based on or how these values are derived
169     data['press_flow'] = ((data['press_wl']*12))*10.81 - 8.81 # cfs
170
171     # check that no data[dt] is set to Nan or anything but datetime
172     # keep only data that has a resolved datetime
173     keep = numpy.array([type(datetime(1970,1,1)) == type(dt) for dt in data['dt'][:]])
174     if keep.any():
175         for param in data.keys():
176             data[param] = data[param][keep]
177            
178     return data
179  
180
181 def creator(platform_info, sensor_info, data):
182     #
183     #
184     title_str = sensor_info['description']+' at '+ platform_info['location']
185     global_atts = {
186         'title' : title_str,
187         'institution' : 'Unversity of North Carolina at Chapel Hill (UNC-CH)',
188         'institution_url' : 'http://nccoos.unc.edu',
189         'institution_dods_url' : 'http://nccoos.unc.edu',
190         'metadata_url' : 'http://nccoos.unc.edu',
191         'references' : 'http://nccoos.unc.edu',
192         'contact' : 'Sara Haines (haines@email.unc.edu)',
193         'station_owner' : 'Environment, Health, and Safety Office',
194         'station_contact' : 'Sharon Myers (samyers@ehs.unc.edu)',
195         #
196         'source' : 'fixed-observation',
197         'history' : 'raw2proc using ' + sensor_info['process_module'],
198         'comment' : 'File created using pycdf'+pycdfVersion()+' and numpy '+pycdfArrayPkg(),
199         # conventions
200         'Conventions' : 'CF-1.0; SEACOOS-CDL-v2.0',
201         # SEACOOS CDL codes
202         'format_category_code' : 'fixed-point',
203         'institution_code' : platform_info['institution'],
204         'platform_code' : platform_info['id'],
205         'package_code' : sensor_info['id'],
206         # institution specific
207         'project' : 'Environment, Health, and Safety (EHS)',
208         'project_url' : 'http://ehs.unc.edu/environment/water_quality',
209         # timeframe of data contained in file yyyy-mm-dd HH:MM:SS
210         # first date in monthly file
211         'start_date' : data['dt'][0].strftime("%Y-%m-%d %H:%M:%S"),
212         # last date in monthly file
213         'end_date' : data['dt'][-1].strftime("%Y-%m-%d %H:%M:%S"),
214         'release_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
215         #
216         'creation_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
217         'modification_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
218         'process_level' : 'level1',
219         #
220         # must type match to data (e.g. fillvalue is real if data is real)
221         '_FillValue' : -99999.,
222         }
223
224     var_atts = {
225         # coordinate variables
226         'time' : {'short_name': 'time',
227                   'long_name': 'Time',
228                   'standard_name': 'time',
229                   'units': 'seconds since 1970-1-1 00:00:00 -0', # UTC
230                   'axis': 'T',
231                   },
232         'lat' : {'short_name': 'lat',
233              'long_name': 'Latitude',
234              'standard_name': 'latitude',
235              'reference':'geographic coordinates',
236              'units': 'degrees_north',
237              'valid_range':(-90.,90.),
238              'axis': 'Y',
239              },
240         'lon' : {'short_name': 'lon',
241                  'long_name': 'Longitude',
242                  'standard_name': 'longitude',
243                  'reference':'geographic coordinates',
244                  'units': 'degrees_east',
245                  'valid_range':(-180.,180.),
246                  'axis': 'Y',
247                  },
248         'z' : {'short_name': 'z',
249                'long_name': 'Altitude',
250                'standard_name': 'altitude',
251                'reference':'zero at mean sea level',
252                'positive' : 'up',
253                'units': 'm',
254                'axis': 'Z',
255                },
256         # data variables
257         'rain': {'short_name': 'rain',
258                  'long_name': '15-Minute Rain',
259                  'standard_name': 'rain',                         
260                  'units': 'inches',
261                   },
262         'press_wl': { 'short_name': 'press_wl',
263                   'long_name': 'Pressure Water Level',
264                   'standard_name': 'water_level',                         
265                   'units': 'feet',
266                   'reference':'zero at station altitude',
267                   'positive' : 'up',
268                   },
269         'press_flow': { 'short_name': 'flow',
270                         'long_name': 'Pressure Stream Flow',
271                         'standard_name': 'water_flux',                         
272                         'units': 'cfs',
273                         },
274         }
275
276     # dimension names use tuple so order of initialization is maintained
277     dim_inits = (
278         ('ntime', NC.UNLIMITED),
279         ('nlat', 1),
280         ('nlon', 1),
281         ('nz', 1),
282         )
283    
284     # using tuple of tuples so order of initialization is maintained
285     # using dict for attributes order of init not important
286     # use dimension names not values
287     # (varName, varType, (dimName1, [dimName2], ...))
288     var_inits = (
289         # coordinate variables
290         ('time', NC.INT, ('ntime',)),
291         ('lat', NC.FLOAT, ('nlat',)),
292         ('lon', NC.FLOAT, ('nlon',)),
293         ('z',  NC.FLOAT, ('nz',)),
294         # data variables
295         ('rain', NC.FLOAT, ('ntime',)),
296         ('press_wl', NC.FLOAT, ('ntime',)),
297         ('press_flow', NC.FLOAT, ('ntime',)),
298         )
299
300     # subset data only to month being processed (see raw2proc.process())
301     i = data['in']
302    
303     # var data
304     var_data = (
305         ('lat',  platform_info['lat']),
306         ('lon', platform_info['lon']),
307         ('z', platform_info['altitude']),
308         #
309         ('time', data['time'][i]),
310         #
311         ('rain', data['rain'][i]),
312         ('press_wl', data['press_wl'][i]),
313         ('press_flow', data['press_flow'][i]),
314         )
315
316     return (global_atts, var_atts, dim_inits, var_inits, var_data)
317
318 def updater(platform_info, sensor_info, data):
319     #
320     global_atts = {
321         # update times of data contained in file (yyyy-mm-dd HH:MM:SS)
322         # last date in monthly file
323         'end_date' : data['dt'][-1].strftime("%Y-%m-%d %H:%M:%S"),
324         'release_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
325         #
326         'modification_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
327         }
328
329     # data variables
330     # update any variable attributes like range, min, max
331     var_atts = {}
332     # var_atts = {
333     #    'wtemp': {'max': max(data.u),
334     #          'min': min(data.v),
335     #          },
336     #    'cond': {'max': max(data.u),
337     #          'min': min(data.v),
338     #          },
339     #    }
340     
341     # subset data only to month being processed (see raw2proc.process())
342     i = data['in']
343
344     # data
345     var_data = (
346         ('time', data['time'][i]),
347         #
348         ('rain', data['rain'][i]),
349         ('press_wl', data['press_wl'][i]),
350         ('press_flow', data['press_flow'][i]),
351         )
352
353     return (global_atts, var_atts, var_data)
354 #
355
Note: See TracBrowser for help on using the browser.