def womreddening(hop):
    """redden or deredden with various reddening laws"""
    import matplotlib.pyplot as plt
    import extinction
    from tmath.wombat.inputter_single import inputter_single
    from tmath.wombat.inputter import inputter
    from tmath.wombat.yesno import yesno
    r_v=3.1
    print('Redden or deredden a spectrum')
    plt.cla()
    plt.plot(hop[0].wave,hop[0].flux,drawstyle='steps-mid',color='k')
    plt.xlabel('Wavelength')
    plt.ylabel('Flux')
    plt.title(hop[0].obname)
    flux=hop[0].flux.copy()
    action=inputter_single('(r)edden or (d)eredden the spectrum? (r/d) ', 'rd')
    print(' ')
    type=inputter_single('Do you want to enter the (c)olor excess, or (v)isual extinction? ','cv')
    print(' ')
    if (type == 'v'):
        av=inputter('Enter A_V in magnitudes: ','float',False)
    else:
        ebv=inputter('Enter E(B-V) in magnitudes: ','float',False)
        av=r_v*ebv
    print(' ')
    print('Do you want to use: ')
    print('(c)ardelli, Clayton, Mathis 1989')
    print("(o)'donnell 1994")
    print('(f)itzpatrick 1999\n')
    
    method=inputter_single('(c/o/f) ','cof')
    if (action == 'r'):
        if (method == 'c'):
            newflux=extinction.apply(extinction.ccm89(hop[0].wave,av,r_v),flux)
        elif (method == 'o'):
            newflux=extinction.apply(extinction.odonnell94(hop[0].wave,av,r_v),flux)
        else:
            newflux=extinction.apply(extinction.fitzpatrick99(hop[0].wave,av,r_v),flux)
    else:
        if (method == 'c'):
            ext=extinction.ccm89(hop[0].wave,av,r_v)
        elif (method == 'o'):
            ext=extinction.odonnell94(hop[0].wave,av,r_v)
        else:
            ext=extinction.fitzpatrick99(hop[0].wave,av,r_v)
        newflux=flux*10**(0.4*ext)
    plt.plot(hop[0].wave,newflux,drawstyle='steps-mid',color='r')
    print('\nOriginal spectrum in black, red/dered in red\n')
    print('Is this OK?\n')
    answer=yesno('y')
    if (answer == 'y'):
        hop[0].flux=newflux.copy()
        print('\nActive spectrum now changed')
    else:
        print('\nSorry to disappoint you, active spectrum unchanged')
    return hop
def womblueshift(hop):
    """add redshift to spectrum"""
    import numpy as np
    from tmath.wombat.yesno import yesno
    from tmath.wombat.inputter_single import inputter_single
    from tmath.wombat.inputter import inputter
    from tmath.wombat.womrebindriver import womrebindriver
    light_speed = 2.99792458e5
    print('Current A/pix is {}'.format(hop[0].wave[1] - hop[0].wave[0]))
    print('\nWavelength range: {} to {}\n'.format(hop[0].wave[0],
                                                  hop[0].wave[-1]))
    answer = inputter_single('Remove redshift in (z) or (k)m/s? (z/k) ', 'zk')
    z = inputter('Enter the desired blueshift (positive is away from us): ',
                 'float', False)
    if (answer == 'k'):
        z = np.sqrt((1.0 + z / c) / (1.0 - z / c)) - 1.0
    hop[0].wave = hop[0].wave * (1.0 + z)
    print('\nNew wavelength range: {} to {}\n'.format(hop[0].wave[0],
                                                      hop[0].wave[-1]))
    print('Rebin spectrum?')
    rebin = yesno('n')
    if (rebin == 'y'):
        hop = womrebindriver(hop, 'scipy')
    else:
        pass
        #FIX header
    return hop
def womrebindriver(hop, mode):
    """input info to call womrebin functions"""
    import matplotlib.pyplot as plt
    import numpy as np
    from tmath.wombat.inputter import inputter
    from tmath.wombat.waveparse import waveparse
    from tmath.wombat.yesno import yesno
    from tmath.wombat.womashrebin import womashrebin
    from tmath.wombat.womscipyrebin import womscipyrebin
    print('Current A/pix is {}'.format(hop[0].wave[1] - hop[0].wave[0]))
    print('Wavelength rage: {} to {}'.format(hop[0].wave[0], hop[0].wave[-1]))
    plt.cla()
    plt.plot(hop[0].wave, hop[0].flux, drawstyle='steps-mid')
    plt.xlabel('Wavelength')
    plt.ylabel('Flux')
    plt.title(hop[0].obname)
    done = False
    while (not done):
        newdelt=inputter('Rebin to how many Angstroms per pixel? ', \
                         'float',False)
        waveb, waver = waveparse()
        if (waveb > waver):
            waveb, waver = waver, waveb
        if (newdelt > 0):
            newbin = (waver - waveb) / newdelt + 1.0
            frac, whole = np.modf(newbin)
            if (frac > 0.000001):
                print('NON-INTEGER number of bins')
                testwave = newdelt * whole + waveb
                print('Closest match is: {} to {}'.format(waveb, testwave))
                print('Would you like this wavelength range?')
                answer = yesno('y')
                if (answer == 'y'):
                    waver = testwave
                    done = True
            else:
                print('Rebinning to {} A/pix, {} to {}'.format(newdelt,waveb,\
                                                       waver))
                print('Is this OK?')
                answer = yesno('y')
                if (answer == 'y'):
                    done = True

    nwave = np.arange(0, whole) * newdelt + waveb
    if (mode == 'ash'):
        nflux = womashrebin(hop[0].wave, hop[0].flux, nwave)
        nvar = womashrebin(hop[0].wave, hop[0].var, nwave)
    else:
        nflux = womscipyrebin(hop[0].wave, hop[0].flux, nwave)
        nvar = womscipyrebin(hop[0].wave, hop[0].var, nwave)
    print('Overplotting rebinned spectrum')
    plt.cla()
    plt.plot(hop[0].wave, hop[0].flux, drawstyle='steps-mid')
    plt.plot(nwave, nflux, drawstyle='steps-mid')

    #FIX header
    hop[0].wave = nwave.copy()
    hop[0].flux = nflux.copy()
    hop[0].var = nvar.copy()
    return hop
def womxshift(hop):
    """linearly shift wavelength by arbitrary amount"""
    import matplotlib.pyplot as plt
    import logging
    from tmath.wombat.inputter import inputter
    from tmath.wombat.wshow import wshow
    plt.cla()
    plt.plot(hop[0].wave,hop[0].flux,drawstyle='steps-mid')
    plt.xlabel('Wavelength')
    plt.ylabel('Flux')
    plt.title(hop[0].obname)
    wshow()

    print('Routine to linearly shift wavelength scale\n')

    shift=inputter('Enter wavelength shift in Angstroms: ','float',False)

    hop[0].wave=hop[0].wave+shift

    plt.plot(hop[0].wave,hop[0].flux,drawstyle='steps-mid')

    logging.debug('File {} wavelength scale shifted by {} A'.format\
                  (hop[0].obname,shift))

    #FIX header
    return hop
def womms(hop):
    """arithmetic on spectra"""
    from tmath.wombat.inputter import inputter
    from tmath.wombat.inputter_single import inputter_single
    from tmath.wombat import HOPSIZE
    print(
        '\nThis routine will perfrom arithmatic operations with two hoppers\n')
    print(
        'Do you want to (a)dd, (s)ubtract, (m)ultiply, or (d)ivide spectra?\n')
    choice = inputter_single('(a/s/m/d) ', 'asmd')
    if (choice == 's'):
        print('Second spectrum will be subtracted from the first.')
    if (choice == 'd'):
        print('First spectrum will be divided by the first.')
    done = False
    while (not done):
        hopnum1 = inputter('\nEnter the first hopper: ', 'int', False)
        print(' ')
        hopnum2 = inputter('Enter the second hopper: ', 'int', False)
        if (hopnum1 < 1) or (hopnum1 > HOPSIZE) or (hopnum2 < 1) or \
           (hopnum2 > HOPSIZE):
            print('\nHopper must be in range 1-{}'.format(HOPSIZE))
        else:
            done = True
    if (hop[hopnum1].wave[0] != hop[hopnum2].wave[0])  \
       or (hop[hopnum1].wave[1] != hop[hopnum2].wave[1]) \
       or (hop[hopnum1].wave[-1] != hop[hopnum2].wave[-1]):
        print('Hoppers to not have the same wavelength scale!')
        return hop
    if (choice == 'a'):
        hop[0].flux = hop[hopnum1].flux + hop[hopnum2].flux
        hop[0].var = hop[hopnum1].var + hop[hopnum2].var
    elif (choice == 's'):
        hop[0].flux = hop[hopnum1].flux - hop[hopnum2].flux
        hop[0].var = hop[hopnum1].var + hop[hopnum2].var
    elif (choice == 'm'):
        hop[0].flux = hop[hopnum1].flux * hop[hopnum2].flux
        hop[0].var=(hop[hopnum2].flux)**2*hop[hopnum1].var + \
                    (hop[hopnum1].flux)**2*hop[hopnum2].var
    elif (choice == 'd'):
        hop[0].flux = hop[hopnum1].flux / hop[hopnum2].flux
        hop[0].var=(hop[hopnum2].flux)**2*hop[hopnum1].var + \
                    (hop[hopnum1].flux)**2*hop[hopnum2].var
    hop[0].wave = hop[hopnum1].wave
    hop[0].obname = hop[hopnum1].obname
    hop[0].header = hop[hopnum1].header
    return hop
示例#6
0
def womhop(hop):
    import copy
    from tmath.wombat.inputter import inputter
    from tmath.wombat import HOPSIZE
    hopnum = 0
    while (hopnum < 1) or (hopnum > HOPSIZE):
        hopnum = inputter('Store in which hopper: ', 'int', False)
    hop[hopnum] = copy.deepcopy(hop[0])
    return hop
示例#7
0
def wombluen(hop):
    """bluen spectrum with scattering law"""
    from tmath.wombat.inputter import inputter
    print('\nThis routine will bluen a spectrum with a power law')
    print('of lambda^{-a}.  You will supply the value of a.\n')

    factor=inputter('Enter exponential factor: ','float',False)

    wavefac=hop[0].wave**(-1.0*factor)
    wavefac=wavefac/wavefac[-1]
    hop[0].flux=hop[0].flux*wavefac

    return hop
示例#8
0
def womrelvel(hop):
    """relativistic velocity calculation"""
    from tmath.wombat.inputter import inputter
    light_speed = 2.99792458e5
    print('Relativistic velocity calculation\n')

    lambda1 = inputter('Observed wavelength ', 'float', False)
    print(' ')
    lambda0 = inputter('Rest wavelength ', 'float', False)
    if (lambda0 <= 0):
        print('Invalid rest wavelength')
        return hop
    z = (lambda1 - lambda0) / lambda0
    sq = (z + 1.0)**2
    vel = z * light_speed
    relvel = ((sq - 1.0) / (sq + 1.0)) * light_speed

    print('\nz: {}'.format(z))
    print('Velocity: {}'.format(vel))
    print('Relativistic velocity {}'.format(relvel))

    return hop
示例#9
0
def womrdhop(hop):
    import copy
    from tmath.wombat import HOPSIZE
    from tmath.wombat.inputter import inputter
    hopnum=0
    while (hopnum < 1) or (hopnum > HOPSIZE):
        hopnum=inputter('Read from which hopper: ','int',False)
    if (len(hop[hopnum].flux) == 0):
        print('Nothing in hopper {}'.format(hopnum))
        print('Active spectrum still {}'.format(hop[0].obname))
    else:
        hop[0]=copy.deepcopy(hop[hopnum])
    print('Object is {}'.format(hop[0].obname))
    return hop
示例#10
0
def womsmo(hop):
    import matplotlib.pyplot as plt
    from tmath.wombat.inputter_single import inputter_single
    from tmath.wombat.inputter import inputter
    plt.cla()
    plt.plot(hop[0].wave,hop[0].flux,drawstyle='steps-mid')
    plt.xlabel('Wavelength')
    plt.ylabel('Flux')
    plt.title(hop[0].obname)
    mode=inputter_single('(b)oxcar or (s)avitzky-Golay smoothing? (b/s) ', \
                         'bs')
    if (mode == 'b'):
        print('\nSmoothing with a boxcar\n')
        from astropy.convolution import convolve, Box1DKernel
        width=inputter('Enter the width of the boxcar: ','int',False)
        if (width > len(hop[0].wave)):
            width = 1
        box_k=Box1DKernel(width)
        sflux=convolve(hop[0].flux,box_k,boundary='extend')
    else:
        print('\nThe Savitzky-Golay filter smooths the data while conserving')
        print('flux and retaining the dynamic range of variations.  The ')
        print('routine suggests a width of 1-2 times the FWHM of the ')
        print('desired features, assuming you know what features you ')
        print('do desire.  This currently uses a polynomial of degree')
        print('2 to create the filter, so the width must be at least 3.')
        print('Good luck.\n')
        from scipy.signal import savgol_filter
        width=inputter('Enter the width for the filter: ','int',False)
        if (width < 3) or (width > len(hop[0].wave)):
            width=3
        sflux=savgol_filter(hop[0].flux,width,2)
    print('Overplotting smoothed spectrum')
    plt.plot(hop[0].wave,sflux,drawstyle='steps-mid')
    hop[0].flux=sflux.copy()
    return hop
def womvelcho(hop):
    """select region of spectrum, put onto velocity scale"""
    import matplotlib.pyplot as plt
    import numpy as np
    import logging
    from tmath.wombat.inputter import inputter
    from tmath.wombat.womwaverange import womwaverange
    from tmath.wombat.womget_element import womget_element
    from tmath.wombat.womscipyrebin import womscipyrebin
    wave=hop[0].wave.copy()
    flux=hop[0].flux.copy()
    var=hop[0].var.copy()
    nwave,nflux,mode=womwaverange(wave,flux,'none')
    wavebindex=womget_element(wave,nwave[0])
    waverindex=womget_element(wave,nwave[-1])
    nvar=var[wavebindex:waverindex+1].copy()
    binvec=np.arange(len(nwave))
    wavelog=np.log(nwave[0])+((np.log(nwave[-1])-np.log(nwave[0]))/len(nwave))*binvec
    wavelog=np.exp(wavelog)
    fluxlog=womscipyrebin(nwave,nflux,wavelog)
    varlog=womscipyrebin(nwave,nvar,wavelog)
    zp=wavelog[0]-1.0
    while (zp < wavelog[0]) or (zp > wavelog[-1]):
        zp=inputter('Enter the zero point for velocity (in angstroms): ','float',False)
    indexzp=womget_element(wavelog, zp)
    print(' ')
    logging.info('Zero at bin {}'.format(indexzp))
    logging.info('with lambda {}'.format(wavelog[indexzp]))
    print(' ')
    z=(wavelog - zp)/zp
    square=(z+1)*(z+1)
    wavekmsrel=((square-1.)/(square+1.))*299792.458
    kmsperbin=np.zeros(len(nwave))
    for i in range(1,len(nwave)):
        kmsperbin[i]=2.0*2.99792458e5*(wavelog[i]-wavelog[i-1])/\
                      (wavelog[i]+wavelog[i-1])
    kmsmean=np.mean(kmsperbin[1:])
    logging.info('Average km/s per bin: {}'.format(kmsmean))
    logging.info('km/s at bin 1: {}'.format(kmsperbin[1]))
    logging.info('km/s at bin n: {}'.format(kmsperbin[-1]))
    print(' ')
    wavekms=kmsmean*binvec+kmsmean/2.0
    indexzp=womget_element(wavekms,zp)
    wavekms=wavekms-wavekms[indexzp]
    hop[0].wave=wavekmsrel.copy()
    hop[0].flux=fluxlog.copy()
    hop[0].var=varlog.copy()
    return hop
示例#12
0
def wommkbb(hop):
    import numpy as np
    import matplotlib.pyplot as plt
    from tmath.wombat.waveparse import waveparse
    from tmath.wombat.inputter import inputter
    from tmath.wombat.inputter_single import inputter_single
    light_speed = 2.99792458e10
    h_planck = 6.6260755e-27
    k_boltzmann = 1.380658e-16
    print('This routine will create a blackbody curve for a given temperature')
    print('with 1 Angstrom bins')
    print('\n')
    temp = inputter('Enter temperature in degrees Kelvin: ', 'float', False)
    if (temp <= 0):
        temp = 1.0
    waveb, waver = waveparse()
    if (waver < waveb):
        waveb, waver = waver, waveb
    if (waver == waveb):
        waver = waver + 1.
    wave = np.arange(waveb, waver + 1)
    wavecm = wave / 1.e8
    answer = inputter_single('Calculate B_nu(n) or B_lambda(l) ', 'nl')
    if (answer.lower()[0] == 'l'):
        flux=(2.0*h_planck*light_speed*light_speed/wavecm**5)/ \
              (np.exp((h_planck*light_speed)/(wavecm*k_boltzmann*temp))-1.0)
        flux = np.pi * flux / (1.e8)
        ext = 'flm'
    else:
        nu = light_speed / wavecm
        flux=(2.0*h_planck*nu**3/light_speed/light_speed)/ \
              (np.exp((h_planck*nu)/(k_boltzmann*temp))-1.0)
        flux = np.pi * flux * 1.e11
        ext = 'fnu'
    spectxt = 'bb{}.{}'.format(temp, ext)
    plt.cla()
    plt.plot(wave, flux, drawstyle='steps-mid')
    plt.title(spectxt)
    hop[0].wave = wave.copy()
    hop[0].flux = flux.copy()
    hop[0].obname = spectxt
    hop[0].var = np.ones(wave.shape)
    hop[0].header = ''
    return hop
示例#13
0
def womwavescale(hop):
    """multiplicative change to wavelength scale, convert units"""
    import matplotlib.pyplot as plt
    import logging
    from tmath.wombat.inputter import inputter
    from tmath.wombat.wshow import wshow
    print('Routine does a multiplicative shift to the wavelength scale')
    shift=inputter('Enter wavelength factor: ','float',False)
    plt.cla()
    plt.plot(hop[0].wave,hop[0].flux,drawstyle='steps-mid')
    plt.ylabel('Flux')
    plt.xlabel('Wavelength')
    xmin,xmax=plt.xlim()
    ymin,ymax=plt.ylim()
    wshow()
    hop[0].wave=hop[0].wave*shift
    plt.plot(hop[0].wave,hop[0].flux,drawstyle='steps-mid')
    logging.info('File {} wavelength scale multiplied by {}'.format(hop[0].obname, shift))
    #FIX header
    return hop
示例#14
0
def womwfits(hop):
    """write fits file"""
    from astropy.io import fits
    from tmath.wombat.inputter import inputter
    print('Object is {}'.format(hop[0].obname))
    fileout=inputter('Enter the name for the output file: ' + \
                     '(.fits will be added,if necessary)','string',False)
    outhdu=fits.PrimaryHDU(hop[0].flux)
    hdul=fits.HDUList([outhdu])
#    hdul[0].header.set('EXTEND','F')
    hdul[0].header.set('OBJECT',hop[0].obname)
    if ('.fits' not in fileout):
            fileout=fileout+'.fits'
    if (len(hop[0].header) > 1):
        hdul[0].header=hop[0].header.copy()
  #  hdul[0].header['SIMPLE']=('T','Written by Wombat')
    hdul[0].header.set('CRPIX1',1)
    hdul[0].header.set('CRVAL1',hop[0].wave[0])
    hdul[0].header.set('CDELT1',hop[0].wave[1]-hop[0].wave[0])
    hdul[0].header.set('CTYPE1','LINEAR')
    hdul[0].header.set('COMMENT','Written by Wombat')
    hdul.writeto(fileout,overwrite=True)
    hdul.close()
    return hop
def womscale2match(hop):
    """scale one spectrum to match another"""
    import matplotlib.pyplot as plt
    import numpy as np
    import logging
    from tmath.wombat.inputter import inputter
    from tmath.wombat.inputter_single import inputter_single
    from tmath.wombat.womwaverange import womwaverange
    from tmath.wombat.womget_element import womget_element
    from tmath.wombat import HOPSIZE
    print('This will scale one hopper to match another')
    done = False
    while (not done):
        hopnum1 = inputter('Enter first hopper: ', 'int', False)
        hopnum2 = inputter('Enter second hopper: ', 'int', False)
        if (hopnum1 < 1) or (hopnum1 > HOPSIZE) or (hopnum2 < 1) or \
           (hopnum2 > HOPSIZE):
            print('Hopper numbers must be in range 1-{}'.format(HOPSIZE))
        else:
            done = True
    if (hop[hopnum1].wave[0] != hop[hopnum2].wave[0]) or \
       (hop[hopnum1].wave[1] != hop[hopnum2].wave[1]) or \
       (hop[hopnum1].wave[-1] != hop[hopnum2].wave[-1]):
        print('Hoppers to not have the same wavelength scale!')
        return hop
    print('\nSpectra run from {} to {}'.format(hop[hopnum1].wave[0], \
                                             hop[hopnum1].wave[-1]))

    plt.cla()
    plt.plot(hop[hopnum1].wave,hop[hopnum1].flux,drawstyle='steps-mid', \
             color='k')
    plt.xlabel('Wavelength')
    plt.ylabel('Flux')
    plt.title(hop[hopnum1].obname)
    plt.plot(hop[hopnum2].wave,hop[hopnum2].flux,drawstyle='steps-mid', \
             color='r')
    print('\nHopper A in black, hopper B in red')
    print('\nChoose region to compute average')
    wave, flux, mode = womwaverange(hop[hopnum1].wave, hop[hopnum1].flux,
                                    'none')
    indexblue = womget_element(hop[hopnum1].wave, wave[0])
    indexred = womget_element(hop[hopnum1].wave, wave[-1])
    avg1 = np.mean(hop[hopnum1].flux[indexblue:indexred + 1])
    avg2 = np.mean(hop[hopnum2].flux[indexblue:indexred + 1])
    print('\n Hopper A: {}'.format(avg1))
    print('\n Hopper B: {}'.format(avg2))
    choice = inputter_single('Scale to (A) or (B) ', 'ab')
    print(' ')
    done = False
    while (not done):
        hopnum3 = inputter('Store scaled spec in which hopper? ', 'int', False)
        if (hopnum3 < 1) or (hopnum3 > HOPSIZE):
            print('Hopper numbers must be in range 1-{}'.format(HOPSIZE))
        else:
            done = True
    if (choice == 'a'):
        hop[hopnum3].flux = hop[hopnum2].flux * (avg1 / avg2).copy()
        print('Scale: {}'.format(avg1 / avg2))
        hop[hopnum3].obname = hop[hopnum2].obname
        hop[hopnum3].header = hop[hopnum2].header
        hop[hopnum3].var = hop[hopnum2].var * (avg1 / avg2).copy()
        lstring='File: {} scaled by {} to match {}'.format(hop[hopnum2], \
                                                           avg1/avg2, \
                                                           hop[hopnum1])
    else:
        hop[hopnum3].flux = hop[hopnum1].flux * (avg2 / avg1).copy()
        print('Scale: {}'.format(avg1 / avg2))
        hop[hopnum3].obname = hop[hopnum1].obname
        hop[hopnum3].header = hop[hopnum1].header
        hop[hopnum3].var = hop[hopnum1].var * (avg2 / avg1).copy()
        lstring='File: {} scaled by {} to match {}'.format(hop[hopnum1].obname, \
                                                           avg2/avg1, \
                                                           hop[hopnum2].obname)
    hop[hopnum3].wave = hop[hopnum1].wave.copy()
    logging.debug(lstring)
    return hop
