youplot 0.3.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9b1c58784cb37da38b1c2bb24ed86961a8d7ddded67899027f9ed725ece7ea8
4
- data.tar.gz: 1f6050c3707ecaa29997ee1af65b440ba016f0eacb47d4dc9c38a15ac59afe9a
3
+ metadata.gz: 83145e216c0d124d537c8a01d63f9203730a74191fefcb9de5743b08e0e504bd
4
+ data.tar.gz: a246eab22f11ab8c526cc838d9f2fbf7d249721b4782287087c08a5410f8647b
5
5
  SHA512:
6
- metadata.gz: 5d62aeed65f6a4692f115453b085cb926d54a8efe184e7e39250a720235f8d13ecf8ec2026099ae2d6a3ab17385e607a9281fff1b12e81914314c991bf471ca4
7
- data.tar.gz: 1e3ad16f26c8287385fdee2a4f13626b369a58c63f2d488678b02bdc15dfb7e22a8b8ed0f31c1d6324537c59aa86c4367187f01e6080f6bf51f3bedade3905f4
6
+ metadata.gz: d9138c26fade36d7d0ca19100b47dcb8e65c8c884d13b74d258dcae9ea304ced2fc783b08e871d76607e57e394e6b861c81f1f5030caba53493b2f4740a05cd2
7
+ data.tar.gz: f293d686791ba1481948877e534c9085e99c24ab9c36026979002ecaa9ee2ece6f12ad7193cda936c62e472e2f94008466cc666e9405157bfcc348c4c21c4579
data/README.md CHANGED
@@ -1,11 +1,14 @@
1
- # YouPlot
1
+ <p align="center">
2
+ <img src="logo.svg" width="60%" height="60%" />
3
+ </p>
2
4
 
