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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: alngraphic.cpp,v $
  4.  * PRODUCTION Revision 1000.0  2004/06/01 19:48:35  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.2
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: alngraphic.cpp,v 1000.0 2004/06/01 19:48:35 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.  *   Alignment graphic overview (using HTML table) 
  38.  *
  39.  */
  40. #include <ncbi_pch.hpp>
  41. #include <objtools/align/alngraphic.hpp>
  42. #include <util/range.hpp>
  43. #include <serial/iterator.hpp>
  44. #include <objects/seq/Bioseq.hpp>
  45. #include <objects/seqloc/Seq_loc.hpp>
  46. #include <objects/seqloc/Seq_id.hpp>
  47. #include <objects/seqalign/Seq_align.hpp>
  48. #include <objects/seqalign/Seq_align_set.hpp>
  49. #include <objects/seqalign/Score.hpp>
  50. #include <objects/seqalign/Dense_seg.hpp>
  51. #include <objects/seqalign/Std_seg.hpp>
  52. #include <objects/seqalign/Dense_diag.hpp>
  53. #include <objects/seqalign/seqalign_exception.hpp>
  54. #include <objects/general/Object_id.hpp>
  55. #include <objmgr/util/sequence.hpp>
  56. #include <html/html.hpp>
  57. BEGIN_NCBI_SCOPE
  58. BEGIN_SCOPE (objects)
  59. USING_SCOPE (sequence);
  60. static string kDigitGif[] = {"0.gif", "1.gif", "2.gif", "3.gif", "4.gif",
  61.                              "5.gif", "6.gif", "7.gif", "8.gif", "9.gif"};
  62. static const TSeqPos kScoreMargin = 50;
  63. static const TSeqPos kScoreLength = 500;
  64. static const TSeqPos kScoreHeight = 40;
  65. static const TSeqPos kBlankBarHeight = 4; 
  66. static const TSeqPos kMasterHeight = 10;
  67. static const TSeqPos kMasterPixel = kScoreLength;
  68. static const TSeqPos kMasterBarLength = 550;
  69. static const TSeqPos kScaleMarginAdj = 1;
  70. static const TSeqPos kScaleWidth = 2;
  71. static const TSeqPos kScaleHeight = 10;
  72. static const TSeqPos kDigitWidth = 10;
  73. static const TSeqPos kDigitHeight = 13;
  74. static const TSeqPos kGapHeight = 1;
  75. static const TSeqPos kNumMark = 6;
  76. static const int kDeflineLength = 55;
  77. /*two ranges are considered overlapping even if they do not overlap but
  78.   they differ only by this number*/
  79. static const int kOverlapDiff = 5;
  80. //gif images
  81. static const string kGifWhite = "white.gif";
  82. static const string kGifMaster ="query_no_scale.gif";
  83. static const string kGifScore = "score.gif";
  84. static const string kGifGrey = "grey.gif";
  85. static const string kGifScale = "scale.gif";
  86. static string s_GetGif(int bits){
  87.     string gif = NcbiEmptyString;
  88.     if(bits < 40){
  89.         gif = "black.gif";
  90.     } else if (bits < 50) {
  91.         gif = "blue.gif";
  92.     } else if (bits < 80) {
  93.         gif = "green.gif";
  94.     } else if (bits < 200) {
  95.         gif = "purple.gif";
  96.     } else  {
  97.         gif = "red.gif";
  98.     } 
  99.     //for alignment with no bits info
  100.     if(bits == 0){
  101.         gif = "red.gif";
  102.     }
  103.     return gif;
  104. }
  105. //Round the number.  i.e., 290 => 250, 735 => 700. 
  106. static int s_GetRoundNumber (int number){
  107.     int round = 0;
  108.    
  109.     if (number > 10) {
  110.         string num_str = NStr::IntToString(number);
  111.         int trail_num = NStr::StringToInt(num_str.substr(1, num_str.size() - 1));
  112.         round = number - trail_num;
  113.         string mid_num_str;
  114.         int mid_num = 0;
  115.         if(num_str.size() > 2) {
  116.             string trail_zero (num_str.size() - 2, '0');
  117.             mid_num_str = "5" +  trail_zero;
  118.             mid_num = NStr::StringToInt(mid_num_str);
  119.         }
  120.        
  121.         if (number >= round + mid_num) {
  122.             round += mid_num;
  123.         } 
  124.     } else {
  125.         round = number;
  126.     }
  127.     return round;
  128. }
  129. CRange<TSeqPos>* CAlnGraphic::x_GetEffectiveRange(TAlnInfoList& alninfo_list){
  130.     CRange<TSeqPos>* range = NULL;
  131.     if(!alninfo_list.empty()){
  132.         range = new CRange<TSeqPos>(alninfo_list.front()->range->GetFrom(), 
  133.                                     alninfo_list.back()->range->GetTo());
  134.     }
  135.     return range;
  136. }
  137. void CAlnGraphic::x_MergeDifferentSeq(double pixel_factor){
  138.   
  139.     TAlnInfoListList::iterator iter_temp;
  140.     list<CRange<TSeqPos>* > effective_range_list;
  141.     CRange<TSeqPos> *effective_range = NULL, *temp_range = NULL;
  142.    
  143.     NON_CONST_ITERATE(TAlnInfoListList, iter, m_AlninfoListList) {
  144.         iter_temp = iter; //current list
  145.         iter_temp ++;  //the next list
  146.         if(!(*iter)->empty() && iter_temp != m_AlninfoListList.end()){
  147.             /*effective ranges means the range covering all ranges for
  148.               alignment from the same seq*/
  149.             temp_range = x_GetEffectiveRange(**iter);
  150.             if(temp_range){
  151.                 effective_range_list.push_back(temp_range);
  152.             }
  153.   
  154.             /*compare the range in current list to range in all other lists.
  155.               If the latter does not overlap with the ranges in the current
  156.               list, move it to the current one*/
  157.             while(iter_temp != m_AlninfoListList.end()){
  158.                 /* Get effective range. Note that, except the current list,
  159.                    all other list contains only one effective range. The
  160.                    current list may have more than one because the range 
  161.                    from other list may be moved to it*/
  162.                 effective_range = x_GetEffectiveRange(**iter_temp);
  163.                 bool overlap = false;
  164.                 if(effective_range){
  165.                     NON_CONST_ITERATE(list<CRange<TSeqPos>*>,
  166.                                       iter2, 
  167.                                       effective_range_list){
  168.                         CRange<TSeqPos>* temp_range2 = *iter2;
  169.                         int min_to = min(effective_range->GetTo(), 
  170.                                          temp_range2->GetTo());
  171.                         int max_from =  max(effective_range->GetFrom(), 
  172.                                             temp_range2->GetFrom());
  173.                         //iter2 = ranges in current list
  174.                         if((int)((max_from - min_to)*pixel_factor) <= kOverlapDiff){
  175.                             //Not overlap but has only overlap_diff is still
  176.                             //considered overlap as it's difficult to see the
  177.                             //difference of only 1 pixel 
  178.                             overlap = true;
  179.                             break;  //overlaps, do nothing
  180.                         } 
  181.                     }
  182.                     //if no overlap, move this list to the current list
  183.                     if(!overlap){
  184.                         (*iter)->merge(**iter_temp);
  185.                         effective_range_list.push_back(effective_range);
  186.                     }
  187.                     if(overlap){
  188.                         delete effective_range;
  189.                     }
  190.                 }
  191.                 iter_temp ++;
  192.             }
  193.             ITERATE(list<CRange<TSeqPos>* >, iter4, effective_range_list){
  194.                 delete *iter4;
  195.             }
  196.             effective_range_list.clear();
  197.         }
  198.         (*iter)->sort(FromRangeAscendingSort);
  199.     }
  200. }
  201. void CAlnGraphic::x_MergeSameSeq(TAlnInfoList& alninfo_list){  
  202.     TAlnInfoList::iterator prev_iter; 
  203.     int i = 0;
  204.  
  205.     NON_CONST_ITERATE (TAlnInfoList, iter, alninfo_list){
  206.         if(i > 0 && (*prev_iter)->range->IntersectingWith(*((*iter)->range))){
  207.             //merge range
  208.             (*iter)->range->Set(min((*prev_iter)->range->GetFrom(), 
  209.                                     (*iter)->range->GetFrom()),
  210.                                 max((*prev_iter)->range->GetTo(), 
  211.                                     (*iter)->range->GetTo()));
  212.             //take the maximal score and evalue 
  213.             if((*iter)->bits < (*prev_iter)->bits){
  214.                 (*iter)->bits = (*prev_iter)->bits;
  215.                 (*iter)->info = (*prev_iter)->info;
  216.             }
  217.             delete (*prev_iter)->range;
  218.             delete *prev_iter;
  219.             alninfo_list.erase(prev_iter);     
  220.         }
  221.         i ++;
  222.         prev_iter = iter;
  223.     }    
  224. }
  225. template<class container> 
  226. static bool s_GetBlastScore(const container& scoreList,  
  227.                                                       int& score, 
  228.                                                       double& bits, 
  229.                                                       double& evalue){
  230.     bool hasScore = false;
  231.     ITERATE (typename container, iter, scoreList) {
  232.         const CObject_id& id=(*iter)->GetId();
  233.         if (id.IsStr()) {
  234.             hasScore = true;
  235.             if (id.GetStr()=="score"){
  236.                 score = (*iter)->GetValue().GetInt();
  237.             } else if (id.GetStr()=="bit_score"){
  238.                 bits = (*iter)->GetValue().GetReal();
  239.             } else if (id.GetStr()=="e_value" || id.GetStr()=="sum_e") {
  240.                 evalue = (*iter)->GetValue().GetReal();
  241.             } 
  242.         }
  243.     }
  244.     return hasScore;
  245. }
  246. static void s_GetAlnScores(const CSeq_align& aln, 
  247.                            int& score, 
  248.                            double& bits, 
  249.                            double& evalue){
  250.     bool hasScore = false;
  251.     //look for scores at seqalign level first
  252.     hasScore = s_GetBlastScore(aln.GetScore(),  score, bits, evalue);
  253.     
  254.     //look at the seg level
  255.     if(!hasScore){
  256.         const CSeq_align::TSegs& seg = aln.GetSegs();
  257.         if(seg.Which() == CSeq_align::C_Segs::e_Std){
  258.             s_GetBlastScore(seg.GetStd().front()->GetScores(), 
  259.                             score, bits, evalue);
  260.         } else if (seg.Which() == CSeq_align::C_Segs::e_Dendiag){
  261.             s_GetBlastScore(seg.GetDendiag().front()->GetScores(), 
  262.                             score, bits, evalue);
  263.         }  else if (seg.Which() == CSeq_align::C_Segs::e_Denseg){
  264.             s_GetBlastScore(seg.GetDenseg().GetScores(),  score, bits, evalue);
  265.         }
  266.     }
  267. }
  268. void CAlnGraphic::x_GetAlnInfo(const CSeq_align& aln, const CSeq_id& id,
  269.                                SAlignInfo* aln_info){
  270.     string info;
  271.     int score = 0;
  272.     double evalue = 0;
  273.     double bits = 0;
  274.     string bit_str, evalue_str;
  275.     string title;
  276.   
  277.     const CBioseq_Handle& handle = m_Scope->GetBioseqHandle(id);
  278.     if(handle){
  279.         const CBioseq::TId& ids = handle.GetBioseqCore()->GetId();
  280.         CRef<CSeq_id> wid = FindBestChoice(ids, CSeq_id::WorstRank);
  281.         aln_info->id = wid;
  282.         aln_info->gi =  FindGi(ids);
  283.         wid->GetLabel(&info, CSeq_id::eContent, 0);
  284.         title = GetTitle(handle);
  285.         if (title.size() > kDeflineLength){
  286.             title = title.substr(0, kDeflineLength) + "..";
  287.         }
  288.         info += " " + title;   
  289.     } else {
  290.         aln_info->gi = 0;
  291.         aln_info->id = &id;
  292.         aln_info->id->GetLabel(&info, CSeq_id::eContent, 0);
  293.     }
  294.     s_GetAlnScores(aln, score, bits, evalue);
  295.     NStr::DoubleToString(bit_str, (int)bits);
  296.     NStr::DoubleToString(evalue_str, evalue);
  297.     
  298.     CNcbiOstrstream ostream; 
  299.     ostream << setprecision (2) << evalue;
  300.     string formatted_evalue = CNcbiOstrstreamToString(ostream);
  301.     info += " S=" + bit_str + " E=" + formatted_evalue;
  302.     aln_info->info = info;
  303.     aln_info->bits = bits;
  304.    
  305. }
  306. CAlnGraphic::CAlnGraphic(const CSeq_align_set& seqalign, CScope& scope)
  307.     :m_AlnSet(&seqalign), m_Scope(&scope)  {
  308.     m_NumAlignToShow = 1200;
  309.     m_View = eCompactView;
  310.     m_BarHeight = e_Height4;
  311.     m_ImagePath = "./";
  312.     m_MouseOverFormName = "document.forms[0]";
  313.     m_NumLine = 55;
  314. }
  315. CAlnGraphic::~CAlnGraphic(){
  316.     //deallocate memory
  317.     ITERATE(TAlnInfoListList, iter, m_AlninfoListList) {
  318.         ITERATE(TAlnInfoList, iter2, **iter){
  319.             delete (*iter2)->range;
  320.             delete *iter2;
  321.         }
  322.         (*iter)->clear();
  323.     }
  324.     m_AlninfoListList.clear();
  325. }
  326. void CAlnGraphic::AlnGraphicDisplay(CNcbiOstream& out){
  327.     /*Note we can't just show each alnment as we go because we will 
  328.       need to put  all hsp's with the same id on one line*/
  329.    
  330.     TAlnInfoList* alninfo_list = NULL;
  331.     bool is_first_aln = true;
  332.     int num_align = 0;
  333.     int master_len = 0;
  334.     CNodeRef center; 
  335.     CRef<CHTML_table> tbl_box;
  336.     CHTML_tc* tbl_box_tc;
  337.     tbl_box = new CHTML_table;  //draw a box around the graphics
  338.     center = new CHTML_center;  //align all graphic in center
  339.   
  340.     tbl_box->SetCellSpacing(0)->SetCellPadding(10)->SetAttribute("border", "1");    
  341.     tbl_box->SetAttribute("bordercolorlight", "#0000FF");
  342.     tbl_box->SetAttribute("bordercolordark", "#0000FF");
  343.    
  344.     CConstRef<CSeq_id> previous_id, subid, master_id;
  345.     for (CSeq_align_set::Tdata::const_iterator iter = m_AlnSet->Get().begin(); 
  346.          iter != m_AlnSet->Get().end() && num_align < m_NumAlignToShow; 
  347.          iter++, num_align++){
  348.         if(!alninfo_list){
  349.             alninfo_list = new TAlnInfoList; 
  350.         }
  351.         //get start and end seq position for master sequence
  352.         CRange<TSeqPos>* seq_range = new CRange<TSeqPos>((*iter)->GetSeqRange(0));
  353.         //for minus strand
  354.         if(seq_range->GetFrom() > seq_range->GetTo()){
  355.             seq_range->Set(seq_range->GetTo(), seq_range->GetFrom());
  356.         }
  357.         subid = &((*iter)->GetSeq_id(1));
  358.         if(is_first_aln) {
  359.             master_id =  &((*iter)->GetSeq_id(0));
  360.             const CBioseq_Handle& handle = m_Scope->GetBioseqHandle(*master_id);
  361.             if(!handle){
  362.                 NCBI_THROW(CException, eUnknown, "Master sequence is not found!");
  363.             }
  364.             master_len = handle.GetBioseqCore()->GetInst().GetLength();
  365.             x_DisplayMaster(master_len, &(*center), &(*tbl_box), tbl_box_tc);
  366.         }
  367.         if(!is_first_aln && !subid->Match(*previous_id)) {
  368.             //this aln is a new id, show result for previous id
  369.             //save ranges for the same seqid
  370.             m_AlninfoListList.push_back(alninfo_list);
  371.             alninfo_list =  new TAlnInfoList;
  372.         }
  373.         SAlignInfo* alninfo = new SAlignInfo;
  374.         alninfo->range = seq_range;
  375.         //get aln info 
  376.         x_GetAlnInfo(**iter, *subid, alninfo);
  377.         alninfo_list->push_back(alninfo);
  378.         is_first_aln = false;
  379.         previous_id = subid;
  380.     }
  381.     
  382.     //save last set of seqs with the same id
  383.     if(alninfo_list){
  384.         m_AlninfoListList.push_back(alninfo_list);
  385.     }
  386.     //merge range for seq with the same id
  387.     ITERATE(TAlnInfoListList, iter, m_AlninfoListList) {
  388.         (*iter)->sort(FromRangeAscendingSort);
  389.         x_MergeSameSeq(**iter);  
  390.     }
  391.     //merge non-overlapping range list so that they can be put on 
  392.     //the same line to compress the results
  393.     if(m_View & eCompactView){
  394.         double pixel_factor = ((double)kMasterPixel)/master_len;
  395.         x_MergeDifferentSeq(pixel_factor);  
  396.     }
  397.     //display the graphic
  398.     x_BuildHtmlTable(master_len, &(*tbl_box), tbl_box_tc);
  399.     center->AppendChild(&(*tbl_box));
  400.     center->Print(out);
  401.     CHTML_hr hr;
  402.     hr.Print(out);
  403. }
  404. //print score legend, master label
  405. void CAlnGraphic::x_PrintTop (CNCBINode* center, CHTML_table* tbl_box, CHTML_tc*& tbl_box_tc){
  406.     if(m_View & eMouseOverInfo){
  407.      
  408.         CRef<CHTML_input> textbox(new CHTML_input("text", "defline"));
  409.         CNodeRef centered_text;       
  410.         textbox->SetAttribute("size", 85);
  411.         textbox->SetAttribute("value", 
  412.                               "Mouse over to see the defline, click to show alignments");
  413.         center->AppendChild(&(*textbox));
  414.       
  415.     }
  416.    
  417.     //score legend graph
  418.     CRef<CHTML_table> tbl(new CHTML_table);
  419.     CHTML_tc* tc;
  420.     tbl->SetCellSpacing(1)->SetCellPadding(0)->SetAttribute("border", "0");
  421.     CRef<CHTML_img> score_margin_img(new CHTML_img(m_ImagePath + kGifWhite,
  422.                                                    kScoreMargin, m_BarHeight));
  423.  
  424.     tc = tbl->InsertAt(0, 0, score_margin_img);
  425.     tc->SetAttribute("align", "LEFT");
  426.     tc->SetAttribute("valign", "CENTER");
  427.     CRef<CHTML_img> score(new CHTML_img(m_ImagePath + kGifScore, kScoreLength,
  428.                                         kScoreHeight));
  429.     tc = tbl->InsertAt(0, 1, score);
  430.     tc->SetAttribute("align", "LEFT");
  431.     tc->SetAttribute("valign", "CENTER");
  432.   
  433.     tbl_box_tc = tbl_box->InsertAt(0, 0, tbl);
  434.     tbl_box_tc->SetAttribute("align", "LEFT");
  435.     tbl_box_tc->SetAttribute("valign", "CENTER");
  436.     //master graph
  437.   
  438.     tbl = new CHTML_table;
  439.     tbl->SetCellSpacing(1)->SetCellPadding(0)->SetAttribute("border", "0");
  440.    
  441.     CRef<CHTML_img> master(new CHTML_img(m_ImagePath + kGifMaster,
  442.                                          kMasterBarLength, kMasterHeight));
  443.     
  444.     tc = tbl->InsertAt(0, 0, master);
  445.     tc->SetAttribute("align", "LEFT");
  446.     tc->SetAttribute("valign", "CENTER");
  447.     tbl_box_tc->AppendChild(&(*tbl));
  448.    
  449. }
  450. void CAlnGraphic::x_DisplayMaster(int master_len, CNCBINode* center, CHTML_table* tbl_box, CHTML_tc*& tbl_box_tc){
  451.     x_PrintTop(&(*center), &(*tbl_box), tbl_box_tc);
  452.  
  453.     //scale 
  454.     CRef<CHTML_table> tbl(new CHTML_table);
  455.     CHTML_tc* tc;
  456.     CRef<CHTML_img> image;
  457.     int column = 0;
  458.     tbl->SetCellSpacing(0)->SetCellPadding(0)->SetAttribute("border", "0");
  459.     image = new CHTML_img(m_ImagePath + kGifWhite, kScoreMargin + kScaleMarginAdj, m_BarHeight);
  460.     tc = tbl->InsertAt(0, column, image);
  461.     tc->SetAttribute("align", "LEFT");
  462.     tc->SetAttribute("valign", "CENTER");
  463.     column ++;
  464.     //first scale 
  465.     image = new CHTML_img(m_ImagePath + kGifScale, kScaleWidth, kScaleHeight);
  466.     tc = tbl->InsertAt(0, column, image);
  467.     tc->SetAttribute("align", "LEFT");
  468.     tc->SetAttribute("valign", "CENTER");
  469.     column ++;
  470.     //second scale mark and on 
  471.     float scale_unit = ((float)(master_len))/(kNumMark - 1);
  472.     int round_number = s_GetRoundNumber(scale_unit);
  473.     int spacer_length;
  474.     double pixel_factor = ((double)kMasterPixel)/master_len;
  475.     for (int i = 1; i*round_number <= master_len; i++) {
  476.         spacer_length = pixel_factor*round_number - kScaleWidth;
  477.         image = new CHTML_img(m_ImagePath + kGifWhite, spacer_length, m_BarHeight);
  478.         tc = tbl->InsertAt(0, column, image);
  479.         tc->SetAttribute("align", "LEFT");
  480.         tc->SetAttribute("valign", "CENTER");
  481.         column ++;  
  482.         image = new CHTML_img(m_ImagePath + kGifScale, kScaleWidth, kScaleHeight);
  483.         tc = tbl->InsertAt(0, column, image);
  484.         tc->SetAttribute("align", "LEFT");
  485.         tc->SetAttribute("valign", "CENTER");
  486.         column ++; 
  487.     }
  488.     tbl_box_tc->AppendChild(&(*tbl));
  489.     //digits 
  490.     //first scale digit
  491.     string digit_str, previous_digitstr;
  492.     int previous_digit;
  493.     column = 0;
  494.     image = new CHTML_img(m_ImagePath + kGifWhite, kScoreMargin, m_BarHeight);
  495.     tbl = new CHTML_table;
  496.     tbl->SetCellSpacing(0)->SetCellPadding(0)->SetAttribute("border", "0");
  497.     tc = tbl->InsertAt(0, column, image);
  498.     tc->SetAttribute("align", "LEFT");
  499.     tc->SetAttribute("valign", "CENTER");
  500.     column ++;
  501.     image = new CHTML_img(m_ImagePath + kDigitGif[0], kDigitWidth, kDigitHeight);
  502.     tc = tbl->InsertAt(0, column, image);
  503.     column ++;
  504.     previous_digit = 0;
  505.     previous_digitstr = NStr::IntToString(0);
  506.     
  507.     //print scale digits from second mark and on
  508.     for (TSeqPos i = 1; i*round_number <= master_len; i++) {
  509.        
  510.         digit_str = NStr::IntToString(i*round_number);        
  511.         spacer_length = pixel_factor*round_number 
  512.             - kDigitWidth*(previous_digitstr.size() 
  513.                            - previous_digitstr.size()/2) 
  514.             - kDigitWidth*(digit_str.size()/2);
  515.         previous_digitstr = digit_str;
  516.         image = new CHTML_img(m_ImagePath + kGifWhite, spacer_length, m_BarHeight);
  517.         tc = tbl->InsertAt(0, column, image);
  518.         tc->SetAttribute("align", "LEFT");
  519.         tc->SetAttribute("valign", "CENTER");
  520.         column ++;
  521.         //digits
  522.         for(size_t j = 0; j < digit_str.size(); j ++){
  523.             string one_digit(1, digit_str[j]); 
  524.             int digit = NStr::StringToInt(one_digit);
  525.             image = new CHTML_img(m_ImagePath + kDigitGif[digit], kDigitWidth, 
  526.                                   kDigitHeight);
  527.             tc = tbl->InsertAt(0, column, image);
  528.             tc->SetAttribute("align", "LEFT");
  529.             tc->SetAttribute("valign", "CENTER");
  530.             column ++;
  531.         }  
  532.     }
  533.     tbl_box_tc->AppendChild(&(*tbl));
  534.     CRef<CHTML_br> br(new CHTML_br);
  535.     tbl_box_tc->AppendChild(br);
  536. }
  537. //alignment bar graph
  538. void CAlnGraphic::x_BuildHtmlTable(int master_len, CHTML_table* tbl_box, CHTML_tc*& tbl_box_tc) {
  539.     CHTML_tc* tc;
  540.     double pixel_factor = ((double)kMasterPixel)/master_len;
  541.     int count = 0;
  542.     //print out each alignment
  543.     ITERATE(TAlnInfoListList, iter, m_AlninfoListList){  //iter =  each line
  544.         if(count > m_NumLine){
  545.             break;
  546.         }
  547.         CRef<CHTML_table> tbl;  //each table represents one line
  548.         CRef<CHTML_img> image;
  549.         CConstRef<CSeq_id> previous_id, current_id;
  550.         CRef<CHTML_a> ad;
  551.         double temp_value ;
  552.         int previous_end = -1;
  553.         int front_margin = 0;
  554.         int bar_length = 0;
  555.         int column = 0;
  556.         if(!(*iter)->empty()){ //table for starting white spacer
  557.             count ++;
  558.             tbl = new CHTML_table;
  559.             tbl->SetCellSpacing(0)->SetCellPadding(0)->SetAttribute("border", "0");  
  560.             image = new CHTML_img(m_ImagePath + kGifWhite, kScoreMargin, m_BarHeight);
  561.             tc = tbl->InsertAt(0, column, image);
  562.             column ++;
  563.             tc->SetAttribute("align", "LEFT");
  564.             tc->SetAttribute("valign", "CENTER");
  565.         }
  566.         ITERATE(TAlnInfoList, iter2, **iter){ //iter2 = each alignments on one line
  567.             current_id = (*iter2)->id;
  568.             //white space in front of this alignment
  569.             temp_value = ((*iter2)->range->GetFrom() - (previous_end + 1))*pixel_factor;
  570.             //rounding to int this way as round() is not portable
  571.             front_margin = temp_value + (temp_value < 0.0 ? -0.5 : 0.5);
  572.             //Need to add white space
  573.             if(temp_value > 0) {
  574.                 //Need to show at least one gap
  575.                 if(front_margin < 1){
  576.                     front_margin = 1;
  577.                 }
  578.                 //connecting the alignments with the same id
  579.                 if(m_View & eCompactView && !previous_id.Empty() 
  580.                    && previous_id->Match(*current_id)){
  581.                     image = new CHTML_img(m_ImagePath + kGifGrey, front_margin,
  582.                                           kGapHeight);
  583.                 } else {
  584.     
  585.                     image = new CHTML_img(m_ImagePath + kGifWhite, front_margin,
  586.                                           m_BarHeight);
  587.                 }
  588.                 tc = tbl->InsertAt(0, column, image);
  589.                 column ++;
  590.                 tc->SetAttribute("align", "LEFT");
  591.                 tc->SetAttribute("valign", "CENTER");
  592.             }
  593.             previous_end = (*iter2)->range->GetTo();
  594.             previous_id = current_id;
  595.             temp_value = (*iter2)->range->GetLength()*pixel_factor;
  596.             bar_length = temp_value + (temp_value < 0.0 ? -0.5 : 0.5);
  597.             image = new CHTML_img(m_ImagePath + s_GetGif((*iter2)->bits), 
  598.                                   bar_length, m_BarHeight);
  599.             image->SetAttribute("border", 0);
  600.             if(m_View & eMouseOverInfo){
  601.                 image->SetAttribute("ONMouseOver", m_MouseOverFormName 
  602.                                     + ".defline.value=" + "'" + (*iter2)->info
  603.                                     + "'");
  604.                 image->SetAttribute("ONMOUSEOUT", m_MouseOverFormName + 
  605.                                     ".defline.value='Mouse-over to show defline and scores, click to show alignments'");
  606.             }
  607.             if(m_View & eAnchorLink){
  608.                 string acc;
  609.                 (*iter2)->id->GetLabel(&acc, CSeq_id::eContent, 0);
  610.                 string seqid = (*iter2)->gi == 
  611.                     0 ? acc : NStr::IntToString((*iter2)->gi);
  612.                 ad = new CHTML_a("#" + seqid, image);
  613.                 tc = tbl->InsertAt(0, column, ad);
  614.             } else {
  615.                 tc = tbl->InsertAt(0, column, image);
  616.             }
  617.             column ++;
  618.             tc->SetAttribute("valign", "CENTER");
  619.             tc->SetAttribute("align", "LEFT");
  620.     
  621.         }
  622.         if(!tbl.Empty()){   
  623.             tbl_box_tc->AppendChild(&(*tbl));
  624.             //table for space between bars
  625.             tbl = new CHTML_table;
  626.             image = new CHTML_img(m_ImagePath + kGifWhite, kScoreMargin 
  627.                                   + kScoreLength, kBlankBarHeight);
  628.             tbl->SetCellSpacing(0)->SetCellPadding(0)->SetAttribute("border", "0");  
  629.             tbl->InsertAt(0, 0, image);
  630.             tbl_box_tc->AppendChild(&(*tbl));
  631.         }
  632.     }
  633. }
  634. END_SCOPE(objects)
  635. END_NCBI_SCOPE
  636. /* 
  637. *============================================================
  638. *$Log: alngraphic.cpp,v $
  639. *Revision 1000.0  2004/06/01 19:48:35  gouriano
  640. *PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.2
  641. *
  642. *Revision 1.2  2004/05/21 21:42:51  gorelenk
  643. *Added PCH ncbi_pch.hpp
  644. *
  645. *Revision 1.1  2004/04/30 15:40:41  jianye
  646. *Initial checkin
  647. *
  648. *===========================================================
  649. */