gnuplotrb 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d42c4f1c4c5be11d3c393f511a24de68744aeac1
4
+ data.tar.gz: dc1035d41e16bfd1413f22bfe37194747f8e4966
5
+ SHA512:
6
+ metadata.gz: 6d0d96f5abeec5638c9642cc08f73caf3cbdc00695b820a159d00a52cdba780c928072f65b0ee6d11e163aab52c2ace600c3d78b3be0017a51890636c3aaa100
7
+ data.tar.gz: 5cf75980f6ba0ddbb262f8062d7bb7c009ad970df5a4ed9988b4256d35badf3d2bb867d91f9bd21d32cf2c8cccd7ab0c03706fc92f6f6e766cd9d82dc12b660a
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gnuplotrb.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Ivan Evgrafov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,34 @@
1
+ = GnuplotRB
2
+
3
+ This is part of ruby gnuplot gem. It already can plot something (see examples and notebooks) but some features still waiting for implementation.
4
+
5
+ {<img src="https://travis-ci.org/dilcom/gnuplotrb.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/dilcom/gnuplotrb]
6
+ {<img src="https://codeclimate.com/github/dilcom/gnuplotrb/badges/gpa.svg" alt="Code quality" />}[https://codeclimate.com/github/dilcom/gnuplotrb]
7
+ {<img src="https://codeclimate.com/github/dilcom/gnuplotrb/badges/coverage.svg" alt="Test coverage" />}[https://codeclimate.com/github/dilcom/gnuplotrb]
8
+
9
+
10
+ == Installation
11
+ While gem isn't on rubygems, it may be installed from source.
12
+ === Dependencies
13
+ * Ruby 2.0+
14
+ * It is required to install {gnuplot 5.0}[http://www.gnuplot.info/download.html] to use that gem.
15
+ === Gem installation
16
+ ==== Install latest version from repository (may be unstable)
17
+ git clone https://github.com/dilcom/gnuplotrb.git
18
+ cd gnuplotrb
19
+ bundle install
20
+ rake install
21
+ ==== Install latest stable vrsion
22
+ gem install gnuplotrb
23
+ ==== Install latest stable vrsion using bundler
24
+ * add
25
+ gem 'gnuplotrb'
26
+ to your Gemfile
27
+ * run
28
+ bundle install
29
+
30
+ == Plain examples
31
+ You may find several examples in {examples directory}[https://github.com/dilcom/gnuplotrb/tree/master/examples]
32
+
33
+ == Notebooks with examples
34
+ You may find several iRuby notebooks and readme for them in {notebooks directory}[https://github.com/dilcom/gnuplotrb/tree/master/notebooks]
@@ -0,0 +1,17 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rspec/core'
4
+ require 'rdoc/task'
5
+ require 'rubocop/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec) do |spec|
8
+ spec.pattern = FileList['spec/**/*_spec.rb'].uniq
9
+ spec.rspec_opts = '--format documentation'
10
+ end
11
+
12
+ RDoc::Task.new do |rdoc|
13
+ rdoc.main = 'README.rdoc'
14
+ rdoc.rdoc_files.include %w(README.rdoc lib)
15
+ end
16
+
17
+ RuboCop::RakeTask.new
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gnuplotrb/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'gnuplotrb'
8
+ spec.version = GnuplotRB::VERSION
9
+ spec.authors = ['Ivan Evgrafov']
10
+ spec.email = ['dilcom3107@gmail.com']
11
+
12
+ spec.summary = 'Ruby bindings for gnuplot'
13
+ spec.description = 'Renewed ruby bindings for gnuplot. Started at GSoC 2015.'
14
+ spec.homepage = 'https://github.com/dilcom/gnuplotrb'
15
+ spec.license = 'MIT'
16
+ spec.required_ruby_version = '>= 2.0'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(/^(test|spec|unimplemented_features|examples|future_work|notebooks|\..+)/) }
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_runtime_dependency 'hamster', '~> 1.0'
22
+ spec.add_development_dependency 'bundler', '~> 1.7'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'rspec', '~> 3.2'
25
+ spec.add_development_dependency 'rdoc', '~> 4.2'
26
+ spec.add_development_dependency 'rubocop', '~> 0.29'
27
+ spec.add_development_dependency 'codeclimate-test-reporter'
28
+ spec.add_development_dependency 'chunky_png'
29
+ spec.add_development_dependency 'daru'
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'tempfile'
2
+ require 'hamster'
3
+ require 'open3'
4
+
5
+ def require_if_available(name)
6
+ begin
7
+ require name
8
+ rescue LoadError
9
+ false
10
+ end
11
+ end
12
+
13
+ require_if_available('daru')
14
+
15
+ require 'gnuplotrb/external_classes/string'
16
+ require 'gnuplotrb/external_classes/array'
17
+ require 'gnuplotrb/external_classes/daru'
18
+ require 'gnuplotrb/external_classes/iruby'
19
+
20
+ require 'gnuplotrb/version'
21
+ require 'gnuplotrb/staff/settings'
22
+ require 'gnuplotrb/mixins/option_handling'
23
+ require 'gnuplotrb/mixins/error_handling'
24
+ require 'gnuplotrb/mixins/plottable'
25
+ require 'gnuplotrb/staff/terminal'
26
+ require 'gnuplotrb/staff/datablock'
27
+ require 'gnuplotrb/staff/dataset'
28
+ require 'gnuplotrb/plot'
29
+ require 'gnuplotrb/splot'
30
+ require 'gnuplotrb/multiplot'
@@ -0,0 +1,14 @@
1
+ class Array
2
+ # taken for example from current gnuplot bindings
3
+ def to_gnuplot_points
4
+ return '' if self.empty?
5
+ case self[0]
6
+ when Array
7
+ self[0].zip(*self[1..-1]).map { |a| a.join(' ') }.join("\n")
8
+ when Numeric
9
+ join("\n")
10
+ else
11
+ self[0].zip(*self[1..-1]).to_gnuplot_points
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ if defined? Daru
2
+ module Daru
3
+ class DataFrame
4
+ def to_gnuplot_points
5
+ result = ''
6
+ self.each_row_with_index do |row, index|
7
+ result += "#{index.to_s} "
8
+ result += row.to_a.join(' ')
9
+ result += "\n"
10
+ end
11
+ result
12
+ end
13
+ end
14
+
15
+ class Vector
16
+ def to_gnuplot_points
17
+ result = ''
18
+ self.each_with_index do |value, index|
19
+ result += "#{index} #{value}\n"
20
+ end
21
+ result
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ if defined?(IRuby)
2
+ module GnuplotRB
3
+ module Plottable
4
+ def to_iruby
5
+ available_terminals = {
6
+ 'png' => 'image/png',
7
+ 'pngcairo' => 'image/png',
8
+ 'jpeg' => 'image/jpeg',
9
+ 'svg' => 'image/svg+xml',
10
+ 'dumb' => 'text/plain'
11
+ }
12
+ terminal, options = term.is_a?(Array) ? [term[0], term[1]] : [term, {}]
13
+ terminal = 'svg' unless available_terminals.keys.include?(terminal)
14
+ [available_terminals[terminal], self.send("to_#{terminal}".to_sym, **options)]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ class String
2
+ def to_gnuplot_points
3
+ clone
4
+ end
5
+ end
@@ -0,0 +1,42 @@
1
+ module GnuplotRB
2
+ ##
3
+ # Just a new error name
4
+ class GnuplotError < ArgumentError
5
+ end
6
+
7
+ ##
8
+ # Mixin for classes that need to run subprocess and
9
+ # handle errors from its stderr.
10
+ module ErrorHandling
11
+ ##
12
+ # ====== Overview
13
+ # Check if there were errors in previous commands.
14
+ # Throws GnuplotError in case of any errors.
15
+ def check_errors
16
+ unless @err_array.empty?
17
+ command = @err_array.first
18
+ rest = @err_array[1..-1].join('; ')
19
+ message = "Error in previous command (\"#{command}\"): \"#{rest}\""
20
+ @err_array.clear
21
+ fail GnuplotError, message
22
+ end
23
+ end
24
+
25
+ ##
26
+ # ====== Overview
27
+ # Start new thread that will read stderr given as stream
28
+ # and add errors into @err_array.
29
+ def handle_stderr(stream)
30
+ @err_array = []
31
+ Thread.new do
32
+ until (line = stream.gets).nil? do
33
+ line.strip!
34
+ @err_array << line if line.size > 3
35
+ end
36
+ end
37
+ end
38
+
39
+ private :check_errors,
40
+ :handle_stderr
41
+ end
42
+ end
@@ -0,0 +1,157 @@
1
+ module GnuplotRB
2
+ ##
3
+ # ====== Overview
4
+ # This module contains methods which are mixed into several classes
5
+ # to set, get and convert their options.
6
+ module OptionHandling
7
+ class << self
8
+ # Some values of options should be quoted to be read by gnuplot
9
+ #
10
+ # TODO: update list with data from gnuplot documentation !!!
11
+ QUOTED_OPTIONS = %w(
12
+ title
13
+ output
14
+ xlabel
15
+ x2label
16
+ ylabel
17
+ y2label
18
+ clabel
19
+ cblabel
20
+ zlabel
21
+ rgb
22
+ font
23
+ )
24
+
25
+ ##
26
+ # For inner use!
27
+ # Replacement '_' with ' ' is made to allow passing several options
28
+ # with the same first word of key.
29
+ # See issue #7 for more info.
30
+ def string_key(key)
31
+ key.to_s.gsub(/_/) { ' ' } + ' '
32
+ end
33
+
34
+ ##
35
+ # ====== Overview
36
+ # Recursive function that converts Ruby option to gnuplot string
37
+ # ====== Arguments
38
+ # * *key* - name of option in gnuplot
39
+ # * *option* - an option that should be converted
40
+ # ====== Examples
41
+ # option_to_string(['png', size: [300, 300]]) #=> 'png size 300,300'
42
+ # option_to_string(xrange: 0..100) #=> 'xrange [0:100]'
43
+ # option_to_string(multiplot: true) #=> 'multiplot'
44
+ def option_to_string(key = nil, option)
45
+ return string_key(key) if !!option == option # check for boolean
46
+ value = ruby_class_to_gnuplot(option)
47
+ value = "\"#{value}\"" if QUOTED_OPTIONS.include?(key.to_s)
48
+ ## :+ here is necessary, because using #{value} will remove quotes
49
+ value = string_key(key) + value if key
50
+ value
51
+ end
52
+
53
+ ##
54
+ # Method for inner use.
55
+ # Needed to convert several ruby classes into
56
+ # value that should be piped to gnuplot.
57
+ def ruby_class_to_gnuplot(option_object)
58
+ case option_object
59
+ when Array
60
+ option_object.map { |el| option_to_string(el) }
61
+ .join(option_object[0].is_a?(Numeric) ? ',' : ' ')
62
+ when Hash
63
+ option_object.map { |i_key, i_val| option_to_string(i_key, i_val) }
64
+ .join(' ')
65
+ when Range
66
+ "[#{option_object.begin}:#{option_object.end}]"
67
+ else
68
+ option_object.to_s
69
+ end
70
+ end
71
+
72
+ ##
73
+ # ====== Overview
74
+ # Check if given terminal available for use.
75
+ # ====== Arguments
76
+ # * *terminal* - terminal to check (e.g. 'png', 'qt', 'gif')
77
+ def valid_terminal?(terminal)
78
+ Settings.available_terminals.include?(terminal)
79
+ end
80
+
81
+ ##
82
+ # ====== Overview
83
+ # Check if given options are valid for gnuplot.
84
+ # Raises ArgumentError if invalid options found.
85
+ # ====== Arguments
86
+ # * *options* - Hash of options to check
87
+ # (e.g. {term: 'qt', title: 'Plot title'})
88
+ #
89
+ # Now checks only terminal name.
90
+ def validate_terminal_options(options)
91
+ terminal = options[:term]
92
+ if terminal
93
+ terminal = terminal[0] if terminal.is_a?(Array)
94
+ message = 'Seems like your Gnuplot does not ' \
95
+ 'support that terminal, please see supported ' \
96
+ 'terminals with Settings::available_terminals'
97
+ fail(ArgumentError, message) unless valid_terminal?(terminal)
98
+ end
99
+ end
100
+ end
101
+
102
+ ##
103
+ # You should implement #initialize in classes that use OptionsHelper
104
+ def initialize(*args)
105
+ fail NotImplementedError, 'You should implement #initialize' \
106
+ ' in classes that use OptionsHelper!'
107
+ end
108
+
109
+ ##
110
+ # You should implement #new_with_options in classes that use OptionsHelper
111
+ def new_with_options(*args)
112
+ fail NotImplementedError, 'You should implement #new_with_options' \
113
+ ' in classes that use OptionsHelper!'
114
+ end
115
+
116
+ ##
117
+ # ====== Overview
118
+ # Create new Plot (or Dataset or Splot or Multiplot) object where current
119
+ # options are merged with given. If no options
120
+ # given it will just return existing set of options.
121
+ # ====== Arguments
122
+ # * *options* - options to add. If no options given, current
123
+ # options are returned.
124
+ # ====== Example
125
+ # sin_graph = Plot.new(['sin(x)', title: 'Sin'], title: 'Sin on [0:3]', xrange: 0..3)
126
+ # sin_graph.plot
127
+ # sin_graph_update = sin_graph.options(title: 'Sin on [-10:10]', xrange: -10..10)
128
+ # sin_graph_update.plot
129
+ # # this may also be considered as
130
+ # # sin_graph.title(...).xrange(...)
131
+ def options(**options)
132
+ @options ||= Hamster::Hash.new
133
+ if options.empty?
134
+ @options
135
+ else
136
+ new_with_options(@options.merge(options))
137
+ end
138
+ end
139
+
140
+ ##
141
+ # Method for inner use.
142
+ # ====== Arguments
143
+ # * *key* - [Symbol] - option key
144
+ # * *value* - anything treated as options value in gnuplot gem
145
+ def option(key, *value)
146
+ if value.empty?
147
+ value = options[key]
148
+ value = value[0] if value && value.size == 1
149
+ value
150
+ else
151
+ options(key => value)
152
+ end
153
+ end
154
+
155
+ private :option
156
+ end
157
+ end
@@ -0,0 +1,102 @@
1
+ module GnuplotRB
2
+ ##
3
+ # This module contains methods that should be mixed into
4
+ # plottable classes. It includes OptionHandling and
5
+ # implements several plotting methods.
6
+ module Plottable
7
+ include OptionHandling
8
+
9
+ ##
10
+ # Terminal object used by this Plottable to pipe data to gnuplot.
11
+ attr_reader :terminal
12
+
13
+ ##
14
+ # You should implement #plot in classes that are Plottable
15
+ def plot(*args)
16
+ fail NotImplementedError, 'You should implement #plot in classes that are Plottable!'
17
+ end
18
+
19
+ ##
20
+ # Method for inner use.
21
+ # ====== Overview
22
+ # Method which outputs plot to specific terminal (possibly some file).
23
+ # Explicit use should be avoided. This method is called from #method_missing
24
+ # when it handles method names like #to_png(options).
25
+ # ====== Arguments
26
+ # * *terminal* - string corresponding to terminal type (png, html, jpeg etc)
27
+ # * *path* - path to output file, if none given it will output to temp file
28
+ # and then read it and return binary contents of file
29
+ # * *options* - used in 'set term <term type> <options here>'
30
+ # ====== Examples
31
+ # ## plot here may be Plot, Splot, Multiplot or any other plottable class
32
+ # plot.to_png('./result.png', size: [300, 500])
33
+ # contents = plot.to_svg(size: [100, 100])
34
+ # plot.to_dumb('./result.txt', size: [30, 15])
35
+ def to_specific_term(terminal, path = nil, **options)
36
+ if path
37
+ result = plot(term: [terminal, options], output: path)
38
+ else
39
+ path = Dir::Tmpname.make_tmpname(terminal, 0)
40
+ plot(term: [terminal, options], output: path)
41
+ result = File.binread(path)
42
+ File.delete(path)
43
+ end
44
+ result
45
+ end
46
+
47
+ ##
48
+ # ====== Overview
49
+ # In this gem #method_missing is used both to handle
50
+ # options and to handle plotting to specific terminal.
51
+ #
52
+ # ====== Options handling
53
+ # ======= Overview
54
+ # You may set options using #option_name(option_value) method.
55
+ # A new object will be constructed with selected option set.
56
+ # And finally you can get current value of any option using
57
+ # #options_name without arguments.
58
+ # ======= Arguments
59
+ # * *option_value* - value to set an option. If none given
60
+ # method will just return current option's value
61
+ # ======= Examples
62
+ # plot = Splot.new
63
+ # new_plot = plot.title('Awesome plot')
64
+ # plot.title #=> nil
65
+ # new_plot.title #=> 'Awesome plot'
66
+ #
67
+ # ====== Plotting to specific term
68
+ # ======= Overview
69
+ # Gnuplot offers possibility to output graphics to many image formats.
70
+ # The easiest way to to so is to use #to_<plot_name> methods.
71
+ # ======= Arguments
72
+ # * *options* - set of options related to terminal (size, font etc).
73
+ # Be careful, some terminals have their own specific options.
74
+ # ======= Examples
75
+ # # font options specific for png term
76
+ # multiplot.to_png('./result.png', size: [300, 500], font: ['arial', 12])
77
+ # # font options specific for svg term
78
+ # content = multiplot.to_svg(size: [100, 100], fname: 'Arial', fsize: 12)
79
+ def method_missing(meth_id, *args)
80
+ meth = meth_id.id2name
81
+ if meth[0..2] == 'to_'
82
+ term = meth[3..-1]
83
+ super unless OptionHandling.valid_terminal?(term)
84
+ to_specific_term(term, *args)
85
+ else
86
+ option(meth_id, *args)
87
+ end
88
+ end
89
+
90
+ ##
91
+ # Returns true foe existing methods and
92
+ # #to_<term_name> when name is a valid terminal type.
93
+ def respond_to?(meth_id)
94
+ # Next line is here to force iRuby use #to_iruby
95
+ # instead of #to_svg.
96
+ return super if defined? IRuby
97
+ meth = meth_id.id2name
98
+ term = meth[0..2] == 'to_' && OptionHandling.valid_terminal?(meth[3..-1])
99
+ term || super
100
+ end
101
+ end
102
+ end