def get_ichrone(models, bands=None, default=False, tracks=False, basic=False, **kwargs): """Gets Isochrone Object by name, or type, with the right bands If `default` is `True`, then will set bands to be the union of bands and default_bands """ if not bands: bands = None if isinstance(models, ModelGridInterpolator): return models if type(models) is type(type): ichrone = models(bands) elif models == 'mist': if tracks: from isochrones.mist import MIST_EvolutionTrack ichrone = MIST_EvolutionTrack(bands=bands, **kwargs) else: if basic: from isochrones.mist import MISTBasic_Isochrone ichrone = MISTBasic_Isochrone(bands=bands, **kwargs) else: from isochrones.mist import MIST_Isochrone ichrone = MIST_Isochrone(bands=bands, **kwargs) else: raise ValueError('Unknown stellar models: {}'.format(models)) return ichrone
def test_mist_basic(bands=['J']): ic = MIST_Isochrone(bands, version='1.0') ic2 = MIST_Isochrone(bands + ['TESS', 'BP', 'RP'], version='1.1') _basic_ic_checks(ic) _basic_ic_checks(ic2) assert np.isclose(ic.radius(1.0, 9.5, 0.0), 0.9764494078461442) assert np.isclose(ic.radius(1.01, 9.72, 0.02), 1.0671791635014685) assert np.isclose(ic.radius(1.21, 9.38, 0.11), 1.2963342261673843) assert np.isclose(ic.radius(0.61, 9.89, -0.22), 0.5873830516268735) assert np.isclose(ic2.radius(1.0, 9.5, 0.0), 0.9765234978729515) assert np.isclose(ic2.radius(1.01, 9.72, 0.02), 1.0671845393364638) assert np.isclose(ic2.radius(1.21, 9.38, 0.11), 1.2963536270911573) assert np.isclose(ic2.radius(0.61, 9.89, -0.22), 0.5873849015685695)
def test_mist_basic(bands=['G','B','V','J','H','K','W1','W2','W3']): ic = MIST_Isochrone(bands) _basic_ic_checks(ic) print('{} ({})'.format(ic.radius(1.0, 9.5, 0.0), 0.9764494078461442)) assert np.isclose(ic.radius(1.0, 9.5, 0.0), 0.9764494078461442) assert np.isclose(ic.radius(1.01, 9.72, 0.02), 1.0671791635014685) assert np.isclose(ic.radius(1.21, 9.38, 0.11), 1.2836469028034225) assert np.isclose(ic.radius(0.61, 9.89, -0.22), 0.59475269177846402)
def test_mist_basic(bands='JHK'): ic = MIST_Isochrone(bands) _basic_ic_checks(ic) assert np.isclose(ic.logg(632, 7.55, -1.75), 2.4117770214014103) # Grid point assert np.isclose(ic.logg(355, 9.653, 0.0), 4.4124675) assert np.isclose(ic.logg(700, 9.3, -0.03), 2.24831956)
def get_ichrone(models, bands=None, default=False, **kwargs): """Gets Isochrone Object by name, or type, with the right bands If `default` is `True`, then will set bands to be the union of bands and default_bands """ if isinstance(models, Isochrone): return models def actual(bands, ictype): if bands is None: return list(ictype.default_bands) elif default: return list(set(bands).union(set(ictype.default_bands))) else: return bands if type(models) is type(type): ichrone = models(actual(bands, models)) elif models == 'dartmouth': from isochrones.dartmouth import Dartmouth_Isochrone ichrone = Dartmouth_Isochrone(bands=actual(bands, Dartmouth_Isochrone), **kwargs) elif models == 'dartmouthfast': from isochrones.dartmouth import Dartmouth_FastIsochrone ichrone = Dartmouth_FastIsochrone(bands=actual( bands, Dartmouth_FastIsochrone), **kwargs) elif models == 'mist': from isochrones.mist import MIST_Isochrone ichrone = MIST_Isochrone(bands=actual(bands, MIST_Isochrone), **kwargs) elif models == 'padova': from isochrones.padova import Padova_Isochrone ichrone = Padova_Isochrone(bands=actual(bands, Padova_Isochrone), **kwargs) elif models == 'basti': from isochrones.basti import Basti_Isochrone ichrone = Basti_Isochrone(bands=actual(bands, Basti_Isochrone), **kwargs) else: raise ValueError('Unknown stellar models: {}'.format(models)) return ichrone
#!/usr/bin/python3 import os import sys import numpy as np import pandas as pd import h5py import tqdm import emcee from isochrones.mist import MIST_Isochrone from isochrones import StarModel mist = MIST_Isochrone() import stardate as sd from stardate.lhf import lnprob from multiprocessing import Pool # Necessary to add cwd to path when script run # by SLURM (since it executes a copy) sys.path.append(os.getcwd()) # def infer_stellar_age(row): # df = row[1] def infer_stellar_age(df): # Small observational uncertainties are needed (even though the stars # weren't simulated with any) in order to get a good fit.
} labels = { 'G': r'$G$', 'J': r'$J$', 'H': r'$H$', 'K': r'$K$', 'PanSTARRS_g': r'$g_\mathrm{PS}$', 'PanSTARRS_r': r'$r_\mathrm{PS}$', 'PanSTARRS_i': r'$i_\mathrm{PS}$', 'PanSTARRS_z': r'$z_\mathrm{PS}$', 'PanSTARRS_y': r'$y_\mathrm{PS}$', } mist = MIST_Isochrone(bands=[ 'G', 'J', 'H', 'K', 'PanSTARRS_g', 'PanSTARRS_r', 'PanSTARRS_i', 'PanSTARRS_z', 'PanSTARRS_y' ]) # MIST ages are in 0.05 dex increment, but the values are not exact. # So if I query `mist.df.loc[0, 8.7]` for feh=0, age=8.7 it will incur # index not found error because the actual value is 8.7000...1, which is kind of stupid. def get_isodf(feh, logage): """Get sub-dataframe for given feh and logage""" iage = np.abs(mist.ages - logage).argmin() return mist.df.loc[feh, mist.ages[iage]] def plotcmd_mist_isochrones(band1, band2, feh,
def main(index, overwrite=False): # First make sure paths exist: # os.makedirs('../cache', exist_ok=True) # os.makedirs('../plots/isochrones', exist_ok=True) # Load the DECam photometry decam = load_data('../data/decam_apw.fits') iso = MIST_Isochrone(['PanSTARRS_g', 'PanSTARRS_i', 'SkyMapper_u']) row = decam[index] name = 'lmcla-{0}-'.format(row['index']) model_file = '../cache/starmodels-{0}.hdf5'.format(str(row['index'])) if path.exists(model_file) and not overwrite: print('skipping {0} - already exists'.format(name)) sys.exit(0) # This is our "anchor star": it was identified as being near the turnoff, # bright, and positionally consistent with being in the LA cluster: j1, = np.where(decam['index'] == 24365)[0] j2 = index if j1 == j2: print('skipping anchor-anchor pair') sys.exit(0) # To fit pairs as resolved binaries, we have to construct the observation # tree manually: tree = ObservationTree() for b in ['PanSTARRS_g', 'PanSTARRS_i', 'SkyMapper_u']: survey, band = b.split('_') if band == 'u' and decam[band.capitalize() + 'MAG'][j2] > 21: extra_s = 0.2 else: extra_s = 0.005 o = Observation(survey, b, 1.) s0 = Source( decam[band.capitalize() + 'MAG'][j1], np.sqrt(0.005**2 + decam[band.capitalize() + 'ERR'][j1]**2)) s1 = Source(decam[band.capitalize() + 'MAG'][j2], np.sqrt(extra_s**2 + decam[band.capitalize() + 'ERR'][j2]**2), separation=100.) o.add_source(s0) o.add_source(s1) tree.add_observation(o) model = StarModel(ic=iso, obs=tree, N=[1, 2]) # model = StarModel(ic=iso, obs=tree) print('setting priors') dist_bounds = [1 * 1e3, 100 * 1e3] # pc # model._priors['distance'] = FlatPrior(dist_bounds) model._priors['distance'] = GaussianPrior(30 * 1e3, 10 * 1e3, bounds=dist_bounds) model.set_bounds(distance=dist_bounds) # 1 to 100 kpc feh_bounds = (-2., 0.5) model.set_bounds(feh=feh_bounds) # model._priors['feh'] = FlatPrior(feh_bounds) model._priors['feh'] = GaussianPrior(-1.1, 0.5, bounds=feh_bounds) AV_bounds = (0, 1) model.set_bounds(AV=AV_bounds) model._priors['AV'] = PowerLawPrior(-1.1, (1e-3, 1)) # model._priors['AV'] = GaussianPrior(0.2, 0.1, bounds=AV_bounds) age_bounds = (7, 9.5) model.set_bounds(age=age_bounds) # model._priors['age'] = GaussianPrior(8, 0.5, bounds=age_bounds) model._priors['age'] = FlatPrior(age_bounds) print('sampling star {0}'.format(row['index'])) model.fit_multinest(basename=name, refit=overwrite, overwrite=overwrite, n_live_points=2048) # model.fit_mcmc(nwalkers=nwalkers, # p0=np.array([350., 8., -0.5, 30000., 0.1]), # nburn=1024, niter=2048) model.save_hdf(model_file) fig = model.corner_physical() fig.savefig('../plots/isochrones/{0}-physical.png'.format(row['index']), dpi=200) plt.close(fig) fig = model.corner_observed() fig.savefig('../plots/isochrones/{0}-observed.png'.format(row['index']), dpi=200) plt.close(fig) # model._samples = model.samples[::1024] # model.save_hdf(sm_model_file) sys.exit(0)
import tempfile import os, shutil, glob import logging import numpy as np from isochrones.dartmouth import Dartmouth_Isochrone from isochrones.mist import MIST_Isochrone from isochrones import StarModel, get_ichrone DAR = Dartmouth_Isochrone() MIST = MIST_Isochrone() def test_dartmouth_basic(bands=['z', 'B', 'W3', 'LSST_r', 'J', 'UK_J']): dar = Dartmouth_Isochrone(bands) _basic_ic_checks(dar) print('{} ({})'.format(dar.radius(1., 9.5, 0.0), 0.95409593462955189)) assert np.isclose(dar.radius(1., 9.5, 0.0), 0.95409593462955189) assert np.isclose(dar.radius(1.01, 9.72, 0.02), 1.0435559519926865) assert np.isclose(dar.radius(1.21, 9.38, 0.11), 1.2762022494652547) assert np.isclose(dar.radius(0.61, 9.89, -0.22), 0.5964945760402941) def test_mist_basic(bands=['G','B','V','J','H','K','W1','W2','W3']): ic = MIST_Isochrone(bands) _basic_ic_checks(ic) print('{} ({})'.format(ic.radius(1.0, 9.5, 0.0), 0.9764494078461442)) assert np.isclose(ic.radius(1.0, 9.5, 0.0), 0.9764494078461442) assert np.isclose(ic.radius(1.01, 9.72, 0.02), 1.0671791635014685) assert np.isclose(ic.radius(1.21, 9.38, 0.11), 1.2836469028034225) assert np.isclose(ic.radius(0.61, 9.89, -0.22), 0.59475269177846402)
def test_mist_basic(bands=['G', 'B', 'V', 'J', 'H', 'K', 'W1', 'W2', 'W3']): ic = MIST_Isochrone(bands) _basic_ic_checks(ic)
def fit_star(star, verbose=False): output_filename = "{0}.h5".format(star.kepid) logging.info("Output filename: {0}".format(output_filename)) if os.path.exists(output_filename): return time.sleep(30) return strt = time.time() # The KIC parameters mean_log_mass = np.log(star.mass) sigma_log_mass = (np.log(star.mass + star.mass_err1) - np.log(star.mass + star.mass_err2) ) # double the kic value mean_feh = star.feh sigma_feh = star.feh_err1 - star.feh_err2 # double the kic value min_distance, max_distance = 0.0, 3000.0 # Other bands other_bands = dict() if np.isfinite(star.tgas_w1gmag): other_bands = dict( W1=(star.tgas_w1gmag, star.tgas_w1gmag_error), W2=(star.tgas_w2gmag, star.tgas_w2gmag_error), W3=(star.tgas_w3gmag, star.tgas_w3gmag_error), ) if np.isfinite(star.tgas_Vmag): other_bands["V"] = (star.tgas_Vmag, star.tgas_e_Vmag) if np.isfinite(star.tgas_Bmag): other_bands["B"] = (star.tgas_Bmag, star.tgas_e_Bmag) if np.isfinite(star.tgas_gpmag): other_bands["g"] = (star.tgas_gpmag, star.tgas_e_gpmag) if np.isfinite(star.tgas_rpmag): other_bands["r"] = (star.tgas_rpmag, star.tgas_e_rpmag) if np.isfinite(star.tgas_ipmag): other_bands["i"] = (star.tgas_ipmag, star.tgas_e_ipmag) # Build the model mist = MIST_Isochrone() mod = StarModel(mist, J=(star.jmag, star.jmag_err), H=(star.hmag, star.hmag_err), K=(star.kmag, star.kmag_err), parallax=(star.tgas_parallax, star.tgas_parallax_error), **other_bands) # Initialize nwalkers = 500 ndim = 5 lnpost_init = -np.inf + np.zeros(nwalkers) coords_init = np.empty((nwalkers, ndim)) m = ~np.isfinite(lnpost_init) while np.any(m): K = m.sum() # Mass coords_init[m, 0] = np.exp(mean_log_mass + sigma_log_mass * np.random.randn(K)) # Age u = np.random.rand(K) coords_init[m, 1] = np.log((np.exp(mist.maxage) - np.exp(mist.minage)) * u + np.exp(mist.minage)) # Fe/H coords_init[m, 2] = mean_feh + sigma_feh * np.random.randn(K) # Distance u = np.random.rand(K) coords_init[m, 3] = (u * (max_distance**3 - min_distance**3) + min_distance**3)**(1. / 3) # Av coords_init[m, 4] = np.random.rand(K) lnpost_init[m] = np.array(list(map(mod.lnpost, coords_init[m]))) m = ~np.isfinite(lnpost_init) class ICModel(emcee3.Model): def compute_log_prior(self, state): state.log_prior = mod.lnprior(state.coords) return state def compute_log_likelihood(self, state): state.log_likelihood = mod.lnlike(state.coords) return state sampler = emcee3.Sampler(emcee3.moves.KDEMove()) ensemble = emcee3.Ensemble(ICModel(), coords_init) chunksize = 200 targetn = 3 for iteration in range(100): if verbose: print("Iteration {0}...".format(iteration + 1)) sampler.run(ensemble, chunksize, progress=verbose) mu = np.mean(sampler.get_coords(), axis=1) try: tau = emcee3.autocorr.integrated_time(mu, c=1) except emcee3.autocorr.AutocorrError: continue tau_max = tau.max() neff = ((iteration + 1) * chunksize / tau_max - 2.0) if verbose: print("Maximum autocorrelation time: {0}".format(tau_max)) print("N_eff: {0}\n".format(neff * nwalkers)) if neff > targetn: break burnin = int(2 * tau_max) ntot = 5000 if verbose: print("Discarding {0} samples for burn-in".format(burnin)) print("Randomly choosing {0} samples".format(ntot)) samples = sampler.get_coords(flat=True, discard=burnin) total_samples = len(total_samples) inds = np.random.choice(np.arange(len(samples)), size=ntot, replace=False) samples = samples[inds] fit_parameters = np.empty(len(samples), dtype=[ ("mass", float), ("log10_age", float), ("feh", float), ("distance", float), ("av", float), ]) computed_parameters = np.empty(len(samples), dtype=[ ("radius", float), ("teff", float), ("logg", float), ]) if verbose: prog = tqdm.tqdm else: prog = lambda f, *args, **kwargs: f for i, p in prog(enumerate(samples), total=len(samples)): ic = mod.ic(*p) fit_parameters[i] = p computed_parameters[i] = (ic["radius"], ic["Teff"], ic["logg"]) total_time = time.time() - strt logging.info("emcee3 took {0} sec".format(total_time)) with h5py.File(output_filename, "w") as f: f.attrs["kepid"] = int(star.kepid) f.attrs["neff"] = neff * nwalkers f.attrs["runtime"] = total_time f.create_dataset("fit_parameters", data=fit_parameters) f.create_dataset("computed_parameters", data=computed_parameters) # Plot fig = corner.corner(samples) fig.savefig("corner-{0}.png".format(star.kepid)) plt.close(fig)
import numpy as np import matplotlib.pyplot as plt import pandas as pd from tqdm import tqdm, trange import emcee import read_mist_models from isochrones.mist import MIST_Isochrone from isochrones import StarModel from stardate.lhf import gyro_model_rossby, gyro_model, sigma, calc_rossby_number bands = ["B", "V", "J", "H", "K", "BP", "RP", "G"] mist = MIST_Isochrone(bands) mist.initialize() def color_err(c): c_err = np.zeros(len(c)) bright = c < 13 medium = (13 < c) * (c < 17) faint = 17 <= c c_err[bright] = np.ones(len(c_err[bright])) * .002 c_err[medium] = np.ones(len(c_err[medium])) * .01 c_err[faint] = np.ones(len(c_err[faint])) * .2 return c_err def photometric_noise(G, bp, rp): """ Calculates the noise on Gaia G, bp, rp and parallax.
def get_isochrone(logage, feh): """Retrieve isochrone for given age and feh.""" mist = MIST_Isochrone() iso = mist.isochrone(logage, feh) return iso