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.
- data/lib/rubyplots/orchestrator.rb +96 -0
- data/lib/rubyplots/scatterplot.rb +54 -0
- data/lib/rubyplots.rb +65 -0
- metadata +51 -0
@@ -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: []
|