blob: 30c159f75a3c71b58493605fefd98444fadc5016 [file] [log] [blame]
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
""" Parse a raw log captured from mtplot into a format compatible with replay.py
This script loads an mtplot log and parses it generating a pickled file called
path.p that contains a list of events. Each event is a list of 0 or more tuples
representing coordinates with x and y ranges from 0.0 to 1.0.
For example the generated path for a very simple log may look like:
[
[(0.1, 0.1)],
[(0.15, 0.2)],
[(0.2, 0.27), (0.8, 0.9)]
]
This is achieved by scaling all the x and y reading by their maximum range
and eliminated most of the unneeded information in the mtplot log.
To use this script, first capture a log by running the following command
and performing your gesture on the pad.
DISPLAY=:0 mtplot > my_mtplot_log.txt
Then parse it with this script
python parse_log my_mtplot_log.txt
It will generate a path.p for you that can then be replayed on the touchbot
with the replay.py script.
"""
import pickle
import re
import sys
from collections import defaultdict
CODE_X = 'ABS_MT_POSITION_X'
CODE_Y = 'ABS_MT_POSITION_Y'
CODE_SLOT = 'ABS_MT_SLOT'
CODE_TRACKING_ID = 'ABS_MT_TRACKING_ID'
MAX_FINGERS = 10
min_vals = {}
max_vals = {}
range_vals = {}
curr_header_slot = None
events = []
slot = 0
curr_state = defaultdict(lambda: {})
with open(sys.argv[1], 'r') as fo:
for line in fo:
header_matches = re.search('\W*Event code \d* \(([A-Z_]*)\)\W*', line)
if header_matches:
curr_header_slot = header_matches.groups()[0]
min_matches = re.search('\W*Min\W*(\d*)\W*', line)
if min_matches:
min_vals[curr_header_slot] = int(min_matches.groups()[0])
max_matches = re.search('\W*Max\W*(\d*)\W*', line)
if max_matches:
max_vals[curr_header_slot] = int(max_matches.groups()[0])
if min_matches or max_matches:
range_vals[curr_header_slot] = float(
max_vals.get(curr_header_slot, 0) -
min_vals.get(curr_header_slot, 0)
)
# Handle the actual events
event_matches = re.search('Event: time[^(]*\([^(]*\)[^(]*\(([A-Z_]*)\)'
', value ([0-9\-]*).*', line)
if event_matches:
value_name = event_matches.groups()[0]
value = int(event_matches.groups()[1])
if value_name == CODE_TRACKING_ID:
if value == -1:
curr_state[slot] = {}
elif value_name == CODE_SLOT:
slot = value
elif slot >= 0:
curr_state[slot][value_name] = value
# Copy over the X and Y values when you get a SYN_REPORT
# and scale them to between 0.0 and 1.0
if re.search('SYN_REPORT', line):
positions = []
for s in curr_state:
if not curr_state[s].get(CODE_X, None):
continue
if not curr_state[s].get(CODE_Y, None):
continue
scaled_x = ((curr_state[s][CODE_X] - min_vals[CODE_X]) /
range_vals[CODE_X])
scaled_y = ((curr_state[s][CODE_Y] - min_vals[CODE_Y]) /
range_vals[CODE_Y])
positions.append((scaled_x, scaled_y))
events.append(positions)
pickle.dump(events, open('path.p', 'w'))
print 'Your parsed log has been saved to disk as "path.p"'