def test_choose_param_init(pheno_path, testdata): model = Model(pheno_path) params = (model.parameters['OMEGA(1,1)'], model.parameters['OMEGA(2,2)']) rvs = RandomVariables(model.random_variables.etas) init = _choose_param_init(model, rvs, params) assert init == 0.0118179 model = Model(pheno_path) model.source.path = testdata # Path where there is no .ext-file init = _choose_param_init(model, rvs, params) assert init == 0.0031045 model = Model(pheno_path) omega1 = S('OMEGA(3,3)') x = stats.Normal('ETA(3)', 0, sympy.sqrt(omega1)) x.variability_level = VariabilityLevel.IIV rvs.add(x) ie = model.modelfit_results.individual_estimates ie['ETA(3)'] = ie['ETA(1)'] model.modelfit_results = ModelfitResults(individual_estimates=ie) init = _choose_param_init(model, rvs, params) assert init == 0.0118179
def test_extract_from_block(): etas = JointNormalSeparate(['ETA(1)', 'ETA(2)'], [0, 0], [[3, 0.25], [0.25, 1]]) for rv in etas: rv.variability_level = VariabilityLevel.IIV rvs = RandomVariables(etas) eta3 = stats.Normal('ETA(3)', 0.5, 2) eta3.variability_level = VariabilityLevel.IIV rvs.add(eta3) dists = rvs.distributions() assert len(dists) == 2 rvs.extract_from_block(etas[0]) dists = rvs.distributions() assert len(dists) == 3 assert rvs[0].name == 'ETA(1)' assert rvs[2].name == 'ETA(3)'
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_full = model.random_variables rvs_block = _get_rvs(model, list_of_rvs) if list_of_rvs is not None: for rv in rvs_block: if isinstance(rv.pspace.distribution, MultivariateNormalDistribution): if rvs_full.get_rvs_from_same_dist(rv): rv_extracted = rvs_full.extract_from_block(rv) rvs_block.discard(rv) rvs_block.add(rv_extracted) pset = _merge_rvs(model, rvs_block) rvs_new = RandomVariables() are_consecutive = rvs_full.are_consecutive(rvs_block) for rv in rvs_full: if rv.name not in [rv.name for rv in rvs_block.etas]: rvs_new.add(rv) elif are_consecutive: rvs_new.add(rvs_block[rv.name]) if not are_consecutive: {rvs_new.add(rv) for rv in rvs_block} # Add new block last model.random_variables = rvs_new model.parameters = pset return model
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_sigma - the matrix of the previous omega block """ next_cov = None # The cov matrix if a block block = self.root.find('block') bare_block = self.root.find('bare_block') zero_fix = [] 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 = sympy.stats.Normal(name, 0, sympy.sqrt( sympy.Symbol(f'{self.name}({i},{i})'))) rvs.add(eta) else: zero_fix.append(name) i += 1 else: if bare_block: numetas = previous_cov.rows else: numetas = self.root.block.size.INT same = bool(self.root.find('same')) 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)] 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 = JointNormalSeparate(names, means, previous_cov) next_cov = previous_cov else: cov = sympy.zeros(numetas) for row in range(numetas): for col in range(row + 1): cov[row, col] = sympy.Symbol( f'{self.name}({start_omega + row},{start_omega + col})') if row != col: cov[col, row] = cov[row, col] next_cov = cov rvs = JointNormalSeparate(names, means, cov) else: rvs = RandomVariables() name = self._rv_name(start_omega) if same: symbol = previous_cov else: symbol = sympy.Symbol(f'{self.name}({start_omega},{start_omega})') eta = sympy.stats.Normal(name, 0, sympy.sqrt(symbol)) next_cov = symbol rvs.add(eta) if self.name == 'OMEGA': level = VariabilityLevel.IIV else: level = VariabilityLevel.RUV for rv in rvs: rv.variability_level = level return rvs, start_omega + numetas, next_cov, zero_fix
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 = sympy.stats.Normal( name, 0, sympy.sqrt(symbol(rev_map[(i, i)]))) rvs.add(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 = JointNormalSeparate(names, 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 = JointNormalSeparate(names, 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 = sympy.stats.Normal(name, 0, sympy.sqrt(sym)) next_cov = sym rvs.add(eta) etas.append(eta.name) if self.name == 'OMEGA': if same: level = VariabilityLevel.IOV else: level = VariabilityLevel.IIV else: level = VariabilityLevel.RUV for rv in rvs: rv.variability_level = level self.eta_map = {eta: start_omega + i for i, eta in enumerate(etas)} return rvs, start_omega + numetas, next_cov, zero_fix