Source code for mosfit.modules.parameters.parameter

"""Definitions for the `Parameter` class."""
import numpy as np

from collections import OrderedDict
from mosfit.modules.module import Module
from mosfit.utils import listify

# Important: Only define one ``Module`` class per file.


[docs]class Parameter(Module): """Model parameter that can either be free or fixed.""" def __init__(self, **kwargs): """Initialize module.""" super(Parameter, self).__init__(**kwargs) self._fixed = kwargs.get('fixed', False) self._fixed_by_user = False self._max_value = kwargs.get('max_value', None) self._min_value = kwargs.get('min_value', None) if (self._min_value is not None and self._max_value is not None and self._min_value == self._max_value): self._printer.message('min_max_same', [self._name], warning=True) self._value = self._min_value self._min_value, self._max_value = None, None self._fixed = True self._fixed_by_user = True if self._min_value is None or self._max_value is None: self._fixed = True self._fixed_by_user = True self._value = kwargs.get('value', None) self._log = kwargs.get('log', False) self._latex = kwargs.get('latex', self._name) self._derived_keys = listify(kwargs.get('derived_keys', [])) + [ 'reference_' + self._name] if (self._log and self._min_value is not None and self._max_value is not None): if self._min_value <= 0.0 or self._max_value <= 0.0: raise ValueError( 'Parameter with log prior cannot have range values <= 0!') self._min_value = np.log(self._min_value) self._max_value = np.log(self._max_value) self._reference_value = None self._clipped_warning = False
[docs] def fix_value(self, value): """Fix value of parameter.""" self._max_value = None self._min_value = None self._value = value self._fixed = True self._fixed_by_user = True
[docs] def is_log(self): """Return if `Parameter`'s value is stored as log10(value).""" return self._log
[docs] def latex(self): """Return the LaTeX representation of the parameter.""" return self._latex
[docs] def lnprior_pdf(self, x): """Evaluate natural log of probability density function.""" return 0.0
[docs] def prior_icdf(self, u): """Evaluate inverse cumulative density function.""" return u
[docs] def value(self, f): """Return the value of the parameter in parameter's units.""" if np.any(np.isnan(f)): raise ValueError('NaN fraction passed to parameter.') value = np.clip(f * (self._max_value - self._min_value) + self._min_value, self._min_value, self._max_value) if self._log: value = np.exp(value) return value
[docs] def fraction(self, value, clip=True): """Return fraction given a parameter's value.""" if self._log: value = np.log(value) f = (value - self._min_value) / (self._max_value - self._min_value) if clip: of = f f = np.clip(f, 0.0, 1.0) if f != of and not self._clipped_warning: self._clipped_warning = True self._printer.message( 'parameter_clipped', [self._name], warning=True) return f
[docs] def get_derived_keys(self): """Return list of keys that should be generated by this parameter.""" return self._derived_keys
[docs] def process(self, **kwargs): """Process module. Initialize a parameter based upon either a fixed value or a distribution, if one is defined. """ if self._fixed: # If this parameter is not free and is already set, then skip if self._name in kwargs: return {} value = self._value else: value = self.value(kwargs['fraction']) output = OrderedDict([[self._name, value]]) if self._reference_value is not None: output['reference_' + self._name] = self._reference_value return output
[docs] def receive_requests(self, **requests): """Receive requests from other ``Module`` objects.""" # Get the first value in the requests dictionary. req_keys = list(requests.keys()) if req_keys: self._reference_value = requests.get(req_keys[0], None)