docs: def correct_spurious_inversions(scaffolds, criterion="colinear"):
      """Invert bins based on orientation neighborhoods. Neighborhoods can be
      defined by three criteria:
  
      -a 'cis' neighborhood is a group of bins belonging to the same initial
      contig
      -a 'colinear' neighborhood is a 'cis' neighborhood where bins are
      ordered the same way they were on the initial contig
      -a 'contiguous' neighborhood is a 'colinear' neighborhood where all bins
      are exactly consecutive, i.e. the end position of each bin matches the
      starting position of the next bin
  
      This function looks for such neighborhoods and orients all bins in it
      according to the majority orientation.
  
      An example with three inversions, one for each criterion:
  
          >>> scaffolds = {
          ...     "scaffold1": [
          ...         ["contig1", 1, 100, 200, 1],
          ...         ["contig1", 2, 200, 300, 1],
          ...         ["contig1", 3, 300, 400, -1], # <-- inversion (contiguous)
          ...         ["contig1", 4, 400, 500, 1],
          ...         ["contig1", 10, 1500, 1605, 1],
          ...         ["contig1", 12, 1750, 1850, -1], # <-- inversion (colinear)
          ...         ["contig1", 23, 2100, 2499, 1],
          ...         ["contig1", 28, 2850, 3000, 1],
          ...         ["contig1", 0, 0, 100, -1], # <-- inversion (cis)
          ...         ["contig2", 554, 1850, 1900, -1],
          ...     ],
          ... }
  
      With the 'cis' criterion, pretty much all bins from "contig1" get inverted
      to the majority orientation (+):
  
          >>> sc_cis = correct_spurious_inversions(scaffolds, "cis")
          >>> for my_bin in sc_cis['scaffold1']:
          ...     print(my_bin)
          ...
          ['contig1', 1, 100, 200, 1]
          ['contig1', 2, 200, 300, 1]
          ['contig1', 3, 300, 400, 1]
          ['contig1', 4, 400, 500, 1]
          ['contig1', 10, 1500, 1605, 1]
          ['contig1', 12, 1750, 1850, 1]
          ['contig1', 23, 2100, 2499, 1]
          ['contig1', 28, 2850, 3000, 1]
          ['contig1', 0, 0, 100, 1]
          ['contig2', 554, 1850, 1900, -1]
  
      With the 'colinear' criterion, the bin ['contig1', 0, 0, 100, -1] is
      treated as a different neighborhood from the rest (as it is not colinear
      with the other bins from 'contig1') and remains untouched:
  
          >>> sc_colinear = correct_spurious_inversions(scaffolds, "colinear")
          >>> for my_bin in sc_colinear['scaffold1']:
          ...     print(my_bin)
          ...
          ['contig1', 1, 100, 200, 1]
          ['contig1', 2, 200, 300, 1]
          ['contig1', 3, 300, 400, 1]
          ['contig1', 4, 400, 500, 1]
          ['contig1', 10, 1500, 1605, 1]
          ['contig1', 12, 1750, 1850, 1]
          ['contig1', 23, 2100, 2499, 1]
          ['contig1', 28, 2850, 3000, 1]
          ['contig1', 0, 0, 100, -1]
          ['contig2', 554, 1850, 1900, -1]
  
      With the 'contiguous' criterion, the ['contig1', 12, 1750, 1850, -1] breaks
      with the contiguous region spanning from 100 to 400 bp on 'contig1' and
      so is treated as a different neighborhood as well:
  
          >>> sc_cont = correct_spurious_inversions(scaffolds, "contiguous")
          >>> for my_bin in sc_cont['scaffold1']:
          ...     print(my_bin)
          ...
          ['contig1', 1, 100, 200, 1]
          ['contig1', 2, 200, 300, 1]
          ['contig1', 3, 300, 400, 1]
          ['contig1', 4, 400, 500, 1]
          ['contig1', 10, 1500, 1605, 1]
          ['contig1', 12, 1750, 1850, -1]
          ['contig1', 23, 2100, 2499, 1]
          ['contig1', 28, 2850, 3000, 1]
          ['contig1', 0, 0, 100, -1]
          ['contig2', 554, 1850, 1900, -1]
  
      Note that 'contig2' remains untouched at all times since bins in it are
      never in the same neighborhood as those from 'contig1'.
  
      """
  
      scaffolds = format_info_frags(scaffolds)
      new_scaffolds = {}
  
      def is_cis(bin1, bin2):
          return bin1[0] == bin2[0]
  
      def is_contiguous(bin1, bin2):
          return is_cis(bin1, bin2) and bin1[3] == bin2[2]
  
      def is_colinear(bin1, bin2):
          return is_cis(bin1, bin2) and bin1[3] <= bin2[2]
  
      condition_callables = {
          "cis": is_cis,
          "colinear": is_colinear,
          "contiguous": is_contiguous,
      }
      block_test = condition_callables.get(criterion, "colinear")
  
      for name, scaffold in scaffolds.items():
          new_scaffold = []
  
          block_cumulative_ori = 0
  
          if len(scaffold) > 2:
              current_bin = scaffold[0]
              block_buffer = []
              for my_bin in scaffold:
  
                  if not block_buffer:
                      new_bin = copy.deepcopy(my_bin)
                      block_buffer.append(new_bin)
                      block_cumulative_ori = my_bin[-1]
                      continue
  
                  elif not block_test(current_bin, my_bin):
                      for my_buf_bin in block_buffer:
                          new_bin = copy.deepcopy(my_buf_bin)
                          if block_cumulative_ori >= 0:
                              new_bin[-1] = 1
                          else:
                              new_bin[-1] = -1
                          new_scaffold.append(new_bin)
                      block_cumulative_ori = my_bin[-1]
                      current_bin = copy.deepcopy(my_bin)
                      block_buffer = copy.deepcopy([my_bin])
  
                  else:
                      block_cumulative_ori += my_bin[-1]
                      new_bin = copy.deepcopy(my_bin)
                      block_buffer.append(new_bin)
                      current_bin = my_bin
  
              for my_bin in block_buffer:
                  new_bin = copy.deepcopy(my_bin)
                  if block_cumulative_ori >= 0:
                      new_bin[-1] = 1
                  else:
                      new_bin[-1] = -1
                  new_scaffold.append(new_bin)
              new_scaffolds[name] = copy.deepcopy(new_scaffold)
  
          else:
              new_scaffolds[name] = copy.deepcopy(scaffold)
  
      return new_scaffolds