source: branches/profile/SL/FAST_ALIGNER/seq_search.hxx

Last change on this file was 8932, checked in by westram, 12 years ago
  • CompactedSubSequence
    • use generic assignment-operator
    • use SmartPtr instead of homegrown ref-counting
  • CompactedSequence
    • removed friend
    • made class public (no longer dangerous)
  • FastSearchSequence derived from Noncopyable (private cctor/assop removed)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.8 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : seq_search.hxx                                    //
4//   Purpose   : Fast sequence search for fast aligner             //
5//                                                                 //
6//   Coded by Ralf Westram (coder@reallysoft.de) in July 1998      //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#ifndef SEQ_SEARCH_HXX
13#define SEQ_SEARCH_HXX
14
15#ifndef AW_BASE_HXX
16#include <aw_base.hxx>
17#endif
18#ifndef ARBDB_BASE_H
19#include <arbdb_base.h>
20#endif
21#ifndef AW_MSG_HXX
22#include <aw_msg.hxx>
23#endif
24#ifndef ATTRIBUTES_H
25#include <attributes.h>
26#endif
27#ifndef BI_BASEPOS_HXX
28#include <BI_basepos.hxx>
29#endif
30
31
32#define fa_assert(bed) arb_assert(bed)
33
34#define SEQ_CHARS   26
35#define MAX_TRIPLES (SEQ_CHARS*SEQ_CHARS*SEQ_CHARS+1) // one faked triple for all non-char triples
36#define GAP_CHARS   ".-~?"      // Characters treated as gaps
37
38inline int max(int i1, int i2) { return i1>i2 ? i1 : i2; }
39inline bool is_ali_gap(char c)  { return strchr(GAP_CHARS, c)!=0; }
40
41class Dots : virtual Noncopyable {
42    // here we store dots ('.') which were deleted when compacting sequences
43    long  BeforeBase; // this position is the "compressed" position
44    Dots *Next;
45
46public:
47
48    Dots(long before_base) {
49        BeforeBase = before_base;
50        Next       = NULL;
51    }
52    ~Dots() {
53        delete Next;
54    }
55
56    void append(Dots *neu);
57    long beforeBase() const { return BeforeBase; }
58    const Dots *next() const { return Next; }
59};
60
61class CompactedSequence : virtual Noncopyable {
62    // compacts a string (gaps removed, all chars upper)
63    // Dont use this class directly - better use CompactedSubSequence
64   
65    BasePosition  basepos;            // relatice <-> absolute position
66    char         *myName;             // sequence name
67    char         *myText;             // sequence w/o gaps (uppercase)
68    int           myStartOffset;      // expanded offsets of first and last position in 'text' (which is given to the c-tor)
69    int          *gapsBeforePosition; // gapsBeforePosition[ idx+1 ] = gaps _after_ position 'idx'
70    Dots         *dots;               // Dots which were deleted from the sequence are stored here
71
72public: 
73   
74    CompactedSequence(const char *text, int length, const char *name, int start_offset=0);
75    ~CompactedSequence();
76
77    const char *get_name() const { return myName; }
78   
79    int length() const                  { return basepos.base_count(); }
80    const char *text(int i=0) const     { return myText+i; }
81    char operator[](int i) const        { return i<0 || i>=length() ? 0 : text()[i]; }
82
83    int expdPosition(int cPos) const {
84        // cPos is [0..N]
85        // for cPos == N this returns the total length of the original sequence
86        fa_assert(cPos>=0 && cPos<=length());
87        return
88            (cPos   == length()
89             ? basepos.abs_count()
90             : basepos.rel_2_abs(cPos))
91            + myStartOffset;
92    }
93
94    int compPosition(int xPos) const {
95        // returns the number of bases left of 'xPos' (not including bases at 'xPos')
96        return basepos.abs_2_rel(xPos-myStartOffset);
97    }
98
99    const int *gapsBefore(int offset=0) const { return gapsBeforePosition + offset; }
100
101    int no_of_gaps_before(int cPos) const {
102        // returns -1 if 'cPos' is no legal compressed position
103        int leftMostGap;
104        if (cPos>0) {
105            leftMostGap = expdPosition(cPos-1)+1;
106        }
107        else {
108            leftMostGap = myStartOffset;
109        }
110        return expdPosition(cPos)-leftMostGap;
111    }
112    int no_of_gaps_after(int cPos) const {
113        // returns -1 if 'cPos' is no legal compressed position
114        int rightMostGap;
115        if (cPos<(length()-1)) {
116            rightMostGap = expdPosition(cPos+1)-1;
117        }
118        else {
119            rightMostGap = basepos.abs_count()+myStartOffset-1;
120        }
121        return rightMostGap-expdPosition(cPos);
122    }
123
124    void storeDots(int beforePos) {
125        if (dots)     dots->append(new Dots(beforePos));
126        else            dots = new Dots(beforePos);
127    }
128
129    const Dots *getDotlist() const { return dots; }
130};
131
132class CompactedSubSequence { // substring class for CompactedSequence
133    SmartPtr<CompactedSequence> mySeq;
134
135    int myPos;                             // offset into mySeq->myText
136    int myLength;                          // number of base positions
137   
138    const char         *myText;            // only for speed-up
139    mutable const Dots *dots;              // just a reference
140
141    int currentDotPosition() const {
142        int pos = dots->beforeBase()-myPos;
143
144        if (pos>(myLength+1)) {
145            dots = NULL;
146            pos = -1;
147        }
148
149        return pos;
150    }
151
152public:
153
154    CompactedSubSequence(const char *seq, int length_, const char *name_, int start_offset=0)
155        : mySeq(new CompactedSequence(seq, length_, name_, start_offset)),
156          myPos(0),
157          myLength(mySeq->length()),
158          myText(mySeq->text()+myPos),
159          dots(NULL)
160    {}
161
162    CompactedSubSequence(const CompactedSubSequence& other)
163        : mySeq(other.mySeq),
164          myPos(other.myPos),
165          myLength(other.myLength),
166          myText(other.myText),
167          dots(NULL)
168    {}
169    CompactedSubSequence(const CompactedSubSequence& other, int rel_pos, int length_)
170        : mySeq(other.mySeq),
171          myPos(other.myPos + rel_pos),
172          myLength(length_),
173          myText(mySeq->text()+myPos),
174          dots(NULL)
175    {}
176    DECLARE_ASSIGNMENT_OPERATOR(CompactedSubSequence);
177
178    int length() const { return myLength; }
179
180    const char *text() const      { return myText; }
181    const char *text(int i) const { return text()+i; }
182
183    const char *name() const { return mySeq->get_name(); }
184
185    char operator[](int i) const                { return i<0 || i>=length() ? 0 : text()[i]; }
186
187    int no_of_gaps_before(int cPos) const       { return mySeq->no_of_gaps_before(myPos+cPos); }
188    int no_of_gaps_after(int cPos) const        { return mySeq->no_of_gaps_after(myPos+cPos); }
189
190    int expdStartPosition() const               { return mySeq->expdPosition(myPos); }
191    int expdPosition(int cPos) const {
192        fa_assert(cPos>=0 && cPos<=myLength);                 // allowed for all positions plus follower
193        return mySeq->expdPosition(myPos+cPos);
194    }
195
196    int compPosition(int xPos) const            { return mySeq->compPosition(xPos)-myPos; }
197
198    int expdLength() const                      { return expdPosition(length()); }
199    const int *gapsBefore(int offset=0) const   { return mySeq->gapsBefore(myPos + offset); }
200
201    int firstDotPosition() const {
202        dots = mySeq->getDotlist();
203        int res = -1;
204
205        while (dots && dots->beforeBase()<myPos) {
206            dots = dots->next();
207        }
208        if (dots) {
209            res = currentDotPosition();
210        }
211
212        return res;
213    }
214
215    int nextDotPosition() const {
216        int res = -1;
217        if (dots) {
218            dots = dots->next();
219        }
220        if (dots) {
221            res = currentDotPosition();
222        }
223        return res;
224    }
225
226#if defined(ASSERTION_USED)
227    bool may_refer_to_same_part_as(const CompactedSubSequence& other) const {
228        return length() == other.length() &&
229            strcmp(text(), other.text()) == 0;
230    }
231#endif
232};
233
234class SequencePosition {
235    // pointer to character position in CompactedSubSequence
236    const CompactedSubSequence *mySequence;
237    long                        myPos;
238    const char                 *myText;
239
240    int distanceTo(const SequencePosition& other) const    { fa_assert(mySequence==other.mySequence); return myPos-other.myPos; }
241
242public:
243
244    SequencePosition(const CompactedSubSequence& seq, long pos=0)
245        : mySequence(&seq),
246          myPos(pos),
247          myText(seq.text(pos)) {}
248    SequencePosition(const SequencePosition& pos, long offset=0)
249        : mySequence(pos.mySequence),
250          myPos(pos.myPos+offset),
251          myText(pos.myText+offset) {}
252    ~SequencePosition() {}
253    DECLARE_ASSIGNMENT_OPERATOR(SequencePosition);
254
255    const char *text() const                     { return myText; }
256    const CompactedSubSequence& sequence() const { return *mySequence; }
257
258    long expdPosition() const     { return sequence().expdPosition(myPos); }
259    long expdPosition(int offset) { return sequence().expdPosition(myPos+offset); }
260
261    SequencePosition& operator++() { myPos++; myText++; return *this; }
262    SequencePosition& operator--() { myPos--; myText--; return *this; }
263
264    SequencePosition& operator+=(long l) { myPos += l; myText += l; return *this; }
265    SequencePosition& operator-=(long l) { myPos -= l; myText -= l; return *this; }
266
267    int operator<(const SequencePosition& other) const { return distanceTo(other)<0; }
268    int operator>(const SequencePosition& other) const { return distanceTo(other)>0; }
269
270    long leftOf() const  { return myPos; }
271    long rightOf() const { return mySequence->length()-myPos; }
272};
273
274class TripleOffset : virtual Noncopyable {
275    // a list of offsets (used in FastSearchSequence)
276    long          myOffset;                         // compacted offset
277    TripleOffset *myNext;
278
279    void IV() const     { fa_assert(myNext!=this); }
280
281public:
282
283    TripleOffset(long Offset, TripleOffset *next_toff) : myOffset(Offset), myNext(next_toff) { IV(); }
284    ~TripleOffset() { delete myNext; }
285
286    TripleOffset *next() const { IV(); return myNext; }
287    long offset() const { IV(); return myOffset; }
288};
289
290
291class AlignBuffer : virtual Noncopyable {
292    // alignment result buffer
293    char *myBuffer;
294    char *myQuality;
295
296    // myQuality contains the following chars:
297    //
298    // '?'      base was just inserted (not aligned)
299    // '-'      master and slave are equal
300    // '+'      gap in master excl-or slave
301    // '~'      master base and slave base are related
302    // '#'      master base and slave base are NOT related (mismatch)
303
304    long mySize;
305    long used;
306
307    void set_used(long newVal) {
308        fa_assert(newVal<=mySize);
309        used = newVal;
310    }
311    void add_used(long toAdd) {
312        set_used(toAdd+used);
313    }
314
315    int isGlobalGap(long off) {
316        // TRUE if gap in slave AND master
317        return (myBuffer[off]=='-' || myBuffer[off]=='.') && myQuality[off]=='-';
318    }
319    void moveUnaligned(long from, long to) {
320        myBuffer[to] = myBuffer[from];
321        myQuality[to] = myQuality[from];
322        myBuffer[from] = '-';
323        myQuality[from] = '-';
324    }
325
326public:
327
328    AlignBuffer(long size) {
329        mySize = size;
330        set_used(0);
331        myBuffer = new char[size+1];
332        myBuffer[size] = 0;
333        myQuality = new char[size+1];
334        myQuality[size] = 0;
335    }
336    ~AlignBuffer() {
337        delete [] myBuffer;
338        delete [] myQuality;
339    }
340
341    const char *text() const            { fa_assert(free()>=0); myBuffer[used]=0;  return myBuffer; }
342    const char *quality() const         { fa_assert(free()>=0); myQuality[used]=0; return myQuality; }
343    long length() const                 { return used; }
344
345    long offset() const                 { return used; }
346    long free() const                   { return mySize-used; }
347
348    void copy(const char *s, char q, long len) {
349        fa_assert(len<=free());
350        memcpy(myBuffer+used, s, len);
351        memset(myQuality+used, q, len);
352        add_used(len);
353    }
354    void set(char c, char q) {
355        fa_assert(free()>=1);
356        myBuffer[used] = c;
357        myQuality[used] = q;
358        add_used(1);
359    }
360    void set(char c, char q, long len) {
361        fa_assert(len<=free());
362        memset(myBuffer+used, c, len);
363        memset(myQuality+used, q, len);
364        add_used(len);
365    }
366    void reset(long newOffset=0) {
367        fa_assert(newOffset>=0 && newOffset<mySize);
368        set_used(newOffset);
369    }
370
371    void correctUnalignedPositions();
372
373    void restoreDots(CompactedSubSequence& slaveSequence);
374    void setDotsAtEOSequence();
375};
376
377
378class FastAlignInsertion : virtual Noncopyable {
379    long insert_at_offset;
380    long inserted_gaps;
381
382    FastAlignInsertion *myNext;
383
384public:
385    FastAlignInsertion(long Offset, long Gaps) {
386        insert_at_offset = Offset;
387        inserted_gaps    = Gaps;
388        myNext           = 0;
389    }
390    ~FastAlignInsertion();
391
392    FastAlignInsertion *append(long Offset, long Gaps) {
393        return myNext = new FastAlignInsertion(Offset, Gaps);
394    }
395    void dump() const {
396        printf(" offset=%5li gaps=%3li\n", insert_at_offset, inserted_gaps);
397    }
398    void dumpAll() const {
399        dump();
400        if (myNext) myNext->dumpAll();
401    }
402
403    const FastAlignInsertion *next() const { return myNext; }
404    long offset() const { return insert_at_offset; }
405    long gaps() const { return inserted_gaps; }
406};
407
408
409class FastAlignReport : virtual Noncopyable {
410    // alignment report
411    long  alignedBases;
412    long  mismatchedBases;      // in aligned part
413    long  unalignedBases;
414    char *my_master_name;
415    bool  showGapsMessages;     // display messages about missing gaps in master
416
417    FastAlignInsertion *first; // list of insertions (order is important)
418    FastAlignInsertion *last;
419
420public:
421
422    FastAlignReport(const char *master_name, bool show_Gaps_Messages) {
423        alignedBases     = 0;
424        mismatchedBases  = 0;
425        unalignedBases   = 0;
426        first            = 0;
427        last             = 0;
428        my_master_name   = strdup(master_name);
429        showGapsMessages = show_Gaps_Messages;
430    }
431    ~FastAlignReport() {
432        if (first) delete first;
433        free(my_master_name);
434    }
435
436    void memorize_insertion(long offset, long gaps) {
437        if (last) {
438            last = last->append(offset, gaps);
439        }
440        else {
441            if (showGapsMessages) aw_message("---- gaps needed.");
442            first = last = new FastAlignInsertion(offset, gaps);
443        }
444
445        if (showGapsMessages) {
446            char *messi = (char*)malloc(100);
447
448            sprintf(messi, "'%s' needs %li gaps at offset %li.", my_master_name, gaps, offset+1);
449            aw_message(messi);
450            free(messi);
451        }
452    }
453
454    const FastAlignInsertion* insertion() const { return first; }
455
456    void count_aligned_base(int mismatched)             { alignedBases++; if (mismatched) mismatchedBases++; }
457    void count_unaligned_base(int no_of_bases)          { unalignedBases += no_of_bases; }
458
459    void dump() const {
460        printf("fast_align_report:\n"
461               " alignedBases    = %li (=%f%%)\n"
462               " mismatchedBases = %li\n"
463               " unalignedBases  = %li\n"
464               "inserts in master-sequence:\n",
465               alignedBases, (float)alignedBases/(alignedBases+unalignedBases),
466               mismatchedBases,
467               unalignedBases);
468        if (first) first->dumpAll();
469    }
470};
471
472class FastSearchSequence : virtual Noncopyable {
473    // a sequence where search of character triples is very fast
474    const CompactedSubSequence *mySequence;
475    TripleOffset *myOffset[MAX_TRIPLES];
476
477    static int triple_index(const char *triple) {
478        int idx = (int)(triple[0]-'A')*SEQ_CHARS*SEQ_CHARS + (int)(triple[1]-'A')*SEQ_CHARS + (triple[2]-'A');
479
480        return idx>=0 && idx<MAX_TRIPLES ? idx : MAX_TRIPLES-1;
481
482        // if we got any non A-Z characters in sequence, the triple value may overflow.
483        // we use (MAX_TRIPLES-1) as index for all illegal indices.
484    }
485
486public:
487
488    FastSearchSequence(const CompactedSubSequence& seq);
489    ~FastSearchSequence();
490
491    ARB_ERROR fast_align(const CompactedSubSequence& align_to, AlignBuffer *alignBuffer,
492                         int max_seq_length, int matchScore, int mismatchScore,
493                         FastAlignReport *report) const;
494
495    const CompactedSubSequence& sequence() const { return *mySequence; }
496    const TripleOffset *find(const char *triple) const { return myOffset[triple_index(triple)]; }
497};
498
499
500class FastSearchOccurrence : virtual Noncopyable {
501    // iterates through all occurrences of one character triple
502    const FastSearchSequence&  mySequence;
503    const TripleOffset        *myOffset;
504
505    void assertValid() const { fa_assert(implicated(myOffset, myOffset != myOffset->next())); }
506
507public:
508
509    FastSearchOccurrence(const FastSearchSequence& Sequence, const char *triple)
510        : mySequence(Sequence)
511    {
512            myOffset = mySequence.find(triple);
513            assertValid();
514    }
515    ~FastSearchOccurrence() { assertValid(); }
516
517    int found() const { assertValid(); return myOffset!=0; }
518    void gotoNext() { fa_assert(myOffset!=0); myOffset = myOffset->next(); assertValid(); }
519
520    long offset() const { assertValid(); return myOffset->offset(); }
521    const CompactedSubSequence& sequence() const   { assertValid(); return mySequence.sequence(); }
522};
523
524#else
525#error seq_search.hxx included twice
526#endif // SEQ_SEARCH_HXX
Note: See TracBrowser for help on using the repository browser.