def test_addedge(self):
     my_skeleton = Skeleton()
     edges = [(0, 1), (1, 2), (2, 3)]
     for edge in edges:
         my_skeleton.add_edge(u=edge[0], v=edge[1])
     self.assertEqual(my_skeleton.nx_graph.number_of_nodes(), len(edges) + 1)
     self.assertEqual(my_skeleton.nx_graph.number_of_edges(), len(edges))
 def test_addnode(self):
     my_skeleton = Skeleton()
     scaling = np.array([1., 1., 0.5])
     nodes_pos_phys = np.array([[0, 0, 0], [50, 50, 50], [100, 100, 100], [150, 150, 150]])
     nodes_pos_voxel = np.floor(nodes_pos_phys * scaling)
     node_ids = range(nodes_pos_voxel.shape[0])
     for node_id, pos_voxel, pos_phys in zip(node_ids, nodes_pos_voxel, nodes_pos_phys):
         my_skeleton.add_node(node_id, pos_voxel=pos_voxel, pos_phys=pos_phys)
    def test_totalPathLength(self):
        test_skeleton = Skeleton()
        nodes_pos_phys = np.array([[0, 0, 0], [5., 5., 5.], [10., 10., 10.], [15., 15., 15.]])
        edges = [(0, 1), (1, 2), (2, 3)]
        test_skeleton.initialize_from_datapoints(nodes_pos_phys, vp_type_voxel=False, edgelist=edges)

        exp_total_length = np.sqrt((15 ** 2) * 3)
        total_length = test_skeleton.calculate_total_phys_length()
        self.assertEqual(exp_total_length, total_length)
    def test_basicinitialization(self):
        my_identifier = 3
        my_voxel_size = np.array([1., 1., 2.])
        my_seg_id = 2
        my_nx_graph = nx.Graph()

        my_skeleton = Skeleton(identifier=my_identifier, voxel_size=my_voxel_size, seg_id=my_seg_id)
        my_skeleton_with_graph = Skeleton(identifier=my_identifier, voxel_size=my_voxel_size, seg_id=my_seg_id,
                                          nx_graph=my_nx_graph)

        self.assertEqual(my_skeleton.nx_graph.number_of_nodes(), 0)
        self.assertEqual(my_skeleton.nx_graph.number_of_edges(), 0)
        self.assertEqual(my_skeleton.identifier, my_identifier)
        self.assertTrue(np.array_equal(my_skeleton.voxel_size, my_voxel_size))
        self.assertEqual(my_skeleton.seg_id, my_seg_id)
        self.assertIsInstance(my_skeleton.nx_graph, nx.Graph)
        self.assertIsInstance(my_skeleton_with_graph.nx_graph, nx.Graph)
    def test_applyTransformation(self):

        try:
            import augment
        except ImportError:
            return

        # normal case and if exactly at the same position
        test_skeleton = Skeleton()
        nodes_target = np.array([[0, 0, 0], [1, 0, 1], [2, 1, 2]])
        edges_target = ((0, 1),(1, 2))
        test_skeleton.initialize_from_datapoints(datapoints=nodes_target, vp_type_voxel=True, edgelist=edges_target,
                                             datapoints_type='nparray')

        nodes_bb = (3, 3, 3)
        # Create transformation matrix.
        transformation = augment.create_identity_transformation(nodes_bb)

        # Rotate around z axis 90 degree anti-clockwise.
        transformation += augment.create_rotation_transformation(
            nodes_bb,
            math.pi/2)

        test_skeleton.apply_transformation(transformation)
        pred_pos0 = test_skeleton.nx_graph.node[0]['position'].voxel
        pred_pos1 = test_skeleton.nx_graph.node[1]['position'].voxel
        pred_pos2 = test_skeleton.nx_graph.node[2]['position'].voxel

        exp_pos0 = np.array([2, 0, 0])
        exp_pos1 = np.array([2, 1, 1])
        exp_pos2 = np.array([1, 2, 2])

        self.assertTrue((pred_pos0 == exp_pos0).all())
        self.assertTrue((pred_pos1 == exp_pos1).all())
        self.assertTrue((pred_pos2 == exp_pos2).all())
    def test_writeToKnossos(self):
        # Represents a branching skeleton. Not a real testfunction.
        # TODO add actual test function, when also reading knossos files is possible.
        test_skeleton = Skeleton(voxel_size=[10., 10., 20.])
        nodes_pos_phys = np.array([[0, 0, 0], [50., 50., 100.], [100., 100., 200.], [100., 100., 300.]])
        edges = [(0, 1), (1, 2), (1, 3)]
        test_skeleton.initialize_from_datapoints(nodes_pos_phys, vp_type_voxel=False, edgelist=edges)

        test_skeleton2 = Skeleton(voxel_size=[10., 10., 20.])
        nodes_pos_phys = np.array([[50., 50., 100.], [50., 50., 200.], [50., 50., 300.]])
        edges = [(0, 1), (1, 2)]
        test_skeleton2.initialize_from_datapoints(nodes_pos_phys, False, edgelist=edges)

        skeleton_container = SkeletonContainer([test_skeleton, test_skeleton2])
        skeleton_container.write_to_knossos_nml('testdata/knossostestfile.nml')
    def test_getDistanceToSkeleton(self):
        # normal case and if exactly at the same position
        Sk_target = Skeleton()
        nodes_target = np.array([[0, 0, 0], [5, 5, 10], [10, 10, 10]])
        edges_target = ((0, 1),(1, 2))
        Sk_target.initialize_from_datapoints(datapoints=nodes_target, vp_type_voxel=True, edgelist=edges_target,
                                             datapoints_type='nparray')
        nodes_pred = np.array([[0, 0, 0], [5, 5, 15]])
        true_distances = np.array([0., 5.])
        distance_to_cl = Sk_target.get_distance_to_skeleton(x=nodes_pred)
        self.assertTrue(np.array_equal(true_distances, distance_to_cl))

        # check if interpolated lines are taken into account
        Sk_target = Skeleton()
        nodes_target = np.array([[0, 0, 0], [20, 20, 20]])
        edges_target = [(0, 1)]
        Sk_target.initialize_from_datapoints(datapoints=nodes_target, vp_type_voxel=True, edgelist=edges_target,
                                             datapoints_type='nparray')
        nodes_pred = np.array([[0, 0, 0], [5, 5, 5], [10, 10, 10]])

        true_distances = np.array([0., 0., 0.])
        distance_to_cl = Sk_target.get_distance_to_skeleton(x=nodes_pred)
        self.assertTrue(np.array_equal(true_distances, distance_to_cl))
    def test_CheckPointInsideBb(self):
        Sk = Skeleton()
        nodes = np.array([[0, 0, 0], [5, 5, 5], [6,6,6], [8,8,8]])
        edges = ((0, 1),(1, 2),(2,3))
        Sk.initialize_from_datapoints(datapoints=nodes, vp_type_voxel=True, edgelist=edges,
                                             datapoints_type='nparray')

        bb_min = [1,1,1]
        bb_max = [6,6,6]
        # check points between min und max and exactly min and max are still counted as inside
        self.assertTrue(Sk.check_point_inside_bb([1,1,1], bb_min=bb_min, bb_max=bb_max))
        self.assertTrue(Sk.check_point_inside_bb([4,4,4], bb_min=bb_min, bb_max=bb_max))
        self.assertTrue(Sk.check_point_inside_bb([5,5,5], bb_min=bb_min, bb_max=bb_max))

        # check points smaller than min and larger than max are counted as outside
        self.assertFalse(Sk.check_point_inside_bb([0,0,0], bb_min=bb_min, bb_max=bb_max))
        self.assertFalse(Sk.check_point_inside_bb([7,7,7], bb_min=bb_min, bb_max=bb_max))
    def test_addedgefeatures(self):
        my_skeleton = Skeleton()
        scaling = np.array([1., 1., 0.5])
        nodes_pos_phys = np.array([[0, 0, 0], [50, 50, 50], [100, 100, 100], [150, 150, 150]])
        nodes_pos_voxel = np.floor(nodes_pos_phys * scaling)
        node_ids = range(nodes_pos_voxel.shape[0])
        for node_id, pos_voxel, pos_phys in zip(node_ids, nodes_pos_voxel, nodes_pos_phys):
            my_skeleton.add_node(node_id=node_id, pos_voxel=pos_voxel, pos_phys=pos_phys)

        edges = [(0, 1), (1, 2), (2, 3)]
        for edge in edges:
            my_skeleton.add_edge(u=edge[0], v=edge[1])

        my_edge = 2
        edge_u = edges[my_edge][0]
        edge_v = edges[my_edge][1]
        my_skeleton._add_edge_features(u=edge_u, v=edge_v, edge_feature_names=['length'])

        length_voxel = np.sqrt(sum((nodes_pos_voxel[edge_u] - nodes_pos_voxel[edge_v]) ** 2))
        length_phys = np.sqrt(sum((nodes_pos_phys[edge_u] - nodes_pos_phys[edge_v]) ** 2))
        self.assertEqual(my_skeleton.nx_graph.edge[edge_u][edge_v]['length'].voxel, length_voxel)
        self.assertEqual(my_skeleton.nx_graph.edge[edge_u][edge_v]['length'].phys, length_phys)
    def test_SkContainerSplitIntoCCs(self):
        # Represents a branching skeleton.
        test_skeleton = Skeleton()
        nodes_pos = np.array([[5, 0, 5], [5, 5, 5], [10, 10, 10], [15, 10, 8]])
        edges = [(0, 1), (1, 2), (1, 3)]
        test_skeleton.initialize_from_datapoints(nodes_pos, vp_type_voxel=True, edgelist=edges)
        test_skeleton.interpolate_edges()
        skeleton_container = SkeletonContainer([test_skeleton])

        for skeleton in skeleton_container.skeleton_list:
            for node_id, node_dic in skeleton.nx_graph.nodes_iter(data=True):
                print node_id, node_dic['position'].voxel
            print skeleton.nx_graph.edges()


        for skeleton in skeleton_container.skeleton_list:
            skeleton.crop_graph_to_bb([6, 6, 6], [20, 20, 20])

        self.assertEqual(1, len(skeleton_container.skeleton_list))
        skeleton_container.split_into_cc()

        self.assertEqual(2, len(skeleton_container.skeleton_list))
    def test_CropGraphToBb(self):
        bb_min = [1,1,1]
        bb_max = [7,7,7]

        Sk = Skeleton()
        nodes = np.array([[0, 0, 0], [5, 5, 5], [6,6,6], [8,8,8]])
        num_nodes_outside = 2
        edges = ((0, 1),(1, 2),(2,3))
        Sk.initialize_from_datapoints(datapoints=nodes, vp_type_voxel=True, edgelist=edges,
                                             datapoints_type='nparray')

        Sk2 = Skeleton()
        nodes2 = np.array([[1, 1, 1], [5, 5, 5], [6,6,6]])
        edges2 = ((0, 1),(1, 2))
        Sk2.initialize_from_datapoints(datapoints=nodes2, vp_type_voxel=True, edgelist=edges2,
                                             datapoints_type='nparray')

        # example where 2 nodes outside
        Sk.crop_graph_to_bb(bb_min, bb_max)
        for node_id in Sk.nx_graph.nodes_iter():
            self.assertTrue(Sk.check_point_inside_bb(Sk.nx_graph.node[node_id]['position'].voxel, bb_min, bb_max))
        self.assertEqual(Sk.nx_graph.number_of_nodes(), len(nodes)-num_nodes_outside)

        # example with no nodes outside
        Sk2.crop_graph_to_bb(bb_min, bb_max)
        for node_id in Sk2.nx_graph.nodes_iter():
            self.assertTrue(Sk2.check_point_inside_bb(Sk2.nx_graph.node[node_id]['position'].voxel, bb_min, bb_max))

        self.assertEqual(Sk2.nx_graph.number_of_nodes(), len(nodes2))
    def test_getRecall(self):
        # normal case
        Sk_target = Skeleton()
        nodes_target = np.array([[0, 0, 0], [5, 5, 10], [5, 5, 15], [20, 20, 20]])
        edges_target = ((0, 1), (1, 2), (2, 3))
        Sk_target.initialize_from_datapoints(datapoints=nodes_target, vp_type_voxel=True, edgelist=edges_target,
                                             datapoints_type='nparray')
        Sk_pred = Skeleton()
        nodes_pred = np.array([[0, 0, 5], [5, 5, 15], [10, 15, 25], [20, 25, 40]])
        edges_pred = ((0, 1), (1, 2), (2, 3))
        Sk_pred.initialize_from_datapoints(datapoints=nodes_pred, vp_type_voxel=True, edgelist=edges_pred,
                                           datapoints_type='nparray')
        tolerance_distance = 5
        human_recall = (1.+1.+1.+0.) / len(nodes_pred)
        fct_recall   = Sk_target.get_recall(other=Sk_pred, tolerance_distance=tolerance_distance)
        self.assertEqual(human_recall, fct_recall)

        # test if tolerance distance is 0, only exactly the same node position are correct
        Sk_target = Skeleton()
        nodes_target = np.array([[0, 0, 0], [5, 5, 5], [10, 10, 10], [20, 20, 20]])
        edges_target = ((0, 1), (1, 2), (2, 3))
        Sk_target.initialize_from_datapoints(datapoints=nodes_target, vp_type_voxel=True, edgelist=edges_target,
                                             datapoints_type='nparray')
        Sk_pred = Skeleton()
        nodes_pred = np.array([[0, 0, 0], [5, 5, 6], [5, 5, 7], [10, 10, 10], [20, 20, 18]])
        edges_pred = ((0, 1), (1, 2), (2, 3), (3, 4))
        Sk_pred.initialize_from_datapoints(datapoints=nodes_pred, vp_type_voxel=True, edgelist=edges_pred,
                                           datapoints_type='nparray')
        tolerance_distance = 0
        human_precision = (1.+0.+0.+1.+0.) / 5.
        fct_precision   = Sk_target.get_precision(other=Sk_pred, tolerance_distance=tolerance_distance)
        self.assertEqual(human_precision, fct_precision)

        # check if interpolated lines are taken into account
        Sk_target = Skeleton()
        nodes_target = np.array([[0, 0, 0], [20, 20, 20]])
        edges_target = [(0, 1)]
        Sk_target.initialize_from_datapoints(datapoints=nodes_target, vp_type_voxel=True, edgelist=edges_target,
                                             datapoints_type='nparray')
        Sk_pred = Skeleton()
        nodes_pred = np.array([[0, 0, 0], [5, 5, 5], [10, 10, 10], [30, 30, 30]])
        edges_pred = ((0, 1), (1, 2), (2, 3))
        Sk_pred.initialize_from_datapoints(datapoints=nodes_pred, vp_type_voxel=True, edgelist=edges_pred,
                                           datapoints_type='nparray')
        tolerance_distance = 0.
        human_recall = (1. + 1.+ 1.) / len(nodes_pred)
        fct_recall = Sk_target.get_precision(other=Sk_pred, tolerance_distance=tolerance_distance)
        self.assertEqual(human_recall, fct_recall)
    def test_GetSegIDs(self):
        segmentation = np.zeros((20, 20, 20))
        segmentation[:, :, 0:7] = 1
        segmentation[:, :, 7:10] = 2
        segmentation[:, :, 10:16] = 3
        segmentation[:, :, 16:20] = 4

        Sk = Skeleton()
        nodes = np.array([[10, 10, 0], [10, 10, 15]])
        edges = [[0, 1]]
        Sk.initialize_from_datapoints(datapoints=nodes, vp_type_voxel=True, edgelist=edges,
                                      datapoints_type='nparray')

        Sk.interpolate_edges()
        # Test basics, collect all seg_ids.
        seg_ids, object_dict = Sk.get_seg_ids(segmentation, size_thres=0, return_objectdict=True)
        expected_segids = np.array([1, 2, 3])
        self.assertTrue(set(expected_segids) == set(seg_ids))
        self.assertEqual(7, object_dict[1]['size'])

        # Test size_thres.
        seg_ids, object_dict = Sk.get_seg_ids(segmentation, size_thres=4, return_objectdict=True)
        expected_segids = np.array([1, 3])
        self.assertTrue(set(expected_segids) == set(seg_ids))
        self.assertEqual(3, object_dict[2]['size'])

        # Test returning empty array if skeleton coordinates are outside the cube.
        Sk.shift_skeleton([20, 20, 20], 'voxel')
        seg_ids, object_dict = Sk.get_seg_ids(segmentation, size_thres=0, return_objectdict=True)
        self.assertEqual(0, len(list(seg_ids)))
        self.assertEqual(0, len(object_dict))
    def test_ShiftSkeleton(self):
        Sk = Skeleton()
        nodes = np.array([[0, 0, 0], [5, 5, 10], [10, 10, 10]])
        edges = ((0, 1),(1, 2))
        Sk.initialize_from_datapoints(datapoints=nodes, vp_type_voxel=True, edgelist=edges,
                                             datapoints_type='nparray')

        offset_1 = np.asarray([1,1,1])
        new_pos0 = nodes[0] + offset_1
        Sk.shift_skeleton(offset=offset_1, VP_type='voxel')
        pos0 = Sk.nx_graph.node[0]['position'].voxel
        self.assertTrue(np.array_equal(new_pos0, pos0))
        self.assertEqual(None, Sk.nx_graph.node[0]['position'].phys)


        Sk = Skeleton()
        nodes = np.array([[0, 0, 0], [5, 5, 10], [10, 10, 10]])
        edges = ((0, 1),(1, 2))
        Sk.initialize_from_datapoints(datapoints=nodes, vp_type_voxel=False, edgelist=edges,
                                             datapoints_type='nparray')
        offset_2 = np.asarray([1,2,3])
        new_pos0 = nodes[0] + offset_2
        Sk.shift_skeleton(offset=offset_2, VP_type='phys')
        pos0 = Sk.nx_graph.node[0]['position'].phys
        self.assertTrue(np.array_equal(new_pos0, pos0))
        self.assertEqual(None, Sk.nx_graph.node[0]['position'].voxel)
    def test_interpolateSkeleton(self):
        test_skeleton = Skeleton(voxel_size=[10., 10., 20.])
        nodes_pos_phys = np.array([[0, 0, 0], [50., 50., 100.], [100., 100., 200.], [100., 100., 300.]])
        edges = [(0, 1), (1, 2), (1, 3)]
        test_skeleton.initialize_from_datapoints(nodes_pos_phys, vp_type_voxel=False, edgelist=edges)

        # Get statistics about the graph and check whether they remain the same after interpolating the edges.
        # voxel
        deg = test_skeleton.nx_graph.degree()
        num_of_branch_nodes = len([n for n in deg if deg[n] > 1])
        num_of_endnodes = len([n for n in deg if deg[n] == 1])
        num_of_nodes_with_no_edge = len([n for n in deg if deg[n] == 0])

        test_skeleton.interpolate_edges(step_size=1, VP_type='voxel')
        self.assertEqual(num_of_branch_nodes, len([n for n in deg if deg[n] > 1]))
        self.assertEqual(num_of_endnodes, len([n for n in deg if deg[n] == 1]))
        self.assertEqual(num_of_nodes_with_no_edge, len([n for n in deg if deg[n] == 0]))

        # phys
        deg = test_skeleton.nx_graph.degree()
        num_of_branch_nodes = len([n for n in deg if deg[n] > 1])
        num_of_endnodes = len([n for n in deg if deg[n] == 1])
        num_of_nodes_with_no_edge = len([n for n in deg if deg[n] == 0])

        test_skeleton.interpolate_edges(step_size=1, VP_type='phys')
        self.assertEqual(num_of_branch_nodes, len([n for n in deg if deg[n] > 1]))
        self.assertEqual(num_of_endnodes, len([n for n in deg if deg[n] == 1]))
        self.assertEqual(num_of_nodes_with_no_edge, len([n for n in deg if deg[n] == 0]))

        # Test interpolation with voxel step size = 2.
        # voxel
        test_skeleton = Skeleton(voxel_size=[10., 10., 20.])
        test_skeleton.initialize_from_datapoints(nodes_pos_phys, vp_type_voxel=False, edgelist=edges)
        deg = test_skeleton.nx_graph.degree()
        num_of_branch_nodes = len([n for n in deg if deg[n] > 1])
        num_of_endnodes = len([n for n in deg if deg[n] == 1])
        num_of_nodes_with_no_edge = len([n for n in deg if deg[n] == 0])
        exp_nodes = test_skeleton.nx_graph.nodes()
        exp_edges = test_skeleton.nx_graph.edges()

        test_skeleton.interpolate_edges(step_size=2, VP_type='voxel')
        self.assertEqual(num_of_branch_nodes, len([n for n in deg if deg[n] > 1]))
        self.assertEqual(num_of_endnodes, len([n for n in deg if deg[n] == 1]))
        self.assertEqual(num_of_nodes_with_no_edge, len([n for n in deg if deg[n] == 0]))
        self.assertNotEqual(exp_nodes, test_skeleton.nx_graph.nodes())
        self.assertNotEqual(exp_edges, test_skeleton.nx_graph.edges())

        # phys
        test_skeleton = Skeleton(voxel_size=[10., 10., 20.])
        test_skeleton.initialize_from_datapoints(nodes_pos_phys, vp_type_voxel=False, edgelist=edges)
        deg = test_skeleton.nx_graph.degree()
        num_of_branch_nodes = len([n for n in deg if deg[n] > 1])
        num_of_endnodes = len([n for n in deg if deg[n] == 1])
        num_of_nodes_with_no_edge = len([n for n in deg if deg[n] == 0])
        exp_nodes = test_skeleton.nx_graph.nodes()
        exp_edges = test_skeleton.nx_graph.edges()

        test_skeleton.interpolate_edges(step_size=2, VP_type='phys')
        self.assertEqual(num_of_branch_nodes, len([n for n in deg if deg[n] > 1]))
        self.assertEqual(num_of_endnodes, len([n for n in deg if deg[n] == 1]))
        self.assertEqual(num_of_nodes_with_no_edge, len([n for n in deg if deg[n] == 0]))
        self.assertNotEqual(exp_nodes, test_skeleton.nx_graph.nodes())
        self.assertNotEqual(exp_edges, test_skeleton.nx_graph.edges())

        # Test interpolation with voxel step size too big and check that the graph does not change at all.
        # voxel
        test_skeleton = Skeleton(voxel_size=[10., 10., 20.])
        test_skeleton.initialize_from_datapoints(nodes_pos_phys, vp_type_voxel=False, edgelist=edges)
        exp_nodes = test_skeleton.nx_graph.nodes()
        exp_edges = test_skeleton.nx_graph.edges()

        test_skeleton.interpolate_edges(step_size=50, VP_type='voxel')
        self.assertEqual(exp_nodes, test_skeleton.nx_graph.nodes())
        self.assertEqual(exp_edges, test_skeleton.nx_graph.edges())

        # phys
        test_skeleton = Skeleton(voxel_size=[10., 10., 20.])
        test_skeleton.initialize_from_datapoints(nodes_pos_phys, vp_type_voxel=False, edgelist=edges)
        exp_nodes = test_skeleton.nx_graph.nodes()
        exp_edges = test_skeleton.nx_graph.edges()

        test_skeleton.interpolate_edges(step_size=200, VP_type='phys')
        self.assertEqual(exp_nodes, test_skeleton.nx_graph.nodes())
        self.assertEqual(exp_edges, test_skeleton.nx_graph.edges())
    def test_evaluate_segmentation_with_gt_skeletons(self):
        segmentation = np.zeros((20, 20, 20))
        segmentation[:, :, 0:7] = 1
        segmentation[:, :, 7:10] = 2
        segmentation[:, :, 10:16] = 3
        segmentation[:, :, 16:20] = 4
        segmentation[:, 0:5, :16] = 5

        sk_left = Skeleton()
        nodes = np.array([[10, 3, 0], [
            10, 3, 20
        ]])  # skeleton that passes y-left part of the cube (ID 5 and 4)
        edges = [[0, 1]]
        sk_left.initialize_from_datapoints(datapoints=nodes,
                                           vp_type_voxel=True,
                                           edgelist=edges,
                                           datapoints_type='nparray')
        sk_left.interpolate_edges()

        sk_right = Skeleton()
        nodes = np.array([[10, 7, 0], [
            10, 7, 20
        ]])  # skeleton that passes y-right part of the cube (ID 1 2 3 4 5)
        edges = [[0, 1]]
        sk_right.initialize_from_datapoints(datapoints=nodes,
                                            vp_type_voxel=True,
                                            edgelist=edges,
                                            datapoints_type='nparray')
        sk_right.interpolate_edges()
        sk_con = SkeletonContainer(skeletons=[sk_left, sk_right])
        num_merges, num_splits, SV_merges, bigraph, new_seg = evaluate_segmentation_with_gt_skeletons(
            segmentation, sk_con, return_new_seg=True, size_thres=0)

        expected_SV_merger = [5]
        self.assertEqual(1, num_merges)
        self.assertEqual(4, num_splits)
        self.assertTrue(set(expected_SV_merger), SV_merges)
        # Since the two skeletons have a common supervoxel, the resulting new segmentation should have exactly
        # one connected component.
        self.assertEqual(1, len(np.unique(new_seg)))
    def test_getNodeIdsOfEndpoints(self):
        # test correct number and node id of edges for branched graph
        test_skeleton_end = Skeleton(voxel_size=np.array([1.,1.,2.]))
        nodes_pos_phys_end = np.array([[0, 0, 0], [10., 5., 5.], [20., 10., 10.], [30., 15., 15.],[20.,20.,20.],[25., 25., 25.],[30., 30., 30.]])
        edges_end = [(0, 1), (1, 2), (2, 3), (1,4), (4, 5), (1, 6)]
        test_skeleton_end.initialize_from_datapoints(nodes_pos_phys_end, vp_type_voxel=False, edgelist=edges_end)

        all_endpoints = test_skeleton_end.get_node_ids_of_endpoints()
        self.assertEqual(len(all_endpoints), 4)
        self.assertEqual(set(all_endpoints), set([0,3,5,6]))

        # test correct number and node id of edges for cyclic graph
        test_skeleton_end = Skeleton(voxel_size=np.array([1.,1.,2.]))
        nodes_pos_phys_end = np.array([[0, 0, 0], [5., 5., 5.], [10., 10., 10.], [15., 15., 15.],[20.,20.,20.],[25., 25., 25.],[30., 30., 30.]])
        edges_end = [(0, 1), (1, 2), (2, 3), (3,4), (4, 5), (5, 6), (6, 0)]
        test_skeleton_end.initialize_from_datapoints(nodes_pos_phys_end, vp_type_voxel=False, edgelist=edges_end)

        all_endpoints = test_skeleton_end.get_node_ids_of_endpoints()
        self.assertEqual(len(all_endpoints), 0)
        self.assertEqual(set(all_endpoints), set([]))

        # test that does return an empty list, if only one single node is given in the connected graph
        test_skeleton_end = Skeleton(voxel_size=np.array([1.,1.,2.]))
        nodes_pos_phys_end = np.array([[5., 5., 5.]])
        test_skeleton_end.initialize_from_datapoints(nodes_pos_phys_end, vp_type_voxel=False, edgelist=None)

        all_endpoints = test_skeleton_end.get_node_ids_of_endpoints()
        self.assertEqual(len(all_endpoints), 0)