示例#1
0
def test_binary(plot=False):
    """
    """
    # TODO: once ps.copy is implemented, just send b.copy() to each of these

    # system = [sma (AU), period (d)]
    system1 = [0.05, 2.575]
    system2 = [1., 257.5]
    system3 = [40., 65000.]

    for system in [system1, system2, system3]:
        for q in [0.5, 1.]:
            for ltte in [True, False]:

                b = phoebe.default_binary()
                b.set_default_unit_all('sma', u.AU)
                b.set_default_unit_all('period', u.d)

                b.set_value('sma@binary', system[0])
                b.set_value('period@binary', system[1])
                b.set_value('q', q)
                _keplerian_v_nbody(b, ltte, system[1], plot=plot)

                b = phoebe.default_binary()
                b.set_default_unit_all('sma', u.AU)
                b.set_default_unit_all('period', u.d)

                b.set_value('sma@binary', system[0])
                b.set_value('period@binary', system[1])
                b.set_value('q', q)
                _frontend_v_backend(b, ltte, system[1], plot=plot)
示例#2
0
def test_all():
    print("phoebe.Bundle() ...")
    b = phoebe.Bundle()
    print("phoebe.default_star()) ...")
    b = phoebe.default_star()
    print("phoebe.default_binary() ...")
    b = phoebe.default_binary()
    print("phoebe.default_binary(contact_binary=True) ...")
    b = phoebe.default_binary(contact_binary=True)
示例#3
0
def test_binary(plot=False):
    """
    """

    # TODO: grid over orbital parameters
    # TODO: once ps.copy is implemented, just send b.copy() to each of these

    b = phoebe.default_binary()
    _keplerian_v_nbody(b, plot=plot)

    b = phoebe.default_binary()
    _phoebe_v_photodynam(b, plot=plot)

    b = phoebe.default_binary()
    _frontend_v_backend(b, plot=plot)
示例#4
0
def _export(filename, plot=False):
    """
    this isn't run during testing, but should be edited to run on certain versions
    of phoebe to then store the .phoebe file in this directory and ensure it can
    be imported later
    """


    if LooseVersion(phoebe.__version__) >= LooseVersion("2.2"):
       raise ImportError("script runs on PHOEBE 2.1.x")
       exit()

    b = phoebe.default_binary()
    # TESS:default was renamed to TESS:T in 2.2
    b.add_dataset('lc', times=np.linspace(0,1,11), passband='TESS:default')
    b.add_dataset('rv', times=phoebe.linspace(0,1,4))
    b.add_dataset('lp', times=phoebe.linspace(0,1,4), wavelengths=np.linspace(500,510,51))
    b.add_dataset('mesh', times=[0])

    b.run_compute()

    if plot:
        b.plot(show=True, time=0)

    b.save(os.path.join(dir, filename))
示例#5
0
文件: test_rm.py 项目: danhey/phoebe2
def test_binary(plot=False):

    b = phoebe.default_binary()

    period = b.get_value('period@orbit')
    times = np.linspace(-0.2, 1.2 * period, 51)

    #turn off albedos (legacy requirement)
    b.set_value_all('irrad_frac_refl_bol', 0.0)

    b.add_dataset('rv',
                  times=times,
                  dataset='rv01',
                  ld_func='logarithmic',
                  ld_coeffs=[0.5, 0.5])

    b.add_compute('phoebe',
                  compute='phnum',
                  ltte=False,
                  atm='extern_planckint',
                  rv_method='flux-weighted',
                  irrad_method='none')
    b.add_compute('legacy',
                  compute='legnum',
                  ltte=False,
                  atm='extern_planckint',
                  rv_method='flux-weighted',
                  refl_num=0)

    for syncpar in [1. / 4, 4]:
        print "setting syncpar@primary to", syncpar
        b.set_value('syncpar@primary', syncpar)
        _beta_vs_legacy(b, plot=plot)

    return b
示例#6
0
def test_binary(plot=False):
    """
    """
    phoebe.devel_on()  # required for nbody dynamics

    # TODO: once ps.copy is implemented, just send b.copy() to each of these

    # system = [sma (AU), period (d)]
    system1 = [0.05, 2.575]
    system2 = [1., 257.5]
    system3 = [40., 65000.]

    for system in [system1, system2, system3]:
        for q in [0.5, 1.]:
            for ltte in [True, False]:
                print("test_dynamics_grid: sma={}, period={}, q={}, ltte={}".
                      format(system[0], system[1], q, ltte))
                b = phoebe.default_binary()
                b.get_parameter('dynamics_method')._choices = [
                    'keplerian', 'bs'
                ]

                b.set_default_unit_all('sma', u.AU)
                b.set_default_unit_all('period', u.d)

                b.set_value('sma@binary', system[0])
                b.set_value('period@binary', system[1])
                b.set_value('q', q)

                _keplerian_v_nbody(b, ltte, system[1], plot=plot)
                _frontend_v_backend(b, ltte, system[1], plot=plot)

    phoebe.devel_off()  # reset for future tests
示例#7
0
def plotphoebe(predata, times):
    incl = predata[0]
    q = predata[1]
    r = predata[2]
    t2t1 = predata[3]
    b = phoebe.default_binary(contact_binary=True)
    #times  = np.linspace(0,1,150)
    times = times
    #b.add_dataset('lc', times=phoebe.linspace(0,1,100), passband= 'Kepler:mean')#compute_phases
    b.add_dataset('lc', times=times)

    b['period@binary'] = 1

    b['incl@binary'] = incl  #58.528934
    b['q@binary'] = q
    b['teff@primary'] = 6500  #6500#6500  #6208
    b['teff@secondary'] = 6500 * t2t1  #6500*92.307556*0.01#6500*100.08882*0.01 #6087

    b['sma@binary'] = 1  #0.05 2.32

    b['requiv@primary'] = r  #0.61845703

    #b.add_dataset('mesh', times=[0.25], dataset='mesh01')

    b.run_compute(irrad_method='none')

    fluxmodel = b['value@fluxes@lc01@model']
    resultflux = -2.5 * np.log10(fluxmodel)
    resultflux = resultflux - np.mean(resultflux)
    #plt.figure(0)
    #plt.plot(b['value@times@lc01@model'], resultflux, '.')
    return times, resultflux
示例#8
0
def test_forbidden(verbose=False):

    phoebe.devel_on()
    phoebe.check_visible_off()

    b = phoebe.default_binary(contact_binary=True)
    b.add_dataset('lc')
    b.add_dataset('rv')
    b.add_dataset('mesh')
    b.add_dataset('lp')

    b.add_compute('legacy')
    b.add_compute('photodynam')
    b.add_compute('jktebop')
    b.add_compute('ellc')

    # TODO: include constraint_func?  Shouldn't matter since they're not in twigs
    should_be_forbidden = b.qualifiers + b.contexts + b.kinds + [c.split('@')[0] for c in b.get_parameter('columns').choices]

    if verbose:
        for l in should_be_forbidden:
            if l not in phoebe.parameters.parameters._forbidden_labels:
                print(l)

    for l in should_be_forbidden:
        assert(l in phoebe.parameters.parameters._forbidden_labels)

    phoebe.reset_settings()
    return b
示例#9
0
def get_binary_flux_kepler(teff1, teff2, q, ecc):
    base_flux = get_flux_value_kepler(teff1)
    b = phoebe.default_binary()
    b.set_value('q', value=q)
    b.set_value('ecc', value=ecc)
    b.set_value('teff', component='primary', value=teff1)
    #    b.set_value('r',component='secondary',value=0.5)
    b.set_value('teff', component='secondary', value=teff2)
    b.set_value(
        'q', value=0.75
    )  #b.add_compute('lc',atm@primary='ck2004',atm@second='ck2004')
    b.add_dataset('lc',
                  dataset='lc01',
                  atm='blackbody',
                  ld_func='interp',
                  times=phoebe.linspace(0, 2, 101),
                  passband='Kepler:mean',
                  intens_weighting='energy')
    #    b.add_dataset('lc',dataset='lc01',ld_func='interp',times = phoebe.linspace(0,1,101),passband='Kepler:mean',intens_weighting='energy')
    b.run_compute(irrad_method='none')
    #    b['lc01@model'].plot(x='phases',c='blue')
    #    b.savefig('lc_kepler.eps')
    times1 = b['value@times@lc01@latest@model']
    fluxes1 = b['value@fluxes@lc01@latest@model'] * base_flux
    return times1, fluxes1
示例#10
0
def test_latexrepr(verbose=False):

    b = phoebe.default_binary(contact_binary=True)
    b.add_dataset('lc')
    b.add_dataset('rv')
    b.add_dataset('mesh')
    b.add_dataset('lp')

    b.add_compute('legacy')
    # b.add_compute('photodynam')
    b.add_compute('jktebop')
    b.add_compute('ellc')

    b.add_spot(component='primary')
    b.add_gaussian_process(dataset='lc01')

    for param in b.to_list():
        if verbose:
            print("param: {}".format(param.twig))
        param.latextwig

    b = phoebe.default_star()
    for param in b.to_list():
        if verbose:
            print("param: {}".format(param.twig))
        param.latextwig

    return b
