Source code for petab.sampling

"""Functions related to parameter sampling"""

from typing import Sequence, Tuple

import numpy as np
import pandas as pd

from . import parameters
from .C import *  # noqa: F403

__all__ = ["sample_from_prior", "sample_parameter_startpoints"]


[docs] def sample_from_prior( prior: Tuple[str, list, str, list], n_starts: int ) -> np.array: """Creates samples for one parameter based on prior Arguments: prior: A tuple as obtained from :func:`petab.parameter.get_priors_from_df` n_starts: Number of samples Returns: Array with sampled values """ # unpack info p_type, p_params, scaling, bounds = prior # define a function to rescale the sampled points to parameter scale def scale(x): if scaling == LIN: return x if scaling == LOG: return np.log(x) if scaling == LOG10: return np.log10(x) raise NotImplementedError( f"Parameter priors on the parameter scale {scaling} are " "currently not implemented." ) def clip_to_bounds(x: np.array): """Clip values in array x to bounds""" return np.maximum(np.minimum(scale(bounds[1]), x), scale(bounds[0])) # define lambda functions for each parameter if p_type == UNIFORM: sp = scale( (p_params[1] - p_params[0]) * np.random.random((n_starts,)) + p_params[0] ) elif p_type == PARAMETER_SCALE_UNIFORM: sp = (p_params[1] - p_params[0]) * np.random.random( (n_starts,) ) + p_params[0] elif p_type == NORMAL: sp = scale( np.random.normal( loc=p_params[0], scale=p_params[1], size=(n_starts,) ) ) elif p_type == LOG_NORMAL: sp = scale( np.exp( np.random.normal( loc=p_params[0], scale=p_params[1], size=(n_starts,) ) ) ) elif p_type == PARAMETER_SCALE_NORMAL: sp = np.random.normal( loc=p_params[0], scale=p_params[1], size=(n_starts,) ) elif p_type == LAPLACE: sp = scale( np.random.laplace( loc=p_params[0], scale=p_params[1], size=(n_starts,) ) ) elif p_type == LOG_LAPLACE: sp = scale( np.exp( np.random.laplace( loc=p_params[0], scale=p_params[1], size=(n_starts,) ) ) ) elif p_type == PARAMETER_SCALE_LAPLACE: sp = np.random.laplace( loc=p_params[0], scale=p_params[1], size=(n_starts,) ) else: raise NotImplementedError( f"Parameter priors of type {prior[0]} are not implemented." ) return clip_to_bounds(sp)
[docs] def sample_parameter_startpoints( parameter_df: pd.DataFrame, n_starts: int = 100, seed: int = None, parameter_ids: Sequence[str] = None, ) -> np.array: """Create :class:`numpy.array` with starting points for an optimization Arguments: parameter_df: PEtab parameter DataFrame n_starts: Number of points to be sampled seed: Random number generator seed (see :func:`numpy.random.seed`) parameter_ids: A sequence of parameter IDs for which to sample starting points. For subsetting or reordering the parameters. Defaults to all estimated parameters. Returns: Array of sampled starting points with dimensions `n_startpoints` x `n_optimization_parameters` """ if seed is not None: np.random.seed(seed) # get types and parameters of priors from dataframe prior_list = parameters.get_priors_from_df( parameter_df, mode=INITIALIZATION, parameter_ids=parameter_ids ) startpoints = [sample_from_prior(prior, n_starts) for prior in prior_list] return np.array(startpoints).T