-
Notifications
You must be signed in to change notification settings - Fork 23
Implement plot metadata call #998
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
DavisVaughan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One medium sized note about possibly adding a graphics_device::on_execute_request() hook to maybe simplify things, but otherwise looks good.
This all does feel a bit hacky 😅, but is hopefully pretty low stakes and "best effort"
For example, this is a little weird, but i doubt people would care much
# same plot, different names
# "ggplot2 scatter plot {N}"
ggplot(mtcars, aes(x = mpg, y = cyl)) + geom_point() + geom_line()
# "ggplot2 line chart {N}"
ggplot(mtcars, aes(x = mpg, y = cyl)) + geom_line() + geom_point()I also asked Thomas if he thought ggplot2 would want to be in charge of registering an S3 method for some kind of ark S3 generic that could provide a "plot kind name", but he thought it would just be best if we kept that all here. He liked the ethos of this feature, but thought it would be inappropriate for ggplot2 itself to try and simplify a (possibly very complex) plot down to a single plot kind, which feels reasonable.
| let info = stored_metadata.get(id); | ||
|
|
||
| let plot_metadata = match info { | ||
| Some(info) => PlotMetadata { | ||
| name: info.name.clone(), | ||
| kind: info.kind.clone(), | ||
| execution_id: info.execution_id.clone(), | ||
| code: info.code.clone(), | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any reason you need a local version of PlotMetadataInfo over just storing PlotMetadatas in the hash map directly?
|
|
||
| #[tracing::instrument(level = "trace", skip_all, fields(id = %id))] | ||
| fn process_new_plot_jupyter_protocol(&self, id: &PlotId) { | ||
| fn process_new_plot_jupyter_protocol(&self, id: &PlotId, execution_context: Option<(String, String)>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please reformat this file? I get diffs when I save due to reformatting.
|
|
||
| // Extract execution context before req is consumed | ||
| let execution_id = req.originator.header.msg_id.clone(); | ||
| let code = req.request.code.clone(); | ||
|
|
||
| // Check for pending graphics updates | ||
| // (Important that this occurs while in the "busy" state of this ExecuteRequest | ||
| // so that the `parent` message is set correctly in any Jupyter messages) | ||
| graphics_device::on_did_execute_request(); | ||
| graphics_device::on_did_execute_request(execution_id, code); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would you feel about a push model where handle_execute_request() pushes the active request's execution_id and code to the graphics device side via a new graphics_device::on_execute_request() hook?
i.e. in handle_execute_request() after this
// Save `ExecuteCode` request so we can respond to it at next prompt
self.active_request = Some(ActiveReadConsoleRequest {
exec_count,
request: exec_req,
originator,
reply_tx,
});
you'd also call graphics_device::on_execute_request() to push the active request's information over.
My thought was that if you did this, then we could remove the awkward code around sometimes having the execution_id and code being passed through process_changes() and sometimes needing to go request it from RMain.
If this idea works out, then DEVICE_CONTEXT would always have an up to date execution_id and code from the graphics_device::on_execute_request() hook and I think it would simplify the model a good bit.
(The way this works right now is what took the most time for me to review and understand)
| file <- paste0("render-", id, ".", format) | ||
| file.path(directory, file) | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is kind of a personal request, but would you mind if we isolated this code in graphics-kind.R or something like that?
I like that graphics.R is currently just about the main flow of handling the graphics devices
I have a feeling this bit of code might require a few rounds of iteration / might be a common place we have to update in the future, so it would be nice to have it tucked away in its own file (for some reason that makes it easier for me to reason about).
| #' 1. Check .Last.value for high-level plot objects (ggplot2, lattice) | ||
| #' 2. Check recording's display list for base graphics patterns | ||
| #' 3. Fall back to generic "plot" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the idea is that for ggplot2, the display list isn't really "rich" enough to give you all the details you need to come up with a good name? And instead you ideally need the plot object?
| # Check for grid graphics (ggplot2, lattice) | ||
| if (any(grepl("^L_", call_names))) { | ||
| return("grid") | ||
| } | ||
|
|
||
| # Check for base graphics | ||
| if (any(grepl("^C_", call_names))) { | ||
| return("base") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like just plot is more useful than these?
Co-authored-by: Davis Vaughan <davis@rstudio.com>
Adds an implementation of a method to get a plot's metadata, including a derived unique name and the code that was executed to create the plot.