Exemplo n.º 1
0
def DataSummary(Mrcut=18, observables=['ssfr']): 
    ''' Summary statistics of the data. In our case that is the 
    SSFR distribution of the SDSS group catalog.
    '''
    obvs = []
    if 'ssfr' in observables:
        # Group Catalog object
        groupcat = GroupCat(Mrcut=Mrcut, position='central')
        # SSFR distribution of group catalog
        bins, dist = groupcat.Ssfr()   
        obvs.append([np.array(bins), np.array(dist)])
    if 'fqz03' in observables: 
        qfrac = Fq()
        M_bin = np.array([9.7, 10.1, 10.5, 10.9, 11.3])
        M_mid = 0.5 * (M_bin[:-1] + M_bin[1:])
        fq_model = qfrac.model(M_mid, 0.3412, lit='wetzel')
        obvs.append([M_mid, fq_model])
    if 'fqz_multi' in observables: 
        qfrac = Fq()
        M_bin = np.array([9.7, 10.1, 10.5, 10.9, 11.3])
        M_mid = 0.5 * (M_bin[:-1] + M_bin[1:])
        
        fq_out = [M_mid]
        for zz in [0.0502, 0.1581, 0.3412, 1.0833]: 
            fq_model = qfrac.model(M_mid, zz, lit='wetzel')
            fq_out += [fq_model]

        obvs.append(fq_out)
    
    if len(observables) == 1: 
        obvs = obvs[0]
    return obvs
def _getPq(ancestor, descendant, succession=None, will=None, pq_prop=None, sfr_prop=None):
    '''' Calculate the quenching probability for Star-Forming ancestor galaxies
    in the ancestor CGPop object. The quenching probability is calculated using 

    P_Q = ( f_Q(Mf,zf) - f_Q(M0,z0) ) / (1 - f_Q(M0,z0)) + Offset_P_Q
    
    where Offset_P_Q is a fudge factor dictated by nuisance parameters described 
    by pq_prop. 
    
    Parameters
    ----------
    pq_prop : dict
        Quenching properties dictionary. Keywords are 'slope' and 'yint' which
        describes the offset to the quenchign probability. The quenchign probability 
        is fudged around to match the observed quenching fraction at z_final: 
        fQ(M*, z_final). 

    Returns
    -------
    P_q : array
        Array that specifies the quenching probabilities for the SF ancestor 
        galaxies. 
    '''
    z_final = descendant.zsnap  # z_final of evolution
    # SF ancestors
    sf_ancestors = np.where(ancestor.sfr_class[will] == 'star-forming')[0]      

    P_q_offset = pq_prop['slope'] * (descendant.mass[succession[sf_ancestors]] - 9.5) + pq_prop['yint']
    
    # fQ(M*, z_final)
    fq_obj = Fq()
    fqf = fq_obj.model(descendant.mass[succession[sf_ancestors]], 
            z_final, 
            lit = sfr_prop['fq']['name'])
    # fQ(M*, z_initial), which is calculated using mass and redshifts when 
    # the host subhalo passes the M* threshold. 
    fq0 = fq_obj.model(descendant.mass_genesis[succession[sf_ancestors]], 
            descendant.zsnap_genesis[succession[sf_ancestors]], 
            lit=sfr_prop['fq']['name'])

    notallquench = np.where(fq0 < 1.0)
    P_q = np.repeat(1.0, len(sf_ancestors))
    P_q[notallquench] = (fqf[notallquench] - fq0[notallquench] ) / (1.0 - fq0[notallquench]) 
    P_q += P_q_offset

    return P_q
def Plot_fQcen_SDSS():
    ''' Compare the quiescent fraction of SDSS from the *corrected* SDSS fQ^cen 
    from Tinker et al. (2013) versus the Wetzel et al. (2013) parameterization. 
    '''
    # mass binnning we impose
    m_low = np.array([9.5, 10., 10.5, 11., 11.5])
    m_high = np.array([10., 10.5, 11., 11.5, 12.0])
    m_mid = 0.5 * (m_low + m_high)

    # SDSS
    fq_file = ''.join(
        ['dat/observations/cosmos_fq/', 'fcen_red_sdss_scatter.dat'])
    m_sdss, fqcen_sdss, N_sdss = np.loadtxt(fq_file,
                                            unpack=True,
                                            usecols=[0, 1, 2])

    fqcen_sdss_rebin = []
    for im, m_mid_i in enumerate(m_mid):
        sdss_mbin = np.where((m_sdss >= m_low[im]) & (m_sdss < m_high[im]))

        fqcen_sdss_rebin.append(
            np.sum(fqcen_sdss[sdss_mbin] * N_sdss[sdss_mbin].astype('float')) /
            np.sum(N_sdss[sdss_mbin].astype('float')))
    fqcen_sdss_rebin = np.array(fqcen_sdss_rebin)

    prettyplot()
    pretty_colors = prettycolors()
    fig = plt.figure()
    sub = fig.add_subplot(111)
    qf = Fq()
    fqcen_model = qf.model(m_mid, 0.05, lit='cosmos_tinker')
    sub.plot(m_mid,
             fqcen_model,
             c=pretty_colors[3],
             lw=3,
             label=r'Wetzel et al. (2013) fit')
    sub.scatter(m_mid,
                fqcen_sdss_rebin,
                color=pretty_colors[0],
                lw=0,
                s=40,
                label=r'Tinker et al. (2013)')

    sub.set_xlim([9.0, 12.0])
    sub.set_xlabel(r'$\mathtt{log\;M_*}$', fontsize=25)
    sub.set_ylim([0.0, 1.0])
    sub.set_ylabel(r'$\mathtt{f_Q^{cen}}$', fontsize=25)
    sub.legend(loc='upper left', scatterpoints=1, markerscale=3)
    fig_file = ''.join(['figure/test/', 'Fq_central_SDSS.png'])
    fig.savefig(fig_file, bbox_inches='tight')
    plt.close()
Exemplo n.º 4
0
    def model(self, fq_prop={'name': 'wetzelsmooth'}, z=None, **mkwargs):
        ''' Plot the model Parameterized queiscent fraction as a function 
        of stellar mass
        '''
        if z is None: 
            if self.z is None: 
                raise ValeuError
            else: 
                redshift = self.z
        else: 
            redshift = z
            self.z = z 

        if self.kwargs == {}: 
            kwargs = mkwargs.copy() 
        else: 
            kwargs = (self.kwargs).copy()
            kwargs.update(mkwargs)
    
        if 'label' in kwargs and kwargs['label'] is not None: 
            fq_label = kwargs['label']
        else: 
            fq_label = fq_prop['name']+'; z = '+str(redshift) 
        
        if 'line_color' in kwargs: 
            line_color = kwargs['line_color']
        else: 
            line_color = 'black'

        if 'line_style' in kwargs:
            line_style = kwargs['line_style'] 
        else: 
            line_style = '-'

        if 'lw' in kwargs: 
            line_width = kwargs['lw'] 
        else:
            line_width = 4

        # parameterized fq 
        fq_obj = Fq()
        fq = fq_obj.model(self.masses, self.z, lit=fq_prop['name'])
        self.subs.plot(
                self.masses, fq, 
                color = line_color,  
                lw = 4, 
                ls = '--', 
                label = fq_label 
                ) 

        return None
