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

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