module R module SVG def self.ggplotSVG(data, script = nil, width = nil, height = nil, options = {}) width ||= 3 height ||= 3 values = [] options = options.dup sources = [:plot, Rbbt.share.Rlib["svg.R"].find(:lib), options[:source]].flatten.compact options.delete :source fast = options[:fast] if fast save_method = "rbbt.SVG.save.fast" else save_method = "rbbt.SVG.save" end if data data.each do |k,v| v = Array === v ? v : [v] next if v == "NA" or v.nil? or v.include? "NA" or v.include? nil values = v break end values = [values] unless Array === values field_classes = values.collect do |v| v = v.first if Array === v case v when FalseClass, TrueClass "'logical'" when Fixnum, Float "'numeric'" when String if v.strip =~ /^[-+]?[\d\.]+$/ "'numeric'" else "'character'" end when Symbol "'factor'" else ":NA" end end if field_classes.any? options[:R_open] ||= "colClasses=c('character'," + field_classes * ", " + ')' else options[:R_open] ||= "colClasses=c('character')" end TmpFile.with_file nil, true, :extension => 'svg' do |tmpfile| data.R <<-EOF, sources, options plot = { #{script} } #{save_method}('#{tmpfile}', plot, width = #{R.ruby2R width}, height = #{R.ruby2R height}) data = NULL EOF Open.read(tmpfile).gsub(/(glyph\d+-\d+)/, '\1-' + File.basename(tmpfile)) end else TmpFile.with_file nil, true, :extension => 'svg' do |tmpfile| R.run <<-EOF, sources, options plot = { #{script} } #{save_method}('#{tmpfile}', plot, width = #{R.ruby2R width}, height = #{R.ruby2R height}) data = NULL EOF Open.read(tmpfile).gsub(/(glyph\d+-\d+)/, '\1-' + File.basename(tmpfile)) end end end end module PNG def self.ggplotPNG(filename, data, script = nil, width = nil, height = nil, options = {}) width ||= 3 height ||= 3 values = [] sources = [:plot, options[:source]].flatten.compact data.each do |k,v| v = Array === v ? v : [v] next if v == "NA" or v.nil? or v.include? "NA" or v.include? nil values = v break end values = [values] unless Array === values field_classes = values.collect do |v| case v when FalseClass, TrueClass "'logical'" when Fixnum, Float "'numeric'" when String if v.strip =~ /^[-+]?[\d\.]+$/ "'numeric'" else "'character'" end when Symbol "'factor'" else ":NA" end end options[:R_open] ||= "colClasses=c('character'," + field_classes * ", " + ')' data.R <<-EOF, :plot, options plot = { #{script} } ggsave('#{filename}', plot, width = #{R.ruby2R width}, height = #{R.ruby2R height}) data = NULL EOF end def self.plot(filename, data = nil, script = nil, width = nil, height = nil, options = {}, &block) width ||= 200 height ||= 200 values = [] script ||= "" if block_given? s = StringIO.new class << s def method_missing(name, *args) name = name.to_s if name[-1] == '=' arg = args.first value = if String === arg arg else R.ruby2R arg end add("" << name[0..-2] << "=" << value) else args_strs = [] args.each do |arg| value = if String === arg arg else R.ruby2R arg end args_strs << value end add("" << name << "(" << args_strs * ", " << ")") end end def add(line) self.write line << "\n" end end block.call(s) s.rewind script << "\n" << s.read end sources = [:plot, options[:source]].flatten.compact if data data.each do |k,v| v = Array === v ? v : [v] next if v == "NA" or v.nil? or v.include? "NA" or v.include? nil values = v break end values = [values] unless values.nil? or Array === values field_classes = values.collect do |v| case v when FalseClass, TrueClass "'logical'" when Fixnum, Float "'numeric'" when String if v.strip =~ /^[-+]?[\d\.]+$/ "'numeric'" else "'character'" end when Symbol "'factor'" else ":NA" end end options[:R_open] ||= "colClasses=c('character'," + field_classes * ", " + ')' if field_classes.any? data.R <<-EOF, :plot, options png("#{ filename }", #{ width }, #{ height }) { #{script} } dev.off() data = NULL EOF else R.run <<-EOF, :plot, options png("#{ filename }", #{ width }, #{ height }) { #{script} } dev.off() EOF end end end end