Esempio n. 1
0
def Sig_INT_rho(R0, Sig, gp):
    J = Jpar(R0, Sig, gp)
    sm0 = 0.02
    splpar_J = splrep(R0[:-gp.nexp], np.log(J), s=sm0) # smoothing determined for Hernquist profile. can go below to 0.01 for very smooth profiles
    rho = -1./np.pi/R0[:-gp.nexp]*J*splev(R0[:-gp.nexp], splpar_J, der=1)
    sm = sm0*1.
    while(min(rho)<0):
        print('min(rho)<0, rho = ', rho)
        sm *= 2
        splpar_J = splrep(R0[:-gp.nexp], np.log(J), s=sm)
        rho = -1./np.pi/R0[:-gp.nexp]*J*splev(R0[:-gp.nexp], splpar_J, der=1)
        if(sm>1):
            print('very irregular profile')
            sel = (rho >= 0.0)
            finerho = rho[sel]
            firstfinerho = finerho[0]
            for k in range(len(rho)):
                if rho[k] <0:
                    rho[k] = firstfinerho
        #    raise Exception('Very irregular profile')

    gh.checkpositive(rho)

    rhoright = gh.expolpowerlaw(R0[:-gp.nexp], rho, R0[-3:], -3.001)
    rho = np.hstack([rho, rhoright])
    return rho
Esempio n. 2
0
def rho(z0, rhopar, pop, gp):
    vec = rhopar
    rho_at_rhalf = vec[0]
    vec = vec[1:]
    # get spline representation on gp.xepol, where rhopar are defined on
    spline_n = nr(gp.xepol, vec, pop, gp)

    # and apply it to these radii, which may be anything in between
    zs =  np.log(z0/gp.Xscale[pop]) # have to integrate in d log(r)
    logrright = []; logrleft = []
    if np.rank(zs) == 0:
        if zs>0:
            logrright.append(zs)
        else:
            logrleft.append(zs)
    else:
        logrright = zs[(zs>=0.)]
        logrleft  = zs[(zs<0.)]
        logrleft  = logrleft[::-1] # inverse order

    # integrate to left and right of halflight radius
    logrhoright = []
    for i in np.arange(0, len(logrright)):
        logrhoright.append(np.log(rho_at_rhalf) + \
                           splint(0., logrright[i], spline_n))
                           # integration along dlog(r) instead of dr

    logrholeft = []
    for i in np.arange(0, len(logrleft)):
        logrholeft.append(np.log(rho_at_rhalf) + \
                          splint(0., logrleft[i], spline_n))

    tmp = np.exp(np.hstack([logrholeft[::-1], logrhoright])) # still defined on log(r)
    gh.checkpositive(tmp, 'rho()')
    return tmp
Esempio n. 3
0
def Sig_INT_rho(R0, Sig, gp):
    J = Jpar(R0, Sig, gp)
    sm0 = 0.02
    splpar_J = splrep(
        R0[:-gp.nexp], np.log(J), s=sm0
    )  # smoothing determined for Hernquist profile. can go below to 0.01 for very smooth profiles
    rho = -1. / np.pi / R0[:-gp.nexp] * J * splev(
        R0[:-gp.nexp], splpar_J, der=1)
    sm = sm0 * 1.
    while (min(rho) < 0):
        print('min(rho)<0, rho = ', rho)
        sm *= 2
        splpar_J = splrep(R0[:-gp.nexp], np.log(J), s=sm)
        rho = -1. / np.pi / R0[:-gp.nexp] * J * splev(
            R0[:-gp.nexp], splpar_J, der=1)
        if (sm > 1):
            print('very irregular profile')
            sel = (rho >= 0.0)
            finerho = rho[sel]
            firstfinerho = finerho[0]
            for k in range(len(rho)):
                if rho[k] < 0:
                    rho[k] = firstfinerho
        #    raise Exception('Very irregular profile')

    gh.checkpositive(rho)

    rhoright = gh.expolpowerlaw(R0[:-gp.nexp], rho, R0[-3:], -3.001)
    rho = np.hstack([rho, rhoright])
    return rho
Esempio n. 4
0
def calculate_rho(r, M):
    r0 = np.hstack([0,r])                         # [lunit]
    M0 = np.hstack([0,M])
    deltaM   = M0[1:]-M0[:-1]                     # [Munit]
    gh.checkpositive(deltaM,  'unphysical negative mass increment encountered')
    deltavol = 4./3.*np.pi*(r0[1:]**3-r0[:-1]**3) # [lunit^3]
    rho     = deltaM / deltavol                  # [Munit/lunit^3]
    gh.checkpositive(rho, 'rho in calculate_rho')
    return rho                                   # [Munit/lunit^3]
Esempio n. 5
0
def calculate_surfdens(r, M):
    r0 = np.hstack([0,r])                         # [lunit]
    M0 = np.hstack([0,M])                         # [Munit]
    deltaM = M0[1:]-M0[:-1]                       # [Munit]
    gh.checkpositive(deltaM, 'unphysical negative mass increment encountered')
    deltavol = np.pi*(r0[1:]**2 - r0[:-1]**2)        # [lunit^2]
    Sig = deltaM/deltavol                           # [Munit/lunit^2]
    gh.checkpositive(Sig, 'Sig in calculate_surfdens')
    return Sig                                      # [Munit/lunit^2]
Esempio n. 6
0
def calculate_rho(r, M):
    r0 = np.hstack([0, r])  # [lunit]
    M0 = np.hstack([0, M])
    deltaM = M0[1:] - M0[:-1]  # [Munit]
    gh.checkpositive(deltaM, 'unphysical negative mass increment encountered')
    deltavol = 4. / 3. * np.pi * (r0[1:]**3 - r0[:-1]**3)  # [lunit^3]
    rho = deltaM / deltavol  # [Munit/lunit^3]
    gh.checkpositive(rho, 'rho in calculate_rho')
    return rho  # [Munit/lunit^3]
Esempio n. 7
0
def calculate_surfdens(r, M):
    r0 = np.hstack([0, r])  # [lunit]
    M0 = np.hstack([0, M])  # [Munit]
    deltaM = M0[1:] - M0[:-1]  # [Munit]
    gh.checkpositive(deltaM, 'unphysical negative mass increment encountered')
    deltavol = np.pi * (r0[1:]**2 - r0[:-1]**2)  # [lunit^2]
    Sig = deltaM / deltavol  # [Munit/lunit^2]
    gh.checkpositive(Sig, 'Sig in calculate_surfdens')
    return Sig  # [Munit/lunit^2]
Esempio n. 8
0
def nu_param_INT_Sig_disc(z0, nupar, pop, gp):
    # use splines on variable transformed integral
    # \Sigma(R) = \int_{r=0}^{R} \rho(r) dr
    z0nu = z0

    nunu = phys.nu_decrease(z0nu, nupar, gp)
    Sig = np.zeros(len(z0nu))
    for i in range(len(z0nu)):
        Sig[i] = gh.quadinflog(z0nu, nunu, z0nu[0], z0nu[i])

    gh.checkpositive(Sig, 'Sig in nu_param_INT_Sig_disc')
    return Sig
Esempio n. 9
0
def nu_param_INT_Sig_disc(z0, nupar, pop, gp):
    # use splines on variable transformed integral
    # \Sigma(R) = \int_{r=0}^{R} \rho(r) dr
    z0nu = z0

    nunu = phys.nu_decrease(z0nu, nupar, gp)
    Sig = np.zeros(len(z0nu))
    for i in range(len(z0nu)):
        Sig[i] = gh.quadinflog(z0nu, nunu, z0nu[0], z0nu[i])

    gh.checkpositive(Sig, 'Sig in nu_param_INT_Sig_disc')
    return Sig