def Plot_fQcen_SDSS(): 
    ''' Compare the quiescent fraction of SDSS from the *corrected* SDSS fQ^cen 
    from Tinker et al. (2013) versus the Wetzel et al. (2013) parameterization. 
    '''
    # mass binnning we impose 
    m_low = np.array([9.5, 10., 10.5, 11., 11.5]) 
    m_high = np.array([10., 10.5, 11., 11.5, 12.0])
    m_mid = 0.5 * (m_low + m_high) 

    # SDSS 
    fq_file = ''.join(['dat/observations/cosmos_fq/', 'fcen_red_sdss_scatter.dat']) 
    m_sdss, fqcen_sdss, N_sdss = np.loadtxt(fq_file, unpack=True, usecols=[0,1,2])
    
    fqcen_sdss_rebin = [] 
    for im, m_mid_i in enumerate(m_mid): 
        sdss_mbin = np.where(
                (m_sdss >= m_low[im]) & 
                (m_sdss < m_high[im])) 
    
        fqcen_sdss_rebin.append(
                np.sum(fqcen_sdss[sdss_mbin] * N_sdss[sdss_mbin].astype('float'))/np.sum(N_sdss[sdss_mbin].astype('float'))
                )
    fqcen_sdss_rebin = np.array(fqcen_sdss_rebin)

    prettyplot() 
    pretty_colors = prettycolors()  
    fig = plt.figure() 
    sub = fig.add_subplot(111)
    qf = Fq()
    fqcen_model = qf.model(m_mid, 0.05, lit='cosmos_tinker') 
    sub.plot(m_mid, fqcen_model, 
            c=pretty_colors[3], lw=3, label=r'Wetzel et al. (2013) fit') 
    sub.scatter(m_mid, fqcen_sdss_rebin, 
            color=pretty_colors[0], lw=0, s=40, label=r'Tinker et al. (2013)') 

    sub.set_xlim([9.0, 12.0]) 
    sub.set_xlabel(r'$\mathtt{log\;M_*}$', fontsize=25) 
    sub.set_ylim([0.0, 1.0]) 
    sub.set_ylabel(r'$\mathtt{f_Q^{cen}}$', fontsize=25) 
    sub.legend(loc='upper left', scatterpoints=1, markerscale=3) 
    fig_file = ''.join(['figure/test/', 
        'Fq_central_SDSS.png']) 
    fig.savefig(fig_file, bbox_inches='tight') 
    plt.close() 
def DataSummary(Mrcut=18, observables=['ssfr']): 
    ''' Summary statistics of the data. In our case that is the 
    SSFR distribution of the SDSS group catalog.
    '''
    obvs = []
    if 'ssfr' in observables:
        # Group Catalog object
        groupcat = GroupCat(Mrcut=Mrcut, position='central')
        # SSFR distribution of group catalog
        bins, dist = groupcat.Ssfr()   
        obvs.append([np.array(bins), np.array(dist)])
    if 'fqz03' in observables: 
        qfrac = Fq()
        M_bin = np.array([9.7, 10.1, 10.5, 10.9, 11.3])
        M_mid = 0.5 * (M_bin[:-1] + M_bin[1:])
        fq_model = qfrac.model(M_mid, 0.3412, lit='wetzel')
        obvs.append([M_mid, fq_model])
    
    if len(observables) == 1: 
        obvs = obvs[0]
    return obvs
