# @GPL_HEADER_START
# Use of the RAVE and related source code is subject to the terms
# of the following licenses:
# 
# GNU Public License (GPL) Rights pursuant to Version 2, June 1991
# Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013
# 
# NO WARRANTY
# 
# ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER
# PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY
# PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN
# "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
# KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT
# LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE,
# MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE
# OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT,
# SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY
# TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF
# WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
# LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF
# CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON
# CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE
# DELIVERABLES UNDER THIS LICENSE.
# 
# Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie
# Mellon University, its trustees, officers, employees, and agents from
# all claims or demands made against them (and any related losses,
# expenses, or attorney's fees) arising out of, or relating to Licensee's
# and/or its sub licensees' negligent use or willful misuse of or
# negligent conduct or willful misconduct regarding the Software,
# facilities, or other rights or assistance granted by Carnegie Mellon
# University under this License, including, but not limited to, any
# claims of product liability, personal injury, death, damage to
# property, or violation of any laws or regulations.
# 
# Carnegie Mellon University Software Engineering Institute authored
# documents are sponsored by the U.S. Department of Defense under
# Contract F19628-00-C-0003. Carnegie Mellon University retains
# copyrights in all material produced under this contract. The U.S.
# Government retains a non-exclusive, royalty-free license to publish or
# reproduce these documents, or allow others to do so, for U.S.
# Government purposes only pursuant to the copyright license under the
# contract clause at 252.227.7013.
# 
# @GPL_HEADER_END
"""
R visualizations
"""

__version__ = "$Rev: 12630 $"

from rave.plugins.decorators import *
from rave.plugins.shell import *
from rave.plugins.dataset import Dataset

from rpy import r as R

rave_font_path = "/u11/zero/rave/fonts/"
# rave_font_path = "/afs/cert.org/usr/prevost1/lib/fonts/"

