}
+std::vector<ConservedPath::path_element> ConservedPath::normalizedIndexes() const
+{
+ vector<path_element> paths;
+ for (ConservedPath::const_iterator this_itor = begin();
+ this_itor != end();
+ ++this_itor)
+ {
+ if (*this_itor < 0) {
+ paths.push_back(-*this_itor);
+ } else {
+ paths.push_back(*this_itor);
+ }
+ }
+ return paths;
+}
+
+
/////////////////////
ExtendedConservedPath::ExtendedConservedPath()
: ConservedPath(),
{
}
+std::vector<ConservedPath::path_element> ExtendedConservedPath::normalizedIndexes() const
+{
+ vector<path_element> paths;
+ for (ConservedPath::const_iterator this_itor = begin();
+ this_itor != end();
+ ++this_itor)
+ {
+ if (*this_itor < 0) {
+ paths.push_back(-(*this_itor) - window_size);
+ } else {
+ paths.push_back((*this_itor));
+ }
+ }
+ return paths;
+}
+
ExtendedConservedPath& ExtendedConservedPath::extend(int growth)
{
window_size += growth;
bool nextTo(const ConservedPath& next) const;
//! indicate which elements of the path are reversed
std::vector<bool> reverseComplimented() const;
+ //! return the list of indexes normalized (to the left)
+ std::vector<path_element> normalizedIndexes() const;
//! either number of conserved bases or average entropy
double score;
ExtendedConservedPath(int win_size, ConservedPath conserved_path);
ExtendedConservedPath(int win_size, double score, std::vector<int> path);
+ std::vector<ConservedPath::path_element> ExtendedConservedPath::normalizedIndexes() const;
//! extend our current path
/*! (aka increment our window size by growth)
*/
void GlSeqBrowser::clear_links()
{
- path_segment_map_vector::iterator psmv_i;
- for(psmv_i = path_segments.begin();
- psmv_i != path_segments.end();
- ++psmv_i)
+ path_segments.clear();
+ for (int i = track_container.size()-1; i > 0; --i)
{
- psmv_i->clear();
+ path_segments.push_back(pair_segment_map());
}
}
for(size_t track_i = 0; track_i != track_container.size(); ++track_i)
{
- track_container[track_i].setX(viewport_center - paths[track_i]);
+ // -15 = shift more to the left
+ track_container[track_i].setX((viewport_center-15) - paths[track_i]);
}
}
ecp_base.extend(growth);
BOOST_CHECK_EQUAL( ecp_base.window_size, window_size + growth );
}
+
+BOOST_AUTO_TEST_CASE ( extended_conserved_normalized )
+{
+ vector<int> path;
+ path += 3,-14,5,-19; // magic from boost assign
+ vector<int> normalized_path;
+ normalized_path += 3,4, 5,9;
+
+ ExtendedConservedPath ecp1;
+ ecp1.window_size = 10;
+ ecp1.score = 18;
+ ecp1.track_indexes = path;
+ BOOST_CHECK_EQUAL ( ecp1.size(), path.size() );
+
+ vector<ConservedPath::path_element> normalized_index(ecp1.normalizedIndexes());
+
+ for(int i=0; i != ecp1.size(); ++i)
+ {
+ BOOST_CHECK_EQUAL(normalized_index[i], normalized_path[i]);
+ }
+}
+
// I didn't bother to compute how the path should shift things
// by the magic number 3, i just ran the test and saw how it failed
// and hard coded this in.
- BOOST_CHECK_EQUAL( gt.left(), -3-gt.border() );
- BOOST_CHECK_EQUAL( gt.right(), 3 + s0.size() + gt.border() );
+ BOOST_CHECK_EQUAL( gt.left(), -18-gt.border() );
+ BOOST_CHECK_EQUAL( gt.right(), s0.size() + gt.border()-11 );
// aparently we end up with a different glsequence in the seqbrowser
BOOST_CHECK( glseq1.x() != gt.sequences()[1].x() );
- BOOST_CHECK_EQUAL( gt.sequences()[0].x(), gt.viewportCenter()-path[0] );
- BOOST_CHECK_EQUAL( gt.sequences()[1].x(), gt.viewportCenter()-path[1] );
- BOOST_CHECK_EQUAL( gt.sequences()[2].x(), gt.viewportCenter()-path[2] );
+ BOOST_CHECK_EQUAL( gt.sequences()[0].x(), (gt.viewportCenter()-15)-path[0] );
+ BOOST_CHECK_EQUAL( gt.sequences()[1].x(), (gt.viewportCenter()-15)-path[1] );
+ BOOST_CHECK_EQUAL( gt.sequences()[2].x(), (gt.viewportCenter()-15)-path[2] );
}
qui/ThresholdWidget.hpp \
qui/ImageScaler.hpp \
qui/ImageSaveDialog.hpp \
+ qui/IntAction.hpp \
qui/seqbrowser/SequenceBrowserWidget.hpp \
qui/seqbrowser/SequenceBrowser.hpp \
qui/seqbrowser/SequenceBrowserSidebar.hpp \
qui/ThresholdWidget.cpp \
qui/ImageScaler.cpp \
qui/ImageSaveDialog.cpp \
+ qui/IntAction.cpp \
qui/seqbrowser/SequenceBrowserWidget.cpp \
qui/seqbrowser/SequenceBrowser.cpp \
qui/seqbrowser/SequenceBrowserSidebar.cpp \
--- /dev/null
+#include "qui/IntAction.hpp"
+
+#include <iostream>
+using namespace std;
+
+IntAction::IntAction(const QString &text, int value, QObject*parent)
+ : QAction(text, parent),
+ val(value)
+{
+ connect(this, SIGNAL(triggered()), this, SLOT(triggerWithValue()));
+}
+
+void IntAction::triggerWithValue()
+{
+ emit triggered(val);
+}
--- /dev/null
+#ifndef _INT_ACTION_H
+#define _INT_ACTION_H
+
+#include <QAction>
+#include <QString>
+
+class IntAction : public QAction
+{
+ Q_OBJECT
+
+public:
+ IntAction(const QString &text, int value, QObject*parent=0);
+
+ int value() const { return val; }
+
+public slots:
+ void triggerWithValue();
+
+signals:
+ void triggered(int);
+
+private:
+ int val;
+};
+#endif
+
#include <vector>
#include <sstream>
-#include <QVBoxLayout>
+#include <QStatusBar>
+#include <QString>
+#include <QMenuBar>
#include "qui/MussaAlignedWindow.hpp"
#include "alg/sequence.hpp"
MussaAlignedWindow::MussaAlignedWindow(Mussa& m,
const set<int>& sel_paths,
QWidget *parent)
- : QWidget(parent),
- analysis(m)//,
- //selected_paths(sel_paths)
-
+ : QMainWindow(parent),
+ analysis(m),
+ pick_align_menu(tr("Choose Alignment")),
+ view_align_menu(tr("View Alignment"))
{
browser.setSequences(analysis.sequences(), analysis.colorMapper());
setSelectedPaths(m, sel_paths);
setAlignment(0);
browser.zoomToSequence();
computeMatchLines();
+ setupMenus();
- QVBoxLayout *layout = new QVBoxLayout;
- layout->addWidget(&browser);
- layout->addWidget(&status);
- setLayout(layout);
+ setCentralWidget(&browser);
+ menuBar()->addMenu(&pick_align_menu);
+ menuBar()->addMenu(&view_align_menu);
ostringstream message;
message << "Selected " << selected_paths.size() << " paths";
- status.showMessage(message.str().c_str(), 5000);
+ statusBar()->showMessage(message.str().c_str(), 5000);
}
size_t pathid=0;
selected_paths.reserve(sel_paths.size());
+ view_paths.reserve(sel_paths.size());
while (pathid != path_size and sel_i != sel_paths.end())
{
assert (*sel_i >= 0);
size_t sel_pathid = (size_t)(*sel_i);
if (pathid == sel_pathid) {
- cout << "found one " << *path_i << endl;
selected_paths.push_back(*path_i);
+ view_paths.push_back(true);
++pathid;
++path_i;
++sel_i;
}
}
+void MussaAlignedWindow::setupMenus()
+{
+ pick_align_menu.clear();
+ view_align_menu.clear();
+ pick_actions.clear();
+ view_actions.clear();
+
+ for(vector<ExtendedConservedPath >::iterator pathz_i=selected_paths.begin();
+ pathz_i != selected_paths.end();
+ ++pathz_i)
+ {
+ ConservedPath::path_type normalized_path = pathz_i->normalizedIndexes();
+ ostringstream menu_text;
+ menu_text << pathz_i->window_size << ":";
+ ConservedPath::iterator element_i = normalized_path.begin();
+ menu_text << *element_i++;
+ for (;
+ element_i != normalized_path.end();
+ ++element_i)
+ {
+ menu_text << ", ";
+ menu_text << *element_i;
+ }
+ int index = pathz_i - selected_paths.begin();
+ IntAction *pick = new IntAction(QString(menu_text.str().c_str()), index, this);
+ connect(pick, SIGNAL(triggered(int)), this, SLOT(setAlignment(size_t)));
+ pick_actions.push_back(pick);
+ pick_align_menu.addAction(pick);
+ IntAction *view = new IntAction(QString(menu_text.str().c_str()), index, this);
+ connect(view, SIGNAL(triggered(int)), this, SLOT(toggleViewAlignment(size_t)));
+ view->setCheckable(true);
+ view->setChecked(true);
+ view_actions.push_back(view);
+ view_align_menu.addAction(view);
+ }
+}
+
void MussaAlignedWindow::setAlignment(size_t alignment_index)
{
if (selected_paths.size() > 0) {
- browser.centerOnPath(selected_paths[alignment_index].track_indexes);
+ browser.centerOnPath(selected_paths[alignment_index].normalizedIndexes());
}
}
+void MussaAlignedWindow::toggleViewAlignment(size_t alignment_index)
+{
+ view_paths[alignment_index]= not view_paths[alignment_index];
+ // perhaps it'd be better if we could erase specific sets
+ // of matches instead of erasing them all and recomputing them all
+ // but this is easier
+ computeMatchLines();
+}
+
void MussaAlignedWindow::computeMatchLines()
{
const vector<Sequence>& raw_sequence = analysis.sequences();
vector<bool> matched;
int align_counter;
+ browser.clear_links();
align_counter = 0;
for(vector<ExtendedConservedPath >::iterator pathz_i=selected_paths.begin();
pathz_i != selected_paths.end();
++pathz_i)
{
- if (true /* show_aligns[align_counter] */)
+ if (view_paths[align_counter])
{
ExtendedConservedPath& a_path = *pathz_i;
window_length = a_path.window_size;
#include <set>
-#include <QStatusBar>
-#include <QWidget>
+#include <QMainWindow>
+#include <QMenu>
#include "alg/mussa.hpp"
+#include "qui/IntAction.hpp"
#include "qui/seqbrowser/SequenceBrowserWidget.hpp"
//! Show sequence alignments
-class MussaAlignedWindow : public QWidget
+class MussaAlignedWindow : public QMainWindow
{
+ Q_OBJECT
+
public:
//! construct an aligned window for an analysis and selected paths
MussaAlignedWindow(Mussa&, const std::set<int>&, QWidget *parent=0);
public slots:
//! use selected_paths[pathid] to set the starting position of our sequence
void setAlignment(size_t pathid);
+ //! toggle whether or not to show the aligned basepairs of a window
+ void toggleViewAlignment(size_t alignment_index);
protected:
void setSelectedPaths(Mussa &m, const std::set<int>& sel_paths);
+ //! set menus (must be called after setSelectedPaths)
+ void setupMenus();
void computeMatchLines();
Mussa& analysis;
//std::vector<Sequence> sequences;
//const std::set<int>& selected_paths;
std::vector<ExtendedConservedPath> selected_paths;
+ std::vector<bool> view_paths;
SequenceBrowserWidget browser;
- QStatusBar status;
+ QMenu pick_align_menu;
+ QMenu view_align_menu;
+ std::vector <IntAction *> pick_actions;
+ std::vector <IntAction *> view_actions;
};
#endif