13 #include "qui/MussaWindow.hpp"
14 #include "mussa_exceptions.hpp"
20 MussaWindow::MussaWindow(Mussa *analysis_, QWidget *parent) :
24 mussaViewTB("Path Views"),
27 closeAction(0) // initialize one of the pointers to null as a saftey flag
32 //This next setWhatsThis function prevents
33 // a segfault when using WhatsThis feature with
35 //scene->setWhatsThis(tr("Mussa in OpenGL!"));
36 setCentralWidget(&browser);
38 mussaViewTB.addAction(toggleMotifsAction);
40 zoomBox.setWhatsThis("zoom magnification factor");
41 zoomBox.setRange(2,1000);
42 mussaViewTB.addWidget(&zoomBox);
43 connect(&zoomBox, SIGNAL(valueChanged(int)),
44 &browser, SLOT(setZoom(int)));
46 threshold.setRange(19, 30);
47 threshold.setThreshold(19);
48 //scene->setClipPlane(20);
49 // FIXME: for when we get the paths drawn at the appropriate depth
50 //connect(&threshold, SIGNAL(thresholdChanged(int)),
51 // this, SLOT(setClipPlane(int)));
52 connect(&threshold, SIGNAL(thresholdChanged(int)),
53 this, SLOT(setSoftThreshold(int)));
54 mussaViewTB.addWidget(&threshold);
56 addToolBar(&mussaViewTB);
58 statusBar()->showMessage("Welcome to mussa", 2000);
62 void MussaWindow::setupActions()
64 // we really don't want to run this more than once.
65 assert (closeAction == 0);
67 // the ever popular about box
68 aboutAction = new QAction(tr("&About"), this);
69 connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
70 aboutAction->setIcon(QIcon("icons/info.png"));
73 closeAction = new QAction(tr("&Close"), this);
74 closeAction->setStatusTip(tr("Close this window"));
75 connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
76 closeAction->setIcon(QIcon("icons/exit.png"));
78 createNewAnalysisAction = new QAction(tr("Define Analysis"), this);
79 connect(createNewAnalysisAction, SIGNAL(triggered()),
80 this, SLOT(createNewAnalysis()));
81 createNewAnalysisAction->setIcon(QIcon("icons/filenew.png"));
83 createSubAnalysisAction = new QAction(tr("Define SubAnalysis"), this);
84 connect(createSubAnalysisAction, SIGNAL(triggered()),
85 this, SLOT(createSubAnalysis()));
87 loadMotifListAction = new QAction(tr("Load Motif List"), this);
88 connect(loadMotifListAction, SIGNAL(triggered()),
89 this, SLOT(loadMotifList()));
91 loadMupaAction = new QAction(tr("Load Mussa Parameters"), this);
92 connect(loadMupaAction, SIGNAL(triggered()),
93 this, SLOT(loadMupa()));
95 loadSavedAnalysisAction = new QAction(tr("Load &Analysis"), this);
96 connect(loadSavedAnalysisAction, SIGNAL(triggered()),
97 this, SLOT(loadSavedAnalysis()));
98 loadSavedAnalysisAction->setIcon(QIcon("icons/fileopen.png"));
100 saveMotifListAction = new QAction(tr("Save Motifs"), this);
101 connect(saveMotifListAction, SIGNAL(triggered()),
102 this, SLOT(saveMotifList()));
103 saveMotifListAction->setIcon(QIcon("icons/filesave.png"));
105 showMussaViewToolbarAction = new QAction(tr("Show Toolbar"), this);
106 connect(showMussaViewToolbarAction, SIGNAL(triggered()),
107 this, SLOT(showMussaToolbar()));
108 showMussaViewToolbarAction->setCheckable(true);
109 showMussaViewToolbarAction->setChecked(true);
111 toggleMotifsAction = new QAction(tr("Toggle Motifs"), this);
112 connect(toggleMotifsAction, SIGNAL(triggered()),
113 this, SLOT(toggleMotifs()));
114 toggleMotifsAction->setCheckable(true);
115 toggleMotifsAction->setIcon(QIcon("icons/motif_icon.png"));
116 toggleMotifsAction->setWhatsThis(tr("Toggle motif annotations on/off\n\n"
117 "You can load motif annotations via "
118 "'File->Load Motif List' menu option."));
120 whatsThisAction = QWhatsThis::createAction(this);
121 whatsThisAction->setIcon(QIcon("icons/help.png"));
123 //Save pixel map action
124 saveBrowserPixmapAction = new QAction(tr("Save to image..."), this);
125 connect(saveBrowserPixmapAction, (SIGNAL(triggered())),
126 &browser, SLOT(promptSaveBrowserPixmap()));
127 saveBrowserPixmapAction->setIcon(QIcon("icons/image2.png"));
130 void MussaWindow::setupMainMenu()
132 // we need to run setupActions first
133 assert (closeAction != 0);
136 newMenu = menuBar()->addMenu(tr("&File"));
137 newMenu->addAction(createNewAnalysisAction);
138 newMenu->addAction(loadMupaAction);
139 newMenu->addAction(loadSavedAnalysisAction);
140 newMenu->addAction(createSubAnalysisAction);
141 newMenu->addSeparator();
142 newMenu->addAction(loadMotifListAction);
143 newMenu->addAction(saveMotifListAction);
144 newMenu->addSeparator();
145 newMenu->addAction(saveBrowserPixmapAction);
146 newMenu->addSeparator();
147 newMenu->addAction(closeAction);
149 newMenu = menuBar()->addMenu(tr("&View"));
150 newMenu->addAction(showMussaViewToolbarAction);
152 newMenu = menuBar()->addMenu(tr("&Help"));
153 newMenu->addAction(whatsThisAction);
154 newMenu->addSeparator();
155 newMenu->addAction(aboutAction);
158 void MussaWindow::about()
160 QMessageBox::about(this, tr("About mussa"),
161 tr("Welcome to Multiple Species Sequence Analysis\n"
162 "(c) 2005-2006 California Institute of Technology\n"
163 "Tristan De Buysscher, Diane Trout\n"));
166 void MussaWindow::createNewAnalysis()
171 void MussaWindow::createSubAnalysis()
177 void MussaWindow::loadMotifList()
179 QString caption("Load a motif list");
180 QString filter("Motif list(*.txt *.mtl)");
181 QString path = QFileDialog::getOpenFileName(this,
188 // try to load safely
190 analysis->load_motifs(path.toStdString());
191 } catch (runtime_error e) {
192 QString msg("Unable to load ");
196 QMessageBox::warning(this, "Load Motifs", msg);
198 assert (analysis != 0);
201 void MussaWindow::saveMotifList()
206 void MussaWindow::loadMupa()
208 QString caption("Load a mussa parameter file");
209 QString filter("Mussa Parameters (*.mupa)");
210 QString mupa_path = QFileDialog::getOpenFileName(this,
215 if (mupa_path.isNull())
217 // try to load safely
219 Mussa *m = new Mussa;
220 m->load_mupa_file(mupa_path.toStdString());
221 m->analyze(0, 0, Mussa::TransitiveNway, 0.0);
222 // only switch mussas if we loaded without error
226 } catch (mussa_load_error e) {
227 QString msg("Unable to load ");
231 QMessageBox::warning(this, "Load Parameter", msg);
233 assert (analysis != 0);
236 void MussaWindow::loadSavedAnalysis()
238 QString caption("Load a previously run analysis");
239 QString muway_dir = QFileDialog::getExistingDirectory(this,
241 QDir::currentPath());
243 if (muway_dir.isNull())
245 // try to safely load
247 Mussa *m = new Mussa;
248 m->load(muway_dir.toStdString());
249 // only switch mussas if we loaded without error
253 } catch (mussa_load_error e) {
254 QString msg("Unable to load ");
258 QMessageBox::warning(this, "Load Parameter", msg);
260 assert (analysis != 0);
263 void MussaWindow::setSoftThreshold(int threshold)
265 if (analysis->get_soft_thres() != threshold) {
266 analysis->set_soft_thres(threshold);
273 void MussaWindow::showMussaToolbar()
275 if (mussaViewTB.isVisible())
281 void MussaWindow::toggleMotifs()
286 void MussaWindow::NotImplementedBox()
288 QMessageBox::warning(this, QObject::tr("mussa"), QObject::tr("Not implemented yet"));
291 void MussaWindow::updateAnalysis()
293 cout << "analysis updated" << endl;
295 const vector<Sequence>& seqs = analysis->sequences();
296 browser.setSequences(seqs, analysis->colorMapper());
300 void MussaWindow::updateLinks()
302 browser.clear_links();
303 bool reversed = false;
304 const NwayPaths& nway = analysis->paths();
306 typedef list<ExtendedConservedPath> conserved_paths;
307 typedef conserved_paths::const_iterator const_conserved_paths_itor;
308 for(const_conserved_paths_itor path_itor = nway.refined_pathz.begin();
309 path_itor != nway.refined_pathz.end();
312 // since we were drawing to the start of a window, and opengl lines
313 // are centered around the two connecting points our lines were slightly
314 // offset. the idea of window_offset is to adjust them to the
315 // right for forward compliment or left for reverse compliment
316 // FIXME: figure out how to unit test these computations
317 //GLfloat window_offset = (path_itor->window_size)/2.0;
319 size_t track_len = path_itor->track_indexes.size();
320 vector<int> normalized_path;
321 normalized_path.reserve(track_len);
322 vector<bool> rc_flags(false, track_len);
323 for (size_t track_i=0; track_i != track_len; ++track_i)
325 int x = path_itor->track_indexes[track_i];
326 // at some point when we modify the pathz data structure to keep
327 // track of the score we can put grab the depth here.
329 // are we reverse complimented?
334 x = -x; // make positive
336 normalized_path.push_back(x);
337 rc_flags.push_back(reversed);
339 browser.link(normalized_path, rc_flags, path_itor->window_size);