Skip to content

Instantly share code, notes, and snippets.

@nathants
Last active January 18, 2024 06:47
Show Gist options
  • Save nathants/63aac8e36d5e8289c06637cd139c391e to your computer and use it in GitHub Desktop.
Save nathants/63aac8e36d5e8289c06637cd139c391e to your computer and use it in GitHub Desktop.
>> echo timestamp=2021-10-07T00:38:00Z a=160.2 b=20.8 c=1 | matplot
#!/usr/bin/env python3
# type: ignore
# The MIT License (MIT)
# Copyright (c) 2022-present Nathan Todd-Stone
# https://en.wikipedia.org/wiki/MIT_License#License_terms
import matplotlib as mpl
from matplotlib import pyplot # pip install matplotlib
import argh # pip install argh
import pandas # pip install pandas
import PyQt5 # pip install pyqt5
import sys
import datetime
import os
colors = {
"base03": "#002B36",
"base02": "#073642",
"base01": "#586e75",
"base00": "#657b83",
"base0": "#839496",
"base1": "#93a1a1",
"base2": "#EEE8D5",
"base3": "#FDF6E3",
"yellow": "#B58900",
"orange": "#CB4B16",
"red": "#DC322F",
"magenta": "#D33682",
"violet": "#6C71C4",
"blue": "#268BD2",
"cyan": "#2AA198",
"green": "#859900",
}
line_color = [
colors[x] for x in [
"base00",
"base3",
"yellow",
"red",
"violet",
"cyan",
"green",
]
]
line_style = [
s
for s in [
'-',
'--',
'-.',
':',
'.',
',',
'o',
'v',
'^',
'<',
'>',
'1',
'2',
'3',
'4',
's',
'p',
'*',
'h',
'H',
'+',
'x',
'D',
'd',
'|',
'_',
]
for _ in line_color
]
def solarized():
params = {"ytick.color": colors["base0"],
"xtick.color": colors["base0"],
"text.color": colors["base0"],
"savefig.facecolor": colors["base03"],
"patch.facecolor": colors["blue"],
"patch.edgecolor": colors["base0"],
"grid.color": colors["base0"],
"figure.edgecolor": colors["base03"],
"figure.facecolor": colors["base02"],
"axes.edgecolor": colors["base0"],
"axes.facecolor": colors["base03"],
"axes.labelcolor": colors["base00"]}
mpl.rcParams.update(params)
def to_num(x):
try:
k, v = x.split('=')
except:
print("fatal:", x)
sys.exit(1)
if '.' in v and v.replace('.', '').replace('e+', '').replace('e-', '').replace('-', '').isdigit():
return [k, float(v)]
elif v.replace('-', '').isdigit():
return [k, int(v)]
else:
try:
return [k, datetime.datetime.strptime(v, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=datetime.timezone.utc)]
except ValueError:
try:
return [k, datetime.datetime.strptime(v, "%Y-%m-%d").replace(tzinfo=datetime.timezone.utc)]
except ValueError:
return [k, v]
def main(name='', logy=False, *paths):
"""
visualize sparse timeseries data in an easily readable way.
usage:
>> echo '
timestamp=2021-10-07T00:38:00Z a=160.2 b=20.8 c=1
timestamp=2021-10-07T00:23:00Z a=263.9333333333333 b=17.066666666666666 c=2
timestamp=2021-10-07T00:08:00Z a=360.4 c=4
timestamp=2021-10-06T23:53:00Z a=462.2 b=18.8 c=8
timestamp=2021-10-06T23:38:00Z a=562.1333333333333 b=18.866666666666667 c=16
timestamp=2021-10-06T23:23:00Z b=26.333333333333332 c=32
timestamp=2021-10-06T23:08:00Z a=356.2 b=24.8 c=64
timestamp=2021-10-06T22:53:00Z a=460.1333333333333 b=20.866666666666667 c=128
timestamp=2021-10-06T22:38:00Z a=564.1333333333333 c=256
timestamp=2021-10-06T22:23:00Z a=659.5333333333333 b=21.466666666666665 c=512
' | matplot
"""
solarized()
if paths:
streams = [(os.path.basename(path), open(path)) for path in paths]
else:
streams = [('stdin', sys.stdin)]
dfs = []
columns = set()
for _, stream in streams:
xss = []
for line in stream:
line = line.strip()
if not line:
continue
columns |= {x.split('=')[0] for x in line.split()}
xs = dict([to_num(x) for x in line.split()])
xss.append(xs)
columns = sorted(columns)
columns = sorted(columns, key=lambda x: x != 'timestamp')
df = pandas.DataFrame(xss, columns=columns)
if len(df) and isinstance(df[columns[0]][0], pandas.Timestamp):
df = df.set_index(columns[0])
dfs.append(df)
df = dfs[0]
for extra in dfs[1:]:
df = df.combine_first(extra)
df.plot(title=name, logy=logy, color=line_color, style=line_style)
pyplot.show()
if __name__ == '__main__':
argh.dispatch_command(main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment