annotate numerics/plot.py @ 177:c2c86c37eadd

this now works on Mac
author Jeff Hammel <k0scist@gmail.com>
date Thu, 10 Mar 2016 13:05:24 -0800
parents f62ac9a27a1f
children 30d820087ae8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
16
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
1 #!/usr/bin/env python
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
3
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
4 """
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
5 plot data with `matplotlib`
17
5245d7d0c1bf basic usage
Jeff Hammel <k0scist@gmail.com>
parents: 16
diff changeset
6
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
7 See also :
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
8 - http://stackoverflow.com/questions/7534453/matplotlib-does-not-show-my-drawings-although-i-call-pyplot-show ;
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
9 - http://bokeh.pydata.org/ ;
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
10 - http://mpld3.github.io/
119
3602e357d5e7 note to self
Jeff Hammel <k0scist@gmail.com>
parents: 53
diff changeset
11
3602e357d5e7 note to self
Jeff Hammel <k0scist@gmail.com>
parents: 53
diff changeset
12 For bokeh tools...
3602e357d5e7 note to self
Jeff Hammel <k0scist@gmail.com>
parents: 53
diff changeset
13 https://github.com/bokeh/bokeh/blob/master/bokeh/plotting_helpers.py#L277
16
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
14 """
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
15
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
16 # imports
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
17 import argparse
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
18 import csv
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
19 import matplotlib.cm as cm
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
20 import matplotlib.pyplot as plt
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
21 import numpy as np
16
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
22 import os
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
23 import sys
133
8b120c7f0cf9 lets call it a night
Jeff Hammel <k0scist@gmail.com>
parents: 132
diff changeset
24 from .manipulate import ManipulationParser
165
d5f93606f402 minor fixes
Jeff Hammel <k0scist@gmail.com>
parents: 133
diff changeset
25 from StringIO import StringIO
16
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
26
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
27 # module globals
129
79d99216ba17 cleanup and remove image display
Jeff Hammel <k0scist@gmail.com>
parents: 121
diff changeset
28 __all__ = ['Plot', 'PlotParser', 'read', 'main']
16
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
29 string = (str, unicode)
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
30
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
31
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
32 class Plot(object):
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
33 """plotting class"""
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
34 def __init__(self, title=None, xlabel=None, ylabel=None):
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
35 self.title = title
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
36 self.xlabel = xlabel
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
37 self.ylabel = ylabel
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
38 self._x = None
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
39 self._y = []
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
40 self.marker = []
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
41
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
42 def x(self, data, label=None):
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
43 self._x = data
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
44 if label is not None:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
45 self.xlabel = xlabel
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
46
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
47 def y(self, data, label=None, marker='.'):
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
48 self._y.append(data)
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
49 self.marker.append(marker)
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
50 if label is not None:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
51 self.ylabel = label
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
52
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
53 def __call__(self, output):
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
54 assert self._y
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
55
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
56 if self.title:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
57 plt.title(self.title)
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
58 if self.xlabel:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
59 plt.xlabel(self.xlabel)
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
60 if self.ylabel:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
61 plt.ylabel(self.ylabel)
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
62 if self._x:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
63 args = sum([[self._x, self._y[i], self.marker[i]] for i in range(len(self._y))], [])
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
64 plt.plot(*args)
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
65 else:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
66 plt.plot(*self._y)
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
67 plt.show()
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
68 plt.savefig(output)
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
69 print ("{}->saved to '{}'".format(self.title or '', output))
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
70
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
71
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
72 def read(f):
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
73 """
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
74 Read from file ``f``
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
75 Accepts CSV and space-delimited files
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
76 """
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
77
177
c2c86c37eadd this now works on Mac
Jeff Hammel <k0scist@gmail.com>
parents: 169
diff changeset
78 if isinstance(f, string):
c2c86c37eadd this now works on Mac
Jeff Hammel <k0scist@gmail.com>
parents: 169
diff changeset
79 with open(f, 'r') as _f:
c2c86c37eadd this now works on Mac
Jeff Hammel <k0scist@gmail.com>
parents: 169
diff changeset
80 return read(_f)
c2c86c37eadd this now works on Mac
Jeff Hammel <k0scist@gmail.com>
parents: 169
diff changeset
81
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
82 retval = None
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
83 for line in f:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
84 line = line.strip()
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
85 if ',' in line:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
86 buffer = StringIO()
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
87 buffer.write(line)
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
88 buffer.seek(0)
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
89 row = list(csv.reader(buffer))[0]
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
90 else:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
91 row = line.split()
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
92 row = [float(i) for i in row]
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
93 if retval is None:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
94 retval = [[i] for i in row]
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
95 else:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
96 for index, value in enumerate(row):
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
97 retval[index].append(value)
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
98
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
99 return retval
16
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
100
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
101
133
8b120c7f0cf9 lets call it a night
Jeff Hammel <k0scist@gmail.com>
parents: 132
diff changeset
102 class PlotParser(ManipulationParser):
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
103 """CLI option parser for the plotter"""
18
e3fc1f75241d stubbing
Jeff Hammel <k0scist@gmail.com>
parents: 17
diff changeset
104
129
79d99216ba17 cleanup and remove image display
Jeff Hammel <k0scist@gmail.com>
parents: 121
diff changeset
105 types = (float,)
79d99216ba17 cleanup and remove image display
Jeff Hammel <k0scist@gmail.com>
parents: 121
diff changeset
106
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
107 def __init__(self, *args, **kwargs):
16
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
108 kwargs.setdefault('description', __doc__)
133
8b120c7f0cf9 lets call it a night
Jeff Hammel <k0scist@gmail.com>
parents: 132
diff changeset
109 ManipulationParser.__init__(self, *args, **kwargs)
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
110 self.add_argument('-s', '--scatter', dest='scatter',
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
111 action='store_true', default=False,
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
112 help="scatter plot")
16
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
113 self.options = None
133
8b120c7f0cf9 lets call it a night
Jeff Hammel <k0scist@gmail.com>
parents: 132
diff changeset
114 self.set_defaults(output=None)
16
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
115
18
e3fc1f75241d stubbing
Jeff Hammel <k0scist@gmail.com>
parents: 17
diff changeset
116
16
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
117 def main(args=sys.argv[1:]):
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
118 """CLI"""
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
119
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
120 # parse command line
18
e3fc1f75241d stubbing
Jeff Hammel <k0scist@gmail.com>
parents: 17
diff changeset
121 parser = PlotParser()
16
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
122 options = parser.parse_args(args)
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
123
129
79d99216ba17 cleanup and remove image display
Jeff Hammel <k0scist@gmail.com>
parents: 121
diff changeset
124 # choose plotting function
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
125 plot_fcn = plt.scatter if options.scatter else plt.plot
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
126
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
127 # read data
169
f62ac9a27a1f handle sys.stdin case
Jeff Hammel <k0scist@gmail.com>
parents: 165
diff changeset
128 all_data = [read(f) for f in options.input]
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
129
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
130 # color map
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
131 # http://stackoverflow.com/questions/12236566/setting-different-color-for-each-series-in-scatter-plot-on-matplotlib
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
132 n_col = sum([(len(data)-1) or 1 for data in all_data])
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
133 colors = iter(cm.rainbow(np.linspace(0, 1, n_col)))
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
134
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
135 for data in all_data:
129
79d99216ba17 cleanup and remove image display
Jeff Hammel <k0scist@gmail.com>
parents: 121
diff changeset
136 # plot each data set
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
137 if len(data) == 1:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
138 plot_fcn(*data, marker='.', color=next(colors))
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
139 else:
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
140 for i in range(1, len(data)):
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
141 plot_fcn(data[0], data[i], label=str(i), marker='.', color=next(colors))
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
142
121
e259aa9ee18f fix up how this works slightly
Jeff Hammel <k0scist@gmail.com>
parents: 120
diff changeset
143 # save plot
e259aa9ee18f fix up how this works slightly
Jeff Hammel <k0scist@gmail.com>
parents: 120
diff changeset
144 if options.output:
e259aa9ee18f fix up how this works slightly
Jeff Hammel <k0scist@gmail.com>
parents: 120
diff changeset
145 plt.savefig(options.output)
165
d5f93606f402 minor fixes
Jeff Hammel <k0scist@gmail.com>
parents: 133
diff changeset
146 print ("Figure saved to file://{}".format(os.path.abspath(options.output.name)))
53
cd9ec2784077 update plot package
Jeff Hammel <k0scist@gmail.com>
parents: 19
diff changeset
147
121
e259aa9ee18f fix up how this works slightly
Jeff Hammel <k0scist@gmail.com>
parents: 120
diff changeset
148 # display plot, I guess
e259aa9ee18f fix up how this works slightly
Jeff Hammel <k0scist@gmail.com>
parents: 120
diff changeset
149 plt.show()
18
e3fc1f75241d stubbing
Jeff Hammel <k0scist@gmail.com>
parents: 17
diff changeset
150
177
c2c86c37eadd this now works on Mac
Jeff Hammel <k0scist@gmail.com>
parents: 169
diff changeset
151
16
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
152 if __name__ == '__main__':
9e593b26e93b add script to plot data
Jeff Hammel <k0scist@gmail.com>
parents:
diff changeset
153 main()