示例#16
0
def womcat(hop):
    """concatenate data with overlapping wavelength regions"""
    import numpy as np
    import logging
    import matplotlib.pyplot as plt
    from tmath.wombat.inputter import inputter
    from tmath.wombat.inputter_single import inputter_single
    from tmath.wombat.womget_element import womget_element
    from tmath.wombat.yesno import yesno
    from tmath.wombat.get_screen_size import get_screen_size
    from tmath.wombat.womwaverange2 import womwaverange2
    from tmath.wombat import HOPSIZE
    from matplotlib.widgets import Cursor
    plt.ion()
    screen_width, screen_height = get_screen_size()
    screenpos = '+{}+{}'.format(int(screen_width * 0.2),
                                int(screen_height * 0.05))
    fig = plt.figure()
    ax = fig.add_subplot(111)
    cursor = Cursor(ax, useblit=True, color='k', linewidth=1)
    fig.canvas.manager.window.wm_geometry(screenpos)
    fig.canvas.set_window_title('Cat')
    fig.set_size_inches(9, 6)
    # turns off key stroke interaction
    fig.canvas.mpl_disconnect(fig.canvas.manager.key_press_handler_id)
    print("\nThis will combine blue and red pieces from two hoppers\n")
    hopnum1 = 0
    hopnum2 = 0
    while (hopnum1 < 1) or (hopnum1 > HOPSIZE):
        hopnum1 = inputter('Enter first hopper: ', 'int', False)
    while (hopnum2 < 1) or (hopnum2 > HOPSIZE):
        hopnum2 = inputter('Enter second hopper: ', 'int', False)
    if (hop[hopnum1].wave[0] > hop[hopnum2].wave[0]):
        hopnum1, hopnum2 = hopnum2, hopnum1
    wdelt1 = hop[hopnum1].wave[1] - hop[hopnum1].wave[0]
    wdelt2 = hop[hopnum2].wave[1] - hop[hopnum2].wave[0]
    # check if wavelength dispersion same
    if (abs(wdelt1 - wdelt2) > 0.00001):
        print('Spectra do not have same Angstrom/pixel')
        print('Blue side: {}'.format(wdelt1))
        print('Red side: {}'.format(wdelt2))
        return hop
    if hop[hopnum1].wave[-1] < hop[hopnum2].wave[0]:
        print('Spectra do not overlap\n')
        return hop
    print("\nOverlap range is {} to {}".format(hop[hopnum2].wave[0],
                                               hop[hopnum1].wave[-1]))
    print("\nPlotting blue side as blue, red side as red\n")

    waveblue = hop[hopnum1].wave.copy()
    fluxblue = hop[hopnum1].flux.copy()
    varblue = hop[hopnum1].var.copy()
    wavered = hop[hopnum2].wave.copy()
    fluxred = hop[hopnum2].flux.copy()
    varred = hop[hopnum2].var.copy()
    indexblue = womget_element(waveblue, wavered[0])
    indexred = womget_element(wavered, waveblue[-1])
    fluxcor = 1.0
    blue_mean = np.mean(fluxblue[indexblue:])
    red_mean = np.mean(fluxred[0:indexred + 1])
    if (blue_mean / red_mean < 0.8) or (blue_mean / red_mean > 1.2):
        fluxcor = blue_mean / red_mean
        print("Averages very different, scaling red to blue for plot")
        print("Red multiplied by {}".format(fluxcor))
    plt.cla()
    plt.plot(waveblue[indexblue:],
             fluxblue[indexblue:],
             drawstyle='steps-mid',
             color='b')
    plt.plot(wavered[0:indexred],
             fluxred[0:indexred] * fluxcor,
             drawstyle='steps-mid',
             color='r')
    plt.xlabel('Wavelength')
    plt.ylabel('Flux')
    plt.pause(0.01)
    print('Change scale?')
    answer = yesno('n')
    if (answer == 'y'):
        xmin_old, xmax_old = plt.xlim()
        ymin_old, ymax_old = plt.ylim()
        done = False
        while (not done):
            plt.xlim([xmin_old, xmax_old])
            plt.ylim([ymin_old, ymax_old])
            print('Click corners of box to change plot scale')
            newlims = plt.ginput(2, timeout=-1)
            xmin = newlims[0][0]
            ymin = newlims[0][1]
            xmax = newlims[1][0]
            ymax = newlims[1][1]
            plt.xlim([xmin, xmax])
            plt.ylim([ymin, ymax])
            print('Is this OK?')
            loopanswer = yesno('y')
            if (loopanswer == 'y'):
                done = True
    print('\nEnter method to select wavelength ranges\n')
    mode = inputter_single(
        'Enter (w)avelengths or mark with the (m)ouse? (w/m) ', 'wm')
    print('\nChoose end points of region to compute average\n')

    waveb, waver, mode = womwaverange2(waveblue[indexblue:],
                                       fluxblue[indexblue:],
                                       wavered[0:indexred],
                                       fluxred[0:indexred] * fluxcor, mode)
    indexblueb = womget_element(waveblue, waveb)
    indexbluer = womget_element(waveblue, waver)
    indexredb = womget_element(wavered, waveb)
    indexredr = womget_element(wavered, waver)
    mean_blue = np.mean(fluxblue[indexblueb:indexbluer + 1])
    mean_red = np.mean(fluxred[indexredb:indexredr + 1])
    print("\nAverage for {}:{}".format(waveb, waver))
    print("Blue side: {}".format(mean_blue))
    print("Red side:  {}\n".format(mean_red))
    brscale = inputter_single('Scale to blue or red (b/r)? ', 'br')
    if (brscale == 'b'):
        brscalefac = mean_blue / mean_red
        logging.info('Cat scaling to blue by {}'.format(brscalefac))
        fluxred = fluxred * brscalefac
        varred = varred * brscalefac**2
    else:
        brscalefac = mean_red / mean_blue
        logging.info('Cat scaling to red by {}'.format(brscalefac))
        fluxblue = fluxblue * brscalefac
        varblue = varblue * brscalefac**2

    # print("\nPlotting blue side as blue, red side as red\n")
    # plt.cla()
    # plt.plot(waveblue[indexblueb:indexbluer+1],fluxblue[indexblueb:indexbluer+1],drawstyle='steps-mid',color='b')
    # plt.plot(wavered[indexredb:indexredr+1],fluxred[indexredb:indexredr+1],drawstyle='steps-mid',color='r')
    # plt.xlabel('Wavelength')
    # plt.ylabel('Flux')
    # plt.pause(0.01)
    # print('Change scale?')
    # answer=yesno('n')
    # if (answer == 'y'):
    #     xmin_old,xmax_old=plt.xlim()
    #     ymin_old,ymax_old=plt.ylim()
    #     done=False
    #     while (not done):
    #         plt.xlim([xmin_old,xmax_old])
    #         plt.ylim([ymin_old,ymax_old])
    #         print('Click corners of box to change plot scale')
    #         newlims=plt.ginput(2,timeout=-1)
    #         xmin=newlims[0][0]
    #         ymin=newlims[0][1]
    #         xmax=newlims[1][0]
    #         ymax=newlims[1][1]
    #         plt.xlim([xmin,xmax])
    #         plt.ylim([ymin,ymax])
    #         print('Is this OK?')
    #         loopanswer=yesno('y')
    #         if (loopanswer == 'y'):
    #             done=True

    # print('\nChoose end points of region to compute average\n')

    # waveb,waver,mode=womwaverange2(waveblue[indexblueb:indexbluer+1],
    #                                fluxblue[indexblueb:indexbluer+1],
    #                                wavered[indexredb:indexredr+1],
    #                                fluxred[indexredb:indexredr+1],mode)
    # indexblueb=womget_element(waveblue,waveb)
    # indexbluer=womget_element(waveblue,waver)
    # indexredb=womget_element(wavered,waveb)
    # indexredr=womget_element(wavered,waver)
    # ewadd=inputter_single('Add overlap region (e)qually or with (w)eights (e/w)?','ew')
    # if (ewadd == 'e'):
    # overflux=(fluxblue[indexblueb:indexbluer+1]+fluxred[indexredb:indexredr+1])/2.
    # overvar=(varblue[indexblueb:indexbluer+1]+varred[indexredb:indexredr+1])

    #replacing with inverse variance weighted average
    overflux = np.average([
        fluxblue[indexblueb:indexbluer + 1], fluxred[indexredb:indexredr + 1]
    ],
                          weights=[
                              1. / varblue[indexblueb:indexbluer + 1],
                              1. / varred[indexredb:indexredr + 1]
                          ],
                          axis=0)
    overvar = np.sum(
        [varblue[indexblueb:indexbluer + 1], varred[indexredb:indexredr + 1]],
        axis=0)
    logging.info('Cat combined sides with inverse variance weighted average')
    # else:
    #     wei_done = False
    #     while (not wei_done):
    #         weiblue=inputter('Enter fractional weight for blue side: ','float',False)
    #         weired=inputter('Enter fractional weight for red side: ','float',False)
    #         if (np.abs((weiblue+weired)-1.0) > 0.000001):
    #             print('Weights do not add to 1.0')
    #         else:
    #             wei_done = True
    #     overflux=(fluxblue[indexblueb:indexbluer+1]*weiblue+
    #               fluxred[indexredb:indexredr+1]*weired)
    #     overvar=(varblue[indexblueb:indexbluer+1]*weiblue**2+
    #               varred[indexredb:indexredr+1]*weired**2)
    # logging.info('Cat adds blue side with weight {} and red side with weight {}'.format(weiblue, weired))
    newbluewave = waveblue[:indexblueb]
    newblueflux = fluxblue[:indexblueb]
    newbluevar = varblue[:indexblueb]
    overwave = waveblue[indexblueb:indexbluer + 1]
    newredwave = wavered[indexredr + 1:]
    newredflux = fluxred[indexredr + 1:]
    newredvar = varred[indexredr + 1:]
    newwave = np.concatenate([newbluewave, overwave, newredwave])
    newflux = np.concatenate([newblueflux, overflux, newredflux])
    newvar = np.concatenate([newbluevar, overvar, newredvar])
    logging.info('File {} and'.format(hop[hopnum1].obname))
    logging.info('File {} concatenated'.format(hop[hopnum2].obname))
    logging.info('over wavelength range {} to {}'.format(
        waveblue[indexblueb], waveblue[indexbluer]))
    plt.clf()
    axarr = fig.subplots(2)

    axarr[0].plot(overwave, overflux, drawstyle='steps-mid', color='k')
    axarr[0].plot(waveblue[indexblueb:indexbluer + 1],
                  fluxblue[indexblueb:indexbluer + 1],
                  drawstyle='steps-mid',
                  color='b')
    axarr[0].plot(wavered[indexredb:indexredr + 1],
                  fluxred[indexredb:indexredr + 1],
                  drawstyle='steps-mid',
                  color='r')
    axarr[0].set_title('Overlap region, with inputs and combination')
    axarr[1].set_ylabel('Flux')
    axarr[1].plot(newwave, newflux, drawstyle='steps-mid', color='k')
    axarr[1].plot(newwave[indexblueb:indexbluer + 1],
                  newflux[indexblueb:indexbluer + 1],
                  drawstyle='steps-mid',
                  color='r')
    plt.pause(0.01)
    hopout = 0
    while (hopout < 1) or (hopout > HOPSIZE):
        hopout = inputter('Enter hopper to store combined spectrum: ', 'int',
                          False)
    hop[hopout].wave = newwave
    hop[hopout].flux = newflux
    hop[hopout].var = newvar
    hop[hopout].obname = hop[hopnum1].obname
    hop[hopout].header = hop[hopnum1].header
    plt.close()
    #fig.clf()
    #plt.cla()
    return hop
示例#17
0
def womscale(hop):
    """scale a spectrum by multiplicative value"""
    from tmath.wombat.inputter import inputter
    factor = inputter('Enter multiplicative scale factor: ', 'float', False)
    hop[0].flux = hop[0].flux * factor
    return hop
示例#18
0
def womfilters(hop):
    """calculate photometric values from spectra"""
    import numpy as np
    import logging
    from tmath.wombat.filtermag import filtermag
    from tmath.wombat.yesno import yesno
    from tmath.wombat.inputter import inputter
    from tmath.wombat.inputter_single import inputter_single
    print('NOTE:  The routine expects an f_lambda spectrum')
    print('       I will try to guess if the spectrum')
    print('       has been scaled by 1E15')
    print(' ')
    print('       Check this before believing fluxes')
    print(' ')
    flux=hop[0].flux.copy()
    if (np.mean(flux) > 0.00001):
        flux = flux *1.e-15

    filtwave=np.zeros((141,10))
    filttran=np.zeros((141,10))
    filtwave[0:21, 1] = [3600.00, 3700.00, 3800.00, 3900.00, \
                         4000.00, 4100.00, 4200.00, 4300.00, \
                         4400.00, 4500.00, 4600.00, 4700.00, \
                         4800.00, 4900.00, 5000.00, 5100.00, \
                         5200.00, 5300.00, 5400.00, 5500.00, \
                         5600.00] 
    filttran[0:21, 1] = [0.00000, 0.03000, 0.13400, 0.56700, \
                         0.92000, 0.97800, 1.00000, 0.97800, \
                         0.93500, 0.85300, 0.74000, 0.64000, \
                         0.53600, 0.42400, 0.32500, 0.23500, \
                         0.15000, 0.09500, 0.04300, 0.00900, \
                         0.00000]
    filtwave[0:24, 2] = [4700.00, 4800.00, 4900.00, 5000.00, \
                      5100.00, 5200.00, 5300.00, 5400.00, \
                      5500.00, 5600.00, 5700.00, 5800.00, \
                      5900.00, 6000.00, 6100.00, 6200.00, \
                      6300.00, 6400.00, 6500.00, 6600.00, \
                      6700.00, 6800.00, 6900.00, 7000.00] 
    filttran[0:24:, 2] = [0.00000, 0.03000, 0.16300, 0.45800, \
                      0.78000, 0.96700, 1.00000, 0.97300, \
                      0.89800, 0.79200, 0.68400, 0.57400, \
                      0.46100, 0.35900, 0.27000, 0.19700, \
                      0.13500, 0.08100, 0.04500, 0.02500, \
                      0.01700, 0.01300, 0.00900, 0.00000]
    filtwave[0:24, 3] = [5500.00, 5600.00, 5700.00, 5800.00, \
                      5900.00, 6000.00, 6100.00, 6200.00, \
                      6300.00, 6400.00, 6500.00, 6600.00, \
                      6700.00, 6800.00, 6900.00, 7000.00, \
                      7100.00, 7200.00, 7300.00, 7400.00, \
                      7500.00, 8000.00, 8500.00, 9000.00]
    filttran[0:24:, 3] = [0.00000, 0.23000, 0.74000, 0.91000, \
                      0.98000, 1.00000, 0.98000, 0.96000, \
                      0.93000, 0.90000, 0.86000, 0.81000, \
                      0.78000, 0.72000, 0.67000, 0.61000, \
                      0.56000, 0.51000, 0.46000, 0.40000, \
                      0.35000, 0.14000, 0.03000, 0.00000]
    filtwave[0:23, 4] = [7000.00, 7100.00, 7200.00, 7300.00, \
                         7400.00, 7500.00, 7600.00, 7700.00, \
                         7800.00, 7900.00, 8000.00, 8100.00, \
                         8200.00, 8300.00, 8400.00, 8500.00, \
                         8600.00, 8700.00, 8800.00, 8900.00, \
                         9000.00, 9100.00, 9200.00]
    filttran[0:23, 4] = [0.00000, 0.02400, 0.23200, 0.55500, \
                         0.78500, 0.91000, 0.96500, 0.98500, \
                         0.99000, 0.99500, 1.00000, 1.00000, \
                         0.99000, 0.98000, 0.95000, 0.91000, \
                         0.86000, 0.75000, 0.56000, 0.33000, \
                         0.15000, 0.03000, 0.00000]

    filtwave[0:24, 0] = [3050.00, 3100.00, 3150.00, 3200.00, \
                      3250.00, 3300.00, 3350.00, 3400.00, \
                      3450.00, 3500.00, 3550.00, 3600.00, \
                      3650.00, 3700.00, 3750.00, 3800.00, \
                      3850.00, 3900.00, 3950.00, 4000.00, \
                      4050.00, 4100.00, 4150.00, 4200.00]
    filttran[0:24, 0] = [0.00000, 0.02000, 0.07700, 0.13500, \
                      0.20400, 0.28200, 0.38500, 0.49300, \
                      0.60000, 0.70500, 0.82000, 0.90000, \
                      0.95900, 0.99300, 1.00000, 0.97500, \
                      0.85000, 0.64500, 0.40000, 0.22300, \
                      0.12500, 0.05700, 0.00500, 0.00000]
    
    filtwave[0:47,5]=[2980., 3005., 3030., 3055., 3080., 3105., 3130.,  \
                      3155., 3180.,3205., 3230., 3255., 3280., 3305., \
                      3330., 3355., 3380., 3405., 3430., 3455., 3480., \
                      3505., 3530., 3555., 3580., 3605., 3630., 3655., \
                      3680., 3705., 3730., 3755., 3780., 3805., 3830., \
                      3855., 3880., 3905., 3930., 3955., 3980., 4005., \
                      4030., 4055., 4080., 4105., 4130.]
    filttran[0:47,5]=[0.    , 0.0014, 0.0071, 0.0127, 0.0198, 0.0314, \
                      0.0464, 0.0629, 0.0794, 0.0949, 0.1093, 0.1229, \
                      0.1352, 0.1458, 0.1545, 0.1617, 0.1679, 0.1737, \
                      0.1786, 0.1819, 0.1842, 0.186 , 0.187 , 0.1868, \
                      0.1862, 0.1858, 0.1853, 0.1841, 0.1812, 0.1754, \
                      0.1669, 0.1558, 0.1419, 0.1247, 0.1054, 0.0851, \
                      0.0634, 0.0405, 0.0216, 0.011 , 0.0062, 0.0032, \
                      0.0015, 0.0008, 0.0006, 0.0003, 0.    ]
    filtwave[0:89,6]=[3630., 3655., 3680., 3705., 3730., 3755., 3780., \
                      3805., 3830., 3855., 3880., 3905., 3930., 3955., \
                      3980., 4005., 4030., 4055., 4080., 4105., 4130., \
                      4155., 4180., 4205., 4230., 4255., 4280., 4305., \
                      4330., 4355., 4380., 4405., 4430., 4455., 4480., \
                      4505., 4530., 4555., 4580., 4605., 4630., 4655., \
                      4680., 4705., 4730., 4755., 4780., 4805., 4830., \
                      4855., 4880., 4905., 4930., 4955., 4980., 5005., \
                      5030., 5055., 5080., 5105., 5130., 5155., 5180., \
                      5205., 5230., 5255., 5280., 5305., 5330., 5355., \
                      5380., 5405., 5430., 5455., 5480., 5505., 5530., \
                      5555., 5580., 5605., 5630., 5655., 5680., 5705., \
                      5730., 5755., 5780., 5805., 5830.]
    filttran[0:89,6]=[0.000e+00, 5.000e-04, 1.300e-03, 2.200e-03, \
                      3.000e-03, 3.900e-03, 5.500e-03, 8.700e-03, \
                      1.620e-02, 3.010e-02, 5.000e-02, 7.450e-02, \
                      1.024e-01, 1.324e-01, 1.629e-01, 1.924e-01, \
                      2.191e-01, 2.419e-01,2.609e-01, 2.767e-01, \
                      2.899e-01, 3.010e-01, 3.105e-01, 3.186e-01, \
                      3.258e-01, 3.324e-01, 3.385e-01, 3.442e-01, \
                      3.496e-01, 3.548e-01, 3.596e-01, 3.640e-01, \
                      3.678e-01, 3.709e-01, 3.736e-01, 3.763e-01, \
                      3.792e-01, 3.827e-01, 3.863e-01, 3.899e-01, \
                      3.931e-01, 3.955e-01, 3.973e-01, 3.986e-01, \
                      3.997e-01, 4.008e-01, 4.019e-01, 4.030e-01, \
                      4.043e-01, 4.057e-01, 4.073e-01, 4.091e-01, \
                      4.110e-01, 4.129e-01, 4.147e-01, 4.165e-01, \
                      4.181e-01, 4.194e-01, 4.201e-01, 4.201e-01, \
                      4.191e-01, 4.169e-01, 4.147e-01, 4.115e-01, \
                      3.988e-01, 3.684e-01, 3.233e-01, 2.690e-01, \
                      2.112e-01, 1.550e-01, 1.043e-01, 6.270e-02, \
                      3.370e-02, 1.900e-02, 1.280e-02, 8.700e-03, \
                      5.700e-03, 3.700e-03, 2.400e-03, 1.700e-03, \
                      1.400e-03, 1.200e-03, 1.000e-03, 9.000e-04, \
                      7.000e-04, 5.000e-04, 3.000e-04, 1.000e-04, 0.000e+00]
    filtwave[0:75,7]=[5380., 5405., 5430., 5455., 5480., 5505., 5530., \
                      5555., 5580., 5605., 5630., 5655., 5680., 5705., \
                      5730., 5755., 5780., 5805., 5830., 5855., 5880., \
                      5905., 5930., 5955., 5980., 6005., 6030., 6055., \
                      6080., 6105., 6130., 6155., 6180., 6205., 6230., \
                      6255., 6280., 6305., 6330., 6355., 6380., 6405., \
                      6430., 6455., 6480., 6505., 6530., 6555., 6580., \
                      6605., 6630., 6655., 6680., 6705., 6730., 6755., \
                      6780., 6805., 6830., 6855., 6880., 6905., 6930., \
                      6955., 6980., 7005., 7030., 7055., 7080., 7105., \
                      7130., 7155., 7180., 7205., 7230.]
    filttran[0:75,7]=[0.000e+00, 1.600e-03, 1.130e-02, 2.970e-02, \
                      5.680e-02, 9.230e-02, 1.356e-01, 1.856e-01, \
                      2.390e-01, 2.917e-01, 3.395e-01, 3.794e-01, \
                      4.116e-01, 4.371e-01, 4.570e-01, 4.723e-01, \
                      4.839e-01, 4.925e-01, 4.990e-01, 5.040e-01, \
                      5.080e-01, 5.112e-01, 5.141e-01, 5.169e-01, \
                      5.194e-01, 5.213e-01, 5.222e-01, 5.220e-01, \
                      5.212e-01, 5.202e-01, 5.197e-01, 5.202e-01, \
                      5.215e-01, 5.233e-01, 5.254e-01, 5.275e-01, \
                      5.294e-01, 5.310e-01, 5.319e-01, 5.320e-01, \
                      5.316e-01, 5.310e-01, 5.305e-01, 5.302e-01, \
                      5.299e-01, 5.290e-01, 5.271e-01, 5.241e-01, \
                      5.211e-01, 5.176e-01, 5.057e-01, 4.775e-01, \
                      4.341e-01, 3.792e-01, 3.162e-01, 2.488e-01, \
                      1.824e-01, 1.225e-01, 7.470e-02, 4.300e-02, \
                      2.470e-02, 1.550e-02, 1.120e-02, 8.300e-03, \
                      5.900e-03, 4.100e-03, 2.900e-03, 2.100e-03, \
                      1.600e-03, 1.300e-03, 1.000e-03, 8.000e-04, \
                      5.000e-04, 2.000e-04, 0.000e+00]
    filtwave[0:89,8]=[6430., 6455., 6480., 6505., 6530., 6555., 6580., \
                      6605., 6630., 6655., 6680., 6705., 6730., 6755., \
                      6780., 6805., 6830., 6855., 6880., 6905., 6930., \
                      6955., 6980., 7005., 7030., 7055., 7080., 7105., \
                      7130., 7155., 7180., 7205., 7230., 7255., 7280., \
                      7305., 7330., 7355., 7380., 7405., 7430., 7455., \
                      7480., 7505., 7530., 7555., 7580., 7605., 7630., \
                      7655., 7680., 7705., 7730., 7755., 7780., 7805., \
                      7830., 7855., 7880., 7905., 7930., 7955., 7980., \
                      8005., 8030., 8055., 8080., 8105., 8130., 8155., \
                      8180., 8205., 8230., 8255., 8280., 8305., 8330., \
                      8355., 8380., 8405., 8430., 8455., 8480., 8505., \
                      8530., 8555., 8580., 8605., 8630.]
    filttran[0:89,8]=[0.000e+00, 1.000e-04, 3.000e-04, 4.000e-04, 5.000e-04, \
                      4.000e-04, 3.000e-04, 5.000e-04, 1.000e-03, 2.100e-03, \
                      3.600e-03, 6.000e-03, 1.110e-02, 2.080e-02, 3.660e-02, \
                      5.970e-02, 9.130e-02, 1.317e-01, 1.779e-01, 2.260e-01, \
                      2.719e-01, 3.125e-01, 3.470e-01, 3.755e-01, 3.978e-01, \
                      4.142e-01, 4.256e-01, 4.331e-01, 4.377e-01, 4.405e-01, \
                      4.416e-01, 4.411e-01, 4.392e-01, 4.358e-01, 4.315e-01, \
                      4.265e-01, 4.214e-01, 4.165e-01, 4.119e-01, 4.077e-01, \
                      4.039e-01, 4.006e-01, 3.975e-01, 3.943e-01, 3.906e-01, \
                      3.862e-01, 3.812e-01, 3.757e-01, 3.700e-01, 3.641e-01, \
                      3.583e-01, 3.526e-01, 3.473e-01, 3.424e-01, 3.379e-01, \
                      3.337e-01, 3.297e-01, 3.259e-01, 3.224e-01, 3.194e-01, \
                      3.169e-01, 3.150e-01, 3.132e-01, 3.111e-01, 3.081e-01, \
                      3.039e-01, 2.996e-01, 2.945e-01, 2.803e-01, 2.493e-01, \
                      2.060e-01, 1.578e-01, 1.118e-01, 7.430e-02, 4.580e-02, \
                      2.570e-02, 1.340e-02, 7.700e-03, 5.500e-03, 3.700e-03, \
                      2.300e-03, 1.500e-03, 1.100e-03, 1.100e-03, 1.100e-03, \
                      9.000e-04, 6.000e-04, 3.000e-04, 0.000e+00]
    filtwave[0:141,9]=[ 7730.,  7755.,  7780.,  7805.,  7830.,  7855.,  7880., \
                       7905., 7930.,  7955.,  7980.,  8005.,  8030.,  8055., \
                       8080.,  8105., 8130.,  8155.,  8180.,  8205.,  8230., \
                       8255.,  8280.,  8305., 8330.,  8355.,  8380.,  8405., \
                       8430.,  8455.,  8480.,  8505., 8530.,  8555.,  8580., \
                       8605.,  8630.,  8655.,  8680.,  8705., 8730.,  8755., \
                       8780.,  8805.,  8830.,  8855.,  8880.,  8905., 8930., \
                       8955.,  8980.,  9005.,  9030.,  9055.,  9080.,  9105.,\
                       9130.,  9155.,  9180.,  9205.,  9230.,  9255.,  9280.,\
                       9305., 9330.,  9355.,  9380.,  9405.,  9430.,  9455., \
                       9480.,  9505., 9530.,  9555.,  9580.,  9605.,  9630., \
                       9655.,  9680.,  9705., 9730.,  9755.,  9780.,  9805.,  \
                       9830.,  9855.,  9880.,  9905., 9930.,  9955.,  9980., \
                       10005., 10030., 10055., 10080., 10105., 10130., 10155.,\
                       10180., 10205., 10230., 10255., 10280., 10305., 10330.,\
                       10355., 10380., 10405., 10430., 10455., 10480., 10505.,\
                       10530., 10555., 10580., 10605., 10630., 10655., 10680.,\
                       10705., 10730., 10755., 10780., 10805., 10830., 10855.,\
                       10880., 10905., 10930., 10955., 10980., 11005., 11030.,\
                       11055., 11080., 11105., 11130., 11155., 11180., 11205.,\
                       11230.]
    filttran[0:141,9]=[0.00e+00, 0.00e+00, 1.00e-04, 1.00e-04, 1.00e-04, \
                       2.00e-04, 2.00e-04, 3.00e-04, 5.00e-04, 7.00e-04, \
                       1.10e-03, 1.70e-03, 2.70e-03, 4.00e-03, 5.80e-03, \
                       8.20e-03, 1.14e-02, 1.55e-02, 2.02e-02, 2.55e-02, \
                       3.11e-02, 3.69e-02, 4.28e-02, 4.84e-02, 5.36e-02, \
                       5.83e-02, 6.25e-02, 6.61e-02, 6.93e-02, 7.20e-02, \
                       7.44e-02, 7.63e-02, 7.79e-02, 7.92e-02, 8.01e-02, \
                       8.08e-02, 8.12e-02, 8.13e-02, 8.12e-02, 8.07e-02, \
                       8.01e-02, 7.91e-02, 7.79e-02, 7.66e-02, 7.50e-02, \
                       7.34e-02, 7.16e-02, 6.98e-02, 6.79e-02, 6.61e-02, \
                       6.42e-02, 6.24e-02, 6.07e-02, 5.90e-02, 5.74e-02, \
                       5.59e-02, 5.46e-02, 5.35e-02, 5.24e-02, 5.15e-02, \
                       5.05e-02, 4.96e-02, 4.85e-02, 4.74e-02, 4.62e-02, \
                       4.50e-02, 4.38e-02, 4.26e-02, 4.15e-02, 4.04e-02, \
                       3.93e-02, 3.83e-02, 3.73e-02, 3.63e-02, 3.53e-02, \
                       3.42e-02, 3.31e-02, 3.19e-02, 3.07e-02, 2.94e-02, \
                       2.80e-02, 2.67e-02, 2.53e-02, 2.40e-02, 2.27e-02, \
                       2.13e-02, 2.01e-02, 1.88e-02, 1.76e-02, 1.65e-02, \
                       1.53e-02, 1.43e-02, 1.32e-02, 1.22e-02, 1.12e-02, \
                       1.03e-02, 9.40e-03, 8.60e-03, 7.80e-03, 7.10e-03, \
                       6.40e-03, 5.80e-03, 5.20e-03, 4.70e-03, 4.20e-03, \
                       3.80e-03, 3.50e-03, 3.10e-03, 2.80e-03, 2.60e-03, \
                       2.40e-03, 2.20e-03, 2.00e-03, 1.90e-03, 1.80e-03, \
                       1.60e-03, 1.50e-03, 1.40e-03, 1.30e-03, 1.20e-03, \
                       1.10e-03, 1.00e-03, 9.00e-04, 8.00e-04, 8.00e-04, \
                       7.00e-04, 7.00e-04, 6.00e-04, 6.00e-04, 5.00e-04, \
                       5.00e-04, 4.00e-04, 4.00e-04, 3.00e-04, 3.00e-04, \
                       2.00e-04, 2.00e-04, 1.00e-04, 1.00e-04, 0.00e+00, \
                       0.00e+00]

    filtsize = [24, 21, 24, 24, 23, 47, 89, 75, 89, 141]
