def MakeErrorTable(baseGs, baseDs, altGs, altDs, outfile=None): if outfile is not None: fp = open(outfile, 'a') else: fp = None DataOut(latexHead, fp=fp) dElems = np.array(sorted(baseDs.keys())) gElems = np.array(sorted(baseGs.keys())) # 19 element/ion colums will fit on a sideways table page # Note: Assume the giants and dwarfs _should_ have the same number of ions halfway = int(round(len(dElems) / 2 + 0.1, 0)) # F*ing Python floating points! DataOut(r'r' * halfway + '} \n', fp=fp) for ionSet, sType, baseAbs, abSet in [(dElems[:halfway], 'Dwarf', baseDs, altDs), \ (gElems[:halfway], 'Giant', baseGs, altGs), \ (dElems[halfway:], 'Dwarf', baseDs, altDs), \ (gElems[halfway:], 'Giant', baseGs, altGs)]: # Do the column headers once for the Dwarfs, only if sType == 'Dwarf': columnHead = r'\multicolumn{1}{l}{Parameter} ' for ion in ionSet: columnHead = columnHead + r'& \multicolumn{{1}}{{c}}{{{0}}} '.format( el.getIonName(ion)) DataOut(columnHead + r'\\{0}\hline{0}'.format('\n'), fp=fp) DataOut(r'\multicolumn{{{0:2d}}}{{|c|}}{{{1}s}}\\{2}\hline{2}'.format( len(ionSet) + 1, sType, '\n'), fp=fp) for parmVar in abSet.keys(): rowData = r'\multicolumn{{1}}{{|l|}}{{{0}}}'.format(parmVar) for ion in ionSet: rowData = rowData + r' & \multicolumn{{1}}{{r|}}{{{0:1.2f}}}'.format( abSet[parmVar][ion] - baseAbs[ion]) DataOut(rowData + r'\\{0}'.format('\n'), fp=fp) DataOut(r'\hline {1}\multicolumn{{1}}{{|l|}}{{{0} Totals}}'.format( sType, '\n'), fp=fp) for ion in ionSet: subtotal = np.sqrt(sum([max((abSet[RowHeaders[2*i]][ion]-baseAbs[ion])**2, \ (abSet[RowHeaders[2*i+1]][ion]-baseAbs[ion])**2 \ ) for i in [0,1,2]])) DataOut(r' & \multicolumn{{1}}{{r|}}{{{0:1.2f}}}'.format(subtotal), fp=fp) DataOut(r'\\{0}\hline{0}'.format('\n'), fp=fp) DataOut(latexFoot, fp=fp) if fp: fp.close() return
def MakeOneLogGPlot(logGPts, abPts, starName='', fileTag=''): # Draw a logG plot for a single star. # We want to use a couple of np.array tricks, so... if len(logGPts) < 2 or len(abPts) < 2: return Xs = np.array(logGPts) Ys = np.array(abPts) ax = pyplot.gca() pyplot.scatter(Xs, Ys) pyplot.axhline(0.0, linestyle=':') interpGs = np.interp([0.1, 0., -0.1], -Ys, Xs) pyplot.plot(Xs, Ys, label=r'${0}({1:4.2f}^{{+{2:4.2f}}}_{{-{3:4.2f}}}$)'.\ format(el.getIonName(22.0),interpGs[1],\ interpGs[1]-interpGs[2],\ interpGs[0]-interpGs[1])) ax.set_xlabel(r'$Log(G)$') ax.set_ylabel('[TiI/TiII]') pyplot.legend() pyplot.savefig(k.ParmPlotDir + 'Logg/' + starName + fileTag + '_logG.png') pyplot.close()
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 QualityPlot(points, starName, ion, fileTag='', plotTitle='', pointLabels=None): # Plot an [X/H]vs.line strength plot, with the points colored by "quality" - # or how well they correspond to the linear fit (along the linear section of # the COG) of other measurements with similar excitation potential values. # The linear portion of the CoG is modeled by an Orthogonal Data Reduction (ODR) # using a linear function (from sp.odr). # The quality of a point is measured as an inverse of its distance to the linear # fit as measured by the ODR. # The passed data, in the array 'points' is of the form: # [wl, Ex.Pot., Log(gf), eqw, Log(eqw/wl), [X/H]] # For now, just bailing if no points were passed nPoints = len(points) if nPoints == 0: return # assert nPoints>0 # This abSTR measure is basically the log10 of the gravity*abundance*temp abStrs = np.array( [line[5] + line[2] + np.log10(line[0]) for line in points]) # We're rounding 'cause...Python. XPs = np.around(points[:, 1], 4) minXP = min(XPs) maxXP = max(XPs) uniqueXPs = sorted(set(XPs)) XPDelta = maxXP - minXP normedXPs = [(xp - minXP) / XPDelta for xp in XPs] # Arrange points to analyze: # I just want you to be confused by the different indices pointData = np.array( zip(abStrs, points[:, 4], XPs, points[:, 5], points[:, 3])) # Bin our points by nearby XPs XPBins = [uniqueXPs[0]] for xp in uniqueXPs: if xp > XPBins[-1] + k.evBinSize: XPBins.append(xp) # We'll weight our linear COG fits by the individual points' [X/H] variance # Note: we'll change the median once we 'weed out' measurements outside of # the linear portion of the CoG. abMed = np.median(points[:, 5]) # abVar = np.std(points[:,5]) linFits = {} plotPoints = {} minminErr = 10. maxmaxErr = 0. for xp in XPBins: fitPoints = np.array([ p for p in pointData if p[2] >= xp and p[2] <= xp + k.evBinSize and p[1] < k.cogPlotLimit - xp * k.cogCorrFactor ]) # fitPoints = np.array([p for p in pointData if p[2]>=xp and p[2]<=xp+k.evBinSize]) if fitPoints.shape[0] < 2: linFits[xp] = [] plotPoints[xp] = [] continue # Weight = distance to group median - max = 100 (ie: 1/sigma <=100) deltas = [abs(ab - abMed) for ab in fitPoints[:, 3]] pointWeights = u.normalize( [1. / (500. * d) if d > 0.002 else 1. for d in deltas]) # The linfits dictionary entry will now contain: # [[Linear fit coefficients], [parameter estimated errors], [covariance matrix], # [estimated error in x], [estimated error in y]] linFits[xp], coeffErrs, covariance, xErrs, yErrs = u.odRegress( fitPoints[:, 0], fitPoints[:, 1], weights=pointWeights) pointErrs = [np.sqrt(p[0]**2 + p[1]**2) for p in zip(xErrs, yErrs)] plotPoints[xp] = np.array( zip(fitPoints[:, 3], fitPoints[:, 1], pointErrs, fitPoints[:, 2], pointWeights)) minErr = min(pointErrs) maxErr = max(pointErrs) if maxErr > maxmaxErr: maxmaxErr = maxErr if minErr < minminErr: minminErr = minErr # Calculate the point 'score' based on priors deltaErr = maxmaxErr - minminErr for xp in XPBins: if len(plotPoints[xp]) == 0: continue # Normalize the errors for the first prior normedErrs = np.array([(pe - minminErr) / deltaErr for pe in plotPoints[xp][:, 2]]) # Normalized XP for second prior, however, we want 0.0eV to be highest # values, and the highest XP to be valued no lower than 0.5 normedXPs = np.array([ 1. - ((px - minXP) / XPDelta) / 2. for px in plotPoints[xp][:, 3] ]) combPriors = u.normalize( np.array([ (ps[0] * (ps[1]**2) * ps[2])**0.25 for ps in zip(normedErrs, normedXPs, plotPoints[xp][:, 4]) ])) plotPoints[xp] = np.array( zip(plotPoints[xp][:, 0], plotPoints[xp][:, 1], combPriors)) fig = pyplot.figure() axes = pyplot.gca() # Y axis is negative Ymin = min(pointData[:, 1]) * 1.05 Ymax = max(pointData[:, 1]) * 0.95 Xmin = min(pointData[:, 3]) * 0.95 Xmax = max(pointData[:, 3]) * 1.05 if len(points) < 200: pointSize = 9 if pointLabels is not None: # Must have one label for each point (even if it is '') if len(pointLabels) < len(abStrs): # Must have labels for all the points pointLabels = None else: pointLabels = None # Seriously, don't label more than 100 points pointSize = 5 allPlotPts = [] # For median/variance calcs. for xp in XPBins: if len(plotPoints[xp]) != 0: pyplot.scatter(plotPoints[xp][:, 0], plotPoints[xp][:, 1], figure=fig, marker='o', s=pointSize, c=1. - plotPoints[xp][:, 2], cmap=pyplot.get_cmap('CMRmap'), edgecolors='None') allPlotPts.extend(plotPoints[xp]) # It's possible that we've weeded a bit too heavily, in which case, # we're done. if len(allPlotPts) < 2: pyplot.close() return abMed = np.median(np.array(allPlotPts)[:, 0]) abVar = np.std(np.array(allPlotPts)[:, 0]) # Plot the median abundance value axes.plot([abMed, abMed], [Ymin, Ymax], linestyle='--', color='r') axes.plot([abMed - abVar, abMed - abVar], [Ymin, Ymax], linestyle=':', color='c') axes.plot([abMed + abVar, abMed + abVar], [Ymin, Ymax], linestyle=':', color='c') pyplot.text(0.65, 0.25, r'{0}({1:3d}): {2:1.3f}+/-{3:1.3f}'.format( el.getIonName(ion), nPoints, abMed, abVar), transform=axes.transAxes, fontsize='smaller') cb = pyplot.colorbar() cb.set_label('Point \"Quality\" (Score)') cb.set_ticks([0., 0.5, 1.0]) # cb.set_ticklabels(['{0:1.2f}'.format(minminErr), '{0:1.2f}'.format(minminErr+(maxmaxErr-minminErr)/2.), '{0:1.2f}'.format(maxmaxErr)]) cb.set_ticklabels(['1.00', '0.50', '0.00']) # Write in a (tiny) label next to each point if pointLabels is not None: for coord in zip(abStrs.tolist(), wls.tolist(), pointLabels): # Place the label below and right of the point pyplot.text(coord[0] + 0.02 * (Xmax - Xmin), coord[1] - 0.03 * (Ymax - Ymin), coord[2], color='k', fontsize='xx-small') # Axes labels and ranges axes.set_ylim([Ymin, Ymax]) axes.set_xlim([Xmin, Xmax]) axes.set_xlabel('[{0}/H]'.format(el.getIonName(ion))) axes.set_ylabel(r'$Log(EQW/\lambda)$') if plotTitle is not '': axes.set_title(plotTitle) saveDirName = dirs.CoGPlotsDir + el.getIonName(ion) + '/' try: os.stat(saveDirName) except: os.mkdir(saveDirName[:-1]) pyplot.savefig('{0}{1}_{2}{3}.png'.format(saveDirName, starName, el.getIonName(ion), fileTag), figure=fig) pyplot.close()
def COGPlot(points, starName, ion, fileTag='', plotTitle='', pointLabels=None, fitXPLines=False): # Plot a curve of growth (COG) # The linear portion of the CoG is modeled by least squares (numpy polyfid for # a 1-d polynomial. # The passed data, in the array 'points' is of the form: # [wl, Ex.Pot., Log(gf), eqw, Log(eqw/wl), [X/H]] # For now, just bailing if no points were passed if len(points) == 0: return assert len(points) > 0 # We'll weight our linear COG fits by the individual points' [X/H] variance abMed = np.median(points[:, 5]) # abVar = np.std(points[:,5]) ## Quick experiment - what does the plot look like if we use the median abundance ## instead of the measured? ## We'll color the points with ex.pot. for this one. # abStrs = np.array([abMed+line[2]+np.log10(line[0]) for line in points]) abStrs = np.array( [line[5] + line[2] + np.log10(line[0]) for line in points]) # We're rounding 'cause...Python. XPs = np.around(points[:, 1], 4) minXP = min(XPs) maxXP = max(XPs) uniqueXPs = sorted(set(XPs)) deltaXP = maxXP - minXP # Arrange points to analyze: # I just want you to be confused by the different indices pointData = np.array( zip(abStrs, points[:, 4], XPs, points[:, 5], points[:, 3], points[:, 0])) linFits = {} plotPoints = {} XPBins = [uniqueXPs[0]] for xp in uniqueXPs: if xp > XPBins[-1] + k.evBinSize: XPBins.append(xp) minminErr = 10. maxmaxErr = 0. for xp in XPBins: fitPoints = np.array( [p for p in pointData if p[2] >= xp and p[2] <= xp + k.evBinSize]) if fitPoints.shape[0] < 3: linFits[xp] = None plotPoints[xp] = None continue # Weight = distance to group median - max = 100 (ie: 1/sigma <=100) deltas = [(abs(ab - abMed))**2 for ab in fitPoints[:, 3]] pointWeights = [1. / (500. * d) if d > 0.002 else 1. for d in deltas] # The linfits dictionary entry will now contain: # [[Linear fit coefficients], [parameter estimated errors], [covariance matrix], # [estimated error in x], [estimated error in y]] linFits[xp], coeffErrs, covariance, xErrs, yErrs = u.odRegress( fitPoints[:, 0], fitPoints[:, 1], weights=pointWeights) pointErrs = [np.sqrt(p[0]**2 + p[1]**2) for p in zip(xErrs, yErrs)] plotPoints[xp] = np.array( zip(fitPoints[:, 0], fitPoints[:, 1], pointErrs, fitPoints[:, 5])) minErr = min(pointErrs) maxErr = max(pointErrs) if maxErr > maxmaxErr: maxmaxErr = maxErr if minErr < minminErr: minminErr = minErr # Normalize the errors for plotting deltaErr = maxmaxErr - minminErr for xp in XPBins: if plotPoints[xp] == None: continue pointErrs = plotPoints[xp][:, 2] normedErrs = np.array([(pe - minminErr) / deltaErr for pe in pointErrs]) plotPoints[xp] = np.array( zip(plotPoints[xp][:, 0], plotPoints[xp][:, 1], normedErrs, plotPoints[xp][:, 3])) fig = pyplot.figure() axes = pyplot.gca() # Y axis is negative Xmin = min(pointData[:, 0]) * 1.1 Xmax = max(pointData[:, 0]) * 0.9 Xmed = np.median(pointData[:, 0]) Ymin = min(pointData[:, 1]) * 0.9 Ymax = max(pointData[:, 1]) * 1.1 legendCount = 0 # fp =open('/home/mikelum/Dropbox/CodeCloud/MyTools/ClusterAnalysis/Plots/slopes.txt','a') for xp in XPBins: if plotPoints[xp] is None: continue # fp.write('---------------\n{0} {1:1.2f}eV ({2:2d}): {3:2.3f}\n '.format(el.getIonName(ion), xp, len(plotPoints[xp]), linFits[xp][0])) # Plot the fit minX = min(plotPoints[xp][:, 0]) minY = linFits[xp][0] * minX + linFits[xp][1] maxX = max(plotPoints[xp][:, 0]) maxY = linFits[xp][0] * maxX + linFits[xp][1] normedXP = ((xp - minXP) / deltaXP) plt = axes.plot([minX, maxX], [minY, maxY], color=pyplot.get_cmap('CMRmap')(normedXP)) # Plot the points: # Color by distance to fit: # axes.scatter(plotPoints[xp][:,0], plotPoints[xp][:,1], figure=fig, marker='o', s=8, c=plotPoints[xp][:,2], cmap=pyplot.get_cmap('CMRmap'), edgecolors='None') # Color by Ex. Pot. axes.scatter(plotPoints[xp][:, 0], plotPoints[xp][:, 1], figure=fig, marker='o', s=8, color=pyplot.get_cmap('CMRmap')(normedXP), edgecolors='None') # Legend Key axes.text(0.75, 0.35 - legendCount * 0.05, r'{0:1.2f}eV: {1:2.3f}'.format(xp, linFits[xp][0]), transform=axes.transAxes, color=pyplot.get_cmap('CMRmap')(normedXP), fontsize='smaller') legendCount += 1 # slopes = np.array([[(p[3],(p[1]-a[1])/(p[0]-a[0])) if (p[0]-a[0]) != 0. else (p[3],float('nan')) for p in plotPoints[xp]] for a in plotPoints[xp]]) # diagIndex = 0 # for p in slopes: # var = abs(linFits[xp][0]/np.nanmean(p[:,1])) # if var > 2. or var< 0.5: # fp.write(' -**') # fp.write('{0:4.3f}:{1:2.3f}'.format(p[diagIndex,0], np.nanmean(p[:,1]))) # if var > 2. or var< 0.5: # fp.write('**- ') # else: # fp.write(' ') # diagIndex += 1 # fp.write('\n') # fp.close() # Plot the linear CoG limit axes.plot([4, 14], [k.cogPlotLimit, k.cogPlotLimit], linestyle=':') # cb = pyplot.colorbar() # cb.set_label('Excitation Potential (eV)') # cb.set_ticks([0., 0.5, 1.0]) # cb.set_ticklabels(['{0:1.2f}'.format(minXP), '{0:1.2f}'.format(minXP+(maxXP-minXP)/2.), '{0:1.2f}'.format(maxXP)]) # Write in a (tiny) label next to each point if pointLabels is not None: for coord in zip(abStrs.tolist(), XPs.tolist(), pointLabels): # Place the label below and right of the point axes.text(coord[0] + 0.02 * (Xmax - Xmin), coord[1] - 0.03 * (Ymax - Ymin), coord[2], color='k', fontsize='xx-small') # Axes labels and ranges axes.set_ylim([Ymin, Ymax]) axes.set_xlim([Xmin, Xmax]) axes.set_xlabel(r'$Log(A*gf*\lambda)$') axes.set_ylabel(r'$Log(EQW/\lambda)$') if plotTitle is not '': axes.set_title(plotTitle) saveDirName = dirs.CoGPlotsDir + el.getIonName(ion) + '/' try: os.stat(saveDirName) except: os.mkdir(saveDirName[:-1]) pyplot.savefig('{0}{1}_{2}{3}.png'.format(saveDirName, starName, el.getIonName(ion), fileTag), figure=fig) pyplot.close()
def AbSTRPlot(starName, ion, points, redSet=np.array([]), greenSet=np.array([]), blueSet=np.array([]), lowLimit=None, hiLimit=None, fileTag='', plotTitle='', labelPoints=None): # For now, just bailing if no points were passed if len(points) == 0: return assert len(points) > 0 # Labels? blackLabels = [] redLabels = [] greenLabels = [] blueLabels = [] # Plot the passed (np.array) point array in an external file abundances = points[:, 0] STRs = points[:, 1] # Xmax = max(abundances) # Xmin = min(abundances) Ymin = min(STRs) Ymax = max(STRs) # # Use an arbitrary Solar+1.0/-1.5 in [X/H] space for the plot limits # solarAB = el.atnoLU(int(ion))[3] # pyplot.axis([np.round(solarAB-0.5,1), np.round(solarAB+1.0,1), np.round(Ymin,1)-0.5, np.round(Ymax,1)+0.5]) axes = pyplot.gca() if len(points) < 500: pointSize = 5 if labelPoints is not None: # Must have one label for each point (even if it is '') if len(labelPoints) < len(abundances): # Must have labels for all the "black" (data) points labelPoints = None else: # Note that array slicing will automatically return empty members # for indices beyond the sliced array length blackLabels = labelPoints[:len(abundances)] redLabels = labelPoints[len(abundances):len(abundances) + len(redSet)] greenLabels = labelPoints[len(abundances) + len(redSet):len(abundances) + len(redSet) + len(greenSet)] blueLabels = labelPoints[len(abundances) + len(redSet) + len(greenSet):len(abundances) + len(redSet) + len(greenSet) + len(blueSet)] else: labelPoints = None # Seriously, don't label more than 30 points pointSize = 3 pyplot.scatter(abundances, STRs, marker='.', s=pointSize + 2) # Write in a (tiny) wavelength reference next to each point if len(blackLabels) > 0: for coord in zip(abundances.tolist(), STRs.tolist(), blackLabels): # Place the label below and right of the point pyplot.text(coord[0] + 0.02, coord[1] - 0.03, coord[2], color='k', fontsize='xx-small') if len(redSet) > 0: if len(redSet) < 30: pointSize = 5 else: pointSize = 3 redAbs = redSet[:, 0] redSTRs = redSet[:, 1] Ymin = min(Ymin, min(redAbs)) Ymax = max(Ymax, max(redSTRs)) pyplot.scatter(redAbs, redSTRs, marker='x', color='red', s=pointSize) for i in range(len(redLabels)): pyplot.text(redSet[i, 0] + 0.02, redSet[i, 1] - 0.03, redLabels[i], color='r', fontsize='xx-small') if len(greenSet) > 0: if len(greenSet) < 30: pointSize = 5 else: pointSize = 3 greenAbs = greenSet[:, 0] greenSTRs = greenSet[:, 1] Ymin = min(Ymin, min(greenAbs)) Ymax = max(Ymax, max(greenSTRs)) pyplot.scatter(greenAbs, greenSTRs, marker='x', color='green', s=pointSize) for i in range(len(greenLabels)): pyplot.text(greenSet[i, 0] + 0.02, greenSet[i, 1] - 0.03, greenLabels[i], color='g', fontsize='xx-small') if len(blueSet) > 0: if len(blueSet) < 30: pointSize = 5 else: pointSize = 3 blueAbs = blueSet[:, 0] blueSTRs = blueSet[:, 1] Ymin = min(Ymin, min(blueAbs)) Ymax = max(Ymax, max(blueSTRs)) pyplot.scatter(blueAbs, blueSTRs, marker='x', color='blue', s=pointSize) for i in range(len(blueLabels)): pyplot.text(blueSet[i, 0] + 0.02, blueSet[i, 1] - 0.03, blueLabels[i], color='b', fontsize='xx-small') # DEBUGGING # axes.set_ylim([min(STRs)-0.1, max(STRs)+0.1]) axes.set_xlim([min(abundances) - 0.1, max(abundances) + 0.1]) axes.set_ylim([np.round(Ymin, 1) - 0.2, np.round(Ymax, 1) + 0.2]) axes.set_xlabel('[{0}/H]'.format(el.getIonName(ion))) axes.set_ylabel('STR. value') if plotTitle is not '': axes.set_title(plotTitle) # Detection Limit? if lowLimit is not None: detXs = np.array([min(abundances) - 1.0, max(abundances) + 1.0]) detYs = lowLimit[0] * detXs + lowLimit[1] pyplot.plot(detXs.tolist(), detYs.tolist(), 'k--') # CoG Limit? if hiLimit is not None: detYs = hiLimit[0] * detXs + hiLimit[1] pyplot.plot(detXs.tolist(), detYs.tolist(), 'k-.') # Plot the best-fit abundance line # Note: We're trying to fit a (hopefully) vertical line, which is ummmm... # ...bad for typical linear regression methods. So, we swap X and Y, and # pretend we're fitting a horizontal line (which also give us the ability to # use p-values to claim "vertical-ness" allPoints = zip(STRs.tolist(), abundances.tolist()) # abFitPoints = np.array([point for point in allPoints if point[0]>(lowLimit[0]*point[1] + lowLimit[1])]) abFitPoints = np.array(allPoints) # avgExPot = np.mean(abFitPoints[:,0]) # Red = Low corrections # weightArray = [10.0*(4.0-abs(avgExPot-x)) for x in abFitPoints[:,0]] # abSlope, abIntercept = sp.polyfit(abFitPoints[:,0], abFitPoints[:,1], 1, w=weightArray) # pyplot.text(0.80, 0.9, 'slope={0:5.1f}\n[{1}/H]={2:1.2f}+/-{3:1.2f}'.format(1./abSlope, el.getIonName(ion), np.mean(abundances), np.std(abundances)), transform=axes.transAxes, color='r', fontsize='smaller') # detYs = np.array([np.round(Ymin,1)-0.5, np.round(Ymax,1)+0.5]) # detXs = abSlope*detYs + abIntercept # pyplot.plot(detXs.tolist(), detYs.tolist(), 'r:') # Green = unweighted fit # abSlope, abIntercept, rv, pv, err = sp.stats.linregress(abFitPoints[:,0], abFitPoints[:,1]) # pyplot.text(0.80, 0.9, 'slope={0:5.1f}\nR^2-value={1:1.4f}\n[{2}/H]={3:1.2f}+/-{4:1.2f}({5:3d})'.format(1./abSlope, rv**2, el.getIonName(ion), np.mean(abundances), np.std(abundances),len(abundances)), transform=axes.transAxes, color='g', fontsize='smaller') if len(redSet) > 0: pyplot.text(0.75, 0.95, '[{0}/H]={1:1.2f}+/-{2:1.2f}({3:3d})'.format( el.getIonName(ion), np.mean(redAbs), np.std(redAbs), len(redSet)), transform=axes.transAxes, color='r', fontsize='smaller') # else: # pyplot.text(0.75, 0.95, '(No data)', transform=axes.transAxes, color='r', fontsize='smaller') if len(greenSet) > 0: pyplot.text(0.75, 0.90, '[{0}/H]={1:1.2f}+/-{2:1.2f}({3:3d})'.format( el.getIonName(ion), np.mean(greenAbs), np.std(greenAbs), len(greenSet)), transform=axes.transAxes, color='g', fontsize='smaller') # else: # pyplot.text(0.75, 0.90, '(No data)', transform=axes.transAxes, color='g', fontsize='smaller') if len(blueSet) > 0: pyplot.text(0.75, 0.85, '[{0}/H]={1:1.2f}+/-{2:1.2f}({3:3d})'.format( el.getIonName(ion), np.mean(blueAbs), np.std(blueAbs), len(blueSet)), transform=axes.transAxes, color='b', fontsize='smaller') # else: # pyplot.text(0.75, 0.85, '(No Data)', transform=axes.transAxes, color='b', fontsize='smaller') pyplot.text(0.75, 0.80, '[{0}/H]={1:1.2f}+/-{2:1.2f}({3:3d})'.format( el.getIonName(ion), np.mean(abundances), np.std(abundances), len(abundances)), transform=axes.transAxes, color='k', fontsize='smaller') # detYs = np.array([np.round(Ymin,1)-0.5, np.round(Ymax,1)+0.5]) # detXs = abSlope*detYs + abIntercept # pyplot.plot(detXs.tolist(), detYs.tolist(), 'g:') # Do the same for just the points in the linear region of the CoG # linearPoints = np.array([point for point in allPoints if point[0]<(hiLimit[0]*point[1] + hiLimit[1])]) # abSlope, abIntercept, rv, pv, err = sp.stats.linregress(linearPoints[:,0], linearPoints[:,1]) # pyplot.text(0.50, 0.9, 'slope={0:5.1f}\nR^2-value={1:1.4f}\[email protected]={2:1.2f}'.format(1./abSlope, rv**2, abIntercept), transform=axes.transAxes, color='g', fontsize='smaller') # detXs = abSlope*detYs + abIntercept # pyplot.plot(detXs.tolist(), detYs.tolist(), 'g:') # pyplot.xlabel('[{0}/H]'.format(el.getIonName(ion))) # pyplot.ylabel('Ex.Pot.') saveDirName = dirs.XPAbPlotsDir + el.getIonName(ion) + '/' try: os.stat(saveDirName) except: os.mkdir(saveDirName[:-1]) pyplot.savefig('{0}{1}_{2}{3}.png'.format(saveDirName, starName, el.getIonName(ion), fileTag)) pyplot.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 PlotClusterAbs(clusterName='NGC-0752', ionList=kAllIonList, fileTag='', mass=1.2, metallicity=0.0, solarRelative=False, referenceCorrect=False): giantParms = GetGiantStarParms(clusterName=clusterName,\ mass=mass, metallicity=metallicity) modelFiles = mk.findDataFiles(k.GiantModelPath) gAtms, gPradks = mk.LoadModels(modelFiles) modelFiles = mk.findDataFiles(k.DwarfModelPath) dAtms, dPradks = mk.LoadModels(modelFiles) gAbs = GetAbsForStars(giantParms,\ gModelAtms=gAtms, gPradks=gPradks,\ dModelAtms=dAtms, dPradks=dPradks,\ referenceCorrect=referenceCorrect) gIons = sorted([ion for ion in gAbs.keys() if ion in ionList]) if solarRelative: gElems = [gAbs[i][0] for i in gIons] else: solarFeH = PA.ptoe[25][PA.abIdx] starIons = gAbs.keys() starFeH = GetStarFeH(gAbs) gElems = [ gAbs[i][0] - PA.ptoe[int(i) - 1][PA.abIdx] - starFeH for i in gIons ] gVar = [gAbs[i][1] for i in gIons] dwarfParms = GetDwarfStarParms(clusterName=clusterName,\ mass=mass, metallicity=metallicity) dAbs = GetAbsForStars(dwarfParms,\ gModelAtms=gAtms, gPradks=gPradks,\ dModelAtms=dAtms, dPradks=dPradks,\ referenceCorrect=referenceCorrect) dIons = sorted([ion for ion in dAbs.keys() if ion in ionList]) if solarRelative: dElems = [dAbs[i][0] for i in dIons] else: # solarFeH = PA.ptoe[25][PA.abIdx] - calculated in giants, above starIons = dAbs.keys() starFeH = GetStarFeH(dAbs) dElems = [ dAbs[i][0] - PA.ptoe[int(i) - 1][PA.abIdx] - starFeH for i in dIons ] dVar = [dAbs[i][1] for i in dIons] ionLUT = {} for num, ion in enumerate(sorted(set(dIons + gIons))): ionLUT[ion] = num ionLabels = [' -', ' '] for ion in sorted(ionLUT.keys()): ionLabels.append(el.getIonName(ion)) ionLabels.append(' ') fig = pyplot.figure() ax = fig.gca() ax.errorbar([ionLUT[ion] for ion in gIons], gElems, yerr=gVar, fmt='rs',\ label=clusterName+' giants') ax.errorbar([ionLUT[ion] for ion in dIons], dElems, yerr=dVar, fmt='bo',\ label=clusterName+' dwarfs') ax.xaxis.set_major_locator(pyplot.MultipleLocator(1)) ax.set_xticklabels(ionLabels, rotation='vertical') ax.set_xlabel('Ion') ax.set_xlim(left=-1, right=len(ionLUT.keys())) if solarRelative: ax.set_ylabel('[X/H]') else: ax.set_ylabel('[X/Fe]') # ax.set_ylim(bottom=-0.4, top=0.5) if not solarRelative: ax.set_ylim(bottom=np.average(gElems + dElems) - 0.5, top=np.average(gElems + dElems) + 0.5) else: ax.set_ylim(bottom=0, top=9) ax.legend(numpoints=1) ax.axhline(y=0.0, xmin=-1, xmax=len(ionLUT.keys()), color='g', linestyle='--') # pyplot.show() pyplot.savefig(dirs.PlotDir + clusterName + 'Abs' + fileTag + '.png') pyplot.close() return
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 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)
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 PlotAllCombos(): abTable=STP.GetAbTable() ionsToCombine=[6.0,7.0,8.0,11.0,12.0,13.0,14.0,20.0,22.0,26.0,63.1] allCombos = u.Cartesian(ionsToCombine,ionsToCombine) # allCombos = u.Cartesian(STP.kAllIonList, STP.kAllIonList) elemCombos = np.array([i for i in allCombos if i[0]<i[1]]) SolarFe = PA.ptoe[25][PA.abIdx] for combo in elemCombos: Xs = [] Ys = [] XErrs = [] YErrs = [] colors = [] for star in abTable.keys(): starAbs = abTable[star] if combo[0] in starAbs.keys() and combo[1] in starAbs.keys(): starFe = 0.75*starAbs[26.0][0] + 0.25*starAbs[26.1][0] - SolarFe SolarX = PA.ptoe[int(combo[0])-1][PA.abIdx] Xs.append(starAbs[combo[0]][0] - starFe - SolarX) XErrs.append(starAbs[combo[0]][1]) SolarY = PA.ptoe[int(combo[1])-1][PA.abIdx] Ys.append(starAbs[combo[1]][0] - starFe - SolarY) YErrs.append(starAbs[combo[1]][1]) colors.append(ColorLookup(star)) slope, intercept, rVal, pVal, stderr = linregress(Xs, Ys) xElem = EL.getIonName(combo[0]) yElem = EL.getIonName(combo[1]) fig = pyplot.figure() ax = fig.gca() for pt in zip(Xs, Ys, XErrs, YErrs, colors): if pt[4] == 'm' or pt[4]=='c': shape='s' else: shape='o' eb = pyplot.errorbar(pt[0], pt[1], yerr=pt[3], xerr=pt[2],\ linestyle='None', marker=shape, color=pt[4]) eb[-1][0].set_linestyle('--') eb[-1][1].set_linestyle('--') minX = min(Xs) maxX = max(Xs) pyplot.plot([minX,maxX],[intercept+slope*minX, intercept+slope*maxX], 'k:') xMin = min(np.median(Xs)-0.5, minX) xMax = max(np.median(Xs)+0.5, maxX) ax.set_xlim(xMin, xMax) yMin = min(np.median(Ys)-0.5, min(Ys)) yMax = max(np.median(Ys)+0.5, max(Ys)) ax.set_ylim(yMin, yMax) pyplot.xlabel('['+xElem+'/Fe]') pyplot.ylabel('['+yElem+'/Fe]') ax.text(0.95, 0.01, 'Slope:{0:4.2f}, R-squared:{1:4.2f}, P-val:{2:4.2f}'.format(slope,rVal**2,pVal), fontsize=10, verticalalignment='bottom', horizontalalignment='right', transform=ax.transAxes,) pyplot.savefig(dirs.RelAbsDir+xElem+'_'+yElem+'.png') pyplot.close()
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 MakeTeffIonPlots(clusterName='NGC-0752', starDataList=None, fileTag='', filterBlends=False, referenceCorrect=False, useDAOSpec=False): # Function plots Teff vs. [TiI/TiII] for a range of temperatures. # 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) gModelFiles = mk.findDataFiles(k.GiantModelPath) gModelAtms, gPradks = mk.LoadModels(gModelFiles) # Want to watch TiI/TiII ions = [22.0, 22.1] abDict = {} dTeffRange = np.linspace(4500, 7000, 101) gTeffRange = np.linspace(3500, 6000, 101) for TeffIdx in range(len(dTeffRange)): tempParmList = [] for s in starDataList: if s[1] < k.giantTeffLimit and s[2] < k.giantLogGLimit: Teff = gTeffRange[TeffIdx] else: Teff = dTeffRange[TeffIdx] tempParmList.append((s[0], Teff, s[2], s[3], s[4], s[5], s[6])) abDict[Teff] = STP.GetAbTable(clusterName=clusterName, starDataList=tempParmList, ions=ions, filterBlends=filterBlends, referenceCorrect=referenceCorrect, useDAOSpec=useDAOSpec, gModelAtms=gModelAtms, gPradks=gPradks, dPradks=dPradks, dModelAtms=dModelAtms) starPoints = {} for Teff in abDict.keys(): for star in abDict[Teff].keys(): if star not in starPoints.keys(): starPoints[star] = {} # TiI/TiII points: if 22.0 in abDict[Teff][star].keys() and \ 22.1 in abDict[Teff][star].keys(): if 22.0 not in starPoints[star].keys(): starPoints[star][22.0] = {} starPoints[star][22.0][Teff] =\ abDict[Teff][star][22.0][0] - abDict[Teff][star][22.1][0] for star in starPoints.keys(): fig = pyplot.figure() starData = [s for s in starDataList if s[0] == star] isGiant = False if len(starData) > 0: isGiant = STP.isGiantStar(starData[0][1:]) for ion in starPoints[star].keys(): Xs = np.array(sorted(starPoints[star][ion].keys())) Ys = np.array([starPoints[star][ion][x] for x in Xs]) if isGiant: Xs = Xs - 1000. interpTs = np.interp([-0.1, 0., 0.1], Ys, Xs) pyplot.scatter(Xs, Ys, label=r'${0}({1:4.0f}^{{+{2:3.0f}}}_{{-{3:3.0f}}}$)'.\ format(el.getIonName(ion),interpTs[1],\ interpTs[1]-interpTs[0],\ interpTs[2]-interpTs[1]), marker='.') pyplot.axhline(0.0, linestyle=':') ax = pyplot.gca() ax.set_xlabel(r'$T_{{eff}}$') ax.set_ylabel('[TiI/TiII]') pyplot.legend() pyplot.savefig(k.ParmPlotDir + 'Teff/' + star + fileTag + '_TiRel.png') pyplot.close()
def XPAbPlot(points, starName, ion, fileTag='', plotTitle='', pointLabels=None, showTrendLine=False): # Plot the Excitation potential vs abundance for the passed points. # The passed data, in the array 'points' is of the form: # [[Ex. Pot, [X/H], EQW (mA), wl](A), ...] # For now, just bailing if no points were passed if len(points) == 0: return assert len(points) > 0 # We're rounding 'cause...Python. XPs = np.around(points[:, 0], 4) Abs = points[:, 1] fig = pyplot.figure() axes = pyplot.gca() Xmin = min(XPs) * 0.9 if Xmin == 0.: Xmin = -0.25 Xmax = max(XPs) + 0.25 Ymin = min(Abs) - 0.2 Ymax = max(Abs) + 0.2 pyplot.scatter(XPs, Abs, figure=fig, marker='o', s=9) # Write in a (tiny) label next to each point if pointLabels is not None: for coord in zip(XPs.tolist(), Abs.tolist(), pointLabels): # Place the label below and right of the point pyplot.text(coord[0] + np.random.random() * 0.04 * (Xmax - Xmin), coord[1] - np.random.random() * 0.06 * (Ymax - Ymin), coord[2], color='k', fontsize='xx-small') # Fit a line, if desired if showTrendLine: slope, intercept, rVal, pVal, err = sp.stats.linregress(XPs, Abs) pyplot.plot([Xmin, Xmax], [intercept + slope * Xmin, intercept + slope * Xmax], 'g:') axes.text(0.95, 0.01, 'Slope:{0:4.2f}, R-squared:{1:4.2f}'.format\ (slope,rVal**2), fontsize=9, verticalalignment='bottom',\ horizontalalignment='right', transform=axes.transAxes,) # Show mean and standard deviation range: mean = np.mean(Abs) std = np.std(Abs) axes.axhline(y=mean, ls='dashed', color='r', label=r'$[{0}/H]:{1:4.2f}\pm{2:4.2f}$'.format( el.getIonName(ion), mean, std)) axes.axhline(y=mean - std, ls='dotted', color='r') axes.axhline(y=mean + std, ls='dotted', color='r') pyplot.plot([Xmin, Xmax], [intercept + slope * Xmin, intercept + slope * Xmax], 'g:') pyplot.plot([Xmin, Xmax], [intercept + slope * Xmin, intercept + slope * Xmax], 'g:') # Axes labels and ranges axes.set_ylim([Ymin, Ymax]) axes.set_xlim([Xmin, Xmax]) axes.set_xlabel('Excitation Potential (eV)') axes.set_ylabel('Abundance [X/H]') axes.legend() if plotTitle is not '': axes.set_title(plotTitle) saveDirName = dirs.XPAbPlotsDir + el.getIonName(ion) + '/' try: os.stat(saveDirName) except: os.mkdir(saveDirName[:-1]) pyplot.savefig('{0}{1}_{2}{3}.png'.format(saveDirName, starName, el.getIonName(ion), fileTag), figure=fig) pyplot.close()
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 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)