1 /*  $Id: deltablast_app.cpp 611306 2020-07-02 13:16:00Z fongah2 $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors:  Greg Boratyn
27  *
28  */
29 
30 /** @file deltablast_app.cpp
31  * DELTA-BLAST command line application
32  */
33 
34 #include <ncbi_pch.hpp>
35 #include <corelib/ncbistl.hpp>
36 #include <corelib/ncbiapp.hpp>
37 #include <algo/blast/api/deltablast.hpp>
38 #include <algo/blast/api/psiblast.hpp> // needed for psiblast iterations
39 #include <algo/blast/api/remote_blast.hpp>
40 #include <algo/blast/api/blast_results.hpp>
41 #include <algo/blast/blastinput/blast_fasta_input.hpp>
42 #include <algo/blast/blastinput/deltablast_args.hpp>
43 #include <algo/blast/api/objmgr_query_data.hpp>
44 #include <algo/blast/api/query_data.hpp>
45 #include <algo/blast/format/blast_format.hpp>
46 #include <objects/scoremat/Pssm.hpp> // needed for printing Pssm
47 #include <objects/scoremat/PssmIntermediateData.hpp> // needed for clearing
48                                        // information content in ascii Pssm
49 #include <objects/seq/Seq_descr.hpp> // needed for adding qurey title to Pssm
50 #include "blast_app_util.hpp"
51 
52 #ifndef SKIP_DOXYGEN_PROCESSING
53 USING_NCBI_SCOPE;
54 USING_SCOPE(objects);
55 USING_SCOPE(blast);
56 #endif
57 
58 class CDeltaBlastApp : public CNcbiApplication
59 {
60 public:
61     /** @inheritDoc */
CDeltaBlastApp()62     CDeltaBlastApp() {
63         CRef<CVersion> version(new CVersion());
64         version->SetVersionInfo(new CBlastVersion());
65         SetFullVersion(version);
66         m_StopWatch.Start();
67         if (m_UsageReport.IsEnabled()) {
68         	m_UsageReport.AddParam(CBlastUsageReport::eVersion, GetVersion().Print());
69         }
70     }
~CDeltaBlastApp()71     ~CDeltaBlastApp() {
72     	m_UsageReport.AddParam(CBlastUsageReport::eRunTime, m_StopWatch.Elapsed());
73     }
74 private:
75     /** @inheritDoc */
76     virtual void Init();
77     /** @inheritDoc */
78     virtual int Run();
79 
80 
81     /// Save Pssm to file
82     void SavePssmToFile(CConstRef<CPssmWithParameters> pssm);
83 
84     /// Do PSI-BLAST iterations follwing DELTA-BLAST
85     bool DoPsiBlastIterations(CRef<CBlastOptionsHandle> opts_hndl,
86                               CRef<CBlastQueryVector> query,
87                               CConstRef<CBioseq> query_bioseq,
88                               CRef<blast::CSearchResultSet> results,
89                               CRef<CBlastDatabaseArgs> db_args,
90                               const CArgs& args,
91                               CRef<CLocalDbAdapter> db_adapter,
92                               CRef<CScope> scope,
93                               CBlastFormat& formatter);
94 
95     /// Compute PSSM for next PSI-BLAST iteration
96     CRef<CPssmWithParameters> ComputePssmForNextPsiBlastIteration(
97                                  const CBioseq& bioseq,
98                                  CConstRef<CSeq_align_set> sset,
99                                  CConstRef<CPSIBlastOptionsHandle> opts_handle,
100                                  CRef<CScope> scope,
101                                  CRef<CBlastAncillaryData> ancillary_data);
102 
103 
104     /// This application's command line args
105     CRef<CDeltaBlastAppArgs> m_CmdLineArgs;
106 
107     CRef<CBlastAncillaryData> m_AncillaryData;
108 
109     CBlastAppDiagHandler m_bah;
110     CBlastUsageReport m_UsageReport;
111     CStopWatch m_StopWatch;
112 };
113 
Init()114 void CDeltaBlastApp::Init()
115 {
116     // formulate command line arguments
117 
118     m_CmdLineArgs.Reset(new CDeltaBlastAppArgs());
119 
120     // read the command line
121 
122     HideStdArgs(fHideLogfile | fHideConffile | fHideFullVersion | fHideXmlHelp
123                 | fHideDryRun);
124     SetupArgDescriptions(m_CmdLineArgs->SetCommandLine());
125 }
126 
127 void
SavePssmToFile(CConstRef<CPssmWithParameters> pssm)128 CDeltaBlastApp::SavePssmToFile(CConstRef<CPssmWithParameters> pssm)
129 {
130     if (pssm.Empty()) {
131         return;
132     }
133 
134     if (m_CmdLineArgs->SaveCheckpoint()) {
135         *m_CmdLineArgs->GetCheckpointStream() << MSerial_AsnText << *pssm;
136     }
137 
138     if (m_CmdLineArgs->SaveAsciiPssm()) {
139         if (m_AncillaryData.Empty() && pssm.NotEmpty()) {
140             m_AncillaryData = ExtractPssmAncillaryData(*pssm);
141         }
142 
143         CBlastFormatUtil::PrintAsciiPssm(*pssm,
144                                          m_AncillaryData,
145                                          *m_CmdLineArgs->GetAsciiPssmStream());
146     }
147 }
148 
149 
150 // Add query sequence title from scope to computed Pssm
s_AddSeqTitleToPssm(CRef<CPssmWithParameters> pssm,CRef<CBlastQueryVector> query_batch,CRef<CScope> scope)151 static void s_AddSeqTitleToPssm(CRef<CPssmWithParameters> pssm,
152                                 CRef<CBlastQueryVector> query_batch,
153                                 CRef<CScope> scope)
154 {
155     CConstRef<CSeq_id> query_id =
156         query_batch->GetBlastSearchQuery(0)->GetQueryId();
157 
158     CBioseq_Handle bhandle = scope->GetBioseqHandle(*query_id);
159     CConstRef<CBioseq> scope_bioseq = bhandle.GetCompleteBioseq();
160 
161     if (scope_bioseq->IsSetDescr()) {
162 
163         CBioseq& pssm_bioseq = pssm->SetQuery().SetSeq();
164         ITERATE (CSeq_descr::Tdata, it, scope_bioseq->GetDescr().Get()) {
165             pssm_bioseq.SetDescr().Set().push_back(*it);
166         }
167     }
168 }
169 
170 // Add sequence data to pssm query
s_AddSeqDataToPssm(CRef<CPssmWithParameters> pssm,CRef<CBlastQueryVector> query_batch,CRef<CScope> scope)171 static void s_AddSeqDataToPssm(CRef<CPssmWithParameters> pssm,
172                                CRef<CBlastQueryVector> query_batch,
173                                CRef<CScope> scope)
174 {
175     CConstRef<CSeq_id> query_id =
176         query_batch->GetBlastSearchQuery(0)->GetQueryId();
177 
178     // first make sure that query id and pssm query id are the same
179     if (!pssm->GetPssm().GetQuery().GetSeq().GetFirstId()->Match(*query_id)) {
180         NCBI_THROW(CException, eInvalid, "Query and PSSM sequence ids do not "
181                    "match");
182     }
183 
184     CBioseq_Handle bhandle = scope->GetBioseqHandle(*query_id);
185     CConstRef<CBioseq> scope_bioseq = bhandle.GetCompleteBioseq();
186 
187     // set sequence data only if query bioseq has them and pssm does not
188     if (scope_bioseq->GetInst().IsSetSeq_data()
189         && !pssm->GetPssm().GetQuery().GetSeq().GetInst().IsSetSeq_data()) {
190         const CSeq_data& seq_data = scope_bioseq->GetInst().GetSeq_data();
191         pssm->SetQuery().SetSeq().SetInst().SetSeq_data(
192                                           const_cast<CSeq_data&>(seq_data));
193     }
194 }
195 
Run(void)196 int CDeltaBlastApp::Run(void)
197 {
198     int status = BLAST_EXIT_SUCCESS;
199 
200     try {
201 
202         // Allow the fasta reader to complain on invalid sequence input
203         SetDiagPostLevel(eDiag_Warning);
204 	    SetDiagPostPrefix("deltablast");
205         SetDiagHandler(&m_bah, false);
206 
207         /*** Get the BLAST options ***/
208         const CArgs& args = GetArgs();
209         RecoverSearchStrategy(args, m_CmdLineArgs);
210         CRef<CBlastOptionsHandle> opts_hndl(&*m_CmdLineArgs->SetOptions(args));
211         const CBlastOptions& opt = opts_hndl->GetOptions();
212 
213         /*** Initialize the database/subject ***/
214         CRef<CBlastDatabaseArgs> db_args(m_CmdLineArgs->GetBlastDatabaseArgs());
215         CRef<CLocalDbAdapter> db_adapter;
216         CRef<CScope> scope;
217         InitializeSubject(db_args, opts_hndl, m_CmdLineArgs->ExecuteRemotely(),
218                          db_adapter, scope);
219         _ASSERT(db_adapter && scope);
220 
221         /*** Get the query sequence(s) ***/
222         CRef<CQueryOptionsArgs> query_opts =
223             m_CmdLineArgs->GetQueryOptionsArgs();
224         SDataLoaderConfig dlconfig =
225             InitializeQueryDataLoaderConfiguration(query_opts->QueryIsProtein(),
226                                                    db_adapter);
227         CBlastInputSourceConfig iconfig(dlconfig, query_opts->GetStrand(),
228                                      query_opts->UseLowercaseMasks(),
229                                      query_opts->GetParseDeflines(),
230                                      query_opts->GetRange());
231         if(IsIStreamEmpty(m_CmdLineArgs->GetInputStream())){
232            	ERR_POST(Warning << "Query is Empty!");
233            	return BLAST_EXIT_SUCCESS;
234         }
235         CBlastFastaInputSource fasta(m_CmdLineArgs->GetInputStream(), iconfig);
236         size_t query_batch_size = m_CmdLineArgs->GetQueryBatchSize();
237         if (m_CmdLineArgs->GetNumberOfPsiBlastIterations() > 1
238             || m_CmdLineArgs->ExecuteRemotely()) {
239 
240             query_batch_size = 1;
241         }
242         CBlastInput input(&fasta, query_batch_size);
243 
244         /*** Initialize the domain database ***/
245         CRef<CLocalDbAdapter> domain_db_adapter(new CLocalDbAdapter(
246                                     *m_CmdLineArgs->GetDomainDatabase()));
247         _ASSERT(domain_db_adapter);
248         CLocalDbAdapter* domain_db_ptr = NULL;
249 
250         // domain database does not need to be loaded into scope unless
251         // domain search results are requested
252         if (m_CmdLineArgs->GetShowDomainHits()) {
253             CRef<CSeqDB> seqdb(new CSeqDB(domain_db_adapter->GetDatabaseName(),
254                                           CSeqDB::eProtein));
255             scope->AddDataLoader(RegisterOMDataLoader(seqdb),
256                           CBlastDatabaseArgs::kSubjectsDataLoaderPriority - 1);
257 
258             domain_db_ptr = domain_db_adapter.GetNonNullPointer();
259         }
260 
261         /*** Get the formatting options ***/
262         CRef<CFormattingArgs> fmt_args(m_CmdLineArgs->GetFormattingArgs());
263         CBlastFormat formatter(opt, *db_adapter,
264                                fmt_args->GetFormattedOutputChoice(),
265                                query_opts->GetParseDeflines(),
266                                m_CmdLineArgs->GetOutputStream(),
267                                fmt_args->GetNumDescriptions(),
268                                fmt_args->GetNumAlignments(),
269                                *scope,
270                                opt.GetMatrixName(),
271                                fmt_args->ShowGis(),
272                                fmt_args->DisplayHtmlOutput(),
273                                opt.GetQueryGeneticCode(),
274                                opt.GetDbGeneticCode(),
275                                opt.GetSumStatisticsMode(),
276                                m_CmdLineArgs->ExecuteRemotely(),
277                                db_adapter->GetFilteringAlgorithm(),
278                                fmt_args->GetCustomOutputFormatSpec(),
279                                false, false, NULL,
280                                domain_db_ptr,
281                                GetCmdlineArgs(GetArguments()));
282 
283         formatter.SetQueryRange(query_opts->GetRange());
284         formatter.SetLineLength(fmt_args->GetLineLength());
285         if(UseXInclude(*fmt_args, args[kArgOutput].AsString())) {
286         	formatter.SetBaseFile(args[kArgOutput].AsString());
287         }
288         formatter.PrintProlog();
289 
290         /*** Process the input ***/
291         for (; !input.End(); formatter.ResetScopeHistory(), QueryBatchCleanup()) {
292 
293             CRef<CBlastQueryVector> query_batch(input.GetNextSeqBatch(*scope));
294             CRef<blast::IQueryFactory> queries(
295                                      new CObjMgr_QueryFactory(*query_batch));
296 
297             SaveSearchStrategy(args, m_CmdLineArgs, queries, opts_hndl);
298 
299             CRef<blast::CSearchResultSet> results;
300             CRef<blast::CSearchResultSet> domain_results;
301 
302             CRef<CDeltaBlast> deltablast;
303             CRef<CPssmWithParameters> pssm;
304 
305             if (m_CmdLineArgs->ExecuteRemotely()) {
306 
307                 // Remote BLAST
308 
309                 CRef<CRemoteBlast> rmt_blast =
310                     InitializeRemoteBlast(queries, db_args, opts_hndl,
311                           m_CmdLineArgs->ProduceDebugRemoteOutput(),
312                           m_CmdLineArgs->GetClientId());
313                 results = rmt_blast->GetResultSet();
314                 pssm = rmt_blast->GetPSSM();
315             } else {
316 
317                 // Run locally
318 
319                 CRef<CDeltaBlastOptionsHandle> delta_opts(
320                         dynamic_cast<CDeltaBlastOptionsHandle*>(&*opts_hndl));
321 
322                 deltablast.Reset(new CDeltaBlast(queries, db_adapter,
323                                                  domain_db_adapter,
324                                                  delta_opts));
325                 deltablast->SetNumberOfThreads(m_CmdLineArgs->GetNumThreads());
326                 results = deltablast->Run();
327                 domain_results = deltablast->GetDomainResults();
328                 pssm = deltablast->GetPssm();
329             }
330 
331             // deltablast computed pssm does not have query title, so
332             // it must be added if pssm is requested
333             if (m_CmdLineArgs->SaveCheckpoint()
334                 || fmt_args->GetFormattedOutputChoice()
335                 == CFormattingArgs::eArchiveFormat) {
336 
337                 s_AddSeqTitleToPssm(pssm, query_batch, scope);
338             }
339 
340             // remote blast remves sequence data from pssm for known ids
341             // the data must be added if pssm is requested after remote search
342             if (m_CmdLineArgs->ExecuteRemotely()
343                 && (m_CmdLineArgs->SaveCheckpoint()
344                     || m_CmdLineArgs->SaveAsciiPssm())) {
345 
346                 s_AddSeqDataToPssm(pssm, query_batch, scope);
347             }
348 
349             // only one PSI-BLAST iteration requested, then print results
350             // (the first PIS-BLAST iteration is done by DELTA-BLAST)
351             if (m_CmdLineArgs->GetNumberOfPsiBlastIterations() == 1) {
352 
353                 SavePssmToFile(pssm);
354 
355                 blast::CSearchResultSet::const_iterator domain_it;
356                 if (m_CmdLineArgs->GetShowDomainHits()) {
357                     domain_it = domain_results->begin();
358                 }
359 
360                 if (fmt_args->ArchiveFormatRequested(args)) {
361                     formatter.WriteArchive(*queries, *opts_hndl, *results, 0, m_bah.GetMessages());
362                     m_bah.ResetMessages();
363                 } else {
364                     BlastFormatter_PreFetchSequenceData(*results, scope,
365                     		                            fmt_args->GetFormattedOutputChoice());
366                     if (m_CmdLineArgs->GetShowDomainHits()) {
367                         BlastFormatter_PreFetchSequenceData(*domain_results, scope,
368                         		                            fmt_args->GetFormattedOutputChoice());
369                     }
370                     ITERATE(blast::CSearchResultSet, result, *results) {
371                         if (m_CmdLineArgs->GetShowDomainHits()) {
372                             _ASSERT(domain_it != domain_results->end());
373                             formatter.PrintOneResultSet(**domain_it,
374                                   query_batch,
375                                   numeric_limits<unsigned int>::max(),
376                                   blast::CPsiBlastIterationState::TSeqIds(),
377                                   true);
378                             ++domain_it;
379                         }
380                         formatter.PrintOneResultSet(**result, query_batch);
381                     }
382                 }
383 
384                 if (m_CmdLineArgs->GetSaveLastPssm()) {
385                     CConstRef<CBioseq> query_bioseq(&pssm->GetQuery().GetSeq());
386                     blast::CSearchResults& res = (*results)[0];
387 
388                     CRef<CPSIBlastOptionsHandle> psi_opts(
389                         dynamic_cast<CPSIBlastOptionsHandle*>(&*opts_hndl));
390 
391                     pssm = ComputePssmForNextPsiBlastIteration(*query_bioseq,
392                                                      res.GetSeqAlign(),
393                                                      psi_opts,
394                                                      scope,
395                                                      res.GetAncillaryData());
396 
397                     SavePssmToFile(pssm);
398                 }
399             }
400             else {
401 
402                 // if more than 1 iterations are requested, then
403                 // do PSI-BLAST iterations, this is not allowed for remote blast
404 
405                 SavePssmToFile(pssm);
406 
407                 // print domain search results if requested
408                 // query_batch_size == 1 if number of iteratins > 1
409                 if (m_CmdLineArgs->GetShowDomainHits()) {
410                     ITERATE (blast::CSearchResultSet, result,
411                              *deltablast->GetDomainResults()) {
412 
413                         formatter.PrintOneResultSet(**result, query_batch,
414                                     numeric_limits<unsigned int>::max(),
415                                     blast::CPsiBlastIterationState::TSeqIds(),
416                                     true);
417                     }
418                 }
419 
420                 // use pssm variable here, because it will contains query title
421                 CConstRef<CBioseq> query_bioseq(&pssm->GetQuery().GetSeq());
422 
423                 bool retval = DoPsiBlastIterations(opts_hndl,
424                                                    query_batch,
425                                                    query_bioseq,
426                                                    results,
427                                                    db_args,
428                                                    args,
429                                                    db_adapter,
430                                                    scope,
431                                                    formatter);
432 
433                 if (retval && !fmt_args->HasStructuredOutputFormat()
434                     && fmt_args->GetFormattedOutputChoice()
435                     != CFormattingArgs::eArchiveFormat) {
436 
437                     m_CmdLineArgs->GetOutputStream() << NcbiEndl
438                                                      << "Search has CONVERGED!"
439                                                      << NcbiEndl;
440                     }
441                     // Reset for next query sequence.
442                     m_AncillaryData.Reset();
443             }
444         }
445 
446         formatter.PrintEpilog(opt);
447 
448         if (m_CmdLineArgs->ProduceDebugOutput()) {
449             opts_hndl->GetOptions().DebugDumpText(NcbiCerr, "BLAST options", 1);
450         }
451 
452         LogQueryInfo(m_UsageReport, input);
453         formatter.LogBlastSearchInfo(m_UsageReport);
454     } CATCH_ALL(status)
455     if(!m_bah.GetMessages().empty()) {
456      	const CArgs & a = GetArgs();
457      	PrintErrorArchive(a, m_bah.GetMessages());
458     }
459 	m_UsageReport.AddParam(CBlastUsageReport::eNumThreads, (int) m_CmdLineArgs->GetNumThreads());
460     m_UsageReport.AddParam(CBlastUsageReport::eExitStatus, status);
461     return status;
462 }
463 
464 // This is a simplified version of CPsiBlastApp::DoIterations()
465 bool
DoPsiBlastIterations(CRef<CBlastOptionsHandle> opts_hndl,CRef<CBlastQueryVector> query,CConstRef<CBioseq> query_bioseq,CRef<blast::CSearchResultSet> results,CRef<CBlastDatabaseArgs> db_args,const CArgs & args,CRef<CLocalDbAdapter> db_adapter,CRef<CScope> scope,CBlastFormat & formatter)466 CDeltaBlastApp::DoPsiBlastIterations(CRef<CBlastOptionsHandle> opts_hndl,
467                                      CRef<CBlastQueryVector> query,
468                                      CConstRef<CBioseq> query_bioseq,
469                                      CRef<blast::CSearchResultSet> results,
470                                      CRef<CBlastDatabaseArgs> db_args,
471                                      const CArgs& args,
472                                      CRef<CLocalDbAdapter> db_adapter,
473                                      CRef<CScope> scope,
474                                      CBlastFormat& formatter)
475 {
476     bool converged = false;
477 
478     const size_t kNumIterations = m_CmdLineArgs->GetNumberOfPsiBlastIterations();
479 
480 
481     CPsiBlastIterationState itr(kNumIterations);
482     CRef<CPSIBlastOptionsHandle> psi_opts;
483 
484 
485     psi_opts.Reset(dynamic_cast<CPSIBlastOptionsHandle*>(&*opts_hndl));
486     CRef<CPsiBlast> psiblast;
487 
488     CRef<IQueryFactory> query_factory(new CObjMgr_QueryFactory(*query));
489 
490     BlastFormatter_PreFetchSequenceData(*results, scope,
491     		 m_CmdLineArgs->GetFormattingArgs()->GetFormattedOutputChoice());
492     if (CFormattingArgs::eArchiveFormat ==
493         m_CmdLineArgs->GetFormattingArgs()->GetFormattedOutputChoice()) {
494         formatter.WriteArchive(*query_factory, *opts_hndl, *results,
495                                itr.GetIterationNumber(), m_bah.GetMessages());
496         m_bah.ResetMessages();
497     }
498     else {
499         ITERATE(blast::CSearchResultSet, result, *results) {
500             formatter.PrintOneResultSet(**result, query,
501                                         itr.GetIterationNumber(),
502                                         itr.GetPreviouslyFoundSeqIds());
503         }
504     }
505     // FIXME: what if there are no results!?!
506 
507     blast::CSearchResults& results_1st_query = (*results)[0];
508     if ( !results_1st_query.HasAlignments() ) {
509         return false;
510     }
511 
512     CConstRef<CSeq_align_set> aln(results_1st_query.GetSeqAlign());
513     CPsiBlastIterationState::TSeqIds ids;
514     CPsiBlastIterationState::GetSeqIds(aln, psi_opts, ids);
515 
516     itr.Advance(ids);
517 
518     while (itr) {
519 
520         CRef<CPssmWithParameters>
521             pssm = ComputePssmForNextPsiBlastIteration(*query_bioseq, aln,
522                                        psi_opts,
523                                        scope,
524                                        (*results)[0].GetAncillaryData());
525 
526         if (psiblast.Empty()) {
527             psiblast.Reset(new CPsiBlast(pssm, db_adapter, psi_opts));
528         }
529         else {
530             psiblast->SetPssm(pssm);
531         }
532 
533         SavePssmToFile(pssm);
534 
535         psiblast->SetNumberOfThreads(m_CmdLineArgs->GetNumThreads());
536         results = psiblast->Run();
537 
538         BlastFormatter_PreFetchSequenceData(*results, scope,
539         		m_CmdLineArgs->GetFormattingArgs()->GetFormattedOutputChoice());
540         if (CFormattingArgs::eArchiveFormat ==
541             m_CmdLineArgs->GetFormattingArgs()->GetFormattedOutputChoice()) {
542             formatter.WriteArchive(*pssm, *opts_hndl, *results,
543                                    itr.GetIterationNumber());
544         }
545         else {
546             ITERATE(blast::CSearchResultSet, result, *results) {
547                 formatter.PrintOneResultSet(**result, query,
548                                             itr.GetIterationNumber(),
549                                             itr.GetPreviouslyFoundSeqIds());
550             }
551         }
552         // FIXME: what if there are no results!?!
553 
554         blast::CSearchResults& results_1st_query = (*results)[0];
555         if ( !results_1st_query.HasAlignments() ) {
556             break;
557         }
558 
559         aln.Reset(results_1st_query.GetSeqAlign());
560         CPsiBlastIterationState::TSeqIds new_ids;
561         CPsiBlastIterationState::GetSeqIds(aln, psi_opts, new_ids);
562 
563         itr.Advance(new_ids);
564     }
565     if (itr.HasConverged()) {
566         converged = true;
567     }
568 
569     if (m_CmdLineArgs->GetSaveLastPssm()) {
570         CRef<CPssmWithParameters>
571             pssm = ComputePssmForNextPsiBlastIteration(*query_bioseq, aln,
572                                        psi_opts,
573                                        scope,
574                                        results_1st_query.GetAncillaryData());
575 
576         SavePssmToFile(pssm);
577     }
578 
579     return converged;
580 }
581 
582 CRef<CPssmWithParameters>
ComputePssmForNextPsiBlastIteration(const CBioseq & bioseq,CConstRef<CSeq_align_set> sset,CConstRef<CPSIBlastOptionsHandle> opts_handle,CRef<CScope> scope,CRef<CBlastAncillaryData> ancillary_data)583 CDeltaBlastApp::ComputePssmForNextPsiBlastIteration(const CBioseq& bioseq,
584                             CConstRef<CSeq_align_set> sset,
585                             CConstRef<CPSIBlastOptionsHandle> opts_handle,
586                             CRef<CScope> scope,
587                             CRef<CBlastAncillaryData> ancillary_data)
588 {
589     CPSIDiagnosticsRequest
590         diags(PSIDiagnosticsRequestNewEx(m_CmdLineArgs->SaveAsciiPssm()));
591 
592     m_AncillaryData = ancillary_data;
593     return PsiBlastComputePssmFromAlignment(bioseq, sset, scope, *opts_handle,
594                                             m_AncillaryData, diags);
595 }
596 
597 
598 #ifndef SKIP_DOXYGEN_PROCESSING
main(int argc,const char * argv[])599 int main(int argc, const char* argv[] /*, const char* envp[]*/)
600 {
601     return CDeltaBlastApp().AppMain(argc, argv);
602 }
603 #endif /* SKIP_DOXYGEN_PROCESSING */
604 
605 
606