diff --git a/packages/dicom/CMakeLists.txt b/packages/dicom/CMakeLists.txt index 7bc34004c..14baf4e32 100644 --- a/packages/dicom/CMakeLists.txt +++ b/packages/dicom/CMakeLists.txt @@ -5,13 +5,4 @@ set(CMAKE_CXX_STANDARD 17) add_subdirectory(gdcm) add_subdirectory(dcmtk) - -find_package(ITK REQUIRED - COMPONENTS ITKCommon - ITKGDCM - WebAssemblyInterface - ) -include(${ITK_USE_FILE}) - -add_executable(sort-dicom-series sort-dicom-series.cxx) -target_link_libraries(sort-dicom-series PUBLIC ${ITK_LIBRARIES}) +add_subdirectory(sort-dicom-series) diff --git a/packages/dicom/python/itkwasm-dicom-wasi/test/test_sort_dicom_series.py b/packages/dicom/python/itkwasm-dicom-wasi/test/test_sort_dicom_series.py new file mode 100644 index 000000000..f7662ba20 --- /dev/null +++ b/packages/dicom/python/itkwasm-dicom-wasi/test/test_sort_dicom_series.py @@ -0,0 +1,15 @@ +from pathlib import Path + + +def test_sort_dicom_series(): + from itkwasm_dicom_wasi import sort_dicom_series + + file_name = "ImageOrientation.1.dcm" + test_file_path = Path( + "..", "..", "test", "data", "input", "DicomImageOrientationTest", file_name + ) + + assert test_file_path.exists() + + output_text = sort_dicom_series([test_file_path]) + assert output_text diff --git a/packages/dicom/sort-dicom-series.cxx b/packages/dicom/sort-dicom-series.cxx deleted file mode 100644 index b2dce94be..000000000 --- a/packages/dicom/sort-dicom-series.cxx +++ /dev/null @@ -1,35 +0,0 @@ -/*========================================================================= - * - * 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. - * - *=========================================================================*/ -#include "itkPipeline.h" -#include "itkInputTextStream.h" -#include "itkOutputTextStream.h" - -int main (int argc, char * argv[]) -{ - itk::wasm::Pipeline pipeline("sort-dicom-series", "Sort a DICOM image series their spatial order and spatial metadata.", argc, argv); - - itk::wasm::InputTextStream dicomSeries; - - itk::wasm::OutputTextStream imageInformation;; - - ITK_WASM_PARSE(pipeline); - - // { order: [1.0, 2.0, 3.0], origin: [0.0, 0.0, 0.0], spacing: [1.0, 1.0, 1.0], direction: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0] } - - return EXIT_SUCCESS; -} diff --git a/packages/dicom/sort-dicom-series/CMakeLists.txt b/packages/dicom/sort-dicom-series/CMakeLists.txt new file mode 100644 index 000000000..81bc3fbac --- /dev/null +++ b/packages/dicom/sort-dicom-series/CMakeLists.txt @@ -0,0 +1,20 @@ +find_package(ITK REQUIRED + COMPONENTS ITKCommon + ITKGDCM + WebAssemblyInterface +) +include(${ITK_USE_FILE}) + +add_executable(sort-dicom-series sort-dicom-series.cxx) +target_link_libraries(sort-dicom-series PUBLIC ${ITK_LIBRARIES}) + +enable_testing() + +add_test(NAME sort-dicom-series-help COMMAND sort-dicom-series --help) + +add_test(NAME sort-dicom-series-smoke + COMMAND sort-dicom-series --files + ${CMAKE_CURRENT_SOURCE_DIR}/test/data/input/DicomImageOrientationTest/ImageOrientation.1.dcm + ${CMAKE_CURRENT_SOURCE_DIR}/test/data/input/DicomImageOrientationTest/ImageOrientation.2.dcm + ${CMAKE_CURRENT_SOURCE_DIR}/test/data/input/DicomImageOrientationTest/ImageOrientation.3.dcm +) \ No newline at end of file diff --git a/packages/dicom/sort-dicom-series/sort-dicom-series.cxx b/packages/dicom/sort-dicom-series/sort-dicom-series.cxx new file mode 100644 index 000000000..8db825bf6 --- /dev/null +++ b/packages/dicom/sort-dicom-series/sort-dicom-series.cxx @@ -0,0 +1,52 @@ +/*========================================================================= + + * 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. + * + *=========================================================================*/ + +#include "itkPipeline.h" +#include "itkOutputTextStream.h" + +#include "rapidjson/document.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" + +int main(int argc, char *argv[]) +{ + itk::wasm::Pipeline pipeline("sort-dicom-series", "Group DICOM files into volumes", argc, argv); + + std::vector files; + pipeline.add_option("--files", files, "DICOM files to group")->required()->check(CLI::ExistingFile)->type_size(1, -1)->type_name("INPUT_BINARY_FILE"); + + itk::wasm::OutputTextStream volumes; + pipeline.add_option("volumes", volumes, "Files grouped into volumes")->required()->type_name("OUTPUT_JSON"); + + ITK_WASM_PARSE(pipeline); + + rapidjson::Document volumesJson; + volumesJson.SetObject(); + rapidjson::Document::AllocatorType &allocator = volumesJson.GetAllocator(); + + rapidjson::Value almostEqualValue; + almostEqualValue.SetBool(false); + volumesJson.AddMember("almostEqual", almostEqualValue, allocator); + + rapidjson::StringBuffer stringBuffer; + rapidjson::Writer writer(stringBuffer); + volumesJson.Accept(writer); + volumes.Get() << stringBuffer.GetString(); + + return EXIT_SUCCESS; +} diff --git a/packages/dicom/typescript/src/index-node-only.ts b/packages/dicom/typescript/src/index-node-only.ts index 8d75fbcb1..fb2cf9f44 100644 --- a/packages/dicom/typescript/src/index-node-only.ts +++ b/packages/dicom/typescript/src/index-node-only.ts @@ -60,3 +60,13 @@ export type { ReadImageDicomFileSeriesNodeOptions } import readImageDicomFileSeriesNode from './read-image-dicom-file-series-node.js' export { readImageDicomFileSeriesNode } + + +import SortDicomSeriesNodeResult from './sort-dicom-series-node-result.js' +export type { SortDicomSeriesNodeResult } + +import SortDicomSeriesNodeOptions from './sort-dicom-series-node-options.js' +export type { SortDicomSeriesNodeOptions } + +import sortDicomSeriesNode from './sort-dicom-series-node.js' +export { sortDicomSeriesNode } diff --git a/packages/dicom/typescript/src/index-only.ts b/packages/dicom/typescript/src/index-only.ts index b3758756a..f78811a9c 100644 --- a/packages/dicom/typescript/src/index-only.ts +++ b/packages/dicom/typescript/src/index-only.ts @@ -66,3 +66,13 @@ export { readImageDicomFileSeries } import readImageDicomFileSeriesWorkerFunction from './read-image-dicom-file-series-worker-function.js' export { readImageDicomFileSeriesWorkerFunction } + + +import SortDicomSeriesResult from "./sort-dicom-series-result.js"; +export type { SortDicomSeriesResult }; + +import SortDicomSeriesOptions from "./sort-dicom-series-options.js"; +export type { SortDicomSeriesOptions }; + +import sortDicomSeries from "./sort-dicom-series.js"; +export { sortDicomSeries }; diff --git a/packages/dicom/typescript/test/node/sort-dicom-series.js b/packages/dicom/typescript/test/node/sort-dicom-series.js new file mode 100644 index 000000000..13fcf989e --- /dev/null +++ b/packages/dicom/typescript/test/node/sort-dicom-series.js @@ -0,0 +1,19 @@ +import test from "ava"; +import path from "path"; +import glob from "glob"; + +import { sortDicomSeriesNode } from "../../dist/index-node.js"; + +const testDataInputDirectory = path.resolve("..", "test", "data", "input"); +const testSeriesDirectory = path.resolve( + testDataInputDirectory, + "DicomImageOrientationTest", +); +const testDicomSeriesFiles = glob.sync(`${testSeriesDirectory}/*.dcm`); + +test("Test reading a DICOM file", async (t) => { + const { volumes } = await sortDicomSeriesNode({ + files: testDicomSeriesFiles, + }); + t.assert(!!volumes); +});