From 8cc4c24249600392871cc802f3ac4dd27368d335 Mon Sep 17 00:00:00 2001 From: Samuel Fadel Date: Mon, 18 Jan 2016 15:46:05 +0100 Subject: Added observer to update values displayed based on some metric. * Modified main() function to connect signals/slots to display calculated values * Color scales are no longer shared; they are also normalized to each component's own data * Stub mouse handling in BarChart (changes cursor shape) --- barchart.cpp | 21 +++++++++++++++----- barchart.h | 7 ++++--- distortionobserver.cpp | 33 -------------------------------- distortionobserver.h | 29 ---------------------------- main.cpp | 40 ++++++++++++++++++++------------------ pm.pro | 12 ++---------- projectionobserver.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ projectionobserver.h | 30 +++++++++++++++++++++++++++++ scatterplot.cpp | 18 ++++++++++------- scatterplot.h | 4 ++-- 10 files changed, 138 insertions(+), 108 deletions(-) delete mode 100644 distortionobserver.cpp delete mode 100644 distortionobserver.h create mode 100644 projectionobserver.cpp create mode 100644 projectionobserver.h diff --git a/barchart.cpp b/barchart.cpp index 941d9e8..f21f874 100644 --- a/barchart.cpp +++ b/barchart.cpp @@ -2,6 +2,7 @@ #include +#include "continuouscolorscale.h" #include "geometry.h" static const QColor OUTLINE_COLOR(0, 0, 0); @@ -11,12 +12,12 @@ static const float DEFAULT_OPACITY = 0.8f; BarChart::BarChart(QQuickItem *parent) : QQuickItem(parent) , m_shouldUpdateBars(false) - , m_colorScale(0) + , m_colorScale(ContinuousColorScale::builtin(ContinuousColorScale::HEATED_OBJECTS)) , m_scale(0, 1, 0, 1) { setClip(true); setFlag(QQuickItem::ItemHasContents); - // setAcceptedMouseButtons(Qt::LeftButton); + //setAcceptedMouseButtons(Qt::LeftButton); // setAcceptHoverEvents(true); } @@ -31,6 +32,7 @@ void BarChart::setValues(const arma::vec &values) m_originalIndices.resize(m_values.n_elem); if (m_values.n_elem > 0) { m_scale.setDomain(m_values.min(), m_values.max()); + m_colorScale.setExtents(m_values.min(), m_values.max()); for (int i = 0; i < m_originalIndices.size(); i++) { m_originalIndices[i] = i; @@ -44,9 +46,12 @@ void BarChart::setValues(const arma::vec &values) m_shouldUpdateBars = true; } -void BarChart::setColorScale(const ColorScale *scale) +void BarChart::setColorScale(const ColorScale &scale) { m_colorScale = scale; + if (m_values.n_elem > 0) { + m_colorScale.setExtents(m_values.min(), m_values.max()); + } emit colorScaleChanged(m_colorScale); m_shouldUpdateBars = true; @@ -136,7 +141,7 @@ void BarChart::updateBars(QSGNode *root) float x = 0; for (auto it = m_originalIndices.cbegin(); it != m_originalIndices.cend(); it++) { updateBarNodeGeom(node, x, barWidth, m_scale(m_values[*it])); - updateBarNodeColor(node, m_colorScale->color(m_values[*it])); + updateBarNodeColor(node, m_colorScale.color(m_values[*it])); x += barWidth; node = node->nextSibling(); } @@ -175,5 +180,11 @@ void BarChart::hoverMoveEvent(QHoverEvent *event) void BarChart::mousePressEvent(QMouseEvent *event) { - // TODO + QCursor dragCursor(Qt::SizeHorCursor); + setCursor(dragCursor); +} + +void BarChart::mouseReleaseEvent(QMouseEvent *event) +{ + unsetCursor(); } diff --git a/barchart.h b/barchart.h index e0edc0a..176f3b2 100644 --- a/barchart.h +++ b/barchart.h @@ -20,16 +20,17 @@ public: signals: void valuesChanged(const arma::vec &values) const; - void colorScaleChanged(const ColorScale *scale) const; + void colorScaleChanged(const ColorScale &scale) const; public slots: void setValues(const arma::vec &values); - void setColorScale(const ColorScale *scale); + void setColorScale(const ColorScale &scale); protected: QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); void hoverMoveEvent(QHoverEvent *event); void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); private: QSGNode *newSceneGraph() const; @@ -42,7 +43,7 @@ private: bool m_shouldUpdateBars; arma::vec m_values; - const ColorScale *m_colorScale; + ColorScale m_colorScale; std::vector m_originalIndices; LinearScale m_scale; }; diff --git a/distortionobserver.cpp b/distortionobserver.cpp deleted file mode 100644 index 29d7e6f..0000000 --- a/distortionobserver.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "distortionobserver.h" - -#include "mp.h" - -DistortionObserver::DistortionObserver(const arma::mat &X, - const arma::uvec &sampleIndices) - : m_X(X) - , m_sampleIndices(sampleIndices) - , m_distortionMeasure(0) -{ - m_distX = mp::dist(m_X); -} - -void DistortionObserver::setMeasure(DistortionMeasure *measure) -{ - m_distortionMeasure = measure; -} - -void DistortionObserver::setMap(const arma::mat &Y) -{ - if (!m_distortionMeasure) { - return; - } - - arma::vec measures = m_distortionMeasure->measure(m_distX, mp::dist(Y)); - - if (m_Y.n_elem != 0) { - emit mapChanged(measures - m_measures); - } else { - m_Y = Y; - m_measures = measures; - } -} diff --git a/distortionobserver.h b/distortionobserver.h deleted file mode 100644 index 101c53d..0000000 --- a/distortionobserver.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef DISTORTIONOBSERVER_H -#define DISTORTIONOBSERVER_H - -#include -#include - -#include "distortionmeasure.h" - -class DistortionObserver : public QObject -{ - Q_OBJECT -public: - DistortionObserver(const arma::mat &X, const arma::uvec &sampleIndices); - void setMeasure(DistortionMeasure *measure); - -signals: - void mapChanged(const arma::vec &distortion); - -public slots: - void setMap(const arma::mat &Y); - -private: - arma::mat m_X, m_Y, m_distX; - arma::uvec m_sampleIndices; - DistortionMeasure *m_distortionMeasure; - arma::vec m_measures; -}; - -#endif // DISTORTIONOBSERVER_H diff --git a/main.cpp b/main.cpp index d2eb5f6..c58d216 100644 --- a/main.cpp +++ b/main.cpp @@ -17,7 +17,7 @@ #include "barchart.h" #include "colormap.h" #include "interactionhandler.h" -#include "selectionhandler.h" +#include "projectionobserver.h" #include "skelft.h" static QObject *mainProvider(QQmlEngine *engine, QJSEngine *scriptEngine) @@ -130,14 +130,12 @@ int main(int argc, char **argv) //}; //colorScale.setExtents(labels.min(), labels.max()); - ContinuousColorScale colorScale = ContinuousColorScale::builtin(ContinuousColorScale::RAINBOW); - colorScale.setExtents(labels.min(), labels.max()); + ContinuousColorScale colorScale = ContinuousColorScale::builtin(ContinuousColorScale::HEATED_OBJECTS); Scatterplot *cpPlot = engine.rootObjects()[0]->findChild("cpPlot"); + Scatterplot *rpPlot = engine.rootObjects()[0]->findChild("rpPlot"); cpPlot->setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton); // cpPlot->setColorData(arma::zeros(cpSize)); - cpPlot->setColorScale(&colorScale); - Scatterplot *plot = engine.rootObjects()[0]->findChild("plot"); VoronoiSplat *splat = engine.rootObjects()[0]->findChild("splat"); skelft2DInitialization(splat->width()); Colormap *colormap = engine.rootObjects()[0]->findChild("colormap"); @@ -151,17 +149,17 @@ int main(int argc, char **argv) // Update projection as the cp are modified InteractionHandler interactionHandler(X, cpIndices); m->setInteractionHandler(&interactionHandler); + m->setTechnique(InteractionHandler::TECHNIQUE_LAMP); QObject::connect(cpPlot, SIGNAL(xyChanged(const arma::mat &)), &interactionHandler, SLOT(setCP(const arma::mat &))); QObject::connect(cpPlot, SIGNAL(xyInteractivelyChanged(const arma::mat &)), &interactionHandler, SLOT(setCP(const arma::mat &))); QObject::connect(&interactionHandler, SIGNAL(cpChanged(const arma::mat &)), - plot, SLOT(setXY(const arma::mat &))); + rpPlot, SLOT(setXY(const arma::mat &))); QObject::connect(&interactionHandler, SIGNAL(cpChanged(const arma::mat &)), splat, SLOT(setSites(const arma::mat &))); - m->setTechnique(InteractionHandler::TECHNIQUE_LAMP); - // Linking between selections in cp plot and full dataset plot + // Linking between selections in cp plot and rp plot //SelectionHandler selectionHandler(cpIndices); //QObject::connect(cpPlot, SIGNAL(selectionChanged(const QSet &)), // &selectionHandler, SLOT(setSelection(const QSet &))); @@ -175,30 +173,34 @@ int main(int argc, char **argv) //QObject::connect(history, SIGNAL(currentItemChanged(const arma::mat &)), // cpPlot, SLOT(setXY(const arma::mat &))); - QObject::connect(plot, SIGNAL(scaleChanged(const LinearScale &, const LinearScale &)), + QObject::connect(rpPlot, SIGNAL(scaleChanged(const LinearScale &, const LinearScale &)), cpPlot, SLOT(setScale(const LinearScale &, const LinearScale &))); BarChart *barChart = engine.rootObjects()[0]->findChild("barChart"); - barChart->setColorScale(&colorScale); - barChart->setValues(labels); + barChart->setAcceptedMouseButtons(Qt::LeftButton); + barChart->setColorScale(colorScale); + + ProjectionObserver projectionObserver(X, cpIndices); + QObject::connect(&interactionHandler, SIGNAL(cpChanged(const arma::mat &)), + &projectionObserver, SLOT(setMap(const arma::mat &))); + QObject::connect(&projectionObserver, SIGNAL(mapChanged(const arma::vec &)), + rpPlot, SLOT(setColorData(const arma::vec &))); + QObject::connect(&projectionObserver, SIGNAL(mapChanged(const arma::vec &)), + splat, SLOT(setValues(const arma::vec &))); + QObject::connect(&projectionObserver, SIGNAL(mapChanged(const arma::vec &)), + barChart, SLOT(setValues(const arma::vec &))); //history->addHistoryItem(Ys); colormap->setColorScale(colorScale); - plot->setColorScale(&colorScale); - plot->setColorData(labels, false); + rpPlot->setColorScale(colorScale); splat->setColorScale(colorScale); - splat->setValues(labels); + cpPlot->setColorScale(colorScale); cpPlot->setAutoScale(false); cpPlot->setColorData(labels(cpIndices), false); cpPlot->setXY(Ys, false); cpPlot->update(); - arma::vec plotOpacities(X.n_rows); - plotOpacities.fill(0.0f); - plotOpacities(cpIndices).fill(0.0f); - plot->setOpacityData(plotOpacities); - auto ret = app.exec(); skelft2DDeinitialization(); diff --git a/pm.pro b/pm.pro index 53ac0a5..3f3332b 100644 --- a/pm.pro +++ b/pm.pro @@ -15,11 +15,7 @@ HEADERS += main.h \ historygraph.h \ barchart.h \ interactionhandler.h \ - selectionhandler.h \ - effectivenessobserver.h \ - distortionobserver.h \ - distortionmeasure.h \ - npdistortion.h \ + projectionobserver.h \ skelft.h \ skelftkernel.h \ mp.h @@ -33,16 +29,12 @@ SOURCES += main.cpp \ historygraph.cpp \ barchart.cpp \ interactionhandler.cpp \ - selectionhandler.cpp \ - effectivenessobserver.cpp \ - distortionobserver.cpp \ - npdistortion.cpp \ + projectionobserver.cpp \ skelft_core.cpp \ lamp.cpp \ plmp.cpp \ knn.cpp \ forceScheme.cpp \ - tsne.cpp \ measures.cpp \ dist.cpp diff --git a/projectionobserver.cpp b/projectionobserver.cpp new file mode 100644 index 0000000..33869a8 --- /dev/null +++ b/projectionobserver.cpp @@ -0,0 +1,52 @@ +#include "projectionobserver.h" + +#include + +#include "mp.h" + +static void aggregatedError(const arma::mat &distX, const arma::mat &distY, arma::vec &v) +{ + double maxX = distX.max(); + double maxY = distY.max(); + + for (arma::uword i = 0; i < v.n_elem; i++) { + v[i] = 0; + for (arma::uword j = 0; j < v.n_elem; j++) { + if (i == j) { + continue; + } + + v[i] += fabs(distY(i, j) / maxY - distX(i, j) / maxX); + } + } +} + +ProjectionObserver::ProjectionObserver(const arma::mat &X, + const arma::uvec &cpIndices) + : m_X(X) + , m_cpIndices(cpIndices) +{ + m_distX = mp::dist(m_X); + m_values.set_size(m_X.n_rows); +} + +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_Y = Y; + m_distY = mp::dist(Y); + + // method called for the first time; set original Y + if (m_origY.n_elem == 0) { + m_origY = m_Y; + m_distOrigY = m_distY; + } + + aggregatedError(m_distX, m_distY, m_values); + emit mapChanged(m_values); +} diff --git a/projectionobserver.h b/projectionobserver.h new file mode 100644 index 0000000..5ac6988 --- /dev/null +++ b/projectionobserver.h @@ -0,0 +1,30 @@ +#ifndef PROJECTIONOBSERVER_H +#define PROJECTIONOBSERVER_H + +#include +#include + +#include "distortionmeasure.h" + +class ProjectionObserver : public QObject +{ + Q_OBJECT +public: + ProjectionObserver(const arma::mat &X, const arma::uvec &cpIndices); + +signals: + void mapChanged(const arma::vec &values) const; + +public slots: + void setMap(const arma::mat &Y); + +private: + arma::mat m_X, m_Y, m_origY, m_prevY; + arma::mat m_distX, m_distY, m_distOrigY, m_distPrevY; + arma::uvec m_cpIndices; + + // TODO: one per implemented measure + arma::vec m_values; +}; + +#endif // PROJECTIONOBSERVER_H diff --git a/scatterplot.cpp b/scatterplot.cpp index 0433af4..366583b 100644 --- a/scatterplot.cpp +++ b/scatterplot.cpp @@ -1,8 +1,13 @@ #include "scatterplot.h" -#include "geometry.h" #include +#include +#include + +#include "continuouscolorscale.h" +#include "geometry.h" + static const qreal GLYPH_OPACITY = 1.0; static const qreal GLYPH_OPACITY_SELECTED = 1.0; @@ -16,6 +21,7 @@ static const float GLYPH_OUTLINE_WIDTH = 2.0f; Scatterplot::Scatterplot(QQuickItem *parent) : QQuickItem(parent) , m_glyphSize(DEFAULT_GLYPH_SIZE) + , m_colorScale(ContinuousColorScale::builtin(ContinuousColorScale::HEATED_OBJECTS)) , m_autoScale(true) , m_sx(0, 1, 0, 1) , m_sy(0, 1, 0, 1) @@ -27,14 +33,11 @@ Scatterplot::Scatterplot(QQuickItem *parent) setFlag(QQuickItem::ItemHasContents); } -void Scatterplot::setColorScale(const ColorScale *colorScale) +void Scatterplot::setColorScale(const ColorScale &colorScale) { - if (!colorScale) { - return; - } - m_colorScale = colorScale; if (m_colorData.n_elem > 0) { + m_colorScale.setExtents(m_colorData.min(), m_colorData.max()); m_shouldUpdateMaterials = true; } } @@ -96,6 +99,7 @@ void Scatterplot::setColorData(const arma::vec &colorData, bool updateView) m_colorData = colorData; emit colorDataChanged(m_colorData); + m_colorScale.setExtents(m_colorData.min(), m_colorData.max()); m_shouldUpdateMaterials = true; if (updateView) { update(); @@ -320,7 +324,7 @@ void Scatterplot::updateGlyphs(QSGNode *glyphsNode) glyphOutlineNode->markDirty(QSGNode::DirtyMaterial); material = static_cast(glyphNode->material()); - material->setColor(m_colorScale->color(m_colorData[i])); + material->setColor(m_colorScale.color(m_colorData[i])); glyphNode->markDirty(QSGNode::DirtyMaterial); } diff --git a/scatterplot.h b/scatterplot.h index 3c2d50b..d17341e 100644 --- a/scatterplot.h +++ b/scatterplot.h @@ -17,7 +17,7 @@ public: Scatterplot(QQuickItem *parent = 0); arma::mat XY() const; - void setColorScale(const ColorScale *colorScale); + void setColorScale(const ColorScale &colorScale); void setXY(const arma::mat &xy, bool updateView); void setColorData(const arma::vec &colorData, bool updateView); void setOpacityData(const arma::vec &opacityData, bool updateView); @@ -67,7 +67,7 @@ private: // Visuals float m_glyphSize; - const ColorScale *m_colorScale; + ColorScale m_colorScale; void autoScale(); bool m_autoScale; -- cgit v1.2.3