def test_snrmap_fast(get_frame): frame, positions = get_frame y0, x0 = positions snmap = snrmap(frame.data, fwhm=frame.fwhm, plot=plot, approximated=True, nproc=2) y1, x1 = np.where(snmap == snmap.max()) assert np.allclose(x1, x0, atol=atol) and np.allclose(y1, y0, atol=atol)
def calc_snr(planet_photons, astro_dict, plot=False): derot_image = reduce_image(planet_photons) planet_loc = find_loc(astro_dict, derot_image) snr = pix_snr_loc(derot_image, planet_loc - mp.array_size // 2, config['data']['fwhm'], verbose=True)[0] if plot: fig = plt.figure(figsize=(12, 6)) ax = fig.add_subplot(121) pcm = ax.imshow(derot_image, origin='lower') fig.colorbar(pcm, ax=ax) aper = plt.Circle(planet_loc[::-1], radius=config['data']['fwhm'] / 2., color='r', fill=False, alpha=0.8) ax.add_patch(aper) ax = fig.add_subplot(122) snrimage = snrmap(derot_image, fwhm=config['data']['fwhm'], nproc=8) pcm = ax.imshow(snrimage, origin='lower') fig.colorbar(pcm, ax=ax) plt.show() return snr
def test_snrmap_masked(get_frame): frame, positions = get_frame y0, x0 = positions snmap = snrmap(frame.data, fwhm=frame.fwhm, plot=plot, nproc=2, known_sources=(int(x0), int(y0))) y1, x1 = np.where(snmap == snmap.max()) assert np.allclose(x1, x0, atol=atol) and np.allclose(y1, y0, atol=atol)
def postprocessing(self, do_adi=True, do_adi_contrast=True, do_pca_full=True, do_pca_ann=True, cropped=True, do_snr_map=True, do_snr_map_opt=True, delta_rot=(0.5, 3), mask_IWA=1, overwrite=True, plot=True, verbose=True, debug=False): """ For post processing the master cube via median ADI, full frame PCA-ADI, or annular PCA-ADI. Includes constrast curves and SNR maps. Parameters: *********** do_adi : bool Whether to do a median-ADI processing do_adi_contrast : bool Whether to compute contrast curve associated to median-ADI do_pca_full : bool Whether to apply PCA-ADI on full frame do_pca_ann : bool, default is False Whether to apply annular PCA-ADI (more computer intensive). Only runs if cropped=True cropped : bool whether the master cube was cropped in pre-processing do_snr_map : bool whether to compute an SNR map (warning: computer intensive); useful only when point-like features are seen in the image do_snr_map_opt : bool Whether to compute a non-conventional (more realistic) SNR map delta_rot : tuple Threshold in rotation angle used in pca_annular to include frames in the PCA library (provided in terms of FWHM). See description of pca_annular() for more details mask_IWA : int, default 1 Size of the numerical mask that hides the inner part of post-processed images. Provided in terms of fwhm overwrite : bool, default True whether to overwrite pre-exisiting output files from previous reductions plot : bool Whether to save plots to the output path (PDF file, print quality) verbose : bool prints more output when True debug : bool, default is False Saves extra output files """ # make directories if they don't exist print("======= Starting post-processing....=======") outpath_sub = self.outpath + "sub_npc{}/".format(self.npc) if not isdir(outpath_sub): os.system("mkdir " + outpath_sub) if verbose: print('Input path is {}'.format(self.inpath)) print('Output path is {}'.format(outpath_sub)) source = self.dataset_dict['source'] tn_shift = 0.568 # Launhardt et al. 2020, true North offset for NACO ADI_cube_name = '{}_master_cube.fits' # template name for input master cube derot_ang_name = 'derot_angles.fits' # template name for corresponding input derotation angles ADI_cube = open_fits(self.inpath + ADI_cube_name.format(source), verbose=verbose) derot_angles = open_fits(self.inpath + derot_ang_name, verbose=verbose) + tn_shift if do_adi_contrast: psfn_name = "master_unsat_psf_norm.fits" # normalised PSF flux_psf_name = "master_unsat-stellarpsf_fluxes.fits" # flux in a FWHM aperture found in calibration psfn = open_fits(self.inpath + psfn_name, verbose=verbose) starphot = open_fits(self.inpath + flux_psf_name, verbose=verbose)[1] # scaled fwhm flux is the second entry mask_IWA_px = mask_IWA * self.fwhm if verbose: print("adopted mask size: {:.0f}".format(mask_IWA_px)) ann_sz = 3 # if PCA-ADI in a single annulus or in concentric annuli, this is the size of the annulus/i in FWHM svd_mode = 'lapack' # python package used for Singular Value Decomposition for PCA reductions n_randsvd = 3 # if svd package is set to 'randsvd' number of times we do PCA rand-svd, before taking the # median of all results (there is a risk of significant self-subtraction when just doing it once) ref_cube = None # if any, load here a centered calibrated cube of reference star observations - would then be # used for PCA instead of the SCI cube itself # TEST number of principal components # PCA-FULL if do_pca_full: test_pcs_full = list(range(1, self.npc + 1)) # PCA-ANN if do_pca_ann: test_pcs_ann = list(range(1, self.npc + 1)) # needs a cropped cube ######################### Simple ADI ########################### if do_adi: if not isfile(outpath_sub + 'final_ADI_simple.fits') or overwrite: if debug: # saves the residuals tmp, _, tmp_tmp = median_sub(ADI_cube, derot_angles, fwhm=self.fwhm, radius_int=0, asize=ann_sz, delta_rot=delta_rot, full_output=debug, verbose=verbose) tmp = mask_circle(tmp, mask_IWA_px) write_fits(outpath_sub + 'TMP_ADI_simple_cube_der.fits', tmp, verbose=verbose) # make median combination of the de-rotated cube. tmp_tmp = median_sub(ADI_cube, derot_angles, fwhm=self.fwhm, radius_int=0, asize=ann_sz, delta_rot=delta_rot, full_output=False, verbose=verbose) tmp_tmp = mask_circle(tmp_tmp, mask_IWA_px) # we mask the IWA write_fits(outpath_sub + 'final_ADI_simple.fits', tmp_tmp, verbose=verbose) ## SNR map if (not isfile(outpath_sub + 'final_ADI_simple_snrmap.fits') or overwrite) and do_snr_map: tmp = open_fits(outpath_sub + 'final_ADI_simple.fits', verbose=verbose) tmp = mask_circle(tmp, mask_IWA_px) tmp_tmp = snrmap(tmp, self.fwhm, nproc=self.nproc, verbose=debug) write_fits(outpath_sub + 'final_ADI_simple_snrmap.fits', tmp_tmp, verbose=verbose) ## Contrast curve if (not isfile(outpath_sub + 'contrast_adi.pdf') or overwrite) and do_adi_contrast: _ = contrast_curve(ADI_cube, derot_angles, psfn, self.fwhm, pxscale=self.pixel_scale, starphot=starphot, algo=median_sub, sigma=5., nbranch=1, theta=0, inner_rad=1, wedge=(0, 360), student=True, transmission=None, smooth=True, plot=plot, dpi=300, debug=debug, save_plot=outpath_sub + 'contrast_adi.pdf', verbose=verbose) if verbose: print("======= Completed Median-ADI =======") ####################### PCA-ADI full ########################### if do_pca_full: test_pcs_str_list = [str(x) for x in test_pcs_full] ntest_pcs = len(test_pcs_full) test_pcs_str = "npc" + "-".join(test_pcs_str_list) PCA_ADI_cube = ADI_cube.copy() tmp_tmp = np.zeros([ntest_pcs, PCA_ADI_cube.shape[1], PCA_ADI_cube.shape[2]]) if do_snr_map_opt: tmp_tmp_tmp_tmp = np.zeros([ntest_pcs, PCA_ADI_cube.shape[1], PCA_ADI_cube.shape[2]]) for pp, npc in enumerate(test_pcs_full): if svd_mode == 'randsvd': tmp_tmp_tmp = np.zeros([n_randsvd, PCA_ADI_cube.shape[1], PCA_ADI_cube.shape[2]]) for nr in range(n_randsvd): tmp_tmp_tmp[nr] = pca(PCA_ADI_cube, angle_list=derot_angles, cube_ref=ref_cube, scale_list=None, ncomp=int(npc), svd_mode='randsvd', scaling=None, mask_center_px=mask_IWA_px, delta_rot=delta_rot, fwhm=self.fwhm, collapse='median', check_memory=True, full_output=False, verbose=verbose) tmp_tmp[pp] = np.median(tmp_tmp_tmp, axis=0) else: if not isfile(outpath_sub + 'final_PCA-ADI_full_' + test_pcs_str + '.fits') or overwrite: tmp_tmp[pp] = pca(PCA_ADI_cube, angle_list=derot_angles, cube_ref=ref_cube, scale_list=None, ncomp=int(npc), svd_mode=svd_mode, scaling=None, mask_center_px=mask_IWA_px, delta_rot=delta_rot, fwhm=self.fwhm, collapse='median', check_memory=True, full_output=False, verbose=verbose) if (not isfile(outpath_sub + 'final_PCA-ADI_full_' +test_pcs_str+'_snrmap_opt.fits') or overwrite) \ and do_snr_map_opt: tmp_tmp_tmp_tmp[pp] = pca(PCA_ADI_cube, angle_list=-derot_angles, cube_ref=ref_cube, scale_list=None, ncomp=int(npc), svd_mode=svd_mode, scaling=None, mask_center_px=mask_IWA_px, delta_rot=delta_rot, fwhm=self.fwhm, collapse='median', check_memory=True, full_output=False, verbose=verbose) if not isfile(outpath_sub + 'final_PCA-ADI_full_' + test_pcs_str + '.fits') or overwrite: write_fits(outpath_sub + 'final_PCA-ADI_full_' + test_pcs_str + '.fits', tmp_tmp, verbose=verbose) if (not isfile(outpath_sub + 'neg_PCA-ADI_full_' + test_pcs_str + '.fits') or overwrite) and do_snr_map_opt: write_fits(outpath_sub + 'neg_PCA-ADI_full_' + test_pcs_str + '.fits', tmp_tmp_tmp_tmp, verbose=verbose) ### Convolution if not isfile(outpath_sub + 'final_PCA-ADI_full_' + test_pcs_str + '_conv.fits') or overwrite: tmp = open_fits(outpath_sub + 'final_PCA-ADI_full_' + test_pcs_str + '.fits', verbose=verbose) for nn in range(tmp.shape[0]): tmp[nn] = frame_filter_lowpass(tmp[nn], fwhm_size=self.fwhm, gauss_mode='conv') write_fits(outpath_sub + 'final_PCA-ADI_full_' + test_pcs_str + '_conv.fits', tmp, verbose=verbose) ### SNR map if (not isfile(outpath_sub + 'final_PCA-ADI_full_' + test_pcs_str + '_snrmap.fits') or overwrite) \ and do_snr_map: tmp = open_fits(outpath_sub + 'final_PCA-ADI_full_' + test_pcs_str + '.fits', verbose=verbose) for pp in range(ntest_pcs): tmp[pp] = snrmap(tmp[pp], self.fwhm, nproc=self.nproc, verbose=debug) tmp[pp] = mask_circle(tmp[pp], mask_IWA_px) write_fits(outpath_sub + 'final_PCA-ADI_full_' + test_pcs_str + '_snrmap.fits', tmp, verbose=verbose) ### SNR map optimized if (not isfile(outpath_sub + 'final_PCA-ADI_full_' + test_pcs_str + '_snrmap_opt.fits') or overwrite) \ and do_snr_map_opt: tmp = open_fits(outpath_sub + 'final_PCA-ADI_full_' + test_pcs_str + '.fits', verbose=verbose) for pp in range(ntest_pcs): tmp[pp] = snrmap(tmp[pp], self.fwhm, array2=tmp_tmp_tmp_tmp[pp], incl_neg_lobes=False, nproc=self.nproc, verbose=debug) tmp[pp] = mask_circle(tmp[pp], mask_IWA_px) write_fits(outpath_sub + 'final_PCA-ADI_full_' + test_pcs_str + '_snrmap_opt.fits', tmp, verbose=verbose) if verbose: print("======= Completed PCA Full Frame =======") ######################## PCA-ADI annular ####################### if do_pca_ann: if cropped == False: raise ValueError('PCA-ADI annular requires a cropped cube!') PCA_ADI_cube = ADI_cube.copy() del ADI_cube test_pcs_str_list = [str(x) for x in test_pcs_ann] ntest_pcs = len(test_pcs_ann) test_pcs_str = "npc" + "-".join(test_pcs_str_list) tmp_tmp = np.zeros([ntest_pcs, PCA_ADI_cube.shape[1], PCA_ADI_cube.shape[2]]) if debug: array_der = np.zeros([ntest_pcs, PCA_ADI_cube.shape[0], PCA_ADI_cube.shape[1], PCA_ADI_cube.shape[2]]) array_out = np.zeros([ntest_pcs, PCA_ADI_cube.shape[0], PCA_ADI_cube.shape[1], PCA_ADI_cube.shape[2]]) if do_snr_map_opt: tmp_tmp_tmp_tmp = np.zeros([ntest_pcs, PCA_ADI_cube.shape[1], PCA_ADI_cube.shape[2]]) for pp, npc in enumerate(test_pcs_ann): if debug and ((not isfile(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_residuals.fits') and not isfile(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_residuals-derot.fits')) or overwrite): # saves residuals and median if debug is true and they either dont exist or are to be overwritten array_out[pp], array_der[pp], tmp_tmp[pp] = pca_annular(PCA_ADI_cube, derot_angles, cube_ref=ref_cube, scale_list=None, radius_int=mask_IWA_px, fwhm=self.fwhm, asize=ann_sz * self.fwhm, n_segments=1, delta_rot=delta_rot, ncomp=int(npc), svd_mode=svd_mode, nproc=self.nproc, min_frames_lib=max(npc, 10), max_frames_lib=200, tol=1e-1, scaling=None, imlib='opencv', interpolation='lanczos4', collapse='median', ifs_collapse_range='all', full_output=debug, verbose=verbose) else: if not isfile(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '.fits') or overwrite: tmp_tmp[pp] = pca_annular(PCA_ADI_cube, derot_angles, cube_ref=ref_cube, scale_list=None, radius_int=mask_IWA_px, fwhm=self.fwhm, asize=ann_sz * self.fwhm, n_segments=1, delta_rot=delta_rot, ncomp=int(npc), svd_mode=svd_mode, nproc=self.nproc, min_frames_lib=max(npc, 10), max_frames_lib=200, tol=1e-1, scaling=None, imlib='opencv', interpolation='lanczos4', collapse='median', ifs_collapse_range='all', full_output=False, verbose=verbose) if (not isfile(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_snrmap_opt.fits') or overwrite) and do_snr_map_opt: tmp_tmp_tmp_tmp[pp] = pca_annular(PCA_ADI_cube, -derot_angles, cube_ref=ref_cube, scale_list=None, radius_int=mask_IWA_px, fwhm=self.fwhm, asize=ann_sz * self.fwhm, n_segments=1, delta_rot=delta_rot, ncomp=int(npc), svd_mode=svd_mode, nproc=self.nproc, min_frames_lib=max(npc, 10), max_frames_lib=200, tol=1e-1, scaling=None, imlib='opencv', interpolation='lanczos4', collapse='median', ifs_collapse_range='all', full_output=False, verbose=verbose) if not isfile(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '.fits') or overwrite: write_fits(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '.fits', tmp_tmp, verbose=verbose) if debug and ((not isfile(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_residuals.fits') and not isfile(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_residuals-derot.fits')) or overwrite): write_fits(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_residuals.fits', array_out, verbose=verbose) write_fits(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_residuals-derot.fits', array_der, verbose=verbose) if (not isfile(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_snrmap_opt.fits') or overwrite) and do_snr_map_opt: write_fits(outpath_sub + 'neg_PCA-ADI_ann_' + test_pcs_str + '.fits', tmp_tmp_tmp_tmp, verbose=verbose) ### Convolution if not isfile(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_conv.fits') or overwrite: tmp = open_fits(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '.fits', verbose=verbose) for nn in range(tmp.shape[0]): tmp[nn] = frame_filter_lowpass(tmp[nn], fwhm_size=self.fwhm, gauss_mode='conv') write_fits(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_conv.fits', tmp, verbose=verbose) ### SNR map if (not isfile( outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_snrmap.fits') or overwrite) and do_snr_map: tmp = open_fits(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '.fits', verbose=verbose) for pp in range(ntest_pcs): tmp[pp] = snrmap(tmp[pp], self.fwhm, nproc=self.nproc, verbose=debug) tmp[pp] = mask_circle(tmp[pp], mask_IWA_px) write_fits(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_snrmap.fits', tmp, verbose=verbose) ### SNR map optimized if (not isfile( outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_snrmap_opt.fits') or overwrite) and do_snr_map_opt: tmp = open_fits(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '.fits', verbose=verbose) for pp in range(ntest_pcs): tmp[pp] = snrmap(tmp[pp], self.fwhm, plot=plot, array2=tmp_tmp_tmp_tmp[pp], nproc=self.nproc, verbose=debug) tmp[pp] = mask_circle(tmp[pp], mask_IWA_px) write_fits(outpath_sub + 'final_PCA-ADI_ann_' + test_pcs_str + '_snrmap_opt.fits', tmp, verbose=verbose) if verbose: print("======= Completed PCA Annular =======")