1 | // =============================================================== // |
---|
2 | // // |
---|
3 | // File : SEC_read.cxx // |
---|
4 | // Purpose : read structure from declaration string // |
---|
5 | // // |
---|
6 | // Institute of Microbiology (Technical University Munich) // |
---|
7 | // http://www.arb-home.de/ // |
---|
8 | // // |
---|
9 | // =============================================================== // |
---|
10 | |
---|
11 | |
---|
12 | #include <sstream> |
---|
13 | #include "SEC_root.hxx" |
---|
14 | #include "SEC_iter.hxx" |
---|
15 | |
---|
16 | #define BUFFER_SIZE 1000 |
---|
17 | |
---|
18 | using namespace std; |
---|
19 | |
---|
20 | /*********************************************************************** |
---|
21 | * Supplementary Functions |
---|
22 | ***********************************************************************/ |
---|
23 | |
---|
24 | static const char * sec_read_line(istream & in) { |
---|
25 | static char string_buffer[BUFFER_SIZE]; |
---|
26 | in.getline(string_buffer, BUFFER_SIZE); |
---|
27 | |
---|
28 | //clean input-stream of whitespaces |
---|
29 | int j=0; |
---|
30 | for (int i=0; i<(BUFFER_SIZE-1); i++) { |
---|
31 | if (!(isspace(string_buffer[i]))) { |
---|
32 | string_buffer[j] = string_buffer[i]; |
---|
33 | j++; |
---|
34 | if (string_buffer[i] == '\0') break; |
---|
35 | } |
---|
36 | } |
---|
37 | return string_buffer; |
---|
38 | } |
---|
39 | |
---|
40 | static GB_ERROR sec_scan_ints(const char * string_buffer, int *number_1, int *number_2) { |
---|
41 | GB_ERROR error = 0; |
---|
42 | char *scanend; // this is a 'const char *' |
---|
43 | |
---|
44 | sec_assert(number_1); |
---|
45 | *number_1 = (int)strtol(string_buffer, &scanend, 10); |
---|
46 | if (number_2) { |
---|
47 | if (scanend[0] != ':') { |
---|
48 | error = "expected ':' after integer number"; |
---|
49 | } |
---|
50 | else { |
---|
51 | *number_2 = (int)strtol(scanend+1, &scanend, 10); |
---|
52 | } |
---|
53 | } |
---|
54 | if (!error && scanend[0] != 0) { // not at string end |
---|
55 | error = number_2 ? "unexpected content after '=NUMBER:NUMBER'" : "unexpected content after '=NUMBER'"; |
---|
56 | } |
---|
57 | return error; |
---|
58 | } |
---|
59 | |
---|
60 | static GB_ERROR sec_scan_doubles(const char * string_buffer, double *number_1, double *number_2) { |
---|
61 | GB_ERROR error = 0; |
---|
62 | char *scanend; // this is a 'const char *' |
---|
63 | |
---|
64 | sec_assert(number_1); |
---|
65 | *number_1 = strtod(string_buffer, &scanend); |
---|
66 | if (number_2) { |
---|
67 | if (scanend[0] != ':') { |
---|
68 | error = "expected ':' after floating-point number"; |
---|
69 | } |
---|
70 | else { |
---|
71 | *number_2 = strtod(scanend+1, &scanend); |
---|
72 | } |
---|
73 | } |
---|
74 | if (!error && scanend[0] != 0) { // not at string end |
---|
75 | error = number_2 ? "unexpected content after '=NUMBER:NUMBER'" : "unexpected content after '=NUMBER'"; |
---|
76 | } |
---|
77 | return error; |
---|
78 | } |
---|
79 | |
---|
80 | static GB_ERROR sec_expect_keyword_and_ints(const char *string_buffer, const char *keyword, size_t keywordlen, int *number_1, int *number_2) { |
---|
81 | // scans 'KEYWORD = NUM:NUM' or 'KEYWORD=NUM' |
---|
82 | // 1 or 2 numbers are returned via number_1 and number_2 |
---|
83 | |
---|
84 | sec_assert(strlen(keyword) == keywordlen); |
---|
85 | |
---|
86 | GB_ERROR error = 0; |
---|
87 | if (strncmp(string_buffer, keyword, keywordlen) != 0 || string_buffer[keywordlen] != '=') { |
---|
88 | error = GBS_global_string("Expected '%s='", keyword); |
---|
89 | } |
---|
90 | else { |
---|
91 | error = sec_scan_ints(string_buffer+keywordlen+1, number_1, number_2); |
---|
92 | } |
---|
93 | if (error) error = GBS_global_string("%s (while parsing '%s')", error, string_buffer); |
---|
94 | return error; |
---|
95 | } |
---|
96 | |
---|
97 | static GB_ERROR sec_expect_keyword_and_doubles(const char *string_buffer, const char *keyword, size_t keywordlen, double *number_1, double *number_2) { |
---|
98 | // scans 'KEYWORD = NUM:NUM' or 'KEYWORD=NUM' |
---|
99 | // 1 or 2 numbers are returned via number_1 and number_2 |
---|
100 | |
---|
101 | sec_assert(strlen(keyword) == keywordlen); |
---|
102 | |
---|
103 | GB_ERROR error = 0; |
---|
104 | if (strncmp(string_buffer, keyword, keywordlen) != 0 || string_buffer[keywordlen] != '=') { |
---|
105 | error = GBS_global_string("Expected '%s='", keyword); |
---|
106 | } |
---|
107 | else { |
---|
108 | error = sec_scan_doubles(string_buffer+keywordlen+1, number_1, number_2); |
---|
109 | } |
---|
110 | if (error) error = GBS_global_string("%s (while parsing '%s')", error, string_buffer); |
---|
111 | return error; |
---|
112 | } |
---|
113 | |
---|
114 | static GB_ERROR sec_expect_constraints(const char *string_buffer, const char *keyword, size_t keywordlen, SEC_constrainted *elem) { |
---|
115 | double min, max; |
---|
116 | GB_ERROR error = sec_expect_keyword_and_doubles(string_buffer, keyword, keywordlen, &min, &max); |
---|
117 | if (!error) elem->setConstraints(min, max); |
---|
118 | return error; |
---|
119 | } |
---|
120 | |
---|
121 | static GB_ERROR sec_expect_closing_bracket(istream& in) { |
---|
122 | const char *string_buffer = sec_read_line(in); |
---|
123 | |
---|
124 | if (strcmp(string_buffer, "}") == 0) return 0; |
---|
125 | return GBS_global_string("Expected '}' instead of '%s'", string_buffer); |
---|
126 | } |
---|
127 | |
---|
128 | /*********************************************************************** |
---|
129 | * READ-Functions |
---|
130 | ***********************************************************************/ |
---|
131 | |
---|
132 | GB_ERROR SEC_region::read(istream & in, SEC_root *root, int /*version*/) { |
---|
133 | int seq_start, seq_end; |
---|
134 | const char *string_buffer = sec_read_line(in); |
---|
135 | GB_ERROR error = sec_expect_keyword_and_ints(string_buffer, "SEQ", 3, &seq_start, &seq_end); |
---|
136 | |
---|
137 | if (!error) { |
---|
138 | sec_assert(root->get_db()->canDisplay()); |
---|
139 | if (root->get_db()->canDisplay()) { |
---|
140 | const XString& x_string = root->get_xString(); |
---|
141 | int x_count = x_string.getXcount(); |
---|
142 | |
---|
143 | if (seq_start >= x_count) error = GBS_global_string("Region start (%i) out of bounds [0..%i]", seq_start, x_count-1); |
---|
144 | else if (seq_end >= x_count) error = GBS_global_string("Region end (%i) out of bounds [0..%i]", seq_end, x_count-1); |
---|
145 | else set_sequence_portion(x_string.getAbsPos(seq_start), x_string.getAbsPos(seq_end)); |
---|
146 | } |
---|
147 | else { |
---|
148 | set_sequence_portion(seq_start, seq_end); |
---|
149 | } |
---|
150 | } |
---|
151 | return error; |
---|
152 | } |
---|
153 | |
---|
154 | GB_ERROR SEC_segment::read(SEC_loop *loop_, istream & in, int version) { |
---|
155 | loop = loop_; |
---|
156 | GB_ERROR error = get_region()->read(in, get_root(), version); |
---|
157 | if (!error) error = sec_expect_closing_bracket(in); |
---|
158 | return error; |
---|
159 | } |
---|
160 | |
---|
161 | GB_ERROR SEC_helix::read(istream & in, int version, double& old_angle_in) { |
---|
162 | const char *string_buffer = sec_read_line(in); |
---|
163 | GB_ERROR error = 0; |
---|
164 | |
---|
165 | old_angle_in = NAN; // illegal for version >= 3 |
---|
166 | |
---|
167 | if (version >= 3) { |
---|
168 | double angle; |
---|
169 | |
---|
170 | error = sec_expect_keyword_and_doubles(string_buffer, "REL", 3, &angle, 0); |
---|
171 | |
---|
172 | if (!error) { |
---|
173 | string_buffer = sec_read_line(in); |
---|
174 | set_rel_angle(angle); |
---|
175 | } |
---|
176 | } |
---|
177 | else { // version 2 or lower |
---|
178 | double angle; |
---|
179 | |
---|
180 | error = sec_expect_keyword_and_doubles(string_buffer, "DELTA", 5, &angle, 0); |
---|
181 | if (!error) { |
---|
182 | string_buffer = sec_read_line(in); |
---|
183 | set_abs_angle(angle); |
---|
184 | |
---|
185 | if (version == 2) { |
---|
186 | error = sec_expect_keyword_and_doubles(string_buffer, "DELTA_IN", 8, &angle, 0); |
---|
187 | |
---|
188 | if (!error) { |
---|
189 | string_buffer = sec_read_line(in); |
---|
190 | old_angle_in = angle+M_PI; // rotate! (DELTA_IN pointed from outside-loop to strand) |
---|
191 | } |
---|
192 | } |
---|
193 | else { |
---|
194 | old_angle_in = angle; // use strands angle |
---|
195 | } |
---|
196 | } |
---|
197 | } |
---|
198 | |
---|
199 | if (!error) error = sec_expect_constraints(string_buffer, "LENGTH", 6, this); |
---|
200 | |
---|
201 | return error; |
---|
202 | } |
---|
203 | |
---|
204 | |
---|
205 | GB_ERROR SEC_helix_strand::read(SEC_loop *loop_, istream & in, int version) { |
---|
206 | // this points away from root-loop, strand2 points towards root |
---|
207 | |
---|
208 | SEC_helix_strand *strand2 = new SEC_helix_strand; |
---|
209 | |
---|
210 | origin_loop = 0; |
---|
211 | |
---|
212 | SEC_root *root = loop_->get_root(); |
---|
213 | GB_ERROR error = get_region()->read(in, root, version); |
---|
214 | |
---|
215 | double next_loop_angle = NAN; |
---|
216 | |
---|
217 | if (!error) { |
---|
218 | helix_info = new SEC_helix(root, strand2, this); |
---|
219 | origin_loop = loop_; // needed by read() |
---|
220 | error = helix_info->read(in, version, next_loop_angle); |
---|
221 | origin_loop = 0; |
---|
222 | |
---|
223 | if (error) { |
---|
224 | delete helix_info; |
---|
225 | helix_info = 0; |
---|
226 | strand2->helix_info = 0; |
---|
227 | } |
---|
228 | } |
---|
229 | |
---|
230 | if (!error) { |
---|
231 | const char *string_buffer = sec_read_line(in); |
---|
232 | if (strncmp(string_buffer, "LOOP={", 6) != 0) { |
---|
233 | error = GBS_global_string("Strand must be followed by 'LOOP={' (not by '%s')", string_buffer); |
---|
234 | } |
---|
235 | else { |
---|
236 | SEC_loop *new_loop = new SEC_loop(root); |
---|
237 | strand2->origin_loop = new_loop; |
---|
238 | |
---|
239 | error = new_loop->read(strand2, in, version, next_loop_angle); |
---|
240 | |
---|
241 | if (!error) { |
---|
242 | error = strand2->get_region()->read(in, root, version); // Loop is complete, now trailing SEQ information must be read |
---|
243 | string_buffer = sec_read_line(in); // remove closing } from input-stream |
---|
244 | } |
---|
245 | |
---|
246 | if (error) { |
---|
247 | strand2->origin_loop = 0; |
---|
248 | delete new_loop; |
---|
249 | } |
---|
250 | } |
---|
251 | } |
---|
252 | |
---|
253 | // Note: don't delete strand2 in case of error -- it's done by caller via deleting 'this' |
---|
254 | |
---|
255 | sec_assert(origin_loop == 0); |
---|
256 | if (!error) origin_loop = loop_; |
---|
257 | |
---|
258 | return error; |
---|
259 | } |
---|
260 | |
---|
261 | |
---|
262 | |
---|
263 | GB_ERROR SEC_loop::read(SEC_helix_strand *rootside_strand, istream & in, int version, double loop_angle) { |
---|
264 | // loop_angle is only used by old versions<3 |
---|
265 | |
---|
266 | const char *string_buffer = sec_read_line(in); |
---|
267 | GB_ERROR error = sec_expect_constraints(string_buffer, "RADIUS", 6, this); |
---|
268 | |
---|
269 | if (!error) { |
---|
270 | set_fixpoint_strand(rootside_strand); |
---|
271 | |
---|
272 | if (version == 3) { |
---|
273 | string_buffer = sec_read_line(in); |
---|
274 | |
---|
275 | double angle; |
---|
276 | error = sec_expect_keyword_and_doubles(string_buffer, "REL", 3, &angle, 0); |
---|
277 | if (!error) set_rel_angle(angle); |
---|
278 | } |
---|
279 | else { |
---|
280 | set_abs_angle(loop_angle); |
---|
281 | sec_assert(get_rel_angle().valid()); |
---|
282 | } |
---|
283 | } |
---|
284 | |
---|
285 | if (!error) { |
---|
286 | enum { EXPECT_SEGMENT, EXPECT_STRAND } expect = (!rootside_strand && version >= 3) ? EXPECT_STRAND : EXPECT_SEGMENT; |
---|
287 | |
---|
288 | SEC_segment *first_new_segment = 0; |
---|
289 | SEC_helix_strand *first_new_strand = 0; |
---|
290 | SEC_segment *last_segment = 0; |
---|
291 | SEC_helix_strand *last_outside_strand = rootside_strand; |
---|
292 | |
---|
293 | bool done = false; |
---|
294 | while (!done && !error) { |
---|
295 | string_buffer = sec_read_line(in); |
---|
296 | |
---|
297 | if (strncmp(string_buffer, "}", 1) == 0) { |
---|
298 | done = true; |
---|
299 | } |
---|
300 | else if (expect == EXPECT_SEGMENT) { |
---|
301 | if (strncmp(string_buffer, "SEGMENT={", 9) == 0) { |
---|
302 | SEC_segment *new_seg = new SEC_segment; |
---|
303 | |
---|
304 | error = new_seg->read(this, in, version); |
---|
305 | if (!error) { |
---|
306 | if (last_outside_strand) last_outside_strand->set_next_segment(new_seg); |
---|
307 | last_outside_strand = 0; |
---|
308 | last_segment = new_seg; |
---|
309 | |
---|
310 | if (!first_new_segment) first_new_segment = new_seg; |
---|
311 | |
---|
312 | expect = EXPECT_STRAND; |
---|
313 | } |
---|
314 | else delete new_seg; |
---|
315 | } |
---|
316 | else error = GBS_global_string("Expected SEGMENT (in '%s')", string_buffer); |
---|
317 | } |
---|
318 | else { |
---|
319 | sec_assert(expect == EXPECT_STRAND); |
---|
320 | if (strncmp(string_buffer, "STRAND={", 8) == 0) { |
---|
321 | SEC_helix_strand *new_strand = new SEC_helix_strand; |
---|
322 | |
---|
323 | error = new_strand->read(this, in, version); |
---|
324 | if (!error) { |
---|
325 | if (last_segment) last_segment->set_next_strand(new_strand); |
---|
326 | last_outside_strand = new_strand; |
---|
327 | last_segment = 0; |
---|
328 | |
---|
329 | if (!first_new_strand) { |
---|
330 | first_new_strand = new_strand; |
---|
331 | if (!rootside_strand) set_fixpoint_strand(first_new_strand); |
---|
332 | } |
---|
333 | |
---|
334 | expect = EXPECT_SEGMENT; |
---|
335 | } |
---|
336 | else delete new_strand; |
---|
337 | } |
---|
338 | else error = GBS_global_string("Expected STRAND (in '%s')", string_buffer); |
---|
339 | } |
---|
340 | } |
---|
341 | |
---|
342 | if (!error && !first_new_segment) error = "Expected at least one SEGMENT in LOOP{}"; |
---|
343 | if (!error && !first_new_strand && !rootside_strand) error = "Expected at least one STRAND in root-LOOP{}"; |
---|
344 | |
---|
345 | if (!error) { |
---|
346 | if (last_segment) { |
---|
347 | sec_assert(last_segment->get_next_strand() == 0); |
---|
348 | if (rootside_strand) { |
---|
349 | last_segment->set_next_strand(rootside_strand); |
---|
350 | } |
---|
351 | else { // root loop (since version 3) |
---|
352 | last_segment->set_next_strand(first_new_strand); |
---|
353 | } |
---|
354 | } |
---|
355 | else { |
---|
356 | sec_assert(last_outside_strand); |
---|
357 | sec_assert(version<3); // version 3 loops always end with segment |
---|
358 | |
---|
359 | sec_assert(!rootside_strand); // only occurs in root-loop |
---|
360 | last_outside_strand->set_next_segment(first_new_segment); |
---|
361 | |
---|
362 | } |
---|
363 | } |
---|
364 | else { |
---|
365 | if (rootside_strand) rootside_strand->set_next_segment(0); // unlink me from parent |
---|
366 | } |
---|
367 | } |
---|
368 | |
---|
369 | if (error) set_fixpoint_strand(0); |
---|
370 | |
---|
371 | return error; |
---|
372 | } |
---|
373 | |
---|
374 | GB_ERROR SEC_root::read_data(const char *input_string, const char *x_string_in) { |
---|
375 | istringstream in(input_string); |
---|
376 | |
---|
377 | delete xString; |
---|
378 | xString = 0; |
---|
379 | |
---|
380 | GB_ERROR error = 0; |
---|
381 | int version = -1; // version of structure string |
---|
382 | |
---|
383 | sec_assert(db->canDisplay()); |
---|
384 | |
---|
385 | if (!error) { |
---|
386 | const char *string_buffer = sec_read_line(in); |
---|
387 | double firstLoopAngle = 0; |
---|
388 | |
---|
389 | error = sec_expect_keyword_and_ints(string_buffer, "VERSION", 7, &version, 0); // version 3++ |
---|
390 | if (error) { // version < 3! |
---|
391 | version = 2; // or less |
---|
392 | |
---|
393 | int ignoreMaxIndex; |
---|
394 | error = sec_expect_keyword_and_ints(string_buffer, "MAX_INDEX", 9, &ignoreMaxIndex, 0); // version 1+2 |
---|
395 | if (!error) { |
---|
396 | string_buffer = sec_read_line(in); |
---|
397 | error = sec_expect_keyword_and_doubles(string_buffer, "ROOT_ANGLE", 10, &firstLoopAngle, 0); // version 2 only |
---|
398 | if (error) { |
---|
399 | firstLoopAngle += M_PI; |
---|
400 | version = 1; // version 1 had no ROOT_ANGLE entry |
---|
401 | error = 0; |
---|
402 | } |
---|
403 | else { |
---|
404 | firstLoopAngle += M_PI; |
---|
405 | string_buffer = sec_read_line(in); |
---|
406 | } |
---|
407 | } |
---|
408 | } |
---|
409 | else { |
---|
410 | if (version>DATA_VERSION) { |
---|
411 | error = GBS_global_string("Structure has version %i, your ARB can only handle versions up to %i", version, DATA_VERSION); |
---|
412 | } |
---|
413 | else { |
---|
414 | string_buffer = sec_read_line(in); |
---|
415 | } |
---|
416 | } |
---|
417 | |
---|
418 | if (!error) { // && db->canDisplay() |
---|
419 | sec_assert(!xString); |
---|
420 | |
---|
421 | size_t len = strlen(x_string_in); |
---|
422 | size_t exp_len = db->length(); |
---|
423 | |
---|
424 | if (len != exp_len && len != (exp_len+1)) { |
---|
425 | error = GBS_global_string("Wrong xstring-length (found=%zu, expected=%zu-%zu)", |
---|
426 | len, exp_len, exp_len+1); |
---|
427 | } |
---|
428 | else { |
---|
429 | xString = new XString(x_string_in, len, db->length()); |
---|
430 | #if defined(DEBUG) |
---|
431 | size_t xlen = xString->getLength(); // internally one position longer than alignment length |
---|
432 | printf("x_string_in len=%zu\nxlen=%zu\nali_length=%zu\n", strlen(x_string_in), xlen, db->length()); |
---|
433 | #endif // DEBUG |
---|
434 | } |
---|
435 | } |
---|
436 | |
---|
437 | delete_root_loop(); |
---|
438 | |
---|
439 | if (!error) { |
---|
440 | #if defined(DEBUG) |
---|
441 | printf("Reading structure format (version %i)\n", version); |
---|
442 | #endif // DEBUG |
---|
443 | |
---|
444 | if (strncmp(string_buffer, "LOOP={", 6) == 0) { |
---|
445 | SEC_loop *rootLoop = new SEC_loop(this); // , NULL, 0, 0); |
---|
446 | |
---|
447 | set_root_loop(rootLoop); |
---|
448 | set_under_construction(true); |
---|
449 | error = rootLoop->read(NULL, in, version, firstLoopAngle); |
---|
450 | |
---|
451 | if (!error) { |
---|
452 | set_under_construction(false); // mark as "constructed" |
---|
453 | } |
---|
454 | else { |
---|
455 | delete_root_loop(); |
---|
456 | } |
---|
457 | } |
---|
458 | else { |
---|
459 | error = GBS_global_string("Expected root loop ('LOOP={'), not '%s'", string_buffer); |
---|
460 | } |
---|
461 | } |
---|
462 | } |
---|
463 | |
---|
464 | if (!error) { |
---|
465 | if (version<DATA_VERSION) { |
---|
466 | printf("Converting secondary structure from version %i to %i\n", version, DATA_VERSION); |
---|
467 | } |
---|
468 | if (version<3) fixStructureBugs(version); |
---|
469 | #if defined(CHECK_INTEGRITY) |
---|
470 | check_integrity(CHECK_STRUCTURE); |
---|
471 | #endif // CHECK_INTEGRITY |
---|
472 | if (version<3) { |
---|
473 | relayout(); |
---|
474 | root_loop->fixAngleBugs(version); |
---|
475 | } |
---|
476 | } |
---|
477 | |
---|
478 | return error; |
---|
479 | } |
---|
480 | |
---|
481 | void SEC_helix::fixAngleBugs(int version) { |
---|
482 | if (version<3) { |
---|
483 | outsideLoop()->fixAngleBugs(version); // first correct substructure |
---|
484 | |
---|
485 | // versions<3 silently mirrored angles between strand and origin-loop |
---|
486 | // to ensure that strand always points away from loop (and not inside). |
---|
487 | // This correction was done during refresh and therefore not saved to the DB. |
---|
488 | // Since version 3 no angles will be mirrored automatically, so we need to correct them here. |
---|
489 | |
---|
490 | Vector loop2strand(rootsideLoop()->get_center(), get_fixpoint()); |
---|
491 | if (scalarProduct(loop2strand, get_abs_angle().normal()) < 0) { // < 0 means angle is an acute angle |
---|
492 | printf("* Autofix acute angle (loop2strand=%.2f, abs=%.2f) of helix nr '%s'\n", |
---|
493 | Angle(loop2strand).radian(), |
---|
494 | get_abs_angle().radian(), |
---|
495 | get_root()->helixNrAt(strandToOutside()->startAttachAbspos())); |
---|
496 | set_rel_angle(Angle(get_rel_angle()).rotate180deg()); |
---|
497 | } |
---|
498 | } |
---|
499 | } |
---|
500 | |
---|
501 | void SEC_loop::fixAngleBugs(int version) { |
---|
502 | if (version<3) { |
---|
503 | for (SEC_strand_iterator strand(this); strand; ++strand) { |
---|
504 | if (strand->pointsToOutside()) { |
---|
505 | strand->get_helix()->fixAngleBugs(version); |
---|
506 | } |
---|
507 | } |
---|
508 | } |
---|
509 | } |
---|
510 | |
---|
511 | void SEC_root::fixStructureBugs(int version) { |
---|
512 | if (version < 3) { |
---|
513 | // old versions produced data structure with non-adjacent regions |
---|
514 | SEC_base_part *start_part = root_loop->get_fixpoint_strand(); |
---|
515 | SEC_base_part *part = start_part; |
---|
516 | SEC_region *reg = part->get_region(); |
---|
517 | |
---|
518 | do { |
---|
519 | SEC_base_part *next_part = part->next(); |
---|
520 | SEC_region *next_reg = next_part->get_region(); |
---|
521 | |
---|
522 | if (!are_adjacent_regions(reg, next_reg)) { |
---|
523 | printf("* Fixing non-adjacent regions: %i..%i and %i..%i\n", |
---|
524 | reg->get_sequence_start(), reg->get_sequence_end(), |
---|
525 | next_reg->get_sequence_start(), next_reg->get_sequence_end()); |
---|
526 | |
---|
527 | // known bug occurs at segment->strand transition.. |
---|
528 | sec_assert(part->parent()->getType() == SEC_LOOP); |
---|
529 | |
---|
530 | // .. and segment region ends one position too early |
---|
531 | sec_assert(get_helixDef()->helixNr(reg->get_sequence_end()) == 0); |
---|
532 | sec_assert(get_helixDef()->helixNr(next_reg->get_sequence_start()) != 0); |
---|
533 | |
---|
534 | // make them adjacent |
---|
535 | reg->set_sequence_portion(reg->get_sequence_start(), next_reg->get_sequence_start()); |
---|
536 | } |
---|
537 | |
---|
538 | part = next_part; |
---|
539 | reg = next_reg; |
---|
540 | } |
---|
541 | while (part != start_part); |
---|
542 | } |
---|
543 | } |
---|