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

Incorrect height for the richtext_grob object #6

Closed
jokergoo opened this issue Feb 4, 2020 · 9 comments
Closed

Incorrect height for the richtext_grob object #6

jokergoo opened this issue Feb 4, 2020 · 9 comments

Comments

@jokergoo
Copy link

jokergoo commented Feb 4, 2020

Hi, thanks for developing this package for better configuring text under grid system! I am developing a package called ComplexHeatmap and I want to support gridtext with it. I found when rot is set to e.g. 30 in richtext_grob() function, the height calculated by grobHeight() is not identical to the height (or the width if the rotation is 90 degrees) of the longest text.

I attached an example here. In the following plot, the height of the rectangles should be the same as the height of September, regardless of the rotation of the text. As a comparison, I also attached plots if using textGrob() function and you can see the height of rectangles is exactly the same as September.

I haven't tested grobWidth() on richtext_grob object, but I guess it should be similar.

Thanks!

grid.newpage()
rot = seq(0, 360, by = 30); rot = rot[rot != 360]
pushViewport(viewport(layout = grid.layout(nrow = 4, ncol = 3)))
for(i in seq_along(rot)) {
	gb = richtext_grob(month.name, x = 1:12, default.units = "native", box_gp = gpar(col = "red"), rot = rot[i])
	# gb = textGrob(month.name, x = 1:12, default.units = "native", rot = rot[i])
	pushViewport(viewport(layout.pos.col = (i-1) %% 3 + 1, layout.pos.row = ceiling(i/3)))
	pushViewport(viewport(xscale = c(0, 13), height = grobHeight(gb), width = unit(0.8, "npc")))
	grid.rect()
	grid.text(paste0("rot = ", rot[i]), x = unit(0.5, "npc"), y = unit(1, "npc"), just = c(0.5, 0))
	grid.draw(gb)
	popViewport()
	popViewport()
}
popViewport()

image

image

@clauswilke
Copy link
Collaborator

