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)
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()))
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)
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)
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
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)