Skip to content
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

Plots are rendered differently on different monitors #7028

Closed
3 of 4 tasks
Mashin6 opened this issue Jun 2, 2020 · 15 comments
Closed
3 of 4 tasks

Plots are rendered differently on different monitors #7028

Mashin6 opened this issue Jun 2, 2020 · 15 comments
Assignees

Comments

@Mashin6
Copy link

Mashin6 commented Jun 2, 2020

I originally reported the problem in RMarkdown project 4521 and this might be issue related to 1827

System details

RStudio Edition : Desktop
RStudio Version : 1.3.959
OS Version      : macOS 10.14.6
R Version       : 3.6.1

Steps to reproduce the problem

  1. In R Markdown document create a plot that has many labels
  2. Move R Studio window to different monitor
  3. Slightly resize R Studio window
  4. Rerun plot code

Describe the problem in detail

RStudio renders figures inconsistently depending on which monitor is the code executed. When I run code chunk on retina display the text in the figure is rendered smaller, but when I move the window to my second 2K display (ThinkVision 23.8'' P24H-10 QHD) all the labels and margins are rendered way larger, which dramatically change how the figure looks like.

Here is a sample code (cowplot package is to exaggerate the issue, but it behaves the same when cowplot is deactivated)

{r message=FALSE, warning=FALSE, fig.width = 8, fig.height = 6}
library(tidyverse)
library(cowplot)

data <- data.frame(x = rnorm(999), y = rep(c("a", "b", "c")))

p1 <- p2 <- data %>% ggplot() +
geom_histogram(aes(x = x, fill = y)) +
facet_wrap(vars(y)) +
scale_x_log10() +
labs(title = "Test subtitile")

plot_grid(p1, p1, labels = c("A", "B"), ncol = 1, label_size = 20) +
draw_plot_label("Test main titile", size = 25, x = 0.5, y = 1.015, hjust = 0.5, vjust = 0.5) +
theme(plot.margin = unit(c(1.5,0,0,0), "cm"))

Output 1:1 screenshots:

83458112-df993780-a42f-11ea-95df-9f015dfdd99f

@stale
Copy link

stale bot commented Feb 5, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs, per https://github.com/rstudio/rstudio/wiki/Issue-Grooming. Thank you for your contributions.

@stale stale bot added the stale Issues which have been closed automatically due to inactivitiy. label Feb 5, 2021
@stale
Copy link

stale bot commented Feb 19, 2021

This issue has been automatically closed due to inactivity.

@stale stale bot closed this as completed Feb 19, 2021
@EoinTravers
Copy link

I have the same issue.
I can add the following:

This isn't restricted to ggplot

```{r fig.width=4, fig.height=4}
plot(iris$Sepal.Length, iris$Sepal.Width)
```

Retina display:

image

External display:

image

HTML Output Matches External Display

When the document is knit to html, using the default options, the generated images are small, the same as those seen on the external display.

fig.retina

Kniting with default settings, the knitr fig.retina parameter is set to 2.

knitr::opts_chunk$get('fig.retina')
## [1] 2

Changing this in the yaml

---
title: "Figure Problems"
output: 
  html_document:
    fig_retina: 1
---

is registered...

knitr::opts_chunk$get('fig.retina')
## [1] 1

...but doesn't change the size of the output figures, suggesting the issue might be somewhere in the knitr or rmarkdown packages.

Changing the setting for a specific chunk also has no effect on the output.

```{r fig.width=4, fig.height=4, fig.retina=2}
knitr::opts_chunk$get('fig.retina')
plot(iris$Sepal.Length, iris$Sepal.Width)
```

System Info

