def from_scarlet(self, scarlet_model_dir, pixel_scale=HSC_pixel_scale): from galsim import Image, InterpolatedImage from galsim.interpolant import Lanczos with open(scarlet_model_dir, 'rb') as f: blend, info, mask = dill.load(f) f.close() assert ''.join(blend.observations[0].channels) == self.channels # Crop the mask new_weights = blend.observations[0].weights x1, y1 = blend.sources[0].bbox.origin[1:] x2 = x1 + blend.sources[0].bbox.shape[1:][0] y2 = y1 + blend.sources[0].bbox.shape[1:][1] mask = mask.astype(bool)[x1:x2, y1:y2] mask += np.sum((new_weights[:, x1:x2, y1:y2] == 0), axis=0).astype(bool) mockgal_img = blend.sources[0].get_model() * np.repeat( ~mask[np.newaxis, :, :], len(self.channels), axis=0) gal_image = np.empty_like(self.bkg.images) for i in range(len(mockgal_img)): mockgal = InterpolatedImage(Image(mockgal_img[i], dtype=float), scale=pixel_scale, x_interpolant=Lanczos(3)) gal_image[i] = mockgal.drawImage(scale=pixel_scale, nx=self.bkg.images.shape[2], ny=self.bkg.images.shape[1]).array # Generate variance map ra, dec = self.bkg.wcs.wcs_pix2world(self.bkg.images.shape[2] / 2, self.bkg.images.shape[1] / 2, 0) info = { 'ra': ra, 'dec': dec, 'scarlet_model': scarlet_model_dir, 'model_type': 'scarlet_lsbg_wvlt_0.5' } mock_model = Data(images=gal_image, variances=None, masks=None, channels=self.channels, wcs=None, weights=None, psfs=self.bkg.psfs, info=info) # Finished!!! self.model = mock_model # model only has `images`, `channels`, `psfs`, and `info`! self.set_mock() # mock has other things, including modified variances.
def resize_mask(self, f, method='iraf', order=5, cval=0.0): '''Zoom/Resize the mask of Celestial object. f > 1 means the mask will be resampled (finer)! f < 1 means the mask will be degraded. Parameters: f (float): the positive factor of zoom. If 0 < f < 1, the mask will be resized to smaller one. method (str): interpolation method. Use 'lanczos' or 'spline' or 'iraf'. order (int): the order Lanczos interpolation (>0). cval (scalar): value to fill the edges. Default is NaN. Returns: shift_image: ndarray. ''' if method == 'lanczos': try: # try to import galsim from galsim import degrees, Angle from galsim.interpolant import Lanczos from galsim import Image, InterpolatedImage from galsim.fitswcs import AstropyWCS except: raise ImportError( '# Import `galsim` failed! Please check if `galsim` is installed!' ) assert (order > 0) and isinstance( order, int), 'order of ' + method + ' must be positive interger.' galimg = InterpolatedImage(Image(self.mask, dtype=float), scale=self.pixel_scale, x_interpolant=Lanczos(order)) ny, nx = self.mask.shape result = galimg.drawImage( scale=self.pixel_scale / f, nx=round(nx * f), ny=round(ny * f)) #, wcs=AstropyWCS(self.wcs)) self.wcs = self._resize_wcs(self.image, self.wcs, f) self._image = result.array self.shape = self.mask.shape self._wcs_header_merge() self.pixel_scale /= f return result.array elif method == 'iraf': self.save_to_fits('./_temp.fits', 'mask') if f > 1: magnify('./_temp.fits', './_resize_temp.fits', f, f) else: blkavg('./_temp.fits', './_resize_temp.fits', 1 / f, 1 / f, option='sum') hdu = fits.open('./_resize_temp.fits') self.mask = hdu[0].data self.shape = hdu[0].data.shape self.header = hdu[0].header self.wcs = wcs.WCS(self.header) self.pixel_scale /= f hdu.close() imdelete('./*temp.fits') else: raise ValueError( "# Not supported interpolation method. Use 'lanczos' or 'iraf'." )
def shift_mask(self, dx, dy, method='iraf', order=5, cval=0.0): '''Shift the mask of Celestial object. Parameters: dx, dy (float): shift distance (in pixel) along x (horizontal) and y (vertical). Note that elements in one row has the same y but different x. Example: dx = 2 is to shift the image "RIGHT", dy = 3 is to shift the image "UP". method (str): interpolation method. Use 'lanczos' or 'spline' or 'iraf' order (int): the order of spline interpolation (within 0-5) or Lanczos interpolation (>0). cval (scalar): value to fill the edges. Default is NaN. Returns: shift_mask: ndarray. ''' ny, nx = self.mask.shape if abs(dx) > nx or abs(ny) > ny: raise ValueError('# Shift distance is beyond the image size.') if method == 'lanczos': try: # try to import galsim from galsim import degrees, Angle from galsim.interpolant import Lanczos from galsim import Image, InterpolatedImage from galsim.fitswcs import AstropyWCS except: raise ImportError( '# Import `galsim` failed! Please check if `galsim` is installed!' ) # Begin shift assert (order > 0) and isinstance( order, int), 'order of ' + method + ' must be positive interger.' galimg = InterpolatedImage(Image(self.mask, dtype=float), scale=self.pixel_scale, x_interpolant=Lanczos(order)) galimg = galimg.shift(dx=dx * self.pixel_scale, dy=dy * self.pixel_scale) result = galimg.drawImage(scale=self.pixel_scale, nx=nx, ny=ny) #, wcs=AstropyWCS(self.wcs)) self._mask = result.array # Change the WCS of image hdr = copy.deepcopy(self.header) hdr['CRPIX1'] += dx hdr['CRPIX2'] += dy self.header = hdr self.wcs = wcs.WCS(hdr) self._wcs_header_merge() return result.array elif method == 'iraf': self.save_to_fits('./_temp.fits', 'mask') imshift('./_temp.fits', './_shift_temp.fits', dx, dy, interp_type='poly3', boundary_type='constant') hdu = fits.open('./_shift_temp.fits') self.mask = hdu[0].data self.shape = hdu[0].data.shape self.header = hdu[0].header self.wcs = wcs.WCS(self.header) hdu.close() imdelete('./*temp.fits') else: raise ValueError( "# Not supported interpolation method. Use 'lanczos' or 'iraf'." )
def resize_mask(self, f, method='lanczos', order=5, cval=0.0): '''Zoom/Resize the mask of Stack object. Cautious: don't use ['bicubic', 'nearest', 'cubic', 'bilinear'] methods! They don't conserve the total flux! Parameters: f (float): the positive factor of zoom. If 0 < f < 1, the image will be resized to smaller one. method (str): interpolation method. Use 'lanczos' or 'spline'. order (int): the order of spline interpolation (within 0-5) or Lanczos interpolation (>0). cval (scalar): value to fill the edges. Default is NaN. Returns: shift_image: ndarray. ''' if method == 'lanczos': try: # try to import galsim from galsim import degrees, Angle from galsim.interpolant import Lanczos from galsim import Image, InterpolatedImage from galsim.fitswcs import AstropyWCS except: raise ImportError( '# Import `galsim` failed! Please check if `galsim` is installed!' ) assert (order > 0) and isinstance( order, int), 'order of ' + method + ' must be positive interger.' galimg = InterpolatedImage(Image(self.mask, dtype=float), scale=0.168, x_interpolant=Lanczos(order)) #galimg = galimg.magnify(f) ny, nx = self.mask.shape result = galimg.drawImage( scale=0.168 / f, nx=round(nx * f), ny=round(ny * f)) #, wcs=AstropyWCS(self.wcs)) self.wcs = self._resize_wcs(self.mask, self.wcs, f) self._mask = result.array self.shape = self.mask.shape return result.array elif method == 'spline': from scipy.ndimage import zoom assert 0 < order <= 5 and isinstance( order, int), 'order of ' + method + ' must be within 0-5.' result = zoom(self.mask, float(f), order=order, mode='constant', cval=cval) self._mask = result self.wcs = self._resize_wcs(self.mask, self.wcs, f) self.shape = self.mask.shape return result elif method in ['bicubic', 'nearest', 'cubic', 'bilinear']: raise Warning( "Cautious! Don't use ['bicubic', 'nearest', 'cubic', 'bilinear'] methods! They don't conserve the total flux!" ) try: from scipy.misc import imresize except: raise ImportError( '# Import `scipy.misc.imresize` failed! This function may no longer be included in scipy!' ) result = imresize(self.mask, float(f), interp=method) self._mask = result.astype(float) self.wcs = self._resize_wcs(self.mask, self.wcs, f) self.shape = self.mask.shape return result.astype(float) else: raise ValueError( "# Not supported interpolation method. Use 'lanczos' or 'spline'." )
def shift_mask(self, dx, dy, method='lanczos', order=5, cval=0.0): '''Shift the mask of Stack object. Parameters: dx, dy (float): shift distance (in pixel) along x (horizontal) and y (vertical). Note that elements in one row has the same y but different x. Example: dx = 2 is to shift the image "RIGHT", dy = 3 is to shift the image "UP". method (str): interpolation method. Use 'lanczos' or 'spline'. order (int): the order of spline interpolation (within 0-5) or Lanczos interpolation (>0). cval (scalar): value to fill the edges. Default is NaN. Returns: shift_mask: ndarray. ''' if not hasattr(self, 'mask'): raise AttributeError("This `Stack` object doesn't have `mask`!") ny, nx = self.image.shape if abs(dx) > nx or abs(ny) > ny: raise ValueError('# Shift distance is beyond the image size.') if method == 'lanczos': try: # try to import galsim from galsim import degrees, Angle from galsim.interpolant import Lanczos from galsim import Image, InterpolatedImage from galsim.fitswcs import AstropyWCS except: raise ImportError( '# Import `galsim` failed! Please check if `galsim` is installed!' ) # Begin shift assert (order > 0) and isinstance( order, int), 'order of ' + method + ' must be positive interger.' galimg = InterpolatedImage(Image(self.mask, dtype=float), scale=0.168, x_interpolant=Lanczos(order)) galimg = galimg.shift(dx=dx * 0.168, dy=dy * 0.168) result = galimg.drawImage(scale=0.168, nx=nx, ny=ny) #, wcs=AstropyWCS(self.wcs)) self._mask = (result.array > 0.5).astype(float) # Change the WCS of image hdr = copy.deepcopy(self.header) hdr['CRPIX1'] += dx hdr['CRPIX2'] += dy self.header = hdr self.wcs = wcs.WCS(hdr) return result.array elif method == 'spline': from scipy.ndimage.interpolation import shift assert 0 < order <= 5 and isinstance( order, int), 'order of ' + method + ' must be within 0-5.' result = shift(self.mask, [dy, dx], order=order, mode='constant', cval=cval) self._mask = (result > 0.5).astype(float) # Change the WCS of image hdr = copy.deepcopy(self.header) hdr['CRPIX1'] += dx hdr['CRPIX2'] += dy self.header = hdr self.wcs = wcs.WCS(hdr) return result else: raise ValueError( "# Not supported interpolation method. Use 'lanczos' or 'spline'." )
def rotate_mask(self, angle, method='lanczos', order=5, reshape=False, cval=0.0): '''Rotate the mask of Stack object. Parameters: angle (float): rotation angle in degress, counterclockwise. method (str): interpolation method. Use 'lanczos', 'spline', 'cubic', 'bicubic', 'nearest' or 'bilinear'. order (int): the order of spline interpolation (within 0-5) or Lanczos interpolation (>0). reshape (bool): if True, the output shape is adapted so that the rorated image is contained completely in the output array. cval (scalar): value to fill the edges. Default is NaN. Returns: rotate_image: ndarray. ''' angle = angle % 360 if not hasattr(self, 'mask'): raise AttributeError("This `Stack` object doesn't have `mask`!") else: if method == 'lanczos': try: from galsim import degrees, Angle from galsim.interpolant import Lanczos from galsim import Image, InterpolatedImage from galsim.fitswcs import AstropyWCS except: raise ImportError( '# Import `galsim` failed! Please check if `galsim` is installed!' ) # Begin rotation assert (order > 0) and isinstance( order, int), 'order of ' + method + ' must be positive interger.' galimg = InterpolatedImage(Image(self.mask, dtype=float), scale=0.168, x_interpolant=Lanczos(order)) galimg = galimg.rotate(Angle(angle, unit=degrees)) ny, nx = self.image.shape result = galimg.drawImage(scale=0.168, nx=nx, ny=ny) #, wcs=AstropyWCS(self.wcs)) self._mask = (result.array > 0.5).astype(float) self.wcs = self._rotate_wcs(self.mask, self.wcs, angle) return result.array elif method == 'spline': from scipy.ndimage.interpolation import rotate as rt assert 0 < order <= 5 and isinstance( order, int), 'order of ' + method + ' must be within 0-5.' result = rt(self.mask, -angle, order=order, mode='constant', cval=cval, reshape=reshape) self._mask = (result > 0.5).astype(float) self.wcs = self._rotate_wcs(self.mask, self.wcs, angle) return result elif method in ['bicubic', 'nearest', 'cubic', 'bilinear']: raise Warning( "Cautious! Don't use ['bicubic', 'nearest', 'cubic', 'bilinear'] methods! They don't conserve the total flux!" ) try: from scipy.misc import imrotate except: raise ImportError( '# Import `scipy.misc.imrotate` failed! This function may no longer be included in scipy!' ) result = imrotate(self.mask, -angle, interp=method) self._mask = (result > 0.5).astype(float) self.wcs = self._rotate_wcs(self.mask, self.wcs, angle) return result else: raise ValueError( "# Not supported interpolation method. Use 'lanczos', 'spline', 'cubic', \ 'bicubic', 'nearest', 'bilinear'.")
def resize_mask(self, f, method='cubic', order=5, cval=0.0): ''' Zoom/Resize the mask of Celestial object. f > 1 means the mask will be resampled (finer)! f < 1 means the mask will be degraded. Parameters: f (float): the positive factor of zoom. If 0 < f < 1, the mask will be resized to smaller one. method (str): interpolation method. Use 'lanczos', 'cubic', 'quintic' or 'iraf'. First three methods require ``GalSim`` installed. Other methods are now consistent with "iraf" results. order (int): the order Lanczos interpolation (>0). cval (float): value to fill the edges. Default is 0. Returns: resize_mask (ndarray): resized image. The "mask" attribute of ``Celestial`` class will also be changed accordingly. ''' if not hasattr(self, 'mask'): raise ValueError("This object doesn't have mask yet!") if method == 'lanczos' or method == 'cubic' or method == 'quintic': try: # try to import galsim from galsim import degrees, Angle from galsim.interpolant import Lanczos from galsim import Image, InterpolatedImage from galsim.fitswcs import AstropyWCS except: raise ImportError( '# Import `galsim` failed! Please check if `galsim` is installed!' ) assert (order > 0) and isinstance( order, int), 'order of ' + method + ' must be positive interger.' if method == 'lanczos': galimg = InterpolatedImage(Image(self.mask, dtype=float), scale=self.pixel_scale, x_interpolant=Lanczos(order)) else: galimg = InterpolatedImage(Image(self.mask, dtype=float), scale=self.pixel_scale, x_interpolant=method) ny, nx = self.mask.shape if f > 1: result = galimg.drawImage(scale=self.pixel_scale / f, nx=int((nx - 1) * f + 1), ny=int((ny - 1) * f + 1)) self.header = self._resize_header_wcs(self.mask, f) self.header['CRPIX1'] += (1 - f * 1) self.header['CRPIX2'] += (1 - f * 1) self._mask = result.array self.shape = self.mask.shape self.header['NAXIS1'] = result.array.shape[1] self.header['NAXIS2'] = result.array.shape[0] self.pixel_scale /= f self.wcs = wcs.WCS(self.header) #### Cautious! The following block could be wrong! #### ## Probably you'll need extra shift of image dshift = 2 * (1 - f * 1) % 0.5 self.shift_mask(dshift, dshift, method='spline') # We don't want to shift wcs. self.header['CRPIX1'] -= dshift self.header['CRPIX2'] -= dshift self.wcs = wcs.WCS(self.header) #### Cautious! The above block could be wrong! #### else: from math import ceil b = round(1 / f) nxout = ceil(nx / b) nyout = ceil(ny / b) result = galimg.drawImage(scale=self.pixel_scale * b, nx=nxout, ny=nyout) self.header = self._resize_header_wcs(self.mask, f) self.header['CRPIX1'] += 0.5 - 1 / b / 2 self.header['CRPIX2'] += 0.5 - 1 / b / 2 self._mask = result.array self.shape = self.image.shape self.header['NAXIS1'] = result.array.shape[1] self.header['NAXIS2'] = result.array.shape[0] self.pixel_scale *= b self.wcs = wcs.WCS(self.header) #### Cautious! The following block could be wrong! #### ## Probably you'll need extra shift of image dshift = 0.5 - 1 / b / 2 self.shift_image(-dshift, -dshift, method='spline') # We don't want to shift wcs. self.header['CRPIX1'] -= dshift self.header['CRPIX2'] -= dshift self.wcs = wcs.WCS(self.header) #### Cautious! The above block could be wrong! #### return self.mask elif method == 'iraf': self.save_to_fits('./_temp.fits', 'mask') if f > 1: magnify('./_temp.fits', './_resize_temp.fits', f, f) else: blkavg('./_temp.fits', './_resize_temp.fits', round(1 / f), round(1 / f), option='sum') hdu = fits.open('./_resize_temp.fits') self.mask = hdu[0].data self.shape = hdu[0].data.shape self.header = hdu[0].header self.wcs = wcs.WCS(self.header) self.pixel_scale /= f hdu.close() imdelete('./*temp.fits') return self.mask else: raise ValueError( "# Not supported interpolation method. Use 'lanczos', 'spline' or 'iraf'." )
def shift_mask(self, dx, dy, method='spline', order=5, cval=0.0): '''Shift the mask of Celestial object. Parameters: dx (float): shift distance (in pixel) along x (horizontal). Note that elements in one row has the same y but different x. Example: dx = 2 is to shift the mask "RIGHT" (as seen in DS9), dy = 3 is to shift the image "UP". dy (float): shift distance (in pixel) along y (vertical). Note that elements in one row has the same y but different x. Example: dx = 2 is to shift the mask "RIGHT" (as seen in DS9), dy = 3 is to shift the image "UP". method (str): interpolation method. Use 'spline', lanczos' or 'iraf'. If using 'iraf', default interpolation is 'poly3. 'Lanczos' requires ``GalSim`` installed. order (int): the order of Spline or Lanczos interpolation (>0). cval (float): value to fill the edges. Default is 0. Returns: shift_mask (ndarray): shifted mask. The "mask" attribute of ``Celestial`` class will also be changed accordingly. ''' ny, nx = self.mask.shape if abs(dx) > nx or abs(ny) > ny: raise ValueError('# Shift distance is beyond the image size.') if method == 'lanczos' or method == 'cubic' or method == 'quintic': try: # try to import galsim from galsim import degrees, Angle from galsim.interpolant import Lanczos from galsim import Image, InterpolatedImage from galsim.fitswcs import AstropyWCS except: raise ImportError( '# Import ``galsim`` failed! Please check if ``galsim`` is installed!' ) # Begin shift assert (order > 0) and isinstance( order, int), 'order of ' + method + ' must be positive interger.' if method == 'lanczos': galimg = InterpolatedImage(Image(self.image, dtype=float), scale=self.pixel_scale, x_interpolant=Lanczos(order)) else: galimg = InterpolatedImage(Image(self.image, dtype=float), scale=self.pixel_scale, x_interpolant=method) galimg = galimg.shift(dx=dx * self.pixel_scale, dy=dy * self.pixel_scale) result = galimg.drawImage(scale=self.pixel_scale, nx=nx, ny=ny) #, wcs=AstropyWCS(self.wcs)) self._mask = result.array # Change the WCS of image hdr = copy.deepcopy(self.header) hdr['CRPIX1'] += dx hdr['CRPIX2'] += dy self.header = hdr self.wcs = wcs.WCS(self.header) return result.array elif method == 'iraf': self.save_to_fits('./_temp.fits', 'mask') imshift('./_temp.fits', './_shift_temp.fits', dx, dy, interp_type='poly3', boundary_type='constant') hdu = fits.open('./_shift_temp.fits') self.mask = hdu[0].data self.shape = hdu[0].data.shape self.header = hdu[0].header self.wcs = wcs.WCS(self.header) hdu.close() imdelete('./*temp.fits') return self.mask elif method == 'spline': from scipy.ndimage.interpolation import shift assert 0 < order <= 5 and isinstance( order, int), 'order of ' + method + ' must be within 0-5.' result = shift(self.mask, [dy, dx], order=order, mode='constant', cval=cval) self._mask = result # Change the WCS of image hdr = copy.deepcopy(self.header) hdr['CRPIX1'] += dx hdr['CRPIX2'] += dy self.header = hdr self.wcs = wcs.WCS(self.header) return result else: raise ValueError( "# Not supported interpolation method. Use 'lanczos' or 'iraf'." )
def resize_image(self, f, method='cubic', order=3, cval=0.0): ''' Zoom/Resize the image of Celestial object. f > 1 means the image will be resampled (finer)! f < 1 means the image will be degraded. Parameters: f (float): the positive factor of zoom. If 0 < f < 1, the image will be resized to smaller one. method (str): interpolation method. Use 'spline', 'iraf', or 'lanczos', 'cubic', 'quintic'. We recommend using 'spline' or 'iraf. The last three methods require ``GalSim`` installed. Other methods are now consistent with "iraf" results. order (int): the order Lanczos interpolation (>0). cval (float): value to fill the edges. Default is 0. Returns: resize_image (ndarray): resized image. The "image" attribute of ``Celestial`` class will also be changed accordingly. ''' if method == 'lanczos' or method == 'cubic' or method == 'quintic': try: # try to import galsim from galsim import degrees, Angle from galsim.interpolant import Lanczos from galsim import Image, InterpolatedImage from galsim.fitswcs import AstropyWCS except: raise ImportError( '# Import `galsim` failed! Please check if `galsim` is installed!' ) assert (order > 0) and isinstance( order, int), 'order of ' + method + ' must be positive interger.' if method == 'lanczos': galimg = InterpolatedImage(Image(self.image, dtype=float), scale=self.pixel_scale, x_interpolant=Lanczos(order)) else: galimg = InterpolatedImage(Image(self.image, dtype=float), scale=self.pixel_scale, x_interpolant=method) ny, nx = self.image.shape if f > 1: result = galimg.drawImage(scale=self.pixel_scale / f, nx=int((nx - 1) * f + 1), ny=int((ny - 1) * f + 1)) self.header = self._resize_header_wcs(f) self.header['CRPIX1'] += (1 - f * 1) self.header['CRPIX2'] += (1 - f * 1) self._image = result.array self.shape = self.image.shape self.header['NAXIS1'] = result.array.shape[1] self.header['NAXIS2'] = result.array.shape[0] self.pixel_scale /= f self.wcs = wcs.WCS(self.header) #### Cautious! The following block could be wrong! #### ## Probably you'll need extra shift of image dshift = 2 * (1 - f * 1) % 0.5 self.shift_image(dshift, dshift, method='spline') # We don't want to shift wcs. self.header['CRPIX1'] -= dshift self.header['CRPIX2'] -= dshift self.wcs = wcs.WCS(self.header) #### Cautious! The above block could be wrong! #### else: from math import ceil b = round(1 / f) nxout = ceil(nx / b) nyout = ceil(ny / b) result = galimg.drawImage(scale=self.pixel_scale * b, nx=nxout, ny=nyout) self.header = self._resize_header_wcs(f) self.header['CRPIX1'] += 0.5 - 1 / b / 2 self.header['CRPIX2'] += 0.5 - 1 / b / 2 self._image = result.array self.shape = self.image.shape self.header['NAXIS1'] = result.array.shape[1] self.header['NAXIS2'] = result.array.shape[0] self.pixel_scale *= b self.wcs = wcs.WCS(self.header) #### Cautious! The following block could be wrong! #### ## Probably you'll need extra shift of image dshift = 0.5 - 1 / b / 2 self.shift_image(-dshift, -dshift, method='spline') # We don't want to shift wcs. self.header['CRPIX1'] -= dshift self.header['CRPIX2'] -= dshift self.wcs = wcs.WCS(self.header) #### Cautious! The above block could be wrong! #### return self.image elif method == 'iraf': self.save_to_fits('./_temp.fits', 'image') if f > 1: magnify('./_temp.fits', './_resize_temp.fits', f, f) else: blkavg('./_temp.fits', './_resize_temp.fits', round(1 / f), round(1 / f), option='sum') try: hdu = fits.open('./_resize_temp.fits') except Exception as e: raise ValueError( 'Interpolation using IRAF filed with error "{}". \n Please try another interpolation method!' .format(e)) self.image = hdu[0].data self.shape = hdu[0].data.shape self.header = hdu[0].header #### Remove redundant PC keywords ### for i in self.header['PC*'].keys(): del self.header[i] ##################################### self.wcs = wcs.WCS(self.header) self.pixel_scale /= f hdu.close() imdelete('./*temp.fits') return self.image elif method == 'spline': ny, nx = self.image.shape if f > 1: from scipy import ndimage assert 0 < order <= 5 and isinstance( order, int), 'order of ' + method + ' must be within 0-5.' nx_zoomed = (nx - 1) * f + 1 f_eff = nx_zoomed / nx result = ndimage.zoom(self.image, f_eff, order=order) result *= 1 / (f_eff**2 ) # Multiplying by this factor to conserve flux self.header = self._resize_header_wcs(f) #self.header['CRPIX1'] += (1 - f * 1) #self.header['CRPIX2'] += (1 - f * 1) self._image = result self.shape = self.image.shape self.header['NAXIS1'] = result.shape[1] self.header['NAXIS2'] = result.shape[0] self.pixel_scale /= f self.wcs = wcs.WCS(self.header) #### Cautious! The following block could be wrong! #### ## Probably you'll need extra shift of image dshift = 2 * (1 - f * 1) % 0.5 self.shift_image(dshift, dshift, method='spline') # We don't want to shift wcs. self.header['CRPIX1'] -= dshift self.header['CRPIX2'] -= dshift self.wcs = wcs.WCS(self.header) #### Cautious! The above block could be wrong! #### else: b = round(1 / f) ny_bin = int(ny / b) nx_bin = int(nx / b) shape = (ny_bin, b, nx_bin, b) x_crop = int(nx_bin * b) y_crop = int(ny_bin * b) result = self.image[0:y_crop, 0:x_crop].reshape(shape).sum(3).sum(1) self.header = self._resize_header_wcs(f) self.header['CRPIX1'] += 0.5 - 1 / b / 2 self.header['CRPIX2'] += 0.5 - 1 / b / 2 self._image = result self.shape = self.image.shape self.header['NAXIS1'] = result.shape[1] self.header['NAXIS2'] = result.shape[0] self.pixel_scale *= b self.wcs = wcs.WCS(self.header) else: raise ValueError( "# Not supported interpolation method. Use 'lanczos', 'spline' or 'iraf'." )
def gen_mock_lsbg(self, galaxy, zp=HSC_zeropoint, pixel_scale=HSC_pixel_scale, verbose=True): ''' Generate mock low surface brightness galaxies. ''' import galsim from galsim import Angle, Image, InterpolatedImage, degrees from galsim.fitswcs import AstropyWCS from galsim.interpolant import Lanczos big_fft_params = galsim.GSParams(maximum_fft_size=20000) if not isinstance(galaxy['comp'], list): galaxy['comp'] = list(galaxy['comp']) if len(galaxy['comp']) == 1: galaxy['flux_fraction'] = [1.0] # print some information if verbose: print('# Generating mock galaxy.') print(' - Total components: ', len(galaxy['comp'])) print(' - Types: ', [c['model'].__name__ for c in galaxy['comp']]) print(' - Flux fraction: ', galaxy['flux_fraction']) # Empty canvas field = np.empty_like(self.bkg.images[0]) model_images = np.empty_like(self.bkg.images) # Calculate RA, DEC of the mock galaxy y_cen = self.bkg.images.shape[2] / 2 x_cen = self.bkg.images.shape[1] / 2 galaxy['ra'], galaxy['dec'] = self.bkg.wcs.wcs_pix2world( x_cen, y_cen, 0) # Calculate flux based on i-band mag and SED i_band_loc = np.argwhere(np.array(list(self.channels)) == 'i')[0][ 0] # location of i-band in `channels` seds = np.array([c['sed'] for c in galaxy['comp']]) # Normalize SED w.r.t i-band seds /= seds[:, i_band_loc][:, np.newaxis] tot_sed = np.sum(seds * np.array(galaxy['flux_fraction'])[:, np.newaxis], axis=0) for i, band in enumerate(self.channels): galaxy[f'{band}mag'] = -2.5 * np.log10(tot_sed[i]) + galaxy['imag'] if verbose: print(f' - Magnitude in {self.channels}: ', [round(galaxy[f'{band}mag'], 1) for band in self.channels]) #### Star generating mock galaxy in each band #### for i, band in enumerate(self.channels): # griz # Random number seed # This random number seed should be fixed across bands!!! rng = galsim.BaseDeviate(23333) # Sky background level sky_SB = 29 # mag/arcsec^2 sky_level = 10**((zp - sky_SB) / 2.5) # counts / arcsec^2 # Define the PSF interp_psf = InterpolatedImage(Image(self.bkg.psfs[i] / self.bkg.psfs[i].sum(), dtype=float), scale=pixel_scale, x_interpolant=Lanczos(3)) # Total flux for all components tot_flux = 10**((zp - galaxy[f'{band}mag']) / 2.5) gal_list = [] for k, comp in enumerate(galaxy['comp']): # Define the galaxy gal = comp['model'](**comp['model_params'], gsparams=big_fft_params) gal_shape = galsim.Shear( **comp['shear_params']) # Shear the galaxy gal = gal.shear(gal_shape) if 'shift' in comp.keys(): # Shift the center gal = gal.shift(comp['shift']) # Add star forming knots if 'n_knots' in comp.keys() and comp['n_knots'] > 0: if not 'knots_frac' in comp.keys(): raise KeyError( '`knots_frac` must be provided to generate star forming knots!' ) else: if 'knots_sed' in comp.keys(): knot_frac = comp['knots_frac'] * \ (comp['knots_sed'] / np.sum(comp['knots_sed']))[i] else: knot_frac = comp['knots_frac'] * 0.25 # flat SED knots = galsim.RandomKnots( comp['n_knots'], half_light_radius=comp['model_params'] ['half_light_radius'], flux=knot_frac, rng=rng) gal = galsim.Add([gal, knots]) gal = gal.withFlux(tot_flux * galaxy['flux_fraction'][k]) # Get Flux gal_list.append(gal) # Adding all components together gal = galsim.Add(gal_list) # Convolve galaxy with PSF final = galsim.Convolve([gal, interp_psf]) # Draw the image with a particular pixel scale. gal_image = final.drawImage(scale=pixel_scale, nx=field.shape[1], ny=field.shape[0]) # Add noise sky_sigma = hsc_sky[f'{band}'] / 3.631 * \ 10**((zp - 22.5) / 2.5) * pixel_scale**2 noise = galsim.GaussianNoise(rng, sigma=sky_sigma) # gal_image.addNoise(noise) # Generate mock image model_img = gal_image.array model_images[i] = model_img # Generate variance map mock_model = Data(images=model_images, variances=None, masks=None, channels=self.channels, wcs=None, weights=None, psfs=self.bkg.psfs, info=galaxy) # Finished!!! self.model = mock_model # model only has `images`, `channels`, `psfs`, and `info`! self.set_mock() # mock has other things, including modified variances.