1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#!/usr/bin/env python2.6 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# Copyright (C) 2011 The Android Open Source Project 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# Licensed under the Apache License, Version 2.0 (the "License"); 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# you may not use this file except in compliance with the License. 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# You may obtain a copy of the License at 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# http://www.apache.org/licenses/LICENSE-2.0 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# Unless required by applicable law or agreed to in writing, software 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# distributed under the License is distributed on an "AS IS" BASIS, 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# See the License for the specific language governing permissions and 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# limitations under the License. 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# Plots debug log output from WindowOrientationListener. 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# See README.txt for details. 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport numpy as np 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport matplotlib.pyplot as plot 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport subprocess 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport re 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport fcntl 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport os 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport errno 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport bisect 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskifrom datetime import datetime, timedelta 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# Parameters. 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskitimespan = 15 # seconds total span shown 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiscrolljump = 5 # seconds jump when scrolling 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskitimeticks = 1 # seconds between each time tick 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# Non-blocking stream wrapper. 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass NonBlockingStream: 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def __init__(self, stream): 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fcntl.fcntl(stream, fcntl.F_SETFL, os.O_NONBLOCK) 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.stream = stream 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.buffer = '' 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.pos = 0 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def readline(self): 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while True: 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski index = self.buffer.find('\n', self.pos) 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if index != -1: 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = self.buffer[self.pos:index] 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.pos = index + 1 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.buffer = self.buffer[self.pos:] 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.pos = 0 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try: 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski chunk = os.read(self.stream.fileno(), 4096) 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski except OSError, e: 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if e.errno == errno.EAGAIN: 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return None 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski raise e 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if len(chunk) == 0: 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if len(self.buffer) == 0: 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski raise(EOFError) 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else: 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = self.buffer 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.buffer = '' 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.pos = 0 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.buffer += chunk 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# Plotter 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass Plotter: 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def __init__(self, adbout): 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.adbout = adbout 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.fig = plot.figure(1) 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.fig.suptitle('Window Orientation Listener', fontsize=12) 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.fig.set_dpi(96) 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.fig.set_size_inches(16, 12, forward=True) 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_x = self._make_timeseries() 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_y = self._make_timeseries() 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_z = self._make_timeseries() 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_magnitude = self._make_timeseries() 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_axes = self._add_timeseries_axes( 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1, 'Raw Acceleration', 'm/s^2', [-20, 20], 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski yticks=range(-15, 16, 5)) 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_line_x = self._add_timeseries_line( 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_axes, 'x', 'red') 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_line_y = self._add_timeseries_line( 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_axes, 'y', 'green') 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_line_z = self._add_timeseries_line( 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_axes, 'z', 'blue') 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_line_magnitude = self._add_timeseries_line( 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_axes, 'magnitude', 'orange', linewidth=2) 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._add_timeseries_legend(self.raw_acceleration_axes) 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski shared_axis = self.raw_acceleration_axes 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_x = self._make_timeseries() 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_y = self._make_timeseries() 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_z = self._make_timeseries() 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_magnitude = self._make_timeseries() 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_axes = self._add_timeseries_axes( 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2, 'Filtered Acceleration', 'm/s^2', [-20, 20], 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sharex=shared_axis, 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski yticks=range(-15, 16, 5)) 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_line_x = self._add_timeseries_line( 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_axes, 'x', 'red') 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_line_y = self._add_timeseries_line( 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_axes, 'y', 'green') 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_line_z = self._add_timeseries_line( 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_axes, 'z', 'blue') 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_line_magnitude = self._add_timeseries_line( 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_axes, 'magnitude', 'orange', linewidth=2) 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._add_timeseries_legend(self.filtered_acceleration_axes) 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.tilt_angle = self._make_timeseries() 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.tilt_angle_axes = self._add_timeseries_axes( 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3, 'Tilt Angle', 'degrees', [-105, 105], 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sharex=shared_axis, 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski yticks=range(-90, 91, 30)) 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.tilt_angle_line = self._add_timeseries_line( 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.tilt_angle_axes, 'tilt', 'black') 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._add_timeseries_legend(self.tilt_angle_axes) 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.orientation_angle = self._make_timeseries() 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.orientation_angle_axes = self._add_timeseries_axes( 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4, 'Orientation Angle', 'degrees', [-25, 375], 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sharex=shared_axis, 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski yticks=range(0, 361, 45)) 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.orientation_angle_line = self._add_timeseries_line( 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.orientation_angle_axes, 'orientation', 'black') 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._add_timeseries_legend(self.orientation_angle_axes) 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.current_rotation = self._make_timeseries() 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.proposed_rotation = self._make_timeseries() 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.predicted_rotation = self._make_timeseries() 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.orientation_axes = self._add_timeseries_axes( 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 5, 'Current / Proposed Orientation', 'rotation', [-1, 4], 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sharex=shared_axis, 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski yticks=range(0, 4)) 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.current_rotation_line = self._add_timeseries_line( 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.orientation_axes, 'current', 'black', linewidth=2) 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.predicted_rotation_line = self._add_timeseries_line( 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.orientation_axes, 'predicted', 'purple', linewidth=3) 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.proposed_rotation_line = self._add_timeseries_line( 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.orientation_axes, 'proposed', 'green', linewidth=3) 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._add_timeseries_legend(self.orientation_axes) 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.time_until_settled = self._make_timeseries() 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.time_until_flat_delay_expired = self._make_timeseries() 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.time_until_swing_delay_expired = self._make_timeseries() 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.time_until_acceleration_delay_expired = self._make_timeseries() 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.stability_axes = self._add_timeseries_axes( 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 6, 'Proposal Stability', 'ms', [-10, 600], 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sharex=shared_axis, 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski yticks=range(0, 600, 100)) 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.time_until_settled_line = self._add_timeseries_line( 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.stability_axes, 'time until settled', 'black', linewidth=2) 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.time_until_flat_delay_expired_line = self._add_timeseries_line( 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.stability_axes, 'time until flat delay expired', 'green') 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.time_until_swing_delay_expired_line = self._add_timeseries_line( 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.stability_axes, 'time until swing delay expired', 'blue') 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.time_until_acceleration_delay_expired_line = self._add_timeseries_line( 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.stability_axes, 'time until acceleration delay expired', 'red') 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._add_timeseries_legend(self.stability_axes) 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.sample_latency = self._make_timeseries() 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.sample_latency_axes = self._add_timeseries_axes( 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 7, 'Accelerometer Sampling Latency', 'ms', [-10, 500], 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sharex=shared_axis, 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski yticks=range(0, 500, 100)) 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.sample_latency_line = self._add_timeseries_line( 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.sample_latency_axes, 'latency', 'black') 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._add_timeseries_legend(self.sample_latency_axes) 178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.fig.canvas.mpl_connect('button_press_event', self._on_click) 180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.paused = False 181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.timer = self.fig.canvas.new_timer(interval=100) 183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.timer.add_callback(lambda: self.update()) 184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.timer.start() 185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.timebase = None 187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._reset_parse_state() 188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Handle a click event to pause or restart the timer. 190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def _on_click(self, ev): 191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if not self.paused: 192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.paused = True 193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.timer.stop() 194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else: 195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.paused = False 196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.timer.start() 197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Initialize a time series. 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def _make_timeseries(self): 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return [[], []] 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Add a subplot to the figure for a time series. 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def _add_timeseries_axes(self, index, title, ylabel, ylim, yticks, sharex=None): 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski num_graphs = 7 205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski height = 0.9 / num_graphs 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski top = 0.95 - height * index 207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski axes = self.fig.add_axes([0.1, top, 0.8, height], 208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xscale='linear', 209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski xlim=[0, timespan], 210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ylabel=ylabel, 211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski yscale='linear', 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ylim=ylim, 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sharex=sharex) 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski axes.text(0.02, 0.02, title, transform=axes.transAxes, fontsize=10, fontweight='bold') 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski axes.set_xlabel('time (s)', fontsize=10, fontweight='bold') 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski axes.set_ylabel(ylabel, fontsize=10, fontweight='bold') 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski axes.set_xticks(range(0, timespan + 1, timeticks)) 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski axes.set_yticks(yticks) 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski axes.grid(True) 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for label in axes.get_xticklabels(): 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label.set_fontsize(9) 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for label in axes.get_yticklabels(): 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski label.set_fontsize(9) 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return axes 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Add a line to the axes for a time series. 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def _add_timeseries_line(self, axes, label, color, linewidth=1): 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return axes.plot([], label=label, color=color, linewidth=linewidth)[0] 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Add a legend to a time series. 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def _add_timeseries_legend(self, axes): 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski axes.legend( 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski loc='upper left', 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bbox_to_anchor=(1.01, 1), 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski borderpad=0.1, 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski borderaxespad=0.1, 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski prop={'size': 10}) 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Resets the parse state. 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def _reset_parse_state(self): 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_raw_acceleration_x = None 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_raw_acceleration_y = None 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_raw_acceleration_z = None 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_raw_acceleration_magnitude = None 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_filtered_acceleration_x = None 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_filtered_acceleration_y = None 249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_filtered_acceleration_z = None 250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_filtered_acceleration_magnitude = None 251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_tilt_angle = None 252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_orientation_angle = None 253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_current_rotation = None 254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_proposed_rotation = None 255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_predicted_rotation = None 256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_time_until_settled = None 257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_time_until_flat_delay_expired = None 258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_time_until_swing_delay_expired = None 259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_time_until_acceleration_delay_expired = None 260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_sample_latency = None 261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Update samples. 263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def update(self): 264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski timeindex = 0 265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while True: 266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try: 267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski line = self.adbout.readline() 268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski except EOFError: 269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski plot.close() 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if line is None: 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski print line 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try: 276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski timestamp = self._parse_timestamp(line) 277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski except ValueError, e: 278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue 279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if self.timebase is None: 280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.timebase = timestamp 281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delta = timestamp - self.timebase 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski timeindex = delta.seconds + delta.microseconds * 0.000001 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if line.find('Raw acceleration vector:') != -1: 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_raw_acceleration_x = self._get_following_number(line, 'x=') 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_raw_acceleration_y = self._get_following_number(line, 'y=') 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_raw_acceleration_z = self._get_following_number(line, 'z=') 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_raw_acceleration_magnitude = self._get_following_number(line, 'magnitude=') 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if line.find('Filtered acceleration vector:') != -1: 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_filtered_acceleration_x = self._get_following_number(line, 'x=') 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_filtered_acceleration_y = self._get_following_number(line, 'y=') 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_filtered_acceleration_z = self._get_following_number(line, 'z=') 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_filtered_acceleration_magnitude = self._get_following_number(line, 'magnitude=') 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if line.find('tiltAngle=') != -1: 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_tilt_angle = self._get_following_number(line, 'tiltAngle=') 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if line.find('orientationAngle=') != -1: 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_orientation_angle = self._get_following_number(line, 'orientationAngle=') 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if line.find('Result:') != -1: 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_current_rotation = self._get_following_number(line, 'currentRotation=') 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_proposed_rotation = self._get_following_number(line, 'proposedRotation=') 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_predicted_rotation = self._get_following_number(line, 'predictedRotation=') 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_sample_latency = self._get_following_number(line, 'timeDeltaMS=') 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_time_until_settled = self._get_following_number(line, 'timeUntilSettledMS=') 308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_time_until_flat_delay_expired = self._get_following_number(line, 'timeUntilFlatDelayExpiredMS=') 309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_time_until_swing_delay_expired = self._get_following_number(line, 'timeUntilSwingDelayExpiredMS=') 310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.parse_time_until_acceleration_delay_expired = self._get_following_number(line, 'timeUntilAccelerationDelayExpiredMS=') 311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.raw_acceleration_x, timeindex, self.parse_raw_acceleration_x) 313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.raw_acceleration_y, timeindex, self.parse_raw_acceleration_y) 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.raw_acceleration_z, timeindex, self.parse_raw_acceleration_z) 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.raw_acceleration_magnitude, timeindex, self.parse_raw_acceleration_magnitude) 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.filtered_acceleration_x, timeindex, self.parse_filtered_acceleration_x) 317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.filtered_acceleration_y, timeindex, self.parse_filtered_acceleration_y) 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.filtered_acceleration_z, timeindex, self.parse_filtered_acceleration_z) 319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.filtered_acceleration_magnitude, timeindex, self.parse_filtered_acceleration_magnitude) 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.tilt_angle, timeindex, self.parse_tilt_angle) 321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.orientation_angle, timeindex, self.parse_orientation_angle) 322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.current_rotation, timeindex, self.parse_current_rotation) 323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if self.parse_proposed_rotation >= 0: 324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.proposed_rotation, timeindex, self.parse_proposed_rotation) 325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else: 326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.proposed_rotation, timeindex, None) 327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if self.parse_predicted_rotation >= 0: 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.predicted_rotation, timeindex, self.parse_predicted_rotation) 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else: 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.predicted_rotation, timeindex, None) 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.time_until_settled, timeindex, self.parse_time_until_settled) 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.time_until_flat_delay_expired, timeindex, self.parse_time_until_flat_delay_expired) 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.time_until_swing_delay_expired, timeindex, self.parse_time_until_swing_delay_expired) 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.time_until_acceleration_delay_expired, timeindex, self.parse_time_until_acceleration_delay_expired) 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._append(self.sample_latency, timeindex, self.parse_sample_latency) 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._reset_parse_state() 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Scroll the plots. 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if timeindex > timespan: 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bottom = int(timeindex) - timespan + scrolljump 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.timebase += timedelta(seconds=bottom) 342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.raw_acceleration_x, bottom) 343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.raw_acceleration_y, bottom) 344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.raw_acceleration_z, bottom) 345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.raw_acceleration_magnitude, bottom) 346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.filtered_acceleration_x, bottom) 347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.filtered_acceleration_y, bottom) 348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.filtered_acceleration_z, bottom) 349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.filtered_acceleration_magnitude, bottom) 350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.tilt_angle, bottom) 351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.orientation_angle, bottom) 352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.current_rotation, bottom) 353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.proposed_rotation, bottom) 354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.predicted_rotation, bottom) 355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.time_until_settled, bottom) 356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.time_until_flat_delay_expired, bottom) 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.time_until_swing_delay_expired, bottom) 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.time_until_acceleration_delay_expired, bottom) 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self._scroll(self.sample_latency, bottom) 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Redraw the plots. 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_line_x.set_data(self.raw_acceleration_x) 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_line_y.set_data(self.raw_acceleration_y) 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_line_z.set_data(self.raw_acceleration_z) 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.raw_acceleration_line_magnitude.set_data(self.raw_acceleration_magnitude) 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_line_x.set_data(self.filtered_acceleration_x) 367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_line_y.set_data(self.filtered_acceleration_y) 368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_line_z.set_data(self.filtered_acceleration_z) 369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.filtered_acceleration_line_magnitude.set_data(self.filtered_acceleration_magnitude) 370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.tilt_angle_line.set_data(self.tilt_angle) 371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.orientation_angle_line.set_data(self.orientation_angle) 372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.current_rotation_line.set_data(self.current_rotation) 373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.proposed_rotation_line.set_data(self.proposed_rotation) 374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.predicted_rotation_line.set_data(self.predicted_rotation) 375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.time_until_settled_line.set_data(self.time_until_settled) 376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.time_until_flat_delay_expired_line.set_data(self.time_until_flat_delay_expired) 377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.time_until_swing_delay_expired_line.set_data(self.time_until_swing_delay_expired) 378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.time_until_acceleration_delay_expired_line.set_data(self.time_until_acceleration_delay_expired) 379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.sample_latency_line.set_data(self.sample_latency) 380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski self.fig.canvas.draw_idle() 382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Scroll a time series. 384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def _scroll(self, timeseries, bottom): 385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bottom_index = bisect.bisect_left(timeseries[0], bottom) 386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski del timeseries[0][:bottom_index] 387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski del timeseries[1][:bottom_index] 388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for i, timeindex in enumerate(timeseries[0]): 389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski timeseries[0][i] = timeindex - bottom 390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Extract a word following the specified prefix. 392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def _get_following_word(self, line, prefix): 393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski prefix_index = line.find(prefix) 394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if prefix_index == -1: 395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return None 396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski start_index = prefix_index + len(prefix) 397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delim_index = line.find(',', start_index) 398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if delim_index == -1: 399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return line[start_index:] 400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else: 401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return line[start_index:delim_index] 402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Extract a number following the specified prefix. 404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def _get_following_number(self, line, prefix): 405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski word = self._get_following_word(line, prefix) 406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if word is None: 407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return None 408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return float(word) 409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Extract an array of numbers following the specified prefix. 411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def _get_following_array_of_numbers(self, line, prefix): 412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski prefix_index = line.find(prefix + '[') 413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if prefix_index == -1: 414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return None 415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski start_index = prefix_index + len(prefix) + 1 416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delim_index = line.find(']', start_index) 417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if delim_index == -1: 418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return None 419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = [] 421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while start_index < delim_index: 422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski comma_index = line.find(', ', start_index, delim_index) 423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if comma_index == -1: 424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result.append(float(line[start_index:delim_index])) 425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result.append(float(line[start_index:comma_index])) 427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski start_index = comma_index + 2 428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result 429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Add a value to a time series. 431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def _append(self, timeseries, timeindex, number): 432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski timeseries[0].append(timeindex) 433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski timeseries[1].append(number) 434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Parse the logcat timestamp. 436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski # Timestamp has the form '01-21 20:42:42.930' 437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski def _parse_timestamp(self, line): 438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return datetime.strptime(line[0:18], '%m-%d %H:%M:%S.%f') 439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# Notice 441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiprint "Window Orientation Listener plotting tool" 442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiprint "-----------------------------------------\n" 443e97c9a244b71b6376003c377b56f7a86bcd0049fJeff Brownprint "Please turn on the Window Orientation Listener logging. See README.txt." 444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# Start adb. 446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiprint "Starting adb logcat.\n" 447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiadb = subprocess.Popen(['adb', 'logcat', '-s', '-v', 'time', 'WindowOrientationListener:V'], 449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski stdout=subprocess.PIPE) 450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiadbout = NonBlockingStream(adb.stdout) 451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# Prepare plotter. 453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiplotter = Plotter(adbout) 454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiplotter.update() 455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski# Main loop. 457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiplot.show() 458