Module pept.tracking.trajectory_separation
Source code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File : __init__.py
# License: License: GNU v3.0
# Author : Andrei Leonard Nicusan <a.l.nicusan@bham.ac.uk>
# Date : 22.08.2019
from .trajectory_separation import TrajectorySeparation
__all__ = [
"TrajectorySeparation"
]
__author__ = "Andrei Leonard Nicusan"
__credits__ = ["Andrei Leonard Nicusan", "Kit Windows-Yule", "Sam Manger"]
__license__ = "GNU v3.0"
__version__ = "0.1"
__maintainer__ = "Andrei Leonard Nicusan"
__email__ = "a.l.nicusan@bham.ac.uk"
__status__ = "Development"
Sub-modules
pept.tracking.trajectory_separation.trajectory_separation
-
The peptml module implements a hierarchical density-based clustering algorithm for general Positron Emission Particle Tracking (PEPT) …
Classes
class TrajectorySeparation (centres, points_to_check=25, max_distance=20, max_cluster_size_diff=500, points_cluster_size=50)
-
Source code
class TrajectorySeparation: def __init__(self, centres, points_to_check = 25, max_distance = 20, max_cluster_size_diff = 500, points_cluster_size = 50): # centres row: [time, x, y, z, clusterSize] # Make sure the trajectory is memory-contiguous for efficient # KDTree partitioning self.centres = np.ascontiguousarray(centres) self.points_to_check = points_to_check self.max_distance = max_distance self.max_cluster_size_diff = max_cluster_size_diff self.points_cluster_size = points_cluster_size # For every point in centres, save a set of the trajectory # indices of the trajectories that they are part of # eg. centres[2] is part of trajectories 0 and 1 => # trajectory_indices[2] = {0, 1} # Initialise a vector of empty sets of size len(centres) self.trajectory_indices = np.array([ set() for i in range(len(self.centres)) ]) # For every trajectory found, save a list of the indices of # the centres that are part of that trajectory # eg. trajectory 1 is comprised of centres 3, 5 and 8 => # centresIndices[1] = [3, 5, 8] self.centres_indices = [[]] # Maximum trajectory index self.max_index = 0 def find_trajectories(self): for i, current_point in enumerate(self.centres): if i == 0: # Add the first point to trajectory 0 self.trajectory_indices[0].add(self.max_index) self.centres_indices[self.max_index].append(0) self.max_index += 1 continue # Search for the closest previous pointsToCheck points # within a given maxDistance start_index = i - self.points_to_check end_index = i if start_index < 0: start_index = 0 # Construct a KDTree from the x, y, z (1:4) of the # selected points. Get the indices for all the points within # maxDistance of the currentPoint tree = cKDTree(self.centres[start_index:end_index, 1:4]) closest_indices = tree.query_ball_point(current_point[1:4], self.max_distance, n_jobs = -1) closest_indices = np.array(closest_indices) + start_index # If no point was found, it is a new trajectory. Continue if len(closest_indices) == 0: self.trajectory_indices[i].add(self.max_index) self.centres_indices.append([i]) self.max_index += 1 continue # For every close point found, search for all the trajectory indices # - If all trajectory indices sets are equal and of a single value # then currentPoint is part of the same trajectory # - If all trajectory indices sets are equal, but of more values, # then currentPoint diverged from an intersection of trajectories # and is part of a single trajectory => separate it # # - If every pair of trajectory indices sets is not disjoint, then # currentPoint is only one of them # - If there exists a pair of trajectory indices sets that is # disjoint, then currentPoint is part of all of them # Select the trajectories of all the points that were found # to be the closest closest_trajectories = self.trajectory_indices[closest_indices] #print("closestTrajectories:") #print(closestTrajectories) # If all the closest points are part of the same trajectory # (just one!), then the currentPoint is part of it too if (np.all(closest_trajectories == closest_trajectories[0]) and len(closest_trajectories[0]) == 1): self.trajectory_indices[i] = closest_trajectories[0] self.centres_indices[ next(iter(closest_trajectories[0])) ].append(i) continue # Otherwise, check the points based on their cluster size else: # Create a list of all the trajectories that were found to # intersect #print('\nIntersection:') closest_traj_indices = list( set().union(*closest_trajectories) ) #print("ClosestTrajIndices:") #print(closestTrajIndices) # For each close trajectory, calculate the mean cluster size # of the last points_cluster_size points # Keep track of the mean cluster size that is the closest to # the currentPoint's clusterSize current_cluster_size = current_point[4] #print("currentClusterSize = {}".format(currentClusterSize)) closest_traj_index = -1 cluster_size_diff = self.max_cluster_diff for traj_index in closest_traj_indices: #print("trajIndex = {}".format(trajIndex)) traj_centres = self.centres[ self.centres_indices[traj_index] ] #print("trajCentres:") #print(trajCentres) mean_cluster_size = traj_centres[-self.points_cluster_size:][:, 4].mean() #print("meanClusterSize = {}".format(meanClusterSize)) #print("clusterSizeDiff = {}".format(clusterSizeDiff)) #print("abs diff = {}".format(np.abs( currentClusterSize - meanClusterSize ))) if np.abs( current_cluster_size - mean_cluster_size ) < cluster_size_diff: closest_traj_index = traj_index cluster_size_diff = np.abs( current_cluster_size - mean_cluster_size ) if closest_traj_index == -1: #self.trajectoryIndices[i] = set(closestTrajIndices) #for trajIndex in closestTrajIndices: # self.centresIndices[trajIndex].append(i) print("\n**** -1 ****\n") break else: #print("ClosestTrajIndex found = {}".format(closestTrajIndex)) self.trajectory_indices[i] = set([closest_traj_index]) self.centres_indices[closest_traj_index].append(i) individual_trajectories = [] for traj_centres in self.centres_indices: individual_traj = pept.PointData(self.centres[traj_centres], sample_size = 0, overlap = 0, verbose = False) individual_trajectories.append(individual_traj) return individual_trajectories ''' # If the current point is not part of any trajectory, assign it # the maxIndex and increment it if len(self.trajectoryIndices[i]) == 0: self.trajectoryIndices[i].append(self.maxIndex) self.maxIndex += 1 print(self.trajectoryIndices[i]) print(self.maxIndex) # Construct a KDTree from the numberOfPoints in front of # the current point tree = cKDTree(self.trajectory[(i + 1):(i + self.numberOfPoints + 2)][1:4]) # For every trajectory that the current point is part of, # find the closest points in front of it numberOfIntersections = len(self.trajectoryIndices[i]) dist, nextPointsIndices = tree.query(currentPoint, k=numberOfIntersections, distance_upper_bound=self.maxDistance, n_jobs=-1) print(nextPointsIndices) # If the current point is part of more trajectories, # an intersection happened. Call subroutine to part # the trajectories if numberOfIntersections > 1: for j in range(0, len(self.trajectoryIndices[i])): trajIndex = self.trajectoryIndices[i][j] self.trajectoryIndices[i + 1 + nextPointsIndices[j]].append(trajIndex) else: self.trajectoryIndices[i + 1 + nextPointsIndices].append(self.trajectoryIndices[i][0]) print(self.trajectoryIndices) ''' def getTrajectories(self): self.individualTrajectories = [] for trajCentres in self.centresIndices: self.individualTrajectories.append(self.centres[trajCentres]) self.individualTrajectories = np.array(self.individualTrajectories) return self.individualTrajectories ''' self.individualTrajectories = [ [] for i in range(0, self.maxIndex + 1) ] for i in range(0, len(self.trajectoryIndices)): for trajIndex in self.trajectoryIndices[i]: self.individualTrajectories[trajIndex].append(self.centres[i]) self.individualTrajectories = np.array(self.individualTrajectories) for i in range(len(self.individualTrajectories)): if len(self.individualTrajectories[i]) > 0: self.individualTrajectories[i] = np.vstack(self.individualTrajectories[i]) return self.individualTrajectories ''' def plotTrajectoriesAltAxes(self, ax): trajectories = self.getTrajectories() for traj in trajectories: if len(traj) > 0: ax.scatter(traj[:, 3], traj[:, 1], traj[:, 2], marker='D', s=10)
Methods
def find_trajectories(self)
-
Source code
def find_trajectories(self): for i, current_point in enumerate(self.centres): if i == 0: # Add the first point to trajectory 0 self.trajectory_indices[0].add(self.max_index) self.centres_indices[self.max_index].append(0) self.max_index += 1 continue # Search for the closest previous pointsToCheck points # within a given maxDistance start_index = i - self.points_to_check end_index = i if start_index < 0: start_index = 0 # Construct a KDTree from the x, y, z (1:4) of the # selected points. Get the indices for all the points within # maxDistance of the currentPoint tree = cKDTree(self.centres[start_index:end_index, 1:4]) closest_indices = tree.query_ball_point(current_point[1:4], self.max_distance, n_jobs = -1) closest_indices = np.array(closest_indices) + start_index # If no point was found, it is a new trajectory. Continue if len(closest_indices) == 0: self.trajectory_indices[i].add(self.max_index) self.centres_indices.append([i]) self.max_index += 1 continue # For every close point found, search for all the trajectory indices # - If all trajectory indices sets are equal and of a single value # then currentPoint is part of the same trajectory # - If all trajectory indices sets are equal, but of more values, # then currentPoint diverged from an intersection of trajectories # and is part of a single trajectory => separate it # # - If every pair of trajectory indices sets is not disjoint, then # currentPoint is only one of them # - If there exists a pair of trajectory indices sets that is # disjoint, then currentPoint is part of all of them # Select the trajectories of all the points that were found # to be the closest closest_trajectories = self.trajectory_indices[closest_indices] #print("closestTrajectories:") #print(closestTrajectories) # If all the closest points are part of the same trajectory # (just one!), then the currentPoint is part of it too if (np.all(closest_trajectories == closest_trajectories[0]) and len(closest_trajectories[0]) == 1): self.trajectory_indices[i] = closest_trajectories[0] self.centres_indices[ next(iter(closest_trajectories[0])) ].append(i) continue # Otherwise, check the points based on their cluster size else: # Create a list of all the trajectories that were found to # intersect #print('\nIntersection:') closest_traj_indices = list( set().union(*closest_trajectories) ) #print("ClosestTrajIndices:") #print(closestTrajIndices) # For each close trajectory, calculate the mean cluster size # of the last points_cluster_size points # Keep track of the mean cluster size that is the closest to # the currentPoint's clusterSize current_cluster_size = current_point[4] #print("currentClusterSize = {}".format(currentClusterSize)) closest_traj_index = -1 cluster_size_diff = self.max_cluster_diff for traj_index in closest_traj_indices: #print("trajIndex = {}".format(trajIndex)) traj_centres = self.centres[ self.centres_indices[traj_index] ] #print("trajCentres:") #print(trajCentres) mean_cluster_size = traj_centres[-self.points_cluster_size:][:, 4].mean() #print("meanClusterSize = {}".format(meanClusterSize)) #print("clusterSizeDiff = {}".format(clusterSizeDiff)) #print("abs diff = {}".format(np.abs( currentClusterSize - meanClusterSize ))) if np.abs( current_cluster_size - mean_cluster_size ) < cluster_size_diff: closest_traj_index = traj_index cluster_size_diff = np.abs( current_cluster_size - mean_cluster_size ) if closest_traj_index == -1: #self.trajectoryIndices[i] = set(closestTrajIndices) #for trajIndex in closestTrajIndices: # self.centresIndices[trajIndex].append(i) print("\n**** -1 ****\n") break else: #print("ClosestTrajIndex found = {}".format(closestTrajIndex)) self.trajectory_indices[i] = set([closest_traj_index]) self.centres_indices[closest_traj_index].append(i) individual_trajectories = [] for traj_centres in self.centres_indices: individual_traj = pept.PointData(self.centres[traj_centres], sample_size = 0, overlap = 0, verbose = False) individual_trajectories.append(individual_traj) return individual_trajectories ''' # If the current point is not part of any trajectory, assign it # the maxIndex and increment it if len(self.trajectoryIndices[i]) == 0: self.trajectoryIndices[i].append(self.maxIndex) self.maxIndex += 1 print(self.trajectoryIndices[i]) print(self.maxIndex) # Construct a KDTree from the numberOfPoints in front of # the current point tree = cKDTree(self.trajectory[(i + 1):(i + self.numberOfPoints + 2)][1:4]) # For every trajectory that the current point is part of, # find the closest points in front of it numberOfIntersections = len(self.trajectoryIndices[i]) dist, nextPointsIndices = tree.query(currentPoint, k=numberOfIntersections, distance_upper_bound=self.maxDistance, n_jobs=-1) print(nextPointsIndices) # If the current point is part of more trajectories, # an intersection happened. Call subroutine to part # the trajectories if numberOfIntersections > 1: for j in range(0, len(self.trajectoryIndices[i])): trajIndex = self.trajectoryIndices[i][j] self.trajectoryIndices[i + 1 + nextPointsIndices[j]].append(trajIndex) else: self.trajectoryIndices[i + 1 + nextPointsIndices].append(self.trajectoryIndices[i][0]) print(self.trajectoryIndices) '''
def getTrajectories(self)
-
Source code
def getTrajectories(self): self.individualTrajectories = [] for trajCentres in self.centresIndices: self.individualTrajectories.append(self.centres[trajCentres]) self.individualTrajectories = np.array(self.individualTrajectories) return self.individualTrajectories ''' self.individualTrajectories = [ [] for i in range(0, self.maxIndex + 1) ] for i in range(0, len(self.trajectoryIndices)): for trajIndex in self.trajectoryIndices[i]: self.individualTrajectories[trajIndex].append(self.centres[i]) self.individualTrajectories = np.array(self.individualTrajectories) for i in range(len(self.individualTrajectories)): if len(self.individualTrajectories[i]) > 0: self.individualTrajectories[i] = np.vstack(self.individualTrajectories[i]) return self.individualTrajectories '''
def plotTrajectoriesAltAxes(self, ax)
-
Source code
def plotTrajectoriesAltAxes(self, ax): trajectories = self.getTrajectories() for traj in trajectories: if len(traj) > 0: ax.scatter(traj[:, 3], traj[:, 1], traj[:, 2], marker='D', s=10)