From eb214cd50e8a36318c7012545d142d5133e95415 Mon Sep 17 00:00:00 2001 From: Samuel Fadel Date: Wed, 20 Jan 2016 01:00:56 +0100 Subject: Added color scale selection and aggregate error. * Projection metrics can be shown as current, diff to previous and diff to original (original seems bugged, beware) --- main.cpp | 12 ++-- main.h | 147 ++++++++++++++++--------------------------------- main_view.qml | 17 +++++- projectionobserver.cpp | 61 ++++++++++++++++++-- projectionobserver.h | 14 ++++- 5 files changed, 138 insertions(+), 113 deletions(-) diff --git a/main.cpp b/main.cpp index 3add8e7..febeea2 100644 --- a/main.cpp +++ b/main.cpp @@ -162,18 +162,22 @@ int main(int argc, char **argv) QObject::connect(m->rpPlot, SIGNAL(scaleChanged(const LinearScale &, const LinearScale &)), m->cpPlot, SLOT(setScale(const LinearScale &, const LinearScale &))); + QObject::connect(m->splat, SIGNAL(colorScaleChanged(const ColorScale &)), + m->colormap, SLOT(setColorScale(const ColorScale &))); + m->barChart = engine.rootObjects()[0]->findChild("barChart"); m->barChart->setAcceptedMouseButtons(Qt::LeftButton); m->setBarChartColorScale(Main::ColorScaleContinuous); ProjectionObserver projectionObserver(X, cpIndices); + m->projectionObserver = &projectionObserver; QObject::connect(&interactionHandler, SIGNAL(cpChanged(const arma::mat &)), - &projectionObserver, SLOT(setMap(const arma::mat &))); - QObject::connect(&projectionObserver, SIGNAL(mapChanged(const arma::vec &)), + m->projectionObserver, SLOT(setMap(const arma::mat &))); + QObject::connect(m->projectionObserver, SIGNAL(valuesChanged(const arma::vec &)), m->rpPlot, SLOT(setColorData(const arma::vec &))); - QObject::connect(&projectionObserver, SIGNAL(mapChanged(const arma::vec &)), + QObject::connect(m->projectionObserver, SIGNAL(valuesChanged(const arma::vec &)), m->splat, SLOT(setValues(const arma::vec &))); - QObject::connect(&projectionObserver, SIGNAL(mapChanged(const arma::vec &)), + QObject::connect(m->projectionObserver, SIGNAL(valuesChanged(const arma::vec &)), m->barChart, SLOT(setValues(const arma::vec &))); //history->addHistoryItem(Ys); diff --git a/main.h b/main.h index 69c58f0..f3bcb66 100644 --- a/main.h +++ b/main.h @@ -4,17 +4,18 @@ #include #include -#include "colorscale.h" -#include "continuouscolorscale.h" - #include "barchart.h" #include "colormap.h" +#include "colorscale.h" +#include "continuouscolorscale.h" +#include "projectionobserver.h" #include "scatterplot.h" #include "voronoisplat.h" class Main : public QObject { Q_OBJECT + Q_ENUMS(ObserverType) Q_ENUMS(ColorScaleType) public: static Main *instance() { @@ -57,6 +58,16 @@ public: arma::mat X() const { return m_dataset.cols(0, m_dataset.n_cols - 2); } arma::vec labels() const { return m_dataset.col(m_dataset.n_cols - 1); } + enum ObserverType { + ObserverCurrent = ProjectionObserver::OBSERVER_CURRENT, + ObserverDiffPrevious = ProjectionObserver::OBSERVER_DIFF_PREVIOUS, + ObserverDiffOriginal = ProjectionObserver::OBSERVER_DIFF_ORIGINAL + }; + + Q_INVOKABLE bool setObserverType(ObserverType observerType) { + return projectionObserver->setType((int) observerType); + } + enum ColorScaleType { ColorScaleCategorical, ColorScaleContinuous, @@ -64,94 +75,29 @@ public: ColorScaleRainbow }; - ColorScale *COLOR_SCALE_CATEGORICAL; - ColorScale *COLOR_SCALE_CONTINUOUS; - ColorScale *COLOR_SCALE_DIVERGENT; - ColorScale *COLOR_SCALE_RAINBOW; + ColorScale COLOR_SCALE_CATEGORICAL; + ColorScale COLOR_SCALE_CONTINUOUS; + ColorScale COLOR_SCALE_DIVERGENT; + ColorScale COLOR_SCALE_RAINBOW; Q_INVOKABLE void setCPPlotColorScale(ColorScaleType colorScaleType) { - switch (colorScaleType) { - case ColorScaleCategorical: - cpPlot->setColorScale(*COLOR_SCALE_CATEGORICAL); - break; - case ColorScaleContinuous: - cpPlot->setColorScale(*COLOR_SCALE_CONTINUOUS); - break; - case ColorScaleDivergent: - cpPlot->setColorScale(*COLOR_SCALE_DIVERGENT); - break; - case ColorScaleRainbow: - cpPlot->setColorScale(*COLOR_SCALE_RAINBOW); - break; - } + cpPlot->setColorScale(getColorScale(colorScaleType)); } Q_INVOKABLE void setRPPlotColorScale(ColorScaleType colorScaleType) { - switch (colorScaleType) { - case ColorScaleCategorical: - rpPlot->setColorScale(*COLOR_SCALE_CATEGORICAL); - break; - case ColorScaleContinuous: - rpPlot->setColorScale(*COLOR_SCALE_CONTINUOUS); - break; - case ColorScaleDivergent: - rpPlot->setColorScale(*COLOR_SCALE_DIVERGENT); - break; - case ColorScaleRainbow: - rpPlot->setColorScale(*COLOR_SCALE_RAINBOW); - break; - } + rpPlot->setColorScale(getColorScale(colorScaleType)); } Q_INVOKABLE void setColormapColorScale(ColorScaleType colorScaleType) { - switch (colorScaleType) { - case ColorScaleCategorical: - colormap->setColorScale(*COLOR_SCALE_CATEGORICAL); - break; - case ColorScaleContinuous: - colormap->setColorScale(*COLOR_SCALE_CONTINUOUS); - break; - case ColorScaleDivergent: - colormap->setColorScale(*COLOR_SCALE_DIVERGENT); - break; - case ColorScaleRainbow: - colormap->setColorScale(*COLOR_SCALE_RAINBOW); - break; - } + colormap->setColorScale(getColorScale(colorScaleType)); } Q_INVOKABLE void setBarChartColorScale(ColorScaleType colorScaleType) { - switch (colorScaleType) { - case ColorScaleCategorical: - barChart->setColorScale(*COLOR_SCALE_CATEGORICAL); - break; - case ColorScaleContinuous: - barChart->setColorScale(*COLOR_SCALE_CONTINUOUS); - break; - case ColorScaleDivergent: - barChart->setColorScale(*COLOR_SCALE_DIVERGENT); - break; - case ColorScaleRainbow: - barChart->setColorScale(*COLOR_SCALE_RAINBOW); - break; - } + barChart->setColorScale(getColorScale(colorScaleType)); } Q_INVOKABLE void setSplatColorScale(ColorScaleType colorScaleType) { - switch (colorScaleType) { - case ColorScaleCategorical: - splat->setColorScale(*COLOR_SCALE_CATEGORICAL); - break; - case ColorScaleContinuous: - splat->setColorScale(*COLOR_SCALE_CONTINUOUS); - break; - case ColorScaleDivergent: - splat->setColorScale(*COLOR_SCALE_DIVERGENT); - break; - case ColorScaleRainbow: - splat->setColorScale(*COLOR_SCALE_RAINBOW); - break; - } + splat->setColorScale(getColorScale(colorScaleType)); } BarChart *barChart; @@ -159,6 +105,8 @@ public: Scatterplot *cpPlot, *rpPlot; VoronoiSplat *splat; + ProjectionObserver *projectionObserver; + public slots: void setCPIndices(const arma::uvec &indices) { m_cpIndices = indices; } void setCP(const arma::mat &cp) { @@ -173,34 +121,35 @@ public slots: private: Main(QObject *parent = 0) : QObject(parent) + , COLOR_SCALE_CATEGORICAL{ + QColor("#1f77b4"), QColor("#ff7f0e"), QColor("#2ca02c"), + QColor("#d62728"), QColor("#9467bd"), QColor("#8c564b"), + QColor("#e377c2"), QColor("#17becf"), QColor("#7f7f7f"), + } + , COLOR_SCALE_CONTINUOUS{ContinuousColorScale::builtin(ContinuousColorScale::HEATED_OBJECTS)} + , COLOR_SCALE_DIVERGENT{ContinuousColorScale::builtin(ContinuousColorScale::RED_GRAY_BLUE)} + , COLOR_SCALE_RAINBOW{ContinuousColorScale::builtin(ContinuousColorScale::RAINBOW)} , barChart(0) , cpPlot(0) , rpPlot(0) , splat(0) { - COLOR_SCALE_CATEGORICAL = new ColorScale{ - QColor("#1f77b4"), - QColor("#ff7f0e"), - QColor("#2ca02c"), - QColor("#d62728"), - QColor("#9467bd"), - QColor("#8c564b"), - QColor("#e377c2"), - QColor("#17becf"), - QColor("#7f7f7f"), - }; - COLOR_SCALE_CONTINUOUS = - new ColorScale{ContinuousColorScale::builtin(ContinuousColorScale::HEATED_OBJECTS)}; - COLOR_SCALE_DIVERGENT = - new ColorScale{ContinuousColorScale::builtin(ContinuousColorScale::RED_GRAY_BLUE)}; - COLOR_SCALE_RAINBOW = - new ColorScale{ContinuousColorScale::builtin(ContinuousColorScale::RAINBOW)}; } - ~Main() { - delete COLOR_SCALE_CATEGORICAL; - delete COLOR_SCALE_CONTINUOUS; - delete COLOR_SCALE_DIVERGENT; - delete COLOR_SCALE_RAINBOW; + ~Main() {} + + ColorScale &getColorScale(ColorScaleType colorScaleType) { + switch (colorScaleType) { + case ColorScaleCategorical: + return COLOR_SCALE_CATEGORICAL; + case ColorScaleContinuous: + return COLOR_SCALE_CONTINUOUS; + case ColorScaleDivergent: + return COLOR_SCALE_DIVERGENT; + case ColorScaleRainbow: + // fall-through + default: + return COLOR_SCALE_RAINBOW; + } } arma::mat m_dataset, m_cp; diff --git a/main_view.qml b/main_view.qml index e2f27d9..561c07d 100644 --- a/main_view.qml +++ b/main_view.qml @@ -311,7 +311,6 @@ ApplicationWindow { id: splatColormapCombo model: colormapModel onActivated: { - Main.setColormapColorScale(model.get(index).value); Main.setSplatColorScale(model.get(index).value); } } @@ -382,17 +381,33 @@ ApplicationWindow { ExclusiveGroup { id: wrtMetricsGroup } RadioButton { + id: currentMetricRadioButton text: "Current" exclusiveGroup: wrtMetricsGroup checked: true + onClicked: Main.setObserverType(Main.ObserverCurrent) } RadioButton { + id: diffPreviousMetricRadioButton text: "Diff. to previous" exclusiveGroup: wrtMetricsGroup + onClicked: { + if (!Main.setObserverType(Main.ObserverDiffPrevious)) { + this.checked = false; + currentMetricRadioButton.checked = true; + } + } } RadioButton { + id: diffOriginalMetricRadioButton text: "Diff. to original" exclusiveGroup: wrtMetricsGroup + onClicked: { + if (!Main.setObserverType(Main.ObserverDiffOriginal)) { + this.checked = false; + currentMetricRadioButton.checked = true; + } + } } } } diff --git a/projectionobserver.cpp b/projectionobserver.cpp index 781aba9..e500755 100644 --- a/projectionobserver.cpp +++ b/projectionobserver.cpp @@ -2,8 +2,12 @@ #include +#include + #include "mp.h" +static const float EPSILON = 1e-6f; + static void aggregatedError(const arma::mat &distX, const arma::mat &distY, arma::vec &v) { double maxX = distX.max(); @@ -17,37 +21,82 @@ static void aggregatedError(const arma::mat &distX, const arma::mat &distY, arma continue; } - v[i] += fabs(distY(i, j) / maxY - distX(i, j) / maxX); + float diff = fabs(distY(i, j) / maxY - distX(i, j) / maxX); + if (diff < EPSILON) { + continue; + } + + v[i] += diff; } } } ProjectionObserver::ProjectionObserver(const arma::mat &X, const arma::uvec &cpIndices) - : m_X(X) + : m_type(OBSERVER_CURRENT) + , m_X(X) , m_cpIndices(cpIndices) { m_distX = mp::dist(m_X); m_values.set_size(m_X.n_rows); } +bool ProjectionObserver::setType(int type) +{ + if (m_type == type) { + return true; + } + + if (type != OBSERVER_DIFF_PREVIOUS || m_prevValues.n_elem != 0) { + m_type = type; + return emitValuesChanged(); + } + + return false; +} + void ProjectionObserver::setMap(const arma::mat &Y) { // update previous map if (m_prevY.n_elem == 0 && m_Y.n_elem > 0) { m_prevY = m_Y; - m_distPrevY = m_distY; + m_prevDistY = m_distY; + m_prevValues = m_values; } m_Y = Y; m_distY = mp::dist(Y); + aggregatedError(m_distX, m_distY, m_values); // method called for the first time; set original Y if (m_origY.n_elem == 0) { m_origY = m_Y; - m_distOrigY = m_distY; + m_origDistY = m_distY; + m_origValues = m_values; } - aggregatedError(m_distX, m_distY, m_values); - emit mapChanged(m_values); + emitValuesChanged(); +} + +bool ProjectionObserver::emitValuesChanged() const +{ + switch (m_type) { + case OBSERVER_CURRENT: + emit valuesChanged(m_values); + return true; + case OBSERVER_DIFF_PREVIOUS: + if (m_prevValues.n_elem > 0) { + emit valuesChanged(m_values - m_prevValues); + return true; + } + return false; + case OBSERVER_DIFF_ORIGINAL: + if (m_origValues.n_elem > 0) { + emit valuesChanged(m_values - m_origValues); + return true; + } + return false; + default: + return false; + } } diff --git a/projectionobserver.h b/projectionobserver.h index 5ac6988..1c305bd 100644 --- a/projectionobserver.h +++ b/projectionobserver.h @@ -10,21 +10,29 @@ class ProjectionObserver : public QObject { Q_OBJECT public: + static const int OBSERVER_CURRENT = 0; + static const int OBSERVER_DIFF_PREVIOUS = 1; + static const int OBSERVER_DIFF_ORIGINAL = 2; + ProjectionObserver(const arma::mat &X, const arma::uvec &cpIndices); signals: - void mapChanged(const arma::vec &values) const; + void valuesChanged(const arma::vec &values) const; public slots: void setMap(const arma::mat &Y); + bool setType(int type); private: + bool emitValuesChanged() const; + + int m_type; arma::mat m_X, m_Y, m_origY, m_prevY; - arma::mat m_distX, m_distY, m_distOrigY, m_distPrevY; + arma::mat m_distX, m_distY, m_origDistY, m_prevDistY; arma::uvec m_cpIndices; // TODO: one per implemented measure - arma::vec m_values; + arma::vec m_values, m_prevValues, m_origValues; }; #endif // PROJECTIONOBSERVER_H -- cgit v1.2.3