def test_treeNoCycle3D(): # test if stats i.e segments, type of graph. branch, end points, and information about cycle # is as expected for a tree like structure crosPairgraph = get_disjoint_trees_no_cycle_3d() stats = SegmentStats(crosPairgraph) stats.setStats() assert stats.totalSegments == 8, "totalSegments in treeNoCycle3D sample should be 8, it is {}".format(stats.totalSegments) assert stats.typeGraphdict[0] == 4, "type of graph in treeNoCycle3D sample should be 4, it is {}".format(stats.typeGraphdict[0]) assert stats.countEndPoints == 8, "number of end points in treeNoCycle3D sample should be 2, it is {}".format(stats.countEndPoints) assert stats.countBranchPoints == 2, "number of branch points in treeNoCycle3D sample should be 2, it is {}".format(stats.countBranchPoints) assert stats.cycleInfoDict == {}, "cycleInfoDict must be empty, it is {}".format(stats.cycleInfoDict)
def test_cycleAndTree(): # test if stats i.e segments, type of graph. branch, end points, and information about cycle # is as expected for a cyclic tree sampleGraph = get_cycles_with_branches_protrude() stats = SegmentStats(sampleGraph) stats.setStats() assert stats.totalSegments == 4, "totalSegments in cycleAndTree sample should be 4, it is {}".format(stats.totalSegments) assert stats.typeGraphdict[0] == 3, "type of graph in cycleAndTree sample should be 3, it is {}".format(stats.typeGraphdict[0]) assert stats.countEndPoints == 2, "number of end points in cycleAndTree sample should be 2, it is {}".format(stats.countEndPoints) assert stats.countBranchPoints == 2, "number of branch points in cycleAndTree sample should be 2, it is {}".format(stats.countBranchPoints) assert stats.cycleInfoDict[0][0] == 2, "number of branch points on the cycle must be 2, it is {}".format(stats.cycleInfoDict[0][0])
def test_singleCycle(): # test if stats i.e segments, type of graph. branch, end points, and information about cycle # is as expected for a single cycle donutGraph = get_cycle_no_tree() stats = SegmentStats(donutGraph) stats.setStats() assert stats.totalSegments == 1, "totalSegments in singleCycle sample should be 1, it is {}".format(stats.totalSegments) assert stats.typeGraphdict[0] == 1, "type of graph in singleCycle sample should be 1, it is {}".format(stats.typeGraphdict[0]) assert stats.countEndPoints == 0, "number of end points in singleCycle sample should be 2, it is {}".format(stats.countEndPoints) assert stats.countBranchPoints == 0, "number of branch points in singleCycle sample should be 0, it is {}".format(stats.countBranchPoints) assert stats.hausdorffDimensionDict == {}, "hausdorffDimensionDict must be empty, it is {}".format(stats.hausdorffDimensionDict) assert stats.cycleInfoDict[0][0] == 0, "number of branch points on the cycle must be 0, it is {}".format(stats.cycleInfoDict[0][0])
def test_singleSegment(): # test if stats i.e segments, type of graph. branch, end points, and information about cycle # is as expected for a single segment lineGraph = get_single_voxel_lineNobranches() stats = SegmentStats(lineGraph) stats.setStats() assert stats.totalSegments == 0, "totalSegments in singleSegment sample should be 0, it is {}".format(stats.totalSegments) assert stats.typeGraphdict[0] == 2, "type of graph in singleSegment sample should be 2, it is {}".format(stats.typeGraphdict[0]) assert stats.countEndPoints == 2, "number of end points in singleSegment sample should be 2, it is {}".format(stats.countEndPoints) assert stats.countBranchPoints == 0, "number of branch points in singleSegment sample should be 0, it is {}".format(stats.countBranchPoints) assert stats.hausdorffDimensionDict == {}, "hausdorffDimensionDict must be empty, it is {}".format(stats.hausdorffDimensionDict) assert stats.cycleInfoDict == {}, "cycleInfoDict must be empty, it is {}".format(stats.cycleInfoDict)
def test_treeNoCycle3D(): # test if stats i.e segments, type of graph. branch, end points, and information about cycle # is as expected for a tree like structure crosPairgraph = get_disjoint_trees_no_cycle_3d() stats = SegmentStats(crosPairgraph) stats.setStats() assert stats.totalSegments == 8, "totalSegments in treeNoCycle3D sample should be 8, it is {}".format( stats.totalSegments) assert stats.typeGraphdict[ 0] == 4, "type of graph in treeNoCycle3D sample should be 4, it is {}".format( stats.typeGraphdict[0]) assert stats.countEndPoints == 8, "number of end points in treeNoCycle3D sample should be 2, it is {}".format( stats.countEndPoints) assert stats.countBranchPoints == 2, "number of branch points in treeNoCycle3D sample should be 2, it is {}".format( stats.countBranchPoints) assert stats.cycleInfoDict == {}, "cycleInfoDict must be empty, it is {}".format( stats.cycleInfoDict)
def test_cycleAndTree(): # test if stats i.e segments, type of graph. branch, end points, and information about cycle # is as expected for a cyclic tree sampleGraph = get_cycles_with_branches_protrude() stats = SegmentStats(sampleGraph) stats.setStats() assert stats.totalSegments == 4, "totalSegments in cycleAndTree sample should be 4, it is {}".format( stats.totalSegments) assert stats.typeGraphdict[ 0] == 3, "type of graph in cycleAndTree sample should be 3, it is {}".format( stats.typeGraphdict[0]) assert stats.countEndPoints == 2, "number of end points in cycleAndTree sample should be 2, it is {}".format( stats.countEndPoints) assert stats.countBranchPoints == 2, "number of branch points in cycleAndTree sample should be 2, it is {}".format( stats.countBranchPoints) assert stats.cycleInfoDict[0][ 0] == 2, "number of branch points on the cycle must be 2, it is {}".format( stats.cycleInfoDict[0][0])
def test_singleSegment(): # test if stats i.e segments, type of graph. branch, end points, and information about cycle # is as expected for a single segment lineGraph = get_single_voxel_lineNobranches() stats = SegmentStats(lineGraph) stats.setStats() assert stats.totalSegments == 0, "totalSegments in singleSegment sample should be 0, it is {}".format( stats.totalSegments) assert stats.typeGraphdict[ 0] == 2, "type of graph in singleSegment sample should be 2, it is {}".format( stats.typeGraphdict[0]) assert stats.countEndPoints == 2, "number of end points in singleSegment sample should be 2, it is {}".format( stats.countEndPoints) assert stats.countBranchPoints == 0, "number of branch points in singleSegment sample should be 0, it is {}".format( stats.countBranchPoints) assert stats.hausdorffDimensionDict == {}, "hausdorffDimensionDict must be empty, it is {}".format( stats.hausdorffDimensionDict) assert stats.cycleInfoDict == {}, "cycleInfoDict must be empty, it is {}".format( stats.cycleInfoDict)
def test_singleCycle(): # test if stats i.e segments, type of graph. branch, end points, and information about cycle # is as expected for a single cycle donutGraph = get_cycle_no_tree() stats = SegmentStats(donutGraph) stats.setStats() assert stats.totalSegments == 1, "totalSegments in singleCycle sample should be 1, it is {}".format( stats.totalSegments) assert stats.typeGraphdict[ 0] == 1, "type of graph in singleCycle sample should be 1, it is {}".format( stats.typeGraphdict[0]) assert stats.countEndPoints == 0, "number of end points in singleCycle sample should be 2, it is {}".format( stats.countEndPoints) assert stats.countBranchPoints == 0, "number of branch points in singleCycle sample should be 0, it is {}".format( stats.countBranchPoints) assert stats.hausdorffDimensionDict == {}, "hausdorffDimensionDict must be empty, it is {}".format( stats.hausdorffDimensionDict) assert stats.cycleInfoDict[0][ 0] == 0, "number of branch points on the cycle must be 0, it is {}".format( stats.cycleInfoDict[0][0])
def setSegmentStatsAfterPruning(self): # stats after pruning the braches self.getNetworkGraph() self.statsAfter = SegmentStats(self.outputGraph) self.statsAfter.setStats()
def getSegmentStatsBeforePruning(self): # stats before pruning the braches self.setNetworkGraph() self.statsBefore = SegmentStats(self.graph) self.statsBefore.setStats()
class Skeleton: def __init__(self, path, **kwargs): # initialize input array # path : can be an 3D binary array or a numpy(.npy) array # if path is a 3D volume saveSkeletonStack, saves series of # skeleton pngs in present directory if type(path) is str: if path.endswith("npy"): # extract rootDir of path self.path = os.path.split(path)[0] + os.sep self.inputStack = np.load(path) else: self.path = path self.inputStack = loadStack(self.path).astype(bool) else: self.path = os.getcwd() self.inputStack = path if kwargs != {}: aspectRatio = kwargs["aspectRatio"] self.inputStack = ndimage.interpolation.zoom(self.inputStack, zoom=aspectRatio, order=2, prefilter=False) def setThinningOutput(self, mode="reflect"): # Thinning output self.skeletonStack = get_thinned(self.inputStack, mode) def setNetworkGraph(self, findSkeleton=False): # Network graph of the crowded region removed output # Generally the function expects a skeleton # and findSkeleton is False by default if findSkeleton is True: self.setThinningOutput() else: self.skeletonStack = self.inputStack self.graph = get_networkx_graph_from_array(self.skeletonStack) def setPrunedSkeletonOutput(self): # Prune unnecessary segments in crowded regions removed skeleton self.setNetworkGraph(findSkeleton=True) self.outputStack = getPrunedSkeleton(self.skeletonStack, self.graph) def getNetworkGraph(self): # Network graph of the final output skeleton stack self.setPrunedSkeletonOutput() self.outputGraph = get_networkx_graph_from_array(self.outputStack) def saveSkeletonStack(self): # Save output skeletonized stack as series of pngs in the path under a subdirectory skeleton # in the input "path" self.setPrunedSkeletonOutput() saveStack(self.outputStack, self.path + "skeleton/") def getSegmentStatsBeforePruning(self): # stats before pruning the braches self.setNetworkGraph() self.statsBefore = SegmentStats(self.graph) self.statsBefore.setStats() def setSegmentStatsAfterPruning(self): # stats after pruning the braches self.getNetworkGraph() self.statsAfter = SegmentStats(self.outputGraph) self.statsAfter.setStats()