source: branches/port5/AWTC/awtc_seq_search.hxx

Last change on this file was 5782, checked in by westram, 16 years ago
  • fixed spelling of 'occurrence'
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.7 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : awtc_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 AWTC_SEQ_SEARCH_HXX
13#define AWTC_SEQ_SEARCH_HXX
14
15#ifndef _CPP_CSTRING
16#include <cstring>
17#endif
18#ifndef _CPP_CSTDLIB
19#include <cstdlib>
20#endif
21
22#ifndef AW_ROOT_HXX
23#include <aw_root.hxx>
24#endif
25#ifndef ARB_ASSERT_H
26#include <arb_assert.h>
27#endif
28#define awtc_assert(bed) arb_assert(bed)
29
30#define SEQ_CHARS   26
31#define MAX_TRIPLES (SEQ_CHARS*SEQ_CHARS*SEQ_CHARS+1) // one faked triple for all non-char triples
32#define GAP_CHARS   ".-~?"      // Characters treated as gaps
33
34void AWTC_message(const char *format, ...) __ATTR__FORMAT(1);
35
36static inline int max(int i1, int i2) { return i1>i2 ? i1 : i2; }
37static inline int AWTC_is_gap(int c)  { return strchr(GAP_CHARS, c)!=0; }
38
39class AWTC_CompactedSubSequence;
40
41class AWTC_Points               // here we store points ('.') which were deleted when compacting sequences
42{
43    long BeforeBase;         // this position is the "compressed" position
44    AWTC_Points *Next;
45
46public:
47
48    AWTC_Points(long before_base) {
49        BeforeBase = before_base;
50        Next       = NULL;
51    }
52    ~AWTC_Points() {
53        delete Next;
54    }
55
56    void append(AWTC_Points *neu);
57    long beforeBase(void) const         { return BeforeBase; }
58    const AWTC_Points *next(void) const { return Next; }
59};
60
61class AWTC_CompactedSequence    // compacts a string (gaps removed, all chars upper)
62// (private class - use AWTC_CompactedSubSequence)
63{
64    char *myText;
65    int   myLength;             // number of base positions
66    int   myStartOffset;        // expanded offsets of first and last position in 'text' (which is given to the c-tor)
67    int   myEndOffset;
68    int  *expdPositionTab;      // this table contains all 'real' (=not compacted) positions of the bases (len = myLength+1)
69
70    int *gapsBeforePosition;    // gapsBeforePosition[ idx+1 ] = gaps _after_ position 'idx'
71    int  referred;
72
73    char *myName;               // sequence name
74
75    AWTC_Points *points;        // Points which were deleted from the sequence are store here
76
77    // -----------------------------------------
78
79    AWTC_CompactedSequence(const char *text, int length, const char *name, int start_offset=0);
80    ~AWTC_CompactedSequence();
81
82    int length() const          {return myLength;}
83    const char *text(int i=0) const     {return myText+i;}
84
85    char operator[](int i) const        {if (i<0 || i>=length()) i = 0; else i = text()[i]; return i;} // HP compiler does not allow two returns
86
87    int expdPosition(int cPos) const {
88        awtc_assert(cPos>=0 && cPos<=myLength); // allowed for all positions plus one following element
89        ;                                       // (which contains the total length of the original sequence)
90        return expdPositionTab[cPos]+myStartOffset;
91    }
92    int compPosition(int xPos) const;
93
94    int no_of_gaps_before(int cPos) const {
95        int leftMostGap;
96        if (cPos>0) {
97            leftMostGap = expdPosition(cPos-1)+1;
98        }
99        else {
100            leftMostGap = myStartOffset;
101        }
102        return expdPosition(cPos)-leftMostGap;
103    }
104    int no_of_gaps_after(int cPos) const {
105        int rightMostGap;
106        if (cPos<(length()-1)) {
107            rightMostGap = expdPosition(cPos+1)-1;
108        }
109        else {
110            rightMostGap = myEndOffset;
111        }
112        return rightMostGap-expdPosition(cPos);
113    }
114
115    void storePoints(int beforePos) {
116        if (points)     points->append(new AWTC_Points(beforePos));
117        else            points = new AWTC_Points(beforePos);
118    }
119
120    friend class AWTC_CompactedSubSequence;
121
122public:
123
124    const AWTC_Points *getPointlist(void) const { return points; }
125};
126
127class AWTC_CompactedSubSequence // smart pointer and substring class for AWTC_CompactedSequence
128{
129    AWTC_CompactedSequence *mySequence;
130    int                     myPos;      // offset into mySequence->myText
131    int                     myLength;   // number of base positions
132    const char             *myText;     // only for speed-up
133    const AWTC_Points      *points;     // just a reference
134
135public:
136
137    AWTC_CompactedSubSequence(const char *seq, int length, const char *name, int start_offset=0);                               // normal c-tor
138    AWTC_CompactedSubSequence(const AWTC_CompactedSubSequence& other);
139    AWTC_CompactedSubSequence(const AWTC_CompactedSubSequence& other, int rel_pos, int length);         // substr c-tor
140    ~AWTC_CompactedSubSequence();                                                               // d-tor
141    AWTC_CompactedSubSequence& operator=(const AWTC_CompactedSubSequence& other);               // =-c-tor
142
143    int length() const                  {return myLength;}
144
145    const char *text() const                    { return myText; }
146    const char *text(int i) const               { return text()+i; }
147
148    const char *name() const                    { return mySequence->myName; }
149
150    char operator[](int i) const                { if (i<0 || i>=length()) { i= 0; } else { i = text()[i]; } return i; }
151
152    int no_of_gaps_before(int cPos) const       { return mySequence->no_of_gaps_before(myPos+cPos); }
153    int no_of_gaps_after(int cPos) const        { return mySequence->no_of_gaps_after(myPos+cPos); }
154
155    int expdStartPosition() const               { return mySequence->expdPosition(myPos); }
156    int expdPosition(int cPos) const
157    {
158        awtc_assert(cPos>=0 && cPos<=myLength);                 // allowed for all positions plus follower
159        return mySequence->expdPosition(myPos+cPos);
160    }
161    int compPosition(int xPos) const            { return mySequence->compPosition(xPos)-myPos; }
162    int expdLength() const                      { return expdPosition(length()-1); }
163    const int *gapsBefore(int offset=0) const   { return mySequence->gapsBeforePosition + myPos + offset; }
164
165    int thisPointPosition(void) {
166        int pos = points->beforeBase()-myPos;
167
168        if (pos>(myLength+1)) {
169            points = NULL;
170            pos = -1;   // HP Compiler !!
171        }
172
173        return pos;
174    }
175
176    int firstPointPosition(void) // HP Compiler needs res
177    {
178        points = mySequence->getPointlist();
179        int res = -1;
180
181        while (points && points->beforeBase()<myPos) {
182            points = points->next();
183        }
184        if (points){
185            res = thisPointPosition();
186        }
187
188        return res;
189    }
190
191    int nextPointPosition(void) // HP Compiler !!!
192    {
193        int res = -1;
194        if (points){
195            points = points->next();
196        }
197        if (points){
198            res = thisPointPosition();
199        }
200        return res;
201    }
202};
203
204class AWTC_SequencePosition     // pointer to character position in AWTC_CompactedSubSequence
205{
206    const AWTC_CompactedSubSequence *mySequence;
207    long myPos;
208    const char *myText;
209
210    int distanceTo(const AWTC_SequencePosition& other) const    {awtc_assert(mySequence==other.mySequence); return myPos-other.myPos;}
211
212public:
213
214    AWTC_SequencePosition(const AWTC_CompactedSubSequence& seq, long pos=0)
215        : mySequence(&seq),
216          myPos(pos),
217          myText(seq.text(pos)) {}
218    AWTC_SequencePosition(const AWTC_SequencePosition& pos, long offset=0)
219        : mySequence(pos.mySequence),
220          myPos(pos.myPos+offset),
221          myText(pos.myText+offset) {}
222    ~AWTC_SequencePosition() {}
223
224    const char *text() const                            { return myText;}
225    const AWTC_CompactedSubSequence& sequence() const   { return *mySequence;}
226
227    long expdPosition() const                           { return sequence().expdPosition(myPos); }
228    long expdPosition(int offset)                       { return sequence().expdPosition(myPos+offset); }
229
230    AWTC_SequencePosition& operator++()                 { myPos++; myText++; return *this; }
231    AWTC_SequencePosition& operator--()                 { myPos--; myText--; return *this; }
232
233    AWTC_SequencePosition& operator+=(long l)           { myPos += l; myText += l; return *this; }
234    AWTC_SequencePosition& operator-=(long l)           { myPos -= l; myText -= l; return *this; }
235
236    int operator<(const AWTC_SequencePosition& other) const { return distanceTo(other)<0; }
237    int operator>(const AWTC_SequencePosition& other) const { return distanceTo(other)>0; }
238
239    long leftOf() const                                 { return myPos;}
240    long rightOf() const                                { return mySequence->length()-myPos;}
241};
242
243class AWTC_TripleOffset         // a list of offsets (used in AWTC_FastSearchSequence)
244{
245    long               myOffset; // compacted offset
246    AWTC_TripleOffset *myNext;
247
248    void IV() const     {awtc_assert(myNext!=this);}
249
250public:
251
252    AWTC_TripleOffset(long Offset, AWTC_TripleOffset *next_toff) : myOffset(Offset), myNext(next_toff) { IV(); }
253    ~AWTC_TripleOffset();
254
255    AWTC_TripleOffset *next() const { IV(); return myNext; }
256    long offset() const { IV(); return myOffset; }
257};
258
259
260class AWTC_alignBuffer                  // alignment result buffer
261{
262    char *myBuffer;
263    char *myQuality;
264
265    // myQuality contains the following chars:
266    //
267    // '?'      base was just inserted (not aligned)
268    // '-'      master and slave are equal
269    // '+'      gap in masert excl-or slave
270    // '~'      master base and slave base are related
271    // '#'      master base and slave base are NOT related (mismatch)
272
273    long mySize;
274    long used;
275
276    void set_used(long newVal)
277    {
278        awtc_assert(newVal<=mySize);
279        used = newVal;
280        GB_status(double(used)/double(mySize));
281    }
282    void add_used(long toAdd)
283    {
284        set_used(toAdd+used);
285    }
286
287    int isGlobalGap(long off)   // TRUE if gap in slave AND master
288    {
289        return (myBuffer[off]=='-' || myBuffer[off]=='.') && myQuality[off]=='-';
290    }
291    void moveUnaligned(long from, long to)
292    {
293        myBuffer[to] = myBuffer[from];
294        myQuality[to] = myQuality[from];
295        myBuffer[from] = '-';
296        myQuality[from] = '-';
297    }
298
299public:
300
301    AWTC_alignBuffer(long size)
302    {
303        mySize = size;
304        set_used(0);
305        myBuffer = new char[size+1];
306        myBuffer[size] = 0;
307        myQuality = new char[size+1];
308        myQuality[size] = 0;
309    }
310    ~AWTC_alignBuffer()
311    {
312        delete [] myBuffer;
313        delete [] myQuality;
314    }
315
316    const char *text() const            { awtc_assert(free()>=0); myBuffer[used]=0;  return myBuffer; }
317    const char *quality() const         { awtc_assert(free()>=0); myQuality[used]=0; return myQuality; }
318    long length() const                 { return used; }
319
320    long offset() const                 { return used; }
321    long free() const                   { return mySize-used; }
322
323    void copy(const char *s, char q, long len)
324    {
325        awtc_assert(len<=free());
326        memcpy(myBuffer+used, s, len);
327        memset(myQuality+used, q, len);
328        add_used(len);
329    }
330    void set(char c, char q)
331    {
332        awtc_assert(free()>=1);
333        myBuffer[used] = c;
334        myQuality[used] = q;
335        add_used(1);
336    }
337    void set(char c, char q, long len)
338    {
339        awtc_assert(len<=free());
340        memset(myBuffer+used, c, len);
341        memset(myQuality+used, q, len);
342        add_used(len);
343    }
344    void reset(long newOffset=0)
345    {
346        awtc_assert(newOffset>=0 && newOffset<mySize);
347        set_used(newOffset);
348    }
349
350    void correctUnalignedPositions(void);
351
352    void expandPoints(AWTC_CompactedSubSequence& slaveSequence);
353    void point_ends_of();
354};
355
356
357class AWTC_fast_align_insertion
358{
359    long insert_at_offset;
360    long inserted_gaps;
361   
362    AWTC_fast_align_insertion *myNext;
363
364public:
365    AWTC_fast_align_insertion(long Offset, long Gaps) {
366        insert_at_offset = Offset;
367        inserted_gaps    = Gaps;
368        myNext           = 0;
369    }
370    ~AWTC_fast_align_insertion();
371
372    AWTC_fast_align_insertion *append(long Offset, long Gaps) {
373        return myNext = new AWTC_fast_align_insertion(Offset, Gaps);
374    }
375    void dump() const {
376        printf(" offset=%5li gaps=%3li\n", insert_at_offset, inserted_gaps);
377    }
378    void dumpAll() const {
379        dump();
380        if (myNext) myNext->dumpAll();
381    }
382
383    const AWTC_fast_align_insertion *next() const { return myNext; }
384    long offset() const { return insert_at_offset; }
385    long gaps() const { return inserted_gaps; }
386};
387
388
389class AWTC_fast_align_report    // alignment report
390{
391    long  alignedBases;
392    long  mismatchedBases;      // in aligned part
393    long  unalignedBases;
394    char *my_master_name;
395    bool  showGapsMessages;     // display messages about missing gaps in master
396
397    AWTC_fast_align_insertion *first; // list of insertions (order is important)
398    AWTC_fast_align_insertion *last;
399
400public:
401
402    AWTC_fast_align_report(const char *master_name, bool show_Gaps_Messages) {
403        alignedBases     = 0;
404        mismatchedBases  = 0;
405        unalignedBases   = 0;
406        first            = 0;
407        last             = 0;
408        my_master_name   = strdup(master_name);
409        showGapsMessages = show_Gaps_Messages;
410    }
411    ~AWTC_fast_align_report() {
412        if (first) delete first;
413        free(my_master_name);
414    }
415
416    void memorize_insertion(long offset, long gaps) {
417        if (last) {
418            last = last->append(offset,gaps);
419        }
420        else {
421            if (showGapsMessages) aw_message("---- gaps needed.");
422            first = last = new AWTC_fast_align_insertion(offset, gaps);
423        }
424
425        if (showGapsMessages) {
426            char *messi = (char*)malloc(100);
427
428            sprintf(messi, "'%s' needs %li gaps at offset %li.", my_master_name, gaps, offset+1);
429            aw_message(messi);
430            free(messi);
431        }
432    }
433
434    const AWTC_fast_align_insertion* insertion() const { return first; }
435
436    void count_aligned_base(int mismatched)             {alignedBases++; if (mismatched) mismatchedBases++;}
437    void count_unaligned_base(int no_of_bases)          {unalignedBases += no_of_bases;}
438
439    void dump() const {
440        printf("fast_align_report:\n"
441               " alignedBases    = %li (=%f%%)\n"
442               " mismatchedBases = %li\n"
443               " unalignedBases  = %li\n"
444               "inserts in master-sequence:\n",
445               alignedBases, (float)alignedBases/(alignedBases+unalignedBases),
446               mismatchedBases,
447               unalignedBases);
448        if (first) first->dumpAll();
449    }
450};
451
452class AWTC_FastSearchSequence           // a sequence where search of character triples is very fast
453{
454    const AWTC_CompactedSubSequence *mySequence;
455    AWTC_TripleOffset *myOffset[MAX_TRIPLES];
456
457    AWTC_FastSearchSequence(const AWTC_FastSearchSequence&) {} // not allowed
458    AWTC_FastSearchSequence& operator=(const AWTC_FastSearchSequence&) { return *this; } // not allowed
459
460    static int triple_index(const char *triple)
461    {
462        int idx = (int)(triple[0]-'A')*SEQ_CHARS*SEQ_CHARS + (int)(triple[1]-'A')*SEQ_CHARS + (triple[2]-'A');
463
464        return idx>=0 && idx<MAX_TRIPLES ? idx : MAX_TRIPLES-1;
465
466        // if we got any non A-Z characters in sequence, the triple value may overflow.
467        // we use (MAX_TRIPLES-1) as index for all illegal indices.
468    }
469
470public:
471
472    AWTC_FastSearchSequence(const AWTC_CompactedSubSequence& seq);
473    ~AWTC_FastSearchSequence() {}
474
475    GB_ERROR fast_align(const AWTC_CompactedSubSequence& align_to, AWTC_alignBuffer *alignBuffer,
476                        int max_seq_length, int matchScore, int mismatchScore,
477                        AWTC_fast_align_report *report) const;
478
479    const AWTC_CompactedSubSequence& sequence() const {return *mySequence;}
480    const AWTC_TripleOffset *find(const char *triple) const { return myOffset[triple_index(triple)]; }
481};
482
483
484class AWTC_FastSearchOccurrence          // iterates through all Occurances of one character triple
485{
486    const AWTC_FastSearchSequence&      mySequence;
487    const AWTC_TripleOffset             *myOffset;
488
489    void IV() const {awtc_assert(!myOffset || myOffset!=myOffset->next());}
490
491public:
492
493    AWTC_FastSearchOccurrence(const AWTC_FastSearchSequence& Sequence, const char *triple)
494        : mySequence(Sequence)                          { myOffset = mySequence.find(triple); IV();}
495    ~AWTC_FastSearchOccurrence()                        { IV();}
496
497    int found() const                                   { IV(); return myOffset!=0; }
498    void gotoNext()                                     { awtc_assert(myOffset!=0); myOffset = myOffset->next(); IV(); }
499
500    long offset() const                                 { IV(); return myOffset->offset();}
501    const AWTC_CompactedSubSequence& sequence() const   { IV(); return mySequence.sequence();}
502};
503
504// -----------------------------
505//      INLINE-Functions:
506// -----------------------------
507
508inline AWTC_CompactedSubSequence::AWTC_CompactedSubSequence(const char *seq, int len, const char *Name, int start_offset) // normal c-tor
509{
510    mySequence = new AWTC_CompactedSequence(seq, len, Name, start_offset);
511    myPos      = 0;
512    myLength   = mySequence->length();
513    myText     = mySequence->text()+myPos;
514}
515
516inline AWTC_CompactedSubSequence::AWTC_CompactedSubSequence(const AWTC_CompactedSubSequence& other)
517{
518    mySequence = other.mySequence;
519    mySequence->referred++;
520
521    myPos    = other.myPos;
522    myLength = other.myLength;
523    myText   = other.myText;
524}
525
526inline AWTC_CompactedSubSequence::AWTC_CompactedSubSequence(const AWTC_CompactedSubSequence& other, int rel_pos, int Length)
527// substr c-tor
528{
529    mySequence = other.mySequence;
530    mySequence->referred++;
531
532    myPos    = other.myPos+rel_pos;
533    myLength = Length;
534    myText   = mySequence->text()+myPos;
535
536    //printf("work on sub-seq: %li-%li\n", pos, pos+length-1);
537
538    awtc_assert((rel_pos+Length)<=mySequence->length());
539    awtc_assert(rel_pos>=0);
540}
541
542inline AWTC_CompactedSubSequence::~AWTC_CompactedSubSequence() // d-tor
543{
544    if (mySequence->referred-- == 1) // last reference
545        delete mySequence;
546}
547
548inline AWTC_CompactedSubSequence& AWTC_CompactedSubSequence::operator=(const AWTC_CompactedSubSequence& other) // =-c-tor
549{
550    // d-tor part
551
552    if (mySequence->referred-- == 1)
553        delete mySequence;
554
555    // c-tor part
556
557    mySequence = other.mySequence;
558    mySequence->referred++;
559
560    myPos    = other.myPos;
561    myLength = other.myLength;
562    myText   = mySequence->text()+myPos;
563
564    return *this;
565}
566
567#else
568#error awtc_seq_search.hxx included twice
569#endif // AWTC_SEQ_SEARCH_HXX
Note: See TracBrowser for help on using the repository browser.