Calvagone / campsis

A generic PK/PD simulation platform based on rxode2 and mrgsolve engines.
https://calvagone.github.io/
GNU General Public License v3.0
8 stars 3 forks source link

LoadLibrary failure: %1 is not a valid Win32 application (issue with advan1_trans1 model) #160

Open luyckxn opened 1 month ago

luyckxn commented 1 month ago

This is a strange issue. Model advan1_trans1 from the Campsis model suite (model_suite$nonmem$advan1_trans1) does not compile anymore with mrgsolve v1.5.2 on Windows.

Here are the steps to reproduce the issue with Campsis or directly with mrgsolve:

library(campsis)

model <- model_suite$nonmem$advan1_trans1

dataset <- Dataset(3)%>%
  add(Bolus(time=0, amount=1000, compartment=1, ii=12, addl=2)) %>%
  add(Observations(times=seq(0,36,by=0.1), compartment=1))

# Working
results <- simulate(model=model, dataset=dataset, dest="rxode2")
spaghettiPlot(results, "CONC")

# Not working with mrgsolve v1.5.2
# Error: LoadLibrary failure:  %1 is not a valid Win32 application
results <- simulate(model=model, dataset=dataset, dest="mrgsolve")
spaghettiPlot(results, "CONC")

# Export to mrgsolve model code
mrgsolveModelCode <- model %>%
  export(dest="mrgsolve") %>%
  toString()

cat(mrgsolveModelCode)

# Build mrgsolve model (error with mrgsolve v1.5.2)
# Error: LoadLibrary failure:  %1 is not a valid Win32 application (the first time)
# Or Error: cannot open output file mod1-mread-source.dll: Permission denied - the model build step failed. (the other times, unless you change the name)
model <- mrgsolve::mread(model="mod1", code=mrgsolveModelCode)
luyckxn commented 1 month ago

If advan3_trans1 is used instead, it works...

@kylebaron: Do you have any idea what the problem could be?

kylebaron commented 1 month ago

@luyckxn can you post what mrgsolveModelCode is?

It looks like mrgsolve and campsis are working ok together on cran

kylebaron commented 1 month ago

I got this; it looks fairly straightforward:

[PARAM] @annotated
THETA_K : 0.0625 : THETA_K
THETA_V : 80 : THETA_V

[CMT] @annotated
A_CENTRAL : CENTRAL
A_OUTPUT : OUTPUT

[OMEGA] @annotated @block
ETA_K : 0.025 : ETA_K
ETA_V : 0 0.025 : ETA_V

[SIGMA] @annotated @block
EPS_PROP : 0.025 : EPS_PROP

[MAIN]
double K=THETA_K*exp(ETA_K);
double V=THETA_V*exp(ETA_V);
double S1=V;

[ODE]
dxdt_A_CENTRAL=-K*A_CENTRAL;
dxdt_A_OUTPUT=K*A_CENTRAL;
double F=A_CENTRAL/S1;

[TABLE]
capture CONC=F;
capture CONC_ERR=CONC*(EPS_PROP + 1);

Not on windows, but here's the entire example:

library(campsis)
#> Loading required package: campsismod
#> 
#> Attaching package: 'campsismod'
#> The following object is masked from 'package:utils':
#> 
#>     find
#> The following objects are masked from 'package:base':
#> 
#>     as.data.frame, Position, replace, sort, toString, write
#> 
#> Attaching package: 'campsis'
#> The following object is masked from 'package:stats':
#> 
#>     simulate
#> The following objects are masked from 'package:base':
#> 
#>     months, sample

model <- model_suite$nonmem$advan1_trans1

dataset <- Dataset(3)%>%
  add(Bolus(time=0, amount=1000, compartment=1, ii=12, addl=2)) %>%
  add(Observations(times=seq(0,36,by=0.1), compartment=1))

# Working
results <- simulate(model=model, dataset=dataset, dest="rxode2")
spaghettiPlot(results, "CONC")


# Not working with mrgsolve v1.5.2
# Error: LoadLibrary failure:  %1 is not a valid Win32 application
results <- simulate(model=model, dataset=dataset, dest="mrgsolve")
spaghettiPlot(results, "CONC")


# Export to mrgsolve model code
mrgsolveModelCode <- model %>%
  export(dest="mrgsolve") %>%
  toString()

cat(mrgsolveModelCode)

# Build mrgsolve model (error with mrgsolve v1.5.2)
# Error: LoadLibrary failure:  %1 is not a valid Win32 application (the first time)
# Or Error: cannot open output file mod1-mread-source.dll: Permission denied - the model build step failed. (the other times, unless you change the name)
model <- mrgsolve::mread(model="mod1", code=mrgsolveModelCode)
#> Building mod1 ...
#> done.

Created on 2024-10-29 with reprex v2.1.1

luyckxn commented 1 month ago

@kylebaron: Thanks. That's the expected output indeed. The problem only occurs on Windows and with this very specific (and basic) model. A colleague of mine was able to reproduce the issue. Mrgsolve v1.5.1 and lower: no issue. Mrgsolve v1.5.2: first time this issue has occured (windows only and with this basic model only, all the other models from the library can be compiled properly).

kylebaron commented 1 month ago

