-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuti_plot.py
186 lines (147 loc) · 7.74 KB
/
uti_plot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
"""Simple 1D & 2D plotting utilities package for "Synchrotron Radiation Workshop" (SRW).
``uti_plot`` currenly wraps ``matplotlib``, but other backends are
planned. If no suitable backend is available, ``uti_plot_init`` sets
the backend to ``uti_plot_none`` so that the calling program is still
functional. This is useful for systems where there is no graphing
library available, but you still want to see the results of the
SRW program.
Usage:
import uti_plot as up
up.uti_plot_init()
uti_plot1d(...)
uti_plot_show()
Modules:
uti_plot
This module, which loads all other modules dynamically
uti_plot_matplotlib
Does the actually plotting using matplotlib.pyplot. Currently, loaded in all cases except
when ``backend`` is ``None``
test_uti_plot
Simple tests for uti_plot
.. moduleauthor:: Rob Nagler <nagler@radiasoft.net>
"""
import sys
import uti_plot_com
import traceback
_backend = None
DEFAULT_BACKEND = '<default>'
def uti_plot_init(backend=DEFAULT_BACKEND, fname_format=None):
"""Initializes plotting engine with backend and, optionally, save plots to fname_format
Tries to initialize `backend` as the plotting engine. If not found, an
error will be printed, and this module's functions will be no-ops. If
DEFAULT_BACKEND provided, an appropriate backend will be chosen and printed.
Plots may also be saved if fname_format is supplied.
You may call ``uti_plot_init(None)`` expicitly so that no plotting occurs.
:param str backend: a matplot backend (TkAgg, etc.) or ``inline`` in IPython
:param str fname_format: where to save plots. format field is a sequential plot number, starting at 0.
"""
global _backend
if backend is not None:
try:
import uti_plot_matplotlib
_backend = uti_plot_matplotlib.Backend(backend, fname_format)
return
except:
traceback.print_exc()
print(backend + ': unable to import specified backend (or its dependency); no plots')
elif fname_format is not None:
raise Value(fname_format + ': fname_format must be null if backend is None')
_backend = _BackendNone()
def uti_plot_show():
"""Display the plots"""
#if '_backend' not in locals(): uti_plot_init() #?
_backend.uti_plot_show()
def uti_plot1d(ar1d, x_range, labels=('energy [eV]', 'ph/s/0.1%bw'), units=None):
"""Generate one-dimensional line plot from given array
:param array ar1d: data points
:param list x_range: Passed to numpy.linspace(start sequence, stop sequnce, num samples)
:param tuple labels: [x-axis, y-axis]
"""
#if '_backend' not in locals(): uti_plot_init() #?
if(units != None):
x_range, x_unit = uti_plot_com.rescale_dim(x_range, units[0])
units = [x_unit, units[1]]
strTitle = '' if(len(labels) < 3) else labels[2]
labels = (labels[0] + ' [' + units[0] + ']', labels[1] + ' [' + units[1] + ']', strTitle)
#print('*****In uti_plot1d')
_backend.uti_plot1d(ar1d, x_range, labels)
def uti_plot2d(ar2d, x_range, y_range, labels=('Horizontal Position [m]','Vertical Position [m]'), units=None):
"""Generate quad mesh plot from given "flattened" array
:param array ar2d: data points
:param list x_range: Passed to numpy.linspace(start sequence, stop sequnce, num samples)
:param list y_range: y axis (same structure as x_range)
:param tuple labels: [x-axis, y-axis]
"""
#if '_backend' not in locals(): uti_plot_init() #?
if(units != None):
x_range, x_unit = uti_plot_com.rescale_dim(x_range, units[0])
y_range, y_unit = uti_plot_com.rescale_dim(y_range, units[1])
units = [x_unit, y_unit, units[2]]
strTitle = '' if(len(labels) < 3) else labels[2]
labels = (labels[0] + ' [' + units[0]+ ']', labels[1] + ' [' + units[1] + ']', strTitle)
_backend.uti_plot2d(ar2d, x_range, y_range, labels)
def uti_plot2d1d(ar2d, x_range, y_range, x=0, y=0, labels=('Horizontal Position', 'Vertical Position', 'Intensity'), units=None, graphs_joined=True):
"""Generate 2d quad mesh plot from given "flattened" array, and 1d cuts passing through (x, y)
:param array ar2d: data points
:param list x_range: Passed to numpy.linspace(start sequence, stop sequnce, num samples)
:param list y_range: y axis (same structure as x_range)
:param x: x value for 1d cut
:param y: y value for 1d cut
:param tuple labels: [x-axis, y-axis, z-axis]
:param tuple units: [x-axis, y-axis, z-axis]
:param graphs_joined: switch specifying whether the 2d plot and 1d cuts have to be displayed in one panel or separately
"""
#if '_backend' not in locals(): uti_plot_init() #?
if(units != None): #checking / re-scaling x, y
x_range, x_unit = uti_plot_com.rescale_dim(x_range, units[0])
y_range, y_unit = uti_plot_com.rescale_dim(y_range, units[1])
units = [x_unit, y_unit, units[2]]
strTitle = labels[2]
label2D = (labels[0] + ' [' + units[0]+ ']', labels[1] + ' [' + units[1] + ']', strTitle)
strTitle = 'At ' + labels[1] + ': ' + str(y)
if y != 0: strTitle += ' ' + units[1]
label1X = (labels[0] + ' [' + units[0] + ']', labels[2] + ' [' + units[2] + ']', strTitle)
strTitle = 'At ' + labels[0] + ': ' + str(x)
if x != 0: strTitle += ' ' + units[0]
label1Y = (labels[1] + ' [' + units[1] + ']', labels[2] + ' [' + units[2] + ']', strTitle)
else: #OC081115
strTitle = labels[2]
label2D = (labels[0], labels[1], strTitle)
strTitle = 'At ' + labels[1] + ': ' + str(y)
label1X = (labels[0], labels[2], strTitle)
strTitle = 'At ' + labels[0] + ': ' + str(x)
label1Y = (labels[1], labels[2], strTitle)
labels = [label2D, label1X, label1Y]
_backend.uti_plot2d1d(ar2d, x_range, y_range, x, y, labels, graphs_joined)
#def uti_data_file_plot(_fname, _read_labels=1, _e=0, _x=0, _y=0, _graphs_joined=True):
#def uti_data_file_plot(_fname, _read_labels=1, _e=0, _x=0, _y=0, _graphs_joined=True, _traj_report=False, _traj_axis='x'): #MR29072016
def uti_data_file_plot(_fname, _read_labels=1, _e=0, _x=0, _y=0, _graphs_joined=True, _traj_report=False, _traj_axis='x', _scale='linear', _width_pixels=None): #MR20012017
"""Generate plot from configuration in _fname
:param str _fname: config loaded from here
:param bool _read_labels: whether to read labels from _fname
:param float _e: photon energy adjustment
:param float _x: horizonal position adjustment
:param float _y: vertical position adjustment
:param bool _graphs_joined: if true, all plots in a single figure
:param bool _traj_report: if true, plot trajectory report data
:param str _traj_axis: the axis to plot vs. z-axis
:param str _scale: the scale to use for plotting data (linear by default, but could use log, log2, log10)
:param int _width_pixels: the width of the final plot in pixels
"""
#if '_backend' not in locals(): uti_plot_init() #?
#_backend.uti_data_file_plot(_fname, _read_labels, _e, _x, _y, _graphs_joined)
#_backend.uti_data_file_plot(_fname, _read_labels, _e, _x, _y, _graphs_joined, _traj_report, _traj_axis) #MR29072016
_backend.uti_data_file_plot(_fname, _read_labels, _e, _x, _y, _graphs_joined, _traj_report, _traj_axis, _scale, _width_pixels) #MR20012017
class _BackendBase(object):
def __getattr__(self, attr):
return self._backend_call
class _BackendMissing(_BackendBase):
def _backend_call(self, *args, **kwargs):
uti_plot_init()
method_name = sys._getframe(1).f_code.co_name
func = getattr(_backend, method_name)
return func(*args)
class _BackendNone(_BackendBase):
def _backend_call(*args, **kwargs):
pass
_backend = _BackendMissing()