Avoid console message form package function - r

I'm using a package function (corenv, from seewave) which create a "please wait..." message in console. As I call it iteratively, that message is very annoying. So, I need a way for:
From my code, to temporarily ban the console messages
OR
To access the function code and take off the message line
The following is not my real code, but a very simple one showing the problem
require(seewave)
a = seq(0, (2*pi), by=0.01) #simple, unreal example
for (i in sequence(100)){
x = sin(a*i/3) #simple, unreal example
y = sin(a*i/2) #simple, unreal example
corenv(x,y,10,plot=FALSE)
}
A very simple question, but I haven't found any solution. I'll aprecciate any help

You could use sink to capture the output, e.g.
sink("tmp.txt")
z = corenv(x,y,10,plot=FALSE)
sink()
You can also wrap it in a function, e.g.
## unlink deletes the temporary file
## on.exit ensures the sink is closed even if
## corenv raises an error.
corenv(..., verbose=FALSE) {
if(verbose) {
sink("tmp.txt")
on.exit(sink(); unlink("tmp.txt"))
}
seewave::corenv(...)
}

Related

R package code coverage with test_that and readline()

Good morning,
I'm building an R package and trying to get code coverage (via codecov) as high as possible. But, I'm struggling to use test_that when the function requires input via readline(). Here is a simplified function using readline() in a similar way to mine.
fun<-function(){
y<-as.numeric(readline((prompt="Enter a number: ")))
res<-2*y
res
}
Any way to use test_that() with this function without having to manually input a number everytime this runs? Like, setting up a default input number only for the test?
Thanks!
From ?readline():
This [function] can only be used in an interactive session.
In a case like this I would probably rewrite my function to something like this:
fun <- function(y = readline(prompt = "Enter a number: ")) {
y <- as.numeric(y)
res <- 2 * y
res
}
When used interactively it works just the same, but when you want to test the function you can do so programmatically, for example:
expect_equal(
fun(y = 10),
20
)
Other alternatives is to include some options in your package or an environment variable that tells your code that you are in testing mode, and alters the behavior of fun(). See e.g. this answer on SO.

How can I make R's output more verbose so as to reassure me that it hasn't broken yet?

I often run code that eats up a lot of RAM, and may take as much as an hour before it gives its outputs. Often, I'll be half an hour in to running such code and I'll be worrying that something gone wrong. Is there any way that I can get R to reassure me that there's not been any errors yet? I suppose that I could put milestones in to the code itself, but I'm wondering if there's anything in R (or RStudio) that can automatically do this job at run time. For example, it would be handy to see how much memory the code is using, because then I'd be reassured that it's still working whenever I see the memory use significantly vary.
You might like my package {boomer}.
If you rig() your function, all its calls will be exploded and printed as the code is executed.
For instance
# remotes::install_github("moodymudskipper/boomer")
fun <- function(x) {
x <- x + 1
Sys.sleep(3)
x + 1
}
library(boomer)
# rig() the function and all the calls will be exploded
# and displayed as they're run
rig(fun)(2)
One way is:
to make a standalone file containing all the stuff to be run,
sourcing it and getting warned when the code is done, possibly with error.
The small function warn_me below:
runs the source file located in "path"
possibly catches an error, if an error there was
plays a sound when the run is over
sends an email reporting the status of the run: OK or fail
optionally: plays a sound until you stop it, so you can't miss it's over
And here it is:
warn_me = function(path, annoying = FALSE){
# The run
info = try(source(path))
# Sound telling it's over
library(beepr)
beep()
# Send an email with status
library(mailR)
msg = if(inherits(info, "try-error")) "The run failed" else "It's over, all went well"
send.mail(from = "me#somewhere.com",
to = "me#somewhere.com",
subject = msg,
body = "All is in the title.",
smtp = list(host.name = "smtp.mailtrap.io", port = 25,
user.name = "********",
passwd = "******", ssl = TRUE),
authenticate = TRUE,
send = TRUE)
if(annoying){
while(TRUE){
beepr::beep()
Sys.sleep(1)
}
}
}
warn_me(path)
I didn't test the package mailR myself, but any email sending package would do. See this excellent page on sending emails in R for alternatives.
If you are running an R script file within RStudio, use the "Source with Echo" selection (Ctrl+Shift+Enter, or via dropdown).

R - Rstudio - make R play a sound if warning/error generated

