├── .gitignore
├── PETTumorSegmentationEffect
├── Testing
│ └── CMakeLists.txt
├── PETTumorSegmentationEffect.png
└── CMakeLists.txt
├── PETTumorSegmentation
├── Testing
│ ├── CMakeLists.txt
│ └── Cxx
│ │ └── CMakeLists.txt
├── Resources
│ ├── Icons
│ │ └── PETTumorSegmentation.png
│ ├── qSlicerPETTumorSegmentationModule.qrc
│ └── UI
│ │ ├── qSlicerPETTumorSegmentationFooBarWidget.ui
│ │ └── qSlicerPETTumorSegmentationModuleWidget.ui
├── Logic
│ ├── instances.inc
│ ├── CMakeLists.txt
│ ├── itkCloneOSFGraphFilter.txx
│ ├── itkCloneOSFGraphFilter.h
│ ├── itkOSFGraphSource.h
│ ├── itkLOGISMOSOSFGraphSolverFilter.h
│ ├── itkMeshToOSFGraphFilter.h
│ ├── itkOSFGraphToOSFGraphFilter.h
│ ├── itkOSFGraphToMeshFilter.h
│ ├── itkCenterNormalColumnBuilderFilter.h
│ ├── itkSimpleOSFGraphBuilderFilter.h
│ ├── itkOSFGraphSource.txx
│ ├── itkSealingSegmentationMergerImageFilter.txx
│ ├── itkSealingSegmentationMergerImageFilter.h
│ ├── itkLOGISMOSOSFGraphSolverFilter.txx
│ ├── itkWorkers.h
│ ├── itkOSFSurface.h
│ ├── itkCenterNormalColumnBuilderFilter.txx
│ ├── itkMeshToOSFGraphFilter.txx
│ ├── itkOSFGraphToMeshFilter.txx
│ ├── itkOSFGraph.h
│ ├── itkSimpleOSFGraphBuilderFilter.txx
│ ├── itkOSFGraphToOSFGraphFilter.txx
│ ├── logismos_graph.cxx
│ ├── logismos_chunk_list.hxx
│ └── logismos_graph.hxx
├── MRML
│ ├── CMakeLists.txt
│ └── vtkMRMLPETTumorSegmentationParametersNode.h
├── CMakeLists.txt
├── qSlicerPETTumorSegmentationModule.h
└── qSlicerPETTumorSegmentationModule.cxx
├── PETTumorSegmentation.png
├── SegmentEditorPETTumorSegmentationEffect
├── PETTumorEffect.png
├── CMakeLists.txt
├── SegmentationCategoryTypeModifier-HeadAndNeckCancer.json
└── AnatomicRegionAndModifier-DICOM-HeadAndNeckCancer.json
├── README.md
├── Testing
├── CMakeLists.txt
└── SegmentEditorPETTumorSegmentationEffectSelfTest.py
├── CMakeLists.txt
└── License.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/settings.json
2 |
--------------------------------------------------------------------------------
/PETTumorSegmentationEffect/Testing/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # placeholder
2 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Testing/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(Cxx)
2 |
--------------------------------------------------------------------------------
/PETTumorSegmentation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QIICR/PETTumorSegmentation/HEAD/PETTumorSegmentation.png
--------------------------------------------------------------------------------
/PETTumorSegmentationEffect/PETTumorSegmentationEffect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QIICR/PETTumorSegmentation/HEAD/PETTumorSegmentationEffect/PETTumorSegmentationEffect.png
--------------------------------------------------------------------------------
/SegmentEditorPETTumorSegmentationEffect/PETTumorEffect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QIICR/PETTumorSegmentation/HEAD/SegmentEditorPETTumorSegmentationEffect/PETTumorEffect.png
--------------------------------------------------------------------------------
/PETTumorSegmentation/Resources/Icons/PETTumorSegmentation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QIICR/PETTumorSegmentation/HEAD/PETTumorSegmentation/Resources/Icons/PETTumorSegmentation.png
--------------------------------------------------------------------------------
/PETTumorSegmentation/Resources/qSlicerPETTumorSegmentationModule.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | Icons/PETTumorSegmentation.png
4 |
5 |
6 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/instances.inc:
--------------------------------------------------------------------------------
1 | #include "graph.h"
2 |
3 | #ifdef _MSC_VER
4 | #pragma warning(disable: 4661)
5 | #endif
6 |
7 | // Instantiations:
8 | // IMPORTANT:
9 | // flowtype should be 'larger' than tcaptype
10 | // tcaptype should be 'larger' than captype
11 |
12 | template class Graph;
13 | template class Graph;
14 | template class Graph;
15 | template class Graph;
16 |
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PETTumorSegmentation
2 | Slicer Extension for tumor and lymph node segmentation in PET scans
3 |
4 | Documentation: https://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/PETTumorSegmentation
5 |
6 | This work is funded in part by Quantitative Imaging to Assess Response in Cancer Therapy Trials NIH grant U01-CA140206 (PIs John Buatti, Tom Casavant, Michael Graham, Milan Sonka), Quantitative Image Informatics for Cancer Research (QIICR) NIH grant U24 CA180918, and Graph-based Medical Image Segmentation in 3D and 4D NIH grant R01 EB004640
7 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Testing/Cxx/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(KIT qSlicer${MODULE_NAME}Module)
2 |
3 | #-----------------------------------------------------------------------------
4 | set(KIT_TEST_SRCS
5 | #qSlicer${MODULE_NAME}ModuleTest.cxx
6 | )
7 |
8 | #-----------------------------------------------------------------------------
9 | slicerMacroConfigureModuleCxxTestDriver(
10 | NAME ${KIT}
11 | SOURCES ${KIT_TEST_SRCS}
12 | WITH_VTK_DEBUG_LEAKS_CHECK
13 | )
14 |
15 | #-----------------------------------------------------------------------------
16 | #simple_test(qSlicer${MODULE_NAME}ModuleTest)
17 |
--------------------------------------------------------------------------------
/SegmentEditorPETTumorSegmentationEffect/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.6)
2 |
3 | #-----------------------------------------------------------------------------
4 | set(MODULE_NAME SegmentEditorPETTumorSegmentationEffect)
5 |
6 | #-----------------------------------------------------------------------------
7 | set(MODULE_PYTHON_SCRIPTS
8 | SegmentEditorPETTumor.py
9 | )
10 |
11 | set(MODULE_PYTHON_RESOURCES
12 | PETTumorEffect.png
13 | SegmentationCategoryTypeModifier-HeadAndNeckCancer.json
14 | AnatomicRegionAndModifier-DICOM-HeadAndNeckCancer.json
15 | )
16 |
17 | #-----------------------------------------------------------------------------
18 | SlicerMacroBuildScriptedModule(
19 | NAME SegmentEditorPETTumorSegmentationEffect
20 | SCRIPTS "${MODULE_PYTHON_SCRIPTS}"
21 | RESOURCES "${MODULE_PYTHON_RESOURCES}"
22 | #WITH_GENERIC_TESTS
23 | )
24 |
25 |
--------------------------------------------------------------------------------
/PETTumorSegmentationEffect/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.6)
2 |
3 | #-----------------------------------------------------------------------------
4 | set(MODULE_NAME PETTumorSegmentationEffect)
5 |
6 | #-----------------------------------------------------------------------------
7 | set(MODULE_PYTHON_SCRIPTS
8 | PETTumorSegmentationEffect.py
9 | )
10 |
11 | set(MODULE_PYTHON_RESOURCES
12 | PETTumorSegmentationEffect.png
13 | )
14 |
15 | #-----------------------------------------------------------------------------
16 | SlicerMacroBuildScriptedModule(
17 | NAME PETTumorSegmentationEffect
18 | SCRIPTS "${MODULE_PYTHON_SCRIPTS}"
19 | RESOURCES "${MODULE_PYTHON_RESOURCES}"
20 | #WITH_GENERIC_TESTS
21 | )
22 |
23 | #-----------------------------------------------------------------------------
24 | if(BUILD_TESTING)
25 | add_subdirectory(Testing)
26 | endif()
27 |
28 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Resources/UI/qSlicerPETTumorSegmentationFooBarWidget.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | qSlicerPETTumorSegmentationFooBarWidget
4 |
5 |
6 |
7 | 0
8 | 0
9 | 103
10 | 27
11 |
12 |
13 |
14 | Foo bar
15 |
16 |
17 |
18 | 0
19 |
20 | -
21 |
22 |
23 | Foo Bar
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Testing/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | set(MODULE_NAME SegmentEditorPETTumorSegmentationEffectSelfTest)
3 |
4 | #-----------------------------------------------------------------------------
5 | set(MODULE_PYTHON_SCRIPTS
6 | SegmentEditorPETTumorSegmentationEffectSelfTest.py
7 | )
8 |
9 | set(MODULE_PYTHON_RESOURCES
10 | )
11 |
12 | #-----------------------------------------------------------------------------
13 | slicerMacroBuildScriptedModule(
14 | NAME ${MODULE_NAME}
15 | SCRIPTS ${MODULE_PYTHON_SCRIPTS}
16 | RESOURCES ${MODULE_PYTHON_RESOURCES}
17 | #WITH_GENERIC_TESTS
18 | )
19 |
20 | #-----------------------------------------------------------------------------
21 | if(BUILD_TESTING)
22 |
23 | # Register the unittest subclass in the main script as a ctest.
24 | # Note that the test will also be available at runtime.
25 | slicer_add_python_unittest(SCRIPT ${MODULE_NAME}.py
26 | SLICER_ARGS --additional-module-paths ${DEPENDENCIES_ADDITIONAL_MODULE_PATHS})
27 |
28 | endif()
29 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | project(vtkSlicer${MODULE_NAME}ModuleLogic)
2 |
3 | set(KIT ${PROJECT_NAME})
4 |
5 | set(${KIT}_EXPORT_DIRECTIVE "VTK_SLICER_${MODULE_NAME_UPPER}_MODULE_LOGIC_EXPORT")
6 |
7 | set(${KIT}_INCLUDE_DIRECTORIES
8 | ${MRML_INCLUDE_DIRS}
9 | ${MRMLCore_INCLUDE_DIRS}
10 | ${Slicer_ModuleMRML_INCLUDE_DIRS}
11 | ${Slicer_Base_INCLUDE_DIRS}
12 | )
13 |
14 | set(${KIT}_SRCS
15 | vtkSlicer${MODULE_NAME}Logic.cxx
16 | vtkSlicer${MODULE_NAME}Logic.h
17 | itkOSFGraph.h
18 | itkOSFGraph.txx
19 | itkOSFSurface.h
20 | itkOSFSurface.txx
21 | )
22 |
23 | set(${KIT}_TARGET_LIBRARIES
24 | ${MRML_LIBRARIES}
25 | ${ITK_LIBRARIES}
26 | vtkSlicer${MODULE_NAME}ModuleMRML
27 | vtkSlicerAnnotationsModuleMRML
28 | )
29 |
30 | #-----------------------------------------------------------------------------
31 | SlicerMacroBuildModuleLogic(
32 | NAME ${KIT}
33 | EXPORT_DIRECTIVE ${${KIT}_EXPORT_DIRECTIVE}
34 | INCLUDE_DIRECTORIES ${${KIT}_INCLUDE_DIRECTORIES}
35 | SRCS ${${KIT}_SRCS}
36 | TARGET_LIBRARIES ${${KIT}_TARGET_LIBRARIES}
37 | )
38 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/MRML/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | project(vtkSlicer${MODULE_NAME}ModuleMRML)
2 |
3 | set(KIT ${PROJECT_NAME})
4 |
5 | set(${KIT}_EXPORT_DIRECTIVE "VTK_SLICER_${MODULE_NAME_UPPER}_MODULE_MRML_EXPORT")
6 |
7 | set(${KIT}_INCLUDE_DIRECTORIES
8 | #../../../../Slicer/Modules/Scripted/EditorLib/Logic
9 | #${CMAKE_CURRENT_SOURCE_DIR}/../../../../Slicer/Modules/Scripted/EditorLib/Logic
10 | #${Slicer_SOURCE_DIR}/Modules/Scripted/EditorLib/Logic
11 | #${Slicer_binary_dir}/Slicer-build/Modules/Scripted/EditorLib/Logic/vtkImageStash.h
12 | #message(${Slicer_binary_dir}/Modules/Scripted/EditorLib/Logic/vtkImageStash.h)
13 | #${Slicer_source_dir}/Modules/Scripted/EditorLib/Logic/vtkImageStash.h
14 | #
15 | ${MRML_INCLUDE_DIRS}
16 | ${MRMLCore_INCLUDE_DIRS}
17 | ${Slicer_ModuleMRML_INCLUDE_DIRS}
18 | ${Slicer_Base_INCLUDE_DIRS}
19 | ${vtkSlicerSegmentationsModuleLogic_INCLUDE_DIRS}
20 | ${Slicer_ModuleSegmentations_INCLUDE_DIRS}
21 | )
22 |
23 | set(${KIT}_SRCS
24 | vtkMRML${MODULE_NAME}ParametersNode.cxx
25 | )
26 |
27 | set(${KIT}_TARGET_LIBRARIES
28 | ${MRML_LIBRARIES}
29 | vtkSlicerSegmentationsModuleLogic
30 | ${ITK_LIBRARIES}
31 | vtkSlicerMarkupsModuleMRML
32 | #vtkSlicerEditorLibModuleLogic
33 | vtkSlicerSegmentationsModuleLogic
34 | )
35 |
36 | #-----------------------------------------------------------------------------
37 | SlicerMacroBuildModuleMRML(
38 | NAME ${KIT}
39 | EXPORT_DIRECTIVE ${${KIT}_EXPORT_DIRECTIVE}
40 | INCLUDE_DIRECTORIES ${${KIT}_INCLUDE_DIRECTORIES}
41 | SRCS ${${KIT}_SRCS}
42 | TARGET_LIBRARIES ${${KIT}_TARGET_LIBRARIES}
43 | )
44 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkCloneOSFGraphFilter.txx:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 |
19 | #ifndef _itkCloneOSFGraphFilter_txx
20 | #define _itkCloneOSFGraphFilter_txx
21 |
22 | #include "itkCloneOSFGraphFilter.h"
23 | #include "itkLinearInterpolateImageFunction.h"
24 |
25 | namespace itk
26 | {
27 |
28 | //----------------------------------------------------------------------------
29 | template
30 | void
31 | CloneOSFGraphFilter
32 | ::GenerateData()
33 | {
34 | this->CopyInputOSFGraphToOutputOSFGraphSurfaces();
35 | this->CopyInputOSFGraphToOutputOSFGraphGraph();
36 | this->GetOutput()->BuildGraphNodeIdentifierLookupTable();
37 | }
38 |
39 | //----------------------------------------------------------------------------
40 | template
41 | void
42 | CloneOSFGraphFilter
43 | ::PrintSelf(std::ostream& os, Indent indent) const
44 | {
45 | Superclass::PrintSelf(os,indent);
46 | // todo: implement
47 | }
48 |
49 | } // namespace
50 |
51 | #endif
52 |
53 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | set(MODULE_NAME PETTumorSegmentation)
3 | set(MODULE_TITLE ${MODULE_NAME})
4 |
5 | string(TOUPPER ${MODULE_NAME} MODULE_NAME_UPPER)
6 |
7 | #-----------------------------------------------------------------------------
8 | add_subdirectory(MRML)
9 | add_subdirectory(Logic)
10 |
11 | #-----------------------------------------------------------------------------
12 | set(MODULE_EXPORT_DIRECTIVE "Q_SLICER_QTMODULES_${MODULE_NAME_UPPER}_EXPORT")
13 |
14 | # Current_{source,binary} and Slicer_{Libs,Base} already included
15 | set(MODULE_INCLUDE_DIRECTORIES
16 | ${CMAKE_CURRENT_SOURCE_DIR}/Logic
17 | ${CMAKE_CURRENT_BINARY_DIR}/Logic
18 | ${CMAKE_CURRENT_SOURCE_DIR}/MRML
19 | ${CMAKE_CURRENT_BINARY_DIR}/MRML
20 | )
21 |
22 | set(MODULE_SRCS
23 | qSlicer${MODULE_NAME}Module.cxx
24 | qSlicer${MODULE_NAME}Module.h
25 | )
26 |
27 | set(MODULE_MOC_SRCS
28 | qSlicer${MODULE_NAME}Module.h
29 | )
30 |
31 | set(MODULE_TARGET_LIBRARIES
32 | vtkSlicer${MODULE_NAME}ModuleMRML
33 | vtkSlicer${MODULE_NAME}ModuleLogic
34 | )
35 |
36 | set(MODULE_RESOURCES
37 | Resources/qSlicer${MODULE_NAME}Module.qrc
38 | )
39 |
40 | #-----------------------------------------------------------------------------
41 | slicerMacroBuildQtModule(
42 | NAME ${MODULE_NAME}
43 | TITLE ${MODULE_TITLE}
44 | EXPORT_DIRECTIVE ${MODULE_EXPORT_DIRECTIVE}
45 | INCLUDE_DIRECTORIES ${MODULE_INCLUDE_DIRECTORIES}
46 | SRCS ${MODULE_SRCS}
47 | MOC_SRCS ${MODULE_MOC_SRCS}
48 | UI_SRCS ${MODULE_UI_SRCS}
49 | TARGET_LIBRARIES ${MODULE_TARGET_LIBRARIES}
50 | RESOURCES ${MODULE_RESOURCES}
51 | WITH_GENERIC_TESTS
52 | )
53 |
54 | #-----------------------------------------------------------------------------
55 | if(BUILD_TESTING)
56 | add_subdirectory(Testing)
57 | endif()
58 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Resources/UI/qSlicerPETTumorSegmentationModuleWidget.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | qSlicerPETTumorSegmentationModuleWidget
4 |
5 |
6 |
7 | 0
8 | 0
9 | 525
10 | 319
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
20 | Display
21 |
22 |
23 |
-
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 | Qt::Vertical
33 |
34 |
35 |
36 | 0
37 | 0
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | qSlicerWidget
47 | QWidget
48 |
49 | 1
50 |
51 |
52 | ctkCollapsibleButton
53 | QWidget
54 |
55 | 1
56 |
57 |
58 | qSlicerPETTumorSegmentationFooBarWidget
59 | QWidget
60 | qSlicerPETTumorSegmentationFooBarWidget.h
61 | 1
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkCloneOSFGraphFilter.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkCloneOSFGraphFilter_h
19 | #define _itkCloneOSFGraphFilter_h
20 |
21 | #include "itkOSFGraphToOSFGraphFilter.h"
22 |
23 | namespace itk
24 | {
25 |
26 | /** \class CloneOSFGraphFilter
27 | * \brief Create a deep copy of an OSFGraph.
28 | * \date 12/9/2014
29 | * \author Christian Bauer
30 | * Create a deep copy of an OSFGraph. CONTINUE
31 | * Template parameters for class CloneOSFGraphFilter:
32 | *
33 | * - TOSFGraph = The graph type of the input to clone.
34 | */
35 | template
36 | class ITK_EXPORT CloneOSFGraphFilter : public OSFGraphToOSFGraphFilter
37 | {
38 | public:
39 | using Self = CloneOSFGraphFilter;
40 | using Superclass = OSFGraphToOSFGraphFilter;
41 | using Pointer = SmartPointer< Self >;
42 | using ConstPointer = SmartPointer< const Self >;
43 |
44 | ITK_DISALLOW_COPY_AND_ASSIGN(CloneOSFGraphFilter);
45 |
46 | itkNewMacro( Self );
47 | itkTypeMacro( CloneOSFGraphFilter, OSFGraphToOSFGraphFilter );
48 |
49 | protected:
50 | /** Constructor for use by New() method. */
51 | CloneOSFGraphFilter() = default;
52 | ~CloneOSFGraphFilter() override = default;
53 | void PrintSelf(std::ostream& os, Indent indent) const override;
54 |
55 | void GenerateData() override;
56 |
57 | private:
58 |
59 | }; // end class CloneOSFGraphFilter
60 |
61 | } // end namespace itk
62 |
63 | #ifndef ITK_MANUAL_INSTANTIATION
64 | #include "itkCloneOSFGraphFilter.txx"
65 | #endif
66 |
67 | #endif
68 |
69 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.9)
2 |
3 | project(PETTumorSegmentation)
4 |
5 | #-----------------------------------------------------------------------------
6 | # Extension meta-information
7 | set(EXTENSION_HOMEPAGE "https://www.slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/PETTumorSegmentation")
8 | set(EXTENSION_CATEGORY "Segmentation")
9 | set(EXTENSION_CONTRIBUTORS "Christian Bauer (University of Iowa), Markus van Tol (University of Iowa), Andrey Fedorov (SPL), Ethan Ulrich (University of Iowa), Reinhard Beichel (University of Iowa), John Buatti (University of Iowa)")
10 | set(EXTENSION_DESCRIPTION "Tumor and lymph node segmentation in PET scans")
11 | set(EXTENSION_ICONURL "https://raw.githubusercontent.com/QIICR/PETTumorSegmentation/master/PETTumorSegmentation.png")
12 | set(EXTENSION_SCREENSHOTURLS "https://www.slicer.org/slicerWiki/images/0/04/PETTumorSegmentation_Effect_with_models.png")
13 |
14 | #-----------------------------------------------------------------------------
15 | # Extension dependencies
16 | find_package(Slicer REQUIRED)
17 | include(${Slicer_USE_FILE})
18 |
19 | if(CMAKE_CONFIGURATION_TYPES)
20 | set(DEPENDENCIES_ADDITIONAL_MODULE_PATHS "")
21 | foreach(config ${CMAKE_CONFIGURATION_TYPES})
22 | list(APPEND DEPENDENCIES_ADDITIONAL_MODULE_PATHS "${CMAKE_BINARY_DIR}/${Slicer_CLIMODULES_LIB_DIR}/${config}")
23 | list(APPEND DEPENDENCIES_ADDITIONAL_MODULE_PATHS "${CMAKE_BINARY_DIR}/${Slicer_QTSCRIPTEDMODULES_LIB_DIR}/${config}")
24 | list(APPEND DEPENDENCIES_ADDITIONAL_MODULE_PATHS "${CMAKE_BINARY_DIR}/${Slicer_QTLOADABLEMODULES_PYTHON_LIB_DIR}/${config}")
25 | list(APPEND DEPENDENCIES_ADDITIONAL_MODULE_PATHS "${CMAKE_BINARY_DIR}/${Slicer_QTLOADABLEMODULES_LIB_DIR}/${config}")
26 | endforeach()
27 | else()
28 | set(DEPENDENCIES_ADDITIONAL_MODULE_PATHS
29 | ${CMAKE_BINARY_DIR}/${Slicer_CLIMODULES_LIB_DIR}
30 | ${CMAKE_BINARY_DIR}/${Slicer_QTSCRIPTEDMODULES_LIB_DIR}
31 | ${CMAKE_BINARY_DIR}/${Slicer_QTLOADABLEMODULES_PYTHON_LIB_DIR}
32 | ${CMAKE_BINARY_DIR}/${Slicer_QTLOADABLEMODULES_LIB_DIR}
33 | )
34 | endif()
35 |
36 | #-----------------------------------------------------------------------------
37 | # Extension modules
38 | add_subdirectory(PETTumorSegmentation)
39 | # add_subdirectory(PETTumorSegmentationEffect) # requires legacy Editor with got removed: https://github.com/Slicer/Slicer/commit/39283db420baf502fa99865c9d5d58d0e5295a6e
40 | add_subdirectory(SegmentEditorPETTumorSegmentationEffect)
41 | add_subdirectory(Testing)
42 | ## NEXT_MODULE
43 |
44 | #-----------------------------------------------------------------------------
45 | include(${Slicer_EXTENSION_GENERATE_CONFIG})
46 | include(${Slicer_EXTENSION_CPACK})
47 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/qSlicerPETTumorSegmentationModule.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | Portions (c) Copyright University of Iowa All Rights Reserved.
6 | Portions (c) Copyright Brigham and Women's Hospital (BWH) All Rights Reserved.
7 |
8 | See COPYRIGHT.txt
9 | or http://www.slicer.org/copyright/copyright.txt for details.
10 |
11 | Unless required by applicable law or agreed to in writing, software
12 | distributed under the License is distributed on an "AS IS" BASIS,
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | See the License for the specific language governing permissions and
15 | limitations under the License.
16 |
17 | ==============================================================================*/
18 |
19 | #ifndef __qSlicerPETTumorSegmentationModule_h
20 | #define __qSlicerPETTumorSegmentationModule_h
21 |
22 | // SlicerQt includes
23 | #include "qSlicerLoadableModule.h"
24 |
25 | #include "qSlicerPETTumorSegmentationModuleExport.h"
26 |
27 |
28 | class qSlicerPETTumorSegmentationModulePrivate;
29 |
30 | /// \ingroup Slicer_QtModules_ExtensionTemplate
31 | class Q_SLICER_QTMODULES_PETTUMORSEGMENTATION_EXPORT
32 | qSlicerPETTumorSegmentationModule
33 | : public qSlicerLoadableModule
34 | {
35 | Q_OBJECT
36 | Q_PLUGIN_METADATA(IID "org.slicer.modules.loadable.qSlicerLoadableModule/1.0");
37 | Q_INTERFACES(qSlicerLoadableModule);
38 |
39 | public:
40 |
41 | typedef qSlicerLoadableModule Superclass;
42 | explicit qSlicerPETTumorSegmentationModule(QObject *parent=0);
43 | ~qSlicerPETTumorSegmentationModule() override;
44 |
45 | qSlicerGetTitleMacro(QTMODULE_TITLE);
46 |
47 | QString helpText() const override;
48 | QString acknowledgementText() const override;
49 | QStringList contributors() const override;
50 |
51 | QIcon icon() const override;
52 |
53 | QStringList categories() const override;
54 | QStringList dependencies() const override;
55 | bool isHidden() const override;
56 |
57 | protected:
58 |
59 | /// Initialize the module. Register the volumes reader/writer
60 | void setup() override;
61 |
62 | /// Create and return the widget representation associated to this module
63 | qSlicerAbstractModuleRepresentation * createWidgetRepresentation() override;
64 |
65 | /// Create and return the logic associated to this module
66 | vtkMRMLAbstractLogic* createLogic() override;
67 |
68 | protected:
69 | QScopedPointer d_ptr;
70 |
71 | private:
72 | Q_DECLARE_PRIVATE(qSlicerPETTumorSegmentationModule);
73 | Q_DISABLE_COPY(qSlicerPETTumorSegmentationModule);
74 |
75 | };
76 |
77 | #endif
78 |
--------------------------------------------------------------------------------
/SegmentEditorPETTumorSegmentationEffect/SegmentationCategoryTypeModifier-HeadAndNeckCancer.json:
--------------------------------------------------------------------------------
1 | {
2 | "SegmentationCategoryTypeContextName": "Segmentation category and type - Head and Neck Cancer",
3 | "@schema": "https://raw.githubusercontent.com/qiicr/dcmqi/master/doc/segment-context-schema.json#",
4 | "SegmentationCodes": {
5 | "Category": [
6 | {
7 | "cid": "7150",
8 | "CodingSchemeDesignator": "SRT",
9 | "CodeMeaning": "Morphologically Altered Structure",
10 | "showAnatomy": true,
11 | "CodeValue": "M-01000",
12 | "contextGroupName": "SegmentationPropertyCategories",
13 | "Type": [
14 | {
15 | "recommendedDisplayRGBValue": [
16 | 0,
17 | 255,
18 | 0
19 | ],
20 | "cid": "7159",
21 | "CodingSchemeDesignator": "SRT",
22 | "CodeMeaning": "Neoplasm, Primary",
23 | "UMLSConceptUID": "C1306459",
24 | "CodeValue": "M-80003",
25 | "contextGroupName": "LesionSegmentationTypes",
26 | "SNOMEDCTConceptID": "86049000"
27 | },
28 | {
29 | "recommendedDisplayRGBValue": [
30 | 255,
31 | 255,
32 | 0
33 | ],
34 | "cid": "7159",
35 | "CodingSchemeDesignator": "SRT",
36 | "CodeMeaning": "Neoplasm, Secondary",
37 | "UMLSConceptUID": "C2939419",
38 | "CodeValue": "M-80006",
39 | "contextGroupName": "LesionSegmentationTypes",
40 | "SNOMEDCTConceptID": "14799000"
41 | },
42 | {
43 | "recommendedDisplayRGBValue": [
44 | 255,
45 | 0,
46 | 0
47 | ],
48 | "cid": "7159",
49 | "CodingSchemeDesignator": "SRT",
50 | "CodeMeaning": "Neoplasm",
51 | "UMLSConceptUID": "C0027651",
52 | "CodeValue": "M-8FFFF",
53 | "contextGroupName": "LesionSegmentationTypes",
54 | "SNOMEDCTConceptID": "108369006"
55 | }
56 | ]
57 | },
58 | {
59 | "cid": "7150",
60 | "CodingSchemeDesignator": "SRT",
61 | "showAnatomy": true,
62 | "CodeMeaning": "Spatial and Relational Concept",
63 | "CodeValue": "R-42018",
64 | "contextGroupName": "SegmentationPropertyCategories",
65 | "Type": [
66 | {
67 | "recommendedDisplayRGBValue": [
68 | 0,
69 | 0,
70 | 255
71 | ],
72 | "cid": "7165",
73 | "CodingSchemeDesignator": "NCIt",
74 | "CodeMeaning": "Reference Region",
75 | "UMLSConceptUID": "C2986814",
76 | "CodeValue": "C94970",
77 | "contextGroupName": "AbstractSegmentationTypes",
78 | "SNOMEDCTConceptID": "C2986814"
79 | }
80 | ]
81 | }
82 | ]
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkOSFGraphSource.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkOSFGraphSource_h
19 | #define _itkOSFGraphSource_h
20 |
21 | #include
22 | #include "itkOSFGraph.h"
23 |
24 | namespace itk
25 | {
26 | /**\class OSFGraphSource
27 | * \brief The superclass for all objects that generate an OSF graph object.
28 | * \date 12/9/2014
29 | * \author Christian Bauer
30 | * The superclass for all objects that generate an OSF graph object. CONTINUE
31 | * Template parameters for class OSFGraphSource:
32 | *
33 | * - TOutputOSFGraph = The type of OSF graph produced by the object.
34 | *
35 | */
36 |
37 | template
38 | class ITK_EXPORT OSFGraphSource : public ProcessObject
39 | {
40 | public:
41 | using Self = OSFGraphSource;
42 | using Superclass = ProcessObject;
43 | using Pointer = SmartPointer< Self >;
44 | using ConstPointer = SmartPointer< const Self >;
45 |
46 | ITK_DISALLOW_COPY_AND_ASSIGN(OSFGraphSource);
47 |
48 | itkNewMacro( Self );
49 | itkTypeMacro( OSFGraphSource, ProcessObject );
50 |
51 | /** Some convenient type aliases. */
52 | //using DataObjectPointer = DataObject::Pointer ;
53 | using OutputOSFGraphType = TOutputOSFGraph;
54 | using OutputOSFGraphPointer = typename OutputOSFGraphType::Pointer;
55 |
56 | /** Get the mesh output of this process object. */
57 | OutputOSFGraphType* GetOutput(void);
58 | OutputOSFGraphType* GetOutput(unsigned int idx);
59 |
60 | /** Graft the specified data object onto this ProcessObject's
61 | * output. */
62 | virtual void GraftOutput(DataObject *output);
63 | virtual void GraftNthOutput(unsigned int idx, DataObject *output);
64 |
65 | /** Make a DataObject of the correct type to be used as the specified
66 | * output. */
67 | using Superclass::MakeOutput;
68 | ProcessObject::DataObjectPointer MakeOutput(ProcessObject::DataObjectPointerArraySizeType idx) override;
69 |
70 | //virtual void Update();
71 |
72 | protected:
73 | /** Constructor for use by New() method. */
74 | OSFGraphSource();
75 | ~OSFGraphSource() override = default;
76 | void PrintSelf(std::ostream& os, Indent indent) const override;
77 |
78 | void GenerateInputRequestedRegion() override;
79 |
80 | private:
81 |
82 | }; // end class OSFGraphSource
83 |
84 | } // end namespace itk
85 |
86 | #ifndef ITK_MANUAL_INSTANTIATION
87 | #include "itkOSFGraphSource.txx"
88 | #endif
89 |
90 | #endif
91 |
92 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkLOGISMOSOSFGraphSolverFilter.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkLOGISMOSOSFGraphSolverFilter_h
19 | #define _itkLOGISMOSOSFGraphSolverFilter_h
20 |
21 | #include "itkOSFGraphToOSFGraphFilter.h"
22 | #include "logismos_graph.hxx"
23 |
24 | namespace itk
25 | {
26 |
27 | /**\class LOGISMOSOSFGraphSolverFilter
28 | * \brief
29 | * \date 12/9/2014
30 | * \author Christian Bauer
31 | * An object that applies the solver to the maximum flow graph generated by the graph builder. CONTINUE
32 | * Template parameters for class LOGISMOSOSFGraphSolverFilter:
33 | *
34 | * - TInputOSFGraph = The type of the graph input object.
35 | * - TOutputOSFGraph = The type of the graph output object.
36 | */
37 | template
38 | class ITK_EXPORT LOGISMOSOSFGraphSolverFilter : public OSFGraphToOSFGraphFilter
39 | {
40 | public:
41 | using Self = LOGISMOSOSFGraphSolverFilter;
42 | using Superclass = OSFGraphToOSFGraphFilter;
43 | using Pointer = SmartPointer< Self >;
44 | using ConstPointer = SmartPointer< const Self >;
45 |
46 | ITK_DISALLOW_COPY_AND_ASSIGN(LOGISMOSOSFGraphSolverFilter);
47 |
48 | itkNewMacro( Self );
49 | itkTypeMacro( LOGISMOSOSFGraphSolverFilter, OSFGraphToOSFGraphFilter );
50 |
51 | using InputOSFGraphType = TInputOSFGraph;
52 | using InputOSFGraphConstPointer = typename InputOSFGraphType::ConstPointer;
53 |
54 | using OutputOSFGraphType = TOutputOSFGraph;
55 | using OutputOSFGraphPointer = typename OutputOSFGraphType::Pointer;
56 |
57 | protected:
58 | /** Constructor for use by New() method. */
59 | LOGISMOSOSFGraphSolverFilter() = default;
60 | ~LOGISMOSOSFGraphSolverFilter() override;
61 | void PrintSelf(std::ostream& os, Indent indent) const override;
62 |
63 | void GenerateData() override;
64 |
65 | using CapacityType = typename InputOSFGraphType::GraphCosts;
66 | using MaxFlowGraphType = LOGISMOS::graph;
67 | using MaxFlowGraphPointer = MaxFlowGraphType*;
68 | MaxFlowGraphPointer m_MaxFlowGraph{ nullptr };
69 | CapacityType m_FlowValue{ 0 };
70 | virtual void BuildMaxFlowGraphGraph();
71 | virtual void UpdateResult();
72 |
73 | private:
74 |
75 | }; // end class LOGISMOSOSFGraphSolverFilter
76 |
77 | } // end namespace itk
78 |
79 | #ifndef ITK_MANUAL_INSTANTIATION
80 | #include "itkLOGISMOSOSFGraphSolverFilter.txx"
81 | #endif
82 |
83 | #endif
84 |
85 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkMeshToOSFGraphFilter.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkMeshToOSFGraphFilter_h
19 | #define _itkMeshToOSFGraphFilter_h
20 |
21 | #include "itkOSFGraphSource.h"
22 |
23 | namespace itk
24 | {
25 | /**\class MeshToOSFGraphFilter
26 | * \brief Converts an ITK mesh into an OSF graph of just the outer points.
27 | * \date 12/9/2014
28 | * \author Christian Bauer
29 | * Converts an ITK mesh into an OSF graph of just the outer points. CONTINUE
30 | * Template parameters for class MeshToOSFGraphFilter:
31 | *
32 | * - TInputOSFGraph = The graph type of the input to convert.
33 | * - TOutputMesh = The itk mesh type of the output after conversion.
34 | */
35 | template
36 | class ITK_EXPORT MeshToOSFGraphFilter : public OSFGraphSource
37 | {
38 | public:
39 | using Self = MeshToOSFGraphFilter;
40 | using Superclass = OSFGraphSource;
41 | using Pointer = SmartPointer< Self >;
42 | using ConstPointer = SmartPointer< const Self >;
43 |
44 | ITK_DISALLOW_COPY_AND_ASSIGN(MeshToOSFGraphFilter);
45 |
46 | itkNewMacro( Self );
47 | itkTypeMacro( MeshToOSFGraphFilter, OSFGraphSource );
48 |
49 | using InputMeshType = TInputMesh;
50 | using InputMeshConstPointer = typename InputMeshType::ConstPointer;
51 |
52 | using OutputOSFGraphType = TOutputOSFGraph;
53 | using OutputOSFGraphPointer = typename OutputOSFGraphType::Pointer;
54 |
55 | using Superclass::SetInput;
56 | virtual void SetInput(unsigned int idx, const InputMeshType* input); // Set the input image of this process object.
57 | virtual const InputMeshType* GetInput(unsigned int idx); // Get the input image of this process object.
58 | virtual void SetInput(const InputMeshType* input) {this->SetInput(0, input);}; // Set the input image of this process object.
59 | virtual const InputMeshType* GetInput() {return this->GetInput(0);}; // Get the input image of this process object.
60 |
61 | OutputOSFGraphType* GetOutput(void); // Get the mesh output of this process object.
62 | virtual void GenerateOutputInformation(void); // Prepare the output
63 | using DataObjectPointerArraySizeType = typename Superclass::DataObjectPointerArraySizeType;
64 | using Superclass::MakeOutput;
65 | virtual DataObject::Pointer MakeOutput(DataObjectPointerArraySizeType idx); // create a valid output
66 |
67 | protected:
68 | /** Constructor for use by New() method. */
69 | MeshToOSFGraphFilter();
70 | ~MeshToOSFGraphFilter() override = default;
71 | void PrintSelf(std::ostream& os, Indent indent) const override;
72 |
73 | void GenerateData() override;
74 | virtual void CopyInputMeshToOutputOSFSurfacePoints(InputMeshConstPointer mesh, typename OutputOSFGraphType::OSFSurface::Pointer osfSurface);
75 | virtual void CopyInputMeshToOutputOSFSurfaceCells(InputMeshConstPointer mesh, typename OutputOSFGraphType::OSFSurface::Pointer osfSurface);
76 |
77 | private:
78 |
79 | }; // end class MeshToOSFGraphFilter
80 |
81 | } // end namespace itk
82 |
83 | #ifndef ITK_MANUAL_INSTANTIATION
84 | #include "itkMeshToOSFGraphFilter.txx"
85 | #endif
86 |
87 | #endif
88 |
89 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkOSFGraphToOSFGraphFilter.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkOSFGraphToOSFGraphFilter_h
19 | #define _itkOSFGraphToOSFGraphFilter_h
20 |
21 | #include "itkOSFGraphSource.h"
22 |
23 | namespace itk
24 | {
25 |
26 | /**\class SealingSegmentationMergerImageFilter
27 | * \brief
28 | * \date 12/9/2014
29 | * \author Christian Bauer
30 | * The superclass for any filter that takes one OSF graph as input and gives another as output.
31 | * By default, copies all input graph data to the output graph.
32 | * Template parameters for class SimpleOSFGraphBuilderFilter:
33 | *
34 | * - TInputOSFGraph = The graph type of the input.
35 | * - TOutputOSFGraph = The graph type of the output.
36 | */
37 |
38 | template
39 | class ITK_EXPORT OSFGraphToOSFGraphFilter : public OSFGraphSource
40 | {
41 | public:
42 | using Self = OSFGraphToOSFGraphFilter;
43 | using Superclass = OSFGraphSource;
44 | using Pointer = SmartPointer< Self >;
45 | using ConstPointer = SmartPointer< const Self >;
46 |
47 | ITK_DISALLOW_COPY_AND_ASSIGN(OSFGraphToOSFGraphFilter);
48 |
49 | itkNewMacro( Self );
50 | itkTypeMacro( OSFGraphToOSFGraphFilter, OSFGraphSource );
51 |
52 | using InputOSFGraphType = TInputOSFGraph;
53 | using InputOSFGraphConstPointer = typename InputOSFGraphType::ConstPointer;
54 |
55 | using OutputOSFGraphType = TOutputOSFGraph;
56 | using OutputOSFGraphPointer = typename OutputOSFGraphType::Pointer;
57 |
58 | using Superclass::SetInput;
59 | virtual void SetInput(unsigned int idx, const InputOSFGraphType* input); // Set the input image of this process object.
60 | virtual const InputOSFGraphType* GetInput(unsigned int idx) const; // Get the input image of this process object.
61 | virtual void SetInput( const InputOSFGraphType* input) {this->SetInput(0, input);}; // Set the input image of this process object.
62 | virtual const InputOSFGraphType* GetInput() const {return this->GetInput(0);}; // Get the input image of this process object.
63 |
64 | OutputOSFGraphType* GetOutput(unsigned int idx); // Get the mesh output of this process object.
65 | OutputOSFGraphType* GetOutput(void) {return this->GetOutput(0);}; // Get the mesh output of this process object.
66 |
67 | protected:
68 | /** Constructor for use by New() method. */
69 | OSFGraphToOSFGraphFilter();
70 | ~OSFGraphToOSFGraphFilter() override = default;
71 | void PrintSelf(std::ostream& os, Indent indent) const override;
72 |
73 | using OSFSurface = typename OutputOSFGraphType::OSFSurface;
74 | using OSFSurfacePointer= typename OSFSurface::Pointer;
75 | using OSFSurfaceConstPointer = typename OSFSurface::ConstPointer;
76 | virtual void CopyInputOSFGraphToOutputOSFGraphSurfaces();
77 | virtual void CopyInputOSFGraphToOutputOSFGraphSurface(OSFSurfaceConstPointer inputOSFSurface, OSFSurfacePointer outputOSFSurface);
78 | virtual void CopyInputOSFGraphToOutputOSFGraphGraph();
79 | // todo: add more copy functions as required
80 |
81 | private:
82 |
83 | }; // end class OSFGraphToOSFGraphFilter
84 |
85 | } // end namespace itk
86 |
87 | #ifndef ITK_MANUAL_INSTANTIATION
88 | #include "itkOSFGraphToOSFGraphFilter.txx"
89 | #endif
90 |
91 | #endif
92 |
93 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkOSFGraphToMeshFilter.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef __itkOSFGraphToMeshFilter_h
19 | #define __itkOSFGraphToMeshFilter_h
20 |
21 | #include "itkMeshSource.h"
22 |
23 | namespace itk
24 | {
25 | /**\class OSFGraphToMeshFilter
26 | * \brief Converts a fully solved itk OSF graph into an itk Mesh.
27 | * \date 12/9/2014
28 | * \author Chrsitian Bauer
29 | * Converts a fully solved itk OSF graph into an itk Mesh. CONTINUE
30 | * Template parameters for class OSFGraphToMeshFilter:
31 | *
32 | * - TInputOSFGraph = The graph type of the input to convert.
33 | * - TOutputMesh = The itk mesh type of the output after conversion.
34 | */
35 | template
36 | class ITK_EXPORT OSFGraphToMeshFilter : public MeshSource
37 | {
38 | public:
39 | /** Standard class type aliases. */
40 | using Self = OSFGraphToMeshFilter;
41 | using Superclass = MeshSource;
42 | using Pointer = SmartPointer;
43 | using ConstPointer = SmartPointer;
44 |
45 | ITK_DISALLOW_COPY_AND_ASSIGN(OSFGraphToMeshFilter);
46 |
47 | itkNewMacro( Self );
48 |
49 | /** Run-time type information (and related methods). */
50 | itkTypeMacro(OSFGraphToMeshFilter, MeshSource);
51 |
52 | /** Enum defining the type of surface to extract */
53 | enum SurfaceType {
54 | CurrentSurface,
55 | InitialSurface,
56 | InnermostSurface,
57 | OutermostSurface
58 | };
59 |
60 | /** Get/Set the type of surface to extract */
61 | itkSetMacro( SurfaceType, SurfaceType );
62 | itkGetMacro( SurfaceType, SurfaceType );
63 |
64 | /** Create a valid output. */
65 | using DataObjectPointerArraySizeType = typename Superclass::DataObjectPointerArraySizeType;
66 | using Superclass::MakeOutput;
67 | DataObject::Pointer MakeOutput(DataObjectPointerArraySizeType idx);
68 |
69 | /** Some Image related type aliases. */
70 | using InputOSFGraphType = TInputOSFGraph;
71 | using InputOSFGraphConstPointer = typename InputOSFGraphType::ConstPointer;
72 |
73 | /** Some Mesh related type aliases. */
74 | using OutputMeshType = TOutputMesh;
75 | using OutputMeshPointer = typename OutputMeshType::Pointer;
76 |
77 | /** Set the input image of this process object. */
78 | using Superclass::SetInput;
79 | void SetInput(const InputOSFGraphType* input);
80 |
81 | /** Get the input image of this process object. */
82 | const InputOSFGraphType* GetInput();
83 |
84 | /** Get the output Mesh of this process object. */
85 | OutputMeshType* GetOutput(unsigned int idx);
86 | OutputMeshType* GetOutput(void) {return this->GetOutput(0);};
87 |
88 | protected:
89 | OSFGraphToMeshFilter();
90 | ~OSFGraphToMeshFilter() override = default;
91 | virtual void PrintSelf(std::ostream& os, Indent indent) const override;
92 |
93 | void GenerateData() override;
94 | void GenerateOutputInformation(void);
95 | virtual void CopyInputOSFSurfaceToOutputMeshPoints(typename InputOSFGraphType::OSFSurface::ConstPointer osfSurface, OutputMeshPointer mesh);
96 | virtual void CopyInputOSFSurfaceToOutputMeshCells(typename InputOSFGraphType::OSFSurface::ConstPointer osfSurface, OutputMeshPointer mesh);
97 |
98 | SurfaceType m_SurfaceType;
99 |
100 | private:
101 | };
102 |
103 | } // end namespace itk
104 |
105 | #ifndef ITK_MANUAL_INSTANTIATION
106 | #include "itkOSFGraphToMeshFilter.txx"
107 | #endif
108 |
109 | #endif
110 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkCenterNormalColumnBuilderFilter.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkCenterNormalColumnBuilderFilter_h
19 | #define _itkCenterNormalColumnBuilderFilter_h
20 |
21 | #include "itkOSFGraphToOSFGraphFilter.h"
22 |
23 | namespace itk
24 | {
25 | /**\class CenterNormalColumnBuilderFilter
26 | * \brief Builds the columns in the graph based on the vertex points of the existing graph.
27 | * \date 12/9/2014
28 | * \author Christian Bauer, Markus Van Tol
29 | * Builds the columns in the graph based on the vertex points of the existing graph. CONTINUE
30 | * Template parameters for class CenterNormalColumnBuilderFilter:
31 | *
32 | * - TInputOSFGraph = The graph type of the input to build columns for.
33 | * - TOutputOSFGraph = The graph type of the input with built columns.
34 | */
35 | template
36 | class ITK_EXPORT CenterNormalColumnBuilderFilter : public OSFGraphToOSFGraphFilter
37 | {
38 | public:
39 | using Self = CenterNormalColumnBuilderFilter;
40 | using Superclass = OSFGraphToOSFGraphFilter;
41 | using Pointer = SmartPointer< Self >;
42 | using ConstPointer = SmartPointer< const Self >;
43 |
44 | ITK_DISALLOW_COPY_AND_ASSIGN(CenterNormalColumnBuilderFilter);
45 |
46 | itkNewMacro( Self );
47 | itkTypeMacro( CenterNormalColumnBuilderFilter, OSFGraphToOSFGraphFilter );
48 |
49 | using InputOSFGraphType = TInputOSFGraph;
50 | using InputOSFGraphConstPointer = typename InputOSFGraphType::ConstPointer;
51 |
52 | using OutputOSFGraphType = TOutputOSFGraph;
53 | using OutputOSFGraphPointer = typename OutputOSFGraphType::Pointer;
54 |
55 | itkSetMacro( StepLength, float );
56 | itkGetMacro( StepLength, float );
57 |
58 | itkSetMacro( NumberOfSteps, unsigned int );
59 | itkGetMacro( NumberOfSteps, unsigned int );
60 |
61 | itkSetVectorMacro( CenterPoint, float, 3 );
62 | itkGetVectorMacro( CenterPoint, const float, 3 );
63 |
64 | protected:
65 | /** Constructor for use by New() method. */
66 | CenterNormalColumnBuilderFilter() = default;
67 | ~CenterNormalColumnBuilderFilter() override = default;
68 | void PrintSelf(std::ostream& os, Indent indent) const override;
69 |
70 | void GenerateData() override;
71 |
72 | float m_StepLength{ 0 };
73 | unsigned int m_NumberOfSteps{ 0 };
74 |
75 | using OSFSurface = typename OutputOSFGraphType::OSFSurface;
76 | using VertexIdentifier = typename OSFSurface::VertexIdentifier;
77 | using CellIdentifier = typename OSFSurface::CellIdentifier;
78 | virtual void BuildColumn(VertexIdentifier vertexId);
79 |
80 | //typedef Vector< float, ::itk::GetImageDimension::ImageDimension > CenterPoint;
81 | float m_CenterPoint[3]; // todo: assuming fixed number of dimensions here
82 | //typedef Vector< float, ::itk::GetImageDimension::ImageDimension > DirectionVector;
83 | using DirectionVector = Vector< float, 3 >; // todo: assuming fixed number of dimensions here
84 | virtual DirectionVector GetNormal(const VertexIdentifier vertexId) const;
85 |
86 | std::vector< std::set > m_VertexToCellLookupTable;
87 | virtual void BuildVertexToCellLookupTable();
88 |
89 | private:
90 |
91 | }; // end class CenterNormalColumnBuilderFilter
92 |
93 | } // end namespace itk
94 |
95 | #ifndef ITK_MANUAL_INSTANTIATION
96 | #include "itkCenterNormalColumnBuilderFilter.txx"
97 | #endif
98 |
99 | #endif
100 |
101 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkSimpleOSFGraphBuilderFilter.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkSimpleOSFGraphBuilderFilter_h
19 | #define _itkSimpleOSFGraphBuilderFilter_h
20 |
21 | #include "itkOSFGraphToOSFGraphFilter.h"
22 |
23 | namespace itk
24 | {
25 | /**\class SimpleOSFGraphBuilderFilter
26 | * \brief Generates the solvable graph information for an OSF graph object.
27 | * \date 12/9/2014
28 | * \author Christian Bauer
29 | * Given an OSF graph with the costs and locations of the nodes and columns, this builds an accompanying
30 | * maximum-flow-solvable graph type, with the source and sink nodes in order to generate the solution to
31 | * the surface. \n
32 | * This also applies the hard and soft smoothness requirements.
33 | * Template parameters for class SimpleOSFGraphBuilderFilter:
34 | *
35 | * - TInputOSFGraph = The graph type of the input.
36 | * - TOutputOSFGraph = The graph type of the output.
37 | */
38 | template
39 | class ITK_EXPORT SimpleOSFGraphBuilderFilter : public OSFGraphToOSFGraphFilter
40 | {
41 | public:
42 | using Self = SimpleOSFGraphBuilderFilter;
43 | using Superclass = OSFGraphToOSFGraphFilter;
44 | using Pointer = SmartPointer< Self >;
45 | using ConstPointer = SmartPointer< const Self >;
46 |
47 | ITK_DISALLOW_COPY_AND_ASSIGN(SimpleOSFGraphBuilderFilter);
48 |
49 | itkNewMacro( Self );
50 | itkTypeMacro( SimpleOSFGraphBuilderFilter, OSFGraphToOSFGraphFilter );
51 |
52 | using InputOSFGraphType = TInputOSFGraph;
53 | using InputOSFGraphConstPointer = typename InputOSFGraphType::ConstPointer;
54 |
55 | using OutputOSFGraphType = TOutputOSFGraph;
56 | using OutputOSFGraphPointer = typename OutputOSFGraphType::Pointer;
57 |
58 | itkSetMacro( SmoothnessConstraint, unsigned int );
59 | itkGetMacro( SmoothnessConstraint, unsigned int );
60 |
61 | itkSetMacro( SoftSmoothnessPenalty, double );
62 | itkGetMacro( SoftSmoothnessPenalty, double );
63 |
64 | protected:
65 | /** Constructor for use by New() method. */
66 | SimpleOSFGraphBuilderFilter() = default;
67 | ~SimpleOSFGraphBuilderFilter() override = default;
68 | void PrintSelf(std::ostream& os, Indent indent) const override;
69 |
70 | void GenerateData() override;
71 |
72 | using SurfaceIdentifier = typename OutputOSFGraphType::VertexIdentifier;
73 | using OSFSurface = typename OutputOSFGraphType::OSFSurface;
74 | using VertexIdentifier = typename OSFSurface::VertexIdentifier;
75 | virtual void CreateNodesForColumn(SurfaceIdentifier surfaceId, VertexIdentifier vertexId);
76 | virtual void CreateIntraColumnArcsForColumn(SurfaceIdentifier surfaceId, VertexIdentifier vertexId);
77 | virtual void CreateInterColumnArcsForColumn(SurfaceIdentifier surfaceId, VertexIdentifier vertexId);
78 |
79 | // note: shanhui said that some people say the value has to be a large negative number
80 | // but he did not experience any negative effects
81 | // this behavior may probably depend on the range of the actual cost values
82 | const typename OutputOSFGraphType::GraphCosts m_Infinity{ std::numeric_limits::infinity() };
83 | const typename OutputOSFGraphType::GraphCosts m_ColumnBasedNodeWeight{ -1 };
84 |
85 | unsigned int m_SmoothnessConstraint{ itk::NumericTraits::max() };
86 | double m_SoftSmoothnessPenalty{ 0 };
87 |
88 | private:
89 | }; // end class SimpleOSFGraphBuilderFilter
90 |
91 | } // end namespace itk
92 |
93 | #ifndef ITK_MANUAL_INSTANTIATION
94 | #include "itkSimpleOSFGraphBuilderFilter.txx"
95 | #endif
96 |
97 | #endif
98 |
99 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkOSFGraphSource.txx:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkOSFGraphSource_txx
19 | #define _itkOSFGraphSource_txx
20 |
21 | #include "itkOSFGraph.h"
22 |
23 | namespace itk
24 | {
25 |
26 | //----------------------------------------------------------------------------
27 | template
28 | OSFGraphSource
29 | ::OSFGraphSource()
30 | {
31 | // Create the output. We use static_cast<> here because we know the default
32 | // output must be of type TOutputMesh
33 | OutputOSFGraphPointer output
34 | = static_cast(this->MakeOutput(0).GetPointer());
35 |
36 | this->ProcessObject::SetNumberOfRequiredOutputs(1);
37 | this->ProcessObject::SetNthOutput( 0, output.GetPointer() );
38 | }
39 |
40 | //----------------------------------------------------------------------------
41 | template
42 | typename OSFGraphSource::DataObjectPointer
43 | OSFGraphSource
44 | ::MakeOutput(DataObjectPointerArraySizeType)
45 | {
46 | return static_cast(TOutputOSFGraph::New().GetPointer());
47 | }
48 |
49 | //----------------------------------------------------------------------------
50 | template
51 | typename OSFGraphSource::OutputOSFGraphType*
52 | OSFGraphSource
53 | ::GetOutput(void)
54 | {
55 | if (this->GetNumberOfOutputs() < 1)
56 | {
57 | return 0;
58 | }
59 |
60 | return static_cast
61 | (this->ProcessObject::GetOutput(0));
62 | }
63 |
64 | //----------------------------------------------------------------------------
65 | template
66 | typename OSFGraphSource::OutputOSFGraphType*
67 | OSFGraphSource
68 | ::GetOutput(unsigned int idx)
69 | {
70 | return static_cast
71 | (this->ProcessObject::GetOutput(idx));
72 | }
73 |
74 | //----------------------------------------------------------------------------
75 | template
76 | void
77 | OSFGraphSource
78 | ::GenerateInputRequestedRegion()
79 | {
80 | Superclass::GenerateInputRequestedRegion();
81 | }
82 |
83 | //----------------------------------------------------------------------------
84 | template
85 | void
86 | OSFGraphSource
87 | ::GraftOutput(DataObject *graft)
88 | {
89 | this->GraftNthOutput(0, graft);
90 | }
91 |
92 | //----------------------------------------------------------------------------
93 | template
94 | void
95 | OSFGraphSource
96 | ::GraftNthOutput(unsigned int idx, DataObject *graft)
97 | {
98 | if ( idx >= this->GetNumberOfOutputs() )
99 | {
100 | itkExceptionMacro(<<"Requested to graft output " << idx <<
101 | " but this filter only has " << this->GetNumberOfOutputs() << " Outputs.");
102 | }
103 |
104 | if ( !graft )
105 | {
106 | itkExceptionMacro(<<"Requested to graft output that is a nullptr pointer" );
107 | }
108 |
109 | DataObject * output = this->GetOutput( idx );
110 |
111 | // Call Graft on the OSFGraph in order to copy meta-information, and containers.
112 | // todo: OSFGraph needs support for that!!!
113 | output->Graft( graft );
114 | }
115 |
116 | //----------------------------------------------------------------------------
117 | template
118 | void
119 | OSFGraphSource
120 | ::PrintSelf(std::ostream& os, Indent indent) const
121 | {
122 | Superclass::PrintSelf(os,indent);
123 | // todo: implement
124 | }
125 |
126 | } // namespace
127 |
128 | #endif
129 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkSealingSegmentationMergerImageFilter.txx:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef __itkSealingSegmentationMergerImageFilter_txx
19 | #define __itkSealingSegmentationMergerImageFilter_txx
20 |
21 | #include "itkSealingSegmentationMergerImageFilter.h"
22 | #include "itkImageRegionIterator.h"
23 | #include "itkImageRegionConstIterator.h"
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #define X_AXIS 0
31 | #define Y_AXIS 1
32 | #define Z_AXIS 2
33 |
34 | namespace itk
35 | {
36 |
37 | template
38 | void
39 | SealingSegmentationMergerImageFilter
40 | ::BeforeThreadedGenerateData()
41 | {
42 | // create output image
43 | const auto& input = this->GetInput();
44 | auto output = this->GetOutput();
45 | output->CopyInformation(input);
46 | output->Allocate();
47 | }
48 |
49 | template
50 | void
51 | SealingSegmentationMergerImageFilter
52 | ::DynamicThreadedGenerateData(const OutputImageRegionType& outputRegionForThread)
53 | {
54 | using InputNeighborhoodIteratorType = itk::ConstNeighborhoodIterator;
55 | using UptakeIteratorType = itk::ImageRegionIterator;
56 | using OutputIteratorType = itk::ImageRegionIterator;
57 |
58 | using InputRadiusType = typename InputNeighborhoodIteratorType::RadiusType;
59 | InputRadiusType radius;
60 | radius.Fill(1);
61 |
62 | InputNeighborhoodIteratorType inputIt(radius, this->GetInput(), outputRegionForThread); //iterator for newly created label
63 | InputNeighborhoodIteratorType segmentationIt(radius, this->GetLabelImage(), outputRegionForThread); //iterator for existing labels
64 | UptakeIteratorType uptakeIt(this->GetDataImage(), outputRegionForThread);
65 | OutputIteratorType outputIt(this->GetOutput(), outputRegionForThread);
66 | while (!outputIt.IsAtEnd()) //Zero out any data left over from old memory
67 | {
68 | outputIt.Set(0);
69 | ++outputIt;
70 | }
71 | outputIt.GoToBegin();
72 | while (!inputIt.IsAtEnd()) //Apply the existing labels and the actual sealing
73 | {
74 | if (inputIt.GetCenterPixel()>0 && (segmentationIt.GetCenterPixel()==0 || m_PaintOver)) //If the new label is to be applied and either the existing one is blank or set to be painted over, then apply the new label
75 | outputIt.Set(m_Label);
76 | else if (segmentationIt.GetCenterPixel()>0) //Otherwise, if there's an existing label, apply it
77 | outputIt.Set(segmentationIt.GetCenterPixel());
78 | else if (m_Sealing && (uptakeIt.Get()>=m_Threshold || m_NecroticRegion)) //Otherwise, if sealing's active and the voxel is either above the threshold or the region is marked necrotic, thereby ignoring the threshold, then check if the voxel must be sealed
79 | {
80 | for (int dim=0; dim<3; ++dim) //check each dimension
81 | {
82 | if (inputIt.GetPrevious(dim)>0 && (segmentationIt.GetNext(dim)>0 || inputIt.GetNext(dim)>0)) //If previous in this dimension is a new label and next is a new or old label, seal with new label
83 | outputIt.Set(m_Label);
84 | else if (inputIt.GetNext(dim)>0 && (segmentationIt.GetPrevious(dim)>0 || inputIt.GetPrevious(dim)>0)) //If next in this dimension is a new label and previous is a new or old label, seal with new label
85 | outputIt.Set(m_Label);
86 | }
87 | }
88 | else
89 | outputIt.Set(0);
90 |
91 | ++inputIt;
92 | ++segmentationIt;
93 | ++uptakeIt;
94 | ++outputIt;
95 | }
96 | }
97 |
98 | template
99 | void SealingSegmentationMergerImageFilter::
100 | PrintSelf(std::ostream& os, Indent indent) const
101 | {
102 | Superclass::PrintSelf(os,indent);
103 | }
104 |
105 | } // end namespace itk
106 |
107 |
108 | #endif
109 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/qSlicerPETTumorSegmentationModule.cxx:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | Portions (c) Copyright University of Iowa All Rights Reserved.
6 | Portions (c) Copyright Brigham and Women's Hospital (BWH) All Rights Reserved.
7 |
8 | See COPYRIGHT.txt
9 | or http://www.slicer.org/copyright/copyright.txt for details.
10 |
11 | Unless required by applicable law or agreed to in writing, software
12 | distributed under the License is distributed on an "AS IS" BASIS,
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | See the License for the specific language governing permissions and
15 | limitations under the License.
16 |
17 | ==============================================================================*/
18 |
19 | // Qt includes
20 | #include
21 |
22 | // PETTumorSegmentation Logic includes
23 | #include
24 |
25 | // PETTumorSegmentation includes
26 | #include "qSlicerPETTumorSegmentationModule.h"
27 |
28 | //-----------------------------------------------------------------------------
29 | #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
30 | #include
31 | Q_EXPORT_PLUGIN2(qSlicerPETTumorSegmentationModule, qSlicerPETTumorSegmentationModule);
32 | #endif
33 |
34 | //-----------------------------------------------------------------------------
35 | /// \ingroup Slicer_QtModules_ExtensionTemplate
36 | class qSlicerPETTumorSegmentationModulePrivate
37 | {
38 | public:
39 | qSlicerPETTumorSegmentationModulePrivate();
40 | };
41 |
42 | //-----------------------------------------------------------------------------
43 | // qSlicerPETTumorSegmentationModulePrivate methods
44 |
45 | //-----------------------------------------------------------------------------
46 | qSlicerPETTumorSegmentationModulePrivate::qSlicerPETTumorSegmentationModulePrivate() = default;
47 |
48 | //-----------------------------------------------------------------------------
49 | // qSlicerPETTumorSegmentationModule methods
50 |
51 | //-----------------------------------------------------------------------------
52 | qSlicerPETTumorSegmentationModule::qSlicerPETTumorSegmentationModule(QObject* _parent)
53 | : Superclass(_parent)
54 | , d_ptr(new qSlicerPETTumorSegmentationModulePrivate)
55 | {
56 | }
57 |
58 | //-----------------------------------------------------------------------------
59 | qSlicerPETTumorSegmentationModule::~qSlicerPETTumorSegmentationModule() = default;
60 |
61 | //-----------------------------------------------------------------------------
62 | QString qSlicerPETTumorSegmentationModule::helpText() const
63 | {
64 | return "This is a loadable module for tumor and lymph node segmentation in PET scans.";
65 | }
66 |
67 | //-----------------------------------------------------------------------------
68 | QString qSlicerPETTumorSegmentationModule::acknowledgementText() const
69 | {
70 | return "This work was funded by NIH grants U01CA140206 and U24CA180918.";
71 | }
72 |
73 | //-----------------------------------------------------------------------------
74 | QStringList qSlicerPETTumorSegmentationModule::contributors() const
75 | {
76 | QStringList moduleContributors;
77 | moduleContributors << QString("Christian Bauer (University of Iowa)");
78 | moduleContributors << QString("Markus van Tol (University of Iowa)");
79 | return moduleContributors;
80 | }
81 |
82 | //-----------------------------------------------------------------------------
83 | QIcon qSlicerPETTumorSegmentationModule::icon() const
84 | {
85 | return QIcon(":/Icons/PETTumorSegmentation.png");
86 | }
87 |
88 | //-----------------------------------------------------------------------------
89 | QStringList qSlicerPETTumorSegmentationModule::categories() const
90 | {
91 | return QStringList() << "EditorEffect";
92 | }
93 |
94 | //-----------------------------------------------------------------------------
95 | QStringList qSlicerPETTumorSegmentationModule::dependencies() const
96 | {
97 | return QStringList();
98 | }
99 |
100 | //-----------------------------------------------------------------------------
101 | void qSlicerPETTumorSegmentationModule::setup()
102 | {
103 | this->Superclass::setup();
104 | }
105 |
106 | //-----------------------------------------------------------------------------
107 | bool qSlicerPETTumorSegmentationModule::isHidden() const
108 | {
109 | return true;
110 | }
111 |
112 | //-----------------------------------------------------------------------------
113 | qSlicerAbstractModuleRepresentation* qSlicerPETTumorSegmentationModule
114 | ::createWidgetRepresentation()
115 | {
116 | return 0;
117 | }
118 |
119 | //-----------------------------------------------------------------------------
120 | vtkMRMLAbstractLogic* qSlicerPETTumorSegmentationModule::createLogic()
121 | {
122 | return vtkSlicerPETTumorSegmentationLogic::New();
123 | }
124 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkSealingSegmentationMergerImageFilter.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef __itkSealingSegmentationMergerImageFilter_h
19 | #define __itkSealingSegmentationMergerImageFilter_h
20 |
21 | #include "itkLinearInterpolateImageFunction.h"
22 | #include "itkNearestNeighborInterpolateImageFunction.h"
23 | #include "itkInterpolateImageFunction.h"
24 | #include "itkConceptChecking.h"
25 | #include "itkImageToImageFilter.h"
26 | #include "itkBinaryThresholdImageFilter.h"
27 | #include "itkConnectedComponentImageFilter.h"
28 | #include "itkVotingBinaryIterativeHoleFillingImageFilter.h"
29 | #include "itkSliceBySliceImageFilter.h"
30 | #include "itkGrayscaleFillholeImageFilter.h"
31 |
32 | namespace itk
33 | {
34 | /**\class SealingSegmentationMergerImageFilter
35 | * \brief Merges two segmentation volumes together, with one explicitly of a new object.
36 | * \date 12/9/2014
37 | * \author Christian Bauer, Markus Van Tol
38 | * Merges a new object segmentation with the segmentation of other objects. If set, avoids overwriting
39 | * old objects and seals gaps between the new object and old objects or more of the new object.
40 | * Template parameters for class SealingSegmentationMergerImageFilter:
41 | *
42 | * - TInputImage = The image type of the new segmentation to be incorporated.
43 | * - TUptakeImage = The image type of the existing segmentation to be added to.
44 | * - TOutputImage = The image type of the merged output.
45 | */
46 | template
47 | class ITK_EXPORT SealingSegmentationMergerImageFilter : public ImageToImageFilter
48 | {
49 | public:
50 | /** Standard class type aliases. */
51 | using Self = SealingSegmentationMergerImageFilter;
52 | using Superclass = ImageToImageFilter;
53 | using Pointer = SmartPointer;
54 | using ConstPointer = SmartPointer;
55 |
56 | ITK_DISALLOW_COPY_AND_ASSIGN(SealingSegmentationMergerImageFilter);
57 |
58 | /** Method for creation through the object factory. */
59 | itkNewMacro(Self);
60 |
61 | /** Run-time type information (and related methods). */
62 | itkTypeMacro(SealingSegmentationMergerImageFilter, ImageToImageFilter);
63 |
64 | /** Some convenient type aliases. */
65 | using InputImageType = TInputImage;
66 | using InputImagePointer = typename InputImageType::ConstPointer;
67 | using InputImageRegionType = typename InputImageType::RegionType;
68 | using InputImagePixelType = typename InputImageType::PixelType;
69 |
70 | using UptakeImageType = TUptakeImage;
71 | using UptakeImagePointer = typename UptakeImageType::Pointer;
72 | using UptakeImageRegionType = typename UptakeImageType::RegionType;
73 | using UptakeImagePixelType = typename UptakeImageType::PixelType;
74 |
75 | using OutputImageType = TOutputImage;
76 | using OutputImagePointer = typename OutputImageType::Pointer;
77 | using OutputImageRegionType = typename OutputImageType::RegionType;
78 | using OutputImagePixelType = typename OutputImageType::PixelType;
79 |
80 | using PointType = typename TOutputImage::PointType ;
81 |
82 | /** ImageDimension enumeration */
83 | static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;
84 | static constexpr unsigned int OutputImageDimension = TOutputImage::ImageDimension;
85 |
86 | itkSetObjectMacro(DataImage, UptakeImageType);
87 | itkGetObjectMacro(DataImage, UptakeImageType);
88 |
89 | itkSetObjectMacro(LabelImage, InputImageType);
90 | itkGetObjectMacro(LabelImage, InputImageType);
91 |
92 | itkSetMacro(Threshold, UptakeImagePixelType);
93 | itkGetMacro(Threshold, UptakeImagePixelType);
94 |
95 | itkSetMacro(Label, InputImagePixelType);
96 | itkGetMacro(Label, InputImagePixelType);
97 |
98 | itkSetMacro(PaintOver, bool);
99 | itkGetMacro(PaintOver, bool);
100 |
101 | itkSetMacro(Sealing, bool);
102 | itkGetMacro(Sealing, bool);
103 |
104 | itkSetMacro(NecroticRegion, bool);
105 | itkGetMacro(NecroticRegion, bool);
106 |
107 | #ifdef ITK_USE_CONCEPT_CHECKING
108 | /** Begin concept checking */
109 | itkConceptMacro(ImageDimensionCheck,
110 | (Concept::SameDimensionOrMinusOne));
112 | /** End concept checking */
113 | #endif
114 |
115 | protected:
116 | SealingSegmentationMergerImageFilter() = default;
117 | ~SealingSegmentationMergerImageFilter() override = default;
118 | void PrintSelf(std::ostream& os, Indent indent) const override;
119 |
120 | void BeforeThreadedGenerateData() override;
121 | void DynamicThreadedGenerateData(const OutputImageRegionType& outputRegionForThread) override;
122 |
123 | private:
124 | UptakeImagePixelType m_Threshold{ 0.0 };
125 | InputImagePixelType m_Label{ 1 } ;
126 | bool m_Sealing{ false };
127 | bool m_PaintOver{ false };
128 | bool m_NecroticRegion{ false };
129 | typename InputImageType::Pointer m_LabelImage;
130 | typename UptakeImageType::Pointer m_DataImage;
131 | };
132 |
133 | } // end namespace itk
134 |
135 | #ifndef ITK_MANUAL_INSTANTIATION
136 | #include "itkSealingSegmentationMergerImageFilter.txx"
137 | #endif
138 |
139 | #endif
140 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkLOGISMOSOSFGraphSolverFilter.txx:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkLOGISMOSOSFGraphSolverFilter_txx
19 | #define _itkLOGISMOSOSFGraphSolverFilter_txx
20 |
21 | #include "itkLOGISMOSOSFGraphSolverFilter.h"
22 |
23 | namespace itk
24 | {
25 |
26 | //----------------------------------------------------------------------------
27 | template
28 | LOGISMOSOSFGraphSolverFilter
29 | ::~LOGISMOSOSFGraphSolverFilter()
30 | {
31 | if (m_MaxFlowGraph!=nullptr)
32 | {
33 | delete m_MaxFlowGraph;
34 | m_MaxFlowGraph = nullptr;
35 | }
36 | }
37 |
38 | //----------------------------------------------------------------------------
39 | template
40 | void
41 | LOGISMOSOSFGraphSolverFilter
42 | ::GenerateData()
43 | {
44 | this->CopyInputOSFGraphToOutputOSFGraphSurfaces();
45 | this->CopyInputOSFGraphToOutputOSFGraphGraph();
46 | InputOSFGraphConstPointer input = this->GetInput();
47 | // build graph
48 | m_MaxFlowGraph = new MaxFlowGraphType();
49 |
50 | this->BuildMaxFlowGraphGraph();
51 | // solve max flow
52 | m_FlowValue = m_MaxFlowGraph->solve();
53 |
54 | // store result
55 | this->UpdateResult();
56 | delete m_MaxFlowGraph;
57 | m_MaxFlowGraph = nullptr;
58 | }
59 |
60 | //----------------------------------------------------------------------------
61 | template
62 | void
63 | LOGISMOSOSFGraphSolverFilter
64 | ::BuildMaxFlowGraphGraph()
65 | {
66 | // add nodes with terminal weights
67 | using GraphNodeContainer = typename InputOSFGraphType::GraphNodesContainer;
68 | typename GraphNodeContainer::ConstPointer graphNodes = this->GetInput()->GetNodes();
69 | typename GraphNodeContainer::ConstIterator graphNodesItr = graphNodes->Begin();
70 | typename GraphNodeContainer::ConstIterator graphNodesEnd = graphNodes->End();
71 |
72 | m_MaxFlowGraph->add_nodes( graphNodes->Size() );
73 |
74 | while ( graphNodesItr!=graphNodesEnd )
75 | {
76 | typename InputOSFGraphType::GraphNodeIdentifier nodeId = graphNodesItr.Index();
77 | const typename InputOSFGraphType::GraphNode& node = graphNodesItr.Value();
78 | m_MaxFlowGraph->add_st_edge( nodeId, node.cap_source, node.cap_sink );
79 | ++graphNodesItr;
80 | }
81 |
82 | // add edges
83 | using GraphEdgesContainer = typename InputOSFGraphType::GraphEdgesContainer;
84 | typename GraphEdgesContainer::ConstPointer graphEdges = this->GetInput()->GetEdges();
85 | typename GraphEdgesContainer::ConstIterator graphEdgesItr = graphEdges->Begin();
86 | typename GraphEdgesContainer::ConstIterator graphEdgesEnd = graphEdges->End();
87 | while ( graphEdgesItr!=graphEdgesEnd )
88 | {
89 | const typename InputOSFGraphType::GraphEdge& edge = graphEdgesItr.Value();
90 | m_MaxFlowGraph->add_edge( edge.startNodeId, edge.endNodeId, edge.cap, edge.rev_cap );
91 | ++graphEdgesItr;
92 | }
93 |
94 | }
95 |
96 | //----------------------------------------------------------------------------
97 | template
98 | void
99 | LOGISMOSOSFGraphSolverFilter
100 | ::UpdateResult()
101 | {
102 | // note: we assume Boykov's max flow lib procudes the same node_id's we use
103 |
104 | // note: instead of iterating through all nodes, we could do a binary search on the nodes associated with a column
105 | // this could give some speedup in case of many column positions
106 |
107 | if (m_MaxFlowGraph==nullptr)
108 | return;
109 |
110 | InputOSFGraphConstPointer input = this->GetInput();
111 | OutputOSFGraphPointer output = this->GetOutput();
112 |
113 | // set all column positions to 0 first
114 | for (typename OutputOSFGraphType::SurfaceIdentifier surfaceId=0; surfaceIdGetNumberOfSurfaces(); surfaceId++)
115 | {
116 | typename OutputOSFGraphType::OSFSurfacePointer surface = output->GetSurface(surfaceId);
117 | for (typename OutputOSFGraphType::VertexIdentifier vertexId=0; vertexIdGetNumberOfVertices(); vertexId++)
118 | surface->SetCurrentVertexPositionIdentifier(vertexId,0);
119 | }
120 |
121 | // update to higest column position still attached to the source
122 | std::size_t numNodes = m_MaxFlowGraph->get_node_cnt();
123 | for (std::size_t nodeId=0; nodeIdin_source_set(nodeId))
126 | {
127 | // update mesh position
128 | const typename InputOSFGraphType::GraphNode& node = input->GetNode( nodeId );
129 | typename OutputOSFGraphType::OSFSurfacePointer surface = output->GetSurface(node.surfaceId);
130 | typename OutputOSFGraphType::ColumnPositionIdentifier currentColumnPosition = surface->GetCurrentVertexPositionIdentifier(node.vertexId);
131 | if (node.positionId>currentColumnPosition)
132 | surface->SetCurrentVertexPositionIdentifier(node.vertexId, node.positionId);
133 | }
134 | }
135 |
136 | }
137 |
138 | //----------------------------------------------------------------------------
139 | template
140 | void
141 | LOGISMOSOSFGraphSolverFilter
142 | ::PrintSelf(std::ostream& os, Indent indent) const
143 | {
144 | Superclass::PrintSelf(os,indent);
145 | // todo: implement
146 | }
147 |
148 | } // namespace
149 |
150 | #endif
151 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkWorkers.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 | #ifndef _itkWorkers_h
18 | #define _itkWorkers_h
19 |
20 | #include
21 |
22 | namespace itk
23 | {
24 | // TODO: write class description with usage examples
25 | /**\class Workers
26 | * \brief Runs functions in a multithreaded manner.
27 | * \date 12/9/2014
28 | * \author Christian Bauer
29 | * Runs functions in a multithreaded manner. CONTINUE
30 | */
31 | class Workers
32 | {
33 | public:
34 | Workers(int numWorkers=1024);
35 |
36 | int GetNumberOfWorkers() const;
37 |
38 | // run non-const method on object without parameters
39 | template
40 | void RunMethod(T* object, void(T::*method)(int, int) );
41 |
42 | // run non-const method on object with one parameter
43 | template
44 | void RunMethod(T* object, void(T::*method)(int, int, T1), T1 p1 );
45 |
46 | // run const method on object without parameters
47 | template
48 | void RunMethod(T* object, void(T::*method)(int, int) const );
49 |
50 | // run static method or function without parameters
51 | void RunFunction(void(*function)(int, int));
52 |
53 | // run static method or function with one parameter
54 | template
55 | void RunFunction(void(*function)(int, int, T1), T1 p1);
56 |
57 | // run non-const method on object without parameters for a specified range of values
58 | template
59 | void RunMethodForRange(T* object, void(T::*method)(RangeType), RangeType min, RangeType max );
60 |
61 | // run non-const method on object with one parameter for a specified range of values
62 | template
63 | void RunMethodForRange(T* object, void(T::*method)(RangeType, T1), RangeType min, RangeType max, T1 p1 );
64 |
65 | // run static method or function without parameters for a specified range of values
66 | template
67 | void RunFunctionForRange(void(*function)(RangeType), RangeType min, RangeType max);
68 |
69 | // run static method or function with one parameter for a specified range of values
70 | template
71 | void RunFunctionForRange(void(*function)(RangeType, T1), RangeType min, RangeType max, T1 p1);
72 |
73 | // run static method or function with two parameter for a specified range of values
74 | // TODO: implement
75 |
76 | // run static method or function with three parameter for a specified range of values
77 | template
78 | void RunFunctionForRange(void(*function)(RangeType, T1, T2, T3), RangeType min, RangeType max, T1 p1, T2 p2, T3 p3);
79 |
80 | // run static method or function with five parameter for a specified range of values
81 | template
82 | void RunFunctionForRange(void(*function)(RangeType, T1, T2, T3, T4, T5), RangeType min, RangeType max, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5);
83 |
84 | // run static method or function with six parameter for a specified range of values
85 | template
86 | void RunFunctionForRange(void(*function)(RangeType, T1, T2, T3, T4, T5, T6), RangeType min, RangeType max, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6);
87 |
88 | protected:
89 | int m_NumWorkers;
90 | using MultiThreader = itk::PlatformMultiThreader;
91 | typename MultiThreader::Pointer m_MultiThreader;
92 |
93 | // callback to run non-const method on object without parameters
94 | template
95 | static ITK_THREAD_RETURN_TYPE RunMethodCB(void* arg);
96 |
97 | // callback to run non-const method on object with one parameter
98 | template
99 | static ITK_THREAD_RETURN_TYPE RunMethodCB(void* arg);
100 |
101 | // callback to run const method on object without parameters
102 | template
103 | static ITK_THREAD_RETURN_TYPE RunConstMethodCB(void* arg);
104 |
105 | // callback to run static method or function without parameters
106 | static ITK_THREAD_RETURN_TYPE RunFunctionCB(void* arg);
107 |
108 | // callback to run static method or function with one parameter
109 | template
110 | static ITK_THREAD_RETURN_TYPE RunFunctionCB(void* arg);
111 |
112 | // callback to run method without parameters for a specified range of values
113 | template
114 | static ITK_THREAD_RETURN_TYPE RunMethodForRangeCB(void* arg);
115 |
116 | // callback to run method with one parameter for a specified range of values
117 | template
118 | static ITK_THREAD_RETURN_TYPE RunMethodForRangeCB(void* arg);
119 |
120 | // callback to run static method or function without parameters for a specified range of values
121 | template
122 | static ITK_THREAD_RETURN_TYPE RunFunctionForRangeCB(void* arg);
123 |
124 | // callback to run static method or function with one parameters for a specified range of values
125 | template
126 | static ITK_THREAD_RETURN_TYPE RunFunctionForRangeCB(void* arg);
127 |
128 | // callback to run static method or function with two parameters for a specified range of values
129 | // TODO: implement
130 |
131 | // callback to run static method or function with three parameters for a specified range of values
132 | template
133 | static ITK_THREAD_RETURN_TYPE RunFunctionForRangeCB(void* arg);
134 |
135 | // callback to run static method or function with five parameters for a specified range of values
136 | template
137 | static ITK_THREAD_RETURN_TYPE RunFunctionForRangeCB(void* arg);
138 |
139 | // callback to run static method or function with six parameters for a specified range of values
140 | template
141 | static ITK_THREAD_RETURN_TYPE RunFunctionForRangeCB(void* arg);
142 | };
143 |
144 | } // end namespace itk
145 |
146 | #ifndef ITK_MANUAL_INSTANTIATION
147 | #include "itkWorkers.txx"
148 | #endif
149 |
150 | #endif
151 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkOSFSurface.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkOSFSurface_h
19 | #define _itkOSFSurface_h
20 |
21 | #include
22 | #include
23 | #include
24 |
25 | namespace itk
26 | {
27 | /**\class OSFSurface
28 | * \brief
29 | * \date 12/9/2014
30 | * \author Christian Bauer
31 | * ?
32 | * Template parameters for class OSFSurface:
33 | *
34 | * - TCostType = ?
35 | * - TSurfaceMeshTraits = ?
36 | */
37 |
38 | template >
39 | class ITK_EXPORT OSFSurface : public Object // todo: should probably change to DataObject
40 | {
41 | public:
42 | using Self = OSFSurface;
43 | using Superclass = Object;
44 | using Pointer = SmartPointer< Self >;
45 | using ConstPointer = SmartPointer< const Self >;
46 |
47 | ITK_DISALLOW_COPY_AND_ASSIGN(OSFSurface);
48 |
49 | itkNewMacro(Self);
50 | itkTypeMacro(OSFSurface, Object);
51 |
52 | // utility type alias that helps defining cells and coordinates
53 | using MeshTraits = TSurfaceMeshTraits;
54 |
55 | // type aliases for identifiers
56 | using IdentifierType = unsigned long;
57 | using VertexIdentifier = IdentifierType;
58 | using ColumnPositionIdentifier = IdentifierType;
59 | using CellIdentifier = IdentifierType;
60 |
61 | // type aliases for a column of an OSF surface
62 | using CoordRepType= typename MeshTraits::CoordRepType;
63 | static constexpr unsigned int PointDimension = MeshTraits::PointDimension;
64 | using CoordinateType = typename MeshTraits::PointType;
65 | using ColumnCoordinatesContainer = VectorContainer< ColumnPositionIdentifier, CoordinateType >;
66 | using ColumnCostType = TCostType;
67 | using ColumnCostsContainer = VectorContainer< ColumnPositionIdentifier, ColumnCostType >;
68 |
69 | // type aliases for a vertex of an OSF surface (not a coordinate, but a whole column)
70 | using VertexColumnCoordinatesContainer = VectorContainer< VertexIdentifier, typename ColumnCoordinatesContainer::Pointer >;
71 | using VertexColumnCostsContainer = VectorContainer< VertexIdentifier, typename ColumnCostsContainer::Pointer >;
72 | using VertexPositionIdentifierContainer = VectorContainer< VertexIdentifier, ColumnPositionIdentifier >;
73 |
74 | // type aliases for a cell of an OSF surface
75 | using CellTraits= typename MeshTraits::CellTraits ;
76 | using CellPixelType = typename MeshTraits::CellPixelType;
77 | using CellType = CellInterface< CellPixelType, CellTraits >;
78 | using CellRawPointer = typename CellType::CellRawPointer;
79 | using CellAutoPointer = typename CellType::CellAutoPointer;
80 | using CellsContainer = typename MeshTraits::CellsContainer;
81 |
82 | VertexIdentifier GetNumberOfVertices( ) const;
83 | ColumnPositionIdentifier GetNumberOfColumns(VertexIdentifier vertexId) const;
84 |
85 | // access to column coordinates of a vertex
86 | ColumnCoordinatesContainer* GetColumnCoordinates(VertexIdentifier vertexId);
87 | const ColumnCoordinatesContainer* GetColumnCoordinates(VertexIdentifier vertexId) const;
88 | void SetColumnCoordinates(VertexIdentifier vertexId, ColumnCoordinatesContainer* columnCoordinates);
89 |
90 | // access to column costs of a vertex
91 | ColumnCostsContainer* GetColumnCosts(VertexIdentifier vertexId);
92 | const ColumnCostsContainer* GetColumnCosts(VertexIdentifier vertexId) const;
93 | void SetColumnCosts(VertexIdentifier vertexId, ColumnCostsContainer* columnCosts);
94 |
95 | // access to initial vertex position
96 | const CoordinateType& GetInitialVertexPosition(VertexIdentifier vertexId) const;
97 | ColumnPositionIdentifier GetInitialVertexPositionIdentifier(VertexIdentifier vertexId) const;
98 | void SetInitialVertexPositionIdentifier(VertexIdentifier vertexId, ColumnPositionIdentifier columnPositionId);
99 |
100 | // access to current vertex position
101 | const CoordinateType& GetCurrentVertexPosition(VertexIdentifier vertexId) const;
102 | ColumnPositionIdentifier GetCurrentVertexPositionIdentifier(VertexIdentifier vertexId) const;
103 | void SetCurrentVertexPositionIdentifier(VertexIdentifier vertexId, ColumnPositionIdentifier columnPositionId);
104 |
105 | // access to cells
106 | CellsContainer* GetCells();
107 | const CellsContainer* GetCells() const;
108 | void SetCells(CellsContainer* cells);
109 |
110 | // access to individual cells
111 | CellIdentifier GetNumberOfCells() const;
112 | bool GetCell(CellIdentifier cellId, CellAutoPointer& cellPointer) const;
113 | void SetCell(CellIdentifier cellId, CellAutoPointer& cellPointer);
114 |
115 | // allow lookup of neighboring of columns on the surface
116 | using VertexIdentifierContainer = VectorContainer< unsigned int, VertexIdentifier >;
117 | const VertexIdentifierContainer* GetNeighbors(VertexIdentifier vertexId) const;
118 | void BuildNeighborLookupTable();
119 |
120 | // todo: do we need cell links like provided by the itk::Mesh?
121 | //using PointCellLinksContainer = typename MeshTraits::PointCellLinksContainer; // todo: do we need this?
122 | //using CellLinksContainer = typename MeshTraits::CellLinksContainer; // todo: do we need this?
123 |
124 | protected:
125 | /** Constructor for use by New() method. */
126 | OSFSurface() = default;
127 | ~OSFSurface() override = default;
128 | void PrintSelf(std::ostream& os, Indent indent) const override;
129 |
130 | typename VertexColumnCoordinatesContainer::Pointer m_VertexColumnCoordinatesContainer{ VertexColumnCoordinatesContainer::New() };
131 | typename VertexColumnCostsContainer::Pointer m_VertexColumnCostsContainer{ VertexColumnCostsContainer::New() };
132 | VertexPositionIdentifierContainer::Pointer m_VertexInitialPositionIdentifierContainer{ VertexPositionIdentifierContainer::New() };
133 | VertexPositionIdentifierContainer::Pointer m_VertexCurrentPositionIdentifierContainer{ VertexPositionIdentifierContainer::New() };
134 | typename CellsContainer::Pointer m_CellsContainer{ CellsContainer::New() };
135 |
136 | void ReleaseCellsMemory();
137 |
138 | using VertexIdentifierListContainer = VectorContainer< VertexIdentifier, typename VertexIdentifierContainer::Pointer >;
139 | VertexIdentifierListContainer::Pointer m_VertexNeighborLookupTable;
140 |
141 | private:
142 | void AddVertexNeighbors(VertexIdentifier vertex1, VertexIdentifier vertex2);
143 |
144 | }; // end class OSFSurface
145 |
146 | } // namespace
147 |
148 | #ifndef ITK_MANUAL_INSTANTIATION
149 | #include "itkOSFSurface.txx"
150 | #endif
151 |
152 | #endif
153 |
154 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkCenterNormalColumnBuilderFilter.txx:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkCenterNormalColumnBuilderFilter_txx
19 | #define _itkCenterNormalColumnBuilderFilter_txx
20 |
21 | #include "itkCenterNormalColumnBuilderFilter.h"
22 |
23 |
24 | /*
25 | Differences from itkSurfaceNormalColumnBuilderFilter:
26 | 1. Normal for point to center rather surface outwards
27 | 2. No steps backward.
28 | 3. Define either step length of number of steps. One will define the other.
29 | 4. Must define the center of the region.
30 | */
31 |
32 | namespace itk
33 | {
34 |
35 | //----------------------------------------------------------------------------
36 | template
37 | void
38 | CenterNormalColumnBuilderFilter
39 | ::GenerateData()
40 | {
41 | if( this->GetInput()->GetNumberOfSurfaces()!=1 )
42 | {
43 | itkWarningMacro("CenterNormalColumnBuilderFilter currently only supports one surface!");
44 | }
45 |
46 | //Copy the basic surface information.
47 | this->CopyInputOSFGraphToOutputOSFGraphSurfaces();
48 |
49 | //Create cells based on the vertices.
50 | BuildVertexToCellLookupTable();
51 |
52 | OutputOSFGraphPointer output = this->GetOutput();
53 | typename OSFSurface::Pointer surface = output->GetSurface();
54 |
55 | //Build each column, one per vertex.
56 | for (VertexIdentifier vertexId=0; vertexIdGetNumberOfVertices(); vertexId++)
57 | { this->BuildColumn(vertexId);}
58 |
59 | }
60 |
61 | //----------------------------------------------------------------------------
62 | template
63 | void
64 | CenterNormalColumnBuilderFilter
65 | ::BuildColumn(VertexIdentifier vertexId)
66 | {
67 | typename OSFSurface::ConstPointer inputSurface = this->GetInput()->GetSurface();
68 | typename OSFSurface::Pointer outputSurface = this->GetOutput()->GetSurface();
69 |
70 | using Coordinate = typename OSFSurface::CoordinateType;
71 | using ColumnCoordinatesContainer = typename OSFSurface::ColumnCoordinatesContainer;
72 | using ColumnCostsContainer = typename OSFSurface::ColumnCostsContainer;
73 |
74 | Coordinate initialPosition;
75 | initialPosition[0] = m_CenterPoint[0];
76 | initialPosition[1] = m_CenterPoint[1];
77 | initialPosition[2] = m_CenterPoint[2];
78 |
79 | //Determine proper direction vector from center to vertex with magnitude 1.
80 | DirectionVector CenterNormalDirection = GetNormal(vertexId);
81 | auto columnPositions = ColumnCoordinatesContainer::New();
82 | columnPositions->CreateIndex( m_NumberOfSteps-1 );
83 |
84 |
85 | // build column coordinates
86 | // Given a vector of magnitude 1 away from the center and the center as an initial position,
87 | // multiply the vector by the number of steps (from 1 to the maximum number of nodes) and the
88 | // length of each step.
89 |
90 | // center outward
91 | for (unsigned int step=0; stepSetElement( step, currentPosition );
95 | }
96 |
97 | //Apply these coordinates to the graph
98 | outputSurface->SetColumnCoordinates( vertexId, columnPositions );
99 |
100 | //Apply default costs
101 | auto columnCosts = ColumnCostsContainer::New();
102 | columnCosts->CreateIndex( columnPositions->Size()-1 );
103 | outputSurface->SetColumnCosts( vertexId, columnCosts );
104 |
105 | //Apply a default position at the centermost node
106 | outputSurface->SetInitialVertexPositionIdentifier( vertexId, 0 );
107 | }
108 |
109 | //----------------------------------------------------------------------------
110 | template
111 | typename CenterNormalColumnBuilderFilter::DirectionVector
112 | CenterNormalColumnBuilderFilter
113 | ::GetNormal(const VertexIdentifier vertexId) const
114 | {
115 | DirectionVector direction;
116 | direction.Fill(0.0);
117 | using Point = typename OSFSurface::CoordinateType;
118 |
119 | auto inputSurface = this->GetInput()->GetSurface();
120 |
121 | Point centerPosition;
122 | centerPosition[0] = m_CenterPoint[0];
123 | centerPosition[1] = m_CenterPoint[1];
124 | centerPosition[2] = m_CenterPoint[2];
125 |
126 | //From the center point to the vertex of this column is the outward normal direction
127 | //Use point subtraction to get a vector from center to vertex
128 | Point vertexPosition = inputSurface->GetInitialVertexPosition( vertexId );
129 |
130 | direction[0] = vertexPosition[0] - centerPosition[0];
131 | direction[1] = vertexPosition[1] - centerPosition[1];
132 | direction[2] = vertexPosition[2] - centerPosition[2];
133 |
134 |
135 | // make compiler happy/normalize resulting vector
136 | if (direction.GetSquaredNorm()>0)
137 | direction.Normalize();
138 | return direction;
139 | }
140 |
141 |
142 |
143 | //----------------------------------------------------------------------------
144 | //Pre-built function
145 | template
146 | void
147 | CenterNormalColumnBuilderFilter
148 | ::BuildVertexToCellLookupTable()
149 | {
150 | typename OSFSurface::ConstPointer inputSurface = this->GetInput()->GetSurface();
151 | typename OSFSurface::CellsContainer::ConstPointer cells = inputSurface->GetCells();
152 | typename OSFSurface::CellsContainer::ConstIterator cellItr = cells->Begin();
153 | typename OSFSurface::CellsContainer::ConstIterator cellEnd = cells->End();
154 |
155 | m_VertexToCellLookupTable.clear();
156 | m_VertexToCellLookupTable.resize(cells->Size());
157 |
158 | while ( cellItr!=cellEnd )
159 | {
160 | const typename OSFSurface::CellType* cellPointer = cellItr.Value();
161 | unsigned int numberOfPoints = cellPointer->GetNumberOfPoints();
162 | if (numberOfPoints>1)
163 | {
164 | typename OSFSurface::CellType::PointIdConstIterator pointIdIterator = cellPointer->PointIdsBegin();
165 | typename OSFSurface::CellType::PointIdConstIterator pointIdEnd = cellPointer->PointIdsEnd();
166 | while( pointIdIterator!=pointIdEnd )
167 | {
168 | m_VertexToCellLookupTable[ *pointIdIterator ].insert( cellItr.Index() );
169 | ++pointIdIterator;
170 | }
171 | }
172 |
173 | ++cellItr;
174 | }
175 | }
176 |
177 | //----------------------------------------------------------------------------
178 | template
179 | void
180 | CenterNormalColumnBuilderFilter
181 | ::PrintSelf(std::ostream& os, Indent indent) const
182 | {
183 | Superclass::PrintSelf(os,indent);
184 | // todo: implement
185 | }
186 |
187 | } // namespace
188 |
189 | #endif
190 |
191 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkMeshToOSFGraphFilter.txx:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkMeshToOSFGraphFilter_txx
19 | #define _itkMeshToOSFGraphFilter_txx
20 |
21 | #include "itkMeshToOSFGraphFilter.h"
22 |
23 | namespace itk
24 | {
25 |
26 | //----------------------------------------------------------------------------
27 | template
28 | MeshToOSFGraphFilter
29 | ::MeshToOSFGraphFilter()
30 | {
31 | this->ProcessObject::SetNumberOfRequiredInputs(1);
32 |
33 | OutputOSFGraphPointer output
34 | = dynamic_cast(this->MakeOutput(0).GetPointer());
35 |
36 | this->ProcessObject::SetNumberOfRequiredOutputs(1);
37 | this->ProcessObject::SetNthOutput(0, output.GetPointer());
38 |
39 | }
40 |
41 | //----------------------------------------------------------------------------
42 | template
43 | void
44 | MeshToOSFGraphFilter
45 | ::SetInput(unsigned int idx, const InputMeshType* input)
46 | {
47 | // process object is not const-correct, the const_cast
48 | // is required here.
49 | this->ProcessObject::SetNthInput(idx, const_cast< InputMeshType * >(input) );
50 | }
51 |
52 | //----------------------------------------------------------------------------
53 | template
54 | const typename MeshToOSFGraphFilter::InputMeshType*
55 | MeshToOSFGraphFilter
56 | ::GetInput(unsigned int idx)
57 | {
58 | return dynamic_cast (this->ProcessObject::GetInput(idx));
59 | }
60 |
61 | //----------------------------------------------------------------------------
62 | template
63 | typename MeshToOSFGraphFilter::OutputOSFGraphType*
64 | MeshToOSFGraphFilter
65 | ::GetOutput()
66 | {
67 | return dynamic_cast (this->ProcessObject::GetOutput(0));
68 | }
69 |
70 | //----------------------------------------------------------------------------
71 | template
72 | void
73 | MeshToOSFGraphFilter
74 | ::GenerateOutputInformation()
75 | {
76 | // todo: do we have to do something here?
77 | }
78 |
79 | //----------------------------------------------------------------------------
80 | template
81 | DataObject::Pointer
82 | MeshToOSFGraphFilter
83 | ::MakeOutput(DataObjectPointerArraySizeType)
84 | {
85 | OutputOSFGraphPointer outputOSFGraph = OutputOSFGraphType::New();
86 | return dynamic_cast< DataObject *>( outputOSFGraph.GetPointer() );
87 | }
88 |
89 | //----------------------------------------------------------------------------
90 | template
91 | void
92 | MeshToOSFGraphFilter
93 | ::PrintSelf(std::ostream& os, Indent indent) const
94 | {
95 | Superclass::PrintSelf(os,indent);
96 | // todo: implement
97 | }
98 |
99 | //----------------------------------------------------------------------------
100 | template
101 | void
102 | MeshToOSFGraphFilter
103 | ::GenerateData()
104 | {
105 | auto outputOSFGraph = this->GetOutput();
106 | for (typename OutputOSFGraphType::SurfaceIdentifier surfaceId=0; surfaceIdGetNumberOfInputs(); surfaceId++)
107 | {
108 | InputMeshConstPointer currentInputSurface = this->GetInput(surfaceId);
109 | typename OutputOSFGraphType::OSFSurface::Pointer currentOutputSurface = outputOSFGraph->GetSurface(surfaceId);
110 | this->CopyInputMeshToOutputOSFSurfacePoints(currentInputSurface,currentOutputSurface);
111 | this->CopyInputMeshToOutputOSFSurfaceCells(currentInputSurface,currentOutputSurface);
112 | }
113 |
114 | }
115 |
116 | //----------------------------------------------------------------------------
117 | template
118 | void
119 | MeshToOSFGraphFilter
120 | ::CopyInputMeshToOutputOSFSurfacePoints(InputMeshConstPointer mesh, typename OutputOSFGraphType::OSFSurface::Pointer osfSurface)
121 | {
122 | using PointIterator = typename TInputMesh::PointsContainer::ConstIterator;
123 | using PointType = typename TInputMesh::PointType;
124 | PointIterator pointIterator = mesh->GetPoints()->Begin();
125 | PointIterator pointEnd = mesh->GetPoints()->End();
126 |
127 | while( pointIterator != pointEnd )
128 | {
129 | typename OutputOSFGraphType::OSFSurface::VertexIdentifier vertexId = pointIterator.Index();
130 | PointType point = pointIterator.Value();
131 |
132 | using ColumnCoordinatesContainerType = typename OutputOSFGraphType::OSFSurface::ColumnCoordinatesContainer;
133 | auto columnCoordinatesContainer = ColumnCoordinatesContainerType::New();
134 | columnCoordinatesContainer->InsertElement(0, point );
135 | osfSurface->SetColumnCoordinates(vertexId, columnCoordinatesContainer);
136 | using ColumnCostsContainerType = typename OutputOSFGraphType::OSFSurface::ColumnCostsContainer;
137 | auto columnCostsContainer = ColumnCostsContainerType::New();
138 | columnCostsContainer->InsertElement(0, 0.0 );
139 | osfSurface->SetColumnCosts(vertexId,columnCostsContainer);
140 | osfSurface->SetInitialVertexPositionIdentifier(vertexId,0);
141 | osfSurface->SetCurrentVertexPositionIdentifier(vertexId,0);
142 |
143 | pointIterator++;
144 | }
145 | }
146 |
147 | //----------------------------------------------------------------------------
148 | template
149 | void
150 | MeshToOSFGraphFilter
151 | ::CopyInputMeshToOutputOSFSurfaceCells(InputMeshConstPointer mesh, typename OutputOSFGraphType::OSFSurface::Pointer osfSurface)
152 | {
153 | using OutputCellsContainer = typename OutputOSFGraphType::OSFSurface::CellsContainer;
154 | using InputCellsContainer = typename TInputMesh::CellsContainer;
155 | using CellAutoPointer = typename OutputOSFGraphType::OSFSurface::CellAutoPointer;
156 |
157 | //outputMesh->SetCellsAllocationMethod( OutputMeshType::CellsAllocatedDynamicallyCellByCell );
158 |
159 | auto outputCells = OutputCellsContainer::New();
160 | const InputCellsContainer * inputCells = mesh->GetCells();
161 |
162 | if( inputCells )
163 | {
164 | outputCells->Reserve( inputCells->Size() );
165 |
166 | typename InputCellsContainer::ConstIterator inputItr = inputCells->Begin();
167 | typename InputCellsContainer::ConstIterator inputEnd = inputCells->End();
168 |
169 | typename OutputCellsContainer::Iterator outputItr = outputCells->Begin();
170 |
171 | CellAutoPointer clone;
172 |
173 | while( inputItr != inputEnd )
174 | {
175 | // outputItr.Value() = inputItr.Value();
176 | // note: this comment is from itkMeshToMeshFilter // BUG: FIXME: Here we are copying a pointer, which is a mistake. What we should do is to clone the cell.
177 | inputItr.Value()->MakeCopy( clone );
178 | outputItr.Value() = clone.ReleaseOwnership();
179 |
180 | ++inputItr;
181 | ++outputItr;
182 | }
183 |
184 | osfSurface->SetCells( outputCells );
185 | }
186 | }
187 |
188 | } // namespace
189 |
190 | #endif
191 |
192 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkOSFGraphToMeshFilter.txx:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef __itkOSFGraphToMeshFilter_txx
19 | #define __itkOSFGraphToMeshFilter_txx
20 |
21 | #include "itkOSFGraphToMeshFilter.h"
22 |
23 | namespace itk
24 | {
25 |
26 | //----------------------------------------------------------------------------
27 | template
28 | OSFGraphToMeshFilter
29 | ::OSFGraphToMeshFilter() :
30 | m_SurfaceType(CurrentSurface)
31 | {
32 | this->ProcessObject::SetNumberOfRequiredInputs(1);
33 |
34 | OutputMeshPointer output
35 | = dynamic_cast(this->MakeOutput(0).GetPointer());
36 |
37 | this->ProcessObject::SetNumberOfRequiredOutputs(1);
38 | this->ProcessObject::SetNthOutput(0, output.GetPointer());
39 |
40 | }
41 |
42 | //----------------------------------------------------------------------------
43 | template
44 | DataObject::Pointer
45 | OSFGraphToMeshFilter
46 | ::MakeOutput(DataObjectPointerArraySizeType)
47 | {
48 | auto outputMesh = OutputMeshType::New();
49 | return dynamic_cast< DataObject *>( outputMesh.GetPointer() );
50 | }
51 |
52 | //----------------------------------------------------------------------------
53 | template
54 | void
55 | OSFGraphToMeshFilter
56 | ::SetInput(const InputOSFGraphType* input)
57 | {
58 | // process object is not const-correct, the const_cast is required here.
59 | this->ProcessObject::SetNthInput(0, const_cast< InputOSFGraphType * >(input) );
60 | }
61 |
62 | //----------------------------------------------------------------------------
63 | template
64 | const typename OSFGraphToMeshFilter::InputOSFGraphType*
65 | OSFGraphToMeshFilter
66 | ::GetInput()
67 | {
68 | return dynamic_cast (this->ProcessObject::GetInput(0));
69 | }
70 |
71 | //----------------------------------------------------------------------------
72 | template
73 | typename OSFGraphToMeshFilter::OutputMeshType *
74 | OSFGraphToMeshFilter
75 | ::GetOutput(unsigned int idx)
76 | {
77 | return dynamic_cast
78 | (this->ProcessObject::GetOutput(idx));
79 | }
80 |
81 | //----------------------------------------------------------------------------
82 | template
83 | void
84 | OSFGraphToMeshFilter
85 | ::GenerateData()
86 | {
87 | InputOSFGraphConstPointer inputOSFGraph = this->GetInput();
88 | for (typename InputOSFGraphType::SurfaceIdentifier surfaceId=0; surfaceIdGetNumberOfSurfaces(); surfaceId++)
89 | {
90 | OutputMeshPointer currentOutputSurface = this->GetOutput(surfaceId);
91 | // todo: we have to create the output meshes first in case we have multiple. One is already created per default in the constructor
92 | typename InputOSFGraphType::OSFSurface::ConstPointer currentInputSurface = inputOSFGraph->GetSurface(surfaceId);
93 | this->CopyInputOSFSurfaceToOutputMeshPoints(currentInputSurface, currentOutputSurface);
94 | this->CopyInputOSFSurfaceToOutputMeshCells(currentInputSurface, currentOutputSurface);
95 | }
96 | }
97 |
98 | //----------------------------------------------------------------------------
99 | template
100 | void
101 | OSFGraphToMeshFilter
102 | ::GenerateOutputInformation()
103 | {
104 | // todo: do we have to do something here?
105 | // todo: does this actually create addititional output meshes depending on the number of surfaces in the input graph
106 | for (typename InputOSFGraphType::SurfaceIdentifier surfaceId=this->GetNumberOfOutputs(); surfaceIdGetInput()->GetNumberOfSurfaces(); surfaceId++)
107 | {
108 | OutputMeshPointer output = dynamic_cast(this->MakeOutput(surfaceId).GetPointer());
109 | this->ProcessObject::SetNumberOfRequiredOutputs(this->GetInput()->GetNumberOfSurfaces());
110 | this->ProcessObject::SetNthOutput(surfaceId, output.GetPointer());
111 | }
112 | }
113 |
114 | //----------------------------------------------------------------------------
115 | template
116 | void
117 | OSFGraphToMeshFilter
118 | ::CopyInputOSFSurfaceToOutputMeshPoints(typename InputOSFGraphType::OSFSurface::ConstPointer osfSurface, OutputMeshPointer mesh)
119 | {
120 | auto points = OutputMeshType::PointsContainer::New();
121 | points->Reserve( osfSurface->GetNumberOfVertices() );
122 | typename OutputMeshType::PointsContainer::Iterator pointIterator = points->Begin();
123 | typename OutputMeshType::PointsContainer::Iterator pointEnd = points->End();
124 |
125 | while ( pointIterator != pointEnd )
126 | {
127 | typename InputOSFGraphType::OSFSurface::VertexIdentifier vertexId = pointIterator.Index();
128 | typename InputOSFGraphType::OSFSurface::ColumnPositionIdentifier columnPositionId = 0;
129 | switch(m_SurfaceType)
130 | {
131 | case CurrentSurface: columnPositionId = osfSurface->GetCurrentVertexPositionIdentifier(vertexId); break;
132 | case InitialSurface: columnPositionId = osfSurface->GetInitialVertexPositionIdentifier(vertexId); break;
133 | case InnermostSurface: columnPositionId = 0; break;
134 | case OutermostSurface: columnPositionId = (osfSurface->GetNumberOfColumns(vertexId)>0) ? osfSurface->GetNumberOfColumns(vertexId) : 0; break;
135 | default: columnPositionId = osfSurface->GetCurrentVertexPositionIdentifier(vertexId);
136 | }
137 | pointIterator.Value() = osfSurface->GetColumnCoordinates(vertexId)->ElementAt(columnPositionId);
138 | ++pointIterator;
139 | }
140 |
141 | mesh->SetPoints(points);
142 | }
143 |
144 | //----------------------------------------------------------------------------
145 | template
146 | void
147 | OSFGraphToMeshFilter
148 | ::CopyInputOSFSurfaceToOutputMeshCells(typename InputOSFGraphType::OSFSurface::ConstPointer osfSurface, OutputMeshPointer mesh)
149 | {
150 | using InputCellsContainer = typename InputOSFGraphType::OSFSurface::CellsContainer;
151 | using OutputCellsContainer = typename TOutputMesh::CellsContainer;
152 | using CellAutoPointer = typename InputOSFGraphType::OSFSurface::CellAutoPointer;
153 |
154 | mesh->SetCellsAllocationMethod( OutputMeshType::CellsAllocatedDynamicallyCellByCell );
155 |
156 | auto outputCells = OutputCellsContainer::New();
157 | const InputCellsContainer * inputCells = osfSurface->GetCells();
158 |
159 | if( inputCells )
160 | {
161 | outputCells->Reserve( inputCells->Size() );
162 |
163 | typename InputCellsContainer::ConstIterator inputItr = inputCells->Begin();
164 | typename InputCellsContainer::ConstIterator inputEnd = inputCells->End();
165 |
166 | typename OutputCellsContainer::Iterator outputItr = outputCells->Begin();
167 |
168 | CellAutoPointer clone;
169 |
170 | while( inputItr != inputEnd )
171 | {
172 | // outputItr.Value() = inputItr.Value();
173 | // note: this comment is from itkMeshToMeshFilter // BUG: FIXME: Here we are copying a pointer, which is a mistake. What we should do is to clone the cell.
174 | inputItr.Value()->MakeCopy( clone );
175 | outputItr.Value() = clone.ReleaseOwnership();
176 |
177 | ++inputItr;
178 | ++outputItr;
179 | }
180 |
181 | mesh->SetCells( outputCells );
182 | }
183 | }
184 |
185 | //----------------------------------------------------------------------------
186 | template
187 | void
188 | OSFGraphToMeshFilter
189 | ::PrintSelf(std::ostream& os, Indent indent) const
190 | {
191 | Superclass::PrintSelf(os,indent);
192 | // todo: implement
193 | }
194 |
195 | } // end namespace itk
196 |
197 | #endif
198 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkOSFGraph.h:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkOSFGraph_h
19 | #define _itkOSFGraph_h
20 |
21 | #include
22 | #include "itkOSFSurface.h"
23 |
24 | namespace itk
25 | {
26 | /**\class OSFGraph
27 | * \brief The class for holding the graph information.
28 | * \date 12/9/2014
29 | * \author Chrsitian Bauer
30 | * ?
31 | * Template parameters for class OSFGraph:
32 | *
33 | * - TCostType = ?
34 | * - TOSFSurfaceType = ?
35 | */
36 | template >
37 | class ITK_EXPORT OSFGraph : public DataObject
38 | {
39 | public:
40 | using Self = OSFGraph;
41 | using Superclass = DataObject;
42 | using Pointer = SmartPointer< Self >;
43 | using ConstPointer = SmartPointer< const Self >;
44 |
45 | ITK_DISALLOW_COPY_AND_ASSIGN(OSFGraph);
46 |
47 | itkNewMacro( Self );
48 | itkTypeMacro( OSFGraph, DataObject );
49 |
50 | using IdentifierType = unsigned long;
51 |
52 | //--------------------------------------------------------------
53 | // surfaces
54 | //--------------------------------------------------------------
55 | using OSFSurface = TOSFSurfaceType;
56 | using VertexIdentifier = typename OSFSurface::VertexIdentifier;
57 | using ColumnPositionIdentifier = typename OSFSurface::ColumnPositionIdentifier;
58 | using SurfaceIdentifier = IdentifierType;
59 | using OSFSurfacePointer = typename OSFSurface::Pointer;
60 | using OSFSurfaceConstPointer = typename OSFSurface::ConstPointer;
61 | using SurfacesContainer = VectorContainer< SurfaceIdentifier, OSFSurfacePointer >;
62 |
63 | // access to surfaces
64 | SurfaceIdentifier GetNumberOfSurfaces() const;
65 | OSFSurface* GetSurface(SurfaceIdentifier surfaceId=0);
66 | const OSFSurface* GetSurface(SurfaceIdentifier surfaceId=0) const;
67 | void SetSurface(OSFSurfacePointer surface) {return this->SetSurface(0, surface);};
68 | void SetSurface(SurfaceIdentifier surfaceId, OSFSurface* surface);
69 |
70 | //--------------------------------------------------------------
71 | // graph nodes and edges
72 | //--------------------------------------------------------------
73 | using GraphCosts = TCostType;
74 | using GraphNodeIdentifier = IdentifierType;
75 | using GraphEdgeIdentifier = IdentifierType;
76 |
77 | class GraphNode
78 | {
79 | public:
80 | GraphNode() = default;
81 | GraphNode(SurfaceIdentifier surfaceId_, VertexIdentifier vertexId_, ColumnPositionIdentifier positionId_, GraphCosts cap_source_, GraphCosts cap_sink_) :
82 | surfaceId(surfaceId_), vertexId(vertexId_), positionId(positionId_), cap_source(cap_source_), cap_sink(cap_sink_) {};
83 | SurfaceIdentifier surfaceId{ 0 };
84 | VertexIdentifier vertexId{ 0 };
85 | ColumnPositionIdentifier positionId{ 0 };
86 | GraphCosts cap_source{ 0 };
87 | GraphCosts cap_sink{ 0 };
88 | };
89 |
90 | class GraphEdge
91 | {
92 | public:
93 | GraphEdge() = default;
94 | GraphEdge(GraphNodeIdentifier startNodeId_, GraphNodeIdentifier endNodeId_, GraphCosts cap_, GraphCosts rev_cap_) :
95 | startNodeId(startNodeId_), endNodeId(endNodeId_), cap(cap_), rev_cap(rev_cap_) {};
96 | GraphNodeIdentifier startNodeId{ 0 };
97 | GraphNodeIdentifier endNodeId{ 0 };
98 | GraphCosts cap{ 0 };
99 | GraphCosts rev_cap{ 0 };
100 | };
101 |
102 | using GraphNodesContainer = VectorContainer< GraphNodeIdentifier, GraphNode >;
103 | using GraphEdgesContainer = VectorContainer< GraphEdgeIdentifier, GraphEdge >;
104 |
105 | // access to nodes
106 | GraphNodeIdentifier GetNumberOfNodes() const;
107 | GraphNode& GetNode(GraphNodeIdentifier nodeId);
108 | const GraphNode& GetNode(GraphNodeIdentifier nodeId) const;
109 | void SetNode(GraphNodeIdentifier nodeId, const GraphNode& node);
110 | GraphNodesContainer* GetNodes();
111 | const GraphNodesContainer* GetNodes() const;
112 | void SetNodes(GraphNodesContainer* nodes);
113 |
114 | // access to edges
115 | GraphEdgeIdentifier GetNumberOfEdges() const;
116 | GraphEdge& GetEdge(GraphEdgeIdentifier edgeId);
117 | const GraphEdge& GetEdge(GraphEdgeIdentifier edgeId) const;
118 | void SetEdge(GraphEdgeIdentifier edgeId, const GraphEdge& edge);
119 | GraphEdgesContainer* GetEdges();
120 | const GraphEdgesContainer* GetEdges() const;
121 | void SetEdges(GraphEdgesContainer* edges);
122 |
123 | // utility function for fast lookup of graph nodes/edges associated with a SurfaceVertexColumnPosition
124 | // after graph construction (nodes/edges) the internally used lookup table has to be build first
125 | void BuildGraphNodeIdentifierLookupTable();
126 | GraphNodeIdentifier GetNodeIdentifer(SurfaceIdentifier surfaceId, VertexIdentifier vertexId, ColumnPositionIdentifier columnPositionId) const;
127 | GraphNode& GetNode(SurfaceIdentifier surfaceId, VertexIdentifier vertexId, ColumnPositionIdentifier columnPositionId);
128 | const GraphNode& GetNode(SurfaceIdentifier surfaceId, VertexIdentifier vertexId, ColumnPositionIdentifier columnPositionId) const;
129 |
130 | /** Type used to define Regions */
131 | using RegionType = long;
132 |
133 | void Initialize(void) override;
134 |
135 | /** Get the maximum number of regions that this data can be
136 | * separated into. */
137 | itkGetConstMacro( MaximumNumberOfRegions, RegionType );
138 |
139 | /** Set the requested region from this data object to match the requested
140 | * region of the data object passed in as a parameter. This method
141 | * implements the API from DataObject. The data object parameter must be
142 | * castable to a PointSet. */
143 | //virtual void SetRequestedRegion(DataObject *data); // TODO: this causes troubles when creating python binding for c++ overloading
144 |
145 | /** Methods to manage streaming. */
146 | void UpdateOutputInformation() override;
147 | void SetRequestedRegionToLargestPossibleRegion() override;
148 | void CopyInformation(const DataObject *data) override;
149 | void Graft(const DataObject *data) override;
150 | bool RequestedRegionIsOutsideOfTheBufferedRegion() override;
151 | bool VerifyRequestedRegion() override;
152 |
153 | /** Set/Get the Requested region */
154 | //virtual void SetRequestedRegion( const RegionType & region ); // TODO: this causes troubles when creating python binding for c++ overloading
155 | itkGetConstMacro( RequestedRegion, RegionType );
156 |
157 | /** Set/Get the Buffered region */
158 | virtual void SetBufferedRegion( const RegionType & region );
159 | itkGetConstMacro( BufferedRegion, RegionType );
160 |
161 | protected:
162 | /** Constructor for use by New() method. */
163 | OSFGraph() = default;
164 | ~OSFGraph() override = default;
165 | void PrintSelf(std::ostream& os, Indent indent) const override;
166 |
167 | typename SurfacesContainer::Pointer m_SurfacesContainer{ SurfacesContainer::New() };
168 | typename GraphNodesContainer::Pointer m_GraphNodesContainer{ GraphNodesContainer::New() };
169 | typename GraphEdgesContainer::Pointer m_GraphEdgesContainer{ GraphEdgesContainer::New() };
170 |
171 | std::vector< std::vector< std::vector< GraphNodeIdentifier > > > m_GraphNodeIdentifierLookupTable; // todo: probably not optimal data structure but should be sufficient
172 |
173 | // If the RegionType is ITK_UNSTRUCTURED_REGION, then the following
174 | // variables represent the maximum number of region that the data
175 | // object can be broken into, which region out of how many is
176 | // currently in the buffered region, and the number of regions and
177 | // the specific region requested for the update. Data objects that
178 | // do not support any division of the data can simply leave the
179 | // MaximumNumberOfRegions as 1. The RequestedNumberOfRegions and
180 | // RequestedRegion are used to define the currently requested
181 | // region. The LargestPossibleRegion is always requested region = 0
182 | // and number of regions = 1;
183 | RegionType m_MaximumNumberOfRegions{ 1 };
184 | RegionType m_NumberOfRegions{ 1 };
185 | RegionType m_RequestedNumberOfRegions{ 0 };
186 | RegionType m_BufferedRegion{ -1 };
187 | RegionType m_RequestedRegion{ -1 };
188 |
189 | private:
190 |
191 | }; // end class OSFGraph
192 |
193 | } // end namespace itk
194 |
195 | #ifndef ITK_MANUAL_INSTANTIATION
196 | #include "itkOSFGraph.txx"
197 | #endif
198 |
199 | #endif
200 |
201 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkSimpleOSFGraphBuilderFilter.txx:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkSimpleOSFGraphBuilderFilter_txx
19 | #define _itkSimpleOSFGraphBuilderFilter_txx
20 |
21 | #include "itkSimpleOSFGraphBuilderFilter.h"
22 | #include "itkLinearInterpolateImageFunction.h"
23 | #include "itkNumericTraits.h"
24 |
25 | namespace itk
26 | {
27 | //----------------------------------------------------------------------------
28 | template
29 | void
30 | SimpleOSFGraphBuilderFilter
31 | ::GenerateData()
32 | {
33 | this->CopyInputOSFGraphToOutputOSFGraphSurfaces();
34 | auto output = this->GetOutput();
35 |
36 | // create nodes for columns
37 | for (SurfaceIdentifier surfaceId=0; surfaceIdGetNumberOfSurfaces(); surfaceId++)
38 | {
39 | typename OSFSurface::Pointer surface = output->GetSurface(surfaceId);
40 | for (VertexIdentifier vertexId=0; vertexIdGetNumberOfVertices(); vertexId++)
41 | this->CreateNodesForColumn(surfaceId, vertexId);
42 | }
43 | output->BuildGraphNodeIdentifierLookupTable();
44 |
45 | // create intra-column arcs
46 | for (SurfaceIdentifier surfaceId=0; surfaceIdGetNumberOfSurfaces(); surfaceId++)
47 | {
48 | typename OSFSurface::Pointer surface = output->GetSurface(surfaceId);
49 | for (VertexIdentifier vertexId=0; vertexIdGetNumberOfVertices(); vertexId++)
50 | this->CreateIntraColumnArcsForColumn(surfaceId, vertexId);
51 | }
52 |
53 | // create inter-column arcs
54 | for (SurfaceIdentifier surfaceId=0; surfaceIdGetNumberOfSurfaces(); surfaceId++)
55 | {
56 | typename OSFSurface::Pointer surface = output->GetSurface(surfaceId);
57 | surface->BuildNeighborLookupTable();
58 | for (VertexIdentifier vertexId=0; vertexIdGetNumberOfVertices(); vertexId++)
59 | this->CreateInterColumnArcsForColumn(surfaceId, vertexId);
60 | }
61 |
62 | }
63 |
64 | //----------------------------------------------------------------------------
65 | template
66 | void
67 | SimpleOSFGraphBuilderFilter
68 | ::CreateNodesForColumn(SurfaceIdentifier surfaceId, VertexIdentifier vertexId)
69 | {
70 | using GraphNode = typename OutputOSFGraphType::GraphNode;
71 |
72 | auto output = this->GetOutput();
73 | typename OSFSurface::ColumnCostsContainer::ConstPointer columnCosts = output->GetSurface(surfaceId)->GetColumnCosts(vertexId);
74 | typename OSFSurface::ColumnCostsContainer::ConstIterator columnCostsItr = columnCosts->Begin();
75 | typename OSFSurface::ColumnCostsContainer::ConstIterator columnCostsEnd = columnCosts->End();
76 | typename OutputOSFGraphType::GraphNodesContainer::Pointer graphNodes = output->GetNodes();
77 | typename OutputOSFGraphType::GraphNodeIdentifier startNodeIndex = graphNodes->Size();
78 | graphNodes->Reserve( graphNodes->Size()+columnCosts->Size() );
79 |
80 | if (columnCosts->Size()>0)
81 | {
82 | typename OutputOSFGraphType::GraphCosts weight = 0;
83 | typename OutputOSFGraphType::GraphCosts previousNodeCost = columnCostsItr.Value();
84 | graphNodes->SetElement( startNodeIndex++, GraphNode(surfaceId, vertexId, columnCostsItr->Index(), -m_ColumnBasedNodeWeight, 0) ); // set node of base to default value
85 | ++columnCostsItr;
86 | while (columnCostsItr!=columnCostsEnd)
87 | {
88 | weight = columnCostsItr.Value()-previousNodeCost;
89 | if (weight>0) // non-negative -> connect to t
90 | graphNodes->SetElement( startNodeIndex++, GraphNode(surfaceId, vertexId, columnCostsItr->Index(), 0.0, weight) );
91 | else // negative -> connect to s
92 | graphNodes->SetElement( startNodeIndex++, GraphNode(surfaceId, vertexId, columnCostsItr->Index(), -weight, 0.0) );
93 | previousNodeCost = columnCostsItr.Value();
94 | ++columnCostsItr;
95 | }
96 | }
97 |
98 | }
99 |
100 | //----------------------------------------------------------------------------
101 | template
102 | void
103 | SimpleOSFGraphBuilderFilter
104 | ::CreateIntraColumnArcsForColumn(SurfaceIdentifier surfaceId, VertexIdentifier vertexId)
105 | {
106 | //Edges along columns, from node to node, outside to inside, with infinite capacity
107 | //These relate the nodes on the column in the graph, allowing for selection of a single one
108 | using GraphEdge = typename OutputOSFGraphType::GraphEdge;
109 | using GraphNodeIdentifier= typename OutputOSFGraphType::GraphNodeIdentifier;
110 |
111 | auto output = this->GetOutput();
112 | typename OSFSurface::ColumnPositionIdentifier numColumnPositions = output->GetSurface(surfaceId)->GetNumberOfColumns(vertexId);
113 | typename OutputOSFGraphType::GraphEdgesContainer::Pointer graphEdges = output->GetEdges();
114 | typename OutputOSFGraphType::GraphEdgeIdentifier startEdgeIndex = graphEdges->Size();
115 | graphEdges->Reserve( graphEdges->Size()+numColumnPositions-1 );
116 |
117 | for (typename OSFSurface::ColumnPositionIdentifier columnPositionId=1; columnPositionIdGetNodeIdentifer(surfaceId, vertexId, columnPositionId);
120 | GraphNodeIdentifier endNodeId = output->GetNodeIdentifer(surfaceId, vertexId, columnPositionId-1);
121 | graphEdges->SetElement( startEdgeIndex++, GraphEdge( startNodeId, endNodeId, m_Infinity, 0) );
122 | }
123 |
124 | }
125 |
126 | //----------------------------------------------------------------------------
127 | template
128 | void
129 | SimpleOSFGraphBuilderFilter
130 | ::CreateInterColumnArcsForColumn(SurfaceIdentifier surfaceId, VertexIdentifier vertexId)
131 | {
132 | using GraphEdge = typename OutputOSFGraphType::GraphEdge;
133 | using GraphNodeIdentifier = typename OutputOSFGraphType::GraphNodeIdentifier;
134 |
135 | auto output = this->GetOutput();
136 | typename OSFSurface::ColumnPositionIdentifier numColumnPositions = output->GetSurface(surfaceId)->GetNumberOfColumns(vertexId);
137 | typename OSFSurface::VertexIdentifierContainer::ConstPointer neighbors = output->GetSurface(surfaceId)->GetNeighbors(vertexId);
138 | typename OutputOSFGraphType::GraphEdgesContainer::Pointer graphEdges = output->GetEdges();
139 |
140 | for (typename OSFSurface::VertexIdentifierContainer::ConstIterator neighborItr=neighbors->Begin(); neighborItr!=neighbors->End(); ++neighborItr)
141 | {
142 | // add hard smoothness constraints
143 | if (m_SmoothnessConstraint!=itk::NumericTraits::max())
144 | {
145 | for (typename OSFSurface::ColumnPositionIdentifier columnPositionId=0; columnPositionIdGetNodeIdentifer(surfaceId, vertexId, columnPositionId);
148 |
149 | // note: computation of columnPositionId for the neighbor node should include the initialVertexPositionId
150 | GraphNodeIdentifier endNodeId = output->GetNodeIdentifer(surfaceId, neighborItr.Value(), typename OSFSurface::ColumnPositionIdentifier(std::max( (int)columnPositionId-(int)m_SmoothnessConstraint, 0)) );
151 | graphEdges->InsertElement( graphEdges->Size(), GraphEdge( startNodeId, endNodeId, m_Infinity, 0) );
152 | }
153 | }
154 | // add soft smoothness penalty term
155 | if (m_SoftSmoothnessPenalty>0.0 && neighborItr.Value()>vertexId)
156 | {
157 | for (typename OSFSurface::ColumnPositionIdentifier columnPositionId=0; columnPositionIdGetNodeIdentifer(surfaceId, vertexId, columnPositionId);
160 |
161 | // note: computation of columnPositionId for the neighbor node should include the initialVertexPositionId
162 | GraphNodeIdentifier endNodeId = output->GetNodeIdentifer(surfaceId, neighborItr.Value(), columnPositionId );
163 | graphEdges->InsertElement( graphEdges->Size(), GraphEdge( startNodeId, endNodeId, m_SoftSmoothnessPenalty, m_SoftSmoothnessPenalty) );
164 | }
165 | }
166 | }
167 | }
168 |
169 | //----------------------------------------------------------------------------
170 | template
171 | void
172 | SimpleOSFGraphBuilderFilter
173 | ::PrintSelf(std::ostream& os, Indent indent) const
174 | {
175 | Superclass::PrintSelf(os,indent);
176 | // todo: implement
177 | }
178 |
179 | } // namespace
180 |
181 | #endif
182 |
183 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/itkOSFGraphToOSFGraphFilter.txx:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _itkOSFGraphToOSFGraphFilter_txx
19 | #define _itkOSFGraphToOSFGraphFilter_txx
20 |
21 | #include "itkOSFGraphToOSFGraphFilter.h"
22 |
23 | namespace itk
24 | {
25 |
26 | //----------------------------------------------------------------------------
27 | template
28 | OSFGraphToOSFGraphFilter
29 | ::OSFGraphToOSFGraphFilter()
30 | {
31 | // Modify superclass default values, can be overridden by subclasses
32 | this->SetNumberOfRequiredInputs(1);
33 | }
34 |
35 | //----------------------------------------------------------------------------
36 | template
37 | void
38 | OSFGraphToOSFGraphFilter
39 | ::SetInput(unsigned int idx, const InputOSFGraphType* input)
40 | {
41 | // process object is not const-correct, the const_cast is required here.
42 | this->ProcessObject::SetNthInput(idx, const_cast< TInputOSFGraph * >(input) );
43 | }
44 |
45 | //----------------------------------------------------------------------------
46 | template
47 | const typename OSFGraphToOSFGraphFilter::InputOSFGraphType*
48 | OSFGraphToOSFGraphFilter
49 | ::GetInput(unsigned int idx) const
50 | {
51 | if (this->GetNumberOfInputs() < 1)
52 | {
53 | return 0;
54 | }
55 | return dynamic_cast (this->ProcessObject::GetInput(idx));
56 | }
57 |
58 | //----------------------------------------------------------------------------
59 | template
60 | typename OSFGraphToOSFGraphFilter::OutputOSFGraphType*
61 | OSFGraphToOSFGraphFilter
62 | ::GetOutput(unsigned int idx)
63 | {
64 | if (this->GetNumberOfOutputs() < 1)
65 | {
66 | return 0;
67 | }
68 | return dynamic_cast (this->ProcessObject::GetOutput(idx));
69 | }
70 |
71 | //----------------------------------------------------------------------------
72 | template
73 | void
74 | OSFGraphToOSFGraphFilter
75 | ::CopyInputOSFGraphToOutputOSFGraphSurfaces()
76 | {
77 | auto inputOSFGraph = this->GetInput();
78 | auto outputOSFGraph = this->GetOutput();
79 | for (typename OutputOSFGraphType::SurfaceIdentifier surfaceId=0; surfaceIdGetNumberOfSurfaces(); surfaceId++)
80 | {
81 | OSFSurfaceConstPointer currentInputSurface = inputOSFGraph->GetSurface(surfaceId);
82 | OSFSurfacePointer currentOutputSurface = outputOSFGraph->GetSurface(surfaceId);
83 | this->CopyInputOSFGraphToOutputOSFGraphSurface( currentInputSurface, currentOutputSurface );
84 | }
85 | }
86 |
87 | //----------------------------------------------------------------------------
88 | template
89 | void
90 | OSFGraphToOSFGraphFilter
91 | ::CopyInputOSFGraphToOutputOSFGraphSurface(OSFSurfaceConstPointer inputOSFSurface, OSFSurfacePointer outputOSFSurface)
92 | {
93 | // copy vertex information
94 | typename OSFSurface::VertexIdentifier numVertices = inputOSFSurface->GetNumberOfVertices();
95 | for (typename OSFSurface::VertexIdentifier vertexId=0; vertexIdGetColumnCoordinates( vertexId );
101 | if (inputPoints)
102 | {
103 | typename InputColumnCoordinatesContainerType::ConstIterator inputItr = inputPoints->Begin();
104 | typename InputColumnCoordinatesContainerType::ConstIterator inputEnd = inputPoints->End();
105 | using OutputColumnCoordinatesContainerType = typename OutputOSFGraphType::OSFSurface::ColumnCoordinatesContainer;
106 | typename OutputColumnCoordinatesContainerType::Pointer outputPoints = OutputColumnCoordinatesContainerType::New();
107 | outputPoints->Reserve( inputPoints->Size() );
108 | typename OutputColumnCoordinatesContainerType::Iterator outputItr = outputPoints->Begin();
109 | while (inputItr!=inputEnd)
110 | {
111 | outputItr.Value() = inputItr.Value();
112 | ++inputItr; ++outputItr;
113 | }
114 | outputOSFSurface->SetColumnCoordinates( vertexId, outputPoints );
115 | }
116 | }
117 |
118 | // copy column point costs
119 | {
120 | using InputColumnCostsContainerType = typename InputOSFGraphType::OSFSurface::ColumnCostsContainer;
121 | typename InputColumnCostsContainerType::ConstPointer inputCosts = inputOSFSurface->GetColumnCosts( vertexId );
122 | if (inputCosts)
123 | {
124 | typename InputColumnCostsContainerType::ConstIterator inputItr = inputCosts->Begin();
125 | typename InputColumnCostsContainerType::ConstIterator inputEnd = inputCosts->End();
126 | using OutputColumnCostsContainerType = typename OutputOSFGraphType::OSFSurface::ColumnCostsContainer;
127 | typename OutputColumnCostsContainerType::Pointer outputCosts = OutputColumnCostsContainerType::New();
128 | outputCosts->Reserve( inputCosts->Size() );
129 | typename OutputColumnCostsContainerType::Iterator outputItr = outputCosts->Begin();
130 | while (inputItr!=inputEnd)
131 | {
132 | outputItr.Value() = inputItr.Value();
133 | ++inputItr; ++outputItr;
134 | }
135 | outputOSFSurface->SetColumnCosts( vertexId, outputCosts );
136 | }
137 | }
138 |
139 | outputOSFSurface->SetInitialVertexPositionIdentifier( vertexId, inputOSFSurface->GetInitialVertexPositionIdentifier(vertexId) );
140 | outputOSFSurface->SetCurrentVertexPositionIdentifier( vertexId, inputOSFSurface->GetCurrentVertexPositionIdentifier(vertexId) );
141 | }
142 |
143 | // copy cells
144 | using OutputCellsContainer = typename OutputOSFGraphType::OSFSurface::CellsContainer;
145 | using InputCellsContainer = typename InputOSFGraphType::OSFSurface::CellsContainer;
146 | using CellAutoPointer = typename OutputOSFGraphType::OSFSurface::CellAutoPointer;
147 |
148 | auto outputCells = OutputCellsContainer::New();
149 | const InputCellsContainer * inputCells = inputOSFSurface->GetCells();
150 |
151 | if( inputCells )
152 | {
153 | outputCells->Reserve( inputCells->Size() );
154 |
155 | typename InputCellsContainer::ConstIterator inputItr = inputCells->Begin();
156 | typename InputCellsContainer::ConstIterator inputEnd = inputCells->End();
157 | typename OutputCellsContainer::Iterator outputItr = outputCells->Begin();
158 |
159 | CellAutoPointer clone;
160 |
161 | while( inputItr != inputEnd )
162 | {
163 | inputItr.Value()->MakeCopy( clone );
164 | outputItr.Value() = clone.ReleaseOwnership();
165 |
166 | ++inputItr;
167 | ++outputItr;
168 | }
169 |
170 | outputOSFSurface->SetCells( outputCells );
171 | }
172 | }
173 | //----------------------------------------------------------------------------
174 | template
175 | void
176 | OSFGraphToOSFGraphFilter
177 | ::CopyInputOSFGraphToOutputOSFGraphGraph()
178 | {
179 | // copy nodes
180 | using GraphNodesContainer = typename OutputOSFGraphType::GraphNodesContainer;
181 | typename GraphNodesContainer::ConstPointer inputGraphNodes = this->GetInput()->GetNodes();
182 | typename GraphNodesContainer::Pointer outputGraphNodes = GraphNodesContainer::New();
183 |
184 | if (inputGraphNodes)
185 | {
186 | outputGraphNodes->Reserve( inputGraphNodes->Size() );
187 | typename GraphNodesContainer::ConstIterator inputItr = inputGraphNodes->Begin();
188 | typename GraphNodesContainer::ConstIterator inputEnd = inputGraphNodes->End();
189 | typename GraphNodesContainer::Iterator outputItr = outputGraphNodes->Begin();
190 | while( inputItr != inputEnd )
191 | {
192 | outputItr.Value() = inputItr.Value();
193 | ++inputItr;
194 | ++outputItr;
195 | }
196 | this->GetOutput()->SetNodes( outputGraphNodes );
197 | }
198 |
199 | // copy edges
200 | using GraphEdgesContainer = typename OutputOSFGraphType::GraphEdgesContainer;
201 | typename GraphEdgesContainer::ConstPointer inputGraphEdges = this->GetInput()->GetEdges();
202 | typename GraphEdgesContainer::Pointer outputGraphEdges = GraphEdgesContainer::New();
203 |
204 | if (inputGraphEdges)
205 | {
206 | outputGraphEdges->Reserve( inputGraphEdges->Size() );
207 | typename GraphEdgesContainer::ConstIterator inputItr = inputGraphEdges->Begin();
208 | typename GraphEdgesContainer::ConstIterator inputEnd = inputGraphEdges->End();
209 | typename GraphEdgesContainer::Iterator outputItr = outputGraphEdges->Begin();
210 | while( inputItr != inputEnd )
211 | {
212 | outputItr.Value() = inputItr.Value();
213 | ++inputItr;
214 | ++outputItr;
215 | }
216 | this->GetOutput()->SetEdges( outputGraphEdges );
217 | }
218 | }
219 |
220 | //----------------------------------------------------------------------------
221 | template
222 | void
223 | OSFGraphToOSFGraphFilter
224 | ::PrintSelf(std::ostream& os, Indent indent) const
225 | {
226 | Superclass::PrintSelf(os,indent);
227 | // todo: implement
228 | }
229 |
230 | } // namespace
231 |
232 | #endif
233 |
234 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/logismos_graph.cxx:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | namespace LOGISMOS{
19 |
20 | ////////////////////////////////////////////////////////
21 | template
22 | _Cap graph<_Cap, _DataChunkSize, _PtrChunkSize>::solve()
23 | {
24 | // make sure we start from correct initial condition
25 | m_orphan_nodes.clear();
26 |
27 | node* p_node;
28 | edge* p_edge;
29 |
30 | p_node=m_nodes.scan_first();
31 | while(p_node){
32 | if(p_node->has_parent() == false || p_node->is_active() == false)
33 | p_edge = 0;
34 | else{
35 | p_edge = grow_active_node(p_node);
36 | m_clock++;
37 | }
38 |
39 | if(p_edge){ // will process same active node in next iteration
40 | augment_path(p_edge);
41 | while(m_orphan_nodes.empty() == false){
42 | adopt_orphan(m_orphan_nodes.front());
43 | m_orphan_nodes.pop_front();
44 | }
45 | }
46 | else{ // ready to process next node
47 | p_node->set_active(false);
48 | p_node = m_nodes.scan_next();
49 | }
50 | }
51 |
52 | while(m_active_nodes.empty() == false){
53 | p_node = m_active_nodes.front(); // p_node->is_active() is always true here
54 | if(p_node->has_parent() == false) // a node in the queue may lose parent during adopt_orphan()
55 | p_edge = 0;
56 | else{
57 | p_edge = grow_active_node(p_node);
58 | m_clock++;
59 | }
60 |
61 | if(p_edge){ // will process same active node in next iteration
62 | augment_path(p_edge);
63 | while(m_orphan_nodes.empty() == false){
64 | adopt_orphan(m_orphan_nodes.front());
65 | m_orphan_nodes.pop_front();
66 | }
67 | }
68 | else{ // ready to process next node in active queue
69 | p_node->set_active(false);
70 | m_active_nodes.pop_front();
71 | }
72 | }
73 | return m_flow;
74 | }
75 |
76 | ////////////////////////////////////////////////////////
77 | template
78 | typename graph<_Cap, _DataChunkSize, _PtrChunkSize>::edge* graph<_Cap, _DataChunkSize, _PtrChunkSize>::grow_active_node(node* node_i)
79 | {
80 | bool i_is_sink = node_i->is_sink();
81 |
82 | for(edge** edge_dptr = node_i->m_out_edges->scan_first(); edge_dptr; edge_dptr = node_i->m_out_edges->scan_next()){
83 | edge* p_edge = *edge_dptr;
84 | _Cap cap = (i_is_sink) ? p_edge->m_sister->m_rcap : p_edge->m_rcap;
85 | if(cap == 0) continue; // only check edge with residual capacity
86 |
87 | node* node_j = p_edge->m_head;
88 | if(node_j->has_parent() == false){
89 | node_j->set_sink(i_is_sink); // assign j to the same tree
90 | node_j->m_par_edge = p_edge->m_sister;
91 | node_j->m_time = node_i->m_time;
92 | node_j->m_dist = node_i->m_dist + 1;
93 | activate(node_j);
94 | }
95 | else if(node_j->is_sink() != i_is_sink){
96 | // return the edge from a source node to a sink node
97 | if(i_is_sink) return p_edge->m_sister;
98 | else return p_edge;
99 | }
100 | else if(node_j->m_time <= node_i->m_time && node_j->m_dist > node_i->m_dist){
101 | // trying to make the distance from j to the terminal node shorter
102 | node_j->m_par_edge = p_edge->m_sister;
103 | node_j->m_time = node_i->m_time;
104 | node_j->m_dist = node_i->m_dist + 1;
105 | }
106 | }
107 | return 0; // found NO edge connecting source and sink trees
108 | }
109 |
110 | ////////////////////////////////////////////////////////
111 | template
112 | void graph<_Cap, _DataChunkSize, _PtrChunkSize>::augment_path(edge* mid_edge)
113 | {
114 | edge* p_edge;
115 | _Cap cap;
116 | _Cap eps = std::numeric_limits<_Cap>::epsilon();
117 | _Cap bottleneck = mid_edge->m_rcap; // initial bottleneck
118 |
119 | // find bottleneck residual capacity of source tree
120 | node* p_node = mid_edge->m_sister->m_head;
121 | while(p_node->is_terminal() == false){
122 | p_edge = p_node->m_par_edge;
123 | cap = p_edge->m_sister->m_rcap;
124 | if(bottleneck > cap) bottleneck = cap;
125 | p_node = p_edge->m_head;
126 | }
127 | if(bottleneck > p_node->m_rcap) bottleneck = p_node->m_rcap;
128 |
129 | // find bottleneck residual capacity of sink tree
130 | p_node = mid_edge->m_head;
131 | while(p_node->is_terminal() == false){
132 | p_edge = p_node->m_par_edge;
133 | cap = p_edge->m_rcap;
134 | if(bottleneck > cap) bottleneck = cap;
135 | p_node = p_edge->m_head;
136 | }
137 | if(bottleneck > -(p_node->m_rcap)) bottleneck = -(p_node->m_rcap);
138 |
139 |
140 | // augment the middle edge
141 | mid_edge->m_rcap -= bottleneck;
142 | mid_edge->m_sister->m_rcap += bottleneck;
143 |
144 | // augment the source tree
145 | p_node = mid_edge->m_sister->m_head;
146 | while(p_node->is_terminal() == false){
147 | p_edge = p_node->m_par_edge;
148 | p_edge->m_rcap += bottleneck;
149 | p_edge->m_sister->m_rcap -= bottleneck;
150 | if(p_edge->m_sister->m_rcap <= eps){
151 | p_edge->m_sister->m_rcap = 0;
152 | mark_orphan(p_node);
153 | }
154 | p_node = p_edge->m_head;
155 | }
156 | p_node->m_rcap -= bottleneck;
157 | if(p_node->m_rcap <= eps){
158 | p_node->m_rcap = 0;
159 | mark_orphan(p_node);
160 | }
161 |
162 | // augment the sink tree
163 | p_node = mid_edge->m_head;
164 | while(p_node->is_terminal() == false){
165 | p_edge = p_node->m_par_edge;
166 | p_edge->m_rcap -= bottleneck;
167 | p_edge->m_sister->m_rcap += bottleneck;
168 | if(p_edge->m_rcap <= eps){
169 | p_edge->m_rcap = 0;
170 | mark_orphan(p_node);
171 | }
172 | p_node = p_edge->m_head;
173 | }
174 | p_node->m_rcap += bottleneck;
175 | if(-p_node->m_rcap <= eps){
176 | p_node->m_rcap = 0;
177 | mark_orphan(p_node);
178 | }
179 |
180 | m_flow += bottleneck;
181 | }
182 |
183 | ////////////////////////////////////////////////////////
184 | template
185 | void graph<_Cap, _DataChunkSize, _PtrChunkSize>::adopt_orphan(node* node_i)
186 | {
187 | bool i_is_sink = node_i->is_sink(); // which tree the orphan node belong, sink (true) or source (false)
188 | node* node_j;
189 | edge* p_edge;
190 |
191 | // try to find a new parent for node i
192 | unsigned int dist;
193 | unsigned int d_max = std::numeric_limits::max();
194 | unsigned int min_dist = std::numeric_limits::max();
195 | edge* min_p_edge = 0; // starting from this edge, can backtrack to terminal w/ minimal distance (# of hops)
196 |
197 | for(edge** edge_dptr = node_i->m_out_edges->scan_first(); edge_dptr; edge_dptr = node_i->m_out_edges->scan_next() ){
198 | p_edge = *edge_dptr;
199 | node_j = p_edge->m_head;
200 | _Cap cap = (i_is_sink) ? p_edge->m_rcap : p_edge->m_sister->m_rcap;
201 | // candidate node j must satisfy:
202 | // 1) the edge between i and j is not saturated,
203 | // 2) it belongs to the same tree as node i,
204 | // 3) it has a parent (not an orphan)
205 | if(cap == 0 || node_j->is_sink() != i_is_sink || node_j->has_parent() == false) continue;
206 |
207 | // node j can become parent for node i only if its originates from the same type of terminal node as node i
208 | // i.e. we can backtrack to terminal node along parent edges without meeting a orphan node.
209 | dist = 0; // distance to terminal node
210 | while(true){
211 | if(node_j->m_time == m_clock){ // node j was update at the same m_clock --> its origin is already validated
212 | dist += node_j->m_dist; break;
213 | }
214 | dist++;
215 | if(node_j->is_terminal()){
216 | node_j->m_time = m_clock; node_j->m_dist = 1; break;
217 | }
218 | if(node_j->is_orphan()){
219 | dist = d_max; break;
220 | }
221 | node_j = node_j->m_par_edge->m_head;
222 | }
223 |
224 | if(dist < d_max){ // node j's origin is valid
225 | if(dist < min_dist){ // we prefer a path such that node j that is closest to the terminal
226 | min_p_edge = p_edge; min_dist = dist;
227 | }
228 | // update time stamps and distance along the path to terminal
229 | for(node_j = p_edge->m_head; node_j->m_time != m_clock; node_j = node_j->m_par_edge->m_head){
230 | node_j->m_time = m_clock; node_j->m_dist = dist; dist--;
231 | }
232 | }
233 | }
234 |
235 | node_i->m_par_edge = min_p_edge; // update i's parent -- zero: not found
236 | if(min_p_edge != 0){
237 | node_i->m_time = m_clock;
238 | node_i->m_dist = min_dist+1;
239 | }
240 | else{
241 | // 1) activate i's neighbors that may claim i as child (positive residual capacity on associated edge)
242 | // 2) node i's children then become orphans
243 | for(edge** edge_dptr = node_i->m_out_edges->scan_first(); edge_dptr; edge_dptr = node_i->m_out_edges->scan_next() ){
244 | p_edge = *edge_dptr;
245 | node_j = p_edge->m_head;
246 | if(node_j->is_sink() == i_is_sink && node_j->has_parent()){
247 | _Cap cap = (i_is_sink) ? p_edge->m_rcap : p_edge->m_sister->m_rcap;
248 | if(cap!=0){
249 | activate(node_j);
250 | }
251 | if(node_j->is_terminal() == false && node_j->is_orphan() == false && node_j->m_par_edge->m_head == node_i){
252 | mark_orphan(node_j);
253 | }
254 | }
255 | }
256 | }
257 | }
258 |
259 | } // end of namespace
260 |
--------------------------------------------------------------------------------
/PETTumorSegmentation/Logic/logismos_chunk_list.hxx:
--------------------------------------------------------------------------------
1 | /*==============================================================================
2 |
3 | Program: PETTumorSegmentation
4 |
5 | (c) Copyright University of Iowa All Rights Reserved.
6 |
7 | See COPYRIGHT.txt
8 | or http://www.slicer.org/copyright/copyright.txt for details.
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | ==============================================================================*/
17 |
18 | #ifndef _LOGISMOS_chunk_list_hxx_
19 | #define _LOGISMOS_chunk_list_hxx_
20 |
21 | #include // for std::size_t
22 | #include // for std::memset
23 | #include
24 | #include // for testing only
25 |
26 | namespace LOGISMOS{
27 |
28 | /// \brief A continuous memory chunk used for data storage.
29 | ///
30 | /// It emulates a std::vector<_T> with fixed capacity of _N that can never grow.
31 | /// \note Only a small subset of member functions of std::vector is provided
32 | /// because we assume this class is only directly used by chunk_list class.
33 | ///
34 | /// \author Honghai Zhang
35 | template
36 | class chunk
37 | {
38 | private:
39 | _T m_data[_N]; ///< data buffer (container) with fixed capacity
40 | _T* m_end; ///< pointer to the location after the last valid data elements
41 |
42 | public:
43 | /// \brief Constructor, data buffer is initially filled with zeros.
44 | ///
45 | /// \note Constructor of data type _T is NOT called.
46 | chunk()
47 | {
48 | std::memset(m_data, 0, sizeof(m_data));
49 | m_end = &(m_data[0]);
50 | }
51 |
52 | // member functions with same names and same or very similar meanings as std::vector
53 | inline _T* begin(){ return &(m_data[0]); }
54 | inline _T* end() { return m_end; }
55 | inline std::size_t size() const{ return m_end - &(m_data[0]); }
56 | inline bool empty() const{ return m_end == &(m_data[0]); }
57 | inline _T& operator[](std::size_t i){ return m_data[i]; }
58 | inline const _T& operator[] (std::size_t i) const{ return m_data[i]; }
59 |
60 | /// \brief Grow the chunk by cnt elements at the end.
61 | ///
62 | /// \return Pointer to the first new element.
63 | /// \note Boundary check is NOT performed.
64 | inline _T* grow(std::size_t cnt=1)
65 | {
66 | _T* ptr = m_end; // the old end is the first new element
67 | m_end += cnt;
68 | return ptr;
69 | }
70 | }; // end of class chunk
71 |
72 | /// \brief A series of chunks
73 | ///
74 | /// This class is specially designed for the use case in which
75 | /// 1) a LARGE number of data elements need to be stored;
76 | /// 2) the number of elements may not be known at construction;
77 | /// 3) the storage can dynamically grow with minimal penalty for performance.
78 | /// Comparing with std::vector
79 | /// 1) grow the chunk_list never requires large blocks of memory to be reallocated and copied;
80 | /// 2) the amount of new memory allocated when growing is fixed instead of always doubling as in std::vector
81 | /// 3) using scan_first() and scan_next() to sequentially access all elements is efficient (should be similar to std::vector);
82 | /// 4) random access using ptr_at() or operator [] is easy and should be good enough
83 | /// but may not be very efficient for sequential access of all elements.
84 | template
85 | class chunk_list
86 | {
87 | typedef chunk<_T, _N> chunk_type;
88 | typedef std::vector list_type;
89 | typedef typename list_type::iterator list_iter_type;
90 |
91 | private:
92 | list_type m_list; ///< the data (chunk) container
93 | std::size_t m_size; ///< actual number of elements of type _T stored, NOT the size of m_list
94 |
95 | _T* m_data_ptr; ///< pointer to the current element of type _T being accessed
96 | list_iter_type m_chunk_iter; ///< iterator of the current chunk being accessed
97 |
98 | public:
99 | /// \brief Constructor
100 | chunk_list() : m_size(0), m_data_ptr(0){ }
101 |
102 | /// \brief Destructor
103 | ~chunk_list(){ clear(); }
104 |
105 | /// \brief Clears all elements in the list and memory allocated.
106 | void clear()
107 | {
108 | m_size = 0; m_data_ptr = 0;
109 | for(list_iter_type iter = m_list.begin(); iter != m_list.end(); ++iter){ delete *iter; }
110 | m_list.clear();
111 | list_type().swap(m_list); // actually frees memory allocated if list_type is std::vector
112 | }
113 |
114 | /// \brief Returns the total number of elements of type _T in the list.
115 | inline std::size_t size() const{ return m_size; }
116 |
117 | /// \brief Returns number of chunks used by the list
118 | inline std::size_t chunks() const{ return m_list.size(); }
119 |
120 | /// \brief Returns pointer to the beginning of the list
121 | inline _T* begin(){ return m_list.front()->begin(); }
122 |
123 | /// \brief Returns pointer to the end of the list, i.e. pointer to location right after the last element.
124 | inline _T* end(){ return m_list.back()->end(); }
125 |
126 | /// \brief Returns pointer to the ith element (no boundary check).
127 | inline _T* ptr_at(std::size_t i)
128 | {
129 | std::size_t c(0); // which chunk
130 | std::size_t d(i); // index within chunk
131 | while(d >= _N){ c++; d -= _N; }
132 | return m_list[c]->begin()+d;
133 | }
134 |
135 | /// \brief Return reference to the ith element (no boundary check).
136 | inline _T& operator[](std::size_t i)
137 | {
138 | std::size_t c(0); // which chunk
139 | std::size_t d(i); // index within chunk
140 | while(d >= _N){ c++; d -= _N; }
141 | return (*m_list[c])[d];
142 | }
143 |
144 | /// \brief Returns const reference to the ith element (no boundary check).
145 | inline const _T& operator[](std::size_t i) const
146 | {
147 | std::size_t c(0); // which chunk
148 | std::size_t d(i); // index within chunk
149 | while(d >= _N){ c++; d -= _N; }
150 | return (*m_list[c])[d];
151 | }
152 |
153 | /// \brief Grow the chunk_list by one elements at the end (allocates a new chunk if needed) and returns pointer to the new element.
154 | inline _T* grow()
155 | {
156 | if(m_list.empty() || m_list.back()->size() == _N){ // list is empty or the last chunk is full
157 | m_list.push_back(new chunk_type()); // create a new chunk
158 | }
159 | m_size++;
160 | return m_list.back()->grow();
161 | }
162 |
163 | /// brief Add a new element with given value specified in val.
164 | inline void push_back(const _T &val){ *grow() = val; }
165 |
166 | /// \brief Grow the chunk_list by cnt elements, i.e. increase the total number of elements can be stored by cnt.
167 | ///
168 | /// \return index of the first element added, i.e. the total number of elements before the new ones are added.
169 | /// \note If cnt > _N, multiple chunks will be added, thus providing a quick way to allocate memory.
170 | std::size_t grow(std::size_t cnt)
171 | {
172 | std::size_t old_size = m_size;
173 |
174 | if(cnt == 1){ grow(); return old_size; }
175 | if(m_list.empty() || m_list.back()->size() == _N){ // list is empty or the last chunk is full
176 | m_list.push_back(new chunk_type()); // create a new chunk
177 | }
178 |
179 | std::size_t grow_slots = cnt;
180 | std::size_t free_slots = _N - m_list.back()->size();
181 | if(grow_slots <= free_slots){ // have enough free slots in the last chunk, grow and return
182 | m_list.back()->grow(grow_slots); m_size += grow_slots; return old_size;
183 | }
184 | else{ // not enough space in the last chunk, fill it first
185 | m_list.back()->grow(free_slots); m_size += free_slots;
186 | grow_slots -= free_slots;
187 | }
188 |
189 | std::size_t chunk_cnt = grow_slots / _N; // number of chunk to grow
190 | std::size_t extra_cnt = grow_slots % _N; // number of additional elements to grow that is not a full chunk
191 | for(std::size_t i=0;igrow(_N); m_size += _N;
194 | }
195 | if(extra_cnt > 0){
196 | m_list.push_back(new chunk_type());
197 | m_list.back()->grow(extra_cnt); m_size += extra_cnt;
198 | }
199 | return old_size;
200 | }
201 |
202 | /// \brief Returns pointer to the first element to access, 0 if chunk_list is empty
203 | ///
204 | /// Use this to start a loop for all elements.
205 | inline _T* scan_first()
206 | {
207 | if(m_list.empty()) return 0;
208 | m_chunk_iter = m_list.begin();
209 | m_data_ptr = (*m_chunk_iter)->begin();
210 | return m_data_ptr;
211 | }
212 |
213 | /// \brief Returns pointer to the ith element, 0 if chunk_list is empty
214 | ///
215 | /// Use this to start a loop starting from the ith element.
216 | inline _T* scan_start(std::size_t i)
217 | {
218 | if(m_list.empty()) return 0;
219 | std::size_t c(0); // which chunk
220 | std::size_t d(i); // index within chunk
221 | while(d >= _N){ c++; d -= _N; }
222 | m_chunk_iter = m_list.begin()+c;
223 | m_data_ptr = (*m_chunk_iter)->begin()+d;
224 | return m_data_ptr;
225 | }
226 |
227 | /// \brief Returns pointer to the next element to access.
228 | ///
229 | /// Use this to continue looping through all elements,
230 | /// will return 0 when reaching the end of the list.
231 | /// \note Must call scan_first() or scan_start(i) before calling this one, will return 0 otherwise.
232 | inline _T* scan_next()
233 | {
234 | if(!m_data_ptr) return 0;
235 | m_data_ptr++;
236 | if(m_data_ptr == (*m_chunk_iter)->end()){ // already pointing to the last element of a chunk
237 | m_chunk_iter++; // move to the next chunk
238 | if(m_chunk_iter == m_list.end()) // reached the last chunk
239 | m_data_ptr = 0;
240 | else
241 | m_data_ptr = (*m_chunk_iter)->begin();
242 | }
243 | return m_data_ptr;
244 | }
245 |
246 | /// \brief Print elements stored (one chunk a line), for testing purpose only
247 | void print()
248 | {
249 | std::cout<chunks()<<" chunks, "<size()<<" elements"<