def DescendantQAplot(nsnap_descendants, **sfinh_kwargs):
    ''' The ultimate QAplot t rule them all. 4 panels showing all the properties.
    '''
    sfinherit_file = InheritSF_file(nsnap_descendants, **sfinh_kwargs)
    bloodline = Lineage(nsnap_ancestor=sfinh_kwargs['nsnap_ancestor'],
                        subhalo_prop=sfinh_kwargs['subhalo_prop'])
    if not isinstance(nsnap_descendants, list):
        nsnap_descendants = [nsnap_descendants]
    bloodline.Read(nsnap_descendants, filename=sfinherit_file)

    for nsnap_descendant in nsnap_descendants:
        descendant = getattr(bloodline,
                             'descendant_snapshot' + str(nsnap_descendant))
        descendant.sfr_prop = sfinh_kwargs['sfr_prop']
        started_here = np.where(
            descendant.nsnap_genesis == sfinh_kwargs['nsnap_ancestor'])
        start_mass = descendant.mass_genesis[started_here]

        # Mass bins
        mass_bins = np.arange(7., 12.5, 0.5)
        mass_bin_low = mass_bins[:-1]
        mass_bin_high = mass_bins[1:]

        plt.close()
        prettyplot()
        fig = plt.figure(1, figsize=[25, 6])
        for i_sub in range(1, 5):
            sub_i = fig.add_subplot(1, 4, i_sub)

            if i_sub == 1:  # SMF
                mf = SMF()
                mass, phi = mf.Obj(descendant)

                sub_i.plot(mass,
                           phi,
                           lw=4,
                           c=pretty_colors[descendant.nsnap],
                           label=r'Simulated')

                censub = CentralSubhalos()
                censub.Read(descendant.nsnap,
                            scatter=sfinh_kwargs['subhalo_prop']['scatter'],
                            source=sfinh_kwargs['subhalo_prop']['source'],
                            nsnap_ancestor=sfinh_kwargs['nsnap_ancestor'])

                mass, phi = mf._smf(censub.mass)
                sub_i.plot(mass,
                           phi,
                           c='k',
                           lw=4,
                           ls='--',
                           label='Central Subhalos')

                sub_i.set_ylim([10**-5, 10**-1])
                sub_i.set_xlim([7.5, 12.0])
                plt.xticks([8., 9., 10., 11., 12.])
                sub_i.set_yscale('log')

                # x,y labels
                sub_i.set_xlabel(r'Mass $\mathtt{M_*}$', fontsize=25)
                sub_i.set_ylabel(r'Stellar Mass Function $\mathtt{\Phi}$',
                                 fontsize=25)
                sub_i.legend(loc='upper right', frameon=False)

            elif i_sub == 2:  # SFMS
                # SMF composition based on their initial mass at nsnap_ancestor
                for i_m in range(len(mass_bin_low)):
                    mbin = np.where((start_mass > mass_bin_low[i_m])
                                    & (start_mass <= mass_bin_high[i_m]))

                    sub_i.scatter(descendant.mass[started_here[0][mbin]],
                                  descendant.sfr[started_here[0][mbin]],
                                  color=pretty_colors[i_m],
                                  label=r"$\mathtt{M_{*,i}=}$" +
                                  str(round(mass_bin_low[i_m], 2)) + "-" +
                                  str(round(mass_bin_high[i_m], 2)))

                qfrac = Fq()
                m_arr = np.arange(9.0, 12.5, 0.5)
                sub_i.plot(m_arr,
                           qfrac.SFRcut(
                               m_arr,
                               descendant.zsnap,
                               sfms_prop=(sfinh_kwargs['sfr_prop'])['sfms']),
                           c='k',
                           ls='--',
                           lw=4)

                sub_i.set_xlim([9.0, 12.0])
                sub_i.set_ylim([-5.0, 2.0])
                sub_i.set_xlabel(r'$\mathtt{log\;M_*}$', fontsize=25)
                sub_i.set_ylabel(r'$\mathtt{log\;SFR}$', fontsize=25)

            elif i_sub == 3:  #SMHM
                for i_m in range(len(mass_bin_low)):
                    mbin = np.where((start_mass > mass_bin_low[i_m])
                                    & (start_mass <= mass_bin_high[i_m]))

                    sub_i.scatter(descendant.halo_mass[started_here[0][mbin]],
                                  descendant.mass[started_here[0][mbin]],
                                  color=pretty_colors[i_m],
                                  label=r"$\mathtt{M_{*,i}=}$" +
                                  str(round(mass_bin_low[i_m], 2)) + "-" +
                                  str(round(mass_bin_high[i_m], 2)))

                stellarmass = descendant.mass[started_here]
                halomass = descendant.halo_mass[started_here]
                mbin = np.arange(halomass.min(), halomass.max(), 0.25)
                mlow = mbin[:-1]
                mhigh = mbin[1:]

                muMstar = np.zeros(len(mlow))
                sigMstar = np.zeros(len(mlow))

                for im in range(len(mlow)):
                    mbin = np.where((halomass > mlow[im])
                                    & (halomass <= mhigh[im]))
                    muMstar[im] = np.mean(stellarmass[mbin])
                    sigMstar[im] = np.std(stellarmass[mbin])
                sub_i.errorbar(0.5 * (mlow + mhigh),
                               muMstar,
                               yerr=sigMstar,
                               color='k',
                               lw=3,
                               fmt='o',
                               capthick=2)

                sub_i.set_ylim([9.0, 12.0])
                sub_i.set_xlim([10.0, 15.0])
                sub_i.set_ylabel(r'Stellar Mass $\mathtt{M_*}$', fontsize=25)
                sub_i.set_xlabel(r'Halo Mass $\mathtt{M_{Halo}}$', fontsize=25)

                #sub_i.legend(loc='upper left', frameon=False, scatterpoints=1)
            elif i_sub == 4:  # Fq
                #mass, fq = descendant.Fq()
                sfq = qfrac.Classify(descendant.mass,
                                     descendant.sfr,
                                     descendant.zsnap,
                                     sfms_prop=descendant.sfr_prop['sfms'])
                gc = GroupCat(Mrcut=18, position='central')
                gc.Read()
                gc_sfq = qfrac.Classify(gc.mass,
                                        gc.sfr,
                                        np.mean(gc.z),
                                        sfms_prop=descendant.sfr_prop['sfms'])
                #sub_i.plot(mass, fq, color=pretty_colors[descendant.nsnap], lw=3, ls='--',
                #        label=r'$\mathtt{z =} '+str(descendant.zsnap)+'$')
                M_bin = np.array([9.7, 10.1, 10.5, 10.9, 11.3])
                M_low = M_bin[:-1]
                M_high = M_bin[1:]
                M_mid = 0.5 * (M_low + M_high)

                fq = np.zeros(len(M_low))
                gc_fq = np.zeros(len(M_low))
                for i_m in xrange(len(M_low)):
                    mlim = np.where((descendant.mass > M_low[i_m])
                                    & (descendant.mass <= M_high[i_m]))
                    gc_mlim = np.where((gc.mass > M_low[i_m])
                                       & (gc.mass <= M_high[i_m]))
                    ngal = np.float(len(mlim[0]))
                    gc_ngal = np.float(len(gc_mlim[0]))

                    if ngal != 0:  # no galaxy in mass bin
                        ngal_q = np.float(
                            len(np.where(sfq[mlim] == 'quiescent')[0]))
                        fq[i_m] = ngal_q / ngal
                    if gc_ngal != 0:
                        gc_ngal_q = np.float(
                            len(np.where(gc_sfq[gc_mlim] == 'quiescent')[0]))
                        gc_fq[i_m] = gc_ngal_q / gc_ngal

                sub_i.plot(M_mid,
                           fq,
                           color=pretty_colors[descendant.nsnap],
                           lw=3,
                           label=r'$\mathtt{z =} ' + str(descendant.zsnap) +
                           '$')

                fq_model = qfrac.model(
                    M_bin,
                    descendant.zsnap,
                    lit=sfinh_kwargs['sfr_prop']['fq']['name'])
                sub_i.plot(M_bin,
                           fq_model,
                           color='k',
                           lw=4,
                           ls='--',
                           label=sfinh_kwargs['sfr_prop']['fq']['name'])
                sub_i.scatter(M_mid,
                              gc_fq,
                              color='k',
                              s=100,
                              lw=0,
                              label='Group Catalog')

                sub_i.set_xlim([9.0, 12.0])
                sub_i.set_ylim([0.0, 1.0])

                sub_i.set_xlabel(r'Mass $\mathtt{M_*}$')
                sub_i.set_ylabel(r'Quiescent Fraction $\mathtt{f_Q}$',
                                 fontsize=20)

                sub_i.legend(loc='upper left',
                             frameon=False,
                             scatterpoints=1,
                             markerscale=0.75)

        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0)
        fig_name = ''.join([
            'figure/test/', 'QAplot.', '.nsnap',
            str(nsnap_descendant), '.'.join(
                (sfinherit_file.rsplit('/')[-1]).rsplit('.')[:-1]), '.png'
        ])
        fig.savefig(fig_name, bbox_inches='tight')
        plt.close()
    return None
Exemplo n.º 8
0
def AssignSFR(mass,
              redshift,
              sfr_prop=None,
              ancestor=None,
              descendant=None,
              quiet=True):
    ''' Assign star-forming properties based on the input mass and redshift. 
    Return sfr_class (star-forming or quiescent), SFR, and sSFR given a set 
    of masses and redshifts.

    Parameters
    ----------
    mass : array
        Array of galaxy stellar mass
    redshift : array
        Array of corresponding galaxy redshift
    sfr_prop : dictionary
        Dictionary that specifies the star-forming properties.

    Notes
    -----
    * Takes ~1.5 seconds for assign_sfr_ancestor in lineage object
    '''
    if sfr_prop is None:
        raise ValueError('Specify SFR Properties dictionary')

    # Dictionaries that specify fQ, SFMS, f_GV
    fq_dict = sfr_prop['fq']
    sfms_dict = sfr_prop['sfms']
    gv_dict = sfr_prop['gv']
    if 'subhalogrowth' in sfr_prop.keys():
        if descendant is None:
            raise ValueError
        if ancestor is None:
            raise ValueError
        for key in descendant.__dict__.keys():
            if 'ancestor' in key:
                ancestor_index = getattr(descendant, key)

    ngal = len(mass)  # Ngal
    sfr_class = np.repeat('', ngal).astype('|S16')
    sfr = np.repeat(-999., ngal)
    ssfr = np.repeat(-999., ngal)
    delta_sfr = np.repeat(-999., ngal)
    avg_sfr = np.repeat(-999., ngal)
    tQ = np.repeat(999., ngal)
    MQ = np.repeat(-999., ngal)

    qfrac = Fq()  # Fq object
    M_bins = np.arange(6.0, 13., 0.5)  # mass bin
    M_mid = 0.5 * (M_bins[:-1] + M_bins[1:])

    # For z = z_ancestor
    massive = np.where((mass > 0.0) & (redshift == redshift.max()))[0]
    ngal = len(massive)
    ngal_M, dum = np.histogram(mass[massive], bins=M_bins)

    np.random.seed()
    rand = np.random.uniform(0., 1., ngal)
    # f_GV(M*)  Green valley fraction
    gvfrac = gv_dict['slope'] * (mass[massive] -
                                 gv_dict['fidmass']) + gv_dict['offset']
    greenvalley = np.where(rand < gvfrac)[0]
    ngal_green = len(greenvalley)
    ngal_green_M, dum = np.histogram(mass[massive[greenvalley]], bins=M_bins)
    if not quiet:
        print ngal_green, ' green valley galaxies out of ', ngal, ' galaxies'

    sfr_class[
        massive[greenvalley]] = 'star-forming'  # classified as star-forming
    ssfr_q_peak = AverageLogSSFR_q_peak(
        mass[massive[greenvalley]])  # Q peak SSFR value
    ssfr_sf_peak = AverageLogSFR_sfms(
        mass[massive[greenvalley]],  # SF peak SSFR value 
        redshift[massive[greenvalley]],
        sfms_prop=sfms_dict) - mass[massive[greenvalley]]
    ssfr[massive[greenvalley]] = np.random.uniform(ssfr_q_peak, ssfr_sf_peak,
                                                   ngal_green)
    sfr[massive[greenvalley]] = ssfr[massive[greenvalley]] + mass[
        massive[greenvalley]]
    tQ[massive[greenvalley]] = Util.get_tsnap(
        redshift.max())  # quenching cosmic time
    MQ[massive[greenvalley]] = mass[massive[greenvalley]]

    # some green valley galaxies will be classified in observations as
    # quiescent or star-forming.
    green_class = qfrac.Classify(mass[massive[greenvalley]],
                                 sfr[massive[greenvalley]],
                                 redshift[massive[greenvalley]],
                                 sfms_prop=sfms_dict)
    GQ = np.where(green_class == 'quiescent')
    ngal_GQ = len(GQ[0])
    ngal_GQ_M, dum = np.histogram(mass[massive[greenvalley[GQ]]], bins=M_bins)

    # f_Q(M*, z) for each massive galaxy
    fq_M = qfrac.model(M_mid, redshift.max(), lit=fq_dict['name'])
    fq_prime_arr = (ngal_M * fq_M - ngal_GQ_M) / (ngal_M - ngal_green_M)
    fq_prime_arr[np.where(ngal_M == 0)] = 0.
    fq_prime_M = interpolate.interp1d(M_mid, fq_prime_arr, kind='linear')

    # assign SFR to the not so green valley
    notgreenvalley = np.where(rand >= gvfrac)[0]
    ngal_notgreenvalley = len(notgreenvalley)
    rand_notgreen = np.random.uniform(0., 1., ngal_notgreenvalley)

    fq_prime = fq_prime_M(mass[massive[notgreenvalley]])  # fQ'

    lowz = np.where((mass > 0.0) & (redshift != redshift.max()))[0]
    ngal_lowz = len(lowz)
    rand_lowz = np.random.uniform(0., 1., ngal_lowz)
    fq_lowz = qfrac.model(mass[lowz], redshift[lowz], lit=fq_dict['name'])
    quiescent = np.concatenate([
        massive[notgreenvalley[np.where(rand_notgreen < fq_prime)]],
        lowz[np.where(rand_lowz < fq_lowz)]
    ])
    starforming = np.concatenate([
        massive[notgreenvalley[np.where(rand_notgreen >= fq_prime)]],
        lowz[np.where(rand_lowz >= fq_lowz)]
    ])
    ngal_q = len(quiescent)
    ngal_sf = len(starforming)

    # Assign SFR to quiescent galaxies
    sfr_class[quiescent] = 'quiescent'
    mu_q_ssfr = AverageLogSSFR_q_peak(mass[quiescent])
    sig_q_ssfr = ScatterLogSSFR_q_peak(mass[quiescent])
    ssfr[quiescent] = sig_q_ssfr * np.random.randn(ngal_q) + mu_q_ssfr
    sfr[quiescent] = ssfr[quiescent] + mass[quiescent]

    # Assign SFR to star-forming galaxies
    sfr_class[starforming] = 'star-forming'
    mu_sf_sfr = AverageLogSFR_sfms(mass[starforming],
                                   redshift[starforming],
                                   sfms_prop=sfms_dict)
    sigma_sf_sfr = ScatterLogSFR_sfms(mass[starforming],
                                      redshift[starforming],
                                      sfms_prop=sfms_dict)
    avg_sfr[starforming] = mu_sf_sfr
    delta_sfr[starforming] = sigma_sf_sfr * np.random.randn(ngal_sf)
    sfr[starforming] = mu_sf_sfr + delta_sfr[starforming]
    ssfr[starforming] = sfr[starforming] - mass[starforming]

    if 'subhalogrowth' in sfr_prop.keys():
        # if SFR assignment is dependent on subhalo growth,
        # loop through mass bins and assign SFR by abundance matching the
        # SFR to the Delta M*_sham.
        mass_range = np.arange(mass[starforming].min(),
                               mass[starforming].max(), 0.1)
        m_low = mass_range[:-1]
        m_high = mass_range[1:]
        for im in range(len(m_low)):
            sf_mass_bin = np.where((mass[starforming] > m_low[im])
                                   & (mass[starforming] <= m_high[im]))[0]
            succession, will = Util.intersection_index(
                ancestor_index, ancestor.snap_index[starforming])
            deltaM = descendant.mass[succession] - mass[starforming[will]]
            dM_sort_index = np.argsort(deltaM)

            deltaSFR = sigma_sf_sfr * np.random.randn(len(deltaM))
            dSFR_sort_index = np.argsort(deltaSFR)
            # abundance matched.
            delta_sfr[starforming[
                will[dM_sort_index]]] = deltaSFR[dSFR_sort_index]

        sfr[starforming] = mu_sf_sfr + delta_sfr[starforming]
        ssfr[starforming] = sfr[starforming] - mass[starforming]

    return [sfr_class, sfr, ssfr, delta_sfr, avg_sfr, tQ, MQ]
