Skip to content

Commit e7cffe7

Browse files
authored
Recolor with HSNE embedding (#185)
* WIP: use global indices if number of points does not match * Allow recoloring of hsne embeddings * Set point size and opacity same as color Remove double call to addColorDataset * Only allow resizing points for now (no size or opacity) * Restore indendation
1 parent f40c035 commit e7cffe7

File tree

7 files changed

+102
-20
lines changed

7 files changed

+102
-20
lines changed

src/ColoringAction.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ Dataset<DatasetImpl> ColoringAction::getCurrentColorDataset() const
179179

180180
void ColoringAction::setCurrentColorDataset(const Dataset<DatasetImpl>& colorDataset)
181181
{
182+
if (!colorDataset.isValid())
183+
return;
184+
182185
addColorDataset(colorDataset);
183186

184187
const auto colorDatasetRowIndex = _colorByModel.rowIndex(colorDataset);

src/PointPlotAction.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,24 @@ void PointPlotAction::addPointOpacityDataset(const Dataset<DatasetImpl>& pointOp
210210
_opacityAction.addDataset(pointOpacityDataset);
211211
}
212212

213+
void PointPlotAction::setCurrentPointSizeDataset(const Dataset<DatasetImpl>& pointSizeDataset)
214+
{
215+
if (!pointSizeDataset.isValid())
216+
return;
217+
218+
addPointSizeDataset(pointSizeDataset);
219+
_sizeAction.setCurrentDataset(pointSizeDataset);
220+
}
221+
222+
void PointPlotAction::setCurrentPointOpacityDataset(const Dataset<DatasetImpl>& pointOpacityDataset)
223+
{
224+
if (!pointOpacityDataset.isValid())
225+
return;
226+
227+
addPointOpacityDataset(pointOpacityDataset);
228+
_opacityAction.setCurrentDataset(pointOpacityDataset);
229+
}
230+
213231
void PointPlotAction::updateDefaultDatasets()
214232
{
215233
if (_scatterplotPlugin == nullptr)

src/PointPlotAction.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ class PointPlotAction : public VerticalGroupAction
5858
*/
5959
void addPointOpacityDataset(const Dataset<DatasetImpl>& pointOpacityDataset);
6060

61+
/**
62+
* Set the current point size dataset
63+
* @param pointSizeDataset Smart pointer to point size dataset
64+
*/
65+
void setCurrentPointSizeDataset(const Dataset<DatasetImpl>& pointSizeDataset);
66+
67+
/**
68+
* Set the current opacity size dataset
69+
* @param pointOpacityDataset Smart pointer to opacity size dataset
70+
*/
71+
void setCurrentPointOpacityDataset(const Dataset<DatasetImpl>& pointOpacityDataset);
72+
6173
protected:
6274

6375
/** Update default datasets (candidates are children of points type and with matching number of points) */

src/ScalarAction.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ void ScalarAction::addDataset(const Dataset<DatasetImpl>& dataset)
3838
{
3939
auto& sourceModel = _sourceAction.getModel();
4040

41+
if (sourceModel.hasDataset(dataset))
42+
return;
43+
4144
sourceModel.addDataset(dataset);
4245

4346
connect(&sourceModel.getDatasets().last(), &Dataset<DatasetImpl>::dataChanged, this, [this, dataset]() {

src/ScalarSourceModel.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ QVariant ScalarSourceModel::data(const QModelIndex& index, int role) const
7474
if (row == DefaultRow::Selection)
7575
return "Selection";
7676
}
77+
78+
break;
7779
}
7880

7981
default:
@@ -86,7 +88,7 @@ QVariant ScalarSourceModel::data(const QModelIndex& index, int role) const
8688
void ScalarSourceModel::addDataset(const Dataset<DatasetImpl>& dataset)
8789
{
8890
// Avoid duplicates
89-
if (rowIndex(dataset) >= DefaultRow::DatasetStart)
91+
if (hasDataset(dataset))
9092
return;
9193

9294
// Insert row into model
@@ -127,6 +129,11 @@ void ScalarSourceModel::addDataset(const Dataset<DatasetImpl>& dataset)
127129
});
128130
}
129131

132+
bool ScalarSourceModel::hasDataset(const Dataset<DatasetImpl>& dataset) const
133+
{
134+
return rowIndex(dataset) >= DefaultRow::DatasetStart;
135+
}
136+
130137
void ScalarSourceModel::removeDataset(const Dataset<DatasetImpl>& dataset)
131138
{
132139
// Get row index of the dataset

src/ScalarSourceModel.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ class ScalarSourceModel : public QAbstractListModel
6565
*/
6666
void addDataset(const Dataset<DatasetImpl>& dataset);
6767

68+
/**
69+
* Determines whether a given dataset is already loaded
70+
* @param dataset Smart pointer to dataset
71+
* @return whether the dataset is already loaded
72+
*/
73+
bool hasDataset(const Dataset<DatasetImpl>& dataset) const;
74+
6875
/**
6976
* Remove a dataset
7077
* @param dataset Smart pointer to dataset

src/ScatterplotPlugin.cpp

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <widgets/ViewPluginLearningCenterOverlayWidget.h>
1919

2020
#include <actions/PluginTriggerAction.h>
21+
#include <actions/ViewPluginSamplerAction.h>
2122

2223
#include <DatasetsMimeData.h>
2324

@@ -29,9 +30,8 @@
2930
#include <QtCore>
3031

3132
#include <algorithm>
32-
#include <functional>
33+
#include <cassert>
3334
#include <vector>
34-
#include <actions/ViewPluginSamplerAction.h>
3535

3636
#define VIEW_SAMPLING_HTML
3737
//#define VIEW_SAMPLING_WIDGET
@@ -172,24 +172,33 @@ ScatterplotPlugin::ScatterplotPlugin(const PluginFactory* factory) :
172172
});
173173
}
174174

175-
if (candidateDataset->getNumPoints() == _positionDataset->getNumPoints()) {
176-
177-
// The number of points is equal, so offer the option to use the points dataset as source for points colors
175+
// Accept both data with the same number if points and data which is derived from
176+
// a parent that has the same number of points (e.g. for HSNE embeddings)
177+
const auto numPointsCandidate = candidateDataset->getNumPoints();
178+
const auto numPointsPosition = _positionDataset->getNumPoints();
179+
const bool sameNumPoints = numPointsPosition == numPointsCandidate;
180+
const bool sameNumPointsAsFull =
181+
/*if*/ _positionDataset->isDerivedData() ?
182+
/*then*/ _positionDataset->getSourceDataset<Points>()->getFullDataset<Points>()->getNumPoints() == numPointsCandidate :
183+
/*else*/ false;
184+
185+
if (sameNumPoints || sameNumPointsAsFull) {
186+
// Offer the option to use the points dataset as source for points colors
178187
dropRegions << new DropWidget::DropRegion(this, "Point color", QString("Colorize %1 points with %2").arg(_positionDataset->text(), candidateDataset->text()), "palette", true, [this, candidateDataset]() {
179-
_settingsAction.getColoringAction().addColorDataset(candidateDataset);
180-
_settingsAction.getColoringAction().setCurrentColorDataset(candidateDataset);
188+
_settingsAction.getColoringAction().setCurrentColorDataset(candidateDataset); // calls addColorDataset internally
181189
});
182190

183-
// The number of points is equal, so offer the option to use the points dataset as source for points size
191+
}
192+
193+
if (sameNumPoints) {
194+
// Offer the option to use the points dataset as source for points size
184195
dropRegions << new DropWidget::DropRegion(this, "Point size", QString("Size %1 points with %2").arg(_positionDataset->text(), candidateDataset->text()), "ruler-horizontal", true, [this, candidateDataset]() {
185-
_settingsAction.getPlotAction().getPointPlotAction().addPointSizeDataset(candidateDataset);
186-
_settingsAction.getPlotAction().getPointPlotAction().getSizeAction().setCurrentDataset(candidateDataset);
196+
_settingsAction.getPlotAction().getPointPlotAction().setCurrentPointSizeDataset(candidateDataset);
187197
});
188198

189-
// The number of points is equal, so offer the option to use the points dataset as source for points opacity
199+
// Offer the option to use the points dataset as source for points opacity
190200
dropRegions << new DropWidget::DropRegion(this, "Point opacity", QString("Set %1 points opacity with %2").arg(_positionDataset->text(), candidateDataset->text()), "brush", true, [this, candidateDataset]() {
191-
_settingsAction.getPlotAction().getPointPlotAction().addPointOpacityDataset(candidateDataset);
192-
_settingsAction.getPlotAction().getPointPlotAction().getOpacityAction().setCurrentDataset(candidateDataset);
201+
_settingsAction.getPlotAction().getPointPlotAction().setCurrentPointOpacityDataset(candidateDataset);
193202
});
194203
}
195204
}
@@ -647,14 +656,37 @@ void ScatterplotPlugin::loadColors(const Dataset<Points>& points, const std::uin
647656
// Generate point scalars for color mapping
648657
std::vector<float> scalars;
649658

650-
if (_positionDataset->getNumPoints() != _numPoints)
651-
{
652-
qWarning("Number of points used for coloring does not match number of points in data, aborting attempt to color plot");
653-
return;
659+
points->extractDataForDimension(scalars, dimensionIndex);
660+
661+
const auto numColorPoints = points->getNumPoints();
662+
663+
664+
if (numColorPoints != _numPoints) {
665+
666+
const bool sameNumPointsAsFull =
667+
/*if*/ _positionDataset->isDerivedData() ?
668+
/*then*/ _positionSourceDataset->getFullDataset<Points>()->getNumPoints() == numColorPoints :
669+
/*else*/ false;
670+
671+
if (sameNumPointsAsFull) {
672+
std::vector<std::uint32_t> globalIndices;
673+
_positionDataset->getGlobalIndices(globalIndices);
674+
675+
std::vector<float> localScalars(_numPoints, 0);
676+
std::int32_t localColorIndex = 0;
677+
678+
for (const auto& globalIndex : globalIndices)
679+
localScalars[localColorIndex++] = scalars[globalIndex];
680+
681+
std::swap(localScalars, scalars);
682+
}
683+
else {
684+
qWarning("Number of points used for coloring does not match number of points in data, aborting attempt to color plot");
685+
return;
686+
}
654687
}
655688

656-
// Populate point scalars
657-
points->extractDataForDimension(scalars, dimensionIndex);
689+
assert(scalars.size() == _numPoints);
658690

659691
// Assign scalars and scalar effect
660692
_scatterPlotWidget->setScalars(scalars);

0 commit comments

Comments
 (0)