ARB
SEC_structure.cxx
Go to the documentation of this file.
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 
15 using namespace std;
16 
17 // ----------------------
18 // Constructors
19 
20 SEC_segment::SEC_segment()
21  : alpha(0),
22  center1(Origin),
23  center2(Origin),
24  next_helix_strand(NULp),
25  loop(NULp)
26 {}
27 
28 SEC_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 
38 SEC_loop::SEC_loop(SEC_root *root_)
39  : SEC_base(root_),
40  Circumference(0),
41  center(0, 0),
42  primary_strand(NULp)
43 {}
44 
45 SEC_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 
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 
82 void 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 
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 
102  invalidate_base_count(); // frees abspos_array
103  delete [] abspos_array;
104 }
105 
106 SEC_segment::~SEC_segment() {
107 }
108 
109 
110 SEC_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 
133 SEC_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 
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 
184 void 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 
193 void 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 
209 void 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 
228 void 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 
250 void 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 
314 void 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 
347 void 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 
357 void SEC_segment::unlink() {
358  next_helix_strand = NULp;
359 }
360 
361 // ------------------------------
362 // split/merge segments
363 
364 SEC_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 
390 void 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 
402 void 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 
412 void 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 
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 
436 SEC_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 
452 static 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 
483  // create default structure
484 
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;
535 
536  relayout();
537 }
538 
void set_under_construction(bool construct)
Definition: SEC_root.hxx:745
void invalidate_base_count()
Definition: SEC_layout.cxx:266
int get_sequence_start() const
Definition: SEC_root.hxx:107
const SEC_db_interface * get_db() const
Definition: SEC_root.hxx:747
int get_sequence_end() const
Definition: SEC_root.hxx:108
bool are_adjacent_regions(const SEC_region *reg1, const SEC_region *reg2)
Definition: SEC_root.hxx:993
void relayout()
Definition: SEC_root.hxx:803
const BI_helix * get_helixDef() const
Definition: SEC_root.hxx:750
void create_default_bone()
size_t getNextAbspos() const
long first_position(const char *helixNr) const
Definition: BI_helix.cxx:373
size_t opposite_position(size_t pos) const
Definition: BI_helix.hxx:96
#define SEG_MAX
STL namespace.
SEC_region(int start, int end)
void init(SEC_graphic *gfx, AWT_canvas *scr, ED4_plugin_host &host)
#define SEC_GC_DATA_COUNT
Definition: SEC_gc.hxx:55
static HelixNrInfo * start
long last_position(const char *helixNr) const
Definition: BI_helix.cxx:381
const Vector ZeroVector
bool isOrigin(const Position &p)
virtual ~SEC_region()
long first_pair_position() const
Definition: BI_helix.cxx:346
#define false
Definition: ureadseq.h:13
const SEC_region * get_region() const
Definition: SEC_root.hxx:304
long next_pair_position(size_t pos) const
Definition: BI_helix.cxx:350
GB_write_int const char GB_write_autoconv_string WRITE_SKELETON(write_pointer, GBDATA *,"%p", GB_write_pointer) char *AW_awa if)(!gb_var) return strdup("")
Definition: AW_awar.cxx:166
const char * helixNr(size_t pos) const
Definition: BI_helix.hxx:102
CONSTEXPR_INLINE bool valid(SpeciesCreationMode m)
Definition: ed4_class.hxx:2249
SEC_base_part * next()
Definition: SEC_root.hxx:301
bool canDisplay() const
Definition: SEC_db.hxx:149
bool under_construction() const
Definition: SEC_root.hxx:744
#define abs(x)
Definition: f2c.h:151
void generate_x_string()
Definition: SEC_io.cxx:23
#define NULp
Definition: cxxforward.h:97
void set_root_loop(SEC_loop *loop)
Definition: SEC_root.hxx:836
const Position Origin
#define sec_assert(cond)
Definition: SEC_defs.hxx:19
static void findLongestHelix(const BI_helix *helix, size_t &start1, size_t &end1, size_t &start2, size_t &end2)