Is there a way to read a plot as a matrix of pixels without saving it on disk? - r

I'd like to have an R plot as a matrix of pixels. I can simply save and read it again as a bitmap. But is there a faster way to do this directly without saving the plot first?
library(readbitmap)
tmp = tempfile()
bmp(tmp)
plot(1)
dev.off()
result = read.bitmap(tmp)

Related

Why does my plot of a raster in R blur in saved file?

I'm hoping to export a map with a raster plotted on it as a .pdf or some other vector file. For some reason, when I save it as a .pdf or .ps file, the raster is blurry/fuzzy/smeared and unusable. Any tips for fixing this? A .png saves with the desired resolution, but can't be manipulated layer-by-layer in post-processing.
library(maps)
library(raster)
ra<-raster(nrows=40,ncols=35,xmn=-110,xmx=-75,ymn=7,ymx=47)
ra2 <- rasterize(cbind(runif(1000,min=-109,max=-76),runif(1000,min=8,max=46)), ra,fun=function(x,...)log10(length(x)))
pal <- colorRampPalette(c("grey90","grey40"))
map(database="world",regions=c("US","Mexico","El Salvador","Honduras","Costa Rica","Guatemala","Belize","Nicaragua","Panama"),myborder=0.0000001,xlim=c(-110,-75),ylim=c(0,50))
plot(ra2,add=T,col=pal(7))
Here is a screenshot of the saved .pdf file
Here is a screenshot of the Quartz window with desired resolution
I just found that adding 'useRaster=FALSE' to the plot() function fixes this.
You can use the following code to save high-resolution image as pdf file
pdf(file = "My Plot.pdf",
width = 14, # The width of the plot in inches
height = 8.5) # The height of the plot in inches
pal <- colorRampPalette(c("grey90","grey40"))
map(database="world",regions=c("US","Mexico","El Salvador","Honduras","Costa Rica","Guatemala","Belize","Nicaragua","Panama"),myborder=0.0000001,xlim=c(-110,-75),ylim=c(0,50))
plot(ra2,add=T,col=pal(7))
#Run dev.off() to create the file!
dev.off()

How can I View the output of this animation code in Rstudio

This R code is to create an animated plot, I have run it and it did run but I have not been able to view it. it is said to save it output on pdf file though I saw the file but unable to open it. I got the code at How do I transfer output of animation R package on a beamer frame
because I want to learn how to input R animated plot on latex thus I was given this as an example. can you show me how I can view its output either on Rstudio or where the code saves it to? If you mean that the output can be viewed on pdf that is originally saved to, show me how? I am using Acrobat Reade Dc.
brownianMotion <- function(n=10,xlim=c(-20,20),ylim=c(-20,20),steps=50)
{
x=rnorm(n)
y=rnorm(n)
for (i in 1:steps) {
plot(x,y,xlim = xlim,ylim = ylim)
text(x,y)
# iterate over particles
for(k in 1:n){
walk=rnorm(2); # random move of particle
x[k]=x[k]+walk[1] # new position
y[k]=y[k]+walk[2]
# simple model for preventing a particle from moving past the limits
if(x[k]<xlim[1]) x[k]=xlim[1]
if(x[k]>xlim[2]) x[k]=xlim[2]
if(y[k]<ylim[1]) y[k]=ylim[1]
if(y[k]>ylim[2]) y[k]=ylim[2]
}
}
}
pdf("frames.pdf") # output device and file name
par(xaxs="i", yaxs="i", pty="s") # square plot region
par(mai=c(0.9,0.9,0.2,0.2)) # plot margins
brownianMotion(n=20, steps=400) # 20 particles, 400 time steps
There are two things here :
you need to add dev.off() after plotting so that the current plot is saved to the output device
the loop over step is rewriting the same filename for each plot, so that you end-up in having only the last frame in frames.pdf. Following this tutorial, you should rather write separate pdf files to an output folder, then animate them within LaTeX.
brownianMotion <- function(n=10,xlim=c(-20,20),ylim=c(-20,20),steps=50){
x=rnorm(n)
y=rnorm(n)
for (i in 1:steps) {
pdf(paste0("out/frames", i, ".pdf")) # save frames{i}.pdf to 'out' folder
plot(x,y,xlim = xlim,ylim = ylim)
text(x,y)
dev.off() # Adding dev.off()
...
}
}
par(xaxs="i", yaxs="i", pty="s") # square plot region
par(mai=c(0.9,0.9,0.2,0.2)) # plot margins
if (!dir.exists("out")) dir.create("out") # create 'out' folder if it doesn't exist
brownianMotion(n=20, steps=4) # 20 particles, 4 steps
The out folder will be located where your working directory is (use getwd() to see it).

Can we change the resolution of image within seqtreedisplay() function call?

I am generating tree images with the seqtreedisplay() function from the R package TraMineR but the default resolution is 72 dpi. I need to create 300 dpi image. Is it be possible do it within the seqtreedisplay() function call using like a "res" argument?
Thanks for help
You can control the resolution of the output file produced by the seqtreedisplay function by passing a device.args argument (that will be treated as an element of the ... list).
The device.args argument should be a list of arguments that will be passed to the used device (jpeg when image.format="jpg", and png otherwise).
To get a 300 dpi resolution, you need to set res=300, but also to increase the the width and height.
I illustrate with the mvad data:
data(mvad)
## Defining a state sequence object
mvad.seq <- seqdef(mvad[, 17:86])
## Growing a seqtree using Hamming distances:
seqt <- seqtree(mvad.seq~ male + Grammar + funemp + gcse5eq + fmpr + livboth,
data=mvad, R=1000, pval=0.05, seqdist.arg=list(method="HAM"))
## Generating the plot as a 300 dpi image in mytree.jpg
seqtreedisplay(seqt, filename = "mytree.jpg", type="d", border=NA, image.format = "jpg",
device.args=list(width=480*300/72, height=480*300/72, res=300))
Below is my previous answer that does not work because seqtreedisplay internally first generates texts and plots in bitmap format before saving them in the image.format.
A solution would be to select a vectorial format (e.g. pdf or eps) for the outcome of seqtreedisplay and then to convert this vectorial file into a raster format with the desired resolution.
Assuming you have installed ImageMagick (and Gostscript on which ImageMagick relies to convert to/from pdf or eps), you could use the convert.g function of TraMineRextras for this conversion. I illustrate below using the mvaddata:
## Drawing the tree as a pdf file and converting into jpeg
seqtreedisplay(seqt, filename = "mytree.pdf", type="d", border=NA, image.format = "pdf")
path <- getwd() ## retrieve the path
convert.g(path = path, fileroot = "mytree", from = "pdf", to = "jpeg",
options = "-units PixelsPerInch -density 300x300")
The resulting jpeg file will be in a jpeg subdirectory of the current folder.

How does R's tikzDevice deal with raster images?