Esempio n. 10
0
def kappa(r0fine, Mrfine, nufine, sigr2nu, intbetasfine, gp):
    # for the following: enabled calculation of kappa

    # kappa_r^4
    kapr4nu = np.ones(len(r0fine)-gp.nexp)
    xint  = r0fine                  # [pc]
    yint  = gu.G1__pcMsun_1km2s_2 * Mrfine/r0fine**2  # [1/pc (km/s)^2]
    yint *= nufine                  # [Munit/pc^4 (km/s)^2]
    yint *= sigr2nu               # [Munit/pc^4 (km/s)^4
    yint *= np.exp(intbetasfine)          # [Munit/pc^4 (km/s)^4]
    gh.checkpositive(yint, 'yint in kappa_r^4')
    yscale = 10.**(1.-min(np.log10(yint[1:])))
    yint *= yscale
    # power-law extrapolation to infinity
    C = max(0., gh.quadinflog(xint[-3:], yint[-3:], r0fine[-1], gp.rinfty*r0fine[-1]))

    splpar_nu = splrep(xint, yint, k=3) # interpolation in real space
    for k in range(len(r0fine)-gp.nexp):
        # integrate from minimal radius to infinity
        kapr4nu[k] = 3.*(np.exp(-intbetasfine[k])/nufine[k]) * \
            (splint(r0fine[k], r0fine[-1], splpar_nu) + C) # [(km/s)^4]

    kapr4nu /= yscale
    gh.checkpositive(kapr4nu, 'kapr4nu in kappa_r^4')

    splpar_kap = splrep(r0fine[:-gp.nexp], np.log(kapr4nu), k=3)
    kapr4ext = np.exp(splev(r0ext, splpar_kap))
    kapr4nu = np.hstack([kapr4nu, kapr4ext])
    gh.checkpositive(kapr4nu, 'kapr4nu in extended kappa_r^4')

    dbetafinedr = splev(r0fine, splrep(r0fine, betafine), der=1)
    gh.checknan(dbetafinedr, 'dbetafinedr in kappa_r^4')

    # kappa^4_los*surfdensity
    kapl4s = np.zeros(len(r0fine)-gp.nexp)
    for k in range(len(r0fine)-gp.nexp):
        xnew = np.sqrt(r0fine[k:]**2-r0fine[k]**2)      # [pc]
        ynew = g(r0fine[k:], r0fine[k], betafine[k:], dbetafinedr[k:]) # [1]
        ynew *= nufine[k:] * kapr4nu[k:]
        C = max(0., gh.quadinflog(xnew[-3:], ynew[-3:], xnew[-1], gp.rinfty*xnew[-1]))
        splpar_nu = splrep(xnew,ynew) # not s=0.1, this sometimes gives negative entries after int
        kapl4s[k] = 2. * (splint(0., xnew[-1], splpar_nu) + C)
        #kapl4s[k] /= yscale
        # LOG('ynew = ',ynew,', kapl4s =', kapl4s[k])

    gh.checkpositive(kapl4s, 'kapl4s in kappa_r^4')

    # project kappa4_los as well
    # only use middle values to approximate, without errors in center and far
    kapl4s_out = np.exp(splev(r0, splrep(r0fine[4:-gp.nexp], kapl4s[4:], k=3))) # s=0.
    gh.checkpositive(kapl4s_out, 'kapl4s_out in kappa_r^4')
    return sigl2s_out, kapl4s_out
Esempio n. 11
0
def rho_param_INT_Sig_disc(z0, rhopar, pop, gp):
    # use splines on variable transformed integral
    # \Sigma(R) = \int_{r=0}^{R} \rho(r) dr
    xmin = z0[0]/30. # tweaked. z0[0]/1e4 gives error in quad()
    z0left = np.array([xmin, z0[0]*0.25, z0[0]*0.50, z0[0]*0.75])
    z0nu = np.hstack([z0left, z0])

    rhonu = phys.rho(z0nu, rhopar, pop, gp) # rho takes rho(rhalf) and n(r) parameters
    Sig = np.zeros(len(z0nu)-gp.nexp)
    for i in range(len(z0nu)-gp.nexp):
        Sig[i] = gh.quadinflog(z0nu, rhonu, xmin, z0nu[i])

    gh.checkpositive(Sig, 'Sig in rho_param_INT_Sig_disc')
    return Sig[len(z0left):] # @z0 (z0nu without z0left, and without 3 extension bins)
Esempio n. 12
0
def rho_param_INT_Sig_disc(z0, rhopar, pop, gp):
    # use splines on variable transformed integral
    # \Sigma(R) = \int_{r=0}^{R} \rho(r) dr
    xmin = z0[0] / 30.  # tweaked. z0[0]/1e4 gives error in quad()
    z0left = np.array([xmin, z0[0] * 0.25, z0[0] * 0.50, z0[0] * 0.75])
    z0nu = np.hstack([z0left, z0])

    rhonu = phys.rho(z0nu, rhopar, pop,
                     gp)  # rho takes rho(rhalf) and n(r) parameters
    Sig = np.zeros(len(z0nu) - gp.nexp)
    for i in range(len(z0nu) - gp.nexp):
        Sig[i] = gh.quadinflog(z0nu, rhonu, xmin, z0nu[i])

    gh.checkpositive(Sig, 'Sig in rho_param_INT_Sig_disc')
    return Sig[len(
        z0left):]  # @z0 (z0nu without z0left, and without 3 extension bins)
Esempio n. 13
0
def Jpar(R0, Sig, gp):
    if Sig[0] < 1e-100:
        return np.ones(len(R0)-gp.nexp)
    splpar_Sig = splrep(R0, np.log(Sig),k=1,s=0.1) # get spline in log space to circumvent flattening
    J = np.zeros(len(Sig)-gp.nexp)
    for i in range(len(Sig)-gp.nexp):
        xint = np.sqrt(R0[i:]**2-R0[i]**2)
        yint = np.exp(splev(np.sqrt(xint**2+R0[i]**2), splpar_Sig))
        J[i] = gh.quadinflog(xint, yint, 0., gp.rinfty*max(gp.xepol))
        #yf = lambda r: np.exp(splev(np.sqrt(r**2+R0[i]**2), splpar_Sig))
        #J[i] = quad(yf, 0, np.inf)[0]
        # OLD: direct integration with integrand as fct of x
        #xint = R0[i:]
        #yint = Sig[i:]*R0[i:]/np.sqrt(R0[i:]**2-R0[i]**2)
        #J[i] = gh.quadinflog(xint[1:], yint[1:], R0[i], np.inf)
    gh.checkpositive(J)
    return J
Esempio n. 14
0
def rho_param_INT_Sig(r0, rhodmpar, pop, gp):
    # use splines on variable transformed integral
    # \Sigma(R) = \int_{r=R}^{R=\infty} \rho(r) d \sqrt(r^2-R^2)
    xmin = gp.xfine[0]/15. # needed, if not: loose on first 4 bins
    r0nu = gp.xfine
    rhonu = phys.rho(r0nu, rhodmpar, pop, gp)
    Sig = np.zeros(len(r0nu)-gp.nexp)
    for i in range(len(r0nu)-gp.nexp):
        xnew = np.sqrt(r0nu[i:]**2-r0nu[i]**2)         # [lunit]
        ynew = 2.*rhonu[i:]
        # power-law extension to infinity
        C = gh.quadinflog(xnew[-gp.nexp:], ynew[-gp.nexp:], xnew[-1], gp.rinfty*xnew[-1])
        Sig[i] = gh.quadinflog(xnew[1:], ynew[1:], xmin, xnew[-1]) + C # np.inf)
    gh.checkpositive(Sig, 'Sig in rho_param_INT_Sig')
    # interpolation onto r0
    tck1 = splrep(np.log(gp.xfine[:-gp.nexp]), np.log(Sig))
    Sigout = np.exp(splev(np.log(r0), tck1))
    return Sigout
