mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
move wavelet stuff back to worklet folder
This commit is contained in:
parent
cf1299bd75
commit
b2d15bbbde
@ -36,7 +36,6 @@ set(headers
|
||||
ResultField.h
|
||||
Threshold.h
|
||||
VertexClustering.h
|
||||
WaveletCompressor.h
|
||||
)
|
||||
|
||||
set(header_template_sources
|
||||
@ -50,7 +49,6 @@ set(header_template_sources
|
||||
PointElevation.hxx
|
||||
Threshold.hxx
|
||||
VertexClustering.hxx
|
||||
WaveletCompressor.hxx
|
||||
)
|
||||
|
||||
vtkm_declare_headers(${headers})
|
||||
|
@ -22,10 +22,6 @@ set(headers
|
||||
ResolveFieldTypeAndExecute.h
|
||||
ResolveFieldTypeAndMap.h
|
||||
RuntimeDeviceTracker.h
|
||||
FilterBanks.h
|
||||
WaveletFilter.h
|
||||
WaveletBase.h
|
||||
WaveletDWT.h
|
||||
)
|
||||
|
||||
vtkm_declare_headers(${headers})
|
||||
|
@ -26,7 +26,6 @@ set(unit_tests
|
||||
UnitTestMarchingCubesFilter.cxx
|
||||
UnitTestThresholdFilter.cxx
|
||||
UnitTestVertexClusteringFilter.cxx
|
||||
UnitTestWaveletCompressorFilter.cxx
|
||||
)
|
||||
|
||||
vtkm_unit_tests(SOURCES ${unit_tests})
|
||||
|
@ -44,12 +44,13 @@ set(headers
|
||||
TriangulateUniformGrid.h
|
||||
Threshold.h
|
||||
VertexClustering.h
|
||||
WaveletTransforms.h
|
||||
WaveletCompressor.h
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
add_subdirectory(internal)
|
||||
add_subdirectory(splatkernels)
|
||||
add_subdirectory(wavelets)
|
||||
|
||||
vtkm_declare_headers(${headers})
|
||||
|
||||
|
238
vtkm/worklet/WaveletCompressor.h
Normal file
238
vtkm/worklet/WaveletCompressor.h
Normal file
@ -0,0 +1,238 @@
|
||||
//============================================================================
|
||||
// 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_waveletcompressor_h
|
||||
#define vtk_m_worklet_waveletcompressor_h
|
||||
|
||||
#include <vtkm/worklet/wavelets/WaveletDWT.h>
|
||||
|
||||
//#include <vtkm/worklet/WaveletTransforms.h>
|
||||
|
||||
#include <vtkm/cont/ArrayHandleConcatenate.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
|
||||
#include <vtkm/Math.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace worklet {
|
||||
|
||||
//template< typename DeviceAdapter >
|
||||
class WaveletCompressor : public vtkm::worklet::wavelets::WaveletDWT
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
WaveletCompressor( const std::string &w_name ) : WaveletDWT( w_name ) {}
|
||||
|
||||
// Multi-level 1D wavelet decomposition
|
||||
template< typename SignalArrayType, typename CoeffArrayType>
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
vtkm::Id WaveDecompose( const SignalArrayType &sigIn, // Input
|
||||
vtkm::Id nLevels, // n levels of DWT
|
||||
CoeffArrayType &coeffOut,
|
||||
vtkm::Id* L )
|
||||
{
|
||||
vtkm::Id sigInLen = sigIn.GetNumberOfValues();
|
||||
if( nLevels < 1 || nLevels > WaveletBase::GetWaveletMaxLevel( sigInLen ) )
|
||||
{
|
||||
std::cerr << "nLevel is not supported: " << nLevels << std::endl;
|
||||
// throw an error
|
||||
}
|
||||
/* 0 levels means no transform
|
||||
if( nLevels == 0 )
|
||||
{
|
||||
vtkm::cont::DeviceAdapterAlgorithm< VTKM_DEFAULT_DEVICE_ADAPTER_TAG>::Copy
|
||||
(sigIn, C );
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
this->ComputeL( sigInLen, nLevels, L );
|
||||
vtkm::Id CLength = this->ComputeCoeffLength( L, nLevels );
|
||||
|
||||
// Use 64bit floats for intermediate calculation
|
||||
#define VAL vtkm::Float64
|
||||
|
||||
vtkm::Id sigInPtr = 0; // pseudo pointer for the beginning of input array
|
||||
vtkm::Id len = sigIn.GetNumberOfValues();
|
||||
vtkm::Id cALen = WaveletBase::GetApproxLength( len );
|
||||
vtkm::Id cptr; // pseudo pointer for the beginning of output array
|
||||
vtkm::Id tlen = 0;
|
||||
vtkm::Id L1d[3];
|
||||
|
||||
// Use an intermediate array
|
||||
typedef vtkm::cont::ArrayHandle< VAL > InterArrayType;
|
||||
typedef typename InterArrayType::PortalControl InterPortalType;
|
||||
InterArrayType interArray;
|
||||
interArray.Allocate( CLength );
|
||||
vtkm::cont::DeviceAdapterAlgorithm< VTKM_DEFAULT_DEVICE_ADAPTER_TAG>::Copy
|
||||
(sigIn, interArray );
|
||||
|
||||
// Define a few more types
|
||||
typedef vtkm::cont::ArrayHandleCounting< vtkm::Id > IdArrayType;
|
||||
typedef vtkm::cont::ArrayHandlePermutation< IdArrayType, InterArrayType > PermutArrayType;
|
||||
|
||||
for( vtkm::Id i = nLevels; i > 0; i-- )
|
||||
{
|
||||
tlen += L[i];
|
||||
cptr = 0 + CLength - tlen - cALen;
|
||||
|
||||
// make input array (permutation array)
|
||||
IdArrayType inputIndices( sigInPtr, 1, len );
|
||||
PermutArrayType input( inputIndices, interArray );
|
||||
// make output array
|
||||
InterArrayType output;
|
||||
|
||||
WaveletDWT::DWT1D( input, output, L1d );
|
||||
|
||||
// update interArray
|
||||
vtkm::cont::ArrayPortalToIterators< InterPortalType >
|
||||
outputIter( output.GetPortalControl() );
|
||||
vtkm::cont::ArrayPortalToIterators< InterPortalType >
|
||||
interArrayIter( interArray.GetPortalControl() );
|
||||
std::copy( outputIter.GetBegin(), outputIter.GetEnd(), interArrayIter.GetBegin() + cptr );
|
||||
|
||||
// update pseudo pointers
|
||||
len = cALen;
|
||||
cALen = WaveletBase::GetApproxLength( cALen );
|
||||
sigInPtr = cptr;
|
||||
}
|
||||
|
||||
vtkm::cont::DeviceAdapterAlgorithm< VTKM_DEFAULT_DEVICE_ADAPTER_TAG>::Copy
|
||||
(interArray, coeffOut );
|
||||
|
||||
#undef VAL
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Multi-level 1D wavelet reconstruction
|
||||
template< typename CoeffArrayType, typename SignalArrayType >
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
vtkm::Id WaveReconstruct( const CoeffArrayType &coeffIn, // Input
|
||||
vtkm::Id nLevels, // n levels of DWT
|
||||
vtkm::Id* L,
|
||||
SignalArrayType &sigOut )
|
||||
{
|
||||
VTKM_ASSERT( nLevels > 0 );
|
||||
|
||||
vtkm::Id LLength = nLevels + 2;
|
||||
|
||||
vtkm::Id L1d[3] = {L[0], L[1], 0};
|
||||
|
||||
// Use 64bit floats for intermediate calculation
|
||||
#define VAL vtkm::Float64
|
||||
|
||||
// Use intermediate arrays
|
||||
typedef vtkm::cont::ArrayHandle< VAL > InterArrayType;
|
||||
typedef typename InterArrayType::PortalControl InterPortalType;
|
||||
typedef vtkm::cont::ArrayHandleCounting< vtkm::Id > IdArrayType;
|
||||
typedef vtkm::cont::ArrayHandlePermutation< IdArrayType, InterArrayType > PermutArrayType;
|
||||
|
||||
InterArrayType interArray;
|
||||
vtkm::cont::DeviceAdapterAlgorithm< VTKM_DEFAULT_DEVICE_ADAPTER_TAG>::Copy
|
||||
(coeffIn, interArray );
|
||||
|
||||
for( vtkm::Id i = 1; i <= nLevels; i++ )
|
||||
{
|
||||
L1d[2] = this->GetApproxLengthLevN( L[ LLength-1 ], nLevels-i );
|
||||
|
||||
// Make an input array
|
||||
IdArrayType inputIndices( 0, 1, L1d[2] );
|
||||
PermutArrayType input( inputIndices, interArray );
|
||||
|
||||
// Make an output array
|
||||
InterArrayType output;
|
||||
|
||||
WaveletDWT::IDWT1D( input, L1d, output );
|
||||
|
||||
// Move output to intermediate array
|
||||
vtkm::cont::ArrayPortalToIterators< InterPortalType >
|
||||
outputIter( output.GetPortalControl() );
|
||||
vtkm::cont::ArrayPortalToIterators< InterPortalType >
|
||||
interArrayIter( interArray.GetPortalControl() );
|
||||
std::copy( outputIter.GetBegin(), outputIter.GetEnd(), interArrayIter.GetBegin() );
|
||||
|
||||
L1d[0] = L1d[2];
|
||||
L1d[1] = L[i+1];
|
||||
}
|
||||
|
||||
vtkm::cont::DeviceAdapterAlgorithm< VTKM_DEFAULT_DEVICE_ADAPTER_TAG>::Copy
|
||||
( interArray, sigOut );
|
||||
|
||||
#undef VAL
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Squash coefficients smaller than a threshold
|
||||
/*
|
||||
template< typename CoeffArrayType >
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
vtkm::Id SquashCoefficients( CoeffArrayType, &coeffIn,
|
||||
vtkm::Id ratio );
|
||||
*/
|
||||
|
||||
|
||||
// Compute the book keeping array L for 1D wavelet decomposition
|
||||
void ComputeL( vtkm::Id sigInLen, vtkm::Id nLevels, vtkm::Id* L )
|
||||
{
|
||||
L[nLevels+1] = sigInLen;
|
||||
L[nLevels] = sigInLen;
|
||||
for( vtkm::Id i = nLevels; i > 0; i-- )
|
||||
{
|
||||
L[i-1] = WaveletBase::GetApproxLength( L[i] );
|
||||
L[i] = WaveletBase::GetDetailLength( L[i] );
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the length of coefficients
|
||||
vtkm::Id ComputeCoeffLength( const vtkm::Id* L, vtkm::Id nLevels )
|
||||
{
|
||||
vtkm::Id sum = L[0]; // 1st level cA
|
||||
for( vtkm::Id i = 1; i <= nLevels; i++ )
|
||||
sum += L[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
// Compute approximate coefficient length at a specific level
|
||||
vtkm::Id GetApproxLengthLevN( vtkm::Id sigInLen, vtkm::Id levN )
|
||||
{
|
||||
vtkm::Id cALen = sigInLen;
|
||||
for( vtkm::Id i = 0; i < levN; i++ )
|
||||
{
|
||||
cALen = WaveletBase::GetApproxLength( cALen );
|
||||
if( cALen == 0 )
|
||||
return cALen;
|
||||
}
|
||||
|
||||
return cALen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}; // class WaveletCompressor
|
||||
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
@ -38,7 +38,7 @@ set(unit_tests
|
||||
UnitTestWorkletMapTopologyExplicit.cxx
|
||||
UnitTestWorkletMapTopologyUniform.cxx
|
||||
UnitTestVertexClustering.cxx
|
||||
UnitTestWaveletTransforms.cxx
|
||||
UnitTestWaveletCompressor.cxx
|
||||
)
|
||||
|
||||
vtkm_save_worklet_unit_tests(${unit_tests})
|
||||
|
208
vtkm/worklet/testing/UnitTestWaveletCompressor.cxx
Normal file
208
vtkm/worklet/testing/UnitTestWaveletCompressor.cxx
Normal file
@ -0,0 +1,208 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/worklet/WaveletCompressor.h>
|
||||
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
#include <vtkm/cont/Timer.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
||||
void TestExtend1D()
|
||||
{
|
||||
// make input data array handle
|
||||
typedef vtkm::Float64 T;
|
||||
typedef vtkm::cont::ArrayHandle<T> ArrayType;
|
||||
vtkm::Id sigLen = 20;
|
||||
std::vector<T> tmpVector;
|
||||
for( vtkm::Id i = 0; i < sigLen; i++ )
|
||||
tmpVector.push_back( static_cast<T>(i) );
|
||||
|
||||
vtkm::cont::ArrayHandle<T> inputArray =
|
||||
vtkm::cont::make_ArrayHandle(tmpVector);
|
||||
ArrayType outputArray;
|
||||
|
||||
vtkm::worklet::wavelets::WaveletDWT w("CDF9/7");
|
||||
/*
|
||||
typedef vtkm::cont::ArrayHandleConcatenate< ArrayType, ArrayType>
|
||||
ArrayConcat;
|
||||
typedef vtkm::cont::ArrayHandleConcatenate< ArrayConcat, ArrayType > ArrayConcat2;
|
||||
ArrayConcat2 outputArray;
|
||||
*/
|
||||
w.Extend1D( inputArray, outputArray, 4,
|
||||
vtkm::worklet::wavelets::SYMW, vtkm::worklet::wavelets::SYMW );
|
||||
|
||||
std::cout << "Start testing Extend1D" << std::endl;
|
||||
for (vtkm::Id i = 0; i < outputArray.GetNumberOfValues(); ++i)
|
||||
std::cout << outputArray.GetPortalConstControl().Get(i) << std::endl;
|
||||
std::cout << "\nFinish testing Extend1D" << std::endl;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
void TestDWTIDWT1D()
|
||||
{
|
||||
vtkm::Id sigLen = 20;
|
||||
std::cout << "Testing Wavelets Worklet" << std::endl;
|
||||
std::cout << "Default test size is 20. " << std::endl;
|
||||
std::cout << "Input a new size to test." << std::endl;
|
||||
std::cout << "Input 0 to stick with 20." << std::endl;
|
||||
vtkm::Id tmpIn;
|
||||
vtkm::Id million = 1;//1000000;
|
||||
std::cin >> tmpIn;
|
||||
if( tmpIn != 0 )
|
||||
sigLen = tmpIn * million;
|
||||
|
||||
// make input data array handle
|
||||
std::vector<vtkm::Float64> tmpVector;
|
||||
for( vtkm::Id i = 0; i < sigLen; i++ )
|
||||
tmpVector.push_back( static_cast<vtkm::Float64>( i ) );
|
||||
vtkm::cont::ArrayHandle<vtkm::Float64> inputArray =
|
||||
vtkm::cont::make_ArrayHandle(tmpVector);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float64> coeffOut;
|
||||
vtkm::Id L[3];
|
||||
|
||||
// Forward Transform
|
||||
vtkm::worklet::wavelets::WaveletDWT waveletdwt( "CDF9/7" );
|
||||
waveletdwt.DWT1D( inputArray, coeffOut, L );
|
||||
|
||||
std::cout << "Forward Wavelet Transform: result coeff length = " <<
|
||||
coeffOut.GetNumberOfValues() << std::endl;
|
||||
/*
|
||||
printf("L[0] = %lld, L[1] = %lld, L[2] = %lld\n", L[0], L[1], L[2] );
|
||||
*/
|
||||
for( vtkm::Id i; i < coeffOut.GetNumberOfValues(); i++ )
|
||||
{
|
||||
if( i == 0 )
|
||||
std::cout << " <-- cA --> " << std::endl;
|
||||
else if( i == L[0] )
|
||||
std::cout << " <-- cD --> " << std::endl;
|
||||
std::cout << coeffOut.GetPortalConstControl().Get(i) << std::endl;
|
||||
}
|
||||
|
||||
// Inverse Transform
|
||||
vtkm::cont::ArrayHandle<vtkm::Float64> reconstructArray;
|
||||
waveletdwt.IDWT1D( coeffOut, L, reconstructArray );
|
||||
std::cout << "Inverse Wavelet Transform: result signal length = " <<
|
||||
reconstructArray.GetNumberOfValues() << std::endl;
|
||||
for( vtkm::Id i; i < reconstructArray.GetNumberOfValues(); i++ )
|
||||
{
|
||||
std::cout << reconstructArray.GetPortalConstControl().Get(i) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
void TestWaveDecomposeReconstruct()
|
||||
{
|
||||
vtkm::Id sigLen = 20;
|
||||
std::cout << "Testing Wavelets Worklet" << std::endl;
|
||||
std::cout << "Default test size is 20. " << std::endl;
|
||||
std::cout << "Input a new size to test." << std::endl;
|
||||
std::cout << "Input 0 to stick with 20." << std::endl;
|
||||
vtkm::Id tmpIn;
|
||||
vtkm::Id million = 1000000;
|
||||
std::cin >> tmpIn;
|
||||
if( tmpIn != 0 )
|
||||
sigLen = tmpIn * million;
|
||||
|
||||
// make input data array handle
|
||||
std::vector<vtkm::Float64> tmpVector;
|
||||
for( vtkm::Id i = 0; i < sigLen; i++ )
|
||||
tmpVector.push_back( vtkm::Sin(static_cast<vtkm::Float64>( i ) ));
|
||||
vtkm::cont::ArrayHandle<vtkm::Float64> inputArray =
|
||||
vtkm::cont::make_ArrayHandle(tmpVector);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float64> outputArray;
|
||||
|
||||
// Use a WaveletCompressor
|
||||
vtkm::Id nLevels = 2;
|
||||
vtkm::worklet::WaveletCompressor compressor("CDF9/7");
|
||||
|
||||
// User input of decompose levels
|
||||
vtkm::Id maxLevel = compressor.GetWaveletMaxLevel( sigLen );
|
||||
std::cout << "Please input how many wavelet transform levels to perform, between 1 and "
|
||||
<< maxLevel << std::endl;
|
||||
vtkm::Id levTemp;
|
||||
std::cin >> levTemp;
|
||||
if( levTemp > 0 && levTemp <= maxLevel )
|
||||
nLevels = levTemp;
|
||||
else
|
||||
{
|
||||
std::cerr << "not valid levels of transforms" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
vtkm::Id L[ nLevels + 2 ];
|
||||
|
||||
// Use a timer and decompose
|
||||
vtkm::cont::Timer<> timer;
|
||||
compressor.WaveDecompose( inputArray, nLevels, outputArray, L );
|
||||
vtkm::Float64 elapsedTime = timer.GetElapsedTime();
|
||||
std::cout << "Decompose takes time: " << elapsedTime << std::endl;
|
||||
|
||||
#if 0
|
||||
std::cout << "Output coefficients has length = " <<
|
||||
outputArray.GetNumberOfValues() << std::endl;
|
||||
for( vtkm::Id i = 0; i < outputArray.GetNumberOfValues(); i++ )
|
||||
{
|
||||
std::cout << outputArray.GetPortalConstControl().Get(i) << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sort all coefficients
|
||||
|
||||
|
||||
// Reconstruct
|
||||
vtkm::cont::ArrayHandle<vtkm::Float64> reconstructArray;
|
||||
timer.Reset();
|
||||
compressor.WaveReconstruct( outputArray, nLevels, L, reconstructArray );
|
||||
elapsedTime = timer.GetElapsedTime();
|
||||
std::cout << "Reconstruction takes time: " << elapsedTime << std::endl;
|
||||
|
||||
//std::cout << "Reconstruct array has length = " <<
|
||||
// reconstructArray.GetNumberOfValues() << std::endl;
|
||||
timer.Reset();
|
||||
for( vtkm::Id i = 0; i < reconstructArray.GetNumberOfValues(); i++ )
|
||||
{
|
||||
//std::cout << reconstructArray.GetPortalConstControl().Get(i) << std::endl;
|
||||
|
||||
VTKM_TEST_ASSERT( test_equal( reconstructArray.GetPortalConstControl().Get(i),
|
||||
vtkm::Sin( static_cast<vtkm::Float64>(i) )),
|
||||
"output value not the same..." );
|
||||
}
|
||||
elapsedTime = timer.GetElapsedTime();
|
||||
std::cout << "Verification takes time: " << elapsedTime << std::endl;
|
||||
|
||||
}
|
||||
|
||||
void TestWaveletCompressor()
|
||||
{
|
||||
std::cout << "Welcome to WaveletCompressor test program :) " << std::endl;
|
||||
//TestExtend1D();
|
||||
//TestDWTIDWT1D();
|
||||
TestWaveDecomposeReconstruct();
|
||||
}
|
||||
|
||||
int UnitTestWaveletCompressor(int, char *[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(TestWaveletCompressor);
|
||||
}
|
30
vtkm/worklet/wavelets/CMakeLists.txt
Normal file
30
vtkm/worklet/wavelets/CMakeLists.txt
Normal file
@ -0,0 +1,30 @@
|
||||
##============================================================================
|
||||
## 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 2016 Sandia Corporation.
|
||||
## Copyright 2016 UT-Battelle, LLC.
|
||||
## Copyright 2016 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.
|
||||
##============================================================================
|
||||
|
||||
set(headers
|
||||
FilterBanks.h
|
||||
WaveletFilter.h
|
||||
WaveletBase.h
|
||||
WaveletTransforms.h
|
||||
WaveletDWT.h
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
vtkm_declare_headers(${headers})
|
80
vtkm/worklet/wavelets/FilterBanks.h
Normal file
80
vtkm/worklet/wavelets/FilterBanks.h
Normal file
@ -0,0 +1,80 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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 2015 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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_wavelets_filterbanks_h
|
||||
#define vtk_m_worklet_wavelets_filterbanks_h
|
||||
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace worklet {
|
||||
|
||||
namespace wavelets {
|
||||
|
||||
const vtkm::Float64 hm4_44[9] = {
|
||||
0.037828455507264,
|
||||
-0.023849465019557,
|
||||
-0.110624404418437,
|
||||
0.377402855612831,
|
||||
0.852698679008894,
|
||||
0.377402855612831,
|
||||
-0.110624404418437,
|
||||
-0.023849465019557,
|
||||
0.037828455507264
|
||||
};
|
||||
|
||||
const vtkm::Float64 h4[9] = {
|
||||
0.0,
|
||||
-0.064538882628697,
|
||||
-0.040689417609164,
|
||||
0.418092273221617,
|
||||
0.788485616405583,
|
||||
0.418092273221617,
|
||||
-0.0406894176091641,
|
||||
-0.0645388826286971,
|
||||
0.0
|
||||
};
|
||||
|
||||
const double hm2_22[6] = {
|
||||
-0.1767766952966368811002110905262,
|
||||
0.3535533905932737622004221810524,
|
||||
1.0606601717798212866012665431573,
|
||||
0.3535533905932737622004221810524,
|
||||
-0.1767766952966368811002110905262
|
||||
};
|
||||
|
||||
const double h2[18] = {
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
0.3535533905932737622004221810524,
|
||||
0.7071067811865475244008443621048,
|
||||
0.3535533905932737622004221810524,
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
0.0
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
183
vtkm/worklet/wavelets/WaveletBase.h
Normal file
183
vtkm/worklet/wavelets/WaveletBase.h
Normal file
@ -0,0 +1,183 @@
|
||||
//============================================================================
|
||||
// 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_wavelets_waveletbase_h
|
||||
#define vtk_m_worklet_wavelets_waveletbase_h
|
||||
|
||||
|
||||
#include <vtkm/worklet/wavelets/WaveletFilter.h>
|
||||
|
||||
#include <vtkm/Math.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace worklet {
|
||||
|
||||
namespace wavelets {
|
||||
|
||||
enum DWTMode { // boundary extension modes
|
||||
INVALID = -1,
|
||||
ZPD,
|
||||
SYMH,
|
||||
SYMW,
|
||||
ASYMH, ASYMW, SP0, SP1, PPD, PER
|
||||
};
|
||||
|
||||
// Functionalities are similar to MatWaveBase in VAPoR.
|
||||
class WaveletBase
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
WaveletBase( const std::string &w_name )
|
||||
{
|
||||
this->filter = NULL;
|
||||
this->wmode = PER;
|
||||
this->wname = w_name;
|
||||
if( wname.compare("CDF9/7") == 0 )
|
||||
{
|
||||
this->wmode = SYMW; // Default extension mode, see MatWaveBase.cpp
|
||||
this->filter = new vtkm::worklet::wavelets::WaveletFilter( wname );
|
||||
}
|
||||
else if( wname.compare("CDF5/3") == 0 )
|
||||
{
|
||||
this->wmode = SYMW;
|
||||
this->filter = new vtkm::worklet::wavelets::WaveletFilter( wname );
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "This wavelet kernel is not supported: " << wname << std::endl;
|
||||
// throw an error
|
||||
}
|
||||
}
|
||||
|
||||
// Destructor
|
||||
virtual ~WaveletBase()
|
||||
{
|
||||
if( filter )
|
||||
delete filter;
|
||||
filter = NULL;
|
||||
}
|
||||
|
||||
// Get the wavelet filter
|
||||
const WaveletFilter* GetWaveletFilter()
|
||||
{
|
||||
if( this->filter == NULL )
|
||||
{
|
||||
// throw an error
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
// Returns length of approximation coefficients from a decompostition pass.
|
||||
vtkm::Id GetApproxLength( vtkm::Id sigInLen )
|
||||
{
|
||||
vtkm::Id filterLen = this->filter->GetFilterLength();
|
||||
|
||||
if (this->wmode == PER)
|
||||
return static_cast<vtkm::Id>(vtkm::Ceil( (static_cast<vtkm::Float64>(sigInLen)) / 2.0 ));
|
||||
else if (this->filter->isSymmetric())
|
||||
{
|
||||
if ( (this->wmode == SYMW && (filterLen % 2 != 0)) ||
|
||||
(this->wmode == SYMH && (filterLen % 2 == 0)) )
|
||||
{
|
||||
if (sigInLen % 2 != 0)
|
||||
return((sigInLen+1) / 2);
|
||||
else
|
||||
return((sigInLen) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<vtkm::Id>( vtkm::Floor(
|
||||
static_cast<vtkm::Float64>(sigInLen + filterLen - 1) / 2.0 ) );
|
||||
}
|
||||
|
||||
// Returns length of detail coefficients from a decompostition pass
|
||||
vtkm::Id GetDetailLength( vtkm::Id sigInLen )
|
||||
{
|
||||
vtkm::Id filterLen = this->filter->GetFilterLength();
|
||||
|
||||
if (this->wmode == PER)
|
||||
return static_cast<vtkm::Id>(vtkm::Ceil( (static_cast<vtkm::Float64>(sigInLen)) / 2.0 ));
|
||||
else if (this->filter->isSymmetric())
|
||||
{
|
||||
if ( (this->wmode == SYMW && (filterLen % 2 != 0)) ||
|
||||
(this->wmode == SYMH && (filterLen % 2 == 0)) )
|
||||
{
|
||||
if (sigInLen % 2 != 0)
|
||||
return((sigInLen-1) / 2);
|
||||
else
|
||||
return((sigInLen) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<vtkm::Id>( vtkm::Floor(
|
||||
static_cast<vtkm::Float64>(sigInLen + filterLen - 1) / 2.0 ) );
|
||||
}
|
||||
|
||||
// Returns length of coefficients generated in a decompostition pass
|
||||
vtkm::Id GetCoeffLength( vtkm::Id sigInLen )
|
||||
{
|
||||
return( GetApproxLength( sigInLen ) + GetDetailLength( sigInLen ) );
|
||||
}
|
||||
vtkm::Id GetCoeffLength2( vtkm::Id sigInX, vtkm::Id sigInY )
|
||||
{
|
||||
return( GetCoeffLength( sigInX) * GetCoeffLength( sigInY ) );
|
||||
}
|
||||
vtkm::Id GetCoeffLength3( vtkm::Id sigInX, vtkm::Id sigInY, vtkm::Id sigInZ)
|
||||
{
|
||||
return( GetCoeffLength( sigInX) * GetCoeffLength( sigInY ) * GetCoeffLength( sigInZ ) );
|
||||
}
|
||||
|
||||
// Returns maximum wavelet decompostion level
|
||||
vtkm::Id GetWaveletMaxLevel( vtkm::Id sigInLen )
|
||||
{
|
||||
if( ! this->filter )
|
||||
return 0;
|
||||
else {
|
||||
vtkm::Id filterLen = this->filter->GetFilterLength();
|
||||
vtkm::Id level;
|
||||
this->WaveLengthValidate( sigInLen, filterLen, level );
|
||||
return level;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
vtkm::worklet::wavelets::DWTMode wmode;
|
||||
WaveletFilter* filter;
|
||||
std::string wname;
|
||||
|
||||
void WaveLengthValidate( vtkm::Id sigInLen, vtkm::Id filterLength, vtkm::Id &level)
|
||||
{
|
||||
if( sigInLen < filterLength )
|
||||
level = 0;
|
||||
else
|
||||
level = static_cast<vtkm::Id>( vtkm::Floor(
|
||||
vtkm::Log2( static_cast<vtkm::Float64>(sigInLen) /
|
||||
static_cast<vtkm::Float64>(filterLength) ) + 1.0 ) );
|
||||
}
|
||||
}; // class WaveletBase.
|
||||
|
||||
|
||||
} // namespace wavelets
|
||||
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
407
vtkm/worklet/wavelets/WaveletDWT.h
Normal file
407
vtkm/worklet/wavelets/WaveletDWT.h
Normal file
@ -0,0 +1,407 @@
|
||||
//============================================================================
|
||||
// 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_wavelets_waveletdwt_h
|
||||
#define vtk_m_worklet_wavelets_waveletdwt_h
|
||||
|
||||
#include <vtkm/worklet/wavelets/WaveletBase.h>
|
||||
|
||||
#include <vtkm/worklet/wavelets/WaveletTransforms.h>
|
||||
|
||||
#include <vtkm/cont/ArrayHandleConcatenate.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
|
||||
#include <vtkm/Math.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace worklet {
|
||||
namespace wavelets {
|
||||
|
||||
class WaveletDWT : public WaveletBase
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
WaveletDWT( const std::string &w_name ) : WaveletBase( w_name ) {}
|
||||
|
||||
|
||||
// Func: Extend 1D signal
|
||||
template< typename SigInArrayType, typename SigExtendedArrayType >
|
||||
vtkm::Id Extend1D( const SigInArrayType &sigIn, // Input
|
||||
SigExtendedArrayType &sigOut, // Output
|
||||
vtkm::Id addLen,
|
||||
vtkm::worklet::wavelets::DWTMode leftExtMethod,
|
||||
vtkm::worklet::wavelets::DWTMode rightExtMethod )
|
||||
{
|
||||
typedef typename SigInArrayType::ValueType ValueType;
|
||||
typedef vtkm::cont::ArrayHandle< ValueType > ExtensionArrayType;
|
||||
ExtensionArrayType leftExtend, rightExtend;
|
||||
leftExtend.Allocate( addLen );
|
||||
rightExtend.Allocate( addLen );
|
||||
|
||||
typedef typename ExtensionArrayType::PortalControl PortalType;
|
||||
typedef typename SigInArrayType::PortalConstControl SigInPortalConstType;
|
||||
|
||||
typedef vtkm::cont::ArrayHandleConcatenate< ExtensionArrayType, SigInArrayType>
|
||||
ArrayConcat;
|
||||
typedef vtkm::cont::ArrayHandleConcatenate< ArrayConcat, ExtensionArrayType >
|
||||
ArrayConcat2;
|
||||
|
||||
PortalType leftExtendPortal = leftExtend.GetPortalControl();
|
||||
PortalType rightExtendPortal = rightExtend.GetPortalControl();
|
||||
SigInPortalConstType sigInPortal = sigIn.GetPortalConstControl();
|
||||
vtkm::Id sigInLen = sigIn.GetNumberOfValues();
|
||||
|
||||
switch( leftExtMethod )
|
||||
{
|
||||
case vtkm::worklet::wavelets::SYMH:
|
||||
{
|
||||
for( vtkm::Id count = 0; count < addLen; count++ )
|
||||
leftExtendPortal.Set( count, sigInPortal.Get( addLen - count - 1) );
|
||||
break;
|
||||
}
|
||||
case vtkm::worklet::wavelets::SYMW:
|
||||
{
|
||||
for( vtkm::Id count = 0; count < addLen; count++ )
|
||||
leftExtendPortal.Set( count, sigInPortal.Get( addLen - count ) );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// throw out an error
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch( rightExtMethod )
|
||||
{
|
||||
case vtkm::worklet::wavelets::SYMH:
|
||||
{
|
||||
for( vtkm::Id count = 0; count < addLen; count++ )
|
||||
rightExtendPortal.Set( count, sigInPortal.Get( sigInLen - count - 1 ) );
|
||||
break;
|
||||
}
|
||||
case SYMW:
|
||||
{
|
||||
for( vtkm::Id count = 0; count < addLen; count++ )
|
||||
rightExtendPortal.Set( count, sigInPortal.Get( sigInLen - count - 2 ) );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// throw out an error
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayConcat leftOn( leftExtend, sigIn );
|
||||
ArrayConcat2 rightOn(leftOn, rightExtend );
|
||||
vtkm::cont::DeviceAdapterAlgorithm< VTKM_DEFAULT_DEVICE_ADAPTER_TAG>::Copy
|
||||
( rightOn, sigOut );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Func:
|
||||
// Performs one level of 1D discrete wavelet transform
|
||||
// It takes care of boundary conditions, etc.
|
||||
template< typename SignalArrayType, typename CoeffArrayType>
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
vtkm::Id DWT1D( const SignalArrayType &sigIn, // Input
|
||||
CoeffArrayType &coeffOut, // Output: cA followed by cD
|
||||
vtkm::Id L[3] ) // Output: how many cA and cD.
|
||||
{
|
||||
|
||||
vtkm::Id sigInLen = sigIn.GetNumberOfValues();
|
||||
if( GetWaveletMaxLevel( sigInLen ) < 1 )
|
||||
{
|
||||
// throw an error
|
||||
std::cerr << "Cannot transform signal of length " << sigInLen << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
L[0] = WaveletBase::GetApproxLength( sigInLen );
|
||||
L[1] = WaveletBase::GetDetailLength( sigInLen );
|
||||
L[2] = sigInLen;
|
||||
|
||||
VTKM_ASSERT( L[0] + L[1] == L[2] );
|
||||
|
||||
vtkm::Id filterLen = WaveletBase::filter->GetFilterLength();
|
||||
|
||||
bool doSymConv = false;
|
||||
if( WaveletBase::filter->isSymmetric() )
|
||||
{
|
||||
if( ( WaveletBase::wmode == SYMW && ( filterLen % 2 != 0 ) ) ||
|
||||
( WaveletBase::wmode == SYMH && ( filterLen % 2 == 0 ) ) )
|
||||
doSymConv = true;
|
||||
}
|
||||
|
||||
vtkm::Id sigConvolvedLen = L[0] + L[1]; // approx + detail coeffs
|
||||
vtkm::Id addLen; // for extension
|
||||
bool oddLow = true;
|
||||
bool oddHigh = true;
|
||||
if( filterLen % 2 != 0 )
|
||||
oddLow = false;
|
||||
if( doSymConv )
|
||||
{
|
||||
addLen = filterLen / 2;
|
||||
if( sigInLen % 2 != 0 )
|
||||
sigConvolvedLen += 1;
|
||||
}
|
||||
else
|
||||
addLen = filterLen - 1;
|
||||
|
||||
vtkm::Id sigExtendedLen = sigInLen + 2 * addLen;
|
||||
|
||||
typedef typename SignalArrayType::ValueType SigInValueType;
|
||||
typedef vtkm::cont::ArrayHandle<SigInValueType> SignalArrayTypeBasic;
|
||||
|
||||
SignalArrayTypeBasic sigInExtended;
|
||||
|
||||
this->Extend1D( sigIn, sigInExtended, addLen, WaveletBase::wmode, WaveletBase::wmode );
|
||||
VTKM_ASSERT( sigInExtended.GetNumberOfValues() == sigExtendedLen );
|
||||
|
||||
// Coefficients in coeffOutTmp are interleaving,
|
||||
// e.g. cA are at 0, 2, 4...; cD are at 1, 3, 5...
|
||||
typedef typename CoeffArrayType::ValueType CoeffOutValueType;
|
||||
typedef vtkm::cont::ArrayHandle< CoeffOutValueType > CoeffOutArrayBasic;
|
||||
CoeffOutArrayBasic coeffOutTmp;
|
||||
|
||||
|
||||
// initialize a worklet
|
||||
vtkm::worklet::wavelets::ForwardTransform forwardTransform;
|
||||
forwardTransform.SetFilterLength( filterLen );
|
||||
forwardTransform.SetCoeffLength( L[0], L[1] );
|
||||
forwardTransform.SetOddness( oddLow, oddHigh );
|
||||
|
||||
vtkm::worklet::DispatcherMapField<vtkm::worklet::wavelets::ForwardTransform>
|
||||
dispatcher(forwardTransform);
|
||||
dispatcher.Invoke( sigInExtended,
|
||||
WaveletBase::filter->GetLowDecomposeFilter(),
|
||||
WaveletBase::filter->GetHighDecomposeFilter(),
|
||||
coeffOutTmp );
|
||||
|
||||
// Separate cA and cD.
|
||||
typedef vtkm::cont::ArrayHandleCounting< vtkm::Id > IdArrayType;
|
||||
typedef vtkm::cont::ArrayHandlePermutation< IdArrayType, CoeffArrayType > PermutArrayType;
|
||||
|
||||
IdArrayType approxIndices( 0, 2, L[0] );
|
||||
IdArrayType detailIndices( 1, 2, L[1] );
|
||||
PermutArrayType cATmp( approxIndices, coeffOutTmp );
|
||||
PermutArrayType cDTmp( detailIndices, coeffOutTmp );
|
||||
|
||||
typedef vtkm::cont::ArrayHandleConcatenate< PermutArrayType, PermutArrayType >
|
||||
PermutArrayConcatenated;
|
||||
PermutArrayConcatenated coeffOutConcat( cATmp, cDTmp );
|
||||
|
||||
vtkm::cont::DeviceAdapterAlgorithm< VTKM_DEFAULT_DEVICE_ADAPTER_TAG>::Copy(
|
||||
coeffOutConcat, coeffOut );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Func:
|
||||
// Performs one level of inverse wavelet transform
|
||||
// It takes care of boundary conditions, etc.
|
||||
template< typename CoeffArrayType, typename SignalArrayType>
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
vtkm::Id IDWT1D( const CoeffArrayType &coeffIn, // Input, cA followed by cD
|
||||
const vtkm::Id L[3], // Input, how many cA and cD
|
||||
SignalArrayType &sigOut ) // Output
|
||||
{
|
||||
#if 0
|
||||
std::cerr << "coeffIn len = " << coeffIn.GetNumberOfValues() << std::endl;
|
||||
std::cerr << L[0] << ", " << L[1] << ", " << L[2] << std::endl;
|
||||
#endif
|
||||
|
||||
VTKM_ASSERT( coeffIn.GetNumberOfValues() == L[2] );
|
||||
|
||||
vtkm::Id filterLen = WaveletBase::filter->GetFilterLength();
|
||||
bool doSymConv = false;
|
||||
vtkm::worklet::wavelets::DWTMode cALeftMode = WaveletBase::wmode;
|
||||
vtkm::worklet::wavelets::DWTMode cARightMode = WaveletBase::wmode;
|
||||
vtkm::worklet::wavelets::DWTMode cDLeftMode = WaveletBase::wmode;
|
||||
vtkm::worklet::wavelets::DWTMode cDRightMode = WaveletBase::wmode;
|
||||
|
||||
if( WaveletBase::filter->isSymmetric() )
|
||||
{
|
||||
if(( WaveletBase::wmode == SYMW && (filterLen % 2 != 0) ) ||
|
||||
( WaveletBase::wmode == SYMH && (filterLen % 2 == 0) ) )
|
||||
{
|
||||
doSymConv = true;
|
||||
|
||||
if( WaveletBase::wmode == SYMH )
|
||||
{
|
||||
cDLeftMode = ASYMH;
|
||||
if( L[2] % 2 != 0 )
|
||||
{
|
||||
cARightMode = SYMW;
|
||||
cDRightMode = ASYMW;
|
||||
}
|
||||
else
|
||||
cDRightMode = ASYMH;
|
||||
}
|
||||
else
|
||||
{
|
||||
cDLeftMode = SYMH;
|
||||
if( L[2] % 2 != 0 )
|
||||
{
|
||||
cARightMode = SYMW;
|
||||
cDRightMode = SYMH;
|
||||
}
|
||||
else
|
||||
cARightMode = SYMH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vtkm::Id cATempLen, cDTempLen, reconTempLen;
|
||||
vtkm::Id addLen = 0;
|
||||
vtkm::Id cDPadLen = 0;
|
||||
if( doSymConv ) // extend cA and cD
|
||||
{
|
||||
addLen = filterLen / 4;
|
||||
if( (L[0] > L[1]) && (WaveletBase::wmode == SYMH) )
|
||||
cDPadLen = L[0];
|
||||
cATempLen = L[0] + 2 * addLen;
|
||||
cDTempLen = cATempLen; // same length
|
||||
}
|
||||
else // not extend cA and cD
|
||||
{
|
||||
cATempLen = L[0];
|
||||
cDTempLen = L[1];
|
||||
}
|
||||
reconTempLen = L[2];
|
||||
if( reconTempLen % 2 != 0 )
|
||||
reconTempLen++;
|
||||
|
||||
typedef vtkm::cont::ArrayHandleCounting< vtkm::Id > IdArrayType;
|
||||
typedef vtkm::cont::ArrayHandlePermutation< IdArrayType, CoeffArrayType > PermutArrayType;
|
||||
|
||||
// Separate cA and cD
|
||||
IdArrayType approxIndices( 0, 1, L[0] );
|
||||
IdArrayType detailIndices( L[0], 1, L[1] );
|
||||
PermutArrayType cA( approxIndices, coeffIn );
|
||||
PermutArrayType cD( detailIndices, coeffIn );
|
||||
|
||||
|
||||
typedef typename CoeffArrayType::ValueType CoeffValueType;
|
||||
typedef vtkm::cont::ArrayHandle< CoeffValueType > CoeffArrayBasic;
|
||||
typedef vtkm::cont::ArrayHandle< CoeffValueType > ExtensionArrayType;
|
||||
|
||||
CoeffArrayBasic cATemp, cDTemp;
|
||||
|
||||
|
||||
if( doSymConv ) // Actually extend cA and cD
|
||||
{
|
||||
this->Extend1D( cA, cATemp, addLen, cALeftMode, cARightMode );
|
||||
if( cDPadLen > 0 )
|
||||
{
|
||||
// Add back the missing final cD: 0.0
|
||||
ExtensionArrayType singleValArray;
|
||||
singleValArray.Allocate(1);
|
||||
singleValArray.GetPortalControl().Set(0, 0.0);
|
||||
vtkm::cont::ArrayHandleConcatenate< PermutArrayType, ExtensionArrayType >
|
||||
cDPad( cD, singleValArray );
|
||||
|
||||
this->Extend1D( cDPad, cDTemp, addLen, cDLeftMode, cDRightMode );
|
||||
}
|
||||
else
|
||||
{
|
||||
this->Extend1D( cD, cDTemp, addLen, cDLeftMode, cDRightMode );
|
||||
|
||||
// Attached an zero if cDTemp is shorter than cDTempLen
|
||||
if( cDTemp.GetNumberOfValues() != cDTempLen )
|
||||
{
|
||||
VTKM_ASSERT( cDTemp.GetNumberOfValues() == cDTempLen - 1 );
|
||||
CoeffArrayBasic singleValArray;
|
||||
singleValArray.Allocate(1);
|
||||
singleValArray.GetPortalControl().Set(0, 0.0);
|
||||
vtkm::cont::ArrayHandleConcatenate< CoeffArrayBasic, CoeffArrayBasic>
|
||||
concat1( cDTemp, singleValArray );
|
||||
CoeffArrayBasic cDStorage;
|
||||
vtkm::cont::DeviceAdapterAlgorithm< VTKM_DEFAULT_DEVICE_ADAPTER_TAG >::Copy
|
||||
( concat1, cDStorage );
|
||||
cDTemp = cDStorage;
|
||||
}
|
||||
}
|
||||
} // end if( doSymConv )
|
||||
else // Make cATemp and cDTemp from cA and cD
|
||||
{
|
||||
vtkm::cont::DeviceAdapterAlgorithm< VTKM_DEFAULT_DEVICE_ADAPTER_TAG >::Copy
|
||||
(cA, cATemp );
|
||||
vtkm::cont::DeviceAdapterAlgorithm< VTKM_DEFAULT_DEVICE_ADAPTER_TAG >::Copy
|
||||
(cD, cDTemp );
|
||||
}
|
||||
|
||||
#if 0
|
||||
std::cerr << "cATemp has length: " << cATemp.GetNumberOfValues() << std::endl;
|
||||
for( vtkm::Id i = 0; i < cATemp.GetNumberOfValues(); i++ )
|
||||
std::cout << cATemp.GetPortalConstControl().Get(i) << std::endl;
|
||||
std::cerr << "cDTemp has length: " << cDTemp.GetNumberOfValues() << std::endl;
|
||||
for( vtkm::Id i = 0; i < cDTemp.GetNumberOfValues(); i++ )
|
||||
std::cout << cDTemp.GetPortalConstControl().Get(i) << std::endl;
|
||||
#endif
|
||||
|
||||
if( filterLen % 2 != 0 )
|
||||
{
|
||||
vtkm::cont::ArrayHandleConcatenate< CoeffArrayBasic, CoeffArrayBasic>
|
||||
coeffInExtended( cATemp, cDTemp );
|
||||
|
||||
// Initialize a worklet
|
||||
vtkm::worklet::wavelets::InverseTransformOdd inverseXformOdd;
|
||||
inverseXformOdd.SetFilterLength( filterLen );
|
||||
inverseXformOdd.SetCALength( L[0], cATempLen );
|
||||
vtkm::worklet::DispatcherMapField< vtkm::worklet::wavelets::InverseTransformOdd >
|
||||
dispatcher( inverseXformOdd );
|
||||
dispatcher.Invoke( coeffInExtended,
|
||||
WaveletBase::filter->GetLowReconstructFilter(),
|
||||
WaveletBase::filter->GetHighReconstructFilter(),
|
||||
sigOut );
|
||||
#if 0
|
||||
std::cerr << "coeffInExtended len = " << coeffInExtended.GetNumberOfValues() << std::endl;
|
||||
std::cerr << sigOut.GetNumberOfValues() << ", " << L[2] << std::endl;
|
||||
#endif
|
||||
|
||||
VTKM_ASSERT( sigOut.GetNumberOfValues() >= L[2] );
|
||||
sigOut.Shrink( L[2] );
|
||||
}
|
||||
else
|
||||
{
|
||||
// need to implement the even filter length worklet first
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
} // function IDWT1D
|
||||
|
||||
|
||||
}; // class WaveletDWT
|
||||
|
||||
} // namespace wavelets
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
182
vtkm/worklet/wavelets/WaveletFilter.h
Normal file
182
vtkm/worklet/wavelets/WaveletFilter.h
Normal file
@ -0,0 +1,182 @@
|
||||
//============================================================================
|
||||
// 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_wavelets_waveletfilter_h
|
||||
#define vtk_m_worklet_wavelets_waveletfilter_h
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
|
||||
#include <vtkm/worklet/wavelets/FilterBanks.h>
|
||||
|
||||
#include <vtkm/Math.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace worklet {
|
||||
|
||||
namespace wavelets {
|
||||
|
||||
// Wavelet filter class;
|
||||
// functionally equivalent to WaveFiltBase and its subclasses in VAPoR.
|
||||
class WaveletFilter
|
||||
{
|
||||
public:
|
||||
// constructor
|
||||
WaveletFilter( const std::string &wname )
|
||||
{
|
||||
lowDecomposeFilter = highDecomposeFilter =
|
||||
lowReconstructFilter = highReconstructFilter = NULL;
|
||||
this->filterLength = 0;
|
||||
if( wname.compare("CDF9/7") == 0 )
|
||||
{
|
||||
this->symmetricity= true;
|
||||
this->filterLength = 9;
|
||||
this->AllocateFilterMemory();
|
||||
wrev( vtkm::worklet::wavelets::hm4_44, lowDecomposeFilter, filterLength );
|
||||
qmf_wrev( vtkm::worklet::wavelets::h4, highDecomposeFilter, filterLength );
|
||||
verbatim_copy( vtkm::worklet::wavelets::h4, lowReconstructFilter, filterLength );
|
||||
qmf_even( vtkm::worklet::wavelets::hm4_44, highReconstructFilter, filterLength );
|
||||
}
|
||||
else if( wname.compare("CDF5/3") == 0 )
|
||||
{
|
||||
this->symmetricity = true;
|
||||
this->filterLength = 5;
|
||||
this->AllocateFilterMemory();
|
||||
wrev( vtkm::worklet::wavelets::hm2_22, lowDecomposeFilter, filterLength );
|
||||
qmf_wrev( vtkm::worklet::wavelets::h2+6, highDecomposeFilter, filterLength );
|
||||
verbatim_copy( vtkm::worklet::wavelets::h2+6, lowReconstructFilter, filterLength );
|
||||
qmf_even( vtkm::worklet::wavelets::hm2_22, highReconstructFilter, filterLength );
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Not supported wavelet kernel: " << wname << std::endl;
|
||||
// throw an error here
|
||||
}
|
||||
}
|
||||
|
||||
// destructor
|
||||
virtual ~WaveletFilter()
|
||||
{
|
||||
if( lowDecomposeFilter ) delete[] lowDecomposeFilter;
|
||||
if( highDecomposeFilter ) delete[] highDecomposeFilter;
|
||||
if( lowReconstructFilter ) delete[] lowReconstructFilter;
|
||||
if( highReconstructFilter ) delete[] highReconstructFilter;
|
||||
}
|
||||
|
||||
vtkm::Id GetFilterLength() { return this->filterLength; }
|
||||
bool isSymmetric() { return this->symmetricity; }
|
||||
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Float64> FilterType;
|
||||
FilterType GetLowDecomposeFilter() const
|
||||
{
|
||||
return vtkm::cont::make_ArrayHandle( lowDecomposeFilter, filterLength );
|
||||
}
|
||||
FilterType GetHighDecomposeFilter() const
|
||||
{
|
||||
return vtkm::cont::make_ArrayHandle( highDecomposeFilter, filterLength );
|
||||
}
|
||||
FilterType GetLowReconstructFilter() const
|
||||
{
|
||||
return vtkm::cont::make_ArrayHandle( lowReconstructFilter, filterLength);
|
||||
}
|
||||
FilterType GetHighReconstructFilter() const
|
||||
{
|
||||
return vtkm::cont::make_ArrayHandle( highReconstructFilter, filterLength );
|
||||
}
|
||||
|
||||
protected:
|
||||
bool symmetricity;
|
||||
vtkm::Id filterLength;
|
||||
vtkm::Float64* lowDecomposeFilter;
|
||||
vtkm::Float64* highDecomposeFilter;
|
||||
vtkm::Float64* lowReconstructFilter;
|
||||
vtkm::Float64* highReconstructFilter;
|
||||
|
||||
void AllocateFilterMemory()
|
||||
{
|
||||
lowDecomposeFilter = new vtkm::Float64[ this->filterLength ];
|
||||
highDecomposeFilter = new vtkm::Float64[ this->filterLength ];
|
||||
lowReconstructFilter = new vtkm::Float64[ this->filterLength ];
|
||||
highReconstructFilter = new vtkm::Float64[ this->filterLength ];
|
||||
}
|
||||
|
||||
// Flipping operation; helper function to initialize a filter.
|
||||
void wrev( const vtkm::Float64* sigIn, vtkm::Float64* sigOut, vtkm::Id sigLength )
|
||||
{
|
||||
for( vtkm::Id count = 0; count < sigLength; count++)
|
||||
sigOut[count] = sigIn[sigLength - count - 1];
|
||||
}
|
||||
|
||||
// Quadrature mirror filtering operation: helper function to initialize a filter.
|
||||
void qmf_even ( const vtkm::Float64* sigIn, vtkm::Float64* sigOut, vtkm::Id sigLength )
|
||||
{
|
||||
for (vtkm::Id count = 0; count < sigLength; count++)
|
||||
{
|
||||
sigOut[count] = sigIn[sigLength - count - 1];
|
||||
|
||||
if (sigLength % 2 == 0) {
|
||||
if (count % 2 != 0)
|
||||
sigOut[count] = -1.0 * sigOut[count];
|
||||
}
|
||||
else {
|
||||
if (count % 2 == 0)
|
||||
sigOut[count] = -1.0 * sigOut[count];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flipping and QMF at the same time: helper function to initialize a filter.
|
||||
void qmf_wrev ( const vtkm::Float64* sigIn, vtkm::Float64* sigOut, vtkm::Id sigLength )
|
||||
{
|
||||
for (vtkm::Id count = 0; count < sigLength; count++) {
|
||||
sigOut[count] = sigIn[sigLength - count - 1];
|
||||
|
||||
if (sigLength % 2 == 0) {
|
||||
if (count % 2 != 0)
|
||||
sigOut[count] = -1 * sigOut[count];
|
||||
}
|
||||
else {
|
||||
if (count % 2 == 0)
|
||||
sigOut[count] = -1 * sigOut[count];
|
||||
}
|
||||
}
|
||||
|
||||
vtkm::Float64 tmp;
|
||||
for (vtkm::Id count = 0; count < sigLength/2; count++) {
|
||||
tmp = sigOut[count];
|
||||
sigOut[count] = sigOut[sigLength - count - 1];
|
||||
sigOut[sigLength - count - 1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// Verbatim Copying: helper function to initialize a filter.
|
||||
void verbatim_copy ( const vtkm::Float64* sigIn, vtkm::Float64* sigOut, vtkm::Id sigLength )
|
||||
{
|
||||
for (vtkm::Id count = 0; count < sigLength; count++)
|
||||
sigOut[count] = sigIn[count];
|
||||
}
|
||||
}; // class WaveletFilter.
|
||||
|
||||
} // namespace wavelets.
|
||||
|
||||
|
||||
} // namespace worklet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif
|
@ -28,6 +28,7 @@
|
||||
|
||||
namespace vtkm {
|
||||
namespace worklet {
|
||||
namespace wavelets {
|
||||
|
||||
// Worklet: perform a simple forward transform
|
||||
class ForwardTransform: public vtkm::worklet::WorkletMapField
|
||||
@ -227,9 +228,10 @@ private:
|
||||
vtkm::Id cALen; // Number of actual cAs
|
||||
vtkm::Id cALenExtended; // Number of extended cA at the beginning of input array
|
||||
|
||||
}; // Finish class ForwardTransform
|
||||
}; // class ForwardTransform
|
||||
|
||||
} // Finish namespace worlet
|
||||
} // Finish namespace vtkm
|
||||
} // namespace wavelets
|
||||
} // namespace worlet
|
||||
} // namespace vtkm
|
||||
|
||||
#endif // vtk_m_worklet_Wavelets_h
|
Loading…
Reference in New Issue
Block a user