Exemple #1
0
def test_pset_names():
    p1 = Parameter('Y', 9)
    p2 = Parameter('X', 3)
    p3 = Parameter('Z', 1)
    pset = ParameterSet([p1, p2, p3])
    assert pset.names == ['Y', 'X', 'Z']
    assert pset.symbols == [symbol('Y'), symbol('X'), symbol('Z')]
Exemple #2
0
def test_minimal(datadir):
    path = datadir / 'minimal.mod'
    model = Model(path)
    assert len(model.statements) == 1
    assert model.statements[0].expression == symbol('THETA(1)') + symbol('ETA(1)') + symbol(
        'EPS(1)'
    )
Exemple #3
0
    def merge_normal_distributions(self, fill=0, create_cov_params=False):
        """Merge all normal distributed rvs together into one joint normal

        Set new covariances (and previous 0 covs) to 'fill'
        """
        cov_to_params = dict()
        cov_number = 1
        means, M, names, others = self._calc_covariance_matrix()
        if fill != 0:
            for row, col in itertools.product(range(M.rows), range(M.cols)):
                if M[row, col] == 0:
                    M[row, col] = fill
        elif create_cov_params:
            for row, col in itertools.product(range(M.rows), range(M.cols)):
                if M[row, col] == 0 and row > col:
                    param_1 = M[row, row]
                    param_2 = M[col, col]
                    cov_name = f'COV{cov_number}'
                    cov_number += 1
                    cov_to_params[cov_name] = (str(param_1), str(param_2))

                    M[row, col] = symbol(cov_name)
                    M[col, row] = symbol(cov_name)

        new_rvs = JointNormalSeparate(names, means, M)
        self.__init__(new_rvs + others)
        return cov_to_params
Exemple #4
0
def has_combined_error(model):
    """Check if a model has a combined additive and proportinal error model

    Parameters
    ----------
    model : Model
        The model to check
    """
    y = model.dependent_variable
    expr = model.statements.full_expression_after_odes(y)
    rvs = model.random_variables.epsilons
    rvs_in_y = {
        symbols.symbol(rv.name) for rv in rvs if symbols.symbol(rv.name) in expr.free_symbols
    }
    if len(rvs_in_y) != 2:
        return False
    eps1 = rvs_in_y.pop()
    eps2 = rvs_in_y.pop()
    canc1 = ((expr - eps1) / (eps2 + 1)).simplify()
    canc2 = ((expr - eps2) / (eps1 + 1)).simplify()
    return (
        eps1 not in canc1.free_symbols
        and eps2 not in canc1.free_symbols
        or eps1 not in canc2.free_symbols
        and eps2 not in canc2.free_symbols
    )
Exemple #5
0
 def parameter_translation(self,
                           reverse=False,
                           remove_idempotent=False,
                           as_symbols=False):
     """Get a dict of NONMEM name to Pharmpy parameter name
     i.e. {'THETA(1)': 'TVCL', 'OMEGA(1,1)': 'IVCL'}
     """
     self.parameters
     d = dict()
     for theta_record in self.control_stream.get_records('THETA'):
         for key, value in theta_record.name_map.items():
             nonmem_name = f'THETA({value})'
             d[nonmem_name] = key
     for record in self.control_stream.get_records('OMEGA'):
         for key, value in record.name_map.items():
             nonmem_name = f'OMEGA({value[0]},{value[1]})'
             d[nonmem_name] = key
     for record in self.control_stream.get_records('SIGMA'):
         for key, value in record.name_map.items():
             nonmem_name = f'SIGMA({value[0]},{value[1]})'
             d[nonmem_name] = key
     if remove_idempotent:
         d = {key: val for key, val in d.items() if key != val}
     if reverse:
         d = {val: key for key, val in d.items()}
     if as_symbols:
         d = {
             symbols.symbol(key): symbols.symbol(val)
             for key, val in d.items()
         }
     return d