Not sure what exactly is going on in your code. I'll have to ask you to try to figure out the specific problem in more detail. The moment you start pushing viewports inside viewports and then try to calculate the width or height of a grob, things can go wrong, in particular when you're rotating grobs and using different types of units along x and y. (For a possibly somewhat related problem, see here: r-lib/gtable#83)

In my testing code, the width and height are calculated correctly.

library(grid)
library(gridtext)

f <- function(rot) {
  gb = richtext_grob(
    month.name, x = ((3:14)+.5)/18,
    box_gp = gpar(col = "red"),
    rot = rot
  )

  grid.newpage()
  grid.draw(
    rectGrob(height = grobHeight(gb), width = grobWidth(gb))
  )
  grid.draw(gb)
}

f(30)

f(45)

f(90)

f(-45)

Created on 2020-02-04 by the reprex package (v0.3.0)

@jokergoo
Copy link
Author

jokergoo commented Feb 6, 2020

The reason is I want to create a viewport with the same height as the richtext_grob. Let's say, when I implement the heatmap package, I want to create a viewport to put the column names in, thus, I need the height of this viewport to have the same height of the column names, also when they are rotated.

Since the texts have absolute width and height, does it matter to calculate the size inside or outside a certain viewport?

A strange thing is when I run your example code in a completely new R session, there is still empty space above and below the text, no matter I directly plot it in an interactive window or save into a PDF file.

f(45)

image

But, it seems it only happens on my laptop (Macbook). If I run the same code in other PC, it is fine:

image

@jokergoo
Copy link
Author

jokergoo commented Feb 6, 2020

Also, I think the height of the grob is calculated from yext from gb$childrens. This value is different from machines with the same grob.

E.g. for following grob where text is rotated with 45 degrees:

gb = richtext_grob(
	month.name, x = ((3:14)+.5)/18,
	box_gp = gpar(col = "red"),
	rot = 45
)

and I check yext for the first children of gb (I think it is for January):

gb$children[[1]]$yext

On my laptop:

[1] 10.89174 41.19233 19.40884 49.70943

On another PC:

[1] -11.15314  19.14218 -19.14218  11.15314

On Rstudio server:

[1] -19.42964  10.91254 -10.91254  19.42964

@clauswilke
Copy link
Collaborator

I'm not sure why you get this wide range of different numbers for yext, but in any case, only the difference between the largest and the smallest numbers matters, and the difference is approximately the same in your three examples, at least within the expected accuracy of font metrics reported by different graphics devices.

library(gridtext)
library(grid)

diff(range(c(10.89174, 41.19233, 19.40884, 49.70943)))
#> [1] 38.81769
diff(range(c(-11.15314, 19.14218, -19.14218, 11.15314)))
#> [1] 38.28436
diff(range(c(-19.42964, 10.91254, -10.91254, 19.42964)))
#> [1] 38.85928

png()
gb <- richtext_grob(
  month.name, x = ((3:14)+.5)/18,
  box_gp = gpar(col = "red"),
  rot = 45
)

gb$children[[1]]$yext
#> [1] -19.09486  11.20573 -11.20573  19.09486
diff(range(gb$children[[1]]$yext))
#> [1] 38.18972
dev.off()
#> quartz_off_screen 
#>                 2

pdf()
gb <- richtext_grob(
  month.name, x = ((3:14)+.5)/18,
  box_gp = gpar(col = "red"),
  rot = 45
)

gb$children[[1]]$yext
#> [1] -19.14218  11.15314 -11.15314  19.14218
diff(range(gb$children[[1]]$yext))
#> [1] 38.28437
dev.off()
#> quartz_off_screen 
#>                 2

Created on 2020-02-06 by the reprex package (v0.3.0)

A couple of additional comments:

  1. In general, grob width and height are only properly defined when a grob is placed into its final viewport. This creates an identifiability problem when you want to create a viewport the size of a grob. I would recommend against this approach, even if it seems that it should be possible.

  2. I'm not discounting the possibility that there is something wrong with my code, but I'll need a very clear and minimal reprex that shows what exactly the problem is. As far as I can tell, grob heights are calculated correctly when gridtext is used inside ggplot, on different platforms.

  3. Please use the reprex package to create examples, to make sure we know exactly what the state of the graphics device is when specific calls are made, and in what order things are executed.

Thanks!

@jokergoo
Copy link
Author

jokergoo commented Feb 6, 2020

Thanks for your reply. Now I tried to set align_widths argument to TRUE and FALSE separately and I convert the height to mm unit for easy reading. In theory, the three numbers in the following code should be all the same, but still on my Macbook, setting align_widths or not gives different height for the text.

On other machines, the three numbers are identical.

library(gridtext)
library(grid)
gb = richtext_grob(month.name, rot = 90, align_widths = FALSE)
convertHeight(grobHeight(gb), "mm")
#> [1] 27.29755859375mm
gb = richtext_grob(month.name, rot = 90, align_widths = TRUE)
convertHeight(grobHeight(gb), "mm")
#> [1] 20.7077799479167mm

# if only September
gb = richtext_grob(month.name[9], rot = 90, align_widths = FALSE)
convertHeight(grobHeight(gb), "mm")
#> [1] 20.7077799479167mm

Created on 2020-02-06 by the reprex package (v0.3.0)

@clauswilke
Copy link
Collaborator

This is what I see (on OS X). Could you run the reprex with si = TRUE, so we can compare the session info?

library(gridtext)
library(grid)
gb = richtext_grob(month.name, rot = 90, align_widths = FALSE)
convertHeight(grobHeight(gb), "mm")
#> [1] 20.7077799479167mm

gb = richtext_grob(month.name, rot = 90, align_widths = TRUE)
convertHeight(grobHeight(gb), "mm")
#> [1] 20.7077799479167mm

# if only September
gb = richtext_grob(month.name[9], rot = 90, align_widths = FALSE)
convertHeight(grobHeight(gb), "mm")
#> [1] 20.7077799479167mm

Created on 2020-02-06 by the reprex package (v0.3.0)

Session info
devtools::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value                       
#>  version  R version 3.6.0 (2019-04-26)
#>  os       macOS Mojave 10.14.6        
#>  system   x86_64, darwin15.6.0        
#>  ui       X11                         
#>  language (EN)                        
#>  collate  en_US.UTF-8                 
#>  ctype    en_US.UTF-8                 
#>  tz       America/Chicago             
#>  date     2020-02-06                  
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package     * version    date       lib source        
#>  assertthat    0.2.1      2019-03-21 [1] CRAN (R 3.6.0)
#>  backports     1.1.5      2019-10-02 [1] CRAN (R 3.6.0)
#>  callr         3.4.1      2020-01-24 [1] CRAN (R 3.6.0)
#>  cli           2.0.1      2020-01-08 [1] CRAN (R 3.6.0)
#>  crayon        1.3.4      2017-09-16 [1] CRAN (R 3.6.0)
#>  desc          1.2.0      2018-05-01 [1] CRAN (R 3.6.0)
#>  devtools      2.2.1      2019-09-24 [1] CRAN (R 3.6.0)
#>  digest        0.6.23     2019-11-23 [1] CRAN (R 3.6.0)
#>  ellipsis      0.3.0      2019-09-20 [1] CRAN (R 3.6.0)
#>  evaluate      0.14       2019-05-28 [1] CRAN (R 3.6.0)
#>  fansi         0.4.1      2020-01-08 [1] CRAN (R 3.6.0)
#>  fs            1.3.1      2019-05-06 [1] CRAN (R 3.6.0)
#>  glue          1.3.1      2019-03-12 [1] CRAN (R 3.6.0)
#>  gridtext    * 0.1.0.9000 2020-02-03 [1] local         
#>  highr         0.8        2019-03-20 [1] CRAN (R 3.6.0)
#>  htmltools     0.3.6      2017-04-28 [1] CRAN (R 3.6.0)
#>  knitr         1.26       2019-11-12 [1] CRAN (R 3.6.0)
#>  magrittr      1.5        2014-11-22 [1] CRAN (R 3.6.0)
#>  markdown      1.1        2019-08-07 [1] CRAN (R 3.6.0)
#>  memoise       1.1.0      2017-04-21 [1] CRAN (R 3.6.0)
#>  pkgbuild      1.0.6      2019-10-09 [1] CRAN (R 3.6.0)
#>  pkgload       1.0.2      2018-10-29 [1] CRAN (R 3.6.0)
#>  prettyunits   1.1.1      2020-01-24 [1] CRAN (R 3.6.0)
#>  processx      3.4.1      2019-07-18 [1] CRAN (R 3.6.0)
#>  ps            1.3.0      2018-12-21 [1] CRAN (R 3.6.0)
#>  R6            2.4.1      2019-11-12 [1] CRAN (R 3.6.0)
#>  Rcpp          1.0.3      2019-11-08 [1] CRAN (R 3.6.0)
#>  remotes       2.1.0      2019-06-24 [1] CRAN (R 3.6.0)
#>  rlang         0.4.3      2020-01-24 [1] CRAN (R 3.6.0)
#>  rmarkdown     1.15       2019-08-21 [1] CRAN (R 3.6.0)
#>  rprojroot     1.3-2      2018-01-03 [1] CRAN (R 3.6.0)
#>  sessioninfo   1.1.1      2018-11-05 [1] CRAN (R 3.6.0)
#>  stringi       1.4.5      2020-01-11 [1] CRAN (R 3.6.0)
#>  stringr       1.4.0      2019-02-10 [1] CRAN (R 3.6.0)
#>  testthat      2.3.1      2019-12-01 [1] CRAN (R 3.6.0)
#>  usethis       1.5.1      2019-07-04 [1] CRAN (R 3.6.0)
#>  withr         2.1.2      2018-03-15 [1] CRAN (R 3.6.0)
#>  xfun          0.12       2020-01-13 [1] CRAN (R 3.6.0)
#>  xml2          1.2.2      2019-08-09 [1] CRAN (R 3.6.0)
#>  yaml          2.2.0      2018-07-25 [1] CRAN (R 3.6.0)
#> 
#> [1] /Library/Frameworks/R.framework/Versions/3.6/Resources/library

@jokergoo
Copy link
Author

jokergoo commented Feb 7, 2020

Hi, I updated the version of gridtext to 0.1.0.9000 (the github version. The previous one installed on my laptop was 0.1.0, from CRAN). Now everything is fine (also the in the plots).

library(gridtext)
library(grid)
gb = richtext_grob(month.name, rot = 90, align_widths = FALSE)
convertHeight(grobHeight(gb), "mm")
#> [1] 20.7077799479167mm

gb = richtext_grob(month.name, rot = 90, align_widths = TRUE)
convertHeight(grobHeight(gb), "mm")
#> [1] 20.7077799479167mm

# if only September
gb = richtext_grob(month.name[9], rot = 90, align_widths = FALSE)
convertHeight(grobHeight(gb), "mm")
#> [1] 20.7077799479167mm

Created on 2020-02-07 by the reprex package (v0.3.0)

Session info
devtools::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value                       
#>  version  R version 3.6.2 (2019-12-12)
#>  os       macOS Mojave 10.14.2        
#>  system   x86_64, darwin15.6.0        
#>  ui       X11                         
#>  language (EN)                        
#>  collate  en_GB.UTF-8                 
#>  ctype    en_GB.UTF-8                 
#>  tz       Europe/Berlin               
#>  date     2020-02-07                  
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package     * version    date       lib source                            
#>  assertthat    0.2.1      2019-03-21 [1] CRAN (R 3.6.0)                    
#>  backports     1.1.5      2019-10-02 [1] CRAN (R 3.6.0)                    
#>  callr         3.4.0      2019-12-09 [1] CRAN (R 3.6.0)                    
#>  cli           2.0.1      2020-01-08 [1] CRAN (R 3.6.0)                    
#>  crayon        1.3.4      2017-09-16 [1] CRAN (R 3.6.0)                    
#>  desc          1.2.0      2018-05-01 [1] CRAN (R 3.6.0)                    
#>  devtools      2.2.1      2019-09-24 [1] CRAN (R 3.6.1)                    
#>  digest        0.6.23     2019-11-23 [1] CRAN (R 3.6.0)                    
#>  ellipsis      0.3.0      2019-09-20 [1] CRAN (R 3.6.0)                    
#>  evaluate      0.14       2019-05-28 [1] CRAN (R 3.6.0)                    
#>  fansi         0.4.1      2020-01-08 [1] CRAN (R 3.6.0)                    
#>  fs            1.3.1      2019-05-06 [1] CRAN (R 3.6.0)                    
#>  glue          1.3.1      2019-03-12 [1] CRAN (R 3.6.0)                    
#>  gridtext    * 0.1.0.9000 2020-02-07 [1] Github (wilkelab/gridtext@5cc4b40)
#>  highr         0.8        2019-03-20 [1] CRAN (R 3.6.0)                    
#>  htmltools     0.4.0      2019-10-04 [1] CRAN (R 3.6.0)                    
#>  knitr         1.26       2019-11-12 [1] CRAN (R 3.6.0)                    
#>  magrittr      1.5        2014-11-22 [1] CRAN (R 3.6.0)                    
#>  markdown      1.1        2019-08-07 [1] CRAN (R 3.6.0)                    
#>  memoise       1.1.0      2017-04-21 [1] CRAN (R 3.6.0)                    
#>  pkgbuild      1.0.6      2019-10-09 [1] CRAN (R 3.6.0)                    
#>  pkgload       1.0.2      2018-10-29 [1] CRAN (R 3.6.0)                    
#>  prettyunits   1.0.2      2015-07-13 [1] CRAN (R 3.6.0)                    
#>  processx      3.4.1      2019-07-18 [1] CRAN (R 3.6.0)                    
#>  ps            1.3.0      2018-12-21 [1] CRAN (R 3.6.0)                    
#>  R6            2.4.1      2019-11-12 [1] CRAN (R 3.6.0)                    
#>  Rcpp          1.0.3      2019-11-08 [1] CRAN (R 3.6.0)                    
#>  remotes       2.1.0      2019-06-24 [1] CRAN (R 3.6.0)                    
#>  rlang         0.4.2      2019-11-23 [1] CRAN (R 3.6.0)                    
#>  rmarkdown     2.0        2019-12-12 [1] CRAN (R 3.6.0)                    
#>  rprojroot     1.3-2      2018-01-03 [1] CRAN (R 3.6.0)                    
#>  sessioninfo   1.1.1      2018-11-05 [1] CRAN (R 3.6.0)                    
#>  stringi       1.4.5      2020-01-11 [1] CRAN (R 3.6.0)                    
#>  stringr       1.4.0      2019-02-10 [1] CRAN (R 3.6.0)                    
#>  testthat      2.3.1      2019-12-01 [1] CRAN (R 3.6.1)                    
#>  usethis       1.5.1      2019-07-04 [1] CRAN (R 3.6.0)                    
#>  withr         2.1.2      2018-03-15 [1] CRAN (R 3.6.0)                    
#>  xfun          0.11       2019-11-12 [1] CRAN (R 3.6.0)                    
#>  xml2          1.2.2      2019-08-09 [1] CRAN (R 3.6.1)                    
#>  yaml          2.2.0      2018-07-25 [1] CRAN (R 3.6.0)                    
#> 
#> [1] /Library/Frameworks/R.framework/Versions/3.6/Resources/library

The f() function defined before:

f <- function(rot) {
  gb = richtext_grob(
    month.name, x = ((3:14)+.5)/18,
    box_gp = gpar(col = "red"),
    rot = rot
  )

  grid.newpage()
  grid.draw(
    rectGrob(height = grobHeight(gb), width = grobWidth(gb))
  )
  grid.draw(gb)
}
f(45)

Screenshot 2020-02-07 at 15 41 35

@jokergoo jokergoo closed this as completed Feb 7, 2020
@jokergoo
Copy link
Author

jokergoo commented Feb 7, 2020

Now I re-installed the version 0.1.0 from CRAN, everything is also working. I don't know why, but it works.

Thank you for your help!

@clauswilke
Copy link
Collaborator

I'm glad things work now. 0.1.0 and 0.1.0.9000 are essentially the same. It would have been strange if one worked and the other didn't.

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

No branches or pull requests

2 participants