diff --git a/pv_app/src/application.cpp b/pv_app/src/application.cpp index 729af9c34b8005c82b3f7ce8fd6c775f441c4b86..44bdd0b0a71db6cffd595533871a199fa6368b3e 100644 --- a/pv_app/src/application.cpp +++ b/pv_app/src/application.cpp @@ -147,6 +147,8 @@ application::setup_ui mp_perf_data_viewer_widget_bottom->hide(); mp_main_splitter->setGeometry(0, 0, 1440, 873); + //mp_main_splitter->setGeometry(0, 0, 1075, 536); + mp_main_splitter->show(); } diff --git a/pvt/_SourceFiles.cmake b/pvt/_SourceFiles.cmake index 106d410c509a2e89672277218d4bfa6058224267..6db76a45692ed1b2ff70a5b861a7d6c7dce0912a 100644 --- a/pvt/_SourceFiles.cmake +++ b/pvt/_SourceFiles.cmake @@ -34,7 +34,7 @@ set(SourceFiles include/pvt/data_array.hpp include/pvt/dft.hpp include/pvt/dft_inverse.hpp - include/pvt/directed_variation.hpp + include/pvt/directed_variance.hpp include/pvt/export_flags.hpp include/pvt/fft.hpp include/pvt/fft_helper.hpp @@ -87,7 +87,7 @@ set(SourceFiles src/correlation_computer.cpp src/dft.cpp src/dft_inverse.cpp - src/directed_variation.cpp + src/directed_variance.cpp src/fft.cpp src/fft_statistics.cpp src/nop.cpp diff --git a/pvt/include/pvt/cartesian_topology_index.hpp b/pvt/include/pvt/cartesian_topology_index.hpp index d651592d5f069b5a7657e4d14943f26765757835..99527c1e90af7c340702ffb92804497580e13279 100644 --- a/pvt/include/pvt/cartesian_topology_index.hpp +++ b/pvt/include/pvt/cartesian_topology_index.hpp @@ -79,18 +79,23 @@ public: coordinate .begin(), 0); } - std::vector<std::size_t> get_coordinate(std::size_t index) const + template <typename T> + void get_coordinate(std::size_t index, std::vector<T>& coordinate) const { - std::vector<std::size_t> coordinate(m_num_dimensions, 0); std::transform( m_dimension_sizes .begin(), m_dimension_sizes .end (), m_dimension_offsets.begin(), - coordinate.begin(), + coordinate .begin(), [index] (std::size_t size, std::size_t offset) { return (index / offset) % size; }); + } + std::vector<std::size_t> get_coordinate(std::size_t index) const + { + std::vector<std::size_t> coordinate(m_num_dimensions, 0); + get_coordinate(index, coordinate); return coordinate; } diff --git a/pvt/include/pvt/directed_variance.hpp b/pvt/include/pvt/directed_variance.hpp new file mode 100644 index 0000000000000000000000000000000000000000..02449e52b928fc349a801652ce48d79ba66af68a --- /dev/null +++ b/pvt/include/pvt/directed_variance.hpp @@ -0,0 +1,47 @@ +//============================================================================== +// pvt performance visualization toolkit +// +// Copyright (c) 2014-2016 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//============================================================================== +// License +// +// This library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// In the future, we may decide to add a commercial license +// at our own discretion without further notice. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//============================================================================== + +#ifndef PVT_DIRECTED_VARIANCE_HPP_ +#define PVT_DIRECTED_VARIANCE_HPP_ + +#include <pvt/api.hpp> +#include <pvt/data_array.hpp> + +namespace pvt +{ +class fft; + +//------------------------------------------------------------------------------ +class PVT_API directed_variance : public data_array<double> +{ +public: + directed_variance(std::size_t dimension_count); + + void compute(const fft& fft); +}; + +} + +#endif // #ifndef PVT_DIRECTED_VARIANCE_HPP_ diff --git a/pvt/include/pvt/directed_variation.hpp b/pvt/include/pvt/directed_variation.hpp deleted file mode 100644 index b774fcbaf7cdbd5cc4dfaefae247c2339d754823..0000000000000000000000000000000000000000 --- a/pvt/include/pvt/directed_variation.hpp +++ /dev/null @@ -1,126 +0,0 @@ -//------------------------------------------------------------------------------ -// pvt performance visualization toolkit -// -// Copyright (c) 2014-2016 RWTH Aachen University, Germany, -// Virtual Reality & Immersive Visualisation Group. -//------------------------------------------------------------------------------ -// License -// -// This library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// In the future, we may decide to add a commercial license -// at our own discretion without further notice. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -//------------------------------------------------------------------------------ - -#ifndef PVT_DIRECTED_VARIATION_HPP_ -#define PVT_DIRECTED_VARIATION_HPP_ - -#include <algorithm> -#include <cmath> -#include <vector> - -#include <pvt/api.hpp> - -namespace pvt { - -class severity_view; - -//------------------------------------------------------------------------------ -class PVT_API directed_variation -{ -public: - directed_variation(std::size_t num_dimensions) - : m_directed_variation(num_dimensions, 0.0) - , m_mean (0.0) - , m_variance (0.0) - { - - } - - double get_mean () const - { - return m_mean; - } - double get_variance () const - { - return m_variance; - } - double get_std_deviation() const - { - return sqrt(m_variance); - } - - double& at(std::size_t index) - { - return m_directed_variation.at(index); - } - const double& at(std::size_t index) const - { - return m_directed_variation.at(index); - } - - double& operator[](std::size_t index) - { - return m_directed_variation[index]; - } - const double& operator[](std::size_t index) const - { - return m_directed_variation[index]; - } - - std::vector<double>::iterator begin() - { - return m_directed_variation.begin(); - } - std::vector<double>::const_iterator begin() const - { - return m_directed_variation.begin(); - } - - std::vector<double>::iterator end() - { - return m_directed_variation.end(); - } - std::vector<double>::const_iterator end() const - { - return m_directed_variation.end(); - } - - std::size_t size() const - { - return m_directed_variation.size(); - } - - void set_to_zero() - { - std::for_each(m_directed_variation.begin(), - m_directed_variation.end(), - [](double& v) { v = 0.0; }); - m_mean = 0.0; - m_variance = 0.0; - } - - void compute(const severity_view& severity_view); - void dump (const std::string& filename) const; - bool read (const std::string& filename, - const severity_view& severity_view); -private: - std::vector<double> m_directed_variation; - double m_mean; - double m_variance; -}; - -} // namespace pvt - -#endif // #ifndef PVT_DIRECTED_VARIATION_HPP_ diff --git a/pvt/include/pvt/export_flags.hpp b/pvt/include/pvt/export_flags.hpp index 8352bcdf0206732d6bc759884a1d60e592df1e8b..7f1c1aa745533d3ad2531c012d2f2c2978e3b81b 100644 --- a/pvt/include/pvt/export_flags.hpp +++ b/pvt/include/pvt/export_flags.hpp @@ -31,14 +31,17 @@ namespace pvt { //------------------------------------------------------------------------------ enum export_flags { - export_nothing = 0x00, - export_metadata = 0x01, - export_severities = 0x01 << 1, - export_fft = 0x01 << 2, - export_data = export_severities | export_fft, - export_metadata_only = export_metadata, - export_all = 0xff, - recompute_spectra = 0x0100 << 2 + export_nothing = 0x00, + export_metadata = 0x01, + export_severities = 0x01 << 1, + export_fft = 0x01 << 2, + export_directed_variances = 0x01 << 3, + export_data = export_severities | export_fft | export_directed_variances, + export_metadata_only = export_metadata, + export_directed_variances_only = export_directed_variances, + export_all = 0xff, + recompute_spectra = 0x0100 << 2, + recompute_directed_variances = 0x0100 << 3 }; } // namespace pvt diff --git a/pvt/include/pvt/fft.hpp b/pvt/include/pvt/fft.hpp index 3218087cb990b33b934ef8e4e9cf39e4d3665fc0..062b69856e69ae10a8d099dafe17520f20af06b4 100644 --- a/pvt/include/pvt/fft.hpp +++ b/pvt/include/pvt/fft.hpp @@ -38,8 +38,6 @@ namespace pvt { -class directed_variation; - //------------------------------------------------------------------------------ class PVT_API fft { @@ -53,6 +51,8 @@ public: , m_normalizer (1.0 / static_cast<double>(cart_topo_idx.get_num_positions())) , m_is_guaranteed_zero(false) + , m_non_redundant_last_dimension + (cart_topo_idx.get_dimension_sizes().back() % 2 == 0) { } @@ -94,7 +94,11 @@ public: { return sqrt(get_variance()); } - void get_directed_variation(directed_variation& directed_variation) const; + + double get_spectral_energy (std::size_t i) const + { + return mod_sq_at(i) * m_normalizer * m_normalizer; + } void clear_dc() { @@ -181,6 +185,73 @@ public: /// \todo Check if this is guaranteed for all possible cases bool is_guaranteed_zero() const { return m_is_guaranteed_zero; } + template <typename T> + void convert_to_frequency + (std::size_t frequency_index, + std::vector<T>& frequency ) const + { + m_cart_topo_idx.get_coordinate(frequency_index, frequency); + } + + template <typename T> + void convert_to_dc_centered_frequency + (std::size_t frequency_index, + std::vector<T>& frequency ) const + { + convert_to_frequency(frequency_index, frequency); + + const auto dc_shift_callable = + [] + (std::size_t frequency_component, + std::size_t dimension_size) + { + const auto half_dimension_size = dimension_size / 2; + const auto in_upper_half = + frequency_component > half_dimension_size; + const auto shift = + static_cast<double>(in_upper_half) * + static_cast<double>(dimension_size); + return static_cast<double>(frequency_component) - shift; + }; + + std::transform( frequency.begin(), + --frequency.end (), + m_cart_topo_idx.get_dimension_sizes().begin(), + frequency.begin(), + dc_shift_callable); + } + + template <typename T> + T get_frequency_norm_squared(const std::vector<T> frequency) const + { + const auto add_squared_callable = + [](T result, T element) + { + return result + element * element; + }; + return std::accumulate(frequency.begin(), + frequency.end (), + 0.0, + add_squared_callable); + } + + template <typename T> + T get_frequency_norm (const std::vector<T> frequency) const + { + return sqrt(get_frequency_norm_squared(frequency)); + } + + template <typename T> + bool is_on_boundary (const std::vector<T>& frequency) const + { + return + (frequency.back() == 0) || + ((frequency.back() == static_cast<T>( + m_cart_topo_idx.get_dimension_sizes().back() - 1)) + && + m_non_redundant_last_dimension); + } + private: double mod_sq_at(std::size_t i) const { @@ -193,6 +264,7 @@ private: double m_normalizer; bool m_is_guaranteed_zero; + bool m_non_redundant_last_dimension; }; } // namespace pvt diff --git a/pvt/include/pvt/fft_statistics.hpp b/pvt/include/pvt/fft_statistics.hpp index 1e91f8e08e13b095b9e3b0f7943482c0734c4fdb..de2b325243890fc9373ffaf1d423473d8f9428e1 100644 --- a/pvt/include/pvt/fft_statistics.hpp +++ b/pvt/include/pvt/fft_statistics.hpp @@ -57,7 +57,7 @@ public: } - /// \todo Better take CartesianTopology as parameter in all related c'tors? + /// \todo Better take cartesian_topology as parameter in all related c'tors? fft_statistics() : fft_statistics(num_attributes) { @@ -89,7 +89,7 @@ public: severity_view.get_performance_data()-> get_fft_statistics(severity_view, *this); } - /// \todo Implement in order to allow for getting FftStatistics via PerfDataFile interface, in a similar way as DirectedVariation. + /// \todo Implement in order to allow for getting fft_statistics via perf_data_file interface, similar to directed_variance. void compute(const fft& fft); private: diff --git a/pvt/include/pvt/io/perf_data_file.hpp b/pvt/include/pvt/io/perf_data_file.hpp index aec22f5f4f06a03db465035e6e40494284ef8f2f..87da89a87a6a2b2673c4ab4e34c9d837d8d90978 100644 --- a/pvt/include/pvt/io/perf_data_file.hpp +++ b/pvt/include/pvt/io/perf_data_file.hpp @@ -39,7 +39,7 @@ namespace pvt { template <typename T> class data_array; class cartesian_topology; class cnode; -class directed_variation; +class directed_variance; class fft; class fft_statistics; class metric; @@ -99,16 +99,16 @@ public: const std::vector<const metric*>& metric_ids, const std::vector<const cnode *>& cnode_ids ) const = 0; - virtual double get_severity (const severity_view& severity_view ) const = 0; + virtual double get_severity (const severity_view& severity_view ) const = 0; virtual void get_severities (const severity_view& severity_view, - data_array<double>& severities ) const = 0; + data_array<double>& severities ) const = 0; virtual void get_fft (const severity_view& severity_view, - fft& fft ) const = 0; + fft& fft ) const = 0; virtual void get_fft_statistics (const severity_view& severity_view, - fft_statistics& fft_statistics ) const = 0; - virtual void get_directed_variation (const severity_view& severity_view, - directed_variation& directed_variation) const = 0; - virtual double get_autocorrelation_off_dc(const severity_view& severity_view ) const = 0; + fft_statistics& fft_statistics ) const = 0; + virtual void get_directed_variance (const severity_view& severity_view, + directed_variance& directed_variance) const = 0; + virtual double get_autocorrelation_off_dc(const severity_view& severity_view ) const = 0; protected: std::string m_filename; diff --git a/pvt/include/pvt/perf_data.hpp b/pvt/include/pvt/perf_data.hpp index 16e4d2b02881c009a9e784dee61a3c074b20c956..c15a6340ca41c92f118160d8b52c0569f1c873cd 100644 --- a/pvt/include/pvt/perf_data.hpp +++ b/pvt/include/pvt/perf_data.hpp @@ -47,7 +47,7 @@ namespace pvt { class correlated_severity_view; -class directed_variation; +class directed_variance; class fft; class fft_statistics; class severity_view; @@ -131,8 +131,8 @@ public: fft& fft ) const; void get_fft_statistics (const severity_view& severity_view, fft_statistics& fft_statistics) const; - void get_directed_variation (const severity_view& severity_view, - directed_variation& directed_variation) const; + void get_directed_variance (const severity_view& severity_view, + directed_variance& directed_variance) const; double get_mean (const severity_view& severity_view) const; double get_variance (const severity_view& severity_view) const; double get_standard_deviation (const severity_view& severity_view) const; diff --git a/pvt/include/pvt/perf_data_cache_cnode.hpp b/pvt/include/pvt/perf_data_cache_cnode.hpp index 83314ceaf84614ab41b3c5784ad5b147e2856b00..daa589341eae421397b4e7b66aacb28bc3a28c6b 100644 --- a/pvt/include/pvt/perf_data_cache_cnode.hpp +++ b/pvt/include/pvt/perf_data_cache_cnode.hpp @@ -27,12 +27,13 @@ #define PVT_PERF_DATA_CACHE_CNODE_HPP_ #include <algorithm> +#include <cmath> #include <vector> #include <pvt/api.hpp> #include <pvt/cnode.hpp> #include <pvt/data_array.hpp> -#include <pvt/directed_variation.hpp> +#include <pvt/directed_variance.hpp> #include <pvt/severity_view.hpp> #include <pvt/suitable_3d_view_computer.hpp> @@ -72,10 +73,10 @@ public: return std::isfinite(relative_severity) ? relative_severity : 0.0; } - const directed_variation& get_directed_variation(const cnode* p_cnode) + const directed_variance& get_directed_variance(const cnode* p_cnode) { - check_and_update_directed_variation(p_cnode); - return m_directed_variations[p_cnode->get_id()]; + check_and_update_directed_variance(p_cnode); + return m_directed_variances[p_cnode->get_id()]; } bool is_suitable_3d_view (const cnode* p_cnode) @@ -98,9 +99,9 @@ public: { for (std::size_t i = 0; i < m_dirty_severities.size(); ++i) { - m_dirty_severities [i] = true; - m_dirty_directed_variations[i] = true; - m_dirty_suitable_3d_views [i] = true; + m_dirty_severities [i] = true; + m_dirty_directed_variance[i] = true; + m_dirty_suitable_3d_views[i] = true; } } @@ -112,12 +113,12 @@ private: } void update_severity (const cnode* p_cnode); - void check_and_update_directed_variation(const cnode* p_cnode) + void check_and_update_directed_variance (const cnode* p_cnode) { - if (m_dirty_directed_variations[p_cnode->get_id()]) - update_directed_variation(p_cnode); + if (m_dirty_directed_variance[p_cnode->get_id()]) + update_directed_variance(p_cnode); } - void update_directed_variation (const cnode* p_cnode); + void update_directed_variance (const cnode* p_cnode); void check_and_update_suitable_3d_view (const cnode* p_cnode) { @@ -126,20 +127,20 @@ private: } void update_suitable_3d_view (const cnode* p_cnode); - const severity_view* mp_severity_view; - data_array<double> m_severities_load_buffer; + const severity_view* mp_severity_view; + data_array<double> m_severities_load_buffer; - std::vector<double> m_severities_total; - std::vector<double> m_severities_self; - std::vector<bool> m_dirty_severities; + std::vector<double> m_severities_total; + std::vector<double> m_severities_self; + std::vector<bool> m_dirty_severities; - std::vector<directed_variation> m_directed_variations; - std::vector<bool> m_dirty_directed_variations; + std::vector<directed_variance> m_directed_variances; + std::vector<bool> m_dirty_directed_variance; - suitable_3d_view_computer m_suitable_3d_view_computer; - std::vector<bool> m_suitable_3d_view; - std::vector<bool> m_suitable_3d_view_in_children; - std::vector<bool> m_dirty_suitable_3d_views; + suitable_3d_view_computer m_suitable_3d_view_computer; + std::vector<bool> m_suitable_3d_view; + std::vector<bool> m_suitable_3d_view_in_children; + std::vector<bool> m_dirty_suitable_3d_views; }; } // namespace pvt diff --git a/pvt/include/pvt/suitable_3d_view_computer.hpp b/pvt/include/pvt/suitable_3d_view_computer.hpp index c12f7338e6d9c9b7cdd596b0ce013e08cb57d1d8..7cf2779466b759fda86127443fd68cbb83cffee8 100644 --- a/pvt/include/pvt/suitable_3d_view_computer.hpp +++ b/pvt/include/pvt/suitable_3d_view_computer.hpp @@ -26,21 +26,26 @@ #ifndef PVT_SUITABLE_3D_VIEW_COMPUTER_HPP_ #define PVT_SUITABLE_3D_VIEW_COMPUTER_HPP_ +#include <algorithm> #include <cassert> #include <vector> #include <pvt/api.hpp> -#include <pvt/directed_variation.hpp> namespace pvt { +class directed_variance; +class severity_view; + //------------------------------------------------------------------------------ class PVT_API suitable_3d_view_computer { public: suitable_3d_view_computer(std::size_t num_dimensions) - : m_threshold (0.01) - , m_filter_dimension_enabled(num_dimensions, false) + : m_num_dimensions (num_dimensions) + , m_threshold (0.01) + , m_severity_threshold (0.01) + , m_use_dimension_for_detection(num_dimensions, 1.0) { } @@ -56,24 +61,36 @@ public: bool get_filter_dimension_enabled(std::size_t index) const { - return m_filter_dimension_enabled[index]; + return !static_cast<bool>(m_use_dimension_for_detection[index]); } - void set_filter_dimension_enabled(std::size_t index, bool enabled) + void set_filter_dimension_enabled(std::size_t index, bool filtered) { - assert(index <= m_filter_dimension_enabled.size()); - m_filter_dimension_enabled[index] = enabled; + assert(index <= m_use_dimension_for_detection.size()); + m_use_dimension_for_detection[index] = static_cast<double>(!filtered); } void set_filter_dimension_enabled(const std::vector<bool>& other ) { - assert(other.size() == m_filter_dimension_enabled.size()); - m_filter_dimension_enabled = other; + assert(other.size() == m_use_dimension_for_detection.size()); + std::transform(other.begin(), + other.end (), + m_use_dimension_for_detection.begin(), + [](bool filtered) + { + return static_cast<double>(!filtered); + }); } - bool is_suitable_3d_view (const directed_variation& directed_variation) const; + bool is_suitable_3d_view(const severity_view& severity_view ) const; + bool is_suitable_3d_view(const directed_variance& directed_variance, + double mean ) const; + bool is_severe_enough (const severity_view& severity_view ) const; + private: - double m_threshold; - std::vector<bool> m_filter_dimension_enabled; + std::size_t m_num_dimensions; + double m_threshold; + double m_severity_threshold; + std::vector<double> m_use_dimension_for_detection; }; } // namespace pvt diff --git a/pvt/src/directed_variance.cpp b/pvt/src/directed_variance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..038430ace742d0c030899c03ea3c576a152f2c05 --- /dev/null +++ b/pvt/src/directed_variance.cpp @@ -0,0 +1,85 @@ +//============================================================================== +// pvt performance visualization toolkit +// +// Copyright (c) 2014-2016 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//============================================================================== +// License +// +// This library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// In the future, we may decide to add a commercial license +// at our own discretion without further notice. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//============================================================================== + +#include <cmath> + +#include <pvt/directed_variance.hpp> +#include <pvt/fft.hpp> + +namespace pvt +{ + +//------------------------------------------------------------------------------ +directed_variance::directed_variance +(std::size_t dimension_count) : data_array<double>(dimension_count) +{ + zero(); +} + + +//------------------------------------------------------------------------------ +void +directed_variance::compute +(const fft& fft) +{ + zero(); + + std::vector<double> curr_frequency(size(), 0.0); + for (std::size_t i = 1; i < fft.get_num_data(); ++i) + { + const double curr_spectral_energy = + fft.get_spectral_energy(i); + fft.convert_to_dc_centered_frequency(i, curr_frequency); + + const bool not_on_boundary = + !fft.is_on_boundary(curr_frequency); + + const double inverse_norm_squared = + 1.0 / fft.get_frequency_norm_squared(curr_frequency); + + // Add spectral energy to directed variance. + const auto add_weighted_spectral_energy_callable = + [curr_spectral_energy, + inverse_norm_squared, + not_on_boundary ] + (double curr_directed_variance , + double curr_frequency_component) + { + return + curr_directed_variance + + (1.0 + static_cast<double>(not_on_boundary)) * + inverse_norm_squared * + curr_frequency_component * curr_frequency_component * + curr_spectral_energy; + }; + + std::transform(begin(), + end (), + curr_frequency.begin(), + begin(), + add_weighted_spectral_energy_callable); + } +} +} // namespace pvt \ No newline at end of file diff --git a/pvt/src/directed_variation.cpp b/pvt/src/directed_variation.cpp deleted file mode 100644 index 7d0197c19cbdcf30d34a61a9a71a1888584d009d..0000000000000000000000000000000000000000 --- a/pvt/src/directed_variation.cpp +++ /dev/null @@ -1,104 +0,0 @@ -//------------------------------------------------------------------------------ -// pvt performance visualization toolkit -// -// Copyright (c) 2014-2016 RWTH Aachen University, Germany, -// Virtual Reality & Immersive Visualisation Group. -//------------------------------------------------------------------------------ -// License -// -// This library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// In the future, we may decide to add a commercial license -// at our own discretion without further notice. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -//------------------------------------------------------------------------------ - -#include <cassert> -#include <cstdio> - -#include <pvt/cnode.hpp> -#include <pvt/directed_variation.hpp> -#include <pvt/fft.hpp> -#include <pvt/fft_statistics.hpp> -#include <pvt/severity_view.hpp> - -namespace pvt { - -//------------------------------------------------------------------------------ -void -directed_variation::compute -(const severity_view& severity_view) -{ - /// \todo Determine what to do with multiple selections - - set_to_zero(); - - assert(severity_view.is_valid()); - - fft fft(severity_view.get_performance_data()-> - get_cartesian_topologies()[0].get_index()); - - severity_view.get_performance_data()->get_fft(severity_view, fft); - - m_mean = fft.get_mean (); - m_variance = fft.get_variance(); - - fft.get_directed_variation(*this); -} - - -//------------------------------------------------------------------------------ -void -directed_variation::dump -(const std::string& filename) const -{ - auto file = fopen(filename.c_str(), "wb"); - for (auto value : m_directed_variation) - fwrite(&value, sizeof(double), 1, file); - fclose(file); -} - - -//------------------------------------------------------------------------------ -bool -directed_variation::read -(const std::string& filename, - const severity_view& severity_view) -{ - auto file = fopen(filename.c_str(), "rb"); - const auto success = (file != nullptr); - if (file != nullptr) - { - fread(m_directed_variation.data(), - m_directed_variation.size() * sizeof(double), - 1, - file); - } - else - { - for_each(m_directed_variation.begin(), - m_directed_variation.end (), - [](double& v){ v = 0.0; }); - } - fclose(file); - - fft_statistics fft_statistics; - severity_view.get_performance_data()->get_fft_statistics(severity_view, - fft_statistics); - m_mean = fft_statistics.get(fft_statistics::mean); - m_variance = fft_statistics.get(fft_statistics::variance); - - return success; -} - -} // namespace pvt diff --git a/pvt/src/fft.cpp b/pvt/src/fft.cpp index 9443a0618c8ee8da59a093e33c8dee228ad7ab69..46f4bb4b7f18e5cfdeb12c4263192f170d6302f6 100644 --- a/pvt/src/fft.cpp +++ b/pvt/src/fft.cpp @@ -23,7 +23,7 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. //------------------------------------------------------------------------------ -#include <pvt/directed_variation.hpp> +#include <pvt/directed_variance.hpp> #include <pvt/fft.hpp> namespace pvt { @@ -52,62 +52,6 @@ const } -//------------------------------------------------------------------------------ -void -fft::get_directed_variation -(directed_variation& directed_variation) -const -{ - const auto& dimension_sizes(m_cart_topo_idx.get_dimension_sizes()); - for (std::size_t i = 1; i < m_cart_topo_idx.get_num_positions(); ++i) - { - const auto curr_coord(m_cart_topo_idx.get_coordinate(i)); - - auto boundary = false; - if ((dimension_sizes.back() % 2 == 1 && - dimension_sizes.back() == curr_coord.back() + 1) || - curr_coord .back() == 0) - boundary = true; - - const auto power_curr_frequency = (boundary ? 1 : 2) * mod_sq_at(i); - - for (std::size_t n = 0; n < curr_coord.size(); ++n) - { - long curr_coord_value = curr_coord.at(n); - auto left_in = true; - auto right_in = true; - for (std::size_t l = 0; l < n; ++l) - { - if (static_cast<long>(curr_coord.at(l)) < -curr_coord_value || - static_cast<long>(curr_coord.at(l)) >= curr_coord_value) - { - left_in = false; - break; - } - } - for (auto r = n+1; r < curr_coord.size(); ++r) - { - if (static_cast<long>(curr_coord.at(r)) <= -curr_coord_value || - static_cast<long>(curr_coord.at(r)) > curr_coord_value) - { - right_in = false; - break; - } - } - if (left_in && right_in) - { - directed_variation[n] += power_curr_frequency; - break; - } - } - } - - const auto mean_inv = 1.0 / get_mean(); - for (std::size_t i = 0; i < directed_variation.size(); ++i) - directed_variation[i] = sqrt(directed_variation[i])*mean_inv*m_normalizer; -} - - //------------------------------------------------------------------------------ void fft::zero diff --git a/pvt/src/io/perf_data_file_cube.cpp b/pvt/src/io/perf_data_file_cube.cpp index 47c85b258fc6ddccd23600822704ee034974ee05..77ad112f6b4e3dbfdbd8de1b664d8f7db4631c97 100644 --- a/pvt/src/io/perf_data_file_cube.cpp +++ b/pvt/src/io/perf_data_file_cube.cpp @@ -38,7 +38,7 @@ #include <pvt/cnode.hpp> #include <pvt/dft.hpp> #include <pvt/dft_inverse.hpp> -#include <pvt/directed_variation.hpp> +#include <pvt/directed_variance.hpp> #include <pvt/fft.hpp> #include <pvt/metric.hpp> #include <pvt/severity_view.hpp> @@ -291,12 +291,14 @@ const //------------------------------------------------------------------------------ void -perf_data_file_cube::get_directed_variation +perf_data_file_cube::get_directed_variance (const severity_view& severity_view, - directed_variation& directed_variation) + directed_variance& directed_variance) const { - directed_variation.compute(severity_view); + fft fft(mp_first_cartesian_topology->get_index()); + get_fft(severity_view, fft); + directed_variance.compute(fft); } diff --git a/pvt/src/io/perf_data_file_cube.hpp b/pvt/src/io/perf_data_file_cube.hpp index d159000da4490e0e1b10a4039594ec50d054ba9a..ed91ac1a9dd610cb7ef4fa235aa350fe67beea84 100644 --- a/pvt/src/io/perf_data_file_cube.hpp +++ b/pvt/src/io/perf_data_file_cube.hpp @@ -43,6 +43,7 @@ namespace cube { namespace pvt { +class directed_variance; class fft; class fft_statistics; @@ -95,8 +96,8 @@ public: void get_fft_statistics (const severity_view& severity_view, fft_statistics& fft_statistics ) const override; - void get_directed_variation (const severity_view& severity_view, - directed_variation& directed_variation) + void get_directed_variance (const severity_view& severity_view, + directed_variance& directed_variance ) const override; double get_autocorrelation_off_dc(const severity_view& severity_view ) const override; diff --git a/pvt/src/io/perf_data_file_native.cpp b/pvt/src/io/perf_data_file_native.cpp index e26b8e7221fe24188c79d5dad231b1e0c99290eb..edc65f0d7afb5331f843f0a5cce142f8bfb0cef6 100644 --- a/pvt/src/io/perf_data_file_native.cpp +++ b/pvt/src/io/perf_data_file_native.cpp @@ -32,7 +32,7 @@ #include <pvt/sysnode.hpp> #include <pvt/dft.hpp> #include <pvt/dft_inverse.hpp> -#include <pvt/directed_variation.hpp> +#include <pvt/directed_variance.hpp> #include <pvt/fft.hpp> #include <pvt/fft_statistics.hpp> #include <pvt/metric.hpp> @@ -313,9 +313,9 @@ const //------------------------------------------------------------------------------ void -perf_data_file_native::get_directed_variation +perf_data_file_native::get_directed_variance (const severity_view& severity_view, - directed_variation& directed_variation) + directed_variance& directed_variance) const { if (!severity_view.is_valid()) @@ -328,9 +328,9 @@ const severity_view.is_metric_total()) ? "I" : "E") + "_" + severity_view.get_cnode()->get_id_string() + ((severity_view.get_cnode()->has_children() && - severity_view.is_cnode_total()) ? "I" : "E") + ".dirvar"); + severity_view.is_cnode_total()) ? "I" : "E") + ".dvariance"); - directed_variation.read(filename_dir_var, severity_view); + directed_variance.read(filename_dir_var); } @@ -606,9 +606,10 @@ const (severity_view.is_metric_total() ? "I" : "E") + "_" + severity_view.get_cnode ()->get_id_string() + (severity_view.is_cnode_total() ? "I" : "E")); - m_severities_load_buffer.dump(severities_filename_base + ".dat"); - + if (export_flags & export_severities) + m_severities_load_buffer.dump(severities_filename_base + ".dat"); + // fft /// \todo Add remaining topologies if(perf_data.get_cartesian_topologies().size() != 0) @@ -620,7 +621,9 @@ const dft::compute(m_severities_load_buffer, cart_topo.get_index(), &fft); else perf_data.get_fft(severity_view, fft); - fft.dump(severities_filename_base + ".fft"); + + if (export_flags & export_fft) + fft.dump(severities_filename_base + ".fft"); // Compute autocorrelation. const double autocorrelation = @@ -636,12 +639,19 @@ const fft.get_variance()); fft_stat.set (fft_statistics::standard_deviation, fft.get_standard_deviation()); - fft_stat.dump(severities_filename_base + ".stat"); + + if (export_flags & export_fft) + fft_stat.dump(severities_filename_base + ".stat"); - // Directed variation. - directed_variation dir_var(cart_topo.get_num_dimensions()); - perf_data.get_directed_variation(severity_view, dir_var); - dir_var.dump(severities_filename_base + ".dirvar"); + if (export_flags & export_directed_variances) + { + directed_variance directed_variance(cart_topo.get_num_dimensions()); + if (export_flags & recompute_directed_variances) + directed_variance.compute(fft); + else + perf_data.get_directed_variance(severity_view, directed_variance); + directed_variance.dump(severities_filename_base + ".dvariances"); + } } } diff --git a/pvt/src/io/perf_data_file_native.hpp b/pvt/src/io/perf_data_file_native.hpp index 66bcd8ca2d6e837c890370e3e866576e93db32b2..92c7b76c0ee353033a40e2db921772199fa0559e 100644 --- a/pvt/src/io/perf_data_file_native.hpp +++ b/pvt/src/io/perf_data_file_native.hpp @@ -63,21 +63,21 @@ public: const std::vector<const metric*>& metric_ids, const std::vector<const cnode*>& cnode_ids ) const override; - double get_severity (const severity_view& severity_view ) + double get_severity (const severity_view& severity_view ) const override; void get_severities (const severity_view& severity_view, - data_array<double>& severities ) + data_array<double>& severities ) const override; void get_fft (const severity_view& severity_view, - fft& fft ) + fft& fft ) const override; void get_fft_statistics (const severity_view& severity_view, - fft_statistics& fft_statistics ) + fft_statistics& fft_statistics ) const override; - void get_directed_variation (const severity_view& severity_view, - directed_variation& directed_variation) + void get_directed_variance (const severity_view& severity_view, + directed_variance& directed_variance) const override; - double get_autocorrelation_off_dc(const severity_view& severity_view ) + double get_autocorrelation_off_dc(const severity_view& severity_view ) const override; private: diff --git a/pvt/src/io/perf_data_file_native_intermediate.cpp b/pvt/src/io/perf_data_file_native_intermediate.cpp index f2e814f37cbe98ad0244b2f5ac56b4d49d8676db..be23b3d926f1c091dc9c1b992ae71075d16f2eaf 100644 --- a/pvt/src/io/perf_data_file_native_intermediate.cpp +++ b/pvt/src/io/perf_data_file_native_intermediate.cpp @@ -32,7 +32,7 @@ #include <pvt/sysnode.hpp> #include <pvt/dft.hpp> #include <pvt/dft_inverse.hpp> -#include <pvt/directed_variation.hpp> +#include <pvt/directed_variance.hpp> #include <pvt/fft.hpp> #include <pvt/fft_statistics.hpp> #include <pvt/metric.hpp> @@ -286,12 +286,14 @@ const //------------------------------------------------------------------------------ void -perf_data_file_native_intermediate::get_directed_variation +perf_data_file_native_intermediate::get_directed_variance (const severity_view& severity_view, - directed_variation& directed_variation) + directed_variance& directed_variance) const { - directed_variation.compute(severity_view); + fft fft(m_first_cartesian_topology->get_index()); + get_fft(severity_view, fft); + directed_variance.compute(fft); } diff --git a/pvt/src/io/perf_data_file_native_intermediate.hpp b/pvt/src/io/perf_data_file_native_intermediate.hpp index 6de2edacf62203ba20459264856b32559e6290f0..87e4c298bdfb680e084c74d85b7afc64445b1928 100644 --- a/pvt/src/io/perf_data_file_native_intermediate.hpp +++ b/pvt/src/io/perf_data_file_native_intermediate.hpp @@ -65,21 +65,21 @@ public: const std::vector<const metric*>& metric_ids, const std::vector<const cnode*>& cnode_ids ) const override; - double get_severity (const severity_view& severity_view ) + double get_severity (const severity_view& severity_view ) const override; void get_severities (const severity_view& severity_view, - data_array<double>& severities ) + data_array<double>& severities ) const override; void get_fft (const severity_view& severity_view, - fft& fft ) + fft& fft ) const override; void get_fft_statistics (const severity_view& severity_view, - fft_statistics& fft_statistics ) + fft_statistics& fft_statistics ) const override; - void get_directed_variation (const severity_view& severity_view, - directed_variation& directed_variation) + void get_directed_variance (const severity_view& severity_view, + directed_variance& directed_variance) const override; - double get_autocorrelation_off_dc(const severity_view& severity_view ) + double get_autocorrelation_off_dc(const severity_view& severity_view ) const override; private: diff --git a/pvt/src/io/perf_data_file_test.cpp b/pvt/src/io/perf_data_file_test.cpp index 902550f79849a259c8034c75b2f294fc09ccc83c..c3afac94681031fdca4c0a5c6ea30c93aed7b7ee 100644 --- a/pvt/src/io/perf_data_file_test.cpp +++ b/pvt/src/io/perf_data_file_test.cpp @@ -32,7 +32,7 @@ #include <pvt/cnode.hpp> #include <pvt/dft.hpp> #include <pvt/dft_inverse.hpp> -#include <pvt/directed_variation.hpp> +#include <pvt/directed_variance.hpp> #include <pvt/fft.hpp> #include <pvt/fft_statistics.hpp> #include <pvt/metric.hpp> @@ -262,12 +262,14 @@ const //------------------------------------------------------------------------------ void -perf_data_file_test::get_directed_variation +perf_data_file_test::get_directed_variance (const severity_view& severity_view, -directed_variation& directed_variation) + directed_variance& directed_variance) const { - directed_variation.compute(severity_view); + fft fft(mp_cartesian_topology->get_index()); + get_fft(severity_view, fft); + directed_variance.compute(fft); } diff --git a/pvt/src/io/perf_data_file_test.hpp b/pvt/src/io/perf_data_file_test.hpp index fb9f1760eb3b31ecb9d7c036892b9d15baab29ab..1449903c638e5b467ec932ca460b621a1e1b63c2 100644 --- a/pvt/src/io/perf_data_file_test.hpp +++ b/pvt/src/io/perf_data_file_test.hpp @@ -70,21 +70,21 @@ public: return false; } - double get_severity (const severity_view& severity_view ) + double get_severity (const severity_view& severity_view ) const override; void get_severities (const severity_view& severity_view, - data_array<double>& severities ) + data_array<double>& severities ) const override; void get_fft (const severity_view& severity_view, - fft& fft ) + fft& fft ) const override; void get_fft_statistics (const severity_view& severity_view, - fft_statistics& fft_statistics ) + fft_statistics& fft_statistics ) const override; - void get_directed_variation (const severity_view& severity_view, - directed_variation& directed_variation) + void get_directed_variance (const severity_view& severity_view, + directed_variance& directed_variance) const override; - double get_autocorrelation_off_dc(const severity_view& severity_view ) + double get_autocorrelation_off_dc(const severity_view& severity_view ) const override; private: diff --git a/pvt/src/perf_data.cpp b/pvt/src/perf_data.cpp index 419cae4671d1f8e53d676d1c0c6caab1f4cd94d8..a86dde8eee6a6dc7d1643b5314c0a1b002232a37 100644 --- a/pvt/src/perf_data.cpp +++ b/pvt/src/perf_data.cpp @@ -205,12 +205,12 @@ const //------------------------------------------------------------------------------ void -perf_data::get_directed_variation +perf_data::get_directed_variance (const severity_view& severity_view, - directed_variation& directed_variation) + directed_variance& directed_variance) const { - mp_perf_data_file->get_directed_variation(severity_view, directed_variation); + mp_perf_data_file->get_directed_variance(severity_view, directed_variance); } diff --git a/pvt/src/perf_data_cache_cnode.cpp b/pvt/src/perf_data_cache_cnode.cpp index c3168cb8cf0d00e7b7180e5a71f625cf96d0ecc9..874f73148121181340df1c379294649f3ed8d87f 100644 --- a/pvt/src/perf_data_cache_cnode.cpp +++ b/pvt/src/perf_data_cache_cnode.cpp @@ -43,14 +43,14 @@ perf_data_cache_cnode::perf_data_cache_cnode ->get_cnodes().size(), 0.0) , m_dirty_severities (p_severity_view->get_performance_data() ->get_cnodes().size(), true) -, m_directed_variations (p_severity_view->get_performance_data() +, m_directed_variances (p_severity_view->get_performance_data() ->get_cnodes().size(), - directed_variation( + directed_variance( p_severity_view ->get_performance_data() ->get_cartesian_topologies()[0] .get_num_dimensions())) -, m_dirty_directed_variations (p_severity_view->get_performance_data() +, m_dirty_directed_variance (p_severity_view->get_performance_data() ->get_cnodes().size(), true) , m_suitable_3d_view_computer (p_severity_view->get_performance_data() ->get_cartesian_topologies()[0] @@ -90,15 +90,16 @@ perf_data_cache_cnode::update_severity //------------------------------------------------------------------------------ void -perf_data_cache_cnode::update_directed_variation +perf_data_cache_cnode::update_directed_variance (const cnode* p_cnode) { + /// \todo Make this work with total *and* self severity. severity_view curr_severity_view(mp_severity_view->get_performance_data()); curr_severity_view.set_metric (mp_severity_view->get_metric()); curr_severity_view.set_cnode (p_cnode); - mp_severity_view->get_performance_data()->get_directed_variation( - curr_severity_view, m_directed_variations[p_cnode->get_id()]); + mp_severity_view->get_performance_data()->get_directed_variance( + curr_severity_view, m_directed_variances[p_cnode->get_id()]); } @@ -107,15 +108,33 @@ void perf_data_cache_cnode::update_suitable_3d_view (const cnode* p_cnode) { + if (mp_severity_view->get_metric() == nullptr) + return; + m_suitable_3d_view [p_cnode->get_id()] = false; m_suitable_3d_view_in_children[p_cnode->get_id()] = false; // suitable 3D view in p_cnode - check_and_update_directed_variation(p_cnode); - m_suitable_3d_view[p_cnode->get_id()] = - m_suitable_3d_view_computer.is_suitable_3d_view( - m_directed_variations[p_cnode->get_id()]); + const double mean = + get_severity_total(p_cnode) / + static_cast<double>(m_severities_load_buffer.size()); + check_and_update_directed_variance(p_cnode); + + const severity_view curr_sev_view(mp_severity_view->get_performance_data(), + mp_severity_view->get_metric (), + mp_severity_view->is_metric_total (), + p_cnode, + mp_severity_view->is_cnode_total ()); + const bool is_large_severity = + m_suitable_3d_view_computer.is_severe_enough(curr_sev_view); + const bool is_large_variation = + m_suitable_3d_view_computer.is_suitable_3d_view( + m_directed_variances[p_cnode->get_id()], mean); + + m_suitable_3d_view[p_cnode->get_id()] = + is_large_severity && is_large_variation; + // suitable 3D view in children for (const cnode* p_curr_child_cnode : p_cnode->get_children()) { diff --git a/pvt/src/suitable_3d_view_computer.cpp b/pvt/src/suitable_3d_view_computer.cpp index 6401506689dd8db451f35f8edce3355511ff42a1..4a001a94fc21947877d0cba4958e60a5158f0948 100644 --- a/pvt/src/suitable_3d_view_computer.cpp +++ b/pvt/src/suitable_3d_view_computer.cpp @@ -23,8 +23,13 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. //------------------------------------------------------------------------------ +#include <cmath> + #include <iostream> +#include <pvt/directed_variance.hpp> +#include <pvt/perf_data.hpp> +#include <pvt/severity_view.hpp> #include <pvt/suitable_3d_view_computer.hpp> namespace pvt { @@ -32,22 +37,57 @@ namespace pvt { //------------------------------------------------------------------------------ bool suitable_3d_view_computer::is_suitable_3d_view -(const directed_variation& directed_variation) +(const severity_view& severity_view) +const +{ + const perf_data* p_perf_data = severity_view.get_performance_data(); + const double mean = p_perf_data->get_mean(severity_view); + + if (mean == 0.0) + return false; + + directed_variance directed_variance(m_num_dimensions); + p_perf_data->get_directed_variance(severity_view, directed_variance); + return is_suitable_3d_view(directed_variance, mean); +} + + +//------------------------------------------------------------------------------ +bool +suitable_3d_view_computer::is_suitable_3d_view +(const directed_variance& directed_variance, + double mean) const { - if (directed_variation.get_mean() == 0.0) + if (mean == 0.0) return false; - double filter = 0.0; - for (std::size_t i = 0; i < m_filter_dimension_enabled.size(); ++i) - { - filter += static_cast<double>(m_filter_dimension_enabled[i]) * - (i == m_filter_dimension_enabled.size() - 1 ? 2.0 : 1.0) * - directed_variation[i] * directed_variation[i]; - } + const double filtered_variance = std::inner_product( + directed_variance.begin(), + directed_variance.end (), + m_use_dimension_for_detection.begin(), + 0.0); + + return std::max(0.0, sqrt(filtered_variance) / mean) >= m_threshold; +} + +//------------------------------------------------------------------------------ +bool +suitable_3d_view_computer::is_severe_enough +(const severity_view& severity_view) +const +{ + const perf_data* p_perf_data = severity_view.get_performance_data(); + const double severity = p_perf_data->get_severity(severity_view); - return directed_variation.get_std_deviation() / directed_variation.get_mean() - - sqrt(filter) >= m_threshold; + pvt::severity_view root_severity_view(p_perf_data, + severity_view.get_metric (), + severity_view.is_metric_total(), + p_perf_data->get_root_cnodes ()[0], + severity_view::total); + + const double root_severity = p_perf_data->get_severity(root_severity_view); + return (severity / root_severity >= m_severity_threshold); } } // namespace pvt diff --git a/pvt/tests/_SourceFiles.cmake b/pvt/tests/_SourceFiles.cmake index e85c94a49eb4c0b37956f5ae2fe7cf29050a5840..f065e61d32c1fb79e4777fbc03d6c05de0743c14 100644 --- a/pvt/tests/_SourceFiles.cmake +++ b/pvt/tests/_SourceFiles.cmake @@ -28,7 +28,9 @@ set(SourceFiles ./src/cartesian_topology_test.cpp ./src/correlation_computer_test.cpp ./src/data_array_test.cpp + ./src/directed_variance_test.cpp ./src/fft_test.cpp ./src/perf_lib_tests.cpp - ./src/severity_view_test + ./src/severity_view_test.cpp + ./src/suitable_3d_view_computer_test.cpp ) diff --git a/pvt/tests/src/directed_variance_test.cpp b/pvt/tests/src/directed_variance_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d92f2c696d55d91da27ccf8dc6659c1060e30f5 --- /dev/null +++ b/pvt/tests/src/directed_variance_test.cpp @@ -0,0 +1,262 @@ +//------------------------------------------------------------------------------ +// pvt_tests performance visualization toolkit tests +// +// Copyright (c) 2014-2016 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//------------------------------------------------------------------------------ +// License +// +// This library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// In the future, we may decide to add a commercial license +// at our own discretion without further notice. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//------------------------------------------------------------------------------ + +#include <random> +#include <vector> + +#include <catch/catch.hpp> + +#include <pvt/directed_variance.hpp> +#include <pvt/cartesian_topology_index.hpp> +#include <pvt/dft.hpp> +#include <pvt/fft.hpp> + + +//------------------------------------------------------------------------------ +TEST_CASE("DirectedVariance::DirectedVariance", "[DirectedVariance]") +{ + for (int size : std::vector<int>{1,2,3,4,5,6,7}) + { + pvt::directed_variance directed_variance(size); + CHECK(directed_variance.size() == size); + CHECK(directed_variance.is_guaranteed_zero()); + } +} + + +//------------------------------------------------------------------------------ +TEST_CASE("DirectedVariance::Compute", "[DirectedVariance]") +{ + const double spectrum_data[] = { + -1.369913,2.366388,0.6521624,0.07948478,-3.139513,-0.6373961,-3.584597,0.2073881,0.1376447,-1.9441,-1.326197,2.905413,0.8863745,-2.710374,2.397778,-0.9319011,-1.174726,-3.528292,4.197448,2.030763,0.6237432,4.207995,-0.670411,-4.546502,4.197127,1.565445,-2.891712,-0.5863564,-4.482699,-1.783888,-2.810772,1.894166,-4.130436,-1.115266,-1.457356,2.61725,3.344832,1.557889,-2.252932,-1.660134,-0.4913552,0.1312131,-0.1153154,2.760733,-1.98237,2.822069,-4.028788,4.303903,-2.451332,-4.187387,2.965507,0.7762695,-0.377119,-2.896434,1.870632,-4.186059,-3.372643,4.578634,1.227212,-1.734647,-1.495074,-3.214745,-2.734743,-0.7711106,-0.4849214,1.157676,-1.590643,-3.509943,-2.987695,0.8403664,3.713521,1.988254,-0.2822454,-4.381549,2.618375,1.632381,-1.294663,2.245158,-1.019739,2.880541,-4.165443,-0.5093203,-1.651713,0.7140556,-2.570878,-4.805998,0.7998896,4.979499,-3.52999,4.122707,1.09838,1.703642,3.912077,0.8228862,-4.785337,0.8622973,-4.290397,-1.859103,2.474399,-0.3474172,-1.037385,-0.990954,3.333944,-0.2554035,4.464058,-1.462566,1.520508,2.29024,3.145041,-2.614427,-3.188559,-1.565896,-1.438336,1.388296,1.622,1.006307,4.331945,-0.7760114,-1.900294,-1.951809,-1.745559,-4.344393,0.02764852,3.914259,0.6552216,0.9407595,-3.857112,2.804464,-2.139115,0.2538526,0.4874584,3.400789,-2.546813,4.938403,0.1297929,3.712869,-1.339926,2.047624,-0.5382827,-4.34787,2.733606,-1.03078,-1.681716,-2.214075,1.616909,-4.670197,-2.081648,4.842972,-4.007842,-3.945008,-3.125872,-4.81508,-0.4591504,0.008876526,0.9195158,0.7854289,-0.3498682,-1.055508,4.408534,2.64489,3.908404,-0.2768685,2.637573,4.372526,0.4875315,3.940774,-1.605772,2.971435,-0.7663714,0.4655775,-1.808636,-0.14464,1.188111,-2.17075,0.676254,4.022637,2.909643,-0.8094599,-4.702995,3.972847,4.436124,-1.44684,-3.72467,3.694023,0.8160294,-2.05145,2.065671,-0.01430093,-2.535358,-1.693163,1.623026,0.2844812,-1.724,-1.258672,-1.70551,0.2590194,-3.545418,-3.866471,-3.633409,-0.3091785,-3.461003,0.6404171,2.183082,4.004183,-3.031348,1.316437,-2.224576,0.4501649,-3.860688,4.071137,-0.6587274,0.6097026,1.675925,-0.7354876,-1.912968,2.824176,-0.7317517,2.338288,0.08061561,0.7470006,2.710333,1.790396,-0.6281233,3.589776,-3.748256,0.9919137,0.8400855,-1.8431,-4.090332,2.316923,-4.2323,4.742728,0.03790093,-2.626879,3.309977,2.202485,1.942958,1.817379,-1.405582,2.536278,1.639531,-2.590465,3.456326,0.3103449,2.875822,-4.462864,-4.430421,-0.8327393,-3.199763,4.103811,2.188127,-3.746204,4.607108,-0.3609127,1.432325,-4.917104,1.829677,2.184505,-4.549202,2.412765,4.042145,-1.93022,-3.126769,-1.600341,4.296105,-3.395978,3.427427,-3.120721,-1.388852,-1.814336,-1.848667,4.481507,1.453348,-1.264266,3.419098,-1.648179,-4.169432,-4.14443,2.739097,0.5629735,0.3000108,-4.267615,-4.8329,-2.155095,-4.945808,3.706581,2.825116,4.955093,-3.065355,0.2911179,-2.734978,0.5646557,4.619667,-1.31312,-4.089968,-1.000821,-2.69756,3.238973,-4.424421,4.447163,4.585067,-0.9135598,3.476157,-4.520727,-0.5010364,-1.528134,-0.2242176,2.461321,-1.962953,0.7482519,2.415686,-1.915374,4.950959,3.119315,-4.689511,-3.219674,0.5949967,0.1770396,4.075034,0.6035698,-4.660614,1.656996,-1.996141,-1.234983,-4.467595,2.738634,3.125744,-1.181945,3.170675,-3.259505,0.4461302,3.249395,3.96159,4.760156,-1.689337,-0.8831463,-0.06247168,2.846347,-2.965174,-0.4221235,-2.229872,-1.832002,0.05475664,3.694801,1.874079,0.1381601,3.094757,-3.673665,2.692834,-1.387724,-4.877,-1.346007,-3.822925,3.726607,-3.003125,0.1171474,2.622373,-2.72918,2.802191,1.723427,1.196739,-1.280793,4.922892,-4.4809,2.463651,-1.857089,3.499174,-0.458942,-4.759206,3.604032,-1.109835,-2.106077,-2.453591,2.832016,4.980618,4.132827,-3.597036,4.355951,0.6811251,3.498149,-4.334909,2.595992,-4.485421,-4.670106,-4.005569,4.115529,-1.646041,-0.2335701,-3.052513,-4.244956,1.686286,-0.9487545,-3.552227,0.8489712,0.3929639,-3.207691,4.382301,3.543788,0.1353077,-1.642821,1.493422,3.208002,-0.2198212,-1.316295,3.071922,3.432747,-1.898178,-3.056682,2.836319,1.875577,-1.162045,3.855697,-2.443832,1.759877,4.468894,-1.675228,3.435107,1.493792,4.784789,3.729388,-1.436914,3.238561,-2.259653,-2.794186,3.430316,4.60554,1.856805,3.763975,1.58563,1.793164,-1.930789,-1.706783,0.6436954,-1.225055,-3.942179,-1.00271,2.703654,0.8958307,1.542261,-2.416321,-1.726497,1.389547,-4.047774,-0.1024064,-1.75815,-1.771344,2.149576,1.387446,-4.021947,3.007576,-3.294618,-3.83159,3.336735,3.671967,1.644395,4.700867,4.768029,0.4876594,-1.236264,-1.013503,-1.522369,-0.9065275,2.69649,-1.077991,-3.64208,1.813689,-3.893352,-2.684463,-3.36132,1.658508,3.418935,3.912671,4.640396,1.478699,-0.6495142,4.400014,-2.25244,2.853991,4.18704,-4.147005,-3.356997,-4.153644,-4.706075,-2.822882,3.460948,-4.625567,1.529059,4.563374,-0.8567305,-1.176542,2.930833,-3.338201,-3.535962,-1.820929,-1.253513,-0.4813879,-3.790662,-1.999548,2.31139,-0.017764,0.1099512,-2.874798,-1.338556,2.871899,-1.967828,0.1724809,-1.233695,1.217031,3.682194,0.2931954,-1.008656,-2.444212,3.767573,1.419545,-3.776185,-4.901763,1.918013,2.714736,3.685224,-0.4101552,-0.7943763,-4.2924,-4.03582,-3.392411,-2.788221,4.358056,4.070031,2.016769,4.826952,-0.7332687,2.89612,-4.54988,2.918114,0.01984436,0.8641107,0.1853472,-1.040283,2.632474,-4.452173,0.8178937,-1.851216,-2.541452,-4.677902,-0.5476424,3.565796,-2.229253,1.003853,-1.604895,4.476669,-4.880149,2.431952,2.917534,-1.644005,-1.203889,-1.814078,-4.141077,4.12799,-0.73715,-1.239947,-3.134105,-0.6570192,4.130657,-3.132485,0.4356758,1.667223,-0.8467199,4.328557,1.526807,-3.304786,-3.093477,2.081823,1.407445,-3.032234,-1.810072,-1.317263,-1.985723,0.00692565,1.588858,-2.372327,-4.14642,-0.9869937,0.6264856,3.994453,-4.381107,-3.902164,-3.973919,0.2723818,-2.032398,2.22746,-3.059622,4.084146,3.837697,-0.01966125,-3.371466,2.166808,-2.950862,-2.744717,-2.700448,1.313718,-3.330663,-4.562059,-1.805587,3.471049,0.439569,-3.808685,-3.151315,0.03174188,1.49604,4.241116,-4.07072,-2.288171,4.511365,3.905877,-4.706106,2.121834,3.786416,-3.670914,-0.8177196,-0.5583311,4.88663,1.054654,-0.09296663,-2.15319,1.851507,-4.06048,-3.963792,-0.08018484,-3.689403,-4.241369,1.765912,4.638205,0.3536397,-1.60834,2.540778,-0.08902409,0.8472323,-2.761184,2.059002,-2.104599,0.1219844,-2.412087,2.530434,1.24684,2.99004,-0.1234092,-0.6575862,1.979607,1.715941,-0.05967927,3.99103,3.959484,-0.7766564,1.515213,-2.674432,-3.356128,2.180855,-0.5086425,3.477356,-3.572774,1.06951,-4.399567,2.478876,-0.6791827,-2.239727,-3.404473,-2.329583,-2.068425,4.321843,0.5630234,2.800825,2.929684,-3.459303,4.630725,3.6181,2.416599,3.199518,-2.027053,4.192428,-0.1109226,0.05335014,2.200289,0.3453289,0.5538159,2.861421,-4.566319,-1.62961,1.160116,-1.499507,1.58428,-3.247864,1.693863,-2.757239,-4.843471,-1.050192,0.3326872,-0.589359,2.453403,-2.677118,-3.612077,1.483618,3.292582,-0.1875171,0.3414228,-1.185971,-0.2426185,-4.225299,1.588602,-4.979177,-1.947325,-4.88343,-0.9010608,0.8278277,-0.3552982,-1.204476,4.902699,-0.3965531,-3.626224,2.015866,-3.055131,-2.320581,-4.448844,4.842378,0.8267493,0.4051684,1.547572,-1.46898,1.609699,1.537668,-3.260082,-3.231951,2.587496,0.3964881,-3.927411,-0.1469738,-4.132704,-1.291339,-4.939216,-0.623815,3.59199,-4.995882,-2.78605,-4.064701,0.1309813,0.7786342,1.071051,-2.933012,-1.32117,0.7520308,-4.170256,2.357965,2.885802,4.651315,-4.512418,-3.777345,3.801185,-3.169972,4.575074,4.82493,-2.548944,-1.769693,-1.475259,-1.188101,0.2354121,4.142811,2.453527,-0.6529329,3.430494,3.805997,-4.858164,-1.136086,-2.065552,4.272876,-2.683444,0.7039462,-1.927873,1.230041,-1.891734,3.55055,-1.853263,-4.974805,0.4941509,0.7358424,-4.897612,3.491554,-3.082488,-0.5684068,-0.1871608,0.8128174,3.094566,-3.270852,4.022744,-0.831012,0.3264192,4.11912,3.621926,-2.271641,-1.73442,-3.089872,2.036488,-2.222206,-4.038173,-2.897205,1.293008,-1.22098,1.403362,-2.225616,-1.050236,0.5560639,3.642455,-2.935901,-2.249444,-1.01599,-1.338648,2.473612,1.931781,-0.9931235,-2.943017,-0.701465,-1.791676,0.8454944,2.810721,-2.777712,-0.3614675,4.643626,-1.169829,0.7037033,2.546449,-2.432819,2.484743,1.649978,2.233204,-0.6115226,4.615884,0.3476094,-2.652029,2.274503,-2.655572,3.515361,4.053975,-4.939088,-4.627424,0.8908671,3.606056,0.4238621,2.184325,-0.6400531,-3.401546,3.28772,-4.910939,3.257024,-0.3799469,1.988309,-0.2810646,4.727108,4.830485,0.4236326,-2.350652,3.089058,3.640319,0.2976578,2.689988,-4.495284,-1.687496,3.396501,0.5444392,0.8912038,-3.012119,-3.505027,-4.935315,0.7148314,-2.671151,-3.604947,-0.7104763,-3.397056,-0.8020962,-1.782109,-1.684752,0.3861716,2.441642,-4.335293,-3.702416,-3.071541,-0.07533606,-2.086793,3.010706,-0.6651532,3.794496,2.756859,-2.094831,4.824826,1.992409,2.539033,-1.645615,-3.981428,-2.304592,0.2324714,4.092899,-3.918883,-4.920475,1.117414,0.1694542,4.674824,0.7865915,3.732613,1.069255,-4.954311,2.380101,-3.59956,-1.93683,-0.6727581,-1.467414,2.753198,2.041578,-2.285471,0.779966,-0.8451113,-0.1609521,-1.805747,4.047759,-1.215726,-3.652803,4.532855,-2.777841,4.330934,0.3709948,-4.187267,-3.63443,-1.176549,-3.387937,-3.638874,-1.54311,3.774307,1.928578,-4.155294,4.926734,0.7512807,0.989133,-2.554384,3.446888,4.589619,1.374557,-3.026944,1.725522,-2.218709,-0.8435813,3.355309,4.444024,-2.242641,4.94601,0.7474062,-3.664192,1.605895,2.714703,-0.4977869,-4.004246,0.562795,4.295855,4.911277,-3.815203,-2.788086,1.811439,-3.616373,-2.700748,-1.323992,1.368377,3.151859,-0.3637925,1.544209,3.848862,1.197046,0.7580547,-4.254427,4.137102,0.7360986,-1.023367,4.093891,3.920758,2.93392,3.642718,-3.48912,2.239089,4.137581,-1.468438,-2.678099,3.987468,-2.174463,-4.521366,-3.079582,4.175912,0.7146019,-0.6738766,-0.3388514,-3.216973,3.838625,-0.3579994,-2.721465,-0.8264616,3.121057,1.4306,-0.3641855,3.31209,-4.777424,-2.545542,0.1662704,4.490584,-1.528808,-0.1116809,1.020497,2.101213,2.715402,3.194785,0.9837849,-2.408737,-3.943825,3.230697,-3.418833,-2.201047,-0.7701247,-1.263477,4.383908,-2.4984,3.990038,3.354573,1.185572 + }; + + SECTION("1D_size1") + { + pvt::cartesian_topology_index cart_topo_idx(std::vector<std::size_t>{1}); + pvt::fft spectrum(cart_topo_idx); + for (std::size_t i = 0; i < cart_topo_idx.get_num_positions(); ++i) + { + spectrum.real(i) = spectrum_data[2 * i + 0]; + spectrum.imag(i) = spectrum_data[2 * i + 1]; + } + + pvt::directed_variance directed_variance(cart_topo_idx.get_num_dimensions()); + directed_variance.compute(spectrum); + REQUIRE(directed_variance.size() == 1); + CHECK(directed_variance.at(0) == Approx(0)); + } + + SECTION("1D_size8") + { + pvt::cartesian_topology_index cart_topo_idx(std::vector<std::size_t>{8}); + pvt::fft spectrum(cart_topo_idx); + for (std::size_t i = 0; i < spectrum.get_num_data(); ++i) + { + spectrum.real(i) = 8 * spectrum_data[2 * i + 0]; + spectrum.imag(i) = 8 * spectrum_data[2 * i + 1]; + } + + pvt::directed_variance directed_variance(cart_topo_idx.get_num_dimensions()); + directed_variance.compute(spectrum); + REQUIRE(directed_variance.size() == 1); + + double intended_result = 0.0; + for (std::size_t j = 1; j < 4; ++j) + { + intended_result += + 2.0 * (spectrum_data[2*j] * spectrum_data[2*j] + + spectrum_data[2*j + 1] * spectrum_data[2*j + 1]); + } + for (std::size_t j = 4; j < 5; ++j) + { + intended_result += + spectrum_data[2*j] * spectrum_data[2*j] + + spectrum_data[2*j + 1] * spectrum_data[2*j + 1]; + } + CHECK(directed_variance.at(0) == intended_result); + } + + SECTION("2D_size4") + { + pvt::cartesian_topology_index cart_topo_idx(std::vector<std::size_t>{2, 2}); + pvt::fft spectrum(cart_topo_idx); + const double spectrum_data[] = { + 10.0, 20.0, 1.0, 0.5, + 0.2, 0.6, 0.3, 0.4 + }; + for (std::size_t i = 0; i < spectrum.get_num_data(); ++i) + { + spectrum.real(i) = 4.0 * spectrum_data[2 * i + 0]; + spectrum.imag(i) = 4.0 * spectrum_data[2 * i + 1]; + } + + pvt::directed_variance directed_variance(cart_topo_idx.get_num_dimensions()); + directed_variance.compute(spectrum); + REQUIRE(directed_variance.size() == 2); + + const std::vector<double> reference_directed_variance { + (0.2 * 0.2 + 0.6 * 0.6) + + 1.0 / 2.0 * (0.3 * 0.3 + 0.4 * 0.4), + (1.0 * 1.0 + 0.5 * 0.5) + + 1.0 / 2.0 * (0.3 * 0.3 + 0.4 * 0.4) + }; + + CHECK(directed_variance[0] == Approx(reference_directed_variance[0])); + CHECK(directed_variance[1] == Approx(reference_directed_variance[1])); + } + + SECTION("2D_size16") + { + pvt::cartesian_topology_index cart_topo_idx(std::vector<std::size_t>{4, 4}); + pvt::fft spectrum(cart_topo_idx); + const double spect_dat[] = { + 1.7, 2.2, 0.6, 1.0, 1.3, 1.4, + 1.6, 0.9, 1.1, 2.3, 1.9, 0.5, + 2.4, 2.1, 0.7, 1.5, 0.2, 1.2, + 0.8, 1.8, 0.1, 2.0, 0.4, 0.3 + }; + for (std::size_t i = 0; i < spectrum.get_num_data(); ++i) + { + spectrum.real(i) = 16.0 * spect_dat[2 * i + 0]; + spectrum.imag(i) = 16.0 * spect_dat[2 * i + 1]; + } + + pvt::directed_variance directed_variance(cart_topo_idx.get_num_dimensions()); + directed_variance.compute(spectrum); + REQUIRE(directed_variance.size() == 2); + + const std::vector<double> reference_directed_variance{ + 2.0 * 0.0 / 1.0 * (spect_dat[ 2] * spect_dat[ 2] + spect_dat[ 3] * spect_dat[ 3]) + + 1.0 * 0.0 / 4.0 * (spect_dat[ 4] * spect_dat[ 4] + spect_dat[ 5] * spect_dat[ 5]) + + 1.0 * 1.0 / 1.0 * (spect_dat[ 6] * spect_dat[ 6] + spect_dat[ 7] * spect_dat[ 7]) + + 2.0 * 1.0 / 2.0 * (spect_dat[ 8] * spect_dat[ 8] + spect_dat[ 9] * spect_dat[ 9]) + + 1.0 * 1.0 / 5.0 * (spect_dat[10] * spect_dat[10] + spect_dat[11] * spect_dat[11]) + + 1.0 * 4.0 / 4.0 * (spect_dat[12] * spect_dat[12] + spect_dat[13] * spect_dat[13]) + + 2.0 * 4.0 / 5.0 * (spect_dat[14] * spect_dat[14] + spect_dat[15] * spect_dat[15]) + + 1.0 * 4.0 / 8.0 * (spect_dat[16] * spect_dat[16] + spect_dat[17] * spect_dat[17]) + + 1.0 * 1.0 / 1.0 * (spect_dat[18] * spect_dat[18] + spect_dat[19] * spect_dat[19]) + + 2.0 * 1.0 / 2.0 * (spect_dat[20] * spect_dat[20] + spect_dat[21] * spect_dat[21]) + + 1.0 * 1.0 / 5.0 * (spect_dat[22] * spect_dat[22] + spect_dat[23] * spect_dat[23]) + + , + + 2.0 * 1.0 / 1.0 * (spect_dat[ 2] * spect_dat[ 2] + spect_dat[ 3] * spect_dat[ 3]) + + 1.0 * 4.0 / 4.0 * (spect_dat[ 4] * spect_dat[ 4] + spect_dat[ 5] * spect_dat[ 5]) + + 1.0 * 0.0 / 1.0 * (spect_dat[ 6] * spect_dat[ 6] + spect_dat[ 7] * spect_dat[ 7]) + + 2.0 * 1.0 / 2.0 * (spect_dat[ 8] * spect_dat[ 8] + spect_dat[ 9] * spect_dat[ 9]) + + 1.0 * 4.0 / 5.0 * (spect_dat[10] * spect_dat[10] + spect_dat[11] * spect_dat[11]) + + 1.0 * 0.0 / 4.0 * (spect_dat[12] * spect_dat[12] + spect_dat[13] * spect_dat[13]) + + 2.0 * 1.0 / 5.0 * (spect_dat[14] * spect_dat[14] + spect_dat[15] * spect_dat[15]) + + 1.0 * 4.0 / 8.0 * (spect_dat[16] * spect_dat[16] + spect_dat[17] * spect_dat[17]) + + 1.0 * 0.0 / 1.0 * (spect_dat[18] * spect_dat[18] + spect_dat[19] * spect_dat[19]) + + 2.0 * 1.0 / 2.0 * (spect_dat[20] * spect_dat[20] + spect_dat[21] * spect_dat[21]) + + 1.0 * 4.0 / 5.0 * (spect_dat[22] * spect_dat[22] + spect_dat[23] * spect_dat[23]) + }; + + CHECK(reference_directed_variance[0] + reference_directed_variance[1] == Approx(55.88)); + CHECK(directed_variance[0] == Approx(reference_directed_variance[0])); + CHECK(directed_variance[1] == Approx(reference_directed_variance[1])); + } + + SECTION("2D_size64") + { + pvt::cartesian_topology_index cart_topo_idx(std::vector<std::size_t>{8, 8}); + pvt::fft spectrum(cart_topo_idx); + for (std::size_t i = 0; i < spectrum.get_num_data(); ++i) + { + spectrum.real(i) = 64 * spectrum_data[2 * i + 0]; + spectrum.imag(i) = 64 * spectrum_data[2 * i + 1]; + } + + pvt::directed_variance directed_variance(cart_topo_idx.get_num_dimensions()); + directed_variance.compute(spectrum); + REQUIRE(directed_variance.size() == 2); + + std::vector<double> intended_result(2, 0.0); + for (std::size_t x = 0; x < 8; ++x) + { + const double x_dc = static_cast<double>(x) - static_cast<double>(x > 4) * 8.0; + + for (std::size_t y = 0; y < 5; ++y) + { + const std::size_t curr_index = x * 5 + y; + + const double norm_sq = x_dc * x_dc + y * y; + + if (curr_index > 0) + { + const double curr_real = spectrum_data[2 * curr_index + 0]; + const double curr_imag = spectrum_data[2 * curr_index + 1]; + const double curr_spectral_energy = + curr_real * curr_real + curr_imag * curr_imag; + REQUIRE(spectrum.get_spectral_energy(curr_index) == Approx(curr_spectral_energy)); + + const double factor = (y == 0 || y == 4) ? 1.0 : 2.0; + + const double weighted_spectral_energy_x = + 1.0 / norm_sq * x_dc * x_dc * curr_spectral_energy; + const double weighted_spectral_energy_y = + 1.0 / norm_sq * y * y * curr_spectral_energy; + + REQUIRE(weighted_spectral_energy_x + weighted_spectral_energy_y + == Approx(curr_spectral_energy)); + + intended_result[0] += factor * weighted_spectral_energy_x; + intended_result[1] += factor * weighted_spectral_energy_y; + } + } + } + CHECK(directed_variance.at(0) == intended_result.at(0)); + CHECK(directed_variance.at(1) == intended_result.at(1)); + } +} + + +//------------------------------------------------------------------------------ +TEST_CASE("DirectedVariance_SumsToVariance", "[DirectedVariance]") +{ + pvt::cartesian_topology_index cart_topo_idx(std::vector<size_t>{8,28,8,8,2,16,4}); + pvt::data_array<double> data(cart_topo_idx.get_num_positions()); + + std::random_device rd; + std::mt19937 mt(rd()); + std::uniform_real_distribution<double> distribution(0.0, 10.0); + std::for_each(data.begin(), + data.end(), + [&distribution, &mt](double& v){ v = distribution(mt);}); + + pvt::fft spectrum(cart_topo_idx); + pvt::dft::compute(data, cart_topo_idx, &spectrum); + + pvt::directed_variance dir_var(cart_topo_idx.get_num_dimensions()); + dir_var.compute(spectrum); + + const double variance_from_dir_var = std::accumulate(dir_var.begin(), + dir_var.end (), + 0.0); + + CHECK(variance_from_dir_var == Approx(spectrum.get_variance())); +} \ No newline at end of file diff --git a/pvt/tests/src/fft_test.cpp b/pvt/tests/src/fft_test.cpp index fcfdfa22df31dc64b950f81c0e95e695f705a261..e227de44c10e20f1430cb7cab5a644e69668aa3b 100644 --- a/pvt/tests/src/fft_test.cpp +++ b/pvt/tests/src/fft_test.cpp @@ -421,7 +421,7 @@ TEST_CASE("Fft", "[Fft]") //------------------------------------------------------------------------------ -TEST_CASE("FftZero", "[FftZero]") +TEST_CASE("FftZero", "[Fft]") { const pvt::cartesian_topology_index cart_topo_idx(std::vector<std::size_t>{2, 4, 4}); pvt::fft fft_zero(cart_topo_idx); @@ -460,7 +460,7 @@ TEST_CASE("FftZero", "[FftZero]") //------------------------------------------------------------------------------ -TEST_CASE("FftClearDC", "[FftClearDC]") +TEST_CASE("FftClearDC", "[Fft]") { const pvt::cartesian_topology_index cart_topo_idx(std::vector<std::size_t>{2, 4, 4}); pvt::fft fft(cart_topo_idx); @@ -475,7 +475,7 @@ TEST_CASE("FftClearDC", "[FftClearDC]") //------------------------------------------------------------------------------ -TEST_CASE("FftStatistics", "[FftStatistics]") +TEST_CASE("FftStatistics", "[Fft]") { const pvt::cartesian_topology_index total_topo_idx( std::vector<size_t>{8, 28, 8, 8, 2, 16, 4}); @@ -491,3 +491,221 @@ TEST_CASE("FftStatistics", "[FftStatistics]") do_check(data, CTI(std::vector<size_t>{28, 8, 8, 2, 16, 4}) , "6D"); do_check(data, CTI(std::vector<size_t>{8, 28, 8, 8, 2, 16, 4}), "7D"); } + +//------------------------------------------------------------------------------ +TEST_CASE("Fft::convert_to_dc_centered_frequency", "[Fft]") +{ + const pvt::cartesian_topology_index topo_idx( + std::vector<size_t>{8, 28, 8, 8, 2, 16, 4}); + + pvt::fft spectrum(topo_idx); + + std::vector<int> frequency(7, 0); + + SECTION("128") + { + const std::size_t freq_index = 128; + spectrum.convert_to_frequency(freq_index, frequency); + REQUIRE(frequency[0] == 0); + REQUIRE(frequency[1] == 0); + REQUIRE(frequency[2] == 0); + REQUIRE(frequency[3] == 1); + REQUIRE(frequency[4] == 0); + REQUIRE(frequency[5] == 10); + REQUIRE(frequency[6] == 2); + spectrum.convert_to_dc_centered_frequency(freq_index, frequency); + CHECK(frequency[0] == 0); + CHECK(frequency[1] == 0); + CHECK(frequency[2] == 0); + CHECK(frequency[3] == 1); + CHECK(frequency[4] == 0); + CHECK(frequency[5] == -6); + CHECK(frequency[6] == 2); + } + + SECTION("218123") + { + const std::size_t freq_index = 218123; + spectrum.convert_to_frequency(218123, frequency); + REQUIRE(frequency[0] == 1); + REQUIRE(frequency[1] == 7); + REQUIRE(frequency[2] == 4); + REQUIRE(frequency[3] == 0); + REQUIRE(frequency[4] == 0); + REQUIRE(frequency[5] == 3); + REQUIRE(frequency[6] == 2); + spectrum.convert_to_dc_centered_frequency(freq_index, frequency); + CHECK(frequency[0] == 1); + CHECK(frequency[1] == 7); + CHECK(frequency[2] == 4); + CHECK(frequency[3] == 0); + CHECK(frequency[4] == 0); + CHECK(frequency[5] == 3); + CHECK(frequency[6] == 2); + } +} + + +//------------------------------------------------------------------------------ +TEST_CASE("Fft::is_on_boundary", "[Fft]") +{ + SECTION("Even size") + { + const pvt::cartesian_topology_index topo_idx( + std::vector<size_t>{8, 28, 8, 8, 2, 16, 4}); + pvt::fft spectrum(topo_idx); + + std::vector<std::size_t> frequency(7, 0); + for (std::size_t i = 0; i < spectrum.get_num_data(); ++i) + { + spectrum.convert_to_frequency(i, frequency); + if (frequency.back() == 0 || frequency.back() == 2) + { + SCOPED_INFO(frequency.back()); + REQUIRE(spectrum.is_on_boundary(frequency)); + } + else + { + SCOPED_INFO(frequency.back()); + REQUIRE_FALSE(spectrum.is_on_boundary(frequency)); + } + + spectrum.convert_to_dc_centered_frequency(i, frequency); + if (frequency.back() == 0 || frequency.back() == 2) + { + SCOPED_INFO(frequency.back()); + REQUIRE(spectrum.is_on_boundary(frequency)); + } + else + { + SCOPED_INFO(frequency.back()); + REQUIRE_FALSE(spectrum.is_on_boundary(frequency)); + } + } + } + + SECTION("Odd Size") + { + const pvt::cartesian_topology_index topo_idx( + std::vector<size_t>{4, 5}); + + pvt::fft spectrum(topo_idx); + + std::vector<std::size_t> frequency(7, 0); + for (std::size_t i = 0; i < spectrum.get_num_data(); ++i) + { + spectrum.convert_to_frequency(i, frequency); + SCOPED_INFO(frequency.back()); + if (frequency.back() == 0) + { + REQUIRE(spectrum.is_on_boundary(frequency)); + } + else + { + REQUIRE_FALSE(spectrum.is_on_boundary(frequency)); + } + + spectrum.convert_to_dc_centered_frequency(i, frequency); + if (frequency.back() == 0) + { + SCOPED_INFO(frequency.back()); + REQUIRE(spectrum.is_on_boundary(frequency)); + } + else + { + SCOPED_INFO(frequency.back()); + REQUIRE_FALSE(spectrum.is_on_boundary(frequency)); + } + } + } + + SECTION("8*28*8*8*2*16*4") + { + const std::vector<size_t> dim_sizes{8, 28, 8, 8, 2, 16, 4}; + const pvt::cartesian_topology_index topo_idx(dim_sizes); + pvt::fft spectrum(topo_idx); + for (std::size_t a = 0; a < dim_sizes[0]; ++a) + { + for (std::size_t b = 0; b < dim_sizes[1]; ++b) + { + for (std::size_t c = 0; c < dim_sizes[2]; ++c) + { + for (std::size_t d = 0; d < dim_sizes[3]; ++d) + { + for (std::size_t e = 0; e < dim_sizes[4]; ++e) + { + for (std::size_t core = 0; core < dim_sizes[5]; ++core) + { + CHECK (spectrum.is_on_boundary(std::vector<std::size_t>{a,b,c,d,e,core,0})); + CHECK_FALSE(spectrum.is_on_boundary(std::vector<std::size_t>{a,b,c,d,e,core,1})); + CHECK (spectrum.is_on_boundary(std::vector<std::size_t>{a,b,c,d,e,core,2})); + } + } + } + } + } + } + } +} + + +//------------------------------------------------------------------------------ +TEST_CASE("Fft::get_frequency_norm_squared", "[Fft]") +{ + const pvt::cartesian_topology_index topo_idx(std::vector<std::size_t>{2, 4, 4}); + pvt::fft spectrum(topo_idx); + + + std::vector<double> frequency(3, 0); + for (std::size_t i = 0; i < spectrum.get_num_data(); ++i) + { + spectrum.convert_to_dc_centered_frequency(i, frequency); + const double norm = spectrum.get_frequency_norm_squared(frequency); + SCOPED_INFO(frequency[0] << " " << frequency[1] << " " << frequency[2]); + REQUIRE(norm == Approx(frequency[0] * frequency[0] + frequency[1] * frequency[1] + frequency[2] * frequency[2])); + } +} + + +//------------------------------------------------------------------------------ +TEST_CASE("Fft::get_frequency_norm", "[Fft]") +{ + const pvt::cartesian_topology_index topo_idx(std::vector<std::size_t>{2, 4, 4}); + pvt::fft spectrum(topo_idx); + + + std::vector<double> frequency(3, 0); + for (std::size_t i = 0; i < spectrum.get_num_data(); ++i) + { + spectrum.convert_to_dc_centered_frequency(i, frequency); + const double norm = spectrum.get_frequency_norm(frequency); + SCOPED_INFO(frequency[0] << " " << frequency[1] << " " << frequency[2]); + REQUIRE(norm == Approx(sqrt(frequency[0] * frequency[0] + frequency[1] * frequency[1] + frequency[2] * frequency[2]))); + } +} + + +//------------------------------------------------------------------------------ +TEST_CASE("Fft::get_spectral_energy", "[Fft]") +{ + const pvt::cartesian_topology_index topo_idx(std::vector<std::size_t>{4, 4}); + pvt::fft spectrum(topo_idx); + + const double spect_dat[] = { + 18,31,12,27,29,20,11,26,3,23,24,4,16,13,32,15,22,7,25,10,21,1,28,9 + }; + + for (std::size_t i = 0; i < spectrum.get_num_data(); ++i) + { + spectrum.real(i) = 16.0 * spect_dat[2 * i + 0]; + spectrum.imag(i) = 16.0 * spect_dat[2 * i + 1]; + } + + for (std::size_t i = 0; i < spectrum.get_num_data(); ++i) + { + CHECK(spectrum.get_spectral_energy(i) == Approx(spect_dat[2 * i + 0] * + spect_dat[2 * i + 0] + + spect_dat[2 * i + 1] * + spect_dat[2 * i + 1])); + } +} \ No newline at end of file diff --git a/pvt/tests/src/suitable_3d_view_computer_test.cpp b/pvt/tests/src/suitable_3d_view_computer_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19a50fa78b65b11700794ba36368db402742d4b3 --- /dev/null +++ b/pvt/tests/src/suitable_3d_view_computer_test.cpp @@ -0,0 +1,174 @@ +//============================================================================== +// perfLib performance visualisation library +// +// Copyright (c) 2014-2016 RWTH Aachen University, Germany, +// Virtual Reality & Immersive Visualisation Group. +//============================================================================== +// License +// +// This library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// In the future, we may decide to add a commercial license +// at our own discretion without further notice. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//============================================================================== + +#include <catch/catch.hpp> + +#include <pvt/directed_variance.hpp> +#include <pvt/suitable_3d_view_computer.hpp> + + +//------------------------------------------------------------------------------ +TEST_CASE( + "suitable_3d_view_computer::is_suitable_3d_view(const directed_variance&)", + "[Suitable3DComputer]") +{ + pvt::suitable_3d_view_computer s3dvc(3); + + pvt::directed_variance dir_var(3); + dir_var[0] = 0.01; + + SECTION("Threshold = 0.08"){ + s3dvc.set_threshold(0.08); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 0.75)); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.25)); + } + SECTION("Threshold = 0.1"){ + s3dvc.set_threshold(0.1); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 0.75)); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + CHECK_FALSE(s3dvc.is_suitable_3d_view(dir_var, 1.25)); + } + SECTION("Threshold = 0.125"){ + s3dvc.set_threshold(0.125); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 0.75)); + CHECK_FALSE(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + CHECK_FALSE(s3dvc.is_suitable_3d_view(dir_var, 1.25)); + } +} + + +//------------------------------------------------------------------------------ +TEST_CASE( + "suitable_3d_view_computer::set_filter_dimension_enabled(std::size_t, bool)", + "[Suitable3DComputer]") +{ + pvt::suitable_3d_view_computer s3dvc(3); + + pvt::directed_variance dir_var(3); + dir_var[0] = 0.005; + dir_var[1] = 0.005; + dir_var[2] = 1.0; + + s3dvc.set_threshold(0.1); + + SECTION("filter enabled: 0 0 0"){ + s3dvc.set_filter_dimension_enabled(0, false); + s3dvc.set_filter_dimension_enabled(1, false); + s3dvc.set_filter_dimension_enabled(2, false); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 0 0 1"){ + s3dvc.set_filter_dimension_enabled(0, false); + s3dvc.set_filter_dimension_enabled(1, false); + s3dvc.set_filter_dimension_enabled(2, true); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 0 1 0"){ + s3dvc.set_filter_dimension_enabled(0, false); + s3dvc.set_filter_dimension_enabled(1, true); + s3dvc.set_filter_dimension_enabled(2, false); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 0 1 1"){ + s3dvc.set_filter_dimension_enabled(0, false); + s3dvc.set_filter_dimension_enabled(1, true); + s3dvc.set_filter_dimension_enabled(2, true); + CHECK_FALSE(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 1 0 0"){ + s3dvc.set_filter_dimension_enabled(0, true); + s3dvc.set_filter_dimension_enabled(1, false); + s3dvc.set_filter_dimension_enabled(2, false); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 1 0 1"){ + s3dvc.set_filter_dimension_enabled(0, true); + s3dvc.set_filter_dimension_enabled(1, false); + s3dvc.set_filter_dimension_enabled(2, true); + CHECK_FALSE(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 1 1 0"){ + s3dvc.set_filter_dimension_enabled(0, true); + s3dvc.set_filter_dimension_enabled(1, true); + s3dvc.set_filter_dimension_enabled(2, false); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 1 1 1"){ + s3dvc.set_filter_dimension_enabled(0, true); + s3dvc.set_filter_dimension_enabled(1, true); + s3dvc.set_filter_dimension_enabled(2, true); + CHECK_FALSE(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } +} + + +//------------------------------------------------------------------------------ +TEST_CASE( + "suitable_3d_view_computer::set_filter_dimension_enabled(const std::vector<bool>&)", + "[Suitable3DComputer]") +{ + pvt::suitable_3d_view_computer s3dvc(3); + + pvt::directed_variance dir_var(3); + dir_var[0] = 0.005; + dir_var[1] = 0.005; + dir_var[2] = 1.0; + + s3dvc.set_threshold(0.1); + + SECTION("filter enabled: 0 0 0"){ + s3dvc.set_filter_dimension_enabled(std::vector<bool>{false, false, false}); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 0 0 1"){ + s3dvc.set_filter_dimension_enabled(std::vector<bool>{false, false, true}); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 0 1 0"){ + s3dvc.set_filter_dimension_enabled(std::vector<bool>{false, true, false}); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 0 1 1"){ + s3dvc.set_filter_dimension_enabled(std::vector<bool>{false, true, true}); + CHECK_FALSE(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 1 0 0"){ + s3dvc.set_filter_dimension_enabled(std::vector<bool>{true, false, false}); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 1 0 1"){ + s3dvc.set_filter_dimension_enabled(std::vector<bool>{true, false, true}); + CHECK_FALSE(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 1 1 0"){ + s3dvc.set_filter_dimension_enabled(std::vector<bool>{true, true, false}); + CHECK(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } + SECTION("filter enabled: 1 1 1"){ + s3dvc.set_filter_dimension_enabled(std::vector<bool>{true, true, true}); + CHECK_FALSE(s3dvc.is_suitable_3d_view(dir_var, 1.0)); + } +} \ No newline at end of file diff --git a/qpvt/_SourceFiles.cmake b/qpvt/_SourceFiles.cmake index 100048cc9fd609fe3964d2d37e18c15b4359cfa8..71e70624f65581e17438988b60568dd23cd067b4 100644 --- a/qpvt/_SourceFiles.cmake +++ b/qpvt/_SourceFiles.cmake @@ -26,7 +26,7 @@ set(SourceFiles include/qpvt/api.hpp - include/qpvt/delegates/directed_variation_glyph_delegate.hpp + include/qpvt/delegates/directed_variance_glyph_delegate.hpp include/qpvt/delegates/severity_glyph_delegate.hpp include/qpvt/models/cnode_impact_list_model.hpp @@ -51,7 +51,7 @@ set(SourceFiles include/qpvt/widgets/squarified_cushion_treemap_widget.hpp include/qpvt/widgets/viewer_widget.hpp - src/delegates/directed_variation_glyph_delegate.cpp + src/delegates/directed_variance_glyph_delegate.cpp src/delegates/severity_glyph_delegate.cpp src/models/cnode_impact_list_model.cpp diff --git a/qpvt/include/qpvt/delegates/directed_variation_glyph_delegate.hpp b/qpvt/include/qpvt/delegates/directed_variance_glyph_delegate.hpp similarity index 80% rename from qpvt/include/qpvt/delegates/directed_variation_glyph_delegate.hpp rename to qpvt/include/qpvt/delegates/directed_variance_glyph_delegate.hpp index ddf1e1fe31dc2e5c6dc9800d0d879b783031eab6..0d15a1ed35adfaafbeb398849884f4b40fb66a70 100644 --- a/qpvt/include/qpvt/delegates/directed_variation_glyph_delegate.hpp +++ b/qpvt/include/qpvt/delegates/directed_variance_glyph_delegate.hpp @@ -23,22 +23,28 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. //------------------------------------------------------------------------------ -#ifndef QPVT_DIRECTED_VARIATION_GLYPH_DELEGATE_HPP_ -#define QPVT_DIRECTED_VARIATION_GLYPH_DELEGATE_HPP_ +#ifndef QPVT_DIRECTED_VARIANCE_GLYPH_DELEGATE_HPP_ +#define QPVT_DIRECTED_VARIANCE_GLYPH_DELEGATE_HPP_ #include <QAbstractItemDelegate> #include <qpvt/api.hpp> +namespace pvt { + class perf_data; +} + namespace qpvt { //------------------------------------------------------------------------------ -class QPVT_API directed_variation_glyph_delegate : public QAbstractItemDelegate +class QPVT_API directed_variance_glyph_delegate : public QAbstractItemDelegate { Q_OBJECT public: - directed_variation_glyph_delegate(QObject* p_parent = nullptr); + directed_variance_glyph_delegate( + pvt::perf_data* p_perf_data, + QObject* p_parent = nullptr); void paint (QPainter* p_painter, const QStyleOptionViewItem& option, @@ -56,9 +62,10 @@ public: } private: - bool m_fade_out_enabled = true; + pvt::perf_data* mp_perf_data; + bool m_fade_out_enabled = true; }; } // namespace qpvt -#endif // #ifndef QPVT_DIRECTED_VARIATION_GLYPH_DELEGATE_HPP_ +#endif // #ifndef QPVT_DIRECTED_VARIANCE_GLYPH_DELEGATE_HPP_ diff --git a/qpvt/include/qpvt/models/cnode_tree_model.hpp b/qpvt/include/qpvt/models/cnode_tree_model.hpp index 6f32d1a4857ba5b34420d1db90bf4305f2cce469..646d4ada9b38b76ee3b3c25e445a505db3f67ebe 100644 --- a/qpvt/include/qpvt/models/cnode_tree_model.hpp +++ b/qpvt/include/qpvt/models/cnode_tree_model.hpp @@ -44,6 +44,11 @@ class QPVT_API cnode_tree_model : public perf_data_tree_model<pvt::cnode> Q_OBJECT public: + enum cnode_tree_model_roles + { + suitable_view_threshold_role = last_user_role + }; + cnode_tree_model(const pvt::severity_view* p_severity_view, QObject* p_parent = nullptr); diff --git a/qpvt/include/qpvt/models/perf_data_tree_model.hpp b/qpvt/include/qpvt/models/perf_data_tree_model.hpp index 344ecbea694ef7bd699f54381a93d92e3286eedb..9e7f0d90f902019c0de5034af765babc4d172223 100644 --- a/qpvt/include/qpvt/models/perf_data_tree_model.hpp +++ b/qpvt/include/qpvt/models/perf_data_tree_model.hpp @@ -57,11 +57,13 @@ public: search_perf_data_item_role = Qt::UserRole, get_perf_data_item_pointer_role, sort_role, + get_severity_role, get_severity_total_role, get_severity_self_role, get_relative_severity_role, using_total_severities_role, - directed_variance_role + directed_variance_role, + last_user_role }; perf_data_tree_model (const pvt::severity_view* p_severity_view, diff --git a/qpvt/include/qpvt/widgets/perf_data_viewer_widget.hpp b/qpvt/include/qpvt/widgets/perf_data_viewer_widget.hpp index ab73e7428678f807f51063f69b24ea32d89e6188..fc7e9b544f0b5dbb4b9d7de57e65412683e71a8d 100644 --- a/qpvt/include/qpvt/widgets/perf_data_viewer_widget.hpp +++ b/qpvt/include/qpvt/widgets/perf_data_viewer_widget.hpp @@ -56,7 +56,7 @@ namespace qpvt { class cnode_impact_selector_widget; class cnode_tree_model; class correlated_views_model; -class directed_variation_glyph_delegate; +class directed_variance_glyph_delegate; class metric_tree_model; class viewer_widget; @@ -129,7 +129,7 @@ private slots: void filter_ok_clicked (bool checked); void filter_cancel_clicked (bool checked); void set_threshold_suitable_3d_view_clicked(bool checked); - void fade_out_directed_variation_clicked (bool checked); + void fade_out_directed_variance_clicked (bool checked); private: void setup_ui(); @@ -156,7 +156,7 @@ private: cartesian_topology_viewer_widget* mp_cartesian_topology_viewer_widget = nullptr; geometry_viewer_widget* mp_geometry_viewer_widget = nullptr; squarified_cushion_treemap_widget* mp_squarified_cushion_treemap_widget = nullptr; - directed_variation_glyph_delegate* mp_directed_variation_glyph_delegate = nullptr; + directed_variance_glyph_delegate* mp_directed_variance_glyph_delegate = nullptr; QTableView* mp_correlation_table_view = nullptr; QTreeView* mp_cnodes_view = nullptr; diff --git a/qpvt/src/delegates/directed_variation_glyph_delegate.cpp b/qpvt/src/delegates/directed_variance_glyph_delegate.cpp similarity index 69% rename from qpvt/src/delegates/directed_variation_glyph_delegate.cpp rename to qpvt/src/delegates/directed_variance_glyph_delegate.cpp index d64e6abe5efb2819bea69dde2e48a462c9c3ca4d..a2c638712eaa420e1bf76c1c651c5a8dfab5c623 100644 --- a/qpvt/src/delegates/directed_variation_glyph_delegate.cpp +++ b/qpvt/src/delegates/directed_variance_glyph_delegate.cpp @@ -27,15 +27,17 @@ #include <QPainter> -#include <qpvt/delegates/directed_variation_glyph_delegate.hpp> +#include <qpvt/delegates/directed_variance_glyph_delegate.hpp> #include <qpvt/models/cnode_tree_model.hpp> namespace qpvt { //------------------------------------------------------------------------------ -directed_variation_glyph_delegate::directed_variation_glyph_delegate -(QObject* p_parent) -: QAbstractItemDelegate(p_parent) +directed_variance_glyph_delegate::directed_variance_glyph_delegate +(pvt::perf_data* p_perf_data, + QObject* p_parent ) +: QAbstractItemDelegate(p_parent ) +, mp_perf_data (p_perf_data) { } @@ -43,7 +45,7 @@ directed_variation_glyph_delegate::directed_variation_glyph_delegate //------------------------------------------------------------------------------ void -directed_variation_glyph_delegate::paint +directed_variance_glyph_delegate::paint (QPainter* p_painter, const QStyleOptionViewItem& option, const QModelIndex& index) @@ -57,11 +59,16 @@ const const QColor baseline_color(255 - 64, 255 - 64, 255 - 64); const QColor bar_color (255 - 64, 255 - 64, 255 - 64); - const QList<QVariant> directed_variations( + const QList<QVariant> directed_variances( index.data(cnode_tree_model::directed_variance_role).toList()); - const std::size_t num_dims = directed_variations.size(); + const std::size_t num_dims = directed_variances.size(); + const double severity = + index.data(cnode_tree_model::get_severity_role).toDouble(); + const double mean_severity = + severity / static_cast<double>(mp_perf_data->get_data_size()); + const double relative_severity = index.data(cnode_tree_model::get_relative_severity_role).toDouble(); @@ -69,6 +76,13 @@ const const double scaled_relative_severity = std::max(0.0, std::min(1.0, (relative_severity - 0.001) / 0.009)); + const double suitable_3d_view_threshold = + index.data(cnode_tree_model::suitable_view_threshold_role).toDouble(); + + const double center_value = + suitable_3d_view_threshold * suitable_3d_view_threshold * + mean_severity * mean_severity; + p_painter->save(); // Clear painting area. @@ -92,28 +106,32 @@ const double max_dir_var = 1.0; for (std::size_t i = 0; i < num_dims; ++i) - max_dir_var = std::max(max_dir_var, directed_variations[i].toDouble()); + max_dir_var = std::max(max_dir_var, directed_variances[i].toDouble()); for (std::size_t i = 0; i < num_dims; ++i) { - const double curr_dir_var = directed_variations[i].toDouble(); - const double clamped_dir_var = std::max(0.0, curr_dir_var); - const double log_dir_var = - log(clamped_dir_var / max_dir_var) / log(10.0); - const double clamped_log_dir_var = - std::max(0.0, std::min(1.0, (log_dir_var + 3.0) / 3.0)); - - const double mapped_dir_var = (clamped_log_dir_var - 0.001) / 0.999; - const double clamped_mapped_dir_var = - std::max(0.0, std::min(1.0, mapped_dir_var)); - + const double curr_dir_var = directed_variances[i].toDouble(); + + const double norm_curr_dir_var = + std::min(curr_dir_var / (2.0 * center_value), 1.0); + const int max_height = height - 2; - const int bar_height = clamped_mapped_dir_var * max_height; + const int bar_height = norm_curr_dir_var * max_height; p_painter->drawRect(left + i * height + 1, top + 1 + max_height - bar_height, height - 2, bar_height); + + p_painter->drawLine(left + i * height, + top + 1 + max_height / 2, + left + i * height + 1, + top + 1 + max_height / 2); + + p_painter->drawLine(left + i * height + height - 2, + top + 1 + max_height / 2, + left + i * height + height - 1, + top + 1 + max_height / 2); } p_painter->restore(); @@ -122,7 +140,7 @@ const //------------------------------------------------------------------------------ QSize -directed_variation_glyph_delegate::sizeHint +directed_variance_glyph_delegate::sizeHint (const QStyleOptionViewItem& option, const QModelIndex& index) const diff --git a/qpvt/src/models/cnode_impact_list_model.cpp b/qpvt/src/models/cnode_impact_list_model.cpp index 8f93dd3efda416b8655e34665e9ba1ab102919bd..ffb148876301260a063404116a81c1015a09dc03 100644 --- a/qpvt/src/models/cnode_impact_list_model.cpp +++ b/qpvt/src/models/cnode_impact_list_model.cpp @@ -28,7 +28,7 @@ #include <pvt/cartesian_topology.hpp> #include <pvt/cartesian_topology_index.hpp> #include <pvt/cnode.hpp> -#include <pvt/directed_variation.hpp> +#include <pvt/directed_variance.hpp> #include <pvt/fft_statistics.hpp> #include <pvt/perf_data.hpp> #include <pvt/severity_view.hpp> @@ -280,8 +280,8 @@ const const auto& cart_topo_idx = mp_perf_data->get_cartesian_topologies()[0]; const auto& num_dims = cart_topo_idx.get_num_dimensions (); - pvt::directed_variation dir_var(num_dims); - mp_perf_data->get_directed_variation(severity_view, dir_var); + pvt::directed_variance dir_var(num_dims); + mp_perf_data->get_directed_variance(severity_view, dir_var); pvt::suitable_3d_view_computer suitable_3d_view_computer(num_dims); suitable_3d_view_computer.set_filter_dimension_enabled( @@ -289,7 +289,9 @@ const suitable_3d_view_computer.set_threshold( mp_suitable_3d_view_computer->get_threshold()); - const bool suitable = suitable_3d_view_computer.is_suitable_3d_view(dir_var); + const bool suitable = suitable_3d_view_computer.is_suitable_3d_view( + dir_var, + mp_perf_data->get_mean(severity_view)); return suitable ? QVariant("~") : QVariant(); } else @@ -308,10 +310,10 @@ const const std::size_t dim_id = index.column() - 4; - pvt::directed_variation dir_var(num_dims); - mp_perf_data->get_directed_variation(severity_view, dir_var); + pvt::directed_variance dir_var(num_dims); + mp_perf_data->get_directed_variance(severity_view, dir_var); - return format_number(dir_var[dim_id] * dir_var.get_mean()); + return format_number(sqrt(dir_var[dim_id])); } else return QVariant(); @@ -367,14 +369,16 @@ const const auto& cart_topo = mp_perf_data->get_cartesian_topologies()[0]; const auto& num_dims = cart_topo.get_num_dimensions(); - pvt::directed_variation dir_var(num_dims); - mp_perf_data->get_directed_variation(severity_view, dir_var); + pvt::directed_variance dir_var(num_dims); + mp_perf_data->get_directed_variance(severity_view, dir_var); pvt::suitable_3d_view_computer suitable_3d_view_computer(num_dims); suitable_3d_view_computer.set_filter_dimension_enabled( m_exclude_dimensions_from_std_dev); - const bool suitable = suitable_3d_view_computer.is_suitable_3d_view(dir_var); + const bool suitable = suitable_3d_view_computer.is_suitable_3d_view( + dir_var, + mp_perf_data->get_mean(severity_view)); return suitable ? QVariant("~") : QVariant(); } else @@ -393,10 +397,10 @@ const const std::size_t dim_id = index.column() - 4; - pvt::directed_variation dir_var(num_dims); - mp_perf_data->get_directed_variation(severity_view, dir_var); + pvt::directed_variance dir_var(num_dims); + mp_perf_data->get_directed_variance(severity_view, dir_var); - return dir_var[dim_id] * dir_var.get_mean(); + return sqrt(dir_var[dim_id]); } else return QVariant(); @@ -418,19 +422,21 @@ const { const std::size_t num_dims = m_exclude_dimensions_from_std_dev.size(); - pvt::directed_variation dir_var(num_dims); - mp_perf_data->get_directed_variation(p_severity_view, dir_var); + pvt::directed_variance dir_var(num_dims); + mp_perf_data->get_directed_variance(p_severity_view, dir_var); - double variance = mp_perf_data->get_variance(p_severity_view); - for (std::size_t dim_id = 0; dim_id < num_dims; ++dim_id) + const double filtered_variance = + std::inner_product(dir_var.begin(), + dir_var.end (), + m_exclude_dimensions_from_std_dev.begin(), + 0.0, + std::plus<double>(), + [](double dv, bool f) { - const double filter = - static_cast<double>(m_exclude_dimensions_from_std_dev[dim_id]) * - dir_var.at(dim_id) * dir_var.at(dim_id) * dir_var.get_mean() * dir_var.get_mean(); - variance -= filter; - } + return dv * static_cast<double>(!f); + }); - return sqrt(variance); + return sqrt(filtered_variance); } } // namespace qpvt diff --git a/qpvt/src/models/cnode_tree_model.cpp b/qpvt/src/models/cnode_tree_model.cpp index d3ed660d7f674eed74dcdfd51e4ce7c4a3286925..0b9fee1c7bd6e8474457ac64adfb3b7129668aa5 100644 --- a/qpvt/src/models/cnode_tree_model.cpp +++ b/qpvt/src/models/cnode_tree_model.cpp @@ -104,6 +104,12 @@ const case cnode_tree_model::get_perf_data_item_pointer_role: return QVariant::fromValue(index.internalPointer()); + case cnode_tree_model::get_severity_role: + return QVariant::fromValue( + index.data(cnode_tree_model::using_total_severities_role).toBool() ? + m_perf_data_cache.get_severity_total(p_cnode) : + m_perf_data_cache.get_severity_self (p_cnode)); + case cnode_tree_model::get_severity_total_role: return QVariant::fromValue(m_perf_data_cache.get_severity_total(p_cnode)); @@ -121,6 +127,9 @@ const case cnode_tree_model::directed_variance_role: return get_directed_variance_as_qvariant(p_cnode); + + case cnode_tree_model::suitable_view_threshold_role: + return m_perf_data_cache.get_suitable_3d_view_computer().get_threshold(); } return QVariant(); }; @@ -133,12 +142,12 @@ cnode_tree_model::get_directed_variance_as_qvariant const { QList<QVariant> directed_variances; - std::for_each(m_perf_data_cache.get_directed_variation(p_cnode).begin(), - m_perf_data_cache.get_directed_variation(p_cnode).end (), - [&directed_variances](double variance) - { - directed_variances.append(QVariant::fromValue(variance)); - }); + std::for_each(m_perf_data_cache.get_directed_variance(p_cnode).begin(), + m_perf_data_cache.get_directed_variance(p_cnode).end (), + [&directed_variances](double variance) + { + directed_variances.append(QVariant::fromValue(variance)); + }); return directed_variances; } diff --git a/qpvt/src/widgets/perf_data_viewer_widget.cpp b/qpvt/src/widgets/perf_data_viewer_widget.cpp index 44b9c9d7d7f79d72b733dc343c368da49c1f1811..49e5fe33039a5e4f6c7178734cd4a88a663ef5c5 100644 --- a/qpvt/src/widgets/perf_data_viewer_widget.cpp +++ b/qpvt/src/widgets/perf_data_viewer_widget.cpp @@ -37,7 +37,7 @@ #include <pvt/perf_data.hpp> #include <pvt/suitable_3d_view_computer.hpp> -#include <qpvt/delegates/directed_variation_glyph_delegate.hpp> +#include <qpvt/delegates/directed_variance_glyph_delegate.hpp> #include <qpvt/delegates/severity_glyph_delegate.hpp> #include <qpvt/models/cnode_tree_model.hpp> #include <qpvt/models/correlated_views_model.hpp> @@ -409,10 +409,10 @@ perf_data_viewer_widget::set_threshold_suitable_3d_view_clicked //------------------------------------------------------------------------------ void -perf_data_viewer_widget::fade_out_directed_variation_clicked +perf_data_viewer_widget::fade_out_directed_variance_clicked (bool checked) { - mp_directed_variation_glyph_delegate->set_fade_out_enabled(checked); + mp_directed_variance_glyph_delegate->set_fade_out_enabled(checked); mp_cnode_tree_model->set_dirty(); mp_cnode_tree_model_sort_proxy->invalidate(); } @@ -508,10 +508,10 @@ perf_data_viewer_widget::setup_ui mp_cnodes_view->sortByColumn (4, Qt::DescendingOrder); mp_cnodes_view->setItemDelegateForColumn(1, new severity_glyph_delegate(mp_cnodes_view)); - mp_directed_variation_glyph_delegate = - new directed_variation_glyph_delegate(mp_cnodes_view); + mp_directed_variance_glyph_delegate = + new directed_variance_glyph_delegate(mp_perf_data, mp_cnodes_view); mp_cnodes_view->setItemDelegateForColumn(3, - mp_directed_variation_glyph_delegate); + mp_directed_variance_glyph_delegate); mp_cnodes_view->header()->moveSection(0, 6); mp_cnodes_view->setAlternatingRowColors(true); @@ -686,16 +686,16 @@ perf_data_viewer_widget::setup_ui mp_cnodes_view->header()->hideSection(6); } - QAction* p_fade_out_directed_variation_action = + QAction* p_fade_out_directed_variance_action = new QAction("Fade out directed variation", mp_cnodes_view); - p_fade_out_directed_variation_action->setCheckable(true); - p_fade_out_directed_variation_action->setChecked( - mp_directed_variation_glyph_delegate->get_fade_out_enabled()); - mp_cnodes_view->addAction(p_fade_out_directed_variation_action); - QObject::connect(p_fade_out_directed_variation_action, + p_fade_out_directed_variance_action->setCheckable(true); + p_fade_out_directed_variance_action->setChecked( + mp_directed_variance_glyph_delegate->get_fade_out_enabled()); + mp_cnodes_view->addAction(p_fade_out_directed_variance_action); + QObject::connect(p_fade_out_directed_variance_action, &QAction::triggered, this, - &perf_data_viewer_widget::fade_out_directed_variation_clicked); + &perf_data_viewer_widget::fade_out_directed_variance_clicked); }