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

root/raw2proc/trunk/raw2proc/proc_cr10x_flow_v2.py

Revision 233 (checked in by haines, 15 years ago)

EHS processing and python virtual env

Line 
1 #!/usr/bin/env python
2 # Last modified:  Time-stamp: <2009-03-19 14:30:42 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 (sontek argonaut and pressure
8 sensor) collected 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, sontek_wl, sontek_flow, press_wl, press_flow
13 updator : time, sontek_wl, sontek_flow, 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     15 Output_Table  15.00 Min
44     1 15 L
45     2 Year_RTM  L
46     3 Day_RTM  L
47     4 Hour_Minute_RTM  L
48     5 Rain15sec_TOT  L
49     6 SonLevlft  L
50     7 SonFlow  L
51     8 PrDepthft  L
52     9 PrFlowcfs  L
53    
54     1 Output_Table  60.00 Min
55     1 1 L
56     2 Year_RTM  L
57     3 Day_RTM  L
58     4 Hour_Minute_RTM  L
59     5 H2OTempC  L
60     6 SpCond  L
61     7 DOSat  L
62     8 DOmg  L
63     9 PH  L
64     10 Turb  L
65     11 BattVolts  L
66
67     Example data:
68    
69     1,2005,83,1600,16.47,0,.4,.04,8.14,115.5,14.25
70     15,2005,83,1615,0,4.551,-.547,.897,.885
71     15,2005,83,1630,0,4.541,.727,.908,1.005
72     15,2005,83,1645,0,4.537,6.731,.878,.676
73     15,2005,83,1700,0,4.537,6.731,.83,.167
74     1,2005,83,1700,16.57,0,.4,.03,8.03,145.7,13.08
75     15,2005,83,1715,0,4.547,5.29,.847,.347
76     15,2005,83,1730,0,4.541,.908,.842,.287
77     15,2005,83,1745,0,4.547,7.3,.853,.407
78     15,2005,83,1800,0,4.551,6.939,.855,.437
79     1,2005,83,1800,15.65,0,.2,.02,7.91,111.3,12.98
80
81     15,2008,187,1715,.36,0,0
82     15,2008,187,1730,.06,0,0
83     15,2008,187,1745,.02,0,0
84     15,2008,187,1800,.01,0,0
85
86     """
87
88     import numpy
89     from datetime import datetime
90     from time import strptime
91
92     # get sample datetime from filename
93     fn = sensor_info['fn']
94     sample_dt_start = filt_datetime(fn)[0]
95
96     # how many samples
97     nsamp = 0
98     for line in lines:
99         m=re.search("^15,", line)
100         if m:
101             nsamp=nsamp+1
102
103     N = nsamp
104     data = {
105         'dt' : numpy.array(numpy.ones((N,), dtype=object)*numpy.nan),
106         'time' : numpy.array(numpy.ones((N,), dtype=long)*numpy.nan),
107         'rain' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
108         'sontek_wl' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
109         'sontek_flow' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
110         'press_wl' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
111         'press_flow' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
112         }
113
114     # sample count
115     i = 0
116
117     for line in lines:
118         csi = []
119         # split line and parse float and integers
120         m=re.search("^15,", line)
121         if m:
122             sw = re.split(',', line)
123         else:
124             continue
125
126         # split line and parse float and integers
127         sw = re.split(',', line)
128         for s in sw:
129             m = re.search(REAL_RE_STR, s)
130             if m:
131                 csi.append(float(m.groups()[0]))
132
133         if re.search('^15,',line) and len(csi)>=4:
134             # get sample datetime from data
135             yyyy = csi[1]
136             yday = csi[2]
137             (MM, HH) = math.modf(csi[3]/100.)
138             MM = math.ceil(MM*100.)
139             if (HH == 24):
140                 yday=yday+1
141                 HH = 0.
142             sample_str = '%04d-%03d %02d:%02d' % (yyyy, yday, HH, MM)
143             if  sensor_info['utc_offset']:
144                 sample_dt = scanf_datetime(sample_str, fmt='%Y-%j %H:%M') + \
145                             timedelta(hours=sensor_info['utc_offset'])
146             else:
147                 sample_dt = scanf_datetime(sample_str, fmt='%Y-%j %H:%M')
148             data['dt'][i] = sample_dt # sample datetime
149             data['time'][i] = dt2es(sample_dt) # sample time in epoch seconds
150
151             if len(csi)==9:
152                 #
153                 data['rain'][i] =  csi[4] # 15 min rain count (inches)
154                 data['sontek_wl'][i] = csi[5] # sontek water level (ft)
155                 data['sontek_flow'][i] = csi[6] # sontek flow (cfs)
156                 data['press_wl'][i] = csi[7] # pressure water level (ft)
157                 data['press_flow'][i] = csi[8] # flow flow (cfs)
158             elif len(csi)==7:
159                 #
160                 data['rain'][i] =  csi[4] # 15 min rain count (inches)
161                 data['sontek_wl'][i] = numpy.nan # sontek water level (ft)
162                 data['sontek_flow'][i] = numpy.nan # sontek flow (cfs)
163                 data['press_wl'][i] = csi[5] # pressure water level (ft)
164                 data['press_flow'][i] = csi[6] # flow flow (cfs)
165
166             i=i+1
167
168         # if re.search
169     # for line
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         'sontek_wl': {'short_name': 'sontek_wl',
263                   'long_name': 'Sontek Water Level',
264                   'standard_name': 'water_level',                         
265                   'units': 'feet',
266                   'reference':'zero at station altitude',
267                   'positive' : 'up',
268                   },
269         'sontek_flow': {'short_name': 'flow',
270                         'long_name': 'Sontek Stream Flow',
271                         'standard_name': 'water_flux',                         
272                         'units': 'cfs',
273                         },
274         'press_wl': { 'short_name': 'press_wl',
275                   'long_name': 'Pressure Water Level',
276                   'standard_name': 'water_level',                         
277                   'units': 'feet',
278                   'reference':'zero at station altitude',
279                   'positive' : 'up',
280                   },
281         'press_flow': { 'short_name': 'flow',
282                         'long_name': 'Pressure Stream Flow',
283                         'standard_name': 'water_flux',                         
284                         'units': 'cfs',
285                         },
286         }
287
288     # dimension names use tuple so order of initialization is maintained
289     dim_inits = (
290         ('ntime', NC.UNLIMITED),
291         ('nlat', 1),
292         ('nlon', 1),
293         ('nz', 1),
294         )
295    
296     # using tuple of tuples so order of initialization is maintained
297     # using dict for attributes order of init not important
298     # use dimension names not values
299     # (varName, varType, (dimName1, [dimName2], ...))
300     var_inits = (
301         # coordinate variables
302         ('time', NC.INT, ('ntime',)),
303         ('lat', NC.FLOAT, ('nlat',)),
304         ('lon', NC.FLOAT, ('nlon',)),
305         ('z',  NC.FLOAT, ('nz',)),
306         # data variables
307         ('rain', NC.FLOAT, ('ntime',)),
308         ('sontek_wl', NC.FLOAT, ('ntime',)),
309         ('sontek_flow', NC.FLOAT, ('ntime',)),
310         ('press_wl', NC.FLOAT, ('ntime',)),
311         ('press_flow', NC.FLOAT, ('ntime',)),
312         )
313
314     # subset data only to month being processed (see raw2proc.process())
315     i = data['in']
316    
317     # var data
318     var_data = (
319         ('lat',  platform_info['lat']),
320         ('lon', platform_info['lon']),
321         ('z', platform_info['altitude']),
322         #
323         ('time', data['time'][i]),
324         #
325         ('rain', data['rain'][i]),
326         ('sontek_wl', data['sontek_wl'][i]),
327         ('sontek_flow', data['sontek_flow'][i]),
328         ('press_wl', data['press_wl'][i]),
329         ('press_flow', data['press_flow'][i]),
330         )
331
332     return (global_atts, var_atts, dim_inits, var_inits, var_data)
333
334 def updater(platform_info, sensor_info, data):
335     #
336     global_atts = {
337         # update times of data contained in file (yyyy-mm-dd HH:MM:SS)
338         # last date in monthly file
339         'end_date' : data['dt'][-1].strftime("%Y-%m-%d %H:%M:%S"),
340         'release_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
341         #
342         'modification_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
343         }
344
345     # data variables
346     # update any variable attributes like range, min, max
347     var_atts = {}
348     # var_atts = {
349     #    'wtemp': {'max': max(data.u),
350     #          'min': min(data.v),
351     #          },
352     #    'cond': {'max': max(data.u),
353     #          'min': min(data.v),
354     #          },
355     #    }
356    
357     # subset data only to month being processed (see raw2proc.process())
358     i = data['in']
359
360     # data
361     var_data = (
362         ('time', data['time'][i]),
363         #
364         ('rain', data['rain'][i]),
365         ('sontek_wl', data['sontek_wl'][i]),
366         ('sontek_flow', data['sontek_flow'][i]),
367         ('press_wl', data['press_wl'][i]),
368         ('press_flow', data['press_flow'][i]),
369         )
370
371     return (global_atts, var_atts, var_data)
372 #
Note: See TracBrowser for help on using the browser.