def test_show(filepath): hdu = fits.open(filepath) cube = hdu[0].data hdu.close() params_ami = { "peakmethod": 'fft', "bs_multi_tri": False, "maskname": "g7", "fw_splodge": 0.7, } bs = amical.extract_bs(cube, filepath, targetname='test', **params_ami, display=False) cal = amical.calibrate(bs, bs) amical.show(cal)
def perform_calibrate(args): """Calibrate the data with AMICAL (save calibrated oifits files)""" sciname, calname = _select_association_file(args) bs_t = amical.load_bs_hdf5(sciname) bs_c = [] for x in calname: bs_c = amical.load_bs_hdf5(x) display = len(bs_c) > 1 cal = amical.calibrate( bs_t, bs_c, clip=args.clip, normalize_err_indep=args.norm, apply_atmcorr=args.atmcorr, apply_phscorr=args.phscorr, display=display, ) # Position angle from North to East pa = bs_t.infos.pa cprint("\nPosition angle computed for the data: pa = %2.3f deg" % pa, "cyan") # Display and save the results as oifits if args.plot: amical.show(cal, true_flag_t3=False, cmax=180, pa=pa) plt.show() oifits_file = Path(bs_t.infos.filename).stem + "_calibrated.fits" amical.save(cal, oifits_file=oifits_file, datadir=args.outdir) return 0
"bs_multi_tri": False, "maskname": "g7", "fw_splodge": 0.7, } # Extract raw complex observables for the target and the calibrator: # It's the core of the pipeline (amical/mf_pipeline/bispect.py) bs_t = amical.extract_bs(cube_t, file_t, targetname="fakebinary", **params_ami, display=True) bs_c = amical.extract_bs(cube_c, file_c, targetname="fakepsf", **params_ami, display=False) # Calibrate the raw data to get calibrated V2 and CP. # bs_c can be a single calibrator result or a list of calibrators. # (see amical/calibration.py for details). cal = amical.calibrate(bs_t, bs_c) # Display and save the results as oifits amical.show(cal) dic = amical.save(cal, oifits_file="example_fakebinary_NIRISS.oifits", fake_obj=True) plt.show(block=True)
} # # Extract raw complex observables for the target and the calibrator: # # It's the core of the pipeline (amical/mf_pipeline/bispect.py) bs_t = amical.extract_bs(cube_t, file_t, targetname='HD142527', **params_ami, display=True) bs_c = amical.extract_bs(cube_c, file_c, targetname='HD142695', **params_ami, display=False) # (from amical.tools import check_seeing_cond, plot_seeing_cond) # In case of multiple files for a same target, you can # check the seeing condition and select only the good ones. # cond_t = check_seeing_cond([bs_t]) # cond_c = check_seeing_cond([bs_c]) # plot_seeing_cond([cond_t, cond_c], lim_seeing=1) # Calibrate the raw data to get get calibrated V2 and CP # bs_c can be a single calibrator result or a list of calibrator. # (see amical/core.py for details). cal = amical.calibrate(bs_t, bs_c) # Display and save the results as oifits amical.show(cal, true_flag_t3=False, cmax=180, pa=0) # bs_t.infos.pa) # amical.save(cal, oifits_file='example_HD142527_SPHERE.oifits', # fake_obj=True, verbose=False, pa=bs_t.infos.pa) plt.show(block=True)
def test_show(cal): amical.show(cal)
def candid_binary_extraction(calib_oifits, mnemonic): """ calib_oifits: full path file name of [calibrated, usually] oifits file This directory is where subdirectory of results are written (text, plots) using the oifits file name root mnemonic: short string to name output file plots - usually with eg HD #s or names of target_calibrator """ outputfile = os.path.dirname(calib_oifits) + '/' + mnemonic # *** # These are the binary parameters we expect CANDID to extract sep = 363.04 # binary separation [mas] theta = 285.398112 # position angle (pa) [deg] dm = 4.2 # delta magnitude [mag] fits.info(calib_oifits) fits.getheader(calib_oifits) # Your input data is an oifits file with fits.open(calib_oifits) as hdu: cp_ext = hdu['OI_T3'].data sqvis_ext = hdu['OI_VIS2'].data oiarray = hdu['OI_ARRAY'].data wavel = hdu['OI_WAVELENGTH'].data['EFF_WAVE'] pscale = hdu['OI_ARRAY'].header['PSCALE'] pav3 = hdu[0].header['PA'] print('Wavelength: %.2e m' % wavel) print('V3 PA: %.2f degrees' % pav3) cp = cp_ext['T3PHI'] cp_err = cp_ext['T3PHIERR'] tri_idx = cp_ext['STA_INDEX'] sqvis = sqvis_ext['VIS2DATA'] sqvis_err = sqvis_ext['VIS2ERR'] bl_idx = sqvis_ext['STA_INDEX'] hole_ctrs = oiarray['STAXYZ'] hole_idx = oiarray['STA_INDEX'] # Calculate the length of the baseline [m] for each pair baselines = [] for bl in bl_idx: hole1, hole2 = (bl[0] - 1), (bl[1] - 1 ) # because hole numbers start at 1 x1, y1 = hole_ctrs[hole1][0], hole_ctrs[hole1][1] x2, y2 = hole_ctrs[hole2][0], hole_ctrs[hole2][1] length = np.abs(np.sqrt((x2 - x1)**2. + (y2 - y1)**2.)) baselines.append(length) # Calculate the length of three baselines for each triangle # Select the longest for plotting tri_baselines = [] tri_longest = [] for tri in tri_idx: hole1, hole2, hole3 = tri[0] - 1, tri[1] - 1, tri[2] - 1 x1, y1 = hole_ctrs[hole1][0], hole_ctrs[hole1][1] x2, y2 = hole_ctrs[hole2][0], hole_ctrs[hole2][1] x3, y3 = hole_ctrs[hole3][0], hole_ctrs[hole3][1] length12 = np.abs(np.sqrt((x2 - x1)**2. + (y2 - y1)**2.)) length23 = np.abs(np.sqrt((x3 - x2)**2. + (y3 - y2)**2.)) length31 = np.abs(np.sqrt((x1 - x3)**2. + (y1 - y3)**2.)) tri_lengths = [length12, length23, length31] tri_baselines.append(tri_lengths) tri_longest.append(np.max(tri_lengths)) # Calculate B_max/lambda bmaxlambda_sqvis = baselines / wavel bmaxlambda_cp = tri_longest / wavel # Label baselines and triangles bl_strings = [] for idx in bl_idx: bl_strings.append(str(idx[0]) + '_' + str(idx[1])) tri_strings = [] for idx in tri_idx: tri_strings.append(str(idx[0]) + '_' + str(idx[1]) + '_' + str(idx[2])) print(sorted(baselines)) # Plot closure phases, square visibilities # Label which point corresponds to which hole pair or triple fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 7)) ax1.errorbar(bmaxlambda_cp, cp, yerr=cp_err, fmt='go') ax1.set_xlabel(r'$B_{max}/\lambda$', size=16) ax1.set_ylabel('Closure phase [deg]', size=14) ax1.set_title('Calibrated Closure Phase', size=14) for ii, tri in enumerate(tri_strings): ax1.annotate(tri, (bmaxlambda_cp[ii], cp[ii]), xytext=(bmaxlambda_cp[ii] + 10000, cp[ii])) ax2.errorbar(bmaxlambda_sqvis, sqvis, yerr=sqvis_err, fmt='go') ax2.set_title('Calibrated Squared Visibility', size=16) ax2.set_xlabel(r'$B_{max}/\lambda$', size=14) ax2.set_ylabel('Squared visibility amplitude', size=14) for ii, bl in enumerate(bl_strings): ax2.annotate(bl, (bmaxlambda_sqvis[ii], sqvis[ii]), xytext=(bmaxlambda_sqvis[ii] + 10000, sqvis[ii])) plt.savefig(outputfile + "_cp_sqv.png") # The above plots show the calibrated closure phases (left) and the # calibrated squared visibilities (right). Each quantity is plotted against # $B_{max}/\lambda$, the baseline length divided by the wavelength of the # observation. In the case of closure phases, where the triangle is formed # by three baselines, the longest one is selected. # # For a monochromatic observation of a point source, we would expect all 35 # closure phases to be zero, and all 21 squared visibilities to be unity. # Asymmetries in the target caused by, e.g., an unresolved companion, cause # the closure phases and visibilities corresponding to the baselines # between affected sub-apertures to diverge from zero or unity. We can now # use the set of calibrated observables to model the most probable location # and contrast ratio of the companion. # You can also use the dedicated tool from AMICAL to plot the data: plot = amical.show(calib_oifits, cmax=30) plt.savefig(outputfile + '_amical_show.png') bmax = 5.28 * u.meter wavel = 4.8e-6 * u.meter maxstep = wavel / (4 * bmax) * u.rad stepsize = int(maxstep.to(u.mas) / u.mas) print('Using a step size of %i mas' % stepsize) param_candid = { 'rmin': 10, # inner radius of the grid 'rmax': 500, # outer radius of the grid 'step': stepsize, # grid sampling 'ncore': multiprocessing.cpu_count() # core for multiprocessing } # Perform the fit fit1 = amical.candid_grid(calib_oifits, **param_candid, diam=0, doNotFit=['diam*'], save=True, outputfile=outputfile) # plot the fitted model on data with residuals mod_v2, mod_cp, chi2 = amical.plot_model(calib_oifits, fit1['best'], save=True, outputfile=outputfile) # In the above output, CANDID provides a best-fit angular size for the # target star, 'best fit diameter (UD)', and the $\chi^2$ and n$\sigma$ # (capped at 50$\sigma$) of the detection. It gives us estimates for the # binary separation ('sep'), position angle ('theta'), contrast ratio # ('CR'), and delta magnitudes ('dm'). # # It also produces plots of the squared visibilities and closure phases, # and plots the residual (difference between the data and the best-fit # model for each observable). # # We can now compare these with our expected values from above: sep_fit, sep_unc = fit1['best']['sep'], fit1['uncer']['sep'] theta_fit, theta_unc = fit1['best']['theta'], fit1['uncer']['theta'] dm_fit, dm_unc = fit1['best']['dm'], fit1['uncer']['dm'] print(' Expected Model') print('Sep [mas]: %.3f %.3f +/- %.2f' % (sep, sep_fit, sep_unc)) print('Theta [deg]: %.3f %.3f +/- %.2f' % (theta, theta_fit, theta_unc)) print('dm [mag]: %.3f %.3f +/- %.2f' % (dm, dm_fit, dm_unc)) # Next, we will use CANDID to find the detection limit at different angular # separations. To do this, CANDID injects an additional companion at each # grid position with different flux ratios and estimates the number of # sigma for a theoretical detection at that point. It interpolates the flux # ratio values at 3$\sigma$ for all points in the grid to produce a # 3$\sigma$ detection map of the contrast (flux) ratio. # Find detection limits using the fake injection method cr_candid = amical.candid_cr_limit(calib_oifits, **param_candid, fitComp=fit1['comp'], save=True, outputfile=outputfile)
def test_show(bss): bs = bss["fft"] cal = amical.calibrate(bs, bs) amical.show(cal)