Esempio n. 15
0
def rho_INTDIRECT_Sig(r0, rho):
    # use splines, spline derivative to go beyond first radial point
    splpar_rho = splrep(r0, np.log(rho), k=3, s=0.1)
    # >= 0.1 against rising in last bin. previous: k=2, s=0.1
    # more points to the left help, but not so much
    r0ext = np.array([0.,r0[0]/6.,r0[0]/5.,r0[0]/4.,\
                      r0[0]/3.,r0[0]/2.,r0[0]/1.5])
    # introduce new points in between
    dR = r0[1:] - r0[:-1]
    r0nu = np.hstack(
        [r0ext, r0, dR / 4. + r0[:-1], dR / 2. + r0[:-1], .75 * dR + r0[:-1]])
    r0nu.sort()
    rhonu = np.exp(splev(r0nu, splpar_rho))
    # extend to higher radii
    splpar_lrho = splrep(r0[-3:], np.log(rho[-3:]), k=1,
                         s=0.2)  # previous: k=2
    dr0 = (r0[-1] - r0[-2]) / 8.
    r0ext = np.hstack(
        [r0[-1] + dr0, r0[-1] + 2 * dr0, r0[-1] + 3 * dr0, r0[-1] + 4 * dr0])
    rhoext = np.exp(splev(r0ext, splpar_lrho))
    r0nu = np.hstack([r0nu, r0ext])
    rhonu = np.hstack([rhonu, rhoext])
    Sig = np.zeros(len(r0nu) - 4)
    for i in range(len(r0nu) - 4):
        xint = r0nu[i:]  # [lunit]
        yint = np.ones(len(xint))
        for j in range(i + 1, len(r0nu)):
            yint[j - i] = r0nu[j] * rhonu[j] / np.sqrt(r0nu[j]**2 - r0nu[i]**2)
            # [Munit/lunit^3]
        # Cubic-spline extrapolation to first bin
        splpar_lyint = splrep(xint[1:], np.log(yint[1:]), k=3, s=0.)
        xnew = xint
        ynew = np.hstack([np.exp(splev(xnew[0], splpar_lyint)), yint[1:]])
        # power-law extension to infinity
        splpar_llyint = splrep(xint[-4:], np.log(yint[-4:]), k=1, s=1.)
        invexp = lambda x: np.exp(splev(x, splpar_llyint))
        dropoffint = quad(invexp, r0nu[-1], np.inf)
        splpar_nu = splrep(xnew, ynew, s=0)  # interpolation in real space
        Sig[i] = 2. * (splint(r0nu[i], r0nu[-1], splpar_nu) + dropoffint[0])
    Sigout = splev(r0, splrep(r0nu[:-4], Sig))  # [Munit/lunit^2]
    gh.checkpositive(Sigout, 'Sigout in rho_INTDIRECT_Sig')
    # [Munit/lunit^2]
    return Sigout
Esempio n. 16
0
def Jpar(R0, Sig, gp):
    if Sig[0] < 1e-100:
        return np.ones(len(R0) - gp.nexp)
    splpar_Sig = splrep(
        R0, np.log(Sig), k=1,
        s=0.1)  # get spline in log space to circumvent flattening
    J = np.zeros(len(Sig) - gp.nexp)
    for i in range(len(Sig) - gp.nexp):
        xint = np.sqrt(R0[i:]**2 - R0[i]**2)
        yint = np.exp(splev(np.sqrt(xint**2 + R0[i]**2), splpar_Sig))
        J[i] = gh.quadinflog(xint, yint, 0., gp.rinfty * max(gp.xepol))
        #yf = lambda r: np.exp(splev(np.sqrt(r**2+R0[i]**2), splpar_Sig))
        #J[i] = quad(yf, 0, np.inf)[0]
        # OLD: direct integration with integrand as fct of x
        #xint = R0[i:]
        #yint = Sig[i:]*R0[i:]/np.sqrt(R0[i:]**2-R0[i]**2)
        #J[i] = gh.quadinflog(xint[1:], yint[1:], R0[i], np.inf)
    gh.checkpositive(J)
    return J
Esempio n. 17
0
def rho_param_INT_Sig(r0, rhodmpar, pop, gp):
    # use splines on variable transformed integral
    # \Sigma(R) = \int_{r=R}^{R=\infty} \rho(r) d \sqrt(r^2-R^2)
    xmin = gp.xfine[0] / 15.  # needed, if not: loose on first 4 bins
    r0nu = gp.xfine
    rhonu = phys.rho(r0nu, rhodmpar, pop, gp)
    Sig = np.zeros(len(r0nu) - gp.nexp)
    for i in range(len(r0nu) - gp.nexp):
        xnew = np.sqrt(r0nu[i:]**2 - r0nu[i]**2)  # [lunit]
        ynew = 2. * rhonu[i:]
        # power-law extension to infinity
        C = gh.quadinflog(xnew[-gp.nexp:], ynew[-gp.nexp:], xnew[-1],
                          gp.rinfty * xnew[-1])
        Sig[i] = gh.quadinflog(xnew[1:], ynew[1:], xmin,
                               xnew[-1]) + C  # np.inf)
    gh.checkpositive(Sig, 'Sig in rho_param_INT_Sig')
    # interpolation onto r0
    tck1 = splrep(np.log(gp.xfine[:-gp.nexp]), np.log(Sig))
    Sigout = np.exp(splev(np.log(r0), tck1))
    return Sigout
Esempio n. 18
0
def rho_param_INT_Sig_theta(Rproj, rhodmpar, pop, gp):
    # use splines on variable transformed integral
    # \Sigma(R) = \int_{r=R}^{R=\infty} \rho(r) d \sqrt(r^2-R^2)
    bit = 1.e-6
    theta = np.linspace(0, np.pi / 2 - bit, gp.nfine)
    cth = np.cos(theta)
    cth2 = cth * cth
    rhonu = phys.rho(Rproj, rhodmpar, pop, gp)
    Sig = np.zeros(len(Rproj))
    for i in range(len(Rproj)):
        rq = Rproj[i] / cth
        rhoq = np.interp(rq, Rproj, rhonu, left=0, right=0)
        #right=rhonu[-1]/1e10) # best for hern
        #rhoq = phys.rho(rq, rhodmpar, pop, gp)
        Sig[i] = 2. * Rproj[i] * simps(rhoq / cth2, theta)
    gh.checkpositive(Sig, 'Sig in rho_param_INT_Sig')
    # interpolation onto r0
    #tck1 = splrep(np.log(gp.xfine), np.log(Sig))
    #Sigout = np.exp(splev(np.log(r0), tck1))
    return Sig
Esempio n. 19
0
def rho_param_INT_Sig_theta(Rproj, rhodmpar, pop, gp):
    # use splines on variable transformed integral
    # \Sigma(R) = \int_{r=R}^{R=\infty} \rho(r) d \sqrt(r^2-R^2)
    bit = 1.e-6
    theta = np.linspace(0, np.pi/2-bit, gp.nfine)
    cth = np.cos(theta)
    cth2 = cth*cth
    rhonu = phys.rho(Rproj, rhodmpar, pop, gp)
    Sig = np.zeros(len(Rproj))
    for i in range(len(Rproj)):
        rq = Rproj[i]/cth
        rhoq = np.interp(rq, Rproj, rhonu, left=0, right=0)
        #right=rhonu[-1]/1e10) # best for hern
        #rhoq = phys.rho(rq, rhodmpar, pop, gp)
        Sig[i] = 2.*Rproj[i]*simps(rhoq/cth2, theta)
    gh.checkpositive(Sig, 'Sig in rho_param_INT_Sig')
    # interpolation onto r0
    #tck1 = splrep(np.log(gp.xfine), np.log(Sig))
    #Sigout = np.exp(splev(np.log(r0), tck1))
    return Sig
