Skip to content

Commit

Permalink
Merge pull request #1170 from thewtex/transform-interface
Browse files Browse the repository at this point in the history
transform interface
  • Loading branch information
thewtex authored Jul 3, 2024
2 parents d62b523 + 669928a commit 83772f2
Show file tree
Hide file tree
Showing 21 changed files with 1,764 additions and 349 deletions.
4 changes: 3 additions & 1 deletion docs/cxx/interface_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,6 @@ For binding generation, set the `type_name` an the options accordingly. The type
- `INPUT_MESH`
- `OUTPUT_MESH`
- `INPUT_POLYDATA`
- `OUTPUT_POLYDATA`
- `OUTPUT_POLYDATA`
- `INPUT_TRANSFORM`
- `OUTPUT_TRANSFORM`
121 changes: 121 additions & 0 deletions include/itkInputTransform.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*=========================================================================
*
* Copyright NumFOCUS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
#ifndef itkInputTransform_h
#define itkInputTransform_h

#include "itkPipeline.h"

#ifndef ITK_WASM_NO_MEMORY_IO
#include "itkWasmExports.h"
#include "itkWasmTransform.h"
#include "itkWasmTransformToTransformFilter.h"
#endif
#ifndef ITK_WASM_NO_FILESYSTEM_IO
#include "itkTransformFileReader.h"
#endif

namespace itk
{
namespace wasm
{

/**
*\class InputTransform
* \brief Input transform for an itk::wasm::Pipeline
*
* This transform is read from the filesystem or memory when ITK_WASM_PARSE_ARGS is called.
*
* Call `Get()` to get the TTransform * to use an input to a pipeline.
*
* \ingroup WebAssemblyInterface
*/
template <typename TTransform>
class ITK_TEMPLATE_EXPORT InputTransform
{
public:
using TransformType = TTransform;

void Set(const TransformType * transform) {
this->m_Transform = transform;
}

const TransformType * Get() const {
return this->m_Transform.GetPointer();
}

InputTransform() = default;
~InputTransform() = default;
protected:
typename TTransform::ConstPointer m_Transform;
};


template <typename TTransform>
bool lexical_cast(const std::string &input, InputTransform<TTransform> &inputTransform)
{
if (input.empty())
{
return false;
}

if (wasm::Pipeline::get_use_memory_io())
{
#ifndef ITK_WASM_NO_MEMORY_IO
using WasmTransformToTransformFilterType = WasmTransformToTransformFilter<TTransform>;
auto wasmTransformToTransformFilter = WasmTransformToTransformFilterType::New();
auto wasmTransform = WasmTransformToTransformFilterType::WasmTransformType::New();
const unsigned int index = std::stoi(input);
auto json = getMemoryStoreInputJSON(0, index);
wasmTransform->SetJSON(json);
wasmTransformToTransformFilter->SetInput(wasmTransform);
wasmTransformToTransformFilter->Update();
inputTransform.Set(wasmTransformToTransformFilter->GetOutput());
#else
return false;
#endif
}
else
{
#ifndef ITK_WASM_NO_FILESYSTEM_IO
using ParametersValueType = typename TTransform::ParametersValueType;
using ReaderType = itk::TransformFileReaderTemplate<ParametersValueType>;
auto reader = ReaderType::New();
reader->SetFileName(input);
reader->Update();
auto transformList = reader->GetTransformList();
if (transformList->empty())
{
return false;
}
auto transform = dynamic_cast<const TTransform *>(transformList->front().GetPointer());
if (!transform)
{
return false;
}
inputTransform.Set(transform);
#else
return false;
#endif
}
return true;
}

} // end namespace wasm
} // end namespace itk

#endif
162 changes: 162 additions & 0 deletions include/itkOutputTransform.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*=========================================================================
*
* Copyright NumFOCUS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
#ifndef itkOutputTransform_h
#define itkOutputTransform_h

#include "itkPipeline.h"

#ifndef ITK_WASM_NO_MEMORY_IO
#include "itkWasmExports.h"
#include "itkWasmTransform.h"
#include "itkTransformToWasmTransformFilter.h"
#include "itkCompositeTransform.h"
#include "itkCompositeTransformIOHelper.h"
#endif
#ifndef ITK_WASM_NO_FILESYSTEM_IO
#include "itkTransformFileWriter.h"
#endif

