source: misc/tools/plotcsv/plotcsv.py @ 6338

Last change on this file since 6338 was 6338, checked in by rwilson, 15 years ago

Initial try at plotcsv version 2.

File size: 5.2 KB
Line 
1#!/usr/bin/env python
2
3'''A module to draw a graph on the screen given a data file.
4
5The code is written such that it may be run as a program or imported
6and used as a module.
7'''
8
9import sys
10import os.path
11import types
12import csv
13import time
14import getopt
15import pylab
16
17
18# Flag strings - keys in the 'options' dictionary
19X_DATACOL = 'x_datacol'
20Y_DATACOL = 'y_datacol'
21X_RANGE = 'x_range'
22Y_RANGE = 'y_range'
23FILENAME = 'filename'
24SIZE = 'size'
25TITLE = 'title'
26X_LABEL = 'x_label'
27Y_LABEL = 'y_label'
28
29
30##
31# @brief Issue an error message.
32# @param msg The message.
33def error(msg):
34    print >>sys.stderr, msg
35    sys.exit(10)
36
37 
38##
39# @brief Plot a sequence of data.
40# @param x_data The X data sequence to plot.
41# @param y_data A list of one or more Y data sequences to plot.
42# @param options A dictionary of plot options.
43def plot_data(x_data, y_data, options):
44    pylab.plot(x_data, y_data)
45    pylab.title(options.get(TITLE, ''))
46    pylab.grid(True)
47
48    # if user request a particular Y range
49    if not options[Y_RANGE] is None:
50        try:
51            (minimum, maximum) = options[Y_RANGE].split(',')
52            minimum = float(minimum)
53            maximum = float(maximum)
54        except:
55            error('Sorry, got a bad value for Y range: %s' % options[Y_RANGE])
56        pylab.ylim(ymin=minimum, ymax=maximum)
57
58    pylab.xlabel(options.get(X_LABEL, ''))
59    pylab.ylabel(options.get(Y_LABEL, ''))
60
61    pylab.show()
62
63
64##
65# @brief Plot a data file.
66# @param filename Path to the data file to plot.
67# @param options A dictionary of options.
68def plot_file(filename, options=None):
69    # set options defaults
70    opts = options
71    if opts is None:
72        opts = {}
73
74    opts[X_DATACOL] = opts.get(X_DATACOL, '0')
75    opts[Y_DATACOL] = opts.get(Y_DATACOL, '1')
76    opts[SIZE] = opts.get(SIZE, '800,600')
77    opts[Y_RANGE] = opts.get(Y_RANGE, None)
78
79    # get contents of data file
80    # after this, 'header' is list of column header strings
81    #             'data' is a list of lists of data
82    fd = open(filename)
83    c = csv.reader(fd)
84    data = []
85    for row in c:
86        data.append(row)
87    fd.close()
88    header = data[0]
89    del data[0]
90
91    # convert column specifiers to 'int' if required
92    try:
93        index = int(opts[X_DATACOL])
94    except:
95        try:
96            index = header.index(opts[X_DATACOL])
97        except ValueError:
98            error("Sorry, X column header '%s' isn't in the data file." % opts[X_DATACOL])
99    opts[X_DATACOL] = index
100
101    try:
102        index = int(opts[Y_DATACOL])
103    except:
104        try:
105            index = header.index(opts[Y_DATACOL])
106        except ValueError:
107            error("Sorry, Y column header '%s' isn't in the data file." % opts[Y_DATACOL])
108    opts[Y_DATACOL] = index
109   
110    # extract required columns from the data
111    x_col = opts[X_DATACOL]
112    y_col = opts[Y_DATACOL]
113
114    # get max column number, check requested columns
115    max_col = len(header)
116    if x_col >= max_col or y_col >= max_col:
117        error('Sorry, maximum column number for that file is %d.' % (max_col-1))
118
119    x_label = header[x_col].title()
120    x_data = map(lambda x: x[x_col], data)
121    if x_label == 'Time':
122        x_label = 'Time (hours)'
123        x_data = map(lambda x: float(x)/3600., x_data)
124    y_data = map(lambda x: x[y_col], data)
125    y_label = header[y_col].title()
126
127    opts[TITLE] = 'File: %s' % filename
128    opts[X_LABEL] = x_label
129    opts[Y_LABEL] = y_label
130
131    plot_data(x_data, y_data, opts)
132
133
134##
135# @brief Help for the befuddled user.
136def usage():
137    print 'usage: %s <options> <filename>' % (ProgName)
138    print 'where <filename> is the path to the data file to plot'
139    print '  and <options>  is zero or more of:'
140    print '                   -x <datacol> where <datacol> is a column specifier,'
141    print '                   -y <datacol>     either a number or a header string'
142    print '                   -v <range>   force a range in Y axis values, of the form'
143    print '                                    <min>,<max>, eq, "-5,10"'
144    print '                   -s <min,max> sets PNG output picture size'
145    sys.exit(10)
146
147if __name__ == '__main__':
148    # dictionary to convert option string to internal name
149    of_dict = { '-x': X_DATACOL,
150                '-y': Y_DATACOL,
151                '-s': SIZE,
152                '-v': Y_RANGE }
153
154    # set name of the program (for error reporting)
155    global ProgName
156    try:
157        ProgName = os.path.basename(sys.argv[0])
158    except:
159        pass
160
161    # get options
162    opt_dict = {}
163    params = sys.argv[1:]
164    (opts, args) = getopt.gnu_getopt(params, 'x:y:s:v:')
165    if len(args) != 1:
166        usage()
167    for (o, v) in opts:
168        try:
169            opt_dict[of_dict[o]] = v.lower()
170        except:
171            usage()
172
173    # get name of data file
174    if len(args) != 1:
175        usage()
176    filename = args[0]
177    (filename_minus, _) = filename.split('.', 1)
178
179    # set default option values
180    opt_dict[X_DATACOL] = opt_dict.get(X_DATACOL, 0)
181    opt_dict[Y_DATACOL] = opt_dict.get(Y_DATACOL, 1)
182    opt_dict[SIZE] = opt_dict.get(SIZE, '800,600')
183#    opt_dict[X_RANGE] = opt_dict.get(X_RANGE, None)
184    opt_dict[Y_RANGE] = opt_dict.get(Y_RANGE, None)
185    opt_dict[FILENAME] = filename_minus
186
187    # plot the file
188    plot_file(args[0], opt_dict)
Note: See TracBrowser for help on using the repository browser.