Esempio n. 20
0
def rho_INTDIRECT_Sig(r0, rho):
    # use splines, spline derivative to go beyond first radial point
    splpar_rho = splrep(r0, np.log(rho), k=3, s=0.1)
    # >= 0.1 against rising in last bin. previous: k=2, s=0.1
    # more points to the left help, but not so much
    r0ext = np.array([0.,r0[0]/6.,r0[0]/5.,r0[0]/4.,\
                      r0[0]/3.,r0[0]/2.,r0[0]/1.5])
    # introduce new points in between
    dR = r0[1:]-r0[:-1]
    r0nu = np.hstack([r0ext,r0,dR/4.+r0[:-1],dR/2.+r0[:-1],.75*dR+r0[:-1]])
    r0nu.sort()
    rhonu = np.exp(splev(r0nu,splpar_rho))
    # extend to higher radii
    splpar_lrho = splrep(r0[-3:],np.log(rho[-3:]),k=1,s=0.2) # previous: k=2
    dr0 = (r0[-1]-r0[-2])/8.
    r0ext = np.hstack([r0[-1]+dr0, r0[-1]+2*dr0, r0[-1]+3*dr0, r0[-1]+4*dr0])
    rhoext = np.exp(splev(r0ext,splpar_lrho))
    r0nu = np.hstack([r0nu, r0ext]);    rhonu = np.hstack([rhonu, rhoext])
    Sig = np.zeros(len(r0nu)-4)
    for i in range(len(r0nu)-4):
        xint = r0nu[i:]         # [lunit]
        yint = np.ones(len(xint))
        for j in range(i+1,len(r0nu)):
            yint[j-i] = r0nu[j] * rhonu[j]/np.sqrt(r0nu[j]**2-r0nu[i]**2)
            # [Munit/lunit^3]
        # Cubic-spline extrapolation to first bin
        splpar_lyint = splrep(xint[1:], np.log(yint[1:]), k=3, s=0.)
        xnew = xint
        ynew = np.hstack([np.exp(splev(xnew[0], splpar_lyint)), yint[1:]])
        # power-law extension to infinity
        splpar_llyint = splrep(xint[-4:], np.log(yint[-4:]), k=1, s=1.)
        invexp = lambda x: np.exp(splev(x, splpar_llyint))
        dropoffint = quad(invexp, r0nu[-1], np.inf)
        splpar_nu = splrep(xnew, ynew, s=0) # interpolation in real space
        Sig[i] = 2. * (splint(r0nu[i], r0nu[-1], splpar_nu) + dropoffint[0])
    Sigout = splev(r0, splrep(r0nu[:-4],Sig))     # [Munit/lunit^2]
    gh.checkpositive(Sigout, 'Sigout in rho_INTDIRECT_Sig')
    # [Munit/lunit^2]
    return Sigout
Esempio n. 21
0
def rho(r0, rhodmpar, pop, gp):
    gh.sanitize_vector(rhodmpar, gp.nrho, 0, 1e30, gp.debug)
    vec = 1. * rhodmpar  # make a new copy so we do not overwrite rhodmpar
    rho_at_rhalf = vec[0]
    vec = vec[1:]
    # get spline representation on gp.xepol, where rhodmpar are defined on
    spline_n = nr(gp.xepol, vec, pop, gp)
    # and apply it to these radii, which may be anything in between
    # self.Xscale is determined in 2D, not 3D
    # use gp.dat.rhalf[0]
    rs = np.log(r0 / gp.dat.rhalf[pop])  # have to integrate in d log(r)
    lnrright = []
    lnrleft = []
    if np.rank(rs) == 0:
        if rs > 0:
            lnrright.append(rs)
        else:
            lnrleft.append(rs)
    else:
        lnrright = rs[(rs >= 0.)]
        lnrleft = rs[(rs < 0.)]
        lnrleft = lnrleft[::-1]  # inverse order

    lnrhoright = []
    for i in np.arange(0, len(lnrright)):
        lnrhoright.append(np.log(rho_at_rhalf) + \
                           splint(0., lnrright[i], spline_n))
        # integration along dlog(r) instead of dr

    lnrholeft = []
    for i in np.arange(0, len(lnrleft)):
        lnrholeft.append(np.log(rho_at_rhalf) + \
                          splint(0., lnrleft[i], spline_n))

    tmp = np.exp(np.hstack([lnrholeft[::-1],
                            lnrhoright]))  # still defined on ln(r)
    gh.checkpositive(tmp, 'rho()')
    return tmp
Esempio n. 22
0
def rho(r0, rhodmpar, pop, gp):
    gh.sanitize_vector(rhodmpar, gp.nrho, 0, 1e30, gp.debug)
    vec = 1.*rhodmpar # make a new copy so we do not overwrite rhodmpar
    rho_at_rhalf = vec[0]
    vec = vec[1:]
    # get spline representation on gp.xepol, where rhodmpar are defined on
    spline_n = nr(gp.xepol, vec, pop, gp)
    # and apply it to these radii, which may be anything in between
    # self.Xscale is determined in 2D, not 3D
    # use gp.dat.rhalf[0]
    rs =  np.log(r0/gp.dat.rhalf[pop]) # have to integrate in d log(r)
    lnrright = []
    lnrleft = []
    if np.rank(rs) == 0:
        if rs>0:
            lnrright.append(rs)
        else:
            lnrleft.append(rs)
    else:
        lnrright = rs[(rs>=0.)]
        lnrleft  = rs[(rs<0.)]
        lnrleft  = lnrleft[::-1] # inverse order

    lnrhoright = []
    for i in np.arange(0, len(lnrright)):
        lnrhoright.append(np.log(rho_at_rhalf) + \
                           splint(0., lnrright[i], spline_n))
                           # integration along dlog(r) instead of dr

    lnrholeft = []
    for i in np.arange(0, len(lnrleft)):
        lnrholeft.append(np.log(rho_at_rhalf) + \
                          splint(0., lnrleft[i], spline_n))

    tmp = np.exp(np.hstack([lnrholeft[::-1], lnrhoright])) # still defined on ln(r)
    gh.checkpositive(tmp, 'rho()')
    return tmp
Esempio n. 23
0
def rho(z0, rhopar, pop, gp):
    vec = rhopar
    rho_at_rhalf = vec[0]
    vec = vec[1:]
    # get spline representation on gp.xepol, where rhopar are defined on
    spline_n = nr(gp.xepol, vec, pop, gp)

    # and apply it to these radii, which may be anything in between
    zs = np.log(z0 / gp.Xscale[pop])  # have to integrate in d log(r)
    logrright = []
    logrleft = []
    if np.rank(zs) == 0:
        if zs > 0:
            logrright.append(zs)
        else:
            logrleft.append(zs)
    else:
        logrright = zs[(zs >= 0.)]
        logrleft = zs[(zs < 0.)]
        logrleft = logrleft[::-1]  # inverse order

    # integrate to left and right of halflight radius
    logrhoright = []
    for i in np.arange(0, len(logrright)):
        logrhoright.append(np.log(rho_at_rhalf) + \
                           splint(0., logrright[i], spline_n))
        # integration along dlog(r) instead of dr

    logrholeft = []
    for i in np.arange(0, len(logrleft)):
        logrholeft.append(np.log(rho_at_rhalf) + \
                          splint(0., logrleft[i], spline_n))

    tmp = np.exp(np.hstack([logrholeft[::-1],
                            logrhoright]))  # still defined on log(r)
    gh.checkpositive(tmp, 'rho()')
    return tmp
