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