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