def sig_rz(z, zpars, tpars): # Mirror prior tparsu = abs(tpars) # dz = zpars[2]-zpars[1] # sig_Rz = np.zeros(gp.nipol) # sig_Rz[0] = tparsu[0] * dz / 2. # for i in range(1,gp.nipol): # sig_Rz[i] = sig_Rz[i-1] + tparsu[i] * dz # f = gp.ipol(zpars,sig_Rz,z) # Alternative here --> don't assume monotonic! f = gh.ipol(zpars, tparsu, z) return f
def rho_INTIPOL_Rho(r0, rho): # assume len(r) = 2*pnts, or at least pnts+4 pnts = len(r0)-1 # start with one missing bin, s.t. interpolation on sub-bin possible Rho = np.zeros(pnts) for i in range(pnts): xint = r0[i:] # [lunit] yint = np.zeros(len(xint)) for j in range(i+1,len(xint)): yint[j] = r0[j] * rho[j]/np.sqrt(r0[j]**2-r0[i]**2) # [munit/lunit^3] # extrapolating with 1:3 is linear only! two points (1,2) to work with! yint[0] = gh.ipol(xint[1:3], yint[1:3], xint[0]) # linear extrapolation # yint[0] = gh.ipol(xipol[1:3], yipol[1:3], xint[0], smooth=0.1) # higher smooth means lower sigmalos # yint[0] = gh.ipollog(xipol[1:3], yipol[1:3], xint[0]) # too jumpy # yint[0] = gh.ipol(xipol[1:4], yipol[1:4], xint[0]) # increase, still missing at high radii # yint[0] = gh.ipol(xipol[1:3],yipol[1:3],xint[0]*1.1) # overall increase, kappa off @ 0 and max # yint[0] = gh.ipol(xipol[1:3],yipol[1:3],xint[0])*0.5 # overall increase, but too high @ center # use other interpolation scheme # igi = InterpolatedUnivariateSpline(xint[1:5],yint[1:5]) # yint[0] = igi(xint[0]) # then fit polynomial on second half of radii ml = max(len(xint)/4,2) x = xint[-ml:] y = np.log(yint[-ml:]) polyhilo = np.polyfit(x,y,1) # integrate polynomial from r0 (up to max(r_data)) to infinity intpoly = int_poly_inf(r0[-1],polyhilo) # attention: can be that intpoly is negative, if rho[i+1] > rho[i] # and even that integration + intpoly < 0 in the wash for Rho[i] for the last bin # circumvent that by requesting intpoly in [0,infty[ if intpoly<0.: intpoly = 0. Rho[i] = 2.*(simps(yint, xint, even=gp.even) + intpoly) # [munit/lunit^2] # better: extrapolation using polynomes # surfden = gh.ipollog(r_tot[1:-1],surfden[1:-1],r_tot) # Rho[0] = gh.ipol(r0[1:3],Rho[1:3],[r0[0]]) # TODO: check that it's fine to disable # extrapolate to last 4 bins, which were neglected for sake of extrapolating yint[0] x = r0[-4:-1] # take values from half+some offset to last point known for Rho y = np.log(Rho[-3:]) # [log(munit/lunit^2)] polyhilo = np.polyfit(x,y,1) return np.hstack([Rho,np.exp(r0[-1:]*polyhilo[0]+polyhilo[1])])
def int_siglos2surf_old(pnts, r0, beta, nu, sigr2): tmp = np.zeros(pnts) for i in range(pnts): xint = r0[i:] # [pc] yint = (1-beta[i:]*(r0[i]/r0[i:])**2) # [1] yint = yint * nu[i:] * sigr2[i:] * r0[i:] # [munit/pc^2 (km/s)^2] yint = yint / np.sqrt(r0[i:]**2-r0[i]**2) # [munit/pc^3 (km/s)^2] yint[0] = gh.ipol(xint[1:3],yint[1:3],[xint[0]]) #-(xint[1]-xint[0])) tmp[i] = 2. * simps(yint, xint, even=gp.even) # [munit/pc^2 (km/s)^2] # tmp[0] = tmp[1] # crude approximation: first bin has same sigma_los2 as second bin # tmp[0] = gh.ipol(r_tot[1:],tmp[1:],r_tot[0]) # tmp[0] = 2.0/surfden[0]*nu_tot[0:]*sigma_tot[0:]*r_tot[0:]/r_tot[:]*rmin return tmp # [munit/pc^2 (km/s)^2]
def ant_kaplos4surf(r0, beta, nu, kapr4): pnts = len(r0)-1 tmp = np.zeros(pnts) for i in range(pnts): xint = r0[i:] # [pc] yint = g(r0[i:], r0[i], beta[i:]) # [1] yint = yint * nu[i:] * kapr4[i:] * r0[i:] # [munit/pc^2 (km/s)^4] yint = yint / np.sqrt(r0[i:]**2-r0[i]**2) # [munit/pc^3 (km/s)^4] # interpolate diverging bin, need 4 (sub)points to get 3rd order xipol = xint[0]+np.arange(4)*(xint[1]-xint[0])/4. dipol = beta[i]+np.arange(4)*(beta[i+1]-beta[i])/4. nuipol= nu[i]+np.arange(4)*(nu[i+1]-nu[i])/4. kapr4ipol = kapr4[i]+np.arange(4)*(kapr4[i+1]-kapr4[i])/4. yipol = g(xipol,r0[i],dipol)* nuipol\ * kapr4ipol * xipol / np.sqrt(xipol**2-r0[i]**2) yint[0] = gh.ipol(xipol[1:4],yipol[1:4],xint[0]) # yint[0] = gh.ipol(xint[1:3],yint[1:3],[xint[0]]) # -(xint[1]-xint[0])) # ^-- rather conservative, lower than above method by factor 0.6 # then fit polynomial on second half of radii ml = max(len(xint)/2,2) x = xint[-ml:] y = np.log(yint[-ml:]) polyhilo = np.polyfit(x,y, 1) # integrate polynomial from r0 (up to max(r_data)) to infinity intpoly = int_poly_inf(r0[-1],polyhilo) tmp[i] = 2. * (simps(yint, xint, even=gp.even) + intpoly) # [munit/pc^2 (km/s)^4] # extrapolate to last 4 bins x = r0[-4:-1] # take values from half+some offset to last point known for tmp y = np.log(tmp[-3:]) polyhilo = np.polyfit(x,y,1) # [munit/pc^2 (km/s)^4] return np.hstack([tmp,np.exp(r0[-1:]*polyhilo[0]+polyhilo[1])])
def disc_sim(): if not gp.investigate == 'sim': print('wrong file included') return gp.zpmin = -1 gp.zpmax = -1 #import all data from files if gp.importdata: z_nu1_raw,nu1_dat_raw,nu1_dat_err_raw = gh.readcoln(gp.files.nufiles[0]) z_sig1_raw,sig1_dat_raw,sig1_dat_err_raw = gh.readcoln(gp.files.sigfiles[0]) #z_surf_raw,surftot_dat_raw,surftot_dat_err_raw = gh.readcoln(gp.files.surfdenfiles[0]) z_surf_raw,surfbar_dat_raw,surfbar_dat_err_raw = gh.readcoln(gp.files.surfdenfiles[0]) z_surf_raw,surfdm_dat_raw,surfdm_dat_err_raw = gh.readcoln(gp.files.surfdenfiles[1]) selnu1 = (z_nu1_raw > 0) selsig1 = (z_sig1_raw > 0) selsurf = (z_surf_raw > 0) if gp.pops == 2: z_nu2_raw,nu2_dat_raw,nu2_dat_err_raw = gh.readcoln(gp.files.nufiles[1]) z_sig2_raw,sig2_dat_raw,sig2_dat_err_raw = gh.readcoln(gp.files.sigfiles[2]) selnu2 = (z_nu2_raw > 0) selsig2 = (z_sig2_raw > 0) # baryonic surface density gp.dat.Mx = z_surf_raw[selsurf]*1000. # [pc] gp.dat.Mdat = surfbar_dat_raw[selsurf] # [Msun/pc^2] gp.dat.Merr = surfbar_dat_err_raw[selsurf] # [Msun/pc^2] # total surface density gp.Mmodel = surftot_dat_raw[selsusrf] # [Msun/pc^2] Kz_zstar = -gp.Mmodel * (2.*np.pi*gp.G1) # should be kappa data (not sure whether this is necessary) gp.dat.densx = z_surf_raw[selsusrf]*1000. # [pc] gp.dat.densdat = phys.kappa(gp.dat.densx, Kz_zstar) #should be the total kappa, not sure about x array though gp.dat.denserr = gp.dat.densdat #not necessary for a certainty gp.dat.nux1 = z_nu1_raw[selnu1]*1000. # [pc] gp.dat.nudat1 = nu1_dat_raw[selnu1] gp.dat.nuerr1 = nu1_dat_err_raw[selnu1] gp.dat.sigx1 = z_sig1_raw[selsig1]*1000. gp.dat.sigdat1 = sig1_dat_raw[selsig1] gp.dat.sigerr1 = sig1_dat_err_raw[selsig1] if gp.pops == 2: gp.dat.nux2 = z_nu2_raw[selnu2]*1000. gp.dat.nudat2 = nu2_dat_raw[selnu2] gp.dat.nuerr2 = nu2_dat_err_raw[selnu2] gp.dat.sigx2 = z_sig2_raw[selsig2]*1000. gp.dat.sigdat2 = z_sig2_raw[selsig2] gp.dat.sigerr2 = z_sig2_raw[selsig2] gp.dat.output() gp.dat.save(gp.files.dir+'pp') # pickle return gp.dat else: # import simulation datapoints and calculate nu, sig zmin = 100. ; zmax = 1300. # [pc] zbinbndry = np.linspace(zmin, zmax, gp.nipol+1) # [pc] assuming linear spacing of bins zbinmin = zbinbndry[:-1] # [pc] zbinmax = zbinbndry[1:] # [pc] gp.xipol= zbinmin + (zbinmax-zbinmin)/2. # [pc] # Read in the data: mass, x_dat,y_dat,z_dat, vx_dat,vy_dat,vz_dat, pot_dat = gh.readcoln(gp.files.posvelfiles[0]) # assume units: Msun, 3*kpc, 3*km/s, [pot] <= last one not needed # [Dave] v is in units [100 km/s] <= not possible?! if max(mass) != min(mass): print('**** Multimass data not yet supported ****') exit(1) # change to [pc] x_dat *= 1000.; y_dat *= 1000.; z_dat *= 1000. # [pc] z_mean = np.sum(mass*z_dat)/np.sum(mass) # [pc] vz_mean = np.sum(mass*vz_dat)/np.sum(mass) # [km/s] # center on coordinate, if also negative z values read in if min(z_dat)<0: z_dat = z_dat - z_mean # [pc] vz_dat = vz_dat - vz_mean # [km/s] # Add errors: if gp.adderrors: # Assume normal errors for now: xerrfac = 10.0; yerrfac = 10.0; zerrfac = 10.0 vxerrfac = 10.0; vyerrfac = 10.0; vzerrfac = 10.0 x_dat_err = abs(x_dat/xerrfac) # [pc] y_dat_err = abs(y_dat/yerrfac) # [pc] z_dat_err = abs(z_dat/zerrfac) # [pc] vx_dat_err = abs(vx_dat/vxerrfac) # [km/s] vy_dat_err = abs(vy_dat/vyerrfac) # [km/s] vz_dat_err = abs(vz_dat/vzerrfac) # [km/s] x_dat = x_dat + npr.normal(-1.,1.,len(z_dat)) * x_dat_err # [pc] y_dat = y_dat + npr.normal(-1.,1.,len(z_dat)) * y_dat_err # [pc] z_dat = z_dat + npr.normal(-1.,1.,len(z_dat)) * z_dat_err # [pc] vx_dat = vx_dat + npr.normal(-1.,1.,len(z_dat)) * vx_dat_err # [km/s] vy_dat = vy_dat + npr.normal(-1.,1.,len(z_dat)) * vy_dat_err # [km/s] vz_dat = vz_dat + npr.normal(-1.,1.,len(z_dat)) * vz_dat_err # [km/s] # Cut on zmax, cut zero velocities TODO: why not allowing zero velocities? could be temporarily... sel = (z_dat < zmax) * (abs(vz_dat) > 0.) # [bool] z_dat = z_dat[sel] # [pc] vz_dat = vz_dat[sel] # [km/s] # determine sigma_v sig_dat_bin = np.zeros(gp.nipol) sig_dat_err_bin = np.zeros(gp.nipol) for i in range(gp.nipol): sel = (z_dat > zbinmin[i])*(z_dat < zbinmax[i]) # select bin vtemp = np.array(vz_dat[sel]) # [km/s] sig_dat_bin[i] = np.sqrt(np.mean(vtemp**2) - np.mean(vtemp)**2) # [km/s] sig_dat_err_bin[i] = sig_dat_bin[i]/(1.*np.sum(sel)) # [km/s] nu_dat_bin = np.zeros(gp.nipol) nu_dat_err_bin = np.zeros(gp.nipol) for i in range(gp.nipol): sel = (z_dat > zbinmin[i])*(z_dat < zbinmax[i]) # select bin nu_dat_bin[i] = 1.*np.sum(sel)/(1.*(zbinmax[i]-zbinmin[i])) # [1/tot. area/pc] nu_dat_err_bin[i] = nu_dat_bin[i] / np.sqrt(np.sum(sel)) # [1/tot. area/pc], Poisson distributed renorm = 1.*max(nu_dat_bin) # [1/tot.area/pc] nu_dat_bin = nu_dat_bin / renorm # [1] nu_dat_err_bin = nu_dat_err_bin / renorm # [1] # [TODO]: downsampling if needed if gp.pops == 2: mass2, x_dat2,y_dat2,z_dat2, vx_dat2,vy_dat2,vz_dat2, pot_dat2 = gh.readcoln(gp.files.posvelfiles[1]) if max(mass2) > min(mass2): print('**** Multimass data not yet supported ****') exit(1) # change to [pc] x_dat2 *= 1000.; y_dat2 *= 1000.; z_dat2 *= 1000. # [pc] z_mean2 = np.sum(mass2*z_dat2)/np.sum(mass2) # [pc] vz_mean2 = np.sum(mass2*vz_dat2)/np.sum(mass2) # [km/s] # center on coordinate, if also negative z values read in if min(z_dat2)<0: z_dat2 = z_dat2 - z_mean2 # [pc] vz_dat2 = vz_dat2 - vz_mean2 # [km/s] # Add errors: if gp.adderrors: # Assume normal errors for now: x_dat_err2 = abs(x_dat2/xerrfac) # [pc] y_dat_err2 = abs(y_dat2/yerrfac) # [pc] z_dat_err2 = abs(z_dat2/zerrfac) # [pc] vx_dat_err2 = abs(vx_dat2/vxerrfac) # [km/s] vy_dat_err2 = abs(vy_dat2/vyerrfac) # [km/s] vz_dat_err2 = abs(vz_dat2/vzerrfac) # [km/s] x_dat2 = x_dat2 + npr.normal(-1.,1.,len(z_dat2)) * x_dat_err2 # [pc] y_dat2 = y_dat2 + npr.normal(-1.,1.,len(z_dat2)) * y_dat_err2 # [pc] z_dat2 = z_dat2 + npr.normal(-1.,1.,len(z_dat2)) * z_dat_err2 # [pc] vx_dat2 = vx_dat2 + npr.normal(-1.,1.,len(z_dat2)) * vx_dat_err2 # [km/s] vy_dat2 = vy_dat2 + npr.normal(-1.,1.,len(z_dat2)) * vy_dat_err2 # [km/s] vz_dat2 = vz_dat2 + npr.normal(-1.,1.,len(z_dat2)) * vz_dat_err2 # [km/s] # Cut on zmax, cut zero velocities TODO: why not allowing zero velocities? could be temporarily... sel = (z_dat2 < zmax) * (abs(vz_dat2) > 0.) # [bool] z_dat2 = z_dat2[sel] # [pc] vz_dat2 = vz_dat2[sel] # [km/s] # determine sigma_v sig_dat_bin2 = np.zeros(gp.nipol) sig_dat_err_bin2 = np.zeros(gp.nipol) for i in range(gp.nipol): sel = (z_dat2 > zbinmin[i])*(z_dat2 < zbinmax[i]) # select bin vtemp = np.array(vz_dat2[sel]) # [km/s] sig_dat_bin2[i] = np.sqrt(np.mean(vtemp**2) - np.mean(vtemp)**2) # [km/s] sig_dat_err_bin2[i] = sig_dat_bin2[i]/(1.*np.sum(sel)) # [km/s] nu_dat_bin2 = np.zeros(gp.nipol) nu_dat_err_bin2 = np.zeros(gp.nipol) for i in range(gp.nipol): sel = (z_dat2 > zbinmin[i])*(z_dat2 < zbinmax[i]) # select bin nu_dat_bin2[i] = 1.*np.sum(sel)/(1.*(zbinmax[i]-zbinmin[i])) # [1/tot. area/pc] nu_dat_err_bin2[i] = nu_dat_bin2[i] / np.sqrt(np.sum(sel)) # [1/tot. area/pc], Poisson distributed renorm = 1.*max(nu_dat_bin2) # [1/tot.area/pc] nu_dat_bin2 /= renorm # [1] nu_dat_err_bin2 /= renorm # [1] # if gp.bprior: # Load the baryonic model: if gp.baryonmodel == 'silvia': zvis,sigexpvis,sigexpviserr,sigsecvis,sigsecviserr = gh.readcoln('/home/ast/user/jread/Data/Local_dm/Vis/Sigma_MM.txt') # [kpc, Msun/pc^2, Msun/pc^2, Msun/pc^2, Msun/pc^2] sigusevis = sigsecvis # [Msun/pc^2] siguseviserr = sigsecviserr # [Msun/pc^2] elif gp.baryonmodel == 'sim': zvis, sigusevis, siguseviserr = gh.readcol3(gp.files.surfdenfiles[0]) # [kpc, Msun/pc^2, Msun/pc^2] zvis *= 1000. # [pc] sigusevis = gh.ipol(zvis, sigusevis, gp.xipol) # interpolate to xipol radius array siguseviserr = gh.ipol(zvis, siguseviserr, gp.xipol) zvis = gp.xipol # [pc] # read in DM surface density zdm, sigusedm, sigusedmerr = gh.readcol3(gp.files.surfdenfiles[1]) # [kpc, Msun/pc^2, Msun/pc^2] zdm *= 1000. # [pc] sigusedm = gh.ipol(zdm, sigusedm, gp.xipol) # interpolate to xipol radius array sigusedmerr = gh.ipol(zdm, sigusedmerr, gp.xipol) zdm = gp.xipol # [pc] elif gp.baryonmodel == 'simple': zvis = gp.xipol # [pc] D = 250. # [pc] K = 1.65 # [TODO] sigusevis = K*zvis/sqrt(zvis**2.+D**2.) / (2.0*np.pi*G1) # [TODO] siguseviserr = sigusevis*0.01 # [TODO] # baryonic surface density, really a Sigma gp.dat.Mx = gp.xipol # [pc] gp.dat.Mdat = sigusevis # [Msun/pc^2] gp.dat.Merr = siguseviserr # [Msun/pc^2] # total surface density (same z array as baryonic) gp.Mmodel = sigusevis + sigusedm # [Msun/pc^2] Kz_zstar = -gp.Mmodel * (2.*np.pi*gp.G1) # [1000/pc (km/s)^2] # should be kappa data (not sure whether this is necessary) gp.dat.densx = gp.xipol # [pc] gp.dat.densdat = phys.kappa(gp.dat.densx, Kz_zstar) # [TODO] gp.dat.denserr = gp.dat.densdat/100. # [TODO] gp.dat.nux1 = gp.xipol # [pc] gp.dat.nudat1 = nu_dat_bin # [Msun/pc^3] gp.dat.nuerr1 = nu_dat_err_bin # [Msun/pc^3] gp.dat.sigx1 = gp.xipol # [pc] gp.dat.sigdat1 = sig_dat_bin # [km/s] gp.dat.sigerr1 = sig_dat_err_bin # [km/s] if gp.pops == 2: gp.dat.nux2 = gp.xipol # [pc] gp.dat.nudat2 = nu_dat_bin2 # [Msun/pc^3] gp.dat.nuerr2 = nu_dat_err_bin2 # [Msun/pc^3] gp.dat.sigx2 = gp.xipol # [pc] gp.dat.sigdat2 = sig_dat_bin2 # [km/s] gp.dat.sigerr2 = sig_dat_err_bin2 # [km/s] gp.dat.output() gp.dat.save(gp.files.dir+'pp') # pickle return gp.dat
def get_prof(prof, pop, gp): zmin = 100. # [pc], first bin center zmax = 1300. # [pc], last bin center # get Stuetzpunkte for theoretical profiles (not yet stars, finer spacing in real space) nth = gp.nipol # [1] number of bins zth = 1.* np.arange(nth) * (zmax-zmin)/(nth-1.) + zmin # [pc] bin centers z0 = 240. # [pc], scaleheight of first population z02 = 200. # [pc], scaleheight of second population D = 250. # [pc], scaleheight of all stellar tracers K = 1.65 F = 1.65e-4 C = 17.**2. # [km/s] integration constant in sig # Draw mock data from exponential disk: nu_zth = np.exp(-zth/z0) # [nu0] = [Msun/A/pc] 3D tracer density if prof == 'nu' and pop==1: return zth, nu_zth Kz_zth = -(K*zth/np.sqrt(zth**2.+D**2.) + 2.0 * F * zth) if gp.adddarkdisc: DD = 600 # [pc] scaleheight of dark disc KD = 0.15 * 1.650 Kz_zth = Kz_zth - KD*zth/np.sqrt(zth**2. + DD**2.) # calculate sig_z^2 inti = np.zeros(nth) for i in range(1, nth): inti[i] = simps(Kz_zth[:i]*nu_zth[:i], zth[:i]) sigzth = np.sqrt((inti + C) / nu_zth) if prof == 'sig' and pop == 1: return zth, sigzth # project back to positions of stars ran = npr.uniform(size=int(gp.ntracer[1-1])) # [1] #zstar = -z0 * np.log(1.0 - ran) # [pc] stellar positions, exponential falloff #sigzstar = gh.ipol(zth, sigzth, zstar) # > 0 ((IDL, Justin)) stellar velocity dispersion # assign [0,1] * maxsig ran2 = npr.normal(size=int(gp.ntracer[2-1])) # [1] #vzstar = ran2 * sigzstar # [km/s] # Add second population [thick-disc like]: if gp.pops == 2: nu_zth2 = gp.ntracer[2-1]/gp.ntracer[1-1]*np.exp(-zth/z02) if prof == 'nu' and pop == 2: return zth, nu_zth2 # [nu0,2] = [Msun/A/pc], 3D tracer density, exponentially falling # no normalization to 1 done here inti = np.zeros(nth) for i in range(1, nth): inti[i] = simps(Kz_zth[:i]*nu_zth2[:i], zth[:i]) sigzth2 = np.sqrt((inti + C) / nu_zth2) # same integration constant if prof == 'sig' and pop == 2: return zth, sigzth2 ran = npr.uniform(-1., 1., gp.ntracer[2-1]) # [1] zstar2 = -z02 * np.log(1.0 - ran) # [pc] #zstarobs = np.hstack([zstar, zstar2]) # concat pop1, pop2 for all stars sigzstar2 = gh.ipol(zth, sigzth2, zstar2) ran2 = npr.normal(-1., 1, gp.ntracer[2-1]) # [1] vzstar2 = ran2 * sigzstar2 # [(km/2)^2]
def sigmaz(zp, kzpars, nupars, norm, tpars, tparsR): # calculate density and Kz force: nu_z = nupars / np.max(nupars) # normalized to 1 # kz_z = kz(zp,zp,kzpars,blow,quadratic) # TODO: reenable kz_z = kzpars # add tilt correction [if required]: if gp.deltaprior: Rsun = tparsR[0] hr = tparsR[1] hsig = tparsR[2] tc = sigma_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.0) * (zr ** 3.0 - zl ** 3.0) + ((a - b) / (2.0 * zz) * (q - (p - q) * zl / zz) + (p - q) / (2.0 * zz) * (b - (a - b) * zl / zz)) * (zr ** 2.0 - zl ** 2.0) + (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.0 * b * h - a) / 2.0 / h ** 2.0 ad = fd0 bd = (fd1 - ad) / h cd = (fd2 - 2.0 * bd * h - ad) / 2.0 / h ** 2.0 AA = a * bd + ad * b BB = c * ad + cd * a CC = b * cd + bd * c z1d = z1 - z0 z2d = z1 ** 2.0 - z0 ** 2.0 z3d = z1 ** 3.0 - z0 ** 3.0 z4d = z1 ** 4.0 - z0 ** 4.0 z5d = z1 ** 5.0 - z0 ** 5.0 intbit = ( z1d * (a * ad - z0 * (AA - BB * z1) + z0 ** 2.0 * (b * bd - CC * z1) + c * cd * z0 ** 2.0 * z1 ** 2.0) + z2d * ( 0.5 * (AA - BB * z1) - z0 * (b * bd - CC * z1) - z0 / 2.0 * BB + z0 ** 2.0 / 2.0 * CC - (z0 * z1 ** 2.0 + z0 ** 2.0 * 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.0 + z0 ** 2.0 + 4.0 * z0 * z1) ) + z4d * (1.0 / 4.0 * CC - c * cd / 2.0 * (z1 + z0)) + z5d * c * cd / 5.0 ) sigint[i] = sigint[i - 1] + intbit if i == len(zp) - 2: # Deal with very last bin: z1d = z2 - z1 z2d = z2 ** 2.0 - z1 ** 2.0 z3d = z2 ** 3.0 - z1 ** 3.0 z4d = z2 ** 4.0 - z1 ** 4.0 z5d = z2 ** 5.0 - z1 ** 5.0 intbit = ( z1d * (a * ad - z0 * (AA - BB * z1) + z0 ** 2.0 * (b * bd - CC * z1) + c * cd * z0 ** 2.0 * z1 ** 2.0) + z2d * ( 0.5 * (AA - BB * z1) - z0 * (b * bd - CC * z1) - z0 / 2.0 * BB + z0 ** 2.0 / 2.0 * CC - (z0 * z1 ** 2.0 + z0 ** 2.0 * 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.0 + z0 ** 2.0 + 4.0 * z0 * z1) ) + z4d * (1.0 / 4.0 * CC - c * cd / 2.0 * (z1 + z0)) + z5d * c * cd / 5.0 ) sigint[i + 1] = sigint[i] + intbit if gp.qtest: nu_z = nupars pnts = 5000 zmin = min(zp) zmax = max(zp) z = dindgen(pnts) * (zmax - zmin) / double(pnts - 1) + zmin # kz_z = kz(z,zp,kzpars,blow) sigint_th = np.zeros(pnts) for i in range(1, pnts): sigint_th[i] = simps(Kz_z[:i] * nu_z[:i], z[:i]) if gp.quadratic: # TODO: quadratic test = gh.ipol(zp, sigint, z) else: test = gh.ipol(zp, sigint, z) gpl.plot(z, sigint_th) gpl.plot(zp, sigint, color=2) gpl.plot(z, test, color=4) gpl.show() sig_z_t2 = 1.0 / nu_z * (sigint + norm) # TODO: try to fit without.. return np.sqrt(sig_z_t2)
def kz(z_in, zpars, kzpars, blow): # Mirror prior # TODO: baryon minimum prior [blow]: # kzparsu = abs(kzpars) # Assume here interpolation between dens "grid points", # [linear or quadratic]. The grid points are stored # in kzpars and give the *differential* increase in # dens(z) towards small z [monotonic dens-prior]: # denarr = np.zeros(gp.nipol) # denarr[0] = kzparsu[0] # for i in range(1,len(kzparsu)): # denarr[i] = denarr[i-1] + kzparsu[i] # denarr = denarr[::-1] # override previous statements: use dens parameter directly, so denarr is really given by denarr = kzpars # Solve interpolated integral for Kz: if not gp.quadratic: # Linear interpolation here: kz_z = np.zeros(gp.nipol) for i in range(1, gp.nipol): zl = zpars[i - 1] zr = zpars[i] zz = zr - zl b = denarr[i - 1] a = denarr[i] kz_z[i] = kz_z[i - 1] + (a - b) / 2.0 / zz * (zr ** 2.0 - zl ** 2.0) + b * zr - a * zl else: # Quadratic interpolation here: kz_z = np.zeros(gp.nipol) for i in range(1, gp.nipol - 1): z0 = zpars[i - 1] z1 = zpars[i] z2 = zpars[i + 1] f0 = denarr[i - 1] f1 = denarr[i] f2 = denarr[i + 1] h = z2 - z1 a = f0 b = (f1 - a) / h c = (f2 - 2.0 * b * h - a) / 2.0 / h ** 2.0 z1d = z1 - z0 z2d = z1 ** 2.0 - z0 ** 2.0 z3d = z1 ** 3.0 - z0 ** 3.0 intbit = (a - b * z0 + c * z0 * z1) * z1d + (b / 2.0 - c / 2.0 * (z0 + z1)) * z2d + c / 3.0 * z3d kz_z[i] = kz_z[i - 1] + intbit if i == n_elements(zpars) - 2: # Deal with very last bin: z1d = z2 - z1 z2d = z2 ** 2.0 - z1 ** 2.0 z3d = z2 ** 3.0 - z1 ** 3.0 intbit = (a - b * z0 + c * z0 * z1) * z1d + (b / 2.0 - c / 2.0 * (z0 + z1)) * z2d + c / 3.0 * z3d kz_z[i + 1] = kz_z[i] + intbit if gp.qtest: pnts = 5000 zmin = min(zpars) zmax = max(zpars) z = np.arange(pnts) * (zmax - zmin) / (pnts - 1.0) + zmin if not gp.quadratic: denarr_z = gh.ipol(zpars, denarr, z) # # TODO: assure linear interpolation? see IDL help else: denarr_z = gh.ipol(zpars, denarr, z) # # TODO: assure only quadratic interpolation kz_th = np.zeros(pnts) for i in range(1, pnts): kz_th[i] = simps(denarr_z[:i], z[:i]) if gp.quadratic: test = gh.ipol(zpars, kz_z, z) # # TODO: assure quadratic interpolation else: test = gh.ipol(zpars, kz_z, z) testsimp = np.zeros(len(zpars)) delta_z = zpars[2] - zpars[1] for i in range(1, len(zpars)): testsimp[i] = testsimp[i - 1] + denarr[i] * delta_z gpl.plot(z, kz_th) gpl.plot(zpars, kz_z) gpl.plot(z, test) gpl.plot(zpars, testsimp) gpl.show() kz_out = kz_z # + blow # let blow alone, take overall Kz # Then interpolate back to the input array: # if not gp.quadratic: # kz_out = gh.ipol(zpars,kz_z,z_in) # # TODO: assure linear interpolation # else: # kz_out = gh.ipol(zpars,kz_z,z_in) # # TODO: quadratic! # Error checking. Sometimes when kz_z(0) << kz_z(1), # the interpolant can go negative. This just means that # we have resolved what should be kz_z(0) = 0. A simple # fix should suffice: for jj in range(0, len(kz_out)): if kz_out[jj] < 0: kz_out[jj] = 0.0 return kz_out
def nu_decrease(z, zpars, pars): parsu = abs(pars) # # Mirror prior if gp.monotonic: rnuz_z = np.zeros(len(zpars)) rnuz_z[0] = parsu[0] for i in range(1, len(rnuz_z)): rnuz_z[i] = rnuz_z[i - 1] + parsu[i] fun = rnuz_z[::-1] else: # Alternative here --> don't assume monotonic! fun = parsu # Normalise: if not gp.quadratic: # Exact linear interpolation integral: norm_nu = 0.0 for i in range(len(zpars) - 1): zl = zpars[i] zr = zpars[i + 1] zz = zr - zl b = fun[i] a = fun[i + 1] norm_nu = norm_nu + (a - b) / 2.0 / zz * (zr ** 2.0 - zl ** 2.0) + b * zr - a * zl else: if gp.qtest: gpl.plot(zpars, pars) test = gh.ipol(zpars, pars, z) gpl.plot(z, test, psym=3, color=2) # Exact quadratic interpolation: norm_nu = 0.0 for i in range(1, len(zpars) - 1): z0 = zpars[i - 1] z1 = zpars[i] z2 = zpars[i + 1] f0 = fun[i - 1] f1 = fun[i] f2 = fun[i + 1] h = z2 - z1 a = f0 b = (f1 - a) / h c = (f2 - 2.0 * b * h - a) / 2.0 / h ** 2.0 z1d = z1 - z0 z2d = z1 ** 2.0 - z0 ** 2.0 z3d = z1 ** 3.0 - z0 ** 3.0 if i == len(zpars) - 2: # Last bin integrate from z0 --> z2: z1d = z2 - z0 z2d = z2 ** 2.0 - z0 ** 2.0 z3d = z2 ** 3.0 - z0 ** 3.0 intquad = (a - b * z0 + c * z0 * z1) * z1d + (b / 2.0 - c / 2.0 * (z0 + z1)) * z2d + c / 3.0 * z3d norm_nu = norm_nu + intquad if gp.qtest: print i, h, intquad testy = a + b * (z - z0) + c * (z - z0) * (z - z1) if i != len(zpars) - 3: sel = z > z0 and z < z1 zcut = z[sel] tcut = testy[sel] else: sel = z > z0 and z < z2 zcut = z[sel] tcut = testy[sel] if gp.qtest: gpl.plot(zcut, tcut, psym=3, color=4) print "qtest: will stop" print simps(test, z), norm_nu exit(1) fun /= norm_nu # Interpolate to input z: if not gp.quadratic: f = gh.ipol(zpars, fun, z) else: f = gh.ipol(zpars, fun, z) # TODO: assure quadratic interpolation # Check for negative density: sel = f > 0 small = min(f[sel]) for jj in range(len(f)): if f[jj] < 0: f[jj] = small return f
def get_prof(prof, pop, gp): zmin = 100. # [pc], first bin center zmax = 1300. # [pc], last bin center # get Stuetzpunkte for theoretical profiles (not yet stars, finer spacing in real space) nth = gp.nipol # [1] number of bins zth = 1. * np.arange(nth) * (zmax - zmin) / (nth - 1.) + zmin # [pc] bin centers z0 = 240. # [pc], scaleheight of first population z02 = 200. # [pc], scaleheight of second population D = 250. # [pc], scaleheight of all stellar tracers K = 1.65 F = 1.65e-4 C = 17.**2. # [km/s] integration constant in sig # Draw mock data from exponential disk: nu_zth = np.exp(-zth / z0) # [nu0] = [Msun/A/pc] 3D tracer density if prof == 'nu' and pop == 1: return zth, nu_zth Kz_zth = -(K * zth / np.sqrt(zth**2. + D**2.) + 2.0 * F * zth) if gp.adddarkdisc: DD = 600 # [pc] scaleheight of dark disc KD = 0.15 * 1.650 Kz_zth = Kz_zth - KD * zth / np.sqrt(zth**2. + DD**2.) # calculate sig_z^2 inti = np.zeros(nth) for i in range(1, nth): inti[i] = simps(Kz_zth[:i] * nu_zth[:i], zth[:i]) sigzth = np.sqrt((inti + C) / nu_zth) if prof == 'sig' and pop == 1: return zth, sigzth # project back to positions of stars ran = npr.uniform(size=int(gp.ntracer[1 - 1])) # [1] #zstar = -z0 * np.log(1.0 - ran) # [pc] stellar positions, exponential falloff #sigzstar = gh.ipol(zth, sigzth, zstar) # > 0 ((IDL, Justin)) stellar velocity dispersion # assign [0,1] * maxsig ran2 = npr.normal(size=int(gp.ntracer[2 - 1])) # [1] #vzstar = ran2 * sigzstar # [km/s] # Add second population [thick-disc like]: if gp.pops == 2: nu_zth2 = gp.ntracer[2 - 1] / gp.ntracer[1 - 1] * np.exp(-zth / z02) if prof == 'nu' and pop == 2: return zth, nu_zth2 # [nu0,2] = [Msun/A/pc], 3D tracer density, exponentially falling # no normalization to 1 done here inti = np.zeros(nth) for i in range(1, nth): inti[i] = simps(Kz_zth[:i] * nu_zth2[:i], zth[:i]) sigzth2 = np.sqrt((inti + C) / nu_zth2) # same integration constant if prof == 'sig' and pop == 2: return zth, sigzth2 ran = npr.uniform(-1., 1., gp.ntracer[2 - 1]) # [1] zstar2 = -z02 * np.log(1.0 - ran) # [pc] #zstarobs = np.hstack([zstar, zstar2]) # concat pop1, pop2 for all stars sigzstar2 = gh.ipol(zth, sigzth2, zstar2) ran2 = npr.normal(-1., 1, gp.ntracer[2 - 1]) # [1] vzstar2 = ran2 * sigzstar2 # [(km/2)^2]
def disc_simple(): # trick to speed up things considerably, after first data generated, if zpnts > 50 (or other low number) # gp.dat.load(gp.files.dir+'pp') # return gp.dat # Draw mock data: nu_zth = np.exp(-zth/z0) # [1] Kz_zth = -(K*zth/np.sqrt(zth**2.+D**2.) + 2.0 * F * zth) # [TODO] if gp.adddarkdisc: # False DD = 600 # [pc] KD = 0.15 * 1.650 # [TODO] Kz_zth = Kz_zth - KD*zth/np.sqrt(zth**2.+DD**2.) # [TODO] inti = np.zeros(zpnts) for i in range(1,zpnts): inti[i] = simps(Kz_zth[:i]*nu_zth[:i],zth[:i]) sigzth = np.sqrt((inti + C) / nu_zth) nstars = 10000. # [1] ran = npr.uniform(size=int(nstars)) # [1] zstar = -z0 * np.log(1.0 - ran) # [pc] sigzstar = gh.ipol(zth,sigzth,zstar) # > 0 #selection? no, IDL GT means ">", so perhaps '>' is a shift ran2 = npr.normal(size=int(nstars)) # [1] vzstar = ran2 * sigzstar # [TODO] # Add second population [thick-disc like]: fac2 = 1. if gp.pops == 2: nu_zth2 = fac2*np.exp(-zth/z02) inti = np.zeros(zpnts) for i in range(1,zpnts): inti[i] = simps(Kz_zth[:i]*nu_zth2[:i],zth[:i]) sigzth2 = np.sqrt((inti + C) / nu_zth2) nstars2 = nstars*fac2 # [1] ran = npr.uniform(-1.,1.,nstars2) # [1] zstar2 = -z02 * np.log(1.0 - ran) # [pc] # zstar = [zstar,zstar2] sigzstar2 = gh.ipol(zth,sigzth2,zstar2) # TODO: > 0? ran2 = npr.normal(-1.,1,nstars2) # [1] vzstar2 = ran2 * sigzstar2 # [(km/2)^2] # Cut on zmax: # z_dat = [zstar((zstar < zmax)),zstar2((zstar2 < zmax))] # vz_dat = [vzstar((zstar < zmax)),vzstar2((zstar2 < zmax))] sel = (zstar < zmax) z_dat = zstar[sel]; vz_dat = vzstar[sel] # Cut zero velocities: sel = (abs(vz_dat) > 0) z_dat = z_dat[sel]; vz_dat = vz_dat[sel] # Calulate binned data (for plots/binned anal.): index = np.argsort(z_dat) z_dat_bin, sig_dat_bin, count_bin = binsmoo(z_dat[index], vz_dat[index], zmin, zmax, gp.nipol, 0.) sig_dat_bin = np.sqrt(sig_dat_bin) sig_dat_err_bin = sig_dat_bin / np.sqrt(count_bin) z_dat_bin, nu_dat_bin, count_bin = bincou(z_dat[index], zmin, zmax, gp.nipol) print(nu_dat_bin) nu_dat_err_bin = nu_dat_bin / np.sqrt(count_bin) renorm = max(nu_dat_bin) nu_dat_bin = nu_dat_bin / renorm nu_dat_err_bin = nu_dat_err_bin / renorm if gp.pops == 2: sel = (zstar2 < zmax) z_dat2 = zstar2[sel]; vz_dat2 = vzstar2[sel] # Cut zero velocities: sel = (abs(vz_dat2) > 0) z_dat2 = z_dat2[sel]; vz_dat2 = vz_dat2[sel] # Calulate binned data (for plots/binned anal.): index2 = np.argsort(z_dat2) z_dat_bin2, sig_dat_bin2, count_bin2 = binsmoo(z_dat2[index2],vz_dat2[index2],zmin,zmax,gp.nipol,0.) sig_dat_bin2 = np.sqrt(sig_dat_bin2) sig_dat_err_bin2 = sig_dat_bin2 / np.sqrt(count_bin2) z_dat_bin2, nu_dat_bin2, count_bin2 = bincou(z_dat2[index2], zmin, zmax, gp.nipol) nu_dat_err_bin2 = nu_dat_bin2 / np.sqrt(count_bin2) renorm2 = max(nu_dat_bin2) # normalize by max density of first bin, rather nu_dat_bin2 = nu_dat_bin2 / renorm2 nu_dat_err_bin2 = nu_dat_err_bin2 / renorm2 if not gp.uselike: sel = (z_dat_bin>0) xip = z_dat_bin[sel] # [pc] gp.dat.Mx = xip # [pc] gp.dat.Mdat = K*xip/np.sqrt(xip**2.+D**2.) / (2.0*np.pi*gp.G1) gp.dat.Merr = gp.dat.Mdat*nu_dat_err_bin/nu_dat_bin gp.Mmodel = (K*xip/np.sqrt(xip**2.+D**2.)+2.*F*xip) / (2.0*np.pi*gp.G1) Kz_zstar = -(K*xip/np.sqrt(xip**2.+D**2.) + 2.0 * F * xip) if gp.adddarkdisc: DD = 0.6 KD = 0.15 * 1.650 Kz_zstar = Kz_zstar - KD*zstar/np.sqrt(xip**2.+DD**2.) # [TODO] gp.dat.densx = xip # TODO: needed somewhere? gp.dat.densdat = -Kz_zstar/(2.*np.pi*gp.G1) # TODO: stellar surface density, store elsewhere gp.dat.denserr = gp.dat.densdat * nu_dat_err_bin/nu_dat_bin gp.dat.nux1 = xip gp.dat.nudat1 = nu_dat_bin[sel] gp.dat.nuerr1 = nu_dat_err_bin[sel] gp.dat.sigx1 = xip gp.dat.sigdat1 = sig_dat_bin[sel] gp.dat.sigerr1 = sig_dat_err_bin[sel] if gp.pops == 2: gp.dat.nux2 = xip gp.dat.nudat2 = nu_dat_bin2[sel] gp.dat.nuerr2 = nu_dat_err_bin2[sel] gp.dat.sigx2 = xip gp.dat.sigdat2 = sig_dat_bin2[sel] gp.dat.sigerr2 = sig_dat_err_bin2[sel] # gp.dat.output() gp.dat.save(gp.files.dir+'pp') # pickle return gp.dat
def get_kzpars(): Kz_zthd = -2.0 * F * zth # [with pc] Sigz_zth = abs(Kz_zthd) / (2.0*np.pi*gp.G1) denth = gh.derivcoarse(Sigz_zth,zth) kzpars = gh.ipol(zth,abs(denth),gp.xipol)*(2.0*np.pi*gp.G1) return kzpars