Skip to content

Instantly share code, notes, and snippets.

@jeffreyhorner
Created September 13, 2011 20:54
Show Gist options
  • Save jeffreyhorner/6d09536d871c1a648a84 to your computer and use it in GitHub Desktop.
Save jeffreyhorner/6d09536d871c1a648a84 to your computer and use it in GitHub Desktop.
Dataset Explorer in Rook
library(datasets)
library(RJSONIO)
library(Cairo)
library(png)
render_json <- function(object) {
# Some objects are instances of a sub-class of data.frame
# and RJSONIO doesn't know what to do with them, so we just
# use trickery.
if (inherits(object,'data.frame',which = TRUE) > 0){
class(object) <- 'data.frame'
# Even these may have ts objects as columns so lets
# just punt for right now and assign it an NA column.
for (i in names(object)){
if (inherits(object[[i]],'ts')){
object[[i]] <- NA
}
}
}
# Unclassing here is unclassy. Would be nice to use as.data.frame
# but it seems that the original ts object is stuffed into the result
# somehow.
if (inherits(object,'ts')){
object <- unclass(object)
}
if (inherits(object,'table') || inherits(object,'array')){
object <- as.data.frame(object)
}
RJSONIO::toJSON(object)
}
extract_dataset <- function(path_info,ext){
datasets <- ls('package:datasets')
cat('path_info',path_info,'\n')
cat('regex',paste('^/(.*)\\.',ext,sep=''),'\n')
tmpdataset <- sub(paste('^/(.*)\\',ext,sep=''),'\\1',path_info)
cat('tmpdataset',tmpdataset,'\n')
dataset <- datasets[datasets %in% tmpdataset][1]
if (is.na(dataset)) dataset <- 'iris'
dataset
}
app <- Builder$new(
Brewery$new(url='.*\\.html$',root='.'),
URLMap$new(
'^/.*\\.csv$' = function(env){
req <- Request$new(env)
res <- Response$new()
dataset <- extract_dataset(req$path_info(),'.csv')
res$header('Content-type','text/csv')
res$write(
paste(
capture.output(eval(parse(text=sprintf('write.csv(%s)',dataset)))),
collapse="\n"
)
)
res$finish()
},
'^/.*\\.json$' = function(env){
req <- Request$new(env)
res <- Response$new()
dataset <- extract_dataset(req$path_info(),'.json')
res$header('Content-type','application/json')
res$write(eval(parse(text=sprintf('render_json(%s)',dataset))))
res$finish()
},
'^/.*\\.png$' = function(env){
req <- Request$new(env)
res <- Response$new()
dataset <- extract_dataset(req$path_info(),'.png')
Cairo(file='/dev/null')
# This is a bit of magic. R has an example function
# which runs example code located at the end of a
# particular help topic. Fortunately, there's a help
# topic for all datasets exported from the 'datasets'
# package. Unfortunately, not all of them produce a plot,
# and they can be noisy. Especially if they run multiple plot
# commands>
#
# This is where you could place your own data and plot routines, FYI
#
capture.output(
suppressWarnings(
eval(
substitute(
example(dataset,package='datasets',ask=FALSE),
list(dataset=dataset)
)
)
))
i <- Cairo:::.image(dev.cur())
r <- Cairo:::.ptr.to.raw(i$ref, 0, i$width * i$height * 4)
dim(r) <- c(4, i$width, i$height) # RGBA planes
# have to swap the red & blue components for some reason
r[c(1,3),,] = r[c(3,1),,]
# now use the png library
p <- writePNG(r, raw()) # raw PNG bytes
dev.off()
res$header('Content-type','image/png')
res$length <- length(p)
res$body <- p
res$finish()
},
'.*' = Redirect$new('/index.html')
)
)
<%
datasets <- ls('package:datasets')
dataset <- datasets[datasets %in% req$GET()[['data']]][1]
if (is.na(dataset)) dataset <- 'iris'
%>
<html>
<head>
<body>
<h1><%=dataset%> Summary</h1>
<p> Download as [<a href="<%=req$to_url(sprintf("/%s.csv",dataset))%>">CSV</a>], [<a href="<%=req$to_url(sprintf("/%s.json",dataset))%>">JSON</a>].
</p>
<code>> summary(<%=dataset%>)</code>
<pre>
<%=paste(capture.output(eval(parse(text=sprintf("summary(%s)",dataset)))),collapse='<br>')%>
</pre>
<code>> str(<%=dataset%>)</code>
<pre>
<%=paste(capture.output(eval(parse(text=sprintf("str(%s)",dataset)))),collapse='<br>')%>
</pre>
<p><strong>Plots created from Examples section. May be garbled or empty.</strong></p>
<img src="<%=req$to_url(sprintf("/%s.png",dataset))%>">
</body>
</html>
# Snippet for server stanza located at /etc/nginx/sites-enabled on ubuntu
server {
location /datasets {
proxy_pass http://rookapp/custom/datasets ;
}
}
<html>
<title>R Dataset Explorer</title>
<head>
<body>
<h3>R Dataset Explorer with Rook</h3>
<p>
This example demonstrates Rook by exploring the R datasets package. Each dataset is presented below. By clicking on one, you will be able to explore the dataset with a plot or by returning the dataset in its entirety as a JSON object.
</p>
<table><tr>
<%
counter <- 0
numcols <- 6
for (i in sort(ls('package:datasets'))){
if (counter %% numcols == 0) cat("</tr><tr>")
%>
<td>
<a href="<%=req$to_url('/dataset.html',data=i)%>"><%=i%></a>
</td>
<%
counter <- counter + 1;
}
%>
</tr></table>
</body>
</html>
# Snippet for http stanza located at /etc/nginx on ubuntu
http {
upstream rookapp {
server localhost:9000;
server localhost:9001;
server localhost:9002;
}
}
#!/usr/bin/env Rscript
# Execute this file from the shell like so:
# Start.sh 9000 &
# Start.sh 9001 &
# Start.sh 9002 &
port <- commandArgs(trailingOnly=TRUE)
library(Rook)
s <- Rhttpd$new()
s$add(RhttpdApp$new(name='datasets',app='config.R'))
s$start(port=port)
while(TRUE) Sys.sleep(.Machine$integer.max)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment