code: def adjust_bad_positions(
      positions_per_page,
      good_positions=None,
      pos_check_signif_level=0.05,
  ):
      """
      Try to adjust the positions in the dict `positions_per_page` (page number -> positions mapping) by determining the
      mean column widths of "good positions" and comparing the individual columns widths with these mean values using a
      Chi squared test. If the p-value of the test is below `pos_check_signif_level`, the positions of the page are
      considered bad and will be fixed by using the mean differences instead.
      If `good_positions` is set to None, the list of good positions will be determined using those that match the median
      number of all positions.
      """
  
      if not 0 < pos_check_signif_level <= 1:
          raise ValueError("`signif_level` must be in range (0,1]")
  
      if not positions_per_page or not isinstance(
          positions_per_page, dict
      ):
          raise ValueError(
              "`positions_per_page` must be a non-empty dict"
          )
  
      median_n_positions = int(
          np.median([len(pos) for pos in positions_per_page.values()])
      )
  
      if not good_positions:
          # no "good" positions list given -> create a list of good positions be selecting those that match the
          # median number of all positions
          good_positions = [
              pos
              for pos in positions_per_page.values()
              if len(pos) == median_n_positions
          ]
  
      if not good_positions:  # no "good" positions -> cannot proceed
          return positions_per_page
  
      mean_widths = np.diff(
          [np.mean(pos) for pos in zip(*good_positions)]
      )
      if min(mean_widths) < 0:
          raise ValueError("invalid positions: got negative mean width")
  
      adjusted_positions = {}
      for p_num, positions in positions_per_page.items():
          if (
              len(positions) != median_n_positions
              or min(np.diff(positions)) < 0
          ):
              # num. of positions not as expected or negative widths
              p_val = 0
          else:  # expected num. of positions. check if they match
              widths = np.diff(positions)
              _, p_val = chisquare(widths, mean_widths)
  
          if p_val < pos_check_signif_level:
              # the adjusted positions will be the first given position as offset plus the mean positions derived from
              # the "good" positions
              positions = np.concatenate(
                  [
                      [positions[0]],
                      positions[0] + np.cumsum(mean_widths),
                  ]
              )
  
          adjusted_positions[p_num] = positions
  
      return adjusted_positions
  
file_path: pdftabextract/pdftabextract/clustering.py
imports: import itertools
  import numpy
  from scipy.stats import chisquare
  from pdftabextract import logger
  from pdftabextract.common import fill_array_a_with_values_from_b, sorted_by_attr, flatten_list, update_text_dict_dim, DIRECTION_HORIZONTAL, DIRECTION_VERTICAL
label_desc: Use image node_id 7 for calling a global function with example usage: adjust_bad_positions(positions_per_page, good_positions, pos_check_signif_level) and returns: adjusted_positions, positions_per_page