13 #include "qui/MussaWindow.hpp"
14 #include "mussa_exceptions.hpp"
20 MussaWindow::MussaWindow(Mussa *analysis_, QWidget *parent) :
24 mussaViewTB("Path Views"),
28 closeAction(0) // initialize one of the pointers to null as a saftey flag
33 //This next setWhatsThis function prevents
34 // a segfault when using WhatsThis feature with
36 //scene->setWhatsThis(tr("Mussa in OpenGL!"));
37 setCentralWidget(&browser);
39 mussaViewTB.addAction(toggleMotifsAction);
41 zoomLabel.setPixmap(QIcon("icons/viewmag.png").pixmap(16, 16));
42 zoomLabel.setToolTip(tr("Zoom"));
43 zoomLabel.setWhatsThis(tr("Zoom magnification factor"));
44 mussaViewTB.addWidget(&zoomLabel);
46 zoomBox.setToolTip(tr("Zoom"));
47 zoomBox.setWhatsThis(tr("Zoom magnification factor"));
48 zoomBox.setRange(1,10000000);
49 mussaViewTB.addWidget(&zoomBox);
50 connect(&zoomBox, SIGNAL(valueChanged(int)),
51 &browser, SLOT(setZoom(int)));
53 threshold.setRange(19, 30);
54 threshold.setThreshold(19);
55 //scene->setClipPlane(20);
56 // FIXME: for when we get the paths drawn at the appropriate depth
57 //connect(&threshold, SIGNAL(thresholdChanged(int)),
58 // this, SLOT(setClipPlane(int)));
59 connect(&threshold, SIGNAL(thresholdChanged(int)),
60 this, SLOT(setSoftThreshold(int)));
61 mussaViewTB.addWidget(&threshold);
63 addToolBar(&mussaViewTB);
65 statusBar()->showMessage("Welcome to mussa", 2000);
69 void MussaWindow::setupActions()
71 // we really don't want to run this more than once.
72 assert (closeAction == 0);
74 // the ever popular about box
75 aboutAction = new QAction(tr("&About"), this);
76 connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
77 aboutAction->setIcon(QIcon("icons/info.png"));
80 closeAction = new QAction(tr("&Close"), this);
81 closeAction->setStatusTip(tr("Close this window"));
82 connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
83 closeAction->setIcon(QIcon("icons/exit.png"));
85 createNewAnalysisAction = new QAction(tr("Define Analysis"), this);
86 connect(createNewAnalysisAction, SIGNAL(triggered()),
87 this, SLOT(createNewAnalysis()));
88 createNewAnalysisAction->setIcon(QIcon("icons/filenew.png"));
90 createSubAnalysisAction = new QAction(tr("Define SubAnalysis"), this);
91 connect(createSubAnalysisAction, SIGNAL(triggered()),
92 this, SLOT(createSubAnalysis()));
94 loadMotifListAction = new QAction(tr("Load Motif List"), this);
95 connect(loadMotifListAction, SIGNAL(triggered()),
96 this, SLOT(loadMotifList()));
98 loadMupaAction = new QAction(tr("Load Mussa Parameters"), this);
99 connect(loadMupaAction, SIGNAL(triggered()),
100 this, SLOT(loadMupa()));
102 loadSavedAnalysisAction = new QAction(tr("Load &Analysis"), this);
103 connect(loadSavedAnalysisAction, SIGNAL(triggered()),
104 this, SLOT(loadSavedAnalysis()));
105 loadSavedAnalysisAction->setIcon(QIcon("icons/fileopen.png"));
107 saveMotifListAction = new QAction(tr("Save Motifs"), this);
108 connect(saveMotifListAction, SIGNAL(triggered()),
109 this, SLOT(saveMotifList()));
110 saveMotifListAction->setIcon(QIcon("icons/filesave.png"));
112 showMussaViewToolbarAction = new QAction(tr("Show Toolbar"), this);
113 connect(showMussaViewToolbarAction, SIGNAL(triggered()),
114 this, SLOT(showMussaToolbar()));
115 showMussaViewToolbarAction->setCheckable(true);
116 showMussaViewToolbarAction->setChecked(true);
118 toggleMotifsAction = new QAction(tr("Toggle Motifs"), this);
119 connect(toggleMotifsAction, SIGNAL(triggered()),
120 this, SLOT(toggleMotifs()));
121 toggleMotifsAction->setCheckable(true);
122 toggleMotifsAction->setIcon(QIcon("icons/motif_icon.png"));
123 toggleMotifsAction->setWhatsThis(tr("Toggle motif annotations on/off\n\n"
124 "You can load motif annotations via "
125 "'File->Load Motif List' menu option."));
127 //Save pixel map action
128 saveBrowserPixmapAction = new QAction(tr("Save to image..."), this);
129 connect(saveBrowserPixmapAction, (SIGNAL(triggered())),
130 &browser, SLOT(promptSaveBrowserPixmap()));
131 saveBrowserPixmapAction->setIcon(QIcon("icons/image2.png"));
133 viewMussaAlignmentAction = new QAction(tr("View mussa alignment"), this);
134 connect(viewMussaAlignmentAction, SIGNAL(triggered()),
135 this, SLOT(viewMussaAlignment() ));
136 viewMussaAlignmentAction->setWhatsThis(tr("Create a zoomed in window "
137 "showing alignment of the seqcomp "
140 whatsThisAction = QWhatsThis::createAction(this);
141 whatsThisAction->setIcon(QIcon("icons/help.png"));
145 void MussaWindow::setupMainMenu()
147 // we need to run setupActions first
148 assert (closeAction != 0);
151 newMenu = menuBar()->addMenu(tr("&File"));
152 newMenu->addAction(createNewAnalysisAction);
153 newMenu->addAction(loadMupaAction);
154 newMenu->addAction(loadSavedAnalysisAction);
155 newMenu->addAction(createSubAnalysisAction);
156 newMenu->addSeparator();
157 newMenu->addAction(loadMotifListAction);
158 newMenu->addAction(saveMotifListAction);
159 newMenu->addSeparator();
160 newMenu->addAction(saveBrowserPixmapAction);
161 newMenu->addSeparator();
162 newMenu->addAction(closeAction);
164 newMenu = menuBar()->addMenu(tr("&View"));
165 newMenu->addAction(viewMussaAlignmentAction);
166 newMenu->addAction(showMussaViewToolbarAction);
168 newMenu = menuBar()->addMenu(tr("&Help"));
169 newMenu->addAction(whatsThisAction);
170 newMenu->addSeparator();
171 newMenu->addAction(aboutAction);
174 void MussaWindow::about()
176 QMessageBox::about(this, tr("About mussa"),
177 tr("Welcome to Multiple Species Sequence Analysis\n"
178 "(c) 2005-2006 California Institute of Technology\n"
179 "Tristan De Buysscher, Diane Trout\n"));
182 void MussaWindow::createNewAnalysis()
187 void MussaWindow::createSubAnalysis()
193 void MussaWindow::loadMotifList()
195 QString caption("Load a motif list");
196 QString filter("Motif list(*.txt *.mtl)");
197 QString path = QFileDialog::getOpenFileName(this,
204 // try to load safely
206 analysis->load_motifs(path.toStdString());
207 } catch (runtime_error e) {
208 QString msg("Unable to load ");
212 QMessageBox::warning(this, "Load Motifs", msg);
214 assert (analysis != 0);
217 void MussaWindow::saveMotifList()
222 void MussaWindow::loadMupa()
224 QString caption("Load a mussa parameter file");
225 QString filter("Mussa Parameters (*.mupa)");
226 QString mupa_path = QFileDialog::getOpenFileName(this,
231 if (mupa_path.isNull())
233 // try to load safely
235 Mussa *m = new Mussa;
236 m->load_mupa_file(mupa_path.toStdString());
237 m->analyze(0, 0, Mussa::TransitiveNway, 0.0);
238 // only switch mussas if we loaded without error
242 } catch (mussa_load_error e) {
243 QString msg("Unable to load ");
247 QMessageBox::warning(this, "Load Parameter", msg);
249 assert (analysis != 0);
252 void MussaWindow::loadSavedAnalysis()
254 QString caption("Load a previously run analysis");
255 QString muway_dir = QFileDialog::getExistingDirectory(this,
257 QDir::currentPath());
259 if (muway_dir.isNull())
261 // try to safely load
263 Mussa *m = new Mussa;
264 m->load(muway_dir.toStdString());
265 // only switch mussas if we loaded without error
269 } catch (mussa_load_error e) {
270 QString msg("Unable to load ");
274 QMessageBox::warning(this, "Load Parameter", msg);
276 assert (analysis != 0);
279 void MussaWindow::setSoftThreshold(int threshold)
281 if (analysis->get_soft_thres() != threshold) {
282 analysis->set_soft_thres(threshold);
289 void MussaWindow::showMussaToolbar()
291 if (mussaViewTB.isVisible())
297 void MussaWindow::toggleMotifs()
302 void MussaWindow::NotImplementedBox()
304 QMessageBox::warning(this, QObject::tr("mussa"), QObject::tr("Not implemented yet"));
307 void MussaWindow::viewMussaAlignment()
309 const set<int>& selected_paths = browser.selectedPaths();
310 if (selected_paths.size() == 0 ) {
311 QMessageBox::warning(this,
312 QObject::tr("mussa"),
313 QObject::tr("you should probably select some paths "
316 MussaAlignedWindow *ma_win = new MussaAlignedWindow(*analysis, selected_paths);
317 aligned_windows.push_back(ma_win);
322 void MussaWindow::updateAnalysis()
324 cout << "analysis updated" << endl;
325 for (list<MussaAlignedWindow *>::iterator maw_i = aligned_windows.begin();
326 maw_i != aligned_windows.end();
334 const vector<Sequence>& seqs = analysis->sequences();
335 browser.setSequences(seqs, analysis->colorMapper());
338 cout << "browser zoom " << browser.zoom() << endl;
339 zoomBox.setValue(browser.zoom());
342 void MussaWindow::updateLinks()
344 browser.clear_links();
345 bool reversed = false;
346 const NwayPaths& nway = analysis->paths();
348 typedef list<ExtendedConservedPath> conserved_paths;
349 typedef conserved_paths::const_iterator const_conserved_paths_itor;
350 for(const_conserved_paths_itor path_itor = nway.refined_pathz.begin();
351 path_itor != nway.refined_pathz.end();
354 // since we were drawing to the start of a window, and opengl lines
355 // are centered around the two connecting points our lines were slightly
356 // offset. the idea of window_offset is to adjust them to the
357 // right for forward compliment or left for reverse compliment
358 // FIXME: figure out how to unit test these computations
359 //GLfloat window_offset = (path_itor->window_size)/2.0;
361 size_t track_len = path_itor->track_indexes.size();
362 vector<int> normalized_path;
363 normalized_path.reserve(track_len);
364 vector<bool> rc_flags(false, track_len);
365 for (size_t track_i=0; track_i != track_len; ++track_i)
367 int x = path_itor->track_indexes[track_i];
368 // at some point when we modify the pathz data structure to keep
369 // track of the score we can put grab the depth here.
371 // are we reverse complimented?
376 x = -x; // make positive
378 normalized_path.push_back(x);
379 rc_flags.push_back(reversed);
381 browser.link(normalized_path, rc_flags, path_itor->window_size);