Package bmrblib :: Package pystarlib :: Module File
[hide private]
[frames] | no frames]

Source Code for Module bmrblib.pystarlib.File

  1  """ 
  2  Classes for dealing with STAR syntax 
  3  """ 
  4  from bmrblib.pystarlib import Utils 
  5  from bmrblib.pystarlib.Utils import Lister 
  6  from bmrblib.pystarlib.TagTable import TagTable 
  7  from bmrblib.pystarlib.Text import comments_strip 
  8  from bmrblib.pystarlib.Text import semicolon_block_collapse 
  9  from bmrblib.pystarlib.Text import nmrView_compress 
 10  from bmrblib.pystarlib.Text import pattern_save_begin 
 11  from bmrblib.pystarlib.Text import pattern_save_end 
 12  from bmrblib.pystarlib.Text import pattern_tagtable_loop 
 13  from bmrblib.pystarlib.Text import pattern_save_begin_nws 
 14  from bmrblib.pystarlib.Text import pattern_save_end_nws 
 15  from bmrblib.pystarlib.Text import pattern_tag_name_nws 
 16  from bmrblib.pystarlib.Text import pattern_tagtable_loop_nws 
 17  from bmrblib.pystarlib.SaveFrame import SaveFrame 
 18   
 19  import os 
 20  import re 
 21  #import profile 
 22   
 23  __author__    = "$Author: jurgenfd $"  
 24  ___revision__ = "$Revision: 13 $" 
 25  ___date__     = "$Date: 2007-08-22 20:59:28 +0200 (Wed, 22 Aug 2007) $" 
 26   
 27   
 28   
 29  """ 
 30  STAR file 
 31  Only methods for reading and writing are currently implemented. 
 32  datanodes is a list of possibly mixed saveframes and tagtables 
 33  """ 
