Пример #1
0
def normalize_now(filenameblue,
                  filenamered,
                  redfile,
                  plotall=True,
                  extinct_correct=False):
    #Read in the observed spectrum
    obs_spectrablue, airmass, exptime, dispersion = st.readspectrum(
        filenameblue)
    datalistblue = fits.open(filenameblue)

    if redfile:
        obs_spectrared, airmassred, exptimered, dispersionred = st.readspectrum(
            filenamered)

    #Extinction correction
    if extinct_correct:
        print 'Extinction correcting spectra.'
        plt.clf()
        plt.plot(obs_spectrablue.warr, obs_spectrablue.opfarr)
        obs_spectrablue.opfarr = st.extinction_correction(
            obs_spectrablue.warr, obs_spectrablue.opfarr, airmass)
        obs_spectrablue.farr = st.extinction_correction(
            obs_spectrablue.warr, obs_spectrablue.farr, airmass)
        obs_spectrablue.sky = st.extinction_correction(obs_spectrablue.warr,
                                                       obs_spectrablue.sky,
                                                       airmass)
        obs_spectrablue.sigma = st.extinction_correction(
            obs_spectrablue.warr, obs_spectrablue.sigma, airmass)
        plt.plot(obs_spectrablue.warr, obs_spectrablue.opfarr)
        plt.show()

        if redfile:
            plt.clf()
            plt.plot(obs_spectrared.warr, obs_spectrared.opfarr)
            obs_spectrared.opfarr = st.extinction_correction(
                obs_spectrared.warr, obs_spectrared.opfarr, airmassred)
            obs_spectrared.farr = st.extinction_correction(
                obs_spectrared.warr, obs_spectrared.farr, airmassred)
            obs_spectrared.sky = st.extinction_correction(
                obs_spectrared.warr, obs_spectrared.sky, airmassred)
            obs_spectrared.sigma = st.extinction_correction(
                obs_spectrared.warr, obs_spectrared.sigma, airmassred)
            plt.plot(obs_spectrared.warr, obs_spectrared.opfarr)
            plt.show()

    #Read in measured FWHM from header. This is used to convolve the model spectrum.
    FWHMpix = datalistblue[0].header['specfwhm']
    FWHM = FWHMpix * (obs_spectrablue.warr[-1] -
                      obs_spectrablue.warr[0]) / len(obs_spectrablue.warr)

    #Read in DA model
    cwd = os.getcwd()
    os.chdir(
        '/afs/cas.unc.edu/depts/physics_astronomy/clemens/students/group/modelfitting/Koester_08'
    )
    dafile = 'da12500_800.dk'
    mod_wav, mod_spec = np.genfromtxt(dafile, unpack=True, skip_header=33)
    os.chdir(cwd)  #Move back to directory with observed spectra

    #Convolve the model to match the seeing of the spectrum
    intlambda = np.divide(range(31000), 10.) + 3660.0
    lowlambda = np.min(np.where(mod_wav > 3600.))
    highlambda = np.min(np.where(mod_wav > 6800.))
    shortlambdas = mod_wav[lowlambda:highlambda]
    shortinten = mod_spec[lowlambda:highlambda]
    interp = inter.InterpolatedUnivariateSpline(shortlambdas, shortinten, k=1)
    intflux = interp(intlambda)
    sig = FWHM / (2. * np.sqrt(2. * np.log(2.)))
    gx = np.divide(range(360), 10.)
    gauss = (1. / (sig * np.sqrt(2. * np.pi))) * np.exp(-(gx - 18.)**2. /
                                                        (2. * sig**2.))
    gf = np.divide(np.outer(intflux, gauss), 10.)
    length = len(intflux) - 360.
    cflux = np.zeros(length)
    clambda = intlambda[180:len(intlambda) - 180]
    x = 0
    while x < length:
        cflux[x] = np.sum(np.diagonal(gf, x, axis1=1, axis2=0), dtype='d')
        x += 1
    interp2 = inter.InterpolatedUnivariateSpline(clambda, cflux, k=1)
    cflux2blue = interp2(obs_spectrablue.warr)
    cflux2blue /= 10**13.  #Divide by 10**13 to scale
    if redfile:
        cflux2red = interp2(obs_spectrared.warr)
        cflux2red /= 10**13.  #Divide by 10**13 to scale

    #plt.clf()
    #plt.plot(obs_spectrablue.warr,obs_spectrablue.opfarr,'b')
    #plt.plot(obs_spectrablue.warr,cflux2blue,'r')
    #if redfile:
    #    plt.plot(obs_spectrared.warr,obs_spectrared.opfarr,'b')
    #    plt.plot(obs_spectrared.warr,cflux2red,'r')
    #plt.show()

    #The response function is the observed spectrum divided by the model spectrum.
    response_blue = obs_spectrablue.opfarr / cflux2blue
    if redfile:
        response_red = obs_spectrared.opfarr / cflux2red
    '''
    plt.clf()
    plt.plot(obs_spectrablue.warr,response_blue,'k')
    if redfile:
        plt.plot(obs_spectrared.warr,response_red,'k')
    plt.show()
    '''

    #We want to mask out the Balmer line features, and the telluric line in the red spectrum. Set up the wavelength ranges to mask here.
    #balmer_features_blue = [[3745,3757],[3760,3780],[3784,3812],[3816,3856],[3865,3921],[3935,4021],[4040,4191],[4223,4460],[4691,5010]] #Keeping ends
    balmer_features_blue = [[3400, 3700], [3745, 3757], [3760, 3780],
                            [3784, 3812], [3816, 3856], [3865, 3921],
                            [3935, 4021], [4040, 4191], [4223, 4460],
                            [4691, 5010], [5140, 5500]]  #Discarding ends
    balmer_features_red = [[6350, 6780], [6835, 6970]]

    balmer_mask_blue = obs_spectrablue.warr == obs_spectrablue.warr
    for wavrange in balmer_features_blue:
        inds = np.where((obs_spectrablue.warr > wavrange[0])
                        & (obs_spectrablue.warr < wavrange[1]))
        balmer_mask_blue[inds] = False

    if redfile:
        balmer_mask_red = obs_spectrared.warr == obs_spectrared.warr
        for wavrange in balmer_features_red:
            indxs = np.where((obs_spectrared.warr > wavrange[0])
                             & (obs_spectrared.warr < wavrange[1]))
            balmer_mask_red[indxs] = False

    spec_wav_masked_blue = obs_spectrablue.warr[balmer_mask_blue]
    response_masked_blue = response_blue[balmer_mask_blue]

    if redfile:
        spec_wav_masked_red = obs_spectrared.warr[balmer_mask_red]
        response_masked_red = response_red[balmer_mask_red]

    #Fit the response function with a polynomial. The order of polynomial is specified first.
    response_poly_order_blue = 7.
    response_fit_blue_poly = np.polyfit(spec_wav_masked_blue,
                                        response_masked_blue,
                                        response_poly_order_blue)
    response_fit_blue = np.poly1d(response_fit_blue_poly)

    if redfile:
        response_poly_order_red = 3.
        response_fit_red_poly = np.polyfit(spec_wav_masked_red,
                                           response_masked_red,
                                           response_poly_order_red)
        response_fit_red = np.poly1d(response_fit_red_poly)

    #Save response function
    #np.savetxt('response_model_no_extinction.txt',np.transpose([obs_spectrablue.warr,response_fit_blue(obs_spectrablue.warr),obs_spectrared.warr,response_fit_red(obs_spectrared.warr)]))
    #plt.clf()
    #plt.plot(obs_spectrablue.warr,response_fit_blue(obs_spectrablue.warr)/response_fit_blue(obs_spectrablue.warr)[1000])
    #plt.show()
    #exit()
    if plotall:
        plt.clf()
        plt.plot(obs_spectrablue.warr, response_blue, 'r')
        plt.plot(spec_wav_masked_blue, response_masked_blue, 'g.')
        plt.plot(obs_spectrablue.warr, response_fit_blue(obs_spectrablue.warr),
                 'k--')
        #plt.show()

        #plt.clf()
        if redfile:
            plt.plot(obs_spectrared.warr, response_red, 'r')
            plt.plot(spec_wav_masked_red, response_masked_red, 'g.')
            plt.plot(obs_spectrared.warr,
                     response_fit_red(obs_spectrared.warr), 'k--')
        plt.show()

    #Divide by the fit to the response function to get the continuum normalized spectra. Divide every extension by the same polynomial
    fcorr_wd_blue_opfarr = obs_spectrablue.opfarr / response_fit_blue(
        obs_spectrablue.warr)
    fcorr_wd_blue_farr = obs_spectrablue.farr / response_fit_blue(
        obs_spectrablue.warr)
    fcorr_wd_blue_sky = obs_spectrablue.sky / response_fit_blue(
        obs_spectrablue.warr)
    fcorr_wd_blue_sigma = obs_spectrablue.sigma / response_fit_blue(
        obs_spectrablue.warr)

    if redfile:
        fcorr_wd_red_opfarr = obs_spectrared.opfarr / response_fit_red(
            obs_spectrared.warr)
        fcorr_wd_red_farr = obs_spectrared.farr / response_fit_red(
            obs_spectrared.warr)
        fcorr_wd_red_sky = obs_spectrared.sky / response_fit_red(
            obs_spectrared.warr)
        fcorr_wd_red_sigma = obs_spectrared.sigma / response_fit_red(
            obs_spectrared.warr)

    if plotall:
        plt.clf()
        plt.plot(obs_spectrablue.warr, fcorr_wd_blue_opfarr, 'b')
        if redfile:
            plt.plot(obs_spectrared.warr, fcorr_wd_red_opfarr, 'r')
        plt.show()
    #exit()

    #Save parameters for diagnostics
    if redfile:
        bigarray = np.zeros([len(obs_spectrablue.warr), 12])
        bigarray[0:len(obs_spectrablue.warr), 0] = obs_spectrablue.warr
        bigarray[0:len(response_blue), 1] = response_blue
        bigarray[0:len(spec_wav_masked_blue), 2] = spec_wav_masked_blue
        bigarray[0:len(response_masked_blue), 3] = response_masked_blue
        bigarray[0:len(response_fit_blue(obs_spectrablue.warr)),
                 4] = response_fit_blue(obs_spectrablue.warr)
        bigarray[0:len(fcorr_wd_blue_opfarr), 5] = fcorr_wd_blue_opfarr
        bigarray[0:len(obs_spectrared.warr), 6] = obs_spectrared.warr
        bigarray[0:len(response_red), 7] = response_red
        bigarray[0:len(spec_wav_masked_red), 8] = spec_wav_masked_red
        bigarray[0:len(response_masked_red), 9] = response_masked_red
        bigarray[0:len(response_fit_red(obs_spectrared.warr)),
                 10] = response_fit_red(obs_spectrared.warr)
        bigarray[0:len(fcorr_wd_red_opfarr), 11] = fcorr_wd_red_opfarr
        now = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M")
        endpoint = '_930'
        with open(
                'continuum_normalization_' +
                filenameblue[5:filenameblue.find(endpoint)] + '_' + now +
                '.txt', 'a') as handle:
            header = str(filenameblue) + ',' + str(
                filenamered
            ) + ',' + dafile + '\n Columns structured as blue then red. If no red file, only blue data given. Columns are: blue wavelengths, blue response all data, blue masked wavelengths, blue masked response data, blue response fit, blue continuum-normalize flux, red wavelengths, red response all data, red masked wavelengths, red masked response data, red response fit, red continuum-normalized flux'
            np.savetxt(handle, bigarray, fmt='%f', header=header)
    if not redfile:
        bigarray = np.zeros([len(obs_spectrablue.warr), 6])
        bigarray[0:len(obs_spectrablue.warr), 0] = obs_spectrablue.warr
        bigarray[0:len(response_blue), 1] = response_blue
        bigarray[0:len(spec_wav_masked_blue), 2] = spec_wav_masked_blue
        bigarray[0:len(response_masked_blue), 3] = response_masked_blue
        bigarray[0:len(response_fit_blue(obs_spectrablue.warr)),
                 4] = response_fit_blue(obs_spectrablue.warr)
        bigarray[0:len(fcorr_wd_blue_opfarr), 5] = fcorr_wd_blue_opfarr
        now = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M")
        endpoint = '_930'
        with open(
                'continuum_normalization_' +
                filenameblue[5:filenameblue.find(endpoint)] + '_' + now +
                '.txt', 'a') as handle:
            header = str(
                filenameblue
            ) + ',' + ',' + dafile + '\n Columns structured as blue then red. If no red file, only blue data given. Columns are: blue wavelengths, blue response all data, blue masked wavelengths, blue masked response data, blue response fit, blue continuum-normalized flux'
            np.savetxt(handle, bigarray, fmt='%f', header=header)

    #Save the continuum normalized spectra here.
    Ni = 4.  #Number of extensions
    Nx1 = len(fcorr_wd_blue_opfarr)
    if redfile:
        Nx2 = len(fcorr_wd_red_opfarr)
    Ny = 1.  #All 1D spectra

    #Update header
    header1 = st.readheader(filenameblue)
    header1.set('STANDARD', dafile, 'DA Model for Continuum Calibration')
    header1.set('RESPPOLY', response_poly_order_blue,
                'Polynomial order for Response Function')
    header1.set('DATENORM',
                datetime.datetime.now().strftime("%Y-%m-%d"),
                'Date of Continuum Normalization')

    data1 = np.empty(shape=(Ni, Ny, Nx1))
    data1[0, :, :] = fcorr_wd_blue_opfarr
    data1[1, :, :] = fcorr_wd_blue_farr
    data1[2, :, :] = fcorr_wd_blue_sky
    data1[3, :, :] = fcorr_wd_blue_sigma

    #Check that filename does not already exist. Prompt user for input if it does.
    loc1 = filenameblue.find('.ms.fits')
    newname1 = filenameblue[0:loc1] + '_flux_model_short.ms.fits'
    clob = False
    mylist = [True for f in os.listdir('.') if f == newname1]
    exists = bool(mylist)

    if exists:
        print 'File %s already exists.' % newname1
        nextstep = raw_input(
            'Do you want to overwrite or designate a new name (overwrite/new)? '
        )
        if nextstep == 'overwrite':
            clob = True
            exists = False
        elif nextstep == 'new':
            newname1 = raw_input('New file name: ')
            exists = False
        else:
            exists = False
    print 'Writing ', newname1
    newim1 = fits.PrimaryHDU(data=data1, header=header1)
    newim1.writeto(newname1, clobber=clob)

    #Save the red file if it exists.
    if redfile:
        header2 = st.readheader(filenamered)
        header2.set('STANDARD', dafile, 'DA Model for Continuum Calibration')
        header2.set('RESPPOLY', response_poly_order_red,
                    'Polynomial order for Response Function')
        header2.set('DATENORM',
                    datetime.datetime.now().strftime("%Y-%m-%d"),
                    'Date of Continuum Normalization')
        data2 = np.empty(shape=(Ni, Ny, Nx2))
        data2[0, :, :] = fcorr_wd_red_opfarr
        data2[1, :, :] = fcorr_wd_red_farr
        data2[2, :, :] = fcorr_wd_red_sky
        data2[3, :, :] = fcorr_wd_red_sigma

        loc2 = filenamered.find('.ms.fits')
        newname2 = filenamered[0:loc2] + '_flux_model_short.ms.fits'
        clob = False
        mylist = [True for f in os.listdir('.') if f == newname2]
        exists = bool(mylist)

        if exists:
            print 'File %s already exists.' % newname2
            nextstep = raw_input(
                'Do you want to overwrite or designate a new name (overwrite/new)? '
            )
            if nextstep == 'overwrite':
                clob = True
                exists = False
            elif nextstep == 'new':
                newname2 = raw_input('New file name: ')
                exists = False
            else:
                exists = False
        print 'Writing ', newname2
        newim2 = fits.PrimaryHDU(data=data2, header=header2)
        newim2.writeto(newname2, clobber=clob)
    now = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M")
    endpoint = '_930'
    with open('continuum_normalization_' + filenameblue[5:filenameblue.find(endpoint)] + '_' + now + '.txt','a') as handle:
        header = str(filenameblue) + ',' + ',' + dafile + '\n Columns structured as blue then red. If no red file, only blue data given. Columns are: blue wavelengths, blue response all data, blue masked wavelengths, blue masked response data, blue response fit, blue continuum-normalized flux'
        np.savetxt(handle,bigarray,fmt='%f',header=header)
    
    
#Save the continuum normalized spectra here.
Ni = 4. #Number of extensions
Nx1 = len(fcorr_wd_blue_opfarr)
if redfile:
    Nx2 = len(fcorr_wd_red_opfarr)
Ny = 1. #All 1D spectra

#Update header
header1 = st.readheader(filenameblue)
header1.set('STANDARD',dafile,'DA Model for Continuum Calibration')
header1.set('RESPPOLY',response_poly_order_blue,'Polynomial order for Response Function')
header1.set('DATENORM',datetime.datetime.now().strftime("%Y-%m-%d"),'Date of Continuum Normalization')


data1 = np.empty(shape = (Ni,Ny,Nx1))
data1[0,:,:] = fcorr_wd_blue_opfarr 
data1[1,:,:] = fcorr_wd_blue_farr
data1[2,:,:] = fcorr_wd_blue_sky
data1[3,:,:] = fcorr_wd_blue_sigma 

#Check that filename does not already exist. Prompt user for input if it does.
loc1 = filenameblue.find('.ms.fits')
newname1 = filenameblue[0:loc1] + '_flux_model.ms.fits'
clob = False
Пример #3
0
    sigma_flux1 = st.cal_spec(WD_spectra1.sigma,sens_wave1,exptime1,dispersion1)

    if redfile:
        star_opflux2 = st.cal_spec(WD_spectra2.opfarr,sens_wave2,exptime2,dispersion2)
        star_flux2 = st.cal_spec(WD_spectra2.farr,sens_wave2,exptime2,dispersion2)
        sky_flux2 = st.cal_spec(WD_spectra2.sky,sens_wave2,exptime2,dispersion2)
        sigma_flux2 = st.cal_spec(WD_spectra2.sigma,sens_wave2,exptime2,dispersion2)

    #plt.clf()
    #plt.plot(WD_spectra.warr,star_opflux)
    #plt.show()

    print 'Saving the final spectrum.'

    #Save the flux-calibrated spectrum and update the header
    header1 = st.readheader(specfile[avocado])
    header1.set('EX-FLAG',-1) #Extiction correction? 0=yes, -1=no
    header1.set('CA-FLAG',0) #Calibrated to flux scale? 0=yes, -1=no
    header1.set('BUNIT','erg/cm2/s/A') #physical units of the array value
    header1.set('STANDARD',str(standards[choice]),'Flux standard used') #flux standard used for flux-calibration

    if redfile:
        header2 = st.readheader(specfile[avocado+1])
        header2.set('EX-FLAG',-1) #Extiction correction? 0=yes, -1=no
        header2.set('CA-FLAG',0) #Calibrated to flux scale? 0=yes, -1=no
        header2.set('BUNIT','erg/cm2/s/A') #physical units of the array value
        header2.set('STANDARD',str(standards[choice+1]),'Flux standard used') #flux standard used for flux-calibration

    #Set up size of new fits image
    Ni = 4. #Number of extensions
    Nx1 = len(star_flux1)