示例#11
0
def test_contact(plot=False, gen_comp=False):

    b = phoebe.default_binary(contact_binary=True)

    b.set_value('incl', component='binary', value=45.0)
    b.flip_constraint('pot', solve_for='requiv@primary')
    b['pot@contact_envelope@component'] = 3.5
    b['q'] = 1.0
    b['teff@primary'] = 10000.
    b['teff@secondary'] = 5000.

    b.add_dataset('lc', times=np.linspace(0,3,21))
    if plot:
        b.add_dataset('mesh', times=[0.0])
    b.add_compute('phoebe', compute='phoebe2', irrad_method='wilson')
    if gen_comp:
        b.add_compute('legacy', compute='phoebe1', refl_num=5, morphology = 'Overcontact binary not in thermal contact')

    # set matching atmospheres
    b.set_value_all('atm', 'extern_planckint')

    # set matching limb-darkening, both bolometric and passband
    b.set_value_all('ld_mode_bol', 'manual')
    b.set_value_all('ld_func_bol', 'logarithmic')
    b.set_value_all('ld_coeffs_bol', [0.0, 0.0])

    b.set_value_all('ld_mode', 'manual')
    b.set_value_all('ld_func', 'logarithmic')
    b.set_value_all('ld_coeffs', [0.0, 0.0])

    for alb in [0, 0.5, 1.0]:
        if plot: print("alb = {}".format(alb))
        b.set_value_all('irrad_frac_refl_bol', alb)

        if plot: print("running phoebe2 model...")
        b.run_compute(compute='phoebe2', ntriangles=1000, model='phoebe2model', overwrite=True)
        if gen_comp:
            if plot: print("running phoebe1 model...")
            b.run_compute(compute='phoebe1', gridsize=30, model='phoebe1model', overwrite=True)
            b.filter(model='phoebe1model').save('test_reflection_contact_{}.comp.model'.format(alb))
        else:
            b.import_model(os.path.join(os.path.dirname(__file__), 'test_reflection_contact_{}.comp.model'.format(alb)), model='phoebe1model', overwrite=True)

        phoebe2_val = b.get_value('fluxes@phoebe2model')
        phoebe1_val = b.get_value('fluxes@phoebe1model')

        if plot:
            # phoebe2_maxintensabs = b.get_value('intens_norm_abs', component='primary').max()
            # phoebe2_maxintensrel = b.get_value('intens_norm_rel', component='primary').max()
            # print("alb={} phoebe1.max={} phoebe2.max={}, phoebe2.maxintensabs={} phoebe2.maxintensrel={}".format(alb, phoebe1_val.max(), phoebe2_val.max(), phoebe2_maxintensabs, phoebe2_maxintensrel))

            b.plot(dataset='lc01', show=True)

        # this is quite a low rtol, but our reflection is more robust because
        # each "half" of the envelope can reflect with itself, whereas WD
        # only allows reflection between the two halves
        assert(np.allclose(phoebe2_val, phoebe1_val, rtol=1e-2, atol=0.))

    return b
示例#12
0
def test_esinw_ecosw(verbose=False):
    if verbose: print("b=phoebe.default_binary()")
    b = phoebe.default_binary()

    if verbose: print("b.set_value('ecc', 0.5)")
    b.set_value('ecc', 0.5)

    if verbose: print(b.filter(qualifier=['ecosw', 'esinw', 'ecc', 'per0']))

    assert (b.get_value('ecosw', context='component') == 0.5)
    assert (b.get_value('esinw', context='component') == 0.0)
    assert (b.run_checks().passed)

    if verbose: print("b.flip_constraint('esinw', solve_for='ecc')")
    b.flip_constraint('esinw', solve_for='ecc')

    if verbose: print(b.filter(qualifier=['ecosw', 'esinw', 'ecc', 'per0']))

    assert (b.run_checks().passed == False)
    assert_raises(ValueError, b.run_compute)

    if verbose: print("b.set_value('per0', 10)")
    b.set_value('per0', 10)

    if verbose: print(b.filter(qualifier=['ecosw', 'esinw', 'ecc', 'per0']))

    assert (b.run_checks().passed)

    assert (b.get_value('ecc', context='component') == 0)

    if verbose: print(b.set_value('per0', 0.0))
    b.set_value('per0', 0.0)

    if verbose: print(b.filter(qualifier=['ecosw', 'esinw', 'ecc', 'per0']))

    assert (b.run_checks().passed == False)

    if verbose: print("b.flip_constraint('ecosw', solve_for='per0')")
    b.flip_constraint('ecosw', solve_for='per0')

    if verbose: print(b.filter(qualifier=['ecosw', 'esinw', 'ecc', 'per0']))

    assert (b.run_checks().passed)
    assert (b.get_value('ecc', context='component') == 0.0)
    assert (b.get_value('per0', context='component') == 0.0)

    if verbose: print("b.set_value('ecosw', 0.5)")
    b.set_value('ecosw', 0.5)

    assert (b.run_checks().passed)

    if verbose: print(b.filter(qualifier=['ecosw', 'esinw', 'ecc', 'per0']))

    assert (b.get_value('per0', context='component') == 0.0)
    assert (b.get_value('ecc', context='component') == 0.5)

    return b
示例#13
0
def test_interp_value():
    b = phoebe.default_binary()
    b.add_dataset('lc', times=[0, 1], fluxes=[0.8, 0.7])

    assert(abs(b.get_parameter('fluxes').interp_value(times=0.5)-0.75) < 1e-12)

    times_in_s = (0.5*u.d).to(u.s)
    assert(abs(b.get_parameter('fluxes').interp_value(times=times_in_s)-0.75) < 1e-12)

    assert(abs(b.get_parameter('fluxes').interp_quantity(times=times_in_s).value-0.75) < 1e-12)
示例#14
0
def test_pot_filloutfactor(verbose=False):
    if verbose: print("b=phoebe.default_binary(contact_binary=True)")
    b = phoebe.default_binary(contact_binary=True)

    b.flip_constraint('pot', solve_for='requiv@primary')
    b.flip_constraint('fillout_factor', solve_for='pot')

    b.set_value('fillout_factor', 0.45)
    b.set_value('q', 0.25)

    assert (b.run_checks().passed)
示例#15
0
def test_binary(plot=False):
    """
    """
    phoebe.devel_on()  # required for nbody dynamics

    # TODO: grid over orbital parameters
    # TODO: once ps.copy is implemented, just send b.copy() to each of these

    b = phoebe.default_binary()
    b.get_parameter('dynamics_method')._choices = ['keplerian', 'bs']
    _keplerian_v_nbody(b, plot=plot)

    b = phoebe.default_binary()
    b.get_parameter('dynamics_method')._choices = ['keplerian', 'bs']
    _phoebe_v_photodynam(b, plot=plot)

    b = phoebe.default_binary()
    b.get_parameter('dynamics_method')._choices = ['keplerian', 'bs']
    _frontend_v_backend(b, plot=plot)

    phoebe.devel_off()  # reset for future tests
示例#16
0
def test_binary(plot=False, gen_comp=False):
    b = phoebe.default_binary()

    period = b.get_value('period@binary')
    b.add_dataset('lc', times=np.linspace(0,period,21))
    b.add_compute('phoebe', irrad_method='none', compute='phoebe2')
    if gen_comp:
        b.add_compute('legacy', refl_num=0, compute='phoebe1')

    # set matching atmospheres
    b.set_value_all('atm', 'extern_planckint')

    # set matching limb-darkening, both bolometric and passband
    b.set_value_all('ld_mode_bol', 'manual')
    b.set_value_all('ld_func_bol', 'linear')
    b.set_value_all('ld_coeffs_bol', [0.0])

    b.set_value_all('ld_mode', 'manual')
    b.set_value_all('ld_func', 'linear')
    b.set_value_all('ld_coeffs', [0.0])

    #turn off albedos (legacy requirement)
    b.set_value_all('irrad_frac_refl_bol',  0.0)


    # 0.51 starts to overlap
    for ecc in [0.3, 0.505]:
        b.set_value('ecc', ecc)

        for per0 in [45, 90, 90+45]:
            b.set_value('per0', per0)

            print("running phoebe2 model...")
            b.run_compute(compute='phoebe2', irrad_method='none', model='phoebe2model', overwrite=True)
            if gen_comp:
                print("running phoebe1 model...")
                b.run_compute(compute='phoebe1', refl_num=0, model='phoebe1model', overwrite=True)
                b.filter(model='phoebe1model').save('test_ecc_{}_{}.comp.model'.format(ecc, per0))
            else:
                b.import_model(os.path.join(os.path.dirname(__file__), 'test_ecc_{}_{}.comp.model'.format(ecc, per0)), model='phoebe1model', overwrite=True)

            phoebe2_val = b.get_value('fluxes@phoebe2model')
            phoebe1_val = b.get_value('fluxes@phoebe1model')

            if plot:
                print("ecc: {} per0:: {} max (rel): {}".format(ecc , per0, abs((phoebe2_val-phoebe1_val)/phoebe1_val).max()))

                b.plot(dataset='lc01', show=True)

            assert(np.allclose(phoebe2_val, phoebe1_val, rtol=1e-3 if ecc < 0.5 else 5e-3, atol=0.))

    return b
