gnuplotrb 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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