signal = np.mean(shortspec)
noise = np.sqrt(np.sum((shortspec-bestline)**2.) / float(len(bestline))) #Noise from RMS
#noise = np.mean(shortsigma) #noise from sigma spectrum
sn_res_ele = signal/noise * np.sqrt(fwhm)
print 'Signal to Noise is: ', sn_res_ele

#plt.clf()
#plt.plot(shortpix,shortspec,'b')
#plt.plot(shortpix,bestline,'g')
#plt.show()

#exit()

#Get the image header and add keywords
header = st.readheader(specfile)
header.set('BANDID1','Optimally Extracted Spectrum')
header.set('BANDID2','Raw Extracted Spectrum')
header.set('BANDID3','Mean Background')
header.set('BANDID4','Sigma Spectrum')
header.set('DISPCOR',0) #Dispersion axis of image
fwhmsave = np.round(fwhm,decimals=4)
snrsave = np.round(sn_res_ele,decimals=4)
header.set('SPECFWHM',fwhmsave,'FWHM of spectrum in pixels') #FWHM of spectrum in pixels
header.set('SNR',snrsave,'Signal to Noise per resolution element') 
header.set('DATEEXTR',datetime.datetime.now().strftime("%Y-%m-%d"),'Date of Spectral Extraction')

#Save the extracted image
Ni = 4. #Number of extensions
Nx = 1. #All 1D spectra
Ny = len(output_spec.spectrum[:,0])
def extract_now(specfile,lamp,FWHMfile,tracefile,trace_exist=False):
    #Open file and read gain and readnoise
    datalist = fits.open(specfile)
    data = datalist[0].data
    data = np.transpose(data[0,:,:])
    
    #Since we have combined multiple images, to keep our statistics correct, we need to multiply the values in ADU by the number of images
    try:
        nimages = float(datalist[0].header['NCOMBINE'])
    except:
        nimages = 1.
    
    data = nimages * data
    
    #gain = datalist[0].header['GAIN']
    gain = 1.33 #from 2017-06-07
    rdnoise = np.sqrt(nimages) * datalist[0].header['RDNOISE']

    #Calculate the variance of each pixel in ADU
    varmodel = ((nimages*rdnoise**2.) + np.absolute(data)*gain)/gain
    
    #Fit a Gaussian every 10 pixels to determine FWHM for convolving in the model fitting, unless this file already exists
    fitpixel = np.arange(3,len(data[:,100]),10)
    allfwhm = np.zeros(len(fitpixel))
    for x in fitpixel:
        #forfit = data[x,2:]
        forfit = np.median(np.array([data[x-2,2:],data[x-1,2:],data[x,2:],data[x+1,2:],data[x+2,2:]]),axis=0)
        guess = np.zeros(4)
        guess[0] = np.mean(forfit)
        guess[1] = np.amax(forfit)
        guess[2] = np.argmax(forfit)
        guess[3] = 3.
        error_fit = np.ones(len(forfit))
        xes = np.linspace(0,len(forfit)-1,num=len(forfit))
        fa = {'x':xes,'y':forfit,'err':error_fit}
        fitparams = mpfit.mpfit(fitgauss,guess,functkw=fa,quiet=True)
        allfwhm[np.argwhere(fitpixel == x)] = 2.*np.sqrt(2.*np.log(2.))*fitparams.params[3]
        #plt.clf()
        #plt.plot(forfit)
        #plt.plot(xes,gauss(xes,fitparams.params))
        #plt.show()
        
    fwhmclipped = SigClip(allfwhm,3,3)
    
    if not FWHMfile:
    #Fit using a line, but give user the option to fit with a different order
        order = 1
        repeat = 'yes'
        while repeat == 'yes':
            fwhmpolyvalues = np.polyfit(fitpixel,fwhmclipped,order)
            allpixel = np.arange(0,len(data[:,100]),1)
            fwhmpoly = np.poly1d(fwhmpolyvalues)
            plt.clf()
            plt.plot(fitpixel,fwhmclipped,'^')
            plt.plot(allpixel,fwhmpoly(allpixel),'g')
            plt.title(specfile)
            plt.show()
            repeat = raw_input('Do you want to try again (yes/no)? ')
            if repeat == 'yes':
                order = raw_input('New order for polynomial: ')
        
        
        locfwhm = specfile.find('.fits')
        print '\n Saving FWHM file.'
        np.save(specfile[0:locfwhm] + '_poly',fwhmpoly(allpixel))
    diagnostics = np.zeros([len(data[:,100]),12])
    diagnostics[0:len(allfwhm),0] = fwhmclipped
    diagnostics[0:len(fitpixel),1] = fitpixel
    if not FWHMfile:
        diagnostics[0:len(allpixel),2] = fwhmpoly(allpixel)
        diagnostics[0:len(allpixel),3] = allpixel
    else:
        fwhm_fit = np.load(FWHMfile)
        allpixel = np.arange(0,len(data[:,100]),1)
        diagnostics[0:len(fwhm_fit),2] = fwhm_fit
        diagnostics[0:len(allpixel),3] = allpixel
    
    #===============================
    #Section to prepare inputs for extraction
    #===============================
    
    
    #Fit a column of the 2D image to determine the FWHM in pixels
    if 'blue' in specfile.lower():
        #Average over 5 rows to deal with any remaining cosmic rays
        forfit = np.mean(np.array([data[1198,:],data[1199,:],data[1200,:],data[1201,:],data[1202,:]]),axis=0)
    elif 'red' in specfile.lower():
        forfit = np.mean(np.array([data[998,:],data[999,:],data[1000,:],data[1001,:],data[1002,:]]),axis=0)
    

    guess = np.zeros(4)
    guess[0] = np.mean(forfit)
    guess[1] = np.amax(forfit)
    guess[2] = np.argmax(forfit)
    guess[3] = 3.
    
    error_fit = np.ones(len(forfit))
    xes = np.linspace(0,len(forfit)-1,num=len(forfit))
    fa = {'x':xes,'y':forfit,'err':error_fit}
    fitparams = mpfit.mpfit(fitgauss,guess,functkw=fa,quiet=True)
    
    #The guassian gives us sigma, convert to FWHM
    fwhm = 2.*np.sqrt(2.*np.log(2.))*fitparams.params[3]
    extraction_rad = 5. * np.round(fwhm,decimals=1) #Extract up to 5 times FWHM
    
    
    #Check to make sure background region does not go within 10 pixels of edge
    background_radii = [35,60]
    #First check this against the bottom
    if fitparams.params[2] - background_radii[1] < 10.:
        background_radii[1] = fitparams.params[2] - 10.
        background_radii[0] -= 60 - background_radii[1]
    #Then check against the top
    hold = background_radii[1]
    if fitparams.params[2] + background_radii[1] > 190.:
        background_radii[1] = 190. - fitparams.params[2]
        background_radii[0] -= hold - background_radii[1]
    #Ensure that the closest point is at least 20 pixels away.
    if background_radii[0] < 20.:
        background_radii[0] = 20.
    background_radii[0] = np.round(background_radii[0],decimals=1)
    background_radii[1] = np.round(background_radii[1],decimals=1)
    #plt.plot(data[1200,:])
    #plt.plot(xes,gauss(xes,fitparams.params))
    #plt.show()
    #extraction_rad = 10.
    #background_radii = [40,60]
    
    
    #Extract the spectrum using superextract
    print 'Starting extraction.'
    if trace_exist:
        trace = np.load(tracefile)
        output_spec = superextract.superExtract(data,varmodel,gain,rdnoise,trace=trace,pord=2,tord=2,bord=1,bkg_radii=background_radii,bsigma=2.,extract_radius=extraction_rad,dispaxis=1,verbose=False,csigma=5.,polyspacing=1,retall=False)
    else:
        output_spec = superextract.superExtract(data,varmodel,gain,rdnoise,pord=2,tord=2,bord=1,bkg_radii=background_radii,bsigma=2.,extract_radius=extraction_rad,dispaxis=1,verbose=False,csigma=5.,polyspacing=1,retall=False)
    #pord = order of profile polynomial. Default = 2. This seems appropriate, no change for higher or lower order.
    #tord = degree of spectral-trace polynomial, 1 = line
    #bord = degree of polynomial background fit
    #bkg_radii = inner and outer radii to use in computing background. Goes on both sides of aperture.  
    #bsigma = sigma-clipping thresholf for computing background
    #extract_radius: radius for spectral extraction. Setting this to be 5*FWHM
    #csigma = sigma-clipping threshold for cleaning & cosmic-ray rejection. Default = 5.
    #qmode: how to compute Marsh's Q-matrix. 'fast-linear' default and preferred.
    #nreject = number of outlier-pixels to reject at each iteration. Default = 100
    #polyspacing = Marsh's S: the spacing between the polynomials. This should be <= 1. Default = 1. Best to leave at 1. S/N decreases dramatically if greater than 1. If less than one, slower but final spectrum is the same. Crossfield note: A few cursory tests suggests that the extraction precision (in the high S/N case) scales as S^-2 -- but the code slows down as S^2.
    #Verbose=True if you want lots of output

    ###########
    # In superextract, to plot a 2D frame at any point, use the following
    #   plt.clf()
    #   plt.imshow(np.transpose(frame),aspect='auto',interpolation='nearest')
    #   plt.show()
    ##########
    
    print 'Done extracting. Starting to save.'
    if not trace_exist:
        print 'Saving the trace.'
        np.save(specfile[0:locfwhm] + '_trace',output_spec.trace)
    sigSpectrum = np.sqrt(output_spec.varSpectrum)
    #plt.clf()
    #plt.imshow(data)
    #plt.plot(output_spec.spectrum,'b')
    #plt.plot(output_spec.raw,'g')
    #plt.plot(output_spec.varSpectrum,'r')
    #plt.plot(sigSpectrum,'r')
    #plt.plot(output_spec.trace,'m')
    #plt.plot(output_spec.tracepos[0],output_spec.tracepos[1],'b^')
    #plt.plot(output_spec.background,'k')
    #plt.plot(output_spec.profile_map,'b')
    #plt.show()
    #plt.clf()
    #plt.plot(output_spec.extractionApertures)
    #plt.show()
    #plt.clf()
    #plt.plot(output_spec.background_map)
    #plt.show()
    
    #Save diagnostic info
    diagnostics[0:len(output_spec.tracepos[0]),4] = output_spec.tracepos[0]
    diagnostics[0:len(output_spec.tracepos[1]),5] = output_spec.tracepos[1]
    diagnostics[0:len(output_spec.trace),6] = output_spec.trace
    diagnostics[0:len(output_spec.backgroundcolumnpixels),7] = output_spec.backgroundcolumnpixels
    diagnostics[0:len(output_spec.backgroundcolumnvalues),8] = output_spec.backgroundcolumnvalues
    diagnostics[0:len(output_spec.backgroundfitpixels),9] = output_spec.backgroundfitpixels
    diagnostics[0:len(output_spec.backgroundfitvalues),10] = output_spec.backgroundfitvalues
    diagnostics[0:len(output_spec.backgroundfitpolynomial),11] = output_spec.backgroundfitpolynomial
    now = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M")
    endpoint = '.fits'
    with open('extraction_' + specfile[4:specfile.find(endpoint)] + '_' + now + '.txt','a') as handle:
        header = 'Columns are: 1) Measured FWHM, 2) pixel value of each FWHM, 3) fit to FWHM measurements, 4) all pixel values, 5) profile pixels, 6) profile position, 7) fit profile positions, 8) Pixels values of cut at pixel 1200, 9) Values along column 1200, 10) Pixels of fit to background, 11) Values used for fit, 12) polynomial fit to background'
        np.savetxt(handle,diagnostics,fmt='%f',header=header)
    
    #Compute the extracted signal to noise and save to header
    if 'blue' in specfile.lower():
        low_pixel, high_pixel = 1125., 1175.
    elif 'red' in specfile.lower():
        low_pixel, high_pixel = 825., 875.
    shortspec = output_spec.spectrum[:,0][low_pixel:high_pixel]
    shortsigma = sigSpectrum[:,0][low_pixel:high_pixel]
    shortpix = np.linspace(low_pixel,high_pixel,num=(high_pixel-low_pixel),endpoint=False)
    guessline = np.zeros(2)
    guessline[0] = (shortspec[-1] - shortspec[0]) / (shortpix[-1]-shortpix[0])
    guessline[1] = shortspec[0]-guessline[0]*shortpix[0]
    par, cov = curve_fit(line,shortpix,shortspec,guessline)
    bestline = line(shortpix,par[0],par[1])
    
    signal = np.mean(shortspec)
    noise = np.sqrt(np.sum((shortspec-bestline)**2.) / float(len(bestline))) #Noise from RMS
    #noise = np.mean(shortsigma) #noise from sigma spectrum
    sn_res_ele = signal/noise * np.sqrt(fwhm)
    print 'Signal to Noise is: ', sn_res_ele
    
    #plt.clf()
    #plt.plot(shortpix,shortspec,'b')
    #plt.plot(shortpix,bestline,'g')
    #plt.show()
    
    #exit()

    #Get the image header and add keywords
    header = st.readheader(specfile)
    header.set('BANDID1','Optimally Extracted Spectrum')
    header.set('BANDID2','Raw Extracted Spectrum')
    header.set('BANDID3','Mean Background')
    header.set('BANDID4','Sigma Spectrum')
    header.set('DISPCOR',0) #Dispersion axis of image
    fwhmsave = np.round(fwhm,decimals=4)
    snrsave = np.round(sn_res_ele,decimals=4)
    header.set('SPECFWHM',fwhmsave,'FWHM of spectrum in pixels') #FWHM of spectrum in pixels
    header.set('SNR',snrsave,'Signal to Noise per resolution element') 
    header.set('DATEEXTR',datetime.datetime.now().strftime("%Y-%m-%d"),'Date of Spectral Extraction')
    
    #Save the extracted image
    Ni = 4. #Number of extensions
    Nx = 1. #All 1D spectra
    Ny = len(output_spec.spectrum[:,0])
    spectrum = np.empty(shape = (Ni,Nx,Ny))
    spectrum[0,:,:] = output_spec.spectrum[:,0]
    spectrum[1,:,:] = output_spec.raw[:,0]
    spectrum[2,:,:] = output_spec.background
    spectrum[3,:,:] = sigSpectrum[:,0]
    
    #Save the extracted spectra with .ms.fits in the filename
    #Ask to overwrite if file already exists or provide new name
    loc = specfile.find('.fits')
    newname = specfile[0:loc] + '.ms.fits'
    clob = False

    mylist = [True for f in os.listdir('.') if f == newname]
    exists = bool(mylist)

    if exists:
        print 'File %s already exists.' % newname
        nextstep = raw_input('Do you want to overwrite or designate a new name (overwrite/new)? ')
        if nextstep == 'overwrite':
            clob = True
            exists = False
        elif nextstep == 'new':
            newname = raw_input('New file name: ')
            exists = False
        else:
            exists = False
    
    
    newim = fits.PrimaryHDU(data=spectrum,header=header)
    newim.writeto(newname,clobber=clob)
    print 'Wrote %s to file.' % newname
    
    #Save parameters to a file for future reference. 
    # specfile,date of extraction, extration_rad,background_radii,newname,newname2
    f = open('extraction_params.txt','a')
    now = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M")
    newinfo = specfile + '\t' + now + '\t' + str(extraction_rad) + '\t' + str(background_radii) + '\t' + newname
    f.write(newinfo + "\n")
    f.close()
    
    ###########################
    #Extract a lamp spectrum using the trace from above
    ##########################
    
    
    if lamp != 'no':
        lamplist = fits.open(lamp)
        lampdata = lamplist[0].data
        lampdata = lampdata[0,:,:]
        lampdata = np.transpose(lampdata)

        #extraction radius will be the FWHM the star
        #But since the Fe lamps are taken binned by 1 in spectral direction, we need to adjust the trace to match.
        #We do that by expanding out the trace to match the length of the Fe lamps, then interpolate and read off values for every pixel.
        bin2size = np.arange(1,len(output_spec.trace)+1)
        bin1size = np.arange(1,len(lampdata)+1)
        ratio = float(len(bin1size)) / float(len(bin2size))
        interpolates = InterpolatedUnivariateSpline(ratio*bin2size,output_spec.trace,k=1)
        newtrace = interpolates(bin1size)
        
        #Do the extraction here.
        lamp_radius = np.ceil(fwhm) #Make sure that extraction radius is a whole number, otherwise you'll get odd structures.
        lampspec = lampextract(lampdata,newtrace,lamp_radius)
        
        #Save the 1D lamp
        lampheader = st.readheader(lamp)
        lampheader.set('BANDID2','Raw Extracted Spectrum')
        lampheader.set('REF',newname,'Reference Star used for trace')
        lampheader.set('DATEEXTR',datetime.datetime.now().strftime("%Y-%m-%d"),'Date of Spectral Extraction')

        Ni = 1. #We are writing just 1 1D spectrum
        Ny = len(lampspec[:,0])
        lampspectrum = np.empty(shape = (Ni,Ny))
        lampspectrum[0,:] = lampspec[:,0]
        
        #Save the extracted spectra with .ms.fits in the filename
        #Ask to overwrite if file already exists or provide new name
        loc2 = lamp.find('.fits')
        loc3 = newname.find('_930')
        newname2 = lamp[0:loc2] + '_' + newname[5:loc3]  + '.ms.fits'
        clob = False

        mylist = [True for f in os.listdir('.') if f == newname2]
        exists = bool(mylist)

        if exists:
            print 'File %s already exists.' % newname2
            nextstep = raw_input('Do you want to overwrite or designate a new name (overwrite/new)? ')
            if nextstep == 'overwrite':
                clob = True
                exists = False
            elif nextstep == 'new':
                newname2 = raw_input('New file name: ')
                exists = False
            else:
                exists = False


        lampim = fits.PrimaryHDU(data=lampspectrum,header=lampheader)
        lampim.writeto(newname2,clobber=clob)
        print 'Wrote %s to file.' % newname2
        
        #Save parameters to a file for future reference. 
        # specfile,date of extraction, extration_rad,background_radii,newname,newname2
        background_radii2 = [0,0] #We do not extract a background for the lamp
        f = open('extraction_params.txt','a')
        now = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M")
        newinfo2 = lamp + '\t' + now + '\t' + str(extraction_rad) + '\t' + str(background_radii2) + '\t' + newname2
        f.write(newinfo2 + "\n")
        f.close()
