rubyplots 0.0.1

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,96 @@
1
+ #-------------------------------------------------
2
+ # Copyright (c) 2014 Matthew Pate
3
+ # This program is licensed under the MIT License
4
+ # Please see the file 'copying.txt' in the source
5
+ # distribution of this software for license terms.
6
+ # ------------------------------------------------
7
+
8
+ require_relative './scatterplot'
9
+ require 'fileutils'
10
+
11
+
12
+ class Orchestrator
13
+
14
+ @latexPath = nil
15
+ @tempLatexDirectory = nil
16
+
17
+ def initialize(tempLatexDirectory)
18
+ validateLatexPackages
19
+ @tempLatexDirectory = tempLatexDirectory
20
+ @latexFile = File.join(@tempLatexDirectory, 'RubyPlotsLatexFile.tex')
21
+ writeOpeningTo @latexFile
22
+ end
23
+
24
+ def addLatexFor(dataFile)
25
+ ScatterPlot.new( dataFile, @latexFile )
26
+ end
27
+
28
+ def generatePlots
29
+ writeClosingTo @latexFile
30
+ compile @latexFile
31
+ end
32
+
33
+ def savePlotsAndCleanup(latexDir)
34
+ parentDir = File.dirname(latexDir)
35
+ plotsToKeep = Dir.glob(latexDir + File::SEPARATOR + "rubyplots-*.pdf")
36
+ plotsToKeep.each do |plot|
37
+ FileUtils.move(plot, parentDir, {:force => true})
38
+ end
39
+ # Todo: Review options for this remove - this is unsecure right now.
40
+ FileUtils.rm_rf @tempLatexDirectory
41
+ end
42
+
43
+
44
+ private
45
+
46
+ def compile(pathToLatex)
47
+ latexDir = File.split(pathToLatex)[0]
48
+ file = File.split(pathToLatex)[1]
49
+
50
+ FileUtils.cd latexDir
51
+ enableLatexSystemCallsFor file
52
+ system "pdflatex #{file} > /dev/null"
53
+ end
54
+
55
+ # A requirement of generating individual PDF's
56
+ # Todo: Figure out why you get 2 errors here that don't seem to effect compilation...
57
+ def enableLatexSystemCallsFor(latex)
58
+ system "pdflatex -shell-escape #{File.basename(latex, ".tex")} > /dev/null"
59
+ end
60
+
61
+ # Validates that latex, tikz, and pgfplots are installed
62
+ def validateLatexPackages
63
+ if which("pdflatex").nil? || !(system "kpsewhich tikz > /dev/null") || !(system "kpsewhich pgfplots > /dev/null")
64
+ raise "Missing required latex packages."
65
+ end
66
+ end
67
+
68
+ def which(cmd)
69
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
70
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
71
+ exts.each { |ext|
72
+ exe = File.join(path, "#{cmd}#{ext}")
73
+ return exe if File.executable? exe
74
+ }
75
+ end
76
+ return nil
77
+ end
78
+
79
+ def writeOpeningTo(file)
80
+ File.open(file, "a") do |f|
81
+ f << '\\documentclass{article}' + "\n"
82
+ f << '\\usepackage{pgfplots}' + "\n"
83
+ f << '\\pgfplotsset{compat = newest}' + "\n"
84
+ f << '\\usepgfplotslibrary{external}' + "\n"
85
+ f << '\\tikzexternalize' + "{#{File.basename(file, ".tex")}}\n"
86
+ f << '\\begin{document}' + "\n"
87
+ end
88
+ end
89
+
90
+ def writeClosingTo(file)
91
+ File.open(file, "a") do |f|
92
+ f << '\\end{document}'
93
+ end
94
+ end
95
+
96
+ end
@@ -0,0 +1,54 @@
1
+ #-------------------------------------------------
2
+ # Copyright (c) 2014 Matthew Pate
3
+ # This program is licensed under the MIT License
4
+ # Please see the file 'copying.txt' in the source
5
+ # distribution of this software for license terms.
6
+ # ------------------------------------------------
7
+
8
+ require 'csv'
9
+
10
+
11
+ class ScatterPlot
12
+
13
+ def initialize(dataFile, latexFile)
14
+ writeScatterPlot(dataFile, latexFile)
15
+ end
16
+
17
+ private
18
+
19
+ # This reads the datafile in a way that requires a certain format.
20
+ # The title of this scatterplot becomes the name of the pdf file (minus the extension).
21
+ # The first line of the file must be the names of the x and y columns.
22
+ # Multiple words for an x or y column must be enclosed in brackets (see validateColumnNames)
23
+ def writeScatterPlot(dataFile, latexFile)
24
+
25
+ # Raising a custom error here because CSV.open will throw this automatically as expected and prefered, but
26
+ # File.open will simply create a file if it doesn't exist, which we don't want, so we're just going to perform
27
+ # the error handling here (rather than letting CSV throw and us manually throwing for File).
28
+ if !(File.exists?(dataFile) && File.exists?(latexFile))
29
+ raise SystemCallError, "One of '#{dataFile}' or '#{latexFile}' do not exist."
30
+ end
31
+
32
+ CSV.open(dataFile, "r", {:col_sep => "\t"}) do |data|
33
+ colNames = data.readline
34
+ validateColumnNames(colNames[0], colNames[1])
35
+
36
+ File.open(latexFile, "a") do |file|
37
+ fileBasename = File.basename(dataFile, ".scatterplot")
38
+ file << '\\tikzsetnextfilename' + "{rubyplots-#{fileBasename}}\n"
39
+ file << '\\begin{tikzpicture}' + "\n"
40
+ file << '\\begin{axis}' + "[title=#{fileBasename}, xlabel=#{colNames[0]}, ylabel=#{colNames[1]}]\n"
41
+ file << '\\addplot table [only marks, ' + "x=#{colNames[0]}, y=#{colNames[1]}] {#{dataFile}};\n"
42
+ file << '\\end{axis}' + "\n"
43
+ file << '\\end{tikzpicture}' + "\n"
44
+ end
45
+ end
46
+ end
47
+
48
+ def validateColumnNames(x, y)
49
+ if ( (x.split.count > 1 && (x[0] != "{" || x[-1] != "}")) || (y.split.count > 1 && (y[0] != "{" || y[1] != "}")) )
50
+ raise "Columns with multiple words dectected in data file and no enclosing brackets found. One of: '#{x}' or '#{y}'"
51
+ end
52
+ end
53
+
54
+ end
data/lib/rubyplots.rb ADDED
@@ -0,0 +1,65 @@
1
+ #-------------------------------------------------
2
+ # Copyright (c) 2014 Matthew Pate
3
+ # This program is licensed under the MIT License
4
+ # Please see the file 'copying.txt' in the source
5
+ # distribution of this software for license terms.
6
+ # ------------------------------------------------
7
+
8
+ require_relative './rubyplots/orchestrator'
9
+
10
+
11
+ class RubyPlots
12
+
13
+ @orchestrator = nil
14
+
15
+ def initialize
16
+ end
17
+
18
+ # data can be a file or directory
19
+ def generatePlotsFor(data)
20
+ dataPath = File.expand_path(data)
21
+ tempLatexDir = createTempDirectoryFor dataPath
22
+ @orchestrator = Orchestrator.new(tempLatexDir)
23
+
24
+ if File.directory? dataPath
25
+ checkTypeAndGenerateForDir dataPath
26
+ else
27
+ checkTypeAndGenerateForFile dataPath
28
+ end
29
+
30
+ @orchestrator.generatePlots
31
+ @orchestrator.savePlotsAndCleanup tempLatexDir
32
+ end
33
+
34
+
35
+ private
36
+
37
+ def createTempDirectoryFor(fileOrDir)
38
+ newDir = nil
39
+ if File.directory? fileOrDir
40
+ newDir = File.join(fileOrDir, 'RubyPlotsWorkingDir')
41
+ else
42
+ newDir = File.join(File.dirname(fileOrDir), 'RubyPlotsWorkingDir')
43
+ end
44
+ Dir.mkdir(newDir)
45
+ return newDir
46
+ end
47
+
48
+ def checkTypeAndGenerateForFile(file)
49
+ if isRightType?(file)
50
+ @orchestrator.addLatexFor(file)
51
+ end
52
+ end
53
+
54
+ def checkTypeAndGenerateForDir(dir)
55
+ Dir.entries(dir).each do |file|
56
+ # We loose the full path on .entries, so rejoin.
57
+ checkTypeAndGenerateForFile File.join(dir, file)
58
+ end
59
+ end
60
+
61
+ def isRightType?(file)
62
+ return File.extname(file) == ".scatterplot"
63
+ end
64
+
65
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubyplots
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Matthew Pate
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-04-06 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: RubyPlots can be set loose on a directory of datafiles or a singluar
15
+ datafile. It uses the file extension to determine a datafile of interest and, using
16
+ the Latex PgfPlots library, creates a single pdf plot for each data file. See the
17
+ Homepage for questions. Enjoy!
18
+ email:
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - lib/rubyplots.rb
24
+ - lib/rubyplots/scatterplot.rb
25
+ - lib/rubyplots/orchestrator.rb
26
+ homepage: http://mcpate.github.io/RubyPlots/
27
+ licenses:
28
+ - MIT
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubyforge_project:
47
+ rubygems_version: 1.8.23
48
+ signing_key:
49
+ specification_version: 3
50
+ summary: RubyPlots - An open source plotting utility for Ruby!
51
+ test_files: []