Package lib :: Package spectrum :: Module sparky
[hide private]
[frames] | no frames]

Source Code for Module lib.spectrum.sparky

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2003-2004,2006-2013 Edward d'Auvergne                         # 
  4  # Copyright (C) 2008 Sebastien Morin                                          # 
  5  # Copyright (C) 2013 Troels E. Linnet                                         # 
  6  #                                                                             # 
  7  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  8  #                                                                             # 
  9  # This program is free software: you can redistribute it and/or modify        # 
 10  # it under the terms of the GNU General Public License as published by        # 
 11  # the Free Software Foundation, either version 3 of the License, or           # 
 12  # (at your option) any later version.                                         # 
 13  #                                                                             # 
 14  # This program is distributed in the hope that it will be useful,             # 
 15  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 16  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 17  # GNU General Public License for more details.                                # 
 18  #                                                                             # 
 19  # You should have received a copy of the GNU General Public License           # 
 20  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 21  #                                                                             # 
 22  ############################################################################### 
 23   
 24  # Module docstring. 
 25  """Module containing functions for handling Sparky files.""" 
 26   
 27   
 28  # Python module imports. 
 29  from re import split 
 30  from warnings import warn 
 31   
 32  # relax module imports. 
 33  from lib.errors import RelaxError 
 34  from lib.io import open_write_file, strip 
 35  from lib.warnings import RelaxWarning 
 36   
 37   
