Exemplo n.º 1
0
    def test_gen_angles(self):
        """
        Test generation of orientation angles.
        
        We expect long. and periapse to be uniformly distributed and
        inclination to be sinusoidally distributed.

        Test method: chi squares
        """

        pp = PlanetPopulation(**self.spec)

        x = 10000
        I, O, w = pp.gen_angles(x)

        #O & w are expected to be uniform
        for param,param_range in zip([O,w],[pp.Orange,pp.wrange]):
            h = np.histogram(param,100,density=True)
            chi2 = scipy.stats.chisquare(h[0],[1.0/np.diff(param_range.value)[0]]*len(h[0]))
            self.assertGreater(chi2[1], 0.95)

        #I is expected to be sinusoidal
        hI = np.histogram(I.to(u.rad).value,100,density=True)
        Ix = np.diff(hI[1])/2.+hI[1][:-1]
        Ip = np.sin(Ix)/2

        Ichi2 = scipy.stats.chisquare(hI[0],Ip)
        assert(Ichi2[1] > 0.95)
Exemplo n.º 2
0
    def test_gen_angles(self):
        """
        Test generation of orientation angles.
        
        We expect long. and periapse to be uniformly distributed and
        inclination to be sinusoidally distributed.

        Test method: chi squares
        """

        pp = PlanetPopulation(**self.spec)

        x = 100000
        I, O, w = pp.gen_angles(x)

        #O & w are expected to be uniform
        for param, param_range in zip([O, w], [pp.Orange, pp.wrange]):
            h = np.histogram(param, 100, density=True)
            chi2 = scipy.stats.chisquare(
                h[0], [1.0 / np.diff(param_range.value)[0]] * len(h[0]))
            self.assertGreater(chi2[1], 0.95)

        #I is expected to be sinusoidal
        hI = np.histogram(I.to(u.rad).value, 100, density=True)
        Ix = np.diff(hI[1]) / 2. + hI[1][:-1]
        Ip = np.sin(Ix) / 2

        Ichi2 = scipy.stats.chisquare(hI[0], Ip)
        assert (Ichi2[1] > 0.95)
Exemplo n.º 3
0
    def test_gen_plan_params(self):
        """
        Test generation of planet orbital and phyiscal properties.

        We expect eccentricity and albedo to be uniformly distributed
        and sma and radius to be log-uniform

        Test method: chi squares
        """
        pp = PlanetPopulation(**self.spec)

        x = 10000

        a, e, p, Rp = pp.gen_plan_params(x)

        #expect e and p to be uniform
        for param,param_range in zip([e,p],[pp.erange,pp.prange]):
            h = np.histogram(param,100,density=True)
            chi2 = scipy.stats.chisquare(h[0],[1.0/np.diff(param_range)[0]]*len(h[0]))
            assert(chi2[1] > 0.95)

        #expect a and Rp to be log-uniform
        for param,param_range in zip([a.value,Rp.value],[pp.arange.value,pp.Rprange.value]):
            h = np.histogram(param,100,density=True)
            hx = np.diff(h[1])/2.+h[1][:-1]
            hp = 1.0/(hx*np.log(param_range[1]/param_range[0]))
            chi2 = scipy.stats.chisquare(h[0],hp)
            assert(chi2[1] > 0.95)
Exemplo n.º 4
0
    def test_gen_plan_params(self):
        """
        Test generation of planet orbital and phyiscal properties.

        We expect eccentricity and albedo to be uniformly distributed
        and sma and radius to be log-uniform

        Test method: chi squares
        """
        pp = PlanetPopulation(**self.spec)

        x = 10000

        a, e, p, Rp = pp.gen_plan_params(x)

        #expect e and p to be uniform
        for param, param_range in zip([e, p], [pp.erange, pp.prange]):

            h = np.histogram(param, 100, density=True)
            chi2 = scipy.stats.chisquare(
                h[0], [1.0 / np.diff(param_range)[0]] * len(h[0]))

            assert (chi2[1] > 0.95)

        #expect a and Rp to be log-uniform
        for param, param_range in zip([a.value, Rp.value],
                                      [pp.arange.value, pp.Rprange.value]):

            h = np.histogram(param, 100, density=True)
            hx = np.diff(h[1]) / 2. + h[1][:-1]
            hp = 1.0 / (hx * np.log(param_range[1] / param_range[0]))
            chi2 = scipy.stats.chisquare(h[0], hp)
            assert (chi2[1] > 0.95)
