Beispiel #1
0
    def ok(self):
        """
        Checks for silly parameter values. Runnning this before chisq could
        save time and disaster
        """

        return self.vcheck('q', 0.001, 100.) and self.vcheck('iangle', 0., 90.) and \
            self.vcheck('r1',0.,1.) and \
            (float(self['r2'][0]) <= 0. or self.vcheck('r2',0.,1-roche.xl1(float(self['q'][0])))) and \
            self.vcheck('cphi3',0.,0.25) and self.vcheck('cphi4',float(self['cphi3'][0]),0.25) and \
            self.vcheck('t1',0.,1.e6) and self.vcheck('t2',-1.e6,1.e6) and \
            self.vcheck('ldc1_1',-20.,20.) and self.vcheck('ldc1_2',-20.,20.) and \
            self.vcheck('ldc1_3',-20.,20.) and self.vcheck('ldc1_4',-20.,20.) and \
            self.vcheck('ldc2_1',-20.,20.) and self.vcheck('ldc2_2',-20.,20.) and \
            self.vcheck('ldc2_3',-20.,20.) and self.vcheck('ldc2_3',-20.,20.) and \
            self.vcheck('period',0.,100.) and self.vcheck('gravity_dark1',0.,1.) and \
            self.vcheck('gravity_dark2',0.,1.) and \
            (self['add_disc'][0] == '0' or \
                 ((float(self['rdisc1'][0]) <= 0. or self.vcheck('rdisc1',float(self['r1'][0]),1.0)) \
                      and (float(self['rdisc2'][0]) <= 0. or \
                               self.vcheck('rdisc2',float(self['rdisc1'][0]),1.)) and \
                      self.vcheck('temp_disc',0.,1.e6) and self.vcheck('texp_disc',-10.,10.))) and \
                      (self['add_spot'][0] == '0' or \
                           (self.vcheck('radius_spot',0.,0.85*roche.xl1(float(self['q'][0]))) and \
                                self.vcheck('length_spot',0.,10.) and \
                                self.vcheck('expon_spot',0.,30.) and self.vcheck('temp_spot',0.,1.e6) and \
                                self.vcheck('cfrac_spot',0.,1.) and self.vcheck('epow_spot',0.,10.)))
Beispiel #2
0
def ln_prior(pars):
    lnp = 0.0
    # mass ratio - be loose (B12 says about 0.15)
    prior = Prior("uniform", 0.02, 0.3)
    lnp += prior.ln_prob(pars[0])
    # r1_a (B12)
    prior = Prior("gaussPos", 0.0213, 0.0015)
    lnp += prior.ln_prob(pars[1])
    # limb darkening
    prior = Prior("gaussPos", 0.32, 0.03)
    lnp += prior.ln_prob(pars[2])
    # size of donor (B12)
    prior = Prior("gaussPos", 0.113, 0.02)
    # is donor bigger than roche lobe?
    if pars[0] <= 0 or pars[3] > 1.0 - roche.xl1(pars[0]):
        lnp += -np.inf
    else:
        lnp += prior.ln_prob(pars[3])
    # inclination (B12)
    prior = Prior("gaussPos", 85.9, 1.0)
    if pars[4] >= 90.0:
        lnp += -np.inf
    else:
        lnp += prior.ln_prob(pars[4])
    # wd flux
    prior = Prior("uniform", 0.01, 0.05)
    lnp += prior.ln_prob(pars[5])
    # donor flux
    prior = Prior("uniform", 0.00, 0.01)
    lnp += prior.ln_prob(pars[6])
    # phase offset
    prior = Prior("uniform", -0.01, 0.01)
    lnp += prior.ln_prob(pars[7])
    return lnp
