13 #include "qui/MussaWindow.hpp"
14 #include "qui/mussa_setup_dialog/MussaSetupDialog.hpp"
15 #include "mussa_exceptions.hpp"
21 MussaWindow::MussaWindow(Mussa *analysis_, QWidget *parent) :
26 mussaViewTB("Path Views"),
30 closeAction(0) // initialize one of the pointers to null as a saftey flag
35 //This next setWhatsThis function prevents
36 // a segfault when using WhatsThis feature with
38 //scene->setWhatsThis(tr("Mussa in OpenGL!"));
39 setCentralWidget(&browser);
40 // well updatePosition isn't quite right as we really just need
42 connect(this, SIGNAL(changedAnnotations()), &browser, SLOT(update()));
44 mussaViewTB.addAction(toggleMotifsAction);
46 zoomLabel.setPixmap(QIcon("icons/viewmag.png").pixmap(16, 16));
47 zoomLabel.setToolTip(tr("Zoom"));
48 zoomLabel.setWhatsThis(tr("Zoom magnification factor"));
49 mussaViewTB.addWidget(&zoomLabel);
51 zoomBox.setToolTip(tr("Zoom"));
52 zoomBox.setWhatsThis(tr("Zoom magnification factor"));
53 zoomBox.setRange(1,10000000);
54 mussaViewTB.addWidget(&zoomBox);
55 connect(&zoomBox, SIGNAL(valueChanged(int)),
56 &browser, SLOT(setZoom(int)));
58 threshold.setRange(19, 30);
59 threshold.setThreshold(19);
60 //scene->setClipPlane(20);
61 // FIXME: for when we get the paths drawn at the appropriate depth
62 //connect(&threshold, SIGNAL(thresholdChanged(int)),
63 // this, SLOT(setClipPlane(int)));
64 connect(&threshold, SIGNAL(thresholdChanged(int)),
65 this, SLOT(setSoftThreshold(int)));
66 mussaViewTB.addWidget(&threshold);
68 addToolBar(&mussaViewTB);
70 statusBar()->showMessage("Welcome to mussa", 2000);
74 void MussaWindow::setupActions()
76 // we really don't want to run this more than once.
77 assert (closeAction == 0);
79 // the ever popular about box
80 aboutAction = new QAction(tr("&About"), this);
81 connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
82 aboutAction->setIcon(QIcon("icons/info.png"));
85 closeAction = new QAction(tr("&Close"), this);
86 closeAction->setStatusTip(tr("Close this window"));
87 connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
88 closeAction->setIcon(QIcon("icons/exit.png"));
90 createNewAnalysisAction = new QAction(tr("Define Analysis"), this);
91 connect(createNewAnalysisAction, SIGNAL(triggered()),
92 this, SLOT(createNewAnalysis()));
93 createNewAnalysisAction->setIcon(QIcon("icons/filenew.png"));
95 createSubAnalysisAction = new QAction(tr("Define SubAnalysis"), this);
96 connect(createSubAnalysisAction, SIGNAL(triggered()),
97 this, SLOT(createSubAnalysis()));
99 editMotifsAction = new QAction(tr("Edit Motifs"), this);;
100 connect(editMotifsAction, SIGNAL(triggered()), this, SLOT(editMotifs()));
102 loadMotifListAction = new QAction(tr("Load Motif List"), this);
103 connect(loadMotifListAction, SIGNAL(triggered()),
104 this, SLOT(loadMotifList()));
105 loadMotifListAction->setIcon(QIcon("icons/fileopen.png"));
107 loadMupaAction = new QAction(tr("Load Mussa Parameters"), this);
108 connect(loadMupaAction, SIGNAL(triggered()),
109 this, SLOT(loadMupa()));
110 loadMupaAction->setIcon(QIcon("icons/fileopen.png"));
112 loadSavedAnalysisAction = new QAction(tr("Load &Analysis"), this);
113 connect(loadSavedAnalysisAction, SIGNAL(triggered()),
114 this, SLOT(loadSavedAnalysis()));
115 loadSavedAnalysisAction->setIcon(QIcon("icons/fileopen.png"));
117 saveMotifListAction = new QAction(tr("Save Motifs"), this);
118 connect(saveMotifListAction, SIGNAL(triggered()),
119 this, SLOT(saveMotifList()));
120 saveMotifListAction->setIcon(QIcon("icons/filesave.png"));
122 showMussaViewToolbarAction = new QAction(tr("Show Toolbar"), this);
123 connect(showMussaViewToolbarAction, SIGNAL(triggered()),
124 this, SLOT(showMussaToolbar()));
125 showMussaViewToolbarAction->setCheckable(true);
126 showMussaViewToolbarAction->setChecked(true);
128 toggleMotifsAction = new QAction(tr("Toggle Motifs"), this);
129 connect(toggleMotifsAction, SIGNAL(triggered()),
130 this, SLOT(toggleMotifs()));
131 toggleMotifsAction->setCheckable(true);
132 toggleMotifsAction->setIcon(QIcon("icons/motif_icon.png"));
133 toggleMotifsAction->setWhatsThis(tr("Toggle motif annotations on/off\n\n"
134 "You can load motif annotations via "
135 "'File->Load Motif List' menu option."));
137 //Save pixel map action
138 saveBrowserPixmapAction = new QAction(tr("Save to image..."), this);
139 connect(saveBrowserPixmapAction, (SIGNAL(triggered())),
140 &browser, SLOT(promptSaveBrowserPixmap()));
141 saveBrowserPixmapAction->setIcon(QIcon("icons/image2.png"));
143 viewMussaAlignmentAction = new QAction(tr("View mussa alignment"), this);
144 connect(viewMussaAlignmentAction, SIGNAL(triggered()),
145 this, SLOT(viewMussaAlignment() ));
146 viewMussaAlignmentAction->setWhatsThis(tr("Create a zoomed in window "
147 "showing alignment of the seqcomp "
150 whatsThisAction = QWhatsThis::createAction(this);
151 whatsThisAction->setIcon(QIcon("icons/help.png"));
155 void MussaWindow::setupMainMenu()
157 // we need to run setupActions first
158 assert (closeAction != 0);
161 newMenu = menuBar()->addMenu(tr("&File"));
162 newMenu->addAction(createNewAnalysisAction);
163 newMenu->addAction(loadMupaAction);
164 newMenu->addAction(loadSavedAnalysisAction);
165 //newMenu->addAction(createSubAnalysisAction);
166 newMenu->addSeparator();
167 newMenu->addAction(loadMotifListAction);
168 newMenu->addAction(saveMotifListAction);
169 newMenu->addSeparator();
170 newMenu->addAction(saveBrowserPixmapAction);
171 newMenu->addSeparator();
172 newMenu->addAction(closeAction);
174 newMenu = menuBar()->addMenu(tr("&View"));
175 newMenu->addAction(editMotifsAction);
176 newMenu->addAction(viewMussaAlignmentAction);
177 newMenu->addAction(showMussaViewToolbarAction);
179 newMenu = menuBar()->addMenu(tr("&Help"));
180 newMenu->addAction(whatsThisAction);
181 newMenu->addSeparator();
182 newMenu->addAction(aboutAction);
185 void MussaWindow::about()
187 QString msg("Welcome to Multiple Species Sequence Analysis\n"
188 "(c) 2005-2006 California Institute of Technology\n"
189 "Tristan De Buysscher, Diane Trout\n");
192 msg += QDir::currentPath();
195 msg += (char *)glGetString(GL_VERSION);
197 QMessageBox::about(this, tr("About mussa"), msg);
199 tr("Welcome to Multiple Species Sequence Analysis\n"
200 "(c) 2005-2006 California Institute of Technology\n"
201 "Tristan De Buysscher, Diane Trout\n"));
206 void MussaWindow::createNewAnalysis()
208 MussaSetupDialog *msd = new MussaSetupDialog(this);
211 std::cout << "New mussa exp. defined!\n";
214 std::cout << " Mussa Object at: " << m << "\n";
219 std::cout << "New mussa exp. aborted!\n";
224 void MussaWindow::createSubAnalysis()
229 void MussaWindow::editMotifs()
231 if (motif_editor != 0) {
232 motif_editor->hide();
235 motif_editor = new MotifEditor(analysis);
236 connect(motif_editor, SIGNAL(changedMotifs()),
237 this, SLOT(updateAnnotations()));
238 motif_editor->show();
241 void MussaWindow::loadMotifList()
243 QString caption("Load a motif list");
244 QString filter("Motif list(*.txt *.mtl)");
245 QString path = QFileDialog::getOpenFileName(this,
252 // try to load safely
254 analysis->load_motifs(path.toStdString());
255 } catch (runtime_error e) {
256 QString msg("Unable to load ");
260 QMessageBox::warning(this, "Load Motifs", msg);
262 assert (analysis != 0);
265 void MussaWindow::saveMotifList()
270 void MussaWindow::loadMupa()
272 QString caption("Load a mussa parameter file");
273 QString filter("Mussa Parameters (*.mupa)");
274 QString mupa_path = QFileDialog::getOpenFileName(this,
279 if (mupa_path.isNull())
281 // try to load safely
283 Mussa *m = new Mussa;
284 m->load_mupa_file(mupa_path.toStdString());
285 m->analyze(0, 0, Mussa::TransitiveNway, 0.0);
286 // only switch mussas if we loaded without error
290 } catch (mussa_load_error e) {
291 QString msg("Unable to load ");
295 QMessageBox::warning(this, "Load Parameter", msg);
297 assert (analysis != 0);
300 void MussaWindow::loadSavedAnalysis()
302 QString caption("Load a previously run analysis");
303 QString muway_dir = QFileDialog::getExistingDirectory(this,
305 QDir::currentPath());
307 if (muway_dir.isNull())
309 // try to safely load
311 Mussa *m = new Mussa;
312 m->load(muway_dir.toStdString());
313 // only switch mussas if we loaded without error
317 } catch (mussa_load_error e) {
318 QString msg("Unable to load ");
322 QMessageBox::warning(this, "Load Parameter", msg);
324 assert (analysis != 0);
327 void MussaWindow::setSoftThreshold(int threshold)
329 if (analysis->get_soft_thres() != threshold) {
330 analysis->set_soft_thres(threshold);
337 void MussaWindow::showMussaToolbar()
339 if (mussaViewTB.isVisible())
345 void MussaWindow::toggleMotifs()
350 void MussaWindow::NotImplementedBox()
352 QMessageBox::warning(this, QObject::tr("mussa"), QObject::tr("Not implemented yet"));
355 void MussaWindow::viewMussaAlignment()
357 const set<int>& selected_paths = browser.selectedPaths();
358 if (selected_paths.size() == 0 ) {
359 QMessageBox::warning(this,
360 QObject::tr("mussa"),
361 QObject::tr("you should probably select some paths "
364 MussaAlignedWindow *ma_win = new MussaAlignedWindow(*analysis,
366 connect(this, SIGNAL(changedAnnotations()),
367 ma_win, SLOT(update()));
368 aligned_windows.push_back(ma_win);
373 void MussaWindow::updateAnalysis()
375 cout << "analysis updated" << endl;
376 for (list<MussaAlignedWindow *>::iterator maw_i = aligned_windows.begin();
377 maw_i != aligned_windows.end();
385 const vector<Sequence>& seqs = analysis->sequences();
386 browser.setSequences(seqs, analysis->colorMapper());
389 cout << "browser zoom " << browser.zoom() << endl;
390 zoomBox.setValue(browser.zoom());
393 void MussaWindow::updateAnnotations()
395 // motifs were changed in the sequences by
396 // Mussa::update_sequences_motifs
397 emit changedAnnotations();
401 void MussaWindow::updateLinks()
403 browser.clear_links();
404 bool reversed = false;
405 const NwayPaths& nway = analysis->paths();
407 typedef list<ExtendedConservedPath> conserved_paths;
408 typedef conserved_paths::const_iterator const_conserved_paths_itor;
409 for(const_conserved_paths_itor path_itor = nway.refined_pathz.begin();
410 path_itor != nway.refined_pathz.end();
413 // since we were drawing to the start of a window, and opengl lines
414 // are centered around the two connecting points our lines were slightly
415 // offset. the idea of window_offset is to adjust them to the
416 // right for forward compliment or left for reverse compliment
417 // FIXME: figure out how to unit test these computations
418 //GLfloat window_offset = (path_itor->window_size)/2.0;
420 size_t track_len = path_itor->track_indexes.size();
421 vector<int> normalized_path;
422 normalized_path.reserve(track_len);
423 vector<bool> rc_flags(false, track_len);
424 for (size_t track_i=0; track_i != track_len; ++track_i)
426 int x = path_itor->track_indexes[track_i];
427 // at some point when we modify the pathz data structure to keep
428 // track of the score we can put grab the depth here.
430 // are we reverse complimented?
435 x = -x; // make positive
437 normalized_path.push_back(x);
438 rc_flags.push_back(reversed);
440 browser.link(normalized_path, rc_flags, path_itor->window_size);