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      """ 
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      """