def solve(input_data,baseDir):
    q,dphi,rw,twd,p = input_data

    # Kepler's law gives a quantity related to wd mass and separation, a
    # scaled_mass = a**3/M_wd. I call this the scaled mass.
    scaled_mass = const.G * (1+q) * p**2 / 4.0 / np.pi**2

    # convert white dwarf radius to units of separation, rw/a
    xl1_a = roche.xl1(q)
    rw_a = rw*xl1_a

    solved = True
    try:
        # try wood models
        mw = find_wdmass(twd,scaled_mass,rw_a,baseDir,model='wood')
    except:
        # try panei models (usually for masses above 1 Msun)
        try:
            mw = find_wdmass(twd,scaled_mass,rw_a,baseDir,model='panei')
        except:
            # try hamada models (for masses less than 0.4 or more than 1.2 Msun)
            try:
                mw=find_wdmass(twd,scaled_mass,rw_a,baseDir,model='hamada')
            except:
                solved = False

    # do nothing if none of the models yielded a solution
    # otherwise,         
    if solved:
        # donor star mass
        mr = mw*q
        
        # from this wd mass and scaled mass, find a
        a3 = scaled_mass*mw
        a = a3**(1./3.)
        a = a.to(units.R_sun)

        # inc
        inc = roche.findi(q,dphi)
        sini = np.sin(np.radians(inc))

        # radial velocities
        kw = (2.0*np.pi*sini*q*a/(1+q)/p).to(units.km/units.s)
        kr = kw/q
        
        #secondary radius
        #use from Warner 1995 (eggleton)
        #radius of sphere with same volume as Roche Lobe...
        r2 = 0.49*a*q**(2.0/3.0)
        r2 /= 0.6 * q**(2.0/3.0) + np.log(1.0+q**(1.0/3.0))

        # need to be a little careful here for different versions of astropy
        data = (q,mw,rw_a*a,mr,r2,a,kw,kr,inc)
        if not quantitySupport:
            data = [getval(datum) for datum in data]
            
        return data
    else:
        return None
Beispiel #4
0
 def ok(self):
     """
     Checks for silly parameter values. Runnning this before chisq could
     save time and disaster.
     """
     return (
         self.vcheck('q', 0.001, 100.) and self.vcheck('iangle', 0., 90.)
         and self.vcheck('r1', 0., 1.)
         and (float(self['r2'][0]) <= 0.
              or self.vcheck('r2', 0., 1 - roche.xl1(float(self['q'][0]))))
         and self.vcheck('cphi3', 0., 0.25)
         and self.vcheck('cphi4', float(self['cphi3'][0]), 0.25)
         and self.vcheck('t1', 0., 1.e6) and self.vcheck('t2', -1.e6, 1.e6)
         and self.vcheck('ldc1_1', -50., 50.)
         and self.vcheck('ldc1_2', -50., 50.)
         and self.vcheck('ldc1_3', -50., 50.)
         and self.vcheck('ldc1_4', -50., 50.)
         and self.vcheck('ldc2_1', -50., 50.)
         and self.vcheck('ldc2_2', -50., 50.)
         and self.vcheck('ldc2_3', -50., 50.)
         and self.vcheck('ldc2_3', -50., 50.)
         and self.vcheck('period', 0., 100.)
         and self.vcheck('gravity_dark1', 0., 5.)
         and self.vcheck('gravity_dark2', 0., 5.) and
         (self['add_disc'][0] == '0' or
          ((float(self['rdisc1'][0]) <= 0.
            or self.vcheck('rdisc1', float(self['r1'][0]), 1.0)) and
           (float(self['rdisc2'][0]) <= 0.
            or self.vcheck('rdisc2', float(self['rdisc1'][0]), 1.))
           and self.vcheck('temp_disc', 0., 1.e6)
           and self.vcheck('texp_disc', -10., 10.))) and
         (self['add_spot'][0] == '0' or
          (self.vcheck('radius_spot', 0., 0.85 * roche.xl1(
              float(self['q'][0]))) and self.vcheck('length_spot', 0., 10.)
           and self.vcheck('expon_spot', 0., 30.) and self.vcheck(
               'temp_spot', 0., 1.e6) and self.vcheck('cfrac_spot', 0., 1.)
           and self.vcheck('epow_spot', 0., 10.))))