Exemplo n.º 9
0
def AssignCenSFR(tf, abcrun=None, prior_name=None):
    ''' Given SGPop object, assign SFRs at infalling time based on the 
    median ABC Run of the Central Galaxy evolution 
    '''
    if abcrun is None: 
        raise ValueError
    if prior_name is None: 
        raise ValueError
    abcinh = ABCInherit(tf, abcrun=abcrun, prior_name=prior_name) 
    
    inh = abcinh.PickleLoad('all') 
    
    sg_obj = SGPop()
    sg_obj.ImportSubhalo(subhalo_prop=abcinh.sim_kwargs['subhalo_prop']) 
    sg_obj.sfms_prop = abcinh.sim_kwargs['sfr_prop']['sfms']
    sg_obj.abcrun = abcrun
    sg_obj.prior_name = prior_name 
    
    sg_obj.first_infall_sfr = np.repeat(-999., len(sg_obj.first_infall_nsnap))
    for i_snap in range(2, abcinh.sim_kwargs['nsnap_ancestor']): 
        infall_now = np.where(
                (sg_obj.first_infall_nsnap == i_snap) & 
                (sg_obj.first_infall_mass > 0.))[0]

        # satellite galaxies that end up massive but have 0. infalling mass 
        #massive_infall_zero =np.where(
        #        (sg_obj.first_infall_mass[infall_now] == 0.) & 
        #        (sg_obj.mass[infall_now] > 0.)
        #        ) 
        
        des_snap = inh[str(i_snap)]
        m_bins = np.arange(des_snap.mass.min()-0.1, des_snap.mass.max()+0.2, 0.2) 

        for i_m in range(len(m_bins)-1): 
            in_massbin = np.where(
                    (des_snap.mass >= m_bins[i_m]) & 
                    (des_snap.mass < m_bins[i_m+1]))

            infall_massbin = np.where(
                    (sg_obj.first_infall_nsnap == i_snap) & 
                    (sg_obj.first_infall_mass >= m_bins[i_m]) & 
                    (sg_obj.first_infall_mass < m_bins[i_m+1]))

            if len(infall_massbin[0]) == 0: 
                continue 

            des_ssfrs = des_snap.sfr[in_massbin] - des_snap.mass[in_massbin] 
            pdf_ssfr_i, ssfr_binedges = np.histogram(des_ssfrs, 
                    bins=np.arange(-13.0, -8.0, 0.2), normed=True) 

            cdf_ssfr_i = np.zeros(len(ssfr_binedges))
            cdf_ssfr_i[1:] = np.cumsum(pdf_ssfr_i * np.diff(ssfr_binedges))
            cdf_interp = interp1d(cdf_ssfr_i, ssfr_binedges, kind='linear') 

            rand_i = np.random.uniform(size=len(infall_massbin[0]))
            sg_obj.first_infall_sfr[infall_massbin] = cdf_interp(rand_i) + \
                    sg_obj.first_infall_mass[infall_massbin]

    # assign SFR to galaxies that fell in before nsnap = 15
    old_infall = np.where(
            (sg_obj.first_infall_nsnap >= abcinh.sim_kwargs['nsnap_ancestor']) &
            (sg_obj.first_infall_mass > 0.))[0]
    
    Pq = np.random.uniform(size=len(old_infall))
    qfrac = Fq() 
    fq_oldinfall = qfrac.model(sg_obj.first_infall_mass[old_infall], sg_obj.first_infall_z[old_infall], lit='wetzel')

    # star-forming
    sfing = np.where(Pq > fq_oldinfall) 
    sig_sfms = sfr_evol.ScatterLogSFR_sfms(
            sg_obj.first_infall_mass[old_infall[sfing]], 
            sg_obj.first_infall_z[old_infall[sfing]], 
            sfms_prop=sg_obj.sfms_prop)
    mu_sfms = sfr_evol.AverageLogSFR_sfms(
            sg_obj.first_infall_mass[old_infall[sfing]], 
            sg_obj.first_infall_z[old_infall[sfing]], 
            sfms_prop=sg_obj.sfms_prop)
    sg_obj.first_infall_sfr[old_infall[sfing]] = mu_sfms + np.random.randn(len(sfing[0])) * sig_sfms

    # quiescent
    qed = np.where(Pq <= fq_oldinfall) 
    mu_ssfr_q = sfr_evol.AverageLogSSFR_q_peak(sg_obj.first_infall_mass[old_infall[qed]])
    sig_ssfr_q = sfr_evol.ScatterLogSSFR_q_peak(sg_obj.first_infall_mass[old_infall[qed]])

    ssfr_q = mu_ssfr_q + np.random.randn(len(qed[0])) * sig_ssfr_q 

    sg_obj.first_infall_sfr[old_infall[qed]] = ssfr_q + sg_obj.first_infall_mass[old_infall[qed]]

    return sg_obj
Exemplo n.º 10
0
def QAplot(descendant, sfinh_kwargs, fig_name=None, **kwargs):
    ''' Given galpop object and the SF Inheritance parametes, 
    plot its SMF, 
    '''
    # Mass bins
    mass_bins = np.arange(7., 12.5, 0.5)
    mass_bin_low = mass_bins[:-1]
    mass_bin_high = mass_bins[1:]

    plt.close()
    prettyplot()
    fig = plt.figure(1, figsize=[20,12])
    for i_sub in range(1,6): 
        sub_i = fig.add_subplot(2,3,i_sub) 
    
        if i_sub == 1:  # SMF
            mf = SMF()
            mass, phi = mf.Obj(descendant)

            sub_i.plot(mass, phi, lw=4, c='r', label=r'Simulated')

            censub = CentralSubhalos()
            censub.Read(descendant.nsnap, 
                    scatter=sfinh_kwargs['subhalo_prop']['scatter'], 
                    source=sfinh_kwargs['subhalo_prop']['source'], 
                    nsnap_ancestor=sfinh_kwargs['nsnap_ancestor'])

            mass, phi = mf._smf(censub.mass)
            sub_i.plot(mass, phi, c='k', lw=4, ls='--', label='Central Subhalos') 

            sub_i.set_ylim([10**-5, 10**-1])
            sub_i.set_xlim([7.5, 12.0])
            plt.xticks([8., 9., 10., 11., 12.])
            sub_i.set_yscale('log')

            # x,y labels
            sub_i.set_ylabel(r'Stellar Mass ($\mathtt{log\; M_*}$)', fontsize=20) 
            sub_i.set_ylabel(r'Stellar Mass Function $\mathtt{\Phi}$', fontsize=20) 
            sub_i.legend(loc='upper right', frameon=False)

        elif i_sub == 2: # SFMS
            # SMF composition based on their initial mass at nsnap_ancestor 

            # random subsample 
            n_tot = len(descendant.mass)
            r_subsample = np.random.choice(n_tot, size=100000)
            sub_i.scatter(descendant.mass[r_subsample], descendant.sfr[r_subsample], color='b', s=0.5) 

            qfrac = Fq()
            m_arr = np.arange(9.0, 12.5, 0.5)
            sub_i.plot(
                    m_arr, 
                    qfrac.SFRcut(m_arr, descendant.zsnap, sfms_prop=(sfinh_kwargs['sfr_prop'])['sfms']), 
                    c='k', ls='--', lw=4)

            sub_i.text(10.5, -4., r'$\mathtt{z='+str(descendant.zsnap)+'}$', fontsize=25)

            sub_i.set_xlim([9.0, 12.0])
            sub_i.set_ylim([-5.0, 2.0])
            sub_i.set_ylabel(r'Stellar Mass ($\mathtt{log\; M_*}$)', fontsize=20) 
            sub_i.set_ylabel(r'$\mathtt{log\;SFR}$', fontsize=20)

        elif i_sub == 3: #SMHM
            #corner.hist2d(descendant.halo_mass, descendant.mass, ax=sub_i, c='b', fill_contours=True, smooth=1.0)
            n_tot = len(descendant.mass)
            r_subsample = np.random.choice(n_tot, size=100000)
            sub_i.scatter(descendant.halo_mass[r_subsample], descendant.mass[r_subsample], color='b', s=0.5)

            stellarmass = descendant.mass
            halomass = descendant.halo_mass
            mbin = np.arange(halomass.min(), halomass.max(), 0.25) 
            mlow = mbin[:-1]
            mhigh = mbin[1:]
            
            muMstar = np.zeros(len(mlow))
            sigMstar = np.zeros(len(mlow))

            for im in range(len(mlow)): 
                mbin = np.where((halomass > mlow[im]) & (halomass <= mhigh[im]))
                muMstar[im] = np.mean(stellarmass[mbin])
                sigMstar[im] = np.std(stellarmass[mbin])
            sub_i.errorbar(0.5*(mlow+mhigh), muMstar, yerr=sigMstar, color='k', lw=3, fmt='o', capthick=2)

            sub_i.set_ylim([9.0, 12.0])
            sub_i.set_xlim([10.0, 15.0])
            sub_i.set_ylabel(r'Stellar Mass ($\mathtt{log\; M_*}$)', fontsize=20) 
            sub_i.set_xlabel(r'Halo Mass ($\mathtt{log\;M_{Halo}}$)', fontsize=20) 

        elif i_sub == 4: # Fq
            sfq = qfrac.Classify(descendant.mass, descendant.sfr, descendant.zsnap, 
                    sfms_prop=descendant.sfr_prop['sfms'])
            gc = GroupCat(Mrcut=18, position='central')
            gc.Read()
            gc_sfq = qfrac.Classify(gc.mass, gc.sfr, np.mean(gc.z), 
                    sfms_prop=descendant.sfr_prop['sfms'])
            #sub_i.plot(mass, fq, color=pretty_colors[descendant.nsnap], lw=3, ls='--', 
            #        label=r'$\mathtt{z =} '+str(descendant.zsnap)+'$')
            M_bin = np.array([9.7, 10.1, 10.5, 10.9, 11.3])
            M_low = M_bin[:-1]
            M_high = M_bin[1:]
            M_mid = 0.5 * (M_low + M_high)

            fq = np.zeros(len(M_low))
            gc_fq = np.zeros(len(M_low))
            for i_m in xrange(len(M_low)):
                mlim = np.where((descendant.mass > M_low[i_m]) & (descendant.mass <= M_high[i_m]))
                gc_mlim = np.where((gc.mass > M_low[i_m]) & (gc.mass <= M_high[i_m]))
                ngal = np.float(len(mlim[0]))
                gc_ngal = np.float(len(gc_mlim[0]))

                if ngal != 0:  # no galaxy in mass bin 
                    ngal_q = np.float(len(np.where(sfq[mlim] == 'quiescent')[0]))
                    fq[i_m] = ngal_q/ngal
                if gc_ngal != 0:
                    gc_ngal_q = np.float(len(np.where(gc_sfq[gc_mlim] == 'quiescent')[0]))
                    gc_fq[i_m] = gc_ngal_q/gc_ngal

            sub_i.plot(M_mid, fq, color='r', lw=3, label=r'Simulated')
            
            # fQ of the Group Catalog 
            sub_i.scatter(M_mid, gc_fq, color='k', s=100, lw=0, label='Group Catalog')
            # fQ of the model (input) fQ
            fq_model = qfrac.model(M_bin, descendant.zsnap, lit=sfinh_kwargs['sfr_prop']['fq']['name'])
            sub_i.plot(M_bin, fq_model, 
                    color='k', lw=4, ls='--', 
                    label=sfinh_kwargs['sfr_prop']['fq']['name'].replace('_', ' ').title() 
                    )

            sub_i.set_xlim([9.0, 12.0])
            sub_i.set_ylim([0.0, 1.0])

            sub_i.set_ylabel(r'Stellar Mass ($\mathtt{log\; M_*}$)', fontsize=20) 
            sub_i.set_ylabel(r'Quiescent Fraction $\mathtt{f_Q}$', fontsize=20) 

            sub_i.legend(loc='upper left', frameon=False, scatterpoints=1, markerscale=0.75)

        elif i_sub == 5: # Tau_Q(M*)
            mass_bin = np.arange(9.0, 12.0, 0.1)

            tau_m = getTauQ(mass_bin, tau_prop=sfinh_kwargs['evol_prop']['tau']) 
            sub_i.plot(10**mass_bin, tau_m, color='r', lw=4, label='Simulated') 

            if 'taus' in kwargs: 
                tau_slopes, tau_offsets = kwargs['taus']

                i_tau_ms = np.zeros((len(mass_bin), len(tau_slopes)))
                for i_tau in range(len(tau_slopes)): 
                    i_tau_prop = sfinh_kwargs['evol_prop']['tau'].copy()
                    i_tau_prop['slope'] = tau_slopes[i_tau]
                    i_tau_prop['yint'] = tau_offsets[i_tau]

                    i_tau_m = getTauQ(mass_bin, tau_prop=i_tau_prop) 
                    #sub_i.plot(10**mass_bin, i_tau_m, color='r', alpha=0.1, lw=2) 
                    i_tau_ms[:,i_tau] = i_tau_m
            
                sig_tau = np.zeros(len(mass_bin))
                for im in range(len(mass_bin)):
                    sig_tau[im] = np.std(i_tau_ms[im,:])
                
                sub_i.errorbar(10**mass_bin, tau_m, yerr=sig_tau, color='r', lw=4) 

            # satellite quenching fraction for comparison 
            tau_sat = getTauQ(mass_bin, tau_prop={'name': 'satellite'}) 

            sub_i.plot(10**mass_bin, tau_sat, color='black', lw=4, ls='--', label=r'Satellite (Wetzel+ 2013)') 

            sub_i.set_xlim([10**9.5, 10**11.75])
            sub_i.set_ylim([0.0, 2.0])
            sub_i.set_xscale('log')

            sub_i.set_xlabel(r'Stellar Mass $[\mathtt{M_\odot}]$',fontsize=20) 
            sub_i.legend(loc='upper right') 

            sub_i.set_ylabel(r'Quenching Timescales $(\tau_\mathtt{Q})$ [Gyr]',fontsize=20) 
        
    plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0) 
    if fig_name is None: 
        plt.show()
        plt.close()
    else: 
        fig.savefig(fig_name, bbox_inches='tight') 
        plt.close()
    return None 
