1 /* $Id: blast_returns.c,v 1.39 2010/06/10 13:44:46 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 *  Author: Ilya Dondoshansky
25 * ===========================================================================*/
26 
27 /** @file blast_returns.c
28  * Manipulating data returned from BLAST other than Seq-aligns
29  */
30 
31 #ifndef SKIP_DOXYGEN_PROCESSING
32 static char const rcsid[] = "$Id: blast_returns.c,v 1.39 2010/06/10 13:44:46 madden Exp $";
33 #endif /* SKIP_DOXYGEN_PROCESSING */
34 
35 #include <algo/blast/api/blast_returns.h>
36 #include <algo/blast/api/blast_seq.h>
37 #include <algo/blast/core/blast_filter.h>
38 #include <algo/blast/core/blast_util.h>
39 #include <algo/blast/core/pattern.h>
40 
41 /** @addtogroup CToolkitAlgoBlast
42  *
43  * @{
44  */
45 
Blast_GetDbInfo(ReadDBFILE * rdfp)46 TxDfDbInfo* Blast_GetDbInfo(ReadDBFILE* rdfp)
47 {
48    TxDfDbInfo* dbinfo = NULL;
49    char* chptr = NULL;
50 
51    if (!rdfp)
52       return NULL;
53 
54    dbinfo = calloc(1, sizeof(TxDfDbInfo));
55 
56    dbinfo->name = strdup(readdb_get_filename(rdfp));
57 
58    if (((chptr = readdb_get_title(rdfp)) == NULL) && dbinfo->name)
59       dbinfo->definition = strdup(dbinfo->name);
60    else
61       dbinfo->definition = strdup(chptr);
62 
63    dbinfo->date = strdup(readdb_get_date(rdfp));
64 
65    dbinfo->is_protein = readdb_is_prot(rdfp);
66 
67    readdb_get_totals_ex(rdfp, &dbinfo->total_length, &dbinfo->number_seqs, TRUE);
68 
69    return dbinfo;
70 }
71 
72 char*
Blast_GetParametersBuffer(EBlastProgramType program_number,const Blast_SummaryReturn * sum_returns)73 Blast_GetParametersBuffer(EBlastProgramType program_number,
74         const Blast_SummaryReturn* sum_returns)
75 {
76    char buffer[128];
77    char* ret_buffer=NULL;
78    Int2 ret_buffer_length=0;
79    BlastUngappedStats* ungapped_stats = NULL;
80    BlastGappedStats* gapped_stats = NULL;
81    BlastRawCutoffs* raw_cutoffs = NULL;
82    Blast_SearchParams* search_params=NULL;
83    Blast_DatabaseStats* db_stats = NULL;
84    BlastDiagnostics* diagnostics = NULL;
85 
86 
87    if (!sum_returns || !sum_returns->search_params || !sum_returns->db_stats)
88      return NULL;
89 
90    search_params = sum_returns->search_params;
91    db_stats = sum_returns->db_stats;
92    diagnostics = sum_returns->diagnostics;
93 
94    if (diagnostics) {
95       ungapped_stats = diagnostics->ungapped_stat;
96       gapped_stats = diagnostics->gapped_stat;
97       raw_cutoffs = diagnostics->cutoffs;
98    }
99 
100    if (program_number == eBlastTypeBlastn ||
101        program_number == eBlastTypePhiBlastn)
102    {
103       sprintf(buffer, "Matrix: blastn matrix:%d %d", search_params->match, search_params->mismatch);
104       add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
105    }
106    else if (search_params->matrix)
107    {
108       sprintf(buffer, "Matrix: %s", search_params->matrix);
109       add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
110    }
111 
112    if (search_params->gapped_search) {
113       if (search_params->gap_extension == 0 && program_number == eBlastTypeBlastn)
114       { /* Formula from PMID 10890397 applies if both gap values are zero. */
115            double gap_extension = (double) search_params->gap_extension;
116            gap_extension = -2*search_params->mismatch + search_params->match;
117            gap_extension /= 2.0;
118            sprintf(buffer, "Gap Penalties: Existence: %ld, Extension: %4.1f",
119               (long) search_params->gap_open, gap_extension);
120       }
121       else
122       {
123            sprintf(buffer, "Gap Penalties: Existence: %ld, Extension: %ld",
124               (long) search_params->gap_open, (long) search_params->gap_extension);
125       }
126       add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
127    }
128 
129    sprintf(buffer, "Number of Sequences: %ld", (long) db_stats->dbnum);
130    add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
131 
132    if (ungapped_stats) {
133       sprintf(buffer, "Number of Hits to DB: %s",
134               Nlm_Int8tostr(ungapped_stats->lookup_hits, 1));
135       add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
136 
137       if (ungapped_stats->init_extends) {
138           sprintf(buffer, "Number of extensions: %ld",
139                   (long) ungapped_stats->init_extends);
140           add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
141       }
142       if (ungapped_stats->good_init_extends) {
143           sprintf(buffer, "Number of successful extensions: %ld",
144                   (long) ungapped_stats->good_init_extends);
145           add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
146       }
147    }
148 
149    if (gapped_stats) {
150       if (search_params->expect > 0.1) {
151          sprintf(buffer, "Number of sequences better than %4.1f: %ld",
152                  search_params->expect,
153                  (long) gapped_stats->num_seqs_passed);
154       } else {
155          sprintf(buffer, "Number of sequences better than %3.1e: %ld",
156                  search_params->expect,
157                  (long) gapped_stats->num_seqs_passed);
158       }
159       add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
160 
161       if (search_params->gapped_search) {
162           if (gapped_stats->seqs_ungapped_passed) {
163               sprintf(buffer,
164                       "Number of HSP's better than %4.1f without gapping: %ld",
165                       search_params->expect,
166                       (long) gapped_stats->seqs_ungapped_passed);
167               add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
168           }
169           sprintf(buffer, "Number of HSP's gapped: %ld",
170                   (long) gapped_stats->extensions);
171           add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
172           sprintf(buffer, "Number of HSP's successfully gapped: %ld",
173                   (long) gapped_stats->good_extensions);
174           add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
175       }
176    }
177 
178    /* Query length makes sense only for single query sequence. */
179    if (db_stats->qlen > 0) {
180        sprintf(buffer, "Length of query: %ld", (long)db_stats->qlen);
181        add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
182    }
183 
184    sprintf(buffer, "Length of database: %s",
185            Nlm_Int8tostr (db_stats->dblength, 1));
186    add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
187 
188    if (db_stats->qlen > 0) {
189        sprintf(buffer, "Length adjustment: %ld", (long) db_stats->hsp_length);
190        add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
191 
192        sprintf(buffer, "Effective length of query: %ld",
193                (long) db_stats->eff_qlen);
194        add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
195 
196        sprintf(buffer, "Effective length of database: %s",
197                Nlm_Int8tostr (db_stats->eff_dblength , 1));
198        add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
199        sprintf(buffer, "Effective search space: %8.0f",
200                (double) db_stats->eff_searchsp);
201        add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
202        sprintf(buffer, "Effective search space used: %8.0f",
203                (double) db_stats->eff_searchsp_used);
204        add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
205    }
206    if (search_params->threshold) {
207        if (search_params->threshold == floor(search_params->threshold))
208            sprintf(buffer, "Neighboring words threshold: %ld",
209                    (long)search_params->threshold);
210        else
211            sprintf(buffer, "Neighboring words threshold: %.2f",
212                    search_params->threshold);
213        add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
214    }
215    if (search_params->window_size) {
216        sprintf(buffer, "Window for multiple hits: %ld",
217                (long) search_params->window_size);
218        add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
219    }
220    if (raw_cutoffs) {
221       BLAST_KAParameters* ka_params_gap = sum_returns->ka_params_gap;
222       BLAST_KAParameters* ka_params = sum_returns->ka_params;
223 
224       if (raw_cutoffs->x_drop_ungapped) {
225           sprintf(buffer, "X1: %ld (%4.1f bits)",
226                   (long)raw_cutoffs->x_drop_ungapped,
227                   (raw_cutoffs->x_drop_ungapped)*(ka_params->Lambda)/NCBIMATH_LN2);
228           add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
229       }
230       if (search_params->gapped_search) {
231          sprintf(buffer, "X2: %ld (%4.1f bits)",
232                  (long)raw_cutoffs->x_drop_gap, raw_cutoffs->x_drop_gap*(ka_params_gap->Lambda)/NCBIMATH_LN2);
233          add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
234          sprintf(buffer, "X3: %ld (%4.1f bits)",
235                  (long)raw_cutoffs->x_drop_gap_final,
236                  raw_cutoffs->x_drop_gap_final*(ka_params_gap->Lambda) /
237                  NCBIMATH_LN2);
238          add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
239 
240          if (raw_cutoffs->ungapped_cutoff) {
241              sprintf(buffer, "S1: %ld (%4.1f bits)",
242                      (long)raw_cutoffs->ungapped_cutoff,
243                      ((raw_cutoffs->ungapped_cutoff*(ka_params->Lambda)) -
244                       (log(ka_params->K)))/NCBIMATH_LN2);
245              add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
246          }
247       }
248       if (raw_cutoffs->cutoff_score) {
249           if (search_params->gapped_search) {
250               sprintf(buffer, "S2: %ld (%4.1f bits)",
251                       (long) raw_cutoffs->cutoff_score,
252                       (((raw_cutoffs->cutoff_score)*(ka_params_gap->Lambda)) -
253                        (log(ka_params_gap->K)))/NCBIMATH_LN2);
254           } else {
255               sprintf(buffer, "S2: %ld (%4.1f bits)",
256                       (long) raw_cutoffs->cutoff_score,
257                       (((raw_cutoffs->cutoff_score)*(ka_params->Lambda)) -
258                        (log(ka_params->K)))/NCBIMATH_LN2);
259           }
260           add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
261       }
262    }
263 
264    return ret_buffer;
265 }
266 
267 /** Save the Karlin-Altschul parameters calculated in the BLAST search.
268  * @param sbp Internal scoring block structure [in]
269  * @param query_info info about query for use in fetching
270  *                Karlin-Altschul parameters [in]
271  * @param sum_returns Returns summary structure [out]
272 */
273 static void
s_SummaryKAParametersFill(const BlastScoreBlk * sbp,const BlastQueryInfo * query_info,Blast_SummaryReturn * sum_returns)274 s_SummaryKAParametersFill(const BlastScoreBlk* sbp, const BlastQueryInfo* query_info,
275                           Blast_SummaryReturn* sum_returns)
276 {
277    Blast_KarlinBlk* kbp;
278    int index;
279    int context = -1;
280 
281    if (!sbp || !query_info)
282       return;
283 
284     for (index=query_info->first_context; index<=query_info->last_context; index++)
285        if (query_info->contexts[index].is_valid == TRUE)
286        {
287           context = index;
288           break;
289        }
290 
291    if (sbp->kbp) {
292         sum_returns->ka_params =
293              (BLAST_KAParameters*) calloc(1, sizeof(BLAST_KAParameters));
294         if (context >= 0)
295         {
296           kbp = sbp->kbp[context];
297           sum_returns->ka_params->Lambda = kbp->Lambda;
298           sum_returns->ka_params->K = kbp->K;
299           sum_returns->ka_params->H = kbp->H;
300         }
301         else
302         {
303           sum_returns->ka_params->Lambda = -1.0;
304           sum_returns->ka_params->K = -1.0;
305           sum_returns->ka_params->H = -1.0;
306         }
307    }
308 
309    if (sbp->kbp_gap) {
310         sum_returns->ka_params_gap =
311              (BLAST_KAParameters*) calloc(1, sizeof(BLAST_KAParameters));
312         if (context >= 0)
313         {
314           kbp = sbp->kbp_gap[context];
315           sum_returns->ka_params_gap->Lambda = kbp->Lambda;
316           sum_returns->ka_params_gap->K = kbp->K;
317           sum_returns->ka_params_gap->H = kbp->H;
318           sum_returns->ka_params_gap->C = kbp->paramC; /* Needed only in PHI BLAST */
319         }
320         else
321         {
322           sum_returns->ka_params_gap->Lambda = -1.0;
323           sum_returns->ka_params_gap->K = -1.0;
324           sum_returns->ka_params_gap->H = -1.0;
325           sum_returns->ka_params_gap->C = -1.0;
326         }
327    }
328 }
329 
330 /** Frees Blast_DatabaseStats object
331  * @param db_stats object to be freed [in]
332  * @return NULL pointer
333  */
334 static Blast_DatabaseStats*
s_SummaryDBStatsFree(Blast_DatabaseStats * db_stats)335 s_SummaryDBStatsFree(Blast_DatabaseStats* db_stats)
336 {
337     sfree(db_stats);
338     return NULL;
339 }
340 
341 /** Allocates and fills in Blast_DatabaseStats
342  * @param program_number blastn/blastp/etc. [in]
343  * @param eff_len_options pointer to effective length options [in]
344  * @param query_info information about query [in]
345  * @param seq_src Source of subject sequences [in]
346  * @param db_stats object to be returned [out]
347  * @return zero on success
348  */
349 static Int2
s_SummaryDBStatsFill(EBlastProgramType program_number,const BlastEffectiveLengthsOptions * eff_len_options,const BlastQueryInfo * query_info,const BlastSeqSrc * seq_src,Blast_DatabaseStats ** db_stats)350 s_SummaryDBStatsFill(EBlastProgramType program_number,
351    const BlastEffectiveLengthsOptions* eff_len_options,
352    const BlastQueryInfo* query_info, const BlastSeqSrc* seq_src,
353    Blast_DatabaseStats** db_stats)
354 {
355    Int8 total_length=0;  /* total length of database. */
356    Int4 num_entries=0;   /* number of entries in database. */
357    Int4 num_frames;      /* number of frames allowed. */
358 
359 
360    ASSERT(db_stats);
361 
362    *db_stats = (Blast_DatabaseStats*) calloc(1, sizeof(Blast_DatabaseStats));
363    if (*db_stats == NULL)
364      return -1;
365 
366    if (eff_len_options->db_length) {
367       total_length = eff_len_options->db_length;
368    } else {
369       total_length = BlastSeqSrcGetTotLen(seq_src);
370 
371       if (total_length == 0) {
372          /* If total length cannot be retrieved directly, calculate it by
373             adding individual sequence lengths. */
374          BlastSeqSrcIterator* itr = BlastSeqSrcIteratorNew();
375          Int4 oid;
376          while ( (oid = BlastSeqSrcIteratorNext(seq_src, itr))
377                  != BLAST_SEQSRC_EOF) {
378             total_length += BlastSeqSrcGetSeqLen(seq_src, (void*) &oid);
379          }
380          itr = BlastSeqSrcIteratorFree(itr);
381       }
382    }
383 
384    if (Blast_SubjectIsTranslated(program_number) ||
385        program_number == eBlastTypeRpsTblastn)
386       total_length /= 3;
387 
388    (*db_stats)->dblength = total_length;
389 
390 
391    if (eff_len_options->dbseq_num)
392       num_entries = eff_len_options->dbseq_num;
393    else
394       num_entries = BlastSeqSrcGetNumSeqs(seq_src);
395 
396    (*db_stats)->dbnum = num_entries;
397 
398    if (program_number == eBlastTypeBlastx ||
399        program_number == eBlastTypeRpsTblastn ||
400        program_number == eBlastTypeTblastx)
401       num_frames = NUM_FRAMES;
402    else if (program_number == eBlastTypeBlastn ||
403             program_number == eBlastTypePhiBlastn)
404       num_frames = 2;
405    else
406       num_frames = 1;
407 
408 
409    if (query_info->last_context < num_frames) {  /* Only one query here. */
410       Int4 qlen = query_info->contexts[query_info->first_context].query_length;
411       (*db_stats)->hsp_length =
412           query_info->contexts[query_info->first_context].length_adjustment;
413       /** FIXME: Should this be different for RPS BLAST? */
414       (*db_stats)->qlen = qlen;
415       (*db_stats)->eff_qlen = qlen - ((*db_stats)->hsp_length);
416       (*db_stats)->eff_dblength = total_length;
417       if (eff_len_options->db_length == 0) {
418          (*db_stats)->eff_dblength -= (Int8)num_entries *
419                                         ((*db_stats)->hsp_length);
420       }
421       (*db_stats)->eff_searchsp =
422           query_info->contexts[query_info->first_context].eff_searchsp;
423       if (eff_len_options &&
424           eff_len_options->num_searchspaces &&
425           eff_len_options->searchsp_eff[0])
426          (*db_stats)->eff_searchsp_used = eff_len_options->searchsp_eff[0];
427       else
428          (*db_stats)->eff_searchsp_used = (*db_stats)->eff_searchsp;
429    }
430 
431    return 0;
432 }
433 
434 /** Free Blast_SearchParams structure and underlying data
435  *
436  * @param search_params the object to be freed [in]
437  * @return NULL pointer
438  */
439 static Blast_SearchParams*
s_SummarySearchParamsFree(Blast_SearchParams * search_params)440 s_SummarySearchParamsFree(Blast_SearchParams* search_params)
441 {
442 
443    if (search_params == NULL)
444       return NULL;
445 
446    sfree(search_params->matrix);
447    sfree(search_params->entrez_query);
448    sfree(search_params->filter_string);
449    sfree(search_params->pattern);
450    sfree(search_params);
451 
452    return NULL;
453 }
454 
455 /** Allocated and fills some search parameters.
456  *
457  * @param program_number identifies blastn/blastp/etc. [in]
458  * @param score_options pointer to scoring options [in]
459  * @param lookup_options pointer to options for lookup table creation [in]
460  * @param hit_options options for saving and evaluating hits [in]
461  * @param query_setup options for filtering etc. [in]
462  * @param word_options options for processing initial hits [in]
463  * @param entrez_query limit search by this query [in]
464  * @param search_params object to be allocated and filled [out]
465  * @return zero on success
466  */
467 Int2
Blast_SearchParamsFill(EBlastProgramType program_number,const BlastScoringOptions * score_options,const LookupTableOptions * lookup_options,const BlastHitSavingOptions * hit_options,const QuerySetUpOptions * query_setup,const BlastInitialWordOptions * word_options,const char * entrez_query,Blast_SearchParams ** search_params)468 Blast_SearchParamsFill(EBlastProgramType program_number,
469    const BlastScoringOptions* score_options,
470    const LookupTableOptions* lookup_options,
471    const BlastHitSavingOptions* hit_options,
472    const QuerySetUpOptions* query_setup,
473    const BlastInitialWordOptions* word_options,
474    const char* entrez_query,
475    Blast_SearchParams** search_params)
476 {
477    Blast_SearchParams* search_params_lcl;
478 
479    ASSERT(search_params);
480    ASSERT(score_options && lookup_options && hit_options && query_setup);
481 
482    *search_params = search_params_lcl = (Blast_SearchParams*) calloc(1, sizeof(Blast_SearchParams));
483    if (search_params_lcl == NULL)
484      return -1;
485 
486    if (program_number == eBlastTypeBlastn ||
487        program_number == eBlastTypePhiBlastn)
488    {
489       search_params_lcl->match = score_options->reward;
490       search_params_lcl->mismatch = score_options->penalty;
491    }
492    else if (score_options->matrix)
493    {
494       search_params_lcl->matrix = StringSave(score_options->matrix);
495    }
496 
497    if (score_options->gapped_calculation)
498    {
499       search_params_lcl->gapped_search = TRUE;
500       search_params_lcl->gap_open = score_options->gap_open;
501       search_params_lcl->gap_extension = score_options->gap_extend;
502    }
503    else
504       search_params_lcl->gapped_search = FALSE;
505 
506    if (query_setup && query_setup->filter_string)
507       search_params_lcl->filter_string = StringSave(query_setup->filter_string);
508    else
509       search_params_lcl->filter_string = StringSave("F");
510 
511    search_params_lcl->expect = hit_options->expect_value;
512 
513    if (lookup_options->phi_pattern)
514       search_params_lcl->pattern = StringSave(lookup_options->phi_pattern);
515 
516    search_params_lcl->threshold = lookup_options->threshold;
517 
518    search_params_lcl->window_size = word_options->window_size;
519 
520    if (entrez_query)
521       search_params_lcl->entrez_query = StringSave(entrez_query);
522 
523    return 0;
524 }
525 
Blast_SummaryReturnNew()526 Blast_SummaryReturn* Blast_SummaryReturnNew()
527 {
528     return (Blast_SummaryReturn*) calloc(1, sizeof(Blast_SummaryReturn));
529 }
530 
531 void
Blast_SummaryReturnClean(Blast_SummaryReturn * sum_returns)532 Blast_SummaryReturnClean(Blast_SummaryReturn* sum_returns)
533 {
534    if (sum_returns) {
535       sfree(sum_returns->ka_params);
536       sfree(sum_returns->ka_params_gap);
537       sum_returns->db_stats = s_SummaryDBStatsFree(sum_returns->db_stats);
538       sum_returns->search_params =
539           s_SummarySearchParamsFree(sum_returns->search_params);
540       sum_returns->diagnostics = Blast_DiagnosticsFree(sum_returns->diagnostics);
541       sum_returns->error = SBlastMessageFree(sum_returns->error);
542       sum_returns->pattern_info =
543           SPHIQueryInfoFree(sum_returns->pattern_info);
544    }
545 }
546 
547 Blast_SummaryReturn*
Blast_SummaryReturnFree(Blast_SummaryReturn * sum_returns)548 Blast_SummaryReturnFree(Blast_SummaryReturn* sum_returns)
549 {
550     Blast_SummaryReturnClean(sum_returns);
551     sfree(sum_returns);
552     return NULL;
553 }
554 
Blast_SummaryReturnFill(EBlastProgramType program_number,const BlastScoringOptions * score_options,const BlastScoreBlk * sbp,const LookupTableOptions * lookup_options,const BlastInitialWordOptions * word_options,const BlastExtensionOptions * ext_options,const BlastHitSavingOptions * hit_options,const BlastEffectiveLengthsOptions * eff_len_options,const QuerySetUpOptions * query_setup,const BlastQueryInfo * query_info,const BlastSeqSrc * seq_src,BlastDiagnostics ** diagnostics,Blast_SummaryReturn * sum_returns)555 Int2 Blast_SummaryReturnFill(EBlastProgramType program_number,
556         const BlastScoringOptions* score_options,
557         const BlastScoreBlk* sbp,
558         const LookupTableOptions* lookup_options,
559         const BlastInitialWordOptions* word_options,
560         const BlastExtensionOptions* ext_options,
561         const BlastHitSavingOptions* hit_options,
562         const BlastEffectiveLengthsOptions* eff_len_options,
563         const QuerySetUpOptions* query_setup,
564         const BlastQueryInfo* query_info,
565         const BlastSeqSrc* seq_src,
566         BlastDiagnostics** diagnostics,
567         Blast_SummaryReturn* sum_returns)
568 {
569     if (!sum_returns)
570         return -1;
571 
572    if (score_options == NULL || sbp == NULL || lookup_options == NULL ||
573       word_options == NULL || ext_options == NULL || hit_options == NULL ||
574       eff_len_options == NULL || query_info == NULL)
575      return -1;
576 
577    s_SummaryKAParametersFill(sbp, query_info, sum_returns);
578    s_SummaryDBStatsFill(program_number, eff_len_options, query_info,
579                             seq_src, &(sum_returns->db_stats));
580 
581    Blast_SearchParamsFill(program_number, score_options,
582             lookup_options, hit_options, query_setup, word_options,
583             NULL, &(sum_returns->search_params));
584    if (diagnostics)
585    {
586       sum_returns->diagnostics = *diagnostics;
587       *diagnostics = NULL;
588    }
589 
590    if (Blast_ProgramIsPhiBlast(program_number)) {
591        /* Copy the pattern information structure. */
592        sum_returns->pattern_info =
593            SPHIQueryInfoCopy(query_info->pattern_info);
594    }
595 
596    return 0;
597 }
598 
599 /** Duplicates the Blast_SearchParams structure.
600  * @param params Search parameters structure [in]
601  * @return New copy of the search parameters structure.
602  */
603 static Blast_SearchParams*
s_SearchParamsDup(const Blast_SearchParams * params)604 s_SearchParamsDup(const Blast_SearchParams* params)
605 {
606     Blast_SearchParams* new_params;
607 
608     if (!params)
609         return NULL;
610 
611     new_params = (Blast_SearchParams*)
612         BlastMemDup(params, sizeof(Blast_SearchParams));
613     if (params->filter_string)
614         new_params->filter_string = strdup(params->filter_string);
615     if (params->matrix)
616         new_params->matrix = strdup(params->matrix);
617     if (params->pattern)
618         new_params->pattern = strdup(params->pattern);
619     if (params->entrez_query)
620         new_params->entrez_query = strdup(params->entrez_query);
621 
622     return new_params;
623 }
624 
Blast_SummaryReturnUpdate(const Blast_SummaryReturn * new_return,Blast_SummaryReturn ** full_return_out)625 int Blast_SummaryReturnUpdate(const Blast_SummaryReturn* new_return,
626                               Blast_SummaryReturn* *full_return_out)
627 {
628     Blast_SummaryReturn* full_return;
629 
630     if (!new_return)
631         return 0;
632     if (!full_return_out)
633         return -1;
634 
635     /* If aggregate returns have not been allocated yet, do it here. Otherwise,
636      * remove all previously saved data, except for the diagnostics structure.
637      * Note that diagnostics structure must be allocated before the call to
638      * Blast_DiagnosticsUpdate.
639      */
640     if (*full_return_out == NULL) {
641         *full_return_out = full_return = Blast_SummaryReturnNew();
642         full_return->diagnostics = Blast_DiagnosticsInit();
643     } else {
644         BlastDiagnostics* diagnostics;
645         full_return = *full_return_out;
646         /* Save the diagnostics structure before cleaning the previous data. */
647         diagnostics = full_return->diagnostics;
648         full_return->diagnostics = NULL;
649         Blast_SummaryReturnClean(full_return);
650         full_return->diagnostics = diagnostics;
651     }
652 
653     full_return->ka_params = (BLAST_KAParameters*)
654         BlastMemDup(new_return->ka_params, sizeof(BLAST_KAParameters));
655     full_return->ka_params_gap = (BLAST_KAParameters*)
656         BlastMemDup(new_return->ka_params_gap, sizeof(BLAST_KAParameters));
657     full_return->db_stats = (Blast_DatabaseStats*)
658         BlastMemDup(new_return->db_stats, sizeof(Blast_DatabaseStats));
659     full_return->search_params =
660         s_SearchParamsDup(new_return->search_params);
661 
662     Blast_DiagnosticsUpdate(full_return->diagnostics, new_return->diagnostics);
663 
664     if (new_return->error)
665         full_return->error = SBlastMessageDup(new_return->error);
666 
667     full_return->pattern_info = SPHIQueryInfoCopy(new_return->pattern_info);
668 
669     return 0;
670 }
671 
672 /* @} */
673 
674