示例#1
0
文件: error.py 项目: pharmpy/pharmpy
def set_dtbs_error(model):
    """Dynamic transform both sides"""
    theta_as_stdev(model)
    set_weighted_error_model(model)
    stats, y, f = _preparations(model)
    tbs_lambda = Parameter('tbs_lambda', 1)
    tbs_zeta = Parameter('tbs_zeta', 0.001)
    model.parameters.append(tbs_lambda)
    model.parameters.append(tbs_zeta)
    lam = tbs_lambda.symbol
    zeta = tbs_zeta.symbol

    for i, s in enumerate(stats):
        if isinstance(s, Assignment) and s.symbol == sympy.Symbol('W'):
            break

    stats.insert(i + 1, Assignment('W', (f ** zeta) * sympy.Symbol('W')))
    ipred = sympy.Piecewise(
        ((f ** lam - 1) / lam, sympy.And(sympy.Ne(lam, 0), sympy.Ne(f, 0))),
        (sympy.log(f), sympy.And(sympy.Eq(lam, 0), sympy.Ne(f, 0))),
        (-1 / lam, sympy.And(sympy.Eq(lam, 0), sympy.Eq(f, 0))),
        (-1000000000, True),
    )
    stats.insert(i + 2, Assignment('IPRED', ipred))
    yexpr = stats.find_assignment(y.name)
    yexpr.subs({f: sympy.Symbol('IPRED')})

    obs = sympy.Piecewise(
        (sympy.log(y), sympy.Eq(lam, 0)), ((y ** lam - 1) / lam, sympy.Ne(lam, 0))
    )
    model.observation_transformation = obs

    return model
示例#2
0
def test_str(testdata):
    s1 = Assignment(S('KA'), S('X') + S('Y'))
    assert str(s1) == 'KA := X + Y\n'
    s2 = Assignment(S('X2'), sympy.exp('X'))
    a = str(s2).split('\n')
    assert a[0].startswith(' ')
    assert len(a) == 3

    model = Model(testdata / 'nonmem' / 'pheno.mod')
    assert 'THETA(2)' in str(model.statements)
    assert 'THETA(2)' in repr(model.statements)
示例#3
0
def add_parameters_ratio(model, numpar, denompar, source, dest):
    statements = model.statements
    if not statements.find_assignment(
            numpar) or not statements.find_assignment(denompar):
        odes = statements.ode_system
        rate = odes.get_flow(source, dest)
        numer, denom = rate.as_numer_denom()
        par1 = Assignment(numpar, numer)
        par2 = Assignment(denompar, denom)
        if rate != par1.symbol / par2.symbol:
            if not statements.find_assignment(numpar):
                statements.add_before_odes(par1)
            if not statements.find_assignment(denompar):
                statements.add_before_odes(par2)
        odes.add_flow(source, dest, par1.symbol / par2.symbol)
示例#4
0
    def power(cls):
        """Power template (for continuous covariates)."""
        symbol = S('symbol')
        expression = (S('cov') / S('median'))**S('theta')
        template = Assignment(symbol, expression)

        return cls(template)
示例#5
0
def test_proportional_error_model_log(testdata):
    model = Model(testdata / 'nonmem' / 'pheno.mod')
    model.statements[5] = Assignment('Y', 'F')
    proportional_error(model, data_trans='log(Y)')
    model.update_source()
    assert str(model).split('\n')[11] == 'Y = LOG(F) + EPS(1)'
    assert str(model).split('\n')[17] == '$SIGMA  0.09 ; sigma'
示例#6
0
    def linear(cls):
        """Linear continuous template (for continuous covariates)."""
        symbol = S('symbol')
        expression = 1 + S('theta') * (S('cov') - S('median'))
        template = Assignment(symbol, expression)

        return cls(template)
示例#7
0
def test_add_random_variables_and_statements(pheno_path):
    model = Model(pheno_path)

    rvs = model.random_variables
    pset = model.parameters

    eta = RandomVariable.normal('ETA_NEW', 'iiv', 0, S('omega'))
    rvs.append(eta)
    pset.append(Parameter('omega', 0.1))

    eps = RandomVariable.normal('EPS_NEW', 'ruv', 0, S('sigma'))
    rvs.append(eps)
    pset.append(Parameter('sigma', 0.1))

    model.random_variables = rvs
    model.parameters = pset

    sset = model.get_pred_pk_record().statements

    statement_new = Assignment(S('X'), 1 + S(eps.name) + S(eta.name))
    sset.append(statement_new)
    model.get_pred_pk_record().statements = sset

    model.update_source()

    assert str(model.get_pred_pk_record()).endswith('X = 1 + ETA(3) + EPS(2)\n\n')
