├── .github └── workflows │ └── build-test.yml ├── .gitignore ├── CITATION.cff ├── CMakeLists.txt ├── Dockerfile ├── EnvironmentInfo.h.in ├── LICENSE.txt ├── NOTICE.txt ├── README.md ├── appveyor.yml ├── azure-pipelines.yml ├── default.nix ├── derivation.nix ├── lib ├── petpvcDiscreteIYPVCImageFilter.h ├── petpvcDiscreteIYPVCImageFilter.txx ├── petpvcFuzzyCorrectionFilter.h ├── petpvcFuzzyCorrectionFilter.txx ├── petpvcFuzzyCorrectionFilter.txx~ ├── petpvcGTMImageFilter.h ├── petpvcGTMImageFilter.txx ├── petpvcIntraRegRLImageFilter.h ├── petpvcIntraRegRLImageFilter.txx ├── petpvcIntraRegVCImageFilter.h ├── petpvcIntraRegVCImageFilter.txx ├── petpvcIterativeYangPVCImageFilter.h ├── petpvcIterativeYangPVCImageFilter.txx ├── petpvcLabbeImageFilter.h ├── petpvcLabbeImageFilter.txx ├── petpvcLabbeMTCPVCImageFilter.h ├── petpvcLabbeMTCPVCImageFilter.txx ├── petpvcLabbePVCImageFilter.h ├── petpvcLabbePVCImageFilter.txx ├── petpvcLabbeRBVPVCImageFilter.h ├── petpvcLabbeRBVPVCImageFilter.txx ├── petpvcMTCPVCImageFilter.h ├── petpvcMTCPVCImageFilter.txx ├── petpvcMullerGartnerImageFilter.h ├── petpvcMullerGartnerImageFilter.txx ├── petpvcRBVPVCImageFilter.h ├── petpvcRBVPVCImageFilter.txx ├── petpvcRLPVCImageFilter.h ├── petpvcRLPVCImageFilter.txx ├── petpvcRegionConvolutionImageFilter.h ├── petpvcRegionConvolutionImageFilter.txx ├── petpvcRoussetPVCImageFilter.h ├── petpvcRoussetPVCImageFilter.txx ├── petpvcSTCPVCImageFilter.h ├── petpvcSTCPVCImageFilter.txx ├── petpvcVanCittertPVCImageFilter.h └── petpvcVanCittertPVCImageFilter.txx ├── parc ├── FS.csv ├── GIF_v3.csv └── README.md ├── shell.nix ├── src ├── CMakeLists.txt ├── DiscreteIY.cxx ├── GTM.cxx ├── IterativeYang.cxx ├── Labbe.cxx ├── MTC.cxx ├── Make4D.cxx ├── MullerGartner.cxx ├── PETPVC.cxx ├── RBV.cxx ├── Relabel.cxx ├── RichardsonLucy.cxx ├── STC.cxx ├── Simulate.cxx └── VanCittert.cxx └── test ├── CMakeLists.txt ├── CompareImages.cxx └── CreateTestImage.cxx /.github/workflows/build-test.yml: -------------------------------------------------------------------------------- 1 | name: Build and ctest CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths-ignore: 8 | - 'appveyor.yml' 9 | - 'azure-pipelines.yml' 10 | - 'CITATION.cff' 11 | - '**/*.md' 12 | - '**/*.html' 13 | - '**/*.htm' 14 | - '**/*.tex' 15 | 16 | pull_request: 17 | branches: 18 | - master 19 | paths-ignore: 20 | - 'appveyor.yml' 21 | - 'azure-pipelines.yml' 22 | - 'CITATION.cff' 23 | - '**/*.md' 24 | - '**/*.html' 25 | - '**/*.htm' 26 | - '**/*.tex' 27 | 28 | jobs: 29 | build: 30 | 31 | runs-on: ${{ matrix.os }} 32 | strategy: 33 | matrix: 34 | include: 35 | - os: ubuntu-latest 36 | compiler: gcc 37 | compiler_version: 9 38 | BUILD_TYPE: "Release" 39 | - os: ubuntu-latest 40 | compiler: gcc 41 | compiler_version: 9 42 | BUILD_TYPE: "Debug" 43 | - os: ubuntu-latest 44 | compiler: gcc 45 | compiler_version: 12 46 | BUILD_TYPE: "Release" 47 | - os: ubuntu-latest 48 | compiler: clang 49 | BUILD_TYPE: "Release" 50 | 51 | # let's run all of them, as opposed to aborting when one fails 52 | fail-fast: false 53 | 54 | name: ${{ matrix.os }}-${{ matrix.compiler }}${{ matrix.compiler_version }}-${{ matrix.BUILD_TYPE }} 55 | 56 | steps: 57 | - uses: actions/checkout@v4 58 | with: 59 | submodules: recursive 60 | 61 | - name: set_compiler_variables 62 | shell: bash 63 | run: | 64 | set -ex 65 | if test 'XX${{ matrix.compiler }}' = 'XXclang'; then 66 | CC="clang" 67 | CXX="clang++" 68 | elif test 'XX${{ matrix.compiler }}' = 'XXgcc'; then 69 | CC="gcc" 70 | CXX="g++" 71 | fi 72 | if test 'XX${{ matrix.compiler_version }}' != 'XX'; then 73 | CC=${CC}-${{ matrix.compiler_version }} 74 | CXX=${CXX}-${{ matrix.compiler_version }} 75 | fi 76 | if test 'XX${{ matrix.os }}' = 'XXmacOS-latest'; then 77 | if test 'XX${{ matrix.compiler }}' = 'XXclang'; then 78 | brew install llvm@${{ matrix.compiler_version }} 79 | if test XX${HOMEBREW_PREFIX} = XX; then 80 | HOMEBREW_PREFIX=/usr/local 81 | fi 82 | LDFLAGS="-L$HOMEBREW_PREFIX/opt/llvm/lib/c++ -Wl,-rpath,$HOMEBREW_PREFIX/opt/llvm/lib/c++" 83 | # make available to jobs below 84 | echo LDFLAGS="$LDFLAGS" >> $GITHUB_ENV 85 | CC="$HOMEBREW_PREFIX/opt/llvm/bin/clang" 86 | CXX="$HOMEBREW_PREFIX/opt/llvm/bin/clang++" 87 | fi 88 | fi 89 | export CC CXX 90 | # make available to jobs below 91 | echo CC="$CC" >> $GITHUB_ENV 92 | echo CXX="$CXX" >> $GITHUB_ENV 93 | 94 | - name: install_dependencies 95 | shell: bash 96 | run: | 97 | set -ex 98 | # We will install some external dependencies here 99 | CMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/install 100 | case ${{matrix.os}} in 101 | (ubuntu*) 102 | sudo apt update 103 | # install compiler 104 | if test 'XX${{ matrix.compiler }}' = 'XXclang'; then 105 | # package is called clang, need libomp-dev for OpenMP support 106 | sudo apt install $CC libomp-dev 107 | else 108 | sudo apt install $CXX 109 | fi 110 | # other dependencies 111 | # note: v5 is distributed without the REVIEW module 112 | sudo apt install libinsighttoolkit4-dev 113 | ;; 114 | (macOS*) 115 | brew install itk 116 | ;; 117 | esac 118 | echo PYTHON_EXECUTABLE="$PYTHON_EXECUTABLE" >> $GITHUB_ENV 119 | 120 | - name: ccache 121 | uses: hendrikmuhs/ccache-action@v1 122 | with: 123 | key: ${{ matrix.os }}-${{ matrix.compiler }}${{ matrix.compiler_version }}-${{ matrix.BUILD_TYPE }} 124 | 125 | - name: configure 126 | shell: bash 127 | env: 128 | BUILD_TYPE: ${{ matrix.BUILD_TYPE }} 129 | BUILD_FLAGS: ${{ matrix.BUILD_FLAGS }} 130 | run: | 131 | set -ex 132 | cmake --version 133 | if test "XX$CC" != "XX"; then 134 | $CC --version 135 | $CXX --version 136 | fi 137 | CMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/install 138 | # make available to jobs below 139 | echo CMAKE_INSTALL_PREFIX="$CMAKE_INSTALL_PREFIX" >> $GITHUB_ENV 140 | EXTRA_BUILD_FLAGS="-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DCMAKE_BUILD_TYPE=${BUILD_TYPE}" 141 | echo "cmake flags $BUILD_FLAGS $EXTRA_BUILD_FLAGS" 142 | mkdir build 143 | cd build 144 | cmake -S .. ${BUILD_FLAGS} ${EXTRA_BUILD_FLAGS} 145 | 146 | - name: build 147 | shell: bash 148 | env: 149 | BUILD_TYPE: ${{ matrix.BUILD_TYPE }} 150 | run: | 151 | cd ${GITHUB_WORKSPACE}/build; 152 | cmake --build . -j 2 --config ${BUILD_TYPE}} --target install 153 | 154 | - name: ctest 155 | shell: bash 156 | env: 157 | BUILD_TYPE: ${{ matrix.BUILD_TYPE }} 158 | run: | 159 | set -vx 160 | cd ${GITHUB_WORKSPACE}/build 161 | ctest --output-on-failure -C ${BUILD_TYPE} 162 | 163 | - name: Upload ctest log files for debugging 164 | uses: actions/upload-artifact@v4 165 | if: failure() 166 | with: 167 | name: ctest_log_files-${{ matrix.os }}-${{ matrix.compiler }}${{ matrix.compiler_version }}-${{ matrix.BUILD_TYPE }} 168 | path: | 169 | ${{ github.workspace }}/build/**/*.log 170 | retention-days: 7 171 | 172 | - name: CPack 173 | shell: bash 174 | env: 175 | BUILD_TYPE: ${{ matrix.BUILD_TYPE }} 176 | run: | 177 | set -vx 178 | cd ${GITHUB_WORKSPACE}/build 179 | cpack 180 | # outputs PETPVC-1.*.*.sh, .tar.gz and .tar.Z 181 | 182 | - name: Upload cpack output 183 | uses: actions/upload-artifact@v4 184 | with: 185 | name: cpack_files-${{ matrix.os }}-${{ matrix.compiler }}${{ matrix.compiler_version }}-${{ matrix.BUILD_TYPE }} 186 | path: | 187 | ${{ github.workspace }}/build/PETPVC-*.*.*.* 188 | retention-days: 10 189 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # development and building 2 | result 3 | build 4 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | title: PETPVC PET Partial Volume Correction 3 | message: >- 4 | If you use this software, please cite it using the 5 | metadata from this file. 6 | type: software 7 | authors: 8 | - family-names: Thomas 9 | given-names: Benjamin 10 | orcid: 'https://orcid.org/0000-0002-9784-1177' 11 | affiliation: University College London 12 | - family-names: Thielemans 13 | given-names: Kris 14 | orcid: 'https://orcid.org/0000-0002-5514-199X' 15 | affiliation: University College London 16 | identifiers: 17 | - type: doi 18 | value: 10.1088/0031-9155/61/22/7975 19 | repository-code: 'https://github.com/UCL/PETPVC' 20 | keywords: 21 | - pet 22 | - spect 23 | - medical imaging 24 | - partial volume correction 25 | - open-source software 26 | license: Apache-2.0 27 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #========================================================================= 2 | # Authors: Benjamin A. Thomas, Kris Thielemans 3 | # 4 | # Copyright University College London 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0.txt 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | #========================================================================= 19 | 20 | cmake_minimum_required(VERSION 2.8) 21 | 22 | PROJECT(PETPVC) 23 | 24 | # set default build-type to Release 25 | if(NOT CMAKE_BUILD_TYPE) 26 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING "type of build: Debug Release RelWithDebInfo MinSizeRel." FORCE) 27 | endif() 28 | 29 | SET(VERSION_MAJOR 1) 30 | SET(VERSION_MINOR 2) 31 | SET(VERSION_PATCH 12) 32 | 33 | MAKE_DIRECTORY(${PROJECT_BINARY_DIR}/config) 34 | 35 | CONFIGURE_FILE( 36 | "${PROJECT_SOURCE_DIR}/EnvironmentInfo.h.in" 37 | "${PROJECT_BINARY_DIR}/config/EnvironmentInfo.h" 38 | ) 39 | 40 | #if(CMAKE_COMPILER_IS_GNUCXX) 41 | # include(CodeCoverage) 42 | # setup_target_for_coverage(${PROJECT_NAME}_coverage tests coverage) 43 | #endif() 44 | 45 | #SET(CMAKE_CXX_FLAGS "-Wall -pedantic -pthread -g -O0 --coverage") 46 | 47 | INCLUDE_DIRECTORIES("${PROJECT_BINARY_DIR}/config") 48 | 49 | ENABLE_TESTING() 50 | 51 | FIND_PACKAGE(ITK REQUIRED) 52 | INCLUDE(${ITK_USE_FILE}) 53 | 54 | IF(NOT ITKReview_LOADED) 55 | MESSAGE(FATAL_ERROR "ITK must be built with Module_ITKReview enabled.") 56 | ENDIF() 57 | 58 | INCLUDE_DIRECTORIES(src) 59 | INCLUDE_DIRECTORIES(lib) 60 | 61 | ADD_SUBDIRECTORY(test) 62 | ADD_SUBDIRECTORY(src) 63 | 64 | INSTALL(DIRECTORY "${PROJECT_SOURCE_DIR}/parc/" DESTINATION "parc") 65 | 66 | SET(CPACK_PACKAGE_NAME "PETPVC") 67 | SET(CPACK_PACKAGE_VENDOR "Institute of Nuclear Medicine") 68 | SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Installer for PETPVC") 69 | SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR}) 70 | SET(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR}) 71 | SET(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH}) 72 | SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") 73 | SET(CPACK_PACKAGE_INSTALL_DIRECTORY "PETPVC") 74 | SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") 75 | 76 | SET(CPACK_COMPONENTS_ALL applications) 77 | SET(CPACK_COMPONENT_APPS_DISPLAY_NAME "PETPVC applications") 78 | SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.txt") 79 | 80 | INCLUDE(CPack) 81 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # PETPVC 2 | 3 | FROM alpine:3.16 4 | 5 | MAINTAINER Benjamin A. Thomas 6 | LABEL Description="PETPVC" 7 | 8 | RUN apk --update add ca-certificates && apk upgrade 9 | 10 | RUN apk add alpine-sdk cmake &&\ 11 | apk add linux-headers &&\ 12 | mkdir -p /opt/ITK/BUILD && cd /opt/ITK && \ 13 | git clone -b 'release' --single-branch --depth=1 https://github.com/InsightSoftwareConsortium/ITK.git && \ 14 | cd /opt/ITK/BUILD && \ 15 | cmake -DBUILD_TESTING:BOOL=OFF -DModule_ITKReview:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=Release /opt/ITK/ITK && \ 16 | make && \ 17 | mkdir -p /opt/PETPVC/BUILD && cd /opt/PETPVC && \ 18 | git clone https://github.com/UCL/PETPVC && \ 19 | cd BUILD && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DITK_DIR=/opt/ITK/BUILD /opt/PETPVC/PETPVC && \ 20 | make && make install && ctest && cd ~ && \ 21 | rm -rf /opt/PETPVC && rm -rf /opt/ITK && \ 22 | apk del --purge alpine-sdk cmake && apk add libstdc++ 23 | -------------------------------------------------------------------------------- /EnvironmentInfo.h.in: -------------------------------------------------------------------------------- 1 | const char * const VERSION_MAJOR = "@VERSION_MAJOR@"; 2 | const char * const VERSION_MINOR = "@VERSION_MINOR@"; 3 | const char * const VERSION_PATCH = "@VERSION_PATCH@"; -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | PET Partial Volume Correction (PVC) toolbox 2 | Copyright 2013-2021 Institute of Nuclear Medicine, University College London. 3 | Copyright 2014-2015 Clinical Imaging Research Centre, A*STAR-NUS. 4 | 5 | This product includes software developed at the Institute of Nuclear 6 | Medicine (http://www.ucl.ac.uk/medicine/nuclear-medicine). 7 | 8 | When using this toolbox, please include a reference to the paper below: 9 | 10 | PETPVC: a toolbox for performing partial volume correction techniques in positron emission tomography 11 | BA Thomas, V Cuplov, A Bousse, A Mendes, K Thielemans, BF Hutton, K Erlandsson 12 | Physics in Medicine and Biology 61 (22), 7975 13 | DOI: http://dx.doi.org/10.1088/0031-9155/61/22/7975 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PETPVC 2 | [![Build and ctest and recon_test_pack CI](https://github.com/UCL/PETPVC/actions/workflows/build-test.yml/badge.svg)](https://github.com/UCL/PETPVC/actions/workflows/build-test.yml)[![Build Status](https://dev.azure.com/petpvc/petpvc/_apis/build/status/UCL.PETPVC?branchName=master)](https://dev.azure.com/petpvc/petpvc/_build/latest?definitionId=1&branchName=master) [![Build status](https://ci.appveyor.com/api/projects/status/7kk9ua9r0lybinwa/branch/master?svg=true)](https://ci.appveyor.com/project/bathomas/petpvc/branch/master) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/ab83c41f20194c2c82fbc74e8788f928)](https://www.codacy.com/app/bathomas/PETPVC?utm_source=github.com&utm_medium=referral&utm_content=UCL/PETPVC&utm_campaign=badger) [![DOI](https://zenodo.org/badge/17082200.svg)](https://zenodo.org/badge/latestdoi/17082200) 3 | 4 | PETPVC: toolbox for partial volume correction (PVC) in positron emission tomography (PET) 5 | 6 | ## Publications 7 | When using this toolbox, please include a reference to the paper: 8 | - PETPVC: a toolbox for performing partial volume correction techniques in positron emission tomography
BA Thomas, V Cuplov, A Bousse, A Mendes, K Thielemans, BF Hutton, K Erlandsson
Physics in Medicine and Biology 61 (22), 7975. [DOI](http://dx.doi.org/10.1088/0031-9155/61/22/7975) 9 | 10 | --- 11 | ## Pre-built binaries 12 | 13 | Binaries for Linux, Mac and Windows are provided in the ['Releases' section on Github](https://github.com/UCL/PETPVC/releases). When running the Windows version, you must have installed the ***Visual C++ Redistributable Packages for Visual Studio 2019*** ([link](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170)). For 64-bit Windows, you might have to install both ```vcredist_x86.exe``` and ```vcredist_x64.exe```. 14 | 15 | Alternatively, PETPVC can also be installed via `conda`, see https://anaconda.org/conda-forge/petpvc. 16 | 17 | --- 18 | ## Installation from source instructions 19 | 20 | The following are required to build this software: 21 | 22 | - [CMake](http://www.cmake.org/) 23 | 24 | - [ITK - Segmentation & Registration Toolkit](http://www.itk.org) >=4.7 25 | 26 | - A C++ compiler 27 | 28 | ### Building and installing 29 | - Ensure that ```ITK``` has been built successfully, with the ```ITKReview``` module (```Module_ITKReview``` in CMake) enabled. 30 | - Clone this repository 31 | ```bash 32 | git clone https://github.com/UCL/PETPVC.git 33 | ``` 34 | - Create a build directory 35 | ```bash 36 | mkdir BUILD 37 | ``` 38 | - Change to the build directory 39 | ```bash 40 | cd BUILD 41 | ``` 42 | - Run CMake 43 | ```bash 44 | cmake /path/to/repository 45 | ``` 46 | - Build and install 47 | ```bash 48 | make 49 | make test 50 | make install 51 | ``` 52 | --- 53 | 54 | ## Usage 55 | 56 | ### PVC methods 57 | 58 | Although there are currently executables for every method, it is based to use 59 | `petpvc` which has options to specify the method and parameters. Type 60 | `petpvc` without arguments to get a usage message. 61 | 62 | An example of running iterative Yang with a 6mm PSF: 63 | 64 | ``` 65 | petpvc -i -m -o --pvc IY -x 6.0 -y 6.0 -z 6.0 [--debug] 66 | ``` 67 | where `````` is the PET image file, `````` is the 4-D mask image file and `````` is the destination file for the PV-corrected image. 68 | 69 | *Warning*: there are currently 2 options which seem the same: 70 | - `-n`: specifies the number of iterations for iterative Yang 71 | - `-k`: specifies the number of iterations for deconvolution methods such as 72 | Van Cittert and Richardson-Lucy. 73 | 74 | Therefore, if you use RL only, you have to use the `-k` option. You can use 75 | both options with for instance `IY+RL` to first run iterative Yang followed by 76 | Richardson-Lucy for extra deconvolution. 77 | 78 | ### Extras 79 | 80 | In addition, there are some utilities that you might find useful: 81 | - `pvc_simulate` allows you to blur an image with a Gaussian (e.g. to simulate 82 | resolution effects) 83 | - some [mask related tools](parc/README.md) 84 | 85 | --- 86 | ## Notes on input and output files 87 | The applications in this toolbox use ITK image readers and writers and can 88 | therefore accept common medical imaging formats such as Nifti, ANALYZE and Nrrd, and raw data with an associated meta-data header ([mhd](http://www.itk.org/Wiki/ITK/MetaIO/Documentation#ITK_MetaIO)) file. 89 | 90 | The tissue classification maps (referred to as mask files) can either be binary or probabilistic. All voxel values in a 3-D volume must be 0 <= x <= 1. The PVC applications expect the mask file to be input as a single 4-D volume, where each 3-D volume consists of a single segmented region. 91 | 92 | The use of 4-D volumes facilitates the use of probabilistic segmentations during the PVC. In addition to the constraint that all voxels must be <= 1, The sum of a voxel location across the fourth dimension should be <= 1. Ideally it should be 1, which requires the background to be included as a segmented region. 93 | 94 | ### Special cases where the inputs/outputs are different 95 | #### Muller-Gartner (MG): 96 | The Muller-Gartner correction requires only the grey matter and white 97 | matter masks. Technically, the CSF space should be included as a third 98 | region, but the contribution of this region is assumed to be zero. The 99 | MG application still requires a 4-D mask volume, where the first volume is 100 | grey matter and the second is white matter. The order is important. The 101 | 4-D mask file can contain more than two 3-D volumes, but these will be 102 | ignored by the MG PVC. 103 | 104 | #### Geometric Transfer Matrix (GTM) method: 105 | GTM cannot produce an image. The output of the GTM is a 106 | comma-separated value (CSV) file of regional mean values. The order of the 107 | mean values for each region is written in the same order as they appear in 108 | the fourth dimension of the mask file. 109 | 110 | #### Single Target Correction (STC) method: 111 | The STC method corrects a single region. The mask image should be a 3-D volume, where each voxel in the target region should be 1. All other voxels should be 0. 112 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | skip_commits: 2 | files: 3 | - .github/**/* 4 | - 'azure-pipelines.yml' 5 | - 'CITATION.cff' 6 | - '**/*.md' 7 | - '**/*.html' 8 | - '**/*.htm' 9 | - '**/*.tex' 10 | 11 | # version format 12 | version: "{build}" 13 | 14 | image: Visual Studio 2019 15 | platform: 16 | - x64 17 | configuration: release 18 | 19 | clone_folder: C:\projects\PETPVC 20 | 21 | environment: 22 | ITKSRC: C:\projects\deps\ITK 23 | ITKINSTALL: C:\projects\deps\ITK-5.4.0 24 | ITKBUILD: C:\projects\deps\ITK-BUILD 25 | 26 | install: 27 | - IF NOT EXIST C:\projects\deps mkdir C:\projects\deps 28 | - cd C:\projects\deps 29 | - set ITK_URL="https://github.com/InsightSoftwareConsortium/ITK/archive/v5.4.0.zip" 30 | - IF NOT EXIST C:\projects\deps\ITK-5.4.0.zip appveyor DownloadFile %ITK_URL% -FileName ITK-5.4.0.zip 31 | - IF NOT EXIST %ITKINSTALL% ( 7z x ITK-5.4.0.zip -oC:\projects\deps\ITK > nul && 32 | mkdir %ITKBUILD% && 33 | cd %ITKBUILD% && 34 | cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DCMAKE_INSTALL_PREFIX=%ITKINSTALL% -DModule_ITKReview=ON ..\ITK\ITK-5.4.0 && 35 | msbuild INSTALL.vcxproj 36 | ) 37 | 38 | cache: 39 | - C:\projects\deps\ITK-5.4.0.zip 40 | - C:\projects\deps\ITK-5.4.0 -> appveyor.yml 41 | 42 | build_script: 43 | - cd C:\projects\PETPVC 44 | - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=%ITKINSTALL% -DCMAKE_INSTALL_PATH=. . 45 | - msbuild INSTALL.vcxproj 46 | - msbuild RUN_TESTS.vcxproj 47 | - msbuild PACKAGE.vcxproj 48 | - ps: Get-ChildItem .\*.exe | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } 49 | - ps: >- 50 | if ($env:APPVEYOR_REPO_TAG -eq "true") 51 | { 52 | Update-AppveyorBuild -Version "$env:APPVEYOR_REPO_TAG_NAME" 53 | } 54 | else 55 | { 56 | Update-AppveyorBuild -Version "dev-$($env:APPVEYOR_REPO_COMMIT.substring(0,7))" 57 | } 58 | deploy: 59 | - provider: GitHub 60 | auth_token: 61 | secure: rAhVQ15Ngn/wGthOvIkrQqrMi9jEjFbKwSUan4OxblikIglipPmQTnzZUViYpbmw 62 | release: PETPVC-$(appveyor_build_version) 63 | description: 'Binary release - $(appveyor_build_version)' 64 | artifact: /.*\.exe/ 65 | draft: true 66 | on: 67 | appveyor_repo_tag: true 68 | 69 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Starter pipeline 2 | # Start with a minimal pipeline that you can customize to build and deploy your code. 3 | # Add steps that build, run tests, deploy, and more: 4 | # https://aka.ms/yaml 5 | 6 | trigger: 7 | - master 8 | 9 | jobs: 10 | - job: ubuntu 11 | pool: 12 | vmImage: 'Ubuntu-20.04' 13 | steps: 14 | - script: | 15 | sudo apt-get update 16 | sudo apt-get install -y ninja-build libinsighttoolkit4-dev 17 | displayName: Apt install dependencies 18 | - script: | 19 | mkdir build.debug 20 | mkdir build.release 21 | displayName: Make Build Directories 22 | - task: CMake@1 23 | inputs: 24 | workingDirectory: 'build.debug' 25 | cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' 26 | - task: CMake@1 27 | inputs: 28 | workingDirectory: 'build.release' 29 | cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' 30 | - script: | 31 | cd build.debug 32 | ninja 33 | displayName: 'Run ninja, debug' 34 | - script: | 35 | cd build.debug 36 | ctest 37 | displayName: 'Run tests, debug' 38 | - script: | 39 | cd build.release 40 | ninja 41 | displayName: 'Run ninja, release' 42 | - script: | 43 | cd build.release 44 | ctest 45 | displayName: 'Run tests, release' 46 | - job: macos 47 | pool: 48 | vmImage: 'macOS-latest' 49 | steps: 50 | - script: | 51 | #brew tap bathomas/homebrew-bat 52 | #brew install ninja insighttoolkit 53 | brew install ninja qt5 54 | # brew install itk 55 | Qt5_DIR=$(brew --prefix qt5)/lib/cmake/Qt5 56 | echo "Qt5_DIR = $Qt5_DIR" 57 | ls $Qt5_DIR 58 | echo "##vso[task.setvariable variable=Qt5_DIR;isOutput=true]$Qt5_DIR" 59 | displayName: Brew install dependencies 60 | - script: | 61 | git clone -b release --single-branch https://github.com/InsightSoftwareConsortium/ITK.git 62 | mkdir build.ITK 63 | mkdir install 64 | cdir=`pwd` 65 | cd build.ITK 66 | ITK_CMAKE_FLAGS="-DITK_BUILD_DEFAULT_MODULES:BOOL=OFF 67 | -DITKGroup_IO:BOOL=OFF 68 | -DModule_ITKIOBMP:BOOL=ON 69 | -DModule_ITKIOGDCM:BOOL=ON 70 | -DModule_ITKIOGIPL:BOOL=ON 71 | -DModule_ITKIOJPEG:BOOL=ON 72 | -DModule_ITKIOJPEG2000:BOOL=ON 73 | -DModule_ITKIOMeta:BOOL=ON 74 | -DModule_ITKIONIFTI:BOOL=ON 75 | -DModule_ITKIONRRD:BOOL=ON 76 | -DModule_ITKIOPNG:BOOL=ON 77 | -DModule_ITKIORAW:BOOL=ON 78 | -DModule_ITKIOTIFF:BOOL=ON 79 | -DModule_ITKImageGrid:BOOL=ON 80 | -DITKGroup_Filtering:BOOL=ON 81 | -DModule_ITKReview:BOOL=ON" 82 | 83 | cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${cdir}/install -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF $ITK_CMAKE_FLAGS ../ITK 84 | displayName: Configure ITK 85 | - script: | 86 | mkdir build.debug 87 | mkdir build.release 88 | displayName: Make Build Directories 89 | - script: | 90 | cd build.ITK 91 | ninja && ninja install 92 | displayName: 'Build ITK with ninja, release' 93 | - task: CMake@1 94 | inputs: 95 | workingDirectory: 'build.debug' 96 | cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug -DQt5_DIR=/usr/local/opt/qt@5/lib/cmake/Qt5 -DCMAKE_INSTALL_PREFIX=../install ..' 97 | - task: CMake@1 98 | inputs: 99 | workingDirectory: 'build.release' 100 | runInsideShell: true 101 | cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DQt5_DIR=/usr/local/opt/qt@5/lib/cmake/Qt5 -DCMAKE_INSTALL_PREFIX=../install ..' 102 | - script: | 103 | cd build.debug 104 | ninja 105 | displayName: 'Run ninja, debug' 106 | - script: | 107 | cd build.debug 108 | ctest 109 | displayName: 'Run tests, debug' 110 | - script: | 111 | cd build.release 112 | ninja 113 | displayName: 'Run ninja, release' 114 | - script: | 115 | cd build.release 116 | ctest 117 | displayName: 'Run tests, release' 118 | - job: Windows_VS2022_x64 119 | pool: 120 | vmImage: 'windows-2022' 121 | steps: 122 | - script: | 123 | git clone -b release --single-branch https://github.com/InsightSoftwareConsortium/ITK.git 124 | mkdir build.ITK 125 | cd build.ITK 126 | set ITK_CMAKE_FLAGS=-DITK_BUILD_DEFAULT_MODULES:BOOL=OFF ^ 127 | -DITKGroup_IO:BOOL=OFF ^ 128 | -DModule_ITKIOBMP:BOOL=ON ^ 129 | -DModule_ITKIOGDCM:BOOL=ON ^ 130 | -DModule_ITKIOGIPL:BOOL=ON ^ 131 | -DModule_ITKIOJPEG:BOOL=ON ^ 132 | -DModule_ITKIOJPEG2000:BOOL=ON ^ 133 | -DModule_ITKIOMeta:BOOL=ON ^ 134 | -DModule_ITKIONIFTI:BOOL=ON ^ 135 | -DModule_ITKIONRRD:BOOL=ON ^ 136 | -DModule_ITKIOPNG:BOOL=ON ^ 137 | -DModule_ITKIORAW:BOOL=ON ^ 138 | -DModule_ITKIOTIFF:BOOL=ON ^ 139 | -DModule_ITKImageGrid:BOOL=ON ^ 140 | -DITKGroup_Filtering:BOOL=ON ^ 141 | -DModule_ITKReview:BOOL=ON 142 | 143 | cmake -G "Visual Studio 17" -A "x64" -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF %ITK_CMAKE_FLAGS% ../ITK 144 | displayName: Configure ITK 145 | - task: MSBuild@1 146 | inputs: 147 | solution: 'build.ITK/INSTALL.vcxproj' 148 | maximumCpuCount: true 149 | platform: 'x64' 150 | configuration: 'Release' 151 | displayName: Build ITK 152 | - script: mkdir build.common 153 | displayName: Make Build Directory 154 | - script: | 155 | cd build.common 156 | cmake -G "Visual Studio 17" -A "x64" -DCMAKE_BUILD_TYPE=Release .. 157 | displayName: Configure PETPVC 158 | - task: MSBuild@1 159 | inputs: 160 | solution: 'build.common/ALL_BUILD.vcxproj' 161 | maximumCpuCount: true 162 | platform: 'x64' 163 | configuration: 'Release' 164 | displayName: 'Build PETPVC' 165 | - task: MSBuild@1 166 | inputs: 167 | solution: 'build.common/RUN_TESTS.vcxproj' 168 | maximumCpuCount: true 169 | platform: 'x64' 170 | configuration: 'Release' 171 | displayName: 'Run tests' -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | /* 2 | PETPVC package for the Nix package manager. 3 | 4 | `default.nix` is used for building with nix-build. 5 | See `derivation.nix` for full description. 6 | 7 | Licensing 8 | --------- 9 | 10 | This file is distributed as part of PETPVC. 11 | 12 | Author: Ashley Gillman 13 | 14 | Copyright 2018 Commonwealth Scientific and Industrial Research 15 | Organisation's Australian eHealth Research Centre 16 | 17 | Licensed under the Apache License, Version 2.0 (the "License"); 18 | you may not use this file except in compliance with the License. 19 | You may obtain a copy of the License at 20 | 21 | http://www.apache.org/licenses/LICENSE-2.0 22 | 23 | Unless required by applicable law or agreed to in writing, software 24 | distributed under the License is distributed on an "AS IS" BASIS, 25 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26 | See the License for the specific language governing permissions and 27 | limitations under the License. 28 | */ 29 | 30 | { pkgs ? import {} }: 31 | 32 | pkgs.callPackage ./derivation.nix { itk = pkgs.itk4; } 33 | -------------------------------------------------------------------------------- /derivation.nix: -------------------------------------------------------------------------------- 1 | /* 2 | PETPVC package for the Nix package manager. 3 | 4 | Development 5 | ----------- 6 | 7 | To drop into a shell with dependencies available: 8 | 9 | nix-shell 10 | 11 | You can then build in this development environment: 12 | 13 | mkdir build && cd build 14 | cmake .. 15 | make 16 | 17 | Building and Installing 18 | ----------------------- 19 | 20 | From the root directory of the project, run: 21 | 22 | nix-build 23 | 24 | This will build to ./result, with binaries in ./result/bin. 25 | 26 | You can install to your path using 27 | 28 | nix-env -i ./result 29 | 30 | Licensing 31 | --------- 32 | 33 | This file is distributed as part of PETPVC. 34 | 35 | Author: Ashley Gillman 36 | 37 | Copyright 2018 Commonwealth Scientific and Industrial Research 38 | Organisation's Australian eHealth Research Centre 39 | 40 | Licensed under the Apache License, Version 2.0 (the "License"); 41 | you may not use this file except in compliance with the License. 42 | You may obtain a copy of the License at 43 | 44 | http://www.apache.org/licenses/LICENSE-2.0 45 | 46 | Unless required by applicable law or agreed to in writing, software 47 | distributed under the License is distributed on an "AS IS" BASIS, 48 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 49 | See the License for the specific language governing permissions and 50 | limitations under the License. 51 | */ 52 | 53 | { stdenv 54 | , fetchFromGitHub 55 | , cmake 56 | , itk 57 | }: 58 | 59 | stdenv.mkDerivation { 60 | name = "PETPVC"; 61 | 62 | # src = fetchFromGitHub { 63 | # owner = "UCL"; 64 | # repo = "PETPVC"; 65 | # rev = "0000000"; # Can place a specific revision here 66 | # # After you first get an error, place the actual sha256 reported below 67 | # sha256 = "0000000000000000000000000000000000000000000000000000"; 68 | # }; 69 | src = builtins.fetchGit { url = ./.; }; # respect .gitignore 70 | 71 | enableParallelBuilding = true; 72 | 73 | buildInputs = [ cmake itk ]; 74 | #cmakeBuildType = "Debug"; 75 | 76 | meta = with stdenv.lib; { 77 | description = "Partial Volume Correction in PET"; 78 | homepage = https://github.com/UCL/PETPVC; 79 | license = licenses.asl20; # Apache 2.0 80 | }; 81 | } 82 | -------------------------------------------------------------------------------- /lib/petpvcDiscreteIYPVCImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcDiscreteIYPVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2014-2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2014-2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCDISCRETEIYIMAGEFILTER_H 24 | #define __PETPVCDISCRETEIYIMAGEFILTER_H 25 | 26 | #include "itkImage.h" 27 | #include "itkImageToImageFilter.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | 39 | #include 40 | 41 | 42 | using namespace itk; 43 | 44 | namespace petpvc 45 | { 46 | template< class TInputImage, typename TMaskImage> 47 | class DiscreteIYPVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 48 | { 49 | public: 50 | /** Standard class typedefs. */ 51 | typedef DiscreteIYPVCImageFilter Self; 52 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 53 | typedef SmartPointer< Self > Pointer; 54 | 55 | /** Method for creation through the object factory. */ 56 | itkNewMacro(Self); 57 | 58 | /** Run-time type information (and related methods). */ 59 | #if ITK_VERSION_MAJOR < 6 60 | itkTypeMacro(DiscreteIYPVCImageFilter, ImageToImageFilter); 61 | #else 62 | itkOverrideGetNameOfClassMacro(DiscreteIYPVCImageFilter); 63 | #endif 64 | 65 | /** Image related typedefs. */ 66 | typedef TInputImage InputImageType; 67 | typedef typename TInputImage::ConstPointer InputImagePointer; 68 | typedef typename TInputImage::RegionType RegionType; 69 | typedef typename TInputImage::SizeType SizeType; 70 | typedef typename TInputImage::IndexType IndexType; 71 | typedef typename TInputImage::PixelType PixelType; 72 | 73 | /** Mask image related typedefs. */ 74 | typedef TMaskImage MaskImageType; 75 | typedef typename TMaskImage::ConstPointer MaskImagePointer; 76 | typedef typename TMaskImage::RegionType MaskRegionType; 77 | typedef typename TMaskImage::SizeType MaskSizeType; 78 | typedef typename TMaskImage::IndexType MaskIndexType; 79 | typedef typename TMaskImage::PixelType MaskPixelType; 80 | 81 | //For calculating mean values from image 82 | typedef itk::StatisticsImageFilter StatisticsFilterType; 83 | 84 | //For getting information about the mask labels 85 | typedef itk::LabelStatisticsImageFilter LabelStatisticsFilterType; 86 | typedef typename LabelStatisticsFilterType::ValidLabelValuesContainerType ValidLabelValuesType; 87 | typedef typename LabelStatisticsFilterType::LabelPixelType LabelPixelType; 88 | 89 | typedef itk::BinaryThresholdImageFilter BinaryThresholdImageFilterType; 90 | 91 | typedef itk::MultiplyImageFilter MultiplyFilterType; 92 | typedef itk::DivideImageFilter DivideFilterType; 93 | typedef itk::AddImageFilter AddFilterType; 94 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 95 | typedef itk::ImageDuplicator DuplicatorType; 96 | 97 | typedef itk::Vector ITKVectorType; 98 | 99 | /** Image related typedefs. */ 100 | itkStaticConstMacro(InputImageDimension, unsigned int, 101 | 3); 102 | 103 | itkStaticConstMacro(MaskImageDimension, unsigned int, 104 | 3); 105 | 106 | typedef vnl_vector VectorType; 107 | typedef vnl_matrix MatrixType; 108 | 109 | /** Set the mask image */ 110 | void SetMaskInput(const TMaskImage *input) { 111 | // Process object is not const-correct so the const casting is required. 112 | this->SetNthInput( 1, const_cast< TMaskImage * >( input ) ); 113 | } 114 | 115 | /** Get the label image */ 116 | const MaskImageType * GetMaskInput() const { 117 | return itkDynamicCastInDebugMode< MaskImageType * >( const_cast< DataObject * >( this->ProcessObject::GetInput(0) ) ); 118 | } 119 | 120 | VectorType GetCorrectedMeans() const { 121 | return this->m_vecRegMeansPVCorr; 122 | } 123 | 124 | MatrixType GetMatrix() const { 125 | return this->m_matGTM; 126 | } 127 | 128 | void SetPSF(ITKVectorType vec) { 129 | this->m_vecVariance = vec; 130 | } 131 | 132 | 133 | ITKVectorType GetPSF() { 134 | return this->m_vecVariance; 135 | } 136 | 137 | void SetIterations( unsigned int nIters ) { 138 | this->m_nIterations = nIters; 139 | } 140 | 141 | void SetVerbose( bool bVerbose ) { 142 | this->m_bVerbose = bVerbose; 143 | } 144 | 145 | 146 | protected: 147 | DiscreteIYPVCImageFilter(); 148 | ~DiscreteIYPVCImageFilter() {}; 149 | 150 | /** Does the real work. */ 151 | virtual void GenerateData() ITK_OVERRIDE; 152 | 153 | VectorType m_vecRegMeansPVCorr; 154 | MatrixType m_matGTM; 155 | ITKVectorType m_vecVariance; 156 | unsigned int m_nIterations; 157 | bool m_bVerbose; 158 | 159 | private: 160 | DiscreteIYPVCImageFilter(const Self &); //purposely not implemented 161 | void operator=(const Self &); //purposely not implemented 162 | 163 | 164 | 165 | }; 166 | } //namespace petpvc 167 | 168 | 169 | #ifndef ITK_MANUAL_INSTANTIATION 170 | #include "petpvcDiscreteIYPVCImageFilter.txx" 171 | #endif 172 | 173 | 174 | #endif // __PETPVCDISCRETEIYIMAGEFILTER_H 175 | -------------------------------------------------------------------------------- /lib/petpvcFuzzyCorrectionFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcFuzzyCorrectionFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2013-2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2014-2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCFUZZYCORRECTIONFILTER_H 24 | #define __PETPVCFUZZYCORRECTIONFILTER_H 25 | 26 | #include "itkImageToImageFilter.h" 27 | #include "vnl/vnl_matrix.h" 28 | 29 | //A class to perform fuzziness 'correction'. This is required to weight the 30 | //mean values correctly when using probabilistic segmentations. For binary 31 | //(piece-wise constant) segmentations, this is not necessary and will return 32 | //the identity matrix. 33 | 34 | using namespace itk; 35 | 36 | namespace petpvc 37 | { 38 | 39 | template 40 | class FuzzyCorrectionFilter : public ImageToImageFilter 41 | { 42 | public: 43 | 44 | typedef FuzzyCorrectionFilter Self; 45 | typedef ImageToImageFilter Superclass; 46 | typedef SmartPointer Pointer; 47 | 48 | //Matrix to hold correction factors 49 | typedef vnl_matrix MatrixType; 50 | 51 | //Vector containing size of region. 52 | typedef vnl_vector VectorType; 53 | 54 | itkNewMacro(Self); 55 | 56 | #if ITK_VERSION_MAJOR < 6 57 | itkTypeMacro(FuzzyCorrectionFilter, ImageToImageFilter); 58 | #else 59 | itkOverrideGetNameOfClassMacro(FuzzyCorrectionFilter); 60 | #endif 61 | 62 | //Returns correction factors. 63 | 64 | vnl_matrix GetMatrix() { 65 | return *this->matFuzz; 66 | }; 67 | 68 | //Returns region size. 69 | 70 | vnl_vector GetSumOfRegions() { 71 | return *this->vecSumOfRegions; 72 | }; 73 | 74 | protected: 75 | FuzzyCorrectionFilter(); 76 | ~FuzzyCorrectionFilter(); 77 | 78 | /** Does the real work. */ 79 | virtual void GenerateData() ITK_OVERRIDE; 80 | 81 | 82 | private: 83 | FuzzyCorrectionFilter(const Self &); //purposely not implemented 84 | void operator=(const Self &); //purposely not implemented 85 | 86 | MatrixType *matFuzz; 87 | VectorType *vecSumOfRegions; 88 | 89 | }; 90 | } //namespace PETPVC 91 | 92 | #ifndef ITK_MANUAL_INSTANTIATION 93 | #include "petpvcFuzzyCorrectionFilter.txx" 94 | #endif 95 | 96 | #endif // __PETPVCFUZZYCORRECTIONFILTER_H 97 | -------------------------------------------------------------------------------- /lib/petpvcFuzzyCorrectionFilter.txx: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcFuzzyCorrectionFilter.txx 3 | 4 | Authors: Benjamin A. Thomas 5 | Kris Thielemans (minor modifications) 6 | 7 | Copyright 2014-2015 Institute of Nuclear Medicine, University College London. 8 | Copyright 2014-2015 Clinical Imaging Research Centre, A*STAR-NUS. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, 18 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | See the License for the specific language governing permissions and 20 | limitations under the License. 21 | 22 | */ 23 | 24 | #ifndef __PETPVCFUZZYCORRECTIONFILTER_TXX 25 | #define __PETPVCFUZZYCORRECTIONFILTER_TXX 26 | 27 | #include "petpvcFuzzyCorrectionFilter.h" 28 | #include "itkObjectFactory.h" 29 | #include "itkImageRegionIterator.h" 30 | #include "itkImageRegionConstIterator.h" 31 | #include 32 | #include 33 | #include 34 | #include "vnl/vnl_matrix.h" 35 | 36 | using namespace itk; 37 | 38 | namespace petpvc 39 | { 40 | 41 | template 42 | FuzzyCorrectionFilter::FuzzyCorrectionFilter() 43 | { 44 | //Constructor. Just initialises the matrix and vector that will 45 | //contain the results of the correction that the filter implements. 46 | this->matFuzz = new MatrixType; 47 | this->vecSumOfRegions = new VectorType; 48 | } 49 | 50 | template 51 | void FuzzyCorrectionFilter::GenerateData() 52 | { 53 | 54 | this->SetGlobalDefaultCoordinateTolerance( 1e-2 ); 55 | this->SetGlobalDefaultDirectionTolerance( 1e-2 ); 56 | 57 | //Get pointers to input and output. 58 | typename TImage::ConstPointer input = this->GetInput(); 59 | typename TImage::Pointer output = this->GetOutput(); 60 | 61 | this->AllocateOutputs(); 62 | 63 | //Get region size. 64 | typename TImage::SizeType imageSize = 65 | input->GetLargestPossibleRegion().GetSize(); 66 | 67 | int nClasses = 0; 68 | 69 | //Set size of output matrix and vector. 70 | //TODO: Should throw an exception here if imageSize.Dimension != 4. 71 | if (imageSize.Dimension == 4) { 72 | nClasses = imageSize[3]; 73 | matFuzz->set_size(nClasses, nClasses); 74 | matFuzz->fill(0); 75 | 76 | vecSumOfRegions->set_size(nClasses); 77 | vecSumOfRegions->fill(0); 78 | 79 | } 80 | 81 | typedef itk::Image MaskImageType; 82 | 83 | typedef itk::StatisticsImageFilter StatisticsFilterType; 84 | typedef itk::ExtractImageFilter ExtractFilterType; 85 | typedef itk::MultiplyImageFilter MultiplyFilterType; 86 | 87 | typename TImage::IndexType desiredStart; 88 | desiredStart.Fill(0); 89 | 90 | typename TImage::SizeType desiredSize = 91 | input->GetLargestPossibleRegion().GetSize(); 92 | 93 | typename TImage::RegionType desiredRegion; 94 | 95 | StatisticsFilterType::Pointer statsFilter = StatisticsFilterType::New(); 96 | 97 | typename ExtractFilterType::Pointer extractTargetFilter = 98 | ExtractFilterType::New(); 99 | typename ExtractFilterType::Pointer extractNeighbourFilter = 100 | ExtractFilterType::New(); 101 | typename MultiplyFilterType::Pointer multiplyFilter = 102 | MultiplyFilterType::New(); 103 | 104 | float fSumTarget; 105 | float fSumNeighbour; 106 | 107 | for (int i = 1; i <= nClasses; i++) { 108 | 109 | fSumTarget = 0.0; 110 | desiredStart[3] = i - 1; 111 | desiredSize[3] = 0; 112 | 113 | //Extract 3D brain mask volume i from 4D image. 114 | extractTargetFilter->SetExtractionRegion( 115 | typename TImage::RegionType(desiredStart, desiredSize)); 116 | extractTargetFilter->SetInput(input); 117 | extractTargetFilter->SetDirectionCollapseToIdentity(); // This is required. 118 | extractTargetFilter->Update(); 119 | 120 | statsFilter->SetInput(extractTargetFilter->GetOutput()); 121 | statsFilter->Update(); 122 | 123 | //Calculate the sum of non-zero voxels. 124 | fSumTarget = statsFilter->GetSum(); 125 | if (fSumTarget == 0) { 126 | itkExceptionMacro("Region " << i << " has zero sum, i.e. no voxels in mask. Remove this region."); 127 | } 128 | if (statsFilter->GetMinimum() < 0) { 129 | itkExceptionMacro("Region " << i << "contains negative voxels in mask. Remove this region."); 130 | } 131 | std::cerr << "sum in region " << i << " = " << fSumTarget << std::endl; 132 | 133 | vecSumOfRegions->put(i - 1, fSumTarget); 134 | 135 | //Set region i as first input. 136 | multiplyFilter->SetInput1(extractTargetFilter->GetOutput()); 137 | 138 | for (int j = 1; j <= nClasses; j++) { 139 | fSumNeighbour = 0.0; 140 | desiredStart[3] = j - 1; 141 | desiredSize[3] = 0; 142 | 143 | //Extract 3D brain mask volume j from 4D image. 144 | extractNeighbourFilter->SetExtractionRegion( 145 | typename TImage::RegionType(desiredStart, desiredSize)); 146 | extractNeighbourFilter->SetInput(input); 147 | extractNeighbourFilter->SetDirectionCollapseToIdentity(); // This is required. 148 | extractNeighbourFilter->Update(); 149 | 150 | //Multiply i by j. 151 | multiplyFilter->SetInput2(extractNeighbourFilter->GetOutput()); 152 | 153 | statsFilter->SetInput(multiplyFilter->GetOutput()); 154 | statsFilter->Update(); 155 | 156 | //Calculate the sum of the remaining voxels. 157 | fSumNeighbour = statsFilter->GetSum(); 158 | 159 | //Fill location in matrix with sum of remaining voxels 160 | //normalised by size of i. 161 | matFuzz->put(i - 1, j - 1, fSumNeighbour / fSumTarget); 162 | 163 | } 164 | 165 | } 166 | } 167 | 168 | template 169 | FuzzyCorrectionFilter::~FuzzyCorrectionFilter(void) 170 | { 171 | //Destructor. 172 | delete this->matFuzz; 173 | delete this->vecSumOfRegions; 174 | } 175 | } // end namespace 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /lib/petpvcFuzzyCorrectionFilter.txx~: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcFuzzyCorrectionFilter.txx 3 | 4 | Authors: Benjamin A. Thomas 5 | Kris Thielemans (minor modifications) 6 | 7 | Copyright 2013-2014 Institute of Nuclear Medicine, University College London. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCFUZZYCORRECTIONFILTER_TXX 24 | #define __PETPVCFUZZYCORRECTIONFILTER_TXX 25 | 26 | #include "petpvcFuzzyCorrectionFilter.h" 27 | #include "itkObjectFactory.h" 28 | #include "itkImageRegionIterator.h" 29 | #include "itkImageRegionConstIterator.h" 30 | #include 31 | #include 32 | #include 33 | #include "vnl/vnl_matrix.h" 34 | 35 | using namespace itk; 36 | 37 | namespace petpvc 38 | { 39 | 40 | template 41 | FuzzyCorrectionFilter::FuzzyCorrectionFilter() 42 | { 43 | //Constructor. Just initialises the matrix and vector that will 44 | //contain the results of the correction that the filter implements. 45 | this->matFuzz = new MatrixType; 46 | this->vecSumOfRegions = new VectorType; 47 | } 48 | 49 | template 50 | void FuzzyCorrectionFilter::GenerateData() 51 | { 52 | 53 | //Get pointers to input and output. 54 | typename TImage::ConstPointer input = this->GetInput(); 55 | typename TImage::Pointer output = this->GetOutput(); 56 | 57 | this->AllocateOutputs(); 58 | 59 | //Get region size. 60 | typename TImage::SizeType imageSize = 61 | input->GetLargestPossibleRegion().GetSize(); 62 | 63 | int nClasses = 0; 64 | 65 | //Set size of output matrix and vector. 66 | //TODO: Should throw an exception here if imageSize.Dimension != 4. 67 | if (imageSize.Dimension == 4) { 68 | nClasses = imageSize[3]; 69 | matFuzz->set_size(nClasses, nClasses); 70 | matFuzz->fill(0); 71 | 72 | vecSumOfRegions->set_size(nClasses); 73 | vecSumOfRegions->fill(0); 74 | 75 | } 76 | 77 | typedef itk::Image MaskImageType; 78 | 79 | typedef itk::StatisticsImageFilter StatisticsFilterType; 80 | typedef itk::ExtractImageFilter ExtractFilterType; 81 | typedef itk::MultiplyImageFilter MultiplyFilterType; 82 | 83 | typename TImage::IndexType desiredStart; 84 | desiredStart.Fill(0); 85 | 86 | typename TImage::SizeType desiredSize = 87 | input->GetLargestPossibleRegion().GetSize(); 88 | 89 | typename TImage::RegionType desiredRegion; 90 | 91 | StatisticsFilterType::Pointer statsFilter = StatisticsFilterType::New(); 92 | 93 | typename ExtractFilterType::Pointer extractTargetFilter = 94 | ExtractFilterType::New(); 95 | typename ExtractFilterType::Pointer extractNeighbourFilter = 96 | ExtractFilterType::New(); 97 | typename MultiplyFilterType::Pointer multiplyFilter = 98 | MultiplyFilterType::New(); 99 | 100 | float fSumTarget; 101 | float fSumNeighbour; 102 | 103 | for (int i = 1; i <= nClasses; i++) { 104 | 105 | fSumTarget = 0.0; 106 | desiredStart[3] = i - 1; 107 | desiredSize[3] = 0; 108 | 109 | //Extract 3D brain mask volume i from 4D image. 110 | extractTargetFilter->SetExtractionRegion( 111 | typename TImage::RegionType(desiredStart, desiredSize)); 112 | extractTargetFilter->SetInput(input); 113 | extractTargetFilter->SetDirectionCollapseToIdentity(); // This is required. 114 | extractTargetFilter->Update(); 115 | 116 | statsFilter->SetInput(extractTargetFilter->GetOutput()); 117 | statsFilter->Update(); 118 | 119 | //Calculate the sum of non-zero voxels. 120 | fSumTarget = statsFilter->GetSum(); 121 | if (fSumTarget == 0) { 122 | itkExceptionMacro("Region " << i << " has zero sum, i.e. no voxels in mask. Remove this region."); 123 | } 124 | if (statsFilter->GetMinimum() < 0) { 125 | itkExceptionMacro("Region " << i << "contains negative voxels in mask. Remove this region."); 126 | } 127 | std::cerr << "sum in region " << i << " = " << fSumTarget << std::endl; 128 | 129 | vecSumOfRegions->put(i - 1, fSumTarget); 130 | 131 | //Set region i as first input. 132 | multiplyFilter->SetInput1(extractTargetFilter->GetOutput()); 133 | 134 | for (int j = 1; j <= nClasses; j++) { 135 | fSumNeighbour = 0.0; 136 | desiredStart[3] = j - 1; 137 | desiredSize[3] = 0; 138 | 139 | //Extract 3D brain mask volume j from 4D image. 140 | extractNeighbourFilter->SetExtractionRegion( 141 | typename TImage::RegionType(desiredStart, desiredSize)); 142 | extractNeighbourFilter->SetInput(input); 143 | extractNeighbourFilter->SetDirectionCollapseToIdentity(); // This is required. 144 | extractNeighbourFilter->Update(); 145 | 146 | //Multiply i by j. 147 | multiplyFilter->SetInput2(extractNeighbourFilter->GetOutput()); 148 | 149 | statsFilter->SetInput(multiplyFilter->GetOutput()); 150 | statsFilter->Update(); 151 | 152 | //Calculate the sum of the remaining voxels. 153 | fSumNeighbour = statsFilter->GetSum(); 154 | 155 | //Fill location in matrix with sum of remaining voxels 156 | //normalised by size of i. 157 | matFuzz->put(i - 1, j - 1, fSumNeighbour / fSumTarget); 158 | 159 | } 160 | 161 | } 162 | } 163 | 164 | template 165 | FuzzyCorrectionFilter::~FuzzyCorrectionFilter(void) 166 | { 167 | //Destructor. 168 | delete this->matFuzz; 169 | delete this->vecSumOfRegions; 170 | } 171 | } // end namespace 172 | 173 | #endif 174 | -------------------------------------------------------------------------------- /lib/petpvcGTMImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcGTMImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2013 Institute of Nuclear Medicine, University College London. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | */ 21 | 22 | #ifndef __PETPVCGTMIMAGEFILTER_H 23 | #define __PETPVCGTMIMAGEFILTER_H 24 | 25 | #include "itkImageToImageFilter.h" 26 | #include "vnl/vnl_matrix.h" 27 | #include 28 | #include 29 | #include 30 | 31 | //A class to perform GTM. 32 | 33 | using namespace itk; 34 | 35 | 36 | namespace petpvc 37 | { 38 | 39 | template 40 | class GTMImageFilter : public ImageToImageFilter 41 | { 42 | public: 43 | 44 | typedef GTMImageFilter Self; 45 | typedef ImageToImageFilter Superclass; 46 | typedef SmartPointer Pointer; 47 | 48 | //Matrix to hold correction factors 49 | typedef vnl_matrix MatrixType; 50 | 51 | //Vector containing size of region. 52 | typedef vnl_vector VectorType; 53 | typedef itk::Vector ITKVectorType; 54 | 55 | itkNewMacro(Self); 56 | 57 | #if ITK_VERSION_MAJOR < 6 58 | itkTypeMacro(GTMImageFilter, ImageToImageFilter); 59 | #else 60 | itkOverrideGetNameOfClassMacro(GTMImageFilter); 61 | #endif 62 | 63 | //Returns correction factors. 64 | vnl_matrix GetMatrix() { 65 | return *this->matCorrFactors; 66 | }; 67 | 68 | //Returns region size. 69 | 70 | vnl_vector GetSumOfRegions() { 71 | return *this->vecSumOfRegions; 72 | }; 73 | 74 | void SetPSF(ITKVectorType vec) { 75 | this->vecVariance = vec; 76 | }; 77 | 78 | ITKVectorType GetPSF() { 79 | return this->vecVariance; 80 | }; 81 | 82 | 83 | protected: 84 | GTMImageFilter(); 85 | ~GTMImageFilter(); 86 | 87 | /** Does the real work. */ 88 | virtual void GenerateData() ITK_OVERRIDE; 89 | 90 | private: 91 | GTMImageFilter(const Self &); //purposely not implemented 92 | void operator=(const Self &); //purposely not implemented 93 | 94 | MatrixType *matCorrFactors; 95 | VectorType *vecSumOfRegions; 96 | ITKVectorType vecVariance; 97 | }; 98 | } //namespace PETPVC 99 | 100 | #ifndef ITK_MANUAL_INSTANTIATION 101 | #include "petpvcGTMImageFilter.txx" 102 | #endif 103 | 104 | #endif // __PETPVCGTMIMAGEFILTER_H 105 | -------------------------------------------------------------------------------- /lib/petpvcGTMImageFilter.txx: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcGTMImageFilter.txx 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2013 Institute of Nuclear Medicine, University College London. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | */ 21 | 22 | #ifndef __PETPVCGTMIMAGEFILTER_TXX 23 | #define __PETPVCGTMIMAGEFILTER_TXX 24 | 25 | #include "petpvcGTMImageFilter.h" 26 | #include "itkObjectFactory.h" 27 | #include "itkImageRegionIterator.h" 28 | #include "itkImageRegionConstIterator.h" 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "vnl/vnl_matrix.h" 35 | 36 | using namespace itk; 37 | 38 | namespace petpvc 39 | { 40 | 41 | template 42 | GTMImageFilter::GTMImageFilter() 43 | { 44 | //Constructor. Just initialises the matrix and vector that will 45 | //contain the results of the correction that the filter implements. 46 | this->matCorrFactors = new MatrixType; 47 | this->vecSumOfRegions = new VectorType; 48 | 49 | //this->vecVariance = new ITKVectorType; 50 | 51 | } 52 | 53 | template 54 | void GTMImageFilter::GenerateData() 55 | { 56 | 57 | this->SetGlobalDefaultCoordinateTolerance( 1e-2 ); 58 | this->SetGlobalDefaultDirectionTolerance( 1e-2 ); 59 | 60 | //Get pointers to input and output. 61 | typename TImage::ConstPointer input = this->GetInput(); 62 | 63 | //Get region size. 64 | typename TImage::SizeType imageSize = 65 | input->GetLargestPossibleRegion().GetSize(); 66 | 67 | int nClasses = 0; 68 | 69 | //Set size of output matrix and vector. 70 | //TODO: Should throw an exception here if imageSize.Dimension != 4. 71 | if (imageSize.Dimension == 4) { 72 | nClasses = imageSize[3]; 73 | matCorrFactors->set_size(nClasses, nClasses); 74 | matCorrFactors->fill(0); 75 | 76 | vecSumOfRegions->set_size(nClasses); 77 | vecSumOfRegions->fill(0); 78 | 79 | } 80 | 81 | typedef itk::Image MaskImageType; 82 | 83 | typedef itk::StatisticsImageFilter StatisticsFilterType; 84 | typedef itk::ExtractImageFilter ExtractFilterType; 85 | typedef itk::MultiplyImageFilter MultiplyFilterType; 86 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 87 | 88 | typedef itk::ImageDuplicator DuplicatorType; 89 | 90 | typename TImage::IndexType desiredStart; 91 | desiredStart.Fill(0); 92 | 93 | typename TImage::SizeType desiredSize = 94 | input->GetLargestPossibleRegion().GetSize(); 95 | 96 | typename TImage::RegionType desiredRegion; 97 | 98 | StatisticsFilterType::Pointer statsFilter = StatisticsFilterType::New(); 99 | 100 | typename ExtractFilterType::Pointer extractTargetFilter = 101 | ExtractFilterType::New(); 102 | typename ExtractFilterType::Pointer extractNeighbourFilter = 103 | ExtractFilterType::New(); 104 | typename MultiplyFilterType::Pointer multiplyFilter = 105 | MultiplyFilterType::New(); 106 | typename BlurringFilterType::Pointer blurringFilter = 107 | BlurringFilterType::New(); 108 | 109 | blurringFilter->SetVariance((this->GetPSF())); 110 | 111 | float fSumTarget; 112 | float fSumNeighbour; 113 | 114 | for (int i = 1; i <= nClasses; i++) { 115 | 116 | fSumTarget = 0.0; 117 | desiredStart[3] = i - 1; 118 | desiredSize[3] = 0; 119 | 120 | //Extract 3D brain mask volume i from 4D image. 121 | extractTargetFilter->SetExtractionRegion( 122 | typename TImage::RegionType(desiredStart, desiredSize)); 123 | extractTargetFilter->SetInput(input); 124 | extractTargetFilter->SetDirectionCollapseToIdentity(); // This is required. 125 | extractTargetFilter->Update(); 126 | 127 | blurringFilter->SetInput(extractTargetFilter->GetOutput()); 128 | 129 | statsFilter->SetInput(blurringFilter->GetOutput()); 130 | statsFilter->Update(); 131 | 132 | //Calculate the sum of non-zero voxels. 133 | fSumTarget = statsFilter->GetSum(); 134 | 135 | vecSumOfRegions->put(i - 1, fSumTarget); 136 | 137 | for (int j = 1; j <= nClasses; j++) { 138 | fSumNeighbour = 0.0; 139 | desiredStart[3] = j - 1; 140 | desiredSize[3] = 0; 141 | 142 | //Extract 3D brain mask volume j from 4D image. 143 | extractNeighbourFilter->SetExtractionRegion( 144 | typename TImage::RegionType(desiredStart, desiredSize)); 145 | extractNeighbourFilter->SetInput(input); 146 | extractNeighbourFilter->SetDirectionCollapseToIdentity(); // This is required. 147 | extractNeighbourFilter->Update(); 148 | 149 | //Multiply i by j. 150 | multiplyFilter->SetInput1(blurringFilter->GetOutput()); 151 | multiplyFilter->SetInput2(extractNeighbourFilter->GetOutput()); 152 | 153 | statsFilter->SetInput(multiplyFilter->GetOutput()); 154 | statsFilter->Update(); 155 | 156 | //Calculate the sum of the remaining voxels. 157 | fSumNeighbour = statsFilter->GetSum(); 158 | 159 | //Fill location in matrix with sum of remaining voxels 160 | //normalised by size of i. 161 | matCorrFactors->put(i - 1, j - 1, fSumNeighbour / fSumTarget); 162 | 163 | //std::cout << "Target: " << fSumTarget << " Neighbour: " << fSumNeighbour << std::endl; 164 | } 165 | 166 | } 167 | } 168 | 169 | template 170 | GTMImageFilter::~GTMImageFilter() 171 | { 172 | //Destructor. 173 | delete this->matCorrFactors; 174 | delete this->vecSumOfRegions; 175 | 176 | } 177 | 178 | } // end namespace 179 | 180 | #endif 181 | -------------------------------------------------------------------------------- /lib/petpvcIntraRegRLImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcIntraRegRLImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCINTRAREGRLIMAGEFILTER_H 24 | #define __PETPVCINTRAREGRLIMAGEFILTER_H 25 | 26 | #include "itkImage.h" 27 | #include "itkImageToImageFilter.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "petpvcRegionConvolutionImageFilter.h" 35 | #include 36 | 37 | #include 38 | 39 | using namespace itk; 40 | 41 | namespace petpvc 42 | { 43 | template< class TInputImage, typename TMaskImage> 44 | class IntraRegRLImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 45 | { 46 | public: 47 | /** Standard class typedefs. */ 48 | typedef IntraRegRLImageFilter Self; 49 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 50 | typedef SmartPointer< Self > Pointer; 51 | 52 | /** Method for creation through the object factory. */ 53 | itkNewMacro(Self); 54 | 55 | /** Run-time type information (and related methods). */ 56 | #if ITK_VERSION_MAJOR < 6 57 | itkTypeMacro(IntraRegRLImageFilter, ImageToImageFilter); 58 | #else 59 | itkOverrideGetNameOfClassMacro(IntraRegRLImageFilter); 60 | #endif 61 | 62 | /** Image related typedefs. */ 63 | typedef TInputImage InputImageType; 64 | typedef typename TInputImage::ConstPointer InputImagePointer; 65 | typedef typename TInputImage::RegionType RegionType; 66 | typedef typename TInputImage::SizeType SizeType; 67 | typedef typename TInputImage::IndexType IndexType; 68 | typedef typename TInputImage::PixelType PixelType; 69 | 70 | /** Mask image related typedefs. */ 71 | typedef TMaskImage MaskImageType; 72 | typedef typename TMaskImage::ConstPointer MaskImagePointer; 73 | typedef typename TMaskImage::RegionType MaskRegionType; 74 | typedef typename TMaskImage::SizeType MaskSizeType; 75 | typedef typename TMaskImage::IndexType MaskIndexType; 76 | typedef typename TMaskImage::PixelType MaskPixelType; 77 | 78 | typedef itk::ImageRegionConstIterator ConstImageIterator; 79 | 80 | //Extracts a 3D volume from 4D file. 81 | typedef itk::ExtractImageFilter ExtractFilterType; 82 | typedef itk::MultiplyImageFilter MultiplyFilterType; 83 | typedef itk::DivideImageFilter DivideFilterType; 84 | typedef itk::AddImageFilter AddFilterType; 85 | typedef itk::SubtractImageFilter SubFilterType; 86 | typedef petpvc::RegionConvolutionPVCImageFilter IntraRegBlurFilterType; 87 | typedef itk::ThresholdImageFilter ThresholdFilterType; 88 | typedef itk::ImageDuplicator DuplicatorType; 89 | 90 | typedef itk::Vector ITKVectorType; 91 | 92 | /** Image related typedefs. */ 93 | itkStaticConstMacro(InputImageDimension, unsigned int, 94 | 3); 95 | 96 | itkStaticConstMacro(MaskImageDimension, unsigned int, 97 | 4); 98 | 99 | typedef vnl_vector VectorType; 100 | typedef vnl_matrix MatrixType; 101 | 102 | /** Set the mask image */ 103 | void SetMaskInput(const TMaskImage *input) { 104 | // Process object is not const-correct so the const casting is required. 105 | this->SetNthInput( 1, const_cast< TMaskImage * >( input ) ); 106 | } 107 | 108 | /** Get the label image */ 109 | const MaskImageType * GetMaskInput() const { 110 | return itkDynamicCastInDebugMode< MaskImageType * >( const_cast< DataObject * >( this->ProcessObject::GetInput(0) ) ); 111 | } 112 | 113 | void SetPSF(ITKVectorType vec) { 114 | this->m_vecVariance = vec; 115 | } 116 | 117 | ITKVectorType GetPSF() { 118 | return this->m_vecVariance; 119 | } 120 | 121 | void SetIterations( unsigned int nIters ) { 122 | this->m_nIterations = nIters; 123 | } 124 | 125 | void SetVerbose( bool bVerbose ) { 126 | this->m_bVerbose = bVerbose; 127 | } 128 | 129 | 130 | protected: 131 | IntraRegRLImageFilter(); 132 | ~IntraRegRLImageFilter() {}; 133 | 134 | /** Does the real work. */ 135 | virtual void GenerateData() ITK_OVERRIDE; 136 | 137 | ITKVectorType m_vecVariance; 138 | unsigned int m_nIterations; 139 | bool m_bVerbose; 140 | 141 | private: 142 | IntraRegRLImageFilter(const Self &); //purposely not implemented 143 | void operator=(const Self &); //purposely not implemented 144 | 145 | 146 | 147 | }; 148 | } //namespace petpvc 149 | 150 | 151 | #ifndef ITK_MANUAL_INSTANTIATION 152 | #include "petpvcIntraRegRLImageFilter.txx" 153 | #endif 154 | 155 | 156 | #endif // __PETPVCINTRAREGRLIMAGEFILTER_H 157 | -------------------------------------------------------------------------------- /lib/petpvcIntraRegVCImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcIntraRegVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015-2019 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCINTRAREGVCIMAGEFILTER_H 24 | #define __PETPVCINTRAREGVCIMAGEFILTER_H 25 | 26 | #include "itkImage.h" 27 | #include "itkImageToImageFilter.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "petpvcRegionConvolutionImageFilter.h" 35 | #include 36 | 37 | #include 38 | 39 | using namespace itk; 40 | 41 | namespace petpvc 42 | { 43 | template< class TInputImage, typename TMaskImage> 44 | class IntraRegVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 45 | { 46 | public: 47 | /** Standard class typedefs. */ 48 | typedef IntraRegVCImageFilter Self; 49 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 50 | typedef SmartPointer< Self > Pointer; 51 | 52 | /** Method for creation through the object factory. */ 53 | itkNewMacro(Self); 54 | 55 | /** Run-time type information (and related methods). */ 56 | #if ITK_VERSION_MAJOR < 6 57 | itkTypeMacro(IntraRegVCImageFilter, ImageToImageFilter); 58 | #else 59 | itkOverrideGetNameOfClassMacro(IntraRegVCImageFilter); 60 | #endif 61 | 62 | /** Image related typedefs. */ 63 | typedef TInputImage InputImageType; 64 | typedef typename TInputImage::ConstPointer InputImagePointer; 65 | typedef typename TInputImage::RegionType RegionType; 66 | typedef typename TInputImage::SizeType SizeType; 67 | typedef typename TInputImage::IndexType IndexType; 68 | typedef typename TInputImage::PixelType PixelType; 69 | 70 | /** Mask image related typedefs. */ 71 | typedef TMaskImage MaskImageType; 72 | typedef typename TMaskImage::ConstPointer MaskImagePointer; 73 | typedef typename TMaskImage::RegionType MaskRegionType; 74 | typedef typename TMaskImage::SizeType MaskSizeType; 75 | typedef typename TMaskImage::IndexType MaskIndexType; 76 | typedef typename TMaskImage::PixelType MaskPixelType; 77 | 78 | typedef itk::ImageRegionConstIterator ConstImageIterator; 79 | 80 | //Extracts a 3D volume from 4D file. 81 | typedef itk::ExtractImageFilter ExtractFilterType; 82 | typedef itk::MultiplyImageFilter MultiplyFilterType; 83 | typedef itk::DivideImageFilter DivideFilterType; 84 | typedef itk::AddImageFilter AddFilterType; 85 | typedef itk::SubtractImageFilter SubFilterType; 86 | typedef petpvc::RegionConvolutionPVCImageFilter IntraRegBlurFilterType; 87 | typedef itk::ThresholdImageFilter ThresholdFilterType; 88 | typedef itk::ImageDuplicator DuplicatorType; 89 | 90 | typedef itk::Vector ITKVectorType; 91 | 92 | /** Image related typedefs. */ 93 | itkStaticConstMacro(InputImageDimension, unsigned int, 94 | 3); 95 | 96 | itkStaticConstMacro(MaskImageDimension, unsigned int, 97 | 4); 98 | 99 | typedef vnl_vector VectorType; 100 | typedef vnl_matrix MatrixType; 101 | 102 | /** Set the mask image */ 103 | void SetMaskInput(const TMaskImage *input) { 104 | // Process object is not const-correct so the const casting is required. 105 | this->SetNthInput( 1, const_cast< TMaskImage * >( input ) ); 106 | } 107 | 108 | /** Get the label image */ 109 | const MaskImageType * GetMaskInput() const { 110 | return itkDynamicCastInDebugMode< MaskImageType * >( const_cast< DataObject * >( this->ProcessObject::GetInput(0) ) ); 111 | } 112 | 113 | void SetPSF(ITKVectorType vec) { 114 | this->m_vecVariance = vec; 115 | } 116 | 117 | ITKVectorType GetPSF() { 118 | return this->m_vecVariance; 119 | } 120 | 121 | void SetIterations( unsigned int nIters ) { 122 | this->m_nIterations = nIters; 123 | } 124 | 125 | void SetAlpha( float alpha ) { 126 | this->m_fAlpha = alpha; 127 | } 128 | 129 | void SetStoppingCond( float stop ) { 130 | this->m_fStopCriterion = stop; 131 | } 132 | 133 | void SetVerbose( bool bVerbose ) { 134 | this->m_bVerbose = bVerbose; 135 | } 136 | 137 | void SetDisableNonNegativity( bool bDisableNonNeg ) { 138 | this->m_bDisableNonNeg = bDisableNonNeg; 139 | } 140 | 141 | protected: 142 | IntraRegVCImageFilter(); 143 | ~IntraRegVCImageFilter() {}; 144 | 145 | /** Does the real work. */ 146 | virtual void GenerateData() ITK_OVERRIDE; 147 | 148 | ITKVectorType m_vecVariance; 149 | unsigned int m_nIterations; 150 | float m_fAlpha; 151 | float m_fStopCriterion; 152 | bool m_bVerbose; 153 | bool m_bDisableNonNeg; 154 | 155 | private: 156 | IntraRegVCImageFilter(const Self &); //purposely not implemented 157 | void operator=(const Self &); //purposely not implemented 158 | 159 | 160 | 161 | }; 162 | } //namespace petpvc 163 | 164 | 165 | #ifndef ITK_MANUAL_INSTANTIATION 166 | #include "petpvcIntraRegVCImageFilter.txx" 167 | #endif 168 | 169 | 170 | #endif // __PETPVCINTRAREGVCIMAGEFILTER_H 171 | -------------------------------------------------------------------------------- /lib/petpvcIterativeYangPVCImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcIterativeYangPVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2013 Institute of Nuclear Medicine, University College London. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | */ 21 | 22 | #ifndef __PETPVCITERATIVEYANGIMAGEFILTER_H 23 | #define __PETPVCITERATIVEYANGIMAGEFILTER_H 24 | 25 | #include "itkImage.h" 26 | #include "itkImageToImageFilter.h" 27 | #include "petpvcFuzzyCorrectionFilter.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | 39 | using namespace itk; 40 | 41 | namespace petpvc 42 | { 43 | template< class TInputImage, typename TMaskImage> 44 | class IterativeYangPVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 45 | { 46 | public: 47 | /** Standard class typedefs. */ 48 | typedef IterativeYangPVCImageFilter Self; 49 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 50 | typedef SmartPointer< Self > Pointer; 51 | 52 | /** Method for creation through the object factory. */ 53 | itkNewMacro(Self); 54 | 55 | /** Run-time type information (and related methods). */ 56 | #if ITK_VERSION_MAJOR < 6 57 | itkTypeMacro(IterativeYangPVCImageFilter, ImageToImageFilter); 58 | #else 59 | itkOverrideGetNameOfClassMacro(IterativeYangPVCImageFilter); 60 | #endif 61 | 62 | /** Image related typedefs. */ 63 | typedef TInputImage InputImageType; 64 | typedef typename TInputImage::ConstPointer InputImagePointer; 65 | typedef typename TInputImage::RegionType RegionType; 66 | typedef typename TInputImage::SizeType SizeType; 67 | typedef typename TInputImage::IndexType IndexType; 68 | typedef typename TInputImage::PixelType PixelType; 69 | 70 | /** Mask image related typedefs. */ 71 | typedef TMaskImage MaskImageType; 72 | typedef typename TMaskImage::ConstPointer MaskImagePointer; 73 | typedef typename TMaskImage::RegionType MaskRegionType; 74 | typedef typename TMaskImage::SizeType MaskSizeType; 75 | typedef typename TMaskImage::IndexType MaskIndexType; 76 | typedef typename TMaskImage::PixelType MaskPixelType; 77 | 78 | //For calculating mean values from image 79 | typedef itk::StatisticsImageFilter StatisticsFilterType; 80 | //Extracts a 3D volume from 4D file. 81 | typedef itk::ExtractImageFilter ExtractFilterType; 82 | typedef itk::MultiplyImageFilter MultiplyFilterType; 83 | typedef itk::DivideImageFilter DivideFilterType; 84 | typedef itk::AddImageFilter AddFilterType; 85 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 86 | typedef itk::ImageDuplicator DuplicatorType; 87 | 88 | typedef FuzzyCorrectionFilter FuzzyCorrFilterType; 89 | typedef itk::Vector ITKVectorType; 90 | 91 | /** Image related typedefs. */ 92 | itkStaticConstMacro(InputImageDimension, unsigned int, 93 | 3); 94 | 95 | itkStaticConstMacro(MaskImageDimension, unsigned int, 96 | 4); 97 | 98 | typedef vnl_vector VectorType; 99 | typedef vnl_matrix MatrixType; 100 | 101 | /** Set the mask image */ 102 | void SetMaskInput(const TMaskImage *input) { 103 | // Process object is not const-correct so the const casting is required. 104 | this->SetNthInput( 1, const_cast< TMaskImage * >( input ) ); 105 | } 106 | 107 | /** Get the label image */ 108 | const MaskImageType * GetMaskInput() const { 109 | return itkDynamicCastInDebugMode< MaskImageType * >( const_cast< DataObject * >( this->ProcessObject::GetInput(0) ) ); 110 | } 111 | 112 | VectorType GetCorrectedMeans() const { 113 | return this->m_vecRegMeansPVCorr; 114 | } 115 | 116 | MatrixType GetMatrix() const { 117 | return this->m_matGTM; 118 | } 119 | 120 | void SetPSF(ITKVectorType vec) { 121 | this->m_vecVariance = vec; 122 | } 123 | 124 | 125 | ITKVectorType GetPSF() { 126 | return this->m_vecVariance; 127 | } 128 | 129 | void SetIterations( unsigned int nIters ) { 130 | this->m_nIterations = nIters; 131 | } 132 | 133 | void SetVerbose( bool bVerbose ) { 134 | this->m_bVerbose = bVerbose; 135 | } 136 | 137 | 138 | protected: 139 | IterativeYangPVCImageFilter(); 140 | ~IterativeYangPVCImageFilter() {}; 141 | 142 | /** Does the real work. */ 143 | virtual void GenerateData() ITK_OVERRIDE; 144 | 145 | VectorType m_vecRegMeansPVCorr; 146 | MatrixType m_matGTM; 147 | ITKVectorType m_vecVariance; 148 | unsigned int m_nIterations; 149 | bool m_bVerbose; 150 | 151 | private: 152 | IterativeYangPVCImageFilter(const Self &); //purposely not implemented 153 | void operator=(const Self &); //purposely not implemented 154 | 155 | 156 | 157 | }; 158 | } //namespace petpvc 159 | 160 | 161 | #ifndef ITK_MANUAL_INSTANTIATION 162 | #include "petpvcIterativeYangPVCImageFilter.txx" 163 | #endif 164 | 165 | 166 | #endif // __PETPVCITERATIVEYANGIMAGEFILTER_H 167 | -------------------------------------------------------------------------------- /lib/petpvcLabbeImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcLabbeImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCLABBEIMAGEFILTER_H 24 | #define __PETPVCLABBEIMAGEFILTER_H 25 | 26 | #include "itkImageToImageFilter.h" 27 | #include "vnl/vnl_matrix.h" 28 | #include 29 | #include 30 | #include 31 | 32 | //A class to perform Labbe PVC. 33 | 34 | using namespace itk; 35 | 36 | 37 | namespace petpvc 38 | { 39 | 40 | template 41 | class LabbeImageFilter : public ImageToImageFilter 42 | { 43 | public: 44 | 45 | typedef LabbeImageFilter Self; 46 | typedef ImageToImageFilter Superclass; 47 | typedef SmartPointer Pointer; 48 | 49 | //Matrix to hold correction factors 50 | typedef vnl_matrix MatrixType; 51 | 52 | //Vector containing size of region. 53 | typedef vnl_vector VectorType; 54 | typedef itk::Vector ITKVectorType; 55 | 56 | itkNewMacro(Self); 57 | 58 | #if ITK_VERSION_MAJOR < 6 59 | itkTypeMacro(LabbeImageFilter, ImageToImageFilter); 60 | #else 61 | itkOverrideGetNameOfClassMacro(LabbeImageFilter); 62 | #endif 63 | 64 | //Returns correction factors. 65 | vnl_matrix GetMatrix() { 66 | return *this->matCorrFactors; 67 | }; 68 | 69 | //Returns region size. 70 | 71 | vnl_vector GetSumOfRegions() { 72 | return *this->vecSumOfRegions; 73 | }; 74 | 75 | void SetPSF(ITKVectorType vec) { 76 | this->vecVariance = vec; 77 | }; 78 | 79 | ITKVectorType GetPSF() { 80 | return this->vecVariance; 81 | }; 82 | 83 | 84 | protected: 85 | LabbeImageFilter(); 86 | ~LabbeImageFilter(); 87 | 88 | /** Does the real work. */ 89 | virtual void GenerateData() ITK_OVERRIDE; 90 | 91 | private: 92 | LabbeImageFilter(const Self &); //purposely not implemented 93 | void operator=(const Self &); //purposely not implemented 94 | 95 | MatrixType *matCorrFactors; 96 | VectorType *vecSumOfRegions; 97 | ITKVectorType vecVariance; 98 | }; 99 | } //namespace PETPVC 100 | 101 | #ifndef ITK_MANUAL_INSTANTIATION 102 | #include "petpvcLabbeImageFilter.txx" 103 | #endif 104 | 105 | #endif // __PETPVCLabbeIMAGEFILTER_H 106 | -------------------------------------------------------------------------------- /lib/petpvcLabbeImageFilter.txx: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcLabbeImageFilter.txx 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCLABBEIMAGEFILTER_TXX 24 | #define __PETPVCLABBEIMAGEFILTER_TXX 25 | 26 | #include "petpvcLabbeImageFilter.h" 27 | #include "itkObjectFactory.h" 28 | #include "itkImageRegionIterator.h" 29 | #include "itkImageRegionConstIterator.h" 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "vnl/vnl_matrix.h" 36 | 37 | using namespace itk; 38 | 39 | namespace petpvc 40 | { 41 | 42 | template 43 | LabbeImageFilter::LabbeImageFilter() 44 | { 45 | //Constructor. Just initialises the matrix and vector that will 46 | //contain the results of the correction that the filter implements. 47 | this->matCorrFactors = new MatrixType; 48 | this->vecSumOfRegions = new VectorType; 49 | 50 | //this->vecVariance = new ITKVectorType; 51 | 52 | } 53 | 54 | template 55 | void LabbeImageFilter::GenerateData() 56 | { 57 | 58 | this->SetGlobalDefaultCoordinateTolerance( 1e-2 ); 59 | this->SetGlobalDefaultDirectionTolerance( 1e-2 ); 60 | 61 | //Get pointers to input and output. 62 | typename TImage::ConstPointer input = this->GetInput(); 63 | 64 | //Get region size. 65 | typename TImage::SizeType imageSize = 66 | input->GetLargestPossibleRegion().GetSize(); 67 | 68 | int nClasses = 0; 69 | 70 | //Set size of output matrix and vector. 71 | //TODO: Should throw an exception here if imageSize.Dimension != 4. 72 | if (imageSize.Dimension == 4) { 73 | nClasses = imageSize[3]; 74 | matCorrFactors->set_size(nClasses, nClasses); 75 | matCorrFactors->fill(0); 76 | 77 | vecSumOfRegions->set_size(nClasses); 78 | vecSumOfRegions->fill(0); 79 | 80 | } 81 | 82 | typedef itk::Image MaskImageType; 83 | 84 | typedef itk::StatisticsImageFilter StatisticsFilterType; 85 | typedef itk::ExtractImageFilter ExtractFilterType; 86 | typedef itk::MultiplyImageFilter MultiplyFilterType; 87 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 88 | 89 | typedef itk::ImageDuplicator DuplicatorType; 90 | 91 | typename TImage::IndexType desiredStart; 92 | desiredStart.Fill(0); 93 | 94 | typename TImage::SizeType desiredSize = 95 | input->GetLargestPossibleRegion().GetSize(); 96 | 97 | typename TImage::RegionType desiredRegion; 98 | 99 | StatisticsFilterType::Pointer statsFilter = StatisticsFilterType::New(); 100 | 101 | typename ExtractFilterType::Pointer extractTargetFilter = 102 | ExtractFilterType::New(); 103 | typename ExtractFilterType::Pointer extractNeighbourFilter = 104 | ExtractFilterType::New(); 105 | typename MultiplyFilterType::Pointer multiplyFilter = 106 | MultiplyFilterType::New(); 107 | typename BlurringFilterType::Pointer blurringFilter = 108 | BlurringFilterType::New(); 109 | 110 | blurringFilter->SetVariance((this->GetPSF())); 111 | 112 | typename BlurringFilterType::Pointer blurringFilter2 = 113 | BlurringFilterType::New(); 114 | 115 | blurringFilter2->SetVariance((this->GetPSF())); 116 | 117 | float fSumTarget; 118 | float fSumNeighbour; 119 | 120 | for (int i = 1; i <= nClasses; i++) { 121 | 122 | fSumTarget = 0.0; 123 | desiredStart[3] = i - 1; 124 | desiredSize[3] = 0; 125 | 126 | //Extract 3D brain mask volume i from 4D image. 127 | extractTargetFilter->SetExtractionRegion( 128 | typename TImage::RegionType(desiredStart, desiredSize)); 129 | extractTargetFilter->SetInput(input); 130 | extractTargetFilter->SetDirectionCollapseToIdentity(); // This is required. 131 | extractTargetFilter->Update(); 132 | 133 | blurringFilter->SetInput(extractTargetFilter->GetOutput()); 134 | 135 | statsFilter->SetInput(blurringFilter->GetOutput()); 136 | statsFilter->Update(); 137 | 138 | //Calculate the sum of non-zero voxels. 139 | fSumTarget = statsFilter->GetSum(); 140 | 141 | vecSumOfRegions->put(i - 1, fSumTarget); 142 | 143 | for (int j = 1; j <= nClasses; j++) { 144 | fSumNeighbour = 0.0; 145 | desiredStart[3] = j - 1; 146 | desiredSize[3] = 0; 147 | 148 | //Extract 3D brain mask volume j from 4D image. 149 | extractNeighbourFilter->SetExtractionRegion( 150 | typename TImage::RegionType(desiredStart, desiredSize)); 151 | extractNeighbourFilter->SetInput(input); 152 | extractNeighbourFilter->SetDirectionCollapseToIdentity(); // This is required. 153 | extractNeighbourFilter->Update(); 154 | 155 | blurringFilter2->SetInput(extractNeighbourFilter->GetOutput()); 156 | 157 | //Multiply i by j. 158 | multiplyFilter->SetInput1(blurringFilter->GetOutput()); 159 | multiplyFilter->SetInput2(blurringFilter2->GetOutput()); 160 | 161 | statsFilter->SetInput(multiplyFilter->GetOutput()); 162 | statsFilter->Update(); 163 | 164 | //Calculate the sum of the remaining voxels. 165 | fSumNeighbour = statsFilter->GetSum(); 166 | 167 | //Fill location in matrix with sum of remaining voxels 168 | //normalised by size of i. 169 | matCorrFactors->put(i - 1, j - 1, fSumNeighbour / fSumTarget); 170 | 171 | //std::cout << "Target: " << fSumTarget << " Neighbour: " << fSumNeighbour << std::endl; 172 | } 173 | 174 | } 175 | } 176 | 177 | template 178 | LabbeImageFilter::~LabbeImageFilter() 179 | { 180 | //Destructor. 181 | delete this->matCorrFactors; 182 | delete this->vecSumOfRegions; 183 | 184 | } 185 | 186 | } // end namespace 187 | 188 | #endif 189 | -------------------------------------------------------------------------------- /lib/petpvcLabbeMTCPVCImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcLabbeMTCPVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCLABBEMTCPVCImageFilter_H 24 | #define __PETPVCLABBEMTCPVCImageFilter_H 25 | 26 | #include "itkImage.h" 27 | #include "itkImageToImageFilter.h" 28 | #include "petpvcLabbeImageFilter.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | using namespace itk; 39 | 40 | namespace petpvc 41 | { 42 | template< class TInputImage, typename TMaskImage> 43 | class LabbeMTCPVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 44 | { 45 | public: 46 | /** Standard class typedefs. */ 47 | typedef LabbeMTCPVCImageFilter Self; 48 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 49 | typedef SmartPointer< Self > Pointer; 50 | 51 | /** Method for creation through the object factory. */ 52 | itkNewMacro(Self); 53 | 54 | /** Run-time type information (and related methods). */ 55 | #if ITK_VERSION_MAJOR < 6 56 | itkTypeMacro(LabbeMTCPVCImageFilter, ImageToImageFilter); 57 | #else 58 | itkOverrideGetNameOfClassMacro(LabbeMTCPVCImageFilter); 59 | #endif 60 | 61 | /** Image related typedefs. */ 62 | typedef TInputImage InputImageType; 63 | typedef typename TInputImage::ConstPointer InputImagePointer; 64 | typedef typename TInputImage::RegionType RegionType; 65 | typedef typename TInputImage::SizeType SizeType; 66 | typedef typename TInputImage::IndexType IndexType; 67 | typedef typename TInputImage::PixelType PixelType; 68 | 69 | /** Mask image related typedefs. */ 70 | typedef TMaskImage MaskImageType; 71 | typedef typename TMaskImage::ConstPointer MaskImagePointer; 72 | typedef typename TMaskImage::RegionType MaskRegionType; 73 | typedef typename TMaskImage::SizeType MaskSizeType; 74 | typedef typename TMaskImage::IndexType MaskIndexType; 75 | typedef typename TMaskImage::PixelType MaskPixelType; 76 | 77 | //For calculating mean values from image 78 | typedef itk::StatisticsImageFilter StatisticsFilterType; 79 | //Extracts a 3D volume from 4D file. 80 | typedef itk::ExtractImageFilter ExtractFilterType; 81 | typedef itk::MultiplyImageFilter MultiplyFilterType; 82 | typedef itk::DivideImageFilter DivideFilterType; 83 | typedef itk::AddImageFilter AddFilterType; 84 | typedef itk::SubtractImageFilter SubtractFilterType; 85 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 86 | 87 | typedef LabbeImageFilter LabbeImageFilterType; 88 | typedef itk::Vector ITKVectorType; 89 | 90 | /** Image related typedefs. */ 91 | itkStaticConstMacro(InputImageDimension, unsigned int, 92 | 3); 93 | 94 | itkStaticConstMacro(MaskImageDimension, unsigned int, 95 | 4); 96 | 97 | typedef vnl_vector VectorType; 98 | typedef vnl_matrix MatrixType; 99 | 100 | /** Set the mask image */ 101 | void SetMaskInput(const TMaskImage *input) { 102 | // Process object is not const-correct so the const casting is required. 103 | this->SetNthInput( 1, const_cast< TMaskImage * >( input ) ); 104 | } 105 | 106 | /** Get the label image */ 107 | const MaskImageType * GetMaskInput() const { 108 | return itkDynamicCastInDebugMode< MaskImageType * >( const_cast< DataObject * >( this->ProcessObject::GetInput(0) ) ); 109 | } 110 | 111 | VectorType GetCorrectedMeans() const { 112 | return this->m_vecRegMeansPVCorr; 113 | } 114 | 115 | MatrixType GetMatrix() const { 116 | return this->m_matGTM; 117 | } 118 | 119 | void SetPSF(ITKVectorType vec) { 120 | this->m_vecVariance = vec; 121 | } 122 | 123 | 124 | ITKVectorType GetPSF() { 125 | return this->m_vecVariance; 126 | } 127 | 128 | void SetVerbose( bool bVerbose ) { 129 | this->m_bVerbose = bVerbose; 130 | } 131 | 132 | void ApplyYang(); 133 | 134 | 135 | protected: 136 | LabbeMTCPVCImageFilter(); 137 | ~LabbeMTCPVCImageFilter() {} 138 | 139 | /** Does the real work. */ 140 | virtual void GenerateData() ITK_OVERRIDE; 141 | 142 | VectorType m_vecRegMeansPVCorr; 143 | MatrixType m_matGTM; 144 | ITKVectorType m_vecVariance; 145 | bool m_bVerbose; 146 | 147 | private: 148 | LabbeMTCPVCImageFilter(const Self &); //purposely not implemented 149 | void operator=(const Self &); //purposely not implemented 150 | 151 | 152 | 153 | }; 154 | } //namespace petpvc 155 | 156 | 157 | #ifndef ITK_MANUAL_INSTANTIATION 158 | #include "petpvcLabbeMTCPVCImageFilter.txx" 159 | #endif 160 | 161 | 162 | #endif // __PETPVCLABBEMTCIMAGEFILTER_H 163 | -------------------------------------------------------------------------------- /lib/petpvcLabbePVCImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcLabbePVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCLABBEPVCIMAGEFILTER_H 24 | #define __PETPVCLABBEPVCIMAGEFILTER_H 25 | 26 | #include "itkImage.h" 27 | #include "itkImageToImageFilter.h" 28 | #include "petpvcLabbeImageFilter.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | 36 | using namespace itk; 37 | 38 | namespace petpvc 39 | { 40 | template< class TInputImage, typename TMaskImage> 41 | class LabbePVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 42 | { 43 | public: 44 | /** Standard class typedefs. */ 45 | typedef LabbePVCImageFilter Self; 46 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 47 | typedef SmartPointer< Self > Pointer; 48 | 49 | /** Method for creation through the object factory. */ 50 | itkNewMacro(Self); 51 | 52 | /** Run-time type information (and related methods). */ 53 | #if ITK_VERSION_MAJOR < 6 54 | itkTypeMacro(LabbePVCImageFilter, ImageToImageFilter); 55 | #else 56 | itkOverrideGetNameOfClassMacro(LabbePVCImageFilter); 57 | #endif 58 | 59 | /** Image related typedefs. */ 60 | typedef TInputImage InputImageType; 61 | typedef typename TInputImage::ConstPointer InputImagePointer; 62 | typedef typename TInputImage::RegionType RegionType; 63 | typedef typename TInputImage::SizeType SizeType; 64 | typedef typename TInputImage::IndexType IndexType; 65 | typedef typename TInputImage::PixelType PixelType; 66 | 67 | /** Mask image related typedefs. */ 68 | typedef TMaskImage MaskImageType; 69 | typedef typename TMaskImage::ConstPointer MaskImagePointer; 70 | typedef typename TMaskImage::RegionType MaskRegionType; 71 | typedef typename TMaskImage::SizeType MaskSizeType; 72 | typedef typename TMaskImage::IndexType MaskIndexType; 73 | typedef typename TMaskImage::PixelType MaskPixelType; 74 | 75 | //For calculating mean values from image 76 | typedef itk::StatisticsImageFilter StatisticsFilterType; 77 | //Extracts a 3D volume from 4D file. 78 | typedef itk::ExtractImageFilter ExtractFilterType; 79 | typedef itk::MultiplyImageFilter MultiplyFilterType; 80 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 81 | 82 | typedef LabbeImageFilter LabbeImageFilterType; 83 | typedef itk::Vector ITKVectorType; 84 | 85 | /** Image related typedefs. */ 86 | itkStaticConstMacro(InputImageDimension, unsigned int, 87 | 3); 88 | 89 | itkStaticConstMacro(MaskImageDimension, unsigned int, 90 | 4); 91 | 92 | typedef vnl_vector VectorType; 93 | typedef vnl_matrix MatrixType; 94 | 95 | /** Set the mask image */ 96 | void SetMaskInput(const TMaskImage *input) { 97 | // Process object is not const-correct so the const casting is required. 98 | this->SetNthInput( 1, const_cast< TMaskImage * >( input ) ); 99 | } 100 | 101 | /** Get the label image */ 102 | const MaskImageType * GetMaskInput() const { 103 | return itkDynamicCastInDebugMode< MaskImageType * >( const_cast< DataObject * >( this->ProcessObject::GetInput(0) ) ); 104 | } 105 | 106 | VectorType GetCorrectedMeans() const { 107 | return this->m_vecRegMeansPVCorr; 108 | } 109 | 110 | MatrixType GetMatrix() const { 111 | return this->m_matLabbe; 112 | } 113 | 114 | void SetPSF(ITKVectorType vec) { 115 | this->m_vecVariance = vec; 116 | }; 117 | 118 | 119 | ITKVectorType GetPSF() { 120 | return this->m_vecVariance; 121 | }; 122 | 123 | void SetVerbose( bool bVerbose ) { 124 | this->m_bVerbose = bVerbose; 125 | } 126 | 127 | protected: 128 | LabbePVCImageFilter(); 129 | ~LabbePVCImageFilter() {} 130 | 131 | /** Does the real work. */ 132 | virtual void GenerateData() ITK_OVERRIDE; 133 | 134 | VectorType m_vecRegMeansPVCorr; 135 | MatrixType m_matLabbe; 136 | ITKVectorType m_vecVariance; 137 | bool m_bVerbose; 138 | 139 | private: 140 | LabbePVCImageFilter(const Self &); //purposely not implemented 141 | void operator=(const Self &); //purposely not implemented 142 | 143 | 144 | 145 | }; 146 | } //namespace petpvc 147 | 148 | 149 | #ifndef ITK_MANUAL_INSTANTIATION 150 | #include "petpvcLabbePVCImageFilter.txx" 151 | #endif 152 | 153 | 154 | #endif // __PETPVCROUSSETIMAGEFILTER_H 155 | -------------------------------------------------------------------------------- /lib/petpvcLabbePVCImageFilter.txx: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcLabbePVCImageFilter.txx 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCLABBEPVCIMAGEFILTER_TXX 24 | #define __PETPVCLABBEPVCIMAGEFILTER_TXX 25 | 26 | #include "petpvcLabbePVCImageFilter.h" 27 | #include "itkObjectFactory.h" 28 | #include "itkImageRegionIterator.h" 29 | #include "itkImageRegionConstIterator.h" 30 | 31 | using namespace itk; 32 | 33 | namespace petpvc 34 | { 35 | 36 | template< class TInputImage, class TMaskImage > 37 | LabbePVCImageFilter< TInputImage, TMaskImage> 38 | ::LabbePVCImageFilter() 39 | { 40 | this->m_bVerbose = false; 41 | } 42 | 43 | template< class TInputImage, class TMaskImage > 44 | void LabbePVCImageFilter< TInputImage, TMaskImage> 45 | ::GenerateData() 46 | { 47 | 48 | this->SetGlobalDefaultCoordinateTolerance( 1e-2 ); 49 | this->SetGlobalDefaultDirectionTolerance( 1e-2 ); 50 | 51 | typename TInputImage::ConstPointer input = this->GetInput(); 52 | typename TInputImage::Pointer output = this->GetOutput(); 53 | 54 | typename LabbeImageFilterType::Pointer pLabbe = LabbeImageFilterType::New(); 55 | 56 | InputImagePointer pPET = dynamic_cast (ProcessObject::GetInput(0)); 57 | MaskImagePointer pMask = dynamic_cast (ProcessObject::GetInput(1)); 58 | 59 | pLabbe->SetInput( pMask ); 60 | pLabbe->SetPSF( this->GetPSF() ); 61 | //Calculate Labbe. 62 | try { 63 | pLabbe->Update(); 64 | } catch (itk::ExceptionObject & err) { 65 | std::cerr << "[Error]\tCannot calculate Labbe" 66 | << std::endl; 67 | } 68 | 69 | if ( this->m_bVerbose ) { 70 | std::cout << pLabbe->GetMatrix() << std::endl; 71 | } 72 | 73 | ///////////////////////////////////////////// 74 | 75 | //Get mask image size. 76 | typename MaskImageType::SizeType imageSize = 77 | pMask->GetLargestPossibleRegion().GetSize(); 78 | 79 | int nClasses = 0; 80 | 81 | //If mask is not 4D, then quit. 82 | if (imageSize.Dimension == 4) { 83 | nClasses = imageSize[3]; 84 | } else { 85 | std::cerr << "[Error]\tMask file must be 4-D!" 86 | << std::endl; 87 | } 88 | 89 | MaskSizeType desiredStart; 90 | desiredStart.Fill(0); 91 | MaskSizeType desiredSize = imageSize; 92 | 93 | //Extract filter used to extract 3D volume from 4D file. 94 | typename ExtractFilterType::Pointer extractFilter = ExtractFilterType::New(); 95 | extractFilter->SetInput( pMask ); 96 | extractFilter->SetDirectionCollapseToIdentity(); // This is required. 97 | 98 | //Stats. filter used to calculate statistics for an image. 99 | typename StatisticsFilterType::Pointer statsFilter = StatisticsFilterType::New(); 100 | 101 | //Multiplies two images together. 102 | typename MultiplyFilterType::Pointer multiplyFilter = MultiplyFilterType::New(); 103 | 104 | //Smooth the pseudo PET by the PSF. 105 | typename BlurringFilterType::Pointer blurFilter = BlurringFilterType::New(); 106 | 107 | blurFilter->SetVariance( this->GetPSF() ); 108 | 109 | typename TInputImage::Pointer imageExtractedRegion;// = InputImagePointer::New(); 110 | 111 | float fSumOfPETReg; 112 | 113 | //Vector to contain the current estimate of the regional mean values. 114 | vnl_vector vecRegMeansCurrent; 115 | vecRegMeansCurrent.set_size(nClasses); 116 | 117 | //Vector to contain the estimated means after Labbe correction. 118 | vnl_vector vecRegMeansUpdated; 119 | vecRegMeansUpdated.set_size(nClasses); 120 | 121 | for (int i = 1; i <= nClasses; i++) { 122 | 123 | //Starts reading from 4D volume at index (0,0,0,i) through to 124 | //(maxX, maxY, maxZ,0), i.e. one 3D brain mask. 125 | desiredStart[3] = i - 1; 126 | desiredSize[3] = 0; 127 | 128 | //Get region mask. 129 | MaskRegionType maskReg; 130 | maskReg.SetSize(desiredSize ); 131 | maskReg.SetIndex(0,desiredStart[0] ); 132 | maskReg.SetIndex(1,desiredStart[1] ); 133 | maskReg.SetIndex(2,desiredStart[2] ); 134 | maskReg.SetIndex(3,desiredStart[3] ); 135 | 136 | extractFilter->SetExtractionRegion( maskReg ); 137 | extractFilter->Update(); 138 | 139 | imageExtractedRegion = extractFilter->GetOutput(); 140 | imageExtractedRegion->SetDirection( pPET->GetDirection() ); 141 | imageExtractedRegion->UpdateOutputData(); 142 | 143 | blurFilter->SetInput( imageExtractedRegion ); 144 | 145 | //Multiply current image estimate by smoothed region mask. To clip PET values 146 | //to mask. 147 | multiplyFilter->SetInput1( pPET ); 148 | multiplyFilter->SetInput2( blurFilter->GetOutput() ); 149 | 150 | statsFilter->SetInput(multiplyFilter->GetOutput()); 151 | statsFilter->Update(); 152 | 153 | //Get sum of the clipped image. 154 | fSumOfPETReg = statsFilter->GetSum(); 155 | 156 | //Place regional mean into vector. 157 | vecRegMeansCurrent.put(i - 1, fSumOfPETReg / pLabbe->GetSumOfRegions().get(i - 1)); 158 | //std::cout << "Sum = " << fSumOfPETReg << " , Mean = " << vecRegMeansCurrent.get(i-1) << " Total vox. = " << gtmFilter->GetSumOfRegions().get( i-1 ) << std::endl; 159 | 160 | } 161 | 162 | //Apply Labbe to regional mean values. 163 | vecRegMeansUpdated = vnl_matrix_inverse(pLabbe->GetMatrix()) * vecRegMeansCurrent; 164 | 165 | if ( this->m_bVerbose ) { 166 | std::cout << std::endl << "Regional means:" << std::endl; 167 | std::cout << vecRegMeansCurrent << std::endl << std::endl; 168 | 169 | std::cout << "Labbe:" << std::endl; 170 | pLabbe->GetMatrix().print(std::cout); 171 | 172 | std::cout << std::endl << "Corrected means:" << std::endl; 173 | 174 | } 175 | 176 | std::cout << vecRegMeansUpdated << std::endl; 177 | this->m_vecRegMeansPVCorr = vecRegMeansUpdated; 178 | 179 | this->AllocateOutputs(); 180 | 181 | ImageAlgorithm::Copy(input.GetPointer(), output.GetPointer(), output->GetRequestedRegion(), 182 | output->GetRequestedRegion() ); 183 | 184 | 185 | } 186 | 187 | }// end namespace 188 | 189 | 190 | #endif 191 | -------------------------------------------------------------------------------- /lib/petpvcLabbeRBVPVCImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcLabbeRBVPVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCLABBERBVIMAGEFILTER_H 24 | #define __PETPVCLABBERBVIMAGEFILTER_H 25 | 26 | #include "itkImage.h" 27 | #include "itkImageToImageFilter.h" 28 | #include "petpvcLabbeImageFilter.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | 38 | using namespace itk; 39 | 40 | namespace petpvc 41 | { 42 | template< class TInputImage, typename TMaskImage> 43 | class LabbeRBVPVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 44 | { 45 | public: 46 | /** Standard class typedefs. */ 47 | typedef LabbeRBVPVCImageFilter Self; 48 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 49 | typedef SmartPointer< Self > Pointer; 50 | 51 | /** Method for creation through the object factory. */ 52 | itkNewMacro(Self); 53 | 54 | /** Run-time type information (and related methods). */ 55 | #if ITK_VERSION_MAJOR < 6 56 | itkTypeMacro(LabbeRBVPVCImageFilter, ImageToImageFilter); 57 | #else 58 | itkOverrideGetNameOfClassMacro(LabbeRBVPVCImageFilter); 59 | #endif 60 | 61 | /** Image related typedefs. */ 62 | typedef TInputImage InputImageType; 63 | typedef typename TInputImage::ConstPointer InputImagePointer; 64 | typedef typename TInputImage::RegionType RegionType; 65 | typedef typename TInputImage::SizeType SizeType; 66 | typedef typename TInputImage::IndexType IndexType; 67 | typedef typename TInputImage::PixelType PixelType; 68 | 69 | /** Mask image related typedefs. */ 70 | typedef TMaskImage MaskImageType; 71 | typedef typename TMaskImage::ConstPointer MaskImagePointer; 72 | typedef typename TMaskImage::RegionType MaskRegionType; 73 | typedef typename TMaskImage::SizeType MaskSizeType; 74 | typedef typename TMaskImage::IndexType MaskIndexType; 75 | typedef typename TMaskImage::PixelType MaskPixelType; 76 | 77 | //For calculating mean values from image 78 | typedef itk::StatisticsImageFilter StatisticsFilterType; 79 | //Extracts a 3D volume from 4D file. 80 | typedef itk::ExtractImageFilter ExtractFilterType; 81 | typedef itk::MultiplyImageFilter MultiplyFilterType; 82 | typedef itk::DivideImageFilter DivideFilterType; 83 | typedef itk::AddImageFilter AddFilterType; 84 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 85 | 86 | typedef LabbeImageFilter LabbeImageFilterType; 87 | typedef itk::Vector ITKVectorType; 88 | 89 | /** Image related typedefs. */ 90 | itkStaticConstMacro(InputImageDimension, unsigned int, 91 | 3); 92 | 93 | itkStaticConstMacro(MaskImageDimension, unsigned int, 94 | 4); 95 | 96 | typedef vnl_vector VectorType; 97 | typedef vnl_matrix MatrixType; 98 | 99 | /** Set the mask image */ 100 | void SetMaskInput(const TMaskImage *input) { 101 | // Process object is not const-correct so the const casting is required. 102 | this->SetNthInput( 1, const_cast< TMaskImage * >( input ) ); 103 | } 104 | 105 | /** Get the label image */ 106 | const MaskImageType * GetMaskInput() const { 107 | return itkDynamicCastInDebugMode< MaskImageType * >( const_cast< DataObject * >( this->ProcessObject::GetInput(0) ) ); 108 | } 109 | 110 | VectorType GetCorrectedMeans() const { 111 | return this->m_vecRegMeansPVCorr; 112 | } 113 | 114 | MatrixType GetMatrix() const { 115 | return this->m_matLabbe; 116 | } 117 | 118 | void SetPSF(ITKVectorType vec) { 119 | this->m_vecVariance = vec; 120 | } 121 | 122 | 123 | ITKVectorType GetPSF() { 124 | return this->m_vecVariance; 125 | } 126 | 127 | void SetVerbose( bool bVerbose ) { 128 | this->m_bVerbose = bVerbose; 129 | } 130 | 131 | void SetUseLabbe() { 132 | this->m_bUseLabbe = true; 133 | } 134 | 135 | 136 | void ApplyYang(); 137 | 138 | 139 | protected: 140 | LabbeRBVPVCImageFilter(); 141 | ~LabbeRBVPVCImageFilter() {} 142 | 143 | /** Does the real work. */ 144 | virtual void GenerateData() ITK_OVERRIDE; 145 | 146 | VectorType m_vecRegMeansPVCorr; 147 | MatrixType m_matLabbe; 148 | ITKVectorType m_vecVariance; 149 | bool m_bVerbose; 150 | 151 | 152 | private: 153 | LabbeRBVPVCImageFilter(const Self &); //purposely not implemented 154 | void operator=(const Self &); //purposely not implemented 155 | 156 | 157 | 158 | }; 159 | } //namespace petpvc 160 | 161 | 162 | #ifndef ITK_MANUAL_INSTANTIATION 163 | #include "petpvcLabbeRBVPVCImageFilter.txx" 164 | #endif 165 | 166 | 167 | #endif // __PETPVCLABBERBVIMAGEFILTER_H 168 | -------------------------------------------------------------------------------- /lib/petpvcMTCPVCImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcMTCPVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCMTCPVCImageFilter_H 24 | #define __PETPVCMTCPVCImageFilter_H 25 | 26 | #include "itkImage.h" 27 | #include "itkImageToImageFilter.h" 28 | #include "petpvcGTMImageFilter.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | using namespace itk; 39 | 40 | namespace petpvc 41 | { 42 | template< class TInputImage, typename TMaskImage> 43 | class MTCPVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 44 | { 45 | public: 46 | /** Standard class typedefs. */ 47 | typedef MTCPVCImageFilter Self; 48 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 49 | typedef SmartPointer< Self > Pointer; 50 | 51 | /** Method for creation through the object factory. */ 52 | itkNewMacro(Self); 53 | 54 | /** Run-time type information (and related methods). */ 55 | #if ITK_VERSION_MAJOR < 6 56 | itkTypeMacro(MTCPVCImageFilter, ImageToImageFilter); 57 | #else 58 | itkOverrideGetNameOfClassMacro(MTCPVCImageFilter); 59 | #endif 60 | 61 | /** Image related typedefs. */ 62 | typedef TInputImage InputImageType; 63 | typedef typename TInputImage::ConstPointer InputImagePointer; 64 | typedef typename TInputImage::RegionType RegionType; 65 | typedef typename TInputImage::SizeType SizeType; 66 | typedef typename TInputImage::IndexType IndexType; 67 | typedef typename TInputImage::PixelType PixelType; 68 | 69 | /** Mask image related typedefs. */ 70 | typedef TMaskImage MaskImageType; 71 | typedef typename TMaskImage::ConstPointer MaskImagePointer; 72 | typedef typename TMaskImage::RegionType MaskRegionType; 73 | typedef typename TMaskImage::SizeType MaskSizeType; 74 | typedef typename TMaskImage::IndexType MaskIndexType; 75 | typedef typename TMaskImage::PixelType MaskPixelType; 76 | 77 | //For calculating mean values from image 78 | typedef itk::StatisticsImageFilter StatisticsFilterType; 79 | //Extracts a 3D volume from 4D file. 80 | typedef itk::ExtractImageFilter ExtractFilterType; 81 | typedef itk::MultiplyImageFilter MultiplyFilterType; 82 | typedef itk::DivideImageFilter DivideFilterType; 83 | typedef itk::AddImageFilter AddFilterType; 84 | typedef itk::SubtractImageFilter SubtractFilterType; 85 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 86 | 87 | typedef GTMImageFilter GTMImageFilterType; 88 | typedef itk::Vector ITKVectorType; 89 | 90 | /** Image related typedefs. */ 91 | itkStaticConstMacro(InputImageDimension, unsigned int, 92 | 3); 93 | 94 | itkStaticConstMacro(MaskImageDimension, unsigned int, 95 | 4); 96 | 97 | typedef vnl_vector VectorType; 98 | typedef vnl_matrix MatrixType; 99 | 100 | /** Set the mask image */ 101 | void SetMaskInput(const TMaskImage *input) { 102 | // Process object is not const-correct so the const casting is required. 103 | this->SetNthInput( 1, const_cast< TMaskImage * >( input ) ); 104 | } 105 | 106 | /** Get the label image */ 107 | const MaskImageType * GetMaskInput() const { 108 | return itkDynamicCastInDebugMode< MaskImageType * >( const_cast< DataObject * >( this->ProcessObject::GetInput(0) ) ); 109 | } 110 | 111 | VectorType GetCorrectedMeans() const { 112 | return this->m_vecRegMeansPVCorr; 113 | } 114 | 115 | MatrixType GetMatrix() const { 116 | return this->m_matGTM; 117 | } 118 | 119 | void SetPSF(ITKVectorType vec) { 120 | this->m_vecVariance = vec; 121 | } 122 | 123 | 124 | ITKVectorType GetPSF() { 125 | return this->m_vecVariance; 126 | } 127 | 128 | void SetVerbose( bool bVerbose ) { 129 | this->m_bVerbose = bVerbose; 130 | } 131 | 132 | void ApplyYang(); 133 | 134 | 135 | protected: 136 | MTCPVCImageFilter(); 137 | ~MTCPVCImageFilter() {} 138 | 139 | /** Does the real work. */ 140 | virtual void GenerateData() ITK_OVERRIDE; 141 | 142 | VectorType m_vecRegMeansPVCorr; 143 | MatrixType m_matGTM; 144 | ITKVectorType m_vecVariance; 145 | bool m_bVerbose; 146 | 147 | private: 148 | MTCPVCImageFilter(const Self &); //purposely not implemented 149 | void operator=(const Self &); //purposely not implemented 150 | 151 | 152 | 153 | }; 154 | } //namespace petpvc 155 | 156 | 157 | #ifndef ITK_MANUAL_INSTANTIATION 158 | #include "petpvcMTCPVCImageFilter.txx" 159 | #endif 160 | 161 | 162 | #endif // __PETPVCMTCIMAGEFILTER_H 163 | -------------------------------------------------------------------------------- /lib/petpvcRBVPVCImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcRBVPVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2013 Institute of Nuclear Medicine, University College London. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | */ 21 | 22 | #ifndef __PETPVCRBVPVCImageFilter_H 23 | #define __PETPVCRBVPVCImageFilter_H 24 | 25 | #include "itkImage.h" 26 | #include "itkImageToImageFilter.h" 27 | #include "petpvcGTMImageFilter.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | 37 | using namespace itk; 38 | 39 | namespace petpvc 40 | { 41 | template< class TInputImage, typename TMaskImage> 42 | class RBVPVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 43 | { 44 | public: 45 | /** Standard class typedefs. */ 46 | typedef RBVPVCImageFilter Self; 47 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 48 | typedef SmartPointer< Self > Pointer; 49 | 50 | /** Method for creation through the object factory. */ 51 | itkNewMacro(Self); 52 | 53 | /** Run-time type information (and related methods). */ 54 | #if ITK_VERSION_MAJOR < 6 55 | itkTypeMacro(RBVPVCImageFilter, ImageToImageFilter); 56 | #else 57 | itkOverrideGetNameOfClassMacro(RBVPVCImageFilter); 58 | #endif 59 | 60 | /** Image related typedefs. */ 61 | typedef TInputImage InputImageType; 62 | typedef typename TInputImage::ConstPointer InputImagePointer; 63 | typedef typename TInputImage::RegionType RegionType; 64 | typedef typename TInputImage::SizeType SizeType; 65 | typedef typename TInputImage::IndexType IndexType; 66 | typedef typename TInputImage::PixelType PixelType; 67 | 68 | /** Mask image related typedefs. */ 69 | typedef TMaskImage MaskImageType; 70 | typedef typename TMaskImage::ConstPointer MaskImagePointer; 71 | typedef typename TMaskImage::RegionType MaskRegionType; 72 | typedef typename TMaskImage::SizeType MaskSizeType; 73 | typedef typename TMaskImage::IndexType MaskIndexType; 74 | typedef typename TMaskImage::PixelType MaskPixelType; 75 | 76 | //For calculating mean values from image 77 | typedef itk::StatisticsImageFilter StatisticsFilterType; 78 | //Extracts a 3D volume from 4D file. 79 | typedef itk::ExtractImageFilter ExtractFilterType; 80 | typedef itk::MultiplyImageFilter MultiplyFilterType; 81 | typedef itk::DivideImageFilter DivideFilterType; 82 | typedef itk::AddImageFilter AddFilterType; 83 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 84 | 85 | typedef GTMImageFilter GTMImageFilterType; 86 | typedef itk::Vector ITKVectorType; 87 | 88 | /** Image related typedefs. */ 89 | itkStaticConstMacro(InputImageDimension, unsigned int, 90 | 3); 91 | 92 | itkStaticConstMacro(MaskImageDimension, unsigned int, 93 | 4); 94 | 95 | typedef vnl_vector VectorType; 96 | typedef vnl_matrix MatrixType; 97 | 98 | /** Set the mask image */ 99 | void SetMaskInput(const TMaskImage *input) { 100 | // Process object is not const-correct so the const casting is required. 101 | this->SetNthInput( 1, const_cast< TMaskImage * >( input ) ); 102 | } 103 | 104 | /** Get the label image */ 105 | const MaskImageType * GetMaskInput() const { 106 | return itkDynamicCastInDebugMode< MaskImageType * >( const_cast< DataObject * >( this->ProcessObject::GetInput(0) ) ); 107 | } 108 | 109 | VectorType GetCorrectedMeans() const { 110 | return this->m_vecRegMeansPVCorr; 111 | } 112 | 113 | MatrixType GetMatrix() const { 114 | return this->m_matGTM; 115 | } 116 | 117 | void SetPSF(ITKVectorType vec) { 118 | this->m_vecVariance = vec; 119 | } 120 | 121 | 122 | ITKVectorType GetPSF() { 123 | return this->m_vecVariance; 124 | } 125 | 126 | void SetVerbose( bool bVerbose ) { 127 | this->m_bVerbose = bVerbose; 128 | } 129 | 130 | void SetUseLabbe() { 131 | this->m_bUseLabbe = true; 132 | } 133 | 134 | 135 | void ApplyYang(); 136 | 137 | 138 | protected: 139 | RBVPVCImageFilter(); 140 | ~RBVPVCImageFilter() {} 141 | 142 | /** Does the real work. */ 143 | virtual void GenerateData() ITK_OVERRIDE; 144 | 145 | VectorType m_vecRegMeansPVCorr; 146 | MatrixType m_matGTM; 147 | ITKVectorType m_vecVariance; 148 | bool m_bVerbose; 149 | 150 | 151 | private: 152 | RBVPVCImageFilter(const Self &); //purposely not implemented 153 | void operator=(const Self &); //purposely not implemented 154 | 155 | 156 | 157 | }; 158 | } //namespace petpvc 159 | 160 | 161 | #ifndef ITK_MANUAL_INSTANTIATION 162 | #include "petpvcRBVPVCImageFilter.txx" 163 | #endif 164 | 165 | 166 | #endif // __PETPVCRBVIMAGEFILTER_H 167 | -------------------------------------------------------------------------------- /lib/petpvcRLPVCImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcRLPVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCRLPVCIMAGEFILTER_H 24 | #define __PETPVCRLPVCIMAGEFILTER_H 25 | 26 | #include "itkImage.h" 27 | #include "itkImageToImageFilter.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include 41 | 42 | using namespace itk; 43 | 44 | namespace petpvc 45 | { 46 | template< class TInputImage> 47 | class RichardsonLucyPVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 48 | { 49 | public: 50 | /** Standard class typedefs. */ 51 | typedef RichardsonLucyPVCImageFilter Self; 52 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 53 | typedef SmartPointer< Self > Pointer; 54 | 55 | /** Method for creation through the object factory. */ 56 | itkNewMacro(Self); 57 | 58 | /** Run-time type information (and related methods). */ 59 | #if ITK_VERSION_MAJOR < 6 60 | itkTypeMacro(RichardsonLucyPVCImageFilter, ImageToImageFilter); 61 | #else 62 | itkOverrideGetNameOfClassMacro(RichardsonLucyPVCImageFilter); 63 | #endif 64 | 65 | /** Image related typedefs. */ 66 | typedef TInputImage InputImageType; 67 | typedef typename TInputImage::ConstPointer InputImagePointer; 68 | typedef typename TInputImage::RegionType RegionType; 69 | typedef typename TInputImage::SizeType SizeType; 70 | typedef typename TInputImage::IndexType IndexType; 71 | typedef typename TInputImage::PixelType PixelType; 72 | 73 | typedef itk::ImageRegionConstIterator ConstImageIterator; 74 | 75 | //For calculating mean values from image 76 | typedef itk::StatisticsImageFilter StatisticsFilterType; 77 | //Extracts a 3D volume from 4D file. 78 | 79 | typedef itk::MultiplyImageFilter MultiplyFilterType; 80 | typedef itk::DivideImageFilter DivideFilterType; 81 | typedef itk::AddImageFilter AddFilterType; 82 | typedef itk::SubtractImageFilter SubFilterType; 83 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 84 | typedef itk::ThresholdImageFilter ThresholdFilterType; 85 | typedef itk::ImageDuplicator DuplicatorType; 86 | 87 | typedef itk::Vector ITKVectorType; 88 | 89 | /** Image related typedefs. */ 90 | itkStaticConstMacro(InputImageDimension, unsigned int, 91 | 3); 92 | 93 | void SetPSF(ITKVectorType vec) { 94 | this->m_vecVariance = vec; 95 | } 96 | 97 | ITKVectorType GetPSF() { 98 | return this->m_vecVariance; 99 | } 100 | 101 | void SetIterations( unsigned int nIters ) { 102 | this->m_nIterations = nIters; 103 | } 104 | 105 | void SetStoppingCond( float stop ) { 106 | this->m_fStopCriterion = stop; 107 | } 108 | 109 | void SetVerbose( bool bVerbose ) { 110 | this->m_bVerbose = bVerbose; 111 | } 112 | 113 | 114 | protected: 115 | RichardsonLucyPVCImageFilter(); 116 | ~RichardsonLucyPVCImageFilter() {}; 117 | 118 | /** Does the real work. */ 119 | virtual void GenerateData() ITK_OVERRIDE; 120 | 121 | // Calculate threshold at which a value is zeroed 122 | float GetZeroThreshold( typename TInputImage::ConstPointer img ); 123 | 124 | ITKVectorType m_vecVariance; 125 | unsigned int m_nIterations; 126 | float m_fStopCriterion; 127 | bool m_bVerbose; 128 | 129 | private: 130 | RichardsonLucyPVCImageFilter(const Self &); //purposely not implemented 131 | void operator=(const Self &); //purposely not implemented 132 | 133 | 134 | 135 | }; 136 | } //namespace petpvc 137 | 138 | 139 | #ifndef ITK_MANUAL_INSTANTIATION 140 | #include "petpvcRLPVCImageFilter.txx" 141 | #endif 142 | 143 | 144 | #endif // __PETPVCRichardsonLucyIMAGEFILTER_H 145 | -------------------------------------------------------------------------------- /lib/petpvcRegionConvolutionImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcRegionConvolutionPVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCREGIONCONVOLUTIONIMAGEFILTER_H 24 | #define __PETPVCREGIONCONVOLUTIONIMAGEFILTER_H 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | using namespace itk; 37 | 38 | namespace petpvc 39 | { 40 | template< class TInputImage, typename TMaskImage> 41 | class RegionConvolutionPVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 42 | { 43 | public: 44 | /** Standard class typedefs. */ 45 | typedef RegionConvolutionPVCImageFilter Self; 46 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 47 | typedef SmartPointer< Self > Pointer; 48 | 49 | /** Method for creation through the object factory. */ 50 | itkNewMacro(Self); 51 | 52 | /** Run-time type information (and related methods). */ 53 | #if ITK_VERSION_MAJOR < 6 54 | itkTypeMacro(RegionConvolutionPVCImageFilter, ImageToImageFilter); 55 | #else 56 | itkOverrideGetNameOfClassMacro(RegionConvolutionPVCImageFilter); 57 | #endif 58 | 59 | /** Image related typedefs. */ 60 | typedef TInputImage InputImageType; 61 | typedef typename TInputImage::ConstPointer InputImagePointer; 62 | typedef typename TInputImage::RegionType RegionType; 63 | typedef typename TInputImage::SizeType SizeType; 64 | typedef typename TInputImage::IndexType IndexType; 65 | typedef typename TInputImage::PixelType PixelType; 66 | 67 | /** Mask image related typedefs. */ 68 | typedef TMaskImage MaskImageType; 69 | typedef typename TMaskImage::ConstPointer MaskImagePointer; 70 | typedef typename TMaskImage::RegionType MaskRegionType; 71 | typedef typename TMaskImage::SizeType MaskSizeType; 72 | typedef typename TMaskImage::IndexType MaskIndexType; 73 | typedef typename TMaskImage::PixelType MaskPixelType; 74 | 75 | typedef itk::MultiplyImageFilter MultiplyFilterType; 76 | typedef itk::DivideImageFilter DivideFilterType; 77 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 78 | typedef itk::ImageDuplicator DuplicatorType; 79 | 80 | typedef itk::Vector ITKVectorType; 81 | 82 | /** Image related typedefs. */ 83 | itkStaticConstMacro(InputImageDimension, unsigned int, 84 | 3); 85 | 86 | itkStaticConstMacro(MaskImageDimension, unsigned int, 87 | 3); 88 | 89 | typedef vnl_vector VectorType; 90 | typedef vnl_matrix MatrixType; 91 | 92 | /** Set the mask image */ 93 | void SetMaskInput(const TMaskImage *input) { 94 | // Process object is not const-correct so the const casting is required. 95 | this->SetNthInput( 1, const_cast< TMaskImage * >( input ) ); 96 | } 97 | 98 | /** Get the label image */ 99 | const MaskImageType * GetMaskInput() const { 100 | return itkDynamicCastInDebugMode< MaskImageType * >( const_cast< DataObject * >( this->ProcessObject::GetInput(0) ) ); 101 | } 102 | 103 | void SetPSF(ITKVectorType vec) { 104 | this->m_vecVariance = vec; 105 | } 106 | 107 | ITKVectorType GetPSF() { 108 | return this->m_vecVariance; 109 | } 110 | 111 | void SetVerbose( bool bVerbose ) { 112 | this->m_bVerbose = bVerbose; 113 | } 114 | 115 | 116 | protected: 117 | RegionConvolutionPVCImageFilter(); 118 | ~RegionConvolutionPVCImageFilter() {}; 119 | 120 | /** Does the real work. */ 121 | virtual void GenerateData() ITK_OVERRIDE; 122 | 123 | ITKVectorType m_vecVariance; 124 | bool m_bVerbose; 125 | 126 | private: 127 | RegionConvolutionPVCImageFilter(const Self &); //purposely not implemented 128 | void operator=(const Self &); //purposely not implemented 129 | 130 | 131 | 132 | }; 133 | } //namespace petpvc 134 | 135 | 136 | #ifndef ITK_MANUAL_INSTANTIATION 137 | #include "petpvcRegionConvolutionImageFilter.txx" 138 | #endif 139 | 140 | 141 | #endif // __PETPVCREGIONCONVOLUTIONIMAGEFILTER_H 142 | -------------------------------------------------------------------------------- /lib/petpvcRegionConvolutionImageFilter.txx: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcRegionConvolutionPVCImageFilter.txx 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCREGIONCONVOLUTIONIMAGEFILTER_TXX 24 | #define __PETPVCREGIONCONVOLUTIONIMAGEFILTER_TXX 25 | 26 | #include "petpvcRegionConvolutionImageFilter.h" 27 | #include "itkObjectFactory.h" 28 | #include "itkImageRegionIterator.h" 29 | #include "itkImageRegionConstIterator.h" 30 | 31 | using namespace itk; 32 | 33 | namespace petpvc 34 | { 35 | 36 | template< class TInputImage, class TMaskImage > 37 | RegionConvolutionPVCImageFilter< TInputImage, TMaskImage> 38 | ::RegionConvolutionPVCImageFilter() 39 | { 40 | this->m_bVerbose = false; 41 | } 42 | 43 | template< class TInputImage, class TMaskImage > 44 | void RegionConvolutionPVCImageFilter< TInputImage, TMaskImage> 45 | ::GenerateData() 46 | { 47 | 48 | this->SetGlobalDefaultCoordinateTolerance( 1e-2 ); 49 | this->SetGlobalDefaultDirectionTolerance( 1e-2 ); 50 | 51 | typename TInputImage::ConstPointer input = this->GetInput(); 52 | typename TInputImage::Pointer output = this->GetOutput(); 53 | 54 | InputImagePointer pPET = dynamic_cast (ProcessObject::GetInput(0)); 55 | MaskImagePointer pMask = dynamic_cast (ProcessObject::GetInput(1)); 56 | 57 | typename MultiplyFilterType::Pointer multiplyFilter = MultiplyFilterType::New(); 58 | typename MultiplyFilterType::Pointer multiplyFilter2 = MultiplyFilterType::New(); 59 | typename DivideFilterType::Pointer divideFilter = DivideFilterType::New(); 60 | typename BlurringFilterType::Pointer blurFilter = BlurringFilterType::New(); 61 | typename BlurringFilterType::Pointer blurFilter2 = BlurringFilterType::New(); 62 | 63 | blurFilter->SetVariance( this->GetPSF() ); 64 | blurFilter2->SetVariance( this->GetPSF() ); 65 | 66 | //Perform regional convolution 67 | multiplyFilter->SetInput1( pMask ); 68 | multiplyFilter->SetInput2( pPET ); 69 | blurFilter->SetInput( multiplyFilter->GetOutput() ); 70 | blurFilter2->SetInput( pMask ); 71 | divideFilter->SetInput1( blurFilter->GetOutput() ); 72 | divideFilter->SetInput2( blurFilter2->GetOutput() ); 73 | multiplyFilter2->SetInput1( pMask ); 74 | multiplyFilter2->SetInput2( divideFilter->GetOutput() ); 75 | 76 | try { 77 | multiplyFilter2->Update(); 78 | } catch (itk::ExceptionObject & err) { 79 | std::cerr << "\n[Error]\tCannot performing regional convolution" 80 | << std::endl; 81 | } 82 | 83 | typename TInputImage::Pointer imageOut= multiplyFilter2->GetOutput(); 84 | 85 | this->AllocateOutputs(); 86 | 87 | ImageAlgorithm::Copy( imageOut.GetPointer(), output.GetPointer(), output->GetRequestedRegion(), 88 | output->GetRequestedRegion() ); 89 | 90 | } 91 | 92 | }// end namespace 93 | 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /lib/petpvcRoussetPVCImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcRoussetPVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2013 Institute of Nuclear Medicine, University College London. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | */ 21 | 22 | #ifndef __PETPVCROUSSETPVCIMAGEFILTER_H 23 | #define __PETPVCROUSSETPVCIMAGEFILTER_H 24 | 25 | #include "itkImage.h" 26 | #include "itkImageToImageFilter.h" 27 | #include "petpvcGTMImageFilter.h" 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | using namespace itk; 35 | 36 | namespace petpvc 37 | { 38 | template< class TInputImage, typename TMaskImage> 39 | class RoussetPVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 40 | { 41 | public: 42 | /** Standard class typedefs. */ 43 | typedef RoussetPVCImageFilter Self; 44 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 45 | typedef SmartPointer< Self > Pointer; 46 | 47 | /** Method for creation through the object factory. */ 48 | itkNewMacro(Self); 49 | 50 | /** Run-time type information (and related methods). */ 51 | #if ITK_VERSION_MAJOR < 6 52 | itkTypeMacro(RoussetPVCImageFilter, ImageToImageFilter); 53 | #else 54 | itkOverrideGetNameOfClassMacro(RoussetPVCImageFilter); 55 | #endif 56 | 57 | /** Image related typedefs. */ 58 | typedef TInputImage InputImageType; 59 | typedef typename TInputImage::ConstPointer InputImagePointer; 60 | typedef typename TInputImage::RegionType RegionType; 61 | typedef typename TInputImage::SizeType SizeType; 62 | typedef typename TInputImage::IndexType IndexType; 63 | typedef typename TInputImage::PixelType PixelType; 64 | 65 | /** Mask image related typedefs. */ 66 | typedef TMaskImage MaskImageType; 67 | typedef typename TMaskImage::ConstPointer MaskImagePointer; 68 | typedef typename TMaskImage::RegionType MaskRegionType; 69 | typedef typename TMaskImage::SizeType MaskSizeType; 70 | typedef typename TMaskImage::IndexType MaskIndexType; 71 | typedef typename TMaskImage::PixelType MaskPixelType; 72 | 73 | //For calculating mean values from image 74 | typedef itk::StatisticsImageFilter StatisticsFilterType; 75 | //Extracts a 3D volume from 4D file. 76 | typedef itk::ExtractImageFilter ExtractFilterType; 77 | typedef itk::MultiplyImageFilter MultiplyFilterType; 78 | 79 | typedef GTMImageFilter GTMImageFilterType; 80 | typedef itk::Vector ITKVectorType; 81 | 82 | /** Image related typedefs. */ 83 | itkStaticConstMacro(InputImageDimension, unsigned int, 84 | 3); 85 | 86 | itkStaticConstMacro(MaskImageDimension, unsigned int, 87 | 4); 88 | 89 | typedef vnl_vector VectorType; 90 | typedef vnl_matrix MatrixType; 91 | 92 | /** Set the mask image */ 93 | void SetMaskInput(const TMaskImage *input) { 94 | // Process object is not const-correct so the const casting is required. 95 | this->SetNthInput( 1, const_cast< TMaskImage * >( input ) ); 96 | } 97 | 98 | /** Get the label image */ 99 | const MaskImageType * GetMaskInput() const { 100 | return itkDynamicCastInDebugMode< MaskImageType * >( const_cast< DataObject * >( this->ProcessObject::GetInput(0) ) ); 101 | } 102 | 103 | VectorType GetCorrectedMeans() const { 104 | return this->m_vecRegMeansPVCorr; 105 | } 106 | 107 | MatrixType GetMatrix() const { 108 | return this->m_matGTM; 109 | } 110 | 111 | void SetPSF(ITKVectorType vec) { 112 | this->m_vecVariance = vec; 113 | }; 114 | 115 | 116 | ITKVectorType GetPSF() { 117 | return this->m_vecVariance; 118 | }; 119 | 120 | void SetVerbose( bool bVerbose ) { 121 | this->m_bVerbose = bVerbose; 122 | } 123 | 124 | protected: 125 | RoussetPVCImageFilter(); 126 | ~RoussetPVCImageFilter() {} 127 | 128 | /** Does the real work. */ 129 | virtual void GenerateData() ITK_OVERRIDE; 130 | 131 | VectorType m_vecRegMeansPVCorr; 132 | MatrixType m_matGTM; 133 | ITKVectorType m_vecVariance; 134 | bool m_bVerbose; 135 | 136 | private: 137 | RoussetPVCImageFilter(const Self &); //purposely not implemented 138 | void operator=(const Self &); //purposely not implemented 139 | 140 | 141 | 142 | }; 143 | } //namespace petpvc 144 | 145 | 146 | #ifndef ITK_MANUAL_INSTANTIATION 147 | #include "petpvcRoussetPVCImageFilter.txx" 148 | #endif 149 | 150 | 151 | #endif // __PETPVCROUSSETIMAGEFILTER_H 152 | -------------------------------------------------------------------------------- /lib/petpvcRoussetPVCImageFilter.txx: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcRoussetPVCImageFilter.txx 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2013 Institute of Nuclear Medicine, University College London. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | */ 21 | 22 | #ifndef __PETPVCROUSSETPVCIMAGEFILTER_TXX 23 | #define __PETPVCROUSSETPVCIMAGEFILTER_TXX 24 | 25 | #include "petpvcRoussetPVCImageFilter.h" 26 | #include "itkObjectFactory.h" 27 | #include "itkImageRegionIterator.h" 28 | #include "itkImageRegionConstIterator.h" 29 | 30 | using namespace itk; 31 | 32 | namespace petpvc 33 | { 34 | 35 | template< class TInputImage, class TMaskImage > 36 | RoussetPVCImageFilter< TInputImage, TMaskImage> 37 | ::RoussetPVCImageFilter() 38 | { 39 | this->m_bVerbose = false; 40 | } 41 | 42 | template< class TInputImage, class TMaskImage > 43 | void RoussetPVCImageFilter< TInputImage, TMaskImage> 44 | ::GenerateData() 45 | { 46 | 47 | this->SetGlobalDefaultCoordinateTolerance( 1e-2 ); 48 | this->SetGlobalDefaultDirectionTolerance( 1e-2 ); 49 | 50 | typename TInputImage::ConstPointer input = this->GetInput(); 51 | typename TInputImage::Pointer output = this->GetOutput(); 52 | 53 | typename GTMImageFilterType::Pointer pGTM = GTMImageFilterType::New(); 54 | 55 | InputImagePointer pPET = dynamic_cast (ProcessObject::GetInput(0)); 56 | MaskImagePointer pMask = dynamic_cast (ProcessObject::GetInput(1)); 57 | 58 | pGTM->SetInput( pMask ); 59 | pGTM->SetPSF( this->GetPSF() ); 60 | //Calculate GTM. 61 | try { 62 | pGTM->Update(); 63 | } catch (itk::ExceptionObject & err) { 64 | std::cerr << "[Error]\tCannot calculate GTM" 65 | << std::endl; 66 | } 67 | 68 | if ( this->m_bVerbose ) { 69 | std::cout << pGTM->GetMatrix() << std::endl; 70 | } 71 | 72 | ///////////////////////////////////////////// 73 | 74 | //Get mask image size. 75 | typename MaskImageType::SizeType imageSize = 76 | pMask->GetLargestPossibleRegion().GetSize(); 77 | 78 | int nClasses = 0; 79 | 80 | //If mask is not 4D, then quit. 81 | if (imageSize.Dimension == 4) { 82 | nClasses = imageSize[3]; 83 | } else { 84 | std::cerr << "[Error]\tMask file must be 4-D!" 85 | << std::endl; 86 | } 87 | 88 | MaskSizeType desiredStart; 89 | desiredStart.Fill(0); 90 | MaskSizeType desiredSize = imageSize; 91 | 92 | //Extract filter used to extract 3D volume from 4D file. 93 | typename ExtractFilterType::Pointer extractFilter = ExtractFilterType::New(); 94 | extractFilter->SetInput( pMask ); 95 | extractFilter->SetDirectionCollapseToIdentity(); // This is required. 96 | 97 | //Stats. filter used to calculate statistics for an image. 98 | typename StatisticsFilterType::Pointer statsFilter = StatisticsFilterType::New(); 99 | 100 | //Multiplies two images together. 101 | typename MultiplyFilterType::Pointer multiplyFilter = MultiplyFilterType::New(); 102 | 103 | typename TInputImage::Pointer imageExtractedRegion;// = InputImagePointer::New(); 104 | 105 | float fSumOfPETReg; 106 | 107 | //Vector to contain the current estimate of the regional mean values. 108 | vnl_vector vecRegMeansCurrent; 109 | vecRegMeansCurrent.set_size(nClasses); 110 | 111 | //Vector to contain the estimated means after GTM correction. 112 | vnl_vector vecRegMeansUpdated; 113 | vecRegMeansUpdated.set_size(nClasses); 114 | 115 | for (int i = 1; i <= nClasses; i++) { 116 | 117 | //Starts reading from 4D volume at index (0,0,0,i) through to 118 | //(maxX, maxY, maxZ,0), i.e. one 3D brain mask. 119 | desiredStart[3] = i - 1; 120 | desiredSize[3] = 0; 121 | 122 | //Get region mask. 123 | MaskRegionType maskReg; 124 | maskReg.SetSize(desiredSize ); 125 | maskReg.SetIndex(0,desiredStart[0] ); 126 | maskReg.SetIndex(1,desiredStart[1] ); 127 | maskReg.SetIndex(2,desiredStart[2] ); 128 | maskReg.SetIndex(3,desiredStart[3] ); 129 | 130 | extractFilter->SetExtractionRegion( maskReg ); 131 | extractFilter->Update(); 132 | 133 | imageExtractedRegion = extractFilter->GetOutput(); 134 | imageExtractedRegion->SetDirection( pPET->GetDirection() ); 135 | imageExtractedRegion->UpdateOutputData(); 136 | 137 | //Multiply current image estimate by region mask. To clip PET values 138 | //to mask. 139 | multiplyFilter->SetInput1( pPET ); 140 | multiplyFilter->SetInput2( imageExtractedRegion ); 141 | 142 | statsFilter->SetInput(multiplyFilter->GetOutput()); 143 | statsFilter->Update(); 144 | 145 | //Get sum of the clipped image. 146 | fSumOfPETReg = statsFilter->GetSum(); 147 | 148 | //Place regional mean into vector. 149 | vecRegMeansCurrent.put(i - 1, fSumOfPETReg / pGTM->GetSumOfRegions().get(i - 1)); 150 | //std::cout << "Sum = " << fSumOfPETReg << " , Mean = " << vecRegMeansCurrent.get(i-1) << " Total vox. = " << gtmFilter->GetSumOfRegions().get( i-1 ) << std::endl; 151 | 152 | } 153 | 154 | //Apply GTM to regional mean values. 155 | vecRegMeansUpdated = vnl_matrix_inverse(pGTM->GetMatrix()) * vecRegMeansCurrent; 156 | 157 | if ( this->m_bVerbose ) { 158 | std::cout << std::endl << "Regional means:" << std::endl; 159 | std::cout << vecRegMeansCurrent << std::endl << std::endl; 160 | 161 | std::cout << "GTM:" << std::endl; 162 | pGTM->GetMatrix().print(std::cout); 163 | 164 | std::cout << std::endl << "Corrected means:" << std::endl; 165 | 166 | } 167 | 168 | std::cout << vecRegMeansUpdated << std::endl; 169 | this->m_vecRegMeansPVCorr = vecRegMeansUpdated; 170 | 171 | this->AllocateOutputs(); 172 | 173 | ImageAlgorithm::Copy(input.GetPointer(), output.GetPointer(), output->GetRequestedRegion(), 174 | output->GetRequestedRegion() ); 175 | 176 | 177 | } 178 | 179 | }// end namespace 180 | 181 | 182 | #endif 183 | -------------------------------------------------------------------------------- /lib/petpvcSTCPVCImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcSTCPVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2017 Institute of Nuclear Medicine, University College London. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | */ 21 | 22 | #ifndef __PETPVCSTCIMAGEFILTER_H 23 | #define __PETPVCSTCIMAGEFILTER_H 24 | 25 | #include "itkImage.h" 26 | #include "itkImageToImageFilter.h" 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | //#include 37 | 38 | #include 39 | #include 40 | 41 | #include 42 | 43 | using namespace itk; 44 | 45 | namespace petpvc 46 | { 47 | 48 | /*! Single Target Correction (STC) 49 | 50 | An Implementation of the STC Method, see
51 | Sari H, Erlandsson K, Law I, Larsson HB, Ourselin S, Arridge S, Atkinson D, Hutton BF. 52 | Estimation of an image derived input function with MR-defined carotid arteries in FDG-PET human studies using a novel partial volume correction method. 53 | J Cereb Blood Flow Metab. 2017;37(4): 1398--409 54 |
55 | Erlanddsson K and Hutton BF. 56 | A novel voxel-based partial volume correction method for single regions of interest. 57 | J Nucl Med Meeting Abstr 2014; 55: 2023. 58 | */ 59 | template< class TInputImage, typename TMaskImage> 60 | class STCPVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 61 | { 62 | public: 63 | /** Standard class typedefs. */ 64 | typedef STCPVCImageFilter Self; 65 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 66 | typedef SmartPointer< Self > Pointer; 67 | 68 | /** Method for creation through the object factory. */ 69 | itkNewMacro(Self); 70 | 71 | /** Run-time type information (and related methods). */ 72 | #if ITK_VERSION_MAJOR < 6 73 | itkTypeMacro(STCPVCImageFilter, ImageToImageFilter); 74 | #else 75 | itkOverrideGetNameOfClassMacro(STCPVCImageFilter); 76 | #endif 77 | 78 | /** Image related typedefs. */ 79 | typedef TInputImage InputImageType; 80 | typedef typename TInputImage::ConstPointer InputImagePointer; 81 | typedef typename TInputImage::RegionType RegionType; 82 | typedef typename TInputImage::SizeType SizeType; 83 | typedef typename TInputImage::IndexType IndexType; 84 | typedef typename TInputImage::PixelType PixelType; 85 | 86 | /** Mask image related typedefs. */ 87 | typedef TMaskImage MaskImageType; 88 | typedef typename TMaskImage::ConstPointer MaskImagePointer; 89 | typedef typename TMaskImage::RegionType MaskRegionType; 90 | typedef typename TMaskImage::SizeType MaskSizeType; 91 | typedef typename TMaskImage::IndexType MaskIndexType; 92 | typedef typename TMaskImage::PixelType MaskPixelType; 93 | 94 | //For calculating mean values from image 95 | typedef itk::StatisticsImageFilter StatisticsFilterType; 96 | 97 | //For getting information about the mask labels 98 | typedef itk::LabelStatisticsImageFilter LabelStatisticsFilterType; 99 | typedef typename LabelStatisticsFilterType::ValidLabelValuesContainerType ValidLabelValuesType; 100 | typedef typename LabelStatisticsFilterType::LabelPixelType LabelPixelType; 101 | 102 | typedef itk::BinaryThresholdImageFilter BinaryThresholdImageFilterType; 103 | 104 | typedef itk::MultiplyImageFilter MultiplyFilterType; 105 | typedef itk::DivideImageFilter DivideFilterType; 106 | typedef itk::AddImageFilter AddFilterType; 107 | typedef itk::SubtractImageFilter SubtractFilterType; 108 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 109 | typedef itk::ImageDuplicator DuplicatorType; 110 | 111 | typedef itk::ImageRegionIterator ImageIteratorType; 112 | 113 | //typedef itk::ImageFileWriter WriterType; 114 | 115 | typedef itk::Vector ITKVectorType; 116 | 117 | /** Image related typedefs. */ 118 | itkStaticConstMacro(InputImageDimension, unsigned int, 119 | 3); 120 | 121 | itkStaticConstMacro(MaskImageDimension, unsigned int, 122 | 3); 123 | 124 | typedef vnl_vector VectorType; 125 | typedef vnl_matrix MatrixType; 126 | 127 | /** Set the mask image */ 128 | void SetMaskInput(const TMaskImage *input) { 129 | // Process object is not const-correct so the const casting is required. 130 | this->SetNthInput( 1, const_cast< TMaskImage * >( input ) ); 131 | } 132 | 133 | /** Get the label image */ 134 | const MaskImageType * GetMaskInput() const { 135 | return itkDynamicCastInDebugMode< MaskImageType * >( const_cast< DataObject * >( this->ProcessObject::GetInput(0) ) ); 136 | } 137 | 138 | VectorType GetCorrectedMeans() const { 139 | return this->m_vecRegMeansPVCorr; 140 | } 141 | 142 | MatrixType GetMatrix() const { 143 | return this->m_matGTM; 144 | } 145 | 146 | void SetPSF(ITKVectorType vec) { 147 | this->m_vecVariance = vec; 148 | } 149 | 150 | 151 | ITKVectorType GetPSF() { 152 | return this->m_vecVariance; 153 | } 154 | 155 | void SetIterations( unsigned int nIters ) { 156 | this->m_nIterations = nIters; 157 | } 158 | 159 | void SetVerbose( bool bVerbose ) { 160 | this->m_bVerbose = bVerbose; 161 | } 162 | 163 | 164 | protected: 165 | STCPVCImageFilter(); 166 | ~STCPVCImageFilter() {}; 167 | 168 | /** Does the real work. */ 169 | virtual void GenerateData() ITK_OVERRIDE; 170 | 171 | VectorType m_vecRegMeansPVCorr; 172 | MatrixType m_matGTM; 173 | ITKVectorType m_vecVariance; 174 | unsigned int m_nIterations; 175 | bool m_bVerbose; 176 | 177 | private: 178 | STCPVCImageFilter(const Self &); //purposely not implemented 179 | void operator=(const Self &); //purposely not implemented 180 | 181 | }; 182 | } //namespace petpvc 183 | 184 | 185 | #ifndef ITK_MANUAL_INSTANTIATION 186 | #include "petpvcSTCPVCImageFilter.txx" 187 | #endif 188 | 189 | 190 | #endif // __PETPVCSTCIMAGEFILTER_H 191 | -------------------------------------------------------------------------------- /lib/petpvcVanCittertPVCImageFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcVanCittertPVCImageFilter.h 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015-2019 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCVANCITTERTIMAGEFILTER_H 24 | #define __PETPVCVANCITTERTIMAGEFILTER_H 25 | 26 | #include "itkImage.h" 27 | #include "itkImageToImageFilter.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | 41 | using namespace itk; 42 | 43 | namespace petpvc 44 | { 45 | template< class TInputImage> 46 | class VanCittertPVCImageFilter:public ImageToImageFilter< TInputImage, TInputImage > 47 | { 48 | public: 49 | /** Standard class typedefs. */ 50 | typedef VanCittertPVCImageFilter Self; 51 | typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; 52 | typedef SmartPointer< Self > Pointer; 53 | 54 | /** Method for creation through the object factory. */ 55 | itkNewMacro(Self); 56 | 57 | /** Run-time type information (and related methods). */ 58 | #if ITK_VERSION_MAJOR < 6 59 | itkTypeMacro(VanCittertPVCImageFilter, ImageToImageFilter); 60 | #else 61 | itkOverrideGetNameOfClassMacro(VanCittertPVCImageFilter); 62 | #endif 63 | 64 | /** Image related typedefs. */ 65 | typedef TInputImage InputImageType; 66 | typedef typename TInputImage::ConstPointer InputImagePointer; 67 | typedef typename TInputImage::RegionType RegionType; 68 | typedef typename TInputImage::SizeType SizeType; 69 | typedef typename TInputImage::IndexType IndexType; 70 | typedef typename TInputImage::PixelType PixelType; 71 | 72 | typedef itk::ImageRegionConstIterator ConstImageIterator; 73 | 74 | //For calculating mean values from image 75 | typedef itk::StatisticsImageFilter StatisticsFilterType; 76 | //Extracts a 3D volume from 4D file. 77 | 78 | typedef itk::MultiplyImageFilter MultiplyFilterType; 79 | typedef itk::AddImageFilter AddFilterType; 80 | typedef itk::SubtractImageFilter SubFilterType; 81 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 82 | typedef itk::ThresholdImageFilter ThresholdFilterType; 83 | typedef itk::ImageDuplicator DuplicatorType; 84 | 85 | typedef itk::Vector ITKVectorType; 86 | 87 | /** Image related typedefs. */ 88 | itkStaticConstMacro(InputImageDimension, unsigned int, 89 | 3); 90 | 91 | void SetPSF(ITKVectorType vec) { 92 | this->m_vecVariance = vec; 93 | } 94 | 95 | 96 | ITKVectorType GetPSF() { 97 | return this->m_vecVariance; 98 | } 99 | 100 | void SetIterations( unsigned int nIters ) { 101 | this->m_nIterations = nIters; 102 | } 103 | 104 | void SetAlpha( float alpha ) { 105 | this->m_fAlpha = alpha; 106 | } 107 | 108 | void SetStoppingCond( float stop ) { 109 | this->m_fStopCriterion = stop; 110 | } 111 | 112 | void SetVerbose( bool bVerbose ) { 113 | this->m_bVerbose = bVerbose; 114 | } 115 | 116 | void SetDisableNonNegativity( bool bDisableNonNeg ) { 117 | this->m_bDisableNonNeg = bDisableNonNeg; 118 | } 119 | 120 | 121 | protected: 122 | VanCittertPVCImageFilter(); 123 | ~VanCittertPVCImageFilter() {}; 124 | 125 | /** Does the real work. */ 126 | virtual void GenerateData() ITK_OVERRIDE; 127 | 128 | ITKVectorType m_vecVariance; 129 | unsigned int m_nIterations; 130 | float m_fAlpha; 131 | float m_fStopCriterion; 132 | bool m_bVerbose; 133 | bool m_bDisableNonNeg; 134 | 135 | private: 136 | VanCittertPVCImageFilter(const Self &); //purposely not implemented 137 | void operator=(const Self &); //purposely not implemented 138 | 139 | 140 | 141 | }; 142 | } //namespace petpvc 143 | 144 | 145 | #ifndef ITK_MANUAL_INSTANTIATION 146 | #include "petpvcVanCittertPVCImageFilter.txx" 147 | #endif 148 | 149 | 150 | #endif // __PETPVCVANCITTERTIMAGEFILTER_H 151 | -------------------------------------------------------------------------------- /lib/petpvcVanCittertPVCImageFilter.txx: -------------------------------------------------------------------------------- 1 | /* 2 | petpvcVanCittertPVCImageFilter.txx 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015-2019 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | */ 22 | 23 | #ifndef __PETPVCVANCITTERTPVCIMAGEFILTER_TXX 24 | #define __PETPVCVANCITTERTPVCIMAGEFILTER_TXX 25 | 26 | #include "petpvcVanCittertPVCImageFilter.h" 27 | #include "itkObjectFactory.h" 28 | #include "itkImageRegionIterator.h" 29 | #include "itkImageRegionConstIterator.h" 30 | 31 | using namespace itk; 32 | 33 | namespace petpvc 34 | { 35 | 36 | template< class TInputImage > 37 | VanCittertPVCImageFilter< TInputImage > 38 | ::VanCittertPVCImageFilter() 39 | { 40 | this->m_nIterations = 30; 41 | this->m_bVerbose = false; 42 | this->m_fAlpha = 1.5; 43 | this->m_fStopCriterion = 0.01; 44 | this->m_bDisableNonNeg = false; 45 | } 46 | 47 | template< class TInputImage > 48 | void VanCittertPVCImageFilter< TInputImage > 49 | ::GenerateData() 50 | { 51 | 52 | this->SetGlobalDefaultCoordinateTolerance( 1e-2 ); 53 | this->SetGlobalDefaultDirectionTolerance( 1e-2 ); 54 | 55 | typename TInputImage::ConstPointer input = this->GetInput(); 56 | typename TInputImage::Pointer output = this->GetOutput(); 57 | 58 | InputImagePointer pPET = dynamic_cast (ProcessObject::GetInput(0)); 59 | 60 | //Gaussian smoothing 61 | typename BlurringFilterType::Pointer blurFilter = BlurringFilterType::New(); 62 | typename BlurringFilterType::Pointer blurFilter2 = BlurringFilterType::New(); 63 | //Multiplies two images together. 64 | typename MultiplyFilterType::Pointer multiplyFilter = MultiplyFilterType::New(); 65 | typename DuplicatorType::Pointer duplicator = DuplicatorType::New(); 66 | typename AddFilterType::Pointer addFilter = AddFilterType::New(); 67 | typename SubFilterType::Pointer subFilter = SubFilterType::New(); 68 | typename ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New(); 69 | 70 | duplicator->SetInputImage( pPET ); 71 | duplicator->Update(); 72 | 73 | typename TInputImage::Pointer imageEstimate; 74 | //Set image estimate to the original PET data for the first iteration. 75 | imageEstimate = duplicator->GetOutput(); 76 | 77 | typename TInputImage::Pointer imagePrev; 78 | //Set imagePrev to the original PET data for the first iteration. 79 | imagePrev = duplicator->GetOutput(); 80 | 81 | blurFilter->SetVariance( this->GetPSF() ); 82 | blurFilter2->SetVariance( this->GetPSF() ); 83 | 84 | thresholdFilter->ThresholdBelow( 0 ); 85 | thresholdFilter->SetOutsideValue( 0 ); 86 | 87 | 88 | float fSumOfPETsq = 0.0; 89 | 90 | ConstImageIterator inputIt( pPET, pPET->GetLargestPossibleRegion() ); 91 | inputIt.GoToBegin(); 92 | 93 | while ( !inputIt.IsAtEnd() ) 94 | { 95 | fSumOfPETsq += inputIt.Get()*inputIt.Get(); 96 | ++inputIt; 97 | } 98 | 99 | int nMaxNumOfIters = this->m_nIterations; 100 | int n=1; 101 | 102 | bool bStopped = false; 103 | 104 | while ( ( n <= nMaxNumOfIters ) && ( !bStopped ) ) { 105 | 106 | float fSumOfDiffsq = 0.0; 107 | 108 | duplicator->SetInputImage( imageEstimate ); 109 | duplicator->Update(); 110 | imagePrev = duplicator->GetOutput(); 111 | 112 | blurFilter->SetInput( imageEstimate ); 113 | subFilter->SetInput1( pPET ); 114 | subFilter->SetInput2( blurFilter->GetOutput() ); 115 | blurFilter2->SetInput( subFilter->GetOutput() ); 116 | multiplyFilter->SetConstant( this->m_fAlpha ); 117 | multiplyFilter->SetInput( blurFilter2->GetOutput() ); 118 | addFilter->SetInput1( imageEstimate ); 119 | addFilter->SetInput2( multiplyFilter->GetOutput() ); 120 | 121 | if (!m_bDisableNonNeg) { 122 | thresholdFilter->SetInput( addFilter->GetOutput() ); 123 | thresholdFilter->Update(); 124 | imageEstimate = thresholdFilter->GetOutput(); 125 | } 126 | else { 127 | addFilter->Update(); 128 | imageEstimate = addFilter->GetOutput(); 129 | } 130 | 131 | imageEstimate->DisconnectPipeline(); 132 | 133 | ConstImageIterator currIt( imageEstimate, imageEstimate->GetLargestPossibleRegion() ); 134 | ConstImageIterator prevIt( imagePrev, imagePrev->GetLargestPossibleRegion() ); 135 | 136 | currIt.GoToBegin(); 137 | prevIt.GoToBegin(); 138 | 139 | while ( !currIt.IsAtEnd() ) 140 | { 141 | float diff = currIt.Get() - prevIt.Get(); 142 | fSumOfDiffsq += diff*diff; 143 | ++currIt; 144 | ++prevIt; 145 | } 146 | 147 | float fCurrentEval = sqrt( fSumOfDiffsq ) / sqrt( fSumOfPETsq ); 148 | std::cout << n << "\t" << fCurrentEval << std::endl; 149 | n++; 150 | 151 | if ( fCurrentEval < this->m_fStopCriterion ) 152 | bStopped = true; 153 | } 154 | std::cout << std::endl; 155 | 156 | 157 | 158 | this->AllocateOutputs(); 159 | 160 | ImageAlgorithm::Copy( imageEstimate.GetPointer(), output.GetPointer(), output->GetRequestedRegion(), 161 | output->GetRequestedRegion() ); 162 | 163 | } 164 | 165 | }// end namespace 166 | 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /parc/FS.csv: -------------------------------------------------------------------------------- 1 | REGION,SOURCE,DST 2 | Unknown,0,0 3 | Left-Cerebral-Exterior,1,0 4 | Left-Cerebral-White-Matter,2,1 5 | Left-Cerebral-Cortex,3,0 6 | Left-Lateral-Ventricle,4,2 7 | Left-Inf-Lat-Vent,5,2 8 | Left-Cerebellum-Exterior,6,0 9 | Left-Cerebellum-White-Matter,7,3 10 | Left-Cerebellum-Cortex,8,4 11 | Left-Thalamus,9,5 12 | Left-Thalamus-Proper,10,5 13 | Left-Caudate,11,6 14 | Left-Putamen,12,7 15 | Left-Pallidum,13,8 16 | 3rd-Ventricle,14,2 17 | 4th-Ventricle,15,53 18 | Brain-Stem,16,9 19 | Left-Hippocampus,17,10 20 | Left-Amygdala,18,11 21 | Left-Insula,19,12 22 | Left-Operculum,20,26 23 | CSF,24,2 24 | Left-Lesion,25,99 25 | Left-Accumbens-area,26,14 26 | Left-Substancia-Nigra,27,0 27 | Left-VentralDC,28,15 28 | Left-undetermined,29,0 29 | Left-vessel,30,0 30 | Left-choroid-plexus,31,16 31 | Right-Cerebral-Exterior,40,0 32 | Right-Cerebral-White-Matter,41,1 33 | Right-Cerebral-Cortex,42,0 34 | Right-Lateral-Ventricle,43,2 35 | Right-Inf-Lat-Vent,44,2 36 | Right-Cerebellum-Exterior,45,0 37 | Right-Cerebellum-White-Matter,46,3 38 | Right-Cerebellum-Cortex,47,4 39 | Right-Thalamus,48,17 40 | Right-Thalamus-Proper,49,17 41 | Right-Caudate,50,18 42 | Right-Putamen,51,19 43 | Right-Pallidum,52,20 44 | Right-Hippocampus,53,21 45 | Right-Amygdala,54,22 46 | Right-Insula,55,23 47 | Right-Operculum,56,31 48 | Right-Lesion,57,99 49 | Right-Accumbens-area,58,24 50 | Right-Substancia-Nigra,59,0 51 | Right-VentralDC,60,15 52 | Right-undetermined,61,0 53 | Right-vessel,62,0 54 | Right-choroid-plexus,63,16 55 | 5th-Ventricle,72,2 56 | WM-hypointensities,77,1 57 | Left-WM-hypointensities,78,1 58 | Right-WM-hypointensities,79,1 59 | non-WM-hypointensities,80,0 60 | Left-non-WM-hypointensities,81,0 61 | Right-non-WM-hypointensities,82,0 62 | Optic-Chiasm,85,25 63 | Corpus_Callosum,192,1 64 | Left-Amygdala-Anterior,96,11 65 | Right-Amygdala-Anterior,97,22 66 | Fornix,250,1 67 | CC_Posterior,251,1 68 | CC_Mid_Posterior,252,1 69 | CC_Central,253,1 70 | CC_Mid_Anterior,254,1 71 | CC_Anterior,255,1 72 | ctx-lh-bankssts,1001,27 73 | ctx-lh-caudalanteriorcingulate,1002,36 74 | ctx-lh-caudalmiddlefrontal,1003,26 75 | ctx-lh-corpuscallosum,1004,44 76 | ctx-lh-cuneus,1005,29 77 | ctx-lh-entorhinal,1006,27 78 | ctx-lh-fusiform,1007,27 79 | ctx-lh-inferiorparietal,1008,28 80 | ctx-lh-inferiortemporal,1009,27 81 | ctx-lh-isthmuscingulate,1010,38 82 | ctx-lh-lateraloccipital,1011,29 83 | ctx-lh-lateralorbitofrontal,1012,26 84 | ctx-lh-lingual,1013,29 85 | ctx-lh-medialorbitofrontal,1014,26 86 | ctx-lh-middletemporal,1015,27 87 | ctx-lh-parahippocampal,1016,30 88 | ctx-lh-paracentral,1017,26 89 | ctx-lh-parsopercularis,1018,26 90 | ctx-lh-parsorbitalis,1019,26 91 | ctx-lh-parstriangularis,1020,26 92 | ctx-lh-pericalcarine,1021,29 93 | ctx-lh-postcentral,1022,28 94 | ctx-lh-posteriorcingulate,1023,39 95 | ctx-lh-precentral,1024,26 96 | ctx-lh-precuneus,1025,28 97 | ctx-lh-rostralanteriorcingulate,1026,37 98 | ctx-lh-rostralmiddlefrontal,1027,26 99 | ctx-lh-superiorfrontal,1028,26 100 | ctx-lh-superiorparietal,1029,28 101 | ctx-lh-superiortemporal,1030,27 102 | ctx-lh-supramarginal,1031,28 103 | ctx-lh-frontalpole,1032,26 104 | ctx-lh-temporalpole,1033,27 105 | ctx-lh-transversetemporal,1034,27 106 | ctx-lh-insula,1035,12 107 | ctx-rh-unknown,2000,0 108 | ctx-rh-bankssts,2001,32 109 | ctx-rh-caudalanteriorcingulate,2002,40 110 | ctx-rh-caudalmiddlefrontal,2003,31 111 | ctx-rh-corpuscallosum,2004,44 112 | ctx-rh-cuneus,2005,34 113 | ctx-rh-entorhinal,2006,32 114 | ctx-rh-fusiform,2007,32 115 | ctx-rh-inferiorparietal,2008,33 116 | ctx-rh-inferiortemporal,2009,32 117 | ctx-rh-isthmuscingulate,2010,42 118 | ctx-rh-lateraloccipital,2011,34 119 | ctx-rh-lateralorbitofrontal,2012,31 120 | ctx-rh-lingual,2013,34 121 | ctx-rh-medialorbitofrontal,2014,31 122 | ctx-rh-middletemporal,2015,32 123 | ctx-rh-parahippocampal,2016,35 124 | ctx-rh-paracentral,2017,31 125 | ctx-rh-parsopercularis,2018,31 126 | ctx-rh-parsorbitalis,2019,31 127 | ctx-rh-parstriangularis,2020,31 128 | ctx-rh-pericalcarine,2021,34 129 | ctx-rh-postcentral,2022,33 130 | ctx-rh-posteriorcingulate,2023,43 131 | ctx-rh-precentral,2024,31 132 | ctx-rh-precuneus,2025,33 133 | ctx-rh-rostralanteriorcingulate,2026,41 134 | ctx-rh-rostralmiddlefrontal,2027,31 135 | ctx-rh-superiorfrontal,2028,31 136 | ctx-rh-superiorparietal,2029,33 137 | ctx-rh-superiortemporal,2030,32 138 | ctx-rh-supramarginal,2031,33 139 | ctx-rh-frontalpole,2032,31 140 | ctx-rh-temporalpole,2033,32 141 | ctx-rh-transversetemporal,2034,32 142 | ctx-rh-insula,2035,23 -------------------------------------------------------------------------------- /parc/GIF_v3.csv: -------------------------------------------------------------------------------- 1 | REGION,SOURCE,DST 2 | Non-Brain Outer Tissue (ignore),0,0 3 | Non-Brain Low (ignore),1,0 4 | Non-Brain Mid (ignore),2,0 5 | Non-Brain High (ignore),3,0 6 | Non-ventricular CSF,4,52 7 | 3rd Ventricle,5,2 8 | 4th Ventricle,12,53 9 | 5th Ventricle,16,53 10 | Right Accumbens Area,24,24 11 | Left Accumbens Area,31,14 12 | Right Amygdala,32,22 13 | Left Amygdala,33,11 14 | Pons,35,51 15 | Brain Stem,36,9 16 | Right Caudate,37,18 17 | Left Caudate,38,6 18 | Right Cerebellum Exterior,39,0 19 | Left Cerebellum Exterior,40,0 20 | Right Cerebellum White Matter,41,3 21 | Left Cerebellum White Matter,42,3 22 | Right Cerebral Exterior,43,0 23 | Left Cerebral Exterior,44,0 24 | 3rd Ventricle (Posterior part),47,2 25 | Right Hippocampus,48,21 26 | Left Hippocampus,49,10 27 | Right Inf Lat Vent,50,2 28 | Left Inf Lat Vent,51,2 29 | Right Lateral Ventricle,52,2 30 | Left Lateral Ventricle,53,2 31 | Right Lesion,54,99 32 | Left Lesion,55,99 33 | Right Pallidum,56,20 34 | Left Pallidum,57,8 35 | Right Putamen,58,19 36 | Left Putamen,59,7 37 | Right Thalamus Proper,60,17 38 | Left Thalamus Proper,61,5 39 | Right Ventral DC,62,15 40 | Left Ventral DC,63,15 41 | Right vessel,64,0 42 | Left vessel,65,0 43 | Right Ventricular Lining,66,2 44 | Left Ventricular Lining,67,2 45 | Optic Chiasm,70,25 46 | Cerebellar Vermal Lobules I-V,72,4 47 | Cerebellar Vermal Lobules VI-VII,73,4 48 | Cerebellar Vermal Lobules VIII-X,74,4 49 | Left Basal Forebrain,76,45 50 | Right Basal Forebrain,77,46 51 | Right Temporal White Matter,81,1 52 | Right Insula White Matter,82,1 53 | Right Cingulate White Matter,83,1 54 | Right Frontal White Matter,84,1 55 | Right Occipital White Matter,85,1 56 | Right Parietal White Matter,86,1 57 | Corpus Callosum,87,1 58 | Left Temporal White Matter,89,1 59 | Left Insula White Matter,90,1 60 | Left Cingulate White Matter,91,1 61 | Left Frontal White Matter,92,1 62 | Left Occipital White Matter,93,1 63 | Left Parietal White Matter,94,1 64 | Right Claustrum,96,49 65 | Left Claustrum,97,50 66 | Right ACgG anterior cingulate gyrus,101,40 67 | Left ACgG anterior cingulate gyrus,102,36 68 | Right AIns anterior insula,103,23 69 | Left AIns anterior insula,104,12 70 | Right AOrG anterior orbital gyrus,105,31 71 | Left AOrG anterior orbital gyrus,106,26 72 | Right AnG angular gyrus,107,33 73 | Left AnG angular gyrus,108,28 74 | Right Calc calcarine cortex,109,34 75 | Left Calc calcarine cortex,110,29 76 | Right CO central operculum,113,32 77 | Left CO central operculum,114,27 78 | Right Cun cuneus,115,34 79 | Left Cun cuneus,116,29 80 | Right Ent entorhinal area,117,32 81 | Left Ent entorhinal area,118,27 82 | Right FO frontal operculum,119,31 83 | Left FO frontal operculum,120,26 84 | Right FRP frontal pole,121,31 85 | Left FRP frontal pole,122,26 86 | Right FuG fusiform gyrus,123,32 87 | Left FuG fusiform gyrus,124,27 88 | Right GRe gyrus rectus,125,31 89 | Left GRe gyrus rectus,126,26 90 | Right IOG inferior occipital gyrus,129,34 91 | Left IOG inferior occipital gyrus,130,29 92 | Right ITG inferior temporal gyrus,133,32 93 | Left ITG inferior temporal gyrus,134,27 94 | Right LiG lingual gyrus,135,34 95 | Left LiG lingual gyrus,136,29 96 | Right LOrG lateral orbital gyrus,137,31 97 | Left LOrG lateral orbital gyrus,138,26 98 | Right MCgG middle cingulate gyrus,139,42 99 | Left MCgG middle cingulate gyrus,140,38 100 | Right MFC medial frontal cortex,141,31 101 | Left MFC medial frontal cortex,142,26 102 | Right MFG middle frontal gyrus,143,31 103 | Left MFG middle frontal gyrus,144,26 104 | Right MOG middle occipital gyrus,145,34 105 | Left MOG middle occipital gyrus,146,29 106 | Right MOrG medial orbital gyrus,147,31 107 | Left MOrG medial orbital gyrus,148,26 108 | Right MPoG postcentral gyrus medial segment,149,33 109 | Left MPoG postcentral gyrus medial segment,150,28 110 | Right MPrG precentral gyrus medial segment,151,31 111 | Left MPrG precentral gyrus medial segment,152,26 112 | Right MSFG superior frontal gyrus medial segment,153,31 113 | Left MSFG superior frontal gyrus medial segment,154,26 114 | Right MTG middle temporal gyrus,155,32 115 | Left MTG middle temporal gyrus,156,27 116 | Right OCP occipital pole,157,34 117 | Left OCP occipital pole,158,29 118 | Right OFuG occipital fusiform gyrus,161,34 119 | Left OFuG occipital fusiform gyrus,162,29 120 | Right OpIFG opercular part of the inferior frontal gyrus,163,31 121 | Left OpIFG opercular part of the inferior frontal gyrus,164,26 122 | Right OrIFG orbital part of the inferior frontal gyrus,165,31 123 | Left OrIFG orbital part of the inferior frontal gyrus,166,26 124 | Right PCgG posterior cingulate gyrus,167,43 125 | Left PCgG posterior cingulate gyrus,168,39 126 | Right PCu precuneus,169,33 127 | Left PCu precuneus,170,28 128 | Right PHG parahippocampal gyrus,171,35 129 | Left PHG parahippocampal gyrus,172,30 130 | Right PIns posterior insula,173,23 131 | Left PIns posterior insula,174,12 132 | Right PO parietal operculum,175,33 133 | Left PO parietal operculum,176,28 134 | Right PoG postcentral gyrus,177,33 135 | Left PoG postcentral gyrus,178,28 136 | Right POrG posterior orbital gyrus,179,21 137 | Left POrG posterior orbital gyrus,180,26 138 | Right PP planum polare,181,32 139 | Left PP planum polare,182,27 140 | Right PrG precentral gyrus,183,31 141 | Left PrG precentral gyrus,184,26 142 | Right PT planum temporale,185,32 143 | Left PT planum temporale,186,27 144 | Right SCA subcallosal area,187,47 145 | Left SCA subcallosal area,188,48 146 | Right SFG superior frontal gyrus,191,31 147 | Left SFG superior frontal gyrus,192,26 148 | Right SMC supplementary motor cortex,193,31 149 | Left SMC supplementary motor cortex,194,26 150 | Right SMG supramarginal gyrus,195,33 151 | Left SMG supramarginal gyrus,196,28 152 | Right SOG superior occipital gyrus,197,34 153 | Left SOG superior occipital gyrus,198,29 154 | Right SPL superior parietal lobule,199,33 155 | Left SPL superior parietal lobule,200,28 156 | Right STG superior temporal gyrus,201,32 157 | Left STG superior temporal gyrus,202,27 158 | Right TMP temporal pole,203,32 159 | Left TMP temporal pole,204,27 160 | Right TrIFG triangular part of the inferior frontal gyrus,205,31 161 | Left TrIFG triangular part of the inferior frontal gyrus,206,26 162 | Right TTG transverse temporal gyrus,207,32 163 | Left TTG transverse temporal gyrus,208,27 -------------------------------------------------------------------------------- /parc/README.md: -------------------------------------------------------------------------------- 1 | # PETPVC mask-related tools 2 | 3 | ## Relabeling an image 4 | 5 | The program ```pvc_relabel``` can be used to transform a 3-D parcellation from region definition to another. The mapping is controlled by a CSV file which is passed as one of the inputs. 6 | 7 | ### Usage 8 | ``` 9 | pvc_relabel -i -o --parc --type 10 | ``` 11 | where `````` is the 3-D image of parcellated regions, `````` is the newly labeled image, `````` is a comma separated file (see below) that maps from one labelling scheme to another and `````` refers to the desired mapping contained in a column of the ``````. 12 | 13 | ### CSV file definition 14 | 15 | An example mapping from FreeSurfer's ```aparc+aseg``` is provided in ```parc/FS.csv```. ```pvc_relabel``` always expects the first row to comprise the column headers: 16 | 17 | ``` 18 | REGION,SOURCE,XXX 19 | ``` 20 | 21 | The ```REGION``` column contains a text description of the region (optional) and ```SOURCE``` holds the numeric ID of the original label (mandatory). The header ```XXX``` can be any desired name for the new mapping scheme. In ```FS.csv``` this is called ```DST```. The column ***must*** contain the new numeric ID to be applied. It is this name that must be passed as the `````` when executing ```pvc_relabel```. Multiple columns can be added to the CSV file for different applications: 22 | 23 | ``` 24 | REGION,SOURCE,MYSCHEME1,MYSCHEME2 25 | ``` 26 | Calling ```pvc_relabel``` with ```--type MYSCHEME1``` will produce an image with the label scheme defined by the ```MYSCHEME1``` and ```--type MYSCHEME2``` will use the second column. 27 | 28 | Note that ```FS.csv``` is an example and that region definitions should be created and validated for each application. 29 | 30 | ## Producing a 4-D mask file from 3-D labels 31 | 32 | Most of the methods provided in the toolbox expect a 4-D mask image as input. The application ```pvc_make4d``` will create a 4-D image from a 3-D label image. Each volume in the 4-D file represents a single region. The set of labels do not need to be continuous. ```pvc_make4d``` will write the volumes in ascending order. 33 | 34 | ### Usage 35 | ``` 36 | pvc_make4d -i <3DMASK> -o <4DMASK> 37 | ``` 38 | where ```<3DMASK>``` is a single 3-D volume of labels and ```<4DMASK>``` is the output 4-D file. -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | /* 2 | PETPVC package for the Nix package manager. 3 | 4 | `shell.nix` is used for development with nix-shell. 5 | See `derivation.nix` for full description. 6 | 7 | Licensing 8 | --------- 9 | 10 | This file is distributed as part of PETPVC. 11 | 12 | Author: Ashley Gillman 13 | 14 | Copyright 2018 Commonwealth Scientific and Industrial Research 15 | Organisation's Australian eHealth Research Centre 16 | 17 | Licensed under the Apache License, Version 2.0 (the "License"); 18 | you may not use this file except in compliance with the License. 19 | You may obtain a copy of the License at 20 | 21 | http://www.apache.org/licenses/LICENSE-2.0 22 | 23 | Unless required by applicable law or agreed to in writing, software 24 | distributed under the License is distributed on an "AS IS" BASIS, 25 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26 | See the License for the specific language governing permissions and 27 | limitations under the License. 28 | */ 29 | 30 | { pkgs ? import {} }: 31 | 32 | # Add cmakeCurses so can use ccmake in development 33 | with pkgs; 34 | (callPackage ./derivation.nix {}).overrideDerivation ( 35 | oldAttrs: { 36 | buildInputs = oldAttrs.buildInputs ++ [ cmakeCurses ]; 37 | }) 38 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #========================================================================= 2 | # Author: Benjamin A. Thomas 3 | # 4 | # Copyright University College London 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0.txt 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | #========================================================================= 19 | 20 | ADD_EXECUTABLE(pvc_gtm GTM.cxx ) 21 | TARGET_LINK_LIBRARIES(pvc_gtm ${ITK_LIBRARIES}) 22 | 23 | ADD_EXECUTABLE(pvc_labbe Labbe.cxx ) 24 | TARGET_LINK_LIBRARIES(pvc_labbe ${ITK_LIBRARIES}) 25 | 26 | ADD_EXECUTABLE(pvc_mtc MTC.cxx ) 27 | TARGET_LINK_LIBRARIES(pvc_mtc ${ITK_LIBRARIES}) 28 | 29 | ADD_EXECUTABLE(pvc_rbv RBV.cxx ) 30 | TARGET_LINK_LIBRARIES(pvc_rbv ${ITK_LIBRARIES}) 31 | 32 | ADD_EXECUTABLE(pvc_iy IterativeYang.cxx ) 33 | TARGET_LINK_LIBRARIES(pvc_iy ${ITK_LIBRARIES}) 34 | 35 | ADD_EXECUTABLE(pvc_diy DiscreteIY.cxx ) 36 | TARGET_LINK_LIBRARIES(pvc_diy ${ITK_LIBRARIES}) 37 | 38 | ADD_EXECUTABLE(pvc_mg MullerGartner.cxx ) 39 | TARGET_LINK_LIBRARIES(pvc_mg ${ITK_LIBRARIES}) 40 | 41 | ADD_EXECUTABLE(pvc_vc VanCittert.cxx ) 42 | TARGET_LINK_LIBRARIES(pvc_vc ${ITK_LIBRARIES}) 43 | 44 | ADD_EXECUTABLE(pvc_rl RichardsonLucy.cxx ) 45 | TARGET_LINK_LIBRARIES(pvc_rl ${ITK_LIBRARIES}) 46 | 47 | ADD_EXECUTABLE(pvc_stc STC.cxx ) 48 | TARGET_LINK_LIBRARIES(pvc_stc ${ITK_LIBRARIES}) 49 | 50 | ADD_EXECUTABLE(petpvc PETPVC.cxx ) 51 | TARGET_LINK_LIBRARIES(petpvc ${ITK_LIBRARIES}) 52 | 53 | ADD_EXECUTABLE(pvc_simulate Simulate.cxx ) 54 | TARGET_LINK_LIBRARIES(pvc_simulate ${ITK_LIBRARIES}) 55 | 56 | ADD_EXECUTABLE(pvc_make4d Make4D.cxx ) 57 | TARGET_LINK_LIBRARIES(pvc_make4d ${ITK_LIBRARIES}) 58 | 59 | ADD_EXECUTABLE(pvc_relabel Relabel.cxx ) 60 | TARGET_LINK_LIBRARIES(pvc_relabel ${ITK_LIBRARIES}) 61 | 62 | INSTALL(TARGETS pvc_gtm pvc_labbe pvc_rbv pvc_iy 63 | pvc_diy pvc_mg pvc_mtc pvc_vc pvc_rl pvc_stc 64 | petpvc pvc_simulate pvc_make4d 65 | pvc_relabel DESTINATION bin 66 | COMPONENT applications) 67 | -------------------------------------------------------------------------------- /src/GTM.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | GTM.cxx 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2013 Institute of Nuclear Medicine, University College London. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | This program implements the Geometric Transfer Matrix (GTM) partial volume 21 | correction (PVC) technique. The method is described in: 22 | Rousset, O. G. and Ma, Y. and Evans, A. C. (1998). "Correction for 23 | partial volume effects in PET: principle and validation". Journal of 24 | Nuclear Medicine, 39(5):904-11. 25 | */ 26 | 27 | #include "EnvironmentInfo.h" 28 | 29 | #include "itkImage.h" 30 | #include "itkImageFileReader.h" 31 | #include "itkImageFileWriter.h" 32 | #include 33 | 34 | #include "petpvcRoussetPVCImageFilter.h" 35 | 36 | typedef itk::Vector VectorType; 37 | typedef itk::Image MaskImageType; 38 | typedef itk::Image PETImageType; 39 | 40 | typedef itk::ImageFileReader MaskReaderType; 41 | typedef itk::ImageFileReader PETReaderType; 42 | typedef itk::ImageFileWriter PETWriterType; 43 | 44 | //Produces the text for the acknowledgments dialog in Slicer. 45 | std::string getAcknowledgments(void); 46 | 47 | using namespace petpvc; 48 | 49 | int main(int argc, char *argv[]) 50 | { 51 | 52 | itk::ImageToImageFilterCommon::SetGlobalDefaultCoordinateTolerance( 1e-2 ); 53 | itk::ImageToImageFilterCommon::SetGlobalDefaultDirectionTolerance( 1e-2 ); 54 | 55 | const char * const AUTHOR = "Benjamin A. Thomas"; 56 | const char * const APP_TITLE = "Geometric Transfer Matrix (GTM) PVC"; 57 | 58 | std::stringstream version_number; 59 | version_number << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_PATCH; 60 | const std::string VERSION_NO = version_number.str(); 61 | 62 | typedef petpvc::RoussetPVCImageFilter FilterType; 63 | 64 | PETImageType::Pointer image = PETImageType::New(); 65 | 66 | //Setting up command line argument list. 67 | MetaCommand command; 68 | 69 | command.SetVersion(VERSION_NO.c_str()); 70 | command.SetAuthor(AUTHOR); 71 | command.SetName(APP_TITLE); 72 | command.SetDescription( 73 | "Performs Geometric Transfer Matrix (GTM) partial volume correction"); 74 | 75 | std::string sAcks = getAcknowledgments(); 76 | command.SetAcknowledgments(sAcks.c_str()); 77 | 78 | command.SetCategory("PETPVC"); 79 | 80 | command.AddField("petfile", "PET filename", MetaCommand::IMAGE, MetaCommand::DATA_IN); 81 | command.AddField("maskfile", "mask filename", MetaCommand::IMAGE, MetaCommand::DATA_IN); 82 | //command.AddField("outputfile", "output filename", MetaCommand::FILE, MetaCommand::DATA_OUT); 83 | 84 | command.SetOption("FWHMx", "x", true, 85 | "The full-width at half maximum in mm along x-axis"); 86 | command.AddOptionField("FWHMx", "X", MetaCommand::FLOAT, true, ""); 87 | 88 | command.SetOption("FWHMy", "y", true, 89 | "The full-width at half maximum in mm along y-axis"); 90 | command.AddOptionField("FWHMy", "Y", MetaCommand::FLOAT, true, ""); 91 | 92 | command.SetOption("FWHMz", "z", true, 93 | "The full-width at half maximum in mm along z-axis"); 94 | command.AddOptionField("FWHMz", "Z", MetaCommand::FLOAT, true, ""); 95 | 96 | command.SetOption("debug", "d", false,"Prints debug information"); 97 | command.SetOptionLongTag("debug", "debug"); 98 | 99 | //Parse command line. 100 | if (!command.Parse(argc, argv)) { 101 | return EXIT_FAILURE; 102 | } 103 | 104 | //Get image filenames 105 | std::string sPETFileName = command.GetValueAsString("petfile"); 106 | std::string sMaskFileName = command.GetValueAsString("maskfile"); 107 | //std::string sOutputFileName = command.GetValueAsString("outputfile"); 108 | 109 | //Get values for PSF. 110 | float fFWHM_x = command.GetValueAsFloat("FWHMx", "X"); 111 | float fFWHM_y = command.GetValueAsFloat("FWHMy", "Y"); 112 | float fFWHM_z = command.GetValueAsFloat("FWHMz", "Z"); 113 | 114 | //Make vector of FWHM in x,y and z. 115 | VectorType vFWHM; 116 | vFWHM[0] = fFWHM_x; 117 | vFWHM[1] = fFWHM_y; 118 | vFWHM[2] = fFWHM_z; 119 | 120 | //Toggle debug mode 121 | bool bDebug = command.GetValueAsBool("debug"); 122 | 123 | //Create reader for mask image. 124 | MaskReaderType::Pointer maskReader = MaskReaderType::New(); 125 | maskReader->SetFileName(sMaskFileName); 126 | 127 | //Try to read mask. 128 | try { 129 | maskReader->Update(); 130 | } catch (itk::ExceptionObject & err) { 131 | std::cerr << "[Error]\tCannot read mask input file: " << sMaskFileName 132 | << err << std::endl; 133 | return EXIT_FAILURE; 134 | } 135 | 136 | //Create reader for PET image. 137 | PETReaderType::Pointer petReader = PETReaderType::New(); 138 | petReader->SetFileName(sPETFileName); 139 | 140 | //Try to read PET. 141 | try { 142 | petReader->Update(); 143 | } catch (itk::ExceptionObject & err) { 144 | std::cerr << "[Error]\tCannot read PET input file: " << sPETFileName 145 | << err << std::endl; 146 | return EXIT_FAILURE; 147 | } 148 | 149 | //Calculate the variance for a given FWHM. 150 | VectorType vVariance; 151 | vVariance = vFWHM / (2.0 * sqrt(2.0 * log(2.0))); 152 | //std::cout << vVariance << std::endl; 153 | 154 | try { 155 | VectorType vVoxelSize = petReader->GetOutput()->GetSpacing();; 156 | } catch (itk::ExceptionObject& err) { 157 | std::cerr << "[Error]\tCannot read PET voxel sizes from input file: " << sPETFileName 158 | << err 159 | << std::endl; 160 | return EXIT_FAILURE; 161 | } 162 | //std::cout << vVoxelSize << std::endl; 163 | 164 | vVariance[0] = pow(vVariance[0], 2); 165 | vVariance[1] = pow(vVariance[1], 2); 166 | vVariance[2] = pow(vVariance[2], 2); 167 | 168 | FilterType::Pointer roussetFilter = FilterType::New(); 169 | roussetFilter->SetInput( petReader->GetOutput() ); 170 | roussetFilter->SetMaskInput( maskReader->GetOutput() ); 171 | roussetFilter->SetPSF( vVariance ); 172 | roussetFilter->SetVerbose( bDebug ); 173 | try { 174 | roussetFilter->Update(); 175 | } 176 | catch (itk::ExceptionObject& err) { 177 | std::cerr << err << std::endl; 178 | return EXIT_FAILURE; 179 | } 180 | 181 | return EXIT_SUCCESS; 182 | } 183 | 184 | std::string getAcknowledgments(void) 185 | { 186 | //Produces acknowledgments string for 3DSlicer. 187 | std::string sAck = "This program implements the Geometric Transfer Matrix (GTM) partial volume correction (PVC) technique.\n" 188 | "The method is described in:\n" 189 | "\tRousset, O. G. and Ma, Y. and Evans, A. C. (1998). \"Correction for\n" 190 | "\tpartial volume effects in PET: principle and validation\". Journal of\n" 191 | "\tNuclear Medicine, 39(5):904-11."; 192 | 193 | return sAck; 194 | } 195 | 196 | -------------------------------------------------------------------------------- /src/Labbe.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | Labbe.cxx 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Institute of Nuclear Medicine, University College London. 7 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | This program implements the Labbe partial volume 22 | correction (PVC) technique. The method is described in: 23 | Labbe, C., M. Koepp, J. Ashburner, T. Spinks, M. Richardson, 24 | J. Duncan, and V. Cunningham., (1998). "Absolute PET quantification with correction for 25 | partial volume effects within cerebral structures." In Carson RE D.-W.M., Herscovitch P. ed. 26 | Quantitative Functional Brain Imaging with Positron Emission Tomography. San Diego, CA: 27 | Academic Press, 59-66. 28 | 29 | */ 30 | 31 | #include "EnvironmentInfo.h" 32 | 33 | #include "itkImage.h" 34 | #include "itkImageFileReader.h" 35 | #include "itkImageFileWriter.h" 36 | #include 37 | 38 | #include "petpvcLabbePVCImageFilter.h" 39 | 40 | typedef itk::Vector VectorType; 41 | typedef itk::Image MaskImageType; 42 | typedef itk::Image PETImageType; 43 | 44 | typedef itk::ImageFileReader MaskReaderType; 45 | typedef itk::ImageFileReader PETReaderType; 46 | typedef itk::ImageFileWriter PETWriterType; 47 | 48 | //Produces the text for the acknowledgments dialog in Slicer. 49 | std::string getAcknowledgments(void); 50 | 51 | using namespace petpvc; 52 | 53 | int main(int argc, char *argv[]) 54 | { 55 | itk::ImageToImageFilterCommon::SetGlobalDefaultCoordinateTolerance( 1e-2 ); 56 | itk::ImageToImageFilterCommon::SetGlobalDefaultDirectionTolerance( 1e-2 ); 57 | 58 | const char * const AUTHOR = "Benjamin A. Thomas"; 59 | const char * const APP_TITLE = "Labbe PVC"; 60 | 61 | std::stringstream version_number; 62 | version_number << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_PATCH; 63 | const std::string VERSION_NO = version_number.str(); 64 | 65 | typedef petpvc::LabbePVCImageFilter FilterType; 66 | 67 | PETImageType::Pointer image = PETImageType::New(); 68 | 69 | //Setting up command line argument list. 70 | MetaCommand command; 71 | 72 | command.SetVersion(VERSION_NO.c_str()); 73 | command.SetAuthor(AUTHOR); 74 | command.SetName(APP_TITLE); 75 | command.SetDescription( 76 | "Performs Labbe partial volume correction"); 77 | 78 | std::string sAcks = getAcknowledgments(); 79 | command.SetAcknowledgments(sAcks.c_str()); 80 | 81 | command.SetCategory("PETPVC"); 82 | 83 | command.AddField("petfile", "PET filename", MetaCommand::IMAGE, MetaCommand::DATA_IN); 84 | command.AddField("maskfile", "mask filename", MetaCommand::IMAGE, MetaCommand::DATA_IN); 85 | //command.AddField("outputfile", "output filename", MetaCommand::FILE, MetaCommand::DATA_OUT); 86 | 87 | command.SetOption("FWHMx", "x", true, 88 | "The full-width at half maximum in mm along x-axis"); 89 | command.AddOptionField("FWHMx", "X", MetaCommand::FLOAT, true, ""); 90 | 91 | command.SetOption("FWHMy", "y", true, 92 | "The full-width at half maximum in mm along y-axis"); 93 | command.AddOptionField("FWHMy", "Y", MetaCommand::FLOAT, true, ""); 94 | 95 | command.SetOption("FWHMz", "z", true, 96 | "The full-width at half maximum in mm along z-axis"); 97 | command.AddOptionField("FWHMz", "Z", MetaCommand::FLOAT, true, ""); 98 | 99 | command.SetOption("debug", "d", false,"Prints debug information"); 100 | command.SetOptionLongTag("debug", "debug"); 101 | 102 | //Parse command line. 103 | if (!command.Parse(argc, argv)) { 104 | return EXIT_FAILURE; 105 | } 106 | 107 | //Get image filenames 108 | std::string sPETFileName = command.GetValueAsString("petfile"); 109 | std::string sMaskFileName = command.GetValueAsString("maskfile"); 110 | //std::string sOutputFileName = command.GetValueAsString("outputfile"); 111 | 112 | //Get values for PSF. 113 | float fFWHM_x = command.GetValueAsFloat("FWHMx", "X"); 114 | float fFWHM_y = command.GetValueAsFloat("FWHMy", "Y"); 115 | float fFWHM_z = command.GetValueAsFloat("FWHMz", "Z"); 116 | 117 | //Make vector of FWHM in x,y and z. 118 | VectorType vFWHM; 119 | vFWHM[0] = fFWHM_x; 120 | vFWHM[1] = fFWHM_y; 121 | vFWHM[2] = fFWHM_z; 122 | 123 | //Toggle debug mode 124 | bool bDebug = command.GetValueAsBool("debug"); 125 | 126 | //Create reader for mask image. 127 | MaskReaderType::Pointer maskReader = MaskReaderType::New(); 128 | maskReader->SetFileName(sMaskFileName); 129 | 130 | //Try to read mask. 131 | try { 132 | maskReader->Update(); 133 | } catch (itk::ExceptionObject & err) { 134 | std::cerr << "[Error]\tCannot read mask input file: " << sMaskFileName 135 | << std::endl; 136 | return EXIT_FAILURE; 137 | } 138 | 139 | //Create reader for PET image. 140 | PETReaderType::Pointer petReader = PETReaderType::New(); 141 | petReader->SetFileName(sPETFileName); 142 | 143 | //Try to read PET. 144 | try { 145 | petReader->Update(); 146 | } catch (itk::ExceptionObject & err) { 147 | std::cerr << "[Error]\tCannot read PET input file: " << sPETFileName 148 | << std::endl; 149 | return EXIT_FAILURE; 150 | } 151 | 152 | //Calculate the variance for a given FWHM. 153 | VectorType vVariance; 154 | vVariance = vFWHM / (2.0 * sqrt(2.0 * log(2.0))); 155 | //std::cout << vVariance << std::endl; 156 | 157 | VectorType vVoxelSize = petReader->GetOutput()->GetSpacing(); 158 | //std::cout << vVoxelSize << std::endl; 159 | 160 | vVariance[0] = pow(vVariance[0], 2); 161 | vVariance[1] = pow(vVariance[1], 2); 162 | vVariance[2] = pow(vVariance[2], 2); 163 | 164 | FilterType::Pointer labbeFilter = FilterType::New(); 165 | labbeFilter->SetInput( petReader->GetOutput() ); 166 | labbeFilter->SetMaskInput( maskReader->GetOutput() ); 167 | labbeFilter->SetPSF( vVariance ); 168 | labbeFilter->SetVerbose( bDebug ); 169 | labbeFilter->Update(); 170 | 171 | return EXIT_SUCCESS; 172 | } 173 | 174 | std::string getAcknowledgments(void) 175 | { 176 | //Produces acknowledgments string for 3DSlicer. 177 | std::string sAck = "This program implements the Labbe partial volume correction (PVC) technique.\n" 178 | "The method is described in:\n" 179 | "\tLabbe, C., M. Koepp, J. Ashburner, T. Spinks, M. Richardson,\n" 180 | "\tJ. Duncan, and V. Cunningham., (1998). \"Absolute PET quantification with correction for\n" 181 | "\tpartial volume effects within cerebral structures.\" In Carson RE D.-W.M., Herscovitch P. ed.\n" 182 | "\tQuantitative Functional Brain Imaging with Positron Emission Tomography. San Diego, CA:\n" 183 | "\tAcademic Press, 59-66."; 184 | 185 | return sAck; 186 | } 187 | 188 | -------------------------------------------------------------------------------- /src/Make4D.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | Make4D.cxx 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2017 Institute of Nuclear Medicine, University College London. 7 | Copyright 2014 Clinical Imaging Research Centre, A*STAR-NUS. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | Takes a 3-D mask image and creates a 4-D image with 1 volume per label. 22 | 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include "EnvironmentInfo.h" 39 | 40 | typedef itk::Image ImageType; 41 | typedef itk::Image MaskImageType; 42 | typedef itk::Image ImageType4D; 43 | 44 | typedef itk::ImageFileReader ReaderType; 45 | typedef itk::ImageFileWriter WriterType; 46 | 47 | typedef itk::ImageRegionIterator ImageIterator; 48 | typedef itk::ImageRegionConstIterator ConstImageIterator; 49 | 50 | typedef itk::LabelGeometryImageFilter LabelGeometryImageFilterType; 51 | typedef itk::BinaryThresholdImageFilter BinaryThresholdImageFilterType; 52 | 53 | typedef itk::JoinSeriesImageFilter JoinSeriesImageFilterType; 54 | 55 | int main(int argc, char *argv[]) 56 | { 57 | 58 | const char * const AUTHOR = "Benjamin A. Thomas"; 59 | const char * const APP_TITLE = "3-D to 4-D mask creation"; 60 | 61 | std::stringstream version_number; 62 | version_number << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_PATCH; 63 | const std::string VERSION_NO = version_number.str(); 64 | 65 | MetaCommand command; 66 | 67 | command.DisableDeprecatedWarnings(); 68 | 69 | command.SetVersion(VERSION_NO.c_str()); 70 | command.SetAuthor(AUTHOR); 71 | command.SetName(APP_TITLE); 72 | command.SetDescription("Creates a 4-D region mask image from a 3-D mask image"); 73 | command.SetAcknowledgments(" "); 74 | command.SetCategory("PETPVC"); 75 | 76 | command.SetOption("Input", "i", true, "Input file"); 77 | command.AddOptionField("Input", "infilename", MetaCommand::FILE, true, "", "", MetaCommand::DATA_IN); 78 | 79 | command.SetOption("Output", "o", true, "Output file"); 80 | command.AddOptionField("Output", "outfilename", MetaCommand::FILE, true, "", "", MetaCommand::DATA_OUT); 81 | 82 | if (!command.Parse(argc, argv)) 83 | { 84 | return EXIT_FAILURE; 85 | } 86 | 87 | std::string inFileName = command.GetValueAsString("Input", "infilename"); 88 | std::string outputFileName = command.GetValueAsString("Output", "outfilename"); 89 | 90 | std::cout << "Input file: " << inFileName << std::endl; 91 | std::cout << "Output file: " << outputFileName << std::endl; 92 | 93 | ReaderType::Pointer reader = ReaderType::New(); 94 | reader->SetFileName(inFileName); 95 | 96 | try 97 | { 98 | reader->Update(); 99 | } 100 | catch (itk::ExceptionObject &ex) 101 | { 102 | std::cerr << "[Error]\tImage file: " << inFileName << " cannot be loaded!" << std::endl; 103 | return EXIT_FAILURE; 104 | } 105 | 106 | ImageType::Pointer inputImage = reader->GetOutput(); 107 | 108 | LabelGeometryImageFilterType::Pointer labelGeometryFilter = LabelGeometryImageFilterType::New(); 109 | LabelGeometryImageFilterType::Pointer labelGeometryImageFilter = LabelGeometryImageFilterType::New(); 110 | labelGeometryImageFilter->SetInput(inputImage); 111 | labelGeometryImageFilter->SetIntensityInput(inputImage); 112 | 113 | labelGeometryImageFilter->Update(); 114 | LabelGeometryImageFilterType::LabelsType allLabels = 115 | labelGeometryImageFilter->GetLabels(); 116 | 117 | std::cout << "No. of labels found:\t" << allLabels.size() << std::endl; 118 | 119 | BinaryThresholdImageFilterType::Pointer binThreshFilter = BinaryThresholdImageFilterType::New(); 120 | binThreshFilter->SetInput(inputImage); 121 | binThreshFilter->SetInsideValue(1); 122 | binThreshFilter->SetOutsideValue(0); 123 | 124 | JoinSeriesImageFilterType::Pointer joinFilter = JoinSeriesImageFilterType::New(); 125 | ImageType::Pointer maskImage = ImageType::New(); 126 | 127 | std::cout << "Mapping:" << std::endl; 128 | 129 | for (int i = 0; i < allLabels.size(); i++) 130 | { 131 | std::cout << "\tID: " << allLabels[i] << " -> volume " << i+1 << std::endl; 132 | int labelValue = allLabels[i]; 133 | binThreshFilter->SetLowerThreshold(labelValue); 134 | binThreshFilter->SetUpperThreshold(labelValue); 135 | binThreshFilter->Update(); 136 | 137 | maskImage = binThreshFilter->GetOutput(); 138 | 139 | joinFilter->SetInput(i, maskImage); 140 | maskImage->DisconnectPipeline(); 141 | } 142 | 143 | WriterType::Pointer writer = WriterType::New(); 144 | writer->SetFileName(outputFileName); 145 | writer->SetInput(joinFilter->GetOutput()); 146 | 147 | try 148 | { 149 | writer->Update(); 150 | } 151 | catch (itk::ExceptionObject &ex) 152 | { 153 | std::cerr << "[Error]\tCannot write output image: " << outputFileName << "!" << std::endl; 154 | return EXIT_FAILURE; 155 | } 156 | 157 | return EXIT_SUCCESS; 158 | } 159 | -------------------------------------------------------------------------------- /src/RichardsonLucy.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | RichardsonLucy.cxx 3 | 4 | Author: Benjamin A. Thomas 5 | 6 | Copyright 2015 Clinical Imaging Research Centre, A*STAR-NUS. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | This program implements the Richardson-Lucy (RL) partial volume correction 21 | technique. Please cite the following paper: 22 | 23 | Tohka, J. and Reilhac A., (2008). "Deconvolution-based partial volume 24 | correction in Raclopride-PET and Monte Carlo comparison to MR-based 25 | method", NeuroImage, vol. 39. 1570--1584. 26 | 27 | */ 28 | 29 | #include "EnvironmentInfo.h" 30 | 31 | #include "itkImage.h" 32 | #include "itkImageFileReader.h" 33 | #include "itkImageFileWriter.h" 34 | #include 35 | 36 | #include "petpvcRLPVCImageFilter.h" 37 | 38 | typedef itk::Vector VectorType; 39 | typedef itk::Image PETImageType; 40 | 41 | typedef itk::ImageFileReader PETReaderType; 42 | typedef itk::ImageFileWriter PETWriterType; 43 | 44 | //Produces the text for the acknowledgments dialog in Slicer. 45 | std::string getAcknowledgments(void); 46 | 47 | int main(int argc, char *argv[]) 48 | { 49 | 50 | itk::ImageToImageFilterCommon::SetGlobalDefaultCoordinateTolerance( 1e-2 ); 51 | itk::ImageToImageFilterCommon::SetGlobalDefaultDirectionTolerance( 1e-2 ); 52 | 53 | const char * const AUTHOR = "Benjamin A. Thomas"; 54 | const char * const APP_TITLE = "Richardson-Lucy (RL) PVC"; 55 | 56 | std::stringstream version_number; 57 | version_number << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_PATCH; 58 | const std::string VERSION_NO = version_number.str(); 59 | 60 | typedef petpvc::RichardsonLucyPVCImageFilter< PETImageType > FilterType; 61 | 62 | //Setting up command line argument list. 63 | MetaCommand command; 64 | 65 | command.SetVersion(VERSION_NO.c_str()); 66 | command.SetAuthor(AUTHOR); 67 | command.SetName(APP_TITLE); 68 | command.SetDescription( 69 | "Performs Richardson-Lucy (RL) partial volume correction"); 70 | 71 | std::string sAcks = getAcknowledgments(); 72 | command.SetAcknowledgments(sAcks.c_str()); 73 | 74 | command.SetCategory("PETPVC"); 75 | 76 | command.AddField("petfile", "PET filename", MetaCommand::IMAGE, MetaCommand::DATA_IN); 77 | command.AddField("outputfile", "output filename", MetaCommand::IMAGE, MetaCommand::DATA_OUT); 78 | 79 | command.SetOption("FWHMx", "x", true, 80 | "The full-width at half maximum in mm along x-axis"); 81 | command.AddOptionField("FWHMx", "X", MetaCommand::FLOAT, true, ""); 82 | 83 | command.SetOption("FWHMy", "y", true, 84 | "The full-width at half maximum in mm along y-axis"); 85 | command.AddOptionField("FWHMy", "Y", MetaCommand::FLOAT, true, ""); 86 | 87 | command.SetOption("FWHMz", "z", true, 88 | "The full-width at half maximum in mm along z-axis"); 89 | command.AddOptionField("FWHMz", "Z", MetaCommand::FLOAT, true, ""); 90 | 91 | command.SetOption("Iterations", "i", false, "Number of iterations"); 92 | command.SetOptionLongTag("Iterations", "iter"); 93 | command.AddOptionField("Iterations", "Val", MetaCommand::INT, false, "10"); 94 | 95 | //command.SetOption("Stop", "s", false, "Stopping criterion"); 96 | //command.SetOptionLongTag("Stop", "stop"); 97 | //command.AddOptionField("Stop", "stopval", MetaCommand::FLOAT, false, "-3e+6"); 98 | 99 | command.SetOption("debug", "d", false,"Prints debug information"); 100 | command.SetOptionLongTag("debug", "debug"); 101 | 102 | //Parse command line. 103 | if (!command.Parse(argc, argv)) { 104 | return EXIT_FAILURE; 105 | } 106 | 107 | //Get image filenames 108 | std::string sPETFileName = command.GetValueAsString("petfile"); 109 | std::string sOutputFileName = command.GetValueAsString("outputfile"); 110 | 111 | //Get values for PSF. 112 | float fFWHM_x = command.GetValueAsFloat("FWHMx", "X"); 113 | float fFWHM_y = command.GetValueAsFloat("FWHMy", "Y"); 114 | float fFWHM_z = command.GetValueAsFloat("FWHMz", "Z"); 115 | 116 | //Get number of iterations 117 | int nNumOfIters = command.GetValueAsInt("Iterations", "Val"); 118 | 119 | //Get value for stopping criterion. 120 | //float fStop = command.GetValueAsFloat("Stop", "stopval"); 121 | 122 | //Make vector of FWHM in x,y and z. 123 | VectorType vFWHM; 124 | vFWHM[0] = fFWHM_x; 125 | vFWHM[1] = fFWHM_y; 126 | vFWHM[2] = fFWHM_z; 127 | 128 | //Toggle debug mode 129 | bool bDebug = command.GetValueAsBool("debug"); 130 | 131 | //Create reader for PET image. 132 | PETReaderType::Pointer petReader = PETReaderType::New(); 133 | petReader->SetFileName(sPETFileName); 134 | 135 | //Try to read PET. 136 | try { 137 | petReader->Update(); 138 | } catch (itk::ExceptionObject & err) { 139 | std::cerr << "[Error]\tCannot read PET input file: " << sPETFileName 140 | << std::endl; 141 | return EXIT_FAILURE; 142 | } 143 | 144 | //Calculate the variance for a given FWHM. 145 | VectorType vVariance; 146 | vVariance = vFWHM / (2.0 * sqrt(2.0 * log(2.0))); 147 | //std::cout << vVariance << std::endl; 148 | 149 | VectorType vVoxelSize = petReader->GetOutput()->GetSpacing(); 150 | //std::cout << vVoxelSize << std::endl; 151 | 152 | vVariance[0] = pow(vVariance[0], 2); 153 | vVariance[1] = pow(vVariance[1], 2); 154 | vVariance[2] = pow(vVariance[2], 2); 155 | 156 | FilterType::Pointer rlFilter = FilterType::New(); 157 | rlFilter->SetInput( petReader->GetOutput() ); 158 | rlFilter->SetPSF(vVariance); 159 | rlFilter->SetIterations( nNumOfIters ); 160 | //rlFilter->SetStoppingCond( fStop ); 161 | rlFilter->SetVerbose ( bDebug ); 162 | 163 | //Perform RL. 164 | try { 165 | rlFilter->Update(); 166 | } catch (itk::ExceptionObject & err) { 167 | std::cerr << "[Error]\tfailure applying Richardson-Lucy on: " << sPETFileName 168 | << "\n" << err 169 | << std::endl; 170 | return EXIT_FAILURE; 171 | } 172 | 173 | PETWriterType::Pointer petWriter = PETWriterType::New(); 174 | petWriter->SetFileName(sOutputFileName); 175 | petWriter->SetInput( rlFilter->GetOutput() ); 176 | 177 | try { 178 | petWriter->Update(); 179 | } catch (itk::ExceptionObject & err) { 180 | std::cerr << "\n[Error]\tCannot write output file: " << sOutputFileName 181 | << std::endl; 182 | 183 | return EXIT_FAILURE; 184 | } 185 | 186 | return EXIT_SUCCESS; 187 | } 188 | 189 | std::string getAcknowledgments(void) 190 | { 191 | //Produces acknowledgments string for 3DSlicer. 192 | std::string sAck = "This program implements the Richardson-Lucy (RL) partial volume correction technique. Please cite the following paper:\n" 193 | "\tTohka, J. and Reilhac A., (2008). \"Deconvolution-based partial volume correction in Raclopride-PET\n\tand Monte Carlo comparison to MR-based method\", NeuroImage, vol. 39. 1570--1584."; 194 | 195 | return sAck; 196 | } 197 | 198 | -------------------------------------------------------------------------------- /src/Simulate.cxx: -------------------------------------------------------------------------------- 1 | /* 2 | Simulate.cxx 3 | 4 | Author: Kris Thielemans 5 | 6 | Copyright 2014 Institute of Nuclear Medicine, University College London. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | This program implements blurring if an image with a kernel to simulate 21 | the partial volume effect. It is useful for testing the PVC methods. 22 | */ 23 | 24 | 25 | #include "EnvironmentInfo.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | typedef itk::Vector VectorType; 37 | typedef itk::Image PETImageType; 38 | 39 | typedef itk::ImageFileReader PETReaderType; 40 | typedef itk::ImageFileWriter PETWriterType; 41 | typedef itk::DiscreteGaussianImageFilter BlurringFilterType; 42 | 43 | //Produces the text for the acknowledgments dialog in Slicer. 44 | std::string getAcknowledgments(void); 45 | 46 | int main(int argc, char *argv[]) 47 | { 48 | const char * const AUTHOR = "Kris Thielemans"; 49 | const char * const APP_TITLE = "PVE Simulation"; 50 | 51 | std::stringstream version_number; 52 | version_number << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_PATCH; 53 | const std::string VERSION_NO = version_number.str(); 54 | 55 | //Setting up command line argument list. 56 | MetaCommand command; 57 | 58 | command.SetVersion(VERSION_NO.c_str()); 59 | command.SetAuthor(AUTHOR); 60 | command.SetName(APP_TITLE); 61 | command.SetDescription( 62 | "Performs PV simulation by simple blurring"); 63 | 64 | std::string sAcks = getAcknowledgments(); 65 | command.SetAcknowledgments(sAcks.c_str()); 66 | 67 | command.SetCategory("PETPVC"); 68 | 69 | command.AddField("petfile", "PET filename", MetaCommand::IMAGE, MetaCommand::DATA_IN); 70 | command.AddField("outputfile", "output filename", MetaCommand::IMAGE, MetaCommand::DATA_OUT); 71 | 72 | command.SetOption("FWHMx", "x", true, 73 | "The full-width at half maximum in mm along x-axis"); 74 | command.AddOptionField("FWHMx", "X", MetaCommand::FLOAT, true, ""); 75 | 76 | command.SetOption("FWHMy", "y", true, 77 | "The full-width at half maximum in mm along y-axis"); 78 | command.AddOptionField("FWHMy", "Y", MetaCommand::FLOAT, true, ""); 79 | 80 | command.SetOption("FWHMz", "z", true, 81 | "The full-width at half maximum in mm along z-axis"); 82 | command.AddOptionField("FWHMz", "Z", MetaCommand::FLOAT, true, ""); 83 | 84 | //Parse command line. 85 | if (!command.Parse(argc, argv)) { 86 | return EXIT_FAILURE; 87 | } 88 | 89 | //Get image filenames 90 | std::string sPETFileName = command.GetValueAsString("petfile"); 91 | std::string sOutputFileName = command.GetValueAsString("outputfile"); 92 | 93 | //Get values for PSF. 94 | float fFWHM_x = command.GetValueAsFloat("FWHMx", "X"); 95 | float fFWHM_y = command.GetValueAsFloat("FWHMy", "Y"); 96 | float fFWHM_z = command.GetValueAsFloat("FWHMz", "Z"); 97 | 98 | //Make vector of FWHM in x,y and z. 99 | VectorType vFWHM; 100 | vFWHM[0] = fFWHM_x; 101 | vFWHM[1] = fFWHM_y; 102 | vFWHM[2] = fFWHM_z; 103 | 104 | //Create reader for PET image. 105 | PETReaderType::Pointer petReader = PETReaderType::New(); 106 | petReader->SetFileName(sPETFileName); 107 | 108 | //Try to read PET. 109 | try { 110 | petReader->Update(); 111 | } catch (itk::ExceptionObject & err) { 112 | std::cerr << "[Error]\tCannot read PET input file: " << sPETFileName 113 | << std::endl; 114 | return EXIT_FAILURE; 115 | } 116 | 117 | //Calculate the variance for a given FWHM. 118 | VectorType vVariance; 119 | vVariance = vFWHM / (2.0 * sqrt(2.0 * log(2.0))); 120 | //std::cout << vVariance << std::endl; 121 | 122 | VectorType vVoxelSize = petReader->GetOutput()->GetSpacing(); 123 | //std::cout << vVoxelSize << std::endl; 124 | 125 | vVariance[0] = pow(vVariance[0], 2); 126 | vVariance[1] = pow(vVariance[1], 2); 127 | vVariance[2] = pow(vVariance[2], 2); 128 | 129 | //Create blurring filter to apply PSF. 130 | BlurringFilterType::Pointer blurFilter = BlurringFilterType::New(); 131 | blurFilter->SetVariance(vVariance); 132 | 133 | // apply blur to input image 134 | blurFilter->SetInput(petReader->GetOutput()); 135 | 136 | //Write out result of final iteration. 137 | PETWriterType::Pointer petWriter = PETWriterType::New(); 138 | petWriter->SetFileName(sOutputFileName); 139 | petWriter->SetInput(blurFilter->GetOutput()); 140 | 141 | try { 142 | petWriter->Update(); 143 | } catch (itk::ExceptionObject & err) { 144 | std::cerr << "[Error]\tCannot write output file: " << sOutputFileName 145 | << std::endl; 146 | 147 | return EXIT_FAILURE; 148 | } 149 | 150 | return EXIT_SUCCESS; 151 | } 152 | 153 | 154 | 155 | std::string getAcknowledgments(void) 156 | { 157 | //Produces acknowledgments string for 3DSlicer. 158 | std::string sAck = "This program implements blurring to simulate the PVE. Please cite the following paper:\n" 159 | "\tErlandsson, K. and Buvat, I. and Pretorius, P.H. and Thomas, B.A. and Hutton, B.F., (2012).\n\t\"A review of partial volume correction techniques " 160 | "for emission tomography and their applications in neurology, cardiology and oncology\", \n\tPhysics in Medicine and Biology, vol. 57, no. 21, R119-59."; 161 | 162 | return sAck; 163 | } 164 | 165 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #========================================================================= 2 | # Author: Kris Thielemans 3 | # 4 | # Copyright University College London 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0.txt 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | #========================================================================= 19 | 20 | ADD_EXECUTABLE(pvc_createTestImage CreateTestImage.cxx ) 21 | TARGET_LINK_LIBRARIES(pvc_createTestImage ${ITK_LIBRARIES}) 22 | 23 | ADD_EXECUTABLE(pvc_compareImages CompareImages.cxx ) 24 | TARGET_LINK_LIBRARIES(pvc_compareImages ${ITK_LIBRARIES}) 25 | 26 | # There's really only 2 tests currently: 27 | # run IterativeYang and RBV and check that the output is almost 28 | # identical to the original. 29 | # 30 | # However, to do this, we need to have an input image, and blur it. 31 | # At present, we just do that as seperate tests. 32 | # 33 | # TODO 34 | # KT isn't sure how to make sure that the Compare* tests only run when 35 | # the previous ones were successful. 36 | # This means that they'll fail when using parallel building 37 | # 38 | # Nov. 08 2014 39 | # V. Cuplov added a ctest to compare pvc_iy and Ben's new 'discrete' Iterative Yang 40 | # version pvc_diy, which only needs a 3D image with labels (a parcellation image) 41 | # as opposed to the 4D mask needed when using pvc_iy. 42 | # The ctest will run a full test (matching, underestimated and overestimated blurring) 43 | # on the DiscreteIterativeYoung output and will also compare the DiscreteIterativeYoung 44 | # image with the IterativeYoung image. 45 | # 46 | 47 | ADD_TEST(NAME generate 48 | COMMAND pvc_createTestImage original.nii 4dmask.nii 3dparcellation.nii) 49 | 50 | ADD_TEST(NAME simulate 51 | COMMAND pvc_simulate -x 5 -y 6 -z 7 original.nii filtered.nii ) 52 | 53 | # macro for adding tests for pvc 54 | # will run matching, underestimated and overestimated blurring 55 | # t_* arguments are thresholds to use for the comparison 56 | macro(add_pvc_test fullname name maskname t_match t_under t_over) 57 | ADD_TEST(NAME Run${fullname} 58 | COMMAND pvc_${name} -x 5 -y 6 -z 7 filtered.nii ${maskname}.nii ${name}.nii ) 59 | 60 | ADD_TEST(NAME Compare${fullname} 61 | COMMAND pvc_compareImages ${name}.nii original.nii ${t_match} ) 62 | 63 | ADD_TEST(NAME Run${fullname}Undercorrect 64 | COMMAND pvc_${name} -x 4 -y 5 -z 5 filtered.nii ${maskname}.nii ${name}_undercorrect.nii ) 65 | 66 | ADD_TEST(NAME Compare${fullname}Undercorrect 67 | COMMAND pvc_compareImages ${name}_undercorrect.nii original.nii ${t_under} ) 68 | 69 | ADD_TEST(NAME Run${fullname}Overcorrect 70 | COMMAND pvc_${name} -x 6 -y 7 -z 8 filtered.nii ${maskname}.nii ${name}_overcorrect.nii ) 71 | 72 | ADD_TEST(NAME Compare${fullname}Overcorrect 73 | COMMAND pvc_compareImages ${name}_overcorrect.nii original.nii ${t_over} ) 74 | ENDMACRO(add_pvc_test) 75 | 76 | add_pvc_test(IterativeYang iy 4dmask .01 .7 .7 ) 77 | # note: currently ridicilously high threshold needed for RBV over-correction. 78 | # the images show 4 isolated pixels with high values. Can we test for 79 | # what we know will happen? 80 | add_pvc_test(RBV rbv 4dmask .01 .7 4) 81 | add_pvc_test(DiscreteIterativeYang diy 3dparcellation .01 .7 .7) 82 | 83 | 84 | ADD_TEST(NAME Compare_iy_diy 85 | COMMAND pvc_compareImages iy.nii diy.nii .001) 86 | 87 | ADD_TEST(NAME Compare_iy_diy_Undercorrect 88 | COMMAND pvc_compareImages iy_undercorrect.nii diy_undercorrect.nii .001) 89 | 90 | ADD_TEST(NAME Compare_iy_diy_Overcorrect 91 | COMMAND pvc_compareImages iy_overcorrect.nii diy_overcorrect.nii .001) 92 | 93 | -------------------------------------------------------------------------------- /test/CompareImages.cxx: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | * Author: Kris Thielemans 3 | * 4 | * Copyright University College London 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0.txt 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | *=========================================================================*/ 19 | 20 | /* 21 | This file compares 2 images by taking the absolute difference 22 | and checking that its maximum is less than a threshold. 23 | */ 24 | 25 | #include "itkImageFileReader.h" 26 | #include "itkAbsoluteValueDifferenceImageFilter.h" 27 | #include "itkMinimumMaximumImageCalculator.h" 28 | #include 29 | 30 | 31 | int main( int argc, char *argv[] ) 32 | { 33 | if( argc != 4 ) { 34 | std::cerr << "Usage: " << argv[0] << " imagefile1 imagefile2 absolute_diff_threshold" << std::endl; 35 | return EXIT_FAILURE; 36 | } 37 | // We declare the pixel type and dimension of the image to be produced as 38 | // output. 39 | typedef float PixelType; 40 | const unsigned int Dimension = 3; 41 | 42 | typedef itk::Image< PixelType, Dimension > ImageType; 43 | typedef itk::ImageFileReader ReaderType; 44 | 45 | try { 46 | ReaderType::Pointer reader = ReaderType::New(); 47 | reader->SetFileName(argv[1]); 48 | reader->Update(); 49 | ImageType::Pointer image1 = reader->GetOutput(); 50 | image1->DisconnectPipeline(); 51 | reader->SetFileName(argv[2]); 52 | reader->Update(); 53 | ImageType::Pointer image2 = reader->GetOutput(); 54 | const float threshold = atof(argv[3]); 55 | 56 | 57 | typedef itk::AbsoluteValueDifferenceImageFilter AbsDiffFilterType; 58 | AbsDiffFilterType::Pointer absdifffilter = AbsDiffFilterType::New(); 59 | absdifffilter->SetInput1(image1); 60 | absdifffilter->SetInput2(image2); 61 | ImageType::Pointer absdiff = absdifffilter->GetOutput(); 62 | 63 | absdifffilter->Update(); 64 | 65 | typedef itk::MinimumMaximumImageCalculator minmaxCalculatorType; 66 | minmaxCalculatorType::Pointer minmaxCalculator = minmaxCalculatorType::New(); 67 | minmaxCalculator->SetImage(absdiff); 68 | minmaxCalculator->ComputeMaximum(); 69 | 70 | const float absmax = minmaxCalculator->GetMaximum(); 71 | std::cerr << "max " << absmax << '\n'; 72 | if (absmax > threshold) { 73 | std::cerr << "Absolute difference too large (" << absmax << ")\n"; 74 | return EXIT_FAILURE; 75 | } 76 | 77 | } catch( itk::ExceptionObject & excp ) { 78 | std::cerr << excp << std::endl; 79 | return EXIT_FAILURE; 80 | } 81 | 82 | return EXIT_SUCCESS; 83 | } 84 | --------------------------------------------------------------------------------