Exemple #1
0
def create_rv_block(model, list_of_rvs=None):
    """
    Creates a full or partial block structure of etas. The etas must be IIVs and cannot
    be fixed. Initial estimates for covariance between the etas is dependent on whether
    the model has results from a previous results. In that case, the correlation will
    be calculated from individual estimates, otherwise correlation will be set to 10%.

    Parameters
    ----------
    model : Model
        Pharmpy model to create block effect on.
    list_of_rvs : list
        List of etas to create a block structure from. If None, all etas that are IIVs and
        non-fixed will be used (full block). None is default.
    """
    rvs = model.random_variables
    if list_of_rvs is None:
        iiv_rvs = model.random_variables.iiv
        nonfix = RandomVariables()
        for rv in iiv_rvs:
            for name in iiv_rvs.parameter_names:
                if model.parameters[name].fix:
                    break
            else:
                nonfix.append(rv)
        list_of_rvs = nonfix.names
    else:
        for name in list_of_rvs:
            if name in rvs and rvs[name].level == 'IOV':
                raise ValueError(
                    f'{name} describes IOV: Joining IOV random variables is currently not supported'
                )
    if len(list_of_rvs) == 1:
        raise ValueError('At least two random variables are needed')

    sset = model.statements
    paramnames = []
    for rv in list_of_rvs:
        statements = sset.find_assignment(rv, is_symbol=False, last=False)
        parameter_names = '_'.join([s.symbol.name for s in statements])
        paramnames.append(parameter_names)

    cov_to_params = rvs.join(list_of_rvs,
                             name_template='IIV_{}_IIV_{}',
                             param_names=paramnames)

    pset = model.parameters
    for cov_name, param_names in cov_to_params.items():
        parent_params = (pset[param_names[0]], pset[param_names[1]])
        covariance_init = _choose_param_init(model, rvs, parent_params)
        param_new = Parameter(cov_name, covariance_init)
        pset.append(param_new)

    return model
Exemple #2
0
    def random_variables(self, start_omega, previous_cov=None):
        """Get a RandomVariableSet for this omega record

        start_omega - the first omega in this record
        previous_cov - the matrix of the previous omega block
        """
        same = bool(self.root.find('same'))
        if not hasattr(self, 'name_map') and not same:
            if isinstance(previous_cov, sympy.Symbol):
                prev_size = 1
            elif previous_cov is not None:
                prev_size = len(previous_cov)
            else:
                prev_size = None
            self.parameters(start_omega, prev_size)
        if hasattr(self, 'name_map'):
            rev_map = {value: key for key, value in self.name_map.items()}
        next_cov = None  # The cov matrix if a block
        block = self.root.find('block')
        bare_block = self.root.find('bare_block')
        zero_fix = []
        etas = []
        if not (block or bare_block):
            rvs = RandomVariables()
            i = start_omega
            numetas = len(self.root.all('diag_item'))
            for node in self.root.all('diag_item'):
                init = node.init.NUMERIC
                fixed = bool(node.find('FIX'))
                name = self._rv_name(i)
                if not (init == 0 and fixed):  # 0 FIX are not RVs
                    eta = RandomVariable.normal(name, 'iiv', 0, symbol(rev_map[(i, i)]))
                    rvs.append(eta)
                    etas.append(eta.name)
                else:
                    zero_fix.append(name)
                    etas.append(name)
                i += 1
        else:
            if bare_block:
                numetas = previous_cov.rows
            else:
                numetas = self.root.block.size.INT
            params, _, _ = self.parameters(
                start_omega, previous_cov.rows if hasattr(previous_cov, 'rows') else None
            )
            all_zero_fix = True
            for param in params:
                if not (param.init == 0 and param.fix):
                    all_zero_fix = False
            if all_zero_fix and len(params) > 0 or (previous_cov == 'ZERO' and same):
                names = [self._rv_name(i) for i in range(start_omega, start_omega + numetas)]
                self.eta_map = {eta: start_omega + i for i, eta in enumerate(names)}
                return RandomVariables(), start_omega + numetas, 'ZERO', names
            if numetas > 1:
                names = [self._rv_name(i) for i in range(start_omega, start_omega + numetas)]
                means = [0] * numetas
                if same:
                    rvs = RandomVariable.joint_normal(names, 'iiv', means, previous_cov)
                    etas = [rv.name for rv in rvs]
                    next_cov = previous_cov
                else:
                    cov = sympy.zeros(numetas)
                    for row in range(numetas):
                        for col in range(row + 1):
                            cov[row, col] = symbol(rev_map[(start_omega + row, start_omega + col)])
                            if row != col:
                                cov[col, row] = cov[row, col]
                    next_cov = cov
                    rvs = RandomVariable.joint_normal(names, 'iiv', means, cov)
                    etas = [rv.name for rv in rvs]
            else:
                rvs = RandomVariables()
                name = self._rv_name(start_omega)
                if same:
                    sym = previous_cov
                else:
                    sym = symbol(rev_map[(start_omega, start_omega)])
                eta = RandomVariable.normal(name, 'iiv', 0, sym)
                next_cov = sym
                rvs.append(eta)
                etas.append(eta.name)

        if self.name == 'OMEGA':
            if same:
                level = 'IOV'
            else:
                level = 'IIV'
        else:
            level = 'RUV'
        for rv in rvs:
            rv.level = level
        self.eta_map = {eta: start_omega + i for i, eta in enumerate(etas)}
        return rvs, start_omega + numetas, next_cov, zero_fix