Module: Plot::PlotUtils

Defined in:
lib/redshift/util/plot.rb

Overview

Module for creating “fire and forget” plot windows. Instead of a plot window that your main program keeps interacting with, these windows are created with one specific plot and left to be closed by the user. No cleanup is required.

The functions in this module cam be accessed in two ways

include Plot::PlotUtils
gnuplot do ... end

or

Plot::PlotUtils.gnuplot do ... end

Class Method Summary collapse

Class Method Details

.fork_returning_resultObject

:nodoc:



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/redshift/util/plot.rb', line 293

def fork_returning_result # :nodoc:
  read_result, write_result = IO.pipe
  fork do
    read_result.close
    result_setter = proc do |r|
      write_result.write Marshal.dump(r)
      write_result.close
    end
    yield result_setter
  end
  write_result.close
  
  begin
    Marshal.load(read_result.read)
  rescue => ex
    ex ## ?
  end
ensure
  [write_result, read_result].each do |io|
    io.close unless io.closed?
  end
end

.gnuplot(app = nil, &bl) ⇒ Object

Yields and returns the Plot instance. On unix/linux, the returned plot instance can no longer be used to send more plot commands, since it is just a copy of the real plot instance which is in a child process. On windows, be sure not to exit immediately after calling this method, or else tempfiles will be deleted before gnuplot has had a chance to read them.



284
285
286
287
288
289
290
291
# File 'lib/redshift/util/plot.rb', line 284

def gnuplot(app=nil, &bl)
  begin
    gnuplot_fork(app, &bl)
  rescue NotImplementedError => ex
    raise unless ex.message =~ /fork/
    gnuplot_no_fork(app, &bl)
  end
end

.gnuplot_fork(app = nil, &bl) ⇒ Object

:nodoc:



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/redshift/util/plot.rb', line 316

def gnuplot_fork(app=nil, &bl) # :nodoc:
  Plot.new(app || 'gnuplot') do |plot|
    unless bl
      raise ArgumentError, "no block given"
    end
    bl[plot]
    
    if plot.is_to_file
      plot.commit
      plot.show
      plot.close
      result = plot
    
    else
      result = fork_returning_result do |result_setter|
        trap "INT" do exit end
        trap "TERM" do exit end # clean up tempfiles

        plot.command "set mouse"
          # redundant, but in some gp versions must do this
          # before the set term in the line below:
        plot.set_window_title plot.uniqname
        if plot.has_working_close_event
          plot.command "bind allwindows Close 'exit gnuplot'"
        end

        plot.commit
        result = plot.dup
        result.clear_data
        result.instance_eval {@files = nil; @pid = Process.pid}
        result_setter.call result
        plot.show

        if plot.has_working_close_event
          Process.wait # wait for gnuplot to exit
        else
          loop do
            sleep 5
            wmstate = `xprop -name #{plot.uniqname} WM_STATE 2>&1`
            break if not $?.success?
            break if wmstate[/window state:\s*withdrawn/i]
          end
        end
      end
    end

    return result
  end
end

.gnuplot_no_fork(app = nil, &bl) ⇒ Object

:nodoc:



366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
# File 'lib/redshift/util/plot.rb', line 366

def gnuplot_no_fork(app=nil, &bl) # :nodoc:
  # assume windows
  Plot.new("#{app || "pgnuplot.exe"} -persist") do |plot|
      # -persist is nicer on windows: supports mouse/key interaction
    bl[plot]
    if plot.is_to_file
      plot.commit
      plot.show
      plot.close
    
    else
      plot.command "bind allwindows Close 'exit gnuplot'"
      plot.command "bind allwindows 'q' 'exit gnuplot'"
      plot.commit
      plot.show
    end
  end
end