# Part of the Optimus package for managing E-Prime data # # Copyright (C) 2008 Board of Regents of the University of Wisconsin System # # Written by Nathan Vack , at the Waisman Laborotory for Brain # Imaging and Behavior, University of Wisconsin - Madison # A runner to take eprime data files, chew them through a pesudo-templater, # and produce delicious files for importing into other packages. They'll look # like: # # presented onset offset # stim1 5992 6493 # stim2 7294 7981 # # This class should handle argument processing, file I/O, and such. # TODO: Think up a clever way to make this handle arbitrary transformers # Probably this is possible by passing the class of the transformer to # this runner, and instance_eval()'ing the template file in its presence. require 'eprime' require 'eprime_reader' require 'tabfile_writer' require 'transformers/timing_extractor' require 'optparse' require 'ostruct' module Eprime module Runners class GenericRunner include ::Eprime::Transformers attr_accessor :out, :err def initialize(extractor_class, script_name, *args) @extractor_class = extractor_class @script_name = script_name @out = STDOUT @err = STDERR @args = args @data = nil @timing_extractor = nil end def process! process_arguments(*@args) validate read_data extract_timings write_timings end def read_data data = Eprime::Data.new @options.input_files.each do |infile| File.open(infile) do |f| new_data = Eprime::Reader.new(f).eprime_data data.merge!(new_data) end end @data = data end def extract_timings @timing_extractor = @extractor_class.new(@data) template_code = '' File.open(@options.template_file) { |f| template_code = f.read } @timing_extractor.instance_eval(template_code) end def write_timings if @options.outfile @out = File.open(@options.outfile, 'w') end writer = TabfileWriter.new( @timing_extractor.extracted_data, @out, {:column_labels => @options.column_labels}) begin writer.write rescue Errno::EPIPE => e # This is OK ensure if @options.outfile @out.close end end end def validate if @options.help || @args.flatten.size == 0 show_help! and raise Exception.new() end if @options.input_files.empty? raise ArgumentError.new("no input files given\n#{usage}") end if !@options.template_file raise ArgumentError.new("no template file given\n#{usage}") end if !File.readable?(@options.template_file) raise ArgumentError.new("can't read #{@options.template_file}\n#{usage}") end return true end def show_help! @err.puts @op.to_s end def usage "#{@op.banner.to_s} \n#{@script_name} --help for help" end private def process_arguments(*args) @options = OpenStruct.new( :help => false, :outfile => nil, :column_labels => true, :template_file => nil, :input_files => [] ) op = OptionParser.new() do |op| op.banner = "Usage: extract_timings --template TEMPLATE_FILE [OPTIONS] INPUT_FILES" op.separator '' op.on('-t', '--template=TEMPLATE_FILE', String, 'A template containing commands describing', 'how to process these files' ) { |t| @options.template_file = t } op.separator '' op.on('--[no-]column-labels', 'Print column lablels in the first row.', 'If not specified, do print labels.' ) { |l| @options.column_labels = l } op.separator '' op.on('-o', '--outfile=OUTFILE', "The name of the file to save to. If not", "given, print to standard output." ) { |o| @options.outfile = o } op.separator '' op.on_tail('-h', '--help', 'Print this message.' ) { |h| @options.help = h } end @options.input_files = op.parse(*args) || [] @op = op end end end end