Exemplo n.º 1
0
def SimSummary(observables=['ssfr'], **sim_kwargs):
    ''' Summary statistics of the simulation. In our case, the simulation is InheritSF 
    and the summary statistic is the SSFR distribution. 
    '''
    obvs = []
    if 'ssfr' in observables:
        bloodline = InheritSF(
                1,
                nsnap_ancestor=sim_kwargs['nsnap_ancestor'],
                subhalo_prop=sim_kwargs['subhalo_prop'], 
                sfr_prop=sim_kwargs['sfr_prop'], 
                evol_prop=sim_kwargs['evol_prop'])
        descendant = getattr(bloodline, 'descendant_snapshot1') 
        
        bins, dist = descendant.Ssfr()
        obvs.append([np.array(bins), np.array(dist)])
    if 'fqz03' in observables: 
        bloodline = InheritSF(
                6,
                nsnap_ancestor=sim_kwargs['nsnap_ancestor'],
                subhalo_prop=sim_kwargs['subhalo_prop'], 
                sfr_prop=sim_kwargs['sfr_prop'], 
                evol_prop=sim_kwargs['evol_prop'])
        descendant = getattr(bloodline, 'descendant_snapshot6') 

        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:]) 

        sfq = qfrac.Classify(descendant.mass, descendant.sfr, descendant.zsnap, 
                sfms_prop=sim_kwargs['sfr_prop']['sfms'])

        ngal, dum = np.histogram(descendant.mass, bins=M_bin)
        ngal_q, dum = np.histogram(descendant.mass[sfq == 'quiescent'], bins=M_bin)

        obvs.append([M_mid, ngal_q.astype('float')/ngal.astype('float')])
    
    if len(observables) == 1: 
        obvs = obvs[0]
    return obvs
