def ReduceTwo(speclist, flatlist='', biaslist='', HeNeAr_file='', stdstar='', trace_recenter=False, ntracesteps=15, airmass_file='apoextinct.dat', flat_mode='spline', flat_order=9, flat_response=True, apwidth=8, skysep=3, skywidth=7, skydeg=0, HeNeAr_prev=False, HeNeAr_interac=True, HeNeAr_tol=20, HeNeAr_order=3, display_HeNeAr=False, std_mode='spline', std_order=12, display_std=False, trim=True, write_reduced=True, display=True, display_final=True): if (len(biaslist) > 0): bias = pydis.biascombine(biaslist, trim=trim) else: bias = 0.0 if (len(biaslist) > 0) and (len(flatlist) > 0): flat, fmask_out = pydis.flatcombine(flatlist, bias, trim=trim, mode=flat_mode, display=False, flat_poly=flat_order, response=flat_response) else: flat = 1.0 fmask_out = (1, ) if HeNeAr_prev is False: prev = '' else: prev = HeNeAr_file + '.lines' # do the HeNeAr mapping first, must apply to all science frames if (len(HeNeAr_file) > 0): wfit = pydis.HeNeAr_fit(HeNeAr_file, trim=trim, fmask=fmask_out, interac=HeNeAr_interac, previous=prev, mode='poly', display=display_HeNeAr, tol=HeNeAr_tol, fit_order=HeNeAr_order) # read in the list of target spectra # assumes specfile is a list of file names of object #-> wrap with array and flatten because Numpy sucks with one-element arrays... specfile = np.array([np.loadtxt(speclist, dtype='string')]).flatten() for i in range(len(specfile)): spec = specfile[i] print("> Processing file " + spec + " [" + str(i) + "/" + str(len(specfile)) + "]") # raw, exptime, airmass, wapprox = pydis.OpenImg(spec, trim=trim) img = pydis.OpenImg(spec, trim=trim) raw = img.data exptime = img.exptime airmass = img.airmass wapprox = img.wavelength # remove bias and flat, divide by exptime data = ((raw - bias) / flat) / exptime if display is True: plt.figure() plt.imshow(np.log10(data), origin='lower', aspect='auto', cmap=cm.Greys_r) plt.title(spec + ' (flat and bias corrected)') plt.show() # with reduced data, trace BOTH apertures trace_1 = pydis.ap_trace(data, fmask=fmask_out, nsteps=ntracesteps, recenter=trace_recenter, interac=True) trace_2 = pydis.ap_trace(data, fmask=fmask_out, nsteps=ntracesteps, recenter=trace_recenter, interac=True) xbins = np.arange(data.shape[1]) if display is True: plt.figure() plt.imshow(np.log10(data), origin='lower', aspect='auto', cmap=cm.Greys_r) plt.plot(xbins, trace_1, 'b', lw=1) plt.plot(xbins, trace_1 - apwidth, 'r', lw=1) plt.plot(xbins, trace_1 + apwidth, 'r', lw=1) plt.plot(xbins, trace_1 - apwidth - skysep, 'g', lw=1) plt.plot(xbins, trace_1 - apwidth - skysep - skywidth, 'g', lw=1) plt.plot(xbins, trace_1 + apwidth + skysep, 'g', lw=1) plt.plot(xbins, trace_1 + apwidth + skysep + skywidth, 'g', lw=1) plt.plot(xbins, trace_2, 'b', lw=1) plt.plot(xbins, trace_2 - apwidth, 'r', lw=1) plt.plot(xbins, trace_2 + apwidth, 'r', lw=1) plt.plot(xbins, trace_2 - apwidth - skysep, 'g', lw=1) plt.plot(xbins, trace_2 - apwidth - skysep - skywidth, 'g', lw=1) plt.plot(xbins, trace_2 + apwidth + skysep, 'g', lw=1) plt.plot(xbins, trace_2 + apwidth + skysep + skywidth, 'g', lw=1) plt.title('(Both Traces, with aperture and sky regions)') plt.show() t_indx = 1 # now do the processing for both traces as if separate stars for trace in [trace_1, trace_2]: tnum = '_' + str(t_indx) t_indx = t_indx + 1 # extract the spectrum, measure sky values along trace, get flux errors ext_spec, sky, fluxerr = pydis.ap_extract(data, trace, apwidth=apwidth, skysep=skysep, skywidth=skywidth, skydeg=skydeg, coaddN=1) if (len(HeNeAr_file) > 0): wfinal = pydis.mapwavelength(trace, wfit, mode='poly') else: # if no line lamp given, use approx from the img header wfinal = wapprox # subtract local sky level, divide by exptime to get flux units # (counts / sec) flux_red = (ext_spec - sky) # now correct the spectrum for airmass extinction flux_red_x = pydis.AirmassCor(wfinal, flux_red, airmass, airmass_file=airmass_file) # now get flux std IF stdstar is defined # !! assume first object in list is std star !! if (len(stdstar) > 0) and (i == 0): sens_flux = pydis.DefFluxCal(wfinal, flux_red_x, stdstar=stdstar, mode=std_mode, polydeg=std_order, display=display_std) sens_wave = wfinal elif (len(stdstar) == 0) and (i == 0): # if 1st obj not the std, then just make array of 1's to multiply thru sens_flux = np.ones_like(flux_red_x) sens_wave = wfinal # final step in reduction, apply sensfunc ffinal, efinal = pydis.ApplyFluxCal(wfinal, flux_red_x, fluxerr, sens_wave, sens_flux) if write_reduced is True: pydis._WriteSpec(spec + tnum, wfinal, ffinal, efinal, trace) now = datetime.datetime.now() lout = open(spec + tnum + '.log', 'w') lout.write( '# This file contains the reduction parameters \n' + '# used in autoreduce for ' + spec + '\n') lout.write('DATE-REDUCED = ' + str(now) + '\n') lout.write('HeNeAr_tol = ' + str(HeNeAr_tol) + '\n') lout.write('HeNeAr_order = ' + str(HeNeAr_order) + '\n') lout.write('trace1 = ' + str(False) + '\n') lout.write('ntracesteps = ' + str(ntracesteps) + '\n') lout.write('trim = ' + str(trim) + '\n') lout.write('response = ' + str(flat_response) + '\n') lout.write('apwidth = ' + str(apwidth) + '\n') lout.write('skysep = ' + str(skysep) + '\n') lout.write('skywidth = ' + str(skywidth) + '\n') lout.write('skydeg = ' + str(skydeg) + '\n') lout.write('stdstar = ' + str(stdstar) + '\n') lout.write('airmass_file = ' + str(airmass_file) + '\n') lout.close() if display_final is True: # the final figure to plot plt.figure() # plt.plot(wfinal, ffinal) plt.errorbar(wfinal, ffinal, yerr=efinal) plt.xlabel('Wavelength') plt.ylabel('Flux') plt.title(spec) #plot within percentile limits plt.ylim((np.percentile(ffinal, 2), np.percentile(ffinal, 98))) plt.show() return
# plt.figure() # plt.plot(wfinal,'r') # plt.show() # subtract local sky level, divide by exptime to get flux units # (counts / sec) flux_red = (ext_spec - sky) # now correct the spectrum for airmass extinction flux_red_x = pydis.AirmassCor(wfinal, flux_red, airmass, airmass_file=airmass_file) # now get flux std IF stdstar is defined # !! assume first object in list is std star !! if (len(stdstar) > 0) and (i==0): sens_flux = pydis.DefFluxCal(wfinal, flux_red_x, stdstar=stdstar, mode=std_mode, polydeg=std_order, display=display_std) sens_wave = wfinal elif (len(stdstar) == 0) and (i==0): # if 1st obj not the std, then just make array of 1's to multiply thru sens_flux = np.ones_like(flux_red_x) sens_wave = wfinal # final step in reduction, apply sensfunc ffinal,efinal = pydis.ApplyFluxCal(wfinal, flux_red_x, fluxerr,
def autoreduce(speclist, flatlist='', biaslist='', HeNeAr_file='', stdstar='', trace_recenter=False, trace_interac=True, trace1=False, ntracesteps=15, airmass_file='apoextinct.dat', flat_mode='spline', flat_order=9, flat_response=True, apwidth=8, skysep=3, skywidth=7, skydeg=0, HeNeAr_prev=False, HeNeAr_interac=True, HeNeAr_tol=20, HeNeAr_order=3, display_HeNeAr=False, std_mode='spline', std_order=12, display_std=False, trim=True, write_reduced=True, display=True, display_final=True, silent=True): """ A wrapper routine to carry out the full steps of the spectral reduction and calibration. Steps include: 1) combines bias and flat images 2) maps wavelength in the HeNeAr image 3) perform simple image reduction: Data = (Raw - Bias)/Flat 4) trace spectral aperture 5) extract spectrum 6) measure sky along extracted spectrum 7) apply flux calibration 8) write output files Parameters ---------- speclist : str Path to file containing list of science images. flatlist : str Path to file containing list of flat images. biaslist : str Path to file containing list of bias images. HeNeAr_file : str Path to the HeNeAr calibration image stdstar : str Name of the standard star to use for flux calibration. If nothing is entered for "stdstar", no flux calibration will be computed. (Default is ''). NOTE1: must include the subdir for the star, e.g. 'spec50cal/feige34'. NOTE2: Assumes the first star in "speclist" is the standard star. trace1 : bool, optional use trace1=True if only perform aperture trace on first object in speclist. Useful if e.g. science targets are faint, and first object is a bright standard star. Note: assumes star placed at same position in spatial direction. (Default is False) trace_recenter : bool, optional If trace1=True, set this to True to allow for small linear adjustments to the trace (default is False) trace_interac : bool, optional Set to True if user should interactively select aperture center for each object spectrum. (Default is True) ntracesteps : int, optional Number of bins in X direction to chop image into. Use fewer bins if ap_trace is having difficulty, such as with faint targets (default here is 25, minimum is 4) apwidth : int, optional The width along the Y axis of the trace to extract. Note: a fixed width is used along the whole trace. (default here is 3 pixels) skysep : int, optional The separation in pixels from the aperture to the sky window. (Default is 25) skywidth : int, optional The width in pixels of the sky windows on either side of the aperture. (Default is 75) HeNeAr_interac : bool, optional Should the HeNeAr identification be done interactively (manually)? (Default here is False) HeNeAr_tol : int, optional When in automatic mode, the tolerance in pixel units between linelist entries and estimated wavelengths for the first few lines matched... use carefully. (Default here is 20) HeNeAr_order : int, optional The polynomial order to use to interpolate between identified peaks in the HeNeAr (Default is 2) display_HeNeAr : bool, optional std_mode : str, optional Fit mode to use with the flux standard star. Options are 'spline' and 'poly' (Default is 'spline') std_order : int, optional The order of polynomial to fit, if std_mode='poly'. (Default is 12) display_std : bool, optional If set, display plots of the flux standard being fit (Default is False) trim : bool, optional Trim the image using the DATASEC keyword in the header, assuming has format of [0:1024,0:512] (Default is True) write_reduced : bool, optional Set to True to write output files, including the .spec file with columns (wavelength, flux); the .trace file with columns (X pixel number, Y pixel of trace); .log file with record of settings used in this routine for reduction. (Default is True) display : bool, optional Set to True to display intermediate steps along the way. (Default is True) display_final : bool, optional Set to False to suppress plotting the final reduced spectrum to the screen. Useful for running in quiet batch mode. (Default is True) """ if (len(biaslist) > 0): bias = pydis.biascombine(biaslist, trim=trim, silent=silent) else: bias = 0.0 if (len(biaslist) > 0) and (len(flatlist) > 0): flat, fmask_out = pydis.flatcombine(flatlist, bias, trim=trim, mode=flat_mode, display=False, flat_poly=flat_order, response=flat_response) else: flat = 1.0 fmask_out = (1, ) if HeNeAr_prev is False: prev = '' else: prev = HeNeAr_file + '.lines' # do the HeNeAr mapping first, must apply to all science frames if (len(HeNeAr_file) > 0): wfit = pydis.HeNeAr_fit(HeNeAr_file, trim=trim, fmask=fmask_out, interac=HeNeAr_interac, previous=prev, mode='poly', display=display_HeNeAr, tol=HeNeAr_tol, fit_order=HeNeAr_order) # read in the list of target spectra # assumes specfile is a list of file names of object specfile = np.array([np.loadtxt(speclist, dtype='string')]).flatten() for i in range(len(specfile)): spec = specfile[i] if silent is False: print("> Processing file " + spec + " [" + str(i) + "/" + str(len(specfile)) + "]") # raw, exptime, airmass, wapprox = pydis.OpenImg(spec, trim=trim) img = pydis.OpenImg(spec, trim=trim) raw = img.data exptime = img.exptime airmass = img.airmass wapprox = img.wavelength # remove bias and flat, divide by exptime data = ((raw - bias) / flat) / exptime if display is True: plt.figure() plt.imshow(np.log10(data), origin='lower', aspect='auto', cmap=cm.Greys_r) plt.title(spec + ' (flat and bias corrected)') plt.show() # with reduced data, trace the aperture if (i == 0) or (trace1 is False): trace = pydis.ap_trace(data, fmask=fmask_out, nsteps=ntracesteps, recenter=trace_recenter, interac=trace_interac) # extract the spectrum, measure sky values along trace, get flux errors ext_spec, sky, fluxerr = pydis.ap_extract(data, trace, apwidth=apwidth, skysep=skysep, skywidth=skywidth, skydeg=skydeg, coaddN=1) xbins = np.arange(data.shape[1]) if display is True: plt.figure() plt.imshow(np.log10(data), origin='lower', aspect='auto', cmap=cm.Greys_r) plt.plot(xbins, trace, 'b', lw=1) plt.plot(xbins, trace - apwidth, 'r', lw=1) plt.plot(xbins, trace + apwidth, 'r', lw=1) plt.plot(xbins, trace - apwidth - skysep, 'g', lw=1) plt.plot(xbins, trace - apwidth - skysep - skywidth, 'g', lw=1) plt.plot(xbins, trace + apwidth + skysep, 'g', lw=1) plt.plot(xbins, trace + apwidth + skysep + skywidth, 'g', lw=1) plt.title('(with trace, aperture, and sky regions)') plt.show() if (len(HeNeAr_file) > 0): wfinal = pydis.mapwavelength(trace, wfit, mode='poly') else: # if no line lamp given, use approx from the img header wfinal = wapprox # plt.figure() # plt.plot(wfinal,'r') # plt.show() # subtract local sky level, divide by exptime to get flux units # (counts / sec) flux_red = (ext_spec - sky) # now correct the spectrum for airmass extinction flux_red_x = pydis.AirmassCor(wfinal, flux_red, airmass, airmass_file=airmass_file) # now get flux std IF stdstar is defined # !! assume first object in list is std star !! if (len(stdstar) > 0) and (i == 0): sens_flux = pydis.DefFluxCal(wfinal, flux_red_x, stdstar=stdstar, mode=std_mode, polydeg=std_order, display=display_std) sens_wave = wfinal elif (len(stdstar) == 0) and (i == 0): # if 1st obj not the std, then just make array of 1's to multiply thru sens_flux = np.ones_like(flux_red_x) sens_wave = wfinal # final step in reduction, apply sensfunc ffinal, efinal = pydis.ApplyFluxCal(wfinal, flux_red_x, fluxerr, sens_wave, sens_flux) if write_reduced is True: pydis._WriteSpec(spec, wfinal, ffinal, efinal, trace) now = datetime.datetime.now() lout = open(spec + '.log', 'w') lout.write('# This file contains the reduction parameters \n' + '# used in autoreduce for ' + spec + '\n') lout.write('DATE-REDUCED = ' + str(now) + '\n') lout.write('HeNeAr_tol = ' + str(HeNeAr_tol) + '\n') lout.write('HeNeAr_order = ' + str(HeNeAr_order) + '\n') lout.write('trace1 = ' + str(trace1) + '\n') lout.write('ntracesteps = ' + str(ntracesteps) + '\n') lout.write('trim = ' + str(trim) + '\n') lout.write('response = ' + str(flat_response) + '\n') lout.write('apwidth = ' + str(apwidth) + '\n') lout.write('skysep = ' + str(skysep) + '\n') lout.write('skywidth = ' + str(skywidth) + '\n') lout.write('skydeg = ' + str(skydeg) + '\n') lout.write('stdstar = ' + str(stdstar) + '\n') lout.write('airmass_file = ' + str(airmass_file) + '\n') lout.close() if display_final is True: # the final figure to plot plt.figure() # plt.plot(wfinal, ffinal) plt.errorbar(wfinal, ffinal, yerr=efinal) plt.xlabel('Wavelength') plt.ylabel('Flux') plt.title(spec) #plot within percentile limits plt.ylim((np.percentile(ffinal, 2), np.percentile(ffinal, 98))) plt.show() return