youplot 0.3.5 → 0.4.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.
- checksums.yaml +4 -4
- data/README.md +27 -15
- data/lib/youplot.rb +4 -4
- data/lib/youplot/backends/processing.rb +9 -5
- data/lib/youplot/backends/{unicode_plot_backend.rb → unicode_plot.rb} +14 -11
- data/lib/youplot/command.rb +49 -14
- data/lib/youplot/dsv.rb +58 -48
- data/lib/youplot/options.rb +18 -0
- data/lib/youplot/parameters.rb +34 -0
- data/lib/youplot/parser.rb +306 -0
- data/lib/youplot/version.rb +1 -1
- metadata +6 -6
- data/lib/youplot/command/options.rb +0 -19
- data/lib/youplot/command/parser.rb +0 -305
- data/lib/youplot/command/plot_params.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83145e216c0d124d537c8a01d63f9203730a74191fefcb9de5743b08e0e504bd
|
4
|
+
data.tar.gz: a246eab22f11ab8c526cc838d9f2fbf7d249721b4782287087c08a5410f8647b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9138c26fade36d7d0ca19100b47dcb8e65c8c884d13b74d258dcae9ea304ced2fc783b08e871d76607e57e394e6b861c81f1f5030caba53493b2f4740a05cd2
|
7
|
+
data.tar.gz: f293d686791ba1481948877e534c9085e99c24ab9c36026979002ecaa9ee2ece6f12ad7193cda936c62e472e2f94008466cc666e9405157bfcc348c4c21c4579
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<p align="center">
|
2
2
|
<img src="logo.svg" width="60%" height="60%" />
|
3
|
-
</
|
3
|
+
</p>
|
4
4
|
|
5
5
|

|
6
6
|
[](https://badge.fury.io/rb/youplot)
|
@@ -106,8 +106,8 @@ In this example, YouPlot counts the number of chromosomes where the gene is loca
|
|
106
106
|
|
107
107
|
```sh
|
108
108
|
cat gencode.v35.annotation.gff3 \
|
109
|
-
| grep -v '#' | grep 'gene' | cut -f1
|
110
|
-
uplot count -t "The number of human gene annotations per chromosome" -c blue
|
109
|
+
| grep -v '#' | grep 'gene' | cut -f1 \
|
110
|
+
| uplot count -t "The number of human gene annotations per chromosome" -c blue
|
111
111
|
```
|
112
112
|
|
113
113
|
<p align="center">
|
@@ -119,7 +119,7 @@ This is fine in most cases, as long as the data size is small. If you want to vi
|
|
119
119
|
|
120
120
|
```sh
|
121
121
|
cat gencode.v35.annotation.gff3 | grep -v '#' | grep 'gene' | cut -f1 \
|
122
|
-
|sort | uniq -c | sort -nrk2 | awk '{print $2,$1}' \
|
122
|
+
| sort | uniq -c | sort -nrk2 | awk '{print $2,$1}' \
|
123
123
|
| uplot bar -d ' ' -t "The number of human gene annotations per chromosome" -c blue
|
124
124
|
```
|
125
125
|
|
@@ -130,15 +130,15 @@ cat gencode.v35.annotation.gff3 | grep -v '#' | grep 'gene' | cut -f1 \
|
|
130
130
|
Wouldn't it be a pain to have to run R, Python, Julia, gnuplot or whatever REPL just to check your data?
|
131
131
|
YouPlot is a command line tool for this purpose. With YouPlot, you can continue working without leaving your terminal and shell.
|
132
132
|
|
133
|
-
###
|
133
|
+
### How to use YouPlot?
|
134
134
|
|
135
135
|
`uplot` is the shortened form of `youplot`. You can use either.
|
136
136
|
|
137
|
-
|
|
138
|
-
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
137
|
+
| Command | Description |
|
138
|
+
|------------------------------------------------|-----------------------------------|
|
139
|
+
| `cat data.tsv \| uplot <command> [options]` | Take input from stdin |
|
140
|
+
| `uplot <command> [options] data.tsv ...` | Take input from files |
|
141
|
+
| `pipeline1 \| uplot <command> -O \| pipeline2` | Outputs data from stdin to stdout |
|
142
142
|
|
143
143
|
### Where to output the plot?
|
144
144
|
|
@@ -148,7 +148,8 @@ The output file or stream for the plot can be specified with the `-o` option.
|
|
148
148
|
### Where to output the input data?
|
149
149
|
|
150
150
|
By default, the input data is not shown anywhere.
|
151
|
-
The `-O` option, with no arguments, outputs the input data directly to the standard output.
|
151
|
+
The `-O` option, with no arguments, outputs the input data directly to the standard output.
|
152
|
+
This is useful when passing data to a subsequent pipeline.
|
152
153
|
|
153
154
|
### What types of plots are available?
|
154
155
|
|
@@ -176,11 +177,21 @@ If your input data contains a header line, you need to specify the `-H` option.
|
|
176
177
|
|
177
178
|
### How to specify the delimiter?
|
178
179
|
|
179
|
-
Use the `-d` option. To specify a blank space, you can use `uplot bar -d ' ' data.txt`.
|
180
|
+
Use the `-d` option. To specify a blank space, you can use `uplot bar -d ' ' data.txt`.
|
181
|
+
You do not need to use `-d` option for tab-delimited text since the default value is tab.
|
180
182
|
|
181
183
|
### Is there a way to specify a column as the x-axis or y-axis?
|
182
184
|
|
183
|
-
Not yet.
|
185
|
+
Not yet.
|
186
|
+
YouPlot treats the first column as the X axis and the second column as the Y axis.
|
187
|
+
When working with multiple series, the first column is the X axis, the second column is series Y1, the third column is series Y2, and so on.
|
188
|
+
If you pass only one column of data for `line` and `bar`, YouPlot will automatically use a sequential number starting from 1 as the X-axis.
|
189
|
+
|
190
|
+
* `--fmt xyy` `--fmt xyxy` `--fmt yx` options give you a few more choices.
|
191
|
+
See `youplot <command> --help` for more details.
|
192
|
+
|
193
|
+
* Use `awk '{print $2, $1}'` to swap lines.
|
194
|
+
* Use `paste` to concatenate series.
|
184
195
|
|
185
196
|
### How to plot real-time data?
|
186
197
|
|
@@ -216,14 +227,15 @@ uplot colors
|
|
216
227
|
|
217
228
|
## Contributing
|
218
229
|
|
219
|
-
YouPlot is a library under development, so even small improvements like typofix are welcome!
|
230
|
+
YouPlot is a library under development, so even small improvements like typofix are welcome!
|
231
|
+
Please feel free to send us your pull requests.
|
220
232
|
|
221
233
|
* [Report bugs](https://github.com/kojix2/youplot/issues)
|
222
234
|
* Fix bugs and [submit pull requests](https://github.com/kojix2/youplot/pulls)
|
223
235
|
* Write, clarify, or fix documentation
|
224
236
|
* English corrections by native speakers are welcome.
|
225
237
|
* Suggest or add new features
|
226
|
-
|
238
|
+
* Make a donation
|
227
239
|
|
228
240
|
### Development
|
229
241
|
|
data/lib/youplot.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
require_relative 'youplot/version'
|
4
|
+
require_relative 'youplot/dsv'
|
5
|
+
require_relative 'youplot/parameters'
|
6
|
+
require_relative 'youplot/command'
|
7
7
|
|
8
8
|
module YouPlot
|
9
9
|
class << self
|
@@ -11,12 +11,16 @@ module YouPlot
|
|
11
11
|
if tally && Enumerable.method_defined?(:tally)
|
12
12
|
arr.tally
|
13
13
|
else
|
14
|
-
#
|
15
|
-
arr.
|
16
|
-
.tap { |h| h.default = nil }
|
14
|
+
# value_counts Enumerable::Statistics
|
15
|
+
arr.value_counts(dropna: false)
|
17
16
|
end
|
18
|
-
.sort
|
19
|
-
|
17
|
+
.sort do |a, b|
|
18
|
+
# compare values
|
19
|
+
r = b[1] <=> a[1]
|
20
|
+
# If the values are the same, compare by name
|
21
|
+
r = a[0] <=> b[0] if r == 0
|
22
|
+
r
|
23
|
+
end
|
20
24
|
.transpose
|
21
25
|
end
|
22
26
|
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# UnicodePlot - Plot your data by Unicode characters
|
4
|
+
# https://github.com/red-data-tools/unicode_plot.rb
|
5
|
+
|
3
6
|
require_relative 'processing'
|
4
7
|
require 'unicode_plot'
|
5
8
|
|
6
9
|
module YouPlot
|
7
10
|
# plotting functions.
|
8
11
|
module Backends
|
9
|
-
module
|
12
|
+
module UnicodePlot
|
10
13
|
class Error < StandardError; end
|
11
14
|
|
12
15
|
module_function
|
@@ -39,7 +42,7 @@ module YouPlot
|
|
39
42
|
labels = series[x_col]
|
40
43
|
values = series[y_col].map(&:to_f)
|
41
44
|
end
|
42
|
-
UnicodePlot.barplot(labels, values, **params.to_hc)
|
45
|
+
::UnicodePlot.barplot(labels, values, **params.to_hc)
|
43
46
|
end
|
44
47
|
|
45
48
|
def histogram(data, params)
|
@@ -47,7 +50,7 @@ module YouPlot
|
|
47
50
|
series = data.series
|
48
51
|
params.title ||= data.headers[0] if headers
|
49
52
|
values = series[0].map(&:to_f)
|
50
|
-
UnicodePlot.histogram(values, **params.to_hc)
|
53
|
+
::UnicodePlot.histogram(values, **params.to_hc)
|
51
54
|
end
|
52
55
|
|
53
56
|
def line(data, params, fmt = nil)
|
@@ -57,7 +60,7 @@ module YouPlot
|
|
57
60
|
# If there is only one series, it is assumed to be sequential data.
|
58
61
|
params.ylabel ||= headers[0] if headers
|
59
62
|
y = series[0].map(&:to_f)
|
60
|
-
UnicodePlot.lineplot(y, **params.to_hc)
|
63
|
+
::UnicodePlot.lineplot(y, **params.to_hc)
|
61
64
|
else
|
62
65
|
# If there are 2 or more series...
|
63
66
|
if fmt == 'yx'
|
@@ -75,7 +78,7 @@ module YouPlot
|
|
75
78
|
end
|
76
79
|
x = series[x_col].map(&:to_f)
|
77
80
|
y = series[y_col].map(&:to_f)
|
78
|
-
UnicodePlot.lineplot(x, y, **params.to_hc)
|
81
|
+
::UnicodePlot.lineplot(x, y, **params.to_hc)
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
@@ -94,9 +97,9 @@ module YouPlot
|
|
94
97
|
end
|
95
98
|
params.xlim ||= series[0].flatten.minmax # why need?
|
96
99
|
params.ylim ||= series[1..-1].flatten.minmax # why need?
|
97
|
-
plot = UnicodePlot.public_send(method1, series[0], series[1], **params.to_hc)
|
100
|
+
plot = ::UnicodePlot.public_send(method1, series[0], series[1], **params.to_hc)
|
98
101
|
2.upto(series.size - 1) do |i|
|
99
|
-
UnicodePlot.public_send(method2, plot, series[0], series[i], name: headers&.[](i))
|
102
|
+
::UnicodePlot.public_send(method2, plot, series[0], series[i], name: headers&.[](i))
|
100
103
|
end
|
101
104
|
plot
|
102
105
|
end
|
@@ -112,9 +115,9 @@ module YouPlot
|
|
112
115
|
params.xlim ||= series2.map(&:first).flatten.minmax # why need?
|
113
116
|
params.ylim ||= series2.map(&:last).flatten.minmax # why need?
|
114
117
|
x1, y1 = series2.shift
|
115
|
-
plot = UnicodePlot.public_send(method1, x1, y1, **params.to_hc)
|
118
|
+
plot = ::UnicodePlot.public_send(method1, x1, y1, **params.to_hc)
|
116
119
|
series2.each_with_index do |(xi, yi), i|
|
117
|
-
UnicodePlot.public_send(method2, plot, xi, yi, name: headers&.[]((i + 1) * 2))
|
120
|
+
::UnicodePlot.public_send(method2, plot, xi, yi, name: headers&.[]((i + 1) * 2))
|
118
121
|
end
|
119
122
|
plot
|
120
123
|
end
|
@@ -152,13 +155,13 @@ module YouPlot
|
|
152
155
|
series = data.series
|
153
156
|
headers ||= (1..series.size).map(&:to_s)
|
154
157
|
series.map! { |s| s.map(&:to_f) }
|
155
|
-
UnicodePlot.boxplot(headers, series, **params.to_hc)
|
158
|
+
::UnicodePlot.boxplot(headers, series, **params.to_hc)
|
156
159
|
end
|
157
160
|
|
158
161
|
def colors(color_names = false)
|
159
162
|
# FIXME
|
160
163
|
s = String.new
|
161
|
-
UnicodePlot::StyledPrinter::TEXT_COLORS.each do |k, v|
|
164
|
+
::UnicodePlot::StyledPrinter::TEXT_COLORS.each do |k, v|
|
162
165
|
s << v
|
163
166
|
s << k.to_s
|
164
167
|
unless color_names
|
data/lib/youplot/command.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'dsv'
|
4
|
-
require_relative '
|
4
|
+
require_relative 'parser'
|
5
5
|
|
6
6
|
# FIXME
|
7
|
-
require_relative 'backends/
|
7
|
+
require_relative 'backends/unicode_plot'
|
8
8
|
|
9
9
|
module YouPlot
|
10
10
|
Data = Struct.new(:headers, :series)
|
@@ -19,7 +19,7 @@ module YouPlot
|
|
19
19
|
@command = nil
|
20
20
|
@params = nil
|
21
21
|
@options = nil
|
22
|
-
@backend = YouPlot::Backends::
|
22
|
+
@backend = YouPlot::Backends::UnicodePlot
|
23
23
|
end
|
24
24
|
|
25
25
|
def run_as_executable
|
@@ -33,21 +33,34 @@ module YouPlot
|
|
33
33
|
@options ||= parser.options
|
34
34
|
@params ||= parser.params
|
35
35
|
|
36
|
+
# color command
|
36
37
|
if %i[colors color colours colour].include? @command
|
37
38
|
plot = create_plot
|
38
39
|
output_plot(plot)
|
39
|
-
|
40
|
+
return
|
41
|
+
end
|
42
|
+
|
43
|
+
# progressive mode
|
44
|
+
if options[:progressive]
|
40
45
|
stop = false
|
41
46
|
Signal.trap(:INT) { stop = true }
|
42
|
-
|
47
|
+
|
48
|
+
# make cursor invisible
|
49
|
+
options[:output].print "\e[?25l"
|
50
|
+
|
51
|
+
# mainloop
|
43
52
|
while (input = Kernel.gets)
|
44
53
|
n = main_progressive(input)
|
45
54
|
break if stop
|
46
55
|
|
47
56
|
options[:output].print "\e[#{n}F"
|
48
57
|
end
|
58
|
+
|
49
59
|
options[:output].print "\e[0J"
|
50
|
-
|
60
|
+
# make cursor visible
|
61
|
+
options[:output].print "\e[?25h"
|
62
|
+
|
63
|
+
# normal mode
|
51
64
|
else
|
52
65
|
# Sometimes the input file does not end with a newline code.
|
53
66
|
while (input = Kernel.gets(nil))
|
@@ -59,23 +72,32 @@ module YouPlot
|
|
59
72
|
private
|
60
73
|
|
61
74
|
def main(input)
|
75
|
+
# Outputs input data to a file or stdout.
|
62
76
|
output_data(input)
|
63
77
|
|
64
|
-
@data =
|
78
|
+
@data = parse_dsv(input)
|
65
79
|
|
80
|
+
# Debug mode, show parsed results
|
66
81
|
pp @data if options[:debug]
|
67
82
|
|
83
|
+
# When run as a program instead of a library
|
68
84
|
if YouPlot.run_as_executable?
|
69
85
|
begin
|
70
86
|
plot = create_plot
|
71
87
|
rescue ArgumentError => e
|
88
|
+
# Show only one line of error.
|
72
89
|
warn e.backtrace[0]
|
90
|
+
# Show error message in purple
|
73
91
|
warn "\e[35m#{e}\e[0m"
|
92
|
+
# Explicitly terminated with exit code: 1
|
74
93
|
exit 1
|
75
94
|
end
|
95
|
+
|
96
|
+
# When running YouPlot as a library (e.g. for testing)
|
76
97
|
else
|
77
98
|
plot = create_plot
|
78
99
|
end
|
100
|
+
|
79
101
|
output_plot(plot)
|
80
102
|
end
|
81
103
|
|
@@ -95,15 +117,28 @@ module YouPlot
|
|
95
117
|
@raw_data << input
|
96
118
|
|
97
119
|
# FIXME
|
98
|
-
@data =
|
120
|
+
@data = parse_dsv(@raw_data)
|
99
121
|
|
100
122
|
plot = create_plot
|
101
123
|
output_plot_progressive(plot)
|
102
124
|
end
|
103
125
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
126
|
+
def parse_dsv(input)
|
127
|
+
# If encoding is specified, convert to UTF-8
|
128
|
+
if options[:encoding]
|
129
|
+
input.force_encoding(options[:encoding])
|
130
|
+
.encode!('utf-8')
|
131
|
+
end
|
132
|
+
|
133
|
+
begin
|
134
|
+
data = DSV.parse(input, options[:delimiter], options[:headers], options[:transpose])
|
135
|
+
rescue CSV::MalformedCSVError => e
|
136
|
+
warn 'Failed to parse the text. '
|
137
|
+
warn 'Please try to set the correct character encoding with --encoding option.'
|
138
|
+
raise e
|
139
|
+
end
|
140
|
+
|
141
|
+
data
|
107
142
|
end
|
108
143
|
|
109
144
|
def create_plot
|
@@ -147,9 +182,9 @@ module YouPlot
|
|
147
182
|
|
148
183
|
def output_plot(plot)
|
149
184
|
case options[:output]
|
150
|
-
when IO
|
185
|
+
when IO, StringIO
|
151
186
|
plot.render(options[:output])
|
152
|
-
|
187
|
+
when String, Tempfile
|
153
188
|
File.open(options[:output], 'w') do |f|
|
154
189
|
plot.render(f)
|
155
190
|
end
|
@@ -158,7 +193,7 @@ module YouPlot
|
|
158
193
|
|
159
194
|
def output_plot_progressive(plot)
|
160
195
|
case options[:output]
|
161
|
-
when IO
|
196
|
+
when IO, StringIO
|
162
197
|
# RefactorMe
|
163
198
|
out = StringIO.new(String.new)
|
164
199
|
def out.tty?
|
data/lib/youplot/dsv.rb
CHANGED
@@ -3,41 +3,49 @@
|
|
3
3
|
require 'csv'
|
4
4
|
|
5
5
|
module YouPlot
|
6
|
-
#
|
6
|
+
# Module to handle DSV (Delimiter-separated values) format.
|
7
|
+
# Extract header and series.
|
7
8
|
module DSV
|
8
9
|
module_function
|
9
10
|
|
10
11
|
def parse(input, delimiter, headers, transpose)
|
11
|
-
|
12
|
+
# Parse as CSV
|
13
|
+
arr = CSV.parse(input, col_sep: delimiter)
|
14
|
+
|
15
|
+
# Remove blank lines
|
16
|
+
arr.delete_if do |i|
|
17
|
+
i == [] or i.all? nil
|
18
|
+
end
|
19
|
+
|
20
|
+
# get header
|
12
21
|
headers = get_headers(arr, headers, transpose)
|
22
|
+
|
23
|
+
# get series
|
13
24
|
series = get_series(arr, headers, transpose)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
|
26
|
+
# Return if No header
|
27
|
+
return Data.new(headers, series) if headers.nil?
|
28
|
+
|
29
|
+
# Warn if header contains nil
|
30
|
+
warn "\e[35mHeaders contains nil in it.\e[0m" if headers.include?(nil)
|
31
|
+
|
32
|
+
# Warn if header contains ''
|
33
|
+
warn "\e[35mHeaders contains \"\" in it.\e[0m" if headers.include? ''
|
34
|
+
|
35
|
+
# Make sure the number of elements in the header matches the number of series.
|
36
|
+
h_size = headers.size
|
37
|
+
s_size = series.size
|
38
|
+
|
39
|
+
if h_size > s_size
|
40
|
+
warn "\e[35mThe number of headers is greater than the number of series.\e[0m"
|
41
|
+
exit 1 if YouPlot.run_as_executable?
|
42
|
+
|
43
|
+
elsif h_size < s_size
|
44
|
+
warn "\e[35mThe number of headers is less than the number of series.\e[0m"
|
45
|
+
exit 1 if YouPlot.run_as_executable?
|
33
46
|
end
|
34
|
-
end
|
35
47
|
|
36
|
-
|
37
|
-
CSV.parse(input, col_sep: delimiter)
|
38
|
-
.delete_if do |i|
|
39
|
-
i == [] or i.all? nil
|
40
|
-
end
|
48
|
+
Data.new(headers, series) if h_size == s_size
|
41
49
|
end
|
42
50
|
|
43
51
|
# Transpose different sized ruby arrays
|
@@ -47,31 +55,33 @@ module YouPlot
|
|
47
55
|
end
|
48
56
|
|
49
57
|
def get_headers(arr, headers, transpose)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
58
|
+
# header(-)
|
59
|
+
return nil unless headers
|
60
|
+
|
61
|
+
# header(+) trenspose(+)
|
62
|
+
return arr.map(&:first) if transpose
|
63
|
+
|
64
|
+
# header(+) transpose(-)
|
65
|
+
arr[0]
|
57
66
|
end
|
58
67
|
|
59
68
|
def get_series(arr, headers, transpose)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
transpose2(arr[1..-1])
|
66
|
-
end
|
67
|
-
else
|
68
|
-
Array.new(arr[0].size, [])
|
69
|
-
end
|
70
|
-
elsif transpose
|
71
|
-
arr
|
72
|
-
else
|
73
|
-
transpose2(arr)
|
69
|
+
# header(-)
|
70
|
+
unless headers
|
71
|
+
return arr if transpose
|
72
|
+
|
73
|
+
return transpose2(arr)
|
74
74
|
end
|
75
|
+
|
76
|
+
# header(+) but no element in the series.
|
77
|
+
# TODO: should raise error?
|
78
|
+
return Array.new(arr[0].size, []) if arr.size == 1
|
79
|
+
|
80
|
+
# header(+) transpose(+)
|
81
|
+
return arr.map { |row| row[1..-1] } if transpose
|
82
|
+
|
83
|
+
# header(+) transpose(-)
|
84
|
+
transpose2(arr[1..-1])
|
75
85
|
end
|
76
86
|
end
|
77
87
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module YouPlot
|
4
|
+
# Command line options that are not Plot parameters
|
5
|
+
Options = Struct.new(
|
6
|
+
:delimiter,
|
7
|
+
:transpose,
|
8
|
+
:headers,
|
9
|
+
:pass,
|
10
|
+
:output,
|
11
|
+
:fmt,
|
12
|
+
:progressive,
|
13
|
+
:encoding,
|
14
|
+
:color_names,
|
15
|
+
:debug,
|
16
|
+
keyword_init: true
|
17
|
+
)
|
18
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module YouPlot
|
4
|
+
# UnicodePlot parameters.
|
5
|
+
# Why Struct, not Hash?
|
6
|
+
# * The keys are static in Struct.
|
7
|
+
# * Struct does not conflict with keyword arguments. Hash dose.
|
8
|
+
Parameters = Struct.new(
|
9
|
+
# Sort me!
|
10
|
+
:title,
|
11
|
+
:width,
|
12
|
+
:height,
|
13
|
+
:border,
|
14
|
+
:margin,
|
15
|
+
:padding,
|
16
|
+
:color,
|
17
|
+
:xlabel,
|
18
|
+
:ylabel,
|
19
|
+
:labels,
|
20
|
+
:symbol,
|
21
|
+
:xscale,
|
22
|
+
:nbins,
|
23
|
+
:closed,
|
24
|
+
:canvas,
|
25
|
+
:xlim,
|
26
|
+
:ylim,
|
27
|
+
:grid,
|
28
|
+
:name
|
29
|
+
) do
|
30
|
+
def to_hc
|
31
|
+
to_h.compact
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,306 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require_relative 'options'
|
5
|
+
|
6
|
+
module YouPlot
|
7
|
+
# Class for parsing command line options
|
8
|
+
class Parser
|
9
|
+
class Error < StandardError; end
|
10
|
+
|
11
|
+
attr_reader :command, :options, :params,
|
12
|
+
:main_parser, :sub_parser
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@command = nil
|
16
|
+
|
17
|
+
@options = Options.new(
|
18
|
+
delimiter: "\t",
|
19
|
+
transpose: false,
|
20
|
+
headers: nil,
|
21
|
+
pass: false,
|
22
|
+
output: $stderr,
|
23
|
+
fmt: 'xyy',
|
24
|
+
progressive: false,
|
25
|
+
encoding: nil,
|
26
|
+
color_names: false,
|
27
|
+
debug: false
|
28
|
+
)
|
29
|
+
|
30
|
+
@params = Parameters.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_base_parser
|
34
|
+
OptionParser.new do |parser|
|
35
|
+
parser.program_name = 'YouPlot'
|
36
|
+
parser.version = YouPlot::VERSION
|
37
|
+
parser.summary_width = 23
|
38
|
+
parser.on_tail('') # Add a blank line at the end
|
39
|
+
parser.separator('')
|
40
|
+
parser.on('Common options:')
|
41
|
+
parser.on('-O', '--pass [FILE]', 'file to output input data to [stdout]',
|
42
|
+
'for inserting YouPlot in the middle of Unix pipes') do |v|
|
43
|
+
options[:pass] = v || $stdout
|
44
|
+
end
|
45
|
+
parser.on('-o', '--output [FILE]', 'file to output plots to [stdout]',
|
46
|
+
'If no option is specified, plot will print to stderr') do |v|
|
47
|
+
options[:output] = v || $stdout
|
48
|
+
end
|
49
|
+
parser.on('-d', '--delimiter DELIM', String, 'use DELIM instead of [TAB] for field delimiter') do |v|
|
50
|
+
options[:delimiter] = v
|
51
|
+
end
|
52
|
+
parser.on('-H', '--headers', TrueClass, 'specify that the input has header row') do |v|
|
53
|
+
options[:headers] = v
|
54
|
+
end
|
55
|
+
parser.on('-T', '--transpose', TrueClass, 'transpose the axes of the input data') do |v|
|
56
|
+
options[:transpose] = v
|
57
|
+
end
|
58
|
+
parser.on('-t', '--title STR', String, 'print string on the top of plot') do |v|
|
59
|
+
params.title = v
|
60
|
+
end
|
61
|
+
parser.on('-x', '--xlabel STR', String, 'print string on the bottom of the plot') do |v|
|
62
|
+
params.xlabel = v
|
63
|
+
end
|
64
|
+
parser.on('-y', '--ylabel STR', String, 'print string on the far left of the plot') do |v|
|
65
|
+
params.ylabel = v
|
66
|
+
end
|
67
|
+
parser.on('-w', '--width INT', Integer, 'number of characters per row') do |v|
|
68
|
+
params.width = v
|
69
|
+
end
|
70
|
+
parser.on('-h', '--height INT', Numeric, 'number of rows') do |v|
|
71
|
+
params.height = v
|
72
|
+
end
|
73
|
+
border_options = UnicodePlot::BORDER_MAP.keys.join(', ')
|
74
|
+
parser.on('-b', '--border STR', String, 'specify the style of the bounding box', "(#{border_options})") do |v|
|
75
|
+
params.border = v.to_sym
|
76
|
+
end
|
77
|
+
parser.on('-m', '--margin INT', Numeric, 'number of spaces to the left of the plot') do |v|
|
78
|
+
params.margin = v
|
79
|
+
end
|
80
|
+
parser.on('--padding INT', Numeric, 'space of the left and right of the plot') do |v|
|
81
|
+
params.padding = v
|
82
|
+
end
|
83
|
+
parser.on('-c', '--color VAL', String, 'color of the drawing') do |v|
|
84
|
+
params.color = v =~ /\A[0-9]+\z/ ? v.to_i : v.to_sym
|
85
|
+
end
|
86
|
+
parser.on('--[no-]labels', TrueClass, 'hide the labels') do |v|
|
87
|
+
params.labels = v
|
88
|
+
end
|
89
|
+
parser.on('-p', '--progress', TrueClass, 'progressive mode [experimental]') do |v|
|
90
|
+
options[:progressive] = v
|
91
|
+
end
|
92
|
+
parser.on('-C', '--color-output', TrueClass, 'colorize even if writing to a pipe') do |_v|
|
93
|
+
UnicodePlot::IOContext.define_method(:color?) { true } # FIXME
|
94
|
+
end
|
95
|
+
parser.on('-M', '--monochrome', TrueClass, 'no colouring even if writing to a tty') do |_v|
|
96
|
+
UnicodePlot::IOContext.define_method(:color?) { false } # FIXME
|
97
|
+
end
|
98
|
+
parser.on('--encoding STR', String, 'Specify the input encoding') do |v|
|
99
|
+
options[:encoding] = v
|
100
|
+
end
|
101
|
+
# Optparse adds the help option, but it doesn't show up in usage.
|
102
|
+
# This is why you need the code below.
|
103
|
+
parser.on('--help', 'print sub-command help menu') do
|
104
|
+
puts parser.help
|
105
|
+
exit if YouPlot.run_as_executable?
|
106
|
+
end
|
107
|
+
parser.on('--debug', TrueClass, 'print preprocessed data') do |v|
|
108
|
+
options[:debug] = v
|
109
|
+
end
|
110
|
+
# yield opt if block_given?
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_main_parser
|
115
|
+
@main_parser = create_base_parser
|
116
|
+
main_parser.banner = \
|
117
|
+
<<~MSG
|
118
|
+
|
119
|
+
Program: YouPlot (Tools for plotting on the terminal)
|
120
|
+
Version: #{YouPlot::VERSION} (using UnicodePlot #{UnicodePlot::VERSION})
|
121
|
+
Source: https://github.com/kojix2/youplot
|
122
|
+
|
123
|
+
Usage: uplot <command> [options] <in.tsv>
|
124
|
+
|
125
|
+
Commands:
|
126
|
+
barplot bar draw a horizontal barplot
|
127
|
+
histogram hist draw a horizontal histogram
|
128
|
+
lineplot line draw a line chart
|
129
|
+
lineplots lines draw a line chart with multiple series
|
130
|
+
scatter s draw a scatter plot
|
131
|
+
density d draw a density plot
|
132
|
+
boxplot box draw a horizontal boxplot
|
133
|
+
colors color show the list of available colors
|
134
|
+
|
135
|
+
count c draw a baplot based on the number of
|
136
|
+
occurrences (slow)
|
137
|
+
|
138
|
+
General options:
|
139
|
+
--help print command specific help menu
|
140
|
+
--version print the version of YouPlot
|
141
|
+
MSG
|
142
|
+
|
143
|
+
# Help for the main parser is simple.
|
144
|
+
# Simply show the banner above.
|
145
|
+
main_parser.on('--help', 'print sub-command help menu') do
|
146
|
+
puts main_parser.banner
|
147
|
+
puts
|
148
|
+
exit if YouPlot.run_as_executable?
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def sub_parser_add_symbol
|
153
|
+
sub_parser.on_head('--symbol STR', String, 'character to be used to plot the bars') do |v|
|
154
|
+
params.symbol = v
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def sub_parser_add_xscale
|
159
|
+
xscale_options = UnicodePlot::ValueTransformer::PREDEFINED_TRANSFORM_FUNCTIONS.keys.join(', ')
|
160
|
+
sub_parser.on_head('--xscale STR', String, "axis scaling (#{xscale_options})") do |v|
|
161
|
+
params.xscale = v.to_sym
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def sub_parser_add_canvas
|
166
|
+
sub_parser.on_head('--canvas STR', String, 'type of canvas') do |v|
|
167
|
+
params.canvas = v.to_sym
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def sub_parser_add_xlim
|
172
|
+
sub_parser.on_head('--xlim FLOAT,FLOAT', Array, 'plotting range for the x coordinate') do |v|
|
173
|
+
params.xlim = v
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def sub_parser_add_ylim
|
178
|
+
sub_parser.on_head('--ylim FLOAT,FLOAT', Array, 'plotting range for the y coordinate') do |v|
|
179
|
+
params.ylim = v
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def sub_parser_add_grid
|
184
|
+
sub_parser.on_head('--[no-]grid', TrueClass, 'draws grid-lines at the origin') do |v|
|
185
|
+
params.grid = v
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def sub_parser_add_fmt_xyxy
|
190
|
+
sub_parser.on_head('--fmt STR', String,
|
191
|
+
'xyxy : header is like x1, y1, x2, y2, x3, y3...',
|
192
|
+
'xyy : header is like x, y1, y2, y2, y3...') do |v|
|
193
|
+
options[:fmt] = v
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def sub_parser_add_fmt_yx
|
198
|
+
sub_parser.on_head('--fmt STR', String,
|
199
|
+
'xy : header is like x, y...',
|
200
|
+
'yx : header is like y, x...') do |v|
|
201
|
+
options[:fmt] = v
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def create_sub_parser
|
206
|
+
@sub_parser = create_base_parser
|
207
|
+
sub_parser.banner = \
|
208
|
+
<<~MSG
|
209
|
+
|
210
|
+
Usage: YouPlot #{command} [options] <in.tsv>
|
211
|
+
|
212
|
+
Options for #{command}:
|
213
|
+
MSG
|
214
|
+
|
215
|
+
case command
|
216
|
+
|
217
|
+
# If you type only `uplot` in the terminal.
|
218
|
+
when nil
|
219
|
+
warn main_parser.banner
|
220
|
+
warn "\n"
|
221
|
+
exit 1 if YouPlot.run_as_executable?
|
222
|
+
|
223
|
+
when :barplot, :bar
|
224
|
+
sub_parser_add_symbol
|
225
|
+
sub_parser_add_fmt_yx
|
226
|
+
sub_parser_add_xscale
|
227
|
+
|
228
|
+
when :count, :c
|
229
|
+
sub_parser_add_symbol
|
230
|
+
sub_parser_add_xscale
|
231
|
+
|
232
|
+
when :histogram, :hist
|
233
|
+
sub_parser_add_symbol
|
234
|
+
sub_parser.on_head('--closed STR', String, 'side of the intervals to be closed [left]') do |v|
|
235
|
+
params.closed = v
|
236
|
+
end
|
237
|
+
sub_parser.on_head('-n', '--nbins INT', Numeric, 'approximate number of bins') do |v|
|
238
|
+
params.nbins = v
|
239
|
+
end
|
240
|
+
|
241
|
+
when :lineplot, :line
|
242
|
+
sub_parser_add_canvas
|
243
|
+
sub_parser_add_grid
|
244
|
+
sub_parser_add_fmt_yx
|
245
|
+
sub_parser_add_ylim
|
246
|
+
sub_parser_add_xlim
|
247
|
+
|
248
|
+
when :lineplots, :lines
|
249
|
+
sub_parser_add_canvas
|
250
|
+
sub_parser_add_grid
|
251
|
+
sub_parser_add_fmt_xyxy
|
252
|
+
sub_parser_add_ylim
|
253
|
+
sub_parser_add_xlim
|
254
|
+
|
255
|
+
when :scatter, :s
|
256
|
+
sub_parser_add_canvas
|
257
|
+
sub_parser_add_grid
|
258
|
+
sub_parser_add_fmt_xyxy
|
259
|
+
sub_parser_add_ylim
|
260
|
+
sub_parser_add_xlim
|
261
|
+
|
262
|
+
when :density, :d
|
263
|
+
sub_parser_add_canvas
|
264
|
+
sub_parser_add_grid
|
265
|
+
sub_parser_add_fmt_xyxy
|
266
|
+
sub_parser_add_ylim
|
267
|
+
sub_parser_add_xlim
|
268
|
+
|
269
|
+
when :boxplot, :box
|
270
|
+
sub_parser_add_xlim
|
271
|
+
|
272
|
+
when :colors, :color, :colours, :colour
|
273
|
+
sub_parser.on_head('-n', '--names', 'show color names only', TrueClass) do |v|
|
274
|
+
options[:color_names] = v
|
275
|
+
end
|
276
|
+
|
277
|
+
else
|
278
|
+
error_message = "uplot: unrecognized command '#{command}'"
|
279
|
+
if YouPlot.run_as_executable?
|
280
|
+
warn error_message
|
281
|
+
exit 1
|
282
|
+
else
|
283
|
+
raise Error, error_message
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def parse_options(argv = ARGV)
|
289
|
+
begin
|
290
|
+
create_main_parser.order!(argv)
|
291
|
+
rescue OptionParser::ParseError => e
|
292
|
+
warn "uplot: #{e.message}"
|
293
|
+
exit 1 if YouPlot.run_as_executable?
|
294
|
+
end
|
295
|
+
|
296
|
+
@command = argv.shift&.to_sym
|
297
|
+
|
298
|
+
begin
|
299
|
+
create_sub_parser&.parse!(argv)
|
300
|
+
rescue OptionParser::ParseError => e
|
301
|
+
warn "uplot: #{e.message}"
|
302
|
+
exit 1 if YouPlot.run_as_executable?
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
data/lib/youplot/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: youplot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kojix2
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-05-
|
11
|
+
date: 2021-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: unicode_plot
|
@@ -109,12 +109,12 @@ files:
|
|
109
109
|
- exe/youplot
|
110
110
|
- lib/youplot.rb
|
111
111
|
- lib/youplot/backends/processing.rb
|
112
|
-
- lib/youplot/backends/
|
112
|
+
- lib/youplot/backends/unicode_plot.rb
|
113
113
|
- lib/youplot/command.rb
|
114
|
-
- lib/youplot/command/options.rb
|
115
|
-
- lib/youplot/command/parser.rb
|
116
|
-
- lib/youplot/command/plot_params.rb
|
117
114
|
- lib/youplot/dsv.rb
|
115
|
+
- lib/youplot/options.rb
|
116
|
+
- lib/youplot/parameters.rb
|
117
|
+
- lib/youplot/parser.rb
|
118
118
|
- lib/youplot/version.rb
|
119
119
|
homepage: https://github.com/kojix2/youplot
|
120
120
|
licenses:
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module YouPlot
|
4
|
-
class Command
|
5
|
-
Options = Struct.new(
|
6
|
-
:delimiter,
|
7
|
-
:transpose,
|
8
|
-
:headers,
|
9
|
-
:pass,
|
10
|
-
:output,
|
11
|
-
:fmt,
|
12
|
-
:progressive,
|
13
|
-
:encoding,
|
14
|
-
:color_names,
|
15
|
-
:debug,
|
16
|
-
keyword_init: true
|
17
|
-
)
|
18
|
-
end
|
19
|
-
end
|
@@ -1,305 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'optparse'
|
4
|
-
require_relative 'options'
|
5
|
-
require_relative 'plot_params'
|
6
|
-
|
7
|
-
module YouPlot
|
8
|
-
class Command
|
9
|
-
class Parser
|
10
|
-
class Error < StandardError; end
|
11
|
-
|
12
|
-
attr_reader :command, :options, :params,
|
13
|
-
:main_parser, :sub_parser
|
14
|
-
|
15
|
-
def initialize
|
16
|
-
@command = nil
|
17
|
-
|
18
|
-
@options = Options.new(
|
19
|
-
delimiter: "\t",
|
20
|
-
transpose: false,
|
21
|
-
headers: nil,
|
22
|
-
pass: false,
|
23
|
-
output: $stderr,
|
24
|
-
fmt: 'xyy',
|
25
|
-
progressive: false,
|
26
|
-
encoding: nil,
|
27
|
-
color_names: false,
|
28
|
-
debug: false
|
29
|
-
)
|
30
|
-
|
31
|
-
@params = PlotParams.new
|
32
|
-
end
|
33
|
-
|
34
|
-
def create_default_parser
|
35
|
-
OptionParser.new do |parser|
|
36
|
-
parser.program_name = 'YouPlot'
|
37
|
-
parser.version = YouPlot::VERSION
|
38
|
-
parser.summary_width = 24
|
39
|
-
parser.on_tail('') # Add a blank line at the end
|
40
|
-
parser.separator('')
|
41
|
-
parser.on('Common options:')
|
42
|
-
parser.on('-O', '--pass [FILE]', 'file to output input data to [stdout]',
|
43
|
-
'for inserting YouPlot in the middle of Unix pipes') do |v|
|
44
|
-
options[:pass] = v || $stdout
|
45
|
-
end
|
46
|
-
parser.on('-o', '--output [FILE]', 'file to output plots to [stdout]',
|
47
|
-
'If no option is specified, plot will print to stderr') do |v|
|
48
|
-
options[:output] = v || $stdout
|
49
|
-
end
|
50
|
-
parser.on('-d', '--delimiter DELIM', String, 'use DELIM instead of [TAB] for field delimiter') do |v|
|
51
|
-
options[:delimiter] = v
|
52
|
-
end
|
53
|
-
parser.on('-H', '--headers', TrueClass, 'specify that the input has header row') do |v|
|
54
|
-
options[:headers] = v
|
55
|
-
end
|
56
|
-
parser.on('-T', '--transpose', TrueClass, 'transpose the axes of the input data') do |v|
|
57
|
-
options[:transpose] = v
|
58
|
-
end
|
59
|
-
parser.on('-t', '--title STR', String, 'print string on the top of plot') do |v|
|
60
|
-
params.title = v
|
61
|
-
end
|
62
|
-
parser.on('-x', '--xlabel STR', String, 'print string on the bottom of the plot') do |v|
|
63
|
-
params.xlabel = v
|
64
|
-
end
|
65
|
-
parser.on('-y', '--ylabel STR', String, 'print string on the far left of the plot') do |v|
|
66
|
-
params.ylabel = v
|
67
|
-
end
|
68
|
-
parser.on('-w', '--width INT', Integer, 'number of characters per row') do |v|
|
69
|
-
params.width = v
|
70
|
-
end
|
71
|
-
parser.on('-h', '--height INT', Numeric, 'number of rows') do |v|
|
72
|
-
params.height = v
|
73
|
-
end
|
74
|
-
border_options = UnicodePlot::BORDER_MAP.keys.join(', ')
|
75
|
-
parser.on('-b', '--border STR', String, 'specify the style of the bounding box', "(#{border_options})") do |v|
|
76
|
-
params.border = v.to_sym
|
77
|
-
end
|
78
|
-
parser.on('-m', '--margin INT', Numeric, 'number of spaces to the left of the plot') do |v|
|
79
|
-
params.margin = v
|
80
|
-
end
|
81
|
-
parser.on('--padding INT', Numeric, 'space of the left and right of the plot') do |v|
|
82
|
-
params.padding = v
|
83
|
-
end
|
84
|
-
parser.on('-c', '--color VAL', String, 'color of the drawing') do |v|
|
85
|
-
params.color = v =~ /\A[0-9]+\z/ ? v.to_i : v.to_sym
|
86
|
-
end
|
87
|
-
parser.on('--[no-]labels', TrueClass, 'hide the labels') do |v|
|
88
|
-
params.labels = v
|
89
|
-
end
|
90
|
-
parser.on('-p', '--progress', TrueClass, 'progressive mode [experimental]') do |v|
|
91
|
-
options[:progressive] = v
|
92
|
-
end
|
93
|
-
parser.on('-C', '--color-output', TrueClass, 'colorize even if writing to a pipe') do |v|
|
94
|
-
UnicodePlot::StyledPrinter.define_method(:color?){ |o| true }
|
95
|
-
end
|
96
|
-
parser.on('-M', '--monochrome', TrueClass, 'no colouring even if writing to a tty') do |v|
|
97
|
-
UnicodePlot::StyledPrinter.define_method(:color?){ |o| false }
|
98
|
-
end
|
99
|
-
parser.on('--encoding STR', String, 'Specify the input encoding') do |v|
|
100
|
-
options[:encoding] = v
|
101
|
-
end
|
102
|
-
# Optparse adds the help option, but it doesn't show up in usage.
|
103
|
-
# This is why you need the code below.
|
104
|
-
parser.on('--help', 'print sub-command help menu') do
|
105
|
-
puts parser.help
|
106
|
-
exit if YouPlot.run_as_executable?
|
107
|
-
end
|
108
|
-
parser.on('--debug', TrueClass, 'print preprocessed data') do |v|
|
109
|
-
options[:debug] = v
|
110
|
-
end
|
111
|
-
# yield opt if block_given?
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def create_main_parser
|
116
|
-
@main_parser = create_default_parser
|
117
|
-
main_parser.banner = \
|
118
|
-
<<~MSG
|
119
|
-
|
120
|
-
Program: YouPlot (Tools for plotting on the terminal)
|
121
|
-
Version: #{YouPlot::VERSION} (using UnicodePlot #{UnicodePlot::VERSION})
|
122
|
-
Source: https://github.com/kojix2/youplot
|
123
|
-
|
124
|
-
Usage: uplot <command> [options] <in.tsv>
|
125
|
-
|
126
|
-
Commands:
|
127
|
-
barplot bar draw a horizontal barplot
|
128
|
-
histogram hist draw a horizontal histogram
|
129
|
-
lineplot line draw a line chart
|
130
|
-
lineplots lines draw a line chart with multiple series
|
131
|
-
scatter s draw a scatter plot
|
132
|
-
density d draw a density plot
|
133
|
-
boxplot box draw a horizontal boxplot
|
134
|
-
colors color show the list of available colors
|
135
|
-
|
136
|
-
count c draw a baplot based on the number of
|
137
|
-
occurrences (slow)
|
138
|
-
|
139
|
-
General options:
|
140
|
-
--help print command specific help menu
|
141
|
-
--version print the version of YouPlot
|
142
|
-
MSG
|
143
|
-
|
144
|
-
# Help for the main parser is simple.
|
145
|
-
# Simply show the banner above.
|
146
|
-
main_parser.on('--help', 'print sub-command help menu') do
|
147
|
-
puts main_parser.banner
|
148
|
-
puts
|
149
|
-
exit if YouPlot.run_as_executable?
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
def sub_parser_add_symbol
|
154
|
-
sub_parser.on_head('--symbol STR', String, 'character to be used to plot the bars') do |v|
|
155
|
-
params.symbol = v
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def sub_parser_add_xscale
|
160
|
-
xscale_options = UnicodePlot::ValueTransformer::PREDEFINED_TRANSFORM_FUNCTIONS.keys.join(', ')
|
161
|
-
sub_parser.on_head('--xscale STR', String, "axis scaling (#{xscale_options})") do |v|
|
162
|
-
params.xscale = v.to_sym
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
def sub_parser_add_canvas
|
167
|
-
sub_parser.on_head('--canvas STR', String, 'type of canvas') do |v|
|
168
|
-
params.canvas = v.to_sym
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
def sub_parser_add_xlim
|
173
|
-
sub_parser.on_head('--xlim FLOAT,FLOAT', Array, 'plotting range for the x coordinate') do |v|
|
174
|
-
params.xlim = v
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def sub_parser_add_ylim
|
179
|
-
sub_parser.on_head('--ylim FLOAT,FLOAT', Array, 'plotting range for the y coordinate') do |v|
|
180
|
-
params.ylim = v
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
def sub_parser_add_grid
|
185
|
-
sub_parser.on_head('--[no-]grid', TrueClass, 'draws grid-lines at the origin') do |v|
|
186
|
-
params.grid = v
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def create_sub_parser
|
191
|
-
@sub_parser = create_default_parser
|
192
|
-
sub_parser.banner = \
|
193
|
-
<<~MSG
|
194
|
-
|
195
|
-
Usage: YouPlot #{command} [options] <in.tsv>
|
196
|
-
|
197
|
-
Options for #{command}:
|
198
|
-
MSG
|
199
|
-
|
200
|
-
case command
|
201
|
-
|
202
|
-
# If you type only `uplot` in the terminal.
|
203
|
-
when nil
|
204
|
-
warn main_parser.banner
|
205
|
-
warn "\n"
|
206
|
-
exit 1 if YouPlot.run_as_executable?
|
207
|
-
|
208
|
-
when :barplot, :bar
|
209
|
-
sub_parser_add_symbol
|
210
|
-
sub_parser.on_head('--fmt STR', String, 'xy : header is like x, y...', 'yx : header is like y, x...') do |v|
|
211
|
-
options[:fmt] = v
|
212
|
-
end
|
213
|
-
sub_parser_add_xscale
|
214
|
-
|
215
|
-
when :count, :c
|
216
|
-
sub_parser_add_symbol
|
217
|
-
sub_parser_add_xscale
|
218
|
-
|
219
|
-
when :histogram, :hist
|
220
|
-
sub_parser_add_symbol
|
221
|
-
sub_parser.on_head('--closed STR', String, 'side of the intervals to be closed [left]') do |v|
|
222
|
-
params.closed = v
|
223
|
-
end
|
224
|
-
sub_parser.on_head('-n', '--nbins INT', Numeric, 'approximate number of bins') do |v|
|
225
|
-
params.nbins = v
|
226
|
-
end
|
227
|
-
|
228
|
-
when :lineplot, :line
|
229
|
-
sub_parser_add_canvas
|
230
|
-
sub_parser_add_grid
|
231
|
-
sub_parser.on_head('--fmt STR', String, 'xy : header is like x, y...', 'yx : header is like y, x...') do |v|
|
232
|
-
options[:fmt] = v
|
233
|
-
end
|
234
|
-
sub_parser_add_ylim
|
235
|
-
sub_parser_add_xlim
|
236
|
-
|
237
|
-
when :lineplots, :lines
|
238
|
-
sub_parser_add_canvas
|
239
|
-
sub_parser_add_grid
|
240
|
-
sub_parser.on_head('--fmt STR', String, 'xyxy : header is like x1, y1, x2, y2, x3, y3...',
|
241
|
-
'xyy : header is like x, y1, y2, y2, y3...') do |v|
|
242
|
-
options[:fmt] = v
|
243
|
-
end
|
244
|
-
sub_parser_add_ylim
|
245
|
-
sub_parser_add_xlim
|
246
|
-
|
247
|
-
when :scatter, :s
|
248
|
-
sub_parser_add_canvas
|
249
|
-
sub_parser_add_grid
|
250
|
-
sub_parser.on_head('--fmt STR', String, 'xyxy : header is like x1, y1, x2, y2, x3, y3...',
|
251
|
-
'xyy : header is like x, y1, y2, y2, y3...') do |v|
|
252
|
-
options[:fmt] = v
|
253
|
-
end
|
254
|
-
sub_parser_add_ylim
|
255
|
-
sub_parser_add_xlim
|
256
|
-
|
257
|
-
when :density, :d
|
258
|
-
sub_parser_add_canvas
|
259
|
-
sub_parser_add_grid
|
260
|
-
sub_parser.on('--fmt STR', String, 'xyxy : header is like x1, y1, x2, y2, x3, y3...',
|
261
|
-
'xyy : header is like x, y1, y2, y2, y3...') do |v|
|
262
|
-
options[:fmt] = v
|
263
|
-
end
|
264
|
-
sub_parser_add_ylim
|
265
|
-
sub_parser_add_xlim
|
266
|
-
|
267
|
-
when :boxplot, :box
|
268
|
-
sub_parser_add_xlim
|
269
|
-
|
270
|
-
when :colors, :color, :colours, :colour
|
271
|
-
sub_parser.on_head('-n', '--names', 'show color names only', TrueClass) do |v|
|
272
|
-
options[:color_names] = v
|
273
|
-
end
|
274
|
-
|
275
|
-
else
|
276
|
-
error_message = "uplot: unrecognized command '#{command}'"
|
277
|
-
if YouPlot.run_as_executable?
|
278
|
-
warn error_message
|
279
|
-
exit 1
|
280
|
-
else
|
281
|
-
raise Error, error_message
|
282
|
-
end
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
def parse_options(argv = ARGV)
|
287
|
-
begin
|
288
|
-
create_main_parser.order!(argv)
|
289
|
-
rescue OptionParser::ParseError => e
|
290
|
-
warn "uplot: #{e.message}"
|
291
|
-
exit 1 if YouPlot.run_as_executable?
|
292
|
-
end
|
293
|
-
|
294
|
-
@command = argv.shift&.to_sym
|
295
|
-
|
296
|
-
begin
|
297
|
-
create_sub_parser&.parse!(argv)
|
298
|
-
rescue OptionParser::ParseError => e
|
299
|
-
warn "uplot: #{e.message}"
|
300
|
-
exit 1 if YouPlot.run_as_executable?
|
301
|
-
end
|
302
|
-
end
|
303
|
-
end
|
304
|
-
end
|
305
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module YouPlot
|
4
|
-
class Command
|
5
|
-
# UnicodePlot parameters.
|
6
|
-
# * Normally in a Ruby program, you might use hash for the parameter object.
|
7
|
-
# * Here, I use Struct for 2 safety reason.
|
8
|
-
# * The keys are static in Struct.
|
9
|
-
# * Struct does not conflict with keyword arguments. Hash dose.
|
10
|
-
PlotParams = Struct.new(
|
11
|
-
# Sort me!
|
12
|
-
:title,
|
13
|
-
:width,
|
14
|
-
:height,
|
15
|
-
:border,
|
16
|
-
:margin,
|
17
|
-
:padding,
|
18
|
-
:color,
|
19
|
-
:xlabel,
|
20
|
-
:ylabel,
|
21
|
-
:labels,
|
22
|
-
:symbol,
|
23
|
-
:xscale,
|
24
|
-
:nbins,
|
25
|
-
:closed,
|
26
|
-
:canvas,
|
27
|
-
:xlim,
|
28
|
-
:ylim,
|
29
|
-
:grid,
|
30
|
-
:name
|
31
|
-
) do
|
32
|
-
def to_hc
|
33
|
-
to_h.compact
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|