diff --git a/README.md b/README.md index 1d80952..2d5843e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ +# Forked from the original bashplotlib: https://github.com/glamp/bashplotlib +## bugfix and feature addition: +- added -d delimiter and default to tab. (scatter) +- default color to none to remove strange character during bash piping. (scatter + hist) +- fixed "broken pipe" during bash piping. (scatter + hist) + + + +############################# Original README ############################# + # bashplotlib *plotting in the terminal* diff --git a/bashplotlib/histogram.py b/bashplotlib/histogram.py index fe0a5f7..7afcda5 100644 --- a/bashplotlib/histogram.py +++ b/bashplotlib/histogram.py @@ -16,6 +16,9 @@ from .utils.helpers import * from .utils.commandhelp import hist +from signal import signal, SIGPIPE, SIG_DFL +signal(SIGPIPE,SIG_DFL) + def calc_bins(n, min_val, max_val, h=None, binwidth=None): """ @@ -42,9 +45,8 @@ def read_numbers(numbers): for number in numbers: yield float(str(number).strip()) else: - with open(numbers) as fh: - for number in fh: - yield float(number.strip()) + for number in open(numbers): + yield float(number.strip()) def run_demo(): @@ -107,11 +109,10 @@ def plot_hist(f, height=20.0, bincount=None, binwidth=None, pch="o", colour="def pch = "o" if isinstance(f, str): - with open(f) as fh: - f = fh.readlines() + f = open(f).readlines() min_val, max_val = None, None - n, mean, sd = 0.0, 0.0, 0.0 + n, mean = 0.0, 0.0 for number in read_numbers(f): n += 1 @@ -123,12 +124,6 @@ def plot_hist(f, height=20.0, bincount=None, binwidth=None, pch="o", colour="def mean /= n - for number in read_numbers(f): - sd += (mean - number)**2 - - sd /= (n - 1) - sd **= 0.5 - bins = list(calc_bins(n, min_val, max_val, bincount, binwidth)) hist = dict((i, 0) for i in range(len(bins))) @@ -184,12 +179,11 @@ def plot_hist(f, height=20.0, bincount=None, binwidth=None, pch="o", colour="def print(" " * (nlen + 1) + "-" * len(xs)) if xlab: - labels = abbreviate([str(b) for b in bins]) - xlen = len(labels[0]) + xlen = len(str(float((max_y) / height) + max_y)) for i in range(0, xlen): printcolour(" " * (nlen + 1), True, colour) for x in range(0, len(hist)): - num = labels[x] + num = str(bins[x]) if x % 2 != 0: pass elif i < len(num): @@ -209,7 +203,6 @@ def plot_hist(f, height=20.0, bincount=None, binwidth=None, pch="o", colour="def summary = "|" + ("observations: %d" % n).center(center) + "|\n" summary += "|" + ("min value: %f" % min_val).center(center) + "|\n" summary += "|" + ("mean : %f" % mean).center(center) + "|\n" - summary += "|" + ("std dev : %f" % sd).center(center) + "|\n" summary += "|" + ("max value: %f" % max_val).center(center) + "|\n" summary += "-" * (2 + center) print(summary) @@ -232,7 +225,7 @@ def main(): parser.add_option('-x', '--xlab', help='label bins on x-axis', default=None, action="store_true", dest='x') parser.add_option('-c', '--colour', help='colour of the plot (%s)' % - colour_help, default='default', dest='colour') + colour_help, default=None, dest='colour') parser.add_option('-d', '--demo', help='run demos', action='store_true', dest='demo') parser.add_option('-n', '--nosummary', help='hide summary', action='store_false', dest='showSummary', default=True) diff --git a/bashplotlib/scatterplot.py b/bashplotlib/scatterplot.py index 76d20e4..9ce6900 100644 --- a/bashplotlib/scatterplot.py +++ b/bashplotlib/scatterplot.py @@ -12,13 +12,15 @@ from .utils.helpers import * from .utils.commandhelp import scatter +from signal import signal, SIGPIPE, SIG_DFL +signal(SIGPIPE,SIG_DFL) + def get_scale(series, is_y=False, steps=20): min_val = min(series) max_val = max(series) scaled_series = [] - for x in drange(min_val, max_val, (max_val - min_val) / steps, - include_stop=True): + for x in drange(min_val, max_val, (max_val - min_val) / steps): if x > 0 and scaled_series and max(scaled_series) < 0: scaled_series.append(0.0) scaled_series.append(x) @@ -28,33 +30,12 @@ def get_scale(series, is_y=False, steps=20): return scaled_series -def _plot_scatter(xs, ys, size, pch, colour, title, cs): - plotted = set() - - if title: - print(box_text(title, 2 * len(get_scale(xs, False, size)) + 1)) - - print("-" * (2 * len(get_scale(xs, False, size)) + 2)) - for y in get_scale(ys, True, size): - print("|", end=' ') - for x in get_scale(xs, False, size): - point = " " - for (i, (xp, yp)) in enumerate(zip(xs, ys)): - if xp <= x and yp >= y and (xp, yp) not in plotted: - point = pch - plotted.add((xp, yp)) - if cs: - colour = cs[i] - printcolour(point, True, colour) - print(" |") - print("-" * (2 * len(get_scale(xs, False, size)) + 2)) - -def plot_scatter(f, xs, ys, size, pch, colour, title): +def plot_scatter(f, xs, ys, size, pch, colour, title, delimiter): """ Form a complex number. Arguments: - f -- comma delimited file w/ x,y coordinates + f -- delimited (by delimiter) file w/ x,y coordinates xs -- if f not specified this is a file w/ x coordinates ys -- if f not specified this is a filew / y coordinates size -- size of the plot @@ -62,27 +43,45 @@ def plot_scatter(f, xs, ys, size, pch, colour, title): colour -- colour of the points title -- title of the plot """ - cs = None + if f: if isinstance(f, str): - with open(f) as fh: - data = [tuple(line.strip().split(',')) for line in fh] - else: - data = [tuple(line.strip().split(',')) for line in f] - xs = [float(i[0]) for i in data] - ys = [float(i[1]) for i in data] - if len(data[0]) > 2: - cs = [i[2].strip() for i in data] - elif isinstance(xs, list) and isinstance(ys, list): - pass + f = open(f) + + data = [tuple(map(float, line.strip().split(delimiter))) for line in f] + xs = [i[0] for i in data] + ys = [i[1] for i in data] else: - with open(xs) as fh: - xs = [float(str(row).strip()) for row in fh] - with open(ys) as fh: - ys = [float(str(row).strip()) for row in fh] + xs = [float(str(row).strip()) for row in open(xs)] + ys = [float(str(row).strip()) for row in open(ys)] - _plot_scatter(xs, ys, size, pch, colour, title, cs) - + plotted = set() + + if title: + print(box_text(title, 2 * len(get_scale(xs, False, size)) + 1)) + + print("-" * (2 * len(get_scale(xs, False, size)) + 2)) + for y in get_scale(ys, True, size): + print("|", end=' ') + for x in get_scale(xs, False, size): + point = " " + for (i, (xp, yp)) in enumerate(zip(xs, ys)): + if xp <= x and yp >= y and (xp, yp) not in plotted: + point = pch + #point = str(i) + plotted.add((xp, yp)) + if x == 0 and y == 0: + point = "o" + elif x == 0: + point = "|" + elif y == 0: + point = "-" + if colour: + printcolour(point, True, colour) + else: + print(point, end='') + print("|") + print("-" * (2 * len(get_scale(xs, False, size)) + 2)) def main(): @@ -94,9 +93,10 @@ def main(): parser.add_option('-x', help='x coordinates', default=None, dest='x') parser.add_option('-y', help='y coordinates', default=None, dest='y') parser.add_option('-s', '--size', help='y coordinates', default=20, dest='size', type='int') + parser.add_option('-d', '--delimiter', help='delimiter', default="\t", dest='delimiter') parser.add_option('-p', '--pch', help='shape of point', default="x", dest='pch') parser.add_option('-c', '--colour', help='colour of the plot (%s)' % - colour_help, default='default', dest='colour') + colour_help, default=None, dest='colour') opts, args = parser.parse_args() @@ -104,7 +104,7 @@ def main(): opts.f = sys.stdin.readlines() if opts.f or (opts.x and opts.y): - plot_scatter(opts.f, opts.x, opts.y, opts.size, opts.pch, opts.colour, opts.t) + plot_scatter(opts.f, opts.x, opts.y, opts.size, opts.pch, opts.colour, opts.t, opts.delimiter) else: print("nothing to plot!") diff --git a/bashplotlib/utils/helpers.py b/bashplotlib/utils/helpers.py index 8b37cf5..685b507 100644 --- a/bashplotlib/utils/helpers.py +++ b/bashplotlib/utils/helpers.py @@ -20,30 +20,29 @@ "grey": '\033[90m', "black": '\033[30m', "default": '\033[39m', + "none": '', "ENDC": '\033[39m', } colour_help = ', '.join([colour for colour in bcolours if colour != "ENDC"]) -def get_colour(colour, default="default"): +def get_colour(colour): """ Get the escape code sequence for a colour """ - return bcolours.get(colour, bcolours[default]) + return bcolours.get(colour, bcolours['ENDC']) -def printcolour(text, sameline=False, colour="default"): +def printcolour(text, sameline=False, colour=get_colour("ENDC")): """ Print color text using escape codes """ - sep = '' if sameline else '\n' - - # If no colour set, do not print color ESC characters - if get_colour(colour) == get_colour("ENDC"): - sys.stdout.write(text + sep) + if sameline: + sep = '' else: - sys.stdout.write(get_colour(colour) + text + get_colour("ENDC") + sep) + sep = '\n' + sys.stdout.write(get_colour(colour) + text + bcolours["ENDC"] + sep) def drange(start, stop, step=1.0, include_stop=False): @@ -66,18 +65,6 @@ def drange(start, stop, step=1.0, include_stop=False): r = round(r, 10) -def abbreviate(labels, rfill=' '): - """ - Abbreviate labels without introducing ambiguities. - """ - max_len = max(len(l) for l in labels) - for i in range(1, max_len): - abbrev = [l[:i].ljust(i, rfill) for l in labels] - if len(abbrev) == len(set(abbrev)): - break - return abbrev - - def box_text(text, width, offset=0): """ Return text inside an ascii textbox