From ff10df2f8bfc71afe8637eec67d11d6ce87b673b Mon Sep 17 00:00:00 2001 From: Samuel Fadel Date: Thu, 28 Jan 2016 15:52:39 +0100 Subject: ProjectionObsever now responds to selection changes. * Scatterplot: small fix to selection updates * ProjectionObserver: whenever CP selection changes, compute influence of CPs over all RPs. Whenever RP selection changes, compute influence of RPs by all CPs. * ProjectionObserver: with empty selections, go back to normal mode --- projectionobserver.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 92 insertions(+), 14 deletions(-) (limited to 'projectionobserver.cpp') diff --git a/projectionobserver.cpp b/projectionobserver.cpp index 395110c..1293128 100644 --- a/projectionobserver.cpp +++ b/projectionobserver.cpp @@ -38,27 +38,37 @@ ProjectionObserver::ProjectionObserver(const arma::mat &X, , m_X(X) , m_cpIndices(cpIndices) , m_rpIndices(X.n_rows - cpIndices.n_elem) + , m_cpSelectionEmpty(true) + , m_rpSelectionEmpty(true) { m_distX = mp::dist(m_X); m_values.set_size(m_X.n_rows); - NumericRange range(0, m_X.n_rows); + NumericRange range(0, m_X.n_rows); std::set_symmetric_difference(range.cbegin(), range.cend(), m_cpIndices.cbegin(), m_cpIndices.cend(), m_rpIndices.begin()); + + computeAlphas(); } -bool ProjectionObserver::setType(int type) +void ProjectionObserver::computeAlphas() { - if (m_type == type) { - return true; - } + m_influences.set_size(m_X.n_rows); + m_alphas.set_size(m_rpIndices.n_elem, m_cpIndices.n_elem); + + for (arma::uword i = 0; i < m_rpIndices.n_elem; i++) { + double sum = 0; + const arma::rowvec &x = m_X.row(m_rpIndices[i]); + for (arma::uword j = 0; j < m_cpIndices.n_elem; j++) { + double norm = arma::norm(x - m_X.row(m_cpIndices[j])); + m_alphas(i, j) = 1.0f / std::max(norm * norm, 1e-6); + sum += m_alphas(i, j); + } - if (type != OBSERVER_DIFF_PREVIOUS || m_prevValues.n_elem != 0) { - m_type = type; - return emitValuesChanged(); + for (arma::uword j = 0; j < m_cpIndices.n_elem; j++) { + m_alphas(i, j) /= sum; + } } - - return false; } void ProjectionObserver::setMap(const arma::mat &Y) @@ -81,21 +91,90 @@ void ProjectionObserver::setMap(const arma::mat &Y) m_origValues = m_values; } - emitValuesChanged(); + if (m_cpSelectionEmpty && m_rpSelectionEmpty) { + emitValuesChanged(); + } +} + +bool ProjectionObserver::setType(int type) +{ + if (m_type == type) { + return true; + } + + if (type != OBSERVER_DIFF_PREVIOUS || m_prevValues.n_elem != 0) { + m_type = type; + if (m_cpSelectionEmpty && m_rpSelectionEmpty) { + return emitValuesChanged(); + } + + return true; + } + + return false; +} + +void ProjectionObserver::setCPSelection(const std::vector &cpSelection) +{ + m_cpSelection.clear(); + for (int i = 0; i < cpSelection.size(); i++) { + if (cpSelection[i]) { + m_cpSelection.push_back(i); + } + } + m_cpSelectionEmpty = m_cpSelection.empty(); + + if (!m_cpSelectionEmpty) { + // compute the influence of CP selection on each RP + for (arma::uword rp = 0; rp < m_rpIndices.n_elem; rp++) { + m_influences[m_rpIndices[rp]] = 0; + const arma::rowvec &row = m_alphas.row(rp); + for (auto cp: m_cpSelection) { + m_influences[m_rpIndices[rp]] += row[cp]; + } + } + + emit rpValuesChanged(m_influences(m_rpIndices)); + } else { + emitValuesChanged(); + } +} + +void ProjectionObserver::setRPSelection(const std::vector &rpSelection) +{ + m_rpSelection.clear(); + for (int i = 0; i < rpSelection.size(); i++) { + if (rpSelection[i]) { + m_rpSelection.push_back(i); + } + } + m_rpSelectionEmpty = m_rpSelection.empty(); + + if (!m_rpSelectionEmpty) { + // compute how influent is each CP on RP selection + for (arma::uword cp = 0; cp < m_cpIndices.n_elem; cp++) { + m_influences[m_cpIndices[cp]] = 0; + for (auto rp: m_rpSelection) { + m_influences[m_cpIndices[cp]] += m_alphas(rp, cp); + } + } + + emit cpValuesChanged(m_influences(m_cpIndices)); + } else { + emit cpValuesChanged(arma::vec()); + } } bool ProjectionObserver::emitValuesChanged() const { switch (m_type) { case OBSERVER_CURRENT: - emit cpValuesChanged(m_values(m_cpIndices)); emit rpValuesChanged(m_values(m_rpIndices)); emit valuesChanged(m_values); return true; case OBSERVER_DIFF_PREVIOUS: if (m_prevValues.n_elem > 0) { arma::vec diff = m_values - m_prevValues; - emit cpValuesChanged(diff(m_cpIndices)); emit rpValuesChanged(diff(m_rpIndices)); emit valuesChanged(diff); return true; @@ -104,7 +183,6 @@ bool ProjectionObserver::emitValuesChanged() const case OBSERVER_DIFF_ORIGINAL: if (m_origValues.n_elem > 0) { arma::vec diff = m_values - m_origValues; - emit cpValuesChanged(diff(m_cpIndices)); emit rpValuesChanged(diff(m_rpIndices)); emit valuesChanged(diff); return true; -- cgit v1.2.3