Last active
January 7, 2017 06:42
-
-
Save rinx/4995d71729514d6a6e7791ad3f2abf9e to your computer and use it in GitHub Desktop.
Histogram libraries for ruby using gnuplot gem
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# hist_gp.rb | |
# | |
# Author: Rintaro Okamura | |
# | |
# Description: | |
# Histogram libraries for ruby using gnuplot gem | |
# | |
require 'gnuplot' | |
module HistGnuplot | |
class Hist | |
def initialize | |
end | |
end | |
# 2D histogram | |
class Hist2D | |
attr_accessor :xdata, :ydata, | |
:title, :xlabel, :ylabel, :cblabel, | |
:binres_x, :binres_y, | |
:interval_x, :interval_y, | |
:dx, :dy, :x, :y, | |
:max_x, :max_y, | |
:min_x, :min_y, | |
:logscale | |
def initialize(xdata, ydata, bin_x=100, bin_y=100) | |
@binres_x = bin_x | |
@binres_y = bin_y | |
@xdata = xdata | |
@ydata = ydata | |
@max_x = xdata.max.to_f | |
@min_x = xdata.min.to_f | |
@max_y = ydata.max.to_f | |
@min_y = ydata.min.to_f | |
@max_x = 999.0 if @max_x.infinite? | |
@max_y = 999.0 if @max_y.infinite? | |
@min_x = -999.0 if @min_x.infinite? | |
@min_y = -999.0 if @min_y.infinite? | |
@logscale = false | |
end | |
def plot(outfilepath='none') | |
@interval_x = ((@max_x - @min_x).to_f / @binres_x).to_f | |
@interval_y = ((@max_y - @min_y).to_f / @binres_y).to_f | |
@dx = @interval_x / 2.0 | |
@dy = @interval_y / 2.0 | |
@x = [] | |
@y = [] | |
@binres_x.times do |i| | |
@x.push(@min_x + @interval_x * (i + 1).to_f - @dx) | |
end | |
@binres_y.times do |i| | |
@y.push(@min_y + @interval_y * (i + 1).to_f - @dy) | |
end | |
hist = Array.new(@binres_x).map{Array.new(@binres_y, 0)} | |
@binres_x.times do |ix| | |
insidebin_x_index = @xdata.each_with_index.select {|a| | |
a[0] >= (@x[ix]) and a[0] < (@x[ix] + @interval_x) | |
}.map{|a| a[1]} | |
@binres_y.times do |iy| | |
insidebin_y_index = @ydata.each_with_index.select {|a| | |
a[0] >= (@y[iy]) and a[0] < (@y[iy] + @interval_y) | |
}.map{|a| a[1]} | |
hist[ix][iy] = (insidebin_x_index & insidebin_y_index).length | |
end | |
end | |
Gnuplot.open do |gp| | |
SPlot.new(gp) do |plot| | |
case outfilepath | |
when /^none$/ | |
plot.terminal 'x11' | |
when /\.tex$/ | |
plot.terminal "tikz" | |
plot.output File.expand_path(outfilepath) | |
when /\.pdf$/ | |
plot.terminal "pdf" | |
plot.output File.expand_path(outfilepath) | |
when /\.png$/ | |
plot.terminal "pngcairo" | |
plot.output File.expand_path(outfilepath) | |
else | |
STDERR.puts "Error: unknown filetype" | |
exit | |
end | |
plot.title @title | |
plot.xlabel @xlabel | |
plot.ylabel @ylabel | |
plot.cblabel @cblabel | |
plot.set "datafile missing \"Infinity\"" | |
plot.set "key off" | |
plot.set "view map" | |
plot.set "size square" | |
plot.xrange "[#{@min_x}:#{@max_x}]" | |
plot.yrange "[#{@min_y}:#{@max_y}]" | |
if @logscale | |
plot.cbrange "[1:#{hist.flatten.max}]" | |
plot.set "logscale cb" | |
else | |
plot.cbrange "[0:#{hist.flatten.max}]" | |
end | |
plot.set "palette defined ( 0 '#000090', 1 '#000fff', 2 '#0090ff', 3 '#0fffee', 4 '#90ff70', 5 '#ffee00', 6 '#ff7000', 7 '#ee0000', 8 '#7f0000')" | |
plot.data << | |
Gnuplot::DataSet.new([@x, @y, hist]) do |ds| | |
ds.with = 'image pixels' | |
end | |
end | |
end | |
end | |
end | |
end | |
private | |
# https://github.com/rdp/ruby_gnuplot/blob/master/lib/gnuplot.rb#L358 | |
class SPlot < Gnuplot::Plot | |
def initialize (io = nil, cmd = "splot") | |
@cmd = cmd | |
@settings = [] | |
@arbitrary_lines = [] | |
@data = [] | |
@styles = [] | |
yield self if block_given? | |
$stderr.puts "writing this to gnuplot:\n" + to_gsplot + "\n" if $VERBOSE | |
if io | |
io << to_gsplot | |
io << store_datasets | |
end | |
end | |
def to_gsplot (io = "") | |
@settings.each do |setting| | |
io << setting.map(&:to_s).join(" ") << "\n" | |
end | |
@styles.each{|s| io << s.to_s << "\n"} | |
@arbitrary_lines.each{|line| io << line << "\n" } | |
io | |
end | |
def store_datasets (io = "") | |
if @data.size > 0 | |
io << @cmd << " " << @data.collect { |e| e.plot_args }.join(", ") | |
io << "\n" | |
v = @data.collect { |ds| ds.to_gsplot } | |
io << v.compact.join("e\n") | |
end | |
end | |
end | |
class Array | |
def to_gsplot | |
f = "" | |
if ( self[0].kind_of? Array ) then | |
x = self[0] | |
y = self[1] | |
d = self[2] | |
x.each_with_index do |xv, i| | |
y.each_with_index do |yv, j| | |
f << [ xv, yv, d[i][j] ].join(" ") << "\n" | |
end | |
f << "\n" | |
end | |
elsif ( self[0].kind_of? Numeric ) then | |
self.length.times do |i| f << "#{self[i]}\n" end | |
else | |
self[0].zip( *self[1..-1] ).to_gsplot | |
end | |
f | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment