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