Exemplo n.º 5
0
 def __init__(self, eta=0.1, **specs):
     
     specs['eta'] = eta
     specs['arange'] = [0.95, 1.67]
     specs['erange'] = [0,0]
     specs['prange'] = [0.2,0.2]
     specs['Rprange'] = [0.61905858602731,1.4]
     specs['Mprange'] = [1,1]
     specs['scaleOrbits'] = True
     PlanetPopulation.__init__(self, **specs)
Exemplo n.º 6
0
 def __init__(self, eta=0.1, **specs):
     
     specs['eta'] = eta
     specs['arange'] = [0.7, 1.5]
     specs['erange'] = [0,0]
     specs['Rprange'] = [1,1]
     specs['Mprange'] = [1,1]
     specs['prange'] = [0.367,0.367]
     specs['scaleOrbits'] = True
     PlanetPopulation.__init__(self, **specs)
Exemplo n.º 7
0
 def __init__(self, eta=0.1, **specs):
     
     specs['eta'] = eta
     specs['arange'] = [0.7, 1.5]
     specs['erange'] = [0,0]
     specs['prange'] = [0.367,0.367]
     specs['Rprange'] = [1,1]
     specs['Mprange'] = [1,1]
     specs['scaleOrbits'] = True
     PlanetPopulation.__init__(self, **specs)
Exemplo n.º 8
0
 def __init__(self, eta=0.1, erange=[0.,0.9], constrainOrbits=True, **specs):
     
     specs['eta'] = eta
     specs['arange'] = [0.7, 1.5]
     specs['erange'] = erange
     specs['Rprange'] = [1,1]
     specs['Mprange'] = [1,1]
     specs['prange'] = [0.367,0.367]
     specs['scaleOrbits'] = True
     specs['constrainOrbits'] = constrainOrbits
     PlanetPopulation.__init__(self, **specs)
Exemplo n.º 9
0
    def __init__(self,
                 smaknee=30,
                 esigma=0.175 / np.sqrt(np.pi / 2.),
                 prange=[0.083, 0.882],
                 Rprange=[1, 22.6],
                 **specs):

        specs['prange'] = prange
        specs['Rprange'] = Rprange
        PlanetPopulation.__init__(self, **specs)

        # calculate norm for sma distribution with decay point (knee)
        self.smaknee = float(smaknee)
        ar = self.arange.to('AU').value
        # sma distribution without normalization
        tmp_dist_sma = lambda x, s0=self.smaknee: x**(-0.62) * np.exp(-(x / s0)
                                                                      **2)
        self.smanorm = integrate.quad(tmp_dist_sma, ar[0], ar[1])[0]

        # calculate norm for eccentricity Rayleigh distribution
        self.esigma = float(esigma)
        er = self.erange
        self.enorm = np.exp(-er[0]**2/(2.*self.esigma**2)) \
                - np.exp(-er[1]**2/(2.*self.esigma**2))

        # define Kepler radius distribution
        Rs = np.array([1, 1.4, 2.0, 2.8, 4.0, 5.7, 8.0, 11.3, 16,
                       22.6])  #Earth Radii
        Rvals85 = np.array([
            0.1555, 0.1671, 0.1739, 0.0609, 0.0187, 0.0071, 0.0102, 0.0049,
            0.0014
        ])
        #sma of 85 days
        a85 = ((85. * u.day / 2. / np.pi)**2 * u.solMass * const.G)**(1. / 3.)
        # sma of 0.8 days (lower limit of Fressin et al 2012)
        a08 = ((0.8 * u.day / 2. / np.pi)**2 * u.solMass * const.G)**(1. / 3.)
        fac1 = integrate.quad(tmp_dist_sma,
                              a08.to('AU').value,
                              a85.to('AU').value)[0]
        Rvals = integrate.quad(tmp_dist_sma, ar[0],
                               ar[1])[0] * (Rvals85 / fac1)
        Rvals[5:] *= 2.5  #account for longer orbital baseline data
        self.Rs = Rs
        self.Rvals = Rvals
        self.eta = np.sum(Rvals)

        # populate outspec with attributes specific to KeplerLike1
        self._outspec['smaknee'] = self.smaknee
        self._outspec['esigma'] = self.esigma
        self._outspec['eta'] = self.eta

        self.dist_albedo_built = None
Exemplo n.º 10
0
 def __init__(self, eta=0.1, erange=[0.,0.9], constrainOrbits=True, **specs):
     
     specs['erange'] = erange
     specs['constrainOrbits'] = constrainOrbits
     
     # specs being modified in EarthTwinHabZone1
     specs['eta'] = eta
     specs['arange'] = [0.7, 1.5]
     specs['Rprange'] = [1,1]
     specs['Mprange'] = [1,1]
     specs['prange'] = [0.367,0.367]
     specs['scaleOrbits'] = True
     
     PlanetPopulation.__init__(self, **specs)
Exemplo n.º 11
0
    def __init__(self, smaknee=30, esigma=0.25, **specs):

        specs['prange'] = [0.083, 0.882]
        specs['Rprange'] = [1, 22.6]
        PlanetPopulation.__init__(self, **specs)

        assert (smaknee >= self.arange[0].to('AU').value) and \
               (smaknee <= self.arange[1].to('AU').value), \
               "sma knee value must be in sma range."

        #define sma distribution
        self.smaknee = float(smaknee)
        self.smadist1 = lambda x, s0=self.smaknee: x**(-0.62) * np.exp(-(
            (x / s0)**2))
        self.smanorm = integrate.quad(self.smadist1,
                                      self.arange.min().to('AU').value,
                                      self.arange.max().to('AU').value)[0]
        self.smadist = lambda x, s0=self.smaknee: (x**(-0.62) * np.exp(-(
            (x / s0)**2))) / self.smanorm

        #define Rayleigh eccentricity distribution
        self.esigma = float(esigma)
        self.edist1 = lambda x, sigma=self.esigma: (x / sigma**2) * np.exp(
            -x**2 / (2. * sigma**2))
        self.enorm = integrate.quad(self.edist1, self.erange.min(),
                                    self.erange.max())[0]
        self.edist = lambda x, sigma=self.esigma: (
            (x / sigma**2) * np.exp(-x**2 / (2.0 * sigma**2))) / self.enorm

        #define Kepler radius distribution
        Rs = np.array([1, 1.4, 2.0, 2.8, 4.0, 5.7, 8.0, 11.3, 16,
                       22.6])  #Earth Radii
        Rvals85 = np.array([
            0.1555, 0.1671, 0.1739, 0.0609, 0.0187, 0.0071, 0.0102, 0.0049,
            0.0014
        ])
        a85 = (((85 * u.day / 2 / np.pi)**2 * const.M_sun *
                const.G)**(1. / 3)).to('AU')  #sma of 85 days
        fac1 = integrate.quad(self.smadist, 0, a85.value)[0]
        Rvals = integrate.quad(
            self.smadist, 0,
            self.arange[1].to('AU').value)[0] * (Rvals85 / fac1)
        Rvals[5:] *= 2.5  #account for longer orbital baseline data

        self.Rs = Rs
        self.Rvals = Rvals
        self.eta = np.sum(Rvals)

        self.dist_albedo_built = False
        self.dist_radius_built = False
Exemplo n.º 12
0
    def __init__(self,
                 eta=0.1,
                 erange=[0., 0.9],
                 constrainOrbits=True,
                 **specs):

        specs['eta'] = eta
        specs['arange'] = [0.7, 1.5]
        specs['erange'] = erange
        specs['Rprange'] = [1, 1]
        specs['Mprange'] = [1, 1]
        specs['prange'] = [0.367, 0.367]
        specs['scaleOrbits'] = True
        specs['constrainOrbits'] = constrainOrbits
        PlanetPopulation.__init__(self, **specs)