def DescendantQAplot(nsnap_descendants, **sfinh_kwargs): 
    ''' The ultimate QAplot t rule them all. 4 panels showing all the properties.
    '''
    sfinherit_file = InheritSF_file(nsnap_descendants, **sfinh_kwargs)
    bloodline = Lineage(
            nsnap_ancestor=sfinh_kwargs['nsnap_ancestor'], 
            subhalo_prop=sfinh_kwargs['subhalo_prop']
            )
    if not isinstance(nsnap_descendants, list): 
        nsnap_descendants = [nsnap_descendants]
    bloodline.Read(nsnap_descendants, filename=sfinherit_file)
    
    for nsnap_descendant in nsnap_descendants: 
        descendant = getattr(bloodline, 'descendant_snapshot'+str(nsnap_descendant)) 
        descendant.sfr_prop = sfinh_kwargs['sfr_prop']
        started_here = np.where(descendant.nsnap_genesis == sfinh_kwargs['nsnap_ancestor'])
        start_mass = descendant.mass_genesis[started_here]

        # Mass bins
        mass_bins = np.arange(7., 12.5, 0.5)
        mass_bin_low = mass_bins[:-1]
        mass_bin_high = mass_bins[1:]

        plt.close()
        prettyplot()
        fig = plt.figure(1, figsize=[25,6])
        for i_sub in range(1,5): 
            sub_i = fig.add_subplot(1,4,i_sub) 
            
            if i_sub == 1:  # SMF
                mf = SMF()
                mass, phi = mf.Obj(descendant)

                sub_i.plot(mass, phi, lw=4, c=pretty_colors[descendant.nsnap], label=r'Simulated')

                censub = CentralSubhalos()
                censub.Read(descendant.nsnap, 
                        scatter=sfinh_kwargs['subhalo_prop']['scatter'], 
                        source=sfinh_kwargs['subhalo_prop']['source'], 
                        nsnap_ancestor=sfinh_kwargs['nsnap_ancestor'])

                mass, phi = mf._smf(censub.mass)
                sub_i.plot(mass, phi, c='k', lw=4, ls='--', label='Central Subhalos') 

                sub_i.set_ylim([10**-5, 10**-1])
                sub_i.set_xlim([7.5, 12.0])
                plt.xticks([8., 9., 10., 11., 12.])
                sub_i.set_yscale('log')

                # x,y labels
                sub_i.set_xlabel(r'Mass $\mathtt{M_*}$', fontsize=25) 
                sub_i.set_ylabel(r'Stellar Mass Function $\mathtt{\Phi}$', fontsize=25) 
                sub_i.legend(loc='upper right', frameon=False)

            elif i_sub == 2: # SFMS
                # SMF composition based on their initial mass at nsnap_ancestor 
                for i_m in range(len(mass_bin_low)): 
                    mbin = np.where((start_mass > mass_bin_low[i_m]) & (start_mass <= mass_bin_high[i_m]))

                    sub_i.scatter(
                            descendant.mass[started_here[0][mbin]], 
                            descendant.sfr[started_here[0][mbin]], 
                            color=pretty_colors[i_m], 
                            label=r"$\mathtt{M_{*,i}=}$"+str(round(mass_bin_low[i_m],2))+"-"+str(round(mass_bin_high[i_m],2))
                            )
                
                qfrac = Fq()
                m_arr = np.arange(9.0, 12.5, 0.5)
                sub_i.plot(
                        m_arr, 
                        qfrac.SFRcut(m_arr, descendant.zsnap, sfms_prop=(sfinh_kwargs['sfr_prop'])['sfms']), 
                        c='k', ls='--', lw=4)

                sub_i.set_xlim([9.0, 12.0])
                sub_i.set_ylim([-5.0, 2.0])
                sub_i.set_xlabel(r'$\mathtt{log\;M_*}$', fontsize=25)
                sub_i.set_ylabel(r'$\mathtt{log\;SFR}$', fontsize=25)

            elif i_sub == 3: #SMHM
                for i_m in range(len(mass_bin_low)): 
                    mbin = np.where((start_mass > mass_bin_low[i_m]) & (start_mass <= mass_bin_high[i_m]))

                    sub_i.scatter(
                            descendant.halo_mass[started_here[0][mbin]], 
                            descendant.mass[started_here[0][mbin]], 
                            color=pretty_colors[i_m], 
                            label=r"$\mathtt{M_{*,i}=}$"+str(round(mass_bin_low[i_m],2))+"-"+str(round(mass_bin_high[i_m],2))
                            )

                stellarmass = descendant.mass[started_here]
                halomass = descendant.halo_mass[started_here]
                mbin = np.arange(halomass.min(), halomass.max(), 0.25) 
                mlow = mbin[:-1]
                mhigh = mbin[1:]
                
                muMstar = np.zeros(len(mlow))
                sigMstar = np.zeros(len(mlow))

                for im in range(len(mlow)): 
                    mbin = np.where((halomass > mlow[im]) & (halomass <= mhigh[im]))
                    muMstar[im] = np.mean(stellarmass[mbin])
                    sigMstar[im] = np.std(stellarmass[mbin])
                sub_i.errorbar(0.5*(mlow+mhigh), muMstar, yerr=sigMstar, color='k', lw=3, fmt='o', capthick=2)

                sub_i.set_ylim([9.0, 12.0])
                sub_i.set_xlim([10.0, 15.0])
                sub_i.set_ylabel(r'Stellar Mass $\mathtt{M_*}$', fontsize=25) 
                sub_i.set_xlabel(r'Halo Mass $\mathtt{M_{Halo}}$', fontsize=25) 

                #sub_i.legend(loc='upper left', frameon=False, scatterpoints=1)
            elif i_sub == 4: # Fq
                #mass, fq = descendant.Fq()
                sfq = qfrac.Classify(descendant.mass, descendant.sfr, descendant.zsnap, 
                        sfms_prop=descendant.sfr_prop['sfms'])
                gc = GroupCat(Mrcut=18, position='central')
                gc.Read()
                gc_sfq = qfrac.Classify(gc.mass, gc.sfr, np.mean(gc.z), 
                        sfms_prop=descendant.sfr_prop['sfms'])
                #sub_i.plot(mass, fq, color=pretty_colors[descendant.nsnap], lw=3, ls='--', 
                #        label=r'$\mathtt{z =} '+str(descendant.zsnap)+'$')
                M_bin = np.array([9.7, 10.1, 10.5, 10.9, 11.3])
                M_low = M_bin[:-1]
                M_high = M_bin[1:]
                M_mid = 0.5 * (M_low + M_high)

                fq = np.zeros(len(M_low))
                gc_fq = np.zeros(len(M_low))
                for i_m in xrange(len(M_low)):
                    mlim = np.where((descendant.mass > M_low[i_m]) & (descendant.mass <= M_high[i_m]))
                    gc_mlim = np.where((gc.mass > M_low[i_m]) & (gc.mass <= M_high[i_m]))
                    ngal = np.float(len(mlim[0]))
                    gc_ngal = np.float(len(gc_mlim[0]))

                    if ngal != 0:  # no galaxy in mass bin 
                        ngal_q = np.float(len(np.where(sfq[mlim] == 'quiescent')[0]))
                        fq[i_m] = ngal_q/ngal
                    if gc_ngal != 0:
                        gc_ngal_q = np.float(len(np.where(gc_sfq[gc_mlim] == 'quiescent')[0]))
                        gc_fq[i_m] = gc_ngal_q/gc_ngal

                sub_i.plot(M_mid, fq, color=pretty_colors[descendant.nsnap], lw=3, label=r'$\mathtt{z =} '+str(descendant.zsnap)+'$')
                
                fq_model = qfrac.model(M_bin, descendant.zsnap, lit=sfinh_kwargs['sfr_prop']['fq']['name'])
                sub_i.plot(M_bin, fq_model, color='k', lw=4, ls='--', label=sfinh_kwargs['sfr_prop']['fq']['name'])
                sub_i.scatter(M_mid, gc_fq, color='k', s=100, lw=0, label='Group Catalog')

                sub_i.set_xlim([9.0, 12.0])
                sub_i.set_ylim([0.0, 1.0])

                sub_i.set_xlabel(r'Mass $\mathtt{M_*}$') 
                sub_i.set_ylabel(r'Quiescent Fraction $\mathtt{f_Q}$', fontsize=20) 

                sub_i.legend(loc='upper left', frameon=False, scatterpoints=1, markerscale=0.75)

        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0) 
        fig_name = ''.join([
            'figure/test/', 
            'QAplot.',
            '.nsnap', str(nsnap_descendant),  
            '.'.join((sfinherit_file.rsplit('/')[-1]).rsplit('.')[:-1]), 
            '.png'])
        fig.savefig(fig_name, bbox_inches='tight') 
        plt.close()
    return None 
