aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.cpp49
-rw-r--r--main.h51
-rw-r--r--manipulationhandler.cpp10
-rw-r--r--manipulationhandler.h2
-rw-r--r--pm.pro2
-rw-r--r--projectionhistory.cpp191
-rw-r--r--projectionhistory.h54
-rw-r--r--projectionobserver.cpp210
-rw-r--r--projectionobserver.h61
9 files changed, 270 insertions, 360 deletions
diff --git a/main.cpp b/main.cpp
index a5aaf68..407753c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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);
diff --git a/main.h b/main.h
index e1964e7..de3a7f4 100644
--- a/main.h
+++ b/main.h
@@ -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;
diff --git a/pm.pro b/pm.pro
index 5b91bc0..c6e0cb0 100644
--- a/pm.pro
+++ b/pm.pro
@@ -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