#ifndef MAIN_H #define MAIN_H #include #include #include #include "colorscale.h" #include "continuouscolorscale.h" #include "divergentcolorscale.h" #include "projectionhistory.h" #include "numericrange.h" #include "barchart.h" #include "colormap.h" #include "scatterplot.h" #include "voronoisplat.h" class Main : public QObject { Q_OBJECT Q_ENUMS(ObserverType) Q_ENUMS(ColorScaleType) public: static Main *instance() { // FIXME: Possibly dangerous static Main *m = 0; if (m == 0) { m = new Main(); } return m; } Q_INVOKABLE bool saveData() const { bool ret = true; if (m_cp.n_elem > 0 && m_indicesSavePath.size() > 0) { ret = ret && m_cp.save(m_cpSavePath, arma::raw_ascii); } if (m_cpIndices.n_elem > 0 && m_cpSavePath.size() > 0) { ret = ret && m_cpIndices.save(m_indicesSavePath, arma::raw_ascii); } return ret; } Q_INVOKABLE bool loadDataset(const std::string &path) { return m_dataset.load(path, arma::raw_ascii); } Q_INVOKABLE void setIndicesSavePath(const std::string &path) { m_indicesSavePath = path; } Q_INVOKABLE void setIndicesSavePath(const QString &path) { setIndicesSavePath(path.toStdString()); } Q_INVOKABLE void setCPSavePath(const std::string &path) { m_cpSavePath = path; } Q_INVOKABLE void setCPSavePath(const QString &path) { setCPSavePath(path.toStdString()); } 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); } Q_INVOKABLE void setSelectRPs() { cpPlot->setAcceptedMouseButtons(Qt::NoButton); cpPlot->setAcceptHoverEvents(false); rpPlot->setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton); rpPlot->setAcceptHoverEvents(true); } Q_INVOKABLE void setSelectCPs() { rpPlot->setAcceptedMouseButtons(Qt::NoButton); rpPlot->setAcceptHoverEvents(false); cpPlot->setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton); cpPlot->setAcceptHoverEvents(true); } enum ColorScaleType { ColorScaleCategorical, ColorScaleContinuous, ColorScaleDivergent, ColorScaleRainbow }; Q_INVOKABLE void setCPColorScale(ColorScaleType colorScaleType) { ColorScale *ptr = colorScaleCPs.get(); float min = ptr != nullptr ? ptr->min() : 0.0f; float max = ptr != nullptr ? ptr->max() : 1.0f; ptr = getColorScale(colorScaleType); ptr->setExtents(min, max); colorScaleCPs.reset(ptr); cpPlot->setColorScale(colorScaleCPs.get()); cpBarChart->setColorScale(colorScaleCPs.get()); cpColormap->setColorScale(colorScaleCPs.get()); } Q_INVOKABLE void setRPColorScale(ColorScaleType colorScaleType) { ColorScale *ptr = colorScaleCPs.get(); float min = 0.0f; float max = 1.0f; if (ptr) { min = ptr->min(); max = ptr->max(); } ptr = getColorScale(colorScaleType); ptr->setExtents(min, max); colorScaleRPs.reset(ptr); rpPlot->setColorScale(colorScaleRPs.get()); splat->setColorScale(colorScaleRPs.get()); rpBarChart->setColorScale(colorScaleRPs.get()); rpColormap->setColorScale(colorScaleRPs.get()); } // Pointers to visual components whose values are set in the main() function // after components are instantiated by the QtQuick engine BarChart *cpBarChart, *rpBarChart; Colormap *cpColormap, *rpColormap; Scatterplot *cpPlot, *rpPlot; VoronoiSplat *splat; // Color scales in use std::unique_ptr colorScaleCPs, colorScaleRPs; // Object that controls manipulation history ProjectionHistory *projectionHistory; 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: void setCPIndices(const arma::uvec &indices) { m_cpIndices = indices; m_rpIndices.set_size(m_dataset.n_rows - m_cpIndices.n_elem); NumericRange allIndices(0, m_dataset.n_rows); std::set_symmetric_difference(allIndices.cbegin(), allIndices.cend(), m_cpIndices.cbegin(), m_cpIndices.cend(), m_rpIndices.begin()); } void setCP(const arma::mat &cp) { if (cp.n_cols != 2 || cp.n_rows != m_cpIndices.n_elem) { return; } m_cp = cp; } void updateMap(const arma::mat &Y) { cpPlot->setXY(Y.rows(m_cpIndices)); const arma::mat ®ularPoints = Y.rows(m_rpIndices); rpPlot->setXY(regularPoints); splat->setSites(regularPoints); } private: Main(QObject *parent = 0) : QObject(parent) , cpBarChart(0) , rpBarChart(0) , cpColormap(0) , rpColormap(0) , cpPlot(0) , rpPlot(0) , splat(0) , projectionHistory(0) { } ~Main() {} ColorScale *getColorScale(ColorScaleType colorScaleType) { switch (colorScaleType) { case ColorScaleCategorical: return new ColorScale{ QColor("#1f77b4"), QColor("#ff7f0e"), QColor("#2ca02c"), QColor("#d62728"), QColor("#9467bd"), QColor("#8c564b"), QColor("#e377c2"), QColor("#17becf"), QColor("#7f7f7f"), }; case ColorScaleContinuous: return ContinuousColorScale::builtin( ContinuousColorScale::HeatedObjects, nullptr); case ColorScaleDivergent: return DivergentColorScale::builtin( DivergentColorScale::RedGrayBlue, nullptr); case ColorScaleRainbow: // fall-through default: return ContinuousColorScale::builtin( ContinuousColorScale::Rainbow, nullptr); } } arma::mat m_dataset, m_cp; arma::uvec m_cpIndices, m_rpIndices; std::string m_indicesSavePath, m_cpSavePath; }; #endif // MAIN_H