Exemple #1
0
 def __init__(self, ext=2.63, dist=7.971e3,
              filts_list=['nirc2,Kp', 'nirc2,H']):
     # Define extinction and distance
     self.A_Ks = ext
     self.dist = dist * u.pc
     
     # Specify filters and get filter information
     self.filts_list = filts_list
     self.num_filts = len(self.filts_list)
     
     self.filts_info = []
     self.filts_flux_ref = np.empty(self.num_filts) *\
                               (u.erg / u.s) / (u.cm**2.)
     for cur_filt_index in range(self.num_filts):
         cur_filt = self.filts_list[cur_filt_index]
         
         cur_filt_info = synthetic.get_filter_info(cur_filt)
         self.filts_info.append(cur_filt_info)
         
         cur_filt_flux_ref = cur_filt_info.flux0 * (u.erg / u.s) / (u.cm**2.)
         self.filts_flux_ref[cur_filt_index] = cur_filt_flux_ref
     
     # Define atmosphere and reddening functions
     self.bb_atm_func = atmospheres.get_bb_atmosphere
     self.red_law = reddening.RedLawNoguerasLara18()
    def make_bb_params(self, Ks_ext, dist, filts_list=['nirc2,Kp', 'nirc2,H']):
        self.Ks_ext = Ks_ext

        self.dist = dist * u.pc
        self.default_dist = dist
        ## Revise prior bounds for distance
        self.lo_dist_prior_bound = 0.8 * dist
        self.hi_dist_prior_bound = 1.2 * dist

        # Filter info and convert extinction to fit filters
        self.filts_list = filts_list
        self.num_filts = len(self.filts_list)

        self.filts_info = []
        self.filts_flux_ref = np.empty(self.num_filts) *\
                                  (u.erg / u.s) / (u.cm**2.)

        self.filts_ext = {}

        for cur_filt_index in range(self.num_filts):
            cur_filt = self.filts_list[cur_filt_index]

            cur_filt_info = synthetic.get_filter_info(cur_filt)
            self.filts_info.append(cur_filt_info)

            cur_filt_flux_ref = cur_filt_info.flux0 * (u.erg / u.s) / (u.cm**
                                                                       2.)
            self.filts_flux_ref[cur_filt_index] = cur_filt_flux_ref

            # Convert from specified extinction in Ks to current filter
            cur_filt_ext = (
                Ks_ext *
                (self.lambda_Ks / self.filts_lambda[cur_filt])**self.ext_alpha)

            self.filts_ext[cur_filt] = cur_filt_ext

        # Make blackbody stellar params object
        self.bb_params_obj = blackbody_params.bb_stellar_params(
            ext=self.Ks_ext,
            dist=self.dist.to(u.pc).value,
            filts_list=self.filts_list)
