def test(): from sedpy import observate import fsps import matplotlib.pyplot as pl filters = [ 'galex_NUV', 'sdss_u0', 'sdss_r0', 'sdss_r0', 'sdss_i0', 'sdss_z0', 'bessell_U', 'bessell_B', 'bessell_V', 'bessell_R', 'bessell_I', 'twomass_J', 'twomass_H' ] flist = observate.load_filters(filters) sps = fsps.StellarPopulation(compute_vega_mags=False) wave, spec = sps.get_spectrum(tage=1.0, zmet=2, peraa=True) sed = observate.getSED(wave, spec, flist) sed_unc = np.abs(np.random.normal(1, 0.3, len(sed))) wgrid = np.linspace(2e3, 13e3, 1000) fgrid = np.linspace(-13, -9, 100) psed, sedpoints = sed_to_psed(flist, sed, sed_unc, wgrid, fgrid) pl.imshow(np.exp(psed).T, cmap='Greys_r', interpolation='nearest', origin='upper', aspect='auto')
def norm_spectrum(obs, norm_band_name='f475w', **kwargs): """Initial guess of spectral normalization using photometry. This obtains the multiplicative factor required to reproduce the the photometry in one band from the observed spectrum (model.obs['spectrum']) using the bsfh unit conventions. Thus multiplying the observed spectrum by this factor gives a spectrum that is approximately erg/s/cm^2/AA at the central wavelength of the normalizing band. The inverse of the multiplication factor is saved as a fixed parameter to be used in producing the mean model. """ from sedpy import observate norm_band = [i for i, f in enumerate(obs['filters']) if norm_band_name in f.name][0] synphot = observate.getSED(obs['wavelength'], obs['spectrum'], obs['filters']) synphot = np.atleast_1d(synphot) # Factor by which the observed spectra should be *divided* to give you the # photometry (or the cgs apparent spectrum), using the given filter as # truth. Alternatively, the factor by which the model spectrum (in cgs # apparent) should be multiplied to give you the observed spectrum. norm = 10**(-0.4 * synphot[norm_band]) / obs['maggies'][norm_band] # Pivot the calibration polynomial near the filter used for approximate # normalization pivot_wave = obs['filters'][norm_band].wave_effective # model.params['pivot_wave'] = 4750. return norm, pivot_wave
def plot_sfh(pars, specs, masses, sfrs, ages, sps=sps): # sfrs plot(ages[0], sfrs[0][i,:], '-o', label='old') plot(ages[1], sfrs[1][i,:], '-o', label='new') integrated_sfr = [np.trapz(sfrs[i], 10**ages[i], axis=1) for i in range(2)] sratio = integrated_sfr[1] / integrated_sfr[0] # masses plot(ages[0], masses[0][i,:], '-o', label='old') plot(ages[1], masses[1][i,:], '-o', label='new') m1 = interp1d(ages[0], masses[0], axis=1)(ages[1]) mratio = masses[1] / m1 zero = (m1 == 0.0) | (masses[1] == 0.0) # Mass to light ratios from sedpy import observate filters = [observate.Filter('bessell_V')] w = sps.wavelengths lv = [observate.getSED(w, s / w**2, filterlist=filters) for s in specs] log_m2l = [np.log10(mass) + lum/2.5 for mass, lum in zip(masses, lv)] log_m2l1 = interp1d(ages[0], log_m2l[0], axis=1)(ages[1]) pass
def get_spectrum(self, outwave=None, filters=None, component=-1, **params): """ """ # Spectrum in Lsun/Hz per solar mass formed, restframe wave, spectrum, mfrac = self.get_galaxy_spectrum(**params) # Redshifting + Wavelength solution # We do it ourselves. a = 1 + self.params.get('zred', 0) af = a b = 0.0 if 'wavecal_coeffs' in self.params: x = wave - wave.min() x = 2.0 * (x / x.max()) - 1.0 c = np.insert(self.params['wavecal_coeffs'], 0, 0) # assume coeeficients give shifts in km/s b = chebval(x, c) / (lightspeed*1e-13) wa, sa = wave * (a + b), spectrum * af # Observed Frame if outwave is None: outwave = wa # Observed frame photometry, as absolute maggies if filters is not None: # Magic to only do filter projections for unique filters, and get a # mapping back into this list of unique filters # note that this may scramble order of unique_filters fnames = [f.name for f in filters] unique_names, uinds, filter_ind = np.unique(fnames, return_index=True, return_inverse=True) unique_filters = np.array(filters)[uinds] mags = getSED(wa, lightspeed/wa**2 * sa * to_cgs, unique_filters) phot = np.atleast_1d(10**(-0.4 * mags)) else: phot = 0.0 # Distance dimming and unit conversion zred = self.params.get('zred', 0.0) if (zred == 0) or ('lumdist' in self.params): # Use 10pc for the luminosity distance (or a number # provided in the dist key in units of Mpc) dfactor = (self.params.get('lumdist', 1e-5) * 1e5)**2 else: lumdist = cosmo.luminosity_distance(zred).value dfactor = (lumdist * 1e5)**2 # Spectrum will be in maggies sa *= to_cgs / dfactor / (3631*jansky_cgs) # Convert from absolute maggies to apparent maggies phot /= dfactor # Mass normalization mass = np.atleast_1d(self.params['mass']) mass = np.squeeze(mass.tolist() + [mass.sum()]) sa = (sa * mass[:, None]) phot = (phot * mass[:, None])[component, filter_ind] return sa, phot, mfrac
def predict_phot(self, filters): """Generate a prediction for the observed photometry. This method assumes that the parameters have been set and that the following attributes are present and correct: + ``_wave`` - The SPS restframe wavelength array + ``_zred`` - Redshift + ``_norm_spec`` - Observed frame spectral fluxes, in units of maggies. + ``_eline_wave`` and ``_eline_lum`` - emission line parameters from the SPS model :param filters: List of :py:class:`sedpy.observate.Filter` objects. If there is no photometry, ``None`` should be supplied :returns phot: Observed frame photometry of the model SED through the given filters. ndarray of shape ``(len(filters),)``, in units of maggies. If ``filters`` is None, this returns 0.0 """ if filters is None: return 0.0 # generate photometry w/o emission lines obs_wave = self.observed_wave(self._wave, do_wavecal=False) flambda = self._norm_spec * lightspeed / obs_wave**2 * (3631 * jansky_cgs) mags = getSED(obs_wave, flambda, filters) phot = np.atleast_1d(10**(-0.4 * mags)) # generate emission-line photometry if self.params.get('nebemlineinspec', False) is False: phot += self.nebline_photometry(filters) return phot
def mags_from_sedpy(z, t, s): t0 = time.time() sps.params['logzsol'] = z sps.params['sigma_smooth'] = s sps.params['tage'] = t wave, spec = sps.get_spectrum(peraa=True, tage=sps.params['tage']) mags = observate.getSED(wave, spec, filters) return time.time() - t0
def mags_from_sedpy(z, t, s): t0 = time.time() sps.params['logzsol'] = z sps.params['sigma_smooth'] = s sps.params['tage'] = t wave, spec = sps.get_spectrum(peraa=True, tage = sps.params['tage']) mags = observate.getSED(wave, spec, filters) return time.time()-t0
def zsfh_to_obs(sfhlist, zlist, lfbandnames=None, select_function=None, bandnames=None, sps=None, isocs=None, **kwargs): """ Go from a list of SFHs (one for each metallicity) to a broadband SED and set of luminosity functions for a stellar population. """ sed_values, lf_values = {}, [] #basti = np.any(sps.zlegend[0:2] == 0.0006) #Hack to check for Basti Isochrones nsfh = len(sfhlist) assert len(zlist) == nsfh ########### # SED ############ if bandnames is not None: filterlist = observate.load_filters(bandnames) spec, wave, mass = rsed.one_region_sed(copy.deepcopy(sfhlist), total_zmet, sps) mags = observate.getSED(wave, spec*rsed.to_cgs, filterlist=filterlist) maggies = 10**(-0.4 * np.atleast_1d(mags)) sed_values['sed_ab_maggies'] = maggies sed_values['sed_filters'] = bandnames ############# # LFs ############ #create the SSP CLFs, using nearest neighbor interpolation for the metallicity all_lf_base = [] bins = rsed.lfbins for i,zmet in enumerate(zlist): if isocs is not None: isoc = isocs[i] else: sps.params['zmet'] = np.abs(sps.zlegend - zmet).argmin() + 1 isoc = sps.isochrones() print("Using Zmet={0} in place of requested " "Zmet={1}".format(sps.zlegend[sps.params['zmet']-1],zmet)) ldat = isochrone_to_clfs(copy.deepcopy(isoc), lfbandnames, select_function=select_function, **kwargs) all_lf_base += [ldat] #use the SSP CLFs to generate a total LF (for each band) for i, band in enumerate(lfbandnames): lf_oneband = {} lf_base = [zbase[i] for zbase in all_lf_base] lfs_zt, lf, logages = rsed.one_region_lfs(copy.deepcopy(sfhlist), lf_base) lf_oneband['bandname'] = band lf_oneband['clf'] = lf lf_oneband['clf_mags'] = bins lf_oneband['logages'] = logages lf_oneband['clfs_zt'] = lfs_zt lf_values += [lf_oneband] ############# # Write output ############ return sed_values, lf_values
def one_sed(self, component_index=0, filterlist=[]): """Get the SED of one component for a multicomponent composite SFH. Should set this up to work as an iterator. :param component_index: Integer index of the component to calculate the SED for. :param filterlist: A list of strings giving the (FSPS) names of the filters onto which the spectrum will be projected. :returns spec: The restframe spectrum in units of Lsun/Hz. :returns maggies: Broadband fluxes through the filters named in ``filterlist``, ndarray. Units are observed frame absolute maggies: M = -2.5 * log_{10}(maggies). :returns extra: The extra information corresponding to this component. """ # Pass the model parameters through to the sps object, and keep track # of the mass of this component mass = 1.0 for k, vs in list(self.params.items()): try: v = vs[component_index] except (IndexError, TypeError): v = vs if k in self.csp.params.all_params: self.csp.params[k] = deepcopy(v) if k == 'mass': mass = v # Now get the spectrum. The spectrum is in units of # Lsun/Hz/per solar mass *formed*, and is restframe w, spec = self.csp.get_spectrum(tage=self.csp.params['tage'], peraa=False) # redshift and get photometry. Note we are boosting fnu by (1+z) *here* a, b = (1 + self.csp.params['zred']), 0.0 wa, sa = w * (a + b), spec * a # Observed Frame if filterlist is not None: mags = getSED(wa, lightspeed / wa**2 * sa * to_cgs, filterlist) phot = np.atleast_1d(10**(-0.4 * mags)) else: phot = 0.0 # now some mass normalization magic mfrac = self.csp.stellar_mass if np.all(self.params.get('mass_units', 'mstar') == 'mstar'): # Convert normalization units from per stellar masss to per mass formed mass /= mfrac # Output correct units return mass * sa, mass * phot, mfrac
def project_filter(wave, spectrum, bands=["sdss_r0"]): """ :param wave: Wavelengths in angstroms ndarray of shape (nw,) :param spectrum: Spectrum, in units of f_lambda (magnitudes will be correct if they are units of erg/s/cm^2). same shape as `wave` """ filters = load_filters(bands) mags = getSED(wave, spectrum, filterlist=filters) return mags
def process_component(self, i, outwave, filters): """Basically do all the COMPSP stuff for one component. """ cspec = self.basis_spec[i, :].copy() cphot = 0 inwave = self.ssp.wavelengths if self.safe: cspec = np.interp(self.params['outwave'], vac2air(inwave), cspec / a) cphot = 10**(-0.4 * getSED(inwave, cspec / a, filters)) return cspec, cphot # Dust attenuation tage = self.params['tage'][i] tesc = self.params.get('dust_tesc', 0.01) dust1 = self.params.get('dust1', 0.0) dust2 = self.params['dust2'] a = (1 + self.params.get('zred', 0.0)) dust = (tage < tesc) * dust1 + dust2 att = self.params['dust_curve'][0](inwave, **self.params) cspec *= np.exp(-att * dust) if filters is not None: cphot = 10**(-0.4 * getSED(inwave * a, cspec / a, filters)) # Wavelength scale. Broadening and redshifting and placing on output # wavelength grid if self.params.get('lsf', [None])[0] is not None: cspec = smoothspec( vac2air(inwave) * a, cspec / a, self.params['sigma_smooth'], **self.params) else: sigma = self.params.get('sigma_smooth', 0.0) cspec = self.ssp.smoothspec(inwave, cspec, sigma) cspec = np.interp(self.params['outwave'], vac2air(inwave * a), cspec / a) return cspec, cphot
def one_sed(self, icomp=0, wave=None, filters=None, **extras): """Pull out individual component parameters from the param dictionary and generate spectra for those components """ cpars = {} for k in self.dust_parlist: try: cpars[k] = np.squeeze(self.params[k][icomp]) except(IndexError, TypeError): cpars[k] = np.squeeze(self.params[k]) spec = cpars['mass'] * modified_BB(wave, **cpars) phot = 10**(-0.4 * getSED(wave*1e4, spec, filters)) return spec, phot, None
def one_sed(self, icomp=0, wave=None, filters=None, **extras): """Pull out individual component parameters from the param dictionary and generate spectra for those components """ cpars = {} for k in self.dust_parlist: try: cpars[k] = np.squeeze(self.params[k][icomp]) except (IndexError, TypeError): cpars[k] = np.squeeze(self.params[k]) spec = cpars['mass'] * modified_BB(wave, **cpars) phot = 10**(-0.4 * getSED(wave * 1e4, spec, filters)) return spec, phot, None
def one_sed(self, component_index=0, filterlist=[]): """Get the SED of one component for a multicomponent composite SFH. Should set this up to work as an iterator. :param component_index: Integer index of the component to calculate the SED for. :param filterlist: A list of strings giving the (FSPS) names of the filters onto which the spectrum will be projected. :returns spec: The restframe spectrum in units of Lsun/Hz. :returns maggies: Broadband fluxes through the filters named in ``filterlist``, ndarray. Units are observed frame absolute maggies: M = -2.5 * log_{10}(maggies). :returns extra: The extra information corresponding to this component. """ # Pass the model parameters through to the sps object, and keep track # of the mass of this component mass = 1.0 for k, vs in list(self.params.items()): try: v = vs[component_index] except (IndexError, TypeError): v = vs if k in self.csp.params.all_params: if k == 'zmet': vv = np.abs(v - (np.arange(len(self.csp.zlegend)) + 1)).argmin() + 1 else: vv = v.copy() self.csp.params[k] = vv if k == 'mass': mass = v # Now get the magnitudes and spectrum. The spectrum is in units of # Lsun/Hz/per solar mass *formed* w, spec = self.csp.get_spectrum(tage=self.csp.params['tage'], peraa=False) mags = getSED(w, lightspeed / w**2 * spec * to_cgs, filterlist) mfrac = self.csp.stellar_mass if np.all(self.params.get('mass_units', 'mstar') == 'mstar'): # Convert normalization units from per stellar masss to per mass formed mass /= mfrac # Output correct units return mass * spec, mass * 10**(-0.4 * (mags)), mfrac
def process_component(self, i, outwave, filters): """Basically do all the COMPSP stuff for one component. """ cspec = self.basis_spec[i, :].copy() cphot = 0 inwave = self.ssp.wavelengths if self.safe: cspec = np.interp(self.params['outwave'], vac2air(inwave), cspec/a) cphot = 10**(-0.4 * getSED(inwave, cspec/a, filters)) return cspec, cphot # Dust attenuation tage = self.params['tage'][i] tesc = self.params.get('dust_tesc', 0.01) dust1 = self.params.get('dust1', 0.0) dust2 = self.params['dust2'] a = (1 + self.params.get('zred', 0.0)) dust = (tage < tesc) * dust1 + dust2 att = self.params['dust_curve'][0](inwave, **self.params) cspec *= np.exp(-att*dust) if filters is not None: cphot = 10**(-0.4 * getSED(inwave*a, cspec / a, filters)) # Wavelength scale. Broadening and redshifting and placing on output # wavelength grid if self.params.get('lsf', [None])[0] is not None: cspec = smoothspec(vac2air(inwave) * a, cspec / a, self.params['sigma_smooth'], **self.params) else: sigma = self.params.get('sigma_smooth', 0.0) cspec = self.ssp.smoothspec(inwave, cspec, sigma) cspec = np.interp(self.params['outwave'], vac2air(inwave * a), cspec/a) return cspec, cphot
def one_sed(self, component_index=0, filterlist=[]): """Get the SED of one component for a multicomponent composite SFH. Should set this up to work as an iterator. :param component_index: Integer index of the component to calculate the SED for. :param filterlist: A list of strings giving the (FSPS) names of the filters onto which the spectrum will be projected. :returns spec: The restframe spectrum in units of Lsun/Hz. :returns maggies: Broadband fluxes through the filters named in ``filterlist``, ndarray. Units are observed frame absolute maggies: M = -2.5 * log_{10}(maggies). :returns extra: The extra information corresponding to this component. """ # Pass the model parameters through to the sps object, and keep track # of the mass of this component mass = 1.0 for k, vs in list(self.params.items()): try: v = vs[component_index] except(IndexError, TypeError): v = vs if k in self.csp.params.all_params: if k == 'zmet': vv = np.abs(v - (np.arange(len(self.csp.zlegend)) + 1)).argmin() + 1 else: vv = v.copy() self.csp.params[k] = vv if k == 'mass': mass = v # Now get the magnitudes and spectrum. The spectrum is in units of # Lsun/Hz/per solar mass *formed* w, spec = self.csp.get_spectrum(tage=self.csp.params['tage'], peraa=False) mags = getSED(w, lightspeed/w**2 * spec * to_cgs, filterlist) mfrac = self.csp.stellar_mass if np.all(self.params.get('mass_units', 'mstar') == 'mstar'): # Convert normalization units from per stellar masss to per mass formed mass /= mfrac # Output correct units return mass * spec, mass * 10**(-0.4*(mags)), mfrac
def rectify_basis(wave, spectra, wlow=0, whigh=np.inf, exclude=[], outwave=None, filters=None, **extras): """Mask a spectral basis using lists of include and exclude ranges """ if filters is not None: flist = observate.load_filters(filters) sed = observate.getSED(wave, spectra, filterlist=flist) return np.array([f.wave_effective for f in flist]), 10**(-0.4 * sed) if outwave is not None: onedinterp = interpolate(wave, spectra, axis=-1) spectra = onedinterp(outwave) wave = outwave g = (wave >= wlow) & (wave <= whigh) for (lo, hi) in exclude: g = g & ((wave < lo) | (wave > hi)) return wave[g], spectra[:, g]
def observe(fnames): # units: lambda (A), flux: fnu normalized to unity dat = load_data() filters = load_filters(fnames) out = {} for name in dat.dtype.names: if name == 'blank' or name == 'lambda': continue # sourcewave: Spectrum wavelength (in AA), ndarray of shape (nwave). # sourceflux: Associated flux (assumed to be in erg/s/cm^2/AA), ndarray of shape (nsource,nwave). # filterlist: List of filter objects, of length nfilt. # array of AB broadband magnitudes, of shape (nsource, nfilter). out[name] = getSED(dat['lambda'], (lightspeed/dat['lambda']**2)*dat[name], filters) return out
def generateSEDs(self, pars, filterlist, wave_min=90, wave_max=1e7, keepspec=False, intspec=False, attenuator=None, **extras): """ :returns sed: ndarray of shape (nobj,nfilter) :returns lbol: ndarray of shape (nobj) :returns outspectra: ndarray of shape (nobj,nwave) """ # Don't use too much memory at once maxmod = 1e7 / self.wavelength.shape[0] ngrid = pars.shape[0] sed = np.zeros([int(ngrid),len(filterlist)]) lbol = np.zeros(int(ngrid)) outspectra = None if keepspec: outspectra = np.zeros([ngrid,self.wavelength.shape[0]]) elif intspec: outspectra = np.zeros(self.wavelength.shape[0]) # split big model grids to avoid memory constraints i = 0 while (i*maxmod <= ngrid): s1, s2 = int((i)*maxmod), int(np.min([(i+1) * maxmod-1, ngrid])) spec = self.spectra_from_pars(pars[int(s1):int(s2)], **extras) if attenuator is not None: spec = attenuator.attenuate_spectrum(self.wavelength, spec, pars[s1:s2], **extras) sed[s1:s2,:] = observate.getSED(self.wavelength, spec, filterlist) lbol[s1:s2] = observate.Lbol(self.wavelength, spec, wave_min=wave_min, wave_max=wave_max) i += 1 if keepspec: outspectra[s1:s2,:] = spec elif intspec: outspectra += spec.sum(axis=0) return sed, lbol, outspectra
def get_mags(wave,spectrum,z,lumdist,formed_mass,filterlist): # filter parameters filters = load_filters(filterlist) # redshift offset the spectrum a = 1+z wa, sa = wave*a, spectrum*a # get the absolute magnitudes mags = getSED(wa, lightspeed/wa**2 * sa * to_cgs, filters) phot = np.atleast_1d(10**(-0.4 * mags)) # get the observed magnitudes dfactor = (lumdist*1e5)**2 phot /= dfactor phot *= formed_mass phot = mgy_to_mag(phot) return phot
def all_region_sed(regions, sps, filters=['galex_NUV'], lf_bases=None): """ Given a cloud name (lmc | smc) and a filter, determine the broadband flux of each region in that cloud based on the SFHs of Harris & Zaritsky 2004 or 2009. The sfhs are given separately for each metallicity; we treat each metallicity independently and sum the resulting spectra before determining the broadband flux. """ from sedpy import observate header = regions.pop('header', None) #dump the header sps.params['sfh'] = 0 #ssp sps.params['imf_type'] = 0 #salpeter filterlist = observate.load_filters(filters) #set up output try: nb = len(lfbins) except: nb = 1 regname, alllocs = [], [] allmags = np.zeros([len(regions), len(filterlist)]) all_lfs = np.zeros([len(regions), nb]) #loop over regions for j, (k, data) in enumerate(regions.iteritems()): spec, lf, wave = one_region_sed(data['sfhs'], data['zmet'], sps, lf_bases=lf_bases) #project filters mags = observate.getSED(wave, spec * bsp.to_cgs, filterlist=filterlist) mags = np.atleast_1d(mags) allmags[j, :] = mags all_lfs[j, :] = lf regname.append(k) alllocs += [data['loc'].strip()] return alllocs, regname, allmags, all_lfs
def test(): from sedpy import observate import fsps import matplotlib.pyplot as pl filters = ['galex_NUV', 'sdss_u0', 'sdss_r0', 'sdss_r0', 'sdss_i0', 'sdss_z0', 'bessell_U', 'bessell_B', 'bessell_V', 'bessell_R', 'bessell_I', 'twomass_J','twomass_H'] flist = observate.load_filters(filters) sps = fsps.StellarPopulation(compute_vega_mags=False) wave, spec = sps.get_spectrum(tage=1.0, zmet=2, peraa=True) sed = observate.getSED(wave, spec, flist) sed_unc = np.abs(np.random.normal(1, 0.3, len(sed))) wgrid = np.linspace( 2e3, 13e3, 1000) fgrid = np.linspace( -13, -9, 100) psed, sedpoints = sed_to_psed(flist, sed, sed_unc, wgrid, fgrid) pl.imshow(np.exp(psed).T, cmap='Greys_r', interpolation='nearest', origin ='upper', aspect='auto')
def get_colors_emission_line(self, zGrid, age, ebv, HaEw, colorList=None, logzsol=0, **kwargs): FilterList = observate.load_filters(self.filter_names) color_idxs = self._define_colors(colorList) ncolors = len(color_idxs) nzGrid = len(zGrid) color_grid = np.zeros([ncolors, nzGrid]) for i, z in enumerate(zGrid): WaveModel, SpecModel = self.added_emission_line_spectra( age, ebv, HaEw, redshift=z, logzsol=logzsol, **kwargs) mags = observate.getSED(WaveModel * (1 + z), SpecModel, filterlist=FilterList) colors = [mags[c[0]] - mags[c[1]] for c in color_idxs] color_grid[:, i] = colors return color_grid
def _getPhotometry_iSEDfit(self, iseddict): ''' Returns AB magnitude photometry ''' assert set(iseddict.keys()).issuperset( set(['tau', 'av', 'mu', 'age', 'mstar', 'zmetal'])) self.pop.params['sfh'] = 1 self.pop.params['tau'] = iseddict['tau'] self.pop.params['dust_type'] = 2 self.pop.params['dust2'] = 0.92 * iseddict['av'] * iseddict[ 'mu'] # ln(10) * 0.4 * A(V) self.pop.params['logzsol'] = np.log10(iseddict['zmetal'] / 0.019) self.pop.params['add_neb_emission'] = True self.pop.params['add_neb_continuum'] = True w, sp = self.pop.get_spectrum(tage=iseddict['age'], peraa=False) a = 1. + iseddict['z'] # scale factor wave = w * a mass = 10**iseddict[ 'mstar'] / self.pop.stellar_mass # stellar mass scaling d_lum = self.cosmo.luminosity_distance(iseddict['z']).value d_factor = (d_lum * 1e5)**2 spec = mass * sp * a * self.to_cgs / d_factor * self.lightspeed / wave**2 # in erg/s/cm^2/AA return getSED(wave, spec, filterlist=load_filters([ 'sdss_u0', 'sdss_g0', 'sdss_r0', 'sdss_i0', 'sdss_z0' ]))
def get_spectrum(self, outwave=None, filters=None, peraa=False, **kwargs): """Return an attenuated, smoothed, distance dimmed stellar spectrum and SED. :returns spec: The spectrum on the outwave grid (assumed in air), in AB maggies. If peraa is True then the spectrum is erg/s/cm^2/AA. :returns phot: Observed frame photometry in units of AB maggies. If ``lumdist`` is not present in the parameters then these are absolute maggies, otherwise they are apparent. :returns x: A blob of extra quantities (e.g. mass, uncertainty) """ self.update(**kwargs) # star spectrum (in Lsun/Hz) wave, spec, unc = self.get_star_spectrum(**self.params) spec *= self.normalize() # dust if 'dust_curve' in self.params: att = self.params['dust_curve'](self._wave, **self.params) spec *= np.exp(-att) # Redshifting + Wavelength solution. We also convert to in-air. a = 1 + self.params.get('zred', 0) b = 0.0 if 'wavecal_coeffs' in self.params: x = wave - wave.min() x = 2.0 * (x / x.max()) - 1.0 c = np.insert(self.params['wavecal_coeffs'], 0, 0) # assume coeeficients give shifts in km/s b = chebval(x, c) / (lightspeed*1e-13) wa, sa = vac2air(wave) * (a + b), spec * a if outwave is None: outwave = wa # Broadening, interpolation onto output wavelength grid if 'sigma_smooth' in self.params: smspec = self.smoothspec(wa, sa, self.params['sigma_smooth'], outwave=outwave, **self.params) elif outwave is not wa: smspec = np.interp(outwave, wa, sa, left=0, right=0) else: smspec = sa # Photometry (observed frame absolute maggies) if filters is not None: mags = getSED(wa, sa * lightspeed / wa**2 * to_cgs, filters) phot = np.atleast_1d(10**(-0.4 * mags)) else: phot = 0.0 # Distance dimming. Default to 10pc distance (i.e. absolute) dfactor = (self.params.get('lumdist', 1e-5) * 1e5)**2 if peraa: # spectrum will be in erg/s/cm^2/AA smspec *= to_cgs / dfactor * lightspeed / outwave**2 else: # Spectrum will be in maggies smspec *= to_cgs / dfactor / 1e3 / (3631*jansky_mks) # Convert from absolute maggies to apparent maggies phot /= dfactor return smspec, phot, None
def main(cloud, agb_dust, lf_band, basti=False): #Run parameters filters = [ 'galex_NUV', 'spitzer_irac_ch1', 'spitzer_irac_ch4', 'spitzer_mips_24' ] min_tpagb_age = 0.0 ldir, outdir = 'lf_data/', 'results_predicted/' ######### # Initialize the ingredients (SPS, SFHs, LFs) ######### # SPS sps = fsps.StellarPopulation(add_agb_dust_model=True) sps.params['sfh'] = 0 sps.params['agb_dust'] = agb_dust dust = ['nodust', 'agbdust'] sps.params['imf_type'] = 0.0 #salpeter filterlist = observate.load_filters(filters) # SFHs if cloud.lower() == 'lmc': regions = utils.lmc_regions() nx, ny, dm = 48, 38, 18.5 zlist = [7, 11, 13, 16] if basti: zlist = [3, 4, 5, 6] elif cloud.lower() == 'smc': regions = utils.smc_regions() nx, ny, dm = 20, 23, 18.9 zlist = [7, 13, 16] if basti: zlist = [3, 5, 6] else: print('do not understand your MC designation') fstring = '{0}z{1:02.0f}_tau{2:02.0f}_irac{3}_n2_test_lf.txt' if basti: fstring = '{0}z{1:02.0f}_tau{2:02.0f}_basti_vega_n2_irac{3}_SSP.txt' lffiles = [fstring.format(ldir, z, agb_dust * 10, lf_band) for z in zlist] rheader = regions.pop('header') #dump the header info from the reg. dict # LFs lf_bases = [read_lfs(f) for f in lffiles] #zero out select ages for j, base in enumerate(lf_bases): blank = base['ssp_ages'] <= min_tpagb_age base['lf'][blank, :] = 0 plot_lf(base, wlengths[lf_band], lffiles[j]) #except(NameError): # lf_bases = None print(lffiles) ############# # Loop over each region, do SFH integrations, filter convolutions # and populate output images and LF cubes ############ im = np.zeros([len(filters), nx, ny]) #flux in each band in each region bins = rsed.lbins agb = np.zeros([len(bins), nx, ny]) #cumulative LF in each region for n, dat in regions.iteritems(): spec, lf, wave = rsed.one_region_sed(dat['sfhs'], dat['zmet'], sps, lf_bases=lf_bases) mags = observate.getSED(wave, spec * rsed.to_cgs, filterlist=filterlist) maggies = 10**(-0.4 * np.atleast_1d(mags)) x, y = utils.regname_to_xy(n, cloud=cloud) agb[:, x, y] = lf[:, None] / np.size(x) im[:, x, y] = maggies[:, None] / np.size(x) ############# # Write output ############ for i, f in enumerate(filters): write_image(im[i, :, :].T, cloud, f, outdir=outdir, agb_dust=agb_dust) #write out AGB N(>M) images as fits #for lim in np.arange(-6.7, -9.5, -0.5): # ind = np.searchsorted(bins, lim) -1 # pyfits.writeto('test.fits', agb[ind,:,:].T, clobber = True) #write out AGB N(>M) images as a pickle file agb_cube = {} agb_cube['agb_clf_cube'] = agb agb_cube['mag_bins'] = bins out = open( "{0}clf.{1}.tau{2:02.0f}.irac{3}.p".format(outdir, cloud.lower(), agb_dust * 10, lf_band), "wb") pickle.dump(agb_cube, out) out.close() # Plot the total LF wave = wlengths[lf_band] fig, ax = pl.subplots(1, 1) lf_tot = agb.sum(-1).sum(-1) ax.plot(bins + dm, lf_tot) ax.set_ylabel(r'$N(<M)$ (total for cloud)') ax.set_xlabel(r'$m_{}$ (Vega apparent)'.format(wave)) ax.set_title(cloud.upper()) ax.set_yscale('log') fig.savefig('{0}total_agb_clf.{1}.tau{2:02.0f}.irac{3}.png'.format( outdir, cloud.lower(), agb_dust * 10, lf_band)) pl.close(fig)
'tau': tau * 1e9, 'sf_slope': -sf_slope / 1e9, 'sf_trunc': sf_trunc * 1e9 } mw, mys, mstar = mysps.get_galaxy_spectrum(**sfh_params) myspec[i, :] = mys # Do some plotting for each age wax.plot(sspages, mysps.all_ssp_weights, '-o', label=r'{}={:4.2f}'.format(pname, tage)) rax.plot(mw, mys / s, label=r'{}={:4.2f}'.format(pname, tage)) dax.plot(mw, s - mys, label=r'{}={:4.2f}'.format(pname, tage)) # Get synthetic photometry for both sps objects mags = observate.getSED(sps.wavelengths, spec, filterlist=filters) mymags = observate.getSED(sps.wavelengths, myspec, filterlist=filters) # Plot mags vs age iband = 0 fig, ax = pl.subplots() ax.plot(ages, mags[:, iband], '-o', label='FSPS, tres={}'.format(int(tres))) ax.plot(ages, mymags[:, iband], '-o', label='Pro') ax.set_xlabel('tage (Gyr)') ax.set_ylabel(r'$M_{{AB}}$ ({})'.format(filters[iband].name)) ax.text(0.1, 0.85, r'$\tau_{{SF}}={:4.2f}, \, \Delta t_{{trunc}}={:4.2f}$'.format( tau, delt_trunc), transform=ax.transAxes) ax.legend(loc=0)
def main(cloud, agb_dust, lf_band, basti=False): #Run parameters filters = ['galex_NUV', 'spitzer_irac_ch1', 'spitzer_irac_ch4', 'spitzer_mips_24'] min_tpagb_age = 0.0 ldir, outdir = 'lf_data/', 'results_predicted/' ######### # Initialize the ingredients (SPS, SFHs, LFs) ######### # SPS sps = fsps.StellarPopulation(add_agb_dust_model = True) sps.params['sfh'] = 0 sps.params['agb_dust'] = agb_dust dust = ['nodust', 'agbdust'] sps.params['imf_type'] = 0.0 #salpeter filterlist = observate.load_filters(filters) # SFHs if cloud.lower() == 'lmc': regions = utils.lmc_regions() nx, ny, dm = 48, 38, 18.5 zlist = [7, 11, 13, 16] if basti: zlist = [3,4,5,6] elif cloud.lower() == 'smc': regions = utils.smc_regions() nx, ny, dm = 20, 23, 18.9 zlist = [7, 13, 16] if basti: zlist = [3,5,6] else: print('do not understand your MC designation') fstring = '{0}z{1:02.0f}_tau{2:02.0f}_irac{3}_n2_test_lf.txt' if basti: fstring = '{0}z{1:02.0f}_tau{2:02.0f}_basti_vega_n2_irac{3}_SSP.txt' lffiles = [fstring.format(ldir, z, agb_dust*10, lf_band) for z in zlist] rheader = regions.pop('header') #dump the header info from the reg. dict # LFs lf_bases = [read_lfs(f) for f in lffiles] #zero out select ages for j, base in enumerate(lf_bases): blank = base['ssp_ages'] <= min_tpagb_age base['lf'][blank,:] = 0 plot_lf(base, wlengths[lf_band], lffiles[j]) #except(NameError): # lf_bases = None print(lffiles) ############# # Loop over each region, do SFH integrations, filter convolutions # and populate output images and LF cubes ############ im = np.zeros([ len(filters), nx, ny]) #flux in each band in each region bins = rsed.lbins agb = np.zeros([ len(bins), nx, ny]) #cumulative LF in each region for n, dat in regions.iteritems(): spec, lf, wave = rsed.one_region_sed(dat['sfhs'], dat['zmet'], sps, lf_bases=lf_bases) mags = observate.getSED(wave, spec * rsed.to_cgs, filterlist = filterlist) maggies = 10**(-0.4 * np.atleast_1d(mags)) x, y = utils.regname_to_xy(n, cloud=cloud) agb[:, x, y] = lf[:, None] / np.size(x) im[:, x, y] = maggies[:, None]/ np.size(x) ############# # Write output ############ for i, f in enumerate(filters): write_image(im[i,:,:].T, cloud, f, outdir=outdir, agb_dust=agb_dust) #write out AGB N(>M) images as fits #for lim in np.arange(-6.7, -9.5, -0.5): # ind = np.searchsorted(bins, lim) -1 # pyfits.writeto('test.fits', agb[ind,:,:].T, clobber = True) #write out AGB N(>M) images as a pickle file agb_cube = {} agb_cube['agb_clf_cube'] = agb agb_cube['mag_bins'] = bins out = open("{0}clf.{1}.tau{2:02.0f}.irac{3}.p".format(outdir, cloud.lower(), agb_dust*10, lf_band), "wb") pickle.dump(agb_cube, out) out.close() # Plot the total LF wave = wlengths[lf_band] fig, ax = pl.subplots(1,1) lf_tot = agb.sum(-1).sum(-1) ax.plot(bins + dm, lf_tot) ax.set_ylabel(r'$N(<M)$ (total for cloud)') ax.set_xlabel(r'$m_{}$ (Vega apparent)'.format(wave)) ax.set_title(cloud.upper()) ax.set_yscale('log') fig.savefig('{0}total_agb_clf.{1}.tau{2:02.0f}.irac{3}.png'.format(outdir, cloud.lower(), agb_dust*10, lf_band)) pl.close(fig)
ax.plot(psi.wavelengths, predicted[bad,:], label='predicted') ax.plot(psi.wavelengths, psi.training_spectra[bad,:], label='actual') ax.text(0.05, 0.9, "#{}, RMS={:4.1f}%".format(psi.training_labels[bad]['miles_id'], rms[bad]), transform=ax.transAxes, fontsize=10) ax.text(0.7, 0.05, title, transform=ax.transAxes, fontsize=10) if i == 0: ax.legend(loc=0, prop={'size':8}) if i < 9: ax.set_xticklabels([]) badfig.savefig('figures/worst10_{}.pdf'.format(ts)) # B-V colors from sedpy import observate filt = observate.load_filters(['hipparcos_V', 'hipparcos_B']) #filt = observate.load_filters(['bessell_V', 'bessell_B']) pmags_actual = observate.getSED(psi.wavelengths, psi.training_spectra, filterlist=filt) pmags_predicted = observate.getSED(psi.wavelengths, predicted, filterlist=filt) # Compare colors to observations mid, b, v = np.genfromtxt('../../data/tycho2_b_v.dat', unpack=True) bv = b - v mid = mid.astype(int) inds = np.zeros(len(mid)) - 1 mlist = psi.training_labels['miles_id'].tolist() for i, m in enumerate(mid): if m in mlist: inds[i] = mlist.index(m) inds = inds.astype(int) good = inds >= 0 fig, axes = pl.subplots(2, 1) ax= axes[0]
] # Calculate SKIRT attenuation curve (requires dust and nodust spectra) dustSpec_SKIRT = np.load( '/scratch/ntf229/RT_fit/resources/SKIRT/' + galaxies[i] + '/maxLevel13/wavelengths250/numPhotons3e8/inc0/dust/spec.npy' ) / 3631 # convert from Jy to maggies dustSpec_SKIRT = 22.5 - 2.5 * np.log10( dustSpec_SKIRT * 1e9) # convert to Pogson magnitudes # Calculate r-band luminosity for each SKIRT spectrum f_lambda_cgs = (1 / 33333) * (1 / (wave_SKIRT**2)) * (dustSpec_SKIRT * 3631) filterlist = observate.load_filters( ["sdss_z0", "wise_w3", "herschel_pacs_100"]) # ~ 1, 10, 100 microns mags = observate.getSED(angstroms, f_lambda_cgs, filterlist=filters) # AB magnitudes # DustPedia Sample file = np.loadtxt('DustPedia_Aperture_Photometry_2.2.csv', dtype=str) # file[0] are column names # columns are separated by commas # empty columns are still separated by a comma # All the photometric measurements are in Jy full_sdss_z0 = [] full_wise_w3 = [] full_pacs_100 = [] count = 0
sps.params['sf_slope'] = sf_slope sps.params['sf_trunc'] = sf_trunc w, s = sps.get_spectrum(tage=tage, peraa=True) spec[i, :] = s # Set up Pro parameters, with unit conversions, get spectrum, and store it. sfh_params = {'tage': tage*1e9, 'tau': tau*1e9, 'sf_slope': -sf_slope / 1e9, 'sf_trunc': sf_trunc*1e9} mw, mys, mstar = mysps.get_galaxy_spectrum(**sfh_params) myspec[i, :] = mys # Do some plotting for each age wax.plot(sspages, mysps.all_ssp_weights, '-o', label=r'{}={:4.2f}'.format(pname, tage)) rax.plot(mw, mys / s, label=r'{}={:4.2f}'.format(pname, tage)) dax.plot(mw, s - mys, label=r'{}={:4.2f}'.format(pname, tage)) # Get synthetic photometry for both sps objects mags = observate.getSED(sps.wavelengths, spec, filterlist=filters) mymags = observate.getSED(sps.wavelengths, myspec, filterlist=filters) # Plot mags vs age iband = 0 fig, ax = pl.subplots() ax.plot(ages, mags[:, iband], '-o', label='FSPS, tres={}'.format(int(tres))) ax.plot(ages, mymags[:, iband], '-o', label='Pro') ax.set_xlabel('tage (Gyr)') ax.set_ylabel(r'$M_{{AB}}$ ({})'.format(filters[iband].name)) ax.text(0.1, 0.85, r'$\tau_{{SF}}={:4.2f}, \, \Delta t_{{trunc}}={:4.2f}$'.format(tau, delt_trunc), transform=ax.transAxes) ax.legend(loc=0) fig.savefig('figures/sft_compare.pdf') # Prettify axes rax.set_xlim(1e3, 2e4)
def get_spectrum(self, outwave=None, filters=None, component=-1, **params): """Get a spectrum and SED for the given params, choosing from different possible components. :param outwave: (default: None) Desired *vacuum* wavelengths. Defaults to the values in `sps.wavelength`. :param peraa: (default: False) If `True`, return the spectrum in erg/s/cm^2/AA instead of AB maggies. :param filters: (default: None) A list of filter objects for which you'd like photometry to be calculated. :param component: (optional, default: -1) An optional array where each element gives the index of the component from which to choose the magnitude. scalar or iterable of same length as `filters` :param **params: Optional keywords giving parameter values that will be used to generate the predicted spectrum. :returns spec: Observed frame component spectra in AB maggies, unless `peraa=True` in which case the units are erg/s/cm^2/AA. (ncomp+1, nwave) :returns phot: Observed frame photometry in AB maggies, ndarray of shape (ncomp+1, nfilters) :returns mass_frac: The ratio of the surviving stellar mass to the total mass formed. """ # Spectrum in Lsun/Hz per solar mass formed, restframe wave, spectrum, mfrac = self.get_galaxy_spectrum(**params) # Redshifting + Wavelength solution # We do it ourselves. a = 1 + self.params.get('zred', 0) af = a b = 0.0 if 'wavecal_coeffs' in self.params: x = wave - wave.min() x = 2.0 * (x / x.max()) - 1.0 c = np.insert(self.params['wavecal_coeffs'], 0, 0) # assume coeeficients give shifts in km/s b = chebval(x, c) / (lightspeed * 1e-13) wa, sa = wave * (a + b), spectrum * af # Observed Frame if outwave is None: outwave = wa # Observed frame photometry, as absolute maggies if filters is not None: # Magic to only do filter projections for unique filters, and get a # mapping back into this list of unique filters # note that this may scramble order of unique_filters fnames = [f.name for f in filters] unique_names, uinds, filter_ind = np.unique(fnames, return_index=True, return_inverse=True) unique_filters = np.array(filters)[uinds] mags = getSED(wa, lightspeed / wa**2 * sa * to_cgs, unique_filters) phot = np.atleast_1d(10**(-0.4 * mags)) else: phot = 0.0 filter_ind = 0 # Distance dimming and unit conversion zred = self.params.get('zred', 0.0) if (zred == 0) or ('lumdist' in self.params): # Use 10pc for the luminosity distance (or a number # provided in the dist key in units of Mpc) dfactor = (self.params.get('lumdist', 1e-5) * 1e5)**2 else: lumdist = cosmo.luminosity_distance(zred).value dfactor = (lumdist * 1e5)**2 # Spectrum will be in maggies sa *= to_cgs / dfactor / (3631 * jansky_cgs) # Convert from absolute maggies to apparent maggies phot /= dfactor # Mass normalization mass = np.atleast_1d(self.params['mass']) mass = np.squeeze(mass.tolist() + [mass.sum()]) sa = (sa * mass[:, None]) phot = (phot * mass[:, None])[component, filter_ind] return sa, phot, mfrac
def total_galaxy_data(sfhfilename, zindex, filternames = None, basti=False, lfstring=None, agb_dust=1.0): total_sfhs = [load_angst_sfh(sfhfilename)] rsed.lfbins += total_sfhs[0]['dmod'][0] zlist = [zindex] ######### # Initialize the ingredients (SPS, SFHs, LFs) ######### # SPS if filternames is not None: sps = fsps.StellarPopulation(add_agb_dust_model = True) sps.params['sfh'] = 0 sps.params['agb_dust'] = agb_dust dust = ['nodust', 'agbdust'] sps.params['imf_type'] = 0.0 #salpeter filterlist = observate.load_filters(filternames) zmets = [sps.zlegend[zindex-1]] else: filterlist = None ############# # Sum the region SFHs into a total integrated SFH, and do the # temporal interpolations to generate integrated spectra, LFs, and # SEDs ############ # Get LFs broken out by age and metallicity as well as the total # LFs. these are stored as a list of different metallicities bins = rsed.lfbins if lfstring is not None: lffiles = [lfstring.format(z) for z in zlist] lf_base = [read_villaume_lfs(f) for f in lffiles] lfs_zt, lf, logages = rsed.one_region_lfs(copy.deepcopy(total_sfhs), lf_base) else: lfs_zt, lf, logages = None, None, None # Get spectrum and magnitudes if filterlist is not None: spec, wave, mass = rsed.one_region_sed(copy.deepcopy(total_sfhs), zmets, sps ) mags = observate.getSED(wave, spec*rsed.to_cgs, filterlist=filterlist) maggies = 10**(-0.4 * np.atleast_1d(mags)) else: maggies, mass = None, None ############# # Write output ############ total_values = {} total_values['agb_clf'] = lf total_values['agb_clfs_zt'] = lfs_zt total_values['clf_mags'] = bins.copy() total_values['logages'] = logages total_values['sed_ab_maggies'] = maggies total_values['sed_filters'] = filternames total_values['lffile'] = lfstring total_values['mstar'] = mass total_values['zlist'] = zlist rsed.lfbins -= total_sfhs[0]['dmod'][0] return total_values, total_sfhs
def get_spectrum(self, outwave=None, filters=None, peraa=False, **params): """Get a spectrum and SED for the given params. ripped from SSPBasis addition: check for flag nebeminspec. if not true, add emission lines directly to photometry """ # Spectrum in Lsun/Hz per solar mass formed, restframe wave, spectrum, mfrac = self.get_galaxy_spectrum(**params) # Redshifting + Wavelength solution # We do it ourselves. a = 1 + self.params.get('zred', 0) af = a b = 0.0 if 'wavecal_coeffs' in self.params: x = wave - wave.min() x = 2.0 * (x / x.max()) - 1.0 c = np.insert(self.params['wavecal_coeffs'], 0, 0) # assume coeeficients give shifts in km/s b = chebval(x, c) / (lightspeed*1e-13) wa, sa = wave * (a + b), spectrum * af # Observed Frame if outwave is None: outwave = wa spec_aa = lightspeed/wa**2 * sa # convert to perAA # Observed frame photometry, as absolute maggies if filters is not None: mags = observate.getSED(wa, spec_aa * to_cgs, filters) phot = np.atleast_1d(10**(-0.4 * mags)) else: phot = 0.0 ### if we don't have emission lines, add them if (not self.params['nebemlineinspec']) and self.params['add_neb_emission']: phot += self.nebline_photometry(filters,a-1)*to_cgs # Spectral smoothing. do_smooth = (('sigma_smooth' in self.params) and ('sigma_smooth' in self.reserved_params)) if do_smooth: # We do it ourselves. smspec = self.smoothspec(wa, sa, self.params['sigma_smooth'], outwave=outwave, **self.params) elif outwave is not wa: # Just interpolate smspec = np.interp(outwave, wa, sa, left=0, right=0) else: # no interpolation necessary smspec = sa # Distance dimming and unit conversion zred = self.params.get('zred', 0.0) if (zred == 0) or ('lumdist' in self.params): # Use 10pc for the luminosity distance (or a number # provided in the dist key in units of Mpc) dfactor = (self.params.get('lumdist', 1e-5) * 1e5)**2 else: lumdist = WMAP9.luminosity_distance(zred).value dfactor = (lumdist * 1e5)**2 if peraa: # spectrum will be in erg/s/cm^2/AA smspec *= to_cgs / dfactor * lightspeed / outwave**2 else: # Spectrum will be in maggies smspec *= to_cgs / dfactor / 1e3 / (3631*jansky_mks) # Convert from absolute maggies to apparent maggies phot /= dfactor # Mass normalization mass = np.sum(self.params.get('mass', 1.0)) if np.all(self.params.get('mass_units', 'mstar') == 'mstar'): # Convert from current stellar mass to mass formed mass /= mfrac return smspec * mass, phot * mass, mfrac
def total_cloud_data(cloud, filternames=None, basti=False, lfstring=None, agb_dust=1.0, one_metal=None): ######### # SPS ######### # if filternames is not None: sps = fsps.StellarPopulation(add_agb_dust_model=True) sps.params['sfh'] = 0 sps.params['agb_dust'] = agb_dust dust = ['nodust', 'agbdust'] sps.params['imf_type'] = 0.0 #salpeter filterlist = observate.load_filters(filternames) else: filterlist = None ########## # SFHs ########## regions, nx, ny, zlist, zlist_basti = cloud_info[cloud.lower()] if basti: zlist = basti_zlist if 'header' in regions.keys(): rheader = regions.pop( 'header') #dump the header info from the reg. dict total_sfhs = None for n, dat in regions.iteritems(): total_sfhs = sum_sfhs(total_sfhs, dat['sfhs']) total_zmet = dat['zmet'] #collapse SFHs to one metallicity if one_metal is not None: ts = None for sfh in total_sfhs: ts = sum_sfhs(ts, sfh) total_sfh = ts zlist = [zlist[one_metal]] total_zmet = [total_zmet[one_metal]] ############# # LFs ############ bins = rsed.lfbins if lfstring is not None: # these are stored as a list of different metallicities lffiles = [lfstring.format(z) for z in zlist] lf_base = [read_villaume_lfs(f) for f in lffiles] #get LFs broken out by age and metallicity as well as the total lfs_zt, lf, logages = rsed.one_region_lfs(copy.deepcopy(total_sfhs), lf_base) else: lfs_zt, lf, logages = None, None, None ########### # SED ############ if filterlist is not None: spec, wave, mass = rsed.one_region_sed(copy.deepcopy(total_sfhs), total_zmet, sps) mags = observate.getSED(wave, spec * rsed.to_cgs, filterlist=filterlist) maggies = 10**(-0.4 * np.atleast_1d(mags)) else: maggies, mass = None, None ############# # Write output ############ total_values = {} total_values['agb_clf'] = lf total_values['agb_clfs_zt'] = lfs_zt total_values['clf_mags'] = bins total_values['logages'] = logages total_values['sed_ab_maggies'] = maggies total_values['sed_filters'] = filternames total_values['lffile'] = lfstring total_values['mstar'] = mass total_values['zlist'] = zlist return total_values, total_sfhs
def total_galaxy_data(sfhfilename, zindex, filternames=None, basti=False, lfstring=None, agb_dust=1.0): total_sfhs = [load_angst_sfh(sfhfilename)] rsed.lfbins += total_sfhs[0]['dmod'][0] zlist = [zindex] ######### # Initialize the ingredients (SPS, SFHs, LFs) ######### # SPS if filternames is not None: sps = fsps.StellarPopulation(add_agb_dust_model=True) sps.params['sfh'] = 0 sps.params['agb_dust'] = agb_dust dust = ['nodust', 'agbdust'] sps.params['imf_type'] = 0.0 #salpeter filterlist = observate.load_filters(filternames) zmets = [sps.zlegend[zindex - 1]] else: filterlist = None ############# # Sum the region SFHs into a total integrated SFH, and do the # temporal interpolations to generate integrated spectra, LFs, and # SEDs ############ # Get LFs broken out by age and metallicity as well as the total # LFs. these are stored as a list of different metallicities bins = rsed.lfbins if lfstring is not None: lffiles = [lfstring.format(z) for z in zlist] lf_base = [read_villaume_lfs(f) for f in lffiles] lfs_zt, lf, logages = rsed.one_region_lfs(copy.deepcopy(total_sfhs), lf_base) else: lfs_zt, lf, logages = None, None, None # Get spectrum and magnitudes if filterlist is not None: spec, wave, mass = rsed.one_region_sed(copy.deepcopy(total_sfhs), zmets, sps) mags = observate.getSED(wave, spec * rsed.to_cgs, filterlist=filterlist) maggies = 10**(-0.4 * np.atleast_1d(mags)) else: maggies, mass = None, None ############# # Write output ############ total_values = {} total_values['agb_clf'] = lf total_values['agb_clfs_zt'] = lfs_zt total_values['clf_mags'] = bins.copy() total_values['logages'] = logages total_values['sed_ab_maggies'] = maggies total_values['sed_filters'] = filternames total_values['lffile'] = lfstring total_values['mstar'] = mass total_values['zlist'] = zlist rsed.lfbins -= total_sfhs[0]['dmod'][0] return total_values, total_sfhs
# and IR luminosities wave, spec, mass, lir = bsp.bursty_sps(lt, sfr, sps, lookback_time=t_lookback, av=av, dav=dav, nsplit=30) for j, jt in enumerate(t_lookback): pl.plot(wave, spec[j, :] * wave * bsp.to_cgs, label='{0} @ {1}'.format(objname[i], tl[j])) # Project onto filters to get # absolute magnitudes mags = observate.getSED(wave, spec * bsp.to_cgs, filterlist=filterlist) # Get the intrinsic spectrum and project onto filters wave, spec, mass, _ = bsp.bursty_sps(lt, sfr, sps, lookback_times=t_lookback, av=None, dav=None) mags_int = observate.getSED(wave, spec * bsp.to_cgs, filterlist=filterlist) pl.xlim(1e3, 1e4) pl.ylim(1e-3, 1e1) pl.yscale('log') pl.xlabel(r'wavelength ($\AA$)') pl.ylabel(r'$\lambda$L$_\lambda$ (erg/s/cm$^2$ @ 10pc)')
def standard_star_compare(): # This is the filters and magnitudes for the calibrator star filters = load_filters(["sdss_g0", "sdss_r0", "sdss_i0", "sdss_z0"]) # Get a reasonable set of model spectra libwave, libflux, libparams = get_library() #store all the flux calibration vectors into an ndarray flux_calib_ndarray = [] #print(flux_calib_ndarray.shape) #NEED TO CHANGE 0 TO INDEX BASED ON CROSSMATCH #loop over 0 for i, val in enumerate(std_stars_df): star_mags = np.array([mask_std_stars['psfMag_g'][i],\ mask_std_stars['psfMag_r'][i],\ mask_std_stars['psfMag_i'][i],\ mask_std_stars['psfMag_z'][i]]) #bino spectrum for calibration star data_wave, data_flux = spec_fetcher(val['Slit ID']) data_flux *= 1e-19 # header units # choose the model with colors closest to the calibrator best_model = choose_model(star_mags, filters, libwave, libflux) # Now work out the normalization of the model from the average magnitude offset best_sed = getSED(libwave, best_model, filters) dm = np.mean(star_mags - best_sed) conv = 10**(-0.4 * dm) # Here, finally, is the fluxed model (erg/s/cm^2/AA) fluxed_model = best_model * conv # Now get the model on the same wavelength vector as the data z = 0.0 # redshift of the star, if known. #? a = (1 + z) fluxed_model_interp = np.interp(data_wave, libwave * a, fluxed_model) calibration = data_flux / fluxed_model_interp # You probably want to median filter the calibration vector. # Perhaps # after some sigma clipping. differences on small scales could be due to # model imperfections (wrong metallicity, wrong gravity for model, LSF # mismatch) # you could also fit the calibration vector with a polynomial, taking into # account errors smoothed_calibration = medfilt(calibration, 101) #fig, axes = plt.subplots(1, 1, sharex=True, figsize=(13, 11)) #plt.plot(data_wave, calibration, label="raw calibration") plt.plot(data_wave, smoothed_calibration, label="smoothed calibration") plt.xlabel("Wavelength [A]") plt.ylabel("actual / input") flux_calib_ndarray.append(smoothed_calibration) #print(np.min(smoothed_calibration)) #ax.legend() #ax.set_ylabel("actual / input") #plt.ylim([0, 0.1]) #plt.xlim([7500, 7700]) flux_calib_ndarray = np.array(flux_calib_ndarray) #mean_calib = flux_calib_ndarray.mean(axis = 0) #mean_calib = np.true_divide(flux_calib_ndarray.sum(0),(flux_calib_ndarray!=0).sum(0)) #ignore all the 0 values flux_calib_ndarray[flux_calib_ndarray == 0] = np.nan mean_calib = np.nanmean(flux_calib_ndarray, axis=0) mean_calib[np.isnan(mean_calib) == True] = 0. plt.plot(data_wave, mean_calib, label="mean calibration", c='k', ls="--") return mean_calib
def get_spectrum(self, outwave=None, filters=None, peraa=False, **params): """Get a spectrum and SED for the given params. :param outwave: (default: None) Desired *vacuum* wavelengths. Defaults to the values in `sps.wavelength`. :param peraa: (default: False) If `True`, return the spectrum in erg/s/cm^2/AA instead of AB maggies. :param filters: (default: None) A list of filter objects for which you'd like photometry to be calculated. :param **params: Optional keywords giving parameter values that will be used to generate the predicted spectrum. :returns spec: Observed frame spectrum in AB maggies, unless `peraa=True` in which case the units are erg/s/cm^2/AA. :returns phot: Observed frame photometry in AB maggies. :returns mass_frac: The ratio of the surviving stellar mass to the total mass formed. """ # Spectrum in Lsun/Hz per solar mass formed, restframe wave, spectrum, mfrac = self.get_galaxy_spectrum(**params) # Redshifting + Wavelength solution # We do it ourselves. a = 1 + self.params.get('zred', 0) af = a b = 0.0 if 'wavecal_coeffs' in self.params: x = wave - wave.min() x = 2.0 * (x / x.max()) - 1.0 c = np.insert(self.params['wavecal_coeffs'], 0, 0) # assume coeeficients give shifts in km/s b = chebval(x, c) / (lightspeed*1e-13) wa, sa = wave * (a + b), spectrum * af # Observed Frame if outwave is None: outwave = wa # Observed frame photometry, as absolute maggies if filters is not None: mags = getSED(wa, lightspeed/wa**2 * sa * to_cgs, filters) phot = np.atleast_1d(10**(-0.4 * mags)) else: phot = 0.0 # Spectral smoothing. do_smooth = (('sigma_smooth' in self.params) and ('sigma_smooth' in self.reserved_params)) if do_smooth: # We do it ourselves. smspec = self.smoothspec(wa, sa, self.params['sigma_smooth'], outwave=outwave, **self.params) elif outwave is not wa: # Just interpolate smspec = np.interp(outwave, wa, sa, left=0, right=0) else: # no interpolation necessary smspec = sa # Distance dimming and unit conversion zred = self.params.get('zred', 0.0) if (zred == 0) or ('lumdist' in self.params): # Use 10pc for the luminosity distance (or a number # provided in the dist key in units of Mpc) dfactor = (self.params.get('lumdist', 1e-5) * 1e5)**2 else: lumdist = cosmo.luminosity_distance(zred).value dfactor = (lumdist * 1e5)**2 if peraa: # spectrum will be in erg/s/cm^2/AA smspec *= to_cgs / dfactor * lightspeed / outwave**2 else: # Spectrum will be in maggies smspec *= to_cgs / dfactor / (3631*jansky_cgs) # Convert from absolute maggies to apparent maggies phot /= dfactor # Mass normalization mass = np.sum(self.params.get('mass', 1.0)) if np.all(self.params.get('mass_units', 'mformed') == 'mstar'): # Convert input normalization units from current stellar mass to mass formed mass /= mfrac return smspec * mass, phot * mass, mfrac
def build_obs(objid=0, luminosity_distance=None, **kwargs): """Load photometry from an ascii file. Assumes the following columns: `objid`, `filterset`, [`mag0`,....,`magN`] where N >= 11. The User should modify this function (including adding keyword arguments) to read in their particular data format and put it in the required dictionary. :param objid: The object id for the row of the photomotery file to use. Integer. Requires that there be an `objid` column in the ascii file. :param phottable: Name (and path) of the ascii file containing the photometry. :param luminosity_distance: (optional) The Johnson 2013 data are given as AB absolute magnitudes. They can be turned into apparent magnitudes by supplying a luminosity distance. :returns obs: Dictionary of observational data. """ from prospect.utils.obsutils import fix_obs #filterlist = load_filters(['sdss_u0', 'sdss_g0', 'sdss_r0', 'sdss_i0', 'sdss_z0', # 'galex_FUV', 'galex_NUV', 'wise_w1', 'wise_w2', # 'wise_w3', 'wise_w4']) filterlist = load_filters(args.filters) microns = np.load('{0}/Prospector_files/wave.npy'.format(args.path)) angstroms = microns * 1e4 spec = np.load('{0}/Prospector_files/spec.npy'.format( args.path)) # units of Jy f_lambda_cgs = (1 / 33333) * (1 / (angstroms**2)) * spec mags = getSED(angstroms, f_lambda_cgs, filterlist=filterlist) # AB magnitudes #print('AB mags', mags) #np.save('ab_mags.npy', mags) maggies = 10**(-0.4 * mags) # convert to maggies wave_eff = np.zeros(len(filterlist)) for i in range(len(filterlist)): filterlist[i].get_properties() wave_eff[i] = filterlist[i].wave_effective print('maggies', maggies) print('effective wavelengths', wave_eff) # Build output dictionary. obs = {} obs['filters'] = filterlist obs['maggies'] = maggies obs['maggies_unc'] = obs['maggies'] * 0.07 obs['phot_mask'] = np.isfinite(np.squeeze(maggies)) obs['wavelength'] = None obs['spectrum'] = None obs['unc'] = None obs['objid'] = None # This ensures all required keys are present and adds some extra useful info obs = fix_obs(obs) return obs
def get_redshifted_photometry(lambda_aa, f_lambda_aa, redshift_grid, filter_list, apply_madau_igm=False): """ - Parameters ---------- lambda_aa, f_lambda_aa: ndarray (size, ) wavelength (in Angstrom) and rest-frame spectral energy distribution f_nu(lambda) redshift_grid: ndarray (size, ) array of redshift values to compute the photometry on filter_list: list of strings names of the photometric filters (will load with the SEDPY package) Returns ------- https://www.roe.ac.uk/ifa/postgrad/pedagogy/2008_phillips.pdf https://arxiv.org/pdf/astro-ph/0210394.pdf """ numBands = len(filter_list) redshift_factors = np.zeros((redshift_grid.size,)) redshifted_fluxes = np.zeros((redshift_grid.size, numBands)) redshifted_fluxes2 = np.zeros((redshift_grid.size, numBands)) for iz, redshift in enumerate(redshift_grid): lambda_aa_redshifted = lambda_aa * (1 + redshift) redshift_factors[iz] = ( D_L(redshift) ** 2.0 * (4 * np.pi) * (1 + redshift) ) ** -1 # separate redshift factor f_lambda_aa_redshifted = f_lambda_aa if apply_madau_igm: tau = igm_madau_tau(lambda_aa, redshift) f_lambda_aa_redshifted *= np.exp(-tau) f_nu_aa_redshifted = f_lambda_aa_redshifted * lambda_aa_redshifted ** 2 / 3e18 # get magnitudes using sedpy mags = observate.getSED( lambda_aa_redshifted, f_lambda_aa_redshifted, filterlist=filter_list ) redshifted_fluxes[iz, :] = 10 ** ( -0.4 * (mags + 48.60) ) # need to convert back from AB to cgs for ib, filter in enumerate(filter_list): filt_lambda, filt_spec = filter.wavelength * 1, filter.transmission * 1 # need to normalize by this integral to satisfy photometry equations filt_spec /= np.trapz(filt_spec / filt_lambda, x=filt_lambda) # interpolate filter on redshifted lambda_aa_redshifted grid tspec = interp(lambda_aa_redshifted, filt_lambda, filt_spec) # print(lambda_aa_redshifted) redshifted_fluxes2[iz, ib] = np.trapz( f_nu_aa_redshifted * tspec / lambda_aa_redshifted, x=lambda_aa_redshifted, ) # tODO: implement the other way around. # tspec = interp(filt_lambda, spec_lambda * (1 + zred), spec_f_lambda) # redshifted_fluxes3[iz, ib] = np.trapz(tspec * filt_spec / filt_lambda, x=filt_lambda) return redshifted_fluxes, redshifted_fluxes2, redshift_factors
def create_grid(self,fname,ebv=None,ages=None,HaEW=None,zGrid=None,\ csiGrid = None, alphaGrid =None, o3o2Grid=None,\ colorList=None,debug=False): def _write_grid(fname): fout = h5py.File(fname, "w") gridDataset = fout.create_dataset("grid", data=model_grid) gridDataset.attrs["shape"] = model_grid.shape gridDataset.attrs["colors"] = color_idxs for i, name in enumerate(allGridNames): fout.create_dataset(name, data=allGrids[i]) gridDataset.attrs[f"AXIS{i}"] = name fout.close() return None color_idxs = self._define_colors(colorList) if debug is True: print("CLRS", color_idxs) if zGrid is None: zGrid = np.linspace(1, 3, 50) if ebv is None: ebv = [0, 0.1, 0.2, 0.3] if ages is None: ages = np.logspace(-3, np.log10(2), 50) if HaEW is None: HaEW = np.linspace(0, 200, 100) if csiGrid is None: csiGrid = np.asarray([1.0]) if alphaGrid is None: alphaGrid = np.asarray([0.0]) if o3o2Grid is None: o3o2Grid = np.asarray([0.35]) FilterList = observate.load_filters(self.filter_names) ncolors = len(color_idxs) nAges = len(ages) nHa = len(HaEW) ndust = len(ebv) nzGrid = len(zGrid) ncsiGrid = len(csiGrid) no3o2Grid = len(o3o2Grid) nalphaGrid = len(alphaGrid) allGrids = [ color_idxs, HaEW, ebv, ages, csiGrid, o3o2Grid, alphaGrid, zGrid ] allGridNames = [ "colors", "Ha", "dust", "ages", "csi", "o3o2", "alpha", "redshift" ] nElements = [len(grid) for grid in allGrids] model_grid = np.zeros(nElements) if debug is True: print("Start creating grid: ", model_grid.shape) tstart = time.time() for i, value in enumerate(ebv): if debug is True: print(i) self.model.params['dust2'] = value * 4.05 # E(B-V) * RV for j, age in enumerate(ages): wave, spec = self.model.get_spectrum(tage=age, peraa=True) emLineSpec = EmissionSpectrum(wave) for k, Ha in enumerate(HaEW): for ii, csi in enumerate(csiGrid): for jj, o3o2 in enumerate(o3o2Grid): for kk, alpha in enumerate(alphaGrid): for nn, z in enumerate(zGrid): emLineSpec.halpha_model(spec, Ha, logzsol=0, csi=csi, alpha=alpha, o3o2=o3o2, redshift=z) mags = observate.getSED( wave * (1 + z), spec + emLineSpec.flux, filterlist=FilterList) colors = [ mags[c[0]] - mags[c[1]] for c in color_idxs ] model_grid[:, k, i, j, ii, jj, kk, nn] = colors tend = time.time() if debug is True: print(f"Elapsed {tend-tstart} secs on grid creation") _write_grid(fname) # self.model.params['dust2'] = 0.00 * 4.05 # E(B-V) * RV # mags= self.model.get_mags(tage=ages[0],redshift=zGrid[0], bands=self.filter_names) # print(mags[:-1]-mags[1:]) # # wave, spec = self.model.get_spectrum(tage=ages[0],peraa=True) # emLineSpec = EmissionSpectrum(wave) # emLineSpec.halpha_model(spec, HaEW[1], logzsol=0) # mags = observate.getSED(wave*(1+zGrid[0]), spec, filterlist=FilterList) # print(mags[:-1]-mags[1:]) # # # selLims = (2900,9600) # fig = mpl.figure(figsize=(12,8)) # ax = fig.add_axes([0.05,0.05,0.9,0.6]) # axLines = fig.add_axes([0.05,0.65,0.9,0.3],sharex=ax) # emLineSpec.plot_spectrum(ax=axLines,color="LimeGreen") # selection = (wave>selLims[0]) & (wave<selLims[1]) # ax.plot(wave[selection],spec[selection]+emLineSpec.flux[selection],color="LimeGreen") # ax.plot(wave[selection],spec[selection],color="k") # ax.set_xlim(selLims[0],selLims[1]) # axLines.tick_params(labelbottom=False) # mpl.show() # # self.model.params['dust2'] = 0.20 * 4.05 # E(B-V) * RV # print(self.model.get_mags(tage=0.1,redshift=2.0, bands=self.filter_names)) return
for i in range(len(galaxies)): for j in range(len(dustFraction)): if dust or partialDust: wave = np.load(SKIRT_path1 + galaxies[i] + SKIRT_path2 + dustFraction[j] + SKIRT_path3 + 'wave.npy') * 1e4 # convert to Angstroms spec = np.load(SKIRT_path1 + galaxies[i] + SKIRT_path2 + dustFraction[j] + SKIRT_path3 + 'spec.npy') # in Jy else: wave = np.load(SKIRT_path1 + galaxies[i] + SKIRT_path2 + 'wave.npy') * 1e4 # convert to Angstroms spec = np.load(SKIRT_path1 + galaxies[i] + SKIRT_path2 + 'spec.npy') # in Jy filterlist = observate.load_filters(bands) f_lambda_cgs = (1 / 33333) * (1 / (wave**2)) * spec mags = observate.getSED(wave, f_lambda_cgs, filterlist=filterlist) # in AB Magnitudes jy = 1e26 * 10**( -1 * (mags + 48.6) / 2.5 ) # convert from AB mags to Janskys (same order as bands) for k in range(len(bands)): SKIRT_flux[i, j, k] = jy[k] # load gas text files textFilePath = '/scratch/ntf229/RT_fit/resources/NIHAO/TextFiles/' + galaxies[ i] + '/' gas = np.loadtxt(textFilePath + 'gas.txt') stars = np.loadtxt(textFilePath + 'stars.txt') #youngStars = np.loadtxt(textFilePath+'youngStars.txt') starMasses = stars[:, 7] # units of M_sun #youngStarMasses = youngStars[:,7] * 1e7 totStarMass[i] = np.sum(starMasses) #gasDensity = np.loadtxt(textFilePath+'gas_density.txt')
#convert into a high resolution sfh, with *no* intrabin sfr variations lt, sfr, fb = bsp.burst_sfh(fwhm_burst=0.05, f_burst=0., contrast=1., sfh=sfh, bin_res=20.) # Get the attenuated spectra # and IR luminosities wave, spec, mass, lir = bsp.bursty_sps(lt, sfr, sps, lookback_time=t_lookback, av=av, dav=dav, nsplit=30) for j, jt in enumerate(t_lookback): pl.plot(wave, spec[j,:] * wave * bsp.to_cgs, label = '{0} @ {1}'.format(objname[i], tl[j])) # Project onto filters to get # absolute magnitudes mags = observate.getSED(wave, spec * bsp.to_cgs, filterlist = filterlist) # Get the intrinsic spectrum and project onto filters wave, spec, mass, _ = bsp.bursty_sps(lt, sfr, sps, lookback_times=t_lookback, av=None, dav=None) mags_int = observate.getSED(wave, spec * bsp.to_cgs, filterlist = filterlist) pl.xlim(1e3, 1e4) pl.ylim(1e-3,1e1) pl.yscale('log') pl.xlabel(r'wavelength ($\AA$)') pl.ylabel(r'$\lambda$L$_\lambda$ (erg/s/cm$^2$ @ 10pc)') pl.legend(loc = 'lower right') pl.savefig('demo_bsp.png') pl.show()