define window for showing a mussa alignment
authorDiane Trout <diane@caltech.edu>
Sat, 18 Mar 2006 02:01:58 +0000 (02:01 +0000)
committerDiane Trout <diane@caltech.edu>
Sat, 18 Mar 2006 02:01:58 +0000 (02:01 +0000)
Create a new window to hold the mussa sequence alignment. (aka
show all the sequences lined up at a starting point with lines connecting
base pairs.)

(This also fixes a bug I introduced into the fltk version of mussa back
when I changed paths from just being a vector of ints into an actual
class.)

I still need to actually allow the user to pick the aligned path and show
the conserved base pairs.

16 files changed:
alg/conserved_path.cpp
alg/conserved_path.hpp
alg/glseqbrowser.cpp
alg/glseqbrowser.hpp
alg/test/test_conserved_path.cpp
gui/ConnView.cpp
gui/SeqView.cpp
gui/SeqWindow.cpp
mussagl.pro
qui/MussaAlignedWindow.cpp [new file with mode: 0644]
qui/MussaAlignedWindow.hpp [new file with mode: 0644]
qui/MussaWindow.cpp
qui/MussaWindow.hpp
qui/seqbrowser/SequenceBrowser.hpp
qui/seqbrowser/SequenceBrowserWidget.cpp
qui/seqbrowser/SequenceBrowserWidget.hpp

index af2a4a01e1b7392cab10e9bc90eae0ae9b2d725d..56253c9bc6fa5948d5128ca06441c124ff4cf6a6 100644 (file)
@@ -22,7 +22,7 @@ ConservedPath::ConservedPath(double s, ConservedPath::path_type path)
     track_indexes(path)
 {
 }
+
 void ConservedPath::clear()
 {
   score = 0.0;
@@ -126,6 +126,22 @@ bool ConservedPath::nextTo(const ConservedPath& next) const
   return true;
 }
 
+vector<bool> ConservedPath::reverseComplimented() const
+{
+  vector<bool> reversed;
+  for (ConservedPath::const_iterator this_itor = begin(); 
+       this_itor != end(); 
+       ++this_itor)
+  {
+    if (*this_itor < 0) 
+      reversed.push_back(true);
+    else
+      reversed.push_back(false);
+  }
+  return reversed;
+
+}
+
 /////////////////////
 ExtendedConservedPath::ExtendedConservedPath()
   : ConservedPath(),
index f5f49533846d3ce428781b654012b8447b9740b2..17f1bb7ff053064a8ac8f441fa682f4546d29ece 100644 (file)
@@ -36,6 +36,8 @@ struct ConservedPath
    *  that definition may not properly track reverse compliment
    */
   bool nextTo(const ConservedPath& next) const;
+  //! indicate which elements of the path are reversed
+  std::vector<bool> reverseComplimented() const;
 
   //! either number of conserved bases or average entropy
   double score;