class mcmc_fitter_bb(object):
    # Filter properties
    lambda_Ks = 2.18e-6 * u.m
    dlambda_Ks = 0.35e-6 * u.m

    filts_lambda = {'nirc2,Kp': 2.124e-6 * u.m, 'nirc2,H': 1.633e-6 * u.m}
    filts_dlambda = {'nirc2,Kp': 0.351e-6 * u.m, 'nirc2,H': 0.296e-6 * u.m}

    ks_filt_info = synthetic.get_filter_info('naco,Ks')

    flux_ref_Ks = ks_filt_info.flux0 * (u.erg / u.s) / (u.cm**2.)

    # Extinction law (using Nogueras-Lara+ 2018)
    ext_alpha = 2.30
    ext_alpha_unc = 0.08

    # Number of triangles and atmosphere to use for binary model
    use_blackbody_atm = True
    model_numTriangles = 1500

    # Model H Extinction Modifier
    default_H_ext_mod = 0.0
    model_H_ext_mod = True

    # Model eccentricity
    default_ecc = 0.0
    model_eccentricity = True

    # Model distance
    default_dist = 7.971e3
    model_distance = True

    # Model star 1 parameters
    model_star1_mass = True
    default_star1_mass = 10.0 * u.solMass

    model_star1_rad = True
    default_star1_rad = 10.0 * u.solRad

    model_star1_teff = True
    default_star1_teff = 8000. * u.K

    # Model star 2 parameters
    model_star2_mass = True
    default_star2_mass = 10.0 * u.solMass

    model_star2_rad = True
    default_star2_rad = 10.0 * u.solRad

    model_star2_teff = True
    default_star2_teff = 8000. * u.K

    # Default prior bounds
    # Extinction prior bounds
    lo_Kp_ext_prior_bound = 2.0
    hi_Kp_ext_prior_bound = 4.0

    lo_H_ext_mod_prior_bound = -2.0
    hi_H_ext_mod_prior_bound = 2.0

    H_ext_mod_alpha_sig_bound = -1.0

    # Star 1 prior bounds
    lo_star1_mass_prior_bound = 0.1
    hi_star1_mass_prior_bound = 20

    lo_star1_rad_prior_bound = 0.1
    hi_star1_rad_prior_bound = 100

    lo_star1_teff_prior_bound = 5000
    hi_star1_teff_prior_bound = 50000

    star1_teff_sig_bound = False
    star1_teff_bound_mu = 10000
    star1_teff_bound_sigma = 1000

    # Star 2 prior bounds
    lo_star2_mass_prior_bound = 0.1
    hi_star2_mass_prior_bound = 20

    lo_star2_rad_prior_bound = 0.1
    hi_star2_rad_prior_bound = 100

    lo_star2_teff_prior_bound = 5000
    hi_star2_teff_prior_bound = 50000

    # Binary system prior bounds
    lo_inc_prior_bound = 0.
    hi_inc_prior_bound = 180.

    lo_period_prior_bound = 79.
    hi_period_prior_bound = 81.

    lo_ecc_prior_bound = -0.1
    hi_ecc_prior_bound = 0.1

    lo_dist_prior_bound = 7600.
    hi_dist_prior_bound = 8200.

    lo_t0_prior_bound = 51773.0
    hi_t0_prior_bound = 51774.0

    def __init__(self):
        return

    # Functions to make blackbody parameters object
    def make_bb_params(self, Ks_ext, dist, filts_list=['nirc2,Kp', 'nirc2,H']):
        self.Ks_ext = Ks_ext

        self.dist = dist * u.pc
        self.default_dist = dist
        ## Revise prior bounds for distance
        self.lo_dist_prior_bound = 0.8 * dist
        self.hi_dist_prior_bound = 1.2 * dist

        # Filter info and convert extinction to fit filters
        self.filts_list = filts_list
        self.num_filts = len(self.filts_list)

        self.filts_info = []
        self.filts_flux_ref = np.empty(self.num_filts) *\
                                  (u.erg / u.s) / (u.cm**2.)

        self.filts_ext = {}

        for cur_filt_index in range(self.num_filts):
            cur_filt = self.filts_list[cur_filt_index]

            cur_filt_info = synthetic.get_filter_info(cur_filt)
            self.filts_info.append(cur_filt_info)

            cur_filt_flux_ref = cur_filt_info.flux0 * (u.erg / u.s) / (u.cm**
                                                                       2.)
            self.filts_flux_ref[cur_filt_index] = cur_filt_flux_ref

            # Convert from specified extinction in Ks to current filter
            cur_filt_ext = (
                Ks_ext *
                (self.lambda_Ks / self.filts_lambda[cur_filt])**self.ext_alpha)

            self.filts_ext[cur_filt] = cur_filt_ext

        # Make blackbody stellar params object
        self.bb_params_obj = blackbody_params.bb_stellar_params(
            ext=self.Ks_ext,
            dist=self.dist.to(u.pc).value,
            filts_list=self.filts_list)

    # Function to set observation filters
    def set_observation_filts(self, obs_filts):
        self.obs_filts = obs_filts

        self.search_filt_kp = np.where(self.obs_filts == 'kp')
        self.search_filt_h = np.where(self.obs_filts == 'h')

    # Function to set observation times
    def set_observation_times(self, obs_times):
        self.obs_times = obs_times

        self.observation_times = (obs_times[self.search_filt_kp],
                                  obs_times[self.search_filt_h])

    # Function to set observation mags
    def set_observation_mags(self, obs_mags, obs_mag_errors):
        self.obs_mags = obs_mags
        self.obs_mag_errors = obs_mag_errors

        self.kp_obs_mags = obs_mags[self.search_filt_kp]
        self.kp_obs_mag_errors = obs_mag_errors[self.search_filt_kp]

        self.h_obs_mags = obs_mags[self.search_filt_h]
        self.h_obs_mag_errors = obs_mag_errors[self.search_filt_h]

    # Function to set model mesh number of triangles
    def set_model_numTriangles(self, model_numTriangles):
        self.model_numTriangles = model_numTriangles

    # Function to set if using blackbody atmosphere
    def set_model_use_blackbody_atm(self, use_blackbody_atm):
        self.use_blackbody_atm = use_blackbody_atm

    # Functions to define prior bounds
    # Extinction priors
    def set_Kp_ext_prior_bounds(self, lo_bound, hi_bound):
        self.lo_Kp_ext_prior_bound = lo_bound
        self.hi_Kp_ext_prior_bound = hi_bound

    def set_H_ext_mod_prior_bounds(self, lo_bound, hi_bound):
        self.lo_H_ext_mod_prior_bound = lo_bound
        self.hi_H_ext_mod_prior_bound = hi_bound

    def set_H_ext_mod_extLaw_sig_prior_bounds(self, sigma_bound):
        self.H_ext_mod_alpha_sig_bound = sigma_bound

    # Stellar parameter priors
    def set_star1_mass_prior_bounds(self, lo_bound, hi_bound):
        self.lo_star1_mass_prior_bound = lo_bound
        self.hi_star1_mass_prior_bound = hi_bound

    def set_star1_rad_prior_bounds(self, lo_bound, hi_bound):
        self.lo_star1_rad_prior_bound = lo_bound
        self.hi_star1_rad_prior_bound = hi_bound

    def set_star1_teff_prior_bounds(self, lo_bound, hi_bound):
        self.lo_star1_teff_prior_bound = lo_bound
        self.hi_star1_teff_prior_bound = hi_bound

    def set_star2_mass_prior_bounds(self, lo_bound, hi_bound):
        self.lo_star2_mass_prior_bound = lo_bound
        self.hi_star2_mass_prior_bound = hi_bound

    def set_star2_rad_prior_bounds(self, lo_bound, hi_bound):
        self.lo_star2_rad_prior_bound = lo_bound
        self.hi_star2_rad_prior_bound = hi_bound

    def set_star2_teff_prior_bounds(self, lo_bound, hi_bound):
        self.lo_star2_teff_prior_bound = lo_bound
        self.hi_star2_teff_prior_bound = hi_bound

    # Binary system parameter priors
    def set_inc_prior_bounds(self, lo_bound, hi_bound):
        self.lo_inc_prior_bound = lo_bound
        self.hi_inc_prior_bound = hi_bound

    def set_period_prior_bounds(self, lo_bound, hi_bound):
        self.lo_period_prior_bound = lo_bound
        self.hi_period_prior_bound = hi_bound

    def set_ecc_prior_bounds(self, lo_bound, hi_bound):
        self.lo_ecc_prior_bound = lo_bound
        self.hi_ecc_prior_bound = hi_bound

    def set_dist_prior_bounds(self, lo_bound, hi_bound):
        self.lo_dist_prior_bound = lo_bound
        self.hi_dist_prior_bound = hi_bound

    def set_t0_prior_bounds(self, lo_bound, hi_bound):
        self.lo_t0_prior_bound = lo_bound
        self.hi_t0_prior_bound = hi_bound

    # Priors
    def lnprior(self, theta):
        # Extract model parameters from theta
        theta_index = 0

        # Extinction model parameters
        Kp_ext = theta[theta_index]
        theta_index += 1

        if self.model_H_ext_mod:
            H_ext_mod = theta[theta_index]
            theta_index += 1
        else:
            H_ext_mod = self.default_H_ext_mod

        # Star 1 model parameters
        if self.model_star1_mass:
            star1_mass = theta[theta_index]
            theta_index += 1
        else:
            star1_mass = self.default_star1_mass

        if self.model_star1_rad:
            star1_rad = theta[theta_index]
            theta_index += 1
        else:
            star1_rad = self.default_star1_rad

        if self.model_star1_teff:
            star1_teff = theta[theta_index]
            theta_index += 1
        else:
            star1_teff = self.default_star1_teff

        # Star 2 model parameters
        if self.model_star2_mass:
            star2_mass = theta[theta_index]
            theta_index += 1
        else:
            star2_mass = self.default_star2_mass

        if self.model_star2_rad:
            star2_rad = theta[theta_index]
            theta_index += 1
        else:
            star2_rad = self.default_star2_rad

        if self.model_star2_teff:
            star2_teff = theta[theta_index]
            theta_index += 1
        else:
            star2_teff = self.default_star2_teff

        # Binary model parameters
        binary_inc = theta[theta_index]
        theta_index += 1

        binary_period = theta[theta_index]
        theta_index += 1

        if self.model_eccentricity:
            binary_ecc = theta[theta_index]
            theta_index += 1
        else:
            binary_ecc = self.default_ecc

        if self.model_distance:
            binary_dist = theta[theta_index]
            theta_index += 1
        else:
            binary_dist = self.default_dist

        t0 = theta[theta_index]

        ## Extinction checks
        Kp_ext_check = (self.lo_Kp_ext_prior_bound <= Kp_ext <=
                        self.hi_Kp_ext_prior_bound)

        H_ext_mod_check = True

        H_ext_mod_bound_oneSig = 1.0
        if self.H_ext_mod_alpha_sig_bound == -1.0:
            H_ext_mod_check = (self.lo_H_ext_mod_prior_bound <= H_ext_mod <=
                               self.hi_H_ext_mod_prior_bound)
        else:
            ### H extinction expected by Kp extinction
            H_ext = Kp_ext * ((self.filts_lambda['nirc2,Kp'] /
                               self.filts_lambda['nirc2,H'])**(self.ext_alpha))

            ### Bounds given by current extinction and uncertainty on extinction law
            H_ext_mod_bound_hi = Kp_ext * (
                (self.filts_lambda['nirc2,Kp'] / self.filts_lambda['nirc2,H'])
                **(self.ext_alpha + self.ext_alpha_unc))
            H_ext_mod_bound_lo = Kp_ext * (
                (self.filts_lambda['nirc2,Kp'] / self.filts_lambda['nirc2,H'])
                **(self.ext_alpha - self.ext_alpha_unc))

            ### Subtract off the H extinction expected by the Kp extinction to get mod
            H_ext_mod_bound_hi = H_ext_mod_bound_hi - H_ext
            H_ext_mod_bound_lo = H_ext - H_ext_mod_bound_lo

            H_ext_mod_bound_oneSig = np.max(
                np.abs([H_ext_mod_bound_hi, H_ext_mod_bound_lo]))

        # Stellar parameters checks
        star1_mass_check = True
        if self.model_star1_mass:
            star1_mass_check = (self.lo_star1_mass_prior_bound <= star1_mass <=
                                self.hi_star1_mass_prior_bound)

        star1_rad_check = True
        if self.model_star1_rad:
            star1_rad_check = (self.lo_star1_rad_prior_bound <= star1_rad <=
                               self.hi_star1_rad_prior_bound)

        star1_teff_check = True
        if self.model_star1_teff and (not self.star1_teff_sig_bound):
            star1_teff_check = (self.lo_star1_teff_prior_bound <= star1_teff <=
                                self.hi_star1_teff_prior_bound)

        star1_checks = star1_mass_check and star1_rad_check and star1_teff_check

        star2_mass_check = True
        if self.model_star2_mass:
            star2_mass_check = (self.lo_star2_mass_prior_bound <= star2_mass <=
                                self.hi_star2_mass_prior_bound)

        star2_rad_check = True
        if self.model_star2_rad:
            star2_rad_check = (self.lo_star2_rad_prior_bound <= star2_rad <=
                               self.hi_star2_rad_prior_bound)

        star2_teff_check = True
        if self.model_star2_teff:
            star2_teff_check = (self.lo_star2_teff_prior_bound <= star2_teff <=
                                self.hi_star2_teff_prior_bound)

        star2_checks = star2_mass_check and star2_rad_check and star2_teff_check

        ## Binary system configuration checks
        inc_check = (self.lo_inc_prior_bound <= binary_inc <=
                     self.hi_inc_prior_bound)
        period_check = (self.lo_period_prior_bound <= binary_period <=
                        self.hi_period_prior_bound)
        ecc_check = (self.lo_ecc_prior_bound <= binary_ecc <=
                     self.hi_ecc_prior_bound)
        dist_check = (self.lo_dist_prior_bound <= binary_dist <=
                      self.hi_dist_prior_bound)
        t0_check = (self.lo_t0_prior_bound <= t0 <= self.hi_t0_prior_bound)

        # print(Kp_ext_check)
        # print(H_ext_mod_check)
        # print(inc_check)
        # print(period_check)
        # print(ecc_check)
        # print(dist_check)
        # print(t0_check)
        # print(star1_checks)
        # print(star2_checks)

        ## Final check and return prior
        # If doing simple prior checks
        if self.H_ext_mod_alpha_sig_bound == -1.0 and not self.star1_teff_sig_bound:
            if ((Kp_ext_check and H_ext_mod_check) and inc_check
                    and period_check and ecc_check and dist_check and t0_check
                    and star1_checks and star2_checks):
                return 0.0
        else:  # Else doing Gaussian prior check on H_ext
            if (Kp_ext_check and inc_check and period_check and ecc_check
                    and dist_check and t0_check and star1_checks
                    and star2_checks):

                log_prior = 0.0

                # Return gaussian prior for H_ext_mod parameter
                if self.H_ext_mod_alpha_sig_bound is not -1.0:
                    log_prior_add = np.log(
                        1.0 / (np.sqrt(2 * np.pi) * H_ext_mod_bound_oneSig))
                    log_prior_add += (-0.5 * (H_ext_mod**2) /
                                      (H_ext_mod_bound_oneSig**2))

                    log_prior += log_prior_add

                # Return gaussian prior for Teff parameter
                if self.star1_teff_sig_bound:
                    log_prior_add = np.log(
                        1.0 /
                        (np.sqrt(2 * np.pi) * self.star1_teff_bound_sigma))
                    log_prior_add += (
                        -0.5 * (star1_teff - self.star1_teff_bound_mu)**2 /
                        self.star1_teff_bound_sigma**2)

                    log_prior += log_prior_add

                return log_prior

        # If here at this point, all previous checks failed
        return -np.inf

    # Calculate model light curve
    def calculate_model_lc(self, theta):
        # Extract model parameters from theta
        theta_index = 0

        # Extinction model parameters
        Kp_ext = theta[theta_index]
        theta_index += 1

        if self.model_H_ext_mod:
            H_ext_mod = theta[theta_index]
            theta_index += 1
        else:
            H_ext_mod = self.default_H_ext_mod

        # Star 1 model parameters
        if self.model_star1_mass:
            star1_mass = theta[theta_index] * u.solMass
            theta_index += 1
        else:
            star1_mass = self.default_star1_mass

        if self.model_star1_rad:
            star1_rad = theta[theta_index] * u.solRad
            theta_index += 1
        else:
            star1_rad = self.default_star1_rad

        if self.model_star1_teff:
            star1_teff = theta[theta_index] * u.K
            theta_index += 1
        else:
            star1_teff = self.default_star1_teff

        # Star 2 model parameters
        if self.model_star2_mass:
            star2_mass = theta[theta_index] * u.solMass
            theta_index += 1
        else:
            star2_mass = self.default_star2_mass

        if self.model_star2_rad:
            star2_rad = theta[theta_index] * u.solRad
            theta_index += 1
        else:
            star2_rad = self.default_star2_rad

        if self.model_star2_teff:
            star2_teff = theta[theta_index] * u.K
            theta_index += 1
        else:
            star2_teff = self.default_star2_teff

        # Binary model parameters
        binary_inc = theta[theta_index] * u.deg
        theta_index += 1

        binary_period = theta[theta_index] * u.d
        theta_index += 1

        if self.model_eccentricity:
            binary_ecc = theta[theta_index]
            theta_index += 1
        else:
            binary_ecc = self.default_ecc

        if self.model_distance:
            binary_dist = theta[theta_index] * u.pc
            theta_index += 1
        else:
            binary_dist = self.default_dist

        t0 = theta[theta_index]

        err_out = (np.array([-1.]), np.array([-1.]))

        ## Construct tuple with binary parameters
        binary_params = (binary_period, binary_ecc, binary_inc, t0)

        # Calculate extinction adjustments
        filt_ext_adj = np.empty(self.num_filts)

        Kp_ext_adj = (Kp_ext - self.filts_ext['nirc2,Kp'])
        H_ext_adj = ((
            (Kp_ext *
             (self.filts_lambda['nirc2,Kp'] / self.filts_lambda['nirc2,H'])**
             self.ext_alpha) - self.filts_ext['nirc2,H']) + H_ext_mod)

        filt_ext_adj = np.array([Kp_ext_adj, H_ext_adj])

        # Calculate distance modulus adjustments
        dist_mod_mag_adj = 5. * np.log10(binary_dist /
                                         ((self.dist).to(u.pc)).value)

        # Perform interpolation
        (star1_params_all,
         star1_params_lcfit) = self.bb_params_obj.calc_stellar_params(
             star1_mass, star1_rad, star1_teff)
        (star2_params_all,
         star2_params_lcfit) = self.bb_params_obj.calc_stellar_params(
             star2_mass, star2_rad, star2_teff)

        (star1_mass_init, star1_mass, star1_rad, star1_lum, star1_teff,
         star1_logg, [star1_mag_Kp,
                      star1_mag_H], [star1_pblum_Kp,
                                     star1_pblum_H]) = star1_params_all
        (star2_mass_init, star2_mass, star2_rad, star2_lum, star2_teff,
         star2_logg, [star2_mag_Kp,
                      star2_mag_H], [star2_pblum_Kp,
                                     star2_pblum_H]) = star2_params_all

        # Run binary star model to get binary mags
        (binary_mags_Kp, binary_mags_H) = lc_calc.binary_star_lc(
            star1_params_lcfit,
            star2_params_lcfit,
            binary_params,
            self.observation_times,
            use_blackbody_atm=self.use_blackbody_atm,
            use_compact_object=True,
            num_triangles=self.model_numTriangles)
        if (binary_mags_Kp[0] == -1.) or (binary_mags_H[0] == -1.):
            return err_out

        ## Apply isoc. distance modulus and isoc. extinction to binary magnitudes
        (binary_mags_Kp, binary_mags_H) = lc_calc.dist_ext_mag_calc(
            (binary_mags_Kp, binary_mags_H), self.dist,
            self.filts_ext['nirc2,Kp'], self.filts_ext['nirc2,H'])

        # Apply the extinction difference between model and the isochrone values
        binary_mags_Kp += Kp_ext_adj
        binary_mags_H += H_ext_adj

        # Apply the distance modulus for difference between isoc. distance and bin. distance
        # (Same for each filter)
        binary_mags_Kp += dist_mod_mag_adj
        binary_mags_H += dist_mod_mag_adj

        # Return final light curve
        return (binary_mags_Kp, binary_mags_H)

    # Log Likelihood function
    def lnlike(self, theta):
        # Extract model parameters from theta
        theta_index = 0

        # Extinction model parameters
        Kp_ext = theta[theta_index]
        theta_index += 1

        if self.model_H_ext_mod:
            H_ext_mod = theta[theta_index]
            theta_index += 1
        else:
            H_ext_mod = self.default_H_ext_mod

        # Star 1 model parameters
        if self.model_star1_mass:
            star1_mass = theta[theta_index] * u.solMass
            theta_index += 1
        else:
            star1_mass = self.default_star1_mass

        if self.model_star1_rad:
            star1_rad = theta[theta_index] * u.solRad
            theta_index += 1
        else:
            star1_rad = self.default_star1_rad

        if self.model_star1_teff:
            star1_teff = theta[theta_index] * u.K
            theta_index += 1
        else:
            star1_teff = self.default_star1_teff

        # Star 2 model parameters
        if self.model_star2_mass:
            star2_mass = theta[theta_index] * u.solMass
            theta_index += 1
        else:
            star2_mass = self.default_star2_mass

        if self.model_star2_rad:
            star2_rad = theta[theta_index] * u.solRad
            theta_index += 1
        else:
            star2_rad = self.default_star2_rad

        if self.model_star2_teff:
            star2_teff = theta[theta_index] * u.K
            theta_index += 1
        else:
            star2_teff = self.default_star2_teff

        # Binary model parameters
        binary_inc = theta[theta_index] * u.deg
        theta_index += 1

        binary_period = theta[theta_index] * u.d
        theta_index += 1

        if self.model_eccentricity:
            binary_ecc = theta[theta_index]
            theta_index += 1
        else:
            binary_ecc = self.default_ecc

        if self.model_distance:
            binary_dist = theta[theta_index] * u.pc
            theta_index += 1
        else:
            binary_dist = self.default_dist

        t0 = theta[theta_index]

        # Calculate light curve
        (binary_model_mags_Kp,
         binary_model_mags_H) = self.calculate_model_lc(theta)

        if (binary_model_mags_Kp[0] == -1.) or (binary_model_mags_H[0] == -1.):
            return -np.inf

        # Phase the observation times
        (kp_phase_out,
         h_phase_out) = lc_calc.phased_obs(self.observation_times,
                                           binary_period, t0)

        (kp_phased_days, kp_phases_sorted_inds, kp_model_times) = kp_phase_out
        (h_phased_days, h_phases_sorted_inds, h_model_times) = h_phase_out

        # Calculate log likelihood and return
        log_likelihood = np.sum(
            (self.kp_obs_mags[kp_phases_sorted_inds] - binary_model_mags_Kp)**
            2. / (self.kp_obs_mag_errors[kp_phases_sorted_inds])**2.)
        log_likelihood += np.sum(
            (self.h_obs_mags[h_phases_sorted_inds] - binary_model_mags_H)**2. /
            (self.h_obs_mag_errors[h_phases_sorted_inds])**2.)

        log_likelihood = -0.5 * log_likelihood

        return log_likelihood

    # Posterior Probability Function
    def lnprob(self, theta):
        lp = self.lnprior(theta)
        if not np.isfinite(lp):
            return -np.inf
        return lp + self.lnlike(theta)
from phoebe import u
from phoebe import c as const

import numpy as np

from spisea import synthetic

from phoebe_phitter import lc_calc, blackbody_params

import matplotlib.pyplot as plt
import matplotlib.font_manager as font_manager
from matplotlib.ticker import MultipleLocator

# Reference fluxes, calculated with PopStar
## Vega magnitudes (m_Vega = 0.03)
ks_filt_info = synthetic.get_filter_info('naco,Ks')

flux_ref_Ks = ks_filt_info.flux0 * (u.erg / u.s) / (u.cm**2.)

# Stellar Parameters
# stellar_params = (mass, rad, teff, mag_Kp, mag_H)


class mcmc_fitter_bb(object):
    # Filter properties
    lambda_Ks = 2.18e-6 * u.m
    dlambda_Ks = 0.35e-6 * u.m

    filts_lambda = {'nirc2,Kp': 2.124e-6 * u.m, 'nirc2,H': 1.633e-6 * u.m}
    filts_dlambda = {'nirc2,Kp': 0.351e-6 * u.m, 'nirc2,H': 0.296e-6 * u.m}
Exemple #5
0
class mcmc_fitter_base_interp(object):
    # Filter properties
    lambda_Ks = 2.18e-6 * u.m
    dlambda_Ks = 0.35e-6 * u.m

    lambda_Kp = 2.124e-6 * u.m
    dlambda_Kp = 0.351e-6 * u.m

    lambda_H = 1.633e-6 * u.m
    dlambda_H = 0.296e-6 * u.m

    ks_filt_info = synthetic.get_filter_info('naco,Ks')
    kp_filt_info = synthetic.get_filter_info('nirc2,Kp')
    h_filt_info = synthetic.get_filter_info('nirc2,H')

    flux_ref_Ks = ks_filt_info.flux0 * (u.erg / u.s) / (u.cm**2.)
    flux_ref_Kp = kp_filt_info.flux0 * (u.erg / u.s) / (u.cm**2.)
    flux_ref_H = h_filt_info.flux0 * (u.erg / u.s) / (u.cm**2.)

    # Extinction law (using Nogueras-Lara+ 2018)
    ext_alpha = 2.30
    ext_alpha_unc = 0.08

    # Number of triangles and atmosphere to use for binary model
    use_blackbody_atm = False
    model_numTriangles = 1500

    # Model H Extinction Modifier
    default_H_ext_mod = 0.0
    model_H_ext_mod = True

    # Model eccentricity
    default_ecc = 0.0
    model_eccentricity = True

    # Model distance
    default_dist = 7.971e3
    model_distance = True

    # Default prior bounds
    lo_Kp_ext_prior_bound = 2.0
    hi_Kp_ext_prior_bound = 4.0

    lo_H_ext_mod_prior_bound = -2.0
    hi_H_ext_mod_prior_bound = 2.0

    H_ext_mod_alpha_sig_bound = -1.0

    lo_inc_prior_bound = 0.
    hi_inc_prior_bound = 180.

    lo_period_prior_bound = 79.
    hi_period_prior_bound = 81.

    lo_ecc_prior_bound = -0.1
    hi_ecc_prior_bound = 0.1

    lo_dist_prior_bound = 7600.
    hi_dist_prior_bound = 8200.

    lo_t0_prior_bound = 51773.0
    hi_t0_prior_bound = 51774.0

    def __init__(self):
        return

    # Functions to make and store isochrones
    def make_isochrone(self,
                       age,
                       Ks_ext,
                       dist,
                       phase,
                       met,
                       use_atm_func='merged'):
        self.Ks_ext = Ks_ext

        self.dist = dist * u.pc
        self.default_dist = dist
        ## Revise prior bounds for distance
        self.lo_dist_prior_bound = 0.8 * dist
        self.hi_dist_prior_bound = 1.2 * dist

        self.age = age
        self.met = met

        self.star1_isochrone = isoc_interp.isochrone_mist(
            age=age,
            ext=Ks_ext,
            dist=dist,
            phase=phase,
            met=met,
            use_atm_func=use_atm_func)
        self.star2_isochrone = self.star1_isochrone

        ## Convert from specified extinction in Ks to Kp and H
        self.Kp_ext = Ks_ext * (self.lambda_Ks /
                                self.lambda_Kp)**self.ext_alpha
        self.H_ext = Ks_ext * (self.lambda_Ks / self.lambda_H)**self.ext_alpha

    def make_star1_isochrone(self,
                             age,
                             Ks_ext,
                             dist,
                             phase,
                             met,
                             use_atm_func='merged'):
        self.Ks_ext = Ks_ext

        self.dist = dist * u.pc
        self.default_dist = dist
        ## Revise prior bounds for distance
        self.lo_dist_prior_bound = 0.8 * dist
        self.hi_dist_prior_bound = 1.2 * dist

        self.age = age
        self.met = met

        self.star1_isochrone = isoc_interp.isochrone_mist(
            age=age,
            ext=Ks_ext,
            dist=dist,
            phase=phase,
            met=met,
            use_atm_func=use_atm_func)

        ## Convert from specified extinction in Ks to Kp and H
        self.Kp_ext = Ks_ext * (self.lambda_Ks /
                                self.lambda_Kp)**self.ext_alpha
        self.H_ext = Ks_ext * (self.lambda_Ks / self.lambda_H)**self.ext_alpha

    def make_star2_isochrone(self,
                             age,
                             Ks_ext,
                             dist,
                             phase,
                             met,
                             use_atm_func='merged'):
        self.Ks_ext = Ks_ext

        self.dist = dist * u.pc
        self.default_dist = dist
        ## Revise prior bounds for distance
        self.lo_dist_prior_bound = 0.8 * dist
        self.hi_dist_prior_bound = 1.2 * dist

        self.age = age
        self.met = met

        self.star2_isochrone = isoc_interp.isochrone_mist(
            age=age,
            ext=Ks_ext,
            dist=dist,
            phase=phase,
            met=met,
            use_atm_func=use_atm_func)

        ## Convert from specified extinction in Ks to Kp and H
        self.Kp_ext = Ks_ext * (self.lambda_Ks /
                                self.lambda_Kp)**self.ext_alpha
        self.H_ext = Ks_ext * (self.lambda_Ks / self.lambda_H)**self.ext_alpha

    # Function to set observation times
    def set_observation_times(self, Kp_observation_times, H_observation_times):
        self.Kp_observation_times = Kp_observation_times
        self.H_observation_times = H_observation_times

        self.observation_times = (self.Kp_observation_times,
                                  self.H_observation_times)

    # Function to set observation mags
    def set_observation_mags(self, kp_obs_mags, kp_obs_mag_errors, h_obs_mags,
                             h_obs_mag_errors):
        self.kp_obs_mags = kp_obs_mags
        self.h_obs_mags = h_obs_mags

        self.kp_obs_mag_errors = kp_obs_mag_errors
        self.h_obs_mag_errors = h_obs_mag_errors

    # Function to set model mesh number of triangles
    def set_model_numTriangles(self, model_numTriangles):
        self.model_numTriangles = model_numTriangles

    # Function to set if using blackbody atmosphere
    def set_model_use_blackbody_atm(self, use_blackbody_atm):
        self.use_blackbody_atm = use_blackbody_atm

    # Function to set for modelling H extinction modifier
    def set_model_H_ext_mod(self, model_H_ext_mod):
        self.model_H_ext_mod = model_H_ext_mod

    # Function to set for modelling eccentricity
    def set_model_eccentricity(self, model_eccentricity):
        self.model_eccentricity = model_eccentricity

    # Function to set for modelling distance
    def set_model_distance(self, model_distance):
        self.model_distance = model_distance

    # Functions to define prior bounds
    def set_Kp_ext_prior_bounds(self, lo_bound, hi_bound):
        self.lo_Kp_ext_prior_bound = lo_bound
        self.hi_Kp_ext_prior_bound = hi_bound

    def set_H_ext_mod_prior_bounds(self, lo_bound, hi_bound):
        self.lo_H_ext_mod_prior_bound = lo_bound
        self.hi_H_ext_mod_prior_bound = hi_bound

    def set_H_ext_mod_extLaw_sig_prior_bounds(self, sigma_bound):
        self.H_ext_mod_alpha_sig_bound = sigma_bound

    def set_inc_prior_bounds(self, lo_bound, hi_bound):
        self.lo_inc_prior_bound = lo_bound
        self.hi_inc_prior_bound = hi_bound

    def set_period_prior_bounds(self, lo_bound, hi_bound):
        self.lo_period_prior_bound = lo_bound
        self.hi_period_prior_bound = hi_bound

    def set_ecc_prior_bounds(self, lo_bound, hi_bound):
        self.lo_ecc_prior_bound = lo_bound
        self.hi_ecc_prior_bound = hi_bound

    def set_dist_prior_bounds(self, lo_bound, hi_bound):
        self.lo_dist_prior_bound = lo_bound
        self.hi_dist_prior_bound = hi_bound

    def set_t0_prior_bounds(self, lo_bound, hi_bound):
        self.lo_t0_prior_bound = lo_bound
        self.hi_t0_prior_bound = hi_bound
