source: tags/ms_r18q1/SECEDIT/SEC_structure.cxx

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