#		Holds the filter zero-points as determined from
#		Vega model by Dreiling & Bell (ApJ, 241,736, 1980)
#
#		B	6.268e-9   erg cm-2 s-1 A-1
#		V	3.604e-9
#		R	2.161e-9
#		I	1.126e-9
#
#		The following zero-points are from Lamla
#		(Landolt-Boernstein Vol. 2b, eds. K. Schaifer & 
#		H.H. Voigt, Berlin: Springer, p. 73, 1982 QC61.L332)
#
#		U	4.22e-9   erg cm-2 s-1 A-1
#
#		J	3.1e-10
#		H	1.2e-10
#		K	3.9e-11
#
#               U        B          V        R         I
    zp_johnson = np.array([4.22e-9, 6.268e-9, 3.604e-9, 2.161e-9, 1.126e-9])
    leff_sloan=np.array([3560.,  4830.,  6260.,  7670.,  9100])
    zp_sloan=3.631e-20*2.99792458e18/(leff_sloan*leff_sloan)
    zeropoint=np.concatenate([zp_johnson,zp_sloan])
    mag=np.zeros(10)
    filtflux=mag.copy()
    coverage=mag.copy()
    efflambda=mag.copy()
    totflux=mag.copy()
    filtername = ['U', 'B', 'V', 'R', 'I','u','g','r','i','z']
    for i,_ in enumerate(filtername):
        filtw=filtwave[0:filtsize[i],i]
        filtt=filttran[0:filtsize[i],i]
        mag[i], filtflux[i], coverage[i], efflambda[i], totflux[i]= \
              filtermag(hop[0].wave,flux, filtw, filtt, \
              zeropoint[i])                                                            
    logging.info('For object {}'.format(hop[0].obname))
    logging.info('Filter magnitude  Flux(erg/s/cm^2/A) Flux(erg/s/cm^2)  Coverage(%)  Eff. Lambda')
    for i in range(0,5):
        if (mag[i] > 99):
            logging.info('  {:1s}        FILTER AND SPECTRUM DO NOT OVERLAP'.format(filtername[i]))
        else:
            logging.info('  {:1s}     {:6.3f}      {:10.4e}        {:10.4e}         {:5.1f}         {:6.1f}'.format(filtername[i],mag[i],filtflux[i],totflux[i],coverage[i]*100.,efflambda[i]))

    for i in range(5,10):
        if (mag[i] > 99):
            logging.info('  {:1s}        FILTER AND SPECTRUM DO NOT OVERLAP'.format(filtername[i]))
        else:
            logging.info('  {:1s}     {:6.3f}      {:10.4e}        {:10.4e}         {:5.1f}         {:6.1f}'.format(filtername[i],mag[i],filtflux[i],totflux[i],coverage[i]*100.,efflambda[i]))

            
    print(' ')
    logging.info('Colors')
    colortab=[[0,1],[1,2],[2,3],[2,4],[5,6],[6,7],[7,8],[8,9]]
    for i in range(0,4):
        if (mag[colortab[i][0]] > 99) or (mag[colortab[i][1]] > 99):
            logging.info('{}-{}    ONE OR BOTH FILTERS DO NOT OVERLAP SPECTRUM'.format(filtername[colortab[i][0]],filtername[colortab[i][1]]))
        else:
            logging.info('{:1s}-{:1s}    {:12.4f}'.format(filtername[colortab[i][0]],filtername[colortab[i][1]],mag[colortab[i][0]]-mag[colortab[i][1]]))
    for i in range(4,8):
        if (mag[colortab[i][0]] > 99) or (mag[colortab[i][1]] > 99):
            logging.info('{}-{}    ONE OR BOTH FILTERS DO NOT OVERLAP SPECTRUM'.format(filtername[colortab[i][0]],filtername[colortab[i][1]]))
        else:
            logging.info('{:1s}-{:1s}    {:12.4f}'.format(filtername[colortab[i][0]],filtername[colortab[i][1]],mag[colortab[i][0]]-mag[colortab[i][1]]))

    print('\nWould you like to scale the spectrum to match photometry?\n')
    answer=yesno('n')
    if (answer == 'y'):
        print('\nWhich filter do you have?')
        scalefilt=inputter_single_mix('U/B/V/R/I/u/g/r/i/z: ','UBVRIugriz')
        filtindex=filtername.index(scalefilt)
        scalemag=inputter('Enter your value for filter {}: '.format(filtername[filtindex]),'float',False)
        print(' ')
        logging.info('Scaling {} from {}={:6.3f} to {}={}'.format(hop[0].obname,filtername[filtindex],mag[filtindex],filtername[filtindex],scalemag))
        logging.info('Multiplying by {:.3f}'.format(10**(0.4*(mag[filtindex]-scalemag))))
        hop[0].flux=hop[0].flux*10**(0.4*(mag[filtindex]-scalemag))
    

    return hop
示例#19
0
def womirfilters(hop):
    """calculate photometric values from spectra"""
    import numpy as np
    import logging
    from tmath.wombat.filtermag import filtermag
    from tmath.wombat.yesno import yesno
    from tmath.wombat.inputter import inputter
    from tmath.wombat.inputter_single import inputter_single
    print('NOTE:  The routine expects an f_lambda spectrum')
    print('       I will try to guess if the spectrum')
    print('       has been scaled by 1E15')
    print(' ')
    print('       Check this before believing fluxes')
    print(' ')
    print('NOTE Also:  These are the 2MASS filter curves')
    print(' ')
    flux = hop[0].flux.copy()
    if (np.mean(flux) > 0.00001):
        flux = flux * 1.e-15

    filtwave = np.zeros((109, 3))
    filttran = np.zeros((109, 3))

    filtwave[:,0]=[1.050, 1.051, 1.062, 1.066, 1.070, 1.075, 1.078, 1.082, \
        1.084, 1.087, 1.089, 1.093, 1.096, 1.102, 1.105, 1.107, 1.109, 1.112, \
        1.116, 1.117, 1.120, 1.123, 1.128, 1.129, 1.132, 1.134, 1.138, 1.140, \
        1.143, 1.147, 1.154, 1.159, 1.164, 1.167, 1.170, 1.173, 1.175, 1.179, \
        1.182, 1.186, 1.188, 1.192, 1.195, 1.199, 1.202, 1.209, 1.216, 1.221, \
        1.227, 1.231, 1.236, 1.240, 1.244, 1.247, 1.253, 1.255, 1.258, 1.260, \
        1.265, 1.270, 1.275, 1.279, 1.286, 1.292, 1.297, 1.302, 1.305, 1.307, \
        1.310, 1.313, 1.316, 1.319, 1.323, 1.326, 1.330, 1.333, 1.334, 1.336, \
        1.339, 1.343, 1.346, 1.349, 1.353, 1.355, 1.360, 1.363, 1.370, 1.373, \
        1.377, 1.383, 1.388, 1.392, 1.395, 1.396, 1.397, 1.398, 1.400, 1.401, \
        1.402, 1.404, 1.406, 1.407, 1.410, 1.412, 1.416, 1.421, 1.426, 1.442, \
        1.450]


    filttran[:,0]=[0.0000, 0.0000, 0.0000, 0.0023, 0.0087, 0.0150, 0.0309, 0.0690, \
        0.1136, 0.1709, 0.2282, 0.2886, 0.3491, 0.4255, 0.4668, 0.5209, \
        0.5687, 0.6228, 0.6546, 0.6864, 0.7150, 0.7437, 0.7595, 0.7595, \
        0.7435, 0.7276, 0.6861, 0.6575, 0.6224, 0.5873, 0.5649, 0.5840, \
        0.6157, 0.6571, 0.6857, 0.7271, 0.7685, 0.8162, 0.8416, 0.8511, \
        0.8447, 0.8256, 0.7937, 0.7554, 0.7172, 0.6757, 0.6629, 0.6883, \
        0.7391, 0.7869, 0.8505, 0.8823, 0.8950, 0.8854, 0.8471, 0.8184, \
        0.7802, 0.7324, 0.6845, 0.6239, 0.5889, 0.5729, 0.5728, 0.5918, \
        0.6172, 0.6681, 0.6968, 0.7286, 0.7667, 0.7954, 0.8431, 0.8813, \
        0.9194, 0.9353, 0.9257, 0.9225, 0.9129, 0.8906, 0.8524, 0.8141, \
        0.7854, 0.7599, 0.7439, 0.7375, 0.7247, 0.7183, 0.7087, 0.7023, \
        0.7022, 0.7181, 0.7339, 0.7147, 0.6829, 0.6446, 0.6160, 0.5873, \
        0.5172, 0.4662, 0.3770, 0.2305, 0.1350, 0.1126, 0.0712, 0.0362, \
        0.0170, 0.0042, 0.0009, 0.0007, 0.0000]


    filtwave[0:57,1]=[1.315, 1.341, 1.368, 1.397, 1.418, 1.440, 1.462, 1.478, \
        1.486, 1.493, 1.504, 1.515, 1.528, 1.539, 1.546, 1.551, 1.556, 1.565, \
        1.572, 1.577, 1.583, 1.592, 1.597, 1.602, 1.613, 1.619, 1.628, 1.633, \
        1.642, 1.648, 1.657, 1.659, 1.671, 1.684, 1.701, 1.715, 1.727, 1.739, \
        1.746, 1.751, 1.753, 1.756, 1.764, 1.775, 1.785, 1.790, 1.796, 1.803, \
        1.810, 1.813, 1.818, 1.828, 1.835, 1.850, 1.871, 1.893, 1.914]


    filttran[0:57,1]=[0.0014, 0.0014, 0.0000, 0.0000, 0.0014, 0.0028, 0.0070, \
        0.0252, 0.0700, 0.1807, 0.3529, 0.4972, 0.6527, 0.7591, 0.8109, \
        0.8319, 0.8403, 0.8389, 0.8305, 0.8235, 0.8193, 0.8277, 0.8347, \
        0.8375, 0.8319, 0.8193, 0.8081, 0.8053, 0.8095, 0.8165, 0.8263, \
        0.8305, 0.8375, 0.8431, 0.8501, 0.8529, 0.8543, 0.8529, 0.8445, \
        0.8305, 0.8151, 0.7927, 0.7255, 0.6275, 0.5084, 0.4258, 0.3291, \
        0.2101, 0.1275, 0.0882, 0.0560, 0.0294, 0.0154, 0.0070, 0.0028, \
        0.0014, 0.0000]


    filtwave[0:76,2]=[1.900, 1.915, 1.927, 1.934, 1.939, 1.948, 1.957, 1.962, \
        1.969, 1.976, 1.981, 1.989, 1.990, 1.998, 2.008, 2.014, 2.019, 2.028, \
        2.037, 2.045, 2.061, 2.072, 2.075, 2.082, 2.089, 2.099, 2.106, 2.113, \
        2.120, 2.124, 2.138, 2.145, 2.155, 2.169, 2.176, 2.185, 2.197, 2.208, \
        2.213, 2.218, 2.232, 2.237, 2.248, 2.256, 2.260, 2.263, 2.265, 2.270, \
        2.272, 2.276, 2.277, 2.281, 2.284, 2.286, 2.291, 2.293, 2.295, 2.297, \
        2.299, 2.306, 2.311, 2.316, 2.320, 2.325, 2.328, 2.335, 2.339, 2.344, \
        2.346, 2.352, 2.361, 2.363, 2.370, 2.375, 2.384, 2.399]

    filttran[0:76,2]=[0.0000, 0.0013, 0.0027, 0.0040, 0.0082, 0.0153, 0.0293, \
        0.0462, 0.0743, 0.1222, 0.1714, 0.2672, 0.3517, 0.4263, 0.6262, \
        0.6797, 0.7487, 0.7853, 0.8120, 0.8303, 0.8485, 0.8513, 0.8583, \
        0.8597, 0.8667, 0.8751, 0.8765, 0.8835, 0.8891, 0.8863, 0.8848, \
        0.8819, 0.8805, 0.8748, 0.8804, 0.8818, 0.8902, 0.8986, 0.9014, \
        0.8999, 0.8999, 0.8956, 0.8913, 0.8969, 0.8997, 0.8997, 0.9053, \
        0.9109, 0.9166, 0.9109, 0.9025, 0.8870, 0.8686, 0.8433, 0.7714, \
        0.7292, 0.6650, 0.5950, 0.5333, 0.4094, 0.3108, 0.2234, 0.1544, \
        0.1234, 0.0896, 0.0599, 0.0416, 0.0320, 0.0300, 0.0162, 0.0063, \
        0.0007, 0.0034, 0.0020, 0.0006, 0.0000]

    filtwave = filtwave * 10000.0

    filtsize = [109, 57, 76]
    #		Holds the filter zero-points as determined from
    #		Vega model by Dreiling & Bell (ApJ, 241,736, 1980)
    #
    #		B	6.268e-9   erg cm-2 s-1 A-1
    #		V	3.604e-9
    #		R	2.161e-9
    #		I	1.126e-9
    #
    #		The following zero-points are from Lamla
    #		(Landolt-Boernstein Vol. 2b, eds. K. Schaifer &
    #		H.H. Voigt, Berlin: Springer, p. 73, 1982 QC61.L332)
    #
    #		U	4.22e-9   erg cm-2 s-1 A-1
    #
    #		J	3.1e-10
    #		H	1.2e-10
    #		K	3.9e-11
    #
    #               U        B          V        R         I

    zeropoint = [3.1e-10, 1.2e-10, 3.9e-11]

    mag = np.zeros(3)
    filtflux = mag.copy()
    coverage = mag.copy()
    efflambda = mag.copy()
    totflux = mag.copy()
    filtername = ['J', 'H', 'K']
    for i, _ in enumerate(filtername):
        filtw = filtwave[0:filtsize[i], i]
        filtt = filttran[0:filtsize[i], i]
        mag[i], filtflux[i], coverage[i], efflambda[i], totflux[i]= \
              filtermag(hop[0].wave,flux, filtw, filtt, \
              zeropoint[i])
    logging.info('For object {}'.format(hop[0].obname))
    logging.info(
        'Filter magnitude  Flux(erg/s/cm^2/A) Flux(erg/s/cm^2)  Coverage(%)  Eff. Lambda'
    )
    for i in range(0, 3):
        if (mag[i] > 99):
            logging.info(
                '  {:1s}        FILTER AND SPECTRUM DO NOT OVERLAP'.format(
                    filtername[i]))
        else:
            logging.info(
                '  {:1s}     {:6.3f}      {:10.4e}        {:10.4e}         {:5.1f}         {:7.1f}'
                .format(filtername[i], mag[i], filtflux[i], totflux[i],
                        coverage[i] * 100., efflambda[i]))

    print(' ')
    logging.info('Colors')
    colortab = [[0, 1], [1, 2]]
    for i in range(0, 2):
        if (mag[colortab[i][0]] > 99) or (mag[colortab[i][1]] > 99):
            logging.info(
                '{}-{}    ONE OR BOTH FILTERS DO NOT OVERLAP SPECTRUM'.format(
                    filtername[colortab[i][0]], filtername[colortab[i][1]]))
        else:
            logging.info('{:1s}-{:1s}    {:12.4f}'.format(
                filtername[colortab[i][0]], filtername[colortab[i][1]],
                mag[colortab[i][0]] - mag[colortab[i][1]]))

    print('\nWould you like to scale the spectrum to match photometry?\n')
    answer = yesno('n')
    if (answer == 'y'):
        print('\nWhich filter do you have?')
        scalefilt = inputter_single_mix('J/H/K: ', 'JHK')
        filtindex = filtername.index(scalefilt)
        scalemag = inputter(
            'Enter your value for filter {}: '.format(filtername[filtindex]),
            'float', False)
        print(' ')
        logging.info('Scaling {} from {}={:6.3f} to {}={}'.format(
            hop[0].obname, filtername[filtindex], mag[filtindex],
            filtername[filtindex], scalemag))
        logging.info('Multiplying by {:.3f}'.format(
            10**(0.4 * (mag[filtindex] - scalemag))))
        hop[0].flux = hop[0].flux * 10**(0.4 * (mag[filtindex] - scalemag))

    return hop
