Commit 561af10a authored by Haocheng LIU's avatar Haocheng LIU

Expose vtkm NDHistogram filter into vtk

The vtkmNDHistogram would generate a vtkSparseArray to store the results.
parent e84ee1dd
......@@ -39,13 +39,14 @@ set(headers
vtkmContour.h
vtkmExternalFaces.h
vtkmExtractVOI.h
vtkmGradient.h
vtkmHistogram.h
vtkmThreshold.h
vtkmLevelOfDetail.h
vtkmGradient.h
vtkmNDHistogram.h
vtkmPointElevation.h
vtkmPolyDataNormals.h
vtkmProbe.h
vtkmThreshold.h
vtkmTriangleMeshPointNormals.h
)
......@@ -53,21 +54,22 @@ set(headers
set(cpu_accelerator_srcs
vtkmAverageToCells.cxx
vtkmAverageToPoints.cxx
vtkmCellSetExplicit.cxx
vtkmCellSetSingleType.cxx
vtkmCleanGrid.cxx
vtkmClip.cxx
vtkmConnectivityExec.cxx
vtkmContour.cxx
vtkmExternalFaces.cxx
vtkmExtractVOI.cxx
vtkmGradient.cxx
vtkmHistogram.cxx
vtkmThreshold.cxx
vtkmLevelOfDetail.cxx
vtkmCellSetExplicit.cxx
vtkmCellSetSingleType.cxx
vtkmConnectivityExec.cxx
vtkmGradient.cxx
vtkmNDHistogram.cxx
vtkmPointElevation.cxx
vtkmPolyDataNormals.cxx
vtkmProbe.cxx
vtkmThreshold.cxx
vtkmTriangleMeshPointNormals.cxx
vtkmlib/Portals.cxx
vtkmlib/ImplicitFunctionConverter.cxx
......@@ -75,23 +77,24 @@ set(cpu_accelerator_srcs
#implementation of the algorithms for gpu accelerators
set(cuda_accelerator_srcs
vtkmAverageToCells.cu
vtkmAverageToPoints.cu
vtkmCellSetExplicit.cu
vtkmCellSetSingleType.cu
vtkmCleanGrid.cu
vtkmClip.cu
vtkmConnectivityExec.cu
vtkmContour.cu
vtkmExternalFaces.cu
vtkmExtractVOI.cu
vtkmGradient.cu
vtkmHistogram.cu
vtkmThreshold.cu
vtkmLevelOfDetail.cu
vtkmAverageToCells.cu
vtkmCellSetExplicit.cu
vtkmCellSetSingleType.cu
vtkmConnectivityExec.cu
vtkmGradient.cu
vtkmNDHistogram.cu
vtkmPointElevation.cu
vtkmPolyDataNormals.cu
vtkmProbe.cu
vtkmThreshold.cu
vtkmTriangleMeshPointNormals.cu
vtkmlib/Portals.cu
vtkmlib/ImplicitFunctionConverter.cu
......
......@@ -10,6 +10,7 @@ vtk_add_test_cxx(vtkAcceleratorsVtkmCxxTests tests
TestVTKMLevelOfDetail.cxx
TestVTKMMarchingCubes.cxx
TestVTKMMarchingCubes2.cxx
TestVTKMNDHistogram.cxx,NO_VALID
TestVTKMPointElevation.cxx
TestVTKMProbe.cxx,NO_VALID
TestVTKMPolyDataNormals.cxx
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestVTKMClip.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkmNDHistogram.h"
#include "vtkActor.h"
#include "vtkArrayData.h"
#include "vtkCamera.h"
#include "vtkCellData.h"
#include "vtkDataSet.h"
#include "vtkDelaunay3D.h"
#include "vtkDoubleArray.h"
#include "vtkImageData.h"
#include "vtkImageToPoints.h"
#include "vtkNew.h"
#include "vtkPointData.h"
#include "vtkSparseArray.h"
#include "vtkTable.h"
namespace {
static const std::vector<std::string> arrayNames = {"temperature0", "temperature1",
"temperature2", "temperature3"};
static const std::vector<std::vector<size_t>> resultBins =
{{0, 0, 1, 1, 2, 2, 3, 3},
{0, 1, 1, 2, 2, 3, 3, 4},
{0, 1, 2, 2, 3, 4, 4, 5},
{0, 1, 2, 3, 3, 4, 5, 6},};
static const std::vector<size_t> resultFrequency = {2, 1, 1, 1, 1, 1, 1, 2};
static const int nData = 10;
static const std::vector<size_t> bins = {4,5,6,7};
void AddArrayToVTKData(std::string scalarName, vtkDataSetAttributes* pd,
double* data, vtkIdType size)
{
vtkNew<vtkDoubleArray> scalars;
scalars->SetArray(data, size, 1);
scalars->SetName(scalarName.c_str());
pd->AddArray(scalars);
}
void MakeTestDataset(vtkDataSet* dataset)
{
static double T0[nData], T1[nData], T2[nData], T3[nData];
for (int i = 0; i < nData; i++)
{
T0[i] = i * 1.0;
T1[i] = i * 2.0;
T2[i] = i * 3.0;
T3[i] = i * 4.0;
}
vtkPointData* pd = dataset->GetPointData();
AddArrayToVTKData(arrayNames[0], pd, T0, static_cast<vtkIdType>(nData));
AddArrayToVTKData(arrayNames[1], pd, T1, static_cast<vtkIdType>(nData));
AddArrayToVTKData(arrayNames[2], pd, T2, static_cast<vtkIdType>(nData));
AddArrayToVTKData(arrayNames[3], pd, T3, static_cast<vtkIdType>(nData));
}
}
int TestVTKMNDHistogram(int, char*[])
{
vtkNew<vtkPolyData> ds;
MakeTestDataset(ds);
vtkNew<vtkmNDHistogram> filter;
filter->SetInputData(ds);
size_t index = 0;
for (const auto& an: arrayNames)
{
filter->AddFieldAndBin(an, bins[index++]);
}
filter->Update();
vtkArrayData* arrayData = filter->GetOutput();
assert(arrayData != nullptr);
// Valid the data range and bin delta
for (vtkIdType i = 0; i < 4; i++)
{
// Validate the delta and range
auto range = filter->GetDataRange(i);
double delta = filter->GetBinDelta(i);
if (range.first != 0.0 || range.second != (i+1)* 9)
{
std::cout << "array index=" << i << " does not have right range" <<std::endl;
return 1;
}
if (delta != ((range.second - range.first) / bins[i]))
{
std::cout << "array index" << i << " does not have right delta" <<std::endl;
return 1;
}
}
vtkSparseArray<double>* sa = static_cast<vtkSparseArray<double>*>(arrayData->GetArray(0));
vtkArrayCoordinates coordinates;
const vtkIdType dimensions = sa->GetDimensions(); // 4
const vtkIdType non_null_size = sa->GetNonNullSize(); // 8
for(vtkIdType n = 0; n != non_null_size; ++n)
{
sa->GetCoordinatesN(n, coordinates);
for(vtkIdType d = 0; d != dimensions; ++d)
{
assert(coordinates[d] == static_cast<vtkIdType>(resultBins[d][n]));
if (coordinates[d] != static_cast<vtkIdType>(resultBins[d][n]))
{
std::cout << "value does not match at index " << n <<
" dimension " << d <<std::endl;
}
}
assert(resultFrequency[n] == sa->GetValue(coordinates));
}
return 0;
}
//=============================================================================
//
// 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 2012 Sandia Corporation.
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
//=============================================================================
#include "vtkmNDHistogram.cxx"
//=============================================================================
//
// 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 2012 Sandia Corporation.
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
//=============================================================================
#include "vtkmNDHistogram.h"
#include "vtkmConfig.h"
#include "vtkCellData.h"
#include "vtkDataSet.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkmFilterPolicy.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkSparseArray.h"
#include "vtkTable.h"
#include "vtkmlib/Storage.h"
#include "vtkmlib/DataSetConverters.h"
#include "vtkmlib/ArrayConverters.h"
#include <vtkm/filter/NDHistogram.h>
vtkStandardNewMacro(vtkmNDHistogram)
//------------------------------------------------------------------------------
void vtkmNDHistogram::PrintSelf(std::ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "FieldNames: " << "\n";
for (const auto& fieldName : FieldNames)
{
os << indent << fieldName << " ";
}
os << indent << "\n";
os << indent << "NumberOfBins: " << "\n";
for (const auto& nob : NumberOfBins)
{
os << indent << nob << " ";
}
os << indent << "\n";
os << indent << "BinDeltas: " << "\n";
for (const auto& bd : BinDeltas)
{
os << indent << bd << " ";
}
os << indent << "\n";
os << indent << "DataRanges: " << "\n";
for (const auto& dr : DataRanges)
{
os << indent << dr.first << " " << dr.second << " ";
}
os << indent << "\n";
}
//------------------------------------------------------------------------------
vtkmNDHistogram::vtkmNDHistogram()
{
}
//------------------------------------------------------------------------------
vtkmNDHistogram::~vtkmNDHistogram()
{
}
//------------------------------------------------------------------------------
void vtkmNDHistogram::AddFieldAndBin(const std::string& fieldName, const vtkIdType& numberOfBins)
{
this->FieldNames.push_back(fieldName);
this->NumberOfBins.push_back(numberOfBins);
this->SetInputArrayToProcess(static_cast<int>(this->FieldNames.size()), 0, 0,
vtkDataObject::FIELD_ASSOCIATION_POINTS, fieldName.c_str());
}
//------------------------------------------------------------------------------
double vtkmNDHistogram::GetBinDelta(size_t fieldIndex)
{
return this->BinDeltas[fieldIndex];
}
//------------------------------------------------------------------------------
std::pair<double, double> vtkmNDHistogram::GetDataRange(size_t fieldIndex)
{
return this->DataRanges[fieldIndex];
}
//------------------------------------------------------------------------------
int vtkmNDHistogram::FillInputPortInformation(int port, vtkInformation* info)
{
this->Superclass::FillInputPortInformation(port, info);
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject");
return 1;
}
//------------------------------------------------------------------------------
int vtkmNDHistogram::GetFieldIndexFromFieldName(const std::string& fieldName)
{
auto iter =
std::find(this->FieldNames.begin(), this->FieldNames.end(), fieldName);
return (iter == std::end(this->FieldNames)) ? -1 :
static_cast<int>(iter - this->FieldNames.begin());
}
//------------------------------------------------------------------------------
int vtkmNDHistogram::RequestData(vtkInformation* vtkNotUsed(request),
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
{
vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
vtkDataSet* input =
vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkArrayData* output = vtkArrayData::GetData(outputVector, 0);
output->ClearArrays();
try
{
vtkm::cont::DataSet in = tovtkm::Convert(input, tovtkm::FieldsFlag::PointsAndCells);
vtkmInputFilterPolicy policy;
vtkm::filter::NDHistogram filter;
for (size_t i = 0; i < this->FieldNames.size(); i++)
{
filter.AddFieldAndBin(this->FieldNames[i], this->NumberOfBins[i]);
}
vtkm::cont::DataSet out = filter.Execute(in, policy);
vtkm::Id numberOfFields = out.GetNumberOfFields();
this->BinDeltas.clear();
this->DataRanges.clear();
this->BinDeltas.reserve(static_cast<size_t>(numberOfFields));
this->DataRanges.reserve(static_cast<size_t>(numberOfFields));
// Fetch the field array out of the vtkm filter result
size_t index = 0;
std::vector<vtkDataArray*> fArrays;
for (auto& fn: this->FieldNames)
{
vtkDataArray* fnArray = fromvtkm::Convert(out.GetField(
fn));
fnArray->SetName(fn.c_str());
fArrays.push_back(fnArray);
this->BinDeltas.push_back(filter.GetBinDelta(index));
this->DataRanges.push_back(std::make_pair(filter.GetDataRange(index).Min,
filter.GetDataRange(index).Max));
index++;
}
vtkDataArray* frequencyArray = fromvtkm::Convert(out.GetField("Frequency"));
frequencyArray->SetName("Frequency");
// Create the sparse array
vtkSparseArray<double>* sparseArray =
vtkSparseArray<double>::New();
vtkArrayExtents sae; //sparse array extent
size_t ndims(fArrays.size());
sae.SetDimensions(static_cast<vtkArrayExtents::DimensionT>(ndims));
for (size_t i=0; i < ndims; i++)
{
sae[static_cast<vtkArrayExtents::DimensionT>(i)] = vtkArrayRange(0, fArrays[i]->GetNumberOfValues());
}
sparseArray->Resize(sae);
// Set the dimension label
for (size_t i=0; i < ndims; i++)
{
sparseArray->SetDimensionLabel(static_cast<vtkIdType>(i),
fArrays[i]->GetName());
}
// Fill in the sparse array
for (vtkIdType i=0; i < frequencyArray->GetNumberOfValues(); i++)
{
vtkArrayCoordinates coords;
coords.SetDimensions(static_cast<vtkArrayCoordinates::DimensionT>(ndims));
for (size_t j=0; j < ndims; j++)
{
coords[static_cast<vtkArrayCoordinates::DimensionT>(j)] = fArrays[j]->GetComponent(i, 0);
}
sparseArray->SetValue(coords, frequencyArray->GetComponent(i, 0));
}
output->AddArray(sparseArray);
// Clean up the memory
for (auto& fArray : fArrays)
{
fArray->FastDelete();
}
frequencyArray->FastDelete();
sparseArray->FastDelete();
}
catch(const vtkm::cont::Error& e)
{
vtkErrorMacro(<<"VTK-m error: " << e.GetMessage());
return 0;
}
return 1;
}
//=============================================================================
//
// 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 2012 Sandia Corporation.
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
//=============================================================================
/**
* @class vtkmNDHistogram
* @brief generate a n dimensional histogram field from input fields
*
* vtkmNDhistogram is a filter that generate a n dimensional histogram field from
* some input fields.
* This filter takes a data set and with target fields and bins defined,
* it would generate a N-Dims histogram from input fields. The input fields should
* have the same number of values.
* The result is stored in a field named as "Frequency". This field contains all
* the frequencies of the N-Dims histogram in sparse representation.
* That being said, the result field does not store 0 frequency bins. Meanwhile
* all input fields now would have the same length and store bin ids instead.
* E.g. (FieldA[i], FieldB[i], FieldC[i], Frequency[i]) is a bin in the histogram.
* The first three numbers are binIDs for FieldA, FieldB and FieldC. Frequency[i] stores
* the frequency for this bin (FieldA[i], FieldB[i], FieldC[i]).
*/
#ifndef vtkmNDHistogram_h
#define vtkmNDHistogram_h
#include <utility>
#include <vector>
#include "vtkArrayDataAlgorithm.h"
#include "vtkAcceleratorsVTKmModule.h" // required for correct export
class VTKACCELERATORSVTKM_EXPORT vtkmNDHistogram : public vtkArrayDataAlgorithm
{
public:
vtkTypeMacro(vtkmNDHistogram, vtkArrayDataAlgorithm)
void PrintSelf(ostream& os, vtkIndent indent) override;
void AddFieldAndBin(const std::string& fieldName, const vtkIdType& numberOfBins);
double GetBinDelta(size_t fieldIndex);
std::pair<double, double> GetDataRange(size_t fieldIndex);
/**
* @brief GetFieldIndexFromFieldName
* @param fieldName
* @return the index of the fieldName. If it's not in the FieldNames list, a -1
* would be returned.
*/
int GetFieldIndexFromFieldName(const std::string& fieldName);
static vtkmNDHistogram* New();
protected:
vtkmNDHistogram();
~vtkmNDHistogram();
int RequestData(vtkInformation* , vtkInformationVector** ,
vtkInformationVector* )override;
int FillInputPortInformation(int port, vtkInformation* info) override;
private:
vtkmNDHistogram(const vtkmNDHistogram&) = delete;
void operator=(const vtkmNDHistogram&) = delete;
std::vector<std::string> FieldNames;
std::vector<vtkIdType> NumberOfBins;
std::vector<double> BinDeltas;
std::vector<std::pair<double, double>> DataRanges;
};
#endif // vtkmNDHistogram_h
// VTK-HeaderTest-Exclude: vtkmNDHistogram.h
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment