bokeh: How to export a grid to png with given size? - bokeh

I prepared some bokeh plots to display as html.
To this end I prepared a gridplot containing the subplots, the legends and some headings. This all displays extremely nice in HTML and with sizing_mode='stretch_width' it's even kind of responsive.
webpage = gridplot([[header_col],[panel_grid_plot]], toolbar_location=None, sizing_mode='stretch_width')
show(webpage)
Now I also want to export this "webpage" to a PNG. To this end, I use
export_png(webpage, filename= png_filename, width=1800)
Unfortunately, the width parameter is ignored as the webpage is an object of type gridbox and not of type Plot. (This is checked in the bokeh/io/export.py in the method def get_layout_html())
The output is a png of a width of 800px which is kind of useless as the actual information is crushed (while the legends are nicely scaled):
Any ideas how to set the width of my PNG export to useful values?
Is there a way to convert a gridboxto a Plot?
Thanx!

You should've received a warning saying that the width argument will be ignored since you're passing into export_png something that's not a plot.
A way of achieving what you want:
webpage = gridplot(..., sizing_mode='stretch_width')
webpage.width = 1800
export_png(webpage)

Related

Create a carousel in Rmarkdown?

Is there any quick and easy way to create a simple carousel in an Rmarkdown doc?
What I know so far
I found slickr but run into errors setting options and knitting (the errors could be specific to me / mac - I am not sure at this point).
I believe it would be possible to hard code html/javascript into the RMarkdown doc i.e. the same way a carousel would be done in any other (regular) html document (i.e. using the html code here)- but I wonder if there's a native (R) way?
Example use
In my particular use case, I'm trying to display multiple complicated ggplots which are each sufficiently complex to make them require their own space (i.e. not faceted or grid.arrange as the size of each plot will get too small to read
Notes
Here is the slickr code I tried
library(texPreview)
library(slickR)
objpath <- file.path(getwd(),"slickr_files/figure-html")
if(!dir.exists(objpath)) { dir.create(objpath,recursive = TRUE) }
tex_opts$set(
fileDir = objpath, # path to save output
returnType = 'html', # return images ready for html
imgFormat = 'png' # return png images
)
knitr::kable(mtcars,'latex') %>%
texPreview::tex_preview(stem = 'kable-1')
# ! LaTeX Error: File `standalone.cls' not found.
A side note, if there's a better way of providing many (e.g. > 3) large, detailed plots that doesn't involve faceting, grid.arrange, or (my current preferred option) tabbing, please give a suggestion as a comment
The example works fine for me. Be sure to save your plots in the folder slickr_files/figure-html.
Then run:
```{r}
slickR::slickR(
list.files(objpath,full.names = TRUE,pattern = 'png'),
height = 200,
width = '95%')
```

R/SparkR on Apache Zeppelin: how to set the plot size?

I run a SparkR notebook within Apache Zeppelin successfully. However, when I create plots (standard R plots, not ggplot), I wanna control the size of the figure, i.e. width and height. Any idea?
Btw, I use livy, so my snippets look like:
%livy2.sparkr
x = rnorm(10)
plot(x)
Try to change the width of your paragraph
Unfortunately livy.sparkr, use to render every plot in a png image as shown here and report here, you can however increase your plot image by saving the image and display it as an img html tag as show on this post.
to do the trick :
set.seed(42)
# create your plot and save it into a png
png("/tmp/myplot.png")
plot(rnorm(10))
dev.off() # Close device
# get base64 of the image for display in html
printImageURI<-function(file,width=1000,height=1000){
uri=image_uri(file)
file.remove(file)
cat(sprintf("%%html <img width='%ipx' height='%ipx' src=\"%s\" />\n",width,height,uri))
}
printImageURI("/tmp/myplot.png",700,800)

What is a simple way to thumbnail some plots in R Markdown/knitr?

