def param_sfms(self, nsnap = None, **pltkwargs): ''' Plot parameterized SFMS ''' sfr_mstar_z, sig_sfr_mstar_z = get_param_sfr_mstar_z() if nsnap is None: if self.cenque_nsnap is not None: nsnap = self.cenque_nsnap else: raise ValueError('nsnap needs to be specified') if 'justsf' in self.kwargs: self.sub.plot( np.arange(8.5, 12.0, 0.1), sfr_mstar_z(np.arange(8.5, 12.0, 0.1), get_z_nsnap(nsnap)), c = 'k', ls = '--', lw = 3 ) else: plt.plot( np.arange(8.5, 12.0, 0.1), sfr_mstar_z(np.arange(8.5, 12.0, 0.1), get_z_nsnap(nsnap)), c = 'k', ls = '--', lw = 3 ) return None
def param_sfms(self, nsnap=None, **pltkwargs): ''' Plot parameterized SFMS ''' sfr_mstar_z, sig_sfr_mstar_z = get_param_sfr_mstar_z() if nsnap is None: if self.cenque_nsnap is not None: nsnap = self.cenque_nsnap else: raise ValueError('nsnap needs to be specified') if 'justsf' in self.kwargs: self.sub.plot(np.arange(8.5, 12.0, 0.1), sfr_mstar_z(np.arange(8.5, 12.0, 0.1), get_z_nsnap(nsnap)), c='k', ls='--', lw=3) else: plt.plot(np.arange(8.5, 12.0, 0.1), sfr_mstar_z(np.arange(8.5, 12.0, 0.1), get_z_nsnap(nsnap)), c='k', ls='--', lw=3) return None
def rho_ssfr_cq_evol( start_nsnap = 13, final_nsnap = 1, sf_prop = {'name': 'average'}, fq_prop = {'name': 'wetzelsmooth'}, tau_prop = {'name': 'instant'}, mass_evol = 'sham', Mrcut=18, **kwargs ): """ Compare sSFR distribution of evolved CenQue and SDSS Group Catalog in the green valley """ if Mrcut == 18: z_med = 0.03 elif Mrcut == 19: z_med = 0.05 elif Mrcut == 20: z_med = 0.08 evol_cq_ssfr_bin, evol_cq_ssfr_hist = ssfr_cq_evol( start_nsnap = start_nsnap, final_nsnap = final_nsnap, sf_prop = sf_prop, fq_prop = fq_prop, tau_prop = tau_prop, mass_evol = mass_evol, **kwargs ) group_ssfr = Ssfr() group_ssfr_bin, group_ssfr_hist = group_ssfr.groupcat(Mrcut=Mrcut) l2_ssfr = 0.0 for i_massbin, massbin in enumerate(group_ssfr.mass_bins): if not np.array_equal(evol_cq_ssfr_bin[i_massbin], group_ssfr_bin[i_massbin]): raise ValueError() # sSFR comparison range q_ssfr_massbin = np.mean(get_q_ssfr_mean(massbin)) sfr_mstar_z, sig_sfr_mstar_z = get_param_sfr_mstar_z() sf_ssfr_massbin = sfr_mstar_z(massbin[1], z_med) - massbin[1] green_range = np.where( (evol_cq_ssfr_bin[i_massbin] > q_ssfr_massbin) & (evol_cq_ssfr_bin[i_massbin] < sf_ssfr_massbin) ) #print np.sum((evol_cq_ssfr_hist[i_massbin][green_range] - group_ssfr_hist[i_massbin][green_range])**2) l2_ssfr += np.sum((evol_cq_ssfr_hist[i_massbin][green_range] - group_ssfr_hist[i_massbin][green_range])**2) return l2_ssfr
def rho_ssfr_cq_evol(start_nsnap=13, final_nsnap=1, sf_prop={'name': 'average'}, fq_prop={'name': 'wetzelsmooth'}, tau_prop={'name': 'instant'}, mass_evol='sham', Mrcut=18, **kwargs): """ Compare sSFR distribution of evolved CenQue and SDSS Group Catalog in the green valley """ if Mrcut == 18: z_med = 0.03 elif Mrcut == 19: z_med = 0.05 elif Mrcut == 20: z_med = 0.08 evol_cq_ssfr_bin, evol_cq_ssfr_hist = ssfr_cq_evol(start_nsnap=start_nsnap, final_nsnap=final_nsnap, sf_prop=sf_prop, fq_prop=fq_prop, tau_prop=tau_prop, mass_evol=mass_evol, **kwargs) group_ssfr = Ssfr() group_ssfr_bin, group_ssfr_hist = group_ssfr.groupcat(Mrcut=Mrcut) l2_ssfr = 0.0 for i_massbin, massbin in enumerate(group_ssfr.mass_bins): if not np.array_equal(evol_cq_ssfr_bin[i_massbin], group_ssfr_bin[i_massbin]): raise ValueError() # sSFR comparison range q_ssfr_massbin = np.mean(get_q_ssfr_mean(massbin)) sfr_mstar_z, sig_sfr_mstar_z = get_param_sfr_mstar_z() sf_ssfr_massbin = sfr_mstar_z(massbin[1], z_med) - massbin[1] green_range = np.where((evol_cq_ssfr_bin[i_massbin] > q_ssfr_massbin) & (evol_cq_ssfr_bin[i_massbin] < sf_ssfr_massbin)) #print np.sum((evol_cq_ssfr_hist[i_massbin][green_range] - group_ssfr_hist[i_massbin][green_range])**2) l2_ssfr += np.sum((evol_cq_ssfr_hist[i_massbin][green_range] - group_ssfr_hist[i_massbin][green_range])**2) return l2_ssfr
def plot_sfms_wetzel_vs_lee(): ''' Plot Wetzel parameterized SFMS and Lee et al. (2015) parameterized SFMS. ''' # wetzel wetzel_sfr_mstar_z, wetzel_sig_sfr_mstar_z = get_param_sfr_mstar_z() # Lee et al. (2015) z_mid = np.array([0.36, 0.55, 0.70, 0.85, 0.99, 1.19]) logM_lim = np.array([8.50, 9.00, 9.00, 9.30, 9.30, 9.30]) masses = np.arange(7.5, 12.0, 0.1) prettyplot() pretty_colors = prettycolors() fig = plt.figure(figsize=(10,10)) sub = fig.add_subplot(111) for i_z, z in enumerate(z_mid): sub.scatter( masses, lee_et_al_2015(masses, z), c = pretty_colors[i_z], label = r"$\mathtt{z = "+str(round(z, 2))+"}$" ) sub.plot( masses, wetzel_sfr_mstar_z(masses, z), c = pretty_colors[i_z], ls = '--', lw = 3 ) #sub.vlines(logM_lim[i_z], -5.0, 2.0, color='k', linestyle='--', lw=2) sub.set_xlim([7.0, 12.0]) sub.set_ylim([-3.0, 2.0]) sub.set_xlabel(r'$\mathtt{log\;M_*}$', fontsize=30) sub.set_ylabel(r'$\mathtt{log\;SFR}$', fontsize=30) sub.legend(loc='lower right', scatterpoints=1) fig_file = ''.join([ 'figure/', 'qaplot_sfms_wetzel_vs_lee.png' ]) fig.savefig(fig_file, bbox_inches='tight') plt.show()
def plot_sfms_wetzel_vs_lee(): ''' Plot Wetzel parameterized SFMS and Lee et al. (2015) parameterized SFMS. ''' # wetzel wetzel_sfr_mstar_z, wetzel_sig_sfr_mstar_z = get_param_sfr_mstar_z() # Lee et al. (2015) z_mid = np.array([0.36, 0.55, 0.70, 0.85, 0.99, 1.19]) logM_lim = np.array([8.50, 9.00, 9.00, 9.30, 9.30, 9.30]) masses = np.arange(7.5, 12.0, 0.1) prettyplot() pretty_colors = prettycolors() fig = plt.figure(figsize=(10, 10)) sub = fig.add_subplot(111) for i_z, z in enumerate(z_mid): sub.scatter(masses, lee_et_al_2015(masses, z), c=pretty_colors[i_z], label=r"$\mathtt{z = " + str(round(z, 2)) + "}$") sub.plot(masses, wetzel_sfr_mstar_z(masses, z), c=pretty_colors[i_z], ls='--', lw=3) #sub.vlines(logM_lim[i_z], -5.0, 2.0, color='k', linestyle='--', lw=2) sub.set_xlim([7.0, 12.0]) sub.set_ylim([-3.0, 2.0]) sub.set_xlabel(r'$\mathtt{log\;M_*}$', fontsize=30) sub.set_ylabel(r'$\mathtt{log\;SFR}$', fontsize=30) sub.legend(loc='lower right', scatterpoints=1) fig_file = ''.join(['figure/', 'qaplot_sfms_wetzel_vs_lee.png']) fig.savefig(fig_file, bbox_inches='tight') plt.show()
def assign_sfr(cenque, sf_prop={'name': 'average'}, fq_prop={'name': 'wetzelsmooth'}, quiet=True, **kwargs): """ Assign star-formation properties to CenQue object. The function Goes through mass bins and then classifies unassigned galaxies into quiescent/star-forming based on quiescent fraction function. Then SF properties are assigned to the galaxies. For quiescent galaxies the sSFR is drawn from a log normal distribution about some predeterimined mu_sSFR. For star-forming galaxies, SFR is sampled from a designated SF-MS model. ---------------------------------------------------------------- Parameters ---------------------------------------------------------------- cenque : CenQue class object ---------------------------------------------------------------- Notes ---------------------------------------------------------------- * Re imagine how to set up SFR """ # time the code start_time = time.time() if cenque.mass == None: raise ValueError() if cenque.zsnap == None: raise ValueError() if 'sf_prop' not in cenque.__dict__.keys(): cenque.sf_prop = sf_prop else: if cenque.sf_prop != sf_prop: cenque.sf_prop = sf_prop warnings.warn("SF properties do not match; Replacing SF_prop") if 'fq_prop' not in cenque.__dict__.keys(): cenque.fq_prop = fq_prop else: if cenque.fq_prop != fq_prop: warnings.warn("fQ properties do not match") mass_bins = cenque.mass_bins mass_bin_low = mass_bins.mass_low mass_bin_mid = mass_bins.mass_mid mass_bin_high = mass_bins.mass_high # remove galaxies below the minimum and maximum mass and galaxies without children within_massbin_with_child = np.where( (cenque.mass > mass_bins.mass_low.min()) & (cenque.mass <= mass_bins.mass_high.max()) & (cenque.child >= 0)) if (min(cenque.mass) < mass_bins.mass_low.min()) or (max( cenque.mass) > mass_bins.mass_high.max()): cenque.sample_trim(within_massbin_with_child) ngal_tot = len(within_massbin_with_child[0]) for attrib in ['sf_prop', 'fq_prop']: if attrib not in cenque.metadata: cenque.metadata.append(attrib) for attrib in ['gal_type', 'sfr', 'ssfr']: if attrib not in cenque.data_columns: cenque.data_columns.append(attrib) if cenque.gal_type is None: cenque.gal_type = np.array(['' for i in xrange(ngal_tot)], dtype='|S16') cenque.sfr = np.array([-999. for i in xrange(ngal_tot)]) cenque.ssfr = np.array([-999. for i in xrange(ngal_tot)]) # simplest SFR assignment for starforming galaxies. Use mu_SFR(M*, z) # and randomly sampled normal delta_SFR. if sf_prop['name'] == 'average': sfr_mstar_z, sig_sfr_mstar_z = get_param_sfr_mstar_z() if 'delta_sfr' not in cenque.__dict__.keys(): cenque.delta_sfr = np.array([-999. for i in xrange(ngal_tot)]) if 'avg_sfr' not in cenque.__dict__.keys(): cenque.avg_sfr = np.array([-999. for i in xrange(ngal_tot)]) extra_attr = ['avg_sfr', 'delta_sfr'] elif sf_prop['name'] == 'average_noscatter': sfr_mstar_z, sig_sfr_mstar_z = get_param_sfr_mstar_z() if 'delta_sfr' not in cenque.__dict__.keys(): cenque.delta_sfr = np.array([-999. for i in xrange(ngal_tot)]) if 'avg_sfr' not in cenque.__dict__.keys(): cenque.avg_sfr = np.array([-999. for i in xrange(ngal_tot)]) extra_attr = ['avg_sfr', 'delta_sfr'] else: raise NotImplementedError() for attrib in extra_attr: if attrib not in cenque.data_columns: cenque.data_columns.append(attrib) # f_Q(M_*,mid, z_snapshot) qf_massbin = get_fq(mass_bin_mid, cenque.zsnap, lit=fq_prop['name']) massbin_unassigned = [ np.where((cenque.mass > mass_bin_low[i_m]) & (cenque.mass <= mass_bin_high[i_m]) & (cenque.gal_type == ''))[0] for i_m in xrange(mass_bins.nbins) ] # Ngal(M_mid), Ngal,Q(M_mid) and Ngal,SF(M_mid) ngal_massbin = np.array([x.size for x in massbin_unassigned]) ngal_q_massbin = np.rint(qf_massbin * ngal_massbin.astype(float)).astype(int) ngal_sf_massbin = ngal_massbin - ngal_q_massbin # fail-safe for ngal_q_massbin if len(np.where(ngal_q_massbin > ngal_massbin)[0]) > 0: ngal_q_massbin[np.where( ngal_q_massbin > ngal_massbin)] = ngal_massbin[np.where( ngal_q_massbin > ngal_massbin)] for i_m in xrange(mass_bins.nbins): if len(massbin_unassigned[i_m]) == 0: continue begin_loop_time = time.time() if not quiet: print mass_bin_low[i_m], ' < M < ', mass_bin_high[i_m] print 'fQ = ', qf_massbin[i_m], ' Ngal = ', ngal_massbin[i_m] print 'Ngal,Q = ', ngal_q_massbin[ i_m], ' Ngal,SF = ', ngal_sf_massbin[i_m] shuffled_massbin_index = np.arange(ngal_massbin[i_m]) np.random.seed() np.random.shuffle(shuffled_massbin_index) i_q_end = ngal_q_massbin[i_m] # Randomly select ngal_q_massbin quiescent galaxies from the # massbin. Assign them 'quiescent' gal_type and sSFR and SFR # based on a predetermined gaussian distribution about sSFR. if ngal_q_massbin[i_m] > 0: q_massbin = shuffled_massbin_index[:i_q_end] i_q_massbin = (massbin_unassigned[i_m])[q_massbin] cenque.gal_type[i_q_massbin] = 'quiescent' # sample SSFR from log-normal distribution with a preset # 0.18 dex scatter centered about some predetermined mean mu_q_ssfr = util.get_q_ssfr_mean(cenque.mass[i_q_massbin]) if len(i_q_massbin) != ngal_q_massbin[i_m]: print shuffled_massbin_index print q_massbin print i_q_massbin print i_q_end, ngal_q_massbin[i_m] cenque.ssfr[i_q_massbin] = 0.18 * np.random.randn( ngal_q_massbin[i_m]) + mu_q_ssfr cenque.sfr[i_q_massbin] = cenque.ssfr[i_q_massbin] + cenque.mass[ i_q_massbin] # ngal_sf_massbin starforming galaxies from the massbin. Assign # them 'star-forming' gal_type and sSFR and SFR in some manner if ngal_sf_massbin[i_m] > 0: #sf_massbin = shuffled_massbin_index[i_q_end:i_sf_end] sf_massbin = shuffled_massbin_index[i_q_end:] i_sf_massbin = (massbin_unassigned[i_m])[sf_massbin] cenque.gal_type[i_sf_massbin] = 'star-forming' # sample SFR if sf_prop['name'] == 'average': mu_sf_sfr = sfr_mstar_z(cenque.mass[i_sf_massbin], cenque.zsnap) sigma_sf_sfr = sig_sfr_mstar_z(cenque.mass[i_sf_massbin], cenque.zsnap) cenque.avg_sfr[i_sf_massbin] = mu_sf_sfr cenque.delta_sfr[ i_sf_massbin] = sigma_sf_sfr * np.random.randn( ngal_sf_massbin[i_m]) cenque.sfr[ i_sf_massbin] = mu_sf_sfr + cenque.delta_sfr[i_sf_massbin] if not quiet: print 'Starforming galaxies: ' print 'Average(SFR) = ', mu_sf_sfr, ' sigma(SFR) = ', sigma_sf_sfr elif sf_prop['name'] == 'average_noscatter': mu_sf_sfr = sfr_mstar_z(cenque.mass[i_sf_massbin], cenque.zsnap) sigma_sf_sfr = 0.0 cenque.avg_sfr[i_sf_massbin] = mu_sf_sfr cenque.delta_sfr[ i_sf_massbin] = sigma_sf_sfr * np.random.randn( ngal_sf_massbin[i_m]) cenque.sfr[ i_sf_massbin] = mu_sf_sfr + cenque.delta_sfr[i_sf_massbin] if not quiet: print 'Starforming galaxies: ' print 'Average(SFR) = ', mu_sf_sfr, ' sigma(SFR) = ', sigma_sf_sfr else: raise NotImplementedError cenque.ssfr[i_sf_massbin] = cenque.sfr[i_sf_massbin] - cenque.mass[ i_sf_massbin] # double check that SF assign didn't fail anywhere assign_fail = np.where((cenque.sfr == -999.0) | (cenque.ssfr == -999.0)) if len(assign_fail[0]) > 0: raise NameError('Function failed!') if not quiet: print 'Assign SFR function takes', (time.time() - start_time) / 60.0, ' minutes' if 'evol_from' in cenque.cenque_type: pass else: cenque.cenque_type = 'sf_assigned' return cenque
def test_mass_evol( mass0, t0, tf, delmass0=0.1, t_initial=4.0079, sfrevol_param=[1.0, 1.0], sfrevol_prop={'name': 'notperiodic'}, massevol_prop={ 'name': 'integrated', 'type': 'euler', 'f_retain': 0.6, 't_step': 0.025 }, ): ''' Testing integrated mass evolution logSFR(z) function is implemented within this module ''' # spline between z and t_cosmic z, t = np.loadtxt(Util.snapshottable(), unpack=True, usecols=[2, 3]) z_of_t = interpolate.interp1d(list(reversed(t)), list(reversed(z)), kind='cubic') z0 = z_of_t(t0) zf = z_of_t(tf) # average SFR of SF MS logsfr_mstar_z, sig_logsfr_mstar_z = get_param_sfr_mstar_z() def logsfr_notquenched(logmass, t_input, **kwargs): zi = kwargs['z0'] mass_i = kwargs['mass0'] delmass_i = kwargs['deltamass0'] avglogsfr = logsfr_mstar_z(logmass, zi) #print 'SFMS(', mass0[0], ',', str(zi), ') ', avglogsfr[0] # Contribution from the SF evolution of the SFMS logsfr_sfms = sfr_evol.logsfr_sfms_evol(zi, z_of_t(t_input)) # Contribution from the SF Duty cycle logsfr_sfduty = sfr_evol.logsfr_sfduty_fluct( t_initial, t_input, delta_sfr=delmass_i, sfrevol_param=sfrevol_param, **sfrevol_prop) #print logsfr_sfduty logsfr_f = avglogsfr + logsfr_sfms + logsfr_sfduty #print np.max(logsfr_f - logsfr_mstar_z(logmass, z_of_t(t_input))), np.min(logsfr_f - logsfr_mstar_z(logmass, z_of_t(t_input))) return logsfr_f sfrkwargs = {'z0': z0, 'mass0': mass0, 'deltamass0': delmass0} mass_f, sfr_f = mass_evol.integrated(massevol_prop['type'], logsfr_notquenched, mass0, t0, tf, f_retain=massevol_prop['f_retain'], delt=massevol_prop['t_step'], **sfrkwargs) #print sfr_f[:3] #print logsfr_notquenched(mass_f, tf, **sfrkwargs)[:3] #print logsfr_mstar_z(mass0, zf)[:3] return mass_f, sfr_f
def plot_integrated_mass_evol(mass0, t0, tf, sfrevol_prop={'name': 'notperiodic'}, massevol_prop={ 'name': 'integrated', 'type': 'euler', 'f_retain': 0.6, 't_step': 0.05 }, title=None, fig_file=None): ''' Plot of the integrated mass and SFR evolution as a function of cosmic time ''' if title is None: raise ValueError delt = (tf - t0) / 10.0 tfs = np.arange(t0 + delt, tf + delt, delt) z, t = np.loadtxt(Util.snapshottable(), unpack=True, usecols=[2, 3]) z_of_t = interpolate.interp1d(list(reversed(t)), list(reversed(z)), kind='cubic') # SF MS logsfr_mstar_z, sig_logsfr_mstar_z = get_param_sfr_mstar_z() # figure prettyplot() pretty_colors = prettycolors() fig = plt.figure(1, figsize=(10, 12)) # mass evolution m_sub = fig.add_subplot(211) # SFR evolution sub = fig.add_subplot(212) delta_masses = np.arange(-0.3, 0.3, 0.05) #delta_masses = [0.0] # test case for delmass in delta_masses: # SFR evolution parameters (for SF duty cycle) sfrevol_param = sfr_evol.get_sfrevol_param(1, np.array([0]), **sfrevol_prop) masses = [mass0] sfmssfrs = [logsfr_mstar_z(mass0, z_of_t(t0))] sfrs = [logsfr_mstar_z(mass0, z_of_t(t0)) + delmass] mass_i_1 = mass0 t_i_1 = t0 for tf_i in tfs: mass_i, sfr_i = test_mass_evol(mass0, t0, tf_i, delmass0=delmass, t_initial=t0, sfrevol_param=sfrevol_param, sfrevol_prop=sfrevol_prop, massevol_prop=massevol_prop) masses.append(mass_i) sfrs.append(sfr_i) sfmssfrs.append(logsfr_mstar_z(mass0, z_of_t(tf_i))) t_i_1 = tf_i mass_i_1 = mass_i tfs = np.hstack([t0, tfs]) for i in xrange(len(masses[0])): if delmass == delta_masses[0]: m_label = str(mass0[i]) else: m_label = None m_sub.plot(tfs, np.array(masses)[:, i], c=pretty_colors[i], lw=3, alpha=0.5, label=m_label) for i in xrange(len(masses[0])): if delmass == delta_masses[0]: sfr_label = str(mass0[i]) else: sfr_label = None sub.plot(tfs, np.array(sfrs)[:, i], c=pretty_colors[i], lw=2, alpha=0.5, label=sfr_label) sub.plot(tfs, np.array(sfmssfrs)[:, i], c='k', lw=2, ls='--') for tf_i in tfs: sub.vlines(tf_i, -1.0, 2.5, color='k', linewidth=1, linestyle=':') m_sub.set_xlim([t0 - 2.5, tf + 0.5]) m_sub.set_ylim([8.5, 12.5]) m_sub.set_ylabel(r"$\mathtt{log\;M_*}$", fontsize=20) m_sub.set_title(title) sub.set_xlim([t0 - 2.5, tf + 0.5]) sub.set_ylim([-2.0, 2.0]) sub.set_xlabel(r"$\mathtt{t_{cosmic}}$", fontsize=20) sub.set_ylabel(r"$\mathtt{log\;SFR}$", fontsize=20) sub.legend(loc='upper left') if fig_file is not None: figfile = ''.join(['figure/', fig_file]) fig.savefig(figfile, bbox_inches='tight') #plt.show() plt.close()
def evolve_onestep(parent_cq, child_cq, predict_step = 3, quiet=False): """ Evolve CenQue class object by one time step """ evo_start = time.time() mass_bins = child_cq.mass_bins # remove galaxies below the min and max mass within_massbin = np.where( (child_cq.mass > min(mass_bins.mass_low)) & (child_cq.mass <= max(mass_bins.mass_high)) ) child_cq.sample_trim(within_massbin) n_child = len(within_massbin[0]) n_parent = len(parent_cq.mass) # SF and stellar mass properties are added as attributes # to the CenQue object child_cq.gal_type = np.array(['' for i in xrange(n_child)], dtype='|S16') child_cq.sfr = np.array([-999. for i in xrange(n_child)]) child_cq.ssfr = np.array([-999. for i in xrange(n_child)]) child_cq.q_ssfr = np.array([-999. for i in xrange(n_child)]) child_cq.tau = np.array([-999. for i in xrange(n_child)]) child_cq.parent_sfr = np.array([-999. for i in xrange(n_child)]) child_cq.parent_mass = np.array([-999. for i in xrange(n_child)]) child_cq.parent_halo_mass = np.array([-999. for i in xrange(n_child)]) for attrib in ['gal_type', 'sfr', 'ssfr', 'q_ssfr', 'tau', 'parent_sfr', 'parent_mass', 'parent_halo_mass']: if attrib not in child_cq.data_columns: child_cq.data_columns.append(attrib) if child_cq.sf_prop['name'] == 'average': child_cq.delta_sfr = np.array([-999. for i in range(n_child)]) extra_attr = ['delta_sfr'] else: raise NotImplementedError() for attrib in extra_attr: if attrib not in child_cq.data_columns: child_cq.data_columns.append(attrib) # parent children match which assigns indices into dictionaries and then get dictionary values parents, children = parent_children_match(parent_cq.snap_index, child_cq.parent) # Deal with parent to children inheritance (children inherit the parents' attributes) # This step needs to be thought out more. if not quiet: inheritance_time = time.time() child_cq.parent_sfr[children] = parent_cq.sfr[parents] child_cq.parent_mass[children] = parent_cq.mass[parents] child_cq.parent_halo_mass[children] = parent_cq.halo_mass[parents] for attr in child_cq.data_columns: # Inherit everything but the TreePM and Halo information if attr not in ('mass', 'halo_mass', 'parent', 'child', 'ilk', 'snap_index', 'pos', 'parent_sfr', 'parent_mass', 'parent_halo_mass'): try: parent_attr = getattr(parent_cq, attr)[parents] getattr(child_cq, attr)[children] = parent_attr except AttributeError: if 'evol_from' not in parent_cq.cenque_type: pass else: raise ValueError() if not quiet: print 'Inheritance takes ', time.time() - inheritance_time # Stellar mass evolution of star forming galaxies. Either integrated or # SHAM masses assigned from TreePM if child_cq.mass_evol == 'integrated': # integrated SFR mass evolution of star-forming galaxies # (only star-forming galaxies) if kwargs['sfr'] == 'sfr_func': integrated_mass = util.integrated_mass_rk4( util.sfr_squarewave, (child_cq.parent_mass)[sf_child_indx], parent_cq.t_cosmic, child_cq.t_cosmic, amp = (child_cq.sfr_amp)[sf_child_indx], freq = (child_cq.sfr_freq)[sf_child_indx], phase = (child_cq.sfr_phase)[sf_child_indx]) (child_cq.mass)[sf_child_indx] = integrated_mass elif kwargs['sfr'] == 'sfr_avg': (child_cq.mass)[sf_child_indx] = util.integrated_mass_rk4( util.sfr_avg_residual, (child_cq.parent_mass)[sf_child_indx], parent_cq.t_cosmic, child_cq.t_cosmic, resid = (child_cq.sfr_resid)[sf_child_indx]) if not silent: print 'Integrated Mass vs SHAM mass' print (child_cq.mass)[sf_child_indx] - (child_cq.sham_mass)[sf_child_indx] # Evolve Quiescent Children. # Quiecsent galaxies keep the same sSFR while the quiescent galaxy # masses are assigned by SHAM masses quiescent_children = np.where( (child_cq.gal_type[children] == 'quiescent') & (child_cq.tau[children] == -999.0) ) q_children = children[quiescent_children] # correct the SFR in order to preserve SSFR # this is because the mass evolves through SHAM child_cq.sfr[q_children] = child_cq.ssfr[q_children] + child_cq.mass[q_children] # Evolve Star-forming Children # include doucmentation details # include doucmentation details # include doucmentation details # include doucmentation details # include doucmentation details starforming_children = np.where( child_cq.gal_type[children] == 'star-forming' ) sf_children = children[starforming_children] if child_cq.sf_prop['name'] == 'average': sfr_mstar_z, sig_sfr_mstar_z = get_param_sfr_mstar_z() child_sfr = sfr_mstar_z( child_cq.mass[sf_children], child_cq.zsnap ) child_cq.sfr[sf_children] = child_sfr + child_cq.delta_sfr[sf_children] else: raise NotImplementedError() child_cq.ssfr[sf_children] = child_cq.sfr[sf_children] - child_cq.mass[sf_children] # Evolve quenching children by exp(- delta t_cosmic / tau) quenching_time = time.time() still_quenching = np.where(child_cq.tau > 0.0) if len(still_quenching[0]) > 0: # for galaxies with tau, keep them quenching! tau_quench = np.log10( np.exp( -(child_cq.t_cosmic - parent_cq.t_cosmic) / child_cq.tau[still_quenching] ) ) # SFR quenching amount child_cq.sfr[still_quenching] = child_cq.parent_sfr[still_quenching] + tau_quench child_cq.ssfr[still_quenching] = child_cq.sfr[still_quenching] - child_cq.mass[still_quenching] else: if 'evol_from' in parent_cq.cenque_type: if child_cq.tau_prop['name'] != 'instant': raise ValueError() if not quiet: print 'Quenching SF galaxies takes ', time.time() - quenching_time # numpy.where of mass bins mass_bin_indices = np.array([ np.where( (child_cq.mass > mass_bins.mass_low[i_m]) & (child_cq.mass <= mass_bins.mass_high[i_m]) & (child_cq.gal_type != '') ) for i_m in xrange(mass_bins.nbins) ]) # number of galaxies in each of the mass bins ngal_mass_bin = np.array([ len(mass_bin_indices[i_m][0]) for i_m in xrange(mass_bins.nbins) ]) # f_Q of child CenQue as a function of mass # f_Q(M_bin) child_fq = get_fq( mass_bins.mass_mid, child_cq.zsnap, lit = child_cq.fq_prop['name'] ) # f_Q of descendant child_cq.predict_nsnap = child_cq.nsnap - predict_step if child_cq.predict_nsnap < 0: child_cq.predict_nsnap = 0 descendant_fq = get_fq_nsnap( mass_bins.mass_mid, child_cq.predict_nsnap, lit = child_cq.fq_prop['name'] ) descendant_tcosmic = util.get_t_nsnap(child_cq.predict_nsnap) # expected number of quiescent galaxies = Ngal * f_Q # N_gal,exp * f_Q(M_bin) exp_ngal_q = np.rint( child_fq * ngal_mass_bin ).astype(int) child_galtype_list = [ child_cq.gal_type[mass_bin_indices[i_m][0]] for i_m in xrange(mass_bins.nbins) ] sf_massbin_indices = [ (mass_bin_indices[i_m][0])[np.where(child_galtype_list[i_m] == 'star-forming')] for i_m in xrange(mass_bins.nbins) ] ngal_sf_mass_bin = [ len(sf_massbin_indices[i_m]) for i_m in xrange(mass_bins.nbins) ] # quiescent + quenching galaxies q_massbin_indices = [ (mass_bin_indices[i_m][0])[np.where(child_galtype_list[i_m] == 'quiescent')] for i_m in xrange(mass_bins.nbins) ] ngal_q_obs = [ len(np.where(sfq_classify( child_cq.mass[q_massbin_index], child_cq.sfr[q_massbin_index], child_cq.zsnap) == 'quiescent' )[0]) for q_massbin_index in q_massbin_indices ] ngal2quench = exp_ngal_q - ngal_q_obs print ngal2quench #ngal2quench = exp_ngal_q - ngal_mass_bin + ngal_sf_mass_bin exp_exp_ngal_q = np.rint( descendant_fq * ngal_mass_bin ).astype(int) ngal2quenchfuture = exp_exp_ngal_q - ngal_q_obs quench_index = [] quenching_start_time = time.time() # Quench a number of star-forming galaxies in order to match the # quiescent fraction at the next cosmic time step # Tau specifier if child_cq.tau_prop['name'] in ('instant', 'constant', 'satellite', 'long'): tau_str = ''.join(['_', child_cq.tau_prop['name'], 'tau']) elif child_cq.tau_prop['name'] in ('line'): tau_str = ''.join([ '_', child_cq.tau_prop['name'], 'tau', '_Mfid', str(child_cq.tau_prop['fid_mass']), '_slope', str(round(child_cq.tau_prop['slope'], 4)), '_yint', str(round(child_cq.tau_prop['yint'],4)) ]) f = open(''.join(['dat/f_quenching/quenching_fraction', tau_str, '_nsnap', str(child_cq.nsnap), '.dat']), 'w') f.write('# mass, f_quenching\n') f_quenchings = [] for i_m in xrange(mass_bins.nbins): quench_is, f_quenching = quenching_galaxies_massbin( child_cq, child_cq.t_cosmic - parent_cq.t_cosmic, descendant_tcosmic - parent_cq.t_cosmic, child_cq.prev_fquenching[i_m], mass_bins.mass_mid[i_m], mass_bin_indices[i_m], sf_massbin_indices[i_m], ngal2quench[i_m], ngal2quenchfuture[i_m], quiet=quiet ) print mass_bins.mass_mid[i_m], f_quenching, child_cq.prev_fquenching[i_m] f_quenchings.append(f_quenching) quench_index += quench_is f.write( '\t'.join([str(mass_bins.mass_mid[i_m]), str(f_quenching), '\n']) ) f.close() quench_index = np.array(quench_index) child_cq.prev_fquenching = f_quenchings if len(quench_index) != 0: child_cq.gal_type[quench_index] = 'quiescent' # boom quenched # assign quenching e-folds for quenching galaxies child_cq.tau[quench_index] = get_quenching_efold( child_cq.parent_mass[quench_index], tau_param = child_cq.tau_prop ) tau_quench = np.log10( np.exp( -(child_cq.t_cosmic - parent_cq.t_cosmic) / child_cq.tau[quench_index] )) child_cq.sfr[quench_index] = child_cq.parent_sfr[quench_index] + tau_quench child_cq.ssfr[quench_index] = child_cq.sfr[quench_index] - child_cq.mass[quench_index] q_ssfr_mean = util.get_q_ssfr_mean(child_cq.mass[quench_index]) child_cq.q_ssfr[quench_index] = 0.18 * np.random.randn(len(quench_index)) + q_ssfr_mean if not quiet: print 'Quenching takes ', time.time() - quenching_start_time print "Child's redshift = ", child_cq.zsnap # deal with orphans ------------------------------------------------------------ if not quiet: orphan_time = time.time() print len(child_cq.gal_type[child_cq.gal_type == '']), ' child galaxies are orphans' child_cq = assign_sfr(child_cq, tau_prop = child_cq.tau_prop, quiet=quiet) if len(child_cq.gal_type[child_cq.gal_type == '']) != 0: print len(child_cq.gal_type[child_cq.gal_type == '']), ' child galaxies are orphans' raise ValueError() if not quiet: print 'Orphan care takes ', time.time() - orphan_time # deal with galaxies that are being quenched beyond the designated final quenching overquench_time = time.time() over_quenched = np.where(child_cq.ssfr < child_cq.q_ssfr) child_cq.ssfr[over_quenched] = child_cq.q_ssfr[over_quenched] child_cq.tau[over_quenched] = -999.0 # done quenching if not quiet: print 'Overquenching takes ', time.time() - overquench_time print 'Evolution for one time step takes ', time.time() - evo_start print 'Quiescent Fraction = ', np.float(len(parent_cq.gal_type[parent_cq.gal_type == 'quiescent']))/np.float(len(parent_cq.gal_type)) return child_cq
def test_mass_evol(mass0, t0, tf, delmass0 = 0.1, t_initial = 4.0079, sfrevol_param = [1.0, 1.0], sfrevol_prop = {'name': 'notperiodic'}, massevol_prop = {'name': 'integrated', 'type': 'euler', 'f_retain': 0.6, 't_step': 0.025}, ): ''' Testing integrated mass evolution logSFR(z) function is implemented within this module ''' # spline between z and t_cosmic z, t = np.loadtxt(Util.snapshottable(), unpack=True, usecols=[2, 3]) z_of_t = interpolate.interp1d(list(reversed(t)), list(reversed(z)), kind='cubic') z0 = z_of_t(t0) zf = z_of_t(tf) # average SFR of SF MS logsfr_mstar_z, sig_logsfr_mstar_z = get_param_sfr_mstar_z() def logsfr_notquenched(logmass, t_input, **kwargs): zi = kwargs['z0'] mass_i = kwargs['mass0'] delmass_i = kwargs['deltamass0'] avglogsfr = logsfr_mstar_z(logmass, zi) #print 'SFMS(', mass0[0], ',', str(zi), ') ', avglogsfr[0] # Contribution from the SF evolution of the SFMS logsfr_sfms = sfr_evol.logsfr_sfms_evol(zi, z_of_t(t_input)) # Contribution from the SF Duty cycle logsfr_sfduty = sfr_evol.logsfr_sfduty_fluct( t_initial, t_input, delta_sfr=delmass_i, sfrevol_param=sfrevol_param, **sfrevol_prop ) #print logsfr_sfduty logsfr_f = avglogsfr + logsfr_sfms + logsfr_sfduty #print np.max(logsfr_f - logsfr_mstar_z(logmass, z_of_t(t_input))), np.min(logsfr_f - logsfr_mstar_z(logmass, z_of_t(t_input))) return logsfr_f sfrkwargs = {'z0': z0, 'mass0': mass0, 'deltamass0': delmass0} mass_f, sfr_f = mass_evol.integrated( massevol_prop['type'], logsfr_notquenched, mass0, t0, tf, f_retain = massevol_prop['f_retain'], delt = massevol_prop['t_step'], **sfrkwargs ) #print sfr_f[:3] #print logsfr_notquenched(mass_f, tf, **sfrkwargs)[:3] #print logsfr_mstar_z(mass0, zf)[:3] return mass_f, sfr_f
def plot_integrated_mass_evol(mass0, t0, tf, sfrevol_prop = {'name': 'notperiodic'}, massevol_prop = {'name': 'integrated', 'type': 'euler', 'f_retain': 0.6, 't_step': 0.05}, title=None, fig_file=None): ''' Plot of the integrated mass and SFR evolution as a function of cosmic time ''' if title is None: raise ValueError delt = (tf-t0)/10.0 tfs = np.arange(t0+delt, tf+delt, delt) z, t = np.loadtxt(Util.snapshottable(), unpack=True, usecols=[2, 3]) z_of_t = interpolate.interp1d(list(reversed(t)), list(reversed(z)), kind='cubic') # SF MS logsfr_mstar_z, sig_logsfr_mstar_z = get_param_sfr_mstar_z() # figure prettyplot() pretty_colors = prettycolors() fig = plt.figure(1, figsize=(10,12)) # mass evolution m_sub = fig.add_subplot(211) # SFR evolution sub = fig.add_subplot(212) delta_masses = np.arange(-0.3, 0.3, 0.05) #delta_masses = [0.0] # test case for delmass in delta_masses: # SFR evolution parameters (for SF duty cycle) sfrevol_param = sfr_evol.get_sfrevol_param(1, np.array([0]), **sfrevol_prop) masses = [mass0] sfmssfrs = [logsfr_mstar_z(mass0, z_of_t(t0))] sfrs = [logsfr_mstar_z(mass0, z_of_t(t0)) + delmass] mass_i_1 = mass0 t_i_1 = t0 for tf_i in tfs: mass_i, sfr_i = test_mass_evol( mass0, t0, tf_i, delmass0 = delmass, t_initial = t0, sfrevol_param=sfrevol_param, sfrevol_prop = sfrevol_prop, massevol_prop=massevol_prop ) masses.append(mass_i) sfrs.append(sfr_i) sfmssfrs.append(logsfr_mstar_z(mass0, z_of_t(tf_i))) t_i_1 = tf_i mass_i_1 = mass_i tfs = np.hstack([t0, tfs]) for i in xrange(len(masses[0])): if delmass == delta_masses[0]: m_label = str(mass0[i]) else: m_label = None m_sub.plot(tfs, np.array(masses)[:,i], c=pretty_colors[i], lw=3, alpha=0.5, label=m_label) for i in xrange(len(masses[0])): if delmass == delta_masses[0]: sfr_label = str(mass0[i]) else: sfr_label = None sub.plot(tfs, np.array(sfrs)[:,i], c=pretty_colors[i], lw=2, alpha=0.5, label=sfr_label) sub.plot(tfs, np.array(sfmssfrs)[:,i], c='k', lw=2, ls='--') for tf_i in tfs: sub.vlines(tf_i, -1.0, 2.5, color='k', linewidth=1, linestyle=':') m_sub.set_xlim([t0-2.5, tf+0.5]) m_sub.set_ylim([8.5, 12.5]) m_sub.set_ylabel(r"$\mathtt{log\;M_*}$", fontsize=20) m_sub.set_title(title) sub.set_xlim([t0-2.5, tf+0.5]) sub.set_ylim([-2.0, 2.0]) sub.set_xlabel(r"$\mathtt{t_{cosmic}}$", fontsize=20) sub.set_ylabel(r"$\mathtt{log\;SFR}$", fontsize=20) sub.legend(loc='upper left') if fig_file is not None: figfile = ''.join([ 'figure/', fig_file ]) fig.savefig(figfile, bbox_inches='tight') #plt.show() plt.close()
def assign_sfr( cenque, sf_prop={'name': 'average'}, fq_prop={'name': 'wetzelsmooth'}, quiet=True, **kwargs ): """ Assign star-formation properties to CenQue object. The function Goes through mass bins and then classifies unassigned galaxies into quiescent/star-forming based on quiescent fraction function. Then SF properties are assigned to the galaxies. For quiescent galaxies the sSFR is drawn from a log normal distribution about some predeterimined mu_sSFR. For star-forming galaxies, SFR is sampled from a designated SF-MS model. ---------------------------------------------------------------- Parameters ---------------------------------------------------------------- cenque : CenQue class object ---------------------------------------------------------------- Notes ---------------------------------------------------------------- * Re imagine how to set up SFR """ # time the code start_time = time.time() if cenque.mass == None: raise ValueError() if cenque.zsnap == None: raise ValueError() if 'sf_prop' not in cenque.__dict__.keys(): cenque.sf_prop = sf_prop else: if cenque.sf_prop != sf_prop: cenque.sf_prop = sf_prop warnings.warn("SF properties do not match; Replacing SF_prop") if 'fq_prop' not in cenque.__dict__.keys(): cenque.fq_prop = fq_prop else: if cenque.fq_prop != fq_prop: warnings.warn("fQ properties do not match") mass_bins = cenque.mass_bins mass_bin_low = mass_bins.mass_low mass_bin_mid = mass_bins.mass_mid mass_bin_high = mass_bins.mass_high # remove galaxies below the minimum and maximum mass and galaxies without children within_massbin_with_child = np.where( (cenque.mass > mass_bins.mass_low.min()) & (cenque.mass <= mass_bins.mass_high.max()) & (cenque.child >= 0) ) if (min(cenque.mass) < mass_bins.mass_low.min()) or (max(cenque.mass) > mass_bins.mass_high.max()): cenque.sample_trim(within_massbin_with_child) ngal_tot = len(within_massbin_with_child[0]) for attrib in ['sf_prop', 'fq_prop']: if attrib not in cenque.metadata: cenque.metadata.append(attrib) for attrib in ['gal_type', 'sfr', 'ssfr']: if attrib not in cenque.data_columns: cenque.data_columns.append(attrib) if cenque.gal_type is None: cenque.gal_type = np.array(['' for i in xrange(ngal_tot)], dtype='|S16') cenque.sfr = np.array([-999. for i in xrange(ngal_tot)]) cenque.ssfr = np.array([-999. for i in xrange(ngal_tot)]) # simplest SFR assignment for starforming galaxies. Use mu_SFR(M*, z) # and randomly sampled normal delta_SFR. if sf_prop['name'] == 'average': sfr_mstar_z, sig_sfr_mstar_z = get_param_sfr_mstar_z() if 'delta_sfr' not in cenque.__dict__.keys(): cenque.delta_sfr = np.array([-999. for i in xrange(ngal_tot)]) if 'avg_sfr' not in cenque.__dict__.keys(): cenque.avg_sfr = np.array([-999. for i in xrange(ngal_tot)]) extra_attr = ['avg_sfr', 'delta_sfr'] elif sf_prop['name'] == 'average_noscatter': sfr_mstar_z, sig_sfr_mstar_z = get_param_sfr_mstar_z() if 'delta_sfr' not in cenque.__dict__.keys(): cenque.delta_sfr = np.array([-999. for i in xrange(ngal_tot)]) if 'avg_sfr' not in cenque.__dict__.keys(): cenque.avg_sfr = np.array([-999. for i in xrange(ngal_tot)]) extra_attr = ['avg_sfr', 'delta_sfr'] else: raise NotImplementedError() for attrib in extra_attr: if attrib not in cenque.data_columns: cenque.data_columns.append(attrib) # f_Q(M_*,mid, z_snapshot) qf_massbin = get_fq( mass_bin_mid, cenque.zsnap, lit = fq_prop['name'] ) massbin_unassigned = [ np.where( (cenque.mass > mass_bin_low[i_m]) & (cenque.mass <= mass_bin_high[i_m]) & (cenque.gal_type == '') )[0] for i_m in xrange(mass_bins.nbins) ] # Ngal(M_mid), Ngal,Q(M_mid) and Ngal,SF(M_mid) ngal_massbin = np.array([x.size for x in massbin_unassigned]) ngal_q_massbin = np.rint(qf_massbin * ngal_massbin.astype(float)).astype(int) ngal_sf_massbin = ngal_massbin - ngal_q_massbin # fail-safe for ngal_q_massbin if len(np.where(ngal_q_massbin > ngal_massbin)[0]) > 0: ngal_q_massbin[np.where(ngal_q_massbin > ngal_massbin)] = ngal_massbin[np.where(ngal_q_massbin > ngal_massbin)] for i_m in xrange(mass_bins.nbins): if len(massbin_unassigned[i_m]) == 0: continue begin_loop_time = time.time() if not quiet: print mass_bin_low[i_m], ' < M < ', mass_bin_high[i_m] print 'fQ = ', qf_massbin[i_m], ' Ngal = ', ngal_massbin[i_m] print 'Ngal,Q = ', ngal_q_massbin[i_m], ' Ngal,SF = ', ngal_sf_massbin[i_m] shuffled_massbin_index = np.arange(ngal_massbin[i_m]) np.random.seed() np.random.shuffle(shuffled_massbin_index) i_q_end = ngal_q_massbin[i_m] # Randomly select ngal_q_massbin quiescent galaxies from the # massbin. Assign them 'quiescent' gal_type and sSFR and SFR # based on a predetermined gaussian distribution about sSFR. if ngal_q_massbin[i_m] > 0: q_massbin = shuffled_massbin_index[:i_q_end] i_q_massbin = (massbin_unassigned[i_m])[q_massbin] cenque.gal_type[i_q_massbin] = 'quiescent' # sample SSFR from log-normal distribution with a preset # 0.18 dex scatter centered about some predetermined mean mu_q_ssfr = util.get_q_ssfr_mean( cenque.mass[i_q_massbin] ) if len(i_q_massbin) != ngal_q_massbin[i_m]: print shuffled_massbin_index print q_massbin print i_q_massbin print i_q_end, ngal_q_massbin[i_m] cenque.ssfr[i_q_massbin] = 0.18 * np.random.randn(ngal_q_massbin[i_m]) + mu_q_ssfr cenque.sfr[i_q_massbin] = cenque.ssfr[i_q_massbin] + cenque.mass[i_q_massbin] # ngal_sf_massbin starforming galaxies from the massbin. Assign # them 'star-forming' gal_type and sSFR and SFR in some manner if ngal_sf_massbin[i_m] > 0: #sf_massbin = shuffled_massbin_index[i_q_end:i_sf_end] sf_massbin = shuffled_massbin_index[i_q_end:] i_sf_massbin = (massbin_unassigned[i_m])[sf_massbin] cenque.gal_type[i_sf_massbin] = 'star-forming' # sample SFR if sf_prop['name'] == 'average': mu_sf_sfr = sfr_mstar_z(cenque.mass[i_sf_massbin], cenque.zsnap) sigma_sf_sfr = sig_sfr_mstar_z(cenque.mass[i_sf_massbin], cenque.zsnap) cenque.avg_sfr[i_sf_massbin] = mu_sf_sfr cenque.delta_sfr[i_sf_massbin] = sigma_sf_sfr * np.random.randn(ngal_sf_massbin[i_m]) cenque.sfr[i_sf_massbin] = mu_sf_sfr + cenque.delta_sfr[i_sf_massbin] if not quiet: print 'Starforming galaxies: ' print 'Average(SFR) = ', mu_sf_sfr, ' sigma(SFR) = ', sigma_sf_sfr elif sf_prop['name'] == 'average_noscatter': mu_sf_sfr = sfr_mstar_z(cenque.mass[i_sf_massbin], cenque.zsnap) sigma_sf_sfr = 0.0 cenque.avg_sfr[i_sf_massbin] = mu_sf_sfr cenque.delta_sfr[i_sf_massbin] = sigma_sf_sfr * np.random.randn(ngal_sf_massbin[i_m]) cenque.sfr[i_sf_massbin] = mu_sf_sfr + cenque.delta_sfr[i_sf_massbin] if not quiet: print 'Starforming galaxies: ' print 'Average(SFR) = ', mu_sf_sfr, ' sigma(SFR) = ', sigma_sf_sfr else: raise NotImplementedError cenque.ssfr[i_sf_massbin] = cenque.sfr[i_sf_massbin] - cenque.mass[i_sf_massbin] # double check that SF assign didn't fail anywhere assign_fail = np.where( (cenque.sfr == -999.0) | (cenque.ssfr == -999.0) ) if len(assign_fail[0]) > 0: raise NameError('Function failed!') if not quiet: print 'Assign SFR function takes', (time.time()-start_time)/60.0, ' minutes' if 'evol_from' in cenque.cenque_type: pass else: cenque.cenque_type = 'sf_assigned' return cenque
def qaplot_parameterized_sfms(): """ QAplot comparison for the parameterized SFMS redshift evolution in comparison to observed SF-MS redshift evolution. """ gc_zmid, gc_slope, gc_yint = get_bestfit_sfms_groupcat() ec_zmid, ec_slope, ec_yint = get_bestfit_sfms_envcount( fid_mass = 10.5 ) avg_sfr_sfms, sig_sfr_sfms = get_param_sfr_mstar_z() mass_bin = np.arange(9.0, 12.0, 0.25) # mass bin fig = plt.figure() sub = fig.add_subplot(111) sub.scatter( 0.03, gc_yint, c='k', s=50, label='Observed GroupCatalog' ) sub.scatter( ec_zmid, ec_yint, c=prettycolors()[3], label='Observed EnvCount' ) sfr_fidmass = np.array([ avg_sfr_sfms(10.5, zmid) for zmid in np.arange(0.0, 1.0, 0.05) ]) sub.plot( np.arange(0.0, 1.0, 0.05), sfr_fidmass, c='k', lw=4, ls='--', label='Parameterized' ) sub.plot( np.arange(0.0, 1.0, 0.05), sfr_fidmass+0.15, c=prettycolors()[3], lw=4, ls='--' ) sfr_cutoff = np.array([ sfr_cut(10.5, ec_zmid[i_z]) for i_z in xrange(len(ec_zmid)) ]) sub.plot(ec_zmid, sfr_cutoff, c='k', lw=3, ls='--', label='SF/Q Classification') sub.set_xlim([0.0, 1.0]) sub.set_ylim([-1.0, 2.0]) sub.set_ylabel('SFR(M=10.5,z)', fontsize=20) sub.set_xlabel('Redshift (z)', fontsize=20) sub.legend(scatterpoints=1, loc='upper left') plt.show()