def calc_elemvar_table(savename,_mywindows=False,_no_indiv_windows=False): if _mywindows: import window # Restore the file with the synthetic spectra with all variations if os.path.exists(savename): with open(savename,'rb') as savefile: baseline= pickle.load(savefile) elem_synspec= pickle.load(savefile) else: raise IOError("File %s with synthetic spectra does not exists; compute this first with apogee/test/test_windows.py" % savename) # Compute the whole table elems= ['C','N','O','Na','Mg','Al','Si','S','K','Ca','Ti','V','Mn','Fe', 'Ni'] table= [] # Loop through synthetic spectra varying one element for elem in elems: col= [] # Now look at the windows for each element for elemc in elems: if not _no_indiv_windows: si, ei= apwindow.waveregions(elemc,asIndex=True,pad=0,dr='13') if _mywindows: elemWeights= window.read(elemc,dr='13') else: elemWeights= apwindow.read(elemc,dr='13') elemWeights/= numpy.nansum(elemWeights) # Start with total col.append(numpy.sqrt(numpy.nansum((elemWeights\ *(elem_synspec[elem][1]-elem_synspec[elem][0])**2.))/numpy.nansum(elemWeights))) if not _no_indiv_windows: for s,e in zip(si,ei): col.append(numpy.sqrt(numpy.nansum((elemWeights\ *(elem_synspec[elem][1]-elem_synspec[elem][0])**2.)[s:e])/numpy.nansum(elemWeights[s:e]))) table.append(col) return table
def read(elem,apStarWavegrid=True,dr=None): """ NAME: read PURPOSE: read the window weights for a given element, modified to only return 'good' windows INPUT: elem - element apStarWavegrid= (True) if True, output the window onto the apStar wavelength grid, otherwise just give the ASPCAP version (blue+green+red directly concatenated) dr= read the window corresponding to this data release OUTPUT: Array with window weights HISTORY: 2015-01-25 - Written - Bovy (IAS) 2015-09-02 - Modified for only returning 'good' windows - Bovy (UofT) """ out= apwindow.read(elem,apStarWavegrid=True,dr=dr) out[bad(elem)]= 0. if not apStarWavegrid: return toAspcapGrid(out) else: return out
def fit_func(elem, name, spectra, spectra_errs, T, dat_type, run_number, location, sigma_val=None): ###Fitting function """Return fit residuals from quadratic fit, spectral errors for desired element, fluxes for desired element, an appropriately-sized array of effective temperatures, the quadratic fitting parameters, the residuals, errors, temperatures, and fluxes with NaNs removed, and the normalized elemental weights. Functions: Reads in the DR14 windows. Obtains the indices of pixels of the absorption lines and saves the flux value and uncertainty for each star in these pixels. Performs the quadratic fit on each pixel using weight_lsq() and computes the residuals using residuals(). Obtains the flux values, uncertainties, fits, residuals, and temperatures with NaNs removed. Writes the residuals and fit parameters to .hdf5 files. Parameters ---------- elem : str Element name (i.e. 'AL') name : str Name of desired cluster (i.e. 'NGC 2682') spectra : tuple Array of floats representing the spectra of the desired cluster spectra_errs : tuple Array of floats representing the spectral uncertainties of the desired cluster T : tuple Array of floats representing the effective temperature of each star in the cluster dat_type : str Indicates whether the data being examined is the data or a simulation run_number : int Number of the run by which to label files location : str If running locally, set to 'personal'. If running on the server, set to 'server'. sigma_val : float, optional Indicates the value of sigma being used for the simulation in question, if applicable (default is None) Returns ------- elem_res : tuple Array of floats representing the fit residuals, with original positioning of points maintained final_err : tuple Array of floats representing the spectral uncertainties from the lines of the desired element, with original positioning of points maintained final_points : tuple Array of floats representing the fluxes from the lines of the desired element, with original positioning of points maintained temp_array : tuple Array of floats representing the effective temperature of each star in the cluster, with a row for each pixel of the desired element elem_a : tuple Array of floats representing the fitting parameters for the quadratic terms in the fits for each pixel of the desired element elem_b : tuple Array of floats representing the fitting parameters for the linear terms in the fits for each pixel of the desired element elem_c : tuple Array of floats representing the fitting parameters for the constant terms in the fits for each pixel of the desired element nanless_res : tuple Array of floats representing the fit residuals, with NaNs removed nanless_T : tuple Array of floats representing the effective temperature of each star in the cluster, with a row for each pixel of the desired element, with NaNs removed nanless_points : tuple Array of floats representing the fluxes from the lines of the desired element, with NaNs removed normed_weights : tuple Array of floats representing the weight of each elemental window, normalized to 1 """ change_dr('12') ###Switch data-release to 12 #Find the DR14 windows from the DR12 windows dr12_elem_windows = window.read( elem) ###Read in the DR12 windows for the element in question change_dr('14') ###Switch back to DR14 dr14_elem_windows_12 = np.concatenate( (dr12_elem_windows[246:3274], dr12_elem_windows[3585:6080], dr12_elem_windows[6344:8335] )) ###Fit the dr12 windows to dr14 ("hacked" dr14 windows) normalized_dr14_elem_windows_12 = ( dr14_elem_windows_12 - np.nanmin(dr14_elem_windows_12)) / ( np.nanmax(dr14_elem_windows_12) - np.nanmin(dr14_elem_windows_12) ) ###Normalize the hacked dr14 windows to 1 #Get the indices of the lines ind_12 = np.argwhere( normalized_dr14_elem_windows_12 > 0 ) ###Get the indices of all of the pixels of the absorption lines of the element in question ind_12 = ind_12.flatten( ) ###Get rid of the extra dimension produced by np.argwhere #Get the fluxes and errors from spectra len_spectra = len(spectra) ###Number of stars elem_points_12 = np.zeros( (len(ind_12), len_spectra) ) ###Array for values of the points in the spectra that are at the indices of the elemental lines in DR12 elem_err_12 = np.zeros( (len(ind_12), len_spectra) ) ###Array for values of the errors in the spectra that are at the indices of the elemental lines in DR12 for i in range(0, len(ind_12)): ###Iterate through the DR12 elemental indices for j in range(0, len_spectra): ###Iterate through the stars elem_points_12[i][j] = spectra[j][ind_12[ i]] ###Get the values of the points in the spectra at these indices in DR12 elem_err_12[i][j] = spectra_errs[j][ind_12[ i]] #APOGEE measured errors ###Get the values of the errors in the spectra at these indices in DR12 #Use only pixels with more than 5 points final_points_12 = [] ###Empty list for the final DR12 points final_err_12 = [] ###Empty list for the final DR12 errors final_inds_12 = [] ###Empty list for the final DR12 elemental line indices for i in range( len(elem_points_12)): ###Iterate through the DR12 flux points if np.count_nonzero( ~np.isnan(elem_points_12[i]) ) >= 5: ###If the number of points in each pixel that are not NaNs is greater than or equal to 5 final_points_12.append(elem_points_12[i]) ###Append those points final_err_12.append(elem_err_12[i]) ###Append those errors final_inds_12.append(ind_12[i]) ###Append those indices final_points_12 = np.array(final_points_12) ###Make into array final_err_12 = np.array(final_err_12) ###Make into array final_inds_12 = np.array(final_inds_12) ###Make into array if len( final_inds_12 ) == 0: ###If no indices are left (i.e. if there are less than 5 points in every pixel) print('Warning: less than 5 points for every pixel, skipping ', elem) ###Skip and don't finish this element else: ###If there are enough points left dr12_weights = normalized_dr14_elem_windows_12[ final_inds_12] ###Get all of the weights of the elemental pixels for DR12 sorted_dr12_weights = np.sort( dr12_weights) ###Sort these weights from smallest to largest #Get windows if location == 'personal': ###If running on Mac window_file = pd.read_hdf( '/Users/chloecheng/Personal/dr14_windows.hdf5', 'window_df') ###Get file I made for DR14 windows elif location == 'server': ###If running on the server window_file = pd.read_hdf( '/geir_data/scr/ccheng/AST425/Personal/dr14_windows.hdf5', 'window_df') ###Get file I made for DR14 windows dr14_elem_windows_14 = window_file[ elem].values ###Get the DR14 windows for the element in question normalized_dr14_elem_windows_14 = ( dr14_elem_windows_14 - np.min(dr14_elem_windows_14)) / ( np.max(dr14_elem_windows_14) - np.min(dr14_elem_windows_14) ) ###Normalize these windows to 1 #Get the indices of the lines if elem == 'C' or elem == 'N' or elem == 'FE': ###If we're looking at one of the elements with order ~1000 pixels ind = np.argwhere( normalized_dr14_elem_windows_14 > np.min( sorted_dr12_weights[int(len(sorted_dr12_weights) * 0.7):]) ) ###Get rid of the smallest 70% of the DR12 pixels else: ###For all of the other elements ind = np.argwhere( normalized_dr14_elem_windows_14 > 0) ###Get all of the pixels ind = ind.flatten( ) ###Get rid of the extra dimension from argwhere (try to streamline this) #Get the fluxes and errors from spectra #Limits of DR12 detectors dr12_d1_left = 322 ###Left limit of detector 1 dr12_d1_right = 3242 ###Right limit of detector 1 dr12_d2_left = 3648 ###Left limit of detector 2 dr12_d2_right = 6048 ###Right limit of detector 2 dr12_d3_left = 6412 ###Left limit of detector 3 dr12_d3_right = 8306 ###Right limit of detector 3 elem_points = np.zeros( (len(ind), len_spectra) ) ###Make an empty array to hold the values of the spectra at the elemental indices elem_err = np.zeros( (len(ind), len_spectra) ) ###Make an empty array to hold the values of the spectral errors at the elemental indices for i in range(0, len(ind)): ###Iterate through the elemental indices for j in range( 0, len_spectra): ###Iterate through the number of stars ###If the indices are outside of the bounds of the DR12 detectors (these bounds should be right) if ind[i] < dr12_d1_left or ( dr12_d1_right < ind[i] < dr12_d2_left) or ( dr12_d2_right < ind[i] < dr12_d3_left) or ind[i] > dr12_d3_right: elem_points[i][ j] = np.nan ###Set the point to NaN and ignore elem_err[i][j] = np.nan ###Set the error to NaN and ignore else: ###If the indices are within the bounds of the DR12 detectors elem_points[i][j] = spectra[j][ ind[i]] ###Get the corresponding point in the spectra elem_err[i][j] = spectra_errs[j][ind[ i]] #APOGEE measured errors ###Get the corresponding point in the spectral errors #Use only pixels with more than 5 points final_points = [ ] ###Make an array for the final set of spectral points final_err = [ ] ###Make an array for the final set of spectral error points final_inds = [ ] ###Make an array for the final set of elemental indices for i in range(len( elem_points)): ###Iterate through the points we just obtained if np.count_nonzero( ~np.isnan(elem_points[i]) ) >= 5: ###If the number of non-NaNs in the pixel is greater than or equal to 5 final_points.append(elem_points[i]) ###Append the points final_err.append(elem_err[i]) ###Append the errors final_inds.append(ind[i]) ###Append the indices final_points = np.array(final_points) ###Make into array final_err = np.array(final_err) ###Make into array final_inds = np.array(final_inds) ###Make into array if len(final_points) == 0: ###If all pixels have less than 5 points print('Warning: less than 5 points for every pixel, skipping ', elem) ###Skip the element and end here else: ###If there are some pixels remaining #Create an appropriately-sized array of temperatures to mask as well temp_array = np.full( (final_points.shape), T ) ###Create an array of the temperatures that is the same size as the spectral points, but each row is the same set of temperatures for i in range( 0, len(final_points)): ###Iterate through the spectral points for j in range(0, len_spectra): ###Iterate through the stars if np.isnan(final_points[i][j]): ###If the point is a NaN temp_array[i][ j] = np.nan ###Mask the corresponding point in the temperature array #Do fits with non-nan numbers nanless_inds = np.isfinite( final_points) ###Get the indices of the non-NaN points fits = [] ###Create an empty list for the fit parameters for i in range( len(final_points)): ###Iterate through the spectral points fits.append( weight_lsq(final_points[i][nanless_inds[i]], temp_array[i][nanless_inds[i]], final_err[i][nanless_inds[i]]) ) ###Fit using weight_lsq function and all points that are not NaNs for i in range(len(fits)): ###Iterate through the fits fits[i] = np.array( fits[i]) ###Make each sub-list into an array fits = np.array(fits) ###Make the whole list into an array ###Check the order of these as well - I think it should be fine if you just change the order in weight_lsq bc still return a, b, c in the order 0, 1, 2 elem_a = fits[:, 0] ###Get the a-parameter elem_b = fits[:, 1] ###Get the b-parameter elem_c = fits[:, 2] ###Get the c-parameter elem_fits = np.zeros_like( final_points) ###Create an array to save the actual fits for i in range(0, len(final_points)): ###Iterate through the points elem_fits[i] = elem_a[i] * temp_array[i]**2 + elem_b[ i] * temp_array[i] + elem_c[i] ###Fit quadratically #Calculate residuals elem_res = residuals(final_points, elem_fits) ###Calculate the fit residuals #Remove nans from fits, residuals, errors, and temperatures for plotting and cumulative distribution #calculation purposes nanless_fits = [] ###Create an empty list for the nanless fits nanless_res = [ ] ###Create an empty list for the nanless fit residuals nanless_err = [] ###Create an empty list for the nanless errors nanless_T = [ ] ###Create an empty list for the nanless temperatures nanless_points = [ ] ###Create an empty list for the nanless spectral points for i in range( len(final_points)): ###Iterate through the spectral points nanless_fits.append( elem_fits[i][nanless_inds[i]]) ###Append the nanless fits nanless_res.append(elem_res[i][ nanless_inds[i]]) ###Append the nanless residuals nanless_err.append(final_err[i][ nanless_inds[i]]) ###Append the nanless errors nanless_T.append(temp_array[i][ nanless_inds[i]]) ###Append the nanless temperatures nanless_points.append(final_points[i][ nanless_inds[i]]) ###Append the nanless points for i in range( len(final_points)): ###Turn all sub lists into arrays nanless_fits[i] = np.array(nanless_fits[i]) nanless_res[i] = np.array(nanless_res[i]) nanless_err[i] = np.array(nanless_err[i]) nanless_T[i] = np.array(nanless_T[i]) nanless_points[i] = np.array(nanless_points[i]) nanless_fits = np.array( nanless_fits) ###Turn all lists into arrays nanless_res = np.array(nanless_res) nanless_err = np.array(nanless_err) nanless_T = np.array(nanless_T) nanless_points = np.array(nanless_points) #Get the weights for later weights = normalized_dr14_elem_windows_14[ final_inds] ###Get the weights fo the DR14 lines that we're using normed_weights = weights / np.sum( weights) ###Normalize the weights #File-saving #If we are looking at the data timestr = time.strftime("%Y%m%d_%H%M%S") ###date_time string name_string = str(name).replace(' ', '') ###cluster name, remove space pid = str(os.getpid()) ###PID string if sigma_val == None: ###IF we are looking at the data if location == 'personal': ###If running on Mac path_dat = '/Users/chloecheng/Personal/run_files/' + name_string + '/' + name_string + '_' + str( elem) + '_' + 'fit_res' + '_' + str( dat_type) + '_' + timestr + '_' + pid + '_' + str( run_number) + '.hdf5' ###Use this path elif location == 'server': ###If running on server path_dat = '/geir_data/scr/ccheng/AST425/Personal/run_files/' + name_string + '/' + name_string + '_' + str( elem) + '_' + 'fit_res' + '_' + str( dat_type) + '_' + timestr + '_' + pid + '_' + str( run_number) + '.hdf5' ###Use this path #If the file exists, output the desired variables if glob.glob( path_dat ): ###If the file already exists, don't write anything return elem_res, final_err, final_points, temp_array, elem_a, elem_b, elem_c, nanless_res, nanless_err, nanless_T, nanless_points, normed_weights #If the file does not exist, create file and output the desired variables else: ###If the file does not exist, write all fitting information file = h5py.File(path_dat, 'w') file['points'] = final_points file['residuals'] = elem_res file['err_200'] = final_err file['a_param'] = elem_a file['b_param'] = elem_b file['c_param'] = elem_c file.close() return elem_res, final_err, final_points, temp_array, elem_a, elem_b, elem_c, nanless_res, nanless_err, nanless_T, nanless_points, normed_weights #If we are looking at simulations else: ###If we are looking at a simulation if location == 'personal': ###If running from Mac path_sim = '/Users/chloecheng/Personal/run_files/' + name_string + '/' + name_string + '_' + str( elem) + '_' + 'fit_res' + '_' + str( dat_type) + '_' + timestr + '_' + pid + '_' + str( run_number) + '.hdf5' ###Use this path elif location == 'server': ###If running on server path_sim = '/geir_data/scr/ccheng/AST425/Personal/run_files/' + name_string + '/' + name_string + '_' + str( elem) + '_' + 'fit_res' + '_' + str( dat_type) + '_' + timestr + '_' + pid + '_' + str( run_number) + '.hdf5' ###Use this path #If the file exists, append to the file if glob.glob(path_sim): ###If the file exists file = h5py.File(path_sim, 'a') ###Append to the file #If the group for the particular value of sigma exists, don't do anything if glob.glob( str(sigma_val) ): ###If this value of sigma has already been tested, don't write anything file.close() #If not, append a new group to the file for the particular value of sigma else: ###If it has not been tested, write all fitting information to a group named after the value of sigma grp = file.create_group(str(sigma_val)) grp['points'] = final_points grp['residuals'] = elem_res grp['err_200'] = final_err grp['a_param'] = elem_a grp['b_param'] = elem_b grp['c_param'] = elem_c file.close() #If the file does not exist, create a new file else: ###If the file does not exist, write all of the fitting information to a group named after the value of sigma file = h5py.File(path_sim, 'w') grp = file.create_group(str(sigma_val)) grp['points'] = final_points grp['residuals'] = elem_res grp['err_200'] = final_err grp['a_param'] = elem_a grp['b_param'] = elem_b grp['c_param'] = elem_c file.close() return elem_res, final_err, final_points, temp_array, elem_a, elem_b, elem_c, nanless_res, nanless_err, nanless_T, nanless_points, normed_weights
def test_windows(options): elems = [ 'C', 'N', 'O', 'Na', 'Mg', 'Al', 'Si', 'S', 'K', 'Ca', 'Ti', 'V', 'Mn', 'Fe', 'Ni', 'Ce', 'Co', 'Cr', 'Cu', 'Ge', 'Nd', 'P', 'Rb', 'Y' ] if options.savefilename is None or \ not os.path.exists(options.savefilename): # Set default linelist for Turbospectrum or MOOG if options.linelist is None and options.moog: linelist = 'moog.201312161124.vac' elif options.linelist is None: linelist = 'turbospec.201312161124' else: linelist = options.linelist # set up a model atmosphere for the requested atmospheric parameters if options.arcturus: options.teff = 4286. options.logg = 1.66 options.metals = -0.52 options.am = 0.4 options.cm = 0.09 options.vm = 1.7 atm = atlas9.Atlas9Atmosphere(teff=options.teff, logg=options.logg, metals=options.metals, am=options.am, cm=options.cm) # create baseline if options.moog: baseline= \ apogee.modelspec.moog.synth(modelatm=atm, linelist=linelist, lsf='all',cont='aspcap', vmacro=6.,isotopes='arcturus', vmicro=options.vm) else: baseline= \ apogee.modelspec.turbospec.synth(modelatm=atm, linelist=linelist, lsf='all',cont='aspcap', vmacro=6.,isotopes='arcturus', vmicro=options.vm) # Loop through elements elem_synspec = {} # Run through once to simulate all differences for elem in elems: # First check that this element has windows elemPath = apwindow.path(elem, dr=options.dr) if not os.path.exists(elemPath): continue # Simulate deltaAbu up and down print "Working on %s" % (elem.capitalize()) abu = [atomic_number(elem), -options.deltaAbu, options.deltaAbu] if options.moog: synspec= \ apogee.modelspec.moog.synth(abu, modelatm=atm, linelist=linelist, lsf='all',cont='aspcap', vmacro=6., isotopes='arcturus', vmicro=options.vm) else: synspec= \ apogee.modelspec.turbospec.synth(abu, modelatm=atm, linelist=linelist, lsf='all',cont='aspcap', vmacro=6., isotopes='arcturus', vmicro=options.vm) elem_synspec[elem] = synspec if not options.savefilename is None: save_pickles(options.savefilename, baseline, elem_synspec) else: with open(options.savefilename, 'rb') as savefile: baseline = pickle.load(savefile) elem_synspec = pickle.load(savefile) # Now run through the different elements again and plot windows for each # with elements that vary significantly colors = sns.color_palette("colorblind") plotelems = [ elem if not elem in ['C', 'N', 'O', 'Fe'] else '%s1' % elem for elem in elems ] plotelems.extend(['C2', 'N2', 'O2', 'Fe2']) for pelem in plotelems: if '1' in pelem or '2' in pelem: elem = pelem[:-1] else: elem = pelem if not elem in elem_synspec: continue # Figure out which elements have significant variations in these # windows and always plot the element that should vary elemIndx = apwindow.tophat(elem, dr=options.dr) elemWeights = apwindow.read(elem, dr=options.dr) elemWeights /= numpy.nansum(elemWeights) # Start with the element in question splot.windows(1. + options.amplify * (elem_synspec[elem][0] - baseline[0]), pelem, color=colors[0], yrange=[0., 1.4], plot_weights=True, zorder=len(elems)) splot.windows(1. + options.amplify * (elem_synspec[elem][1] - baseline[0]), pelem, color=colors[0], overplot=True, zorder=len(elems)) elem_shown = [elem] # Run through the rest to figure out the order elemVar = numpy.zeros(len(elems)) for ii, altElem in enumerate(elems): if altElem == elem: continue if not altElem in elem_synspec: continue elemVar[ii] = 0.5 * numpy.nansum( (elem_synspec[altElem][0] - baseline[0])**2. * elemWeights) elemVar[ii] += 0.5 * numpy.nansum( (elem_synspec[altElem][1] - baseline[0])**2. * elemWeights) jj = 0 sortindx = numpy.argsort(elemVar)[::-1] for altElem in numpy.array(elems)[sortindx]: if altElem == elem: continue if not altElem in elem_synspec: continue if numpy.fabs(\ numpy.nanmax([(elem_synspec[altElem][0]-baseline[0])[elemIndx], (elem_synspec[altElem][1]-baseline[0])[elemIndx]]))\ > options.varthreshold: jj += 1 if jj >= len(colors): jj = len(colors) - 1 elem_shown.append(altElem) splot.windows(1. + options.amplify * (elem_synspec[altElem][0] - baseline[0]), pelem, color=colors[jj], overplot=True, zorder=len(elems) - jj) splot.windows(1. + options.amplify * (elem_synspec[altElem][1] - baseline[0]), pelem, color=colors[jj], overplot=True, zorder=len(elems) - jj) t = pyplot.gca().transData fig = pyplot.gcf() for s, c in zip(elem_shown, colors[:jj + 1]): xc = 0.05 if elem == 'K' or elem == 'Ce' or elem == 'Ge' or elem == 'Nd' \ or elem == 'Rb': xc = apwindow.waveregions(elem, dr=options.dr, pad=3)[0][0] - 15000. + 1. text = pyplot.text(xc, 1.2, " " + (r"$\mathrm{%s}$" % s) + " ", color=c, transform=t, size=16., backgroundcolor='w') text.draw(fig.canvas.get_renderer()) ex = text.get_window_extent() t = transforms.offset_copy(text._transform, x=1.5 * ex.width, units='dots') # Save bovy_plot.bovy_end_print(options.plotfilename.replace('ELEM', pelem)) return None
def windows(*args, **kwargs): """ NAME: windows PURPOSE: plot the spectral windows for a given element INPUT: Either: (a) wavelength, spectrum (\AA,spectrum units) (b) spectrum (assumed on standard APOGEE re-sampled wavelength grid) (c) location ID, APOGEE ID (default loads aspcapStar, loads extension ext(=1); apStar=True loads apStar spectrum) +element string (e.g., 'Al'); Adding 1 and 2 splits the windows into two KEYWORDS: plot_weights= (False) if True, also plot the weights for the windows (assumes that the spectrum is on the apStarWavegrid) markLines= mark the location of 'lines' (see apogee.spec.window.lines) apogee.spec.plot.waveregions keywords OUTPUT: plot to output The final axes allow one to put additional labels on the plot, e.g., for adding the APOGEE ID: bovy_plot.bovy_text(r'$\mathrm{%s}$' % '2M02420597+0837017',top_left=True) Note that an ID (e.g., the apogee ID) and Teff, logg, metallicity, and alpha-enhancement labels can be added using the keywords label* above HISTORY: 2015-01-26 - Written (based on older code) - Bovy (IAS) """ pad = kwargs.pop('pad', 3) try: si, ei = apwindow.waveregions(args[2], pad=pad, asIndex=True) except IOError: try: si, ei = apwindow.waveregions(args[2][:-1], pad=pad, asIndex=True) except IOError: raise IOError( "Windows for element %s could not be loaded, please specify an existing APOGEE element" % ((args[2].lower().capitalize()))) if args[2][-1] == '1': si = si[:len(si) // 2] ei = ei[:len(ei) // 2] else: si = si[len(si) // 2:] ei = ei[len(ei) // 2:] # Remove the number from the element newargs = (args[0], args[1], args[2][:-1]) for ii in range(len(args) - 3): newargs = newargs + (args[ii + 3], ) args = newargs # Also get the number and total width of all of the windows dlam = apwindow.total_dlambda(args[2], pad=pad) numw = apwindow.num(args[2]) # Set spacing between windows if numw > 20: kwargs['skipdx'] = 0.003 kwargs['_noskipdiags'] = True elif numw > 15: kwargs['skipdx'] = 0.01 # Set initial space to zero kwargs['_startendskip'] = 0 # Set initial figure width if not kwargs.get('overplot', False) and not 'fig_width' in kwargs: if dlam > 150.: kwargs['fig_width'] = 8.4 else: kwargs['fig_width'] = 4.2 # Don't tick x kwargs['_noxticks'] = True # Label the largest wavelength in angstrom kwargs['_labelwav'] = True # Don't label the lines unless explicitly asked for kwargs['labelLines'] = kwargs.get('labelLines', False) # Plot the weights as well if kwargs.pop('plot_weights', False): kwargs['_plotw'] = apwindow.read(args[2], apStarWavegrid=True) if kwargs.get('apStar', False): kwargs['yrange'] = kwargs.get('yrange', [0., 1.1 * numpy.nanmax(args[1])]) else: kwargs['yrange'] = kwargs.get('yrange', [0., 1.2]) # mark the 'lines' markLines = kwargs.get('markLines', not 'overplot' in kwargs) if markLines and not '_markwav' in kwargs: kwargs['_markwav'] = apwindow.lines(args[2]) # Plot waveregions(args[0], args[1], startindxs=si, endindxs=ei, *args[3:], **kwargs) # Add label bovy_plot.bovy_text(r'$\mathrm{%s}$' % ((args[2].lower().capitalize())), top_left=True, fontsize=10, backgroundcolor='w') return None
def elemchi2(spec,specerr, elem,elem_linspace=(-0.5,0.5,11),tophat=False, fparam=None, teff=4750.,logg=2.5,metals=0.,am=0.,nm=0.,cm=0.,vm=None, lib='GK',pca=True,sixd=True,dr=None, offile=None, inter=3,f_format=1,f_access=None, verbose=False): """ NAME: elemchi2 PURPOSE: Calculate the chi^2 for a given element INPUT: Either: (1) location ID - single or list/array of location IDs APOGEE ID - single or list/array of APOGEE IDs; loads aspcapStar (2) spec - spectrum: can be (nwave) or (nspec,nwave) specerr - spectrum errors: can be (nwave) or (nspec,nwave) elem - element to consider (e.g., 'Al') elem_linspace= ((-0.5,0.5,11)) numpy.linspace range of abundance, relative to the relevant value in fparam / metals,am,nm,cm tophat= (False) if True, don't use the value of weights, just use them to define windows that have weight equal to one Input parameters (can be 1D arrays) Either: (1) fparam= (None) output of ferre.fit (2) teff= (4750.) Effective temperature (K) logg= (2.5) log10 surface gravity / cm s^-2 metals= (0.) overall metallicity am= (0.) [alpha/M] nm= (0.) [N/M] cm= (0.) [C/M] vm= if using the 7D library, also specify the microturbulence Library options: lib= ('GK') spectral library pca= (True) if True, use a PCA compressed library sixd= (True) if True, use the 6D library (w/o vm) dr= data release FERRE options: inter= (3) order of the interpolation f_format= (1) file format (0=ascii, 1=unf) f_access= (None) 0: load whole library, 1: use direct access (for small numbers of interpolations), None: automatically determine a good value (currently, 1) verbose= (False) if True, run FERRE in verbose mode OUTPUT: chi^2 HISTORY: 2015-03-12 - Written - Bovy (IAS) """ # Parse fparam if not fparam is None: teff= fparam[:,paramIndx('TEFF')] logg= fparam[:,paramIndx('LOGG')] metals= fparam[:,paramIndx('METALS')] am= fparam[:,paramIndx('ALPHA')] nm= fparam[:,paramIndx('N')] cm= fparam[:,paramIndx('C')] if sixd: vm= None else: vm= fparam[:,paramIndx('LOG10VDOP')] # parse spec, specerr input nspec= len(teff) if len(spec.shape) == 1: spec= numpy.reshape(spec,(1,spec.shape[0])) specerr= numpy.reshape(specerr,(1,specerr.shape[0])) # Read the weights if tophat: weights= apwindow.tophat(elem,apStarWavegrid=False,dr=dr) else: weights= apwindow.read(elem,apStarWavegrid=False,dr=dr) weights/= numpy.sum(weights) # Decide which parameter to vary nvelem= elem_linspace[2] var_elem= numpy.tile(numpy.linspace(*elem_linspace),(nspec,1)) if elem.lower() == 'c': cm= var_elem+numpy.tile(cm,(nvelem,1)).T elif elem.lower() == 'n': nm= var_elem+numpy.tile(nm,(nvelem,1)).T elif elem.lower() in ['o','mg','s','si','ca','ti']: am= var_elem+numpy.tile(am,(nvelem,1)).T else: metals= var_elem+numpy.tile(metals,(nvelem,1)).T # Upgrade dimensionality of other parameters for interpolate input teff= numpy.tile(teff,(nvelem,1)).T logg= numpy.tile(logg,(nvelem,1)).T if not sixd: vm= numpy.tile(vm,(nvelem,1)).T.flatten() if not elem.lower() == 'c': cm= numpy.tile(cm,(nvelem,1)).T if not elem.lower() == 'n': nm= numpy.tile(nm,(nvelem,1)).T if not elem.lower() in ['o','mg','s','si','ca','ti']: am= numpy.tile(am,(nvelem,1)).T if elem.lower() in ['c','n','o','mg','s','si','ca','ti']: metals= numpy.tile(metals,(nvelem,1)).T # Get interpolated spectra, [nspec,nwave] ispec= interpolate(teff.flatten(),logg.flatten(),metals.flatten(), am.flatten(),nm.flatten(),cm.flatten(),vm=vm, lib=lib,pca=pca,sixd=sixd,dr=dr, inter=inter,f_format=f_format,f_access=f_access, verbose=verbose,apStarWavegrid=False) dspec= numpy.tile(spec,(1,nvelem)).reshape((nspec*nvelem,spec.shape[1])) dspecerr= numpy.tile(specerr, (1,nvelem)).reshape((nspec*nvelem,spec.shape[1])) tchi2= _chi2(ispec,dspec,dspecerr,numpy.tile(weights,(nspec*nvelem,1))) return numpy.reshape(tchi2,(nspec,nvelem))
def windows(*args,**kwargs): """ NAME: windows PURPOSE: plot the spectral windows for a given element INPUT: Either: (a) wavelength, spectrum (\AA,spectrum units) (b) spectrum (assumed on standard APOGEE re-sampled wavelength grid) (c) location ID, APOGEE ID (default loads aspcapStar, loads extension ext(=1); apStar=True loads apStar spectrum) +element string (e.g., 'Al'); Adding 1 and 2 splits the windows into two KEYWORDS: plot_weights= (False) if True, also plot the weights for the windows (assumes that the spectrum is on the apStarWavegrid) markLines= mark the location of 'lines' (see apogee.spec.window.lines) apogee.spec.plot.waveregions keywords OUTPUT: plot to output The final axes allow one to put additional labels on the plot, e.g., for adding the APOGEE ID: bovy_plot.bovy_text(r'$\mathrm{%s}$' % '2M02420597+0837017',top_left=True) Note that an ID (e.g., the apogee ID) and Teff, logg, metallicity, and alpha-enhancement labels can be added using the keywords label* above HISTORY: 2015-01-26 - Written (based on older code) - Bovy (IAS) """ pad= kwargs.pop('pad',3) try: si,ei= apwindow.waveregions(args[2],pad=pad,asIndex=True) except IOError: try: si, ei= apwindow.waveregions(args[2][:-1],pad=pad,asIndex=True) except IOError: raise IOError("Windows for element %s could not be loaded, please specify an existing APOGEE element" % ((args[2].lower().capitalize()))) if args[2][-1] == '1': si= si[:len(si)//2] ei= ei[:len(ei)//2] else: si= si[len(si)//2:] ei= ei[len(ei)//2:] # Remove the number from the element newargs= (args[0],args[1],args[2][:-1]) for ii in range(len(args)-3): newargs= newargs+(args[ii+3],) args= newargs # Also get the number and total width of all of the windows dlam= apwindow.total_dlambda(args[2],pad=pad) numw= apwindow.num(args[2]) # Set spacing between windows if numw > 20: kwargs['skipdx']= 0.003 kwargs['_noskipdiags']= True elif numw > 15: kwargs['skipdx']= 0.01 # Set initial space to zero kwargs['_startendskip']= 0 # Set initial figure width if not kwargs.get('overplot',False) and not 'fig_width' in kwargs: if dlam > 150.: kwargs['fig_width']= 8.4 else: kwargs['fig_width']= 4.2 # Don't tick x kwargs['_noxticks']= True # Label the largest wavelength in angstrom kwargs['_labelwav']= True # Don't label the lines unless explicitly asked for kwargs['labelLines']= kwargs.get('labelLines',False) # Plot the weights as well if kwargs.pop('plot_weights',False): kwargs['_plotw']= apwindow.read(args[2],apStarWavegrid=True) if kwargs.get('apStar',False): kwargs['yrange']= kwargs.get('yrange', [0.,1.1*numpy.nanmax(args[1])]) else: kwargs['yrange']= kwargs.get('yrange',[0.,1.2]) # mark the 'lines' markLines= kwargs.get('markLines',not 'overplot' in kwargs) if markLines and not '_markwav' in kwargs: kwargs['_markwav']= apwindow.lines(args[2]) # Plot waveregions(args[0],args[1],startindxs=si,endindxs=ei, *args[3:],**kwargs) # Add label bovy_plot.bovy_text(r'$\mathrm{%s}$' % ((args[2].lower().capitalize())), top_left=True,fontsize=10,backgroundcolor='w') return None
def fit_func(elem, name, spectra, spectra_errs, T, dat_type, run_number, location, sigma_val=None): """Return fit residuals from quadratic fit, spectral errors for desired element, fluxes for desired element, an appropriately-sized array of effective temperatures, the quadratic fitting parameters, the residuals, errors, temperatures, and fluxes with NaNs removed, and the normalized elemental weights. Functions: Reads in the DR14 windows. Obtains the indices of pixels of the absorption lines and saves the flux value and uncertainty for each star in these pixels. Performs the quadratic fit on each pixel using weight_lsq() and computes the residuals using residuals(). Obtains the flux values, uncertainties, fits, residuals, and temperatures with NaNs removed. Writes the residuals and fit parameters to .hdf5 files. Parameters ---------- elem : str Element name (i.e. 'AL') name : str Name of desired cluster (i.e. 'NGC 2682') spectra : tuple Array of floats representing the spectra of the desired cluster spectra_errs : tuple Array of floats representing the spectral uncertainties of the desired cluster T : tuple Array of floats representing the effective temperature of each star in the cluster dat_type : str Indicates whether the data being examined is the data or a simulation run_number : int Number of the run by which to label files location : str If running locally, set to 'personal'. If running on the server, set to 'server'. sigma_val : float, optional Indicates the value of sigma being used for the simulation in question, if applicable (default is None) Returns ------- elem_res : tuple Array of floats representing the fit residuals, with original positioning of points maintained final_err : tuple Array of floats representing the spectral uncertainties from the lines of the desired element, with original positioning of points maintained final_points : tuple Array of floats representing the fluxes from the lines of the desired element, with original positioning of points maintained temp_array : tuple Array of floats representing the effective temperature of each star in the cluster, with a row for each pixel of the desired element elem_a : tuple Array of floats representing the fitting parameters for the quadratic terms in the fits for each pixel of the desired element elem_b : tuple Array of floats representing the fitting parameters for the linear terms in the fits for each pixel of the desired element elem_c : tuple Array of floats representing the fitting parameters for the constant terms in the fits for each pixel of the desired element nanless_res : tuple Array of floats representing the fit residuals, with NaNs removed nanless_T : tuple Array of floats representing the effective temperature of each star in the cluster, with a row for each pixel of the desired element, with NaNs removed nanless_points : tuple Array of floats representing the fluxes from the lines of the desired element, with NaNs removed normed_weights : tuple Array of floats representing the weight of each elemental window, normalized to 1 """ change_dr('12') #Find the DR14 windows from the DR12 windows dr12_elem_windows = window.read(elem) change_dr('14') dr14_elem_windows_12 = np.concatenate((dr12_elem_windows[246:3274], dr12_elem_windows[3585:6080], dr12_elem_windows[6344:8335])) normalized_dr14_elem_windows_12 = (dr14_elem_windows_12 - np.nanmin(dr14_elem_windows_12))/(np.nanmax(dr14_elem_windows_12) - np.nanmin(dr14_elem_windows_12)) #Get the indices of the lines ind_12 = np.argwhere(normalized_dr14_elem_windows_12 > 0) ind_12 = ind_12.flatten() #Get the fluxes and errors from spectra len_spectra = len(spectra) elem_points_12 = np.zeros((len(ind_12), len_spectra)) elem_err_12 = np.zeros((len(ind_12), len_spectra)) for i in range(0, len(ind_12)): for j in range(0, len_spectra): elem_points_12[i][j] = spectra[j][ind_12[i]] elem_err_12[i][j] = spectra_errs[j][ind_12[i]] #APOGEE measured errors #Use only pixels with more than 5 points final_points_12 = [] final_err_12 = [] final_inds_12 = [] for i in range(len(elem_points_12)): if np.count_nonzero(~np.isnan(elem_points_12[i])) >= 5: final_points_12.append(elem_points_12[i]) final_err_12.append(elem_err_12[i]) final_inds_12.append(ind_12[i]) final_points_12 = np.array(final_points_12) final_err_12 = np.array(final_err_12) final_inds_12 = np.array(final_inds_12) if len(final_inds_12) == 0: print('Warning: less than 5 points for every pixel, skipping ', elem) else: dr12_weights = normalized_dr14_elem_windows_12[final_inds_12] sorted_dr12_weights = np.sort(dr12_weights) #Get windows if location == 'personal': window_file = pd.read_hdf('/Users/chloecheng/Personal/dr14_windows.hdf5', 'window_df') elif location == 'server': window_file = pd.read_hdf('/geir_data/scr/ccheng/AST425/Personal/dr14_windows.hdf5', 'window_df') dr14_elem_windows_14 = window_file[elem].values normalized_dr14_elem_windows_14 = (dr14_elem_windows_14 - np.min(dr14_elem_windows_14))/(np.max(dr14_elem_windows_14) - np.min(dr14_elem_windows_14)) #Get the indices of the lines if elem == 'C' or elem == 'N' or elem == 'FE': ind = np.argwhere(normalized_dr14_elem_windows_14 > np.min(sorted_dr12_weights[int(len(sorted_dr12_weights)*0.7):])) else: ind = np.argwhere(normalized_dr14_elem_windows_14 > 0) ind = ind.flatten() #Get the fluxes and errors from spectra elem_points = np.zeros((len(ind), len_spectra)) elem_err = np.zeros((len(ind), len_spectra)) for i in range(0, len(ind)): for j in range(0, len_spectra): elem_points[i][j] = spectra[j][ind[i]] elem_err[i][j] = spectra_errs[j][ind[i]] #APOGEE measured errors #Use only pixels with more than 5 points final_points = [] final_err = [] final_inds = [] for i in range(len(elem_points)): if np.count_nonzero(~np.isnan(elem_points[i])) >= 5: final_points.append(elem_points[i]) final_err.append(elem_err[i]) final_inds.append(ind[i]) final_points = np.array(final_points) final_err = np.array(final_err) final_inds = np.array(final_inds) if len(final_points) == 0: print('Warning: less than 5 points for every pixel, skipping ', elem) else: #Create an appropriately-sized array of temperatures to mask as well temp_array = np.full((final_points.shape), T) for i in range(0, len(final_points)): for j in range(0, len_spectra): if np.isnan(final_points[i][j]): temp_array[i][j] = np.nan #Do fits with non-nan numbers nanless_inds = np.isfinite(final_points) fits = [] for i in range(len(final_points)): fits.append(weight_lsq(final_points[i][nanless_inds[i]], temp_array[i][nanless_inds[i]], final_err[i][nanless_inds[i]])) for i in range(len(fits)): fits[i] = np.array(fits[i]) fits = np.array(fits) elem_a = fits[:,0] elem_b = fits[:,1] elem_c = fits[:,2] elem_fits = np.zeros_like(final_points) for i in range(0, len(final_points)): elem_fits[i] = elem_a[i]*temp_array[i]**2 + elem_b[i]*temp_array[i] + elem_c[i] #Calculate residuals elem_res = residuals(final_points, elem_fits) #Remove nans from fits, residuals, errors, and temperatures for plotting and cumulative distribution #calculation purposes nanless_fits = [] nanless_res = [] nanless_err = [] nanless_T = [] nanless_points = [] for i in range(len(final_points)): nanless_fits.append(elem_fits[i][nanless_inds[i]]) nanless_res.append(elem_res[i][nanless_inds[i]]) nanless_err.append(final_err[i][nanless_inds[i]]) nanless_T.append(temp_array[i][nanless_inds[i]]) nanless_points.append(final_points[i][nanless_inds[i]]) for i in range(len(final_points)): nanless_fits[i] = np.array(nanless_fits[i]) nanless_res[i] = np.array(nanless_res[i]) nanless_err[i] = np.array(nanless_err[i]) nanless_T[i] = np.array(nanless_T[i]) nanless_points[i] = np.array(nanless_points[i]) nanless_fits = np.array(nanless_fits) nanless_res = np.array(nanless_res) nanless_err = np.array(nanless_err) nanless_T = np.array(nanless_T) nanless_points = np.array(nanless_points) #Get the weights for later weights = normalized_dr14_elem_windows_14[final_inds] normed_weights = weights/np.sum(weights) #File-saving #If we are looking at the data timestr = time.strftime("%Y%m%d_%H%M%S") name_string = str(name).replace(' ', '') pid = str(os.getpid()) if sigma_val == None: if location == 'personal': path_dat = '/Users/chloecheng/Personal/run_files_' + name_string + '_' + str(elem) + '/' + name_string + '/' + name_string + '_' + str(elem) + '_' + 'fit_res' + '_' + str(dat_type) + '_' + timestr + '_' + pid + '_' + str(run_number) + '.hdf5' elif location == 'server': path_dat = '/geir_data/scr/ccheng/AST425/Personal/run_files_' + name_string + '_' + str(elem) + '/' + name_string + '/' + name_string + '_' + str(elem) + '_' + 'fit_res' + '_' + str(dat_type) + '_' + timestr + '_' + pid + '_' + str(run_number) + '.hdf5' #If the file exists, output the desired variables if glob.glob(path_dat): return elem_res, final_err, final_points, temp_array, elem_a, elem_b, elem_c, nanless_res, nanless_err, nanless_T, nanless_points, normed_weights #If the file does not exist, create file and output the desired variables else: file = h5py.File(path_dat, 'w') file['points'] = final_points file['residuals'] = elem_res file['err_200'] = final_err file['a_param'] = elem_a file['b_param'] = elem_b file['c_param'] = elem_c file.close() return elem_res, final_err, final_points, temp_array, elem_a, elem_b, elem_c, nanless_res, nanless_err, nanless_T, nanless_points, normed_weights #If we are looking at simulations else: if location == 'personal': path_sim = '/Users/chloecheng/Personal/run_files_' + name_string + '_' + str(elem) + '/' + name_string + '/' + name_string + '_' + str(elem) + '_' + 'fit_res' + '_' + str(dat_type) + '_' + timestr + '_' + pid + '_' + str(run_number) + '.hdf5' elif location == 'server': path_sim = '/geir_data/scr/ccheng/AST425/Personal/run_files_' + name_string + '_' + str(elem) + '/' + name_string + '/' + name_string + '_' + str(elem) + '_' + 'fit_res' + '_' + str(dat_type) + '_' + timestr + '_' + pid + '_' + str(run_number) + '.hdf5' #If the file exists, append to the file if glob.glob(path_sim): file = h5py.File(path_sim, 'a') #If the group for the particular value of sigma exists, don't do anything if glob.glob(str(sigma_val)): file.close() #If not, append a new group to the file for the particular value of sigma else: grp = file.create_group(str(sigma_val)) grp['points'] = final_points grp['residuals'] = elem_res grp['err_200'] = final_err grp['a_param'] = elem_a grp['b_param'] = elem_b grp['c_param'] = elem_c file.close() #If the file does not exist, create a new file else: file = h5py.File(path_sim, 'w') grp = file.create_group(str(sigma_val)) grp['points'] = final_points grp['residuals'] = elem_res grp['err_200'] = final_err grp['a_param'] = elem_a grp['b_param'] = elem_b grp['c_param'] = elem_c file.close() return elem_res, final_err, final_points, temp_array, elem_a, elem_b, elem_c, nanless_res, nanless_err, nanless_T, nanless_points, normed_weights
def test_windows(options): elems= ['C','N','O','Na','Mg','Al','Si','S','K','Ca','Ti','V','Mn','Fe', 'Ni','Ce','Co','Cr','Cu','Ge','Nd','P','Rb','Y'] if options.savefilename is None or \ not os.path.exists(options.savefilename): # Set default linelist for Turbospectrum or MOOG if options.linelist is None and options.moog: linelist= 'moog.201312161124.vac' elif options.linelist is None: linelist= 'turbospec.201312161124' else: linelist= options.linelist # set up a model atmosphere for the requested atmospheric parameters if options.arcturus: options.teff= 4286. options.logg= 1.66 options.metals= -0.52 options.am= 0.4 options.cm= 0.09 options.vm= 1.7 atm= atlas9.Atlas9Atmosphere(teff=options.teff,logg=options.logg, metals=options.metals, am=options.am,cm=options.cm) # create baseline if options.moog: baseline= \ apogee.modelspec.moog.synth(modelatm=atm, linelist=linelist, lsf='all',cont='aspcap', vmacro=6.,isotopes='arcturus', vmicro=options.vm) else: baseline= \ apogee.modelspec.turbospec.synth(modelatm=atm, linelist=linelist, lsf='all',cont='aspcap', vmacro=6.,isotopes='arcturus', vmicro=options.vm) # Loop through elements elem_synspec= {} # Run through once to simulate all differences for elem in elems: # First check that this element has windows elemPath= apwindow.path(elem,dr=options.dr) if not os.path.exists(elemPath): continue # Simulate deltaAbu up and down print "Working on %s" % (elem.capitalize()) abu= [atomic_number(elem),-options.deltaAbu,options.deltaAbu] if options.moog: synspec= \ apogee.modelspec.moog.synth(abu, modelatm=atm, linelist=linelist, lsf='all',cont='aspcap', vmacro=6., isotopes='arcturus', vmicro=options.vm) else: synspec= \ apogee.modelspec.turbospec.synth(abu, modelatm=atm, linelist=linelist, lsf='all',cont='aspcap', vmacro=6., isotopes='arcturus', vmicro=options.vm) elem_synspec[elem]= synspec if not options.savefilename is None: save_pickles(options.savefilename,baseline,elem_synspec) else: with open(options.savefilename,'rb') as savefile: baseline= pickle.load(savefile) elem_synspec= pickle.load(savefile) # Now run through the different elements again and plot windows for each # with elements that vary significantly colors= sns.color_palette("colorblind") plotelems= [elem if not elem in ['C','N','O','Fe'] else '%s1' % elem for elem in elems] plotelems.extend(['C2','N2','O2','Fe2']) for pelem in plotelems: if '1' in pelem or '2' in pelem: elem = pelem[:-1] else: elem= pelem if not elem in elem_synspec: continue # Figure out which elements have significant variations in these # windows and always plot the element that should vary elemIndx= apwindow.tophat(elem,dr=options.dr) elemWeights= apwindow.read(elem,dr=options.dr) elemWeights/= numpy.nansum(elemWeights) # Start with the element in question splot.windows(1.+options.amplify*(elem_synspec[elem][0]-baseline[0]), pelem, color=colors[0], yrange=[0.,1.4], plot_weights=True, zorder=len(elems)) splot.windows(1.+options.amplify*(elem_synspec[elem][1]-baseline[0]), pelem, color=colors[0],overplot=True, zorder=len(elems)) elem_shown= [elem] # Run through the rest to figure out the order elemVar= numpy.zeros(len(elems)) for ii,altElem in enumerate(elems): if altElem == elem: continue if not altElem in elem_synspec: continue elemVar[ii]= 0.5*numpy.nansum((elem_synspec[altElem][0]-baseline[0])**2.*elemWeights) elemVar[ii]+= 0.5*numpy.nansum((elem_synspec[altElem][1]-baseline[0])**2.*elemWeights) jj= 0 sortindx= numpy.argsort(elemVar)[::-1] for altElem in numpy.array(elems)[sortindx]: if altElem == elem: continue if not altElem in elem_synspec: continue if numpy.fabs(\ numpy.nanmax([(elem_synspec[altElem][0]-baseline[0])[elemIndx], (elem_synspec[altElem][1]-baseline[0])[elemIndx]]))\ > options.varthreshold: jj+= 1 if jj >= len(colors): jj= len(colors)-1 elem_shown.append(altElem) splot.windows(1.+options.amplify*(elem_synspec[altElem][0]-baseline[0]), pelem, color=colors[jj],overplot=True, zorder=len(elems)-jj) splot.windows(1.+options.amplify*(elem_synspec[altElem][1]-baseline[0]), pelem, color=colors[jj],overplot=True, zorder=len(elems)-jj) t = pyplot.gca().transData fig= pyplot.gcf() for s,c in zip(elem_shown,colors[:jj+1]): xc= 0.05 if elem == 'K' or elem == 'Ce' or elem == 'Ge' or elem == 'Nd' \ or elem == 'Rb': xc= apwindow.waveregions(elem,dr=options.dr, pad=3)[0][0]-15000.+1. text = pyplot.text(xc,1.2," "+(r"$\mathrm{%s}$" % s)+" ",color=c, transform=t,size=16.,backgroundcolor='w') text.draw(fig.canvas.get_renderer()) ex= text.get_window_extent() t= transforms.offset_copy(text._transform,x=1.5*ex.width, units='dots') # Save bovy_plot.bovy_end_print(options.plotfilename.replace('ELEM',pelem)) return None