def womscalemany(hop):
    """scale many hoppers to one"""
    import matplotlib.pyplot as plt
    import numpy as np
    import logging
    from tmath.wombat.inputter import inputter
    from tmath.wombat.womwaverange import womwaverange
    from tmath.wombat.womget_element import womget_element
    from tmath.wombat import HOPSIZE
    print('This will scale many hoppers to one')
    done = False
    while (not done):
        hopnum1 = inputter('Enter fiducial hopper: ', 'int', False)
        if (hopnum1 < 1) or (hopnum1 > HOPSIZE):
            print('Hopper number must be in range 1-{}'.format(HOPSIZE))
        else:
            done = True
    hoplist = []
    hopnum2 = 0
    while (hopnum2 != 99):
        done = False
        while (not done):
            hopnum2 = inputter('Enter another hopper: (99 to end) ', 'int',
                               False)
            if (hopnum2 != 99):
                if (hopnum2 < 1) or (hopnum2 > HOPSIZE):
                    print(
                        'Hopper numbers must be in range 1-{}'.format(HOPSIZE))
                elif (len(hop[hopnum2].wave) == 0):
                    print('Nothing in that hopper')
                else:
                    hoplist.append(hopnum2)
                    done = True
                if (hopnum2 > 0) and (hopnum2 < 21) and \
                   (len(hop[hopnum2].wave) != 0):
                    if (hop[hopnum1].wave[0] != hop[hopnum2].wave[0])  \
                       or (hop[hopnum1].wave[1] != hop[hopnum2].wave[1]) \
                       or (hop[hopnum1].wave[-1] != hop[hopnum2].wave[-1]):
                        print('Hoppers to not have the same wavelength scale!')
                        return hop
            else:
                done = True
    print('\nSpectra run from {} to {}'.format(hop[hopnum1].wave[0], \
                                             hop[hopnum1].wave[-1]))

    plt.cla()
    plt.plot(hop[hopnum1].wave,hop[hopnum1].flux,drawstyle='steps-mid', \
             color='k')
    plt.xlabel('Wavelength')
    plt.ylabel('Flux')
    plt.title(hop[hopnum1].obname)
    print('\nPlotting fiducial spectrum')
    print('\nChoose region to compute average')
    wave, flux, mode = womwaverange(hop[hopnum1].wave, hop[hopnum1].flux,
                                    'none')
    indexblue = womget_element(hop[hopnum1].wave, wave[0])
    indexred = womget_element(hop[hopnum1].wave, wave[-1])
    avg1 = np.mean(hop[hopnum1].flux[indexblue:indexred + 1])
    print('Fiducial spectrum mean in range: {}'.format(avg1))
    for i, _ in enumerate(hoplist):
        print('{} {}'.format(i, hoplist[i]))
        avgloop = np.mean(hop[hoplist[i]].flux[indexblue:indexred + 1])
        print('Hopper {} mean in range: {}'.format(hoplist[i], avgloop))
        hop[hoplist[i]].flux = hop[hoplist[i]].flux * avg1 / avgloop
        hop[hoplist[i]].var = hop[hoplist[i]].var * avg1 / avgloop
        logging.debug('File: {} scaled by {} to match {}'.format(
            hop[hoplist[i]].obname, avg1 / avgloop, hop[hopnum1].obname))
    return hop
示例#21
0
def womzap(hop):
    """routine to zap outliers (CRs)"""
    import numpy as np
    import matplotlib.pyplot as plt
    import logging
    from tmath.wombat.inputter import inputter
    from tmath.wombat.inputter_single import inputter_single
    from tmath.wombat.yesno import yesno
    from tmath.wombat.wshow import wshow
    plt.cla()
    plt.plot(hop[0].wave,hop[0].flux,drawstyle='steps-mid')
    plt.xlabel('Wavelength')
    plt.ylabel('Flux')
    plt.title(hop[0].obname)
    wshow()
    print('\nRoutine to zap outliers\n')
    done = False
    while (not done):
        nsig=inputter('Enter zapping threshold in sigmas (0=replace all with median): ','float',False)
        print(' ')
        boxsize=inputter('Enter box size for computing statistics: (odd integer < 45) ','int',False)
        if (boxsize < 3) or (boxsize > 45) or (nsig < 0):
            print('Invalid boxsize or sigma')
        else:
            done = True
    if (boxsize % 2 == 0):
        boxsize=boxsize+1
    half=int(boxsize/2.)
    newflux=hop[0].flux.copy()
    if (nsig > 0):
        mode=inputter_single('Use inter(q)uartile or (m)edian variance (q/m)? ','qm')
        if (mode == 'm'):
            for i in range(half,len(newflux)-half):
                sample=newflux[i-half:i+half+1]
                medval=np.median(sample)
                varpix=(sample[half]-medval)**2
                sum=-1.0*varpix
                for k in range(0,boxsize):
                    diff=sample[k]-medval
                    sum=sum+diff*diff
                sum=sum/(boxsize-1)
                if (varpix > nsig*nsig*sum):
                    newflux[i]=medval
        if (mode == 'q'):
            for i in range(half,len(newflux)-half):
                sample=newflux[i-half:i+half+1]
                medval=np.median(sample)
                q25=np.percentile(sample,25.)
                q75=np.percentile(sample,75.)
                qsig=0.7414272*(q75-q25)
                diff=abs(sample[half]-medval)
                if (diff > nsig*qsig):
                    newflux[i]=medval
    if (nsig == 0):
        from scipy.ndimage.filters import median_filter
        newflux=median_filter(newflux,boxsize)
    plt.plot(hop[0].wave,newflux,drawstyle='steps-mid')
    print('Does this zapping look good?')
    good=yesno('y')
    if (good == 'y'):
        hop[0].flux=newflux.copy()
        logging.debug('File {} zapped with sigma {} and boxsize {}'.format\
                      (hop[0].obname,nsig,boxsize))
    else:
        print('OK, active spectrum unchanged')
    #FIX var
    return hop
                                                                           
def womspl(hop, fig):
    """fit spline to spectrum"""
    import matplotlib.pyplot as plt
    import numpy as np
    import copy
    from tmath.wombat.womplot import womplot
    from tmath.wombat.onclick import onclick
    from scipy.interpolate import splrep, splev
    from tmath.wombat.inputter import inputter
    from tmath.wombat.yesno import yesno
    from tmath.wombat import HOPSIZE
    import tmath.wombat.womconfig as womconfig
    #    global nsplinepoints, tmpsplptsx, tmpsplptsy, pflag
    print('\nObject is {}\n'.format(hop[0].obname))
    womplot(hop)
    xmin, xmax = plt.xlim()
    ymin, ymax = plt.ylim()
    plt.xlim([xmin, xmax])
    plt.ylim([ymin, ymax])
    womconfig.nsplinepoints = 0
    womconfig.tmpsplptsx = []
    womconfig.tmpsplptsy = []

    done = False
    while (not done):
        plt.cla()
        plt.plot(hop[0].wave, hop[0].flux, drawstyle='steps-mid')
        if (len(womconfig.tmpsplptsx) > 0):
            plt.plot(womconfig.tmpsplptsx, womconfig.tmpsplptsy, 'ro')
        plt.xlabel('Wavelength')
        plt.ylabel('Flux')
        plt.title(hop[0].obname)
        plt.xlim([xmin, xmax])
        plt.ylim([ymin, ymax])
        cid = fig.canvas.mpl_connect('button_press_event', onclick)
        print('\nClick on continuum points for spline fit.')
        print('Left button    = add point')
        print('Middle button  = delete point')
        print('Right button   = done\n')
        womconfig.pflag = ''
        while (womconfig.pflag != 'done'):
            plt.pause(0.01)
        fig.canvas.mpl_disconnect(cid)

        splptsy = [
            z
            for _, z in sorted(zip(womconfig.tmpsplptsx, womconfig.tmpsplptsy))
        ]
        splptsx = sorted(womconfig.tmpsplptsx)
        spline = splrep(splptsx, splptsy, k=3)
        splineresult = splev(hop[0].wave, spline)
        plt.plot(hop[0].wave, splineresult, drawstyle='steps-mid')
        plt.pause(0.01)
        print('Is this fit OK? ')
        answer = yesno('y')
        if (answer == 'y'):
            done = True
    print('\nSubtract spline fit from flux?\n')
    sub = yesno('n')
    if (sub == 'y'):
        hop[0].flux = hop[0].flux - splineresult
    print('\nStore spline in hopper?\n')
    store = yesno('y')
    if (store == 'y'):
        hopnum = 0
        while (hopnum < 1) or (hopnum > HOPSIZE):
            hopnum = inputter('Store in which hopper: ', 'int', False)
        hop[hopnum] = copy.deepcopy(hop[0])
        hop[hopnum].flux = splineresult.copy()
        hop[hopnum].obname = hop[hopnum].obname + 'spline'
        hop[hopnum].var = np.zeros(len(hop[0].wave))
    return hop
def wommkatmdisp(hop):
    import numpy as np
    import matplotlib.pyplot as plt
    from tmath.wombat.waveparse import waveparse
    from tmath.wombat.inputter import inputter
    from tmath.wombat.airtovac import airtovac
    light_speed = 2.99792458e10
    h_planck = 6.6260755e-27
    k_boltzmann = 1.380658e-16
    print('This routine will create a curve of the dispersion of light')
    print('by the atmosphere in arc seconds per 1 Angstrom bin')
    print('\n')
    print('Enter airmass for the calculation: ')
    airmass = inputter('(default = 1.5): ', 'float', True, 1.5)
    if (airmass < 1.0) or (airmass > 7.0):
        airmass = 1.5
    print('Enter temperature at telescope in degrees Celsius: ')
    temp = inputter('(default = 7C [45F]): ', 'float', True, 7.0)
    if (temp <= -100) or (temp >= 100):
        temp = 7.0
    print('Enter barometric pressure at telescope in mm of Hg: ')
    press = inputter('(default = 600 mm Hg): ', 'float', True, 600.0)
    if (press <= 0):
        press = 600.0
    print('Enter water vapor pressure at telescope in mm of Hg: ')
    water = inputter('(default = 8 mm Hg): ', 'float', True, 8.0)
    if (water <= 0):
        water = 8.0

    waveb, waver = waveparse()
    if (waver < waveb):
        waveb, waver = waver, waveb
    if (waver == waveb):
        waver = waver + 1.
    print('\nOK, calculating dispersion of light in arc seconds over the')
    print('range {}A to {}A at temperature {}C, pressure {} mm Hg,'.format(
        waveb, waver, temp, press))
    print('and water vapor pressure {} mm Hg at airmass {}.'.format(
        water, airmass))
    print('Zero is set at 5000A.')

    wave = np.arange(waveb, waver + 1.)
    vacuum = airtovac(wave)
    lfactor = (1.e4 / vacuum)**2
    waterfactor = water * ((0.0624 - 0.000680 * lfactor) /
                           (1.0 + 0.003661 * temp))
    nstp = 1E-6 * (64.328 + (29498.1 / (146.0 - lfactor)) + (255.4 /
                                                             (41 - lfactor)))
    n = (nstp)*((press*(1.0+(1.049-0.0157*temp)*1E-6*press))/  \
              (720.883*(1.0+0.003661*temp)))-waterfactor*1.0E-6
    n = n + 1.0
    five = airtovac(np.array([5000.0]))
    fivefact = (1.e4 / five)**2
    wfive = water * ((0.0624 - 0.000680 * fivefact) / (1.0 + 0.003661 * temp))
    nstpfive = 1E-6 * (64.328 + (29498.1 / (146.0 - fivefact)) +
                       (255.4 / (41 - fivefact)))
    nfive = (nstpfive)*((press*(1.0+(1.049-0.0157*temp)*1E-6*press))/ \
                        (720.883*(1.0+0.003661*temp)))-wfive*1.0E-6
    nfive = nfive + 1.0
    cosz = 1. / airmass
    tanz = (np.sqrt(1 - cosz**2)) / cosz
    flux = 206265. * (n - nfive) * tanz
    spectxt = 'Atmospheric dispersion curve at z = {}'.format(airmass)
    plt.cla()
    plt.plot(wave, flux, drawstyle='steps-mid')
    plt.title(spectxt)
    hop[0].wave = wave.copy()
    hop[0].flux = flux.copy()
    hop[0].obname = spectxt
    hop[0].var = np.ones(wave.shape)
    hop[0].header = ''
    return hop
示例#24
0
def mkbstar(bfile, gratcode):
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.widgets import Cursor
    from astropy.io import fits
    from tmath.wombat.get_screen_size import get_screen_size
    from tmath.wombat.getmswave import getmswave
    from tmath.wombat.inputter_single import inputter_single
    from tmath.wombat.inputter import inputter
    from tmath.wombat.yesno import yesno
    from tmath.pydux.obs_extinction import obs_extinction
    from tmath.pydux.wave_telluric import wave_telluric
    from tmath.pydux.fitspl import fitspl
    from tmath.pydux.bblo import bblo
    from tmath.pydux.finalscaler import finalscaler
    from tmath.pydux.pacheck import pacheck

    screen_width, screen_height = get_screen_size()
    plt.ion()
    screenpos = '+{}+{}'.format(int(screen_width * 0.2),
                                int(screen_height * 0.05))
    fig = plt.figure()

    fig.canvas.manager.window.wm_geometry(screenpos)
    fig.canvas.set_window_title('B Star')
    fig.set_size_inches(18, 12)
    # turns off key stroke interaction
    fig.canvas.mpl_disconnect(fig.canvas.manager.key_press_handler_id)

    # this should bring the window to the top, but it doesn't
    wm = plt.get_current_fig_manager()
    #fig.canvas.manager.window.attributes('-topmost', 1)
    blah = wm.window.attributes('-topmost', 1)

    #plt.pause(0.2)
    #fig.canvas.manager.window.attributes('-topmost', 0)
    blah = wm.window.attributes('-topmost', 0)

    fitsfile = fits.open(bfile)
    rawdata = fitsfile[0].data
    head = fitsfile[0].header
    num_apertures = rawdata.shape[1]
    wavearr = np.zeros((rawdata.shape[2], rawdata.shape[1]))
    objectname = head['OBJECT']
    airmass = float(head['AIRMASS'])
    exptime = float(head['EXPTIME'])

    if (exptime < 1):
        exptime = 1.
    head = pacheck(head)
    observat = head['OBSERVAT'].strip().lower()
    sitefactor = obs_extinction(observat)
    for i in range(0, num_apertures):
        wavearr[:, i] = getmswave(head, i)
    if (wavearr[-1, 0] < 3000):
        print('************************************************')
        print('Spectrum not wavelength calibrated---bailing out')
        print('************************************************')
        sys.exit(1)
    ap_choice = -1
    if (np.mean(rawdata[0, 0, :]) < 1e-7):
        rawdata = rawdata * 1e15
    # scale to rational numbers for fit (rational as in sane,
    # not opposed to irrational)
    if (num_apertures != 1):
        axarr = fig.subplots(num_apertures, sharex=True)
        fig.subplots_adjust(hspace=0)
        for i in range(0, num_apertures):
            x = wavearr[:, i]
            y = rawdata[0, i, :]
            axarr[i].clear()

            plt.pause(0.01)
            axarr[i].plot(x, y, drawstyle='steps-mid')
            axarr[i].set_ylabel('Aperture {}'.format(i))
            plt.pause(0.01)
        while (ap_choice < 0) or (ap_choice > num_apertures - 1):
            ap_choice = inputter(
                'Which aperture do you want to use for the B star? ', 'int',
                False)
        fig.clf()
    else:
        ap_choice = 0
    ymin, ymax = finalscaler(rawdata[0, ap_choice, :])
    fig.clf()
    x1 = wavearr[:, ap_choice]
    y1 = rawdata[1, ap_choice, :]
    y0 = rawdata[0, ap_choice, :]
    plt.plot(x1, y1, drawstyle='steps-mid', color='r')
    plt.plot(x1, y0, drawstyle='steps-mid', color='k')
    plt.pause(0.01)
    plt.ylim([ymin, ymax])
    plt.pause(0.01)
    print('\nPlotting optimal as black, normal as red')
    extract = inputter_single(
        'Do you want to use (n)ormal or (o)ptimal extraction? ', 'no')
    if (extract == 'o'):
        bstar = rawdata[0, ap_choice, :]
    else:
        bstar = rawdata[1, ap_choice, :]
    # fix IRAF weirdness where data can go negative in dispcor interpolation
    bstar[np.where(bstar < 0)] = 0.01
    wave = wavearr[:, ap_choice]
    print('\nAirmass: {}\n'.format(airmass))
    airlimit = 0.5
    while (airlimit < 1.0) or (airlimit > 10.):
        airlimit = inputter('Above what airmass is considered high? ', 'float',
                            False)

    print('\nNow fit the continuum manually\n')
    plt.clf()
    ax = fig.add_subplot(111)
    cursor = Cursor(ax, useblit=True, color='k', linewidth=1)
    airlimit = 1.5
    splineresult = fitspl(wave, np.log10(bstar), (airmass > airlimit), fig)
    splineresult = 10**(splineresult)
    plt.cla()
    plt.plot(wave, splineresult, drawstyle='steps-mid')
    plt.pause(0.01)
    bstar = bstar / splineresult
    if (airmass > airlimit):
        loc = wave_telluric(wave, 'high')
    else:
        loc = wave_telluric(wave, 'low')
    #invert loc and convert all good sections to np.nan so they won't plot
    loc = np.invert(loc)
    bstar[loc] = 1.0
    bstar[np.where(bstar > 1.)] = 1.0
    bstar[np.where(bstar <= 0.)] = 0.01
    plt.cla()
    plt.plot(wave, bstar, drawstyle='steps-mid')
    plt.pause(0.01)
    print('\nDo you want to blotch the B-star?')
    blotch = yesno('n')
    if (blotch == 'y'):
        bstar = bblo(wave, bstar, (airmass > airlimit), fig)
    delkeylist=['WAT0_001', 'WAT1_001', 'WAT2_001', 'WAT0_002', \
                'WAT1_002', 'WAT2_002', 'WAT3_001', 'WAT2_003', \
                'CTYPE1', 'CTYPE2', 'CTYPE3', 'CD1_1', 'CD2_2', \
                'CD3_3', 'LTM1_1', 'LTM2_2', 'LTM3_3', 'WCSDIM']
    for k in delkeylist:
        try:
            head.remove(k)
        except KeyError:
            pass
    plt.cla()
    plt.plot(wave, bstar, drawstyle='steps-mid')
    plt.pause(0.01)
    head.set('CRPIX1', 1)
    head.set('CRVAL1', wave[0])
    head.set('CDELT1', wave[1] - wave[0])
    head.set('CTYPE1', 'LINEAR')
    outfile = 'bstar' + gratcode + '.fits'
    print('Writing data to {}'.format(outfile))
    outhdu = fits.PrimaryHDU(bstar)
    hdul = fits.HDUList([outhdu])
    hdul[0].header = head.copy()
    hdul.writeto(outfile, overwrite=True)
    print('mkbstar')
    print(bfile, gratcode)
    return
示例#25
0
def main():
    secondord = False
    gratcode2 = ''
    # logging straight from docs.python.org cookbook page
    #  INFO level to screen and cal.log
    #  DEBUG level only to cal.log
    logging.getLogger('matplotlib').setLevel(logging.WARNING)
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S',
                        filename='cal.log',
                        filemode='a')
    # define a Handler which writes INFO messages or higher to the sys.stderr
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    # set a format which is simpler for console use
    formatter = logging.Formatter('%(message)s')
    # tell the handler to use this format
    console.setFormatter(formatter)
    # add the handler to the root logger
    logging.getLogger('').addHandler(console)

    user = getpass.getuser()
    print('Hello, {} \n'.format(user))
    logging.debug('CAL starts')
    logging.debug('{} running things'.format(user))

    print(' ')
    print('This program is a driver for the calibration routines.')
    print('It expects files that have been dispersion calibrated,')
    print('usually through IRAF (you know, with a -d- in front).')
    print('(In other words, include the d in your file names.)')
    print(' ')
    print('Do you want to use second-order correction?\n')
    answer = yesno('n')
    if (answer == 'y'):
        secondord = True
    #axarr=fig.subplots(2,sharex=True)
    #fig.subplots_adjust(hspace=0)

    print('\nWe now need a grating code, such as opt or ir2.')
    print('This will be used to keep track of the fluxstar and')
    print('bstar as in fluxstaropt.fits or bstarir2.fits\n')
    gratcode = inputter('Enter the grating code: ', 'string', False)
    print(' ')
    if (secondord):
        gratcode2 = inputter('Enter the second-order grating code: ', 'string', False)
    print(' ')
    print('Enter the file containing the list of objects')
    print('(should be dispersion-corrected)\n')
    done = False
    while (not done):
        # objectlist = inputter('Object list file: ', 'string', False)
        dfiles=glob.glob('d*.fits')
        for d in dfiles:
            if gratcode in d:
                listfile= open(d.split('_ex.fits')[0],"w+")
                listfile.write(d)
                listfile.close()
                objectlist = listfile.name
        if (os.path.isfile(objectlist)):
            done = True
        else:
            print('No such file')
    print('\nDo you want to fit a flux star?\n')
    answer = yesno('y')
    if (answer == 'y'):
        plt.close()
        fluxfile = getfitsfile('flux star', '.fits')
        pydux.mkfluxstar(fluxfile, gratcode)
        if (secondord):
            print(' ')
            fluxfile2 = getfitsfile('second flux star', '.fits')
            pydux.mkfluxstar(fluxfile2, gratcode2)
    else:
        try:
            fluxfits = fits.open('fluxstar'+gratcode+'.fits')
            fluxfile = fluxfits[0].header['FLUXFILE']
            fluxfits.close()
        # except FileNotFoundError:
        except KeyError:
            fluxfile = 'Unknown'
        if (secondord):
            try:
                fluxfits2 = fits.open('fluxstar'+gratcode2+'.fits')
                fluxfile2 = fluxfits2[0].header['FLUXFILE']
                fluxfits2.close()
            # except FileNotFoundError:
            except KeyError:
                fluxfile2 = 'Unknown'

    print('\nDo you want to apply the flux star(s) to the data?\n')
    answer = yesno('y')
    if (answer == 'y'):
        pydux.calibrate(objectlist, gratcode, secondord, gratcode2)


    print('\nDo you want to fit a b-star?\n')
    answer = yesno('y')
    if (answer == 'y'):
        plt.close()
        print('\nDo you want to use the flux star {}'.format(fluxfile))
        print('as the b-star?\n')
        same = yesno('y')
        print(' ')
        if (same == 'n'):
            bfile = getfitsfile('b-star', '.fits')
        else:
            bfile = fluxfile
        bfile = 'c'+gratcode+bfile
        pydux.mkbstar(bfile, gratcode)
        if (secondord):
            print('\nDo you want to use the flux star {}'.format(fluxfile2))
            print('as the b-star?\n')
            same = yesno('y')
            if (same == 'n'):
                bfile2 = getfitsfile('b-star', '.fits')
            else:
                bfile2 = fluxfile2
            bfile2 = 'c'+gratcode+bfile2
            pydux.mkbstar(bfile2, gratcode2)

    print('\nFinal calibration (atmos. removal, sky line wave. adjust, etc.)?')
    answer = yesno('y')
    if (answer == 'y'):
        plt.close()
        pydux.final(objectlist, gratcode, secondord, gratcode2, user)

    print('\nThere, was that so hard?')
