Example #1
0
    def build_lnl_fn(self, normv, nllv):
        """ Build a function to return the likelihood value arrays of
        normalization and likelihood values.

        Parameters
        ----------

        normv : `numpy.array`
            Set of test normalization values

        nllv : `numpy.array`
            Corresponding set of negative log-likelihood values

        Returns
        -------

        output : `fermipy.castro.LnLFn` or `LnLFn_norm_prior`
            Object that can compute the negative log-likelihood with
            the prior included (if requested)

        """
        lnlfn = castro.LnLFn(normv, nllv, self._norm_type)
        if self._astro_prior is None:
            return lnlfn
        if self._prior_applied:
            return lnlfn
        return LnLFn_norm_prior(lnlfn, self._astro_prior)
Example #2
0
 def build_lnl_fn(self, normv, nllv):
     """ Build a function to return the likelihood value arrays of
     normalization and likelihood values
     """
     lnlfn = castro.LnLFn(normv, nllv, self._norm_type)
     if self._astro_prior is None:
         return lnlfn
     if self._prior_applied:
         return lnlfn
     return stats_utils.LnLFn_norm_prior(lnlfn, self._astro_prior)
Example #3
0
    def compute_castro_data(castro_data, spec_vals, xscan_vals, **kwargs):
        """ Convert CastroData object, i.e., Likelihood as a function of
        flux and energy flux, to a StackCastroData object, i.e., Likelihood as
        a function of stacking normalization and index

        Parameters
        ----------

        castro_data : `CastroData`
            Input data

        spec_vals : `numpy.array`
            Input spectra

        xscan_vals : `numpy.array`
            Values for scan variables


        Returns
        -------

        output : `StackCastroData`
            The stacking-space likelihood curves


        """
        ref_stack = kwargs.get('ref_stack', 1.)
        norm_factor = kwargs.pop('norm_factor', 1.)
        spec_name = kwargs.pop('spec_name')
        astro_prior = kwargs.pop('astro_prior')
        n_xval = len(xscan_vals)
        n_yval = kwargs.get('nystep', 200)

        norm_limits = castro_data.getLimits(1e-5)
        # This puts the spectrum in units of the reference spectrum
        # This means that the scan values will be expressed
        # In units of the reference spectra as well
        spec_vals /= norm_factor

        norm_vals = np.ndarray((n_xval, n_yval))
        dll_vals = np.ndarray((n_xval, n_yval))
        mle_vals = np.ndarray((n_xval))
        nll_offsets = np.ndarray((n_xval))

        scan_mask = np.ones((n_xval), bool)
        # for i, index in enumerate(xscan_vals):
        for i in range(n_xval):
            max_ratio = 1. / ((spec_vals[i] / norm_limits).max())
            log_max_ratio = np.log10(max_ratio)
            norm_vals[i][0] = 10**(log_max_ratio - 5)
            norm_vals[i][1:] = np.logspace(log_max_ratio - 4,
                                           log_max_ratio + 4, n_yval - 1)
            test_vals = (np.expand_dims(spec_vals[i], 1) *
                         (np.expand_dims(norm_vals[i], 1).T))
            dll_vals[i, 0:] = castro_data(test_vals)
            mle_vals[i] = norm_vals[i][dll_vals[i].argmin()]
            nll_offsets[i] = dll_vals[i].min()
            dll_vals[i] -= nll_offsets[i]

            msk = np.isfinite(dll_vals[i])
            if not msk.any():
                print("Skipping scan value %0.2e for spec %s" %
                      (xscan_vals[i], spec_name))
                scan_mask[i] = False
                continue

            if is_not_null(astro_prior):
                try:
                    lnlfn = castro.LnLFn(norm_vals[i], dll_vals[i], 'dummy')
                    lnlfn_prior = LnLFn_norm_prior(lnlfn, astro_prior)
                    dll_vals[i, 0:] = lnlfn_prior(norm_vals[i])
                    nll_offsets[i] = dll_vals[i].min()
                except ValueError:
                    print("Skipping index %0.2e for spec %s" %
                          (xscan_vals[i], spec_name))
                    scan_mask[i] = False
                    dll_vals[i, 0:] = np.nan * np.ones((n_yval))
                    nll_offsets[i] = np.nan

        kwcopy = kwargs.copy()
        kwcopy['xscan_vals'] = xscan_vals[scan_mask]
        kwcopy['astro_prior'] = astro_prior

        # Here we convert the normalization values to standard units
        norm_vals *= ref_stack
        stack_castro = StackCastroData(norm_vals[scan_mask],
                                       dll_vals[scan_mask],
                                       nll_offsets[scan_mask], **kwcopy)
        return stack_castro
