NCBI C Toolkit Cross Reference

C/algo/blast/api/blast_format.c


  1 /* $Id: blast_format.c,v 1.118 2009/06/16 20:39:39 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 offical 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 * Author: Ilya Dondoshansky
 27 *
 28 */
 29 
 30 /** @file blast_format.c
 31  * Formatting of BLAST results (SeqAlign)
 32  */
 33 
 34 #ifndef SKIP_DOXYGEN_PROCESSING
 35 static char const rcsid[] = "$Id: blast_format.c,v 1.118 2009/06/16 20:39:39 madden Exp $";
 36 #endif /* SKIP_DOXYGEN_PROCESSING */
 37 
 38 #include <algo/blast/api/blast_format.h>
 39 #include <algo/blast/api/blast_seq.h>
 40 #include <algo/blast/core/blast_filter.h>
 41 #include <algo/blast/core/blast_util.h>
 42 #include <algo/blast/api/blast_returns.h>
 43 #include <algo/blast/api/blast_seq.h>
 44 #include <algo/blast/composition_adjustment/composition_constants.h>
 45 #include <readdb.h>
 46 #include <txalign.h>
 47 #include <blfmtutl.h>
 48 #include <xmlblast.h>
 49 
 50 
 51 /** @addtogroup CToolkitAlgoBlast
 52  *
 53  * @{
 54  */
 55 
 56 /** Allocate and initialize the formatting options structure.
 57  * @param program_number Number of the BLAST program [in]
 58  * @param align_view What kind of formatted output to show? [in]
 59  * @param format_options_ptr The initialized structure [out]
 60  */
 61 static Int2
 62 s_BlastFormattingOptionsNew(EBlastProgramType program_number, 
 63                             EAlignView align_view, 
 64                             BlastFormattingOptions** format_options_ptr)
 65 {
 66    BlastFormattingOptions* format_options; 
 67 
 68    /* For translated RPS blast, the query will be a
 69       nucleotide sequence and subject sequences will
 70       be protein; thus the formatting must behave as
 71       if a blastx search was performed */
 72 
 73    if (program_number == eBlastTypeRpsTblastn)
 74       program_number = eBlastTypeBlastx;
 75 
 76    if ((format_options = (BlastFormattingOptions*)
 77         calloc(1, sizeof(BlastFormattingOptions))) == NULL)
 78       return -1;
 79    format_options->believe_query = FALSE;
 80 
 81    if ((program_number == eBlastTypeBlastx || 
 82         program_number == eBlastTypeTblastx)
 83         && align_view > 0 && align_view < eAlignViewXml)
 84    {
 85           ErrPostEx(SEV_FATAL, 1, 0, "This alignment view option is not "
 86                     "supported for blastx or tblastx");
 87           sfree(format_options);
 88           return -1;
 89    }
 90 
 91 
 92    format_options->print_options = 0;
 93    format_options->align_options = 0;
 94    format_options->align_options += TXALIGN_COMPRESS;
 95    format_options->align_options += TXALIGN_END_NUM;
 96    
 97    if (align_view == eAlignViewPairwise)
 98    {
 99       format_options->align_options += TXALIGN_MATRIX_VAL;
100       format_options->align_options += TXALIGN_SHOW_QS;
101    }
102    else
103    {
104        format_options->align_options += TXALIGN_MASTER;
105        if (align_view == eAlignViewQueryAnchoredIdent || 
106            align_view == eAlignViewFlatQueryAnchoredIdent)
107             format_options->align_options += TXALIGN_MISMATCH;
108        if (align_view == eAlignViewFlatQueryAnchoredIdent || 
109            align_view == eAlignViewFlatQueryAnchoredNoIdent ||
110            align_view == eAlignViewFlatQueryAnchoredBluntEnds)
111             format_options->align_options += TXALIGN_FLAT_INS;
112         if (align_view == eAlignViewQueryAnchoredBluntEnds || 
113             align_view == eAlignViewFlatQueryAnchoredBluntEnds)
114             format_options->align_options += TXALIGN_BLUNT_END;
115    }
116 
117    if (program_number == eBlastTypeBlastx)
118       format_options->align_options += TXALIGN_BLASTX_SPECIAL;
119    
120    format_options->align_view = align_view;
121 
122    *format_options_ptr = format_options;
123    return 0;
124 }
125 
126 Int2 
127 BlastPrintLogReport(FILE* outfp, Int4 num_processed)
128 {
129      if (!outfp)
130          return -1;
131 
132      /* Index of the next query to be processed is equal to the number of
133         queries processed so far. */
134      fprintf(outfp, "#Mega BLAST run finished, processed %ld queries\n", 
135              (long) num_processed);
136 
137      return 0;
138 }
139 
140 #define BXML_INCLUDE_QUERY 0x1
141 
142 /** Creates the header part of an XML report for a BLAST search.
143  * @param program Program name [in]
144  * @param database Database name [in]
145  * @param query_loc Query Seq-loc [in]
146  * @param flags Flag to indicate whether query sequence should be included in
147  *              the output. [in]
148  * @param search_param Search parameters [in]
149  */
150 static BlastOutput* 
151 s_CreateBlastOutputHead(const char* program, const char* database, 
152                         SeqLoc* query_loc, Int4 flags, 
153                         const Blast_SearchParams* search_param)
154 {
155     BlastOutput* boutp;
156     Char buffer[1024];
157     char* program_to_use = NULL;
158     
159     if((boutp = BlastOutputNew()) == NULL)
160         return FALSE;
161     
162     if (strcmp(program, "rpsblast") == 0)
163         program_to_use = strdup("blastp");
164     else if (strcmp(program, "rpstblastn") == 0)
165         program_to_use = strdup("blastx");
166     else
167         program_to_use = strdup(program);
168 
169     /* For optimization BLOSUM62 may be loaded ones */
170     if (query_loc) {
171        SeqId* sip = SeqLocId(query_loc);
172        Bioseq* bsp;
173        SeqIdWrite(sip, buffer, PRINTID_FASTA_LONG, sizeof(buffer));
174        boutp->query_ID = strdup(buffer);
175 
176        bsp = BioseqLockById(sip);
177 
178        if(bsp != NULL) {
179           if (BioseqGetTitle(bsp) != NULL)
180              boutp->query_def = strdup(BioseqGetTitle(bsp));
181           else
182              boutp->query_def = strdup("No definition line found");
183        }
184        BioseqUnlock(bsp);
185 
186        boutp->query_len = SeqLocLen(query_loc);
187 
188        if(flags & BXML_INCLUDE_QUERY) {
189            boutp->query_seq = (char *) calloc(boutp->query_len+1, 1);
190            SeqPortStreamLoc(query_loc, 
191                             STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL,
192                             boutp->query_seq, NULL);
193        } else {
194           boutp->query_seq = NULL;    /* Do we need sequence here??? */
195        }
196     }
197     /* Program name. Use the local version of the program. No need to copy it
198        since it was locally allocated. */
199     boutp->program = program_to_use;
200 
201     /* Database name */
202     if (database)
203         boutp->db = strdup(database);
204 
205     /* Version text */
206     sprintf(buffer, "%s %s [%s]", program_to_use, BlastGetVersionNumber(), 
207             BlastGetReleaseDate());
208     boutp->version = strdup(buffer);
209 
210     /* Reference */
211     boutp->reference = BlastGetReference(FALSE);
212 
213     /* Filling parameters */
214     boutp->param = ParametersNew();    
215     boutp->param->expect = search_param->expect;
216     boutp->param->gap_open = search_param->gap_open;
217     boutp->param->gap_extend = search_param->gap_extension;
218     if (search_param->matrix)
219         boutp->param->matrix = strdup(search_param->matrix);
220     boutp->param->sc_match = search_param->match;
221     boutp->param->sc_mismatch = search_param->mismatch;
222     boutp->param->include = search_param->ethresh;
223     if (search_param->filter_string)
224         boutp->param->filter = strdup(search_param->filter_string);
225     
226     return boutp;
227 }
228 
229 /** Finds ASN.1 type for printing appropriate parts of the XML output. */
230 #define MACRO_atp_find(atp,name)\
231         if((atp = AsnTypeFind(amp, #name))==NULL){\
232                 ErrPostEx(SEV_ERROR,0,0,\
233                         "Could not find type <%s>", #name);\
234                 return NULL; \
235         }
236 
237 
238 /** Initializes the XML output structure and prints the XML output header. 
239  * @param aip ASN.1 output stream [in]
240  * @param program BLAST program name [in]
241  * @param database BLAST database name [in]
242  * @param query_loc Query Seq-loc [in]
243  * @param flags Flag for query sequence inclusion [in]
244  * @param search_params BLAST search parameters [in]
245  * @return Initialized structure for printing XML output.
246  */
247 static MBXml* 
248 s_MBXmlInit(AsnIo* aip, char* program, char* database, 
249           SeqLoc* query_loc, Int4 flags, Blast_SearchParams* search_params)
250 {
251     MBXml* xmlp;
252     AsnModule* amp;
253     DataVal av;
254     AsnType* atp;
255     Boolean retval = FALSE;
256 
257     AsnType*       BLASTOUTPUT;
258     AsnType*       BLASTOUTPUT_program;
259     AsnType*       BLASTOUTPUT_version;
260     AsnType*       BLASTOUTPUT_reference;
261     AsnType*       BLASTOUTPUT_db;
262     AsnType*       BLASTOUTPUT_query_ID;
263     AsnType*       BLASTOUTPUT_query_def;
264     AsnType*       BLASTOUTPUT_query_len;
265     AsnType*       BLASTOUTPUT_query_seq;
266     AsnType*       BLASTOUTPUT_param;
267     AsnType*       BLASTOUTPUT_iterations;
268     AsnType*       BLASTOUTPUT_iterations_E;
269     AsnType*       BLASTOUTPUT_mbstat;
270 
271     if (strcmp(program, "rpsblast") == 0)
272        program = "blastp";
273     else if (strcmp(program, "rpstblastn") == 0)
274        program = "blastx";
275 
276     AsnSetXMLmodulePrefix("http://www.ncbi.nlm.nih.gov/dtd/");
277     xmlp = (MBXml*) MemNew(sizeof(MBXml));
278     
279     xmlp->aip = aip;
280     
281     if (! bxmlobjAsnLoad()) {
282         return NULL;
283     }
284     
285     amp = AsnAllModPtr();
286 
287     MACRO_atp_find(BLASTOUTPUT,BlastOutput);
288     MACRO_atp_find(BLASTOUTPUT_program,BlastOutput.program);
289     MACRO_atp_find(BLASTOUTPUT_version,BlastOutput.version);
290     MACRO_atp_find(BLASTOUTPUT_reference,BlastOutput.reference);
291     MACRO_atp_find(BLASTOUTPUT_db,BlastOutput.db);
292     MACRO_atp_find(BLASTOUTPUT_query_ID,BlastOutput.query-ID);
293     MACRO_atp_find(BLASTOUTPUT_query_def,BlastOutput.query-def);
294     MACRO_atp_find(BLASTOUTPUT_query_len,BlastOutput.query-len);
295     MACRO_atp_find(BLASTOUTPUT_query_seq,BlastOutput.query-seq);
296     MACRO_atp_find(BLASTOUTPUT_param,BlastOutput.param);
297     MACRO_atp_find(BLASTOUTPUT_iterations,BlastOutput.iterations);
298     MACRO_atp_find(BLASTOUTPUT_iterations_E,BlastOutput.iterations.E);
299     MACRO_atp_find(BLASTOUTPUT_mbstat,BlastOutput.mbstat);
300 
301     /* Start of iterations structure */
302     xmlp->atp = BLASTOUTPUT_iterations_E;
303 
304     /* Head of all BlastOutput structure */
305     xmlp->BlastOutput = BLASTOUTPUT;
306     
307     /* Head of iterations strucure */
308     xmlp->BlastOutput_iterations = BLASTOUTPUT_iterations;
309 
310     /* Head of the final statistics for Mega BLAST */
311     xmlp->BlastOutput_mbstat = BLASTOUTPUT_mbstat;
312     
313     xmlp->boutp = s_CreateBlastOutputHead(program, database, query_loc, flags, search_params);
314     
315     atp = AsnLinkType(NULL, BLASTOUTPUT);   /* link local tree */
316     
317     if (atp == NULL) {
318         return NULL;
319     }
320     
321     if (! AsnOpenStruct(xmlp->aip, atp, (Pointer) xmlp->boutp)) {
322         return NULL;
323     }
324 
325     if (xmlp->boutp->program != NULL) {
326         av.ptrvalue = xmlp->boutp -> program;
327         retval = AsnWrite(xmlp->aip, BLASTOUTPUT_program,  &av);
328     }
329     
330     if (xmlp->boutp->version != NULL) {
331         av.ptrvalue = xmlp->boutp->version;
332         retval = AsnWrite(xmlp->aip, BLASTOUTPUT_version,  &av);
333     }
334     
335     if (xmlp->boutp->reference != NULL) {
336         av.ptrvalue = xmlp->boutp->reference;
337         retval = AsnWrite(xmlp->aip, BLASTOUTPUT_reference,  &av);
338     }
339 
340     if (xmlp->boutp -> db != NULL) {
341         av.ptrvalue = xmlp->boutp->db;
342         retval = AsnWrite(xmlp->aip, BLASTOUTPUT_db,  &av);
343     }
344 
345     if (xmlp->boutp -> query_ID != NULL) {
346         av.ptrvalue = xmlp->boutp->query_ID;
347         retval = AsnWrite(xmlp->aip, BLASTOUTPUT_query_ID,  &av);
348     }
349 
350     if (xmlp->boutp->query_def != NULL) {
351         av.ptrvalue = xmlp->boutp->query_def;
352         retval = AsnWrite(xmlp->aip, BLASTOUTPUT_query_def,  &av);
353     }
354 
355     av.intvalue = xmlp->boutp->query_len;
356     retval = AsnWrite(xmlp->aip, BLASTOUTPUT_query_len,  &av);
357 
358     if (xmlp->boutp->query_seq != NULL) {
359         av.ptrvalue = xmlp->boutp->query_seq;
360         retval = AsnWrite(xmlp->aip, BLASTOUTPUT_query_seq,  &av);
361     }
362 
363     if (xmlp->boutp->param != NULL) {
364         if (!ParametersAsnWrite(xmlp->boutp->param, 
365                                 xmlp->aip, BLASTOUTPUT_param)) {
366             return NULL;
367         }
368     }
369 
370     if(!AsnOpenStruct(xmlp->aip, BLASTOUTPUT_iterations, NULL))
371         return NULL;
372     
373     AsnIoFlush(xmlp->aip);
374     
375     return xmlp;
376 }
377 
378 /** Fills the Statistics ASN.1 generated structure for the XML report.
379  * @param sum_returns Search summary return data [in]
380  * @param ungapped Is this an ungapped search? [in]
381  * @return Populated structure.
382  */
383 static Statistics*
384 s_XMLBuildStatistics(Blast_SummaryReturn* sum_returns, Boolean ungapped)
385 {
386    Statistics* stat;
387    Blast_DatabaseStats* db_stats = sum_returns->db_stats;
388 
389    stat = StatisticsNew();
390 
391    stat->eff_space = (double) db_stats->eff_searchsp;
392    stat->hsp_len = db_stats->hsp_length;
393    stat->db_num= db_stats->dbnum;
394    stat->db_len = db_stats->dblength;
395 
396    if(ungapped) {
397       if(sum_returns->ka_params != NULL) {
398          stat->lambda = sum_returns->ka_params->Lambda;
399          stat->kappa = sum_returns->ka_params->K;
400          stat->entropy = sum_returns->ka_params->H;
401       }
402    } else {
403       if(sum_returns->ka_params_gap != NULL) {
404          stat->lambda = sum_returns->ka_params_gap->Lambda;
405          stat->kappa = sum_returns->ka_params_gap->K;
406          stat->entropy = sum_returns->ka_params_gap->H;
407       }
408    }
409 
410    return stat;
411 }
412 
413 /** Fills the Iteration ASN.1 structure, for part of the BLAST XML report
414  * corresponding to one query.
415  * @param seqalign Seq-align list with results [in]
416  * @param sum_returns Search summary data [in]
417  * @param is_ooframe Was out-of-frame gapping used in this search? [in]
418  * @param ungapped Was this an ungapped search? [in]
419  * @param iter_num Index of this "iteration" (query). [in]
420  * @param message Error or warning message [in]
421  * @param query Query Bioseq [in]
422  * @param mask_loc List of masking locations [in]
423  * @return Populated structure.
424  */
425 static Iteration* 
426 s_XMLBuildOneQueryIteration(SeqAlign* seqalign,
427                             Blast_SummaryReturn* sum_returns,
428                             Boolean is_ooframe, Boolean ungapped,
429                             Int4 iter_num, char* message,
430                             Bioseq* query, ValNode* mask_loc)
431 {
432     Iteration* iterp = IterationNew();
433     iterp->iter_num = iter_num;
434 
435     if (query) {
436        char buffer[1024];
437        SeqIdWrite(query->id, buffer, PRINTID_FASTA_LONG, sizeof(buffer));
438        iterp->query_ID = strdup(buffer);
439 
440        if(BioseqGetTitle(query) != NULL)
441           iterp->query_def = strdup(BioseqGetTitle(query));
442        else
443           iterp->query_def = strdup("No definition line found");
444 
445        iterp->query_len = query->length;
446     }
447 
448     if(seqalign != NULL) {
449        iterp->hits =
450           BXMLSeqAlignToHits(seqalign, ungapped, is_ooframe, mask_loc);
451     }
452 
453     iterp->stat = s_XMLBuildStatistics(sum_returns, ungapped);
454 
455     if (message)
456         iterp->message = strdup(message);
457 
458     return iterp;
459 }
460 
461 Int2 BlastFormattingInfoNew(EAlignView align_view, 
462                             const SBlastOptions* search_options,
463                             const char* program_name, const char* db_name, 
464                             const char* outfile_name, 
465                             BlastFormattingInfo* *info_ptr)
466 {
467     BlastFormattingInfo* info;
468     
469     if (!outfile_name || !info_ptr || !search_options || 
470         align_view >= eAlignViewMax)
471         return -1;
472 
473     info = *info_ptr = 
474         (BlastFormattingInfo*) calloc(1, sizeof(BlastFormattingInfo));
475 
476     s_BlastFormattingOptionsNew(search_options->program, align_view, 
477                                 &info->format_options);
478     info->search_options = search_options;
479     info->program_name = strdup(program_name);
480     if (db_name)
481         info->db_name = strdup(db_name);
482 
483    if (align_view != eAlignViewXml && align_view < eAlignViewAsnText) {
484       FILE* outfp;
485       if ((outfp = FileOpen(outfile_name, "w")) == NULL)
486       {
487           ErrPostEx(SEV_WARNING, 0, 0, "Unable to open output file %s:", outfile_name);
488           return -1;
489       }
490       info->outfp = outfp;
491    } else {
492       char write_mode[3];
493       /* AsnIoOpen requires a non-const argument, so use a local variable. */
494       char* filename_copy = strdup(outfile_name);
495       if (align_view == eAlignViewXml)
496           strcpy(write_mode, "wx");
497       else if (align_view == eAlignViewAsnText)
498           strcpy(write_mode, "w"); 
499       else
500           strcpy(write_mode, "wb"); 
501       
502       if ((info->aip = AsnIoOpen(filename_copy, write_mode)) == NULL)
503       {
504           ErrPostEx(SEV_WARNING, 0, 0, "Unable to open output file %s:", filename_copy);
505           return -1;
506       }
507       sfree(filename_copy);
508    }
509    info->is_seqalign_null = TRUE; /* will be updated in BLAST_FormatResults */
510    info->head_on_every_query = FALSE; /* One header for a file is the default. */
511    return 0;
512 }
513 
514 Int2 BlastFormattingInfoNewBasic(EAlignView align_view, 
515                                  const BLAST_SummaryOptions* basic_options,
516                                  SeqLoc* query_seqloc,
517                                  const char* outfile_name, 
518                                  SBlastOptions* *advanced_options,
519                                  BlastFormattingInfo* *info_ptr)
520 {
521     Blast_SummaryReturn* extra_returns = Blast_SummaryReturnNew();
522     char* program_name = NULL;
523     Int2 status = 0;
524 
525     Blast_SearchOptionsFromSummaryOptions(basic_options, query_seqloc,
526                                           extra_returns, advanced_options,
527                                           &program_name);
528 
529     Blast_SummaryReturnFree(extra_returns);
530 
531     status =
532         BlastFormattingInfoNew(align_view, *advanced_options, program_name, 
533                                NULL, outfile_name, info_ptr);
534     sfree(program_name);
535     return status;
536 }
537 
538 void 
539 BlastFormattingInfoSetUpOptions(BlastFormattingInfo* info, Int4 num_descriptions,
540                                 Int4 num_alignments, Boolean html, 
541                                 Boolean is_megablast, Boolean show_gi,
542                                 Boolean believe_defline)
543 {
544     ASSERT(info && info->format_options && info->search_options);
545 
546     info->format_options->number_of_descriptions = num_descriptions;
547     info->format_options->number_of_alignments = num_alignments;
548     info->format_options->html = html;
549     if (html) {
550         info->format_options->align_options += TXALIGN_HTML;
551         info->format_options->print_options += TXALIGN_HTML;
552     }
553     info->format_options->is_megablast = is_megablast;
554     if (show_gi) {
555         info->format_options->align_options += TXALIGN_SHOW_GI;
556         info->format_options->print_options += TXALIGN_SHOW_GI;
557     }
558 
559     if (!info->search_options->score_options->gapped_calculation)
560         info->format_options->print_options += TXALIGN_SHOW_NO_OF_SEGS;
561 
562     info->format_options->believe_query = believe_defline;
563 }
564 
565 BlastFormattingInfo* BlastFormattingInfoFree(BlastFormattingInfo* info)
566 {
567     if (info->outfp)
568         FileClose(info->outfp);
569     /* Free the XML or ASN.1 i/o structure. Note that info->aip is set for
570        XML too, but it should not be freed twice. */
571     if (info->xmlp) {
572         Boolean ungapped = 
573             !info->search_options->score_options->gapped_calculation;
574         MBXmlClose(info->xmlp, NULL, ungapped);
575     } else if (info->aip) {
576         AsnIoClose(info->aip);
577     }
578     sfree(info->program_name);
579     sfree(info->db_name);
580     sfree(info->format_options);
581     /* The remaining fields are not owned by the structure. */
582     sfree(info);
583 
584     return NULL;
585 }
586 
587 Uint1 
588 GetOldAlignType(EBlastProgramType prog, Boolean* db_is_na)
589 {
590     Uint1 align_type = 0;
591 
592     switch (prog) {
593     case eBlastTypeBlastp: case eBlastTypeRpsBlast: case eBlastTypePhiBlastp:
594     case eBlastTypePsiBlast:
595         align_type = 2;
596         *db_is_na = FALSE;
597         break;
598     case eBlastTypeBlastn: case eBlastTypePhiBlastn: 
599         align_type = 1;
600         *db_is_na = TRUE;
601         break;
602     case eBlastTypeBlastx: case eBlastTypeRpsTblastn:
603         align_type = 3;
604         *db_is_na = FALSE;
605         break;
606     case eBlastTypePsiTblastn: case eBlastTypeTblastn:
607         align_type = 4;
608         *db_is_na = TRUE;
609         break;
610     case eBlastTypeTblastx:
611         align_type = 5;
612         *db_is_na = TRUE;
613         break;        
614     default:
615         break;
616     }
617     return align_type;
618 }
619 
620 /** Deletes matrix generated by s_LoadMatrix
621  * @param matrix data to be freed [in]
622  */
623 const int k_MatrixSize = 128;
624 static void s_DeleteMatrix(Int4** matrix)
625 {
626     int i;
627     if (matrix == NULL)
628       return;
629 
630     for(i=0; i<k_MatrixSize; i++)
631          MemFree(matrix[i]);
632 
633     MemFree(matrix);
634 
635     return;
636 }
637 
638 /** Adopted from api/jzcoll.c:load_default_matrix
639  * We take the compressed matrix and move it 
640  * to a format that includes all ASCII letters,
641  * though most cells will be blank.  this is understodd
642  * by txalign.c and does not seem worth fixing now.
643  * @param name matrix name (e.g., BLOSUM90) [in]
644  */
645 static Int4** s_LoadMatrix(const char* name)
646 {
647     Int4** ss;
648     int i, j;
649     int dim = 0;
650     const char* pchars = NULL;
651     SNCBIPackedScoreMatrix* pack_matrix = 
652        NCBISM_GetStandardMatrix(name?name:BLAST_DEFAULT_MATRIX);
653 
654     if (pack_matrix == NULL)
655         return NULL;
656 
657     pchars = pack_matrix->symbols;
658     dim = strlen(pchars);
659 
660     ss = (Int4**) MemNew((size_t)k_MatrixSize * sizeof (Int4*));
661     if (ss == NULL)
662        return NULL;
663 
664     for(i = 0; i<k_MatrixSize; ++i)
665            ss[i] = (Int4*) MemNew((size_t)k_MatrixSize * sizeof (Int4));
666 
667     for(i = 0; i < k_MatrixSize; i++)
668            for(j = 0; j < k_MatrixSize;j++)
669                  ss[i][j] = -1000;
670 
671     for(i = 0; i < dim; ++i)
672            for(j = 0; j < dim; ++j)
673                  ss[pchars[i]][pchars[j]] = pack_matrix->scores[(i*dim)+j];
674 
675     return ss;
676 }
677 
678 
679 
680 static Int2
681 s_BLAST_PrintDatabaseInfo(const BlastFormattingInfo* format_info)
682 {
683    Int2 status = 0;
684    BlastFormattingOptions* format_options = format_info->format_options;
685 
686    if (format_options->align_view < eAlignViewXml) {
687       if(format_info->db_name) { 
688          EBlastProgramType prog = format_info->search_options->program;
689          const Boolean kDbIsProt = 
690               (prog == eBlastTypeBlastp || prog == eBlastTypeBlastx ||
691                prog == eBlastTypeRpsBlast || prog == eBlastTypeRpsTblastn ||
692                prog == eBlastTypePhiBlastp);
693          init_buff_ex(90);
694          status = 
695             PrintDbInformation(format_info->db_name, kDbIsProt, 70, 
696                                format_info->outfp, format_options->html);
697          free_buff();
698       }
699    }
700    return status;
701 }
702 
703 /** Prints out the description of a query sequence, along
704  *  with notification that the query has no hits
705  * @param slp The query Seq-loc
706  * @param format_options Options for formatting
707  * @param outfp File to which the output will be directed
708  */
709 static void 
710 s_AcknowledgeEmptyResults(SeqLoc *slp,
711                           BlastFormattingOptions* format_options,
712                           const BlastFormattingInfo* format_info,
713                           FILE *outfp)
714 {
715     Bioseq *bsp = BioseqLockById(SeqLocId(slp));
716 
717     if (format_info->head_on_every_query == TRUE)
718         BLAST_PrintOutputHeader(format_info);
719 
720     init_buff_ex(70);
721     AcknowledgeBlastQuery(bsp, 70, outfp, 
722        format_options->believe_query, format_options->html);
723     free_buff();
724     BioseqUnlock(bsp);
725 
726     if (format_info->head_on_every_query == TRUE)
727     {
728         s_BLAST_PrintDatabaseInfo(format_info);
729         fprintf(format_info->outfp, "%s", "Searching..................................................done\n\n");
730     }
731     fprintf(outfp, " ***** No hits found ******\n\n\n");
732 }
733 
734 Int2 BLAST_FormatResults(SBlastSeqalignArray* seqalign_arr, Int4 num_queries, 
735         SeqLoc* query_slp, SeqLoc* mask_loc_head, 
736         BlastFormattingInfo* format_info,
737         Blast_SummaryReturn* sum_returns)
738 {  
739    SeqLoc* mask_loc;
740    SeqLoc* next_mask_loc = NULL;
741    SeqLoc* tmp_loc = NULL;
742    Uint1 align_type;
743    Boolean db_is_na;
744    Int4 query_index;
745    SeqLoc* slp;
746    SeqLoc* mask_slp;
747    AsnIo* aip = NULL;
748    MBXml* xmlp = NULL;
749    FILE *outfp = NULL;
750    BlastFormattingOptions* format_options;
751    EAlignView align_view;
752    Boolean ungapped;
753 
754    ASSERT(format_info && format_info->format_options && 
755           format_info->search_options && query_slp);
756 
757    format_options = format_info->format_options;
758    align_view = format_options->align_view;
759    ungapped = 
760        !format_info->search_options->score_options->gapped_calculation;
761 
762    if (align_view == eAlignViewXml) {
763        const Int4 kXmlFlag = 0; /* Change to BXML_INCLUDE_QUERY if inclusion
764                                    of query sequence is desired in the XML
765                                    output header. */
766        xmlp = format_info->xmlp;
767        if (!xmlp) {
768            xmlp = format_info->xmlp = 
769                s_MBXmlInit(format_info->aip, format_info->program_name, 
770                            format_info->db_name, query_slp, kXmlFlag, 
771                            sum_returns->search_params);
772        }
773    } else if (align_view == eAlignViewAsnText || 
774               align_view == eAlignViewAsnBinary)
775        aip = format_info->aip; 
776    else 
777        outfp = format_info->outfp;
778 
779    align_type = 
780        GetOldAlignType(format_info->search_options->program, &db_is_na);
781 
782    if (format_info->db_name) {
783        /* Enable fetching from the BLAST database. */
784       ReadDBBioseqFetchEnable ("blast", format_info->db_name, db_is_na, TRUE);
785       /* If database is translated, set the genetic code for tranlation. */
786       if (Blast_SubjectIsTranslated(format_info->search_options->program)) {
787           ReadDBBioseqSetDbGeneticCode(format_info->search_options->
788                                        db_options->genetic_code);
789       }
790    }
791 
792    if(format_info->search_options->score_options->is_ooframe) {
793         ErrPostEx(SEV_WARNING, 0, 0, 
794          "Out-of-frame option selected, Expect values are only approximate and calculated not assuming out-of-frame alignments");
795    }
796 
797 
798    slp = query_slp;
799    mask_loc = mask_loc_head;
800   
801    for (query_index=0; query_index<seqalign_arr->num_queries && slp; query_index++, slp=slp->next)
802    {
803       Bioseq* bsp = NULL;
804       SeqAlignPtr seqalign = seqalign_arr->array[query_index];
805       /* Find which query the current SeqAlign is for */
806       SeqId* query_id = TxGetQueryIdFromSeqAlign(seqalign);
807       if (seqalign == NULL)
808       {
809             if (align_view < eAlignViewXml)
810                 s_AcknowledgeEmptyResults(slp, format_options, format_info, outfp);  /* this query has no results. */
811             else if (align_view == eAlignViewXml)
812             {
813                 /* Retrieve this query's Bioseq */
814                 Iteration* iterp;
815                 /* Call to TxGetQueryIdFromSeqAlign returned NULL. */
816                 query_id = SeqLocId(slp);
817                 bsp = BioseqLockById(query_id);
818                 iterp = s_XMLBuildOneQueryIteration(NULL, sum_returns, FALSE, ungapped, 
819                                          query_index+1+format_info->num_formatted,
820                                          "No hits found", bsp, NULL);
821                 IterationAsnWrite(iterp, xmlp->aip, xmlp->atp);
822                 AsnIoFlush(xmlp->aip);
823                 IterationFree(iterp);
824                 BioseqUnlock(bsp);
825             }
826             else if (align_view == eAlignViewTabularWithComments)
827             {
828                  query_id = SeqLocId(slp);
829                  bsp = BioseqLockById(query_id);
830                  PrintTabularOutputHeader(format_info->db_name, bsp, NULL, 
831                                      format_info->program_name,
832                                      0, format_options->believe_query, outfp);
833                  BioseqUnlock(bsp);
834             }
835             continue;
836       }
837       format_info->is_seqalign_null = FALSE; /* reset flag, at least one query has seqalign */
838 
839       /* Find the masking location for this query. Initialize next_mask_loc
840          to the current start of the chain, in case nothing for this query 
841          will be found. */
842       next_mask_loc = mask_loc;
843       for ( ; mask_loc; mask_loc = mask_loc->next) {
844          mask_slp = (SeqLoc*) mask_loc->data.ptrvalue;
845          if (SeqIdComp(query_id, SeqLocId(mask_slp)) == SIC_YES) {
846             break;
847          }
848       }
849       /* Unlink the masking location for this query and save the next one */
850       if (mask_loc) {
851          for (next_mask_loc = mask_loc; next_mask_loc->next; 
852               next_mask_loc = next_mask_loc->next) {
853             mask_slp = (SeqLoc*) next_mask_loc->next->data.ptrvalue;
854             if (SeqIdComp(query_id, SeqLocId(mask_slp))
855                 != SIC_YES) {
856                break;
857             }
858          }
859          tmp_loc = next_mask_loc;
860          next_mask_loc = next_mask_loc->next;
861          tmp_loc->next = NULL;
862       }
863 
864       /* On the next iteration we can start from the next query */
865 
866       /* Retrieve this query's Bioseq */
867       bsp = BioseqLockById(query_id);
868 
869       if (align_view < eAlignViewXml) {
870          if (format_info->head_on_every_query == TRUE)
871              BLAST_PrintOutputHeader(format_info);
872 
873          init_buff_ex(70);
874          AcknowledgeBlastQuery(bsp, 70, outfp, 
875             format_options->believe_query, format_options->html);
876          free_buff();
877 
878          if (format_info->head_on_every_query == TRUE)
879          {
880              s_BLAST_PrintDatabaseInfo(format_info);
881              fprintf(format_info->outfp, "%s", "Searching..................................................done\n\n");
882          }
883       }
884       if (align_view == eAlignViewTabular || 
885           align_view == eAlignViewTabularWithComments) {
886          if (align_view == eAlignViewTabularWithComments)
887             PrintTabularOutputHeader(format_info->db_name, bsp, NULL, 
888                                      format_info->program_name,
889                                      0, format_options->believe_query, outfp);
890          
891          BlastPrintTabulatedResults(seqalign, bsp, NULL, 
892             format_options->number_of_alignments, format_info->program_name, 
893             ungapped, format_options->believe_query, 0, 0, 
894             outfp, (Boolean)(align_view == eAlignViewTabularWithComments));
895       } else if(align_view == eAlignViewXml) {
896          Iteration* iterp;
897          
898          ASSERT(xmlp && xmlp->aip);
899          /* The index of this "query iteration" is the query_index in the 
900             current formatting round, plus the number of previously formatted
901             queries. */
902          iterp = 
903              s_XMLBuildOneQueryIteration(seqalign, sum_returns, FALSE, 
904                                          ungapped, 
905                                          query_index+1+format_info->num_formatted,
906                                          NULL, bsp, mask_loc);
907          IterationAsnWrite(iterp, xmlp->aip, xmlp->atp);
908          AsnIoFlush(xmlp->aip);
909          IterationFree(iterp);
910       } else {
911          SeqAnnot* seqannot = SeqAnnotNew();
912          seqannot->type = 2;
913          AddAlignInfoToSeqAnnot(seqannot, align_type);
914          seqannot->data = seqalign;
915          if (aip) {
916             SeqAnnotAsnWrite((SeqAnnot*) seqannot, aip, NULL);
917             AsnIoReset(aip);
918          } 
919          if (outfp) {
920             BlastPruneSapStruct* prune;
921             Int4** matrix = s_LoadMatrix(sum_returns->search_params->matrix);
922             ObjMgrSetHold();
923             init_buff_ex(85);
924             PrintDefLinesFromSeqAlignEx2(seqalign, 80, outfp, 
925                format_options->print_options, FIRST_PASS, NULL,
926                format_options->number_of_descriptions, NULL, NULL);
927             free_buff();
928             
929             /** @todo FIXME: note that by calling BlastPruneHitsFromSeqAlign
930              * we're making a COPY of the seqalign to print it out! Clearly
931              * this could use a better design */
932             prune = BlastPruneHitsFromSeqAlign(seqalign, 
933                        format_options->number_of_alignments, NULL);
934             seqannot->data = prune->sap;
935 
936             if(format_info->search_options->score_options->is_ooframe) {
937                OOFShowBlastAlignment(prune->sap, mask_loc, outfp, 
938                                      format_options->align_options, NULL);
939             } else if (align_view != eAlignViewPairwise) {
940                ShowTextAlignFromAnnot(seqannot, 60, outfp, NULL, NULL, 
941                   format_options->align_options, matrix, mask_loc, NULL);
942             } else {
943                ShowTextAlignFromAnnot(seqannot, 60, outfp, NULL, NULL, 
944                   format_options->align_options, matrix, mask_loc, 
945                   FormatScoreFunc);
946             }
947             s_DeleteMatrix(matrix);
948             seqannot->data = seqalign;
949             prune = BlastPruneSapStructDestruct(prune);
950             ObjMgrClearHold();
951          }
952          /* Set data to NULL, because we do not free Seq-align here. */
953          seqannot->data = NULL;
954          seqannot = SeqAnnotFree(seqannot);
955       }
956       BioseqUnlock(bsp);
957       /* Relink the mask locations so chain can be freed in the end.
958        The 'tmp_loc' variable points to the location that was unlinked. */
959       if (tmp_loc)
960           tmp_loc->next = next_mask_loc;
961       
962       mask_loc = next_mask_loc;
963       ObjMgrFreeCache(0);
964 
965    } /* End loop on seqaligns for different queries */
966 
967    /* close BlastOutput_iterations openned in s_MBXmlInit; Rt ticket # 15135151 */
968    if((format_info->is_seqalign_null==TRUE) && (align_view == eAlignViewXml)) {
969      /* extra output only if no hits at all, otherwise "for loop" logic should take care*/
970      Iteration* iterp;    
971      iterp = IterationNew();
972      iterp->iter_num = 1;
973      iterp->stat = s_XMLBuildStatistics(sum_returns, ungapped);
974 
975      ASSERT(xmlp && xmlp->aip);
976      IterationAsnWrite(iterp, xmlp->aip, xmlp->atp);
977      AsnIoFlush(xmlp->aip);
978      IterationFree(iterp);
979 
980    }
981 
982    if (format_info->db_name) {
983        /* Free the database translation tables, if applicable. */
984        TransTableFreeAll();
985        ReadDBBioseqFetchDisable();
986    }
987 
988    /* Update the count of the formatted queries. */
989    format_info->num_formatted += num_queries;
990 
991    return 0;
992 }
993 
994 /** Creates a list of SeqLoc structures with data about PHI BLAST pattern 
995  * occurrences, to be used as features on Query Seq-locs.
996  * @param pattern_info Pattern information structure. [in]
997  * @param query_seqloc Query SeqLoc, needed to retrieve Seq-id. [in]
998  * @param seed_seqloc_ptr List of SeqLoc's with pattern data. [out]
999  */
1000 static Int2
1001 s_PHIBlastCreateSeedSeqLoc(const SPHIQueryInfo* pattern_info, 
1002                            SeqLoc* query_seqloc, 
1003                            SeqLoc** seed_seqloc_ptr)
1004 {
1005     Int4 index;
1006     for (index = 0; index < pattern_info->num_patterns; ++index) {
1007         const SPHIPatternInfo* this_occurrence = 
1008             &pattern_info->occurrences[index];
1009         SeqInt* si = SeqIntNew();
1010         si->id = SeqIdDup(SeqLocId(query_seqloc));
1011         si->from = this_occurrence->offset;
1012         si->to = this_occurrence->offset + this_occurrence->length - 1;
1013         ValNodeAddPointer(seed_seqloc_ptr, SEQLOC_INT, si);
1014     }
1015     return 0;
1016 }
1017 
1018 /** Produces part of the text report describing the PHI BLAST pattern 
1019  * occurrences.
1020  * @param sum_returns Search summary return data [in]
1021  * @param outfp Output file stream [in]
1022  */ 
1023 static Int2
1024 s_PHIBlastFormatPatternInfo(Blast_SummaryReturn* sum_returns, FILE* outfp)
1025 {
1026     Int4 index;
1027     SPHIQueryInfo* pattern_info = sum_returns->pattern_info;
1028     double lenXprob = 
1029         sum_returns->db_stats->eff_dblength * pattern_info->probability;
1030     Int8 db_patterns;
1031 
1032     /* Get the pattern count in database from the diagnostics structure - it is
1033        equal to the number of "lookup" hits. */
1034     ASSERT(sum_returns->diagnostics && sum_returns->diagnostics->ungapped_stat);
1035     db_patterns = sum_returns->diagnostics->ungapped_stat->lookup_hits;
1036 
1037     fprintf(outfp, "\n%d occurrence(s) of pattern in query\n", 
1038             pattern_info->num_patterns);
1039     for (index = 0; index < pattern_info->num_patterns; ++index) {
1040         fprintf(outfp, "\n pattern %s\n at position %d of query sequence\n",
1041                 sum_returns->search_params->pattern, 
1042                 pattern_info->occurrences[index].offset + 1);
1043         fprintf(outfp, "effective database length=%.1e\n", 
1044                 (double)sum_returns->db_stats->eff_dblength);
1045         fprintf(outfp, " pattern probability=%.1e\nlengthXprobability=%.1e\n", 
1046                 pattern_info->probability, lenXprob);
1047         fprintf(outfp, 
1048                 "\nNumber of occurrences of pattern in the database is %s\n",
1049                 Nlm_Int8tostr(db_patterns, 0));
1050         fprintf(outfp, "WARNING: There may be more matching sequences with "
1051                 "e-values below the threshold of %f\n", 
1052                 sum_returns->search_params->expect);
1053 
1054     }
1055     return 0;
1056 }
1057 
1058 Int2 PHIBlastFormatResults(ValNode* phivnps, SeqLoc* query_slp,
1059                            const BlastFormattingInfo* format_info, 
1060                            Blast_SummaryReturn* sum_returns)
1061 {  
1062    Boolean db_is_na;
1063    Bioseq* query_bsp = NULL;
1064    FILE *outfp = NULL;
1065    ValNode* pruneSeed = NULL;
1066    Uint1 featureOrder[FEATDEF_ANY];
1067    Uint1 groupOrder[FEATDEF_ANY];
1068    SeqLoc* seed_seqloc = NULL; /* SeqLoc containing pattern locations. */ 
1069    EBlastProgramType program;
1070    BlastFormattingOptions* format_options;
1071 
1072    if (!format_info || !format_info->outfp || !query_slp)
1073       return -1;
1074 
1075    format_options = format_info->format_options;
1076    program = format_info->search_options->program;
1077 
1078    ASSERT(Blast_ProgramIsPhiBlast(program));
1079 
1080    outfp = format_info->outfp;
1081 
1082    s_PHIBlastFormatPatternInfo(sum_returns, outfp);
1083 
1084    /* Old toolkit might have different values for program numbers, so 
1085       use old toolkit function to determine alignment type. */
1086    if (program == eBlastTypePhiBlastn)
1087        db_is_na = TRUE;
1088    else
1089        db_is_na = FALSE;
1090 
1091    if (format_info->db_name)
1092       ReadDBBioseqFetchEnable ("blast", format_info->db_name, db_is_na, TRUE);
1093 
1094    pruneSeed = 
1095        SeedPruneHitsFromSeedReturn(phivnps,
1096                                    format_options->number_of_descriptions);
1097 
1098    s_PHIBlastCreateSeedSeqLoc(sum_returns->pattern_info, query_slp, 
1099                               &seed_seqloc);
1100 
1101    PrintDefLinesExtra(pruneSeed, 80, outfp, format_options->print_options,
1102                       FIRST_PASS, NULL, seed_seqloc);
1103 
1104    if (format_options->number_of_alignments < 
1105        format_options->number_of_descriptions) {
1106        pruneSeed = 
1107            SeedPruneHitsFromSeedReturn(phivnps,
1108                                        format_options->number_of_alignments);
1109    }
1110 
1111    query_bsp = BioseqLockById(SeqLocId(query_slp));
1112    memset(featureOrder, 0, sizeof(featureOrder));
1113    memset(groupOrder, 0, sizeof(groupOrder));
1114    featureOrder[FEATDEF_REGION] = 1;
1115    groupOrder[FEATDEF_REGION] = 1;
1116 
1117    if (format_options->align_view != eAlignViewPairwise) {
1118        ShowTextAlignFromAnnotExtra(query_bsp, pruneSeed, seed_seqloc, 60, outfp,
1119                                    featureOrder, groupOrder,
1120                                    format_options->align_options, NULL, NULL, 
1121                                    NULL);
1122    } else {
1123        ShowTextAlignFromAnnotExtra(query_bsp, pruneSeed, seed_seqloc, 60, outfp,
1124                                    featureOrder, groupOrder,
1125                                    format_options->align_options, NULL, NULL, 
1126                                    FormatScoreFunc);
1127    }
1128 
1129    SeqLocSetFree(seed_seqloc);
1130 
1131    if (format_info->db_name)
1132       ReadDBBioseqFetchDisable();
1133 
1134    return 0;
1135 }
1136 
1137 ValNode* PHIBlastResultsFree(ValNode* phivnps)
1138 {
1139     ValNode* vnp;
1140 
1141     for (vnp = phivnps; vnp; vnp = vnp->next)
1142         SeqAlignSetFree((SeqAlign*) vnp->data.ptrvalue);
1143     ValNodeFree(phivnps);
1144     return NULL;
1145 }
1146 
1147 Int2 Blast_PrintOutputFooter(const BlastFormattingInfo* format_info, 
1148                              const Blast_SummaryReturn* sum_returns) 
1149 {
1150    FILE *outfp;
1151    char* params_buffer=NULL;
1152    BlastFormattingOptions* format_options;
1153    EBlastProgramType program;
1154 
1155    if (!format_info || !format_info->outfp || !sum_returns)
1156       return -1;
1157 
1158    outfp = format_info->outfp;
1159 
1160    format_options = format_info->format_options;
1161    program = format_info->search_options->program;
1162 
1163    if (format_options->align_view >= eAlignViewXml)
1164       return 0;
1165 
1166    if(format_options->html) 
1167       fprintf(outfp, "<PRE>\n");
1168    init_buff_ex(85);
1169 
1170    if (format_info->db_name) {
1171        const Boolean kDbIsProt = 
1172            (program == eBlastTypeBlastp    ||
1173             program == eBlastTypeBlastx    ||
1174             program == eBlastTypePhiBlastp ||
1175             program == eBlastTypePsiBlast  ||
1176             program == eBlastTypeRpsBlast  ||
1177             program == eBlastTypeRpsTblastn);
1178        ReadDBFILE* rdfp = readdb_new(format_info->db_name, kDbIsProt);
1179        TxDfDbInfo* dbinfo_head,* dbinfo;
1180        dbinfo_head = Blast_GetDbInfo(rdfp);
1181        rdfp = readdb_destruct(rdfp);
1182 
1183        for (dbinfo = dbinfo_head; dbinfo; dbinfo = dbinfo->next) {
1184            PrintDbReport((TxDfDbInfo*) dbinfo, 70, outfp);
1185        }
1186        dbinfo_head = TxDfDbInfoDestruct(dbinfo_head);
1187    }
1188 
1189       
1190    if (sum_returns->ka_params)
1191    {
1192       BLAST_KAParameters* ka_params=sum_returns->ka_params;
1193       PrintKAParameters(ka_params->Lambda, ka_params->K, ka_params->H, 70, 
1194                            outfp, FALSE);
1195    }
1196 
1197  
1198    if (sum_returns->ka_params_gap && sum_returns->search_params->gapped_search)
1199    {
1200       BLAST_KAParameters* ka_params=sum_returns->ka_params_gap;
1201       if (Blast_ProgramIsPhiBlast(program)) {
1202           PrintKAParametersExtra(ka_params->Lambda, ka_params->K, ka_params->H, 
1203                                  ka_params->C, 70, outfp, TRUE);
1204       } else {
1205           PrintKAParameters(ka_params->Lambda, ka_params->K, ka_params->H, 70, 
1206                             outfp, TRUE);
1207       }
1208    }
1209    params_buffer = 
1210       Blast_GetParametersBuffer(program, sum_returns);
1211    PrintTildeSepLines(params_buffer, 70, outfp);
1212    sfree(params_buffer);
1213 
1214    if(format_options->html)
1215       fprintf(outfp, "</PRE>\n</BODY>\n</HTML>\n");
1216 
1217    free_buff();
1218 
1219    return 0;
1220 }
1221 
1222 Int2 
1223 BLAST_PrintOutputHeader(const BlastFormattingInfo* format_info)
1224 {
1225    Int2 status = 0;
1226    BlastFormattingOptions* format_options;
1227 
1228    if (!format_info)
1229        return -1;
1230    
1231    format_options = format_info->format_options;
1232 
1233    if (format_options->align_view < eAlignViewXml) {
1234       if (format_options->html) {
1235          fprintf(format_info->outfp, 
1236                  "<HTML>\n<TITLE>BLAST Search Results</TITLE>\n");
1237          fprintf(format_info->outfp, 
1238                  "<BODY BGCOLOR=\"#FFFFFF\" LINK=\"#0000FF\" "
1239                  "VLINK=\"#660099\" ALINK=\"#660099\">\n");
1240          fprintf(format_info->outfp, "<PRE>\n");
1241       }
1242       init_buff_ex(90);
1243       if (format_options->is_megablast) {
1244          BlastPrintVersionInfo("MEGABLAST", format_options->html, format_info->outfp);
1245          fprintf(format_info->outfp, "\n");
1246          MegaBlastPrintReference(format_options->html, 90, format_info->outfp);
1247       }
1248       else if (strcmp(format_info->program_name, "rpsblast") == 0 ||
1249                strcmp(format_info->program_name, "rpstblastn") == 0) {
1250          BlastPrintVersionInfo("RPS-BLAST", format_options->html, format_info->outfp);
1251       }
1252       else {
1253          BlastPrintVersionInfo(format_info->program_name, format_options->html, 
1254                                format_info->outfp);
1255          fprintf(format_info->outfp, "\n");
1256          BlastPrintReference(format_options->html, 90, format_info->outfp);
1257       }
1258       {{
1259           int comp_based_stats =
1260               format_info->search_options->ext_options->compositionBasedStats;
1261           if (comp_based_stats == eCompositionBasedStats) {
1262               CBStatisticsPrintReference(format_options->html, 90,
1263                                         TRUE, FALSE, format_info->outfp);
1264           } else if (comp_based_stats > eCompositionBasedStats) {
1265               CAdjustmentPrintReference(format_options->html, 90,
1266                                         format_info->outfp);
1267           }
1268       }}
1269       free_buff();
1270       fprintf(format_info->outfp, "\n");
1271 
1272       if (format_info->head_on_every_query == FALSE)
1273       {
1274           status = s_BLAST_PrintDatabaseInfo(format_info);
1275           fprintf(format_info->outfp, "%s", "Searching..................................................done\n\n");
1276       }
1277    }
1278 
1279    return status;
1280 }
1281 
1282 #ifdef BUFFER_LENGTH
1283 #undef BUFFER_LENGTH
1284 #endif
1285 
1286 /** Buffer length for printing sequence ids. */
1287 #define BUFFER_LENGTH 256
1288 
1289 void 
1290 Blast_SeqIdGetDefLine(SeqId* sip, char** buffer_ptr, Boolean ncbi_gi, 
1291                       Boolean accession_only, Boolean search_for_id)
1292 {
1293    char* seqid_buffer = NULL;
1294    Int4 gi = 0;
1295    Boolean numeric_id_type = FALSE;
1296 
1297    *buffer_ptr = NULL;
1298 
1299    if (sip == NULL)
1300         return;
1301 
1302    /* Check for ad hoc ID's generated by formatdb if the user does not provide 
1303       any. */
1304    if (search_for_id && (sip->choice != SEQID_GENERAL ||
1305        StringCmp(((Dbtag*)sip->data.ptrvalue)->db, "BL_ORD_ID")))  
1306    {
1307       if ((!accession_only && !ncbi_gi) || sip->choice == SEQID_LOCAL) {
1308          seqid_buffer = (char*) malloc(BUFFER_LENGTH + 1);
1309          SeqIdWrite(sip, seqid_buffer, PRINTID_FASTA_LONG, BUFFER_LENGTH);
1310       } else if (accession_only) {
1311          seqid_buffer = (char*) malloc(BUFFER_LENGTH + 1);
1312          SeqIdWrite(SeqIdFindBestAccession(sip), seqid_buffer, 
1313                     PRINTID_TEXTID_ACC_VER, BUFFER_LENGTH);
1314       } else if (ncbi_gi) {
1315          numeric_id_type = 
1316             GetAccessionFromSeqId(SeqIdFindBest(sip, SEQID_GI), 
1317                                   &gi, &seqid_buffer);
1318       } else {
1319          numeric_id_type = 
1320             GetAccessionFromSeqId(SeqIdFindBestAccession(sip), 
1321                                   &gi, &seqid_buffer);
1322       }
1323    }
1324 
1325    if (numeric_id_type && gi > 0) {
1326       seqid_buffer = (char*) malloc(16);
1327       sprintf(seqid_buffer, "%ld", (long) gi);
1328    }   
1329    if (!seqid_buffer) {
1330       /* If it's still NULL make a last ditch effort to get info. */
1331       char* title=NULL;
1332       Bioseq* bsp = BioseqLockById(sip);
1333       if (bsp) {
1334          if (BioseqGetTitle(bsp) != NULL)
1335             title = strdup(BioseqGetTitle(bsp));
1336          else
1337             title = strdup("No definition line found");
1338       }
1339       BioseqUnlock(bsp);
1340       
1341       if (title) /* Use first token as id. */
1342          seqid_buffer = StringTokMT(title, " \t\n\r", &title);  
1343    }
1344    *buffer_ptr = seqid_buffer;
1345 
1346 }
1347 
1348 Int2 
1349 Blast_SummaryReturnsPostError(Blast_SummaryReturn* sum_return)
1350 {
1351     SBlastMessage* error = NULL;
1352 
1353     if (!sum_return)
1354         return -1;
1355 
1356     /* If there was no error, there is nothing to post. */
1357     if (!sum_return->error)
1358         return 0;
1359 
1360     error = sum_return->error;
1361 
1362     ErrPostEx(error->sev, 0, 0, error->message);
1363 
1364     return 0;
1365 }
1366 /* @} */
1367 
1368 

source navigation ]   [ diff markup ]   [ identifier search ]   [ freetext search ]   [ file search ]  

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.