示例#26
0
def final(objectlist, gratcode, secondord, gratcode2, user):
    import matplotlib.pyplot as plt
    from matplotlib import gridspec
    import numpy as np
    from datetime import datetime
    import os, pdb
    import inspect
    import glob
    import math
    from astropy.io import fits
    from astropy import units as u
    from astropy.coordinates import SkyCoord
    #    from astropy.time import Time
    from tmath.wombat.get_screen_size import get_screen_size
    from tmath.wombat.getmswave import getmswave
    from tmath.wombat.inputter_single import inputter_single
    from tmath.wombat.inputter import inputter
    from tmath.wombat.womcatfinal import womcatfinal
    from tmath.pydux.scipyrebinsky import scipyrebinsky
    from tmath.wombat.yesno import yesno
    from tmath.wombat.womashrebin import womashrebin
    from tmath.wombat.wominterpofluxconserving import interpo_flux_conserving
    from tmath.wombat.womspectres import spectres
    from tmath.pydux.getfitsfile import getfitsfile
    from tmath.pydux.pacheck import pacheck
    from tmath.pydux.jdcnv import jdcnv
    from tmath.pydux.baryvel import baryvel
    from tmath.pydux.finalscaler import finalscaler
    from tmath.pydux.envelope import envelope
    from tmath.pydux.congrid import congrid
    from tmath.pydux.xcor import xcor
    from tmath.pydux.telluric_remove import telluric_remove
    from tmath.pydux.waveparse import waveparse
    from tmath.pydux.parsehourangle import parsehourangle
    from tmath.pydux import RADEG
    plt.ion()

    screen_width, screen_height = get_screen_size()
    screenpos = '+{}+{}'.format(int(screen_width * 0.2),
                                int(screen_height * 0.05))
    fig = plt.figure()

    fig.canvas.manager.window.wm_geometry(screenpos)
    fig.canvas.set_window_title('Final Reductions')
    fig.set_size_inches(8, 5)
    # turns off key stroke interaction
    fig.canvas.mpl_disconnect(fig.canvas.manager.key_press_handler_id)

    # this should bring the window to the top, but it doesn't
    # wm=plt.get_current_fig_manager()
    #fig.canvas.manager.window.attributes('-topmost', 1)
    # blah=wm.window.attributes('-topmost', 1)

    #plt.pause(0.2)
    #fig.canvas.manager.window.attributes('-topmost', 0)
    # blah=wm.window.attributes('-topmost', 0)

    bstarfits = fits.open('bstar' + gratcode + '.fits')
    bstarstar = bstarfits[0].data
    bstarhead = bstarfits[0].header
    bstarwavezero = float(bstarhead['CRVAL1'])
    bstarwavedelt = float(bstarhead['CDELT1'])
    bstarwave = np.arange(len(bstarstar)) * bstarwavedelt + bstarwavezero
    bstarairmass = float(bstarhead['AIRMASS'])
    bstarname = bstarhead['OBJECT']
    try:
        bstarnum = int(bstarhead['OBSNUM'])
    except KeyError:
        bstarnum = 0
    if (secondord):
        bstarfits2 = fits.open('bstarstar' + gratcode2 + '.fits')
        bstarstar2 = bstarfits[0].data
        bstarhead2 = bstarfits[0].header
        bstarwavezero2 = float(bstarhead2['CRVAL1'])
        bstarwavedelt2 = float(bstarhead2['CDELT1'])
        bstarwave2 = np.arange(
            len(bstarstar2)) * bstarwavedelt2 + bstarwavezero2
        bstarairmass2 = float(bstarhead2['AIRMASS'])
        bstarname2 = bstarhead2['OBJECT']
        try:
            bstarnum2 = int(bstarhead2['OBSNUM'])
        except KeyError:
            bstarnum2 = 0
    observat = bstarhead['OBSERVAT'].strip().lower()
    #reduxdir=os.environ['PY_REDUX']
    reduxdir = inspect.getfile(xcor)
    reduxdir = reduxdir.rsplit('/', 1)[0] + '/'
    kecksky=['keck','gemini-north','gemini-n','gemini-south','gemini-s', \
             'soar','ctio','vlt','lco','lco-imacs','lapalma']
    licksky = ['lick', 'kpno', 'flwo', 'mmto', 'sso']
    if (observat in kecksky):
        mskyfile = reduxdir + 'kecksky.fits'
    elif (observat in licksky):
        mskyfile = reduxdir + 'licksky.fits'
    else:
        print('\nCannot find mastersky file and observatory unknown\n')
        mskyfile = getfitsfile('master sky', '.fits')
    print('Using {} as master sky'.format(mskyfile))
    mskyfits = fits.open(mskyfile)
    mskydata = mskyfits[0].data
    mskyhead = mskyfits[0].header
    mskywavezero = float(mskyhead['CRVAL1'])
    mskywavedelt = float(mskyhead['CDELT1'])
    mskywave = np.arange(len(mskydata)) * mskywavedelt + mskywavezero
    if (np.abs(np.mean(mskydata)) < 1e-7):
        mskydata = mskydata * 1e15
    print('\nHello {}\n'.format(user))
    lat_dict = {
        'keck': 19.8283,
        'gemini-north': 19.8238,
        'gemini-south': -30.228,
        'gemini-n': 19.8238,
        'gemini-s': -30.228,
        'soar': -30.228,
        'kpno': 31.9633,
        'lick': 37.3414,
        'palomar': 33.35611,
        'mcdonald': 30.6717,
        'flwo': 31.681,
        'mmto': 31.688,
        'sso': -31.2734,
        'vlt': -24.6254,
        'lco': -29.01,
        'lco-imacs': -29.01,
        'lapalma': 28.75833,
        'ctio': -30.16894
    }
    infile = open(objectlist, 'r')
    objname = ''
    secondtime = False
    seconddone = False
    for inputfile in infile:
        inputfile = inputfile.strip()
        if ('.fits' not in inputfile):
            inputfile = inputfile + '.fits'
        multifits = fits.open('c' + gratcode + inputfile)
        multispec = multifits[0].data
        mshead = multifits[0].header
        num_apertures = multispec.shape[1]
        num_bands = multispec.shape[0]
        wavearr = np.zeros((multispec.shape[2], multispec.shape[1]))
        if (secondord):
            multifits2 = fits.open('c' + gratcode2 + inputfile)
            multispec2 = multifits2[0].data
            mshead2 = multifits2[0].header
        pacheck(mshead)
        objectname = mshead['OBJECT']
        print('The object is: {}'.format(objectname))
        observat = mshead['OBSERVAT'].strip().lower()
        airmass = float(mshead['AIRMASS'])
        if (airmass < 1):
            airmass = 1.0
        stringra = mshead['RA']
        stringdec = mshead['DEC']
        geminilist = ['gemini-north', 'gemini-south', 'gemini-n', 'gemini-s']
        if (observat) in geminilist:
            ra = float(stringra)
            dec = float(stringdec)
        else:
            coords = SkyCoord(stringra, stringdec, unit=(u.hourangle, u.deg))
            ra = coords.ra.deg
            dec = coords.dec.deg
        ra = ra / RADEG
        dec = dec / RADEG
        haheader = mshead['HA']
        ha = parsehourangle(haheader)
        ha = ha * (360. / 24.) / RADEG

        if (observat in lat_dict):
            latitude = lat_dict[observat]
        else:
            print('Observatory Unknown!!!!!!!')
            latitude = 0.0
        latitude = latitude / RADEG
        # Get Julian date and Earth's velocity
        #epoch=float(mshead['EPOCH'])
        date = mshead['DATE-OBS'].strip()
        # get year,month,day from ISO Y2K format YYYY-MM-DDThh:mm:ss.ssss
        # the time following T is optional, so we get T from UTMIDDLE
        if (date[4] == '-'):
            year = int(date.split('-')[0])
            month = int(date.split('-')[1])
            day = int(date.split('-')[2].split('T')[0])
            printdate = '{}{:02d}{:02d}'.format(year, month, day)
        else:
            # Old date format DD/MM/YY
            year = int(date[6:8])
            month = int(date[3:5])
            day = int(date[0:2])
            # try to catch old format written after 2000
            # good until 2050, by which time no one should
            # be doing this
            if (year > 50):
                year = year + 1900
            else:
                year = year + 2000
            printdate = '{}{:02d}{:02d}'.format(year, month, day)
        try:
            ut = mshead['UTMIDDLE'].strip()
        except KeyError:
            ut = mshead['UT'].strip()
        if ('T' in ut):
            ut = ut.split('T')[1]
        # some UT/UTMIDDLE values are ISO format
        hour = int(ut.split(':')[0])
        minute = int(ut.split(':')[1])
        second = float(ut.split(':')[2])
        julian = jdcnv(year, month, day,
                       (hour + (minute / 60.) + (second / 3600.)))
        vh, vb = baryvel(julian)
        # Earth's velocity toward object
        v=vb[0]*np.cos(dec)*np.cos(ra) + vb[1]*np.cos(dec)*np.sin(ra) \
           + vb[2]*np.sin(dec)
        # Correct for earth's rotation.
        # Note that this isn't strictly correct because ha is set to
        # the beginning of the observation, while it really should be
        # the middle.  But this is a small difference and doesn't affect
        # the results in any way that we would notice...
        v = v - (0.4651 * np.cos(latitude) * np.sin(ha) * np.cos(dec))
        print(
            '\nThe velocity of the Earth toward the target is {} km/s'.format(
                v))
        print('\nThere are {} apertures in the spectrum.\n'.format(
            num_apertures))
        # clean up header
        """        delkeylist=['WAT0_001', 'WAT1_001', 'WAT2_001', 'WAT0_002', \
                'WAT1_002', 'WAT2_002', 'WAT3_001', 'WAT2_003', \
                'CTYPE1', 'CTYPE2', 'CTYPE3', 'CD1_1', 'CD2_2', \
                'CD3_3', 'LTM1_1', 'LTM2_2', 'LTM3_3', 'WCSDIM']
        for k in delkeylist:
            try:
                mshead.remove(k)
            except KeyError:
                pass """
        waveb = None
        waver = None
        bshift = None
        for i in range(0, num_apertures):
            # plt.close()
            # fig=plt.figure()
            # plt.plot(multispec[0,i,:], drawstyle='steps-mid',color='r')
            # plt.plot(multispec[1,i,:], drawstyle='steps-mid',color='k')
            # plt.xlim(1750,1900)
            # plt.pause(0.01)
            # print('Check plot')
            # answer=yesno('y')

            print('\nAperture {}:'.format(i + 1))
            wave = getmswave(mshead, i)
            print(wave[0], wave[-1])
            wdelt = wave[1] - wave[0]
            mean = np.mean(multispec[0, i, :])
            ymin, ymax = finalscaler(multispec[0, i, :])
            # plt.clf()
            gs = gridspec.GridSpec(2, 1, height_ratios=[4, 1])
            ax0 = plt.subplot(gs[0])
            ax1 = plt.subplot(gs[1])
            fig.subplots_adjust(hspace=0)
            ax0.plot(wave,
                     multispec[1, i, :],
                     drawstyle='steps-mid',
                     color='r')
            ax0.plot(wave,
                     multispec[0, i, :],
                     drawstyle='steps-mid',
                     color='k')
            # ax0.plot(multispec[0,i,:],multispec[2,i,:],drawstyle='steps-mid',color='r')
            # ax0.plot(multispec[0,i,:],multispec[1,i,:],drawstyle='steps-mid',color='k')
            plt.pause(0.01)
            ax0.set_ylim((ymin, ymax))
            ax1.semilogy(wave,np.abs(multispec[1,i,:]-multispec[0,i,:])/mean, \
                         drawstyle='steps-mid',color='k')
            ax0.set_ylabel('Flux')
            ax1.set_ylabel('Log of fractional residuals')
            ax1.set_xlabel('Wavelength')
            plt.pause(0.01)
            print('\nPlotting optimal as black, normal as red\n')
            extract = inputter_single(
                'Do you want to use the (n)ormal or the (o)ptimal extraction? ',
                'no')
            if (extract == 'o'):
                object = multispec[0, i, :]
                extractcode = 'optimal'
                if (secondord):
                    object2 = multispec2[0, i, :]
            else:
                object = multispec[1, i, :]
                extractcode = 'normal'
                if (secondord):
                    object2 = multispec2[1, i, :]
            skyband = 2
            if (num_bands == 2):
                skyband = 1
            if (num_bands > 3):
                sigma = multispec[3, i, :]
            else:
                sigma = np.sqrt(multispec[skyband, i, :])
            if (np.abs(np.mean(object)) < 1e-7):
                print('\nScaling data up by 10^15\n')
                object = object * 1.e15
                sigma = sigma * 1.e15
            if (secondord):
                if (num_bands > 3):
                    sigma2 = multispec2[3, i, :]
                else:
                    sigma2 = np.sqrt(multispec2[skyband, i, :])
                    if (np.abs(np.mean(object)) < 1e-7):
                        object2 = object2 * 1.e15
                        sigma2 = sigma2 * 1.e15
            nandslist = ['gemini-n', 'gemini-s', 'lco-imacs']
            if (observat in nandslist):
                skyfile = inputfile.replace('tot', 'sky')
                skyfits = fits.open(skyfile)
                sky = skyfits[0].data[2, 0, :]
            else:
                sky = multispec[skyband, i, :]
            envelope_size = 25
            mx, mn = envelope(sky, envelope_size)
            skycont = congrid(mn, (len(sky), ), minusone=True)
            test_sky = sky
            sky = sky - skycont
            if (np.abs(np.mean(sky)) < 1.e-7):
                sky = sky * 1.e15
            print(len(mskywave), len(mskydata))
            msky = scipyrebinsky(mskywave, mskydata, wave)
            xfactor = 10
            maxlag = 200
            if 'kast' in mshead.get('VERSION', ''):
                shift = xcor(msky[50:-50], sky[50:-50], xfactor, maxlag)
            else:
                shift = xcor(msky, sky, xfactor, maxlag)
            angshift = shift * wdelt
            print('wdeltf', wdelt)
            print('The x-cor shift in Angstroms is {}'.format(angshift))
            wave = wave + angshift  #check to make sure signs are right
            skyshiftdone = False
            npixsky2 = len(sky) // 2
            msky_max = np.max(msky[npixsky2 - 1:])
            sky_max = np.max(sky[npixsky2 - 1:])
            scale = sky_max / msky_max

            plt.close()
            fig = plt.figure(figsize=[8, 5])
            fig.subplots_adjust(hspace=0)
            while (not skyshiftdone):
                axarr = fig.subplots(2)

                waveplus = wave - angshift

                if not secondtime:
                    axarr[0].plot(waveplus[0:npixsky2],scale*msky[0:npixsky2], \
                                  drawstyle='steps-mid',color='k')
                    axarr[0].plot(wave[0:npixsky2],sky[0:npixsky2], \
                                  drawstyle='steps-mid',color='r')
                    axarr[1].plot(waveplus[npixsky2-1:],scale*msky[npixsky2-1:], \
                                  drawstyle='steps-mid',color='k')
                    axarr[1].plot(wave[npixsky2-1:],sky[npixsky2-1:], \
                                  drawstyle='steps-mid',color='r')
                    plt.pause(0.01)
                    print('\nBlack spectrum = master sky')
                    print(
                        'Red spectrum   = object sky shifted to match master sky'
                    )
                    print('Is this ok?')
                    answer = yesno('y')
                    if (answer == 'n'):
                        wave = wave - angshift
                        angshift = inputter(
                            'Enter desired shift in Angstroms: ', 'float',
                            False)
                        wave = wave + angshift
                    else:
                        skyshiftdone = True
                else:
                    wave = wave + angshift
                    skyshiftdone = True

            plt.close()
            # B star removal
            bstarpass = bstarstar
            bobj, bsig, bangshift=telluric_remove(bstarwave,bstarpass, bstarairmass, wave, \
                                       object, airmass, sigma, object, shift=bshift)
            # bobj, bsig, bangshift=telluric_remove(bstarwave,bstarpass, bstarairmass, wave, \
            #                            test_sky, airmass, sigma, object)
            bshift = bangshift
            if (secondord):
                bobj2, bsig2, bangshift2 =telluric_remove(bstarwave2,bstarpass2, bstarairmass2, \
                                             wave, object2, airmass, sigma2)

            print('\nRemoving redshift due to motion of Earth...')
            z = -1 * v / 2.99792458e5
            wave = wave / (1 + z)
            # rebin
            fig = plt.figure()
            axarr = fig.subplots(1, 2)
            ymin, ymax = finalscaler(bobj[0:100])
            axarr[0].plot(wave[0:100], bobj[0:100], drawstyle='steps-mid')
            axarr[0].set_xlabel('Wavelength')
            axarr[0].set_ylabel('Flux')
            #axarr[0].set_ylim((ymin,ymax))
            if (secondtime):
                axarr[0].plot([wavesave0, wavesave0], [ymin, ymax], color='r')
            plt.pause(0.01)
            ymin, ymax = finalscaler(bobj[-100:])
            axarr[1].plot(wave[-100:], bobj[-100:], drawstyle='steps-mid')
            axarr[1].set_xlabel('Wavelength')
            axarr[1].set_ylabel('Flux')
            try:
                axarr[1].set_ylim((ymin, ymax))
            except ValueError:
                bobj_median = np.nanmedian(bobj)
                axarr[1].set_ylim((bobj_median / 10., bobj_median * 10.))
            if (secondtime):
                axarr[1].plot([wavesaven, wavesaven], [ymin, ymax], color='r')

                newdelt = 0.0
            plt.pause(0.01)
            print('\nCurrent A/pix is {}'.format(wave[1] - wave[0]))
            if (secondtime):
                print('\nPrevious resolution choice: {}'.format(deltsave))
            else:
                deltsave = 0.0
            newdelt = wave[1] - wave[0]
            # while (newdelt <= 0) or (newdelt > wave[-1]):
            #     print('Rebin to how many Angstroms per pixel? ')
            #     newdelt=inputter('         <CR> selects previous choice: ','float',True,deltsave)
            #     if (newdelt <= 0) or (newdelt > wave[-1]):
            #         print('Need positive resoution and smaller than the')
            #         print('entire spectrum.  Try again')
            print('\nCurrent range: {} {}'.format(wave[0], wave[-1]))
            if (secondtime):
                print('\nPrevious selection was {} {} (marked in red on plot)'.
                      format(wavesave0, wavesaven))
                print('\n<CR> selects previous choice\n')
            else:
                wavesave0 = 0.0
                wavesaven = 0.0
                print('Enter the new wavelength range desired: ')

            waveb, waver = waveparse(wave, wavesave0, wavesaven)
            newbin = (waver - waveb) / newdelt + 1.0  #should stay the same now
            # frac,whole=np.modf(newbin)
            # if (frac > 0.000001):
            # testwave=newdelt*whole+waveb
            # print('Closest match is: {} to {}'.format(waveb,testwave))
            # print('Would you like this wavelength range?')
            # answer=yesno('y')
            # if (answer == 'y'):
            #     waver=testwave

            wave_locs = np.where((wave > waveb) & (wave < waver))

            # deltsave=newdelt
            wavesave0 = waveb
            wavesaven = waver
            waverange = str(waveb) + ' ' + str(waver)
            secondtime = True
            # nwave=np.arange(0,whole)*newdelt + waveb
            # vartmp=bsig*bsig
            # olddeltvec=wave-np.roll(wave,1)
            # olddelt=np.mean(olddeltvec)

            # nwave = wave
            # finalobj = bobj
            # finalvar = bsig**2.
            # finalsig = bsig

            #NOT TESTED!!!
            nwave = wave[wave_locs]
            print(nwave[0], nwave[-1])
            finalobj = bobj[wave_locs]
            finalvar = bsig[wave_locs]**2.
            finalsig = bsig[wave_locs]

            # finalobj=womashrebin(wave,bobj,nwave)
            # finalvar=womashrebin(wave,vartmp,nwave)
            # finalsig=np.sqrt(finalvar)*np.sqrt(olddelt/newdelt)

            #Matt's interpolation algorithm. womashrebin is an unreadable monstrosity.
            # interp_data = interpo_flux_conserving(wave, bobj, 1./vartmp, waveb, waver, dw=newdelt, testing=False)

            # interp_wave = np.arange(math.ceil(wave[0])+1., math.floor(wave[-1])-1., dtype=float, step=newdelt)
            # spectres_data = spectres(interp_wave, wave, bobj, spec_errs=bsig)

            # trim_range = (interp_data[0] > waveb) & (interp_data[0] < waver)
            # nwave = interp_data[0][trim_range]
            # finalobj = interp_data[1][trim_range]
            # finalvar = 1./interp_data[2][trim_range]
            # finalsig = np.sqrt(finalvar)

            suffixes = {}
            suffixes['ap' + str(i + 1)] = ''
            if os.path.isfile('../HOST_AP_DATA.txt'):
                with open('../HOST_AP_DATA.txt') as host_ap_data:
                    h_lines = host_ap_data.readlines()
                    for l in h_lines:
                        suffixes[l.split()[0]] = '_' + l.split()[1]

            #gonna ignore the second order stuff for now
            if (secondord):
                vartmp2 = bsig2 * bsig2
                finalobj2 = womashrebin(wave, bobj2, nwave)
                finalvar2 = womashrebin(wave, vartmp2, nwave)
                finalsig2 = np.sqrt(finalvar2) * np.sqrt(olddelt / newdelt)
            if (secondord and not seconddone):
                finalobj, finalsig, wavebeg, waveend, brscale = secondcat(
                    nwave, finalobj, finalobj2, finalsig, finalsig2,
                    secondtime, wavebeg, waveend, brscale)
            seconddone = True
            ymin, ymax = finalscaler(finalobj)
            plt.close()
            fig = plt.figure()
            plt.plot(nwave, finalobj, drawstyle='steps-mid')
            # plt.plot(spectres_data[0],spectres_data[1],drawstyle='steps-mid', color='green')
            plt.xlabel('Wavelength')
            plt.ylabel('Flux')
            plt.title(objectname)
            plt.savefig(objectname + '-' + gratcode + '_ap' + str(i + 1) +
                        suffixes['ap' + str(i + 1)] + '.png')
            plt.show()

            outputdone = False
            while (not outputdone):
                print('\nThe file is: {}'.format(inputfile))
                print('The object is: {}'.format(objectname))
                print('The DATE-OBS is: {}'.format(date))
                print('The aperture is: {}'.format(i + 1))
                print('The previous name was: {}'.format(objname))
                print('\nEnter the object name for the final fits file: ')
                # objname=inputter('(UT date and .fits will be added): ','string',False)
                objname = objectname + '-' + gratcode
                fname = objname + '-' + printdate + '_ap' + str(
                    i + 1) + suffixes['ap' + str(i + 1)] + '.fits'
                sname = objname + '-' + printdate + '_ap' + str(
                    i + 1) + suffixes['ap' + str(i + 1)] + '-sigma.fits'
                outputdone = True
                if (os.path.isfile(fname)):
                    print('{} already exists!!!!'.format(fname))
                    print('Do you wish to overwrite it? ')
                    answer = yesno('y')
                    if (answer == 'y'):
                        outputdone = True
                else:
                    outputdone = True
            # add to header
            new_mshead = mshead.copy()
            new_mshead.set('CRPIX1', 1)
            new_mshead.set('CRVAL1', nwave[0])
            new_mshead.set('CDELT1', nwave[1] - nwave[0])
            new_mshead.set('CTYPE1', 'LINEAR')
            new_mshead.set('W_RANGE', waverange)
            new_mshead.set('BSTAR_Z', bstarairmass)
            new_mshead.set('BSTARNUM', bstarnum)
            new_mshead.set('BSTAROBJ', bstarname)
            new_mshead.set('BARYVEL', v)
            new_mshead.set('SKYSHIFT', angshift)
            new_mshead.set('ATMSHIFT', bangshift)
            new_mshead.set('EXTRACT', extractcode)
            new_mshead.set('REDUCER', user)
            new_mshead.set('RED_DATE',
                           str(datetime.now()).split()[0],
                           'EPOCH OF REDUCTION')
            new_mshead.set('OBJECT', objectname)
            # if (secondord):
            #     new_mshead.set('SECOND', 'yes',  'Second order correction attempted')
            #     new_mshead.set('COMBRANGE',combrange)
            #     new_mshead.set('BSTAR_Z2',bstarairmass2)
            #     new_mshead.set('BSTARNU2', bstarnum2)
            #     new_mshead.set('BSTAROB2', bstarname2)
            #     fluxairmass2=mshead2['FLX2_Z']
            #     fluxnum2=mshead2['FLX2_NUM']
            #     fluxname2=mshead2['FLX2_OBJ']
            #     new_mshead.set('FLX2_Z',fluxairmass2)
            #     new_mshead.set('FLX2_NUM', fluxnum2)
            #     new_mshead.set('FLX2_OBJ', fluxname2)
            outdata = np.zeros((len(finalobj), 2))
            outdata[:, 0] = finalobj.copy()
            outdata[:, 1] = finalsig.copy()
            outhdu = fits.PrimaryHDU(outdata)
            hdul = fits.HDUList([outhdu])
            mshead.set('NAXIS2', 2)
            hdul[0].header = new_mshead.copy()
            hdul.writeto(fname, overwrite=True)

            spectxt = objname + '-' + printdate + '_ap' + str(
                i + 1) + suffixes['ap' + str(i + 1)] + '.flm'
            spectxt = spectxt.strip()
            np.savetxt(spectxt,
                       np.transpose([nwave,
                                     finalobj.copy(),
                                     finalsig.copy()]))

            hdul.close()

            print('Do you wish to combine with another spectrum? ')
            answer = yesno('y')
            fname_comb = None
            if (answer == 'y'):
                plt.close()
                done = False
                while (not done):
                    files = glob.glob(objname.split('-')[0] + '*.fits')
                    print(files)
                    for f in files:
                        if objname not in f and ('red' in f or 'blue' in f
                                                 ) and '_ap' + str(i + 1) in f:
                            inputfile = f
                    inputfile = input(
                        'Name of fits file to be combined? [{}]: '.format(
                            inputfile)) or inputfile
                    print(inputfile)
                    inputfile = inputfile.strip()
                    if (inputfile == ''):
                        return hop
                    if ('.fits' not in inputfile):
                        inputfile = inputfile + '.fits'
                    try:
                        fitsdata = fits.open(inputfile)
                    except OSError:
                        print('File {} cannot be opened.'.format(inputfile))
                    else:
                        done = True

                crval1 = fitsdata[0].header['CRVAL1']
                try:
                    wdelt = fitsdata[0].header['CDELT1']
                except KeyError:
                    wdelt = 0.0000001
                if (wdelt < 0.000001):
                    wdelt = fitsdata[0].header['CD1_1']
                try:
                    objectname = fitsdata[0].header['OBJECT']
                    if (not isinstance(objectname, str)):
                        objectname = inputfile
                except KeyError:
                    objectname = inputfile

                data_new = fitsdata[0].data
                wave_new = np.arange(1, len(data_new) + 1) * wdelt + crval1
                if (len(data_new.shape) == 2):
                    var_new = data_new[:, 1]
                    var_new = var_new.astype(float)
                    var_new = var_new * var_new
                    flux_new = data_new[:, 0]
                    flux_new = flux_new.astype(float)
                else:
                    flux_new = data_new.astype(float)
                    var_new = np.ones(data_new.shape)

                if 'red' in inputfile:
                    wavecomb, fluxcomb, varcomb = womcatfinal(
                        [nwave, finalobj, finalvar],
                        [wave_new, flux_new, var_new])
                    nwave = wavecomb
                    finalobj = fluxcomb
                    finalsig = np.sqrt(varcomb)
                elif 'blue' in inputfile:
                    wavecomb, fluxcomb, varcomb = womcatfinal(
                        [wave_new, flux_new, var_new],
                        [nwave, finalobj, finalvar])
                    nwave = wavecomb
                    finalobj = fluxcomb
                    finalsig = np.sqrt(varcomb)
                else:
                    print(
                        "Please include 'blue' or 'red' in filename of spectrum to combine"
                    )

                plt.clf()
                plt.plot(nwave, finalobj, drawstyle='steps-mid')
                plt.xlabel('Wavelength')
                plt.ylabel('Flux')
                plt.title(objectname)
                plt.savefig(objectname + '_combined_ap' + str(i + 1) +
                            suffixes['ap' + str(i + 1)] + '.png')

                outputdone = False
                while (not outputdone):
                    print('\nThe file is: {}'.format(inputfile))
                    print('The object is: {}'.format(objectname))
                    print('The DATE-OBS is: {}'.format(date))
                    print('The aperture is: {}'.format(i + 1))
                    print('The previous name was: {}'.format(objname))
                    print('\nEnter the object name for the final fits file: ')
                    # objname=inputter('(UT date and .fits will be added): ','string',False)
                    objname = objectname + '-combined'
                    fname_comb = objname + '-' + printdate + '_ap' + str(
                        i + 1) + suffixes['ap' + str(i + 1)] + '.fits'
                    sname_comb = objname + '-' + printdate + '_ap' + str(
                        i + 1) + suffixes['ap' + str(i + 1)] + '-sigma.fits'
                    outputdone = True
                    if (os.path.isfile(fname)):
                        print('{} already exists!!!!'.format(fname))
                        print('Do you wish to overwrite it? ')
                        answer = yesno('y')
                        if (answer == 'y'):
                            outputdone = True
                    else:
                        outputdone = True
                # add to header
                mshead_combined = new_mshead.copy()
                mshead_combined.set('CRPIX1', 1)
                mshead_combined.set('CRVAL1', nwave[0])
                mshead_combined.set('CDELT1', nwave[1] - nwave[0])
                mshead_combined.set('CTYPE1', 'LINEAR')
                mshead_combined.set('W_RANGE', waverange)
                mshead_combined.set('BSTAR_Z', bstarairmass)
                mshead_combined.set('BSTARNUM', bstarnum)
                mshead_combined.set('BSTAROBJ', bstarname)
                mshead_combined.set('BARYVEL', v)
                mshead_combined.set('SKYSHIFT', angshift)
                mshead_combined.set('ATMSHIFT', bangshift)
                mshead_combined.set('EXTRACT', extractcode)
                mshead_combined.set('REDUCER', user)
                mshead_combined.set(
                    'RED_DATE',
                    datetime.now().strftime("%Y-%M-%d %I:%M%p"),
                    'EPOCH OF REDUCTION')
                mshead_combined.set('OBJECT', objectname)
                if (secondord):  #not implemented
                    mshead_combined.set('SECOND', 'yes',
                                        'Second order correction attempted')
                    mshead_combined.set('COMBRANGE', combrange)
                    mshead_combined.set('BSTAR_Z2', bstarairmass2)
                    mshead_combined.set('BSTARNU2', bstarnum2)
                    mshead_combined.set('BSTAROB2', bstarname2)
                    fluxairmass2 = mshead2['FLX2_Z']
                    fluxnum2 = mshead2['FLX2_NUM']
                    fluxname2 = mshead2['FLX2_OBJ']
                    mshead_combined.set('FLX2_Z', fluxairmass2)
                    mshead_combined.set('FLX2_NUM', fluxnum2)
                    mshead_combined.set('FLX2_OBJ', fluxname2)
                outdata = np.zeros((len(finalobj), 2))
                outdata[:, 0] = finalobj.copy()
                outdata[:, 1] = finalsig.copy()
                outhdu = fits.PrimaryHDU(outdata)
                hdul = fits.HDUList([outhdu])
                mshead_combined.set('NAXIS2', 2)
                hdul[0].header = mshead_combined.copy()
                hdul.writeto(fname_comb, overwrite=True)
                hdul.close()
                spectxt = objname + '-' + printdate + '_ap' + str(
                    i + 1) + suffixes['ap' + str(i + 1)] + '.flm'
                spectxt = spectxt.strip()
                np.savetxt(
                    spectxt,
                    np.transpose([nwave,
                                  finalobj.copy(),
                                  finalsig.copy()]))

            is_final = input('Is this a final reduction? [y]/n: ') or 'y'
            if is_final:
                if not os.path.isdir('../../final_reductions/'):
                    os.mkdir('../../final_reductions/')
                os.system('cp ' + fname + ' ' + '../../final_reductions/' +
                          fname)
                if fname_comb:
                    os.system('cp ' + fname_comb + ' ' +
                              '../../final_reductions/' + fname_comb)
        print('final')
        print(objectlist, gratcode, secondord, gratcode2)
        plt.close()
    return
