def _fill_with_empties(self, timestamp): timestamps = sorted(self.detections.keys()) min_timestamp = timestamps[0] max_timestamp = timestamps[-1] # if there are timestamps smaller than the inserted one, insert empty detections at the # timestamps previous to the inserted timestamp until already existing timestamps are reached if timestamp > min_timestamp: previous = timestamp.get_previous() while not previous in self.detections: empty_detection = ds.EmptyDetection(previous) self.detections[previous] = empty_detection empty_detection.path = self previous = previous.get_previous() # if there are timestamps bigger than the inserted one, insert empty detections at the # timestamps next to the inserted timestamp until already existing timestamps are reached if timestamp < max_timestamp: next = timestamp.get_next() while not next in self.detections: empty_detection = ds.EmptyDetection(next) self.detections[next] = empty_detection empty_detection.path = self next = next.get_next()
def process_timestamp(self, timestamp, database_connection): dset = self.dset_store.get(timestamp, database_connection) # set claims on best matches self.claim_manager.clear() for path in self.path_manager.open_paths: mset = scoring.xgboost_learning(path, dset) for m in mset.matches: self.claim_manager.add_claim(ds.MatchClaim(m[0], m[1], path)) self.claim_manager.sort_claims() # allocate claims self.claim_manager.allocate_claims_greedy(timestamp, self.path_manager) self.claim_manager.clear() # set unsuccessful paths pending for path in self.path_manager.open_paths: if not path.has_match_at_timestamp(timestamp): path.add_match(ds.Match(ds.EmptyDetection(timestamp))) if closing.hard_closing(path): self.path_manager.close_path(path) # open new path for every detection not already used in any path for d in dset.detections: if not d.taken: new_path = ds.Path(ds.Match(d)) self.path_manager.appendPath(new_path) d.take()
def remove_detection(self, detection): timestamp = detection.timestamp # remove detection self.detections.pop(timestamp, None) detection.path = None # replace with empty detection empty_detection = ds.EmptyDetection(timestamp) self.detections[timestamp] = empty_detection empty_detection.path = self # remove unnecessary empty detections self._remove_empties(timestamp)
def process_timestamp(self, timestamp, database_connection): if len(self.path_manager.open_paths) > 0: # build or expand graph self.graph.build(timestamp, database_connection) # traverse graph, build hypothesis self.graph.traverse(timestamp, self.hypothesis_manager, self.dset_store, database_connection) # for every open path set claims on best connections to hypothesis for path in self.path_manager.open_paths: self.hypothesis_manager.build_connection_claims( path, self.claim_manager, self.dset_store, database_connection) # allocate claims self.claim_manager.sort_claims() self.claim_manager.allocate_claims_greedy() self.graph.remove_timestamp( timestamp, database_connection ) # remove all data from graph for this timestamp self.hypothesis_manager.clear() self.claim_manager.clear() # set unsuccessful paths pending for path in self.path_manager.open_paths: if not path.has_detection_at_timestamp(timestamp): path.add_detection(ds.EmptyDetection(timestamp)) if closing.hard_closing(path): self.path_manager.close_path(path) # open new path for every detection not already used in any path dset = self.dset_store.get(timestamp, database_connection) for d in dset.detections: if not d.taken: new_path = ds.Path(d) self.path_manager.appendPath(new_path) d.take()
def on_mouse_move( self, event=None ): if (event is not None) \ and (self.path_view_scroll_origin is not None) \ and (event.buttons() == QtCore.Qt.MiddleButton): offset = self.path_view_scroll_origin - event.pos() self.path_view_scroll_origin = event.pos() self.path_view.verticalScrollBar().setValue(self.path_view.verticalScrollBar().value() + offset.y()) self.path_view.horizontalScrollBar().setValue(self.path_view.horizontalScrollBar().value() + offset.x()) return if not self.editing_active: return # Check if modifier key for new detection is active. modifiers = QtGui.QApplication.keyboardModifiers() insert_new_detection_mode = (modifiers & QtCore.Qt.AltModifier) == QtCore.Qt.AltModifier # Check if modifier key for tracking stationary bees is active. stationary_bee_mode = (modifiers & QtCore.Qt.ControlModifier) == QtCore.Qt.ControlModifier detection_search_distance = 60 if not stationary_bee_mode else 15 path = self.current_paths[ 0 ] timestamp = self.current_timestamp mouse_pos_widget = self.path_view.mapFromGlobal( QtGui.QCursor.pos() ) widget_x = mouse_pos_widget.x() widget_y = mouse_pos_widget.y() # mouse has to hover over the viewport widget if ( widget_x < 0 or widget_x > self.path_view.width() or widget_y < 0 or widget_y > self.path_view.height() ): return mouse_pos_scene = self.path_view.mapToScene( mouse_pos_widget ) mouse_pos = np.array( [ mouse_pos_scene.x(), mouse_pos_scene.y() ] ) # get nearest detection within a limit nearest = None if not insert_new_detection_mode: nearest = self.get_nearest_detection( timestamp, mouse_pos.reshape(1, 2), limit = detection_search_distance, ignore_empty = stationary_bee_mode ) if ( nearest is not None # there is a detection nearby and nearest.path is None # it's not already assigned ): # assign the new found detection to our path path.add_and_overwrite_detection( nearest ) self.build_path_details( self.current_paths ) # We found something but it's already in our path? Then, don't insert empty detection. elif ( nearest is not None and nearest.path == path ): pass # else insert empty detection with position information # if mouse position is inside camera image dimensions elif ( (insert_new_detection_mode or stationary_bee_mode) and mouse_pos[ 0 ] >= 0 and mouse_pos[ 0 ] <= 4000 and mouse_pos[ 1 ] >= 0 and mouse_pos[ 1 ] <= 3000 ): # already has detection at this timestamp if timestamp in path.detections: detection = path.detections[ timestamp ] # if the already present detection is one from the decoder data we have to # replace it with an empty one before we can set the position from the mouse # otherwise the present detection will get its position updated if not detection.is_empty(): detection = ds.EmptyDetection( timestamp ) path.add_and_overwrite_detection( detection ) # no detection at this timestamp, insert new empty one else: detection = ds.EmptyDetection( timestamp ) path.add_detection( detection ) detection.position = mouse_pos # set position self.build_path_details( self.current_paths )
def load_tracks(self): if self.dset_store is None: print 'Error: no data folder loaded' return self.block_inputs(True) self.dset_store.delete_path_associations() self.path_manager = ds.PathManager(config.PATHS_FILE) if os.path.isfile(config.PATHS_FILE): try: with open(config.PATHS_FILE, 'rb') as paths_file: input = pickle.load(paths_file) if self.dset_store.source != input['source']: print 'Warning: data source for detections and paths do not match' paths_input = input['paths'] self.paths_load_progress.setMaximum(len(paths_input)) self.app.processEvents() for i, tag_id in enumerate(paths_input.keys()): self.path_manager.paths[tag_id] = {} for path_id in paths_input[tag_id].keys(): path = ds.Path(tag_id) self.path_manager.paths[tag_id][path_id] = path for frame, detection_data in paths_input[tag_id][ path_id].items(): timestamp = self.dset_store.get_timestamp(frame) if timestamp is not None: detection_id, pos_x, pos_y, readability = detection_data # data point is associated with a detection from the pipeline output if detection_id is not None: dset = self.dset_store.get(timestamp) if detection_id in dset.detections: detection = dset.detections[ detection_id] else: print 'Warning: detection_id not found, your truth file does not match your pipeline data. Please rematch!' continue # if two paths claim the same detection only the first one gets it if detection.path is None: detection.readability = readability path.add_detection(detection) # insert empty detection for every following path else: detection = ds.EmptyDetection( timestamp) detection.position = np.array( [pos_x, pos_y]) detection.readability = readability path.add_detection(detection) # data point is an empty detection else: detection = ds.EmptyDetection(timestamp) detection.position = np.array( [pos_x, pos_y]) detection.readability = readability path.add_detection(detection) self.paths_load_progress.setValue(i + 1) self.app.processEvents() self.paths_load_label.setText( str(len(paths_input)) + ' paths loaded') self.app.processEvents() except: pass else: self.paths_load_progress.setMaximum(1) self.paths_load_progress.setValue(1) self.paths_load_label.setText('will write to new file') self.app.processEvents() self.block_inputs(False)