I am using R Markdown with knitr in R Studio to create and update a simple project website to keep my colleagues up to speed with a data analysis model I am building. There are some plots on the page, which (for smaller plots) so far has worked nicely, they can see the code and the results in the same place.
However, some plots have grown very large (and must remain large to allow quick side-by-side comparison of models), and don't fit on the page very well. I've used separately uploaded pdfs (with a link on the page) for some of them. It would be nicer if there was a simple way of generating thumbnails of some of these plots, so that the user can view a small plot image, click on it and then inspect the much larger image in detail. However, if it takes a lot of manual scripting for each plot instance, I'd rather not waste time on it and just upload the couple of pdfs. A similar question here talks about package, knitrbootsrap, but I don't want to thumbnail all my plots, just a select few. The package seems to use Magnific popup, but integrating it myself in a Markdown page seems like a hassle(?). I didn't find anything in the R Markdown reference guide. Of course a one way would be to generate two plots, one tiny, which is shown, and link it to another, larger plot image/pdf that is uploaded separately - but a simpler, more automatic way would be desireable.
Hence the question - is there a simpler way to generate clickable plot thumbnails in R Markdown?
So, this is what I came up with. Add a plot hook, so that you generate a full-resolution pdf image before generating a small image in the chunk:
allow_thumbnails <- function(x, options) {
if (!is.null(options$thumb)) {
filename <- sprintf("%s.full.pdf", strsplit(basename(x), "\\.")[[1]][1])
absolute_path <- file.path(dirname(x), filename)
# generate the full resolution pdf
pdf(absolute_path, width = options$thumb$width, height = options$thumb$height)
eval(parse(text = options$code))
dev.off()
# add an html link to the low resolution png
options$fig.link = absolute_path
}
knitr:::hook_plot_md_base(x, options)
}
And then in the Rmd file, I define the size of the full-resolution image using the thumb argument:
```{r init}
knit_hooks$set(plot = allow_thumbnails)
```
```{r my_large_plot, fig.width = 15, fig.height = 15, thumb = list(width = 45, height = 45)}
my_large_plot()
```
This generates an html file with a clickable png that takes you to the pdf.

Can transparency be used with PostScript/EPS?

I am trying to save an R plot as an EPS file but I have a problem with the following component of the plot - the gray transparent polygon (transparent black = gray effect):
polygon(x.polygon, y.polygon.6, col="#00000022", border=NA)
This line of code works fine when saving the plot as PDF but not as EPS. Looks like EPS does not support transparency? What other choice would I have?
Here is the code for the full plot:
postscript(file="Figure.eps", width=5.5, height=5.5, onefile=F, horizontal=F)
ts(t(data.frame(initial_timepoint, second_timepoint, third_timepoint, final_timepoint)))->obj
obj[,-c(3,7)]->obj1
plot(obj1, plot.type="single", lwd=0.6, xaxs="i",yaxs="i",xlab="",ylab="LV ejection fraction (%)",xaxt='n',yaxt='n',ylim=c(0,70),col="black")
axis(1, at=c(1,2,3,4), labels=c("1","2","3","4"),cex.axis=1)
axis(2, at=seq(0,70,10), labels=c("0%","10%","20%","30%","40%","50%","60%","70%"),cex.axis=1, las=1)
abline(v=c(2,3),lwd=0.6,lty=2)
stderr <- function(x) sqrt(var(x,na.rm=TRUE)/length(na.omit(x)))
avg<-c(mean(initial_timepoint,na.rm=T), mean(second_timepoint,na.rm=T), mean(third_timepoint,na.rm=T), mean(final_timepoint,na.rm=T))
err<-c(stderr(initial_timepoint), stderr(second_timepoint), stderr(third_timepoint), stderr(final_timepoint))
my.count <- c(1,2,3,4)
my.count.rev <- c(4,3,2,1)
y.polygon.6 <- c((avg+err*1.96)[my.count],(avg-err*1.96)[my.count.rev])
x.polygon <- c(my.count, my.count.rev)
polygon(x.polygon, y.polygon.6, col="#00000022", border=NA)
lines(avg,col="black",lwd=0.8,lty=3)
lines((avg+err*1.96),lwd=0.8,lty=3)
lines((avg-err*1.96),lwd=0.8,lty=3)
dev.off()
Although the EPS format does not natively support semi-transparency, it is still possible to use cairo_ps(), that one automatically rasterizes semi-transparent areas, and the resolution at which it does this can be controlled with the argument fallback_resolution :
cairo_ps(file = "test.eps", onefile = FALSE, fallback_resolution = 600)
qplot(Sepal.Length, Petal.Length, data = iris, color = Species, size = Petal.Width, alpha = I(0.7))
dev.off()
All the non-semi-transparent areas then nicely stay as vector graphics.
Or even shorter you can also use :
ggsave("filename.eps", device=cairo_ps, fallback_resolution = 600)
Or use the functions to export to eps using the new export package, which just came out on CRAN :
install.packages("export")
library(export)
graph2eps("filename.eps", fallback_resolution = 600)
That package also supports a number of other export formats, including Powerpoint (graph2ppt), see ?graph2vector, which also retains semi-transparency...
The PostScript graphics model itself does not support general transparency of page elements at all. (Hence it is also not possible for EPS.) PostScript colors are all fully opaque.
An object drawn on top of another object would overwrite and cover all lower objects with its own color leaving no room for transparent effects. (If you see something that looks like transparency overlays in a PostScript viewer or printout, then that was only emulated transparency, by flattening the two (or more) respective objects into one single rasterized area creating the illusion of transparency.)
The PDF graphics model is based on PostScript's, but it extends it in various aspects, adding several new features. One of these is real transparency for complete objects.
After Adobe added transparency to PDF, it also created an extension [1] to the existing PostScript language that was able to include code in PS programs which would add transparency to PDFs created from this PostScript via Distiller. However, when rendering on screen or printing on paper this same original PostScript including this same code, that additional transparency would not appear, and the top (transparent in PDF) object would still overwrite the bottom ones when directly used in PostScript.
What other choice would I have?
Various:
Use PDF only. Don't use EPS.
If you must use EPS, use a two-step process:
Create the PDF first.
Then convert from the (transparency-enabled) PDF to EPS, 'flattening' the transparent elements into rasterized areas which emulate the desired transparency effect.
[1] The name of this extension is called pdfmark. With the help of the pdfmark operator one can also add other features to PostScript code which only materialize when distilling this PostScript to PDF: annotations, interactive form fields and buttons, metadata, hyperlinks, and more. All these elements would not have any effect in the direct PostScript rendering on screen or on paper prints.
Instead of making gray out of transparent black, I recommend using the gray.colors() function in R to generate the shades of gray you need. Then you get the look you want in your .eps file without a problem.
This is working fine for me to save .eps files
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.use('PS')
legend = plt.legend(loc="upper left", edgecolor="black")
legend.get_frame().set_alpha(None)
legend.get_frame().set_facecolor((0, 0, 0, 0))
plt.show()
plt.savefig('fig1.eps', format='eps')

convert textGrob to imageGrob/rasterGrob?

Apologies if this is very straightforward. Actually I hope it will be!
I am trying to dynamically create images from text which I can then resize and plot (either stretched or squashed) to produce a motif-type graph.
I started out using images (which I'd generated using png() and ggplot()) and plotting them as annotation_custom()
require(ggplot2)
require(grid)
require(gridExtra)
qplot(c(0,10),c(0,10)) +
annotation_custom(rasterGrob(image=readPNG("1999.png"),x=0,y=0,height=1,width=1,just=c("left","bottom")),
xmin=0,xmax=5,ymin=0,ymax=7.5)
to produce:
This is fine, but it's awkward to create the images dynamically if they are not the same size, using png(), plus it's clunky to persist them to file, so I tried to see if I could use a textGrob:
myText<-"1000"
myTextGrob<-textGrob(myText,just=c("left","bottom"),gp=gpar(fontsize="100",col="red",fontfamily="Showcard Gothic"))
qplot(c(0,10),c(0,10))+annotation_custom(myTextGrob,0,0,0,0)
and got this, which is fine, except....
...it doesn't seem possible to stretch & skew it in the same way as a rasterGrob so my question is - is it possible to create the textGrob and coerce it to a rasterGrob? Or is there another solution which will let me skew/stretch the textGrob?
Thanks in advance!
It doesn't seem easy without creating temporary files. Instead of raster files, you might use vector paths with the grImport package. There are two options to import text,
as a path; it works (example below), but there's no obvious way to bypass the ps to xml conversion step with intermediate files
as a text string; the xml is much shorter in this case, and could be created directly from R, but unfortunately I couldn't find a way to transform the two axes independently.
library(grImport)
scale_text <- function(text="hello world", scale=4, tmp=tempfile()){
tmp.ps <- paste0(tmp, ".ps")
tmp.xml <- paste0(tmp, ".xml")
string.ps <- paste0('%!PS
/Courier % name the desired font
20 selectfont % choose the size in points and establish
% the font as the current one
1 ', scale, ' scale % scale axis
72 500 moveto % position the current point at
% coordinates 72, 500 (the origin is at the
% lower-left corner of the page)
(', text, ') show % stroke the text in parentheses
showpage % print all on the page
')
cat(string.ps, file=tmp.ps)
PostScriptTrace(tmp.ps, tmp.xml)
readPicture(tmp.xml)
}
hello <- scale_text()
grid.newpage()
grid.picture(hello)

Resources