Exemplo n.º 13
0
    def __init__(self, eta=1, arange=[0.7*np.sqrt(0.83),1.5*np.sqrt(0.83)], erange=[0.,0.35], constrainOrbits=False, **specs):
        #eta is probability of planet occurance in a system. I set this to 1
        specs['erange'] = erange
        specs['constrainOrbits'] = constrainOrbits
        pE = 0.26 # From Brown 2005 #0.33 listed in paper but q=0.26 is listed in the paper in the figure
        # specs being modified in JupiterTwin
        specs['eta'] = eta
        specs['arange'] = arange #*u.AU
        specs['Rprange'] = [1.,1.] #*u.earthRad
        #specs['Mprange'] = [1*MpEtoJ,1*MpEtoJ]
        specs['prange'] = [pE,pE]
        specs['scaleOrbits'] = True

        self.pE = pE

        PlanetPopulation.__init__(self, **specs)
Exemplo n.º 14
0
    def __init__(self,
                 eta=0.1,
                 erange=[0., 0.9],
                 constrainOrbits=True,
                 **specs):

        specs['erange'] = erange
        specs['constrainOrbits'] = constrainOrbits

        # specs being modified in EarthTwinHabZone1
        specs['eta'] = eta
        specs['arange'] = [0.7, 1.5]
        specs['Rprange'] = [1, 1]
        specs['Mprange'] = [1, 1]
        specs['prange'] = [0.367, 0.367]
        specs['scaleOrbits'] = True

        PlanetPopulation.__init__(self, **specs)
Exemplo n.º 15
0
    def __init__(self, eta=1, erange=[0.,0.048], constrainOrbits=True, **specs):
        #eta is probability of planet occurance in a system. I set this to 1
        specs['erange'] = erange
        specs['constrainOrbits'] = constrainOrbits
        aEtoJ = 5.204
        RpEtoJ = 11.209
        MpEtoJ = 317.83
        pJ = 0.538# 0.538 from nssdc.gsfc.nasa.gov
        # specs being modified in JupiterTwin
        specs['eta'] = eta
        specs['arange'] = [1*aEtoJ,1*aEtoJ]#0.7*aEtoJ, 1.5*aEtoJ]
        specs['Rprange'] = [1*RpEtoJ,1*RpEtoJ]
        specs['Mprange'] = [1*MpEtoJ,1*MpEtoJ]
        specs['prange'] = [pJ,pJ]
        specs['scaleOrbits'] = True

        self.RpEtoJ = RpEtoJ
        self.pJ = pJ

        PlanetPopulation.__init__(self, **specs)
Exemplo n.º 16
0
 def __init__(self, smaknee=30, esigma=0.175/np.sqrt(np.pi/2.), 
         prange=[0.083, 0.882], Rprange=[1, 22.6], **specs):
     
     specs['prange'] = prange
     specs['Rprange'] = Rprange
     PlanetPopulation.__init__(self, **specs)
     
     # calculate norm for sma distribution with decay point (knee)
     self.smaknee = float(smaknee)
     ar = self.arange.to('AU').value
     # sma distribution without normalization
     tmp_dist_sma = lambda x,s0=self.smaknee: x**(-0.62)*np.exp(-(x/s0)**2)
     self.smanorm = integrate.quad(tmp_dist_sma, ar[0], ar[1])[0]
     
     # calculate norm for eccentricity Rayleigh distribution 
     self.esigma = float(esigma)
     er = self.erange
     self.enorm = np.exp(-er[0]**2/(2.*self.esigma**2)) \
             - np.exp(-er[1]**2/(2.*self.esigma**2))
     
     # define Kepler radius distribution
     Rs = np.array([1,1.4,2.0,2.8,4.0,5.7,8.0,11.3,16,22.6]) #Earth Radii
     Rvals85 = np.array([0.1555,0.1671,0.1739,0.0609,0.0187,0.0071,0.0102,0.0049,0.0014])
     #sma of 85 days
     a85 = ((85.*u.day/2./np.pi)**2*u.solMass*const.G)**(1./3.)
     # sma of 0.8 days (lower limit of Fressin et al 2012)
     a08 = ((0.8*u.day/2./np.pi)**2*u.solMass*const.G)**(1./3.) 
     fac1 = integrate.quad(tmp_dist_sma, a08.to('AU').value, a85.to('AU').value)[0]
     Rvals = integrate.quad(tmp_dist_sma, ar[0], ar[1])[0]*(Rvals85/fac1)
     Rvals[5:] *= 2.5 #account for longer orbital baseline data
     self.Rs = Rs
     self.Rvals = Rvals
     self.eta = np.sum(Rvals)
     
     # populate outspec with attributes specific to KeplerLike1
     self._outspec['smaknee'] = self.smaknee
     self._outspec['esigma'] = self.esigma
     self._outspec['eta'] = self.eta
     
     self.dist_albedo_built = None
