InĀ [Ā ]:
import numpy as np
from matplotlib import pyplot as plt
import pandas as pd
import h5py
InĀ [34]:
from brutus import filters
from brutus import seds
from brutus import utils as butils

filt = filters.decam[1:] + filters.tmass

# import EEP tracks
nnfile = "brutus/data/DATAFILES/nn_c3k.h5"
mistfile = "brutus/data/DATAFILES/MIST_1.2_EEPtrk.h5"
sedmaker = seds.SEDmaker(filters=filt, nnfile=nnfile, mistfile=mistfile)

# import MIST model grid
gridfile = "brutus/data/DATAFILES/grid_mist_v9.h5"
(models_mist, labels_mist, lmask_mist) = butils.load_models(gridfile, filters=filt)
Filters: ['DECam_g', 'DECam_r', 'DECam_i', 'DECam_z', 'DECam_Y', '2MASS_J', '2MASS_H', '2MASS_Ks']
Constructing MIST library...done!
Computing age weights for track (mini, feh, afe) = (300.0, 0.5, 0.0)            
Initializing FastNN predictor...done!
Reading filter 2MASS_Ks           
InĀ [38]:
# load offsets
off_file_mist = "brutus/data/DATAFILES/offsets_mist_v8.txt"
print("MIST photometric offsets:")
off_mist = butils.load_offsets(off_file_mist, filters=filt)
MIST photometric offsets:
DECam_g (1.0%)
DECam_r (-3.0%)
DECam_i (-3.0%)
DECam_z (-2.0%)
DECam_Y (-3.0%)
2MASS_J (-2.0%)
2MASS_H (1.0%)
2MASS_Ks (-2.0%)
InĀ [39]:
from brutus.fitting import BruteForce

# initialize `BruteForce` class
BF_mist = BruteForce(models_mist, labels_mist, lmask_mist)
InĀ [68]:
# df = pd.read_csv("dust_region_stars_photometry.csv")
df = pd.read_csv("dust_region_stars_photometry.csv")
# replace 0.0 with NaN
df.replace(0.0, np.nan, inplace=True)
df.drop(14)
df
Out[68]:
ra dec l b g_maggies g_err_maggies r_maggies r_err_maggies i_maggies i_err_maggies ... y_maggies y_err_maggies j_maggies j_err_maggies h_maggies h_err_maggies k_maggies k_err_maggies parallax_mas parallax_err_mas
0 158.595688 -60.640267 286.897020 -2.108413 3.262650e-10 5.512280e-11 1.486350e-09 1.103840e-10 1.859870e-09 9.591350e-11 ... 4.244120e-09 5.658440e-10 NaN NaN NaN NaN NaN NaN NaN NaN
1 158.593768 -60.637999 286.895067 -2.106923 4.774170e-10 3.816080e-11 1.518170e-09 1.156390e-10 3.709260e-09 9.456880e-11 ... 8.300150e-09 3.654590e-10 NaN NaN NaN NaN NaN NaN NaN NaN
2 158.590155 -60.637249 286.893156 -2.107162 4.326790e-10 6.233630e-11 3.272280e-09 1.195550e-10 1.479240e-08 1.185260e-10 ... 7.151570e-08 5.488640e-10 4.751164e-07 3.413267e-08 0.000002 6.375882e-08 0.000003 1.270950e-07 -0.089649 0.624679
3 158.591477 -60.640051 286.895124 -2.109261 2.379470e-09 2.970760e-11 9.653800e-09 1.606340e-10 1.964540e-08 1.326030e-10 ... 3.027720e-08 4.184930e-10 NaN NaN NaN NaN NaN NaN 0.549278 0.356951
4 158.603323 -60.652291 286.906293 -2.116940 2.010640e-09 3.450460e-11 5.733520e-09 1.626940e-10 7.139540e-09 1.070160e-10 ... 1.172830e-08 4.794800e-10 NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
185 158.577578 -60.675798 286.907169 -2.143603 3.428220e-10 3.664220e-11 1.289940e-09 5.706480e-11 3.144120e-09 8.704980e-11 ... 5.605290e-09 4.503020e-10 NaN NaN NaN NaN NaN NaN NaN NaN
186 158.579003 -60.676241 286.907995 -2.143636 1.431000e-08 6.734040e-11 3.959220e-08 1.771800e-10 5.490650e-08 2.286510e-10 ... 7.378240e-08 5.629940e-10 NaN NaN NaN NaN NaN NaN 0.547826 0.139770
187 158.576333 -60.676827 286.907158 -2.144799 4.302820e-10 3.753040e-11 1.594290e-09 5.666400e-11 3.113620e-09 8.523950e-11 ... 5.999620e-09 3.966240e-10 NaN NaN NaN NaN NaN NaN NaN NaN
188 158.583188 -60.679296 286.911303 -2.145250 2.556870e-09 3.030260e-11 8.227790e-09 7.297320e-11 1.425060e-08 1.083070e-10 ... 2.412240e-08 4.076210e-10 NaN NaN NaN NaN NaN NaN 0.570677 0.428726
189 158.580621 -60.679310 286.910222 -2.145893 8.697740e-10 2.652580e-11 3.727510e-09 6.123480e-11 7.706750e-09 9.265820e-11 ... 1.503800e-08 3.841620e-10 NaN NaN NaN NaN NaN NaN NaN NaN

