def calculatePositions(tree, branchIDToFiloTypeMap=None, filoDist=10, branchDrawnLeft=None): if branchDrawnLeft is None: branchDrawnLeft = {} # No directions stored yet. # First calculate branch types if it hasn't been done yet: if branchIDToFiloTypeMap is None: ftArray, _, _, _, _, _ = addedSubtractedTransitioned([tree], filoDist=filoDist) filoTypes = ftArray[0] branchIDList = util.sortedBranchIDList([tree]) branchIDToFiloTypeMap = {} for i in range(len(branchIDList)): branchIDToFiloTypeMap[branchIDList[i]] = filoTypes[i] # Next, simplify into a mapping of whether each branch is a filo (horizontal) or not (vertical) branchIsFiloMap = {} for id, filoType in branchIDToFiloTypeMap.items(): branchIsFiloMap[id] = (filoType == FiloType.INTERSTITIAL or filoType == FiloType.TERMINAL) # Finally, calculate both X and Y positions pointX = _calculatePointX(tree, branchIsFiloMap, branchDrawnLeft, filoDist) pointY = _calculatePointY(tree, branchIsFiloMap) return pointX, pointY
def __init__(self, parent, selectedTree, treeModels, is2D, filePaths, opt, sizeFactor=10, *args, **kwargs): self.firstTree = max(0, min(selectedTree - 1, len(treeModels) - MAX_TREE_COUNT)) self.treeModels = treeModels self.filePaths = filePaths self.options = opt self.dendrogram = is2D np.set_printoptions(precision=3) self.branchIDList = util.sortedBranchIDList(self.treeModels) self.filoTypes, self.added, self.subtracted, self.transitioned, _, _ = addedSubtractedTransitioned( self.treeModels, excludeAxon=opt.excludeAxon, excludeBasal=opt.excludeBasal, terminalDist=opt.terminalDist, filoDist=opt.filoDist ) mot, self.filoLengths = motility( self.treeModels, excludeAxon=opt.excludeAxon, excludeBasal=opt.excludeBasal, includeAS=opt.includeAS, terminalDist=opt.terminalDist, filoDist=opt.filoDist ) np.set_printoptions() self.motility = mot['raw'] self.sizeFactor = sizeFactor self.dendrogramX, self.dendrogramY = calculateAllPositions( self.treeModels, self.filoTypes, self.branchIDList, filoDist=opt.filoDist ) nPlots = min(len(treeModels), MAX_TREE_COUNT) super(Motility3DCanvas, self).__init__(*args, in3D=(not self.dendrogram), subplots=nPlots, **kwargs) self.fig.canvas.mpl_connect('motion_notify_event', self.handleMove) self.fig.subplots_adjust(top=0.95, bottom=0.05, right=0.95, left=0.05, wspace=0.05, hspace=0.05)
def runFiloTipCluster(path): fullState = files.loadState(usePathOrPick(path)) # Process each tree in order: for treeIdx, tree in enumerate(fullState.trees): branchIDList = util.sortedBranchIDList([tree]) # Find the types of each branch: filoTypes, _, _, _, _, _ = addedSubtractedTransitioned([tree]) # Keep only interstitial filo... interstitialFiloIDs = [] for branchID, filoType in zip(branchIDList, filoTypes[0]): if filoType == FiloType.INTERSTITIAL: interstitialFiloIDs.append(branchID) print("%d Interstitial Filos detected" % (len(interstitialFiloIDs))) # and map to the points at their tip: tipPoints = [] for branch in tree.branches: if branch.id in interstitialFiloIDs: if len(branch.points) > 0: tipPoints.append(branch.points[-1]) fig = plt.figure() fig.suptitle("Interstitial Filo Tip clustering for [%d]" % (treeIdx + 1)) fig.subplots_adjust(left=0.02, bottom=0.07, right=0.98, top=0.9, wspace=0.05, hspace=0.2) # 3D plot showing where the filo tips are on the branches. ax3D = fig.add_subplot(121, projection='3d') ax3D.set_title("3D positions") for branch in tree.branches: if branch.parentPoint is not None: points = [branch.parentPoint] + branch.points ax3D.plot(*tree.worldCoordPoints(points), c=(0.5, 0.5, 0.5, 0.1)) ax3D.scatter(*tree.worldCoordPoints(tipPoints)) # 2D plot comparing spatial distance to tree distance sDs, tDs = [], [] ax2D = fig.add_subplot(122) ax2D.set_title("Spatial distance vs Tree Distance") ax2D.set_xlabel("Spatial Distance (uM)") ax2D.set_ylabel("Tree Distance (uM)") for i, p1 in enumerate(tipPoints): for p2 in tipPoints[i + 1:]: spatialDist, treeDist = tree.spatialAndTreeDist(p1, p2) sDs.append(spatialDist) tDs.append(treeDist) if len(sDs) > 0 and len(tDs) > 0: ax2D.scatter(sDs, tDs) ax2D.plot([0, np.max(sDs)], [0, np.max(sDs)], '--', c=(0.5, 0.5, 0.5, 0.7)) plt.show()
def testImportNoChange(path='data/localFirst.dyn.gz'): print("Testing no motility changes after nodes copied...") fullState = files.loadState(path) assert len(fullState.trees) == 1 treeA = fullState.trees[0] # NOTE: old trees sometimes have empty branches: emptyBranches = [b for b in treeA.branches if len(b.points) == 0] for emptyBranch in emptyBranches: treeA.removeBranch(emptyBranch) treeB = Tree() treeB.clearAndCopyFrom(treeA, fullState) treeB._parentState = treeA._parentState # Copy branch and point IDs: for i in range(len(treeA.branches)): treeB.branches[i].id = treeA.branches[i].id for j in range(len(treeA.branches[i].points)): treeB.branches[i].points[j].id = treeA.branches[i].points[j].id trees = [treeA, treeB] print("\nResults:\n---------") # TDBL the same for identical trees allTDBL = [ TDBL(tree, excludeAxon=True, excludeBasal=False, includeFilo=False, filoDist=5) for tree in trees ] # print (allTDBL) assert allTDBL[0] == allTDBL[1] print("🙌 TDBL match!") filoTypes, added, subtracted, transitioned, masterChanged, masterNodes = \ addedSubtractedTransitioned(trees, excludeAxon=True, excludeBasal=False, terminalDist=5, filoDist=5) assert not np.any(added) assert not np.any(subtracted) assert not np.any(transitioned) print("🙌 Nothing added, subtracted or transitioned!") motilities, filoLengths = motility(trees, excludeAxon=True, excludeBasal=False, terminalDist=5, filoDist=5) mot = motilities['raw'][0] assert np.all(np.logical_or(mot == 0, np.isnan(mot))) assert np.all( np.logical_or(filoLengths[0] == filoLengths[1], np.isnan(filoLengths[0]))) assert np.array_equal(filoTypes[0], filoTypes[1]) print("🙌 Filotypes, filo lengths match!")
def branchType(fullState: FullState, branchIDList: List[str], **kwargs: Any) -> pd.DataFrame: nTrees = len(fullState.trees) filoTypes, added, subtracted, transitioned, masterChanged, masterNodes = \ pdAnalysis.addedSubtractedTransitioned(fullState.trees, **kwargs) intFiloTypes = filoTypes.astype(int) colNames = [('branchType_%02d' % (i + 1)) for i in range(nTrees)] return pd.DataFrame(data=intFiloTypes.T, index=branchIDList, columns=colNames)
def filoCount(fullState: FullState, **kwargs: Any) -> pd.DataFrame: filoTypes = pdAnalysis.addedSubtractedTransitioned(fullState.trees, **kwargs)[0] countInterstitial = np.sum( (filoTypes == FiloType.INTERSTITIAL) | (filoTypes == FiloType.BRANCH_WITH_INTERSTITIAL), axis=1) countTerminal = np.sum((filoTypes == FiloType.TERMINAL) | (filoTypes == FiloType.BRANCH_WITH_TERMINAL), axis=1) return pd.DataFrame({ 'filoCount': countInterstitial + countTerminal, 'interstitialFiloCount': countInterstitial, 'terminalFiloCount': countTerminal, })
def motility(fullState: FullState, **kwargs: Any) -> pd.DataFrame: trees = fullState.trees nA: List[int] = [] nS: List[int] = [] nT: List[int] = [] nE: List[int] = [] nR: List[int] = [] branchIDList = util.sortedBranchIDList(trees) _, added, subtracted, transitioned, _, _ = \ pdAnalysis.addedSubtractedTransitioned(trees, **kwargs) motilityValues, _ = pdAnalysis.motility(trees, **kwargs) rawMotility = motilityValues['raw'] # Use raw motility for treeIdx, treeModel in enumerate(trees): if treeIdx == 0: # First tree has no changes by definition: for arr in [nA, nS, nT, nE, nR]: arr.append(-1) else: # Otherwise, look up A/S/T and calculate E/R oldTreeModel = trees[treeIdx - 1] growCount, shrinkCount = 0, 0 for branch in treeModel.branches: branchIdx = branchIDList.index(branch.id) if not added[treeIdx - 1][branchIdx] and not transitioned[treeIdx - 1][branchIdx]: motValue = rawMotility[treeIdx - 1][branchIdx] if abs(motValue) > MIN_MOTILITY and len(branch.points) > 0: if motValue > 0: growCount += 1 else: shrinkCount += 1 nA.append(np.sum(added[treeIdx - 1])) nS.append(np.sum(subtracted[treeIdx - 1])) nT.append(np.sum(transitioned[treeIdx - 1])) nE.append(growCount) nR.append(shrinkCount) return pd.DataFrame({ 'branchesAdded': nA, 'branchesSubtracted': nS, 'branchesTransitioned': nT, 'branchesExtended': nE, 'branchesRetracted': nR, })
def calculateResults(path='data/movie5local.mat'): results = {} if path.endswith('.mat'): # Keep orphans around, to match against old matlab analysis fullState = files.importFromMatlab(path, removeOrphanBranches=False) else: assert path.endswith('.dyn.gz') fullState = files.loadState(path) trees = fullState.trees TERM_DIST = 5 FILO_DIST = 5 allTDBL = [ TDBL(tree, excludeAxon=True, excludeBasal=False, includeFilo=False, filoDist=FILO_DIST) for tree in trees ] results['tdbl'] = np.array([allTDBL]) filoTypes, added, subtracted, transitioned, masterChanged, masterNodes = \ addedSubtractedTransitioned(trees, excludeAxon=True, excludeBasal=False, terminalDist=TERM_DIST, filoDist=FILO_DIST) results['filotypes'] = filoTypes results['added'] = added results['subtracted'] = subtracted results['transitioned'] = transitioned results['masterChanged'] = masterChanged results['masterNodes'] = masterNodes motilities, filoLengths = motility(trees, excludeAxon=True, excludeBasal=False, terminalDist=TERM_DIST, filoDist=FILO_DIST) results['filolengths'] = filoLengths return fullState, results