Exemplo n.º 17
0
    def __init__(self,
                 eta=1,
                 erange=[0., 0.048],
                 constrainOrbits=True,
                 **specs):
        #eta is probability of planet occurance in a system. I set this to 1
        specs['erange'] = erange
        specs['constrainOrbits'] = constrainOrbits
        aEtoJ = 5.204
        RpEtoJ = 11.209
        MpEtoJ = 317.83
        pJ = 0.538  # 0.538 from nssdc.gsfc.nasa.gov
        # specs being modified in JupiterTwin
        specs['eta'] = eta
        specs['arange'] = [1 * aEtoJ, 1 * aEtoJ]  #0.7*aEtoJ, 1.5*aEtoJ]
        specs['Rprange'] = [1 * RpEtoJ, 1 * RpEtoJ]
        specs['Mprange'] = [1 * MpEtoJ, 1 * MpEtoJ]
        specs['prange'] = [pJ, pJ]
        specs['scaleOrbits'] = True

        self.RpEtoJ = RpEtoJ
        self.pJ = pJ

        PlanetPopulation.__init__(self, **specs)
Exemplo n.º 18
0
 def __init__(self, smaknee=30, esigma=0.25, **specs):
     
     specs['prange'] = [0.083,0.882]
     specs['Rprange'] = [1,22.6]
     PlanetPopulation.__init__(self, **specs)
     
     assert (smaknee >= self.arange[0].to('AU').value) and \
            (smaknee <= self.arange[1].to('AU').value), \
            "sma knee value must be in sma range."
     
     #define sma distribution
     self.smaknee = float(smaknee)
     self.smadist1 = lambda x,s0=self.smaknee: x**(-0.62)*np.exp(-((x/s0)**2))
     self.smanorm = integrate.quad(self.smadist1, self.arange.min().to('AU').value, self.arange.max().to('AU').value)[0]        
     self.smadist = lambda x,s0=self.smaknee: (x**(-0.62)*np.exp(-((x/s0)**2)))/self.smanorm
     
     #define Rayleigh eccentricity distribution
     self.esigma = float(esigma)
     self.edist1 = lambda x,sigma=self.esigma: (x/sigma**2)*np.exp(-x**2/(2.*sigma**2))
     self.enorm = integrate.quad(self.edist1, self.erange.min(), self.erange.max())[0]
     self.edist = lambda x,sigma=self.esigma: ((x/sigma**2)*np.exp(-x**2/(2.0*sigma**2)))/self.enorm
     
     #define Kepler radius distribution
     Rs = np.array([1,1.4,2.0,2.8,4.0,5.7,8.0,11.3,16,22.6]) #Earth Radii
     Rvals85 = np.array([0.1555, 0.1671, 0.1739, 0.0609, 0.0187, 0.0071, 0.0102, 0.0049, 0.0014])
     a85 = (((85*u.day/2/np.pi)**2*const.M_sun*const.G)**(1./3)).to('AU') #sma of 85 days
     fac1 = integrate.quad(self.smadist,0,a85.value)[0]
     Rvals = integrate.quad(self.smadist,0,self.arange[1].to('AU').value)[0]*(Rvals85/fac1)
     Rvals[5:] *= 2.5 #account for longer orbital baseline data
     
     self.Rs = Rs
     self.Rvals = Rvals
     self.eta = np.sum(Rvals)
     
     self.dist_albedo_built = False
     self.dist_radius_built = False
Exemplo n.º 19
0
    def test_checkranges(self):
        """
        Test that check ranges is doing what it should do

        """

        pp = PlanetPopulation(arange=[10, 1], **self.spec)
        self.assertTrue(pp.arange[0].value == 1)
        self.assertTrue(pp.arange[1].value == 10)

        with self.assertRaises(AssertionError):
            pp = PlanetPopulation(prange=[-1, 1], **self.spec)

        with self.assertRaises(AssertionError):
            pp = PlanetPopulation(erange=[-1, 1], **self.spec)

        with self.assertRaises(AssertionError):
            pp = PlanetPopulation(arange=[0, 1], **self.spec)

        with self.assertRaises(AssertionError):
            pp = PlanetPopulation(Rprange=[0, 1], **self.spec)

        with self.assertRaises(AssertionError):
            pp = PlanetPopulation(Mprange=[0, 1], **self.spec)
