13 #include "qui/MussaWindow.hpp"
14 #include "mussa_exceptions.hpp"
18 #include <boost/filesystem/path.hpp>
19 namespace fs = boost::filesystem;
23 MussaWindow::MussaWindow(Mussa *analysis_, QWidget *parent) :
28 mussaViewTB("Path Views"),
31 closeAction(0) // initialize one of the pointers to null as a saftey flag
36 //This next setWhatsThis function prevents
37 // a segfault when using WhatsThis feature with
39 //scene->setWhatsThis(tr("Mussa in OpenGL!"));
40 setCentralWidget(&browser);
41 // well updatePosition isn't quite right as we really just need
43 connect(this, SIGNAL(changedAnnotations()), &browser, SLOT(update()));
45 mussaViewTB.addAction(toggleMotifsAction);
46 mussaViewTB.addWidget(&zoom);
48 connect(&zoom, SIGNAL(valueChanged(double)),
49 &browser, SLOT(setZoom(double)));
51 // threshold range is set in updateAnalysis
53 //scene->setClipPlane(20);
54 // FIXME: for when we get the paths drawn at the appropriate depth
55 //connect(&threshold, SIGNAL(thresholdChanged(int)),
56 // this, SLOT(setClipPlane(int)));
57 connect(&threshold, SIGNAL(thresholdChanged(int)),
58 this, SLOT(setSoftThreshold(int)));
59 mussaViewTB.addWidget(&threshold);
61 addToolBar(&mussaViewTB);
63 statusBar()->showMessage("Welcome to mussa", 2000);
67 MussaWindow::~MussaWindow()
69 if (analysis != 0) delete analysis;
70 aligned_windows.clear();
71 if (motif_editor != 0) delete motif_editor;
73 if (aboutAction != 0) delete aboutAction;
74 if (closeAction != 0) delete closeAction;
75 if (createNewAnalysisAction != 0) delete createNewAnalysisAction;
76 if (createSubAnalysisAction != 0) delete createSubAnalysisAction;
77 if (editMotifsAction != 0) delete editMotifsAction;
78 if (loadMotifListAction != 0) delete loadMotifListAction;
79 if (loadMupaAction != 0) delete loadMupaAction;
80 if (loadSavedAnalysisAction != 0) delete loadSavedAnalysisAction;
81 if (newMussaWindowAction != 0) delete newMussaWindowAction;
82 if (saveMotifListAction != 0) delete saveMotifListAction;
83 if (showMussaViewToolbarAction != 0) delete showMussaViewToolbarAction;
84 if (toggleMotifsAction != 0) delete toggleMotifsAction;
85 if (saveBrowserPixmapAction != 0) delete saveBrowserPixmapAction;
88 void MussaWindow::setAnalysis(Mussa *new_analysis)
90 if (new_analysis != 0) {
91 // only switch mussas if we loaded without error
93 analysis = new_analysis;
98 void MussaWindow::setupActions()
100 // we really don't want to run this more than once.
101 assert (closeAction == 0);
103 // the ever popular about box
104 aboutAction = new QAction(tr("&About"), this);
105 connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
106 aboutAction->setIcon(QIcon(":/icons/info.png"));
109 closeAction = new QAction(tr("&Close"), this);
110 closeAction->setStatusTip(tr("Close this window"));
111 connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
112 closeAction->setIcon(QIcon(":/icons/exit.png"));
114 createNewAnalysisAction = new QAction(tr("Define Analysis"), this);
115 connect(createNewAnalysisAction, SIGNAL(triggered()),
116 this, SLOT(createNewAnalysis()));
117 createNewAnalysisAction->setIcon(QIcon(":/icons/filenew.png"));
119 createSubAnalysisAction = new QAction(tr("Define SubAnalysis"), this);
120 connect(createSubAnalysisAction, SIGNAL(triggered()),
121 this, SLOT(createSubAnalysis()));
123 editMotifsAction = new QAction(tr("Edit Motifs"), this);;
124 connect(editMotifsAction, SIGNAL(triggered()), this, SLOT(editMotifs()));
126 loadMotifListAction = new QAction(tr("Load Motif List"), this);
127 connect(loadMotifListAction, SIGNAL(triggered()),
128 this, SLOT(loadMotifList()));
129 loadMotifListAction->setIcon(QIcon(":/icons/fileopen.png"));
131 loadMupaAction = new QAction(tr("Load Mussa Parameters"), this);
132 connect(loadMupaAction, SIGNAL(triggered()),
133 this, SLOT(loadMupa()));
134 loadMupaAction->setIcon(QIcon(":/icons/fileopen.png"));
136 loadSavedAnalysisAction = new QAction(tr("Load &Analysis"), this);
137 connect(loadSavedAnalysisAction, SIGNAL(triggered()),
138 this, SLOT(loadSavedAnalysis()));
139 loadSavedAnalysisAction->setIcon(QIcon(":/icons/fileopen.png"));
141 newMussaWindowAction = new QAction(tr("&New Mussa Window"), this);
142 newMussaWindowAction->setStatusTip("open another mussa window to allow comparing results");
143 connect(newMussaWindowAction, SIGNAL(triggered()),
144 this, SLOT(newMussaWindow()));
145 newMussaWindowAction->setIcon(QIcon(":/icons/window_new.png"));
147 saveMotifListAction = new QAction(tr("Save Motifs"), this);
148 connect(saveMotifListAction, SIGNAL(triggered()),
149 this, SLOT(saveMotifList()));
150 saveMotifListAction->setIcon(QIcon(":/icons/filesave.png"));
152 showMussaViewToolbarAction = new QAction(tr("Show Toolbar"), this);
153 connect(showMussaViewToolbarAction, SIGNAL(triggered()),
154 this, SLOT(showMussaToolbar()));
155 showMussaViewToolbarAction->setCheckable(true);
156 showMussaViewToolbarAction->setChecked(true);
158 toggleMotifsAction = new QAction(tr("Toggle Motifs"), this);
159 connect(toggleMotifsAction, SIGNAL(triggered()),
160 this, SLOT(toggleMotifs()));
161 toggleMotifsAction->setCheckable(true);
162 toggleMotifsAction->setIcon(QIcon(":/icons/motif_icon.png"));
163 toggleMotifsAction->setWhatsThis(tr("Toggle motif annotations on/off\n\n"
164 "You can load motif annotations via "
165 "'File->Load Motif List' menu option."));
167 //Save pixel map action
168 saveBrowserPixmapAction = new QAction(tr("Save to image..."), this);
169 connect(saveBrowserPixmapAction, (SIGNAL(triggered())),
170 &browser, SLOT(promptSaveBrowserPixmap()));
171 saveBrowserPixmapAction->setIcon(QIcon(":/icons/image2.png"));
173 viewMussaAlignmentAction = new QAction(tr("View mussa alignment"), this);
174 connect(viewMussaAlignmentAction, SIGNAL(triggered()),
175 this, SLOT(viewMussaAlignment() ));
176 viewMussaAlignmentAction->setWhatsThis(tr("Create a zoomed in window "
177 "showing alignment of the seqcomp "
180 whatsThisAction = QWhatsThis::createAction(this);
181 whatsThisAction->setIcon(QIcon(":/icons/help.png"));
185 void MussaWindow::setupMainMenu()
187 // we need to run setupActions first
188 assert (closeAction != 0);
191 newMenu = menuBar()->addMenu(tr("&File"));
192 newMenu->addAction(newMussaWindowAction);
193 newMenu->addAction(createNewAnalysisAction);
194 newMenu->addAction(loadMupaAction);
195 newMenu->addAction(loadSavedAnalysisAction);
196 //newMenu->addAction(createSubAnalysisAction);
197 newMenu->addSeparator();
198 newMenu->addAction(loadMotifListAction);
199 newMenu->addAction(saveMotifListAction);
200 newMenu->addSeparator();
201 newMenu->addAction(saveBrowserPixmapAction);
202 newMenu->addSeparator();
203 newMenu->addAction(closeAction);
205 newMenu = menuBar()->addMenu(tr("&View"));
206 newMenu->addAction(editMotifsAction);
207 newMenu->addAction(viewMussaAlignmentAction);
208 newMenu->addAction(showMussaViewToolbarAction);
210 newMenu = menuBar()->addMenu(tr("&Help"));
211 newMenu->addAction(whatsThisAction);
212 newMenu->addSeparator();
213 newMenu->addAction(aboutAction);
216 void MussaWindow::about()
218 QString msg("Welcome to Multiple Species Sequence Analysis\n"
219 "(c) 2005-2006 California Institute of Technology\n"
220 "Tristan De Buysscher, Diane Trout\n");
223 msg += QDir::currentPath();
226 msg += (char *)glGetString(GL_VERSION);
228 QMessageBox::about(this, tr("About mussa"), msg);
231 void MussaWindow::createNewAnalysis()
234 if (setup_analysis_dialog.exec()) {
236 m = setup_analysis_dialog.getMussa();
239 std::cout << "New mussa exp. aborted!\n";
241 } catch(mussa_error e) {
242 QString msg(e.what());
243 QMessageBox::warning(this, tr("Create New Analysis"), msg);
247 void MussaWindow::createSubAnalysis()
252 void MussaWindow::editMotifs()
254 if (motif_editor != 0) {
255 motif_editor->hide();
258 motif_editor = new MotifEditor(analysis);
259 connect(motif_editor, SIGNAL(changedMotifs()),
260 this, SLOT(updateAnnotations()));
261 motif_editor->show();
264 void MussaWindow::loadMotifList()
266 QString caption("Load a motif list");
267 QString filter("Motif list(*.txt *.mtl)");
268 QString path = QFileDialog::getOpenFileName(this,
275 // try to load safely
277 fs::path converted_path(path.toStdString(), fs::native);
278 analysis->load_motifs(converted_path);
279 } catch (runtime_error e) {
280 QString msg("Unable to load ");
284 QMessageBox::warning(this, "Load Motifs", msg);
286 assert (analysis != 0);
289 void MussaWindow::saveMotifList()
294 void MussaWindow::loadMupa()
296 QString caption("Load a mussa parameter file");
297 QString filter("Mussa Parameters (*.mupa)");
298 QString mupa_path = QFileDialog::getOpenFileName(this,
303 if (mupa_path.isNull())
305 // try to load safely
307 Mussa *m = new Mussa;
308 fs::path converted_path(mupa_path.toStdString(), fs::native);
309 m->load_mupa_file(converted_path);
310 m->analyze(0, 0, Mussa::TransitiveNway, 0.0);
312 } catch (mussa_load_error e) {
313 QString msg("Unable to load ");
317 QMessageBox::warning(this, "Load Parameter", msg);
319 assert (analysis != 0);
322 void MussaWindow::loadSavedAnalysis()
324 QString caption("Load a previously run analysis");
325 QString muway_dir = QFileDialog::getExistingDirectory(this,
327 QDir::currentPath());
329 if (muway_dir.isNull())
331 // try to safely load
333 Mussa *m = new Mussa;
334 fs::path converted_path(muway_dir.toStdString(), fs::native);
335 m->load(converted_path);
336 // only switch mussas if we loaded without error
338 } catch (mussa_load_error e) {
339 QString msg("Unable to load ");
343 QMessageBox::warning(this, "Load Parameter", msg);
345 assert (analysis != 0);
348 void MussaWindow::newMussaWindow()
350 Mussa *a = new Mussa();
351 MussaWindow *win = new MussaWindow(a);
355 void MussaWindow::setSoftThreshold(int threshold)
357 if (analysis->get_soft_thres() != threshold) {
358 analysis->set_soft_thres(threshold);
365 void MussaWindow::showMussaToolbar()
367 if (mussaViewTB.isVisible())
373 void MussaWindow::toggleMotifs()
378 void MussaWindow::NotImplementedBox()
380 QMessageBox::warning(this, QObject::tr("mussa"), QObject::tr("Not implemented yet"));
383 void MussaWindow::viewMussaAlignment()
385 const set<int>& selected_paths = browser.selectedPaths();
386 if (selected_paths.size() == 0 ) {
387 QMessageBox::warning(this,
388 QObject::tr("mussa"),
389 QObject::tr("you should probably select some paths "
392 MussaAlignedWindow *ma_win = new MussaAlignedWindow(*analysis,
394 connect(this, SIGNAL(changedAnnotations()),
395 ma_win, SLOT(update()));
396 aligned_windows.push_back(ma_win);
401 void MussaWindow::updateAnalysis()
403 threshold.setRange(analysis->get_threshold(),analysis->get_window());
404 for (list<MussaAlignedWindow *>::iterator maw_i = aligned_windows.begin();
405 maw_i != aligned_windows.end();
413 const vector<Sequence>& seqs = analysis->sequences();
414 browser.setSequences(seqs, analysis->colorMapper());
417 zoom.setValue(browser.zoom());
420 void MussaWindow::updateAnnotations()
422 // motifs were changed in the sequences by
423 // Mussa::update_sequences_motifs
424 emit changedAnnotations();
428 void MussaWindow::updateLinks()
430 browser.clear_links();
431 bool reversed = false;
432 const NwayPaths& nway = analysis->paths();
434 typedef list<ExtendedConservedPath> conserved_paths;
435 typedef conserved_paths::const_iterator const_conserved_paths_itor;
436 for(const_conserved_paths_itor path_itor = nway.refined_pathz.begin();
437 path_itor != nway.refined_pathz.end();
440 // since we were drawing to the start of a window, and opengl lines
441 // are centered around the two connecting points our lines were slightly
442 // offset. the idea of window_offset is to adjust them to the
443 // right for forward compliment or left for reverse compliment
444 // FIXME: figure out how to unit test these computations
445 //GLfloat window_offset = (path_itor->window_size)/2.0;
447 size_t track_len = path_itor->track_indexes.size();
448 vector<int> normalized_path;
449 normalized_path.reserve(track_len);
450 vector<bool> rc_flags(false, track_len);
451 for (size_t track_i=0; track_i != track_len; ++track_i)
453 int x = path_itor->track_indexes[track_i];
454 // at some point when we modify the pathz data structure to keep
455 // track of the score we can put grab the depth here.
457 // are we reverse complimented?
465 normalized_path.push_back(x);
466 rc_flags.push_back(reversed);
468 browser.link(normalized_path, rc_flags, path_itor->window_size);