Пример #6
0
def flux_calibrate_now(stdlist,
                       fluxlist,
                       speclist,
                       extinct_correct=False,
                       masterresp=False):
    if extinct_correct:
        extinctflag = 0
    else:
        extinctflag = -1
    if masterresp:  #Use the master response function
        #Read in master response function and use that.
        cwd = os.getcwd()
        os.chdir(
            '/afs/cas.unc.edu/depts/physics_astronomy/clemens/students/group/standards/response_curves/'
        )
        standards = sorted(glob('*resp*.npy'))

        master_response_blue_in = np.load(standards[0])
        master_response_blue_in_pol = np.poly1d(master_response_blue_in)
        master_response_blue_out = np.load(standards[1])
        master_response_blue_out_pol = np.poly1d(master_response_blue_out)
        master_response_red_in = np.load(standards[2])
        master_response_red_in_pol = np.poly1d(master_response_red_in)
        master_response_red_out = np.load(standards[3])
        master_response_red_out_pol = np.poly1d(master_response_red_out)

        os.chdir(cwd)

        airstd = np.ones([4])
        #airstd[0] = 1.1

        #For saving files correctly
        stdflux = np.array(['mmaster.dat'])
        #standards = np.array([masterlist])
        allexcluded = [[None] for i in range(len(standards))]
        orderused = np.zeros([len(standards)])
        size = 0.

        #Find shift for each night
        #For blue setup: use mean of 4530-4590
        #for red setup: use mean of 6090-6190
        try:
            flux_tonight_list = np.genfromtxt('response_curves.txt', dtype=str)
            print 'Found response_curves.txt file.'
            print flux_tonight_list
            if flux_tonight_list.size == 1:
                flux_tonight_list = np.array([flux_tonight_list])
            for x in flux_tonight_list:
                #print x
                if 'blue' in x.lower():
                    wave_tonight, sens_tonight = np.genfromtxt(x, unpack=True)
                    blue_low_index = np.min(np.where(wave_tonight > 4530.))
                    blue_high_index = np.min(np.where(wave_tonight > 4590.))
                    blue_mean_tonight = np.mean(
                        sens_tonight[blue_low_index:blue_high_index])
                elif 'red' in x.lower():
                    wave_tonight, sens_tonight = np.genfromtxt(x, unpack=True)
                    red_low_index = np.min(np.where(wave_tonight > 6090.))
                    red_high_index = np.min(np.where(wave_tonight > 6190.))
                    red_mean_tonight = np.mean(
                        sens_tonight[red_low_index:red_high_index])
        except:
            print 'No response_curves.txt file found.'
            blue_mean_tonight = None
            red_mean_tonight = None
            flux_tonight_list = ['None', 'None']

    else:  #Use the standard star fluxes in the typical manner
        #Read in each standard star spectrum
        standards = np.genfromtxt(stdlist, dtype=str)
        if standards.size == 1:
            standards = np.array([standards])
        stdflux = np.genfromtxt(fluxlist, dtype=str)
        if stdflux.size == 1:
            stdflux = np.array(
                [stdflux]
            )  #save stdflux explicitly as an array so you can index if only 1 element
        #Check that the files are set up correctly to avoid mixing standards.
        #This checks that the files in liststandard have similar characters to those in listflux and the correct order. But might break if flux file doesn't match. E.G. mcd32d9927.dat is often called CD-32_9927 in our system.
        '''
        onion = 0
        for stanspec in standards:
            quickcheck = stdflux[onion//2].lower()[1:-4] in stanspec.lower()
            if not quickcheck:
                print 'Check your standard star and flux files. They are mixed up.'
                sys.exit()
            onion += 1
        '''
        orderused = np.zeros([len(standards)])
        senspolys = []
        airstd = np.zeros([len(standards)])
        allexcluded = [[None] for i in range(len(standards))]

        #Calculating the sensitivity function of each standard star
        cucumber = 0
        for stdspecfile in standards:
            print stdspecfile
            #Read in the observed spectrum of the standard star
            obs_spectra, airmass, exptime, dispersion = st.readspectrum(
                stdspecfile
            )  #obs_spectra is an object containing opfarr,farr,sky,sigma,warr
            airstd[cucumber] = airmass
            #plt.clf()
            #plt.plot(obs_spectra.warr,obs_spectra.opfarr)
            #plt.show()

            #Do the extinction correction
            if extinct_correct:
                print 'Extinction correcting spectra.'
                plt.clf()
                plt.plot(obs_spectra.warr, obs_spectra.opfarr)
                obs_spectra.opfarr = st.extinction_correction(
                    obs_spectra.warr, obs_spectra.opfarr, airmass)
                plt.plot(obs_spectra.warr, obs_spectra.opfarr)
                #plt.show()

            #Change to the standard star directory
            cwd = os.getcwd()
            os.chdir(
                '/afs/cas.unc.edu/depts/physics_astronomy/clemens/students/group/standards'
            )

            #read in the standard file
            placeholder = cucumber // 2
            stdfile = stdflux[placeholder]
            std_spectra = st.readstandard(stdfile)
            os.chdir(cwd)
            #plt.clf()
            #plt.plot(std_spectra.warr,std_spectra.magarr,'.')
            #plt.show()
            #Only keep the part of the standard file that overlaps with observation.
            lowwv = np.where(std_spectra.warr >= np.min(obs_spectra.warr))
            lowwv = np.asarray(lowwv)
            highwv = np.where(std_spectra.warr <= np.max(obs_spectra.warr))
            highwv = np.asarray(highwv)
            index = np.intersect1d(lowwv, highwv)

            std_spectra.warr = std_spectra.warr[index]
            std_spectra.magarr = std_spectra.magarr[index]
            std_spectra.wbin = std_spectra.wbin[index]

            #Convert from AB mag to fnu, then to fwave (ergs/s/cm2/A)
            stdzp = 3.68e-20  #The absolute flux per unit frequency at an AB mag of zero
            std_spectra.magarr = st.magtoflux(std_spectra.magarr, stdzp)
            std_spectra.magarr = st.fnutofwave(std_spectra.warr,
                                               std_spectra.magarr)

            #plt.clf()
            #plt.plot(std_spectra.warr,std_spectra.magarr,'.')
            #plt.show()
            #np.savetxt('hz4_stan.txt',np.transpose([std_spectra.warr,std_spectra.magarr]))
            #exit()

            #We want to rebin the observed spectrum to match with the bins in the standard file. This makes summing up counts significantly easier.
            #Set the new binning here.
            print 'Starting to rebin: ', stdspecfile
            low = np.rint(np.min(obs_spectra.warr))  #Rounds to nearest integer
            high = np.rint(np.max(obs_spectra.warr))
            size = 0.05  #size in Angstroms you want each bin

            num = (
                high - low
            ) / size + 1.  #number of bins. Must add one to get correct number.
            wavenew = np.linspace(low, high,
                                  num=num)  #wavelength of each new bin

            #Now do the rebinning using Ian Crossfield's rebinning package
            binflux = st.resamplespec(wavenew, obs_spectra.warr,
                                      obs_spectra.opfarr,
                                      200.)  #200 is the oversampling factor
            print 'Done rebinning. Now summing the spectrum into new bins to match', stdfile
            #plt.clf()
            #plt.plot(obs_spectra.warr,obs_spectra.opfarr)
            #plt.plot(wavenew,binflux)
            #plt.show()

            #Now sum the rebinned spectra into the same bins as the standard star file
            counts = st.sum_std(std_spectra.warr, std_spectra.wbin, wavenew,
                                binflux)
            #plt.clf()
            #plt.plot(std_spectra.warr,std_spectra.magarr)
            #plt.plot(obs_spectra.warr,obs_spectra.opfarr,'b')
            #plt.plot(std_spectra.warr,counts,'g+')
            #plt.show()

            #Calculate the sensitivity function
            sens_function = st.sensfunc(counts, std_spectra.magarr, exptime,
                                        std_spectra.wbin, airmass)
            #plt.clf()
            #plt.plot(std_spectra.warr,sens_function)
            #plt.show()
            #sys.exit()
            #Fit a low order polynomial to this function so that it is smooth.
            #The sensitivity function is in units of 2.5 * log10[counts/sec/Ang / ergs/cm2/sec/Ang]
            #Choose regions to not include in fit, first by checking if a mask file exists, and if not the prompt for user interaction.
            if 'blue' in stdspecfile.lower():
                std_mask = stdfile[0:-4] + '_blue_maskasdf.dat'
            if 'red' in stdspecfile.lower():
                std_mask = stdfile[0:-4] + '_red_maskasdf.dat'
            std_mask2 = glob(std_mask)
            if len(std_mask2) == 1.:
                print 'Found mask file.\n'
                mask = np.ones(len(std_spectra.warr))
                excluded_wave = np.genfromtxt(
                    std_mask)  #Read in wavelengths to exclude
                #print excluded_wave
                #print type(excluded_wave)
                #Find index of each wavelength
                excluded = []
                for x in excluded_wave:
                    #print x
                    #print np.where(std_spectra.warr == find_nearest(std_spectra.warr,x))
                    pix_val = np.where(
                        std_spectra.warr == find_nearest(std_spectra.warr, x))
                    excluded.append(pix_val[0][0])
                #print excluded
                lettuce = 0
                while lettuce < len(excluded):
                    mask[excluded[lettuce]:excluded[lettuce + 1] + 1] = 0
                    lettuce += 2
                excluded = np.array(excluded).tolist()
                allexcluded[cucumber] = excluded
                indices = np.where(mask != 0.)
                lambdasfit = std_spectra.warr[indices]
                fluxesfit = sens_function[indices]
            else:
                print 'No mask found. User interaction required.\n'

                global ax, fig, coords
                coords = []
                plt.clf()
                fig = plt.figure(1)
                ax = fig.add_subplot(111)
                ax.plot(std_spectra.warr, sens_function)
                cid = fig.canvas.mpl_connect('button_press_event', onclick)
                print 'Please click on both sides of regions you want to exclude. Then close the plot.'
                plt.title(
                    'Click both sides of regions you want to exclude. Then close the plot.'
                )
                plt.show(1)

                #Mask our the regions you don't want to fit
                #We need make sure left to right clicking and right to left clicking both work.
                mask = np.ones(len(std_spectra.warr))
                excluded = np.zeros(len(coords))
                lettuce = 0
                if len(coords) > 0:
                    while lettuce < len(coords):
                        x1 = np.where(std_spectra.warr == (find_nearest(
                            std_spectra.warr, coords[lettuce][0])))
                        excluded[lettuce] = np.asarray(x1)
                        lettuce += 1
                        x2 = np.where(std_spectra.warr == (find_nearest(
                            std_spectra.warr, coords[lettuce][0])))
                        if x2 < x1:
                            x1, x2 = x2, x1
                        mask[
                            x1[0][0]:x2[0][0] +
                            1] = 0  #have to add 1 here to the second index so that we exclude through that index. Most important for when we need to exclude the last point of the array.
                        excluded[lettuce - 1] = np.asarray(x1)
                        excluded[lettuce] = np.asarray(x2)
                        lettuce += 1

                excluded = np.array(excluded).tolist()
                allexcluded[cucumber] = excluded
                indices = np.where(mask != 0.)
                lambdasfit = std_spectra.warr[indices]
                fluxesfit = sens_function[indices]

                #Save masked wavelengths
                lambdasnotfit = std_spectra.warr[excluded]
                #print lambdasnotfit
                #print stdfile
                if 'blue' in stdspecfile.lower():
                    std_mask_name = stdfile[0:-4] + '_blue_mask.dat'
                if 'red' in stdspecfile.lower():
                    std_mask_name = stdfile[0:-4] + '_red_mask.dat'
                np.savetxt(std_mask_name,
                           np.transpose(np.array(lambdasnotfit)))
                #exit()

            ##Move back to directory with observed spectra
            #os.chdir(cwd)

            #Make sure they are finite
            ind1 = np.isfinite(lambdasfit) & np.isfinite(fluxesfit)
            lambdasfit = lambdasfit[ind1]
            fluxesfit = fluxesfit[ind1]

            print 'Fitting the sensitivity funtion now.'
            order = 4
            repeat = 'yes'
            while repeat == 'yes':
                p = np.polyfit(lambdasfit, fluxesfit, order)
                f = np.poly1d(p)
                smooth_sens = f(lambdasfit)
                residual = fluxesfit - smooth_sens
                plt.close()
                plt.ion()
                g, (ax1, ax2) = plt.subplots(2, sharex=True)
                ax1.plot(lambdasfit, fluxesfit, 'b+')
                ax1.plot(lambdasfit, smooth_sens, 'r', linewidth=2.0)
                ax1.set_ylabel('Sensitivity Function')
                ax2.plot(lambdasfit, residual, 'k+')
                ax2.set_ylabel('Residuals')
                ax1.set_title('Current polynomial order: %s' % order)
                g.subplots_adjust(hspace=0)
                plt.setp([a.get_xticklabels() for a in g.axes[:-1]],
                         visible=False)
                plt.show()
                plt.ioff()
                #Save this sensitivity curve
                '''
                try:
                    temp_file = fits.open(stdspecfile)
                    ADCstat = temp_file[0].header['ADCSTAT']
                except:
                    ADCstat = 'none'
                    pass
                if 'blue' in stdspecfile.lower():
                    resp_name = 'senscurve_' + stdfile[1:-4] + '_' + str(np.round(airstd[cucumber],decimals=3))  + '_' + ADCstat  + '_' + cwd[60:70] + '_blue.txt'
                elif 'red' in stdspecfile.lower():
                    resp_name = 'senscurve_' + stdfile[1:-4] + '_' + str(np.round(airstd[cucumber],decimals=3))  + '_' + ADCstat  + '_' + cwd[60:70] + '_red.txt'
                print resp_name
                #exit()
                np.savetxt(resp_name,np.transpose([lambdasfit,fluxesfit]))
                '''
                repeat = raw_input('Do you want to try again (yes/no)? ')
                if repeat == 'yes':
                    order = raw_input('New order for polynomial: ')

            orderused[cucumber] = order
            senspolys.append(f)

            #Save arrays for diagnostic plots
            if cucumber == 0:
                bigarray = np.zeros([len(lambdasfit), 4. * len(standards)])
                artichoke = 0
            bigarray[0:len(lambdasfit), artichoke] = lambdasfit
            bigarray[0:len(fluxesfit), artichoke + 1] = fluxesfit
            bigarray[0:len(smooth_sens), artichoke + 2] = smooth_sens
            bigarray[0:len(residual), artichoke + 3] = residual
            artichoke += 4

            cucumber += 1

        #Save fit and residuals into text file for diagnostic plotting later.
        #Need to save lambdasfit,fluxesfit,smooth_sens,residual for each standard
        #List of standards is found as standards
        now = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M")
        with open('sens_fits_' + now + '.txt', 'a') as handle:
            header = str(
                standards
            ) + '\n Set of four columns correspond to wavelength, observed flux, polynomial fit, \n and residuals for each standard listed above. \n You will probably need to strip zeros from the bottoms of some columns.'
            np.savetxt(handle, bigarray, fmt='%f', header=header)

    #Outline for next steps:
    #Read in both red and blue files
    #compute airmass and compare to airstd
    #choose best standard and flux calibrate both blue and red
    #save files and write to sensitivity_params.txt

    if speclist[-4:] == 'fits':
        specfile = np.array([speclist])
    else:
        specfile = np.genfromtxt(speclist, dtype=str)
        if specfile.size == 1:
            specfile = np.array([specfile])

    length = len(specfile)
    airwd = np.zeros([length])
    bean = 0
    #if length == 1:
    #    redfile = False
    #else:
    #    redfile = True

    avocado = 0
    while avocado < length:
        #Read in the blue and red spectra we want to flux calibrate. Save the airmass
        WD_spectra1, airmass1, exptime1, dispersion1 = st.readspectrum(
            specfile[avocado])
        if (len(specfile) >= 1) and (avocado + 1 < length):
            if 'red' in specfile[avocado + 1]:
                redfile = True
            else:
                redfile = False
        else:
            redfile = False
        if redfile:
            WD_spectra2, airmass2, exptime2, dispersion2 = st.readspectrum(
                specfile[avocado + 1])

        #Extinction correct WD
        if extinct_correct:
            print 'Extinction correcting spectra.'
            #plt.clf()
            #plt.plot(WD_spectra1.warr,WD_spectra1.opfarr)
            WD_spectra1.opfarr = st.extinction_correction(
                WD_spectra1.warr, WD_spectra1.opfarr, airmass1)
            WD_spectra1.farr = st.extinction_correction(
                WD_spectra1.warr, WD_spectra1.farr, airmass1)
            WD_spectra1.sky = st.extinction_correction(WD_spectra1.warr,
                                                       WD_spectra1.sky,
                                                       airmass1)
            WD_spectra1.sigma = st.extinction_correction(
                WD_spectra1.warr, WD_spectra1.sigma, airmass1)
            #plt.plot(WD_spectra1.warr,WD_spectra1.opfarr)
            #plt.show()

            if redfile:
                #plt.clf()
                #plt.plot(WD_spectra2.warr,WD_spectra2.opfarr)
                WD_spectra2.opfarr = st.extinction_correction(
                    WD_spectra2.warr, WD_spectra2.opfarr, airmass2)
                WD_spectra2.farr = st.extinction_correction(
                    WD_spectra2.warr, WD_spectra2.farr, airmass2)
                WD_spectra2.sky = st.extinction_correction(
                    WD_spectra2.warr, WD_spectra2.sky, airmass2)
                WD_spectra2.sigma = st.extinction_correction(
                    WD_spectra2.warr, WD_spectra2.sigma, airmass2)

                #zaplt.plot(WD_spectra2.warr,WD_spectra2.opfarr)
                #plt.show()
        airwd[avocado] = airmass1
        if redfile:
            airwd[avocado + 1] = airmass2
        #Compare the airmasses to determine the best standard star
        tomato = 0
        while tomato < len(airstd):
            if redfile:
                diff = np.absolute(
                    np.mean([airwd[avocado], airwd[avocado + 1]]) -
                    np.mean([airstd[tomato], airstd[tomato + 1]]))
            else:
                diff = np.absolute(airwd[avocado] - airstd[tomato])
            if tomato == 0:
                difference = diff
                choice = tomato
            if diff < difference:
                difference = diff
                choice = tomato
            tomato += 2

        #To get the flux calibration, perform the following
        #Flux = counts / (Exptime * dispersion * 10**(sens/2.5))
        #Get the sensitivity function at the correct wavelength spacing
        if masterresp:
            header_temp = st.readheader(specfile[avocado])
            ADCstatus = header_temp['ADCSTAT']
            if ADCstatus == 'IN':
                sens_wave1_unscale = master_response_blue_in_pol(
                    WD_spectra1.warr)
                blue_low_index = np.min(np.where(WD_spectra1.warr > 4530.))
                blue_high_index = np.min(np.where(WD_spectra1.warr > 4590.))
                blue_mean_stan = np.mean(
                    sens_wave1_unscale[blue_low_index:blue_high_index])
                if blue_mean_tonight == None:
                    sens_wave1 = sens_wave1_unscale
                else:
                    sens_wave1 = sens_wave1_unscale + (blue_mean_tonight -
                                                       blue_mean_stan)
                choice = 0
            else:
                sens_wave1_unscale = master_response_blue_out_pol(
                    WD_spectra1.warr)
                blue_low_index = np.min(np.where(WD_spectra1.warr > 4530.))
                blue_high_index = np.min(np.where(WD_spectra1.warr > 4590.))
                blue_mean_stan = np.mean(
                    sens_wave1_unscale[blue_low_index:blue_high_index])
                if blue_mean_tonight == None:
                    sens_wave1 = sens_wave1_unscale
                else:
                    sens_wave1 = sens_wave1_unscale + (blue_mean_tonight -
                                                       blue_mean_stan)
                choice = 1
            if redfile:
                header_temp = st.readheader(specfile[avocado + 1])
                ADCstatus = header_temp['ADCSTAT']
                if ADCstatus == 'IN':
                    sens_wave2_unscale = master_response_red_in_pol(
                        WD_spectra2.warr)
                    red_low_index = np.min(np.where(WD_spectra2.warr > 6090.))
                    red_high_index = np.min(np.where(WD_spectra2.warr > 6190.))
                    red_mean_stan = np.mean(
                        sens_wave2_unscale[red_low_index:red_high_index])
                    if red_mean_tonight == None:
                        sens_wave2 = sens_wave2_unscale
                    else:
                        sens_wave2 = sens_wave2_unscale + (red_mean_tonight -
                                                           red_mean_stan)
                    choice2 = 2
                else:
                    sens_wave2_unscale = master_response_red_out_pol(
                        WD_spectra2.warr)
                    red_low_index = np.min(np.where(WD_spectra2.warr > 6090.))
                    red_high_index = np.min(np.where(WD_spectra2.warr > 6190.))
                    red_mean_stan = np.mean(
                        sens_wave2_unscale[red_low_index:red_high_index])
                    if red_mean_tonight == None:
                        sens_wave2 = sens_wave2_unscale
                    else:
                        sens_wave2 = sens_wave2_unscale + (red_mean_tonight -
                                                           red_mean_stan)
                    choice2 = 3
        else:
            sens_wave1 = senspolys[choice](WD_spectra1.warr)
            if redfile:
                sens_wave2 = senspolys[choice + 1](WD_spectra2.warr)

        #Perform the flux calibration. We do this on the optimal extraction, non-variance weighted aperture, the sky spectrum, and the sigma spectrum.
        print 'Doing the final flux calibration.'
        #np.savetxt('response_g60-54_extinction_2016-03-17.txt',np.transpose([WD_spectra1.warr,(exptime1 * dispersion1 * 10.**(sens_wave1/2.5))]))#,WD_spectra2.warr,(exptime2 * dispersion2 * 10.**(sens_wave2/2.5))]))
        #exit()
        star_opflux1 = st.cal_spec(WD_spectra1.opfarr, sens_wave1, exptime1,
                                   dispersion1)
        star_flux1 = st.cal_spec(WD_spectra1.farr, sens_wave1, exptime1,
                                 dispersion1)
        sky_flux1 = st.cal_spec(WD_spectra1.sky, sens_wave1, exptime1,
                                dispersion1)
        sigma_flux1 = st.cal_spec(WD_spectra1.sigma, sens_wave1, exptime1,
                                  dispersion1)

        if redfile:
            star_opflux2 = st.cal_spec(WD_spectra2.opfarr, sens_wave2,
                                       exptime2, dispersion2)
            star_flux2 = st.cal_spec(WD_spectra2.farr, sens_wave2, exptime2,
                                     dispersion2)
            sky_flux2 = st.cal_spec(WD_spectra2.sky, sens_wave2, exptime2,
                                    dispersion2)
            sigma_flux2 = st.cal_spec(WD_spectra2.sigma, sens_wave2, exptime2,
                                      dispersion2)

        #plt.clf()
        #plt.plot(WD_spectra.warr,star_opflux)
        #plt.show()

        #Save final spectra if using master response
        if masterresp:
            if avocado == 0:
                diagnostic_array = np.zeros(
                    [len(WD_spectra1.warr), 2 * length])
            diagnostic_array[0:len(WD_spectra1.warr), bean] = WD_spectra1.warr
            bean += 1
            diagnostic_array[0:len(star_opflux1), bean] = star_opflux1
            bean += 1
            if redfile:
                diagnostic_array[0:len(WD_spectra2.warr),
                                 bean] = WD_spectra2.warr
                bean += 1
                diagnostic_array[0:len(star_opflux2), bean] = star_opflux2
                bean += 1
        #if avocado == (length -1 ) or (redfile == True and avocado == (length-2)):
        #    print 'Saveing diagnostic file.'
        #    now = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M")
        #    with open('flux_fits_' + now + '.txt','a') as handle:
        #        header = str(specfile) + '\n Each star is formatted as wavelength, flux'
        #        np.savetxt(handle,diagnostic_array,fmt='%.10e',header=header)

        print 'Saving the final spectrum.'

        #Save the flux-calibrated spectrum and update the header
        header1 = st.readheader(specfile[avocado])
        header1.set('EX-FLAG',
                    extinctflag)  #Extiction correction? 0=yes, -1=no
        header1.set('CA-FLAG', 0)  #Calibrated to flux scale? 0=yes, -1=no
        header1.set('BUNIT', 'erg/cm2/s/A')  #physical units of the array value
        header1.set(
            'STANDARD', str(standards[choice]),
            'Flux standard used')  #flux standard used for flux-calibration
        if masterresp:
            header1.set('STDOFF', str(flux_tonight_list[0]),
                        'Night offset used')

        if redfile:
            header2 = st.readheader(specfile[avocado + 1])
            header2.set('EX-FLAG',
                        extinctflag)  #Extiction correction? 0=yes, -1=no
            header2.set('CA-FLAG', 0)  #Calibrated to flux scale? 0=yes, -1=no
            header2.set('BUNIT',
                        'erg/cm2/s/A')  #physical units of the array value
            if masterresp:
                header2.set('STANDARD', str(standards[choice2]),
                            'Flux standard used'
                            )  #flux standard used for flux-calibration
                header1.set('STDOFF', str(flux_tonight_list[1]),
                            'Night offset used')
            else:
                header2.set('STANDARD', str(standards[choice + 1]),
                            'Flux standard used'
                            )  #flux standard used for flux-calibration

        #Set up size of new fits image
        Ni = 4.  #Number of extensions
        Nx1 = len(star_flux1)
        if redfile:
            Nx2 = len(star_flux2)
        Ny = 1.  #All 1D spectra

        data1 = np.empty(shape=(Ni, Ny, Nx1))
        data1[0, :, :] = star_opflux1
        data1[1, :, :] = star_flux1
        data1[2, :, :] = sky_flux1
        data1[3, :, :] = sigma_flux1

        if redfile:
            data2 = np.empty(shape=(Ni, Ny, Nx2))
            data2[0, :, :] = star_opflux2
            data2[1, :, :] = star_flux2
            data2[2, :, :] = sky_flux2
            data2[3, :, :] = sigma_flux2

        #Add '_flux' to the end of the filename
        loc1 = specfile[avocado].find('.ms.fits')
        if masterresp:
            newname1 = specfile[avocado][0:loc1] + '_flux_' + stdflux[0][
                1:-4] + '.ms.fits'
        else:
            newname1 = specfile[avocado][0:loc1] + '_flux_' + stdflux[
                choice // 2][1:-4] + '.ms.fits'
        clob = False
        mylist = [True for f in os.listdir('.') if f == newname1]
        exists = bool(mylist)

        if exists:
            print 'File %s already exists.' % newname1
            nextstep = raw_input(
                'Do you want to overwrite or designate a new name (overwrite/new)? '
            )
            if nextstep == 'overwrite':
                clob = True
                exists = False
            elif nextstep == 'new':
                newname1 = raw_input('New file name: ')
                exists = False
            else:
                exists = False
        print 'Saving: ', newname1
        newim1 = fits.PrimaryHDU(data=data1, header=header1)
        newim1.writeto(newname1, clobber=clob)

        if redfile:
            loc2 = specfile[avocado + 1].find('.ms.fits')
            if masterresp:
                newname2 = specfile[
                    avocado +
                    1][0:loc2] + '_flux_' + stdflux[0][1:-4] + '.ms.fits'
            else:
                newname2 = specfile[avocado + 1][0:loc2] + '_flux_' + stdflux[
                    choice // 2][1:-4] + '.ms.fits'
            clob = False
            mylist = [True for f in os.listdir('.') if f == newname2]
            exists = bool(mylist)

            if exists:
                print 'File %s already exists.' % newname2
                nextstep = raw_input(
                    'Do you want to overwrite or designate a new name (overwrite/new)? '
                )
                if nextstep == 'overwrite':
                    clob = True
                    exists = False
                elif nextstep == 'new':
                    newname2 = raw_input('New file name: ')
                    exists = False
                else:
                    exists = False

            newim2 = fits.PrimaryHDU(data=data2, header=header2)
            newim2.writeto(newname2, clobber=clob)
            print 'Saving: ', newname2

        #Finally, save all the used parameters into a file for future reference.
        # specfile,current date, stdspecfile,stdfile,order,size,newname
        f = open('sensitivity_params.txt', 'a')
        now = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M")
        if masterresp:
            newinfo1 = specfile[avocado] + '\t' + now + '\t' + standards[
                choice] + '\t' + stdflux[0] + '\t' + str(
                    allexcluded[choice]) + '\t' + str(
                        orderused[choice]) + '\t' + str(size) + '\t' + newname1
        else:
            newinfo1 = specfile[avocado] + '\t' + now + '\t' + standards[
                choice] + '\t' + stdflux[choice // 2] + '\t' + str(
                    allexcluded[choice]) + '\t' + str(
                        orderused[choice]) + '\t' + str(size) + '\t' + newname1
        if redfile:
            if masterresp:
                newinfo2 = specfile[
                    avocado + 1] + '\t' + now + '\t' + standards[
                        choice2] + '\t' + stdflux[0] + '\t' + str(
                            allexcluded[choice + 1]) + '\t' + str(
                                orderused[choice + 1]) + '\t' + str(
                                    size) + '\t' + newname2
            else:
                newinfo2 = specfile[
                    avocado + 1] + '\t' + now + '\t' + standards[
                        choice + 1] + '\t' + stdflux[choice // 2] + '\t' + str(
                            allexcluded[choice + 1]) + '\t' + str(
                                orderused[choice + 1]) + '\t' + str(
                                    size) + '\t' + newname2
            f.write(newinfo1 + "\n" + newinfo2 + "\n")
        else:
            f.write(newinfo1 + "\n")
        f.close()

        if redfile:
            avocado += 2
        else:
            avocado += 1

    print 'Done flux calibrating the spectra.'