docs: 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