def _mini_mocha_galid(lib='bc03'): ''' pick 100 unique Lgal galids that roughly fall under the BGS target selection for the mini mock challenge: r < 20. ''' # gather all galids galids = [] dir_inputs = os.path.join(UT.lgal_dir(), 'gal_inputs') for finput in glob.glob(dir_inputs + '/*'): galids.append(int(os.path.basename(finput).split('_')[2])) galids = np.array(galids) n_id = len(galids) # get noiseless source spectra _, spectra_s = _lgal_noiseless_spectra(galids, lib=lib) # get DECAM photometry photo, _ = FM.Photo_DESI(spectra_s['wave'], spectra_s['flux_dust']) target_selection = (photo[:, 1] <= 20.) print('%i Lgal galaxies within target_selection' % np.sum(target_selection)) # now randomly choose 100 galids mini_galids = np.random.choice(galids[target_selection], size=100, replace=False) fids = os.path.join(UT.dat_dir(), 'mini_mocha', 'lgal.galids.%s.txt' % lib) np.savetxt(fids, mini_galids, fmt='%i', header='%i Lgal galids for mini mock challenge' % len(mini_galids)) return None
def QA_fm_Lgal_mini_mocha(lib='bc03'): ''' quality assurance/sanity plots ''' import matplotlib as mpl import matplotlib.pyplot as plt mpl.rcParams['text.usetex'] = True mpl.rcParams['font.family'] = 'serif' mpl.rcParams['axes.linewidth'] = 1.5 mpl.rcParams['axes.xmargin'] = 1 mpl.rcParams['xtick.labelsize'] = 'x-large' mpl.rcParams['xtick.major.size'] = 5 mpl.rcParams['xtick.major.width'] = 1.5 mpl.rcParams['ytick.labelsize'] = 'x-large' mpl.rcParams['ytick.major.size'] = 5 mpl.rcParams['ytick.major.width'] = 1.5 mpl.rcParams['legend.frameon'] = False # read mini mocha data fmm = h5py.File( os.path.join(UT.dat_dir(), 'mini_mocha', 'lgal.mini_mocha.%s.v%s.hdf5' % (lib, version)), 'r') ngal = fmm['spec_flux_source'][...].shape[0] # plot BGS spectra and source spectra for sanity checks fig = plt.figure(figsize=(15, 15)) for ii, i in enumerate( np.random.choice(np.arange(ngal), size=3, replace=False)): sub = fig.add_subplot(3, 1, ii + 1) for band in ['b', 'r', 'z']: sub.plot(fmm['spec_wave_%s_bgs' % band][...], fmm['spec_flux_%s_bgs' % band][...][0, i, :], c='C0') sub.plot(fmm['spec_wave_source'][...], fmm['spec_fiber_flux_source'][...][i, :], c='k', ls='--') sub.set_xlim(3.6e3, 9.8e3) sub.set_ylim(-2, 10) sub.set_xlabel('wavelength', fontsize=25) fig.savefig(os.path.join(UT.dat_dir(), 'mini_mocha', 'lgal.mini_mocha.%s.v%s.png' % (lib, version)), bbox_inches='tight') return None
def Fbestfit_specphoto(igal, noise='bgs0_legacy', sample='mini_mocha', method='ifsps'): ''' file name of best-fit of photometry of spectral_challenge galaxy #igal :param igal: index of spectral_challenge galaxy :param noise: noise of the spectra. If noise == 'none', no noise. If noise =='legacy', then legacy like noise. (default: 'none') :param sample: mini_mocha :param method: fitting method. (default: ifsps) ''' model = 'vanilla' f_bf = os.path.join( UT.dat_dir(), sample, 'ifsps', 'lgal.specphoto.noise_%s.%s.%i.hdf5' % (noise, model, igal)) return f_bf
def compare_FSPS_Speculator(): ''' ''' tt_i = np.array([0.25, 0.25, 0.25, 0.25, 1e-4, 1e-4, 0., 1.5]) w0, lum0 = FSPS_sspLum(tt_i) w1, lum1 = Speculator_sspLum(tt_i) wlim0 = (w0 > 3e3) wlim1 = (w1 > 3e3) print(np.sum(lum0)) print(np.sum(lum1)) print(lum0[wlim0]) print(lum1[wlim1]) fig = plt.figure(figsize=(10, 5)) sub = fig.add_subplot(111) sub.plot(w0, lum0, c='k', label='FSPS') sub.plot(w1, lum1, c='C0', label='Speculator') sub.set_xlim(3e3, 1e4) ffig = os.path.join(UT.dat_dir(), '_fsps_speculator_comparison.png') fig.savefig(ffig, bbox_inches='tight') return None
def fm_TNG_minimocha(): ''' generate spectroscopy and photometry for the mini Mock Challenge (MoCha) * input: galaxy properties (SFH, ZH, etc), noiseless spectra * "true" photometry directly from noiseless spectra * assign photometric uncertainty and fiber flux using legacy imaging * "measured" photometry and fiber flux + fiber source spectra (scaled down noiseless spectra), * "BGS" spectra notes ----- * only 5000 galaxies for the mini_mocha ''' from scipy.spatial import cKDTree as KDTree # read TNG source spectra ftng = h5py.File(os.path.join(UT.dat_dir(), 'tng', 'tng.hdf5'), 'r') wave = ftng['wave'][...] sed = ftng['sed_neb'][...][:5000, :] # SED with nebular emission lines ngal = sed.shape[0] print('%i illustris tng galaxies' % ngal) _wave_s = wave * u.Angstrom _spec_s = sed * u.Lsun / u.Hz H0 = 70 * u.km / u.s / u.Mpc # 0a. assign redshifts z ~ U(0.001, 0.4) zred = np.random.uniform(0.001, 0.4, size=ngal) # 0b. generate 'true' photometry from noiseless spectra wave_s = np.tile(_wave_s.value, (ngal, 1)) # redshift wavelength wave_s *= (1. + zred[:, None]) # convert fluxes _spec = _spec_s / ( 4. * np.pi * (zred[:, None] * const.c / H0).to(u.cm)**2) / _wave_s**2 * const.c spec_s = (_spec.to(u.erg / u.s / u.cm**2 / u.Angstrom)).value * 1e17 photo_true, mag_true = FM.Photo_DESI(wave_s, spec_s) # r < 20 cut target_selection = (mag_true[:, 1] <= 20.) # compile meta data meta = {} meta['logM_total'] = ftng['logmstar'][...][:ngal][target_selection] meta['sfr_100myr'] = 10.**ftng['logsfr.100'][...][:ngal][target_selection] meta['redshift'] = zred[target_selection] # save to metadata # 1. generate 'true' photometry from noiseless spectra wave_s = wave_s[target_selection, :] spec_s = spec_s[target_selection, :] photo_true = photo_true[target_selection, :] # 2. assign uncertainties to the photometry using BGS targets from the Legacy survey bgs_targets = h5py.File( os.path.join(UT.dat_dir(), 'bgs.1400deg2.rlim21.0.hdf5'), 'r') n_targets = len(bgs_targets['ra'][...]) bands = ['g', 'r', 'z', 'w1', 'w2', 'w3', 'w4'] bgs_photo = np.zeros((n_targets, len(bands))) bgs_photo_ivar = np.zeros((n_targets, len(bands))) bgs_fiberflux = np.zeros(n_targets) # r-band fiber flux for ib, band in enumerate(bands): bgs_photo[:, ib] = bgs_targets['flux_%s' % band][...] bgs_photo_ivar[:, ib] = bgs_targets['flux_ivar_%s' % band][...] bgs_fiberflux = bgs_targets['fiberflux_r'][...] # construct KD tree from BGS targets (currently downsampled) bgs_features = np.array([ bgs_photo[:, 0], bgs_photo[:, 1], bgs_photo[:, 2], bgs_photo[:, 0] - bgs_photo[:, 1], bgs_photo[:, 1] - bgs_photo[:, 2] ]).T tree = KDTree(bgs_features) # match ivars and fiberflux match_features = np.array([ photo_true[:, 0], photo_true[:, 1], photo_true[:, 2], photo_true[:, 0] - photo_true[:, 1], photo_true[:, 1] - photo_true[:, 2] ]).T dist, indx = tree.query(match_features) photo_ivars = bgs_photo_ivar[indx, :] photo_fiber_true = bgs_fiberflux[indx] # 3.a. apply the uncertainty to the photometry to get "measured" photometry. photo_meas = photo_true + photo_ivars**-0.5 * np.random.randn( photo_true.shape[0], photo_true.shape[1]) # ***this needs to be checked; sometimes it gives greater than 1*** # ***this needs to be checked; sometimes it gives greater than 1*** # ***this needs to be checked; sometimes it gives greater than 1*** # ***this needs to be checked; sometimes it gives greater than 1*** f_fiber = np.clip(photo_fiber_true / photo_true[:, 1], None, 1.) # (r fiber flux) / (r total flux) meta['logM_fiber'] = np.log10(f_fiber) + meta['logM_total'] # apply uncertainty to fiber flux as well photo_fiber_meas = photo_fiber_true + f_fiber * photo_ivars[:, 1]**-0.5 * np.random.randn( photo_true. shape[0]) photo_ivar_fiber = f_fiber**-2 * photo_ivars[:, 1] # 3.b. get fiber spectra by scaling down noiseless Lgal source spectra spectra_fiber = spec_s * f_fiber[:, None] # 10e-17 erg/s/cm2/A # 4. generate BGS like spectra # read in sampled observing conditions, sky brightness, and exposure time _fsky = os.path.join(UT.dat_dir(), 'mini_mocha', 'bgs.exposure.surveysim.150s.v0p4.sample.hdf5') fsky = h5py.File(_fsky, 'r') nexp = len(fsky['airmass'][...]) # number of exposures wave_sky = fsky['wave'][...] # sky wavelength sbright_sky = fsky['sky'][...] # store to meta-data for k in [ 'airmass', 'moon_alt', 'moon_ill', 'moon_sep', 'seeing', 'sun_alt', 'sun_sep', 'texp_total', 'transp' ]: meta[k] = fsky[k][...] meta['wave_sky'] = wave_sky meta['sbright_sky'] = sbright_sky # generate BGS spectra for the exposures spectra_bgs = {} for iexp in range(nexp): # sky brightness of exposure Isky = [wave_sky, sbright_sky[iexp]] fbgs = os.path.join( UT.dat_dir(), 'mini_mocha', 'tng.mini_mocha.bgs_spec.%iof%i.fits' % (iexp + 1, nexp)) # interpolate source spectra onto linearly spaced wavelengths wlin = np.linspace(1e3, 2e4, 19000) spectra_fiber_lin = np.zeros((spectra_fiber.shape[0], len(wlin))) for i in range(spectra_fiber.shape[0]): spectra_fiber_lin[i] = np.interp(wlin, wave_s[i, :], spectra_fiber[i, :]) bgs_spec = FM.Spec_BGS( wlin, # wavelength spectra_fiber_lin, # fiber spectra flux fsky['texp_total'][...][iexp], # exp time fsky['airmass'][...][iexp], # airmass Isky, filename=fbgs) if iexp == 0: spectra_bgs['wave_b'] = bgs_spec.wave['b'] spectra_bgs['wave_r'] = bgs_spec.wave['r'] spectra_bgs['wave_z'] = bgs_spec.wave['z'] spectra_bgs['flux_b'] = np.zeros( (nexp, bgs_spec.flux['b'].shape[0], bgs_spec.flux['b'].shape[1])) spectra_bgs['flux_r'] = np.zeros( (nexp, bgs_spec.flux['r'].shape[0], bgs_spec.flux['r'].shape[1])) spectra_bgs['flux_z'] = np.zeros( (nexp, bgs_spec.flux['z'].shape[0], bgs_spec.flux['z'].shape[1])) spectra_bgs['ivar_b'] = np.zeros( (nexp, bgs_spec.flux['b'].shape[0], bgs_spec.flux['b'].shape[1])) spectra_bgs['ivar_r'] = np.zeros( (nexp, bgs_spec.flux['r'].shape[0], bgs_spec.flux['r'].shape[1])) spectra_bgs['ivar_z'] = np.zeros( (nexp, bgs_spec.flux['z'].shape[0], bgs_spec.flux['z'].shape[1])) spectra_bgs['flux_b'][iexp] = bgs_spec.flux['b'] spectra_bgs['flux_r'][iexp] = bgs_spec.flux['r'] spectra_bgs['flux_z'][iexp] = bgs_spec.flux['z'] spectra_bgs['ivar_b'][iexp] = bgs_spec.ivar['b'] spectra_bgs['ivar_r'][iexp] = bgs_spec.ivar['r'] spectra_bgs['ivar_z'][iexp] = bgs_spec.ivar['z'] # write out everything fmeta = os.path.join(UT.dat_dir(), 'mini_mocha', 'tng.mini_mocha.meta.p') pickle.dump(meta, open(fmeta, 'wb')) # meta-data fout = h5py.File( os.path.join(UT.dat_dir(), 'mini_mocha', 'tng.mini_mocha.hdf5'), 'w') fout.create_dataset('redshift', data=zred) # photometry for i, b in enumerate(bands): # 'true' fout.create_dataset('photo_flux_%s_true' % b, data=photo_true[:, i]) fout.create_dataset('photo_ivar_%s_true' % b, data=photo_ivars[:, i]) # 'measured' fout.create_dataset('photo_flux_%s_meas' % b, data=photo_meas[:, i]) # fiber flux fout.create_dataset('photo_fiberflux_r_true', data=photo_fiber_true) fout.create_dataset('photo_fiberflux_r_meas', data=photo_fiber_meas) fout.create_dataset('photo_fiberflux_r_ivar', data=photo_ivar_fiber) fout.create_dataset('frac_fiber', data=f_fiber) # fraction of flux in fiber # spectroscopy # noiseless source spectra wlim = (_wave_s.value > 1e3) & (_wave_s.value < 2e4) fout.create_dataset('spec_wave_source', data=wave_s[:, wlim]) fout.create_dataset('spec_flux_source', data=spec_s[:, wlim]) # noiseless source spectra in fiber fout.create_dataset('spec_fiber_flux_source', data=spectra_fiber[:, wlim]) # BGS source spectra for k in spectra_bgs.keys(): fout.create_dataset('spec_%s_bgs' % k, data=spectra_bgs[k]) fout.close() return None
def cigale_dir(sample='mini_mocha'): return os.path.join(UT.dat_dir(), sample, 'cigale')
def validate_sample(sim): ''' generate some plots to validate the mini Mock Challenge photometry and spectroscopy ''' # read photometry photo, _ = Data.Photometry(sim=sim, noise='legacy', sample='mini_mocha') photo_g = 22.5 - 2.5 * np.log10(photo['flux'][:, 0]) photo_r = 22.5 - 2.5 * np.log10(photo['flux'][:, 1]) photo_z = 22.5 - 2.5 * np.log10(photo['flux'][:, 2]) flux_g = photo['flux'][:, 0] * 1e-9 * 1e17 * UT.c_light() / 4750.**2 * ( 3631. * UT.jansky_cgs()) flux_r = photo['flux'][:, 1] * 1e-9 * 1e17 * UT.c_light() / 6350.**2 * ( 3631. * UT.jansky_cgs()) flux_z = photo['flux'][:, 2] * 1e-9 * 1e17 * UT.c_light() / 9250.**2 * ( 3631. * UT.jansky_cgs()) # convert to 10^-17 ergs/s/cm^2/Ang ivar_g = photo['ivar'][:, 0] * (1e-9 * 1e17 * UT.c_light() / 4750.**2 * (3631. * UT.jansky_cgs()))**-2. ivar_r = photo['ivar'][:, 1] * (1e-9 * 1e17 * UT.c_light() / 6350.**2 * (3631. * UT.jansky_cgs()))**-2. ivar_z = photo['ivar'][:, 2] * ( 1e-9 * 1e17 * UT.c_light() / 9250.**2 * (3631. * UT.jansky_cgs()))**-2. # convert to 10^-17 ergs/s/cm^2/Ang # read BGS targets from imaging bgs_targets = h5py.File( os.path.join(UT.dat_dir(), 'bgs.1400deg2.rlim21.0.hdf5'), 'r') n_targets = len(bgs_targets['ra'][...]) bgs_g = 22.5 - 2.5 * np.log10(bgs_targets['flux_g'][...])[::10] bgs_r = 22.5 - 2.5 * np.log10(bgs_targets['flux_r'][...])[::10] bgs_z = 22.5 - 2.5 * np.log10(bgs_targets['flux_z'][...])[::10] # photometry validation fig = plt.figure(figsize=(6, 6)) sub = fig.add_subplot(111) DFM.hist2d(bgs_g - bgs_r, bgs_r - bgs_z, color='k', levels=[0.68, 0.95], range=[[-1., 3.], [-1., 3.]], bins=40, smooth=0.5, plot_datapoints=True, fill_contours=False, plot_density=False, linewidth=0.5, ax=sub) sub.scatter([-100.], [-100], c='k', s=1, label='BGS targets') sub.scatter(photo_g - photo_r, photo_r - photo_z, c='C0', s=1, label='LGal photometry') sub.legend(loc='upper left', handletextpad=0, markerscale=10, fontsize=20) sub.set_xlabel('$g-r$', fontsize=25) sub.set_xlim(-1., 3.) sub.set_ylabel('$r-z$', fontsize=25) sub.set_ylim(-1., 3.) ffig = os.path.join(UT.dat_dir(), 'mini_mocha', 'mini_mocha.%s.photo.png' % sim) fig.savefig(ffig, bbox_inches='tight') fig.savefig(UT.fig_tex(ffig, pdf=True), bbox_inches='tight') # read spectra spec_s, _ = Data.Spectra(sim=sim, noise='none', sample='mini_mocha') spec_bgs0, _ = Data.Spectra(sim=sim, noise='bgs0', sample='mini_mocha') spec_bgs1, _ = Data.Spectra(sim=sim, noise='bgs1', sample='mini_mocha') spec_bgs2, _ = Data.Spectra(sim=sim, noise='bgs2', sample='mini_mocha') # read sky brightness _fsky = os.path.join(UT.dat_dir(), 'mini_mocha', 'bgs.exposure.surveysim.150s.v0p4.sample.hdf5') fsky = h5py.File(_fsky, 'r') wave_sky = fsky['wave'][...] # sky wavelength sbright_sky = fsky['sky'][...] # spectra validationg fig = plt.figure(figsize=(10, 5)) sub = fig.add_subplot(111) for i, spec_bgs in enumerate([spec_bgs2, spec_bgs0]): wsort = np.argsort(spec_bgs['wave']) if i == 0: _plt, = sub.plot(spec_bgs['wave'][wsort], spec_bgs['flux'][0, wsort], c='C%i' % i, lw=0.25) else: sub.plot(spec_bgs['wave'][wsort], spec_bgs['flux'][0, wsort], c='C%i' % i, lw=0.25) _plt_photo = sub.errorbar( [4750, 6350, 9250], [flux_g[0], flux_r[0], flux_z[0]], [ivar_g[0]**-0.5, ivar_r[0]**-0.5, ivar_z[0]**-0.5], fmt='.r') _plt_sim, = sub.plot(spec_s['wave'][0, :], spec_s['flux'][0, :], c='k', ls='-', lw=1) _plt_sim0, = sub.plot(spec_s['wave'][0, :], spec_s['flux_unscaled'][0, :], c='k', ls=':', lw=0.25) leg = sub.legend([_plt_sim0, _plt_photo, _plt_sim, _plt], [ '%s spectrum' % sim.upper(), '%s photometry' % sim.upper(), '%s fiber spectrum' % sim.upper(), '%s BGS spectra' % sim.upper() ], loc='upper right', fontsize=17) for legobj in leg.legendHandles: legobj.set_linewidth(2.0) sub.set_xlabel('Wavelength [$A$]', fontsize=20) sub.set_xlim(3e3, 1e4) sub.set_ylabel('flux [$10^{-17} erg/s/cm^2/A$', fontsize=20) if sim == 'lgal': sub.set_ylim(-2., 8.) elif sim == 'tng': sub.set_ylim(0., None) ffig = os.path.join(UT.dat_dir(), 'mini_mocha', 'mini_mocha.%s.spectra.png' % sim) fig.savefig(ffig, bbox_inches='tight') fig.savefig(UT.fig_tex(ffig, pdf=True), bbox_inches='tight') return None
def fit_pFF_spectra(igal, noise='none', iter_max=10, overwrite=False): ''' Fit Lgal spectra. `noise` specifies whether to fit spectra without noise or with BGS-like noise. :param igal: index of Lgal galaxy within the spectral_challenge :param noise: If 'none', fit noiseless spectra. If 'bgs1'...'bgs8', fit BGS-like spectra. (default: 'none') :param justplot: If True, skip the fitting and plot the best-fit. This is mainly implemented because I'm having issues plotting in NERSC. (default: False) ''' # read noiseless Lgal spectra of the spectral_challenge mocks specs, meta = Data.Spectra(sim='lgal', noise=noise, lib='bc03', sample='mini_mocha') model = 'vanilla' w_obs = specs['wave'] flux_obs = specs['flux'][igal] if noise != 'none': ivar_obs = specs['ivar'][igal] truths = [ meta['logM_fiber'][igal], np.log10(meta['Z_MW'][igal]), meta['t_age_MW'][igal] ] labels = ['$\log M_*$', '$\log Z$', r'$t_{\rm age}$'] if noise == 'none': # no noise ivar_obs = np.ones(len(w_obs)) print('--- input ---') print('z = %f' % meta['redshift'][igal]) print('log M* total = %f' % meta['logM_total'][igal]) print('log M* fiber = %f' % meta['logM_fiber'][igal]) print('MW Z = %f' % meta['Z_MW'][igal]) print('MW tage = %f' % meta['t_age_MW'][igal]) f_bf = os.path.join(UT.dat_dir(), 'mini_mocha', 'pff', 'lgal.spec.noise_%s.%s.%i.hdf5' % (noise, model, igal)) if os.path.isfile(f_bf): if not overwrite: print("** CAUTION: %s already exists **" % os.path.basename(f_bf)) # initiating fit pff = Fitters.pseudoFirefly(model_name=model, prior=None) bestfit = pff.Fit_spec(w_obs, flux_obs, ivar_obs, meta['redshift'][igal], mask='emline', fit_cap=1000, iter_max=10, writeout=f_bf, silent=False) print('--- bestfit ---') print('written to %s' % f_bf) print('log M* = %f' % bestfit['theta_med'][0]) print('log Z = %f' % bestfit['theta_med'][1]) print('---------------') fig = plt.figure(figsize=(12, 4)) sub = fig.add_subplot(111) sub.plot(bestfit['wavelength_data'], bestfit['flux_data'], c='k', zorder=1, lw=0.5) sub.plot(bestfit['wavelength_model'] * (1. + bestfit['redshift']), bestfit['flux_model'], c='C1') sub.set_xlabel('Wavelength', fontsize=20) sub.set_xlim(3500, 1e4) sub.set_ylabel('Flux', fontsize=20) sub.set_ylim(0., None) fig.savefig(f_bf.replace('.hdf5', '.png'), bbox_inches='tight') return None
def fit_spectrophotometry(igal, sim='lgal', noise='bgs0_legacy', method='ifsps', model='emulator', nwalkers=100, burnin=100, niter='adaptive', maxiter=200000, opt_maxiter=100, overwrite=False, postprocess=False, justplot=False): ''' Fit Lgal spectra. `noise` specifies whether to fit spectra without noise or with BGS-like noise. Produces an MCMC chain and, if not on nersc, a corner plot of the posterior. :param igal: index of Lgal galaxy within the spectral_challenge :param noise: If 'bgs1'...'bgs8', fit BGS-like spectra. (default: 'none') :param justplot: If True, skip the fitting and plot the best-fit. This is mainly implemented because I'm having issues plotting in NERSC. (default: False) ''' noise_spec = noise.split('_')[0] noise_photo = noise.split('_')[1] # read noiseless Lgal spectra of the spectral_challenge mocks specs, meta = Data.Spectra(sim=sim, noise=noise_spec, lib='bc03', sample='mini_mocha') # read Lgal photometry of the mini_mocha mocks photo, _ = Data.Photometry(sim=sim, noise=noise_photo, lib='bc03', sample='mini_mocha') if meta['redshift'][igal] < 0.101: # current Speculator wavelength doesn't extend far enough # current Speculator wavelength doesn't extend far enough # current Speculator wavelength doesn't extend far enough # current Speculator wavelength doesn't extend far enough # current Speculator wavelength doesn't extend far enough return None w_obs = specs['wave'] flux_obs = specs['flux'][igal] ivar_obs = specs['ivar'][igal] if method == 'ispeculator': photo_obs = photo['flux'][igal, :3] photo_ivar_obs = photo['ivar'][igal, :3] else: photo_obs = photo['flux'][igal, :5] photo_ivar_obs = photo['ivar'][igal, :5] # get fiber flux factor prior range based on measured fiber flux f_fiber_true = (photo['fiberflux_r_true'][igal] / photo['flux_r_true'][igal]) prior_width = np.max([ 0.05, 5. * photo['fiberflux_r_ivar'][igal]**-0.5 / photo['flux'][igal, 1] ]) f_fiber_min = ( photo['fiberflux_r_meas'][igal]) / photo['flux'][igal, 1] - prior_width f_fiber_max = ( photo['fiberflux_r_meas'][igal]) / photo['flux'][igal, 1] + prior_width f_fiber_prior = [f_fiber_min, f_fiber_max] print('--- input ---') print('z = %f' % meta['redshift'][igal]) print('log M* total = %f' % meta['logM_total'][igal]) print('log M* fiber = %f' % meta['logM_fiber'][igal]) print('f_fiber = %f' % f_fiber_true) print('log SFR 100myr = %f' % np.log10(meta['sfr_100myr'][igal])) print('log Z_MW = %f' % np.log10(meta['Z_MW'][igal])) f_mcmc = os.path.join( UT.dat_dir(), 'mini_mocha', method, '%s.specphoto.noise_%s.%s.%i.mcmc.hdf5' % (sim, noise, model, igal)) if method == 'ifsps': ifitter = Fitters.iFSPS(model_name=model) elif method == 'ispeculator': ifitter = Fitters.iSpeculator(model_name=model) print('--- mcmc ---') if (justplot or not overwrite) and os.path.isfile(f_mcmc): print(' reading... %s' % os.path.basename(f_mcmc)) # read in mcmc chain fmcmc = h5py.File(f_mcmc, 'r') mcmc = {} for k in fmcmc.keys(): mcmc[k] = fmcmc[k][...] fmcmc.close() else: if os.path.isfile(f_mcmc) and not overwrite: print("** CAUTION: %s already exists **" % os.path.basename(f_mcmc)) print(' writing... %s' % os.path.basename(f_mcmc)) # initiating fit prior = ifitter._default_prior(f_fiber_prior=f_fiber_prior) mcmc = ifitter.MCMC_spectrophoto(w_obs, flux_obs, ivar_obs, photo_obs, photo_ivar_obs, meta['redshift'][igal], mask='emline', prior=prior, nwalkers=nwalkers, burnin=burnin, niter=niter, maxiter=maxiter, opt_maxiter=opt_maxiter, writeout=f_mcmc, silent=False) if postprocess: print('--- postprocessing ---') f_post = f_mcmc.replace('.mcmc.hdf5', '.postproc.hdf5') mcmc = ifitter.postprocess(mcmc_output=mcmc, writeout=f_post) i_fib = list(mcmc['theta_names'].astype(str)).index('f_fiber') print('log M* total = %f' % mcmc['theta_med'][0]) print('log M* fiber = %f' % (mcmc['theta_med'][0] + np.log10(mcmc['theta_med'][i_fib]))) print('---------------') try: # plotting on nersc never works. if os.environ['NERSC_HOST'] == 'cori': return None except KeyError: labels = [lbl_dict[_t] for _t in mcmc['theta_names'].astype(str)] truths = [None for _ in labels] truths[0] = meta['logM_total'][igal] truths[i_fib] = f_fiber_true if postprocess: i_sfr = list( mcmc['theta_names'].astype(str)).index('logsfr.100myr') truths[i_sfr] = np.log10(meta['sfr_100myr'][igal]) i_zw = list(mcmc['theta_names'].astype(str)).index('logz.mw') truths[i_zw] = np.log10(meta['Z_MW'][igal]) print('log SFR 100myr = %f' % np.median(mcmc['mcmc_chain'][:, i_sfr])) print('log Z_MW = %f' % np.median(mcmc['mcmc_chain'][:, i_zw])) # corner plot of the posteriors fig = DFM.corner(mcmc['mcmc_chain'], range=mcmc['prior_range'], quantiles=[0.16, 0.5, 0.84], levels=[0.68, 0.95], nbin=40, smooth=True, truths=truths, labels=labels, label_kwargs={'fontsize': 20}) if postprocess: fig.savefig(f_post.replace('.hdf5', '.png'), bbox_inches='tight') else: fig.savefig(f_mcmc.replace('.hdf5', '.png'), bbox_inches='tight') plt.close() fig = plt.figure(figsize=(18, 5)) gs = mpl.gridspec.GridSpec(1, 2, figure=fig, width_ratios=[1, 3], wspace=0.2) sub = plt.subplot(gs[0]) sub.errorbar(np.arange(len(photo_obs)), photo_obs, yerr=photo_ivar_obs**-0.5, fmt='.k', label='data') sub.scatter(np.arange(len(photo_obs)), mcmc['flux_photo_model'], c='C1', label='model') sub.legend(loc='upper left', markerscale=3, handletextpad=0.2, fontsize=15) sub.set_xticks([0, 1, 2, 3, 4]) sub.set_xticklabels(['$g$', '$r$', '$z$', 'W1', 'W2']) sub.set_xlim(-0.5, len(photo_obs) - 0.5) sub = plt.subplot(gs[1]) sub.plot(w_obs, flux_obs, c='k', lw=1, label='data') sub.plot(mcmc['wavelength_model'], mcmc['flux_spec_model'], c='C1', ls='--', lw=1, label=method) sub.legend(loc='upper right', fontsize=15) sub.set_xlabel('wavelength [$A$]', fontsize=20) sub.set_xlim(3600., 9800.) sub.set_ylim(-1., 5.) if postprocess: fig.savefig(f_post.replace('.hdf5', '.bestfit.png'), bbox_inches='tight') else: fig.savefig(f_mcmc.replace('.hdf5', '.bestfit.png'), bbox_inches='tight') plt.close() return None
def fit_photometry(igal, sim='lgal', noise='legacy', method='ifsps', model='emulator', nwalkers=100, burnin=100, niter='adaptive', maxiter=200000, opt_maxiter=100, overwrite=False, postprocess=False, justplot=False): ''' Fit simulated photometry. `noise` specifies whether to fit spectra without noise or with legacy-like noise. `dust` specifies whether to if spectra w/ dust or not. Produces an MCMC chain and, if not on nersc, a corner plot of the posterior. :param igal: index of Lgal galaxy within the spectral_challenge :param noise: If 'none', fit noiseless photometry. If 'legacy', fit Legacy-like photometry. (default: 'none') :param justplot: If True, skip the fitting and plot the best-fit. This is mainly implemented because I'm having issues plotting in NERSC. (default: False) ''' # read Lgal photometry of the mini_mocha mocks photo, meta = Data.Photometry(sim=sim, noise=noise, lib='bc03', sample='mini_mocha') if meta['redshift'][igal] < 0.101: # current Speculator wavelength doesn't extend far enough # current Speculator wavelength doesn't extend far enough # current Speculator wavelength doesn't extend far enough # current Speculator wavelength doesn't extend far enough # current Speculator wavelength doesn't extend far enough return None print('--- input ---') print('z = %f' % meta['redshift'][igal]) print('log M* total = %f' % meta['logM_total'][igal]) print('log SFR 100myr = %f' % np.log10(meta['sfr_100myr'][igal])) print('log Z MW = %f' % np.log10(meta['Z_MW'][igal])) if method == 'ispeculator': photo_obs = photo['flux'][igal, :3] ivar_obs = photo['ivar'][igal, :3] else: photo_obs = photo['flux'][igal, :5] ivar_obs = photo['ivar'][igal, :5] f_mcmc = os.path.join( UT.dat_dir(), 'mini_mocha', method, '%s.photo.noise_%s.%s.%i.mcmc.hdf5' % (sim, noise, model, igal)) # initiating fit if method == 'ifsps': ifitter = Fitters.iFSPS(model_name=model) elif method == 'ispeculator': ifitter = Fitters.iSpeculator(model_name=model) print('--- bestfit ---') if (justplot or not overwrite) and os.path.isfile(f_mcmc): # read in best-fit file with mcmc chain print(' reading in %s' % f_mcmc) fmcmc = h5py.File(f_mcmc, 'r') mcmc = {} for k in fmcmc.keys(): mcmc[k] = fmcmc[k][...] fmcmc.close() else: if os.path.isfile(f_mcmc) and not overwrite: print("** CAUTION: %s already exists **" % os.path.basename(f_bf)) print(' writing %s' % f_mcmc) prior = ifitter._default_prior(f_fiber_prior=None) mcmc = ifitter.MCMC_photo(photo_obs, ivar_obs, meta['redshift'][igal], bands='desi', prior=prior, nwalkers=nwalkers, burnin=burnin, niter=niter, maxiter=maxiter, opt_maxiter=opt_maxiter, writeout=f_mcmc, silent=False) if postprocess: print('--- postprocessing ---') f_post = f_mcmc.replace('.mcmc.hdf5', '.postproc.hdf5') mcmc = ifitter.postprocess(mcmc_output=mcmc, writeout=f_post) print('log M* total = %f' % mcmc['theta_med'][0]) print('---------------') try: # plotting on nersc never works. if os.environ['NERSC_HOST'] == 'cori': return None except KeyError: labels = [lbl_dict[_t] for _t in mcmc['theta_names'].astype(str)] truths = [None for _ in labels] truths[0] = meta['logM_total'][igal] if postprocess: i_sfr = list( mcmc['theta_names'].astype(str)).index('logsfr.100myr') truths[i_sfr] = np.log10(meta['sfr_100myr'][igal]) i_zmw = list(mcmc['theta_names'].astype(str)).index('logz.mw') truths[i_zmw] = np.log10(meta['Z_MW'][igal]) print('log SFR 100myr = %f' % np.median(mcmc['mcmc_chain'][:, i_sfr])) print('log Z MW = %f' % np.median(mcmc['mcmc_chain'][:, i_zmw])) fig = DFM.corner(mcmc['mcmc_chain'], range=mcmc['prior_range'], quantiles=[0.16, 0.5, 0.84], levels=[0.68, 0.95], nbin=40, smooth=True, truths=truths, labels=labels, label_kwargs={'fontsize': 20}) if postprocess: fig.savefig(f_post.replace('.hdf5', '.png'), bbox_inches='tight') else: fig.savefig(f_mcmc.replace('.hdf5', '.png'), bbox_inches='tight') plt.close() fig = plt.figure(figsize=(5, 3)) sub = fig.add_subplot(111) sub.errorbar(np.arange(len(photo_obs)), photo_obs, yerr=ivar_obs**-0.5, fmt='.k', label='data') sub.scatter(np.arange(len(photo_obs)), mcmc['flux_photo_model'], c='C1', label='model') sub.legend(loc='upper left', markerscale=3, handletextpad=0.2, fontsize=15) sub.set_xticks([0, 1, 2]) sub.set_xticklabels(['$g$', '$r$', '$z$']) sub.set_xlim(-0.5, len(photo_obs) - 0.5) if postprocess: fig.savefig(f_post.replace('.hdf5', '.bestfit.png'), bbox_inches='tight') else: fig.savefig(f_mcmc.replace('.hdf5', '.bestfit.png'), bbox_inches='tight') plt.close() return None
# --- plotting --- import matplotlib as mpl import matplotlib.pyplot as plt mpl.rcParams['text.usetex'] = True mpl.rcParams['font.family'] = 'serif' mpl.rcParams['axes.linewidth'] = 1.5 mpl.rcParams['axes.xmargin'] = 1 mpl.rcParams['xtick.labelsize'] = 'x-large' mpl.rcParams['xtick.major.size'] = 5 mpl.rcParams['xtick.major.width'] = 1.5 mpl.rcParams['ytick.labelsize'] = 'x-large' mpl.rcParams['ytick.major.size'] = 5 mpl.rcParams['ytick.major.width'] = 1.5 mpl.rcParams['legend.frameon'] = False dir_fig = os.path.join(UT.dat_dir(), 'mini_mocha') def mini_mocha_spec(noise='bgs0_legacy', sample='mini_mocha', method='ifsps'): ''' Compare properties inferred from forward modeled spectra to input properties ''' if noise != 'none': noise_spec = noise.split('_')[0] noise_photo = noise.split('_')[1] else: noise_spec = 'none' noise_photo = 'none' # read noiseless Lgal spectra of the spectral_challenge mocks specs, meta = Data.Spectra(sim='lgal', noise=noise_spec, lib='bc03',
def fm_Lgal_mini_mocha(lib='bc03'): ''' generate spectroscopy and photometry for the mini Mock Challenge (MoCha) * input: galaxy properties (SFH, ZH, etc), noiseless spectra * "true" photometry directly from noiseless spectra * assign photometric uncertainty and fiber flux using legacy imaging * "measured" photometry and fiber flux + fiber source spectra (scaled down noiseless spectra), * "BGS" spectra ''' from scipy.spatial import cKDTree as KDTree # read in mini mocha galids fids = os.path.join(UT.dat_dir(), 'mini_mocha', 'lgal.galids.%s.txt' % lib) galids = np.loadtxt(fids, skiprows=1) # get Lgal meta data _meta = _lgal_metadata(galids) # get noiseless source spectra _meta_spec, spectra_s = _lgal_noiseless_spectra(galids, lib=lib) # compile meta-data meta = {} for k in _meta.keys(): meta[k] = _meta[k] for k in _meta_spec.keys(): meta[k] = _meta_spec[k] print('%.2f < z < %.2f' % (meta['redshift'].min(), meta['redshift'].max())) # 1. generate 'true' photometry from noiseless spectra photo_true, _ = FM.Photo_DESI(spectra_s['wave'], spectra_s['flux_dust']) # 2. assign uncertainties to the photometry using BGS targets from the Legacy survey bgs_targets = h5py.File( os.path.join(UT.dat_dir(), 'bgs.1400deg2.rlim21.0.hdf5'), 'r') n_targets = len(bgs_targets['ra'][...]) bands = ['g', 'r', 'z', 'w1', 'w2', 'w3', 'w4'] bgs_photo = np.zeros((n_targets, len(bands))) bgs_photo_ivar = np.zeros((n_targets, len(bands))) bgs_fiberflux = np.zeros(n_targets) # r-band fiber flux for ib, band in enumerate(bands): bgs_photo[:, ib] = bgs_targets['flux_%s' % band][...] bgs_photo_ivar[:, ib] = bgs_targets['flux_ivar_%s' % band][...] bgs_fiberflux = bgs_targets['fiberflux_r'][...] # construct KD tree from BGS targets (currently downsampled) bgs_features = np.array([ bgs_photo[:, 0], bgs_photo[:, 1], bgs_photo[:, 2], bgs_photo[:, 0] - bgs_photo[:, 1], bgs_photo[:, 1] - bgs_photo[:, 2] ]).T tree = KDTree(bgs_features) # match ivars and fiberflux match_features = np.array([ photo_true[:, 0], photo_true[:, 1], photo_true[:, 2], photo_true[:, 0] - photo_true[:, 1], photo_true[:, 1] - photo_true[:, 2] ]).T dist, indx = tree.query(match_features) photo_ivars = bgs_photo_ivar[indx, :] photo_fiber_true = bgs_fiberflux[indx] # 3.a. apply the uncertainty to the photometry to get "measured" photometry. photo_meas = photo_true + photo_ivars**-0.5 * np.random.randn( photo_true.shape[0], photo_true.shape[1]) f_fiber = photo_fiber_true / photo_true[:, 1] # (r fiber flux) / (r total flux) assert f_fiber.max() <= 1. meta['logM_fiber'] = np.log10(f_fiber) + meta['logM_total'] # apply uncertainty to fiber flux as well photo_fiber_meas = photo_fiber_true + f_fiber * photo_ivars[:, 1]**-0.5 * np.random.randn( photo_true. shape[0]) photo_ivar_fiber = f_fiber**-2 * photo_ivars[:, 1] # 3.b. get fiber spectra by scaling down noiseless Lgal source spectra spectra_fiber = spectra_s[ 'flux_dust'] * f_fiber[:, None] # 10e-17 erg/s/cm2/A # 4. generate BGS like spectra # read in sampled observing conditions, sky brightness, and exposure time _fsky = os.path.join(UT.dat_dir(), 'mini_mocha', 'bgs.exposure.surveysim.150s.v0p4.sample.hdf5') fsky = h5py.File(_fsky, 'r') nexp = len(fsky['airmass'][...]) # number of exposures wave_sky = fsky['wave'][...] # sky wavelength sbright_sky = fsky['sky'][...] # store to meta-data for k in [ 'airmass', 'moon_alt', 'moon_ill', 'moon_sep', 'seeing', 'sun_alt', 'sun_sep', 'texp_total', 'transp' ]: meta[k] = fsky[k][...] meta['wave_sky'] = wave_sky meta['sbright_sky'] = sbright_sky # generate BGS spectra for the exposures spectra_bgs = {} for iexp in range(nexp): # sky brightness of exposure Isky = [wave_sky * u.Angstrom, sbright_sky[iexp]] fbgs = os.path.join( UT.dat_dir(), 'mini_mocha', 'lgal.bgs_spec.%s.v%s.%iof%i.fits' % (lib, version, iexp + 1, nexp)) bgs_spec = FM.Spec_BGS( spectra_s['wave'], # wavelength spectra_fiber, # fiber spectra flux fsky['texp_total'][...][iexp], # exp time fsky['airmass'][...][iexp], # airmass Isky, filename=fbgs) if iexp == 0: spectra_bgs['wave_b'] = bgs_spec.wave['b'] spectra_bgs['wave_r'] = bgs_spec.wave['r'] spectra_bgs['wave_z'] = bgs_spec.wave['z'] spectra_bgs['flux_b'] = np.zeros( (nexp, bgs_spec.flux['b'].shape[0], bgs_spec.flux['b'].shape[1])) spectra_bgs['flux_r'] = np.zeros( (nexp, bgs_spec.flux['r'].shape[0], bgs_spec.flux['r'].shape[1])) spectra_bgs['flux_z'] = np.zeros( (nexp, bgs_spec.flux['z'].shape[0], bgs_spec.flux['z'].shape[1])) spectra_bgs['ivar_b'] = np.zeros( (nexp, bgs_spec.flux['b'].shape[0], bgs_spec.flux['b'].shape[1])) spectra_bgs['ivar_r'] = np.zeros( (nexp, bgs_spec.flux['r'].shape[0], bgs_spec.flux['r'].shape[1])) spectra_bgs['ivar_z'] = np.zeros( (nexp, bgs_spec.flux['z'].shape[0], bgs_spec.flux['z'].shape[1])) spectra_bgs['flux_b'][iexp] = bgs_spec.flux['b'] spectra_bgs['flux_r'][iexp] = bgs_spec.flux['r'] spectra_bgs['flux_z'][iexp] = bgs_spec.flux['z'] spectra_bgs['ivar_b'][iexp] = bgs_spec.ivar['b'] spectra_bgs['ivar_r'][iexp] = bgs_spec.ivar['r'] spectra_bgs['ivar_z'][iexp] = bgs_spec.ivar['z'] # write out everything fmeta = os.path.join(UT.dat_dir(), 'mini_mocha', 'lgal.mini_mocha.%s.v%s.meta.p' % (lib, version)) fout = h5py.File( os.path.join(UT.dat_dir(), 'mini_mocha', 'lgal.mini_mocha.%s.v%s.hdf5' % (lib, version)), 'w') pickle.dump(meta, open(fmeta, 'wb')) # meta-data # photometry for i, b in enumerate(bands): # 'true' fout.create_dataset('photo_flux_%s_true' % b, data=photo_true[:, i]) fout.create_dataset('photo_ivar_%s_true' % b, data=photo_ivars[:, i]) # 'measured' fout.create_dataset('photo_flux_%s_meas' % b, data=photo_meas[:, i]) # fiber flux fout.create_dataset('photo_fiberflux_r_true', data=photo_fiber_true) fout.create_dataset('photo_fiberflux_r_meas', data=photo_fiber_meas) fout.create_dataset('photo_fiberflux_r_ivar', data=photo_ivar_fiber) fout.create_dataset('frac_fiber', data=f_fiber) # fraction of flux in fiber # spectroscopy # noiseless source spectra wlim = (spectra_s['wave'] < 2e5) & (spectra_s['wave'] > 1e3 ) # truncating the spectra fout.create_dataset('spec_wave_source', data=spectra_s['wave'][wlim]) fout.create_dataset('spec_flux_source', data=spectra_s['flux_dust'][:, wlim]) # noiseless source spectra in fiber fout.create_dataset('spec_fiber_flux_source', data=spectra_fiber[:, wlim]) # BGS source spectra for k in spectra_bgs.keys(): fout.create_dataset('spec_%s_bgs' % k, data=spectra_bgs[k]) fout.close() return None
def fit_spectrophotometry(igal, noise='none', nwalkers=100, burnin=100, niter=1000, overwrite=False, justplot=False): ''' Fit Lgal spectra. `noise` specifies whether to fit spectra without noise or with BGS-like noise. Produces an MCMC chain and, if not on nersc, a corner plot of the posterior. :param igal: index of Lgal galaxy within the spectral_challenge :param noise: If 'none', fit noiseless spectra. If 'bgs1'...'bgs8', fit BGS-like spectra. (default: 'none') :param justplot: If True, skip the fitting and plot the best-fit. This is mainly implemented because I'm having issues plotting in NERSC. (default: False) ''' if noise != 'none': noise_spec = noise.split('_')[0] noise_photo = noise.split('_')[1] else: noise_spec = 'none' noise_photo = 'none' # read noiseless Lgal spectra of the spectral_challenge mocks specs, meta = Data.Spectra(sim='lgal', noise=noise_spec, lib='bc03', sample='mini_mocha') # read Lgal photometry of the mini_mocha mocks photo, _ = Data.Photometry(sim='lgal', noise=noise_photo, lib='bc03', sample='mini_mocha') model = 'vanilla' w_obs = specs['wave'] flux_obs = specs['flux'][igal] if noise_spec != 'none': ivar_obs = specs['ivar'][igal] else: ivar_obs = np.ones(len(w_obs)) photo_obs = photo['flux'][igal,:5] if noise_photo != 'none': photo_ivar_obs = photo['ivar'][igal,:5] else: photo_ivar_obs = np.ones(photo_obs.shape[0]) # get fiber flux factor prior range based on measured fiber flux f_fiber_true = (photo['fiberflux_r_meas'][igal]/photo['flux_r_true'][igal]) f_fiber_min = (photo['fiberflux_r_meas'][igal] - 3.*photo['fiberflux_r_ivar'][igal]**-0.5)/photo['flux'][igal,1] f_fiber_max = (photo['fiberflux_r_meas'][igal] + 3.*photo['fiberflux_r_ivar'][igal]**-0.5)/photo['flux'][igal,1] f_fiber_prior = [f_fiber_min, f_fiber_max] print(f_fiber_prior) print(f_fiber_true) print((photo['fiberflux_r_true'][igal]/photo['flux_r_true'][igal])) truths = [meta['logM_total'][igal], np.log10(meta['Z_MW'][igal]), meta['t_age_MW'][igal], None, None, f_fiber_true] labels = ['$\log M_*$', '$\log Z$', r'$t_{\rm age}$', 'dust2', r'$\tau$', r'$f_{\rm fiber}$'] print('--- input ---') print('z = %f' % meta['redshift'][igal]) print('log M* total = %f' % meta['logM_total'][igal]) print('log M* fiber = %f' % meta['logM_fiber'][igal]) print('MW Z = %f' % meta['Z_MW'][igal]) print('MW tage = %f' % meta['t_age_MW'][igal]) f_bf = os.path.join(UT.dat_dir(), 'mini_mocha', 'ifsps', 'lgal.specphoto.noise_%s.%s.%i.hdf5' % (noise, model, igal)) if not justplot: if os.path.isfile(f_bf): if not overwrite: print("** CAUTION: %s already exists **" % os.path.basename(f_bf)) # initiating fit ifsps = Fitters.iFSPS(model_name=model, prior=None) bestfit = ifsps.MCMC_spectrophoto( w_obs, flux_obs, ivar_obs, photo_obs, photo_ivar_obs, meta['redshift'][igal], f_fiber_prior=f_fiber_prior, mask='emline', nwalkers=nwalkers, burnin=burnin, niter=niter, writeout=f_bf, silent=False) else: # read in best-fit file with mcmc chain fbestfit = h5py.File(f_bf, 'r') bestfit = {} for k in fbestfit.keys(): bestfit[k] = fbestfit[k][...] print('--- bestfit ---') print('written to %s' % f_bf) print('log M* total = %f' % bestfit['theta_med'][0]) print('log M* fiber = %f' % (bestfit['theta_med'][0] + np.log10(bestfit['theta_med'][-1]))) print('log Z = %f' % bestfit['theta_med'][1]) print('---------------') try: # plotting on nersc never works. if os.environ['NERSC_HOST'] == 'cori': return None except KeyError: # corner plot of the posteriors fig = DFM.corner(bestfit['mcmc_chain'], range=bestfit['priors'], quantiles=[0.16, 0.5, 0.84], levels=[0.68, 0.95], nbin=40, smooth=True, truths=truths, labels=labels, label_kwargs={'fontsize': 20}) fig.savefig(f_bf.replace('.hdf5', '.png'), bbox_inches='tight') return None
def fit_photometry(igal, noise='none', nwalkers=100, burnin=100, niter=1000, overwrite=False, justplot=False): ''' Fit Lgal photometry. `noise` specifies whether to fit spectra without noise or with legacy-like noise. `dust` specifies whether to if spectra w/ dust or not. Produces an MCMC chain and, if not on nersc, a corner plot of the posterior. :param igal: index of Lgal galaxy within the spectral_challenge :param noise: If 'none', fit noiseless photometry. If 'legacy', fit Legacy-like photometry. (default: 'none') :param justplot: If True, skip the fitting and plot the best-fit. This is mainly implemented because I'm having issues plotting in NERSC. (default: False) ''' # read Lgal photometry of the mini_mocha mocks photo, meta = Data.Photometry(sim='lgal', noise=noise, lib='bc03', sample='mini_mocha') model = 'vanilla' photo_obs = photo['flux'][igal,:5] if noise != 'none': ivar_obs = photo['ivar'][igal,:5] truths = [meta['logM_total'][igal], np.log10(meta['Z_MW'][igal]), meta['t_age_MW'][igal], None, None] labels = ['$\log M_*$', '$\log Z$', r'$t_{\rm age}$', 'dust2', r'$\tau$'] if noise == 'none': # no noise ivar_obs = np.ones(photo_obs.shape[0]) print('--- input ---') print('z = %f' % meta['redshift'][igal]) print('log M* total = %f' % meta['logM_total'][igal]) print('MW Z = %f' % meta['Z_MW'][igal]) print('MW tage = %f' % meta['t_age_MW'][igal]) f_bf = os.path.join(UT.dat_dir(), 'mini_mocha', 'ifsps', 'lgal.photo.noise_%s.%s.%i.hdf5' % (noise, model, igal)) if not justplot: if os.path.isfile(f_bf): if not overwrite: print("** CAUTION: %s already exists **" % os.path.basename(f_bf)) return None # initiate fitting ifsps = Fitters.iFSPS(model_name=model, prior=None) bestfit = ifsps.MCMC_photo( photo_obs, ivar_obs, meta['redshift'][igal], bands='desi', nwalkers=nwalkers, burnin=burnin, niter=niter, writeout=f_bf, silent=False) else: # read in best-fit file with mcmc chain fbestfit = h5py.File(f_bf, 'r') bestfit = {} for k in fbestfit.keys(): bestfit[k] = fbestfit[k][...] print('--- bestfit ---') print('written to %s ---' % f_bf) print('log M* = %f' % bestfit['theta_med'][0]) print('log Z = %f' % bestfit['theta_med'][1]) print('---------------') try: # plotting on nersc never works. if os.environ['NERSC_HOST'] == 'cori': return None except KeyError: fig = DFM.corner(bestfit['mcmc_chain'], range=bestfit['priors'], quantiles=[0.16, 0.5, 0.84], levels=[0.68, 0.95], nbin=40, smooth=True, truths=truths, labels=labels, label_kwargs={'fontsize': 20}) fig.savefig(f_bf.replace('.hdf5', '.png'), bbox_inches='tight') return None