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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: conservation_colorer.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 18:28:29  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.35
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: conservation_colorer.cpp,v 1000.3 2004/06/01 18:28:29 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. * Authors:  Paul Thiessen
  35. *
  36. * File Description:
  37. *      Classes to color alignment blocks by sequence conservation
  38. *
  39. * ===========================================================================
  40. */
  41. #ifdef _MSC_VER
  42. #pragma warning(disable:4018)   // disable signed/unsigned mismatch warning in MSVC
  43. #endif
  44. #include <ncbi_pch.hpp>
  45. #include <corelib/ncbistd.hpp>  // must come before C-toolkit stuff
  46. #include <corelib/ncbi_limits.h>
  47. #include <util/tables/raw_scoremat.h>
  48. #include "block_multiple_alignment.hpp"
  49. #include "conservation_colorer.hpp"
  50. #include "cn3d_tools.hpp"
  51. #include "cn3d_blast.hpp"
  52. #include <blastkar.h>           // for BLAST standard probability routines
  53. #include <objseq.h>
  54. #include <math.h>
  55. USING_NCBI_SCOPE;
  56. BEGIN_SCOPE(Cn3D)
  57. static inline char ScreenResidueCharacter(char original)
  58. {
  59.     char ch = toupper(original);
  60.     switch (ch) {
  61.         case 'A': case 'R': case 'N': case 'D': case 'C':
  62.         case 'Q': case 'E': case 'G': case 'H': case 'I':
  63.         case 'L': case 'K': case 'M': case 'F': case 'P':
  64.         case 'S': case 'T': case 'W': case 'Y': case 'V':
  65.         case 'B': case 'Z':
  66.             break;
  67.         default:
  68.             ch = 'X'; // make all but natural aa's just 'X'
  69.     }
  70.     return ch;
  71. }
  72. int GetBLOSUM62Score(char a, char b)
  73. {
  74.     static SNCBIFullScoreMatrix Blosum62Matrix;
  75.     static bool unpacked = false;
  76.     if (!unpacked) {
  77.         NCBISM_Unpack(&NCBISM_Blosum62, &Blosum62Matrix);
  78.         unpacked = true;
  79.     }
  80.     return Blosum62Matrix.s[ScreenResidueCharacter(a)][ScreenResidueCharacter(b)];
  81. }
  82. static int GetPSSMScore(const BLAST_Matrix *pssm, char ch, int masterIndex)
  83. {
  84.     if (!pssm || masterIndex < 0 || masterIndex >= pssm->rows) {
  85.         ERRORMSG("GetPSSMScore() - invalid parameters");
  86.         return 0;
  87.     }
  88.     return pssm->matrix[masterIndex][LookupBLASTResidueNumberFromCharacter(ch)];
  89. }
  90. static map < char, float > StandardProbabilities;
  91. ConservationColorer::ConservationColorer(const BlockMultipleAlignment *parent) :
  92.     nColumns(0), basicColorsCurrent(false), fitColorsCurrent(false), alignment(parent)
  93. {
  94.     if (StandardProbabilities.size() == 0) {  // initialize static stuff
  95.         static const char ncbistdaa2char[26] = {
  96.             'X', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M',
  97.             'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z', 'X', 'X'
  98.         };
  99.         // calculate expected residue frequencies (standard probabilities)
  100.         // (code borrowed from SeqAlignInform() in cddutil.c)
  101.         BLAST_ScoreBlkPtr sbp = BLAST_ScoreBlkNew(Seq_code_ncbistdaa, 1);
  102.         BLAST_ResFreqPtr stdrfp = NULL;
  103.         int a;
  104.         if (!sbp) goto on_error;
  105.         sbp->read_in_matrix = TRUE;
  106.         sbp->protein_alphabet = TRUE;
  107.         sbp->posMatrix = NULL;
  108.         sbp->number_of_contexts = 1;
  109.         Nlm_Char BLOSUM62[20];
  110.         Nlm_StrCpy(BLOSUM62, "BLOSUM62");
  111.         // test C-toolkit data directory registry - which BlastScoreBlkMatFill() uses
  112.         Nlm_Char dataPath[255];
  113.         if (Nlm_FindPath("ncbi", "ncbi", "data", dataPath, 255))
  114.             TRACEMSG("FindPath() returned '" << dataPath << "'");
  115.         else
  116.             WARNINGMSG("FindPath() failed!");
  117.         if (BlastScoreBlkMatFill(sbp, BLOSUM62) != 0) goto on_error;
  118.         stdrfp = BlastResFreqNew(sbp);
  119.         if (!stdrfp) goto on_error;
  120.         if (BlastResFreqStdComp(sbp, stdrfp) != 0) goto on_error;
  121.         for (a=1; a<23; ++a) // from 'A' to 'Y'
  122.             StandardProbabilities[ncbistdaa2char[a]] = (float) stdrfp->prob[a];
  123. //        for (a=1; a<23; ++a)
  124. //            TESTMSG("std prob '" << ncbistdaa2char[a] << "' = "
  125. //                << setprecision(10) << StandardProbabilities[ncbistdaa2char[a]]);
  126.         goto cleanup;
  127. on_error:
  128.         ERRORMSG("ConservationColorer::ConservationColorer() - "
  129.             "error initializing standard residue probabilities");
  130. cleanup:
  131.         if (stdrfp) BlastResFreqDestruct(stdrfp);
  132.         if (sbp) BLAST_ScoreBlkDestruct(sbp);
  133.     }
  134. }
  135. void ConservationColorer::AddBlock(const UngappedAlignedBlock *block)
  136. {
  137.     // sanity check
  138.     if (!block->IsFrom(alignment)) {
  139.         ERRORMSG("ConservationColorer::AddBlock : block is not from the associated alignment");
  140.         return;
  141.     }
  142.     blocks[block].resize(block->width);
  143.     // map block column position to profile position
  144.     for (int i=0; i<block->width; ++i) blocks[block][i] = nColumns + i;
  145.     nColumns += block->width;
  146.     basicColorsCurrent = fitColorsCurrent = false;
  147. }
  148. void ConservationColorer::CalculateBasicConservationColors(void)
  149. {
  150.     if (basicColorsCurrent || blocks.size() == 0) return;
  151.     TRACEMSG("calculating basic conservation colors");
  152.     int nRows = alignment->NRows();
  153.     ColumnProfile::iterator p, pe, p2;
  154.     int row, profileColumn;
  155.     alignmentProfile.resize(nColumns);
  156.     typedef vector < int > IntVector;
  157.     IntVector varieties(nColumns, 0), weightedVarieties(nColumns, 0);
  158.     identities.resize(nColumns);
  159.     int minVariety, maxVariety, minWeightedVariety, maxWeightedVariety;
  160.     typedef vector < float > FloatVector;
  161.     FloatVector informationContents(nColumns, 0.0f);
  162.     float totalInformationContent = 0.0f;
  163.     BlockMap::const_iterator b, be = blocks.end();
  164.     for (b=blocks.begin(); b!=be; ++b) {
  165.         for (int blockColumn=0; blockColumn<b->first->width; ++blockColumn) {
  166.             profileColumn = b->second[blockColumn];
  167.             ColumnProfile& profile = alignmentProfile[profileColumn];
  168.             // create profile for this column
  169.             profile.clear();
  170.             for (row=0; row<nRows; ++row) {
  171.                 char ch = ScreenResidueCharacter(b->first->GetCharacterAt(blockColumn, row));
  172.                 if ((p=profile.find(ch)) != profile.end())
  173.                     ++(p->second);
  174.                 else
  175.                     profile[ch] = 1;
  176.             }
  177.             pe = profile.end();
  178.             // identity for this column
  179.             if (profile.size() == 1 && profile.begin()->first != 'X')
  180.                 identities[profileColumn] = true;
  181.             else
  182.                 identities[profileColumn] = false;
  183.             // variety for this column
  184.             int& variety = varieties[profileColumn];
  185.             variety = profile.size();
  186.             if (profile.find('X') != profile.end())
  187.                 variety += profile['X'] - 1; // each 'X' counts as one variety
  188.             if (blockColumn == 0 && b == blocks.begin()) {
  189.                 minVariety = maxVariety = variety;
  190.             } else {
  191.                 if (variety < minVariety) minVariety = variety;
  192.                 else if (variety > maxVariety) maxVariety = variety;
  193.             }
  194.             // weighted variety for this column
  195.             int& weightedVariety = weightedVarieties[profileColumn];
  196.             for (p=profile.begin(); p!=pe; ++p) {
  197.                 weightedVariety +=
  198.                     (p->second * (p->second - 1) / 2) * GetBLOSUM62Score(p->first, p->first);
  199.                 p2 = p;
  200.                 for (++p2; p2!=pe; ++p2)
  201.                     weightedVariety +=
  202.                         p->second * p2->second * GetBLOSUM62Score(p->first, p2->first);
  203.             }
  204.             if (blockColumn == 0 && b == blocks.begin()) {
  205.                 minWeightedVariety = maxWeightedVariety = weightedVariety;
  206.             } else {
  207.                 if (weightedVariety < minWeightedVariety) minWeightedVariety = weightedVariety;
  208.                 else if (weightedVariety > maxWeightedVariety) maxWeightedVariety = weightedVariety;
  209.             }
  210.             // information content (calculated in bits -> logs of base 2) for this column
  211.             float &columnInfo = informationContents[profileColumn];
  212.             for (p=profile.begin(); p!=pe; ++p) {
  213.                 static const float ln2 = log(2.0f), threshhold = 0.0001f;
  214.                 float residueScore = 0.0f, expFreq = StandardProbabilities[p->first];
  215.                 if (expFreq > threshhold) {
  216.                     float obsFreq = 1.0f * p->second / nRows,
  217.                           freqRatio = obsFreq / expFreq;
  218.                     if (freqRatio > threshhold) {
  219.                         residueScore = obsFreq * ((float) log(freqRatio)) / ln2;
  220.                         columnInfo += residueScore; // information content
  221.                     }
  222.                 }
  223.             }
  224.             totalInformationContent += columnInfo;
  225.         }
  226.     }
  227.     INFOMSG("Total information content of aligned blocks: " << totalInformationContent << " bits");
  228.     // now assign colors
  229.     varietyColors.resize(nColumns);
  230.     weightedVarietyColors.resize(nColumns);
  231.     informationContentColors.resize(nColumns);
  232.     double scale;
  233.     for (profileColumn=0; profileColumn<nColumns; ++profileColumn) {
  234.         // variety
  235.         if (maxVariety == minVariety)
  236.             scale = 1.0;
  237.         else
  238.             scale = 1.0 - 1.0 * (varieties[profileColumn] - minVariety) / (maxVariety - minVariety);
  239.         varietyColors[profileColumn] = GlobalColors()->Get(Colors::eConservationMap, scale);
  240.         // weighted variety
  241.         if (maxWeightedVariety == minWeightedVariety)
  242.             scale = 1.0;
  243.         else
  244.             scale = 1.0 * (weightedVarieties[profileColumn] - minWeightedVariety) /
  245.                 (maxWeightedVariety - minWeightedVariety);
  246.         weightedVarietyColors[profileColumn] = GlobalColors()->Get(Colors::eConservationMap, scale);
  247.         // information content, based on absolute scale
  248.         static const float minInform = 0.10f, maxInform = 6.24f;
  249.         scale = (informationContents[profileColumn] - minInform) / (maxInform - minInform);
  250.         if (scale < 0.0) scale = 0.0;
  251.         else if (scale > 1.0) scale = 1.0;
  252.         scale = sqrt(scale);    // apply non-linearity so that lower values are better distinguished
  253.         informationContentColors[profileColumn] = GlobalColors()->Get(Colors::eConservationMap, scale);
  254.     }
  255.     basicColorsCurrent = true;
  256.     fitColorsCurrent = false;
  257. }
  258. void ConservationColorer::CalculateFitConservationColors(void)
  259. {
  260.     if (fitColorsCurrent || blocks.size() == 0) return;
  261.     CalculateBasicConservationColors();     // also includes profile
  262.     TRACEMSG("calculating fit conservation colors");
  263.     int nRows = alignment->NRows();
  264.     ColumnProfile::iterator p, pe;
  265.     int row, profileColumn;
  266.     typedef map < char, int > CharIntMap;
  267.     vector < CharIntMap > fitScores(nColumns);
  268.     int minFit, maxFit;
  269.     typedef vector < float > FloatVector;
  270.     typedef map < const UngappedAlignedBlock * , FloatVector > BlockRowScores;
  271.     BlockRowScores blockFitScores, blockZFitScores, blockRowFitScores;
  272.     float minBlockFit, maxBlockFit, minBlockZFit, maxBlockZFit, minBlockRowFit, maxBlockRowFit;
  273.     BlockMap::const_iterator b, be = blocks.end();
  274.     for (b=blocks.begin(); b!=be; ++b) {
  275.         blockFitScores[b->first].resize(nRows, 0.0f);
  276.         for (int blockColumn=0; blockColumn<b->first->width; ++blockColumn) {
  277.             profileColumn = b->second[blockColumn];
  278.             ColumnProfile& profile = alignmentProfile[profileColumn];
  279.             pe = profile.end();
  280.             // fit scores
  281.             for (p=profile.begin(); p!=pe; ++p) {
  282.                 int& fit = fitScores[profileColumn][p->first];
  283.                 fit = GetPSSMScore(alignment->GetPSSM(),
  284.                     p->first, b->first->GetRangeOfRow(0)->from + blockColumn);
  285.                 if (blockColumn == 0 && b == blocks.begin() && p == profile.begin()) {
  286.                     minFit = maxFit = fit;
  287.                 } else {
  288.                     if (fit < minFit) minFit = fit;
  289.                     else if (fit > maxFit) maxFit = fit;
  290.                 }
  291.             }
  292.             // add up residue fit scores to get block fit scores
  293.             for (row=0; row<nRows; ++row) {
  294.                 char ch = ScreenResidueCharacter(b->first->GetCharacterAt(blockColumn, row));
  295.                 blockFitScores[b->first][row] += fitScores[profileColumn][ch];
  296.             }
  297.         }
  298.         // find average/min/max block fit
  299.         float average = 0.0f;
  300.         for (row=0; row<nRows; ++row) {
  301.             float& score = blockFitScores[b->first][row];
  302.             score /= b->first->width;   // average fit score across the block for this row
  303.             average += score;
  304.             if (row == 0 && b == blocks.begin()) {
  305.                 minBlockFit = maxBlockFit = score;
  306.             } else {
  307.                 if (score < minBlockFit) minBlockFit = score;
  308.                 else if (score > maxBlockFit) maxBlockFit = score;
  309.             }
  310.         }
  311.         average /= nRows;
  312.         // calculate block Z scores from block fit scores
  313.         if (nRows >= 2) {
  314.             // calculate standard deviation of block fit score over all rows of this block
  315.             float stdDev = 0.0f;
  316.             for (row=0; row<nRows; ++row)
  317.                 stdDev += (blockFitScores[b->first][row] - average) *
  318.                           (blockFitScores[b->first][row] - average);
  319.             stdDev /= nRows - 1;
  320.             stdDev = sqrt(stdDev);
  321.             if (stdDev > 1e-10) {
  322.                 // calculate Z scores for each row
  323.                 blockZFitScores[b->first].resize(nRows);
  324.                 for (row=0; row<nRows; ++row)
  325.                     blockZFitScores[b->first][row] = (blockFitScores[b->first][row] - average) / stdDev;
  326.             }
  327.         }
  328.     }
  329.     // calculate row fit scores based on Z-scores for each block across a given row
  330.     if (blocks.size() >= 2) {
  331.         for (b=blocks.begin(); b!=be; ++b)
  332.             blockRowFitScores[b->first].resize(nRows, kMin_Float);
  333.         // calculate row average, standard deviation, and Z-scores
  334.         for (row=0; row<nRows; ++row) {
  335.             float average = 0.0f;
  336.             for (b=blocks.begin(); b!=be; ++b)
  337.                 average += blockFitScores[b->first][row];
  338.             average /= blocks.size();
  339.             float stdDev = 0.0f;
  340.             for (b=blocks.begin(); b!=be; ++b)
  341.                 stdDev += (blockFitScores[b->first][row] - average) *
  342.                           (blockFitScores[b->first][row] - average);
  343.             stdDev /= blocks.size() - 1;
  344.             stdDev = sqrt(stdDev);
  345.             if (stdDev > 1e-10) {
  346.                 for (b=blocks.begin(); b!=be; ++b)
  347.                     blockRowFitScores[b->first][row] = (blockFitScores[b->first][row] - average) / stdDev;
  348.             }
  349.         }
  350.     }
  351.     // now assign colors
  352.     double scale;
  353.     fitColors.resize(nRows * nColumns);
  354.     for (profileColumn=0; profileColumn<nColumns; ++profileColumn) {
  355.         // fit
  356.         CharIntMap::const_iterator c, ce = fitScores[profileColumn].end();
  357.         for (c=fitScores[profileColumn].begin(); c!=ce; ++c) {
  358.             if (maxFit == minFit)
  359.                 scale = 1.0;
  360.             else
  361.                 scale = 1.0 * (c->second - minFit) / (maxFit - minFit);
  362.             fitColors[profileColumn][c->first] = GlobalColors()->Get(Colors::eConservationMap, scale);
  363.         }
  364.     }
  365.     // block fit
  366.     blockFitColors.clear();
  367.     for (b=blocks.begin(); b!=be; ++b) {
  368.         blockFitColors[b->first].resize(nRows);
  369.         for (row=0; row<nRows; ++row) {
  370.             if (maxBlockFit == minBlockFit)
  371.                 scale = 1.0;
  372.             else
  373.                 scale = 1.0 * (blockFitScores[b->first][row] - minBlockFit) / (maxBlockFit - minBlockFit);
  374.             blockFitColors[b->first][row] = GlobalColors()->Get(Colors::eConservationMap, scale);
  375.         }
  376.     }
  377.     // block Z fit
  378.     blockZFitColors.clear();
  379.     for (b=blocks.begin(); b!=be; ++b) {
  380.         blockZFitColors[b->first].resize(nRows, Vector(0,0,0));
  381.         if (blockZFitScores.find(b->first) != blockZFitScores.end()) {  // if this column has scores
  382.             for (row=0; row<nRows; ++row) {                             // normalize colors per column
  383.                 float zScore = blockZFitScores[b->first][row];
  384.                 if (row == 0) {
  385.                     minBlockZFit = maxBlockZFit = zScore;
  386.                 } else {
  387.                     if (zScore < minBlockZFit) minBlockZFit = zScore;
  388.                     else if (zScore > maxBlockZFit) maxBlockZFit = zScore;
  389.                 }
  390.             }
  391.             for (row=0; row<nRows; ++row) {
  392.                 if (maxBlockZFit == minBlockZFit)
  393.                     scale = 1.0;
  394.                 else
  395.                     scale = 1.0 * (blockZFitScores[b->first][row] - minBlockZFit) /
  396.                                         (maxBlockZFit - minBlockZFit);
  397.                 blockZFitColors[b->first][row] = GlobalColors()->Get(Colors::eConservationMap, scale);
  398.             }
  399.         }
  400.     }
  401.     // block row fit
  402.     blockRowFitColors.clear();
  403.     for (b=blocks.begin(); b!=be; ++b)
  404.         blockRowFitColors[b->first].resize(nRows, Vector(0,0,0));
  405.     if (blocks.size() >= 2) {
  406.         for (row=0; row<nRows; ++row) {
  407.             if (blockRowFitScores.begin()->second[row] != kMin_Float) { // if this row has fit scores
  408.                 for (b=blocks.begin(); b!=be; ++b) {                    // normalize colors per row
  409.                     float zScore = blockRowFitScores[b->first][row];
  410.                     if (b == blocks.begin()) {
  411.                         minBlockRowFit = maxBlockRowFit = zScore;
  412.                     } else {
  413.                         if (zScore < minBlockRowFit) minBlockRowFit = zScore;
  414.                         else if (zScore > maxBlockRowFit) maxBlockRowFit = zScore;
  415.                     }
  416.                 }
  417.                 for (b=blocks.begin(); b!=be; ++b) {
  418.                     if (maxBlockRowFit == minBlockRowFit)
  419.                         scale = 1.0;
  420.                     else
  421.                         scale = 1.0 * (blockRowFitScores[b->first][row] - minBlockRowFit) /
  422.                                             (maxBlockRowFit - minBlockRowFit);
  423.                     blockRowFitColors[b->first][row] = GlobalColors()->Get(Colors::eConservationMap, scale);
  424.                 }
  425.             }
  426.         }
  427.     }
  428.     fitColorsCurrent = true;
  429. }
  430. void ConservationColorer::GetProfileIndexAndResidue(
  431.     const UngappedAlignedBlock *block, int blockColumn, int row,
  432.     int *profileIndex, char *residue) const
  433. {
  434.     BlockMap::const_iterator b = blocks.find(block);
  435.     *profileIndex = b->second[blockColumn];
  436.     *residue = ScreenResidueCharacter(b->first->GetCharacterAt(blockColumn, row));
  437. }
  438. void ConservationColorer::Clear(void)
  439. {
  440.     nColumns = 0;
  441.     blocks.clear();
  442.     FreeColors();
  443. }
  444. void ConservationColorer::FreeColors(void)
  445. {
  446.     alignmentProfile.clear();
  447.     identities.clear();
  448.     varietyColors.clear();
  449.     weightedVarietyColors.clear();
  450.     informationContentColors.clear();
  451.     fitColors.clear();
  452.     blockFitColors.clear();
  453.     blockZFitColors.clear();
  454.     blockRowFitColors.clear();
  455.     basicColorsCurrent = fitColorsCurrent = false;
  456. }
  457. END_SCOPE(Cn3D)
  458. /*
  459. * ---------------------------------------------------------------------------
  460. * $Log: conservation_colorer.cpp,v $
  461. * Revision 1000.3  2004/06/01 18:28:29  gouriano
  462. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.35
  463. *
  464. * Revision 1.35  2004/05/21 21:41:39  gorelenk
  465. * Added PCH ncbi_pch.hpp
  466. *
  467. * Revision 1.34  2004/03/15 18:23:01  thiessen
  468. * prefer prefix vs. postfix ++/-- operators
  469. *
  470. * Revision 1.33  2004/02/19 17:04:53  thiessen
  471. * remove cn3d/ from include paths; add pragma to disable annoying msvc warning
  472. *
  473. * Revision 1.32  2003/12/11 19:35:54  thiessen
  474. * use built-in blosum62 matrix
  475. *
  476. * Revision 1.31  2003/11/04 18:09:17  thiessen
  477. * rearrange headers for OSX build
  478. *
  479. * Revision 1.30  2003/02/13 18:31:39  thiessen
  480. * separate basic from fit color calculation
  481. *
  482. * Revision 1.29  2003/02/12 15:36:14  thiessen
  483. * clean up fit scoring code
  484. *
  485. * Revision 1.28  2003/02/06 16:39:53  thiessen
  486. * add block row fit coloring
  487. *
  488. * Revision 1.27  2003/02/03 19:20:03  thiessen
  489. * format changes: move CVS Log to bottom of file, remove std:: from .cpp files, and use new diagnostic macros
  490. *
  491. * Revision 1.26  2003/01/31 17:18:58  thiessen
  492. * many small additions and changes...
  493. *
  494. * Revision 1.25  2003/01/30 14:00:23  thiessen
  495. * add Block Z Fit coloring
  496. *
  497. * Revision 1.24  2003/01/28 21:07:56  thiessen
  498. * add block fit coloring algorithm; tweak row dragging; fix style bug
  499. *
  500. * Revision 1.23  2002/07/23 16:40:39  thiessen
  501. * remove static decl
  502. *
  503. * Revision 1.22  2002/07/23 15:46:50  thiessen
  504. * print out more BLAST info; tweak save file name
  505. *
  506. * Revision 1.21  2002/04/27 16:32:12  thiessen
  507. * fix small leaks/bugs found by BoundsChecker
  508. *
  509. * Revision 1.20  2002/03/01 15:47:10  thiessen
  510. * fix bug in fit coloring for non-standard residues
  511. *
  512. * Revision 1.19  2002/02/13 19:45:29  thiessen
  513. * Fit coloring by info content contribution
  514. *
  515. * Revision 1.18  2001/09/27 15:37:58  thiessen
  516. * decouple sequence import and BLAST
  517. *
  518. * Revision 1.17  2001/08/24 00:41:35  thiessen
  519. * tweak conservation colors and opengl font handling
  520. *
  521. * Revision 1.16  2001/08/13 22:30:59  thiessen
  522. * add structure window mouse drag/zoom; add highlight option to render settings
  523. *
  524. * Revision 1.15  2001/06/04 14:58:00  thiessen
  525. * add proximity sort; highlight sequence on browser launch
  526. *
  527. * Revision 1.14  2001/06/02 17:22:45  thiessen
  528. * fixes for GCC
  529. *
  530. * Revision 1.13  2001/05/31 18:47:08  thiessen
  531. * add preliminary style dialog; remove LIST_TYPE; add thread single and delete all; misc tweaks
  532. *
  533. * Revision 1.12  2001/05/25 01:38:16  thiessen
  534. * minor fixes for compiling on SGI
  535. *
  536. * Revision 1.11  2001/05/22 22:37:13  thiessen
  537. * check data registry path
  538. *
  539. * Revision 1.10  2001/05/22 19:09:30  thiessen
  540. * many minor fixes to compile/run on Solaris/GTK
  541. *
  542. * Revision 1.9  2001/03/22 00:33:16  thiessen
  543. * initial threading working (PSSM only); free color storage in undo stack
  544. *
  545. * Revision 1.8  2001/02/22 00:30:06  thiessen
  546. * make directories global ; allow only one Sequence per StructureObject
  547. *
  548. * Revision 1.7  2001/02/15 00:03:54  thiessen
  549. * print out total information content
  550. *
  551. * Revision 1.6  2001/02/13 20:33:49  thiessen
  552. * add information content coloring
  553. *
  554. * Revision 1.5  2000/11/30 15:49:38  thiessen
  555. * add show/hide rows; unpack sec. struc. and domain features
  556. *
  557. * Revision 1.4  2000/10/16 20:03:07  thiessen
  558. * working block creation
  559. *
  560. * Revision 1.3  2000/10/16 14:25:48  thiessen
  561. * working alignment fit coloring
  562. *
  563. * Revision 1.2  2000/10/04 17:41:30  thiessen
  564. * change highlight color (cell background) handling
  565. *
  566. * Revision 1.1  2000/09/20 22:24:48  thiessen
  567. * working conservation coloring; split and center unaligned justification
  568. *
  569. */