Skip to content

Commit e6c6d1b

Browse files
Merge branch 'release/0.1.4'
2 parents 60b87f4 + 0425d23 commit e6c6d1b

File tree

15 files changed

+183
-33
lines changed

15 files changed

+183
-33
lines changed

.Rbuildignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,4 @@ Rplots.pdf$
6060
^last.dump*
6161

6262
vignettes/
63+
^*.gif$

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Package: progressr
2-
Version: 0.1.3
2+
Version: 0.1.3-9000
33
Title: A Unifying API for Progress Updates
44
Description: A minimal API for reporting progress updates upstream. The design is to separate the representation of progress updates from how they are presented. What type of progress to signal is controlled by the developer. How these progress updates are rendered is controlled by the end user. For instance, some users may prefer visual feedback such as a horizontal progress bar in the terminal, whereas others may prefer auditory feedback.
55
Authors@R: c(

NEWS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Package: progressr
22
==================
33

4+
Version: 0.1.4 [2019-07-02]
5+
6+
NEW FEATURES:
7+
8+
* Add support for progressor(along = ...).
9+
10+
411
Version: 0.1.3 [2019-07-01]
512

613
NEW FEATURES:

OVERVIEW.md

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
1+
![Life cycle: maturing](https://img.shields.io/badge/lifecycle-maturing-blue.svg)
2+
13
The **[progressr]** package provides a minimal API for reporting progress updates in [R](https://www.r-project.org/). The design is to separate the representation of progress updates from how they are presented. What type of progress to signal is controlled by the developer. How these progress updates are rendered is controlled by the end user. For instance, some users may prefer visual feedback such as a horizontal progress bar in the terminal, whereas others may prefer auditory feedback.
24

5+
6+
<img src="incl/three_in_chinese.gif" alt="Three strokes writing three in Chinese" style="float: right; margin-right: 1ex; margin-left: 1ex;"/>
7+
38
Design motto:
49

510
> The developer is responsible for providing progress updates but it's only the end user who decides if, when, and how progress should be presented. No exceptions will be allowed.
611
712

13+
## Two Minimal APIs
14+
15+
| Developer's API | End-user's API |
16+
|-----------------------|-----------------------------|
17+
| `p <- progressor(n)` | `with_progress(expr)` |
18+
| `p(msg, ...)` | `handlers(...)` |
19+
| | `options(progressr.*=...)` |
20+
21+
22+
823
## A simple example
924

1025
Assume that we have a function `slow_sum()` for adding up the values in a vector. It is so slow, that we like to provide progress updates to whoever might be interested in it. With the **progressr** package, this can be done as:
@@ -49,24 +64,27 @@ To get progress updates, we can call it as:
4964

5065
## Customizing how progress is reported
5166

52-
The default is to present progress via `utils::txtProgressBar()`, which is available on all R installations. To change the default, to, say, `progress_bar()` by the **[progress]** package, set the following R option(\*):
67+
The default is to present progress via `utils::txtProgressBar()`, which is available on all R installations. To change the default, to, say, `progress_bar()` by the **[progress]** package, set:
5368

5469
```r
55-
options(progressr.handlers = progress_handler)
70+
handlers("progress")
5671
```
5772
This progress handler will present itself as:
5873
```r
5974
> with_progress(y <- slow_sum(1:10))
6075
[==================>---------------------------] 40% Added 4
6176
```
6277

78+
To set the default progress handler(s) in all your R sessions, call `progressr::handlers(...)` in your <code>~/.Rprofile</code> file. An alternative, which avoids loading the **progressr** package if never used, is to set `options(progressr.handlers = progress_handler)`.
79+
80+
6381

6482
### Auditory progress updates
6583

6684
Note all progress updates have to be presented visually. This can equally well be done auditory. For example, using:
6785

6886
```r
69-
options(progressr.handlers = beepr_handler)
87+
handlers("beepr")
7088
```
7189
will present itself as sounds played at the beginning, while progressing, and at the end (using different **[beepr]** sounds). There will be _no_ output written to the terminal;
7290
```r
@@ -81,7 +99,7 @@ will present itself as sounds played at the beginning, while progressing, and at
8199

82100
It is possible to have multiple progress handlers presenting progress updates at the same time. For example, to get both visual and auditory updates, use:
83101
```r
84-
options(progressr.handlers = list(txtprogressbar_handler, beepr_handler))
102+
handlers("txtprogressbar", "beepr")
85103
```
86104

87105

@@ -102,6 +120,30 @@ with_progress({
102120
```
103121

104122

123+
### The future framework
124+
125+
The **[future]** framework has built-in support for the kind of progression updates produced by the **progressr** package. Here is an example that uses `future_lapply()` of the **[future.apply]** package to parallelize on the local machine while at the same time signaling progression updates:
126+
127+
```r
128+
library(future.apply)
129+
plan(multisession)
130+
131+
library(progressr)
132+
handlers("progress", "beepr")
133+
134+
with_progress({
135+
p <- progressr::progressor(5)
136+
y <- future_lapply(1:5, function(x, ...) {
137+
p(sprintf("x=%g", x))
138+
Sys.sleep(1)
139+
sqrt(x)
140+
})
141+
})
142+
## [=================>-----------------------------] 40% x=2
143+
```
144+
145+
146+
105147
## Roadmap
106148

107149
Because this project is under active development, the progressr API is currently kept at a very minimum. This will allow for the framework and the API to evolve while minimizing the risk for breaking code that depends on it. The roadmap for developing the API is roughly:
@@ -117,13 +159,26 @@ For a more up-to-date view on what features might be added, see <https://github.
117159

118160
## Appendix
119161

162+
### Under the hood
163+
164+
When using the **progressr** package, progression updates are communicated via R's condition framework, which provides methods for creating, signaling, capturing, muffling, and relaying conditions. Progression updates are of classes `progression` and `immediateCondition`(\*). The below figure gives an example how progression conditions are created, signaled, and rendered.
165+
166+
(\*) The `immediateCondition` class of conditions are relayed as soon as possible by the **[future]** framework, which means that progression updates produced in parallel workers are reported to the end user as soon as the main R session have received them.
167+
168+
169+
170+
171+
![](vignettes/figures/slow_sum.svg)
172+
173+
_Figure: Sequence diagram illustrating how signaled progression conditions are captured by `with_progress()` and relayed to the two progression handlers 'progress' (a progress bar in the terminal) and 'beepr' (auditory) that the end user has chosen._
174+
175+
120176
### Debugging
121177

122178
To debug progress updates, use:
123179
```r
124-
> options(progressr.handlers = debug_handler)
180+
> handlers("debug")
125181
> with_progress(y <- slow_sum(1:10))
126-
[13:33:50.776] (1.033s => +0.001s) shutdown: 10/10 (+0) '' {clear=TRUE, enabled=TRUE, status=ok}
127182
[13:33:49.743] (0.000s => +0.002s) initiate: 0/10 (+0) '' {clear=TRUE, enabled=TRUE, status=}
128183
[13:33:49.847] (0.104s => +0.001s) update: 1/10 (+1) 'Added 1' {clear=TRUE, enabled=TRUE, status=}
129184
[13:33:49.950] (0.206s => +0.001s) update: 2/10 (+1) 'Added 2' {clear=TRUE, enabled=TRUE, status=}
@@ -136,15 +191,13 @@ To debug progress updates, use:
136191
[13:33:50.670] (0.927s => +0.001s) update: 9/10 (+1) 'Added 9' {clear=TRUE, enabled=TRUE, status=}
137192
[13:33:50.773] (1.030s => +0.001s) update: 10/10 (+1) 'Added 10' {clear=TRUE, enabled=TRUE, status=}
138193
[13:33:50.774] (1.031s => +0.003s) update: 10/10 (+0) 'Added 10' {clear=TRUE, enabled=TRUE, status=}
194+
[13:33:50.776] (1.033s => +0.001s) shutdown: 10/10 (+0) '' {clear=TRUE, enabled=TRUE, status=ok}
139195
```
140196

141-
<small>
142-
(*) To set the default progress handler in all your R sessions, set this option in your <code>~/.Rprofile</code> file.
143-
</small>
144-
145197

146198

147199
[progressr]: https://github.com/HenrikBengtsson/progressr/
148200
[beepr]: https://cran.r-project.org/package=beepr
149201
[progress]: https://cran.r-project.org/package=progress
150-
202+
[future]: https://cran.r-project.org/package=future
203+
[future.apply]: https://cran.r-project.org/package=future.apply

R/options.R

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,24 @@
6262
#'
6363
#'
6464
#' @seealso
65-
#' To set \R options when \R starts (even before the \pkg{progressr} package is loaded), see the \link[base]{Startup} help page. The \href{https://cran.r-project.org/package=startup}{\pkg{startup}} package provides a friendly mechanism for configurating \R's startup process.
65+
#' To set \R options when \R starts (even before the \pkg{progressr} package is loaded), see the \link[base]{Startup} help page. The \href{https://cran.r-project.org/package=startup}{\pkg{startup}} package provides a friendly mechanism for configuring \R at startup.
6666
#'
6767
#' @aliases
68+
#' progressr.clear
6869
#' progressr.debug
70+
#' progressr.delay
71+
#' progressr.delay_stdout progressr.delay_conditions
72+
#' progressr.enable progressr.enable_after
73+
#' progressr.interval
74+
#' progressr.intrusiveness
75+
#' progressr.intrusiveness.auditory
76+
#' progressr.intrusiveness.debug
77+
#' progressr.intrusiveness.file
78+
#' progressr.intrusiveness.gui
79+
#' progressr.intrusiveness.notifier
80+
#' progressr.intrusiveness.terminal
6981
#' progressr.handlers
70-
#' progressr.clear
82+
#' progressr.times
7183
#'
7284
#' @keywords internal
7385
#' @name progressr.options

R/progressor.R

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#'
33
#' @param steps (integer) Maximum number of steps.
44
#'
5+
#' @param along (vector; alternative) Corresponds to `steps = seq_along(along)`.
6+
#'
57
#' @param label (character) A label.
68
#'
79
#' @param initiate (logical) If TRUE, the progressor will signal a
@@ -16,7 +18,12 @@
1618
progressor <- local({
1719
progressor_count <- 0L
1820

19-
function(steps, label = NA_character_, initiate = TRUE, auto_finish = TRUE) {
21+
function(steps = NULL, along = NULL, label = NA_character_, initiate = TRUE, auto_finish = TRUE) {
22+
stop_if_not(!is.null(steps) || !is.null(along))
23+
if (!is.null(along)) steps <- length(along)
24+
stop_if_not(length(steps) == 1L, is.numeric(steps), !is.na(steps),
25+
steps >= 0)
26+
2027
label <- as.character(label)
2128
stop_if_not(length(label) == 1L)
2229

R/slow_sum.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#'
1717
#' @export
1818
slow_sum <- function(x, delay = getOption("progressr.delay", 1.0), stdout = FALSE, message = TRUE) {
19-
progress <- progressor(length(x))
19+
progress <- progressor(along = x)
2020

2121
sum <- 0
2222
for (kk in seq_along(x)) {

README.md

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,27 @@
11
# progressr: A Unifying API for Progress Updates
22

3+
![Life cycle: maturing](https://img.shields.io/badge/lifecycle-maturing-blue.svg)
4+
35
The **[progressr]** package provides a minimal API for reporting progress updates in [R](https://www.r-project.org/). The design is to separate the representation of progress updates from how they are presented. What type of progress to signal is controlled by the developer. How these progress updates are rendered is controlled by the end user. For instance, some users may prefer visual feedback such as a horizontal progress bar in the terminal, whereas others may prefer auditory feedback.
46

7+
8+
<img src="incl/three_in_chinese.gif" alt="Three strokes writing three in Chinese" style="float: right; margin-right: 1ex; margin-left: 1ex;"/>
9+
510
Design motto:
611

712
> The developer is responsible for providing progress updates but it's only the end user who decides if, when, and how progress should be presented. No exceptions will be allowed.
813
914

15+
## Two Minimal APIs
16+
17+
| Developer's API | End-user's API |
18+
|-----------------------|-----------------------------|
19+
| `p <- progressor(n)` | `with_progress(expr)` |
20+
| `p(msg, ...)` | `handlers(...)` |
21+
| | `options(progressr.*=...)` |
22+
23+
24+
1025
## A simple example
1126

1227
Assume that we have a function `slow_sum()` for adding up the values in a vector. It is so slow, that we like to provide progress updates to whoever might be interested in it. With the **progressr** package, this can be done as:
@@ -48,26 +63,30 @@ To get progress updates, we can call it as:
4863
|===================== | 40%
4964
```
5065

66+
5167
## Customizing how progress is reported
5268

53-
The default is to present progress via `utils::txtProgressBar()`, which is available on all R installations. To change the default, to, say, `progress_bar()` by the **[progress]** package, set the following R option(\*):
69+
The default is to present progress via `utils::txtProgressBar()`, which is available on all R installations. To change the default, to, say, `progress_bar()` by the **[progress]** package, set:
5470

5571
```r
56-
options(progressr.handlers = progress_handler)
72+
handlers("progress")
5773
```
5874
This progress handler will present itself as:
5975
```r
6076
> with_progress(y <- slow_sum(1:10))
6177
[==================>---------------------------] 40% Added 4
6278
```
6379

80+
To set the default progress handler(s) in all your R sessions, call `progressr::handlers(...)` in your <code>~/.Rprofile</code> file. An alternative, which avoids loading the **progressr** package if never used, is to set `options(progressr.handlers = progress_handler)`.
81+
82+
6483

6584
### Auditory progress updates
6685

6786
Note all progress updates have to be presented visually. This can equally well be done auditory. For example, using:
6887

6988
```r
70-
options(progressr.handlers = beepr_handler)
89+
handlers("beepr")
7190
```
7291
will present itself as sounds played at the beginning, while progressing, and at the end (using different **[beepr]** sounds). There will be _no_ output written to the terminal;
7392
```r
@@ -82,7 +101,7 @@ will present itself as sounds played at the beginning, while progressing, and at
82101

83102
It is possible to have multiple progress handlers presenting progress updates at the same time. For example, to get both visual and auditory updates, use:
84103
```r
85-
options(progressr.handlers = list(txtprogressbar_handler, beepr_handler))
104+
handlers("txtprogressbar", "beepr")
86105
```
87106

88107

@@ -103,6 +122,30 @@ with_progress({
103122
```
104123

105124

125+
### The future framework
126+
127+
The **[future]** framework has built-in support for the kind of progression updates produced by the **progressr** package. Here is an example that uses `future_lapply()` of the **[future.apply]** package to parallelize on the local machine while at the same time signaling progression updates:
128+
129+
```r
130+
library(future.apply)
131+
plan(multisession)
132+
133+
library(progressr)
134+
handlers("progress", "beepr")
135+
136+
with_progress({
137+
p <- progressr::progressor(5)
138+
y <- future_lapply(1:5, function(x, ...) {
139+
p(sprintf("x=%g", x))
140+
Sys.sleep(1)
141+
sqrt(x)
142+
})
143+
})
144+
## [=================>-----------------------------] 40% x=2
145+
```
146+
147+
148+
106149
## Roadmap
107150

108151
Because this project is under active development, the progressr API is currently kept at a very minimum. This will allow for the framework and the API to evolve while minimizing the risk for breaking code that depends on it. The roadmap for developing the API is roughly:
@@ -120,16 +163,24 @@ For a more up-to-date view on what features might be added, see <https://github.
120163

121164
### Under the hood
122165

166+
When using the **progressr** package, progression updates are communicated via R's condition framework, which provides methods for creating, signaling, capturing, muffling, and relaying conditions. Progression updates are of classes `progression` and `immediateCondition`(\*). The below figure gives an example how progression conditions are created, signaled, and rendered.
167+
168+
(\*) The `immediateCondition` class of conditions are relayed as soon as possible by the **[future]** framework, which means that progression updates produced in parallel workers are reported to the end user as soon as the main R session have received them.
169+
170+
171+
172+
123173
![](vignettes/figures/slow_sum.svg)
124174

175+
_Figure: Sequence diagram illustrating how signaled progression conditions are captured by `with_progress()` and relayed to the two progression handlers 'progress' (a progress bar in the terminal) and 'beepr' (auditory) that the end user has chosen._
176+
125177

126178
### Debugging
127179

128180
To debug progress updates, use:
129181
```r
130-
> options(progressr.handlers = debug_handler)
182+
> handlers("debug")
131183
> with_progress(y <- slow_sum(1:10))
132-
[13:33:50.776] (1.033s => +0.001s) shutdown: 10/10 (+0) '' {clear=TRUE, enabled=TRUE, status=ok}
133184
[13:33:49.743] (0.000s => +0.002s) initiate: 0/10 (+0) '' {clear=TRUE, enabled=TRUE, status=}
134185
[13:33:49.847] (0.104s => +0.001s) update: 1/10 (+1) 'Added 1' {clear=TRUE, enabled=TRUE, status=}
135186
[13:33:49.950] (0.206s => +0.001s) update: 2/10 (+1) 'Added 2' {clear=TRUE, enabled=TRUE, status=}
@@ -142,18 +193,16 @@ To debug progress updates, use:
142193
[13:33:50.670] (0.927s => +0.001s) update: 9/10 (+1) 'Added 9' {clear=TRUE, enabled=TRUE, status=}
143194
[13:33:50.773] (1.030s => +0.001s) update: 10/10 (+1) 'Added 10' {clear=TRUE, enabled=TRUE, status=}
144195
[13:33:50.774] (1.031s => +0.003s) update: 10/10 (+0) 'Added 10' {clear=TRUE, enabled=TRUE, status=}
196+
[13:33:50.776] (1.033s => +0.001s) shutdown: 10/10 (+0) '' {clear=TRUE, enabled=TRUE, status=ok}
145197
```
146198

147-
<small>
148-
(*) To set the default progress handler in all your R sessions, set this option in your <code>~/.Rprofile</code> file.
149-
</small>
150-
151199

152200

153201
[progressr]: https://github.com/HenrikBengtsson/progressr/
154202
[beepr]: https://cran.r-project.org/package=beepr
155203
[progress]: https://cran.r-project.org/package=progress
156-
204+
[future]: https://cran.r-project.org/package=future
205+
[future.apply]: https://cran.r-project.org/package=future.apply
157206

158207
## Installation
159208
R package progressr is only available via [GitHub](https://github.com/HenrikBengtsson/progressr) and can be installed in R as:

incl/three_in_chinese.gif

6.9 KB
Loading

inst/WORDLIST

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ HenrikBengtsson
77
https
88
macOS
99
NL
10+
parallelize
1011
plyr
1112
Plyr
1213
POSIXct
@@ -16,4 +17,5 @@ progressor
1617
Progressor
1718
roadmap
1819
Roadmap
20+
Rprofile
1921
substyle

0 commit comments

Comments
 (0)