def test_OFTI_pan_priors(): # initialize sampler myDriver = orbitize.driver.Driver(input_file, 'OFTI', 1, 1.22, 56.95, mass_err=0.08, plx_err=0.26) s = myDriver.sampler # change PAN prior new_min = 0.05 new_max = np.pi - 0.05 myDriver.system.sys_priors[4] = priors.UniformPrior(new_min, new_max) # run sampler orbits = s.run_sampler(100) # check that bounds were applied correctly assert np.max(orbits[:, 4]) < new_max assert np.min(orbits[:, 4]) > new_min # change PAN prior again mu = np.pi / 2 sigma = 0.05 myDriver.system.sys_priors[4] = priors.GaussianPrior(mu, sigma=sigma) # run sampler again orbits = s.run_sampler(250) # check that bounds were applied correctly assert mu == pytest.approx(np.mean(orbits[:, 4]), abs=0.01) assert sigma == pytest.approx(np.std(orbits[:, 4]), abs=0.01)
mass_err = 0.5 # [Msol] plx_err = 0.04714455423 # [mas] HD142527_system = system.System(num_secondary_bodies, data_table, m0, plx, hipparcos_IAD=HD142527_Hip, gaia=HD142527_Gaia, fit_secondary_mass=fit_secondary_mass, mass_err=mass_err, plx_err=plx_err) # set uniform primary mass prior m0_index = HD142527_system.param_idx['m0'] HD142527_system.sys_priors[m0_index] = priors.GaussianPrior(2.05, 0.3) # set uniform primary mass prior m1_index = HD142527_system.param_idx['m1'] HD142527_system.sys_priors[m1_index] = priors.GaussianPrior(0.25, 0.2) # MCMC parameters num_temps = 20 num_walkers = 50 num_threads = int(mp.cpu_count() * 2 / 3) # init driver HD142527_sampler = sampler.MCMC(HD142527_system, num_threads=num_threads, num_temps=num_temps, num_walkers=num_walkers) print('Driver Initialized! Running MCMC...')
def __init__(self, num_secondary_bodies, data_table, system_mass, plx, mass_err=0, plx_err=0, restrict_angle_ranges=None, results=None): self.num_secondary_bodies = num_secondary_bodies self.sys_priors = [] self.labels = [] self.results = [] # # Group the data in some useful ways # self.data_table = data_table # List of arrays of indices corresponding to each body self.body_indices = [] # List of arrays of indices corresponding to epochs in RA/Dec for each body self.radec = [] # List of arrays of indices corresponding to epochs in SEP/PA for each body self.seppa = [] radec_indices = np.where(self.data_table['quant_type'] == 'radec') seppa_indices = np.where(self.data_table['quant_type'] == 'seppa') for body_num in np.arange(self.num_secondary_bodies + 1): self.body_indices.append( np.where(self.data_table['object'] == body_num)) self.radec.append( np.intersect1d(self.body_indices[body_num], radec_indices)) self.seppa.append( np.intersect1d(self.body_indices[body_num], seppa_indices)) if (len(radec_indices) + len(seppa_indices) == len( self.data_table)) and (restrict_angle_ranges is None): restrict_angle_ranges = True if restrict_angle_ranges: angle_upperlim = np.pi else: angle_upperlim = 2. * np.pi # # Set priors for each orbital element # for body in np.arange(num_secondary_bodies): # Add semimajor axis prior self.sys_priors.append(priors.JeffreysPrior(0.1, 100.)) self.labels.append('sma{}'.format(body + 1)) # Add eccentricity prior self.sys_priors.append(priors.UniformPrior(0., 1.)) self.labels.append('ecc{}'.format(body + 1)) # Add inclination angle prior self.sys_priors.append(priors.SinPrior()) self.labels.append('inc{}'.format(body + 1)) # Add argument of periastron prior self.sys_priors.append(priors.UniformPrior(0., angle_upperlim)) self.labels.append('aop{}'.format(body + 1)) # Add position angle of nodes prior self.sys_priors.append(priors.UniformPrior(0., angle_upperlim)) self.labels.append('pan{}'.format(body + 1)) # Add epoch of periastron prior. self.sys_priors.append(priors.UniformPrior(0., 1.)) self.labels.append('epp{}'.format(body + 1)) # # Set priors on total mass and parallax # self.labels.append('plx') self.labels.append('mtot') if plx_err > 0: self.sys_priors.append(priors.GaussianPrior(plx, plx_err)) else: self.sys_priors.append(plx) if mass_err > 0: self.sys_priors.append(priors.GaussianPrior(system_mass, mass_err)) else: self.sys_priors.append(system_mass) #add labels dictionary for parameter indexing self.param_idx = dict(zip(self.labels, np.arange(len(self.labels))))
def __init__(self, num_secondary_bodies, data_table, stellar_mass, plx, mass_err=0, plx_err=0, restrict_angle_ranges=None, tau_ref_epoch=58849, fit_secondary_mass=False, results=None): self.num_secondary_bodies = num_secondary_bodies self.sys_priors = [] self.labels = [] self.results = [] self.fit_secondary_mass = fit_secondary_mass self.tau_ref_epoch = tau_ref_epoch self.restrict_angle_ranges = restrict_angle_ranges # # Group the data in some useful ways # self.data_table = data_table # Creates a copy of the input in case data_table needs to be modified self.input_table = self.data_table.copy() # Rob: check if instrument column is other than default. If other than default, then separate data table into n number of instruments. # gather list of instrument: list_instr = self.data_table['instruments'][name of instrument] # List of arrays of indices corresponding to each body # instruments = np.unique(self.data_table['instruments']) gives a list of unique names self.body_indices = [] # List of arrays of indices corresponding to epochs in RA/Dec for each body self.radec = [] # List of arrays of indices corresponding to epochs in SEP/PA for each body self.seppa = [] # List of index arrays corresponding to each rv for each body self.rv = [] # instr1_tbl = np.where(self.data_table['instruments'] == list_instr[0]) # loop through the indices per input_table: # rv_indices = np.where(instr1_tbl['quant_type'] == 'rv') # ... return the parameter labels for each table # ... self.fit_astrometry = True radec_indices = np.where(self.data_table['quant_type'] == 'radec') seppa_indices = np.where(self.data_table['quant_type'] == 'seppa') if len(radec_indices[0]) == 0 and len(seppa_indices[0]) == 0: self.fit_astrometry = False rv_indices = np.where(self.data_table['quant_type'] == 'rv') # defining all indices to loop through the unique rv instruments to get different offsets and jitters instrument_list = np.unique(self.data_table['instrument']) inst_indices_all = [] for inst in instrument_list: inst_indices = np.where(self.data_table['instrument'] == inst) inst_indices_all.append(inst_indices) # defining indices for unique instruments in the data table self.rv_instruments = np.unique( self.data_table['instrument'][rv_indices]) self.rv_inst_indices = [] for inst in self.rv_instruments: inst_indices = np.where(self.data_table['instrument'] == inst) self.rv_inst_indices.append(inst_indices) # astrometry instruments same for radec and seppa: self.astr_instruments = np.unique( self.data_table['instrument'][np.where( self.data_table['quant_type'] != 'rv')]) # save indicies for all of the ra/dec, sep/pa measurements for convenience self.all_radec = radec_indices self.all_seppa = seppa_indices for body_num in np.arange(self.num_secondary_bodies + 1): self.body_indices.append( np.where(self.data_table['object'] == body_num)) self.radec.append( np.intersect1d(self.body_indices[body_num], radec_indices)) self.seppa.append( np.intersect1d(self.body_indices[body_num], seppa_indices)) self.rv.append( np.intersect1d(self.body_indices[body_num], rv_indices)) # we should track the influence of the planet(s) on each other/the star if we are not fitting massless planets and # we are not fitting relative astrometry of just a single body self.track_planet_perturbs = self.fit_secondary_mass and \ ((len(self.radec[1]) + len(self.seppa[1]) + len(self.rv[1]) < len(data_table)) or \ (self.num_secondary_bodies > 1)) if restrict_angle_ranges: angle_upperlim = np.pi else: angle_upperlim = 2. * np.pi # # Set priors for each orbital element # for body in np.arange(num_secondary_bodies): # Add semimajor axis prior self.sys_priors.append(priors.LogUniformPrior(0.001, 1e7)) self.labels.append('sma{}'.format(body + 1)) # Add eccentricity prior self.sys_priors.append(priors.UniformPrior(0., 1.)) self.labels.append('ecc{}'.format(body + 1)) # Add inclination angle prior self.sys_priors.append(priors.SinPrior()) self.labels.append('inc{}'.format(body + 1)) # Add argument of periastron prior self.sys_priors.append(priors.UniformPrior(0., 2. * np.pi)) self.labels.append('aop{}'.format(body + 1)) # Add position angle of nodes prior self.sys_priors.append(priors.UniformPrior(0., angle_upperlim)) self.labels.append('pan{}'.format(body + 1)) # Add epoch of periastron prior. self.sys_priors.append(priors.UniformPrior(0., 1.)) self.labels.append('tau{}'.format(body + 1)) # # Set priors on total mass and parallax # self.labels.append('plx') if plx_err > 0: self.sys_priors.append(priors.GaussianPrior(plx, plx_err)) else: self.sys_priors.append(plx) # checking for rv data to include appropriate rv priors: if len(self.rv[0]) > 0 and self.fit_secondary_mass: # Rob and Lea: # for instrument in rv_instruments: # add gamma and sigma for each and label each unique gamma and sigma per instrument name (gamma+instrument1, ...) for instrument in self.rv_instruments: self.sys_priors.append(priors.UniformPrior( -5, 5)) # gamma prior in km/s self.labels.append('gamma_{}'.format(instrument)) self.sys_priors.append(priors.LogUniformPrior( 1e-4, 0.05)) # jitter prior in km/s self.labels.append('sigma_{}'.format(instrument)) if self.fit_secondary_mass: for body in np.arange(num_secondary_bodies) + 1: self.sys_priors.append(priors.LogUniformPrior( 1e-6, 2)) # in Solar masses for now self.labels.append('m{}'.format(body)) self.labels.append('m0') else: self.labels.append('mtot') # still need to append m0/mtot, even though labels are appended above if mass_err > 0: self.sys_priors.append(priors.GaussianPrior( stellar_mass, mass_err)) else: self.sys_priors.append(stellar_mass) # add labels dictionary for parameter indexing self.param_idx = dict(zip(self.labels, np.arange(len(self.labels))))
def __init__(self, num_secondary_bodies, data_table, stellar_mass, plx, mass_err=0, plx_err=0, restrict_angle_ranges=None, tau_ref_epoch=58849, fit_secondary_mass=False, results=None): self.num_secondary_bodies = num_secondary_bodies self.sys_priors = [] self.labels = [] self.results = [] self.fit_secondary_mass = fit_secondary_mass self.tau_ref_epoch = tau_ref_epoch # # Group the data in some useful ways # self.data_table = data_table # Creates a copy of the input in case data_table needs to be modified self.input_table = self.data_table.copy() # List of arrays of indices corresponding to each body self.body_indices = [] # List of arrays of indices corresponding to epochs in RA/Dec for each body self.radec = [] # List of arrays of indices corresponding to epochs in SEP/PA for each body self.seppa = [] # List of index arrays corresponding to each rv for each body self.rv = [] radec_indices = np.where(self.data_table['quant_type'] == 'radec') seppa_indices = np.where(self.data_table['quant_type'] == 'seppa') rv_indices = np.where(self.data_table['quant_type'] == 'rv') # save indicies for all of the ra/dec, sep/pa measurements for convenience self.all_radec = radec_indices self.all_seppa = seppa_indices for body_num in np.arange(self.num_secondary_bodies + 1): self.body_indices.append( np.where(self.data_table['object'] == body_num)) self.radec.append( np.intersect1d(self.body_indices[body_num], radec_indices)) self.seppa.append( np.intersect1d(self.body_indices[body_num], seppa_indices)) self.rv.append( np.intersect1d(self.body_indices[body_num], rv_indices)) # we should track the influence of the planet(s) on each other/the star if we are not fitting massless planets and # we are not fitting relative astrometry of just a single body self.track_planet_perturbs = self.fit_secondary_mass and \ ((len(self.radec[1]) + len(self.seppa[1]) + len(self.rv[1]) < len(data_table)) or \ (self.num_secondary_bodies > 1)) if restrict_angle_ranges: angle_upperlim = np.pi else: angle_upperlim = 2. * np.pi # # Set priors for each orbital element # for body in np.arange(num_secondary_bodies): # Add semimajor axis prior self.sys_priors.append(priors.LogUniformPrior(0.001, 1e7)) self.labels.append('sma{}'.format(body + 1)) # Add eccentricity prior self.sys_priors.append(priors.UniformPrior(0., 1.)) self.labels.append('ecc{}'.format(body + 1)) # Add inclination angle prior self.sys_priors.append(priors.SinPrior()) self.labels.append('inc{}'.format(body + 1)) # Add argument of periastron prior self.sys_priors.append(priors.UniformPrior(0., 2. * np.pi)) self.labels.append('aop{}'.format(body + 1)) # Add position angle of nodes prior self.sys_priors.append(priors.UniformPrior(0., angle_upperlim)) self.labels.append('pan{}'.format(body + 1)) # Add epoch of periastron prior. self.sys_priors.append(priors.UniformPrior(0., 1.)) self.labels.append('tau{}'.format(body + 1)) # # Set priors on total mass and parallax # self.labels.append('plx') if plx_err > 0: self.sys_priors.append(priors.GaussianPrior(plx, plx_err)) else: self.sys_priors.append(plx) # checking for rv data to include appropriate rv priors: if len(self.rv[0]) > 0 and self.fit_secondary_mass: self.sys_priors.append(priors.UniformPrior( -5, 5)) # gamma prior in km/s self.labels.append('gamma') self.sys_priors.append(priors.LogUniformPrior( 1e-4, 0.05)) # jitter prior in km/s self.labels.append('sigma') if self.fit_secondary_mass: for body in np.arange(num_secondary_bodies) + 1: self.sys_priors.append(priors.LogUniformPrior( 1e-6, 2)) # in Solar masses for now self.labels.append('m{}'.format(body)) self.labels.append('m0') else: self.labels.append('mtot') # still need to append m0/mtot, even though labels are appended above if mass_err > 0: self.sys_priors.append(priors.GaussianPrior( stellar_mass, mass_err)) else: self.sys_priors.append(stellar_mass) # add labels dictionary for parameter indexing self.param_idx = dict(zip(self.labels, np.arange(len(self.labels))))
def __init__(self, num_secondary_bodies, data_table, stellar_mass, plx, mass_err=0, plx_err=0, restrict_angle_ranges=None, tau_ref_epoch=58849, fit_secondary_mass=False, results=None): self.num_secondary_bodies = num_secondary_bodies self.sys_priors = [] self.labels = [] self.results = [] self.fit_secondary_mass = fit_secondary_mass self.tau_ref_epoch = tau_ref_epoch # # Group the data in some useful ways # self.data_table = data_table # Creates a copy of the input in case data_table needs to be modified self.input_table = self.data_table.copy() # List of arrays of indices corresponding to each body self.body_indices = [] # List of arrays of indices corresponding to epochs in RA/Dec for each body self.radec = [] # List of arrays of indices corresponding to epochs in SEP/PA for each body self.seppa = [] radec_indices = np.where(self.data_table['quant_type'] == 'radec') seppa_indices = np.where(self.data_table['quant_type'] == 'seppa') for body_num in np.arange(self.num_secondary_bodies + 1): self.body_indices.append( np.where(self.data_table['object'] == body_num)) self.radec.append( np.intersect1d(self.body_indices[body_num], radec_indices)) self.seppa.append( np.intersect1d(self.body_indices[body_num], seppa_indices)) if restrict_angle_ranges: angle_upperlim = np.pi else: angle_upperlim = 2. * np.pi # # Set priors for each orbital element # for body in np.arange(num_secondary_bodies): # Add semimajor axis prior self.sys_priors.append(priors.LogUniformPrior(0.001, 1e7)) self.labels.append('sma{}'.format(body + 1)) # Add eccentricity prior self.sys_priors.append(priors.UniformPrior(0., 1.)) self.labels.append('ecc{}'.format(body + 1)) # Add inclination angle prior self.sys_priors.append(priors.SinPrior()) self.labels.append('inc{}'.format(body + 1)) # Add argument of periastron prior self.sys_priors.append(priors.UniformPrior(0., 2. * np.pi)) self.labels.append('aop{}'.format(body + 1)) # Add position angle of nodes prior self.sys_priors.append(priors.UniformPrior(0., angle_upperlim)) self.labels.append('pan{}'.format(body + 1)) # Add epoch of periastron prior. self.sys_priors.append(priors.UniformPrior(0., 1.)) self.labels.append('tau{}'.format(body + 1)) # # Set priors on total mass and parallax # self.labels.append('plx') if plx_err > 0: self.sys_priors.append(priors.GaussianPrior(plx, plx_err)) else: self.sys_priors.append(plx) if self.fit_secondary_mass: for body in np.arange(num_secondary_bodies): self.sys_priors.append(priors.LogUniformPrior( 1e-6, 1)) # in Solar masses for now self.labels.append('m{}'.format(body)) self.labels.append('m0') else: self.labels.append('mtot') # still need to append m0/mtot, even though labels are appended above if mass_err > 0: self.sys_priors.append(priors.GaussianPrior( stellar_mass, mass_err)) else: self.sys_priors.append(stellar_mass) # add labels dictionary for parameter indexing self.param_idx = dict(zip(self.labels, np.arange(len(self.labels))))