34 -class File (Lister):
35 - def __init__(self, 36 title = 'general_star_file_title', 37 filename = '', 38 datanodes = None, 39 flavor = None, # Call set_flavor when changing 40 # preferred_quote = '"', # Put somewhere else? 41 verbosity = 2 42 ):
43 self.title = title 44 self.filename = filename 45 46 if datanodes: 47 self.datanodes = datanodes 48 else: 49 self.datanodes = [] 50 51 self.flavor = flavor 52 self.verbosity = verbosity
53 54 "Simple checks on integrity"
55 - def check_integrity(self, recursive = 1):
56 if recursive: 57 for datanode in self.datanodes: 58 if datanode.check_integrity(recursive = 1): 59 print("ERROR: integrity check failed for Saveframe") 60 return 1 61 if self.verbosity >= 9: 62 print('Checked integrity of File (%2s datanodes, recurs.=%s) : OK [%s]' % ( 63 len(self.datanodes), recursive, self.title))
64 65 "Returns the STAR text representation"
66 - def star_text(self, flavor = None):
67 if flavor == None: 68 flavor = self.flavor 69 str = 'data_%s\n' % self.title 70 # Data node objects can be of type SaveFrame OR TagTable only 71 # Data node object can now also contain comment information 72 # these comments are printed before the saveframe (Wim 2003/08/05) 73 for datanode in self.datanodes: 74 str = str + datanode.comment 75 str = str + datanode.star_text(flavor = flavor) 76 return str
77 78 79 """ 80 Reads a NMR-STAR formatted file using 81 the filename attribute. 82 """
83 - def read (self, nmrView_type = 0):
84 85 if not self.filename: 86 print('ERROR: no filename in STARFile with title:', self.title) 87 return 1 88 # print "DEBUG: Current directory", os.listdir(os.curdir) 89 text = open(self.filename, 'r').read() 90 if self.parse(text=text, nmrView_type = nmrView_type): 91 print("ERROR: couldn't parse file") 92 return 1 93 94 return 0
95 96 97 """ 98 - Parses text into save frames and tagtables. 99 - Input text should start at position given with non-white space character 100 - Appends a list of datanodes(save frames or tagtables) 101 """
102 - def parse (self, text='', nmrView_type = 0):
103 104 if self.verbosity > 2: 105 print('DEBUG: Parsing STAR file:', self.filename) 106 107 """ 108 '"Begin at the beginning," the King said, gravely, 109 "and go on till you come to the end; then stop."' (LC) 110 """ 111 # print "DEBUG taking care of EOL variations" 112 text = Utils.dos2unix(text)# \r\n -> \n 113 text = Utils.mac2unix(text)# \r -> \n 114 115 text = comments_strip(text) 116 117 ## Collapse the semicolon block for ease of parsing 118 text = semicolon_block_collapse(text) 119 120 121 ## For nmrView 'nmrStar' also compress { } into {} 122 ## Wim 05/03/2003 123 if nmrView_type: 124 text = nmrView_compress(text) 125 126 ## TITLE 127 match_data_tag = re.search(r'\s*data_(\S+)\s+', text, 0) 128 if not match_data_tag: 129 print("ERROR: found no 'data_title' string in ") 130 print("ERROR: file's text (first 100 chars):[%s] " % text[0:100]) 131 return 1 132 self.title = match_data_tag.group(1) 133 pos = match_data_tag.end() 134 135 136 ## Four quick searches for possible continuations 137 next_sf_begin = None # SAVE FRAME BEGIN 138 next_sf_end = None # SAVE FRAME END 139 next_free_tt = None # FREE TAGTABLE 140 next_loop_tt = None # LOOP TAGTABLE 141 sf_open = None # When a saveframe is open 142 text_length = len(text) 143 144 ## Only break when parsed to the eof 145 while pos < text_length: 146 if self.verbosity >= 9: 147 print('Parse text from position:%s : [%s]' % ( 148 pos, text[pos:pos+10])) 149 150 match_save_begin_nws = pattern_save_begin_nws.search(text, pos, pos+len('save_1')) 151 if match_save_begin_nws: 152 if match_save_begin_nws.start() == pos: 153 next_sf_begin = 1 154 if not next_sf_begin: 155 match_save_end_nws = pattern_save_end_nws.search(text, pos, pos+len('save_ ')) 156 if match_save_end_nws: 157 if match_save_end_nws.start() == pos: 158 next_sf_end = 1 159 if not (next_sf_begin or next_sf_end): 160 match_tag_name_nws = pattern_tag_name_nws.search(text, pos, pos+len(' _X')) 161 if match_tag_name_nws: 162 if match_tag_name_nws.start() == pos: 163 next_free_tt = 1 164 if not (next_sf_begin or next_sf_end or next_free_tt): 165 match_tagtable_loop_nws = pattern_tagtable_loop_nws.search(text, pos, pos+len('loop_ ')) 166 if match_tagtable_loop_nws: 167 if match_tagtable_loop_nws.start() == pos: 168 next_loop_tt = 1 169 170 ## Just checking 171 if not (next_sf_begin or next_sf_end or next_free_tt or next_loop_tt): 172 print('ERROR: No new item found in data_nodes_parse.') 173 print('Items looked for are a begin or end of a saveframe, or') 174 print('a begin of a tagtable(free or looped).') 175 print() 176 print("At text (before pos=", pos, "):") 177 start = pos-70 178 if start < 0: 179 start = 0 180 print("[" + text[start:pos] + "]") 181 print("At text (starting pos=", pos, "):") 182 print("[" + text[pos:pos+70]+ "]") 183 return None 184 185 ## SAVE FRAME BEGIN 186 if next_sf_begin: 187 if sf_open: 188 print("ERROR: Found the beginning of a saveframe but") 189 print("ERROR: saveframe before is still open(not closed;-)") 190 return None 191 match_save_begin = pattern_save_begin.search(text, pos) 192 if not match_save_begin: 193 print("ERROR: Code error (no second match on sf begin)"); 194 return None 195 if match_save_begin.start() != pos: 196 print("ERROR: Code error (wrong second match on sf begin)"); 197 return None 198 self.datanodes.append(SaveFrame(tagtables = [])) # Need resetting ? 199 self.datanodes[-1].title = match_save_begin.group(1) 200 sf_open = 1 201 next_sf_begin = None 202 pos = match_save_begin.end() 203 continue 204 205 ## SAVE FRAME END 206 if next_sf_end: 207 if not sf_open: 208 print("ERROR: Found the end of a saveframe but") 209 print("ERROR: saveframe was not open") 210 return None 211 match_save_end = pattern_save_end.search(text, pos) 212 if not match_save_end: 213 print("ERROR: Code error (no second match on sf end)"); 214 return None 215 if match_save_end.start() != pos: 216 print("ERROR: Code error (wrong second match on sf end)"); 217 return None 218 sf_open = None 219 next_sf_end = None 220 pos = match_save_end.end() 221 continue 222 223 ## FREE or LOOP TAGTABLE 224 if next_free_tt: 225 free = 1 226 next_free_tt = None 227 else: # next_loop_tt must be true as this was checked before 228 if not next_loop_tt: 229 print('ERROR: code bug in File.parse()') 230 return None 231 free = None 232 next_loop_tt = None 233 234 match_tagtable_loop = pattern_tagtable_loop.search(text, pos) 235 if not match_tagtable_loop: 236 print('ERROR: Code error, no second match on tagtable_loop') 237 return None 238 if match_tagtable_loop.start() != pos: 239 print("ERROR: Code error (wrong second match on tagtable_loop)") 240 return None 241 pos = match_tagtable_loop.end() 242 243 if sf_open: 244 dn = self.datanodes[-1].tagtables # Insert in last saveframes' tagtables 245 else: 246 dn = self.datanodes 247 248 dn.append( 249 TagTable(free = free, 250 tagnames = [], 251 tagvalues = [], 252 verbosity = self.verbosity)) 253 tt = dn[-1] # Just to be verbose for the beloved reader 254 pos = tt.parse(text=text, pos=pos) 255 256 if pos == None: 257 print("ERROR: In parsing tagtable") 258 return None 259 if self.verbosity >=9: 260 print('Parsed tagtable up to pos: [%s]' % pos) 261 262 if self.verbosity > 2: 263 print('DEBUG Parsed: [%s] datanodes (top level count only)' % \ 264 len(self.datanodes)) 265 266 if self.check_integrity(recursive = 0): 267 print("ERROR: integrity not ok") 268 return 1 269 270 # Save some memory 271 text = '' 272 return 0
273 274 275 276 """ 277 Writes the object to a STAR formatted file using 278 the filename attribute. 279 """
280 - def write (self):
281 if not self.filename: 282 print('ERROR: no filename in STARFile with title:', self.title) 283 return 1 284 285 # A file path to open. 286 if isinstance(self.filename, str): 287 f = open(self.filename, 'w') 288 f.write(self.star_text()) 289 f.close() 290 291 # An already opened file handle. 292 else: 293 self.filename.write(self.star_text()) 294 295 if self.verbosity > 2: 296 print('DEBUG: Written STAR file:', self.filename)
297 298 """ 299 Reads only the top part of a file up to but excluding the line 300 on which any given regexp matches. 301 Returns None on success. 302 """
303 - def getHeader( self, matchStrList, inputFN, outputFN ):
304 matchList = [] 305 for str in matchStrList: 306 m = re.compile(str) 307 if m is None: 308 print("ERROR: failed to compile pattern: ", str) 309 return 1 310 # print "Appended: ", str 311 matchList.append( m ) 312 313 input = open(inputFN, 'r') 314 output = open(outputFN, 'w') 315 L =[] 316 line = input.readline() 317 found = False 318 while line: 319 for m in matchList: 320 # print "DEBUG: looking at line: ", line, " with ", m 321 if m.search(line) != None: 322 found = True 323 break 324 if found: 325 break 326 L.append(line) 327 line = input.readline() 328 329 # print "DEBUG: writing number of lines: ", len(L) 330 output.writelines(L) 331 output.close() 332 if not os.path.exists(outputFN): 333 print("WARNING: failed to materialize file: " + outputFN) 334 return 1 335 return None
336 337 """ 338 Returns sfs that match the category, None for error and empty list 339 for no matches. 340 """
341 - def getSaveFrames(self, category = None):
342 if not category: 343 return None 344 result = [] 345 for node in self.datanodes: 346 if isinstance(node, SaveFrame): # redundant test for well behaved files 347 if node.getSaveFrameCategory()==category: 348 result.append(node) 349 return result
350 351 352 353 """ 354 Tries to reformat a file on disk with the filename given in the 355 attribute of this object. 356 Running Steve Madings (BMRB) formatNMRSTAR program if available 357 NOTE: this does NOT do anything with the datanodes of this object! 358 """
359 - def formatNMRSTAR(self, 360 # comment_file_str_dir = '/bmrb/lib', 361 ):
362 363 if self.verbosity >= 9: 364 print("Attempting to reformat STAR file using external program if available") 365 366 if os.name != 'posix': 367 print("WARNING: No external program available on non-posix systems for reformatting STAR files") 368 return 1 369 370 ## Try command and check for non-zero exit status 371 ## Note that these commands are only valid on Unix 372 ## Standard error is thrown on the bit bucket. 373 cmd = "%s < %s 2>/dev/null" % ('formatNMRSTAR', self.filename) 374 pipe = os.popen(cmd) 375 output = pipe.read() 376 377 ## The program exit status is available by the following construct 378 ## The status will be the exit number (in one of the bytes) 379 ## unless the program executed successfully in which case it will 380 ## be None. 381 status = pipe.close() 382 if self.verbosity >= 9: 383 print("Got status:", status) 384 385 ## Success 386 if (status == None): 387 try: 388 open(self.filename, 'w').write(output) 389 except IOError: 390 print('ERROR: Could not open the file for writing', self.filename) 391 return 1 392 if self.verbosity >= 9: 393 print("Reformatted STAR file:", self.filename) 394 return 0 395 else: 396 if self.verbosity : 397 print("WARNING: Not pretty printing STAR file", self.filename) 398 return 1
399