index cb6b0e3b0633c12d7306e6bfabfb7c29acc82844..70637a0dae60a12df2af47015545ec81ed79d927 100644 (file)
@@ -76,8 +76,8 @@ void GlSeqBrowser::processSelection(GLuint hits, GLuint buffer[], GLuint bufsize
   GLuint pair_key_0 = 0;
   GLuint pair_key_1 = 0;
 
-  selectedPaths.clear();
-  selectedTracks.clear();
+  selected_paths.clear();
+  selected_tracks.clear();
 
   std::cout << "hits = " << hits << std::endl;
   ptr = (GLuint *) buffer;
@@ -104,7 +104,7 @@ void GlSeqBrowser::processSelection(GLuint hits, GLuint buffer[], GLuint bufsize
             psm_i = path_segments[path_index].find(k);
             if (psm_i != path_segments[path_index].end()) {
               Segment &seg = psm_i->second;
-              selectedPaths.insert(seg.path_ids.begin(), seg.path_ids.end());
+              selected_paths.insert(seg.path_ids.begin(), seg.path_ids.end());
             }
             // else something else is wrong
           } else {
@@ -116,7 +116,7 @@ void GlSeqBrowser::processSelection(GLuint hits, GLuint buffer[], GLuint bufsize
           break;
         case MussaTrack:
           objid = *ptr++; ++consumed_names;
-          selectedTracks.insert(objid);
+          selected_tracks.insert(objid);
         break;
         default:
           cout << "unknown type " << objtype << " ";
@@ -317,6 +317,11 @@ GlSeqBrowser::link(const vector<int>& path, const vector<bool>& rc, int length)
   ++pathid;
 }
 
+const set<int>& GlSeqBrowser::selectedPaths() const
+{
+  return selected_paths;
+}
+
 void GlSeqBrowser::update_viewport(float center, int new_zoom)
 {
   float max_width = max_ortho.width();
@@ -429,18 +434,18 @@ void GlSeqBrowser::draw_segments() const
       const Segment &s = psm_i->second;
       // need to do something so we can detect our selection
       vector<int> selected;
-      set_intersection(selectedPaths.begin(), selectedPaths.end(),
+      set_intersection(selected_paths.begin(), selected_paths.end(),
                        s.path_ids.begin(), s.path_ids.end(),
                        back_inserter(selected));
 
       if (not s.reversed) {
-        if (selectedPaths.size() == 0 or selected.size() > 0) {
+        if (selected_paths.size() == 0 or selected.size() > 0) {
           glColor3f(1.0, 0.0, 0.0);
         } else {
           glColor3f(1.0, 0.8, 0.8);
         }
       } else { 
-        if (selectedPaths.size() == 0 or selected.size() > 0) {
+        if (selected_paths.size() == 0 or selected.size() > 0) {
           glColor3f(0.0, 0.0, 1.0);
         } else {
           glColor3f(0.8, 0.8, 1.0);
index fa337a5a25ee9f6665e1113a9d705a85b8e0c123..af7efdc78d3b3630b195ce05b89aa0be4548a16d 100644 (file)
@@ -58,6 +58,8 @@ public:
   void clear_links();
   //! define a path
   void link(const std::vector<int>& path, const std::vector<bool>& isRC, int length);
+  //! returns the index of pathids based on order added by link
+  const std::set<int>& selectedPaths() const;
 
   //! Provide a logical name for a type discriminator for our glName stack
   enum FeatureType { MussaTrack, MussaSegment };
@@ -151,9 +153,9 @@ protected:
   //! true if we have a selection
   bool selectedMode;
   //! indicate which paths are selected
-  std::set<int> selectedPaths;
+  std::set<int> selected_paths;
   //! which track is selected (it only makes sense to have one track selected).
-  std::set<int> selectedTracks;
+  std::set<int> selected_tracks;
 
 };
 #endif
index b28c63573f63bde8d86a3e4e433ff199b9ec1954..ec1b54cde5fec5a872ea2819d10d7539e31045a6 100644 (file)
@@ -63,6 +63,26 @@ BOOST_AUTO_TEST_CASE ( conserved_path_vector )
   BOOST_CHECK_EQUAL( cp.size(), 1 );
 }
 
+// does the reverse compliment test work?
+BOOST_AUTO_TEST_CASE ( conserved_path_reverse_compliment ) 
+{
+  vector<int> path;
+  path += 3,4,-5,1; // magic from boost assign
+
+  ConservedPath cp1(10, path);
+  vector<bool> reversed = cp1.reverseComplimented();
+
+  BOOST_CHECK_EQUAL( path.size(), reversed.size());
+  vector<int>::iterator path_i = path.begin();
+  vector<bool>::iterator reversed_i = reversed.begin();
+  for(; path_i != path.end() and reversed_i != reversed.end(); 
+      ++path_i, ++reversed_i)
+  {
+    // if we're less than zero our reversed flag should be true
+    BOOST_CHECK_EQUAL( *path_i < 0, *reversed_i);
+  }
+}
+
 BOOST_AUTO_TEST_CASE ( extended_conserved_path_simple ) 
 {
   vector<int> path;
index a25d6324f729c06253ddf391ffd5c5c50613e490..b6ba9468a1d5263cb31deb4095433d460c633b53 100644 (file)
@@ -623,8 +623,7 @@ ConnView::spawnSeq()
     {
       if (*highlight_i)
       {
-        ExtendedConservedPath& a_path = *pathz_i;
-        selected_paths.push_back(a_path);
+        selected_paths.push_back(*pathz_i);
       }
       ++highlight_i;
     }
index 24f7819cbbca0cdef288f6fd1bdc103d1d50fbc4..419d21e2d887ae70b9709a14a8c2bf56c81de1d2 100644 (file)
@@ -24,7 +24,6 @@ SeqView::setup(string name, int sq_num,
                vector<fltk_motif> *some_motifs)
 {
   int seq_i;
-  list<ExtendedConservedPath >::iterator pathz_i;
 
   analysis_name = name;
   seq_num = sq_num;
@@ -46,7 +45,9 @@ SeqView::setup(string name, int sq_num,
   for(seq_i = 0; seq_i < seq_num; ++seq_i)
     raw_sequence.push_back( (*S)[seq_i].get_seq() );
 
-  for(pathz_i = P.begin(); pathz_i != P.end(); ++pathz_i)
+  for(list<ExtendedConservedPath >::iterator pathz_i = P.begin(); 
+      pathz_i != P.end(); 
+      ++pathz_i)
   {
     show_aligns.push_back(true);
   }  
@@ -217,7 +218,6 @@ void
 SeqView::draw_match_lines(double ch_width)
 {
   int i, y_loc;
-  list<ExtendedConservedPath >::iterator pathz_i;
   int i2, i3;
   int x_start, y_start, x_end, y_end;
   int window_length, win_i;
@@ -233,22 +233,16 @@ SeqView::draw_match_lines(double ch_width)
 
 
   align_counter = 0;
-  for(pathz_i = P.begin(); pathz_i != P.end(); ++pathz_i)
+  for(list<ExtendedConservedPath >::iterator pathz_i = P.begin(); 
+      pathz_i != P.end(); 
+      ++pathz_i)
   {
     if (show_aligns[align_counter])
     {
       ExtendedConservedPath& a_path = *pathz_i;
       window_length = a_path.window_size;
-
       // determine which parts of the path are RC relative to first species
-      rc_list.clear();
-      for(i2 = 0; i2 < a_path.size()-1; i2++)
-      {
-        if (a_path[i2] < 0)
-          rc_list.push_back(true);
-        else
-          rc_list.push_back(false);
-      }
+      rc_list = a_path.reverseComplimented();
       
       // loop over each bp in the conserved region for all sequences
       for(win_i = 0; win_i < window_length; win_i++)
@@ -428,7 +422,7 @@ SeqView::align_offsets(int align_num)
     for(i = 0; i < seq_num ; i++)
     {
       //cout << (*pathz_i)[i+1] << endl;
-      seq_align_offsets.push_back( abs((*pathz_i)[i+1]) );
+      seq_align_offsets.push_back( abs((*pathz_i).track_indexes[i]) );
       // for testing purposes: to see everything in the short test sequences
       //seq_align_offsets.push_back(0);
     }
index 46a73b8bfafba932ae5464b34a294ca3af571058..8578f4974e1d2c0fa11e01807bc5cd77342e5a46 100644 (file)
@@ -48,7 +48,6 @@ SeqWindow::real_show_align_cb(int which_align)
   vector<int> a_path;
   int window_length;
 
-
   cout << "fumish\n";    
   seq_box->toggle_align(which_align);
   seq_box->redraw();
@@ -135,9 +134,9 @@ SeqWindow::SeqWindow(int w, int h, const char* title, int sq_num,
     some_menu_data = new menu_align_data_bundle;
     some_menu_data->swm_ptr = this;
     some_menu_data->which_align = align_number;
-    align_id_ostr << (*align_iter)[0] << ": ";
-    for(i = 1; i <= seq_num; i++)
-      align_id_ostr << (*align_iter)[i] << ", ";
+    align_id_ostr << (*align_iter).window_size << ": ";
+    for(i = 0; i != seq_num; i++)
+      align_id_ostr << (*align_iter).track_indexes[i] << ", ";
     align_id_string = align_id_ostr.str();
     choose_align_menu->add((const char*)align_id_string.c_str(), 0, 
                            (Fl_Callback *) set_align_cb, 
@@ -151,13 +150,6 @@ SeqWindow::SeqWindow(int w, int h, const char* title, int sq_num,
     ++align_iter;
   }
 
-  /*
-  show_align_menu->add("f&ee"); 
-  show_align_menu->add("f&ie"); 
-  show_align_menu->add("f&oe"); 
-  show_align_menu->add("f&um"); 
-  */
-
   Fl_Button *test_but = new Fl_Button(375, 2, 150, 30, "Toggle Motifs");
   test_but->color(FL_WHITE,FL_BLUE);
   test_but->box(FL_BORDER_BOX);
@@ -178,29 +170,3 @@ SeqWindow::SeqWindow(int w, int h, const char* title, int sq_num,
   Fl::visual(FL_DOUBLE|FL_INDEX);
   show();
 }
-
-
-
-/*
-  some_menu_data = new menu_align_data_bundle;
-  some_menu_data->swm_ptr = this;
-  some_menu_data->which_align = 2;
-  choose_align_menu->add("f&ie", FL_ALT+'i', (Fl_Callback *) set_align_cb,
-                  (void*) some_menu_data);
-
-  some_menu_data = new menu_align_data_bundle;
-  some_menu_data->swm_ptr = this;
-  some_menu_data->which_align = 3;
-  choose_align_menu->add("f&oe", FL_ALT+'o', (Fl_Callback *) set_align_cb,
-                  (void*) some_menu_data);
-
-  some_menu_data = new menu_align_data_bundle;
-  some_menu_data->swm_ptr = this;
-  some_menu_data->which_align = 4;
-  choose_align_menu->add("f&um", FL_ALT+'u', (Fl_Callback *) set_align_cb,
-                  (void*) some_menu_data);
-*/
-
-
-
-
index 8c0633564458b588b6a85866149a976d1664f341..72286856245026240aa8838e7bfdd01a8c761f89 100644 (file)
@@ -13,6 +13,7 @@ INCLUDEPATH += . alg qui
 # Input
 HEADERS += mussa_exceptions.hpp \
            qui/MussaWindow.hpp \
+           qui/MussaAlignedWindow.hpp \
            qui/ThresholdWidget.hpp \
            qui/ImageScaler.hpp \
            qui/ImageSaveDialog.hpp \
@@ -33,6 +34,7 @@ HEADERS += mussa_exceptions.hpp \
            alg/sequence.hpp
 SOURCES += mussagl.cpp \
            qui/MussaWindow.cpp \
+           qui/MussaAlignedWindow.cpp \
            qui/ThresholdWidget.cpp \
            qui/ImageScaler.cpp \
            qui/ImageSaveDialog.cpp \
diff --git a/qui/MussaAlignedWindow.cpp b/qui/MussaAlignedWindow.cpp
new file mode 100644 (file)
index 0000000..bd647a5
--- /dev/null
@@ -0,0 +1,21 @@
+#include "qui/MussaAlignedWindow.hpp"
+
+#include <QVBoxLayout>
+
+using namespace std;
+
+MussaAlignedWindow::MussaAlignedWindow(Mussa& m, 
+                                       const set<int>& sel_paths, 
+                                       QWidget *parent)
+  : QWidget(parent),
+    analysis(m),
+    selected_paths(sel_paths)
+    
+{
+  browser.setSequences(analysis.sequences(), analysis.colorMapper());
+
+  QVBoxLayout *layout = new QVBoxLayout;
+  layout->addWidget(&browser);
+  setLayout(layout);
+}
+
diff --git a/qui/MussaAlignedWindow.hpp b/qui/MussaAlignedWindow.hpp
new file mode 100644 (file)
index 0000000..a9cbbfc
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef MUSSA_ALIGNED_WINDOW_H
+#define MUSSA_ALIGNED_WINDOW_H
+
+#include <set>
+
+#include <QWidget>
+#include "alg/mussa.hpp"
+#include "qui/seqbrowser/SequenceBrowserWidget.hpp"
+
+//! Show sequence alignments
+class MussaAlignedWindow : public QWidget
+{
+public:
+  MussaAlignedWindow(Mussa& m, const std::set<int>& sel_paths, QWidget *parent=0);
+
+protected:
+  Mussa &analysis;
+  const std::set<int>& selected_paths;
+
+  SequenceBrowserWidget browser;
+};
+#endif
index f8945c4459d9ae391d60a7655972c629c255de44..8696913d407c88b73c96d7edafe7cc5da7bef166 100644 (file)
@@ -11,6 +11,7 @@
 #include <QWhatsThis>
 
 #include "qui/MussaWindow.hpp"
+#include "qui/MussaAlignedWindow.hpp"
 #include "mussa_exceptions.hpp"
 
 #include <iostream>
@@ -124,14 +125,22 @@ void MussaWindow::setupActions()
                                   "You can load motif annotations via "
                                   "'File->Load Motif List' menu option."));
 
-  whatsThisAction = QWhatsThis::createAction(this);
-  whatsThisAction->setIcon(QIcon("icons/help.png"));
-
   //Save pixel map action
   saveBrowserPixmapAction = new QAction(tr("Save to image..."), this);
   connect(saveBrowserPixmapAction, (SIGNAL(triggered())),
          &browser, SLOT(promptSaveBrowserPixmap()));
   saveBrowserPixmapAction->setIcon(QIcon("icons/image2.png"));
+
+  viewMussaAlignmentAction = new QAction(tr("View mussa alignment"), this);
+  connect(viewMussaAlignmentAction, SIGNAL(triggered()),
+          this, SLOT(viewMussaAlignment() ));
+  viewMussaAlignmentAction->setWhatsThis(tr("Create a zoomed in window "
+                                            "showing alignment of the seqcomp "
+                                            "defined paths"));
+
+  whatsThisAction = QWhatsThis::createAction(this);
+  whatsThisAction->setIcon(QIcon("icons/help.png"));
+
 }
 
 void MussaWindow::setupMainMenu()
@@ -154,6 +163,7 @@ void MussaWindow::setupMainMenu()
   newMenu->addAction(closeAction);
 
   newMenu = menuBar()->addMenu(tr("&View"));
+  newMenu->addAction(viewMussaAlignmentAction);
   newMenu->addAction(showMussaViewToolbarAction);
 
   newMenu = menuBar()->addMenu(tr("&Help"));
@@ -295,6 +305,20 @@ void MussaWindow::NotImplementedBox()
   QMessageBox::warning(this, QObject::tr("mussa"), QObject::tr("Not implemented yet"));
 }      
 
+void MussaWindow::viewMussaAlignment()
+{
+  const set<int>& selected_paths = browser.selectedPaths();
+  if (selected_paths.size() == 0 ) {
+    QMessageBox::warning(this, 
+                         QObject::tr("mussa"),
+                         QObject::tr("you should probably select some paths "
+                                     "first"));
+  } else {
+    QWidget *ma_win = new MussaAlignedWindow(*analysis, selected_paths);
+    ma_win->show();
+  }
+}
+                        
 void MussaWindow::updateAnalysis()
 {
   cout << "analysis updated" << endl;
index 26e16bc097aa8bf6afa3c61c5abb99ac4dc69ed5..d748b0d69525f6ccd60a2f01e26c004875ca52f2 100644 (file)
@@ -48,6 +48,9 @@ public slots:
   void setSoftThreshold(int thres);
 
   void showMussaToolbar();
+
+  //! open new window showing our alignment
+  void viewMussaAlignment();
   
 protected:
   Mussa *analysis;
@@ -68,8 +71,9 @@ protected:
   QAction *saveMotifListAction;
   QAction *showMussaViewToolbarAction;
   QAction *toggleMotifsAction;
-  QAction *whatsThisAction;
   QAction *saveBrowserPixmapAction;
+  QAction *whatsThisAction;
+  QAction *viewMussaAlignmentAction;
 
   //! initialze the actions
   void setupActions();
index ed3da990676e885682d173c3018d09b457e61b35..d77b5d44df6d637f27eb9e2ebb1318724a8c348e 100644 (file)
@@ -7,6 +7,8 @@
 #include <vector>
 #include <GL/gl.h>
 
+#include <set>
+
 #include "alg/mussa.hpp"
 #include "alg/glsequence.hpp"
 #include "alg/glseqbrowser.hpp"
index 215bcd36c490f06469f9af147302e5620fd823e0..8d4f44e6a3155d4dc5b42bfe597e16ebd45c533c 100644 (file)
@@ -90,6 +90,11 @@ void SequenceBrowserWidget::link(const std::vector<int>& path,
   scrollable_browser.browser().link(path, isRC, length);
 }
 
+const std::set<int> SequenceBrowserWidget::selectedPaths() const
+{
+  return scrollable_browser.browser().selectedPaths();
+}
+
 /* This could theoretically be pushed down to some set 
  * of signals and slots connecting SequenceDescriptions and 
  * some signal emitted by the browser's viewportChanged code
index e51f445246d2c60af5f781c127cbc10acd3ca4eb..87f5b282f1fb7a5c6b8a33d310caa417a684426a 100644 (file)
@@ -37,6 +37,8 @@ public:
   void clear_links();
   //! set per species links
   void link(const std::vector<int> &path, const std::vector<bool>& isRC, int length);
+  // return set of pathids defined by order of link calls
+  const std::set<int> selectedPaths() const;
   
 public slots:
   //! set the zoom level of our browser