share one instance of the copySelectedSequenceAsFastaAction
[mussa.git] / qui / MussaAlignedWindow.cpp
1 #include <list>
2 #include <vector>
3 #include <sstream>
4
5 #include <QStatusBar>
6 #include <QString>
7 #include <QMenuBar>
8
9 #include "qui/MussaAlignedWindow.hpp"
10 #include "alg/sequence.hpp"
11
12 #include <iostream>
13 using namespace std;
14
15 MussaAlignedWindow::MussaAlignedWindow(Mussa& m, 
16                                        const set<int>& sel_paths, 
17                                        QWidget *parent)
18   : QMainWindow(parent),
19     analysis(m),
20     pick_align_menu(tr("Choose Alignment")),
21     view_align_menu(tr("View Alignment"))
22 {
23   setupActions();
24   browser.setSequences(analysis.sequences(), analysis.colorMapper());
25   setSelectedPaths(m, sel_paths);
26   setAlignment(0);
27   double zoom_level = browser.zoomToSequence();
28   zoom.setValue(zoom_level);
29   computeMatchLines();
30   setupMenus();
31   setupAlignmentMenus();
32   
33   setCentralWidget(&browser);
34
35   addToolBar(&alignTB);
36   alignTB.addWidget(&zoom);
37   
38   connect(&zoom, SIGNAL(valueChanged(double)), 
39           &browser, SLOT(setZoom(double)));
40  
41   ostringstream message;
42   message << "Selected " << selected_paths.size() << " paths";
43   statusBar()->showMessage(message.str().c_str(), 5000);
44   browser.updatePosition();
45 }
46
47 void MussaAlignedWindow::setupActions()
48 {
49   //Save pixel map action
50   saveBrowserPixmapAction = new QAction(tr("Save to image..."), this);
51   connect(saveBrowserPixmapAction, (SIGNAL(triggered())),
52           &browser, SLOT(promptSaveBrowserPixmap()));
53   saveBrowserPixmapAction->setIcon(QIcon(":/icons/image2.png"));
54 }
55
56 void MussaAlignedWindow::setupMenus()
57 {
58   QMenu *newMenu = menuBar()->addMenu(tr("&File"));
59   newMenu->addAction(saveBrowserPixmapAction);
60
61   newMenu = menuBar()->addMenu(tr("&Edit"));
62   newMenu->addAction(&browser.getCopySelectedSequenceAsFastaAction());
63 }
64
65 void MussaAlignedWindow::setupAlignmentMenus()
66 {
67   pick_align_menu.clear();
68   view_align_menu.clear();
69   pick_actions.clear();
70   view_actions.clear();
71
72   for(vector<ConservedPath >::iterator pathz_i=selected_paths.begin(); 
73       pathz_i != selected_paths.end(); 
74       ++pathz_i)
75   {
76     ConservedPath::path_type normalized_path = pathz_i->normalizedIndexes();
77     ostringstream menu_text;
78     menu_text << pathz_i->window_size << ":";
79     ConservedPath::iterator element_i = normalized_path.begin();
80     menu_text << *element_i++;
81     for (;
82          element_i != normalized_path.end();
83          ++element_i)
84     {
85       menu_text << ", ";
86       menu_text << *element_i;
87     }
88     int index = pathz_i - selected_paths.begin();
89     IntAction *pick = new IntAction(QString(menu_text.str().c_str()), index, this);
90     connect(pick, SIGNAL(triggered(int)), this, SLOT(setAlignment(int)));
91     pick_actions.push_back(pick);
92     pick_align_menu.addAction(pick);
93     IntAction *view = new IntAction(QString(menu_text.str().c_str()), index, this);
94     connect(view, SIGNAL(triggered(int)), this, SLOT(toggleViewAlignment(int)));
95     view->setCheckable(true);
96     view->setChecked(true);
97     view_actions.push_back(view);
98     view_align_menu.addAction(view);
99   }
100
101   menuBar()->addMenu(&pick_align_menu);
102   menuBar()->addMenu(&view_align_menu);
103 }
104
105
106 void MussaAlignedWindow::setSelectedPaths(Mussa &m, const set<int>& sel_paths)
107 {
108   // sets are sorted
109   set<int>::iterator sel_i = sel_paths.begin();
110   list<ConservedPath>::const_iterator path_i = m.paths().refined_pathz.begin();
111   list<ConservedPath>::const_iterator path_end = m.paths().refined_pathz.end();
112   size_t path_size = m.paths().refined_pathz.size();
113   size_t pathid=0;
114
115   selected_paths.reserve(sel_paths.size());
116   view_paths.reserve(sel_paths.size());
117   while (pathid != path_size and sel_i != sel_paths.end())
118   {
119     assert (*sel_i >= 0);
120     size_t sel_pathid = (size_t)(*sel_i);
121     if (pathid == sel_pathid) {
122       selected_paths.push_back(*path_i);
123       view_paths.push_back(true);
124       ++pathid;
125       ++path_i;
126       ++sel_i;
127     } else if (pathid < sel_pathid) {
128       ++pathid;
129       ++path_i;
130     } else if (pathid > sel_pathid) {
131       ++sel_i;
132     }
133   }
134 }
135
136 void MussaAlignedWindow::setAlignment(int alignment_index)
137 {
138   if (selected_paths.size() > 0) {
139     browser.centerOnPath(selected_paths[alignment_index].normalizedIndexes());
140   }
141 }
142
143 void MussaAlignedWindow::toggleViewAlignment(int alignment_index)
144 {
145   view_paths[alignment_index]= not view_paths[alignment_index]; 
146   // perhaps it'd be better if we could erase specific sets
147   // of matches instead of erasing them all and recomputing them all
148   // but this is easier
149   computeMatchLines();
150 }
151
152 void MussaAlignedWindow::update()
153 {
154   browser.update();
155 }
156
157 void MussaAlignedWindow::computeMatchLines()
158 {
159   browser.clear_links();
160   
161   // filter out conserved paths
162   list<ConservedPath> filtered_paths;
163   vector<ConservedPath>::iterator path_i = selected_paths.begin();
164   list<ConservedPath::path_type> result;
165   list<vector<bool> > reversed;
166
167   for(vector<ConservedPath>::size_type count = 0; 
168       count != selected_paths.size();
169       ++count, ++path_i)
170   {
171     if (view_paths[count]) 
172       filtered_paths.push_back(*path_i);
173   }
174   analysis.createLocalAlignment(filtered_paths.begin(), 
175                                 filtered_paths.end(),
176                                 result, 
177                                 reversed);
178
179   list<ConservedPath::path_type>::const_iterator result_i = result.begin();
180   list<vector<bool> >::const_iterator reversed_i = reversed.begin();
181   for(int i = 0; i != result.size(); ++i, ++result_i, ++reversed_i)
182   {
183     // make 1 base long links
184     browser.link(*result_i, *reversed_i, 1);
185   }
186 }