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   
 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  """ 
 35 -    def __init__(self,  
 36                      title                   = 'general_star_file_title',  
 37                      filename                = '',  
 38                      datanodes               = None,  
 39                      flavor                  = None,  
 40   
 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" 
 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           
 71           
 72           
 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   
 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   
112          text = Utils.dos2unix(text) 
113          text = Utils.mac2unix(text) 
114   
115          text = comments_strip(text) 
116   
117           
118          text = semicolon_block_collapse(text) 
119           
120           
121           
122           
123          if nmrView_type: 
124              text = nmrView_compress(text)  
125           
126           
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           
137          next_sf_begin   = None       
138          next_sf_end     = None       
139          next_free_tt    = None       
140          next_loop_tt    = None       
141          sf_open         = None       
142          text_length     = len(text) 
143   
144           
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               
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               
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    = []))  
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               
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               
224              if next_free_tt: 
225                  free            = 1 
226                  next_free_tt    = None 
227              else:  
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  
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]  
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           
271          text = '' 
272          return 0 
 273   
274   
275   
276      """ 
277      Writes the object to a STAR formatted file using 
278      the filename attribute. 
279      """ 
281          if not self.filename: 
282              print('ERROR: no filename in STARFile with title:', self.title) 
283              return 1 
284   
285           
286          if isinstance(self.filename, str): 
287              f = open(self.filename, 'w') 
288              f.write(self.star_text()) 
289              f.close() 
290   
291           
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      """ 
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   
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   
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   
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      """ 
342          if not category: 
343              return None 
344          result = [] 
345          for node in self.datanodes: 
346              if isinstance(node, SaveFrame):  
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      """