Exemple #6
0
def _f_link_assignment(model, compartment):
    f = symbol('F')
    fexpr = compartment.amount
    pkrec = model.control_stream.get_records('PK')[0]
    if pkrec.statements.find_assignment('S1'):
        fexpr = fexpr / symbol('S1')
    ass = Assignment(f, fexpr)
    return ass
Exemple #7
0
def test_copy(datadir):
    path = datadir / 'minimal.mod'
    model = Model(path)
    copy = model.copy()
    assert id(model) != id(copy)
    assert model.statements[0].expression == symbol('THETA(1)') + symbol('ETA(1)') + symbol(
        'EPS(1)'
    )
Exemple #8
0
def test_rv():
    omega1 = symbol('OMEGA(1,1)')
    x = stats.Normal('ETA(1)', 0, sympy.sqrt(omega1))
    rvs = RandomVariables([x])
    assert len(rvs) == 1
    retrieved = rvs['ETA(1)']
    assert retrieved.name == 'ETA(1)'
    assert retrieved.pspace.distribution.mean == 0
    assert rvs.free_symbols == {symbol('ETA(1)'), omega1}
Exemple #9
0
def test_validate_parameters():
    a, b, c, d = (symbol('a'), symbol('b'), symbol('c'), symbol('d'))
    rvs = JointNormalSeparate(['ETA(1)', 'ETA(2)'], [0, 0], [[a, b], [b, c]])
    rvs = RandomVariables(rvs)
    rvs.add(stats.Normal('ETA(3)', 0.5, d))
    params = {'a': 2, 'b': 0.1, 'c': 1, 'd': 23}
    assert rvs.validate_parameters(params)
    params2 = {'a': 2, 'b': 2, 'c': 1, 'd': 23}
    assert not rvs.validate_parameters(params2)
Exemple #10
0
 def __init__(self, src, **kwargs):
     super().__init__()
     parser = NMTranParser()
     self.source = src
     if not self.source.filename_extension:
         self.source.filename_extension = '.ctl'
     self._name = self.source.path.stem
     self.control_stream = parser.parse(src.code)
     self._initial_individual_estimates_updated = False
     self._updated_etas_file = None
     self._dataset_updated = False
     self._modelfit_results = None
     self.dependent_variable_symbol = symbols.symbol('Y')
     self.individual_prediction_symbol = symbols.symbol('CIPREDI')
Exemple #11
0
def _preparations(model):
    stats = model.statements
    y = model.dependent_variable
    f = model.statements.find_assignment(y.name).expression
    for eps in model.random_variables.epsilons:
        f = f.subs({symbols.symbol(eps.name): 0})
    return stats, y, f
Exemple #12
0
 def free_symbols(self):
     symbs = set()
     for rv in self:
         free = {s for s in rv.pspace.free_symbols if s.name != rv.name}
         symbs |= free
         symbs.add(symbol(rv.name))
     return symbs
Exemple #13
0
def test_pset_getitem():
    p = Parameter('Y', 9)
    pset = Parameters((p, ))
    assert len(pset) == 1
    assert pset['Y'] is p

    p2 = Parameter('Z', 5)
    pset.append(p2)

    assert len(pset) == 2

    # Check that the parameter set keeps the insertion order upon iteration
    for i, param in enumerate(pset):
        if i == 0:
            assert param is p
        else:
            assert param is p2

    assert pset[symbol('Z')] == p2

    p3 = Parameter('K', 19)
    with pytest.raises(KeyError):
        pset[p3]

    assert len(pset[[p]]) == 1
Exemple #14
0
def test_all_parameters():
    omega1 = symbol('OMEGA(1,1)')
    eta1 = stats.Normal('ETA(1)', 0, sympy.sqrt(omega1))
    omega2 = symbol('OMEGA(2,2)')
    eta2 = stats.Normal('ETA(2)', 0, sympy.sqrt(omega2))
    sigma = symbol('SIGMA(1,1)')
    eps = stats.Normal('EPS(1)', 0, sympy.sqrt(sigma))

    rvs = RandomVariables([eta1, eta2, eps])

    assert len(rvs) == 3

    params = rvs.all_parameters()

    assert len(params) == 3
    assert params == ['OMEGA(1,1)', 'OMEGA(2,2)', 'SIGMA(1,1)']