Esempio n. 24
0
def rho_INT_Sig(r0, rho, gp):
    # use splines on variable transformed integral
    # \Sigma(R) = \int_{r=R}^{R=\infty} \rho(r) d \sqrt(r^2-R^2)
    if rho[0] <= 1e-100:
        return np.zeros(gp.nepol)
    gh.checknan(rho, 'rho_INT_Sig')
    # >= 0.1 against rising in last bin. previous: k=2, s=0.1
    # TODO: check use of np.log(r0) here
    splpar_rho = splrep(r0, np.log(rho), k=3, s=0.01)  # 0.01?
    r0ext = np.array([0., r0[0] * 0.25, r0[0] * 0.50, r0[0] * 0.75])
    #dR = r0[1:]-r0[:-1]
    r0nu = np.hstack([r0ext, r0])
    # points in between possible, but not helping much:
    # ,dR*0.25+r0[:-1],dR*0.50+r0[:-1],dR*0.75+r0[:-1]])
    r0nu.sort()
    rhonu = np.exp(splev(r0nu, splpar_rho))
    # extend to higher radii
    splpar_lrhor = splrep(r0[-3:], np.log(rho[-3:]), k=1,
                          s=1.)  # k=2 gives NaN!
    dr0 = (r0[-1] - r0[-2]) / 8.
    r0ext = np.hstack(
        [r0[-1] + dr0, r0[-1] + 2 * dr0, r0[-1] + 3 * dr0, r0[-1] + 4 * dr0])
    rhoext = np.exp(splev(r0ext, splpar_lrhor))
    r0nu = np.hstack([r0nu, r0ext])
    rhonu = np.hstack([rhonu, rhoext])
    gh.checkpositive(rhonu, 'rhonu in rho_INT_Sig')
    Sig = np.zeros(len(r0nu) - 4)
    for i in range(len(r0nu) - 4):
        xnew = np.sqrt(r0nu[i:]**2 - r0nu[i]**2)  # [lunit]
        ynew = 2. * rhonu[i:]
        yscale = 10.**(1. - min(np.log10(ynew)))
        ynew *= yscale
        # power-law extension to infinity
        C = gh.quadinflog(xnew[-4:], ynew[-4:], xnew[-1],
                          gp.rinfty * max(gp.xepol))
        splpar_nu = splrep(
            xnew, ynew,
            k=3)  # interpolation in real space. previous: k=2, s=0.1
        Sig[i] = splint(0., xnew[-1], splpar_nu) + C
    Sig /= yscale
    gh.checkpositive(Sig, 'Sig in rho_INT_Sig')
    Sigout = splev(r0, splrep(r0nu[:-4], Sig))  # [Munit/lunit^2]
    gh.checkpositive(Sigout, 'Sigout in rho_INT_Sig')
    return Sigout
Esempio n. 25
0
def rho_INT_Sig(r0, rho, gp):
    # use splines on variable transformed integral
    # \Sigma(R) = \int_{r=R}^{R=\infty} \rho(r) d \sqrt(r^2-R^2)
    if rho[0] <= 1e-100:
        return np.zeros(gp.nepol)
    gh.checknan(rho, 'rho_INT_Sig')
    # >= 0.1 against rising in last bin. previous: k=2, s=0.1
    # TODO: check use of np.log(r0) here
    splpar_rho = splrep(r0, np.log(rho), k=3, s=0.01) # 0.01?
    r0ext = np.array([0., r0[0]*0.25, r0[0]*0.50, r0[0]*0.75])
    #dR = r0[1:]-r0[:-1]
    r0nu = np.hstack([r0ext,r0])
    # points in between possible, but not helping much:
    # ,dR*0.25+r0[:-1],dR*0.50+r0[:-1],dR*0.75+r0[:-1]])
    r0nu.sort()
    rhonu = np.exp(splev(r0nu, splpar_rho))
    # extend to higher radii
    splpar_lrhor   = splrep(r0[-3:],np.log(rho[-3:]),k=1,s=1.) # k=2 gives NaN!
    dr0    = (r0[-1]-r0[-2])/8.
    r0ext  = np.hstack([r0[-1]+dr0, r0[-1]+2*dr0, r0[-1]+3*dr0, r0[-1]+4*dr0])
    rhoext = np.exp(splev(r0ext, splpar_lrhor))
    r0nu   = np.hstack([r0nu, r0ext])
    rhonu  = np.hstack([rhonu, rhoext])
    gh.checkpositive(rhonu, 'rhonu in rho_INT_Sig')
    Sig = np.zeros(len(r0nu)-4)
    for i in range(len(r0nu)-4):
        xnew = np.sqrt(r0nu[i:]**2-r0nu[i]**2)         # [lunit]
        ynew = 2.*rhonu[i:]
        yscale = 10.**(1.-min(np.log10(ynew)))
        ynew *= yscale
        # power-law extension to infinity
        C = gh.quadinflog(xnew[-4:],ynew[-4:],xnew[-1], gp.rinfty*max(gp.xepol))
        splpar_nu  = splrep(xnew,ynew,k=3) # interpolation in real space. previous: k=2, s=0.1
        Sig[i] = splint(0., xnew[-1], splpar_nu) + C
    Sig /= yscale
    gh.checkpositive(Sig, 'Sig in rho_INT_Sig')
    Sigout = splev(r0, splrep(r0nu[:-4], Sig))     # [Munit/lunit^2]
    gh.checkpositive(Sigout, 'Sigout in rho_INT_Sig')
    return Sigout
Esempio n. 26
0
def sigz(zp, rhopar, lbaryonpar, MtoL, nupar, norm, tpar, pop, gp):
    # calculate density and Kz force:
    nutmp = rho(zp, nupar, pop, gp)
    nu_z = nutmp / np.max(nutmp)  # normalized to [1]
    gh.checkpositive(nu_z)
    rhodmtmp = rho(zp, rhopar, 0, gp)  # rho_DM in linearly spaced bins
    gh.checkpositive(rhodmtmp)
    rhostartmp = rho(zp, lbaryonpar, 0, gp)
    gh.checkpositive(rhostartmp)
    rhotmp = rhodmtmp + MtoL * rhostartmp  # add baryons
    kz_z = kz(zp, rhotmp, gp)  # [(km/s)^2/pc]

    # add tilt correction [if required]:
    #Rsun = tparsR[0]
    #hr   = tparsR[1]
    #hsig = tparsR[2]
    #tc = sig_rz(zp, zp, tpars)
    #tc = tc * (1.0/Rsun - 1.0/hr - 1.0/hsig)
    # flag when the tilt becomes significant:
    #if abs(np.sum(tc))/abs(np.sum(kz_z)) > 0.1:
    #    print('Tilt > 10%!', abs(np.sum(tc)), abs(np.sum(kz_z)))
    #kz_z = kz_z-tc

    # do exact integral
    if not gp.quadratic:
        # linear interpolation here:
        sigint = np.zeros(len(zp))
        for i in range(1, len(zp)):
            zl = zp[i - 1]
            zr = zp[i]
            zz = zr - zl
            b = nu_z[i - 1]
            a = nu_z[i]
            q = kz_z[i - 1]
            p = kz_z[i]

            intbit = (a-b)*(p-q)/(3.0*zz**2.) * (zr**3.-zl**3.) + \
                ((a-b)/(2.0*zz) * (q-(p-q)*zl/zz) + (p-q)/(2.0*zz)  * \
                 (b-(a-b)*zl/zz)) * (zr**2.-zl**2.)+\
                (b-(a-b)*zl/zz) * (q-(p-q)*zl/zz) * zz

            if i == 0:
                sigint[0] = intbit
            else:
                sigint[i] = sigint[i - 1] + intbit
    else:
        # quadratic interpolation
        sigint = np.zeros(len(zp))
        for i in range(1, len(zp) - 1):
            z0 = zp[i - 1]
            z1 = zp[i]
            z2 = zp[i + 1]
            f0 = nu_z[i - 1]
            f1 = nu_z[i]
            f2 = nu_z[i + 1]
            fd0 = kz_z[i - 1]
            fd1 = kz_z[i]
            fd2 = kz_z[i + 1]
            h = z2 - z1
            a = f0
            b = (f1 - a) / h
            c = (f2 - 2. * b * h - a) / 2. / h**2.
            ad = fd0
            bd = (fd1 - ad) / h
            cd = (fd2 - 2. * bd * h - ad) / 2. / h**2.
            AA = a * bd + ad * b
            BB = c * ad + cd * a
            CC = b * cd + bd * c
            z1d = z1 - z0
            z2d = z1**2. - z0**2.
            z3d = z1**3. - z0**3.
            z4d = z1**4. - z0**4.
            z5d = z1**5. - z0**5.
            intbit = z1d * (a*ad - z0*(AA-BB*z1) + z0**2.*(b*bd-CC*z1) + \
                        c*cd*z0**2.*z1**2.) + \
                        z2d * (0.5*(AA-BB*z1)-z0*(b*bd-CC*z1)-z0/2.*BB+z0**2./2.*CC - \
                        (z0*z1**2.+z0**2.*z1)*c*cd)+z3d*(1.0/3.0*(b*bd-CC*z1)+1.0/3.0*BB-2.0/3.0*z0*CC + \
                        1.0/3.0*c*cd*(z1**2.+z0**2.+4.0*z0*z1))+z4d*(1.0/4.0*CC-c*cd/2.0*(z1 + z0)) + \
                        z5d*c*cd/5.

            sigint[i] = sigint[i - 1] + intbit
            if i == len(zp) - 2:
                # Deal with very last bin:
                z1d = z2 - z1
                z2d = z2**2. - z1**2.
                z3d = z2**3. - z1**3.
                z4d = z2**4. - z1**4.
                z5d = z2**5. - z1**5.
                intbit = z1d * (a*ad - z0*(AA-BB*z1) + z0**2.*(b*bd-CC*z1) + \
                         c*cd*z0**2.*z1**2.) + \
                  z2d * (0.5*(AA-BB*z1)-z0*(b*bd-CC*z1) - z0/2.*BB + z0**2./2.*CC - \
                         (z0*z1**2. + z0**2.*z1)*c*cd) + \
                  z3d * (1.0/3.0*(b*bd-CC*z1)+1.0/3.0*BB - 2.0/3.0*z0*CC + \
                         1.0/3.0*c*cd*(z1**2. + z0**2. + 4.0*z0*z1)) + \
                  z4d * (1.0/4.0*CC - c*cd/2.0 * (z1 + z0)) + \
                  z5d * c*cd / 5.

                sigint[i + 1] = sigint[i] + intbit
    sig_z_t2 = 1.0 / nu_z * (sigint + norm)
    return np.sqrt(sig_z_t2[3:-3])
