def GetDwarfAbs(parmList, abDict): # Note: could use an XOR, and a isGiant flag to combine the Dwarf and Giant # versions of this function accumulator = {} dwarfList = [s[0] for s in parmList if not RC.isGiantStar(s[1:])] for dName in dwarfList: if dName in abDict.keys(): for ion in abDict[dName].keys(): if ion in accumulator.keys(): accumulator[ion].append(abDict[dName][ion][0]) else: accumulator[ion] = [abDict[dName][ion][0]] retDict = {} for ion in accumulator.keys(): retDict[ion] = np.mean([ab for ab in accumulator[ion]]) return retDict
def MakeLineListTable(ions=[], wls=[], outFile=d.TableDir + 'Table2.dat'): lines, refs = LL.getLines(elements=ions, wavelengthRange=wls,\ dataFormat=None) unused1, unused2, weights = RC.GetSolarCorrections() fp = open(outFile, 'w') fmt, db = BuildFormatString(table2Format, DataLabels=table2Labels, DataUnits=table2Units, DataExp=table2Desc, MakeBbBDesc=True) fp.write(db) allIons = sorted(set(np.array(lines)[:, 1])) lineData = [] for i in allIons: ion = np.round(i, decimals=1) (elem, state, unused) = el.getIonState(el.getIonName(ion)) ionLines = np.array( sorted([l for l in lines if np.round(l[1], decimals=1) == ion], key=lambda l: l[0])) for line in ionLines: wl = np.round(line[0], decimals=3) xp = line[2] gf = line[3] if gf < 0: gfs = '-' else: gfs = '' gf = abs(gf) try: qu = int(weights[ion][wl]) except KeyError: qu = 0 rf = line[5] lineData.append([elem, state, wl, xp, gfs, gf, qu, rf]) for line in lineData: fp.write(fmt.format(*line) + '\n') fp.close()
def selectLinesForElement(lines, ion, modelAtms, pradks, starParms, varLimit = np.finfo(np.float64).max, enforceMin=False, refLines=None, refCorrs=None, lineWeights=None): # From the passed list, select all the lines of the passed ion # (in XX.x form), with abundances within +/-varLimit of the mean. # An additional selection criteria is that the line eqw falls on # the linear portion of the curve of growth. # If enforceMin = True, the selection will be limited to the lesser # of the total number of lines for this element, or the constant # MinNumStatLines. # To save time in looped, or multiple calls, solar (or giant) corrections # can be passed in refLines and refCorrs. This is basically the output # of RC.getGiantCorrections or RC.getSolarCorrections for the passed ion. corrLines, allLines = RC.SortAndFilterLines(lines[ion], ion, starParms, filterBlends=True, refCorrect=True, modelAtms=modelAtms , pradks=pradks, refLines=refLines, refCorrs=refCorrs, lineWeights=lineWeights) # If we did not receive enough (any) corrected lines, so return a subset of # all the lines. if (corrLines==None or len(corrLines) < k.MinNumStatLines): if len(allLines) <= k.MinNumStatLines: # Well, we can't make more lines, so just return what we have return sorted(allLines, key=lambda line: line[0]) else: meanAb = np.mean(np.array(allLines)[:,5]) allSorted = sorted(allLines, key=lambda line: abs(line[5]-meanAb))[:k.MinNumStatLines] return sorted(allSorted, key=lambda line: line[0]) elif enforceMin: # We have enough lines to consider filtering for the variance limit. meanAb = np.mean(np.array(corrLines)[:,5]) limitedLines = [line for line in corrLines if abs(line[5]-meanAb)<=varLimit] if len(limitedLines) < k.MinNumStatLines: # Variance filtering was a bit much, return the best we can return sorted(sorted(corrLines, key=lambda line: abs(line[5]-meanAb))[:k.MinNumStatLines], key=lambda l: l[0]) else: return sorted(limitedLines, key=lambda line: line[0]) else: # enforceMin not set, so filter away! meanAb = np.mean(np.array(corrLines)[:,5]) rtnLines = [x for x in corrLines if abs(x[5]-meanAb) < abs(varLimit)] return sorted(rtnLines, key=lambda line: line[0])
def MakeSolarCompTable(outFilename=k.TempAbOutFilename, headerLeft='', headerRight=''): # Function creates a LaTeX table with elemental abundances as calculated from # our Solar reference spectrum, based on a "quality" measurement of each line. # Each column of the table represents a measurement using lines of a particular # quality or better. The final column is represents all of the measured lines. corrections, lines, weights = RC.GetSolarCorrections() # We're going to create one column for each "quality" setting from the # returned weights list. Basically, each weight is a quality level. # The columnDict contains: # {weight:{ion:[ab,std,#lines],...},...} columnDict = {} for wt in k.AbWeights: columnDict[wt] = {} allIonList = sorted(lines.keys()) for ion in allIonList: ionLines = lines[ion] # A single line will not show up as a list of one item. Rather, the # entire list will be that one line's parameters...grrr. if not u.is_list(ionLines[0]): ionLines = [ionLines] for wt in k.AbWeights: wtLines = np.array([line for line in ionLines \ if line[0] in weights[ion] and weights[ion][line[0]] >= wt]) if len(wtLines) > 0: asplundCorr = PA.ptoe[int(ion) - 1][PA.abIdx] columnDict[wt][ion] = [ np.mean(wtLines[:, 5]) + asplundCorr, np.std(wtLines[:, 5]), len(wtLines) ] # Create a nice column title for each quality type: nameList = [ r'$\Delta\leq{0:1.2f}$'.format(r[1]) for r in k.AbWeightRanges[:-1] ] nameList.append('All lines') outfile = open(outFilename, 'w') latexHeader = STP.kLaTexHeader1 + '\\rhead{\\textbf{' + headerRight\ + '}}\n\\lhead{\\textbf{' + headerLeft\ + '}}\n\\begin{document}\n' outfile.write(latexHeader) outfile.write('\\begin{landscape}\n'\ + '\\hspace*{-5cm}\n'\ + '\\begin{tabular}{|l|l|l|l|l|l|l|l|l|l|') outfile.write( '}\n\\multicolumn{1}{l}{Ion} & \\multicolumn{1}{l}{Asplund (2009)}') for name in nameList: outfile.write(' & \\multicolumn{{1}}{{l}}{{{0}}}'.format(name)) outfile.write('\\\\\n\\hline\n') for ion in allIonList: outfile.write('{0} & {1:1.2f}$\pm${2:1.2f}'.format(el.getIonName(ion),\ PA.ptoe[int(ion)-1][PA.abIdx],\ PA.ptoe[int(ion)-1][PA.solarErrIdx])) for wt in k.AbWeights: if ion in columnDict[wt].keys() and columnDict[wt][ion][2] > 0: outfile.write(' & {0:1.2f}$\pm${1:1.2f} ({2:d})'.\ format(columnDict[wt][ion][0]-PA.ptoe[int(ion)-1][PA.abIdx], columnDict[wt][ion][1], columnDict[wt][ion][2])) else: outfile.write(' & \\multicolumn{1}{c|}{---} ') outfile.write('\\\\\n\\hline\n') outfile.write('\\label{{tab:SolarAbs}}\n' + '\\end{tabular}\n\\end{landscape}\n' + '\\clearpage\n') outfile.write('\\end{document}\n') outfile.close()
def PlotXPAbs(starData, clusterName='NGC-0752', ionList=kAllIonList, fileTag='', labelPlot=True, labelPoints=False, showTrendLine=False, modelAtms=None, pradks=None, referenceCorrect=False): # Make XP vs. Ab for the passed star # One element per plot. starName = starData[0] starParmTuple = tuple(starData[1:]) isGiant = RC.isGiantStar(starParmTuple) if isGiant: modelPath = k.GiantModelPath else: modelPath = k.DwarfModelPath if modelAtms == None or pradks == None: modelFiles = mk.findDataFiles(modelPath) modelAtms, pradks = mk.LoadModels(modelFiles) abdict, uncorrLines, unusedMin, unusedMax = \ AB.CalcAbsAndLines(clusterName+' '+starName, tuple(starData[1:6]), ionList=ionList, modelAtms=modelAtms, pradks=pradks) # uncorrLines: # # {elem.ion:[[Wavelength, Ex.Pot., logGf, eqw, logRW, abund],...]} if referenceCorrect: if isGiant: # Obligatory comment on bad Giant corrections, and using # Solar instead. correctDict, referenceLines, lineWeights = \ RC.GetSolarCorrections(ionList=ionList, modelAtms=modelAtms, pradks=pradks) else: correctDict, referenceLines, lineWeights = \ RC.GetDwarfCorrections(ionList=ionList, modelAtms=modelAtms, pradks=pradks) correctionsAvailable = False if len(correctDict) > 0 and len(referenceLines) > 0: correctionsAvailable = True for ion in ionList: if ion not in uncorrLines.keys(): continue # Does this element have NLTE corrections available? Note: we do # this BEFORE Solar corrections, which assumes that the same # NLTE corrections are already applied to any Solar corrections # we use. if ion in NLTEIons: LTELines = AB.CorrectNLTEAbs(ion, uncorrLines[ion], tuple(starData[1:6])) else: if ion in uncorrLines.keys(): LTELines = uncorrLines[ion] else: # Either synthesized lines, or none available LTELines = np.array([]) # Do we want the "reference corrected" abundances? if referenceCorrect and correctionsAvailable: tempAdj,tempAll = \ RC.SortAndFilterLines(LTELines, ion, tuple(starData[1:6]), solarCorrect=referenceCorrect, solarLines=referenceLines[ion], solarCorrs=correctDict[ion], lineWeights=lineWeights[ion]) # correctedLines: # [[ab, line STR score, wl, "quality"], ...] # allLines: # [[ab, line STR score, wl],...] # We want to use np.arrays, so... allLines = np.array(tempAll) correctedLines = np.array(tempAdj) if len(allLines) == 0 or len(correctedLines) == 0: correctionsAvailable = False elif len(allLines) == 1 or len(correctedLines) == 1: print('Single Line determination:{0}'.format(starData[0])) print(allLines, correctedLines) # One plot per ion. if labelPlot: plotLabel = 'XP vs Ab for [{2}/H] in {0} {1}.'.\ format(clusterName, starName, el.getIonName(ion)) else: plotLabel = '' if referenceCorrect and correctionsAvailable: tempPoints = [] for line in uncorrLines[ion]: correctedAbs = [l[0] for l in correctedLines if \ u.in_range(l[2],line[0]-0.05, line[0]+0.05)] if len(correctedAbs) > 0: tempPoints.append( [line[1], np.mean(correctedAbs), line[3], line[0]]) else: tempPoints.append([line[1], line[5], line[3], line[0]]) XPAbPoints = np.array(tempPoints) else: XPAbPoints = np.array([[line[1],line[5],line[3],line[0]]\ for line in uncorrLines[ion]]) if labelPoints: # Label the points with the wavelength pointLabels = ['{0:2.3f}'.format(point[3]) \ for point in XPAbPoints] else: pointLabels = None ps.XPAbPlot(XPAbPoints, starName, ion, fileTag=fileTag + 'XPAb', plotTitle=plotLabel, pointLabels=pointLabels, showTrendLine=showTrendLine)
def MakeAbTable(clusterName='NGC-0752', starDataList=None, ions=kAllIonList, outFilename=k.TempAbOutFilename, filterBlends=False, referenceCorrect=False, useDAOSpec=False, headerLeft='', headerRight=''): if starDataList == None: starDataList = GetAllStarParms(clusterName=clusterName) # Lookup the abundance(s) for the passed star(s), and create a LaTeX chart tableDict = GetAbTable(clusterName, starDataList, ions, filterBlends, referenceCorrect, useDAOSpec) giantNames = np.array([s[0] for s in starDataList \ if RC.isGiantStar(s[1:5])]) # dwarfNames = np.array([s[0] for s in starDataList # if not RC.isGiantStar(s[1],s[2])]) # Iron abundance is listed as [Fe/H], all others will be [X/Fe]. # Compile a cluster/dwarfs/giants average table entry. # Entries are of the form: # {Ion:[[star ab, star line quality], ...], ...} clusterDict = {} dwarfDict = {} giantDict = {} for star in tableDict.keys(): # Place this stars measures into the proper category dictionary if star in giantNames: catDict = giantDict else: catDict = dwarfDict starFe = GetStarFeH(tableDict[star]) for ion in tableDict[star].keys(): solarIonH = PA.ptoe[int(ion) - 1][PA.abIdx] if tableDict[star][ion][0] == 0.: continue if ion not in [26.0, 26.1]: # Adjust values for [X/Fe] tableDict[star][ion][0] = tableDict[star][ion][0]\ - solarIonH\ - starFe if ion in clusterDict.keys(): clusterDict[ion].append([tableDict[star][ion][0],\ tableDict[star][ion][3]]) else: clusterDict[ion] = [[tableDict[star][ion][0],\ tableDict[star][ion][3]]] if ion in catDict.keys(): catDict[ion].append([tableDict[star][ion][0],\ tableDict[star][ion][3]]) else: catDict[ion] = [[tableDict[star][ion][0],\ tableDict[star][ion][3]]] idxName = clusterName + ' (all)' tableDict[idxName] = {} for ion in clusterDict.keys(): # If each star's ab measurement for are "independent measures" of the # cluster abundance, we should divide the stdev by sqrt(num_measures)... # Calcs broken into separate lines for readability. cMean = np.mean([l[0] for l in clusterDict[ion]]) cStd = np.std([l[0] for l in clusterDict[ion]]) cScoreMean = np.mean([l[1] for l in clusterDict[ion]]) tableDict[idxName][ion] = \ [cMean, cStd, len(clusterDict[ion]), cScoreMean] idxName = clusterName + ' (dwarfs)' tableDict[idxName] = {} for ion in dwarfDict.keys(): dMean = np.mean([l[0] for l in dwarfDict[ion]]) dStd = np.std([l[0] for l in dwarfDict[ion]]) dScoreMean = np.mean([l[1] for l in dwarfDict[ion]]) tableDict[idxName][ion] = \ [dMean, dStd, len(dwarfDict[ion]), dScoreMean] idxName = clusterName + ' (giants)' tableDict[idxName] = {} for ion in giantDict.keys(): gMean = np.mean([l[0] for l in giantDict[ion]]) gStd = np.std([l[0] for l in giantDict[ion]]) gScoreMean = np.mean([l[1] for l in giantDict[ion]]) tableDict[idxName][ion] = \ [gMean, gStd, len(giantDict[ion]), gScoreMean] ions = sorted(list(set(ions))) # The cluster name starts with "N", so it will be first in the list nameList = sorted(tableDict.keys()) outfile = open(outFilename, 'w') latexHeader = kLaTexHeader1 + '\\rhead{\\textbf{' + headerRight\ + '}}\n\\lhead{\\textbf{' + headerLeft\ + '}}\n\\begin{document}\n' outfile.write(latexHeader) # New page/table: for tableCount in range(int(len(nameList) / 6) + 1): outfile.write('\\begin{landscape}\n'\ + '\\hspace*{-5cm}\n'\ + '\\begin{tabular}{|l|l|l|l|l|l|l|') outfile.write('}\n\\multicolumn{1}{l}{Ion}') for name in nameList[tableCount * 6:(tableCount + 1) * 6]: outfile.write(' & \\multicolumn{{1}}{{l}}{{{0}}}'.format(name)) outfile.write('\\\\\n\\hline\n') # A little bit of stupidity to put FeI and FeII at the top of the table: printIons = sorted(ions) printIons.remove(26.) printIons.remove(26.1) printIons = [26.0, 26.1] + printIons for ion in printIons: if int(ion) == 26: outfile.write('[{0}/H]'.format(el.getIonName(ion))) else: outfile.write('[{0}/Fe]'.format(el.getIonName(ion))) for star in nameList[tableCount * 6:(tableCount + 1) * 6]: if ion in tableDict[star].keys( ) and tableDict[star][ion][2] > 0: outfile.write(' & {0:3.2f}$\pm${1:3.2f} ({2:d}, {3:1.1f})'.\ format(tableDict[star][ion][0], tableDict[star][ion][1], tableDict[star][ion][2], tableDict[star][ion][3])) else: outfile.write(' & \multicolumn{1}{c|}{---}') outfile.write('\\\\\n\\hline\n') # Place a double line after the Fe/H measures if ion == 26.1: outfile.write('\\hline\n') outfile.write('\\label{{tab:752Abs-{0}}}\n'.format(tableCount + 1) + '\\end{tabular}\n\\end{landscape}\n' + '\\clearpage\n') outfile.write('\\end{document}\n') outfile.close()
def GetAbTable(clusterName='NGC-0752', starDataList=None, ions=kAllIonList, filterBlends=False, referenceCorrect=False, useDAOSpec=False, gModelAtms=None, gPradks=None, dModelAtms=None, dPradks=None): # Returns a dictionary with each star name (key) has a list of elements # (secondary key), with a list containing [Abundance in [X/H], variance in the # line measurements, count of lines measured, average quality score]: # returnDict={starName:{ion:[[X/H],stdev, count, avg.quality],...},...} if starDataList == None: starDataList = GetAllStarParms(clusterName=clusterName) # Since we're doing a bunch of lines (uh...), we'll need both giant and # dwarf references. Giant references are prefixed by a 'g', dwarfs by 'd'. if gModelAtms == None or gPradks == None: gModelFiles = mk.findDataFiles(k.GiantModelPath) gModelAtms, gPradks = mk.LoadModels(gModelFiles) if dModelAtms == None or dPradks == None: dModelFiles = mk.findDataFiles(k.DwarfModelPath) dModelAtms, dPradks = mk.LoadModels(dModelFiles) # We need iron to do relative abundances: if 26.0 not in ions: ions.append(26.0) # Turns out our giant corrections are not good # gCorrectDict, gReferenceLines, gLineWeights = \ # GetGiantCorrections(ionList=ions, # modelAtms=gModelAtms, # pradks=gPradks) # So, use the Solar corrections for now gCorrectDict, gReferenceLines, gLineWeights = \ RC.GetSolarCorrections(ionList=ions, modelAtms=dModelAtms, pradks=dPradks) dCorrectDict, dReferenceLines, dLineWeights = \ RC.GetDwarfCorrections(ionList=ions, modelAtms=dModelAtms, pradks=dPradks) tableDict = {} for starData in starDataList: starName = starData[0] starParms = tuple(starData[1:6]) if RC.isGiantStar(starParms): modelAtms = gModelAtms pradks = gPradks referenceLines = gReferenceLines referenceDict = gCorrectDict lineWeights = gLineWeights else: modelAtms = dModelAtms pradks = dPradks referenceLines = dReferenceLines referenceDict = dCorrectDict lineWeights = dLineWeights tableDict[starName] = GetAbsForStar(starData, ions=ions,\ filterBlends=filterBlends, refCorrect=referenceCorrect,\ refDict=referenceDict, refLines=referenceLines, \ lineWeights=lineWeights, useDAOSpec=useDAOSpec, \ modelAtms=modelAtms, pradks=pradks) return tableDict
def GetAbsForStar(starData, clusterName='NGC-0752', ions=kAllIonList, \ filterBlends=False, refCorrect=False,\ refLines=None, refDict=None, lineWeights=None, useDAOSpec=False, modelAtms=None, pradks=None): # Get all the elemental abundances for the single passed star (params): # starData: (starName, Teff, LogG, VTurb, Met, Mass) # # Returns a dictionary of {ion:(Ab, std, #lines, avg Quality)...} starName = starData[0] starParms = tuple(starData[1:6]) abdict, uncorrLines, unusedMins, unusedMaxes = \ AB.CalcAbsAndLines(clusterName+' '+starName, starParms, ionList=ions, modelAtms=modelAtms, pradks=pradks, useDAOlines=useDAOSpec) # uncorrLines: # # {elem.ion:[[Wavelength, Ex.Pot., logGf, eqw, logRW, abund],...]} starAbDict = {} ionLUT = sorted(list(abdict.keys())) ionLUT = sorted(set(ionLUT + [ion for ion in SynthAbsDict.keys()\ if starName in SynthAbsDict[ion].keys()])) if refCorrect and (refLines is None or refDict is None): refCorrect = False for ion in ionLUT: # We'll make one line per ion. Note, synth elements won't # necessarily have lines in the table/dict. if ion not in list(uncorrLines.keys()) + list(SynthAbsDict.keys()): continue if refCorrect and ion not in refLines.keys(): correctionsAvail = False else: correctionsAvail = True # Does this element have NLTE corrections available? Note: we do # this BEFORE Solar corrections, which assumes that the same # NLTE corrections are already applied to any Solar corrections # we use. if ion in NLTEIons: LTELines = AB.CorrectNLTEAbs(ion, uncorrLines[ion], starParms) else: if ion in uncorrLines.keys(): LTELines = uncorrLines[ion] else: # Either synthesized lines, or none available LTELines = np.array([]) # Now apply "Solar" or "Astrophysical Log gf" corrections, if requested if correctionsAvail and (refCorrect or filterBlends) and ion in uncorrLines.keys(): tempAdj,tempAll = \ RC.SortAndFilterLines(LTELines, ion, starParms, filterBlends=filterBlends, solarCorrect=refCorrect, solarLines=refLines[ion], solarCorrs=refDict[ion], lineWeights=lineWeights[ion]) # correctedLines: # [[ab, line STR score, wl, "quality"], ...] # allLines: # [[ab, line STR score, wl],...] # We want to use np.arrays, so... allLines = np.array(tempAll) correctedLines = np.array(tempAdj) else: if len(LTELines) > 0: allLines = np.array(\ [[l[5], el.STR(l[2], l[1], starParms[0]), l[0]] \ for l in LTELines]) correctedLines = np.array(\ [[l[0], l[1], l[2], k.AbWeights[-1]] \ for l in allLines]) else: allLines = correctedLines = np.array([]) if ion in SynthAbsDict.keys() and \ starName in SynthAbsDict[ion].keys(): # We have a C I or N I synthesis: if ion == 6.0: nonSynthLines = np.array([l for l in correctedLines\ if l[2]<7110 or l[2]>7120]) elif ion == 7.0: # N I synthesis uses both the 7115 region (giants) # and the 7442 region (all). Only the 7442 region # has a potentially measured line, tho. nonSynthLines = np.array([l for l in correctedLines \ if np.floor(l[2]) != 7442]) else: nonSynthLines = [] synthArray = GetSynthLines(starName, ion,\ clusterName=clusterName) # Returned tuple: (synthMean, synthStd, synthCount) # Include our synthesis as the number of lines measured if len(nonSynthLines) == 0: starAbDict[ion] = [synthArray[0], synthArray[1],\ synthArray[2],k.NoAbWeight] else: mean = np.mean(nonSynthLines[:, 0]) std = np.std(nonSynthLines[:, 0]) ct = len(nonSynthLines) totalCt = ct + synthArray[2] totalMean = ((mean*ct)+(synthArray[0]*synthArray[2]))/\ (totalCt) totalStd = np.sqrt(\ (ct*(totalMean-mean)**2+ synthArray[2]*(synthArray[0]-mean)**2)/\ (totalCt-1)) starAbDict[ion] = [totalMean, totalStd, totalCt, k.NoAbWeight] # We have already created the abundance dictionary for this ion, # so skip out on the next part. continue else: # No synthesized lines need to be added. pass if refCorrect and len(correctedLines) > 0: linesToCount = correctedLines avgQ = np.mean(correctedLines[:, 3]) else: linesToCount = allLines avgQ = k.NoAbWeight if len(linesToCount) > 0: starAbDict[ion] = [ np.mean(linesToCount[:, 0]), np.std(linesToCount[:, 0]), len(linesToCount), avgQ ] else: # No lines to count. Make sure we don't have an entry: if ion in starAbDict.keys(): del starAbDict[ion] return starAbDict
def PlotAbs(clusterName, starData, ions, fileTag='', plotTitle='', filterBlends=False, referenceCorrect=False, labelPoints=False, useDAOSpec=False, modelAtms=None, pradks=None): pointLabels = None # Lookup the abundance(s) for the passed star, and plot them # (into a .png file). One element per plot. starName = starData[0] starParmTuple = tuple(starData[1:6]) isGiant = RC.isGiantStar(starParmTuple) if isGiant: modelPath = k.GiantModelPath else: modelPath = k.DwarfModelPath if modelAtms == None or pradks == None: modelFiles = mk.findDataFiles(modelPath) modelAtms, pradks = mk.LoadModels(modelFiles) # uncorrLines format: # {elem.ion:[[Wavelength, Ex.Pot., logGf, eqw, logRW, abund],...]} # abDict format: # {elem.ion:[abundance mean, ab. std.dev., # lines]} abdict, uncorrLines, unusedMin, unusedMax = \ AB.CalcAbsAndLines(clusterName+' '+starName, starParmTuple, ionList=ions, modelAtms=modelAtms, pradks=pradks, useDAOlines=useDAOSpec) if isGiant: # Obtain the reference corrections for a giant star - Note: this is # badly broken! So, we're just going to use the Solar corrections for # now: correctDict, referenceLines, lineWeights = \ RC.GetDwarfCorrections(ionList=ions, modelAtms=modelAtms, pradks=pradks, useDAOSpec=useDAOSpec) # correctDict, referenceLines, lineWeights = \ # GetGiantCorrections(ionList=ions, # modelAtms=modelAtms, # pradks=pradks) else: # ...or for a dwarf star. correctDict, referenceLines, lineWeights = \ RC.GetDwarfCorrections(ionList=ions, modelAtms=modelAtms, pradks=pradks, useDAOSpec=useDAOSpec) for ion in ions: # We'll make one plot per ion. pointLabels = [] redData = greenData = blueData = [] if ion not in uncorrLines.keys(): print('No {0:2.1f} lines for {1}.'.format(ion, starName)) continue if (referenceCorrect or filterBlends) and \ ion in referenceLines.keys() and ion in correctDict.keys() and \ ion in lineWeights.keys(): adjustedLines, dataPoints = \ RC.SortAndFilterLines(uncorrLines[ion], ion, starParmTuple, filterBlends=filterBlends, solarCorrect=referenceCorrect, solarLines=referenceLines[ion], solarCorrs=correctDict[ion], lineWeights=lineWeights[ion]) tempData = [] for line in uncorrLines[ion]: corrLine = u.find(lambda l: l[0] == line[0], dataPoints) if corrLine is not None: tempData.append(corrLine) else: tempData.append([line[5], el.STR(line[2], line[1], \ starParmTuple[0]),line[0]]) redData = np.array(tempData) else: dataPoints = np.array([[line[5], el.STR(line[2], line[1], starParmTuple[0]), line[0]] \ for line in uncorrLines[ion]]) if labelPoints: pointLabels = ['{0:4.3f}'.format(line[2]) for line in dataPoints] pointLabels.extend(['{0:4.3f}'.\ format(line[2]) for line in redData]) pointLabels.extend(['{0:4.3f}'.\ format(line[2]) for line in greenData]) pointLabels.extend(['{0:4.3f}'.\ format(line[2]) for line in blueData]) loSlope, loIntercept, rv, pv, err = \ ps.GetDetectionLimit(starParmTuple, ion, modelAtms=modelAtms, pradks=pradks) hiSlope, hiIntercept, rv, pv, err = \ ps.GetCoGLimit(starParmTuple, ion, modelAtms=modelAtms, pradks=pradks) ps.AbSTRPlot(starName, ion, dataPoints, redSet=redData, greenSet=greenData, blueSet=blueData, lowLimit=(loSlope, loIntercept), hiLimit=(hiSlope, hiIntercept), fileTag=fileTag, plotTitle=plotTitle, labelPoints=pointLabels)
def COGPlot(clusterName, starData, ions, fileTag='', labelPlot=True, labelPoints=False, modelAtms=None, pradks=None, makeQualityPlot=False): # Make Curve of Growth (COG) plots for the passed star # One element per plot. # If the makeQualityPlot flag is set, a second plot will be made, with the # points shaded relative to how well they correspond to the linear fit of # measurements with similar excitation potentials. starName = starData[0] starParmTuple = tuple(starData[1:]) isGiant = RC.isGiantStar(starParmTuple) if isGiant: modelPath = k.GiantModelPath else: modelPath = k.DwarfModelPath if modelAtms == None or pradks == None: modelFiles = mk.findDataFiles(modelPath) modelAtms, pradks = mk.LoadModels(modelFiles) abdict, uncorrLines, unusedMin, unusedMax = \ AB.CalcAbsAndLines(clusterName+' '+starName, tuple(starData[1:6]), ionList=ions, modelAtms=modelAtms, pradks=pradks) for ion in ions: # One plot per ion. if ion not in uncorrLines.keys(): print('No {0:2.1f} lines for {1}.'.format(ion, starName)) continue if labelPlot: plotLabel = 'Curve of Growth for [{2}/H] in {0} {1}.'.\ format(clusterName, starName, el.getIonName(ion)) else: plotLabel = '' if labelPoints: # Label the points with the excitation potential pointLabels = ['{0:2.3f}'.format(point[1]) \ for point in np.array(uncorrLines[ion])] else: pointLabels = None ps.COGPlot(np.array(uncorrLines[ion]), starName, ion, fileTag=fileTag, plotTitle=plotLabel, pointLabels=pointLabels) if makeQualityPlot: if labelPlot: plotLabel = 'Measurement quality for [{2}/H] in {0} {1}.'.\ format(clusterName, starName, el.getIonName(ion)) else: plotLabel = '' ps.QualityPlot(np.array(uncorrLines[ion]), starName, ion, fileTag=fileTag + 'QP', plotTitle=plotLabel, pointLabels=pointLabels)
def MakeVPlots(clusterName='NGC-0752', starDataList=None, fileTag='', filterBlends=False, referenceCorrect=False, useDAOSpec=False, ions=[20.0]): # Function plots V_turb vs. sigma [Ca/H] (sigma is the line-to-line # standard deviation of the measured Ca lines), for a range of V_turb values. # Intended to provide a spectroscopic confirmation/adjustment # for photometrically-determined parameters. if starDataList is None: starDataList = STP.GetAllStarParms(clusterName=clusterName) dModelFiles = mk.findDataFiles(k.DwarfModelPath) dModelAtms, dPradks = mk.LoadModels(dModelFiles) dCorrectDict, dReferenceLines, dLineWeights = \ RC.GetDwarfCorrections(ionList=ions, modelAtms=dModelAtms, pradks=dPradks) gModelFiles = mk.findDataFiles(k.GiantModelPath) gModelAtms, gPradks = mk.LoadModels(gModelFiles) # Note: We're using dwarf corrections for giant stars... # because they're better than giant corrections for the # giant stars. This needs to be fixed. :( gCorrectDict, gReferenceLines, gLineWeights = \ RC.GetSolarCorrections(ionList=ions, modelAtms=dModelAtms, pradks=dPradks) # For now, CaI appears to work best for all stars. # VI, Ti I/II, Fe I/II, Cr I/II also work, but not as well - (See Reddy, et al. 2012). # ions = [20.0] abDict = {} colorArray=['r','orange','gold','darkgreen','navy',\ 'm','saddlebrown','skyblue','hotpink'] for starParms in starDataList: if RC.isGiantStar(starParms[1:]): modelAtms = gModelAtms pradks = gPradks refLines = gReferenceLines refDict = gCorrectDict lineWeights = gLineWeights else: modelAtms = dModelAtms pradks = dPradks refLines = dReferenceLines refDict = dCorrectDict lineWeights = dLineWeights starPoints = {} for v in np.linspace(0.5, 3.0, 26): parmTuple = (starParms[0], starParms[1], starParms[2], v, \ starParms[4], starParms[5], starParms[6]) abDict[v] = STP.GetAbsForStar(parmTuple, ions=ions,\ filterBlends=filterBlends, refCorrect=referenceCorrect,\ refDict=refDict, refLines=refLines, lineWeights=lineWeights,\ useDAOSpec=useDAOSpec, modelAtms=modelAtms, pradks=pradks) for ion in abDict[v].keys(): if ion not in starPoints.keys(): starPoints[ion] = {} if abDict[v][ion][0] == 0.: continue starPoints[ion][v] = abDict[v][ion][1] colorIdx = 0 ymaxes = [] for ion in starPoints.keys(): Xs = sorted(np.array(list(starPoints[ion].keys()))) if len(Xs) == 0 or ion in STP.SynthAbsDict.keys(): continue Ys = np.array([starPoints[ion][x] for x in Xs]) if len(Xs) < 2 or len(Ys) < 2: continue Ys = Ys / min(Ys) ymaxes.append(max(Ys)) try: minV = Xs[np.where(Ys == min(Ys))[0][0]] except IndexError: continue pyplot.plot(Xs, Ys, label=r'$({1}) V_{{turb}}={0:3.1f}km/sec$'.format( minV, el.getIonName(ion)), color=colorArray[colorIdx]) pyplot.scatter(Xs, Ys, color=colorArray[colorIdx]) pyplot.axvline(minV, linestyle=':', color=colorArray[colorIdx]) colorIdx += 1 if colorIdx == len(colorArray): colorIdx = 0 ax = pyplot.gca() ax.set_xlabel(r'$V_{{turb}} km/s$') ax.set_ylabel('Normalized [X/H] variance') ax.set_ylim((0., min(5.0, max(ymaxes)))) pyplot.legend(fontsize=8) pyplot.savefig(k.ParmPlotDir + 'Vturb/' + starParms[0] + fileTag + '.png') pyplot.close()
def MakeTeffPlots(clusterName='NGC-0752', starDataList=None, fileTag='', referenceCorrect=False): # Function plots Teff vs. slope of (XP vs. [Fe/H]) for a range of temperatures. # Intended to provide a spectroscopic confirmation/adjustment # for photometrically-determined parameters. We assume that at the "correct" # temperature, the slope of XP vs. [Fe/H] would be zero. if starDataList is None: starDataList = STP.GetAllStarParms(clusterName=clusterName) dModelFiles = mk.findDataFiles(k.DwarfModelPath) dModelAtms, dPradks = mk.LoadModels(dModelFiles) gModelFiles = mk.findDataFiles(k.GiantModelPath) gModelAtms, gPradks = mk.LoadModels(gModelFiles) # Map Fe I Ab vs. Ex pot. ions = [26.0] abDict = {} dTeffRange = np.linspace(5000, 7000, 81) gTeffRange = np.linspace(4000, 6000, 81) for star in starDataList: starName = star[0] isGiant = RC.isGiantStar(star[1:]) if isGiant: modelAtms = gModelAtms pradks = gPradks tRange = gTeffRange if referenceCorrect: correctDict, referenceLines, lineWeights = \ RC.GetGiantCorrections(ionList=ions, modelAtms=modelAtms, pradks=pradks) else: modelAtms = dModelAtms pradks = dPradks tRange = dTeffRange if referenceCorrect: correctDict, referenceLines, lineWeights = \ RC.GetDwarfCorrections(ionList=ions, modelAtms=modelAtms, pradks=pradks) logG = star[2] vTurb = star[3] met = star[4] slopes = [] for Teff in tRange: unusedDict, uncorrLines, unusedMin, unusedMax = \ AB.CalcAbsAndLines(clusterName+' '+starName, tuple([Teff, star[2], star[3], star[4], star[5]]),\ ionList=ions, modelAtms=modelAtms, pradks=pradks) XPs = [] Abs = [] if referenceCorrect: adjLines, allLines = RC.SortAndFilterLines( uncorrLines[26.0], 26.0, tuple([Teff, star[2], star[3], star[4], star[5]]), solarCorrect=True, solarLines=referenceLines[26.0], solarCorrs=correctDict[26.0], lineWeights=lineWeights[26.0]) if len(adjLines) > 10: # Assume 10 Fe I lines needed for nice plots for line in adjLines: # XP isn't returned, so have to do a lookup into the # original list. XPs.append( u.find(lambda l: l[0] == line[2], uncorrLines[26.0])[1]) Abs.append(line[0]) if len(XPs) == 0 or len(Abs) == 0: # Either no corrections, or corrections failed XPs = [line[1] for line in uncorrLines[26.0]] Abs = [line[5] for line in uncorrLines[26.0]] slope, intercept, rVal, pVal, err = sp.stats.linregress(XPs, Abs) slopes.append(slope) # We have to flip because interp expects the xvalues to be # monotomically increasing interpTs = np.interp([-0.02, 0., 0.02], slopes[::-1], tRange[::-1]) if interpTs[0] > interpTs[1]: minusR = interpTs[1] - interpTs[2] plusR = interpTs[0] - interpTs[1] else: minusR = interpTs[1] - interpTs[0] plusR = interpTs[2] - interpTs[1] fig = pyplot.figure() TeffLabel = r'$T_{{eff}} = {0:4.0f}^{{+{1:4.0f}}}_{{-{2:4.0f}}}$)'.\ format(interpTs[1],minusR,plusR) pyplot.scatter(tRange, slopes, label=TeffLabel) pyplot.axhline(0.0, linestyle=':') pyplot.legend() pyplot.savefig(k.ParmPlotDir + 'Teff/' + star[0] + fileTag + '_FeSlope.png') pyplot.close()
def MakeTAbPlots(clusterName='NGC-0752', starDataList=None, ionList=STP.kAllIonList, fileTag='', useSubfigures=False, referenceCorrect=False): # Create a bunch of .ps plots with the star's effective temperature vs. [X/Fe] # for all ions in the optional passed list. One ion per plot if starDataList == None: starDataList = STP.GetAllStarParms(clusterName=clusterName) abTable = STP.GetAbTable(clusterName=clusterName, starDataList=starDataList, ions=ionList, referenceCorrect=referenceCorrect) solarFeH = PA.ptoe[25][PA.abIdx] clusterFeH = \ 0.75*np.mean([abTable[star][26.0][0] for star in abTable.keys()])+\ 0.25*np.mean([abTable[star][26.1][0] for star in abTable.keys() \ if 26.1 in abTable[star].keys()]) for ion in ionList: solarIonH = PA.ptoe[int(ion) - 1][PA.abIdx] fig = pyplot.figure() ax = pyplot.gca() redGPoints = [] magGPoints = [] bluDPoints = [] cyaDPoints = [] for star in starDataList: starName = star[0] if starName not in abTable.keys(): continue starIons = sorted(abTable[starName].keys()) if ion not in starIons: continue starParms = star[1:] # Get the Fe/H for this star. Note: We don't do Fe/Fe comps. if int(ion) != 26: # If both ions are measured, weight 75/25 for FeI/FeII if 26.0 in starIons and 26.1 in starIons: starFe = 0.75*abTable[starName][26.0][0]\ + 0.25*abTable[starName][26.1][0]\ - solarFeH else: starFe = abTable[starName][26.0][0] - solarFeH else: starFe = 0. if RC.isGiantStar(starParms): # if starParms[5] < 50: # magGPoints.append([starParms[0], # abTable[starName][ion][0]-solarIonH-starFe, # abTable[starName][ion][1]]) # else: redGPoints.append([ starParms[0], abTable[starName][ion][0] - solarIonH - starFe, abTable[starName][ion][1] ]) else: # if starParms[5] < 25: # cyaDPoints.append([starParms[0], # abTable[starName][ion][0]-solarIonH-starFe, # abTable[starName][ion][1]]) # else: bluDPoints.append([ starParms[0], abTable[starName][ion][0] - solarIonH - starFe, abTable[starName][ion][1] ]) dMean = np.mean([l[1] for l in cyaDPoints + bluDPoints]) dStd = np.std([l[1] for l in cyaDPoints + bluDPoints]) ax.axhline(y=dMean, ls='dashed', color='b', label=r'Dwarf Avg. (${0:4.2f}\pm{1:4.2f}$)'.\ format(dMean,dStd)) ax.axhline(y=dMean - dStd, ls='dotted', color='b') ax.axhline(y=dMean + dStd, ls='dotted', color='b') gMean = np.mean([l[1] for l in redGPoints + magGPoints]) gStd = np.std([l[1] for l in redGPoints + magGPoints]) ax.axhline(y=gMean, ls='dashed', color='r', label=r'Giant Avg. (${0:4.2f}\pm{1:4.2f}$)'.\ format(gMean,gStd)) ax.axhline(y=gMean - gStd, ls='dotted', color='r') ax.axhline(y=gMean + gStd, ls='dotted', color='r') ax.axhline(y=0., ls='dashed', color='g', linewidth=1.0,\ label='Solar (${0:4.2f}$)'.\ format(PA.ptoe[int(ion)-1][PA.abIdx])) pyplot.rcParams.update({'legend.fontsize': 10}) ax.legend() if dMean > 0. and gMean > 0.: ax.set_ylim([ min([dMean - 0.5, gMean - 0.5]), max([dMean + 0.5, gMean + 0.5]) ]) elif dMean > 0.: ax.set_ylim([dMean - 0.5, dMean + 0.5]) elif gMean > 0: ax.set_ylim([gMean - 0.5, gMean + 0.5]) Xs = [l[0] for l in bluDPoints] Ys = [l[1] for l in bluDPoints] Es = [l[2] for l in bluDPoints] eb = ax.errorbar(Xs, Ys, yerr=Es, fmt='o', color='b') if len(eb) > 0 and len(eb[-1]) > 0: eb[-1][0].set_linestyle('--') # Xs = [l[0] for l in cyaDPoints] # Ys = [l[1] for l in cyaDPoints] # Es = [l[2] for l in cyaDPoints] # eb=ax.errorbar(Xs, Ys, yerr=Es, fmt='s', color='c') # if len(eb)>0 and len(eb[-1])>0: eb[-1][0].set_linestyle('--') Xs = [l[0] for l in redGPoints] Ys = [l[1] for l in redGPoints] Es = [l[2] for l in redGPoints] eb = ax.errorbar(Xs, Ys, yerr=Es, fmt='o', color='r') if len(eb) > 0 and len(eb[-1]) > 0: eb[-1][0].set_linestyle('--') # Xs = [l[0] for l in magGPoints] # Ys = [l[1] for l in magGPoints] # Es = [l[2] for l in magGPoints] # eb=ax.errorbar(Xs, Ys, yerr=Es, fmt='s', color='m') # if len(eb)>0 and len(eb[-1])>0: eb[-1][0].set_linestyle('--') ionStr = el.getIonName(ion) if int(ion) != 26: ax.set_ylim((-0.5, 0.5)) else: ax.set_ylim((-0.3, 0.3)) ax.set_xlabel(r'$T_{eff}$ (K)') if int(ion) != 26: ax.set_ylabel(r'$[{0}/Fe]$'.format(ionStr)) else: ax.set_ylabel(r'$[{0}]$'.format(ionStr)) pyplot.savefig('{0}{1}{2}.png'.format(k.PlotDir + 'Elems/', ionStr, fileTag), figure=fig) # pyplot.show() pyplot.close(fig)