Exemple #15
0
def test_has_same_order():
    omega1 = symbol('OMEGA(1,1)')
    eta1 = stats.Normal('ETA(1)', 0, sympy.sqrt(omega1))
    omega2 = symbol('OMEGA(2,2)')
    eta2 = stats.Normal('ETA(2)', 0, sympy.sqrt(omega2))
    omega3 = symbol('OMEGA(1,1)')
    eta3 = stats.Normal('ETA(3)', 0, sympy.sqrt(omega3))

    rvs_full = RandomVariables([eta1, eta2, eta3])
    assert rvs_full.are_consecutive(rvs_full)

    rvs_sub = RandomVariables([eta1, eta2])
    assert rvs_full.are_consecutive(rvs_sub)

    rvs_rev = RandomVariables([eta3, eta2, eta1])
    assert not rvs_full.are_consecutive(rvs_rev)
Exemple #16
0
def _calculate_covariate_baselines(model, covariates):
    exprs = [
        ass.expression.args[0][0] for ass in model.statements
        if symbols.symbol('FREMTYPE') in ass.free_symbols
        and ass.symbol.name == 'IPRED'
    ]
    exprs = [
        expr.subs(dict(model.modelfit_results.parameter_estimates)).subs(
            model.parameters.inits) for expr in exprs
    ]
    new = []
    for expr in exprs:
        for symb in expr.free_symbols:
            stat = model.statements.find_assignment(symb.name)
            if stat is not None:
                expr = expr.subs(symb, stat.expression)
        new.append(expr)
    exprs = new

    def fn(row):
        return [np.float64(expr.subs(dict(row))) for expr in exprs]

    df = model.modelfit_results.individual_estimates.apply(
        fn, axis=1, result_type='expand')
    df.columns = covariates
    return df
Exemple #17
0
 def free_symbols(self):
     free = {symbols.symbol('t')}
     for (_, _, rate) in self._g.edges.data('rate'):
         free |= rate.free_symbols
     for node in self._g.nodes:
         free |= node.free_symbols
     return free
Exemple #18
0
 def from_odes(self, ode_system):
     """Set statements of record given an eplicit ode system"""
     odes = ode_system.odes[:
                            -1]  # Skip last ode as it is for the output compartment
     functions = [ode.lhs.args[0] for ode in odes]
     function_map = {
         f: symbols.symbol(f'A({i + 1})')
         for i, f in enumerate(functions)
     }
     statements = []
     for i, ode in enumerate(odes):
         # For now Piecewise signals zero-order infusions, which are handled with parameters
         ode = ode.replace(sympy.Piecewise, lambda a1, a2: 0)
         symbol = symbols.symbol(f'DADT({i + 1})')
         expression = ode.rhs.subs(function_map)
         statements.append(Assignment(symbol, expression))
     self.statements = statements
Exemple #19
0
def add_rate_assignment_if_missing(model,
                                   name,
                                   value,
                                   source,
                                   dest,
                                   synonyms=None):
    added = define_parameter(model, name, value, synonyms=synonyms)
    if added:
        model.statements.ode_system.add_flow(source, dest, symbol(name))
Exemple #20
0
def has_proportional_error(model):
    """Check if a model has a proportional error model

    Parameters
    ----------
    model : Model
        The model to check
    """
    y = model.dependent_variable
    expr = model.statements.full_expression_after_odes(y)
    rvs = model.random_variables.epsilons
    rvs_in_y = {
        symbols.symbol(rv.name) for rv in rvs if symbols.symbol(rv.name) in expr.free_symbols
    }
    if len(rvs_in_y) != 1:
        return False
    eps = rvs_in_y.pop()
    return eps not in (expr / (1 + eps)).simplify().free_symbols
Exemple #21
0
def update_abbr_record(model, rv_trans):
    trans = dict()
    if not rv_trans:
        return trans
    for rv in model.random_variables:
        rv_symb = symbol(rv.name)
        abbr_pattern = re.match(r'ETA_(\w+)', rv.name)
        if abbr_pattern and '_' not in abbr_pattern.group(1):
            parameter = abbr_pattern.group(1)
            nonmem_name = rv_trans[rv_symb]
            abbr_name = f'ETA({parameter})'
            trans[rv_symb] = symbol(abbr_name)
            abbr_record = f'$ABBR REPLACE {abbr_name}={nonmem_name}\n'
            model.control_stream.insert_record(abbr_record)
        elif not re.match(r'(ETA|EPS)\([0-9]\)', rv.name):
            warnings.warn(
                f'Not valid format of name {rv.name}, falling back to NONMEM name. If custom name, '
                f'follow the format "ETA_X" to get "ETA(X)" in $ABBR.')
    return trans
Exemple #22
0
def force_des(model, odes):
    """Switch to $DES if necessary"""
    if isinstance(odes, ExplicitODESystem):
        return

    amounts = {sympy.Function(amt.name)(symbol('t')) for amt in odes.amounts}
    if odes.atoms(sympy.Function) & amounts:
        modeling.explicit_odes(model)
        new = model.statements.ode_system
        to_des(model, new)
Exemple #23
0
 def expression(self, expr, parameters):
     """Replace all symbols with same names as rvs with the corresponding rvs
     or indexed variables for joint distributions and replace parameter values
     """
     d = dict()
     i = 1
     for rvs, dist in self.distributions():
         if len(rvs) > 1:
             joint_name = f'__J{i}'
             mu = dist.mu.subs(parameters)
             sigma = dist.sigma.subs(parameters)
             x = stats.Normal(joint_name, mu, sigma)
             d.update({symbol(rv.name): x[n] for n, rv in enumerate(rvs)})
             i += 1
         else:
             mean = dist.mean.subs(parameters)
             std = dist.std.subs(parameters)
             d[symbol(rvs[0].name)] = stats.Normal(rvs[0].name, mean, std)
     return expr.subs(d)
Exemple #24
0
 def __init__(self, symbol, expression):
     """symbol can be either string or sympy symbol
     symbol can be a string and a real symbol will be created
     """
     try:
         symbol.is_Symbol
         self.symbol = symbol
     except AttributeError:
         self.symbol = symbols.symbol(symbol)
     self.expression = sympy.sympify(expression)
Exemple #25
0
 def subs(self, substitutions):
     d = {
         sympy.Function(str(key))(symbols.symbol('t')): value
         for key, value in substitutions.items()
     }
     self.odes = [ode.subs(d) for ode in self.odes]
     self.ics = {
         key.subs(d): value.subs(d)
         for key, value in self.ics.items()
     }
Exemple #26
0
    def statements(self):
        try:
            return self._statements
        except AttributeError:
            pass

        rec = self.get_pred_pk_record()
        statements = rec.statements

        error = self._get_error_record()
        if error:
            sub = self.control_stream.get_records('SUBROUTINES')[0]
            advan = sub.get_option_startswith('ADVAN')
            trans = sub.get_option_startswith('TRANS')
            if not trans:
                trans = 'TRANS1'
            comp = compartmental_model(self, advan, trans)
            if comp is not None:
                cm, link = comp
                statements += [cm, link]
            else:
                statements.append(
                    ODESystem())  # FIXME: Placeholder for ODE-system
                # FIXME: Dummy link statement
                statements.append(Assignment('F', symbols.symbol('F')))
            statements += error.statements

        if pharmpy.plugins.nonmem.conf.parameter_names == 'comment':
            if not hasattr(self, '_parameters'):
                self._read_parameters()
            trans = self.parameter_translation(remove_idempotent=True,
                                               as_symbols=True)
            parameter_symbols = {symb for _, symb in trans.items()}
            clashing_symbols = parameter_symbols & statements.free_symbols
            if clashing_symbols:
                warnings.warn(
                    f'The parameter names {clashing_symbols} are also names of variables '
                    f'in the model code. Falling back to the NONMEM default parameter '
                    f'names for these.')
                rev_trans = {val: key for key, val in trans.items()}
                trans = {
                    nm_symb: symb
                    for nm_symb, symb in trans.items()
                    if symb not in clashing_symbols
                }
                for symb in clashing_symbols:
                    self.parameters[symb.name].name = rev_trans[symb].name
            statements.subs(trans)

        self._statements = statements
        self._old_statements = statements.copy()
        return statements