3
5
  ![Build Status](https://github.com/kojix2/youplot/workflows/test/badge.svg)
4
6
  [![Gem Version](https://badge.fury.io/rb/youplot.svg)](https://badge.fury.io/rb/youplot)
5
- [![Docs Latest](https://img.shields.io/badge/docs-latest-blue.svg)](https://rubydoc.info/gems/youplot)
7
+ [![Docs Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://rubydoc.info/gems/youplot)
6
8
  [![The MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.txt)
9
+ [![DOI](https://zenodo.org/badge/283230219.svg)](https://zenodo.org/badge/latestdoi/283230219)
7
10
 
8
- Create ASCII charts on the terminal with data from standard streams in the pipeline.
11
+ YouPlot is a command line tool for Unicode Plotting working with data from standard stream.
9
12
 
10
13
  :bar_chart: Powered by [UnicodePlot](https://github.com/red-data-tools/unicode_plot.rb)
11
14
 
@@ -15,16 +18,25 @@ Create ASCII charts on the terminal with data from standard streams in the pipel
15
18
  gem install youplot
16
19
  ```
17
20
 
18
- ## Screenshots
21
+ ## Quick Start
19
22
 
20
- **histogram**
23
+ * `cat data.tsv | uplot <command> [options]` or
24
+ * `uplot <command> [options] <data.tsv>`
25
+
26
+ ### barplot
21
27
 
22
28
  ```sh
23
- ruby -r numo/narray -e "puts Numo::DFloat.new(1000).rand_norm.to_a" \
24
- | uplot hist --nbins 15
29
+ curl -sL https://git.io/ISLANDScsv \
30
+ | sort -nk2 -t, \
31
+ | tail -n15 \
32
+ | uplot bar -d, -t "Areas of the World's Major Landmasses"
25
33
  ```
26
34
 
27
- <img src="https://i.imgur.com/wpsoGJq.png" width="75%" height="75%">
35
+ <p align="center">
36
+ <img alt="barplot" src="https://user-images.githubusercontent.com/5798442/101999903-d36a2d00-3d24-11eb-9361-b89116f44122.png">
37
+ </p>
38
+
39
+ ### histogram
28
40
 
29
41
  ```sh
30
42
  echo -e "from numpy import random;" \
@@ -34,91 +46,163 @@ echo -e "from numpy import random;" \
34
46
  | uplot hist --nbins 20
35
47
  ```
36
48
 
37
- <img src="https://i.imgur.com/97R2MQx.png" width="75%" height="75%">
49
+ <p align="center">
50
+ <img alt="histogram" src="https://user-images.githubusercontent.com/5798442/101999820-21cafc00-3d24-11eb-86db-e410d19b07df.png">
51
+ </p>
38
52
 
39
- **scatter**
53
+ ### lineplot
40
54
 
41
55
  ```sh
42
- curl -s https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv \
43
- | cut -f1-4 -d, \
44
- | uplot scatter -H -d, -t IRIS
56
+ curl -sL https://git.io/AirPassengers \
57
+ | cut -f2,3 -d, \
58
+ | uplot line -d, -w 50 -h 15 -t AirPassengers --xlim 1950,1960 --ylim 0,600
45
59
  ```
46
60
 
47
- <img src="https://i.imgur.com/STX7bFT.png" width="75%" height="75%">
61
+ <p align="center">
62
+ <img alt="lineplot" src="https://user-images.githubusercontent.com/5798442/101999825-24c5ec80-3d24-11eb-99f4-c642e8d221bc.png">
63
+ </p>
48
64
 
49
- **line**
65
+ ### scatter
50
66
 
51
67
  ```sh
52
- curl -s https://www.mhlw.go.jp/content/pcr_positive_daily.csv \
53
- | cut -f2 -d, \
54
- | uplot line -w 50 -h 15 -t 'PCR positive tests' --xlabel Date --ylabel number
68
+ curl -sL https://git.io/IRIStsv \
69
+ | cut -f1-4 \
70
+ | uplot scatter -H -t IRIS
55
71
  ```
56
72
 
57
- <img src="https://i.imgur.com/PVl5dsa.png" width="75%" height="75%">
73
+ <p align="center">
74
+ <img alt="scatter" src="https://user-images.githubusercontent.com/5798442/101999827-27284680-3d24-11eb-9903-551857eaa69c.png">
75
+ </p>
58
76
 
59
- **box**
77
+ ### density
60
78
 
61
79
  ```sh
62
- curl -s https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv \
63
- | cut -f1-4 -d, \
64
- | uplot box -H -d, -t IRIS
80
+ curl -sL https://git.io/IRIStsv \
81
+ | cut -f1-4 \
82
+ | uplot density -H -t IRIS
65
83
  ```
66
84
 
67
- <img src="https://i.imgur.com/sNI4SmN.png" width="75%" height="75%">
85
+ <p align="center">
86
+ <img alt="density" src="https://user-images.githubusercontent.com/5798442/101999828-2abbcd80-3d24-11eb-902c-2f44266fa6ae.png">
87
+ </p>
68
88
 
69
- **colors**
89
+ ### boxplot
70
90
 
71
91
  ```sh
72
- uplot colors
92
+ curl -sL https://git.io/IRIStsv \
93
+ | cut -f1-4 \
94
+ | uplot boxplot -H -t IRIS
73
95
  ```
74
96
 
75
- <img src="https://i.imgur.com/LxyHQsz.png">
97
+ <p align="center">
98
+ <img alt="boxplot" src="https://user-images.githubusercontent.com/5798442/101999830-2e4f5480-3d24-11eb-8891-728c18bf5b35.png">
99
+ </p>
76
100
 
77
- ## Usage
101
+ ### count
102
+
103
+ In this example, YouPlot counts the number of chromosomes where the gene is located from the human gene annotation file and it creates a bar chart. The human gene annotation file can be downloaded from the following website.
78
104
 
79
- `uplot --help`
105
+ * https://www.gencodegenes.org/human/
80
106
 
107
+ ```sh
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
81
111
  ```
82
- Program: YouPlot (Tools for plotting on the terminal)
83
- Version: 0.2.7 (using UnicodePlot 0.0.4)
84
- Source: https://github.com/kojix2/youplot
85
112
 
86
- Usage: uplot <command> [options] <in.tsv>
113
+ <p align="center">
114
+ <img alt="count" src="https://user-images.githubusercontent.com/5798442/101999832-30b1ae80-3d24-11eb-96fe-e5000bed1f5c.png">
115
+ </p>
87
116
 
88
- Commands:
89
- barplot bar
90
- histogram hist
91
- lineplot line
92
- lineplots lines
93
- scatter s
94
- density d
95
- boxplot box
96
- colors show the list of available colors
117
+ Note: `count` is not very fast because it runs in a Ruby script.
118
+ This is fine in most cases, as long as the data size is small. If you want to visualize huge data, it is faster to use a combination of common Unix commands as shown below.
97
119
 
98
- count c baplot based on the number of occurrences
99
- (slower than `sort | uniq -c | sort -n -k1`)
120
+ ```sh
121
+ cat gencode.v35.annotation.gff3 | grep -v '#' | grep 'gene' | cut -f1 \
122
+ | sort | uniq -c | sort -nrk2 | awk '{print $2,$1}' \
123
+ | uplot bar -d ' ' -t "The number of human gene annotations per chromosome" -c blue
124
+ ```
100
125
 
101
- Options:
102
- -O, --pass [VAL] file to output standard input data to [stdout]
103
- for inserting YouPlot in the middle of Unix pipes
104
- -o, --output VAL file to output results to [stderr]
105
- -d, --delimiter VAL use DELIM instead of TAB for field delimiter
106
- -H, --headers specify that the input has header row
107
- -T, --transpose transpose the axes of the input data
108
- -t, --title VAL print string on the top of plot
109
- -x, --xlabel VAL print string on the bottom of the plot
110
- -y, --ylabel VAL print string on the far left of the plot
111
- -w, --width VAL number of characters per row
112
- -h, --height VAL number of rows
113
- -b, --border VAL specify the style of the bounding box
114
- -m, --margin VAL number of spaces to the left of the plot
115
- -p, --padding VAL space of the left and right of the plot
116
- -c, --color VAL color of the drawing
117
- --[no-]labels hide the labels
118
- --fmt VAL xyxy : header is like x1, y1, x2, y2, x3, y3...
119
- xyy : header is like x, y1, y2, y2, y3...
126
+ ## Usage
127
+
128
+ ### Why YouPlot?
129
+
130
+ Wouldn't it be a pain to have to run R, Python, Julia, gnuplot or whatever REPL just to check your data?
131
+ YouPlot is a command line tool for this purpose. With YouPlot, you can continue working without leaving your terminal and shell.
132
+
133
+ ### How to use YouPlot?
134
+
135
+ `uplot` is the shortened form of `youplot`. You can use either.
136
+
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
+
143
+ ### Where to output the plot?
144
+
145
+ By default, the plot is output to *standard error output*.
146
+ The output file or stream for the plot can be specified with the `-o` option.
147
+
148
+ ### Where to output the input data?
149
+
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.
152
+ This is useful when passing data to a subsequent pipeline.
153
+
154
+ ### What types of plots are available?
155
+
156
+ The following sub-commands are available.
157
+
158
+ | command | short | how it works |
159
+ |-----------|-------|----------------------------------------|
160
+ | barplot | bar | draw a horizontal barplot |
161
+ | histogram | hist | draw a horizontal histogram |
162
+ | lineplot | line | draw a line chart |
163
+ | lineplots | lines | draw a line chart with multiple series |
164
+ | scatter | s | draw a scatter plot |
165
+ | density | d | draw a density plot |
166
+ | boxplot | box | draw a horizontal boxplot |
167
+
168
+ See Quick Start for `count`.
169
+
170
+ | command | short | how it works |
171
+ |-----------|-------|----------------------------------------------------------|
172
+ | count | c | draw a barplot based on the number of occurrences (slow) |
173
+
174
+ ### What if the header line is included?
175
+
176
+ If your input data contains a header line, you need to specify the `-H` option.
177
+
178
+ ### How to specify the delimiter?
179
+
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.
182
+
183
+ ### Is there a way to specify a column as the x-axis or y-axis?
184
+
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.
195
+
196
+ ### How to plot real-time data?
197
+
198
+ Experimental progressive mode is currently under development.
199
+
200
+ ```sh
201
+ ruby -e 'loop{puts rand(100)}' | uplot line --progress
120
202
  ```
121
203
 
204
+ ### How to view detailed command line options?
205
+
122
206
  Use `--help` to print command-specific options.
123
207
 
124
208
  `uplot hist --help`
@@ -128,20 +212,46 @@ Usage: uplot histogram [options] <in.tsv>
128
212
 
129
213
  Options for histogram:
130
214
  --symbol VAL character to be used to plot the bars
131
- --closed VAL
215
+ --closed VAL side of the intervals to be closed [left]
132
216
  -n, --nbins VAL approximate number of bins
133
217
 
134
218
  Options:
135
219
  ...
136
220
  ```
137
221
 
138
- ## Development
222
+ ### How to view the list of available colors?
139
223
 
140
- Let's keep it simple.
224
+ ```sh
225
+ uplot colors
226
+ ```
141
227
 
142
228
  ## Contributing
143
229
 
144
- Bug reports and pull requests are welcome on GitHub at [https://github.com/kojix2/youplot](https://github.com/kojix2/youplot).
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.
232
+
233
+ * [Report bugs](https://github.com/kojix2/youplot/issues)
234
+ * Fix bugs and [submit pull requests](https://github.com/kojix2/youplot/pulls)
235
+ * Write, clarify, or fix documentation
236
+ * English corrections by native speakers are welcome.
237
+ * Suggest or add new features
238
+ * Make a donation
239
+
240
+ ### Development
241
+
242
+ ```sh
243
+ # fork the main repository by clicking the Fork button.
244
+ git clone https://github.com/your_name/YouPlot
245
+ bundle install # Install the gem dependencies
246
+ bundle exec rake test # Run the test
247
+ bundle exec rake install # Installation from source code
248
+ ```
249
+
250
+ ### Acknowledgements
251
+
252
+ * [Red Data Tools](https://github.com/red-data-tools) - Technical support
253
+ * [sampo grafiikka](https://jypg.net/sampo_grafiikka) - Project logo creation
254
+ * [yutaas](https://github.com/yutaas) - English proofreading
145
255
 
146
256
  ## License
147
257
 
data/exe/uplot CHANGED
@@ -3,4 +3,4 @@
3
3
 
4
4
  require 'youplot'
5
5
 
6
- YouPlot::Command.new.run
6
+ YouPlot::Command.new.run_as_executable
data/exe/youplot CHANGED
@@ -3,4 +3,4 @@
3
3
 
4
4
  require 'youplot'
5
5
 
6
- YouPlot::Command.new.run
6
+ YouPlot::Command.new.run_as_executable
data/lib/youplot.rb CHANGED
@@ -1,9 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'unicode_plot'
4
- require 'youplot/version'
5
- require 'youplot/dsv_reader'
6
- require 'youplot/command'
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
+ class << self
10
+ attr_accessor :run_as_executable
11
+
12
+ def run_as_executable?
13
+ @run_as_executable
14
+ end
15
+ end
16
+ @run_as_executable = false
9
17
  end
@@ -6,17 +6,21 @@ module YouPlot
6
6
  module Processing
7
7
  module_function
8
8
 
9
- def count_values(arr)
9
+ def count_values(arr, tally: true)
10
10
  # tally was added in Ruby 2.7
11
- if Enumerable.method_defined? :tally
11
+ if tally && Enumerable.method_defined?(:tally)
12
12
  arr.tally
13
13
  else
14
- # https://github.com/marcandre/backports
15
- arr.each_with_object(Hash.new(0)) { |item, res| res[item] += 1 }
16
- .tap { |h| h.default = nil }
14
+ # value_counts Enumerable::Statistics
15
+ arr.value_counts(dropna: false)
17
16
  end
18
- .sort { |a, b| a[1] <=> b[1] }
19
- .reverse
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,17 @@
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 UnicodePlotBackend
12
+ module UnicodePlot
13
+ class Error < StandardError; end
14
+
10
15
  module_function
11
16
 
12
17
  def barplot(data, params, fmt = nil, count: false)
@@ -37,7 +42,7 @@ module YouPlot
37
42
  labels = series[x_col]
38
43
  values = series[y_col].map(&:to_f)
39
44
  end
40
- UnicodePlot.barplot(labels, values, **params.to_hc)
45
+ ::UnicodePlot.barplot(labels, values, **params.to_hc)
41
46
  end
42
47
 
43
48
  def histogram(data, params)
@@ -45,7 +50,7 @@ module YouPlot
45
50
  series = data.series
46
51
  params.title ||= data.headers[0] if headers
47
52
  values = series[0].map(&:to_f)
48
- UnicodePlot.histogram(values, **params.to_hc)
53
+ ::UnicodePlot.histogram(values, **params.to_hc)
49
54
  end
50
55
 
51
56
  def line(data, params, fmt = nil)
@@ -55,7 +60,7 @@ module YouPlot
55
60
  # If there is only one series, it is assumed to be sequential data.
56
61
  params.ylabel ||= headers[0] if headers
57
62
  y = series[0].map(&:to_f)
58
- UnicodePlot.lineplot(y, **params.to_hc)
63
+ ::UnicodePlot.lineplot(y, **params.to_hc)
59
64
  else
60
65
  # If there are 2 or more series...
61
66
  if fmt == 'yx'
@@ -73,7 +78,7 @@ module YouPlot
73
78
  end
74
79
  x = series[x_col].map(&:to_f)
75
80
  y = series[y_col].map(&:to_f)
76
- UnicodePlot.lineplot(x, y, **params.to_hc)
81
+ ::UnicodePlot.lineplot(x, y, **params.to_hc)
77
82
  end
78
83
  end
79
84
 
@@ -90,10 +95,11 @@ module YouPlot
90
95
  params.name ||= headers[1]
91
96
  params.xlabel ||= headers[0]
92
97
  end
98
+ params.xlim ||= series[0].flatten.minmax # why need?
93
99
  params.ylim ||= series[1..-1].flatten.minmax # why need?
94
- 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)
95
101
  2.upto(series.size - 1) do |i|
96
- 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))
97
103
  end
98
104
  plot
99
105
  end
@@ -103,14 +109,15 @@ module YouPlot
103
109
  series = data.series
104
110
  method2 = get_method2(method1)
105
111
  series.map! { |s| s.map(&:to_f) }
106
- series = series.each_slice(2).to_a
112
+ series2 = series.each_slice(2).to_a
113
+ series = nil
107
114
  params.name ||= headers[0] if headers
108
- params.xlim = series.map(&:first).flatten.minmax # why need?
109
- params.ylim = series.map(&:last).flatten.minmax # why need?
110
- x1, y1 = series.shift
111
- plot = UnicodePlot.public_send(method1, x1, y1, **params.to_hc)
112
- series.each_with_index do |(xi, yi), i|
113
- UnicodePlot.public_send(method2, plot, xi, yi, name: headers&.[]((i + 1) * 2))
115
+ params.xlim ||= series2.map(&:first).flatten.minmax # why need?
116
+ params.ylim ||= series2.map(&:last).flatten.minmax # why need?
117
+ x1, y1 = series2.shift
118
+ plot = ::UnicodePlot.public_send(method1, x1, y1, **params.to_hc)
119
+ series2.each_with_index do |(xi, yi), i|
120
+ ::UnicodePlot.public_send(method2, plot, xi, yi, name: headers&.[]((i + 1) * 2))
114
121
  end
115
122
  plot
116
123
  end
@@ -148,39 +155,51 @@ module YouPlot
148
155
  series = data.series
149
156
  headers ||= (1..series.size).map(&:to_s)
150
157
  series.map! { |s| s.map(&:to_f) }
151
- UnicodePlot.boxplot(headers, series, **params.to_hc)
158
+ ::UnicodePlot.boxplot(headers, series, **params.to_hc)
152
159
  end
153
160
 
154
161
  def colors(color_names = false)
155
- UnicodePlot::StyledPrinter::TEXT_COLORS.each do |k, v|
156
- print v
157
- print k
162
+ # FIXME
163
+ s = String.new
164
+ ::UnicodePlot::StyledPrinter::TEXT_COLORS.each do |k, v|
165
+ s << v
166
+ s << k.to_s
158
167
  unless color_names
159
- print "\t"
160
- print ' ●'
168
+ s << "\t"
169
+ s << ' ●'
161
170
  end
162
- print "\033[0m"
163
- print "\t"
171
+ s << "\033[0m"
172
+ s << "\t"
173
+ end
174
+ s << "\n"
175
+ def s.render(obj)
176
+ obj.print(self)
164
177
  end
165
- puts
178
+ s
166
179
  end
167
180
 
168
181
  def check_series_size(data, fmt)
169
182
  series = data.series
170
183
  if series.size == 1
171
- warn 'youplot: There is only one series of input data. Please check the delimiter.'
172
- warn ''
173
- warn " Headers: \e[35m#{data.headers.inspect}\e[0m"
174
- warn " The first item is: \e[35m\"#{series[0][0]}\"\e[0m"
175
- warn " The last item is : \e[35m\"#{series[0][-1]}\"\e[0m"
176
- exit 1
184
+ warn <<~EOS
185
+ youplot: There is only one series of input data. Please check the delimiter.
186
+
187
+ Headers: \e[35m#{data.headers.inspect}\e[0m
188
+ The first item is: \e[35m\"#{series[0][0]}\"\e[0m
189
+ The last item is : \e[35m\"#{series[0][-1]}\"\e[0m
190
+ EOS
191
+ # NOTE: Error messages cannot be colored.
192
+ YouPlot.run_as_executable ? exit(1) : raise(Error)
177
193
  end
178
194
  if fmt == 'xyxy' && series.size.odd?
179
- warn 'YouPlot: In the xyxy format, the number of series must be even.'
180
- warn ''
181
- warn " Number of series: \e[35m#{series.size}\e[0m"
182
- warn " Headers: \e[35m#{data.headers.inspect}\e[0m"
183
- exit 1
195
+ warn <<~EOS
196
+ YouPlot: In the xyxy format, the number of series must be even.
197
+
198
+ Number of series: \e[35m#{series.size}\e[0m
199
+ Headers: \e[35m#{data.headers.inspect}\e[0m
200
+ EOS
201
+ # NOTE: Error messages cannot be colored.
202
+ YouPlot.run_as_executable ? exit(1) : raise(Error)
184
203
  end
185
204
  end
186
205
  end