190 rows Ɨ 22 columns

InĀ [Ā ]:
# turn all phtommetry into an numpy array
phot = df[["g_maggies", "r_maggies", "i_maggies", "z_maggies", "y_maggies", "j_maggies", "h_maggies", "k_maggies"]].to_numpy()
err = df[["g_err_maggies", "r_err_maggies", "i_err_maggies", "z_err_maggies", "y_err_maggies", "j_err_maggies", "h_err_maggies", "k_err_maggies"]].to_numpy()
mask_band = ~np.isnan(phot)
coords = df[["l", "b"]].to_numpy()
parallax = df["parallax_mas"].to_numpy()
parallax_err = df["parallax_err_mas"].to_numpy()
InĀ [Ā ]:
# fit a set of hypothetical objects
BF_mist.fit(
    phot,  # fluxes (in maggies)
    err,  # errors (in maggies)
    mask_band,  # band mask (True/False whether band was observed)
    np.arange(len(phot)),  # additional information to be written out
    "dust_region_brutus_mist",  # filename where results are stored (.h5 automatically added)
    data_coords=coords,  # array of (l, b) coordinates for Galactic prior
    parallax=parallax,
    parallax_err=parallax_err,  # parallax measurements (in mas)
    phot_offsets=off_mist,  # photometric offsets applied to **data**
    # dustfile=dustfile,  # 3-D dustmap prior
    Ndraws=500,  # number of samples to save to disk
    Nmc_prior=50,  # number of Monte Carlo draws used to incorporate priors
    logl_dim_prior=True,  # use chi2 distribution instead of Gaussian
    save_dar_draws=True,  # save (dist, Av, Rv) samples
    running_io=True,  # write out objects as soon as they finish
    verbose=True,
)  # print progress
InĀ [5]:
# now open dust_region_brutus_mist.h5 to examine results
hf = h5py.File("dust_region_brutus_mist.h5", "r")
print(list(hf.keys()))
['labels', 'ml_av', 'ml_cov_sar', 'ml_rv', 'ml_scale', 'model_idx', 'obj_Nbands', 'obj_chi2min', 'obj_log_evid', 'obj_log_post', 'samps_dist', 'samps_dred', 'samps_logp', 'samps_red']
InĀ [6]:
# load results
f = h5py.File("dust_region_brutus_mist.h5", "r")
idxs_mist = f["model_idx"][:]  # model indices
chi2_mist = f["obj_chi2min"][:]  # best-fit chi2
nbands_mist = f["obj_Nbands"][:]  # number of bands in fit
dists_mist = f["samps_dist"][:]  # distance samples
reds_mist = f["samps_red"][:]  # A(V) samples
dreds_mist = f["samps_dred"][:]  # R(V) samples
lnps_mist = f["samps_logp"][:]  # log-posterior of samples
InĀ [Ā ]:
from brutus import plotting as bplot
InĀ [Ā ]:
# pick an object
i = 2

fig = plt.subplots(1, 1, figsize=(6, 6))