Esempio n. 27
0
######################## calculation of sigma_LOS ##########################


start_time = time.time()

# integrate enclosed 3D mass from 3D density
r0tmp = np.hstack([0.,rfine])
rhoint = 4.*np.pi*rfine**2*rhonu
# add point to avoid 0.0 in Mrnu(rfine[0])
rhotmp = np.hstack([0.,rhoint])

splpar = splrep(r0tmp, rhotmp, k=1, s=0.) # not necessarily monotonic
Mrnu = np.zeros(len(rfine))              # work in refined model
for i in range(len(rfine)):              # get Mrnu
    Mrnu[i] = splint(0., rfine[i], splpar)
gh.checkpositive(Mrnu, 'Mrnu')

Mr_hern = ga.M_hern(rfine, 1, 1)

# (sigr2, 3D) * nu/exp(-idnu)
xint = rfine                           # [pc]
yint = G1 * Mrnu / rfine**2         # [1/pc (km/s)^2]
yint *= nunu                          # [Munit/pc^4 (km/s)^2]
yint *= np.exp(idnu)                  # [Munit/pc^4 (km/s)^2]
gh.checkpositive(yint, 'yint sigr2')

# use quadinflog or quadinfloglog here
sigr2nu = np.zeros(len(rfine))
for i in range(len(rfine)):
    sigr2nu[i] = np.exp(-idnu[i])/nunu[i]*\
                 gh.quadinflog(xint, yint, rfine[i], gp.rinfty*rfine[-1], True)
Esempio n. 28
0
def sigz(zp, rhopar, lbaryonpar, MtoL, nupar, norm, tpar, pop, gp):
    # calculate density and Kz force:
    nutmp = rho(zp, nupar, pop, gp)
    nu_z = nutmp/np.max(nutmp)  # normalized to [1]
    gh.checkpositive(nu_z)
    rhodmtmp = rho(zp, rhopar, 0, gp) # rho_DM in linearly spaced bins
    gh.checkpositive(rhodmtmp)
    rhostartmp = rho(zp, lbaryonpar, 0, gp)
    gh.checkpositive(rhostartmp)
    rhotmp = rhodmtmp+MtoL*rhostartmp # add baryons
    kz_z = kz(zp, rhotmp, gp) # [(km/s)^2/pc]

    # add tilt correction [if required]:
    #Rsun = tparsR[0]
    #hr   = tparsR[1]
    #hsig = tparsR[2]
    #tc = sig_rz(zp, zp, tpars)
    #tc = tc * (1.0/Rsun - 1.0/hr - 1.0/hsig)
    # flag when the tilt becomes significant:
    #if abs(np.sum(tc))/abs(np.sum(kz_z)) > 0.1:
    #    print('Tilt > 10%!', abs(np.sum(tc)), abs(np.sum(kz_z)))
    #kz_z = kz_z-tc

    # do exact integral
    if not gp.quadratic:
        # linear interpolation here:
        sigint = np.zeros(len(zp))
        for i in range(1,len(zp)):
            zl = zp[i-1];  zr = zp[i];  zz = zr-zl
            b = nu_z[i-1]
            a = nu_z[i]
            q = kz_z[i-1]
            p = kz_z[i]

            intbit = (a-b)*(p-q)/(3.0*zz**2.) * (zr**3.-zl**3.) + \
                ((a-b)/(2.0*zz) * (q-(p-q)*zl/zz) + (p-q)/(2.0*zz)  * \
                 (b-(a-b)*zl/zz)) * (zr**2.-zl**2.)+\
                (b-(a-b)*zl/zz) * (q-(p-q)*zl/zz) * zz

            if i==0:
                sigint[0] = intbit
            else:
                sigint[i] = sigint[i-1] + intbit
    else:
        # quadratic interpolation
        sigint = np.zeros(len(zp))
        for i in range(1,len(zp)-1):
            z0 = zp[i-1];   z1 = zp[i];   z2 = zp[i+1]
            f0 = nu_z[i-1]; f1 = nu_z[i]; f2 = nu_z[i+1]
            fd0 = kz_z[i-1];fd1 = kz_z[i];fd2 = kz_z[i+1]
            h = z2-z1; a = f0; b = (f1-a)/h; c = (f2-2.*b*h-a)/2./h**2.
            ad = fd0; bd = (fd1-ad)/h; cd = (fd2-2.*bd*h-ad)/2./h**2.
            AA = a*bd+ad*b
            BB = c*ad+cd*a
            CC = b*cd+bd*c
            z1d = z1-z0
            z2d = z1**2.-z0**2.
            z3d = z1**3.-z0**3.
            z4d = z1**4.-z0**4.
            z5d = z1**5.-z0**5.
            intbit = z1d * (a*ad - z0*(AA-BB*z1) + z0**2.*(b*bd-CC*z1) + \
                        c*cd*z0**2.*z1**2.) + \
                        z2d * (0.5*(AA-BB*z1)-z0*(b*bd-CC*z1)-z0/2.*BB+z0**2./2.*CC - \
                        (z0*z1**2.+z0**2.*z1)*c*cd)+z3d*(1.0/3.0*(b*bd-CC*z1)+1.0/3.0*BB-2.0/3.0*z0*CC + \
                        1.0/3.0*c*cd*(z1**2.+z0**2.+4.0*z0*z1))+z4d*(1.0/4.0*CC-c*cd/2.0*(z1 + z0)) + \
                        z5d*c*cd/5.

            sigint[i] = sigint[i-1] + intbit
            if i == len(zp)-2:
                # Deal with very last bin:
                z1d = z2-z1
                z2d = z2**2.-z1**2.
                z3d = z2**3.-z1**3.
                z4d = z2**4.-z1**4.
                z5d = z2**5.-z1**5.
                intbit = z1d * (a*ad - z0*(AA-BB*z1) + z0**2.*(b*bd-CC*z1) + \
                         c*cd*z0**2.*z1**2.) + \
                  z2d * (0.5*(AA-BB*z1)-z0*(b*bd-CC*z1) - z0/2.*BB + z0**2./2.*CC - \
                         (z0*z1**2. + z0**2.*z1)*c*cd) + \
                  z3d * (1.0/3.0*(b*bd-CC*z1)+1.0/3.0*BB - 2.0/3.0*z0*CC + \
                         1.0/3.0*c*cd*(z1**2. + z0**2. + 4.0*z0*z1)) + \
                  z4d * (1.0/4.0*CC - c*cd/2.0 * (z1 + z0)) + \
                  z5d * c*cd / 5.

                sigint[i+1] = sigint[i] + intbit
    sig_z_t2 = 1.0/nu_z * (sigint + norm)
    return  np.sqrt(sig_z_t2[3:-3])
Esempio n. 29
0
def ant_sigkaplos(r0, rhodmpar, lbaryonpar, MtoL, nupar, betapar, pop, gp):
    rmin = np.log10(min(r0))
    rmax = np.log10(max(r0)*gp.rinfty)
    r0fine = np.logspace(rmin, rmax, gp.nfine)

    # rho
    # --------------------------------------------------------------------------
    rhofine  = phys.rho(r0fine,  rhodmpar, 0, gp) # DM mass profile (first)
    if gp.checksig and gp.stopstep <= 1:
        clf()
        loglog(r0fine, rhofine, 'r.-', label='rederived from dn/dlogr params')
        loglog(r0fine, ga.rho(r0fine, gp)[0], 'b--', label='analytic')
        axvline(max(gp.xipol))
        axvline(min(gp.xipol))
        axvline(gp.dat.rhalf[0], lw=2)
        xlabel('$r/\\rm{pc}$')
        ylabel('$\\rho(r)$')
        legend(loc='lower left')
        savefig('fit_rho_'+gp.investigate+'.pdf')
        pdb.set_trace()

    # add up tracer densities to get overall density profile
    # add rho* to take into account the baryonic addition
    # (*not* Sigma from nu_i, could miss populations, have
    # varying selection function as fct of radius
    # need a M/L parameter)
    # only if we work on real data, add up total baryonic contribution
    if gp.investigate == 'obs':
        nu_baryons = MtoL*phys.rho(r0fine, lbaryonpar, pop, gp)
        rhofine += nu_baryons

    # beta
    # ------------------------------------------------------------------------
    betafine = phys.beta(r0fine, betapar, gp)[0]
    if gp.checksig and gp.stopstep <= 2:
        clf()
        anbeta = ga.beta(r0fine, gp)[1]
        plot(r0fine, betafine, 'r.-', label='model')
        plot(r0fine, anbeta, 'b--', label='analytic')
        xscale('log')
        axvline(max(gp.xipol))
        axvline(min(gp.xipol))
        axvline(gp.dat.rhalf[0], lw=2)
        xlabel('$r/\\rm{pc}$')
        ylabel('$\\beta$')
        ylim([-0.5, 1.0])
        legend(loc='lower right')
        savefig('fit_beta_'+gp.investigate+'.pdf')
        pdb.set_trace()

    # nu
    # ------------------------------------------------------------------------
    nufine   = phys.rho(r0fine, nupar, pop, gp)
    if gp.checksig:
        annu = ga.rho(r0fine, gp)[pop]
    if gp.checksig and gp.stopstep <= 3:
        clf()
        loglog(gp.xipol, gp.dat.nu[pop], 'g.-', label='data')
        fill_between(gp.xipol, gp.dat.nu[pop]-gp.dat.nuerr[pop], \
                     gp.dat.nu[pop]+gp.dat.nuerr[pop],\
                     color='g', alpha=0.6)
        loglog(r0fine, nufine, 'r.-', label='model')
        loglog(r0fine, annu, 'b--', label='analytic')
        legend(loc='lower left')
        axvline(max(gp.xipol))
        axvline(min(gp.xipol))
        axvline(gp.dat.rhalf[0], lw=2)
        xlabel('$r/\\rm{pc}$')
        ylabel('$\\nu$')
        savefig('fit_nu_'+gp.investigate+'.pdf')
        pdb.set_trace()


    # \Sigma
    # ---------------------------------------------------------------
    Sigfine  = gip.rho_param_INT_Sig_theta(r0fine, nupar, pop, gp)
    if gp.checksig and gp.stopstep <= 4:
        clf()
        anSig = ga.Sigma(r0fine, gp)[pop]
        loglog(gp.xipol, gp.dat.Sig[pop], 'g--', label='data')
        loglog(r0fine, Sigfine, 'r.-', label='model')
        loglog(r0fine, anSig, 'b--', label='analytic')
        fill_between(gp.xipol, gp.dat.Sig[pop]-gp.dat.Sigerr[pop], \
                     gp.dat.Sig[pop]+gp.dat.Sigerr[pop],\
                     color='g', alpha=0.6)
        axvline(max(gp.xipol))
        axvline(min(gp.xipol))
        axvline(gp.Xscale[0], lw=2)
        xlabel('$r/\\rm{pc}$')
        ylabel('$\\Sigma$')
        legend(loc='lower left')
        savefig('fit_Sig_'+gp.investigate+'.pdf')
        pdb.set_trace()

    # int beta(s)/s ds
    # ------------------------------------------------------
    # test for constant \beta
    if gp.checksig:
        if gp.investigate == 'gaia':
            beta_star1, r_DM, gamma_star1, r_star1, r_a1, gamma_DM, rho0 = gp.files.params
            anintbetasfine = 0.5*(np.log(r0fine**2+r_a1**2)-np.log(r_a1**2))
        elif gp.investigate == 'hern':
            anintbetasfine = 0.0*r0fine
    #betapar[0] = 1
    #betapar[1] = 1
    anintbetasfine = np.log(r0fine)-np.log(r0fine[0])
    intbetasfine   = ant_intbeta(r0fine, betapar, gp)
    if gp.checksig and gp.stopstep <= 5 :
        clf()
        plot(r0fine, intbetasfine, 'r.-', label='model')
        plot(r0fine, anintbetasfine, 'b--', label='analytic')
        ylim([-5, 5])
        axvline(max(gp.xipol))
        axvline(min(gp.xipol))
        axvline(gp.dat.rhalf[0], lw=2)
        xscale('log')
        xlabel('$r/\\rm{pc}$')
        ylabel('$\\int ds \\beta(s)/s$')
        legend(loc='lower right')
        savefig('fit_intbeta_'+gp.investigate+'.pdf')
        pdb.set_trace()

    # M(r)
    # -------------------------------------------------------
    #rhofine = ga.rho_hern(r0fine, gp)[0]
    rhoint = 4.*np.pi*r0fine**2*rhofine
    # add point to avoid 0.0 in Mrfine(r0fine[0])
    r0tmp = np.hstack([0.,r0fine])
    rhotmp = np.hstack([0.,rhoint])
    splpar_rho = splrep(r0tmp, rhotmp, k=1, s=0.) # not necessarily monotonic
    Mrfine = np.zeros(len(r0fine)) # work in refined model
    for i in range(len(r0fine)):
        Mrfine[i] = splint(0., r0fine[i], splpar_rho)
    gh.checkpositive(Mrfine, 'Mrfine')
    if gp.checksig:
        anMr = ga.Mr(r0fine, gp)[0] # earlier: pop
        anMr = Mrfine
        #anMr = ga.M_hern(r0fine, gp)[0]
    if gp.checksig and gp.stopstep <= 6:
        #loglog(gp.xipol, gp.dat.Mr[pop], 'g.-', label='data')
        #s = r0fine/r_DM # [1]
        clf()
        loglog(r0fine, Mrfine, 'r.-', label='model')
        #loglog(r0fine, anMr, 'b--', label='analytic')
        axvline(max(gp.xipol))
        axvline(min(gp.xipol))
        axvline(gp.dat.rhalf[0], lw=2)
        xlabel('$r/\\rm{pc}$')
        ylabel('$M(r)$')
        legend(loc='lower right')
        savefig('fit_M_'+gp.investigate+'.pdf')
        pdb.set_trace()

    # nu(r)\cdot\sigma_r^2(r) integrand
    # -------------------------------------------------------
    # (sigr2, 3D) * nu/exp(-intbetasfine)
    xint = r0fine                           # [pc]
    yint = gu.G1__pcMsun_1km2s_2 * Mrfine / r0fine**2         # [1/pc (km/s)^2]
    yint *= nufine                          # [Munit/pc^4 (km/s)^2]
    yint *= np.exp(2*(intbetasfine))                  # [Munit/pc^4 (km/s)^2]
    gh.checkpositive(yint, 'yint sigr2')
    if gp.checksig and gp.stopstep <= 7:
        clf()
        loglog(xint, yint, 'r.-', label='model')
        loglog(xint, gu.G1__pcMsun_1km2s_2 * anMr / r0fine**2 * annu * np.exp(2*anintbetasfine), 'b--', label='from analytic')
        axvline(max(gp.xipol))
        axvline(min(gp.xipol))
        axvline(gp.dat.rhalf[0], lw=2)
        xlabel('$xint/\\rm{pc}$')
        ylabel('$yint$')
        legend(loc='lower left')
        savefig('fit_nu_sigmar2_'+gp.investigate+'.pdf')
        pdb.set_trace()

    # actual integration, gives \sigma_r^2 \nu
    sigr2nu_model = np.zeros(len(r0fine))
    for k in range(len(r0fine)):
        #theta_old = np.linspace(0, np.arccos(r0fine[k]/(gp.rinfty*max(gp.xepol))), gp.nfine)
        theta = np.arccos(r0fine[k]/r0fine[k:])
        rq = r0fine[k]/np.cos(theta)

        #Mrq = np.interp(rq, r0fine, Mrfine, left=0, right=0)
        #nuq = np.interp(rq, r0fine, nufine, left=0, right=0)
        #intbetaq = np.interp(rq, r0fine, intbetasfine, left=0, right=0)
        #func_interp_before = Mrq*nuq*np.exp(2*intbetaq)

        func_base = Mrfine*nufine*np.exp(2*intbetasfine)
        #func_interp_after = np.interp(rq, r0fine, func_base, left=0, right=0)
        func_interp_after = func_base[k:]

        #print('median(func_interp_after / func_interp_before = ',\
        #      np.median(func_interp_after / func_interp_before))

        #sigr2nu_model[k] =  np.exp(-2*intbetasfine[k])/r0fine[k] * \
        #                    gu.G1__pcMsun_1km2s_2*simps(func_interp_before*np.sin(theta), theta)

        sigr2nu_model[k] = np.exp(-2*intbetasfine[k])/r0fine[k] * \
                               gu.G1__pcMsun_1km2s_2*simps(func_interp_after*np.sin(theta), theta)

    # clean last value (which is always 0 by construction)
    sigr2nu_model[-1] = sigr2nu_model[-2]/10.
    gh.checkpositive(sigr2nu_model, 'sigr2nu_model in sigl2s')
    #gh.checkpositive(sigr2nu_model_new, 'sigr2nu_model_new in sigl2s')
    if gp.checksig and gp.stopstep <= 8:
        clf()
        ansigr2nu = ga.sigr2(r0fine, gp)*annu
        loglog(r0fine, sigr2nu_model, 'r.-', label='model')
        loglog(r0fine, ansigr2nu, 'b--', label='analytic')
        axvline(max(gp.xipol))
        axvline(min(gp.xipol))
        axvline(gp.dat.rhalf[0], lw=2)
        xlabel('$r/\\rm{pc}$')
        ylabel('$\\sigma_r^2(r)\\nu(r)$')
        legend(loc='lower right')
        savefig('fit_sigr2_'+gp.investigate+'.pdf')

    # project back to LOS values, \sigma_{LOS}^2 * \Sigma(R)
    # -------------------------------------------------------
    sigl2s = np.zeros(len(r0fine))
    for k in range(len(r0fine)):
        bit = 1.e-6
        theta = np.linspace(0, np.pi/2-bit, gp.nfine)
        # work on same radii as data are given
        theta = np.arccos(r0fine[k]/r0fine[k:])
        cth = np.cos(theta)
        cth2 = cth*cth
        ynew = (1-betafine[k:]*cth2)*sigr2nu_model[k:]

        rq = r0fine[k]/cth
        ynewq = np.interp(rq, r0fine[k:], ynew, left=0, right=0)
        sigl2s[k] = 2.*r0fine[k]*simps(ynewq/cth2, theta)
    sigl2s[-1] = sigl2s[-2]/10.
    gh.checkpositive(sigl2s, 'sigl2s')
    if gp.checksig and gp.stopstep <= 9:
        clf()
        anSigsiglos2_hern = ga.Sig_sig_los_2(r0fine, gp)
        loglog(r0fine, sigl2s, 'r.-', label='model')
        loglog(r0fine, anSigsiglos2_hern, 'b--', label='analytic')
        axvline(max(gp.xipol))
        axvline(min(gp.xipol))
        axvline(gp.Xscale[0], lw=2)
        xlabel('$r/\\rm{pc}$')
        ylabel('$\\sigma_{\\rm{LOS}}^2 \Sigma$')
        legend(loc='lower left')
        savefig('fit_Sig_siglos2_'+gp.investigate+'.pdf')
        pdb.set_trace()


    # sigma_LOS^2
    # -------------------------------------------------------
    siglos2 = sigl2s/Sigfine
    if gp.checksig and gp.stopstep <= 10:
        clf()
        #ansiglos = ga.sig_los(r0fine, gp)
        plot(r0fine, siglos2, 'r.-', label='model')
        #plot(r0fine, ansiglos**2, 'b--', label='analytic')
        axvline(max(gp.xipol))
        axvline(min(gp.xipol))
        axvline(gp.Xscale[0], lw=2)
        xscale('log')
        xlabel('$r/\\rm{pc}$')
        ylabel('$\\sigma_{\\rm{LOS}}^2$')
        legend(loc='upper right')
        savefig('fit_siglos2_'+gp.investigate+'.pdf')
        pdb.set_trace()

    # derefine on radii of the input vector
    splpar_sig = splrep(r0fine, np.log(siglos2), k=3, s=0.)
    siglos2_out = np.exp(splev(r0, splpar_sig))
    # gh.checkpositive(siglos2_out, 'siglos2_out')
    if gp.checksig and gp.stopstep <= 11:
        clf()
        #ansiglos = ga.sig_los(r0, gp)
        plot(r0, np.sqrt(siglos2_out), 'r.-', label='model')
        #plot(r0, ansiglos, 'b--', label='analytic')
        plot(gp.xipol, gp.dat.sig[pop], 'g.-', label='data')
        fill_between(gp.xipol, gp.dat.sig[pop]-gp.dat.sigerr[pop], gp.dat.sig[pop]+gp.dat.sigerr[pop], color='g', alpha=0.6)
        xscale('log')
        axvline(max(gp.xipol))
        axvline(min(gp.xipol))
        axvline(gp.Xscale[0], lw=2)
        xlabel('$r/\\rm{pc}$')
        ylabel('$\\sigma_{\\rm{LOS}}$')
        ylim([0,25])
        legend(loc='upper right')
        savefig('fit_siglos_out_'+gp.investigate+'.pdf')
        pdb.set_trace()

    if not gp.usekappa:
        kapl4s_out = np.ones(len(siglos2_out))
    if gp.usekappa:
        kapl4s_out = kappa(r0fine, Mrfine, nufine, sigr2nu_model, intbetasfine, gp)

    zetaa = -1; zetab = -1
    if gp.usezeta:
        zetaa, zetab = zeta(r0fine, nufine, \
                            Sigfine,\
                            Mrfine, betafine,\
                            sigr2nu_model, gp)

    gh.sanitize_vector(siglos2_out, len(r0), 0, 1e30, gp.debug)
    return siglos2_out, kapl4s_out, zetaa, zetab