def process(data_dir, user_data, survey_data): pool = multiprocessing.Pool(processes=12) user_ids = [user.user_id for user in user_data] object_paths = [ '/'.join([data_dir, user.object_file]) for user in user_data ] object_features = pool.map(process_objects, object_paths) object_timelines = [x['object_timeline'] for x in object_features] experiment_paths = [ '/'.join([data_dir, user.experiment_file]) for user in user_data ] args = zip(experiment_paths, object_timelines) experiment_features = pool.map(process_experiment, args) webcam_paths = [ '/'.join([data_dir, user.webcam_file]) for user in user_data ] args = zip(webcam_paths, object_timelines) webcam_features = pool.map(process_code, args) all_data = [] for user_id, (exp, exp_timeline), (cam, cam_timeline), obj, survey in zip( user_ids, experiment_features, webcam_features, object_features, survey_data): object_stats = ObjectStats() object_stats.update(exp) object_stats.update(cam) data = (user_id, object_stats, exp_timeline, cam_timeline, obj, survey) all_data.append(data) html = views.generate(all_data) output_path = '/'.join([data_dir, 'index.html']) with open(output_path, 'w') as output_file: print(html, file=output_file)
def __init__(self, object_timeline): self._previous_message = None self._previous_time = None self._object_stats = ObjectStats() self._object_timeline = object_timeline self._raw_first_time = None for obj in objects.OBJECTS: self._object_stats.add(obj, 'camera_movement_time', 0) self._timeline = []
def __init__(self, object_timeline): self._pose_update_start = None self._pose_update_end = None self._object_stats = ObjectStats() self._object_timeline = object_timeline self._raw_first_time = None for obj in objects.OBJECTS: self._object_stats.add(obj, 'marker_movement_time', 0) self._timeline = []
def __init__(self, object_timeline): self._is_left_closed = True self._is_right_closed = True self.left_grasps = 0 self.right_grasps = 0 self._object_stats = ObjectStats() self._object_timeline = object_timeline self._raw_first_time = None for obj in objects.OBJECTS: self._object_stats.add(obj, 'grasp_count', 0)
class CameraMovementTime(object): def __init__(self, object_timeline): self._previous_message = None self._previous_time = None self._object_stats = ObjectStats() self._object_timeline = object_timeline self._raw_first_time = None for obj in objects.OBJECTS: self._object_stats.add(obj, 'camera_movement_time', 0) self._timeline = [] def update(self, topic, message, time): time = time.to_sec() if self._raw_first_time is None: self._raw_first_time = time if topic != topics.CAMERA_POSE: return # Camera movement is updated continuously, so we just count up the time # between changes in camera position. obj = self._object_timeline.object_at(time - self._raw_first_time) if self._previous_message is not None and message != self._previous_message: duration = time - self._previous_time self._object_stats.add(obj, 'camera_movement_time', duration) self._object_stats.add('all', 'camera_movement_time', duration) self._timeline.append((time - self._raw_first_time, duration, 'camera')) self._previous_message = message self._previous_time = time def object_stats(self): return self._object_stats def timeline(self): return self._timeline
class GraspCount(object): def __init__(self, object_timeline): self._is_left_closed = True self._is_right_closed = True self.left_grasps = 0 self.right_grasps = 0 self._object_stats = ObjectStats() self._object_timeline = object_timeline self._raw_first_time = None for obj in objects.OBJECTS: self._object_stats.add(obj, 'grasp_count', 0) def update(self, topic, message, time): time = time.to_sec() if self._raw_first_time is None: self._raw_first_time = time obj = None if topic == topics.LEFT_GRASP or topic == topics.RIGHT_GRASP: obj = self._object_timeline.object_at(time - self._raw_first_time) if topic == topics.LEFT_GRASP: if message.position == 0: if not self._is_left_closed: self._object_stats.add(obj, 'grasp_count', 1) self._object_stats.add('all', 'grasp_count', 1) self._is_left_closed = True else: self._is_left_closed = False elif topic == topics.RIGHT_GRASP: if message.position == 0: if not self._is_right_closed: self._object_stats.add(obj, 'grasp_count', 1) self._object_stats.add('all', 'grasp_count', 1) self._is_right_closed = True else: self._is_right_closed = False def object_stats(self): return self._object_stats
def __init__(self, object_timeline): self._first_action = None self._first_time = None self._first_messages = {} self._raw_first_time = None self._last_action = None self._last_time = None self._last_messages = {} self._raw_last_time = None self._object_stats = ObjectStats() self._object_timeline = object_timeline self._compute_object_stats() self._timeline = []
def __init__(self, object_timeline): self._left_time = ObjectStats() self._right_time = ObjectStats() self._other_time = ObjectStats() self._squared_left = ObjectStats() for obj in objects.OBJECTS: self._squared_left.add(obj, 'squared_left', 0) self._squared_right = ObjectStats() for obj in objects.OBJECTS: self._squared_right.add(obj, 'squared_right', 0) self._num_left_looks = ObjectStats() self._num_right_looks = ObjectStats() self._state = 'other' self._prev_time = None self._timeline = [] self._object_timeline = object_timeline self._raw_first_time = None
def process_experiment((path, object_timeline)): """Extract features of the bag file.""" print('Processing', path) bag = open_bag(path) if bag is None: return None object_stats = ObjectStats() time_taken_processor = processors.TimeTaken(object_timeline) camera_movement_processor = processors.CameraMovementTime(object_timeline) marker_movement_processor = processors.MarkerMovementTime(object_timeline) grasp_count_processor = processors.GraspCount(object_timeline) for topic, message, time in bag.read_messages(topics=EXPERIMENT_TOPICS): model = message_factory.model(message) if model is None: continue time_taken_processor.update(topic, model, time) camera_movement_processor.update(topic, model, time) marker_movement_processor.update(topic, model, time) grasp_count_processor.update(topic, model, time) bag.close() time_taken_processor.update_last() object_stats.update(time_taken_processor.object_stats()) object_stats.update(camera_movement_processor.object_stats()) object_stats.update(marker_movement_processor.object_stats()) object_stats.update(grasp_count_processor.object_stats()) for obj, stats in object_stats.items(): stats['other_time'] = ( stats['time_taken'] - stats['camera_movement_time'] - stats['marker_movement_time'] ) timeline = build_timeline( marker_movement_processor.timeline(), camera_movement_processor.timeline()) return object_stats, timeline
class MarkerMovementTime(object): def __init__(self, object_timeline): self._pose_update_start = None self._pose_update_end = None self._object_stats = ObjectStats() self._object_timeline = object_timeline self._raw_first_time = None for obj in objects.OBJECTS: self._object_stats.add(obj, 'marker_movement_time', 0) self._timeline = [] def update(self, topic, message, time): time = time.to_sec() if self._raw_first_time is None: self._raw_first_time = time # The feedback topic is not updated continuously, so we look only at the # amount of time POSE_UPDATE events are published. if (topic != topics.MARKER_FEEDBACK): return if message.event_type == 1: if self._pose_update_start is None: self._pose_update_start = time self._pose_update_end = time else: if ( self._pose_update_end is not None and self._pose_update_start is not None ): obj = self._object_timeline.object_at(time - self._raw_first_time) duration = self._pose_update_end - self._pose_update_start self._object_stats.add(obj, 'marker_movement_time', duration) self._object_stats.add('all', 'marker_movement_time', duration) self._timeline.append((time - self._raw_first_time, duration, 'marker')) self._pose_update_start = None self._pose_update_end = None def object_stats(self): return self._object_stats def timeline(self): return self._timeline
class TimeTaken(object): def __init__(self, object_timeline): self._first_action = None self._first_time = None self._first_messages = {} self._raw_first_time = None self._last_action = None self._last_time = None self._last_messages = {} self._raw_last_time = None self._object_stats = ObjectStats() self._object_timeline = object_timeline self._compute_object_stats() self._timeline = [] def _compute_object_stats(self): for obj in objects.OBJECTS: self._object_stats.add(obj, 'time_taken', 0) for event in self._object_timeline._timeline: duration = event.end_time - event.start_time self._object_stats.add(event.obj, 'time_taken', duration) def update(self, topic, message, time): time = time.to_sec() # The first message which is different from its predecessor on the same # topic is considered the first action. if self._first_action is None: if topic in self._first_messages: if self._first_messages[topic] != message: self._first_action = message self._first_time = time else: self._first_messages[topic] = message # The first message which is the same as all its successors on the same # topic is considered the last action on that topic. We keep track of the # last action across topics. if topic in self._last_messages: if self._last_messages[topic] != message: self._last_messages[topic] = message if self._last_time is None or time > self._last_time: self._last_action = message self._last_time = time else: self._last_messages[topic] = message # Keep track of absolute first and last message. if self._raw_first_time is None: self._raw_first_time = time self._raw_last_time = time def update_last(self): first_obj = self._object_timeline.object_at(self._first_time - self._raw_first_time) leading_time = self._first_time - self._raw_first_time self._object_stats.add(first_obj, 'time_taken', -leading_time) last_obj = self._object_timeline.object_at(self._last_time - self._raw_first_time) trailing_time = self._last_time - self._raw_last_time self._object_stats.add(last_obj, 'time_taken', -trailing_time) self._object_stats.add('all', 'time_taken', self._last_time - self._first_time) def object_stats(self): return self._object_stats
def object_stats(self): object_stats = ObjectStats() object_stats.update(self._left_time) object_stats.update(self._num_left_looks) object_stats.update(self._right_time) object_stats.update(self._num_right_looks) init_features = [ 'num_left_looks', 'left_time', 'mean_left', 'left_stddev', 'num_right_looks', 'right_time', 'mean_right', 'right_stddev' ] for obj in objects.OBJECTS: for feature in init_features: object_stats.add(obj, feature, 0) for obj, stats in object_stats.items(): num_left_looks = stats['num_left_looks'] left_time = stats['left_time'] mean_left = left_time / num_left_looks if num_left_looks != 0 else 0 stats['mean_left'] = mean_left squared_left = self._squared_left.get_stats(obj)['squared_left'] squared_mean = mean_left * mean_left stddev = ( squared_left / num_left_looks - squared_mean if num_left_looks != 0 else 0 ) stats['left_stddev'] = stddev num_right_looks = stats['num_right_looks'] right_time = stats['right_time'] mean_right = right_time / num_right_looks if num_right_looks != 0 else 0 stats['mean_right'] = mean_right squared_right = self._squared_right.get_stats(obj)['squared_right'] squared_mean = mean_right * mean_right stddev = ( squared_right / num_right_looks - squared_mean if num_right_looks != 0 else 0 ) stats['right_stddev'] = stddev return object_stats
class Code(object): def __init__(self, object_timeline): self._left_time = ObjectStats() self._right_time = ObjectStats() self._other_time = ObjectStats() self._squared_left = ObjectStats() for obj in objects.OBJECTS: self._squared_left.add(obj, 'squared_left', 0) self._squared_right = ObjectStats() for obj in objects.OBJECTS: self._squared_right.add(obj, 'squared_right', 0) self._num_left_looks = ObjectStats() self._num_right_looks = ObjectStats() self._state = 'other' self._prev_time = None self._timeline = [] self._object_timeline = object_timeline self._raw_first_time = None def update(self, topic, message, time): time = time.to_sec() if self._raw_first_time is None: self._raw_first_time = time if topic != topics.CODING: return if self._prev_time is not None and message.data != self._state: obj = self._object_timeline.object_at(time - self._raw_first_time) delta = time - self._prev_time self._timeline.append((delta, self._state)) if self._state == 'left': self._left_time.add(obj, 'left_time', delta) self._squared_left.add(obj, 'squared_left', delta*delta) self._num_left_looks.add(obj, 'num_left_looks', 1) self._left_time.add('all', 'left_time', delta) self._squared_left.add('all', 'squared_left', delta*delta) self._num_left_looks.add('all', 'num_left_looks', 1) elif self._state == 'right': self._right_time.add(obj, 'right_time', delta) self._squared_right.add(obj, 'squared_right', delta*delta) self._num_right_looks.add(obj, 'num_right_looks', 1) self._right_time.add('all', 'right_time', delta) self._squared_right.add('all', 'squared_right', delta*delta) self._num_right_looks.add('all', 'num_right_looks', 1) else: self._other_time.add(obj, 'other_time', delta) self._other_time.add('all', 'other_time', delta) self._state = message.data self._prev_time = time def object_stats(self): object_stats = ObjectStats() object_stats.update(self._left_time) object_stats.update(self._num_left_looks) object_stats.update(self._right_time) object_stats.update(self._num_right_looks) init_features = [ 'num_left_looks', 'left_time', 'mean_left', 'left_stddev', 'num_right_looks', 'right_time', 'mean_right', 'right_stddev' ] for obj in objects.OBJECTS: for feature in init_features: object_stats.add(obj, feature, 0) for obj, stats in object_stats.items(): num_left_looks = stats['num_left_looks'] left_time = stats['left_time'] mean_left = left_time / num_left_looks if num_left_looks != 0 else 0 stats['mean_left'] = mean_left squared_left = self._squared_left.get_stats(obj)['squared_left'] squared_mean = mean_left * mean_left stddev = ( squared_left / num_left_looks - squared_mean if num_left_looks != 0 else 0 ) stats['left_stddev'] = stddev num_right_looks = stats['num_right_looks'] right_time = stats['right_time'] mean_right = right_time / num_right_looks if num_right_looks != 0 else 0 stats['mean_right'] = mean_right squared_right = self._squared_right.get_stats(obj)['squared_right'] squared_mean = mean_right * mean_right stddev = ( squared_right / num_right_looks - squared_mean if num_right_looks != 0 else 0 ) stats['right_stddev'] = stddev return object_stats def timeline(self): return self._timeline