aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main_view.qml38
-rw-r--r--scatterplot.cpp76
-rw-r--r--scatterplot.h16
-rw-r--r--selectionhandler.cpp8
-rw-r--r--selectionhandler.h5
5 files changed, 78 insertions, 65 deletions
diff --git a/main_view.qml b/main_view.qml
index 19b4efc..c84aa6c 100644
--- a/main_view.qml
+++ b/main_view.qml
@@ -1,6 +1,7 @@
import QtQuick 2.0
import QtQuick.Controls 1.3
import QtQuick.Dialogs 1.2
+import QtQuick.Extras 1.4
import PM 1.0
ApplicationWindow {
@@ -14,7 +15,6 @@ ApplicationWindow {
title: "File"
MenuItem { action: openAction }
MenuItem { action: savePlotAction }
- MenuItem { action: saveDataAction }
MenuItem { action: quitAction }
}
@@ -78,10 +78,24 @@ ApplicationWindow {
}
FileDialog {
- id: fileDialog
- title: "Choose a file..."
+ id: fileOpenDialog
+ title: "Choose a data set to load..."
+ selectMultiple: false
+ selectExisting: true
+
onAccepted: {
- // datasetLoader.load(fileDialog.fileUrls)
+ console.log("Loading data set: " + this.fileUrl)
+ }
+ }
+
+ FileDialog {
+ id: fileSaveDialog
+ title: "Save subsample mapping..."
+ selectMultiple: false
+ selectExisting: false
+
+ onAccepted: {
+ subsamplePlot.saveToFile(this.fileUrl)
}
}
@@ -96,21 +110,17 @@ ApplicationWindow {
id: openAction
text: "&Open..."
shortcut: "Ctrl+O"
- onTriggered: fileDialog.open()
+ onTriggered: fileOpenDialog.open()
}
Action {
id: savePlotAction
- text: "Save &plot"
+ text: "&Save subsample"
shortcut: "Ctrl+S"
- onTriggered: console.log("Save plot")
- }
-
- Action {
- id: saveDataAction
- text: "Save &data"
- shortcut: "Ctrl+D"
- onTriggered: console.log("Save data")
+ onTriggered: {
+ console.log("Saving subsample mapping...")
+ fileSaveDialog.open()
+ }
}
ExclusiveGroup {
diff --git a/scatterplot.cpp b/scatterplot.cpp
index 69f459c..a546980 100644
--- a/scatterplot.cpp
+++ b/scatterplot.cpp
@@ -34,6 +34,20 @@ void Scatterplot::setColorScale(ColorScale *colorScale)
}
}
+arma::mat Scatterplot::XY() const
+{
+ return m_xy;
+}
+
+bool Scatterplot::saveToFile(const QUrl &url)
+{
+ if (!url.isLocalFile()) {
+ return false;
+ }
+
+ return m_xy.save(url.path().toStdString(), arma::raw_ascii);
+}
+
void Scatterplot::setXY(const arma::mat &xy)
{
if (xy.n_cols != 2) {
@@ -79,7 +93,7 @@ void Scatterplot::updateMaterials()
update();
}
-int calculateCircleVertexCount(qreal radius)
+static int calculateCircleVertexCount(qreal radius)
{
// 10 * sqrt(r) \approx 2*pi / acos(1 - 1 / (4*r))
return (int) (10.0 * sqrt(radius));
@@ -105,14 +119,14 @@ void updateCircleGeometry(QSGGeometry *geometry, float size, float cx, float cy)
}
}
-inline float Scatterplot::fromDataXToScreenX(float x)
+inline float Scatterplot::fromDataXToScreenX(float x) const
{
return PADDING + (x - m_xmin) / (m_xmax - m_xmin) * (width() - 2*PADDING);
}
-inline float Scatterplot::fromDataYToScreenY(float y)
+inline float Scatterplot::fromDataYToScreenY(float y) const
{
- return PADDING + (y - m_ymin) / (m_ymax - m_ymin) * (height() - 2*PADDING);
+ return PADDING + (1 - (y - m_ymin) / (m_ymax - m_ymin)) * (height() - 2*PADDING);
}
QSGNode *Scatterplot::createGlyphNodeTree()
@@ -287,18 +301,13 @@ void Scatterplot::mouseMoveEvent(QMouseEvent *event)
void Scatterplot::mouseReleaseEvent(QMouseEvent *event)
{
- bool mergeSelection;
- arma::uvec selection;
-
switch (m_currentInteractionState) {
case INTERACTION_SELECTING:
- mergeSelection = (event->modifiers() == Qt::ControlModifier);
- selection = findSelection(mergeSelection);
- if (selection.n_elem > 0) {
- setSelection(selection);
- m_currentInteractionState = INTERACTION_SELECTED;
- } else {
- m_currentInteractionState = INTERACTION_NONE;
+ {
+ bool mergeSelection = (event->modifiers() == Qt::ControlModifier);
+ m_currentInteractionState =
+ updateSelection(mergeSelection) ? INTERACTION_SELECTED
+ : INTERACTION_NONE;
}
break;
@@ -313,44 +322,35 @@ void Scatterplot::mouseReleaseEvent(QMouseEvent *event)
}
}
-arma::uvec Scatterplot::findSelection(bool mergeSelection)
+bool Scatterplot::updateSelection(bool mergeSelection)
{
- QSet<int> selectedGlyphs(m_selectedGlyphs);
- if (!mergeSelection) {
- selectedGlyphs.clear();
+ QSet<int> selection;
+ if (mergeSelection) {
+ selection.unite(m_selectedGlyphs);
}
- QPointF dragOrigin(m_dragOriginPos.x() / width() * (m_xmax - m_xmin) + m_xmin,
- m_dragOriginPos.y() / height() * (m_ymax - m_ymin) + m_ymin);
- QPointF dragCurrent(m_dragCurrentPos.x() / width() * (m_xmax - m_xmin) + m_xmin,
- m_dragCurrentPos.y() / height() * (m_ymax - m_ymin) + m_ymin);
- QRectF selectionRect(dragOrigin, dragCurrent);
+ qreal originX = m_dragOriginPos.x() / width() * (m_xmax - m_xmin) + m_xmin;
+ qreal originY = (1 - m_dragOriginPos.y() / height()) * (m_ymax - m_ymin) + m_ymin;
+ qreal currentX = m_dragCurrentPos.x() / width() * (m_xmax - m_xmin) + m_xmin;
+ qreal currentY = (1 - m_dragCurrentPos.y() / height()) * (m_ymax - m_ymin) + m_ymin;
+
+ QRectF selectionRect(QPointF(originX, originY), QPointF(currentX, currentY));
for (arma::uword i = 0; i < m_xy.n_rows; i++) {
arma::rowvec row = m_xy.row(i);
if (selectionRect.contains(row[0], row[1])) {
- selectedGlyphs.insert(i);
+ selection.insert(i);
}
}
- arma::uvec selection(selectedGlyphs.size());
- int i = 0;
- for (auto it = selectedGlyphs.cbegin(); it != selectedGlyphs.cend(); it++, i++) {
- selection[i] = *it;
- }
-
- return selection;
+ setSelection(selection);
+ return !selection.isEmpty();
}
-void Scatterplot::setSelection(const arma::uvec &selection)
+void Scatterplot::setSelection(const QSet<int> &selection)
{
- m_selectedGlyphs.clear();
-
- for (auto it = selection.cbegin(); it != selection.cend(); it++) {
- m_selectedGlyphs.insert(*it);
- }
-
+ m_selectedGlyphs = selection;
update();
emit selectionChanged(selection);
diff --git a/scatterplot.h b/scatterplot.h
index f4fd238..3d7fa36 100644
--- a/scatterplot.h
+++ b/scatterplot.h
@@ -13,17 +13,19 @@ class Scatterplot : public QQuickItem
public:
Scatterplot(QQuickItem *parent = 0);
+ arma::mat XY() const;
void setColorScale(ColorScale *colorScale);
+ Q_INVOKABLE bool saveToFile(const QUrl &url);
signals:
- void xyChanged(const arma::mat &XY);
- void colorDataChanged(const arma::vec &colorData);
- void selectionChanged(const arma::uvec &selection);
+ void xyChanged(const arma::mat &XY) const;
+ void colorDataChanged(const arma::vec &colorData) const;
+ void selectionChanged(const QSet<int> &selection) const;
public slots:
void setXY(const arma::mat &xy);
void setColorData(const arma::vec &colorData);
- void setSelection(const arma::uvec &selection);
+ void setSelection(const QSet<int> &selection);
protected:
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
@@ -33,10 +35,10 @@ protected:
private:
QSGNode *createGlyphNodeTree();
- arma::uvec findSelection(bool mergeSelection);
+ bool updateSelection(bool mergeSelection);
- float fromDataXToScreenX(float x);
- float fromDataYToScreenY(float y);
+ float fromDataXToScreenX(float x) const;
+ float fromDataYToScreenY(float y) const;
void applyManipulation();
diff --git a/selectionhandler.cpp b/selectionhandler.cpp
index 4c488a0..44eef28 100644
--- a/selectionhandler.cpp
+++ b/selectionhandler.cpp
@@ -5,14 +5,14 @@ SelectionHandler::SelectionHandler(const arma::uvec &sampleIndices)
{
}
-void SelectionHandler::setSelection(const arma::uvec &selection)
+void SelectionHandler::setSelection(const QSet<int> &selection)
{
- arma::uvec newSelection(selection);
+ QSet<int> newSelection;
// The selecion happens over the sample indices. We use the original dataset
// indices in sampleIndices to translate indices.
- for (auto it = newSelection.begin(); it != newSelection.end(); it++) {
- *it = m_sampleIndices[*it];
+ for (auto it = selection.begin(); it != selection.end(); it++) {
+ newSelection.insert(m_sampleIndices[*it]);
}
emit selectionChanged(newSelection);
diff --git a/selectionhandler.h b/selectionhandler.h
index 4c4a2ca..e5b9686 100644
--- a/selectionhandler.h
+++ b/selectionhandler.h
@@ -2,6 +2,7 @@
#define SELECTIONHANDLER_H
#include <QObject>
+#include <QSet>
#include <armadillo>
class SelectionHandler : public QObject
@@ -11,10 +12,10 @@ public:
SelectionHandler(const arma::uvec &sampleIndices);
signals:
- void selectionChanged(const arma::uvec &selection);
+ void selectionChanged(const QSet<int> &selection);
public slots:
- void setSelection(const arma::uvec &selection);
+ void setSelection(const QSet<int> &selection);
private:
arma::uvec m_sampleIndices;