def run_on_single_catalog(self, catalog_instance, catalog_name, output_dir): '''collect quantities and plot the relationship between velocity dispersion and halo mass''' if not catalog_instance.has_quantities([ 'halo_mass', 'halo_id', 'velocity_x', 'velocity_y', 'velocity_z', 'redshift' ]): return TestResult(skipped=True, summary='do not have needed quantities') #list containing each galaxy's larger cluster mass complete_mass = catalog_instance.get_quantities( 'halo_mass')['halo_mass'] #sort the complete_mass list #make a list of indices corresponding to halos that make the mass cut mass_indices = np.argsort(complete_mass) complete_mass = complete_mass[mass_indices] complete_mass = np.array(complete_mass) start_index = np.searchsorted(complete_mass, self.masscut) cut_indices = list(range(start_index, np.size(complete_mass))) #make a list of each galaxy's halo ID, sort it in same fashion as mass, and cut according to mass cut complete_id_list = catalog_instance.get_quantities( 'halo_id')['halo_id'] complete_id_list = complete_id_list[mass_indices] cut_id_list = complete_id_list[cut_indices] #sort the cut_id_list in increasing order and get the unique values to prepare for looping indexing_indices = np.argsort(cut_id_list) cut_id_list = cut_id_list[indexing_indices] unique_id_list = np.unique(cut_id_list) #make a list of masses that make the mass cut and are sorted in the same fashion as the id list cut_masses = complete_mass[cut_indices][indexing_indices] #make a list of galaxy masses, used to check galaxy mass and disregard any galaxies with low stellar masses stellar_masses = catalog_instance.get_quantities('stellar_mass') stellar_masses = stellar_masses['stellar_mass'][mass_indices][ cut_indices][indexing_indices] #list to contain velocity magnitudes of galaxies within a cluster vel_mag_list = np.array([]) #list to contain velocity dispersions of cluster galaxies vel_dispersion = np.array([]) #list to contain the masses of clusters to be plotted mass = np.array([]) #fetch and sort each velocity component for each galaxy according to the id list vx = catalog_instance.get_quantities('velocity_x') vx_list = vx['velocity_x'][mass_indices][cut_indices][indexing_indices] vy = catalog_instance.get_quantities('velocity_y') vy_list = vy['velocity_y'][mass_indices][cut_indices][indexing_indices] vz = catalog_instance.get_quantities('velocity_z') vz_list = vz['velocity_z'][mass_indices][cut_indices][indexing_indices] #Get a list of redshifts for each galaxy in the catalog, sorted according to the ID's redshifts = catalog_instance.get_quantities('redshift')['redshift'] redshifts = redshifts[mass_indices][cut_indices][indexing_indices] largest = 0 smallest = np.max(cut_masses) #list to contain redshifts of all galaxies within a particular cluster redshift_list = np.array([]) #list to contain representative redshift for each cluster (determined from galaxy redshifts) median_r = np.array([]) #galaxy counter and list to store number of galaxies in each cluster galaxy_num = 0 galaxy_num_list = np.array([]) #function used to calculate velocity dispersion def dispersion(val_array): if (self.disp_func == "biweight"): dis = stat.biweight_scale(val_array) else: dis = np.std(val_array) return dis #for each cluster above the mass cut for unique_id in unique_id_list: #find location of this cluster's galaxies in the list index = np.searchsorted(cut_id_list, unique_id) #add the cluster's mass to a list mass = np.append(mass, cut_masses[index]) #for every galaxy that is part of the same cluster, make list of velocity magnitudes, #galaxy counts, and redshifts while unique_id == cut_id_list[index]: if (stellar_masses[index] > self.stellarcut): vel_mag = np.sqrt( np.power(vx_list[index], 2) + np.power(vy_list[index], 2) + np.power(vz_list[index], 2)) vel_mag_list = np.append(vel_mag_list, vel_mag) redshift_list = np.append(redshift_list, redshifts[index]) galaxy_num += 1 index += 1 if (index == np.size(cut_id_list)): break #append each calculated value for the cluster to the proper list galaxy_num_list = np.append(galaxy_num_list, galaxy_num) mask_num = galaxy_num_list > 5 galaxy_num = 0 vel_dispersion = np.append(vel_dispersion, dispersion(vel_mag_list)) #use a representative, robust estimate of redshift for the whole cluster median_r = np.append(median_r, np.median(redshift_list)) #la = cut_masses[index-1]*(cosmo.H(np.median(redshift_list)).value/100) #sm = cut_masses[index-1]*(cosmo.H(np.median(redshift_list)).value/100) if (cut_masses[index - 1] * ((cosmo.H(np.median(redshift_list))).value / 100) > largest): largest = cut_masses[index - 1] * ( cosmo.H(np.median(redshift_list)).value / 100) if (cut_masses[index - 1] * ((cosmo.H(np.median(redshift_list))).value / 100) < smallest): smallest = cut_masses[index - 1] * ( cosmo.H(np.median(redshift_list)).value / 100) #reset lists to empty for the next iteration/cluster vel_mag_list = np.array([]) redshift_list = np.array([]) #fig, ax = plt.subplots(nrows=1,ncols=1) #make different plots depending on what you want the color axis to show x_axis = np.multiply(mass[mask_num], (cosmo.H(median_r[mask_num]).value / 100)) if self.truncate_cat_name: catalog_name = catalog_name.partition('_')[0] else: catalog_name + ' cluster' if (self.c_axis == 'number'): img = self.summary_ax.scatter(x_axis, vel_dispersion[mask_num], c=galaxy_num_list[mask_num], norm=LogNorm(), label=catalog_name) elif (self.c_axis == 'redshift'): img = self.summary_ax.scatter(x_axis, vel_dispersion[mask_num], c=median_r[mask_num], norm=LogNorm(), label=catalog_name) #save halo masses, normalized hubble parameters, and velocity dispersion of galaxies for each cluster self.mass_col = mass[mask_num] self.norm_h_col = cosmo.H(median_r[mask_num]).value / 100 self.vel_disp_col = vel_dispersion[mask_num] self.median_r_col = median_r[mask_num] self.galaxy_num_col = np.around(galaxy_num_list[mask_num], decimals=0) if (self.c_axis == 'number'): np.savetxt( os.path.join(output_dir, 'summary.txt'), np.c_[self.mass_col, self.norm_h_col, self.vel_disp_col, self.galaxy_num_col], fmt='%12.4e', header= 'HALO_MASS // CLUSTER_NORMALIZED_H // CLUSTER_VELOCITY_DISPERSION // CLUSTER_GALAXY_COUNT' ) elif (self.c_axis == 'redshift'): np.savetxt( os.path.join(output_dir, 'summary.txt'), np.c_[self.mass_col, self.norm_h_col, self.vel_disp_col, self.median_r_col], fmt='%12.4e', header= 'HALO_MASS // CLUSTER_NORMALIZED_H // CLUSTER_VELOCITY_DISPERSION // CLUSTER_GALAZY_COUNT' ) #make plot x = np.linspace(smallest * .75, largest * 1.5) self.summary_ax.plot( x, eval("1082*(x/10**15)**.3361*{:.2f}".format(self.convert_fof)), c="red", label="{:.2f}*(Evrard et. al. 2008)".format(self.convert_fof)) self.summary_ax.legend(loc='best', fontsize=self.legend_size) print(self.legend_size) bar = self.summary_fig.colorbar(img, ax=self.summary_ax) self.summary_ax.set_xscale('log') self.summary_ax.set_ylim( np.min(vel_dispersion[mask_num]) * .3, np.max(vel_dispersion[mask_num]) * 5) self.summary_ax.set_xlim(smallest * .75, largest * 1.5) self.summary_ax.set_yscale('log') self.summary_ax.set_xlabel(r'$h(z)M_{\rm FoF}\quad [M_{\odot}]$', size=self.font_size) self.summary_ax.set_ylabel(r'$\sigma_v\quad {\rm [km/s]}$', size=self.font_size) #label color axis depending on what you want to show if (self.c_axis == 'number'): bar.ax.set_ylabel('galaxies per cluster', size=self.font_size) else: bar.ax.set_ylabel('median redshift', size=self.font_size) plt.tight_layout() plt.savefig(os.path.join(output_dir, 'mass_virial_scaling.png')) plt.close() return TestResult(inspect_only=True)
def rhs(t, n): """ Calculate the RHS of the radiative transfer equations. RHS of the coupled nHII, n_HeII, n_HeIII and T equations. The equations are labelled as A,B,C, and D and the rest of the variables are the terms contained in the respective equations. Parameters ---------- t : float Time of evaluation in s. n : array-like 1-D array containing the variables nHII, nHeII, nHeIII, T for evaluating the RHS. Returns ------- array_like The RHS of the radiative transfer equations. """ if isnan(n[0]) or isnan(n[1]) or isnan(n[2]) or isnan(n[3]): print('Warning: calculations contain nan values, check the rhs') n_HIIx = n[0] n_HIx = n_H(zstar, C) - n[0] if isnan(n_HIIx): n_HIIx = n_H(zstar, C) n_HIx = 0 if n_HIIx > n_H(zstar, C): n_HIIx = n_H(zstar, C) n_HIx = 0 if n_HIIx < 0: n_HIIx = 0 n_HIx = n_H(zstar, C) n_HeIIx = n[1] n_HeIIIx = n[2] n_HeIx = n_He(zstar, C) - n[1] - n[2] if isnan(n_HeIIIx): n_HeIIIx = n_He(zstar, C) n_HeIIx = 0 n_HeIx = 0 if n_HeIIIx > n_He(zstar, C): n_HeIIIx = n_He(zstar, C) n_HeIIx = 0 n_HeIx = 0 if n_HeIIIx < 0: n_HeIIIx = 0 n_HeIIx = 0 n_HeIx = n_He(zstar, C) Tx = n[3] if isnan(Tx): print('Tx is nan') if (Tx < T_gamma.value * (1 + zstar) ** 1 / (1 + 250)): Tx = T_gamma.value * (1 + zstar) ** 1 / (1 + 250) n_ee = n_HIIx + n_HeIIx + 2 * n_HeIIIx mu = (n_H(zstar, C) + 4 * n_He(zstar, C)) / ( n_H(zstar, C) + n_He(zstar, C) + n_ee) n_B = n_H(zstar, C) + n_He(zstar, C) + n_ee A1_HI = xi_HI(Tx) * n_HIx * n_ee A1_HeI = xi_HeI(Tx) * n_HeIx * n_ee A1_HeII = xi_HeII(Tx) * n_HeIIx * n_ee A2_HII = eta_HII(Tx) * n_HIIx * n_ee A2_HeII = eta_HeII(Tx) * n_HeIIx * n_ee A2_HeIII = eta_HeIII(Tx) * n_HeIIIx * n_ee A3 = omega_HeII(Tx) * n_ee * n_HeIIIx A4_HI = psi_HI(Tx) * n_HIx * n_ee A4_HeI = psi_HeI(Tx, n_ee, n_HeIIx) * n_ee A4_HeII = psi_HeII(Tx) * n_HeIIx * n_ee A5 = theta_ff(Tx) * (n_HIIx + n_HeIIx + 4 * n_HeIIIx) * n_ee H = pl.H(zstar) H = H.to(u.s ** -1) A6 = (2 * H * kb * Tx * n_B / mu).value A = gamma_HI(n_HIIx, n_HeIx, n_HeIIx, n_HeIIIx, Tx, I1_HI, I2_HI, I3_HI, zstar,C, gamma_2c) * n_HIx - alpha_HII( Tx) * n_HIIx * n_ee B = gamma_HeI(n_HIIx, n_HeIx, n_HeIIx, n_HeIIIx, I1_HeI, I2_HeI, I3_HeI, zstar, C) * n_HeIx + beta_HeI( Tx) * n_ee * n_HeIx - beta_HeII(Tx) * n_ee * n_HeIIx - alpha_HeII( Tx) * n_ee * n_HeIIx + alpha_HeIII(Tx) * n_ee * n_HeIIIx - zeta_HeII( Tx) * n_ee * n_HeIIx Cc = gamma_HeII(I1_HeII) * n_HeIIx + beta_HeII( Tx) * n_ee * n_HeIIx - alpha_HeIII(Tx) * n_ee * n_HeIIIx Dd = (Tx / mu) * (-mu / (n_H(zstar, C) + n_He(zstar, C) + n_ee)) * (A + B + 2 * Cc) D = (2 / 3) * mu / (kb.value * n_B) * ( f_Heat(n_HIIx/n_H(zstar,C), zstar) * n_HIx * I1_T_HI + f_Heat(n_HIIx/n_H(zstar,C), zstar) * n_HeIx * I1_T_HeI + f_Heat( n_HIIx/n_H(zstar,C), zstar) * n_HeIIx * I1_T_HeII + sigma_s.value * n_ee / (m_e * c ** 2).value * ( I2_Ta + Tx * I2_Tb) - ( A1_HI + A1_HeI + A1_HeII + A2_HII + A2_HeII + A2_HeIII + A3 + A4_HI + A4_HeI + A4_HeII + A5 + A6)) + Dd
def rhs(t, n): """ Calculate the RHS of the radiative transfer equations. RHS of the coupled nHII, n_HeII, n_HeIII and T equations. The equations are labelled as A,B,C, and D and the rest of the variables are the terms contained in the respective equations. Parameters ---------- t : float Time of evaluation in s. n : array-like 1-D array containing the variables nHII, nHeII, nHeIII, T for evaluating the RHS. Returns ------- array_like The RHS of the radiative transfer equations. """ n_HIx = n_H(z_reion).value - n[0] n_HIIx = n[0] if n_HIx < 0: n_HIx = 0 n_HIIx = n_H(z_reion).value if n_HIIx > n_H(z_reion).value: n_HIIx = n_H(z_reion).value n_HIx = 0 if n_HIIx < 0: n_HIIx = 0 n_HIx = n_H(z_reion).value n_HeIx = n_He(z_reion).value - (n[1] + n[2]) n_HeIIx = n[1] n_HeIIIx = n[2] if n_HeIx > n_He(z_reion).value: n_HeIx = n_He(z_reion).value n_HeIIx = 0 n_HeIIIx = 0 if n_HeIx < 0: n_HeIx = 0 if n_HeIIx > n_He(z_reion).value: n_HeIIx = n_He(z_reion).value n_HeIx = 0 n_HeIIIx = 0 if n_HeIIx < 0: n_HeIIx = 0 if n_HeIIIx > n_He(z_reion).value: n_HeIIIx = n_He(z_reion).value n_HeIIx = 0 n_HeIx = 0 if n_HeIIIx < 0: n_HeIIIx = 0 Tx = n[3] n_ee = n_HIIx + n_HeIIx + 2 * n_HeIIIx mu = (n_H(z_reion).value + 4 * n_He(z_reion).value) / ( n_H(z_reion).value + n_He(z_reion).value + n_ee) n_B = n_H(z_reion).value + n_He(z_reion).value + n_ee A1_HI = xi_HI(Tx) * n_HIx * n_ee A1_HeI = xi_HeI(Tx) * n_HeIx * n_ee A1_HeII = xi_HeII(Tx) * n_HeIIx * n_ee A2_HII = eta_HII(Tx) * n_HIIx * n_ee A2_HeII = eta_HeII(Tx) * n_HeIIx * n_ee A2_HeIII = eta_HeIII(Tx) * n_HeIIIx * n_ee A3 = omega_HeII(Tx) * n_ee * n_HeIIIx A4_HI = psi_HI(Tx) * n_HIx * n_ee A4_HeI = psi_HeI(Tx, n_ee, n_HeIIx) * n_ee A4_HeII = psi_HeII(Tx) * n_HeIIx * n_ee A5 = theta_ff(Tx) * (n_HIIx + n_HeIIx + 4 * n_HeIIIx) * n_ee H = pl.H(zstar) H = H.to(u.s**-1) A6 = (2 * H * kb * Tx * u.K * n_B / mu).value A = gamma_HI(n_HIIx, n_HeIx, n_HeIIx, n_HeIIIx, Tx ) * n_HIx - alpha_HII(Tx) * n_HIIx * n_ee B = gamma_HeI( n_HIIx, n_HeIx, n_HeIIx, n_HeIIIx ) * n_HeIx + beta_HeI(Tx) * n_ee * n_HeIx - beta_HeII( Tx) * n_ee * n_HeIIx - alpha_HeII( Tx) * n_ee * n_HeIIx + alpha_HeIII( Tx) * n_ee * n_HeIIIx - zeta_HeII( Tx) * n_ee * n_HeIIx C = gamma_HeII(n_HIIx, n_HeIx, n_HeIIx, n_HeIIIx) * n_HeIIx + beta_HeII( Tx) * n_ee * n_HeIIx - alpha_HeIII( Tx) * n_ee * n_HeIIIx Dd = (Tx / mu) * ( -mu / (n_H(z_reion).value + n_He(z_reion).value + n_ee)) * (A + B + 2 * C) D = (2 / 3) * mu / (kb.value * n_B) * ( f_Heat(n_HIIx, z_reion) * n_HIx * I1_T_HI + f_Heat(n_HIIx, z_reion) * n_HeIx * I1_T_HeI + f_Heat(n_HIIx, z_reion) * n_HeIIx * I1_T_HeII + sigma_s.value * n_ee / (m_e * c**2).value * (I2_Ta + Tx * I2_Tb) - (A1_HI + A1_HeI + A1_HeII + A2_HII + A2_HeII + A2_HeIII + A3 + A4_HI + A4_HeI + A4_HeII + A5 + A6)) + Dd return ravel(array([A, B, C, D]))