diff --git a/imagine/carrier_mapper.py b/imagine/carrier_mapper.py index 633f866158ac742cf754a2c43edcb07e3a094f3c..55e632a5333cee1f697bbc0c27e549b8ee8acd90 100644 --- a/imagine/carrier_mapper.py +++ b/imagine/carrier_mapper.py @@ -1,2 +1,33 @@ # -*- coding: utf-8 -*- +import numpy as np + + +def carrier_mapper(x, a=-np.inf, m=0, b=np.inf): + """ + Maps x from [-inf, inf] into the interval [a, b], where x=0 -> m + """ + + if a == -np.inf and b == np.inf and m == 0: + return x + + x = np.float(x) + a = np.float(a) + b = np.float(b) + if m is None: + if a == -np.inf and b == np.inf: + m = 0 + else: + m = a + (b-a)/2. + else: + m = np.float(m) + + # map x from [-inf, inf] to [0, 1] + y = np.arctan(x)/np.pi + 0.5 + # compute where m would lie in [0, 1] + n = (m - a)/(b - a) + # strech y, such that x=0 -> n + y = y**np.emath.logn(0.5, n) + # strech y to the interval [a,b] + y = y*(b-a) + a + return y diff --git a/imagine/likelihoods/__init__.py b/imagine/likelihoods/__init__.py index 633f866158ac742cf754a2c43edcb07e3a094f3c..9636f33bdfc4b1f2133f3fa1719a9fc7661e8021 100644 --- a/imagine/likelihoods/__init__.py +++ b/imagine/likelihoods/__init__.py @@ -1,2 +1,3 @@ # -*- coding: utf-8 -*- +from likelihood import Likelihood diff --git a/imagine/likelihoods/likelihood.py b/imagine/likelihoods/likelihood.py new file mode 100644 index 0000000000000000000000000000000000000000..5e4ae1325436201993cdd253e224a086274a6c86 --- /dev/null +++ b/imagine/likelihoods/likelihood.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- + +import abc + +from keepers import Loggable + + +class Likelihood(Loggable, object): + @abc.abstractmethod + def __call__(self, observables): + raise NotImplementedError diff --git a/imagine/likelihoods/sum_likelihood.py b/imagine/likelihoods/sum_likelihood.py new file mode 100644 index 0000000000000000000000000000000000000000..60f570e56dd4f704ebb7f7a924eb2969acacc6e9 --- /dev/null +++ b/imagine/likelihoods/sum_likelihood.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- + +from likelihood import Likelihood + + +class SumLikelihood(Likelihood): + def __init__(self, likelihoods): + self.likelihoods = [] + for likelihood in likelihoods: + assert isinstance(likelihood, Likelihood) + self.likelihoods += [likelihood] + + def __call__(self, observables): + likelihood = 0 + for current_likelihood in self.likelihoods: + likelihood += current_likelihood(observables) + + return likelihood diff --git a/imagine/observers/__init__.py b/imagine/observers/__init__.py index 633f866158ac742cf754a2c43edcb07e3a094f3c..aefc4c5dd63a2b45ea58d31cc1d6eb373ed85d95 100644 --- a/imagine/observers/__init__.py +++ b/imagine/observers/__init__.py @@ -1,2 +1,3 @@ # -*- coding: utf-8 -*- +from observer import Observer diff --git a/imagine/observers/observer.py b/imagine/observers/observer.py new file mode 100644 index 0000000000000000000000000000000000000000..657cd23dbce50d814c4c0ff8a419bb4a0b82d221 --- /dev/null +++ b/imagine/observers/observer.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + + +class Observer(object): + pass diff --git a/imagine/pipeline.py b/imagine/pipeline.py index a3b12ee0712800233bae660aecdfa12c4c575288..b1f815a5ceea62868c2a2cc781c5fc33d6e8a721 100644 --- a/imagine/pipeline.py +++ b/imagine/pipeline.py @@ -8,15 +8,18 @@ from likelihoods import Likelihood from observers import Observer from priors import Prior +from carrier_mapper import carrier_mapper + class Pipeline(Loggable, object): - def __init__(self, observer, likelihood, prior, - parameters=[], ensemble_size=1): + def __init__(self, observer, likelihood, prior, ensemble_size=1, + active_parameters=[], parameter_mapping={}): self.logger.debug("Setting up pipeline.") self.observer = observer self.likelihood = likelihood self.prior = prior - self.parameters = parameters + self.active_parameters = active_parameters + self.parameter_mapping = parameter_mapping self.ensemble_size = ensemble_size @property @@ -51,23 +54,24 @@ class Pipeline(Loggable, object): "prior must be an instance of prior-class.") @property - def parameters(self): - return self._parameters + def parameter_mapping(self): + return self._parameter_mapping - @parameters.setter - def parameters(self, parameters): + @parameter_mapping.setter + def parameter_mapping(self, parameters): """ - parameters is either a list of the parameter-names, or a list of lists - containing [parameter-name, min, max, mean] + The parameter-mapping must be a dictionary with + key: parameter-name + value: [min, mean, max] """ - new_parameters = [] + new_mapping = {} for p in parameters: - if isinstance(p, list): - new_parameters += [[str(p[0]), p[1], p[2], p[3]]] - else: - new_parameters += [[str(p), None, None, None]] - self.logger.debug("Setting parameters to %s." % str(new_parameters)) - self._parameters = new_parameters + new_key = str(p[0]) + new_value = [p[1], p[2], p[3]] + new_mapping[new_key] = new_value + self.logger.debug("Setting parameter_mapping %s to %s." % + (new_key, new_mapping[new_key])) + self._parameter_mapping = new_mapping @property def ensemble_size(self): @@ -82,52 +86,19 @@ class Pipeline(Loggable, object): self.logger.debug("Setting ensemble size to %i." % ensemble_size) self._ensemble_size = ensemble_size - @staticmethod - def carrier_mapper(x, a=-np.inf, b=np.inf, m=0): - """ - Maps x from [-inf, inf] into the interval [a, b], where x=0 -> m - """ - - if a == -np.inf and b == np.inf and m == 0: - return x - - x = np.float(x) - a = np.float(a) - b = np.float(b) - if m is None: - if a == -np.inf and b == np.inf: - m = 0 + def _map_parameters(self, parameter_list): + parameter_dict = {} + for i, name in enumerate(self.active_parameters): + if name in self.parameter_mapping: + mapping = self.parameter_mapping[name] + mapped_parameter = carrier_mapper(parameter_list[i], + a=mapping[1], + m=mapping[2], + b=mapping[3]) else: - m = a + (b-a)/2. - else: - m = np.float(m) - - # map x from [-inf, inf] to [0, 1] - y = np.arctan(x)/np.pi + 0.5 - # compute where m would lie in [0, 1] - n = (m - a)/(b - a) - # strech y, such that x=0 -> n - y = y**np.emath.logn(0.5, n) - # strech y to the interval [a,b] - y = y*(b-a) + a - return y + mapped_parameter = np.float(parameter_list[i]) + parameter_dict[name] = mapped_parameter + return parameter_dict def __call__(self, parameter_list): - parameter_dict = {} - for (i, p) in enumerate(self.parameters): - parameter_dict[p[0]] = self.carrier_mapper(parameter_list[i], - a=p[1], - b=p[2], - m=p[3]) - - - - - - - - - - - - + mapped_parameters = self._map_parameters(parameter_list) diff --git a/imagine/priors/__init__.py b/imagine/priors/__init__.py index 633f866158ac742cf754a2c43edcb07e3a094f3c..88db6327264d9b32e6bbdebbc240520d3b2605d1 100644 --- a/imagine/priors/__init__.py +++ b/imagine/priors/__init__.py @@ -1,2 +1,3 @@ # -*- coding: utf-8 -*- +from prior import Prior diff --git a/imagine/priors/prior.py b/imagine/priors/prior.py new file mode 100644 index 0000000000000000000000000000000000000000..84dbbed4d85379305f81c40c33853edc82a5da34 --- /dev/null +++ b/imagine/priors/prior.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- + +import abc + +from keepers import Loggable + + +class Prior(Loggable, object): + @abc.abstractmethod + def __call__(self, parameters): + raise NotImplemented diff --git a/imagine/priors/sum_prior.py b/imagine/priors/sum_prior.py new file mode 100644 index 0000000000000000000000000000000000000000..f703eef5b5c922b0e36ae44371f8ab193b44bc13 --- /dev/null +++ b/imagine/priors/sum_prior.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- + +from prior import Prior + + +class SumPrior(Prior): + def __init__(self, priors): + self.priors = [] + for prior in priors: + assert isinstance(prior, Prior) + self.priors += [prior] + + def __call__(self, parameters): + prior = 0 + for current_prior in self.priors: + prior += current_prior(parameters) + return prior