showalign.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:72k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: showalign.cpp,v $
  4.  * PRODUCTION Revision 1000.5  2004/06/01 19:41:04  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.36
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: showalign.cpp,v 1000.5 2004/06/01 19:41:04 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Jian Ye
  35.  *
  36.  * File Description:
  37.  *   Sequence alignment display
  38.  *
  39.  */
  40. #include <ncbi_pch.hpp>
  41. #include <objtools/alnmgr/util/showalign.hpp>
  42. #include <corelib/ncbiexpt.hpp>
  43. #include <corelib/ncbiutil.hpp>
  44. #include <corelib/ncbistre.hpp>
  45. #include <corelib/ncbireg.hpp>
  46. #include <util/range.hpp>
  47. #include <util/md5.hpp>
  48. #include <objects/general/Object_id.hpp>
  49. #include <objects/general/User_object.hpp>
  50. #include <objects/general/User_field.hpp>
  51. #include <objects/general/Dbtag.hpp>
  52. #include <serial/iterator.hpp>
  53. #include <serial/objistr.hpp>
  54. #include <serial/objostr.hpp>
  55. #include <serial/serial.hpp>
  56. #include <serial/objostrasnb.hpp> 
  57. #include <serial/objistrasnb.hpp> 
  58. #include <connect/ncbi_conn_stream.hpp>
  59. #include <objmgr/object_manager.hpp>
  60. #include <objmgr/scope.hpp>
  61. #include <objmgr/feat_ci.hpp>
  62. #include <objtools/data_loaders/genbank/gbloader.hpp>
  63. #include <objmgr/util/sequence.hpp>
  64. #include <objmgr/util/feature.hpp>
  65. #include <objects/seqfeat/SeqFeatData.hpp>
  66. #include <objects/seqfeat/Cdregion.hpp>
  67. #include <objects/seq/Seq_descr.hpp>
  68. #include <objects/seq/Seqdesc.hpp>
  69. #include <objects/seq/Bioseq.hpp>
  70. #include <objects/seqset/Seq_entry.hpp>
  71. #include <objects/seqloc/Seq_id.hpp>
  72. #include <objects/seqloc/Seq_interval.hpp>
  73. #include <objects/seqalign/Seq_align_set.hpp>
  74. #include <objects/seqalign/Score.hpp>
  75. #include <objects/seqalign/Std_seg.hpp>
  76. #include <objects/seqalign/Dense_diag.hpp>
  77. #include <objtools/alnmgr/alnmix.hpp>
  78. #include <objtools/alnmgr/alnvec.hpp>
  79. #include <objects/blastdb/Blast_def_line.hpp>
  80. #include <objects/blastdb/Blast_def_line_set.hpp>
  81. #include <objects/blastdb/defline_extra.hpp>
  82. #include <stdio.h>
  83. #include <util/tables/raw_scoremat.h>
  84. BEGIN_NCBI_SCOPE
  85. BEGIN_SCOPE (objects)
  86. USING_SCOPE (sequence);
  87. static const char k_IdentityChar = '.';
  88. static const int k_NumFrame = 6;
  89. static const string k_FrameConversion[k_NumFrame] = {"+1", "+2", "+3", "-1", "-2", "-3"};
  90. static const int k_GetSubseqThreshhold = 10000;
  91. static const int k_ColorMismatchIdentity = 0;  /*threshhold to color mismatch.  98 means 98% */
  92. static const string k_DumpGnlUrl = "/blast/dumpgnl.cgi";
  93. static const int k_FeatureIdLen = 16;
  94. static const int k_NumAsciiChar = 128;
  95. const string color[]={"#000000", "#808080", "#FF0000"};
  96. static const char k_PSymbol[CDisplaySeqalign::kPMatrixSize+1] = "ARNDCQEGHILKMFPSTWYVBZX";
  97. /* url for linkout*/
  98. static const string k_EntrezUrl = "<a href="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=%s&list_uids=%d&dopt=%s" %s>";
  99. static const string k_TraceUrl = "<a href="http://www.ncbi.nlm.nih.gov/Traces/trace.cgi?cmd=retrieve&dopt=fasta&val=%s">";
  100. static const string k_LocusLinkUrl = "<a href="http://www.ncbi.nlm.nih.gov/LocusLink/list.cgi?Q=%d%s"><img border=0 height=16 width=16 src="/blast/images/L.gif" alt="LocusLink info"></a>";
  101. static const string k_UnigeneUrl = "<a href="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=unigene&cmd=search&term=%d[Nucleotide+UID]"><img border=0 height=16 width=16 src="/blast/images/U.gif" alt="UniGene info"></a>";
  102. static const string k_StructureUrl = "<a href="http://www.ncbi.nlm.nih.gov/Structure/cblast/cblast.cgi?blast_RID=%s&blast_rep_gi=%d&hit=%d&blast_CD_RID=%s&blast_view=%s&hsp=0&taxname=%s&client=blast"><img border=0 height=16 width=16 src="http://www.ncbi.nlm.nih.gov/Structure/cblast/str_link.gif" alt="Related structures"></a>";
  103. static const string k_StructureOverviewUrl = "<a href="http://www.ncbi.nlm.nih.gov/Structure/cblast/cblast.cgi?blast_RID=%s&blast_rep_gi=%d&hit=%d&blast_CD_RID=%s&blast_view=%s&hsp=0&taxname=%s&client=blast">Related Structures</a>";
  104. static const string k_GeoUrl =  "<a href="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=geo&term=%d[gi]"><img border=0 height=16 width=16 src="/blast/images/G.gif" alt="Geo"></a>";
  105. //Constructor
  106. CDisplaySeqalign::CDisplaySeqalign(const CSeq_align_set& seqalign, list <SeqlocInfo*>& maskSeqloc, list <FeatureInfo*>& externalFeature, const int matrix[][kPMatrixSize], CScope& scope) : m_SeqalignSetRef(&seqalign), m_Seqloc(maskSeqloc), m_QueryFeature(externalFeature), m_Scope(scope) {
  107.   m_AlignOption = 0;
  108.   m_SeqLocChar = eX;
  109.   m_SeqLocColor = eBlack;
  110.   m_LineLen = 60;
  111.   m_IdStartMargin = 2;
  112.   m_StartSequenceMargin = 2;
  113.   m_SeqStopMargin = 2;
  114.   m_IsDbNa = true;
  115.   m_IsQueryNa = true;
  116.   m_IsDbGi = false;
  117.   m_DbName = NcbiEmptyString;
  118.   m_NumAlignToShow = 10000;
  119.   m_AlignType = eNotSet;
  120.   m_Rid = "0";
  121.   m_CddRid = "0";
  122.   m_EntrezTerm = NcbiEmptyString;
  123.   m_QueryNumber = 0;
  124.   m_BlastType = NcbiEmptyString;
  125.   m_MidLineStyle = eBar;
  126.   m_ConfigFile = NULL;
  127.   m_Reg = NULL;
  128.   SNCBIFullScoreMatrix blosumMatrix;
  129.   NCBISM_Unpack(&NCBISM_Blosum62, &blosumMatrix);
  130.  
  131.   int** temp = new int*[k_NumAsciiChar];
  132.   for(int i = 0; i<k_NumAsciiChar; ++i) {
  133.     temp[i] = new int[k_NumAsciiChar];
  134.   }
  135.   for (int i=0; i<k_NumAsciiChar; i++){
  136.     for (int j=0; j<k_NumAsciiChar; j++){
  137.       temp[i][j] = -1000;
  138.     }
  139.   }
  140.   for(int i = 0; i < kPMatrixSize; ++i){
  141.     for(int j = 0; j < kPMatrixSize; ++j){
  142.       if(matrix){
  143. temp[(size_t)k_PSymbol[i]][(size_t)k_PSymbol[j]] = matrix[i][j];
  144.       } else {
  145. temp[(size_t)k_PSymbol[i]][(size_t)k_PSymbol[j]] = blosumMatrix.s[(size_t)k_PSymbol[i]][(size_t)k_PSymbol[j]];
  146.       }
  147.      
  148.     }
  149.   }
  150.   for(int i = 0; i < kPMatrixSize; ++i) {
  151.     temp[(size_t)k_PSymbol[i]]['*'] = temp['*'][(size_t)k_PSymbol[i]] = -4;
  152.   }
  153.   temp['*']['*'] = 1;
  154.  
  155.   m_Matrix = temp;
  156.  
  157. }
  158. //Destructor
  159. CDisplaySeqalign::~CDisplaySeqalign(){
  160.   for(int i = 0; i<k_NumAsciiChar; ++i) {
  161.     delete [] m_Matrix[i];
  162.   }
  163.   delete [] m_Matrix;
  164.   if (m_ConfigFile) {
  165.     delete m_ConfigFile;
  166.   } 
  167.   if (m_Reg) {
  168.     delete m_Reg;
  169.   }
  170. }
  171. static void AddSpace(CNcbiOstream& out, int number);
  172. static string GetTaxNames(const CBioseq& cbsp, int taxid);
  173. static string getNameInitials(string& name);
  174. static string GetSeqForm(char* formName, bool dbIsNa, int queryNumber);
  175. static const string GetSeqIdStringByFastaOrder(const CSeq_id& id, CScope& sp, bool with_version);
  176. static int GetGiForSeqIdList (const list<CRef<CSeq_id> >& ids);
  177. static string MakeURLSafe(char* src);
  178. static void getAlnScores(const CSeq_align& aln, int& score, double& bits, double& evalue);
  179. template<class container> static bool s_GetBlastScore(const container& scoreList,  int& score, double& bits, double& evalue);
  180. static bool s_canDoMultiAlign(const CSeq_align_set& aln, CScope& scope);
  181. static CRef<CSeq_id> GetSeqIdByType(const list<CRef<CSeq_id> >& ids, CSeq_id::E_Choice choice);
  182. static int s_getFrame (int start, ENa_strand strand, const CSeq_id& id, CScope& sp);
  183. static CRef<CSeq_align> CreateDensegFromDendiag(const CSeq_align& aln);
  184. static void x_ColorDifferentBases(string& seq, char identityChar, CNcbiOstream& out);
  185. static void s_WrapOutputLine(CNcbiOstream& out, const string& str);
  186. static void s_WrapOutputLine(CNcbiOstream& out, const string& str){
  187.   const int line_len = 60;
  188.   const int front_space = 12;
  189.   bool do_wrap = false;
  190.   int length = (int) str.size();
  191.   if (length > line_len) {
  192.     for (int i = 0; i < length; i ++){
  193.       if(i > 0 && i % line_len == 0){
  194. do_wrap = true;
  195.       }   
  196.       out << str[i];
  197.       if(do_wrap && isspace(str[i])){
  198. out << endl;  
  199. AddSpace(out, front_space);
  200. do_wrap = false;
  201.       }
  202.     }
  203.   } else {
  204.     out << str;
  205.   }
  206. }
  207. //To add color to bases other than identityChar
  208. static void x_ColorDifferentBases(string& seq, char identityChar, CNcbiOstream& out){
  209.   string base_color = "#FF0000";
  210.   bool tagOpened = false;
  211.   for(int i = 0; i < (int)seq.size(); i ++){
  212.     if(seq[i] != identityChar){
  213.       if(!tagOpened){
  214. out << "<font color=""+base_color+""><b>";
  215. tagOpened =  true;
  216.       }
  217.      
  218.     } else {
  219.       if(tagOpened){
  220. out << "</b></font>";
  221. tagOpened = false;
  222.       }
  223.     }
  224.     out << seq[i];
  225.     if(tagOpened && i == (int)seq.size() - 1){
  226.       out << "</b></font>";
  227.       tagOpened = false;
  228.     }
  229.   } 
  230. }
  231. template<class container> static bool s_GetBlastScore(const container&  scoreList,  int& score, double& bits, double& evalue){
  232.   bool hasScore = false;
  233.   ITERATE (typename container, iter, scoreList) {
  234.     const CObject_id& id=(*iter)->GetId();
  235.     if (id.IsStr()) {
  236.       hasScore = true;
  237.       if (id.GetStr()=="score"){
  238. score = (*iter)->GetValue().GetInt();
  239.       
  240.       } else if (id.GetStr()=="bit_score"){
  241. bits = (*iter)->GetValue().GetReal();
  242.       } else if (id.GetStr()=="e_value" || id.GetStr()=="sum_e") {
  243. evalue = (*iter)->GetValue().GetReal();
  244.       } 
  245.     }
  246.   }
  247.   return hasScore;
  248. }
  249. static CRef<CSeq_align> CreateDensegFromDendiag(const CSeq_align& aln) {
  250.   CRef<CSeq_align> sa(new CSeq_align);
  251.   if ( !aln.GetSegs().IsDendiag()) {
  252.     NCBI_THROW(CException, eUnknown, "Input Seq-align should be Dendiag!");
  253.   }
  254.   
  255.   if(aln.IsSetType()){
  256.     sa->SetType(aln.GetType());
  257.   }
  258.   if(aln.IsSetDim()){
  259.     sa->SetDim(aln.GetDim());
  260.   }
  261.   if(aln.IsSetScore()){
  262.     sa->SetScore() = aln.GetScore();
  263.   }
  264.   if(aln.IsSetBounds()){
  265.     sa->SetBounds() = aln.GetBounds();
  266.   }
  267.   
  268.   CDense_seg& ds = sa->SetSegs().SetDenseg();
  269.   int counter = 0;
  270.   ds.SetNumseg() = 0;
  271.   ITERATE (CSeq_align::C_Segs::TDendiag, iter, aln.GetSegs().GetDendiag()){
  272.      
  273.     if(counter == 0){//assume all dendiag segments have same dim and ids
  274.       if((*iter)->IsSetDim()){
  275. ds.SetDim((*iter)->GetDim());
  276.       }
  277.       if((*iter)->IsSetIds()){
  278. ds.SetIds() = (*iter)->GetIds();
  279.       }
  280.     }
  281.     ds.SetNumseg() ++;
  282.     if((*iter)->IsSetStarts()){
  283.       ITERATE(CDense_diag::TStarts, iterStarts, (*iter)->GetStarts()){
  284. ds.SetStarts().push_back(*iterStarts);
  285.       }
  286.     }
  287.     if((*iter)->IsSetLen()){
  288.       ds.SetLens().push_back((*iter)->GetLen());
  289.     }
  290.     if((*iter)->IsSetStrands()){
  291.       ITERATE(CDense_diag::TStrands, iterStrands, (*iter)->GetStrands()){
  292. ds.SetStrands().push_back(*iterStrands);
  293.       }
  294.     }
  295.     if((*iter)->IsSetScores()){
  296.       ITERATE(CDense_diag::TScores, iterScores, (*iter)->GetScores()){
  297. ds.SetScores().push_back(*iterScores); //this might not have right meaning
  298.       }
  299.     }
  300.     counter ++;
  301.   }
  302.   
  303.   return sa;
  304. }
  305. static int s_GetStdsegMasterFrame(const CStd_seg& ss, CScope& scope){
  306.   const CRef<CSeq_loc> slc = ss.GetLoc().front();
  307.   ENa_strand strand = GetStrand(*slc);
  308.   int frame = s_getFrame(strand ==  eNa_strand_plus ? GetStart(*slc) : GetStop(*slc), strand ==  eNa_strand_plus? eNa_strand_plus : eNa_strand_minus, *(ss.GetIds().front()), scope);
  309.   
  310.   return frame;
  311. }
  312. /*Note that start is zero bases.  It returns frame +/1(1-3).  ) indicates erro*/
  313. static int s_getFrame (int start, ENa_strand strand, const CSeq_id& id, CScope& sp) {
  314.   int frame = 0;
  315.   if (strand == eNa_strand_plus) {
  316.     frame = (start % 3) + 1;
  317.   } else if (strand == eNa_strand_minus) {
  318.     frame = -((sp.GetBioseqHandle(id).GetBioseqCore()->GetInst().GetLength() - start - 1) % 3 + 1);
  319.    
  320.   }
  321.   return frame;
  322. }
  323. static bool s_canDoMultiAlign(const CSeq_align_set& aln, CScope& scope){
  324.   bool multiAlign = true;
  325.   int firstFrame = 0;
  326.   bool isFirstSeqalign = true;
  327.   /*Make sure that in case of stdseg, the master must be in same frame for all pairwise for multialign view */
  328.   for (CTypeConstIterator<CSeq_align> seqalign = ConstBegin(aln); seqalign; ++ seqalign){
  329.     if (seqalign->GetSegs().Which() == CSeq_align::C_Segs::e_Denseg){
  330.       break;
  331.     } else if (seqalign->GetSegs().Which() == CSeq_align::C_Segs::e_Std){
  332.       CTypeConstIterator<CStd_seg> ss = ConstBegin(*seqalign);     
  333.       int curFrame = s_GetStdsegMasterFrame(*ss, scope);
  334.       if (isFirstSeqalign){
  335. firstFrame = curFrame;
  336. isFirstSeqalign = false;
  337.       } else {
  338. if (firstFrame != curFrame){
  339.   multiAlign = false;
  340.   break;
  341. }
  342.        
  343.       }
  344.     }
  345.    
  346.   }
  347.   return multiAlign;
  348. }
  349. static void getAlnScores(const CSeq_align& aln, int& score, double& bits, double& evalue){
  350.   bool hasScore = false;
  351.   //look for scores at seqalign level first
  352.   hasScore = s_GetBlastScore(aln.GetScore(),  score, bits, evalue);
  353.   //look at the seg level
  354.   if(!hasScore){
  355.     const CSeq_align::TSegs& seg = aln.GetSegs();
  356.     if(seg.Which() == CSeq_align::C_Segs::e_Std){
  357.       s_GetBlastScore(seg.GetStd().front()->GetScores(),  score, bits, evalue);
  358.     } else if (seg.Which() == CSeq_align::C_Segs::e_Dendiag){
  359.       s_GetBlastScore(seg.GetDendiag().front()->GetScores(),  score, bits, evalue);
  360.     }  else if (seg.Which() == CSeq_align::C_Segs::e_Denseg){
  361.        s_GetBlastScore(seg.GetDenseg().GetScores(),  score, bits, evalue);
  362.     }
  363.   }
  364. }
  365. string CDisplaySeqalign::getUrl(const list<CRef<CSeq_id> >& ids, int row) const{
  366.   string urlLink = NcbiEmptyString;
  367.  
  368.   char dopt[32], db[32];
  369.   int gi = GetGiForSeqIdList(ids);
  370.   string toolUrl= m_Reg->Get(m_BlastType, "TOOL_URL");
  371.   if(toolUrl == NcbiEmptyString || (gi > 0 && toolUrl.find("dumpgnl.cgi") != string::npos)){ //use entrez or dbtag specified
  372.     if(m_IsDbNa) {
  373.       strcpy(dopt, "GenBank");
  374.       strcpy(db, "Nucleotide");
  375.     } else {
  376.       strcpy(dopt, "GenPept");
  377.       strcpy(db, "Protein");
  378.     }    
  379.  
  380.     char urlBuf[1024];
  381.     if (gi > 0) {
  382.       sprintf(urlBuf, k_EntrezUrl.c_str(), db, gi, dopt, (m_AlignOption & eNewTargetWindow) ? "TARGET="EntrezView"" : "");
  383.       urlLink = urlBuf;
  384.     } else {//seqid general, dbtag specified
  385.       const CRef<CSeq_id> wid = FindBestChoice(ids, CSeq_id::WorstRank);
  386.       if(wid->Which() == CSeq_id::e_General){
  387.         const CDbtag& dtg = wid->GetGeneral();
  388.         const string& dbName = dtg.GetDb();
  389.         if(NStr::CompareNocase(dbName, "TI") == 0){
  390.           sprintf(urlBuf, k_TraceUrl.c_str(), wid->GetSeqIdString().c_str());
  391.           urlLink = urlBuf;
  392.         } else { //future use
  393.         }
  394.       }
  395.     }
  396.   } else { //need to use url in configuration file
  397.     string altUrl = NcbiEmptyString;
  398.       urlLink = getDumpgnlLink(ids, row, altUrl);
  399.   }
  400.   return urlLink;
  401. }
  402. static string getNameInitials(string& name){
  403.   vector<string> arr;
  404.   string initials;
  405.   NStr::Tokenize(name, " ", arr);
  406.   for(vector<string>::iterator iter = arr.begin(); iter != arr.end(); iter ++){
  407.     if (*iter != NcbiEmptyString){
  408.       initials += (*iter)[0];
  409.     }
  410.   }
  411.   return initials;
  412. }
  413. static void AddSpace(CNcbiOstream& out, int number){
  414.   for(int i=0; i<number; i++){
  415.     out<<" ";
  416.   }
  417. }
  418. void CDisplaySeqalign::AddLinkout(const CBioseq& cbsp, const CBlast_def_line& bdl, int firstGi, int gi, CNcbiOstream& out) const{
  419.   char molType[8]={""};
  420.   if(cbsp.IsAa()){
  421.     sprintf(molType, "[pgi]");
  422.   }
  423.   else {
  424.     sprintf(molType, "[ngi]");
  425.   }
  426.  
  427.   if (bdl.IsSetLinks()){
  428.     for (list< int >::const_iterator iter = bdl.GetLinks().begin(); iter != bdl.GetLinks().end(); iter ++){
  429.       char buf[1024];
  430.       if((*iter) & eLocuslink){
  431.         sprintf(buf, k_LocusLinkUrl.c_str(), gi, molType);
  432.         out << buf;
  433.       }
  434.       if ((*iter) & eUnigene) {
  435. sprintf(buf, k_UnigeneUrl.c_str(),  gi);
  436. out << buf;
  437.       }
  438.       if ((*iter) & eStructure){
  439.         sprintf(buf, k_StructureUrl.c_str(), m_Rid.c_str(), firstGi, gi, m_CddRid.c_str(), "onepair", (m_EntrezTerm == NcbiEmptyString) ? "none":((char*) m_EntrezTerm.c_str()));
  440. out << buf;
  441.       }
  442.       if ((*iter) & eGeo){
  443.          sprintf(buf, k_GeoUrl.c_str(), gi);
  444.          out << buf;
  445.       }
  446.     }
  447.   }
  448. }
  449. //return the get sequence table for html display
  450. static string GetSeqForm(char* formName, bool dbIsNa, int queryNumber){
  451.   char buf[2048] = {""};
  452.   if(formName){
  453.     sprintf(buf, "<table border="0"><tr><td><FORM  method="post" action="http://www.ncbi.nlm.nih.gov:80/entrez/query.fcgi?SUBMIT=y" name="%s"><input type=button value="Get selected sequences" onClick="finalSubmit(%d, 'getSeqAlignment%d', 'getSeqGi', '%s')"><input type="hidden" name="db" value=""><input type="hidden" name="term" value=""><input type="hidden" name="doptcmdl" value="docsum"><input type="hidden" name="cmd" value="search"></form></td><td><FORM><input type="button" value="Select all" onClick="handleCheckAll('select', 'getSeqAlignment%d', 'getSeqGi')"></form></td><td><FORM><input type="button" value="Deselect all" onClick="handleCheckAll('deselect', 'getSeqAlignment%d', 'getSeqGi')"></form></td></tr></table>", formName, dbIsNa?1:0, queryNumber, formName, queryNumber, queryNumber);
  454.    
  455.   }
  456.   return buf;
  457. }
  458. //Return the seqid in "fasta" orders
  459. static const string GetSeqIdStringByFastaOrder(const CSeq_id& id, CScope& sp, bool with_version){
  460.   string idString = NcbiEmptyString;
  461.   static const int total_seqid_types=19;
  462.   static int fasta_order[total_seqid_types];
  463.   //fasta order.  See seqidwrite() in C library
  464.   fasta_order[CSeq_id::e_not_set]=33;
  465.   fasta_order[CSeq_id::e_Local]=20;
  466.   fasta_order[CSeq_id::e_Gibbsq]=15;
  467.   fasta_order[CSeq_id::e_Gibbmt]=16;
  468.   fasta_order[CSeq_id::e_Giim]=30;
  469.   fasta_order[CSeq_id::e_Genbank]=10;   
  470.   fasta_order[CSeq_id::e_Embl]=10;
  471.   fasta_order[CSeq_id::e_Pir]=10;
  472.   fasta_order[CSeq_id::e_Swissprot]=10;
  473.   fasta_order[CSeq_id::e_Patent]=15;
  474.   fasta_order[CSeq_id::e_Other]=12;
  475.   fasta_order[CSeq_id::e_General]=13;
  476.   fasta_order[CSeq_id::e_Gi]=255;
  477.   fasta_order[CSeq_id::e_Ddbj]=10;
  478.   fasta_order[CSeq_id::e_Prf]=10;
  479.   fasta_order[CSeq_id::e_Pdb]=12;
  480.   fasta_order[CSeq_id::e_Tpg]=10;
  481.   fasta_order[CSeq_id::e_Tpe]=10;
  482.   fasta_order[CSeq_id::e_Tpd]=10;
  483.  
  484.   CRef<CSeq_id> idRef;
  485.   const list<CRef<CSeq_id> >& ids=sp.GetBioseqHandle(id).GetBioseqCore()->GetId();
  486.  
  487.   for (CBioseq::TId::const_iterator iter = ids.begin(); iter != ids.end(); iter ++){
  488.     if(iter == ids.begin()){
  489.       idRef = *iter;
  490.     }
  491.     else if(fasta_order[(*iter)->Which()]<fasta_order[idRef->Which()]){
  492.       idRef = *iter;
  493.     }
  494.     
  495.   }
  496.   if(!(ids.empty())){
  497.     idString = idRef->GetSeqIdString(with_version);
  498.   }
  499.   return idString;
  500. }
  501. static CRef<CSeq_id> GetSeqIdByType(const list<CRef<CSeq_id> >& ids, CSeq_id::E_Choice choice) {
  502.   CRef<CSeq_id> cid;
  503.   for (CBioseq::TId::const_iterator iter = ids.begin(); iter != ids.end(); iter ++){
  504.     if ((*iter)->Which() == choice){
  505.       cid = *iter;
  506.       break;
  507.     }
  508.   }
  509.  
  510.   return cid;
  511. }
  512. static int GetGiForSeqIdList (const list<CRef<CSeq_id> >& ids){
  513.   int gi = 0;
  514.   CRef<CSeq_id> id = GetSeqIdByType(ids, CSeq_id::e_Gi);
  515.   if (!(id.Empty())){
  516.     return id->GetGi();
  517.   }
  518.   return gi;
  519. }
  520. //To display the seqalign represented by internal alnvec
  521. void CDisplaySeqalign::DisplayAlnvec(CNcbiOstream& out){ 
  522.   int maxIdLen=0;
  523.   int maxStartLen=0;
  524.   int startLen=0;
  525.   int actualLineLen=0;
  526.   int aln_stop=m_AV->GetAlnStop();
  527.   const int rowNum=m_AV->GetNumRows();
  528.  
  529.   if(m_AlignOption & eMasterAnchored){
  530.     m_AV->SetAnchor(0);
  531.   }
  532.   m_AV->SetGapChar('-');
  533.   m_AV->SetEndChar(' ');
  534.   vector<string> sequence(rowNum);
  535.   CAlnMap::TSeqPosList* seqStarts = new CAlnMap::TSeqPosList[rowNum];
  536.   CAlnMap::TSeqPosList* seqStops = new CAlnMap::TSeqPosList[rowNum];
  537.   CAlnMap::TSeqPosList* insertStart = new CAlnMap::TSeqPosList[rowNum];
  538.   CAlnMap::TSeqPosList* insertAlnStart = new CAlnMap::TSeqPosList[rowNum];
  539.   CAlnMap::TSeqPosList* insertLength = new CAlnMap::TSeqPosList[rowNum];
  540.   string* seqidArray=new string[rowNum];
  541.   string middleLine;
  542.   list<alnFeatureInfo*>* bioseqFeature= new list<alnFeatureInfo*>[rowNum];
  543.   CAlnMap::TSignedRange* rowRng = new CAlnMap::TSignedRange[rowNum];
  544.   int* frame = new int[rowNum];
  545.   //conver to aln coordinates for mask seqloc
  546.   list<alnSeqlocInfo*> alnLocList;
  547.   for (list<SeqlocInfo*>::iterator iter=m_Seqloc.begin();  iter!=m_Seqloc.end(); iter++){
  548.     alnSeqlocInfo* alnloc = new alnSeqlocInfo;    
  549.    
  550.     for (int i=0; i<rowNum; i++){
  551.      
  552.       if((*iter)->seqloc->GetInt().GetId().Match(m_AV->GetSeqId(i))){
  553. int actualAlnStart = 0, actualAlnStop = 0;
  554. if(m_AV->IsPositiveStrand(i)){
  555.   actualAlnStart = m_AV->GetAlnPosFromSeqPos(i, (*iter)->seqloc->GetInt().GetFrom());
  556.   actualAlnStop = m_AV->GetAlnPosFromSeqPos(i, (*iter)->seqloc->GetInt().GetTo());
  557. } else {
  558.   actualAlnStart = m_AV->GetAlnPosFromSeqPos(i, (*iter)->seqloc->GetInt().GetTo());
  559.   actualAlnStop = m_AV->GetAlnPosFromSeqPos(i, (*iter)->seqloc->GetInt().GetFrom());
  560. }
  561.         alnloc->alnRange.Set(actualAlnStart, actualAlnStop);      
  562. break;
  563.       }
  564.     }
  565.     alnloc->seqloc = *iter;   
  566.     alnLocList.push_back(alnloc);
  567.   }
  568.   m_Alnloc = alnLocList;
  569.   //Add external query feature info such as phi blast pattern
  570.   for (list<FeatureInfo*>::iterator iter=m_QueryFeature.begin();  iter!=m_QueryFeature.end(); iter++){
  571.     for(int i = 0; i < rowNum; i++){
  572.       if((*iter)->seqloc->GetInt().GetId().Match(m_AV->GetSeqId(i))){
  573. int actualSeqStart = 0, actualSeqStop = 0;
  574. if(m_AV->IsPositiveStrand(i)){
  575.   if((*iter)->seqloc->GetInt().GetFrom() < m_AV->GetSeqStart(i)){
  576.     actualSeqStart = m_AV->GetSeqStart(i);
  577.   } else {
  578.     actualSeqStart = (*iter)->seqloc->GetInt().GetFrom();
  579.   }
  580.   if((*iter)->seqloc->GetInt().GetTo() > m_AV->GetSeqStop(i)){
  581.     actualSeqStop = m_AV->GetSeqStop(i);
  582.   } else {
  583.     actualSeqStop = (*iter)->seqloc->GetInt().GetTo();
  584.   }
  585. } else {
  586.   if((*iter)->seqloc->GetInt().GetFrom() < m_AV->GetSeqStart(i)){
  587.     actualSeqStart = (*iter)->seqloc->GetInt().GetFrom();
  588.   } else {
  589.     actualSeqStart = m_AV->GetSeqStart(i);
  590.   }
  591.   
  592.   if((*iter)->seqloc->GetInt().GetTo() > m_AV->GetSeqStop(i)){
  593.     actualSeqStop = (*iter)->seqloc->GetInt().GetTo();
  594.   } else {
  595.     actualSeqStop = m_AV->GetSeqStop(i);
  596.   }
  597. }
  598. int alnFrom = m_AV->GetAlnPosFromSeqPos(i, actualSeqStart);
  599. int alnTo = m_AV->GetAlnPosFromSeqPos(i, actualSeqStop);
  600. alnFeatureInfo* featInfo = new alnFeatureInfo;
  601. string tempFeat = NcbiEmptyString;
  602. setFeatureInfo(featInfo, *((*iter)->seqloc), alnFrom, alnTo, aln_stop, (*iter)->featureChar, (*iter)->featureId, tempFeat);    
  603. bioseqFeature[i].push_back(featInfo);
  604.       }
  605.     }
  606.   }
  607.   //prepare data for each row
  608.   for (int row=0; row<rowNum; row++) {
  609.     rowRng[row] = m_AV->GetSeqAlnRange(row);
  610.     frame[row] = (m_AV->GetWidth(row) == 3 ? s_getFrame(m_AV->IsPositiveStrand(row) ? m_AV->GetSeqStart(row) : m_AV->GetSeqStop(row), m_AV->IsPositiveStrand(row) ? eNa_strand_plus : eNa_strand_minus, m_AV->GetSeqId(row), m_Scope) : 0);
  611.  
  612.        
  613.     //make sequence
  614.     m_AV->GetWholeAlnSeqString(row, sequence[row],  &insertAlnStart[row], &insertStart[row], &insertLength[row], m_LineLen, &seqStarts[row], &seqStops[row]);
  615.     
  616.     //make feature.  Only for pairwise, non-query-anchored and untranslated
  617.     if(!(m_AlignOption & eMasterAnchored) && !(m_AlignOption & eMultiAlign) && m_AV->GetWidth(row) != 3){
  618.       if(m_AlignOption & eShowCdsFeature){
  619. getFeatureInfo(bioseqFeature[row], *m_featScope, CSeqFeatData::e_Cdregion, row, sequence[row]);
  620.       }
  621.       if(m_AlignOption & eShowGeneFeature){
  622. getFeatureInfo(bioseqFeature[row], *m_featScope, CSeqFeatData::e_Gene, row, sequence[row]);
  623.       }
  624.     }
  625.  
  626.     //make id
  627.     if(m_AlignOption & eShowBlastStyleId) {
  628.        if(row==0){//query
  629.          seqidArray[row]="Query";
  630.        } else {//hits
  631.          if (!(m_AlignOption&eMultiAlign)){
  632.          //hits for pairwise 
  633.            seqidArray[row]="Sbjct";
  634.          } else {
  635.            int gi = GetGiForSeqIdList(m_AV->GetBioseqHandle(row).GetBioseqCore()->GetId());
  636.            if (m_AlignOption&eShowGi && gi > 0){
  637.              seqidArray[row]=NStr::IntToString(gi);
  638.            } else {
  639.              const CRef<CSeq_id> wid = FindBestChoice(m_AV->GetBioseqHandle(row).GetBioseqCore()->GetId(), CSeq_id::WorstRank);
  640.              seqidArray[row]=wid->GetSeqIdString();
  641.            }           
  642.          }
  643.        }
  644.     } else {
  645.       int gi = GetGiForSeqIdList(m_AV->GetBioseqHandle(row).GetBioseqCore()->GetId());
  646.       if (m_AlignOption&eShowGi && gi > 0){
  647.         seqidArray[row]=NStr::IntToString(gi);
  648.       } else {
  649.        
  650.         const CRef<CSeq_id> wid = FindBestChoice(m_AV->GetBioseqHandle(row).GetBioseqCore()->GetId(), CSeq_id::WorstRank);
  651.         seqidArray[row]=wid->GetSeqIdString();
  652.       }      
  653.     }
  654.     //max id length
  655.     maxIdLen=max<int>(seqidArray[row].size(), maxIdLen);
  656.     //max start length
  657.     int maxCood=max<int>(m_AV->GetSeqStart(row), m_AV->GetSeqStop(row));
  658.     maxStartLen = max<int>(NStr::IntToString(maxCood).size(), maxStartLen);
  659.   }
  660.   //adjust max id length for feature id 
  661.   for(int i = 0; i < rowNum; i ++){
  662.     for (list<alnFeatureInfo*>::iterator iter=bioseqFeature[i].begin();  iter != bioseqFeature[i].end(); iter++){
  663.       maxIdLen=max<int>((*iter)->feature->featureId.size(), maxIdLen );
  664.     }
  665.   }  //end of preparing row data
  666.   
  667.   bool colorMismatch = false; //color the mismatches
  668.   //output identities info 
  669.   if(m_AlignOption&eShowBlastInfo && !(m_AlignOption&eMultiAlign)) {
  670.     int match = 0;
  671.     int positive = 0;
  672.     int gap = 0;
  673.     int identity = 0;
  674.     fillIdentityInfo(sequence[0], sequence[1],  match,  positive, middleLine);
  675.     identity = (match*100)/(aln_stop+1);
  676.     if(identity >= k_ColorMismatchIdentity && identity <100){
  677.       colorMismatch = true;
  678.     }
  679.     out<<" Identities = "<<match<<"/"<<(aln_stop+1)<<" ("<<identity<<"%"<<")";
  680.     if(m_AlignType&eProt) {
  681.       out<<", Positives = "<<(positive + match)<<"/"<<(aln_stop+1)<<" ("<<(((positive + match)*100)/(aln_stop+1))<<"%"<<")";
  682.     }
  683.     gap = getNumGaps();
  684.     out<<", Gaps = "<<gap<<"/"<<(aln_stop+1)<<" ("<<((gap*100)/(aln_stop+1))<<"%"<<")"<<endl;
  685.     if (m_AlignType&eNuc){ 
  686.       out<<" Strand="<<(m_AV->StrandSign(0)==1 ? "Plus" : "Minus")<<"/"<<(m_AV->StrandSign(1)==1? "Plus" : "Minus")<<endl;
  687.     }
  688.     if(frame[0] != 0 && frame[1] != 0) {
  689.       out <<" Frame = " << ((frame[0] > 0) ? "+" : "") << frame[0] <<"/"<<((frame[1] > 0) ? "+" : "") << frame[1]<<endl;
  690.     } else if (frame[0] != 0){
  691.       out <<" Frame = " << ((frame[0] > 0) ? "+" : "") << frame[0] <<endl;
  692.     }  else if (frame[1] != 0){
  693.       out <<" Frame = " << ((frame[1] > 0) ? "+" : "") << frame[1] <<endl;
  694.     } 
  695.     out<<endl;
  696.   }
  697.   //output rows
  698.   for(int j=0; j<=aln_stop; j+=m_LineLen){
  699.     //output according to aln coordinates
  700.     if(aln_stop-j+1<m_LineLen) {
  701.       actualLineLen=aln_stop-j+1;
  702.     } else {
  703.       actualLineLen=m_LineLen;
  704.     }
  705.     CAlnMap::TSignedRange curRange(j, j+actualLineLen-1);
  706.     //here is each row
  707.     for (int row=0; row<rowNum; row++) {
  708.       bool hasSequence = true;
  709.    
  710.       hasSequence = curRange.IntersectingWith(rowRng[row]);
  711.      
  712.       //only output rows that have sequence
  713.       if (hasSequence){
  714. int start = seqStarts[row].front() + 1;  //+1 for 1 based
  715. int end = seqStops[row].front() + 1;
  716. list<string> inserts;
  717. string insertPosString;  //the one with "" to indicate insert
  718. if(m_AlignOption & eMasterAnchored){
  719.   list<insertInformation*> insertList;
  720.   GetInserts(insertList, insertAlnStart[row], insertStart[row], insertLength[row],  j + m_LineLen);
  721.   fillInserts(row, curRange, j, inserts, insertPosString, insertList);
  722.   ITERATE(list<insertInformation*>, iterINsert, insertList){
  723.     delete *iterINsert;
  724.   }
  725. }
  726.         if(row == 0&&(m_AlignOption&eHtml)&&(m_AlignOption&eMultiAlign) && (m_AlignOption&eSequenceRetrieval && m_IsDbGi)){
  727.           char checkboxBuf[200];
  728.           sprintf(checkboxBuf, "<input type="checkbox" name="getSeqMaster" value="" onClick="uncheckable('getSeqAlignment%d', 'getSeqMaster')">", m_QueryNumber);
  729.           out << checkboxBuf;
  730.         }
  731.         string urlLink;
  732.         //setup url link for seqid
  733.         if(row>0&&(m_AlignOption&eHtml)&&(m_AlignOption&eMultiAlign)){
  734.         
  735.           int gi = GetGiForSeqIdList(m_AV->GetBioseqHandle(row).GetBioseqCore()->GetId());
  736.           if(gi > 0){
  737.             out<<"<a name="<<gi<<"></a>";
  738.           } else {
  739.             out<<"<a name="<<seqidArray[row]<<"></a>";
  740.           }
  741.           //get sequence checkbox
  742.           if(m_AlignOption&eSequenceRetrieval && m_IsDbGi){
  743.             char checkBoxBuf[512];
  744.             sprintf(checkBoxBuf, "<input type="checkbox" name="getSeqGi" value="%d" onClick="synchronizeCheck(this.value, 'getSeqAlignment%d', 'getSeqGi', this.checked)">", gi, m_QueryNumber);
  745.             out << checkBoxBuf;        
  746.           }
  747.           urlLink = getUrl(m_AV->GetBioseqHandle(row).GetBioseqCore()->GetId(), row);         
  748.           out << urlLink;
  749.          
  750.         }
  751.         out<<seqidArray[row]; 
  752.         if(row>0&& m_AlignOption&eHtml && m_AlignOption&eMultiAlign && urlLink != NcbiEmptyString){
  753.           out<<"</a>";
  754.          
  755.         }
  756.         //adjust space between id and start
  757.         AddSpace(out, maxIdLen-seqidArray[row].size()+m_IdStartMargin);
  758. out << start;
  759.         startLen=NStr::IntToString(start).size();
  760.         AddSpace(out, maxStartLen-startLen+m_StartSequenceMargin);
  761. if (row>0 && m_AlignOption & eShowIdentity){
  762.   for (int index = j; index < j + actualLineLen && index < (int)sequence[row].size(); index ++){
  763.     if (sequence[row][index] == sequence[0][index] && isalpha(sequence[row][index])) {
  764.       sequence[row][index] = k_IdentityChar;           
  765.     }         
  766.   }
  767. }
  768. OutputSeq(sequence[row], m_AV->GetSeqId(row), j, actualLineLen, frame[row], (row > 0 && colorMismatch)?true:false, out);
  769.         AddSpace(out, m_SeqStopMargin);
  770. out << end;
  771.         
  772.         out<<endl;
  773.      
  774. //display inserts for anchored type
  775. if(m_AlignOption & eMasterAnchored){
  776.   bool insertAlready = false;
  777.   for(list<string>::iterator iter = inserts.begin(); iter != inserts.end(); iter ++){
  778.    
  779.     if(!insertAlready){
  780.       if((m_AlignOption&eHtml)&&(m_AlignOption&eMultiAlign) && (m_AlignOption&eSequenceRetrieval && m_IsDbGi)){
  781. char checkboxBuf[200];
  782. sprintf(checkboxBuf, "<input type="checkbox" name="getSeqMaster" value="" onClick="uncheckable('getSeqAlignment%d', 'getSeqMaster')">", m_QueryNumber);
  783. out << checkboxBuf;
  784.       }
  785.       AddSpace(out, maxIdLen+m_IdStartMargin+maxStartLen+m_StartSequenceMargin);
  786.       out << insertPosString<<endl;
  787.     }
  788.     if((m_AlignOption&eHtml)&&(m_AlignOption&eMultiAlign) && (m_AlignOption&eSequenceRetrieval && m_IsDbGi)){
  789.       char checkboxBuf[200];
  790.       sprintf(checkboxBuf, "<input type="checkbox" name="getSeqMaster" value="" onClick="uncheckable('getSeqAlignment%d', 'getSeqMaster')">", m_QueryNumber);
  791.       out << checkboxBuf;
  792.     }
  793.     AddSpace(out, maxIdLen+m_IdStartMargin+maxStartLen+m_StartSequenceMargin);
  794.     out<<*iter<<endl;
  795.     
  796.     insertAlready = true;
  797.   }
  798. //display feature. Feature, if set, will be displayed for query regardless
  799.         CSeq_id no_id;
  800. for (list<alnFeatureInfo*>::iterator iter=bioseqFeature[row].begin();  iter != bioseqFeature[row].end(); iter++){
  801.   if ( curRange.IntersectingWith((*iter)->alnRange)){  
  802.     if((m_AlignOption&eHtml)&&(m_AlignOption&eMultiAlign) && (m_AlignOption&eSequenceRetrieval && m_IsDbGi)){
  803.       char checkboxBuf[200];
  804.       sprintf(checkboxBuf, "<input type="checkbox" name="getSeqMaster" value="" onClick="uncheckable('getSeqAlignment%d', 'getSeqMaster')">", m_QueryNumber);
  805.       out << checkboxBuf;
  806.     }
  807.     out<<(*iter)->feature->featureId;
  808.     AddSpace(out, maxIdLen+m_IdStartMargin+maxStartLen+m_StartSequenceMargin-(*iter)->feature->featureId.size());
  809.     OutputSeq((*iter)->featureString, no_id, j, actualLineLen, 0, false, out);
  810.     out<<endl;
  811.   }
  812. }
  813. //display middle line
  814. if (row == 0 && ((m_AlignOption & eShowMiddleLine)) && !(m_AlignOption&eMultiAlign)) {
  815.   AddSpace(out, maxIdLen+m_IdStartMargin+maxStartLen+m_StartSequenceMargin);
  816.   OutputSeq(middleLine, no_id, j, actualLineLen, 0, false, out);
  817.   out<<endl;
  818. }
  819.       }
  820.       if(!seqStarts[row].empty()){ //shouldn't need this check
  821. seqStarts[row].pop_front();
  822.       }
  823.       if(!seqStops[row].empty()){
  824. seqStops[row].pop_front();
  825.       }
  826.     }
  827.     out<<endl;
  828.   }//end of displaying rows
  829.  
  830.   //free allocation
  831.   for(int i = 0; i < rowNum; i ++){
  832.     for (list<alnFeatureInfo*>::iterator iter=bioseqFeature[i].begin();  iter != bioseqFeature[i].end(); iter++){
  833.       delete (*iter)->feature;
  834.       delete (*iter);
  835.     }
  836.   } 
  837.   for (list<alnSeqlocInfo*>::const_iterator iter = alnLocList.begin();  iter != alnLocList.end(); iter++){
  838.     delete (*iter);
  839.   }
  840.   delete [] bioseqFeature;
  841.   delete [] seqidArray;
  842.   delete [] rowRng;
  843.   delete [] seqStarts;
  844.   delete [] seqStops;
  845.   delete [] frame;
  846.   delete [] insertStart;
  847.   delete [] insertAlnStart;
  848.   delete [] insertLength;
  849. }
  850. //To display the seqalign
  851. void CDisplaySeqalign::DisplaySeqalign(CNcbiOstream& out){
  852.   
  853.   if(m_SeqalignSetRef->Get().empty()){
  854.     return;
  855.   }
  856.   //scope for feature fetching
  857.   if(!(m_AlignOption & eMasterAnchored) && (m_AlignOption & eShowCdsFeature || m_AlignOption & eShowGeneFeature)){
  858.     m_FeatObj = new CObjectManager();
  859.     m_FeatObj->RegisterDataLoader(*new CGBDataLoader("ID", NULL, 2), CObjectManager::eDefault); 
  860.     m_featScope = new CScope(*m_FeatObj);  //for seq feature fetch
  861.     m_featScope->AddDefaults();      
  862.   }
  863.  
  864.   setDbGi(); //for whether to add get sequence feature
  865.   if(m_AlignOption & eHtml){
  866.     //set config file
  867.     m_ConfigFile = new CNcbiIfstream(".ncbirc");
  868.     m_Reg = new CNcbiRegistry(*m_ConfigFile);
  869.     out<<"<script src="blastResult.js"></script>";
  870.   }
  871.    //get sequence 
  872.   if(m_AlignOption&eSequenceRetrieval && m_AlignOption&eHtml && m_IsDbGi){ 
  873.         out<<GetSeqForm((char*)"submitterTop", m_IsDbNa, m_QueryNumber);
  874.         out<<"<form name="getSeqAlignment"<<m_QueryNumber<<"">n";
  875.       }
  876.   //begin to display
  877.   int num_align = 0;
  878.   string toolUrl = NcbiEmptyString;
  879.   if(m_AlignOption & eHtml){
  880.     toolUrl = m_Reg->Get(m_BlastType, "TOOL_URL");
  881.   }
  882.   auto_ptr<CObjectOStream> out2(CObjectOStream::Open(eSerial_AsnText, out));
  883.   //*out2 << *m_SeqalignSetRef;
  884.   if(!(m_AlignOption&eMultiAlign)){/*pairwise alignment. Note we can't just show each alnment as we go because we will need seg information form all hsp's with the same id for genome url link.  As a result we show hsp's with the same id as a group*/
  885.     list<alnInfo*> avList;        
  886.     CConstRef<CSeq_id> previousId, subid;
  887.     bool isFirstAln = true;
  888.     for (CSeq_align_set::Tdata::const_iterator iter = m_SeqalignSetRef->Get().begin(); iter != m_SeqalignSetRef->Get().end()&&num_align<m_NumAlignToShow; iter++, num_align++) {
  889.       
  890.       //make alnvector
  891.       CRef<CAlnVec> avRef;
  892.       CRef<CSeq_align> finalAln;
  893.       if((*iter)->GetSegs().Which() == CSeq_align::C_Segs::e_Std){
  894. CRef<CSeq_align> densegAln = (*iter)->CreateDensegFromStdseg();
  895. if (m_AlignOption & eTranslateNucToNucAlignment) { 
  896.   finalAln = densegAln->CreateTranslatedDensegFromNADenseg();
  897. } else {
  898.   finalAln = densegAln;
  899. }
  900.       } else if((*iter)->GetSegs().Which() == CSeq_align::C_Segs::e_Denseg){
  901. if (m_AlignOption & eTranslateNucToNucAlignment) { 
  902.   finalAln = (*iter)->CreateTranslatedDensegFromNADenseg();
  903. } else {
  904.   finalAln = (*iter);
  905. }
  906.       } else if((*iter)->GetSegs().Which() == CSeq_align::C_Segs::e_Dendiag){
  907. CRef<CSeq_align> densegAln = CreateDensegFromDendiag(**iter);
  908. if (m_AlignOption & eTranslateNucToNucAlignment) { 
  909.   finalAln = densegAln->CreateTranslatedDensegFromNADenseg();
  910. } else {
  911.   finalAln = densegAln;
  912. }
  913.       } else {
  914. NCBI_THROW(CException, eUnknown, "Seq-align should be Denseg, Stdseg or Dendiag!");
  915.       }
  916.       CRef<CDense_seg> finalDenseg(new CDense_seg);
  917.       const CTypeIterator<CDense_seg> ds = Begin(*finalAln);
  918.       if((ds->IsSetStrands() && ds->GetStrands().front()==eNa_strand_minus) && !(ds->IsSetWidths() && ds->GetWidths()[0] == 3)){
  919. //show plus strand if master is minus for non-translated case
  920. memcpy(&*finalDenseg, &(*ds), sizeof(CDense_seg));
  921. finalDenseg->Reverse();
  922. avRef = new CAlnVec(*finalDenseg, m_Scope);
  923.       } else {
  924. avRef = new CAlnVec(*ds, m_Scope);
  925.       }
  926.     
  927.       if(!(avRef.Empty())){
  928. try{
  929.   const CBioseq_Handle& handle = avRef->GetBioseqHandle(1);
  930.   if(handle){
  931.     subid=&(avRef->GetSeqId(1));
  932.     
  933.     if(!isFirstAln && !subid->Match(*previousId)) {//this aln is a new id, show result for previous id
  934.       x_DisplayAlnvecList(out, avList);
  935.     
  936.       for(list<alnInfo*>::iterator iterAv = avList.begin(); iterAv != avList.end(); iterAv ++){
  937. delete(*iterAv);
  938.       }
  939.       avList.clear();
  940.       
  941.     }
  942.     //save the current alnment regardless
  943.     alnInfo* alnvecInfo = new alnInfo;
  944.     getAlnScores(**iter, alnvecInfo->score, alnvecInfo->bits, alnvecInfo->eValue);
  945.     alnvecInfo->alnVec = avRef;
  946.     avList.push_back(alnvecInfo);
  947.     int gi = GetGiForSeqIdList(handle.GetBioseqCore()->GetId());
  948.     if(!(toolUrl == NcbiEmptyString || (gi > 0 && toolUrl.find("dumpgnl.cgi") != string::npos)) || (m_AlignOption & eLinkout)){ /*need to construct segs for dumpgnl and get sub-sequence for long sequences*/
  949.       string idString = avRef->GetSeqId(1).GetSeqIdString();
  950.       if(m_Segs.count(idString) > 0){  //already has seg, concatenate
  951. /*Note that currently it's not necessary to use map to store this information.  But I already implemented this way for previous version.  Will keep this way as it's more flexible if we change something*/
  952. m_Segs[idString] += "," + NStr::IntToString(avRef->GetSeqStart(1)) + "-" + NStr::IntToString(avRef->GetSeqStop(1));
  953.       } else {//new segs
  954. m_Segs.insert(map<string, string>::value_type(idString, NStr::IntToString(avRef->GetSeqStart(1)) + "-" + NStr::IntToString(avRef->GetSeqStop(1))));
  955.       }
  956.     }     
  957.     isFirstAln = false;
  958.     previousId = subid;
  959.   }
  960.  
  961. } catch (CException& e){
  962. continue;
  963. }
  964.       }
  965.     } 
  966.   
  967.     //Show here for the last one 
  968.     if(!avList.empty()){
  969.       x_DisplayAlnvecList(out, avList);
  970.       for(list<alnInfo*>::iterator iterAv = avList.begin(); iterAv != avList.end(); iterAv ++){
  971. delete(*iterAv);
  972.       }
  973.       avList.clear();
  974.     }
  975.         
  976.   } else if(m_AlignOption&eMultiAlign){ //multiple alignment
  977.        
  978.     CRef<CAlnMix>* mix = new CRef<CAlnMix>[k_NumFrame]; //each for one frame for translated alignment
  979.     for(int i = 0; i < k_NumFrame; i++){
  980.       mix[i] = new CAlnMix(m_Scope);
  981.     }
  982.     num_align = 0;
  983.     vector<CRef<CSeq_align_set> > alnVector(k_NumFrame);
  984.     for(int i = 0; i <  k_NumFrame; i ++){
  985.       alnVector[i] = new CSeq_align_set;
  986.     }
  987.     for (CSeq_align_set::Tdata::const_iterator alnIter = m_SeqalignSetRef->Get().begin(); alnIter != m_SeqalignSetRef->Get().end()&&num_align<m_NumAlignToShow; alnIter ++, num_align++) {
  988.       //need to convert to denseg for stdseg
  989.       if((*alnIter)->GetSegs().Which() == CSeq_align::C_Segs::e_Std) {
  990. CTypeConstIterator<CStd_seg> ss = ConstBegin(**alnIter); 
  991. CRef<CSeq_align> convertedDs = (*alnIter)->CreateDensegFromStdseg();
  992. if((convertedDs->GetSegs().GetDenseg().IsSetWidths() && convertedDs->GetSegs().GetDenseg().GetWidths()[0] == 3) || m_AlignOption & eTranslateNucToNucAlignment){//only do this for translated master
  993.   int frame = s_GetStdsegMasterFrame(*ss, m_Scope);
  994.   switch(frame){
  995.   case 1:
  996.     alnVector[0]->Set().push_back(convertedDs);
  997.     break;
  998.   case 2:
  999.     alnVector[1]->Set().push_back(convertedDs);
  1000.     break;
  1001.   case 3:
  1002.     alnVector[2]->Set().push_back(convertedDs);
  1003.     break;
  1004.   case -1:
  1005.     alnVector[3]->Set().push_back(convertedDs);
  1006.     break;
  1007.   case -2:
  1008.     alnVector[4]->Set().push_back(convertedDs);
  1009.     break;
  1010.   case -3:
  1011.     alnVector[5]->Set().push_back(convertedDs);
  1012.     break;
  1013.   default:
  1014.     break;
  1015.   }
  1016. }
  1017. else {
  1018.   alnVector[0]->Set().push_back(convertedDs);
  1019. }
  1020.       } else if((*alnIter)->GetSegs().Which() == CSeq_align::C_Segs::e_Denseg){
  1021. alnVector[0]->Set().push_back(*alnIter);
  1022.       } else if((*alnIter)->GetSegs().Which() == CSeq_align::C_Segs::e_Dendiag){
  1023. alnVector[0]->Set().push_back(CreateDensegFromDendiag(**alnIter));
  1024.       } else {
  1025. NCBI_THROW(CException, eUnknown, "Input Seq-align should be Denseg, Stdseg or Dendiag!");
  1026.       }
  1027.     }
  1028.     
  1029.     for(int i = 0; i < (int)alnVector.size(); i ++){
  1030.       bool hasAln = false;
  1031.       for(CTypeConstIterator<CSeq_align> alnRef = ConstBegin(*alnVector[i]); alnRef; ++alnRef){
  1032. CTypeConstIterator<CDense_seg> ds = ConstBegin(*alnRef);
  1033.         //*out2 << *ds;      
  1034. try{
  1035.   if (m_AlignOption & eTranslateNucToNucAlignment) {  
  1036.     mix[i]->Add(*ds, CAlnMix::fForceTranslation);
  1037.   } else {
  1038.     mix[i]->Add(*ds);
  1039.   }
  1040. } catch (CException& e){
  1041.   continue;
  1042. }
  1043.  hasAln = true;
  1044.       }
  1045.       if(hasAln){
  1046.         //    *out2<<*alnVector[i];
  1047.   mix[i]->Merge(CAlnMix::fGen2EST| CAlnMix::fMinGap | CAlnMix::fQuerySeqMergeOnly | CAlnMix::fFillUnalignedRegions);  
  1048. // *out2<<mix[i]->GetDenseg();
  1049.       }
  1050.     }
  1051.     
  1052.     int numDistinctFrames = 0;
  1053.     for(int i = 0; i < (int)alnVector.size(); i ++){
  1054.       if(!alnVector[i]->Get().empty()){
  1055. numDistinctFrames ++;
  1056.       }
  1057.     }
  1058.     
  1059.     out<<endl;
  1060.     for(int i = 0; i < k_NumFrame; i ++){
  1061.       try{
  1062. CRef<CAlnVec> avRef (new CAlnVec (mix[i]->GetDenseg(), m_Scope));
  1063. m_AV = avRef;
  1064. if(numDistinctFrames > 1){
  1065.  out << "For reading frame " << k_FrameConversion[i] << " of query sequence:" << endl << endl;
  1066. }
  1067. DisplayAlnvec(out);
  1068.       } catch (CException e){
  1069. continue;
  1070.       }
  1071.     } 
  1072.     delete [] mix;
  1073.   }
  1074.   if(m_AlignOption&eSequenceRetrieval && m_AlignOption&eHtml && m_IsDbGi){
  1075.     out<<"</form>n";
  1076.     out<<GetSeqForm((char*)"submitterBottom", m_IsDbNa, m_QueryNumber);
  1077.   }
  1078. }
  1079. //compute number of identical and positive residues; set middle line accordingly
  1080. const void CDisplaySeqalign::fillIdentityInfo(const string& sequenceStandard, const string& sequence , int& match, int& positive, string& middleLine) {
  1081.   match = 0;
  1082.   positive = 0;
  1083.   int min_length=min<int>(sequenceStandard.size(), sequence.size());
  1084.   if(m_AlignOption & eShowMiddleLine){
  1085.     middleLine = sequence;
  1086.   }
  1087.   for(int i=0; i<min_length; i++){
  1088.     if(sequenceStandard[i]==sequence[i]){
  1089.       if(m_AlignOption & eShowMiddleLine){
  1090. if(m_MidLineStyle == eBar ) {
  1091.   middleLine[i] = '|';
  1092. } else if (m_MidLineStyle == eChar){
  1093.   middleLine[i] = sequence[i];
  1094. }
  1095.       }
  1096.       match ++;
  1097.     } else {
  1098.       if ((m_AlignType&eProt) && m_Matrix[sequenceStandard[i]][sequence[i]] > 0){  
  1099. positive ++;
  1100. if(m_AlignOption & eShowMiddleLine){
  1101.   if (m_MidLineStyle == eChar){
  1102.     middleLine[i] = '+';
  1103.   }
  1104. }
  1105.       } else {
  1106. if (m_AlignOption & eShowMiddleLine){
  1107.   middleLine[i] = ' ';
  1108. }
  1109.       }    
  1110.     }
  1111.   }  
  1112. }
  1113. const void CDisplaySeqalign::PrintDefLine(const CBioseq_Handle& bspHandle, CNcbiOstream& out) const
  1114. {
  1115.   if(bspHandle){
  1116.     const CRef<CSeq_id> wid = FindBestChoice(bspHandle.GetBioseqCore()->GetId(), CSeq_id::WorstRank);
  1117.  
  1118.     const CRef<CBlast_def_line_set> bdlRef = GetBlastDefline(bspHandle);
  1119.     const list< CRef< CBlast_def_line > >& bdl = bdlRef->Get();
  1120.     bool isFirst = true;
  1121.     int firstGi = 0;
  1122.   
  1123.     if(bdl.empty()){ //no blast defline struct, should be no such case now
  1124.       out << ">"; 
  1125.       wid->WriteAsFasta(out);
  1126.       out<<" ";
  1127.       s_WrapOutputLine(out, GetTitle(bspHandle));
  1128.       out << endl;
  1129.     } else {
  1130.       //print each defline 
  1131.       for(list< CRef< CBlast_def_line > >::const_iterator iter = bdl.begin(); iter != bdl.end(); iter++){
  1132. string urlLink;
  1133. if(isFirst){
  1134.   out << ">";
  1135.    
  1136. } else{
  1137.   out << " ";
  1138. }
  1139. const CRef<CSeq_id> wid2 = FindBestChoice((*iter)->GetSeqid(), CSeq_id::WorstRank);
  1140. int gi =  GetGiForSeqIdList((*iter)->GetSeqid());
  1141. if(isFirst){
  1142.   firstGi = gi;
  1143. }
  1144. if ((m_AlignOption&eSequenceRetrieval) && (m_AlignOption&eHtml) && m_IsDbGi && isFirst) {
  1145.   char buf[512];
  1146.   sprintf(buf, "<input type="checkbox" name="getSeqGi" value="%d" onClick="synchronizeCheck(this.value, 'getSeqAlignment%d', 'getSeqGi', this.checked)">", gi, m_QueryNumber);
  1147.   out << buf;
  1148. }
  1149.  
  1150. if(m_AlignOption&eHtml){
  1151.      
  1152.   urlLink = getUrl((*iter)->GetSeqid(), 1);    
  1153.   out<<urlLink;
  1154. }
  1155.     
  1156. if(m_AlignOption&eShowGi && gi > 0){
  1157.   out<<"gi|"<<gi<<"|";
  1158. }       
  1159.    
  1160. wid2->WriteAsFasta(out);
  1161. if(m_AlignOption&eHtml){
  1162.   if(urlLink != NcbiEmptyString){
  1163.     out<<"</a>";
  1164.   }
  1165.   if(gi != 0){
  1166.     out<<"<a name="<<gi<<"></a>";
  1167.   } else {
  1168.     out<<"<a name="<<wid2->GetSeqIdString()<<"></a>";
  1169.   }
  1170.   if(m_AlignOption&eLinkout){
  1171.     out <<" ";
  1172.     AddLinkout(*(bspHandle.GetBioseqCore()), (**iter), firstGi, gi, out);
  1173.     if((int)bspHandle.GetBioseqCore()->GetInst().GetLength() > k_GetSubseqThreshhold){
  1174.       string dumpGnlUrl = getDumpgnlLink((*iter)->GetSeqid(), 1, k_DumpGnlUrl);
  1175.       out<<dumpGnlUrl<<"<img border=0 height=16 width=16 src="/blast/images/D.gif" alt="Download subject sequence spanning the HSP"></a>";
  1176.     }
  1177.   }
  1178. }
  1179.  
  1180. out <<" ";
  1181. if((*iter)->IsSetTitle()){
  1182.   s_WrapOutputLine(out, (*iter)->GetTitle());     
  1183. }
  1184. out<<endl;
  1185. isFirst = false;
  1186.       }
  1187.     }
  1188.   }
  1189. }
  1190. //Output sequence and mask sequences if any
  1191. const void CDisplaySeqalign::OutputSeq(string& sequence, const CSeq_id& id, int start, int len, int frame, bool colorMismatch, CNcbiOstream& out) const {
  1192.   int actualSize = sequence.size();
  1193.   assert(actualSize > start);
  1194.   list<CRange<int> > actualSeqloc;
  1195.   string actualSeq = sequence.substr(start, len);
  1196.   
  1197.   if(id.Which() != CSeq_id::e_not_set){ /*only do this for sequence but not for others like middle line, features*/
  1198.     //go through seqloc containing mask info
  1199.     for (list<alnSeqlocInfo*>::const_iterator iter = m_Alnloc.begin();  iter != m_Alnloc.end(); iter++){
  1200.       int from=(*iter)->alnRange.GetFrom();
  1201.       int to=(*iter)->alnRange.GetTo();
  1202.       int locFrame = (*iter)->seqloc->frame;
  1203.       if(id.Match((*iter)->seqloc->seqloc->GetInt().GetId()) && locFrame == frame){
  1204. bool isFirstChar = true;
  1205. CRange<int> eachSeqloc(0, 0);
  1206. //go through each residule and mask it
  1207. for (int i=max<int>(from, start); i<=min<int>(to, start+len); i++){
  1208.   //store seqloc start for font tag below
  1209.   if ((m_AlignOption & eHtml) && isFirstChar){         
  1210.     isFirstChar = false;
  1211.     eachSeqloc.Set(i, eachSeqloc.GetTo());
  1212.   }
  1213.   if (m_SeqLocChar==eX){
  1214.     actualSeq[i-start]='X';
  1215.   } else if (m_SeqLocChar==eN){
  1216.     actualSeq[i-start]='n';
  1217.   } else if (m_SeqLocChar==eLowerCase){
  1218.     actualSeq[i-start]=tolower(actualSeq[i-start]);
  1219.   }
  1220.   //store seqloc start for font tag below
  1221.   if ((m_AlignOption & eHtml) && i == min<int>(to, start+len)){ 
  1222.     eachSeqloc.Set(eachSeqloc.GetFrom(), i);
  1223.   }
  1224. }
  1225. if(!(eachSeqloc.GetFrom()==0&&eachSeqloc.GetTo()==0)){
  1226.   actualSeqloc.push_back(eachSeqloc);
  1227. }
  1228.       }
  1229.     }
  1230.   }
  1231.   if(actualSeqloc.empty()){//no need to add font tag
  1232.     if((m_AlignOption & eColorDifferentBases) && (m_AlignOption & eHtml) && colorMismatch){
  1233.       //color the mismatches. Only for rows without mask.  Otherwise it may confilicts with mask font tag.
  1234.       x_ColorDifferentBases(actualSeq, k_IdentityChar, out);
  1235.     } else {
  1236.       out<<actualSeq;
  1237.     }
  1238.   } else {//now deal with font tag for mask for html display    
  1239.     bool endTag = false;
  1240.     bool numFrontTag = 0;
  1241.     for (int i = 0; i < (int)actualSeq.size(); i ++){
  1242.       for (list<CRange<int> >::iterator iter=actualSeqloc.begin();  iter!=actualSeqloc.end(); iter++){
  1243.         int from = (*iter).GetFrom() - start;
  1244.         int to = (*iter).GetTo() - start;
  1245. //start tag
  1246.         if(from == i){
  1247.           out<<"<font color=""+color[m_SeqLocColor]+"">";
  1248.           numFrontTag = 1;
  1249.         }
  1250. //need to close tag at the end of mask or end of sequence
  1251.         if(to == i || i == (int)actualSeq.size() - 1 ){
  1252.           endTag = true;
  1253.         }
  1254.       }
  1255.       out<<actualSeq[i];
  1256.       if(endTag && numFrontTag == 1){
  1257.         out<<"</font>";
  1258.         endTag = false;
  1259.         numFrontTag = 0;
  1260.       }
  1261.     }
  1262.   }
  1263. }
  1264. int CDisplaySeqalign::getNumGaps() {
  1265.   int gap = 0;
  1266.   for (int row=0; row<m_AV->GetNumRows(); row++) {
  1267.     CRef<CAlnMap::CAlnChunkVec> chunk_vec = m_AV->GetAlnChunks(row, m_AV->GetSeqAlnRange(0));
  1268.     for (int i=0; i<chunk_vec->size(); i++) {
  1269.       CConstRef<CAlnMap::CAlnChunk> chunk = (*chunk_vec)[i];
  1270.       if (chunk->IsGap()) {
  1271.         gap += (chunk->GetAlnRange().GetTo() - chunk->GetAlnRange().GetFrom() + 1);
  1272.       }
  1273.     }
  1274.   }
  1275.   return gap;
  1276. }
  1277. const CRef<CBlast_def_line_set>  CDisplaySeqalign::GetBlastDefline (const CBioseq_Handle& handle) const {
  1278.   CRef<CBlast_def_line_set> bdls(new CBlast_def_line_set());
  1279.   if(handle.IsSetDescr()){
  1280.     const CSeq_descr& desc = handle.GetDescr();
  1281.     const list< CRef< CSeqdesc > >& descList = desc.Get();
  1282.     for (list<CRef< CSeqdesc > >::const_iterator iter = descList.begin(); iter != descList.end(); iter++){
  1283.       
  1284.       if((*iter)->IsUser()){
  1285.         const CUser_object& uobj = (*iter)->GetUser();
  1286.         const CObject_id& uobjid = uobj.GetType();
  1287.         if(uobjid.IsStr()){
  1288.    
  1289.           const string& label = uobjid.GetStr();
  1290.           if (label == kAsnDeflineObjLabel){
  1291.            const vector< CRef< CUser_field > >& usf = uobj.GetData();
  1292.            string buf;
  1293.           
  1294.    if(usf.front()->GetData().IsOss()){ //only one user field
  1295.              typedef const CUser_field::TData::TOss TOss;
  1296.              const TOss& oss = usf.front()->GetData().GetOss();
  1297.              int size = 0;
  1298.              //determine the octet string length
  1299.              ITERATE (TOss, iter3, oss) {
  1300.        size += (**iter3).size();
  1301.              }
  1302.              
  1303.              int i =0;
  1304.              char* temp = new char[size];
  1305.              //retrive the string
  1306.              ITERATE (TOss, iter3, oss) {
  1307.       
  1308.                for(vector< char >::iterator iter4 = (**iter3).begin(); iter4 !=(**iter3).end(); iter4++){
  1309.                  temp[i] = *iter4;
  1310.                  i++;
  1311.                }
  1312.              }            
  1313.     
  1314.      CConn_MemoryStream stream;
  1315.              stream.write(temp, i);
  1316.              auto_ptr<CObjectIStream> ois(CObjectIStream::Open(eSerial_AsnBinary, stream));
  1317.              *ois >> *bdls;
  1318.      delete [] temp;
  1319.            }         
  1320.           }
  1321.         }
  1322.       }
  1323.     }
  1324.   }
  1325.   return bdls;
  1326. }
  1327. static string GetTaxNames(const CBioseq& cbsp, int taxid){
  1328.   string name;
  1329.   if(cbsp.IsSetDescr()){  
  1330.     const CSeq_descr& desc = cbsp.GetDescr();
  1331.     const list< CRef< CSeqdesc > >& descList = desc.Get();   
  1332.     for (list<CRef< CSeqdesc > >::const_iterator iter = descList.begin(); iter != descList.end(); iter++){
  1333.       if((*iter)->IsUser()){
  1334.         const CUser_object& uobj = (*iter)->GetUser();
  1335.         const CObject_id& uobjid = uobj.GetType();
  1336.         if(uobjid.IsStr()){   
  1337.           const string& label = uobjid.GetStr();
  1338.           if (label == kTaxDataObjLabel){
  1339.             const vector< CRef< CUser_field > >& usf = uobj.GetData();        
  1340.             for (vector< CRef< CUser_field > >::const_iterator iter2 = usf.begin(); iter2 != usf.end(); iter2 ++){
  1341.               const CObject_id& oid = (*iter2)->GetLabel();
  1342.               if (oid.GetId() == taxid){
  1343.                 (**iter2).GetData().Which();
  1344.                 name = (**iter2).GetData().GetStrs().front();
  1345.                 break;
  1346.               }
  1347.             }
  1348.           }
  1349.         }
  1350.       }
  1351.     }
  1352.   }
  1353.   return name;
  1354. }
  1355. void CDisplaySeqalign::getFeatureInfo(list<alnFeatureInfo*>& feature, CScope& scope, CSeqFeatData::E_Choice choice, int row, string& sequence) const {
  1356.   //Only fetch features for seq that has a gi
  1357.   CRef<CSeq_id> id = GetSeqIdByType(m_AV->GetBioseqHandle(row).GetBioseqCore()->GetId(), CSeq_id::e_Gi);
  1358.   if(!(id.Empty())){
  1359.     const CBioseq_Handle& handle = scope.GetBioseqHandle(*id);
  1360.     //cds feature
  1361.     for  (CFeat_CI feat (handle, m_AV->GetSeqStart(row), m_AV->GetSeqStop(row), choice); feat;  ++feat) {
  1362.       
  1363.       const CSeq_loc& loc = feat->GetLocation();
  1364.       string featLable = NcbiEmptyString;
  1365.       string featId;
  1366.       string alternativeFeatStr = NcbiEmptyString;
  1367.       feature::GetLabel(feat->GetOriginalFeature(), &featLable, feature::eBoth, &(m_AV->GetScope()));
  1368.       featId = featLable.substr(0, k_FeatureIdLen); //default
  1369.   
  1370.       int alnStop = m_AV->GetAlnStop();      
  1371.       if(loc.IsInt()){
  1372. alnFeatureInfo* featInfo = new alnFeatureInfo;
  1373. int featSeqFrom = loc.GetInt().GetFrom();
  1374. int featSeqTo = loc.GetInt().GetTo();
  1375. int actualFeatSeqStart = 0, actualFeatSeqStop = 0;
  1376. if(m_AV->IsPositiveStrand(row)){
  1377.   if(featSeqFrom < (int)m_AV->GetSeqStart(row)){
  1378.     actualFeatSeqStart = m_AV->GetSeqStart(row);
  1379.   } else {
  1380.     actualFeatSeqStart = featSeqFrom;
  1381.   }
  1382.   if(featSeqTo > (int)m_AV->GetSeqStop(row)){
  1383.     actualFeatSeqStop = m_AV->GetSeqStop(row);
  1384.   } else {
  1385.     actualFeatSeqStop = featSeqTo;
  1386.   }
  1387. } else {
  1388.   if(featSeqFrom < (int)m_AV->GetSeqStart(row)){
  1389.     actualFeatSeqStart = featSeqFrom;
  1390.   } else {
  1391.     actualFeatSeqStart = m_AV->GetSeqStart(row); 
  1392.   }
  1393.   if(featSeqTo > (int)m_AV->GetSeqStop(row)){
  1394.     actualFeatSeqStop = featSeqTo;
  1395.   } else {
  1396.     actualFeatSeqStop = m_AV->GetSeqStop(row);
  1397.   }
  1398. }
  1399. int alnFrom = m_AV->GetAlnPosFromSeqPos(row, actualFeatSeqStart);
  1400. int alnTo = m_AV->GetAlnPosFromSeqPos(row, actualFeatSeqStop);
  1401. char featChar = ' ';
  1402. if(choice == CSeqFeatData::e_Gene){
  1403.   featChar = '^';
  1404. } else if (choice == CSeqFeatData::e_Cdregion){
  1405.   featChar = '~';
  1406. }
  1407. //need to construct the protein seq aligned to nucleotide seq 
  1408. if (choice == CSeqFeatData::e_Cdregion){
  1409.   string rawCdrProduct = NcbiEmptyString;
  1410.   if(feat->IsSetProduct()){
  1411.     const CSeq_loc& productLoc = feat->GetProduct(); 
  1412.     //only show first k_FeatureIdLen letters
  1413.     if(productLoc.IsWhole()){
  1414.       const CSeq_id& productId = productLoc.GetWhole();
  1415.       const CBioseq_Handle& productHandle = scope.GetBioseqHandle(productId );
  1416.       featId = "CDS:" + GetTitle(productHandle).substr(0, k_FeatureIdLen);
  1417.     }
  1418.   }
  1419.   //show protein product only if the row is plus strand
  1420.   if(m_AV->IsPositiveStrand(row)){
  1421.     string line(alnStop+1, ' ');  
  1422.     CCdregion_translate::TranslateCdregion (rawCdrProduct, handle, loc, feat->GetData().GetCdregion(), true, false);
  1423.     
  1424.     bool firstBase = true;
  1425.     char gapChar = m_AV->GetGapChar(row);
  1426.     int marginAdjuster = 0;
  1427.     int featStartSeqPos = 0;
  1428.     int firstFeatStringPos = 0;
  1429.     int numBase = 0;
  1430.     
  1431.     //put actual amino acid to the cdr product line in aln coord
  1432.     for (int i = alnFrom; i < alnTo; i++){
  1433.       if(sequence[i] != gapChar){
  1434. numBase ++;
  1435. if(firstBase){
  1436.   firstBase = false;
  1437.   featStartSeqPos = m_AV->GetSeqPosFromAlnPos(row, i);
  1438.   const CCdregion& cdr = feat->GetData().GetCdregion();
  1439.   int frame = 1;
  1440.   if(cdr.IsSetFrame()){
  1441.     frame = cdr.GetFrame();
  1442.   }
  1443.   int numBaseFromFeatStart = (featStartSeqPos - (featSeqFrom + (frame -1) )); //Number of bases between feature start and current base. adjust using frame
  1444.   if(numBaseFromFeatStart % 3 == 0){ //this base is the 1st base
  1445.     marginAdjuster = 0; //aa aligned to 2nd base of a condon
  1446.     firstFeatStringPos = numBaseFromFeatStart / 3;  
  1447.   } else if (numBaseFromFeatStart % 3 == 1) {
  1448.     marginAdjuster = 1;
  1449.     firstFeatStringPos = numBaseFromFeatStart / 3;
  1450.   } else {
  1451.     marginAdjuster = -1;
  1452.     firstFeatStringPos = (numBaseFromFeatStart / 3) + 1;
  1453.   }
  1454. }
  1455. if((numBase + marginAdjuster) % 3 == 2){
  1456.   int stringPos = firstFeatStringPos + (numBase + marginAdjuster) / 3;
  1457.   if(stringPos < (int)rawCdrProduct.size()){//should not need this check
  1458.     line[i] = rawCdrProduct[stringPos];
  1459.   }
  1460. }
  1461.       }
  1462.     }
  1463.     alternativeFeatStr = line;
  1464.   }
  1465. setFeatureInfo(featInfo, loc, alnFrom, alnTo, alnStop, featChar, featId, alternativeFeatStr);     
  1466. feature.push_back(featInfo);
  1467.       
  1468.       }
  1469.     }
  1470.   }
  1471. }
  1472. void  CDisplaySeqalign::setFeatureInfo(alnFeatureInfo* featInfo, const CSeq_loc& seqloc, int alnFrom, int alnTo, int alnStop, char patternChar, string patternId, string& alternativeFeatStr) const{
  1473.   FeatureInfo* feat = new FeatureInfo;
  1474.   feat->seqloc = &seqloc;
  1475.   feat->featureChar = patternChar;
  1476.   feat->featureId = patternId;
  1477.     
  1478.   if(alternativeFeatStr != NcbiEmptyString){
  1479.     featInfo->featureString = alternativeFeatStr;
  1480.   } else {
  1481.     //fill feature string
  1482.     string line(alnStop+1, ' ');
  1483.     for (int j = alnFrom; j <= alnTo; j++){
  1484.       line[j] = feat->featureChar;
  1485.     }
  1486.     featInfo->featureString = line;
  1487.   }
  1488.  
  1489.   featInfo->alnRange.Set(alnFrom, alnTo); 
  1490.   featInfo->feature = feat;
  1491. }
  1492. //May need to add a "|" to the current insert for insert on next rows
  1493. static int addBar(string& seq, int insertAlnPos, int alnStart){
  1494.   int end = seq.size() -1 ;
  1495.   int barPos = insertAlnPos - alnStart + 1;
  1496.   string addOn;
  1497.   if(barPos - end > 1){
  1498.     string spacer(barPos - end - 1, ' ');
  1499.     addOn += spacer + "|";
  1500.   } else if (barPos - end == 1){
  1501.     addOn += "|";
  1502.   }
  1503.   seq += addOn;
  1504.   return max<int>((barPos - end), 0);
  1505. }
  1506. //Add new insert seq to the current insert seq and return the end position of the latest insert
  1507. static int adjustInsert(string& curInsert, string& newInsert, int insertAlnPos, int alnStart){
  1508.   int insertEnd = 0;
  1509.   int curInsertSize = curInsert.size();
  1510.   int insertLeftSpace = insertAlnPos - alnStart - curInsertSize + 2;  //plus2 because insert is put after the position
  1511.   if(curInsertSize > 0){
  1512.     assert(insertLeftSpace >= 2);
  1513.   }
  1514.   int newInsertSize = newInsert.size();  
  1515.   if(insertLeftSpace - newInsertSize >= 1){ //can insert with the end position right below the bar
  1516.     string spacer(insertLeftSpace - newInsertSize, ' ');
  1517.     curInsert += spacer + newInsert;
  1518.     
  1519.   } else { //Need to insert beyond the insert postion
  1520.     if(curInsertSize > 0){
  1521.       curInsert += " " + newInsert;
  1522.     } else {  //can insert right at the firt position
  1523.       curInsert += newInsert;
  1524.     }
  1525.   }
  1526.   insertEnd = alnStart + curInsert.size() -1 ; //-1 back to string position
  1527.   return insertEnd;
  1528. }
  1529. //recusively fill the insert
  1530. void CDisplaySeqalign::doFills(int row, CAlnMap::TSignedRange& alnRange, int  alnStart, list<insertInformation*>& insertList, list<string>& inserts) const {
  1531.   if(!insertList.empty()){
  1532.     string bar(alnRange.GetLength(), ' ');
  1533.     
  1534.     string seq;
  1535.     list<insertInformation*> leftOverInsertList;
  1536.     bool isFirstInsert = true;
  1537.     int curInsertAlnStart = 0;
  1538.     int prvsInsertAlnEnd = 0;
  1539.     
  1540.     //go through each insert and fills the seq if it can  be filled on the same line.  If not, go to the next line
  1541.     for(list<insertInformation*>::iterator iter = insertList.begin(); iter != insertList.end(); iter ++){
  1542.       curInsertAlnStart = (*iter)->alnStart;
  1543.       //always fill the first insert.  Also fill if there is enough space
  1544.       if(isFirstInsert || curInsertAlnStart - prvsInsertAlnEnd >= 1){
  1545. bar[curInsertAlnStart-alnStart+1] = '|';  
  1546. int seqStart = (*iter)->seqStart;
  1547. int seqEnd = seqStart + (*iter)->insertLen - 1;
  1548. string newInsert;
  1549. newInsert = m_AV->GetSeqString(newInsert, row, seqStart, seqEnd);
  1550. prvsInsertAlnEnd = adjustInsert(seq, newInsert, curInsertAlnStart, alnStart);
  1551. isFirstInsert = false;
  1552.       } else { //if no space, save the chunk and go to next line 
  1553. bar[curInsertAlnStart-alnStart+1] = '|';  //indicate insert goes to the next line
  1554. prvsInsertAlnEnd += addBar(seq, curInsertAlnStart, alnStart);   //May need to add a bar after the current insert sequence to indicate insert goes to the next line.
  1555. leftOverInsertList.push_back(*iter);    
  1556.       }
  1557.     }
  1558.     //save current insert.  Note that each insert has a bar and sequence below it
  1559.     inserts.push_back(bar);
  1560.     inserts.push_back(seq);
  1561.     //here recursively fill the chunk that don't have enough space
  1562.     doFills(row, alnRange, alnStart, leftOverInsertList, inserts);
  1563.   }
  1564.  
  1565. }
  1566. /*fill a list of inserts for a particular row*/
  1567. void CDisplaySeqalign::fillInserts(int row, CAlnMap::TSignedRange& alnRange, int alnStart, list<string>& inserts, string& insertPosString, list<insertInformation*>& insertList) const{
  1568.   string line(alnRange.GetLength(), ' ');
  1569.  
  1570.   ITERATE(list<insertInformation*>, iter, insertList){
  1571.     int from = (*iter)->alnStart;
  1572.     line[from - alnStart + 1] = '\';
  1573.   }
  1574.   insertPosString = line; //this is the line with "" right after each insert position
  1575.     
  1576.   //here fills the insert sequence
  1577.   doFills(row, alnRange, alnStart, insertList, inserts);
  1578. }
  1579. void CDisplaySeqalign::GetInserts(list<insertInformation*>& insertList, CAlnMap::TSeqPosList& insertAlnStart, CAlnMap::TSeqPosList& insertSeqStart, CAlnMap::TSeqPosList& insertLength, int lineAlnStop){
  1580.   while(!insertAlnStart.empty() && (int)insertAlnStart.front() < lineAlnStop){
  1581.     CDisplaySeqalign::insertInformation* insert = new CDisplaySeqalign::insertInformation;
  1582.     insert->alnStart = insertAlnStart.front() - 1; //Need to minus one as we are inserting after this position
  1583.     insert->seqStart = insertSeqStart.front();
  1584.     insert->insertLen = insertLength.front();
  1585.     insertList.push_back(insert);
  1586.     insertAlnStart.pop_front();
  1587.     insertSeqStart.pop_front();
  1588.     insertLength.pop_front();
  1589.   }
  1590.  
  1591. }
  1592. //segments starts and stops used for map viewer 
  1593. string CDisplaySeqalign::getSegs(int row) const {
  1594.   string segs = NcbiEmptyString;
  1595.   if(m_AlignOption & eMultiAlign){ //only show this hsp
  1596.     segs = NStr::IntToString(m_AV->GetSeqStart(row)) + "-" + NStr::IntToString(m_AV->GetSeqStop(row));
  1597.   } else { //for all segs
  1598.     string idString = m_AV->GetSeqId(1).GetSeqIdString();
  1599.     map<string, string>::const_iterator iter = m_Segs.find(idString);
  1600.     if ( iter != m_Segs.end() ){
  1601.       segs = iter->second;
  1602.     }
  1603.   }
  1604.   return segs;
  1605. }
  1606. /* transforms a string so that it becomes safe to be used as part of URL
  1607.  * the function converts characters with special meaning (such as
  1608.  * semicolon -- protocol separator) to escaped hexadecimal (%xx)
  1609.  */
  1610. static string MakeURLSafe(char* src){
  1611.   static char HEXDIGS[] = "0123456789ABCDEF";
  1612.   char* buf;
  1613.   size_t len;
  1614.   char* p;
  1615.   char c;
  1616.   string url = NcbiEmptyString;
  1617.   if (src){
  1618.     /* first pass to calculate required buffer size */
  1619.     for (p = src, len = 0; (c = *(p++)) != ''; ) {
  1620.       switch (c) {
  1621.       default:
  1622. if (c < '0' || (c > '9' && c < 'A') ||
  1623.     (c > 'Z' && c < 'a') || c > 'z') {
  1624.   len += 3;
  1625.   break;
  1626. }
  1627.       case '-': case '_': case '.': case '!': case '~':
  1628.       case '*': case ''': case '(': case ')':
  1629. ++len;
  1630.       }
  1631.     }
  1632.     buf = new char[len + 1];
  1633.     /* second pass -- conversion */
  1634.     for (p = buf; (c = *(src++)) != ''; ) {
  1635.       switch (c) {
  1636.       default:
  1637. if (c < '0' || (c > '9' && c < 'A') ||
  1638.     (c > 'Z' && c < 'a') || c > 'z') {
  1639.   *(p++) = '%';
  1640.   *(p++) = HEXDIGS[(c >> 4) & 0xf];
  1641.   *(p++) = HEXDIGS[c & 0xf];
  1642.   break;
  1643. }
  1644.       case '-': case '_': case '.': case '!': case '~':
  1645.       case '*': case ''': case '(': case ')':
  1646. *(p++) = c;
  1647.       }
  1648.     }
  1649.     *p = '';
  1650.     url = buf;
  1651.     delete [] buf;
  1652.   }
  1653.   return url;
  1654. }
  1655. //make url for dumpgnl.cgi
  1656. string CDisplaySeqalign::getDumpgnlLink(const list<CRef<CSeq_id> >& ids, int row, const string& alternativeUrl)const {
  1657.   string link = NcbiEmptyString;  
  1658.   string toolUrl= m_Reg->Get(m_BlastType, "TOOL_URL");
  1659.   string passwd = m_Reg->Get(m_BlastType, "PASSWD");
  1660.   bool nodb_path =  false;
  1661.   CRef<CSeq_id> idGeneral = GetSeqIdByType(ids, CSeq_id::e_General);
  1662.   CRef<CSeq_id> idOther = GetSeqIdByType(ids, CSeq_id::e_Other);
  1663.   const CRef<CSeq_id> idAccession = FindBestChoice(ids, CSeq_id::WorstRank);
  1664.   string segs = getSegs(row);
  1665.   int gi = GetGiForSeqIdList(ids);
  1666.   if(!idGeneral.Empty() && idGeneral->AsFastaString().find("gnl|BL_ORD_ID")){ /* We do need to make security protected link to BLAST gnl */
  1667.     return NcbiEmptyString;
  1668. }
  1669.   if(alternativeUrl != NcbiEmptyString){ 
  1670.     toolUrl = alternativeUrl;
  1671.   }
  1672.   /* dumpgnl.cgi need to use path  */
  1673.   if (toolUrl.find("dumpgnl.cgi") ==string::npos){
  1674.     nodb_path = true;
  1675.   }  
  1676.   int length = m_DbName.size();
  1677.   string str;
  1678.   char  *chptr, *dbtmp;
  1679.   Char tmpbuff[256];
  1680.   char* dbname = new char[sizeof(char)*length + 2];
  1681.   strcpy(dbname, m_DbName.c_str());
  1682.   if(nodb_path) {
  1683.     int i, j;
  1684.     dbtmp = new char[sizeof(char)*length + 2]; /* aditional space and NULL */
  1685.     memset(dbtmp, '', sizeof(char)*length + 2);
  1686.     for(i = 0; i < length; i++) {            
  1687.        if(isspace(dbname[i]) || dbname[i] == ',') {/* Rolling spaces */
  1688.  continue;
  1689.        }
  1690.        j = 0;
  1691.        while (!isspace(dbname[i]) && j < 256  && i < length) { 
  1692.  tmpbuff[j] = dbname[i];
  1693.  j++; i++;
  1694.  if(dbname[i] == ',') { /* Comma is valid delimiter */
  1695.    break;
  1696.  }
  1697.        }
  1698.        tmpbuff[j] = '';
  1699.        if((chptr = strrchr(tmpbuff, '/')) != NULL) { 
  1700.  strcat(dbtmp, (char*)(chptr+1));
  1701.        } else {
  1702.  strcat(dbtmp, tmpbuff);
  1703.        }
  1704.        strcat(dbtmp, " ");            
  1705.      }
  1706.    } else {
  1707.      dbtmp = dbname;
  1708.    }
  1709.   
  1710.   const CSeq_id* bestid = NULL;
  1711.   if (idGeneral.Empty()){
  1712.     bestid = idOther;
  1713.     if (idOther.Empty()){
  1714.       bestid = idAccession;
  1715.     }
  1716.   }
  1717.   /*
  1718.    * Need to protect start and stop positions
  1719.    * to avoid web users sending us hand-made URLs
  1720.    * to retrive full sequences
  1721.    */
  1722.   char gnl[256];
  1723.   unsigned char buf[32];
  1724.   CMD5 urlHash;
  1725.   if (bestid && bestid->Which() !=  CSeq_id::e_Gi){
  1726.     length = passwd.size();
  1727.     urlHash.Update(passwd.c_str(), length);
  1728.     strcpy(gnl, bestid->AsFastaString().c_str());
  1729.     urlHash.Update(gnl, strlen(gnl));
  1730.     urlHash.Update(segs.c_str(), segs.size());
  1731.     urlHash.Update(passwd.c_str(), length);
  1732.     urlHash.Finalize(buf);
  1733.     
  1734.   } else {
  1735.     gnl[0] = '';
  1736.   }
  1737.   
  1738.   str = MakeURLSafe(dbtmp == NULL ? (char*) "nr" : dbtmp);
  1739.   link += "<a href="";
  1740.   if (toolUrl.find("?") == string::npos){
  1741.     link += toolUrl + "?" + "db=" + str + "&na=" + (m_IsDbNa? "1" : "0") + "&";
  1742.   } else {
  1743.     link += toolUrl + "&db=" + str + "&na=" + (m_IsDbNa? "1" : "0") + "&";
  1744.   }
  1745.   
  1746.   if (gnl[0] != ''){
  1747.     str = MakeURLSafe(gnl);
  1748.     link += "gnl=";
  1749.     link += str;
  1750.     link += "&";
  1751.   }
  1752.   if (gi > 0){
  1753.     link += "gi=" + NStr::IntToString(gi) + "&";
  1754.   }
  1755.   if (m_Rid != NcbiEmptyString){
  1756.     link += "RID=" + m_Rid +"&";
  1757.   }
  1758.   
  1759.   if ( m_QueryNumber > 0){
  1760.     link += "QUERY_NUMBER=" + NStr::IntToString(m_QueryNumber) + "&";
  1761.   }
  1762.   link += "segs=" + segs + "&";
  1763.   
  1764.   char tempBuf[128];
  1765.   
  1766.   sprintf(tempBuf,
  1767.   "seal=%02X%02X%02X%02X"
  1768.   "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
  1769.   buf[0], buf[1], buf[2], buf[3],
  1770.   buf[4], buf[5], buf[6], buf[7],
  1771.   buf[8], buf[9], buf[10], buf[11],
  1772.   buf[12], buf[13], buf[14], buf[15]);
  1773.   
  1774.   link += tempBuf;
  1775.   link += "">";
  1776.   if(nodb_path){
  1777.     delete [] dbtmp;
  1778.   }
  1779.   delete [] dbname;
  1780.   return link;
  1781. }
  1782. void CDisplaySeqalign::setDbGi() {
  1783.   //determine if the database has gi by looking at the 1st hit.  Could be wrong but simple for now
  1784.  
  1785.   CTypeConstIterator<CSeq_align> saTemp = ConstBegin(*m_SeqalignSetRef);
  1786.   if(saTemp->IsSetSegs()){ 
  1787.     if(saTemp->GetSegs().Which() == CSeq_align::C_Segs::e_Denseg){
  1788.       CTypeConstIterator<CDense_seg> dsTemp = ConstBegin(*saTemp); 
  1789.       const vector< CRef< CSeq_id > >& idTemp = (dsTemp->GetIds());
  1790.       vector< CRef< CSeq_id > >::const_iterator iterTemp = idTemp.begin();
  1791.       iterTemp++;
  1792.       const CBioseq_Handle& handleTemp = m_Scope.GetBioseqHandle(**iterTemp);
  1793.       if(handleTemp){
  1794. int giTemp = GetGiForSeqIdList(handleTemp.GetBioseqCore()->GetId());
  1795. if(giTemp >0 ) { 
  1796.   m_IsDbGi = true;
  1797. }
  1798.       }
  1799.     } else if (saTemp->GetSegs().Which() == CSeq_align::C_Segs::e_Std){
  1800.       CTypeConstIterator<CStd_seg> dsTemp = ConstBegin(*saTemp); 
  1801.       const CStd_seg::TIds& idTemp = (dsTemp->GetIds());
  1802.       CStd_seg::TIds::const_iterator iterTemp = idTemp.begin();
  1803.       iterTemp++;
  1804.       const CBioseq_Handle& handleTemp = m_Scope.GetBioseqHandle(**iterTemp);
  1805.       if(handleTemp){
  1806. int giTemp = GetGiForSeqIdList(handleTemp.GetBioseqCore()->GetId());
  1807. if(giTemp >0 ) { 
  1808.   m_IsDbGi = true;
  1809. }
  1810.       }
  1811.     }
  1812.   }
  1813. }
  1814. //Need to call this if the seqalign is stdseg or dendiag for ungapped blast alignment display as each stdseg ro dendiag is a distinct alignment.  Don't call it for other case as it's a waste of time.
  1815. CRef<CSeq_align_set>CDisplaySeqalign::PrepareBlastUngappedSeqalign(CSeq_align_set& alnset) {
  1816.   CRef<CSeq_align_set> alnSetRef(new CSeq_align_set);
  1817.   ITERATE(CSeq_align_set::Tdata, iter, alnset.Get()){
  1818.     const CSeq_align::TSegs& seg = (*iter)->GetSegs();
  1819.     if(seg.Which() == CSeq_align::C_Segs::e_Std){
  1820.       if(seg.GetStd().size() > 1){ //has more than one stdseg. Need to seperate as each is a distinct HSP
  1821. ITERATE (CSeq_align::C_Segs::TStd, iterStdseg, seg.GetStd()){
  1822.   CRef<CSeq_align> aln(new CSeq_align);
  1823.   if((*iterStdseg)->IsSetScores()){
  1824.     aln->SetScore() = (*iterStdseg)->GetScores();
  1825.   }
  1826.   aln->SetSegs().SetStd().push_back(*iterStdseg);
  1827.   alnSetRef->Set().push_back(aln);
  1828. }
  1829.       } else {
  1830. alnSetRef->Set().push_back(*iter);
  1831.       }
  1832.     } else if(seg.Which() == CSeq_align::C_Segs::e_Dendiag){
  1833.       if(seg.GetDendiag().size() > 1){ //has more than one dendiag. Need to seperate as each is a distinct HSP
  1834. ITERATE (CSeq_align::C_Segs::TDendiag, iterDendiag, seg.GetDendiag()){
  1835.   CRef<CSeq_align> aln(new CSeq_align);
  1836.   if((*iterDendiag)->IsSetScores()){
  1837.     aln->SetScore() = (*iterDendiag)->GetScores();
  1838.   }
  1839.   aln->SetSegs().SetDendiag().push_back(*iterDendiag);
  1840.   alnSetRef->Set().push_back(aln);
  1841. }
  1842.       } else {
  1843. alnSetRef->Set().push_back(*iter);
  1844.       }
  1845.     } else { //Denseg, doing nothing.
  1846.       alnSetRef->Set().push_back(*iter);
  1847.     }
  1848.   }
  1849.   
  1850.   return alnSetRef;
  1851. }
  1852. void CDisplaySeqalign::x_DisplayAlnvecList(CNcbiOstream& out, list<alnInfo*>& avList) {
  1853.   bool isFirstAlnInList = true;
  1854.   for(list<alnInfo*>::iterator iterAv = avList.begin(); iterAv != avList.end(); iterAv ++){
  1855.     m_AV = (*iterAv)->alnVec;
  1856.     const CBioseq_Handle& bsp_handle=m_AV->GetBioseqHandle(1); 
  1857.     if(isFirstAlnInList && (m_AlignOption&eShowBlastInfo)) {
  1858.       PrintDefLine(bsp_handle,  out);
  1859.       out<<"          Length="<<bsp_handle.GetBioseqCore()->GetInst().GetLength()<<endl<<endl;
  1860.       
  1861.     }
  1862.     
  1863.     if (m_AlignOption&eShowBlastInfo) {
  1864.       
  1865.       out<<" Score = "<<(*iterAv)->bits<<" ";
  1866.       out<<"bits ("<<(*iterAv)->score<<"),"<<"  ";
  1867.       out<<"Expect = "<<(*iterAv)->eValue<<endl;
  1868.     }
  1869.     DisplayAlnvec(out);
  1870.     out<<endl;
  1871.     isFirstAlnInList = false;
  1872.   }
  1873.   
  1874. }
  1875. END_SCOPE(objects)
  1876. END_NCBI_SCOPE
  1877. /* 
  1878. *============================================================
  1879. *$Log: showalign.cpp,v $
  1880. *Revision 1000.5  2004/06/01 19:41:04  gouriano
  1881. *PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.36
  1882. *
  1883. *Revision 1.36  2004/05/21 21:42:51  gorelenk
  1884. *Added PCH ncbi_pch.hpp
  1885. *
  1886. *Revision 1.35  2004/04/26 16:50:48  ucko
  1887. *Don't try to pass temporary (dummy) CSeq_id objects, even by const
  1888. *reference, as CSeq_id has no public copy constructor.
  1889. *
  1890. *Revision 1.34  2004/04/14 16:29:03  jianye
  1891. *deprecated getbioseq
  1892. *
  1893. *Revision 1.33  2004/03/18 16:30:24  grichenk
  1894. *Changed type of seq-align containers from list to vector.
  1895. *
  1896. *Revision 1.32  2004/02/10 21:59:36  jianye
  1897. *Clean up some defs
  1898. *
  1899. *Revision 1.31  2004/01/29 23:13:20  jianye
  1900. *Wrap defline
  1901. *
  1902. *Revision 1.30  2004/01/27 17:11:43  ucko
  1903. *Allocate storage for m_NumAsciiChar to avoid link errors on AIX.
  1904. *
  1905. *Revision 1.29  2004/01/21 18:32:46  jianye
  1906. *initialize m_ConfigFile
  1907. *
  1908. *Revision 1.28  2004/01/13 17:58:02  jianye
  1909. *Added geo linkout
  1910. *
  1911. *Revision 1.27  2004/01/05 17:59:24  vasilche
  1912. *Moved genbank loader and its readers sources to new location in objtools.
  1913. *Genbank is now in library libncbi_xloader_genbank.
  1914. *Id1 reader is now in library libncbi_xreader_id1.
  1915. *OBJMGR_LIBS macro updated correspondingly.
  1916. *
  1917. *Old headers temporarily will contain redirection to new location
  1918. *for compatibility:
  1919. *objmgr/gbloader.hpp > objtools/data_loaders/genbank/gbloader.hpp
  1920. *objmgr/reader_id1.hpp > objtools/data_loaders/genbank/readers/id1/reader_id1.hpp
  1921. *
  1922. *Revision 1.26  2003/12/29 20:54:52  jianye
  1923. *change CanGet to IsSet
  1924. *
  1925. *Revision 1.25  2003/12/29 18:36:32  jianye
  1926. *Added nuc to nuc translation, show minus master as plus strand, etc
  1927. *
  1928. *Revision 1.24  2003/12/22 21:13:59  camacho
  1929. *Fix Seq-align-set type qualifier.
  1930. *Indenting left as-is.
  1931. *
  1932. *Revision 1.23  2003/12/16 19:21:23  jianye
  1933. *Set k_ColorMismatchIdentity to 0
  1934. *
  1935. *Revision 1.22  2003/12/11 22:27:18  jianye
  1936. *Use toolkit blosum matrix
  1937. *
  1938. *Revision 1.21  2003/12/09 19:40:24  ucko
  1939. *+<stdio.h> for sprintf
  1940. *
  1941. *Revision 1.20  2003/12/04 22:27:34  jianye
  1942. *Fixed accession problem for redundat hits
  1943. *
  1944. *Revision 1.19  2003/12/01 23:15:45  jianye
  1945. *Added showing CDR product
  1946. *
  1947. *Revision 1.18  2003/11/26 17:57:04  jianye
  1948. *Handling query set case for get sequence feature
  1949. *
  1950. *Revision 1.17  2003/10/28 22:41:06  jianye
  1951. *Added downloading sub seq capability for long seq
  1952. *
  1953. *Revision 1.16  2003/10/27 20:55:53  jianye
  1954. *Added color mismatches capability
  1955. *
  1956. *Revision 1.15  2003/10/08 17:48:54  jianye
  1957. *Fomat cvs log message area better
  1958. *
  1959. *Revision 1.14  2003/10/08 17:38:22  jianye
  1960. *fix comment sign generated by cvs
  1961. * Revision 1.13  2003/10/08 17:30:00  jianye
  1962. * get rid of some warnings under linux
  1963. *
  1964. *===========================================================
  1965. */