Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace optparse with docopt for command line args #28

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions bashplotlib/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""bashplotlib/__init__.py
"""

import os, sys

PROJECT_ROOT = os.path.dirname(os.path.realpath(__file__))

4 changes: 4 additions & 0 deletions bashplotlib/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""cli/__init__.py
"""
26 changes: 26 additions & 0 deletions bashplotlib/cli/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""demo.py
"""
import os, sys
from bashplotlib.cli.hist import __doc__ as HIST_DOCSTRING
from bashplotlib.core.histogram import plot_hist
from bashplotlib import PROJECT_ROOT

DATA_PATH = os.path.realpath(os.path.join(PROJECT_ROOT, '..', 'data'))

if not os.path.exists(DATA_PATH):
sys.stderr.write('You need to download the example data set to run the demo...')
sys.stderr.write('try running `./examples/downloaddata.sh` to get the data')
sys.exit(1)

def _hist_demo():
f = os.path.join(DATA_PATH, 'exp.txt')
print f
plot_hist(f)

def run_demo(command):
if command == "hist":
_hist_demo()
elif command == "scatter":
raise NotImplementedError('`run_demo` is only implemented for `hist` cmd so far.')
16 changes: 16 additions & 0 deletions bashplotlib/cli/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""cli/helpers.py
"""
import sys, os
from select import select

def read_stdin_or_timeout():
"""Try reading stdin. give up in 0.5s if nothing read yet."""
timeout = 0.5
rlist, _, _ = select([sys.stdin], [], [], timeout)
if rlist:
return sys.stdin.readlines()
else:
return None

56 changes: 56 additions & 0 deletions bashplotlib/cli/hist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""hist - construct a histogram for a continuous variable from your terminal

Usage:
hist [[FILE|-f FILENAME] -t TITLE -b BINS -s SIZE -p MARKERSHAPE -x XLAB -c COLOUR] [-n] [-h]

Arguments:
FILE A file containing a column of numbers [default: stdin]
-f --file FILENAME Same as FILE but shorter and less explicit [default: stdin]
-t --title TITLE Title for the chart [default: ]
-b --bins BINS Number of bins in the histogram [default: None]
-s --height SIZE Height of the histogram in lines [default: 20.0]
-p --pch MARKERSHAPE Shape of each bar [default: o]
-x --xlab XLAB Label bins on x-axis [default: None]
-c --colour COLOUR Colour of the plot (Pink, blue, green, red, white, aqua, grey, yellow) [default: white]

Options:
-n --nosummary Hide summary
-h --help Show this screen

Examples:
$ hist test.csv -t "you're the man now dog"
$ hist -f test.csv -t "you're the man now dog"
$ hist --file test.csv -t "you're the man now dog"
$ cat test.csv | hist -t "you're the man now dog"

"""
from docopt import docopt
from bashplotlib.cli.helpers import read_stdin_or_timeout

def parse_args():
"""takes __doc__ for given cmd. Returns parsed args using docopt.
"""
args = docopt(__doc__)
for k, v in args.iteritems():
if v == 'None':
args[k] = None
if args['FILE'] and args['FILE'] != args['--file']:
args['--file'] = args['FILE']
if args['--file'] == 'stdin':
args['--file'] = read_stdin_or_timeout()
if args['--file'] is None:
print __doc__
sys.exit(1)
plot_params = {
'bincount': args['--bins'],
'colour': args['--colour'],
'data': args['--file'],
'height': float(args['--height'].strip()),
'pch': args['--pch'],
'showSummary': (not args['--nosummary']),
'title': args['--title'],
'xlab': args['--xlab']
}
return plot_params
53 changes: 53 additions & 0 deletions bashplotlib/cli/scatter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""scatter

Usage:
scatter ((FILE | -f FILENAME) | (-X XDATA -y YDATA)) [-t TITLE -s SIZE -p MARKERSHAPE -c COLOUR] [-h -H]

Arguments:
FILE Csv with 2 columns for x and y [default: ]
-f --file FILENAME Same as FILE but shorter and less explicit [default: ]
-X --xs-file XDATA Text file with 1 column for the X values [default: ]
-y --ys-file YDATA Text file with 1 column for the y values [default: ]
-t --title TITLE Title for the chart [default: ]
-s --size SIZE Height of the histogram in lines [default: 20.0]
-p --pch MARKERSHAPE Shape of each bar [default: x]
-c --colour COLOUR Colour of the plot (Pink, blue, green, red, white, aqua, grey, yellow) [default: white]
-H --skip-header Skip the first row in FILENAME, XDATA, and YDATA [default: False]

Options:
-h --help Show this screen

Examples:
$ scatter2 -X data/exp.txt -y data/exp.txt

"""
from docopt import docopt
from bashplotlib.cli.helpers import read_stdin_or_timeout

