예제 #1
0
    def __init__(self, cyclic_domain=False, **params):
        # _domain is a bounds instance used to apply cyclic conditions; this is
        # applied first, before any bounds specified in the initialization
        # are used
        self._domain = boundaries.Bounds(self._domainbounds[0],
                                         self._domainbounds[1],
                                         cyclic=cyclic_domain)

        for p, bnds in params.items():
            if bnds is None:
                bnds = self._domain
            elif isinstance(bnds, boundaries.Bounds):
                # convert to radians
                bnds._min = bnds._min.__class__(bnds._min)
                bnds._max = bnds._max.__class__(bnds._max)
            else:
                # create a Bounds instance from the given tuple
                bnds = boundaries.Bounds(bnds[0], bnds[1])
            # check that the bounds are in the domain
            if bnds.min < self._domain.min or bnds.max > self._domain.max:
                raise ValueError("bounds must be in [{x},{y}); "
                                 "got [{a},{b})".format(x=self._domain.min,
                                                        y=self._domain.max,
                                                        a=bnds.min,
                                                        b=bnds.max))

            # update
            params[p] = bnds
        super(UniformAngle, self).__init__(**params)
예제 #2
0
파일: bounded.py 프로젝트: OliverEdy/pycbc
 def __init__(self, **params):
     # convert input bounds to Bounds class, if necessary
     for param,bnds in params.items():
         if bnds is None:
             params[param] = boundaries.Bounds()
         elif not isinstance(bnds, boundaries.Bounds):
             params[param] = boundaries.Bounds(bnds[0], bnds[1])
         # warn the user about reflected boundaries
         if isinstance(bnds, boundaries.Bounds) and (
                 bnds.min.name == 'reflected' or
                 bnds.max.name == 'reflected'):
             warnings.warn("Param {} has one or more ".format(param) +
                           "reflected boundaries. Reflected boundaries "
                           "can cause issues when used in an MCMC.")
     self._bounds = params
     self._params = sorted(list(params.keys()))
예제 #3
0
 def __init__(self, **params):
     super(SinAngle, self).__init__(**params)
     # replace the domain
     self._domain = boundaries.Bounds(self._domainbounds[0],
                                      self._domainbounds[1],
                                      btype_min='closed',
                                      btype_max='closed',
                                      cyclic=False)
     self._lognorm = -sum([numpy.log(
         abs(self._func(bnd[1]) - self._func(bnd[0]))) \
         for bnd in self._bounds.values()])
     self._norm = numpy.exp(self._lognorm)
예제 #4
0
파일: qnm.py 프로젝트: josh-willis/pycbc
 def __init__(self, f0=None, tau=None, final_mass=None, final_spin=None,
              rdfreq='f0', damping_time='tau', norm_tolerance=1e-3,
              norm_seed=0):
     if f0 is None:
         raise ValueError("must provide a range for f0")
     if tau is None:
         raise ValueError("must provide a range for tau")
     self.rdfreq = rdfreq
     self.damping_time = damping_time
     parent_args = {rdfreq: f0, damping_time: tau}
     super(UniformF0Tau, self).__init__(**parent_args)
     if final_mass is None:
         final_mass = (0., numpy.inf)
     if final_spin is None:
         final_spin = (-0.996, 0.996)
     self.final_mass_bounds = boundaries.Bounds(
         min_bound=final_mass[0], max_bound=final_mass[1])
     self.final_spin_bounds = boundaries.Bounds(
         min_bound=final_spin[0], max_bound=final_spin[1])
     # Re-normalize to account for cuts: we'll do this by just sampling
     # a large number of spaces f0 taus, and seeing how many are in the
     # desired range.
     # perseve the current random state
     s = numpy.random.get_state()
     numpy.random.seed(norm_seed)
     nsamples = int(1./norm_tolerance**2)
     draws = super(UniformF0Tau, self).rvs(size=nsamples)
     # reset the random state
     numpy.random.set_state(s)
     num_in = self._constraints(draws).sum()
     # if num_in is 0, than the requested tolerance is too large
     if num_in == 0:
         raise ValueError("the normalization is < then the norm_tolerance; "
                          "try again with a smaller nrom_tolerance")
     self._lognorm += numpy.log(num_in) - numpy.log(nsamples)
     self._norm = numpy.exp(self._lognorm)
예제 #5
0
def get_param_bounds_from_config(cp, section, tag, param):
    """Gets bounds for the given parameter from a section in a config file.

    Minimum and maximum values for bounds are specified by adding
    `min-{param}` and `max-{param}` options, where `{param}` is the name of
    the parameter. The types of boundary (open, closed, or reflected) to create
    may also be specified by adding options `btype-min-{param}` and
    `btype-max-{param}`. Cyclic conditions can be adding option
    `cyclic-{param}`. If no `btype` arguments are provided, the
    left bound will be closed and the right open.

    For example, the following will create right-open bounds for parameter
    `foo`:

    .. code-block:: ini

        [{section}-{tag}]
        min-foo = -1
        max-foo = 1

    This would make the boundaries cyclic:

    .. code-block:: ini

        [{section}-{tag}]
        min-foo = -1
        max-foo = 1
        cyclic-foo =

    For more details on boundary types and their meaning, see
    `boundaries.Bounds`.

    If the parameter is not found in the section will just return None (in
    this case, all `btype` and `cyclic` arguments are ignored for that
    parameter).  If bounds are specified, both a minimum and maximum must be
    provided, else a Value or Type Error will be raised.

    Parameters
    ----------
    cp : ConfigParser instance
        The config file.
    section : str
        The name of the section.
    tag : str
        Any tag in the section name. The full section name searched for in
        the config file is `{section}(-{tag})`.
    param : str
        The name of the parameter to retrieve bounds for.

    Returns
    -------
    bounds : {Bounds instance | None}
        If bounds were provided, a `boundaries.Bounds` instance
        representing the bounds. Otherwise, `None`.
    """
    try:
        minbnd = float(cp.get_opt_tag(section, 'min-' + param, tag))
    except Error:
        minbnd = None
    try:
        maxbnd = float(cp.get_opt_tag(section, 'max-' + param, tag))
    except Error:
        maxbnd = None
    if minbnd is None and maxbnd is None:
        bnds = None
    elif minbnd is None or maxbnd is None:
        raise ValueError("if specifying bounds for %s, " % (param) +
                         "you must provide both a minimum and a maximum")
    else:
        bndargs = {'min_bound': minbnd, 'max_bound': maxbnd}
        # try to get  any other conditions, if provided
        try:
            minbtype = cp.get_opt_tag(section, 'btype-min-{}'.format(param),
                                      tag)
        except Error:
            minbtype = 'closed'
        try:
            maxbtype = cp.get_opt_tag(section, 'btype-max-{}'.format(param),
                                      tag)
        except Error:
            maxbtype = 'open'
        bndargs.update({'btype_min': minbtype, 'btype_max': maxbtype})
        cyclic = cp.has_option_tag(section, 'cyclic-{}'.format(param), tag)
        bndargs.update({'cyclic': cyclic})
        bnds = boundaries.Bounds(**bndargs)
    return bnds
예제 #6
0
    def from_config(cls, cp, section, tag):
        """Loads a proposal from a config file.

        The section that is read should have the format ``[{section}-{tag}]``,
        where ``{tag}`` is a :py:const:`pycbc.VARARGS_DELIM` separated list
        of the parameters to create the jump proposal for.

        Options that are read:

        * name : str
            Required. Must match the name of the proposal.
        * adaptation-duration : int
            Required. Sets the ``adaptation_duration``.
        * min-{param} : float
        * max-{param} : float
            Required. Bounds must be provided for every parameter. These are
            used to determine the prior widths.
        * adaptation-decay : int
            Optional. Sets the ``adaptation_decay``. If not provided, will use
            the class's default.
        * start-iteration : int
            Optional. Sets the ``start_iteration``.If not provided, will use
            the class's default.
        * target-rate : float
            Optional. Sets the ``target_rate``. If not provided, will use
            the class's default.

        .. note::
           The min and max parameter bounds are only used for setting the width
           of the covariance of the proposal; they are not used as bounds on
           the proposal itself. In other words, it is possible to get proposals
           outside of the given min and max values.

        Example::

            [jump_proposal-mchirp+q]
            name = adaptive_normal
            adaptation-duration = 1000
            min-q = 1
            max-q = 8
            min-mchirp = 20
            max-mchirp = 80

        Parameters
        ----------
        cp : WorkflowConfigParser instance
            Config file to read from.
        section : str
            The name of the section to look in.
        tag : str
            :py:const:`pycbc.VARARGS_DELIM` separated list of parameter names
            to create proposals for.

        Returns
        -------
        :py:class:`epsie.proposals.AdaptiveNormal`:
            An adaptive normal proposal for use with ``epsie`` samplers.
        """
        # check that the name matches
        assert cp.get_opt_tag(
            section, "name",
            tag) == cls.name, ("name in specified section must match mine")
        params = tag.split(VARARGS_DELIM)
        # get options
        readsection = '-'.join([section, tag])
        opts = {
            opt: cp.get(readsection, opt)
            for opt in cp.options(readsection) if opt != 'name'
        }
        adaptation_duration = opts.pop('adaptation-duration', None)
        if adaptation_duration is None:
            raise ValueError("No adaptation-duration specified")
        adaptation_duration = int(adaptation_duration)
        # get the bounds
        prior_widths = {}
        for param in params:
            minbound = opts.pop('min-{}'.format(param), None)
            if minbound is None:
                raise ValueError("Must provide a minimum bound for {p}."
                                 "Syntax is min-{p} = val".format(p=param))
            maxbound = opts.pop('max-{}'.format(param), None)
            if maxbound is None:
                raise ValueError("Must provide a maximum bound for {p}."
                                 "Syntax is max-{p} = val".format(p=param))
            prior_widths[param] = boundaries.Bounds(float(minbound),
                                                    float(maxbound))
        # optional args
        optional_args = {}
        adaptation_decay = opts.pop('adaptation-decay', None)
        if adaptation_decay is not None:
            optional_args['adaptation_decay'] = int(adaptation_decay)
        start_iteration = opts.pop('start-iteration', None)
        if start_iteration is not None:
            optional_args['start_iteration'] = int(start_iteration)
        target_rate = opts.pop('target_rate', None)
        if target_rate is not None:
            optional_args['target_rate'] = float(target_rate)
        # check that there are no unrecognized options
        if opts:
            raise ValueError('unrecognized options {} in section {}'.format(
                ', '.join(opts.keys()), readsection))
        return cls(params, prior_widths, adaptation_duration, **optional_args)