Let different cells use the same graphics device by ma1112 · Pull Request #749 · IRkernel/IRkernel · GitHub
Skip to content

Let different cells use the same graphics device#749

Open
ma1112 wants to merge 1 commit intoIRkernel:masterfrom
ma1112:no_new_grapnics_device
Open

Let different cells use the same graphics device#749
ma1112 wants to merge 1 commit intoIRkernel:masterfrom
ma1112:no_new_grapnics_device

Conversation

@ma1112
Copy link
Copy Markdown

@ma1112 ma1112 commented Apr 11, 2025

This PR resolves #240 , and as a side effect it also resolves issues reporting various behaviour when plotting with IRKernel, e.g. also #722.

The goal of this PR is to let different cells use the same graphics device. I.e. when one plots in one cell e.g. with the plot command and then enhances the plot in the following cell e.g. with lines, the cumulative effect of those two commands should be visible in the output of the former cell.

IRKernel calls evaluate to run R code cell by cell, and evaluate creates a new graphics device for each function call. See the evaluate source code

With this change, IRKernel now creates its own graphics device and calls evalute() with new_device = FALSE.

Also, in order to capture plots properly, IRKernel now executes dev.control(displaylist = "enable"), similarly to evaluate that executes this for each kernel it creates (code). This is needed to capture the effects of multiple plotting functions applied on the same device.

By re-using the same graphics device, if one creates a plot in one cell, evaluate will call handle_graphics() in all subsesquent cells, even if the cell does not plot anything. To handle that, guardrails are applied in order not to send plots multiple times to the UI, in a from of introducing the boolean variable last_recorded_plot_sent.

Moreover, as a side effect, IRKernel's own device settings are now taking effect, that has been hidden by evalaute's default new_device option that has set the device to pdf for each execution. See the IRkernel code here and evaluate's code here.

This PR resolves issues/240, and as a side effect it also resolves issues reporting various behaviour when plotting with IRKernel, e.g. also issues/722.

The goal of this PR is to let different cells use the same graphics device. I.e. when one plots in one cell e.g. with the `plot` command and then enhances the plot in the following cell e.g. with `lines`, the cumulative effect of those two commands should be visible in the output of the former cell.

`IRKernel` calls `evaluate` to run R code cell by cell, and `evaluate` creates a new graphics device for each function call. See [the evaluate source code](https://github.com/r-lib/evaluate/blob/8d2bb1f353b878178b042d36ddcff2cca4a2be5e/R/evaluate.R#L77)
With this change, `IRKernel` now creates its own graphics device and calls `evalute()` with `new_device = FALSE.`
Also, in order to capture plots properly, `IRKernel` now executes `dev.control(displaylist = "enable")`, similarly to `evaluate` that executes this for each kernel it creates ([code](https://github.com/r-lib/evaluate/blob/8d2bb1f353b878178b042d36ddcff2cca4a2be5e/R/watchout.R#L9C5-L9C40))
With this change, if one creates a plot in one cell, `evaluate` will call `handle_graphics()` in all subsesquent cells, even if the cell does not plot anyhting. To handle that, guardrails are applied in order not to send plots multiple times to the UI, in a from of introducing the boolean variable `last_recorded_plot_sent`.
Moreover, as a side effect, `IRKernel`'s own device settings are now taking effect, that has been hidden by `evalaute`'s default `new_device` option that has set the device to `pdf` for each execution. See the IRkernel code [here](https://github.com/IRkernel/IRkernel/blob/124f2347f15cfadeabc6738868e05e6087f4c456/R/environment_shadow.r#L121) and evaluate's code [here](https://github.com/r-lib/evaluate/blob/8d2bb1f353b878178b042d36ddcff2cca4a2be5e/R/watchout.R#L8).
Comment thread R/execution.r
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest I do not really understand what is the reason for sending the plot here, as well as after we call evaluate(), so I tried keeping the same logic with the new re-useable graphics devices.

Comment thread R/execution.r
}

if (is.null(prev) && !is.null(current)) {
return(!require_exact_length)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain the logic here?

Copy link
Copy Markdown
Author

@ma1112 ma1112 Apr 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if require_exact_length is set to false, the function behaves as the former version of plot_builds_upon. Specifically, in this branch is.null(prev) is true, so the function returns TRUE.

if require_exact_length is set to true, the goal of the function is to check if the two plots are exactly the same.
If prev is null but current is not null, they can not be the same and therefore we return FALSE.

I am open to suggestions on how to rewrite the function to make it more readable. Maybe renaming require_exact_length to require_exact_match or explicitly writing out the logic here would help more?
E.g.

    if (is.null(prev) && !is.null(current)) {
        if(require_exact_length) { 
            return FALSE
        } else { 
            return TRUE
    }
```

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@flying-sheep does the explanation above help?

@ma1112
Copy link
Copy Markdown
Author

ma1112 commented May 12, 2025

@flying-sheep I know you said you had little time to review PRs but I'm wondering if you might find some time to look at this PR, or at least set some expectations on when you might have a chance to take a look.

@ma1112 ma1112 requested a review from flying-sheep May 22, 2025 11:57
@ma1112
Copy link
Copy Markdown
Author

ma1112 commented Jun 3, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

plot.new has not been called yet error message

2 participants