R version 4.0.3 (2020-10-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Big Sur 10.16
RStudio: 1.4.1103 (desktop)

@cderv
Copy link
Collaborator

cderv commented Jan 10, 2022

I don't know if there is an issue with RStudio or not. Regarding last comment, I answered here rstudio/rmarkdown#1827 (comment) on how fig.retina plays out to me.

@EoinTravers
Copy link

This discussion on twitter is relevant to this issue, and includes this nice but hacky fix.

@Mashin6
Copy link
Author

Mashin6 commented Jan 12, 2022

Referencing related issues #2098 and #7892. (thanks @cderv for looking those up)

@cderv
Copy link
Collaborator

cderv commented Jan 12, 2022

@ronblum would it be possible to reopen this issue closed by stale bot ? Seems still an issue and related to a few others about resolution of figure in Notebook . Thanks!

@ronblum ronblum removed the stale Issues which have been closed automatically due to inactivitiy. label Jan 12, 2022
@ronblum ronblum reopened this Jan 12, 2022
@jeffvroom
Copy link
Contributor

I see a few problems that mostly center around [this code] (

width = width * pixelRatio,
height = height * pixelRatio,
units = units,
res = 96 * pixelRatio
) where it sets up the device to render the graph to a PNG image.

  1. It hardcodes the dpi used to convert inches to pixels as 96 rather than looking at the dpi parameter (if one is supplied).
  2. It ignores fig.retina if it's being set in the annotations but instead always uses devicePixelRatio that comes from the IDE that gets it from the browser's window.devicePixelRatio. Here is where we get fig.width/height but do not get fig.retina to override the devicePixelRatio.
  3. It multiplies the width and height by devicePixelRatio as well as res and that doubles the effect. So in my test, with fig.width/fig.height = 2", the resulting resolution is 768 that would be 4" on a display with 96 dpi.

In at least one customer situation, it seems like we need a way to disable the effect of the retina, or to at least not double it up because the results of ggplot are not consistent with other graphics they are rendering.

@jeffvroom
Copy link
Contributor

jeffvroom commented Mar 8, 2022

I believe this is where R is computing the scaling factor based on 'res' supplied above:

https://github.com/wch/r-source/blob/2370ec2512d2e78eea678213eb141eae878718c4/src/modules/X11/devX11.c#L3001-L3006

confirming to me that we don't have to do the scaling twice. These particular plots have fixed_width attribute set and the code to render the img tag is here:

if (isFixedSizePlotUrl(plot_.getUrl()))
{
ImageElementEx img = plot_.getElement().cast();
img.getStyle().setProperty("height", "auto");
img.getStyle().setProperty("maxWidth", "100%");

To correct the plot size, the easiest thing would be to just remove the " * pixelRatio" in NotebookPlot.R in all 6 places where it appears. The img tag is already correcting for devicePixelRatio by scaling up the image by that factor.

The downside of that is less clear plot images on retina. The better solution would be to only scale up 'res' (not width and height) and change the img tag to have width=(1/devicePixelRatio)% - i.e. width=50% for retina. That way, we'd have clearer plots. We could continue setting max-width to this value, so the image fits into the console window, even if a larger plot size is specified than will fit in the console or change it to width so the image is clipped if it's too large. I can see advantages either way... if there's other adjacent graphics, it looks wrong to display the wrong size image. - Edit: that doesn't work because that width=50% applies to the window's size, not the image size. There's no way to scale the image by 50% unless we can access to the pixel dimensions of the image.

BTW, I found an easier to way to check the devicePixelRatio used by RStudio is:

.Call("rs_devicePixelRatio")

@ronblum
Copy link
Contributor

ronblum commented Dec 2, 2022

Moving to Cherry Blossom, in order to verify that it's fixed by PR #12324. If it's not, we'll reassign it to the current milestone.

@jonvanausdeln jonvanausdeln self-assigned this Jan 26, 2023
@jonvanausdeln
Copy link

I tried on latest daily, 2023.03.0-daily+280. However, I would like confirmation from @Mashin6 and/or @EoinTravers that this solves their issue.

@Mashin6
Copy link
Author

Mashin6 commented Feb 7, 2023

I played a bit with the latest 2023.03.0-daily+293 and for me the main issue seems to be gone. Figures are rendered with the same proportion of text size, spacings, etc.
However I noticed that at different screen resolutions/scalings the figures are rendered at different pixel dimensions. My suspicion is that the problem is somehow related to non-HiDPI resolutions/monitors.

retina display - all resolutions - figure dimensions 768 × 768 pixels
retina-1512x982

External Monitor - 2560x1140 (native) - figure dimensions 384 × 384 pixels
External-2560x1440

External Monitor - 1280x720 (HiDPI scale) - figure dimensions 768 × 768 pixels
External-1280x720

@jonvanausdeln
Copy link

Thank you @Mashin6! Since the main issue is resolved, I will close out this issue. Would you be able to open a new issue on what you are still experiencing? I would be happy to open if you'd like, I just don't want to miss any details.

@frederikziebell
Copy link

@jeffvroom Is there a way to set the device pixel ratio from a current RStudio session, similar to the .Call you described above to view it?

@kevinushey
Copy link
Contributor

@frederikziebell I suspect not, but you might want to file a separate issue to make sure your request isn't lost.

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

No branches or pull requests

9 participants