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