Exemplo n.º 20
0
    def __init__(self, starMass=1., occDataPath=None, esigma=0.175/np.sqrt(np.pi/2.), **specs):
        PlanetPopulation.__init__(self, **specs)
        self.starMass = starMass * u.M_sun
        self.occDataPath = occDataPath
        self.esigma = float(esigma)
        er = self.erange
        self.enorm = np.exp(-er[0]**2/(2.*self.esigma**2)) \
                     - np.exp(-er[1]**2/(2.*self.esigma**2))
        self.dist_sma_built = None
        self.dist_radius_built = None
        self.dist_albedo_built = None
        # check occDataPath
        if self.occDataPath is None:
            classpath = os.path.split(inspect.getfile(self.__class__))[0]
            filename = 'NominalOcc_Radius.csv'
            self.occDataPath = os.path.join(classpath, filename)

        assert os.path.exists(self.occDataPath), "occurrence rate table not found at {}".format(self.occDataPath)

        # load data
        occData = dict(ascii.read(self.occDataPath))
        self.aData = "a_min" in occData
        self.RData = "R_min" in occData
        # load occurrence rates
        eta2D = []
        for tmp in occData['Occ']:
            eta2D.append(tmp)
        eta2D = np.array(eta2D)
        # load semi-major axis or period
        if self.aData:
            amin = []
            for tmp in occData['a_min']:
                amin.append(tmp)
            amin = np.array(amin)
            amax = []
            for tmp in occData['a_max']:
                amax.append(tmp)
            amax = np.array(amax)
            self.smas = np.hstack((np.unique(amin),np.unique(amax)[-1]))
            len1 = len(self.smas) - 1
            self.arange = np.array([self.smas[0],self.smas[-1]])*u.AU
        else:
            Pmin = []
            for tmp in occData['P_min']:
                Pmin.append(tmp)
            Pmin = np.array(Pmin)
            Pmax = []
            for tmp in occData['P_max']:
                Pmax.append(tmp)
            Pmax = np.array(Pmax)
            self.Ps = np.hstack((np.unique(Pmin),np.unique(Pmax)[-1]))
            len1 = len(self.Ps) -1
            self.arange = ((const.G*self.starMass*(np.array([self.Ps[0],self.Ps[-1]])*u.day)**2/4./np.pi**2)**(1./3.)).to('AU')
        # load radius or mass
        if self.RData:
            Rmin = []
            for tmp in occData['R_min']:
                Rmin.append(tmp)
            Rmin = np.array(Rmin)
            Rmax = []
            for tmp in occData['R_max']:
                Rmax.append(tmp)
            Rmax = np.array(Rmax)
            self.Rs = np.hstack((np.unique(Rmin), np.unique(Rmax)[-1]))
            len2 = len(self.Rs) - 1
            self.Rprange = np.array([self.Rs[0],self.Rs[-1]])*u.R_earth
            # maximum from data sheets provided
            self.Mprange = np.array([0.08, 4768.])*u.earthMass
        else:
            Mmin = []
            for tmp in occData['M_min']:
                Mmin.append(tmp)
            Mmin = np.array(Mmin)
            Mmax = []
            for tmp in occData['M_max']:
                Mmax.append(tmp)
            Mmax = np.array(Mmax)
            self.Ms = np.hstack((np.unique(Mmin), np.unique(Mmax)[-1]))
            len2 = len(self.Ms) - 1
            self.Mprange = np.array([self.Ms[0],self.Ms[-1]])*u.M_earth
            self.Rprange = np.array([1.008*0.08**(0.279), 17.739*(0.225*u.M_jup.to('earthMass'))**(-0.044)])*u.earthRad
        if self.constrainOrbits:
            self.rrange = self.arange
        else:
            self.rrange = np.array([self.arange[0].to('AU').value*(1.0-self.erange[1]),
                                    self.arange[1].to('AU').value*(1.0+self.erange[1])])*u.AU
        # reshape eta2D array
        self.eta2D = eta2D.reshape((len1,len2)).T
        self.eta = self.eta2D.sum()