示例#8
0
    def exponential(cls):
        """Exponential template (for continuous covariates)."""
        symbol = S('symbol')
        expression = exp(S('theta') * (S('cov') - S('median')))
        template = Assignment(symbol, expression)

        return cls(template)
示例#9
0
    def categorical(cls, counts):
        """Linear categorical template (for categorical covariates)."""
        symbol = S('symbol')
        most_common = counts.mode().pop(0)
        categories = counts.unique()
        values = [1]

        if np.isnan(most_common):
            most_common = S('NaN')

        conditions = [Eq(S('cov'), most_common)]

        for i, cat in enumerate(categories):
            if cat != most_common:
                if len(categories) == 2:
                    values += [1 + S('theta')]
                else:
                    values += [1 + S(f'theta{i}')]
                if np.isnan(cat):
                    conditions += [Eq(S('cov'), S('NaN'))]
                else:
                    conditions += [Eq(S('cov'), cat)]

        expression = Piecewise(*zip(values, conditions))

        template = Assignment(symbol, expression)

        return cls(template)
示例#10
0
文件: error.py 项目: pharmpy/pharmpy
def set_weighted_error_model(model):
    """Encode error model with one epsilon and W as weight"""
    stats, y, f = _preparations(model)
    epsilons = model.random_variables.epsilons
    expr = stats.find_assignment(y.name).expression
    ssum = 0
    q = sympy.Q.real(y)  # Dummy predicate
    for term in expr.args:
        eps = [x for x in term.free_symbols if x.name in epsilons.names]
        if len(eps) > 0:
            eps = eps[0]
            remaining = term / eps
            ssum += remaining ** 2
            for symb in remaining.free_symbols:
                q &= sympy.Q.positive(symb)
    w = sympy.sqrt(ssum)
    w = sympy.refine(w, q)

    for i, s in enumerate(stats):
        if isinstance(s, Assignment) and s.symbol == y:
            stats.insert(i, Assignment('W', w))
            break

    stats.reassign(y, f + sympy.Symbol('W') * sympy.Symbol(epsilons[0].name))
    model.remove_unused_parameters_and_rvs()
    return model
示例#11
0
def test_translate_sympy_piecewise(parser, symbol, expression, buf_expected):
    buf_original = '$PRED\nY = THETA(1) + ETA(1) + EPS(1)\n'
    rec = parser.parse(buf_original).records[0]
    s = Assignment(symbol, expression)
    statements = rec.statements
    statements.append(s)
    rec.statements = statements
    assert str(rec) == buf_original.strip() + buf_expected
示例#12
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
示例#13
0
def _add_parameter(model, name, init=0.1):
    pops = model.create_symbol(f'POP_{name}')
    pop_param = Parameter(pops.name, init=init, lower=0)
    model.parameters.add(pop_param)
    symb = model.create_symbol(name)
    ass = Assignment(symb, pop_param.symbol)
    model.statements.insert(0, ass)
    return symb
示例#14
0
def update_lag_time(model, old, new):
    new_dosing = new.find_dosing()
    new_lag_time = new_dosing.lag_time
    old_lag_time = old.find_dosing().lag_time
    if new_lag_time != old_lag_time and new_lag_time != 0:
        ass = Assignment('ALAG1', new_lag_time)
        model.statements.add_before_odes(ass)
        new_dosing.lag_time = ass.symbol
示例#15
0
def test_statements_setter_add_from_sympy(parser, buf_original, sym,
                                          expression, buf_new):
    rec_original = parser.parse(buf_original).records[0]

    assignment = Assignment(sym, expression)
    statements = rec_original.statements
    statements += [assignment]
    rec_original.statements = statements

    assert str(rec_original) == buf_new
示例#16
0
    def boxcox(cls, no_of_etas):
        assignments = ModelStatements()
        for i in range(1, no_of_etas + 1):
            symbol = S(f'etab{i}')
            expression = (exp(S(f'eta{i}')) ** S(f'theta{i}') - 1) / (S(f'theta{i}'))

            assignment = Assignment(symbol, expression)
            assignments.append(assignment)

        return cls('boxcox', assignments, 'lambda')
示例#17
0
def test_find_assignment(testdata):
    model = Model(testdata / 'nonmem' / 'pheno_real.mod')
    statements = model.statements

    assert str(statements.find_assignment('CL').expression) == 'TVCL*exp(ETA(1))'
    assert str(statements.find_assignment('S1').expression) == 'V'
    assert str(statements.find_assignment('EPS(1)', is_symbol=False).symbol) == 'Y'

    statements.append(Assignment(S('CL'), S('TVCL') + S('V')))

    assert str(statements.find_assignment('CL').expression) == 'TVCL + V'
