45 Commits

Author SHA1 Message Date
kojix2
19f05e57ac v0.4.4 2022-08-02 17:05:30 +09:00
kojix2
f11fd6babb Consistent variable names 2022-08-02 16:58:48 +09:00
kojix2
9d69c4322c Make configuration files available (#30) 2022-07-31 22:37:50 +09:00
kojix2
41c0d37a13 Friendly error messages 2022-05-25 16:24:13 +09:00
kojix2
a1dcc532ea Friendly error messages 2022-05-25 16:03:33 +09:00
kojix2
523700348c Create doc.yml 2022-03-24 18:47:41 +09:00
kojix2
e34ab2b097 Update README.md
Do you need commit rights to my repository?
Do you want to get admin rights and take over the project?
If so, please feel free to contact kojix2.
2022-02-13 13:05:13 +09:00
kojix2
f8fe010d27 Add Ruby3.1 to CI (#29) 2021-12-30 11:54:15 +09:00
kojix2
e76d4f279e v0.4.3 2021-11-19 14:09:46 +09:00
kojix2
3a1a29424d Remove add_development_dependency from gem 2021-11-19 14:03:57 +09:00
kojix2
b78da2388a Rubocop auto correct 2021-11-19 13:56:09 +09:00
KIKISeries
a7bb75e87d Fix a typo
S -> s
2021-07-14 09:56:47 +09:00
kojix2
ca9f97a7dc Specify the version of UnicodePlot 2021-07-12 14:56:41 +09:00
kojix2
f67a5ce913 Add comments on the run_as_executable variable 2021-07-12 14:49:34 +09:00
kojix2
dbbfd366be Remove unused variable 2021-07-11 08:59:44 +09:00
kojix2
42cadee553 Improved CI
Remove needless line
2021-07-11 08:43:47 +09:00
kojix2
e689c69838 Update CI
* Enable bundler-cache
2021-07-11 08:38:05 +09:00
kojix2
c53169e9ee Update README.md (#24) 2021-07-03 07:22:19 +09:00
kojix2
95a35399a2 Show a error message when linecolor is specified as a number 2021-07-03 06:52:37 +09:00
kojix2
7c00f95962 Fix Readme style 2021-06-20 19:10:09 +09:00
kojix2
fcbf9305d7 Add StringIO for consistency 2021-06-18 10:43:28 +09:00
kojix2
04eddfd79b Fix typo 2021-06-17 08:19:04 +09:00
kojix2
125c2291d5 Add categorical/date to README 2021-06-17 08:13:58 +09:00
kojix2
6a72418d01 Update README 2021-06-17 07:49:51 +09:00
kojix2
72a56659de Removed -x and -y options
The -x and -y options now stand for --xlabel and --ylabel.

These options should be used to specify the series in the future.
2021-06-17 07:47:14 +09:00
kojix2
858792fa99 Fix a typo 2021-06-14 13:08:45 +09:00
kojix2
e7079c56a2 Update README.md 2021-06-14 13:07:29 +09:00
kojix2
bb8a16a327 Swap the order of count and color in help 2021-06-14 11:37:06 +09:00
kojix2
be0f706231 Update README.md 2021-06-14 11:23:52 +09:00
kojix2
e5c87fbe6f Add recommended tools to README.md 2021-06-11 10:48:33 +09:00
kojix2
4f17579846 v0.4.2 2021-06-10 11:35:35 +09:00
kojix2
81df12a033 Changed width option from Integer to Numeric
This is to keep consistency with other options
2021-06-10 11:33:46 +09:00
kojix2
a8073bc684 Convert xlim and ylim types to numbers
Fix (#18)
2021-06-10 11:19:35 +09:00
kojix2
23bb767afe Revert "Accept hyphens as an output option"
This reverts commit dfc027d972.

No need to change.
2021-06-08 17:44:53 +09:00
kojix2
dfc027d972 Accept hyphens as an output option 2021-06-07 23:51:46 +09:00
kojix2
7a1bacccbc Update README.md
Center the logo and badge
2021-06-04 00:20:54 +09:00
kojix2
92989eb582 🚀 Transferred YouPlot to RedDataTools 2021-06-03 12:01:07 +09:00
kojix2
33c68c0607 v0.4.1 2021-06-03 11:06:59 +09:00
kojix2
30b3b6e7d3 Rubocop auto correct 2021-06-03 11:03:49 +09:00
kojix2
d49a11bb7a Merge branch 'v0.4.1' 2021-06-03 11:01:20 +09:00
kojix2
c573d690bc Revert "Set the Gem Ruby version to 2.6 or higher"
I changed my mind, it better work on 2.4!

This reverts commit 2649959745.
2021-06-03 10:53:12 +09:00
kojix2
f823377c50 Make tests pass in Ruby 2.4 2021-06-03 10:48:47 +09:00
kojix2
d9777435a4 Add Test on ruby 2.4 2021-06-03 10:39:43 +09:00
kojix2
2649959745 Set the Gem Ruby version to 2.6 or higher 2021-06-03 10:32:20 +09:00
kojix2
4651c697d4 Add reverse to count 2021-05-31 22:50:11 +09:00
16 changed files with 338 additions and 164 deletions

View File

@@ -7,12 +7,11 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ 'ubuntu', 'macos' ] os: [ 'ubuntu', 'macos' ]
ruby: [ '2.6', '2.7', '3.0' ] ruby: [ '2.4', '2.5', '2.6', '2.7', '3.0', '3.1' ]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@v1
with: with:
ruby-version: ${{ matrix.ruby }} ruby-version: ${{ matrix.ruby }}
- run: gem install bundler bundler-cache: true
- run: bundle install
- run: bundle exec rake test - run: bundle exec rake test

23
.github/workflows/doc.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: doc
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.1
- name: Generate document
run: gem install -N yard && yard doc
- name: Publish Documentation on GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./doc

View File

@@ -4,3 +4,9 @@ source 'https://rubygems.org'
# Specify your gem's dependencies in youplot.gemspec # Specify your gem's dependencies in youplot.gemspec
gemspec gemspec
group :test do
gem 'rake'
gem 'simplecov'
gem 'test-unit'
end

155
README.md
View File

@@ -1,16 +1,16 @@
<p align="center"> <div align="center">
<img src="logo.svg" width="60%" height="60%" /> <img src="logo.svg">
</p> <hr>
<img alt="Build Status" src="https://github.com/red-data-tools/YouPlot/workflows/test/badge.svg">
<a href="https://rubygems.org/gems/youplot/"><img alt="Gem Version" src="https://badge.fury.io/rb/youplot.svg"></a>
<a href="https://zenodo.org/badge/latestdoi/283230219"><img alt="DOI" src="https://zenodo.org/badge/283230219.svg"></a>
<a href="https://rubydoc.info/gems/youplot/"><img alt="Docs Stable" src="https://img.shields.io/badge/docs-stable-blue.svg"></a>
<a href="LICENSE.txt"><img alt="The MIT License" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
![Build Status](https://github.com/kojix2/youplot/workflows/test/badge.svg) YouPlot is a command line tool that draws plots on the terminal.
[![Gem Version](https://badge.fury.io/rb/youplot.svg)](https://badge.fury.io/rb/youplot)
[![Docs Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://rubydoc.info/gems/youplot)
[![The MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.txt)
[![DOI](https://zenodo.org/badge/283230219.svg)](https://zenodo.org/badge/latestdoi/283230219)
YouPlot is a command line tool for Unicode Plotting working with data from standard stream.
:bar_chart: Powered by [UnicodePlot](https://github.com/red-data-tools/unicode_plot.rb) :bar_chart: Powered by [UnicodePlot](https://github.com/red-data-tools/unicode_plot.rb)
</div>
## Installation ## Installation
@@ -20,8 +20,9 @@ gem install youplot
## Quick Start ## Quick Start
* `cat data.tsv | uplot <command> [options]` or <img alt="barplot" src="https://user-images.githubusercontent.com/5798442/101999903-d36a2d00-3d24-11eb-9361-b89116f44122.png" width=160> <img alt="histogram" src="https://user-images.githubusercontent.com/5798442/101999820-21cafc00-3d24-11eb-86db-e410d19b07df.png" width=160> <img alt="scatter" src="https://user-images.githubusercontent.com/5798442/101999827-27284680-3d24-11eb-9903-551857eaa69c.png" width=160> <img alt="density" src="https://user-images.githubusercontent.com/5798442/101999828-2abbcd80-3d24-11eb-902c-2f44266fa6ae.png" width=160> <img alt="boxplot" src="https://user-images.githubusercontent.com/5798442/101999830-2e4f5480-3d24-11eb-8891-728c18bf5b35.png" width=160>
* `uplot <command> [options] <data.tsv>`
`uplot <command> [options] <data.tsv>`
### barplot ### barplot
@@ -100,10 +101,6 @@ curl -sL https://git.io/IRIStsv \
### count ### count
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.
* https://www.gencodegenes.org/human/
```sh ```sh
cat gencode.v35.annotation.gff3 \ cat gencode.v35.annotation.gff3 \
| grep -v '#' | grep 'gene' | cut -f1 \ | grep -v '#' | grep 'gene' | cut -f1 \
@@ -114,23 +111,21 @@ cat gencode.v35.annotation.gff3 \
<img alt="count" src="https://user-images.githubusercontent.com/5798442/101999832-30b1ae80-3d24-11eb-96fe-e5000bed1f5c.png"> <img alt="count" src="https://user-images.githubusercontent.com/5798442/101999832-30b1ae80-3d24-11eb-96fe-e5000bed1f5c.png">
</p> </p>
In this example, YouPlot counts the number of chromosomes where genes are located.
* [GENCODE - Human Release](https://www.gencodegenes.org/human/)
Note: `count` is not very fast because it runs in a Ruby script. Note: `count` is not very fast because it runs in a Ruby script.
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. 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.
```sh ```sh
cat gencode.v35.annotation.gff3 | grep -v '#' | grep 'gene' | cut -f1 \ cat gencode.v35.annotation.gff3 | grep -v '#' | grep 'gene' | cut -f1 \
| sort | uniq -c | sort -nrk2 | awk '{print $2,$1}' \ | sort | uniq -c | sort -nrk1 \
| uplot bar -d ' ' -t "The number of human gene annotations per chromosome" -c blue | uplot bar --fmt yx -d ' ' -t "The number of human gene annotations per chromosome" -c blue
``` ```
## Usage ## Usage
### Why YouPlot? ### Commands
Wouldn't it be a pain to have to run R, Python, Julia, gnuplot or whatever REPL just to check your data?
YouPlot is a command line tool for this purpose. With YouPlot, you can continue working without leaving your terminal and shell.
### How to use YouPlot?
`uplot` is the shortened form of `youplot`. You can use either. `uplot` is the shortened form of `youplot`. You can use either.
@@ -140,18 +135,7 @@ YouPlot is a command line tool for this purpose. With YouPlot, you can continue
| `uplot <command> [options] data.tsv ...` | Take input from files | | `uplot <command> [options] data.tsv ...` | Take input from files |
| `pipeline1 \| uplot <command> -O \| pipeline2` | Outputs data from stdin to stdout | | `pipeline1 \| uplot <command> -O \| pipeline2` | Outputs data from stdin to stdout |
### Where to output the plot? ### Subcommands
By default, the plot is output to *standard error output*.
The output file or stream for the plot can be specified with the `-o` option.
### Where to output the input data?
By default, the input data is not shown anywhere.
The `-O` option, with no arguments, outputs the input data directly to the standard output.
This is useful when passing data to a subsequent pipeline.
### What types of plots are available?
The following sub-commands are available. The following sub-commands are available.
@@ -164,74 +148,83 @@ The following sub-commands are available.
| scatter | s | draw a scatter plot | | scatter | s | draw a scatter plot |
| density | d | draw a density plot | | density | d | draw a density plot |
| boxplot | box | draw a horizontal boxplot | | boxplot | box | draw a horizontal boxplot |
| | | |
See Quick Start for `count`.
| command | short | how it works |
|-----------|-------|----------------------------------------------------------|
| count | c | draw a barplot based on the number of occurrences (slow) | | count | c | draw a barplot based on the number of occurrences (slow) |
| | | |
| colors | color | show the list of available colors |
### What if the header line is included? ### Output the plot
If your input data contains a header line, you need to specify the `-H` option. * `-o`
* By default, the plot is output to **standard error output**.
* If you want to output to standard input, Use hyphen ` -o -` or no argument `uplot s -o | `.
### How to specify the delimiter? ### Output the input data
Use the `-d` option. To specify a blank space, you can use `uplot bar -d ' ' data.txt`. * `-O`
You do not need to use `-d` option for tab-delimited text since the default value is tab. * By default, the input data is not shown anywhere.
* If you want to pass the input data directly to the standard output, Use hyphen `-O -` or no argument `uplot s -O |`.
* This is useful when passing data to a subsequent pipeline.
### Is there a way to specify a column as the x-axis or y-axis? ### Header
Not yet. * `-H`
YouPlot treats the first column as the X axis and the second column as the Y axis. * If input data contains a header line, you need to specify the `-H` option.
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.
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.
* `--fmt xyy` `--fmt xyxy` `--fmt yx` options give you a few more choices. ### Delimiter
See `youplot <command> --help` for more details.
* Use `awk '{print $2, $1}'` to swap lines. * `-d`
* Use `paste` to concatenate series. * You do not need to use `-d` option for tab-delimited text since the default value is tab.
* To specify a blank space, you can use `uplot bar -d ' ' data.txt`.
### How to plot real-time data? ### Real-time data
Experimental progressive mode is currently under development. * `-p` `--progress`
* Experimental progressive mode is currently under development.
* `ruby -e 'loop{puts rand(100)}' | uplot line --progress`
```sh ### Show detailed options for subcommands
ruby -e 'loop{puts rand(100)}' | uplot line --progress
```
### How to view detailed command line options? * `--help`
* The `--help` option will show more detailed options for each subcommand.
* `uplot hist --help`
Use `--help` to print command-specific options. ### Set columns as x-axis or y-axis
`uplot hist --help` * YouPlot treats the first column as the X axis and the second column as the Y axis. 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.
* 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.
``` * `--fmt`
Usage: uplot histogram [options] <in.tsv> * `--fmt xyy` `--fmt xyxy` `--fmt yx` options give you a few more choices. See `youplot <command> --help` for more details.
* The fmt option may be renamed in the future.
* The `-x` and `-y` options might be used to specify columns in the future.
Options for histogram: * Use `awk '{print $2, $1}'` to swap columns. Use `paste` to concatenate series.
--symbol VAL character to be used to plot the bars
--closed VAL side of the intervals to be closed [left]
-n, --nbins VAL approximate number of bins
Options: ### Categorical data
...
```
### How to view the list of available colors? * With GNU datamash, you can manage to handle categorized data.
* `cat test/fixtures/iris.csv | sed '/^$/d' | datamash --header-in --output-delimiter=: -t, -g5 collapse 3,4 | cut -f2-3 -d: | sed 's/:/\n/g' | uplot s -d, -T --fmt xyxy`
* This is not so easy...
```sh ### Time series
uplot colors
``` * Not yet supported.
## Tools that are useful to use with YouPlot
* [csvtk](https://github.com/shenwei356/csvtk)
* [GNU datamash](https://www.gnu.org/software/datamash/)
* [awk](https://www.gnu.org/software/gawk/)
* [xsv](https://github.com/BurntSushi/xsv)
## Contributing ## Contributing
YouPlot is a library under development, so even small improvements like typofix are welcome! YouPlot is a library under development, so even small improvements like typofix are welcome!
Please feel free to send us your pull requests. Please feel free to send us your pull requests.
* [Report bugs](https://github.com/kojix2/youplot/issues) * [Report bugs](https://github.com/red-data-tools/YouPlot/issues)
* Fix bugs and [submit pull requests](https://github.com/kojix2/youplot/pulls) * Fix bugs and [submit pull requests](https://github.com/red-data-tools/YouPlot/pulls)
* Write, clarify, or fix documentation * Write, clarify, or fix documentation
* English corrections by native speakers are welcome. * English corrections by native speakers are welcome.
* Suggest or add new features * Suggest or add new features
@@ -245,11 +238,15 @@ git clone https://github.com/your_name/YouPlot
bundle install # Install the gem dependencies bundle install # Install the gem dependencies
bundle exec rake test # Run the test bundle exec rake test # Run the test
bundle exec rake install # Installation from source code bundle exec rake install # Installation from source code
bundle exec exe/uplot # Run youplot (Try out the edited code)
``` ```
Do you need commit rights to my repository?
Do you want to get admin rights and take over the project?
If so, please feel free to contact us.
### Acknowledgements ### Acknowledgements
* [Red Data Tools](https://github.com/red-data-tools) - Technical support
* [sampo grafiikka](https://jypg.net/sampo_grafiikka) - Project logo creation * [sampo grafiikka](https://jypg.net/sampo_grafiikka) - Project logo creation
* [yutaas](https://github.com/yutaas) - English proofreading * [yutaas](https://github.com/yutaas) - English proofreading

View File

@@ -6,6 +6,12 @@ require_relative 'youplot/parameters'
require_relative 'youplot/command' require_relative 'youplot/command'
module YouPlot module YouPlot
# @run_as_executable = true / false
# YouPlot behaves slightly differently when run as a command line tool
# and when run as a script (e.g. for testing). In the event of an error,
# when run as a command line tool, YouPlot will display a short error message
# and exit abnormally. When run as a script, it will just raise an error.
@run_as_executable = false
class << self class << self
attr_accessor :run_as_executable attr_accessor :run_as_executable
@@ -13,5 +19,4 @@ module YouPlot
@run_as_executable @run_as_executable
end end
end end
@run_as_executable = false
end end

View File

@@ -6,22 +6,30 @@ module YouPlot
module Processing module Processing
module_function module_function
def count_values(arr, tally: true) def count_values(arr, tally: true, reverse: false)
# tally was added in Ruby 2.7 # tally was added in Ruby 2.7
result = \
if tally && Enumerable.method_defined?(:tally) if tally && Enumerable.method_defined?(:tally)
arr.tally arr.tally
else else
# value_counts Enumerable::Statistics # value_counts Enumerable::Statistics
arr.value_counts(dropna: false) arr.value_counts(dropna: false)
end end
.sort do |a, b|
# sorting
result = result.sort do |a, b|
# compare values # compare values
r = b[1] <=> a[1] r = b[1] <=> a[1]
# If the values are the same, compare by name # If the values are the same, compare by name
r = a[0] <=> b[0] if r == 0 r = a[0] <=> b[0] if r.zero?
r r
end end
.transpose
# --reverse option
result.reverse! if reverse
# prepare for barplot
result.transpose
end end
end end
end end

View File

@@ -6,6 +6,27 @@
require_relative 'processing' require_relative 'processing'
require 'unicode_plot' require 'unicode_plot'
# If the line color is specified as a number, the program will display an error
# message to the user and exit. Remove this patch when UnicodePlot is improved.
module UnicodePlot
class << self
alias lineplot_original lineplot
def lineplot(*args, **kw)
if kw[:color].is_a? Numeric
warn <<~EOS
YouPlot: Line colors cannot be specified by numerical values.
For more information, please see the following issue.
https://github.com/red-data-tools/unicode_plot.rb/issues/34
EOS
YouPlot.run_as_executable ? exit(1) : raise(Error)
end
lineplot_original(*args, **kw)
end
end
end
module YouPlot module YouPlot
# plotting functions. # plotting functions.
module Backends module Backends
@@ -14,12 +35,12 @@ module YouPlot
module_function module_function
def barplot(data, params, fmt = nil, count: false) def barplot(data, params, fmt = nil, count: false, reverse: false)
headers = data.headers headers = data.headers
series = data.series series = data.series
# `uplot count` # `uplot count`
if count if count
series = Processing.count_values(series[0]) series = Processing.count_values(series[0], reverse: reverse)
params.title = headers[0] if headers params.title = headers[0] if headers
end end
if series.size == 1 if series.size == 1
@@ -106,11 +127,10 @@ module YouPlot
def plot_xyxy(data, method1, params) def plot_xyxy(data, method1, params)
headers = data.headers headers = data.headers
series = data.series series2 = data.series
.map { |s| s.map(&:to_f) }
.each_slice(2).to_a
method2 = get_method2(method1) method2 = get_method2(method1)
series.map! { |s| s.map(&:to_f) }
series2 = series.each_slice(2).to_a
series = nil
params.name ||= headers[0] if headers params.name ||= headers[0] if headers
params.xlim ||= series2.map(&:first).flatten.minmax # why need? params.xlim ||= series2.map(&:first).flatten.minmax # why need?
params.ylim ||= series2.map(&:last).flatten.minmax # why need? params.ylim ||= series2.map(&:last).flatten.minmax # why need?
@@ -182,7 +202,7 @@ module YouPlot
series = data.series series = data.series
if series.size == 1 if series.size == 1
warn <<~EOS warn <<~EOS
youplot: There is only one series of input data. Please check the delimiter. YouPlot: There is only one series of input data. Please check the delimiter.
Headers: \e[35m#{data.headers.inspect}\e[0m Headers: \e[35m#{data.headers.inspect}\e[0m
The first item is: \e[35m\"#{series[0][0]}\"\e[0m The first item is: \e[35m\"#{series[0][0]}\"\e[0m

View File

@@ -40,6 +40,24 @@ module YouPlot
return return
end end
# config command
if @command == :config
if ENV['MYYOUPLOTRC']
puts "config file : #{ENV['MYYOUPLOTRC']}"
puts parser.config.inspect
else
puts <<~EOS
You don't have a config file. The default config file paths are:
./.youplot.yml, ./.youplotrc, ~/.youplot.yml, ~/.youplotrc
You can specify a config file with the environment variable MYYOUPLOTRC.
File format is YAML. For example:
width : 40
height : 20
EOS
end
return
end
# progressive mode # progressive mode
if options[:progressive] if options[:progressive]
stop = false stop = false
@@ -63,9 +81,15 @@ module YouPlot
# normal mode # normal mode
else else
# Sometimes the input file does not end with a newline code. # Sometimes the input file does not end with a newline code.
while (input = Kernel.gets(nil)) begin
main(input) begin
input = Kernel.gets(nil)
rescue Errno::ENOENT => e
warn e.message
next
end end
main(input)
end until input
end end
end end
@@ -135,7 +159,12 @@ module YouPlot
rescue CSV::MalformedCSVError => e rescue CSV::MalformedCSVError => e
warn 'Failed to parse the text. ' warn 'Failed to parse the text. '
warn 'Please try to set the correct character encoding with --encoding option.' warn 'Please try to set the correct character encoding with --encoding option.'
raise e warn e.backtrace.grep(/youplot/).first
exit 1
rescue ArgumentError => e
warn 'Failed to parse the text. '
warn e.backtrace.grep(/youplot/).first
exit 1
end end
data data
@@ -146,7 +175,7 @@ module YouPlot
when :bar, :barplot when :bar, :barplot
@backend.barplot(data, params, options[:fmt]) @backend.barplot(data, params, options[:fmt])
when :count, :c when :count, :c
@backend.barplot(data, params, count: true) @backend.barplot(data, params, count: true, reverse: options[:reverse])
when :hist, :histogram when :hist, :histogram
@backend.histogram(data, params) @backend.histogram(data, params)
when :line, :lineplot when :line, :lineplot
@@ -169,7 +198,7 @@ module YouPlot
def output_data(input) def output_data(input)
# Pass the input to subsequent pipelines # Pass the input to subsequent pipelines
case options[:pass] case options[:pass]
when IO when IO, StringIO
options[:pass].print(input) options[:pass].print(input)
else else
if options[:pass] if options[:pass]

View File

@@ -14,7 +14,7 @@ module YouPlot
# Remove blank lines # Remove blank lines
arr.delete_if do |i| arr.delete_if do |i|
i == [] or i.all? nil i == [] or i.all?(&:nil?)
end end
# get header # get header

View File

@@ -11,8 +11,8 @@ module YouPlot
:fmt, :fmt,
:progressive, :progressive,
:encoding, :encoding,
:color_names, :reverse, # count
:debug, :color_names, # color
keyword_init: true :debug
) )
end end

View File

@@ -9,25 +9,75 @@ module YouPlot
class Error < StandardError; end class Error < StandardError; end
attr_reader :command, :options, :params, attr_reader :command, :options, :params,
:main_parser, :sub_parser :main_parser, :sub_parser,
:config_file, :config
def initialize def initialize
@command = nil @command = nil
@options = Options.new( @options = Options.new(
delimiter: "\t", "\t", # elimiter:
transpose: false, false, # transpose:
headers: nil, nil, # headers:
pass: false, false, # pass:
output: $stderr, $stderr, # output:
fmt: 'xyy', 'xyy', # fmt:
progressive: false, false, # progressive:
encoding: nil, nil, # encoding:
color_names: false, false, # color_names:
debug: false false # debug:
) )
@params = Parameters.new @params = Parameters.new
if @config_file = find_config_file
ENV['MYYOUPLOTRC'] = @config_file
@config = read_config_file(config_file)
configure(config)
end
end
def candidate_paths
paths = []
paths << ENV['MYYOUPLOTRC'] if ENV['MYYOUPLOTRC']
paths << '.youplot.yml'
paths << '.youplotrc'
paths << File.join(ENV['HOME'], '.youplotrc') if ENV['HOME']
paths << File.join(ENV['HOME'], '.youplot.yml') if ENV['HOME']
paths
end
def find_config_file
config_file_path = nil
candidate_paths.each do |file|
path = File.expand_path(file)
if File.exist?(path)
config_file_path = path
break
end
end
config_file_path
end
def read_config_file(path)
require 'yaml'
YAML.load_file(path)
end
def configure(config)
option_members = @options.members
param_members = @params.members
# It would be more useful to be able to configure by plot type
config.each do |k, v|
k = k.to_sym
if option_members.include?(k)
@options[k] = v
elsif param_members.include?(k)
@params[k] = v
else
raise Error, "Unknown option/param: #{k}"
end
end
end end
def create_base_parser def create_base_parser
@@ -58,13 +108,13 @@ module YouPlot
parser.on('-t', '--title STR', String, 'print string on the top of plot') do |v| parser.on('-t', '--title STR', String, 'print string on the top of plot') do |v|
params.title = v params.title = v
end end
parser.on('-x', '--xlabel STR', String, 'print string on the bottom of the plot') do |v| parser.on('--xlabel STR', String, 'print string on the bottom of the plot') do |v|
params.xlabel = v params.xlabel = v
end end
parser.on('-y', '--ylabel STR', String, 'print string on the far left of the plot') do |v| parser.on('--ylabel STR', String, 'print string on the far left of the plot') do |v|
params.ylabel = v params.ylabel = v
end end
parser.on('-w', '--width INT', Integer, 'number of characters per row') do |v| parser.on('-w', '--width INT', Numeric, 'number of characters per row') do |v|
params.width = v params.width = v
end end
parser.on('-h', '--height INT', Numeric, 'number of rows') do |v| parser.on('-h', '--height INT', Numeric, 'number of rows') do |v|
@@ -95,7 +145,7 @@ module YouPlot
parser.on('-M', '--monochrome', TrueClass, 'no colouring even if writing to a tty') do |_v| parser.on('-M', '--monochrome', TrueClass, 'no colouring even if writing to a tty') do |_v|
UnicodePlot::IOContext.define_method(:color?) { false } # FIXME UnicodePlot::IOContext.define_method(:color?) { false } # FIXME
end end
parser.on('--encoding STR', String, 'Specify the input encoding') do |v| parser.on('--encoding STR', String, 'specify the input encoding') do |v|
options[:encoding] = v options[:encoding] = v
end end
# Optparse adds the help option, but it doesn't show up in usage. # Optparse adds the help option, but it doesn't show up in usage.
@@ -118,7 +168,7 @@ module YouPlot
Program: YouPlot (Tools for plotting on the terminal) Program: YouPlot (Tools for plotting on the terminal)
Version: #{YouPlot::VERSION} (using UnicodePlot #{UnicodePlot::VERSION}) Version: #{YouPlot::VERSION} (using UnicodePlot #{UnicodePlot::VERSION})
Source: https://github.com/kojix2/youplot Source: https://github.com/red-data-tools/YouPlot
Usage: uplot <command> [options] <in.tsv> Usage: uplot <command> [options] <in.tsv>
@@ -130,10 +180,9 @@ module YouPlot
scatter s draw a scatter plot scatter s draw a scatter plot
density d draw a density plot density d draw a density plot
boxplot box draw a horizontal boxplot boxplot box draw a horizontal boxplot
colors color show the list of available colors
count c draw a baplot based on the number of count c draw a baplot based on the number of
occurrences (slow) occurrences (slow)
colors color show the list of available colors
General options: General options:
--help print command specific help menu --help print command specific help menu
@@ -163,20 +212,21 @@ module YouPlot
end end
def sub_parser_add_canvas def sub_parser_add_canvas
sub_parser.on_head('--canvas STR', String, 'type of canvas') do |v| canvas_types = UnicodePlot::Canvas::CANVAS_CLASS_MAP.keys.join(', ')
sub_parser.on_head('--canvas STR', String, 'type of canvas', "(#{canvas_types})") do |v|
params.canvas = v.to_sym params.canvas = v.to_sym
end end
end end
def sub_parser_add_xlim def sub_parser_add_xlim
sub_parser.on_head('--xlim FLOAT,FLOAT', Array, 'plotting range for the x coordinate') do |v| sub_parser.on_head('--xlim FLOAT,FLOAT', Array, 'plotting range for the x coordinate') do |v|
params.xlim = v params.xlim = v.map(&:to_f)
end end
end end
def sub_parser_add_ylim def sub_parser_add_ylim
sub_parser.on_head('--ylim FLOAT,FLOAT', Array, 'plotting range for the y coordinate') do |v| sub_parser.on_head('--ylim FLOAT,FLOAT', Array, 'plotting range for the y coordinate') do |v|
params.ylim = v params.ylim = v.map(&:to_f)
end end
end end
@@ -226,6 +276,9 @@ module YouPlot
sub_parser_add_xscale sub_parser_add_xscale
when :count, :c when :count, :c
sub_parser.on_head('-r', '--reverse', TrueClass, 'reverse the result of comparisons') do |v|
options.reverse = v
end
sub_parser_add_symbol sub_parser_add_symbol
sub_parser_add_xscale sub_parser_add_xscale
@@ -270,10 +323,12 @@ module YouPlot
sub_parser_add_xlim sub_parser_add_xlim
when :colors, :color, :colours, :colour when :colors, :color, :colours, :colour
sub_parser.on_head('-n', '--names', 'show color names only', TrueClass) do |v| sub_parser.on_head('-n', '--names', TrueClass, 'show color names only') do |v|
options[:color_names] = v options[:color_names] = v
end end
when :config
else else
error_message = "uplot: unrecognized command '#{command}'" error_message = "uplot: unrecognized command '#{command}'"
if YouPlot.run_as_executable? if YouPlot.run_as_executable?

View File

@@ -1,5 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
module YouPlot module YouPlot
VERSION = '0.4.0' VERSION = '0.4.4'
end end

38
test/fixtures/iris-count.txt vendored Normal file
View File

@@ -0,0 +1,38 @@
sepal_length
┌ ┐
5.0 ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 10.0
5.1 ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 9.0
6.3 ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 9.0
5.7 ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■ 8.0
6.7 ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■ 8.0
5.5 ┤■■■■■■■■■■■■■■■■■■■■■■■■ 7.0
5.8 ┤■■■■■■■■■■■■■■■■■■■■■■■■ 7.0
6.4 ┤■■■■■■■■■■■■■■■■■■■■■■■■ 7.0
4.9 ┤■■■■■■■■■■■■■■■■■■■■ 6.0
5.4 ┤■■■■■■■■■■■■■■■■■■■■ 6.0
5.6 ┤■■■■■■■■■■■■■■■■■■■■ 6.0
6.0 ┤■■■■■■■■■■■■■■■■■■■■ 6.0
6.1 ┤■■■■■■■■■■■■■■■■■■■■ 6.0
4.8 ┤■■■■■■■■■■■■■■■■■ 5.0
6.5 ┤■■■■■■■■■■■■■■■■■ 5.0
4.6 ┤■■■■■■■■■■■■■■ 4.0
5.2 ┤■■■■■■■■■■■■■■ 4.0
6.2 ┤■■■■■■■■■■■■■■ 4.0
6.9 ┤■■■■■■■■■■■■■■ 4.0
7.7 ┤■■■■■■■■■■■■■■ 4.0
4.4 ┤■■■■■■■■■■ 3.0
5.9 ┤■■■■■■■■■■ 3.0
6.8 ┤■■■■■■■■■■ 3.0
7.2 ┤■■■■■■■■■■ 3.0
4.7 ┤■■■■■■■ 2.0
6.6 ┤■■■■■■■ 2.0
4.3 ┤■■■ 1.0
4.5 ┤■■■ 1.0
5.3 ┤■■■ 1.0
7.0 ┤■■■ 1.0
7.1 ┤■■■ 1.0
7.3 ┤■■■ 1.0
7.4 ┤■■■ 1.0
7.6 ┤■■■ 1.0
7.9 ┤■■■ 1.0
└ ┘

View File

@@ -40,6 +40,8 @@ class YouPlotIRISTest < Test::Unit::TestCase
assert_equal fixture('iris-barplot.txt'), @stderr_file.read assert_equal fixture('iris-barplot.txt'), @stderr_file.read
end end
# barplot doesn't make sense, but just to make sure it works.
test :bar do test :bar do
YouPlot::Command.new(['bar', '-H', '-d,', '-t', 'IRIS-BARPLOT']).run YouPlot::Command.new(['bar', '-H', '-d,', '-t', 'IRIS-BARPLOT']).run
assert_equal fixture('iris-barplot.txt'), @stderr_file.read assert_equal fixture('iris-barplot.txt'), @stderr_file.read
@@ -55,6 +57,8 @@ class YouPlotIRISTest < Test::Unit::TestCase
assert_equal fixture('iris-histogram.txt'), @stderr_file.read assert_equal fixture('iris-histogram.txt'), @stderr_file.read
end end
# Yeah, lineplot/lineplots don't make sense too.
test :lineplot do test :lineplot do
YouPlot::Command.new(['lineplot', '-H', '-d,', '-t', 'IRIS-LINEPLOT']).run YouPlot::Command.new(['lineplot', '-H', '-d,', '-t', 'IRIS-LINEPLOT']).run
assert_equal fixture('iris-lineplot.txt'), @stderr_file.read assert_equal fixture('iris-lineplot.txt'), @stderr_file.read
@@ -105,15 +109,20 @@ class YouPlotIRISTest < Test::Unit::TestCase
assert_equal fixture('iris-boxplot.txt'), @stderr_file.read assert_equal fixture('iris-boxplot.txt'), @stderr_file.read
end end
# test :c do # Yeah, lineplot/lineplots don't make sense too.
# YouPlot::Command.new(['count', '-H', '-d,']).run # Just checking the behavior.
# assert_equal fixture('iris-count.txt'), @stderr_file.read
# end
# test :count do test :c do
# YouPlot::Command.new(['c', '-H', '-d,']).run YouPlot::Command.new(['count', '-H', '-d,']).run
# assert_equal fixture('iris-count.txt'), @stderr_file.read assert_equal fixture('iris-count.txt'), @stderr_file.read
# end end
test :count do
YouPlot::Command.new(['c', '-H', '-d,']).run
assert_equal fixture('iris-count.txt'), @stderr_file.read
end
# Output options.
test :plot_output_stdout do test :plot_output_stdout do
YouPlot::Command.new(['bar', '-o', '-H', '-d,', '-t', 'IRIS-BARPLOT']).run YouPlot::Command.new(['bar', '-o', '-H', '-d,', '-t', 'IRIS-BARPLOT']).run

View File

@@ -155,21 +155,11 @@ class YouPlotSimpleTest < Test::Unit::TestCase
assert_equal fixture('simple-lineplot-xlabel.txt'), @stderr_file.read assert_equal fixture('simple-lineplot-xlabel.txt'), @stderr_file.read
end end
test :line_x do
YouPlot::Command.new(['line', '-x', 'X-LABEL']).run
assert_equal fixture('simple-lineplot-xlabel.txt'), @stderr_file.read
end
test :line_ylabel do test :line_ylabel do
YouPlot::Command.new(['line', '--ylabel', 'Y-LABEL']).run YouPlot::Command.new(['line', '--ylabel', 'Y-LABEL']).run
assert_equal fixture('simple-lineplot-ylabel.txt'), @stderr_file.read assert_equal fixture('simple-lineplot-ylabel.txt'), @stderr_file.read
end end
test :line_y do
YouPlot::Command.new(['line', '-y', 'Y-LABEL']).run
assert_equal fixture('simple-lineplot-ylabel.txt'), @stderr_file.read
end
test :line_width do test :line_width do
YouPlot::Command.new(['line', '--width', '17']).run YouPlot::Command.new(['line', '--width', '17']).run
assert_equal fixture('simple-lineplot-width-17.txt'), @stderr_file.read assert_equal fixture('simple-lineplot-width-17.txt'), @stderr_file.read

View File

@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
spec.summary = 'A command line tool for Unicode Plotting' spec.summary = 'A command line tool for Unicode Plotting'
spec.description = 'A command line tool for Unicode Plotting' spec.description = 'A command line tool for Unicode Plotting'
spec.homepage = 'https://github.com/kojix2/youplot' spec.homepage = 'https://github.com/red-data-tools/YouPlot'
spec.license = 'MIT' spec.license = 'MIT'
spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0') spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
@@ -19,10 +19,5 @@ Gem::Specification.new do |spec|
spec.executables = %w[uplot youplot] spec.executables = %w[uplot youplot]
spec.require_paths = ['lib'] spec.require_paths = ['lib']
spec.add_runtime_dependency 'unicode_plot' spec.add_dependency 'unicode_plot', '>= 0.0.5'
spec.add_development_dependency 'bundler'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'rubocop'
spec.add_development_dependency 'simplecov'
spec.add_development_dependency 'test-unit'
end end