14519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown#!/usr/bin/env python2.6 24519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# 34519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# Copyright (C) 2011 The Android Open Source Project 44519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# 54519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# Licensed under the Apache License, Version 2.0 (the "License"); 64519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# you may not use this file except in compliance with the License. 74519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# You may obtain a copy of the License at 84519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# 94519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# http://www.apache.org/licenses/LICENSE-2.0 104519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# 114519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# Unless required by applicable law or agreed to in writing, software 124519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# distributed under the License is distributed on an "AS IS" BASIS, 134519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 144519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# See the License for the specific language governing permissions and 154519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# limitations under the License. 164519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# 174519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 184519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# 194519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# Plots debug log output from WindowOrientationListener. 204519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# See README.txt for details. 214519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# 224519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 234519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownimport numpy as np 244519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownimport matplotlib.pyplot as plot 254519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownimport subprocess 264519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownimport re 274519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownimport fcntl 284519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownimport os 294519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownimport errno 304519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownimport bisect 314519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownfrom datetime import datetime, timedelta 324519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 334519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# Parameters. 344519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Browntimespan = 15 # seconds total span shown 354519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownscrolljump = 5 # seconds jump when scrolling 364519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Browntimeticks = 1 # seconds between each time tick 374519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 384519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# Non-blocking stream wrapper. 394519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownclass NonBlockingStream: 404519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def __init__(self, stream): 414519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown fcntl.fcntl(stream, fcntl.F_SETFL, os.O_NONBLOCK) 424519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.stream = stream 434519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.buffer = '' 444519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.pos = 0 454519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 464519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def readline(self): 474519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown while True: 484519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown index = self.buffer.find('\n', self.pos) 494519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if index != -1: 504519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown result = self.buffer[self.pos:index] 514519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.pos = index + 1 524519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return result 534519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 544519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.buffer = self.buffer[self.pos:] 554519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.pos = 0 564519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown try: 574519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown chunk = os.read(self.stream.fileno(), 4096) 584519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown except OSError, e: 594519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if e.errno == errno.EAGAIN: 604519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return None 614519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown raise e 624519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if len(chunk) == 0: 634519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if len(self.buffer) == 0: 644519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown raise(EOFError) 654519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown else: 664519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown result = self.buffer 674519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.buffer = '' 684519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.pos = 0 694519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return result 704519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.buffer += chunk 714519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 724519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# Plotter 734519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownclass Plotter: 744519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def __init__(self, adbout): 754519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.adbout = adbout 764519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 774519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.fig = plot.figure(1) 784519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.fig.suptitle('Window Orientation Listener', fontsize=12) 794519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.fig.set_dpi(96) 804519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.fig.set_size_inches(16, 12, forward=True) 814519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 824519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_x = self._make_timeseries() 834519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_y = self._make_timeseries() 844519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_z = self._make_timeseries() 855aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.raw_acceleration_magnitude = self._make_timeseries() 864519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_axes = self._add_timeseries_axes( 874519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 1, 'Raw Acceleration', 'm/s^2', [-20, 20], 884519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown yticks=range(-15, 16, 5)) 894519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_line_x = self._add_timeseries_line( 904519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_axes, 'x', 'red') 914519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_line_y = self._add_timeseries_line( 924519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_axes, 'y', 'green') 934519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_line_z = self._add_timeseries_line( 944519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_axes, 'z', 'blue') 955aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.raw_acceleration_line_magnitude = self._add_timeseries_line( 965aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.raw_acceleration_axes, 'magnitude', 'orange', linewidth=2) 974519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._add_timeseries_legend(self.raw_acceleration_axes) 984519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 994519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown shared_axis = self.raw_acceleration_axes 1004519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 1014519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_x = self._make_timeseries() 1024519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_y = self._make_timeseries() 1034519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_z = self._make_timeseries() 1045aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.filtered_acceleration_magnitude = self._make_timeseries() 1054519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_axes = self._add_timeseries_axes( 1064519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2, 'Filtered Acceleration', 'm/s^2', [-20, 20], 1074519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown sharex=shared_axis, 1084519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown yticks=range(-15, 16, 5)) 1094519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_line_x = self._add_timeseries_line( 1104519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_axes, 'x', 'red') 1114519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_line_y = self._add_timeseries_line( 1124519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_axes, 'y', 'green') 1134519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_line_z = self._add_timeseries_line( 1144519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_axes, 'z', 'blue') 1155aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.filtered_acceleration_line_magnitude = self._add_timeseries_line( 1164519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_axes, 'magnitude', 'orange', linewidth=2) 1174519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._add_timeseries_legend(self.filtered_acceleration_axes) 1184519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 1194519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.tilt_angle = self._make_timeseries() 1204519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.tilt_angle_axes = self._add_timeseries_axes( 1214519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 3, 'Tilt Angle', 'degrees', [-105, 105], 1224519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown sharex=shared_axis, 1234519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown yticks=range(-90, 91, 30)) 1244519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.tilt_angle_line = self._add_timeseries_line( 1254519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.tilt_angle_axes, 'tilt', 'black') 1264519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._add_timeseries_legend(self.tilt_angle_axes) 1274519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 1284519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.orientation_angle = self._make_timeseries() 1294519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.orientation_angle_axes = self._add_timeseries_axes( 1304519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 4, 'Orientation Angle', 'degrees', [-25, 375], 1314519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown sharex=shared_axis, 1324519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown yticks=range(0, 361, 45)) 1334519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.orientation_angle_line = self._add_timeseries_line( 1344519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.orientation_angle_axes, 'orientation', 'black') 1354519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._add_timeseries_legend(self.orientation_angle_axes) 1364519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 137c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self.current_rotation = self._make_timeseries() 138c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self.proposed_rotation = self._make_timeseries() 1395aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.predicted_rotation = self._make_timeseries() 1404519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.orientation_axes = self._add_timeseries_axes( 1415aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown 5, 'Current / Proposed Orientation', 'rotation', [-1, 4], 1424519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown sharex=shared_axis, 1434519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown yticks=range(0, 4)) 144c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self.current_rotation_line = self._add_timeseries_line( 145c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self.orientation_axes, 'current', 'black', linewidth=2) 1465aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.predicted_rotation_line = self._add_timeseries_line( 1475aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.orientation_axes, 'predicted', 'purple', linewidth=3) 148c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self.proposed_rotation_line = self._add_timeseries_line( 149c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self.orientation_axes, 'proposed', 'green', linewidth=3) 1504519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._add_timeseries_legend(self.orientation_axes) 1514519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 1525aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.time_until_settled = self._make_timeseries() 1535aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.time_until_flat_delay_expired = self._make_timeseries() 1545aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.time_until_swing_delay_expired = self._make_timeseries() 155daf5d894ef71c5674e83b11de8b408e3bdabe4c7Jeff Brown self.time_until_acceleration_delay_expired = self._make_timeseries() 1565aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.stability_axes = self._add_timeseries_axes( 1575aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown 6, 'Proposal Stability', 'ms', [-10, 600], 1585aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown sharex=shared_axis, 1595aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown yticks=range(0, 600, 100)) 1605aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.time_until_settled_line = self._add_timeseries_line( 1615aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.stability_axes, 'time until settled', 'black', linewidth=2) 1625aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.time_until_flat_delay_expired_line = self._add_timeseries_line( 1635aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.stability_axes, 'time until flat delay expired', 'green') 1645aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.time_until_swing_delay_expired_line = self._add_timeseries_line( 1655aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.stability_axes, 'time until swing delay expired', 'blue') 166daf5d894ef71c5674e83b11de8b408e3bdabe4c7Jeff Brown self.time_until_acceleration_delay_expired_line = self._add_timeseries_line( 167daf5d894ef71c5674e83b11de8b408e3bdabe4c7Jeff Brown self.stability_axes, 'time until acceleration delay expired', 'red') 1685aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._add_timeseries_legend(self.stability_axes) 1694519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 1704519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.sample_latency = self._make_timeseries() 1714519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.sample_latency_axes = self._add_timeseries_axes( 1725aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown 7, 'Accelerometer Sampling Latency', 'ms', [-10, 500], 1734519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown sharex=shared_axis, 1744519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown yticks=range(0, 500, 100)) 1754519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.sample_latency_line = self._add_timeseries_line( 1764519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.sample_latency_axes, 'latency', 'black') 1774519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._add_timeseries_legend(self.sample_latency_axes) 1784519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 1795aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.fig.canvas.mpl_connect('button_press_event', self._on_click) 1805aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.paused = False 1815aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown 1824519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.timer = self.fig.canvas.new_timer(interval=100) 1834519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.timer.add_callback(lambda: self.update()) 1844519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.timer.start() 1854519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 1864519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.timebase = None 1874519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._reset_parse_state() 1884519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 1895aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown # Handle a click event to pause or restart the timer. 1905aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown def _on_click(self, ev): 1915aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown if not self.paused: 1925aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.paused = True 1935aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.timer.stop() 1945aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown else: 1955aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.paused = False 1965aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.timer.start() 1975aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown 1984519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Initialize a time series. 1994519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def _make_timeseries(self): 2004519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return [[], []] 2014519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2024519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Add a subplot to the figure for a time series. 2034519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def _add_timeseries_axes(self, index, title, ylabel, ylim, yticks, sharex=None): 2045aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown num_graphs = 7 2054519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown height = 0.9 / num_graphs 2064519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown top = 0.95 - height * index 2074519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown axes = self.fig.add_axes([0.1, top, 0.8, height], 2084519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown xscale='linear', 2094519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown xlim=[0, timespan], 2104519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown ylabel=ylabel, 2114519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown yscale='linear', 2124519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown ylim=ylim, 2134519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown sharex=sharex) 2144519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown axes.text(0.02, 0.02, title, transform=axes.transAxes, fontsize=10, fontweight='bold') 2154519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown axes.set_xlabel('time (s)', fontsize=10, fontweight='bold') 2164519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown axes.set_ylabel(ylabel, fontsize=10, fontweight='bold') 2174519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown axes.set_xticks(range(0, timespan + 1, timeticks)) 2184519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown axes.set_yticks(yticks) 2194519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown axes.grid(True) 2204519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2214519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown for label in axes.get_xticklabels(): 2224519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown label.set_fontsize(9) 2234519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown for label in axes.get_yticklabels(): 2244519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown label.set_fontsize(9) 2254519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2264519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return axes 2274519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2284519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Add a line to the axes for a time series. 2294519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def _add_timeseries_line(self, axes, label, color, linewidth=1): 2304519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return axes.plot([], label=label, color=color, linewidth=linewidth)[0] 2314519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2324519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Add a legend to a time series. 2334519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def _add_timeseries_legend(self, axes): 2344519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown axes.legend( 2354519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown loc='upper left', 2364519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown bbox_to_anchor=(1.01, 1), 2374519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown borderpad=0.1, 2384519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown borderaxespad=0.1, 2394519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown prop={'size': 10}) 2404519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2414519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Resets the parse state. 2424519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def _reset_parse_state(self): 2434519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_raw_acceleration_x = None 2444519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_raw_acceleration_y = None 2454519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_raw_acceleration_z = None 2465aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.parse_raw_acceleration_magnitude = None 2474519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_filtered_acceleration_x = None 2484519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_filtered_acceleration_y = None 2494519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_filtered_acceleration_z = None 2505aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.parse_filtered_acceleration_magnitude = None 2514519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_tilt_angle = None 2524519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_orientation_angle = None 253c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self.parse_current_rotation = None 254c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self.parse_proposed_rotation = None 2555aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.parse_predicted_rotation = None 2565aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.parse_time_until_settled = None 2575aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.parse_time_until_flat_delay_expired = None 2585aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.parse_time_until_swing_delay_expired = None 259daf5d894ef71c5674e83b11de8b408e3bdabe4c7Jeff Brown self.parse_time_until_acceleration_delay_expired = None 2604519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_sample_latency = None 2614519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2624519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Update samples. 2634519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def update(self): 2644519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown timeindex = 0 2654519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown while True: 2664519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown try: 2674519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown line = self.adbout.readline() 2684519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown except EOFError: 2694519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown plot.close() 2704519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return 2714519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if line is None: 2724519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown break 2734519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown print line 2744519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2754519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown try: 2764519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown timestamp = self._parse_timestamp(line) 2774519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown except ValueError, e: 2784519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown continue 2794519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if self.timebase is None: 2804519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.timebase = timestamp 2814519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown delta = timestamp - self.timebase 2824519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown timeindex = delta.seconds + delta.microseconds * 0.000001 2834519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2844519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if line.find('Raw acceleration vector:') != -1: 2854519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_raw_acceleration_x = self._get_following_number(line, 'x=') 2864519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_raw_acceleration_y = self._get_following_number(line, 'y=') 2874519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_raw_acceleration_z = self._get_following_number(line, 'z=') 2885aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.parse_raw_acceleration_magnitude = self._get_following_number(line, 'magnitude=') 2894519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2904519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if line.find('Filtered acceleration vector:') != -1: 2914519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_filtered_acceleration_x = self._get_following_number(line, 'x=') 2924519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_filtered_acceleration_y = self._get_following_number(line, 'y=') 2934519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_filtered_acceleration_z = self._get_following_number(line, 'z=') 2945aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.parse_filtered_acceleration_magnitude = self._get_following_number(line, 'magnitude=') 2954519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2964519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if line.find('tiltAngle=') != -1: 2974519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_tilt_angle = self._get_following_number(line, 'tiltAngle=') 2984519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 2994519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if line.find('orientationAngle=') != -1: 3004519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_orientation_angle = self._get_following_number(line, 'orientationAngle=') 3014519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 3024519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if line.find('Result:') != -1: 303c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self.parse_current_rotation = self._get_following_number(line, 'currentRotation=') 304c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self.parse_proposed_rotation = self._get_following_number(line, 'proposedRotation=') 3055aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.parse_predicted_rotation = self._get_following_number(line, 'predictedRotation=') 3064519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.parse_sample_latency = self._get_following_number(line, 'timeDeltaMS=') 3075aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.parse_time_until_settled = self._get_following_number(line, 'timeUntilSettledMS=') 3085aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.parse_time_until_flat_delay_expired = self._get_following_number(line, 'timeUntilFlatDelayExpiredMS=') 3095aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.parse_time_until_swing_delay_expired = self._get_following_number(line, 'timeUntilSwingDelayExpiredMS=') 310daf5d894ef71c5674e83b11de8b408e3bdabe4c7Jeff Brown self.parse_time_until_acceleration_delay_expired = self._get_following_number(line, 'timeUntilAccelerationDelayExpiredMS=') 3114519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 3124519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._append(self.raw_acceleration_x, timeindex, self.parse_raw_acceleration_x) 3134519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._append(self.raw_acceleration_y, timeindex, self.parse_raw_acceleration_y) 3144519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._append(self.raw_acceleration_z, timeindex, self.parse_raw_acceleration_z) 3155aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._append(self.raw_acceleration_magnitude, timeindex, self.parse_raw_acceleration_magnitude) 3164519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._append(self.filtered_acceleration_x, timeindex, self.parse_filtered_acceleration_x) 3174519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._append(self.filtered_acceleration_y, timeindex, self.parse_filtered_acceleration_y) 3184519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._append(self.filtered_acceleration_z, timeindex, self.parse_filtered_acceleration_z) 3195aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._append(self.filtered_acceleration_magnitude, timeindex, self.parse_filtered_acceleration_magnitude) 3204519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._append(self.tilt_angle, timeindex, self.parse_tilt_angle) 3214519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._append(self.orientation_angle, timeindex, self.parse_orientation_angle) 322c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self._append(self.current_rotation, timeindex, self.parse_current_rotation) 323c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown if self.parse_proposed_rotation >= 0: 324c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self._append(self.proposed_rotation, timeindex, self.parse_proposed_rotation) 325c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown else: 326c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self._append(self.proposed_rotation, timeindex, None) 3275aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown if self.parse_predicted_rotation >= 0: 3285aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._append(self.predicted_rotation, timeindex, self.parse_predicted_rotation) 329c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown else: 3305aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._append(self.predicted_rotation, timeindex, None) 3315aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._append(self.time_until_settled, timeindex, self.parse_time_until_settled) 3325aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._append(self.time_until_flat_delay_expired, timeindex, self.parse_time_until_flat_delay_expired) 3335aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._append(self.time_until_swing_delay_expired, timeindex, self.parse_time_until_swing_delay_expired) 334daf5d894ef71c5674e83b11de8b408e3bdabe4c7Jeff Brown self._append(self.time_until_acceleration_delay_expired, timeindex, self.parse_time_until_acceleration_delay_expired) 3354519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._append(self.sample_latency, timeindex, self.parse_sample_latency) 3364519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._reset_parse_state() 3374519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 3384519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Scroll the plots. 3394519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if timeindex > timespan: 3404519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown bottom = int(timeindex) - timespan + scrolljump 3414519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.timebase += timedelta(seconds=bottom) 3424519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._scroll(self.raw_acceleration_x, bottom) 3434519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._scroll(self.raw_acceleration_y, bottom) 3444519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._scroll(self.raw_acceleration_z, bottom) 3455aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._scroll(self.raw_acceleration_magnitude, bottom) 3464519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._scroll(self.filtered_acceleration_x, bottom) 3474519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._scroll(self.filtered_acceleration_y, bottom) 3484519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._scroll(self.filtered_acceleration_z, bottom) 3495aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._scroll(self.filtered_acceleration_magnitude, bottom) 3504519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._scroll(self.tilt_angle, bottom) 3514519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self._scroll(self.orientation_angle, bottom) 352c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self._scroll(self.current_rotation, bottom) 353c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self._scroll(self.proposed_rotation, bottom) 3545aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._scroll(self.predicted_rotation, bottom) 3555aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._scroll(self.time_until_settled, bottom) 3565aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._scroll(self.time_until_flat_delay_expired, bottom) 3575aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self._scroll(self.time_until_swing_delay_expired, bottom) 358daf5d894ef71c5674e83b11de8b408e3bdabe4c7Jeff Brown self._scroll(self.time_until_acceleration_delay_expired, bottom) 359c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self._scroll(self.sample_latency, bottom) 3604519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 3614519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Redraw the plots. 3624519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_line_x.set_data(self.raw_acceleration_x) 3634519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_line_y.set_data(self.raw_acceleration_y) 3644519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.raw_acceleration_line_z.set_data(self.raw_acceleration_z) 3655aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.raw_acceleration_line_magnitude.set_data(self.raw_acceleration_magnitude) 3664519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_line_x.set_data(self.filtered_acceleration_x) 3674519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_line_y.set_data(self.filtered_acceleration_y) 3684519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.filtered_acceleration_line_z.set_data(self.filtered_acceleration_z) 3695aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.filtered_acceleration_line_magnitude.set_data(self.filtered_acceleration_magnitude) 3704519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.tilt_angle_line.set_data(self.tilt_angle) 3714519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.orientation_angle_line.set_data(self.orientation_angle) 372c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self.current_rotation_line.set_data(self.current_rotation) 373c0347aa19f354a8e1ff4fcd5372b134c0c7c16adJeff Brown self.proposed_rotation_line.set_data(self.proposed_rotation) 3745aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.predicted_rotation_line.set_data(self.predicted_rotation) 3755aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.time_until_settled_line.set_data(self.time_until_settled) 3765aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.time_until_flat_delay_expired_line.set_data(self.time_until_flat_delay_expired) 3775aa73ae58f049379a97bc86add541f27170c02a4Jeff Brown self.time_until_swing_delay_expired_line.set_data(self.time_until_swing_delay_expired) 378daf5d894ef71c5674e83b11de8b408e3bdabe4c7Jeff Brown self.time_until_acceleration_delay_expired_line.set_data(self.time_until_acceleration_delay_expired) 3794519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.sample_latency_line.set_data(self.sample_latency) 3804519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 3814519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown self.fig.canvas.draw_idle() 3824519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 3834519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Scroll a time series. 3844519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def _scroll(self, timeseries, bottom): 3854519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown bottom_index = bisect.bisect_left(timeseries[0], bottom) 3864519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown del timeseries[0][:bottom_index] 3874519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown del timeseries[1][:bottom_index] 3884519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown for i, timeindex in enumerate(timeseries[0]): 3894519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown timeseries[0][i] = timeindex - bottom 3904519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 3914519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Extract a word following the specified prefix. 3924519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def _get_following_word(self, line, prefix): 3934519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown prefix_index = line.find(prefix) 3944519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if prefix_index == -1: 3954519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return None 3964519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown start_index = prefix_index + len(prefix) 3974519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown delim_index = line.find(',', start_index) 3984519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if delim_index == -1: 3994519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return line[start_index:] 4004519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown else: 4014519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return line[start_index:delim_index] 4024519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 4034519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Extract a number following the specified prefix. 4044519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def _get_following_number(self, line, prefix): 4054519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown word = self._get_following_word(line, prefix) 4064519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if word is None: 4074519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return None 4084519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return float(word) 4094519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 4104519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Extract an array of numbers following the specified prefix. 4114519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def _get_following_array_of_numbers(self, line, prefix): 4124519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown prefix_index = line.find(prefix + '[') 4134519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if prefix_index == -1: 4144519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return None 4154519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown start_index = prefix_index + len(prefix) + 1 4164519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown delim_index = line.find(']', start_index) 4174519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if delim_index == -1: 4184519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return None 4194519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 4204519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown result = [] 4214519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown while start_index < delim_index: 4224519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown comma_index = line.find(', ', start_index, delim_index) 4234519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown if comma_index == -1: 4244519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown result.append(float(line[start_index:delim_index])) 4254519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown break; 4264519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown result.append(float(line[start_index:comma_index])) 4274519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown start_index = comma_index + 2 4284519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return result 4294519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 4304519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Add a value to a time series. 4314519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def _append(self, timeseries, timeindex, number): 4324519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown timeseries[0].append(timeindex) 4334519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown timeseries[1].append(number) 4344519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 4354519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Parse the logcat timestamp. 4364519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown # Timestamp has the form '01-21 20:42:42.930' 4374519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown def _parse_timestamp(self, line): 4384519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown return datetime.strptime(line[0:18], '%m-%d %H:%M:%S.%f') 4394519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 4404519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# Notice 4414519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownprint "Window Orientation Listener plotting tool" 4424519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownprint "-----------------------------------------\n" 4434519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownprint "Please turn on the Window Orientation Listener logging in Development Settings." 4444519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 4454519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# Start adb. 4464519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownprint "Starting adb logcat.\n" 4474519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 4484519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownadb = subprocess.Popen(['adb', 'logcat', '-s', '-v', 'time', 'WindowOrientationListener:V'], 4494519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown stdout=subprocess.PIPE) 4504519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownadbout = NonBlockingStream(adb.stdout) 4514519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 4524519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# Prepare plotter. 4534519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownplotter = Plotter(adbout) 4544519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownplotter.update() 4554519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown 4564519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brown# Main loop. 4574519f07e9c6b993fbe7a3d3df24d71d9450a54f1Jeff Brownplot.show() 458