38 -def read_list(peak_list=None, file_data=None):
39 """Extract the peak intensity information from the Sparky peak intensity file. 40 41 @keyword peak_list: The peak list object to place all data into. 42 @type peak_list: lib.spectrum.objects.Peak_list instance 43 @keyword file_data: The data extracted from the file converted into a list of lists. 44 @type file_data: list of lists of str 45 @raises RelaxError: When the expected peak intensity is not a float. 46 """ 47 48 # The number of header lines. 49 num = 0 50 if file_data[0][0] == 'Assignment': 51 num = num + 1 52 if file_data[1] == '': 53 num = num + 1 54 print("Number of header lines found: %s" % num) 55 56 # The columns according to the file. 57 w1_col = None 58 w2_col = None 59 w3_col = None 60 w4_col = None 61 int_col = None 62 for i in range(len(file_data[0])): 63 # The chemical shifts. 64 if file_data[0][i] == 'w1': 65 w1_col = i 66 elif file_data[0][i] == 'w2': 67 w2_col = i 68 elif file_data[0][i] == 'w3': 69 w3_col = i 70 elif file_data[0][i] == 'w4': 71 w4_col = i 72 73 # The peak height. 74 elif file_data[0][i] == 'Height': 75 # The peak height when exported from CcpNmr Analysis export without 'Data'. 76 int_col = i 77 78 # The peak height when exported from Sparky. 79 if file_data[0][i-1] == 'Data' and file_data[0][i] == 'Height': 80 int_col = i-1 81 82 # The peak volume. 83 elif file_data[0][i] == 'Intensity': 84 int_col = i 85 86 # Remove the header. 87 file_data = file_data[num:] 88 89 # Strip the data. 90 file_data = strip(file_data) 91 92 # The dimensionality. 93 if w4_col != None: 94 dim = 4 95 elif w3_col != None: 96 dim = 3 97 elif w2_col != None: 98 dim = 2 99 elif w1_col != None: 100 dim = 1 101 else: 102 raise RelaxError("The dimensionality of the peak list cannot be determined.") 103 print("%sD peak list detected." % dim) 104 105 # Loop over the file data. 106 for line in file_data: 107 # Skip non-assigned peaks. 108 if line[0] == '?-?': 109 continue 110 111 # Split up the assignments. 112 if dim == 1: 113 assign1 = line[0] 114 elif dim == 2: 115 assign1, assign2 = split('-', line[0]) 116 elif dim == 3: 117 assign1, assign2, assign3 = split('-', line[0]) 118 elif dim == 4: 119 assign1, assign2, assign3, assign4 = split('-', line[0]) 120 121 # Process the assignment for each dimension. 122 if dim >= 1: 123 row1 = split('([a-zA-Z]+)', assign1) 124 name1 = row1[-2] + row1[-1] 125 if dim >= 2: 126 row2 = split('([a-zA-Z]+)', assign2) 127 name2 = row2[-2] + row2[-1] 128 if dim >= 3: 129 row3 = split('([a-zA-Z]+)', assign3) 130 name3 = row3[-2] + row3[-1] 131 if dim >= 4: 132 row4 = split('([a-zA-Z]+)', assign4) 133 name4 = row4[-2] + row4[-1] 134 135 # Get the residue number for dimension 1. 136 got_res_num1 = True 137 try: 138 res_num1 = int(row1[-3]) 139 except: 140 got_res_num1 = False 141 raise RelaxError("Improperly formatted Sparky file, cannot process the residue number for dimension 1 in assignment: %s." % line[0]) 142 143 # Get the residue number for dimension 2. 144 try: 145 res_num2 = int(row2[-3]) 146 except: 147 # We cannot always expect dimension 2 to have residue number. 148 if got_res_num1: 149 res_num2 = res_num1 150 else: 151 res_num2 = None 152 warn(RelaxWarning("Improperly formatted Sparky file, cannot process the residue number for dimension 2 in assignment: %s. Setting residue number to %s." % (line[0], res_num2))) 153 154 # The residue name for dimension 1. 155 got_res_name1 = True 156 try: 157 res_name1 = row1[-4] 158 except: 159 got_res_name1 = False 160 res_name1 = None 161 warn(RelaxWarning("Improperly formatted Sparky file, cannot process the residue name for dimension 1 in assignment: %s. Setting residue name to %s." % (line[0], res_name1))) 162 163 # The residue name for dimension 2. 164 try: 165 res_name2 = row2[-4] 166 except: 167 # We cannot always expect dimension 2 to have residue name. 168 if got_res_name1: 169 res_name2 = res_name1 170 else: 171 res_name2 = None 172 warn(RelaxWarning("Improperly formatted NMRPipe SeriesTab file, cannot process the residue name for dimension 2 in assignment: %s. Setting residue name to %s." % (line[0], res_name2))) 173 174 # Chemical shifts. 175 w1 = None 176 w2 = None 177 w3 = None 178 w4 = None 179 if w1_col != None: 180 try: 181 w1 = float(line[w1_col]) 182 except ValueError: 183 raise RelaxError("The chemical shift from the line %s is invalid." % line) 184 if w2_col != None: 185 try: 186 w2 = float(line[w2_col]) 187 except ValueError: 188 raise RelaxError("The chemical shift from the line %s is invalid." % line) 189 if w3_col != None: 190 try: 191 w3 = float(line[w3_col]) 192 except ValueError: 193 raise RelaxError("The chemical shift from the line %s is invalid." % line) 194 if w4_col != None: 195 try: 196 w4 = float(line[w4_col]) 197 except ValueError: 198 raise RelaxError("The chemical shift from the line %s is invalid." % line) 199 200 # Intensity. 201 if int_col != None: 202 try: 203 intensity = float(line[int_col]) 204 except ValueError: 205 raise RelaxError("The peak intensity value from the line %s is invalid." % line) 206 207 # Add the assignment to the peak list object. 208 if dim == 1: 209 peak_list.add(res_nums=[res_num1], res_names=[res_name1], spin_names=[name1], shifts=[w1], intensity=intensity) 210 elif dim == 2: 211 peak_list.add(res_nums=[res_num1, res_num2], res_names=[res_name1, res_name2], spin_names=[name1, name2], shifts=[w1, w2], intensity=intensity) 212 elif dim == 3: 213 peak_list.add(res_nums=[res_num1, res_num2, res_num1], res_names=[res_name1, res_name2, res_name1], spin_names=[name1, name2, name3], shifts=[w1, w2, w3], intensity=intensity) 214 elif dim == 4: 215 peak_list.add(res_nums=[res_num1, res_num2, res_num1, res_num1], res_names=[res_name1, res_name2, res_name1, res_name1], spin_names=[name1, name2, name3, name4], shifts=[w1, w2, w3, w4], intensity=intensity) 216 217 # If no intensity column, for example when reading spins from a spectrum list. 218 elif int_col == None: 219 warn(RelaxWarning(("The peak intensity value from the line %s is invalid. The return value will be without intensity." % line))) 220 221 # Add the assignment to the peak list object. 222 if dim == 1: 223 peak_list.add(res_nums=[res_num1], res_names=[res_name1], spin_names=[name1], shifts=[w1]) 224 elif dim == 2: 225 peak_list.add(res_nums=[res_num1, res_num2], res_names=[res_name1, res_name2], spin_names=[name1, name2], shifts=[w1, w2]) 226 elif dim == 3: 227 peak_list.add(res_nums=[res_num1, res_num2, res_num1], res_names=[res_name1, res_name2, res_name1], spin_names=[name1, name2, name3], shifts=[w1, w2, w3]) 228 elif dim == 4: 229 peak_list.add(res_nums=[res_num1, res_num2, res_num1, res_num1], res_names=[res_name1, res_name2, res_name1, res_name1], spin_names=[name1, name2, name3, name4], shifts=[w1, w2, w3, w4])
230 231
232 -def write_list(file_prefix=None, dir=None, res_names=None, res_nums=None, atom1_names=None, atom2_names=None, w1=None, w2=None, data_height=None, force=True):
233 """Create a Sparky .list file. 234 235 @keyword file_prefix: The base part of the file name without the .list extension. 236 @type file_prefix: str 237 @keyword dir: The directory to place the file in. 238 @type dir: str or None 239 @keyword res_names: The residue name list for each peak entry. 240 @type res_names: list of str 241 @keyword res_nums: The residue number list for each peak entry. 242 @type res_nums: list of int 243 @keyword atom1_names: The atom name list for w1 for each peak entry. 244 @type atom1_names: list of str 245 @keyword atom2_names: The atom name list for w2 for each peak entry. 246 @type atom2_names: list of str 247 @keyword w1: The w1 chemical shift list in ppm for each peak entry. 248 @type w1: list of float 249 @keyword w2: The w2 chemical shift list in ppm for each peak entry. 250 @type w2: list of float 251 @keyword data_height: The optional data height list for each peak entry. 252 @type data_height: None or list of float 253 @keyword force: A flag which if True will cause any pre-existing files to be overwritten. 254 @type force: bool 255 """ 256 257 # Checks. 258 N = len(w1) 259 if len(res_names) != N: 260 raise RelaxError("The %s residue names does not match the %s number of entries." % (len(res_names), N)) 261 if len(res_nums) != N: 262 raise RelaxError("The %s residue numbers does not match the %s number of entries." % (len(res_nums), N)) 263 if len(atom1_names) != N: 264 raise RelaxError("The %s w1 atom names does not match the %s number of entries." % (len(atom1_names), N)) 265 if len(atom2_names) != N: 266 raise RelaxError("The %s w2 atom names does not match the %s number of entries." % (len(atom2_names), N)) 267 if len(w1) != N: 268 raise RelaxError("The %s w1 chemical shifts does not match the %s number of entries." % (len(w1), N)) 269 if len(w2) != N: 270 raise RelaxError("The %s w2 chemical shifts does not match the %s number of entries." % (len(w2), N)) 271 if data_height and len(data_height) != N: 272 raise RelaxError("The %s data heights does not match the %s number of entries." % (len(data_height), N)) 273 274 # Printout. 275 print("Creating the Sparky list file.") 276 277 # Open the file. 278 if isinstance(file_prefix, str): 279 file = open_write_file(file_name=file_prefix+".list", dir=dir, force=force) 280 else: 281 file = file_prefix 282 283 # The header. 284 file.write("%17s %10s %10s" % ("Assignment ", "w1 ", "w2 ")) 285 if data_height != None: 286 file.write(" %12s" % "Data Height") 287 file.write("\n\n") 288 289 # The data. 290 for i in range(N): 291 # Generate the assignment. 292 assign = "%s%i%s-%s" % (res_names[i], res_nums[i], atom1_names[i], atom2_names[i]) 293 294 # Write out the line. 295 file.write("%17s %10.3f %10.3f" % (assign, w1[i], w2[i])) 296 if data_height != None: 297 file.write(" %12i" % data_height[i]) 298 file.write("\n")
299