def update(self, parameters, first_theta): """From a ParameterSet update the THETAs in this record Currently only updating initial estimates """ i = first_theta for theta in self.root.all('theta'): name = f'THETA({i})' param = parameters[name] new_init = param.init if float(str(theta.init)) != new_init: theta.init.tokens[0].value = str(new_init) fix = bool(theta.find('FIX')) if fix != param.fix: if param.fix: space = AttrToken('WS', ' ') fix_token = AttrToken('FIX', 'FIX') theta.children.extend([space, fix_token]) else: remove_token_and_space(theta, 'FIX') n = self._multiple(theta) i += n
def update(self, parameters, first_omega, previous_size): """From a ParameterSet update the OMEGAs in this record returns the next omega number """ block = self.root.find('block') bare_block = self.root.find('bare_block') if not (block or bare_block): size = 1 i = first_omega new_nodes = [] for node in self.root.children: if node.rule != 'diag_item': new_nodes.append(node) else: sd = bool(node.find('SD')) fix = bool(node.find('FIX')) n = node.n.INT if node.find('n') else 1 new_inits = [] new_fix = [] for j in range(i, i + n): name = f'{self.name}({j},{j})' if not sd: value = float(parameters[name].init) else: value = parameters[name].init ** 0.5 new_inits.append(value) new_fix.append(parameters[name].fix) if n == 1 or (new_inits.count(new_inits[0]) == len(new_inits) and new_fix.count(new_fix[0]) == len(new_fix)): # All equal? if float(str(node.init)) != new_inits[0]: node.init.tokens[0].value = str(new_inits[0]) if new_fix[0] != fix: if new_fix[0]: insert_before_or_at_end(node, 'RPAR', [AttrToken('WS', ' '), AttrToken('FIX', 'FIX')]) else: remove_token_and_space(node, 'FIX') new_nodes.append(node) else: # Need to split xn new_children = [] for child in node.children: if child.rule != 'n': new_children.append(child) node.children = new_children for j, init in enumerate(new_inits): new_node = AttrTree.transform(node) if float(str(new_node.init)) != init: new_node.init.tokens[0].value = str(init) if new_fix[j] != fix: insert_before_or_at_end(node, 'RPAR', [AttrToken('WS', ' '), AttrToken('FIX', 'FIX')]) else: remove_token_and_space(node, 'FIX') new_nodes.append(new_node) if j != len(new_inits) - 1: # Not the last new_nodes.append(AttrTree.create('ws', {'WS': ' '})) i += n self.root.children = new_nodes next_omega = i else: same = bool(self.root.find('same')) if same: return first_omega + previous_size, previous_size size = self.root.block.size.INT fix, sd, corr, cholesky = self._block_flags() row = first_omega col = first_omega inits = [] new_fix = [] for row in range(first_omega, first_omega + size): for col in range(first_omega, row + 1): name = f'{self.name}({row},{col})' inits.append(parameters[name].init) new_fix.append(parameters[name].fix) if len(set(new_fix)) != 1: # Not all true or all false raise ValueError('Cannot only fix some parameters in block') A = pharmpy.math.flattened_to_symmetric(inits) if corr: for i in range(size): for j in range(size): if i != j: A[i, j] = A[i, j] / (math.sqrt(A[i, i]) * math.sqrt(A[j, j])) if sd: np.fill_diagonal(A, A.diagonal()**0.5) if cholesky: A = np.linalg.cholesky(A) inds = np.tril_indices_from(A) array = list(A[inds]) i = 0 new_nodes = [] for node in self.root.children: if node.rule != 'omega': new_nodes.append(node) else: n = node.n.INT if node.find('n') else 1 if array[i:i+n].count(array[i]) == n: # All equal? if float(str(node.init)) != array[i]: node.init.tokens[0].value = str(array[i]) new_nodes.append(node) else: # Need to split xn new_children = [] for child in node.children: if child.rule not in ['n', 'LPAR', 'RPAR']: new_children.append(child) node.children = new_children for j, init in enumerate(array[i:i+n]): new_node = AttrTree.transform(node) if float(str(new_node.init)) != init: new_node.init.tokens[0].value = str(init) new_nodes.append(new_node) if j != n - 1: # Not the last new_nodes.append(AttrTree.create('ws', {'WS': ' '})) i += n self.root.children = new_nodes if new_fix[0] != fix: if new_fix[0]: insert_after(self.root, 'block', [AttrToken('WS', ' '), AttrToken('FIX', 'FIX')]) else: remove_token_and_space(self.root, 'FIX', recursive=True) next_omega = first_omega + size return next_omega, size