├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── question.md └── workflows │ ├── autoformat.yml │ ├── pr-lint.yml │ ├── release.yml │ └── tests.yml ├── .gitignore ├── .readthedocs.yaml ├── LICENSE ├── README.md ├── brainles_preprocessing ├── __init__.py ├── brain_extraction │ ├── __init__.py │ └── brain_extractor.py ├── brats │ ├── __init__.py │ ├── t1_centric.py │ └── t1c_centric.py ├── cli.py ├── constants.py ├── defacing │ ├── __init__.py │ ├── defacer.py │ └── quickshear │ │ ├── __init__.py │ │ ├── nipy_quickshear.py │ │ └── quickshear.py ├── modality.py ├── normalization │ ├── __init__.py │ ├── normalizer_base.py │ ├── percentile_normalizer.py │ └── windowing_normalizer.py ├── preprocessor.py ├── registration │ ├── ANTs │ │ ├── ANTs.py │ │ ├── TODO_ANTs_parameters.py │ │ └── __init__.py │ ├── __init__.py │ ├── elastix │ │ ├── __init__.py │ │ └── elastix.py │ ├── greedy │ │ ├── __init__.py │ │ └── greedy.py │ ├── niftyreg │ │ ├── __init__.py │ │ ├── niftyreg.py │ │ └── niftyreg_scripts │ │ │ ├── niftyreg_1.5.68 │ │ │ ├── bin │ │ │ │ ├── groupwise_niftyreg_params.sh │ │ │ │ ├── groupwise_niftyreg_run.sh │ │ │ │ ├── reg_aladin │ │ │ │ ├── reg_average │ │ │ │ ├── reg_f3d │ │ │ │ ├── reg_jacobian │ │ │ │ ├── reg_measure │ │ │ │ ├── reg_resample │ │ │ │ ├── reg_tools │ │ │ │ └── reg_transform │ │ │ └── include │ │ │ │ ├── AffineDeformationFieldKernel.h │ │ │ │ ├── AladinContent.h │ │ │ │ ├── BlockMatchingKernel.h │ │ │ │ ├── CPUAffineDeformationFieldKernel.h │ │ │ │ ├── CPUBlockMatchingKernel.h │ │ │ │ ├── CPUConvolutionKernel.h │ │ │ │ ├── CPUKernelFactory.h │ │ │ │ ├── CPUOptimiseKernel.h │ │ │ │ ├── CPUResampleImageKernel.h │ │ │ │ ├── ConvolutionKernel.h │ │ │ │ ├── Kernel.h │ │ │ │ ├── KernelFactory.h │ │ │ │ ├── OptimiseKernel.h │ │ │ │ ├── Platform.h │ │ │ │ ├── ResampleImageKernel.h │ │ │ │ ├── _reg_ReadWriteImage.h │ │ │ │ ├── _reg_ReadWriteMatrix.h │ │ │ │ ├── _reg_aladin.cpp │ │ │ │ ├── _reg_aladin.h │ │ │ │ ├── _reg_aladin_sym.cpp │ │ │ │ ├── _reg_aladin_sym.h │ │ │ │ ├── _reg_base.h │ │ │ │ ├── _reg_blockMatching.h │ │ │ │ ├── _reg_dti.h │ │ │ │ ├── _reg_f3d.h │ │ │ │ ├── _reg_f3d2.h │ │ │ │ ├── _reg_f3d_sym.h │ │ │ │ ├── _reg_femTrans.h │ │ │ │ ├── _reg_globalTrans.h │ │ │ │ ├── _reg_kld.h │ │ │ │ ├── _reg_lncc.h │ │ │ │ ├── _reg_localTrans.h │ │ │ │ ├── _reg_localTrans_jac.h │ │ │ │ ├── _reg_localTrans_regul.h │ │ │ │ ├── _reg_macros.h │ │ │ │ ├── _reg_maths.h │ │ │ │ ├── _reg_maths_eigen.h │ │ │ │ ├── _reg_measure.h │ │ │ │ ├── _reg_mind.h │ │ │ │ ├── _reg_nmi.h │ │ │ │ ├── _reg_optimiser.cpp │ │ │ │ ├── _reg_optimiser.h │ │ │ │ ├── _reg_resampling.h │ │ │ │ ├── _reg_splineBasis.h │ │ │ │ ├── _reg_ssd.h │ │ │ │ ├── _reg_stringFormat.h │ │ │ │ ├── _reg_tools.h │ │ │ │ ├── nifti1.h │ │ │ │ ├── nifti1_io.h │ │ │ │ ├── png.h │ │ │ │ ├── pngconf.h │ │ │ │ ├── pngdebug.h │ │ │ │ ├── pnginfo.h │ │ │ │ ├── pnglibconf.h │ │ │ │ ├── pngpriv.h │ │ │ │ ├── pngstruct.h │ │ │ │ ├── readpng.h │ │ │ │ ├── reg_png.h │ │ │ │ ├── zlib.h │ │ │ │ ├── znzlib.h │ │ │ │ └── zutil.h │ │ │ ├── reg_aladin │ │ │ ├── reg_resample │ │ │ ├── rigid_reg.sh │ │ │ └── transform.sh │ └── registrator.py └── utils │ ├── __init__.py │ ├── generic.py │ ├── logging_utils.py │ └── zenodo.py ├── docs ├── Makefile ├── make.bat └── source │ ├── brain-extraction.rst │ ├── brainles-preprocessing.rst │ ├── conf.py │ ├── defacing.rst │ ├── index.rst │ └── registration.rst ├── example ├── example_data │ ├── OtherEXampleFromTCIA │ │ ├── MRHR_FLAIR_AX_OtherEXampleTCIA_TCGA-FG-6692_Si_TCGA-FG-6692_MRHR_FLAIR_AX_SE_IR_5_tir2d1_21_fla.nii.gz │ │ ├── MRHR_T1_AX_POST_GAD_OtherEXampleTCIA_TCGA-FG-6692_Si_TCGA-FG-6692_MRHR_T1_AX_POST_GAD_SE_13_se2d1r_t1c.nii.gz │ │ ├── MRHR_T2_AX_OtherEXampleTCIA_TCGA-FG-6692_Si_TCGA-FG-6692_MRHR_T2_AX_SE_2_tse2d1_11_t2.nii.gz │ │ └── T1_AX_OtherEXampleTCIA_TCGA-FG-6692_Si_TCGA-FG-6692_T1_AX_SE_10_se2d1_t1.nii.gz │ └── TCGA-DU-7294 │ │ ├── AXIAL_FLAIR_RF2_150_TCGA-DU-7294_TCGA-DU-7294_GE_TCGA-DU-7294_AXIAL_FLAIR_RF2_150_IR_7_fla.nii.gz │ │ ├── AX_T1_POST_GD_FLAIR_TCGA-DU-7294_TCGA-DU-7294_GE_TCGA-DU-7294_AX_T1_POST_GD_FLAIR_RM_13_t1c.nii.gz │ │ ├── AX_T1_pre_gd_TCGA-DU-7294_TCGA-DU-7294_GE_TCGA-DU-7294_AX_T1_pre_gd_RM_8_t1.nii.gz │ │ └── AX_T2_FR-FSE_RF2_150_TCGA-DU-7294_TCGA-DU-7294_GE_TCGA-DU-7294_AX_T2_FR-FSE_RF2_150_RM_4_t2.nii.gz └── example_modality_centric_preprocessor.py ├── pyproject.toml └── tests ├── registrator_base.py ├── test_data └── input │ ├── ants_matrix.mat │ ├── bet_tcia_example_t1c_mask.nii.gz │ ├── ereg_matrix.mat │ ├── niftyreg_matrix.txt │ ├── tcia_example_t1.nii.gz │ └── tcia_example_t1c.nii.gz ├── test_hdbet_brain_extractor.py ├── test_registrators.py └── test_zenodo.py /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '[BUG] ' 5 | labels: 'bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Install '....' 17 | 3. Run commands '....' 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Screenshots** 23 | If applicable, add screenshots to help explain your problem. 24 | 25 | **Environment** 26 | 27 | ### operating system and version? 28 | e.g. Ubuntu 23.10 LTS 29 | 30 | 31 | ### NVIDIA drivers and GPUs 32 | please paste the output of (or a more suitable base version for your system): 33 | ```sh 34 | nvidia-smi 35 | ``` 36 | 37 | You should see something like: 38 | ``` 39 | +---------------------------------------------------------------------------------------+ 40 | | NVIDIA-SMI 530.30.02 Driver Version: 530.30.02 CUDA Version: 12.1 | 41 | |-----------------------------------------+----------------------+----------------------+ 42 | | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | 43 | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | 44 | | | | MIG M. | 45 | |=========================================+======================+======================| 46 | | 0 NVIDIA RTX A5000 Off| 00000000:01:00.0 Off | Off | 47 | | 30% 17C P8 12W / 230W| 6MiB / 24564MiB | 0% Default | 48 | | | | N/A | 49 | +-----------------------------------------+----------------------+----------------------+ 50 | | 1 Quadro RTX 8000 Off| 00000000:C1:00.0 Off | Off | 51 | | 33% 17C P8 9W / 260W| 6MiB / 49152MiB | 0% Default | 52 | | | | N/A | 53 | +-----------------------------------------+----------------------+----------------------+ 54 | ``` 55 | 56 | 57 | ### Python environment and version? 58 | e.g. Conda environment with Python 3.10. Check your Python version with: 59 | ```sh 60 | python --version 61 | ``` 62 | 63 | ### version of brainles_preprocessing ? 64 | please specify your version of brainles_preprocessing (please make sure you run the latest version): 65 | ```sh 66 | pip freeze | grep brainles_preprocessing 67 | ``` 68 | 69 | **Additional context** 70 | Add any other context about the problem here. 71 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '[FEATURE] ' 5 | labels: 'enhancement' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Please ask your question, make sure to read the FAQ before 4 | title: '[QUESTION] ' 5 | labels: 'question' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Your question** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | -------------------------------------------------------------------------------- /.github/workflows/autoformat.yml: -------------------------------------------------------------------------------- 1 | name: autoformat 2 | 3 | on: 4 | issue_comment: 5 | types: [created, edited] 6 | jobs: 7 | run_autoformat: 8 | uses: BrainLesion/BrainLes/.github/workflows/autoformat.yml@main 9 | secrets: inherit 10 | -------------------------------------------------------------------------------- /.github/workflows/pr-lint.yml: -------------------------------------------------------------------------------- 1 | name: lint 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | jobs: 8 | run_lint: 9 | uses: BrainLesion/BrainLes/.github/workflows/pr_lint.yml@main 10 | secrets: inherit 11 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | release: 5 | types: [created] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | publish: 10 | name: Publish to test PyPI 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout Repository 14 | uses: actions/checkout@v3 15 | - name: Set up Python 16 | uses: actions/setup-python@v4 17 | with: 18 | python-version: "3.x" 19 | - name: Install dependencies 20 | run: | 21 | pip install build 22 | pip install twine 23 | - name: Build package 24 | run: python -m build 25 | - name: Upload to PyPI 26 | env: 27 | TWINE_USERNAME: __token__ 28 | TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} 29 | run: | 30 | twine upload dist/* 31 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python 3 | 4 | name: tests 5 | 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | pull_request: 10 | branches: [ "main" ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | python-version: ["3.10", "3.11", "3.12"] 20 | 21 | steps: 22 | - uses: actions/checkout@v3 23 | - name: Set up Python ${{ matrix.python-version }} 24 | uses: actions/setup-python@v3 25 | with: 26 | python-version: ${{ matrix.python-version }} 27 | - name: Install dependencies 28 | run: | 29 | python -m pip install --upgrade pip 30 | python -m pip install uv 31 | uv pip install flake8 pytest --system 32 | uv pip install -e .[all] --system 33 | - name: Lint with flake8 34 | run: | 35 | # stop the build if there are Python syntax errors or undefined names 36 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 37 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 38 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 39 | - name: Test with pytest 40 | run: | 41 | pytest 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | .vscode 132 | 133 | .DS_Store 134 | 135 | brainles_preprocessing/registration/atlases 136 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | build: 4 | os: "ubuntu-22.04" 5 | tools: 6 | python: "3.10" 7 | jobs: 8 | post_create_environment: 9 | # Install poetry 10 | # https://python-poetry.org/docs/#installing-manually 11 | - pip install poetry 12 | post_install: 13 | # Install dependencies with 'docs' dependency group 14 | # https://python-poetry.org/docs/managing-dependencies/#dependency-groups 15 | # VIRTUAL_ENV needs to be set manually for now. 16 | # See https://github.com/readthedocs/readthedocs.org/pull/11152/ 17 | - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install --with docs --all-extras 18 | 19 | sphinx: 20 | configuration: docs/source/conf.py -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # BrainLes-Preprocessing 4 | [![Python Versions](https://img.shields.io/pypi/pyversions/brainles-preprocessing)](https://pypi.org/project/brainles-preprocessing/) 5 | [![Stable Version](https://img.shields.io/pypi/v/brainles-preprocessing?label=stable)](https://pypi.python.org/pypi/brainles-preprocessing/) 6 | [![Documentation Status](https://readthedocs.org/projects/brainles-preprocessing/badge/?version=latest)](http://brainles-preprocessing.readthedocs.io/?badge=latest) 7 | [![tests](https://github.com/BrainLesion/preprocessing/actions/workflows/tests.yml/badge.svg)](https://github.com/BrainLesion/preprocessing/actions/workflows/tests.yml) 8 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 9 | 10 | 11 | `BrainLes preprocessing` is a comprehensive tool for preprocessing tasks in biomedical imaging, with a focus on (but not limited to) multi-modal brain MRI. It can be used to build modular preprocessing pipelines: 12 | 13 | This includes **normalization**, **co-registration**, **atlas registration** and **skulstripping / brain extraction**. 14 | 15 | BrainLes is written `backend-agnostic` meaning it allows to swap the registration, brain extraction tools and defacing tools. 16 | 17 | 18 | 19 | 20 | ## Installation 21 | 22 | With a Python 3.10+ environment you can install directly from [pypi.org](https://pypi.org/project/brainles-preprocessing/): 23 | 24 | ``` 25 | pip install brainles-preprocessing 26 | ``` 27 | 28 | We recommend using Python `3.10 / 3.11 / 3.12`. 29 | 30 | > [!NOTE] 31 | > For python `3.13` the installation can currently fail with the error `Failed to build antspyx`. 32 | > This usually means that there is no pre-built wheel for the package and it has to be build locally. 33 | > This will require cmake (install e.g. with `pip install cmake`) and quite some time. 34 | > Rerunning the installation with cmake installed should fix the error. 35 | 36 | 37 | ## Usage 38 | A minimal example to register (to the standard atlas using ANTs) and skull strip (using HDBet) a t1c image (center modality) with 1 moving modality (flair) could look like this: 39 | ```python 40 | from pathlib import Path 41 | from brainles_preprocessing.modality import Modality, CenterModality 42 | from brainles_preprocessing.normalization.percentile_normalizer import ( 43 | PercentileNormalizer, 44 | ) 45 | from brainles_preprocessing.preprocessor import Preprocessor 46 | 47 | patient_folder = Path("/home/marcelrosier/preprocessing/patient") 48 | 49 | # specify a normalizer 50 | percentile_normalizer = PercentileNormalizer( 51 | lower_percentile=0.1, 52 | upper_percentile=99.9, 53 | lower_limit=0, 54 | upper_limit=1, 55 | ) 56 | 57 | # define center and moving modalities 58 | center = CenterModality( 59 | modality_name="t1c", 60 | input_path=patient_folder / "t1c.nii.gz", 61 | normalizer=percentile_normalizer, 62 | # specify the output paths for the raw and normalized images of each step - here only for atlas registered and brain extraction 63 | raw_skull_output_path="patient/raw_skull_dir/t1c_skull_raw.nii.gz", 64 | raw_bet_output_path="patient/raw_bet_dir/t1c_bet_raw.nii.gz", 65 | raw_defaced_output_path="patient/raw_defaced_dir/t1c_defaced_raw.nii.gz", 66 | normalized_skull_output_path="patient/norm_skull_dir/t1c_skull_normalized.nii.gz", 67 | normalized_bet_output_path="patient/norm_bet_dir/t1c_bet_normalized.nii.gz", 68 | normalized_defaced_output_path="patient/norm_defaced_dir/t1c_defaced_normalized.nii.gz", 69 | # specify output paths for the brain extraction and defacing masks 70 | bet_mask_output_path="patient/masks/t1c_bet_mask.nii.gz", 71 | defacing_mask_output_path="patient/masks/t1c_defacing_mask.nii.gz", 72 | ) 73 | 74 | moving_modalities = [ 75 | Modality( 76 | modality_name="flair", 77 | input_path=patient_folder / "flair.nii.gz", 78 | normalizer=percentile_normalizer, 79 | # specify the output paths for the raw and normalized images of each step - here only for atlas registered and brain extraction 80 | raw_skull_output_path="patient/raw_skull_dir/fla_skull_raw.nii.gz", 81 | raw_bet_output_path="patient/raw_bet_dir/fla_bet_raw.nii.gz", 82 | raw_defaced_output_path="patient/raw_defaced_dir/fla_defaced_raw.nii.gz", 83 | normalized_skull_output_path="patient/norm_skull_dir/fla_skull_normalized.nii.gz", 84 | normalized_bet_output_path="patient/norm_bet_dir/fla_bet_normalized.nii.gz", 85 | normalized_defaced_output_path="patient/norm_defaced_dir/fla_defaced_normalized.nii.gz", 86 | ) 87 | ] 88 | 89 | # instantiate and run the preprocessor using defaults for registration/ brain extraction/ defacing backends 90 | preprocessor = Preprocessor( 91 | center_modality=center, 92 | moving_modalities=moving_modalities, 93 | ) 94 | 95 | preprocessor.run() 96 | 97 | ``` 98 | 99 | 100 | The package allows to choose registration backends, brain extraction tools and defacing methods. 101 | An example notebook with 4 modalities and further outputs and customizations can be found following these badges: 102 | 103 | [![nbviewer](https://raw.githubusercontent.com/jupyter/design/master/logos/Badges/nbviewer_badge.svg)](https://nbviewer.org/github/BrainLesion/tutorials/blob/main/preprocessing/preprocessing_tutorial.ipynb) 104 | 105 | Open In Colab 106 | 107 | 108 | For further information please have a look at our [Jupyter Notebook tutorials](https://github.com/BrainLesion/tutorials/tree/main/preprocessing) in our tutorials repo (WIP). 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | ## Documentation 118 | We provide a (WIP) documentation. Have a look [here](https://brainles-preprocessing.readthedocs.io/en/latest/?badge=latest) 119 | 120 | ## FAQ 121 | Please credit the authors by citing their work. 122 | 123 | ### Registration 124 | We currently provide support for [ANTs](https://github.com/ANTsX/ANTs) (default), [Niftyreg](https://github.com/KCL-BMEIS/niftyreg) (Linux). 125 | 126 | ### Atlas Reference 127 | We provide the SRI-24 atlas from this [publication](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2915788/). 128 | However, custom atlases in NIfTI format are supported. 129 | 130 | ### Brain extraction 131 | We currently provide support for [HD-BET](https://github.com/MIC-DKFZ/HD-BET). 132 | 133 | ### Defacing 134 | We currently provide support for [Quickshear](https://github.com/nipy/quickshear). 135 | -------------------------------------------------------------------------------- /brainles_preprocessing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/__init__.py -------------------------------------------------------------------------------- /brainles_preprocessing/brain_extraction/__init__.py: -------------------------------------------------------------------------------- 1 | from .brain_extractor import HDBetExtractor 2 | -------------------------------------------------------------------------------- /brainles_preprocessing/brain_extraction/brain_extractor.py: -------------------------------------------------------------------------------- 1 | # TODO add typing and docs 2 | import shutil 3 | from abc import ABC, abstractmethod 4 | from pathlib import Path 5 | from typing import Optional, Union 6 | from enum import Enum 7 | 8 | from auxiliary.nifti.io import read_nifti, write_nifti 9 | from brainles_hd_bet import run_hd_bet 10 | 11 | 12 | class Mode(Enum): 13 | FAST = "fast" 14 | ACCURATE = "accurate" 15 | 16 | 17 | class BrainExtractor: 18 | @abstractmethod 19 | def extract( 20 | self, 21 | input_image_path: Union[str, Path], 22 | masked_image_path: Union[str, Path], 23 | brain_mask_path: Union[str, Path], 24 | log_file_path: Optional[Union[str, Path]], 25 | mode: Union[str, Mode], 26 | **kwargs, 27 | ) -> None: 28 | """ 29 | Abstract method to extract the brain from an input image. 30 | 31 | Args: 32 | input_image_path (str or Path): Path to the input image. 33 | masked_image_path (str or Path): Path where the brain-extracted image will be saved. 34 | brain_mask_path (str or Path): Path where the brain mask will be saved. 35 | log_file_path (str or Path, Optional): Path to the log file. 36 | mode (str or Mode): Extraction mode. 37 | **kwargs: Additional keyword arguments. 38 | """ 39 | pass 40 | 41 | def apply_mask( 42 | self, 43 | input_image_path: Union[str, Path], 44 | mask_path: Union[str, Path], 45 | bet_image_path: Union[str, Path], 46 | ) -> None: 47 | """ 48 | Apply a brain mask to an input image. 49 | 50 | Args: 51 | input_image_path (str or Path): Path to the input image (NIfTI format). 52 | mask_path (str or Path): Path to the brain mask image (NIfTI format). 53 | bet_image_path (str or Path): Path to save the resulting masked image (NIfTI format). 54 | """ 55 | 56 | try: 57 | # Read data 58 | input_data = read_nifti(str(input_image_path)) 59 | mask_data = read_nifti(str(mask_path)) 60 | except FileNotFoundError as e: 61 | raise FileNotFoundError(f"File not found: {e.filename}") from e 62 | except Exception as e: 63 | raise RuntimeError(f"Error reading files: {e}") from e 64 | 65 | # Check that the input and mask have the same shape 66 | if input_data.shape != mask_data.shape: 67 | raise ValueError("Input image and mask must have the same dimensions.") 68 | 69 | # Mask and save it 70 | masked_data = input_data * mask_data 71 | 72 | try: 73 | write_nifti( 74 | input_array=masked_data, 75 | output_nifti_path=str(bet_image_path), 76 | reference_nifti_path=str(input_image_path), 77 | create_parent_directory=True, 78 | ) 79 | except Exception as e: 80 | raise RuntimeError(f"Error writing output file: {e}") from e 81 | 82 | 83 | class HDBetExtractor(BrainExtractor): 84 | def extract( 85 | self, 86 | input_image_path: Union[str, Path], 87 | masked_image_path: Union[str, Path], 88 | brain_mask_path: Union[str, Path], 89 | log_file_path: Optional[Union[str, Path]] = None, 90 | # TODO convert mode to enum 91 | mode: Union[str, Mode] = Mode.ACCURATE, 92 | device: Optional[Union[int, str]] = 0, 93 | do_tta: Optional[bool] = True, 94 | ) -> None: 95 | # GPU + accurate + TTA 96 | """ 97 | Skull-strips images with HD-BET and generates a skull-stripped file and mask. 98 | 99 | Args: 100 | input_image_path (str or Path): Path to the input image. 101 | masked_image_path (str or Path): Path where the brain-extracted image will be saved. 102 | brain_mask_path (str or Path): Path where the brain mask will be saved. 103 | log_file_path (str or Path, Optional): Path to the log file. 104 | mode (str or Mode): Extraction mode ('fast' or 'accurate'). 105 | device (str or int): Device to use for computation (e.g., 0 for GPU 0, 'cpu' for CPU). 106 | do_tta (bool): whether to do test time data augmentation by mirroring along all axes. 107 | """ 108 | 109 | # Ensure mode is a Mode enum instance 110 | if isinstance(mode, str): 111 | try: 112 | mode_enum = Mode(mode.lower()) 113 | except ValueError: 114 | raise ValueError(f"'{mode}' is not a valid Mode.") 115 | elif isinstance(mode, Mode): 116 | mode_enum = mode 117 | else: 118 | raise TypeError("Mode must be a string or a Mode enum instance.") 119 | 120 | # Run HD-BET 121 | run_hd_bet( 122 | mri_fnames=[str(input_image_path)], 123 | output_fnames=[str(masked_image_path)], 124 | mode=mode_enum.value, 125 | device=device, 126 | # TODO consider postprocessing 127 | postprocess=False, 128 | do_tta=do_tta, 129 | keep_mask=True, 130 | overwrite=True, 131 | ) 132 | 133 | # Construct the path to the generated mask 134 | masked_image_path = Path(masked_image_path) 135 | hdbet_mask_path = masked_image_path.with_name( 136 | masked_image_path.name.replace(".nii.gz", "_mask.nii.gz") 137 | ) 138 | 139 | if hdbet_mask_path.resolve() != Path(brain_mask_path).resolve(): 140 | try: 141 | shutil.copyfile( 142 | src=str(hdbet_mask_path), 143 | dst=str(brain_mask_path), 144 | ) 145 | except Exception as e: 146 | raise RuntimeError(f"Error copying mask file: {e}") from e 147 | -------------------------------------------------------------------------------- /brainles_preprocessing/brats/__init__.py: -------------------------------------------------------------------------------- 1 | from .t1_centric import preprocess_brats_style_t1_centric 2 | from .t1c_centric import preprocess_brats_style_t1c_centric 3 | -------------------------------------------------------------------------------- /brainles_preprocessing/brats/t1_centric.py: -------------------------------------------------------------------------------- 1 | # # TODO currently broken, make this work again 2 | 3 | # from brainles_preprocessing.core import ( 4 | # Modality, 5 | # preprocess_modality_centric_to_atlas_space, 6 | # ) 7 | 8 | 9 | # def preprocess_brats_style_t1_centric( 10 | # input_t1: str, 11 | # output_t1: str, 12 | # input_t1c: str, 13 | # output_t1c: str, 14 | # input_t2: str, 15 | # output_t2: str, 16 | # input_flair: str, 17 | # output_flair: str, 18 | # bet_mode: str = "gpu", 19 | # limit_cuda_visible_devices: str | None = None, 20 | # temporary_directory: str | None = None, 21 | # keep_coregistration: str | None = None, 22 | # keep_atlas_registration: str | None = None, 23 | # keep_brainextraction: str | None = None, 24 | # ) -> None: 25 | # """ 26 | # Preprocesses multiple modalities in a BRATS-style dataset to atlas space. 27 | 28 | # Args: 29 | # input_t1 (str): Path to the input T1 modality data. 30 | # output_t1 (str): Path to save the preprocessed T1 modality data. 31 | # input_t1c (str): Path to the input T1c modality data. 32 | # output_t1c (str): Path to save the preprocessed T1c modality data. 33 | # input_t2 (str): Path to the input T2 modality data. 34 | # output_t2 (str): Path to save the preprocessed T2 modality data. 35 | # input_flair (str): Path to the input FLAIR modality data. 36 | # output_flair (str): Path to save the preprocessed FLAIR modality data. 37 | # bet_mode (str, optional): The mode for brain extraction, e.g., "gpu". 38 | # limit_cuda_visible_devices (str | None, optional): Specify CUDA devices to use. 39 | # temporary_directory (str | None, optional): Path to a custom temporary directory. 40 | # keep_coregistration (str | None, optional): Specify if coregistration should be retained. 41 | # keep_atlas_registration (str | None, optional): Specify if atlas registration should be retained. 42 | # keep_brainextraction (str | None, optional): Specify if brain extraction should be retained. 43 | 44 | # Description: 45 | # This function preprocesses multiple medical image modalities from a BRATS-style dataset to align them to the 46 | # atlas space. It provides options for various preprocessing steps such as brain extraction, registration, 47 | # and intensity normalization. 48 | 49 | # If a custom temporary directory is not provided using the `temporary_directory` parameter, a temporary 50 | # directory is created to store intermediate results. You can use a custom temporary directory path to 51 | # facilitate debugging or control the location of temporary files. 52 | 53 | # Example: 54 | # >>> preprocess_brats_style_t1_centric( 55 | # ... input_t1="/path/to/t1.nii", 56 | # ... output_t1="/path/to/preprocessed_t1.nii", 57 | # ... input_t1c="/path/to/t1c.nii", 58 | # ... output_t1c="/path/to/preprocessed_t1c.nii", 59 | # ... input_t2="/path/to/t2.nii", 60 | # ... output_t2="/path/to/preprocessed_t2.nii", 61 | # ... input_flair="/path/to/flair.nii", 62 | # ... output_flair="/path/to/preprocessed_flair.nii", 63 | # ... bet_mode="gpu", 64 | # ... limit_cuda_visible_devices="0", 65 | # ... temporary_directory="/path/to/custom_temp_dir", 66 | # ... keep_coregistration="True", 67 | # ... keep_atlas_registration="False", 68 | # ... keep_brainextraction=None 69 | # ... ) 70 | # """ 71 | # # Create a Modality object for the primary T1 modality 72 | # primary = Modality( 73 | # modality_name="t1", 74 | # input_path=input_t1, 75 | # output_path=output_t1, 76 | # bet=True, 77 | # ) 78 | 79 | # # Create Modality objects for other moving modalities 80 | # moving_modalities = [ 81 | # Modality( 82 | # modality_name="t1c", 83 | # input_path=input_t1c, 84 | # output_path=output_t1c, 85 | # bet=True, 86 | # ), 87 | # Modality( 88 | # modality_name="t2", 89 | # input_path=input_t2, 90 | # output_path=output_t2, 91 | # bet=True, 92 | # ), 93 | # Modality( 94 | # modality_name="flair", 95 | # input_path=input_flair, 96 | # output_path=output_flair, 97 | # bet=True, 98 | # ), 99 | # ] 100 | 101 | # # Perform preprocessing to align modalities to the atlas space 102 | # preprocess_modality_centric_to_atlas_space( 103 | # center_modality=primary, 104 | # moving_modalities=moving_modalities, 105 | # bet_mode=bet_mode, 106 | # limit_cuda_visible_devices=limit_cuda_visible_devices, 107 | # temporary_directory=temporary_directory, 108 | # keep_coregistration=keep_coregistration, 109 | # keep_atlas_registration=keep_atlas_registration, 110 | # keep_brainextraction=keep_brainextraction, 111 | # ) 112 | -------------------------------------------------------------------------------- /brainles_preprocessing/brats/t1c_centric.py: -------------------------------------------------------------------------------- 1 | # # TODO currently broken, make this work again 2 | 3 | # from brainles_preprocessing.core import ( 4 | # Modality, 5 | # preprocess_modality_centric_to_atlas_space, 6 | # ) 7 | 8 | 9 | # def preprocess_brats_style_t1c_centric( 10 | # input_t1c: str, 11 | # output_t1c: str, 12 | # input_t1: str, 13 | # output_t1: str, 14 | # input_t2: str, 15 | # output_t2: str, 16 | # input_flair: str, 17 | # output_flair: str, 18 | # bet_mode: str = "gpu", 19 | # limit_cuda_visible_devices: str | None = None, 20 | # temporary_directory: str | None = None, 21 | # keep_coregistration: str | None = None, 22 | # keep_atlas_registration: str | None = None, 23 | # keep_brainextraction: str | None = None, 24 | # ) -> None: 25 | # """ 26 | # Preprocesses multiple modalities in a BRATS-style dataset to atlas space. 27 | 28 | # Args: 29 | # input_t1c (str): Path to the input T1c modality data. 30 | # output_t1c (str): Path to save the preprocessed T1c modality data. 31 | # input_t1 (str): Path to the input T1 modality data. 32 | # output_t1 (str): Path to save the preprocessed T1 modality data. 33 | # input_t2 (str): Path to the input T2 modality data. 34 | # output_t2 (str): Path to save the preprocessed T2 modality data. 35 | # input_flair (str): Path to the input FLAIR modality data. 36 | # output_flair (str): Path to save the preprocessed FLAIR modality data. 37 | # bet_mode (str, optional): The mode for brain extraction, e.g., "gpu". 38 | # limit_cuda_visible_devices (str | None, optional): Specify CUDA devices to use. 39 | # temporary_directory (str | None, optional): Path to a custom temporary directory. 40 | # keep_coregistration (str | None, optional): Specify if coregistration should be retained. 41 | # keep_atlas_registration (str | None, optional): Specify if atlas registration should be retained. 42 | # keep_brainextraction (str | None, optional): Specify if brain extraction should be retained. 43 | 44 | # Description: 45 | # This function preprocesses multiple medical image modalities from a BRATS-style dataset to align them to the 46 | # atlas space. It provides options for various preprocessing steps such as brain extraction, registration, 47 | # and intensity normalization. 48 | 49 | # If a custom temporary directory is not provided using the `temporary_directory` parameter, a temporary 50 | # directory is created to store intermediate results. You can use a custom temporary directory path to 51 | # facilitate debugging or control the location of temporary files. 52 | 53 | # Example: 54 | # >>> preprocess_brats_style_t1c_centric( 55 | # ... input_t1c="/path/to/t1c.nii", 56 | # ... output_t1c="/path/to/preprocessed_t1c.nii", 57 | # ... input_t1="/path/to/t1.nii", 58 | # ... output_t1="/path/to/preprocessed_t1.nii", 59 | # ... input_t2="/path/to/t2.nii", 60 | # ... output_t2="/path/to/preprocessed_t2.nii", 61 | # ... input_flair="/path/to/flair.nii", 62 | # ... output_flair="/path/to/preprocessed_flair.nii", 63 | # ... bet_mode="gpu", 64 | # ... limit_cuda_visible_devices="0", 65 | # ... temporary_directory="/path/to/custom_temp_dir", 66 | # ... keep_coregistration="True", 67 | # ... keep_atlas_registration="False", 68 | # ... keep_brainextraction=None 69 | # ... ) 70 | # """ 71 | # # Create a Modality object for the primary T1c modality 72 | # primary = Modality( 73 | # modality_name="t1c", 74 | # input_path=input_t1c, 75 | # output_path=output_t1c, 76 | # bet=True, 77 | # ) 78 | 79 | # # Create Modality objects for other moving modalities 80 | # moving_modalities = [ 81 | # Modality( 82 | # modality_name="t1", 83 | # input_path=input_t1, 84 | # output_path=output_t1, 85 | # bet=True, 86 | # ), 87 | # Modality( 88 | # modality_name="t2", 89 | # input_path=input_t2, 90 | # output_path=output_t2, 91 | # bet=True, 92 | # ), 93 | # Modality( 94 | # modality_name="flair", 95 | # input_path=input_flair, 96 | # output_path=output_flair, 97 | # bet=True, 98 | # ), 99 | # ] 100 | 101 | # # Perform preprocessing to align modalities to the atlas space 102 | # preprocess_modality_centric_to_atlas_space( 103 | # center_modality=primary, 104 | # moving_modalities=moving_modalities, 105 | # bet_mode=bet_mode, 106 | # limit_cuda_visible_devices=limit_cuda_visible_devices, 107 | # temporary_directory=temporary_directory, 108 | # keep_coregistration=keep_coregistration, 109 | # keep_atlas_registration=keep_atlas_registration, 110 | # keep_brainextraction=keep_brainextraction, 111 | # ) 112 | -------------------------------------------------------------------------------- /brainles_preprocessing/cli.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from pathlib import Path 3 | import typer 4 | from typing_extensions import Annotated 5 | from importlib.metadata import version 6 | 7 | 8 | from brainles_preprocessing.modality import Modality, CenterModality 9 | from brainles_preprocessing.normalization.percentile_normalizer import ( 10 | PercentileNormalizer, 11 | ) 12 | from brainles_preprocessing.preprocessor import Preprocessor 13 | 14 | 15 | def version_callback(value: bool): 16 | __version__ = version("brainles_preprocessing") 17 | if value: 18 | typer.echo(f"Preprocessor CLI v{__version__}") 19 | raise typer.Exit() 20 | 21 | 22 | app = typer.Typer( 23 | context_settings={"help_option_names": ["-h", "--help"]}, add_completion=False 24 | ) 25 | 26 | 27 | @app.command() 28 | def main( 29 | input_t1c: Annotated[ 30 | str, 31 | typer.Option( 32 | "-t1c", 33 | "--input_t1c", 34 | help="The path to the T1c image", 35 | ), 36 | ], 37 | input_t1: Annotated[ 38 | str, 39 | typer.Option( 40 | "-t1", 41 | "--input_t1", 42 | help="The path to the T1 image", 43 | ), 44 | ], 45 | input_t2: Annotated[ 46 | str, 47 | typer.Option( 48 | "-t2", 49 | "--input_t2", 50 | help="The path to the T2 image", 51 | ), 52 | ], 53 | input_fla: Annotated[ 54 | str, 55 | typer.Option( 56 | "-fl", 57 | "--input_fla", 58 | help="The path to the FLAIR image", 59 | ), 60 | ], 61 | output_dir: Annotated[ 62 | str, 63 | typer.Option( 64 | "-o", 65 | "--output_dir", 66 | help="The path to the output directory", 67 | ), 68 | ], 69 | input_atlas: Annotated[ 70 | Optional[str], 71 | typer.Option( 72 | "-a", 73 | "--input_atlas", 74 | help="The path to the atlas image", 75 | ), 76 | ] = "SRI24 BraTS atlas", 77 | version: Annotated[ 78 | Optional[bool], 79 | typer.Option( 80 | "-v", 81 | "--version", 82 | callback=version_callback, 83 | is_eager=True, 84 | help="Print the version and exit.", 85 | ), 86 | ] = None, 87 | ): 88 | """ 89 | Preprocess the input images according to the BraTS protocol. 90 | """ 91 | 92 | output_dir = Path(output_dir) 93 | output_dir.mkdir(parents=True, exist_ok=True) 94 | 95 | # specify a normalizer 96 | percentile_normalizer = PercentileNormalizer( 97 | lower_percentile=0.1, 98 | upper_percentile=99.9, 99 | lower_limit=0, 100 | upper_limit=1, 101 | ) 102 | 103 | # define center and moving modalities 104 | center = CenterModality( 105 | modality_name="t1c", 106 | input_path=input_t1c, 107 | normalizer=percentile_normalizer, 108 | # specify the output paths for the raw and normalized images of each step - here only for atlas registered and brain extraction 109 | raw_skull_output_path=output_dir / "t1c_skull_raw.nii.gz", 110 | raw_bet_output_path=output_dir / "t1c_bet_raw.nii.gz", 111 | raw_defaced_output_path=output_dir / "t1c_defaced_raw.nii.gz", 112 | normalized_skull_output_path=output_dir / "t1c_skull_normalized.nii.gz", 113 | normalized_bet_output_path=output_dir / "t1c_bet_normalized.nii.gz", 114 | normalized_defaced_output_path=output_dir / "t1c_defaced_normalized.nii.gz", 115 | # specify output paths for the brain extraction and defacing masks 116 | bet_mask_output_path=output_dir / "t1c_bet_mask.nii.gz", 117 | defacing_mask_output_path=output_dir / "t1c_defacing_mask.nii.gz", 118 | ) 119 | 120 | for modality in ["t1", "t2", "fla"]: 121 | moving_modalities = [ 122 | Modality( 123 | modality_name=modality, 124 | input_path=eval(f"input_{modality}"), 125 | normalizer=percentile_normalizer, 126 | # specify the output paths for the raw and normalized images of each step - here only for atlas registered and brain extraction 127 | raw_skull_output_path=output_dir / f"{modality}_skull_raw.nii.gz", 128 | raw_bet_output_path=output_dir / f"{modality}_bet_raw.nii.gz", 129 | raw_defaced_output_path=output_dir / f"{modality}_defaced_raw.nii.gz", 130 | normalized_skull_output_path=output_dir 131 | / f"{modality}_skull_normalized.nii.gz", 132 | normalized_bet_output_path=output_dir 133 | / f"{modality}_bet_normalized.nii.gz", 134 | normalized_defaced_output_path=output_dir 135 | / f"{modality}_defaced_normalized.nii.gz", 136 | ) 137 | ] 138 | 139 | # if the input atlas is the SRI24 BraTS atlas, set it to None, because it will be picked up through the package 140 | if input_atlas == "SRI24 BraTS atlas": 141 | input_atlas = None 142 | 143 | # instantiate and run the preprocessor using defaults for registration/ brain extraction/ defacing backends 144 | preprocessor = Preprocessor( 145 | center_modality=center, 146 | moving_modalities=moving_modalities, 147 | temp_folder=output_dir / "temp", 148 | input_atlas=input_atlas, 149 | ) 150 | 151 | preprocessor.run() 152 | 153 | 154 | if __name__ == "__main__": 155 | app() 156 | -------------------------------------------------------------------------------- /brainles_preprocessing/constants.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, IntEnum 2 | 3 | 4 | class PreprocessorSteps(IntEnum): 5 | INPUT = 0 6 | COREGISTERED = 1 7 | ATLAS_REGISTERED = 2 8 | ATLAS_CORRECTED = 3 9 | BET = 4 10 | DEFACED = 5 11 | 12 | 13 | class Atlas(str, Enum): 14 | BRATS_SRI24 = "brats_sri24.nii" 15 | """Slightly modified SRI24 atlas as found in the BraTS challenges""" 16 | BRATS_SRI24_SKULLSTRIPPED = "brats_sri24_skullstripped.nii" 17 | """Slightly modified SRI24 skull stripped atlas as found in the BraTS challenges""" 18 | 19 | SRI24 = "sri24.nii" 20 | """SRI24 atlas from https://www.nitrc.org/frs/download.php/4502/sri24_anatomy_unstripped_nifti.zip""" 21 | SRI24_SKULLSTRIPPED = "sri24_skullstripped.nii" 22 | """SRI24 skull stripped atlas from https://www.nitrc.org/frs/download.php/4499/sri24_anatomy_nifti.zip""" 23 | 24 | BRATS_MNI152 = "brats_MNI152lin_T1_1mm.nii.gz" 25 | """Slightly modified MNI152 atlas as found in the BraTS challenges""" 26 | -------------------------------------------------------------------------------- /brainles_preprocessing/defacing/__init__.py: -------------------------------------------------------------------------------- 1 | from .defacer import Defacer 2 | from .quickshear.quickshear import QuickshearDefacer 3 | -------------------------------------------------------------------------------- /brainles_preprocessing/defacing/defacer.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from pathlib import Path 3 | from typing import Union 4 | 5 | from auxiliary.nifti.io import read_nifti, write_nifti 6 | 7 | 8 | class Defacer(ABC): 9 | """ 10 | Base class for defacing medical images using brain masks. 11 | 12 | Subclasses should implement the `deface` method to generate a defaced image 13 | based on the provided input image and mask. 14 | """ 15 | 16 | @abstractmethod 17 | def deface( 18 | self, 19 | input_image_path: Union[str, Path], 20 | mask_image_path: Union[str, Path], 21 | ) -> None: 22 | """ 23 | Generate a defacing mask provided an input image. 24 | 25 | Args: 26 | input_image_path (str or Path): Path to the input image (NIfTI format). 27 | mask_image_path (str or Path): Path to the output mask image (NIfTI format). 28 | """ 29 | pass 30 | 31 | def apply_mask( 32 | self, 33 | input_image_path: Union[str, Path], 34 | mask_path: Union[str, Path], 35 | defaced_image_path: Union[str, Path], 36 | ) -> None: 37 | """ 38 | Apply a brain mask to an input image. 39 | 40 | Args: 41 | input_image_path (str or Path): Path to the input image (NIfTI format). 42 | mask_path (str or Path): Path to the brain mask image (NIfTI format). 43 | defaced_image_path (str or Path): Path to save the resulting defaced image (NIfTI format). 44 | """ 45 | 46 | if not input_image_path.is_file(): 47 | raise FileNotFoundError( 48 | f"Input image file does not exist: {input_image_path}" 49 | ) 50 | if not mask_path.is_file(): 51 | raise FileNotFoundError(f"Mask file does not exist: {mask_path}") 52 | 53 | try: 54 | # Read data 55 | input_data = read_nifti(str(input_image_path)) 56 | mask_data = read_nifti(str(mask_path)) 57 | except Exception as e: 58 | raise RuntimeError( 59 | f"An error occurred while reading input files: {e}" 60 | ) from e 61 | 62 | # Check that the input and mask have the same shape 63 | if input_data.shape != mask_data.shape: 64 | raise ValueError("Input image and mask must have the same dimensions.") 65 | 66 | # Apply mask (element-wise multiplication) 67 | masked_data = input_data * mask_data 68 | 69 | # Save the defaced image 70 | write_nifti( 71 | input_array=masked_data, 72 | output_nifti_path=str(defaced_image_path), 73 | reference_nifti_path=str(input_image_path), 74 | create_parent_directory=True, 75 | ) 76 | -------------------------------------------------------------------------------- /brainles_preprocessing/defacing/quickshear/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/defacing/quickshear/__init__.py -------------------------------------------------------------------------------- /brainles_preprocessing/defacing/quickshear/quickshear.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from typing import Union 3 | 4 | import nibabel as nib 5 | 6 | from brainles_preprocessing.defacing.defacer import Defacer 7 | from brainles_preprocessing.defacing.quickshear.nipy_quickshear import run_quickshear 8 | from auxiliary.nifti.io import write_nifti 9 | 10 | 11 | class QuickshearDefacer(Defacer): 12 | """ 13 | Defacer using Quickshear algorithm. 14 | 15 | Quickshear uses a skull stripped version of an anatomical images as a reference to deface the unaltered anatomical image. 16 | 17 | Base publication: 18 | - PDF: https://www.researchgate.net/profile/J-Hale/publication/262319696_Quickshear_defacing_for_neuroimages/links/570b97ee08aed09e917516b1/Quickshear-defacing-for-neuroimages.pdf 19 | - Bibtex: 20 | ``` 21 | @article{schimke2011quickshear, 22 | title={Quickshear Defacing for Neuroimages.}, 23 | author={Schimke, Nakeisha and Hale, John}, 24 | journal={HealthSec}, 25 | volume={11}, 26 | pages={11}, 27 | year={2011} 28 | } 29 | ``` 30 | """ 31 | 32 | def __init__(self, buffer: float = 10.0): 33 | """Initialize Quickshear defacer 34 | 35 | Args: 36 | buffer (float, optional): buffer parameter from quickshear algorithm. Defaults to 10.0. 37 | """ 38 | super().__init__() 39 | self.buffer = buffer 40 | 41 | def deface( 42 | self, 43 | input_image_path: Union[str, Path], 44 | mask_image_path: Union[str, Path], 45 | ) -> None: 46 | """ 47 | Generate a defacing mask using Quickshear algorithm. 48 | 49 | Note: 50 | The input image must be a brain-extracted (skull-stripped) image. 51 | 52 | Args: 53 | input_image_path (str or Path): Path to the brain-extracted input image. 54 | mask_image_path (str or Path): Path to save the generated mask image. 55 | """ 56 | 57 | bet_img = nib.load(str(input_image_path)) 58 | mask = run_quickshear(bet_img=bet_img, buffer=self.buffer) 59 | write_nifti( 60 | input_array=mask, 61 | output_nifti_path=str(mask_image_path), 62 | reference_nifti_path=str(input_image_path), 63 | ) 64 | -------------------------------------------------------------------------------- /brainles_preprocessing/normalization/__init__.py: -------------------------------------------------------------------------------- 1 | from .normalizer_base import Normalizer 2 | from .percentile_normalizer import PercentileNormalizer 3 | from .windowing_normalizer import WindowingNormalizer 4 | -------------------------------------------------------------------------------- /brainles_preprocessing/normalization/normalizer_base.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | 4 | class Normalizer(ABC): 5 | """ 6 | Abstract base class for image normalization methods. 7 | """ 8 | 9 | def __init__(self): 10 | super().__init__() 11 | 12 | @abstractmethod 13 | def normalize(self, image): 14 | """ 15 | Normalize the input image based on the chosen method. 16 | 17 | Parameters: 18 | image (numpy.ndarray): The input image. 19 | 20 | Returns: 21 | numpy.ndarray: The normalized image. 22 | """ 23 | pass 24 | -------------------------------------------------------------------------------- /brainles_preprocessing/normalization/percentile_normalizer.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from .normalizer_base import Normalizer 3 | 4 | 5 | class PercentileNormalizer(Normalizer): 6 | """ 7 | Normalizer subclass for percentile-based image normalization. 8 | """ 9 | 10 | def __init__( 11 | self, 12 | lower_percentile: float = 0.0, 13 | upper_percentile: float = 100.0, 14 | lower_limit: float = 0, 15 | upper_limit: float = 1, 16 | ): 17 | """ 18 | Initialize the PercentileNormalizer. 19 | 20 | Parameters: 21 | lower_percentile (float): The lower percentile for mapping. 22 | upper_percentile (float): The upper percentile for mapping. 23 | lower_limit (float): The lower limit for normalized values. 24 | upper_limit (float): The upper limit for normalized values. 25 | """ 26 | super().__init__() 27 | self.lower_percentile = lower_percentile 28 | self.upper_percentile = upper_percentile 29 | self.lower_limit = lower_limit 30 | self.upper_limit = upper_limit 31 | 32 | def normalize(self, image: np.ndarray): 33 | """ 34 | Normalize the input image using percentile-based mapping. 35 | 36 | Parameters: 37 | image (numpy.ndarray): The input image. 38 | 39 | Returns: 40 | numpy.ndarray: The percentile-normalized image. 41 | """ 42 | lower_value = np.percentile(image, self.lower_percentile) 43 | upper_value = np.percentile(image, self.upper_percentile) 44 | normalized_image = np.clip( 45 | (image - lower_value) / (upper_value - lower_value), 0, 1 46 | ) 47 | normalized_image = ( 48 | normalized_image * (self.upper_limit - self.lower_limit) + self.lower_limit 49 | ) 50 | return normalized_image 51 | -------------------------------------------------------------------------------- /brainles_preprocessing/normalization/windowing_normalizer.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from .normalizer_base import Normalizer 3 | 4 | 5 | class WindowingNormalizer(Normalizer): 6 | """ 7 | Normalizer subclass for windowing-based image normalization. 8 | """ 9 | 10 | def __init__(self, center, width): 11 | """ 12 | Initialize the WindowingNormalizer. 13 | 14 | Parameters: 15 | center (float): The window center. 16 | width (float): The window width. 17 | """ 18 | super().__init__() 19 | self.center = center 20 | self.width = width 21 | 22 | def normalize(self, image): 23 | """ 24 | Normalize the input image using windowing. 25 | 26 | Parameters: 27 | image (numpy.ndarray): The input image. 28 | 29 | Returns: 30 | numpy.ndarray: The windowed normalized image. 31 | """ 32 | min_value = self.center - self.width / 2 33 | max_value = self.center + self.width / 2 34 | windowed_image = np.clip(image, min_value, max_value) 35 | return windowed_image 36 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/ANTs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/ANTs/__init__.py -------------------------------------------------------------------------------- /brainles_preprocessing/registration/__init__.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | 3 | 4 | try: 5 | from .ANTs.ANTs import ANTsRegistrator 6 | except ImportError: 7 | warnings.warn( 8 | "ANTS package not found. If you want to use it, please install it using 'pip install antspyx'" 9 | ) 10 | 11 | 12 | from .niftyreg.niftyreg import NiftyRegRegistrator 13 | 14 | 15 | try: 16 | from .elastix.elastix import ElastixRegistrator 17 | except ImportError: 18 | warnings.warn( 19 | "itk-elastix package not found. If you want to use it, please install it using 'pip install brainles_preprocessing[itk-elastix]'" 20 | ) 21 | 22 | try: 23 | from .greedy.greedy import GreedyRegistrator 24 | except ImportError: 25 | warnings.warn( 26 | "picsl_greedy package not found. If you want to use it, please install it using 'pip install brainles_preprocessing[picsl_greedy]'" 27 | ) 28 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/elastix/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/elastix/__init__.py -------------------------------------------------------------------------------- /brainles_preprocessing/registration/elastix/elastix.py: -------------------------------------------------------------------------------- 1 | # TODO add typing and docs 2 | from typing import Optional 3 | import os 4 | 5 | import itk 6 | 7 | from brainles_preprocessing.registration.registrator import Registrator 8 | from brainles_preprocessing.utils import check_and_add_suffix 9 | 10 | 11 | class ElastixRegistrator(Registrator): 12 | def __init__( 13 | self, 14 | ): 15 | pass 16 | 17 | def register( 18 | self, 19 | fixed_image_path: str, 20 | moving_image_path: str, 21 | transformed_image_path: str, 22 | matrix_path: str, 23 | log_file_path: Optional[str] = None, 24 | parameter_object: Optional[itk.ParameterObject] = None, 25 | ) -> None: 26 | """ 27 | Register images using elastix. 28 | 29 | Args: 30 | fixed_image_path (str): Path to the fixed image. 31 | moving_image_path (str): Path to the moving image. 32 | transformed_image_path (str): Path to the transformed image (output). 33 | matrix_path (str): Path to the transformation matrix (output). This gets overwritten if it already exists. 34 | log_file_path (Optional[str]): Path to the log file. 35 | parameter_object (Optional[itk.ParameterObject]): The parameter object for elastix registration. 36 | """ 37 | # initialize parameter object 38 | if parameter_object is None: 39 | parameter_object = self.__initialize_parameter_object() 40 | # add .txt suffix to the matrix path if it doesn't have any extension 41 | matrix_path = check_and_add_suffix(matrix_path, ".txt") 42 | 43 | # read images as itk images 44 | fixed_image = itk.imread(fixed_image_path) 45 | moving_image = itk.imread(moving_image_path) 46 | 47 | if log_file_path is not None: 48 | # split log_file_path 49 | log_path, log_file = os.path.split(log_file_path) 50 | result_image, result_transform_params = itk.elastix_registration_method( 51 | fixed_image, 52 | moving_image, 53 | parameter_object=parameter_object, 54 | log_to_file=True, 55 | log_file_name=log_file, 56 | output_directory=log_path, 57 | ) 58 | else: 59 | result_image, result_transform_params = itk.elastix_registration_method( 60 | fixed_image, 61 | moving_image, 62 | parameter_object=parameter_object, 63 | log_to_console=True, 64 | ) 65 | 66 | itk.imwrite(result_image, transformed_image_path) 67 | 68 | if not os.path.exists(matrix_path): 69 | result_transform_params.WriteParameterFile( 70 | result_transform_params.GetParameterMap(0), 71 | matrix_path, 72 | ) 73 | 74 | def transform( 75 | self, 76 | fixed_image_path: str, 77 | moving_image_path: str, 78 | transformed_image_path: str, 79 | matrix_path: str, 80 | log_file_path: Optional[str] = None, 81 | ) -> None: 82 | """ 83 | Apply a transformation using elastix. 84 | 85 | Args: 86 | fixed_image_path (str): Path to the fixed image. 87 | moving_image_path (str): Path to the moving image. 88 | transformed_image_path (str): Path to the transformed image (output). 89 | matrix_path (str): Path to the transformation matrix (output). This gets overwritten if it already exists. 90 | log_file_path (Optional[str]): Path to the log file. 91 | """ 92 | parameter_object = self.__initialize_parameter_object() 93 | 94 | # check if the matrix file exists 95 | if os.path.exists(matrix_path): 96 | parameter_object.SetParameter( 97 | 0, "InitialTransformParametersFileName", matrix_path 98 | ) 99 | 100 | self.register( 101 | fixed_image_path, 102 | moving_image_path, 103 | transformed_image_path, 104 | matrix_path, 105 | log_file_path, 106 | parameter_object, 107 | ) 108 | 109 | def __initialize_parameter_object(self) -> itk.ParameterObject: 110 | """ 111 | Initialize the parameter object for elastix registration. 112 | 113 | Returns: 114 | itk.ParameterObject: The parameter object for registration. 115 | """ 116 | parameter_object = itk.ParameterObject.New() 117 | default_rigid_parameter_map = parameter_object.GetDefaultParameterMap("rigid") 118 | parameter_object.AddParameterMap(default_rigid_parameter_map) 119 | return parameter_object 120 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/greedy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/greedy/__init__.py -------------------------------------------------------------------------------- /brainles_preprocessing/registration/greedy/greedy.py: -------------------------------------------------------------------------------- 1 | # TODO add typing and docs 2 | from typing import Optional 3 | import contextlib 4 | import os 5 | 6 | from picsl_greedy import Greedy3D 7 | 8 | from brainles_preprocessing.registration.registrator import Registrator 9 | from brainles_preprocessing.utils import check_and_add_suffix 10 | 11 | 12 | class GreedyRegistrator(Registrator): 13 | def __init__( 14 | self, 15 | ): 16 | pass 17 | 18 | def register( 19 | self, 20 | fixed_image_path: str, 21 | moving_image_path: str, 22 | transformed_image_path: str, 23 | matrix_path: str, 24 | log_file_path: Optional[str] = None, 25 | ) -> None: 26 | """ 27 | Register images using greedy. Ref: https://pypi.org/project/picsl-greedy/ and https://greedy.readthedocs.io/en/latest/reference.html#greedy-usage 28 | 29 | Args: 30 | fixed_image_path (str): Path to the fixed image. 31 | moving_image_path (str): Path to the moving image. 32 | transformed_image_path (str): Path to the transformed image (output). 33 | matrix_path (str): Path to the transformation matrix (output). This gets overwritten if it already exists. 34 | log_file_path (Optional[str]): Path to the log file, which is not used. 35 | """ 36 | # add .txt suffix to the matrix path if it doesn't have any extension 37 | matrix_path = check_and_add_suffix(matrix_path, ".mat") 38 | 39 | registor = Greedy3D() 40 | # these parameters are taken from the OG BraTS Pipeline [https://github.com/CBICA/CaPTk/blob/master/src/applications/BraTSPipeline.cxx] 41 | command_to_run = f"-i {fixed_image_path} {moving_image_path} -o {matrix_path} -a -dof 6 -m NMI -n 100x50x5 -ia-image-centers" 42 | 43 | if log_file_path is not None: 44 | with open(log_file_path, "a+") as f: 45 | with contextlib.redirect_stdout(f): 46 | registor.execute(command_to_run) 47 | else: 48 | registor.execute(command_to_run) 49 | 50 | self.transform( 51 | fixed_image_path, moving_image_path, transformed_image_path, matrix_path 52 | ) 53 | 54 | def transform( 55 | self, 56 | fixed_image_path: str, 57 | moving_image_path: str, 58 | transformed_image_path: str, 59 | matrix_path: str, 60 | interpolator: Optional[str] = "LINEAR", 61 | log_file_path: Optional[str] = None, 62 | ) -> None: 63 | """ 64 | Apply a transformation using greedy. 65 | 66 | Args: 67 | fixed_image_path (str): Path to the fixed image. 68 | moving_image_path (str): Path to the moving image. 69 | transformed_image_path (str): Path to the transformed image (output). 70 | matrix_path (str): Path to the transformation matrix (output). This gets overwritten if it already exists. 71 | interpolator (Optional[str]): The interpolator to use; one of NN, LINEAR or LABEL. 72 | log_file_path (Optional[str]): Path to the log file, which is not used. 73 | """ 74 | registor = Greedy3D() 75 | interpolator_upper = interpolator.upper() 76 | if "LABEL" in interpolator_upper: 77 | interpolator_upper += " 0.3vox" 78 | 79 | matrix_path = check_and_add_suffix(matrix_path, ".mat") 80 | 81 | if not os.path.exists(matrix_path): 82 | self.register( 83 | fixed_image_path, 84 | moving_image_path, 85 | transformed_image_path, 86 | matrix_path, 87 | log_file_path, 88 | ) 89 | 90 | command_to_run = f"-rf {fixed_image_path} -rm {moving_image_path} {transformed_image_path} -r {matrix_path} -ri {interpolator_upper}" 91 | if log_file_path is not None: 92 | with open(log_file_path, "a+") as f: 93 | with contextlib.redirect_stdout(f): 94 | registor.execute(command_to_run) 95 | else: 96 | registor.execute(command_to_run) 97 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/niftyreg/__init__.py -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from auxiliary.runscript import ScriptRunner 4 | from auxiliary.turbopath import turbopath 5 | 6 | from brainles_preprocessing.registration.registrator import Registrator 7 | 8 | # from auxiliary import ScriptRunner 9 | 10 | 11 | class NiftyRegRegistrator(Registrator): 12 | def __init__( 13 | self, 14 | registration_abspath: str = os.path.dirname(os.path.abspath(__file__)), 15 | registration_script: str | None = None, 16 | transformation_script: str | None = None, 17 | ): 18 | """ 19 | Initialize the NiftyRegRegistrator. 20 | 21 | Args: 22 | registration_abspath (str): Absolute path to the registration directory. 23 | registration_script (str, optional): Path to the registration script. If None, a default script will be used. 24 | transformation_script (str, optional): Path to the transformation script. If None, a default script will be used. 25 | """ 26 | # Set default registration script 27 | if registration_script is None: 28 | self.registration_script = os.path.join( 29 | registration_abspath, "niftyreg_scripts", "rigid_reg.sh" 30 | ) 31 | else: 32 | self.registration_script = registration_script 33 | 34 | # Set default transformation script 35 | if transformation_script is None: 36 | self.transformation_script = os.path.join( 37 | registration_abspath, "niftyreg_scripts", "transform.sh" 38 | ) 39 | else: 40 | self.transformation_script = transformation_script 41 | 42 | def register( 43 | self, 44 | fixed_image_path: str, 45 | moving_image_path: str, 46 | transformed_image_path: str, 47 | matrix_path: str, 48 | log_file_path: str, 49 | ) -> None: 50 | """ 51 | Register images using NiftyReg. 52 | 53 | Args: 54 | fixed_image_path (str): Path to the fixed image. 55 | moving_image_path (str): Path to the moving image. 56 | transformed_image_path (str): Path to the transformed image (output). 57 | matrix_path (str): Path to the transformation matrix (output). 58 | log_file_path (str): Path to the log file. 59 | """ 60 | runner = ScriptRunner( 61 | script_path=self.registration_script, 62 | log_path=log_file_path, 63 | ) 64 | 65 | niftyreg_executable = str( 66 | turbopath(__file__).parent + "/niftyreg_scripts/reg_aladin", 67 | ) 68 | 69 | turbopath(matrix_path) 70 | if matrix_path.suffix != ".txt": 71 | matrix_path = matrix_path.with_suffix(".txt") 72 | 73 | input_params = [ 74 | turbopath(niftyreg_executable), 75 | turbopath(fixed_image_path), 76 | turbopath(moving_image_path), 77 | turbopath(transformed_image_path), 78 | turbopath(matrix_path), 79 | ] 80 | 81 | # Call the run method to execute the script and capture the output in the log file 82 | success, error = runner.run(input_params) 83 | 84 | # if success: 85 | # print("Script executed successfully. Check the log file for details.") 86 | # else: 87 | # print("Script execution failed:", error) 88 | 89 | def transform( 90 | self, 91 | fixed_image_path: str, 92 | moving_image_path: str, 93 | transformed_image_path: str, 94 | matrix_path: str, 95 | log_file_path: str, 96 | ) -> None: 97 | """ 98 | Apply a transformation using NiftyReg. 99 | 100 | Args: 101 | fixed_image_path (str): Path to the fixed image. 102 | moving_image_path (str): Path to the moving image. 103 | transformed_image_path (str): Path to the transformed image (output). 104 | matrix_path (str): Path to the transformation matrix. 105 | log_file_path (str): Path to the log file. 106 | """ 107 | runner = ScriptRunner( 108 | script_path=self.transformation_script, 109 | log_path=log_file_path, 110 | ) 111 | 112 | niftyreg_executable = str( 113 | turbopath(__file__).parent + "/niftyreg_scripts/reg_resample", 114 | ) 115 | 116 | turbopath(matrix_path) 117 | if matrix_path.suffix != ".txt": 118 | matrix_path = matrix_path.with_suffix(".txt") 119 | 120 | input_params = [ 121 | turbopath(niftyreg_executable), 122 | turbopath(fixed_image_path), 123 | turbopath(moving_image_path), 124 | turbopath(transformed_image_path), 125 | turbopath(matrix_path), 126 | # we need to add txt as this is the format for niftyreg matrixes 127 | ] 128 | 129 | # Call the run method to execute the script and capture the output in the log file 130 | success, error = runner.run(input_params) 131 | 132 | # if success: 133 | # print("Script executed successfully. Check the log file for details.") 134 | # else: 135 | # print("Script execution failed:", error) 136 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/groupwise_niftyreg_params.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################################################ 4 | ###################### PARAMETERS THAT CAN BE CHANGED ###################### 5 | ############################################################################ 6 | # Array that contains the input images to create the atlas 7 | export IMG_INPUT=(`ls /path/to/all/your/images_*.nii`) 8 | export IMG_INPUT_MASK= # leave empty to not use floating masks 9 | 10 | # template image to use to initialise the atlas creation 11 | export TEMPLATE=`ls ${IMG_INPUT[0]}` 12 | export TEMPLATE_MASK= # leave empty to not use a reference mask 13 | 14 | # folder where the result images will be saved 15 | export RES_FOLDER=`pwd`/groupwise_result 16 | 17 | # argument to use for the affine (reg_aladin) 18 | export AFFINE_args="-omp 4" 19 | # argument to use for the non-rigid registration (reg_f3d) 20 | export NRR_args="-omp 4" 21 | 22 | # number of affine loop to perform - Note that the first step is always rigid 23 | export AFF_IT_NUM=5 24 | # number of non-rigid loop to perform 25 | export NRR_IT_NUM=10 26 | 27 | # grid engine arguments 28 | export QSUB_CMD="qsub -l h_rt=05:00:00 -l tmem=0.9G -l h_vmem=0.9G -l vf=0.9G -l s_stack=10240 -j y -S /bin/csh -b y -cwd -V -R y -pe smp 4" 29 | ############################################################################ 30 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_aladin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_aladin -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_average: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_average -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_f3d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_f3d -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_jacobian: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_jacobian -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_measure: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_measure -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_resample: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_resample -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_tools: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_tools -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_transform: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_transform -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/AffineDeformationFieldKernel.h: -------------------------------------------------------------------------------- 1 | #ifndef AFFINEDEFORMATIONFIELDKERNEL_H 2 | #define AFFINEDEFORMATIONFIELDKERNEL_H 3 | 4 | #include "Kernel.h" 5 | 6 | class AffineDeformationFieldKernel : public Kernel { 7 | public: 8 | static std::string getName() { 9 | return "AffineDeformationFieldKernel"; 10 | } 11 | 12 | AffineDeformationFieldKernel( std::string name) : Kernel(name) { 13 | } 14 | 15 | virtual ~AffineDeformationFieldKernel(){} 16 | virtual void calculate(bool compose = false) = 0; 17 | }; 18 | 19 | #endif // AFFINEDEFORMATIONFIELDKERNEL_H 20 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/AladinContent.h: -------------------------------------------------------------------------------- 1 | #ifndef ALADINCONTENT_H_ 2 | #define ALADINCONTENT_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "Kernel.h" 10 | #include "_reg_blockMatching.h" 11 | 12 | class AladinContent { 13 | public: 14 | 15 | AladinContent(); 16 | AladinContent(nifti_image *CurrentReferenceIn, 17 | nifti_image *CurrentFloatingIn, 18 | int *CurrentReferenceMaskIn, 19 | size_t byte, 20 | const unsigned int percentageOfBlocks, 21 | const unsigned int InlierLts, 22 | int BlockStepSize); 23 | AladinContent(nifti_image *CurrentReferenceIn, 24 | nifti_image *CurrentFloatingIn, 25 | int *CurrentReferenceMaskIn, 26 | size_t byte); 27 | AladinContent(nifti_image *CurrentReferenceIn, 28 | nifti_image *CurrentFloatingIn, 29 | int *CurrentReferenceMaskIn, 30 | mat44 *transMat, 31 | size_t byte, 32 | const unsigned int percentageOfBlocks, 33 | const unsigned int InlierLts, 34 | int BlockStepSize); 35 | AladinContent(nifti_image *CurrentReferenceIn, 36 | nifti_image *CurrentFloatingIn, 37 | int *CurrentReferenceMaskIn, 38 | mat44 *transMat, 39 | size_t byte); 40 | 41 | virtual ~AladinContent(); 42 | 43 | /* *************************************************************** */ 44 | void AllocateWarpedImage(); 45 | void ClearWarpedImage(); 46 | /* *************************************************************** */ 47 | void AllocateDeformationField(size_t bytes); 48 | void ClearDeformationField(); 49 | virtual void initVars(); 50 | 51 | unsigned int floatingVoxels, referenceVoxels; 52 | 53 | //getters 54 | virtual nifti_image *getCurrentDeformationField() 55 | { 56 | return this->CurrentDeformationField; 57 | } 58 | nifti_image *getCurrentReference() 59 | { 60 | return this->CurrentReference; 61 | } 62 | nifti_image *getCurrentFloating() 63 | { 64 | return this->CurrentFloating; 65 | } 66 | virtual nifti_image *getCurrentWarped(int = 0) 67 | { 68 | return this->CurrentWarped; 69 | } 70 | int *getCurrentReferenceMask() 71 | { 72 | return this->CurrentReferenceMask; 73 | } 74 | mat44 *getTransformationMatrix() 75 | { 76 | return this->transformationMatrix; 77 | } 78 | virtual _reg_blockMatchingParam* getBlockMatchingParams() { 79 | return this->blockMatchingParams; 80 | } 81 | //setters 82 | virtual void setTransformationMatrix(mat44 *transformationMatrixIn) 83 | { 84 | this->transformationMatrix = transformationMatrixIn; 85 | } 86 | virtual void setCurrentDeformationField(nifti_image *CurrentDeformationFieldIn) 87 | { 88 | this->CurrentDeformationField = CurrentDeformationFieldIn; 89 | } 90 | virtual void setCurrentWarped(nifti_image *CurrentWarpedImageIn) 91 | { 92 | this->CurrentWarped = CurrentWarpedImageIn; 93 | } 94 | 95 | virtual void setCurrentReferenceMask(int *, size_t) {} 96 | void setCaptureRange(const int captureRangeIn); 97 | // 98 | virtual void setBlockMatchingParams(_reg_blockMatchingParam* bmp) { 99 | blockMatchingParams = bmp; 100 | } 101 | 102 | virtual bool isCurrentComputationDoubleCapable(); 103 | 104 | protected: 105 | nifti_image *CurrentReference; 106 | nifti_image *CurrentFloating; 107 | int *CurrentReferenceMask; 108 | 109 | nifti_image *CurrentDeformationField; 110 | nifti_image *CurrentWarped; 111 | 112 | mat44 *transformationMatrix; 113 | mat44 refMatrix_xyz; 114 | mat44 floMatrix_ijk; 115 | _reg_blockMatchingParam* blockMatchingParams; 116 | 117 | //int floatingDatatype; 118 | size_t bytes; 119 | unsigned int currentPercentageOfBlockToUse; 120 | unsigned int inlierLts; 121 | int stepSizeBlock; 122 | }; 123 | 124 | #endif //ALADINCONTENT_H_ 125 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/BlockMatchingKernel.h: -------------------------------------------------------------------------------- 1 | #ifndef BLOCKMATCHINGKERNEL_H 2 | #define BLOCKMATCHINGKERNEL_H 3 | 4 | #include "Kernel.h" 5 | 6 | class BlockMatchingKernel : public Kernel { 7 | public: 8 | static std::string getName() { 9 | return "blockMatchingKernel"; 10 | } 11 | BlockMatchingKernel(std::string name) : Kernel(name) { 12 | 13 | } 14 | virtual ~BlockMatchingKernel(){} 15 | virtual void calculate() = 0; 16 | }; 17 | 18 | #endif // BLOCKMATCHINGKERNEL_H 19 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/CPUAffineDeformationFieldKernel.h: -------------------------------------------------------------------------------- 1 | #ifndef CPUAFFINEDEFORMATIONFIELDKERNEL_H 2 | #define CPUAFFINEDEFORMATIONFIELDKERNEL_H 3 | 4 | #include "AffineDeformationFieldKernel.h" 5 | #include "AladinContent.h" 6 | #include 7 | 8 | 9 | class CPUAffineDeformationFieldKernel : public AffineDeformationFieldKernel { 10 | public: 11 | CPUAffineDeformationFieldKernel(AladinContent *con, std::string nameIn); 12 | 13 | void calculate(bool compose = false); 14 | 15 | mat44 *affineTransformation; 16 | nifti_image *deformationFieldImage; 17 | int *mask; 18 | }; 19 | 20 | #endif // AFFINEDEFORMATIONFIELDKERNEL_H 21 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/CPUBlockMatchingKernel.h: -------------------------------------------------------------------------------- 1 | #ifndef CPUBLOCKMATCHINGKERNEL_H 2 | #define CPUBLOCKMATCHINGKERNEL_H 3 | 4 | #include "BlockMatchingKernel.h" 5 | #include "_reg_blockMatching.h" 6 | #include "nifti1_io.h" 7 | #include "AladinContent.h" 8 | 9 | class CPUBlockMatchingKernel : public BlockMatchingKernel { 10 | public: 11 | 12 | CPUBlockMatchingKernel(AladinContent *con, std::string name); 13 | 14 | void calculate(); 15 | 16 | nifti_image *reference; 17 | nifti_image *warped; 18 | _reg_blockMatchingParam* params; 19 | int *mask; 20 | 21 | }; 22 | 23 | #endif // CPUBLOCKMATCHINGKERNEL_H 24 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/CPUConvolutionKernel.h: -------------------------------------------------------------------------------- 1 | #ifndef CPUCONVOLUTIONKERNEL_H 2 | #define CPUCONVOLUTIONKERNEL_H 3 | 4 | #include "ConvolutionKernel.h" 5 | #include 6 | 7 | class CPUConvolutionKernel : public ConvolutionKernel { 8 | public: 9 | CPUConvolutionKernel(std::string name); 10 | 11 | void calculate(nifti_image *image, float *sigma, int kernelType, int *mask = NULL, bool *timePoints = NULL, bool *axis = NULL); 12 | }; 13 | 14 | #endif // CPUCONVOLUTIONKERNEL_H 15 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/CPUKernelFactory.h: -------------------------------------------------------------------------------- 1 | #ifndef CPUKERNLFACTORY_H 2 | #define CPUKERNLFACTORY_H 3 | 4 | #include "KernelFactory.h" 5 | 6 | class AladinContent; 7 | 8 | class CPUKernelFactory : public KernelFactory 9 | { 10 | public: 11 | Kernel *produceKernel(std::string name, AladinContent *con) const; 12 | }; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/CPUOptimiseKernel.h: -------------------------------------------------------------------------------- 1 | #ifndef CPUOPTIMISEKERNEL_H 2 | #define CPUOPTIMISEKERNEL_H 3 | 4 | #include "OptimiseKernel.h" 5 | #include "_reg_blockMatching.h" 6 | #include "nifti1_io.h" 7 | #include "AladinContent.h" 8 | 9 | class CPUOptimiseKernel : public OptimiseKernel { 10 | public: 11 | CPUOptimiseKernel(AladinContent *con, std::string name); 12 | 13 | _reg_blockMatchingParam *blockMatchingParams; 14 | mat44 *transformationMatrix; 15 | 16 | void calculate(bool affine); 17 | 18 | }; 19 | 20 | #endif // CPUOPTIMISEKERNEL_H 21 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/CPUResampleImageKernel.h: -------------------------------------------------------------------------------- 1 | #ifndef CPURESAMPLEIMAGEKERNEL_H 2 | #define CPURESAMPLEIMAGEKERNEL_H 3 | 4 | #include "ResampleImageKernel.h" 5 | #include "AladinContent.h" 6 | 7 | class CPUResampleImageKernel : public ResampleImageKernel 8 | { 9 | public: 10 | CPUResampleImageKernel(AladinContent *con, std::string name); 11 | 12 | nifti_image *floatingImage; 13 | nifti_image *warpedImage; 14 | nifti_image *deformationField; 15 | int *mask; 16 | 17 | void calculate(int interp, float paddingValue, bool *dti_timepoint = NULL, mat33 * jacMat = NULL); 18 | }; 19 | 20 | #endif // CPURESAMPLEIMAGEKERNEL_H 21 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/ConvolutionKernel.h: -------------------------------------------------------------------------------- 1 | #ifndef CONVOLUTIONKERNEL_H 2 | #define CONVOLUTIONKERNEL_H 3 | 4 | #include "Kernel.h" 5 | #include "nifti1_io.h" 6 | 7 | class ConvolutionKernel : public Kernel { 8 | public: 9 | static std::string getName() { 10 | return "ConvolutionKernel"; 11 | } 12 | ConvolutionKernel(std::string name) : Kernel(name) { 13 | } 14 | virtual ~ConvolutionKernel(){} 15 | virtual void calculate(nifti_image *image, float *sigma, int kernelType, int *mask = NULL, bool *timePoints = NULL, bool *axis = NULL) = 0; 16 | }; 17 | 18 | #endif // CONVOLUTIONKERNEL_H 19 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/Kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_H_ 2 | #define KERNEL_H_ 3 | 4 | #include 5 | #include 6 | 7 | class Kernel { 8 | public: 9 | 10 | 11 | Kernel(std::string nameIn){ name = nameIn; } 12 | virtual ~Kernel(){} 13 | 14 | std::string getName() const; 15 | std::string name; 16 | 17 | template 18 | T* castTo() { 19 | return dynamic_cast(this); 20 | } 21 | }; 22 | 23 | 24 | 25 | #endif /*KERNEL_H_*/ 26 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/KernelFactory.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNELFACTORY_H_ 2 | #define KERNELFACTORY_H_ 3 | 4 | #include "AladinContent.h" 5 | 6 | class KernelFactory { 7 | public: 8 | 9 | virtual Kernel* produceKernel(std::string name, AladinContent* con) const = 0; 10 | virtual ~KernelFactory() { 11 | } 12 | }; 13 | 14 | 15 | 16 | #endif /*KERNELFACTORY_H_*/ 17 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/OptimiseKernel.h: -------------------------------------------------------------------------------- 1 | #ifndef OPTIMISEKERNEL_H 2 | #define OPTIMISEKERNEL_H 3 | 4 | #include "Kernel.h" 5 | 6 | class OptimiseKernel : public Kernel{ 7 | public: 8 | static std::string getName() { 9 | return "OptimiseKernel"; 10 | } 11 | OptimiseKernel(std::string name) : Kernel(name) { 12 | } 13 | virtual ~OptimiseKernel(){} 14 | virtual void calculate(bool affine) = 0; 15 | }; 16 | 17 | #endif // OPTIMISEKERNEL_H 18 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/Platform.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM_H_ 2 | #define PLATFORM_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define NR_PLATFORM_CPU 0 9 | #define NR_PLATFORM_CUDA 1 10 | #define NR_PLATFORM_CL 2 11 | 12 | class Kernel; 13 | class KernelFactory; 14 | class AladinContent; 15 | 16 | class Platform { 17 | public: 18 | Platform(int platformCode); 19 | virtual ~Platform(); 20 | 21 | Kernel *createKernel(const std::string& name, AladinContent *con) const; 22 | std::string getName(); 23 | 24 | int getPlatformCode(); 25 | //void setPlatformCode(const int platformCodeIn); 26 | void setGpuIdx(unsigned gpuIdxIn); 27 | unsigned getGpuIdx(); 28 | 29 | private: 30 | KernelFactory* factory; 31 | std::string platformName; 32 | int platformCode; 33 | unsigned gpuIdx; 34 | }; 35 | 36 | 37 | 38 | #endif //PLATFORM_H_ 39 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/ResampleImageKernel.h: -------------------------------------------------------------------------------- 1 | #ifndef RESAMPLEIMAGEKERNEL_H 2 | #define RESAMPLEIMAGEKERNEL_H 3 | 4 | #include "Kernel.h" 5 | #include "nifti1_io.h" 6 | 7 | class ResampleImageKernel : public Kernel { 8 | public: 9 | static std::string getName() { 10 | return "ResampleImageKernel"; 11 | } 12 | ResampleImageKernel( std::string name) : Kernel(name) { 13 | } 14 | 15 | virtual ~ResampleImageKernel(){} 16 | 17 | virtual void calculate(int interp, float paddingValue, bool *dti_timepoint = NULL, mat33 * jacMat = NULL) = 0; 18 | }; 19 | 20 | #endif // RESAMPLEIMAGEKERNEL_H 21 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_ReadWriteImage.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file _reg_ReadWriteImage.h 3 | * @author Marc Modat 4 | * @date 30/05/2012 5 | * @brief IO interface to the NiftyReg project. It uses the nifti, nrrd and png libraries. 6 | * 7 | * Created by Marc Modat on 30/05/2012. 8 | * Copyright (c) 2012, University College London. All rights reserved. 9 | * Centre for Medical Image Computing (CMIC) 10 | * See the LICENSE.txt file in the nifty_reg root folder 11 | * 12 | */ 13 | 14 | #ifndef _REG_READWRITEIMAGE_H 15 | #define _REG_READWRITEIMAGE_H 16 | 17 | #include "nifti1_io.h" 18 | #include 19 | 20 | #include "reg_png.h" 21 | #ifdef _USE_NRRD 22 | #include "reg_nrrd.h" 23 | #endif 24 | /** @defgroup NIFTYREG_FILEFORMAT_TYPE 25 | * @brief Codes to define the image file format 26 | * @{ 27 | */ 28 | #define NR_NII_FORMAT 0 29 | #define NR_PNG_FORMAT 1 30 | #ifdef _USE_NRRD 31 | #define NR_NRRD_FORMAT 2 32 | #endif 33 | /* @} */ 34 | 35 | /* *************************************************************** */ 36 | /** The function checks the file format using the provided filename 37 | * Nifti is returned by default if no format are specified 38 | * @param filename Filename of the input images 39 | * @return Code, NIFTYREG_FILEFORMAT_TYPE, that encode the file format 40 | */ 41 | int reg_io_checkFileFormat(const char *filename); 42 | /* *************************************************************** */ 43 | /** The function expects a filename and returns a nifti_image structure 44 | * The function will use to correct library and will return a NULL image 45 | * if the image can not be read 46 | * @param filename Filename of the input images 47 | * @return Image as a nifti image 48 | */ 49 | nifti_image *reg_io_ReadImageFile(const char *filename); 50 | /* *************************************************************** */ 51 | /** The function expects a filename and returns a nifti_image structure 52 | * The function will use to correct library and will return a NULL image 53 | * if the image can not be read 54 | * Only the header information is read and the actual data is not store 55 | * @param filename Filename of the input images 56 | * @return Image as a nifti image 57 | */ 58 | nifti_image *reg_io_ReadImageHeader(const char *filename); 59 | /* *************************************************************** */ 60 | /** The function expects a filename and nifti_image structure 61 | * The image will be converted to the format specified in the 62 | * filename before being saved 63 | * @param image Nifti image to be saved 64 | * @param filename Filename of the output images 65 | */ 66 | void reg_io_WriteImageFile(nifti_image *image, const char *filename); 67 | /* *************************************************************** */ 68 | /** The function expects a nifti_image structure 69 | * The image will be displayed on the standard output 70 | * @param Nifti image to be displayed 71 | */ 72 | void reg_io_diplayImageData(nifti_image *image); 73 | /* *************************************************************** */ 74 | #endif 75 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_ReadWriteMatrix.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file _reg_ReadWriteMatrix.h 3 | * @author Benoit Presles 4 | * @date 17/09/2015 5 | * @brief library that contains the functions related to matrix 6 | * 7 | * Created by Benoit Presles on 17/09/2015. 8 | * Copyright (c) 2015, University College London. All rights reserved. 9 | * Centre for Medical Image Computing (CMIC) 10 | * See the LICENSE.txt file in the nifty_reg root folder 11 | * 12 | */ 13 | 14 | 15 | #ifndef _REG_READWRITEMATRIX_H 16 | #define _REG_READWRITEMATRIX_H 17 | 18 | #include "nifti1_io.h" 19 | //STD 20 | #include 21 | #include 22 | 23 | /** @brief Read a text file that contains a affine transformation 24 | * and store it into a mat44 structure. This function can also read 25 | * affine parametrisation from Flirt (FSL package) and convert it 26 | * to a standard millimeter parametrisation 27 | * @param mat Structure that will be updated with the affine 28 | * transformation matrix 29 | * @param referenceImage Reference image of the current transformation 30 | * @param floatingImage Floating image of the current transformation. 31 | * Note that referenceImage and floating image have to be defined but 32 | * are only used when dealing with a Flirt affine matrix. 33 | * @param filename Filename for the text file that contains the matrix 34 | * to read 35 | * @param flirtFile If this flag is set to true the matrix is converted 36 | * from a Flirt (FSL) parametrisation to a standard parametrisation 37 | */ 38 | extern "C++" 39 | void reg_tool_ReadAffineFile(mat44 *mat, 40 | nifti_image *referenceImage, 41 | nifti_image *floatingImage, 42 | char *fileName, 43 | bool flirtFile); 44 | 45 | /** 46 | * @brief Read a file that contains a 4-by-4 matrix and store it into 47 | * a mat44 structure 48 | * @param mat structure that store the affine transformation matrix 49 | * @param filename Filename of the text file that contains the matrix to read 50 | **/ 51 | extern "C++" 52 | void reg_tool_ReadAffineFile(mat44 *mat, 53 | char *filename); 54 | 55 | /** 56 | * @brief Read a file that contains a 4-by-4 matrix and store it into 57 | * a mat44 structure 58 | * @param filename Filename of the text file that contains the matrix to read 59 | * @return mat44 structure that store the matrix 60 | **/ 61 | extern "C++" 62 | mat44* reg_tool_ReadMat44File(char *fileName); 63 | 64 | /** @brief This function save a 4-by-4 matrix to the disk as a text file 65 | * @param mat Matrix to be saved on the disk 66 | * @param filename Name of the text file to save on the disk 67 | */ 68 | extern "C++" 69 | void reg_tool_WriteAffineFile(mat44 *mat, 70 | const char *fileName); 71 | 72 | /** 73 | * @brief Read a file that contains a m-by-n matrix and return its size 74 | * @param filename Filename of the text file that contains the matrix to read 75 | * @return pair of values that contains the matrix size 76 | **/ 77 | extern "C++" 78 | std::pair reg_tool_sizeInputMatrixFile(char *filename); 79 | /** 80 | * @brief Read a file that contains a m-by-n matrix and store it into 81 | * an appropriate structure 82 | * @param filename Filename of the text file that contains the matrix to read 83 | * @param nbLine number of line of the imput matrix 84 | * @param nbColumn number of column of the imput matrix 85 | * @return a pointer to a 2D array that points the read matrix 86 | **/ 87 | extern "C++" template 88 | T** reg_tool_ReadMatrixFile(char *filename, 89 | size_t nbLine, 90 | size_t nbColumn); 91 | 92 | /** 93 | * @brief Write a file that contains a m-by-n matrix into a text file 94 | * @param filename Filename of the text file to be written 95 | * @param mat Input matrix to be saved 96 | * @param nbLine number of line of the imput matrix 97 | * @param nbColumn number of column of the imput matrix 98 | **/ 99 | extern "C++" template 100 | void reg_tool_WriteMatrixFile(char *filename, 101 | T **mat, 102 | size_t nbLine, 103 | size_t nbColumn); 104 | 105 | #endif // _REG_READWRITEMATRIX_H 106 | 107 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_aladin_sym.h: -------------------------------------------------------------------------------- 1 | /* 2 | * _reg_aladin_sym.h 3 | * 4 | * 5 | * Created by David Cash on 28/02/2012. 6 | * Copyright (c) 2009, University College London. All rights reserved. 7 | * Centre for Medical Image Computing (CMIC) 8 | * See the LICENSE.txt file in the nifty_reg root folder 9 | * 10 | */ 11 | 12 | #ifndef _REG_ALADIN_SYM_H 13 | #define _REG_ALADIN_SYM_H 14 | 15 | #include "_reg_aladin.h" 16 | 17 | /// @brief Symmetric Block matching registration class 18 | template 19 | class reg_aladin_sym : public reg_aladin 20 | { 21 | private: 22 | AladinContent *backCon; 23 | Kernel *bAffineTransformation3DKernel, *bConvolutionKernel, *bBlockMatchingKernel, *bOptimiseKernel, *bResamplingKernel; 24 | 25 | virtual void initAladinContent(nifti_image *ref, 26 | nifti_image *flo, 27 | int *mask, 28 | mat44 *transMat, 29 | size_t bytes); 30 | virtual void initAladinContent(nifti_image *ref, 31 | nifti_image *flo, 32 | int *mask, 33 | mat44 *transMat, 34 | size_t bytes, 35 | unsigned int blockPercentage, 36 | unsigned int inlierLts, 37 | unsigned int blockStepSize); 38 | virtual void clearAladinContent(); 39 | virtual void createKernels(); 40 | virtual void clearKernels(); 41 | 42 | protected: 43 | nifti_image *InputFloatingMask; 44 | int **FloatingMaskPyramid; 45 | int *BackwardActiveVoxelNumber; 46 | 47 | _reg_blockMatchingParam *BackwardBlockMatchingParams; 48 | 49 | mat44 *BackwardTransformationMatrix; 50 | 51 | virtual void ClearCurrentInputImage(); 52 | virtual void GetBackwardDeformationField(); 53 | virtual void UpdateTransformationMatrix(int); 54 | 55 | virtual void DebugPrintLevelInfoStart(); 56 | virtual void DebugPrintLevelInfoEnd(); 57 | virtual void InitialiseRegistration(); 58 | virtual void GetWarpedImage(int, float); 59 | 60 | public: 61 | reg_aladin_sym(); 62 | virtual ~reg_aladin_sym(); 63 | virtual void SetInputFloatingMask(nifti_image *); 64 | }; 65 | 66 | #include "_reg_aladin_sym.cpp" 67 | 68 | #endif // _REG_ALADIN_SYM_H 69 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_blockMatching.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file _reg_blockMatching.h 3 | * @brief Functions related to the block matching approach 4 | * @author Marc Modat and Pankaj Daga 5 | * @date 24/03/2009 6 | * 7 | * Created by Marc Modat and Pankaj Daga on 24/03/2009. 8 | * Copyright (c) 2009, University College London. All rights reserved. 9 | * Centre for Medical Image Computing (CMIC) 10 | * See the LICENSE.txt file in the nifty_reg root folder 11 | * 12 | */ 13 | 14 | #ifndef __REG_BLOCKMATCHING_H__ 15 | #define __REG_BLOCKMATCHING_H__ 16 | 17 | #include "_reg_maths.h" 18 | #include 19 | 20 | #define TOLERANCE 0.001 21 | #define MAX_ITERATIONS 30 22 | 23 | #define BLOCK_WIDTH 4 24 | #define BLOCK_3D_SIZE 64 25 | #define BLOCK_2D_SIZE 16 26 | #define OVERLAP_SIZE 3 27 | 28 | #define NUM_BLOCKS_TO_COMPARE 343 // We compare in a 7x7x7 neighborhood. 29 | #define NUM_BLOCKS_TO_COMPARE_2D 49 30 | #define NUM_BLOCKS_TO_COMPARE_1D 7 31 | 32 | /// @brief Structure which contains the block matching parameters 33 | struct _reg_blockMatchingParam 34 | { 35 | int totalBlockNumber; 36 | int *totalBlock; 37 | unsigned int blockNumber[3]; 38 | //Number of block we keep for LTS 39 | int percent_to_keep; 40 | 41 | unsigned int dim; 42 | float *referencePosition; 43 | float *warpedPosition; 44 | 45 | //Before: 46 | //Min between Number of block we keep in total (totalBlockNumber*percent_to_keep) and Number of total block - unuseable blocks 47 | //Now: 48 | //Number of total block - unuseable blocks 49 | int activeBlockNumber; 50 | //int *activeBlock; 51 | 52 | //Number of active block which has a displacement vector (not NaN) 53 | int definedActiveBlockNumber; 54 | //int *definedActiveBlock; 55 | 56 | int voxelCaptureRange; 57 | 58 | int stepSize; 59 | 60 | _reg_blockMatchingParam() 61 | : totalBlockNumber(0), 62 | totalBlock(0), 63 | percent_to_keep(0), 64 | dim(0), 65 | referencePosition(0), 66 | warpedPosition(0), 67 | activeBlockNumber(0), 68 | voxelCaptureRange(0), 69 | stepSize(0) 70 | {} 71 | 72 | ~_reg_blockMatchingParam() 73 | { 74 | if (referencePosition) free(referencePosition); 75 | if (warpedPosition) free(warpedPosition); 76 | if (totalBlock) free(totalBlock); 77 | } 78 | }; 79 | /* *************************************************************** */ 80 | /** @brief This function initialise a _reg_blockMatchingParam structure 81 | * according to the the provided arguments 82 | * @param referenceImage Reference image where the blocks are defined 83 | * @param params Block matching parameter structure that will be populated 84 | * @param percentToKeep_block Amount of block to block to keep for the 85 | * optimisation process 86 | * @param percentToKeep_opt Hmmmm ... I actually don't remember. 87 | * Need to check the source :) 88 | * @param stepSize_block To define 89 | * @param mask Array than contains a mask of the voxel form the reference 90 | * image to consider for the registration 91 | * @param runningOnGPU Has to be set to true if the registration has to be performed on the GPU 92 | */ 93 | extern "C++" 94 | void initialise_block_matching_method(nifti_image * referenceImage, 95 | _reg_blockMatchingParam *params, 96 | int percentToKeep_block, 97 | int percentToKeep_opt, 98 | int stepSize_block, 99 | int *mask, 100 | bool runningOnGPU = false); 101 | 102 | /** @brief Interface for the block matching algorithm. 103 | * @param referenceImage Reference image in the current registration task 104 | * @param warpedImage Warped floating image in the currrent registration task 105 | * @param params Block matching parameter structure that contains all 106 | * relevant information 107 | * @param mask Mask array where only voxel defined as active are considered 108 | */ 109 | extern "C++" 110 | void block_matching_method(nifti_image * referenceImage, 111 | nifti_image * warpedImage, 112 | _reg_blockMatchingParam *params, 113 | int *mask); 114 | 115 | /** @brief Find the optimal affine transformation that matches the points 116 | * in the reference image to the point in the warped image 117 | * @param params Block-matching structure that contains the relevant information 118 | * @param transformation_matrix Initial transformation matrix that is updated 119 | * @param affine Returns an affine transformation (12 DoFs) if set to true; 120 | * returns a rigid transformation (6 DoFs) otherwise 121 | */ 122 | void optimize(_reg_blockMatchingParam *params, 123 | mat44 * transformation_matrix, 124 | bool affine = true); 125 | #endif 126 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_dti.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file _reg_ssd.h 3 | * @brief File that contains sum squared difference related function 4 | * @author Marc Modat 5 | * @date 19/05/2009 6 | * 7 | * Created by Marc Modat on 19/05/2009. 8 | * Copyright (c) 2009, University College London. All rights reserved. 9 | * Centre for Medical Image Computing (CMIC) 10 | * See the LICENSE.txt file in the nifty_reg root folder 11 | * 12 | */ 13 | 14 | #ifndef _REG_DTI_H 15 | #define _REG_DTI_H 16 | 17 | //#include "_reg_measure.h" 18 | #include "_reg_ssd.h" // HERE 19 | 20 | /* *************************************************************** */ 21 | /* *************************************************************** */ 22 | /// @brief DTI related measure of similarity class 23 | class reg_dti : public reg_measure 24 | { 25 | public: 26 | /// @brief reg_dti class constructor 27 | reg_dti(); 28 | // /// @brief Initialise the reg_dti object 29 | void InitialiseMeasure(nifti_image *refImgPtr, 30 | nifti_image *floImgPtr, 31 | int *maskRefPtr, 32 | nifti_image *warFloImgPtr, 33 | nifti_image *warFloGraPtr, 34 | nifti_image *forVoxBasedGraPtr, 35 | nifti_image *forwardLocalWeightPtr = NULL, 36 | int *maskFloPtr = NULL, 37 | nifti_image *warRefImgPtr = NULL, 38 | nifti_image *warRefGraPtr = NULL, 39 | nifti_image *bckVoxBasedGraPtr = NULL); 40 | // /// @brief Returns the value 41 | virtual double GetSimilarityMeasureValue(); 42 | // /// @brief Compute the voxel based gradient for DTI images 43 | virtual void GetVoxelBasedSimilarityMeasureGradient(int current_timepoint); 44 | /// @brief reg_dti class destructor 45 | ~reg_dti() {} 46 | protected: 47 | // Store the indicies of the DT components in the order XX,XY,YY,XZ,YZ,ZZ 48 | unsigned int dtIndicies[6]; 49 | float currentValue; 50 | }; 51 | /* *************************************************************** */ 52 | 53 | /** @brief Copmutes and returns the SSD between two input image 54 | * @param referenceImage First input image to use to compute the metric 55 | * @param warpedImage Second input image to use to compute the metric 56 | * @param mask Array that contains a mask to specify which voxel 57 | * should be considered. If set to NULL, all voxels are considered 58 | * @return Returns an L2 measure of the distance between the anisotropic components of the diffusion tensors 59 | */ 60 | extern "C++" template 61 | double reg_getDTIMeasureValue(nifti_image *referenceImage, 62 | nifti_image *warpedImage, 63 | int *mask, 64 | unsigned int * dtIndicies 65 | ); 66 | 67 | /** @brief Compute a voxel based gradient of the sum squared difference. 68 | * @param referenceImage First input image to use to compute the metric 69 | * @param warpedImage Second input image to use to compute the metric 70 | * @param warpedImageGradient Spatial gradient of the input warped image 71 | * @param dtiGradientImage Output image that will be updated with the 72 | * value of the dti measure gradient 73 | * @param maxSD Input scalar that contain the difference value between 74 | * the highest and the lowest intensity. 75 | * @param mask Array that contains a mask to specify which voxel 76 | * should be considered. If set to NULL, all voxels are considered 77 | */ 78 | extern "C++" template 79 | void reg_getVoxelBasedDTIMeasureGradient(nifti_image *referenceImage, 80 | nifti_image *warpedImage, 81 | nifti_image *warImgGradient, 82 | nifti_image *dtiMeasureGradientImage, 83 | int *mask, 84 | unsigned int * dtIndicies); 85 | #endif 86 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_f3d.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file _reg_f3d.h 3 | * @author Marc Modat 4 | * @date 19/11/2010 5 | * 6 | * Copyright (c) 2010, University College London. All rights reserved. 7 | * Centre for Medical Image Computing (CMIC) 8 | * See the LICENSE.txt file in the nifty_reg root folder 9 | * 10 | */ 11 | 12 | #ifndef _REG_F3D_H 13 | #define _REG_F3D_H 14 | 15 | #include "_reg_base.h" 16 | 17 | /// @brief Fast Free Form Deformation registration class 18 | template 19 | class reg_f3d : public reg_base 20 | { 21 | protected: 22 | nifti_image *inputControlPointGrid; // pointer to external 23 | nifti_image *controlPointGrid; 24 | T bendingEnergyWeight; 25 | T linearEnergyWeight; 26 | T jacobianLogWeight; 27 | bool jacobianLogApproximation; 28 | T spacing[3]; 29 | 30 | nifti_image *transformationGradient; 31 | bool gridRefinement; 32 | 33 | double currentWJac; 34 | double currentWBE; 35 | double currentWLE; 36 | double bestWJac; 37 | double bestWBE; 38 | double bestWLE; 39 | 40 | virtual void AllocateTransformationGradient(); 41 | virtual void ClearTransformationGradient(); 42 | virtual T InitialiseCurrentLevel(); 43 | 44 | virtual double ComputeBendingEnergyPenaltyTerm(); 45 | virtual double ComputeLinearEnergyPenaltyTerm(); 46 | virtual double ComputeJacobianBasedPenaltyTerm(int); 47 | virtual double ComputeLandmarkDistancePenaltyTerm(); 48 | 49 | virtual void GetBendingEnergyGradient(); 50 | virtual void GetLinearEnergyGradient(); 51 | virtual void GetJacobianBasedGradient(); 52 | virtual void GetLandmarkDistanceGradient(); 53 | virtual void SetGradientImageToZero(); 54 | virtual T NormaliseGradient(); 55 | virtual void SmoothGradient(); 56 | virtual void GetObjectiveFunctionGradient(); 57 | virtual void GetApproximatedGradient(); 58 | void GetSimilarityMeasureGradient(); 59 | 60 | virtual void GetDeformationField(); 61 | virtual void DisplayCurrentLevelParameters(); 62 | 63 | virtual double GetObjectiveFunctionValue(); 64 | virtual void UpdateBestObjFunctionValue(); 65 | virtual void UpdateParameters(float); 66 | virtual void SetOptimiser(); 67 | 68 | virtual void PrintInitialObjFunctionValue(); 69 | virtual void PrintCurrentObjFunctionValue(T); 70 | 71 | virtual void CorrectTransformation(); 72 | 73 | void (*funcProgressCallback)(float pcntProgress, void *params); 74 | void *paramsProgressCallback; 75 | 76 | public: 77 | reg_f3d(int refTimePoint,int floTimePoint); 78 | virtual ~reg_f3d(); 79 | 80 | void SetControlPointGridImage(nifti_image *); 81 | void SetBendingEnergyWeight(T); 82 | void SetLinearEnergyWeight(T); 83 | void SetJacobianLogWeight(T); 84 | void ApproximateJacobianLog(); 85 | void DoNotApproximateJacobianLog(); 86 | void SetSpacing(unsigned int ,T); 87 | 88 | void NoGridRefinement() 89 | { 90 | this->gridRefinement=false; 91 | } 92 | // F3D2 specific options 93 | virtual void SetCompositionStepNumber(int) 94 | { 95 | return; 96 | } 97 | virtual void ApproximateComposition() 98 | { 99 | return; 100 | } 101 | virtual void UseSimilaritySymmetry() 102 | { 103 | return; 104 | } 105 | virtual void UseBCHUpdate(int) 106 | { 107 | return; 108 | } 109 | virtual void UseGradientCumulativeExp() 110 | { 111 | return; 112 | } 113 | virtual void DoNotUseGradientCumulativeExp() 114 | { 115 | return; 116 | } 117 | 118 | // F3D_SYM specific options 119 | virtual void SetFloatingMask(nifti_image *) 120 | { 121 | return; 122 | } 123 | virtual void SetInverseConsistencyWeight(T) 124 | { 125 | return; 126 | } 127 | virtual nifti_image *GetBackwardControlPointPositionImage() 128 | { 129 | return NULL; 130 | } 131 | 132 | // F3D_gpu specific option 133 | virtual int CheckMemoryMB() 134 | { 135 | return EXIT_SUCCESS; 136 | } 137 | 138 | virtual void CheckParameters(); 139 | virtual void Initialise(); 140 | virtual nifti_image *GetControlPointPositionImage(); 141 | virtual nifti_image **GetWarpedImage(); 142 | 143 | // Function used for testing 144 | virtual void reg_test_setControlPointGrid(nifti_image *cpp) 145 | { 146 | this->controlPointGrid=cpp; 147 | } 148 | }; 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_f3d2.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file _reg_f3d2.h 3 | * @author Marc Modat 4 | * @date 19/11/2011 5 | * 6 | * Copyright (c) 2011, University College London. All rights reserved. 7 | * Centre for Medical Image Computing (CMIC) 8 | * See the LICENSE.txt file in the nifty_reg root folder 9 | * 10 | */ 11 | 12 | #include "_reg_f3d_sym.h" 13 | 14 | #ifndef _REG_F3D2_H 15 | #define _REG_F3D2_H 16 | 17 | 18 | /// @brief Fast Free Form Diffeomorphic Deformation registration class 19 | template 20 | class reg_f3d2 : public reg_f3d_sym 21 | { 22 | protected: 23 | bool BCHUpdate; 24 | bool useGradientCumulativeExp; 25 | int BCHUpdateValue; 26 | 27 | virtual void GetDeformationField(); 28 | virtual void GetInverseConsistencyErrorField(bool forceAll); 29 | virtual void GetInverseConsistencyGradient(); 30 | virtual void GetVoxelBasedGradient(); 31 | virtual void UpdateParameters(float); 32 | virtual void ExponentiateGradient(); 33 | virtual void UseBCHUpdate(int); 34 | virtual void UseGradientCumulativeExp(); 35 | virtual void DoNotUseGradientCumulativeExp(); 36 | 37 | public: 38 | reg_f3d2(int refTimePoint,int floTimePoint); 39 | ~reg_f3d2(); 40 | virtual void Initialise(); 41 | virtual nifti_image **GetWarpedImage(); 42 | }; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_f3d_sym.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @file _reg_f3d_sym.h 3 | * @author Marc Modat 4 | * @date 10/11/2011 5 | * 6 | * Copyright (c) 2011, University College London. All rights reserved. 7 | * Centre for Medical Image Computing (CMIC) 8 | * See the LICENSE.txt file in the nifty_reg root folder 9 | * 10 | */ 11 | 12 | #ifndef _REG_F3D_SYM_H 13 | #define _REG_F3D_SYM_H 14 | 15 | #include "_reg_f3d.h" 16 | 17 | /// @brief Symmetric Fast Free Form Deformation registration class 18 | template 19 | class reg_f3d_sym : public reg_f3d 20 | { 21 | protected: 22 | // Optimiser related function 23 | virtual void SetOptimiser(); 24 | 25 | nifti_image *floatingMaskImage; 26 | int **floatingMaskPyramid; 27 | int *currentFloatingMask; 28 | int *backwardActiveVoxelNumber; 29 | 30 | nifti_image *backwardControlPointGrid; 31 | nifti_image *backwardDeformationFieldImage; 32 | nifti_image *backwardWarped; 33 | nifti_image *backwardWarpedGradientImage; 34 | nifti_image *backwardVoxelBasedMeasureGradientImage; 35 | nifti_image *backwardTransformationGradient; 36 | 37 | double *backwardProbaJointHistogram; 38 | double *backwardLogJointHistogram; 39 | double backwardEntropies[4]; 40 | 41 | mat33 *backwardJacobianMatrix; 42 | 43 | T inverseConsistencyWeight; 44 | double currentIC; 45 | double bestIC; 46 | 47 | virtual void AllocateWarped(); 48 | virtual void ClearWarped(); 49 | virtual void AllocateDeformationField(); 50 | virtual void ClearDeformationField(); 51 | virtual void AllocateWarpedGradient(); 52 | virtual void ClearWarpedGradient(); 53 | virtual void AllocateVoxelBasedMeasureGradient(); 54 | virtual void ClearVoxelBasedMeasureGradient(); 55 | virtual void AllocateTransformationGradient(); 56 | virtual void ClearTransformationGradient(); 57 | virtual T InitialiseCurrentLevel(); 58 | virtual void ClearCurrentInputImage(); 59 | 60 | virtual double ComputeBendingEnergyPenaltyTerm(); 61 | virtual double ComputeLinearEnergyPenaltyTerm(); 62 | virtual double ComputeJacobianBasedPenaltyTerm(int); 63 | virtual double ComputeLandmarkDistancePenaltyTerm(); 64 | virtual void GetDeformationField(); 65 | virtual void WarpFloatingImage(int); 66 | virtual void GetVoxelBasedGradient(); 67 | virtual void GetSimilarityMeasureGradient(); 68 | virtual void GetObjectiveFunctionGradient(); 69 | virtual void GetBendingEnergyGradient(); 70 | virtual void GetLinearEnergyGradient(); 71 | virtual void GetJacobianBasedGradient(); 72 | virtual void GetLandmarkDistanceGradient(); 73 | virtual void SetGradientImageToZero(); 74 | virtual T NormaliseGradient(); 75 | virtual void SmoothGradient(); 76 | virtual void GetApproximatedGradient(); 77 | virtual void DisplayCurrentLevelParameters(); 78 | virtual void PrintInitialObjFunctionValue(); 79 | virtual void PrintCurrentObjFunctionValue(T); 80 | virtual void UpdateBestObjFunctionValue(); 81 | virtual double GetObjectiveFunctionValue(); 82 | 83 | virtual void GetInverseConsistencyErrorField(bool forceAll); 84 | virtual double GetInverseConsistencyPenaltyTerm(); 85 | virtual void GetInverseConsistencyGradient(); 86 | 87 | virtual void UpdateParameters(float); 88 | virtual void InitialiseSimilarity(); 89 | 90 | public: 91 | virtual void SetFloatingMask(nifti_image *); 92 | virtual void SetInverseConsistencyWeight(T); 93 | 94 | reg_f3d_sym(int refTimePoint,int floTimePoint); 95 | ~reg_f3d_sym(); 96 | void CheckParameters(); 97 | void Initialise(); 98 | nifti_image *GetBackwardControlPointPositionImage(); 99 | nifti_image **GetWarpedImage(); 100 | bool GetSymmetricStatus() 101 | { 102 | return true; 103 | } 104 | }; 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_femTrans.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file _reg_femTransformation_gpu.h 3 | * @author Marc Modat 4 | * @date 02/11/2011 5 | * @brief Functions built to interface between NiftyReg and NiftySim 6 | * It basically allows to populate a dense deformation 7 | * 8 | * Created by Marc Modat on 02/11/2011. 9 | * Copyright (c) 2011, University College London. All rights reserved. 10 | * Centre for Medical Image Computing (CMIC) 11 | * See the LICENSE.txt file in the nifty_reg root folder 12 | * 13 | */ 14 | 15 | #ifndef _REG_FEMTRANS_H 16 | #define _REG_FEMTRANS_H 17 | 18 | #include "nifti1_io.h" 19 | #include 20 | #include "_reg_maths.h" 21 | 22 | /** @brief Initialise multiples arrays to populate a dense deformation 23 | * field from a FEM parametrisation 24 | * @param elementNodes Arrays that contains the nodes use to define each element. 25 | * @param nodePositions Arrays that contains the position in mm of 26 | * every node 27 | * @param deformationFieldImage Deformation field image, at this stage it 28 | * is only used to define the space of the transformation 29 | * @param closestNodes This array will contain for every voxel the closest 30 | * nodes to be used for interpolation 31 | * @param femInterpolationWeight This arrayt will contain for every voxel 32 | * the weight associated with the closest node. 33 | */ 34 | void reg_fem_InitialiseTransformation(int *elementNodes, 35 | unsigned int elementNumber, 36 | float *nodePositions, 37 | nifti_image *deformationFieldImage, 38 | unsigned int *closestNodes, 39 | float *femInterpolationWeight 40 | ); 41 | 42 | /** @brief A dense deformation field is filled using interpolation 43 | * from a coarse mesh 44 | * @param nodePositions Array that contains the position of every node 45 | * @param deformationFieldImage Deformation field image that will be 46 | * filled 47 | * @param closestNodes Array that contains for every voxel the closest 48 | * nodes from the mesh 49 | * @param femInterpolationWeight Array that contains for every voxel, 50 | * the weight associated with the closest nodes. 51 | */ 52 | void reg_fem_getDeformationField(float *nodePositions, 53 | nifti_image *deformationFieldImage, 54 | unsigned int *closestNodes, 55 | float *femInterpolationWeight 56 | ); 57 | 58 | /** @brief Convert a dense gradient image into a mesh based gradient image 59 | * @param voxelBasedGradient Image that contains the gradient image 60 | * @param closestNodes Array that contains the closest nodes associated 61 | * with every voxel 62 | * @param femInterpolationWeight Array that contains for every voxel the 63 | * weight associated with the closest nodes 64 | * @param nodeNumber Scalar that contains the total number of node in the mesh 65 | * @param femBasedGradient Array that contains the gradient values at 66 | * every node. 67 | */ 68 | void reg_fem_voxelToNodeGradient(nifti_image *voxelBasedGradient, 69 | unsigned int *closestNodes, 70 | float *femInterpolationWeight, 71 | unsigned int nodeNumber, 72 | float *femBasedGradient); 73 | #endif 74 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_globalTrans.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file _reg_globalTrans.h 3 | * @author Marc Modat 4 | * @date 25/03/2009 5 | * @brief library that contains the function related to global transformation 6 | * 7 | * Created by Marc Modat on 25/03/2009. 8 | * Copyright (c) 2009, University College London. All rights reserved. 9 | * Centre for Medical Image Computing (CMIC) 10 | * See the LICENSE.txt file in the nifty_reg root folder 11 | * 12 | */ 13 | 14 | #ifndef _REG_AFFINETRANS_H 15 | #define _REG_AFFINETRANS_H 16 | 17 | #include "nifti1_io.h" 18 | #include "_reg_tools.h" 19 | /* *************************************************************** */ 20 | /// @brief Structure that is used to store the distance between two corresponding voxel 21 | struct _reg_sorted_point3D 22 | { 23 | float reference[3]; 24 | float warped[3]; 25 | 26 | double distance; 27 | 28 | _reg_sorted_point3D(float * t, float * r, double d) 29 | :distance(d) 30 | { 31 | reference[0] = t[0]; 32 | reference[1] = t[1]; 33 | reference[2] = t[2]; 34 | 35 | warped[0] = r[0]; 36 | warped[1] = r[1]; 37 | warped[2] = r[2]; 38 | } 39 | 40 | bool operator <(const _reg_sorted_point3D &sp) const 41 | { 42 | return (sp.distance < distance); 43 | } 44 | }; 45 | typedef struct _reg_sorted_point3D _reg_sorted_point3D; 46 | /* *************************************************************** */ 47 | /// @brief Structure that is used to store the distance between two corresponding pixel 48 | struct _reg_sorted_point2D 49 | { 50 | float reference[2]; 51 | float warped[2]; 52 | 53 | double distance; 54 | 55 | _reg_sorted_point2D(float * t, float * r, double d) 56 | :distance(d) 57 | { 58 | reference[0] = t[0]; 59 | reference[1] = t[1]; 60 | 61 | warped[0] = r[0]; 62 | warped[1] = r[1]; 63 | } 64 | bool operator <(const _reg_sorted_point2D &sp) const 65 | { 66 | return (sp.distance < distance); 67 | } 68 | }; 69 | typedef struct _reg_sorted_point2D _reg_sorted_point2D; 70 | /* *************************************************************** */ 71 | /** @brief This Function compute a deformation field based 72 | * on affine transformation matrix 73 | * @param affine This matrix contains the affine transformation 74 | * used to parametrise the transformation 75 | * @param deformationField Image that contains the deformation field 76 | * that is being updated 77 | */ 78 | extern "C++" 79 | void reg_affine_getDeformationField(mat44 *affine, 80 | nifti_image *deformationField, 81 | bool compose=false, 82 | int *mask = NULL); 83 | /* *************************************************************** */ 84 | void optimize_2D(float* referencePosition, float* warpedPosition, 85 | unsigned int definedActiveBlock, int percent_to_keep, int max_iter, double tol, 86 | mat44* final, bool affine); 87 | /* *************************************************************** */ 88 | void estimate_affine_transformation2D(std::vector<_reg_sorted_point2D> &points, mat44* transformation); 89 | /* *************************************************************** */ 90 | void estimate_rigid_transformation2D(std::vector<_reg_sorted_point2D> &points, mat44* transformation); 91 | /* *************************************************************** */ 92 | void optimize_3D(float* referencePosition, float* warpedPosition, 93 | unsigned int definedActiveBlock, int percent_to_keep, int max_iter, double tol, 94 | mat44* final, bool affine); 95 | /* *************************************************************** */ 96 | void estimate_affine_transformation3D(std::vector<_reg_sorted_point3D> &points, mat44* transformation); 97 | /* *************************************************************** */ 98 | void estimate_rigid_transformation3D(std::vector<_reg_sorted_point3D> &points, mat44* transformation); 99 | /* *************************************************************** */ 100 | #endif 101 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_kld.h: -------------------------------------------------------------------------------- 1 | /* 2 | * _reg_kld.h 3 | * 4 | * 5 | * Created by Marc Modat on 14/05/2012. 6 | * Copyright (c) 2012, University College London. All rights reserved. 7 | * Centre for Medical Image Computing (CMIC) 8 | * See the LICENSE.txt file in the nifty_reg root folder 9 | * 10 | */ 11 | 12 | #ifndef _REG_KLDIV_H 13 | #define _REG_KLDIV_H 14 | 15 | #include "_reg_measure.h" 16 | 17 | /* *************************************************************** */ 18 | class reg_kld : public reg_measure 19 | { 20 | public: 21 | /// @brief reg_kld class constructor 22 | reg_kld(); 23 | /// @brief Initialise the reg_kld object 24 | void InitialiseMeasure(nifti_image *refImgPtr, 25 | nifti_image *floImgPtr, 26 | int *maskRefPtr, 27 | nifti_image *warFloImgPtr, 28 | nifti_image *warFloGraPtr, 29 | nifti_image *forVoxBasedGraPtr, 30 | nifti_image *forwardLocalWeightPtr = NULL, 31 | int *maskFloPtr = NULL, 32 | nifti_image *warRefImgPtr = NULL, 33 | nifti_image *warRefGraPtr = NULL, 34 | nifti_image *bckVoxBasedGraPtr = NULL); 35 | /// @brief Returns the kld value 36 | virtual double GetSimilarityMeasureValue(); 37 | /// @brief Compute the voxel based kld gradient 38 | virtual void GetVoxelBasedSimilarityMeasureGradient(int current_timepoint); 39 | /// @brief reg_kld class destructor 40 | ~reg_kld() {} 41 | }; 42 | /* *************************************************************** */ 43 | 44 | /** @brief Computes and returns the KLD between two input image 45 | * @param reference First input image to use to compute the metric 46 | * @param warped Second input image to use to compute the metric 47 | * @param activeTimePoint Specified which time point volumes have to be considered 48 | * @param jacobianDeterminantImage Image that contains the Jacobian 49 | * determinant of a transformation at every voxel position. This 50 | * image is used to modulate the KLD. The argument is ignored if the 51 | * pointer is set to NULL 52 | * @param mask Array that contains a mask to specify which voxel 53 | * should be considered. If set to NULL, all voxels are considered 54 | * @return Returns the computed sum squared difference 55 | */ 56 | extern "C++" template 57 | double reg_getKLDivergence(nifti_image *reference, 58 | nifti_image *warped, 59 | double *timePointWeight, 60 | nifti_image *jacobianDeterminantImage, 61 | int *mask); 62 | /* *************************************************************** */ 63 | 64 | /** @brief Compute a voxel based gradient of the sum squared difference. 65 | * @param reference First input image to use to compute the metric 66 | * @param warped Second input image to use to compute the metric 67 | * @param activeTimePoint Specified which time point volumes have to be considered 68 | * @param warpedGradient Spatial gradient of the input result image 69 | * @param KLdivGradient Output image htat will be updated with the 70 | * value of the KLD gradient 71 | * @param jacobianDeterminantImage Image that contains the Jacobian 72 | * determinant of a transformation at every voxel position. This 73 | * image is used to modulate the KLD. The argument is ignored if the 74 | * pointer is set to NULL 75 | * @param mask Array that contains a mask to specify which voxel 76 | * should be considered. If set to NULL, all voxels are considered 77 | */ 78 | extern "C++" template 79 | void reg_getKLDivergenceVoxelBasedGradient(nifti_image *reference, 80 | nifti_image *warped, 81 | nifti_image *warpedGradient, 82 | nifti_image *KLdivGradient, 83 | nifti_image *jacobianDeterminantImage, 84 | int *mask, 85 | int current_timepoint, 86 | double timepoint_weight); 87 | /* *************************************************************** */ 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_lncc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file _reg_lncc.h 3 | * @author Aileen Corder 4 | * @author Marc Modat 5 | * @date 10/11/2012. 6 | * @brief Header file for the LNCC related class and functions 7 | * Copyright (c) 2012, University College London. All rights reserved. 8 | * Centre for Medical Image Computing (CMIC) 9 | * See the LICENSE.txt file in the nifty_reg root folder 10 | */ 11 | 12 | #ifndef _REG_LNCC_H 13 | #define _REG_LNCC_H 14 | 15 | #include "_reg_measure.h" 16 | 17 | /* *************************************************************** */ 18 | /* *************************************************************** */ 19 | class reg_lncc : public reg_measure 20 | { 21 | public: 22 | /// @brief reg_lncc class constructor 23 | reg_lncc(); 24 | /// @brief reg_lncc class destructor 25 | ~reg_lncc(); 26 | /// @brief Initialise the reg_lncc object 27 | void InitialiseMeasure(nifti_image *refImgPtr, 28 | nifti_image *floImgPtr, 29 | int *maskRefPtr, 30 | nifti_image *warFloImgPtr, 31 | nifti_image *warFloGraPtr, 32 | nifti_image *forVoxBasedGraPtr, 33 | nifti_image *forwardLocalWeightPtr = NULL, 34 | int *maskFloPtr = NULL, 35 | nifti_image *warRefImgPtr = NULL, 36 | nifti_image *warRefGraPtr = NULL, 37 | nifti_image *bckVoxBasedGraPtr = NULL); 38 | /// @brief Returns the lncc value 39 | double GetSimilarityMeasureValue(); 40 | /// @brief Compute the voxel based lncc gradient 41 | void GetVoxelBasedSimilarityMeasureGradient(int current_timepoint); 42 | /// @brief Stuff 43 | void SetKernelStandardDeviation(int t, float stddev) 44 | { 45 | this->kernelStandardDeviation[t]=stddev; 46 | } 47 | /// @brief Stuff 48 | void SetKernelType(int t) 49 | { 50 | this->kernelType=t; 51 | } 52 | protected: 53 | float kernelStandardDeviation[255]; 54 | nifti_image *forwardCorrelationImage; 55 | nifti_image *referenceMeanImage; 56 | nifti_image *referenceSdevImage; 57 | nifti_image *warpedFloatingMeanImage; 58 | nifti_image *warpedFloatingSdevImage; 59 | int *forwardMask; 60 | 61 | nifti_image *backwardCorrelationImage; 62 | nifti_image *floatingMeanImage; 63 | nifti_image *floatingSdevImage; 64 | nifti_image *warpedReferenceMeanImage; 65 | nifti_image *warpedReferenceSdevImage; 66 | int *backwardMask; 67 | 68 | int kernelType; 69 | 70 | template 71 | void UpdateLocalStatImages(nifti_image *refImage, 72 | nifti_image *warImage, 73 | nifti_image *meanRefImage, 74 | nifti_image *meanWarImage, 75 | nifti_image *stdDevRefImage, 76 | nifti_image *stdDevWarImage, 77 | int *refMask, 78 | int *mask, 79 | int current_timepoint); 80 | }; 81 | /* *************************************************************** */ 82 | /* *************************************************************** */ 83 | /** @brief Copmutes and returns the LNCC between two input image 84 | * @param referenceImage First input image to use to compute the metric 85 | * @param warpedImage Second input image to use to compute the metric 86 | * @param gaussianStandardDeviation Standard deviation of the Gaussian kernel 87 | * to use. 88 | * @param mask Array that contains a mask to specify which voxel 89 | * should be considered. If set to NULL, all voxels are considered 90 | * @return Returns the computed LNCC 91 | */ 92 | extern "C++" template 93 | double reg_getLNCCValue(nifti_image *referenceImage, 94 | nifti_image *referenceMeanImage, 95 | nifti_image *referenceStdDevImage, 96 | nifti_image *warpedImage, 97 | nifti_image *warpedMeanImage, 98 | nifti_image *warpedStdDevImage, 99 | int *combinedMask, 100 | float *kernelStdDev, 101 | nifti_image *correlationImage, 102 | int kernelType); 103 | 104 | /* *************************************************************** */ 105 | /** @brief Compute a voxel based gradient of the LNCC. 106 | * @param referenceImage First input image to use to compute the metric 107 | * @param warpedImage Second input image to use to compute the metric 108 | * @param warpedImageGradient Spatial gradient of the input warped image 109 | * @param lnccGradientImage Output image that will be updated with the 110 | * value of the LNCC gradient 111 | * @param gaussianStandardDeviation Standard deviation of the Gaussian kernel 112 | * to use. 113 | * @param mask Array that contains a mask to specify which voxel 114 | * should be considered. If set to NULL, all voxels are considered 115 | */ 116 | extern "C++" template 117 | void reg_getVoxelBasedLNCCGradient(nifti_image *referenceImage, 118 | nifti_image *referenceMeanImage, 119 | nifti_image *referenceStdDevImage, 120 | nifti_image *warpedImage, 121 | nifti_image *warpedMeanImage, 122 | nifti_image *warpedStdDevImage, 123 | int *combinedMask, 124 | float *kernelStdDev, 125 | nifti_image *correlationImage, 126 | nifti_image *warImgGradient, 127 | nifti_image *lnccGradientImage, 128 | int kernelType, 129 | int current_timepoint, 130 | double timepoint_weight); 131 | #endif 132 | 133 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_macros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Reg Macros - Helper macros based on vtkSetGet.h that makes 3 | * it easy to creat functions for simple Get and Set functions 4 | * of class memebers 5 | */ 6 | 7 | #ifndef _REG_MACROS_H 8 | #define _REG_MACROS_H 9 | 10 | // 11 | // Set built-in type. Creates member Set"name"() (e.g., SetVisibility()); 12 | // 13 | #define SetMacro(name,type) \ 14 | virtual void Set##name (type _arg) \ 15 | { \ 16 | if (this->name != _arg) \ 17 | { \ 18 | this->name = _arg; \ 19 | } \ 20 | } 21 | 22 | // 23 | // Get built-in type. Creates member Get"name"() (e.g., GetVisibility()); 24 | // 25 | #define GetMacro(name,type) \ 26 | virtual type Get##name () { \ 27 | return this->name; \ 28 | } 29 | 30 | // 31 | // Create members "name"On() and "name"Off() (e.g., DebugOn() DebugOff()). 32 | // Set method must be defined to use this macro. 33 | // 34 | #define BooleanMacro(name,type) \ 35 | virtual void name##On () { this->Set##name(static_cast(1));} \ 36 | virtual void name##Off () { this->Set##name(static_cast(0));} 37 | 38 | #define SetVector3Macro(name,type) \ 39 | virtual void Set##name (type _arg1, type _arg2, type _arg3) \ 40 | { \ 41 | if ((this->name[0] != _arg1)||(this->name[1] != _arg2)||(this->name[2] != _arg3)) \ 42 | { \ 43 | this->name[0] = _arg1; \ 44 | this->name[1] = _arg2; \ 45 | this->name[2] = _arg3; \ 46 | } \ 47 | }; \ 48 | virtual void Set##name (type _arg[3]) \ 49 | { \ 50 | this->Set##name (_arg[0], _arg[1], _arg[2]);\ 51 | } 52 | 53 | #define GetVector3Macro(name,type) \ 54 | virtual type *Get##name () \ 55 | { \ 56 | return this->name; \ 57 | } \ 58 | virtual void Get##name (type &_arg1, type &_arg2, type &_arg3) \ 59 | { \ 60 | _arg1 = this->name[0]; \ 61 | _arg2 = this->name[1]; \ 62 | _arg3 = this->name[2]; \ 63 | }; \ 64 | virtual void Get##name (type _arg[3]) \ 65 | { \ 66 | this->Get##name (_arg[0], _arg[1], _arg[2]);\ 67 | } 68 | 69 | #define SetClampMacro(name,type,min,max) \ 70 | virtual void Set##name (type _arg) \ 71 | { \ 72 | if (this->name != (_argmax?max:_arg))) \ 73 | { \ 74 | this->name = (_argmax?max:_arg)); \ 75 | } \ 76 | } \ 77 | virtual type Get##name##MinValue () \ 78 | { \ 79 | return min; \ 80 | } \ 81 | virtual type Get##name##MaxValue () \ 82 | { \ 83 | return max; \ 84 | } 85 | 86 | #define SetStringMacro(name) \ 87 | virtual void Set##name (const char* _arg) \ 88 | { \ 89 | if ( this->name == NULL && _arg == NULL) { return;} \ 90 | if ( this->name && _arg && (!strcmp(this->name,_arg))) { return;} \ 91 | if (this->name) { delete [] this->name; } \ 92 | if (_arg) \ 93 | { \ 94 | size_t n = strlen(_arg) + 1; \ 95 | char *cp1 = new char[n]; \ 96 | const char *cp2 = (_arg); \ 97 | this->name = cp1; \ 98 | do { *cp1++ = *cp2++; } while ( --n ); \ 99 | } \ 100 | else \ 101 | { \ 102 | this->name = NULL; \ 103 | } \ 104 | } 105 | 106 | // 107 | // Get character string. Creates member Get"name"() 108 | // (e.g., char *GetFilename()); 109 | // 110 | #define GetStringMacro(name) \ 111 | virtual char* Get##name () { \ 112 | return this->name; \ 113 | } 114 | 115 | 116 | #endif // _REG_MACROS_H 117 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_maths_eigen.h: -------------------------------------------------------------------------------- 1 | //_reg_maths_eigen.h 2 | #ifndef _REG_MATHS_EIGEN_H 3 | #define _REG_MATHS_EIGEN_H 4 | 5 | #include "nifti1_io.h" 6 | 7 | /* *************************************************************** */ 8 | /* Functions calling the Eigen library */ 9 | /* See http://eigen.tuxfamily.org/index.php?title=Main_Page */ 10 | /* *************************************************************** */ 11 | 12 | /* *************************************************************** */ 13 | extern "C++" template 14 | void svd(T **in, size_t m, size_t n, T * w, T **v); 15 | /* *************************************************************** */ 16 | extern "C++" template 17 | void svd(T **in, size_t m, size_t n, T ***U, T ***S, T ***V); 18 | /* *************************************************************** */ 19 | extern "C++" template 20 | T reg_matrix2DDet(T** mat, size_t m, size_t n); 21 | /* *************************************************************** */ 22 | /** @brief Compute the inverse of a 4-by-4 matrix 23 | */ 24 | mat44 reg_mat44_inv(mat44 const* mat); 25 | /* *************************************************************** */ 26 | /** @brief Compute the square root of a 4-by-4 matrix 27 | */ 28 | mat44 reg_mat44_sqrt(mat44 const* mat); 29 | /* *************************************************************** */ 30 | /** @brief Compute the log of a 3-by-3 matrix 31 | */ 32 | void reg_mat33_expm(mat33 *in_tensor); 33 | /* *************************************************************** */ 34 | /** @brief Compute the exp of a 4-by-4 matrix 35 | */ 36 | mat44 reg_mat44_expm(const mat44 *mat); 37 | /* *************************************************************** */ 38 | /** @brief Compute the log of a 3-by-3 matrix 39 | */ 40 | void reg_mat33_logm(mat33 *in_tensor); 41 | /* *************************************************************** */ 42 | /** @brief Compute the log of a 4-by-4 matrix 43 | */ 44 | mat44 reg_mat44_logm(const mat44 *mat); 45 | /* *************************************************************** */ 46 | /** @brief Compute the average of two matrices using a log-euclidean 47 | * framework 48 | */ 49 | mat44 reg_mat44_avg2(mat44 const* A, mat44 const* b); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_measure.h: -------------------------------------------------------------------------------- 1 | /** @file _reg_measure.h 2 | * @author Marc Modat 3 | * @date 25/06/2013 4 | * @brief Contains a measure class to embbed all measures of similarity classes 5 | * Also contains an interface class between reg_base and the measure class 6 | */ 7 | 8 | #ifndef _REG_MEASURE_H 9 | #define _REG_MEASURE_H 10 | 11 | #include "_reg_tools.h" 12 | #include 13 | /* \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ */ 14 | /* \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ */ 15 | /// @brief Class common to all measure of similarity classes 16 | class reg_measure 17 | { 18 | public: 19 | /// @brief Set the pointers to be ussed by the measure object 20 | void InitialiseMeasure(nifti_image *refImgPtr, 21 | nifti_image *floImgPtr, 22 | int *maskRefPtr, 23 | nifti_image *warFloImgPtr, 24 | nifti_image *warFloGraPtr, 25 | nifti_image *forVoxBasedGraPtr, 26 | nifti_image *localWeightSimPtr = NULL, 27 | int *maskFloPtr = NULL, 28 | nifti_image *warRefImgPtr = NULL, 29 | nifti_image *warRefGraPtr = NULL, 30 | nifti_image *bckVoxBasedGraPtr = NULL) 31 | { 32 | this->isSymmetric=false; 33 | this->referenceImagePointer=refImgPtr; 34 | this->referenceTimePoint=this->referenceImagePointer->nt; 35 | this->floatingImagePointer=floImgPtr; 36 | this->referenceMaskPointer=maskRefPtr; 37 | this->warpedFloatingImagePointer=warFloImgPtr; 38 | this->warpedFloatingGradientImagePointer=warFloGraPtr; 39 | this->forwardVoxelBasedGradientImagePointer=forVoxBasedGraPtr; 40 | this->forwardLocalWeightSimImagePointer=localWeightSimPtr; 41 | if(maskFloPtr != NULL && warRefImgPtr!=NULL && warRefGraPtr!=NULL && bckVoxBasedGraPtr!=NULL) { 42 | this->isSymmetric=true; 43 | this->floatingMaskPointer=maskFloPtr; 44 | this->warpedReferenceImagePointer=warRefImgPtr; 45 | this->warpedReferenceGradientImagePointer=warRefGraPtr; 46 | this->backwardVoxelBasedGradientImagePointer=bckVoxBasedGraPtr; 47 | } 48 | else { 49 | this->floatingMaskPointer=NULL; 50 | this->warpedReferenceImagePointer=NULL; 51 | this->warpedReferenceGradientImagePointer=NULL; 52 | this->backwardVoxelBasedGradientImagePointer=NULL; 53 | } 54 | #ifndef NDEBUG 55 | printf("[NiftyReg DEBUG] reg_measure::InitialiseMeasure()\n"); 56 | #endif 57 | } 58 | /// @brief Returns the registration measure of similarity value 59 | virtual double GetSimilarityMeasureValue() = 0; 60 | /// @brief Compute the voxel based measure of similarity gradient 61 | virtual void GetVoxelBasedSimilarityMeasureGradient(int current_timepoint){ 62 | if(current_timepoint<0 || current_timepoint>=this->referenceImagePointer->nt){ 63 | reg_print_fct_error("reg_measure::GetVoxelBasedSimilarityMeasureGradient"); 64 | reg_print_msg_error("The specified active timepoint is not defined in the ref/war images"); 65 | reg_exit(); 66 | } 67 | } 68 | /// @brief Here 69 | virtual void GetDiscretisedValue(nifti_image *, float *, int , int) {} 70 | void SetTimepointWeight(int timepoint, double weight) 71 | { 72 | this->timePointWeight[timepoint]=weight; 73 | } 74 | double *GetTimepointsWeights(void) 75 | { 76 | return this->timePointWeight; 77 | } 78 | /************************************************************************/ 79 | nifti_image* GetReferenceImage(void) 80 | { 81 | return this->referenceImagePointer; 82 | } 83 | int* GetReferenceMask(void) 84 | { 85 | return this->referenceMaskPointer; 86 | } 87 | /************************************************************************/ 88 | protected: 89 | nifti_image *referenceImagePointer; 90 | int *referenceMaskPointer; 91 | nifti_image *warpedFloatingImagePointer; 92 | nifti_image *warpedFloatingGradientImagePointer; 93 | nifti_image *forwardVoxelBasedGradientImagePointer; 94 | nifti_image *forwardLocalWeightSimImagePointer; 95 | 96 | bool isSymmetric; 97 | nifti_image *floatingImagePointer; 98 | int *floatingMaskPointer; 99 | nifti_image *warpedReferenceImagePointer; 100 | nifti_image *warpedReferenceGradientImagePointer; 101 | nifti_image *backwardVoxelBasedGradientImagePointer; 102 | 103 | double timePointWeight[255]; 104 | int referenceTimePoint; 105 | /// @brief Measure class constructor 106 | reg_measure() 107 | { 108 | memset(this->timePointWeight,0,255*sizeof(double) ); 109 | #ifndef NDEBUG 110 | printf("[NiftyReg DEBUG] reg_measure constructor called\n"); 111 | #endif 112 | } 113 | /// @brief Measure class desstructor 114 | virtual ~reg_measure() {} 115 | }; 116 | /* \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ */ 117 | /* \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ */ 118 | #endif // _REG_MEASURE_H 119 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_mind.h: -------------------------------------------------------------------------------- 1 | /* 2 | * _reg_mind.h 3 | * 4 | * 5 | * Created by Marc Modat on 01/12/2015. 6 | * Copyright (c) 2015, University College London. All rights reserved. 7 | * Centre for Medical Image Computing (CMIC) 8 | * See the LICENSE.txt file in the nifty_reg root folder 9 | * 10 | */ 11 | #ifndef _REG_MIND_H 12 | #define _REG_MIND_H 13 | 14 | #include "_reg_ssd.h" 15 | //#include "ConvolutionKernel.h" 16 | //#include "Platform.h" 17 | #include 18 | #include "_reg_globalTrans.h" 19 | #include "_reg_resampling.h" 20 | #include 21 | 22 | #define MIND_TYPE 0 23 | #define MINDSSC_TYPE 1 24 | 25 | /* *************************************************************** */ 26 | /* *************************************************************** */ 27 | /// @brief MIND measure of similarity class 28 | class reg_mind : public reg_ssd 29 | { 30 | public: 31 | /// @brief reg_mind class constructor 32 | reg_mind(); 33 | /// @brief Initialise the reg_mind object 34 | void InitialiseMeasure(nifti_image *refImgPtr, 35 | nifti_image *floImgPtr, 36 | int *maskRefPtr, 37 | nifti_image *warFloImgPtr, 38 | nifti_image *warFloGraPtr, 39 | nifti_image *forVoxBasedGraPtr, 40 | nifti_image *forwardLocalWeightPtr = NULL, 41 | int *maskFloPtr = NULL, 42 | nifti_image *warRefImgPtr = NULL, 43 | nifti_image *warRefGraPtr = NULL, 44 | nifti_image *bckVoxBasedGraPtr = NULL); 45 | /// @brief Returns the mind based measure of similarity value 46 | virtual double GetSimilarityMeasureValue(); 47 | /// @brief Compute the voxel based gradient 48 | virtual void GetVoxelBasedSimilarityMeasureGradient(int current_timepoint); 49 | /// @brief 50 | void SetDescriptorOffset(int); 51 | int GetDescriptorOffset(); 52 | /// @brief Measure class desstructor 53 | ~reg_mind(); 54 | 55 | protected: 56 | nifti_image *referenceImageDescriptor; 57 | nifti_image *floatingImageDescriptor; 58 | nifti_image *warpedReferenceImageDescriptor; 59 | nifti_image *warpedFloatingImageDescriptor; 60 | double timePointWeightDescriptor[255]; 61 | 62 | int descriptorOffset; 63 | int mind_type; 64 | int discriptor_number; 65 | }; 66 | /* *************************************************************** */ 67 | /// @brief MIND-SSC measure of similarity class 68 | class reg_mindssc : public reg_mind 69 | { 70 | public: 71 | /// @brief reg_mind class constructor 72 | reg_mindssc(); 73 | /// @brief Measure class desstructor 74 | ~reg_mindssc(); 75 | }; 76 | /* *************************************************************** */ 77 | 78 | extern "C++" 79 | void GetMINDImageDesciptor(nifti_image* inputImgPtr, 80 | nifti_image* MINDImgPtr, 81 | int *mask, 82 | int descriptorOffset, 83 | int current_timepoint); 84 | extern "C++" 85 | void GetMINDSSCImageDesciptor(nifti_image* inputImgPtr, 86 | nifti_image* MINDSSCImgPtr, 87 | int *mask, 88 | int descriptorOffset, 89 | int current_timepoint); 90 | #endif 91 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_resampling.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file _reg_resampling.h 3 | * @author Marc Modat 4 | * @date 24/03/2009 5 | * 6 | * Created by Marc Modat on 24/03/2009. 7 | * Copyright (c) 2009, University College London. All rights reserved. 8 | * Centre for Medical Image Computing (CMIC) 9 | * See the LICENSE.txt file in the nifty_reg root folder 10 | * 11 | */ 12 | 13 | #ifndef _REG_RESAMPLING_H 14 | #define _REG_RESAMPLING_H 15 | 16 | #include "nifti1_io.h" 17 | 18 | /** @brief This function resample a floating image into the space of a reference/warped image. 19 | * The deformation is provided by a 4D nifti image which is in the space of the reference image. 20 | * In the 4D image, for each voxel i,j,k, the position in the real word for the floating image is store. 21 | * Interpolation can be nearest Neighbor (0), linear (1) or cubic spline (3). 22 | * The cubic spline interpolation assume a padding value of 0 23 | * The padding value for the NN and the LIN interpolation are user defined. 24 | * @param floatingImage Floating image that is interpolated 25 | * @param warpedImage Warped image that is being generated 26 | * @param deformationField Vector field image that contains the dense correspondences 27 | * @param mask Array that contains information about the mask. Only voxel with mask value different 28 | * from zero are being considered. If NULL, all voxels are considered 29 | * @param interp Interpolation type. 0, 1 or 3 correspond to nearest neighbor, linear or cubic 30 | * interpolation 31 | * @param paddingValue Value to be used for padding when the correspondences are outside of the 32 | * reference image space. 33 | * @param dtIndicies Array of 6 integers that correspond to the "time" indicies of the diffusion tensor 34 | * components in the order xx,yy,zz,xy,xz,yz. If there are no DT images, pass an array of -1's 35 | */ 36 | extern "C++" 37 | void reg_resampleImage(nifti_image *floatingImage, 38 | nifti_image *warpedImage, 39 | nifti_image *deformationField, 40 | int *mask, 41 | int interp, 42 | float paddingValue, 43 | bool *dti_timepoint = NULL, 44 | mat33 * jacMat = NULL); 45 | extern "C++" 46 | void reg_resampleImage_PSF(nifti_image *floatingImage, 47 | nifti_image *warpedImage, 48 | nifti_image *deformationField, 49 | int *mask, 50 | int interp, 51 | float paddingValue, 52 | mat33 * jacMat, 53 | char algorithm); 54 | 55 | 56 | extern "C++" 57 | void reg_resampleGradient(nifti_image *gradientImage, 58 | nifti_image *warImgGradient, 59 | nifti_image *deformationField, 60 | int interp, 61 | float paddingValue); 62 | 63 | extern "C++" 64 | void reg_getImageGradient(nifti_image *floatingImage, 65 | nifti_image *warImgGradient, 66 | nifti_image *deformationField, 67 | int *mask, 68 | int interp, 69 | float paddingValue, 70 | int active_timepoint, 71 | bool *dti_timepoint = NULL, 72 | mat33 *jacMat = NULL, 73 | nifti_image *warpedImage = NULL); 74 | 75 | extern "C++" 76 | void reg_getImageGradient_symDiff(nifti_image* inputImg, 77 | nifti_image* gradImg, 78 | int *mask, 79 | float padding_value, 80 | int timepoint); 81 | extern "C++" 82 | nifti_image *reg_makeIsotropic(nifti_image *, int); 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_splineBasis.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file _reg_splineBasis.h 3 | * @brief Library that contains local deformation related functions 4 | * @author Marc Modat 5 | * @date 23/12/2015 6 | * 7 | * Centre for Medical Image Computing (CMIC) 8 | * See the LICENSE.txt file in the nifty_reg root folder 9 | * 10 | */ 11 | 12 | #ifndef _REG_SPLINE_H 13 | #define _REG_SPLINE_H 14 | 15 | #include "_reg_tools.h" 16 | 17 | 18 | extern "C++" template 19 | void get_BSplineBasisValues(DTYPE basis, 20 | DTYPE *values); 21 | extern "C++" template 22 | void get_BSplineBasisValues(DTYPE basis, 23 | DTYPE *values, 24 | DTYPE *first); 25 | extern "C++" template 26 | void get_BSplineBasisValues(DTYPE basis, 27 | DTYPE *values, 28 | DTYPE *first, 29 | DTYPE *second); 30 | 31 | 32 | extern "C++" template 33 | void get_BSplineBasisValue(DTYPE basis, 34 | int index, 35 | DTYPE &value); 36 | extern "C++" template 37 | void get_BSplineBasisValue(DTYPE basis, 38 | int index, 39 | DTYPE &value, 40 | DTYPE &first); 41 | extern "C++" template 42 | void get_BSplineBasisValue(DTYPE basis, 43 | int index, 44 | DTYPE &value, 45 | DTYPE &first, 46 | DTYPE &second); 47 | 48 | extern "C++" template 49 | void set_first_order_basis_values(DTYPE *basisX, 50 | DTYPE *basisY); 51 | 52 | extern "C++" template 53 | void set_first_order_basis_values(DTYPE *basisX, 54 | DTYPE *basisY, 55 | DTYPE *basisZ); 56 | 57 | extern "C++" template 58 | void set_second_order_bspline_basis_values(DTYPE *basisXX, 59 | DTYPE *basisYY, 60 | DTYPE *basisXY); 61 | extern "C++" template 62 | void set_second_order_bspline_basis_values(DTYPE *basisXX, 63 | DTYPE *basisYY, 64 | DTYPE *basisZZ, 65 | DTYPE *basisXY, 66 | DTYPE *basisYZ, 67 | DTYPE *basisXZ); 68 | 69 | 70 | extern "C++" template 71 | void get_SplineBasisValues(DTYPE basis, 72 | DTYPE *values); 73 | extern "C++" template 74 | void get_SplineBasisValues(DTYPE basis, 75 | DTYPE *values, 76 | DTYPE *first); 77 | extern "C++" template 78 | void get_SplineBasisValues(DTYPE basis, 79 | DTYPE *values, 80 | DTYPE *first, 81 | DTYPE *second); 82 | 83 | extern "C++" template 84 | void get_SlidedValues(DTYPE &defX, 85 | DTYPE &defY, 86 | int X, 87 | int Y, 88 | DTYPE *defPtrX, 89 | DTYPE *defPtrY, 90 | mat44 *df_voxel2Real, 91 | int *dim, 92 | bool displacement); 93 | extern "C++" template 94 | void get_SlidedValues(DTYPE &defX, 95 | DTYPE &defY, 96 | DTYPE &defZ, 97 | int X, 98 | int Y, 99 | int Z, 100 | DTYPE *defPtrX, 101 | DTYPE *defPtrY, 102 | DTYPE *defPtrZ, 103 | mat44 *df_voxel2Real, 104 | int *dim, 105 | bool displacement); 106 | 107 | 108 | extern "C++" template 109 | void get_GridValues(int startX, 110 | int startY, 111 | nifti_image *splineControlPoint, 112 | DTYPE *splineX, 113 | DTYPE *splineY, 114 | DTYPE *dispX, 115 | DTYPE *dispY, 116 | bool approx, 117 | bool displacement); 118 | extern "C++" template 119 | void get_GridValues(int startX, 120 | int startY, 121 | int startZ, 122 | nifti_image *splineControlPoint, 123 | DTYPE *splineX, 124 | DTYPE *splineY, 125 | DTYPE *splineZ, 126 | DTYPE *dispX, 127 | DTYPE *dispY, 128 | DTYPE *dispZ, 129 | bool approx, 130 | bool displacement); 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_ssd.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file _reg_ssd.h 3 | * @brief File that contains sum squared difference related function 4 | * @author Marc Modat 5 | * @date 19/05/2009 6 | * 7 | * Created by Marc Modat on 19/05/2009. 8 | * Copyright (c) 2009, University College London. All rights reserved. 9 | * Centre for Medical Image Computing (CMIC) 10 | * See the LICENSE.txt file in the nifty_reg root folder 11 | * 12 | */ 13 | 14 | #ifndef _REG_SSD_H 15 | #define _REG_SSD_H 16 | 17 | #include "_reg_measure.h" 18 | 19 | /* *************************************************************** */ 20 | /* *************************************************************** */ 21 | /// @brief SSD measure of similarity classe 22 | class reg_ssd : public reg_measure 23 | { 24 | public: 25 | /// @brief reg_ssd class constructor 26 | reg_ssd(); 27 | /// @brief Initialise the reg_ssd object 28 | void InitialiseMeasure(nifti_image *refImgPtr, 29 | nifti_image *floImgPtr, 30 | int *maskRefPtr, 31 | nifti_image *warFloImgPtr, 32 | nifti_image *warFloGraPtr, 33 | nifti_image *forVoxBasedGraPtr, 34 | nifti_image *localWeightSimPtr, 35 | int *maskFloPtr = NULL, 36 | nifti_image *warRefImgPtr = NULL, 37 | nifti_image *warRefGraPtr = NULL, 38 | nifti_image *bckVoxBasedGraPtr = NULL); 39 | 40 | /// @brief Define if the specified time point should be normalised 41 | void SetNormaliseTimepoint(int timepoint, bool normalise); 42 | /// @brief Returns the ssd value 43 | virtual double GetSimilarityMeasureValue(); 44 | /// @brief Compute the voxel based ssd gradient 45 | virtual void GetVoxelBasedSimilarityMeasureGradient(int current_timepoint); 46 | /// @brief Here 47 | virtual void GetDiscretisedValue(nifti_image *controlPointGridImage, 48 | float *discretisedValue, 49 | int discretise_radius, 50 | int discretise_step); 51 | /// @brief reg_ssd class desstructor 52 | ~reg_ssd() {} 53 | protected: 54 | float currentValue[255]; 55 | 56 | private: 57 | bool normaliseTimePoint[255]; 58 | }; 59 | /* *************************************************************** */ 60 | 61 | /** @brief Copmutes and returns the SSD between two input images 62 | * @param referenceImage First input image to use to compute the metric 63 | * @param warpedImage Second input image to use to compute the metric 64 | * @param activeTimePoint Specified which time point volumes have to be considered 65 | * @param jacobianDeterminantImage Image that contains the Jacobian 66 | * determinant of a transformation at every voxel position. This 67 | * image is used to modulate the SSD. The argument is ignored if the 68 | * pointer is set to NULL 69 | * @param mask Array that contains a mask to specify which voxel 70 | * should be considered. If set to NULL, all voxels are considered 71 | * @return Returns the computed sum squared difference 72 | */ 73 | extern "C++" template 74 | double reg_getSSDValue(nifti_image *referenceImage, 75 | nifti_image *warpedImage, 76 | double *timePointWeight, 77 | nifti_image *jacobianDeterminantImage, 78 | int *mask, 79 | float *currentValue, 80 | nifti_image *localWeightImage 81 | ); 82 | 83 | /** @brief Compute a voxel based gradient of the sum squared difference. 84 | * @param referenceImage First input image to use to compute the metric 85 | * @param warpedImage Second input image to use to compute the metric 86 | * @param activeTimePoint Specified which time point volumes have to be considered 87 | * @param warpedImageGradient Spatial gradient of the input warped image 88 | * @param ssdGradientImage Output image htat will be updated with the 89 | * value of the SSD gradient 90 | * @param jacobianDeterminantImage Image that contains the Jacobian 91 | * determinant of a transformation at every voxel position. This 92 | * image is used to modulate the SSD. The argument is ignored if the 93 | * pointer is set to NULL 94 | * @param mask Array that contains a mask to specify which voxel 95 | * should be considered. If set to NULL, all voxels are considered 96 | */ 97 | extern "C++" template 98 | void reg_getVoxelBasedSSDGradient(nifti_image *referenceImage, 99 | nifti_image *warpedImage, 100 | nifti_image *warpedImageGradient, 101 | nifti_image *ssdGradientImage, 102 | nifti_image *jacobianDeterminantImage, 103 | int *mask, 104 | int current_timepoint, 105 | double timepoint_weight, 106 | nifti_image *localWeightImage 107 | ); 108 | #endif 109 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_stringFormat.h: -------------------------------------------------------------------------------- 1 | // http://stackoverflow.com/a/26221725 2 | // but re-written with variadic arguments from C (better supported prior to 3 | // C++11 than the C++ form) and avoid unique_ptr use. 4 | #include 5 | #include 6 | 7 | /* 8 | template 9 | std::string stringFormat( const std::string& format, Args ... args ) 10 | */ 11 | std::string stringFormat( const std::string format, ... ); 12 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/pngdebug.h: -------------------------------------------------------------------------------- 1 | 2 | /* pngdebug.h - Debugging macros for libpng, also used in pngtest.c 3 | * 4 | * Copyright (c) 1998-2011 Glenn Randers-Pehrson 5 | * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 6 | * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 7 | * 8 | * Last changed in libpng 1.5.0 [January 6, 2011] 9 | * 10 | * This code is released under the libpng license. 11 | * For conditions of distribution and use, see the disclaimer 12 | * and license in png.h 13 | */ 14 | 15 | /* Define PNG_DEBUG at compile time for debugging information. Higher 16 | * numbers for PNG_DEBUG mean more debugging information. This has 17 | * only been added since version 0.95 so it is not implemented throughout 18 | * libpng yet, but more support will be added as needed. 19 | * 20 | * png_debug[1-2]?(level, message ,arg{0-2}) 21 | * Expands to a statement (either a simple expression or a compound 22 | * do..while(0) statement) that outputs a message with parameter 23 | * substitution if PNG_DEBUG is defined to 2 or more. If PNG_DEBUG 24 | * is undefined, 0 or 1 every png_debug expands to a simple expression 25 | * (actually ((void)0)). 26 | * 27 | * level: level of detail of message, starting at 0. A level 'n' 28 | * message is preceded by 'n' tab characters (not implemented 29 | * on Microsoft compilers unless PNG_DEBUG_FILE is also 30 | * defined, to allow debug DLL compilation with no standard IO). 31 | * message: a printf(3) style text string. A trailing '\n' is added 32 | * to the message. 33 | * arg: 0 to 2 arguments for printf(3) style substitution in message. 34 | */ 35 | #ifndef PNGDEBUG_H 36 | #define PNGDEBUG_H 37 | /* These settings control the formatting of messages in png.c and pngerror.c */ 38 | /* Moved to pngdebug.h at 1.5.0 */ 39 | # ifndef PNG_LITERAL_SHARP 40 | # define PNG_LITERAL_SHARP 0x23 41 | # endif 42 | # ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET 43 | # define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b 44 | # endif 45 | # ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET 46 | # define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d 47 | # endif 48 | # ifndef PNG_STRING_NEWLINE 49 | # define PNG_STRING_NEWLINE "\n" 50 | # endif 51 | 52 | #ifdef PNG_DEBUG 53 | # if (PNG_DEBUG > 0) 54 | # if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) 55 | # include 56 | # if (PNG_DEBUG > 1) 57 | # ifndef _DEBUG 58 | # define _DEBUG 59 | # endif 60 | # ifndef png_debug 61 | # define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) 62 | # endif 63 | # ifndef png_debug1 64 | # define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) 65 | # endif 66 | # ifndef png_debug2 67 | # define png_debug2(l,m,p1,p2) \ 68 | _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) 69 | # endif 70 | # endif 71 | # else /* PNG_DEBUG_FILE || !_MSC_VER */ 72 | # ifndef PNG_STDIO_SUPPORTED 73 | # include /* not included yet */ 74 | # endif 75 | # ifndef PNG_DEBUG_FILE 76 | # define PNG_DEBUG_FILE stderr 77 | # endif /* PNG_DEBUG_FILE */ 78 | 79 | # if (PNG_DEBUG > 1) 80 | /* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on 81 | * non-ISO compilers 82 | */ 83 | # ifdef __STDC__ 84 | # ifndef png_debug 85 | # define png_debug(l,m) \ 86 | do { \ 87 | int num_tabs=l; \ 88 | fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ 89 | (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ 90 | } while (0) 91 | # endif 92 | # ifndef png_debug1 93 | # define png_debug1(l,m,p1) \ 94 | do { \ 95 | int num_tabs=l; \ 96 | fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ 97 | (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ 98 | } while (0) 99 | # endif 100 | # ifndef png_debug2 101 | # define png_debug2(l,m,p1,p2) \ 102 | do { \ 103 | int num_tabs=l; \ 104 | fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ 105 | (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ 106 | } while (0) 107 | # endif 108 | # else /* __STDC __ */ 109 | # ifndef png_debug 110 | # define png_debug(l,m) \ 111 | do { \ 112 | int num_tabs=l; \ 113 | char format[256]; \ 114 | snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ 115 | (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ 116 | m,PNG_STRING_NEWLINE); \ 117 | fprintf(PNG_DEBUG_FILE,format); \ 118 | } while (0) 119 | # endif 120 | # ifndef png_debug1 121 | # define png_debug1(l,m,p1) \ 122 | do { \ 123 | int num_tabs=l; \ 124 | char format[256]; \ 125 | snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ 126 | (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ 127 | m,PNG_STRING_NEWLINE); \ 128 | fprintf(PNG_DEBUG_FILE,format,p1); \ 129 | } while (0) 130 | # endif 131 | # ifndef png_debug2 132 | # define png_debug2(l,m,p1,p2) \ 133 | do { \ 134 | int num_tabs=l; \ 135 | char format[256]; \ 136 | snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ 137 | (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ 138 | m,PNG_STRING_NEWLINE); \ 139 | fprintf(PNG_DEBUG_FILE,format,p1,p2); \ 140 | } while (0) 141 | # endif 142 | # endif /* __STDC __ */ 143 | # endif /* (PNG_DEBUG > 1) */ 144 | 145 | # endif /* _MSC_VER */ 146 | # endif /* (PNG_DEBUG > 0) */ 147 | #endif /* PNG_DEBUG */ 148 | #ifndef png_debug 149 | # define png_debug(l, m) ((void)0) 150 | #endif 151 | #ifndef png_debug1 152 | # define png_debug1(l, m, p1) ((void)0) 153 | #endif 154 | #ifndef png_debug2 155 | # define png_debug2(l, m, p1, p2) ((void)0) 156 | #endif 157 | #endif /* PNGDEBUG_H */ 158 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/readpng.h: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------- 2 | 3 | rpng - simple PNG display program readpng.h 4 | 5 | --------------------------------------------------------------------------- 6 | 7 | Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. 8 | 9 | This software is provided "as is," without warranty of any kind, 10 | express or implied. In no event shall the author or contributors 11 | be held liable for any damages arising in any way from the use of 12 | this software. 13 | 14 | The contents of this file are DUAL-LICENSED. You may modify and/or 15 | redistribute this software according to the terms of one of the 16 | following two licenses (at your option): 17 | 18 | 19 | LICENSE 1 ("BSD-like with advertising clause"): 20 | 21 | Permission is granted to anyone to use this software for any purpose, 22 | including commercial applications, and to alter it and redistribute 23 | it freely, subject to the following restrictions: 24 | 25 | 1. Redistributions of source code must retain the above copyright 26 | notice, disclaimer, and this list of conditions. 27 | 2. Redistributions in binary form must reproduce the above copyright 28 | notice, disclaimer, and this list of conditions in the documenta- 29 | tion and/or other materials provided with the distribution. 30 | 3. All advertising materials mentioning features or use of this 31 | software must display the following acknowledgment: 32 | 33 | This product includes software developed by Greg Roelofs 34 | and contributors for the book, "PNG: The Definitive Guide," 35 | published by O'Reilly and Associates. 36 | 37 | 38 | LICENSE 2 (GNU GPL v2 or later): 39 | 40 | This program is free software; you can redistribute it and/or modify 41 | it under the terms of the GNU General Public License as published by 42 | the Free Software Foundation; either version 2 of the License, or 43 | (at your option) any later version. 44 | 45 | This program is distributed in the hope that it will be useful, 46 | but WITHOUT ANY WARRANTY; without even the implied warranty of 47 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 48 | GNU General Public License for more details. 49 | 50 | You should have received a copy of the GNU General Public License 51 | along with this program; if not, write to the Free Software Foundation, 52 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 53 | 54 | ---------------------------------------------------------------------------*/ 55 | 56 | #include "png.h" /* libpng header; includes zlib.h */ 57 | #include "zlib.h" 58 | 59 | #ifndef TRUE 60 | # define TRUE 1 61 | # define FALSE 0 62 | #endif 63 | 64 | #ifndef MAX 65 | # define MAX(a,b) ((a) > (b)? (a) : (b)) 66 | # define MIN(a,b) ((a) < (b)? (a) : (b)) 67 | #endif 68 | 69 | #ifdef DEBUG 70 | # define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);} 71 | #else 72 | # define Trace(x) ; 73 | #endif 74 | 75 | typedef unsigned char uch; 76 | typedef unsigned short ush; 77 | typedef unsigned long ulg; 78 | 79 | 80 | /* prototypes for public functions in readpng.c */ 81 | 82 | void readpng_version_info(void); 83 | 84 | int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight); 85 | 86 | int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue); 87 | 88 | uch *readpng_get_image(double display_exponent, int *pChannels, 89 | ulg *pRowbytes); 90 | 91 | void readpng_cleanup(int free_image_data); 92 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/reg_png.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file reg_png.h 3 | * @author Marc Modat 4 | * @date 30/05/2012 5 | * @brief Interface between NiftyReg and pnglib 6 | * 7 | * Created by Marc Modat on 30/05/2012. 8 | * Copyright (c) 2012, University College London. All rights reserved. 9 | * Centre for Medical Image Computing (CMIC) 10 | * See the LICENSE.txt file in the nifty_reg root folder 11 | * 12 | */ 13 | 14 | #ifndef _REG_PNG_H 15 | #define _REG_PNG_H 16 | 17 | #include "nifti1_io.h" 18 | #include "_reg_tools.h" 19 | 20 | /* *************************************************************** */ 21 | /** @brief This function read a png file from the hard-drive and convert 22 | * it into a nifti_structure. using this function, you can either 23 | * read the full image or only the header information 24 | * @param filename Filename of the png file to read 25 | * @param readData The actual data is read if the flag is set to true 26 | * @return Returns a pointer to the nifti_image that contains the PNG file 27 | */ 28 | nifti_image *reg_io_readPNGfile(const char *filename, bool readData); 29 | /* *************************************************************** */ 30 | /** @brief This function first convert a nifti image into a png and then 31 | * save the png file. 32 | * @param image Nifti image that will first be converted to a png file 33 | * and then will be saved on the disk 34 | * @param filename Path where the png file will be saved on the disk 35 | */ 36 | void reg_io_writePNGfile(nifti_image *image, const char *filename); 37 | /* *************************************************************** */ 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/znzlib.h: -------------------------------------------------------------------------------- 1 | #ifndef _ZNZLIB_H_ 2 | #define _ZNZLIB_H_ 3 | 4 | /* 5 | znzlib.h (zipped or non-zipped library) 6 | 7 | ***** This code is released to the public domain. ***** 8 | 9 | ***** Author: Mark Jenkinson, FMRIB Centre, University of Oxford ***** 10 | ***** Date: September 2004 ***** 11 | 12 | ***** Neither the FMRIB Centre, the University of Oxford, nor any of ***** 13 | ***** its employees imply any warranty of usefulness of this software ***** 14 | ***** for any purpose, and do not assume any liability for damages, ***** 15 | ***** incidental or otherwise, caused by any use of this document. ***** 16 | 17 | */ 18 | 19 | /* 20 | 21 | This library provides an interface to both compressed (gzip/zlib) and 22 | uncompressed (normal) file IO. The functions are written to have the 23 | same interface as the standard file IO functions. 24 | 25 | To use this library instead of normal file IO, the following changes 26 | are required: 27 | - replace all instances of FILE* with znzFile 28 | - change the name of all function calls, replacing the initial character 29 | f with the znz (e.g. fseek becomes znzseek) 30 | - add a third parameter to all calls to znzopen (previously fopen) 31 | that specifies whether to use compression (1) or not (0) 32 | - use znz_isnull rather than any (pointer == NULL) comparisons in the code 33 | 34 | NB: seeks for writable files with compression are quite restricted 35 | 36 | */ 37 | 38 | 39 | /*=================*/ 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | /*=================*/ 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | 50 | /* include optional check for HAVE_FDOPEN here, from deleted config.h: 51 | 52 | uncomment the following line if fdopen() exists for your compiler and 53 | compiler options 54 | */ 55 | /* #define HAVE_FDOPEN */ 56 | 57 | 58 | #ifdef HAVE_ZLIB 59 | #if defined(ITKZLIB) 60 | #include "itk_zlib.h" 61 | #else 62 | #include "zlib.h" 63 | #endif 64 | #endif 65 | 66 | 67 | struct znzptr 68 | { 69 | int withz; 70 | FILE* nzfptr; 71 | #ifdef HAVE_ZLIB 72 | gzFile zfptr; 73 | #endif 74 | } ; 75 | 76 | /* the type for all file pointers */ 77 | typedef struct znzptr * znzFile; 78 | 79 | 80 | /* int znz_isnull(znzFile f); */ 81 | /* int znzclose(znzFile f); */ 82 | #define znz_isnull(f) ((f) == NULL) 83 | #define znzclose(f) Xznzclose(&(f)) 84 | 85 | /* Note extra argument (use_compression) where 86 | use_compression==0 is no compression 87 | use_compression!=0 uses zlib (gzip) compression 88 | */ 89 | 90 | znzFile znzopen(const char *path, const char *mode, int use_compression); 91 | 92 | znzFile znzdopen(int fd, const char *mode, int use_compression); 93 | 94 | int Xznzclose(znzFile * file); 95 | 96 | size_t znzread(void* buf, size_t size, size_t nmemb, znzFile file); 97 | 98 | size_t znzwrite(const void* buf, size_t size, size_t nmemb, znzFile file); 99 | 100 | long znzseek(znzFile file, long offset, int whence); 101 | 102 | int znzrewind(znzFile stream); 103 | 104 | long znztell(znzFile file); 105 | 106 | int znzputs(const char *str, znzFile file); 107 | 108 | char * znzgets(char* str, int size, znzFile file); 109 | 110 | int znzputc(int c, znzFile file); 111 | 112 | int znzgetc(znzFile file); 113 | 114 | #if !defined(WIN32) 115 | int znzprintf(znzFile stream, const char *format, ...); 116 | #endif 117 | 118 | /*=================*/ 119 | #ifdef __cplusplus 120 | } 121 | #endif 122 | /*=================*/ 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/reg_aladin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/reg_aladin -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/reg_resample: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/reg_resample -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/rigid_reg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Function to check if a file exists 4 | file_exists() { 5 | if [ -f "$1" ]; then 6 | return 0 7 | else 8 | return 1 9 | fi 10 | } 11 | 12 | # Check if the correct number of arguments is provided 13 | if [ "$#" -ne 5 ]; then 14 | echo "Usage: $0 " 15 | exit 1 16 | fi 17 | 18 | # Assign arguments to meaningful variable names 19 | niftyreg_executable="$1" 20 | fixed_image="$2" 21 | moving_image="$3" 22 | transformed_image="$4" 23 | transformation_matrix="$5" 24 | 25 | # Validate the existence of input files 26 | if ! file_exists "$fixed_image"; then 27 | echo "Error: Fixed image '$fixed_image' does not exist." 28 | exit 1 29 | fi 30 | 31 | if ! file_exists "$moving_image"; then 32 | echo "Error: Moving image '$moving_image' does not exist." 33 | exit 1 34 | fi 35 | 36 | # NiftyReg configuration 37 | niftyreg_path=$niftyreg_executable 38 | registration_options=( 39 | "-rigOnly" # Perform rigid-only registration 40 | "-ref" "$fixed_image" 41 | "-flo" "$moving_image" 42 | "-res" "$transformed_image" 43 | "-aff" "$transformation_matrix" 44 | ) 45 | 46 | # Perform rigid-only registration with NiftyReg 47 | if file_exists "$niftyreg_path"; then 48 | "$niftyreg_path" "${registration_options[@]}" 49 | exit_code=$? 50 | if [ $exit_code -ne 0 ]; then 51 | echo "Error: NiftyReg registration failed with exit code $exit_code." 52 | exit $exit_code 53 | fi 54 | else 55 | echo "Error: NiftyReg script not found at '$niftyreg_path'." 56 | exit 1 57 | fi 58 | 59 | # Optional: Additional commands or post-processing steps 60 | 61 | echo "Registration completed successfully." 62 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/niftyreg/niftyreg_scripts/transform.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Function to check if a file exists 4 | file_exists() { 5 | if [ -f "$1" ]; then 6 | return 0 7 | else 8 | return 1 9 | fi 10 | } 11 | 12 | # Check if the correct number of arguments is provided 13 | if [ "$#" -ne 5 ]; then 14 | echo "Usage: $0 " 15 | exit 1 16 | fi 17 | 18 | # Assign arguments to meaningful variable names 19 | niftyreg_executable="$1" 20 | fixed_image="$2" 21 | moving_image="$3" 22 | transformed_image="$4" 23 | transformation_matrix="$5" 24 | 25 | # Validate the existence of input files 26 | if ! file_exists "$fixed_image"; then 27 | echo "Error: Fixed image '$fixed_image' does not exist." 28 | exit 1 29 | fi 30 | 31 | if ! file_exists "$moving_image"; then 32 | echo "Error: Moving image '$moving_image' does not exist." 33 | exit 1 34 | fi 35 | 36 | if ! file_exists "$transformation_matrix"; then 37 | echo "Error: Transformation matrix file '$transformation_matrix' does not exist." 38 | exit 1 39 | fi 40 | 41 | # NiftyReg configuration 42 | niftyreg_path=$niftyreg_executable 43 | interpolation_method="3" # Choose the appropriate interpolation method (e.g., 0, 1, 3) 44 | 45 | # Perform resampling with NiftyReg 46 | resample_command=( 47 | "$niftyreg_path" 48 | -ref "$fixed_image" 49 | -flo "$moving_image" 50 | -trans "$transformation_matrix" 51 | -res "$transformed_image" 52 | -inter "$interpolation_method" 53 | ) 54 | 55 | if file_exists "$niftyreg_path"; then 56 | "${resample_command[@]}" 57 | exit_code=$? 58 | if [ $exit_code -ne 0 ]; then 59 | echo "Error: NiftyReg failed with exit code $exit_code." 60 | exit $exit_code 61 | fi 62 | else 63 | echo "Error: NiftyReg script not found at '$niftyreg_path'." 64 | exit 1 65 | fi 66 | 67 | # Optional: Additional commands or post-processing steps 68 | 69 | echo "Resampling completed successfully." 70 | -------------------------------------------------------------------------------- /brainles_preprocessing/registration/registrator.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import Any 3 | 4 | 5 | class Registrator(ABC): 6 | # TODO probably the init here should be removed? 7 | # def __init__(self, backend): 8 | # self.backend = backend 9 | 10 | @abstractmethod 11 | def register( 12 | self, 13 | fixed_image_path: Any, 14 | moving_image_path: Any, 15 | transformed_image_path: Any, 16 | matrix_path: Any, 17 | log_file_path: str, 18 | ): 19 | """ 20 | Abstract method for registering images. 21 | 22 | Args: 23 | fixed_image_path (Any): The fixed image for registration. 24 | moving_image_path (Any): The moving image to be registered. 25 | transformed_image_path (Any): The resulting transformed image after registration. 26 | matrix_path (Any): The transformation matrix applied during registration. 27 | log_file_path (str): The path to the log file for recording registration details. 28 | """ 29 | pass 30 | 31 | @abstractmethod 32 | def transform( 33 | self, 34 | fixed_image_path: Any, 35 | moving_image_path: Any, 36 | transformed_image_path: Any, 37 | matrix_path: Any, 38 | log_file_path: str, 39 | ): 40 | """ 41 | Abstract method for transforming images. 42 | 43 | Args: 44 | fixed_image_path (Any): The fixed image to be transformed. 45 | moving_image_path (Any): The moving image to be transformed. 46 | transformed_image_path (Any): The resulting transformed image. 47 | matrix_path (Any): The transformation matrix applied during transformation. 48 | log_file_path (str): The path to the log file for recording transformation details. 49 | 50 | """ 51 | pass 52 | -------------------------------------------------------------------------------- /brainles_preprocessing/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .generic import check_and_add_suffix 2 | -------------------------------------------------------------------------------- /brainles_preprocessing/utils/generic.py: -------------------------------------------------------------------------------- 1 | def check_and_add_suffix(filename: str, suffix: str) -> str: 2 | """ 3 | Adds a suffix to the filename if it doesn't already have it. 4 | 5 | Parameters: 6 | filename (str): The filename to check and potentially modify. 7 | suffix (str): The suffix to add to the filename. 8 | 9 | Returns: 10 | str: The filename with the suffix added if needed. 11 | """ 12 | filename_copy = filename 13 | if not filename_copy.endswith(suffix): 14 | filename_copy += suffix 15 | return filename_copy 16 | -------------------------------------------------------------------------------- /brainles_preprocessing/utils/logging_utils.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import signal 3 | import logging 4 | import traceback 5 | 6 | from datetime import datetime 7 | from pathlib import Path 8 | from typing import Optional, Union 9 | 10 | 11 | class LoggingManager: 12 | """ 13 | Manages logging configurations for the application or library. 14 | """ 15 | 16 | def __init__(self, name: str, log_file_path: Optional[Union[str, Path]] = None): 17 | self.name = name 18 | self.log_file_path = log_file_path 19 | 20 | # Create and configure the custom logger 21 | self.logger = logging.getLogger(self.name) 22 | self.log_file_handler = None 23 | 24 | # Disable log propagation 25 | self.logger.propagate = False 26 | 27 | # Set up the logger 28 | self._setup_logger() 29 | 30 | # Set up the logger file if provided 31 | if log_file_path: 32 | self._set_log_file(log_file_path) 33 | 34 | def get_logger(self) -> logging.Logger: 35 | """ 36 | Returns the logger instance. 37 | """ 38 | return self.logger 39 | 40 | def _setup_logger(self): 41 | """ 42 | Sets up the custom logger and overwrites system hooks to add logging for exceptions and signals. 43 | """ 44 | # Configure the custom logger if it hasn't been configured yet 45 | if not self.logger.handlers: 46 | self.logger.setLevel(logging.INFO) 47 | formatter = logging.Formatter( 48 | "[%(levelname)s | %(name)s] %(asctime)s: %(message)s", 49 | "%Y-%m-%dT%H:%M:%S%z", 50 | ) 51 | 52 | # Add a console handler 53 | console_handler = logging.StreamHandler() 54 | console_handler.setFormatter(formatter) 55 | self.logger.addHandler(console_handler) 56 | 57 | # Overwrite system hooks to log exceptions and signals (caution advised) 58 | sys.excepthook = self.exception_handler 59 | signal.signal(signal.SIGINT, self.signal_handler) 60 | signal.signal(signal.SIGTERM, self.signal_handler) 61 | 62 | def _set_log_file(self, log_file: str = None) -> None: 63 | """ 64 | Sets the log file handler for the logger. 65 | 66 | Args: 67 | log_file (str | Path, optional): Log file path. If not provided, a timestamped log file is created. 68 | """ 69 | 70 | # Remove existing log file handler if present 71 | if self.log_file_handler: 72 | self.remove_log_file_handler() 73 | 74 | # Ensure parent directories exist 75 | log_file = Path( 76 | log_file 77 | if log_file 78 | else f"brainles_preprocessing_{datetime.now().strftime('%Y-%m-%d_T%H-%M-%S.%f')}.log" 79 | ) 80 | log_file.parent.mkdir(parents=True, exist_ok=True) 81 | 82 | # Create and add the file handler 83 | self.log_file_handler = logging.FileHandler(str(log_file)) 84 | self.log_file_handler.setFormatter( 85 | logging.Formatter( 86 | "[%(levelname)-8s | %(name)s | %(module)-15s | L%(lineno)-5d] %(asctime)s: %(message)s", 87 | "%Y-%m-%dT%H:%M:%S%z", 88 | ) 89 | ) 90 | self.logger.addHandler(self.log_file_handler) 91 | self.log_file_path = log_file 92 | 93 | def remove_log_file_handler(self) -> None: 94 | """ 95 | Removes the log file handler from the logger. 96 | """ 97 | if self.log_file_handler: 98 | self.logger.removeHandler(self.log_file_handler) 99 | self.log_file_handler.close() 100 | self.log_file_handler = None 101 | self.log_file_path = None 102 | 103 | # overwrite system hooks to log exceptions and signals (SIGINT, SIGTERM) 104 | #! NOTE: This will note work in Jupyter Notebooks, (Without extra setup) see https://stackoverflow.com/a/70469055: 105 | def exception_handler(self, exception_type, value, tb): 106 | """Handle exceptions 107 | 108 | Args: 109 | exception_type (Exception): Exception type 110 | exception (Exception): Exception 111 | traceback (Traceback): Traceback 112 | """ 113 | self.logger.error( 114 | "".join(traceback.format_exception(exception_type, value, tb)) 115 | ) 116 | 117 | if issubclass(exception_type, SystemExit): 118 | # add specific code if exception was a system exit 119 | sys.exit(value.code) 120 | 121 | def signal_handler(self, sig, frame): 122 | """ 123 | Handles signals by logging them and exiting. 124 | 125 | Args: 126 | sig (int): Signal number 127 | frame (FrameType): Current stack frame 128 | """ 129 | signame = signal.Signals(sig).name 130 | self.logger.error(f"Received signal {sig} ({signame}), exiting...") 131 | sys.exit(0) 132 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/source/brain-extraction.rst: -------------------------------------------------------------------------------- 1 | brain_extraction 2 | ============================================ 3 | 4 | 5 | brain_extraction.brain_extractor 6 | -------------------------------------------- 7 | 8 | .. automodule:: brainles_preprocessing.brain_extraction.brain_extractor 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/source/brainles-preprocessing.rst: -------------------------------------------------------------------------------- 1 | brainles_preprocessing 2 | ============================================ 3 | 4 | 5 | modality 6 | -------------------------------------------- 7 | 8 | .. automodule:: brainles_preprocessing.modality 9 | 10 | 11 | preprocessor 12 | -------------------------------------------- 13 | 14 | .. automodule:: brainles_preprocessing.preprocessor 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # For the full list of built-in configuration values, see the documentation: 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 5 | 6 | import os 7 | import sys 8 | 9 | sys.path.insert(0, os.path.abspath("../../")) 10 | 11 | # -- Project information ----------------------------------------------------- 12 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 13 | 14 | project = "brainles-preprocessing" 15 | copyright = "2023, Florian Kofler et al." 16 | author = "Florian Kofler et al." 17 | 18 | # -- General configuration --------------------------------------------------- 19 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 20 | 21 | extensions = [ 22 | "sphinx.ext.autodoc", 23 | "sphinx.ext.autosummary", 24 | "sphinx.ext.napoleon", 25 | "sphinx_copybutton", 26 | "myst_parser", 27 | ] 28 | 29 | templates_path = ["_templates"] 30 | exclude_patterns = [] 31 | 32 | 33 | # -- Options for HTML output ------------------------------------------------- 34 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 35 | 36 | html_theme = "sphinx_rtd_theme" 37 | html_static_path = ["_static"] 38 | 39 | autodoc_default_options = { 40 | "members": True, 41 | "undoc-members": True, 42 | "private-members": True, 43 | "show-inheritance": True, 44 | } 45 | -------------------------------------------------------------------------------- /docs/source/defacing.rst: -------------------------------------------------------------------------------- 1 | defacing 2 | ============================================ 3 | 4 | 5 | 6 | defacing.defacer 7 | -------------------------------------------- 8 | 9 | .. automodule:: brainles_preprocessing.defacing.defacer 10 | 11 | 12 | defacing.quickshear 13 | -------------------------------------- 14 | 15 | .. automodule:: brainles_preprocessing.defacing.quickshear.quickshear 16 | 17 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. brainles-preprocessing documentation master file, created by 2 | sphinx-quickstart on Tue Nov 28 11:28:54 2023. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to brainles-preprocessing's documentation! 7 | =================================================== 8 | 9 | .. include:: ../../README.md 10 | :parser: myst_parser.sphinx_ 11 | 12 | .. toctree:: 13 | :maxdepth: 4 14 | :caption: Contents: 15 | 16 | 17 | 18 | Indices and tables 19 | =================== 20 | 21 | * :ref:`genindex` 22 | * :ref:`modindex` 23 | * :ref:`search` 24 | 25 | .. toctree:: 26 | :maxdepth: 2 27 | :caption: brainles_preprocessing: 28 | 29 | brainles-preprocessing.rst 30 | 31 | 32 | .. toctree:: 33 | :maxdepth: 2 34 | :caption: brain_extraction: 35 | 36 | brain-extraction.rst 37 | 38 | 39 | .. toctree:: 40 | :maxdepth: 2 41 | :caption: registration: 42 | 43 | registration.rst 44 | 45 | .. toctree:: 46 | :maxdepth: 2 47 | :caption: defacing: 48 | 49 | defacing.rst 50 | -------------------------------------------------------------------------------- /docs/source/registration.rst: -------------------------------------------------------------------------------- 1 | registration 2 | ================================================= 3 | 4 | 5 | registration.registrator 6 | -------------------------------------------- 7 | 8 | .. automodule:: brainles_preprocessing.registration.registrator 9 | 10 | 11 | registration.ANTs 12 | -------------------------------------- 13 | 14 | .. automodule:: brainles_preprocessing.registration.ANTs.ANTs 15 | 16 | 17 | registration.niftyreg 18 | -------------------------------------- 19 | 20 | .. automodule:: brainles_preprocessing.registration.niftyreg.niftyreg 21 | 22 | 23 | registration.greedy 24 | -------------------------------------- 25 | 26 | .. automodule:: brainles_preprocessing.registration.greedy.greedy 27 | 28 | 29 | registration.elastix 30 | -------------------------------------- 31 | 32 | .. automodule:: brainles_preprocessing.registration.elastix.elastix 33 | -------------------------------------------------------------------------------- /example/example_data/OtherEXampleFromTCIA/MRHR_FLAIR_AX_OtherEXampleTCIA_TCGA-FG-6692_Si_TCGA-FG-6692_MRHR_FLAIR_AX_SE_IR_5_tir2d1_21_fla.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/example/example_data/OtherEXampleFromTCIA/MRHR_FLAIR_AX_OtherEXampleTCIA_TCGA-FG-6692_Si_TCGA-FG-6692_MRHR_FLAIR_AX_SE_IR_5_tir2d1_21_fla.nii.gz -------------------------------------------------------------------------------- /example/example_data/OtherEXampleFromTCIA/MRHR_T1_AX_POST_GAD_OtherEXampleTCIA_TCGA-FG-6692_Si_TCGA-FG-6692_MRHR_T1_AX_POST_GAD_SE_13_se2d1r_t1c.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/example/example_data/OtherEXampleFromTCIA/MRHR_T1_AX_POST_GAD_OtherEXampleTCIA_TCGA-FG-6692_Si_TCGA-FG-6692_MRHR_T1_AX_POST_GAD_SE_13_se2d1r_t1c.nii.gz -------------------------------------------------------------------------------- /example/example_data/OtherEXampleFromTCIA/MRHR_T2_AX_OtherEXampleTCIA_TCGA-FG-6692_Si_TCGA-FG-6692_MRHR_T2_AX_SE_2_tse2d1_11_t2.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/example/example_data/OtherEXampleFromTCIA/MRHR_T2_AX_OtherEXampleTCIA_TCGA-FG-6692_Si_TCGA-FG-6692_MRHR_T2_AX_SE_2_tse2d1_11_t2.nii.gz -------------------------------------------------------------------------------- /example/example_data/OtherEXampleFromTCIA/T1_AX_OtherEXampleTCIA_TCGA-FG-6692_Si_TCGA-FG-6692_T1_AX_SE_10_se2d1_t1.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/example/example_data/OtherEXampleFromTCIA/T1_AX_OtherEXampleTCIA_TCGA-FG-6692_Si_TCGA-FG-6692_T1_AX_SE_10_se2d1_t1.nii.gz -------------------------------------------------------------------------------- /example/example_data/TCGA-DU-7294/AXIAL_FLAIR_RF2_150_TCGA-DU-7294_TCGA-DU-7294_GE_TCGA-DU-7294_AXIAL_FLAIR_RF2_150_IR_7_fla.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/example/example_data/TCGA-DU-7294/AXIAL_FLAIR_RF2_150_TCGA-DU-7294_TCGA-DU-7294_GE_TCGA-DU-7294_AXIAL_FLAIR_RF2_150_IR_7_fla.nii.gz -------------------------------------------------------------------------------- /example/example_data/TCGA-DU-7294/AX_T1_POST_GD_FLAIR_TCGA-DU-7294_TCGA-DU-7294_GE_TCGA-DU-7294_AX_T1_POST_GD_FLAIR_RM_13_t1c.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/example/example_data/TCGA-DU-7294/AX_T1_POST_GD_FLAIR_TCGA-DU-7294_TCGA-DU-7294_GE_TCGA-DU-7294_AX_T1_POST_GD_FLAIR_RM_13_t1c.nii.gz -------------------------------------------------------------------------------- /example/example_data/TCGA-DU-7294/AX_T1_pre_gd_TCGA-DU-7294_TCGA-DU-7294_GE_TCGA-DU-7294_AX_T1_pre_gd_RM_8_t1.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/example/example_data/TCGA-DU-7294/AX_T1_pre_gd_TCGA-DU-7294_TCGA-DU-7294_GE_TCGA-DU-7294_AX_T1_pre_gd_RM_8_t1.nii.gz -------------------------------------------------------------------------------- /example/example_data/TCGA-DU-7294/AX_T2_FR-FSE_RF2_150_TCGA-DU-7294_TCGA-DU-7294_GE_TCGA-DU-7294_AX_T2_FR-FSE_RF2_150_RM_4_t2.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/example/example_data/TCGA-DU-7294/AX_T2_FR-FSE_RF2_150_TCGA-DU-7294_TCGA-DU-7294_GE_TCGA-DU-7294_AX_T2_FR-FSE_RF2_150_RM_4_t2.nii.gz -------------------------------------------------------------------------------- /example/example_modality_centric_preprocessor.py: -------------------------------------------------------------------------------- 1 | # This script is an example of how to use the ModalityCentricPreprocessor class to preprocess a set of MR images. It is only here for quick development and testing purposes. It is not intended to be used in a production environment. 2 | from brainles_preprocessing.normalization.percentile_normalizer import ( 3 | PercentileNormalizer, 4 | ) 5 | from auxiliary.turbopath import turbopath 6 | from tqdm import tqdm 7 | 8 | from brainles_preprocessing.brain_extraction import HDBetExtractor 9 | from brainles_preprocessing.modality import Modality 10 | from brainles_preprocessing.preprocessor import Preprocessor 11 | from brainles_preprocessing.registration import ( 12 | ANTsRegistrator, 13 | # NiftyRegRegistrator, 14 | ) 15 | 16 | 17 | def preprocess(inputDir): 18 | inputDir = turbopath(inputDir) 19 | print("*** start ***") 20 | 21 | # where are the raw mr files? 22 | brainles_dir = turbopath(inputDir) + "/" + inputDir.name + "_brainles" 23 | 24 | raw_bet_dir = brainles_dir / "raw_bet" 25 | norm_bet_dir = brainles_dir / "normalized_bet" 26 | raw_skull_dir = brainles_dir / "raw_skull" 27 | norm_skull_dir = brainles_dir / "normalized_skull" 28 | raw_deface_dir = brainles_dir / "raw_defaced" 29 | norm_deface_dir = brainles_dir / "normalized_defaced" 30 | 31 | t1_file = inputDir.files("*t1.nii.gz") 32 | t1c_file = inputDir.files("*t1c.nii.gz") 33 | t2_file = inputDir.files("*t2.nii.gz") 34 | flair_file = inputDir.files("*fla.nii.gz") 35 | if len(t1_file) == len(t1c_file) == len(t2_file) == len(flair_file) == 1: 36 | # print(t1_file) 37 | # print(t1c_file) 38 | # print(t2_file) 39 | # print(flair_file) 40 | t1File = t1_file[0] 41 | t1cFile = t1c_file[0] 42 | t2File = t2_file[0] 43 | flaFile = flair_file[0] 44 | # normalizer 45 | percentile_normalizer = PercentileNormalizer( 46 | lower_percentile=0.1, 47 | upper_percentile=99.9, 48 | lower_limit=0, 49 | upper_limit=1, 50 | ) 51 | # define modalities 52 | center = Modality( 53 | modality_name="t1c", 54 | input_path=t1cFile, 55 | raw_bet_output_path=raw_bet_dir / inputDir.name + "_t1c_bet_raw.nii.gz", 56 | raw_skull_output_path=raw_skull_dir / inputDir.name 57 | + "_t1c_skull_raw.nii.gz", 58 | normalized_bet_output_path=norm_bet_dir / inputDir.name 59 | + "_t1c_bet_normalized.nii.gz", 60 | normalized_skull_output_path=norm_skull_dir / inputDir.name 61 | + "_t1c_skull_normalized.nii.gz", 62 | raw_defaced_output_path=raw_deface_dir / inputDir.name 63 | + "_t1c_defaced_raw.nii.gz", 64 | normalized_defaced_output_path=norm_deface_dir 65 | / "_t1c_defaced_normalized.nii.gz", 66 | atlas_correction=True, 67 | normalizer=percentile_normalizer, 68 | ) 69 | moving_modalities = [ 70 | Modality( 71 | modality_name="t1", 72 | input_path=t1File, 73 | raw_bet_output_path=raw_bet_dir / inputDir.name + "_t1_bet_raw.nii.gz", 74 | raw_skull_output_path=raw_skull_dir / inputDir.name 75 | + "_t1_skull_raw.nii.gz", 76 | normalized_bet_output_path=norm_bet_dir / inputDir.name 77 | + "_t1_bet_normalized.nii.gz", 78 | normalized_skull_output_path=norm_skull_dir / inputDir.name 79 | + "_t1_skull_normalized.nii.gz", 80 | raw_defaced_output_path=raw_deface_dir / inputDir.name 81 | + "_t1_defaced_raw.nii.gz", 82 | normalized_defaced_output_path=norm_deface_dir / inputDir.name 83 | + "_t1_defaced_normalized.nii.gz", 84 | atlas_correction=True, 85 | normalizer=percentile_normalizer, 86 | ), 87 | Modality( 88 | modality_name="t2", 89 | input_path=t2File, 90 | raw_bet_output_path=raw_bet_dir / inputDir.name + "_t2_bet_raw.nii.gz", 91 | raw_skull_output_path=raw_skull_dir / inputDir.name 92 | + "_t2_skull_raw.nii.gz", 93 | normalized_bet_output_path=norm_bet_dir / inputDir.name 94 | + "_t2_bet_normalized.nii.gz", 95 | normalized_skull_output_path=norm_skull_dir / inputDir.name 96 | + "_t2_skull_normalized.nii.gz", 97 | raw_defaced_output_path=raw_deface_dir / inputDir.name 98 | + "_t2_defaced_raw.nii.gz", 99 | normalized_defaced_output_path=norm_deface_dir / inputDir.name 100 | + "_t2_defaced_normalized.nii.gz", 101 | atlas_correction=True, 102 | normalizer=percentile_normalizer, 103 | ), 104 | Modality( 105 | modality_name="flair", 106 | input_path=flaFile, 107 | raw_bet_output_path=raw_bet_dir / inputDir.name + "_fla_bet_raw.nii.gz", 108 | raw_skull_output_path=raw_skull_dir / inputDir.name 109 | + "_fla_skull_raw.nii.gz", 110 | normalized_bet_output_path=norm_bet_dir / inputDir.name 111 | + "_fla_bet_normalized.nii.gz", 112 | normalized_skull_output_path=norm_skull_dir / inputDir.name 113 | + "_fla_skull_normalized.nii.gz", 114 | raw_defaced_output_path=raw_deface_dir / inputDir.name 115 | + "_fla_defaced_raw.nii.gz", 116 | normalized_defaced_output_path=norm_deface_dir / inputDir.name 117 | + "_fla_defaced_normalized.nii.gz", 118 | atlas_correction=True, 119 | normalizer=percentile_normalizer, 120 | ), 121 | ] 122 | 123 | preprocessor = Preprocessor( 124 | center_modality=center, 125 | moving_modalities=moving_modalities, 126 | # choose the registration backend you want to use 127 | # registrator=NiftyRegRegistrator(), 128 | registrator=ANTsRegistrator(), 129 | brain_extractor=HDBetExtractor(), 130 | temp_folder="temporary_directory", 131 | limit_cuda_visible_devices="0", 132 | ) 133 | 134 | preprocessor.run( 135 | save_dir_coregistration=brainles_dir + "/co-registration", 136 | save_dir_atlas_registration=brainles_dir + "/atlas-registration", 137 | save_dir_atlas_correction=brainles_dir + "/atlas-correction", 138 | save_dir_brain_extraction=brainles_dir + "/brain-extraction", 139 | save_dir_defacing=brainles_dir + "/defacing", 140 | ) 141 | 142 | 143 | ### *** GOGOGO *** ### 144 | if __name__ == "__main__": 145 | EXAMPLE_DATA_DIR = turbopath("example/example_data") 146 | 147 | exams = EXAMPLE_DATA_DIR.dirs() 148 | 149 | for exam in tqdm(exams): 150 | print("processing:", exam) 151 | preprocess(exam) 152 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning>=1.0.0,<2.0.0"] 3 | build-backend = "poetry_dynamic_versioning.backend" 4 | 5 | [tool.poetry-dynamic-versioning] 6 | enable = true 7 | 8 | [tool.poetry] 9 | exclude = [ 10 | "example", # Example data and scripts 11 | "tests", # Test files 12 | "docs", # Documentation files 13 | ".github", # GitHub workflows, actions, etc. 14 | ] 15 | 16 | name = "brainles_preprocessing" 17 | version = "0.0.0.dev" # will be overwritten by poetry-dynamic-versioning but needs to be set 18 | description = "Tool for preprocessing tasks in biomedical imaging, with a focus on (but not limited to) multi-modal brain MRI" 19 | license = "Apache-2.0" 20 | 21 | authors = [ 22 | "Florian Kofler ", 23 | "Isra Mekki ", 24 | "Marcel Rosier ", 25 | ] 26 | 27 | maintainers = [ 28 | "Florian Kofler ", 29 | "Isra Mekki ", 30 | "Marcel Rosier ", 31 | ] 32 | 33 | readme = "README.md" 34 | repository = "https://github.com/BrainLesion/preprocessing" 35 | #documentation = "" 36 | 37 | keywords = [ 38 | "brain tumor", 39 | "glioma", 40 | "BraTS", 41 | "skullstripping", 42 | "brain extraction", 43 | ] 44 | classifiers = [ 45 | "Programming Language :: Python :: 3", 46 | "Operating System :: OS Independent", 47 | ] 48 | 49 | [tool.poetry.dependencies] 50 | python = "^3.10" 51 | # core 52 | path = "^16.10.0" 53 | ttictoc = "^0.5.6" 54 | pathlib = "^1.0.1" 55 | nibabel = ">=3.2.1" 56 | numpy = "^1.23.0" 57 | typer = "^0.15.0" 58 | black = "^22.1.0" 59 | 60 | # registration 61 | antspyx = "^0.4.2" 62 | 63 | # hd-bet reqs 64 | brainles_hd_bet = ">=0.0.10" 65 | 66 | # utils 67 | tqdm = "^4.64.1" 68 | auxiliary = ">=0.0.42" 69 | rich = "^13.6.0" 70 | 71 | # optional registration backends 72 | itk-elastix = { version = "^0.20.0", optional = true } 73 | picsl_greedy = { version = "^0.0.6", optional = true } 74 | 75 | 76 | [tool.poetry.extras] 77 | all = ["itk-elastix", "picsl_greedy"] 78 | itk-elastix = ["itk-elastix"] 79 | picsl_greedy = ["picsl_greedy"] 80 | 81 | 82 | [tool.poetry.group.dev.dependencies] 83 | pytest = ">=8.1.1" 84 | 85 | [tool.poetry.group.docs] 86 | optional = true 87 | 88 | [tool.poetry.group.docs.dependencies] 89 | Sphinx = ">=7.0.0" 90 | sphinx-copybutton = ">=0.5.2" 91 | sphinx-rtd-theme = ">=1.3.0" 92 | myst-parser = ">=2.0.0" 93 | 94 | [tool.poetry.scripts] 95 | preprocessor = "brainles_preprocessing.cli:app" 96 | -------------------------------------------------------------------------------- /tests/registrator_base.py: -------------------------------------------------------------------------------- 1 | import os 2 | from abc import abstractmethod 3 | 4 | from auxiliary.turbopath import turbopath 5 | import shutil 6 | 7 | 8 | class RegistratorBase: 9 | @abstractmethod 10 | def get_registrator(self): 11 | pass 12 | 13 | @abstractmethod 14 | def get_method_and_extension(self): 15 | pass 16 | 17 | def setUp(self): 18 | self.registrator = self.get_registrator() 19 | self.method_name, self.matrix_extension = self.get_method_and_extension() 20 | 21 | test_data_dir = turbopath(__file__).parent + "/test_data" 22 | input_dir = test_data_dir + "/input" 23 | self.output_dir = test_data_dir + f"/temp_output_{self.method_name}" 24 | os.makedirs(self.output_dir, exist_ok=True) 25 | 26 | self.fixed_image = input_dir + "/tcia_example_t1c.nii.gz" 27 | self.moving_image = input_dir + "/tcia_example_t1.nii.gz" 28 | 29 | self.matrix = self.output_dir + f"/{self.method_name}_matrix" 30 | self.transform_matrix = input_dir + f"/{self.method_name}_matrix" 31 | 32 | def tearDown(self): 33 | # Clean up created files if they exist 34 | shutil.rmtree(self.output_dir) 35 | # pass 36 | 37 | def test_register_creates_output_files(self): 38 | transformed_image = ( 39 | self.output_dir + f"/{self.method_name}_registered_image.nii.gz" 40 | ) 41 | log_file = self.output_dir + f"/{self.method_name}_registration.log" 42 | 43 | self.registrator.register( 44 | fixed_image_path=self.fixed_image, 45 | moving_image_path=self.moving_image, 46 | transformed_image_path=transformed_image, 47 | matrix_path=self.matrix, 48 | log_file_path=log_file, 49 | ) 50 | 51 | self.assertTrue( 52 | os.path.exists(transformed_image), 53 | "transformed file was not created.", 54 | ) 55 | 56 | self.assertTrue( 57 | os.path.exists(f"{self.matrix}.{self.matrix_extension}"), 58 | "matrix file was not created.", 59 | ) 60 | 61 | self.assertTrue( 62 | os.path.exists(log_file), 63 | "log file was not created.", 64 | ) 65 | 66 | def test_transform_creates_output_files(self): 67 | transformed_image = ( 68 | self.output_dir + f"/{self.method_name}_transformed_image.nii.gz" 69 | ) 70 | log_file = self.output_dir + f"/{self.method_name}_transformation.log" 71 | 72 | print("tf m:", self.transform_matrix) 73 | self.registrator.transform( 74 | fixed_image_path=self.fixed_image, 75 | moving_image_path=self.moving_image, 76 | transformed_image_path=transformed_image, 77 | matrix_path=self.transform_matrix, 78 | log_file_path=log_file, 79 | ) 80 | 81 | self.assertTrue( 82 | os.path.exists(transformed_image), 83 | "transformed file was not created.", 84 | ) 85 | 86 | self.assertTrue( 87 | os.path.exists(log_file), 88 | "log file was not created.", 89 | ) 90 | -------------------------------------------------------------------------------- /tests/test_data/input/ants_matrix.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/tests/test_data/input/ants_matrix.mat -------------------------------------------------------------------------------- /tests/test_data/input/bet_tcia_example_t1c_mask.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/tests/test_data/input/bet_tcia_example_t1c_mask.nii.gz -------------------------------------------------------------------------------- /tests/test_data/input/ereg_matrix.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/tests/test_data/input/ereg_matrix.mat -------------------------------------------------------------------------------- /tests/test_data/input/niftyreg_matrix.txt: -------------------------------------------------------------------------------- 1 | 0.9888756 0.1354215 0.06153017 -1.314461 2 | -0.1397797 0.9874795 0.07311541 -1.147088 3 | -0.05085838 -0.08090271 0.9954236 2.731441 4 | 0 0 0 1 5 | -------------------------------------------------------------------------------- /tests/test_data/input/tcia_example_t1.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/tests/test_data/input/tcia_example_t1.nii.gz -------------------------------------------------------------------------------- /tests/test_data/input/tcia_example_t1c.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BrainLesion/preprocessing/960edb333f9f28d14e583f9a1ffbfaff8785b288/tests/test_data/input/tcia_example_t1c.nii.gz -------------------------------------------------------------------------------- /tests/test_hdbet_brain_extractor.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import unittest 4 | 5 | from auxiliary.turbopath import turbopath 6 | 7 | from brainles_preprocessing.brain_extraction import HDBetExtractor 8 | 9 | 10 | class TestHDBetExtractor(unittest.TestCase): 11 | def setUp(self): 12 | test_data_dir = turbopath(__file__).parent + "/test_data" 13 | input_dir = test_data_dir + "/input" 14 | self.output_dir = test_data_dir + "/temp_output_hdbet" 15 | os.makedirs(self.output_dir, exist_ok=True) 16 | 17 | self.brain_extractor = HDBetExtractor() 18 | 19 | self.input_image_path = input_dir + "/tcia_example_t1c.nii.gz" 20 | self.input_brain_mask_path = input_dir + "/bet_tcia_example_t1c_mask.nii.gz" 21 | 22 | self.masked_image_path = self.output_dir + "/bet_tcia_example_t1c.nii.gz" 23 | self.brain_mask_path = self.output_dir + "/bet_tcia_example_t1c_mask.nii.gz" 24 | self.masked_again_image_path = ( 25 | self.output_dir + "/bet_tcia_example_t1c_masked2.nii.gz" 26 | ) 27 | 28 | print(self.input_image_path) 29 | print(self.masked_image_path) 30 | 31 | def tearDown(self): 32 | # Clean up created files if they exist 33 | shutil.rmtree(self.output_dir) 34 | 35 | def test_extract_creates_output_files(self): 36 | # we try to run the fastest possible skullstripping on CPU 37 | self.brain_extractor.extract( 38 | input_image_path=self.input_image_path, 39 | masked_image_path=self.masked_image_path, 40 | brain_mask_path=self.brain_mask_path, 41 | mode="fast", 42 | device="cpu", 43 | do_tta=False, 44 | # TODO generate and also test for presence of log file 45 | ) 46 | 47 | self.assertTrue( 48 | os.path.exists(self.masked_image_path), "Masked image file was not created." 49 | ) 50 | self.assertTrue( 51 | os.path.exists(self.brain_mask_path), 52 | "Brain mask image file was not created.", 53 | ) 54 | 55 | def test_apply_mask_creates_output_file(self): 56 | self.brain_extractor.apply_mask( 57 | input_image_path=self.input_image_path, 58 | mask_path=self.input_brain_mask_path, 59 | bet_image_path=self.masked_again_image_path, 60 | ) 61 | self.assertTrue( 62 | os.path.exists(self.masked_again_image_path), 63 | "Output image file was not created in apply_mask.", 64 | ) 65 | -------------------------------------------------------------------------------- /tests/test_registrators.py: -------------------------------------------------------------------------------- 1 | from registrator_base import RegistratorBase 2 | 3 | from brainles_preprocessing.registration.ANTs.ANTs import ANTsRegistrator 4 | from brainles_preprocessing.registration.niftyreg.niftyreg import NiftyRegRegistrator 5 | from brainles_preprocessing.registration.elastix.elastix import ElastixRegistrator 6 | from brainles_preprocessing.registration.greedy.greedy import GreedyRegistrator 7 | 8 | import unittest 9 | 10 | 11 | class TestANTsRegistrator(RegistratorBase, unittest.TestCase): 12 | def get_registrator(self): 13 | return ANTsRegistrator() 14 | 15 | def get_method_and_extension(self): 16 | return "ants", "mat" 17 | 18 | 19 | class TestNiftyRegRegistrator(RegistratorBase, unittest.TestCase): 20 | def get_registrator(self): 21 | return NiftyRegRegistrator() 22 | 23 | def get_method_and_extension(self): 24 | return "niftyreg", "txt" 25 | 26 | 27 | class TestElastixRegistrator(RegistratorBase, unittest.TestCase): 28 | def get_registrator(self): 29 | return ElastixRegistrator() 30 | 31 | def get_method_and_extension(self): 32 | return "elastix", "txt" 33 | 34 | 35 | class TestGreedyRegistrator(RegistratorBase, unittest.TestCase): 36 | def get_registrator(self): 37 | return GreedyRegistrator() 38 | 39 | def get_method_and_extension(self): 40 | return "greedy", "mat" 41 | -------------------------------------------------------------------------------- /tests/test_zenodo.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import shutil 3 | import zipfile 4 | from unittest.mock import MagicMock, patch 5 | from pathlib import Path 6 | from io import BytesIO 7 | 8 | from requests import RequestException 9 | 10 | from brainles_preprocessing.utils.zenodo import ( 11 | ATLASES_FOLDER, 12 | verify_or_download_atlases, 13 | _get_latest_version_folder_name, 14 | _get_zenodo_metadata_and_archive_url, 15 | _download_atlases, 16 | _extract_archive, 17 | ) 18 | 19 | 20 | @pytest.fixture 21 | def mock_zenodo_metadata(): 22 | return {"version": "1.0.0"}, "https://fakeurl.com/archive.zip" 23 | 24 | 25 | @pytest.fixture 26 | def mock_atlases_folder(tmp_path): 27 | atlases_path = tmp_path / "atlases" 28 | atlases_path.mkdir() 29 | return atlases_path 30 | 31 | 32 | @patch("brainles_preprocessing.utils.zenodo.requests.get") 33 | def test_get_zenodo_metadata_and_archive_url(mock_get, mock_zenodo_metadata): 34 | mock_response = MagicMock() 35 | mock_response.status_code = 200 36 | mock_response.json.return_value = { 37 | "metadata": mock_zenodo_metadata[0], 38 | "links": {"archive": mock_zenodo_metadata[1]}, 39 | } 40 | mock_get.return_value = mock_response 41 | 42 | metadata, archive_url = _get_zenodo_metadata_and_archive_url() 43 | assert metadata["version"] == "1.0.0" 44 | assert archive_url == "https://fakeurl.com/archive.zip" 45 | 46 | 47 | @patch("brainles_preprocessing.utils.zenodo.requests.get") 48 | def test_get_zenodo_metadata_and_archive_url_failure(mock_get): 49 | mock_get.side_effect = RequestException() 50 | assert _get_zenodo_metadata_and_archive_url() == None 51 | 52 | 53 | @patch( 54 | "brainles_preprocessing.utils.zenodo._get_latest_version_folder_name", 55 | return_value=None, 56 | ) 57 | @patch( 58 | "brainles_preprocessing.utils.zenodo._get_zenodo_metadata_and_archive_url", 59 | return_value=None, 60 | ) 61 | @patch("brainles_preprocessing.utils.zenodo.logger.error") 62 | def test_verify_or_download_atlases_no_local_no_meta( 63 | mock_sys_exit, mock_get_meta, mock_get_latest_version 64 | ): 65 | with pytest.raises(SystemExit): 66 | verify_or_download_atlases() 67 | mock_sys_exit.assert_called_once_with( 68 | "Atlases not found locally and Zenodo could not be reached. Exiting..." 69 | ) 70 | 71 | 72 | @patch( 73 | "brainles_preprocessing.utils.zenodo._get_latest_version_folder_name", 74 | return_value=None, 75 | ) 76 | @patch("brainles_preprocessing.utils.zenodo._get_zenodo_metadata_and_archive_url") 77 | @patch("brainles_preprocessing.utils.zenodo._download_atlases") 78 | def test_verify_or_download_atlases_no_local( 79 | mock_download, mock_zenodo_meta, mock_atlases_folder 80 | ): 81 | mock_zenodo_meta.return_value = ({"version": "1.0.0"}, "https://fakeurl.com") 82 | mock_download.return_value = mock_atlases_folder / "atlases_v1.0.0" 83 | 84 | atlases_path = verify_or_download_atlases() 85 | assert atlases_path == mock_atlases_folder / "atlases_v1.0.0" 86 | 87 | 88 | @patch( 89 | "brainles_preprocessing.utils.zenodo._get_latest_version_folder_name", 90 | return_value="atlases_v1.0.0", 91 | ) 92 | @patch("brainles_preprocessing.utils.zenodo.logger.info") 93 | @patch("brainles_preprocessing.utils.zenodo._get_zenodo_metadata_and_archive_url") 94 | def test_verify_or_download_atlases_latest_local( 95 | mock_zenodo_meta, mock_logger_info, mock_atlases_folder 96 | ): 97 | mock_zenodo_meta.return_value = ({"version": "1.0.0"}, "https://fakeurl.com") 98 | 99 | atlases_path = verify_or_download_atlases() 100 | assert atlases_path == ATLASES_FOLDER / "atlases_v1.0.0" 101 | mock_logger_info.assert_called_with(f"Latest atlases (1.0.0) are already present.") 102 | 103 | 104 | @patch("brainles_preprocessing.utils.zenodo.shutil.rmtree") 105 | @patch( 106 | "brainles_preprocessing.utils.zenodo._get_latest_version_folder_name", 107 | return_value="atlases_v1.0.0", 108 | ) 109 | @patch("brainles_preprocessing.utils.zenodo.logger.info", return_value=None) 110 | @patch("brainles_preprocessing.utils.zenodo._get_zenodo_metadata_and_archive_url") 111 | @patch("brainles_preprocessing.utils.zenodo._download_atlases") 112 | def test_verify_or_download_atlases_old_local( 113 | mock_download, 114 | mock_zenodo_meta, 115 | mock_logger_info, 116 | mock_shutil_rmtree, 117 | mock_atlases_folder, 118 | ): 119 | mock_zenodo_meta.return_value = ({"version": "2.0.0"}, "https://fakeurl.com") 120 | mock_download.return_value = mock_atlases_folder / "atlases_v2.0.0" 121 | 122 | atlases_path = verify_or_download_atlases() 123 | 124 | mock_logger_info.assert_called_with( 125 | "New atlases available on Zenodo (2.0.0). Deleting old and fetching new atlases..." 126 | ) 127 | 128 | mock_shutil_rmtree.assert_called_once() 129 | 130 | assert atlases_path == mock_atlases_folder / "atlases_v2.0.0" 131 | 132 | 133 | @patch("brainles_preprocessing.utils.zenodo._extract_archive") 134 | @patch("brainles_preprocessing.utils.zenodo.requests.get") 135 | def test_download_atlases(mock_get, mock_extract_archive, mock_zenodo_metadata): 136 | mock_response = MagicMock() 137 | mock_response.status_code = 200 138 | mock_response.iter_content = lambda chunk_size: [b"data"] 139 | mock_get.return_value = mock_response 140 | 141 | atlases_path = _download_atlases(mock_zenodo_metadata[0], mock_zenodo_metadata[1]) 142 | assert atlases_path.exists() 143 | 144 | 145 | @patch("brainles_preprocessing.utils.zenodo.zipfile.ZipFile") 146 | def test_extract_archive(mock_zipfile, tmp_path): 147 | mock_response = MagicMock() 148 | mock_response.iter_content = lambda chunk_size: [b"data"] 149 | record_folder = tmp_path / "atlases_v1.0.0" 150 | record_folder.mkdir() 151 | 152 | dummy_zip = record_folder / "archive.zip" 153 | dummy_zip.touch() 154 | 155 | mock_zip = MagicMock() 156 | mock_zip.namelist.return_value = ["file1.txt", "file2.txt"] 157 | mock_zip.__enter__.return_value = mock_zip 158 | mock_zipfile.return_value = mock_zip 159 | 160 | _extract_archive(mock_response, record_folder) 161 | 162 | mock_zip.extract.assert_called() 163 | --------------------------------------------------------------------------------