def compute_initial_figure(self): # Scale results to keep same aspect ratio (matplotlib apsect='equal' is broken in 3d...) xmin, xmax, ymin, ymax, zmin, zmax = None, None, None, None, None, None for offset, ax in enumerate(self.axes): treeIdx = self.firstTree + offset treeModel = self.treeModels[treeIdx] x, y, z = treeModel.worldCoordPoints(treeModel.flattenPoints()) if xmin is None: xmin, xmax = np.min(x), np.max(x) ymin, ymax = np.min(y), np.max(y) zmin, zmax = np.min(z), np.max(z) else: xmin, xmax = min(xmin, np.min(x)), max(xmax, np.max(x)) ymin, ymax = min(ymin, np.min(y)), max(ymax, np.max(y)) zmin, zmax = min(zmin, np.min(z)), max(zmax, np.max(z)) r = (0.5 * max(xmax - xmin, ymax - ymin, zmax - zmin)) * 1.1 xM, yM, zM = (xmax + xmin) / 2, (ymax + ymin) / 2, (zmax + zmin) / 2 for offset, ax in enumerate(self.axes): treeIdx = self.firstTree + offset treeModel = self.treeModels[treeIdx] ax.set_title(util.createTitle(treeIdx, self.filePaths[treeIdx]), color='white') ax.set_xlim3d(xM - r, xM + r) ax.set_ylim3d(yM - r, yM + r) ax.set_zlim3d(zM - r, zM + r) self.drawSingleTree3D(ax, treeIdx, treeModel)
def drawSingleTreeChanges(self, ax, isFirstTree): changeColor = GONE_COLOR if isFirstTree else ADDED_COLOR treeIdx = self.firstTree + (0 if isFirstTree else 1) otherTreeIdx = self.firstTree + (1 if isFirstTree else 0) treeModel = self.treeModels[treeIdx] otherTreeModel = self.treeModels[otherTreeIdx] ax.set_title(util.createTitle(treeIdx, self.filePaths[treeIdx]), color='w') # Draw lines for each branch: for branch in treeModel.branches: if branch.parentPoint is None: continue points = [branch.parentPoint] + branch.points x, y, z = treeModel.worldCoordPoints(points) ax.plot(x, y, z, c=GREY_COLOUR, lw=1) # TODO - draw axon differently? # Split points by keep/new status: somaColor = None otherPointIDs = set([p.id for p in otherTreeModel.flattenPoints()]) keptPoints, newPoints = [], [] for p in treeModel.flattenPoints(): newPoint = p.id not in otherPointIDs if p.isRoot(): somaColor = changeColor if newPoint else KEPT_COLOR else: toAppend = newPoints if newPoint else keptPoints toAppend.append(p) # Draw the points by keep/remove: self.drawPointsOneColor(ax, treeModel, keptPoints, KEPT_COLOR) self.drawPointsOneColor(ax, treeModel, newPoints, changeColor) self.drawPointsOneColor(ax, treeModel, [treeModel.rootPoint], somaColor, s=350) # Big soma # Make equal aspect ratio: x, y, z = treeModel.worldCoordPoints(treeModel.flattenPoints()) xmin, xmax = np.min(x), np.max(x) ymin, ymax = np.min(y), np.max(y) zmin, zmax = np.min(z), np.max(z) r = (0.5 * max(xmax - xmin, ymax - ymin, zmax - zmin)) * 1.1 xM, yM, zM = (xmax + xmin) / 2, (ymax + ymin) / 2, (zmax + zmin) / 2 ax.set_xlim3d(xM - r, xM + r) ax.set_ylim3d(yM - r, yM + r) ax.set_zlim3d(zM - r, zM + r)
def _addItem(self, idx, filePath, stackHidden, isFirst, isLast): """Adds a single row into the list, and attaches events.""" title = util.createTitle(idx, filePath) # Build the widget itself. container = QtWidgets.QWidget() wText = QtWidgets.QLabel(title) bViz = cursorPointer( QtWidgets.QPushButton("Show" if stackHidden else "Hide")) bDel = cursorPointer(QtWidgets.QPushButton("Delete")) bUp = cursorPointer(QtWidgets.QPushButton("▲")) bDn = cursorPointer(QtWidgets.QPushButton("▼")) for b in [bUp, bDn]: b.setMaximumWidth(20) l = QtWidgets.QHBoxLayout() l.addWidget(wText) l.addWidget(bViz) l.addWidget(bDel) l.addWidget(bUp) l.addWidget(bDn) l.addStretch() l.setSizeConstraint(QtWidgets.QLayout.SetFixedSize) container.setLayout(l) if isFirst: bUp.setEnabled(False) if isLast: bDn.setEnabled(False) # Build the list item, and add the widget: itemN = QtWidgets.QListWidgetItem() itemN.setSizeHint(container.sizeHint()) self.list.addItem(itemN) self.list.setItemWidget(itemN, container) # Attach events: bViz.clicked.connect(lambda: self._handleVizChange(idx)) bDel.clicked.connect(lambda: self._handleDelete(idx, title)) bUp.clicked.connect(lambda: self._handleUp(idx)) bDn.clicked.connect(lambda: self._handleDn(idx))
def updateTitle(self): self.setWindowTitle(util.createTitle(self.windowIndex, self.imagePath))
def compute_initial_figure(self): SZ_FACTOR = self.sizeFactor xminD, xmaxD, yminD, ymaxD = 0, 0, 0, 0 if self.dendrogram: allX = [x for treeX in self.dendrogramX for x in treeX.values()] allY = [y for treeY in self.dendrogramY for y in treeY.values()] xminD, xmaxD = np.min(allX), np.max(allX) yminD, ymaxD = np.min(allY), np.max(allY) # Update colors to be white on black: print ("") for offset, ax in enumerate(self.axes): treeIdx = self.firstTree + offset treeModel = self.treeModels[treeIdx] denX, denY = self.dendrogramX[treeIdx], self.dendrogramY[treeIdx] ax.set_title(util.createTitle(treeIdx, self.filePaths[treeIdx])) ax.set_facecolor("white") if self.dendrogram: ax.margins(0.1) ax.set_xticklabels([]) ax.set_yticklabels([]) else: ax.w_xaxis.set_pane_color((1.0,1.0,1.0,1.0)) ax.w_yaxis.set_pane_color((1.0,1.0,1.0,1.0)) ax.w_zaxis.set_pane_color((1.0,1.0,1.0,1.0)) ax.w_xaxis._axinfo['grid'].update({'linewidth':0.25,'color':'gray'}) ax.w_yaxis._axinfo['grid'].update({'linewidth':0.25,'color':'gray'}) ax.w_zaxis._axinfo['grid'].update({'linewidth':0.25,'color':'gray'}) # Draw lines for each branch: for branch in treeModel.branches: if branch.parentPoint is None: continue points = [branch.parentPoint] + branch.points if self.dendrogram: x = [denX[p.id] for p in points] y = [denY[p.id] for p in points] ax.plot(x, y, c=TREE_COLOUR) else: x, y, z = treeModel.worldCoordPoints(points) ax.plot(x, y, z, c=TREE_COLOUR) # TODO - draw axon differently? # Draw filo for each branch: if treeIdx > 0: oldTreeModel = self.treeModels[treeIdx - 1] oldDenX, oldDenY = self.dendrogramX[treeIdx - 1], self.dendrogramY[treeIdx - 1] # For debugging puposes, maybe remove? growCount, shrinkCount = 0, 0 for branch in treeModel.branches: branchIdx = self.branchIDList.index(branch.id) plot = True if self.added[treeIdx-1][branchIdx]: color, sz = ADDED_COLOR, self.filoLengths[treeIdx][branchIdx] * SZ_FACTOR elif self.transitioned[treeIdx-1][branchIdx]: color, sz = TRANS_COLOR, self.filoLengths[treeIdx][branchIdx] * SZ_FACTOR plot = False # Don't draw transitions ?! else: mot = self.motility[treeIdx-1][branchIdx] if abs(mot) >= self.options.minMotilityDist and len(branch.points) > 0: color = GROW_COLOR if mot > 0 else SHRINK_COLOR if mot > 0: growCount += 1 else: shrinkCount += 1 sz = abs(mot) * SZ_FACTOR else: plot = False if plot: if len(branch.points) != 0: if self.dendrogram: x = [denX[branch.points[-1].id]] y = [denY[branch.points[-1].id]] ax.scatter(x, y, c=[color], s=sz) else: x, y, z = treeModel.worldCoordPoints([branch.points[-1]]) ax.scatter(x, y, z, c=[color], s=sz) # Show removed branches from last point: branchInLast = self.treeModels[treeIdx - 1].getBranchByID(branch.id) if branchInLast is not None: for childPoint in branchInLast.points: retracted = 0 for childBranch in childPoint.children: if childBranch is None or len(childBranch.points) == 0: continue childBranchIdx = self.branchIDList.index(childBranch.id) firstPointID = childBranch.points[0].id inCurrentTree = self.treeModels[treeIdx].getPointByID(firstPointID) is not None if not inCurrentTree: retracted += self.filoLengths[treeIdx - 1][childBranchIdx] if retracted > 0: # print ("extra retraction: " + str(retracted)) if self.dendrogram: # Not really correct... pass else: x, y, z = oldTreeModel.worldCoordPoints([childPoint]) childPointInNew = treeModel.getPointByID(childPoint.id) if childPointInNew is not None: x, y, z = treeModel.worldCoordPoints([childPointInNew]) ax.scatter(x, y, z, c=[RETRACT_COLOR], s=(retracted * SZ_FACTOR)) # Subtractions do not appear in tree, so find by looking at last tree for branchIdx, branchId in enumerate(self.branchIDList): if not self.subtracted[treeIdx - 1][branchIdx]: continue branchInLast = self.treeModels[treeIdx - 1].getBranchByID(branchId) if branchInLast is None: continue # Draw at the parent of the subtracted branch, not the end point. drawAt = branchInLast.parentPoint if drawAt is not None: # Walk up the old tree until a point exists in the new # tree to connect the removal to. drawAtInNew = treeModel.getPointByID(drawAt.id) while drawAtInNew is None and drawAt is not None: drawAt = drawAt.nextPointInBranch(delta=-1) if drawAt is not None: drawAtInNew = treeModel.getPointByID(drawAt.id) if drawAt is None or drawAtInNew is None: continue sz = self.filoLengths[treeIdx-1][branchIdx] * SZ_FACTOR if self.dendrogram: x = [denX[drawAtInNew.id]] y = [denY[drawAtInNew.id]] ax.scatter(x, y, c=[GONE_COLOR], s=sz) else: x, y, z = treeModel.worldCoordPoints([drawAtInNew]) ax.scatter(x, y, z, c=[GONE_COLOR], s=sz) # For debugging puposes, maybe remove? print ("Stack #%d -> #%d" % (treeIdx, treeIdx + 1)) print (" - #Added = %d" % np.sum(self.added[treeIdx-1])) print (" - #Subtracted = %d" % np.sum(self.subtracted[treeIdx-1])) print (" - #Transitioned = %d" % np.sum(self.transitioned[treeIdx-1])) print (" - #Extensions = %d" % growCount) print (" - #Retractions = %d" % shrinkCount) # And finally draw the soma as a big sphere (if present): if treeModel.rootPoint is not None: if not self.dendrogram: x, y, z = treeModel.worldCoordPoints([treeModel.rootPoint]) ax.scatter(x, y, z, c=[TREE_COLOUR], s=350) # Make equal aspect ratio: if not self.dendrogram: x, y, z = treeModel.worldCoordPoints(treeModel.flattenPoints()) xmin, xmax = np.min(x), np.max(x) ymin, ymax = np.min(y), np.max(y) zmin, zmax = np.min(z), np.max(z) r = (0.5 * max(xmax - xmin, ymax - ymin, zmax - zmin)) * 1.1 xM, yM, zM = (xmax + xmin) / 2, (ymax + ymin) / 2, (zmax + zmin) / 2 ax.set_xlim3d(xM - r, xM + r) ax.set_ylim3d(yM - r, yM + r) ax.set_zlim3d(zM - r, zM + r) else: xM, yM = (xmaxD + xminD) / 2, (ymaxD + yminD) / 2 xR, yR = (0.5 * (xmaxD - xminD) * 1.1), (0.5 * (ymaxD - yminD) * 1.1) ax.set_xlim(xM - xR, xM + xR) ax.set_ylim(yM - yR, yM + yR)