So, advan1_trans1 doesn't work, but advan1_trans2 does work; so the difference is K instead of CL. And as you note, advan1_trans1 is even simpler (less math going on).

@luyckxn Do you have unit tests compiling these two models?

library(campsis)

export(model_suite$nonmem$advan1_trans1, dest = "mrgsolve") %>% toString() %>% cat()

#> [PARAM] @annotated
#> THETA_K : 0.0625 : THETA_K
#> THETA_V : 80 : THETA_V
#> 
#> [CMT] @annotated
#> A_CENTRAL : CENTRAL
#> A_OUTPUT : OUTPUT
#> 
#> [OMEGA] @annotated @block
#> ETA_K : 0.025 : ETA_K
#> ETA_V : 0 0.025 : ETA_V
#> 
#> [SIGMA] @annotated @block
#> EPS_PROP : 0.025 : EPS_PROP
#> 
#> [MAIN]
#> double K=THETA_K*exp(ETA_K);
#> double V=THETA_V*exp(ETA_V);
#> double S1=V;
#> 
#> [ODE]
#> dxdt_A_CENTRAL=-K*A_CENTRAL;
#> dxdt_A_OUTPUT=K*A_CENTRAL;
#> double F=A_CENTRAL/S1;
#> 
#> [TABLE]
#> capture CONC=F;
#> capture CONC_ERR=CONC*(EPS_PROP + 1);

export(model_suite$nonmem$advan1_trans2, dest = "mrgsolve") %>% toString() %>% cat()
#> [PARAM] @annotated
#> THETA_CL : 5 : THETA_CL
#> THETA_V : 80 : THETA_V
#> 
#> [CMT] @annotated
#> A_CENTRAL : CENTRAL
#> A_OUTPUT : OUTPUT
#> 
#> [OMEGA] @annotated @block
#> ETA_CL : 0.025 : ETA_CL
#> ETA_V : 0 0.025 : ETA_V
#> 
#> [SIGMA] @annotated @block
#> EPS_PROP : 0.025 : EPS_PROP
#> 
#> [MAIN]
#> double CL=THETA_CL*exp(ETA_CL);
#> double V=THETA_V*exp(ETA_V);
#> double S1=V;
#> 
#> [ODE]
#> dxdt_A_CENTRAL=-CL*A_CENTRAL/V;
#> dxdt_A_OUTPUT=CL*A_CENTRAL/V;
#> double F=A_CENTRAL/S1;
#> 
#> [TABLE]
#> capture CONC=F;
#> capture CONC_ERR=CONC*(EPS_PROP + 1);

Created on 2024-10-29 with reprex v2.1.1

luyckxn commented 1 month ago

@kylebaron yes indeed, advan1_trans2 works just smoothly. Very strange. In fact, we detected the problem because advan1_trans1 was used by some tests in another (private) package. Before adding any new tests on my side, I wanted to contact you first since you know better than me what has changed in mrgsolve v1.5.2 :-)

luyckxn commented 1 month ago

So if you re-use the advan1_trans1 mrgsolve model code (generated by Campsis) and read it using the function mread or mread_file, you should be able to reproduce the problem, on Windows.

kylebaron commented 1 month ago

@luyckxn I will keep looking into it with you. I went through the change set from 1.5.1 to 1.5.2 and don't see anything obvious that would affect this code, especially in a platform-dependent way. I can work on getting a Windows box up and see if I can find anything else.

Just to clarify: are these models tested in the package? I'd like to know if the result on CRAN is meaningful or not. There is a reverse-depends check that happens before pushing out any new code; but that wouldn't mean anything if this model is not tested.

Thanks, Kyle

luyckxn commented 1 month ago

Thanks a lot. It is untested yet on CRAN. So the reverse-depends check will not detect anything. I will add a test for the next release.

luyckxn commented 1 month ago

I added a test on the develop branch (see commit just above). CI seems to pass smoothly on Windows (all tests OK with mrgsolve v1.5.2)... While locally, on my PC, it doesn't. I will investigate further...

mattfidler commented 1 month ago

Hi @kylebaron

Did you do any pre-linking/pre-compiling headers or something similar with mrgsolve in this release (ie you pre-compile the headers), if so there are multiple windows platforms that can cause this problem.

I have seen this with CRAN when we pre-compiled the headers and it was submitted to CRAN.

kylebaron commented 1 month ago

Hi @mattfidler -

No; nothing fancy like that - precompiling etc. I've wondered about that sort of thing, but never brave enough to mess around with it let alone try to release.

Kyle

luyckxn commented 1 month ago

I think I solved the mistery... The dll file of this particular model is detected as a trojan by BitDefender and deleted... That's completely crazy.

bitdefender

Sorry for bothering you yesterday... and thanks a lot for your help.

kylebaron commented 1 month ago

Oh weird .... No problem. Thanks for reporting. I'll look to see if there's anything else we can do to verify there is a dll present when we go to load it; I'm pretty sure we do something but maybe we could do better and at least issue a better error.

mattfidler commented 1 month ago

If my reading of the French is correct, it assumes that mrgsolve binaries connect to the internet?

luyckxn commented 1 month ago

@mattfidler No, I don't think so, the trojan is detected by bitdefender's anti-malware software, not its firewall.