예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
    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