Beispiel #5
0
def solve(input_data, baseDir):
    q, dphi, rw, twd, p = input_data

    # Kepler's law gives a quantity related to wd mass and separation, a
    # scaled_mass = a**3/M_wd. I call this the scaled mass.
    scaled_mass = const.G * (1 + q) * p**2 / 4.0 / np.pi**2

    # convert white dwarf radius to units of separation, rw/a
    xl1_a = roche.xl1(q)
    rw_a = rw * xl1_a

    solved = True
    try:
        # try wood models
        mw = find_wdmass(twd, scaled_mass, rw_a, baseDir, model='wood')
    except:
        # try panei models (usually for masses above 1 Msun)
        try:
            mw = find_wdmass(twd, scaled_mass, rw_a, baseDir, model='panei')
        except:
            # try hamada models (for masses less than 0.4 or more than 1.2 Msun)
            try:
                mw = find_wdmass(twd,
                                 scaled_mass,
                                 rw_a,
                                 baseDir,
                                 model='hamada')
            except:
                solved = False

    # do nothing if none of the models yielded a solution
    # otherwise,
    if solved:
        # donor star mass
        mr = mw * q

        # from this wd mass and scaled mass, find a
        a3 = scaled_mass * mw
        a = a3**(1. / 3.)
        a = a.to(units.R_sun)

        # inc
        inc = roche.findi(q, dphi)
        sini = np.sin(np.radians(inc))

        # radial velocities
        kw = (2.0 * np.pi * sini * q * a / (1 + q) / p).to(units.km / units.s)
        kr = kw / q

        #secondary radius
        #use from Warner 1995 (eggleton)
        #radius of sphere with same volume as Roche Lobe...
        r2 = 0.49 * a * q**(2.0 / 3.0)
        r2 /= 0.6 * q**(2.0 / 3.0) + np.log(1.0 + q**(1.0 / 3.0))

        # need to be a little careful here for different versions of astropy
        data = (q, mw, rw_a * a, mr, r2, a, kw, kr, inc)
        if not quantitySupport:
            data = [getval(datum) for datum in data]

        return data
    else:
        return None
    def ln_prior(self,verbose=False):
        """Returns the natural log of the prior probability of this model.
        
        Certain parameters (dphi, rdisc, scale, az) need to be treated as special cases,
        as the model contains more prior information than included in the parameter priors"""
        
        # Use of the super function allows abstract class in model.py to be referenced
        # Here the ln_prior function is referenced
        retVal = super(LCModel,self).ln_prior()
        
        # Remaining part of this function deals with special cases
        # dphi
        tol = 1.0e-6
        try:
            # Uses getParam function from model.py to get the objects of variable parameters
            q = self.getParam('q')
            dphi = self.getParam('dphi')
            # maxphi is dphi when i = 90
            maxphi = roche.findphi(q.currVal,90.0)
            # dphi cannot be greater than (or within a certain tolerance of) maxphi
            if dphi.currVal > maxphi-tol:
                if verbose:
                    print('Combination of q and dphi is invalid')
                retVal += -np.inf
            
        except:
            # We get here when roche.findphi raises error - usually invalid q
            retVal += -np.inf
            if verbose:
                print('Combination of q and dphi is invalid')
        
        # rdisc 
        try:
            xl1 = roche.xl1(q.currVal) # xl1/a
            maxrdisc = 0.46/xl1 # Maximum size disc can reach before precessing
            # rdisc is unique to each eclipse, so have to use slightly different method to 
            # obtain its object, compared to q and dphi which are shared parameters
            rdiscTemplate = 'rdisc_{0}'
            for iecl in range(self.necl):
                rdisc = self.getParam(rdiscTemplate.format(iecl))
                # rdisc cannot be greater than maxrdisc
                if rdisc.currVal > maxrdisc:
                    retVal += -np.inf
                
        except:
            # We get here when roche.findphi raises error - usually invalid q
            if verbose:
                print('Rdisc and q imply disc does not hit stream')
            retVal += -np.inf
        
        #BS scale
        rwd = self.getParam('rwd')
        minscale = rwd.currVal/3 # Minimum BS scale equal to 1/3 of rwd
        maxscale = rwd.currVal*3 # Maximum BS scale equal to 3x rwd
        scaleTemplate = 'scale_{0}'
        for iecl in range(self.necl):
            scale = self.getParam(scaleTemplate.format(iecl))
            # BS scale must be within allowed range 
            if scale.currVal < minscale or scale.currVal > maxscale:
                retVal += -np.inf
                if verbose:
                    print('BS Scale is not between 1/3 and 3 times WD size')
            
        #BS az
        slope = 80.0
        try:
            # Find position of bright spot where it hits disc
            azTemplate = 'az_{0}'
            for iecl in range(self.necl):
                rdisc = self.getParam(rdiscTemplate.format(iecl))
                rd_a = rdisc.currVal*xl1 # rdisc/a
                az = self.getParam(azTemplate.format(iecl))
                # Does stream miss disc? (rdisc/a < 0.2 or rdisc/a > 0.65 )
                # If yes, Tom's code will fail
                # Calculate position of BS
                x,y,vx,vy = roche.bspot(q.currVal,rd_a)
                # Find tangent to disc at this point
                alpha = np.degrees(np.arctan2(y,x))
                # Alpha is between -90 and 90. If negative, spot lags disc (i.e. alpha > 90)
                if alpha < 0: alpha = 90 - alpha
                tangent = alpha + 90 # Disc tangent
                # Calculate minimum and maximum az values using tangent and slope
                minaz = max(0,tangent-slope)
                maxaz = min(178,tangent+slope)
                # BS az must be within allowed range
                if az.currVal < minaz or az.currVal > maxaz:
                    retVal += -np.inf

        except:
            if verbose:
                print('Stream does not hit disc, or az is outside 80 degree tolerance')
            # We get here when roche.findphi raises error - usually invalid q
            retVal += -np.inf
           
        if complex:
            # BS exponential parameters
            # Total extent of bright spot is scale*(e1/e2)**(1/e2)
            # Limit this to half an inner lagrangian distance
            scaleTemplate = 'scale_{0}'
            exp1Template = 'exp1_{0}'
            exp2Template = 'exp2_{0}'
            for iecl in range(self.necl):
                sc = self.getParam(scaleTemplate.format(iecl))
                e1 = self.getParam(exp1Template.format(iecl))
                e2 = self.getParam(exp2Template.format(iecl))
                if sc.currVal*(e1.currVal/e2.currVal)**(1.0/e2.currVal) > 0.5:
                    retVal += -np.inf
    
        return retVal
