Skip to content

Instantly share code, notes, and snippets.

@jtrussell
Last active October 15, 2017 20:43
Show Gist options
  • Save jtrussell/d7869b38b95a0886e5ef55fbe0c078af to your computer and use it in GitHub Desktop.
Save jtrussell/d7869b38b95a0886e5ef55fbe0c078af to your computer and use it in GitHub Desktop.
A little script for plotting things using YAML front matter for cofiguration
#@echo off & python -x %~f0 %* & goto :eof
##!/bin/python
# Meant to be used as executable, i.e. place this file somewhere in your path
# and uncomment the first line as necessary.
#
# Data file are expected to be formatted as:
#
# x_0,y1_0,y2_0,...,yN_0
# ...
# x_m,y1_m,y2_m,...,yN_m
#
# Any option can be overridden with YAML front matter. See the example file
# below.
#
# Note, including an `iamge_format` will cause your figure to be saved to disk
# rather than shown.
import matplotlib.pyplot as plt
import os
import sys
import yaml
args = sys.argv[1:]
cwd = os.getcwd()
if len(args) is not 1:
print('Expected a single parameter, a data file to plot.')
sys.exit(0)
# Can all be overidden with YAML front matter
opts = {
'title': 'My Chart',
'legend_loc': 'best',
'x_label': 'Domain',
'y_label': 'Range',
'show_grid': True,
'sep': ',',
'x_lim': False,
'y_lim': False,
'image_format': False,
'series_labels': [
'Blue Stars',
'Green Circles',
'Red Triagles',
'Cyan Diamonds'
],
'plot_fn': 'plot',
# Line chart stuff - plot_fn: plot
'series_formats': ['b-*', 'g-o', 'r-^', 'c-D'],
# Bar chart stuff - plot_fn: bar
'colors': ['blue', 'green', 'red', 'cyan']
}
data_file_path = os.path.join(cwd, args[0])
with open(data_file_path) as data_file:
# Check for yaml front matter
lines = data_file.readlines()
ix = 0
# Merge defaults opts with YAML front matter
if lines[ix].strip() == '---':
yaml_lines = [lines[ix]]
ix = 1
while lines[ix].strip() != '---':
yaml_lines.append(lines[ix])
ix = ix + 1
ix = ix + 1
opts = { **opts, **yaml.load('\n'.join(yaml_lines)) }
# Process data opts
data_lines = lines[ix:]
data_rows = [line.split(opts['sep']) for line in data_lines]
num_series = len(data_rows[0]) - 1
data_rows = [row for row in data_rows if len(row) == num_series + 1]
plt.figure()
if opts['title']:
plt.title(opts['title'])
if opts['x_label']:
plt.xlabel(opts['x_label'])
if opts['y_label']:
plt.ylabel(opts['y_label'])
if opts['x_lim']:
plt.xlim(opts['x_lim'][0], opts['x_lim'][1])
if opts['y_lim']:
plt.ylim(opts['y_lim'][0], opts['y_lim'][1])
if opts['show_grid']:
plt.grid()
x_domain = [row[0] for row in data_rows]
for ix_series in range(1, num_series + 1):
y_range = [row[ix_series].strip() for row in data_rows]
if opts['plot_fn'] == 'bar':
ind = [x for x in range(len(x_domain))]
for ix in ind:
y_val = y_range[ix]
y_val = float(y_val) if '.' in y_val else int(y_val)
plt.bar(ind[ix], y_val, label=y_val, color=opts['colors'][ix])
plt.xticks(ind, x_domain)
else:
# Default plot_fn is `plot`
y_format = opts['series_formats'][ix_series - 1]
series_label = opts['series_labels'][ix_series - 1]
plt.plot(x_domain, y_range, y_format, label=series_label)
if opts['legend_loc']:
plt.legend(loc=opts['legend_loc'])
if opts['image_format']:
image_file_name, _ = os.path.splitext(os.path.basename(data_file_path))
image_file_path = os.path.join(cwd, image_file_name + '.' + opts['image_format'])
plt.savefig(image_file_path)
else:
plt.show()
# vi:syntax=python
---
title: Test
x_label: Foobar
series_labels:
- Thing 1
- Thing 2
---
1,3,4
2,4,1
3,2,7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment