docs: def sackin(self, normalize='leaves'):
          '''Compute the Sackin balance index of this ``Tree``
  
          Args:
              ``normalize`` (``str``): How to normalize the Sackin index (if at all)
  
              * ``None`` to not normalize
  
              * ``"leaves"`` to normalize by the number of leaves
  
              * ``"yule"`` to normalize to the Yule model
  
              * ``"pda"`` to normalize to the Proportional to Distinguishable Arrangements model
  
          Returns:
              ``float``: Sackin index (either normalized or not)
          '''
          num_nodes_from_root = dict(); sackin = 0; num_leaves = 0
          for node in self.traverse_preorder():
              num_nodes_from_root[node] = 1
              if not node.is_root():
                  num_nodes_from_root[node] += num_nodes_from_root[node.parent]
              if node.is_leaf():
                  num_nodes_from_root[node] -= 1; sackin += num_nodes_from_root[node]; num_leaves += 1
          if normalize is None or normalize is False:
              return sackin
          elif not isinstance(normalize,str):
              raise TypeError("normalize must be None or a string")
          normalize = normalize.lower()
          if normalize == 'leaves':
              return float(sackin)/num_leaves
          elif normalize == 'yule':
              x = sum(1./i for i in range(2, num_leaves+1))
              return (sackin - (2*num_leaves*x)) / num_leaves
          elif normalize == 'pda':
              return sackin/(num_leaves**1.5)
          else:
              raise RuntimeError("normalize must be None, 'leaves', 'yule', or 'pda'")