Esempio n. 1
0
        def get_phi(self, params):
            """Return wideband timing-model prior."""

            # get DMEFAC- and DMEQUAD-adjusted DMX errors
            dme = self.get_dme(params)

            # initialize the timing-model "infinite" prior
            phi = KernelMatrix(1e40 * np.ones(self._npars, "d"))

            # fill the DMX slots with weighted errors
            for index, which in zip(self._dmindex, self._dmwhich):
                phi.set(1.0 / np.sum(1.0 / dme[which] ** 2), index)

            return phi
Esempio n. 2
0
    class BasisGP(signal_base.Signal):
        signal_type = "basis"
        signal_name = name
        signal_id = name

        basis_combine = combine

        def __init__(self, psr):
            super(BasisGP, self).__init__(psr)
            self.name = self.psrname + "_" + self.signal_id
            self._do_selection(psr, priorFunction, basisFunction, coefficients, selection)

        def _do_selection(self, psr, priorfn, basisfn, coefficients, selection):
            sel = selection(psr)

            self._keys = sorted(sel.masks.keys())
            self._masks = [sel.masks[key] for key in self._keys]
            self._prior, self._bases = {}, {}
            self._params, self._coefficients = {}, {}

            for key, mask in zip(self._keys, self._masks):
                pnames = [psr.name, name, key]
                pname = "_".join([n for n in pnames if n])

                self._prior[key] = priorfn(pname, psr=psr)
                self._bases[key] = basisfn(pname, psr=psr)

                for par in itertools.chain(self._prior[key]._params.values(), self._bases[key]._params.values()):
                    self._params[par.name] = par

            if coefficients:
                # we can only create GPCoefficients parameters if the basis
                # can be constructed with default arguments
                # (and does not change size)
                self._construct_basis()

                for key in self._keys:
                    pname = "_".join([n for n in [psr.name, name, key] if n])

                    chain = itertools.chain(self._prior[key]._params.values(), self._bases[key]._params.values())
                    priorargs = {par.name: self._params[par.name] for par in chain}

                    logprior = parameter.Function(functools.partial(self._get_coefficient_logprior, key), **priorargs)

                    size = self._slices[key].stop - self._slices[key].start

                    cpar = parameter.GPCoefficients(logprior=logprior, size=size)(pname + "_coefficients")

                    self._coefficients[key] = cpar
                    self._params[cpar.name] = cpar

        @property
        def basis_params(self):
            """Get any varying basis parameters."""
            ret = []
            for basis in self._bases.values():
                ret.extend([pp.name for pp in basis.params])
            return ret

        @signal_base.cache_call("basis_params")
        def _construct_basis(self, params={}):
            basis, self._labels = {}, {}
            for key, mask in zip(self._keys, self._masks):
                basis[key], self._labels[key] = self._bases[key](params=params, mask=mask)

            nc = sum(F.shape[1] for F in basis.values())
            self._basis = np.zeros((len(self._masks[0]), nc))

            # TODO: should this be defined here? it will cache phi
            self._phi = KernelMatrix(nc)

            self._slices = {}
            nctot = 0
            for key, mask in zip(self._keys, self._masks):
                Fmat = basis[key]
                nn = Fmat.shape[1]
                self._basis[mask, nctot : nn + nctot] = Fmat
                self._slices.update({key: slice(nctot, nn + nctot)})
                nctot += nn

        # this class does different things (and gets different method
        # definitions) if the user wants it to model GP coefficients
        # (e.g., for a hierarchical likelihood) or if they do not
        if coefficients:

            def _get_coefficient_logprior(self, key, c, **params):
                self._construct_basis(params)

                phi = self._prior[key](self._labels[key], params=params)

                if phi.ndim == 1:
                    return -0.5 * np.sum(c * c / phi) - 0.5 * np.sum(np.log(phi)) - 0.5 * len(phi) * np.log(2 * np.pi)
                    # note: (2*pi)^(n/2) is not in signal_base likelihood
                else:
                    # TO DO: this code could be embedded in KernelMatrix
                    phiinv, logdet = KernelMatrix(phi).inv(logdet=True)
                    return -0.5 * np.dot(c, np.dot(phiinv, c)) - 0.5 * logdet - 0.5 * phi.shape[0] * np.log(2 * np.pi)

            # MV: could assign this to a data member at initialization
            @property
            def delay_params(self):
                return [pp.name for pp in self.params if "_coefficients" in pp.name]

            @signal_base.cache_call(["basis_params", "delay_params"])
            def get_delay(self, params={}):
                self._construct_basis(params)

                c = np.zeros(self._basis.shape[1])
                for key, slc in self._slices.items():
                    p = self._coefficients[key]
                    c[slc] = params[p.name] if p.name in params else p.value

                return np.dot(self._basis, c)

            def get_basis(self, params={}):
                return None

            def get_phi(self, params):
                return None

            def get_phiinv(self, params):
                return None

        else:

            @property
            def delay_params(self):
                return []

            def get_delay(self, params={}):
                return 0

            def get_basis(self, params={}):
                self._construct_basis(params)

                return self._basis

            def get_phi(self, params):
                self._construct_basis(params)

                for key, slc in self._slices.items():
                    phislc = self._prior[key](self._labels[key], params=params)
                    self._phi = self._phi.set(phislc, slc)
                return self._phi

            def get_phiinv(self, params):
                return self.get_phi(params).inv()