R("""
#-----------------------------------------------------------------------
# rave-zero.r

library(gplots)
library(GDD)

#-----------------------------------------------------------------------

zero.cex = 0.85

zero.setup.png <- function(filename, w, h) {
#  png(filename=filename, width=w, height=h)
  GDD(file=filename, type="png", w=w, h=h)
  par(mar = c(3.5,3.5,2,2)+0.1, ann=T, xaxs='i', yaxs='i', cex=zero.cex,
      lab=c(10,5,7))
}

#-----------------------------------------------------------------------
difftime.sec = 1
difftime.min = 60
difftime.hour = 3600
difftime.day = difftime.hour * 24

floor.hour <- function(t, n = 1) {
  t <- as.POSIXlt(t)
  h <- floor(t$hour / n) * n
  return (ISOdatetime(t$year+1900, t$mon+1, t$mday, h, 0, 0))
}

ceil.hour <- function(t, n = 1) {
  return (floor.hour(as.POSIXlt(t) -
                     difftime.sec + difftime.hour, n))
}

floor.day <- function(t) {
  t <- as.POSIXlt(t)
  return (ISOdatetime(t$year+1900, t$mon+1, t$mday, 0, 0, 0))
}

ceil.day <- function(t) {
  return (floor.day(as.POSIXlt(t) - difftime.sec + difftime.day))
}

floor.week <- function(t) {
  t <- as.POSIXlt(t)
  t <- floor.day(t)
  wday = as.integer(julian(t, origin=as.Date('1970-01-04'))) %% 7
  t <- t - difftime.day * wday
  return (t)
}

ceil.week <- function(t) {
  return (floor.week(as.POSIXlt(t) -
                     difftime.sec + (difftime.day * 7)))
}

fmt.num <- function(n) {
  
  if ( n < 1000 ) {
    return(sprintf("%0.0f", n))
  } else if ( n < 1000000 ) {
    return(sprintf("%0.1fk", n/1000))
  } else if ( n < 1000000000 ) {
    return(sprintf("%0.1fM", n/1000000))
  } else if ( n < 1000000000000 ) {
    return(sprintf("%0.1fG", n/1000000000))
  } else {
    return(sprintf("%0.1fT", n/1000000000000))
  }
}

zero.ts.grid <- function(sdate, edate, maxval, log='') {
  marks <- axTicks(side=2)
  axis(side=2, at=marks, label=lapply(marks, fmt.num))
  segments(x0=sdate, x1=edate, y0=marks, y1=marks, col='#e8e8e8')
  #abline(h=marks, lty=1, col='#e8e8e8')
  delta = difftime(edate, sdate, units='secs')
  if ( delta <= difftime.hour * 3 ) {
    # <= three hours: one hour marks and 10 minute marks
    marks <- seq(floor.hour(sdate), ceil.hour(edate), by=difftime.min * 10)
    marks <- marks[marks >= sdate & marks <= edate ]
    abline(v=as.POSIXct(marks), lty=1, col='#e8e8e8')
    mtext(side=1, at=marks, text=format(marks, '%H:%M'), cex=zero.cex, line=0.5)
    marks <- seq(floor.hour(sdate), ceil.hour(edate), by=difftime.hour)
    marks <- marks[marks >= sdate & marks <= edate]
    abline(v=as.POSIXct(marks), lty=1, col='#a0a0a0')
    mtext(side=1, at=marks, text=format(marks, '%Y-%m-%d'), cex=zero.cex, line=1.5) 
  } else if ( delta <= difftime.day ) {
    # <= one day: six-hourly and hourly marks
    marks <- seq(floor.hour(sdate), ceil.hour(edate), by=difftime.hour)
    marks <- marks[marks >= sdate & marks <= edate]
    abline(v=as.POSIXct(marks), lty=1, col='#e8e8e8')
    mtext(side=1, at=marks, text=format(marks, '%H'), cex=zero.cex, line=0.5)
    marks <- seq(floor.hour(sdate,6), ceil.hour(edate,6), by=(difftime.hour*6))
    marks <- marks[marks >= sdate & marks <= edate]
    abline(v=as.POSIXct(marks), lty=1, col='#a0a0a0')
    marks <- seq(floor.day(sdate), ceil.day(edate), by=difftime.day)
    mtext(side=1, at=marks, text=format(marks, '%Y-%m-%d'), cex=zero.cex, line=1.5)
  } else if ( delta <= 7 * difftime.day ) {
    # <= one week: daily and six-hourly marks
    marks <- seq(floor.hour(sdate, 6), ceil.hour(edate, 6),
                 by=(difftime.hour * 6))
    marks <- marks[marks >= sdate & marks <= edate]
    abline(v=as.POSIXct(marks), lty=1, col='#e8e8e8')
    mtext(side=1, at=marks, text=format(marks, '%H'), cex=zero.cex, line=0.5)
    marks <- seq(floor.day(sdate), ceil.day(edate), by=difftime.day)
    marks <- marks[marks >= sdate & marks <= edate]
    abline(v=as.POSIXct(marks), lty=1, col='#a0a0a0')
    mtext(side=1, at=marks, text=format(marks, '%Y-%m-%d'), cex=zero.cex, line=1.5)
  } else {
    # otherwise: daily and weekly marks
    marks <- seq(floor.day(sdate), ceil.day(edate), by=difftime.day)
    marks <- marks[marks >= sdate & marks <= edate]
    abline(v=as.POSIXct(marks), lty=1, col='#e8e8e8')
    mtext(side=1, at=marks, text=format(marks, '%d'), cex=zero.cex, line=0.5)
    marks <- seq(floor.week(sdate), ceil.week(edate), by=(difftime.day * 7))
    marks <- marks[marks >= sdate & marks <= edate]
    abline(v=as.POSIXct(marks), lty=1, col='#a0a0a0')
    mtext(side=1, at=marks, text=format(marks, '%Y-%m-%d'), cex=zero.cex, line=1.5)
  }
  if ( log == 'y' | log == 'xy' || log =='yx' ) {
    segments(x0=sdate, x1=edate, y0=1, y1=1, lty=1, col='#a0a0a0')
  } else {
    segments(x0=sdate, x1=edate, y0=0, y1=0, lty=1, col='#a0a0a0')
  }
}

#-----------------------------------------------------------------------
zero.render.no.data.png <- function(outfile, w=366, h=366) {
  zero.setup.png(filename=outfile, w=w, h=h)
  on.exit(dev.off())
  plot.new()
  plot.window(xlim=c(-1,1), ylim=c(-1,1))
  text(0, 0, 'No data', font=3, cex=2.0)
}

#-----------------------------------------------------------------------
zero.render.pie.png <- function(outfile, labels, counts,
                                n=15, other=T, w=366, h=366) {
  v <- counts[1:n]
  l <- labels[1:n]
  if ( other ) {
    v <- c(v, sum(counts[(n+1):length(counts)]))
    l <- c(l, 'other')
  }
  names(v) <- l

  zero.setup.png(filename=outfile, w=w, h=h)
  on.exit(dev.off())
  pie(v)
}

#-----------------------------------------------------------------------
zero.render.bar.png <- function(outfile, labels, data, width, height) {
  data <- as.numeric(data)
  names(data) <- labels
  n <- length(data)

  zero.setup.png(filename=outfile, w=width, h=height)
  on.exit(dev.off())
  barplot2(data, plot.grid=T, xlim=c(0,n+0.2),
	   width=0.8, space=0.25, axisnames=F)
  mtext(side=1, at=seq(0.6, n-0.4, by=1), labels, cex=zero.cex, line=1.0)
}

#-----------------------------------------------------------------------
zero.render.line.png <- function(outfile, x, y, width, height,
                                 log='', xlim=NULL, ylim=NULL) {
  x <- as.numeric(x)
  y <- as.numeric(y)
  zero.setup.png(filename=outfile, w=width, h=height)
  on.exit(dev.off())
  plot(x=x, y=y, log=log, xlim=xlim, ylim=ylim)
}

#-----------------------------------------------------------------------
zero.render.scatter.png <- function(outfile, x, y, width, height,
                                 log='', xlim=NULL, ylim=NULL,
                                 xlab='', ylab='') {
  x <- as.numeric(x)
  y <- as.numeric(y)
  zero.setup.png(filename=outfile, w=width, h=height)
  par(mar = c(4,4,2.5,3.5)+0.1)
  on.exit(dev.off())
  plot(x=x, y=y, log=log, xlim=xlim, ylim=ylim, type="p", col="red",
       xlab=xlab, ylab=ylab)
}

zero.render.multi.scatter.png <- function(outfile, labels, xs, ys,
                                          width, height, log='',
                                          xlim=NULL, ylim=NULL) {
  zero.setup.png(filename=outfile, w=width, h=height)
  on.exit(dev.off())
  colors <- rainbow(length(labels))

  maxy <- max(flatten(ys))
  miny <- min(flatten(ys))
  if ( ! is.null(ylim) ) {
    maxy <- ylim[2]
    miny <- ylim[1]
  }
  if ( (log == 'y') | (log == 'yx') | (log == 'xy') ) {
    if ( miny <= 0 ) {
      miny <- 1
    }
  }

  maxx <- max(flatten(xs))
  minx <- min(flatten(xs))
  if ( ! is.null(xlim) ) {
    maxx <- xlim[2]
    minx <- xlim[1]
  }
  if ( (log == 'x') | (log == 'yx') | (log == 'xy') ) {
    if ( minx <= 0 ) {
      minx <- 1
    }
  }

  for ( i in 1:length(labels) ) {
    x <- as.numeric(xs[[i]])
    y <- as.numeric(ys[[i]])
    if ( i == 1 ) {
      plot(x=x, y=y, type="p", col=colors[i], xlim=c(minx, maxx),
           ylim=c(miny, maxy), log=log)
    } else {
      plot(x=x, y=y, type="p", frame.plot=F, axes=T, col=colors[i],
           xlim=c(minx, maxx), ylim=c(miny, maxy), log=log)
    }
    par(new=T)
  }
  legend('right', bty='n', legend=labels, col=colors, fill=colors)
}

#-----------------------------------------------------------------------
ip.to.xip <- function(ip) {
    if ( (ip >= 167772160) & (ip < 184549376) ) {
        return (((ip - 167772160) / 16777216) * 0.05 + 0.0)
    }
    if ( (ip >= 2363326464) & (ip < 2363359232) ) {
        return (((ip - 2363326464) / 32768) * 0.85 + 0.05)
    }
    if ( (ip >= 2885681152) & (ip < 2902458368) ) {
        return (((ip - 2885681152) / 16777216) * 0.05 + 0.9)
    }
    if ( (ip >= 3232235520) & (ip < 3232301056) ) {
        return (((ip - 3232235520) / 65536) * 0.05 + 0.95)
    }
    return(0.0)
}

zero.xip.grid <- function(log='') {
  axis(side=2)
  abline(v=c(0.05,0.9,0.95), lty=1, col='#a0a0a0')
  pub.at = c(0.025, 0.475, 0.92, 0.98)
  pub.labels = c('10', '140.221.128/17', '172', '192.168')
  loc.ip.at = seq(128, 256, by=4)
  loc.at = ((loc.ip.at - 128) / 128) * 0.85 + 0.05
  axis(side=3, at=pub.at, labels=pub.labels)
  axis(side=1, at=loc.at, labels=loc.ip.at)
}

zero.render.scatter.xip.png <- function(outfile, x, y, width, height,
                                 log='', ylim=NULL) {
  x <- as.numeric(x)
  x <- sapply(x, ip.to.xip)
  y <- as.numeric(y)
  zero.setup.png(filename=outfile, w=width, h=height)
  on.exit(dev.off())
  plot(x=x, y=y, log=log, xlim=c(0.0,1.0), ylim=ylim, type="p", frame.plot=T,
       axes=F, panel.first=zero.xip.grid(log=log), col="red")
}

#-----------------------------------------------------------------------
zero.min_one <- function(x) {
  if ( x <= 0 ) {
    return(1)
  } else {
    return(x)
  }
}

zero.render.ts.png <- function(outfile, time, data, sdate, edate, log='',
                               width, height, by=3600, ylim=NULL, ylab='') {

  sdate <- as.POSIXct(sdate)
  edate <- as.POSIXct(edate)

  time <- as.POSIXct(time)
  time.trimmed <- time[time >= sdate & time <= edate]

  data <- as.numeric(data)
  data.trimmed <- data[match(time.trimmed, time)]

  time.filled <- as.POSIXct(seq(floor.hour(sdate), ceil.hour(edate), by=by))
  data.filled <- rep(0, length(time.filled))
  data.filled[match(time.trimmed, time.filled)] <- data.trimmed
  data.filled <- sapply(data.filled, zero.min_one)

  zero.setup.png(filename=outfile, w=width, h=height)
  on.exit(dev.off())

  if ( is.null(ylim) ) {
    maxy <- max(data)
    if ( (log == 'y') | (log == 'xy') | (log == 'yx') ) {
      ylim = c(1,max(data.filled))
    } else {
      ylim = c(0,max(data.filled))
    }
  }

  par(mar = c(2.5,3.5,2.5,3.5)+0.1)
  plot(x=time.filled, y=data.filled, type='l', frame.plot=F,
       xlim=c(sdate, edate), ylim=ylim, axes=F, col='red', log=log,
       ylab=ylab)
  zero.ts.grid(sdate, edate, max(data.filled))
  par(new=T)
  plot(x=time.filled, y=data.filled, type='l', frame.plot=F,
       xlim=c(sdate, edate), ylim=ylim, axes=F, col='red', log=log,
       ylab=ylab)
}

#-----------------------------------------------------------------------
flatten <- function(l) {
  result <- NULL
  for ( i in 1:length(l) ) {
    result <- c(result, l[[i]])
  }
  return(result)
}


zero.render.multi.ts.png <- function(outfile, labels, time, data,
                                     sdate, edate, width, height, log='',
				     by=3600, ylim=NULL, ylab='y') {

  sdate <- as.POSIXct(sdate)
  edate <- as.POSIXct(edate)

  time.filled <- as.POSIXct(seq(floor.hour(sdate), ceil.hour(edate), by=by))

  colors <- rainbow(length(time))
  
  zero.setup.png(filename=outfile, w=width, h=height)
  on.exit(dev.off())
  
  legend.width = as.double(difftime(edate, sdate, units='secs')) / 4.25
  
  par(mar = c(3.5,4.5,2,0)+0.1)
  on.exit(dev.off())

  if ( is.null(ylim) ) {
    maxy <- max(flatten(data))
    if ( (log == 'y') | (log == 'xy') | (log == 'yx') ) {
      ylim = c(1, maxy)
    } else {
      ylim = c(0, maxy)
    }
  } else {
    maxy <- ylim[[2]]
  }

  for ( i in rev(1:length(time)) ) {
    ctime <- as.POSIXct(time[[i]])
    ctime.trimmed <- ctime[ctime >= sdate & ctime <= edate]
    cdata <- as.numeric(data[[i]])
    cdata.trimmed <- cdata[match(ctime.trimmed, ctime)]
    cdata.filled <- rep(0, length(time.filled))
    cdata.filled[match(ctime.trimmed, time.filled)] <- cdata.trimmed
    cdata.filled <- sapply(cdata.filled, zero.min_one)
    if ( i == length(time) ) {
      plot(x=time.filled, y=cdata.filled, type='l', frame.plot=F,
           xlim=c(sdate, edate+legend.width), ylim=ylim, axes=F, log=log,
           col=colors[i], ylab=ylab)
      zero.ts.grid(sdate, edate, maxy, log=log)
      if ( i == 1 ) {
        plot(x=time.filled, y=cdata.filled, type='l', frame.plot=F,
             xlim=c(sdate, edate+legend.width), ylim=ylim, axes=F, log=log,
             col=colors[i], ylab=ylab)
      }
    } else {
      plot(x=time.filled, y=cdata.filled, type='l', frame.plot=F, log=log,
           xlim=c(sdate, edate+legend.width), ylim=ylim, axes=F,
           col=colors[i], ylab='')
    }
    par(new=T)
  }

  legend('right', bty='n', lty=1, legend=labels, col=colors)
}

#-----------------------------------------------------------------------
library(maps)
library(mapdata)

country.codes <- c(
  'ad','ae','af','ag','ai','al','am','an','ao','aq','ar','as','at','au','aw',
  'az','ba','bb','bd','be','bf','bg','bh','bi','bj','bm','bn','bo','br','bs',
  'bt','bw','by','bz','ca','cc','cf','cg','ch','ci','ck','cl','cm','cn','co',
  'cr','cu','cv','cx','cy','cz','de','dj','dk','dm','do','dz','ec','ee','eg',
  'eh','er','es','et','fi','fj','fk','fm','fo','fr','ga','gb','gd','ge','gf',
  'gh','gi','gl','gm','gn','gp','gq','gr','gt','gu','gw','gy','hk','hn','hr',
  'ht','hu','id','ie','il','in','iq','ir','is','it','jm','jo','jp','ke','kg',
  'kh','ki','km','kn','kp','kr','kw','ky','kz','la','lb','lc','li','lk','lr',
  'ls','lt','lu','lv','ly','ma','mc','md','mg','mh','mk','ml','mm','mn','mo',
  'mp','mq','mr','ms','mt','mu','mv','mw','mx','my','mz','na','nc','ne','nf',
  'ng','ni','nl','no','np','nr','nu','nz','om','pa','pe','pf','pg','ph','pk',
  'pl','pm','pn','pr','pt','pw','py','qa','re','ro','ru','rw','sa','sb','sc',
  'sd','se','sg','sh','si','sj','sk','sl','sm','sn','so','sr','st','sv','sy',
  'sz','tc','td','tg','th','tj','tk','tm','tn','to','tp','tr','tt','tv','tw',
  'tz','ua','ug','uk','us','uy','uz','va','vc','ve','vg','vi','vn','vu','wf',
  'ws','ye','yt','yu','za','zm','zr','zw')

country.long <- c(
  1.50, 54.00, 65.00, -61.80, -63.05, 20.00, 45.00, -69.00, 18.50, 166.67,
  -64.00, -170.50, 13.33, 135.00, -69.97, 47.50, 17.83, -59.53, 90.00, 4.00,
  -2.00, 25.00, 50.50, 30.00, 2.25, -64.75, 114.67, -65.00, -55.00, -76.00,
  90.50, 24.00, 28.00, -88.75, -96.00, 96.83, 21.00, 15.00, 8.00, -5.00,
  -158.00, -71.00, 12.00, 105.00, -72.00, -84.00, -80.00, -24.00, 105.67,
  33.00, 15.00, 10.50, 42.50, 10.00, -61.33, -70.67, 3.00, -77.50, 26.00,
  30.00, -14.00, 39.00, -4.00, 39.00, 26.00, 178.00, -59.00, 152.00, -7.00,
  2.00, 11.75, -4.50, -61.67, 43.50, -53.00, -2.00, -5.35, -40.00, -15.50,
  -10.00, -61.58, 10.00, 22.00, -90.25, 144.83, -15.00, -59.00, 114.17,
  -86.50, 15.50, -72.42, 20.00, 120.00, -8.00, 34.75, 77.00, 44.00, 53.00,
  -18.00, 12.83, -77.50, 36.00, 138.00, 38.00, 75.00, 105.00, -170.00, 44.25,
  -62.75, 127.00, 127.50, 47.75, -80.67, 68.00, 105.00, 35.83, -60.97, 9.53,
  81.00, -9.50, 28.25, 24.00, 6.17, 25.00, 17.00, -5.00, 7.42, 29.00, 47.00,
  168.00, 22.00, -4.00, 98.00, 105.00, 113.00, 145.67, -61.00, -12.00, -62.20,
  14.42, 57.58, 73.00, 34.00, -102.00, 112.50, 35.00, 17.00, 165.50, 8.00,
  167.92, 8.00, -85.00, 5.75, 10.00, 84.00, 166.92, -169.87, 174.00, 57.00,
  -80.00, -76.00, -140.00, 147.00, 122.00, 70.00, 20.00, -56.33, -130.08,
  -66.55, -8.00, 134.00, -58.00, 51.25, 55.60, 25.00, 47.00, 30.00, 45.00,
  159.00, 55.67, 30.00, 15.00, 103.80, -5.70, 15.17, 20.00, 19.50, -11.50,
  12.42, -14.00, 48.00, -56.00, 7.00, -88.92, 38.00, 31.50, -71.58, 19.00,
  1.17, 100.00, 71.00, -171.75, 60.00, 9.00, -175.00, 125.00, 35.00, -61.00,
  178.00, 121.00, 35.00, 32.00, 33.00, -4.50, -98.00, -56.00, 64.00, 12.45,
  -61.20, -66.00, -64.50, -64.43, 106.00, 167.00, -177.00, -172.33, 47.50,
  45.17, 21.00, 26.00, 30.00, 22.00, 29.00)

country.lat <- c(
  42.50, 24.00, 33.00, 17.05, 18.22, 41.00, 40.00, 12.17, -12.50, -77.85,
  -34.00, -14.32, 47.33, -25.00, 12.50, 40.50, 44.25, 13.17, 24.00, 50.83,
  13.00, 43.00, 26.00, -3.50, 9.50, 32.33, 4.50, -17.00, -10.00, 24.00,
  27.50, -22.00, 53.00, 17.25, 60.00, -12.17, 7.00, -1.00, 47.00, 8.00,
  -20.00, -30.00, 6.00, 35.00, 4.00, 10.00, 21.50, 16.00, -10.50, 35.00,
  49.75, 51.50, 11.50, 56.00, 15.50, 19.00, 28.00, -2.00, 59.00, 27.00,
  23.00, 15.00, 40.00, 8.00, 64.00, -18.00, -51.75, 5.00, 62.00, 46.00,
  -1.00, 54.00, 12.12, 42.00, 4.00, 8.00, 36.13, 72.00, 13.50, 11.00, 16.25,
  2.00, 39.00, 15.50, 13.47, 12.00, 5.00, 22.25, 15.00, 45.17, 19.00, 47.00,
  -5.00, 53.00, 31.50, 20.00, 33.00, 32.00, 65.00, 42.83, 18.25, 31.00,
  36.00, 1.00, 41.00, 13.00, -5.00, -12.17, 17.33, 40.00, 37.00, 29.50,
  19.50, 48.00, 18.00, 33.83, 13.88, 47.17, 7.00, 6.50, -29.50, 56.00,
  49.75, 57.00, 25.00, 32.00, 43.73, 47.00, -20.00, 11.00, 41.83, 17.00,
  22.00, 46.00, 22.00, 15.12, 14.67, 20.00, 16.75, 35.92, -20.30, 3.20,
  -13.50, 23.00, 2.50, -18.25, -22.00, -21.50, 16.00, -29.08, 10.00, 13.00,
  52.50, 62.00, 28.00, -0.53, -19.03, -42.00, 21.00, 9.00, -10.00, -15.00,
  -6.00, 13.00, 30.00, 52.00, 46.83, -25.07, 18.23, 39.50, 6.00, -23.00,
  25.50, -21.10, 46.00, 60.00, -2.00, 25.00, -8.00, -4.58, 15.00, 62.00,
  1.37, -15.95, 46.25, 78.00, 48.67, 8.50, 43.93, 14.00, 6.00, 4.00, 1.00,
  13.83, 35.00, -26.50, 21.73, 15.00, 8.00, 15.00, 39.00, -9.00, 40.00,
  34.00, -20.00, -9.00, 39.00, 11.00, -8.00, 23.50, -6.00, 49.00, 2.00,
  54.00, 38.00, -33.00, 41.00, 41.90, 13.08, 8.00, 18.50, 18.50, 16.00,
  -16.00, -14.00, -13.58, 15.50, -12.83, 44.00, -30.00, -15.00, -1.00,
  -19.00)

zero.render.map.png <- function(outfile, countries, values, w=740, h=354) {
  zero.setup.png(filename=outfile, w=w, h=h)
  on.exit(dev.off())
  par(mar=c(0,0,0,0))
  map('worldHires')
  countries.x <- country.long[match(countries, country.codes)]
  countries.y <- country.lat[match(countries, country.codes)]
  prop <- sqrt(values / max(values))
#  color <- rgb(sqrt(prop), 0, 1-sqrt(prop))
  color <- 'red'
  symbols(x=countries.x,
          y=countries.y,
          circles=(prop * 12),
          fg=color,
          bg=color,
          inches=F,
          add=T)
}
""")

