def getGuesses(logFile, guessFilename): tGuess = k.SolarTeff gGuess = k.SolarLogG vGuess = k.SolarVturb if guessFilename is not None: # Assume the log file has the correct format of: NNNN_SSS_ssssss_II_OOO.fits # Where: # NNNN = NGC catalog number of parent cluster # (note: clusters not contained in the NGC catalog will be prefaced by a letter # representative of their catalog. ex: I = IC # SSS = Reference indexing system for this cluster. # (ex: MJP = Montgomery, Janes, and Phelps) # ssssss = Star index number from the aformetioned index. # ...which means that we can look up the guess by the star name. logFileWords = os.path.basename(logFile).split('_') # starName = '_'.join(logFileWords[0:3]) starName = logFileWords[0] print('Looking for star: %s' % starName) try: guessFile = open(guessFilename, 'r') guessLines = guessFile.readlines() except: u.errorOut('Error in parameter determination:\nUnable to open file:%s' % guessFilename, True) try: guessStr = [guessLine for guessLine in guessLines if guessLine.find(starName)==0][0] except IndexError: return tGuess, gGuess, vGuess guesses = guessStr.split() if len(guesses) > 0 and u.is_number(guesses[1]): tGuess = float(guesses[1]) if len(guesses) > 1 and u.is_number(guesses[2]): gGuess = float(guesses[2]) if len(guesses) > 2 and u.is_number(guesses[3]): vGuess = float(guesses[3]) return tGuess, gGuess, vGuess
def readDAORV(daoLogfile): # Reads the calculated RV from the first line of a log file. # We're expecting the first line to read: # "Radial velocity = <RV value> dispersion =..." rvStr = 'NaN' infile = open(daoLogfile, 'r') data = infile.readlines() infile.close() for line in data: words = line.split() if len(words) > 0: if words[0] == "Final": rvStr = words[3] break if u.is_number(rvStr): rv = float(rvStr) else: rv = -999.99 return rv
def ParseSimbadHTML(simbadBytes): fluxes = [] simbadPage = simbadBytes.decode('UTF-8') if 'Fluxes' not in simbadPage: return fluxes # Get the table of fluxes fluxTable = simbadPage.split('Fluxes')[1].split('</TABLE>')[0] fluxStrs = fluxTable.split('<TR>')[1:] for fluxEntry in fluxStrs: # Each flux entry wants to have the form: # [filter, flux, [error], quality, flags, Ref] # First, some filters contain a space. Like "g (AB)" - so check # if the second field is a number, if not, assume it is a # continuation of a filter fe = fluxEntry.split('<TT>')[1].split('</TT>')[0].split() idx = 1 if not u.is_number(fe[idx]): fil = ' '.join(fe[0:2]) idx += 1 else: fil = fe[0] mag = float(fe[idx]) idx += 1 try: err = float(fe[idx][1:-1]) except ValueError: err = 0. idx += 1 if fe[idx] == '<SPAN': grade = fe[idx + 4] idx += 5 else: grade = '-' flags = ' '.join(fe[idx:]) fluxes.append([fil, mag, err, grade, flags]) return fluxes
def ParseMOOGOut2File(out2Name): try: out2File = open(out2Name) except IOError: print('Unable to open {0} for line data read. Exiting.'.format(out2Name)) sys.exit() fileData = out2File.read() out2File.close() lines = deque(str.split(fileData,'\n')) # MOOG can occasionally "bail" from an modeling run. Of course there's no easy # way to catch MOOG printing "...I QUIT!", so we manually read the second # line of the .out2 file: "Good" runs will have the first (comment) line # from the .log file. "Bad" runs will be the intermediate output product # starting with "element" - or nothing at all. waitForUser = False # For now, we're assuming automated operations: if len(lines)<3: print('MOOG unable to complete element:(unknown) for {0}.'.format(out2Name[:-4])) if k.isPython3: if waitForUser: input('Press enter to acknowledge and continue') else: if waitForUser: raw_input('Press enter to acknowledge and continue') return {} if lines[1].split()[0] == 'element': print('MOOG unable to complete element:{0} for {1}.'.format(lines[1].split()[1], out2Name[:-4])) if k.isPython3: if waitForUser: input('Press enter to acknowledge and continue') else: if waitForUser: raw_input('Press enter to acknowledge and continue') return {} # elementDict is a dictionary with the element symbol + # ionization state (float) as key and an array of elements: # [Wavelength, Ex.Pot., logGf, eqw, logRW, abund] # for all the lines of that element as the value. # Example: elementDict = {26.0:[[4347.23, 0.00, -5.503, 89.8, -4.68, 8.95]...]} elementDict = {} currentElement = 1.0 # HI is a flag for "No element" lineAbs = [] while len(lines) > 1: thisLine = lines.popleft().split(); if len(thisLine) < 5: continue elif thisLine[0] == 'Abundance': # We have a new element. Put the last list (if any) # into the dictionary, and start clean if len(lineAbs) > 0: if currentElement in elementDict.keys(): elementDict[currentElement].extend(lineAbs) else: elementDict[currentElement] = lineAbs currentElement = float(EL.symbolLU(thisLine[4])[0]) + (EL.ionLU(thisLine[5])-1.)/10. lineAbs = [] elif u.is_number(thisLine[0]): # Note: MOOG2014 added the atom.ion ID as the second column in each line # So, now the input looks like: # [Wavelength, ID, Ex.Pot., logGf, eqw, logRW, abund, delta Avg.] # # If the abundance (or delta avg) field is 999.990, it is MOOG's # way of denoting one of the components of a blended line. Since # the abundance calculation for this line will be listed elsewhere, # we can skip this line in the .out2 file if float(thisLine[6]) > 900.: continue # Abundance line, but do a touch of editing... lineAbs.append([float(thisLine[0]), float(thisLine[2]), float(thisLine[3]), float(thisLine[4]), float(thisLine[5]),float(thisLine[6])]) # The following is the code for pre-2014 versions of MOOG: # lineAbs.append([float(x) for x in thisLine[:-1]]) # Were we working on an element when the file ended? if len(lineAbs) > 0: if currentElement in elementDict.keys(): elementDict[currentElement].extend(lineAbs) else: elementDict[currentElement] = lineAbs return elementDict
def loadATLASModels(filename): # The current format (as of: Jan. 2015) for the ATLAS models subdivides # models into files, based on metallicity and velocity. There is only # one metallicity/velocity combination per file. We assume this, but leave the # possibility of multiple met./vel. per file, open. try: model = open(filename, 'r') lines = model.readlines() except IOError: print('Error in reading: {0}'.format(filename)) exit() model.close() modelStartLines = [] count = 0 for thisLine in lines: theseWords = thisLine.split() if len(theseWords) is not 0: if theseWords[0][-3:] == 'EFF': # Note: several of the ATLAS model files are missing the first # character of each line, so some files have a first model line # starting with "TEFF", while others have "EFF" modelStartLines.append(count) count += 1 tableDict = {} pradkValue = {} for startLineNo in modelStartLines: Tstr = lines[startLineNo].split()[1] Gstr = lines[startLineNo].split()[3] Mstr = lines[startLineNo + 1].split()[3].strip('[]') # Special case: if Mstr == 'SOLAR': Mstr = '0.0' Vstr = lines[startLineNo + 1].split()[5] # Special case: if Vstr == 'WITH': Vstr = '1.5' TabLenstr = lines[startLineNo + 22].split()[2] # Our table lengths need to be the same... otherwise, matrix # interpolation isn't gonna work! For now, we just toss short/long # files. In the future, it might be better to try to convert them # to the same length. if not (u.is_number(Tstr) and u.is_number(Gstr) and u.is_number(Mstr) and u.is_number(Vstr) and u.is_number(TabLenstr)): continue if int(TabLenstr) != 72: continue if len(lines[startLineNo + 24].split()) == 7: # Some ATLAS models omit the last two columns when they are all zeroes tableDict[(float(Tstr), float(Gstr))] = [ [float(t) for t in s.split()] + [0., 0.] for s in lines[startLineNo + 23:startLineNo + 23 + int(TabLenstr)] ] else: tableDict[(float(Tstr), float(Gstr))] = [[ float(t) for t in s.split() ] for s in lines[startLineNo + 23:startLineNo + 23 + int(TabLenstr)]] pradkValue[(float(Tstr), float(Gstr))] = float( lines[startLineNo + 23 + int(TabLenstr)].split()[1]) theKeys = tableDict.keys() # Just re-use the met. & vel. values read from the final table met = float(Mstr) vel = float(Vstr) return met, vel, tableDict, pradkValue
def PlotFeXx(clusterName='NGC-0752', starDataList=None, fileTag='', groupErrors=False,\ ionList=STP.kAllIonList, filterBlends=False, referenceCorrect=False): # abTable = {starID:element/ion:[X/H, sigma, #, quality score]} abTable=STP.GetAbTable(clusterName=clusterName, starDataList=starDataList,\ ions=ionList, filterBlends=filterBlends, referenceCorrect=referenceCorrect) SolarFe = PA.ptoe[25][PA.abIdx] for ion in ionList: Xs = [] Ys = [] XErrs = [] YErrs = [] colors = [] allPts = [] SolarY = float(PA.ptoe[int(ion)-1][PA.abIdx]) for star in abTable.keys(): starAbs = abTable[star] starFe = float(STP.GetStarFeH(starAbs)) if ion in starAbs.keys(): if not(u.is_number(starAbs[ion][0]) and \ u.is_number(starAbs[26.0][1]) and \ u.is_number(starAbs[ion][1])): continue adj = SolarY if ion != 26.0: adj+=starFe allPts.append([float(starFe), float(starAbs[ion][0])-adj, float(starAbs[26.0][1]), float(starAbs[ion][1]), ColorLookup(star)]) yElem = EL.getIonName(ion) fig = pyplot.figure() axes = fig.gca() allPts = np.array(allPts) # allPts = np.array(zip(Xs, Ys, XErrs, YErrs, colors)) gAbs = np.array([p[1] for p in allPts if p[4]=='r']).astype(np.float) gAvg = np.mean(gAbs) gStd = np.std(gAbs) gFeAbs = np.array([p[0] for p in allPts if p[4]=='r']).astype(np.float) gFeAvg = np.mean(gFeAbs) gFeStd = np.std(gFeAbs) dAbs = np.array([p[1] for p in allPts if p[4]=='b']).astype(np.float) dAvg = np.mean(dAbs) dStd = np.std(dAbs) dFeAbs = np.array([p[0] for p in allPts if p[4]=='b']).astype(np.float) dFeAvg = np.mean(dFeAbs) dFeStd = np.std(dFeAbs) axes.axhline(y=gAvg, ls='dashed', color='r', label=r'Giant Avg. (${0:4.2f}\pm{1:4.2f}$)'.\ format(gAvg,gStd)) axes.axhline(y=gAvg+gStd, ls='dotted', color='r') axes.axhline(y=gAvg-gStd, ls='dotted', color='r') axes.axhline(y=dAvg, ls='dashed', color='b', label=r'Dwarf Avg. (${0:4.2f}\pm{1:4.2f}$)'.\ format(dAvg,dStd)) axes.axhline(y=dAvg+dStd, ls='dotted', color='b') axes.axhline(y=dAvg-dStd, ls='dotted', color='b') # axes.axhline(y=SolarY, ls='dashed', color='g', # label=r'Solar ({0:4.2f})'.format(SolarY)) axes.axhline(y=0., ls='dashed', color='g', label=r'Solar ({0:4.2f})'.format(SolarY)) Xs = np.array(allPts[:,0]).astype(np.float) XErrs = np.array(allPts[:,2]).astype(np.float) xMin = max(np.median(Xs)-0.3, min(Xs)-0.1) xMax = min(np.median(Xs)+0.3, max(Xs)+0.1) axes.set_xlim(xMin, xMax) Ys = np.array(allPts[:,1]).astype(np.float) YErrs = np.array(allPts[:,3]).astype(np.float) yMin = min(np.median(Ys)-0.3, min(Ys)) yMax = max(np.median(Ys)+0.3, max(Ys)) axes.set_ylim(yMin, yMax) axes.set_xlabel('[Fe/H]', fontsize=18) if ion != 26.0: axes.set_ylabel('['+yElem+'/Fe]', fontsize=18) else: axes.set_ylabel('['+yElem+'/H]', fontsize=18) if groupErrors: axes.scatter(gFeAbs, gAbs, marker='o', color='r') eb = axes.errorbar(gFeAvg, gAvg, xerr=gFeStd,\ linestyle='None', markersize=12., marker='H', color='r', ecolor='r', \ label='Giant Mean', capsize=10., elinewidth=2, markerfacecolor='None') eb[-1][0].set_linestyle('--') # eb[-1][1].set_linestyle('--') eb[-1][0].set_linewidth(2.) # eb[-1][1].set_linewidth(2.) axes.scatter(dFeAbs, dAbs, marker='o', color='b') eb = axes.errorbar(dFeAvg, dAvg, xerr=dFeStd,\ linestyle='None', markersize=12., marker='H', color='b', ecolor='b', \ label='Dwarf Mean', capsize=10., elinewidth=2, markerfacecolor='None') eb[-1][0].set_linestyle('--') # eb[-1][1].set_linestyle('--') eb[-1][0].set_linewidth(2.) # eb[-1][1].set_linewidth(2.) else: eb = axes.errorbar(Xs, Ys, yerr=YErrs, xerr=XErrs,\ linestyle='None', marker='o', ecolor=allPts[:,4]) eb[-1][0].set_linestyle(':') eb[-1][1].set_linestyle(':') eb[-1][0].set_linewidth(0.5) eb[-1][1].set_linewidth(0.5) axes.legend() pyplot.savefig(dirs.RelAbsDir+'Fe_'+yElem+fileTag+'.png') pyplot.close()
def evaluateParams(FeILines, FeIILines, TiILines, TiIILines): # The evaluation score is the product of the p-values for matching # I and II ionization state abundances, and having a slope of 0.0 # (ie: no correlation between) excitation potential and measured # abundance for a given line. # # Note that we are being VERY loose with our definition of "probabilities" # Specifically, we are using the P-score of the linear regression and of # the T-Test as a probability. This is technically incorrect, as the # P-score should really only be used for rejection of a null hypothesis # that the abundance vs. excitation potential slope is zero, or that the # two populations have the same mean. # Since we are really only interested in getting a relative scoring for the # quality of the linear fit to a zero slope, and the quality of the match # of the abundances of the two population, the use of a P-score as a # scoring mechanism is valid. if len(FeILines) < k.MinNumStatLines: print('Warning: Only {0:2d} FeI Lines!'.format(len(FeILines))) # If the number is _really_ small, we realistically can't do anything... if len(FeILines) < k.MinNumStatLines/5 or not u.is_list(FeILines): return 0., 0. FeIExPotList = np.array(FeILines)[:,1].tolist() FeIAbList = np.array(FeILines)[:,5].tolist() FeSlope, intercept, r_value, FeP_value, stderr = stats.linregress(FeIExPotList,FeIAbList) if len(FeIILines) < k.MinNumStatLines/2: # Not enough FeII lines, so we have to assume that the Fe I abundance is definitive FeAbTProb = k.BadProbability else: FeIIAbList = np.array(FeIILines)[:,5].tolist() FeAbTScore, FeAbTProb = stats.ttest_ind(FeIAbList, FeIIAbList) if len(TiILines) < k.MinNumStatLines/2: # Not enough TiI lines, so we will just use the Fe I line slope TiP_value = k.BadProbability TiAbTProb = k.BadProbability else: TiIExPotList = np.array(TiILines)[:,1].tolist() TiIAbList = np.array(TiILines)[:,5].tolist() TiSlope, intercept, r_value, TiP_value, stderr = stats.linregress(TiIExPotList,TiIAbList) if len(TiIILines) < k.MinNumStatLines/4: # Not enough TiII lines, so we will just use the Fe I/II comparison TiAbTProb = k.BadProbability else: TiIIAbList = np.array(TiIILines)[:,5].tolist() TiAbTScore, TiAbTProb = stats.ttest_ind(TiIAbList, TiIIAbList) if not u.is_number(TiAbTProb): TiAbTProb = k.BadProbability # Returns slope probability, ionization balance probability # Note that python floating point calculations should treat # any value of around 10**-16 as zero, so we force calculations # with values of < 10**-14 to 0.0 # Testing with Fe Only: # slopeProb = FeP_value*TiP_value slopeProb = FeP_value if slopeProb < k.BadProbability/100.: slopeProb = 0. # I'm not sure I like using the Ti I/I abundance balance (NLTE effects?) # Weight Fe by 2x over Ti: balanceProb = (FeAbTProb**2*TiAbTProb)**(1./3.) # balanceProb = np.sqrt(FeAbTProb*TiAbTProb) # balanceProb = FeAbTProb if balanceProb < k.BadProbability/100.: balanceProb = 0. return slopeProb, balanceProb