Repository navigation
Add a progressr-based progress bar for sampling. - #1138
Conversation
This uses the [`progressr`](https://progressr.futureverse.org/index.html) framework to enable a progress bar for sampling operations. By default, this replaces standard iteration messages, but not other informative messages produced during sampling. From a user point of view, this adds two arguments to the `$sample()` method: - `show_progress_bar`: Default = FALSE If TRUE, registers a progress bar via `progressr` and signals an update for every output line that matches "Iteration:". The user is responsible for registering those progress updates with an appropriate handler. - `suppress_iteration_messages`: Defaults to the value of show_progress_bar, but can also be set directly. If TRUE, disables display of output lines matching "Iteration:", while still causing the progress bar to update. This keeps all of Stan's other informative output, but just removes the superfluous iteration messages when using a progress bar. I've tried to keep all additions to the code as non-intrusive as possible. One minor decision I made was to pass the value of `refresh` from the `$sample()` method through to the `CmdStanProcs` class so that the progress bar can report and update the number of steps in the bar to the same 'scale' as the number of iterations. (Calling `$sample()` with `iter_sampling=8000` and `refresh=100` will result in 80 'ticks' of the progress bar, each increasing the progress by 100.) By default, `progressr` doesn't register a handler to display the progress bar, as this is the responsibility of the user. Multiple packages can be used to display the progress bar. A default progress bar can be registered using the [`cli`](https://cli.r-lib.org/) library in this way: ```r library(progressr) library(cli) handlers( global=TRUE ) handlers("cli") options( cli.spinner = "moon", cli.progress_show_after = 0, cli.progress_clear = FALSE ) handlers( handler_cli( format = "{cli::pb_spin} Progress: |{cli::pb_bar}| {cli::pb_current}/{cli::pb_total} | {cli::pb_percent} | ETA: {cli::pb_eta}", clear = FALSE )) ``` A variety of alternative progress bar handlers are available, including audible and notification-based handlers, and ones that interact with RStudio's jobs pane: <https://progressr.futureverse.org/articles/progressr-11-handlers.html>
In addition to updating the progress bar on stdout lines that match "Iteration:", the CmdStanProcs object(s) now pass the current stdout line to the progress bar as a message for _every_ line, even if the number of completed iterations hasn't increased.
Added a `register_default_progress_handler()` function to `utils.R` that creates a default progress bar for sampling operations and registers it as global handler for progressr. Requires `cli` and `progressr`.
Was accidentally passing `refresh` to each informational progress bar update, rather than the calculated `progress_amount`. This caused each message line to update the progress bar, even if it didn't match an iteration message.
Moved code to close the progress bar to after the `check_finished()` function.
The nature of CmdStan's output makes pulling appropriate refresh and update values for the progress bar slightly tricky. In the original verison of the code, this led to the bar occasionally updating past the point where it was full, or terminating early due to an incorrectly calculated number of steps. This commit reworks the calculations of updates and refresh values for the progress bar, as well as adding some extra conditions to avoid the bar potentially crashing in odd scenarios.
New arguments for `iter_warmup` and `iter_sampling` were not being assigned a default value if not specified in sampling statement.
|
Looks like some tests are failing because the lower bound for iter_sampling should be 0 instead of 1. |
Great. Thanks for this. (First pull request for me on a project like this, so I was a little unfamiliar with the process and running the unit tests.) I've fixed the initial errors, and a couple of other warnings. Now running the tests and documentation generation commands locally before I push an update. |
- `iter_{warmup,sampling}` arguments to MCMCProcs are allowed to be 0.
- Documentation for `register_default_progress_handler` added to
repository.
- Ensured that calls to `progressr` functions are appropriately
prefixed.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v1.0 #1138 +/- ##
=======================================
Coverage ? 94.04%
=======================================
Files ? 19
Lines ? 7538
Branches ? 0
=======================================
Hits ? 7089
Misses ? 449
Partials ? 0 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Added documentation for `show_progress_bar` and `suppress_iteration_messages` in `sample()` function. Changed `require()` calls for `progressr` and `cli` to suggested `requireNamespace()` alternatives.
|
Thanks for the help with the unit tests. In the spirit of peer review, some notes and thoughts:
|
|
Awesome, thank you for the PR! I think I have the flu right now, but I will take a look when I'm feeling better and caught up on work. |
No rush on my side! Hope you feel better soon. |
|
I haven't forgotten about this, just dealing with a backlog of work. In the meantime, I posted on the Stan forum to hopefully get some more people to try it out and let us know how it goes: https://discourse.mc-stan.org/t/please-help-test-a-new-progress-bar-for-sampling-in-cmdstanr/40946
Should we maybe add something to the documentation about this? At least while the progress bar is still new we'll be gathering info about whether any users suffer this fate, so we could warn users that it's an experimental feature and to be cautious using it. Then eventually we can remove the experimental caveat from the doc. What do you think @josswright @VisruthSK? |
|
@VisruthSK awesome, looks like this handles everything in my review comments on #1313. Looking back on some of my old review comments on this PR from before, I think there are a couple of small things we should add to the doc because users will want to know:
And then one tiny thing I noticed in the "sample can suppress CmdStan iteration messages" test. |
|
Just to say that I'm so sorry to have dropped the ball on this after the initial activity. Some rather complicated life things happened, which are still ongoing, and it's not left me much time. |
|
No worries at all @josswright! I really appreciate all the work you did to get this started and I think we can finish it from here. I'm going to add you as a contributor in the DESCRIPTION file on this branch so you'll be listed whenever this merges. Might be able to get it into the upcoming v1.0 release. |
|
Just wanted to second what Jonah said, thanks for tackling this and solving all the tough parts! Hope things are going okay for you. |
|
@avehtari coming back to your five comments from February now that this might get into the 1.0 release candidate:
|
finish_progress() cleared the queue of held chain ids after printing them, so when a held "finished unexpectedly" warning became an error (options(warn = 2), or a tryCatch around $sample()) the deferred call printed the same lines again.
RStudio's console pane handles cursor-up sequences since rstudio/rstudio#17786 (May 2026), and cli flips its ansi_tty capability on for those versions (r-lib/cli#823), so multi-line bars will work in current RStudio but not older releases. One bar stays the design.
progressr's intro vignette asks packages to always signal progress and leave the decision to the user's handlers. CmdStanR keeps an argument on purpose: progressr scopes reporting to the session or to one call, not to a package, and the bar also replaces CmdStan's own iteration lines, which something has to decide to hide. Decided 2026-10-09.
|
Merged! Thanks again @josswright. And thanks @VisruthSK for taking over. And thanks @avehtari for your review comments (they are all addressed now). |
Submission Checklist
Summary
As discussed in #18 , this pull request adds a progress bar to CmdStanR's
sample()function via theprogressrframework.This can be enabled via two new options to
model$sample(...):show_progress_bar- boolean - defaultFALSEEnables the progress bar.
suppress_iteration_messages- boolean - defaultFALSEifshow_progress_barisFALSE, andTRUEifshow_progress_barisTRUE.Causes any output lines reporting an iteration (such as
Chain 1 Iteration 1 / 2000 (Warmup)) to be suppressed.For the progress bar to be displayed, a progress bar handler must be created and registered by the end user. (See: https://progressr.futureverse.org/) For ease of use, a
register_default_progress_handler()function has been added. Callingregister_default_progress_handler()before amodel$sample(...)call will spawn a default progress bar via the cli library.Copyright and Licensing
Please list the copyright holder for the work you are submitting
(this will be you or your assignee, such as a university or company):
Joss Wright, University of Oxford
By submitting this pull request, the copyright holder is agreeing to
license the submitted work under the following licenses: