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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: sequence_display.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 18:29:04  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.73
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: sequence_display.cpp,v 1000.3 2004/06/01 18:29: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. * Authors:  Paul Thiessen
  35. *
  36. * File Description:
  37. *      Classes to hold rows in a sequence/alignment display
  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>
  46. #include <corelib/ncbistl.hpp>
  47. #include <corelib/ncbistre.hpp>
  48. #include <corelib/ncbi_limits.h>
  49. #include <algorithm>
  50. #include "sequence_display.hpp"
  51. #include "viewer_window_base.hpp"
  52. #include "viewer_base.hpp"
  53. #include "molecule.hpp"
  54. #include "messenger.hpp"
  55. #include "structure_set.hpp"
  56. #include "style_manager.hpp"
  57. #include "sequence_viewer_window.hpp"
  58. #include "sequence_viewer.hpp"
  59. #include "alignment_manager.hpp"
  60. #include "cn3d_colors.hpp"
  61. #include "update_viewer.hpp"
  62. #include "update_viewer_window.hpp"
  63. #include "cn3d_tools.hpp"
  64. #include "cn3d_threader.hpp"
  65. #include "conservation_colorer.hpp"
  66. #include "molecule_identifier.hpp"
  67. #include "cn3d_blast.hpp"
  68. USING_NCBI_SCOPE;
  69. BEGIN_SCOPE(Cn3D)
  70. // block marker string stuff
  71. static const char
  72.     blockLeftEdgeChar = '<',
  73.     blockRightEdgeChar = '>',
  74.     blockOneColumnChar = '^',
  75.     blockInsideChar = '-';
  76. static const string blockBoundaryStringTitle("(blocks)");
  77. // color converter
  78. static inline void Vector2wxColor(const Vector& colorVec, wxColor *colorWX)
  79. {
  80.     colorWX->Set(
  81.         static_cast<unsigned char>((colorVec[0] + 0.000001) * 255),
  82.         static_cast<unsigned char>((colorVec[1] + 0.000001) * 255),
  83.         static_cast<unsigned char>((colorVec[2] + 0.000001) * 255)
  84.     );
  85. }
  86. ////////////////////////////////////////////////////////////////////////////////
  87. // The sequence view is composed of rows which can be from sequence, alignment,
  88. // or any string - anything derived from DisplayRow, implemented below.
  89. ////////////////////////////////////////////////////////////////////////////////
  90. bool DisplayRowFromAlignment::GetCharacterTraitsAt(
  91.     int column, BlockMultipleAlignment::eUnalignedJustification justification,
  92.     char *character, Vector *color,
  93.     bool *drawBackground, Vector *cellBackgroundColor) const
  94. {
  95.     bool isHighlighted,
  96.         result = alignment->GetCharacterTraitsAt(
  97.             column, row, justification, character, color,
  98.             &isHighlighted, drawBackground, cellBackgroundColor);
  99.     // always apply highlight color, even if alignment has set its own background color
  100.     if (isHighlighted) {
  101.         *drawBackground = true;
  102.         *cellBackgroundColor = GlobalColors()->Get(Colors::eHighlight);
  103.     }
  104.     return result;
  105. }
  106. DisplayRowFromSequence::DisplayRowFromSequence(const Sequence *s, int from, int to) :
  107.     sequence(s), fromIndex(from), toIndex(to)
  108. {
  109.     if (from < 0 || from >= sequence->Length() || from > to || to < 0 || to >= sequence->Length())
  110.         ERRORMSG("DisplayRowFromSequence::DisplayRowFromSequence() - from/to indexes out of range");
  111. }
  112. bool DisplayRowFromSequence::GetCharacterTraitsAt(
  113. int column, BlockMultipleAlignment::eUnalignedJustification justification,
  114.     char *character, Vector *color, bool *drawBackground, Vector *cellBackgroundColor) const
  115. {
  116.     int index = column + fromIndex;
  117.     if (index > toIndex)
  118.         return false;
  119.     *character = tolower(sequence->sequenceString[index]);
  120.     if (sequence->molecule)
  121.         *color = sequence->molecule->GetResidueColor(index);
  122.     else
  123.         color->Set(0,0,0);
  124.     if (GlobalMessenger()->IsHighlighted(sequence, index)) {
  125.         *drawBackground = true;
  126.         *cellBackgroundColor = GlobalColors()->Get(Colors::eHighlight);
  127.     } else {
  128.         *drawBackground = false;
  129.     }
  130.     return true;
  131. }
  132. bool DisplayRowFromSequence::GetSequenceAndIndexAt(
  133.     int column, BlockMultipleAlignment::eUnalignedJustification justification,
  134.     const Sequence **sequenceHandle, int *seqIndex) const
  135. {
  136.     int index = column + fromIndex;
  137.     if (index > toIndex)
  138.         return false;
  139.     *sequenceHandle = sequence;
  140.     *seqIndex = index;
  141.     return true;
  142. }
  143. void DisplayRowFromSequence::SelectedRange(int from, int to,
  144.     BlockMultipleAlignment::eUnalignedJustification justification, bool toggle) const
  145. {
  146.     from += fromIndex;
  147.     to += fromIndex;
  148.     // skip if selected outside range
  149.     if (from < fromIndex && to < fromIndex) return;
  150.     if (from > toIndex && to > toIndex) return;
  151.     // trim to within range
  152.     if (from < fromIndex) from = fromIndex;
  153.     else if (from > toIndex) from = toIndex;
  154.     if (to < fromIndex) to = fromIndex;
  155.     else if (to > toIndex) to = toIndex;
  156.     if (toggle)
  157.         GlobalMessenger()->ToggleHighlights(sequence, from, to);
  158.     else
  159.         GlobalMessenger()->AddHighlights(sequence, from, to);
  160. }
  161. bool DisplayRowFromString::GetCharacterTraitsAt(int column,
  162. BlockMultipleAlignment::eUnalignedJustification justification,
  163.     char *character, Vector *color, bool *drawBackground, Vector *cellBackgroundColor) const
  164. {
  165.     if (column >= theString.size()) return false;
  166.     *character = theString[column];
  167.     *color = stringColor;
  168.     if (hasBackgroundColor) {
  169.         *drawBackground = true;
  170.         *cellBackgroundColor = backgroundColor;
  171.     } else {
  172.         *drawBackground = false;
  173.     }
  174.     return true;
  175. }
  176. ////////////////////////////////////////////////////////////////////////////////
  177. // The SequenceDisplay is the structure that holds the DisplayRows of the view.
  178. // It's also derived from ViewableAlignment, in order to be plugged into a
  179. // SequenceDisplayWidget.
  180. ////////////////////////////////////////////////////////////////////////////////
  181. SequenceDisplay::SequenceDisplay(bool editable, ViewerWindowBase* const *parentViewerWindow) :
  182.     isEditable(editable), maxRowWidth(0), viewerWindow(parentViewerWindow), startingColumn(0)
  183. {
  184. }
  185. SequenceDisplay::~SequenceDisplay(void)
  186. {
  187.     for (int i=0; i<rows.size(); ++i) delete rows[i];
  188. }
  189. void SequenceDisplay::Empty(void)
  190. {
  191.     for (int i=0; i<rows.size(); ++i) delete rows[i];
  192.     rows.clear();
  193.     startingColumn = maxRowWidth = 0;
  194. }
  195. SequenceDisplay * SequenceDisplay::Clone(const Old2NewAlignmentMap& newAlignments) const
  196. {
  197.     SequenceDisplay *copy = new SequenceDisplay(isEditable, viewerWindow);
  198.     for (int row=0; row<rows.size(); ++row)
  199.         copy->rows.push_back(rows[row]->Clone(newAlignments));
  200.     copy->startingColumn = startingColumn;
  201.     copy->maxRowWidth = maxRowWidth;
  202.     return copy;
  203. }
  204. void SequenceDisplay::AddRow(DisplayRow *row)
  205. {
  206.     rows.push_back(row);
  207.     if (row->Width() > maxRowWidth) maxRowWidth = row->Width();
  208. }
  209. BlockMultipleAlignment * SequenceDisplay::GetAlignmentForRow(int row) const
  210. {
  211.     if (row < 0 || row >= rows.size()) return NULL;
  212.     const DisplayRowFromAlignment *displayRow = dynamic_cast<const DisplayRowFromAlignment*>(rows[row]);
  213.     if (displayRow) return displayRow->alignment;
  214.     const DisplayRowFromString *stringRow = dynamic_cast<const DisplayRowFromString*>(rows[row]);
  215.     if (stringRow) return stringRow->alignment;
  216.     return NULL;
  217. }
  218. void SequenceDisplay::UpdateMaxRowWidth(void)
  219. {
  220.     RowVector::iterator r, re = rows.end();
  221.     maxRowWidth = 0;
  222.     for (r=rows.begin(); r!=re; ++r)
  223.         if ((*r)->Width() > maxRowWidth) maxRowWidth = (*r)->Width();
  224. }
  225. void SequenceDisplay::AddRowFromAlignment(int row, BlockMultipleAlignment *fromAlignment)
  226. {
  227.     if (!fromAlignment || row < 0 || row >= fromAlignment->NRows()) {
  228.         ERRORMSG("SequenceDisplay::AddRowFromAlignment() failed");
  229.         return;
  230.     }
  231.     AddRow(new DisplayRowFromAlignment(row, fromAlignment));
  232. }
  233. void SequenceDisplay::AddRowFromSequence(const Sequence *sequence, int from, int to)
  234. {
  235.     if (!sequence) {
  236.         ERRORMSG("SequenceDisplay::AddRowFromSequence() failed");
  237.         return;
  238.     }
  239.     AddRow(new DisplayRowFromSequence(sequence, from, to));
  240. }
  241. void SequenceDisplay::AddRowFromString(const string& anyString)
  242. {
  243.     AddRow(new DisplayRowFromString(anyString));
  244. }
  245. bool SequenceDisplay::GetRowTitle(int row, wxString *title, wxColour *color) const
  246. {
  247.     const DisplayRow *displayRow = rows[row];
  248.     const DisplayRowFromString *strRow = dynamic_cast<const DisplayRowFromString*>(displayRow);
  249.     if (strRow && !strRow->title.empty()) {
  250.         *title = strRow->title.c_str();
  251.         color->Set(0,0,0);      // black
  252.         return true;
  253.     }
  254.     const Sequence *sequence = displayRow->GetSequence();
  255.     if (!sequence) return false;
  256.     // set title
  257.     *title = sequence->identifier->ToString().c_str();
  258.     // set color - by object if there's an associated molecule
  259.     const DisplayRowFromAlignment *alnRow = dynamic_cast<const DisplayRowFromAlignment*>(displayRow);
  260.     const Molecule *molecule;
  261.     if (alnRow && (molecule=alnRow->alignment->GetSequenceOfRow(alnRow->row)->molecule) != NULL)
  262.         Vector2wxColor(molecule->parentSet->styleManager->GetObjectColor(molecule), color);
  263.     else
  264.         color->Set(0,0,0);      // ... black otherwise
  265.     return true;
  266. }
  267. bool SequenceDisplay::GetCharacterTraitsAt(int column, int row,
  268.         char *character, wxColour *color, bool *drawBackground,
  269.         wxColour *cellBackgroundColor) const
  270. {
  271.     if (row < 0 || row > rows.size()) {
  272.         WARNINGMSG("SequenceDisplay::GetCharacterTraitsAt() - row out of range");
  273.         return false;
  274.     }
  275.     const DisplayRow *displayRow = rows[row];
  276.     if (column >= displayRow->Width())
  277.         return false;
  278.     Vector colorVec, bgColorVec;
  279.     if (!displayRow->GetCharacterTraitsAt(column,
  280.             (*viewerWindow) ? (*viewerWindow)->GetCurrentJustification() : BlockMultipleAlignment::eLeft,
  281.             character, &colorVec, drawBackground, &bgColorVec))
  282.         return false;
  283.     Vector2wxColor(colorVec, color);
  284.     if (*drawBackground) Vector2wxColor(bgColorVec, cellBackgroundColor);
  285.     return true;
  286. }
  287. void SequenceDisplay::MouseOver(int column, int row) const
  288. {
  289.     if (*viewerWindow) {
  290.         wxString idLoc, status;
  291.         if (row >= 0 && row < rows.size()) {
  292.             const DisplayRow *displayRow = rows[row];
  293.             const Sequence *sequence = NULL;
  294.             // show id if we're in sequence area
  295.             if (column >= 0 && column < displayRow->Width()) {
  296.                 // show title and seqloc
  297.                 int index = -1;
  298.                 if (displayRow->GetSequenceAndIndexAt(column,
  299.                         (*viewerWindow)->GetCurrentJustification(), &sequence, &index)) {
  300.                     if (index >= 0) {
  301.                         wxString title;
  302.                         wxColour color;
  303.                         if (GetRowTitle(row, &title, &color))
  304.                             idLoc.Printf("%s, loc %i", title.c_str(), index + 1); // show one-based numbering
  305.                     }
  306.                 }
  307.                 // show PDB residue number if available (assume resID = index+1)
  308.                 if (sequence && index >= 0 && sequence->molecule) {
  309.                     const Residue *residue = sequence->molecule->residues.find(index + 1)->second;
  310.                     if (residue && residue->namePDB.size() > 0) {
  311.                         wxString n = residue->namePDB.c_str();
  312.                         n = n.Strip(wxString::both);
  313.                         if (n.size() > 0)
  314.                             idLoc = idLoc + " (PDB " + n + ")";
  315.                     }
  316.                 }
  317.                 // show alignment block number and row-wise string
  318.                 const DisplayRowFromAlignment *alnRow =
  319.                     dynamic_cast<const DisplayRowFromAlignment *>(displayRow);
  320.                 if (alnRow) {
  321.                     int blockNum = alnRow->alignment->GetAlignedBlockNumber(column);
  322.                     int rowNum = 0;
  323.                     // get apparent row number (crude!)
  324.                     for (int r=0; r<=row; ++r) {
  325.                         const DisplayRowFromAlignment *aRow =
  326.                             dynamic_cast<const DisplayRowFromAlignment *>(rows[r]);
  327.                         if (aRow && aRow->alignment == alnRow->alignment) ++rowNum;
  328.                     }
  329.                     if (blockNum > 0)
  330.                         status.Printf("Block %i, Row %i", blockNum, rowNum);
  331.                     else
  332.                         status.Printf("Row %i", rowNum);
  333.                     if (alnRow->alignment->GetRowStatusLine(alnRow->row).size() > 0) {
  334.                         status += " ; ";
  335.                         status += alnRow->alignment->GetRowStatusLine(alnRow->row).c_str();
  336.                     }
  337.                 }
  338.             }
  339.             // else show length and description if we're in the title area
  340.             else if (column < 0) {
  341.                 sequence = displayRow->GetSequence();
  342.                 if (sequence) {
  343.                     idLoc.Printf("length %i", sequence->Length());
  344.                     status = sequence->description.c_str();
  345.                 }
  346.             }
  347.         }
  348.         (*viewerWindow)->SetStatusText(idLoc, 0);
  349.         (*viewerWindow)->SetStatusText(status, 1);
  350.     }
  351. }
  352. void SequenceDisplay::UpdateAfterEdit(const BlockMultipleAlignment *forAlignment)
  353. {
  354.     UpdateBlockBoundaryRow(forAlignment);
  355.     UpdateMaxRowWidth(); // in case alignment width has changed
  356.     (*viewerWindow)->viewer->Save();    // make undoable
  357.     (*viewerWindow)->UpdateDisplay(this);
  358.     if ((*viewerWindow)->AlwaysSyncStructures())
  359.         (*viewerWindow)->SyncStructures();
  360. }
  361. bool SequenceDisplay::MouseDown(int column, int row, unsigned int controls)
  362. {
  363.     TRACEMSG("got MouseDown at col:" << column << " row:" << row);
  364.     // process events in title area (launch of browser for entrez page on a sequence)
  365.     if (column < 0 && row >= 0 && row < NRows()) {
  366.         const Sequence *seq = rows[row]->GetSequence();
  367.         if (seq) seq->LaunchWebBrowserWithInfo();
  368.         return false;
  369.     }
  370.     shiftDown = ((controls & ViewableAlignment::eShiftDown) > 0);
  371.     controlDown = ((controls &
  372. #ifdef __WXMAC__
  373.         // on Mac, can't do ctrl-clicks, so use meta instead
  374.         ViewableAlignment::eAltOrMetaDown
  375. #else
  376.         ViewableAlignment::eControlDown
  377. #endif
  378.             ) > 0);
  379.     if (!shiftDown && !controlDown && column == -1)
  380.         GlobalMessenger()->RemoveAllHighlights(true);
  381.     // process events in sequence area
  382.     BlockMultipleAlignment *alignment = GetAlignmentForRow(row);
  383.     if (alignment && column >= 0) {
  384.         // operations for any viewer window
  385.         if ((*viewerWindow)->DoSplitBlock()) {
  386.             if (alignment->SplitBlock(column)) {
  387.                 if (!controlDown) (*viewerWindow)->SplitBlockOff();
  388.                 UpdateAfterEdit(alignment);
  389.             }
  390.             return false;
  391.         }
  392.         if ((*viewerWindow)->DoDeleteBlock()) {
  393.             if (alignment->DeleteBlock(column)) {
  394.                 if (!controlDown) (*viewerWindow)->DeleteBlockOff();
  395.                 UpdateAfterEdit(alignment);
  396.             }
  397.             return false;
  398.         }
  399.         // operations specific to the sequence window
  400.         SequenceViewerWindow *sequenceWindow = dynamic_cast<SequenceViewerWindow*>(*viewerWindow);
  401.         if (sequenceWindow && row >= 0) {
  402.             if (sequenceWindow->DoMarkBlock()) {
  403.                 if (alignment->MarkBlock(column)) {
  404.                     if (!controlDown) sequenceWindow->MarkBlockOff();
  405.                     GlobalMessenger()->PostRedrawSequenceViewer(sequenceWindow->sequenceViewer);
  406.                 }
  407.                 return false;
  408.             }
  409.             if (sequenceWindow->DoProximitySort()) {
  410.                 if (ProximitySort(row)) {
  411.                     sequenceWindow->ProximitySortOff();
  412.                     GlobalMessenger()->PostRedrawSequenceViewer(sequenceWindow->sequenceViewer);
  413.                 }
  414.                 return false;
  415.             }
  416.             if (sequenceWindow->DoRealignRow() || sequenceWindow->DoDeleteRow()) {
  417.                 DisplayRowFromAlignment *selectedRow = dynamic_cast<DisplayRowFromAlignment*>(rows[row]);
  418.                 if (!selectedRow || selectedRow->row == 0 || !selectedRow->alignment) {
  419.                     WARNINGMSG("Can't delete/realign that row...");
  420.                     return false;
  421.                 }
  422.                 if (sequenceWindow->DoRealignRow()) {
  423.                     vector < int > selectedSlaves(1);
  424.                     selectedSlaves[0] = selectedRow->row;
  425.                     sequenceWindow->sequenceViewer->alignmentManager->
  426.                         RealignSlaveSequences(alignment, selectedSlaves);
  427.                     if (!controlDown) sequenceWindow->RealignRowOff();
  428.                     return false;
  429.                 }
  430.                 if (sequenceWindow->DoDeleteRow()) {
  431.                     if (alignment->NRows() <= 2) {
  432.                         WARNINGMSG("Can't delete that row...");
  433.                         return false;
  434.                     }
  435.                     // in case we need to redraw molecule associated with removed row
  436.                     const Molecule *molecule = alignment->GetSequenceOfRow(selectedRow->row)->molecule;
  437.                     // delete row based on alignment row # (not display row #); redraw molecule
  438.                     if (alignment->DeleteRow(selectedRow->row)) {
  439.                         // delete this row from the display, and update higher row #'s
  440.                         RowVector::iterator r, re = rows.end(), toDelete;
  441.                         for (r=rows.begin(); r!=re; ++r) {
  442.                             DisplayRowFromAlignment
  443.                                 *currentARow = dynamic_cast<DisplayRowFromAlignment*>(*r);
  444.                             if (!currentARow)
  445.                                 continue;
  446.                             else if (currentARow->row > selectedRow->row)
  447.                                 (currentARow->row)--;
  448.                             else if (currentARow == selectedRow)
  449.                                 toDelete = r;
  450.                         }
  451.                         delete *toDelete;
  452.                         rows.erase(toDelete);
  453.                         if (!controlDown) sequenceWindow->DeleteRowOff();
  454.                         UpdateAfterEdit(alignment);
  455.                         if (molecule && sequenceWindow->AlwaysSyncStructures())
  456.                             GlobalMessenger()->PostRedrawMolecule(molecule);
  457.                     }
  458.                     return false;
  459.                 }
  460.             }
  461.         }
  462.         // operations specific to the update window
  463.         UpdateViewerWindow *updateWindow = dynamic_cast<UpdateViewerWindow*>(*viewerWindow);
  464.         if (updateWindow && row >= 0) {
  465.             // delete all blocks
  466.             if (updateWindow->DoDeleteAllBlocks()) {
  467.                 if (alignment->DeleteAllBlocks()) {
  468.                     if (!controlDown) updateWindow->DeleteAllBlocksOff();
  469.                     UpdateAfterEdit(alignment);
  470.                 }
  471.                 return false;
  472.             }
  473.             // thread single
  474.             if (updateWindow->DoThreadSingle()) {
  475.                 if (!updateWindow->updateViewer->alignmentManager->GetCurrentMultipleAlignment()) {
  476.                     ERRORMSG("Can't run threader without existing core alignment");
  477.                     return false;
  478.                 }
  479.                 // get threader options
  480.                 globalThreaderOptions.nRandomStarts = Threader::EstimateNRandomStarts(
  481.                     updateWindow->updateViewer->alignmentManager->GetCurrentMultipleAlignment(),
  482.                     alignment);
  483.                 ThreaderOptionsDialog optDialog(updateWindow, globalThreaderOptions);
  484.                 if (optDialog.ShowModal() == wxCANCEL) return false;  // user cancelled
  485.                 if (!optDialog.GetValues(&globalThreaderOptions)) {
  486.                     ERRORMSG("Error retrieving options values from dialog");
  487.                     return false;
  488.                 }
  489.                 updateWindow->updateViewer->alignmentManager->ThreadUpdate(globalThreaderOptions, alignment);
  490.                 updateWindow->ThreadSingleOff();
  491.                 return false;
  492.             }
  493.             // BLAST single
  494.             if (updateWindow->DoBlastSingle()) {
  495.                 updateWindow->updateViewer->BlastUpdate(alignment, false);
  496.                 if (!controlDown) updateWindow->BlastSingleOff();
  497.                 return false;
  498.             }
  499.             // BLAST/PSSM single
  500.             if (updateWindow->DoBlastPSSMSingle()) {
  501.                 updateWindow->updateViewer->BlastUpdate(alignment, true);
  502.                 if (!controlDown) updateWindow->BlastPSSMSingleOff();
  503.                 return false;
  504.             }
  505.             // BLAST neighbor single
  506.             if (updateWindow->DoBlastNeighborSingle()) {
  507.                 updateWindow->updateViewer->BlastNeighbor(alignment);
  508.                 if (!controlDown) updateWindow->BlastNeighborSingleOff();
  509.                 return false;
  510.             }
  511.             // Block align single
  512.             if (updateWindow->DoBlockAlignSingle()) {
  513.                 updateWindow->updateViewer->alignmentManager->BlockAlignUpdate(alignment);
  514.                 if (!controlDown) updateWindow->BlockAlignSingleOff();
  515.                 return false;
  516.             }
  517.             // set region (on slave sequence)
  518.             if (updateWindow->DoSetRegion()) {
  519.                 // dialog uses 1-based sequence locations
  520.                 RegionDialog dialog(updateWindow,
  521.                     alignment->GetSequenceOfRow(1), alignment->alignSlaveFrom + 1, alignment->alignSlaveTo + 1);
  522.                 if (dialog.ShowModal() == wxOK) {
  523.                     int from, to;
  524.                     if (!dialog.GetValues(&from, &to)) {
  525.                         ERRORMSG("RegionDialog returned OK, but values invalid");
  526.                     } else {
  527.                         TRACEMSG("set region (slave): " << from << " to " << to);
  528.                         alignment->alignSlaveFrom = from - 1;
  529.                         alignment->alignSlaveTo = to - 1;
  530.                     }
  531.                     if (!controlDown) updateWindow->SetRegionOff();
  532.                 }
  533.                 return false;
  534.             }
  535.             // merge single
  536.             if (updateWindow->DoMergeSingle()) {
  537.                 AlignmentManager::UpdateMap single;
  538.                 single[alignment] = true;
  539.                 updateWindow->updateViewer->alignmentManager->MergeUpdates(single, false);
  540.                 if (!controlDown) updateWindow->MergeSingleOff();
  541.                 return false;
  542.             }
  543.             // merge neighbor
  544.             if (updateWindow->DoMergeNeighbor()) {
  545.                 AlignmentManager::UpdateMap single;
  546.                 single[alignment] = true;
  547.                 updateWindow->updateViewer->alignmentManager->MergeUpdates(single, true);
  548.                 if (!controlDown) updateWindow->MergeNeighborOff();
  549.                 return false;
  550.             }
  551.             // delete single
  552.             if (updateWindow->DoDeleteSingle()) {
  553.                 updateWindow->updateViewer->DeleteAlignment(alignment);
  554.                 if (!controlDown) updateWindow->DeleteSingleOff();
  555.                 return false;
  556.             }
  557.         }
  558.     }
  559.     return true;
  560. }
  561. void SequenceDisplay::SelectedRectangle(int columnLeft, int rowTop,
  562.     int columnRight, int rowBottom)
  563. {
  564.     TRACEMSG("got SelectedRectangle " << columnLeft << ',' << rowTop << " to "
  565.         << columnRight << ',' << rowBottom);
  566. BlockMultipleAlignment::eUnalignedJustification justification =
  567. (*viewerWindow)->GetCurrentJustification();
  568.     BlockMultipleAlignment *alignment = GetAlignmentForRow(rowTop);
  569.     if (alignment && alignment == GetAlignmentForRow(rowBottom)) {
  570.         if ((*viewerWindow)->DoMergeBlocks()) {
  571.             if (alignment->MergeBlocks(columnLeft, columnRight)) {
  572.                 if (!controlDown) (*viewerWindow)->MergeBlocksOff();
  573.                 UpdateAfterEdit(alignment);
  574.             }
  575.             return;
  576.         }
  577.         if ((*viewerWindow)->DoCreateBlock()) {
  578.             if (alignment->CreateBlock(columnLeft, columnRight, justification)) {
  579.                 if (!controlDown) (*viewerWindow)->CreateBlockOff();
  580.                 UpdateAfterEdit(alignment);
  581.             }
  582.             return;
  583.         }
  584.     }
  585.     if (!shiftDown && !controlDown)
  586.         GlobalMessenger()->RemoveAllHighlights(true);
  587.     for (int i=rowTop; i<=rowBottom; ++i)
  588.         rows[i]->SelectedRange(columnLeft, columnRight, justification, controlDown); // toggle if control down
  589. }
  590. void SequenceDisplay::DraggedCell(int columnFrom, int rowFrom,
  591.     int columnTo, int rowTo)
  592. {
  593.     // special shift-by-one if shift/ctrl click w/ no drag
  594.     if (columnFrom == columnTo && rowFrom == rowTo) {
  595.         if (shiftDown && columnTo > 0)
  596.             --columnTo;
  597.         else if (controlDown && columnTo < maxRowWidth-1)
  598.             ++columnTo;
  599.     }
  600.     TRACEMSG("got DraggedCell " << columnFrom << ',' << rowFrom << " to "
  601.         << columnTo << ',' << rowTo);
  602.     if (rowFrom == rowTo && columnFrom == columnTo) return;
  603.     if (rowFrom != rowTo && columnFrom != columnTo) return;     // ignore diagonal drag
  604.     if (columnFrom != columnTo) {
  605.         BlockMultipleAlignment *alignment = GetAlignmentForRow(rowFrom);
  606.         if (alignment) {
  607.             // process horizontal drag on special block boundary row
  608.             DisplayRowFromString *strRow = dynamic_cast<DisplayRowFromString*>(rows[rowFrom]);
  609.             if (strRow) {
  610.                 wxString title;
  611.                 wxColour ignored;
  612.                 if (GetRowTitle(rowFrom, &title, &ignored) && title == blockBoundaryStringTitle.c_str()) {
  613.                     char ch = strRow->theString[columnFrom];
  614.                     if (ch == blockRightEdgeChar || ch == blockLeftEdgeChar || ch == blockOneColumnChar) {
  615.                         if (alignment->MoveBlockBoundary(columnFrom, columnTo))
  616.                             UpdateAfterEdit(alignment);
  617.                     }
  618.                 }
  619.                 return;
  620.             }
  621.             // process drag on regular row - block row shift
  622.             DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(rows[rowFrom]);
  623.             if (alnRow) {
  624.                 if (alignment->ShiftRow(alnRow->row, columnFrom, columnTo,
  625.                         (*viewerWindow)->GetCurrentJustification()))
  626.                     UpdateAfterEdit(alignment);
  627.                 return;
  628.             }
  629.         }
  630.         return;
  631.     }
  632.     // use vertical drag to reorder row; move rowFrom so that it ends up just before the
  633.     // initial rowTo row
  634.     if (rowFrom == rowTo - 1) return;
  635.     if (rowTo > rowFrom) --rowTo;
  636.     RowVector newRows(rows);
  637.     DisplayRow *row = newRows[rowFrom];
  638.     RowVector::iterator r = newRows.begin();
  639.     int i;
  640.     for (i=0; i<rowFrom; ++i) ++r; // get iterator for position rowFrom
  641.     newRows.erase(r);
  642.     for (r=newRows.begin(), i=0; i<rowTo; ++i) ++r; // get iterator for position rowTo
  643.     newRows.insert(r, row);
  644.     // make sure that the master row of an alignment is still first
  645.     bool masterOK = true;
  646.     for (i=0; i<newRows.size(); ++i) {
  647.         DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(newRows[i]);
  648.         if (alnRow) {
  649.             if (alnRow->row != 0) {
  650.                 WARNINGMSG("The first alignment row must always be the master sequence");
  651.                 masterOK = false;
  652.             }
  653.             break;
  654.         }
  655.     }
  656.     if (masterOK) {
  657.         rows = newRows;
  658.         (*viewerWindow)->UpdateDisplay(this);
  659.         (*viewerWindow)->viewer->Save();   // make this an undoable operation
  660.         GlobalMessenger()->PostRedrawAllSequenceViewers();
  661.     }
  662. }
  663. void SequenceDisplay::RedrawAlignedMolecules(void) const
  664. {
  665.     for (int i=0; i<rows.size(); ++i) {
  666.         const Sequence *sequence = rows[i]->GetSequence();
  667.         if (sequence && sequence->molecule)
  668.             GlobalMessenger()->PostRedrawMolecule(sequence->molecule);
  669.     }
  670. }
  671. DisplayRowFromString * SequenceDisplay::FindBlockBoundaryRow(const BlockMultipleAlignment *forAlignment) const
  672. {
  673.     DisplayRowFromString *blockBoundaryRow = NULL;
  674.     for (int row=0; row<rows.size(); ++row) {
  675.         if ((blockBoundaryRow = dynamic_cast<DisplayRowFromString*>(rows[row])) != NULL) {
  676.             if (blockBoundaryRow->alignment == forAlignment &&
  677.                 blockBoundaryRow->title == blockBoundaryStringTitle)
  678.                 break;
  679.             else
  680.                 blockBoundaryRow = NULL;
  681.         }
  682.     }
  683.     return blockBoundaryRow;
  684. }
  685. static inline DisplayRowFromString * CreateBlockBoundaryRow(BlockMultipleAlignment *forAlignment)
  686. {
  687.     return new DisplayRowFromString("", Vector(0,0,0),
  688.         blockBoundaryStringTitle, true, Vector(0.8,0.8,1), forAlignment);
  689. }
  690. void SequenceDisplay::AddBlockBoundaryRows(void)
  691. {
  692.     if (!IsEditable()) return;
  693.     // find alignment master rows
  694.     int i = 0;
  695.     map < const BlockMultipleAlignment * , bool > doneForAlignment;
  696.     do {
  697.         RowVector::iterator r;
  698.         for (r=rows.begin(), i=0; i<rows.size(); ++r, ++i) {
  699.             DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(*r);
  700.             if (!alnRow || alnRow->row != 0 || !alnRow->alignment ||
  701.                 doneForAlignment.find(alnRow->alignment) != doneForAlignment.end()) continue;
  702.             // insert block row before each master row
  703.             DisplayRowFromString *blockBoundaryRow = CreateBlockBoundaryRow(alnRow->alignment);
  704.             UpdateBlockBoundaryRow(blockBoundaryRow);
  705.             rows.insert(r, blockBoundaryRow);
  706.             doneForAlignment[alnRow->alignment] = true;
  707.             break;  // insert on vector can cause invalidation of iterators, so start over
  708.         }
  709.     } while (i < rows.size());
  710.     if (*viewerWindow) (*viewerWindow)->UpdateDisplay(this);
  711. }
  712. void SequenceDisplay::AddBlockBoundaryRow(BlockMultipleAlignment *forAlignment)
  713. {
  714.     DisplayRowFromString *blockBoundaryRow = CreateBlockBoundaryRow(forAlignment);
  715.     AddRow(blockBoundaryRow);
  716.     UpdateBlockBoundaryRow(blockBoundaryRow);
  717. }
  718. void SequenceDisplay::UpdateBlockBoundaryRow(const BlockMultipleAlignment *forAlignment) const
  719. {
  720.     DisplayRowFromString *blockBoundaryRow;
  721.     if (!IsEditable() || (blockBoundaryRow = FindBlockBoundaryRow(forAlignment)) == NULL ||
  722.         !blockBoundaryRow->alignment) return;
  723.     UpdateBlockBoundaryRow(blockBoundaryRow);
  724. }
  725. void SequenceDisplay::UpdateBlockBoundaryRow(DisplayRowFromString *blockBoundaryRow) const
  726. {
  727.     if (!IsEditable() || !blockBoundaryRow || !blockBoundaryRow->alignment) return;
  728.     int alignmentWidth = blockBoundaryRow->alignment->AlignmentWidth();
  729.     blockBoundaryRow->theString.resize(alignmentWidth);
  730.     // fill out block boundary marker string
  731.     int blockColumn, blockWidth;
  732.     for (int i=0; i<alignmentWidth; ++i) {
  733.         blockBoundaryRow->alignment->GetAlignedBlockPosition(i, &blockColumn, &blockWidth);
  734.         if (blockColumn >= 0 && blockWidth > 0) {
  735.             if (blockWidth == 1)
  736.                 blockBoundaryRow->theString[i] = blockOneColumnChar;
  737.             else if (blockColumn == 0)
  738.                 blockBoundaryRow->theString[i] = blockLeftEdgeChar;
  739.             else if (blockColumn == blockWidth - 1)
  740.                 blockBoundaryRow->theString[i] = blockRightEdgeChar;
  741.             else
  742.                 blockBoundaryRow->theString[i] = blockInsideChar;
  743.         } else
  744.             blockBoundaryRow->theString[i] = ' ';
  745.     }
  746.     if (*viewerWindow) GlobalMessenger()->PostRedrawSequenceViewer((*viewerWindow)->viewer);
  747. }
  748. void SequenceDisplay::RemoveBlockBoundaryRows(void)
  749. {
  750.     vector < bool > toRemove(rows.size(), false);
  751.     int nToRemove = 0;
  752.     for (int row=0; row<rows.size(); ++row) {
  753.         DisplayRowFromString *blockBoundaryRow = dynamic_cast<DisplayRowFromString*>(rows[row]);
  754.         if (blockBoundaryRow && blockBoundaryRow->title == blockBoundaryStringTitle) {
  755.             delete blockBoundaryRow;
  756.             toRemove[row] = true;
  757.             ++nToRemove;
  758.         }
  759.     }
  760.     VectorRemoveElements(rows, toRemove, nToRemove);
  761.     UpdateMaxRowWidth();
  762.     if (*viewerWindow) (*viewerWindow)->UpdateDisplay(this);
  763. }
  764. void SequenceDisplay::GetProteinSequences(SequenceList *seqs) const
  765. {
  766.     seqs->clear();
  767.     for (int row=0; row<rows.size(); ++row) {
  768.         const Sequence *seq = rows[row]->GetSequence();
  769.         if (seq && seq->isProtein)
  770.             seqs->push_back(seq);
  771.     }
  772. }
  773. void SequenceDisplay::GetSequences(const BlockMultipleAlignment *forAlignment, SequenceList *seqs) const
  774. {
  775.     seqs->clear();
  776.     for (int row=0; row<rows.size(); ++row) {
  777.         DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(rows[row]);
  778.         if (alnRow && alnRow->alignment == forAlignment)
  779.             seqs->push_back(alnRow->alignment->GetSequenceOfRow(alnRow->row));
  780.     }
  781. }
  782. void SequenceDisplay::GetRowOrder(
  783.     const BlockMultipleAlignment *forAlignment, vector < int > *slaveRowOrder) const
  784. {
  785.     slaveRowOrder->clear();
  786.     for (int row=0; row<rows.size(); ++row) {
  787.         DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(rows[row]);
  788.         if (alnRow && alnRow->alignment == forAlignment)
  789.             slaveRowOrder->push_back(alnRow->row);
  790.     }
  791. }
  792. // comparison function: if CompareRows(a, b) == true, then row a moves up
  793. typedef bool (*CompareRows)(const DisplayRowFromAlignment *a, const DisplayRowFromAlignment *b);
  794. static bool CompareRowsByIdentifier(const DisplayRowFromAlignment *a, const DisplayRowFromAlignment *b)
  795. {
  796.     return MoleculeIdentifier::CompareIdentifiers(
  797.         a->alignment->GetSequenceOfRow(a->row)->identifier,
  798.         b->alignment->GetSequenceOfRow(b->row)->identifier);
  799. }
  800. static bool CompareRowsByScore(const DisplayRowFromAlignment *a, const DisplayRowFromAlignment *b)
  801. {
  802.     return (a->alignment->GetRowDouble(a->row) > b->alignment->GetRowDouble(b->row));
  803. }
  804. static bool CompareRowsByEValue(const DisplayRowFromAlignment *a, const DisplayRowFromAlignment *b)
  805. {
  806.     return ((a->alignment->GetRowDouble(a->row) >= 0.0 &&
  807.              a->alignment->GetRowDouble(a->row) < b->alignment->GetRowDouble(b->row)) ||
  808.             b->alignment->GetRowDouble(b->row) < 0.0);
  809. }
  810. static bool CompareRowsFloatPDB(const DisplayRowFromAlignment *a, const DisplayRowFromAlignment *b)
  811. {
  812.     return (a->alignment->GetSequenceOfRow(a->row)->identifier->pdbID.size() > 0 &&
  813.             b->alignment->GetSequenceOfRow(b->row)->identifier->pdbID.size() == 0);
  814. }
  815. static bool CompareRowsFloatHighlights(const DisplayRowFromAlignment *a, const DisplayRowFromAlignment *b)
  816. {
  817.     return (GlobalMessenger()->IsHighlightedAnywhere(a->alignment->GetSequenceOfRow(a->row)->identifier) &&
  818.             !GlobalMessenger()->IsHighlightedAnywhere(b->alignment->GetSequenceOfRow(b->row)->identifier));
  819. }
  820. static Threader::GeometryViolationsForRow violations;
  821. static bool CompareRowsFloatGV(const DisplayRowFromAlignment *a, const DisplayRowFromAlignment *b)
  822. {
  823.     return (violations[a->row].size() > 0 && violations[b->row].size() == 0);
  824. }
  825. static CompareRows rowComparisonFunction = NULL;
  826. void SequenceDisplay::SortRowsByIdentifier(void)
  827. {
  828.     rowComparisonFunction = CompareRowsByIdentifier;
  829.     SortRows();
  830.     (*viewerWindow)->viewer->Save();   // make this an undoable operation
  831. (*viewerWindow)->UpdateDisplay(this);
  832. }
  833. void SequenceDisplay::SortRowsByThreadingScore(double weightPSSM)
  834. {
  835.     if (!CalculateRowScoresWithThreader(weightPSSM)) return;
  836.     rowComparisonFunction = CompareRowsByScore;
  837.     SortRows();
  838.     TRACEMSG("sorted rows");
  839.     (*viewerWindow)->viewer->Save();   // make this an undoable operation
  840. (*viewerWindow)->UpdateDisplay(this);
  841. }
  842. void SequenceDisplay::FloatPDBRowsToTop(void)
  843. {
  844.     rowComparisonFunction = CompareRowsFloatPDB;
  845.     SortRows();
  846.     (*viewerWindow)->viewer->Save();   // make this an undoable operation
  847. (*viewerWindow)->UpdateDisplay(this);
  848. }
  849. void SequenceDisplay::FloatHighlightsToTop(void)
  850. {
  851.     rowComparisonFunction = CompareRowsFloatHighlights;
  852.     SortRows();
  853.     (*viewerWindow)->viewer->Save();   // make this an undoable operation
  854. (*viewerWindow)->UpdateDisplay(this);
  855. }
  856. void SequenceDisplay::FloatGVToTop(void)
  857. {
  858.     DisplayRowFromAlignment *alnRow = NULL;
  859.     for (int row=0; row<rows.size(); ++row) {
  860.         alnRow = dynamic_cast<DisplayRowFromAlignment*>(rows[row]);
  861.         if (alnRow)
  862.             break;
  863.     }
  864.     if (!alnRow) {
  865.         ERRORMSG("SequenceDisplay::FloatGVToTop() - can't get alignment");
  866.         return;
  867.     }
  868.     if ((*viewerWindow)->viewer->alignmentManager->threader->
  869.             GetGeometryViolations(alnRow->alignment, &violations) == 0)
  870.         return;
  871.     if (!(*viewerWindow)->menuBar->IsChecked(ViewerWindowBase::MID_SHOW_GEOM_VLTNS))
  872.         (*viewerWindow)->Command(ViewerWindowBase::MID_SHOW_GEOM_VLTNS);
  873.     rowComparisonFunction = CompareRowsFloatGV;
  874.     SortRows();
  875.     (*viewerWindow)->viewer->Save();   // make this an undoable operation
  876.     (*viewerWindow)->UpdateDisplay(this);
  877. }
  878. void SequenceDisplay::SortRowsBySelfHit(void)
  879. {
  880.     // get alignment
  881.     for (int row=0; row<rows.size(); ++row) {
  882.         DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(rows[row]);
  883.         if (alnRow) {
  884.             // do self-hit calculation
  885.             (*viewerWindow)->viewer->CalculateSelfHitScores(alnRow->alignment);
  886.             // then sort by score
  887.             rowComparisonFunction = CompareRowsByEValue;
  888.             SortRows();
  889. (*viewerWindow)->viewer->Save();   // make this an undoable operation
  890. (*viewerWindow)->UpdateDisplay(this);
  891.             break;
  892.         }
  893.     }
  894. }
  895. void SequenceDisplay::SortRows(void)
  896. {
  897.     if (!rowComparisonFunction) {
  898.         ERRORMSG("SequenceDisplay::SortRows() - must first set comparison function");
  899.         return;
  900.     }
  901.     // to simplify sorting, construct list of slave rows only
  902.     vector < DisplayRowFromAlignment * > slaves;
  903.     int row;
  904.     for (row=0; row<rows.size(); ++row) {
  905.         DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(rows[row]);
  906.         if (alnRow && alnRow->row > 0)
  907.             slaves.push_back(alnRow);
  908.     }
  909.     // do the sort
  910.     stable_sort(slaves.begin(), slaves.end(), rowComparisonFunction);
  911.     rowComparisonFunction = NULL;
  912.     // recreate the row list with new order
  913.     RowVector newRows(rows.size());
  914.     int nSlaves = 0;
  915.     for (row=0; row<rows.size(); ++row) {
  916.         DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(rows[row]);
  917.         if (alnRow && alnRow->row > 0)
  918.             newRows[row] = slaves[nSlaves++];   // put sorted slaves in place
  919.         else
  920.             newRows[row] = rows[row];           // leave other rows in original order
  921.     }
  922.     if (nSlaves == slaves.size())   // sanity check
  923.         rows = newRows;
  924.     else
  925.         ERRORMSG("SequenceDisplay::SortRows() - internal inconsistency");
  926. }
  927. bool SequenceDisplay::ProximitySort(int displayRow)
  928. {
  929.     DisplayRowFromAlignment *keyRow = dynamic_cast<DisplayRowFromAlignment*>(rows[displayRow]);
  930.     if (!keyRow || keyRow->row == 0) return false;
  931.     if (keyRow->alignment->NRows() < 3) return true;
  932.     TRACEMSG("doing Proximity Sort on alignment row " << keyRow->row);
  933.     int row;
  934.     BlockMultipleAlignment::UngappedAlignedBlockList blocks;
  935.     keyRow->alignment->GetUngappedAlignedBlocks(&blocks);
  936.     BlockMultipleAlignment::UngappedAlignedBlockList::const_iterator b, be = blocks.end();
  937.     const Sequence *seq1 = keyRow->alignment->GetSequenceOfRow(keyRow->row);
  938.     vector < DisplayRowFromAlignment * > sortedByScore;
  939.     // calculate scores for each row based on simple Blosum62 sum of all aligned pairs
  940.     for (row=0; row<rows.size(); ++row) {
  941.         DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(rows[row]);
  942.         if (!alnRow) continue;
  943.         sortedByScore.push_back(alnRow);
  944.         if (alnRow == keyRow) {
  945.             keyRow->alignment->SetRowDouble(keyRow->row, kMax_Double);
  946.             keyRow->alignment->SetRowStatusLine(keyRow->row, "(key row)");
  947.         } else {
  948.             const Sequence *seq2 = alnRow->alignment->GetSequenceOfRow(alnRow->row);
  949.             double score = 0.0;
  950.             for (b=blocks.begin(); b!=be; ++b) {
  951.                 const Block::Range
  952.                     *r1 = (*b)->GetRangeOfRow(keyRow->row),
  953.                     *r2 = (*b)->GetRangeOfRow(alnRow->row);
  954.                 for (int i=0; i<(*b)->width; ++i)
  955.                     score += GetBLOSUM62Score(
  956.                         seq1->sequenceString[r1->from + i], seq2->sequenceString[r2->from + i]);
  957.             }
  958.             alnRow->alignment->SetRowDouble(alnRow->row, score);
  959.             wxString str;
  960.             str.Printf("Score vs. key row: %i", (int) score);
  961.             alnRow->alignment->SetRowStatusLine(alnRow->row, str.c_str());
  962.         }
  963.     }
  964.     if (sortedByScore.size() != keyRow->alignment->NRows()) {
  965.         ERRORMSG("SequenceDisplay::ProximitySort() - wrong # rows in sort list");
  966.         return false;
  967.     }
  968.     // sort by these scores
  969.     stable_sort(sortedByScore.begin(), sortedByScore.end(), CompareRowsByScore);
  970.     // find where the master row is in sorted list
  971.     int M;
  972.     for (M=0; M<sortedByScore.size(); ++M) if (sortedByScore[M]->row == 0) break;
  973.     // arrange by proximity to key row
  974.     vector < DisplayRowFromAlignment * > arrangedByProximity(sortedByScore.size(), NULL);
  975.     // add master and key row
  976.     arrangedByProximity[0] = sortedByScore[M];  // move master back to top
  977.     arrangedByProximity[M] = sortedByScore[0];  // move key row to M
  978.     // remove these from sorted list
  979.     vector < bool > toRemove(sortedByScore.size(), false);
  980.     toRemove[M] = toRemove[0] = true;
  981.     VectorRemoveElements(sortedByScore, toRemove, 2);
  982.     // add the rest of the sequences in the sorted list to the arranged list
  983.     int i = 1, j = 1, N, R = 0;
  984.     while (R < sortedByScore.size()) {
  985.         N = M + i*j;    // iterate N = M+1, M-1, M+2, M-2, ...
  986.         j = -j;
  987.         if (j > 0) ++i;
  988.         if (N > 0 && N < arrangedByProximity.size())
  989.             arrangedByProximity[N] = sortedByScore[R++];
  990.     }
  991.     // recreate the row list with new order
  992.     RowVector newRows(rows.size());
  993.     int nNewRows = 0;
  994.     for (row=0; row<rows.size(); ++row) {
  995.         DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(rows[row]);
  996.         if (alnRow)
  997.             newRows[row] = arrangedByProximity[nNewRows++];   // put arranged rows in place
  998.         else
  999.             newRows[row] = rows[row];           // leave other rows in original order
  1000.     }
  1001.     if (nNewRows == arrangedByProximity.size())   // sanity check
  1002.         rows = newRows;
  1003.     else
  1004.         ERRORMSG("SequenceDisplay::ProximitySort() - internal inconsistency");
  1005.     // finally, highlight the key row and scroll approximately there
  1006.     GlobalMessenger()->RemoveAllHighlights(true);
  1007.     GlobalMessenger()->AddHighlights(seq1, 0, seq1->Length() - 1);
  1008.     (*viewerWindow)->ScrollToRow((M - 3) > 0 ? (M - 3) : 0);
  1009.     (*viewerWindow)->viewer->Save();   // make this an undoable operation
  1010. (*viewerWindow)->UpdateDisplay(this);
  1011.     return true;
  1012. }
  1013. bool SequenceDisplay::CalculateRowScoresWithThreader(double weightPSSM)
  1014. {
  1015.     if (isEditable) {
  1016.         SequenceViewer *seqViewer = dynamic_cast<SequenceViewer*>((*viewerWindow)->viewer);
  1017.         if (seqViewer) {
  1018.             seqViewer->alignmentManager->CalculateRowScoresWithThreader(weightPSSM);
  1019.             TRACEMSG("calculated row scores");
  1020.             return true;
  1021.         }
  1022.     }
  1023.     return false;
  1024. }
  1025. void SequenceDisplay::RowsAdded(int nRowsAddedToMultiple, BlockMultipleAlignment *multiple, int alnWhere)
  1026. {
  1027.     if (nRowsAddedToMultiple <= 0) return;
  1028.     // find the last row that's from this multiple
  1029.     int r, nRows = 0, lastAlnRowIndex, displayWhere = -1;
  1030.     DisplayRowFromAlignment *lastAlnRow = NULL;
  1031.     for (r=0; r<rows.size(); ++r) {
  1032.         DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(rows[r]);
  1033.         if (alnRow && alnRow->alignment == multiple) {
  1034.             lastAlnRow = alnRow;
  1035.             lastAlnRowIndex = r;
  1036.             ++nRows;
  1037.             if (alnWhere >= 0 && alnRow->row == alnWhere)
  1038.                 displayWhere = r;  // convert 'where' from alignment row to display row
  1039.         }
  1040.     }
  1041.     if (!lastAlnRow || multiple->NRows() != nRows + nRowsAddedToMultiple) {
  1042.         ERRORMSG("SequenceDisplay::RowsAdded() - inconsistent parameters");
  1043.         return;
  1044.     }
  1045.     int rowToMergeAfter = (displayWhere >= 0) ? displayWhere : lastAlnRowIndex;
  1046.     INFOMSG("adding new row after display row #" << (rowToMergeAfter+1));
  1047.     // move higher rows up to leave space for new rows
  1048.     int nRowsToMove = rows.size() - 1 - rowToMergeAfter;
  1049.     rows.resize(rows.size() + nRowsAddedToMultiple);
  1050.     for (r=0; r<nRowsToMove; ++r)
  1051.         rows[rows.size() - 1 - r] = rows[rows.size() - 1 - r - nRowsAddedToMultiple];
  1052.     // add new rows, assuming new rows to add to the display are from the last rows of the multiple
  1053.     for (r=0; r<nRowsAddedToMultiple; ++r)
  1054.         rows[rowToMergeAfter + 1 + r] = new DisplayRowFromAlignment(
  1055.             multiple->NRows() + r - nRowsAddedToMultiple, multiple);
  1056.     UpdateAfterEdit(multiple);
  1057. }
  1058. void SequenceDisplay::RowsRemoved(const vector < int >& rowsRemoved,
  1059.     const BlockMultipleAlignment *multiple)
  1060. {
  1061.     if (rowsRemoved.size() == 0) return;
  1062.     // first, construct a map of old alignment row numbers -> new row numbers; also do sanity checks
  1063.     int i;
  1064.     vector < int > alnRowNumbers(multiple->NRows() + rowsRemoved.size());
  1065.     vector < bool > removedAlnRows(alnRowNumbers.size(), false);
  1066.     for (i=0; i<alnRowNumbers.size(); ++i) alnRowNumbers[i] = i;
  1067.     for (i=0; i<rowsRemoved.size(); ++i) {
  1068.         if (rowsRemoved[i] < 1 || rowsRemoved[i] >= alnRowNumbers.size()) {
  1069.             ERRORMSG("SequenceDisplay::RowsRemoved() - can't remove row " << removedAlnRows[i]);
  1070.             return;
  1071.         } else
  1072.             removedAlnRows[rowsRemoved[i]] = true;
  1073.     }
  1074.     VectorRemoveElements(alnRowNumbers, removedAlnRows, rowsRemoved.size());
  1075.     map < int, int > oldRowToNewRow;
  1076.     for (i=0; i<alnRowNumbers.size(); ++i) oldRowToNewRow[alnRowNumbers[i]] = i;
  1077.     // then tag rows to remove from display, and update row numbers for rows not removed
  1078.     vector < bool > removeDisplayRows(rows.size(), false);
  1079.     for (i=0; i<rows.size(); ++i) {
  1080.         DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(rows[i]);
  1081.         if (alnRow && alnRow->alignment == multiple) {
  1082.             if (removedAlnRows[alnRow->row]) {
  1083.                 delete rows[i];
  1084.                 removeDisplayRows[i] = true;
  1085.             } else
  1086.                 alnRow->row = oldRowToNewRow[alnRow->row];
  1087.         }
  1088.     }
  1089.     VectorRemoveElements(rows, removeDisplayRows, rowsRemoved.size());
  1090.     UpdateAfterEdit(multiple);
  1091. }
  1092. bool SequenceDisplay::GetDisplayCoordinates(const Molecule *molecule, int seqIndex,
  1093.     BlockMultipleAlignment::eUnalignedJustification justification, int *column, int *row)
  1094. {
  1095.     if (!molecule || seqIndex < 0) return false;
  1096.     int displayRow;
  1097.     const Sequence *seq;
  1098.     // search by Molecule*
  1099.     for (displayRow=0; displayRow<NRows(); ++displayRow) {
  1100.         seq = rows[displayRow]->GetSequence();
  1101.         if (seq && seq->molecule == molecule) {
  1102.             *row = displayRow;
  1103.             const DisplayRowFromAlignment *alnRow = dynamic_cast<DisplayRowFromAlignment*>(rows[displayRow]);
  1104.             if (alnRow) {
  1105.                 *column = alnRow->alignment->GetAlignmentIndex(alnRow->row, seqIndex, justification);
  1106.                 return (*column >= 0);
  1107.             }
  1108.             const DisplayRowFromSequence *seqRow = dynamic_cast<DisplayRowFromSequence*>(rows[displayRow]);
  1109.             if (seqRow && seqIndex >= seqRow->fromIndex && seqIndex <= seqRow->toIndex) {
  1110.                 *column = seqIndex - seqRow->fromIndex;
  1111.                 return true;
  1112.             }
  1113.         }
  1114.     }
  1115.     return false;
  1116. }
  1117. END_SCOPE(Cn3D)
  1118. /*
  1119. * ---------------------------------------------------------------------------
  1120. * $Log: sequence_display.cpp,v $
  1121. * Revision 1000.3  2004/06/01 18:29:04  gouriano
  1122. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.73
  1123. *
  1124. * Revision 1.73  2004/05/21 21:41:39  gorelenk
  1125. * Added PCH ncbi_pch.hpp
  1126. *
  1127. * Revision 1.72  2004/03/15 17:55:06  thiessen
  1128. * prefer prefix vs. postfix ++/-- operators
  1129. *
  1130. * Revision 1.71  2004/02/19 17:05:05  thiessen
  1131. * remove cn3d/ from include paths; add pragma to disable annoying msvc warning
  1132. *
  1133. * Revision 1.70  2003/11/06 19:07:19  thiessen
  1134. * leave show gv's on if on already
  1135. *
  1136. * Revision 1.69  2003/10/20 13:17:15  thiessen
  1137. * add float geometry violations sorting
  1138. *
  1139. * Revision 1.68  2003/07/14 18:37:07  thiessen
  1140. * change GetUngappedAlignedBlocks() param types; other syntax changes
  1141. *
  1142. * Revision 1.67  2003/02/03 19:20:05  thiessen
  1143. * format changes: move CVS Log to bottom of file, remove std:: from .cpp files, and use new diagnostic macros
  1144. *
  1145. * Revision 1.66  2003/01/31 17:18:58  thiessen
  1146. * many small additions and changes...
  1147. *
  1148. * Revision 1.65  2003/01/29 01:41:05  thiessen
  1149. * add merge neighbor instead of merge near highlight
  1150. *
  1151. * Revision 1.64  2003/01/28 21:07:56  thiessen
  1152. * add block fit coloring algorithm; tweak row dragging; fix style bug
  1153. *
  1154. * Revision 1.63  2003/01/27 16:42:24  thiessen
  1155. * remove debugging messages
  1156. *
  1157. * Revision 1.62  2003/01/27 15:52:22  thiessen
  1158. * merge after highlighted row; show rejects; trim rejects from new reject list
  1159. *
  1160. * Revision 1.61  2003/01/23 20:03:05  thiessen
  1161. * add BLAST Neighbor algorithm
  1162. *
  1163. * Revision 1.60  2002/10/13 22:58:08  thiessen
  1164. * add redo ability to editor
  1165. *
  1166. * Revision 1.59  2002/09/16 21:24:58  thiessen
  1167. * add block freezing to block aligner
  1168. *
  1169. * Revision 1.58  2002/09/05 18:38:57  thiessen
  1170. * add sort by highlights
  1171. *
  1172. * Revision 1.57  2002/08/28 20:30:33  thiessen
  1173. * fix proximity sort bug
  1174. *
  1175. * Revision 1.56  2002/08/15 22:13:16  thiessen
  1176. * update for wx2.3.2+ only; add structure pick dialog; fix MultitextDialog bug
  1177. *
  1178. * Revision 1.55  2002/08/15 12:57:07  thiessen
  1179. * fix highlight redraw bug
  1180. *
  1181. * Revision 1.54  2002/08/13 20:46:37  thiessen
  1182. * add global block aligner
  1183. *
  1184. * Revision 1.53  2002/07/26 15:28:48  thiessen
  1185. * add Alejandro's block alignment algorithm
  1186. *
  1187. * Revision 1.52  2002/07/23 15:46:50  thiessen
  1188. * print out more BLAST info; tweak save file name
  1189. *
  1190. * Revision 1.51  2002/06/13 14:54:07  thiessen
  1191. * add sort by self-hit
  1192. *
  1193. * Revision 1.50  2002/05/17 19:10:27  thiessen
  1194. * preliminary range restriction for BLAST/PSSM
  1195. *
  1196. * Revision 1.49  2002/05/07 20:22:47  thiessen
  1197. * fix for BLAST/PSSM
  1198. *
  1199. * Revision 1.48  2002/05/02 18:40:25  thiessen
  1200. * do BLAST/PSSM for debug builds only, for testing
  1201. *
  1202. * Revision 1.47  2002/04/26 19:01:00  thiessen
  1203. * fix display delete bug
  1204. *
  1205. * Revision 1.46  2002/04/26 13:46:36  thiessen
  1206. * comment out all blast/pssm methods
  1207. *
  1208. * Revision 1.45  2002/03/28 14:06:02  thiessen
  1209. * preliminary BLAST/PSSM ; new CD startup style
  1210. *
  1211. * Revision 1.44  2002/02/28 19:11:52  thiessen
  1212. * wrap sequences in single-structure mode
  1213. *
  1214. * Revision 1.43  2002/02/22 14:24:01  thiessen
  1215. * sort sequences in reject dialog ; general identifier comparison
  1216. *
  1217. * Revision 1.42  2002/02/21 12:26:30  thiessen
  1218. * fix row delete bug ; remember threader options
  1219. *
  1220. * Revision 1.41  2002/02/19 14:59:39  thiessen
  1221. * add CDD reject and purge sequence
  1222. *
  1223. * Revision 1.40  2002/02/15 15:27:12  thiessen
  1224. * on Mac, use meta for MouseDown events
  1225. *
  1226. * Revision 1.39  2002/02/15 01:02:17  thiessen
  1227. * ctrl+click keeps edit modes
  1228. *
  1229. * Revision 1.38  2002/02/05 18:53:25  thiessen
  1230. * scroll to residue in sequence windows when selected in structure window
  1231. *
  1232. * Revision 1.37  2001/12/05 17:16:56  thiessen
  1233. * fix row insert bug
  1234. *
  1235. * Revision 1.36  2001/11/30 14:02:05  thiessen
  1236. * progress on sequence imports to single structures
  1237. *
  1238. * Revision 1.35  2001/11/27 16:26:08  thiessen
  1239. * major update to data management system
  1240. *
  1241. * Revision 1.34  2001/10/08 00:00:09  thiessen
  1242. * estimate threader N random starts; edit CDD name
  1243. *
  1244. * Revision 1.33  2001/09/27 15:37:59  thiessen
  1245. * decouple sequence import and BLAST
  1246. *
  1247. * Revision 1.32  2001/09/19 22:55:39  thiessen
  1248. * add preliminary net import and BLAST
  1249. *
  1250. * Revision 1.31  2001/08/24 14:54:50  thiessen
  1251. * make status row # order-independent :)
  1252. *
  1253. * Revision 1.30  2001/08/24 14:32:51  thiessen
  1254. * add row # to status line
  1255. *
  1256. * Revision 1.29  2001/08/08 02:25:27  thiessen
  1257. * add <memory>
  1258. *
  1259. * Revision 1.28  2001/07/10 16:39:55  thiessen
  1260. * change selection control keys; add CDD name/notes dialogs
  1261. *
  1262. * Revision 1.27  2001/06/21 02:02:34  thiessen
  1263. * major update to molecule identification and highlighting ; add toggle highlight (via alt)
  1264. *
  1265. * Revision 1.26  2001/06/07 19:05:38  thiessen
  1266. * functional (although incomplete) render settings panel ; highlight title - not sequence - upon mouse click
  1267. *
  1268. * Revision 1.25  2001/06/05 13:21:08  thiessen
  1269. * fix structure alignment list problems
  1270. *
  1271. * Revision 1.24  2001/06/04 14:58:00  thiessen
  1272. * add proximity sort; highlight sequence on browser launch
  1273. *
  1274. * Revision 1.23  2001/06/01 18:07:27  thiessen
  1275. * fix display clone bug
  1276. *
  1277. * Revision 1.22  2001/06/01 14:05:12  thiessen
  1278. * add float PDB sort
  1279. *
  1280. * Revision 1.21  2001/06/01 13:35:58  thiessen
  1281. * add aligned block number to status line
  1282. *
  1283. * Revision 1.20  2001/05/31 18:47:08  thiessen
  1284. * add preliminary style dialog; remove LIST_TYPE; add thread single and delete all; misc tweaks
  1285. *
  1286. * Revision 1.19  2001/05/22 19:09:31  thiessen
  1287. * many minor fixes to compile/run on Solaris/GTK
  1288. *
  1289. * Revision 1.18  2001/05/14 16:04:31  thiessen
  1290. * fix minor row reordering bug
  1291. *
  1292. * Revision 1.17  2001/05/11 02:10:42  thiessen
  1293. * add better merge fail indicators; tweaks to windowing/taskbar
  1294. *
  1295. * Revision 1.16  2001/05/09 17:15:06  thiessen
  1296. * add automatic block removal upon demotion
  1297. *
  1298. * Revision 1.15  2001/05/02 16:35:15  thiessen
  1299. * launch entrez web page on sequence identifier
  1300. *
  1301. * Revision 1.14  2001/04/19 12:58:32  thiessen
  1302. * allow merge and delete of individual updates
  1303. *
  1304. * Revision 1.13  2001/04/18 15:46:53  thiessen
  1305. * show description, length, and PDB numbering in status line
  1306. *
  1307. * Revision 1.12  2001/04/05 22:55:35  thiessen
  1308. * change bg color handling ; show geometry violations
  1309. *
  1310. * Revision 1.11  2001/04/04 00:27:14  thiessen
  1311. * major update - add merging, threader GUI controls
  1312. *
  1313. * Revision 1.10  2001/03/30 14:43:41  thiessen
  1314. * show threader scores in status line; misc UI tweaks
  1315. *
  1316. * Revision 1.9  2001/03/30 03:07:34  thiessen
  1317. * add threader score calculation & sorting
  1318. *
  1319. * Revision 1.8  2001/03/22 00:33:17  thiessen
  1320. * initial threading working (PSSM only); free color storage in undo stack
  1321. *
  1322. * Revision 1.7  2001/03/19 15:50:39  thiessen
  1323. * add sort rows by identifier
  1324. *
  1325. * Revision 1.6  2001/03/13 01:25:05  thiessen
  1326. * working undo system for >1 alignment (e.g., update window)
  1327. *
  1328. * Revision 1.5  2001/03/09 15:49:04  thiessen
  1329. * major changes to add initial update viewer
  1330. *
  1331. * Revision 1.4  2001/03/06 20:49:14  thiessen
  1332. * fix row->alignment bug
  1333. *
  1334. * Revision 1.3  2001/03/06 20:20:50  thiessen
  1335. * progress towards >1 alignment in a SequenceDisplay ; misc minor fixes
  1336. *
  1337. * Revision 1.2  2001/03/02 15:32:52  thiessen
  1338. * minor fixes to save & show/hide dialogs, wx string headers
  1339. *
  1340. * Revision 1.1  2001/03/01 20:15:51  thiessen
  1341. * major rearrangement of sequence viewer code into base and derived classes
  1342. *
  1343. */