def individual_parameter_statistics(model, expr): """Calculate statistics for an individual parameter The parameter does not have to be in the model, but can be an expression of other parameters from the model. Does not support parameters that relies on the solution of the ODE-system """ expr = sympy.sympify(expr) pe = dict(model.modelfit_results.parameter_estimates) full_expr = model.statements.full_expression_from_odes(expr) expr = model.random_variables.expression(full_expr.subs(pe), pe) mean = np.float64(sympy.stats.E(expr)) variance = np.float64(sympy.stats.variance(expr)) parameters = sample_from_covariance_matrix(model, n=100) samples = [] with warnings.catch_warnings(): warnings.filterwarnings('ignore') for _, row in parameters.iterrows(): expr = model.random_variables.expression(full_expr.subs(dict(row)), dict(row)) samples.extend( next(sympy.stats.sample(expr, library='numpy', size=10)).tolist()) stderr = pd.Series(samples).std() res = {'mean': mean, 'variance': variance, 'stderr': stderr} return pd.Series(res)
def model_sample(self, args): model = args.model from pharmpy.parameter_sampling import sample_from_covariance_matrix samples = sample_from_covariance_matrix(model, n=args.samples) for row, params in samples.iterrows(): model.parameters = params model.name = f'sample_{row + 1}' model.write()
def test_sample_from_covariance_matrix(testdata): model = Model(testdata / 'nonmem' / 'pheno_real.mod') np.random.seed(318) samples = sample_from_covariance_matrix(model, n=3) correct = pd.DataFrame({ 'THETA(1)': [0.004965, 0.004811, 0.004631], 'THETA(2)': [0.979979, 1.042210, 0.962791], 'THETA(3)': [0.007825, -0.069350, 0.052367], 'OMEGA(1,1)': [0.019811, 0.059127, 0.030619], 'OMEGA(2,2)': [0.025248, 0.029088, 0.019749], 'SIGMA(1,1)': [0.014700, 0.014347, 0.011470], }) pd.testing.assert_frame_equal(samples, correct, atol=1e-6) # Make cov matrix non-posdef model.modelfit_results.covariance_matrix['THETA(1)']['THETA(1)'] = -1 with pytest.warns(UserWarning): sample_from_covariance_matrix(model, n=1, force_posdef_covmatrix=True)
def test_sample_from_covariance_matrix(testdata): model = Model(testdata / 'nonmem' / 'pheno_real.mod') np.random.seed(318) samples = sample_from_covariance_matrix(model, n=3) correct = pd.DataFrame({ 'THETA(1)': [0.004965, 0.004811, 0.004631], 'THETA(2)': [0.979979, 1.042210, 0.962791], 'THETA(3)': [0.007825, -0.069350, 0.052367], 'OMEGA(1,1)': [0.019811, 0.059127, 0.030619], 'OMEGA(2,2)': [0.025248, 0.029088, 0.019749], 'SIGMA(1,1)': [0.014700, 0.014347, 0.011470] }) pd.testing.assert_frame_equal(samples, correct, check_less_precise=True)
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
def test_sample_from_covariance_matrix(testdata): model = Model(testdata / 'nonmem' / 'pheno_real.mod') rng = np.random.default_rng(318) samples = sample_from_covariance_matrix(model, n=3, seed=rng) correct = pd.DataFrame({ 'THETA(1)': [0.004489330033579095, 0.004866193232279955, 0.004619661658761273], 'THETA(2)': [0.9720563045663096, 1.0217868717352445, 0.9662036500731115], 'THETA(3)': [0.19927467608338267, 0.237140948854298, 0.1979609848931148], 'OMEGA(1,1)': [0.012012933626520568, 0.03859989956899462, 0.03228178862778379], 'OMEGA(2,2)': [0.03718187653238525, 0.036766142234483934, 0.02433717922068797], 'SIGMA(1,1)': [0.00962550646345379, 0.01311348785596405, 0.014054031573722888], }) pd.testing.assert_frame_equal(samples, correct, atol=1e-6) # Make cov matrix non-posdef model.modelfit_results.covariance_matrix['THETA(1)']['THETA(1)'] = -1 with pytest.warns(UserWarning): sample_from_covariance_matrix(model, n=1, force_posdef_covmatrix=True)
def individual_parameter_statistics(self, exprs, seed=None): """Calculate statistics for individual parameters exprs - is one string or an iterable of strings The parameter does not have to be in the model, but can be an expression of other parameters from the model. Does not support parameters that relies on the solution of the ODE-system """ if isinstance(exprs, str) or isinstance(exprs, sympy.Basic): exprs = [_split_equation(exprs)] else: exprs = [_split_equation(expr) for expr in exprs] model = self.model dataset = model.dataset cols = set(dataset.columns) i = 0 table = pd.DataFrame(columns=['parameter', 'covariates', 'mean', 'variance', 'stderr']) for name, expr in exprs: full_expr = model.statements.full_expression_from_odes(expr) covariates = {symb.name for symb in full_expr.free_symbols if symb.name in cols} if not covariates: cases = {'median': dict()} else: q5 = dataset[{'ID'} | covariates].groupby('ID').median().quantile(0.05) q95 = dataset[{'ID'} | covariates].groupby('ID').median().quantile(0.95) median = dataset[{'ID'} | covariates].groupby('ID').median().median() cases = {'p5': dict(q5), 'median': dict(median), 'p95': dict(q95)} df = pd.DataFrame(index=list(cases.keys()), columns=['mean', 'variance', 'stderr']) for case, cov_values in cases.items(): pe = dict(model.modelfit_results.parameter_estimates) cov_expr = full_expr.subs(cov_values) expr = cov_expr.subs(pe) samples = model.random_variables.sample( expr, parameters=pe, samples=1000000, seed=seed ) mean = np.mean(samples) variance = np.var(samples) parameters = sample_from_covariance_matrix( model, n=100, force_posdef_covmatrix=True, seed=seed, ) samples = [] with warnings.catch_warnings(): warnings.filterwarnings('ignore') for _, row in parameters.iterrows(): batch = model.random_variables.sample( cov_expr.subs(dict(row)), parameters=dict(row), samples=10, seed=seed, ) samples.extend(list(batch)) stderr = pd.Series(samples).std() df.loc[case] = [mean, variance, stderr] df.index.name = 'covariates' df.reset_index(inplace=True) if not name: name = f'unknown{i}' i += 1 df['parameter'] = name table = pd.concat([table, df]) table.set_index(['parameter', 'covariates'], inplace=True) return table