Unable to open png device in loop - r

I've been fiddling around with a function in R, where, long story short, I have a for-loop, and at each step, I save a plot using png, then immediately readPNG so that I can extract RGB information. I then make a second plot, then readPNG this so I can compare the RGB of the two images.
The problem is that I keep getting an error message about being unable to start the png() device, or to open the file for writing, after a number of loops (can be as few as a handful of loops, or as many as a few thousand).
Here is really simplified code, but it has the bare essentials, and generates the error message:
testfun<-function(beg,fini)
{
library(png)
setwd("D://mydirectory")
for (i in beg:fini)
{
png("test.png",width=277,height=277) #candidate image
par(mai=c(0,0,0,0))
plot(1,type="n",ann=FALSE,xlim=c(0,255),ylim=c(0,255),
xaxt="n",yaxt="n",frame.plot=F)
polygon(x=c(10,60,60),y=c(10,10,60),col="red")
graphics.off()
image<-readPNG("test.png")
#code where I get rgb values for original
png("test2.png",width=277,height=277) #candidate image with diferent params
par(mai=c(0,0,0,0))
plot(1,type="n",ann=FALSE,xlim=c(0,255),ylim=c(0,255),
xaxt="n",yaxt="n",frame.plot=F)
polygon(x=c(10,60,60),y=c(10,10,60),col="blue")
graphics.off()
image<-readPNG("test2.png")
#code where I get rgb values for second image, and compare
}
}
And the error message:
Error in png("test.png", width = 277, height = 277) :
unable to start png() device
In addition: Warning messages:
1: In png("test.png", width = 277, height = 277) :
Unable to open file 'test.png' for writing
2: In png("test.png", width = 277, height = 277) : opening device failed
Originally I had graphics.off() as dev.off() but then thought maybe the loop was so fast that turning off one device wasn't fast enough before needing to be open again and it was getting 'confused' somehow. I also tried using Sys.sleep(0.1) after each graphics.off, but that didn't help either. Am I missing something stupid and obvious, or is this just a device bug?

I've had the same problem occur, although not in a loop situation. In my case, it was because I was pointing the .png output to a directory that did not exist.
png('./tweets/graphics/unique words.png', width=12, height=8, units='in', res=300)
Once I created the directory, and referenced it correctly, the error went away and I got my .png image.

I had this issue while saving plots in a loop also. #Dino Fire gave me a hint, my loop-generated file name contained an illegal character...
Ensure that the file name is legal (look for slashes, ampersands, apostrophes etc.)

For me, the reason readPNG() wasn't working was because I was running it from within a Rmd (RMarkdown) file.
As soon as I ran the code in the R console or a regular script, it worked immediately.

if you are using RStudio (or R) set working directory to where pictures are (.jpg, .png) . It should be a directory, not just (C:/).
getwd()
setwd("C:/RCode/Deep Learning/Downloads/")
getwd()

Related

R png()/pdf() doesn't work when running script but works if executing step by step

I'm creating a script to cluster my data in a server. I need to save the text output and the images as well. The text output works just fine but when I try to use the png() + plot() + dev.off() thing to save the plots, no image is created.
[ADDED FOR CLARIFICATION]
What I need to do is to SAVE the plot (i.e. generate an image file) in running mode. If I run the code step by step, the file is created.
I already tried to change the image format to PDF and JPG using the corresponding functions but I'm still getting no images as output when running the code as script. When stepping, it works great.
Since it takes a little while for R to render the image when I'm running step by step, I tried to add Sys.sleep(2) in between commands (code below) but nothing changed.
I think the problem might be related to the package that I'm using and the type of object it generates (library(NMF)). I looked at the documentation to see if there was something about the way the plot() function works with the type of object that the clustering algorithm generates but the text is vague:
"The result (of estim.r <- nmf(esGolub, 2:6, nrun=10, seed=123456) for example) is a S3 object of class NMF.rank, that contains a data.frame with the quality measures in column, and the values of r in row. It also contains a list of the consensus matrix for
each value of r".
"All the measures can be plotted at once with the method plot (Figure 1), and the function consensusmap generates heatmaps of the consensus matrix for each value of the rank".
There is another type of image that can be generated after the clustering runs: the consensusmap. This one works on both cases (stepping and running).
The script is pretty short. Here it is:
library(NMF)
data = read.csv('R.csv', header=TRUE, sep=";")
res1 <- nmf(data, rank=2:5, nrun=1, "brunet", "random")
# this always works
capture.output(summary(res1) ,file = "summary.txt", append = TRUE)
# this always works too
png(filename = 'consensus.png', width = 1366, height = 768, units = 'px')
consensusmap(res1)
dev.off()
# this does not work on 'running mode', only 'stepping mode'
png(filename = 'metrics.png', width = 1366, height = 768, units = 'px')
# added hoping it would fix the issue. It didn't
Sys.sleep(2)
plot(res1)
# added hoping it would fix the issue. It didn't
Sys.sleep(2)
dev.off()
The summary.txt file is generated, the consensus.png too. The metrics.png is not. What's going on here??