Exemple #6
0
from phoebe import u
from phoebe import c as const

import numpy as np

from spisea import synthetic

from phoebe_phitter import lc_calc, isoc_interp

import matplotlib.pyplot as plt
import matplotlib.font_manager as font_manager
from matplotlib.ticker import MultipleLocator

# Reference fluxes, calculated with PopStar
## Vega magnitudes (m_Vega = 0.03)
ks_filt_info = synthetic.get_filter_info('naco,Ks')
kp_filt_info = synthetic.get_filter_info('nirc2,Kp')
h_filt_info = synthetic.get_filter_info('nirc2,H')

flux_ref_Ks = ks_filt_info.flux0 * (u.erg / u.s) / (u.cm**2.)
flux_ref_Kp = kp_filt_info.flux0 * (u.erg / u.s) / (u.cm**2.)
flux_ref_H = h_filt_info.flux0 * (u.erg / u.s) / (u.cm**2.)

# Stellar Parameters
# stellar_params = (mass, rad, teff, mag_Kp, mag_H)


class mcmc_fitter_base_interp(object):
    # Filter properties
    lambda_Ks = 2.18e-6 * u.m
    dlambda_Ks = 0.35e-6 * u.m
    def __init__(self,
                 age=3.9e6,
                 ext=2.63,
                 dist=7.971e3,
                 met=0.0,
                 phase=None,
                 use_atm_func='merged',
                 filts_list=[
                     'nirc2,Kp', 'nirc2,H', 'wfc3,ir,f127m', 'wfc3,ir,f139m',
                     'wfc3,ir,f153m'
                 ]):
        log_age = np.log10(age)

        self.log_age = log_age
        self.A_Ks = ext
        self.dist = dist
        self.met = met

        # Evolution/Atmosphere Models
        evo_model = evolution.MISTv1()

        if use_atm_func == 'merged':
            atm_func = atmospheres.get_merged_atmosphere
        elif use_atm_func == 'castelli':
            atm_fun = atmospheres.get_castelli_atmosphere
        elif use_atm_func == 'phoenix':
            atm_func = atmospheres.get_phoenixv16_atmosphere

        # Set filters
        self.filts_list = filts_list
        self.num_filts = len(self.filts_list)

        self.filts_info = []
        self.filts_flux_ref = np.empty(self.num_filts) *\
                                  (u.erg / u.s) / (u.cm**2.)
        for cur_filt_index in range(self.num_filts):
            cur_filt = self.filts_list[cur_filt_index]

            cur_filt_info = synthetic.get_filter_info(cur_filt)
            self.filts_info.append(cur_filt_info)

            cur_filt_flux_ref = cur_filt_info.flux0 * (u.erg / u.s) / (u.cm**
                                                                       2.)
            self.filts_flux_ref[cur_filt_index] = cur_filt_flux_ref

        # Extinction law
        red_law = reddening.RedLawNoguerasLara18()
        self.ext_alpha = 2.30

        # Create an isochrone with the given parameters
        self.iso_curAge = synthetic.IsochronePhot(self.log_age,
                                                  self.A_Ks,
                                                  self.dist,
                                                  evo_model=evo_model,
                                                  atm_func=atm_func,
                                                  red_law=red_law,
                                                  metallicity=self.met,
                                                  filters=self.filts_list)

        ## Create another isochrone for absolute mags / passband luminosities
        self.iso_absMag = synthetic.IsochronePhot(self.log_age,
                                                  0.0,
                                                  10.0,
                                                  evo_model=evo_model,
                                                  atm_func=atm_func,
                                                  red_law=red_law,
                                                  metallicity=self.met,
                                                  filters=self.filts_list)

        # Save out specific stellar parameter columns needed
        ## If needing specific phase, draw it out before saving
        if phase is not None:
            phase_check = np.where(
                self.iso_curAge.points['phase'] == mist_phase_dict[phase])
        else:
            phase_check = np.where(self.iso_curAge.points['phase'] >= -1)

        self.iso_mass_init = (self.iso_curAge.points['mass'][phase_check]).to(
            u.solMass)
        self.iso_mass = (
            self.iso_curAge.points['mass_current'][phase_check]).to(u.solMass)
        self.iso_rad = (self.iso_curAge.points['R'][phase_check]).to(u.solRad)
        self.iso_lum = (self.iso_curAge.points['L'][phase_check]).to(u.solLum)
        self.iso_teff = (self.iso_curAge.points['Teff'][phase_check]).to(u.K)
        self.iso_logg = self.iso_curAge.points['logg'][phase_check]

        self.iso_mag = {}
        for filt in self.filts_list:
            filt_dict_name = filt.replace(',', '_')
            filt_dict_name = filt_dict_name.replace('wfc3_ir', 'hst')

            self.iso_mag[filt] = self.iso_curAge.points[
                'm_' + filt_dict_name][phase_check]

        ## Stellar parameters from the absolute magnitude isochrones
        self.iso_absMag_mass_init = (
            self.iso_absMag.points['mass'][phase_check]).to(u.solMass)
        self.iso_absMag_mass = (
            self.iso_absMag.points['mass_current'][phase_check]).to(u.solMass)
        self.iso_absMag_rad = (self.iso_absMag.points['R'][phase_check]).to(
            u.solRad)

        self.iso_absMag_mag = {}
        for filt in self.filts_list:
            filt_dict_name = filt.replace(',', '_')
            filt_dict_name = filt_dict_name.replace('wfc3_ir', 'hst')

            self.iso_absMag_mag[filt] = self.iso_absMag.points[
                'm_' + filt_dict_name][phase_check]

        ## Maximum bounds on the radius in isochrone
        self.iso_rad_min = np.min(self.iso_rad).value
        self.iso_rad_max = np.max(self.iso_rad).value

        ## Maximum bounds on the initial mass in isochrone
        self.iso_mass_init_min = np.min(self.iso_mass_init).value
        self.iso_mass_init_max = np.max(self.iso_mass_init).value