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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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?')
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
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
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