I am running a script that loops over a list of stock pair combinations... occasionally the script stops running due to an error generated by differing data lengths between pair combo and I simply remove the mismatched stock from consideration):
Error in model.frame.default(formula = stckY ~ stckX + 0, drop.unused.levels = TRUE) :
variable lengths differ (found for 'stckX')
Is there any way I can make R / Rstudio play a sound when the error message occurs so that I can be alerted without having to keep my eyes on the screen while the script is looping along?
I can generate sounds linearly using:
beep <- function(n = 3){
for(i in seq(n)){
system("rundll32 user32.dll,MessageBeep -1")
Sys.sleep(.5)
}
}
beep()
but how can I do this conditional on an error message?
Building on #frankc answer and #hrbrmstr comment, a way to do this:
install.packages("beepr")
library(beepr)
options(error = beep)
try options(error = beep)
you would still need to define beep before you do this. Haven't verified this works but it should per ?options:
'error': either a function or an expression governing the handling
of non-catastrophic errors such as those generated by 'stop'
as well as by signals and internally detected errors. If the
option is a function, a call to that function, with no
arguments, is generated as the expression. The default value
is 'NULL': see 'stop' for the behaviour in that case. The
functions 'dump.frames' and 'recover' provide alternatives
that allow post-mortem debugging. Note that these need to
specified as e.g. 'options(error = utils::recover)' in
startup files such as '.Rprofile'.

If (something got printed) x=false, how to do this in R?

So I am using a function in R that uses compiled fortran code. While using this function, lsoda, in package deSolve. I get messages printed to the screen like
DLSODA- At current T (=R1), MXSTEP (=I1) steps
taken on this call before reaching TOUT
In above message, I =
[1] 5000
In above message, R =
[1] 21.31629
The problem is that the above is not a "warning" or an "error"; the is.null(warnings()) evaluates to TRUE after I see this message. If it were a warning I could just write x = is.null(warnings()) and that would do the trick. I could use tryCatch for errors, but what about messages that are neither errors or warnings?
The reason I ask, is that this function is called in a while loop, inside a for loop. I want the while loop to break if this message gets printed, and then for the outer for loop to move onto the next iteration. Normally you'd use tryCatch to do something like this but because there is no error, I have no idea how to do this
You can redirect the output and then check whether lsoda printed something:
out <- capture.output(lsoda(...))
if(length(grep("In above message", out))!=0) {
# error
}
We basically check whether any of the lines printed by lsoda contains the string In above message. If you need to use the result from lsoda, you can also run like this:
out <- capture.output(result <- lsoda(...))
As suggested, you can also use grepl:
if(any(grepl("In above message", out))) {
# error
}

Sink does not release file

I know that the sink() function can be used to divert R output into a file, e.g.
sink('sink-closing.txt')
cat('Hello world!')
sink()
Is there a simple command to close all outstanding sinks?
Below, I elaborate on my question.
Suppose that my R-script opens a sink() in an R-script, but there is an error in the R-script which occurs before the script closes the sink(). I may run the R-script multiple times, trying to fix the error. Finally, I want to close all the sinks and print to the console. How do I do so?
Finally, in the interest of concreteness, I provide a MWE to illustrate the problem I face.
First, I write an R-script sink-closing.R which has an error in it.
sink('sink-closing.txt')
foo <- function() {
cat(sprintf('Hello world! My name is %s\n',
a.variable.that.does.not.exist))
}
foo()
sink()
Next, I source the R-script multiple times, say 3 times by mistake as I try to find and fix the bug.
> source('~/Dropbox/cookbook/r-cookbook/sink-closing.R')
Error in sprintf("Hello world! My name is %s\n", a.variable.that.does.not.exist) :
object 'a.variable.that.does.not.exist' not found
Now, suppose that I am debugging the R-script and want to print to the console. I can call sink() multiple times to close the earlier sinks. If I call it 3 times, then I can finally print to the console as before. But how do I know how many sinks I need to close?
closeAllConnections() # .........................
I'm getting upvotes for this as time goes along but Simon.S.A and others are better.
You can use sink.number() to tell you how many diversions are already set and then call sink that many times. Putting it into a function you could have this
sink.reset <- function(){
for(i in seq_len(sink.number())){
sink(NULL)
}
}
Based on #mnel's comment:
sinkall <- function() {
i <- sink.number()
while (i > 0) {
sink()
i <- i - 1
}
}
Should close all open sinks.
You may also encounter this problem when dealing with devices and plots, where the number of open devices isn't reported anywhere. For a more general case you could use this:
stopWhenError <- function(FUN) {
tryCatch({
while(TRUE) {
FUN()
}
}, warning = function(w) {
print("All finished!")
}, error = function(e) {
print("All finished!")
})
}
stopWhenError(sink) # for sink.
stopWhenError(dev.off) # close all open plotting devices.
EDIT:
sink throws a warning not an error so I've modified the code so that it won't run forever, whoops!
The most common time I experience this is when an error occurs preventing a sink from closing. For example, the following will leave an open sink after execution.
sink("output.txt")
my_function_that_will_error()
sink()
This can be avoided using on.exit(sink()). This will close the sink "when the current function exits (either naturally or as the result of an error)" (documentation here).
But you do have to change the order:
sink("output.txt")
on.exit(sink())
my_function_that_might_error()
So we create the sink, tell R to close it when it exits, and then execute the code that might error. This will close the sink regardless of whether the code errors or not.

Resources