def plot_beast_ifit(filters, waves, stats, pdf1d_hdu, starnum): # setup the plot grid gridNrow, gridNcol = 5, 12 gs = gridspec.GridSpec( gridNrow, gridNcol, height_ratios=[1.0] * gridNrow, width_ratios=[1.0] * gridNcol, ) ax = [] # axes for the big SED plot. Leave empty columns right of the plot to # put the legend and values. sed_height = 2 free_cols = 3 index_sedplot = len(ax) ax.append(plt.subplot(gs[0:sed_height, 0:-1 - free_cols])) # axes for the 1D PDFs nprim = 4 nsec = 3 nderiv = 3 indices_1dpdf = [] rows = [sed_height + i for i in range(3)] widths = [3, 4, 4] naxes = [nprim, nsec, nderiv] for r, w, n in zip(rows, widths, naxes): for i in range(n): indices_1dpdf.append(len(ax)) ax.append(plt.subplot(gs[r, i * w:(i + 1) * w])) # plot the SED # print(np.sort(stats.colnames)) n_filters = len(filters) # get the observations waves *= 1e-4 obs_flux = np.empty((n_filters), dtype=np.float) mod_flux = np.empty((n_filters, 3), dtype=np.float) mod_flux_nd = np.empty((n_filters, 3), dtype=np.float) mod_flux_wbias = np.empty((n_filters, 3), dtype=np.float) k = starnum c = ap_SkyCoord( ra=stats["RA"][k] * ap_units.degree, dec=stats["DEC"][k] * ap_units.degree, frame="icrs", ) corname = ("PHAT J" + c.ra.to_string(unit=ap_units.hourangle, sep="", precision=2, alwayssign=False, pad=True) + c.dec.to_string(sep="", precision=2, alwayssign=True, pad=True)) for i, cfilter in enumerate(filters): obs_flux[i] = stats[cfilter][k] fluxname = "log" + cfilter mod_flux[i, 0] = np.power(10.0, stats[fluxname + "_wd_p50"][k]) mod_flux[i, 1] = np.power(10.0, stats[fluxname + "_wd_p16"][k]) mod_flux[i, 2] = np.power(10.0, stats[fluxname + "_wd_p84"][k]) mod_flux_nd[i, 0] = np.power(10.0, stats[fluxname + "_nd_p50"][k]) mod_flux_nd[i, 1] = np.power(10.0, stats[fluxname + "_nd_p16"][k]) mod_flux_nd[i, 2] = np.power(10.0, stats[fluxname + "_nd_p84"][k]) if "sym" + fluxname + "_wd_bias_p50" in stats.colnames: mod_flux_wbias[i, 0] = inverse_symlog(stats["sym" + fluxname + "_wd_bias_p50"][k]) mod_flux_wbias[i, 1] = inverse_symlog(stats["sym" + fluxname + "_wd_bias_p16"][k]) mod_flux_wbias[i, 2] = inverse_symlog(stats["sym" + fluxname + "_wd_bias_p84"][k]) sed_ax = ax[index_sedplot] sed_ax.plot(waves, obs_flux, "ko", label="observed") if "symlog" + filters[0] + "_wd_bias_p50" in stats.colnames: sed_ax.plot(waves, mod_flux_wbias[:, 0], "b-", label="stellar+dust+bias") sed_ax.fill_between(waves, mod_flux_wbias[:, 1], mod_flux_wbias[:, 2], color="b", alpha=0.3) sed_ax.plot(waves, mod_flux[:, 0], "r-", label="stellar+dust") sed_ax.fill_between(waves, mod_flux[:, 1], mod_flux[:, 2], color="r", alpha=0.2) sed_ax.plot(waves, mod_flux_nd[:, 0], "y-", label="stellar only") sed_ax.fill_between(waves, mod_flux_nd[:, 1], mod_flux_nd[:, 2], color="y", alpha=0.1) # sed_ax.legend(loc='upper right', bbox_to_anchor=(1.25, 1.025), fontsize=8) sed_ax.legend(loc="lower right", fontsize=9) sed_ax.set_ylabel(r"Flux [ergs s$^{-1}$ cm$^{-2}$ $\AA^{-1}$]") sed_ax.set_yscale("log") sed_ax.text(0.5, -0.07, r"$\lambda$ [$\AA$]", transform=sed_ax.transAxes, va="top") sed_ax.set_xlim(0.2, 2.0) sed_ax.set_xscale("log") sed_ax.minorticks_off() sed_ax.set_xticks([0.2, 0.3, 0.4, 0.5, 0.8, 1.0, 2.0]) sed_ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) sed_ax.get_xaxis().set_minor_formatter(matplotlib.ticker.ScalarFormatter()) sed_ax.text(0.05, 0.95, corname, transform=sed_ax.transAxes, va="top", ha="left") # add the text results keys = [ "Av", "M_ini", "logA", "distance", "Rv", "f_A", "Z", "logT", "logg", "logL" ] dispnames = [ "A(V)", "log(M)", "log(t)", "d(kpc)", "R(V)", r"f$_\mathcal{A}$", "Z", r"log(T$_\mathrm{eff})$", "log(g)", "log(L)", ] startprim, stopprim = 0, nprim - 1 # 0 1 2 3 startsec, stopsec = stopprim + 1, stopprim + nsec # 4 5 6 startderiv, stopderiv = stopsec + 1, stopsec + nderiv # 7 8 9 laby = 0.96 ty = np.linspace(laby - 0.1, 0.1, num=len(keys)) ty[startsec:] -= 0.04 ty[startderiv:] -= 0.04 tx = [1.14, 1.3, 1.47] for i in range(len(keys)): sed_ax.text(tx[0], ty[i], dispnames[i], ha="center", transform=sed_ax.transAxes) sed_ax.text( tx[1], ty[i], disp_str(stats, starnum, keys[i]), ha="center", color="m", transform=sed_ax.transAxes, ) best_val = stats[keys[i] + "_Best"][k] if keys[i] == "M_ini": best_val = np.log10(best_val) if keys[i] == "distance": best_val /= 1000.0 dispnames[i] = dispnames[i].replace("pc", "kpc") sed_ax.text( tx[2], ty[i], "$" + "{0:.2f}".format(best_val) + "$", ha="center", color="c", transform=sed_ax.transAxes, ) sed_ax.text(tx[0], laby, "Param", ha="center", transform=sed_ax.transAxes, fontsize=10) sed_ax.text( tx[1], laby, r"50$\pm$33%", ha="center", color="k", transform=sed_ax.transAxes, fontsize=10, ) sed_ax.text( tx[2], laby, "Best", color="k", ha="center", transform=sed_ax.transAxes, fontsize=10, ) # now draw boxes around the different kinds of parameters tax = sed_ax left, right = tx[0], tx[-1] def draw_box_around_values(start, stop, ls): deltaline = ty[start] - ty[start + 1] top = ty[start] + deltaline # Draw the top border ABOVE the text bottom = ty[stop] rec = Rectangle( (left - 0.1, bottom - 0.02), right - left + 0.15, top - bottom + 0.01, fill=False, lw=2, transform=tax.transAxes, ls=ls, ) rec = tax.add_patch(rec) rec.set_clip_on(False) # primary draw_box_around_values(startprim, stopprim, ls="dashed") # secondary draw_box_around_values(startsec, stopsec, ls="dotted") # derived draw_box_around_values(startderiv, stopderiv, ls="dashdot") # Make these plots: # A, M, t, dist, # R, fA, Z # logT, logg, logL # This is done by iterating over the axes created at the start of # this function, from left to right, line per line. # plot the primary parameter 1D PDFs ax_iter = (ax[i] for i in indices_1dpdf) first_primary_ax = next(ax_iter) plot_1dpdf(first_primary_ax, pdf1d_hdu, "Av", "A(V)", starnum, stats=stats) plot_1dpdf(next(ax_iter), pdf1d_hdu, "M_ini", "log(M)", starnum, logx=True, stats=stats) plot_1dpdf(next(ax_iter), pdf1d_hdu, "logA", "log(t)", starnum, stats=stats) last_primary_ax = next(ax_iter) plot_1dpdf(last_primary_ax, pdf1d_hdu, "distance", "d(kpc)", starnum, stats=stats) # plot the secondary parameter 1D PDFs first_secondary_ax = next(ax_iter) plot_1dpdf(first_secondary_ax, pdf1d_hdu, "Rv", "R(V)", starnum, stats=stats) plot_1dpdf(next(ax_iter), pdf1d_hdu, "f_A", r"f$_\mathcal{A}$", starnum, stats=stats) last_secondary_ax = next(ax_iter) plot_1dpdf(last_secondary_ax, pdf1d_hdu, "Z", "Z", starnum, stats=stats) # plot the derived parameter 1D PDFs first_derived_ax = next(ax_iter) plot_1dpdf( first_derived_ax, pdf1d_hdu, "logT", r"log(T$_\mathrm{eff})$", starnum, stats=stats, ) plot_1dpdf(next(ax_iter), pdf1d_hdu, "logg", "log(g)", starnum, stats=stats) last_derived_ax = next(ax_iter) plot_1dpdf(last_derived_ax, pdf1d_hdu, "logL", "log(L)", starnum, stats=stats) # A more manual version of tight_layout plt.subplots_adjust(top=0.95, bottom=0.05, left=0.125, right=0.925, wspace=0.5, hspace=0.5) # PLOT ALL THE BOXES AFTER CALLING TIGHT LAYOUT! Tight layout # changes the coordinates of the axes a little, but leaves the boxes # untouched. Therefore, we plot the boxes here by extracting the # coordinates of the axes after they have been modified by # tight_layout. def rectangle_around_axes(bottomleft_ax, topright_ax, pad, ls, label=None): """ pad: tuple, (left, right, bottom, top) """ left, bottom = bottomleft_ax.get_position().get_points()[0] right, top = topright_ax.get_position().get_points()[1] left -= pad[0] right += pad[1] bottom -= pad[2] top += pad[3] transf = plt.gcf().transFigure rec = Rectangle( (left, bottom), right - left, top - bottom, transform=transf, fill=False, lw=2, ls=ls, ) rec = bottomleft_ax.add_patch(rec) rec.set_clip_on(False) if label: middle = (top + bottom) / 2.0 moreleft = left # pad[0] bottomleft_ax.text( moreleft, middle, label, transform=transf, rotation="vertical", fontstyle="oblique", va="center", ha="right", ) rectanglePadding = (0.03, 0.01, 0.03, 0.01) # Box around primaries tax = first_primary_ax rectangle_around_axes( first_primary_ax, last_primary_ax, pad=rectanglePadding, ls="dashed", label="Primary", ) tax.text( 0.0, 0.5, "Probability", transform=tax.transAxes, rotation="vertical", va="center", ha="right", ) # Box around secondaries tax = first_secondary_ax rectangle_around_axes( first_secondary_ax, last_secondary_ax, pad=rectanglePadding, ls="dotted", label="Secondary", ) tax.text( 0.0, 0.5, "Probability", transform=tax.transAxes, rotation="vertical", va="center", ha="right", ) # Box around deriveds tax = first_derived_ax rectangle_around_axes( first_derived_ax, last_derived_ax, pad=rectanglePadding, ls="dashdot", label="Derived", ) tax.text( 0.0, 0.5, "Probability", transform=tax.transAxes, rotation="vertical", va="center", ha="right", )
def plot_beast_ifit(filters, waves, stats, pdf1d_hdu): # setup the plot grid gridNrow, gridNcol = 5, 12 gs = gridspec.GridSpec(gridNrow, gridNcol, height_ratios=[1.] * gridNrow, width_ratios=[1.] * gridNcol) ax = [] # axes for the big SED plot. Leave empty columns right of the plot to # put the legend and values. sed_height = 2 free_cols = 2 index_sedplot = len(ax) ax.append(plt.subplot(gs[0:sed_height, 0:-1 - free_cols])) # axes for the 1D PDFs nprim = 4 nsec = 3 nderiv = 3 indices_1dpdf = [] rows = [sed_height + i for i in range(3)] widths = [3, 4, 4] naxes = [nprim, nsec, nderiv] for r, w, n in zip(rows, widths, naxes): for i in range(n): indices_1dpdf.append(len(ax)) ax.append(plt.subplot(gs[r, i * w:(i + 1) * w])) # plot the SED # print(np.sort(stats.colnames)) n_filters = len(filters) # get the observations waves *= 1e-4 obs_flux = np.empty((n_filters), dtype=np.float) mod_flux = np.empty((n_filters, 3), dtype=np.float) mod_flux_nd = np.empty((n_filters, 3), dtype=np.float) mod_flux_wbias = np.empty((n_filters, 3), dtype=np.float) k = starnum c = ap_SkyCoord(ra=stats['RA'][k] * ap_units.degree, dec=stats['DEC'][k] * ap_units.degree, frame='icrs') corname = ('PHAT J' + c.ra.to_string(unit=ap_units.hourangle, sep="", precision=2, alwayssign=False, pad=True) + c.dec.to_string(sep="", precision=2, alwayssign=True, pad=True)) for i, cfilter in enumerate(filters): obs_flux[i] = stats[cfilter][k] mod_flux[i, 0] = np.power(10.0, stats['log' + cfilter + '_wd_p50'][k]) mod_flux[i, 1] = np.power(10.0, stats['log' + cfilter + '_wd_p16'][k]) mod_flux[i, 2] = np.power(10.0, stats['log' + cfilter + '_wd_p84'][k]) mod_flux_nd[i, 0] = np.power(10.0, stats['log' + cfilter + '_nd_p50'][k]) mod_flux_nd[i, 1] = np.power(10.0, stats['log' + cfilter + '_nd_p16'][k]) mod_flux_nd[i, 2] = np.power(10.0, stats['log' + cfilter + '_nd_p84'][k]) if 'log' + cfilter + '_wd_bias_p50' in stats.colnames: mod_flux_wbias[i, 0] = np.power( 10.0, stats['log' + cfilter + '_wd_bias_p50'][k]) mod_flux_wbias[i, 1] = np.power( 10.0, stats['log' + cfilter + '_wd_bias_p16'][k]) mod_flux_wbias[i, 2] = np.power( 10.0, stats['log' + cfilter + '_wd_bias_p84'][k]) sed_ax = ax[index_sedplot] sed_ax.plot(waves, obs_flux, 'ko', label='observed') if 'log' + filters[0] + '_wd_bias_p50' in stats.colnames: sed_ax.plot(waves, mod_flux_wbias[:, 0], 'b-', label='stellar+dust+bias') sed_ax.fill_between(waves, mod_flux_wbias[:, 1], mod_flux_wbias[:, 2], color='b', alpha=0.3) sed_ax.plot(waves, mod_flux[:, 0], 'r-', label='stellar+dust') sed_ax.fill_between(waves, mod_flux[:, 1], mod_flux[:, 2], color='r', alpha=0.2) sed_ax.plot(waves, mod_flux_nd[:, 0], 'y-', label='stellar only') sed_ax.fill_between(waves, mod_flux_nd[:, 1], mod_flux_nd[:, 2], color='y', alpha=0.1) sed_ax.legend(loc='upper right', bbox_to_anchor=(1.25, 1.025)) sed_ax.set_ylabel(r'Flux [ergs s$^{-1}$ cm$^{-2}$ $\AA^{-1}$]') sed_ax.set_yscale('log') sed_ax.set_xscale('log') sed_ax.text(0.5, -0.01, r'$\lambda$ [$\AA$]', transform=sed_ax.transAxes, va='top') sed_ax.set_xlim(0.2, 2.0) sed_ax.set_xticks([0.2, 0.3, 0.4, 0.5, 0.8, 0.9, 1.0, 2.0]) sed_ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) sed_ax.text(0.05, 0.95, corname, transform=sed_ax.transAxes, va='top', ha='left') # add the text results keys = [ 'Av', 'M_ini', 'logA', 'distance', 'Rv', 'f_A', 'Z', 'logT', 'logg', 'logL' ] dispnames = [ 'A(V)', 'log(M)', 'log(t)', 'distance(pc)', 'R(V)', r'f$_\mathcal{A}$', 'Z', r'log(T$_\mathrm{eff})$', 'log(g)', 'log(L)' ] startprim, stopprim = 0, nprim - 1 # 0 1 2 3 startsec, stopsec = stopprim + 1, stopprim + nsec # 4 5 6 startderiv, stopderiv = stopsec + 1, stopsec + nderiv # 7 8 9 laby = 0.72 ty = np.linspace(laby - 0.07, 0.1, num=len(keys)) ty[startsec:] -= 0.025 ty[startderiv:] -= 0.025 tx = [1.12, 1.2, 1.3] for i in range(len(keys)): sed_ax.text(tx[0], ty[i], dispnames[i], ha='right', transform=sed_ax.transAxes) sed_ax.text(tx[1], ty[i], disp_str(stats, starnum, keys[i]), ha='center', color='m', transform=sed_ax.transAxes) best_val = stats[keys[i] + '_Best'][k] if keys[i] == 'M_ini': best_val = np.log10(best_val) if keys[i] == 'distance': best_val /= 1000. dispnames[i] = dispnames[i].replace('pc', 'kpc') sed_ax.text(tx[2], ty[i], '$' + "{0:.2f}".format(best_val) + '$', ha='center', color='c', transform=sed_ax.transAxes) sed_ax.text(tx[0], laby, 'Param', ha='right', transform=sed_ax.transAxes) sed_ax.text(tx[1], laby, '50%$\pm$33%', ha='center', color='k', transform=sed_ax.transAxes) sed_ax.text(tx[2], laby, 'Best', color='k', ha='center', transform=sed_ax.transAxes) # now draw boxes around the different kinds of parameters tax = sed_ax left, right = tx[0], tx[-1] def draw_box_around_values(start, stop, ls): deltaline = ty[start] - ty[start + 1] top = ty[start] + deltaline # Draw the top border ABOVE the text bottom = ty[stop] rec = Rectangle((left - 0.1, bottom - 0.02), right - left + 0.15, top - bottom + 0.01, fill=False, lw=2, transform=tax.transAxes, ls=ls) rec = tax.add_patch(rec) rec.set_clip_on(False) # primary draw_box_around_values(startprim, stopprim, ls='dashed') # secondary draw_box_around_values(startsec, stopsec, ls='dotted') # derived draw_box_around_values(startderiv, stopderiv, ls='dashdot') # padding for rectangles of 1D PDFs pad = 0.1 # Make these plots: # A, M, t, dist, # R, fA, Z # logT, logg, logL # This is done by iterating over the axes created at the start of # this function, from left to right, line per line. # plot the primary parameter 1D PDFs ax_iter = (ax[i] for i in indices_1dpdf) first_primary_ax = next(ax_iter) plot_1dpdf(first_primary_ax, pdf1d_hdu, 'Av', 'A(V)', starnum, stats=stats) plot_1dpdf(next(ax_iter), pdf1d_hdu, 'M_ini', 'log(M)', starnum, logx=True, stats=stats) plot_1dpdf(next(ax_iter), pdf1d_hdu, 'logA', 'log(t)', starnum, stats=stats) last_primary_ax = next(ax_iter) plot_1dpdf(last_primary_ax, pdf1d_hdu, 'distance', 'distance(pc)', starnum, stats=stats) # plot the secondary parameter 1D PDFs first_secondary_ax = next(ax_iter) plot_1dpdf(first_secondary_ax, pdf1d_hdu, 'Rv', 'R(V)', starnum, stats=stats) plot_1dpdf(next(ax_iter), pdf1d_hdu, 'f_A', r'f$_\mathcal{A}$', starnum, stats=stats) last_secondary_ax = next(ax_iter) plot_1dpdf(last_secondary_ax, pdf1d_hdu, 'Z', 'Z', starnum, stats=stats) # plot the derived parameter 1D PDFs first_derived_ax = next(ax_iter) plot_1dpdf(first_derived_ax, pdf1d_hdu, 'logT', r'log(T$_\mathrm{eff})$', starnum, stats=stats) plot_1dpdf(next(ax_iter), pdf1d_hdu, 'logg', 'log(g)', starnum, stats=stats) last_derived_ax = next(ax_iter) plot_1dpdf(last_derived_ax, pdf1d_hdu, 'logL', 'log(L)', starnum, stats=stats) # A more manual version of tight_layout plt.subplots_adjust(top=.95, bottom=.05, left=.125, right=.925, wspace=.5, hspace=.5) # PLOT ALL THE BOXES AFTER CALLING TIGHT LAYOUT! Tight layout # changes the coordinates of the axes a little, but leaves the boxes # untouched. Therefore, we plot the boxes here by extracting the # coordinates of the axes after they have been modified by # tight_layout. def rectangle_around_axes(bottomleft_ax, topright_ax, pad, ls, label=None): """ pad: tuple, (left, right, bottom, top) """ left, bottom = bottomleft_ax.get_position().get_points()[0] right, top = topright_ax.get_position().get_points()[1] left -= pad[0] right += pad[1] bottom -= pad[2] top += pad[3] transf = plt.gcf().transFigure rec = Rectangle((left, bottom), right - left, top - bottom, transform=transf, fill=False, lw=2, ls=ls) rec = bottomleft_ax.add_patch(rec) rec.set_clip_on(False) if label: middle = (top + bottom) / 2. moreleft = left # pad[0] bottomleft_ax.text(moreleft, middle, label, transform=transf, rotation='vertical', fontstyle='oblique', va='center', ha='right') rectanglePadding = (0.03, 0.01, 0.03, 0.01) # Box around primaries tax = first_primary_ax rectangle_around_axes(first_primary_ax, last_primary_ax, pad=rectanglePadding, ls='dashed', label='Primary') tax.text(0.0, 0.5, 'Probability', transform=tax.transAxes, rotation='vertical', va='center', ha='right') # Box around secondaries tax = first_secondary_ax rectangle_around_axes(first_secondary_ax, last_secondary_ax, pad=rectanglePadding, ls='dotted', label='Secondary') tax.text(0.0, 0.5, 'Probability', transform=tax.transAxes, rotation='vertical', va='center', ha='right') # Box around deriveds tax = first_derived_ax rectangle_around_axes(first_derived_ax, last_derived_ax, pad=rectanglePadding, ls='dashdot', label='Derived') tax.text(0.0, 0.5, 'Probability', transform=tax.transAxes, rotation='vertical', va='center', ha='right')
def IAU_names_and_extra_info(obsdata, surveyname="PHAT", extraInfo=False): """ Generates IAU approved names for the data using RA & DEC and extra information about the sources (ra, dec, photometry, etc.) Parameters ---------- obsdata : class observations data surveyname : str name of survey [default = 'PHAT'] extraInfo : bool set to get the HST specific PHAT software reduced survey information Returns ------- r : dict A dict with a (name, ndarray) pair """ r = {} go_name = False if "ra" in list(obsdata.data.keys()): go_name = True ra_str = "ra" dec_str = "dec" if "RA" in list(obsdata.data.keys()): go_name = True ra_str = "RA" dec_str = "DEC" if go_name: # generate the IAU names _tnames = [] for i in range(len(obsdata)): c = ap_SkyCoord( ra=obsdata.data[ra_str][i] * ap_units.degree, dec=obsdata.data[dec_str][i] * ap_units.degree, frame="icrs", ) _tnames.append(surveyname + " J" + c.ra.to_string( unit=ap_units.hourangle, sep="", precision=2, alwayssign=False, pad=True, ) + c.dec.to_string(sep="", precision=2, alwayssign=True, pad=True) ) r["Name"] = _tnames # other useful information r["RA"] = obsdata.data[ra_str] r["DEC"] = obsdata.data[dec_str] if extraInfo: r["field"] = obsdata.data["field"] r["inside_brick"] = obsdata.data["inside_brick"] r["inside_chipgap"] = obsdata.data["inside_chipgap"] else: r["Name"] = ["noname" for x in range(len(obsdata))] # include the observed filter fluxes for k, filtername in enumerate(obsdata.filters): obsfiltname = obsdata.filter_aliases[filtername] r[filtername] = (obsdata.data[obsfiltname] * obsdata.vega_flux[k]).astype(float) return r
def IAU_names_and_extra_info(obsdata, surveyname='PHAT',extraInfo=False): """ generates IAU approved names for the data using RA & DEC and extra information about the sources (ra, dec, photometry, etc.) keywords -------- obsdata: Observations surveyname: string name of survey [default = 'PHAT'] extraInfo: bool set to get the HST specific PHAT software reduced survey information returns ------- r: dict returns a dict with a (name, ndarray) pair """ r = {} go_name = False if 'ra' in list(obsdata.data.keys()): go_name = True ra_str = 'ra' dec_str = 'dec' if 'RA' in list(obsdata.data.keys()): go_name = True ra_str = 'RA' dec_str = 'DEC' if go_name: # generate the IAU names _tnames = [] for i in range(len(obsdata)): c = ap_SkyCoord(ra=obsdata.data[ra_str][i]*ap_units.degree, dec=obsdata.data[dec_str][i]*ap_units.degree, frame='icrs') _tnames.append(surveyname + ' J' + c.ra.to_string(unit=ap_units.hourangle, sep="",precision=2, alwayssign=False,pad=True) + c.dec.to_string(sep="",precision=2, alwayssign=True,pad=True)) r['Name'] = _tnames # other useful information r['RA'] = obsdata.data[ra_str] r['DEC'] = obsdata.data[dec_str] if extraInfo: r['field'] = obsdata.data['field'] r['inside_brick'] = obsdata.data['inside_brick'] r['inside_chipgap'] = obsdata.data['inside_chipgap'] else: r['Name'] = ["noname" for x in range(len(obsdata))] # include the observed filter fluxes for k, filtername in enumerate(obsdata.filters): r[filtername] = (obsdata.data[filtername]* obsdata.vega_flux[k]).astype(float) return r
def plot_beast_ifit(filters, waves, stats, pdf1d_hdu): # setup the plot grid gs = gridspec.GridSpec(4, 4, height_ratios=[1.0, 1.0, 1.0, 1.0], width_ratios=[1.0, 1.0, 1.0, 1.0]) ax = [] # plots for the 1D PDFs for j in range(2): for i in range(4): ax.append(plt.subplot(gs[j + 2, i])) # now for the big SED plot ax.append(plt.subplot(gs[0:2, 0:3])) # plot the SED #print(np.sort(stats.colnames)) n_filters = len(filters) # get the observations waves *= 1e-4 obs_flux = np.empty((n_filters), dtype=np.float) mod_flux = np.empty((n_filters, 3), dtype=np.float) mod_flux_nd = np.empty((n_filters, 3), dtype=np.float) mod_flux_wbias = np.empty((n_filters, 3), dtype=np.float) k = starnum c = ap_SkyCoord(ra=stats['RA'][k] * ap_units.degree, dec=stats['DEC'][k] * ap_units.degree, frame='icrs') corname = ('PHAT J' + c.ra.to_string(unit=ap_units.hourangle, sep="", precision=2, alwayssign=False, pad=True) + c.dec.to_string(sep="", precision=2, alwayssign=True, pad=True)) for i, cfilter in enumerate(filters): obs_flux[i] = stats[cfilter][k] mod_flux[i, 0] = np.power(10.0, stats['log' + cfilter + '_wd_p50'][k]) mod_flux[i, 1] = np.power(10.0, stats['log' + cfilter + '_wd_p16'][k]) mod_flux[i, 2] = np.power(10.0, stats['log' + cfilter + '_wd_p84'][k]) mod_flux_nd[i, 0] = np.power(10.0, stats['log' + cfilter + '_nd_p50'][k]) mod_flux_nd[i, 1] = np.power(10.0, stats['log' + cfilter + '_nd_p16'][k]) mod_flux_nd[i, 2] = np.power(10.0, stats['log' + cfilter + '_nd_p84'][k]) if 'log' + cfilter + '_wd_bias_p50' in stats.colnames: mod_flux_wbias[i, 0] = np.power( 10.0, stats['log' + cfilter + '_wd_bias_p50'][k]) mod_flux_wbias[i, 1] = np.power( 10.0, stats['log' + cfilter + '_wd_bias_p16'][k]) mod_flux_wbias[i, 2] = np.power( 10.0, stats['log' + cfilter + '_wd_bias_p84'][k]) ax[8].plot(waves, obs_flux, 'ko', label='observed') if 'log' + filters[0] + '_wd_bias_p50' in stats.colnames: ax[8].plot(waves, mod_flux_wbias[:, 0], 'b-', label='stellar+dust+bias') ax[8].fill_between(waves, mod_flux_wbias[:, 1], mod_flux_wbias[:, 2], color='b', alpha=0.3) ax[8].plot(waves, mod_flux[:, 0], 'r-', label='stellar+dust') ax[8].fill_between(waves, mod_flux[:, 1], mod_flux[:, 2], color='r', alpha=0.2) ax[8].plot(waves, mod_flux_nd[:, 0], 'y-', label='stellar only') ax[8].fill_between(waves, mod_flux_nd[:, 1], mod_flux_nd[:, 2], color='y', alpha=0.1) ax[8].legend(loc='upper right', bbox_to_anchor=(1.25, 1.025)) ax[8].set_ylabel(r'Flux [ergs s$^{-1}$ cm$^{-2}$ $\AA^{-1}$]') ax[8].set_yscale('log') ax[8].set_xscale('log') ax[8].text(0.5, -0.01, r'$\lambda$ [$\AA$]', transform=ax[8].transAxes, va='top') ax[8].set_xlim(0.2, 2.0) ax[8].set_xticks([0.2, 0.3, 0.4, 0.5, 0.8, 0.9, 1.0, 2.0]) ax[8].get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) ax[8].text(0.05, 0.95, corname, transform=ax[8].transAxes, va='top', ha='left') # add the text results keys = ['Av', 'M_ini', 'logA', 'Rv', 'f_A', 'Z', 'logT', 'logg', 'logL'] dispnames = [ 'A(V)', 'log(M)', 'log(t)', 'R(V)', r'f$_\mathcal{A}$', 'Z', r'log(T$_\mathrm{eff})$', 'log(g)', 'log(L)' ] laby = 0.72 ty = np.linspace(laby - 0.07, 0.1, num=len(keys)) ty[3:] -= 0.025 ty[6:] -= 0.025 tx = [1.12, 1.2, 1.3] for i in range(len(keys)): ax[8].text(tx[0], ty[i], dispnames[i], ha='right', transform=ax[8].transAxes) ax[8].text(tx[1], ty[i], disp_str(stats, starnum, keys[i]), ha='center', color='m', transform=ax[8].transAxes) best_val = stats[keys[i] + '_Best'][k] if keys[i] == 'M_ini': best_val = np.log10(best_val) ax[8].text(tx[2], ty[i], '$' + "{0:.2f}".format(best_val) + '$', ha='center', color='c', transform=ax[8].transAxes) ax[8].text(tx[0], laby, 'Param', ha='right', transform=ax[8].transAxes) ax[8].text(tx[1], laby, '50%$\pm$33%', ha='center', color='k', transform=ax[8].transAxes) ax[8].text(tx[2], laby, 'Best', color='k', ha='center', transform=ax[8].transAxes) # now draw boxes around the different kinds of parameters tax = ax[8] # primary rec = Rectangle((tx[0] - 0.1, ty[2] - 0.02), tx[2] - tx[0] + 0.15, (ty[0] - ty[2]) * 1.5, fill=False, lw=2, transform=tax.transAxes, ls='dashed') rec = tax.add_patch(rec) rec.set_clip_on(False) # secondary rec = Rectangle((tx[0] - 0.1, ty[5] - 0.02), tx[2] - tx[0] + 0.15, (ty[3] - ty[5]) * 1.5, fill=False, lw=2, transform=tax.transAxes, ls='dotted') rec = tax.add_patch(rec) rec.set_clip_on(False) # derived rec = Rectangle((tx[0] - 0.1, ty[8] - 0.02), tx[2] - tx[0] + 0.15, (ty[6] - ty[8]) * 1.5, fill=False, lw=2, transform=tax.transAxes, ls='dashdot') rec = tax.add_patch(rec) rec.set_clip_on(False) # padding for rectangles of 1D PDFs pad = 0.1 # plot the primary parameter 1D PDFs plot_1dpdf(ax[0], pdf1d_hdu, 'Av', 'A(V)', starnum, stats=stats) plot_1dpdf(ax[1], pdf1d_hdu, 'M_ini', 'log(M)', starnum, logx=True, stats=stats) plot_1dpdf(ax[2], pdf1d_hdu, 'logA', 'log(t)', starnum, stats=stats) # draw a box around them and label tax = ax[0] rec = Rectangle((-1.75 * pad, -pad), 3 * (1.0 + pad) + 1.5 * pad, 1.0 + 1.5 * pad, fill=False, lw=2, transform=tax.transAxes, ls='dashed') rec = tax.add_patch(rec) rec.set_clip_on(False) tax.text(-2. * pad, 0.5, 'Primary', transform=tax.transAxes, rotation='vertical', fontstyle='oblique', va='center', ha='right') tax.text(0.0, 0.5, 'Probability', transform=tax.transAxes, rotation='vertical', va='center', ha='right') # plot the secondary parameter 1D PDFs plot_1dpdf(ax[4], pdf1d_hdu, 'Rv', 'R(V)', starnum, stats=stats) plot_1dpdf(ax[5], pdf1d_hdu, 'f_A', r'f$_\mathcal{A}$', starnum, stats=stats) plot_1dpdf(ax[6], pdf1d_hdu, 'Z', 'Z', starnum, stats=stats) # draw a box around them tax = ax[4] rec = Rectangle((-1.75 * pad, -pad), 3 * (1.0 + pad) + 1.5 * pad, 1.0 + 1.5 * pad, fill=False, lw=2, transform=tax.transAxes, ls='dotted') rec = tax.add_patch(rec) rec.set_clip_on(False) tax.text(-2 * pad, 0.5, 'Secondary', transform=tax.transAxes, rotation='vertical', fontstyle='oblique', va='center', ha='right') tax.text(0.0, 0.5, 'Probability', transform=tax.transAxes, rotation='vertical', va='center', ha='right') # plot the derived parameter 1D PDFs plot_1dpdf(ax[3], pdf1d_hdu, 'logT', r'log(T$_\mathrm{eff})$', starnum, stats=stats) plot_1dpdf(ax[7], pdf1d_hdu, 'logg', 'log(g)', starnum, stats=stats) # draw a box around them tax = ax[7] rec = Rectangle((-0.25 * pad, -pad), 1.0 + 0.5 * pad, 2 * (1.0 + 2. * pad) - 0.125 * pad, fill=False, lw=2, transform=tax.transAxes, ls='dashdot') rec = tax.add_patch(rec) rec.set_clip_on(False) tax.text(0.5, 2 * (1.0 + 2 * pad) - 1.0 * pad, 'Derived', transform=tax.transAxes, rotation='horizontal', fontstyle='oblique', va='bottom', ha='center') # optimize the figure layout plt.tight_layout(h_pad=2.0, w_pad=1.0)