Permalink
Browse files

Merged in changes from master

  • Loading branch information...
mohawkjohn committed Sep 29, 2011
2 parents 8808c37 + 3b462d3 commit 3c7c13ad803d3874f7be0a6063023795697352f4
Showing with 237 additions and 2 deletions.
  1. +8 −2 lib/sciruby.rb
  2. +98 −0 lib/sciruby/analysis.rb
  3. +87 −0 lib/sciruby/analysis/suite.rb
  4. +44 −0 lib/sciruby/analysis/suite_report_builder.rb
View
@@ -51,15 +51,21 @@ def dataset_search database, args = {}
def dataset database, source_id
"SciRuby::Data::#{database.to_s.camelize}".constantize.new.dataset(source_id)
end
+
+ # Shorthand for SciRuby::Analysis.store(*args, &block)
+ def analyze *args, &block
+ SciRuby::Analysis.store(*args, &block)
+ end
end
+ autoload(:Analysis, File.join(DIR, 'sciruby', 'analysis'))
autoload(:Config, File.join(DIR, 'sciruby', 'config'))
- autoload(:Plotter, File.join(DIR, 'sciruby', 'plotter'))
autoload(:Editor, File.join(DIR, 'sciruby', 'editor'))
+ autoload(:Plotter, File.join(DIR, 'sciruby', 'plotter'))
autoload(:Recommend, File.join(DIR, 'sciruby', 'recommend'))
autoload(:Validation, File.join(DIR, 'sciruby', 'validation'))
autoload(:Data, File.join(DIR, 'sciruby', 'data'))
end
autoload(:Shoes, File.join(SciRuby::DIR, 'ext', 'shoes'))
-autoload(:CSV, File.join(SciRuby::DIR, 'ext', 'csv'))
+autoload(:CSV, File.join(SciRuby::DIR, 'ext', 'csv'))
View
@@ -0,0 +1,98 @@
+require 'sciruby/analysis/suite'
+require 'sciruby/analysis/suite_report_builder'
+
+module SciRuby
+ # DSL to run a statistical analysis without hassle.
+ # * Shortcut methods to avoid having to use complete namespaces, many based on R.
+ # * Attach/detach vectors to workspace, as with R
+ # == Example
+ # an1 = Statsample::Analysis.store(:first) do
+ # # Load excel file with x,y,z vectors
+ # ds = excel('data.xls')
+ # # See variables on ds dataset
+ # names(ds)
+ # # Attach the vectors to workspace, like R
+ # attach(ds)
+ # # vector 'x' is attached to workspace like a method,
+ # # so you can use like any variable
+ # mean,sd = x.mean, x.sd
+ # # Shameless R robbery
+ # a = c( 1:10)
+ # b = c(21:30)
+ # summary(cor(ds)) # Call summary method on correlation matrix
+ # end
+ # # You can run the analysis by its name
+ # Statsample::Analysis.run(:first)
+ # # or using the returned variables
+ # an1.run
+ # # You can also generate a report using ReportBuilder.
+ # # .summary() method call 'report_building' on the object,
+ # # instead of calling text summary
+ # an1.generate("report.html")
+ module Analysis
+ @@stored_analyses={}
+ @@last_analysis=nil
+ def self.clear_analysis
+ @@stored_analyses.clear
+ end
+ def self.stored_analyses
+ @@stored_analyses
+ end
+ def self.last
+ @@stored_analyses[@@last_analysis]
+ end
+ def self.store(name, opts=Hash.new,&block)
+ raise "You should provide a block" if !block
+ @@last_analysis=name
+ opts={:name=>name}.merge(opts)
+ @@stored_analyses[name]=Suite.new(opts,&block)
+ end
+ # Run analysis +*args+
+ # Without arguments, run all stored analyses
+ # Only 'echo' will be printed to screen.
+ def self.run(*args)
+ args=stored_analyses.keys if args.size==0
+ raise "Analysis #{args} doesn't exists" if (args - stored_analyses.keys).size>0
+ args.each do |name|
+ stored_analyses[name].run
+ end
+ end
+
+ # Add analysis +*args+ to a ReportBuilder object.
+ # Without arguments, add all stored analyses.
+ # Each analysis is wrapped inside a ReportBuilder::Section object.
+ # This is the method used by +save+ and +to_text+.
+ def self.add_to_reportbuilder(rb, *args)
+ args=stored_analyses.keys if args.size==0
+ raise "Analysis #{name} doesn't exists" if (args - stored_analyses.keys).size>0
+ args.each do |name|
+ section=ReportBuilder::Section.new(:name=>stored_analyses[name].name)
+ rb_an=stored_analyses[name].add_to_reportbuilder(section)
+ rb.add(section)
+ rb_an.run
+ end
+ end
+
+ # Save the analysis to a file.
+ # Without arguments, adds all stored analyses.
+ def self.save(filename, *args)
+ rb=ReportBuilder.new(:name=>filename)
+ add_to_reportbuilder(rb, *args)
+ rb.save(filename)
+ end
+
+ # Run analysis and return as string.
+ # Only 'echo' will be printed to screen.
+ # Without arguments, add all stored analyses.
+ def self.to_text(*args)
+ rb=ReportBuilder.new(:name=>"Analysis #{Time.now}")
+ add_to_reportbuilder(rb, *args)
+ rb.to_text
+ end
+
+ # Run analysis and print to screen all echo and summary callings
+ def self.run_batch(*args)
+ puts to_text(*args)
+ end
+ end
+end
@@ -0,0 +1,87 @@
+require "statsample"
+
+module SciRuby
+ module Analysis
+ class Suite
+ include ::Statsample::Shorthand
+ attr_accessor :output
+ attr_accessor :name
+ attr_reader :block
+ def initialize(opts=Hash.new(), &block)
+ if !opts.is_a? Hash
+ opts={:name=>opts}
+ end
+
+ @block=block
+ @name=opts[:name] || "Analysis #{Time.now}"
+ @attached=[]
+ @output=opts[:output] || ::STDOUT
+ end
+ # Run the analysis, putting output on
+ def run
+ @block.arity<1 ? instance_eval(&@block) : @block.call(self)
+ end
+ # Provides a description of the procedure. Only appears as a commentary on
+ # SuiteReportBuilder outputs
+ def desc(d)
+ @output.puts("Description:")
+ @output.puts(" #{d}")
+ end
+ def echo(*args)
+ @output.puts(*args)
+ end
+ def summary(obj)
+ obj.summary
+ end
+ def add_to_reportbuilder(rb)
+ SuiteReportBuilder.new({:name=>name, :rb=>rb}, &block)
+ end
+
+ def generate(filename)
+ ar=SuiteReportBuilder.new({:name=>name}, &block)
+ ar.generate(filename)
+ end
+ def to_text
+ ar=SuiteReportBuilder.new({:name=>name}, &block)
+ ar.to_text
+ end
+
+ def attach(ds)
+ @attached.push(ds)
+ end
+ def detach(ds=nil)
+ if ds.nil?
+ @attached.pop
+ else
+ @attached.delete(ds)
+ end
+ end
+ alias :old_boxplot :boxplot
+ alias :old_histogram :histogram
+ alias :old_scatterplot :scatterplot
+
+ def show_svg(svg)
+ require 'tmpdir'
+ fn=Dir.tmpdir+"/image_#{Time.now.to_f}.svg"
+ File.open(fn,"w") {|fp| fp.write svg}
+ `xdg-open '#{fn}'`
+ end
+ def boxplot(*args)
+ show_svg(old_boxplot(*args).to_svg)
+ end
+ def histogram(*args)
+ show_svg(old_histogram(*args).to_svg)
+ end
+ def scatterplot(*args)
+ show_svg(old_scatterplot(*args).to_svg)
+ end
+
+ def method_missing(name, *args,&block)
+ @attached.reverse.each do |ds|
+ return ds[name.to_s] if ds.fields.include? (name.to_s)
+ end
+ raise "Method #{name} doesn't exists"
+ end
+ end
+ end
+end
@@ -0,0 +1,44 @@
+module SciRuby
+ module Analysis
+ class SuiteReportBuilder < Suite
+ attr_accessor :rb
+ def initialize(opts=Hash.new,&block)
+ if !opts.is_a? Hash
+ opts={:name=>opts}
+ end
+ super(opts,&block)
+ @rb=opts[:rb] || ReportBuilder.new(:name=>name)
+ end
+ def generate(filename)
+ run if @block
+ @rb.save(filename)
+ end
+ def to_text
+ run if @block
+ @rb.to_text
+ end
+ def summary(o)
+ @rb.add(o)
+ end
+ def desc(d)
+ @rb.add(d)
+ end
+ def echo(*args)
+ args.each do |a|
+ @rb.add(a)
+ end
+ end
+
+ def boxplot(*args)
+ @rb.add(old_boxplot(*args))
+ end
+ def histogram(*args)
+ @rb.add(old_histogram(*args))
+ end
+ def boxplot(*args)
+ @rb.add(old_boxplot(*args))
+ end
+
+ end
+ end
+end

0 comments on commit 3c7c13a

Please sign in to comment.