Exemplo n.º 2
0
def ABC(T,
        eps_input,
        Npart=1000,
        cen_tf=None,
        cen_prior_name=None,
        cen_abcrun=None):
    ''' ABC-PMC implementation. 

    Parameters
    ----------
    T : (int) 
        Number of iterations

    eps_input : (float)
        Starting epsilon threshold value 

    N_part : (int)
        Number of particles

    prior_name : (string)
        String that specifies what prior to use.

    abcrun : (string)
        String that specifies abc run information 
    '''
    abcinh = ABCInherit(cen_tf, abcrun=cen_abcrun, prior_name=cen_prior_name)

    # Data (Group Catalog Satellite fQ)
    grpcat = GroupCat(Mrcut=18, position='satellite')
    grpcat.Read()
    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:])

    sfq = qfrac.Classify(grpcat.mass,
                         grpcat.sfr,
                         np.median(grpcat.z),
                         sfms_prop=abcinh.sim_kwargs['sfr_prop']['sfms'])
    ngal, dum = np.histogram(grpcat.mass, bins=m_bin)
    ngal_q, dum = np.histogram(grpcat.mass[sfq == 'quiescent'], bins=m_bin)
    data_sum = [M_mid, ngal_q.astype('float') / ngal.astype('float')]

    # Simulator
    cen_assigned_sat_file = ''.join([
        '/data1/hahn/pmc_abc/pickle/', 'satellite', '.cenassign', '.',
        cen_abcrun, '_ABC', '.', cen_prior_name, '_prior', '.p'
    ])

    if not os.path.isfile(cen_assigned_sat_file):
        sat_cen = AssignCenSFR(cen_tf,
                               abcrun=cen_abcrun,
                               prior_name=cen_prior_name)
        pickle.dump(sat_cen, open(cen_assigned_sat_file, 'wb'))
    else:
        sat_cen = pickle.load(open(cen_assigned_sat_file, 'rb'))

    def Simz(tt):  # Simulator (forward model)
        tqdel_dict = {'name': 'explin', 'm': tt[0], 'b': tt[1]}

        sat_evol = EvolveSatSFR(sat_cen, tqdelay_dict=tqdel_dict)

        sfq_sim = qfrac.Classify(sat_evol.mass,
                                 sat_evol.sfr,
                                 sat_evol.zsnap,
                                 sfms_prop=sat_evol.sfms_prop)
        ngal_sim, dum = np.histogram(sat_evol.mass, bins=m_bin)
        ngal_q_sim, dum = np.histogram(sat_evol.mass[sfq_sim == 'quiescent'],
                                       bins=m_bin)
        sim_sum = [
            M_mid,
            ngal_q_sim.astype('float') / ngal_sim.astype('float')
        ]
        return sim_sum

    # Priors
    prior_min = [-11.75, 2.]
    prior_max = [-10.25, 4.]
    prior = abcpmc.TophatPrior(prior_min, prior_max)  # ABCPMC prior object

    def rho(simum, datum):
        datum_dist = datum[1]
        simum_dist = simum[1]
        drho = np.sum((datum_dist - simum_dist)**2)
        return drho

    abcrun_flag = cen_abcrun + '_central'

    theta_file = lambda pewl: ''.join([
        code_dir(), 'dat/pmc_abc/', 'Satellite.tQdelay.theta_t',
        str(pewl), '_', abcrun_flag, '.dat'
    ])
    w_file = lambda pewl: ''.join([
        code_dir(), 'dat/pmc_abc/', 'Satellite.tQdelay.w_t',
        str(pewl), '_', abcrun_flag, '.dat'
    ])
    dist_file = lambda pewl: ''.join([
        code_dir(), 'dat/pmc_abc/', 'Satellite.tQdelay.dist_t',
        str(pewl), '_', abcrun_flag, '.dat'
    ])
    eps_file = ''.join([
        code_dir(), 'dat/pmc_abc/Satellite.tQdelay.epsilon_', abcrun_flag,
        '.dat'
    ])

    eps = abcpmc.ConstEps(T, eps_input)
    try:
        mpi_pool = mpi_util.MpiPool()
        abcpmc_sampler = abcpmc.Sampler(
            N=Npart,  # N_particles
            Y=data_sum,  # data
            postfn=Simz,  # simulator 
            dist=rho,  # distance function  
            pool=mpi_pool)
    except AttributeError:
        abcpmc_sampler = abcpmc.Sampler(
            N=Npart,  # N_particles
            Y=data_sum,  # data
            postfn=Simz,  # simulator 
            dist=rho)  # distance function
    abcpmc_sampler.particle_proposal_cls = abcpmc.ParticleProposal

    pools = []
    f = open(eps_file, "w")
    f.close()
    eps_str = ''
    for pool in abcpmc_sampler.sample(prior, eps, pool=None):
        print '----------------------------------------'
        print 'eps ', pool.eps
        new_eps_str = '\t' + str(pool.eps) + '\n'
        if eps_str != new_eps_str:  # if eps is different, open fiel and append
            f = open(eps_file, "a")
            eps_str = new_eps_str
            f.write(eps_str)
            f.close()

        print("T:{0},ratio: {1:>.4f}".format(pool.t, pool.ratio))
        print eps(pool.t)

        # write theta, weights, and distances to file
        np.savetxt(theta_file(pool.t),
                   pool.thetas,
                   header='tQdelay_slope, tQdelay_offset')
        np.savetxt(w_file(pool.t), pool.ws)
        np.savetxt(dist_file(pool.t), pool.dists)

        # update epsilon based on median thresholding
        eps.eps = np.median(pool.dists)
        pools.append(pool)

    return pools
