1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module for interfacing with Grace (also known as Xmgrace, Xmgr, and ace)."""
24
25
26 from math import ceil, sqrt
27
28
29 import pipe_control
30 from pipe_control import pipes
31 import specific_analyses
32
33
35 """Write the data into the Grace xy-scatter plot.
36
37 The numerical data should be supplied as a 4 dimensional list or array object. The first dimension corresponds to the graphs, Gx. The second corresponds the sets of each graph, Sx. The third corresponds to the data series (i.e. each data point). The forth is a list of the information about each point, it is a list where the first element is the x value, the second is the y value, the third is the optional dx or dy error (either dx or dy dependent upon the graph_type arg), and the forth is the optional dy error when graph_type is xydxdy (the third position is then dx).
38
39
40 @param data: The 4D structure of numerical data to graph (see docstring).
41 @type data: list of lists of lists of float
42 @keyword file: The file object to write the data to.
43 @type file: file object
44 @keyword graph_type: The graph type which can be one of xy, xydy, xydx, or xydxdy.
45 @type graph_type: str
46 @keyword norm: The normalisation flag which if set to True will cause all graphs to be normalised to 1. The first dimension is the graph.
47 @type norm: None or list of bool
48 """
49
50
51 graph_num = len(data)
52
53
54 if not norm:
55 norm = []
56 for gi in range(graph_num):
57 norm.append(False)
58
59
60 comment_col = 2
61 if graph_type in ['xydx', 'xydy']:
62 comment_col = 3
63 elif graph_type == 'xydxdy':
64 comment_col = 4
65
66
67 for gi in range(graph_num):
68
69 for si in range(len(data[gi])):
70
71 file.write("@target G%s.S%s\n" % (gi, si))
72 file.write("@type %s\n" % graph_type)
73
74
75 norm_fact = 1.0
76 if norm[gi]:
77 norm_fact = data[gi][si][0][1]
78
79
80 for point in data[gi][si]:
81
82 if point[0] == None or point[1] == None:
83 continue
84
85
86 file.write("%-30s %-30.15f" % (point[0], point[1]/norm_fact))
87
88
89 if graph_type in ['xydx', 'xydy', 'xydxdy']:
90
91 error = point[2]
92 if error == None:
93 error = 0.0
94
95
96 file.write(" %-30.15f" % (error/norm_fact))
97
98
99 if graph_type == 'xydxdy':
100
101 error = point[3]
102 if error == None:
103 error = 0.0
104
105
106 file.write(" %-30.15f" % (error/norm_fact))
107
108
109 try:
110 file.write("%30s \"# %s\"" % ('', point[comment_col]))
111 except IndexError:
112 pass
113
114
115 file.write("\n")
116
117
118 file.write("&\n")
119
120
121 for i in range(graph_num):
122 file.write("@with g%i\n" % i)
123 file.write("@autoscale\n")
124
125
126 if len(data) > 1:
127 row_num = int(round(sqrt(len(data))))
128 col_num = int(ceil(sqrt(len(data))))
129 file.write("@arrange(%i, %i, .1, .1, .1, OFF, OFF, OFF)\n" % (row_num, col_num))
130
131
133 """Write the grace header for xy-scatter plots.
134
135 Many of these keyword arguments should be supplied in a [X, Y] list format, where the first element corresponds to the X data, and the second the Y data. Defaults will be used for any non-supplied args (or lists with elements set to None).
136
137
138 @keyword file: The file object to write the data to.
139 @type file: file object
140 @keyword paper_size: The paper size, i.e. 'A4'. If set to None, this will default to letter size.
141 @type paper_size: str
142 @keyword title: The title of the graph.
143 @type title: None or str
144 @keyword subtitle: The sub-title of the graph.
145 @type subtitle: None or str
146 @keyword view: List of 4 coordinates defining the graph view port.
147 @type view: None or list of float
148 @keyword graph_num: The total number of graphs.
149 @type graph_num: int
150 @keyword sets: The number of data sets in each graph.
151 @type sets: list of int
152 @keyword set_names: The names associated with each graph data set Gx.Sy. For example this can be a list of spin identification strings. The first dimension is the graph, the second is the set.
153 @type set_names: None or list of list of str
154 @keyword set_colours: The colours for each graph data set Gx.Sy. The first dimension is the graph, the second is the set.
155 @type set_colours: None or list of list of int
156 @keyword x_axis_type_zero: The flags specifying if the X-axis should be placed at zero.
157 @type x_axis_type_zero: None or list of lists of bool
158 @keyword y_axis_type_zero: The flags specifying if the Y-axis should be placed at zero.
159 @type y_axis_type_zero: None or list of lists of bool
160 @keyword symbols: The symbol style for each graph data set Gx.Sy. The first dimension is the graph, the second is the set.
161 @type symbols: None or list of list of int
162 @keyword symbol_sizes: The symbol size for each graph data set Gx.Sy. The first dimension is the graph, the second is the set.
163 @type symbol_sizes: None or list of list of int
164 @keyword symbol_fill: The symbol file style for each graph data set Gx.Sy. The first dimension is the graph, the second is the set.
165 @type symbol_fill: None or list of list of int
166 @keyword linestyle: The line style for each graph data set Gx.Sy. The first dimension is the graph, the second is the set.
167 @type linestyle: None or list of list of int
168 @keyword linetype: The line type for each graph data set Gx.Sy. The first dimension is the graph, the second is the set.
169 @type linetype: None or list of list of int
170 @keyword linewidth: The line width for all elements of each graph data set Gx.Sy. The first dimension is the graph, the second is the set.
171 @type linewidth: None or list of float
172 @keyword data_type: The axis data category (in the [X, Y] list format).
173 @type data_type: None or list of list of str
174 @keyword seq_type: The sequence data type (in the [X, Y] list format). This is for molecular sequence specific data and can be one of 'res', 'spin', or 'mixed'.
175 @type seq_type: None or list of list of str
176 @keyword axis_labels: The labels for the axes (in the [X, Y] list format). The first dimension is the graph.
177 @type axis_labels: None or list of list of str
178 @keyword legend_pos: The position of the legend, e.g. [0.3, 0.8]. The first dimension is the graph.
179 @type legend_pos: None or list of list of float
180 @keyword legend: If True, the legend will be visible. The first dimension is the graph.
181 @type legend: list of bool
182 @keyword norm: The normalisation flag which if set to True will cause all graphs to be normalised to 1. The first dimension is the graph.
183 @type norm: list of bool
184 """
185
186
187 if sets == None:
188 sets = []
189 for gi in range(graph_num):
190 sets.append(1)
191 if x_axis_type_zero == None:
192 x_axis_type_zero = []
193 for gi in range(graph_num):
194 x_axis_type_zero.append(False)
195 if y_axis_type_zero == None:
196 y_axis_type_zero = []
197 for gi in range(graph_num):
198 y_axis_type_zero.append(False)
199 if linewidth == None:
200 linewidth = []
201 for gi in range(graph_num):
202 linewidth.append(0.5)
203 if norm == None:
204 norm = []
205 for gi in range(graph_num):
206 norm.append(False)
207
208
209 if not data_type:
210 data_type = [None, None]
211 if not seq_type:
212 seq_type = [None, None]
213 if not axis_labels:
214 axis_labels = []
215 for gi in range(graph_num):
216 axis_labels.append([None, None])
217
218
219 file.write("@version 50121\n")
220
221
222 if paper_size == 'A4':
223 file.write("@page size 842, 595\n")
224
225
226 for gi in range(graph_num):
227
228 file.write("@with g%i\n" % gi)
229
230
231 if not view:
232 view = [0.15, 0.15, 1.28, 0.85]
233 file.write("@ view %s, %s, %s, %s\n" % (view[0], view[1], view[2], view[3]))
234
235
236 if title:
237 file.write("@ title \"%s\"\n" % title)
238 if subtitle:
239 file.write("@ subtitle \"%s\"\n" % subtitle)
240
241
242 if x_axis_type_zero[gi]:
243 file.write("@ xaxis type zero true\n")
244 if y_axis_type_zero[gi]:
245 file.write("@ yaxis type zero true\n")
246
247
248 axes = ['x', 'y']
249 for i in range(2):
250
251 analysis_spec = False
252 if pipes.cdp_name():
253
254 analysis_spec = True
255
256
257 return_units = specific_analyses.setup.get_specific_fn('return_units', pipes.get_type())
258 return_grace_string = specific_analyses.setup.get_specific_fn('return_grace_string', pipes.get_type())
259
260
261 if data_type[i] and data_type[i] != 'spin' and pipe_control.minimise.return_data_name(data_type[i]):
262 return_units = pipe_control.minimise.return_units
263 return_grace_string = pipe_control.minimise.return_grace_string
264
265
266 if data_type[i] == 'spin':
267
268 if seq_type[i] == 'res':
269
270 if not axis_labels[gi][i]:
271 axis_labels[gi][i] = "Residue number"
272
273
274 if seq_type[i] == 'spin':
275
276 if not axis_labels[gi][i]:
277 axis_labels[gi][i] = "Spin number"
278
279
280 if seq_type[i] == 'mixed':
281
282 if not axis_labels[gi][i]:
283 axis_labels[gi][i] = "Spin identification string"
284
285
286 else:
287
288 if analysis_spec and (not axis_labels or not axis_labels[gi][i]):
289
290 units = return_units(data_type[i])
291
292
293 axis_labels[gi][i] = return_grace_string(data_type[i])
294
295
296 if units:
297 axis_labels[gi][i] = axis_labels[gi][i] + "\\N (" + units + ")"
298
299
300 if norm and norm[gi] and axes[i] == 'y':
301 axis_labels[gi][i] = axis_labels[gi][i] + " \\N\\q(normalised)\\Q"
302
303
304 if axis_labels[gi][i]:
305 file.write("@ %saxis label \"%s\"\n" % (axes[i], axis_labels[gi][i]))
306 file.write("@ %saxis label char size 1.00\n" % axes[i])
307 file.write("@ %saxis tick major size 0.50\n" % axes[i])
308 file.write("@ %saxis tick major linewidth %s\n" % (axes[i], linewidth[gi]))
309 file.write("@ %saxis tick minor linewidth %s\n" % (axes[i], linewidth[gi]))
310 file.write("@ %saxis tick minor size 0.25\n" % axes[i])
311 file.write("@ %saxis ticklabel char size 0.70\n" % axes[i])
312
313
314 if legend != None and legend[gi]:
315 file.write("@ legend on\n")
316 else:
317 file.write("@ legend off\n")
318 if legend_pos != None:
319 file.write("@ legend %s, %s\n" % (legend_pos[gi][0], legend_pos[gi][1]))
320
321
322 file.write("@ frame linewidth %s\n" % linewidth[gi])
323
324
325 for i in range(sets[gi]):
326
327 if symbols:
328 file.write("@ s%i symbol %i\n" % (i, symbols[gi][i]))
329 else:
330
331 num = i % 10 + 1
332
333
334 file.write("@ s%i symbol %i\n" % (i, num))
335
336
337 if symbol_sizes:
338 file.write("@ s%i symbol size %s\n" % (i, symbol_sizes[gi][i]))
339 else:
340 file.write("@ s%i symbol size 0.45\n" % i)
341
342
343 if symbol_fill:
344 file.write("@ s%i symbol fill pattern %i\n" % (i, symbol_fill[gi][i]))
345
346
347 file.write("@ s%i symbol linewidth %s\n" % (i, linewidth[gi]))
348
349
350 if set_colours:
351 file.write("@ s%i symbol color %s\n" % (i, set_colours[gi][i]))
352 file.write("@ s%i symbol fill color %s\n" % (i, set_colours[gi][i]))
353
354
355 file.write("@ s%i errorbar size 0.5\n" % i)
356 file.write("@ s%i errorbar linewidth %s\n" % (i, linewidth[gi]))
357 file.write("@ s%i errorbar riser linewidth %s\n" % (i, linewidth[gi]))
358
359
360 if linestyle:
361 file.write("@ s%i line linestyle %s\n" % (i, linestyle[gi][i]))
362
363
364 if linetype:
365 file.write("@ s%i line type %s\n" % (i, linetype[gi][i]))
366
367
368 if set_colours:
369 file.write("@ s%i line color %s\n" % (i, set_colours[gi][i]))
370 file.write("@ s%i fill color %s\n" % (i, set_colours[gi][i]))
371 file.write("@ s%i avalue color %s\n" % (i, set_colours[gi][i]))
372 file.write("@ s%i errorbar color %s\n" % (i, set_colours[gi][i]))
373
374
375 if set_names and len(set_names) and len(set_names[gi]) and set_names[gi][i]:
376 file.write("@ s%i legend \"%s\"\n" % (i, set_names[gi][i]))
377