YouPlot/lib/uplot/plot.rb

158 lines
4.5 KiB
Ruby
Raw Normal View History

2020-09-18 23:08:09 +08:00
# frozen_string_literal: true
2020-08-16 11:46:45 +08:00
require 'unicode_plot'
module Uplot
# plotting functions.
module Plot
module_function
2020-10-10 22:21:55 +08:00
def barplot(data, params, count: false)
2020-08-16 11:46:45 +08:00
headers = data.headers
series = data.series
if count
2020-11-08 00:41:13 +08:00
series = Preprocessing.count_values(series[0])
2020-08-16 11:46:45 +08:00
params.title = headers[0] if headers
end
params.title ||= headers[1] if headers
2020-11-08 11:21:05 +08:00
labels = series[0].map(&:to_s)
2020-08-16 11:46:45 +08:00
values = series[1].map(&:to_f)
UnicodePlot.barplot(labels, values, **params.to_hc)
end
def histogram(data, params)
headers = data.headers
series = data.series
params.title ||= data.headers[0] if headers
values = series[0].map(&:to_f)
UnicodePlot.histogram(values, **params.to_hc)
end
def line(data, params)
headers = data.headers
series = data.series
if series.size == 1
# If there is only one series, it is assumed to be sequential data.
params.ylabel ||= headers[0] if headers
y = series[0].map(&:to_f)
UnicodePlot.lineplot(y, **params.to_hc)
else
# If there are 2 or more series,
# assume that the first 2 series are the x and y series respectively.
if headers
params.xlabel ||= headers[0]
params.ylabel ||= headers[1]
end
x = series[0].map(&:to_f)
y = series[1].map(&:to_f)
UnicodePlot.lineplot(x, y, **params.to_hc)
end
end
def get_method2(method1)
2020-11-06 09:21:36 +08:00
"#{method1}!".to_sym
2020-08-16 11:46:45 +08:00
end
def plot_xyy(data, method1, params)
2020-08-16 11:46:45 +08:00
headers = data.headers
series = data.series
method2 = get_method2(method1)
series.map! { |s| s.map(&:to_f) }
if headers
params.name ||= headers[1]
params.xlabel ||= headers[0]
end
params.ylim ||= series[1..-1].flatten.minmax # why need?
plot = UnicodePlot.public_send(method1, series[0], series[1], **params.to_hc)
2.upto(series.size - 1) do |i|
UnicodePlot.public_send(method2, plot, series[0], series[i], name: headers&.[](i))
end
plot
end
def plot_xyxy(data, method1, params)
2020-08-16 11:46:45 +08:00
headers = data.headers
series = data.series
method2 = get_method2(method1)
series.map! { |s| s.map(&:to_f) }
series = series.each_slice(2).to_a
params.name ||= headers[0] if headers
params.xlim = series.map(&:first).flatten.minmax # why need?
params.ylim = series.map(&:last).flatten.minmax # why need?
x1, y1 = series.shift
plot = UnicodePlot.public_send(method1, x1, y1, **params.to_hc)
series.each_with_index do |(xi, yi), i|
UnicodePlot.public_send(method2, plot, xi, yi, name: headers&.[]((i + 1) * 2))
end
plot
end
def plot_fmt(data, fmt, method1, params)
2020-08-16 11:46:45 +08:00
case fmt
when 'xyy'
plot_xyy(data, method1, params)
2020-08-16 11:46:45 +08:00
when 'xyxy'
plot_xyxy(data, method1, params)
else
raise "Unknown format: #{fmt}"
2020-08-16 11:46:45 +08:00
end
end
def lines(data, params, fmt = 'xyy')
check_series_size(data, fmt)
plot_fmt(data, fmt, :lineplot, params)
end
2020-08-16 11:46:45 +08:00
def scatter(data, params, fmt = 'xyy')
2020-08-16 12:20:52 +08:00
check_series_size(data, fmt)
plot_fmt(data, fmt, :scatterplot, params)
2020-08-16 11:46:45 +08:00
end
def density(data, params, fmt = 'xyy')
2020-08-16 12:20:52 +08:00
check_series_size(data, fmt)
plot_fmt(data, fmt, :densityplot, params)
2020-08-16 11:46:45 +08:00
end
def boxplot(data, params)
headers = data.headers
series = data.series
headers ||= (1..series.size).map(&:to_s)
series.map! { |s| s.map(&:to_f) }
UnicodePlot.boxplot(headers, series, **params.to_hc)
end
2020-08-16 12:20:52 +08:00
2020-11-06 09:21:36 +08:00
def colors(color_names = false)
2020-09-15 17:58:34 +08:00
UnicodePlot::StyledPrinter::TEXT_COLORS.each do |k, v|
print v
print k
2020-11-06 09:21:36 +08:00
unless color_names
print "\t"
print ' ●'
end
2020-09-15 17:58:34 +08:00
print "\033[0m"
print "\t"
end
puts
2020-08-24 19:17:33 +08:00
end
2020-08-16 12:20:52 +08:00
def check_series_size(data, fmt)
series = data.series
if series.size == 1
2020-08-16 12:43:37 +08:00
warn 'uplot: There is only one series of input data. Please check the delimiter.'
warn ''
2020-08-16 12:34:41 +08:00
warn " Headers: \e[35m#{data.headers.inspect}\e[0m"
2020-08-16 12:20:52 +08:00
warn " The first item is: \e[35m\"#{series[0][0]}\"\e[0m"
warn " The last item is : \e[35m\"#{series[0][-1]}\"\e[0m"
exit 1
end
2020-08-16 12:34:41 +08:00
if fmt == 'xyxy' && series.size.odd?
2020-08-16 12:43:37 +08:00
warn 'uplot: In the xyxy format, the number of series must be even.'
warn ''
2020-08-16 12:34:41 +08:00
warn " Number of series: \e[35m#{series.size}\e[0m"
warn " Headers: \e[35m#{data.headers.inspect}\e[0m"
exit 1
end
2020-08-16 12:20:52 +08:00
end
2020-08-16 11:46:45 +08:00
end
end