R("""
# FEAR
.C("gddSetFTFontPath", as.character("%(font_path)s"), PACKAGE="GDD")
""" % {'font_path': rave_font_path})

default_width = 740
default_height = 400

import os

@op_file
@mime_type('image/png')
def render_map(out_file, country_col, data_col, width, height):
    R.zero_render_map_png(out_file, w=width, h=height,
                          countries=country_col, values=data_col)
    if out_file[-4:] != '.png':
        os.rename(out_file + '.png', out_file)


@op_file
@mime_type('image/png')
def render_timeseries_multi(out_file, label_col, time_col, data_col,
                            width, height, sdate, edate, by,
                            log=None, ylim=None, ylab='y'):
    sdate = iso_datetime(sdate)
    edate = iso_datetime(edate)
    labels = []
    l_time = {}
    l_data = {}
    for i in xrange(len(label_col)):
        (label, time, data) = (label_col[i], time_col[i], data_col[i])
        if time >= sdate and time <= edate:
            if label not in l_time:
                labels.append(label)
                l_time[label] = []
                l_data[label] = []
            l_time[label].append(time)
            l_data[label].append(float(data))
    l_times = [ l_time[l] for l in labels ]
    l_datas = [ l_data[l] for l in labels ]
    kwargs = {}
    if log:
        kwargs['log'] = log
    R.zero_render_multi_ts_png(out_file, width=width, height=height,
                               sdate=sdate, edate=edate, by=by,
                               ylim=ylim, ylab=ylab, labels=labels,
                               time=l_times, data=l_datas, **kwargs)
    if out_file[-4:] != '.png':
        os.rename(out_file + '.png', out_file)

@op_file
@mime_type('image/png')
def render_timeseries(out_file, time_col, data_col,
                      width, height, sdate, edate, by,
                      log=None, ylim=None):
    sdate = iso_datetime(sdate)
    edate = iso_datetime(edate)
    kwargs = {}
    if log:
      kwargs['log'] = log
    R.zero_render_ts_png(out_file, width=width, height=height,
                         sdate=sdate, edate=edate, by=by,
                         ylim=ylim, time=time_col, data=map(float, data_col),
                         **kwargs)
    if out_file[-4:] != '.png':
        os.rename(out_file + '.png', out_file)

@op_file
@mime_type('image/png')
def render_blank(out_file, width, height):
    R.zero_render_no_data_png(out_file, w=width, h=height)
    if out_file[-4:] != '.png':
        os.rename(out_file + '.png', out_file)

@op_file
@mime_type('image/png')
def render_scatter(out_file, x_col, y_col,
                   width, height, xlim=None, ylim=None, xlab='', ylab=''):
    R.zero_render_scatter_png(out_file, x_col, y_col, width, height,
                              xlim=xlim, ylim=ylim, xlab=xlab, ylab=ylab)
    if out_file[-4:] != '.png':
        os.rename(out_file + '.png', out_file)