Exemplo n.º 3
0
def EvolveSatSFR(sg_in, tqdelay_dict=None):
    ''' Evolve the infalling SFR assigned based on central galaxy SFRs
    '''
    if tqdelay_dict == None:
        raise ValueError

    # initalize
    sg_obj = SGPop()
    sg_obj.ilk = sg_in.ilk.copy()
    sg_obj.pos = sg_in.pos.copy()
    sg_obj.snap_index = sg_in.snap_index.copy()
    sg_obj.zsnap = sg_in.zsnap.copy()
    sg_obj.t_cosmic = sg_in.t_cosmic.copy()
    sg_obj.sfms_prop = sg_in.sfms_prop.copy()
    sg_obj.abcrun = sg_in.abcrun
    sg_obj.prior_name = sg_in.prior_name
    sg_obj.mass = sg_in.mass.copy()
    sg_obj.sfr = np.repeat(-999., len(sg_obj.mass))
    sg_obj.ssfr = np.repeat(-999., len(sg_obj.mass))
    sg_obj.halo_mass = sg_in.halo_mass.copy()
    sg_obj.first_infall_nsnap = sg_in.first_infall_nsnap.copy()
    sg_obj.first_infall_z = sg_in.first_infall_z.copy()
    sg_obj.first_infall_t = sg_in.first_infall_t.copy()
    sg_obj.first_infall_sfr = sg_in.first_infall_sfr.copy()
    sg_obj.first_infall_mass = sg_in.first_infall_mass.copy()
    sg_obj.t_qstart = np.repeat(-999., len(sg_obj.mass))
    sg_obj.z_qstart = np.repeat(-999., len(sg_obj.mass))
    sg_obj.q_ssfr = np.repeat(-999., len(sg_obj.mass))

    # First classify the galaxies into SF, Q, and Qing
    # this is so that t_Q,start = t_inf for Qing galaxies,
    # Q galaxies are left alone
    # SF galaxies are affected by the delay time
    infall = np.where((sg_obj.first_infall_mass > 0.)
                      & (sg_obj.first_infall_sfr > -999.))

    fq_obj = Fq()
    sfq_class = fq_obj.Classify(sg_obj.first_infall_mass[infall],
                                sg_obj.first_infall_sfr[infall],
                                sg_obj.first_infall_z[infall],
                                sg_obj.sfms_prop)

    sf_infall = (infall[0])[np.where(
        sfq_class == 'star-forming')]  # starforming @ infall
    q_infall = (infall[0])[np.where(
        sfq_class == 'quiescent')]  # quiescent @ infall

    ssfr_final = sfr_evol.AverageLogSSFR_q_peak(sg_obj.mass[infall]) + \
            sfr_evol.ScatterLogSSFR_q_peak(sg_obj.mass[infall]) * np.random.randn(len(infall[0]))

    # sub-divide the quiescent @ infall population to those that are
    # quenching @ infall + quiescent @ infall based on simple SSFR cut
    q_mass_infall = sg_obj.first_infall_mass[q_infall]
    q_sfr_infall = sg_obj.first_infall_sfr[q_infall]
    q_ssfr_infall = q_sfr_infall - q_mass_infall

    q_cut_SSFR = sfr_evol.AverageLogSSFR_q_peak(q_mass_infall) + \
            1.5 * sfr_evol.ScatterLogSSFR_q_peak(q_mass_infall)

    qing_infall = q_infall[np.where(q_ssfr_infall > q_cut_SSFR)]  # quenching
    qq_infall = q_infall[np.where(q_ssfr_infall <= q_cut_SSFR)]  # quenched

    # Quiescent @ infall-----
    # The SSFR is preserved from infall, so effectively their SFR decreases
    sg_obj.ssfr[qq_infall] = sg_obj.first_infall_sfr[qq_infall] - \
            sg_obj.first_infall_mass[qq_infall]
    sg_obj.sfr[qq_infall] = sg_obj.mass[qq_infall] + sg_obj.ssfr[qq_infall]

    # Quenching @ infall-----
    # Quenching satellite galaxies skip the delay phase and immediately
    # start quenching when the simulation begins.
    sg_obj.t_qstart[qing_infall] = sg_obj.first_infall_t[qing_infall]
    sg_obj.z_qstart[qing_infall] = sg_obj.first_infall_z[qing_infall]
    sg_obj.q_ssfr[qing_infall] = sfr_evol.AverageLogSSFR_q_peak(sg_obj.mass[qing_infall]) + \
            sfr_evol.ScatterLogSSFR_q_peak(sg_obj.mass[qing_infall]) * np.random.randn(len(qing_infall))

    dlogSFR_MS_M = 0.53 * (sg_obj.mass[qing_infall] -
                           sg_obj.first_infall_mass[qing_infall])

    dlogSFR_MS_z = sg_obj.sfms_prop['zslope'] * (
        sg_obj.zsnap - sg_obj.first_infall_z[qing_infall])

    dlogSFR_Q = sfr_evol.DeltaLogSFR_quenching(sg_obj.t_qstart[qing_infall],
                                               sg_obj.t_cosmic,
                                               M_q=sg_obj.mass[qing_infall],
                                               tau_prop={'name': 'satellite'})

    sg_obj.sfr[qing_infall] = sg_obj.first_infall_sfr[qing_infall] + \
            dlogSFR_MS_M + dlogSFR_MS_z + dlogSFR_Q
    sg_obj.ssfr[
        qing_infall] = sg_obj.sfr[qing_infall] - sg_obj.mass[qing_infall]

    # deal with over quenching
    #overquenched = np.where(sg_obj.ssfr[qing_infall] < sg_obj.q_ssfr[qing_infall])
    #sg_obj.ssfr[qing_infall[overquenched]] = sg_obj.q_ssfr[qing_infall[overquenched]]

    # Star-forming @ infall
    if tqdelay_dict['name'] == 'hacked':
        sg_obj.t_qstart[sf_infall] = sg_obj.first_infall_t[sf_infall] + \
                tDelay(sg_obj.mass[sf_infall], **tqdelay_dict)
    else:
        sg_obj.t_qstart[sf_infall] = sg_obj.first_infall_t[sf_infall] + \
                tDelay(sg_obj.first_infall_mass[sf_infall], **tqdelay_dict)
    # if t_qstart > t_cosmic, then it does not quenching during the simualtion
    sf_q = np.where(sg_obj.t_qstart[sf_infall] < sg_obj.t_cosmic)
    sf_noq = np.where(sg_obj.t_qstart[sf_infall] >= sg_obj.t_cosmic)
    sf_infall_q = sf_infall[sf_q]
    sf_infall_noq = sf_infall[sf_noq]

    sg_obj.z_qstart[sf_infall_q] = Util.get_zsnap(sg_obj.t_qstart[sf_infall_q])
    sg_obj.z_qstart[sf_infall_noq] = 999.

    # SF galaxies that quench
    sg_obj.q_ssfr[sf_infall_q] = \
            sfr_evol.AverageLogSSFR_q_peak(sg_obj.mass[sf_infall_q]) + \
            sfr_evol.ScatterLogSSFR_q_peak(sg_obj.mass[sf_infall_q]) * \
            np.random.randn(len(sf_infall_q))

    dlogSFR_MS_M = 0.53 * (sg_obj.mass[sf_infall_q] -
                           sg_obj.first_infall_mass[sf_infall_q])

    dlogSFR_MS_z = sg_obj.sfms_prop['zslope'] * (
        sg_obj.zsnap - sg_obj.first_infall_z[sf_infall_q])
    dlogSFR_Q = sfr_evol.DeltaLogSFR_quenching(sg_obj.t_qstart[sf_infall_q],
                                               sg_obj.t_cosmic,
                                               M_q=sg_obj.mass[sf_infall_q],
                                               tau_prop={'name': 'satellite'})

    sg_obj.sfr[sf_infall_q] = sg_obj.first_infall_sfr[sf_infall_q] + \
            dlogSFR_MS_M + dlogSFR_MS_z + dlogSFR_Q
    sg_obj.ssfr[
        sf_infall_q] = sg_obj.sfr[sf_infall_q] - sg_obj.mass[sf_infall_q]
    # deal with over quenching
    #overquenched = np.where(sg_obj.ssfr[sf_infall_q] < sg_obj.q_ssfr[sf_infall_q])
    #sg_obj.ssfr[sf_infall_q[overquenched]] = sg_obj.q_ssfr[sf_infall_q[overquenched]]

    # SF galaxies that do NOT quench
    dlogSFR_MS_M = 0.53 * (sg_obj.mass[sf_infall_noq] -
                           sg_obj.first_infall_mass[sf_infall_noq])

    dlogSFR_MS_z = sg_obj.sfms_prop['zslope'] * (
        sg_obj.zsnap - sg_obj.first_infall_z[sf_infall_noq])

    sg_obj.sfr[sf_infall_noq] = sg_obj.first_infall_sfr[sf_infall_noq] + \
            dlogSFR_MS_M + dlogSFR_MS_z
    sg_obj.ssfr[
        sf_infall_noq] = sg_obj.sfr[sf_infall_noq] - sg_obj.mass[sf_infall_noq]

    # deal with overquenching all at once
    overquench = np.where(sg_obj.ssfr[infall] < ssfr_final)
    sg_obj.ssfr[infall[0][overquench]] = ssfr_final[overquench]
    sg_obj.sfr[infall[0][overquench]] = ssfr_final[overquench] + sg_obj.mass[
        infall[0][overquench]]

    return sg_obj
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.º 5
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.º 6
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 
Exemplo n.º 7
0
def SimSummary(observables=['ssfr'], **sim_kwargs):
    ''' Summary statistics of the simulation. In our case, the simulation is Inherit 
    and the summary statistic is the SSFR distribution. 
    '''
    obvs = []

    if 'fqz03' in observables and 'fqz_multi' in observables: 
        raise ValueError

    nsnap_ds = [1]
    if 'fqz03' in observables: 
        nsnap_ds += [6]
    if 'fqz_multi' in observables: 
        nsnap_ds += [3, 6] 

    inh = Inherit(nsnap_ds, 
            nsnap_ancestor=sim_kwargs['nsnap_ancestor'],
            subhalo_prop=sim_kwargs['subhalo_prop'], 
            sfr_prop=sim_kwargs['sfr_prop'], 
            evol_prop=sim_kwargs['evol_prop'])
    des_dict = inh() 

    # SSFR 
    des1 = des_dict['1']
    if 'ssfr' in observables: 
        bins, dist = des1.Ssfr()
        obvs.append([np.array(bins), np.array(dist)])

    if 'fqz03' in observables:  # fQ(nsnap = 6) 
        des6 = des_dict['6']

        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:]) 

        sfq = qfrac.Classify(des6.mass, des6.sfr, des6.zsnap, 
                sfms_prop=sim_kwargs['sfr_prop']['sfms'])

        ngal, dum = np.histogram(des6.mass, bins=M_bin)
        ngal_q, dum = np.histogram(des6.mass[sfq == 'quiescent'], bins=M_bin)

        obvs.append([M_mid, ngal_q.astype('float')/ngal.astype('float')])

    if 'fqz_multi' in observables:  # fQ at multiple snapshots 
        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_list = [M_mid]

        for nd in nsnap_ds: 
            des_tmp = des_dict[str(nd)]

            sfq = qfrac.Classify(des_tmp.mass, des_tmp.sfr, des_tmp.zsnap, 
                    sfms_prop=sim_kwargs['sfr_prop']['sfms'])

            ngal, dum = np.histogram(des_tmp.mass, bins=M_bin)
            ngal_q, dum = np.histogram(des_tmp.mass[sfq == 'quiescent'], bins=M_bin)
            fq_tmp = ngal_q.astype('float')/ngal.astype('float')

            fq_list += [fq_tmp]
        # ancesotr 
        sfq = qfrac.Classify(inh.ancestor.mass, inh.ancestor.sfr, inh.ancestor.zsnap, 
                sfms_prop=sim_kwargs['sfr_prop']['sfms'])
        ngal, dum = np.histogram(inh.ancestor.mass, bins=M_bin)
        ngal_q, dum = np.histogram(inh.ancestor.mass[sfq == 'quiescent'], bins=M_bin)
        fq_tmp = ngal_q.astype('float')/ngal.astype('float')
        fq_list += [fq_tmp]

        obvs.append(fq_list)
    
    if len(observables) == 1: 
        obvs = obvs[0]
    return obvs