Package generic_fns :: Module grace
[hide private]
[frames] | no frames]

Source Code for Module generic_fns.grace

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2003-2012 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax.                                     # 
  6  #                                                                             # 
  7  # relax is free software; you can redistribute it and/or modify               # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation; either version 2 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # relax is distributed in the hope that it will be useful,                    # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with relax; if not, write to the Free Software                        # 
 19  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   # 
 20  #                                                                             # 
 21  ############################################################################### 
 22   
 23  # Module docstring. 
 24  """Module for interfacing with Grace (also known as Xmgrace, Xmgr, and ace).""" 
 25   
 26  # Python module imports. 
 27  from numpy import array, ndarray 
 28  from os import system 
 29  from warnings import warn 
 30   
 31  # relax module imports. 
 32  import generic_fns 
 33  from generic_fns.mol_res_spin import count_molecules, count_residues, count_spins, exists_mol_res_spin_data, generate_spin_id, spin_loop 
 34  from generic_fns import pipes 
 35  from relax_errors import RelaxError, RelaxNoSequenceError, RelaxNoSimError 
 36  from relax_io import get_file_path, open_write_file, test_binary 
 37  from relax_warnings import RelaxWarning 
 38  import specific_fns 
 39  from status import Status; status = Status() 
 40   
 41   
42 -def determine_seq_type(spin_id=None):
43 """Determine the spin sequence data type. 44 45 The purpose is to identify systems whereby only spins or only residues exist. 46 47 @keyword spin_id: The spin identification string. 48 @type spin_id: str 49 @return: The spin sequence data type. This can be one of 'spin', 'res,' or 'mixed'. 50 @rtype: str 51 """ 52 53 # Count the molecules, residues, and spins. 54 num_mol = count_molecules(spin_id) 55 num_res = count_residues(spin_id) 56 num_spin = count_spins(spin_id) 57 58 # Only residues. 59 if num_mol == 1 and num_spin == 1: 60 return 'res' 61 62 # Only spins. 63 if num_mol == 1 and num_res == 1: 64 return 'spin' 65 66 # Mixed. 67 return 'mixed'
68 69
70 -def get_data(spin_id=None, x_data_type=None, y_data_type=None, plot_data=None):
71 """Return all the xy data, along with the graph type and names for the graph sets. 72 73 @keyword spin_id: The spin identification string. 74 @type spin_id: str 75 @keyword x_data_type: The category of the X-axis data. 76 @type x_data_type: str 77 @keyword y_data_type: The category of the Y-axis data. 78 @type y_data_type: str 79 @keyword plot_data: The type of the plotted data, one of 'value', 'error', or 'sim'. 80 @type plot_data: str 81 @return: The 4D graph numerical data structure, the graph type (i.e. on of 'xy', 'xydy', or 'xydxdy'), and the labels for the graph sets. 82 @rtype: list of lists of lists of float, str, and list of str 83 """ 84 85 # Initialise the 4D data structure (Gx, Sx, data point, data point info), and graph set labels. 86 data = [[]] 87 set_labels = [] 88 x_err_flag = False 89 y_err_flag = False 90 data_list = False 91 data_dict = False 92 93 # Specific x and y value returning functions. 94 x_return_value = y_return_value = specific_fns.setup.get_specific_fn('return_value', pipes.get_type()) 95 x_return_conversion_factor = y_return_conversion_factor = specific_fns.setup.get_specific_fn('return_conversion_factor', pipes.get_type()) 96 97 # Test if the X-axis data type is a minimisation statistic. 98 if x_data_type != 'spin' and generic_fns.minimise.return_data_name(x_data_type): 99 x_return_value = generic_fns.minimise.return_value 100 x_return_conversion_factor = generic_fns.minimise.return_conversion_factor 101 102 # Test if the Y-axis data type is a minimisation statistic. 103 if y_data_type != 'spin' and generic_fns.minimise.return_data_name(y_data_type): 104 y_return_value = generic_fns.minimise.return_value 105 y_return_conversion_factor = generic_fns.minimise.return_conversion_factor 106 107 # Number of graph sets. 108 if plot_data == 'sim': 109 sets = cdp.sim_number 110 else: 111 sets = 1 112 113 # Loop over the data points. 114 for i in range(sets): 115 # The graph label. 116 set_label = '' 117 if plot_data == 'sim': 118 set_label = "Sim: %i" % i 119 120 # The sim number. 121 sim = None 122 if plot_data == 'sim': 123 sim = i 124 125 # Spin names list (for creating new graph sets). 126 spin_names = [] 127 128 # Loop over the spins. 129 for spin, mol_name, res_num, res_name, id in spin_loop(full_info=True, selection=spin_id, return_id=True): 130 # Skip deselected spins. 131 if not spin.select: 132 continue 133 134 # The X data (plotted as residue numbers). 135 if x_data_type == 'spin': 136 x_val = res_num 137 x_err = None 138 139 # The X data (plotted as values). 140 else: 141 # Append the x-axis values and errors. 142 x_val, x_err = x_return_value(spin, x_data_type, sim=sim) 143 144 # The Y data (plotted as residue numbers). 145 if y_data_type == 'spin': 146 y_val = res_num 147 y_err = None 148 149 # The Y data (plotted as values). 150 else: 151 # Append the y-axis values and errors. 152 y_val, y_err = y_return_value(spin, y_data_type, sim=sim) 153 154 # Go to the next spin if there is missing xy data. 155 if x_val == None or y_val == None: 156 continue 157 158 # One set per spin (list data has been returned). 159 if data_list or isinstance(x_val, list): 160 # Append a new set structure and set the name to the spin ID. 161 data[0].append([]) 162 set_labels.append("Spin %s" % id) 163 164 # The set index. 165 index = len(data[0]) - 1 166 167 # No errors. 168 if x_err == None: 169 x_err = [None]*len(x_val) 170 if y_err == None: 171 y_err = [None]*len(y_val) 172 173 # Data list flag. 174 data_list = True 175 176 # One set per spin (dictionary data has been returned). 177 if data_dict or isinstance(x_val, dict): 178 # Append a new set structure and set the name to the spin ID. 179 data[0].append([]) 180 set_labels.append("Spin %s" % id) 181 182 # The set index. 183 index = len(data[0]) - 1 184 185 # Convert to lists. 186 list_data = [] 187 for key in x_val.keys(): 188 list_data.append([x_val[key], y_val[key]]) 189 list_data.sort() 190 191 # Overwrite the data structures. 192 x_val = [] 193 y_val = [] 194 for i in range(len(list_data)): 195 x_val.append(list_data[i][0]) 196 y_val.append(list_data[i][1]) 197 198 # No errors. 199 if x_err == None: 200 x_err = [None]*len(x_val) 201 if y_err == None: 202 y_err = [None]*len(y_val) 203 204 # Data list flag. 205 data_dict = True 206 207 # Convert the data to lists for packing into 1 point. 208 else: 209 x_val = [x_val] 210 y_val = [y_val] 211 x_err = [x_err] 212 y_err = [y_err] 213 214 # A new spin type (one data set per spin type). 215 if not data_list and not data_dict and spin.name not in spin_names: 216 # Append a new set structure. 217 data[0].append([]) 218 219 # Append the label. 220 set_labels.append("%s spins. " % spin.name + set_label) 221 222 # Add the spin name to the list. 223 spin_names.append(spin.name) 224 225 # The set index. 226 index = i * len(spin_names) + spin_names.index(spin.name) 227 228 # Loop over the points. 229 for j in range(len(x_val)): 230 # Initialise and alias point structure. 231 data[0][index].append([]) 232 point = data[0][index][-1] 233 234 # Conversion factors. 235 x_val[j] = x_val[j] / x_return_conversion_factor(x_data_type) 236 if x_err[j]: 237 x_err[j] = x_err[j] / x_return_conversion_factor(x_data_type) 238 y_val[j] = y_val[j] / y_return_conversion_factor(y_data_type) 239 if y_err[j]: 240 y_err[j] = y_err[j] / y_return_conversion_factor(y_data_type) 241 242 # Append the data. 243 point.append(x_val[j]) 244 point.append(y_val[j]) 245 point.append(x_err[j]) 246 point.append(y_err[j]) 247 248 # Error flags. 249 if x_err[j] and not x_err_flag: 250 x_err_flag = True 251 if y_err[j] and not y_err_flag: 252 y_err_flag = True 253 254 # The graph type. 255 graph_type = 'xy' 256 if x_err_flag: 257 graph_type = graph_type + 'dx' 258 if y_err_flag: 259 graph_type = graph_type + 'dy' 260 261 # Remodel the data. 262 new_data = [] 263 for i in range(len(data)): 264 new_data.append([]) 265 for j in range(len(data[i])): 266 new_data[i].append([]) 267 for k in range(len(data[i][j])): 268 # The xy data. 269 new_data[i][j].append([]) 270 new_data[i][j][k].append(data[i][j][k][0]) 271 new_data[i][j][k].append(data[i][j][k][1]) 272 273 # First error set. 274 if graph_type in ['xydx', 'xydxdy']: 275 new_data[i][j][k].append(data[i][j][k][2]) 276 277 # Second error set. 278 if graph_type in ['xydy', 'xydxdy']: 279 new_data[i][j][k].append(data[i][j][k][3]) 280 281 # Return the data. 282 return new_data, set_labels, graph_type
283 284
285 -def view(file=None, dir=None, grace_exe='xmgrace'):
286 """Execute Grace. 287 288 @keyword file: The name of the file to open in Grace. 289 @type file: str 290 @keyword dir: The optional directory containing the file. 291 @type dir: str 292 @keyword grace_exe: The name of the Grace executable file. This should be located within the 293 system path. 294 @type grace_exe: str 295 """ 296 297 # Test the binary file string corresponds to a valid executable. 298 test_binary(grace_exe) 299 300 # File path. 301 file_path = get_file_path(file, dir) 302 303 # Run Grace. 304 system(grace_exe + " " + file_path + " &")
305 306
307 -def write(x_data_type='spin', y_data_type=None, spin_id=None, plot_data='value', file=None, dir=None, force=False, norm=True):
308 """Writing data to a file. 309 310 @keyword x_data_type: The category of the X-axis data. 311 @type x_data_type: str 312 @keyword y_data_type: The category of the Y-axis data. 313 @type y_data_type: str 314 @keyword spin_id: The spin identification string. 315 @type spin_id: str 316 @keyword plot_data: The type of the plotted data, one of 'value', 'error', or 'sim'. 317 @type plot_data: str 318 @keyword file: The name of the Grace file to create. 319 @type file: str 320 @keyword dir: The optional directory to place the file into. 321 @type dir: str 322 @param force: Boolean argument which if True causes the file to be overwritten if it 323 already exists. 324 @type force: bool 325 @keyword norm: The normalisation flag which if set to True will cause all graphs to be 326 normalised to a starting value of 1. 327 @type norm: bool 328 """ 329 330 # Test if the current pipe exists. 331 pipes.test() 332 333 # Test if the sequence data is loaded. 334 if not exists_mol_res_spin_data(): 335 raise RelaxNoSequenceError 336 337 # Test if the plot_data argument is one of 'value', 'error', or 'sim'. 338 if plot_data not in ['value', 'error', 'sim']: 339 raise RelaxError("The plot data argument " + repr(plot_data) + " must be set to either 'value', 'error', 'sim'.") 340 341 # Test if the simulations exist. 342 if plot_data == 'sim' and not hasattr(cdp, 'sim_number'): 343 raise RelaxNoSimError 344 345 # Open the file for writing. 346 file_path = get_file_path(file, dir) 347 file = open_write_file(file, dir, force) 348 349 # Get the data. 350 data, set_names, graph_type = get_data(spin_id, x_data_type=x_data_type, y_data_type=y_data_type, plot_data=plot_data) 351 352 # No data, so close the empty file and exit. 353 if not len(data) or not len(data[0]) or not len(data[0][0]): 354 warn(RelaxWarning("No data could be found, creating an empty file.")) 355 file.close() 356 return 357 358 # Determine the sequence data type. 359 seq_type = [None, None] 360 if x_data_type == 'spin': 361 seq_type[0] = 'res' 362 if y_data_type == 'spin': 363 seq_type[1] = 'res' 364 365 # Write the header. 366 write_xy_header(sets=len(data[0]), file=file, data_type=[x_data_type, y_data_type], seq_type=seq_type, set_names=set_names, norm=norm) 367 368 # Write the data. 369 write_xy_data(data, file=file, graph_type=graph_type, norm=norm) 370 371 # Close the file. 372 file.close() 373 374 # Add the file to the results file list. 375 if not hasattr(cdp, 'result_files'): 376 cdp.result_files = [] 377 cdp.result_files.append(['grace', 'Grace', file_path]) 378 status.observers.result_file.notify()
379 380 381
382 -def write_xy_data(data, file=None, graph_type=None, norm=False):
383 """Write the data into the Grace xy-scatter plot. 384 385 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). 386 387 388 @param data: The 4D structure of numerical data to graph (see docstring). 389 @type data: list of lists of lists of float 390 @keyword file: The file object to write the data to. 391 @type file: file object 392 @keyword graph_type: The graph type which can be one of xy, xydy, xydx, or xydxdy. 393 @type graph_type: str 394 @keyword norm: The normalisation flag which if set to True will cause all graphs to be normalised to 1. 395 @type norm: bool 396 """ 397 398 # Comment columns. 399 comment_col = 2 400 if graph_type in ['xydx', 'xydy']: 401 comment_col = 3 402 elif graph_type == 'xydxdy': 403 comment_col = 4 404 405 # Loop over the graphs. 406 for gi in range(len(data)): 407 # Loop over the data sets of the graph. 408 for si in range(len(data[gi])): 409 # The target and type. 410 file.write("@target G%s.S%s\n" % (gi, si)) 411 file.write("@type %s\n" % graph_type) 412 413 # Normalisation (to the first data point y value!). 414 norm_fact = 1.0 415 if norm: 416 norm_fact = data[gi][si][0][1] 417 418 # Loop over the data points. 419 for point in data[gi][si]: 420 # Bad data. 421 if point[0] == None or point[1] == None: 422 continue 423 424 # X and Y data. 425 file.write("%-30s %-30s" % (point[0], point[1]/norm_fact)) 426 427 # The dx and dy errors. 428 if graph_type in ['xydx', 'xydy', 'xydxdy']: 429 # Catch x or y-axis errors of None. 430 error = point[2] 431 if error == None: 432 error = 0.0 433 434 # Write the error. 435 file.write(" %-30s" % (error/norm_fact)) 436 437 # The dy errors of xydxdy. 438 if graph_type == 'xydxdy': 439 # Catch y-axis errors of None. 440 error = point[3] 441 if error == None: 442 error = 0.0 443 444 # Write the error. 445 file.write(" %-30s" % (error/norm_fact)) 446 447 # The comment if given. 448 try: 449 file.write("%30s \"# %s\"" % ('', point[comment_col])) 450 except IndexError: 451 pass 452 453 # End the point. 454 file.write("\n") 455 456 # End of the data set i. 457 file.write("&\n")
458 459
460 -def write_xy_header(file=None, paper_size='A4', title=None, subtitle=None, view=None, sets=1, set_names=None, set_colours=None, symbols=None, symbol_sizes=None, symbol_fill=None, linestyle=None, linetype=None, linewidth=0.5, data_type=None, seq_type=None, axis_labels=None, axis_min=None, axis_max=None, legend_pos=None, legend=False, norm=False):
461 """Write the grace header for xy-scatter plots. 462 463 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). 464 465 466 @keyword file: The file object to write the data to. 467 @type file: file object 468 @keyword paper_size: The paper size, i.e. 'A4'. If set to None, this will default to letter size. 469 @type paper_size: str 470 @keyword title: The title of the graph. 471 @type title: None or str 472 @keyword subtitle: The sub-title of the graph. 473 @type subtitle: None or str 474 @keyword view: List of 4 coordinates defining the graph view port. 475 @type view: None or list of float 476 @keyword sets: The number of data sets in the graph G0. 477 @type sets: int 478 @keyword set_names: The names associated with each graph data set G0.Sx. For example this can be a list of spin identification strings. 479 @type set_names: None or list of str 480 @keyword set_colours: The colours for each graph data set G0.Sx. 481 @type set_colours: None or list of int 482 @keyword symbols: The symbol style for each graph data set G0.Sx. 483 @type symbols: None or list of int 484 @keyword symbol_sizes: The symbol size for each graph data set G0.Sx. 485 @type symbol_sizes: None or list of int 486 @keyword symbol_fill: The symbol file style for each graph data set G0.Sx. 487 @type symbol_fill: None or list of int 488 @keyword linestyle: The line style for each graph data set G0.Sx. 489 @type linestyle: None or list of int 490 @keyword linetype: The line type for each graph data set G0.Sx. 491 @type linetype: None or list of int 492 @keyword linewidth: The line width for all elements of each graph data set G0.Sx. 493 @type linewidth: None or float 494 @keyword data_type: The axis data category (in the [X, Y] list format). 495 @type data_type: None or list of str 496 @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'. 497 @type seq_type: None or list of str 498 @keyword axis_labels: The labels for the axes (in the [X, Y] list format). 499 @type axis_labels: None or list of str 500 @keyword axis_min: The minimum values for specifying the graph ranges (in the [X, Y] list format). 501 @type axis_min: None or list of str 502 @keyword axis_max: The maximum values for specifying the graph ranges (in the [X, Y] list format). 503 @type axis_max: None or list of str 504 @keyword legend_pos: The position of the legend, e.g. [0.3, 0.8]. 505 @type legend_pos: None or list of float 506 @keyword legend: If True, the legend will be visible. 507 @type legend: bool 508 @keyword norm: The normalisation flag which if set to True will cause all graphs to be normalised to 1. 509 @type norm: bool 510 """ 511 512 # Set the None args to lists as needed. 513 if not data_type: 514 data_type = [None, None] 515 if not seq_type: 516 seq_type = [None, None] 517 if not axis_labels: 518 axis_labels = [None, None] 519 if not axis_min: 520 axis_min = [None, None] 521 if not axis_max: 522 axis_max = [None, None] 523 524 # Set the Grace version number of the header's formatting for compatibility. 525 file.write("@version 50121\n") 526 527 # The paper size. 528 if paper_size == 'A4': 529 file.write("@page size 842, 595\n") 530 531 # Graph G0. 532 file.write("@with g0\n") 533 534 # The view port. 535 if not view: 536 view = [0.15, 0.15, 1.28, 0.85] 537 file.write("@ view %s, %s, %s, %s\n" % (view[0], view[1], view[2], view[3])) 538 539 # The title and subtitle. 540 if title: 541 file.write("@ title \"%s\"\n" % title) 542 if subtitle: 543 file.write("@ subtitle \"%s\"\n" % subtitle) 544 545 # Axis specific settings. 546 axes = ['x', 'y'] 547 for i in range(2): 548 # Analysis specific methods for making labels. 549 analysis_spec = False 550 if pipes.cdp_name(): 551 # Flag for making labels. 552 analysis_spec = True 553 554 # Specific value and error, conversion factor, and units returning functions. 555 return_units = specific_fns.setup.get_specific_fn('return_units', pipes.get_type()) 556 return_grace_string = specific_fns.setup.get_specific_fn('return_grace_string', pipes.get_type()) 557 558 # Test if the axis data type is a minimisation statistic. 559 if data_type[i] and data_type[i] != 'spin' and generic_fns.minimise.return_data_name(data_type[i]): 560 return_units = generic_fns.minimise.return_units 561 return_grace_string = generic_fns.minimise.return_grace_string 562 563 # Some axis default values for spin data. 564 if data_type[i] == 'spin': 565 # Residue only data. 566 if seq_type[i] == 'res': 567 # Axis limits. 568 if not axis_min[i]: 569 axis_min[i] = repr(cdp.mol[0].res[0].num - 1) 570 if not axis_max[i]: 571 axis_max[i] = repr(cdp.mol[0].res[-1].num + 1) 572 573 # X-axis label. 574 if not axis_labels[i]: 575 axis_labels[i] = "Residue number" 576 577 # Spin only data. 578 if seq_type[i] == 'spin': 579 # Axis limits. 580 if not axis_min[i]: 581 axis_min[i] = repr(cdp.mol[0].res[0].spin[0].num - 1) 582 if not axis_max[i]: 583 axis_max[i] = repr(cdp.mol[0].res[0].spin[-1].num + 1) 584 585 # X-axis label. 586 if not axis_labels[i]: 587 axis_labels[i] = "Spin number" 588 589 # Mixed data. 590 if seq_type[i] == 'mixed': 591 # X-axis label. 592 if not axis_labels[i]: 593 axis_labels[i] = "Spin identification string" 594 595 # Some axis default values for other data types. 596 else: 597 # Label. 598 if analysis_spec and not axis_labels[i]: 599 # Get the units. 600 units = return_units(data_type[i]) 601 602 # Set the label. 603 axis_labels[i] = return_grace_string(data_type[i]) 604 605 # Add units. 606 if units: 607 axis_labels[i] = axis_labels[i] + "\\N (" + units + ")" 608 609 # Normalised data. 610 if norm and axes[i] == 'y': 611 axis_labels[i] = axis_labels[i] + " \\N\\q(normalised)\\Q" 612 613 # Write out the data. 614 if axis_min[i] != None: 615 file.write("@ world %smin %s\n" % (axes[i], axis_min[i])) 616 if axis_max[i] != None: 617 file.write("@ world %smax %s\n" % (axes[i], axis_max[i])) 618 if axis_labels[i]: 619 file.write("@ %saxis label \"%s\"\n" % (axes[i], axis_labels[i])) 620 file.write("@ %saxis label char size 1.48\n" % axes[i]) 621 file.write("@ %saxis tick major size 0.75\n" % axes[i]) 622 file.write("@ %saxis tick major linewidth %s\n" % (axes[i], linewidth)) 623 file.write("@ %saxis tick minor linewidth %s\n" % (axes[i], linewidth)) 624 file.write("@ %saxis tick minor size 0.45\n" % axes[i]) 625 file.write("@ %saxis ticklabel char size 1.00\n" % axes[i]) 626 627 # Legend box. 628 if legend_pos: 629 file.write("@ legend %s, %s\n" % (legend_pos[0], legend_pos[1])) 630 if legend: 631 file.write("@ legend off\n") 632 633 # Frame. 634 file.write("@ frame linewidth %s\n" % linewidth) 635 636 # Loop over each graph set. 637 for i in range(sets): 638 # Symbol style (default to all different symbols). 639 if symbols: 640 file.write("@ s%i symbol %i\n" % (i, symbols[i])) 641 else: 642 # The symbol number (between 1 and 10). 643 num = (i+1) - (i+1) / 11 * 10 644 645 # Write out. 646 file.write("@ s%i symbol %i\n" % (i, num)) 647 648 # Symbol sizes (default to a small size). 649 if symbol_sizes: 650 file.write("@ s%i symbol size %s\n" % (i, symbol_sizes[i])) 651 else: 652 file.write("@ s%i symbol size 0.45\n" % i) 653 654 # The symbol fill. 655 if symbol_fill: 656 file.write("@ s%i symbol fill pattern %i\n" % (i, symbol_fill[i])) 657 658 # The symbol line width. 659 file.write("@ s%i symbol linewidth %s\n" % (i, linewidth)) 660 661 # Symbol colour (default to nothing). 662 if set_colours: 663 file.write("@ s%i symbol color %s\n" % (i, set_colours[i])) 664 665 # Error bars. 666 file.write("@ s%i errorbar size 0.5\n" % i) 667 file.write("@ s%i errorbar linewidth %s\n" % (i, linewidth)) 668 file.write("@ s%i errorbar riser linewidth %s\n" % (i, linewidth)) 669 670 # Line linestyle (default to nothing). 671 if linestyle: 672 file.write("@ s%i line linestyle %s\n" % (i, linestyle[i])) 673 674 # Line linetype (default to nothing). 675 if linetype: 676 file.write("@ s%i line type %s\n" % (i, linetype[i])) 677 678 # Line colours (default to nothing). 679 if set_colours: 680 file.write("@ s%i line color %s\n" % (i, set_colours[i])) 681 682 # Legend. 683 if set_names and set_names[i]: 684 file.write("@ s%i legend \"%s\"\n" % (i, set_names[i]))
685