示例#27
0
def womgau(hop):
    """fit gaussian to line"""
    import numpy as np
    import logging
    import matplotlib.pyplot as plt
    from scipy.optimize import curve_fit
    from tmath.wombat.womwaverange import womwaverange
    from tmath.wombat.womget_element import womget_element
    from tmath.wombat.inputter import inputter
    from tmath.wombat.inputter_single import inputter_single
    from tmath.wombat.gauss import gauss
    from tmath.wombat.gauss_cont import gauss_cont
    from tmath.wombat.yesno import yesno
    print(' ')
    logging.info('Object is {}'.format(hop[0].obname))
    print(' ')
    print('Spectrum runs from {} to {}'.format(hop[0].wave[0],
                                               hop[0].wave[-1]))
    print(' ')
    print('This routine expects the spectrum to be in flambda units.')
    print('It also expects a linear wavelength scale.')
    print(' ')
    print('Choose general region of spectrum\n')
    nwave, nflux, mode = womwaverange(hop[0].wave, hop[0].flux, 'none')
    print('\nNow pick the exact range for the fit')
    waveint, fluxint, mode = womwaverange(nwave, nflux, mode)
    indexblue = womget_element(nwave, waveint[0])
    indexred = womget_element(nwave, waveint[-1])
    if (mode == 'w'):
        done = False
        while (not done):
            print(' ')
            wavecenter = inputter('Enter approximate center of Gaussian : ',
                                  'float', False)
            indexcenter = womget_element(waveint, wavecenter)
            if (indexcenter <= 0) or (wavecenter > waveint[-1]):
                print('Bad central wavelength, try again')
            else:
                done = True
    else:
        done = False
        while (not done):
            print('Mark the approximate center of the Gaussian')
            pickcent = plt.ginput(1, timeout=-1)
            indexcenter = womget_element(waveint, pickcent[0][0])
            print('\nApproximate center at {}'.format(waveint[indexcenter]))
            print('\nIs this OK?')
            answer = yesno('y')
            if (answer == 'y'):
                done = True
    weights = np.sqrt(hop[0].var[indexblue:indexred + 1])
    print(' ')
    continuum = inputter_single(
        'Do you want to fit gaussian with (c)ontinuum, or (n)o continuum? ',
        'cn')
    if (continuum == 'c'):
        p = [fluxint[indexcenter], waveint[indexcenter], 3.0, 1.0, waveint[0]]
        result = curve_fit(gauss_cont,
                           waveint,
                           fluxint,
                           sigma=weights,
                           p0=p,
                           absolute_sigma=True,
                           full_output=True)
    else:
        p = [fluxint[indexcenter], waveint[indexcenter], 3.0]
        result = curve_fit(gauss,
                           waveint,
                           fluxint,
                           sigma=weights,
                           p0=p,
                           absolute_sigma=True,
                           full_output=True)
    coefferr = np.sqrt(np.diag(result[1]))
    coeff = result[0]
    # make 'finer-grained' version of fit, 0.2A/pix for calculations
    wavecalc = np.arange(2 * 5 * 50 * abs(
        coeff[2])) * 0.2 + coeff[1] - 0.2 * 5 * 50 * abs(coeff[2])
    calccenter = womget_element(wavecalc, coeff[1])
    if (continuum == 'c'):
        fluxcalc = gauss_cont(wavecalc, *coeff)
        fluxcont = wavecalc * coeff[3] + coeff[4]
        fluxgaussian = fluxcalc - fluxcont
        linecont = fluxcont[calccenter]
    else:
        fluxcalc = gauss(wavecalc, *coeff)

    deltafit = wavecalc[1] - wavecalc[0]
    calcindexblue = womget_element(wavecalc, waveint[0])
    calcindexred = womget_element(wavecalc, waveint[-1])
    sumfluxcalc = np.sum(fluxcalc[calcindexblue:calcindexred + 1] * deltafit)
    sumallfluxcalc = np.sum(fluxcalc * deltafit)
    chi = (result[2]['fvec']**2).sum()
    redchi = chi / (len(waveint) - len(coeff))
    if (continuum == 'c'):
        sumfluxgaussian = np.sum(fluxgaussian[calcindexblue:calcindexred + 1] *
                                 deltafit)
        sumallfluxgaussian = np.sum(fluxgaussian * deltafit)
        sumfluxcont = np.sum(fluxcont[calcindexblue:calcindexred + 1] *
                             deltafit)
        sumallfluxcont = np.sum(fluxcont * deltafit)
        # propagate uncertainty (from old version) not sure this is correct
        height_pct = coefferr[0] / coeff[0]
        sigma_pct = coefferr[2] / coeff[2]
        flux_pct = np.sqrt(height_pct**2 + sigma_pct**2)
        sumfluxgaussiansig = sumfluxgaussian * flux_pct
        sumallfluxgaussiansig = sumallfluxgaussian * flux_pct
    plt.cla()
    plt.plot(nwave, nflux, drawstyle='steps-mid', color='k')
    plt.ylabel('Flux')
    plt.xlabel('Wavelength')
    xmin, xmax = plt.xlim()
    ymin, ymax = plt.ylim()
    plt.plot(wavecalc, fluxcalc, drawstyle='steps-mid', color='b')
    if (continuum == 'c'):
        plt.plot(wavecalc, fluxgaussian, drawstyle='steps-mid', color='r')
        plt.plot(wavecalc, fluxcont, drawstyle='steps-mid', color='g')
    plt.plot([waveint[0], waveint[0]], [ymin, ymax], color='k', linestyle='--')
    plt.plot([waveint[-1], waveint[-1]], [ymin, ymax],
             color='k',
             linestyle='--')
    plt.xlim([xmin, xmax])
    plt.ylim([ymin, ymax])
    logging.info('For object {} Gaussian fit'.format(hop[0].obname))
    if (continuum == 'c'):
        print(
            '\nData = Black, Fit = Blue, Continuum = Green, Fit-Continuum = Red\n'
        )
    else:
        print('\nData = Black, Fit = Blue\n')
    logging.info('Height      {:16.8f}+/-{:16.8f}'.format(
        coeff[0], coefferr[0]))
    logging.info('Center      {:16.8f}+/-{:16.8f}'.format(
        coeff[1], coefferr[1]))
    logging.info('Sigma       {:16.8f}+/-{:16.8f}'.format(
        coeff[2], coefferr[2]))
    if (continuum == 'c'):
        logging.info('Slope       {:16.8f}+/-{:16.8f}'.format(
            coeff[3], coefferr[3]))
        logging.info('Y-intercept {:16.8f}+/-{:16.8f}'.format(
            coeff[4], coefferr[4]))
        logging.info('FWHM        {:16.8f}+/-{:16.8f}'.format(
            2.35482 * np.abs(coeff[2]), 2.35482 * coefferr[2]))
        logging.info(
            'Flux between dotted lines (Gaussian): {:16.8f}+/-{:16.8f}'.format(
                sumfluxgaussian, sumfluxgaussiansig))
        logging.info('EW between dotted lines (Gaussian): {:16.8f}'.format(
            sumfluxgaussian / linecont))
        logging.info('Flux for full (Gaussian): {:16.8f}+/-{:16.8f}'.format(
            sumallfluxgaussian, sumallfluxgaussiansig))
        logging.info('EW for full (Gaussian): {:16.8f}'.format(
            sumallfluxgaussian / linecont))
        logging.info(
            'Continuum flux at line center: {:16.8f}'.format(linecont))
    logging.info('Chi^2: {}'.format(chi))
    logging.info('Reduced chi^2: {}'.format(redchi))
    logging.info('All fluxes might need to be scaled by 1e-15')
    print(' ')
    return hop
def telluric_remove(bstarwave,
                    bstar,
                    bairmass,
                    wave,
                    object,
                    airmass,
                    variance,
                    spectrum,
                    shift=None):
    import numpy as np
    import pdb
    import matplotlib.pyplot as plt
    from tmath.wombat.inputter import inputter
    from tmath.wombat.yesno import yesno
    from tmath.wombat.womscipyrebin import womscipyrebin
    from tmath.wombat.womget_element import womget_element
    from tmath.pydux.xcor import xcor
    from tmath.pydux.finalscaler import finalscaler
    bstartmp = womscipyrebin(bstarwave, bstar, wave)
    #    plt.cla()
    #    plt.plot(bstarwave,bstartmp)
    #    plt.pause(0.01)
    #    answer=yesno('y')
    print('\nThe ratio of airmasses (object/B-star) is {}'.format(airmass /
                                                                  bairmass))
    if (airmass / bairmass > 3.0) or (airmass / bairmass < 0.33):
        print('\nWARNING: OBJECT AND B-STAR HAVE WILDLY DIFFERENT')
        print('AIRMASSES: ATMOSPHERIC BAND DIVISION MAY BE LOUSY\n')

    wmin = wave[0]
    wmax = wave[-1]
    npix = len(object)
    wdelt = wave[1] - wave[0]
    print('wdelt', wdelt)
    lag = np.zeros(3)
    lagflag = [False] * 3
    xfactor = 10
    maxlag = 200

    if not shift:
        print('\nCross-correlating object with B-star spectrum\n')
        fig = plt.figure()
        axarr = fig.subplots(2, 1)
        if (wmin < 6200) and (wmax > 6400) and (wmax < 6900):
            indblue = womget_element(wave, 6200)
            indred = womget_element(wave, 6400)
            lag[0] = xcor(object[indblue:indred + 1],
                          bstartmp[indblue:indred + 1], xfactor, maxlag)
            lagflag[0] = True
            print('The shift at the 6250A band is {} angstroms'.format(lag[0] *
                                                                       wdelt))
        if (wmin < 6800) and (wmax > 6500):
            indblue = womget_element(wave, 6800)
            indred = womget_element(wave, 6950)
            scale = 1. / np.max(object[indblue:indred + 1])
            obb = scale * object[indblue:indred + 1]
            bb = bstartmp[indblue:indred + 1]
            lag[1] = xcor(obb, bb, xfactor, maxlag)
            lagflag[1] = True
            print('The shift at the B band is {} angstroms'.format(lag[1] *
                                                                   wdelt))

            plt.cla()
            # ymin,ymax=finalscaler(object)
            # plt.plot(wave,object,drawstyle='steps-mid',color='r')
            # plt.plot(wave,newobject,drawstyle='steps-mid',color='k')
            ymin, ymax = finalscaler(bstartmp[indblue:indred + 1])
            axarr[0].plot(wave[indblue:indred + 1],
                          scale * object[indblue:indred + 1],
                          drawstyle='steps-mid',
                          color='r')
            axarr[0].plot(wave[indblue:indred + 1],
                          bstartmp[indblue:indred + 1],
                          drawstyle='steps-mid',
                          color='k')
            axarr[0].plot(wave[indblue:indred + 1] + lag[1] * wdelt,
                          bstartmp[indblue:indred + 1],
                          drawstyle='steps-mid',
                          color='g')
            plt.pause(0.01)

        if (wmin < 7500) and (wmax > 8000):

            indblue = womget_element(wave, 7500)
            indred = womget_element(wave, 8000)
            scale = 1. / np.max(object[indblue:indred + 1])
            lag[2] = xcor(scale * object[indblue:indred + 1],
                          bstartmp[indblue:indred + 1], xfactor, maxlag)
            print('The shift at the A band is {} angstroms'.format(lag[2] *
                                                                   wdelt))
            lagflag[2] = True
            # ymin,ymax=finalscaler(object)
            # plt.plot(wave,object,drawstyle='steps-mid',color='r')
            # plt.plot(wave,newobject,drawstyle='steps-mid',color='k')
            ymin, ymax = finalscaler(bstartmp[indblue:indred + 1])
            axarr[1].plot(wave[indblue:indred + 1],
                          scale * object[indblue:indred + 1],
                          drawstyle='steps-mid',
                          color='r')
            axarr[1].plot(wave[indblue:indred + 1],
                          bstartmp[indblue:indred + 1],
                          drawstyle='steps-mid',
                          color='k')
            axarr[1].plot(wave[indblue:indred + 1] + lag[2] * wdelt,
                          bstartmp[indblue:indred + 1],
                          drawstyle='steps-mid',
                          color='g')
            plt.pause(0.01)
            check = inputter('Check plot [enter when done]: ', 'string', False)

        if (sum(lagflag) > 0):
            avglag = np.sum(lag) / sum(lagflag)
            angshift = avglag * wdelt
            print('The mean shift is {} Angstroms'.format(angshift))
        else:
            angshift = 0.0
        plt.close()
    else:
        angshift = shift
    fig = plt.figure(figsize=[9, 5])
    telluric_done = False
    bstartmpcopy = bstartmp.copy()
    while (not telluric_done):
        print('Applying a shift of {} Angstroms'.format(angshift))
        bstartmp = bstartmpcopy.copy()
        tmp = womscipyrebin(wave + angshift, bstartmp, wave)
        bstartmp = tmp.copy()
        bstartmp = bstartmp**((airmass / bairmass)**0.55)
        # newobject=object/bstartmp
        newobject = spectrum / bstartmp
        bvar = variance / bstartmp
        print('\nPlotting before and after atmospheric band correction\n')
        plt.cla()
        # ymin,ymax=finalscaler(object)
        # plt.plot(wave,object,drawstyle='steps-mid',color='r')
        # plt.plot(wave,newobject,drawstyle='steps-mid',color='k')
        ymin, ymax = finalscaler(spectrum)
        plt.plot(wave, spectrum, drawstyle='steps-mid', color='r')
        plt.plot(wave, newobject, drawstyle='steps-mid', color='k')
        plt.ylim([ymin, ymax])
        plt.pause(0.01)

        if not shift:
            print('Is this OK?')
            answer = yesno('y')
            if (answer == 'n'):
                angshift = inputter('Enter B-star shift in Angstroms: ',
                                    'float', False)
            else:
                telluric_done = True
        else:
            check = inputter('Check plot [enter when done]: ', 'string', False)
            telluric_done = True
    plt.close()
    return newobject, bvar, angshift
def mkfluxstar(fluxfile, gratcode):
    import pdb
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.widgets import Cursor
    from astropy.io import fits
    from tmath.wombat.get_screen_size import get_screen_size
    from tmath.wombat.getmswave import getmswave
    from tmath.wombat.inputter_single import inputter_single
    from tmath.wombat.inputter import inputter
    from tmath.wombat.womscipyrebin import womscipyrebin
    from tmath.pydux.obs_extinction import obs_extinction
    from tmath.pydux.wave_telluric import wave_telluric
    from tmath.pydux.fitspl import fitspl
    from tmath.pydux.finalscaler import finalscaler
    from tmath.pydux.abcalc import abcalc
    from tmath.pydux.pacheck import pacheck

    screen_width, screen_height = get_screen_size()
    plt.ion()
    screenpos = '+{}+{}'.format(int(screen_width * 0.2),
                                int(screen_height * 0.05))
    fig = plt.figure()
    fig.canvas.manager.window.wm_geometry(screenpos)
    fig.canvas.set_window_title('Flux Star')
    fig.set_size_inches(18, 12)
    # turns off key stroke interaction
    fig.canvas.mpl_disconnect(fig.canvas.manager.key_press_handler_id)

    # this should bring the window to the top, but it doesn't
    wm = plt.get_current_fig_manager()
    #fig.canvas.manager.window.attributes('-topmost', 1)
    blah = wm.window.attributes('-topmost', 1)

    #plt.pause(0.2)
    #fig.canvas.manager.window.attributes('-topmost', 0)
    blah = wm.window.attributes('-topmost', 0)

    #extinction terms from Allen, 3rd edition
    extwave= [2400.,2600.,2800.,3000.,3200.,3400.,3600.,3800., \
              4000.,4500.,5000.,5500.,6000.,6500.,7000.,8000., \
              9000.,10000.,12000.,14000.]
    extvals=[68.0,89.0,36.0,4.5,1.30,0.84,0.68,0.55,0.46,0.31, \
             0.23,0.195,0.170,0.126,0.092,0.062,0.048,0.039, \
             0.028,0.021]

    fitsfile = fits.open(fluxfile)
    rawdata = fitsfile[0].data
    head = fitsfile[0].header
    num_apertures = rawdata.shape[1]

    wavearr = np.zeros((rawdata.shape[2], rawdata.shape[1]))
    objectname = head['OBJECT']
    airmass = float(head['AIRMASS'])
    exptime = float(head['EXPTIME'])
    head = pacheck(head)
    if (exptime < 1):
        exptime = 1.
    observat = head['OBSERVAT'].strip().lower()
    sitefactor = obs_extinction(observat)
    for i in range(0, num_apertures):
        wavearr[:, i] = getmswave(head, i)
    if (wavearr[-1, 0] < 3000):
        print('************************************************')
        print('Spectrum not wavelength calibrated---bailing out')
        print('************************************************')
        sys.exit(1)
    ap_choice = -1

    if (num_apertures != 1):
        axarr = fig.subplots(num_apertures, sharex=True)
        fig.subplots_adjust(hspace=0)
        for i in range(0, num_apertures):
            x = wavearr[:, i]
            y = rawdata[0, i, :]
            axarr[i].clear()

            plt.pause(0.01)
            axarr[i].plot(x, y, drawstyle='steps-mid')
            axarr[i].set_ylabel('Aperture {}'.format(i))
            plt.pause(0.01)
        while (ap_choice < 0) or (ap_choice > num_apertures - 1):
            ap_choice = inputter(
                'Which aperture do you want to use for the flux star? ', 'int',
                False)
        fig.clf()
    else:
        ap_choice = 0

    ymin, ymax = finalscaler(rawdata[0, ap_choice, :])
    fig.clf()
    x1 = wavearr[:, ap_choice]
    y1 = rawdata[1, ap_choice, :]
    y0 = rawdata[0, ap_choice, :]
    plt.plot(x1, y1, drawstyle='steps-mid', color='r')
    plt.plot(x1, y0, drawstyle='steps-mid', color='k')
    plt.pause(0.01)
    plt.ylim([ymin, ymax])
    plt.pause(0.01)
    print('\nPlotting optimal as black, normal as red')
    extract = inputter_single(
        'Do you want to use (n)ormal or (o)ptimal extraction? ', 'no')
    if (extract == 'o'):
        star = rawdata[0, ap_choice, :]
    else:
        star = rawdata[1, ap_choice, :]
    # fix IRAF weirdness where data can go negative in dispcor interpolation
    star[np.where(star < 0)] = 0.01
    wave = wavearr[:, ap_choice]
    extinction = womscipyrebin(extwave, extvals, wave)
    extfactor = np.exp(extinction * sitefactor * airmass)
    star = star * extfactor
    abcurve = abcalc(wave, objectname)
    wdata = 10.0**(0.4 * abcurve)
    fstar = star * wdata / exptime
    print('Now fit the continuum manually\n')
    plt.clf()
    ax = fig.add_subplot(111)
    cursor = Cursor(ax, useblit=True, color='k', linewidth=1)
    airlimit = 1.5
    splineresult = fitspl(wave, np.log10(fstar), (airmass > airlimit), fig)
    splineresult = 10**(splineresult)
    plt.cla()
    plt.plot(wave, splineresult, drawstyle='steps-mid')
    plt.pause(0.01)
    delkeylist=['WAT0_001', 'WAT1_001', 'WAT2_001', 'WAT0_002', \
                'WAT1_002', 'WAT2_002', 'WAT3_001', 'WAT2_003', \
                'CTYPE1', 'CTYPE2', 'CTYPE3', 'CD1_1', 'CD2_2', \
                'CD3_3', 'LTM1_1', 'LTM2_2', 'LTM3_3', 'WCSDIM']
    for k in delkeylist:
        try:
            head.remove(k)
        except KeyError:
            pass
    head.set('CRPIX1', 1)
    head.set('CRVAL1', wave[0])
    head.set('CDELT1', wave[1] - wave[0])
    head.set('CTYPE1', 'LINEAR')
    head.set('FLUXFILE', fluxfile)
    outfile = 'fluxstar' + gratcode + '.fits'
    print('Writing data to {}'.format(outfile))
    outhdu = fits.PrimaryHDU(splineresult)
    hdul = fits.HDUList([outhdu])
    hdul[0].header = head.copy()
    hdul.writeto(outfile, overwrite=True)
    print('mkfluxstar')
    print(fluxfile, gratcode)
    return
