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
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
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
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]
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]
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]
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]
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
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
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)
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)
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
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
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
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
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
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
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
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
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
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
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
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
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
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])
######################## 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)
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])
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