From 3c92c6256fd796f24db177caf813ba52e2389ff8 Mon Sep 17 00:00:00 2001 From: Samuel Fadel Date: Wed, 13 Apr 2016 12:20:01 -0300 Subject: Bundling now supports selection. Selection is implemented via main() updating the line plot using the current active selection. Beware of bug (issue #23). Also adds support for setting the line width, while changing the default line width to 2 pixels wide. ProjectionHistory: now reports changes to selections relative to the whole dataset, not only CPs/RPs. --- main.cpp | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 111 insertions(+), 19 deletions(-) (limited to 'main.cpp') diff --git a/main.cpp b/main.cpp index bf9042a..8cc9323 100644 --- a/main.cpp +++ b/main.cpp @@ -43,6 +43,32 @@ arma::uvec extractCPs(const arma::mat &X) return indices.subvec(0, numCPs-1); } +void overviewBundles(const Main *m) +{ + const arma::mat &unreliability = m->projectionHistory->unreliability(); + arma::uvec indicesLargest = arma::sort_index(unreliability, "descending"); + arma::uword numLargest = m->projectionHistory->Y().n_rows * 0.1f; + indicesLargest = indicesLargest.subvec(0, numLargest-1); + m->bundlePlot->setValues(unreliability(indicesLargest)); + + const arma::uvec &cpIndices = m->projectionHistory->cpIndices(); + arma::uvec CPs = cpIndices(indicesLargest / unreliability.n_rows); + + const arma::uvec &rpIndices = m->projectionHistory->rpIndices(); + arma::uvec RPs = indicesLargest; + RPs.transform([&unreliability](arma::uword v) { + return v % unreliability.n_rows; + }); + RPs = rpIndices(RPs); + + arma::uvec indices(CPs.n_elem + RPs.n_elem); + for (arma::uword i = 0; i < CPs.n_elem; i++) { + indices[2*i + 0] = CPs(i); + indices[2*i + 1] = RPs(i); + } + m->bundlePlot->setLines(indices, m->projectionHistory->Y()); +} + int main(int argc, char **argv) { QApplication app(argc, argv); @@ -201,14 +227,47 @@ int main(int argc, char **argv) QObject::connect(m->projectionHistory, &ProjectionHistory::currentMapChanged, [m](const arma::mat &Y) { // ... and bundling + overviewBundles(m); + }); + + // Linking between selections + SelectionHandler cpSelectionHandler(cpIndices.n_elem); + QObject::connect(m->cpPlot, &Scatterplot::selectionInteractivelyChanged, + &cpSelectionHandler, &SelectionHandler::setSelection); + QObject::connect(m->cpBarChart, &BarChart::selectionInteractivelyChanged, + &cpSelectionHandler, &SelectionHandler::setSelection); + QObject::connect(&cpSelectionHandler, &SelectionHandler::selectionChanged, + m->cpPlot, &Scatterplot::setSelection); + QObject::connect(&cpSelectionHandler, &SelectionHandler::selectionChanged, + m->cpBarChart, &BarChart::setSelection); + QObject::connect(&cpSelectionHandler, &SelectionHandler::selectionChanged, + [m](const std::vector &cpSelection) { + // given some CPs, see unexpected RPs *influenced by* them + std::vector selectedCPIndices; + for (int i = 0; i < cpSelection.size(); i++) { + if (cpSelection[i]) { + selectedCPIndices.push_back(i); + } + } + + if (selectedCPIndices.empty()) { + overviewBundles(m); + return; + } + + arma::uvec selectedCPs(selectedCPIndices.size()); + std::copy(selectedCPIndices.begin(), selectedCPIndices.end(), + selectedCPs.begin()); + + // Only the 10% largest values, filtered by the selected RPs const arma::mat &unreliability = m->projectionHistory->unreliability(); - arma::uvec indicesLargest = arma::sort_index(unreliability, "descending"); - auto numLargest = Y.n_rows * 0.1f; + arma::uvec indicesLargest = arma::sort_index(unreliability.cols(selectedCPs), "descending"); + arma::uword numLargest = indicesLargest.n_elem * 0.1f; indicesLargest = indicesLargest.subvec(0, numLargest-1); m->bundlePlot->setValues(unreliability(indicesLargest)); const arma::uvec &cpIndices = m->projectionHistory->cpIndices(); - arma::uvec CPs = cpIndices(indicesLargest / unreliability.n_rows); + arma::uvec CPs = cpIndices(selectedCPs(indicesLargest / unreliability.n_rows)); const arma::uvec &rpIndices = m->projectionHistory->rpIndices(); arma::uvec RPs = indicesLargest; @@ -219,23 +278,12 @@ int main(int argc, char **argv) arma::uvec indices(CPs.n_elem + RPs.n_elem); for (arma::uword i = 0; i < CPs.n_elem; i++) { - indices(2*i + 0) = CPs(i); - indices(2*i + 1) = RPs(i); + indices[2*i + 0] = CPs(i); + indices[2*i + 1] = RPs(i); } - m->bundlePlot->setLines(indices, Y); + m->bundlePlot->setLines(indices, m->projectionHistory->Y()); }); - // Linking between selections - SelectionHandler cpSelectionHandler(cpIndices.n_elem); - QObject::connect(m->cpPlot, &Scatterplot::selectionInteractivelyChanged, - &cpSelectionHandler, &SelectionHandler::setSelection); - QObject::connect(m->cpBarChart, &BarChart::selectionInteractivelyChanged, - &cpSelectionHandler, &SelectionHandler::setSelection); - QObject::connect(&cpSelectionHandler, &SelectionHandler::selectionChanged, - m->cpPlot, &Scatterplot::setSelection); - QObject::connect(&cpSelectionHandler, &SelectionHandler::selectionChanged, - m->cpBarChart, &BarChart::setSelection); - SelectionHandler rpSelectionHandler(X.n_rows - cpIndices.n_elem); QObject::connect(m->rpPlot, &Scatterplot::selectionInteractivelyChanged, &rpSelectionHandler, &SelectionHandler::setSelection); @@ -245,6 +293,49 @@ int main(int argc, char **argv) m->rpPlot, &Scatterplot::setSelection); QObject::connect(&rpSelectionHandler, &SelectionHandler::selectionChanged, m->rpBarChart, &BarChart::setSelection); + QObject::connect(&rpSelectionHandler, &SelectionHandler::selectionChanged, + [m](const std::vector &rpSelection) { + // given some RPs, see unexpected CPs *influencing* them + std::vector selectedRPIndices; + for (int i = 0; i < rpSelection.size(); i++) { + if (rpSelection[i]) { + selectedRPIndices.push_back(i); + } + } + + if (selectedRPIndices.empty()) { + overviewBundles(m); + return; + } + + arma::uvec selectedRPs(selectedRPIndices.size()); + std::copy(selectedRPIndices.begin(), selectedRPIndices.end(), + selectedRPs.begin()); + + // Only the 10% largest values, filtered by the selected RPs + const arma::mat &unreliability = m->projectionHistory->unreliability(); + arma::uvec indicesLargest = arma::sort_index(unreliability.rows(selectedRPs), "descending"); + arma::uword numLargest = indicesLargest.n_elem * 0.1f; + indicesLargest = indicesLargest.subvec(0, numLargest-1); + m->bundlePlot->setValues(unreliability(indicesLargest)); + + const arma::uvec &cpIndices = m->projectionHistory->cpIndices(); + arma::uvec CPs = cpIndices(indicesLargest / selectedRPs.n_elem); + + const arma::uvec &rpIndices = m->projectionHistory->rpIndices(); + arma::uvec RPs = indicesLargest; + RPs.transform([&selectedRPs](arma::uword v) { + return v % selectedRPs.n_elem; + }); + RPs = rpIndices(selectedRPs(RPs)); + + arma::uvec indices(CPs.n_elem + RPs.n_elem); + for (arma::uword i = 0; i < CPs.n_elem; i++) { + indices[2*i + 0] = CPs(i); + indices[2*i + 1] = RPs(i); + } + m->bundlePlot->setLines(indices, m->projectionHistory->Y()); + }); // Brushing between each bar chart and respective scatterplot BrushingHandler cpBrushHandler; @@ -304,16 +395,17 @@ int main(int argc, char **argv) QObject::connect(m->projectionHistory, &ProjectionHistory::rpValuesChanged, m->rpBarChart, &BarChart::setValues); - // Recompute values whenever selection changes + // ProjectionHistory takes special care of separate CP/RP selections QObject::connect(&cpSelectionHandler, &SelectionHandler::selectionChanged, m->projectionHistory, &ProjectionHistory::setCPSelection); QObject::connect(&rpSelectionHandler, &SelectionHandler::selectionChanged, m->projectionHistory, &ProjectionHistory::setRPSelection); + //QObject::connect(m->projectionHistory, &ProjectionHistory::selectionChanged, + // m->bundlePlot, LinePlot::selectionChanged); // Connect projection components to rewinding mechanism QObject::connect(plotTC, &TransitionControl::tChanged, m->projectionHistory, &ProjectionHistory::setRewind); - QObject::connect(m->projectionHistory, &ProjectionHistory::mapRewound, m, &Main::updateMap); QObject::connect(m->projectionHistory, &ProjectionHistory::cpValuesRewound, -- cgit v1.2.3