Random SPR, with prune and regraft edges chosen randomly, and
        lengths drawn uniformly from the available edge lengths.

        N1: disallow_sibling_sprs prevents sprs that don't alter the topology
        of the tree

def rspr(self, disallow_sibling_sprs=False,
             keep_entire_edge=False, rescale=False):
        """ Random SPR, with prune and regraft edges chosen randomly, and
        lengths drawn uniformly from the available edge lengths.

        N1: disallow_sibling_sprs prevents sprs that don't alter the topology
        of the tree """

        starting_length = self.tree._tree.length()

        excl = [self.tree._tree.seed_node.edge]  # exclude r
        if disallow_sibling_sprs:
            excl.extend(self._check_single_outgroup())
        prune_edge, l1 = self.tree.map_event_onto_tree(excl)
        if keep_entire_edge:
            l1 = prune_edge.length

        prune_edge_child_nodes = prune_edge.head_node.preorder_iter()
        excl.extend([node.edge for node in prune_edge_child_nodes])

        if disallow_sibling_sprs:
            sibs = [node.edge for node in prune_edge.head_node.sister_nodes()]
            par = prune_edge.tail_node.edge
            sibs.append(par)
            for edge in sibs:
                if edge not in excl:
                    excl.append(edge)
            if set(self.tree._tree.preorder_edge_iter()) - set(excl) == set([]):
                print(repr(self.tree))
                print(self.tree._tree.as_ascii_plot())
                # print(edges[prune_edge])
                raise Exception('No non-sibling sprs available')

        regraft_edge, l2 = self.tree.map_event_onto_tree(excl)

        # edges, nodes, redges, rnodes = self.tree._name_things()
        # print(edges[prune_edge], l1, edges[regraft_edge], l2)
        self.spr(prune_edge, l1, regraft_edge, l2)
        if rescale:
            self.tree.scale(starting_length / self.tree.length())
            self.tree._dirty = True