#include "qui/MussaAlignedWindow.hpp"
#include "alg/sequence.hpp"
+#include <iostream>
using namespace std;
-MussaAlignedWindow::MussaAlignedWindow(Mussa& m,
- const set<int>& sel_paths,
+MussaAlignedWindow::MussaAlignedWindow(MussaRef m,
+ boost::shared_ptr<QDir> default_dir_,
+ const set<int>& sel_paths,
+ SubanalysisWindowRef window,
QWidget *parent)
: QMainWindow(parent),
analysis(m),
+ default_dir(default_dir_),
+ subanalysis_window(window),
+ browser(default_dir),
pick_align_menu(tr("Choose Alignment")),
- view_align_menu(tr("View Alignment"))
+ view_align_menu(tr("View Alignment")),
+ threshold_widget(0),
+ zoom(0),
+ alignTB(0)
{
- browser.setSequences(analysis.sequences(), analysis.colorMapper());
- setSelectedPaths(m, sel_paths);
+ setupActions();
+ connect(&browser, SIGNAL(basepairsCopied(size_t)),
+ this, SLOT(showBasePairsCopied(size_t)));
+ browser.setSequences(analysis->sequences(), analysis->colorMapper());
+ setSelectedPaths(analysis, sel_paths);
setAlignment(0);
- browser.zoomToSequence();
+ double zoom_level = browser.zoomToSequence();
+
+ zoom = new ZoomWidget();
+ connect(zoom, SIGNAL(valueChanged(double)),
+ &browser, SLOT(setZoom(double)));
+ zoom->setValue(zoom_level);
computeMatchLines();
setupMenus();
-
+ setupAlignmentMenus();
+
setCentralWidget(&browser);
- menuBar()->addMenu(&pick_align_menu);
- menuBar()->addMenu(&view_align_menu);
+ // Add a threhold widget set to our current threshold and make it readonly
+ threshold_widget = new ThresholdWidget;
+ threshold_widget->setRange(analysis->get_threshold(),analysis->get_window());
+ threshold_widget->setBasepairThreshold(analysis->get_soft_threshold());
+ threshold_widget->setReadOnly(true);
+
+ alignTB = new QToolBar();
+ alignTB->addWidget(zoom);
+ alignTB->addWidget(threshold_widget);
+ addToolBar(alignTB);
+
ostringstream message;
message << "Selected " << selected_paths.size() << " paths";
statusBar()->showMessage(message.str().c_str(), 5000);
+ browser.updatePosition();
+
+ updateTitle();
}
+void MussaAlignedWindow::setupActions()
+{
+ // more cut-n-paste from MussaWindow
+ createSubAnalysisAction = new QAction(tr("Add to Subanalysis"), this);
+ connect(createSubAnalysisAction, SIGNAL(triggered()),
+ this, SLOT(createSubAnalysis()));
+
+ //Save pixel map action
+ saveBrowserPixmapAction = new QAction(tr("Save to image..."), this);
+ connect(saveBrowserPixmapAction, (SIGNAL(triggered())),
+ &browser, SLOT(promptSaveBrowserPixmap()));
+ saveBrowserPixmapAction->setIcon(QIcon(":/icons/image2.png"));
+}
-void MussaAlignedWindow::setSelectedPaths(Mussa &m, const set<int>& sel_paths)
+void MussaAlignedWindow::setupMenus()
{
- // sets are sorted
- set<int>::iterator sel_i = sel_paths.begin();
- list<ExtendedConservedPath>::const_iterator path_i = m.paths().rpbegin();
- list<ExtendedConservedPath>::const_iterator path_end = m.paths().rpend();
- size_t path_size = m.paths().refined_pathz.size();
- size_t pathid=0;
+ QMenu *newMenu = menuBar()->addMenu(tr("&File"));
+ newMenu->addAction(saveBrowserPixmapAction);
- 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) {
- selected_paths.push_back(*path_i);
- view_paths.push_back(true);
- ++pathid;
- ++path_i;
- ++sel_i;
- } else if (pathid < sel_pathid) {
- ++pathid;
- ++path_i;
- } else if (pathid > sel_pathid) {
- ++sel_i;
- }
- }
+ newMenu = menuBar()->addMenu(tr("&Edit"));
+ newMenu->addAction(browser.getCopySelectedSequenceAsStringAction());
+ newMenu->addAction(browser.getCopySelectedSequenceAsFastaAction());
+ newMenu->addAction(createSubAnalysisAction);
+
+ // add some extra features to the context menu
+ QMenu *popupMenu = browser.getPopupMenu();
+ if (popupMenu) {
+ popupMenu->addAction(createSubAnalysisAction);
+ }
}
-void MussaAlignedWindow::setupMenus()
+void MussaAlignedWindow::setupAlignmentMenus()
{
pick_align_menu.clear();
view_align_menu.clear();
pick_actions.clear();
view_actions.clear();
- for(vector<ExtendedConservedPath >::iterator pathz_i=selected_paths.begin();
+ for(vector<ConservedPath >::iterator pathz_i=selected_paths.begin();
pathz_i != selected_paths.end();
++pathz_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)));
+ connect(pick, SIGNAL(triggered(int)), this, SLOT(setAlignment(int)));
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)));
+ connect(view, SIGNAL(triggered(int)), this, SLOT(toggleViewAlignment(int)));
view->setCheckable(true);
view->setChecked(true);
view_actions.push_back(view);
view_align_menu.addAction(view);
}
+
+ menuBar()->addMenu(&pick_align_menu);
+ menuBar()->addMenu(&view_align_menu);
}
-void MussaAlignedWindow::setAlignment(size_t alignment_index)
+
+void MussaAlignedWindow::setSelectedPaths(MussaRef m, const set<int>& sel_paths)
+{
+ // sets are sorted
+ set<int>::iterator sel_i = sel_paths.begin();
+ list<ConservedPath>::const_iterator path_i = m->paths().refined_pathz.begin();
+ list<ConservedPath>::const_iterator path_end = m->paths().refined_pathz.end();
+ size_t path_size = m->paths().refined_pathz.size();
+ 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) {
+ selected_paths.push_back(*path_i);
+ view_paths.push_back(true);
+ ++pathid;
+ ++path_i;
+ ++sel_i;
+ } else if (pathid < sel_pathid) {
+ ++pathid;
+ ++path_i;
+ } else if (pathid > sel_pathid) {
+ ++sel_i;
+ }
+ }
+}
+
+// FIXME: this is a cut-n-paste from MussaWindow, perhaps they should be refactored to
+// some shared place
+void MussaAlignedWindow::createSubAnalysis()
+{
+ list<SequenceLocation> result;
+ SequenceLocationModel& model = subanalysis_window->getModel();
+ browser.copySelectedTracksAsSeqLocation(result);
+ for(list<SequenceLocation>::iterator result_itor = result.begin();
+ result_itor != result.end();
+ ++result_itor)
+ {
+ model.push_back(*result_itor);
+ }
+
+ if (not subanalysis_window->isVisible()) {
+ subanalysis_window->show();
+ }
+}
+
+void MussaAlignedWindow::setAlignment(int alignment_index)
{
if (selected_paths.size() > 0) {
browser.centerOnPath(selected_paths[alignment_index].normalizedIndexes());
}
}
-void MussaAlignedWindow::toggleViewAlignment(size_t alignment_index)
+void MussaAlignedWindow::showBasePairsCopied(size_t bp_copied)
+{
+ QString msg("Copied ");
+ QString num;
+ num.setNum(bp_copied);
+ msg += num + " base pairs";
+ statusBar()->showMessage(msg, 5000);
+}
+
+void MussaAlignedWindow::toggleViewAlignment(int alignment_index)
{
view_paths[alignment_index]= not view_paths[alignment_index];
// perhaps it'd be better if we could erase specific sets
computeMatchLines();
}
-void MussaAlignedWindow::computeMatchLines()
+void MussaAlignedWindow::update()
{
- const vector<Sequence>& raw_sequence = analysis.sequences();
- vector<int> aligned_path;
- int i2, i3;
- int x_start, x_end;
- int window_length, win_i;
- int rc_1 = 0;
- int rc_2 = 0;
- bool rc_color;
- vector<bool> rc_list;
- bool full_match;
- vector<bool> matched;
- int align_counter;
+ browser.update();
+}
+void MussaAlignedWindow::updateTitle()
+{
+ std::string title("Sequence View: ");
+ if (analysis) {
+ title += analysis->get_title();
+ }
+ setWindowTitle(title.c_str());
+}
+
+void MussaAlignedWindow::computeMatchLines()
+{
browser.clear_links();
- align_counter = 0;
- for(vector<ExtendedConservedPath >::iterator pathz_i=selected_paths.begin();
- pathz_i != selected_paths.end();
- ++pathz_i)
+
+ // filter out conserved paths
+ list<ConservedPath> filtered_paths;
+ vector<ConservedPath>::iterator path_i = selected_paths.begin();
+ list<ConservedPath::path_type> result;
+ list<vector<bool> > reversed;
+
+ for(vector<ConservedPath>::size_type count = 0;
+ count != selected_paths.size();
+ ++count, ++path_i)
{
- if (view_paths[align_counter])
- {
- ExtendedConservedPath& a_path = *pathz_i;
- window_length = a_path.window_size;
- // determine which parts of the path are RC relative to first species
- rc_list = a_path.reverseComplimented();
-
- // loop over each bp in the conserved region for all sequences
- for(win_i = 0; win_i < window_length; win_i++)
- {
- aligned_path.clear();
- // determine which exact base pairs match between the sequences
- full_match = true;
- for(i2 = 0; i2 < a_path.size()-1; i2++)
- {
- // assume not rc as most likely, adjust below
- rc_1 = 0;
- rc_2 = 0;
- // no matter the case, any RC node needs adjustments
- if (a_path[i2] < 0)
- rc_1 = window_length-1;
- if (a_path[i2+1] < 0)
- rc_2 = window_length-1;
-
- x_start = (abs(a_path[i2]-rc_1+win_i));
- x_end = (abs(a_path[i2+1]-rc_2+win_i));
-
- // RC case handling
- // ugh, and xor...only want rc coloring if just one of the nodes is rc
- // if both nodes are rc, then they are 'normal' relative to each other
- if ( ( rc_list[i2] || rc_list[i2+1] ) &&
- !(rc_list[i2] && rc_list[i2+1] ) )
- { //the hideous rc matching logic - not complex, but annoying
- if ( !( ( (raw_sequence[i2][x_start] == 'A') &&
- (raw_sequence[i2+1][x_end] == 'T') ) ||
- ( (raw_sequence[i2][x_start] == 'T') &&
- (raw_sequence[i2+1][x_end] == 'A') ) ||
- ( (raw_sequence[i2][x_start] == 'G') &&
- (raw_sequence[i2+1][x_end] == 'C') ) ||
- ( (raw_sequence[i2][x_start] == 'C') &&
- (raw_sequence[i2+1][x_end] == 'G') ) ) )
- full_match = false;
- }
- else
- {
- if (!( (raw_sequence[i2][x_start] == raw_sequence[i2+1][x_end]) &&
- (raw_sequence[i2][x_start] != 'N') &&
- (raw_sequence[i2+1][x_end] != 'N') ) )
- full_match = false;
- }
- }
-
- // draw for matches stretching across all sequences
- if (full_match)
- {
- // now can draw the line for each bp in this window that matches
- // grrr, need to ask if anyone cares if I switch the seq
- // top-bot order...
- i3 = 0;
- //y_loc = y_min + 5;
- for(i2 = 0; i2 < a_path.size()-1; i2++)
- {
- // assume not rc as most likely, adjust below
- rc_1 = 0;
- rc_2 = 0;
- // no matter the case, any RC node needs adjustments
- if (a_path[i2] < 0)
- {
- rc_1 = window_length;
- }
- if (a_path[i2] < 0)
- {
- rc_2 = window_length;
- }
-
- // maybe shouldn't recalc these, but store values from first loop
- x_start = (abs((int) (a_path[i2]-rc_1+win_i)));
- x_end = (abs((int) (a_path[i2+1]-rc_2+win_i)));
- aligned_path.push_back(x_start);
- // if we're on the last time through the loop, save x_end too
- if (i2 == a_path.size()-2) {
- aligned_path.push_back(x_end);
- }
- }
- }
- if (aligned_path.size() > 0) {
- browser.link(aligned_path, rc_list,1);
- }
- }
- }
- align_counter++;
+ if (view_paths[count])
+ filtered_paths.push_back(*path_i);
}
-}
+ analysis->createLocalAlignment(filtered_paths.begin(),
+ filtered_paths.end(),
+ result,
+ reversed);
+ list<ConservedPath::path_type>::const_iterator result_i = result.begin();
+ list<vector<bool> >::const_iterator reversed_i = reversed.begin();
+ for(int i = 0; i != result.size(); ++i, ++result_i, ++reversed_i)
+ {
+ // make 1 base long links
+ browser.link(*result_i, *reversed_i, 1);
+ }
+}