diff options
-rw-r--r-- | main.cpp | 49 | ||||
-rw-r--r-- | main.h | 51 | ||||
-rw-r--r-- | manipulationhandler.cpp | 10 | ||||
-rw-r--r-- | manipulationhandler.h | 2 | ||||
-rw-r--r-- | pm.pro | 2 | ||||
-rw-r--r-- | projectionhistory.cpp | 191 | ||||
-rw-r--r-- | projectionhistory.h | 54 | ||||
-rw-r--r-- | projectionobserver.cpp | 210 | ||||
-rw-r--r-- | projectionobserver.h | 61 |
9 files changed, 270 insertions, 360 deletions
@@ -17,11 +17,11 @@ #include "barchart.h" #include "colormap.h" #include "transitioncontrol.h" +#include "projectionhistory.h" #include "manipulationhandler.h" #include "mapscalehandler.h" #include "selectionhandler.h" #include "brushinghandler.h" -#include "projectionobserver.h" static const int RNG_SEED = 1; @@ -158,7 +158,7 @@ int main(int argc, char **argv) TransitionControl *plotTC = engine.rootObjects()[0]->findChild<TransitionControl *>("plotTC"); // Shared object which stores modifications to projections - ProjectionHistory history; + ProjectionHistory history(X, cpIndices); m->projectionHistory = &history; // Keep track of the current cp (in order to save them later, if requested) @@ -178,28 +178,20 @@ int main(int argc, char **argv) m->projectionHistory, &ProjectionHistory::addMap); // ... and update visual components whenever the history changes - QObject::connect(m->projectionHistory, &ProjectionHistory::mapAdded, - m, &Main::updateMap); - QObject::connect(m->projectionHistory, &ProjectionHistory::undoPerformed, - m, &Main::updateMap); - QObject::connect(m->projectionHistory, &ProjectionHistory::resetPerformed, + QObject::connect(m->projectionHistory, &ProjectionHistory::currentMapChanged, m, &Main::updateMap); // Keep both scatterplots and the splat scaled equally and relative to the // full plot MapScaleHandler mapScaleHandler; - QObject::connect(m->projectionHistory, &ProjectionHistory::mapAdded, - &mapScaleHandler, &MapScaleHandler::scaleToMap); - QObject::connect(m->projectionHistory, &ProjectionHistory::undoPerformed, - &mapScaleHandler, &MapScaleHandler::scaleToMap); - QObject::connect(m->projectionHistory, &ProjectionHistory::resetPerformed, - &mapScaleHandler, &MapScaleHandler::scaleToMap); QObject::connect(&mapScaleHandler, &MapScaleHandler::scaleChanged, m->cpPlot, &Scatterplot::setScale); QObject::connect(&mapScaleHandler, &MapScaleHandler::scaleChanged, m->rpPlot, &Scatterplot::setScale); QObject::connect(&mapScaleHandler, &MapScaleHandler::scaleChanged, m->splat, &VoronoiSplat::setScale); + QObject::connect(m->projectionHistory, &ProjectionHistory::currentMapChanged, + &mapScaleHandler, &MapScaleHandler::scaleToMap); QObject::connect(m->splat, &VoronoiSplat::colorScaleChanged, m->colormap, &Colormap::setColorScale); @@ -225,7 +217,7 @@ int main(int argc, char **argv) QObject::connect(&rpSelectionHandler, &SelectionHandler::selectionChanged, m->rpBarChart, &BarChart::setSelection); - // Brushing between bar chart and respective scatterplot + // Brushing between each bar chart and respective scatterplot BrushingHandler cpBrushHandler; QObject::connect(m->cpPlot, &Scatterplot::itemInteractivelyBrushed, &cpBrushHandler, &BrushingHandler::brushItem); @@ -246,37 +238,31 @@ int main(int argc, char **argv) QObject::connect(&rpBrushHandler, &BrushingHandler::itemBrushed, m->rpBarChart, &BarChart::brushItem); - // Recompute values whenever projection changes - ProjectionObserver projectionObserver(X, cpIndices); - m->projectionObserver = &projectionObserver; - QObject::connect(m->projectionHistory, &ProjectionHistory::mapAdded, - m->projectionObserver, &ProjectionObserver::addMap); - QObject::connect(m->projectionObserver, &ProjectionObserver::cpValuesChanged, + // Update visual components whenever values change + QObject::connect(m->projectionHistory, &ProjectionHistory::cpValuesChanged, m->cpPlot, &Scatterplot::setColorData); - QObject::connect(m->projectionObserver, &ProjectionObserver::rpValuesChanged, + QObject::connect(m->projectionHistory, &ProjectionHistory::rpValuesChanged, m->splat, &VoronoiSplat::setValues); - QObject::connect(m->projectionObserver, &ProjectionObserver::cpValuesChanged, + QObject::connect(m->projectionHistory, &ProjectionHistory::cpValuesChanged, m->cpBarChart, &BarChart::setValues); - QObject::connect(m->projectionObserver, &ProjectionObserver::rpValuesChanged, + QObject::connect(m->projectionHistory, &ProjectionHistory::rpValuesChanged, m->rpBarChart, &BarChart::setValues); // Recompute values whenever selection changes QObject::connect(&cpSelectionHandler, &SelectionHandler::selectionChanged, - &projectionObserver, &ProjectionObserver::setCPSelection); + m->projectionHistory, &ProjectionHistory::setCPSelection); QObject::connect(&rpSelectionHandler, &SelectionHandler::selectionChanged, - &projectionObserver, &ProjectionObserver::setRPSelection); + m->projectionHistory, &ProjectionHistory::setRPSelection); // Connect projection components to rewinding mechanism QObject::connect(plotTC, &TransitionControl::tChanged, - &manipulationHandler, &ManipulationHandler::setRewind); - QObject::connect(plotTC, &TransitionControl::tChanged, - m->projectionObserver, &ProjectionObserver::setRewind); + m->projectionHistory, &ProjectionHistory::setRewind); - QObject::connect(&manipulationHandler, &ManipulationHandler::mapRewound, + QObject::connect(m->projectionHistory, &ProjectionHistory::mapRewound, m, &Main::updateMap); - QObject::connect(m->projectionObserver, &ProjectionObserver::cpValuesRewound, + QObject::connect(m->projectionHistory, &ProjectionHistory::cpValuesRewound, m->cpPlot, &Scatterplot::setColorData); - QObject::connect(m->projectionObserver, &ProjectionObserver::rpValuesRewound, + QObject::connect(m->projectionHistory, &ProjectionHistory::rpValuesRewound, m->splat, &VoronoiSplat::setValues); // General component set up @@ -297,7 +283,6 @@ int main(int argc, char **argv) m->setCPBarChartColorScale(Main::ColorScaleRainbow); m->setRPBarChartColorScale(Main::ColorScaleRainbow); - // This sets the initial CP configuration, triggering all the necessary // signals to set up the helper objects and visual components manipulationHandler.setCP(Ys); @@ -6,7 +6,6 @@ #include "colorscale.h" #include "continuouscolorscale.h" -#include "projectionobserver.h" #include "projectionhistory.h" #include "numericrange.h" #include "barchart.h" @@ -76,25 +75,6 @@ public: cpPlot->setAcceptHoverEvents(true); } - enum ObserverType { - ObserverCurrent = ProjectionObserver::ObserverCurrent, - ObserverDiffPrevious = ProjectionObserver::ObserverDiffPrevious, - ObserverDiffFirst = ProjectionObserver::ObserverDiffFirst - }; - - Q_INVOKABLE bool setObserverType(ObserverType observerType) { - switch (observerType) { - case ObserverCurrent: - return projectionObserver->setType(ProjectionObserver::ObserverCurrent); - case ObserverDiffPrevious: - return projectionObserver->setType(ProjectionObserver::ObserverDiffPrevious); - case ObserverDiffFirst: - return projectionObserver->setType(ProjectionObserver::ObserverDiffFirst); - } - - return false; - } - enum ColorScaleType { ColorScaleCategorical, ColorScaleContinuous, @@ -139,17 +119,29 @@ public: Scatterplot *cpPlot, *rpPlot; VoronoiSplat *splat; - // Shared object that controls manipulation history + // Object that controls manipulation history ProjectionHistory *projectionHistory; - ProjectionObserver *projectionObserver; - Q_INVOKABLE void undoManipulation() { - projectionHistory->undo(); - projectionObserver->undo(); - } - Q_INVOKABLE void resetManipulation() { - projectionHistory->reset(); - projectionObserver->reset(); + Q_INVOKABLE void undoManipulation() { projectionHistory->undo(); } + Q_INVOKABLE void resetManipulation() { projectionHistory->reset(); } + + enum ObserverType { + ObserverCurrent = ProjectionHistory::ObserverCurrent, + ObserverDiffPrevious = ProjectionHistory::ObserverDiffPrevious, + ObserverDiffFirst = ProjectionHistory::ObserverDiffFirst + }; + + Q_INVOKABLE bool setObserverType(ObserverType observerType) { + switch (observerType) { + case ObserverCurrent: + return projectionHistory->setType(ProjectionHistory::ObserverCurrent); + case ObserverDiffPrevious: + return projectionHistory->setType(ProjectionHistory::ObserverDiffPrevious); + case ObserverDiffFirst: + return projectionHistory->setType(ProjectionHistory::ObserverDiffFirst); + } + + return false; } public slots: @@ -195,7 +187,6 @@ private: , cpPlot(0) , rpPlot(0) , splat(0) - , projectionObserver(0) , projectionHistory(0) { } diff --git a/manipulationhandler.cpp b/manipulationhandler.cpp index f561ad7..daaba01 100644 --- a/manipulationhandler.cpp +++ b/manipulationhandler.cpp @@ -35,13 +35,3 @@ void ManipulationHandler::setCP(const arma::mat &Ys) emit mapChanged(Y); } - -void ManipulationHandler::setRewind(double t) -{ - if (!m_history->hasPrev()) { - return; - } - - arma::mat Y = m_history->Y() * t + m_history->prev() * (1.0 - t); - emit mapRewound(Y); -} diff --git a/manipulationhandler.h b/manipulationhandler.h index b1aed61..9199c93 100644 --- a/manipulationhandler.h +++ b/manipulationhandler.h @@ -27,11 +27,9 @@ public: signals: void mapChanged(const arma::mat &Y) const; - void mapRewound(const arma::mat &Y) const; public slots: void setCP(const arma::mat &Ys); - void setRewind(double t); private: arma::mat m_X; @@ -35,7 +35,6 @@ HEADERS += main.h \ numericrange.h \ selectionhandler.h \ brushinghandler.h \ - projectionobserver.h \ projectionhistory.h \ skelft.h \ skelftkernel.h \ @@ -56,7 +55,6 @@ SOURCES += main.cpp \ mapscalehandler.cpp \ selectionhandler.cpp \ brushinghandler.cpp \ - projectionobserver.cpp \ projectionhistory.cpp \ skelft_core.cpp \ lamp.cpp \ diff --git a/projectionhistory.cpp b/projectionhistory.cpp index bd55431..f450e0e 100644 --- a/projectionhistory.cpp +++ b/projectionhistory.cpp @@ -1,19 +1,66 @@ #include "projectionhistory.h" -ProjectionHistory::ProjectionHistory(QObject *parent) - : QObject(parent) +#include <algorithm> +#include <cmath> + +#include "mp.h" +#include "numericrange.h" + +ProjectionHistory::ProjectionHistory(const arma::mat &X, + const arma::uvec &cpIndices) + : m_type(ObserverCurrent) + , m_X(X) + , m_cpIndices(cpIndices) + , m_rpIndices(X.n_rows - cpIndices.n_elem) + , m_cpSelectionEmpty(true) + , m_rpSelectionEmpty(true) + , m_values(X.n_rows) + , m_prevValues(X.n_rows) + , m_firstValues(X.n_rows) , m_hasFirst(false) , m_hasPrev(false) { + m_distX = mp::dist(m_X); + + NumericRange<arma::uword> allIndices(0, m_X.n_rows); + std::set_symmetric_difference(allIndices.cbegin(), allIndices.cend(), + m_cpIndices.cbegin(), m_cpIndices.cend(), m_rpIndices.begin()); + + computeAlphas(); } +void ProjectionHistory::computeAlphas() +{ + m_influences.set_size(m_X.n_rows); + m_alphas.set_size(m_rpIndices.n_elem, m_cpIndices.n_elem); + + for (arma::uword i = 0; i < m_rpIndices.n_elem; i++) { + double sum = 0; + const arma::rowvec &x = m_X.row(m_rpIndices[i]); + for (arma::uword j = 0; j < m_cpIndices.n_elem; j++) { + double norm = arma::norm(x - m_X.row(m_cpIndices[j])); + m_alphas(i, j) = 1.0 / std::max(norm * norm, 1e-6); + sum += m_alphas(i, j); + } + + for (arma::uword j = 0; j < m_cpIndices.n_elem; j++) { + m_alphas(i, j) /= sum; + } + } +} void ProjectionHistory::undo() { if (m_hasPrev) { m_hasPrev = false; m_Y = m_prevY; + m_distY = m_prevDistY; + m_values = m_prevValues; - emit undoPerformed(m_Y); + emit undoPerformed(); + emit currentMapChanged(m_Y); + if (m_cpSelectionEmpty && m_rpSelectionEmpty) { + emitValuesChanged(); + } } } @@ -22,8 +69,14 @@ void ProjectionHistory::reset() if (m_hasFirst) { m_hasPrev = false; m_Y = m_firstY; + m_distY = m_firstDistY; + m_values = m_firstValues; - emit resetPerformed(m_Y); + emit resetPerformed(); + emit currentMapChanged(m_Y); + if (m_cpSelectionEmpty && m_rpSelectionEmpty) { + emitValuesChanged(); + } } } @@ -32,14 +85,142 @@ void ProjectionHistory::addMap(const arma::mat &Y) if (m_hasFirst) { m_hasPrev = true; m_prevY = m_Y; + m_prevDistY = m_distY; + m_prevValues = m_values; } m_Y = Y; + m_distY = mp::dist(Y); + + mp::aggregatedError(m_distX, m_distY, m_values); if (!m_hasFirst) { m_hasFirst = true; m_firstY = m_Y; + m_firstDistY = m_distY; + m_firstValues = m_values; + } + + emit currentMapChanged(m_Y); + if (m_cpSelectionEmpty && m_rpSelectionEmpty) { + emitValuesChanged(); + } +} + +bool ProjectionHistory::setType(ObserverType type) +{ + if (m_type == type) { + return true; + } + + if ((type == ObserverDiffPrevious && !m_hasPrev) + || (type == ObserverDiffFirst && !m_hasFirst)) { + return false; + } + + m_type = type; + if (!m_cpSelectionEmpty || !m_rpSelectionEmpty) { + // We changed our type, but cannot emit values since we have non-empty + // selections + return true; + } + return emitValuesChanged(); +} + +void ProjectionHistory::setCPSelection(const std::vector<bool> &cpSelection) +{ + m_cpSelection.clear(); + for (int i = 0; i < cpSelection.size(); i++) { + if (cpSelection[i]) { + m_cpSelection.push_back(i); + } + } + m_cpSelectionEmpty = m_cpSelection.empty(); + + if (!m_cpSelectionEmpty) { + // compute the influence of CP selection on each RP + for (arma::uword rp = 0; rp < m_rpIndices.n_elem; rp++) { + m_influences[m_rpIndices[rp]] = 0; + const arma::rowvec &row = m_alphas.row(rp); + for (auto cp: m_cpSelection) { + m_influences[m_rpIndices[rp]] += row[cp]; + } + } + + emit rpValuesChanged(m_influences(m_rpIndices)); + } else { + emitValuesChanged(); + } +} + +void ProjectionHistory::setRPSelection(const std::vector<bool> &rpSelection) +{ + m_rpSelection.clear(); + for (int i = 0; i < rpSelection.size(); i++) { + if (rpSelection[i]) { + m_rpSelection.push_back(i); + } + } + m_rpSelectionEmpty = m_rpSelection.empty(); + + if (!m_rpSelectionEmpty) { + // compute how influent is each CP on RP selection + for (arma::uword cp = 0; cp < m_cpIndices.n_elem; cp++) { + m_influences[m_cpIndices[cp]] = 0; + for (auto rp: m_rpSelection) { + m_influences[m_cpIndices[cp]] += m_alphas(rp, cp); + } + } + + emit cpValuesChanged(m_influences(m_cpIndices)); + } else { + emit cpValuesChanged(arma::vec()); + } +} + +bool ProjectionHistory::emitValuesChanged() const +{ + switch (m_type) { + case ObserverCurrent: + emit rpValuesChanged(m_values(m_rpIndices)); + emit valuesChanged(m_values); + return true; + case ObserverDiffPrevious: + if (m_hasPrev) { + arma::vec diff = m_values - m_prevValues; + emit rpValuesChanged(diff(m_rpIndices)); + emit valuesChanged(diff); + return true; + } + return false; + case ObserverDiffFirst: + if (m_hasFirst) { + arma::vec diff = m_values - m_firstValues; + emit rpValuesChanged(diff(m_rpIndices)); + emit valuesChanged(diff); + return true; + } + return false; + default: + return false; + } +} + +void ProjectionHistory::setRewind(double t) +{ + if (!m_hasPrev) { + return; + } + + arma::mat Y = m_Y * t + m_prevY * (1.0 - t); + emit mapRewound(Y); + + if (!m_cpSelectionEmpty || !m_rpSelectionEmpty) { + return; } - emit mapAdded(m_Y); + arma::vec values = m_values * t + m_prevValues * (1.0 - t); + emit cpValuesRewound(values(m_cpIndices)); + emit rpValuesRewound(values(m_rpIndices)); + emit valuesRewound(values); } diff --git a/projectionhistory.h b/projectionhistory.h index 9fe9ffc..a18af0c 100644 --- a/projectionhistory.h +++ b/projectionhistory.h @@ -10,11 +10,17 @@ class ProjectionHistory { Q_OBJECT public: - explicit ProjectionHistory(QObject *parent = 0); + enum ObserverType { + ObserverCurrent, + ObserverDiffPrevious, + ObserverDiffFirst + }; - const arma::mat &Y() const { return m_Y; } - const arma::mat &first() const { return m_firstY; } - const arma::mat &prev() const { return m_prevY; } + ProjectionHistory(const arma::mat &X, const arma::uvec &cpIndices); + + const arma::mat &Y() const { return m_Y; } + const arma::mat &firstY() const { return m_firstY; } + const arma::mat &prevY() const { return m_prevY; } bool hasFirst() const { return m_hasFirst; } bool hasPrev() const { return m_hasPrev; } @@ -23,15 +29,47 @@ public: void reset(); signals: - void undoPerformed(const arma::mat &prevY) const; - void resetPerformed(const arma::mat &firstY) const; - void mapAdded(const arma::mat &newY) const; + void undoPerformed() const; + void resetPerformed() const; + + void currentMapChanged(const arma::mat &Y) const; + void valuesChanged(const arma::vec &values) const; + void cpValuesChanged(const arma::vec &values) const; + void rpValuesChanged(const arma::vec &values) const; + + void mapRewound(const arma::mat &Y) const; + void valuesRewound(const arma::vec &values) const; + void cpValuesRewound(const arma::vec &values) const; + void rpValuesRewound(const arma::vec &values) const; public slots: void addMap(const arma::mat &Y); + bool setType(ObserverType type); + void setCPSelection(const std::vector<bool> &cpSelection); + void setRPSelection(const std::vector<bool> &rpSelection); + + void setRewind(double t); + private: - arma::mat m_Y, m_firstY, m_prevY; + bool emitValuesChanged() const; + + ObserverType m_type; + + arma::mat m_X, m_Y, m_firstY, m_prevY; + arma::mat m_distX, m_distY, m_firstDistY, m_prevDistY; + arma::uvec m_cpIndices, m_rpIndices; + + bool m_cpSelectionEmpty, m_rpSelectionEmpty; + std::vector<int> m_cpSelection, m_rpSelection; + + // alpha(i, j): the influence CP j has on RP i + void computeAlphas(); + arma::mat m_alphas, m_influences; + + // TODO: one per implemented measure + arma::vec m_values, m_firstValues, m_prevValues; + bool m_hasFirst, m_hasPrev; }; diff --git a/projectionobserver.cpp b/projectionobserver.cpp deleted file mode 100644 index 94f266a..0000000 --- a/projectionobserver.cpp +++ /dev/null @@ -1,210 +0,0 @@ -#include "projectionobserver.h" - -#include <algorithm> -#include <cmath> - -#include "mp.h" -#include "numericrange.h" - -ProjectionObserver::ProjectionObserver(const arma::mat &X, - const arma::uvec &cpIndices) - : m_type(ObserverCurrent) - , m_X(X) - , m_cpIndices(cpIndices) - , m_rpIndices(X.n_rows - cpIndices.n_elem) - , m_cpSelectionEmpty(true) - , m_rpSelectionEmpty(true) - , m_values(X.n_rows) - , m_prevValues(X.n_rows) - , m_firstValues(X.n_rows) - , m_hasFirst(false) - , m_hasPrev(false) -{ - m_distX = mp::dist(m_X); - - NumericRange<arma::uword> allIndices(0, m_X.n_rows); - std::set_symmetric_difference(allIndices.cbegin(), allIndices.cend(), - m_cpIndices.cbegin(), m_cpIndices.cend(), m_rpIndices.begin()); - - computeAlphas(); -} - -void ProjectionObserver::computeAlphas() -{ - m_influences.set_size(m_X.n_rows); - m_alphas.set_size(m_rpIndices.n_elem, m_cpIndices.n_elem); - - for (arma::uword i = 0; i < m_rpIndices.n_elem; i++) { - double sum = 0; - const arma::rowvec &x = m_X.row(m_rpIndices[i]); - for (arma::uword j = 0; j < m_cpIndices.n_elem; j++) { - double norm = arma::norm(x - m_X.row(m_cpIndices[j])); - m_alphas(i, j) = 1.0 / std::max(norm * norm, 1e-6); - sum += m_alphas(i, j); - } - - for (arma::uword j = 0; j < m_cpIndices.n_elem; j++) { - m_alphas(i, j) /= sum; - } - } -} - -void ProjectionObserver::undo() -{ - if (m_hasPrev) { - m_hasPrev = false; - m_distY = m_prevDistY; - m_values = m_prevValues; - - if (m_cpSelectionEmpty && m_rpSelectionEmpty) { - emitValuesChanged(); - } - } -} - -void ProjectionObserver::reset() -{ - if (m_hasFirst) { - m_hasPrev = false; - m_distY = m_firstDistY; - m_values = m_firstValues; - - if (m_cpSelectionEmpty && m_rpSelectionEmpty) { - emitValuesChanged(); - } - } -} - -void ProjectionObserver::addMap(const arma::mat &Y) -{ - if (m_hasFirst) { - m_hasPrev = true; - m_prevDistY = m_distY; - m_prevValues = m_values; - } - - m_distY = mp::dist(Y); - - mp::aggregatedError(m_distX, m_distY, m_values); - - if (!m_hasFirst) { - m_hasFirst = true; - m_firstDistY = m_distY; - m_firstValues = m_values; - } - - if (m_cpSelectionEmpty && m_rpSelectionEmpty) { - emitValuesChanged(); - } -} - -bool ProjectionObserver::setType(ObserverType type) -{ - if (m_type == type) { - return true; - } - - if ((type == ObserverDiffPrevious && !m_hasPrev) - || (type == ObserverDiffFirst && !m_hasFirst)) { - return false; - } - - m_type = type; - if (!m_cpSelectionEmpty || !m_rpSelectionEmpty) { - // We changed our type, but cannot emit values since we have non-empty - // selections - return true; - } - return emitValuesChanged(); -} - -void ProjectionObserver::setCPSelection(const std::vector<bool> &cpSelection) -{ - m_cpSelection.clear(); - for (int i = 0; i < cpSelection.size(); i++) { - if (cpSelection[i]) { - m_cpSelection.push_back(i); - } - } - m_cpSelectionEmpty = m_cpSelection.empty(); - - if (!m_cpSelectionEmpty) { - // compute the influence of CP selection on each RP - for (arma::uword rp = 0; rp < m_rpIndices.n_elem; rp++) { - m_influences[m_rpIndices[rp]] = 0; - const arma::rowvec &row = m_alphas.row(rp); - for (auto cp: m_cpSelection) { - m_influences[m_rpIndices[rp]] += row[cp]; - } - } - - emit rpValuesChanged(m_influences(m_rpIndices)); - } else { - emitValuesChanged(); - } -} - -void ProjectionObserver::setRPSelection(const std::vector<bool> &rpSelection) -{ - m_rpSelection.clear(); - for (int i = 0; i < rpSelection.size(); i++) { - if (rpSelection[i]) { - m_rpSelection.push_back(i); - } - } - m_rpSelectionEmpty = m_rpSelection.empty(); - - if (!m_rpSelectionEmpty) { - // compute how influent is each CP on RP selection - for (arma::uword cp = 0; cp < m_cpIndices.n_elem; cp++) { - m_influences[m_cpIndices[cp]] = 0; - for (auto rp: m_rpSelection) { - m_influences[m_cpIndices[cp]] += m_alphas(rp, cp); - } - } - - emit cpValuesChanged(m_influences(m_cpIndices)); - } else { - emit cpValuesChanged(arma::vec()); - } -} - -bool ProjectionObserver::emitValuesChanged() const -{ - switch (m_type) { - case ObserverCurrent: - emit rpValuesChanged(m_values(m_rpIndices)); - emit valuesChanged(m_values); - return true; - case ObserverDiffPrevious: - if (m_hasPrev) { - arma::vec diff = m_values - m_prevValues; - emit rpValuesChanged(diff(m_rpIndices)); - emit valuesChanged(diff); - return true; - } - return false; - case ObserverDiffFirst: - if (m_hasFirst) { - arma::vec diff = m_values - m_firstValues; - emit rpValuesChanged(diff(m_rpIndices)); - emit valuesChanged(diff); - return true; - } - return false; - default: - return false; - } -} - -void ProjectionObserver::setRewind(double t) -{ - if (!m_hasPrev || !m_cpSelectionEmpty || !m_rpSelectionEmpty) { - return; - } - - arma::vec values = m_values * t + m_prevValues * (1.0 - t); - emit cpValuesRewound(values(m_cpIndices)); - emit rpValuesRewound(values(m_rpIndices)); - emit valuesRewound(values); -} diff --git a/projectionobserver.h b/projectionobserver.h deleted file mode 100644 index c021482..0000000 --- a/projectionobserver.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef PROJECTIONOBSERVER_H -#define PROJECTIONOBSERVER_H - -#include <QObject> -#include <armadillo> - -#include "projectionhistory.h" - -class ProjectionObserver - : public QObject -{ - Q_OBJECT -public: - enum ObserverType { - ObserverCurrent, - ObserverDiffPrevious, - ObserverDiffFirst - }; - - ProjectionObserver(const arma::mat &X, - const arma::uvec &cpIndices); - - void undo(); - void reset(); - -signals: - void valuesChanged(const arma::vec &values) const; - void cpValuesChanged(const arma::vec &values) const; - void rpValuesChanged(const arma::vec &values) const; - void valuesRewound(const arma::vec &values) const; - void cpValuesRewound(const arma::vec &values) const; - void rpValuesRewound(const arma::vec &values) const; - -public slots: - void addMap(const arma::mat &Y); - bool setType(ObserverType type); - void setCPSelection(const std::vector<bool> &cpSelection); - void setRPSelection(const std::vector<bool> &rpSelection); - void setRewind(double t); - -private: - bool emitValuesChanged() const; - - ObserverType m_type; - arma::mat m_X; - arma::mat m_distX, m_distY, m_firstDistY, m_prevDistY; - arma::uvec m_cpIndices, m_rpIndices; - - bool m_cpSelectionEmpty, m_rpSelectionEmpty; - std::vector<int> m_cpSelection, m_rpSelection; - - // alpha(i, j): the influence CP j has on RP i - void computeAlphas(); - arma::mat m_alphas, m_influences; - - // TODO: one per implemented measure - arma::vec m_values, m_firstValues, m_prevValues; - bool m_hasFirst, m_hasPrev; -}; - -#endif // PROJECTIONOBSERVER_H |