Exemplo n.º 21
0
    def __init__(self,
                 starMass=1.,
                 occDataPath=None,
                 esigma=0.175 / np.sqrt(np.pi / 2.),
                 **specs):
        PlanetPopulation.__init__(self, **specs)
        self.starMass = starMass * u.M_sun
        self.occDataPath = occDataPath
        self.esigma = float(esigma)
        er = self.erange
        self.enorm = np.exp(-er[0]**2 / (2. * self.esigma**2)) - np.exp(
            -er[1]**2 / (2. * self.esigma**2))
        self.dist_sma_built = None
        self.dist_radius_built = None
        self.dist_albedo_built = None
        # check occDataPath
        if self.occDataPath is None:
            classpath = os.path.split(inspect.getfile(self.__class__))[0]
            filename = 'NominalOcc_Radius.csv'
            self.occDataPath = os.path.join(classpath, filename)

        assert os.path.exists(
            self.occDataPath), "occurrence rate table not found at {}".format(
                self.occDataPath)

        # load data
        occData = dict(ascii.read(self.occDataPath))
        self.aData = "a_min" in occData
        self.RData = "R_min" in occData
        # load occurrence rates
        eta2D = []
        for tmp in occData['Occ']:
            eta2D.append(tmp)
        eta2D = np.array(eta2D)
        # load semi-major axis or period
        if self.aData:
            amin = []
            for tmp in occData['a_min']:
                amin.append(tmp)
            amin = np.array(amin)
            amax = []
            for tmp in occData['a_max']:
                amax.append(tmp)
            amax = np.array(amax)
            self.smas = np.hstack((np.unique(amin), np.unique(amax)[-1]))
            len1 = len(self.smas) - 1
            self.arange = np.array([self.smas[0], self.smas[-1]]) * u.AU
        else:
            Pmin = []
            for tmp in occData['P_min']:
                Pmin.append(tmp)
            Pmin = np.array(Pmin)
            Pmax = []
            for tmp in occData['P_max']:
                Pmax.append(tmp)
            Pmax = np.array(Pmax)
            self.Ps = np.hstack((np.unique(Pmin), np.unique(Pmax)[-1]))
            len1 = len(self.Ps) - 1
            self.arange = ((const.G * self.starMass *
                            (np.array([self.Ps[0], self.Ps[-1]]) * u.day)**2 /
                            4. / np.pi**2)**(1. / 3.)).to('AU')
        # load radius or mass
        if self.RData:
            Rmin = []
            for tmp in occData['R_min']:
                Rmin.append(tmp)
            Rmin = np.array(Rmin)
            Rmax = []
            for tmp in occData['R_max']:
                Rmax.append(tmp)
            Rmax = np.array(Rmax)
            self.Rs = np.hstack((np.unique(Rmin), np.unique(Rmax)[-1]))
            len2 = len(self.Rs) - 1
            self.Rprange = np.array([self.Rs[0], self.Rs[-1]]) * u.R_earth
            # maximum from data sheets provided
            self.Mprange = np.array([0.08, 4768.]) * u.earthMass
        else:
            Mmin = []
            for tmp in occData['M_min']:
                Mmin.append(tmp)
            Mmin = np.array(Mmin)
            Mmax = []
            for tmp in occData['M_max']:
                Mmax.append(tmp)
            Mmax = np.array(Mmax)
            self.Ms = np.hstack((np.unique(Mmin), np.unique(Mmax)[-1]))
            len2 = len(self.Ms) - 1
            self.Mprange = np.array([self.Ms[0], self.Ms[-1]]) * u.M_earth
            self.Rprange = np.array([
                1.008 * 0.08**(0.279), 17.739 *
                (0.225 * u.M_jup.to('earthMass'))**(-0.044)
            ]) * u.earthRad
        if self.constrainOrbits:
            self.rrange = self.arange
        else:
            self.rrange = np.array([
                self.arange[0].to('AU').value *
                (1.0 - self.erange[1]), self.arange[1].to('AU').value *
                (1.0 + self.erange[1])
            ]) * u.AU
        # reshape eta2D array
        self.eta2D = eta2D.reshape((len1, len2))
        self.eta = self.eta2D.sum()