//============================================================================ // 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. // // Copyright 2014 Sandia Corporation. // Copyright 2014 UT-Battelle, LLC. // Copyright 2014 Los Alamos National Security. // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // the U.S. Government retains certain rights in this software. // // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National // Laboratory (LANL), the U.S. Government retains certain rights in // this software. //============================================================================ #ifndef vtk_m_worklet_FieldHistogram_h #define vtk_m_worklet_FieldHistogram_h #include #include #include #include #include #include #include #ifndef VTKM_DEVICE_ADAPTER #define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL #endif typedef VTKM_DEFAULT_DEVICE_ADAPTER_TAG DeviceAdapter; namespace vtkm { namespace worklet { //simple functor that prints basic statistics template class FieldHistogram { public: struct minFunctor { VTKM_EXEC_EXPORT FieldType operator()(const FieldType &x, const FieldType &y) const { return Min(x, y); } }; struct maxFunctor { VTKM_EXEC_EXPORT FieldType operator()(const FieldType& x, const FieldType& y) const { return Max(x, y); } }; // For each value set the bin it should be in class SetHistogramBin : public vtkm::worklet::WorkletMapField { public: typedef void ControlSignature(FieldIn<> value, FieldOut<> binIndex); typedef void ExecutionSignature(_1,_2); typedef _1 InputDomain; vtkm::Id numberOfBins; FieldType minValue; FieldType delta; VTKM_CONT_EXPORT SetHistogramBin( vtkm::Id numberOfBins0, FieldType minValue0, FieldType delta0) : numberOfBins(numberOfBins0), minValue(minValue0), delta(delta0) {} VTKM_EXEC_EXPORT void operator()(const FieldType &value, vtkm::Id &binIndex) const { binIndex = static_cast((value - minValue) / delta); if (binIndex < 0) binIndex = 0; if (binIndex >= numberOfBins) binIndex = numberOfBins - 1; } }; // Calculate the adjacent difference between values in ArrayHandle class AdjacentDifference : public vtkm::worklet::WorkletMapField { public: typedef void ControlSignature(FieldIn inputIndex, FieldOut outputCount); typedef void ExecutionSignature(_1,_2); typedef _1 InputDomain; typedef typename vtkm::cont::ArrayHandle::ExecutionTypes::PortalConst IdPortalType; IdPortalType totalCountArray; VTKM_CONT_EXPORT AdjacentDifference(IdPortalType totalCount) : totalCountArray(totalCount) { } VTKM_EXEC_EXPORT void operator()(const vtkm::Id &index, vtkm::Id & difference) const { if (index == 0) difference = this->totalCountArray.Get(index); else difference = this->totalCountArray.Get(index) - this->totalCountArray.Get(index - 1); } }; // Execute the histogram binning filter given data and number of bins void Run(vtkm::cont::ArrayHandle fieldArray, vtkm::Id numberOfBins, FieldType* minValue, FieldType* delta, vtkm::cont::ArrayHandle binArray) { typedef typename vtkm::cont::DeviceAdapterAlgorithm DeviceAlgorithms; typedef typename vtkm::cont::ArrayHandle::PortalConstControl FieldPortal; vtkm::Id numberOfValues = fieldArray.GetNumberOfValues(); vtkm::cont::ArrayHandle tempArray; DeviceAlgorithms::Copy(fieldArray, tempArray); FieldPortal tempPortal = tempArray.GetPortalConstControl(); FieldType initValue = tempPortal.Get(0); *minValue = DeviceAlgorithms::Reduce(fieldArray, initValue, minFunctor()); FieldType maxValue = DeviceAlgorithms::Reduce(fieldArray, initValue, maxFunctor()); FieldType range = maxValue - *minValue; *delta = range / static_cast(numberOfBins); // Worklet fills in the bin belonging to each value vtkm::cont::ArrayHandle binIndex; binIndex.Allocate(numberOfValues); // Worklet to set the bin number for each data value vtkm::worklet::DispatcherMapField setHistogramBinDispatcher(SetHistogramBin(numberOfBins, *minValue, *delta)); setHistogramBinDispatcher.Invoke(fieldArray, binIndex); // Sort the resulting bin array for counting DeviceAlgorithms::Sort(binIndex); // Get the upper bound of each bin number vtkm::cont::ArrayHandle totalCount; vtkm::cont::ArrayHandleCounting binCounter(0, 1, numberOfBins); DeviceAlgorithms::UpperBounds(binIndex, binCounter, totalCount); // Difference between adjacent items is the bin count vtkm::worklet::DispatcherMapField adjacentDifferenceDispatcher(AdjacentDifference(totalCount.PrepareForInput(DeviceAdapter()))); adjacentDifferenceDispatcher.Invoke(binCounter, binArray); } }; } } // namespace vtkm::worklet #endif // vtk_m_worklet_FieldHistogram_h