Example #4
0
    def convert_castro_data(self,
                            castro_data,
                            channel,
                            norm_type,
                            jfactor=None):
        """ Convert CastroData object, i.e., Likelihood as a function of
        flux and energy flux, to a DMCastroData object, i.e., Likelihood as
        a function of DM mass and sigmav
        """
        if not self.check_energy_bins(castro_data.refSpec):
            raise ValueError("CastroData energy binning does not match")
        mask = self._s_table['ref_chan'] == channel
        masses = self._s_table[mask]['ref_mass'].data
        spec_vals = self._s_table[mask]['ref_%s' % norm_type].data
        nmass = len(masses)

        # Get the reference values
        ref_sigmav = self._ref_vals["ref_sigv"]
        ref_norm = self._ref_vals["ref_J"]

        j_prior = None
        if jfactor is None:
            # Just use the reference values
            j_ref = ref_norm
            norm_factor = 1.
        elif isinstance(jfactor, float):
            # Rescale the normalization values
            j_ref = jfactor
            norm_factor = jfactor / ref_norm
        elif isinstance(jfactor, dict):
            j_ref = jfactor.get('j_value')
            norm_factor = j_ref / ref_norm
            j_prior = stats_utils.create_prior_functor(jfactor)

        norm_limits = castro_data.getLimits(1e-5)
        spec_vals *= norm_factor

        n_scan_pt = 100

        norm_vals = np.ndarray((nmass, n_scan_pt))
        dll_vals = np.ndarray((nmass, n_scan_pt))
        mle_vals = np.ndarray((nmass))

        # for i, mass in enumerate(masses):
        for i in range(nmass):
            max_ratio = 1. / ((spec_vals[i] / norm_limits).max())
            log_max_ratio = np.log10(max_ratio)
            norm_vals[i][0] = 0.
            norm_vals[i][1:] = np.logspace(log_max_ratio - 2,
                                           log_max_ratio + 2, n_scan_pt - 1)
            test_vals = (np.expand_dims(spec_vals[i], 1) *
                         (np.expand_dims(norm_vals[i], 1).T))
            dll_vals[i, 0:] = castro_data(test_vals)
            mle_vals[i] = norm_vals[i][dll_vals[i].argmin()]
            mle_ll = dll_vals[i].min()
            dll_vals[i] -= mle_ll

            if j_prior is not None:
                lnlfn = castro.LnLFn(norm_vals[i], dll_vals[i], 'dummy')
                lnlfn_prior = stats_utils.LnLFn_norm_prior(lnlfn, j_prior)
                dll_vals[i, 0:] = lnlfn_prior(norm_vals[i])

        norm_vals *= (ref_sigmav)
        dm_castro = DMCastroData(norm_vals, dll_vals, norm_factor, channel,
                                 masses, j_ref, j_prior)
        return dm_castro
Example #5
0
    def convert_castro_data(self, castro_data, channel,
                            norm_type, astro_factor=None):
        """ Convert CastroData object, i.e., Likelihood as a function of
        flux and energy flux, to a DMCastroData object, i.e., Likelihood as
        a function of DM mass and sigmav

        Parameters
        ----------

        castro_data : `CastroData`
            Input data

        channel : int
            Index for the DM interaction channel

        norm_type : str
            Type of spectral normalization to use for the conversion

        astro_factor : dict or float or None
            Nuisance factor used to make the conversion.

            If astro_factor is None, it will use the reference value
            If astro_factor is a float, it will use that
            If astro_factor is a dict, it will use that to create a prior

        Returns
        -------

        output : `DMCastroData`
            The DM-space likelihood curves


        """
        if not self.check_energy_bins(castro_data.refSpec):
            raise ValueError("CastroData energy binning does not match")
        mask = self._s_table['ref_chan'] == channel
        masses = self._s_table[mask]['ref_mass'].data
        spec_vals = self._s_table[mask]['ref_%s' % norm_type].data
        nmass = len(masses)

        is_decay = channel >= 100

        # Get the reference values
        if is_decay:
            ref_inter = self._ref_vals["REF_TAU"]
            ref_norm = self._ref_vals["REF_D"]
            astro_str = 'd_value'
        else:
            ref_inter = self._ref_vals["REF_SIGV"]
            ref_norm = self._ref_vals["REF_J"]
            astro_str = 'j_value'

        astro_prior = None
        if is_null(astro_factor):
            # Just use the reference values
            astro_value = ref_norm
            norm_factor = 1.
        elif isinstance(astro_factor, float):
            # Rescale the normalization values
            astro_value = astro_factor
            norm_factor = ref_norm / astro_factor
        elif isinstance(astro_factor, dict):
            astro_value = astro_factor.get(astro_str)
            norm_factor = ref_norm / astro_value
            astro_factor['scale'] = astro_value
            astro_functype = astro_factor.get('functype', None)
            if is_null(astro_functype):
                astro_prior = None
            else:
                astro_prior = create_prior_functor(astro_factor)
        else:
            sys.stderr.write(
                "Did not recoginize Astro factor %s %s\n" %
                (astro_factor, type(astro_factor)))

        norm_limits = castro_data.getLimits(1e-5)
        # This puts the spectrum in units of the reference spectrum
        # This means that the scan values will be expressed
        # In units of the reference spectra as well
        spec_vals /= norm_factor
        n_scan_pt = 200

        norm_vals = np.ndarray((nmass, n_scan_pt))
        dll_vals = np.ndarray((nmass, n_scan_pt))
        mle_vals = np.ndarray((nmass))
        nll_offsets = np.ndarray((nmass))

        mass_mask = np.ones((nmass), bool)
        # for i, mass in enumerate(masses):
        for i in range(nmass):
            max_ratio = 1. / ((spec_vals[i] / norm_limits).max())
            log_max_ratio = np.log10(max_ratio)
            norm_vals[i][0] = 10**(log_max_ratio - 5)
            norm_vals[i][1:] = np.logspace(log_max_ratio - 4, log_max_ratio + 4,
                                           n_scan_pt - 1)
            test_vals = (np.expand_dims(
                spec_vals[i], 1) * (np.expand_dims(norm_vals[i], 1).T))
            dll_vals[i, 0:] = castro_data(test_vals)
            mle_vals[i] = norm_vals[i][dll_vals[i].argmin()]
            nll_offsets[i] = dll_vals[i].min()
            dll_vals[i] -= nll_offsets[i]

            msk = np.isfinite(dll_vals[i])
            if not msk.any():
                print (
                    "Skipping mass %0.2e for channel %s" %
                    (masses[i], channel))
                mass_mask[i] = False
                continue

            if is_not_null(astro_prior):
                try:
                    lnlfn = castro.LnLFn(norm_vals[i], dll_vals[i], 'dummy')
                    lnlfn_prior = LnLFn_norm_prior(lnlfn, astro_prior)
                    dll_vals[i, 0:] = lnlfn_prior(norm_vals[i])
                    nll_offsets[i] = dll_vals[i].min()
                except ValueError:
                    print (
                        "Skipping mass %0.2e for channel %s" %
                        (masses[i], channel))
                    mass_mask[i] = False
                    dll_vals[i, 0:] = np.nan * np.ones((n_scan_pt))
                    nll_offsets[i] = np.nan

        # Here we convert the normalization values to standard units
        norm_vals *= (ref_inter)
        dm_castro = DMCastroData(norm_vals[mass_mask], dll_vals[mass_mask],
                                 nll_offsets[mass_mask], channel, masses[mass_mask], astro_value,
                                 astro_prior=astro_prior, ref_astro=ref_norm,
                                 ref_inter=ref_inter, decay=is_decay)
        return dm_castro