13 #include "qui/PathScene.hpp"
14 #include "qui/PathWindow.hpp"
15 #include "qui/ImageSaveDialog.hpp"
16 #include "mussa_exceptions.hpp"
22 PathWindow::PathWindow(Mussa *analysis_, QWidget *parent) :
26 mussaViewTB("Path Views"),
29 closeAction(0) // initialize one of the pointers to null as a saftey flag
34 //This next setWhatsThis function prevents
35 // a segfault when using WhatsThis feature with
37 //scene->setWhatsThis(tr("Mussa in OpenGL!"));
38 setCentralWidget(&path_view);
40 mussaViewTB.addAction(toggleMotifsAction);
42 zoomBox.setWhatsThis("zoom magnification factor");
43 zoomBox.setRange(2,1000);
44 mussaViewTB.addWidget(&zoomBox);
45 connect(&zoomBox, SIGNAL(valueChanged(int)),
46 &path_view.scene, SLOT(setZoom(int)));
48 threshold.setRange(19, 30);
49 threshold.setThreshold(19);
50 //scene->setClipPlane(20);
51 // FIXME: for when we get the paths drawn at the appropriate depth
52 //connect(threshold, SIGNAL(thresholdChanged(int)),
53 // scene, SLOT(setClipPlane(int)));
54 //connect(&threshold, SIGNAL(thresholdChanged(int)),
55 // &scene, SLOT(setSoftThreshold(int)));
56 mussaViewTB.addWidget(&threshold);
58 addToolBar(&mussaViewTB);
60 statusBar()->showMessage("Welcome to mussa", 2000);
64 void PathWindow::setupActions()
66 // we really don't want to run this more than once.
67 assert (closeAction == 0);
69 // the ever popular about box
70 aboutAction = new QAction(tr("&About"), this);
71 connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
72 aboutAction->setIcon(QIcon("icons/info.png"));
75 closeAction = new QAction(tr("&Close"), this);
76 closeAction->setStatusTip(tr("Close this window"));
77 connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
78 closeAction->setIcon(QIcon("icons/exit.png"));
80 createNewAnalysisAction = new QAction(tr("Define Analysis"), this);
81 connect(createNewAnalysisAction, SIGNAL(triggered()),
82 this, SLOT(createNewAnalysis()));
83 createNewAnalysisAction->setIcon(QIcon("icons/filenew.png"));
85 createSubAnalysisAction = new QAction(tr("Define SubAnalysis"), this);
86 connect(createSubAnalysisAction, SIGNAL(triggered()),
87 this, SLOT(createSubAnalysis()));
89 loadMotifListAction = new QAction(tr("Load Motif List"), this);
90 connect(loadMotifListAction, SIGNAL(triggered()),
91 this, SLOT(loadMotifList()));
93 loadMupaAction = new QAction(tr("Load Mussa Parameters"), this);
94 connect(loadMupaAction, SIGNAL(triggered()),
95 this, SLOT(loadMupa()));
97 loadSavedAnalysisAction = new QAction(tr("Load &Analysis"), this);
98 connect(loadSavedAnalysisAction, SIGNAL(triggered()),
99 this, SLOT(loadSavedAnalysis()));
100 loadSavedAnalysisAction->setIcon(QIcon("icons/fileopen.png"));
102 saveMotifListAction = new QAction(tr("Save Motifs"), this);
103 connect(saveMotifListAction, SIGNAL(triggered()),
104 this, SLOT(saveMotifList()));
105 saveMotifListAction->setIcon(QIcon("icons/filesave.png"));
107 showMussaViewToolbarAction = new QAction(tr("Show Toolbar"), this);
108 connect(showMussaViewToolbarAction, SIGNAL(triggered()),
109 this, SLOT(showMussaToolbar()));
110 showMussaViewToolbarAction->setCheckable(true);
111 showMussaViewToolbarAction->setChecked(true);
113 toggleMotifsAction = new QAction(tr("Toggle Motifs"), this);
114 connect(toggleMotifsAction, SIGNAL(triggered()),
115 this, SLOT(toggleMotifs()));
116 toggleMotifsAction->setCheckable(true);
117 toggleMotifsAction->setIcon(QIcon("icons/motif_icon.png"));
118 toggleMotifsAction->setWhatsThis(tr("Toggle motif annotations on/off\n\n"
119 "You can load motif annotations via "
120 "'File->Load Motif List' menu option."));
122 whatsThisAction = QWhatsThis::createAction(this);
123 whatsThisAction->setIcon(QIcon("icons/help.png"));
125 //Save pixel map action
126 saveOpenGlPixmapAction = new QAction(tr("Save to image..."), this);
127 connect(saveOpenGlPixmapAction, (SIGNAL(triggered())),
128 this, SLOT(promptSaveOpenGlPixmap()));
129 saveOpenGlPixmapAction->setIcon(QIcon("icons/image2.png"));
132 void PathWindow::setupMainMenu()
134 // we need to run setupActions first
135 assert (closeAction != 0);
138 newMenu = menuBar()->addMenu(tr("&File"));
139 newMenu->addAction(createNewAnalysisAction);
140 newMenu->addAction(loadMupaAction);
141 newMenu->addAction(loadSavedAnalysisAction);
142 newMenu->addAction(createSubAnalysisAction);
143 newMenu->addSeparator();
144 newMenu->addAction(loadMotifListAction);
145 newMenu->addAction(saveMotifListAction);
146 newMenu->addSeparator();
147 newMenu->addAction(saveOpenGlPixmapAction);
148 newMenu->addSeparator();
149 newMenu->addAction(closeAction);
151 newMenu = menuBar()->addMenu(tr("&View"));
152 newMenu->addAction(showMussaViewToolbarAction);
154 newMenu = menuBar()->addMenu(tr("&Help"));
155 newMenu->addAction(whatsThisAction);
156 newMenu->addSeparator();
157 newMenu->addAction(aboutAction);
160 void PathWindow::about()
162 QMessageBox::about(this, tr("About mussa"),
163 tr("Welcome to Multiple Species Sequence Analysis\n"
164 "(c) 2005-2006 California Institute of Technology\n"
165 "Tristan De Buysscher, Diane Trout\n"));
168 void PathWindow::createNewAnalysis()
173 void PathWindow::createSubAnalysis()
179 void PathWindow::loadMotifList()
181 QString caption("Load a motif list");
182 QString filter("Motif list(*.txt *.mtl)");
183 QString path = QFileDialog::getOpenFileName(this,
190 // try to load safely
192 analysis->load_motifs(path.toStdString());
193 } catch (runtime_error e) {
194 QString msg("Unable to load ");
198 QMessageBox::warning(this, "Load Motifs", msg);
200 assert (analysis != 0);
203 void PathWindow::saveMotifList()
208 void PathWindow::loadMupa()
210 QString caption("Load a mussa parameter file");
211 QString filter("Mussa Parameters (*.mupa)");
212 QString mupa_path = QFileDialog::getOpenFileName(this,
217 if (mupa_path.isNull())
219 // try to load safely
221 Mussa *m = new Mussa;
222 m->load_mupa_file(mupa_path.toStdString());
223 m->analyze(0, 0, Mussa::TransitiveNway, 0.0);
224 // only switch mussas if we loaded without error
228 } catch (mussa_load_error e) {
229 QString msg("Unable to load ");
233 QMessageBox::warning(this, "Load Parameter", msg);
235 assert (analysis != 0);
238 void PathWindow::loadSavedAnalysis()
240 QString caption("Load a previously run analysis");
241 QString muway_dir = QFileDialog::getExistingDirectory(this,
243 QDir::currentPath());
245 if (muway_dir.isNull())
247 // try to safely load
249 Mussa *m = new Mussa;
250 m->load(muway_dir.toStdString());
251 // only switch mussas if we loaded without error
255 } catch (mussa_load_error e) {
256 QString msg("Unable to load ");
260 QMessageBox::warning(this, "Load Parameter", msg);
262 assert (analysis != 0);
265 void PathWindow::setSoftThreshold(int threshold)
267 if (analysis->get_threshold() != threshold) {
268 analysis->set_soft_thres(threshold);
275 void PathWindow::showMussaToolbar()
277 if (mussaViewTB.isVisible())
283 void PathWindow::toggleMotifs()
288 void PathWindow::NotImplementedBox()
290 QMessageBox::warning(this, QObject::tr("mussa"), QObject::tr("Not implemented yet"));
293 void PathWindow::promptSaveOpenGlPixmap()
296 size = path_view.scene.size();
298 ImageSaveDialog imageSaveDialog(&path_view.scene, this);
299 imageSaveDialog.setSize(size.width(), size.height());
300 int result = imageSaveDialog.exec();
301 cout << "Result: " << result << "\n";
304 void PathWindow::updateAnalysis()
306 cout << "analysis updated" << endl;
307 path_view.scene.clear();
308 const vector<Sequence>& seqs = analysis->sequences();
309 for(vector<Sequence>::const_iterator seq_i = seqs.begin();
313 path_view.scene.push_sequence(*seq_i);
318 void PathWindow::updateLinks()
320 path_view.scene.clear_links();
321 bool reversed = false;
322 const NwayPaths& nway = analysis->paths();
324 typedef list<ExtendedConservedPath> conserved_paths;
325 typedef conserved_paths::const_iterator const_conserved_paths_itor;
326 for(const_conserved_paths_itor path_itor = nway.refined_pathz.begin();
327 path_itor != nway.refined_pathz.end();
330 // since we were drawing to the start of a window, and opengl lines
331 // are centered around the two connecting points our lines were slightly
332 // offset. the idea of window_offset is to adjust them to the
333 // right for forward compliment or left for reverse compliment
334 // FIXME: figure out how to unit test these computations
335 //GLfloat window_offset = (path_itor->window_size)/2.0;
337 size_t track_len = path_itor->track_indexes.size();
338 vector<int> normalized_path;
339 normalized_path.reserve(track_len);
340 vector<bool> rc_flags(false, track_len);
341 for (size_t track_i=0; track_i != track_len; ++track_i)
343 int x = path_itor->track_indexes[track_i];
344 // at some point when we modify the pathz data structure to keep
345 // track of the score we can put grab the depth here.
347 // are we reverse complimented?
352 x = -x; // make positive
354 normalized_path.push_back(x);
355 rc_flags.push_back(reversed);
357 path_view.scene.link(normalized_path, rc_flags, path_itor->window_size);