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)
Example #2
0
                    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
Example #3
0
                    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]))