NCBI C++ ToolKit
inversion_merge_aligner.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: inversion_merge_aligner.cpp 71429 2016-03-03 20:39:42Z whlavina $
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  * Author: Nathan Bouk
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbiexpt.hpp>
34 #include <corelib/ncbi_system.hpp>
35 #include <math.h>
36 
38 
41 #include <objmgr/scope.hpp>
51 #include <objmgr/seq_vector.hpp>
52 
55 
56 
58 
61 
62 #define MARKLINE cerr << __FILE__ << ":" << __LINE__ << endl
63 
66  ISequenceSet* QuerySet,
67  ISequenceSet* SubjectSet,
68  TAlignResultsRef AccumResults)
69 {
70  TAlignResultsRef NewResults(new CAlignResultsSet);
71 
73  AccumResults->Get()) {
74  int BestRank = QueryIter->second->GetBestRank();
75  if(BestRank > m_Threshold || BestRank == -1) {
76  _TRACE("Determined ID: "
77  << QueryIter->second->GetQueryId()->AsFastaString()
78  << " needs Inversion Merger.");
79  x_RunMerger(Scope, *QueryIter->second, NewResults);
80  }
81  }
82 
83  return NewResults;
84 }
85 
86 
88  const CRef<CSeq_align>& B)
89 {
90  bool PctCovExists[2];
91  double PctCovs[2];
92 
93  PctCovExists[0] = A->GetNamedScore("pct_coverage", PctCovs[0]);
94  PctCovExists[1] = B->GetNamedScore("pct_coverage", PctCovs[1]);
95 
96  // first come elements with pct_coverage
97  if(PctCovExists[0] != PctCovExists[1])
98  return PctCovExists[0];
99 
100  // if both are without pct_coverage then elements are unordered
101  if (!PctCovExists[0])
102  return false;
103 
104  // if both are with pct_coverage order them by the coverage value
105  return ( PctCovs[0] > PctCovs[1] );
106 }
107 
108 
109 void CInversionMergeAligner::x_RunMerger(objects::CScope& Scope,
110  CQuerySet& QueryAligns,
111  TAlignResultsRef Results)
112 {
113  CRef<CSeq_align_set> ResultSet(new CSeq_align_set);
114 
115 
116  ITERATE(CQuerySet::TAssemblyToSubjectSet, AssemIter, QueryAligns.Get()) {
117  ITERATE(CQuerySet::TSubjectToAlignSet, SubjectIter, AssemIter->second) {
118  //ITERATE(CQuerySet::TSubjectToAlignSet, SubjectIter, QueryIter->second->Get()) {
119 
120  CRef<CSeq_align_set> SubjectSet = SubjectIter->second;
121 
123  Minuses(new CSeq_align_set);
124 
125  x_SplitAlignmentsByStrand(*SubjectSet, *Pluses, *Minuses);
126 
127  //x_HandleSingleStrandMerging(*Pluses, *ResultSet, Scope);
128  //x_HandleSingleStrandMerging(*Minuses, *ResultSet, Scope);
129 
130  if(Pluses->Set().empty() || Minuses->Set().empty()) {
131  continue;
132  }
133 
134  x_SortAlignSet(*Pluses);
135  x_SortAlignSet(*Minuses);
136 
137 
138  double PctCovs[2] = { 0.0, 0.0 };
139  double Expands[2] = { 0.0, 0.0 };
140  double NumIdts[2] = { 0.0, 0.0 };
141 
142  Pluses->Get().front()->GetNamedScore("pct_coverage", PctCovs[0]);
143  Minuses->Get().front()->GetNamedScore("pct_coverage", PctCovs[1]);
144 
145 
146  CRef<CSeq_align_set> Dominant, NonDominant;
147  if(PctCovs[0] >= PctCovs[1]) {
148  Dominant = Pluses;
149  NonDominant = Minuses;
150  } else {
151  Dominant = Minuses;
152  NonDominant = Pluses;
153  }
154 
155  bool Made = false;
156  ITERATE(CSeq_align_set::Tdata, DomIter, Dominant->Get()) {
157  ITERATE(CSeq_align_set::Tdata, NonIter, NonDominant->Get()) {
158 
159  (*DomIter)->GetNamedScore("pct_coverage", PctCovs[0]);
160  (*NonIter)->GetNamedScore("pct_coverage", PctCovs[1]);
161 
162  (*DomIter)->GetNamedScore("expansion", Expands[0]);
163  (*NonIter)->GetNamedScore("expansion", Expands[1]);
164 
165  (*DomIter)->GetNamedScore("num_ident", NumIdts[0]);
166  (*NonIter)->GetNamedScore("num_ident", NumIdts[1]);
167 
168 
169  CRange<TSeqPos> DomSubjRange = (*DomIter)->GetSeqRange(1);
170  CRange<TSeqPos> NonSubjRange = (*NonIter)->GetSeqRange(1);
171 
172  TSeqPos Dist;
173  if(DomSubjRange.IntersectingWith(NonSubjRange)) {
174  Dist = 0;
175  } else {
176  if(DomSubjRange.GetTo() > NonSubjRange.GetTo())
177  Dist = DomSubjRange.GetFrom() - NonSubjRange.GetTo();
178  else
179  Dist = NonSubjRange.GetFrom() - DomSubjRange.GetTo();
180  }
181 
182  if( (PctCovs[0]/PctCovs[1]) <= 1000.0 &&
183  (PctCovs[0]/PctCovs[1]) >= 1.0 &&
184  Dist <= NonSubjRange.GetLength()*10 &&
185  Expands[0] <= 3.0 && Expands[1] <= 3.0 ) {
186 
187  CRef<CSeq_align> Disc(new CSeq_align);
188  Disc = x_CreateDiscAlignment(**DomIter, **NonIter, Scope);
189  if(!Disc.IsNull()) {
190  cerr << "Making Disc: (" << NumIdts[0] << "," << Expands[0] << ") to "
191  << "(" << NumIdts[1] << "," << Expands[1] << ")" << endl;
192  ResultSet->Set().push_back(Disc);
193  Made = true;
194  break;
195  }
196  }
197  }
198  if(Made)
199  break;
200  }
201  } // end Subject Set Loop
202  }
203 
204  if(!ResultSet->Get().empty()) {
205  Results->Insert(CRef<CQuerySet>(new CQuerySet(*ResultSet)));
206  }
207 }
208 
209 
211 {
212  vector<CRef<CSeq_align> > TempVec;
213  TempVec.reserve(AlignSet.Set().size());
214  TempVec.resize(AlignSet.Set().size());
215  copy(AlignSet.Set().begin(), AlignSet.Set().end(), TempVec.begin());
216  sort(TempVec.begin(), TempVec.end(), s_SortByPctCoverage);
217  AlignSet.Set().clear();
218  copy(TempVec.begin(), TempVec.end(),
219  insert_iterator<CSeq_align_set::Tdata>(AlignSet.Set(), AlignSet.Set().end()));
220 }
221 
222 
224  CSeq_align_set& Pluses, CSeq_align_set& Minuses)
225 {
226  ITERATE(CSeq_align_set::Tdata, AlignIter, Source.Get()) {
227  if( (*AlignIter)->GetSeqStrand(0) == eNa_strand_plus)
228  Pluses.Set().push_back(*AlignIter);
229  else if( (*AlignIter)->GetSeqStrand(0) == eNa_strand_minus)
230  Minuses.Set().push_back(*AlignIter);
231  }
232 }
233 
234 
236  CSeq_align_set& Results,
237  CScope& Scope)
238 {
239  CScoreBuilder Scorer;
240 
241  if(Source.CanGet() && !Source.Get().empty()) {
243  Out = x_MergeSeqAlignSet(Source, Scope);
244  if(!Out.IsNull() && Out->CanGet() && !Out->Get().empty()) {
245  NON_CONST_ITERATE(CSeq_align_set::Tdata, MergedIter, Out->Set()) {
246  Scorer.AddScore(Scope, **MergedIter, CSeq_align::eScore_PercentIdentity_Ungapped);
247  Scorer.AddScore(Scope, **MergedIter, CSeq_align::eScore_PercentCoverage);
248 
249  TSeqPos AlignLen, AlignedLen;
250  AlignedLen = Scorer.GetAlignLength(**MergedIter, true);
251  AlignLen = (*MergedIter)->GetSeqRange(1).GetLength();
252  (*MergedIter)->SetNamedScore("expansion", double(AlignLen)/double(AlignedLen) );
253 
254  Source.Set().push_back(*MergedIter);
255  Results.Set().push_back(*MergedIter);
256  }
257  }
258  }
259 }
260 
261 
262 
265 {
268  return CRef<CSeq_align>();
269  }
270 
271  CRef<CSeq_align> Disc(new CSeq_align);
273 
274  CRef<CSeq_align> DomRef(new CSeq_align), NonRef(new CSeq_align);
275  DomRef->Assign(Dom);
276  NonRef->Assign(Non);
277 
278  if (Dom.GetSeq_id(0).IsLocal() &&
279  Dom.GetSeq_id(0).GetLocal().GetStr() == "HG858_PATCH") {
280  TSeqPos SwitchSpot = 35739;
281 
282  if ( NonRef->GetSeqStart(0) == 0 && NonRef->GetSeqStop(0) == SwitchSpot-1) {
283  CRef<CDense_seg> DomSlice, NonSlice;
284  DomSlice = DomRef->GetSegs().GetDenseg().ExtractSlice(0, SwitchSpot, DomRef->GetSeqStop(0));
285  NonSlice = NonRef->GetSegs().GetDenseg().ExtractSlice(0, NonRef->GetSeqStart(0), SwitchSpot-1);
286 
287  DomRef->SetSegs().SetDenseg().Assign(*DomSlice);
288  NonRef->SetSegs().SetDenseg().Assign(*NonSlice);
289  }
290  }
291 
292  if(Dom.GetSeq_id(0).IsLocal() &&
293  (Dom.GetSeq_id(0).GetLocal().GetStr() == "HG281_PATCH" ||
294  Dom.GetSeq_id(0).GetLocal().GetStr() == "HG1000_2_PATCH") ) {
295  return CRef<CSeq_align>();
296  }
297 
298  // Run Clean up on the two parts, as an attempt to uniqify what they cover.
299  CRef<CSeq_align_set> Source(new CSeq_align_set), Cleaned;
300  Source->Set().push_back(DomRef);
301  Source->Set().push_back(NonRef);
302  Cleaned = x_MergeSeqAlignSet(*Source, Scope);
303 
304  if(Cleaned.IsNull() || Cleaned->Set().size() != 2) {
305  return CRef<CSeq_align>();
306  } else {
307  DomRef = Cleaned->Set().front();
308  NonRef = *( ++(Cleaned->Set().begin()) );
309  if(Dom.GetSeqStrand(0) != DomRef->GetSeqStrand(0))
310  swap(DomRef, NonRef);
311  }
312 
313  CDense_seg& DomSeg = DomRef->SetSegs().SetDenseg();
314  CDense_seg& NonSeg = NonRef->SetSegs().SetDenseg();
315 
316 // Find data in gaps
317  int DomIndex = 0, NonIndex = 0;
318  for(DomIndex = 0; DomIndex < DomSeg.GetNumseg(); DomIndex++) {
319 
320  CRange<TSeqPos> DomRange;
321 
322  if(DomSeg.GetStarts()[(DomIndex*DomSeg.GetDim())+1] == -1) {
323  DomRange.SetFrom(DomSeg.GetStarts()[DomIndex*DomSeg.GetDim()]);
324  DomRange.SetLength(DomSeg.GetLens()[DomIndex]);
325  } else {
326  continue;
327  }
328 
329  for(NonIndex = 0; NonIndex < NonSeg.GetNumseg(); NonIndex++) {
330 
331  if(NonSeg.GetStarts()[NonIndex*NonSeg.GetDim()] == -1 ||
332  NonSeg.GetStarts()[(NonIndex*NonSeg.GetDim())+1] == -1)
333  continue;
334 
335  CRange<TSeqPos> NonRange(NonSeg.GetStarts()[NonIndex*NonSeg.GetDim()],
336  NonSeg.GetStarts()[NonIndex*NonSeg.GetDim()]+
337  NonSeg.GetLens()[NonIndex]-1);
338 
339  if(DomRange.IntersectingWith(NonRange)) {
340  if(NonRange.GetLength() <= 16) {
341  NonSeg.SetStarts()[NonIndex*NonSeg.GetDim()] = -1;
342  }
343  }
344  }
345  }
346 
347  NonSeg.RemovePureGapSegs();
348  NonSeg.Compact();
349  if(x_IsAllGap(NonSeg)) {
350  return CRef<CSeq_align>();
351  }
352  NonSeg.TrimEndGaps();
353 
354  CRef<CDense_seg> FillUnaligned = NonSeg.FillUnaligned();
355  if(!FillUnaligned.IsNull()) {
356  NonSeg.Assign(*FillUnaligned);
357  }
358 
359  // Non segment is too short to live
360  if(DomSeg.GetSeqRange(0).GetLength() < 16 ||
361  NonSeg.GetSeqRange(0).GetLength() < 16) {
362  return CRef<CSeq_align>();
363  }
364 
365  Disc->SetSegs().SetDisc().Set().push_back(DomRef);
366  Disc->SetSegs().SetDisc().Set().push_back(NonRef);
367 
368  Disc->SetNamedScore(GetName(), 1);
369 
370  return Disc;
371 }
372 
373 
374 
376 CInversionMergeAligner::x_MergeSeqAlignSet(const CSeq_align_set& InAligns, objects::CScope& Scope)
377 {
378  list<CConstRef<CSeq_align> > In;
379  ITERATE(CSeq_align_set::Tdata, AlignIter, InAligns.Get()) {
380  CConstRef<CSeq_align> Align(*AlignIter);
381  In.push_back(Align);
382  }
383 
385 
386  try {
387  CAlignCleanup Cleaner(Scope);
388  Cleaner.SortInputsByScore(false);
389  Cleaner.FillUnaligned(true);
390  Cleaner.Cleanup(In, Out->Set());
391  } catch(CException& e) {
392  ERR_POST(Error << "Cleanup Error: " << e.ReportAll());
393  throw e;
394  }
395 
396  NON_CONST_ITERATE(CSeq_align_set::Tdata, AlignIter, Out->Set()) {
397  CRef<CSeq_align> Align(*AlignIter);
398  CDense_seg& Denseg = Align->SetSegs().SetDenseg();
399 
400  if(!Denseg.CanGetStrands() || Denseg.GetStrands().empty()) {
401  Denseg.SetStrands().resize(Denseg.GetDim()*Denseg.GetNumseg(), eNa_strand_plus);
402  }
403 
404  if(Denseg.GetSeqStrand(1) != eNa_strand_plus) {
405  Denseg.Reverse();
406  }
407 
408  CRef<CDense_seg> Filled = Denseg.FillUnaligned();
409  Denseg.Assign(*Filled);
410  }
411 
412  if(Out->Set().empty())
413  return CRef<CSeq_align_set>();
414  return Out;
415 }
416 
417 
419 {
420  for(int Index = 0; Index < Denseg.GetNumseg(); Index++) {
421  if( Denseg.GetStarts()[Index*Denseg.GetDim()] != -1 &&
422  Denseg.GetStarts()[(Index*Denseg.GetDim())+1] != -1) {
423  return false;
424  }
425  }
426  return true;
427 }
428 
429 
431 //end
Declares the CBl2Seq (BLAST 2 Sequences) class.
Declares the CBlastNucleotideOptionsHandle class.
Declares the CBlastOptionsHandle and CBlastOptionsFactory classes.
Definitions of special type used in BLAST.
Main argument class for BLASTN application.
class CAlignCleanup implements an alignment cleanup utility based on the C++ alignment manager.
void FillUnaligned(bool b)
Fill any unaligned regions with explicit gaps.
void SortInputsByScore(bool b)
flags these primarity affect the CAlnVec implementation
void Cleanup(const TAligns &aligns_in, TAligns &aligns_out, EMode mode=eDefault)
void TrimEndGaps()
Trim leading/training gaps if possible.
Definition: Dense_seg.cpp:344
ENa_strand GetSeqStrand(TDim row) const
Definition: Dense_seg.cpp:241
void Reverse(void)
Reverse the segments' orientation.
Definition: Dense_seg.cpp:644
void RemovePureGapSegs()
Remove any segments in which every row has a gap (these can arise when ExtractRows is used)
Definition: Dense_seg.cpp:574
CRef< CDense_seg > ExtractSlice(TDim row, TSeqPos from, TSeqPos to) const
Extract a slice of the alignment that includes the specified range.
Definition: Dense_seg.cpp:747
CRef< CDense_seg > FillUnaligned() const
Create a new dense-seg with added all unaligned pieces (implicit inserts), if any,...
Definition: Dense_seg.cpp:1108
void Compact()
Join adjacent mergeable segments to create a more compact alignment.
Definition: Dense_seg.cpp:432
CRange< TSeqPos > GetSeqRange(TDim row) const
Definition: Dense_seg.hpp:234
void Assign(const CSerialObject &obj, ESerialRecursionMode how=eRecursive)
overloaded Assign()
Definition: Dense_seg.cpp:62
void x_SplitAlignmentsByStrand(const objects::CSeq_align_set &Source, objects::CSeq_align_set &Pluses, objects::CSeq_align_set &Minuses)
void x_HandleSingleStrandMerging(objects::CSeq_align_set &Source, objects::CSeq_align_set &Results, objects::CScope &Scope)
void x_RunMerger(objects::CScope &Scope, CQuerySet &QueryAligns, TAlignResultsRef Results)
void x_SortAlignSet(objects::CSeq_align_set &AlignSet)
CRef< objects::CSeq_align > x_CreateDiscAlignment(const objects::CSeq_align &Dom, const objects::CSeq_align &Non, objects::CScope &Scope)
CRef< objects::CSeq_align_set > x_MergeSeqAlignSet(const objects::CSeq_align_set &InAligns, objects::CScope &Scope)
static bool s_SortByPctCoverage(const CRef< objects::CSeq_align > &A, const CRef< objects::CSeq_align > &B)
TAlignResultsRef GenerateAlignments(objects::CScope &Scope, ISequenceSet *QuerySet, ISequenceSet *SubjectSet, TAlignResultsRef AccumResults)
bool x_IsAllGap(const objects::CDense_seg &Denseg)
TAssemblyToSubjectSet & Get()
Definition: result_set.hpp:82
CRef –.
Definition: ncbiobj.hpp:618
CScope –.
Definition: scope.hpp:92
TSeqPos GetAlignLength(const CSeq_align &align, bool ungapped=false)
Compute the length of the alignment (= length of all segments, gaps + aligned)
void AddScore(CScope &scope, CSeq_align &align, EScoreType score)
deprecated: use CSeq_align::EScoreType directly
@ eScore_PercentIdentity_Ungapped
Definition: Seq_align.hpp:164
@ eScore_PercentCoverage
Definition: Seq_align.hpp:168
TSeqPos GetSeqStop(TDim row) const
Definition: Seq_align.cpp:273
void SetNamedScore(const string &id, int score)
Definition: Seq_align.cpp:636
const CSeq_id & GetSeq_id(TDim row) const
Get seq-id (the first one if segments have different ids).
Definition: Seq_align.cpp:317
bool GetNamedScore(const string &id, int &score) const
Get score.
Definition: Seq_align.cpp:563
TSeqPos GetSeqStart(TDim row) const
Definition: Seq_align.cpp:252
ENa_strand GetSeqStrand(TDim row) const
Get strand (the first one if segments have different strands).
Definition: Seq_align.cpp:294
Declares the CDiscNucleotideOptionsHandle class.
#define A(i)
Definition: ecp_curves.c:936
unsigned int TSeqPos
Type for sequence locations and lengths.
Definition: ncbimisc.hpp:875
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
Definition: ncbimisc.hpp:822
void swap(NCBI_NS_NCBI::pair_base_member< T1, T2 > &pair1, NCBI_NS_NCBI::pair_base_member< T1, T2 > &pair2)
Definition: ncbimisc.hpp:1508
#define _TRACE(message)
Definition: ncbidbg.hpp:122
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
Definition: ncbidiag.hpp:186
void Error(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1197
string ReportAll(TDiagPostFlags flags=eDPF_Exception) const
Report all exceptions.
Definition: ncbiexpt.cpp:370
virtual void Assign(const CSerialObject &source, ESerialRecursionMode how=eRecursive)
Set object to copy of another one.
bool IsNull(void) const THROWS_NONE
Check if pointer is null – same effect as Empty().
Definition: ncbiobj.hpp:735
position_type GetLength(void) const
Definition: range.hpp:158
bool IntersectingWith(const TThisType &r) const
Definition: range.hpp:331
TThisType & SetLength(position_type length)
Definition: range.hpp:194
#define END_SCOPE(ns)
End the previously defined scope.
Definition: ncbistl.hpp:75
#define BEGIN_SCOPE(ns)
Define a new scope.
Definition: ncbistl.hpp:72
void SetFrom(TFrom value)
Assign a value to From data member.
Definition: Range_.hpp:231
TTo GetTo(void) const
Get the To member data.
Definition: Range_.hpp:269
TFrom GetFrom(void) const
Get the From member data.
Definition: Range_.hpp:222
const TStr & GetStr(void) const
Get the variant data.
Definition: Object_id_.hpp:297
const TDenseg & GetDenseg(void) const
Get the variant data.
Definition: Seq_align_.cpp:153
Tdata & Set(void)
Assign a value to data member.
bool CanGet(void) const
Check if it is safe to call Get method.
E_Choice Which(void) const
Which variant is currently selected.
Definition: Seq_align_.hpp:691
const TStarts & GetStarts(void) const
Get the Starts member data.
Definition: Dense_seg_.hpp:530
void SetSegs(TSegs &value)
Assign a value to Segs data member.
Definition: Seq_align_.cpp:310
const TLens & GetLens(void) const
Get the Lens member data.
Definition: Dense_seg_.hpp:555
void SetType(TType value)
Assign a value to Type data member.
Definition: Seq_align_.hpp:818
TDim GetDim(void) const
Get the Dim member data.
Definition: Dense_seg_.hpp:421
TStarts & SetStarts(void)
Assign a value to Starts data member.
Definition: Dense_seg_.hpp:536
TStrands & SetStrands(void)
Assign a value to Strands data member.
Definition: Dense_seg_.hpp:586
bool CanGetStrands(void) const
Check if it is safe to call GetStrands method.
Definition: Dense_seg_.hpp:574
TNumseg GetNumseg(void) const
Get the Numseg member data.
Definition: Dense_seg_.hpp:465
list< CRef< CSeq_align > > Tdata
const TStrands & GetStrands(void) const
Get the Strands member data.
Definition: Dense_seg_.hpp:580
const Tdata & Get(void) const
Get the member data.
const TSegs & GetSegs(void) const
Get the Segs member data.
Definition: Seq_align_.hpp:921
@ eType_disc
discontinuous alignment
Definition: Seq_align_.hpp:104
const TLocal & GetLocal(void) const
Get the variant data.
Definition: Seq_id_.cpp:193
bool IsLocal(void) const
Check if variant Local is selected.
Definition: Seq_id_.hpp:775
@ eNa_strand_plus
Definition: Na_strand_.hpp:66
@ eNa_strand_minus
Definition: Na_strand_.hpp:67
USING_SCOPE(objects)
Main class to perform a BLAST search on the local machine.
constexpr auto sort(_Init &&init)
Magic spell ;-) needed for some weird compilers... very empiric.
Defines NCBI C++ exception handling.
void copy(Njn::Matrix< S > *matrix_, const Njn::Matrix< T > &matrix0_)
Definition: njn_matrix.hpp:613
void Out(T t, int w, CNcbiOstream &to=cout)
Definition: parse.cpp:467
Modified on Wed Apr 17 13:10:27 2024 by modify_doxy.py rev. 669887