docs: def grid_bp_data (bps, items, mask=True):
      """Given a bunch of scalars associated with intensity-type basepols, place
      them onto a grid. There should be only two polarizations represented (e.g.
      RR, LL); baselines for one of them will be put into the upper triangle of
      the grid, while baselines for the other will be put into the lower triangle.
  
      `bps` is an iterable that yields a superset of all bps to be gridded.
  
      `items` is an iterable that yields tuples of (bp, value). (`bps` is
      therefore a bit redundant with it, but this structure makes it so that we
      don't need to iterate of `items` twice, which can be convenient.)
  
      Returns: (pol1, pol2, ants, data), where
  
      pol1
        The polarization gridded into the upper triangle
      pol2
        The polarization gridded into the lower triangle
      ants
        An array of the antenna numbers seen in `bps`
      data
        An n-by-n grid of the values, where n is the size of `ants`. Unsampled
        basepols are filled with NaNs, or masked if `mask` is True.
  
      The basepol (ant1, ant2, pol1) is gridded into `data[i1,i2]`, where `i1`
      is the index of `ant1` in `ants`, etc. The basepol (ant1, ant2, pol2) is
      gridded into `data[i2,i1]`.
  
      """
      seen_ants = set ()
      seen_pols = set ()
  
      for ant1, ant2, pol in (bp_to_aap (bp) for bp in bps):
          seen_ants.add (ant1)
          seen_ants.add (ant2)
          seen_pols.add (pol)
  
      if len (seen_pols) != 2:
          raise Exception ('can only work with 2 polarizations')
      pol1, pol2 = sorted (seen_pols)
  
      seen_ants = np.array (sorted (seen_ants))
      ant_map = dict ((a, i) for (i, a) in enumerate (seen_ants))
  
      data = None
      n = len (seen_ants)
  
      for bp, value in items:
          if data is None:
              data = np.empty ((n, n), dtype=np.result_type (value))
              data.fill (np.nan)
  
          ant1, ant2, pol = bp_to_aap (bp)
          i1 = ant_map[ant1]
          i2 = ant_map[ant2]
  
          if pol == pol1:
              data[i1,i2] = value
          else:
              data[i2,i1] = value
  
      if mask:
          data = np.ma.MaskedArray (data, ~np.isfinite (data))
  
      return pol1, pol2, seen_ants, data