Beispiel #7
0
from __future__ import print_function
import matplotlib.pyplot as plt
import numpy as np
from trm import roche
import sys
import lfit
import time
import os

    
phi = np.linspace(-0.15,0.2,1000,endpoint=False)
width = np.mean(np.diff(phi))*np.ones_like(phi)/2.

q = 0.1
inc = 85.9
xl1 = roche.xl1(q) 
dphi = roche.findphi(q,inc)
rwd = 0.01 
rdisc = 0.6
rexp = 0.2
az = 157.0
frac = 0.2
scale = 0.039
exp1 = 2.0
exp2 = 1.0
tilt = 120.0
yaw = 1.0


start = time.clock()
w = lfit.PyWhiteDwarf(rwd,0.4)
Beispiel #8
0
import numpy as np
from trm import roche
import sys
import lfit
import time
import commands
import os

q = 0.1
inc = 86.9


phi = np.linspace(-0.5, 0.5, 1000)
width = np.mean(np.diff(phi)) * np.ones_like(phi) / 2.0

xl1 = roche.xl1(q)
dphi = roche.findphi(q, inc)
rwd = 0.01  # r1_a
w = lfit.PyWhiteDwarf(rwd / xl1, 0.4)

rdisc = 0.6
rexp = 0.2
d = lfit.PyDisc(q, rwd / xl1, rdisc, rexp, 1000)