示例#18
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
示例#19
0
def test_proportional_error_model(testdata):
    model = Model(testdata / 'nonmem' / 'pheno.mod')
    model.statements[5] = Assignment('Y', 'F')
    proportional_error(model)
    model.update_source()
    assert str(model).split('\n')[11] == 'Y=F+F*EPS(1)'
    assert str(model).split('\n')[17] == '$SIGMA  0.09 ; sigma'

    model = Model(testdata / 'nonmem' / 'pheno.mod')
    proportional_error(model)
    model.update_source()
    assert str(model).split('\n')[11] == 'Y=F+F*EPS(1)'
    assert str(model).split('\n')[17] == '$SIGMA 0.013241'
示例#20
0
def update_ode_system(model, old, new):
    """Update ODE system

    Handle changes from CompartmentSystem to ExplicitODESystem
    """
    if type(old) == CompartmentalSystem and type(new) == ExplicitODESystem:
        to_des(model, new)
    elif type(old) == CompartmentalSystem and type(new) == CompartmentalSystem:
        # subs = model.control_stream.get_records('SUBROUTINES')[0]
        # old_trans = subs.get_option_startswith('TRANS')
        # conv_advan, new_advan, new_trans = change_advan(model)
        update_lag_time(model, old, new)
        if isinstance(new.find_dosing().dose,
                      Bolus) and 'RATE' in model.dataset.columns:
            df = model.dataset
            df.drop(columns=['RATE'], inplace=True)
            model.dataset = df

        advan, trans = new_advan_trans(model)
        pk_param_conversion(model, advan=advan, trans=trans)
        add_needed_pk_parameters(model, advan, trans)
        update_subroutines_record(model, advan, trans)
        update_model_record(model, advan)

        statements = model.statements
        if isinstance(new.find_dosing().dose,
                      Infusion) and not statements.find_assignment('D1'):
            # Handle direct moving of Infusion dose
            statements.subs({'D2': 'D1'})

        if isinstance(new.find_dosing().dose, Infusion) and isinstance(
                old.find_dosing().dose, Bolus):
            dose = new.find_dosing().dose
            if dose.rate is None:
                # FIXME: Not always D1 here!
                ass = Assignment('D1', dose.duration)
                dose.duration = ass.symbol
            else:
                raise NotImplementedError(
                    "First order infusion rate is not yet supported")
            statements = model.statements
            statements.add_before_odes(ass)
            df = model.dataset
            rate = np.where(df['AMT'] == 0, 0, -2)
            df['RATE'] = rate
            # FIXME: Adding at end for now. Update $INPUT cannot yet handle adding in middle
            # df.insert(list(df.columns).index('AMT') + 1, 'RATE', rate)
            model.dataset = df

    force_des(model, new)
示例#21
0
    def create_effect_statement(self, operation_str, statement_original):
        """Creates statement for addition or multiplication of covariate
        to parameter, e.g. (if parameter is CL and covariate is WGT):

            CL = CLWGT + TVCL*EXP(ETA(1))"""
        operation = self._get_operation(operation_str)

        symbol = statement_original.symbol
        expression = statement_original.symbol

        statement_new = Assignment(symbol,
                                   operation(expression, self.template.symbol))

        return statement_new
示例#22
0
    def apply(self, parameter, covariate, thetas, statistics):
        effect_name = f'{parameter}{covariate}'
        self.template.symbol = S(effect_name)

        self.template.subs(thetas)
        self.template.subs({'cov': covariate})

        template_str = [str(symbol) for symbol in self.template.free_symbols]

        if 'mean' in template_str:
            self.template.subs({'mean': f'{covariate}_MEAN'})
            s = Assignment(S(f'{covariate}_MEAN'),
                           Float(statistics['mean'], 6))
            self.statistic_statements.append(s)
        if 'median' in template_str:
            self.template.subs({'median': f'{covariate}_MEDIAN'})
            s = Assignment(S(f'{covariate}_MEDIAN'),
                           Float(statistics['median'], 6))
            self.statistic_statements.append(s)
        if 'std' in template_str:
            self.template.subs({'std': f'{covariate}_STD'})
            s = Assignment(S(f'{covariate}_STD'), Float(statistics['std'], 6))
            self.statistic_statements.append(s)
