示例#1
0
    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()
示例#3
0
    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)
示例#4
0
    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()
示例#5
0
	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 )
示例#6
0
    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)