def cutFits(f, ra, dec, size=(4 * u.arcsec, 4 * u.arcsec), sigma=False): if not os.path.isfile(f): return None try: if len(size) != 2: return except Exception as e: print( "\033[31msize must be an int or length-2 list/tuple/array\033[0m" ) frame = fFile[0].header['SYSTEM'].strip() p = SkyCoord(ra=ra * u.degree, dec=dec * u.degree, frame=frame.lower()) sizeQuant = u.Quantity(size, u.arcsec) wcs = WCS(header=fFile[0].header) try: cutout = Cutout2D(fFile[0].data, p, sizeQuant, wcs=wcs) if sigma: sigma = getSigma(fFile) sigma_cutout = Cutout2D(sigma, p, size, wcs=wcs) return cutout.data, sigma_cutout.data else: return cutout.data except NoOverlapError: print( 'Ra, Dec not inside frame for Ra:' + ' {ra}, Dec: {dec}, and frame: {f}'.format( ra=ra, dec=dec, f=fFile[0] ) ) return False
def _get_local_cutout(self): """Fetch cutout data via local FITS images (e.g. RACS / VLASS).""" fields = self._find_image() assert len( fields ) > 0, f"No fields located at {self.position.ra:.2f}, {self.position.dec:.2f}" closest = fields[fields.dist_field_centre == fields.dist_field_centre.min()].iloc[0] image_path = SURVEYS.loc[self.survey]['images'] if self.survey == 'vlass': filepath = f'{closest.epoch}/{closest.tile}/{closest.image}/{closest.filename}' image_path = vlass_path elif 'racs' in self.survey: pol = self.survey[-1] if on_system == 'ada': filepath = f'RACS_test4_1.05_{closest.field}.fits' else: filepath = f'RACS_{closest.field}.EPOCH00.{pol}.fits' elif 'vast' in self.survey: pattern = re.compile(r'vastp(\dx*)([IV])') epoch = pattern.sub(r'\1', self.survey) pol = pattern.sub(r'\2', self.survey) filepath = f'VAST_{closest.field}.EPOCH0{epoch}.{pol}.fits' else: filepath = f'*{closest.field}*0.restored.fits' try: self.filepath = glob.glob(image_path + filepath)[0] except IndexError: raise FITSException( f'Could not match {self.survey} image filepath: \n{image_path + filepath}' ) with fits.open(self.filepath) as hdul: self.header, data = hdul[0].header, hdul[0].data wcs = WCS(self.header, naxis=2) self.mjd = Time(self.header['DATE']).mjd try: cutout = Cutout2D(data[0, 0, :, :], self.position, self.radius * u.deg, wcs=wcs) except IndexError: cutout = Cutout2D(data, self.position, self.radius * u.deg, wcs=wcs) self.data = cutout.data * 1000 self.wcs = cutout.wcs if 'racs' in self.survey or 'vast' in self.survey: self.pos_err = SURVEYS.loc[self.basesurvey].pos_err self._get_source() else: # Probably using vlass, yet to include aegean catalogs self.plot_sources = False self.plot_neighbours = False
def plot_residual_image(old_res, new_res, mode): nres = fits.getdata(new_res) ores = fits.getdata(old_res) cmap = 'hot' cnorm = SymLogNorm(linthresh=30, linscale=0.5) # # Zoomed out # fig = plt.figure(figsize=(10, 5)) ax1 = plt.subplot(121, aspect='equal') im = plt.imshow(ores, cmap=cmap, norm=cnorm) plt.title('Old ' + mode) plt.gca().invert_yaxis() plt.subplot(122, sharex=ax1, sharey=ax1, aspect='equal') plt.imshow(nres, cmap=cmap, norm=cnorm) plt.title('New ' + mode) plt.gca().invert_yaxis() plt.subplots_adjust(right=0.8) cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7]) fig.colorbar(im, cax=cbar_ax) # # Zoomed in. # c_pos = [500, 550] c_siz = [200, 200] nres_c = Cutout2D(nres, c_pos, c_siz) ores_c = Cutout2D(ores, c_pos, c_siz) cnorm = SymLogNorm(linthresh=30, linscale=0.5, vmin=nres_c.data.min(), vmax=nres_c.data.max()) fig2 = plt.figure(figsize=(10, 5)) ax2 = plt.subplot(121, aspect='equal') im = plt.imshow(ores_c.data, extent=np.array(ores_c.bbox_original)[::-1].flatten(), cmap=cmap, norm=cnorm) plt.title('Old ' + mode) plt.gca().invert_yaxis() plt.subplot(122, sharex=ax2, sharey=ax2, aspect='equal') plt.imshow(nres_c.data, extent=np.array(nres_c.bbox_original)[::-1].flatten(), cmap=cmap, norm=cnorm) plt.title('New ' + mode) plt.gca().invert_yaxis() plt.subplots_adjust(right=0.8) cbar_ax = fig2.add_axes([0.85, 0.15, 0.05, 0.7]) fig2.colorbar(im, cax=cbar_ax) plt.show() return
def detect(self): cs = [SkyCoord(ra,dec,unit='deg') for ra,dec in zip(self.ras,self.decs)] cw = WCS(self.cheader) if self.wv > 240: cw_n = WCS(self.nheader) size = u.Quantity((self.pixsize,self.pixsize),u.degree) fluxes = [Cutout2D(self.cmap,c,size,wcs = cw).data for c in cs] else: size = if self.wv > 240: noises = [Cutout2D(self.noise,c,size,wcs = cw_n).data for c in cs] else: noises = [self.noise for i in range(len(cs))] dd_fluxes = [] dd_noises = [] dd_ras = [] dd_decs = [] dd_mags = [] for i in range(len(fluxes)): if fluxes[i] > 2*noises[i]: dd_fluxes.append(fluxes[i]) dd_noises.append(noises[i]) dd_ras.append(self.ras[i]) dd_decs.append(self.decs[i]) dd_mags.append(self.mags[i]) results = Table([dd_ras,dd_decs,dd_fluxes,dd_noises,dd_mags],names = ['RA','DEC','flux','noise','PetroMag_i']) return results
def Load_image(self): if self.file is None: raise ValueError('No file specified') try: hdu = fits.open(self.file) except: raise ValueError('Could not load {}'.format(self.file)) self.date = self.file.split('tess')[-1].split('-')[0] self.sector = self.file.split('-')[1] self.camera = self.file.split('-')[2] self.ccd = self.file.split('-')[3] self.hdu = hdu[1] self.header = hdu[1].header data = hdu[1].data err = hdu[2].data self.wcs = WCS(hdu[1].header) cut = Cutout2D(data, (1024 + 44, 1024), 2048, wcs=self.wcs) self.image = cut.data wcs = cut.wcs err = Cutout2D(err, (1024 + 44, 1024), 2048).data self.noise = err print('Successfully loaded {}'.format(self.file)) return
def get_next_im(im_locs, obj_loc, min_visible_region, cutout_dims): for i in im_locs: print(i) im = fits.open(i)[-1] wcs = WCS(im.header) pix_xy = wcs.all_world2pix(obj_loc, 1)[0] #Pixel coords of obj if ((min_visible_region != 0)&(min_visible_region !=(0,0))): #minimal visible region wanted try: #Should only succeed if all pixels in this cutout have values dummy = Cutout2D(im.data, pix_xy, min_visible_region, mode='strict') except: #print('Image at obsjd {} rejected due to NaN close to im center'.format(im.header['OBSJD'])) continue #Start next i in loop cutout = Cutout2D(im.data, pix_xy, cutout_dims, mode='partial', wcs=wcs) #Get relevand image data not available in the cutout im_center = [round(pix_xy[0]), round(pix_xy[1])] if 'ZTFData/ref' in i: imtype = 'ref' date = ' ' if im.header['DBFID']==1: obsfilter = 'ZTF_g' elif im.header['DBFID']==2: obsfilter = 'ZTF_r' else: obsfilter = 'ZTF_i' else: imtype = 'dif' date = time.Time(im.header['OBSJD'], format='jd') obsfilter = im.header['FILTER'] #yield 1 item which is a list of required items yield [cutout, imtype, date, obsfilter, im_center]
def make_cutout(image, WCS_img, position, size=100.0, size_in_arcsec=False, show_img=False): ''' Makes cutout. ''' # get coordinate frame WCS_img.sip = None # define position if size_in_arcsec: size = u.Quantity((size, size), u.arcsec) cutout = Cutout2D(image, position, size, wcs=WCS_img) else: size = (size * u.pixel, size * u.pixel) cutout = Cutout2D( image, WCS_img.wcs_world2pix([[position.ra.deg, position.dec.deg]], 1)[0], size) if show_img: img = pl.imshow(cutout.data, origin='lower') pl.axis('off') pl.show() return (cutout)
def get_next_im(target): ''' Generator function for making the animation The next image in the list is opened, the target location is found and cut out, and the cutout is tested. If the tests are passed successfully, the cutout will be used in the next frame of the animation. Else a warning is issued before continueing to the next image. 1st test: Is the minimum visible region fully observed (e.g. no NaN)? 2nd test: Are there positive values? (prevents weird negative frames found when using previous versions of the code) Parameters: target (anim_target): Object to animate. Yields: list: A list containing the rotated cutout, rotation details, and some metadata. ''' for i in target.im_locs: #Open next image and check if it meets the animation requirements. im = fits.open(i)[-1] wcs = WCS(im.header) pix_xy = wcs.all_world2pix([(target.ra, target.dec)], 0)[0] #1st test if (('/sci/' in i) & (target.min_visible!=0) & (target.min_visible!=(0,0))): try: #Should only succeed if all pixels in this cutout have values dummy = Cutout2D(im.data, pix_xy, target.min_visible, mode='strict') except: #Can't fully fill min visible region print('Image at obsjd {} rejected due to NaN'\ ' close to im center'.format(im.header['OBSJD'])) continue #Start next i in loop cutout = Cutout2D(im.data, pix_xy, target.cutout_dims, mode='partial', wcs=wcs) #2nd test if np.nanmax(cutout.data) < 0: print('Image at obsjd {} rejected due to all values being negative\ '.format(im.header['OBSJD'])) continue #Get needed info from the header (Give entire header in the future?) if 'ZTFData/ref' in i: imtype = 'ref' else: imtype = 'dif' #Correct image orientation / being mirrored if needed. immat, rots, flip, resid = find_orientation(cutout) im_center = [round(pix_xy[0]), round(pix_xy[1])] #yield a list of items required by the subplots yield [immat, imtype, im.header, rots, flip, resid, im_center]
def getTailPeaks(tailTimeSteps, noradid, mwa, sat, ts, args): """ finds all the peak pixels in tail using gaussian fit Parameters ---------- tailTimeSteps : the list of tail time steps noradid : the norad id of the satellite mwa : observer object sat : the satellite object ts : time object Returns ------- x_array : array of x pixels of tail y_array : array of y pixels of tail ra_array : array of ra of tail dec_array : array of dec of tail """ x_array, y_array = [], [] x_err_array, y_err_array = [], [] y = np.linspace(0, 4, 5) x = np.linspace(0, 4, 5) x, y = np.meshgrid(x, y) for t in tailTimeSteps: hdu = fits.open("Neg" + args.filePrefix + "-t" + str(t).zfill(4) + ".fits") UTCTime = datetime.strptime(hdu[0].header['DATE-OBS'], '%Y-%m-%dT%H:%M:%S.%f') data = hdu[0].data data = maskData(data, UTCTime, mwa, sat, wcs, ts) if np.all(data == 0): print("file full of zeros") print("aborting....") sys.exit(0) row, col = np.where(data == np.min(data)) beam_cutout = Cutout2D(beam, (col, row), (5 ,5 )) cutout = Cutout2D(data, (col, row), (5,5)) temp = cutout.data / beam_cutout.data temp /= np.nansum(temp) initial_guess = (temp[1,1], 1, 1, 2) popt, pconv = opt.curve_fit(twoD_Gaussian, (x, y), temp.ravel(), p0=initial_guess) perr = np.sqrt(np.diag(pconv)) mu_x, mu_y = popt[1], popt[2] sigma_x, sigma_y = perr[1], perr[2] solX = float(col + (mu_x - 2)) solY = float(row + (mu_y - 2)) x_array.append(solX) y_array.append(solY) x_err_array.append(sigma_x) y_err_array.append(sigma_y) return x_array, y_array, x_err_array, y_err_array
def low_bkg_ref(self): files = self.imagefiles summed = np.zeros(len(files)) * np.nan ex = self.hduext for i in range(len(files)): hdu = fits.open(files[i]) data = hdu[ex].data wcs = WCS(hdu[ex].header) cut = Cutout2D(data, (1024 + 44, 1024), 2048, wcs=wcs) data = cut.data wcs = cut.wcs data[data <= 0] = np.nan if np.nansum(abs(data)) > 0: summed[i] = np.nansum(abs(data)) lim = np.percentile(summed[np.isfinite(summed)], 5) ind = np.where((summed < lim))[0] good = files[ind] goods = np.zeros((len(good), 2048, 2048)) var = np.zeros((len(good), 2048, 2048)) mjd = np.zeros(len(good)) i = 0 sat_count = np.zeros_like(data) for g in good: hdu = fits.open(g) data = hdu[ex].data wcs = WCS(hdu[ex].header) cut = Cutout2D(data, (1024 + 44, 1024), 2048, wcs=wcs) data = cut.data wcs = cut.wcs goods[i] = data e = hdu[2].data cut = Cutout2D(e, (1024 + 44, 1024), 2048) data = cut.data var[i] = data**2 jd = hdu[1].header['TSTART'] + hdu[1].header['BJDREFI'] mjd[i] = Time(jd, format='jd', scale='tdb').mjd sat_count[data > 4.8E4 - 500] += 1 i += 1 ref = np.nanmedian(goods, axis=0) var = np.nanmedian(var, axis=0) hdu[1].header['MJD'] = (np.nanmean(mjd), 'stacked') hdu[1].header['NIMAGES'] = (str(len(good)), 'number of images stacked') sats = sat_count / len(good) >= (0.05) self.hdu = hdu[1] self.header = hdu[1].header self.image = ref self.noise = np.sqrt(var) return
def image_snippet(image, center, width=50, axis=None, fig=None, is_mask=False, pad_black=False, **kwargs): """ Display a subsection of an image about a center. Parameters ---------- image : numpy array The full image from which a section is to be taken. center : list-like The location of the center of the cutout. width : int, optional Width of the cutout, in pixels. axis : matplotlib.Axes instance, optional Axis on which the image should be displayed. fig : matplotlib.Figure, optional Figure on which the image should be displayed. is_mask : bool, optional Set to ``True`` if the image is a mask, i.e. all values are either zero or one. pad_black : bool, optional If ``True``, pad edges of the image with zeros to fill out width if the slice is near the edge. """ if pad_black: sub_image = Cutout2D(image, center, width, mode='partial', fill_value=0) else: # Return a smaller subimage if extent goes out side image sub_image = Cutout2D(image, center, width, mode='trim') show_image(sub_image.data, cmap='gray', ax=axis, fig=fig, show_colorbar=False, show_ticks=False, is_mask=is_mask, **kwargs)
def Reference_image(files,FITS=False): summed = np.zeros(len(files)) * np.nan for i in range(len(files)): hdu = fits.open(files[i]) data = hdu[1].data wcs = WCS(hdu[1].header) cut = Cutout2D(data,(1024+44,1024),2048,wcs=wcs) data = cut.data wcs = cut.wcs data[data <= 0] = np.nan if np.nansum(abs(data)) > 0: summed[i] = np.nansum(abs(data)) lim = np.percentile(summed[np.isfinite(summed)],5) ind = np.where((summed < lim))[0] good = files[ind] goods = np.zeros((len(good),2048,2048)) var = np.zeros((len(good),2048,2048)) mjd = np.zeros(len(good)) i = 0 for g in good: hdu = fits.open(g) data = hdu[1].data wcs = WCS(hdu[1].header) cut = Cutout2D(data,(1024+44,1024),2048,wcs=wcs) data = cut.data wcs = cut.wcs goods[i] = data e = hdu[2].data cut = Cutout2D(e,(1024+44,1024),2048) data = cut.data var[i] = data**2 jd = hdu[1].header['TSTART'] + hdu[1].header['BJDREFI'] mjd[i] = Time(jd, format='jd', scale='tdb').mjd i += 1 ref = np.nanmedian(goods,axis=0) var = np.nanmedian(var,axis=0) hdu[1].header['MJD'] = (np.nanmean(mjd), 'stacked') if FITS: ref_fits = deepcopy(hdu) ref_fits[1].data = ref ref_fits[1].header.update(wcs.to_header()) ref_fits[2].data = err ref_fits[2].header.update(wcs.to_header()) return ref_fits else: return ref, np.sqrt(var), wcs, hdu
def get_cutout(path, name, position, size): sci = fits.open(os.path.join(path, name+"sci.fits")) wht = fits.open(os.path.join(path, name+"wht.fits")) image = sci[0].data image = image.byteswap().newbyteorder() weight = wht[0].data weight = weight.byteswap().newbyteorder() wcs = WCS(sci[0].header) cutout_image = Cutout2D(image, position, size, wcs=wcs) cutout_weight = Cutout2D(weight, position, size, wcs=wcs) image = np.ascontiguousarray(cutout_image.data) weight = np.ascontiguousarray(cutout_weight.data) rms = np.sqrt(1.0 / weight) return image, weight, rms, cutout_image, cutout_image.wcs
def test_copy(self): data = np.copy(self.data) c = Cutout2D(data, (2, 3), (3, 3)) xy = (0, 0) value = 100. c.data[xy] = value xy_orig = c.to_original_position(xy) yx = xy_orig[::-1] assert data[yx] == value data = np.copy(self.data) c2 = Cutout2D(self.data, (2, 3), (3, 3), copy=True) c2.data[xy] = value assert data[yx] != value
def getTailPeaks(tailTimeSteps, noradid, mwa, sat, ts): x_array, y_array, ra_array, dec_array = [], [], [], [] hduBeam = fits.open(beamFile) beam = hduBeam[0].data y = np.linspace(0, 4, 5) x = np.linspace(0, 4, 5) x, y = np.meshgrid(x, y) for t in tailTimeSteps: hdu = fits.open("Neg" + "6Sigma1Floodfilllr14SigmaRFIBinaryMapPeakFlux-t" + str(t).zfill(4) + ".fits") UTCTime = datetime.strptime(hdu[0].header['DATE-OBS'], '%Y-%m-%dT%H:%M:%S.%f') data = hdu[0].data data = maskData(data, UTCTime, mwa, sat, wcs, ts) if np.all(data == 0): tailTimeSteps.remove(t) continue row, col = np.where(data == np.min(data)) beam_cutout = Cutout2D(beam, (col, row), (5, 5)) cutout = Cutout2D(data, (col, row), (5, 5)) temp = cutout.data / beam_cutout.data temp /= abs(np.sum(temp)) initial_guess = (temp[1, 1], 1, 1, 2) popt, pconv = opt.curve_fit(twoD_Gaussian, (x, y), temp.ravel(), p0=initial_guess) perr = np.sqrt(np.diag(pconv)) mu_x, mu_y = popt[1], popt[2] print("tail t {} x {} y {} dx {} dy {}".format(t, mu_x, mu_y, perr[1], perr[2])) solX = col + (mu_x - 2) solY = row + (mu_y - 2) x_array.append(solX[0]) y_array.append(solY[0]) pixcrd = np.array([[0, 0], [solX, solY]], dtype=np.float64) world = wcs.wcs_pix2world(pixcrd, 0) ra, dec = world[1] ra_array.append(ra) dec_array.append(dec) return x_array, y_array, ra_array, dec_array
def gen_cutouts(cutout_dims, radec, refquery, difquery, obj_name): nr_refims = len(refquery.metatable) nr_frames = nr_refims + len( difquery.metatable) #amount of images to go through #Make an empty list containing cutouts cutouts = [] #Also define an array storing relevant data for each image im_dat = pd.DataFrame( columns=[ 'obj_name', 'im_type', 'obs_filter', 'obsjd', 'peak_val', 'mean_val', 'standev' ], index=np.arange(0, nr_frames)) #Probably still needs to be expanded #Loop through the images to get required data data_locs = refquery.get_local_data() + difquery.get_local_data( 'scimrefdiffimg.fits.fz') for i in range(len(data_locs)): im = fits.open(data_locs[i]) wcs = WCS(im[-1].header) pix_xy = wcs.all_world2pix(radec, 1)[0] #Pixel location of object try: #See if the target coord is in the image, if not go to next image dummy = Cutout2D(im[-1].data, pix_xy, 1, mode='strict') except: continue cutouts.append( Cutout2D(im[-1].data, pix_xy, cutout_dims, mode='partial')) #Do the cutout, pad if needed #record data about image j = np.shape(cutouts)[0] - 1 #Current index is that of the last cutout im_dat.obj_name[j] = obj_name if i < nr_refims: im_dat.im_type[j] = 'ref' im_dat.obsjd[j] = ' ' if refquery.metatable.fid[j] == 1: im_dat.obs_filter[j] = 'ZTF_g' elif refquery.metatable.fid[j] == 2: im_dat.obs_filter[j] = 'ZTF_r' else: im_dat.obs_filter[j] = 'ZTF_i' else: im_dat.im_type[j] = 'diff' im_dat.obsjd[j] = im[-1].header['OBSJD'] im_dat.obs_filter[j] = im[-1].header['FILTER'] im_dat.peak_val[j] = np.nanmax(cutouts[j].data) im_dat.mean_val[j] = np.nanmean(cutouts[j].data) im_dat.standev[j] = np.nanstd(cutouts[j].data) #Close fits file before moving on to the next im.close() return cutouts, im_dat
def isolated_center(x, y, image): """Finds the centroid of each isolated source with centroid_quadratic. Parameters ---------- x : array-like Initial guesses of x positions for sources. y : array-like Initial guesses of y positions for sources. image : np.ndarray FFI flux data. Returns ------- cenx : array-like Controid x coordinates for all good input sources. ceny : array-like Centroid y coordinates for all good input sources. good : list Indexes into input arrays corresponding to good sources. """ cenx, ceny, good = [], [], [] for i in range(len(x)): if x[i] > 0. and y[i] > 0.: tpf = Cutout2D(image, position=(x[i], y[i]), size=(7,7), mode='partial') origin = tpf.origin_original cen = centroid_quadratic(tpf.data - np.nanmedian(tpf.data)) cenx.append(cen[0]+origin[0]); ceny.append(cen[1]+origin[1]) good.append(i) cenx, ceny = np.array(cenx), np.array(ceny) return cenx, ceny, good
def get_postage_stamp(radecstr, size, image, image_wcs): """ Extract a postage stamp image from a larger image Parameters ---------- radecstr : str SkyCoord pareseable string for ra, dec coordinates size : 2 element tuple size in ra and dec in arcsec image : 2D numpy.ndarray image to cut postage stamps from image_wcs : astropy.wcs WCS for image """ position = SkyCoord(radecstr) pix_scales = 3600. * proj_plane_pixel_scales(image_wcs) pix_size = (size[0] / pix_scales[0], size[1] / pix_scales[1]) try: result = Cutout2D(image, position, pix_size, wcs=image_wcs) except: return None return result
def cutout(self, position, width, mode="trim"): """ Create a cutout around a given position. Parameters ---------- position : `~astropy.coordinates.SkyCoord` Center position of the cutout region. width : tuple of `~astropy.coordinates.Angle` Angular sizes of the region in (lon, lat) in that specific order. If only one value is passed, a square region is extracted. mode : {'trim', 'partial', 'strict'} Mode option for Cutout2D, for details see `~astropy.nddata.utils.Cutout2D`. Returns ------- cutout : `~gammapy.maps.WcsNDMap` Cutout map """ width = _check_width(width) dummy_data = np.empty(self.to_image().data_shape) c2d = Cutout2D( data=dummy_data, wcs=self.wcs, position=position, # Cutout2D takes size with order (lat, lon) size=width[::-1] * u.deg, mode=mode, ) return self._init_copy(wcs=c2d.wcs, npix=c2d.shape[::-1])
def _get_stamps(fits_file, ra, dec, size, indiv_fits_files=None, return_indiv_stamps=False): """ Cut out science, template, and difference stamps around a detection at `ra,dec` from `fits_file` """ def get_indiv_stamps(): if not indiv_fits_files: return _indiv_stamps = np.zeros((size, size, len(indiv_fits_files))) for j, indiv_fits_file in enumerate(indiv_fits_files): try: im_wcs = WCS(indiv_fits_file[SCIENCE_IMAGE_EXT].header) stamp_coo = SkyCoord(ra, dec, unit='deg') indiv_cutout = Cutout2D(indiv_fits_file[SCIENCE_IMAGE_EXT].data, stamp_coo, (size, size), mode='partial', fill_value=1e-6, wcs=im_wcs).data except KeyError: logger.warning("extension {} missing from {}".format(image_ext, fits_file)) return except NoOverlapError: logger.warning("requested stamp(s) are off edge of image") return _indiv_stamps[:, :, j] = indiv_cutout return _indiv_stamps # layers are: science, template, difference, peak-to-peak individual, min individual, max individual stamps = np.zeros((size, size, 6)) for i, image_ext in enumerate([SCIENCE_IMAGE_EXT, TEMPLATE_IMAGE_EXT, DIFFERENCE_IMAGE_EXT]): try: im_wcs = WCS(fits_file[image_ext].header) stamp_coo = SkyCoord(ra, dec, unit='deg') cutout = Cutout2D(fits_file[image_ext].data, stamp_coo, (size, size), mode='partial', fill_value=1e-6, wcs=im_wcs, ).data except KeyError: logger.warning("extension {} missing from {}".format(image_ext, fits_file)) return except NoOverlapError: logger.warning("requested stamp is off edge of image") return stamps[:, :, i] = cutout indiv_stamps = get_indiv_stamps() # modify return signature to support multiarg. if (indiv_stamps is None) and ~return_indiv_stamps: return stamps if (indiv_stamps is None) and return_indiv_stamps: return stamps, None # Add additional frames that capture statistics from the individual science images stamps[:, :, 3] = np.ptp(np.atleast_3d(indiv_stamps), axis=2) stamps[:, :, 4] = np.min(np.atleast_3d(indiv_stamps), axis=2) stamps[:, :, 5] = np.max(np.atleast_3d(indiv_stamps), axis=2) if return_indiv_stamps: return stamps, indiv_stamps else: return stamps
def cut_2d(data_masked,position,size,wcs): data=data_masked.data cut=Cutout2D(data=data,position=position,size=size,wcs=wcs) data_cut=cut.data wcs_cut=cut.wcs return wcs_cut, data_cut
def centroiding_iteration(ccd, position_xy, cbox_size=5., csigma=3.): ''' Find the intensity-weighted centroid of the image iteratively Returns ------- xc_img, yc_img : float The centroided location in the original image coordinate in image XY. shift : float The total distance between the initial guess and the fitted centroid, i.e., the distance between `(xc_img, yc_img)` and `position_xy`. ''' imgX, imgY = position_xy cutccd = Cutout2D(ccd.data, position=position_xy, size=cbox_size) avg, med, std = sigma_clipped_stats(cutccd.data, sigma=3, iters=5) cthresh = med + csigma * std # using pixels only above med + 3*std for centroiding is recommended. # See Ma+2009, Optics Express, 17, 8525 mask = (cutccd.data < cthresh) if ccd.mask is not None: mask += ccd.mask xc_cut, yc_cut = centroid_com(data=cutccd.data, mask=mask) # Find the centroid with pixels have values > 3sigma, by center of mass # method. The position is in the cutout image coordinate, e.g., (3, 3). xc_img, yc_img = cutccd.to_original_position((xc_cut, yc_cut)) # convert the cutout image coordinate to original coordinate. # e.g., (3, 3) becomes something like (137, 189) dx = xc_img - imgX dy = yc_img - imgY shift = np.sqrt(dx**2 + dy**2) return xc_img, yc_img, shift
def cutout2CCDData(ccd, position, size, mode='trim', fill_value=np.nan, full=True): ''' Converts the Cutout2D object to proper CCDData. Parameters ---------- ccd: CCDData The ccd to be trimmed. position, size, mode, fill_value: See the ``ccdproc.trim_image`` doc. full: bool If ``True`` (default), returns the ``Cutout2D`` object. If ``False``, only the trimmed ccd is returned. ''' w = WCS(ccd.header) cut = Cutout2D(data=ccd.data, position=position, size=size, wcs=w, mode=mode, fill_value=fill_value, copy=True) # Copy True just to avoid any contamination to the original ccd. y1 = cut.ymin_original y2 = cut.ymax_original x1 = cut.xmin_original x2 = cut.xmax_original trimmed_ccd = trim_image(ccd[y1:y2, x1:x2]) if full: return trimmed_ccd, cut return trimmed_ccd
def cut_hdu(self, location, size, writetodisk=False, saveas=None): """ cutout size lxw ~ (dy x dx) box on fits file centered at a pixel or skycoord location if size is scalar gives a square dy=dx updates hdr wcs keeps other info from original """ try: hdu = self.sci except: hdu = self cphdu = hdu.copy() dat = cphdu.data hdr = cphdu.header wcs, frame = WCS(hdr), hdr['RADESYS'].lower() print("cut_hdu") print("location,wcs", location, wcs) print("shape", dat.shape) cut = Cutout2D(dat, location, size, wcs=wcs) cutwcs = cut.wcs cphdu.data = cut.data cphdu.header.update(cut.wcs.to_header()) if writetodisk: cphdu.writeto(saveas, overwrite=True) self.postage_stamp = cphdu return cphdu
def single_cutout(ax,position,image,mask1=None,mask2=None,points=None,label=None,size=6*u.arcsec): cutout_image = Cutout2D(image.data,position,size=size,wcs=image.wcs) norm = simple_norm(cutout_image.data,clip=False,stretch='linear',percent=99.5) ax.imshow(cutout_image.data,origin='lower',norm=norm,cmap=plt.cm.gray_r) # plot the nebulae catalogue cutout_mask, _ = reproject_interp(mask1,output_projection=cutout_image.wcs,shape_out=cutout_image.shape,order='nearest-neighbor') region_ID = np.unique(cutout_mask[~np.isnan(cutout_mask)]) contours = [] for i in region_ID: blank_mask = np.zeros_like(cutout_mask) blank_mask[cutout_mask==i] = 1 contours += find_contours(blank_mask, 0.5) for coords in contours: ax.plot(coords[:,1],coords[:,0],color='tab:red',lw=1,label='HII-region') mask = np.zeros((*cutout_mask.shape,4)) mask[~np.isnan(cutout_mask.data),:] = (0.84, 0.15, 0.16,0.1) ax.imshow(mask,origin='lower') # plot the association catalogue if mask2: cutout_mask, _ = reproject_interp(mask2,output_projection=cutout_image.wcs,shape_out=cutout_image.shape,order='nearest-neighbor') region_ID = np.unique(cutout_mask[~np.isnan(cutout_mask)]) contours = [] for i in region_ID: blank_mask = np.zeros_like(cutout_mask) blank_mask[cutout_mask==i] = 1 contours += find_contours(blank_mask, 0.5) for coords in contours: ax.plot(coords[:,1],coords[:,0],color='tab:blue',lw=1,label='association') mask = np.zeros((*cutout_mask.shape,4)) mask[~np.isnan(cutout_mask.data),:] = (0.12,0.47,0.71,0.1) ax.imshow(mask,origin='lower') # mark the position of the clusters within the cutout if points: region = RectangleSkyRegion(position,0.9*size,0.9*size) in_frame = points[region.contains(points['SkyCoord'],cutout_image.wcs)] for row in in_frame: x,y = row['SkyCoord'].to_pixel(cutout_image.wcs) if 5<x<cutout_image.data.shape[0]-5 and 5<y<cutout_image.data.shape[1]-5: ax.scatter(x,y,marker='o',facecolors='none',s=20,lw=0.4,color='tab:blue',label='cluster') if label: t = ax.text(0.07,0.875,label, transform=ax.transAxes,color='black',fontsize=8) t.set_bbox(dict(facecolor='white', alpha=1, ec='white')) ax.set_xticks([]) ax.set_yticks([]) return ax
def apply_recenter_cutout(self, ra, dec): """ Center the image at ra, dec. The image will be cut accordingly. Parameters ---------- ra: float, RA in deg. dec: float, Dec in deg. """ new_center_pix = self.get_wcs().all_world2pix([[ra, dec]], 0)[0] new_center_skycoord = SkyCoord(ra, dec, unit="deg") shape = np.array(np.shape(self.img_data)) new_shape = np.array([ 2 * np.min([shape[0] - new_center_pix[0], new_center_pix[0]]), 2 * np.min([shape[1] - new_center_pix[1], new_center_pix[1]]) ]).astype(int) print('ncp', new_center_pix, new_center_pix[::-1], ra, dec) print(self.img_hdr['CRVAL1'], self.img_hdr['CRVAL2']) self.img_hdr['CRVAL1'] cutout = Cutout2D(self.img_data.T, new_center_pix.T, new_shape.T, wcs=self.get_wcs().copy(), copy=True) #, mode='strict') hdr = cutout.wcs.to_header() print(hdr['CRVAL1'], hdr['CRVAL2']) sys.exit() hdr['BMAJ'], hdr['BMIN'], hdr['BPA'] = self.get_beam() self.img_hdr = hdr self.img_data = cutout.data logging.info(f'{self.imagefile}: recenter, size ({shape[0]}, {shape[1]})' \ f' --> ({new_shape[0]}, {new_shape[1]})')
def new_HST_image_plot(storage,f, axloc): img_file = '/Users/jansen/Google Drive/Astro/KMOS_SIN/HST_data/HST_'+storage['X-ray ID']+'.fits' img=pyfits.getdata(img_file) img_wcs= WCS(img_file).celestial hdr=pyfits.getheader(img_file) new_size = storage['Phys_size'] print (new_size) try: pixscale=abs(hdr['CD1_1']*3600) except: pixscale=abs(hdr['CDELT1']*3600) print (pixscale) Cat = storage['Cat_entry'] try: Ra_opt = Cat['ra'] Dec_opt = Cat['dec'] except: Ra_opt = Cat['RA'] Dec_opt = Cat['DEC'] opt_world= np.array([[Ra_opt,Dec_opt]]) opt_pixcrd = img_wcs.wcs_world2pix(opt_world, 0) # WCS transform opt_x= (opt_pixcrd[0,0]) # X pixel opt_y= (opt_pixcrd[0,1]) # Y pixel position = np.array([opt_x, opt_y]) cutout = Cutout2D(img, position, new_size/pixscale, wcs=img_wcs,mode='partial') img=(cutout.data).copy() img_wcs=cutout.wcs cut_opt = img if type(axloc)==str: ax = f.add_subplot(axloc, projection=img_wcs) else: ax = f.add_subplot(axloc[0],axloc[1],axloc[2], projection=img_wcs) rms = np.std(cut_opt - cut_opt.mean(axis=0)) #rms = 0.13/3 print ('RMS of the HST', rms) ax.imshow((cut_opt), origin='low', vmin=0, vmax=3*rms) ax.set_autoscale_on(False) return storage, ax
def cutout_exclusion_mask(self, fov='9 deg'): """Cutout appropriate part of exclusion mask In many cases the exclusion mask is given as all-sky image, but only a small fraction of that image is needed Parameters ---------- exclusion : `~gammapy.image.ExclusionMask` Input exclusion mask fov : `~astropy.coordinates.Angle` Field of view """ from astropy.nddata import Cutout2D from astropy.nddata.utils import PartialOverlapError fov = Angle(fov) exclusion = self.exclusion try: c = Cutout2D(exclusion.mask, self.on_region.pos, fov, exclusion.wcs, copy=True, mode='strict') except PartialOverlapError: raise PartialOverlapError('FOV ({}) not completely contained ' 'in exclusion mask'.format(fov)) self.exclusion = ExclusionMask(name=exclusion.name, data=c.data, wcs=c.wcs)
def find_star(infile, pos=pos0, find_size2d=size2d): ## Mod on 24/02/2017 to handle CRs (quick fix) ## Mod on 01/04/2017 to handle CRs and bad pixels using cosmicrays_lacosmic ## Mod on 04/04/2017 to pass pos and find_size2d keywords im0, hdr0 = fits.getdata(infile, header=True) # + on 01/04/2017 im0_clean = cosmicray_lacosmic(im0, sigclip=10) # Mod on 04/04/2017 # find_size2d = size2d #u.Quantity((25, 770), u.pixel) cutout = Cutout2D(im0_clean[0], pos, find_size2d, mode='partial', fill_value=np.nan) cutout = cutout.data peak = np.where(cutout == np.max(cutout)) ycen, xcen = peak[0][0], peak[1][0] # print xcen, ycen xcen += pos[0] - find_size2d[1].value / 2.0 ycen += pos[1] - find_size2d[0].value / 2.0 # print xcen, ycen return xcen, ycen
def test_cut_image_stamps(): setup = pipeline_setup.pipeline_setup({'red_dir': TEST_DATA}) stamp_dims = (20, 20) image_file = os.path.join(TEST_DATA, 'lsc1m005-fl15-20170701-0144-e91_cropped.fits') image = fits.getdata(image_file) detected_sources_file = os.path.join( TEST_DATA, 'lsc1m005-fl15-20170701-0144-e91_cropped_sources.txt') detected_sources = catalog_utils.read_source_catalog(detected_sources_file) stamps = psf.cut_image_stamps(setup, image, detected_sources[0:100, 1:3], stamp_dims) test_stamp = Cutout2D(np.ones([100, 100]), (50, 50), (10, 10)) got_stamp = False for s in stamps: if type(s) == type(test_stamp): got_stamp = True assert got_stamp == True