I'm using Ruby 1.9.2 p180.
I'm writing a continuous evaluation tool for Rubyvis (to be part of SciRuby). Basically, you set up the Rubyvis::Panel
in your input file (e.g., test.rb
), and this SciRuby class (Plotter) watches test.rb
for modifications. When there's a change, SciRuby runs the script through eval
.
The script works if I run it from the command line, but when executed through eval
, the plot is wrong -- a straight line, as if all the data is gone, instead of what you see here. Note: Previously, it said here that the SVG was different -- but it turns out this was the result of REXML being loaded instead of nokogiri.
Here are the test scripts and eval code. Most produce the straight line (with exceptions described in the edit section below).
I haven't the faintest how this is happening.
I have a few ideas as to why it might be happening, but no clue as to the mechanism.
eval
doesn't allow deep copies to be made. Objects that are taken from eval
are missing pieces in certain contexts, particularly when lambda is used to process the data into the correct format for the plot.eval
is not honoring the bundled dep list when require
is called -- maybe the wrong version of nokogiri is being used in my binding?Has anyone seen anything like this before? I'm sort of feeling around in the dark -- at a total loss as to where to begin troubleshooting.
It seems that the call to OpenStruct.new
is causing the problem.
If I define data as a list of lists, data = pv.range(0,10,0.1).map { |d| [d,Math.sin(d)+2+rand()] }
, it works well.
But when data is defined as a list of OpenStructs, the following code gives incorrect output:
data = pv.range(0, 10, 0.1).map {|x|
o = OpenStruct.new({:x=> x, :y=> Math.sin(x) + 2+rand()})
STDERR.puts o.inspect # Output is correct.
o
}
STDERR.puts "size of data: #{data.size}"
STDERR.puts "first x = #{data.first.x}" # Output is first x = 0.0
STDERR.puts "first y = #{data.first.y}" # Output is first y = (WRONG)
I can even induce an error if I use collect when assigning the data, e.g.,
vis.add(pv.Line).data(data.collect { |d| [d.x,d.y] }
plotter.rb:88:in `block in <main>': undefined method `x' for [0.0, nil]:Array (NoMethodError)
versus no error with vis.add(pv.Line).data(data)
. The error appears to originate from the call to eval("vis.render()", bind)
in my app's source (not in the plot script).
It turns out that if I just use a hash, e.g., {:x => x, :y => Math.sin(x)}
, that works fine. But when I explicitly say Hash.new({:x => x, :y => Math.sin(x)})
, that gives an error regardless of how I call vis.data:
rubyvis/lib/rubyvis/internals.rb:184:in `each': comparison of Hash with Hash failed (ArgumentError)
So the difference is in how my data is assigned. The question is: why?
Copies of the inputs are available in the original gist. Thanks for your help.
It turns out that if I just use a hash, e.g., {:x => x, :y => Math.sin(x)}, that works fine. But when I explicitly say Hash.new({:x => x, :y => Math.sin(x)}), that gives an error regardless of how I call vis.data:
First of all, your call to Hash.new is wrong. Hash.new takes a parameter that's the default value of the hash.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With