def disc_mock(gp): global K,C,D,F, zth, zp_kz, zmin, zmax, z0, z02 # Set up simple population here using analytic formulae: 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 = 3*gp.nipol zth = 1.* np.arange(nth) * (zmax-zmin)/(nth-1.) + zmin 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: nu_zth = np.exp(-zth/z0) # [1] Kz_zth = -(K*zth/np.sqrt(zth**2.+D**2.) + 2.0 * F * zth) if gp.adddarkdisc: DD = 600 # [pc] 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) # 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 sigzstar = gh.ipol(zth, sigzth, zstar) # > 0 ((IDL, Justin)) stellar velocity dispersion # assign [0,1] * maxsig ran2 = npr.normal(size=int(gp.ntracer[1-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) # no normalization to 1 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 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] # enforce observational cut on zmax: sel = (zstar < zmax) print('fraction of z<zmax selected elements: ', 1.*sum(sel)/(1.*len(sel))) z_dat = zstar[sel] vz_dat = vzstar[sel] # throw away velocities of value zero (unstable?): sel = (abs(vz_dat) > 0) print('fraction of vz_dat>0 selected elements: ', 1.*sum(sel)/(1.*len(sel))) z_dat = z_dat[sel] vz_dat = vz_dat[sel] # Calulate binned data (for plots/binned anal.). old way, linear spacings, no const #particles/bin binmin, binmax, z_dat_bin, sig_dat_bin, count_bin = gh.binsmooth(z_dat, vz_dat, \ zmin, zmax, gp.nipol, 0.) sig_dat_err_bin = sig_dat_bin / np.sqrt(count_bin) nu_dat_bin, count_bin = gh.bincount(z_dat, binmax) 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 only 1 pop, use 0 for all components binmin0 = binmin; binmax0 = binmax; z_dat_bin0 = z_dat_bin sig_dat_bin0 = sig_dat_bin; sig_dat_err_bin0 = sig_dat_err_bin nu_dat_bin0 = nu_dat_bin; nu_dat_err_bin0 = nu_dat_err_bin if gp.pops == 2: # enforce observational constraint on z<z_max 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 analysis): binmin2, binmax2, z_dat_bin2, sig_dat_bin2, count_bin2 = gh.binsmooth(z_dat2, vz_dat2, \ zmin, zmax, gp.nipol, 0.) sig_dat_err_bin2 = sig_dat_bin2 / np.sqrt(count_bin2) nu_dat_bin2, count_bin2 = gh.bincount(z_dat2, binmax2) 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 # CALCULATE PROPERTIES FOR ALL POP TOGETHER z_dat0 = np.hstack([z_dat, z_dat2]) vz_dat0 = np.hstack([vz_dat, vz_dat2]) # Calulate binned data (for plots/binned anal.). old way, linear spacings, no const #particles/bin binmin0, binmax0, z_dat_bin0, sig_dat_bin0, count_bin0 = gh.binsmooth(z_dat0, vz_dat0, \ zmin, zmax, gp.nipol, 0.) sig_dat_err_bin0 = sig_dat_bin0 / np.sqrt(count_bin0) # binmin, binmax, z_dat_bin = gh.bin_r_const_tracers(z_dat, gp.nipol) nu_dat_bin0, count_bin0 = gh.bincount(z_dat0, binmax0) nu_dat_err_bin0 = nu_dat_bin0 / np.sqrt(count_bin0) renorm0 = max(nu_dat_bin0) nu_dat_bin0 = nu_dat_bin0 / renorm0 nu_dat_err_bin0 = nu_dat_err_bin0 / renorm0 xip = np.copy(z_dat_bin0) # [pc] gp.dat.binmin = binmin0 gp.dat.rbin = xip gp.xipol = gp.dat.rbin gp.Rscale.append(D) # [pc] gp.Rscale.append(z0) # [pc] maxr = max(gp.dat.rbin) gp.xepol = np.hstack([gp.dat.rbin, 2*maxr, 4*maxr, 8*maxr]) gp.dat.binmax = binmax0 gp.dat.Mrdat = K*xip/np.sqrt(xip**2.+D**2.) / (2.0*np.pi*gu.G1__pcMsun_1km2s_2) gp.dat.Mrerr = gp.dat.Mrdat*nu_dat_err_bin/nu_dat_bin gp.dat.nu.append(nu_dat_bin0) # [Msun/pc^3], normalized to 1 at center gp.dat.nuerr.append(nu_dat_err_bin0) # [Msun/pc^3], normalized gp.dat.sig.append(sig_dat_bin0) # [km/s] gp.dat.sigerr.append(sig_dat_err_bin0)# [km/s] gp.dat.nu.append(nu_dat_bin) # [Msun/pc^3], normalized to 1 gp.dat.nuerr.append(nu_dat_err_bin) # [Msun/pc^3], normalized gp.dat.sig.append(sig_dat_bin) # [km/s] gp.dat.sigerr.append(sig_dat_err_bin) # [km/s] if gp.pops == 2: gp.Rscale.append(z02) # [pc] gp.dat.nu.append(nu_dat_bin2) # [Msun/pc^3], normalized to 1 gp.dat.nuerr.append(nu_dat_err_bin2) # [Msun/pc^3], normalized gp.dat.sig.append(sig_dat_bin2) # [km/s] gp.dat.sigerr.append(sig_dat_err_bin2)# [km/s] return gp.dat
def run(gp): global K, C, D, F, zth, zp_kz, zmin, zmax, z0, z02 # Set up simple population here using analytic formulae: zmin = 100.0 # [pc], first bin center zmax = 1300.0 # [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.0 * np.arange(nth) * (zmax - zmin) / (nth - 1.0) + zmin # [pc] bin centers z0 = 240.0 # [pc], scaleheight of first population z02 = 200.0 # [pc], scaleheight of second population D = 250.0 # [pc], scaleheight of all stellar tracers K = 1.65 F = 1.65e-4 C = 17.0 ** 2.0 # [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 Kz_zth = -(K * zth / np.sqrt(zth ** 2.0 + D ** 2.0) + 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.0 + DD ** 2.0) # 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) # 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[1 - 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) # [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 ran = npr.uniform(-1.0, 1.0, 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.0, 1, gp.ntracer[2 - 1]) # [1] vzstar2 = ran2 * sigzstar2 # [(km/2)^2] # enforce observational cut on zmax: sel = zstar < zmax print("fraction of z<zmax selected elements: ", 1.0 * sum(sel) / (1.0 * len(sel))) z_dat1 = zstar[sel] vz_dat1 = vzstar[sel] # throw away velocities of value zero (unstable?): sel = abs(vz_dat1) > 0 print("fraction of vz_dat>0 selected elements: ", 1.0 * sum(sel) / (1.0 * len(sel))) z_dat1 = z_dat1[sel] vz_dat1 = vz_dat1[sel] # Calulate binned data (for plots/binned anal.). old way, linear spacings, no const #particles/bin binmin1, binmax1, z_dat_bin1, sig_dat_bin1, count_bin1 = gh.binsmooth(z_dat1, vz_dat1, zmin, zmax, gp.nipol, 0.0) sig_dat_err_bin1 = np.sqrt(sig_dat_bin1) # Poisson errors nu_dat_bin1, nu_dat_err_bin1 = gh.bincount(z_dat1, binmax1) nu_dat_bin1 /= binmax1 - binmin1 nu_dat_err_bin1 /= binmax1 - binmin1 import gr_params gpr = gr_params.grParams(gp) if gpr.showplots: nuscaleb = nu_zth[np.argmin(np.abs(zth - z0))] plt.loglog(zth, nu_zth / nuscaleb, "b.-") nuscaler = nu_dat_bin1[np.argmin(np.abs(zth - z0))] plt.loglog(zth, nu_dat_bin1 / nuscaler, "r.-") # pdb.set_trace() Sig_dat_bin1 = np.cumsum(nu_dat_bin1) Sig_dat_err_bin1 = np.sqrt(Sig_dat_bin1) Mrdat1 = np.cumsum(Sig_dat_bin1) Mrerr1 = Mrdat1 * Sig_dat_err_bin1 / Sig_dat_bin1 scales = [[], [], []] scales[1].append(z0) # [pc] scales[1].append(Sig_dat_bin1[0]) scales[1].append(Mrdat1[-1]) scales[1].append(nu_dat_bin1[0]) scales[1].append(max(sig_dat_bin1)) # start analysis of "all stars" with only component 1, # append to it later if more populations required z_dat0 = z_dat1 # [pc] vz_dat0 = vz_dat1 # [km/s] if gp.pops == 2: # enforce observational constraints on z<z_max 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 analysis): binmin2, binmax2, z_dat_bin2, sig_dat_bin2, count_bin2 = gh.binsmooth( z_dat2, vz_dat2, zmin, zmax, gp.nipol, 0.0 ) sig_dat_err_bin2 = np.sqrt(sig_dat_bin2) # Poissonian errors nu_dat_bin2, nu_dat_err_bin2 = gh.bincount(z_dat2, binmax2) nu_dat_bin2 /= binmax2 - binmin2 nu_dat_err_bin2 /= binmax2 - binmin2 Sig_dat_bin2 = np.cumsum(nu_dat_bin2) Sig_dat_err_bin2 = np.sqrt(Sig_dat_bin2) Mrdat2 = np.cumsum(nu_dat_bin2) Mrerr2 = np.sqrt(Mrdat2) scales[2].append(z02) # [pc] scales[2].append(Sig_dat_bin2[0]) scales[2].append(Mrdat2[-1]) scales[2].append(nu_dat_bin2[0]) # normalize by max density of first bin, rather scales[2].append(max(sig_dat_bin2)) # calculate properties for all pop together with stacked values z_dat0 = np.hstack([z_dat1, z_dat2]) vz_dat0 = np.hstack([vz_dat1, vz_dat2]) # Calulate binned data (for plots/binned anal.). old way, linear spacings, no const #particles/bin binmin0, binmax0, z_dat_bin0, sig_dat_bin0, count_bin0 = gh.binsmooth(z_dat0, vz_dat0, zmin, zmax, gp.nipol, 0.0) sig_dat_err_bin0 = np.sqrt(sig_dat_bin0) # binmin, binmax, z_dat_bin = gh.bin_r_const_tracers(z_dat, gp.nipol) nu_dat_bin0, nu_dat_err_bin0 = gh.bincount(z_dat0, binmax0) nu_dat_bin0 /= binmax0 - binmin0 nu_dat_err_bin0 /= binmax0 - binmin0 Sig_dat_bin0 = np.cumsum(nu_dat_bin0) Sig_dat_err_bin0 = np.sqrt(Sig_dat_bin0) # renorm0 = max(nu_dat_bin0) xip = np.copy(z_dat_bin0) # [pc] Mrdat0 = K * xip / np.sqrt(xip ** 2.0 + D ** 2.0) / (2.0 * np.pi * gu.G1__pcMsun_1km2s_2) Mrerr0 = Mrdat0 * nu_dat_err_bin0 / nu_dat_bin0 scales[0].append(D) # [pc] scales[0].append(Sig_dat_bin0[0]) scales[0].append(Mrdat0[-1]) scales[0].append(nu_dat_bin0[0]) scales[0].append(max(sig_dat_bin0)) rmin = binmin0 / scales[0][0] # [pc] rbin = xip / scales[0][0] # [pc] rmax = binmax0 / scales[0][0] # [pc] # store parameters for output # normalized by scale values nudat = [] nudat.append(nu_dat_bin0 / scales[0][3]) # [Msun/pc^3] nudat.append(nu_dat_bin1 / scales[1][3]) if gp.pops == 2: nudat.append(nu_dat_bin2 / scales[2][3]) nuerr = [] nuerr.append(nu_dat_err_bin0 / scales[0][3]) # [Msun/pc^3] nuerr.append(nu_dat_err_bin1 / scales[1][3]) if gp.pops == 2: nuerr.append(nu_dat_err_bin2 / scales[2][3]) Mrdat = [] Mrdat.append(Mrdat0 / scales[0][2]) # [Msun] Mrdat.append(Mrdat1 / scales[1][2]) if gp.pops == 2: Mrdat.append(Mrdat2 / scales[2][2]) Mrerr = [] Mrerr.append(Mrerr0 / scales[0][2]) # [Msun] Mrerr.append(Mrerr1 / scales[1][2]) if gp.pops == 2: Mrerr.append(Mrerr2 / scales[2][2]) Sigdat = [] Sigdat.append(Sig_dat_bin0 / scales[0][1]) Sigdat.append(Sig_dat_bin1 / scales[1][1]) if gp.pops == 2: Sigdat.append(Sig_dat_bin2 / scales[2][1]) Sigerr = [] Sigerr.append(Sig_dat_err_bin0 / scales[0][1]) Sigerr.append(Sig_dat_err_bin1 / scales[1][1]) if gp.pops == 2: Sigerr.append(Sig_dat_err_bin2 / scales[2][1]) sigdat = [] sigdat.append(sig_dat_bin0 / scales[0][4]) # [km/s] sigdat.append(sig_dat_bin1 / scales[1][4]) if gp.pops == 2: sigdat.append(sig_dat_bin2 / scales[2][4]) sigerr = [] sigerr.append(sig_dat_err_bin0 / scales[0][4]) # [km/s] sigerr.append(sig_dat_err_bin1 / scales[1][4]) if gp.pops == 2: sigerr.append(sig_dat_err_bin2 / scales[2][4]) write_disc_output_files(rbin, rmin, rmax, nudat, nuerr, Sigdat, Sigerr, Mrdat, Mrerr, sigdat, sigerr, scales, gp) return gp.dat