def parse_args():
"""takes __doc__ for given cmd. Returns parsed args using docopt.
"""
args = docopt(__doc__)
for k, v in args.iteritems():
if v == 'None':
args[k] = None
if args['--file'] is None and (args['--xs-file'] is None or args['--ys-file'] is None):
print __doc__
sys.exit(1)
if args['FILE'] is not None or args['--file'] is not None:
if args['FILE'] and args['FILE'] != args['--file']:
args['--file'] = args['FILE']
if args['--file'] == 'stdin':
args['--file'] = read_stdin_or_timeout()
plot_params = {
'filename': args['--file'],
'xs': args['--xs-file'],
'ys': args['--ys-file'],
'size': float(args['--size']),
'pch': args['--pch'],
'colour': args['--colour'],
'title': args['--title'],
}
return {k: v for k,v in plot_params.items() if v is not None and v != ""}
4 changes: 4 additions & 0 deletions bashplotlib/core/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""core/__init__.py
"""
110 changes: 110 additions & 0 deletions bashplotlib/core/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""core/helpers.py
"""
import os
import sys
import collections

bcolours = {
"white": '\033[97m',
"aqua": '\033[96m',
"pink": '\033[95m',
"blue": '\033[94m',
"yellow": '\033[93m',
"green": '\033[92m',
"red": '\033[91m',
"grey": '\033[90m',
"ENDC": '\033[0m'
}

def isiterable(obj):
"""
Return True if you can loop over obj otherwise False
"""
return isinstance(obj, collections.Iterable)

def get_colour(colour):
return bcolours.get(colour, bcolours['white'])

def printcolour(text, sameline=False, colour=get_colour("ENDC")):
"""
Print color text using escape codes
"""
if sameline:
sep = ''
else:
sep = '\n'
sys.stdout.write(get_colour(colour) + text + bcolours["ENDC"] + sep)

printcolor = printcolour

def drange(start, stop, step=1.0):
"generate between 2 numbers w/ optional step"
if step==0:
step = 0.01
r = start
while r < stop:
yield r
r += step

def box_text(text, width, offset=0):
box = " "*offset + "-"*(width+2) + "\n"
box += " "*offset + "|"+ text.center(width) + "|" + "\n"
box += " "*offset + "-"*(width+2)
return box

def try_cast_str_to_number(number_str, verbose=False):
"takes txt and tries to coerce it to float"
try:
return float(number_str.strip())
except Exception, err:
if verbose:
sys.stderr.write(err.message)
sys.stderr.flush()
return None

def read_xy_pairs_from_csv(filename, X=0, y=1, sep=',', header=False):
"""Grab 2 columns from a csv file by name or col index

Arguments:
filename Name of the csv file to read
X Index of the X column in the file [default: 0]
y Index of the y column in the file [default: 0]
sep Delimiter of the file [default: ,]
header Does the file have headers in row #1 [default: False]

"""
with open(filename, 'r') as f:
data = [line.strip() for line in f.readlines()]
data = [line.split(sep) for line in data]
data = [map(str.strip, row) for row in data]

if isinstance(X, int) and isinstance(y, int):
X_idx, y_idx = X, y
elif isinstance(X, basestring) and isinstance(y, basestring) \
and X.strip().isdigit() and y.strip().isdigit():
X_idx = int(try_cast_str_to_number(X))
y_idx = int(try_cast_str_to_number(y))
else:
X_idx, y_idx = None, None
X_y_pairs = []
for i, row in enumerate(data):
if i == 0 and header:
for j, col in enumerate(row):
if col.strip().lower() == X.strip().lower():
X_idx = j
if col.strip().lower() == y.strip().lower():
y_idx = j
if (X_idx is None or y_idx is None):
raise Exception("Column not found.")
try:
row = [try_cast_str_to_number(item) for item in row]
if row[0] and row[1]:
X_y_pairs.append(row)
except Exception, err:
pass
return X_y_pairs



Loading