示例#17
0
def test_forbidden(verbose=False):

    phoebe.devel_on()

    b = phoebe.default_binary(contact_binary=True)
    b.add_dataset('lc')
    b.add_dataset('rv')
    b.add_dataset('mesh')
    b.add_dataset('lp')

    b.add_compute('legacy')
    b.add_compute('photodynam')
    b.add_compute('jktebop')
    b.add_compute('ellc')

    b.add_spot(component='primary')
    b.add_gaussian_process(dataset='lc01')

    b.add_solver('estimator.lc_periodogram')
    b.add_solver('estimator.rv_periodogram')
    b.add_solver('estimator.lc_geometry')
    b.add_solver('estimator.rv_geometry')
    b.add_solver('estimator.ebai')
    b.add_solver('optimizer.nelder_mead')
    b.add_solver('optimizer.differential_evolution')
    b.add_solver('optimizer.cg')
    b.add_solver('optimizer.powell')
    b.add_solver('sampler.emcee')
    b.add_solver('sampler.dynesty')


    # TODO: include constraint_func?  Shouldn't matter since they're not in twigs
    should_be_forbidden = b.qualifiers + b.contexts + b.kinds + [c.split('@')[0] for c in b.get_parameter(qualifier='columns').choices]

    if verbose:
        for l in should_be_forbidden:
            if l not in phoebe.parameters.parameters._forbidden_labels:
                print(l)

    for l in should_be_forbidden:
        assert(l in phoebe.parameters.parameters._forbidden_labels)

    phoebe.reset_settings()
    return b
示例#18
0
def test_reimport(filename=None):

    #import data

    if filename:
        b = phb2.from_legacy(filename)
    else:
        b = phb2.default_binary()
        b.add_compute(kind='legacy')

    b.export_legacy('test.legacy')
    b2 = phb2.from_legacy('test.legacy')

    # compare data

    # check to see if datasets are attached and the right number
    Nlcs = len(b.get_dataset(kind='lc').datasets)
    Nlcs2 = len(b2.get_dataset(kind='lc').datasets)
    Nrvs = len(b.get_dataset(kind='rv').datasets)
    Nrvs2 = len(b2.get_dataset(kind='rv').datasets)

    # must be equal
    assert (Nlcs == Nlcs2)
    assert (2 * Nrvs == Nrvs2)

    # check to make sure parameters are the same

    pars = b.filter()
    pars2 = b.filter()

    #checking parameters
    for x in range(len(pars)):
        val1 = pars[x].value
        val2 = pars2[x].value
        if pars[x].qualifier not in ['times', 'fluxes', 'sigmas', 'rvs']:
            #            print pars[x].qualifier
            #            print pars[x]
            try:
                assert (val1 == val2)
            except:
                assert (all(val1 == val2))
示例#19
0
def compute_lc(values):
    q = values[3]
    ff = values[2]
    tratio = values[1]
    incl = values[0]

    b = phoebe.default_binary(contact_binary = True)
    b.add_dataset('lc', compute_phases=phases)
    b['pblum_mode'] = 'pbflux'
    b.flip_constraint('pot', solve_for='requiv@primary')
    b.flip_constraint('fillout_factor', solve_for='pot')
    # b.set_value_all('atm', value='blackbody')
    # b.set_value_all('ld_mode', value='manual')
    b['q'] = q
    b['fillout_factor'] = ff 
    b['teff@secondary'] = tratio*b['teff@primary'].value
    b['incl@binary'] = incl
    
    try:
        b.run_compute()
        return b['value@fluxes@model']
    except:
        return np.zeros(len(phases))
示例#20
0
# As always, let's do imports and initialize a logger and a new bundle.  See [Building a System](../tutorials/building_a_system.ipynb) for more details.

# In[1]:

get_ipython().run_line_magic('matplotlib', 'inline')

# In[2]:

import phoebe
from phoebe import u  # units
import numpy as np
import matplotlib.pyplot as plt

logger = phoebe.logger()

b = phoebe.default_binary()

# In[3]:

b.set_value(qualifier='pitch', component='primary', value=30)

# Model without Spots
# --------------------------

# In[4]:

b.add_dataset('lc', times=phoebe.linspace(0, 1, 101))

# In[5]:

b.run_compute(irrad_method='none', model='no_spot')
示例#21
0
get_ipython().system('pip install -I "phoebe>=2.1,<2.2"')

# In[1]:

get_ipython().run_line_magic('matplotlib', 'inline')

# As always, let's do imports and initialize a logger and a new bundle.  See [Building a System](../tutorials/building_a_system.ipynb) for more details.

# In[1]:

import phoebe
from phoebe import u  # units

logger = phoebe.logger()

b = phoebe.default_binary(contact_binary=True)

# Model without Spots
# --------------------------

# In[2]:

b.add_dataset('lc', times=phoebe.linspace(0, 0.5, 101))

# In[3]:

b.run_compute(irrad_method='none', model='no_spot')

# Adding Spots
# ---------------------
import phoebe

print("creating default_star.bundle")
b = phoebe.default_star(force_build=True)
b.save('./default_star.bundle', compact=True, incl_uniqueid=False)

print("creating default_binary.bundle")
b = phoebe.default_binary(force_build=True)
b.save('./default_binary.bundle', compact=True, incl_uniqueid=False)

print("creating default_contact_binary.bundle")
b = phoebe.default_binary(contact_binary=True, force_build=True)
b.save('./default_contact_binary.bundle', compact=True, incl_uniqueid=False)
    b.set_value_all('ld_mode', 'lookup')
    b.set_value_all('ld_func', 'linear')
    
    b.run_compute(kind='phoebe', model='phoebe2_model', ntriangles=3000)
    b.run_compute(kind='legacy', model='phoebe1_model', gridsize=60)
    b.run_compute(kind='ellc', model='ellc_model')
    b.run_compute(kind='jktebop', model='jktebop_model')
    return b


# # Detached Case

# In[4]:


b = phoebe.default_binary()
b['period@binary'] = 1.2  # 1.0 case causes some issues with ellc
b['requiv@primary'] = 0.95  # same stars causes issues with RM in legacy


# In[5]:


b = run_comparison_models(b)


# In[6]:


afig, mplfig = b.plot(x='phases', context='model',
                      ylim={'lc': (2.05,2.15), 'rv': (-100,100)}, xlim={'rv': (-0.25,0.25)},
示例#24
0
def binary_star_mesh(star1_params,
                     star2_params,
                     binary_params,
                     observation_times,
                     use_blackbody_atm=False,
                     make_mesh_plots=True,
                     mesh_temp=False,
                     mesh_temp_cmap=None,
                     plot_name=None,
                     print_diagnostics=False,
                     par_compute=False,
                     num_par_processes=8,
                     num_triangles=1500):
    """Compute the light curve for a binary system
    
    Keyword arguments:
    star1_params -- Tuple of parameters for the primary star
    star2_params -- Tuple of parameters for the secondary star
    binary_params -- Tuple of parameters for the binary system configuration
    observation_times -- Tuple of observation times,
        with numpy array of MJDs in each band
        (kp_MJDs, h_MJDs, mesh_MJDs) = observation_times
    use_blackbody_atm -- Use blackbody atmosphere
        instead of default Castelli & Kurucz (default False)
    make_mesh_plots -- Make a mesh plot of the binary system (default False)
    plot_name
    print_diagnostics
    par_compute
    num_par_processes
    """

    if par_compute:
        # TODO: Need to implement parallelization correctly
        phoebe.mpi_on(nprocs=num_par_processes)
    else:
        phoebe.mpi_off()

    # Read in the stellar parameters of the binary components
    (star1_mass, star1_rad, star1_teff, star1_logg, star1_mag_Kp, star1_mag_H,
     star1_pblum_Kp, star1_pblum_H) = star1_params
    (star2_mass, star2_rad, star2_teff, star2_logg, star2_mag_Kp, star2_mag_H,
     star2_pblum_Kp, star2_pblum_H) = star2_params

    # Read in the parameters of the binary system
    (binary_period, binary_ecc, binary_inc, t0) = binary_params

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

    # Check for high temp ck2004 atmosphere limits
    if not use_blackbody_atm:
        # log g = 3.5, high temp bounds (above 31e3 K)
        if star1_teff > (31000 * u.K) and (4.0 > star1_logg > 3.5):
            star1_teff_round = 30995.0 * u.K

            if print_diagnostics:
                print('Star 1 out of C&K 2004 grid')
                print('star1_logg = {0:.4f}'.format(star1_logg))
                print('Rounding down star1_teff')
                print('{0:.4f} -> {1:.4f}'.format(star1_teff,
                                                  star1_teff_round))

            star1_teff = star1_teff_round
        if star2_teff > (31000 * u.K) and (4.0 > star2_logg > 3.5):
            star2_teff_round = 30995.0 * u.K

            if print_diagnostics:
                print('Star 2 out of C&K 2004 grid')
                print('star2_logg = {0:.4f}'.format(star2_logg))
                print('Rounding down star2_teff')
                print('{0:.4f} -> {1:.4f}'.format(star2_teff,
                                                  star2_teff_round))

            star2_teff = star2_teff_round

        # log g = 4.0, high temp bounds (above 40e3 K)
        if star1_teff > (40000 * u.K) and (4.5 > star1_logg > 4.0):
            star1_teff_round = 39995.0 * u.K

            print('Star 1 out of C&K 2004 grid')
            print('star1_logg = {0:.4f}'.format(star1_logg))
            print('Rounding down star1_teff')
            print('{0:.4f} -> {1:.4f}'.format(star1_teff, star1_teff_round))

            star1_teff = star1_teff_round
        if star2_teff > (40000 * u.K) and (4.0 > star2_logg > 3.50):
            star2_teff_round = 39995.0 * u.K

            print('Star 2 out of C&K 2004 grid')
            print('star2_logg = {0:.4f}'.format(star2_logg))
            print('Rounding down star2_teff')
            print('{0:.4f} -> {1:.4f}'.format(star2_teff, star2_teff_round))

            star2_teff = star2_teff_round

    # Set up binary model
    b = phoebe.default_binary()

    ## Set a default distance
    b.set_value('distance', 10 * u.pc)

    ## Set period, semimajor axis, and mass ratio (q)
    binary_sma = ((binary_period**2. * const.G * (star1_mass + star2_mass)) /
                  (4. * np.pi**2.))**(1. / 3.)

    binary_q = star2_mass / star1_mass

    if print_diagnostics:
        print('\nBinary orbit checks')
        print('Binary SMA: {0}'.format(binary_sma.to(u.AU)))
        print('Binary Mass Ratio (q): {0}'.format(binary_q))

    b.set_value('period@orbit', binary_period)
    b.set_value('sma@binary@component', binary_sma)
    b.set_value('q@binary@component', binary_q)

    ## Inclination
    b.set_value('incl@orbit', binary_inc)

    # Check for overflow
    ## Variables to help store the non-detached binary cases
    star1_semidetached = False
    star2_semidetached = False

    star1_overflow = False
    star2_overflow = False

    ## Get the max radii for both component stars
    star1_rad_max = b.get_value('requiv_max@primary@component') * u.solRad
    star2_rad_max = b.get_value('requiv_max@secondary@component') * u.solRad

    ## Check for semidetached cases
    if print_diagnostics:
        print('\nSemidetached checks')
        print('Star 1: {0}'.format(
            np.abs((star1_rad - star1_rad_max) / star1_rad_max)))
        print('Star 2: {0}'.format(
            np.abs((star2_rad - star2_rad_max) / star2_rad_max)))

    semidet_cut = 0.001  # (within 0.1% of max radii)
    semidet_cut = 0.015  # (within 1.5% of max radii)

    if np.abs((star1_rad - star1_rad_max) / star1_rad_max) < semidet_cut:
        star1_semidetached = True
    if np.abs((star2_rad - star2_rad_max) / star2_rad_max) < semidet_cut:
        star2_semidetached = True

    ## Check for overflow
    if (star1_rad > star1_rad_max) and not star1_semidetached:
        star1_overflow = True

    if (star2_rad > star2_rad_max) and not star2_semidetached:
        star2_overflow = True

    ### Check for if both stars are overflowing; which star overflows more?
    ### Choose that star to be overflowing more
    if star1_overflow and star2_overflow:
        if (star1_rad - star1_rad_max) >= (star2_rad - star2_rad_max):
            star2_overflow = False
        else:
            star1_overflow = False

    if print_diagnostics:
        print('\nOverflow Checks')
        print('Star 1 Semidetached: {0}'.format(star1_semidetached))
        print('Star 2 Semidetached: {0}'.format(star2_semidetached))
        print('Star 1 Overflow: {0}'.format(star1_overflow))
        print('Star 2 Overflow: {0}'.format(star2_overflow))

    # If star 2 is overflowing, have to re set up model:
    # Calling this same binary_star_lc function again,
    # with star 2 as primary and star 1 as secondary.
    # Change t0 = t0 - per/2 to make sure phase is correct,
    # wrt stars 1 and 2 being in same respective position
    if star2_overflow and not star1_overflow:
        redo_binary_params = (binary_period, binary_ecc, binary_inc,
                              t0 - (binary_period.to(u.d).value / 2.))

        return binary_star_lc(star2_params,
                              star1_params,
                              redo_binary_params,
                              observation_times,
                              use_blackbody_atm=use_blackbody_atm,
                              make_mesh_plots=make_mesh_plots,
                              mesh_temp=mesh_temp,
                              mesh_temp_cmap=mesh_temp_cmap,
                              plot_name=plot_name,
                              print_diagnostics=print_diagnostics,
                              par_compute=par_compute,
                              num_par_processes=num_par_processes,
                              num_triangles=num_triangles)

    ## If none of these overflow cases, set variable to store if binary is detached
    binary_detached = (not star1_semidetached) and \
                      (not star2_semidetached) and \
                      (not star1_overflow) and \
                      (not star2_overflow)

    ### Set non-zero eccentricity only if binary is detached
    if binary_detached:
        b.set_value('ecc@binary@component', binary_ecc)
    else:
        b.set_value('ecc@binary@component', 0.)

    ## Change set up for contact or semidetached cases
    if star1_overflow or star2_overflow:
        b = phoebe.default_binary(contact_binary=True)

        ### Reset all necessary binary properties for contact system
        b.set_value('distance', 10 * u.pc)

        b.set_value('period@orbit', binary_period)
        b.set_value('sma@binary@component', binary_sma)
        b.set_value('q@binary@component', binary_q)
        b.set_value('incl@orbit', binary_inc)

    if star1_semidetached and not star2_overflow:
        b.add_constraint('semidetached', 'primary')
    if star2_semidetached and not star1_overflow:
        b.add_constraint('semidetached', 'secondary')

    # Set up compute
    if use_blackbody_atm:
        b.add_compute('phoebe',
                      compute='detailed',
                      irrad_method='wilson',
                      atm='blackbody')
    else:
        b.add_compute('phoebe', compute='detailed', irrad_method='wilson')

    # Set the parameters of the component stars of the system
    ## Primary
    b.set_value('teff@primary@component', star1_teff)
    # b.set_value('logg@primary@component', star1_logg)
    if (not star1_semidetached) and (not star2_overflow):
        b.set_value('requiv@primary@component', star1_rad)

    ## Secondary
    b.set_value('teff@secondary@component', star2_teff)
    # b.set_value('logg@secondary@component', star2_logg)
    if (not star2_semidetached) and (not star1_overflow) and (
            not star2_overflow):
        try:
            b.set_value('requiv@secondary@component', star2_rad)
        except:
            print('\nOverflow Checks')
            print('Star 1 Semidetached: {0}'.format(star1_semidetached))
            print('Star 2 Semidetached: {0}'.format(star2_semidetached))
            print('Star 1 Overflow: {0}'.format(star1_overflow))
            print('Star 2 Overflow: {0}'.format(star2_overflow))

            print("Cannot set secondary radius: {0}".format(sys.exc_info()[0]))

            return err_out

    # Set the number of triangles in the mesh
    # Detached stars
    if len(b.filter('ntriangles@primary@detailed@compute')) == 1:
        b.set_value('ntriangles@primary@detailed@compute', num_triangles)

    if len(b.filter('ntriangles@secondary@detailed@compute')) == 1:
        b.set_value('ntriangles@secondary@detailed@compute', num_triangles)

    # Contact envelope
    if len(b.filter('ntriangles@contact_envelope@detailed@compute')) == 1:
        if print_diagnostics:
            print('Setting number of triangles for contact envelope')
        b.set_value('ntriangles@contact_envelope@detailed@compute',
                    num_triangles * 2.)

    # Phase the observation times
    ## Read in observation times
    (kp_MJDs, h_MJDs, mesh_MJDs) = observation_times

    ## Phase the observation times
    kp_phased_days = (
        (kp_MJDs - t0) % binary_period.to(u.d).value) / binary_period.to(
            u.d).value
    h_phased_days = ((h_MJDs - t0) %
                     binary_period.to(u.d).value) / binary_period.to(u.d).value
    mesh_phased_days = (
        (mesh_MJDs - t0) % binary_period.to(u.d).value) / binary_period.to(
            u.d).value

    # Add light curve datasets
    ## Kp
    kp_phases_sorted_inds = np.argsort(kp_phased_days)

    kp_model_times = (kp_phased_days) * binary_period.to(u.d).value
    kp_model_times = kp_model_times[kp_phases_sorted_inds]

    # b.add_dataset(phoebe.dataset.lc, time=kp_model_times,
    #               dataset='mod_lc_Kp', passband='Keck_NIRC2:Kp')
    if use_blackbody_atm:
        b.add_dataset(phoebe.dataset.lc,
                      time=kp_model_times,
                      dataset='mod_lc_Kp',
                      passband='Keck_NIRC2:Kp')
        b.set_value('ld_mode@primary@mod_lc_Kp', 'manual')
        b.set_value('ld_mode@secondary@mod_lc_Kp', 'manual')
        b.set_value('ld_func@primary@mod_lc_Kp', 'logarithmic')
        b.set_value('ld_func@secondary@mod_lc_Kp', 'logarithmic')
    else:
        b.add_dataset(phoebe.dataset.lc,
                      time=kp_model_times,
                      dataset='mod_lc_Kp',
                      passband='Keck_NIRC2:Kp')

    ## H
    h_phases_sorted_inds = np.argsort(h_phased_days)

    h_model_times = (h_phased_days) * binary_period.to(u.d).value
    h_model_times = h_model_times[h_phases_sorted_inds]

    # b.add_dataset(phoebe.dataset.lc, times=h_model_times,
    #               dataset='mod_lc_H', passband='Keck_NIRC2:H')
    if use_blackbody_atm:
        b.add_dataset(phoebe.dataset.lc,
                      times=h_model_times,
                      dataset='mod_lc_H',
                      passband='Keck_NIRC2:H')
        b.set_value('ld_mode@primary@mod_lc_H', 'manual')
        b.set_value('ld_mode@secondary@mod_lc_H', 'manual')
        b.set_value('ld_func@primary@mod_lc_H', 'logarithmic')
        b.set_value('ld_func@secondary@mod_lc_H', 'logarithmic')
    else:
        b.add_dataset(phoebe.dataset.lc,
                      times=h_model_times,
                      dataset='mod_lc_H',
                      passband='Keck_NIRC2:H')

    # Add mesh dataset if making mesh plot
    mesh_phases_sorted_inds = np.argsort(mesh_phased_days)

    mesh_model_times = (mesh_phased_days) * binary_period.to(u.d).value
    mesh_model_times = mesh_model_times[mesh_phases_sorted_inds]

    if make_mesh_plots:
        b.add_dataset('mesh', times=mesh_model_times, dataset='mod_mesh')

        if mesh_temp:
            b['columns@mesh'] = ['teffs', 'loggs']

    # Set the passband luminosities for the stars
    b.set_value('pblum_mode@mod_lc_Kp', 'decoupled')
    b.set_value('pblum_mode@mod_lc_H', 'decoupled')

    b.set_value('pblum@primary@mod_lc_Kp', star1_pblum_Kp)
    b.set_value('pblum@primary@mod_lc_H', star1_pblum_H)

    b.set_value('pblum@secondary@mod_lc_Kp', star2_pblum_Kp)
    b.set_value('pblum@secondary@mod_lc_H', star2_pblum_H)

    # Run compute
    # if print_diagnostics:
    #     print("Trying inital compute run")
    #     b.run_compute(compute='detailed', model='run',
    #                   progressbar=False)

    try:
        b.run_compute(compute='detailed', model='run', progressbar=False)
    except:
        if print_diagnostics:
            print("Error during primary binary compute: {0}".format(
                sys.exc_info()[0]))
        return err_out

    # Save out mesh plot
    if make_mesh_plots:
        ## Plot Nerdery
        plt.rc('font', family='serif')
        plt.rc('font', serif='Computer Modern Roman')
        plt.rc('text', usetex=True)
        plt.rc('text.latex', preamble=r"\usepackage{gensymb}")

        plt.rc('xtick', direction='in')
        plt.rc('ytick', direction='in')
        # plt.rc('xtick', top = True)
        # plt.rc('ytick', right = True)

        suffix_str = ''
        if plot_name is not None:
            suffix_str = '_' + plot_name

        ## Mesh plot
        mesh_plot_out = []

        if mesh_temp:
            b['mod_mesh@model'].plot(
                fc='teffs',
                fcmap=mesh_temp_cmap,
                ec='face',
                animate=True,
                save='./binary_mesh{0}.gif'.format(suffix_str),
                save_kwargs={'writer': 'imagemagick'})
            for (mesh_model_time,
                 mesh_index) in zip(mesh_model_times,
                                    range(len(mesh_model_times))):
                plt.clf()
                new_fig = plt.figure()
                (mesh_af_fig, mesh_plt_fig) = b['mod_mesh@model'].plot(
                    fig=new_fig,
                    time=mesh_model_time,
                    fc='teffs',
                    fcmap=mesh_temp_cmap,
                    ec='face',
                    save='./binary_mesh_{0}.pdf'.format(mesh_index))
                mesh_plot_out.append(mesh_plt_fig)
                plt.close(new_fig)
        else:
            b['mod_mesh@model'].plot(
                animate=True,
                save='./binary_mesh{0}.gif'.format(suffix_str),
                save_kwargs={'writer': 'imagemagick'})
            for mesh_model_time in mesh_model_times:
                mesh_plot_out.append(b['mod_mesh@model'].plot(
                    time=mesh_model_time,
                    save='./binary_mesh.pdf'.format(suffix_str)))

    # Get fluxes
    ## Kp
    model_fluxes_Kp = np.array(
        b['fluxes@lc@mod_lc_Kp@model'].value) * u.W / (u.m**2.)
    model_mags_Kp = -2.5 * np.log10(model_fluxes_Kp / flux_ref_Kp) + 0.03

    ## H
    model_fluxes_H = np.array(
        b['fluxes@lc@mod_lc_H@model'].value) * u.W / (u.m**2.)
    model_mags_H = -2.5 * np.log10(model_fluxes_H / flux_ref_H) + 0.03

    if print_diagnostics:
        print('\nFlux Checks')
        print('Fluxes, Kp: {0}'.format(model_fluxes_Kp))
        print('Mags, Kp: {0}'.format(model_mags_Kp))
        print('Fluxes, H: {0}'.format(model_fluxes_H))
        print('Mags, H: {0}'.format(model_mags_H))

    if make_mesh_plots:
        return (model_mags_Kp, model_mags_H, mesh_plot_out)
    else:
        return (model_mags_Kp, model_mags_H)
示例#25
0
def test_binary(verbose=False):
    def assert_t0s(p1_t0_ref, p1_t0_supconj, p1_t0_perpass, tol=1e-4):
        # b.run_delayed_constraints()

        p2_t0_ref = b.get_value('t0_ref@component')
        p2_t0_supconj = b.get_value('t0_supconj@component')
        p2_t0_perpass = b.get_value('t0_perpass@component')

        if verbose:
            print("{}=={}, {}=={}, {}=={}".format(p1_t0_ref, p2_t0_ref,
                                                  p1_t0_supconj, p2_t0_supconj,
                                                  p1_t0_perpass,
                                                  p2_t0_perpass))

        assert (abs(p2_t0_ref - p1_t0_ref) < tol)
        assert (abs(p2_t0_supconj - p1_t0_supconj) < tol)
        assert (abs(p2_t0_perpass - p1_t0_perpass) < tol)

    b = phoebe.Bundle.default_binary()

    b = phoebe.default_binary()
    # ecc = 0, per0 = 0
    # compare against values in PHOEBE 1 by manually setting the HJD0 in PHOEBE 1
    # so that supconj matches the prescribed 0.0
    p1_ref = 0.0  # SET
    p1_supconj = 0.0
    p1_perpass = -0.25
    assert_t0s(p1_ref, p1_supconj, p1_perpass)

    b['ecc'] = 0.2
    p1_ref = 0.063235  # SET
    p1_supconj = 0.0
    p1_perpass = -0.186765
    assert_t0s(p1_ref, p1_supconj, p1_perpass)

    b['per0'] = 90
    p1_ref = 0.0  # SET
    p1_supconj = 0.0
    p1_perpass = 0.0
    assert_t0s(p1_ref, p1_supconj, p1_perpass)

    b.flip_constraint('t0_ref', solve_for='t0_supconj')
    # shouldn't change values
    assert_t0s(p1_ref, p1_supconj, p1_perpass)

    b['t0_ref@component'] = 0.0
    b['per0'] = 180
    p1_ref = 0.0  # SET
    p1_supconj = 0.063235
    p1_perpass = 0.25
    assert_t0s(p1_ref, p1_supconj, p1_perpass)

    b['t0_ref@component'] = 0.3
    b['per0'] = 45
    p1_ref = 0.3  # SET
    p1_supconj = 0.259489
    p1_perpass = 0.17500
    assert_t0s(p1_ref, p1_supconj, p1_perpass)

    # cannot flip both constraints to solve for t0_supconj
    assert_raises(ValueError,
                  b.flip_constraint,
                  't0_perpass',
                  solve_for='t0_supconj')

    b.flip_constraint('t0_supconj', solve_for='t0_ref')
    b.flip_constraint('t0_perpass', solve_for='t0_supconj')
    # shouldn't change values
    assert_t0s(p1_ref, p1_supconj, p1_perpass)

    b['t0_perpass'] = 0.0
    b['period@orbit'] = 3
    b['ecc'] = 0.3
    b['per0'] = 0.123, 'rad'
    # set p1 HJD0 = +0.691272
    p1_ref = 0.691272  # SET
    p1_supconj = 0.418709
    p1_perpass = 0.0
    assert_t0s(p1_ref, p1_supconj, p1_perpass)

    return b
#!pip install -I "phoebe>=2.3,<2.4"

# In[2]:

import phoebe
from phoebe import u  # units
import numpy as np
import matplotlib.pyplot as plt

logger = phoebe.logger()

# Here we'll initialize a default binary, but ask for it to be created as a contact system.

# In[3]:

b_cb = phoebe.default_binary(contact_binary=True)

# We'll compare this to the default detached binary

# In[4]:

b_detached = phoebe.default_binary()

# Hierarchy
# -------------

# Let's first look at the hierarchy of the default detached binary, and then compare that to the hierarchy of the overcontact system

# In[5]:

print(b_detached.hierarchy)
示例#27
0
def get_binary(dict, times, flux):
    binary = phoebe.default_binary()
    binary.set_value('vgamma@system', dict['vgamma@system'])
    mass1 = dict['mass@primary']
    mass2 = dict['mass@secondary']

    P = dict['period@binary']
    mu_sun = 1.32712440018e20  # = G M_sun [m3 s^-2], Wiki Standard_gravitational_parameter
    R_sun = 695700000  # [m] Wiki Sun

    sma = (mu_sun * (mass1 + mass2) *
           (P * 86400 / (2 * np.pi))**2)**(1. / 3) / R_sun  # Kepler equation

    incl = dict['incl@binary']
    vp_sini = dict['vsini@primary']
    vs_sini = dict['vsini@secondary']

    Rp = dict['requiv@primary']  # [R_sun]
    Rs = dict['requiv@secondary']  # [R_sun]

    sini = np.sin(np.pi * incl / 180)

    vp = vp_sini * 86400 / sini  # [km/s]
    vs = vs_sini * 86400 / sini  # [km/s]

    Pp = 2 * np.pi * Rp * R_sun / 1000 / vp
    Ps = 2 * np.pi * Rs * R_sun / 1000 / vs

    Fp = P / Pp
    Fs = P / Ps

    binary.set_value('q', mass2 / mass1)
    binary.set_value('incl@binary', incl)
    binary.set_value('sma@binary', sma)  # calculated
    binary.set_value('ecc@binary', abs(dict['ecc@binary']))

    binary.set_value('period@binary', P)  # calculated

    binary.set_value('syncpar@primary', Fp)  # calculated
    binary.set_value('syncpar@secondary', Fs)  # calculated

    binary.set_value('requiv@primary', Rp)
    binary.set_value('requiv@secondary', Rs)

    binary.set_value('teff@primary', dict['teff@primary'])
    binary.set_value('teff@secondary', dict['teff@secondary'])

    binary.set_value('syncpar@secondary@component', 1)
    binary.set_value('syncpar@primary@component', 1)

    binary.set_value('t0_supconj@binary@component',
                     dict['t0_supconj@binary@component'])

    binary.add_dataset('lc',
                       times=times,
                       dataset='lc01',
                       fluxes=flux,
                       overwrite=True,
                       ld_func='logarithmic',
                       passband='TESS:T')
    binary.set_value('pblum_mode', 'dataset-scaled')

    binary['gravb_bol@primary'] = dict['gravb_bol@primary']
    binary['gravb_bol@secondary'] = dict['gravb_bol@secondary']
    binary['irrad_frac_refl_bol@primary'] = dict['irrad_frac_refl_bol@primary']
    binary['irrad_frac_refl_bol@secondary'] = dict[
        'irrad_frac_refl_bol@secondary']

    return binary
示例#28
0
    file = open(path + fileName + 'Outputs.txt', 'w')
    file.write('')

    #Create new folder for lightcurves
    if not os.path.exists(path):
        os.mkdir(path)

    start = time.time()

    period, times, fluxes, sigmas = np.genfromtxt(
        'lightcurves/Data/Running Median/' + fileName + '.csv',
        delimiter=',',
        unpack=True)
    period = period[0]

    b = pb.default_binary()
    b.add_dataset('lc',
                  times=times,
                  fluxes=fluxes,
                  sigmas=sigmas,
                  passband='Johnson:R',
                  dataset='lc01',
                  overwrite=True)
    b.set_value('period@binary', value=period)

    b.set_value('requiv@primary@star@component', value=1.07)

    b.set_value('teff@primary@star@component', value=5800)
    b.set_value('teff@secondary@star@component', value=5500)

    b.set_value('incl@orbit', value=79)
示例#29
0
def binary_star_lc(star1_params, star2_params, binary_params, observation_times,
        use_blackbody_atm=False,
        use_compact_object=False,
        make_mesh_plots=False, mesh_temp=False, mesh_temp_cmap=None,
        plot_name=None,
        print_diagnostics=False, par_compute=False, num_par_processes=8,
        num_triangles=1500):
    """Compute the light curve for a binary system
    
    Keyword arguments:
    star1_params -- Tuple of parameters for the primary star
    star2_params -- Tuple of parameters for the secondary star
    binary_params -- Tuple of parameters for the binary system configuration
    observation_times -- Tuple of observation times,
        with numpy array of MJDs in each band and for the RVs
        (kp_MJDs, h_MJDs, rv_MJDs) = observation_times
    use_blackbody_atm -- Use blackbody atmosphere
        instead of default Castelli & Kurucz (default False)
    use_compact_object -- Set eclipse_method to 'only_horizon',
            necessary for compact companions without eclipses (default False)
    make_mesh_plots -- Make a mesh plot of the binary system (default False)
    plot_name
    print_diagnostics
    par_compute
    num_par_processes
    """
    
    if par_compute:
        # TODO: Need to implement parallelization correctly
        phoebe.mpi_on(nprocs=num_par_processes)
    else:
        phoebe.mpi_off()
    
    # Read in the stellar parameters of the binary components
    (star1_mass, star1_rad, star1_teff, star1_logg,
     [star1_mag_Kp, star1_mag_H],
     [star1_pblum_Kp, star1_pblum_H]) = star1_params
    (star2_mass, star2_rad, star2_teff, star2_logg,
     [star2_mag_Kp, star2_mag_H],
     [star2_pblum_Kp, star2_pblum_H]) = star2_params
    
    # Read in the parameters of the binary system
    (binary_period, binary_ecc, binary_inc, t0) = binary_params
    
    err_out = (np.array([-1.]), np.array([-1.]),
               np.array([-1.]), np.array([-1.]))
    if make_mesh_plots:
        err_out = (np.array([-1.]), np.array([-1.]),
                   np.array([-1.]), np.array([-1.]),
                   np.array([-1.]))
    
    # Check for high temp ck2004 atmosphere limits
    if not use_blackbody_atm:
        # log g = 3.5, high temp bounds (above 31e3 K)
        if star1_teff > (31000 * u.K) and (4.0 > star1_logg > 3.5):
            star1_teff_round = 30995.0 * u.K
            
            if print_diagnostics:
                print('Star 1 out of C&K 2004 grid')
                print('star1_logg = {0:.4f}'.format(star1_logg))
                print('Rounding down star1_teff')
                print('{0:.4f} -> {1:.4f}'.format(star1_teff, star1_teff_round))
            
            star1_teff = star1_teff_round
        if star2_teff > (31000 * u.K) and (4.0 > star2_logg > 3.5):
            star2_teff_round = 30995.0 * u.K
            
            if print_diagnostics:
                print('Star 2 out of C&K 2004 grid')
                print('star2_logg = {0:.4f}'.format(star2_logg))
                print('Rounding down star2_teff')
                print('{0:.4f} -> {1:.4f}'.format(star2_teff, star2_teff_round))
            
            star2_teff = star2_teff_round
        
        # log g = 4.0, high temp bounds (above 40e3 K)
        if star1_teff > (40000 * u.K) and (4.5 > star1_logg > 4.0):
            star1_teff_round = 39995.0 * u.K
            
            print('Star 1 out of C&K 2004 grid')
            print('star1_logg = {0:.4f}'.format(star1_logg))
            print('Rounding down star1_teff')
            print('{0:.4f} -> {1:.4f}'.format(star1_teff, star1_teff_round))
            
            star1_teff = star1_teff_round
        if star2_teff > (40000 * u.K) and (4.0 > star2_logg > 3.50):
            star2_teff_round = 39995.0 * u.K
            
            print('Star 2 out of C&K 2004 grid')
            print('star2_logg = {0:.4f}'.format(star2_logg))
            print('Rounding down star2_teff')
            print('{0:.4f} -> {1:.4f}'.format(star2_teff, star2_teff_round))
            
            star2_teff = star2_teff_round
    
    # Set up binary model
    b = phoebe.default_binary()
    
    ## Set a default distance
    b.set_value('distance', 10 * u.pc)
    
    ## Set period, semimajor axis, and mass ratio (q)
    binary_sma = ((binary_period**2. * const.G * (star1_mass + star2_mass)) / (4. * np.pi**2.))**(1./3.)
    
    binary_q = star2_mass / star1_mass
    
    if print_diagnostics:
        print('\nBinary orbit checks')
        print('Binary SMA: {0}'.format(binary_sma.to(u.AU)))
        print('Binary Mass Ratio (q): {0}'.format(binary_q))
    
    b.set_value('period@orbit', binary_period)
    b.set_value('sma@binary@component', binary_sma)
    b.set_value('q@binary@component', binary_q)
    
    ## Inclination
    b.set_value('incl@orbit', binary_inc)
    
    # Check for overflow
    ## Variables to help store the non-detached binary cases
    star1_semidetached = False
    star2_semidetached = False
    
    star1_overflow = False
    star2_overflow = False
    
    ## Get the max radii for both component stars
    star1_rad_max = b.get_value('requiv_max@primary@component') * u.solRad
    star2_rad_max = b.get_value('requiv_max@secondary@component') * u.solRad
    
    ## Check for semidetached cases
    if print_diagnostics:
        print('\nSemidetached checks')
        print('Star 1: {0}'.format(np.abs((star1_rad - star1_rad_max) / star1_rad_max)))
        print('Star 2: {0}'.format(np.abs((star2_rad - star2_rad_max) / star2_rad_max)))
    
    semidet_cut = 0.001   # (within 0.1% of max radii)
    semidet_cut = 0.015   # (within 1.5% of max radii)
    
    if np.abs((star1_rad - star1_rad_max) / star1_rad_max) < semidet_cut:
        star1_semidetached = True
    if np.abs((star2_rad - star2_rad_max) / star2_rad_max) < semidet_cut:
        star2_semidetached = True
    
    ## Check for overflow
    if (star1_rad > star1_rad_max) and not star1_semidetached:
        star1_overflow = True
    
    if (star2_rad > star2_rad_max) and not star2_semidetached:
        star2_overflow = True
    
    
    
    ### Check for if both stars are overflowing; which star overflows more?
    ### Choose that star to be overflowing more
    if star1_overflow and star2_overflow:
        if (star1_rad - star1_rad_max) >= (star2_rad - star2_rad_max):
            star2_overflow = False
        else:
            star1_overflow = False
    
    
    if print_diagnostics:
        print('\nOverflow Checks')
        print('Star 1 Semidetached: {0}'.format(star1_semidetached))
        print('Star 2 Semidetached: {0}'.format(star2_semidetached))
        print('Star 1 Overflow: {0}'.format(star1_overflow))
        print('Star 2 Overflow: {0}'.format(star2_overflow))
    
    # If star 2 is overflowing, have to re set up model:
    # Calling this same binary_star_lc function again,
    # with star 2 as primary and star 1 as secondary.
    # Change t0 = t0 - per/2 to make sure phase is correct,
    # wrt stars 1 and 2 being in same respective position
    if star2_overflow and not star1_overflow:
        redo_binary_params = (binary_period, binary_ecc, binary_inc,
                              t0 - (binary_period.to(u.d).value/2.))
        
        return binary_star_lc(star2_params, star1_params,
                    redo_binary_params,
                    observation_times,
                    use_blackbody_atm=use_blackbody_atm,
                    make_mesh_plots=make_mesh_plots,
                    mesh_temp=mesh_temp, mesh_temp_cmap=mesh_temp_cmap,
                    plot_name=plot_name,
                    print_diagnostics=print_diagnostics,
                    par_compute=par_compute, num_par_processes=num_par_processes,
                    num_triangles=num_triangles)
    
    ## If none of these overflow cases, set variable to store if binary is detached
    binary_detached = (not star1_semidetached) and \
                      (not star2_semidetached) and \
                      (not star1_overflow) and \
                      (not star2_overflow)
    
    ### Set non-zero eccentricity only if binary is detached
    if binary_detached:
        b.set_value('ecc@binary@component', binary_ecc)
    else:
        b.set_value('ecc@binary@component', 0.)
    
    ## Change set up for contact or semidetached cases
    if star1_overflow or star2_overflow:
        b = phoebe.default_binary(contact_binary=True)
        
        ### Reset all necessary binary properties for contact system
        b.set_value('distance', 10 * u.pc)
        
        b.set_value('period@orbit', binary_period)
        b.set_value('sma@binary@component', binary_sma)
        b.set_value('q@binary@component', binary_q)
        b.set_value('incl@orbit', binary_inc)
    
    if star1_semidetached and not star2_overflow:
        b.add_constraint('semidetached', 'primary')
    if star2_semidetached and not star1_overflow:
        b.add_constraint('semidetached', 'secondary')
    
    # Set up compute
    if use_blackbody_atm:
        b.add_compute('phoebe', compute='detailed',
                      irrad_method='wilson', atm='blackbody')
        
        b.set_value('atm@primary@detailed', 'blackbody')
        b.set_value('atm@secondary@detailed', 'blackbody')
    else:
        b.add_compute('phoebe', compute='detailed', irrad_method='wilson')
    
    # Set the parameters of the component stars of the system
    ## Primary
    b.set_value('teff@primary@component', star1_teff)
    # b.set_value('logg@primary@component', star1_logg)
    if (not star1_semidetached) and (not star2_overflow):
        b.set_value('requiv@primary@component', star1_rad)
    
    ## Secondary
    b.set_value('teff@secondary@component', star2_teff)
    # b.set_value('logg@secondary@component', star2_logg)
    if (not star2_semidetached) and (not star1_overflow) and (not star2_overflow):
        try:
            b.set_value('requiv@secondary@component', star2_rad)
        except:
            print('\nOverflow Checks')
            print('Star 1 Semidetached: {0}'.format(star1_semidetached))
            print('Star 2 Semidetached: {0}'.format(star2_semidetached))
            print('Star 1 Overflow: {0}'.format(star1_overflow))
            print('Star 2 Overflow: {0}'.format(star2_overflow))
            
            print("Cannot set secondary radius: {0}".format(sys.exc_info()[0]))
            
            return err_out
    
    
    # Set the number of triangles in the mesh
    # Detached stars
    if len(b.filter('ntriangles@primary@detailed@compute')) == 1: 
        b.set_value('ntriangles@primary@detailed@compute', num_triangles)
        
    if len(b.filter('ntriangles@secondary@detailed@compute')) == 1: 
        b.set_value('ntriangles@secondary@detailed@compute', num_triangles)
    
    # Contact envelope
    if len(b.filter('ntriangles@contact_envelope@detailed@compute')) == 1:
       if print_diagnostics:
           print('Setting number of triangles for contact envelope')
       b.set_value('ntriangles@contact_envelope@detailed@compute',
                   num_triangles * 2.)
    
    # Phase the observation times
    ## Read in observation times
    (kp_MJDs, h_MJDs, rv_MJDs) = observation_times
    
    ## Phase the observation times
    kp_phased_days = ((kp_MJDs - t0) % binary_period.to(u.d).value) / binary_period.to(u.d).value
    h_phased_days = ((h_MJDs - t0) % binary_period.to(u.d).value) / binary_period.to(u.d).value
    rv_phased_days = ((rv_MJDs - t0) % binary_period.to(u.d).value) / binary_period.to(u.d).value
    
    # Add light curve datasets
    if use_blackbody_atm:
        b.set_value_all('ld_mode_bol', 'manual')
        b.set_value_all('ld_func_bol', 'linear')
        b.set_value_all('ld_coeffs_bol', [0.0])
    
    # Check for compact companion
    if use_compact_object:
        b.set_value('irrad_method@detailed', 'none')
    
    ## Kp
    kp_phases_sorted_inds = np.argsort(kp_phased_days)
    
    kp_model_times = (kp_phased_days) * binary_period.to(u.d).value
    kp_model_times = kp_model_times[kp_phases_sorted_inds]
    
    if use_blackbody_atm:
        b.add_dataset(phoebe.dataset.lc, time=kp_model_times,
                      dataset='mod_lc_Kp', passband='Keck_NIRC2:Kp')
        
        b.set_value_all('ld_mode@mod_lc_Kp', 'manual')
        
        b.set_value_all('ld_func@mod_lc_Kp', 'linear')
        
        b.set_value_all('ld_coeffs@mod_lc_Kp', [0.0])
    else:
        b.add_dataset(phoebe.dataset.lc, time=kp_model_times,
                      dataset='mod_lc_Kp', passband='Keck_NIRC2:Kp')
    
    ## H
    h_phases_sorted_inds = np.argsort(h_phased_days)
    
    h_model_times = (h_phased_days) * binary_period.to(u.d).value
    h_model_times = h_model_times[h_phases_sorted_inds]
    
    if use_blackbody_atm:
        b.add_dataset(phoebe.dataset.lc, times=h_model_times,
                      dataset='mod_lc_H', passband='Keck_NIRC2:H')
        
        b.set_value_all('ld_mode@mod_lc_H', 'manual')
        
        b.set_value_all('ld_func@mod_lc_H', 'linear')
        
        b.set_value_all('ld_coeffs@mod_lc_H', [0.0])
    else:
        b.add_dataset(phoebe.dataset.lc, times=h_model_times,
                      dataset='mod_lc_H', passband='Keck_NIRC2:H')
    
    ## RV
    rv_phases_sorted_inds = np.argsort(rv_phased_days)
    
    rv_model_times = (rv_phased_days) * binary_period.to(u.d).value
    rv_model_times = rv_model_times[rv_phases_sorted_inds]
    
    if use_blackbody_atm:
        b.add_dataset(phoebe.dataset.rv, time=rv_model_times,
                      dataset='mod_rv', passband='Keck_NIRC2:Kp')
        
        b.set_value_all('ld_mode@mod_rv', 'manual')
        
        b.set_value_all('ld_func@mod_rv', 'linear')
        
        b.set_value_all('ld_coeffs@mod_rv', [0.0])
    else:
        b.add_dataset(phoebe.dataset.rv, time=rv_model_times,
                      dataset='mod_rv', passband='Keck_NIRC2:Kp')
    
    
    # Add mesh dataset if making mesh plot
    if make_mesh_plots:
        b.add_dataset('mesh', times=[(binary_period/4.).to(u.d).value],
                      dataset='mod_mesh')
        if mesh_temp:
            b['columns@mesh'] = ['teffs', 'loggs', 'areas',
                                 '*@mod_lc_Kp', '*@mod_lc_H']
    
    # Set the passband luminosities for the stars
    b.set_value('pblum_mode@mod_lc_Kp', 'decoupled')
    b.set_value('pblum_mode@mod_lc_H', 'decoupled')
    
    b.set_value('pblum@primary@mod_lc_Kp', star1_pblum_Kp)
    b.set_value('pblum@primary@mod_lc_H', star1_pblum_H)
    
    b.set_value('pblum@secondary@mod_lc_Kp', star2_pblum_Kp)
    b.set_value('pblum@secondary@mod_lc_H', star2_pblum_H)
    
    # Run compute
    # Determine eclipse method
    if use_compact_object:
        eclipse_method = 'only_horizon'
    else:
        eclipse_method = 'native'
    
    if print_diagnostics:
        print("Trying inital compute run")
        b.run_compute(compute='detailed', model='run',
                      progressbar=False, eclipse_method=eclipse_method)
    else:
        try:
            b.run_compute(compute='detailed', model='run',
                          progressbar=False, eclipse_method=eclipse_method)
        except:
            if print_diagnostics:
                print("Error during primary binary compute: {0}".format(sys.exc_info()[0]))
            return err_out
    
    
    # Save out mesh plot
    if make_mesh_plots:
        ## Plot Nerdery
        plt.rc('font', family='serif')
        plt.rc('font', serif='Computer Modern Roman')
        plt.rc('text', usetex=True)
        plt.rc('text.latex', preamble=r"\usepackage{gensymb}")

        plt.rc('xtick', direction = 'in')
        plt.rc('ytick', direction = 'in')
        # plt.rc('xtick', top = True)
        # plt.rc('ytick', right = True)
        
        suffix_str = ''
        if plot_name is not None:
            suffix_str = '_' + plot_name
        
        ## Mesh plot
        if mesh_temp:
            mesh_plot_out = b['mod_mesh@model'].plot(save='./binary_mesh{0}.pdf'.format(suffix_str),
                                                     fc='teffs',
                                                     fcmap=mesh_temp_cmap,
                                                     ec='none')
                                                     
            # print(mesh_plot_out.axs)
            
            # Extract and output mesh quantities
            mesh_quant_names = ['teffs', 'loggs', 'areas', 'abs_intensities']
            mesh_quant_do_filt = [False, False, False, True]
            mesh_quant_units = [u.K, 1.0, u.solRad**2, u.W / (u.m**3)]
            
            mesh_quant_filts = ['mod_lc_Kp', 'mod_lc_H']            
            mesh_quants_pri = {}
            mesh_quants_sec = {}
            
            for (quant, do_filt,
                 quant_unit) in zip(mesh_quant_names, mesh_quant_do_filt,
                                    mesh_quant_units):
                if do_filt:
                    for filt in mesh_quant_filts:
                        quant_pri = b['{0}@primary@{1}'.format(quant, filt)].value *\
                                    quant_unit
                        quant_sec = b['{0}@secondary@{1}'.format(quant, filt)].value *\
                                    quant_unit
                    
                        mesh_quants_pri['{0}_{1}'.format(quant, filt)] = quant_pri
                        mesh_quants_sec['{0}_{1}'.format(quant, filt)] = quant_sec
                else:
                    quant_pri = b['{0}@primary'.format(quant)].value * quant_unit
                    quant_sec = b['{0}@secondary'.format(quant)].value * quant_unit
                    
                    mesh_quants_pri[quant] = quant_pri
                    mesh_quants_sec[quant] = quant_sec
            
            # Construct mesh tables for each star and output
            mesh_pri_table = Table(mesh_quants_pri)
            mesh_pri_table.sort(['teffs'], reverse=True)
            with open('mesh_pri.txt', 'w') as out_file:
                for line in mesh_pri_table.pformat_all():
                    out_file.write(line + '\n')
            mesh_pri_table.write('mesh_pri.h5', format='hdf5',
                                 path='data', serialize_meta=True,
                                 overwrite=True)
            mesh_pri_table.write('mesh_pri.fits', format='fits',
                                 overwrite=True)
            
            mesh_sec_table = Table(mesh_quants_sec)
            mesh_sec_table.sort(['teffs'], reverse=True)
            with open('mesh_sec.txt', 'w') as out_file:
                for line in mesh_sec_table.pformat_all():
                    out_file.write(line + '\n')
            mesh_sec_table.write('mesh_sec.h5', format='hdf5',
                                 path='data', serialize_meta=True,
                                 overwrite=True)
            mesh_sec_table.write('mesh_sec.fits', format='fits',
                                 overwrite=True)
        else:
            mesh_plot_out = b['mod_mesh@model'].plot(save='./binary_mesh{0}.pdf'.format(suffix_str))
    
    
    # Get fluxes
    ## Kp
    model_fluxes_Kp = np.array(b['fluxes@lc@mod_lc_Kp@model'].value) * u.W / (u.m**2.)
    model_mags_Kp = -2.5 * np.log10(model_fluxes_Kp / flux_ref_Kp) + 0.03
    
    ## H
    model_fluxes_H = np.array(b['fluxes@lc@mod_lc_H@model'].value) * u.W / (u.m**2.)
    model_mags_H = -2.5 * np.log10(model_fluxes_H / flux_ref_H) + 0.03
    
    # Get RVs
    model_RVs_pri = np.array(b['rvs@primary@run@rv@model'].value) * u.km / u.s
    model_RVs_sec = np.array(b['rvs@secondary@run@rv@model'].value) * u.km / u.s
    
    
    if print_diagnostics:
        print("\nFlux Checks")
        print("Fluxes, Kp: {0}".format(model_fluxes_Kp))
        print("Mags, Kp: {0}".format(model_mags_Kp))
        print("Fluxes, H: {0}".format(model_fluxes_H))
        print("Mags, H: {0}".format(model_mags_H))
        
        print("\nRV Checks")
        print("RVs, Primary: {0}".format(model_RVs_pri))
        print("RVs, Secondary: {0}".format(model_RVs_sec))
        
    if make_mesh_plots:
        return (model_mags_Kp, model_mags_H,
                model_RVs_pri, model_RVs_sec,
                mesh_plot_out)
    else:
        return (model_mags_Kp, model_mags_H,
                model_RVs_pri, model_RVs_sec)
示例#30
0
#Create File Structure
fileName = 'lc_14535'
path = 'lightcurves/SolverFitted/'+fileName+'/'

#Create new folder for lightcurves
if not os.path.exists(path):
    os.mkdir(path)


start = time.time()

period, times, fluxes, sigmas = np.genfromtxt('lightcurves/Data/Running Median/' + fileName + '.csv', delimiter=',', unpack=True)
period = period[0]

b = pb.default_binary(contact_binary=True)
b.add_dataset('lc', times=times, fluxes=fluxes, sigmas=sigmas, passband='Johnson:R', dataset='lc01', overwrite=True)
b.set_value('period@binary', value=period)

b.flip_constraint('mass@primary', 'sma@orbit')
b.set_value('mass@primary@component', value=1.1) #1.1

b.flip_constraint('mass@secondary', 'q')
b.set_value('mass@secondary@component', value=1.0) #1.0

b.set_value('requiv@primary@star@component', value=1.21) #1.21

b.set_value('teff@primary@star@component', value=6300) #6300
b.set_value('teff@secondary@star@component', value=6000) #6000

b.set_value('incl@orbit', value=68) #68