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