summaryrefslogtreecommitdiff
path: root/report/plot_application.rb
blob: 1e498f2a14fd9f7e3ec90019ffdb3db34fc13b77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
require 'digest/md5'

class Validation::Application < OpenTox::Application

  helpers do
    def r_eval(cmd)
#      $logger.debug cmd
      @r.eval cmd
    end
  end

  # produces a boxplot
  # params should be given in URI, e.g. : ..boxplot/test_values=5.8,5.6,5.3;predicted=5.9
  # ; separates series (or categories)
  # = seperates key and values for each series
  # , seperates values for each series
  # 'hline=<float>' can be given as optional param (with '?') to draw horizontal lines with the given stepwidth
  # (default: no horizontal lines, lines allow to compare different plots)
  get '/validation/boxplot/:vals' do

    filename = "#{Digest::MD5.hexdigest(params[:vals].inspect+params[:hline].inspect+params[:size].inspect)}.png"
    unless (File.exists?("/tmp/#{filename}"))
      # retrieve values
      vals = {}
      params[:vals].split(";").collect do |x|
          y = x.split("=")
          vals[y[0]] = (y[1] ? y[1].split(",").collect{|z| z.to_f} : nil)
      end
      names = "c(\""+vals.keys.join("\",\"")+"\")"
      values = vals.values.collect{|a| "c("+(a ? a.join(",") : "")+")"}.join(",")
      
      # the min range is set to hline*2 to draw at least two horizontal lines
      hline = params[:hline] ? params[:hline].to_f : nil
      unless hline
        ylim = ""
      else
        min = vals.values.flatten.compact.min
        max = vals.values.flatten.compact.max
        if (max-min<(hline*2))
          to_add = (hline*2)-(max-min)
          min -= to_add/2.0
          max += to_add/2.0
        end
        range = "c(#{min},#{max})"
        ylim = ",ylim=#{range}"
      end

      # return "boxplot(#{values},col=c('red','blue','green'),names=#{names}#{ylim})"
      @r = RinRuby.new(true,false)
      size = (params[:size] ? params[:size].to_i : 300)
      r_eval "png(\"/tmp/#{filename}\",width=#{2*size},height=#{size})"
      r_eval "par(mai=c(0.5,0.5,0.2,0.2))"
      r_eval "boxplot(#{values},col=c('red','blue','green'),names=#{names}#{ylim})"
      if hline
        # seq defines were to draw hline
        # example: min -9.5, max 10.5, hline = 2 -> seq(-10,12,by=2) -> produces lines from -10 to 12 with step-width 2
        r_eval "abline(h=seq(floor(#{min}/#{hline})*#{hline}, round(#{max}/#{hline})*#{hline}, by=#{hline}),lty=2,col='dimgrey')"
      end
      r_eval 'dev.off()'
      @r.quit
    end
    send_file("/tmp/#{filename}",:filename=>"#{params[:vals]}.png",:type=>'image/png',:disposition => 'inline')
  end

  get '/validation/binplot/:vals' do

    filename = "#{Digest::MD5.hexdigest(params[:vals].inspect+params[:size].inspect)}.png"
    unless (File.exists?("/tmp/#{filename}")) and false

      @r = RinRuby.new(true,false)
      size = (params[:size] ? params[:size].to_i : 300)

      # each bin is given as x1,x2,y
      xvals = []
      yvals = []
      params[:vals].split(";").each do |bin|
        x1,x2,y = bin.split(",")
        if xvals.size==0 # first add point at y=0 to add a vertrical line from 0 to x1
          xvals << x1.to_f
          yvals << 0
        end
        # for each bin, add an additional point at y=0 to draw a vertrical line to 0
        xvals += [x1.to_f, x2.to_f, x2.to_f]
        yvals += [y.to_f,  y.to_f, 0]
      end
      # add first point again to draw horizontal line at y=0
      xvals << xvals[0]
      yvals << yvals[0]

      r_eval "x <- c(#{xvals.join(",")})"
      r_eval "y <- c(#{yvals.join(",")})"
      r_eval "png(\"/tmp/#{filename}\",width=#{2*size},height=#{size})"
#      r_eval "par(mai=c(0.5,0.5,0.2,0.2))"
#      r_eval "par(mfrow=c(2,4))"
      r_eval "plot(x,y,type='n', xlim=rev(range(x)), ylim=c(0,max(y)), xlab='#{params[:xlab]}', ylab='#{params[:ylab]}')" # type='n',
#      r_eval "par(pch=22, col='red')"
      r_eval "lines(x,y, type='l', col='red')"
      r_eval "title(main='#{params[:title]}')"
      r_eval 'dev.off()'
      @r.quit
    end
    send_file("/tmp/#{filename}",:filename=>"#{params[:vals]}.png",:type=>'image/png',:disposition => 'inline')
  end

end