def test_sincshift(self): a = np.zeros((3, 5)) self.assertEqual(a.shape, util.sincshift(a, 0.1, 0.0).shape) self.assertEqual(a.shape, util.sincshift(a, 0.0, 0.1).shape) self.assertEqual(a.shape, util.sincshift(a, 0.1, 0.1).shape) self.assertEqual(a.shape, util.sincshift2d(a, 0.1, 0.0).shape) self.assertEqual(a.shape, util.sincshift2d(a, 0.0, 0.1).shape) self.assertEqual(a.shape, util.sincshift2d(a, 0.1, 0.1).shape)
def test_sincshift(self): a = np.zeros((3,5)) self.assertEqual(a.shape, util.sincshift(a, 0.1, 0.0).shape) self.assertEqual(a.shape, util.sincshift(a, 0.0, 0.1).shape) self.assertEqual(a.shape, util.sincshift(a, 0.1, 0.1).shape) self.assertEqual(a.shape, util.sincshift2d(a, 0.1, 0.0).shape) self.assertEqual(a.shape, util.sincshift2d(a, 0.0, 0.1).shape) self.assertEqual(a.shape, util.sincshift2d(a, 0.1, 0.1).shape)
def _xypix(self, ispec, wavelength): """ Return xslice, yslice, pix for PSF at spectrum ispec, wavelength """ assert 0 <= ispec < self.nspec xc, yc = self.xy(ispec, wavelength) scale = self._scale #- shorthand #- Calculate offset into CCD pixel xoffset = int(xc * scale) % scale yoffset = int(yc * scale) % scale #- Place high res spot into grid aligned with CCD pixels ny, nx = self._spot.shape A = np.zeros(shape=(ny+scale, nx+scale)) A[yoffset:yoffset+ny, xoffset:xoffset+nx] = self._spot ccdpix = rebin_image(A, scale) #- Fractional high-res pixel offset #- This can be slow; is it really necessary? dxx = ((xc * scale) % scale - xoffset) / scale dyy = ((yc * scale) % scale - yoffset) / scale ccdpix = sincshift(ccdpix, dxx, dyy) #- sinc shift can cause negative ringing, so clip and re-normalize ccdpix = ccdpix.clip(0) ccdpix /= np.sum(ccdpix) #- Find where the [0,0] pixel goes on the CCD xccd = int(xc - ccdpix.shape[1]/2 + 1) yccd = int(yc - ccdpix.shape[0]/2 + 1) xx = slice(xccd, xccd+ccdpix.shape[1]) yy = slice(yccd, yccd+ccdpix.shape[0]) return xx, yy, ccdpix
def _xypix(self, ispec, wavelength): """ Return xslice, yslice, pix for PSF at spectrum ispec, wavelength """ assert 0 <= ispec < self.nspec xc, yc = self.xy(ispec, wavelength) scale = self._scale #- shorthand #- Calculate offset into CCD pixel xoffset = int(xc * scale) % scale yoffset = int(yc * scale) % scale #- Place high res spot into grid aligned with CCD pixels ny, nx = self._spot.shape A = np.zeros(shape=(ny + scale, nx + scale)) A[yoffset:yoffset + ny, xoffset:xoffset + nx] = self._spot ccdpix = rebin_image(A, scale) #- Fractional high-res pixel offset #- This can be slow; is it really necessary? dxx = ((xc * scale) % scale - xoffset) / scale dyy = ((yc * scale) % scale - yoffset) / scale ccdpix = sincshift(ccdpix, dxx, dyy) #- sinc shift can cause negative ringing, so clip and re-normalize ccdpix = ccdpix.clip(0) ccdpix /= np.sum(ccdpix) #- Find where the [0,0] pixel goes on the CCD xccd = int(xc - ccdpix.shape[1] // 2 + 1) yccd = int(yc - ccdpix.shape[0] // 2 + 1) xx = slice(xccd, xccd + ccdpix.shape[1]) yy = slice(yccd, yccd + ccdpix.shape[0]) return xx, yy, ccdpix
def _xypix(self, ispec, wavelength, ispec_cache=None, iwave_cache=None): """ Evaluate PSF for a given spectrum and wavelength returns xslice, yslice, pixels[yslice, xslice] """ #- Get fiber group and scaling factors for this spectrum igroup = self.xyscale['IGROUP'][ispec] x0 = self.xyscale['X0'][ispec] xscale = self.xyscale['XSCALE'][ispec] y0 = self.xyscale['Y0'][ispec] yscale = self.xyscale['YSCALE'][ispec] #- Get x and y centroid x, y = self.xy(ispec, wavelength) #- Rescale units xx = xscale * (x - x0) yy = yscale * (y - y0) #- Generate PSF image at (x,y) psfimage = np.zeros(self.psfimage.shape[2:4]) for i in range(self.psfimage.shape[1]): nx = self.nexp['XEXP'][i] ny = self.nexp['YEXP'][i] psfimage += xx**nx * yy**ny * self.psfimage[igroup, i] #- Sinc Interpolate dx = x - int(round(x)) dy = y - int(round(y)) psfimage = sincshift(psfimage, dx, dy) #- Check boundaries ny, nx = psfimage.shape ix = int(round(x)) iy = int(round(y)) xmin = max(0, ix-nx//2) xmax = min(self.npix_x, ix+nx//2+1) ymin = max(0, iy-ny//2) ymax = min(self.npix_y, iy+ny//2+1) if ix < nx//2: psfimage = psfimage[:, nx//2-ix:] if iy < ny//2: psfimage = psfimage[ny//2-iy:, :] if ix+nx//2+1 > self.npix_x: dx = self.npix_x - (ix+nx//2+1) psfimage = psfimage[:, :dx] if iy+ny//2+1 > self.npix_y: dy = self.npix_y - (iy+ny//2+1) psfimage = psfimage[:dy, :] xslice = slice(xmin, xmax) yslice = slice(ymin, ymax) #- Clip negative values psfimage[psfimage<0] = 0.0 #- Normalize integral to 1.0 psfimage /= psfimage.sum() assert xslice.stop-xslice.start == psfimage.shape[1] assert yslice.stop-yslice.start == psfimage.shape[0] return xslice, yslice, psfimage
def _xypix(self, ispec, wavelength): """ Evaluate PSF for a given spectrum and wavelength returns xslice, yslice, pixels[yslice, xslice] """ #- Get fiber group and scaling factors for this spectrum igroup = self.xyscale['IGROUP'][ispec] x0 = self.xyscale['X0'][ispec] xscale = self.xyscale['XSCALE'][ispec] y0 = self.xyscale['Y0'][ispec] yscale = self.xyscale['YSCALE'][ispec] #- Get x and y centroid x, y = self.xy(ispec, wavelength) #- Rescale units xx = xscale * (x - x0) yy = yscale * (y - y0) #- Generate PSF image at (x,y) psfimage = np.zeros(self.psfimage.shape[2:4]) for i in range(self.psfimage.shape[1]): nx = self.nexp['XEXP'][i] ny = self.nexp['YEXP'][i] psfimage += xx**nx * yy**ny * self.psfimage[igroup, i] #- Sinc Interpolate dx = x - int(round(x)) dy = y - int(round(y)) psfimage = sincshift(psfimage, dx, dy) #- Check boundaries ny, nx = psfimage.shape ix = int(round(x)) iy = int(round(y)) xmin = max(0, ix - nx // 2) xmax = min(self.npix_x, ix + nx // 2 + 1) ymin = max(0, iy - ny // 2) ymax = min(self.npix_y, iy + ny // 2 + 1) if ix < nx // 2: psfimage = psfimage[:, nx // 2 - ix:] if iy < ny // 2: psfimage = psfimage[ny // 2 - iy:, :] if ix + nx // 2 + 1 > self.npix_x: dx = self.npix_x - (ix + nx // 2 + 1) psfimage = psfimage[:, :dx] if iy + ny // 2 + 1 > self.npix_y: dy = self.npix_y - (iy + ny // 2 + 1) psfimage = psfimage[:dy, :] xslice = slice(xmin, xmax) yslice = slice(ymin, ymax) #- Clip negative values psfimage[psfimage < 0] = 0.0 #- Normalize integral to 1.0 psfimage /= psfimage.sum() assert xslice.stop - xslice.start == psfimage.shape[1] assert yslice.stop - yslice.start == psfimage.shape[0] return xslice, yslice, psfimage