Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions cmdstanpy/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2027,7 +2027,14 @@ def diagnose(
Gradients are evaluated in the unconstrained space.
"""

with temp_single_json(data) as _data, temp_single_json(inits) as _inits:
with (
temp_single_json(data) as _data,
temp_single_json(inits) as _inits,
# the output is read below and is not needed after this call.
tempfile.TemporaryDirectory(
prefix=self.name, dir=_TMPDIR
) as output_dir,
):
cmd = [
str(self.exe_file),
"diagnose",
Expand All @@ -2036,14 +2043,12 @@ def diagnose(
if epsilon is not None:
cmd.append(f"epsilon={epsilon}")
if error is not None:
cmd.append(f"epsilon={error}")
cmd.append(f"error={error}")
if _data is not None:
cmd += ["data", f"file={_data}"]
if _inits is not None:
cmd.append(f"init={_inits}")

output_dir = tempfile.mkdtemp(prefix=self.name, dir=_TMPDIR)

output = os.path.join(output_dir, "output.csv")
cmd += ["output", f"file={output}"]
if sig_figs is not None:
Expand Down
34 changes: 34 additions & 0 deletions test/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import numpy as np
import pytest

from cmdstanpy import _TMPDIR
from cmdstanpy.model import CmdStanModel
from cmdstanpy.utils import EXTENSION

Expand Down Expand Up @@ -472,3 +473,36 @@ def test_diagnose() -> None:
require_gradients_ok=False,
)
assert np.abs(gradients["error"]).max() > 1e-3


def test_diagnose_error_argument(caplog: pytest.LogCaptureFixture) -> None:
model = CmdStanModel(stan_file=BERN_STAN)
with caplog.at_level(logging.DEBUG, logger="cmdstanpy"):
model.diagnose(data=BERN_DATA, epsilon=1e-5, error=1e-3)
cmds = [r.getMessage() for r in caplog.records if "Cmd:" in r.message]
assert len(cmds) == 1
assert "'epsilon=1e-05'" in cmds[0]
assert "'error=0.001'" in cmds[0]
assert cmds[0].count("epsilon=") == 1


@pytest.mark.parametrize("fails", [False, True])
def test_diagnose_removes_output_dir(
fails: bool, caplog: pytest.LogCaptureFixture
) -> None:
model = CmdStanModel(stan_file=BERN_STAN)
cmdstanpy_tmp = set(os.listdir(_TMPDIR))

with caplog.at_level(logging.DEBUG, logger="cmdstanpy"):
if fails:
with pytest.raises(RuntimeError, match="may exceed"):
model.diagnose(data=BERN_DATA, epsilon=3)
else:
model.diagnose(data=BERN_DATA)

assert set(os.listdir(_TMPDIR)) == cmdstanpy_tmp
# the command is logged as a list repr, which escapes Windows separators
output_arg = "file=" + repr(str(_TMPDIR))[1:-1]
cmds = [r.getMessage() for r in caplog.records if "Cmd:" in r.message]
assert len(cmds) == 1
assert output_arg in cmds[0]
Loading