code: def getColRowWithinChannel(self, ra, dec, ch, wantZeroOffset=False,
                                 allowIllegalReturnValues=True):
          
          # How close is a given ra/dec to the origin of a KeplerModule?
          x, y = self.defaultMap.skyToPix(ra, dec)
          kepModule = self.getChannelAsPolygon(ch)
          r = np.array([x[0],y[0]]) - kepModule.polygon[0, :]
  
          v1 = kepModule.polygon[1, :] - kepModule.polygon[0, :]
          v3 = kepModule.polygon[3, :] - kepModule.polygon[0, :]
  
          # Divide by |v|^2 because you're normalising v and r
          colFrac = np.dot(r, v1) / np.linalg.norm(v1)**2
          rowFrac = np.dot(r, v3) / np.linalg.norm(v3)**2
  
          # This is where it gets a little hairy. The channel "corners"
          # supplied to me actually represent points 5x5 pixels inside
          # the science array. Which isn't what you'd expect.
          # These magic numbers are the pixel numbers of the corner
          # edges given in fov.txt
          col = colFrac*(1106-17) + 17
          row = rowFrac*(1038-25) + 25
  
          if not allowIllegalReturnValues:
              if not self.colRowIsOnSciencePixel(col, row):
                  msg = "Request position %7f %.7f " % (ra, dec)
                  msg += "does not lie on science pixels for channel %i " % (ch)
                  msg += "[ %.1f %.1f]" % (col, row)
                  raise ValueError(msg)
  
          # Convert from zero-offset to one-offset coords
          if not wantZeroOffset:
              col += 1
              row += 1
  
          return (col, row)
docs: Returns (col, row) given a (ra, dec) coordinate and channel number.