Exemplo n.º 12
0
def AssignSFR(mass, redshift, sfr_prop=None, ancestor=None, descendant=None, quiet=True):
    ''' Assign star-forming properties based on the input mass and redshift. 
    Return sfr_class (star-forming or quiescent), SFR, and sSFR given a set 
    of masses and redshifts.

    Parameters
    ----------
    mass : array
        Array of galaxy stellar mass
    redshift : array
        Array of corresponding galaxy redshift
    sfr_prop : dictionary
        Dictionary that specifies the star-forming properties.

    Notes
    -----
    * Takes ~1.5 seconds for assign_sfr_ancestor in lineage object
    '''
    if sfr_prop is None: 
        raise ValueError('Specify SFR Properties dictionary')
    
    # Dictionaries that specify fQ, SFMS, f_GV
    fq_dict = sfr_prop['fq']        
    sfms_dict = sfr_prop['sfms']    
    gv_dict = sfr_prop['gv']        
    if 'subhalogrowth' in sfr_prop.keys(): 
        if descendant is None: 
            raise ValueError
        if ancestor is None: 
            raise ValueError
        for key in descendant.__dict__.keys(): 
            if 'ancestor' in key: 
                ancestor_index = getattr(descendant, key) 

    ngal = len(mass) # Ngal 
    sfr_class= np.repeat('', ngal).astype('|S16') 
    sfr      = np.repeat(-999., ngal) 
    ssfr     = np.repeat(-999., ngal)
    delta_sfr   = np.repeat(-999., ngal)
    avg_sfr     = np.repeat(-999., ngal)
    tQ  = np.repeat(999., ngal) 
    MQ  = np.repeat(-999., ngal)

    qfrac = Fq()    # Fq object
    M_bins = np.arange(6.0, 13., 0.5)   # mass bin 
    M_mid = 0.5 * (M_bins[:-1] + M_bins[1:])

    # For z = z_ancestor 
    massive = np.where((mass > 0.0) & (redshift == redshift.max()))[0] 
    ngal = len(massive) 
    ngal_M, dum = np.histogram(mass[massive], bins=M_bins)
    
    np.random.seed()
    rand = np.random.uniform(0., 1., ngal)
    # f_GV(M*)  Green valley fraction 
    gvfrac = gv_dict['slope'] * (mass[massive] - gv_dict['fidmass']) + gv_dict['offset']
    greenvalley = np.where(rand < gvfrac)[0]
    ngal_green = len(greenvalley) 
    ngal_green_M, dum = np.histogram(mass[massive[greenvalley]], bins=M_bins)
    if not quiet: 
        print ngal_green, ' green valley galaxies out of ', ngal, ' galaxies'
    
    sfr_class[massive[greenvalley]] = 'star-forming'    # classified as star-forming
    ssfr_q_peak = AverageLogSSFR_q_peak(mass[massive[greenvalley]]) # Q peak SSFR value
    ssfr_sf_peak = AverageLogSFR_sfms(mass[massive[greenvalley]],   # SF peak SSFR value 
            redshift[massive[greenvalley]], 
            sfms_prop=sfms_dict) - mass[massive[greenvalley]]
    ssfr[massive[greenvalley]] = np.random.uniform(ssfr_q_peak, ssfr_sf_peak, ngal_green)
    sfr[massive[greenvalley]] = ssfr[massive[greenvalley]] + mass[massive[greenvalley]]
    tQ[massive[greenvalley]] = Util.get_tsnap(redshift.max())  # quenching cosmic time 
    MQ[massive[greenvalley]] = mass[massive[greenvalley]]
    
    # some green valley galaxies will be classified in observations as 
    # quiescent or star-forming.
    green_class = qfrac.Classify(
            mass[massive[greenvalley]], 
            sfr[massive[greenvalley]], 
            redshift[massive[greenvalley]], 
            sfms_prop=sfms_dict)
    GQ = np.where(green_class == 'quiescent')
    ngal_GQ = len(GQ[0]) 
    ngal_GQ_M, dum = np.histogram(mass[massive[greenvalley[GQ]]], bins=M_bins)

    # f_Q(M*, z) for each massive galaxy
    fq_M = qfrac.model(M_mid, redshift.max(), lit=fq_dict['name']) 
    fq_prime_arr = (ngal_M * fq_M - ngal_GQ_M)/(ngal_M - ngal_green_M)
    fq_prime_arr[np.where(ngal_M == 0)] = 0.
    fq_prime_M = interpolate.interp1d(M_mid, fq_prime_arr, kind='linear') 
    
    # assign SFR to the not so green valley
    notgreenvalley = np.where(rand >= gvfrac)[0]
    ngal_notgreenvalley = len(notgreenvalley) 
    rand_notgreen = np.random.uniform(0., 1., ngal_notgreenvalley)
    
    fq_prime = fq_prime_M(mass[massive[notgreenvalley]])    # fQ'

    lowz = np.where((mass > 0.0) & (redshift != redshift.max()))[0] 
    ngal_lowz = len(lowz)
    rand_lowz = np.random.uniform(0., 1., ngal_lowz) 
    fq_lowz = qfrac.model(mass[lowz], redshift[lowz], lit=fq_dict['name']) 
    quiescent = np.concatenate([
        massive[notgreenvalley[np.where(rand_notgreen < fq_prime)]], 
        lowz[np.where(rand_lowz < fq_lowz)]])
    starforming = np.concatenate([
        massive[notgreenvalley[np.where(rand_notgreen >= fq_prime)]], 
        lowz[np.where(rand_lowz >= fq_lowz)]])
    ngal_q = len(quiescent)
    ngal_sf = len(starforming)

    # Assign SFR to quiescent galaxies
    sfr_class[quiescent] = 'quiescent'
    mu_q_ssfr = AverageLogSSFR_q_peak(mass[quiescent])
    sig_q_ssfr = ScatterLogSSFR_q_peak(mass[quiescent])
    ssfr[quiescent] = sig_q_ssfr * np.random.randn(ngal_q) + mu_q_ssfr 
    sfr[quiescent]  = ssfr[quiescent] + mass[quiescent]
    
    # Assign SFR to star-forming galaxies 
    sfr_class[starforming] = 'star-forming'
    mu_sf_sfr = AverageLogSFR_sfms(
            mass[starforming], 
            redshift[starforming], 
            sfms_prop=sfms_dict)
    sigma_sf_sfr = ScatterLogSFR_sfms(
            mass[starforming], 
            redshift[starforming],
            sfms_prop=sfms_dict)
    avg_sfr[starforming] = mu_sf_sfr
    delta_sfr[starforming] = sigma_sf_sfr * np.random.randn(ngal_sf)
    sfr[starforming] = mu_sf_sfr + delta_sfr[starforming]
    ssfr[starforming] = sfr[starforming] - mass[starforming]

    if 'subhalogrowth' in sfr_prop.keys(): 
        # if SFR assignment is dependent on subhalo growth, 
        # loop through mass bins and assign SFR by abundance matching the 
        # SFR to the Delta M*_sham. 
        mass_range = np.arange(mass[starforming].min(), mass[starforming].max(), 0.1)
        m_low = mass_range[:-1]
        m_high = mass_range[1:]
        for im in range(len(m_low)):
            sf_mass_bin = np.where(
                    (mass[starforming] > m_low[im]) & 
                    (mass[starforming] <= m_high[im]))[0]
            succession, will = Util.intersection_index(
                    ancestor_index, 
                    ancestor.snap_index[starforming])
            deltaM = descendant.mass[succession] - mass[starforming[will]]
            dM_sort_index = np.argsort(deltaM)

            deltaSFR = sigma_sf_sfr * np.random.randn(len(deltaM))
            dSFR_sort_index = np.argsort(deltaSFR)
            # abundance matched.             
            delta_sfr[starforming[will[dM_sort_index]]] = deltaSFR[dSFR_sort_index]

        sfr[starforming] = mu_sf_sfr + delta_sfr[starforming]
        ssfr[starforming] = sfr[starforming] - mass[starforming]
    
    return [sfr_class, sfr, ssfr, delta_sfr, avg_sfr, tQ, MQ]