#include <QMenuBar>
#include <QMessageBox>
#include <QScrollBar>
-#include <QSpinBox>
#include <QStatusBar>
#include <QString>
-#include <QToolBar>
#include <QWhatsThis>
#include "qui/PathScene.hpp"
-#include "qui/PathWidget.hpp"
#include "qui/PathWindow.hpp"
-#include "qui/ThresholdWidget.hpp"
#include "qui/ImageSaveDialog.hpp"
+#include "mussa_exceptions.hpp"
#include <iostream>
-PathWindow::PathWindow(Mussa *analysis, QWidget *) :
+using namespace std;
+
+PathWindow::PathWindow(Mussa *analysis_, QWidget *parent) :
+ QMainWindow(parent),
+ analysis(analysis_),
+ path_view(this),
+ mussaViewTB("Path Views"),
+ zoomBox(),
+ threshold(),
closeAction(0) // initialize one of the pointers to null as a saftey flag
{
- scene = new PathScene(analysis, this);
-
setupActions();
setupMainMenu();
//This next setWhatsThis function prevents
// a segfault when using WhatsThis feature with
// opengl widget.
- scene->setWhatsThis(tr("Mussa in OpenGL!"));
- // make a widget so we can have a scroll bar
- PathWidget *path_widget = new PathWidget(scene, this);
- setCentralWidget(path_widget);
-
- mussaViewTB = new QToolBar("Path Views");
- mussaViewTB->addAction(toggleMotifsAction);
-
- QSpinBox *zoom = new QSpinBox();
- zoom->setWhatsThis("zoom magnification factor");
- zoom->setRange(2,1000);
- mussaViewTB->addWidget(zoom);
- connect(zoom, SIGNAL(valueChanged(int)), scene, SLOT(setZoom(int)));
+ //scene->setWhatsThis(tr("Mussa in OpenGL!"));
+ setCentralWidget(&path_view);
+
+ mussaViewTB.addAction(toggleMotifsAction);
+
+ zoomBox.setWhatsThis("zoom magnification factor");
+ zoomBox.setRange(2,1000);
+ mussaViewTB.addWidget(&zoomBox);
+ connect(&zoomBox, SIGNAL(valueChanged(int)),
+ &path_view.scene, SLOT(setZoom(int)));
- ThresholdWidget *threshold = new ThresholdWidget;
- threshold->setRange(19, 30);
- threshold->setThreshold(19);
- scene->setClipPlane(20);
+ threshold.setRange(19, 30);
+ threshold.setThreshold(19);
+ //scene->setClipPlane(20);
// FIXME: for when we get the paths drawn at the appropriate depth
//connect(threshold, SIGNAL(thresholdChanged(int)),
// scene, SLOT(setClipPlane(int)));
- connect(threshold, SIGNAL(thresholdChanged(int)),
- scene, SLOT(setSoftThreshold(int)));
- mussaViewTB->addWidget(threshold);
+ //connect(&threshold, SIGNAL(thresholdChanged(int)),
+ // &scene, SLOT(setSoftThreshold(int)));
+ mussaViewTB.addWidget(&threshold);
- //Image Save Dialog
- imageSaveDialog = new ImageSaveDialog(scene, this);
-
- addToolBar(mussaViewTB);
+ addToolBar(&mussaViewTB);
statusBar()->showMessage("Welcome to mussa", 2000);
+ updateAnalysis();
}
void PathWindow::setupActions()
loadMotifListAction = new QAction(tr("Load Motif List"), this);
connect(loadMotifListAction, SIGNAL(triggered()),
- scene, SLOT(loadMotifList()));
+ this, SLOT(loadMotifList()));
loadMupaAction = new QAction(tr("Load Mussa Parameters"), this);
connect(loadMupaAction, SIGNAL(triggered()),
- scene, SLOT(loadMupa()));
+ this, SLOT(loadMupa()));
loadSavedAnalysisAction = new QAction(tr("Load &Analysis"), this);
connect(loadSavedAnalysisAction, SIGNAL(triggered()),
- scene, SLOT(loadSavedAnalysis()));
+ this, SLOT(loadSavedAnalysis()));
loadSavedAnalysisAction->setIcon(QIcon("icons/fileopen.png"));
saveMotifListAction = new QAction(tr("Save Motifs"), this);
NotImplementedBox();
}
+
+void PathWindow::loadMotifList()
+{
+ QString caption("Load a motif list");
+ QString filter("Motif list(*.txt *.mtl)");
+ QString path = QFileDialog::getOpenFileName(this,
+ caption,
+ QDir::currentPath(),
+ filter);
+ // user hit cancel?
+ if (path.isNull())
+ return;
+ // try to load safely
+ try {
+ analysis->load_motifs(path.toStdString());
+ } catch (runtime_error e) {
+ QString msg("Unable to load ");
+ msg += path;
+ msg += "\n";
+ msg += e.what();
+ QMessageBox::warning(this, "Load Motifs", msg);
+ }
+ assert (analysis != 0);
+}
+
void PathWindow::saveMotifList()
{
NotImplementedBox();
}
+void PathWindow::loadMupa()
+{
+ QString caption("Load a mussa parameter file");
+ QString filter("Mussa Parameters (*.mupa)");
+ QString mupa_path = QFileDialog::getOpenFileName(this,
+ caption,
+ QDir::currentPath(),
+ filter);
+ // user hit cancel?
+ if (mupa_path.isNull())
+ return;
+ // try to load safely
+ try {
+ Mussa *m = new Mussa;
+ m->load_mupa_file(mupa_path.toStdString());
+ m->analyze(0, 0, Mussa::TransitiveNway, 0.0);
+ // only switch mussas if we loaded without error
+ delete analysis;
+ analysis = m;
+ updateAnalysis();
+ } catch (mussa_load_error e) {
+ QString msg("Unable to load ");
+ msg += mupa_path;
+ msg += "\n";
+ msg += e.what();
+ QMessageBox::warning(this, "Load Parameter", msg);
+ }
+ assert (analysis != 0);
+}
+
+void PathWindow::loadSavedAnalysis()
+{
+ QString caption("Load a previously run analysis");
+ QString muway_dir = QFileDialog::getExistingDirectory(this,
+ caption,
+ QDir::currentPath());
+ // user hit cancel?
+ if (muway_dir.isNull())
+ return;
+ // try to safely load
+ try {
+ Mussa *m = new Mussa;
+ m->load(muway_dir.toStdString());
+ // only switch mussas if we loaded without error
+ delete analysis;
+ analysis = m;
+ updateAnalysis();
+ } catch (mussa_load_error e) {
+ QString msg("Unable to load ");
+ msg += muway_dir;
+ msg += "\n";
+ msg += e.what();
+ QMessageBox::warning(this, "Load Parameter", msg);
+ }
+ assert (analysis != 0);
+}
+
+void PathWindow::setSoftThreshold(int threshold)
+{
+ if (analysis->get_threshold() != threshold) {
+ analysis->set_soft_thres(threshold);
+ analysis->nway();
+ updateLinks();
+ update();
+ }
+}
+
void PathWindow::showMussaToolbar()
{
- std::clog << "isVis?" << mussaViewTB->isVisible() <<std::endl;
- if (mussaViewTB->isVisible())
- mussaViewTB->hide();
+ if (mussaViewTB.isVisible())
+ mussaViewTB.hide();
else
- mussaViewTB->show();
- std::clog << "isVis?" << mussaViewTB->isVisible() <<std::endl;
+ mussaViewTB.show();
}
void PathWindow::toggleMotifs()
void PathWindow::promptSaveOpenGlPixmap()
{
QSize size;
- size = scene->size();
- imageSaveDialog->setSize(size.width(), size.height());
- int result = imageSaveDialog->exec();
- std::cout << "Result: " << result << "\n";
+ size = path_view.scene.size();
+ //Image Save Dialog
+ ImageSaveDialog imageSaveDialog(&path_view.scene, this);
+ imageSaveDialog.setSize(size.width(), size.height());
+ int result = imageSaveDialog.exec();
+ cout << "Result: " << result << "\n";
+}
+
+void PathWindow::updateAnalysis()
+{
+ cout << "analysis updated" << endl;
+ path_view.scene.clear();
+ const vector<Sequence>& seqs = analysis->sequences();
+ for(vector<Sequence>::const_iterator seq_i = seqs.begin();
+ seq_i != seqs.end();
+ ++seq_i)
+ {
+ path_view.scene.push_sequence(*seq_i);
+ }
+ updateLinks();
+}
+
+void PathWindow::updateLinks()
+{
+ path_view.scene.clear_links();
+ bool reversed = false;
+ const NwayPaths& nway = analysis->paths();
+
+ typedef list<ExtendedConservedPath> conserved_paths;
+ typedef conserved_paths::const_iterator const_conserved_paths_itor;
+ for(const_conserved_paths_itor path_itor = nway.refined_pathz.begin();
+ path_itor != nway.refined_pathz.end();
+ ++path_itor)
+ {
+ // since we were drawing to the start of a window, and opengl lines
+ // are centered around the two connecting points our lines were slightly
+ // offset. the idea of window_offset is to adjust them to the
+ // right for forward compliment or left for reverse compliment
+ // FIXME: figure out how to unit test these computations
+ //GLfloat window_offset = (path_itor->window_size)/2.0;
+
+ size_t track_len = path_itor->track_indexes.size();
+ vector<int> normalized_path;
+ normalized_path.reserve(track_len);
+ vector<bool> rc_flags(false, track_len);
+ for (size_t track_i=0; track_i != track_len; ++track_i)
+ {
+ int x = path_itor->track_indexes[track_i];
+ // at some point when we modify the pathz data structure to keep
+ // track of the score we can put grab the depth here.
+ //
+ // are we reverse complimented?
+ if ( x>=0) {
+ reversed = false;
+ } else {
+ reversed = true;
+ x = -x; // make positive
+ }
+ normalized_path.push_back(x);
+ rc_flags.push_back(reversed);
+ }
+ path_view.scene.link(normalized_path, rc_flags, path_itor->window_size);
+ }
}