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

root/raw2proc/tags/raw2proc-1.0/proc_avp_ascii_met.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-01-26 11:23:09 haines>
3 """
4 how to parse data, and assert what data and info goes into
5 creating and updating monthly netcdf files
6
7
8 parser : output delimited ASCII file from onsite perl script
9 creator : lat, lon, z, time, wspd, wdir, cdir, u, v, nwnd
10
11 updater : time, wspd, wdir, cdir, u, v, nwnd
12
13
14 Examples
15 --------
16
17 >> (parse, create, update) = load_processors('proc_avp_ascii_wnd')
18 or
19 >> si = get_config(cn+'.sensor_info')
20 >> (parse, create, update) = load_processors(si['met']['proc_module'])
21
22 >> lines = load_data(filename)
23 >> data = parse(platform_info, sensor_info, lines)
24 >> create(platform_info, sensor_info, data) or
25 >> update(platform_info, sensor_info, data)
26
27 """
28
29 from raw2proc import *
30 from procutil import *
31 from ncutil import *
32 import time
33
34 now_dt = datetime.utcnow()
35 now_dt.replace(microsecond=0)
36
37 def parser(platform_info, sensor_info, lines):
38     """
39     parse Automated Vertical Profile Station (AVP) Wind data
40
41     Notes
42     -----
43     1. Wind:
44
45     Date, time, speed, dir, compass dir, North , East, n-samples
46         (m/s) (magN) (magN)      (m/s)   (m/s)
47
48     08/11/2008 00:00:00    5.881  197  197  -5.638  -1.674     696
49     08/11/2008 00:30:00    5.506  216  197  -4.448  -3.246     699
50     08/11/2008 01:00:00    7.233  329  159   6.183  -3.754     705
51
52     """
53     import numpy
54     from datetime import datetime
55     from time import strptime
56
57     # get sample datetime from filename
58     fn = sensor_info['fn']
59     sample_dt_start = filt_datetime(fn)[0]
60
61     # if line has weird ascii chars -- remove it
62     for index, line in enumerate(lines):
63         if re.search(r"[\x1a]", line):
64             # print '... ... remove unexpected  ... ' + str(line)
65             lines.pop(index)
66
67     lines.sort()
68     N = len(lines)
69     data = {
70         'dt' : numpy.array(numpy.ones((N,), dtype=object)*numpy.nan),
71         'time' : numpy.array(numpy.ones((N,), dtype=long)*numpy.nan),
72         'wspd' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
73         'wdir' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
74         'cdir' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
75         'v' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
76         'u' : numpy.array(numpy.ones((N,), dtype=float)*numpy.nan),
77         'nwnd' : numpy.array(numpy.ones((N,), dtype=int)*numpy.nan),
78         }
79
80     i = 0
81     mvar = platform_info['mvar'# Magnetic Variation at station
82
83     for line in lines:
84         # if line has weird ascii chars -- skip it and iterate to next line
85         if re.search(r"[\x1a]", line):
86             print 'skipping bad data line ... ' + str(line)
87             continue
88            
89         wnd = []
90
91         # split line and parse float and integers
92         sw = re.split('[\s\/\:]*', line)
93         for s in sw:
94             m = re.search(REAL_RE_STR, s)
95             if m:
96                 wnd.append(float(m.groups()[0]))
97
98         if len(wnd)>=11:
99             # get sample datetime from data
100             sample_str = '%02d-%02d-%4d %02d:%02d:%02d' % tuple(wnd[0:6])
101             if  sensor_info['utc_offset']:
102                 sample_dt = scanf_datetime(sample_str, fmt='%m-%d-%Y %H:%M:%S') + \
103                             timedelta(hours=sensor_info['utc_offset'])
104             else:
105                 sample_dt = scanf_datetime(sample_str, fmt='%m-%d-%Y %H:%M:%S')
106
107             wspd = int(wnd[6]) # wind speed (m/s)
108             wdir = int(wnd[7]) # wind dir (mag N)
109             cdir = wnd[8]      # compass dir (mag N)
110             u = wnd[9]         # Easterly (?) Component (m/s) (mag or true??)
111             v = wnd[10]        # Northerly (?) Component (m/s) (mag or true??)
112             if len(wnd)>=12:
113                 nwnd = int(wnd[11])
114             else:
115                 nwnd = numpy.nan # Number of samples in wind average
116             # prior to Sep 2008 number of samples were not recorded
117             
118             # combine wind dir and buoy compass direction
119             # correct direction from magnetic N to true N
120             # rotate u, v to true N
121             # or
122             # recompute u, v from direction and speed
123
124             data['dt'][i] = sample_dt # sample datetime
125             data['time'][i] = dt2es(sample_dt) # sample time in epoch seconds
126             data['wspd'][i] =  wspd
127             data['wdir'][i] = wdir
128             data['cdir'][i] = cdir
129             data['u'][i] = u
130             data['v'][i] = v
131             data['nwnd'][i] = nwnd
132
133             i=i+1
134
135         # if len(wnd)>=11
136     # for line
137
138     return data
139
140 def creator(platform_info, sensor_info, data):
141         #
142         # subset data only to month being processed (see raw2proc.process())
143         i = data['in']
144         dt = data['dt'][i]
145         #
146         title_str = sensor_info['description']+' at '+ platform_info['location']
147         global_atts = {
148                 'title' : title_str,
149                 'institution' : 'University of North Carolina at Chapel Hill (UNC-CH)',
150                 'institution_url' : 'http://nccoos.org',
151                 'institution_dods_url' : 'http://nccoos.org',
152                 'metadata_url' : 'http://nccoos.org',
153                 'references' : 'http://nccoos.org',
154                 'contact' : 'Sara Haines (haines@email.unc.edu)',
155                 #
156                 'source' : 'AVP Wind Observations',
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-point',
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.org',
169                 # timeframe of data contained in file yyyy-mm-dd HH:MM:SS
170                 'start_date' : dt[0].strftime("%Y-%m-%d %H:%M:%S"),
171                 'end_date' : dt[-1].strftime("%Y-%m-%d %H:%M:%S"),
172                 'release_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
173                 #
174                 'creation_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
175                 'modification_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
176                 'process_level' : 'level1',
177                 #
178                 # must type match to data (e.g. fillvalue is real if data is real)
179                 '_FillValue' : numpy.nan,
180                 }
181
182         var_atts = {
183                 # coordinate variables
184                 'time' : {'short_name': 'time',
185                           'long_name': 'Sample Time',
186                           'standard_name': 'time',
187                           'units': 'seconds since 1970-1-1 00:00:00 -0', # UTC
188                           'axis': 'T',
189                           },
190                 'lat' : {'short_name': 'lat',
191                          'long_name': 'Latitude in Decimal Degrees',
192                          'standard_name': 'latitude',
193                          'reference':'geographic coordinates',
194                          'units': 'degrees_north',
195                          'valid_range':(-90.,90.),
196                          'axis': 'Y',
197                          },
198                 'lon' : {'short_name': 'lon',
199                          'long_name': 'Longitude in Decimal Degrees',
200                          'standard_name': 'longitude',
201                          'reference':'geographic coordinates',
202                          'units': 'degrees_east',
203                          'valid_range':(-180.,180.),
204                          'axis': 'Y',
205                          },
206                 'z' : {'short_name': 'z',
207                        'long_name': 'Height',
208                        'standard_name': 'height',
209                        'reference':'zero at sea-surface',
210                        'positive': 'up',
211                        'units': 'm',
212                        'axis': 'Z',
213                        },
214                 # data variables
215                 'wspd' : {'short_name': 'wspd',
216                           'long_name': 'Wind Speed',
217                           'standard_name': 'wind_speed',
218                           'units': 'm s-1',
219                           'can_be_normalized': 'no',
220                           'z' : sensor_info['anemometer_height'],
221                           },
222                 'wdir' : {'short_name': 'wdir',
223                           'long_name': 'Wind Direction from',
224                           'standard_name': 'wind_from_direction',
225                           'reference': 'clockwise from Magnetic North',
226                           'valid_range': (0., 360),
227                           'units': 'degrees',
228                           'z' : sensor_info['anemometer_height'],
229                           },
230                 'cdir' :  {'short_name': 'cdir',
231                            'long_name': 'Buoy Orientation',
232                            'standard_name': 'compass_direction',
233                            'reference': 'clockwise from Magnetic North',
234                            'valid_range': (0., 360),
235                            'units': 'degrees',
236                            },
237                 'u' : {'short_name': 'u',
238                        'long_name': 'East/West Component of Wind',
239                        'standard_name': 'eastward_wind',
240                        'reference': 'relative to True East (?)',
241                        'units': 'm s-1',
242                        'can_be_normalized': 'no',
243                        'z' : sensor_info['anemometer_height'],
244                        },
245                 'v' : {'short_name': 'v',
246                        'long_name': 'North/South Component of Wind',
247                        'standard_name': 'northward_wind',
248                        'reference': 'relative to True North (?)',
249                        'units': 'm s-1',
250                        'can_be_normalized': 'no',
251                        'z' : sensor_info['anemometer_height'],
252                        },
253                 'nwnd' : {'short_name': 'nwnd',
254                        'long_name': 'Number of wind samples in sample period',
255                        'standard_name': 'number_of_samples',
256                        'units': 'm s-1',
257                        },
258                
259         }
260        
261         # dimension names use tuple so order of initialization is maintained
262         dim_inits = (
263                 ('time', NC.UNLIMITED),
264                 ('lat', 1),
265                 ('lon', 1),
266                 ('z', 1)
267                 )
268
269         # using tuple of tuples so order of initialization is maintained
270         # using dict for attributes order of init not important
271         # use dimension names not values
272         # (varName, varType, (dimName1, [dimName2], ...))
273         var_inits = (
274                 # coordinate variables
275                 ('time', NC.INT, ('time',)),
276                 ('lat', NC.FLOAT, ('lat',)),
277                 ('lon', NC.FLOAT, ('lon',)),
278                 ('z',  NC.FLOAT, ('z',)),
279                 # data variables
280                 ('wspd', NC.FLOAT, ('time',)),
281                 ('wdir', NC.FLOAT, ('time',)),
282                 ('cdir', NC.FLOAT, ('time',)),
283                 ('u', NC.FLOAT, ('time',)),
284                 ('v', NC.FLOAT, ('time',)),
285                 ('nwnd', NC.FLOAT, ('time',)),
286                 )
287
288         # var data
289         var_data = (
290                 ('lat',  platform_info['lat']),
291                 ('lon', platform_info['lon']),
292                 ('z', 1),
293                 #
294                 ('time', data['time'][i]),
295                 ('wspd', data['wspd'][i]),
296                 ('wdir', data['wdir'][i]),
297                 ('cdir', data['cdir'][i]),
298                 ('u', data['u'][i]),
299                 ('v', data['v'][i]),
300                 ('nwnd', data['nwnd'][i]),
301                 )
302                
303         return (global_atts, var_atts, dim_inits, var_inits, var_data)
304
305 def updater(platform_info, sensor_info, data):
306         #
307         # subset data only to month being processed (see raw2proc.process())
308         i = data['in']
309         dt = data['dt'][i]
310         #
311         global_atts = {
312                 # update times of data contained in file (yyyy-mm-dd HH:MM:SS)
313                 # last date in monthly file
314                 'end_date' : dt[-1].strftime("%Y-%m-%d %H:%M:%S"),
315                 'release_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
316                 #
317                 'modification_date' : now_dt.strftime("%Y-%m-%d %H:%M:%S"),
318                 }
319
320         # data variables
321         # update any variable attributes like range, min, max
322         var_atts = {}
323         # var_atts = {
324         #       'u': {'max': max(data.u),
325         #                 'min': min(data.v),
326         #                 },
327         #       'v': {'max': max(data.u),
328         #                 'min': min(data.v),
329         #                 },
330         #       }
331         
332         # subset data only to month being processed (see raw2proc.process())
333         i = data['in']
334
335         # data
336         var_data = (
337                 ('time', data['time'][i]),
338                 ('wspd', data['wspd'][i]),
339                 ('wdir', data['wdir'][i]),
340                 ('cdir', data['cdir'][i]),
341                 ('u', data['u'][i]),
342                 ('v', data['v'][i]),
343                 ('nwnd', data['nwnd'][i]),
344                 )
345
346         return (global_atts, var_atts, var_data)
347
348 #
349
Note: See TracBrowser for help on using the browser.