Error : Unable to start png() device

I am using Windows. When trying to plot a graph on png device, it fails with the error.
My code:
png("C:\\plot1.png", width = 480, height = 480, units = "px", bg = "white")
par(mar= c(4, 4, 2, 1))
hist(pwrcon$Global_active_power,col = "red", main = "Global Active Power", xlab = "Global Active Power (kilowatts)")
dev.off()
Error:
Error in png("C:\\plot1.png", width = 480, height = 480, units = "px", :
unable to start png() device
In addition: Warning messages:
1: In png("C:\\plot1.png", width = 480, height = 480, units = "px", :
unable to open file 'C:\plot1.png' for writing
2: In png("C:\\plot1.png", width = 480, height = 480, units = "px", :
opening device failed
Can anyone help me in getting this resolved?
Thanks in advance
I cannot explain why, but I once found that when the folder path in which my RStudio project was saved was a very long character string, the png device would fail. When I shortened the folder path it worked.
I had the same issue while working in an r-markdown document.
The issue in my case had something to do with viewing the Chunk Output Inline. When I switched to viewing the Chunk Output in Console, it worked just fine.
I got also this error: "Error in (function (filename = "Rplot%03d.png", width = 480, height = 480, :
unable to start png() device"
The name of the .Rmd file that I've been working on was containing some nonenglish characters, so removing them has been helpful in my case.
Had the same problem on a PC. The problem was that there was an antivirus program with "Safe files" enabled, which blocked Rstudio from creating graphics files. The antivirus didn't display any information when blocking, so it doesn't give you any clues really.
The filename C:\plot1.png contains a backslash (\) which is an escape character . This causes the error you are getting.
Change it to a slash (/)
png("C:/plot1.png", width = 480, height = 480, units = "px", bg = "white")
Or double the backslash (\\):
png("C:\\plot1.png", width = 480, height = 480, units = "px", bg = "white")
I received the error mentioned above
Error in (function (filename = "Rplot%03d.png", width = 480, height = 480, : unable to start png() device Calls: <Anonymous> ...
My issue was with the fig.width option in one of my R-code chunks of my R-markdown document and when the output was rendered as an html document. The fig.width was too large compared to the other fig.width options in other code-chunks. Again this was observed only when I attempted to render it as an html document, not as a powerpoint presentation.
Also met the similar issue in Windows 10, my R script is put in the same folder as RScript.exe, using the package ggplot2. However I got the message could not open file 'Rplot001.png'.
Finally found two ways to solve the problem:
Move the R script to any other folder except the folder RScript.exe located.
Set work directory using the command setwd("YourPath") first, then do other things.
I came across the same type of error, neither png nor jpg device could not open from ggplot2's ggsave command. The path contained an Å symbol which was stored as \305 when inserted in a variable describing the directory.
setwd(path) followed by ggsave(filename)for this directory variable did work in this case, but ggsave(paste(path, filename, sep="/") did not.
Replacing the Å with an A in my case could resolve the error.
One other problem could be that your Rstudio may have updated. I have encountered this problem while working inside R-markdown. Trying the code in a regular R script still works. Try saving the markdown as a new file. This should fix the problem temporarily.
Do not know of a long term solution.
I had the same error message. Turns out there was a typo in the path name.
Besides these problems, reinstalling ggplot and tydiverse from CRAN seemed to have worked for some, see here
I also had this error today when working in an RMarkdown notebook (it was fine yesterday). If I edit a chunk then try to run it I get this error. If I then save the notebook and try the chunk again it works. My working directory is a OneDrive folder. I wonder whether that may be an issue.
Having to save every after edit is not ideal, but a workaround.
I added "dev.off()
"before plot, the problem solved. The reason may be because of the previous device has not turn off yet.
This has been solved, but I thought I might add my answer if it makes someone's life easier.
Of course you can have your wd set to some short path (or path with no special characters): setwd("c/Users/John/My_r_project)
But I use R at work, thus my R project is saved on a common drive with super long path, and my working directory has to be long. A workaround was:
```{r setup, include=FALSE}
knitr::opts_chunk$set(
fig.path = "c/Users/John/My_r_project/figures" #make sure you create the folder first in Windows
)
```
And you can of course add other options there as well, such as: dpi = 300, echo = FALSE, ...
I had the same problem while running R in Jupyter notebook. I did a lot of Google searches and tried everything possible. The only way it worked for me was by restarting the kernel. But, restarting the kernel is not a good solution if you already have trained your models which took you a long time.
If you are trying to save the PNG image, make sure you have permission to create files in the destination folder. I've seen this error come up on a corporate network where full access had not been granted to the user.
The error usually means that the file cannot over accessed or overwritten, meaning that the file is in use or the file path is not writeable.
In the first case, just close the files you have open (e.g., in an image preview) and try again.
interestingly, also observed the error when in the UI 'tableOutput' was used and on the server side 'renderPlot'
I have seen this message, and find this is because the png file is occupied by another software or process.
So close the software or process, then restart rstudio.
I once also run into this problem. For me the first solution worked, but you might also want to check the other two options.
Restart R session. Tab Session > Restart R (Ctrl + Shift + F10)
Check working directory using getwd() and change it is necessary using setwd(path)
Don't forget to close the device using dev.off()

R Need to restart RStudio to view and save in a file using dev.copy() and dev.off()

I am trying to create a plot and eventually save it as a file. But because I am making a lot of changes and want to test it out, I want to be able to view and save the plot at the same time. I have looked at this page to do what I want to do but in my system, it does not seem to be working as it is supposed to.
Here are my codes:
png('Save.png')
sample.df <- data.frame(group = c('A','B','A','C','B','A','A','C','B','C','C','C','B'),
X = c(2,11,3,4,1,6,3,7,5,9,10,2,8),
Y = c(3,8,5,2,7,9,3,6,6,1,3,4,10))
plot(Y ~ X, data = sample.df)
dev.copy(png, 'Save.png')
dev.off()
There are several issues (I am new to R so I might be missing something entirely):
(1) When I use png(), I cannot view the plot in RStudio so I used dev.copy() but it does not allow me to view my plot in R studio
(2) Even after I use dev.off(), I cannot view the saved file until I close the RStudio (says "Windows Photo Viewer can't open this picture because the picture is being edited in another program"). I need to restart every time so it is very inconvenient.
What am I doing wrong and how could I view and view saved file without restarting RStudio every time? Thank you in advance!
Addition
Based on Love Tätting's comments, when I run dev.list(), this is what I get.
> png('Save.png')
>
> sample.df <- data.frame(group = c('A','B','A','C','B','A','A','C','B','C','C','C','B'),
+ X = c(2,11,3,4,1,6,3,7,5,9,10,2,8),
+ Y = c(3,8,5,2,7,9,3,6,6,1,3,4,10))
>
> plot(Y ~ X, data = sample.df)
>
> dev.copy(png, 'Save.png')
png
3
> dev.off()
png
2
> dev.list()
png
2
> dev.off()
null device
1
> dev.list()
NULL
Why do I not get RStudioGD?
RStudio has its own device, "RStudioGD". You can see it with dev.list(), where it by default is the first and only one.
R's design for decoupling rendering and backend is by the abstraction of devices. Which ones you can use is platform and environment dependent. dev.list() shows the stack of current devices.
If I understand your problem correctly you want to display the graph first in RStudio, and then decide whether you want to save it or not. Depending on how often you save th image you could use the 'export' button in the plot pane in RStudio and save it manually.
Otherwise, your choice of trying to copy it would be the obvious one for me as well.
To my knowledge the device abstraction in R does not allow one to encapsulate the device as an object, so one for example could make it an argument to a function that does the actual plot. Since dev.set() takes an index as argument, passing the index as argument will be dependent on state of the stack of devices.
I have not come up with a clean solution to this myself and have sometimes retorted to bracketing the plot rendering code with a call to a certain device and saving it right after, and switching device depending on a global.
So, if you can, use RStudios export functionality, otherwise an abstraction would need to maintain the state of the global stack of devices and do extensive testing of its state as it is global and you cannot direct a plot call to a certain device, it simply plots to the current device (to my knowledge).
Edit after OP comment
It seems that it is somewhat different behaviour you are experiencing if you cannot watch the file after dev.off, but also need to quit RStudio. For some type of plot frameworks there is a need to call print on the graphical object to have it actually print to the file. Perhaps this is done by RStudio at shutdown as part of normal teardown procedures of open devices? In that ase the file should be empty if you forcibly look in its contents before quiting RStudio.
The other thing that sometimes work is to call dev.off twice. I don't know exactly why, but sometimes more devices get created than I have anticipated. After you have done dev.off, what does dev.list show?
Edit after OP's edit
I can see that you do, png(); dev.copy(); dev.off(). This will leave you with one more device opened than closed. You will still have the first graphics device that you started open as can be seen when you do the listing. You can simply remove dev.copy(). The image will be saved on dev.off() and should be able to open from the filesystem.
As to why you cannot see the RStudio graphics device, I am not entirely sure. It might be that other code is messing with your device stack. I would check in a clean session if it is there to make sure other code isn't tampering with the device stack. From RStudio forums and other SO questions there seem to have been plot pane related problems in RStudio that have resolved after updating RStudio to the latest. If that is a viable solution for you I would try that.
I've just added support for RStudio's RStudioGD device to the developer's version of R.devices package (I'm the author). This will allow you to do the following in RStudio:
library("R.devices")
sample.df <- data.frame(
group = c('A','B','A','C','B','A','A','C','B','C','C','C','B'),
X = c(2,11,3,4,1,6,3,7,5,9,10,2,8),
Y = c(3,8,5,2,7,9,3,6,6,1,3,4,10)
)
figs <- devEval(c("RStudioGD", "png"), name = "foo", {
plot(Y ~ X, data = sample.df)
})
You can specify any set of output target types, e.g. c("RStudioGD", "png", "pdf", "x11"). The devices that output to file will by default write the files in folder figures/ with filenames as <name>.<ext>, e.g. figures/foo.png in the above example.
The value of the call, figs, holds references to all figures produced, e.g. figs$png. You can open them directly from R using the operator !. For example:
> figs$png
[1] "figures/foo.png"
> !figs$png
[1] "figures/foo.png"
The latter call should show the PNG file using your system's PNG viewer.
Until I submit these updates to CRAN, you can install the developer's version (2.15.1.9000) as:
remotes::install_github("HenrikBengtsson/R.devices#develop")

how to solve the error 'gswin32c.exe' not found?

I want submit figures to a journal which requires a high quality figures min dpi is 300 so I tried to save my plot with high quality but I am getting an error.
my plot contains several figures.
Example:
par(mfrow=c(2,4))
x=c(5,2,4,5,8,7)
x1=c(5,2,4,5,8,7)
x2=c(5,2,4,5,8,7)
x3=c(5,2,4,5,8,7)
plot(x)
plot(x1)
plot(x2)
bitmap("Plot118.tiff", height = 531, width = 1328, type="tifflzw", res=300)
Error in system(paste(gsexe, "-help"), intern = TRUE, invisible = TRUE) :
'gswin32c.exe' not found
Any help please on how to solve this problem or to produce a high quality figure?
Easiest way: install RStudio, create your plot, and use the Export -> Save as PDF option. There you can specify the pdf size.
To be able to run the bitmap command, you need Ghostscript installed. Once that is installed, you probably also need to set the GS_CMD environment variable. See also this question on the R-devel mailing list.

Filename created w sprintf truncated when RStudio console width too short

I just encountered something baffling (at least to me) and hope wiser members can shed some light.
I used RStudio 0.98.490 on Windows XP to save a plot to PNG. The filename was created using strwrap(sprintf()). I habitually use longer (i.e. more informative) filenames, and I guess I was probably over-enthusiastic this time, which is why this issue surfaced.
I noticed that when the width of the RStudio console is shorter than the length of the filename during run-time, the latter gets truncated and the file created does not have the .png extension. I experimented and dragged the width of RStudio console to longer than the filename - the problem disappears.
My question: why does this happen? More importantly, can I resolve this truncation without changes to my filename? I am a newbie to R and I can't see why 2 seemingly unrelated items should interact.
Truncation shown below:
> writeLines( paste0(FName, " generated") ) # Write to Console
aaaaaa aaaaaaaaaaaaaabcdef ghijk lmnopqrstuvaaaaaa aaaaaaaaaaaaa213424534aaaaaa generated
aaaaaaaaaaaaa.png generated
>
Sample code is attached below:
astring <- "aaaaaa aaaaaaaaaaaaa"
FName <- strwrap( sprintf("%sabcdef ghijk lmnopqrstuv%s213424534%s.png",
astring, astring, astring) ) # simulate long filename
png( filename = FName)
a <- rnorm(100)
b <- rnorm(100)*2
plot(b,a)
dev.off()
writeLines( paste0(FName, " generated") ) # Write to Console
The closest resource I found was https://stackoverflow.com/questions/6104448/preserving-long-comments-in-console-output-not-falling-victim-to-truncat but the problem faced by the author appeared slightly different.
I would appreciate very much if someone can enlighten. Thanks!
EDIT: Thanks to #jlhoward, I looked up strwrap() and found the width parameter. By assigning '255' (or any big integer), the problem is resolved.
Why are you using strwrap(...)?
As the documentation explains, strwrap(...) parses your input into words, and then wraps (by inserting "\n") based on a width parameter. The default for this parameter is getOption("width"), which is based on the console width. Try typing
getOption("width")
then shrink or expand your console window and do it again.
If you just use sprintf(...) to generate your filename, you don't have this problem.

Resources