blast_dust.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:9k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: blast_dust.c,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:07:03  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.24
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: blast_dust.c,v 1000.2 2004/06/01 18:07:03 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's offical duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ==========================================================================
  33.  *
  34.  * Authors: Richa Agarwala (based upon versions variously worked upon by Roma 
  35.  *          Tatusov, John Kuzio, and Ilya Dondoshansky).
  36.  *   
  37.  * ==========================================================================
  38.  */
  39. /** @file blast_dust.c
  40.  * A utility to find low complexity NA regions. This parallels functionality 
  41.  * of dust.c from the C toolkit, but without using the structures generated 
  42.  * from ASN.1 spec.
  43.  */
  44. static char const rcsid[] = 
  45.     "$Id: blast_dust.c,v 1000.2 2004/06/01 18:07:03 gouriano Exp $";
  46. #include <algo/blast/core/blast_dust.h>
  47. #include <algo/blast/core/blast_util.h>
  48. #include <algo/blast/core/blast_encoding.h>
  49. /* local, file scope, structures and variables */
  50. typedef struct DREGION { /* endpoints */
  51. struct DREGION* next;
  52. Int4 from, to;
  53. } DREGION;
  54. typedef struct DCURLOC { /* localcurrents */
  55. Int4 curlevel, curstart, curend;
  56. } DCURLOC;
  57. /* local functions */
  58. static void wo (Int4, Uint1*, Int4, DCURLOC*, Uint1*, Boolean, Int4);
  59. static Boolean wo1 (Int4, Uint1*, Int4, DCURLOC*);
  60. static Int4 dust_triplet_find (Uint1*, Int4, Int4, Uint1*);
  61. /* entry point for dusting */
  62. static Int4 dust_segs (Uint1* sequence, Int4 length, Int4 start,
  63.        DREGION* reg,
  64.        Int4 level, Int4 windowsize, Int4 minwin, Int4 linker)
  65. {
  66.    Int4    len;
  67.    Int4 i;
  68.    Uint1* seq;
  69.    DREGION* regold = NULL;
  70.    DCURLOC cloc;
  71.    Int4 nreg;
  72.    
  73.    /* defaults are more-or-less in keeping with original dust */
  74.    if (level < 2 || level > 64) level = 20;
  75.    if (windowsize < 8 || windowsize > 64) windowsize = 64;
  76.    if (minwin < 4 || minwin > 128) minwin = 4;
  77.    if (linker < 1 || linker > 32) linker = 1;
  78.    
  79.    nreg = 0;
  80.    seq = (Uint1*) calloc(1, windowsize); /* triplets */
  81.    if (!seq) {
  82.       return -1;
  83.    }
  84.    len = (Int4) ((length > windowsize) ? windowsize : length);
  85.    len -= 2;
  86.    dust_triplet_find (sequence, 0, len-1, seq+1);
  87.    for (i = 0; i < length-2; i++) {
  88.       len = (Int4) ((length > i+windowsize) ? windowsize : length-i);
  89.       len -= 2;
  90.       if ((length >= i+windowsize) || (i==0))
  91.           wo (len, sequence, i, &cloc, seq, TRUE, level);
  92.       else /* remaining portion of sequence is less than windowsize */
  93.           wo (len, sequence, i, &cloc, seq, FALSE, level);
  94.       
  95.       if (cloc.curlevel > level) {
  96.          if (nreg &&
  97.              regold->to + linker >= cloc.curstart+i+start &&
  98.              regold->from <= cloc.curend + i + start + linker) {
  99.             /* overlap windows nicely if needed */
  100.             if (regold->to < cloc.curend + i + start)
  101.                 regold->to = cloc.curend + i + start;
  102.             if (regold->from > cloc.curstart + i + start)
  103.                 regold->from = cloc.curstart + i + start;
  104.          } else {
  105.             /* new window or dusted regions do not overlap */
  106.             reg->from = cloc.curstart + i + start;
  107.             reg->to = cloc.curend + i + start;
  108.             regold = reg;
  109.             reg = (DREGION*) calloc(1, sizeof(DREGION));
  110.             if (!reg) {
  111.                sfree(seq);
  112.                return -1;
  113.             }
  114.             reg->next = NULL;
  115.             regold->next = reg;
  116.             nreg++;
  117.          }
  118.       } /* end 'if' high score */
  119.    } /* end for */
  120.    sfree (seq);
  121.    return nreg;
  122. }
  123. static void wo (Int4 len, Uint1* seq_start, Int4 iseg, DCURLOC* cloc, 
  124.                 Uint1* seq, Boolean FIND_TRIPLET, Int4 level)
  125. {
  126. Int4 smaller_window_start, mask_window_end;
  127.         Boolean SINGLE_TRIPLET;
  128. cloc->curlevel = 0;
  129. cloc->curstart = 0;
  130. cloc->curend = 0;
  131. if (len < 1)
  132. return;
  133.         /* get the chunk of sequence in triplets */
  134. if (FIND_TRIPLET==TRUE) /* Copy suffix as prefix and find one */
  135. {
  136. memmove(seq,seq+1,(len-1)*sizeof(Uint1));
  137. seq[len-1] = seq[len] = seq[len+1] = 0;
  138. dust_triplet_find (seq_start, iseg+len-1, 1, seq+len-1);
  139. }
  140. else /* Copy suffix */
  141. memmove(seq,seq+1,len*sizeof(Uint1));
  142.         /* dust the chunk */
  143. SINGLE_TRIPLET = wo1 (len, seq, 0, cloc); /* dust at start of window */
  144.         /* consider smaller windows only if anything interesting 
  145.            found for starting position  and smaller windows have potential of
  146.            being at higher level */
  147. if ((cloc->curlevel > level) && (!SINGLE_TRIPLET)) {
  148. mask_window_end = cloc->curend-1;
  149. smaller_window_start = 1;
  150.                 while ((smaller_window_start < mask_window_end) &&
  151.                        (!SINGLE_TRIPLET)) {
  152. SINGLE_TRIPLET = wo1(mask_window_end-smaller_window_start,
  153.                              seq+smaller_window_start, smaller_window_start, cloc);
  154.                  smaller_window_start++;
  155.         }
  156. }
  157. cloc->curend += cloc->curstart;
  158. }
  159. /* returns TRUE if there is single triplet in the sequence considered */
  160. static Boolean wo1 (Int4 len, Uint1* seq, Int4 iwo, DCURLOC* cloc)
  161. {
  162.    Uint4 sum;
  163. Int4 loop;
  164. Int4 newlevel;
  165. Int2* countsptr;
  166. Int2 counts[4*4*4];
  167. Uint1 triplet_count = 0;
  168. memset (counts, 0, sizeof (counts));
  169. /* zero everything */
  170. sum = 0;
  171. newlevel = 0;
  172. /* dust loop -- specific for triplets */
  173. for (loop = 0; loop < len; loop++)
  174. {
  175. countsptr = &counts[*seq++];
  176. if (*countsptr)
  177. {
  178. sum += (Uint4)(*countsptr);
  179. newlevel = 10 * sum / loop;
  180. if (cloc->curlevel < newlevel)
  181. {
  182. cloc->curlevel = newlevel;
  183. cloc->curstart = iwo;
  184. cloc->curend = loop + 2; /* triplets */
  185. }
  186. }
  187. else
  188. triplet_count++;
  189. (*countsptr)++;
  190. }
  191. if (triplet_count > 1)
  192. return(FALSE);
  193. return(TRUE);
  194. }
  195. /** Fill an array with 2-bit encoded triplets.
  196.  * @param seq_start Pointer to the start of the sequence in blastna 
  197.  *                  encoding [in]
  198.  * @param icur Offset at which to start extracting triplets [in]
  199.  * @param max Maximal length of the sequence segment to be processed [in]
  200.  * @param s1 Array of triplets [out]
  201.  * @return How far was the sequence processed?
  202.  */
  203. static Int4 
  204. dust_triplet_find (Uint1* seq_start, Int4 icur, Int4 max, Uint1* s1)
  205. {
  206.    Int4 n;
  207.    Uint1* s2,* s3;
  208.    Int2 c;
  209.    Uint1* seq = &seq_start[icur];
  210.    Uint1 end_byte = NCBI4NA_TO_BLASTNA[NULLB];
  211.    
  212.    n = 0;
  213.    
  214.    s2 = s1 + 1;
  215.    s3 = s1 + 2;
  216.    
  217.    /* set up 1 */
  218.    if ((c = *seq++) == end_byte)
  219.       return n;
  220.    c &= NCBI2NA_MASK;
  221.    *s1 |= c;
  222.    *s1 <<= 2;
  223.    
  224.    /* set up 2 */
  225.    if ((c = *seq++) == end_byte)
  226.       return n;
  227.    c &= NCBI2NA_MASK;
  228.    *s1 |= c;
  229.    *s2 |= c;
  230.    
  231.    /* triplet fill loop */
  232.    while (n < max && (c = *seq++) != end_byte) {
  233.       c &= NCBI2NA_MASK;
  234.       *s1 <<= 2;
  235.       *s2 <<= 2;
  236.       *s1 |= c;
  237.       *s2 |= c;
  238.       *s3 |= c;
  239.       s1++;
  240.       s2++;
  241.       s3++;
  242.       n++;
  243.    }
  244.    
  245.    return n;
  246. }
  247. /* look for dustable locations (as slpDust from dust.c) */
  248. static Int2 
  249. GetDustLocations (ListNode** loc, DREGION* reg, Int4 nreg)
  250. {
  251.    Int4 i;
  252.    ListNode* last_loc = NULL;
  253.    SSeqRange* dintp;
  254.         
  255.    if (!loc)
  256.       return -1;
  257.    
  258.    *loc = NULL;
  259.    /* point to dusted locations */
  260.    if (nreg > 0) {
  261.       for (i = 0; reg && i < nreg; i++) {
  262.          dintp = (SSeqRange*) calloc(1, sizeof(SSeqRange));
  263.          if (!dintp) {
  264.             return -1;
  265.          }
  266.          dintp->left = reg->from;
  267.          dintp->right = reg->to;
  268.          if (!last_loc)
  269.             last_loc = ListNodeAddPointer (loc, 0, dintp);
  270.          else 
  271.             last_loc = ListNodeAddPointer (&last_loc, 0, dintp);
  272.          reg = reg->next;
  273.       }
  274.    }
  275.    return 0;
  276. }
  277. Int2 SeqBufferDust (Uint1* sequence, Int4 length, Int4 offset,
  278.                     Int2 level, Int2 window, Int2 minwin, Int2 linker,
  279.                     BlastSeqLoc** dust_loc)
  280. {
  281. DREGION* reg,* regold;
  282. Int4 nreg;
  283.    Int2 status = 0;
  284.         /* place for dusted regions */
  285. regold = reg = (DREGION*) calloc(1, sizeof(DREGION));
  286. if (!reg)
  287.            return -1;
  288.         nreg = dust_segs (sequence, length, offset, reg, (Int4)level, 
  289.                   (Int4)window, (Int4)minwin, (Int4)linker);
  290.         status = GetDustLocations(dust_loc, reg, nreg);
  291.         /* clean up memory */
  292. reg = regold;
  293. while (reg)
  294. {
  295. regold = reg;
  296. reg = reg->next;
  297. sfree (regold);
  298. }
  299. return status;
  300. }