namespace itk
{
namespace wasm
{
/**
*\class OutputTransform
* \brief Output transform for an itk::wasm::Pipeline
*
* This transform is written to the filesystem or memory when it goes out of scope.
*
* Call `GetTransform()` to get the TTransform * to use an input to a pipeline.
*
* \ingroup WebAssemblyInterface
*/
template <typename TTransform>
class ITK_TEMPLATE_EXPORT OutputTransform
{
public:
using TransformType = TTransform;

void Set(const TransformType * transform) {
this->m_Transform = transform;
}

const TransformType * Get() const {
return this->m_Transform.GetPointer();
}

/** FileName or output index. */
void SetIdentifier(const std::string & identifier)
{
this->m_Identifier = identifier;
}
const std::string & GetIdentifier() const
{
return this->m_Identifier;
}

OutputTransform() = default;
~OutputTransform() {
if(wasm::Pipeline::get_use_memory_io())
{
#ifndef ITK_WASM_NO_MEMORY_IO
if (!this->m_Transform.IsNull() && !this->m_Identifier.empty())
{
using TransformToWasmTransformFilterType = TransformToWasmTransformFilter<TransformType>;
auto transformToWasmTransformFilter = TransformToWasmTransformFilterType::New();
transformToWasmTransformFilter->SetTransform(this->m_Transform.GetPointer());
transformToWasmTransformFilter->Update();
auto wasmTransform = transformToWasmTransformFilter->GetOutput();
const auto index = std::stoi(this->m_Identifier);
setMemoryStoreOutputDataObject(0, index, wasmTransform);

using ParametersValueType = typename TransformType::ParametersValueType;
using FixedParametersValueType = typename TransformType::FixedParametersValueType;
using CompositeTransformType = CompositeTransform<ParametersValueType, TransformType::InputSpaceDimension>;
auto compositeTransform = dynamic_cast<const CompositeTransformType *>(wasmTransform->GetTransform());
if (compositeTransform)
{
unsigned int dataCount = 0;
CompositeTransformIOHelperTemplate<ParametersValueType> helper;
auto transformList = helper.GetTransformList(compositeTransform);
// composite transform
transformList.pop_front();
// iterate through the transform list and store each transfrom's fixed parameters and parameters
for (const auto & transform: transformList)
{
const auto fixedParamsAddress = reinterpret_cast< size_t >( transform->GetFixedParameters().data_block() );
const auto fixedParamsSize = transform->GetFixedParameters().Size() * sizeof(FixedParametersValueType);
setMemoryStoreOutputArray(0, index, dataCount, fixedParamsAddress, fixedParamsSize);
++dataCount;

const auto paramsAddress = reinterpret_cast< size_t >( transform->GetParameters().data_block() );
const auto paramsSize = transform->GetParameters().Size() * sizeof(ParametersValueType);
setMemoryStoreOutputArray(0, index, dataCount, paramsAddress, paramsSize);
++dataCount;
}
}
else
{
const auto fixedParamsAddress = reinterpret_cast< size_t >( wasmTransform->GetTransform()->GetFixedParameters().data_block() );
const auto fixedParamsSize = wasmTransform->GetTransform()->GetFixedParameters().Size() * sizeof(FixedParametersValueType);
setMemoryStoreOutputArray(0, index, 0, fixedParamsAddress, fixedParamsSize);

const auto paramsAddress = reinterpret_cast< size_t >( wasmTransform->GetTransform()->GetParameters().data_block() );
const auto paramsSize = wasmTransform->GetTransform()->GetParameters().Size() * sizeof(ParametersValueType);
setMemoryStoreOutputArray(0, index, 1, paramsAddress, paramsSize);
}
}
#else
std::cerr << "Memory IO not supported" << std::endl;
abort();
#endif
}
else
{
#ifndef ITK_WASM_NO_FILESYSTEM_IO
if (!this->m_Transform.IsNull() && !this->m_Identifier.empty())
{
using ParametersValueType = typename TransformType::ParametersValueType;
using WriterType = TransformFileWriterTemplate<ParametersValueType>;
auto writer = WriterType::New();
writer->SetFileName(this->m_Identifier);
writer->SetInput(this->m_Transform);
writer->Update();
}
#else
std::cerr << "Filesystem IO not supported" << std::endl;
abort();
#endif
}
}
protected:
typename TTransform::ConstPointer m_Transform;

std::string m_Identifier;
};

template <typename TTransform>
bool lexical_cast(const std::string &input, OutputTransform<TTransform> &outputTransform)
{
outputTransform.SetIdentifier(input);
return true;
}

} // namespace wasm
} // namespace itk

#endif
Loading

0 comments on commit 83772f2

Please sign in to comment.