az = 157.0
frac = 0.2
scale = 0.039
exp1 = 2.0
exp2 = 1.0
tilt = 120.0
yaw = 1.0
def ln_prior_base(pars):

    lnp = 0.0

    #Wd flux
    prior = Prior('uniform',0.001,2)
    lnp += prior.ln_prob(pars[0])

    #Disc flux
    prior = Prior('uniform',0.001,2)
    lnp += prior.ln_prob(pars[1])

    #BS flux
    prior = Prior('uniform',0.001,2)
    lnp += prior.ln_prob(pars[2])

    #Donor flux
    prior = Prior('uniform',0.0,2)
    lnp += prior.ln_prob(pars[3])

    #Mass ratio
    prior = Prior('uniform',0.001,3.5)
    lnp += prior.ln_prob(pars[4])

    #Wd eclipse width, dphi
    tol = 1.0e-6
    try:
        maxphi = roche.findphi(pars[4],90.0) #dphi when i is slightly less than 90
        prior = Prior('uniform',0.001,maxphi-tol)
        lnp += prior.ln_prob(pars[5])
    except:
        # we get here when roche.findphi raises error - usually invalid q
        lnp += -np.inf

    #Disc radius (XL1) 
    try:
        xl1 = roche.xl1(pars[4]) # xl1/a
        prior = Prior('uniform',0.25,0.46/xl1) # maximum size disc can be without precessing
        lnp += prior.ln_prob(pars[6])
    except:
        # we get here when roche.findphi raises error - usually invalid q
        lnp += -np.inf
    
    #Limb darkening
    prior = Prior('gauss',0.39,0.005)
    lnp += prior.ln_prob(pars[7])

    #Wd radius (XL1)
    prior = Prior('uniform',0.0001,0.1)
    lnp += prior.ln_prob(pars[8])

    #BS scale (XL1)
    rwd = pars[8]
    prior = Prior('log_uniform',rwd/3.,rwd*3.)
    lnp += prior.ln_prob(pars[9])

    #BS az
    slop=40.0

    try:
        # find position of bright spot where it hits disc
        # will fail if q invalid
        xl1 = roche.xl1(pars[4]) # xl1/a
        rd_a = pars[6]*xl1

        # Does stream miss disc? (disc/a < 0.2 or > 0.65 )
        # if so, Tom's code will fail
        x,y,vx,vy = roche.bspot(pars[4],rd_a)
            
        # find tangent to disc at this point
        alpha = np.degrees(np.arctan2(y,x))
            
        # alpha is between -90 and 90. if negative spot lags disc ie alpha > 90
        if alpha < 0: alpha = 90-alpha
        tangent = alpha + 90 # disc tangent
    
        prior = Prior('uniform',max(0,tangent-slop),min(178,tangent+slop))
        lnp += prior.ln_prob(pars[10])
    except:
        lnp += -np.inf
        
    #BS isotropic fraction
    prior = Prior('uniform',0.001,0.9)
    lnp += prior.ln_prob(pars[11])
    
    #Disc exponent
    prior = Prior('uniform',0.0001,2.5)
    lnp += prior.ln_prob(pars[12])

    #Phase offset
    prior = Prior('uniform',-0.1,0.1)
    lnp += prior.ln_prob(pars[13])

    if len(pars) > 14:
        #BS exp1
        prior = Prior('uniform',0.01,4.0)
        lnp += prior.ln_prob(pars[14])

        #BS exp2
        prior = Prior('uniform',0.9,3.0)
        lnp += prior.ln_prob(pars[15])

        #BS tilt angle
        prior = Prior('uniform',0.0,165.0)
        lnp += prior.ln_prob(pars[16])

        #BS yaw angle
        prior = Prior('uniform',-90,90.0)
        lnp += prior.ln_prob(pars[17])
    return lnp