Merge topic 'add_statistics_filter'

58acf3a43 add statistics filter

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !2957
This commit is contained in:
Zhe Wang 2023-02-02 03:32:12 +00:00 committed by Kitware Robot
commit 2d8b3ef33f
8 changed files with 295 additions and 2 deletions

@ -0,0 +1,3 @@
# New Statistics filter
The statistics filter computes the descriptive statistics of the fields specified by users based on `DescriptiveStatistics`. Users can set `RequiredStatsList` to specify which statistics will be stored in the output data set.

@ -15,6 +15,7 @@ set(density_estimate_headers
ParticleDensityBase.h
ParticleDensityCloudInCell.h
ParticleDensityNearestGridPoint.h
Statistics.h
)
set(density_estimate_sources_device
@ -25,6 +26,7 @@ set(density_estimate_sources_device
ParticleDensityBase.cxx
ParticleDensityCloudInCell.cxx
ParticleDensityNearestGridPoint.cxx
Statistics.cxx
)
vtkm_library(

@ -0,0 +1,114 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/ErrorFilterExecution.h>
#include <vtkm/filter/density_estimate/Statistics.h>
#include <vtkm/worklet/DescriptiveStatistics.h>
namespace vtkm
{
namespace filter
{
namespace density_estimate
{
VTKM_CONT vtkm::cont::DataSet Statistics::DoExecute(const vtkm::cont::DataSet& inData)
{
vtkm::worklet::DescriptiveStatistics worklet;
vtkm::cont::DataSet output;
auto resolveType = [&](const auto& concrete) {
auto result = worklet.Run(concrete);
for (size_t i = 0; i < RequiredStatsList.size(); i++)
{
vtkm::cont::ArrayHandle<vtkm::FloatDefault> stat;
stat.Allocate(1);
Stats statEnum = RequiredStatsList[i];
switch (statEnum)
{
case Stats::N:
{
stat.WritePortal().Set(0, static_cast<vtkm::FloatDefault>(result.N()));
break;
}
case Stats::Min:
{
stat.WritePortal().Set(0, static_cast<vtkm::FloatDefault>(result.Min()));
break;
}
case Stats::Max:
{
stat.WritePortal().Set(0, static_cast<vtkm::FloatDefault>(result.Max()));
break;
}
case Stats::Sum:
{
stat.WritePortal().Set(0, static_cast<vtkm::FloatDefault>(result.Sum()));
break;
}
case Stats::Mean:
{
stat.WritePortal().Set(0, static_cast<vtkm::FloatDefault>(result.Mean()));
break;
}
case Stats::SampleStdDev:
{
stat.WritePortal().Set(0, static_cast<vtkm::FloatDefault>(result.SampleStddev()));
break;
}
case Stats::PopulationStdDev:
{
stat.WritePortal().Set(0, static_cast<vtkm::FloatDefault>(result.PopulationStddev()));
break;
}
case Stats::SampleVariance:
{
stat.WritePortal().Set(0, static_cast<vtkm::FloatDefault>(result.SampleVariance()));
break;
}
case Stats::PopulationVariance:
{
stat.WritePortal().Set(0, static_cast<vtkm::FloatDefault>(result.PopulationVariance()));
break;
}
case Stats::Skewness:
{
stat.WritePortal().Set(0, static_cast<vtkm::FloatDefault>(result.Skewness()));
break;
}
case Stats::Kurtosis:
{
stat.WritePortal().Set(0, static_cast<vtkm::FloatDefault>(result.Kurtosis()));
break;
}
default:
{
throw vtkm::cont::ErrorFilterExecution(
"Unsupported statistics variable in statistics filter.");
}
}
output.AddField({ this->StatsName[static_cast<int>(statEnum)],
vtkm::cont::Field::Association::WholeDataSet,
stat });
}
};
const auto& fieldArray = this->GetFieldFromDataSet(inData).GetData();
fieldArray
.CastAndCallForTypesWithFloatFallback<vtkm::TypeListFieldScalar, VTKM_DEFAULT_STORAGE_LIST>(
resolveType);
return output;
}
} // namespace density_estimate
} // namespace filter
} // namespace vtkm

@ -0,0 +1,81 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_density_estimate_Statistics_h
#define vtk_m_filter_density_estimate_Statistics_h
#include <vtkm/filter/FilterField.h>
#include <vtkm/filter/density_estimate/vtkm_filter_density_estimate_export.h>
namespace vtkm
{
namespace filter
{
namespace density_estimate
{
/// \brief Calculating the statistics of input fields
///
/// This filter calculates the statistics of input fields.
///
class VTKM_FILTER_DENSITY_ESTIMATE_EXPORT Statistics : public vtkm::filter::FilterField
{
public:
enum struct Stats
{
N = 0,
Min,
Max,
Sum,
Mean,
SampleStdDev,
PopulationStdDev,
SampleVariance,
PopulationVariance,
Skewness,
Kurtosis
};
/// \{
/// \brief The output statistical variables for executing the statistics filter.
///
void SetRequiredStats(const std::vector<Stats> StatsList) { RequiredStatsList = StatsList; }
const std::vector<Stats>& GetRequiredStats() const { return this->RequiredStatsList; }
/// \}
private:
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
std::vector<Stats> RequiredStatsList{ Stats::N,
Stats::Min,
Stats::Max,
Stats::Sum,
Stats::Mean,
Stats::SampleStdDev,
Stats::PopulationStdDev,
Stats::SampleVariance,
Stats::PopulationVariance,
Stats::Skewness,
Stats::Kurtosis };
// This string vector stores variables names stored in the output dataset
std::vector<std::string> StatsName{ "N",
"Min",
"Max",
"Sum",
"Mean",
"SampleStddev",
"PopulationStdDev",
"SampleVariance",
"PopulationVariance",
"Skewness",
"Kurtosis" };
};
} // namespace density_estimate
} // namespace filter
} // namespace vtkm
#endif //vtk_m_filter_density_estimate_Statistics_h

@ -14,6 +14,7 @@ set(unit_tests
UnitTestNDEntropyFilter.cxx
UnitTestNDHistogramFilter.cxx
UnitTestPartitionedDataSetHistogramFilter.cxx
UnitTestStatisticsFilter.cxx
)
set(unit_tests_device

@ -0,0 +1,86 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/filter/density_estimate/Statistics.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
vtkm::FloatDefault getStatsFromArray(vtkm::cont::DataSet dataset, const std::string statName)
{
vtkm::cont::ArrayHandle<vtkm::FloatDefault> array;
dataset.GetField(statName).GetData().AsArrayHandle(array);
vtkm::cont::ArrayHandle<vtkm::FloatDefault>::ReadPortalType portal = array.ReadPortal();
vtkm::FloatDefault value = portal.Get(0);
return value;
}
void TestStatisticsPartial()
{
vtkm::cont::DataSet dataSet;
constexpr vtkm::FloatDefault N = 1000;
// the number is from 0 to 999
auto scalaArray =
vtkm::cont::ArrayHandleCounting<vtkm::FloatDefault>(0.0f, 1.0f, static_cast<vtkm::Id>(N));
dataSet.AddPointField("scalarField", scalaArray);
using STATS = vtkm::filter::density_estimate::Statistics;
STATS statisticsFilter;
//set required states
std::vector<STATS::Stats> RequiredStatsList{ STATS::Stats::N, STATS::Stats::Sum,
STATS::Stats::Mean, STATS::Stats::SampleVariance,
STATS::Stats::Skewness, STATS::Stats::Kurtosis };
//default RequiredStatsList contains all statistics variables
statisticsFilter.SetRequiredStats(RequiredStatsList);
using AsscoType = vtkm::cont::Field::Association;
statisticsFilter.SetActiveField("scalarField", AsscoType::Points);
// We use the same test cases with the UnitTestDescriptiveStatistics.h
vtkm::cont::DataSet resultDataSet = statisticsFilter.Execute(dataSet);
vtkm::FloatDefault NValueFromFilter = getStatsFromArray(resultDataSet, "N");
VTKM_TEST_ASSERT(test_equal(NValueFromFilter, N));
vtkm::FloatDefault SumFromFilter = getStatsFromArray(resultDataSet, "Sum");
VTKM_TEST_ASSERT(test_equal(SumFromFilter, N * (N - 1) / 2));
vtkm::FloatDefault MeanFromFilter = getStatsFromArray(resultDataSet, "Mean");
VTKM_TEST_ASSERT(test_equal(MeanFromFilter, (N - 1) / 2));
vtkm::FloatDefault SVFromFilter = getStatsFromArray(resultDataSet, "SampleVariance");
VTKM_TEST_ASSERT(test_equal(SVFromFilter, 83416.66));
vtkm::FloatDefault SkewnessFromFilter = getStatsFromArray(resultDataSet, "Skewness");
VTKM_TEST_ASSERT(test_equal(SkewnessFromFilter, 0));
// we use fisher=False when computing the Kurtosis value
vtkm::FloatDefault KurtosisFromFilter = getStatsFromArray(resultDataSet, "Kurtosis");
VTKM_TEST_ASSERT(test_equal(KurtosisFromFilter, 1.8));
}
void TestStatistics()
{
TestStatisticsPartial();
} // TestFieldStatistics
}
//More deatiled tests can be found in the UnitTestStatisticsFilter
int UnitTestStatisticsFilter(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestStatistics, argc, argv);
}

@ -27,10 +27,9 @@ namespace vtkm
{
namespace worklet
{
//simple functor that prints basic statistics
template <typename FieldType>
class FieldStatistics
class VTKM_DEPRECATED(2.1, "Use DescriptiveStatistics or the statistics filter.") FieldStatistics
{
public:
// For moments readability

@ -283,6 +283,7 @@ vtkm::cont::DataSet Make2DUniformStatDataSet1()
//
// Create a dataset with known point data and cell data (statistical distributions)
//
VTKM_DEPRECATED_SUPPRESS_BEGIN
void PrintStatInfo(vtkm::worklet::FieldStatistics<vtkm::Float32>::StatInfo statinfo)
{
std::cout << " Median " << statinfo.median << std::endl;
@ -302,12 +303,14 @@ void PrintStatInfo(vtkm::worklet::FieldStatistics<vtkm::Float32>::StatInfo stati
std::cout << statinfo.centralMoment[i] << " ";
std::cout << "]" << std::endl;
}
VTKM_DEPRECATED_SUPPRESS_END
//
// Test simple dataset 2D Uniform with 10 cells
//
void TestFieldSimple()
{
VTKM_DEPRECATED_SUPPRESS_BEGIN
// Create the output structure
vtkm::worklet::FieldStatistics<vtkm::Float32>::StatInfo statinfo;
@ -332,6 +335,7 @@ void TestFieldSimple()
VTKM_TEST_ASSERT(test_equal(statinfo.stddev, expected[5]), "Error in stddev");
VTKM_TEST_ASSERT(test_equal(statinfo.skewness, expected[6]), "Error in skewness");
VTKM_TEST_ASSERT(test_equal(statinfo.kurtosis, expected[7]), "Error in kurtosis");
VTKM_DEPRECATED_SUPPRESS_END
}
//
@ -339,6 +343,7 @@ void TestFieldSimple()
//
void TestFieldStandardDistributions()
{
VTKM_DEPRECATED_SUPPRESS_BEGIN
// Create the output structure
vtkm::worklet::FieldStatistics<vtkm::Float32>::StatInfo statinfo;
@ -374,6 +379,8 @@ void TestFieldStandardDistributions()
vtkm::worklet::FieldStatistics<vtkm::Float32>().Run(p_uniform, statinfo);
std::cout << "Uniform distributed POINT data:" << std::endl;
PrintStatInfo(statinfo);
VTKM_DEPRECATED_SUPPRESS_END
} // TestFieldStatistics
void TestFieldStatistics()