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)
Example #2
0
 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 = []
Example #3
0
 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 = []
Example #4
0
 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)
Example #5
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
Example #6
0
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
Example #7
0
 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 = []
Example #8
0
 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
Example #10
0
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
Example #11
0
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
Example #12
0
  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
Example #13
0
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