1 // ==========================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ==========================================================================
4 // Copyright (c) 2006-2015, Knut Reinert, FU Berlin
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // * Redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution.
15 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
16 // its contributors may be used to endorse or promote products derived
17 // from this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29 // DAMAGE.
30 //
31 // ==========================================================================
32 // Author: Andreas Gogol-Doering <andreas.doering@mdc-berlin.de>
33 // Author: Manuel Holtgrewe <manuel.holtgrewe@fu-berlin.de>
34 // ==========================================================================
35
36 // SEQAN_NO_GENERATED_FORWARDS
37
38 // TODO(holtgrew): Currently, operations are a function of the whole gap count, could be of clipped region only.
39 // TODO(holtgrew): Problem with the gap value, getValue(), value().
40
41 #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ARRAY_H_
42 #define SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ARRAY_H_
43
44 namespace seqan {
45
46 // ============================================================================
47 // Forwards
48 // ============================================================================
49
50 // Internally used tag for creating iterators at the begin of containers.
51 struct Begin__;
52 typedef Tag<Begin__> Begin_;
53
54 // Internally used tag for creating iterators at the end of containers.
55 struct End__;
56 typedef Tag<End__> End_;
57
58 // Internally used tag for creating iterators inside of containers.
59 struct Position__;
60 typedef Tag<Position__> Position_;
61
62 struct ArrayGaps_;
63 typedef Tag<ArrayGaps_> ArrayGaps;
64
65 template <typename TSequence> class Gaps<TSequence, ArrayGaps>;
66
67 template <typename TSequence>
68 inline void _reinitArrayGaps(Gaps<TSequence, ArrayGaps> & gaps);
69
70 // ============================================================================
71 // Tags, Classes, Enums
72 // ============================================================================
73
74 struct ArrayGaps_;
75 typedef Tag<ArrayGaps_> ArrayGaps;
76
77 /*!
78 * @class ArrayGaps
79 * @headerfile <seqan/align.h>
80 * @extends Gaps
81 * @brief Stores length of gap- and non-gap runs in an array.
82 *
83 * @signature template <typename TSequence>
84 * class Gaps<TSequence, ArrayGaps>
85 *
86 * @tparam TSequence The type of the underling sequence.
87 */
88
89 /*!
90 * @fn ArrayGaps::Gaps
91 * @headerfile <seqan/align.h>
92 * @brief Constructor.
93 *
94 * @signature Gaps::Gaps([other]);
95 * @signature Gaps::Gaps(seq);
96 *
97 * @param[in] other Other Gaps object to copy from.
98 * @param[in] seq Sequence concept to construct the gaps for.
99 */
100
101 template <typename TSequence>
102 class Gaps<TSequence, ArrayGaps>
103 {
104 public:
105 // -----------------------------------------------------------------------
106 // Internal Typedefs
107 // -----------------------------------------------------------------------
108
109 typedef typename Size<Gaps>::Type TSize_;
110 typedef typename Size<TSequence>::Type TSequenceSize_;
111 typedef typename Position<Gaps>::Type TPosition_;
112 typedef typename Position<TSequence>::Type TSequencePosition_;
113 typedef typename Value<Gaps>::Type TValue_;
114
115 typedef String<TSequenceSize_> TArray_;
116 typedef typename Position<TArray_>::Type TArrayPos_;
117
118 // -----------------------------------------------------------------------
119 // Member Variables
120 // -----------------------------------------------------------------------
121
122 // Holder of the underlying sequence.
123 Holder<TSequence> _source;
124
125 // The array with the alternating gap/source char counts.
126 TArray_ _array;
127
128 // Begin and end position in the source.
129 TSequencePosition_ _sourceBeginPos, _sourceEndPos;
130 // Begin and end position in the view.
131 TPosition_ _clippingBeginPos, _clippingEndPos;
132 // TODO(holtgrew): The following is a possible optimization.
133 // // Index of clipping begin and end in the _array seq/gap char count array.
134 // // This identifies a slice of the view.
135 // TArrayPos_ _clippingBeginIdx, _clippingEndIdx;
136 // // Offset within the slice.
137 // TSequenceSize_ _clippingBeginOffset, _clippingEndOffset;
138
139 // -----------------------------------------------------------------------
140 // Constructors
141 // -----------------------------------------------------------------------
142
Gaps()143 Gaps() : _sourceBeginPos(0), _sourceEndPos(0), _clippingBeginPos(0), _clippingEndPos(0)//,
144 // _clippingBeginIdx(0), _clippingEndIdx(0), _clippingBeginOffset(0), _clippingEndOffset(0)
145 {}
146
147 explicit
Gaps(TSequence & seq)148 Gaps(TSequence & seq) :
149 _source(seq), _sourceBeginPos(0), _sourceEndPos(length(seq)),
150 _clippingBeginPos(0), _clippingEndPos(length(seq))//,
151 // _clippingBeginIdx(0), _clippingEndIdx(0), _clippingBeginOffset(0),
152 // _clippingEndOffset(0)
153 {
154 // Initialize array gaps object for ungapped sequence.
155 _reinitArrayGaps(*this);
156 }
157
Gaps(Gaps const & other)158 Gaps(Gaps const & other) :
159 _source(other._source), _array(other._array), _sourceBeginPos(other._sourceBeginPos),
160 _sourceEndPos(other._sourceEndPos), _clippingBeginPos(other._clippingBeginPos),
161 _clippingEndPos(other._clippingEndPos)
162 {}
163
164 // -----------------------------------------------------------------------
165 // Array Subscript Operator
166 // -----------------------------------------------------------------------
167
168 inline Gaps &
169 operator=(Gaps const & other)
170 {
171 setValue(_source, source(other));
172 _array = other._array;
173 _sourceBeginPos = other._sourceBeginPos;
174 _sourceEndPos = other._sourceEndPos;
175 _clippingBeginPos = other._clippingBeginPos;
176 _clippingEndPos = other._clippingEndPos;
177 return *this;
178 }
179
180 // -----------------------------------------------------------------------
181 // Array Subscript Operator
182 // -----------------------------------------------------------------------
183
184 inline TValue_
185 operator[](TPosition_ clippedViewPos) const
186 {
187 return value(*this, clippedViewPos);
188 }
189 };
190
191 // ----------------------------------------------------------------------------
192 // Function swap()
193 // ----------------------------------------------------------------------------
194
195 template <typename TSequence>
swap(Gaps<TSequence,ArrayGaps> & lhs,Gaps<TSequence,ArrayGaps> & rhs)196 void swap(Gaps<TSequence, ArrayGaps> & lhs, Gaps<TSequence, ArrayGaps> & rhs)
197 {
198 swap(lhs._source, rhs._source);
199 swap(lhs._array, rhs._array);
200
201 std::swap(lhs._sourceBeginPos, rhs._sourceBeginPos);
202 std::swap(lhs._sourceEndPos, rhs._sourceEndPos);
203 std::swap(lhs._clippingBeginPos, rhs._clippingBeginPos);
204 std::swap(lhs._clippingEndPos, rhs._clippingEndPos);
205 }
206
207 // ============================================================================
208 // Metafunctions
209 // ============================================================================
210
211 // ============================================================================
212 // Functions
213 // ============================================================================
214
215 // ----------------------------------------------------------------------------
216 // Function detach()
217 // ----------------------------------------------------------------------------
218
219 // TODO(holtgrew): Remove? Only used by module blast.
220
221 template <typename TSequence>
detach(Gaps<TSequence,ArrayGaps> & gaps)222 void detach(Gaps<TSequence, ArrayGaps> & gaps)
223 {
224 detach(gaps._source);
225 }
226
227 // ----------------------------------------------------------------------------
228 // Function _setLength()
229 // ----------------------------------------------------------------------------
230
231 // Set the length, only use if TSequence is Nothing.
232
233 template <typename TSequence, typename TSize>
_setLength(Gaps<TSequence,ArrayGaps> & gaps,TSize newLen)234 inline void _setLength(Gaps<TSequence, ArrayGaps> & gaps, TSize newLen)
235 {
236 // Reset array.
237 resize(gaps._array, 3);
238 gaps._array[0] = 0;
239 gaps._array[1] = newLen;
240 gaps._array[2] = 0;
241 // Reset clipping information.
242 gaps._clippingBeginPos = 0;
243 gaps._clippingEndPos = newLen;
244 gaps._sourceBeginPos = 0;
245 gaps._sourceEndPos = gaps._clippingEndPos;
246 // gaps._clippingBeginIdx = 1;
247 // gaps._clippingBeginOffset = 0;
248 // gaps._clippingEndIdx = 1;
249 // gaps._clippingEndOffset = value(gaps._source)[1];
250 }
251
252 // ----------------------------------------------------------------------------
253 // Helper Function _reinitArrayGaps()
254 // ----------------------------------------------------------------------------
255
256 // Reset the array gaps DS such that represents the ungapped sequence.
257
258 template <typename TSequence>
_reinitArrayGaps(Gaps<TSequence,ArrayGaps> & gaps)259 inline void _reinitArrayGaps(Gaps<TSequence, ArrayGaps> & gaps)
260 {
261 _setLength(gaps, length(value(gaps._source)));
262 }
263
264 // ----------------------------------------------------------------------------
265 // Function begin()
266 // ----------------------------------------------------------------------------
267
268 // TODO(holtgrew): We'd rather have "TTag const &" here.
269 template <typename TSequence, typename TTag>
270 inline typename Iterator<Gaps<TSequence, ArrayGaps> >::Type
begin(Gaps<TSequence,ArrayGaps> & gaps,Tag<TTag> const)271 begin(Gaps<TSequence, ArrayGaps> & gaps, Tag<TTag> const /*tag*/)
272 {
273 typedef typename Iterator<Gaps<TSequence, ArrayGaps> >::Type TIter;
274 return TIter(gaps, Begin_());
275 }
276
277 // TODO(holtgrew): We'd rather have "TTag const &" here.
278 template <typename TSequence, typename TTag>
279 inline typename Iterator<Gaps<TSequence, ArrayGaps> const>::Type
begin(Gaps<TSequence,ArrayGaps> const & gaps,Tag<TTag> const)280 begin(Gaps<TSequence, ArrayGaps> const & gaps, Tag<TTag> const /*tag*/)
281 {
282 typedef typename Iterator<Gaps<TSequence, ArrayGaps> const>::Type TIter;
283 return TIter(gaps, Begin_());
284 }
285
286 // ----------------------------------------------------------------------------
287 // Function end()
288 // ----------------------------------------------------------------------------
289
290 // TODO(holtgrew): We'd rather have "TTag const &" here.
291 template <typename TSequence, typename TTag>
292 inline typename Iterator<Gaps<TSequence, ArrayGaps> >::Type
end(Gaps<TSequence,ArrayGaps> & gaps,Tag<TTag> const)293 end(Gaps<TSequence, ArrayGaps> & gaps, Tag<TTag> const /*tag*/)
294 {
295 typedef typename Iterator<Gaps<TSequence, ArrayGaps> >::Type TIter;
296 return TIter(gaps, End_());
297 }
298
299 // TODO(holtgrew): We'd rather have "TTag const &" here.
300 template <typename TSequence, typename TTag>
301 inline typename Iterator<Gaps<TSequence, ArrayGaps> const>::Type
end(Gaps<TSequence,ArrayGaps> const & gaps,Tag<TTag> const)302 end(Gaps<TSequence, ArrayGaps> const & gaps, Tag<TTag> const /*tag*/)
303 {
304 typedef typename Iterator<Gaps<TSequence, ArrayGaps> const>::Type TIter;
305 return TIter(gaps, End_());
306 }
307
308 // ----------------------------------------------------------------------------
309 // Function iter()
310 // ----------------------------------------------------------------------------
311
312 // TODO(holtgrew): We'd rather have "TTag const &" here.
313 template <typename TSequence, typename TTag, typename TPosition>
314 inline typename Iterator<Gaps<TSequence, ArrayGaps> >::Type
iter(Gaps<TSequence,ArrayGaps> & gaps,TPosition pos,Tag<TTag> const)315 iter(Gaps<TSequence, ArrayGaps> & gaps, TPosition pos, Tag<TTag> const /*tag*/)
316 {
317 typedef typename Iterator<Gaps<TSequence, ArrayGaps> >::Type TIter;
318 return TIter(gaps, pos, Position_());
319 }
320
321 // TODO(holtgrew): We'd rather have "TTag const &" here.
322 template <typename TSequence, typename TTag, typename TPosition>
323 inline typename Iterator<Gaps<TSequence, ArrayGaps> const>::Type
iter(Gaps<TSequence,ArrayGaps> const & gaps,TPosition pos,Tag<TTag> const)324 iter(Gaps<TSequence, ArrayGaps> const & gaps, TPosition pos, Tag<TTag> const /*tag*/)
325 {
326 typedef typename Iterator<Gaps<TSequence, ArrayGaps> const>::Type TIter;
327 return TIter(gaps, pos, Position_());
328 }
329
330 // ----------------------------------------------------------------------------
331 // Function length()
332 // ----------------------------------------------------------------------------
333
334 template <typename TSequence>
335 inline typename Size<Gaps<TSequence, ArrayGaps> >::Type
length(Gaps<TSequence,ArrayGaps> const & gaps)336 length(Gaps<TSequence, ArrayGaps> const & gaps)
337 {
338 SEQAN_ASSERT_GEQ(gaps._clippingEndPos, gaps._clippingBeginPos);
339 return gaps._clippingEndPos - gaps._clippingBeginPos;
340 }
341
342 // ----------------------------------------------------------------------------
343 // Function unclippedLength()
344 // ----------------------------------------------------------------------------
345
346 template <typename TSequence>
347 inline typename Size<Gaps<TSequence, ArrayGaps> >::Type
unclippedLength(Gaps<TSequence,ArrayGaps> const & gaps)348 unclippedLength(Gaps<TSequence, ArrayGaps> const & gaps)
349 {
350 typedef typename Size<Gaps<TSequence, ArrayGaps> >::Type TSize;
351
352 TSize result = 0;
353 for (unsigned i = 0; i < length(gaps._array); ++i)
354 result += gaps._array[i];
355
356 return result;
357 }
358
359 // ----------------------------------------------------------------------------
360 // Function createSource()
361 // ----------------------------------------------------------------------------
362
363 // TODO(holtgrew): Remove? Switch to Hosted Type Interface?
364
365 template <typename TSequence>
createSource(Gaps<TSequence,ArrayGaps> & gaps)366 inline void createSource(Gaps<TSequence, ArrayGaps> & gaps)
367 {
368 create(gaps._source);
369 }
370
371 // ----------------------------------------------------------------------------
372 // Function source()
373 // ----------------------------------------------------------------------------
374
375 template <typename TSequence>
376 inline typename Source<Gaps<TSequence, ArrayGaps> const>::Type &
source(Gaps<TSequence,ArrayGaps> const & gaps)377 source(Gaps<TSequence, ArrayGaps> const & gaps)
378 {
379 return value(gaps._source);
380 }
381
382 template <typename TSequence>
383 inline typename Source<Gaps<TSequence, ArrayGaps> >::Type &
source(Gaps<TSequence,ArrayGaps> & gaps)384 source(Gaps<TSequence, ArrayGaps> & gaps)
385 {
386 return value(gaps._source);
387 }
388
389 // ----------------------------------------------------------------------------
390 // Function setSource()
391 // ----------------------------------------------------------------------------
392
393 // TODO(holtgrew): Test with clippings, also for AnchorGaps.
394
395 template <typename TSequence>
396 inline void
setSource(Gaps<TSequence,ArrayGaps> & gaps,TSequence & source)397 setSource(Gaps<TSequence, ArrayGaps> & gaps, TSequence & source)
398 {
399 setValue(gaps._source, source);
400 _reinitArrayGaps(gaps);
401 }
402
403 template <typename TSequence>
404 inline void
setSource(Gaps<TSequence const,ArrayGaps> & gaps,TSequence & source)405 setSource(Gaps<TSequence const, ArrayGaps> & gaps, TSequence & source)
406 {
407 setValue(gaps._source, source);
408 _reinitArrayGaps(gaps);
409 }
410
411 // ----------------------------------------------------------------------------
412 // Function assignSource()
413 // ----------------------------------------------------------------------------
414
415 template <typename TSequence, typename TSequence2>
416 inline void
assignSource(Gaps<TSequence,ArrayGaps> & gaps,TSequence2 const & source)417 assignSource(Gaps<TSequence, ArrayGaps> & gaps, TSequence2 const & source)
418 {
419 value(gaps._source) = source;
420 _reinitArrayGaps(gaps);
421 }
422
423 // ----------------------------------------------------------------------------
424 // Function toSourcePosition()
425 // ----------------------------------------------------------------------------
426
427 template <typename TSequence, typename TPosition>
428 inline typename Position<TSequence>::Type
toSourcePosition(Gaps<TSequence,ArrayGaps> const & gaps,TPosition clippedViewPos)429 toSourcePosition(Gaps<TSequence, ArrayGaps> const & gaps, TPosition clippedViewPos)
430 {
431 typedef Gaps<TSequence, ArrayGaps> TGaps;
432 typedef typename Position<TGaps>::Type TGapsPos;
433 typedef typename TGaps::TArrayPos_ TArrayPos;
434 typedef typename Position<TSequence>::Type TSourcePos;
435
436 // Translate from clipped view position to unclipped view position.
437 TGapsPos unclippedViewPos = clippedViewPos + clippedBeginPosition(gaps);
438
439 // Get index i of the according bucket and offset within bucket.
440 TSourcePos result = 0;
441 TArrayPos i = 0;
442 TSourcePos const iEnd = length(gaps._array);
443 for (TSourcePos counter = unclippedViewPos; counter > TGapsPos(0) && i < iEnd;)
444 {
445 if (counter > gaps._array[i])
446 {
447 if (i % 2) // character bucket
448 result += gaps._array[i];
449 counter -= gaps._array[i];
450 i += 1;
451 }
452 else if (counter <= gaps._array[i])
453 {
454 if (i % 2) // character bucket
455 {
456 result += counter;
457 }
458 counter = 0;
459 }
460 }
461
462 return result;
463 }
464
465 // ----------------------------------------------------------------------------
466 // Function toViewPosition()
467 // ----------------------------------------------------------------------------
468
469 // Parameter rightOfGaps moves to the right end of gaps if the character at sourcePosition is followed by a gap in the
470 // view.
471 template <typename TSequence, typename TPosition>
472 inline typename Position<Gaps<TSequence, ArrayGaps> >::Type
473 toViewPosition(Gaps<TSequence, ArrayGaps> const & gaps, TPosition sourcePosition, bool rightOfGaps = true)
474 {
475 typedef Gaps<TSequence, ArrayGaps> TGaps;
476 typedef typename Position<TGaps>::Type TGapsPosition;
477 typedef typename TGaps::TArray_ TArray;
478 typedef typename TGaps::TArrayPos_ TArrayPos;
479 typedef typename Value<TArray>::Type TArrayValue;
480
481 if (sourcePosition == TPosition(0))
482 return gaps._array[0] - clippedBeginPosition(gaps);
483
484 // First, convert to unclipped source position.
485 TGapsPosition unclippedViewPosition = 0;
486 TArrayPos i = 0;
487 for (TArrayValue counter = sourcePosition; counter > TArrayValue(0); ++i)
488 {
489 if (i % 2 /*== 1*/) // sequence bucket
490 {
491 if (counter > gaps._array[i])
492 {
493 unclippedViewPosition += gaps._array[i];
494 counter -= gaps._array[i];
495 }
496 else if (counter < gaps._array[i])
497 {
498 unclippedViewPosition += counter;
499 counter = 0;
500 }
501 else // counter == gaps._array[i]
502 {
503 unclippedViewPosition += counter;
504 if (rightOfGaps && i + 2 < length(gaps._array))
505 unclippedViewPosition += gaps._array[i + 1];
506 counter = 0;
507 }
508 }
509 else // gaps bucket
510 {
511 unclippedViewPosition += gaps._array[i];
512 }
513 }
514
515 // Return after clipping.
516 return unclippedViewPosition - clippedBeginPosition(gaps);
517 }
518
519 // ----------------------------------------------------------------------------
520 // Function insertGaps()
521 // ----------------------------------------------------------------------------
522
523 template <typename TSequence, typename TPosition, typename TCount>
524 inline void
insertGaps(Gaps<TSequence,ArrayGaps> & gaps,TPosition clippedViewPos,TCount count)525 insertGaps(Gaps<TSequence, ArrayGaps> & gaps, TPosition clippedViewPos, TCount count)
526 {
527 typedef Gaps<TSequence, ArrayGaps> TGaps;
528 typedef typename Position<TGaps>::Type TGapsPosition;
529 typedef typename TGaps::TArray_ TArray;
530 typedef typename TGaps::TArrayPos_ TArrayPos;
531 typedef typename Position<TSequence>::Type TSeqPos;
532
533 // Translate from clipped view position to unclipped view position.
534 TGapsPosition unclippedViewPos = clippedViewPos + clippedBeginPosition(gaps);
535
536 // Get index i of the according bucket and offset within bucket.
537 TArrayPos i = 0;
538 TSeqPos offset = 0;
539 for (TSeqPos counter = unclippedViewPos; counter > 0;)
540 {
541 SEQAN_ASSERT_LT(i, length(gaps._array));
542 if (counter > gaps._array[i])
543 {
544 counter -= gaps._array[i];
545 i += 1;
546 }
547 else
548 {
549 offset = counter;
550 counter = 0;
551 }
552 }
553
554 SEQAN_ASSERT_GEQ(gaps._array[i], offset);
555
556 // Insert gaps, simple and fast if we are in a gaps bucket, a bit harder
557 // otherwise.
558 if (i % 2) // character bucket
559 {
560 if (gaps._array[i] > offset) // In the middle of the bucket.
561 {
562 TArray arr;
563 resize(arr, 2, 0);
564 arr[0] = count;
565 arr[1] = gaps._array[i] - offset;
566 gaps._array[i] = offset;
567 insert(gaps._array, i + 1, arr);
568 }
569 else // At the end of the bucket.
570 {
571 if (i + 1 < length(gaps._array)) // Not at end of array.
572 {
573 gaps._array[i + 1] += count;
574 }
575 else // At end of array.
576 {
577 resize(gaps._array, length(gaps._array) + 2, 0);
578 gaps._array[i + 1] = count;
579 gaps._array[i + 2] = 0;
580 }
581 }
582 }
583 else // gap bucket
584 {
585 gaps._array[i] += count;
586 }
587
588 // Adjust clipping information.
589 gaps._clippingEndPos += count;
590 }
591
592 // ----------------------------------------------------------------------------
593 // Function value()
594 // ----------------------------------------------------------------------------
595
596 template <typename TSequence, typename TPosition>
597 inline typename Value<Gaps<TSequence, ArrayGaps> >::Type
value(Gaps<TSequence,ArrayGaps> const & gaps,TPosition clippedViewPos)598 value(Gaps<TSequence, ArrayGaps> const & gaps, TPosition clippedViewPos)
599 {
600 if (isGap(gaps, clippedViewPos))
601 return '-';
602 else
603 return value(source(gaps), toSourcePosition(gaps, clippedViewPos));
604 return typename Value<Gaps<TSequence, ArrayGaps> >::Type();
605 }
606
607 // ----------------------------------------------------------------------------
608 // Function removeGaps()
609 // ----------------------------------------------------------------------------
610
611 template <typename TSequence, typename TPosition, typename TCount>
612 inline typename Size<Gaps<TSequence, ArrayGaps> >::Type
removeGaps(Gaps<TSequence,ArrayGaps> & gaps,TPosition clippedViewPos,TCount count)613 removeGaps(Gaps<TSequence, ArrayGaps> & gaps, TPosition clippedViewPos, TCount count)
614 {
615 typedef Gaps<TSequence, ArrayGaps> TGaps;
616 typedef typename Position<TGaps>::Type TGapsPosition;
617 typedef typename TGaps::TArray_ TArray;
618 typedef typename TGaps::TArrayPos_ TArrayPos;
619 typedef typename Value<TArray>::Type TArrayValue;
620 typedef typename Position<TSequence>::Type TSeqPos;
621
622 // Translate from clipped view position to unclipped view position.
623 TGapsPosition pos = clippedViewPos + clippedBeginPosition(gaps);
624
625 // Get index i of the according bucket and offset within bucket.
626 SEQAN_ASSERT_GEQ(length(gaps._array), 2u);
627 // Start at position 1 if there are no leading gaps.
628 TArrayPos i = (gaps._array[0] == 0);
629 TSeqPos offset = 0;
630 for (TSeqPos counter = pos; counter > 0;)
631 {
632 SEQAN_ASSERT_LT(i, length(gaps._array));
633 if (counter > gaps._array[i])
634 {
635 counter -= gaps._array[i];
636 i += 1;
637 }
638 else
639 {
640 offset = counter;
641 counter = 0;
642 }
643 }
644
645 // Advance into next bucket if at end of current.
646 if (offset > 0 && offset == gaps._array[i])
647 {
648 i += 1;
649 offset = 0;
650 }
651
652 // If we are inside a non-gap bucket then we cannot remove any gaps.
653 if (i % 2)
654 return 0;
655
656 // Otherwise, we can remove gaps right of the current position but not
657 // more than there are.
658 TSeqPos toRemove = count;
659 if (toRemove > gaps._array[i] - offset)
660 toRemove = gaps._array[i] - offset;
661 gaps._array[i] -= toRemove;
662 // In some cases, we remove the whole gap and merge the character buckets.
663 if (gaps._array[i] == TArrayValue(0))
664 {
665 // No merging for leading and trailing gap.
666 if (i != TArrayPos(0) && i != TArrayPos(length(gaps._array) - 1))
667 {
668 gaps._array[i - 1] += gaps._array[i + 1];
669 erase(gaps._array, i, i + 2);
670 }
671 }
672
673 // Also update the right clipping position.
674 gaps._clippingEndPos -= toRemove;
675
676 // Finally, return number of removed gaps.
677 return toRemove;
678 }
679
680 // ----------------------------------------------------------------------------
681 // Function clearGaps()
682 // ----------------------------------------------------------------------------
683
684 template <typename TSequence>
685 inline void
clearGaps(Gaps<TSequence,ArrayGaps> & gaps)686 clearGaps(Gaps<TSequence, ArrayGaps> & gaps)
687 {
688 _reinitArrayGaps(gaps);
689 }
690
691 // ----------------------------------------------------------------------------
692 // Function clear()
693 // ----------------------------------------------------------------------------
694
695 template <typename TSequence>
696 inline void
clear(Gaps<TSequence,ArrayGaps> & gaps)697 clear(Gaps<TSequence, ArrayGaps> & gaps)
698 {
699 clear(gaps._source);
700 clear(gaps._array);
701 gaps._sourceBeginPos = 0;
702 gaps._sourceEndPos = 0;
703 gaps._clippingBeginPos = 0;
704 gaps._clippingEndPos = 0;
705 // cannot use clearGaps() here, since that calls value() on _source
706 // which instates the Holder to Owner; we want it to be empty
707 }
708
709 // ----------------------------------------------------------------------------
710 // Function isGap()
711 // ----------------------------------------------------------------------------
712
713 template <typename TSequence, typename TPosition>
714 inline bool
isGap(Gaps<TSequence,ArrayGaps> const & gaps,TPosition clippedViewPos)715 isGap(Gaps<TSequence, ArrayGaps> const & gaps, TPosition clippedViewPos)
716 {
717 typedef Gaps<TSequence, ArrayGaps> TGaps;
718 typedef typename Position<TGaps>::Type TGapsPosition;
719 typedef typename TGaps::TArrayPos_ TArrayPos;
720 typedef typename Position<TSequence>::Type TSeqPos;
721
722 // Translate from clipped view position to unclipped view position.
723 TGapsPosition pos = clippedViewPos + clippedBeginPosition(gaps);
724
725 // Get index i of the according bucket and offset within bucket.
726 SEQAN_ASSERT_GEQ(length(gaps._array), 2u);
727 // Start at position 1 if there are no leading gaps.
728 TArrayPos i = (gaps._array[0] == 0);
729 TSeqPos offset = 0;
730 for (TSeqPos counter = pos; counter > TSeqPos(0);)
731 {
732 SEQAN_ASSERT_LT(i, length(gaps._array));
733 if (counter > gaps._array[i])
734 {
735 counter -= gaps._array[i];
736 i += 1;
737 }
738 else
739 {
740 offset = counter;
741 counter = 0;
742 }
743 }
744
745 // Advance into next bucket if at end of current.
746 if (offset > TSeqPos(0) && offset == gaps._array[i])
747 i += 1;
748
749 return !(i % 2);
750 }
751
752 // ----------------------------------------------------------------------------
753 // Function clearClipping()
754 // ----------------------------------------------------------------------------
755
756 template <typename TSequence>
757 inline void
clearClipping(Gaps<TSequence,ArrayGaps> & gaps)758 clearClipping(Gaps<TSequence, ArrayGaps> & gaps)
759 {
760 typedef Gaps<TSequence, ArrayGaps> TGaps;
761 typedef typename TGaps::TArrayPos_ TArrayPos;
762
763 gaps._sourceBeginPos = 0;
764 gaps._sourceEndPos = length(value(gaps._source));
765 gaps._clippingBeginPos = 0;
766 gaps._clippingEndPos = 0;
767 for (TArrayPos i = 0; i < length(gaps._array); ++i)
768 gaps._clippingEndPos += gaps._array[i];
769
770 SEQAN_ASSERT_LEQ(static_cast<int>(gaps._sourceEndPos), static_cast<int>(gaps._clippingEndPos));
771 }
772
773 // ----------------------------------------------------------------------------
774 // Function setClippedBeginPosition()
775 // ----------------------------------------------------------------------------
776
777 template <typename TSequence, typename TPosition>
778 inline void
setClippedBeginPosition(Gaps<TSequence,ArrayGaps> & gaps,TPosition unclippedViewPosition)779 setClippedBeginPosition(Gaps<TSequence, ArrayGaps> & gaps, TPosition unclippedViewPosition)
780 {
781 gaps._sourceBeginPos = toSourcePosition(gaps, unclippedViewPosition - clippedBeginPosition(gaps));
782 gaps._clippingBeginPos = unclippedViewPosition;
783 }
784
785 // ----------------------------------------------------------------------------
786 // Function setClippedEndPosition()
787 // ----------------------------------------------------------------------------
788
789 template <typename TSequence, typename TPosition>
790 inline void
setClippedEndPosition(Gaps<TSequence,ArrayGaps> & gaps,TPosition unclippedViewPosition)791 setClippedEndPosition(Gaps<TSequence, ArrayGaps> & gaps, TPosition unclippedViewPosition)
792 {
793 gaps._sourceEndPos = toSourcePosition(gaps, unclippedViewPosition - clippedBeginPosition(gaps));
794 //if (isGap(gaps, unclippedViewPosition - clippedBeginPosition(gaps)))
795 // gaps._sourceEndPos += 1;
796 gaps._clippingEndPos = unclippedViewPosition;
797 }
798
799 // ----------------------------------------------------------------------------
800 // Function clippedBeginPosition()
801 // ----------------------------------------------------------------------------
802
803 template <typename TSequence>
804 inline typename Position<Gaps<TSequence, ArrayGaps> >::Type
clippedBeginPosition(Gaps<TSequence,ArrayGaps> const & gaps)805 clippedBeginPosition(Gaps<TSequence, ArrayGaps> const & gaps)
806 {
807 return gaps._clippingBeginPos;
808 }
809
810 // ----------------------------------------------------------------------------
811 // Function clippedEndPosition()
812 // ----------------------------------------------------------------------------
813
814 template <typename TSequence>
815 inline typename Position<Gaps<TSequence, ArrayGaps> >::Type
clippedEndPosition(Gaps<TSequence,ArrayGaps> const & gaps)816 clippedEndPosition(Gaps<TSequence, ArrayGaps> const & gaps)
817 {
818 return gaps._clippingEndPos;
819 }
820
821 // ----------------------------------------------------------------------------
822 // Function setBeginPosition()
823 // ----------------------------------------------------------------------------
824
825 template <typename TSequence, typename TPosition>
826 inline void
setBeginPosition(Gaps<TSequence,ArrayGaps> & gaps,TPosition sourcePosition)827 setBeginPosition(Gaps<TSequence, ArrayGaps> & gaps, TPosition sourcePosition)
828 {
829 setClippedBeginPosition(gaps, toViewPosition(gaps, sourcePosition) + clippedBeginPosition(gaps));
830 }
831
832 // ----------------------------------------------------------------------------
833 // Function setEndPosition()
834 // ----------------------------------------------------------------------------
835
836 template <typename TSequence, typename TPosition>
837 inline void
setEndPosition(Gaps<TSequence,ArrayGaps> & gaps,TPosition sourcePosition)838 setEndPosition(Gaps<TSequence, ArrayGaps> & gaps, TPosition sourcePosition)
839 {
840 setClippedEndPosition(gaps, toViewPosition(gaps, sourcePosition) + clippedBeginPosition(gaps));
841 }
842
843 // ----------------------------------------------------------------------------
844 // Function beginPosition()
845 // ----------------------------------------------------------------------------
846
847 // TODO(holtgrew): We would rather like to have the const version only :(
848 template <typename TSequence>
849 inline typename Position<TSequence>::Type
beginPosition(Gaps<TSequence,ArrayGaps> const & gaps)850 beginPosition(Gaps<TSequence, ArrayGaps> const & gaps)
851 {
852 return gaps._sourceBeginPos;
853 }
854
855 template <typename TSequence>
856 inline typename Position<TSequence>::Type
beginPosition(Gaps<TSequence,ArrayGaps> & gaps)857 beginPosition(Gaps<TSequence, ArrayGaps> & gaps)
858 {
859 return gaps._sourceBeginPos;
860 }
861
862 // ----------------------------------------------------------------------------
863 // Function endPosition()
864 // ----------------------------------------------------------------------------
865
866 // TODO(holtgrew): We would rather like to have the const version only :(
867 template <typename TSequence>
868 inline typename Position<TSequence>::Type
endPosition(Gaps<TSequence,ArrayGaps> const & gaps)869 endPosition(Gaps<TSequence, ArrayGaps> const & gaps)
870 {
871 return gaps._sourceEndPos;
872 }
873
874 template <typename TSequence>
875 inline typename Position<ArrayGaps>::Type
endPosition(Gaps<TSequence,ArrayGaps> & gaps)876 endPosition(Gaps<TSequence, ArrayGaps> & gaps)
877 {
878 return gaps._sourceEndPos;
879 }
880
881 } // namespace seqan
882
883 #endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ARRAY_H_
884