def table(self): """An :class:`astropy.table.Table` with the chain.""" msuns = np.array([fsps.get_filter(n).msun_ab for n in self._model.computed_bands]) theta_f_accept = json.dumps(dict(zip(self._model.theta_params, self.median_theta_faccept))) phi_f_accept = json.dumps(dict(zip(self._model.phi_params, self.phi_faccept))) meta = OrderedDict(( ('theta_f_accept', theta_f_accept), ('phi_f_accept', phi_f_accept), ('observed_bands', self._model.observed_bands), ('instruments', self._model.instruments), ('computed_bands', self._model.computed_bands), ('msun_ab', msuns), ('band_indices', self._model.band_indices), ('theta_params', self._model.theta_params), ('phi_params', self._model.phi_params), ('theta_proposal_sigma', self._theta_prop), ('phi_proposal_sigma', self._theta_prop), ('sed', self._model._seds), ('sed_err', self._model._errs), ('pixels', self._model.pixel_metadata), ('area', self._model._areas))) # Make tables for individual chains; stack later # FIXME should axis order be changed for theta throughout the sampler? # or I can just continue to swarp aces here theta_table = Table(np.swapaxes(self.theta, 1, 2), names=self._model.theta_params, meta=meta) phi_table = Table(self.phi, names=self._model.phi_params) background_names = ["B__{0}__{1}".format(n, b) for n, b in zip(self._model.instruments, self._model.observed_bands)] B_table = Table(self.B, names=background_names) blob_table = Table(self.blobs) tbl = MultiPixelChain(hstack((theta_table, phi_table, B_table, blob_table))) # Add M/L computations for each computed band. for i, (band_name, msun) in enumerate(zip(self._model.computed_bands, msuns)): logLsol = micro_jy_to_luminosity(tbl['model_sed'][:, :, i], msun, np.atleast_2d(tbl['d']).T) ml = tbl['logMstar'] - logLsol colname = "logML_{0}".format(band_name) tbl.add_column(Column(name=colname, data=ml)) return tbl
def compute_library_seds(self, bands, age=13.7, default_pset=None): """Compute an SED for each library model instance. Model SEDs are stored as absolute fluxes (µJy at d=10pc), normalized to a 1 Solar mass stellar population. .. todo:: Support parallel computation. Parameters ---------- bands : list List of `FSPS bandpass names <http://dan.iel.fm/python-fsps/current/filters/>`_. default_pset : dict Default Python-FSPS parameters. """ if default_pset is None: default_pset = {} # ALWAYS compute AB mags default_pset['compute_vega_mags'] = False # Solar magnitude in each bandpass solar_mags = [fsps.get_filter(n).msun_ab for n in bands] # Add bands and AB solar mags to the group attr metadata self.group.attrs['bands'] = bands self.group.attrs['msun_ab'] = solar_mags # Build the SED table table_names = ['seds', 'mass_light', 'meta'] for name in table_names: if name in self.group: del self.group[name] # Table for SEDs n_models = len(self.group["params"]) dtype = np.dtype([(n, np.float) for n in bands]) sed_table = self.group.create_dataset("seds", (n_models,), dtype=dtype) # Table for M/L ratios in each bandpass dtype = np.dtype([(n, np.float) for n in bands]) ml_table = self.group.create_dataset("mass_light", (n_models,), dtype=dtype) # Table for metadata (stellar mass, dust mass, etc..) meta_cols = ('logMstar', 'logMdust', 'logLbol', 'logSFR', 'logAge') dtype = np.dtype([(n, np.float) for n in meta_cols]) meta_table = self.group.create_dataset("meta", (n_models,), dtype=dtype) # Iterate on each model # TODO eventually split this work between processors sp_param_names = self.group['params'].dtype.names sp = fsps.StellarPopulation(**default_pset) for i, row in enumerate(self.group["params"]): for n, p in zip(sp_param_names, row): sp.params[n] = float(p) mags = sp.get_mags(tage=age, bands=bands) fluxes = abs_ab_mag_to_micro_jy(mags, 10.) # Fill in SED and ML tables for n, msun, flux in zip(bands, solar_mags, fluxes): # interesting slicing syntax for structured array assignment sed_table[n, i] = flux logL = micro_jy_to_luminosity(flux, msun, 10.) log_ml = np.log10(sp.stellar_mass) - logL ml_table[n, i] = log_ml # Fill in meta data table meta_table['logMstar', i] = np.log10(sp.stellar_mass) meta_table['logMdust', i] = np.log10(sp.dust_mass) meta_table['logLbol', i] = np.log10(sp.log_lbol) meta_table['logSFR', i] = np.log10(sp.sfr) meta_table['logAge', i] = sp.log_age
def table(self): """An :class:`astropy.table.Table` with the chain.""" if self.sampler is None: return None msuns = np.array([fsps.get_filter(n).msun_ab for n in self.model.computed_bands]) meta = OrderedDict(( ('observed_bands', self.model.observed_bands), ('instruments', self.model.instruments), ('computed_bands', self.model.computed_bands), ('msun_ab', msuns), ('d', self.model.d), # expected distance in parsecs ('band_indices', self.model.band_indices), ('theta_params', self.model.param_names), ('compute_time', self._run_time), ('step_time', self._call_time), ('sed', self.model._sed), ('sed_err', self.model._err), ('pixels', self.model.pixel_metadata), ('area', self.model._area), ('n_walkers', self.n_walkers), ("f_accept", self.sampler.acceptance_fraction), ("acor", self.sampler.acor))) # Convert flatchain into a structured array nwalkers, nsteps, ndim = self.sampler.chain.shape flatchain_arr = self.sampler.chain[:, :, :].reshape((-1, ndim)) dt = [(n, np.float) for n in self.model.param_names] flatchain = np.empty(flatchain_arr.shape[0], dtype=np.dtype(dt)) for i, n in enumerate(self.model.param_names): flatchain[n][:] = flatchain_arr[:, i] # Flatten the blob list and make a structured array blobs = self.sampler.blobs blobchain = np.empty(nwalkers * nsteps, self.model.blob_dtype) blobchain.fill(np.nan) for i in xrange(nsteps): for j in xrange(nwalkers): for k in self.model.blob_dtype.names: blobchain[k][i * self.n_walkers + j] = blobs[i][j][k] chain_table = Table(flatchain, meta=meta) blob_table = Table(blobchain) tbl = SinglePixelChain(hstack((chain_table, blob_table), join_type='exact')) # Add M/L computations for each computed band. for i, (band_name, msun) in enumerate(zip(self.model.computed_bands, msuns)): # Either use expected distance or the chain distance # FIXME fragile code if 'd' in self.model.param_names: d = np.array(tbl['d']) else: d = self.model.d logLsol = micro_jy_to_luminosity(tbl['model_sed'][:, i], msun, d) ml = tbl['logMstar'] - logLsol colname = "logML_{0}".format(band_name) tbl.add_column(Column(name=colname, data=ml)) return tbl