~ubuntu-branches/ubuntu/oneiric/ncbi-tools6/oneiric

« back to all changes in this revision

Viewing changes to algo/blast/core/blast_dust.c

  • Committer: Bazaar Package Importer
  • Author(s): Aaron M. Ucko
  • Date: 2008-07-14 19:43:15 UTC
  • mfrom: (2.1.12 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080714194315-ed44u9ek7txva2rz
Tags: 6.1.20080302-3
tools/readdb.c: enable madvise()-based code on all glibc (hence all
Debian) systems, not just Linux.  (Closes: #490437.)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: blast_dust.c,v 1.37 2005/11/16 14:27:03 madden Exp $
2
 
 * ===========================================================================
3
 
 *
4
 
 *                            PUBLIC DOMAIN NOTICE
5
 
 *               National Center for Biotechnology Information
6
 
 *
7
 
 *  This software/database is a "United States Government Work" under the
8
 
 *  terms of the United States Copyright Act.  It was written as part of
9
 
 *  the author's official duties as a United States Government employee and
10
 
 *  thus cannot be copyrighted.  This software/database is freely available
11
 
 *  to the public for use. The National Library of Medicine and the U.S.
12
 
 *  Government have not placed any restriction on its use or reproduction.
13
 
 *
14
 
 *  Although all reasonable efforts have been taken to ensure the accuracy
15
 
 *  and reliability of the software and data, the NLM and the U.S.
16
 
 *  Government do not and cannot warrant the performance or results that
17
 
 *  may be obtained by using this software or data. The NLM and the U.S.
18
 
 *  Government disclaim all warranties, express or implied, including
19
 
 *  warranties of performance, merchantability or fitness for any particular
20
 
 *  purpose.
21
 
 *
22
 
 *  Please cite the author in any work or product based on this material.
23
 
 *
24
 
 * ==========================================================================
25
 
 *
26
 
 * Authors: Richa Agarwala (based upon versions variously worked upon by Roma 
27
 
 *          Tatusov, John Kuzio, and Ilya Dondoshansky).
28
 
 *   
29
 
 * ==========================================================================
30
 
 */
31
 
 
32
 
/** @file blast_dust.c
33
 
 * A utility to find low complexity NA regions. This parallels functionality 
34
 
 * of dust.c from the C toolkit, but without using the structures generated 
35
 
 * from ASN.1 spec.
36
 
 */
37
 
 
38
 
#ifndef SKIP_DOXYGEN_PROCESSING
39
 
static char const rcsid[] =
40
 
    "$Id: blast_dust.c,v 1.37 2005/11/16 14:27:03 madden Exp $";
41
 
#endif /* SKIP_DOXYGEN_PROCESSING */
42
 
 
43
 
#include <algo/blast/core/blast_dust.h>
44
 
#include <algo/blast/core/blast_util.h>
45
 
#include <algo/blast/core/blast_encoding.h>
46
 
#include <algo/blast/core/blast_filter.h>
47
 
 
48
 
 
49
 
/** Declared in blast_def.h as extern const. */
50
 
const int kDustLevel = 20;
51
 
const int kDustWindow = 64;
52
 
const int kDustLinker = 1;
53
 
 
54
 
 
55
 
/* local, file scope, structures and variables */
56
 
 
57
 
/** endpoints
58
 
 * @todo expand documentation
59
 
 */
60
 
typedef struct DREGION { 
61
 
        struct  DREGION*        next;
62
 
        Int4    from, to;
63
 
} DREGION;
64
 
 
65
 
/** localcurrents 
66
 
 * @todo expand documentation
67
 
 */
68
 
typedef struct DCURLOC { 
69
 
        Int4    cursum, curstart, curend;
70
 
        Int2    curlength;
71
 
} DCURLOC;
72
 
 
73
 
Uint1 *SUM_THRESHOLD;
74
 
 
75
 
/* local functions */
76
 
 
77
 
static void wo (Int4, Uint1*, Int4, DCURLOC*, Uint1*, Uint1, Int4);
78
 
static Boolean wo1 (Int4, Uint1*, Int4, DCURLOC*);
79
 
static Int4 dust_triplet_find (Uint1*, Int4, Int4, Uint1*);
80
 
 
81
 
/* entry point for dusting */
82
 
 
83
 
static Int4 dust_segs (Uint1* sequence, Int4 length, Int4 start,
84
 
                       DREGION* reg,
85
 
                       Int4 level, Int4 windowsize, Int4 linker)
86
 
{
87
 
   Int4    len;
88
 
   Int4 i;
89
 
   Uint1* seq;
90
 
   DREGION* regold = NULL;
91
 
   DCURLOC      cloc;
92
 
   Int4 nreg;
93
 
   
94
 
   /* defaults are more-or-less in keeping with original dust */
95
 
   if (level < 2 || level > 64) level = kDustLevel;
96
 
   if (windowsize < 8 || windowsize > 64) windowsize = kDustWindow;
97
 
   if (linker < 1 || linker > 32) linker = kDustLinker;
98
 
   
99
 
   nreg = 0;
100
 
   seq = (Uint1*) calloc(1, windowsize);                        /* triplets */
101
 
   if (!seq) {
102
 
      return -1;
103
 
   }
104
 
   SUM_THRESHOLD = (Uint1 *) calloc(windowsize, sizeof(Uint1));  
105
 
   if (!SUM_THRESHOLD) {
106
 
      return -1;
107
 
   }
108
 
   SUM_THRESHOLD[0] = 1;
109
 
   for (i=1; i < windowsize; i++)
110
 
       SUM_THRESHOLD[i] = (level * i)/10;
111
 
 
112
 
   if (length < windowsize) windowsize = length;
113
 
 
114
 
   /* Consider smaller windows in beginning of the sequence */
115
 
   for (i = 2; i <= windowsize-1; i++) {
116
 
      len = i-1;
117
 
      wo (len, sequence, 0, &cloc, seq, 1, level);
118
 
      
119
 
      if (cloc.cursum*10 > level*cloc.curlength) {
120
 
         if (nreg &&
121
 
             regold->to + linker >= cloc.curstart+start &&
122
 
             regold->from <= cloc.curend + start + linker) {
123
 
            /* overlap windows nicely if needed */
124
 
            if (regold->to < cloc.curend +  start)
125
 
                regold->to = cloc.curend +  start;
126
 
            if (regold->from > cloc.curstart + start)
127
 
                regold->from = cloc.curstart + start;
128
 
         } else {
129
 
            /* new window or dusted regions do not overlap */
130
 
            reg->from = cloc.curstart + start;
131
 
            reg->to = cloc.curend + start;
132
 
            regold = reg;
133
 
            reg = (DREGION*) calloc(1, sizeof(DREGION));
134
 
            if (!reg) {
135
 
               sfree(seq);
136
 
               sfree(SUM_THRESHOLD);
137
 
               return -1;
138
 
            }
139
 
            reg->next = NULL;
140
 
            regold->next = reg;
141
 
            nreg++;
142
 
         }
143
 
      }                         /* end 'if' high score  */
144
 
   }                                    /* end for */
145
 
 
146
 
   for (i = 1; i < length-2; i++) {
147
 
      len = (Int4) ((length > i+windowsize) ? windowsize : length-i);
148
 
      len -= 2;
149
 
      if (length >= i+windowsize)
150
 
          wo (len, sequence, i, &cloc, seq, 2, level);
151
 
      else /* remaining portion of sequence is less than windowsize */
152
 
          wo (len, sequence, i, &cloc, seq, 3, level);
153
 
      
154
 
      if (cloc.cursum*10 > level*cloc.curlength) {
155
 
         if (nreg &&
156
 
             regold->to + linker >= cloc.curstart+i+start &&
157
 
             regold->from <= cloc.curend + i + start + linker) {
158
 
            /* overlap windows nicely if needed */
159
 
            if (regold->to < cloc.curend + i + start)
160
 
                regold->to = cloc.curend + i + start;
161
 
            if (regold->from > cloc.curstart + i + start)
162
 
                regold->from = cloc.curstart + i + start;
163
 
         } else {
164
 
            /* new window or dusted regions do not overlap */
165
 
            reg->from = cloc.curstart + i + start;
166
 
            reg->to = cloc.curend + i + start;
167
 
            regold = reg;
168
 
            reg = (DREGION*) calloc(1, sizeof(DREGION));
169
 
            if (!reg) {
170
 
               sfree(seq);
171
 
               sfree(SUM_THRESHOLD);
172
 
               return -1;
173
 
            }
174
 
            reg->next = NULL;
175
 
            regold->next = reg;
176
 
            nreg++;
177
 
         }
178
 
      }                         /* end 'if' high score  */
179
 
   }                                    /* end for */
180
 
   sfree (seq);
181
 
   sfree(SUM_THRESHOLD);
182
 
   return nreg;
183
 
}
184
 
 
185
 
static void wo (Int4 len, Uint1* seq_start, Int4 iseg, DCURLOC* cloc, 
186
 
                Uint1* seq, Uint1 FIND_TRIPLET, Int4 level)
187
 
{
188
 
        Int4 smaller_window_start, mask_window_end;
189
 
        Boolean SINGLE_TRIPLET;
190
 
 
191
 
        cloc->cursum = 0;
192
 
        cloc->curlength = 1;
193
 
        cloc->curstart = 0;
194
 
        cloc->curend = 0;
195
 
 
196
 
        if (len < 1)
197
 
                return;
198
 
 
199
 
        /* get the chunk of sequence in triplets */
200
 
        if (FIND_TRIPLET==1) /* Append one */
201
 
        {
202
 
                seq[len-1] = seq[len] = seq[len+1] = 0;
203
 
                dust_triplet_find (seq_start, iseg+len-1, 1, seq+len-1);
204
 
        }
205
 
        if (FIND_TRIPLET==2) /* Copy suffix as prefix and find one */
206
 
        {
207
 
                memmove(seq,seq+1,(len-1)*sizeof(Uint1));
208
 
                seq[len-1] = seq[len] = seq[len+1] = 0;
209
 
                dust_triplet_find (seq_start, iseg+len-1, 1, seq+len-1);
210
 
        }
211
 
        if (FIND_TRIPLET==3) /* Copy suffix */
212
 
                memmove(seq,seq+1,len*sizeof(Uint1));
213
 
 
214
 
        /* dust the chunk */
215
 
        SINGLE_TRIPLET = wo1 (len, seq, 0, cloc); /* dust at start of window */
216
 
 
217
 
        /* consider smaller windows only if anything interesting 
218
 
           found for starting position  and smaller windows have potential of
219
 
           being at higher level */
220
 
        if ((cloc->cursum*10 > level*cloc->curlength) && (!SINGLE_TRIPLET)) {
221
 
                mask_window_end = cloc->curend-1;
222
 
                smaller_window_start = 1;
223
 
                while ((smaller_window_start < mask_window_end) &&
224
 
                       (!SINGLE_TRIPLET)) {
225
 
                        SINGLE_TRIPLET = wo1(mask_window_end-smaller_window_start,
226
 
                             seq+smaller_window_start, smaller_window_start, cloc);
227
 
                        smaller_window_start++;
228
 
                }
229
 
        }
230
 
 
231
 
        cloc->curend += cloc->curstart;
232
 
}
233
 
 
234
 
/** returns TRUE if there is single triplet in the sequence considered */
235
 
static Boolean wo1 (Int4 len, Uint1* seq, Int4 iwo, DCURLOC* cloc)
236
 
{
237
 
   Uint4 sum;
238
 
        Int4 loop;
239
 
 
240
 
        Int2* countsptr;
241
 
        Int2 counts[4*4*4];
242
 
        Uint1 triplet_count = 0;
243
 
 
244
 
        memset (counts, 0, sizeof (counts));
245
 
/* zero everything */
246
 
        sum = 0;
247
 
 
248
 
/* dust loop -- specific for triplets   */
249
 
        for (loop = 0; loop < len; loop++)
250
 
        {
251
 
                countsptr = &counts[*seq++];
252
 
                if (*countsptr)
253
 
                {
254
 
                        sum += (Uint4)(*countsptr);
255
 
 
256
 
                    if (sum >= SUM_THRESHOLD[loop])
257
 
                    {
258
 
                        if ((Uint4)cloc->cursum*loop < sum*cloc->curlength)
259
 
                        {
260
 
                                cloc->cursum = sum;
261
 
                                cloc->curlength = loop;
262
 
                                cloc->curstart = iwo;
263
 
                                cloc->curend = loop + 2; /* triplets */
264
 
                        }
265
 
                    }
266
 
                }
267
 
                else
268
 
                        triplet_count++;
269
 
                (*countsptr)++;
270
 
        }
271
 
 
272
 
        if (triplet_count > 1)
273
 
                return(FALSE);
274
 
        return(TRUE);
275
 
}
276
 
 
277
 
/** Fill an array with 2-bit encoded triplets.
278
 
 * @param seq_start Pointer to the start of the sequence in blastna 
279
 
 *                  encoding [in]
280
 
 * @param icur Offset at which to start extracting triplets [in]
281
 
 * @param max Maximal length of the sequence segment to be processed [in]
282
 
 * @param s1 Array of triplets [out]
283
 
 * @return How far was the sequence processed?
284
 
 */
285
 
static Int4 
286
 
dust_triplet_find (Uint1* seq_start, Int4 icur, Int4 max, Uint1* s1)
287
 
{
288
 
   Int4 n;
289
 
   Uint1* s2,* s3;
290
 
   Int2 c;
291
 
   Uint1* seq = &seq_start[icur];
292
 
   Uint1 end_byte = NCBI4NA_TO_BLASTNA[NULLB];
293
 
   
294
 
   n = 0;
295
 
   
296
 
   s2 = s1 + 1;
297
 
   s3 = s1 + 2;
298
 
   
299
 
   /* set up 1 */
300
 
   if ((c = *seq++) == end_byte)
301
 
      return n;
302
 
   c &= NCBI2NA_MASK;
303
 
   *s1 |= c;
304
 
   *s1 <<= 2;
305
 
   
306
 
   /* set up 2 */
307
 
   if ((c = *seq++) == end_byte)
308
 
      return n;
309
 
   c &= NCBI2NA_MASK;
310
 
   *s1 |= c;
311
 
   *s2 |= c;
312
 
   
313
 
   /* triplet fill loop */
314
 
   while (n < max && (c = *seq++) != end_byte) {
315
 
      c &= NCBI2NA_MASK;
316
 
      *s1 <<= 2;
317
 
      *s2 <<= 2;
318
 
      *s1 |= c;
319
 
      *s2 |= c;
320
 
      *s3 |= c;
321
 
      s1++;
322
 
      s2++;
323
 
      s3++;
324
 
      n++;
325
 
   }
326
 
   
327
 
   return n;
328
 
}
329
 
 
330
 
/** Look for dustable locations */
331
 
static Int2 
332
 
GetDustLocations (BlastSeqLoc** loc, DREGION* reg, Int4 nreg)
333
 
{
334
 
   BlastSeqLoc* tail = NULL;   /* pointer to tail of loc linked list */
335
 
        
336
 
   if (!loc)
337
 
      return -1;
338
 
   
339
 
   *loc = NULL;
340
 
 
341
 
   /* point to dusted locations */
342
 
   if (nreg > 0) {
343
 
      Int4 i;
344
 
      for (i = 0; reg && i < nreg; i++) {
345
 
         /* Cache the tail of the list to avoid the overhead of traversing the
346
 
          * list when appending to it */
347
 
         tail = BlastSeqLocNew(tail ? &tail : loc, reg->from, reg->to);
348
 
         reg = reg->next;
349
 
      }
350
 
   }
351
 
#if 0
352
 
   /* N.B.: 
353
 
    * additional error checking added below results in unit test failures!
354
 
    */
355
 
 
356
 
   /* point to dusted locations */
357
 
   if (nreg > 0) {
358
 
      Int4 i;
359
 
      for (i = 0; reg && i < nreg; i++) {
360
 
         if (BlastSeqLocNew(loc, reg->from, reg->to) == NULL) {
361
 
             break;
362
 
         }
363
 
         reg = reg->next;
364
 
      }
365
 
      /* either BlastSeqLocNew failed or nreg didn't match the number of
366
 
       * elements in reg, so return error */
367
 
      if (reg) {
368
 
          *loc = BlastSeqLocFree(*loc);
369
 
          return -1;
370
 
      }
371
 
   }
372
 
#endif
373
 
   return 0;
374
 
}
375
 
 
376
 
Int2 SeqBufferDust (Uint1* sequence, Int4 length, Int4 offset,
377
 
                    Int2 level, Int2 window, Int2 linker,
378
 
                    BlastSeqLoc** dust_loc)
379
 
{
380
 
        DREGION* reg,* regold;
381
 
        Int4 nreg;
382
 
   Int2 status = 0;
383
 
 
384
 
        /* place for dusted regions */
385
 
        regold = reg = (DREGION*) calloc(1, sizeof(DREGION));
386
 
        if (!reg)
387
 
           return -1;
388
 
 
389
 
        nreg = dust_segs (sequence, length, offset, reg, (Int4)level, 
390
 
                  (Int4)window, (Int4)linker);
391
 
 
392
 
        status = GetDustLocations(dust_loc, reg, nreg);
393
 
 
394
 
        /* clean up memory */
395
 
        reg = regold;
396
 
        while (reg)
397
 
        {
398
 
                regold = reg;
399
 
                reg = reg->next;
400
 
                sfree (regold);
401
 
        }
402
 
 
403
 
        return status;
404
 
}