Question

I have done some data analysis with Sage and R, and at this point I would like to produce a nice set of plots to condense the results so that I can present them properly.

What I've done is set the entire notebook to R, in the drop-down menu. Then I execute some code in a number of cells. Works great. The largest cell with code I have fills up most of my screen (five large SQL-selects to pull data from a database and store in variables). So for some code it seems like there are no restrictions at all.

Now I'm doing the plottings. And I start that off with these two lines to get a canvas:

png("temp.png", width=1800, height=1000)
par(mfrow=c(2,2))

Then I want to get four plots within the same PNG, so that it is nicely compressed together. But Sage just refuses to show any plot results with all four plots. Just having the first two plots works great (I get two blank spaces at the bottom). Both the two first plots work great, or the two middle plots, or the two last, or the first and the last. But three plots doesn't work and neither does four.

So I tried something a lot more simple, like this:

png("temp.png", width=1800, height=1000)
par(mfrow=c(2,2))
plot(1:20)
plot(20:1)
plot(seq(5,15,0.5))
plot(seq(15,5,-0.5))
dev.off()

This code works great, and I get four simple plots. And I can even extend that to look more like what I am actually trying to plot like this and make it work:

png("temp.png", width=1800, height=1000)
par(mfrow=c(2,2))
plot(1:20)
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="")
par(new=T)
plot(data.frame(seq(0,20), seq(0,20)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="")
plot(20:1)
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="")
par(new=T)
plot(data.frame(seq(0,20), seq(0,20)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="")
plot(seq(5,15,0.5))
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="")
par(new=T)
plot(data.frame(seq(0,20), seq(0,20)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="")
plot(seq(15,5,-0.5))
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="")
par(new=T)
plot(data.frame(seq(0,20), seq(0,20)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="")
dev.off()

So far so good. Seems to me like my idea about how I want to show my data should work. But my actual code doesn't work. Here's what it looks like in my actual plotting cell (that shows nothing):

png("temp.png", width=1800, height=1000)
par(mfrow=c(2,2))
smoothScatter(WFr, colramp=colorRampPalette(c("white", "black")), xlab="Julian day", ylab="Residual", xlim=c(175,279), ylim=c(-0.3,0.3), main="Wild Females, model residuals over time")
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
par(new=T)
plot(data.frame(seq(100,299), WFrlm$coef[1]+WFrlm$coef[2]*seq(100,299)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
smoothScatter(WMr, colramp=colorRampPalette(c("white", "black")), xlab="Julian day", ylab="Residual", xlim=c(175,279), ylim=c(-0.3,0.3), main="Wild Males, model residuals over time")
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
par(new=T)
plot(data.frame(seq(100,299), WMrlm$coef[1]+WMrlm$coef[2]*seq(100,299)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
smoothScatter(CFr, colramp=colorRampPalette(c("white", "black")), xlab="Julian day", ylab="Residual", xlim=c(175,279), ylim=c(-0.3,0.3), main="Cultured Females, model residuals over time")
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
par(new=T)
plot(data.frame(seq(100,299), CFrlm$coef[1]+CFrlm$coef[2]*seq(100,299)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
smoothScatter(CMr, colramp=colorRampPalette(c("white", "black")), xlab="Julian day", ylab="Residual", xlim=c(175,279), ylim=c(-0.3,0.3), main="Cultured Males, model residuals over time")
lines(c(0,500),c(0,0), lwd=1, col="Black", xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
par(new=T)
plot(data.frame(seq(100,299), CMrlm$coef[1]+CMrlm$coef[2]*seq(100,299)), type="l", lwd=2, col="Red", axes=F, xlab="", ylab="", xlim=c(175,279), ylim=c(-0.3,0.3))
dev.off()

What is wrong here? Since each of the plots seem to work fine on its own, and they do print out when I put them in pairs, why won't they show up when I try it with all four? BTW, I have also tried with plot() instead of smoothScatter() and it is the same thing; shows 2 plots but not more. I also tried par(mfrow=c(4,1)) but no difference.

At first I thought there was a limit as to how much R code you can put in one single cell, but my SQL-select-cells have much more code than the plotting cells. So I'm wondering if maybe there is some sort of time-out that makes Sage stop waiting for the PNG output? I tried searching my hard drive for "temp.png" too but I don't get anything showing up.

Is there a restriction on how much data you can pass to a plot in Sage? Can I adjust this somehow? Or is there some sort of debug mode I can enter to better understand why nothing is happening when I add all four plots to the output?

Was it helpful?

Solution 2

There is no need to change any r.py code, as kcrisman suggested in his answer. The R code always runs, but when the code is longer than 1024 characters R code is run as a script file instead of as a command line, and then Sage fails to detect any output that is generated.

The workaround that I found is to save output from long code snippets into a known file, e.g. "~/temp.png" for plots. Then you can use the next cell to draw a dummy plot, and then write your previously created plot onto the canvas. Since this plot is generated from a shorter code (less than 1024 characters), Sage will be able to detect the output that is generated the second time around. Here is the code I used:

png("~/output.png", width=1800, height=1000)
par(mfrow=c(2,2))
# do fancy plot stuff here
dev.off()
# <---- I used a second cell here ---->
library(png)
x <- readPNG("~/output.png")
png("tmp.png", width=1800, height=1000)
plot(1:2, type="n", axes=F, xlab="", ylab="")
# rasterImage() prints on the plot. The plot goes from x = c(1,2) to y = c(1,2).
# So we tell rasterImage() to print within that x/y (i.e. "1,1,2,2") to keep
# the plot scaled correctly.
rasterImage(x, 1, 1, 2, 2)
dev.off()

You could of course do it like a function or something. But since it only applies on rare occasions when plot arguments are so long that the code length exceeds 1024 characters, I have only done it as a special cell on its own.

OTHER TIPS

Short version of my answer there, for completeness:

If you have your own installation, then in devel/sage/sage/interfaces/r.py, replace

eval_using_file_cutoff=1024)

with the cutoff you would like in terms of the number of characters. (You'll have to do ./sage -b before restarting the server.) If you don't, you won't be able to address this directly using the drop-down menu, though using r.eval() in the normal Sage menu with some extra options should do it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top