root/track/trunk/track.py

Revision 29 (checked in by cbc, 12 years ago)

Modify in preparation of Nobletec and KML output.

Line 
1 #!/usr/bin/env python
2
3 """
4 Parse glider surface positions from glider logs.
5
6 Usage:
7
8    python track.py [positions [start_date [end_date]]]
9
10    where (optional) positions are the number of positions to report, and
11
12    where (optional) start_date and end_date are of the form: YYYYMMDD.
13
14        start_date is inclusive; stop_date is exclusive.
15
16    An exception is raised if start_date > stop_date.
17 """
18
19 import sys
20 import os
21 import re
22 from datetime import datetime, timedelta
23 from glob import glob
24
25 glider_dir = '/var/opt/gmc/gliders'
26 gliders = ['pelagia', 'ramses']
27 comms = ['freewave', 'network', ]
28 positions = 10  # report most recent number of positions
29 tomorrow = datetime.now() + timedelta(1)
30 start_date = '20120125'                       # inclusive
31 stop_date = '%04d%02d%02d' % (tomorrow.year,  # exclusive
32                               tomorrow.month,
33                               tomorrow.day)
34 file_pattern_template = "%s_%s_%04d%02d%02dT*.log"
35 p_pattern = re.compile(r"^GPS Location:\s+(\S+)\s+\S\s+(\S+)"
36                        r"\s+\S\s+\S+\s+(\S+)\s+")
37 c_pattern = re.compile(r"^Curr Time:\s+(\S+)\s+(\S+)\s+(\S+)"
38                        r"\s+(\S+)\s+(\S+)\s+")
39 bad_coordinate = "69696969.000"
40 bad_freshness = "1e+308"
41 stale = 120.0  # position must not be older than this many seconds
42 delta = timedelta(seconds=600)  # positions must be this many seconds apart
43 months = {'Jan': 1,
44           'Feb': 2,
45           'Mar': 3,
46           'Apr': 4,
47           'May': 5,
48           'Jun': 6,
49           'Jul': 7,
50           'Aug': 8,
51           'Sep': 9,
52           'Oct': 10,
53           'Nov': 11,
54           'Dec': 12}
55 shtnom = {}
56 for month in months:
57     shtnom[months[month]] = month
58 weekdays = {0: 'Mon',
59             1: 'Tue',
60             2: 'Wed',
61             3: 'Thu',
62             4: 'Fri',
63             5: 'Sat',
64             6: 'Sun'}
65
66
67 def find(gliders=gliders,
68          start_date=start_date,
69          stop_date=stop_date):
70     start_datetime = datetime(int(start_date[:4]),
71                               int(start_date[4:6]),
72                               int(start_date[6:]))
73     stop_datetime = datetime(int(stop_date[:4]),
74                              int(stop_date[4:6]),
75                              int(stop_date[6:]))
76     try:
77         assert start_datetime < stop_datetime
78     except AssertionError:
79         print >> sys.stderr, "Start date is not less than stop date."
80         print __doc__
81         sys.exit(2)
82
83     date = start_datetime
84     date_range = []
85     while date < stop_datetime:
86         date_range.append(date)
87         date += timedelta(1)
88
89     file_patterns = {}
90     for glider in gliders:
91         file_patterns[glider] = [file_pattern_template % (glider,
92                                                           comm,
93                                                           date.year,
94                                                           date.month,
95                                                           date.day,)
96                                  for comm in comms
97                                  for date in date_range]
98
99     log_dirs = {}
100     for glider in gliders:
101         log_dirs[glider] = os.path.join(glider_dir, glider, 'logs')
102
103     file_paths = {}
104     for glider in gliders:
105         file_paths[glider] = []
106         for file_pattern in file_patterns[glider]:
107             file_paths[glider].extend(glob(os.path.join(log_dirs[glider],
108                                                         file_pattern)))
109     return file_paths
110
111
112 def parse(gliders=gliders,
113           start_date=start_date,
114           stop_date=stop_date):
115     file_paths = find(gliders, start_date, stop_date)
116     points = {}
117     for glider in gliders:
118         points[glider] = []
119         for file_path in file_paths[glider]:
120             handle = open(file_path)
121             contents = handle.readlines()
122             handle.close()
123             protents = contents[4:]
124             xref = zip(protents, contents)
125             for pline, cline in xref:
126                 match = p_pattern.search(pline)
127                 if match:
128                     lat, lon, fresh = match.groups()
129                     if lat == bad_coordinate:
130                         continue
131                     if lon == bad_coordinate:
132                         continue
133                     if fresh == bad_freshness:
134                         continue
135                     # if float(fresh) >= stale:
136                     #     continue
137                     match = c_pattern.search(cline)
138                     if match:
139                         weekday, month, day, time, year = match.groups()
140                         year = int(year)
141                         month = months[month]
142                         day = int(day)
143                         hour = int(time[0:2])
144                         minute = int(time[3:5])
145                         second = int(time[6:8])
146                         stamp = datetime(year, month, day,
147                                          hour, minute, second)
148                         stamp = stamp - timedelta(seconds=float(fresh))
149                         points[glider].append({'lat': lat,
150                                                'lon': lon,
151                                                'fresh': fresh,
152                                                'stamp': stamp, }),
153                         break
154
155         points[glider].sort(cmp=lambda x, y: cmp(x['stamp'], y['stamp']))
156         # If two adjacent positions differ in time by less than delta,
157         # then remove the earlier position from the report.
158         # This effect is cumulative for a string of adjacent positions.
159         for pointa, pointb in zip(points[glider][:-1], points[glider][1:]):
160             if pointb['stamp'] - pointa['stamp'] < delta:
161                 points[glider].remove(pointa)
162
163     return points
164
165 if __name__ == '__main__':
166     if not (len(sys.argv) < 5):
167         sys.exit(__doc__)
168
169     try:
170         positions = int(sys.argv[1])
171     except:
172         pass
173
174     try:
175         start_date = sys.argv[2]
176         int(start_date)
177     except:
178         pass
179
180     try:
181         stop_date = sys.argv[3]
182         int(stop_date)
183     except:
184         pass
185
186     points = parse(gliders, start_date, stop_date)
187     spec = "Glider: %s, Lat: %s, Lon: %s on %s %s %02d, " \
188            "%04d at %02d:%02d:%02d UTC\n"
189     for glider in gliders:
190         for point in points[glider][-positions:]:
191             print spec % (glider,
192                           point['lat'],
193                           point['lon'],
194                           weekdays[point['stamp'].weekday()],
195                           shtnom[point['stamp'].month],
196                           point['stamp'].day,
197                           point['stamp'].year,
198                           point['stamp'].hour,
199                           point['stamp'].minute,
200                           point['stamp'].second)
Note: See TracBrowser for help on using the browser.