I have read, if tikz takes a raster image it is to be stored as png. Having that, tikz produces the rest of the graph around it and include the raster image in the final tex-file back again.
Now I have the following:
pic <- T
if(pic)
{
tikz(file=paste(plotpath,"Rohdaten_S1_S2_D21.tex",sep=""),width=width,height=height,engine = "pdftex",)
#png(filename=paste(plotpath,"Rohdaten_S1_S2_D6.png",sep=""),width=width,height=height,res=res,units="in")
par(mfrow=c(2,1),mar=c(1.1,3,2,0),mgp=c(1.5,0.5,0),ps=f.size,cex=1,xaxt="n")
}
if(!pic) par(mfrow=c(2,1),mar=c(1,4,3,0))
for(i in 1:2)
{
x <- sensors[[i]]$time
y <- sensors[[i]]$depth
z <- sensors[[i]]$velo
image(x,y,z)
# plot.image(x,y,z
# ,xlim=c(max(x)-400,max(x)),zlim=2*c(-1,1)
# ,xlab="",ylab="$d/\\mathrm{m}$",zlab="$v/(\\mathrm{mm/s})$"
# ,z.adj=c(0,0),ndz=5,z.cex=1
# )
abline(v=(1:10)/0.026+par("usr")[1],lty=2)
if(!pic) abline(h=(1:floor(max(y/0.02)))*0.02)
mtext(text=paste("Sensor",i),side=3,line=0.1,adj=0)
par(mar=c(3,3,0.1,0),xaxt="s")
}
title(xlab="t/s")
if(pic) dev.off()
even the simple image() function will produce a 100MB large .tex file.
No png is produced, everything is in the .tex file?!
What am I doing wrong? Is there a switch to be set TRUE? What do I have to do to put the rasterimage apart from the nice looking text.
Thank you for your help.
The solution is quite simple, but not obvious.
the image()-function in R produces vector graphics in the first
instance. There is a switch image(...,useRaster = T) with which
one can force the image()-function to produce raster graphics.
the image()-function aspects a regular grid (quadratic pixels). Otherwise an error occurs.
How to get a regular grid?
Suppose you have an image with the coordinates x[],y[] and the scalar matrix z[,]. Then the re-sampled regular grid can be calculated:
x.new<-seq(min(xlim),max(xlim),length.out=dim.max[1])
y.new<-seq(min(ylim),max(ylim),length.out=dim.max[2])
z<-apply(z,2,function(y,x,xout) return(approx(x,y,xout=xout+min(diff(x))/2,method="constant",rule=2)$y),x,x.new)
z<-t(apply(z,1,function(y,x,xout) return(approx(x,y,xout=xout+min(diff(x))/2,method="constant",rule=2)$y),y,y.new))
tikz(file ='a.tex',width = 2, height = 2)
image(x,y,z,useRaster = T)
dev.off()
The important things are the method = "constant" and the rule = 2 statements in the approx()-function. These enables a "shifting" to the regular grid.
Applying all this and tikz() will split the picture in a a.tex-file and a a_ras1.png-file.
I hope this will help sombody programming R and using tikzDevice to produce pictures for tex documents.

fast way to read in png, add grid & coords, and output

I have a lot of png files of a floor plan (mapping) layout that I want to:
read into R
Add grid lines
Add coordinates per cell in grid
Output
There are 1000 of these files so I'm looking for a speedy method. What would be a fast way to accomplish this task. These don't need to be publication quality as I'm looking for certain behavior clusters within cells and want recording the coordinated for these events for each of the 100 frames (pngs).
Here is a MWE that produces 10 png files:
x <- y <- seq(-4*pi, 4*pi, len = 27)
r <- sqrt(outer(x^2, y^2, "+"))
dir.create("delete_me")
wd <- getwd()
setwd("delete_me")
lapply(1:10, function(x){
png(sprintf("file_%s.png", x))
image(z = z <- cos(r^2)*exp(-r/x))
dev.off()
})
setwd(wd)
The final output will look like this for each png (with all the coords filled in).
I assume grid will be the way to create the gridlines quickly but am not sure about reading the png in quickly or plotting the coordinates (assume we'll use a 10 x 10 grid on each png).
How about using ggplot() and annotation_custom() to plot the image across the entire plot area, then manually overplot the grid lines.
(In the image, I trimmed the excess whitespace and axis from the png file in advance)
# pre-req libraries
require(ggplot2)
require(grid) # rasterGrob function
require(png) # to read the PNG file
width<-10
height<-10
# generate the points and labels for the grid
points<-data.frame(expand.grid(w=1:width,h=1:height))
points$labs<-paste0("(",points$w,",",points$h,")")
points$x<-points$w-0.5 # center
points$y<-points$h-0.5
# make the gridline co-ordinates
gridx<-data.frame(x=0:width,xend=0:width,y=rep(0,width+1),yend=rep(height,width+1))
gridy<-data.frame(x=rep(0,height+1),xend=rep(width,height+1),y=0:height,yend=0:height)
grids<-rbind(gridx,gridy)
# function to plot using ggplot with annotation_custom for the image
plotgrid<-function(file){
g<-ggplot(points)+theme_bw()+
annotation_custom(rasterGrob(readPNG(file),0,0,1,1,just=c("left","bottom")),0,width,0,height)+
geom_text(aes(x=x,y=y,label=labs))+
geom_segment(aes(x=x,xend=xend,y=y,yend=yend),data=grids) +
coord_cartesian(c(0,width),c(0,height))
return(g)
}
# run the function for each file in the folder
setwd("delete_me")
lapply(list.files(),function(x)plotgrid(x))
setwd(wd)

Resources