示例#23
0
    def john_draper(cls, no_of_etas):
        assignments = ModelStatements()
        for i in range(1, no_of_etas + 1):
            symbol = S(f'etad{i}')

            eta = S(f'eta{i}')
            theta = S(f'theta{i}')

            expression = sign(eta) * (((abs(eta) + 1) ** theta - 1) / theta)

            assignment = Assignment(symbol, expression)
            assignments.append(assignment)

        return cls('johndraper', assignments, 'lambda')
示例#24
0
    def statements(self):
        try:
            return self._statements
        except AttributeError:
            pass

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

        des = self._get_des_record()
        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, des)
            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', S('F')))
            statements += error.statements

        if not hasattr(self, '_parameters'):
            self._read_parameters()

        trans_statements, trans_params = self._create_name_trans(statements)
        for key, value in trans_params.items():
            try:
                self.parameters[key].name = value
                for theta in self.control_stream.get_records('THETA'):
                    theta.update_name_map(trans_params)
                for omega in self.control_stream.get_records('OMEGA'):
                    omega.update_name_map(trans_params)
                for sigma in self.control_stream.get_records('SIGMA'):
                    sigma.update_name_map(trans_params)
            except KeyError:
                self.random_variables.subs({S(key): value})

        statements.subs(trans_statements)

        self._statements = statements
        self._old_statements = statements.copy()
        return statements
示例#25
0
def test_reassign():
    s1 = Assignment(S('G'), sympy.Integer(3))
    s2 = Assignment(S('M'), sympy.Integer(2))
    s3 = Assignment(S('Z'), sympy.Integer(23) + S('M'))
    s4 = Assignment(S('KA'), S('X') + S('Y'))
    s = ModelStatements([s1, s2, s3, s4])
    s.reassign(S('M'), S('x') + S('y'))
    assert s == ModelStatements([s1, Assignment('M', S('x') + S('y')), s3, s4])

    s5 = Assignment('KA', S('KA') + S('Q') + 1)
    s = ModelStatements([s1, s2, s3, s4, s5])
    s.reassign(S('KA'), S('F'))
    assert s == ModelStatements([s1, s2, s3, Assignment('KA', S('F'))])
示例#26
0
    def piecewise_linear(cls):
        """Piecewise linear ("hockey-stick") template (for continuous
        covariates)."""
        symbol = S('symbol')
        values = [
            1 + S('theta1') * (S('cov') - S('median')),
            1 + S('theta2') * (S('cov') - S('median')),
        ]
        conditions = [Le(S('cov'), S('median')), Gt(S('cov'), S('median'))]
        expression = Piecewise((values[0], conditions[0]),
                               (values[1], conditions[1]))

        template = Assignment(symbol, expression)

        return cls(template)
示例#27
0
def define_parameter(model, name, value, synonyms=None):
    """Define a parameter in statments if not defined
    Update if already defined as other value
    return True if new assignment was added
    """
    if synonyms is None:
        synonyms = [name]
    for syn in synonyms:
        ass = model.statements.find_assignment(syn)
        if ass:
            if value != ass.expression and value != symbol(name):
                ass.expression = value
            return False
    new_ass = Assignment(name, value)
    model.statements.add_before_odes(new_ass)
    return True
示例#28
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
示例#29
0
def _create_template(effect, model, covariate):
    """Creates Covariate class objects with effect template."""
    if effect == 'lin':
        return CovariateEffect.linear()
    elif effect == 'cat':
        counts = _count_categorical(model, covariate)
        return CovariateEffect.categorical(counts)
    elif effect == 'piece_lin':
        return CovariateEffect.piecewise_linear()
    elif effect == 'exp':
        return CovariateEffect.exponential()
    elif effect == 'pow':
        return CovariateEffect.power()
    else:
        symbol = S('symbol')
        expression = sympy.sympify(effect)
        return CovariateEffect(Assignment(symbol, expression))
示例#30
0
    def tdist(cls, no_of_etas):
        assignments = ModelStatements()
        for i in range(1, no_of_etas + 1):
            symbol = S(f'etat{i}')

            eta = S(f'eta{i}')
            theta = S(f'theta{i}')

            num_1 = eta ** 2 + 1
            denom_1 = 4 * theta

            num_2 = (5 * eta ** 4) + (16 * eta ** 2 + 3)
            denom_2 = 96 * theta ** 2

            num_3 = (3 * eta ** 6) + (19 * eta ** 4) + (17 * eta ** 2) - 15
            denom_3 = 384 * theta ** 3

            expression = eta * (1 + (num_1 / denom_1) + (num_2 / denom_2) + (num_3 / denom_3))

            assignment = Assignment(symbol, expression)
            assignments.append(assignment)

        return cls('tdist', assignments, 'df')