source: tags/arb_5.5/SECEDIT/SEC_structure.cxx

Last change on this file was 6017, checked in by westram, 15 years ago
  • do not insert \n into error (\n will not display in secedit main window)
  • rename (SEC_root) get_helix → get_helixDef (get_helix is duplicated in SEC_helix_strand)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.1 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : SEC_structure.cxx                                 //
4//   Purpose   : general implementation of classes in SEC_root.hxx //
5//                                                                 //
6//   Coded by Ralf Westram (coder@reallysoft.de) in August 2007    //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#include "SEC_root.hxx"
13#include "SEC_iter.hxx"
14
15using namespace std;
16
17// ---------------------
18//      Constructors
19// ---------------------
20
21SEC_segment::SEC_segment()
22    : alpha(0)
23    , center1(Origin)
24    , center2(Origin)
25    , next_helix_strand(0)
26    , loop(0)
27{}
28
29SEC_helix_strand::SEC_helix_strand()
30    : origin_loop(0)
31    , other_strand(0)
32    , helix_info(0)
33    , next_segment(0)
34    , fixpoint(Origin)
35    , rightAttach(Origin)
36    , leftAttach(Origin)
37{}
38
39SEC_loop::SEC_loop(SEC_root *root_)
40    : SEC_base(root_)
41    , Circumferance(0)
42    , center(0, 0)
43    , primary_strand(0)
44{}
45
46SEC_helix::SEC_helix(SEC_root *root_, SEC_helix_strand *to_root, SEC_helix_strand *from_root)
47    : SEC_base(root_)
48    , strand_to_root(to_root)
49    , base_length(0)
50{
51    sec_assert(to_root->get_helix()     == 0);
52    sec_assert(from_root->get_helix()   == 0);
53    sec_assert(to_root->get_other_strand()   == 0);
54    sec_assert(from_root->get_other_strand() == 0);
55
56    to_root->set_other_strand(from_root);
57    from_root->set_other_strand(to_root);
58
59    to_root->set_helix_info(this);
60    from_root->set_helix_info(this);
61}
62
63
64SEC_root::SEC_root()
65    : root_loop(0)
66    , cursorAbsPos(-1)
67    , xString(0)
68    , constructing(false)
69    , db(0)
70    , bg_color(0)
71    , autoscroll(0)
72    , nailedAbsPos(-1)
73    , drawnPositions(0)
74    , cursor_line(LineVector(Origin, ZeroVector))
75    , show_constraints(SEC_NO_TYPE)
76{
77}
78
79
80void SEC_root::init(SEC_graphic *gfx, AWT_canvas *ntw) {
81    // canvas   = ntw;
82    db = new SEC_db_interface(gfx, ntw);
83}
84
85// --------------------
86//      Destructors
87// --------------------
88
89SEC_region::SEC_region(int start, int end)
90    : sequence_start(start)
91    , sequence_end(end)
92    , baseCount(-1)
93    , abspos_array(NULL)
94#if defined(DEBUG)
95    , abspos_array_size(0)
96#endif // DEBUG
97{
98    sec_assert((start == -1 && end == -1) || start != end);
99}
100
101SEC_region::~SEC_region() {
102    invalidate_base_count();                        // frees abspos_array
103    delete [] abspos_array;
104}
105
106SEC_segment::~SEC_segment() {
107}
108
109
110SEC_helix_strand::~SEC_helix_strand() {
111    if(next_segment != NULL) {
112        next_segment->delete_pointer_2(this);
113    }
114
115    delete helix_info;
116
117    if (other_strand != NULL) {
118        if (other_strand->next_segment != NULL) {
119            other_strand->next_segment->delete_pointer_2(other_strand);
120        }
121        other_strand->helix_info = NULL;
122        other_strand->other_strand = NULL;
123        other_strand->next_segment = NULL;
124        delete other_strand;
125    }
126
127    delete origin_loop;
128}
129
130
131#define SEG_MAX 20
132
133SEC_loop::~SEC_loop() {
134    if (primary_strand) {
135        sec_assert(get_root()->get_root_loop() != this);
136
137        // collect all segments in an array
138        SEC_segment *segment[SEG_MAX];
139        int          i = 0;
140
141        for (SEC_strand_iterator strand(this); strand; ++strand) {
142            SEC_segment *seg = strand->get_next_segment();
143            if (seg) {
144                sec_assert(i < SEG_MAX);
145                sec_assert(seg->get_loop() == this);
146
147                segment[i++] = seg;
148            }
149        }
150
151        set_fixpoint_strand(NULL); // disconnect from loop
152
153        // delete all strands connected to loop
154        int j;
155        for (j=0; j<i; j++) {
156            SEC_helix_strand *strand = segment[j]->get_next_strand();
157            if (strand) {
158                sec_assert(strand->get_origin_loop() == this);
159                strand->set_origin_loop(NULL);
160                delete strand;
161            }
162        }
163        // delete all segments connected to loop
164        for (j=0; j<i; j++) delete segment[j];       
165    }
166}
167
168SEC_root::~SEC_root() {
169    delete db;
170    delete autoscroll;
171
172    delete_root_loop();
173
174    free(bg_color);
175
176    delete_announced_positions();
177}
178
179// -------------------------
180//      integrity checks
181// -------------------------
182
183#if defined(CHECK_INTEGRITY)
184
185void SEC_region::check_integrity(const SEC_root *root, SEC_CHECK_TYPE what) const {
186    if (what&CHECK_SIZE) {
187        sec_assert(baseCount >= 0);
188        if (baseCount>0) {
189            sec_assert(abspos_array || !root->get_db()->canDisplay());
190        }
191    }
192}
193
194void SEC_segment::check_integrity(SEC_CHECK_TYPE what) const {
195    if (what&CHECK_STRUCTURE) {
196        sec_assert(next_helix_strand != 0);
197        sec_assert(loop == parent());
198    }
199    if (what&CHECK_SIZE) {
200        sec_assert(alpha == alpha);
201        sec_assert(alpha != 0);
202    }
203    if (what&CHECK_POSITIONS) {
204        sec_assert(center1.valid());
205        sec_assert(center2.valid());
206    }
207    get_region()->check_integrity(get_root(), what);
208}
209
210void SEC_helix_strand::check_integrity(SEC_CHECK_TYPE what) const {
211    if (what&CHECK_STRUCTURE) {
212        sec_assert(other_strand != this);
213        sec_assert(other_strand->other_strand == this);
214        sec_assert(helix_info);
215        sec_assert(helix_info == other_strand->helix_info);
216        sec_assert(parent() == helix_info);
217    }
218    if (what&CHECK_SIZE) {
219        get_region()->get_base_count(); // asserts base count is up-to-date
220    }
221    if (what&CHECK_POSITIONS) {
222        sec_assert(fixpoint.valid());
223        sec_assert(rightAttach.valid());
224        sec_assert(leftAttach.valid());
225    }
226    get_region()->check_integrity(get_root(), what);
227}
228
229void SEC_helix::check_integrity(SEC_CHECK_TYPE what) const {
230    sec_assert(strand_to_root);
231   
232    SEC_helix_strand *other_strand = strand_to_root->get_other_strand();
233    sec_assert(other_strand);
234
235    if (what&CHECK_STRUCTURE) {
236        sec_assert(strand_to_root->get_helix()      == this);
237        sec_assert(other_strand->get_other_strand() == strand_to_root);
238        sec_assert(get_rel_angle().valid());
239        sec_assert(parent()                         == rootsideLoop());
240    }
241
242    if (what&CHECK_SIZE) {
243        sec_assert(base_length >= 1);
244        sec_assert(drawnSize() >= 0);
245    }
246   
247    strand_to_root->check_integrity(what);
248    other_strand->check_integrity(what);
249}
250
251void SEC_loop::check_integrity(SEC_CHECK_TYPE what) const {
252    int count       = 0;
253    int rootStrands = 0;
254
255    if (what&CHECK_STRUCTURE) {
256        sec_assert(primary_strand);
257        sec_assert(primary_strand->get_origin_loop() == this);
258        sec_assert(get_rel_angle().valid());
259    }
260
261    for (SEC_strand_const_iterator strand(this); strand; ++strand) {
262        if (what&CHECK_STRUCTURE) {
263            sec_assert(this == strand->get_origin_loop());
264        }
265       
266        const SEC_helix *helix = strand->get_helix();
267        if (this == helix->rootsideLoop()) { // test outgoing helixes
268            helix->check_integrity(what);
269        }
270        else {
271            rootStrands++;
272        }
273       
274        const SEC_segment *seg = strand->get_next_segment();
275
276        if (what&CHECK_STRUCTURE) {
277            sec_assert(this == seg->get_loop());
278        }
279        seg->check_integrity(what);
280        count++;
281        sec_assert(count<100);  // more than 100 segments in one loop! assume error in structure!
282    }
283
284    if (what&CHECK_STRUCTURE) {
285        if (is_root_loop()) {
286            sec_assert(!rootStrands);
287            sec_assert(primary_strand->pointsToOutside());
288            sec_assert(parent() == 0);
289        }
290        else {
291            sec_assert(rootStrands);
292            sec_assert(primary_strand->pointsToRoot());
293            sec_assert(parent() == get_rootside_helix());
294        }
295    }
296
297    if (what&CHECK_SIZE) {
298        sec_assert(Circumferance>0);
299        sec_assert(drawnSize()>0);
300    }
301    if (what&CHECK_POSITIONS) {
302        sec_assert(center.valid());
303        if (is_root_loop()) {
304            sec_assert(isOrigin(center));
305        }
306    }
307
308    // now recurse downwards
309    for (SEC_strand_const_iterator strand(this); strand; ++strand) {
310        SEC_loop *outsideLoop = strand->get_helix()->outsideLoop();
311        if (outsideLoop != this) outsideLoop->check_integrity(what);
312    }
313}
314
315void SEC_root::check_integrity(SEC_CHECK_TYPE what) const {
316    if (root_loop) {
317        sec_assert(!under_construction()); // cannot check integrity, when structure is under construction
318   
319        root_loop->check_integrity(what);
320
321        // check whether structure is a ring and whether regions are correct
322
323        const SEC_base_part *start_part = root_loop->get_fixpoint_strand();
324        const SEC_base_part *part       = start_part;
325        const SEC_region    *region     = part->get_region();
326
327        int count = 0;
328        do {
329            const SEC_base_part *next_part   = part->next();
330            const SEC_region    *next_region = next_part->get_region();
331
332            sec_assert(are_adjacent_regions(region, next_region));
333
334            part   = next_part;
335            region = next_region;
336
337            count++;
338            sec_assert(count<10000); // structure does not seem to be a ring
339        }
340        while (part != start_part);
341    }
342}
343#endif // CHECK_INTEGRITY
344
345// --------------------------------
346//      unlink strands/segments
347// --------------------------------
348
349void SEC_helix_strand::unlink(bool fromOtherStrandAsWell) {
350    // if called with fromOtherStrandAsWell == false,
351    // the strand-pair remains deletable
352   
353    next_segment = NULL;
354    origin_loop  = NULL;
355
356    if (fromOtherStrandAsWell) other_strand = NULL;
357}
358
359void SEC_segment::unlink(void) {
360    next_helix_strand = NULL;
361}
362
363// -----------------------------
364//      split/merge segments
365// -----------------------------
366
367SEC_helix_strand *SEC_segment::split(size_t start, size_t end, SEC_segment **segment2_ptr) {
368    // split segment into 'segment1 - strand - segment2'
369    // segment2 still points to same loop as 'this' (must be corrected by caller)
370    // strand is a single strand (must be connected by caller)
371
372    sec_assert(get_region()->contains_seq_position(start));
373    sec_assert(get_region()->contains_seq_position(end-1));
374
375    SEC_helix_strand *strand   = new SEC_helix_strand;
376    SEC_segment      *segment2 = new SEC_segment;
377
378    segment2->set_sequence_portion(end, get_region()->get_sequence_end());
379    strand->set_sequence_portion(start, end);
380    set_sequence_portion(get_region()->get_sequence_start(), start);
381
382    segment2->set_loop(get_loop()); // set to same loop as this (must be corrected later)
383    strand->set_origin_loop(get_loop());
384
385    segment2->set_next_strand(get_next_strand());
386    set_next_strand(strand);
387
388    *segment2_ptr = segment2;
389
390    return strand;
391}
392
393void SEC_segment::mergeWith(SEC_segment *other, SEC_loop *target_loop) {
394    set_sequence_portion(get_region()->get_sequence_start(),
395                         other->get_region()->get_sequence_end());
396
397    set_next_strand(other->get_next_strand());
398    set_loop(target_loop);
399    delete other;
400}
401
402// ---------------------
403//      Reset angles
404// ---------------------
405
406void SEC_loop::reset_angles() {
407    for (SEC_strand_iterator strand(this); strand; ++strand) {
408        if (strand->pointsToOutside()) {
409            Angle abs(center, strand->get_fixpoint());
410            strand->get_helix()->set_abs_angle(abs);
411        }
412    }
413    set_rel_angle(0); 
414}
415
416void SEC_helix::reset_angles() {
417    outsideLoop()->set_rel_angle(0);
418    SEC_loop *rloop = rootsideLoop();
419
420    Angle toFix(rloop->get_center(), strandToOutside()->get_fixpoint());
421    set_abs_angle(toFix);
422}
423
424
425// --------------
426//      other
427// --------------
428
429size_t SEC_base_part::getNextAbspos() const {
430    // returns the next valid abspos
431    const SEC_region *reg   = get_region();
432    int               start = reg->get_sequence_start();
433
434    if (start != reg->get_sequence_end()) {
435        return start;
436    }
437    return next()->getNextAbspos();
438}
439
440
441SEC_segment *SEC_helix_strand::get_previous_segment(void) {
442    SEC_segment *segment_before;
443    SEC_helix_strand *strand_pointer = next_segment->get_next_strand();
444
445    if (strand_pointer == this) {
446        segment_before = next_segment;   //we are in a loop with only one segment
447    }
448    else {
449        while (strand_pointer != this) {
450            segment_before = strand_pointer->get_next_segment();
451            strand_pointer = segment_before->get_next_strand();
452        }
453    }
454    return segment_before;
455}
456
457static void findLongestHelix(const BI_helix *helix, size_t& start1, size_t& end1, size_t& start2, size_t& end2) {
458    const char *longestHelixNr = 0;
459    size_t      longestLength  = 0;
460
461    const char *lastHelixNr  = 0;
462    size_t      lastHelixLen = 0;
463    for (long pos = helix->first_pair_position(); pos != -1; pos = helix->next_pair_position(pos)) {
464        const char *currHelixNr = helix->helixNr(size_t(pos));
465        if (currHelixNr != lastHelixNr) {
466            if (lastHelixLen>longestLength) {
467                longestLength  = lastHelixLen;
468                longestHelixNr = lastHelixNr;
469            }
470            lastHelixNr  = currHelixNr;
471            lastHelixLen = 1;
472        }
473        else {
474            lastHelixLen++;
475        }
476    }
477   
478    if (lastHelixLen>longestLength) {
479        longestLength  = lastHelixLen;
480        longestHelixNr = lastHelixNr;
481    }
482
483    sec_assert(longestHelixNr);
484    start1 = helix->first_position(longestHelixNr);
485    end1   = helix->last_position(longestHelixNr);
486    start2 = helix->opposite_position(end1);
487    end2   = helix->opposite_position(start1);
488}
489
490void SEC_root::create_default_bone() {
491    // create default structure
492
493    set_under_construction(true);
494   
495    SEC_loop *loop1 = new SEC_loop(this);
496    SEC_loop *loop2 = new SEC_loop(this);
497
498    set_root_loop(loop1);
499
500    SEC_segment *segment1 = new SEC_segment;
501    SEC_segment *segment2 = new SEC_segment;
502
503    segment1->set_loop(loop1);
504    segment2->set_loop(loop2);
505
506    SEC_helix_strand *strand1 = new SEC_helix_strand;
507    SEC_helix_strand *strand2 = new SEC_helix_strand;
508
509    loop1->set_fixpoint_strand(strand1);
510    loop2->set_fixpoint_strand(strand2);
511
512    segment1->set_next_strand(strand1);
513    segment2->set_next_strand(strand2);
514
515    strand1->set_origin_loop(loop1);
516    strand2->set_origin_loop(loop2);
517
518    SEC_helix *helix = new SEC_helix(this, strand1, strand2);
519
520    strand1->set_next_segment(segment1);
521    strand2->set_next_segment(segment2);
522
523    size_t start1, end1, start2, end2;
524    findLongestHelix(get_helixDef(), start1, end1, start2, end2);
525
526    strand1->set_sequence_portion(start1, end1+1); segment2->set_sequence_portion(end1+1, start2);
527    strand2->set_sequence_portion(start2, end2+1); segment1->set_sequence_portion(end2+1, start1);
528   
529    root_loop = helix->rootsideLoop();
530   
531    loop1->set_rel_angle(0);
532    loop2->set_rel_angle(0);
533    helix->set_rel_angle(0);
534
535    root_loop->mark_angle_absolute();
536    root_loop->set_center(Origin);
537
538    set_under_construction(false);
539
540    delete xString;
541    xString = 0;
542    generate_x_string();
543
544    relayout();
545}
546
Note: See TracBrowser for help on using the repository browser.