Exemple #27
0
def force_des(model, odes):
    """Switch to $DES if necessary"""
    if isinstance(odes, ExplicitODESystem):
        return

    # Import put here to avoid circular import in Python 3.6
    import pharmpy.modeling as modeling

    amounts = {sympy.Function(amt.name)(symbol('t')) for amt in odes.amounts}
    if odes.atoms(sympy.Function) & amounts:
        modeling.explicit_odes(model)
        new = model.statements.ode_system
        to_des(model, new)
Exemple #28
0
def calculate_results_using_cov_sampling(
    frem_model,
    continuous,
    categorical,
    cov_model=None,
    force_posdef_samples=500,
    force_posdef_covmatrix=False,
    samples=1000,
    rescale=True,
    seed=None,
):
    """Calculate the FREM results using covariance matrix for uncertainty

    :param cov_model: Take the parameter uncertainty covariance matrix from this model
                      instead of the frem model.
    :param force_posdef_samples: The number of sampling tries before stopping to use
                                 rejection sampling and instead starting to shift values so
                                 that the frem matrix becomes positive definite. Set to 0 to
                                 always force positive definiteness.
    :param force_posdef_covmatrix: Set to force the covariance matrix of the frem movdel or
                                   the cov model to be positive definite. Default is to raise
                                   in this case.
    :param samples: The number of parameter vector samples to use.
    """
    if cov_model is not None:
        uncertainty_results = cov_model.modelfit_results
    else:
        uncertainty_results = frem_model.modelfit_results

    _, dist = frem_model.random_variables.iiv.distributions()[-1]
    sigma_symb = dist.sigma

    parameters = [
        s for s in frem_model.modelfit_results.parameter_estimates.index
        if symbols.symbol(s) in sigma_symb.free_symbols
    ]
    parvecs = sample_from_covariance_matrix(
        frem_model,
        modelfit_results=uncertainty_results,
        force_posdef_samples=force_posdef_samples,
        force_posdef_covmatrix=force_posdef_covmatrix,
        parameters=parameters,
        n=samples,
        seed=seed,
    )
    res = calculate_results_from_samples(frem_model,
                                         continuous,
                                         categorical,
                                         parvecs,
                                         rescale=rescale)
    return res
Exemple #29
0
def test_initialization(name, init, lower, upper, fix):
    param = Parameter(name, init, lower, upper, fix)
    assert param.name == name
    assert param.symbol == symbol(name)
    assert param.init == init
    if lower is not None:
        assert param.lower == lower
    else:
        assert param.lower == -sympy.oo
    if upper is not None:
        assert param.upper == upper
    else:
        assert param.upper == sympy.oo
    assert param.fix == bool(fix)
Exemple #30
0
 def rv_translation(self,
                    reverse=False,
                    remove_idempotent=False,
                    as_symbols=False):
     self.random_variables
     d = dict()
     for record in self.control_stream.get_records('OMEGA'):
         for key, value in record.eta_map.items():
             nonmem_name = f'ETA({value})'
             d[nonmem_name] = key
     for record in self.control_stream.get_records('SIGMA'):
         for key, value in record.eta_map.items():
             nonmem_name = f'EPS({value})'
             d[nonmem_name] = key
     if remove_idempotent:
         d = {key: val for key, val in d.items() if key != val}
     if reverse:
         d = {val: key for key, val in d.items()}
     if as_symbols:
         d = {
             symbols.symbol(key): symbols.symbol(val)
             for key, val in d.items()
         }
     return d