示例#30
0
def abcalc(wave, objectname):

    #  creates ab curve to flux standard stars
    #  TM 11/21/98

    #  EVALUATES AB(NU) MAGNITUDES FOR THE FLUX STAR SPECIFIED BY IDNO.
    #
    #  IDNO = 1 FOR HD 19445
    #         2 FOR HD 84937
    #         3 FOR BD +26 2606
    #         4 FOR BD +17 4708
    #         5 FOR HD 140283
    #         6 FOR GD-248
    #         7 FOR G158-100
    #         8 FOR LTT 1788
    #         9 FOR LTT 377
    #        10 FOR HZ 4
    #        11 FOR HZ 7
    #        12 FOR ROSS 627
    #        13 FOR LDS 235B
    #        14 FOR G99-37
    #        15 FOR LB 227
    #        16 FOR L745-46A
    #        17 FOR FEIGE 24
    #        18 FOR G60-54
    #        19 FOR G24-9
    #        20 FOR BD+28 4211
    #        21 FOR G191B2B
    #        22 FOR G157-34
    #        23 FOR G138-31
    #        24 FOR HZ 44
    #        25 FOR LTT 9491
    #        26 FOR FEIGE 100
    #        27 FOR FEIGE 34
    #        28 FOR LTT 1020
    #        29 FOR LTT 9239
    #	 30 FOR HILTNER 600 (APPROXIMATE)
    #	 31 FOR BD+25 3941 (APPROXIMATE)
    #        32 FOR BD+33 2642 (APPROXIMATE)
    #        33 FOR FEIGE 56 (APPROXIMATE)
    #        34 FOR G193-74
    #        35 FOR eg145
    #        36 for FEIGE 25
    #        37 for PG0823+546
    #        38 for HD 217086
    #        39 for HZ 14
    #        40 for FEIGE 66
    #
    #        NUMBERS 25--29 WERE ADDED ON 2 AUGUST 1987# NUMBER 8 WAS
    #        MODIFIED SLIGHTLY (UP TO 0.11 MAG) NEAR THE H-K BREAK.
    #
    #	 NUMBERS 30 AND 31 WERE ADDED ON 24 JANUARY 1988# NUMBERS
    #	 ARE ONLY APPROXIMATE NEAR THE BALMER LIMIT, LONGWARD OF
    #	 8100 A, AND SHORTWARD OF 3300 A. DITTO FOR NUMBER 32,
    #        WHI#H WAS ADDED ON 2 MAY 1988. DITTO FOR NUMBER 33, WHICH
    #        WAS ADDED ON 25 AUGUST 1991.
    #	THERE ARE 41 WAVELENGTHS.

    #  INTERPOLATION IN THIS TABLE SHOULD APPROXIMATE THE MONOCHROMATIC
    #  CONTINUUM FLUX DISTRIBUTION OF THE MCSP STANDARD STARS.
    #  SYSTEMATIC ERRORS AS LARGE AS 5% MAY OCCUR NEAR THE CONVERGENCE
    #  OF THE BALMER SERIES, WHERE THE CONTINUUM IS NOT WELL DEFINED.
    #  NO ATTEMPT IS MADE TO FOLLOW THE WINGS OF THE BALMER LINES,
    #  A PROCEDURE WHICH SEEMS DANGEROUS AT BEST.
    #
    #	NOTE THAT ALEX FILIPPENKO HAS MODIFIED ALL AB MAGNITUDES SO
    #	THAT ABSORPTION LINES ARE INTERPOLATED OVER SMOOTHLY. THIS
    #	MEANS THAT MCSP STANDARDS AND OTHERS CANNOT BE USED IN THE
    #	MANNER USED BEFORE (THAT IS, SUMMING ALL COUNTS IN 40-ANG
    #	BANDPASSES AND COMPARING WITH TABULATED VALUES).
    #
    import numpy as np
    from tmath.wombat.inputter import inputter
    from tmath.wombat.womscipyrebin import womscipyrebin

    idstar = 0
    while (idstar < 1) or (idstar > 56):
        print('The object is {}'.format(objectname))
        print(' ')
        print('  WHICH STANDARD STAR IS THIS ?')
        print('  ORIGINAL MCSP FLUX STANDARDS (AB79 SCALE): ')
        print('  (1) HD 19445       (2) HD 84937        (3) BD+262606')
        print('  (4) BD+17 4708       (5) HD 140283 (SOMEWHAT OBSOLETE)')
        print('  OTHERS (AB69, AB79, STONE, OR BALDWIN/STONE SCALE): ')
        print('  (6) GD-248 (AB79)            (7) G158-100 (AB79)')
        print('  (8) LTT 1788 (B/S)           (9) LTT 377 (B/S)')
        print('  (10) HZ 4 (~AB79)            (11) HZ 7 (~AB79)')
        print('  (12) ROSS 627 (~AB79)        (13) LDS 235B (~AB79)')
        print('  (14) G99-37 (~AB79)          (15) LB 227 (~AB79)')
        print('  (16) L745-46A (~AB79)        (17) FEIGE 24 (~AB79)')
        print('  (18) G60-54 (~AB79)          (19) G24-9 (AB79)')
        print('  (20) BD+28 4211 (STONE)      (21) G191B2B (~AB79)')
        print('  (22) G157-34 (AB79)          (23) G138-31 (AB79)')
        print('  (24) HZ 44 (~AB79)           (25) LTT 9491 (B/S)')
        print('  (26) FEIGE 110 (STONE)       (27) FEIGE 34 (STONE)')
        print('  (28) LTT 1020 (B/S)          (29) LTT 9239 (B/S)')
        print('  (30) HILTNER 600 (STONE)     (31) BD+25 3941 (STONE)')
        print('  (32) BD+33 2642 (STONE)      (33) FEIGE 56 (STONE)')
        print('  (34) G193-74 (AB79)          (35) EG145 (OKE,74)  ')
        print('  (36) FEIGE 25 (STONE)        (37) PG0823+546 ')
        print('  (38) HD 217086               (39) HZ 14 ')
        print('  (40) FEIGE 66                (41) Feige 67 (Groot special) ')
        print('  (42) LTT 377                 (43) LTT 2415 ')
        print('  (44) LTT 4364                (45) Feige 15')
        print('  (46) Hiltner 102 (lousy)     (47) LTT 3864 ')
        print('  (48) LTT 3218                (49) CYG OB2  ')
        print('  (50) VMa 2                   (51) GD 71 ')
        print('  (52) HZ 43                   (53) LTT 7379')
        print('  (54) LTT 7987                (55) GD 153 ')
        print('  (56) CD32D9927 ')
        idstar = inputter('Star number? ', 'int', False)

    #  All numbers from lolita's abcalc.f, we trust that they are ok

    waveab = [3080.0, 3160.0, 3240.0, 3320.0, 3400.0, 3480.0, 3560.0, \
              3640.0, 3680.0, 3720.0, 3760.0, 3780.0, 3820.0, 3860.0, \
              4020.0, 4200.0, 4400.0, 4560.0, 4760.0, 5000.0, 5120.0, \
              5240.0, 5400.0, 5560.0, 5760.0, 6020.0, 6420.0, 6780.0, \
              7100.0, 7460.0, 7780.0, 8100.0, 8380.0, 8780.0, 9300.0, \
              9700.0, 9940.0,10260.0,10820.0,11140.0,12000.0]
    ab = np.zeros((41, 57))
    ab[:, 1] = [9.476, 9.391, 9.310, 9.232, 9.168, 9.103, 9.039, \
                8.979, 8.945, 8.919, 8.849, 8.814, 8.762, 8.695, \
                8.483, 8.385, 8.293, 8.235, 8.180, 8.118, 8.081, \
                8.048, 8.014, 7.982, 7.948, 7.908, 7.862, 7.837, \
                7.812, 7.790, 7.776, 7.760, 7.759, 7.755, 7.752, \
                7.752, 7.752, 7.752, 7.760, 7.760, 7.763]
    ab[:, 2] = [9.677, 9.610, 9.542, 9.480, 9.422, 9.370, 9.310, \
                9.269, 9.243, 9.205, 9.099, 9.018, 8.926, 8.850, \
                8.650, 8.548, 8.496, 8.448, 8.400, 8.351, 8.332, \
                8.315, 8.290, 8.266, 8.237, 8.202, 8.174, 8.150, \
                8.133, 8.125, 8.123, 8.112, 8.111, 8.115, 8.119, \
                8.123, 8.130, 8.137, 8.150, 8.160, 8.180]
    ab[:, 3] = [11.155, 11.072, 10.998, 10.935, 10.866, 10.806, \
                10.750, 10.698, 10.670, 10.651, 10.540, 10.480, \
                10.400, 10.320, 10.120, 10.021, 9.955, 9.908, 9.843, \
                9.768, 9.741, 9.719, 9.693, 9.660, 9.630, 9.594, \
                9.552, 9.527, 9.502, 9.485, 9.474, 9.463, 9.457, \
                9.457, 9.458, 9.458, 9.461, 9.462, 9.468, 9.473, \
                9.488]
    ab[:, 4] = [10.955, 10.872, 10.798, 10.718, 10.663, 10.601, \
                10.536, 10.487, 10.452, 10.426, 10.307, 10.268, \
                10.190, 10.110, 9.880, 9.765, 9.690, 9.637, 9.573, \
                9.520, 9.491, 9.465, 9.434, 9.405, 9.374, 9.337, \
                9.294, 9.262, 9.233, 9.216, 9.211, 9.200, 9.194, \
                9.194, 9.195, 9.195, 9.198, 9.199, 9.205, 9.210, \
                9.225]
    ab[:, 5] = [9.050, 8.820, 8.630, 8.520, 8.430, 8.360, 8.300, \
                8.230, 8.200, 8.160, 8.050, 7.990, 7.915, 7.870, \
                7.680, 7.560, 7.470, 7.420, 7.340, 7.260, 7.230, \
                7.210, 7.170, 7.120, 7.080, 7.040, 6.975, 6.930, \
                6.890, 6.860, 6.840, 6.830, 6.810, 6.800, 6.810, \
                6.840, 6.860, 6.880, 6.890, 6.900, 6.910]
    ab[:, 6] = [15.295, 15.262, 15.229, 15.200, 15.178, 15.163, \
                15.150, 15.138, 15.133, 15.127, 15.122, 15.119, \
                15.113, 15.108, 15.090, 15.071, 15.058, 15.052, \
                15.050, 15.056, 15.063, 15.070, 15.081, 15.093, \
                15.110, 15.133, 15.175, 15.212, 15.245, 15.283, \
                15.318, 15.353, 15.384, 15.427, 15.484, 15.528, \
                15.554, 15.592, 15.652, 15.688, 15.775]
    ab[:, 7] = [16.725, 16.665, 16.591, 16.502, 16.400, 16.292, \
                16.183, 16.082, 16.034, 15.986, 15.938, 15.914, \
                15.868, 15.824, 15.651, 15.490, 15.346, 15.246, \
                15.139, 15.027, 14.979, 14.932, 14.872, 14.824, \
                14.768, 14.696, 14.609, 14.537, 14.485, 14.430, \
                14.393, 14.361, 14.338, 14.310, 14.281, 14.261, \
                14.248, 14.233, 14.209, 14.199, 14.178]
    ab[:, 8] = [14.785, 14.637, 14.492, 14.348, 14.214, 14.113, \
                14.025, 13.946, 13.911, 13.880, 13.840, 13.818, \
                13.780, 13.737, 13.626, 13.524, 13.440, 13.380, \
                13.310, 13.237, 13.195, 13.166, 13.136, 13.100, \
                13.062, 13.020, 12.976, 12.949, 12.925, 12.898, \
                12.874, 12.850, 12.833, 12.815, 12.809, 12.808, \
                12.804, 12.800, 12.794, 12.790, 12.781]
    ab[:, 9] = [13.180, 13.030, 12.890, 12.660, 12.610, 12.580, \
                12.530, 12.460, 12.375, 12.300, 12.230, 12.200, \
                12.130, 12.020, 11.775, 11.630, 11.570, 11.500, \
                11.390, 11.360, 11.325, 11.285, 11.235, 11.190, \
                11.170, 11.150, 11.085, 11.060, 11.040, 11.035, \
                11.020, 10.985, 10.980, 10.970, 10.965, 10.960, \
                10.960, 10.960, 10.960, 10.960, 10.960]
    ab[:, 10] = [14.660, 14.670, 14.680, 14.690, 14.710, 14.730, \
                 14.750, 14.780, 14.800, 14.820, 14.800, 14.770, \
                 14.770, 14.720, 14.470, 14.360, 14.310, 14.330, \
                 14.380, 14.430, 14.450, 14.480, 14.520, 14.550, \
                 14.590, 14.640, 14.740, 14.840, 14.900, 15.000, \
                 15.080, 15.170, 15.170, 15.170, 15.170, 15.170, \
                 15.170, 15.170, 15.170, 15.170, 15.170]
    ab[:, 11] = [13.910, 13.930, 13.940, 13.960, 13.990, 14.010, \
                 14.035, 14.060, 14.080, 14.100, 14.090, 14.080, \
                 14.080, 14.060, 13.880, 13.850, 13.900, 13.970, \
                 14.040, 14.100, 14.135, 14.170, 14.210, 14.280, \
                 14.340, 14.400, 14.530, 14.630, 14.710, 14.800, \
                 14.880, 14.970, 14.970, 14.970, 14.970, 14.970, \
                 14.970, 14.970, 14.970, 14.970, 14.970]
    ab[:, 12] = [15.080, 14.970, 14.880, 14.825, 14.760, 14.710, \
                 14.652, 14.640, 14.620, 14.600, 14.570, 14.550, \
                 14.540, 14.530, 14.440, 14.350, 14.280, 14.250, \
                 14.220, 14.170, 14.138, 14.120, 14.100, 14.070, \
                 14.045, 14.020, 14.010, 14.005, 13.995, 13.993, \
                 13.991, 13.990, 13.990, 13.990, 13.990, 13.990, \
                 13.990, 13.990, 13.990, 13.990, 13.990]
    ab[:, 13] = [15.410, 15.400, 15.390, 15.390, 15.380, 15.380, \
                 15.390, 15.410, 15.420, 15.430, 15.430, 15.420, \
                 15.410, 15.400, 15.390, 15.415, 15.440, 15.460, \
                 15.500, 15.540, 15.560, 15.570, 15.600, 15.610, \
                 15.630, 15.680, 15.760, 15.850, 15.910, 15.980, \
                 16.060, 16.140, 16.210, 16.310, 16.390, 16.540, \
                 16.620, 16.620, 16.620, 16.620, 16.620]
    ab[:, 14] = [15.795, 15.710, 15.580, 15.490, 15.390, 15.310, \
                 15.220, 15.185, 15.162, 15.140, 15.110, 15.080, \
                 15.050, 15.030, 14.900, 14.810, 14.710, 14.670, \
                 14.610, 14.520, 14.488, 14.460, 14.440, 14.400, \
                 14.360, 14.320, 14.300, 14.290, 14.285, 14.285, \
                 14.290, 14.300, 14.310, 14.320, 14.330, 14.360, \
                 14.380, 14.380, 14.380, 14.380, 14.380]
    ab[:, 15] = [15.270, 15.295, 15.310, 15.320, 15.360, 15.400, \
                 15.415, 15.460, 15.483, 15.490, 15.500, 15.515, \
                 15.530, 15.530, 15.200, 15.050, 15.000, 15.020, \
                 15.090, 15.154, 15.177, 15.215, 15.260, 15.300, \
                 15.355, 15.410, 15.530, 15.630, 15.700, 15.807, \
                 15.910, 16.010, 16.010, 16.010, 16.010, 16.010, \
                 16.010, 16.010, 16.010, 16.010, 16.010]
    ab[:, 16] = [13.820, 13.730, 13.600, 13.520, 13.420, 13.350, \
                 13.300, 13.280, 13.270, 13.265, 13.250, 13.230, \
                 13.210, 13.190, 13.130, 13.070, 13.010, 13.005, \
                 12.985, 12.940, 12.922, 12.920, 12.895, 12.880, \
                 12.860, 12.843, 12.850, 12.870, 12.880, 12.900, \
                 12.920, 12.940, 12.960, 12.990, 13.020, 13.060, \
                 13.090, 13.090, 13.090, 13.090, 13.090]
    ab[:, 17] = [11.540, 11.565, 11.580, 11.640, 11.680, 11.730, \
                 11.760, 11.830, 11.870, 11.890, 11.920, 11.930, \
                 11.950, 11.970, 11.990, 12.010, 12.076, 12.135, \
                 12.210, 12.290, 12.345, 12.338, 12.380, 12.393, \
                 12.415, 12.450, 12.435, 12.414, 12.375, 12.330, \
                 12.310, 12.280, 12.255, 12.210, 12.160, 12.115, \
                 12.100, 12.070, 12.070, 12.070, 12.070]
    ab[:, 18] = [17.749, 17.659, 17.562, 17.460, 17.359, 17.250, \
                 17.146, 17.049, 17.006, 16.945, 16.902, 16.881, \
                 16.828, 16.785, 16.610, 16.436, 16.285, 16.173, \
                 16.068, 15.960, 15.900, 15.860, 15.800, 15.740, \
                 15.680, 15.620, 15.550, 15.508, 15.480, 15.460, \
                 15.450, 15.440, 15.435, 15.430, 15.427, 15.423, \
                 15.425, 15.430, 15.435, 15.440, 15.456]
    ab[:, 19] = [16.780, 16.740, 16.692, 16.634, 16.570, 16.502, \
                 16.431, 16.363, 16.330, 16.300, 16.271, 16.256, \
                 16.229, 16.202, 16.105, 16.020, 15.940, 15.887, \
                 15.829, 15.776, 15.757, 15.740, 15.718, 15.700, \
                 15.681, 15.659, 15.632, 15.615, 15.604, 15.594, \
                 15.586, 15.582, 15.581, 15.586, 15.598, 15.609, \
                 15.617, 15.628, 15.649, 15.662, 15.695]
    ab[:, 20] = [9.500, 9.510, 9.530, 9.560, 9.600, 9.649, 9.695, \
                 9.736, 9.758, 9.772, 9.791, 9.800, 9.820, 9.833, \
                 9.920, 10.011, 10.107, 10.186, 10.261, 10.363, \
                 10.406, 10.449, 10.518, 10.582, 10.660, 10.730, \
                 10.850, 10.937, 11.023, 11.110, 11.165, 11.216, \
                 11.268, 11.310, 11.360, 11.400, 11.427, 11.450, \
                 11.485, 11.500, 11.530]
    ab[:, 21] = [10.750, 10.790, 10.839, 10.883, 10.925, 10.966, \
                 11.011, 11.052, 11.069, 11.089, 11.106, 11.111, \
                 11.129, 11.143, 11.206, 11.283, 11.369, 11.429, \
                 11.508, 11.600, 11.642, 11.686, 11.750, 11.815, \
                 11.888, 11.980, 12.114, 12.225, 12.312, 12.408, \
                 12.488, 12.562, 12.634, 12.726, 12.842, 12.915, \
                 12.955, 12.998, 13.061, 13.090, 13.148]
    ab[:, 22] = [15.889, 15.853, 15.808, 15.766, 15.728, 15.698, \
                 15.670, 15.643, 15.630, 15.618, 15.605, 15.599, \
                 15.586, 15.573, 15.524, 15.478, 15.437, 15.415, \
                 15.393, 15.372, 15.365, 15.358, 15.351, 15.349, \
                 15.350, 15.354, 15.364, 15.373, 15.383, 15.397, \
                 15.413, 15.434, 15.455, 15.487, 15.530, 15.566, \
                 15.587, 15.617, 15.673, 15.705, 15.785]
    ab[:, 23] = [17.252, 17.190, 17.124, 17.060, 17.000, 16.950, \
                 16.891, 16.841, 16.817, 16.793, 16.769, 16.757, \
                 16.732, 16.706, 16.609, 16.515, 16.423, 16.359, \
                 16.288, 16.220, 16.194, 16.170, 16.141, 16.119, \
                 16.099, 16.078, 16.055, 16.041, 16.031, 16.024, \
                 16.023, 16.025, 16.028, 16.033, 16.041, 16.047, \
                 16.051, 16.058, 16.070, 16.078, 16.095]
    ab[:, 24] = [10.737, 10.773, 10.804, 10.830, 10.868, 10.897, \
                 10.930, 10.959, 10.978, 10.989, 11.002, 11.010, \
                 11.029, 11.045, 11.107, 11.163, 11.233, 11.290, \
                 11.359, 11.442, 11.478, 11.516, 11.566, 11.616, \
                 11.680, 11.773, 11.905, 12.023, 12.120, 12.235, \
                 12.321, 12.400, 12.468, 12.540, 12.637, 12.709, \
                 12.760, 12.819, 12.909, 12.954, 13.061]
    ab[:, 25] = [14.156, 14.137, 14.118, 14.099, 14.080, 14.062, \
                 14.045, 14.030, 14.023, 14.017, 14.012, 14.009, \
                 14.005, 14.002, 13.996, 13.997, 14.003, 14.011, \
                 14.026, 14.053, 14.066, 14.079, 14.096, 14.113, \
                 14.139, 14.173, 14.212, 14.261, 14.321, 14.380, \
                 14.412, 14.436, 14.450, 14.462, 14.467, 14.469, \
                 14.471, 14.475, 14.481, 14.485, 14.496]
    ab[:, 26] = [10.883, 10.922, 10.960, 10.998, 11.031, 11.065, \
                 11.102, 11.138, 11.154, 11.171, 11.187, 11.195, \
                 11.210, 11.226, 11.283, 11.350, 11.438, 11.505, \
                 11.588, 11.681, 11.723, 11.764, 11.822, 11.879, \
                 11.937, 12.014, 12.146, 12.236, 12.321, 12.415, \
                 12.487, 12.539, 12.585, 12.650, 12.735, 12.800, \
                 12.839, 12.892, 12.983, 13.035, 13.176]
    ab[:, 27] = [10.126, 10.165, 10.204, 10.242, 10.283, 10.324, \
                 10.367, 10.409, 10.428, 10.446, 10.463, 10.471, \
                 10.487, 10.502, 10.568, 10.653, 10.750, 10.824, \
                 10.920, 11.024, 11.070, 11.116, 11.179, 11.241, \
                 11.311, 11.406, 11.551, 11.653, 11.721, 11.796, \
                 11.852, 11.892, 11.920, 11.960, 12.011, 12.051, \
                 12.075, 12.106, 12.162, 12.194, 12.279]
    ab[:, 28] = [13.481, 13.272, 13.063, 12.872, 12.730, 12.617, \
                 12.528, 12.461, 12.430, 12.399, 12.365, 12.348, \
                 12.313, 12.276, 12.131, 11.991, 11.858, 11.775, \
                 11.700, 11.626, 11.594, 11.564, 11.522, 11.477, \
                 11.428, 11.379, 11.304, 11.260, 11.233, 11.192, \
                 11.158, 11.133, 11.113, 11.082, 11.061, 11.056, \
                 11.056, 11.057, 11.058, 11.058, 11.059]
    ab[:, 29] = [14.338, 14.094, 13.850, 13.625, 13.455, 13.330, \
                 13.225, 13.134, 13.093, 13.053, 13.016, 12.997, \
                 12.962, 12.926, 12.772, 12.605, 12.460, 12.364, \
                 12.264, 12.179, 12.140, 12.101, 12.051, 12.008, \
                 11.964, 11.913, 11.839, 11.784, 11.740, 11.696, \
                 11.675, 11.646, 11.631, 11.599, 11.566, 11.553, \
                 11.549, 11.548, 11.547, 11.546, 11.544]
    ab[:, 30] = [11.010, 10.970, 10.930, 10.850, 10.830, 10.810, \
                 10.800, 10.790, 10.780, 10.750, 10.720, 10.680, \
                 10.580, 10.500, 10.470, 10.460, 10.460, 10.450, \
                 10.450, 10.440, 10.430, 10.430, 10.420, 10.420, \
                 10.430, 10.440, 10.480, 10.500, 10.520, 10.550, \
                 10.570, 10.590, 10.610, 10.640, 10.670, 10.700, \
                 10.720, 10.740, 10.780, 10.800, 10.860]
    ab[:, 31] = [12.190, 12.110, 12.060, 11.950, 11.850, 11.790, \
                 11.740, 11.660, 11.630, 11.580, 11.500, 11.450, \
                 11.350, 11.260, 11.160, 11.070, 10.990, 10.870, \
                 10.790, 10.690, 10.590, 10.500, 10.410, 10.360, \
                 10.320, 10.280, 10.210, 10.130, 10.070, 10.020, \
                 9.980, 9.960, 9.970, 9.980, 9.990, 10.000, 10.010, \
                 10.020, 10.030, 10.040, 10.050]
    ab[:, 32] = [10.780, 10.730, 10.670, 10.628, 10.641, 10.663, \
                 10.688, 10.700, 10.687, 10.656, 10.585, 10.546, \
                 10.483, 10.434, 10.456, 10.516, 10.573, 10.617, \
                 10.672, 10.746, 10.777, 10.802, 10.840, 10.882, \
                 10.930, 10.991, 11.080, 11.132, 11.169, 11.219, \
                 11.249, 11.312, 11.415, 11.511, 11.623, 11.730, \
                 11.799, 11.890, 12.028, 12.098, 12.283]
    ab[:, 33] = [11.510, 11.450, 11.332, 11.290, 11.270, 11.270, \
                 11.288, 11.290, 11.290, 11.250, 11.125, 11.020, \
                 10.900, 10.830, 10.700, 10.764, 10.820, 10.845, \
                 10.902, 10.980, 11.010, 11.035, 11.070, 11.110, \
                 11.144, 11.205, 11.307, 11.375, 11.430, 11.518, \
                 11.593, 11.648, 11.690, 11.750, 11.890, 11.960, \
                 12.015, 12.090, 12.210, 12.280, 12.420]
    ab[:, 34] = [16.350, 16.300, 16.263, 16.195, 16.160, 16.100, \
                 16.070, 16.025, 16.010, 15.980, 15.960, 15.958, \
                 15.930, 15.890, 15.858, 15.807, 15.737, 15.732, \
                 15.702, 15.670, 15.648, 15.635, 15.624, 15.613, \
                 15.600, 15.587, 15.582, 15.583, 15.589, 15.602, \
                 15.619, 15.633, 15.649, 15.682, 15.752, 15.825, \
                 15.860, 15.940, 16.020, 16.080, 16.250]
    ab[:, 35] = [14.50, 14.50, 14.41, 14.45, 14.42, 14.45, 14.44, \
                 14.49, 14.46, 14.49, 14.47, 14.53, 14.60, 14.58, \
                 14.55, 14.49, 14.53, 14.53, 14.56, 14.66, 14.67, \
                 14.63, 14.68, 14.70, 14.77, 14.83, 14.86, 14.97, \
                 14.99, 15.07, 15.12, 15.16, 15.20, 15.27, 15.35, \
                 15.44, 15.38, 15.36, 15.35, 15.34, 15.30]
    ab[:, 36] = [12.590, 12.590, 12.598, 12.556, 12.540, 12.494, \
                 12.515, 12.509, 12.497, 12.427, 12.270, 12.192, \
                 12.035, 11.878, 11.752, 11.768, 11.815, 11.830, \
                 11.883, 11.950, 11.959, 11.968, 11.989, 12.010, \
                 12.024, 12.080, 12.189, 12.209, 12.240, 12.288, \
                 12.340, 12.361, 12.400, 12.400, 12.400, 12.400, \
                 12.400, 12.400, 12.400, 12.400, 12.400]
    ab[:, 37] = [13.5600, 13.5600, 13.4400, 13.4600, 13.5800, 13.5760, \
                 13.5480, 13.6440, 13.6780, 13.6900, 13.7000, 13.7200, \
                 13.7480, 13.7680, 13.8420, 13.9500, 14.0000, 14.1100, \
                 14.1540, 14.2500, 14.3040, 14.3260, 14.3900, 14.3660, \
                 14.4340, 14.5520, 14.6627, 14.7020, 14.7900, 14.8200, \
                 14.8780, 14.9218, 14.9320, 14.8800, 14.9777, 15.0173, \
                 15.0647, 15.1137, 15.1137, 15.1137, 15.1137]
    ab[:, 38] = [8.95000, 8.95000, 8.87000, 8.73600, 8.65000, 8.62000, \
                 8.52800, 8.49600, 8.47800, 8.46200, 8.43400, 8.40200, \
                 8.35400, 8.32600, 8.22000, 8.15000, 8.08000, 7.96400, \
                 7.88800, 7.79000, 7.70800, 7.61600, 7.58000, 7.48000, \
                 7.45400, 7.39600, 7.34200, 7.23422, 7.20000, 7.15864, \
                 7.11746, 7.09000, 7.09000, 7.09000, 7.09000, 7.09000, \
                 7.09000, 7.09000, 7.09000, 7.09000, 7.09000]
    ab[:, 39] = [13.3800, 13.3800, 13.3912, 13.3576, 13.3700, 13.3724, \
                 13.3819, 13.3912, 13.3959, 13.4007, 13.4054, 13.4077, \
                 13.4123, 13.4170, 13.4360, 13.4600, 13.5064, 13.5620, \
                 13.6630, 13.7901, 13.8228, 13.8848, 13.9700, 14.0092, \
                 14.1128, 14.1708, 14.3481, 14.4030, 14.5000, 14.5856, \
                 14.5978, 14.6716, 14.6716, 14.6716, 14.6716, 14.6716, \
                 14.6716, 14.6716, 14.6716, 14.6716, 14.6716]
    ab[:,40]= [9.71000, 9.71000, 9.69960, 9.71940, 9.75000, 9.78720, \
               9.80216, 9.81480, 9.82124, 9.82851, 9.83550, 9.83918, \
               9.84723, 9.85676, 9.89451, 9.96000, 10.0500, 10.1132, \
               10.2140, 10.3200, 10.3714, 10.4180, 10.4700, 10.5340, \
               10.6116, 10.7332, 10.9026, 10.9693, 11.0300, 11.1424, \
               11.2164, 11.2752, 11.3143, 11.2954, 11.4150, 11.5300, \
               11.6312, 11.7700, 11.7700, 11.7700, 11.7700]
    ab[:, 41] = [10.7060, 10.7060, 10.7070, 10.8412, 10.8751, 10.9346, \
                 10.9988, 11.0508, 11.0876, 11.1117, 11.1198, 11.1309, \
                 11.1536, 11.1253, 11.1920, 11.2856, 11.3744, 11.4628, \
                 11.5659, 11.6423, 11.6924, 11.7352, 11.8133, 11.8565, \
                 11.9284, 12.0111, 12.1394, 12.2520, 12.3412, 12.4391, \
                 12.5198, 12.5946, 12.6563, 12.7585, 12.8850, 12.8850, \
                 12.8850, 12.8850, 12.8850, 12.8850, 12.8850]
    ab[:, 42] = [12.6650, 12.6650, 12.6650, 12.6689, 12.6060, 12.5745, \
                 12.4804, 12.3900, 12.3252, 12.2909, 12.2230, 12.1593, \
                 12.0765, 12.0277, 11.7515, 11.6150, 11.5000, 11.4408, \
                 11.3709, 11.3090, 11.2841, 11.2483, 11.2300, 11.1848, \
                 11.1531, 11.1270, 11.0906, 11.0527, 11.0500, 11.0405, \
                 11.0333, 11.0334, 11.0415, 11.0607, 11.0660, 11.0623, \
                 11.0590, 11.0628, 11.1040, 11.1040, 11.1040]
    ab[:, 43] = [13.4480, 13.4480, 13.4480, 13.4304, 13.3760, 13.3201, \
                 13.2367, 13.1485, 13.1038, 13.0542, 12.9668, 12.9094, \
                 12.8061, 12.7308, 12.5630, 12.4730, 12.4300, 12.3768, \
                 12.3296, 12.2690, 12.2535, 12.2343, 12.2000, 12.1752, \
                 12.1656, 12.1231, 12.0979, 12.0637, 12.0610, 12.0447, \
                 12.0358, 12.0350, 12.0426, 12.0589, 12.0848, 12.0996, \
                 12.1069, 12.1220, 12.1220, 12.1220, 12.1220]
    ab[:, 44] = [11.9290, 11.9290, 11.9290, 11.9046, 11.8710, 11.8479, \
                 11.8000, 11.7477, 11.7263, 11.7090, 11.6945, 11.6854, \
                 11.6673, 11.6534, 11.6223, 11.5960, 11.5740, 11.5590, \
                 11.5371, 11.5154, 11.5068, 11.5009, 11.5000, 11.5009, \
                 11.5019, 11.5053, 11.5110, 11.5168, 11.5520, 11.5775, \
                 11.5920, 11.6202, 11.6513, 11.6907, 11.7590, 11.8070, \
                 11.8338, 11.8690, 11.8690, 11.8690, 11.8690]
    ab[:, 45] = [11.7000, 11.7000, 11.6640, 11.5452, 11.5300, 11.5080, \
                 11.4916, 11.3878, 10.6773, 10.2642, 10.2610, 10.2566, \
                 10.2443, 10.2311, 10.1995, 10.2156, 10.2294, 10.2487, \
                 10.2753, 10.3380, 10.3431, 10.3561, 10.3827, 10.4104, \
                 10.4257, 10.4725, 10.5476, 10.5986, 10.6300, 10.6840, \
                 10.7300, 10.7407, 10.7600, 10.7600, 10.7600, 10.7600, \
                 10.7600, 10.7600, 10.7600, 10.7600, 10.7600]
    ab[:, 46] = [11.9800, 11.9800, 11.9368, 11.7878, 11.7300, 11.6804, \
                 11.6335, 11.5881, 11.5662, 11.5266, 11.4671, 11.4369, \
                 11.3756, 11.3132, 11.2430, 11.1481, 11.0673, 10.9546, \
                 10.8776, 10.7300, 10.6385, 10.5474, 10.4362, 10.3487, \
                 10.2950, 10.2300, 10.1340, 10.0134, 9.93000, 9.87329, \
                 9.81000, 9.73858, 9.72000, 9.72000, 9.72000, 9.72000, \
                 9.72000, 9.72000, 9.72000, 9.72000, 9.72000]
    ab[:, 47] = [13.7300, 13.7300, 13.6836, 13.5524, 13.3700, 13.3659, \
                 13.2409, 13.0914, 13.0160, 12.9800, 12.9800, 12.9800, \
                 12.9312, 12.8542, 12.6721, 12.5692, 12.4777, 12.4015, \
                 12.3132, 12.2700, 12.2428, 12.1974, 12.1997, 12.1187, \
                 12.0558, 12.0370, 11.9921, 11.9808, 11.9500, 11.9355, \
                 11.9100, 11.8901, 11.8895, 11.8679, 11.8612, 11.8664, \
                 11.8605, 11.8813, 11.9400, 11.9400, 11.9400]
    ab[:, 48] = [12.4400, 12.4400, 12.3899, 12.3234, 12.3017, 12.2882, \
                 12.2779, 12.2677, 12.2625, 12.2733, 12.2800, 12.2691, \
                 12.1489, 11.9884, 11.9632, 11.8777, 11.8386, 11.8197, \
                 11.8198, 11.8300, 11.8369, 11.8437, 11.8516, 11.8599, \
                 11.8679, 11.8826, 11.9407, 11.9594, 11.9600, 12.0066, \
                 12.0400, 12.0421, 12.1004, 12.1041, 12.1510, 12.2075, \
                 12.2522, 12.3002, 12.3000, 12.3000, 12.3000]
    ab[:, 49] = [15.1000, 15.1000, 15.0400, 14.9527, 14.8300, 14.5632, \
                 14.3972, 14.2112, 14.1330, 14.0266, 13.9064, 13.8616, \
                 13.7702, 13.6812, 13.4022, 13.0700, 12.7400, 12.3942, \
                 12.1244, 11.7000, 11.4582, 11.2224, 11.0100, 10.6924, \
                 10.4476, 10.1932, 9.86280, 9.46970, 9.21000, 9.01880, \
                 8.80220, 8.55000, 8.55000, 8.55000, 8.55000, 8.55000, \
                 8.55000, 8.55000, 8.55000, 8.55000, 8.55000]
    ab[:, 50] = [14.1000, 14.1000, 14.1000, 13.9600, 13.7600, 13.5200, \
                 13.4500, 13.3600, 13.2671, 13.2056, 13.1505, 13.1267, \
                 13.0874, 13.0555, 12.9277, 12.8200, 12.6900, 12.5800, \
                 12.5000, 12.4500, 12.4100, 12.4200, 12.4100, 12.3600, \
                 12.3556, 12.3556, 12.3100, 12.3000, 12.2756, 12.2987, \
                 12.3100, 12.2544, 12.2514, 12.3034, 12.2867, 12.2867, \
                 12.3830, 12.3622, 12.3500, 12.3500, 12.3500]
    ab[:,51] = [12.194600, 12.228300, 12.270300, 12.321600, 12.354300, \
                12.393000, 12.426700, 12.465400, 12.479000, 12.496700, \
                12.515500, 12.523100, 12.534000, 12.538500, 12.523600, \
                12.551700, 12.626000, 12.682800, 12.769200, 12.860300, \
                12.903400, 12.945100, 12.996200, 13.052800, 13.126000, \
                13.209800, 13.338300, 13.440400, 13.530800, 13.625200, \
                13.706700, 13.789400, 13.856400, 13.955600, 14.046900, \
                14.128700, 14.173900, 14.244800, 14.352100, 14.404500, \
                14.556200]
    ab[:,52]= [11.890830, 11.953902, 12.001304, 12.038769, 12.068400, \
               12.117474, 12.158472, 12.193123, 12.204728, 12.247052, \
               12.256253, 12.264238, 12.288051, 12.299415, 12.346685, \
               12.400056, 12.476015, 12.550985, 12.628268, 12.718414, \
               12.767287, 12.800667, 12.874192, 12.927598, 13.002908, \
               13.089129, 13.226055, 13.322492, 13.418968, 13.513610, \
               13.603105, 13.685889, 13.728714, 13.841738, 13.964003, \
               14.030111, 14.105518, 14.132800, 14.132800, 14.132800, \
               14.132800]
    ab[:,53]=[ 11.850000, 11.850000, 11.850000, 11.862280, 11.753000, \
               11.710168, 11.583240, 11.455560, 11.391720, 11.327880, \
               11.264040, 11.232120, 11.168280, 11.104440, 10.878012, \
               10.764100, 10.590400, 10.528520, 10.427080, 10.354000, \
               10.322270, 10.293700, 10.238000, 10.182120, 10.128600, \
               10.090520, 10.032000, 9.9762198, 9.9617100, 9.9360398, \
               9.9185802, 9.9072905, 9.9031467, 9.9140937, 9.9183197, \
               9.9221601, 9.9244636, 9.9169998, 9.9169998, 9.9169998, \
               9.9169998]
    ab[:,54]=[12.373000, 12.373000, 12.373000, 12.356440, 12.367000, \
              12.397760, 12.395280, 12.386800, 12.403720, 12.419600, \
              12.422360, 12.421640, 12.412320, 12.403216, 12.223200, \
              11.962500, 11.955000, 11.989480, 12.050820, 12.113800, \
              12.140126, 12.165320, 12.207000, 12.247120, 12.309800, \
              12.370320, 12.459800, 12.549230, 12.609700, 12.681920, \
              12.752000, 12.815400, 12.880920, 12.958500, 13.082100, \
              13.161000, 13.220040, 13.175000, 13.175000, 13.175000, \
              13.175000]
    ab[:,55] = [12.431100, 12.467100, 12.510300, 12.547300, 12.601100, \
                12.643000, 12.672900, 12.715400, 12.725200, 12.746000, \
                12.767500, 12.777500, 12.793400, 12.797200, 12.814100, \
                12.861100, 12.933300, 12.994100, 13.078300, 13.172600, \
                13.212700, 13.258900, 13.314200, 13.377200, 13.450300, \
                13.528800, 13.662500, 13.764600, 13.859700, 13.955800, \
                14.044400, 14.125700, 14.184500, 14.283600, 14.377200, \
                14.483600, 14.542900, 14.592500, 14.699500, 14.761600, \
                14.911200]
    ab[:,56]=[12.024000, 12.024000, 12.024000, 12.010360, 11.966999, \
              11.948019, 11.845119, 11.752359, 11.703140, 11.617559, \
              11.453240, 11.356260, 11.181759, 11.091120, 10.767380, \
              10.643000, 10.570000, 10.488140, 10.471140, 10.456500, \
              10.454224, 10.448364, 10.446000, 10.416080, 10.418639, \
              10.420500, 10.441330, 10.444580, 10.465000, 10.494888, \
              10.510241, 10.525400, 10.539100, 10.558599, 10.585599, \
              10.609200, 10.623360, 10.631999, 10.631999, 10.631999, \
              10.631999]

    # use scipy interp here as the very non-linear wavelength scale
    # precludes the use of womashrebin --- this is going finer anyway
    abcurve = womscipyrebin(waveab, ab[:, idstar], wave)
    return abcurve