home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / network / blast2 / client / netblap2.c < prev    next >
Encoding:
Text File  |  1996-07-05  |  47.7 KB  |  1,687 lines  |  [TEXT/R*ch]

  1. /*
  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. * File Name: netblap1.c
  27. *
  28. * Author:  Epstein, Madden
  29. *
  30. * Version Creation Date:   06/16/95
  31. *
  32. * $Revision: 4.0 $
  33. *
  34. * File Description: 
  35. *       API for BLAST service
  36. *
  37. * Modifications:  
  38. * --------------------------------------------------------------------------
  39. * Date     Name        Description of modification
  40. * -------  ----------  -----------------------------------------------------
  41. * 2/24/94  Tatusov     Moved "traditional" BLAST output to blastout.c
  42. * 8/12/94  Epstein     Fixed order of blresp messages in BlastBioseq
  43. * 2/17/95  Madden      Addition of BlastBioseq2
  44. *
  45. * ==========================================================================
  46. *
  47. *
  48. * RCS Modification History:
  49. * $Log: netblap2.c,v $
  50.  * Revision 4.0  1995/07/26  13:55:34  ostell
  51.  * force revision to 4.0
  52.  *
  53.  * Revision 1.19  1995/07/25  15:02:28  madden
  54.  * Added print_usage to print out options.
  55.  *
  56.  * Revision 1.17  1995/07/24  17:33:08  madden
  57.  * removed debugging code that AsnWrites the response to a temp file.
  58.  *
  59.  * Revision 1.16  1995/07/24  16:34:25  madden
  60.  * replaced NETBLAP1_BUFFER_SIZE by NETBLAP2_BUFLEN.
  61.  *
  62.  * Revision 1.15  1995/07/24  16:26:35  madden
  63.  * Added MaskTheResidues to mask a number of residues at once.  Removed
  64.  * MaskThisResidue.
  65.  *
  66.  * Revision 1.14  1995/07/20  18:52:00  madden
  67.  * Replaced SeqIdPrint by SeqIdWrite.
  68.  *
  69.  * Revision 1.13  1995/07/19  14:03:56  madden
  70.  * Changed AdjustOffSetInSeqAnnot to adjust StdSegPtr.
  71.  *
  72.  * Revision 1.12  1995/07/18  21:06:03  madden
  73.  * Added call to AdjustOffSetInSeqAnnot to BlastSeqLoc2.
  74.  *
  75.  * Revision 1.11  1995/07/18  20:05:36  madden
  76.  * Changed masking of BlastSeqLoc2 for cases where blast does not start at
  77.  * the beginning of the SeqLoc.
  78.  *
  79.  * Revision 1.10  1995/07/12  17:42:29  madden
  80.  * Added parameter to BlastBioseq, BlastSeqLoc, BlastBioseq2, and BlastSeqLoc2
  81.  * to allow parts of sequence to be masked.  Also added the function
  82.  * MaskThisResidue to mask sequences with "N" or "X".
  83.  *
  84.  * Revision 1.9  1995/06/28  20:08:38  madden
  85.  * Added Boolean get_seqalign argument to SubmitBlastRequest.
  86.  *
  87.  * Revision 1.8  1995/06/28  18:28:07  madden
  88.  * Changed BlastBioseq2 and BlastSeqLoc2 to take an additional argument:
  89.  * a "BLAST0ResponsePtr PNTR".
  90.  *
  91.  * Revision 1.7  1995/06/28  15:38:17  madden
  92.  * BlastBioseq2 and BlastSeqLoc2 return NULL if no results.
  93.  *
  94.  * Revision 1.6  1995/06/23  22:14:53  madden
  95.  * Fixed problems identified by lint.
  96.  *
  97.  * Revision 1.5  1995/06/23  21:39:51  madden
  98.  * Sixth argument in BlastBioseq now takes a Uint4 rather than a BoolPtr.
  99.  *
  100.  * Revision 1.4  1995/06/22  17:06:04  madden
  101.  * Added functions SubmitSeqAlignBlastRequest and SubmitResultBlastRequest,
  102.  * changed BlastBioseq2 and BlastSeqLoc2 to take SeqAlignPtr directly from
  103.  * the BLAST output.
  104.  *
  105.  * Revision 1.3  1995/06/22  13:19:01  madden
  106.  * Added five Booleans to PrepRequestInfoPtr that control the amount of
  107.  * output, these correspond to the five Uint1's on BLAST0SearchPtr that
  108.  * determine whether a matrix, query seq, db seq, etc is returned.
  109.  *
  110.  * Revision 1.2  1995/06/22  12:54:45  madden
  111.  * Changed HitDataPtr to BLAST0ResultPtr.
  112.  *
  113.  * Revision 1.1  1995/06/16  11:26:59  epstein
  114.  * Initial revision
  115.  *
  116.  * Revision 1.28  95/05/17  17:59:27  epstein
  117.  * add RCS log revision history
  118.  * 
  119. */
  120.  
  121. #include <asn.h>
  122. #include <ncbi.h>
  123. #include <objseq.h>
  124. #include <objsset.h>
  125. #include <prtutil.h>
  126. #include <seqport.h>
  127. #include <sequtil.h>
  128. #include <netblap2.h>
  129. #include <ncbinet.h>
  130.  
  131.  
  132. #define NETBLAP2_BUFLEN 200
  133. #define STANDALONE
  134.  
  135. extern void MsgSetReadTimeout PROTO((NI_HandPtr mh, int t));
  136.  
  137. static Boolean ReestablishNetBlast PROTO((void));
  138. static Boolean NetInit PROTO((void));
  139. static Boolean ForceNetInit PROTO((void));
  140. static Boolean NetFini PROTO((void));
  141. static Boolean GenericReestablishNet PROTO((CharPtr svcName, Boolean showErrs));
  142.  
  143. static ByteStorePtr StoreResiduesInBS PROTO ((Uint1Ptr buffer, Int4 buf_len, ByteStorePtr bsp, Uint1Ptr bitctr_to, Uint1 newcode, Uint1 oldcode, Int4 len));
  144.  
  145. static BLAST0RequestPtr PrepareRequest PROTO ((PrepRequestInfoPtr prip));
  146.  
  147. static VoidPtr SubmitBlastRequest PROTO((BLAST0RequestPtr blreqp, BLAST0ResponsePtr PNTR blrespPtr, ProgressCallback progCallback, Boolean get_seqalign));
  148.  
  149. static BLAST0ResultPtr LIBCALL BlastSeqLoc PROTO ((SeqLocPtr slp, CharPtr progname, CharPtr dbname, CharPtr cmdLineOptions, BLAST0ResponsePtr PNTR blrespPtr, SeqLocPtr mask_seqloc, ProgressCallback progCallback));
  150.  
  151. static void MaskTheResidues PROTO((Uint1Ptr buffer, Int4 max_length, Uint1 mask_residue, Int4 offset, SeqLocPtr mask_slp));
  152.  
  153.  
  154. static void AdjustOffSetInSeqAnnot PROTO ((SeqAnnotPtr sap, SeqLocPtr slp));
  155.  
  156. static NI_HandPtr svcp = NULL;
  157. static AsnIoPtr   asnin = NULL;
  158. static AsnIoPtr   asnout = NULL;
  159. static Boolean num_attached = 0;
  160. static Boolean reallyFinal = TRUE;
  161. static NI_DispatcherPtr dispatcher;
  162.  
  163.  
  164. /*****************************************************************************
  165. *
  166. *   BlastInit ()
  167. *
  168. *****************************************************************************/
  169.  
  170. Boolean LIBCALL
  171. BlastInit (CharPtr clientId, Boolean ignoreErrs)
  172.  
  173. {
  174.     if (clientId != NULL && StrCmp(clientId, "blasttest") == 0)
  175.     {
  176.         asnin  = AsnIoOpen("blserver.inp", "r");
  177.         asnout = AsnIoOpen("blclient.out", "w");
  178.         
  179.         if (asnin == NULL || asnout == NULL)
  180.           return FALSE;
  181.     } else {
  182.         if (! NetInit())
  183.             return FALSE;
  184.     
  185.         svcp = NI_GenericGetService(dispatcher, NULL, "BLAST", "blast2", FALSE);
  186.         if (svcp == NULL)
  187.         {
  188.             ErrPost(CTX_UNKNOWN, 1, "NI_ServiceGet [%s] (%s)", ni_errlist[ni_errno], ni_errtext);
  189.             BlastFini();
  190.             return FALSE;
  191.         }
  192.     
  193.         MsgSetReadTimeout(svcp, 600);
  194.         asnin = svcp->raip;
  195.         asnout = svcp->waip;
  196.     }
  197.     
  198.     return TRUE;
  199. }
  200.  
  201. /*****************************************************************************
  202. *
  203. *   BlastFini ()
  204. *
  205. *****************************************************************************/
  206.  
  207. Boolean LIBCALL
  208. BlastFini()
  209.  
  210. {
  211.     NetFini();
  212.     return TRUE;
  213. }
  214.  
  215.  
  216. static Boolean LIBCALLBACK
  217. callbackWithMon (BLAST0ResponsePtr brp)
  218. {
  219.     static MonitorPtr mon = NULL;
  220.     BLAST0JobProgressPtr jprogp;
  221.     BLAST0JobDescPtr jdescp;
  222.  
  223.     switch (brp->choice)
  224.     {
  225.     case BLAST0Response_job_start:
  226.         if ((jdescp = (BLAST0JobDescPtr) brp->data.ptrvalue) == NULL)
  227.         {
  228.             return TRUE;
  229.         }
  230.         if (mon != NULL)
  231.         {
  232.             MonitorFree(mon);
  233.             mon = NULL;
  234.         }
  235.         mon = MonitorIntNew(jdescp->desc == NULL ? "BLAST" : jdescp->desc,
  236.                             0, jdescp->size);
  237.         return TRUE;
  238.     case BLAST0Response_job_progress:
  239.         if (mon != NULL)
  240.         {
  241.             if ((jprogp = (BLAST0JobProgressPtr) brp->data.ptrvalue) != NULL)
  242.             {
  243.                 MonitorIntValue(mon, jprogp->done);
  244.             }
  245.         }
  246.         return TRUE;
  247.     case BLAST0Response_job_done:
  248.         if (mon != NULL)
  249.         {
  250.             MonitorFree(mon);
  251.             mon = NULL;
  252.         }
  253.         return TRUE;
  254.     default:
  255.         return FALSE;
  256.     }
  257. }
  258.  
  259.  
  260. BLAST0ResultPtr LIBCALL
  261. SimpleBlastBioseq(BioseqPtr bsp, CharPtr progname, CharPtr dbname, CharPtr cmdLineOptions, Boolean useMonitors)
  262. {
  263.     return BlastBioseq(bsp, progname, dbname, cmdLineOptions, NULL, NULL, 15, useMonitors ? callbackWithMon : NULL);
  264. }
  265.  
  266. /***************************************************************************
  267. *
  268. *    Run BLAST on the BioseqPtr with the program "progname" and database
  269. *    "dbname".  By setting bits on the Uint4 one can determine the 
  270. *    amount of output returned.  These correspond to four of the five 
  271. *    Uint1's in BLAST0Search:
  272. *
  273. *        1st bit, if set omit matrix (return_matrix is FALSE);
  274. *        2nd bit, if set omit query (return_query is FALSE);
  275. *        3rd bit, if set omit query seq (return_query_seq_in_seg is FALSE);
  276. *        4th bit, if set omit db seq (return_db_seq_in_seg is FALSE);
  277. *
  278. *    "mask_seqloc" gives the position of the sequence to be masked.
  279. *    A filtering program (e.g., dust or seg should return a SeqLocPtr),
  280. *    indicating which sequence should be masked. 
  281. *
  282. ************************************************************************/
  283.  
  284. BLAST0ResultPtr LIBCALL
  285. BlastBioseq(BioseqPtr bsp, CharPtr progname, CharPtr dbname, CharPtr cmdLineOptions, BLAST0ResponsePtr PNTR blrespPtr, SeqLocPtr mask_seqloc, Uint4 output, ProgressCallback progCallback)
  286. {
  287.     BLAST0RequestPtr blreqp;
  288.     Boolean is_na;
  289.     BLAST0ResultPtr retval = NULL;
  290.     Int4 gi = -1;
  291.     Char textid[NETBLAP2_BUFLEN];
  292.     PrepRequestInfo pri;
  293.     SeqPortPtr spp;
  294.     ValNodePtr vnp;
  295.  
  296.     if (bsp == NULL)
  297.         return NULL;
  298.  
  299.     if (ISA_na(bsp->mol)) 
  300.     is_na = TRUE;
  301.     else
  302.     is_na = FALSE;
  303.  
  304.     if (is_na)
  305.         spp = SeqPortNew(bsp, 0, -1, 0, Seq_code_iupacna);
  306.     else
  307.         spp = SeqPortNew(bsp, 0, -1, 0, Seq_code_iupacaa);
  308.  
  309.     if (spp == NULL)
  310.     {
  311.         ErrPostEx(SEV_ERROR, 0, 0, "BlastBioseq: Unable to open SeqPort");
  312.     return NULL;
  313.     }
  314.  
  315.  
  316.     SeqIdWrite(bsp->id, textid, PRINTID_FASTA_LONG, NETBLAP2_BUFLEN);
  317.  
  318.     pri.is_na = is_na;
  319.     pri.defline = BioseqGetTitle(bsp);
  320.     pri.options = cmdLineOptions;
  321.     pri.dbname = dbname;
  322.     pri.textid = StringSave(textid);
  323.     pri.progname = progname;
  324.     pri.length = BioseqGetLen(bsp);
  325.     if ((vnp = bsp->id) != NULL) 
  326.     {
  327.     while (vnp)
  328.     {
  329.         if (vnp->choice == SEQID_GI)
  330.         {
  331.                   gi = vnp->data.intvalue;
  332.             break;
  333.         }
  334.         vnp = vnp->next;
  335.     }
  336.     }
  337.     pri.gi = gi;
  338.     pri.spp = spp;
  339.  
  340. /* Set flags in "pri" that control the amount returned. */
  341.  
  342.     if (output & BLAST_SERVER_OMIT_MATRIX)
  343.         pri.return_matrix = FALSE;
  344.     else
  345.         pri.return_matrix = TRUE;
  346.  
  347.     if (output & BLAST_SERVER_OMIT_QUERY)
  348.         pri.return_query = FALSE;
  349.     else
  350.         pri.return_query = TRUE;
  351.  
  352.     if (output & BLAST_SERVER_OMIT_QUERY_SEQ_IN_SEG)
  353.         pri.return_query_seq_in_seg = FALSE;
  354.     else
  355.         pri.return_query_seq_in_seg = TRUE;
  356.  
  357.     if (output & BLAST_SERVER_OMIT_DB_SEQ_IN_SEG)
  358.         pri.return_db_seq_in_seg = FALSE;
  359.     else
  360.         pri.return_db_seq_in_seg = TRUE;
  361.  
  362.     pri.return_BLAST0result = TRUE;    /* always a BLAST0Result */
  363.  
  364.     pri.mask = mask_seqloc;
  365.     pri.start = 0;
  366.  
  367.     blreqp = PrepareRequest(&pri);
  368.     
  369.     if (pri.spp)
  370.     pri.spp = SeqPortFree(pri.spp);
  371.  
  372.     retval = SubmitResultBlastRequest(blreqp, blrespPtr, progCallback);
  373.  
  374.     BLAST0RequestFree(blreqp);
  375.  
  376.     return retval;
  377. }
  378.  
  379. /************************************************************************
  380. *    Perform BLAST on the sequence from a SeqLoc.  The use of SeqLocId
  381. *    ensures that each SeqLoc is associated with only one SeqId,
  382. *    otherwise NULL is returned.
  383. ************************************************************************/
  384.  
  385. static BLAST0ResultPtr LIBCALL
  386. BlastSeqLoc(SeqLocPtr slp, CharPtr progname, CharPtr dbname, CharPtr cmdLineOptions, BLAST0ResponsePtr PNTR blrespPtr, SeqLocPtr mask_seqloc, ProgressCallback progCallback)
  387. {
  388.     BLAST0RequestPtr blreqp;
  389.     BioseqPtr bsp;
  390.     Boolean is_na;
  391.     BLAST0ResultPtr retval = NULL;
  392.     Int2 mol_type;
  393.     Int4 gi = -1;
  394.     Char textid[NETBLAP2_BUFLEN];
  395.     PrepRequestInfo pri;
  396.     SeqIdPtr sip;
  397.     SeqPortPtr spp;
  398.     ValNodePtr vnp;
  399.  
  400.     sip = SeqLocId(slp);
  401.     if (sip == NULL)
  402.     {
  403.         ErrPostEx(SEV_ERROR, 0, 0, "BlastSeqLoc: Unable to get SeqId");
  404.         return NULL;
  405.     }
  406.  
  407. /* Find the bsp for the title (i.e., defline) */
  408.     bsp = BioseqLockById(sip);
  409.     if (bsp == NULL)
  410.     {
  411.         ErrPostEx(SEV_ERROR, 0, 0, "BlastSeqLoc: Unable to get Bioseq");
  412.         return NULL;
  413.     }
  414.  
  415.     mol_type = SeqLocMol(slp);
  416.     
  417.     if (ISA_na(mol_type)) 
  418.     is_na = TRUE;
  419.     else
  420.     is_na = FALSE;
  421.  
  422.     if (is_na)
  423.         spp = SeqPortNewByLoc(slp, Seq_code_iupacna);
  424.     else
  425.         spp = SeqPortNewByLoc(slp, Seq_code_iupacaa);
  426.  
  427.     if (spp == NULL)
  428.     {
  429.         ErrPostEx(SEV_ERROR, 0, 0, "BlastBioseq: Unable to open SeqPort");
  430.     return NULL;
  431.     }
  432.  
  433.  
  434.     SeqIdWrite(sip, textid, PRINTID_FASTA_LONG, NETBLAP2_BUFLEN);
  435.  
  436.     pri.is_na = is_na;
  437.     pri.defline = BioseqGetTitle(bsp);
  438.     pri.options = cmdLineOptions;
  439.     pri.dbname = dbname;
  440.     pri.textid = StringSave(textid);
  441.     pri.progname = progname;
  442.     pri.length = SeqLocLen(slp);
  443.     if ((vnp = sip) != NULL) 
  444.     {
  445.     while (vnp)
  446.     {
  447.         if (vnp->choice == SEQID_GI)
  448.         {
  449.                   gi = vnp->data.intvalue;
  450.             break;
  451.         }
  452.         vnp = vnp->next;
  453.     }
  454.     }
  455.     pri.gi = gi;
  456.     pri.spp = spp;
  457.  
  458.     pri.mask = mask_seqloc;
  459.     pri.start = 0;
  460.  
  461.     blreqp = PrepareRequest(&pri);
  462.  
  463.     retval = SubmitResultBlastRequest(blreqp, blrespPtr, progCallback);
  464.  
  465.     BLAST0RequestFree(blreqp);
  466.  
  467.     return retval;
  468. }
  469.  
  470. /*****************************************************************
  471. *    Submits a BLAST0RequestPtr and returns BLAST0ResponsePtr.
  472. *    This function should not be used to submit search requests,
  473. *    (i.e., perform a BLAST search, BLAST0-Request.search)
  474. *    but for database inquiries etc.  To submit a search request
  475. *    use BlastBioseq, BlastBioseq2, SubmitSearchRequest, etc.
  476. *****************************************************************/
  477.  
  478. BLAST0ResponsePtr SubmitInfoRequest (BLAST0RequestPtr blreqp)
  479.  
  480. {
  481.     Boolean success;
  482.     BLAST0ResponsePtr blresp;
  483.  
  484.     success = BLAST0RequestAsnWrite (blreqp, asnout, NULL);
  485.     if (success == FALSE)
  486.     {
  487.            ErrPostEx(SEV_WARNING, 0, 0, "BLAST0RequestAsnWrite failed");
  488.        return NULL;
  489.     }
  490.     AsnIoReset (asnout);
  491.     /* read back response */
  492.     blresp = BLAST0ResponseAsnRead(asnin, NULL);
  493.  
  494.     return blresp;
  495. }
  496.  
  497. /********************************************************************
  498. *
  499. *    Prepare a request from the information in the PrepRequestInfoPtr.
  500. *    Note that only two alphabets (Seq_code_ncbi4na and 
  501. *    Seq_code_ncbistdaa) are supported.
  502. *********************************************************************/
  503. static BLAST0RequestPtr PrepareRequest (PrepRequestInfoPtr prip)
  504.  
  505. {
  506.  
  507.     Boolean is_na = prip->is_na;
  508.     BLAST0RequestPtr blreqp;
  509.     BLAST0SearchPtr blsrchp;
  510.     BLAST0SequencePtr blseqp;
  511.     BLAST0SeqDescPtr seqdesc;
  512.     Uint1 seqAlphabet;
  513.     Int4 index, start, total;
  514.     Int2 cmdLineLen;
  515.     Uint1 buffer[NETBLAP2_BUFLEN];
  516.     CharPtr p, pSave, q;
  517.     CharPtr cmdLineOptions = prip->options;
  518.     SeqLocPtr mask_slp = prip->mask;
  519.     Uint1 bitctr, residue, mask_residue;
  520.     ValNodePtr node;
  521.     SeqPortPtr spp = prip->spp;
  522.  
  523.     /* computed values */
  524.     ByteStorePtr theSequence;
  525.     Int2 alphabet;
  526.  
  527.     
  528.     alphabet = is_na ? BLAST0SeqData_ncbi4na : BLAST0SeqData_ncbistdaa;
  529.     seqAlphabet = is_na ? Seq_code_ncbi4na : Seq_code_ncbistdaa;
  530.  
  531.     if (is_na)
  532.     mask_residue = 'N';
  533.     else
  534.     mask_residue = 'X';
  535.  
  536.     theSequence = NULL;
  537.     bitctr = 0;
  538.     total=0;
  539.     start = prip->start;
  540.     while (total < prip->length)
  541.     {
  542.     index=0;
  543.         while ((residue=SeqPortGetResidue(spp)) != SEQPORT_EOF)
  544.         {
  545.         if (IS_residue(residue))
  546.         {
  547.                 buffer[index] = residue;
  548.             index++;
  549.         }
  550.                 else if (residue == SEQPORT_EOS)
  551.                         ErrPostEx(SEV_INFO, 0, 0,"[Segment boundary]\n");
  552.                 else if (residue == SEQPORT_VIRT)
  553.                         ErrPostEx(SEV_INFO, 0, 0,"[Virtual Sequence]\n");
  554.                 else
  555.                         ErrPostEx(SEV_INFO, 
  556.                 0, 0,"Unrecognized residue [%d]\n", residue);
  557.  
  558.         if (index == NETBLAP2_BUFLEN)
  559.             break;
  560.         }
  561.     if (index > 0)
  562.         MaskTheResidues(buffer, index, mask_residue, (start+total), mask_slp);
  563.     total += index;
  564.     if (index > 0)
  565.     {
  566.             if (is_na)
  567.                 theSequence = StoreResiduesInBS(buffer, index, theSequence, &bitctr, seqAlphabet, Seq_code_iupacna, prip->length);
  568.              else
  569.                 theSequence = StoreResiduesInBS(buffer, index, theSequence, &bitctr, seqAlphabet, Seq_code_iupacaa, prip->length);
  570.     }
  571.     else if (total == 0)
  572.     {
  573.             ErrPostEx(SEV_ERROR, 0, 0, "PrepareRequest: no sequence");
  574.         return NULL;
  575.     }
  576.     }
  577.     
  578.     blreqp = ValNodeNew(NULL);
  579.     blreqp->choice = BLAST0Request_search;
  580.     blsrchp = BLAST0SearchNew();
  581.     blreqp->data.ptrvalue = blsrchp;
  582.     blsrchp->program = StringSave(prip->progname);
  583.     blsrchp->database = StringSave(prip->dbname);
  584.     blseqp = BLAST0SequenceNew();
  585.     blsrchp->query = blseqp;
  586.     blsrchp->options = NULL;
  587. /* Go through the string cmdLineOptions taking off leading spaces. */
  588. /* If cmdLineOptions consists only of spaces it will be rejected. */
  589.     if (cmdLineOptions)
  590.         while (*cmdLineOptions == ' ')
  591.         cmdLineOptions++;
  592.     if (cmdLineOptions != NULL && *cmdLineOptions != NULLB)
  593.     { /* parse the string */
  594.         /* avoid using strtok(), since it's not reentrant */
  595.         cmdLineLen = StrLen(cmdLineOptions);
  596.         /* make a copy, and append a space to simplify parsing */
  597.         pSave = MemNew(cmdLineLen + 2);
  598.         StrCpy(pSave, cmdLineOptions);
  599.         pSave[cmdLineLen] = ' ';
  600.         pSave[cmdLineLen+1] = '\0';
  601.         p = pSave;
  602.         while ((q = StrPBrk(p, " \t")) != NULL)
  603.         {
  604.           *q = '\0';
  605.           if (blsrchp->options == NULL)
  606.           {
  607.             node = ValNodeNew(NULL);
  608.             blsrchp->options = node;
  609.           } else {
  610.             node = ValNodeNew(blsrchp->options);
  611.           }
  612.           node->data.ptrvalue = (VoidPtr) StringSave(p);
  613.           p = q + 1;
  614.           /* skip over the white space */
  615.           while (*p && ( *p == ' ' || *p == '\t'))
  616.             p++;
  617.         }
  618.         MemFree(pSave);
  619.     }
  620.  
  621. /* Set the Booleans that determine the amount of output. */
  622.     blsrchp->return_matrix = prip->return_matrix;
  623.     blsrchp->return_query = prip->return_query;
  624.     blsrchp->return_BLAST0result = prip->return_BLAST0result;
  625.     blsrchp->return_query_seq_in_seg = prip->return_query_seq_in_seg;
  626.     blsrchp->return_db_seq_in_seg = prip->return_db_seq_in_seg;
  627.  
  628.     seqdesc = BLAST0SeqDescNew();
  629.     blseqp->desc = seqdesc;
  630.  
  631.     seqdesc->id = ValNodeNew(NULL);
  632.     if (prip->gi != -1)
  633.     {
  634.       seqdesc->id->choice = BLAST0SeqId_giid;
  635.       seqdesc->id->data.intvalue = prip->gi;
  636.       seqdesc->id->next = ValNodeNew(NULL);
  637.       seqdesc->id = seqdesc->id->next;
  638.     }
  639.     seqdesc->id->choice = BLAST0SeqId_textid;
  640.     seqdesc->id->data.ptrvalue = prip->textid;
  641.     seqdesc->defline = StringSave(prip->defline);
  642.  
  643.     blseqp->length = prip->length;
  644.     blseqp->gcode = 1;
  645.     blseqp->seq = ValNodeNew(NULL);
  646.     blseqp->seq->choice = alphabet;
  647.     blseqp->seq->data.ptrvalue = theSequence;
  648.  
  649.     return blreqp;
  650.  
  651. }
  652.  
  653. /*************************************************************************
  654. *
  655. *    MaskTheResidues masks up to max_length residues in buffer.
  656. *    The residue to be used for masking (generally 'N' for nucleotides
  657. *    and 'X' for proteins) is mask_residue.  offset tells how far
  658. *    along the sequence the first residue in buffer is.  mask_slp
  659. *    specifies which parts of the sequence to mask.
  660. *
  661. *************************************************************************/
  662.  
  663. static void
  664. MaskTheResidues(Uint1Ptr buffer, Int4 max_length, Uint1 mask_residue, Int4 offset, SeqLocPtr mask_slp)
  665.  
  666. {
  667.     SeqLocPtr slp=NULL;
  668.         Int4 index, position, start, stop;
  669.        
  670.     while (mask_slp)
  671.     {
  672.             while((slp = SeqLocFindNext(mask_slp, slp))!=NULL)
  673.             {
  674.                       start = SeqLocStart(slp);
  675.                       stop = SeqLocStop(slp);
  676.             for (index=0; index<max_length; index++)
  677.             {
  678.                 position = index+offset;
  679.                 if (position >= start) 
  680.                 {
  681.                     if (position <= stop)
  682.                         buffer[index] = mask_residue;
  683.                     else if (position > stop)
  684.                         break;
  685.                 }
  686.             }
  687.             }
  688.         mask_slp = mask_slp->next;
  689.     }
  690.  
  691. }
  692.  
  693.  
  694. /**************************************************************************
  695. *
  696. *    Submits a BLAST0RequestPtr and returns a SeqAlignPtr.
  697. *    Checking is done that the BLAST0SearchPtr really specifies that a
  698. *    SeqAlignPtr should be returned.
  699. ************************************************************************/
  700. SeqAlignPtr
  701. SubmitSeqAlignBlastRequest(BLAST0RequestPtr blreqp, BLAST0ResponsePtr PNTR blrespPtr, ProgressCallback progCallback)
  702.  
  703. {
  704.     BLAST0SearchPtr search;
  705.     SeqAlignPtr seqalign;
  706.  
  707.     if (blreqp && blreqp->choice == BLAST0Request_search)
  708.     {
  709.        search = (BLAST0SearchPtr) blreqp->data.ptrvalue;
  710.        if (search->return_BLAST0result == FALSE)
  711.            seqalign = (SeqAlignPtr) SubmitBlastRequest(blreqp, blrespPtr, progCallback, TRUE);
  712.        else
  713.                ErrPostEx(SEV_WARNING, 0, 0, "SubmitSeqAlignBlastRequest: wrong type of BLAST0Search");
  714.     }
  715.     return seqalign;
  716. }
  717.  
  718. /**************************************************************************
  719. *
  720. *    Submits a BLAST0RequestPtr and returns a BLAST0ResultPtr.
  721. *    Checking is done that the BLAST0SearchPtr really specifies that a
  722. *    BLAST0ResultPtr should be returned.
  723. ************************************************************************/
  724. BLAST0ResultPtr
  725. SubmitResultBlastRequest(BLAST0RequestPtr blreqp, BLAST0ResponsePtr PNTR blrespPtr, ProgressCallback progCallback)
  726.  
  727. {
  728.     BLAST0SearchPtr search;
  729.     BLAST0ResultPtr result;
  730.  
  731.     if (blreqp && blreqp->choice == BLAST0Request_search)
  732.     {
  733.        search = (BLAST0SearchPtr) blreqp->data.ptrvalue;
  734.        if (search->return_BLAST0result == TRUE)
  735.            result = (BLAST0ResultPtr) SubmitBlastRequest(blreqp, blrespPtr, progCallback, FALSE);
  736.        else
  737.                ErrPostEx(SEV_WARNING, 0, 0, "SubmitResultBlastRequest: wrong type of BLAST0Search");
  738.     }
  739.     return result;
  740. }
  741.  
  742. /**************************************************************************
  743. *    
  744. *    Submit a BLAST search request (i.e., a BLAST0-Search) using a 
  745. *    BLAST0RequestPtr.  The return value is a VoidPtr, which must
  746. *    be recast as either a BLAST0ResultPtr or a SeqAlignPtr by
  747. *    the calling function.  The type of data returned is determined
  748. *    by BLAST0Search.return_BLAST0result.  This should be checked by
  749. *    the submitting function!
  750. *
  751. *************************************************************************/    
  752.  
  753. static VoidPtr
  754. SubmitBlastRequest(BLAST0RequestPtr blreqp, BLAST0ResponsePtr PNTR blrespPtr, ProgressCallback progCallback, Boolean get_seqalign)
  755.  
  756. {
  757.     Boolean done = FALSE, freeIt, success;
  758.     BLAST0ResponsePtr bllist = NULL, blresp;
  759.     BLAST0ResultPtr blastResult;
  760.     SeqAlignPtr seqalign;
  761.     VoidPtr retval = NULL;
  762.  
  763.     success = BLAST0RequestAsnWrite (blreqp, asnout, NULL);
  764.     if (success == FALSE || asnout == NULL)
  765.     {
  766.            ErrPostEx(SEV_WARNING, 0, 0, "BLAST0RequestAsnWrite failed");
  767.        return NULL;
  768.     }
  769.     AsnIoReset (asnout);    
  770.     
  771.     /* now read back response */
  772.     while (!done && (blresp = BLAST0ResponseAsnRead(asnin, NULL)) != NULL)
  773.     {
  774.         switch (blresp->choice) {
  775.         case BLAST0Response_ack:
  776.             done = TRUE;
  777.             break;
  778.         case BLAST0Response_result:
  779.             blastResult = (BLAST0ResultPtr) blresp->data.ptrvalue;
  780.             if (blastResult != NULL)
  781.             {
  782.                 retval = (VoidPtr) blastResult;
  783.                 blresp->data.ptrvalue = NULL; /* for clean free */
  784.             
  785.                 BLAST0ResponseFree(blresp);
  786.             }
  787.             break;
  788.         case BLAST0Response_seqalign:
  789.             seqalign = (SeqAlignPtr) blresp->data.ptrvalue;
  790.             if (seqalign != NULL)
  791.             {
  792.                 retval = (VoidPtr) seqalign;
  793.                 blresp->data.ptrvalue = NULL; /* for clean free */
  794.             
  795.                 BLAST0ResponseFree(blresp);
  796.             }
  797.             break;
  798.     
  799.         case BLAST0Response_job_start:
  800.         case BLAST0Response_job_progress:
  801.         case BLAST0Response_job_done:
  802.         default:
  803.             freeIt = TRUE;
  804.             if (progCallback != NULL)
  805.             {
  806.                 if (! progCallback(blresp))
  807.                 { /* otherwise, make a linked list of other portions of response */
  808.                     if (blrespPtr != NULL && get_seqalign == FALSE)
  809.                     {
  810.                         if (bllist != NULL)
  811.                         {
  812.                             bllist->next = blresp;
  813.                         } else {
  814.                             *blrespPtr = blresp;
  815.                         }
  816.  
  817.                         blresp->next = NULL;
  818.                         bllist = blresp;
  819.                         freeIt = FALSE;
  820.                     }
  821.                 }
  822.             }
  823. /* get_seqalign TRUE (BlastBioseq2 or BlastSeqLoc2); only warnings are saved. */
  824.         if (get_seqalign == TRUE && 
  825.         blresp->choice == BLAST0Response_status)
  826.         {
  827.                 *blrespPtr = blresp;
  828.         break;
  829.         }
  830.             if (freeIt)
  831.             {
  832.                 BLAST0ResponseFree(blresp);
  833.             }
  834.             break;
  835.         }
  836.     }
  837.     
  838.     return retval;
  839. }
  840.  
  841. /***************************************************************************
  842. *
  843. *    Produce a SeqAnnot from the BLAST data, that was produced using a
  844. *    Bioseq.
  845. *
  846. *    BLAST0ResponsePtr PNTR blrespPtr is used to return ONLY the 
  847. *    BLAST0ResponsePtr of type warning ("BLAST0Response_warning"),
  848. *    if an error occurs (e.g., bad option).
  849. *
  850. ***************************************************************************/
  851. SeqAnnotPtr LIBCALL
  852. BlastBioseq2(BioseqPtr bsp, CharPtr progname, CharPtr dbname, CharPtr blast_params, BLAST0ResponsePtr PNTR blrespPtr, SeqLocPtr mask_seqloc, Boolean useMonitors)
  853.  
  854. {
  855.     BLAST0RequestPtr blreqp;
  856.     Boolean is_na;
  857.     SeqAnnotPtr seqannot;
  858.     SeqAlignPtr seqalign;
  859.     Int4 gi = -1;
  860.     Char textid[NETBLAP2_BUFLEN];
  861.     PrepRequestInfo pri;
  862.     SeqPortPtr spp;
  863.     ValNodePtr vnp;
  864.  
  865.     if (bsp == NULL)
  866.         return NULL;
  867.  
  868.     if (ISA_na(bsp->mol)) 
  869.     is_na = TRUE;
  870.     else
  871.     is_na = FALSE;
  872.  
  873.     if (is_na)
  874.         spp = SeqPortNew(bsp, 0, -1, 0, Seq_code_iupacna);
  875.     else
  876.         spp = SeqPortNew(bsp, 0, -1, 0, Seq_code_iupacaa);
  877.  
  878.     if (spp == NULL)
  879.     {
  880.         ErrPostEx(SEV_ERROR, 0, 0, "BlastBioseq: Unable to open SeqPort");
  881.     return NULL;
  882.     }
  883.  
  884.  
  885.     SeqIdWrite(bsp->id, textid, PRINTID_FASTA_LONG, NETBLAP2_BUFLEN);
  886.  
  887.     pri.is_na = is_na;
  888.     pri.defline = BioseqGetTitle(bsp);
  889.     pri.options = blast_params;
  890.     pri.dbname = dbname;
  891.     pri.textid = StringSave(textid);
  892.     pri.progname = progname;
  893.     pri.length = BioseqGetLen(bsp);
  894.     if ((vnp = bsp->id) != NULL) 
  895.     {
  896.     while (vnp)
  897.     {
  898.         if (vnp->choice == SEQID_GI)
  899.         {
  900.                   gi = vnp->data.intvalue;
  901.             break;
  902.         }
  903.         vnp = vnp->next;
  904.     }
  905.     }
  906.     pri.gi = gi;
  907.     pri.spp = spp;
  908.  
  909. /* None of these are required. */
  910.     pri.return_matrix = FALSE;
  911.     pri.return_query = FALSE;
  912.     pri.return_query_seq_in_seg = FALSE;
  913.     pri.return_db_seq_in_seg = FALSE;
  914.     pri.return_BLAST0result = FALSE;
  915.     pri.mask = mask_seqloc;
  916.     pri.start = 0;
  917.  
  918.     blreqp = PrepareRequest(&pri);
  919.     
  920.     if (pri.spp)
  921.     pri.spp = SeqPortFree(pri.spp);
  922.  
  923.     seqalign = SubmitSeqAlignBlastRequest(blreqp, blrespPtr, useMonitors ? callbackWithMon : NULL);
  924.  
  925.     if (seqalign)
  926.     {
  927.         seqannot = SeqAnnotNew();
  928.         seqannot->type = 2;
  929.         seqannot->data = seqalign;
  930.     }
  931.     else
  932.     seqannot = NULL;
  933.  
  934.     BLAST0RequestFree(blreqp);
  935.  
  936.     return seqannot;
  937. }
  938.  
  939.  
  940. /***************************************************************************
  941. *
  942. *    Produce a SeqAnnot from the BLAST data, that was produced using a
  943. *    SeqLoc.
  944. *
  945. *    BLAST0ResponsePtr PNTR blrespPtr is used to return ONLY the 
  946. *    BLAST0ResponsePtr of type warning ("BLAST0Response_warning"),
  947. *    if an error occurs (e.g., bad option).
  948. *
  949. ***************************************************************************/
  950. SeqAnnotPtr LIBCALL
  951. BlastSeqLoc2(SeqLocPtr slp, CharPtr progname, CharPtr dbname, CharPtr blast_params, BLAST0ResponsePtr PNTR blrespPtr, SeqLocPtr mask_seqloc, Boolean useMonitors)
  952.  
  953. {
  954.     SeqAlignPtr seqalign;
  955.     SeqAnnotPtr seqannot;
  956.     BioseqPtr bsp;
  957.     BLAST0RequestPtr blreqp;
  958.     Boolean is_na;
  959.     Int2 mol_type;
  960.     Int4 gi = -1;
  961.     Char textid[NETBLAP2_BUFLEN];
  962.     PrepRequestInfo pri;
  963.     SeqIdPtr sip;
  964.     SeqPortPtr spp;
  965.     ValNodePtr vnp;
  966.  
  967.     sip = SeqLocId(slp);
  968.     if (sip == NULL)
  969.     {
  970.         ErrPostEx(SEV_ERROR, 0, 0, "BlastSeqLoc: Unable to get SeqId");
  971.         return NULL;
  972.     }
  973.  
  974. /* Find the bsp for the title (i.e., defline) */
  975.     bsp = BioseqLockById(sip);
  976.     if (bsp == NULL)
  977.     {
  978.         ErrPostEx(SEV_ERROR, 0, 0, "BlastSeqLoc: Unable to get Bioseq");
  979.         return NULL;
  980.     }
  981.  
  982.     mol_type = SeqLocMol(slp);
  983.     
  984.     if (ISA_na(mol_type)) 
  985.     is_na = TRUE;
  986.     else
  987.     is_na = FALSE;
  988.  
  989.     if (is_na)
  990.         spp = SeqPortNewByLoc(slp, Seq_code_iupacna);
  991.     else
  992.         spp = SeqPortNewByLoc(slp, Seq_code_iupacaa);
  993.  
  994.     if (spp == NULL)
  995.     {
  996.         ErrPostEx(SEV_ERROR, 0, 0, "BlastBioseq: Unable to open SeqPort");
  997.     return NULL;
  998.     }
  999.  
  1000.  
  1001.     SeqIdWrite(sip, textid, PRINTID_FASTA_LONG, NETBLAP2_BUFLEN);
  1002.  
  1003.  
  1004.     pri.is_na = is_na;
  1005.     pri.defline = BioseqGetTitle(bsp);
  1006.     pri.options = blast_params;
  1007.     pri.dbname = dbname;
  1008.     pri.textid = StringSave(textid);
  1009.     pri.progname = progname;
  1010.     pri.length = SeqLocLen(slp);
  1011.     if ((vnp = sip) != NULL) 
  1012.     {
  1013.     while (vnp)
  1014.     {
  1015.         if (vnp->choice == SEQID_GI)
  1016.         {
  1017.                   gi = vnp->data.intvalue;
  1018.             break;
  1019.         }
  1020.         vnp = vnp->next;
  1021.     }
  1022.     }
  1023.     pri.gi = gi;
  1024.     pri.spp = spp;
  1025.  
  1026.     pri.return_matrix = FALSE;
  1027.     pri.return_query = FALSE;
  1028.     pri.return_query_seq_in_seg = FALSE;
  1029.     pri.return_db_seq_in_seg = FALSE;
  1030.     pri.return_BLAST0result = FALSE;
  1031.     pri.mask = mask_seqloc;
  1032.     pri.start = SeqLocStart(slp);
  1033.  
  1034.     blreqp = PrepareRequest(&pri);
  1035.     
  1036.     if (pri.spp)
  1037.     pri.spp = SeqPortFree(pri.spp);
  1038.  
  1039.     seqalign = SubmitSeqAlignBlastRequest(blreqp, blrespPtr, useMonitors ? callbackWithMon : NULL);
  1040.  
  1041.     if (seqalign)
  1042.     {
  1043.         seqannot = SeqAnnotNew();
  1044.         seqannot->type = 2;
  1045.         seqannot->data = seqalign;
  1046.     }
  1047.     else
  1048.     seqannot = NULL;
  1049.  
  1050.     if (seqannot)
  1051.     AdjustOffSetInSeqAnnot(seqannot, slp);
  1052.  
  1053.     BLAST0RequestFree(blreqp);
  1054.  
  1055.     return seqannot;
  1056. }
  1057.  
  1058. /***********************************************************************
  1059. *
  1060. *    Adjust the Offset in the SeqAnnot to correspond to the beginning
  1061. *    of the sequence and not where BLAST started. 
  1062. *
  1063. *    This function works on SeqAnnot's that contain SeqAlignPtr's of
  1064. *    type DenseDiagPtr and StdSegPtr, which is what BLAST returns.    
  1065. *
  1066. *    The first id in each DenseDiag or StdSeg should correspond to the 
  1067. *    original BLAST'ed sequence.  The offset is only found once as it 
  1068. *    should be the same for every pair of hits.
  1069. *
  1070. **********************************************************************/
  1071.  
  1072. static void
  1073. AdjustOffSetInSeqAnnot(SeqAnnotPtr sap, SeqLocPtr slp)
  1074.  
  1075. {
  1076.     DenseDiagPtr ddp;
  1077.     Int4 offset;
  1078.     SeqAlignPtr salp;
  1079.     SeqIdPtr sip=NULL;
  1080.     SeqIntPtr seq_int;
  1081.     SeqLocPtr seqloc, whole_slp;
  1082.     StdSegPtr ssp;
  1083.     
  1084.         if (sap != NULL)
  1085.         {
  1086.             if (sap->type == 2)
  1087.             {   
  1088.                 salp = sap->data;
  1089.                 while (salp)
  1090.                 {
  1091.                    if (salp->segtype == 1)
  1092.                    {
  1093.                       ddp = salp->segs;
  1094.                       while (ddp)
  1095.                       {    /* Get the offset on the first call. */
  1096.             if (sip == NULL)
  1097.             {
  1098.                  sip = ddp->id;
  1099.                  whole_slp = 
  1100.                 ValNodeAddPointer(NULL, SEQLOC_WHOLE, sip);
  1101.                  offset = 
  1102.                 GetOffsetInLoc(slp, whole_slp, SEQLOC_START);
  1103.                  whole_slp = ValNodeFree(whole_slp);
  1104.             }
  1105.             ddp->starts[0] += offset;
  1106.                         ddp = ddp->next;
  1107.                       }
  1108.                    }   
  1109.            else if (salp->segtype == 3)
  1110.            {
  1111.             ssp = salp->segs;
  1112.             while (ssp)
  1113.             {
  1114.                  if (sip == NULL)
  1115.                  {
  1116.                     sip = ssp->ids;
  1117.                      whole_slp = 
  1118.                    ValNodeAddPointer(NULL, SEQLOC_WHOLE, sip);
  1119.                     offset = 
  1120.                        GetOffsetInLoc(slp, whole_slp, SEQLOC_START);
  1121.                     whole_slp = ValNodeFree(whole_slp);
  1122.                  }
  1123.                  seqloc = ssp->loc;
  1124.                  seq_int = seqloc->data.ptrvalue;
  1125.                  seq_int->from += offset;
  1126.                  seq_int->to += offset;
  1127.                              ssp = ssp->next;
  1128.             }
  1129.            }
  1130.                    salp = salp->next;
  1131.                 }
  1132.              }   
  1133.         }
  1134. }
  1135.  
  1136.  
  1137. /********************************************************************
  1138. *CharPtr FormatResultWithTemplate (HitdataPtr hitdata, StdPrintOptionsPtr Spop)
  1139. *
  1140. *    This function formats the data in the BLAST0ResultPtr using the
  1141. *    PrintTemplate functions found in the NCBI toolbox.  The data
  1142. *    in the BLAST0ResultPtr corresponds to the data in the ASN.1 
  1143. *    structure "BLAST0-Result".
  1144. ***********************************************************************/
  1145.  
  1146. CharPtr 
  1147. FormatResultWithTemplate (BLAST0ResultPtr blresp, StdPrintOptionsPtr Spop)
  1148.  
  1149. {
  1150.     if (blresp == NULL || Spop == NULL)
  1151.         return NULL;
  1152.  
  1153.         if (! StdFormatPrint((Pointer)blresp,
  1154.                 (AsnWriteFunc)BLAST0ResultAsnWrite, "StdBLAST0Result", Spop))
  1155.                         ErrPostEx(SEV_ERROR, 0, 0, "StdFormatPrint failed");
  1156.  
  1157.         if (Spop->ptr != NULL && *((CharPtr) (Spop->ptr)) != '\0')
  1158.                 return Spop->ptr;
  1159.         else
  1160.                 return NULL;
  1161. }    /* FormatResultWithTemplate */
  1162.  
  1163.  
  1164. /* convert from BLAST format to SeqFeat format */
  1165. static Int2
  1166. ConvertStrand(Int2 strand)
  1167. {
  1168.     switch (strand)
  1169.     {
  1170.     case BLAST0_Seq_interval_strand_plus:
  1171.     case BLAST0_Seq_interval_strand_plus_rf:
  1172.         return 1; /* plus */
  1173.     case BLAST0_Seq_interval_strand_minus:
  1174.     case BLAST0_Seq_interval_strand_minus_rf:
  1175.         return 2; /* minus */
  1176.     case BLAST0_Seq_interval_strand_both:
  1177.         return 3; /* both */
  1178.     default: /* unknown, or unable to convert */
  1179.         return 0;
  1180.     }
  1181. }
  1182.  
  1183.  
  1184. SeqAnnotPtr LIBCALL HitDataToSeqAnnotAlignment(BLAST0ResultPtr hdp, SeqIdPtr sip)
  1185. {
  1186.     SeqAnnotPtr sep;
  1187.     SeqAlignPtr sap;
  1188.     SeqAlignPtr last;
  1189.     /* Int4 dim; */ /* number of entries per BLAST0-segment */
  1190.     DenseDiagPtr ddp, lastddp;
  1191.     ScorePtr dstscore, lastscore;
  1192.     BLAST0HitListPtr hlp;
  1193.     BLAST0HSPPtr hsp;
  1194.     BLAST0SegmentPtr segp;
  1195.     BLAST0SeqIntervalPtr query;
  1196.     BLAST0SeqIntervalPtr hit;
  1197.     ScorePtr srcscore;
  1198.     CharPtr p;
  1199.     Boolean giidNotFound;
  1200.     BLAST0SeqDescPtr sdp;
  1201.     ValNodePtr vnp;
  1202.     SeqIdPtr hitid;
  1203.  
  1204.     if (hdp == NULL || hdp->hitlists == NULL)
  1205.         return NULL;
  1206.  
  1207.     SeqAsnLoad();
  1208.  
  1209.     sep = SeqAnnotNew();
  1210.     sep->type = 2; /* alignments */
  1211.  
  1212.     /* dim = hdp->dim;*/ /* should be 2, or 3 for BLAST3 */
  1213.  
  1214.     for (hlp = hdp->hitlists; hlp != NULL; hlp = hlp->next)
  1215.     {
  1216.         sap = SeqAlignNew();
  1217.         if (sep->data == NULL)
  1218.         {
  1219.             sep->data = sap;
  1220.         } else {
  1221.             last->next = sap;
  1222.         }
  1223.         last = sap;
  1224.         sap->type = 2; /* diags */
  1225.         sap->segtype = 1; /* dendiag */
  1226. /*        sap->dim = dim;*/
  1227.         sap->score = NULL;
  1228.         sap->segs = NULL;
  1229.         for (hsp = hlp->hsps; hsp != NULL; hsp = hsp->next)
  1230.         {
  1231.             segp = hsp->segs;
  1232.             if (segp != NULL && segp->next != NULL &&
  1233.                 (query = segp->loc) != NULL && (hit = segp->next->loc))
  1234.             {
  1235.                 ddp = DenseDiagNew();
  1236.                 if (sap->segs == NULL)
  1237.                 {
  1238.                     sap->segs = ddp;
  1239.                 } else {
  1240.                     lastddp->next = ddp;
  1241.                 }
  1242.                 lastddp = ddp;
  1243. /*                ddp->dim = dim;*/
  1244.                 ddp->len = hsp->len;
  1245.                 ddp->scores = NULL;
  1246.                 ddp->starts = (Int4Ptr) MemNew(2 * sizeof(Int4));
  1247.                 ddp->starts[0] = query->from;
  1248.                 ddp->starts[1] = hit->from;
  1249.                 ddp->strands = (Uint1Ptr) MemNew(2 * sizeof(Uint1));
  1250.                 ddp->strands[0] = ConvertStrand(query->strand);
  1251.                 ddp->strands[1] = ConvertStrand(hit->strand);
  1252.  
  1253.                 if (hlp->seqs != NULL)
  1254.                 {
  1255.                     sdp = hlp->seqs->desc;
  1256.                     giidNotFound = TRUE;
  1257.                     hitid = NULL;
  1258.                     for (vnp = sdp->id; vnp != NULL; vnp = vnp->next)
  1259.                     {
  1260.                         if (vnp->choice == BLAST0SeqId_giid &&
  1261.                             vnp->data.intvalue > 0)
  1262.                         {
  1263.                             SeqIdFree(hitid);
  1264.                             hitid = ValNodeNew(NULL);
  1265.                             hitid->choice = SEQID_GI;
  1266.                             hitid->data.intvalue = vnp->data.intvalue;
  1267.                             giidNotFound = FALSE;
  1268.                         } else {
  1269.                             if (vnp->choice == BLAST0SeqId_textid &&
  1270.                                 giidNotFound && vnp->data.ptrvalue != NULL)
  1271.                             {
  1272.                                 hitid = SeqIdParse(vnp->data.ptrvalue);
  1273.                             }
  1274.                         }
  1275.                     }
  1276.                     ddp->id = SeqIdDup(sip);
  1277.                     ddp->id->next = hitid;
  1278.                 }
  1279.                 for (srcscore = (ScorePtr) hsp->scores; srcscore != NULL; srcscore = srcscore->next)
  1280.                 { /* just copy the scores */
  1281.                     dstscore = ScoreNew();
  1282.                     if (ddp->scores == NULL)
  1283.                     {
  1284.                         ddp->scores = dstscore;
  1285.                     } else {
  1286.                         lastscore->next = dstscore;
  1287.                     }
  1288.                     lastscore = dstscore;
  1289.                     dstscore->id = ObjectIdDup(srcscore->id);
  1290.                     dstscore->value = srcscore->value;
  1291.                     dstscore->choice = srcscore->choice;
  1292.                 }
  1293.             }
  1294.         }
  1295.     }
  1296.  
  1297.     return sep;
  1298. }
  1299.  
  1300. SeqAnnotPtr LIBCALL HitDataToSeqAnnot(BLAST0ResultPtr hdp, SeqIdPtr sip)
  1301. {
  1302.     SeqAnnotPtr sep;
  1303.     SeqFeatPtr sfp, last;
  1304.     BLAST0HitListPtr hlp;
  1305.     BLAST0SegmentPtr segp;
  1306.     /*    Int4 dim;*/ /* number of entries per BLAST0-segment */
  1307.     BLAST0SeqIntervalPtr query;
  1308.     BLAST0SeqIntervalPtr hit;
  1309.     SeqLocPtr querySeqLoc;
  1310.     SeqLocPtr hitSeqLoc;
  1311.     SeqIntPtr querySeqInt;
  1312.     SeqIntPtr hitSeqInt;
  1313.     CharPtr p;
  1314.     Boolean giidNotFound;
  1315.     BLAST0SeqDescPtr sdp;
  1316.     ValNodePtr vnp;
  1317.  
  1318.     if (hdp == NULL || hdp->hitlists == NULL)
  1319.         return NULL;
  1320.  
  1321.     SeqAsnLoad();
  1322.  
  1323.     sep = SeqAnnotNew();
  1324.     sep->type = 1; /* Feature table */
  1325.  
  1326. /*    dim = hdp->dim;*/ /* should be 2, or 3 for BLAST3 */
  1327.  
  1328.     for (hlp = hdp->hitlists; hlp != NULL; hlp = hlp->next)
  1329.     {
  1330.         if (hlp->hsps != NULL)
  1331.         {
  1332.             segp = hlp->hsps->segs; /* ignore any other HSPs */
  1333.             if (segp != NULL && segp->next != NULL &&
  1334.                 (query = segp->loc) != NULL && (hit = segp->next->loc))
  1335.             {
  1336.                 sfp = SeqFeatNew();
  1337.                 if (sep->data == NULL)
  1338.                 {
  1339.                     sep->data = sfp;
  1340.                 } else {
  1341.                     last->next = sfp;
  1342.                 }
  1343.                 last = sfp;
  1344.  
  1345.                 sfp->data.choice = SEQFEAT_SEQ; /* value for seq int */
  1346.                 sfp->data.value.ptrvalue = (Pointer) ValNodeNew(NULL);
  1347.                 hitSeqLoc = sfp->data.value.ptrvalue;
  1348.                 hitSeqLoc->choice = SEQLOC_INT;
  1349.                 hitSeqInt = SeqIntNew();
  1350.                 hitSeqLoc->data.ptrvalue = (Pointer) hitSeqInt;
  1351.                 hitSeqInt->strand = ConvertStrand(hit->strand);
  1352.                 hitSeqInt->from = hit->from;
  1353.                 hitSeqInt->to = hit->to;
  1354.  
  1355.                 if (hlp->seqs != NULL)
  1356.                 {
  1357.                     sdp = hlp->seqs->desc;
  1358.                     if (sdp->defline != NULL)
  1359.                     {
  1360.                         sfp->comment = StringSave(sdp->defline);
  1361.                     }
  1362.                     giidNotFound = TRUE;
  1363.                     for (vnp = sdp->id; vnp != NULL; vnp = vnp->next)
  1364.                     {
  1365.                         if (vnp->choice == BLAST0SeqId_giid &&
  1366.                             vnp->data.intvalue > 0)
  1367.                         {
  1368.                             SeqIdFree(hitSeqInt->id);
  1369.                             hitSeqInt->id = ValNodeNew(NULL);
  1370.                             hitSeqInt->id->choice = SEQID_GI;
  1371.                             hitSeqInt->id->data.intvalue = vnp->data.intvalue;
  1372.                             giidNotFound = FALSE;
  1373.                         } else {
  1374.                             if (vnp->choice == BLAST0SeqId_textid &&
  1375.                                 giidNotFound && vnp->data.ptrvalue != NULL)
  1376.                             {
  1377.                                 hitSeqInt->id = SeqIdParse(vnp->data.ptrvalue);
  1378.                             }
  1379.                         }
  1380.                     }
  1381.                 }
  1382.  
  1383.                 sfp->location = ValNodeNew(NULL);
  1384.                 querySeqLoc = sfp->location;
  1385.                 querySeqLoc->choice = SEQLOC_INT;
  1386.                 querySeqInt = SeqIntNew();
  1387.                 querySeqLoc->data.ptrvalue = (Pointer) querySeqInt;
  1388.                 querySeqInt->strand = ConvertStrand(query->strand);
  1389.                 querySeqInt->from = query->from;
  1390.                 querySeqInt->to = query->to;
  1391.                 querySeqInt->id = SeqIdDup(sip);
  1392.             }
  1393.         }
  1394.     }
  1395.  
  1396.     return sep;
  1397. }
  1398.  
  1399.  
  1400. static Boolean ReestablishNetBlast(void)
  1401. {
  1402.     return GenericReestablishNet("blast1", TRUE);
  1403. }
  1404.  
  1405. static Boolean GenericReestablishNet(CharPtr svcName, Boolean showErrs)
  1406. {
  1407.     MonitorPtr mon = NULL;
  1408.     Boolean retval;
  1409.     CharPtr buf;
  1410.  
  1411.     buf = MemNew(2 * StrLen(svcName) + 60);
  1412.  
  1413.     if (showErrs) {
  1414.         sprintf (buf, "Re-establishing %s Service", svcName);
  1415.         mon = MonitorStrNew(buf, 40);
  1416.         sprintf (buf, "Requesting %s service", svcName);
  1417.         MonitorStrValue(mon, buf);
  1418.     }
  1419.     NetFini();
  1420.     retval = TRUE;
  1421.  
  1422.     if (! NetInit())
  1423.     {
  1424.         sprintf (buf, "%s get failed; re-contacting dispatcher", svcName);
  1425.         MonitorStrValue(mon, buf);
  1426.         retval = FALSE;
  1427.         if (ForceNetInit())
  1428.         { /* successfully established contact w/dispatcher */
  1429.             sprintf (buf, "%s get failed; re-requesting %s service",
  1430.                      svcName, svcName);
  1431.             MonitorStrValue(mon, buf);
  1432.             retval = NetInit();
  1433.         }
  1434.         else {
  1435.             ErrPost(CTX_UNKNOWN, 1, "Unable to re-contact dispatcher");
  1436.             if (showErrs) {
  1437.                 ErrShow();
  1438.             }
  1439.         }
  1440.     }
  1441.  
  1442.     MonitorFree(mon);
  1443.  
  1444.     if (! retval )
  1445.     {
  1446.         sprintf (buf, "Unable to re-establish %s service", svcName);
  1447.         ErrPost(CTX_UNKNOWN, 1, buf);
  1448.         if (showErrs) {
  1449.             ErrShow();
  1450.         }
  1451.     }
  1452.  
  1453.     MemFree(buf);
  1454.     return retval;
  1455. }
  1456.  
  1457. static Boolean
  1458. NetInit(void)
  1459. {
  1460.     if (num_attached++ > 0)
  1461.         return TRUE;
  1462.  
  1463.     return ((dispatcher = NI_GenericInit(NULL, NULL, TRUE, NULL, 0)) != NULL);
  1464. }
  1465.  
  1466.  
  1467. static Boolean ForceNetInit(void)
  1468. {
  1469.     Boolean retval;
  1470.  
  1471.     reallyFinal = FALSE;
  1472.     num_attached = 0; /* force re-attempt to contact dispatcher */
  1473.     retval = NetInit();
  1474.     reallyFinal = TRUE;
  1475.  
  1476.     return retval;
  1477. }
  1478.  
  1479. static Boolean NetFini(void)
  1480. {
  1481.     if (num_attached > 0)
  1482.         num_attached--;
  1483.  
  1484.     if (num_attached == 0)
  1485.     {
  1486.         NI_ServiceDisconnect(svcp);
  1487.         svcp = NULL;
  1488.         NI_EndServices (dispatcher);
  1489.         dispatcher = NULL;
  1490.     }
  1491.  
  1492.     return TRUE;
  1493. }
  1494. /*****************************************************************************
  1495. *
  1496. *   StoreResiduesInBS(Uint1Ptr, newcode, oldcode, len)
  1497.     Transfers the residues in buffer to the ByteStore "to". 
  1498. *    On the first call the ByteStore "to" should be NULL
  1499. *    and len should indicate the total number of residues in
  1500. *    the sequence.  bitctr_to may be any number.  On subsequent
  1501. *    calls bitctr_to  and to should be passed back in.
  1502. *    On every call buf_len should indicate how many residues are
  1503. *    to be transferred from buffer to "to".  
  1504. *
  1505. *    At present (2/22/95) this only works with oldcode of iupac[na]a.
  1506. *
  1507. *****************************************************************************/
  1508. static ByteStorePtr StoreResiduesInBS (Uint1Ptr buffer, Int4 buf_len, ByteStorePtr to, Uint1Ptr bitctr_to, Uint1 newcode, Uint1 oldcode, Int4 len)
  1509.  
  1510. {
  1511.     Boolean first_time;
  1512.     Int4 index, storelen;
  1513.     Uint1 byte_from, residue_from, bitctr_from, mask_from, lshift_from,
  1514.           rshift_from, bc_from ,
  1515.           byte_to, lshift_to[5], bc_to, byte_tmp;
  1516.     SeqMapTablePtr smtp;
  1517.  
  1518.     if ((! oldcode) || (! newcode) || (len <= 0))
  1519.         return NULL;
  1520.  
  1521.     if (to)
  1522.     first_time = FALSE;
  1523.     else
  1524.     first_time = TRUE;
  1525.  
  1526.     if ((smtp = SeqMapTableFind(newcode, oldcode)) == NULL)
  1527.         return NULL;
  1528.  
  1529.     if (newcode == Seq_code_ncbi2na)
  1530.         storelen = (len / 4) + 1;
  1531.     else if (newcode == Seq_code_ncbi4na)
  1532.         storelen = (len / 2) + 1;
  1533.     else
  1534.         storelen = len;
  1535.  
  1536.     if (first_time)
  1537.         to = BSNew((Uint4)storelen);
  1538.  
  1539.     if (to == NULL)
  1540.         return NULL;
  1541.  
  1542.     switch (oldcode)
  1543.     {
  1544.         case Seq_code_ncbi2na:
  1545.             bc_from = 4;            /* bit shifts needed */
  1546.             rshift_from = 6;
  1547.             lshift_from = 2;
  1548.             mask_from = 192;
  1549.             break;
  1550.         case Seq_code_ncbi4na:
  1551.             bc_from = 2;
  1552.             rshift_from = 4;
  1553.             lshift_from = 4;
  1554.             mask_from = 240;
  1555.             break;
  1556.         default:
  1557.             bc_from = 1;
  1558.             rshift_from = 0;
  1559.             lshift_from = 0;
  1560.             mask_from = 255;
  1561.             break;
  1562.     }
  1563.  
  1564.     lshift_to[1] = 0;
  1565.     switch (newcode)
  1566.     {
  1567.         case Seq_code_ncbi2na:
  1568.             bc_to = 4;            /* bit shifts needed */
  1569.             lshift_to[2] = 2;
  1570.             lshift_to[3] = 4;
  1571.             lshift_to[4] = 6;
  1572.             break;
  1573.         case Seq_code_ncbi4na:
  1574.             bc_to = 2;
  1575.             lshift_to[2] = 4;
  1576.             break;
  1577.         default:
  1578.             bc_to = 1;
  1579.             break;
  1580.     }
  1581.  
  1582.     if (first_time)
  1583.         *bitctr_to = bc_to;
  1584.     byte_to = 0;
  1585.     bitctr_from = 0;
  1586.  
  1587.     index = 0;
  1588.     while (index < buf_len)
  1589.     {
  1590.         if (! bitctr_from)        /* need a new byte */
  1591.         {
  1592.             byte_from = buffer[index];
  1593.             bitctr_from = bc_from;
  1594.         }
  1595.         residue_from = byte_from & mask_from;
  1596.         residue_from >>= rshift_from;
  1597.         byte_from <<= lshift_from;
  1598.         bitctr_from--;
  1599.  
  1600.         byte_tmp = SeqMapTableConvert(smtp, residue_from);
  1601.         if (byte_tmp == INVALID_RESIDUE)
  1602.         {
  1603.             ErrPostEx(SEV_ERROR, 0, 0, "StoreResiduesInBS: invalid residue [%d=%c]",
  1604.                 (int)residue_from, (char)residue_from);
  1605.             BSFree(to);
  1606.             return NULL;
  1607.         }
  1608.         byte_tmp <<= lshift_to[*bitctr_to];
  1609.         byte_to |= byte_tmp;
  1610.         (*bitctr_to)--;
  1611.         if (! *bitctr_to)
  1612.         {
  1613.             BSPutByte(to, byte_to);
  1614.             *bitctr_to = bc_to;
  1615.             byte_to = 0;
  1616.         }
  1617.     
  1618.         index++;
  1619.     }
  1620.  
  1621.     if (*bitctr_to != bc_to)      /* partial byte not written */
  1622.         BSPutByte(to, byte_to);
  1623.  
  1624.     return to;
  1625. }
  1626.  
  1627. /**************************************************************************
  1628. *
  1629. *    format the usage for a blast program
  1630.  
  1631. *    THis function is a clone of print_usage in busage.c in blastapp.
  1632. *    This function should be moved to "blast.c" soon, then both
  1633. *    server and client versions of BLAST can share it.
  1634. **************************************************************************/
  1635. int
  1636. print_usage(FILE *fp, ValNodePtr vnp)
  1637. {
  1638.     Char buf[512];
  1639.     CharPtr string, ptr;
  1640.  
  1641.     if (fp == NULL)
  1642.         return 0;
  1643.  
  1644.     if (vnp == NULL)
  1645.         return 0;
  1646.  
  1647.     fflush(stdout);
  1648.     fflush(fp);
  1649.  
  1650.     while (vnp)
  1651.     {
  1652.         string = vnp->data.ptrvalue;
  1653.         ptr = buf;
  1654.         while (*string != NULLB)
  1655.         {
  1656. /* If the character is a tilde, do a line return; if no tilde precedes the
  1657. end of the string, print without a line return! */
  1658.             if (*string == '~')
  1659.             {
  1660.                 *ptr = NULLB;
  1661.                 fprintf(fp, "%s\n", buf);
  1662.                 ptr = buf;
  1663.                 string++;
  1664.                 while (*string == '~')
  1665.                 {
  1666.                     fprintf(fp, "\n");
  1667.                     string++;
  1668.                 }
  1669.                 if (*string == NULLB)
  1670.                     break;
  1671.             }
  1672.             else if (*(string+1) == NULLB)
  1673.             {
  1674.                 ptr++;
  1675.                 *ptr = NULLB;
  1676.                 fprintf(fp, "%s", buf);
  1677.             }
  1678.             *ptr = *string;
  1679.             ptr++; string++;
  1680.         }
  1681.         
  1682.         vnp = vnp->next;
  1683.     }
  1684.  
  1685.     return 0;
  1686. }
  1687.