fig, ax, parts = bplot.posterior_predictive(
    models_mist,  # stellar model grid
    idxs_mist[i],  # model indices
    reds_mist[i],  # A(V) draws
    dreds_mist[i],  # R(V) draws
    dists_mist[i],  # distance draws
    data=phot[i],
    data_err=err[i],  # data
    data_mask=mask[i],  # band mask
    offset=off_mist,  # photometric offsets
    psig=2.0,  # plot 2-sigma errors
    labels=filt,  # filters
    vcolor="blue",  # "violin plot" colors for the posteriors
    pcolor="black",
    fig=fig,
)  # photometry colors for the data
InĀ [20]:
# Convert Gaia parallax to distance in kpc
valid_gaia = (parallax > 0) & (~np.isnan(parallax))
gaia_dist = np.full_like(parallax, np.nan)
gaia_dist_err = np.full_like(parallax, np.nan)
gaia_dist[valid_gaia] = 1 / parallax[valid_gaia]
gaia_dist_err[valid_gaia] = (1 / parallax[valid_gaia] ** 2) * parallax_err[valid_gaia]

# Compute percentiles for Gaia distances in the fitted distributions
median_dist = np.median(dists_mist, axis=1)
percentiles_lower = np.full_like(parallax, np.nan)
percentiles_upper = np.full_like(parallax, np.nan)
for i in np.where(valid)[0]:
    percentiles_lower[i] = np.median(dists_mist[i, :]) - np.percentile(dists_mist[i, :], 16)
    percentiles_upper[i] = np.percentile(dists_mist[i, :], 84) - np.median(dists_mist[i, :])
percentiles = np.vstack([percentiles_lower, percentiles_upper])

i_mag = -2.5 * np.log10(phot[:, 2])

mask = valid_gaia & (~np.isnan(median_dist))

# Plot
plt.figure(figsize=(10, 8))
plt.errorbar(median_dist[mask], gaia_dist[mask], yerr=gaia_dist_err[mask], xerr=percentiles[:, mask], fmt="o", capsize=5)
# plt.colorbar()
plt.xlabel("Fitted Distance (kpc)")
plt.ylabel("Gaia Distance (kpc)")
plt.title("Gaia Distance vs Fitted Distance with Percentiles")
plt.plot([0, 5], [0, 5], "r--", alpha=0.5)  # 1:1 line
plt.xlim(0, 5)
plt.ylim(0, 5)
plt.show()
No description has been provided for this image
InĀ [28]:
plt.figure(figsize=(10, 6))

# Determine colors based on data availability
has_2mass = np.any(mask_band[:, 5:8], axis=1)
colors = []
for i in range(len(idxs_mist)):
    if valid_gaia[i] and has_2mass[i]:
        colors.append("purple")
    elif valid_gaia[i]:
        colors.append("blue")
    elif has_2mass[i]:
        colors.append("red")
    else:
        colors.append("black")

for i in range(len(idxs_mist)):
    # plt.plot(dists_mist[i, :], reds_mist[i, :], "k.", alpha=0.1)
    # plot with average and error bar
    plt.errorbar(
        np.median(dists_mist[i, :]),
        np.median(reds_mist[i, :]),
        xerr=[
            [np.median(dists_mist[i, :]) - np.percentile(dists_mist[i, :], 16)],
            [np.percentile(dists_mist[i, :], 84) - np.median(dists_mist[i, :])],
        ],
        yerr=[
            [np.median(reds_mist[i, :]) - np.percentile(reds_mist[i, :], 16)],
            [np.percentile(reds_mist[i, :], 84) - np.median(reds_mist[i, :])],
        ],
        fmt="o",
        color=colors[i],
        alpha=0.7,
    )
plt.xlabel("Distance (kpc)")
plt.ylabel("A(V) (mag)")
plt.xlim(0, 5)

# Add legend
import matplotlib.patches as mpatches

black_patch = mpatches.Patch(color="black", label="DECaPS only")
red_patch = mpatches.Patch(color="red", label="D + 2MASS")
blue_patch = mpatches.Patch(color="blue", label="D + Gaia")
purple_patch = mpatches.Patch(color="purple", label="D + Gaia + 2MASS")
plt.legend(handles=[black_patch, red_patch, blue_patch, purple_patch])

plt.show()
No description has been provided for this image