comparison graph.py @ 13:3f22fa1f32d5

Twiddle with start/end passing, add option for overriding local time zone.
author Daniel O'Connor <darius@dons.net.au>
date Fri, 22 Dec 2017 16:30:45 +0100
parents 2b115732f4bc
children aa18210c2703
comparison
equal deleted inserted replaced
12:2b115732f4bc 13:3f22fa1f32d5
57 parser.add_argument('-g', '--graphfn', help = 'File to write graph to', type = str) 57 parser.add_argument('-g', '--graphfn', help = 'File to write graph to', type = str)
58 parser.add_argument('-d', '--days', help = 'Days ago to graph', type = int) 58 parser.add_argument('-d', '--days', help = 'Days ago to graph', type = int)
59 parser.add_argument('-s', '--start', help = 'Start date for graph (YYYY-MM-DD)', type = valid_date) 59 parser.add_argument('-s', '--start', help = 'Start date for graph (YYYY-MM-DD)', type = valid_date)
60 parser.add_argument('-e', '--end', help = 'End date for graph (YYYY-MM-DD)', type = valid_date) 60 parser.add_argument('-e', '--end', help = 'End date for graph (YYYY-MM-DD)', type = valid_date)
61 parser.add_argument('-c', '--column', help = 'Column to plot (can be specified multiple times)', type = str, action = 'append') 61 parser.add_argument('-c', '--column', help = 'Column to plot (can be specified multiple times)', type = str, action = 'append')
62 parser.add_argument('-z', '--timezone', help = 'Timezone to operate in in (Oslon format) default: localtime)', type = str)
62 63
63 args = parser.parse_args() 64 args = parser.parse_args()
64 65
65 if args.days is not None and args.days < 0: 66 if args.days is not None and args.days < 0:
66 parser.error('days must be non-negative') 67 parser.error('days must be non-negative')
99 dbh = sqlite3.connect(args.filename, detect_types = sqlite3.PARSE_DECLTYPES) 100 dbh = sqlite3.connect(args.filename, detect_types = sqlite3.PARSE_DECLTYPES)
100 cur = dbh.cursor() 101 cur = dbh.cursor()
101 102
102 # Get local timezone name and convert start/end to it 103 # Get local timezone name and convert start/end to it
103 # Why is this so hard... 104 # Why is this so hard...
104 ltname = tzlocal.get_localzone().zone 105 if args.timezone is None:
105 ltname = 'Australia/Adelaide' 106 args.timezone = tzlocal.get_localzone().zone
106 lt = dateutil.tz.gettz(ltname) 107
108 lt = dateutil.tz.gettz(args.timezone)
109 if lt == None:
110 parser.error('Unknown timezone')
111
107 utc = dateutil.tz.gettz('UTC') 112 utc = dateutil.tz.gettz('UTC')
108 matplotlib.rcParams['timezone'] = ltname 113 matplotlib.rcParams['timezone'] = args.timezone
109 114
110 if args.start.tzinfo == None: 115 if args.start.tzinfo == None:
111 args.start = args.start.replace(tzinfo = lt) 116 args.start = args.start.replace(tzinfo = lt)
112 if args.end.tzinfo == None: 117 if args.end.tzinfo == None:
113 args.end = args.end.replace(tzinfo = lt) 118 args.end = args.end.replace(tzinfo = lt)
114 startlt = args.start 119 startlt = args.start
115 endlt = args.end 120 endlt = args.end
116 args.start = args.start.astimezone(utc) 121 args.start = args.start.astimezone(utc)
117 args.end = args.end.astimezone(utc) 122 args.end = args.end.astimezone(utc)
118 graph(args.graphfn, cur, cols, int(args.start.strftime('%s')), int(args.end.strftime('%s')), lt, utc) 123 graph(args.graphfn, cur, cols, args.start, args.end, lt, utc)
119 124
120 def graph(fname, cur, _cols, start, end, lt, utc): 125 def graph(fname, cur, _cols, start, end, lt, utc):
121 import numpy 126 import numpy
122 import matplotlib 127 import matplotlib
123 import matplotlib.dates 128 import matplotlib.dates
124 129
125 startdt = datetime.datetime.fromtimestamp(start).replace(tzinfo = utc).astimezone(lt) 130 startepoch = int(start.strftime('%s'))
126 enddt = datetime.datetime.fromtimestamp(end).replace(tzinfo = utc).astimezone(lt) 131 endepoch = int(end.strftime('%s'))
127 132
128 colourlist = ['b','g','r','c','m','y','k'] 133 colourlist = ['b','g','r','c','m','y','k']
129 134
130 cols = [] 135 cols = []
131 136
154 raise exceptions.Exception('Asked to graph >2 different units') 159 raise exceptions.Exception('Asked to graph >2 different units')
155 160
156 for c in cols: 161 for c in cols:
157 # Get the data 162 # Get the data
158 cur.execute('SELECT tstamp, ' + c.rowname + ' FROM ' + c.table + ' WHERE tstamp > ? AND tstamp < ? ORDER BY tstamp', 163 cur.execute('SELECT tstamp, ' + c.rowname + ' FROM ' + c.table + ' WHERE tstamp > ? AND tstamp < ? ORDER BY tstamp',
159 (start, end)) 164 (startepoch, endepoch))
160 ary = numpy.array(cur.fetchall()) 165 ary = numpy.array(cur.fetchall())
161 if ary.shape[0] == 0: 166 if ary.shape[0] == 0:
162 print('No data for ' + c.rowname) 167 print('No data for ' + c.rowname)
163 return 168 return
164 169
221 226
222 if len(annotations) > 0: 227 if len(annotations) > 0:
223 ax1.text(0.02, 0.5, reduce(lambda a, b: a + '\n' + b, annotations), 228 ax1.text(0.02, 0.5, reduce(lambda a, b: a + '\n' + b, annotations),
224 transform = ax1.transAxes, bbox = dict(facecolor = 'blue', alpha = 0.5), 229 transform = ax1.transAxes, bbox = dict(facecolor = 'blue', alpha = 0.5),
225 ha = 'left', va = 'top') 230 ha = 'left', va = 'top')
226 ndays = int(max(1, round((end - start) / 86400))) 231 ndays = int(max(1, round(((end - start).total_seconds()) / 86400)))
227 for ax in fig.get_axes(): 232 for ax in fig.get_axes():
228 if (enddt - startdt).total_seconds() > 86400: 233 if ndays > 1:
229 ax.set_title('%s to %s' % (startdt.strftime('%Y-%m-%d'), enddt.strftime('%Y-%m-%d'))) 234 ax.set_title('%s to %s' % (start.strftime('%Y-%m-%d'), end.strftime('%Y-%m-%d')))
230 else: 235 else:
231 ax.set_title('%s' % (startdt.strftime('%Y-%m-%d'))) 236 ax.set_title('%s' % (start.strftime('%Y-%m-%d')))
232 ax.set_xlim([startdt, enddt]) 237 ax.set_xlim([start, end])
233 ax.format_xdata = lambda d: matplotlib.dates.num2date(d).strftime('%d %b %H:%M') 238 ax.format_xdata = lambda d: matplotlib.dates.num2date(d).strftime('%d %b %H:%M')
234 ax.xaxis.grid(True) 239 ax.xaxis.grid(True)
235 ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%d %b\n%H:%M')) 240 ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%d %b\n%H:%M'))
236 ax.xaxis.set_major_locator(matplotlib.dates.HourLocator(interval = 2 * ndays)) 241 ax.xaxis.set_major_locator(matplotlib.dates.HourLocator(interval = 2 * ndays))
237 ax.xaxis.set_minor_locator(matplotlib.dates.MinuteLocator(interval = 5 * ndays)) 242 ax.xaxis.set_minor_locator(matplotlib.dates.MinuteLocator(interval = 5 * ndays))