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

root/raw2proc/trunk/raw2proc/procutil.py

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

read and process directional wave data from 2-d spectra

Line 
1 #!/usr/bin/env python
2 # Last modified:  Time-stamp: <2008-05-08 16:11:36 haines>
3 """Utilities to help data processing
4
5    Mostly time functions right now
6
7    TO DO:
8    check_configs()
9    unit conversions (udunits?)
10 """
11
12 __version__ = "v0.1"
13 __author__ = "Sara Haines <sara_haines@unc.edu>"
14
15 from datetime import datetime, timedelta, tzinfo
16 from dateutil.tz import tzlocal, tzutc
17 import time
18 import math
19
20 def check_configs():
21     """Test config files for comformnity
22
23     check either one or all for a platform
24    
25     id in filename == platform.id
26     datetime in filename <= platform.config_start_date
27        (close in time usually the same day
28     also platform.config_start_date < platform.config_end_date
29        (there needs to be some time that the platform was operational)
30     test existence of specific structural elements (platform info and sensor info)
31     and specific fields for both platform and sensor
32     verify that for each platform_info['packages'] there is sensor_info and same id
33       for pi['packages'][0] in si.keys()
34       pi['packages'][0] == si['adcp']['id']
35     bounds on data in fields
36     show difference between two consecutive configs?
37     pretty print to screen of dictionary info for platform and sensor info
38    
39         cn = os.path.splitext(os.path.basename(config))[0]
40         cndt = filt_datetime(os.path.basename(config))[0]
41         pi = get_config(cn+'.platform_info')
42         if pi['config_start_date']:
43             config_start_dt = filt_datetime(pi['config_start_date'])[0]
44         elif pi['config_start_date'] == None:
45             config_start_dt = now_dt
46         if pi['config_end_date']:
47             config_end_dt = filt_datetime(pi['config_end_date'])[0]
48         elif pi['config_end_date'] == None:
49             config_end_dt = now_dt
50
51         print cn + ' -----------------'
52         print cndt
53         print config_start_dt
54         print config_end_dt
55         print now_dt
56         print 'file date ok? ' + str(cndt <= config_start_dt)
57         print 'operation date ok? ' + str(config_start_dt < config_end_dt)
58     """
59
60 def dt2es(dt):
61     """Convert datetime object to epoch seconds (es) as seconds since Jan-01-1970 """
62     # microseconds of timedelta object not used
63     delta = dt - datetime(1970,1,1,0,0,0)
64     es = delta.days*24*60*60 + delta.seconds
65     return es
66
67 def es2dt(es):
68     """ Convert epoch seconds (es) to datetime object"""
69     dt = datetime(*time.gmtime(es)[0:6])
70     return dt
71
72 def find_months(year, month=1):
73     """Find which months to process
74
75     Since data are in subdirectories based on months determine
76     previous, current, and next month to look in directories for data
77     of the current month or month to process.
78
79     :Parameters:
80         year : int value or str 'yyyy_mm'
81         month : int value
82
83     :Returns:
84         which_months : tuple of 3 datetime objects
85              (prev_month, current_month, next_month)
86
87     Examples
88     --------
89     >>> find_months(2007, 2)
90     >>> find_months('2007_02')
91    
92     """
93     if type(year) == int and type(month) == int :
94         dt = datetime(year, month, day=1)
95         this_month = dt
96     elif type(year) == str :
97         dt = filt_datetime(year)[0]
98         this_month = dt
99     #
100     if dt.month == 1: # if January
101         prev_month = datetime(dt.year-1, month=12, day=1) # Dec
102         next_month = datetime(dt.year, dt.month+1, day=1) # Feb
103     elif dt.month == 12: # if December
104         prev_month = datetime(dt.year, dt.month-1, day=1) # Nov
105         next_month = datetime(dt.year+1, month=1, day=1)  # Jan
106     else:
107         prev_month = datetime(dt.year, dt.month-1, day=1)
108         next_month = datetime(dt.year, dt.month+1, day=1)
109     #
110     return (prev_month, this_month, next_month)
111
112 def this_month():
113     """Return this month (GMT) as formatted string (yyyy_mm) """
114     this_month_str = "%4d_%02d" % time.gmtime()[0:2]
115     return this_month_str
116
117 def scanf_datetime(ts, fmt='%Y-%m-%dT%H:%M:%S'):
118     """Convert string representing date and time to datetime object"""
119     # default string format follows convention YYYY-MM-DDThh:mm:ss
120    
121     t = time.strptime(ts, fmt)
122     # the '*' operator unpacks the tuple, producing the argument list.
123     dt = datetime(*t[0:6])
124     return dt
125
126 def filt_datetime(input_string, remove_ext=True):
127     """
128     Following the template, (YY)YYMMDDhhmmss
129     and versions with of this with decreasing time precision,
130     find the most precise, reasonable string match and
131     return its datetime object.
132     """
133
134     # remove any trailing filename extension
135     from os.path import splitext
136     import re
137     if remove_ext:
138         (s, e) = splitext(input_string)
139         input_string = s
140    
141     # YYYYMMDDhhmmss and should handle most cases of the stamp
142     # other forms this should pass
143     # YY_MM_DD_hh:mm:ss
144     # YYYY_MM_DD_hh:mm:ss
145     # YYYY,MM,DD,hh,mm,ss
146     # YY,MM,DD,hh,mm,ss
147
148     case1_regex = r"""
149     # case 1: (YY)YYMMDDhhmmss
150     (\d{4}|\d{2})     # 2- or 4-digit YEAR (e.g. '07' or '2007')
151     \D?               # optional 1 character non-digit separator (e.g. ' ' or '-')
152     (\d{2})           # 2-digit MONTH (e.g. '12')
153     \D?               # optional 1 character non-digit separator
154     (\d{2})           # 2-digit DAY of month (e.g. '10')
155     \D?               # optional 1 character non-digit separator (e.g. ' ' or 'T')
156     (\d{2})           # 2-digit HOUR (e.g. '10')
157     \D?               # optional 1 character non-digit separator (e.g. ' ' or ':')
158     (\d{2})           # 2-digit MINUTE (e.g. '10')
159     \D?               # optional 1 character non-digit separator (e.g. ' ' or ':')
160     (\d{2})           # 2-digit SECOND (e.g. '10')
161     """
162
163     case2_regex = r"""
164     # case 2: (YY)YYMMDDhhmm (no seconds)
165     (\d{4}|\d{2})     # 2- or 4-digit YEAR
166     \D?               # optional 1 character non-digit separator (e.g. ' ' or '-')
167     (\d{2})           # 2-digit MONTH
168     \D?               # optional 1 character non-digit separator
169     (\d{2})           # 2-digit DAY
170     \D?               # optional 1 character non-digit separator (e.g. ' ' or 'T')
171     (\d{2})           # 2-digit HOUR
172     \D?               # optional 1 character non-digit separator (e.g. ' ' or ':')
173     (\d{2})           # 2-digit MINUTE
174     """
175
176     case3_regex = r"""
177     # case 3: (YY)YYMMDDhh (no seconds, no minutes)
178     (\d{4}|\d{2})     # 2- or 4-digit YEAR
179     \D?               # optional 1 character non-digit separator (e.g. ' ' or '-')
180     (\d{2})           # 2-digit MONTH
181     \D?               # optional 1 character non-digit separator
182     (\d{2})           # 2-digit DAY
183     \D?               # optional 1 character non-digit separator (e.g. ' ' or 'T')
184     (\d{2})           # 2-digit HOUR
185     """
186
187     case4_regex = r"""
188     # case 4: (YY)YYMMDD (no time values, just date)
189     (\d{4}|\d{2})     # 2- or 4-digit YEAR
190     \D?               # optional 1 character non-digit separator (e.g. ' ' or '-')
191     (\d{2})           # 2-digit MONTH
192     \D?               # optional 1 character non-digit separator
193     (\d{2})           # 2-digit DAY
194     """
195
196     case5_regex = r"""
197     # case 5: (YY)YYMM (no time values, just month year)
198     (\d{4}|\d{2})     # 2- or 4-digit YEAR
199     \D?               # optional 1 character non-digit separator (e.g. ' ' or '-')
200     (\d{2})           # 2-digit MONTH
201     """
202
203     ##  Verbose regular expressions require use of re.VERBOSE flag.
204     ##  so we can use multiline regexp
205
206     # cases are ordered from precise to more coarse resolution of time
207     cases = [case1_regex, case2_regex, case3_regex, case4_regex, case5_regex]
208     patterns = [re.compile(c, re.VERBOSE) for c in cases]
209     matches = [p.search(input_string) for p in patterns]
210
211     # for testing, try to computer datetime objects
212     # just because there is a match does not mean it makes sense
213     for ind in range(len(matches)):
214         if bool(matches[ind]):
215             # print matches[ind].groups()
216             bits = matches[ind].groups()
217             values = [int(yi) for yi in bits]
218             # check for 2-digit year
219             if values[0] < 50:
220                 values[0] += 2000
221             elif values[0]>=50 and values[0]<100:
222                 values[0] += 1900
223             #
224             # we must have at least 3 arg input to datetime
225             if len(values)==1:
226                 values.extend([1,1]) # add First of January
227             elif len(values)==2:
228                 values.extend([1]) # add first day of month
229
230             #
231             # compute dt
232             try:
233                 dt = datetime(*values)
234             except ValueError, e:
235                 # value error if something not valid for datetime
236                 # e.g. month 1...12, something parsed wrong
237                 dt = None
238             else:
239                 # absolute difference in days from now (UTC)
240                 z = dt - datetime.utcnow()
241                 daysdiff = abs(z.days)
242                 # if this date unreasonable (>10 years*365), throw it out
243                 # something parsed wrong
244                 if daysdiff > 3650:
245                     dt = None               
246         else:
247             dt = None
248
249         # place datetime object or None within sequence of matches
250         matches[ind] = dt
251
252     # find the first (most precise) date match since there might be more than
253     # as we searched more coarse templates, but now we have thrown out
254    
255     b = [bool(x) for x in matches]
256     try:
257         ind = b.index(True)
258     except ValueError, e:
259         print 'filt_datetime: No date found in ', input_string
260         dt = None
261     else:
262        dt = matches[ind]
263        return dt,ind
264
265 def display_time_diff(diff):
266     """Display time difference in HH:MM:DD using number weeks (W)
267     and days (D) if necessary"""
268     # weeks, days = divmod(diff.days, 7)
269     days = diff.days
270     minutes, seconds = divmod(diff.seconds, 60)
271     hours, minutes = divmod(minutes, 60)   
272     # if (weeks>2 and days>0):
273     #    str = "%d Weeks, %d Days %02d:%02d" % (days, hours, minutes)
274     if (days==1):
275         str = "%02d:%02d" % (24+hours, minutes)
276     elif (days>1):
277         str = "%d Days %02d:%02d" % (days, hours, minutes)
278     else:
279         str = "%02d:%02d" % (hours, minutes)
280     return str
281
282 def copy_loop_sequence(src, dst, fn_glob, numFiles=24):
283     """ """
284     # src = '/seacoos/data/nccoos/level3/bogue/adcpwaves/dspec/'+this_month.strftime("%Y_%m")
285     # dst = '/home/haines/rayleigh/loop/'
286     # fn_glob = 'bogue_dspec_plot*'
287
288 # unit conversions
289 def meters2feet(meters):
290     """Convert meters to feet: <feet> = <meters>*3.28084 """
291     return meters*3.28084
292
293        
294 def millibar2inches_Hg(millibar):
295     """Convert millibars to inches Hg: <inches_Hg> = <millibar>*0.0295301 """
296     return millibar*0.0295301
297
298
299 def celsius2fahrenheit(celsius):
300     """Convert deg Celsius to deg Fahrenheit: <fahrenheit> = ((1.8*<celsius>)+32) """
301     return (1.8*celsius)+32
302
303
304 def millimeters2inches(millimeters):
305     """ Convert millimeter to inches: <inches> = <millimeters>*0.0393700787) """
306     return millimeters*0.0393700787
307
308
309 def meters_sec2knots(meters_sec):
310     """ Convert m/s to knots: <knots> = <meters_sec>*1.94384449) """
311     return meters_sec*1.94384449
312
313
314 def wind_vector2u(wind_speed, wind_from_direction):
315     """ Convert wind vector to U (east) component: <u> = <wind_speed>*sine(<wind_from_direction>*pi/180) """
316     return wind_speed*math.sin(wind_from_direction*math.pi/180)
317
318
319 def wind_vector2v(wind_speed, wind_from_direction):
320     """ Convert wind vector to V (north) component: <v> = <wind_speed>*cosine(<wind_from_direction>*pi/180) """
321     return wind_speed*math.cos(wind_from_direction*math.pi/180)
322
Note: See TracBrowser for help on using the browser.