def test_add_random_variables(pheno_path, rv_new, buf_new): model = Model(pheno_path) rvs = model.random_variables pset = model.parameters eta = sympy.stats.Normal('eta_new', 0, sympy.sqrt(S(rv_new.name))) eta.variability_level = VariabilityLevel.IIV rvs.add(eta) pset.add(rv_new) model.random_variables = rvs model.parameters = pset model.update_source() rec_ref = ( f'$OMEGA DIAGONAL(2)\n' f' 0.0309626 ; IVCL\n' f' 0.031128 ; IVV\n\n' f'{buf_new} ; omega\n' ) rec_mod = '' for rec in model.control_stream.get_records('OMEGA'): rec_mod += str(rec) assert rec_mod == rec_ref rv = model.random_variables['eta_new'] assert rv.pspace.distribution.mean == 0 assert rv.pspace.distribution.std ** 2 == rv_new.symbol
def test_combined_error_model(testdata): model = Model(testdata / 'nonmem' / 'pheno.mod') combined_error(model) model.update_source() assert str(model).split('\n')[11] == 'Y = EPS(1)*F + EPS(2) + F' assert str(model).split('\n')[17] == '$SIGMA 0.09 ; sigma_prop' assert str(model).split('\n')[18] == '$SIGMA 11.2225 ; sigma_add'
def test_add_parameters_and_statements(pheno_path, param_new, statement_new, buf_new): model = Model(pheno_path) pset = model.parameters pset.append(param_new) model.parameters = pset sset = model.statements # Insert new statement before ODE system. new_sset = ModelStatements() for s in sset: if isinstance(s, ODESystem): new_sset.append(statement_new) new_sset.append(s) model.statements = new_sset model.update_source() rec = ( f'$PK\n' f'IF(AMT.GT.0) BTIME=TIME\n' f'TAD=TIME-BTIME\n' f'TVCL=THETA(1)*WGT\n' f'TVV=THETA(2)*WGT\n' f'IF(APGR.LT.5) TVV=TVV*(1+THETA(3))\n' f'CL=TVCL*EXP(ETA(1))\n' f'V=TVV*EXP(ETA(2))\n' f'S1=V\n' f'{buf_new}\n\n' ) assert str(model.get_pred_pk_record()) == rec
def test_add_parameters(pheno_path, param_new, init_expected, buf_new): model = Model(pheno_path) pset = model.parameters assert len(pset) == 6 pset.append(param_new) model.parameters = pset model.update_source() assert len(pset) == 7 assert model.parameters[param_new.name].init == init_expected parser = NMTranParser() stream = parser.parse(str(model)) assert str(model.control_stream) == str(stream) rec_ref = ( f'$THETA (0,0.00469307) ; PTVCL\n' f'$THETA (0,1.00916) ; PTVV\n' f'$THETA (-.99,.1)\n' f'{buf_new}\n' ) rec_mod = '' for rec in model.control_stream.get_records('THETA'): rec_mod += str(rec) assert rec_ref == rec_mod
def test_remove_iov(testdata): model = Model(testdata / 'nonmem/pheno_block.mod') model_str = str(model) model_with_iov = re.sub( r'\$OMEGA 0.031128 ; IVV\n\$OMEGA 0.1', r'$OMEGA BLOCK(1)\n0.1\n$OMEGA BLOCK(1) SAME\n', model_str, ) model.control_stream = NMTranParser().parse(model_with_iov) remove_iov(model) model.update_source() assert (str(model.get_pred_pk_record()) == '$PK\n' 'CL=THETA(1)*EXP(ETA(1))\n' 'V = THETA(2)\n' 'S1 = ETA(2) + ETA(3) + V\n\n') rec_omega = ''.join( str(rec) for rec in model.control_stream.get_records('OMEGA')) assert (rec_omega == '$OMEGA 0.0309626 ; IVCL\n' '$OMEGA BLOCK(2)\n' '0.0309626\n' '0.0005 0.031128\n') model = Model(testdata / 'nonmem/pheno_block.mod') with pytest.warns(UserWarning): remove_iov(model)
def test_michaelis_menten_elimination(testdata): model = Model(testdata / 'nonmem' / 'pheno.mod') michaelis_menten_elimination(model) model.update_source() correct = """$PROBLEM PHENOBARB SIMPLE MODEL $DATA pheno.dta IGNORE=@ $INPUT ID TIME AMT WGT APGR DV $SUBROUTINE ADVAN6 TOL=3 $MODEL COMPARTMENT=(CENTRAL DEFDOSE) $PK CLMM = THETA(3) KM = THETA(2) V = THETA(1)*EXP(ETA(1)) S1=V $DES DADT(1) = -A(1)*CLMM*KM/(V*(A(1)/V + KM)) $ERROR Y=F+F*EPS(1) $THETA (0,1.00916) ; TVV $THETA (0,135.8) ; POP_KM $THETA (0,0.00469307) ; POP_CLMM $OMEGA 0.031128 ; IVV $SIGMA 0.013241 $ESTIMATION METHOD=1 INTERACTION """ assert str(model) == correct
def test_add_random_variables(pheno_path, rv_new, buf_new): model = Model(pheno_path) rvs = model.random_variables pset = model.parameters eta = RandomVariable.normal('eta_new', 'iiv', 0, S(rv_new.name)) rvs.append(eta) pset.append(rv_new) model.random_variables = rvs model.parameters = pset model.update_source() rec_ref = ( f'$OMEGA DIAGONAL(2)\n' f' 0.0309626 ; IVCL\n' f' 0.031128 ; IVV\n\n' f'{buf_new} ; omega\n' ) rec_mod = '' for rec in model.control_stream.get_records('OMEGA'): rec_mod += str(rec) assert rec_mod == rec_ref rv = model.random_variables['eta_new'] assert rv.sympy_rv.pspace.distribution.mean == 0 assert (rv.sympy_rv.pspace.distribution.std ** 2).name == 'omega'
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')
def test_iiv_on_ruv(pheno_path, epsilons, same_eta, err_ref, omega_ref): model = Model(pheno_path) model_str = str(model) model_more_eps = re.sub('IPRED=F\nIRES=DV-IPRED', 'IPRED=F+EPS(2)\nIRES=DV-IPRED+EPS(3)', model_str) model_sigma = re.sub(r'\$SIGMA 0.013241', '$SIGMA 0.013241\n$SIGMA 0.1\n$SIGMA 0.1', model_more_eps) model.control_stream = NMTranParser().parse(model_sigma) iiv_on_ruv(model, epsilons, same_eta) model.update_source() err_rec = model.control_stream.get_records('ERROR')[0] assert str( err_rec) == f'$ERROR\n' f'W=F\n' f'{err_ref}' f'IWRES=IRES/W\n\n' omega_rec = ''.join( str(rec) for rec in model.control_stream.get_records('OMEGA')) assert omega_rec == (f'$OMEGA DIAGONAL(2)\n' f' 0.0309626 ; IVCL\n' f' 0.031128 ; IVV\n\n' f'{omega_ref}\n')
def test_remove_eta(pheno_path): model = Model(pheno_path) rvs = model.random_variables eta1 = rvs['ETA(1)'] del rvs[eta1] model.update_source() assert str(model).split('\n')[12] == 'V = TVV*EXP(ETA(1))'
def test_set_parameters(pheno_path): model = Model(pheno_path) params = { 'THETA(1)': 0.75, 'THETA(2)': 0.5, 'THETA(3)': 0.25, 'OMEGA(1,1)': 0.1, 'OMEGA(2,2)': 0.2, 'SIGMA(1,1)': 0.3, } model.parameters = params assert model.parameters['THETA(1)'] == Parameter('THETA(1)', 0.75, lower=0, upper=1000000) assert model.parameters['THETA(2)'] == Parameter('THETA(2)', 0.5, lower=0, upper=1000000) assert model.parameters['THETA(3)'] == Parameter('THETA(3)', 0.25, lower=-0.99, upper=1000000) assert model.parameters['OMEGA(1,1)'] == Parameter('OMEGA(1,1)', 0.1, lower=0, upper=sympy.oo) assert model.parameters['OMEGA(2,2)'] == Parameter('OMEGA(2,2)', 0.2, lower=0, upper=sympy.oo) assert model.parameters['SIGMA(1,1)'] == Parameter('SIGMA(1,1)', 0.3, lower=0, upper=sympy.oo) model.update_source() thetas = model.control_stream.get_records('THETA') assert str(thetas[0]) == '$THETA (0,0.75) ; PTVCL\n' assert str(thetas[1]) == '$THETA (0,0.5) ; PTVV\n' assert str(thetas[2]) == '$THETA (-.99,0.25)\n' omegas = model.control_stream.get_records('OMEGA') assert str(omegas[0]) == '$OMEGA DIAGONAL(2)\n 0.1 ; IVCL\n 0.2 ; IVV\n\n' sigmas = model.control_stream.get_records('SIGMA') assert str(sigmas[0]) == '$SIGMA 0.3\n' model = Model(pheno_path) params = model.parameters params['THETA(1)'].init = 18 model.parameters = params assert model.parameters['THETA(1)'] == Parameter('THETA(1)', 18, lower=0, upper=1000000) assert model.parameters['THETA(2)'] == Parameter('THETA(2)', 1.00916, lower=0, upper=1000000)
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'
def test_update_inits(pheno_path): model = Model(pheno_path) model.update_inits() with ConfigurationContext(conf, parameter_names=['comment', 'basic']): model = Model(pheno_path) model.update_inits() model.update_source()
def test_des(testdata, model_path, transformation): model_ref = Model(testdata / model_path) transformation(model_ref) model_ref.update_source() model_des = Model(StringIO(str(model_ref))) model_des.source.path = model_ref.source.path # To be able to find dataset assert model_ref.statements.ode_system == model_des.statements.ode_system
def test_additive_error_model(testdata): model = Model(testdata / 'nonmem' / 'pheno.mod') additive_error(model) model.update_source() assert str(model).split('\n')[11] == 'Y = F + EPS(1)' assert str(model).split('\n')[17] == '$SIGMA 11.2225 ; sigma' before = str(model) additive_error(model) # One more time and nothing should change assert before == str(model)
def test_combined_error_model_log(testdata): model = Model(testdata / 'nonmem' / 'pheno.mod') combined_error(model, data_trans='log(Y)') model.update_source() assert str(model).split('\n')[11] == 'Y = LOG(F) + EPS(2)/F + EPS(1)' assert str(model).split('\n')[17] == '$SIGMA 0.09 ; sigma_prop' assert str(model).split('\n')[18] == '$SIGMA 11.2225 ; sigma_add' before = str(model) combined_error(model) # One more time and nothing should change assert before == str(model)
def test_remove_iiv(testdata, etas, pk_ref, omega_ref): model = Model(testdata / 'nonmem/pheno_block.mod') remove_iiv(model, etas) model.update_source() assert str(model.get_pred_pk_record()) == pk_ref rec_omega = ''.join( str(rec) for rec in model.control_stream.get_records('OMEGA')) assert rec_omega == omega_ref
def test_transit_compartments_added_mdt(testdata): model = Model(testdata / 'nonmem' / 'modeling' / 'pheno_advan5_nodepot.mod') set_transit_compartments(model, 2) transits = model.statements.ode_system.find_transit_compartments( model.statements) assert len(transits) == 2 model.update_source() correct = ("""$PROBLEM PHENOBARB SIMPLE MODEL $DATA ../pheno.dta IGNORE=@ $INPUT ID TIME AMT WGT APGR DV FA1 FA2 $SUBROUTINE ADVAN5 TRANS1 $MODEL COMPARTMENT=(TRANSIT1 DEFDOSE) COMPARTMENT=(TRANSIT2) COMPARTMENT=(CENTRAL) """ + """COMPARTMENT=(PERIPHERAL) $PK MDT = THETA(6) IF(AMT.GT.0) BTIME=TIME TAD=TIME-BTIME TVCL=THETA(1)*WGT TVV=THETA(2)*WGT IF(APGR.LT.5) TVV=TVV*(1+THETA(3)) CL=TVCL*EXP(ETA(1)) V=TVV*EXP(ETA(2)) K30 = CL/V K34 = THETA(4) K43 = THETA(5) S3 = V K12 = 2/MDT K23 = 2/MDT $ERROR W=F Y=F+W*EPS(1) IPRED=F IRES=DV-IPRED IWRES=IRES/W $THETA (0,0.00469307) ; CL $THETA (0,1.00916) ; V $THETA (-.99,.1) $THETA (0,10) $THETA (0,10) $THETA (0,0.5) ; POP_MDT $OMEGA DIAGONAL(2) 0.0309626 ; IVCL 0.031128 ; IVV $SIGMA 1e-7 $ESTIMATION METHOD=1 INTERACTION $COVARIANCE UNCONDITIONAL $TABLE ID TIME DV AMT WGT APGR IPRED PRED RES TAD CWRES NPDE NOAPPEND NOPRINT ONEHEADER FILE=sdtab1 """) assert str(model) == correct
def test_block_rvs(testdata, etas, pk_ref, omega_ref): with ConfigurationContext(conf, parameter_names='comment'): model = Model(testdata / 'nonmem/pheno_block.mod') create_rv_block(model, etas) model.update_source() assert str(model.get_pred_pk_record()) == pk_ref rec_omega = ''.join( str(rec) for rec in model.control_stream.get_records('OMEGA')) assert rec_omega == omega_ref
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'
def test_add_depot(testdata): code = """$PROBLEM PHENOBARB SIMPLE MODEL $DATA pheno.dta IGNORE=@ $INPUT ID TIME AMT WGT APGR DV $SUBROUTINE ADVAN1 TRANS2 $PK CL=THETA(1)*EXP(ETA(1)) V=THETA(2)*EXP(ETA(2)) $ERROR CONC = A(1)/V Y = CONC + CONC*EPS(1) $THETA (0,0.00469307) ; TVCL $THETA (0,1.00916) ; TVV $OMEGA 0.0309626 ; IVCL $OMEGA 0.031128 ; IVV $SIGMA 0.013241 $ESTIMATION METHOD=1 INTERACTION """ model = Model(StringIO(code)) model.source.path = testdata / 'nonmem' / 'pheno.mod' # To be able to find dataset first_order_absorption(model) model.update_source() correct = """$PROBLEM PHENOBARB SIMPLE MODEL $DATA pheno.dta IGNORE=@ $INPUT ID TIME AMT WGT APGR DV $SUBROUTINE ADVAN2 TRANS2 $PK MAT = THETA(3) CL=THETA(1)*EXP(ETA(1)) V=THETA(2)*EXP(ETA(2)) KA = 1/MAT $ERROR CONC = A(2)/V Y = CONC + CONC*EPS(1) $THETA (0,0.00469307) ; TVCL $THETA (0,1.00916) ; TVV $THETA (0,2.0) ; POP_MAT $OMEGA 0.0309626 ; IVCL $OMEGA 0.031128 ; IVV $SIGMA 0.013241 $ESTIMATION METHOD=1 INTERACTION """ assert str(model) == correct
def test_add_covariate_effect_nan(pheno_path): model = Model(pheno_path) data = model.dataset new_col = [np.nan] * 10 + ([1.0] * (len(data.index) - 10)) data['new_col'] = new_col model.dataset = data add_covariate_effect(model, 'CL', 'new_col', 'cat') model.update_source(nofiles=True) assert not re.search('NaN', str(model)) assert re.search(r'NEW_COL\.EQ\.-99', str(model))
def test_abbr_read_write(pheno_path): with ConfigurationContext( conf, parameter_names=['abbr', 'comment', 'basic'], write_etas_in_abbr=True ): model_write = Model(pheno_path) add_iiv(model_write, 'S1', 'add') model_write.update_source() model_read = Model(StringIO(str(model_write))) model_read.source.path = pheno_path assert str(model_read) == str(model_write) assert model_read.statements == model_write.statements assert not ( model_read.random_variables - model_write.random_variables ) # Different order due to renaming in read
def test_lag_time(testdata): model = Model(testdata / 'nonmem' / 'modeling' / 'pheno_advan1.mod') before = str(model) add_lag_time(model) model.update_source() correct = '''$PROBLEM PHENOBARB SIMPLE MODEL $DATA ../pheno.dta IGNORE=@ $INPUT ID TIME AMT WGT APGR DV FA1 FA2 $SUBROUTINE ADVAN1 TRANS2 $PK MDT = THETA(4) IF(AMT.GT.0) BTIME=TIME TAD=TIME-BTIME TVCL=THETA(1)*WGT TVV=THETA(2)*WGT IF(APGR.LT.5) TVV=TVV*(1+THETA(3)) CL=TVCL*EXP(ETA(1)) V=TVV*EXP(ETA(2)) S1=V ALAG1 = MDT $ERROR W=F Y=F+W*EPS(1) IPRED=F IRES=DV-IPRED IWRES=IRES/W $THETA (0,0.00469307) ; CL $THETA (0,1.00916) ; V $THETA (-.99,.1) $THETA (0,0.5) ; POP_MDT $OMEGA DIAGONAL(2) 0.0309626 ; IVCL 0.031128 ; IVV $SIGMA 1e-7 $ESTIMATION METHOD=1 INTERACTION $COVARIANCE UNCONDITIONAL $TABLE ID TIME DV AMT WGT APGR IPRED PRED RES TAD CWRES NPDE NOAPPEND NOPRINT ONEHEADER FILE=sdtab1 ''' assert str(model) == correct remove_lag_time(model) model.update_source() assert str(model) == before
def test_add_two_parameters(pheno_path): model = Model(pheno_path) pset = model.parameters assert len(pset) == 6 param_1 = Parameter('COVEFF1', 0.2) param_2 = Parameter('COVEFF2', 0.1) pset.append(param_1) pset.append(param_2) model.parameters = pset model.update_source() assert len(pset) == 8 assert model.parameters[param_1.name].init == 0.2 assert model.parameters[param_2.name].init == 0.1
def test_to_explicit_odes(pheno_path, testdata): model = Model(pheno_path) explicit_odes(model) model.update_source() lines = str(model).split('\n') assert lines[5] == '$MODEL COMPARTMENT=(CENTRAL DEFDOSE)' assert lines[16] == '$DES' assert lines[17] == 'DADT(1) = -A(1)*CL/V' model = Model(testdata / 'nonmem' / 'modeling' / 'pheno_advan1_zero_order.mod') explicit_odes(model) model.update_source() lines = str(model).split('\n') assert lines[15] == 'D1 = THETA(4)'
def test_remove_estimation_step(): code = '''$PROBLEM base model $INPUT ID DV TIME $DATA file.csv IGNORE=@ $PRED Y = THETA(1) + ETA(1) + ERR(1) $THETA 0.1 $OMEGA 0.01 $SIGMA 1 $EST METH=COND INTER ''' model = Model(StringIO(code)) model.remove_estimation_step(0) assert not model.estimation_steps model.update_source() assert str(model).split('\n')[-2] == '$SIGMA 1'
def test_combined_mm_fo_elimination(testdata): code = """$PROBLEM PHENOBARB SIMPLE MODEL $DATA pheno.dta IGNORE=@ $INPUT ID TIME AMT WGT APGR DV $SUBROUTINE ADVAN1 TRANS2 $PK CL=THETA(1)*EXP(ETA(1)) V=THETA(2)*EXP(ETA(2)) S1=V $ERROR Y=F+F*EPS(1) $THETA (0,0.00469307) ; TVCL $THETA (0,1.00916) ; TVV $OMEGA 0.0309626 ; IVCL $OMEGA 0.031128 ; IVV $SIGMA 0.013241 $ESTIMATION METHOD=1 INTERACTION """ model = Model(StringIO(code)) model.source.path = testdata / 'nonmem' / 'pheno.mod' # To be able to find dataset mixed_mm_fo_elimination(model) model.update_source() correct = """$PROBLEM PHENOBARB SIMPLE MODEL $DATA pheno.dta IGNORE=@ $INPUT ID TIME AMT WGT APGR DV $SUBROUTINE ADVAN6 TOL=3 $MODEL COMPARTMENT=(CENTRAL DEFDOSE) $PK CLMM = THETA(4) KM = THETA(3) CL=THETA(1)*EXP(ETA(1)) V=THETA(2)*EXP(ETA(2)) S1=V $DES DADT(1) = -A(1)*(CL + CLMM*KM/(A(1)/V + KM))/V $ERROR Y=F+F*EPS(1) $THETA (0,0.00469307) ; TVCL $THETA (0,1.00916) ; TVV $THETA (0,135.8) ; POP_KM $THETA (0,0.002346535) ; POP_CLMM $OMEGA 0.0309626 ; IVCL $OMEGA 0.031128 ; IVV $SIGMA 0.013241 $ESTIMATION METHOD=1 INTERACTION """ assert str(model) == correct
def test_john_draper(pheno_path, etas, etad, buf_new): model = Model(pheno_path) john_draper(model, etas) model.update_source() rec_ref = (f'$PK\n' f'{etad}\n' f'IF(AMT.GT.0) BTIME=TIME\n' f'TAD=TIME-BTIME\n' f'TVCL=THETA(1)*WGT\n' f'TVV=THETA(2)*WGT\n' f'IF(APGR.LT.5) TVV=TVV*(1+THETA(3))\n' f'{buf_new}\n' f'S1=V\n\n') assert str(model.get_pred_pk_record()) == rec_ref
def test_estimation_steps_setter(estcode, method, inter, cov, rec_ref): code = '''$PROBLEM base model $INPUT ID DV TIME $DATA file.csv IGNORE=@ $PRED Y = THETA(1) + ETA(1) + ERR(1) $THETA 0.1 $OMEGA 0.01 $SIGMA 1 ''' code += estcode model = Model(StringIO(code)) model.estimation_steps[0].method = method model.estimation_steps[0].interaction = inter model.estimation_steps[0].cov = cov model.update_source() assert str(model).split('\n')[-2] == rec_ref