├── .coveragerc ├── .flake8 ├── .gitattributes ├── .gitignore ├── .pre-commit-config.yaml ├── CMakeLists.txt ├── LICENCE.CeCILL.txt ├── LICENCE.GPLv3.txt ├── README.rst ├── bin ├── ylDistmaps ├── ylFixCortexTopology ├── ylGetExchangedPropvol ├── ylPostProcessEquivolumetricDepth ├── ylRandomizeLabels ├── ylRelabel └── ylRelabelConjunction ├── brainvisa └── toolboxes │ └── highres_cortex │ ├── highres_cortex.png │ ├── highres_cortex.py │ └── processes │ ├── category_documentation.minf │ ├── isovolume.procdoc │ ├── isovolume.py │ ├── laplacian.procdoc │ ├── laplacian.py │ ├── thickness_adv.procdoc │ ├── thickness_adv.py │ ├── thickness_upw.procdoc │ ├── thickness_upw.py │ ├── traverses.procdoc │ └── traverses.py ├── doc ├── .gitignore ├── references.bib └── test-references.tex ├── examples └── scripts │ ├── column-regions │ └── column-regions.sh │ ├── dist │ └── distmaps.sh │ ├── heat │ └── heat.sh │ ├── isovolume │ └── isovolume.sh │ ├── laplace-euclidean │ └── laplace-euclidean.sh │ └── upwind-euclidean │ └── upwind-euclidean.sh ├── project_info.cmake ├── python └── highres_cortex │ ├── __init__.py │ ├── capsul │ ├── __init__.py │ ├── filtered_sumcurvs.xml │ ├── isovolume.xml │ ├── processes.py │ ├── thickness_adv.xml │ ├── thickness_upw.xml │ └── traverses.xml │ ├── cortex_topo.py │ ├── scripts │ ├── __init__.py │ ├── distmaps.py │ ├── fix_cortex_topology.py │ ├── get_exchanged_propvol.py │ ├── postprocess_equivolumetric_depth.py │ ├── randomize_labels.py │ ├── relabel.py │ └── relabel_conjunction.py │ └── test │ ├── __init__.py │ ├── compare_with_reference.py │ ├── synthetic_data.py │ └── test_capsul.py ├── soma-env └── soma-env-recipe.yaml ├── src ├── CMakeLists.txt ├── commands │ ├── CMakeLists.txt │ ├── ylAdvectEuclidean.cc │ ├── ylAdvectPath.cc │ ├── ylAdvectTubes.cc │ ├── ylAdvectValues.cc │ ├── ylIsoCurvature.cc │ ├── ylLabelEachVoxel.cc │ ├── ylLaplacian.cc │ ├── ylMakeTraversePseudoAreaMap.cc │ ├── ylMergeCortexColumnRegions.cc │ ├── ylPropagateAlongField.cc │ └── ylUpwindDistance.cc └── library │ ├── CMakeLists.txt │ ├── advection.cc │ ├── advection.hh │ ├── advection.tcc │ ├── cortex.hh │ ├── cortex_advection.cc │ ├── cortex_advection.hh │ ├── cortex_column_region_quality.cc │ ├── cortex_column_region_quality.hh │ ├── cortex_column_region_quality.tcc │ ├── field.cc │ ├── field.hh │ ├── front.cc │ ├── front.hh │ ├── iterative_region_merger.cc │ ├── iterative_region_merger.hh │ ├── iterative_region_merger.tcc │ ├── label_volume.cc │ ├── label_volume.hh │ ├── label_volume.tcc │ ├── laplace_solver.cc │ ├── laplace_solver.hh │ ├── laplace_solver.tcc │ ├── propagate_along_field.cc │ ├── propagate_along_field.hh │ ├── propagate_along_field.tcc │ ├── upwinding.cc │ ├── upwinding.hh │ ├── volume_util.cc │ ├── volume_util.hh │ └── volume_util.tcc └── tests ├── CMakeLists.txt ├── bootstrap-docker ├── .gitignore ├── casa-dev:ubuntu-12.04 │ ├── Dockerfile │ └── prepare.sh ├── ubuntu14.04 │ ├── Dockerfile │ └── prepare.sh └── ubuntu16.04 │ ├── Dockerfile │ └── prepare.sh ├── precision ├── cbs-post.sh ├── cbs-pre.sh └── evaluate.LayoutXML.in ├── run_all_scripts.sh ├── test_all_scripts.sh └── test_env.sh.in /.coveragerc: -------------------------------------------------------------------------------- 1 | # .coveragerc to control coverage.py -*- mode: conf-unix; -*- 2 | 3 | [run] 4 | branch = True 5 | omit = python/highres_cortex/test/* 6 | 7 | [report] 8 | # Regexes for lines to exclude from consideration 9 | exclude_lines = 10 | # Have to re-enable the standard pragma 11 | pragma: no cover 12 | 13 | # Don't complain about missing debug-only code: 14 | def __repr__ 15 | if self\.debug 16 | 17 | # Don't complain if tests don't hit defensive assertion code: 18 | raise AssertionError 19 | raise NotImplementedError 20 | 21 | # Don't complain if non-runnable code isn't run: 22 | if 0: 23 | if __name__ == .__main__.: 24 | 25 | [html] 26 | directory = python_coverage_report 27 | 28 | [xml] 29 | output = python_coverage.xml 30 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = 3 | # E203 (whitespace before ':') has false positive for array slicings 4 | E203, 5 | # these are on the default ignore list 6 | E121, E126, E226, E133, E203, E241, 7 | # We want line-break *before* the operator (new PEP8 style similar to math) 8 | W503, 9 | # Gives false positives when a name contains an uppercase acronym 10 | N802 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * whitespace="trailing-space,tab-in-indent" 2 | 3 | *.cc text diff=cpp 4 | *.hh text diff=cpp 5 | *.tcc text diff=cpp 6 | *.py text diff=python 7 | *.sh eol=lf 8 | *.cmake text 9 | *.tex text diff=tex 10 | *.bib text diff=bibtex 11 | *.txt text 12 | *.rst text 13 | *.xml text 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # CMake build files 2 | /CMakeCache.txt 3 | /Testing/ 4 | CMakeFiles/ 5 | Makefile 6 | cmake_install.cmake 7 | install_manifest.txt 8 | 9 | # brainvisa-cmake files 10 | /CMakeDoxyfile.in 11 | /CMakeDoxygenDefaults.cmake 12 | /DartConfiguration.tcl 13 | /include/ 14 | /lib/ 15 | /python/brainvisa/compilation_info.py 16 | /src/library/Doxyfile 17 | /CPackConfig.cmake 18 | /CPackSourceConfig.cmake 19 | CTestTestfile.cmake 20 | 21 | # generated files 22 | /bin/ylAdvectEuclidean 23 | /bin/ylAdvectPath 24 | /bin/ylAdvectTubes 25 | /bin/ylAdvectValues 26 | /bin/ylIsoCurvature 27 | /bin/ylLabelEachVoxel 28 | /bin/ylLaplacian 29 | /bin/ylMakeTraversePseudoAreaMap 30 | /bin/ylMergeCortexColumnRegions 31 | /bin/ylPropagateAlongField 32 | /bin/ylUpwindDistance 33 | /tests/test_env.sh 34 | 35 | # Python 36 | __pycache__/ 37 | *.py[cod] 38 | 39 | # pytest 40 | .cache/ 41 | .coverage 42 | coverage.xml 43 | python_coverage_html_report/ 44 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: meta 3 | hooks: 4 | - id: check-useless-excludes 5 | 6 | - repo: https://github.com/pre-commit/pre-commit-hooks 7 | rev: v4.1.0 8 | hooks: 9 | - id: check-added-large-files 10 | - id: check-case-conflict 11 | - id: check-executables-have-shebangs 12 | - id: check-json 13 | - id: check-merge-conflict 14 | exclude_types: [rst] 15 | - id: check-shebang-scripts-are-executable 16 | exclude: \.in$ 17 | - id: check-symlinks 18 | - id: check-xml 19 | files: \.procdoc$ 20 | types: [file] 21 | - id: check-yaml 22 | - id: debug-statements 23 | - id: destroyed-symlinks 24 | - id: end-of-file-fixer 25 | - id: fix-byte-order-marker 26 | - id: fix-encoding-pragma 27 | - id: trailing-whitespace 28 | 29 | - repo: https://github.com/pycqa/flake8 30 | rev: 3.9.2 31 | hooks: 32 | - id: flake8 33 | name: flake8 under python3 34 | language_version: python3 35 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright Forschungszentrum Jülich GmbH (2016, 2017, 2018). 2 | # Copyright Télécom ParisTech (2015). 3 | # Copyright CEA (2014). 4 | # Copyright Université Paris XI (2014). 5 | # 6 | # Contributor: Yann Leprince . 7 | # 8 | # Copying and distribution of this file, with or without modification, 9 | # are permitted in any medium without royalty provided the copyright 10 | # notice and this notice are preserved. This file is offered as-is, 11 | # without any warranty. 12 | 13 | cmake_minimum_required(VERSION 3.10) 14 | find_package(brainvisa-cmake REQUIRED) 15 | BRAINVISA_PROJECT(CXX) 16 | 17 | option(BUILD_SHARED_LIBS "Build highres-cortex as a shared library" ON) 18 | 19 | # The AIMS version-file checks for strict equality of major and minor version 20 | # numbers, so requesting version 4.5 explicitly in the find_package command 21 | # will reject versions 4.6 and later, which we do not want. 22 | BRAINVISA_FIND_PACKAGE(aims-free REQUIRED) 23 | if("${aims-free_VERSION}" VERSION_LESS 4.5) 24 | message(FATAL_ERROR "Required dependency aims-free should be at least version 4.5") 25 | endif() 26 | include("${AIMS-FREE_USE_FILE}") 27 | BRAINVISA_DEPENDENCY(DEV DEPENDS aims-free DEV ">= 4.5") 28 | BRAINVISA_DEPENDENCY(RUN DEPENDS aims-free RUN ">= ${aims-free_VERSION}") 29 | 30 | BRAINVISA_DEPENDENCY(RUN DEPENDS "capsul" RUN ">= 2.0") 31 | 32 | 33 | if( NOT Boost_FOUND ) 34 | # if Boost has already been detected (from another project within 35 | # brainvisa-cmake), then we must not change Boost_NO_BOOST_CMAKE nor 36 | # Boost_ADDITIONAL_VERSIONS, otherwise it will reset paths already setup 37 | # in the cache (event manually). 38 | 39 | # Do not use BoostConfig.cmake from boost-cmake, because its behaviour may 40 | # be different from regular FindBoost.cmake. 41 | set(Boost_NO_BOOST_CMAKE ON) 42 | # All suitable Boost versions should be included here, if they are not 43 | # already contained in the FindBoost.cmake module provided with CMake. 44 | # Hence, new versions should be added here as they are released... 45 | set(Boost_ADDITIONAL_VERSIONS 46 | "1.75.0" "1.75" "1.74.0" "1.74" "1.73.0" "1.73" "1.72.0" "1.72" 47 | "1.71.0" "1.71" "1.70.0" "1.70" "1.69.0" "1.69" "1.68.0" "1.68" 48 | "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65" 49 | "1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" 50 | "1.60.0" "1.60" "1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" 51 | "1.56.0" "1.56" "1.55.0" "1.55" "1.54.0" "1.54" "1.53.0" "1.53" 52 | "1.52.0" "1.52" "1.51.0" "1.51" "1.50.0" "1.50" "1.49.0" "1.49") 53 | find_package(Boost 1.49 REQUIRED) 54 | endif() 55 | # The version of Boost is not checked by find_package if it is in the cache. 56 | if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.49) 57 | message(FATAL_ERROR 58 | "Unsuitable Boost version ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}." 59 | "${Boost_SUBMINOR_VERSION} is already in the CMake cache. " 60 | "Please set the BOOST_ROOT variable to a directory containing " 61 | "Boost 1.49 or newer (under BOOST_ROOT/include).") 62 | endif() 63 | BRAINVISA_DEPENDENCY(DEV DEPENDS libboost DEV ">= 1.49") 64 | # No run-time dependency as we use header-only Boost libraries 65 | 66 | 67 | # OpenMP is optional 68 | find_package(OpenMP) 69 | if(OPENMP_FOUND) 70 | BRAINVISA_DEPENDENCY(RUN DEPENDS openmp RUN) 71 | endif() 72 | 73 | find_package(Doxygen) 74 | 75 | find_package(python REQUIRED) 76 | BRAINVISA_DEPENDENCY(DEV DEPENDS python DEV ">= 2.7") 77 | BRAINVISA_DEPENDENCY(RUN RECOMMENDS python RUN ">= 2.7") 78 | # No need for find_package(NumPy) as that is for C headers 79 | BRAINVISA_DEPENDENCY(RUN RECOMMENDS python-numpy RUN) 80 | 81 | # For fix_cortex_topology 82 | BRAINVISA_DEPENDENCY(RUN SUGGESTS morphologist-nonfree RUN ">= 4.5") 83 | 84 | 85 | BRAINVISA_COPY_PYTHON_DIRECTORY("${CMAKE_CURRENT_SOURCE_DIR}/python" 86 | ${PROJECT_NAME}) 87 | BRAINVISA_COPY_PYTHON_DIRECTORY("${CMAKE_CURRENT_SOURCE_DIR}/brainvisa" 88 | ${PROJECT_NAME}) 89 | 90 | BRAINVISA_COPY_DIRECTORY("${CMAKE_CURRENT_SOURCE_DIR}/bin" 91 | bin 92 | ${PROJECT_NAME}) 93 | 94 | 95 | set(REL_SHARE_DIR "share/${PROJECT_NAME}-${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}") 96 | 97 | # FIXME: These scripts are documentation, but tests depend on it. How can I 98 | # make sure that they are installed by both 'install-test' and 'install-doc'? 99 | brainvisa_copy_directory( 100 | "${CMAKE_CURRENT_SOURCE_DIR}/examples" 101 | "${REL_SHARE_DIR}/examples" 102 | ${PROJECT_NAME}-test 103 | ) 104 | 105 | # don't warn on obsolete classes within this library: we still provide obsolete 106 | # features so we have to build them without warnings 107 | add_definitions( "-DAIMSDATA_CLASS_NO_DEPREC_WARNING=1" ) 108 | 109 | add_subdirectory(src) 110 | 111 | include(CTest) 112 | if(BUILD_TESTING) 113 | add_subdirectory(tests) 114 | endif() 115 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | highres-cortex 3 | ================ 4 | 5 | This is a collection of software designed to process 3D images of the cerebral cortex at a sub-millimetre scale, for example high-resolution MRI. In particular, it implements Bok’s equivolumetric depth, which models the depth of cortical layers while compensating for local cortical curvature. If you use this work in an academic publication, **please cite** the relevant references (see also ``_): 6 | 7 | - Yann Leprince, Fabrice Poupon, Thierry Delzescaux, Dominique Hasboun, Cyril Poupon, and Denis Rivière. *Combined Laplacian-equivolumic model for studying cortical lamination with ultra high field MRI (7 T)*. 2015 IEEE 12th International Symposium on Biomedical Imaging (ISBI), IEEE, Apr 2015, New York, United States. pp.580-583, DOI: `10.1109/ISBI.2015.7163940 `_. https://hal-cea.archives-ouvertes.fr/cea-01119475 8 | 9 | - Yann Leprince, Clara Fischer, Jean-François Mangin, Benoît Larrat, Sébastien Mériaux, Cyril Poupon, Isabel Reillo, Victor Borrell, Ophélie Foubet, Roberto Toro, and Denis Rivière. *Architectonics-informed partition of the cortex at sub-millimetre resolution*. 20th Annual Meeting of the Organization for Human Brain Mapping (OHBM), Jun 2014, Hamburg, Germany. 5, pp.951, 2014, F1000Posters. https://hal-cea.archives-ouvertes.fr/cea-01074735 10 | 11 | 12 | 13 | Installation 14 | ============ 15 | 16 | highres-cortex is released as part of the official BrainVISA containers since March 2021 (BrainVISA 5.0.0). Please refer to https://brainvisa.info/web/download.html for installation instructions. 17 | 18 | 19 | Graphical user interface 20 | ======================== 21 | 22 | highres-cortex is available as a minimalistic BrainVISA toolbox since BrainVISA 23 | 5.1 (January 2023). Simply launch `brainvisa` and refer to the in-program documentation of the toolbox. 24 | 25 | 26 | Command-line usage 27 | ================== 28 | 29 | This package can be used on the command line, here is a short introduction. It is assumed that you are running the Singularity version on a Linux computer, it should work in the same way in the virtual machine (you just need to remove the `bv` prefix from all commands). 30 | 31 | 1. Prepare your input data: the input that is common to to all processes is ``classif``: a voxel-wise tissue classification image in signed 16-bit pixel type, with 0 for exterior voxels (CSF), 100 for cortical gray matter, and 200 for subcortical white matter. 32 | 33 | 2. Run the process that you are interested in. The common interface to all processes is the `Capsul`_ command-line, which you can call with ``bv python -m capsul``. Use ``bv python -m capsul --process-help `` to get help for a specific process. Use ``bv python -m capsul [parameter=value ...]`` to run a process. 34 | 35 | The most important processes are described below: 36 | 37 | - Equivolumetric depth according to Bok’s model can be computed with ``highres_cortex.capsul.isovolume``. The only mandatory input is ``classif``, the output is ``equivolumetric_depth``. You can fine-tune the process with optional parameters, most importantly ``advection_step_size`` can be adapted to the spatial resolution and required accuracy. For example:: 38 | 39 | bv python -m capsul highres_cortex.capsul.isovolume classif=classif.nii.gz advection_step_size=0.03 equivolumetric_depth=equivolumetric_depth.nii.gz 40 | 41 | - Cortical thickness, according to the Laplace model, can be calculated with two different methods: 42 | 43 | - The upwinding method is very fast, and already has sub-pixel accurracy: ``highres_cortex.capsul.thickness_upw``. The only mandatory input is ``classif``, the output is ``thickness_image``. 44 | 45 | - The advection method is slower, but ``advection_step_size`` can be tuned for greater accuracy: ``highres_cortex.capsul.thickness_adv``. 46 | 47 | - For parcellating the cortex into volumetric traverses, ``highres_cortex.capsul.traverses`` can be used. The only mandatory input is ``classif``, the output is ``cortical_traverses``. The ``goal_diameter`` parameter controls the target diameter of merged regions (in millimetres). The ``advection_step_size`` parameter is also relevant for this process. 48 | 49 | If you have used highres-cortex before the Capsul interface was introduced (beginning of 2018), you may be using the old shell scripts. See ``_ for equivalent scripts that make use of the Capsul processes. 50 | 51 | 52 | Contributing 53 | ============ 54 | 55 | This repository uses `pre-commit`_ to ensure that all committed code follows minimal quality standards. Please install it and configure it to run as a pre-commit hook in your local repository (note that this is done automatically by ``bv_maker``): 56 | 57 | .. code-block:: shell 58 | 59 | # Install pre-commit in a virtual environment 60 | python3 -m venv venv/ 61 | . venv/bin/activate 62 | pip install pre-commit 63 | 64 | pre-commit install # install the pre-commit hook 65 | 66 | 67 | Licence 68 | ======= 69 | 70 | The source code of this work is placed under the CeCILL licence (see ``_). This library contains code that is under the GNU LGPL licence (see ``_), as a result, compiled code must be redistributed under the GNU General Public Licence (see ``_). 71 | 72 | External code used in this repository 73 | ------------------------------------- 74 | 75 | - Code for numerical diagonalization of 3×3 matrices (``_) is Copyright 2006 Joachim Kopp, under the GNU LGPL v2.1 or later. Reference: Kopp, Joachim. ‘Efficient Numerical Diagonalization of Hermitian 3x3 Matrices’. *International Journal of Modern Physics C* 19, no. 03 (March 2008): 523–48. `arXiv:physics/0610206 `_. 76 | 77 | 78 | .. _BrainVISA: https://brainvisa.info/ 79 | .. _Capsul: https://brainvisa.info/capsul/ 80 | .. _pre-commit: https://pre-commit.com/ 81 | .. _BrainVISA download page: https://brainvisa.info/web/download.html 82 | 83 | .. Copyright CEA (2014, 2015, 2021, 2022). 84 | Copyright Forschungszentrum Jülich GmbH (2016, 2017, 2018). 85 | Copyright Télécom ParisTech (2015, 2016). 86 | Copyright Université Paris XI (2014). 87 | 88 | Author: Yann Leprince . 89 | 90 | Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty. 91 | -------------------------------------------------------------------------------- /bin/ylDistmaps: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | from highres_cortex.scripts.distmaps import main 6 | 7 | if __name__ == "__main__": 8 | sys.exit(main()) 9 | -------------------------------------------------------------------------------- /bin/ylFixCortexTopology: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | from highres_cortex.scripts.fix_cortex_topology import main 6 | 7 | if __name__ == "__main__": 8 | sys.exit(main()) 9 | -------------------------------------------------------------------------------- /bin/ylGetExchangedPropvol: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | from highres_cortex.scripts.get_exchanged_propvol import main 6 | 7 | if __name__ == "__main__": 8 | sys.exit(main()) 9 | -------------------------------------------------------------------------------- /bin/ylPostProcessEquivolumetricDepth: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | from highres_cortex.scripts.postprocess_equivolumetric_depth import main 6 | 7 | if __name__ == "__main__": 8 | sys.exit(main()) 9 | -------------------------------------------------------------------------------- /bin/ylRandomizeLabels: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | from highres_cortex.scripts.randomize_labels import main 6 | 7 | if __name__ == "__main__": 8 | sys.exit(main()) 9 | -------------------------------------------------------------------------------- /bin/ylRelabel: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | from highres_cortex.scripts.relabel import main 6 | 7 | if __name__ == "__main__": 8 | sys.exit(main()) 9 | -------------------------------------------------------------------------------- /bin/ylRelabelConjunction: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | from highres_cortex.scripts.relabel_conjunction import main 6 | 7 | if __name__ == "__main__": 8 | sys.exit(main()) 9 | -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/highres_cortex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neurospin/highres-cortex/a2d6a7d2b0b1d07a3a3333d7826a6f607024d5aa/brainvisa/toolboxes/highres_cortex/highres_cortex.png -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/highres_cortex.py: -------------------------------------------------------------------------------- 1 | userName = "highres-cortex" 2 | icon = "highres_cortex.png" 3 | description = "Analysis tools for sub-millimetre MRI of the cerebral cortex" 4 | -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/processes/category_documentation.minf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

highres-cortex toolbox

6 | 7 |

This is a collection of software designed to process 3D images of the cerebral cortex at a sub-millimetre scale, for example high-resolution MRI. In particular, it implements Bok’s equivolumetric depth, which models the depth of cortical layers while compensating for local cortical curvature.

8 | 9 |

Basic usage

10 | 11 |
    12 |
  1. Prepare your input data: the input that is common to to all processes is classif: a voxel-wise tissue classification image in signed 16-bit pixel type, with 0 for exterior voxels (CSF), 100 for cortical gray matter, and 200 for subcortical white matter.

  2. 13 |
  3. The most important processes are described below:

    14 |
      15 |
    • Equivolumetric depth according to Bok’s model can be computed with (highres_cortex.capsul.isovolume).

    • 16 |
    • Cortical thickness, according to the Laplace model, can be calculated with two different methods:

      17 |
        18 |
      • The upwinding method is very fast, and already has sub-pixel accurracy: (highres_cortex.capsul.thickness_upw).
      • 19 |
      • The advection method is slower, but advection_step_size can be tuned for greater accuracy: (highres_cortex.capsul.thickness_adv).
      • 20 |
    • 21 |
    • For parcellating the cortex into volumetric traverses, (highres_cortex.capsul.traverses) can be used.

    • 22 |
  4. 23 |
24 | 25 |

Technical note

26 |

The BrainVISA processes in highres-cortex are a bit different from other toolboxes, because they are implemented as Capsul processes, which are merely exposed in BrainVISA for convenience, but only support a limited subset of features. For example, they do not support BrainVISA databases, so you should not use the green or red database buttons for choosing files (use the file browser, or directly input the file names instead). Also, running these process always happens in a soma-workflow interface.

27 |

You can call these processes from the command-line with bv python -m capsul; use bv python -m capsul --process-help <process_name> to get help for a specific process. For example: 28 |

bv python -m capsul highres_cortex.capsul.isovolume classif=classif.nii.gz advection_step_size=0.03 equivolumetric_depth=equivolumetric_depth.nii.gz

29 |
30 | 31 |
32 | -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/processes/isovolume.procdoc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Compute Bok’s equivolumetric depth, which models the depth of cortical layers while compensating for local cortical curvature.

6 |

The only mandatory input is classif, the output is equivolumetric_depth. You can fine-tune the process with optional parameters, most importantly advection_step_size can be adapted to the spatial resolution and required accuracy.

7 | 8 |

For a full description of this method, see this poster:

9 |

Yann Leprince, Fabrice Poupon, Thierry Delzescaux, Dominique Hasboun, Cyril Poupon, Denis Rivière. Combined Laplacian-equivolumic model for studying cortical lamination with ultra high field MRI (7 T). 2015 IEEE 12th International Symposium on Biomedical Imaging (ISBI), IEEE, Apr 2015, New York, United States. pp.580-583, DOI: 10.1109/ISBI.2015.7163940. https://hal-cea.archives-ouvertes.fr/cea-01119475 10 |

11 | 12 |

classification image of the cortex (100 inside, 0 in CSF, 200 in white matter)

13 |
14 |

Verbosity level

15 |
16 |

target maximum relative error in first-order finite differences

17 |
18 |

typical thickness of the cortex (mm), used for accelerating convergence

19 |
20 |

X standard deviation of the gaussian filter [default=largest voxel size]

21 |
22 |

size of the advection step (millimetres)

23 |
24 |

maximum advection distance (millimetres)

25 |
26 |

output image

27 |
28 |
29 |
30 |
31 |
32 | -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/processes/isovolume.py: -------------------------------------------------------------------------------- 1 | from brainvisa.processes import * 2 | from brainvisa.processing import capsul_process 3 | 4 | name = "Compute equivolumetric depth" 5 | userLevel = 0 6 | 7 | base_class = capsul_process.CapsulProcess 8 | capsul_process = "highres_cortex.capsul.isovolume" 9 | -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/processes/laplacian.procdoc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Solve the Laplacian model in the cortex

6 |
7 | 8 | 9 |

classification image of the cortex (100 inside, 0 in CSF, 200 in white matter)

10 |
11 |

output pseudo-temperature field (from 0 in CSF to 1 in the white matter)

12 |
13 |

target maximum relative error in first-order finite differences

14 |
15 |

typical thickness of the cortex (mm), used for accelerating convergence

16 |
17 |

Verbosity level

18 |
19 |
20 |
21 |
22 |
23 | -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/processes/laplacian.py: -------------------------------------------------------------------------------- 1 | from brainvisa.processes import * 2 | from brainvisa.processing import capsul_process 3 | 4 | name = "Solve Laplacian model" 5 | userLevel = 0 6 | 7 | base_class = capsul_process.CapsulProcess 8 | capsul_process = "highres_cortex.capsul.processes.Laplacian" 9 | -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/processes/thickness_adv.procdoc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Compute the cortical thickness along Laplace field lines from a classification volume, using Eulerian advection (slightly more precise than upwinding, but much slower)

6 | 7 | 8 |

classification image of the cortex (100 inside, 0 in CSF, 200 in white matter)

9 |
10 |

Verbosity level

11 |
12 |

target maximum relative error in first-order finite differences

13 |
14 |

typical thickness of the cortex (mm), used for accelerating convergence

15 |
16 |

size of the advection step (millimetres)

17 |
18 |

maximum advection distance (millimetres)

19 |
20 |

result of the arithmetic

21 |
22 |
23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/processes/thickness_adv.py: -------------------------------------------------------------------------------- 1 | from brainvisa.processes import * 2 | from brainvisa.processing import capsul_process 3 | 4 | name = "Cortical thickness (advection)" 5 | userLevel = 1 6 | 7 | base_class = capsul_process.CapsulProcess 8 | capsul_process = "highres_cortex.capsul.thickness_adv" 9 | -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/processes/thickness_upw.procdoc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Compute the cortical thickness along Laplace field lines from a classification volume, using upwinding (much faster than advection, but slightly less precise)

6 |

The only mandatory input is classif, the output is thickness_image.

7 | 8 |

classification image of the cortex (100 inside, 0 in CSF, 200 in white matter)

9 |
10 |

Verbosity level

11 |
12 |

target maximum relative error in first-order finite differences

13 |
14 |

typical thickness of the cortex (mm), used for accelerating convergence

15 |
16 |

result of the arithmetic

17 |
18 |
19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/processes/thickness_upw.py: -------------------------------------------------------------------------------- 1 | from brainvisa.processes import * 2 | from brainvisa.processing import capsul_process 3 | 4 | name = "Cortical thickness" 5 | userLevel = 0 6 | 7 | base_class = capsul_process.CapsulProcess 8 | capsul_process = "highres_cortex.capsul.thickness_upw" 9 | -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/processes/traverses.procdoc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Create cortical traverses

6 |
7 |

The only mandatory input is classif, the output is cortical_traverses. The goal_diameter parameter controls the target diameter of merged regions (in millimetres). The advection_step_size parameter is also relevant for this process.

8 | 9 |

For a full description of this method, see this poster:

10 |

11 | Yann Leprince, Clara Fischer, Jean-François Mangin, Benoît Larrat, Sébastien Mériaux, Cyril Poupon, Isabel Reillo, Victor Borrell, Ophélie Foubet, Roberto Toro, and Denis Rivière. Architectonics-informed partition of the cortex at sub-millimetre resolution. 20th Annual Meeting of the Organization for Human Brain Mapping (OHBM), Jun 2014, Hamburg, Germany. 5, pp.951, 2014, F1000Posters. https://hal-cea.archives-ouvertes.fr/cea-01074735 12 |

13 | 14 |

classification image of the cortex (100 inside, 0 in CSF, 200 in white matter)

15 |
16 |

Verbosity level

17 |
18 |

target maximum relative error in first-order finite differences

19 |
20 |

typical thickness of the cortex (mm), used for accelerating convergence

21 |
22 |

size of the advection step (millimetres)

23 |
24 |

goal region diameter (millimetres)

25 |
26 |

output label image

27 |
28 |
29 |
30 |
31 |
32 | -------------------------------------------------------------------------------- /brainvisa/toolboxes/highres_cortex/processes/traverses.py: -------------------------------------------------------------------------------- 1 | from brainvisa.processes import * 2 | from brainvisa.processing import capsul_process 3 | 4 | name = "Generate cortical traverses" 5 | userLevel = 0 6 | 7 | base_class = capsul_process.CapsulProcess 8 | capsul_process = "highres_cortex.capsul.traverses" 9 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | test-references.aux 2 | test-references.bbl 3 | test-references.blg 4 | test-references.fdb_latexmk 5 | test-references.fls 6 | test-references.log 7 | test-references.pdf 8 | -------------------------------------------------------------------------------- /doc/references.bib: -------------------------------------------------------------------------------- 1 | % -*- mode: bibtex; coding: us-ascii; -*- 2 | 3 | @InProceedings{leprince14_isbi, 4 | author = {Yann Leprince and Fabrice Poupon and Thierry Delzescaux and 5 | Dominique Hasboun and Cyril Poupon and Denis Rivi{\`e}re}, 6 | title = {Combined {L}aplacian-equivolumic model for studying cortical 7 | lamination with ultra high field {MRI} (7\,{T})}, 8 | year = 2015, 9 | booktitle = {IEEE International Symposium on Biomedical Imaging (ISBI)}, 10 | organization = {IEEE}, 11 | address = {New York, United States}, 12 | month = apr, 13 | url = {https://hal-cea.archives-ouvertes.fr/cea-01119475}, 14 | } 15 | 16 | @InProceedings{leprince14_ohbm_poster, 17 | author = {Leprince, Yann and Fischer, Clara and Mangin, Jean-Fran{\c 18 | c}ois and Larrat, Beno{\^i}t and M{\'e}riaux, S{\'e}bastien 19 | and Poupon, Cyril and Reillo, Isabel and Borrell, Victor and 20 | Foubet, Oph{\'e}lie and Toro, Roberto and Rivi{\`e}re, Denis}, 21 | title = {Architectonics-informed partition of the cortex at 22 | sub-millimetre resolution}, 23 | booktitle = {20th Annual Meeting of the Organization for Human Brain 24 | Mapping (OHBM)}, 25 | year = 2014, 26 | month = jun, 27 | address = {Hamburg, Germany}, 28 | url = {https://hal-cea.archives-ouvertes.fr/cea-01074735}, 29 | note = {hal-cea.archives-ouvertes.fr/cea-01074735}, 30 | } 31 | 32 | @PhdThesis{leprince15_phdthesis, 33 | author = {Yann Leprince}, 34 | title = {Imagerie des couches corticales par r{\'e}sonance 35 | magn{\'e}tique {\`a} 7~teslas}, 36 | school = {Universit{\'e} Paris-Sud}, 37 | year = 2015, 38 | url = {http://www.theses.fr/2015PA112022}, 39 | month = feb, 40 | } 41 | 42 | @Misc{highres-cortex, 43 | author = {Yann Leprince and others}, 44 | title = {{highres-cortex}: analysis tools for high resolution cortical 45 | {MRI}}, 46 | url = {https://github.com/neurospin/highres-cortex}, 47 | howpublished = {github.com/neurospin/highres-cortex}, 48 | year = 2014, 49 | } 50 | 51 | Local Variables: 52 | bibtex-field-delimiters: braces 53 | bibtex-align-at-equal-sign: t 54 | End: 55 | -------------------------------------------------------------------------------- /doc/test-references.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \begin{document} 3 | \nocite{*} 4 | \bibliographystyle{plain} 5 | \bibliography{references} 6 | \end{document} 7 | -------------------------------------------------------------------------------- /examples/scripts/column-regions/column-regions.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | # 3 | # Copyright Forschungszentrum Jülich GmbH (2018). 4 | # 5 | # Contributor: Yann Leprince . 6 | # 7 | # Copying and distribution of this file, with or without modification, 8 | # are permitted in any medium without royalty provided the copyright 9 | # notice and this notice are preserved. This file is offered as-is, 10 | # without any warranty. 11 | 12 | python -m capsul highres_cortex.capsul.traverses \ 13 | classif=../classif.nii.gz \ 14 | goal_traverse_diameter=1.0 \ 15 | verbosity=1 \ 16 | advection_step_size=0.05 \ 17 | cortical_traverses=merged_randomized.nii.gz 18 | -------------------------------------------------------------------------------- /examples/scripts/dist/distmaps.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | # 3 | # Copyright Forschungszentrum Jülich GmbH (2018). 4 | # Copyright CEA (2014). 5 | # Copyright Université Paris XI (2014). 6 | # 7 | # Contributor: Yann Leprince . 8 | # 9 | # Copying and distribution of this file, with or without modification, 10 | # are permitted in any medium without royalty provided the copyright 11 | # notice and this notice are preserved. This file is offered as-is, 12 | # without any warranty. 13 | 14 | python -m capsul highres_cortex.capsul.processes.Distmaps \ 15 | classif=../classif.nii.gz \ 16 | distwhite=distwhite.nii.gz \ 17 | distCSF=distCSF.nii.gz \ 18 | classif_with_outer_boundaries=../classif_with_outer_boundaries.nii.gz 19 | -------------------------------------------------------------------------------- /examples/scripts/heat/heat.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | # 3 | # Copyright Forschungszentrum Jülich GmbH (2018). 4 | # 5 | # Contributor: Yann Leprince . 6 | # 7 | # Copying and distribution of this file, with or without modification, 8 | # are permitted in any medium without royalty provided the copyright 9 | # notice and this notice are preserved. This file is offered as-is, 10 | # without any warranty. 11 | 12 | python -m capsul highres_cortex.capsul.processes.Laplacian \ 13 | classif=../classif.nii.gz \ 14 | verbosity=1 \ 15 | laplace_field=heat.nii.gz 16 | -------------------------------------------------------------------------------- /examples/scripts/isovolume/isovolume.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | # 3 | # Copyright Forschungszentrum Jülich GmbH (2018). 4 | # 5 | # Contributor: Yann Leprince . 6 | # 7 | # Copying and distribution of this file, with or without modification, 8 | # are permitted in any medium without royalty provided the copyright 9 | # notice and this notice are preserved. This file is offered as-is, 10 | # without any warranty. 11 | 12 | python -m capsul highres_cortex.capsul.isovolume \ 13 | classif=../classif.nii.gz \ 14 | verbosity=1 \ 15 | advection_step_size=0.05 \ 16 | equivolumetric_depth=equivolumic_depth.nii.gz 17 | -------------------------------------------------------------------------------- /examples/scripts/laplace-euclidean/laplace-euclidean.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | # 3 | # Copyright Forschungszentrum Jülich GmbH (2018). 4 | # 5 | # Contributor: Yann Leprince . 6 | # 7 | # Copying and distribution of this file, with or without modification, 8 | # are permitted in any medium without royalty provided the copyright 9 | # notice and this notice are preserved. This file is offered as-is, 10 | # without any warranty. 11 | 12 | python -m capsul highres_cortex.capsul.thickness_adv \ 13 | classif=../classif.nii.gz \ 14 | advection_step_size=0.05 \ 15 | verbosity=1 \ 16 | thickness_image=total-length.nii.gz \ 17 | equidistant_depth=pial-fraction.nii.gz 18 | -------------------------------------------------------------------------------- /examples/scripts/upwind-euclidean/upwind-euclidean.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | # 3 | # Copyright Forschungszentrum Jülich GmbH (2018). 4 | # 5 | # Contributor: Yann Leprince . 6 | # 7 | # Copying and distribution of this file, with or without modification, 8 | # are permitted in any medium without royalty provided the copyright 9 | # notice and this notice are preserved. This file is offered as-is, 10 | # without any warranty. 11 | 12 | python -m capsul highres_cortex.capsul.thickness_upw \ 13 | classif=../classif.nii.gz \ 14 | verbosity=1 \ 15 | thickness_image=total-length.nii.gz \ 16 | equidistant_depth=pial-fraction.nii.gz 17 | -------------------------------------------------------------------------------- /project_info.cmake: -------------------------------------------------------------------------------- 1 | # Copyright CEA (2014). 2 | # Copyright Université Paris XI (2014). 3 | # 4 | # Contributor: Yann Leprince . 5 | # 6 | # Copying and distribution of this file, with or without modification, 7 | # are permitted in any medium without royalty provided the copyright 8 | # notice and this notice are preserved. This file is offered as-is, 9 | # without any warranty. 10 | 11 | set( BRAINVISA_PACKAGE_NAME highres-cortex ) 12 | set( BRAINVISA_PACKAGE_MAIN_PROJECT highres-cortex ) 13 | set( BRAINVISA_PACKAGE_LICENCES "CeCILL-v2.1" ) 14 | set( BRAINVISA_PACKAGE_MAINTAINER "CEA - Yann Leprince" ) 15 | set( BRAINVISA_PACKAGE_VERSION_MAJOR 5 ) 16 | set( BRAINVISA_PACKAGE_VERSION_MINOR 2 ) 17 | set( BRAINVISA_PACKAGE_VERSION_PATCH 0 ) 18 | -------------------------------------------------------------------------------- /python/highres_cortex/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright CEA (2014). 3 | # Copyright Université Paris XI (2014). 4 | # 5 | # Contributor: Yann Leprince . 6 | # 7 | # This file is part of highres-cortex, a collection of software designed 8 | # to process high-resolution magnetic resonance images of the cerebral 9 | # cortex. 10 | # 11 | # This software is governed by the CeCILL licence under French law and 12 | # abiding by the rules of distribution of free software. You can use, 13 | # modify and/or redistribute the software under the terms of the CeCILL 14 | # licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | # . 16 | # 17 | # As a counterpart to the access to the source code and rights to copy, 18 | # modify and redistribute granted by the licence, users are provided only 19 | # with a limited warranty and the software's author, the holder of the 20 | # economic rights, and the successive licensors have only limited 21 | # liability. 22 | # 23 | # In this respect, the user's attention is drawn to the risks associated 24 | # with loading, using, modifying and/or developing or reproducing the 25 | # software by the user in light of its specific status of scientific 26 | # software, that may mean that it is complicated to manipulate, and that 27 | # also therefore means that it is reserved for developers and experienced 28 | # professionals having in-depth computer knowledge. Users are therefore 29 | # encouraged to load and test the software's suitability as regards their 30 | # requirements in conditions enabling the security of their systems and/or 31 | # data to be ensured and, more generally, to use and operate it in the 32 | # same conditions as regards security. 33 | # 34 | # The fact that you are presently reading this means that you have had 35 | # knowledge of the CeCILL licence and that you accept its terms. 36 | 37 | """Tools to process high-resolution images of the cerebral cortex.""" 38 | -------------------------------------------------------------------------------- /python/highres_cortex/capsul/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neurospin/highres-cortex/a2d6a7d2b0b1d07a3a3333d7826a6f607024d5aa/python/highres_cortex/capsul/__init__.py -------------------------------------------------------------------------------- /python/highres_cortex/capsul/filtered_sumcurvs.xml: -------------------------------------------------------------------------------- 1 | 37 | 38 | 39 | Compute the filtered sum of principal curvatures of isophote surfaces 40 | 41 | This is equivalent to computing the divergence of the normalized gradient 42 | of the input scalar field. 43 | 44 | .. note:: 45 | 46 | A Gaussian smoothing of width sigma is first applied to the input 47 | image, in order to limit the appearance of local high curvature values 48 | (e.g. due to the discontinuity of second-order derivative at the 49 | borders of the cortex). 50 | 51 | 53 | 54 | 55 | 56 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /python/highres_cortex/capsul/isovolume.xml: -------------------------------------------------------------------------------- 1 | 38 | 39 | 40 | Compute equivolumetric depth 41 | 42 | 44 | 46 | 47 | 49 | 51 | 52 | 53 | 54 | 56 | 57 | 58 | 59 | 60 | 61 | 63 | 64 | 65 | 67 | 68 | 69 | 71 | 72 | 73 | 74 | 75 | 76 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 93 | 94 | 95 | 96 | 98 | 99 | 100 | 101 | 103 | 104 | 106 | 108 | 109 | 111 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /python/highres_cortex/capsul/thickness_adv.xml: -------------------------------------------------------------------------------- 1 | 38 | 39 | 40 | Compute the cortical thickness along Laplace field lines from a classification volume, using Eulerian advection (slightly more precise than upwinding, but much slower) 41 | 42 | 44 | 46 | 48 | 49 | 50 | 51 | 53 | 54 | 55 | 56 | 58 | 59 | 60 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 87 | 89 | 90 | 92 | 94 | 95 | 96 | 97 | 98 | 99 | 101 | 103 | 104 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /python/highres_cortex/capsul/thickness_upw.xml: -------------------------------------------------------------------------------- 1 | 39 | 40 | 41 | Compute the cortical thickness along Laplace field lines from a classification volume, using upwinding (much faster than advection, but slightly less precise) 42 | 43 | 45 | 47 | 48 | 49 | 50 | 51 | 53 | 54 | 55 | 56 | 57 | 59 | 60 | 61 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 82 | 84 | 85 | 87 | 89 | 90 | 91 | 92 | 93 | 94 | 96 | 98 | 99 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /python/highres_cortex/scripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neurospin/highres-cortex/a2d6a7d2b0b1d07a3a3333d7826a6f607024d5aa/python/highres_cortex/scripts/__init__.py -------------------------------------------------------------------------------- /python/highres_cortex/scripts/distmaps.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright Forschungszentrum Jülich GmbH (2018). 5 | # Copyright CEA (2014). 6 | # Copyright Université Paris XI (2014). 7 | # 8 | # Contributor: Yann Leprince . 9 | # 10 | # This file is part of highres-cortex, a collection of software designed 11 | # to process high-resolution magnetic resonance images of the cerebral 12 | # cortex. 13 | # 14 | # This software is governed by the CeCILL licence under French law and 15 | # abiding by the rules of distribution of free software. You can use, 16 | # modify and/or redistribute the software under the terms of the CeCILL 17 | # licence as circulated by CEA, CNRS and INRIA at the following URL: 18 | # . 19 | # 20 | # As a counterpart to the access to the source code and rights to copy, 21 | # modify and redistribute granted by the licence, users are provided only 22 | # with a limited warranty and the software's author, the holder of the 23 | # economic rights, and the successive licensors have only limited 24 | # liability. 25 | # 26 | # In this respect, the user's attention is drawn to the risks associated 27 | # with loading, using, modifying and/or developing or reproducing the 28 | # software by the user in light of its specific status of scientific 29 | # software, that may mean that it is complicated to manipulate, and that 30 | # also therefore means that it is reserved for developers and experienced 31 | # professionals having in-depth computer knowledge. Users are therefore 32 | # encouraged to load and test the software's suitability as regards their 33 | # requirements in conditions enabling the security of their systems and/or 34 | # data to be ensured and, more generally, to use and operate it in the 35 | # same conditions as regards security. 36 | # 37 | # The fact that you are presently reading this means that you have had 38 | # knowledge of the CeCILL licence and that you accept its terms. 39 | 40 | from __future__ import absolute_import, division, print_function 41 | 42 | import sys 43 | 44 | from soma import aims 45 | 46 | import highres_cortex.cortex_topo 47 | 48 | 49 | def compute_distmaps_files(classif_filename, output_distwhite_filename, 50 | output_distCSF_filename, output_classif_filename): 51 | classif = aims.read(classif_filename) 52 | 53 | dist_from_white = highres_cortex.cortex_topo.signed_distance( 54 | classif, [100], [200], 150) 55 | aims.write(dist_from_white, output_distwhite_filename) 56 | 57 | dist_from_CSF = highres_cortex.cortex_topo.signed_distance( 58 | classif, [100], [0], 50) 59 | aims.write(dist_from_CSF, output_distCSF_filename) 60 | 61 | aims.write(classif, output_classif_filename) 62 | 63 | 64 | def parse_command_line(argv=sys.argv): 65 | """Parse the script's command line.""" 66 | import argparse 67 | parser = argparse.ArgumentParser( 68 | description="""\ 69 | Compute the signed distance to white matter and to CSF 70 | """) 71 | parser.add_argument("classif", help="classification image of the cortex " 72 | "(100 inside, 0 in CSF, 200 in white matter)") 73 | parser.add_argument("output_distwhite", help="signed Euclidean distance " 74 | "to the white matter boundary") 75 | parser.add_argument("output_distCSF", help="signed Euclidean distance " 76 | "to the CSF boundary") 77 | parser.add_argument("output_classif_with_boundaries", 78 | help="classification image of the cortex (100 inside, " 79 | "0 in CSF, 200 in white matter, 50 on the CSF " 80 | "boundary, 150 on the white matter boundary)") 81 | 82 | args = parser.parse_args(argv[1:]) 83 | return args 84 | 85 | 86 | def main(argv=sys.argv): 87 | """The script's entry point.""" 88 | args = parse_command_line(argv) 89 | return compute_distmaps_files( 90 | args.classif, 91 | args.output_distwhite, 92 | args.output_distCSF, 93 | args.output_classif_with_boundaries) or 0 94 | 95 | 96 | if __name__ == "__main__": 97 | sys.exit(main()) 98 | -------------------------------------------------------------------------------- /python/highres_cortex/scripts/fix_cortex_topology.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright Télécom ParisTech (2015). 5 | # 6 | # Contributor: Yann Leprince . 7 | # 8 | # This file is part of highres-cortex, a collection of software designed 9 | # to process high-resolution magnetic resonance images of the cerebral 10 | # cortex. 11 | # 12 | # This software is governed by the CeCILL licence under French law and 13 | # abiding by the rules of distribution of free software. You can use, 14 | # modify and/or redistribute the software under the terms of the CeCILL 15 | # licence as circulated by CEA, CNRS and INRIA at the following URL: 16 | # . 17 | # 18 | # As a counterpart to the access to the source code and rights to copy, 19 | # modify and redistribute granted by the licence, users are provided only 20 | # with a limited warranty and the software's author, the holder of the 21 | # economic rights, and the successive licensors have only limited 22 | # liability. 23 | # 24 | # In this respect, the user's attention is drawn to the risks associated 25 | # with loading, using, modifying and/or developing or reproducing the 26 | # software by the user in light of its specific status of scientific 27 | # software, that may mean that it is complicated to manipulate, and that 28 | # also therefore means that it is reserved for developers and experienced 29 | # professionals having in-depth computer knowledge. Users are therefore 30 | # encouraged to load and test the software's suitability as regards their 31 | # requirements in conditions enabling the security of their systems and/or 32 | # data to be ensured and, more generally, to use and operate it in the 33 | # same conditions as regards security. 34 | # 35 | # The fact that you are presently reading this means that you have had 36 | # knowledge of the CeCILL licence and that you accept its terms. 37 | 38 | from __future__ import absolute_import, division, print_function 39 | 40 | import argparse 41 | import sys 42 | 43 | import soma.subprocess as subprocess 44 | from soma import aims 45 | 46 | import highres_cortex.cortex_topo 47 | 48 | 49 | def fix_cortex_topology_files(input_filename, output_filename, 50 | filling_size, fclosing): 51 | """Call highres_cortex.cortex_topo.fix_cortex_topology on files.""" 52 | input_volume = aims.read(input_filename) 53 | 54 | try: 55 | output = highres_cortex.cortex_topo.fix_cortex_topology( 56 | input_volume, filling_size, fclosing) 57 | except OSError as exc: 58 | print("error: the VipHomotopic command cannot be" 59 | " found or executed ({0}). Please make sure that" 60 | " Morphologist is properly installed and that the" 61 | " command is in your PATH.".format(exc.strerror)) 62 | return 1 63 | except subprocess.CalledProcessError as exc: 64 | print("error: the VipHomotopic command returned an error code ({0})." 65 | " Please inspect its output above for more information." 66 | .format(exc.returncode)) 67 | return 1 68 | 69 | # BUG: aims.write offers no error checking, so the program will exit 70 | # successfully even if writing fails 71 | aims.write(output, output_filename) 72 | 73 | 74 | def parse_command_line(argv=sys.argv): 75 | """Parse the script's command line.""" 76 | parser = argparse.ArgumentParser( 77 | description="""\ 78 | Impose the topology of a hollow sphere onto the cortex in a voxelwise 79 | segmentation, which uses the following labels: 100 in the cortex itself, 0 80 | outside (CSF), 200 inside (white matter). In the output, the cortex is defined 81 | using 6-connectivity, each other compartment using 26-connectivity. 82 | """) 83 | parser.add_argument("input", 84 | help="3D volume containing the input segmentation") 85 | parser.add_argument("output", 86 | help="output 3D volume") 87 | parser.add_argument("--filling-size", type=float, default=2., 88 | help="""\ 89 | The size, in millimetres, of the largest holes in either cortical boundary that 90 | will be filled. This must be smaller than the thinnest cortex in the image. The 91 | default value is 2 mm, which is appropriate for a human brain.""") 92 | parser.add_argument("--fclosing", type=float, default=10., 93 | help="""\ 94 | The radius of the morphological closing which is used by VipHomotopic in 95 | Cortical surface mode to retrieve the brain's outer envelope. The default 96 | value, 10 mm, is appropriate for a human brain.""") 97 | 98 | args = parser.parse_args(argv[1:]) 99 | if not args.filling_size >= 0: 100 | parser.error("filling_size must be a non-negative number") 101 | if not args.fclosing >= 0: 102 | parser.error("fclosing must be a non-negative number") 103 | return args 104 | 105 | 106 | def main(argv=sys.argv): 107 | """The script's entry point.""" 108 | args = parse_command_line(argv) 109 | return fix_cortex_topology_files( 110 | args.input, args.output, args.filling_size, args.fclosing) or 0 111 | 112 | 113 | if __name__ == "__main__": 114 | sys.exit(main()) 115 | -------------------------------------------------------------------------------- /python/highres_cortex/scripts/get_exchanged_propvol.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright Forschungszentrum Jülich GmbH (2018). 5 | # Copyright CEA (2014). 6 | # Copyright Université Paris XI (2014). 7 | # 8 | # Contributor: Yann Leprince . 9 | # 10 | # This file is part of highres-cortex, a collection of software designed 11 | # to process high-resolution magnetic resonance images of the cerebral 12 | # cortex. 13 | # 14 | # This software is governed by the CeCILL licence under French law and 15 | # abiding by the rules of distribution of free software. You can use, 16 | # modify and/or redistribute the software under the terms of the CeCILL 17 | # licence as circulated by CEA, CNRS and INRIA at the following URL: 18 | # . 19 | # 20 | # As a counterpart to the access to the source code and rights to copy, 21 | # modify and redistribute granted by the licence, users are provided only 22 | # with a limited warranty and the software's author, the holder of the 23 | # economic rights, and the successive licensors have only limited 24 | # liability. 25 | # 26 | # In this respect, the user's attention is drawn to the risks associated 27 | # with loading, using, modifying and/or developing or reproducing the 28 | # software by the user in light of its specific status of scientific 29 | # software, that may mean that it is complicated to manipulate, and that 30 | # also therefore means that it is reserved for developers and experienced 31 | # professionals having in-depth computer knowledge. Users are therefore 32 | # encouraged to load and test the software's suitability as regards their 33 | # requirements in conditions enabling the security of their systems and/or 34 | # data to be ensured and, more generally, to use and operate it in the 35 | # same conditions as regards security. 36 | # 37 | # The fact that you are presently reading this means that you have had 38 | # knowledge of the CeCILL licence and that you accept its terms. 39 | 40 | from __future__ import absolute_import, division, print_function 41 | 42 | import os.path 43 | import shutil 44 | import sys 45 | import tempfile 46 | import six 47 | 48 | import numpy as np 49 | import soma.subprocess as subprocess 50 | from soma import aims 51 | 52 | 53 | def relabel_positive_labels(volume): 54 | size_x = volume.getSizeX() 55 | size_y = volume.getSizeY() 56 | size_z = volume.getSizeZ() 57 | old_to_new_labels = {} 58 | next_label = 1 59 | for z in six.moves.xrange(size_z): 60 | for y in six.moves.xrange(size_y): 61 | for x in six.moves.xrange(size_x): 62 | old_label = volume.at(x, y, z) 63 | if old_label > 0: 64 | try: 65 | new_label = old_to_new_labels[old_label] 66 | except KeyError: 67 | new_label = next_label 68 | old_to_new_labels[old_label] = new_label 69 | next_label += 1 70 | volume.setValue(new_label, x, y, z) 71 | 72 | 73 | def get_exchanged_propvol_files(classif_filename, 74 | CSF_labels_on_white_filename, 75 | white_labels_on_CSF_filename, 76 | output_filename): 77 | classif = aims.read(classif_filename) 78 | CSF_labels_on_white = aims.read(CSF_labels_on_white_filename) 79 | white_labels_on_CSF = aims.read(white_labels_on_CSF_filename) 80 | output = aims.Volume(CSF_labels_on_white) 81 | 82 | np_CSF_labels_on_white = np.asarray(CSF_labels_on_white) 83 | np_white_labels_on_CSF = np.asarray(white_labels_on_CSF) 84 | np_classif = np.asarray(classif) 85 | np_output = np.asarray(output) 86 | 87 | white_mask = (np_classif == 150) 88 | CSF_mask = (np_classif == 50) 89 | 90 | np_output[white_mask] = np_CSF_labels_on_white[white_mask] 91 | np_output[CSF_mask] = np_white_labels_on_CSF[CSF_mask] 92 | 93 | temp_dir = None 94 | try: 95 | temp_dir = tempfile.mkdtemp(prefix="hcortex") 96 | temp_filename = os.path.join(temp_dir, 'raw_exchanged_labels.nii') 97 | aims.write(output, temp_filename) 98 | 99 | # These “failed components” will probably be separated by connexity 100 | # AimsReplaceLevel -i raw_exchanged_labels.nii.gz \ 101 | # -o exchanged_labels.nii.gz \ 102 | # -g 100000000 -n 0 -g 200000000 -n 0 103 | 104 | subprocess.check_call(["AimsConnectComp", 105 | "-i", "raw_exchanged_labels.nii", 106 | "-o", "connected_exchanged_labels.nii"], 107 | cwd=temp_dir) 108 | 109 | # The background is cut in one big region + many small, restore it then 110 | # relabel 111 | propvol = aims.read( 112 | os.path.join(temp_dir, "connected_exchanged_labels.nii")) 113 | finally: 114 | if temp_dir: 115 | shutil.rmtree(temp_dir) 116 | np_propvol = np.asarray(propvol) 117 | exclusion_mask = (np_CSF_labels_on_white == -1) 118 | bulk_mask = (np_CSF_labels_on_white == 0) 119 | np_propvol[bulk_mask] = 0 120 | np_propvol[exclusion_mask] = -1 121 | 122 | relabel_positive_labels(propvol) 123 | aims.write(propvol, output_filename) 124 | 125 | 126 | def parse_command_line(argv=sys.argv): 127 | """Parse the script's command line.""" 128 | import argparse 129 | parser = argparse.ArgumentParser( 130 | description="""\ 131 | Get exchanged propagation volume 132 | """) 133 | parser.add_argument("classif_with_outer_boundaries", help="classification " 134 | "image of the cortex (100 inside, 0 in CSF, 200 in " 135 | "white matter, 50 on the CSF border, 150 on the white " 136 | "matter border)") 137 | parser.add_argument("CSF_labels_on_white", help="labels of the CSF " 138 | "projected onto the white matter boundary") 139 | parser.add_argument("white_labels_on_CSF", help="labels of the white " 140 | "matter projected onto the CSF boundary") 141 | parser.add_argument("output", help="volume where each interface is " 142 | "labelled with connected components facing the same " 143 | "voxels of the other interface") 144 | 145 | args = parser.parse_args(argv[1:]) 146 | return args 147 | 148 | 149 | def main(argv=sys.argv): 150 | """The script's entry point.""" 151 | args = parse_command_line(argv) 152 | return get_exchanged_propvol_files( 153 | args.classif_with_outer_boundaries, 154 | args.CSF_labels_on_white, 155 | args.white_labels_on_CSF, 156 | args.output) or 0 157 | 158 | 159 | if __name__ == "__main__": 160 | sys.exit(main()) 161 | -------------------------------------------------------------------------------- /python/highres_cortex/scripts/postprocess_equivolumetric_depth.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright CEA (2019). 5 | # 6 | # Contributor: Yann Leprince . 7 | # 8 | # This file is part of highres-cortex, a collection of software designed 9 | # to process high-resolution magnetic resonance images of the cerebral 10 | # cortex. 11 | # 12 | # This software is governed by the CeCILL licence under French law and 13 | # abiding by the rules of distribution of free software. You can use, 14 | # modify and/or redistribute the software under the terms of the CeCILL 15 | # licence as circulated by CEA, CNRS and INRIA at the following URL: 16 | # . 17 | # 18 | # As a counterpart to the access to the source code and rights to copy, 19 | # modify and redistribute granted by the licence, users are provided only 20 | # with a limited warranty and the software's author, the holder of the 21 | # economic rights, and the successive licensors have only limited 22 | # liability. 23 | # 24 | # In this respect, the user's attention is drawn to the risks associated 25 | # with loading, using, modifying and/or developing or reproducing the 26 | # software by the user in light of its specific status of scientific 27 | # software, that may mean that it is complicated to manipulate, and that 28 | # also therefore means that it is reserved for developers and experienced 29 | # professionals having in-depth computer knowledge. Users are therefore 30 | # encouraged to load and test the software's suitability as regards their 31 | # requirements in conditions enabling the security of their systems and/or 32 | # data to be ensured and, more generally, to use and operate it in the 33 | # same conditions as regards security. 34 | # 35 | # The fact that you are presently reading this means that you have had 36 | # knowledge of the CeCILL licence and that you accept its terms. 37 | 38 | from __future__ import absolute_import, division, print_function 39 | 40 | import sys 41 | 42 | import numpy as np 43 | from soma import aims 44 | 45 | from highres_cortex.cortex_topo import CSF_LABEL, WHITE_LABEL 46 | 47 | 48 | def postprocess_equivolumetric_depth(input_filename, classif_filename, 49 | output_filename): 50 | depth_vol = aims.read(input_filename) 51 | classif_vol = aims.read(classif_filename) 52 | 53 | depth_arr = np.asarray(depth_vol) 54 | classif_arr = np.asarray(classif_vol) 55 | 56 | depth_arr[classif_arr == CSF_LABEL] = 0.0 57 | depth_arr[classif_arr == WHITE_LABEL] = 1.0 58 | 59 | header = depth_vol.header() 60 | header['cal_min'] = 0.0 61 | header['cal_max'] = 1.0 62 | header['intent_code'] = 1001 # NIFTI_INTENT_ESTIMATE 63 | header['intent_name'] = 'Equivol. depth' 64 | header['descrip'] = ( 65 | 'Equivolumetric cortical depth computed with highres-cortex' 66 | ) 67 | 68 | aims.write(depth_vol, output_filename) 69 | 70 | 71 | def parse_command_line(argv=sys.argv): 72 | """Parse the script's command line.""" 73 | import argparse 74 | parser = argparse.ArgumentParser( 75 | description="""\ 76 | Post-process an equivolumetric depth image. 77 | 78 | - Set the outside of the brain (CSF) to 0.0 79 | - Set the white matter to 1.0 80 | - Set various Nifti header fields 81 | """) 82 | parser.add_argument("input_image", 83 | help="input image of equivolumetric depth") 84 | parser.add_argument("classif", help="classification image of the cortex " 85 | "(100 inside, 0 in CSF, 200 in white matter)") 86 | parser.add_argument("output_image") 87 | 88 | args = parser.parse_args(argv[1:]) 89 | return args 90 | 91 | 92 | def main(argv=sys.argv): 93 | """The script's entry point.""" 94 | args = parse_command_line(argv) 95 | return postprocess_equivolumetric_depth( 96 | args.input_image, 97 | args.classif, 98 | args.output_image) or 0 99 | 100 | 101 | if __name__ == "__main__": 102 | sys.exit(main()) 103 | -------------------------------------------------------------------------------- /python/highres_cortex/scripts/randomize_labels.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright Forschungszentrum Jülich GmbH (2018). 5 | # Copyright CEA (2014). 6 | # Copyright Université Paris XI (2014). 7 | # 8 | # Contributor: Yann Leprince . 9 | # 10 | # This file is part of highres-cortex, a collection of software designed 11 | # to process high-resolution magnetic resonance images of the cerebral 12 | # cortex. 13 | # 14 | # This software is governed by the CeCILL licence under French law and 15 | # abiding by the rules of distribution of free software. You can use, 16 | # modify and/or redistribute the software under the terms of the CeCILL 17 | # licence as circulated by CEA, CNRS and INRIA at the following URL: 18 | # . 19 | # 20 | # As a counterpart to the access to the source code and rights to copy, 21 | # modify and redistribute granted by the licence, users are provided only 22 | # with a limited warranty and the software's author, the holder of the 23 | # economic rights, and the successive licensors have only limited 24 | # liability. 25 | # 26 | # In this respect, the user's attention is drawn to the risks associated 27 | # with loading, using, modifying and/or developing or reproducing the 28 | # software by the user in light of its specific status of scientific 29 | # software, that may mean that it is complicated to manipulate, and that 30 | # also therefore means that it is reserved for developers and experienced 31 | # professionals having in-depth computer knowledge. Users are therefore 32 | # encouraged to load and test the software's suitability as regards their 33 | # requirements in conditions enabling the security of their systems and/or 34 | # data to be ensured and, more generally, to use and operate it in the 35 | # same conditions as regards security. 36 | # 37 | # The fact that you are presently reading this means that you have had 38 | # knowledge of the CeCILL licence and that you accept its terms. 39 | 40 | from __future__ import absolute_import, division, print_function 41 | 42 | import random 43 | import sys 44 | 45 | from six.moves import range 46 | 47 | from soma import aims 48 | 49 | 50 | def randomize_labels(labels): 51 | import numpy as np 52 | np_input_labels = np.asarray(labels) 53 | max_label = np.max(np_input_labels) 54 | nonzero_labels = list(range(1, max_label + 1)) 55 | random.shuffle(nonzero_labels) 56 | new_labels = [0] + nonzero_labels 57 | 58 | output = aims.Volume(labels) 59 | size_x = output.getSizeX() 60 | size_y = output.getSizeY() 61 | size_z = output.getSizeZ() 62 | for z in range(size_z): 63 | for y in range(size_y): 64 | for x in range(size_x): 65 | old_label = labels.at(x, y, z) 66 | if old_label >= 0: 67 | new_label = new_labels[old_label] 68 | else: 69 | new_label = 0 70 | output.setValue(new_label, x, y, z) 71 | return output 72 | 73 | 74 | def randomize_labels_files(input_filename, output_filename): 75 | input_vol = aims.read(input_filename) 76 | output_vol = randomize_labels(input_vol) 77 | aims.write(output_vol, output_filename) 78 | 79 | 80 | def parse_command_line(argv=sys.argv): 81 | """Parse the script's command line.""" 82 | import argparse 83 | parser = argparse.ArgumentParser( 84 | description="""\ 85 | Randomize the labels of an image with consecutive labels 86 | """) 87 | parser.add_argument("input", help="input label image") 88 | parser.add_argument("output", help="output label image") 89 | 90 | args = parser.parse_args(argv[1:]) 91 | return args 92 | 93 | 94 | def main(argv=sys.argv): 95 | """The script's entry point.""" 96 | args = parse_command_line(argv) 97 | return randomize_labels_files( 98 | args.input, 99 | args.output) or 0 100 | 101 | 102 | if __name__ == "__main__": 103 | sys.exit(main()) 104 | -------------------------------------------------------------------------------- /python/highres_cortex/scripts/relabel.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright Forschungszentrum Jülich GmbH (2018). 5 | # Copyright CEA (2014). 6 | # Copyright Université Paris XI (2014). 7 | # 8 | # Contributor: Yann Leprince . 9 | # 10 | # This file is part of highres-cortex, a collection of software designed 11 | # to process high-resolution magnetic resonance images of the cerebral 12 | # cortex. 13 | # 14 | # This software is governed by the CeCILL licence under French law and 15 | # abiding by the rules of distribution of free software. You can use, 16 | # modify and/or redistribute the software under the terms of the CeCILL 17 | # licence as circulated by CEA, CNRS and INRIA at the following URL: 18 | # . 19 | # 20 | # As a counterpart to the access to the source code and rights to copy, 21 | # modify and redistribute granted by the licence, users are provided only 22 | # with a limited warranty and the software's author, the holder of the 23 | # economic rights, and the successive licensors have only limited 24 | # liability. 25 | # 26 | # In this respect, the user's attention is drawn to the risks associated 27 | # with loading, using, modifying and/or developing or reproducing the 28 | # software by the user in light of its specific status of scientific 29 | # software, that may mean that it is complicated to manipulate, and that 30 | # also therefore means that it is reserved for developers and experienced 31 | # professionals having in-depth computer knowledge. Users are therefore 32 | # encouraged to load and test the software's suitability as regards their 33 | # requirements in conditions enabling the security of their systems and/or 34 | # data to be ensured and, more generally, to use and operate it in the 35 | # same conditions as regards security. 36 | # 37 | # The fact that you are presently reading this means that you have had 38 | # knowledge of the CeCILL licence and that you accept its terms. 39 | 40 | from __future__ import absolute_import, division, print_function 41 | 42 | import sys 43 | 44 | from soma import aims 45 | 46 | from six.moves import range 47 | 48 | 49 | def relabel(labels): 50 | output = aims.Volume(labels) 51 | size_x = output.getSizeX() 52 | size_y = output.getSizeY() 53 | size_z = output.getSizeZ() 54 | old_to_new_labels = {} 55 | next_label = 1 56 | for z in range(size_z): 57 | for y in range(size_y): 58 | for x in range(size_x): 59 | label = labels.at(x, y, z) 60 | if label == 0: 61 | new_label = 0 62 | else: 63 | try: 64 | new_label = old_to_new_labels[label] 65 | except KeyError: 66 | new_label = next_label 67 | old_to_new_labels[label] = new_label 68 | next_label += 1 69 | output.setValue(new_label, x, y, z) 70 | return output 71 | 72 | 73 | def relabel_files(input_filename, output_filename): 74 | input_vol = aims.read(input_filename) 75 | output_vol = relabel(input_vol) 76 | aims.write(output_vol, output_filename) 77 | 78 | 79 | def parse_command_line(argv=sys.argv): 80 | """Parse the script's command line.""" 81 | import argparse 82 | parser = argparse.ArgumentParser( 83 | description="""\ 84 | Assign new consecutive labels to an existing label image 85 | """) 86 | parser.add_argument("input", help="input label image") 87 | parser.add_argument("output", help="output label image") 88 | 89 | args = parser.parse_args(argv[1:]) 90 | return args 91 | 92 | 93 | def main(argv=sys.argv): 94 | """The script's entry point.""" 95 | args = parse_command_line(argv) 96 | return relabel_files( 97 | args.input, 98 | args.output) or 0 99 | 100 | 101 | if __name__ == "__main__": 102 | sys.exit(main()) 103 | -------------------------------------------------------------------------------- /python/highres_cortex/scripts/relabel_conjunction.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright Forschungszentrum Jülich GmbH (2018). 5 | # Copyright CEA (2014). 6 | # Copyright Université Paris XI (2014). 7 | # 8 | # Contributor: Yann Leprince . 9 | # 10 | # This file is part of highres-cortex, a collection of software designed 11 | # to process high-resolution magnetic resonance images of the cerebral 12 | # cortex. 13 | # 14 | # This software is governed by the CeCILL licence under French law and 15 | # abiding by the rules of distribution of free software. You can use, 16 | # modify and/or redistribute the software under the terms of the CeCILL 17 | # licence as circulated by CEA, CNRS and INRIA at the following URL: 18 | # . 19 | # 20 | # As a counterpart to the access to the source code and rights to copy, 21 | # modify and redistribute granted by the licence, users are provided only 22 | # with a limited warranty and the software's author, the holder of the 23 | # economic rights, and the successive licensors have only limited 24 | # liability. 25 | # 26 | # In this respect, the user's attention is drawn to the risks associated 27 | # with loading, using, modifying and/or developing or reproducing the 28 | # software by the user in light of its specific status of scientific 29 | # software, that may mean that it is complicated to manipulate, and that 30 | # also therefore means that it is reserved for developers and experienced 31 | # professionals having in-depth computer knowledge. Users are therefore 32 | # encouraged to load and test the software's suitability as regards their 33 | # requirements in conditions enabling the security of their systems and/or 34 | # data to be ensured and, more generally, to use and operate it in the 35 | # same conditions as regards security. 36 | # 37 | # The fact that you are presently reading this means that you have had 38 | # knowledge of the CeCILL licence and that you accept its terms. 39 | 40 | from __future__ import absolute_import, division, print_function 41 | 42 | import sys 43 | 44 | from six.moves import range 45 | 46 | from soma import aims 47 | 48 | 49 | def relabel_conjunction(labels1, labels2): 50 | output = aims.Volume(labels1) 51 | output.fill(0) 52 | size_x = output.getSizeX() 53 | size_y = output.getSizeY() 54 | size_z = output.getSizeZ() 55 | old_to_new_labels = {} 56 | next_label = 1 57 | for z in range(size_z): 58 | for y in range(size_y): 59 | for x in range(size_x): 60 | labels = (labels1.at(x, y, z), labels2.at(x, y, z)) 61 | # Negative means outside propagation region 62 | if labels[0] < 0 or labels[1] < 0: 63 | continue 64 | # Zeros are failed propagations, they should not be aggregated 65 | # together 66 | if labels[0] == 0 or labels[1] == 0: 67 | new_label = next_label 68 | next_label += 1 69 | else: 70 | try: 71 | new_label = old_to_new_labels[labels] 72 | except KeyError: 73 | new_label = next_label 74 | old_to_new_labels[labels] = new_label 75 | next_label += 1 76 | output.setValue(new_label, x, y, z) 77 | sys.stderr.write("{0}: {1} regions in conjunction\n" 78 | .format(sys.argv[0], next_label - 1)) 79 | return output 80 | 81 | 82 | def relabel_conjunction_files(labels1_filename, labels2_filename, 83 | output_filename): 84 | labels1_vol = aims.read(labels1_filename) 85 | labels2_vol = aims.read(labels2_filename) 86 | output_vol = relabel_conjunction(labels1_vol, labels2_vol) 87 | aims.write(output_vol, output_filename) 88 | 89 | 90 | def parse_command_line(argv=sys.argv): 91 | """Parse the script's command line.""" 92 | import argparse 93 | parser = argparse.ArgumentParser( 94 | description="""\ 95 | Assign new labels to voxels that have the same pair of labels in both 96 | input images. 97 | """) 98 | parser.add_argument("labels1", help="input label image") 99 | parser.add_argument("labels2", help="input label image") 100 | parser.add_argument("output", help="output label image") 101 | 102 | args = parser.parse_args(argv[1:]) 103 | return args 104 | 105 | 106 | def main(argv=sys.argv): 107 | """The script's entry point.""" 108 | args = parse_command_line(argv) 109 | return relabel_conjunction_files( 110 | args.labels1, 111 | args.labels2, 112 | args.output) or 0 113 | 114 | 115 | if __name__ == "__main__": 116 | sys.exit(main()) 117 | -------------------------------------------------------------------------------- /python/highres_cortex/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neurospin/highres-cortex/a2d6a7d2b0b1d07a3a3333d7826a6f607024d5aa/python/highres_cortex/test/__init__.py -------------------------------------------------------------------------------- /soma-env/soma-env-recipe.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: highres-cortex 3 | 4 | soma-env: 5 | publication: neuro-forge 6 | components: 7 | - highres-cortex 8 | internal-dependencies: 9 | - soma 10 | - anatomist 11 | 12 | type: compiled 13 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright CEA (2014). 2 | # Copyright Université Paris XI (2014). 3 | # 4 | # Contributor: Yann Leprince . 5 | # 6 | # Copying and distribution of this file, with or without modification, 7 | # are permitted in any medium without royalty provided the copyright 8 | # notice and this notice are preserved. This file is offered as-is, 9 | # without any warranty. 10 | 11 | add_subdirectory(library) 12 | add_subdirectory(commands) 13 | -------------------------------------------------------------------------------- /src/commands/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright Forschungszentrum Jülich GmbH (2016). 2 | # Copyright Télécom ParisTech (2015). 3 | # Copyright CEA (2014). 4 | # Copyright Université Paris XI (2014). 5 | # 6 | # Contributor: Yann Leprince . 7 | # 8 | # Copying and distribution of this file, with or without modification, 9 | # are permitted in any medium without royalty provided the copyright 10 | # notice and this notice are preserved. This file is offered as-is, 11 | # without any warranty. 12 | 13 | set(OpenMP_commands 14 | ylLaplacian 15 | ylIsoCurvature 16 | ) 17 | set(_commands 18 | ${OpenMP_commands} 19 | ylAdvectEuclidean 20 | ylAdvectPath 21 | ylAdvectTubes 22 | ylAdvectValues 23 | ylPropagateAlongField 24 | ylLabelEachVoxel 25 | ylMergeCortexColumnRegions 26 | ylMakeTraversePseudoAreaMap 27 | ylUpwindDistance 28 | ) 29 | 30 | include_directories("${CMAKE_BINARY_DIR}/include") 31 | 32 | foreach(_command ${_commands}) 33 | BRAINVISA_ADD_EXECUTABLE(${_command} ${_command}.cc) 34 | target_link_libraries(${_command} ${PROJECT_NAME} ${AIMS_AIMSDATA_LIBRARIES}) 35 | BRAINVISA_INSTALL(TARGETS ${_command} 36 | DESTINATION bin 37 | COMPONENT ${PROJECT_NAME}) 38 | endforeach() 39 | 40 | if(OPENMP_FOUND) 41 | set_source_files_properties(${OpenMP_commands} PROPERTIES 42 | COMPILE_FLAGS ${OpenMP_CXX_FLAGS}) 43 | if(OpenMP_CXX_LIBRARIES) 44 | foreach(_command ${OpenMP_commands}) 45 | target_link_libraries(${_command} ${OpenMP_CXX_LIBRARIES}) 46 | endforeach() 47 | else() 48 | # Old versions of FindOpenMP.cmake (before CMake 3.9) do not define 49 | # _LIBRARIES. This works with GCC and clang. 50 | set_target_properties(${OpenMP_commands} PROPERTIES 51 | LINK_FLAGS ${OpenMP_CXX_FLAGS}) 52 | endif() 53 | endif() 54 | -------------------------------------------------------------------------------- /src/commands/ylLabelEachVoxel.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | 7 | This file is part of highres-cortex, a collection of software designed 8 | to process high-resolution magnetic resonance images of the cerebral 9 | cortex. 10 | 11 | This software is governed by the CeCILL licence under French law and 12 | abiding by the rules of distribution of free software. You can use, 13 | modify and/or redistribute the software under the terms of the CeCILL 14 | licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | . 16 | 17 | As a counterpart to the access to the source code and rights to copy, 18 | modify and redistribute granted by the licence, users are provided only 19 | with a limited warranty and the software's author, the holder of the 20 | economic rights, and the successive licensors have only limited 21 | liability. 22 | 23 | In this respect, the user's attention is drawn to the risks associated 24 | with loading, using, modifying and/or developing or reproducing the 25 | software by the user in light of its specific status of scientific 26 | software, that may mean that it is complicated to manipulate, and that 27 | also therefore means that it is reserved for developers and experienced 28 | professionals having in-depth computer knowledge. Users are therefore 29 | encouraged to load and test the software's suitability as regards their 30 | requirements in conditions enabling the security of their systems and/or 31 | data to be ensured and, more generally, to use and operate it in the 32 | same conditions as regards security. 33 | 34 | The fact that you are presently reading this means that you have had 35 | knowledge of the CeCILL licence and that you accept its terms. 36 | */ 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | using std::clog; 49 | using std::endl; 50 | using carto::VolumeRef; 51 | using carto::verbose; 52 | using soma::AllocatorStrategy; 53 | using soma::AllocatorContext; 54 | 55 | namespace 56 | { 57 | const int EXIT_USAGE_ERROR = 2; 58 | std::string program_name; 59 | } // end of anonymous namespace 60 | 61 | int main(const int argc, const char **argv) 62 | { 63 | // Initialize command-line option parsing 64 | aims::Reader > input_reader; 65 | aims::Writer > output_writer; 66 | int32_t first_label = 1; 67 | 68 | program_name = argv[0]; 69 | aims::AimsApplication app(argc, argv, 70 | "Assign a unique label to each voxel of a mask.\n" 71 | "\n" 72 | "Non-zero voxels of the mask are each assigned a positive unique label."); 73 | app.addOption(input_reader, "--input", "input mask"); 74 | app.addOption(output_writer, "--output", 75 | "output label volume with S32 datatype"); 76 | { 77 | std::ostringstream help_str; 78 | help_str << "assign labels starting with this value [default: " 79 | << first_label << "]"; 80 | app.addOption(first_label, "--first", help_str.str(), true); 81 | } 82 | app.alias("-i", "--input"); 83 | app.alias("-o", "--output"); 84 | app.alias("--first-label", "--first"); 85 | 86 | 87 | // Process command-line options 88 | try 89 | { 90 | app.initialize(); 91 | } 92 | catch(const carto::user_interruption &) 93 | { 94 | // Exit after printing e.g. help 95 | return EXIT_SUCCESS; 96 | } 97 | catch(const std::runtime_error &e) 98 | { 99 | clog << program_name << ": error processing command-line options: " 100 | << e.what() << endl; 101 | return EXIT_USAGE_ERROR; 102 | } 103 | 104 | VolumeRef input_mask; 105 | input_reader.setAllocatorContext( 106 | AllocatorContext(AllocatorStrategy::ReadOnly)); 107 | input_reader.read(input_mask); 108 | const int size_x = input_mask.getSizeX(); 109 | const int size_y = input_mask.getSizeY(); 110 | const int size_z = input_mask.getSizeZ(); 111 | VolumeRef labelled_volume(size_x, size_y, size_z); 112 | labelled_volume->header() = input_mask->header(); 113 | labelled_volume->fill(0); 114 | 115 | int32_t next_label = first_label; 116 | for(int z = 0; z < size_z; ++z) 117 | for(int y = 0; y < size_y; ++y) 118 | for(int x = 0; x < size_x; ++x) 119 | { 120 | if(input_mask(x, y, z) != 0) { 121 | labelled_volume(x, y, z) = next_label; 122 | next_label++; 123 | } 124 | } 125 | 126 | if(verbose != 0) { 127 | clog << program_name << ": assigned labels between " << first_label 128 | << " and " << next_label - 1 << "." << endl; 129 | } 130 | 131 | bool success = output_writer.write(labelled_volume); 132 | return success ? EXIT_SUCCESS : EXIT_FAILURE; 133 | } 134 | -------------------------------------------------------------------------------- /src/commands/ylLaplacian.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Télécom ParisTech (2015). 3 | 4 | Contributor: Yann Leprince . 5 | 6 | This file is part of highres-cortex, a collection of software designed 7 | to process high-resolution magnetic resonance images of the cerebral 8 | cortex. 9 | 10 | This software is governed by the CeCILL licence under French law and 11 | abiding by the rules of distribution of free software. You can use, 12 | modify and/or redistribute the software under the terms of the CeCILL 13 | licence as circulated by CEA, CNRS and INRIA at the following URL: 14 | . 15 | 16 | As a counterpart to the access to the source code and rights to copy, 17 | modify and redistribute granted by the licence, users are provided only 18 | with a limited warranty and the software's author, the holder of the 19 | economic rights, and the successive licensors have only limited 20 | liability. 21 | 22 | In this respect, the user's attention is drawn to the risks associated 23 | with loading, using, modifying and/or developing or reproducing the 24 | software by the user in light of its specific status of scientific 25 | software, that may mean that it is complicated to manipulate, and that 26 | also therefore means that it is reserved for developers and experienced 27 | professionals having in-depth computer knowledge. Users are therefore 28 | encouraged to load and test the software's suitability as regards their 29 | requirements in conditions enabling the security of their systems and/or 30 | data to be ensured and, more generally, to use and operate it in the 31 | same conditions as regards security. 32 | 33 | The fact that you are presently reading this means that you have had 34 | knowledge of the CeCILL licence and that you accept its terms. 35 | */ 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | 50 | #include 51 | 52 | using std::clog; 53 | using std::endl; 54 | using carto::VolumeRef; 55 | using carto::verbose; 56 | using soma::AllocatorStrategy; 57 | using soma::AllocatorContext; 58 | 59 | 60 | // Anonymous namespace for file-local symbols 61 | namespace 62 | { 63 | const int EXIT_USAGE_ERROR = 2; 64 | std::string program_name; 65 | } // end of anonymous namespace 66 | 67 | int main(const int argc, const char **argv) 68 | { 69 | typedef float Real; 70 | // Initialize command-line option parsing 71 | aims::Reader > classif_reader; 72 | Real relative_precision = 0.001f; 73 | float typical_cortical_thickness = 3; 74 | aims::Writer > output_writer; 75 | 76 | program_name = argv[0]; 77 | aims::AimsApplication app(argc, argv, 78 | "Solve the Laplacian model in the cortex"); 79 | app.addOption(classif_reader, "--classif", 80 | "classification image of the cortex (100 inside, 0 in CSF, " 81 | "200 in white matter)"); 82 | app.addOption(output_writer, "--output", 83 | "output pseudo-temperature field (from 0 in CSF " 84 | "to 1 in the white matter)"); 85 | { 86 | std::ostringstream help_str; 87 | help_str << "desired maximum relative error in first-order" 88 | " finite differences (default: " << relative_precision << ")"; 89 | app.addOption(relative_precision, "--precision", help_str.str(), true); 90 | } 91 | { 92 | std::ostringstream help_str; 93 | help_str << "typical thickness of the cortex (mm), used for accelerating" 94 | " convergence (default: " << typical_cortical_thickness << "mm)"; 95 | app.addOption(typical_cortical_thickness, "--typical-cortical-thickness", 96 | help_str.str(), true); 97 | } 98 | app.alias("-i", "--classif"); 99 | app.alias("--input", "--classif"); 100 | app.alias("-o", "--output"); 101 | 102 | 103 | // Process command-line options 104 | try 105 | { 106 | app.initialize(); 107 | } 108 | catch(const carto::user_interruption &) 109 | { 110 | // Exit after printing e.g. help 111 | return EXIT_SUCCESS; 112 | } 113 | catch(const std::runtime_error &e) 114 | { 115 | clog << program_name << ": error processing command-line options: " 116 | << e.what() << endl; 117 | return EXIT_USAGE_ERROR; 118 | } 119 | 120 | if(!(relative_precision > 0 && relative_precision < 1)) { 121 | clog << program_name << ": precision must be strictly between 0 and 1" 122 | << endl; 123 | return EXIT_USAGE_ERROR; 124 | } 125 | if(!(typical_cortical_thickness > 0)) { 126 | clog << program_name << ": typical cortical thickness must be" 127 | " strictly positive" << endl; 128 | return EXIT_USAGE_ERROR; 129 | } 130 | 131 | if(verbose != 0) clog << program_name << ": reading classif..." << endl; 132 | classif_reader.setAllocatorContext( 133 | AllocatorContext(AllocatorStrategy::ReadOnly)); 134 | VolumeRef classif; 135 | bool success = classif_reader.read(classif); 136 | if(!success) { 137 | clog << program_name << ": error reading file '" 138 | << classif_reader.fileName() 139 | << "'specified as --classif, aborting" << endl; 140 | return EXIT_FAILURE; 141 | } 142 | 143 | const std::vector voxsize = classif->getVoxelSize(); 144 | const float min_voxsize = *std::min_element(voxsize.begin(), 145 | voxsize.begin() + 3); 146 | const Real absolute_precision = relative_precision * min_voxsize 147 | / (2 * typical_cortical_thickness); 148 | 149 | if(absolute_precision < yl::LaplaceSolver::best_precision()) { 150 | clog << program_name 151 | << boost::format(": warning: requested precision (relative %1$.1e, " 152 | "absolute %2$.1e) cannot be guaranteed.") 153 | % relative_precision % absolute_precision << std::endl; 154 | } 155 | 156 | yl::LaplaceSolver solver(classif); 157 | 158 | solver.set_verbosity(verbose); 159 | solver.initialize_solution(); 160 | solver.SOR(absolute_precision, typical_cortical_thickness); 161 | solver.clamp_to_range(0, 1); 162 | solver.eliminate_extrema(); 163 | VolumeRef solution = solver.solution(); 164 | 165 | 166 | if(verbose != 0) clog << program_name << ": writing output..." << endl; 167 | { 168 | bool write_success = output_writer.write(solution); 169 | if(!write_success) { 170 | clog << program_name << ": cannot write output volume" << endl; 171 | } 172 | success = success && write_success; 173 | } 174 | 175 | return success ? EXIT_SUCCESS : EXIT_FAILURE; 176 | } 177 | -------------------------------------------------------------------------------- /src/commands/ylMakeTraversePseudoAreaMap.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | 7 | This file is part of highres-cortex, a collection of software designed 8 | to process high-resolution magnetic resonance images of the cerebral 9 | cortex. 10 | 11 | This software is governed by the CeCILL licence under French law and 12 | abiding by the rules of distribution of free software. You can use, 13 | modify and/or redistribute the software under the terms of the CeCILL 14 | licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | . 16 | 17 | As a counterpart to the access to the source code and rights to copy, 18 | modify and redistribute granted by the licence, users are provided only 19 | with a limited warranty and the software's author, the holder of the 20 | economic rights, and the successive licensors have only limited 21 | liability. 22 | 23 | In this respect, the user's attention is drawn to the risks associated 24 | with loading, using, modifying and/or developing or reproducing the 25 | software by the user in light of its specific status of scientific 26 | software, that may mean that it is complicated to manipulate, and that 27 | also therefore means that it is reserved for developers and experienced 28 | professionals having in-depth computer knowledge. Users are therefore 29 | encouraged to load and test the software's suitability as regards their 30 | requirements in conditions enabling the security of their systems and/or 31 | data to be ensured and, more generally, to use and operate it in the 32 | same conditions as regards security. 33 | 34 | The fact that you are presently reading this means that you have had 35 | knowledge of the CeCILL licence and that you accept its terms. 36 | */ 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #include 49 | #include 50 | 51 | using std::clog; 52 | using std::endl; 53 | using carto::VolumeRef; 54 | using soma::AllocatorStrategy; 55 | using soma::AllocatorContext; 56 | 57 | namespace 58 | { 59 | const int EXIT_USAGE_ERROR = 2; 60 | std::string program_name; 61 | } // end of anonymous namespace 62 | 63 | int main(const int argc, const char **argv) 64 | { 65 | typedef yl::CortexColumnRegionQuality QualityCriterion; 66 | 67 | // Initialize command-line option parsing 68 | aims::Reader > input_reader; 69 | aims::Reader > CSF_projections_reader; 70 | aims::Reader > white_projections_reader; 71 | aims::Reader > classif_reader; 72 | float goal_diameter = QualityCriterion::default_goal_diameter(); 73 | aims::Writer > output_writer; 74 | 75 | program_name = argv[0]; 76 | aims::AimsApplication app(argc, argv, 77 | "Map the quality of cortex column regions"); 78 | app.addOption(input_reader, "--input", "input label volume"); 79 | app.addOption(CSF_projections_reader, "--proj-csf", 80 | "projected coordinates of the CSF surface"); 81 | app.addOption(white_projections_reader, "--proj-white", 82 | "projected coordinates of the white surface"); 83 | app.addOption(classif_reader, "--classif", 84 | "grey/white/CSF classification image"); 85 | { 86 | std::ostringstream help_str; 87 | help_str << "goal region diameter (in millimetres) [default: " 88 | << goal_diameter << "]"; 89 | app.addOption(goal_diameter, "--goal-diameter", 90 | help_str.str(), true); 91 | } 92 | app.addOption(output_writer, "--output", "output quality map"); 93 | app.alias("-i", "--input"); 94 | app.alias("-o", "--output"); 95 | 96 | 97 | // Process command-line options 98 | try 99 | { 100 | app.initialize(); 101 | } 102 | catch(const carto::user_interruption &) 103 | { 104 | // Exit after printing e.g. help 105 | return EXIT_SUCCESS; 106 | } 107 | catch(const std::runtime_error &e) 108 | { 109 | clog << program_name << ": error processing command-line options: " 110 | << e.what() << endl; 111 | return EXIT_USAGE_ERROR; 112 | } 113 | 114 | VolumeRef input_regions; 115 | input_reader.setAllocatorContext( 116 | AllocatorContext(AllocatorStrategy::ReadOnly)); 117 | input_reader.read(input_regions); 118 | yl::LabelVolume label_volume(input_regions); 119 | 120 | CSF_projections_reader.setAllocatorContext( 121 | AllocatorContext(AllocatorStrategy::ReadOnly)); 122 | VolumeRef CSF_projections; 123 | CSF_projections_reader.read(CSF_projections); 124 | 125 | white_projections_reader.setAllocatorContext( 126 | AllocatorContext(AllocatorStrategy::ReadOnly)); 127 | VolumeRef white_projections; 128 | white_projections_reader.read(white_projections); 129 | 130 | classif_reader.setAllocatorContext( 131 | AllocatorContext(AllocatorStrategy::ReadOnly)); 132 | VolumeRef classif; 133 | classif_reader.read(classif); 134 | 135 | const int extension_x = input_regions.getSizeX(); 136 | const int extension_y = input_regions.getSizeY(); 137 | const int extension_z = input_regions.getSizeZ(); 138 | carto::Volume output_volume(extension_x, extension_y, extension_z); 139 | output_volume.copyHeaderFrom(input_regions->header()); 140 | output_volume.fill(0); 141 | 142 | QualityCriterion quality_criterion(CSF_projections, 143 | white_projections, 144 | classif); 145 | quality_criterion.setShapeParametres(goal_diameter); 146 | 147 | for(yl::LabelVolume::const_regions_iterator 148 | labels_it = label_volume.regions_begin(), 149 | labels_end = label_volume.regions_end(); 150 | labels_it != labels_end; 151 | ++labels_it) 152 | { 153 | const int32_t label = *labels_it; 154 | const QualityCriterion::Cache cache = quality_criterion.cache(label_volume, label); 155 | const float quality = quality_criterion.pseudo_area(cache); 156 | for(yl::LabelVolume::const_point_iterator 157 | point_it = label_volume.region_begin(label), 158 | point_end = label_volume.region_end(label); 159 | point_it != point_end; 160 | ++point_it) 161 | { 162 | const Point3d& point = *point_it; 163 | const int x = point[0]; 164 | const int y = point[1]; 165 | const int z = point[2]; 166 | output_volume(x, y, z) = quality; 167 | } 168 | } 169 | 170 | bool success = output_writer.write(output_volume); 171 | return success ? EXIT_SUCCESS : EXIT_FAILURE; 172 | } 173 | -------------------------------------------------------------------------------- /src/commands/ylMergeCortexColumnRegions.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | 7 | This file is part of highres-cortex, a collection of software designed 8 | to process high-resolution magnetic resonance images of the cerebral 9 | cortex. 10 | 11 | This software is governed by the CeCILL licence under French law and 12 | abiding by the rules of distribution of free software. You can use, 13 | modify and/or redistribute the software under the terms of the CeCILL 14 | licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | . 16 | 17 | As a counterpart to the access to the source code and rights to copy, 18 | modify and redistribute granted by the licence, users are provided only 19 | with a limited warranty and the software's author, the holder of the 20 | economic rights, and the successive licensors have only limited 21 | liability. 22 | 23 | In this respect, the user's attention is drawn to the risks associated 24 | with loading, using, modifying and/or developing or reproducing the 25 | software by the user in light of its specific status of scientific 26 | software, that may mean that it is complicated to manipulate, and that 27 | also therefore means that it is reserved for developers and experienced 28 | professionals having in-depth computer knowledge. Users are therefore 29 | encouraged to load and test the software's suitability as regards their 30 | requirements in conditions enabling the security of their systems and/or 31 | data to be ensured and, more generally, to use and operate it in the 32 | same conditions as regards security. 33 | 34 | The fact that you are presently reading this means that you have had 35 | knowledge of the CeCILL licence and that you accept its terms. 36 | */ 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #include 49 | #include 50 | 51 | using std::clog; 52 | using std::endl; 53 | using carto::VolumeRef; 54 | using carto::verbose; 55 | using soma::AllocatorStrategy; 56 | using soma::AllocatorContext; 57 | 58 | namespace 59 | { 60 | const int EXIT_USAGE_ERROR = 2; 61 | std::string program_name; 62 | 63 | template 64 | float get_smallest_voxel_spacing(const VolumeType& volume) 65 | { 66 | std::vector voxel_size = volume->getVoxelSize(); 67 | voxel_size.resize(3); 68 | std::sort(voxel_size.begin(), voxel_size.end()); 69 | return voxel_size[0]; 70 | } 71 | 72 | } // end of anonymous namespace 73 | 74 | 75 | int main(const int argc, const char **argv) 76 | { 77 | typedef yl::CortexColumnRegionQuality QualityCriterion; 78 | 79 | // Initialize command-line option parsing 80 | aims::Reader > input_reader; 81 | aims::Reader > CSF_projections_reader; 82 | aims::Reader > white_projections_reader; 83 | aims::Reader > classif_reader; 84 | float goal_diameter = QualityCriterion::default_goal_diameter(); 85 | aims::Writer > output_writer; 86 | 87 | program_name = argv[0]; 88 | aims::AimsApplication app(argc, argv, 89 | "Aggregate over-segmented cortex column regions"); 90 | app.addOption(input_reader, "--input", "input label volume"); 91 | app.addOption(CSF_projections_reader, "--proj-csf", 92 | "projected coordinates of the CSF surface"); 93 | app.addOption(white_projections_reader, "--proj-white", 94 | "projected coordinates of the white surface"); 95 | app.addOption(classif_reader, "--classif", 96 | "grey/white/CSF classification image"); 97 | { 98 | std::ostringstream help_str; 99 | help_str << "goal region diameter (millimetres) [default: " 100 | << goal_diameter << "]"; 101 | app.addOption(goal_diameter, "--goal-diameter", 102 | help_str.str(), true); 103 | } 104 | app.addOption(output_writer, "--output", "output label volume"); 105 | app.alias("-i", "--input"); 106 | app.alias("-o", "--output"); 107 | 108 | 109 | // Process command-line options 110 | try 111 | { 112 | app.initialize(); 113 | } 114 | catch(const carto::user_interruption &) 115 | { 116 | // Exit after printing e.g. help 117 | return EXIT_SUCCESS; 118 | } 119 | catch(const std::runtime_error &e) 120 | { 121 | clog << program_name << ": error processing command-line options: " 122 | << e.what() << endl; 123 | return EXIT_USAGE_ERROR; 124 | } 125 | 126 | VolumeRef input_regions_volume; 127 | input_reader.setAllocatorContext( 128 | AllocatorContext(AllocatorStrategy::ReadOnly)); 129 | input_reader.read(input_regions_volume); 130 | const yl::LabelVolume input_regions(input_regions_volume); 131 | 132 | CSF_projections_reader.setAllocatorContext( 133 | AllocatorContext(AllocatorStrategy::ReadOnly)); 134 | VolumeRef CSF_projections; 135 | 136 | white_projections_reader.setAllocatorContext( 137 | AllocatorContext(AllocatorStrategy::ReadOnly)); 138 | CSF_projections_reader.read(CSF_projections); 139 | VolumeRef white_projections; 140 | white_projections_reader.read(white_projections); 141 | 142 | classif_reader.setAllocatorContext( 143 | AllocatorContext(AllocatorStrategy::ReadOnly)); 144 | VolumeRef classif; 145 | classif_reader.read(classif); 146 | 147 | QualityCriterion quality_criterion(CSF_projections, 148 | white_projections, 149 | classif); 150 | quality_criterion.setShapeParametres(goal_diameter); 151 | 152 | yl::IterativeRegionMerger 153 | region_merger(input_regions, quality_criterion, verbose); 154 | 155 | region_merger.merge_worst_regions_iteratively(); 156 | 157 | VolumeRef output_volume = region_merger.volume(); 158 | 159 | bool success = output_writer.write(output_volume); 160 | return success ? EXIT_SUCCESS : EXIT_FAILURE; 161 | } 162 | -------------------------------------------------------------------------------- /src/library/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright CEA (2014, 2017). 2 | # Copyright Télécom ParisTech (2015). 3 | # Copyright Université Paris XI (2014). 4 | # 5 | # Contributor: Yann Leprince . 6 | # 7 | # Copying and distribution of this file, with or without modification, 8 | # are permitted in any medium without royalty provided the copyright 9 | # notice and this notice are preserved. This file is offered as-is, 10 | # without any warranty. 11 | 12 | set(_headers 13 | cortex.hh 14 | field.hh 15 | front.hh 16 | advection.hh 17 | advection.tcc 18 | cortex_advection.hh 19 | propagate_along_field.hh 20 | propagate_along_field.tcc 21 | label_volume.hh 22 | label_volume.tcc 23 | iterative_region_merger.hh 24 | iterative_region_merger.tcc 25 | cortex_column_region_quality.hh 26 | cortex_column_region_quality.tcc 27 | laplace_solver.hh 28 | laplace_solver.tcc 29 | upwinding.hh 30 | volume_util.hh 31 | volume_util.tcc 32 | ) 33 | set(_sources 34 | field.cc 35 | front.cc 36 | advection.cc 37 | cortex_advection.cc 38 | propagate_along_field.cc 39 | label_volume.cc 40 | iterative_region_merger.cc 41 | cortex_column_region_quality.cc 42 | laplace_solver.cc 43 | upwinding.cc 44 | volume_util.cc 45 | ) 46 | 47 | BRAINVISA_COPY_AND_INSTALL_HEADERS(_headers ${PROJECT_NAME} headersTarget) 48 | 49 | include_directories(${Boost_INCLUDE_DIRS}) 50 | 51 | add_library(${PROJECT_NAME} ${_sources}) 52 | add_dependencies(${PROJECT_NAME} ${headersTarget}) 53 | 54 | if(OPENMP_FOUND) 55 | set_source_files_properties(${_sources} PROPERTIES 56 | COMPILE_FLAGS ${OpenMP_CXX_FLAGS}) 57 | if(OpenMP_CXX_LIBRARIES) 58 | target_link_libraries(${PROJECT_NAME} ${OpenMP_CXX_LIBRARIES}) 59 | else() 60 | # Old versions of FindOpenMP.cmake (before CMake 3.9) do not define 61 | # _LIBRARIES. This works with GCC and clang. 62 | set_target_properties(${PROJECT_NAME} PROPERTIES 63 | LINK_FLAGS ${OpenMP_CXX_FLAGS}) 64 | endif() 65 | endif() 66 | 67 | set_property(TARGET ${PROJECT_NAME} PROPERTY VERSION ${${PROJECT_NAME}_VERSION}) 68 | target_link_libraries(${PROJECT_NAME} ${AIMS_AIMSDATA_LIBRARIES}) 69 | BRAINVISA_INSTALL(TARGETS ${PROJECT_NAME} 70 | DESTINATION lib 71 | COMPONENT ${PROJECT_NAME}) 72 | 73 | if(DOXYGEN_FOUND) 74 | set( DOXYFILE_PREDEFINED "${AIMS_DEFINITIONS}") 75 | # Enable cross-linking to AIMS documentation (only works for in-tree build) 76 | set(AIMS-FREE_DOC_DIR "${AIMS-FREE_BINARY_DIR}/share/doc") 77 | set(AIMS-FREE_VERSION_MAJMIN 78 | "${aims-free_VERSION_MAJOR}.${aims-free_VERSION_MINOR}") 79 | set(SOMA-IO_DOC_DIR "${SOMA-IO_BINARY_DIR}/share/doc") 80 | set(SOMA-IO_VERSION_MAJMIN "${soma-io_VERSION_MAJOR}.${soma-io_VERSION_MINOR}") 81 | 82 | set(BV_DOC_URL "http://brainvisa.info/" CACHE STRING 83 | "Doxygen documentation links to the BrainVISA documentation at this URL") 84 | 85 | set(DOXYFILE_TAGFILES "${AIMS-FREE_DOC_DIR}/aimsdata-${AIMS-FREE_VERSION_MAJMIN}/doxygen/aimsdata.tag=${BV_DOC_URL}aimsdata-${AIMS-FREE_VERSION_MAJMIN}/doxygen ${AIMS-FREE_DOC_DIR}/aimsalgo-${AIMS-FREE_VERSION_MAJMIN}/doxygen/aimsalgo.tag=${BV_DOC_URL}aimsalgo-${AIMS-FREE_VERSION_MAJMIN}/doxygen ${AIMS-FREE_DOC_DIR}/cartodata-${AIMS-FREE_VERSION_MAJMIN}/doxygen/cartodata.tag=${BV_DOC_URL}cartodata-${AIMS-FREE_VERSION_MAJMIN}/doxygen ${SOMA-IO_DOC_DIR}/cartobase-${SOMA-IO_VERSION_MAJMIN}/doxygen/cartobase.tag=${BV_DOC_URL}cartobase-${SOMA-IO_VERSION_MAJMIN}/doxygen") 86 | 87 | BRAINVISA_GENERATE_DOXYGEN_DOC(_headers 88 | INPUT_PREFIX "${CMAKE_BINARY_DIR}/include/${PROJECT_NAME}") 89 | 90 | if(aims-free_IS_BEING_COMPILED) 91 | add_dependencies(${PROJECT_NAME}-doxygen aimsdata-doxygen aimsalgo-doxygen cartobase-doxygen cartodata-doxygen) 92 | endif(aims-free_IS_BEING_COMPILED) 93 | 94 | endif(DOXYGEN_FOUND) 95 | -------------------------------------------------------------------------------- /src/library/advection.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | 7 | This file is part of highres-cortex, a collection of software designed 8 | to process high-resolution magnetic resonance images of the cerebral 9 | cortex. 10 | 11 | This software is governed by the CeCILL licence under French law and 12 | abiding by the rules of distribution of free software. You can use, 13 | modify and/or redistribute the software under the terms of the CeCILL 14 | licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | . 16 | 17 | As a counterpart to the access to the source code and rights to copy, 18 | modify and redistribute granted by the licence, users are provided only 19 | with a limited warranty and the software's author, the holder of the 20 | economic rights, and the successive licensors have only limited 21 | liability. 22 | 23 | In this respect, the user's attention is drawn to the risks associated 24 | with loading, using, modifying and/or developing or reproducing the 25 | software by the user in light of its specific status of scientific 26 | software, that may mean that it is complicated to manipulate, and that 27 | also therefore means that it is reserved for developers and experienced 28 | professionals having in-depth computer knowledge. Users are therefore 29 | encouraged to load and test the software's suitability as regards their 30 | requirements in conditions enabling the security of their systems and/or 31 | data to be ensured and, more generally, to use and operate it in the 32 | same conditions as regards security. 33 | 34 | The fact that you are presently reading this means that you have had 35 | knowledge of the CeCILL licence and that you accept its terms. 36 | */ 37 | 38 | #include "advection.hh" 39 | #include 40 | 41 | yl::Advection::Advection(const VectorField3d& advection_field) 42 | : m_vector_field(advection_field), m_verbose(0), m_max_iter(default_max_iter) 43 | { 44 | } 45 | 46 | yl::ConstantStepAdvection:: 47 | ConstantStepAdvection(const yl::VectorField3d& advection_field, 48 | const float step) 49 | : Advection(advection_field), m_step(step) 50 | { 51 | } 52 | 53 | void yl::ConstantStepAdvection:: 54 | move_one_step(Point3df& point, 55 | const Point3df& local_field) const 56 | { 57 | float gx = local_field[0], gy = local_field[1], gz = local_field[2]; 58 | // Normalize the field, stop if too small or infinite or NaN. 59 | const float gn = std::sqrt(gx*gx + gy*gy + gz*gz); 60 | if(!std::isnormal(gn)) 61 | throw yl::Advection::AbnormalField(); 62 | gx /= gn; gy /= gn; gz /= gn; 63 | 64 | point[0] += m_step * gx; 65 | point[1] += m_step * gy; 66 | point[2] += m_step * gz; 67 | } 68 | 69 | #include "advection.tcc" 70 | 71 | template bool yl::Advection::visitor_advection 72 | (yl::Advection::Visitor& visitor, const Point3df& start_point) const; 73 | -------------------------------------------------------------------------------- /src/library/advection.hh: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014, 2017, 2019). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | Contributor: Denis Rivière . 7 | 8 | This file is part of highres-cortex, a collection of software designed 9 | to process high-resolution magnetic resonance images of the cerebral 10 | cortex. 11 | 12 | This software is governed by the CeCILL licence under French law and 13 | abiding by the rules of distribution of free software. You can use, 14 | modify and/or redistribute the software under the terms of the CeCILL 15 | licence as circulated by CEA, CNRS and INRIA at the following URL: 16 | . 17 | 18 | As a counterpart to the access to the source code and rights to copy, 19 | modify and redistribute granted by the licence, users are provided only 20 | with a limited warranty and the software's author, the holder of the 21 | economic rights, and the successive licensors have only limited 22 | liability. 23 | 24 | In this respect, the user's attention is drawn to the risks associated 25 | with loading, using, modifying and/or developing or reproducing the 26 | software by the user in light of its specific status of scientific 27 | software, that may mean that it is complicated to manipulate, and that 28 | also therefore means that it is reserved for developers and experienced 29 | professionals having in-depth computer knowledge. Users are therefore 30 | encouraged to load and test the software's suitability as regards their 31 | requirements in conditions enabling the security of their systems and/or 32 | data to be ensured and, more generally, to use and operate it in the 33 | same conditions as regards security. 34 | 35 | The fact that you are presently reading this means that you have had 36 | knowledge of the CeCILL licence and that you accept its terms. 37 | */ 38 | 39 | #ifndef YL_ADVECTION_HH_INCLUDED 40 | #define YL_ADVECTION_HH_INCLUDED 41 | 42 | #include "field.hh" 43 | 44 | namespace yl 45 | { 46 | 47 | /** Advect a visitor along a vector field */ 48 | class Advection 49 | { 50 | public: 51 | explicit Advection(const VectorField3d& advection_field); 52 | virtual ~Advection() {}; 53 | 54 | /** Advect a visitor along a vector field 55 | 56 | \arg visitor object being taken through all the advection path, see 57 | Visitor. Can be derived from Visitor, or must have all the same methods. 58 | \arg start_point the start of the advection path 59 | 60 | \retval true if the advection is stopped by the visitor without 61 | encountering any error 62 | \retval false if the advection stops for another reason 63 | */ 64 | template 65 | bool 66 | visitor_advection(TVisitor& visitor, 67 | const Point3df& start_point) const; 68 | 69 | /** Abstract base class for advection visitors */ 70 | class Visitor 71 | { 72 | public: 73 | Visitor() : m_verbosity(0) {}; 74 | virtual ~Visitor() {}; 75 | 76 | /** Called before visit() on the first point of the advection path */ 77 | virtual void first(const Point3df& point) = 0; 78 | /** Called for every point on the advection path, including the first */ 79 | virtual void visit(const Point3df& point) = 0; 80 | /** Predicate that decides if the advection will continue or stop */ 81 | virtual bool move_on(const Point3df& point) const = 0; 82 | /** Indicates whether the Visitor encountered an error */ 83 | virtual bool aborted() const = 0; 84 | /** Called after the advection is stopped by move_on() */ 85 | virtual void finished(const Point3df& /*start_point*/) {} 86 | /** Called when the advection cannot finish successfully */ 87 | virtual void abort() {} 88 | 89 | int verbosity() const { return m_verbosity; } 90 | /** Set the verbosity level (output to stderr) 91 | 92 | 0: silent (default on instance creation) 93 | 1: show errors 94 | */ 95 | void set_verbose(int verbosity) { m_verbosity = verbosity; } 96 | 97 | private: 98 | int m_verbosity; 99 | }; 100 | 101 | /** Default iteration limit */ 102 | static const unsigned int default_max_iter = 1000; 103 | /** Set the maximum number of iterations */ 104 | void set_max_iter(unsigned int max_iter) 105 | { 106 | m_max_iter = max_iter; 107 | }; 108 | 109 | /** Set the verbosity level (output to stderr) 110 | 111 | 0: silent (default on instance creation) 112 | 1: errors 113 | 2: informational messages 114 | >=3: debug (needs setting debug_output in advection.tcc) 115 | */ 116 | void set_verbose(const int verbosity) 117 | { 118 | m_verbose = verbosity; 119 | }; 120 | 121 | /** Thrown by move_one_step() to abort the advection */ 122 | class AbnormalField 123 | { 124 | }; 125 | 126 | private: 127 | virtual void move_one_step(Point3df& point, 128 | const Point3df& local_field) const = 0; 129 | 130 | const yl::VectorField3d& m_vector_field; 131 | int m_verbose; 132 | unsigned int m_max_iter; 133 | }; 134 | 135 | /** Forward advection using a constant step size 136 | 137 | The step size can be negative, in which case the advection is done in the 138 | opposite direction. 139 | */ 140 | class ConstantStepAdvection : public Advection 141 | { 142 | public: 143 | ConstantStepAdvection(const yl::VectorField3d& advection_field, float step); 144 | virtual ~ConstantStepAdvection() {}; 145 | 146 | /** Change the step length */ 147 | void set_step(float step) 148 | { 149 | m_step = step; 150 | }; 151 | 152 | private: 153 | virtual void move_one_step(Point3df& point, 154 | const Point3df& local_field) const; 155 | 156 | float m_step; 157 | }; 158 | 159 | } // namespace yl 160 | 161 | #endif // !defined(YL_ADVECTION_HH_INCLUDED) 162 | -------------------------------------------------------------------------------- /src/library/advection.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014, 2017). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | Contributor: Denis Rivière . 7 | 8 | This file is part of highres-cortex, a collection of software designed 9 | to process high-resolution magnetic resonance images of the cerebral 10 | cortex. 11 | 12 | This software is governed by the CeCILL licence under French law and 13 | abiding by the rules of distribution of free software. You can use, 14 | modify and/or redistribute the software under the terms of the CeCILL 15 | licence as circulated by CEA, CNRS and INRIA at the following URL: 16 | . 17 | 18 | As a counterpart to the access to the source code and rights to copy, 19 | modify and redistribute granted by the licence, users are provided only 20 | with a limited warranty and the software's author, the holder of the 21 | economic rights, and the successive licensors have only limited 22 | liability. 23 | 24 | In this respect, the user's attention is drawn to the risks associated 25 | with loading, using, modifying and/or developing or reproducing the 26 | software by the user in light of its specific status of scientific 27 | software, that may mean that it is complicated to manipulate, and that 28 | also therefore means that it is reserved for developers and experienced 29 | professionals having in-depth computer knowledge. Users are therefore 30 | encouraged to load and test the software's suitability as regards their 31 | requirements in conditions enabling the security of their systems and/or 32 | data to be ensured and, more generally, to use and operate it in the 33 | same conditions as regards security. 34 | 35 | The fact that you are presently reading this means that you have had 36 | knowledge of the CeCILL licence and that you accept its terms. 37 | */ 38 | 39 | #include 40 | 41 | 42 | namespace 43 | { 44 | int debug_output = 0; 45 | } // end of anonymous namespace 46 | 47 | template 48 | bool 49 | yl::Advection:: 50 | visitor_advection(TVisitor& visitor, 51 | const Point3df& start_point) const 52 | { 53 | using std::clog; 54 | using std::endl; 55 | 56 | if(m_verbose >= 2) { 57 | clog << "yl::Advection::visitor_advection starting at " 58 | << start_point << endl; 59 | } 60 | 61 | unsigned int iter = 0; 62 | Point3df point = start_point; 63 | visitor.first(point); 64 | 65 | while(visitor.move_on(point)) { 66 | if(iter >= m_max_iter) { 67 | if(m_verbose >= 1) { 68 | clog << " advection aborted after " << iter 69 | << " iterations: too many iterations." << endl; 70 | } 71 | visitor.abort(); 72 | return false; 73 | } 74 | 75 | if(debug_output >= 3 && m_verbose >= 3) { 76 | clog << " iteration " << iter << " at " << point << endl; 77 | } 78 | 79 | ++iter; 80 | visitor.visit(point); 81 | 82 | // Move along the field 83 | Point3df local_field; 84 | try { 85 | m_vector_field.evaluate(point, local_field); 86 | } catch(const Field::UndefinedField&) { 87 | if(m_verbose >= 1) { 88 | clog << " advection aborted after " << iter 89 | << " iterations: vector field is undefined at " << point << endl; 90 | } 91 | 92 | visitor.abort(); 93 | return false; 94 | } 95 | 96 | try { 97 | move_one_step(point, local_field); 98 | } catch(const AbnormalField&) { 99 | if(m_verbose >= 1) { 100 | clog << " advection aborted after " << iter 101 | << " iterations: vector field is abnormal" 102 | " (too small, infinite, or NaN) at " 103 | << point << endl; 104 | } 105 | 106 | visitor.abort(); 107 | return false; 108 | } 109 | } 110 | 111 | visitor.finished(start_point); 112 | 113 | if(m_verbose >= 2) { 114 | clog << " advection finished after " << iter << " iterations" << endl; 115 | } 116 | return !visitor.aborted(); 117 | } 118 | -------------------------------------------------------------------------------- /src/library/cortex.hh: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Télécom ParisTech (2015). 3 | 4 | Contributor: Yann Leprince . 5 | 6 | This file is part of highres-cortex, a collection of software designed 7 | to process high-resolution magnetic resonance images of the cerebral 8 | cortex. 9 | 10 | This software is governed by the CeCILL licence under French law and 11 | abiding by the rules of distribution of free software. You can use, 12 | modify and/or redistribute the software under the terms of the CeCILL 13 | licence as circulated by CEA, CNRS and INRIA at the following URL: 14 | . 15 | 16 | As a counterpart to the access to the source code and rights to copy, 17 | modify and redistribute granted by the licence, users are provided only 18 | with a limited warranty and the software's author, the holder of the 19 | economic rights, and the successive licensors have only limited 20 | liability. 21 | 22 | In this respect, the user's attention is drawn to the risks associated 23 | with loading, using, modifying and/or developing or reproducing the 24 | software by the user in light of its specific status of scientific 25 | software, that may mean that it is complicated to manipulate, and that 26 | also therefore means that it is reserved for developers and experienced 27 | professionals having in-depth computer knowledge. Users are therefore 28 | encouraged to load and test the software's suitability as regards their 29 | requirements in conditions enabling the security of their systems and/or 30 | data to be ensured and, more generally, to use and operate it in the 31 | same conditions as regards security. 32 | 33 | The fact that you are presently reading this means that you have had 34 | knowledge of the CeCILL licence and that you accept its terms. 35 | */ 36 | 37 | #ifndef CORTEX_HH_INCLUDED 38 | #define CORTEX_HH_INCLUDED 39 | 40 | namespace yl 41 | { 42 | 43 | enum { 44 | CSF_LABEL = 0, 45 | CORTEX_LABEL = 100, 46 | WHITE_LABEL = 200 47 | }; 48 | 49 | } // namespace yl 50 | 51 | #endif // !defined(CORTEX_HH_INCLUDED) 52 | -------------------------------------------------------------------------------- /src/library/cortex_column_region_quality.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | 7 | This file is part of highres-cortex, a collection of software designed 8 | to process high-resolution magnetic resonance images of the cerebral 9 | cortex. 10 | 11 | This software is governed by the CeCILL licence under French law and 12 | abiding by the rules of distribution of free software. You can use, 13 | modify and/or redistribute the software under the terms of the CeCILL 14 | licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | . 16 | 17 | As a counterpart to the access to the source code and rights to copy, 18 | modify and redistribute granted by the licence, users are provided only 19 | with a limited warranty and the software's author, the holder of the 20 | economic rights, and the successive licensors have only limited 21 | liability. 22 | 23 | In this respect, the user's attention is drawn to the risks associated 24 | with loading, using, modifying and/or developing or reproducing the 25 | software by the user in light of its specific status of scientific 26 | software, that may mean that it is complicated to manipulate, and that 27 | also therefore means that it is reserved for developers and experienced 28 | professionals having in-depth computer knowledge. Users are therefore 29 | encouraged to load and test the software's suitability as regards their 30 | requirements in conditions enabling the security of their systems and/or 31 | data to be ensured and, more generally, to use and operate it in the 32 | same conditions as regards security. 33 | 34 | The fact that you are presently reading this means that you have had 35 | knowledge of the CeCILL licence and that you accept its terms. 36 | */ 37 | 38 | #include "cortex_column_region_quality.hh" 39 | 40 | 41 | #include "cortex_column_region_quality.tcc" 42 | 43 | template yl::CortexColumnRegionQuality::Cache 44 | yl::CortexColumnRegionQuality::cache( 45 | const LabelVolume&, int32_t) const; 46 | template float yl::CortexColumnRegionQuality::fusion_ordering( 47 | const LabelVolume&, int32_t) const; 48 | template float yl::CortexColumnRegionQuality::fusion_ordering( 49 | const LabelVolume&, int32_t, int32_t) const; 50 | 51 | 52 | #include 53 | 54 | 55 | using carto::VolumeRef; 56 | 57 | namespace 58 | { 59 | 60 | float diameter_to_pseudo_area(float diameter) 61 | { 62 | return 0.125f * square(diameter); 63 | } 64 | 65 | } // end of anonymous namespace 66 | 67 | yl::CortexColumnRegionQuality:: 68 | CortexColumnRegionQuality(const VolumeRef& CSF_projections, 69 | const VolumeRef& white_projections, 70 | const VolumeRef& classif) 71 | : m_CSF_projections(CSF_projections), 72 | m_white_projections(white_projections), 73 | m_classif(classif) 74 | { 75 | setShapeParametres(default_goal_diameter()); 76 | assert(m_CSF_projections.getSizeT() == 3); 77 | assert(m_white_projections.getSizeT() == 3); 78 | } 79 | 80 | void 81 | yl::CortexColumnRegionQuality:: 82 | setShapeParametres(float goal_diameter) 83 | { 84 | assert(goal_diameter >= 0.f); 85 | m_pseudo_area_cutoff = diameter_to_pseudo_area(goal_diameter); 86 | } 87 | 88 | float yl::CortexColumnRegionQuality::default_goal_diameter() 89 | { 90 | return 0.5f; 91 | } 92 | -------------------------------------------------------------------------------- /src/library/cortex_column_region_quality.hh: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | 7 | This file is part of highres-cortex, a collection of software designed 8 | to process high-resolution magnetic resonance images of the cerebral 9 | cortex. 10 | 11 | This software is governed by the CeCILL licence under French law and 12 | abiding by the rules of distribution of free software. You can use, 13 | modify and/or redistribute the software under the terms of the CeCILL 14 | licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | . 16 | 17 | As a counterpart to the access to the source code and rights to copy, 18 | modify and redistribute granted by the licence, users are provided only 19 | with a limited warranty and the software's author, the holder of the 20 | economic rights, and the successive licensors have only limited 21 | liability. 22 | 23 | In this respect, the user's attention is drawn to the risks associated 24 | with loading, using, modifying and/or developing or reproducing the 25 | software by the user in light of its specific status of scientific 26 | software, that may mean that it is complicated to manipulate, and that 27 | also therefore means that it is reserved for developers and experienced 28 | professionals having in-depth computer knowledge. Users are therefore 29 | encouraged to load and test the software's suitability as regards their 30 | requirements in conditions enabling the security of their systems and/or 31 | data to be ensured and, more generally, to use and operate it in the 32 | same conditions as regards security. 33 | 34 | The fact that you are presently reading this means that you have had 35 | knowledge of the CeCILL licence and that you accept its terms. 36 | */ 37 | 38 | // TODO rename this to cortical_traverse_quality 39 | 40 | #ifndef CORTEX_COLUMN_REGION_QUALITY_HH_INCLUDED 41 | #define CORTEX_COLUMN_REGION_QUALITY_HH_INCLUDED 42 | 43 | #include 44 | #include "label_volume.hh" 45 | 46 | namespace yl 47 | { 48 | 49 | struct MomentAccumulator 50 | { 51 | public: 52 | MomentAccumulator() 53 | : m_000(0.f), 54 | m_100(0.f), m_010(0.f), m_001(0.f), 55 | m_200(0.f), 56 | m_110(0.f), m_020(0.f), 57 | m_101(0.f), m_011(0.f), m_002(0.f) {} 58 | 59 | MomentAccumulator(float m000, 60 | float m100, float m010, float m001, 61 | float m200, 62 | float m110, float m020, 63 | float m101, float m011, float m002) 64 | : m_000(m000), 65 | m_100(m100), m_010(m010), m_001(m001), 66 | m_200(m200), 67 | m_110(m110), m_020(m020), 68 | m_101(m101), m_011(m011), m_002(m002) {} 69 | 70 | void update(float x, float y, float z) 71 | { 72 | m_000 += 1; 73 | m_100 += x; m_010 += y; m_001 += z; 74 | m_200 += x * x; 75 | m_110 += y * x; m_020 += y * y; 76 | m_101 += z * x; m_011 += z * y; m_002 += z * z; 77 | }; 78 | 79 | MomentAccumulator operator + (const MomentAccumulator& other) const 80 | { 81 | return MomentAccumulator(m_000 + other.m_000, 82 | m_100 + other.m_100, 83 | m_010 + other.m_010, 84 | m_001 + other.m_001, 85 | m_200 + other.m_200, 86 | m_110 + other.m_110, 87 | m_020 + other.m_020, 88 | m_101 + other.m_101, 89 | m_011 + other.m_011, 90 | m_002 + other.m_002); 91 | }; 92 | 93 | std::size_t m_000; 94 | float m_100, m_010, m_001; 95 | float m_200; 96 | float m_110, m_020; 97 | float m_101, m_011, m_002; 98 | }; 99 | 100 | 101 | class CortexColumnRegionQuality 102 | { 103 | public: 104 | CortexColumnRegionQuality(const carto::VolumeRef& CSF_projections, 105 | const carto::VolumeRef& white_projections, 106 | const carto::VolumeRef& classif); 107 | 108 | void setShapeParametres(float goal_diameter); 109 | 110 | template 111 | float fusion_ordering(const LabelVolume& /*label_vol*/, Tlabel /*label*/) const; 112 | 113 | template 114 | float fusion_ordering(const LabelVolume& /*label_vol*/, Tlabel /*label1*/, Tlabel /*label2*/) const; 115 | 116 | template 117 | inline float fusion_ordering(const PointIterator& point_it_begin, 118 | const PointIterator& point_it_end) const; 119 | 120 | class Cache 121 | { 122 | public: 123 | Cache() 124 | : m_CSF_moments(), 125 | m_white_moments(), 126 | m_region_size(0), 127 | m_touches_CSF(false), 128 | m_touches_white(false) 129 | {}; 130 | Cache(const MomentAccumulator& CSF_moments, 131 | const MomentAccumulator& white_moments, 132 | std::size_t region_size, 133 | bool touches_CSF, 134 | bool touches_white) 135 | : m_CSF_moments(CSF_moments), 136 | m_white_moments(white_moments), 137 | m_region_size(region_size), 138 | m_touches_CSF(touches_CSF), 139 | m_touches_white(touches_white) 140 | {}; 141 | 142 | Cache operator + (const Cache& other) const 143 | { 144 | return Cache(CSF_moments() + other.CSF_moments(), 145 | white_moments() + other.white_moments(), 146 | region_size() + other.region_size(), 147 | touches_CSF() || other.touches_CSF(), 148 | touches_white() || other.touches_white()); 149 | }; 150 | 151 | const MomentAccumulator& CSF_moments() const {return m_CSF_moments;}; 152 | MomentAccumulator& CSF_moments() {return m_CSF_moments;}; 153 | const MomentAccumulator& white_moments() const {return m_white_moments;}; 154 | MomentAccumulator& white_moments() {return m_white_moments;}; 155 | std::size_t region_size() const {return m_region_size;}; 156 | std::size_t& region_size() {return m_region_size;}; 157 | bool touches_CSF() const {return m_touches_CSF;}; 158 | bool& touches_CSF() {return m_touches_CSF;}; 159 | bool touches_white() const {return m_touches_white;}; 160 | bool& touches_white() {return m_touches_white;}; 161 | private: 162 | MomentAccumulator m_CSF_moments; 163 | MomentAccumulator m_white_moments; 164 | std::size_t m_region_size; 165 | bool m_touches_CSF; 166 | bool m_touches_white; 167 | }; 168 | float fusion_ordering(const Cache& /*cache*/) const; 169 | bool want_fusion (const Cache& /*cache*/) const; 170 | float pseudo_area(const Cache& /*cache*/) const; 171 | template 172 | Cache cache(const PointIterator& point_it_begin, 173 | const PointIterator& point_it_end) const; 174 | template 175 | Cache cache(const LabelVolume& /*label_vol*/, Tlabel /*label*/) const; 176 | 177 | static float default_goal_diameter(); 178 | 179 | private: 180 | carto::VolumeRef m_CSF_projections; 181 | carto::VolumeRef m_white_projections; 182 | carto::VolumeRef m_classif; 183 | float m_pseudo_area_cutoff; 184 | }; // class CortexColumnRegionQuality 185 | 186 | }; // namespace yl 187 | 188 | #endif // !defined(CORTEX_COLUMN_REGION_QUALITY_HH_INCLUDED) 189 | -------------------------------------------------------------------------------- /src/library/field.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014, 2017). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | Contributor: Denis Rivière . 7 | 8 | This file is part of highres-cortex, a collection of software designed 9 | to process high-resolution magnetic resonance images of the cerebral 10 | cortex. 11 | 12 | This software is governed by the CeCILL licence under French law and 13 | abiding by the rules of distribution of free software. You can use, 14 | modify and/or redistribute the software under the terms of the CeCILL 15 | licence as circulated by CEA, CNRS and INRIA at the following URL: 16 | . 17 | 18 | As a counterpart to the access to the source code and rights to copy, 19 | modify and redistribute granted by the licence, users are provided only 20 | with a limited warranty and the software's author, the holder of the 21 | economic rights, and the successive licensors have only limited 22 | liability. 23 | 24 | In this respect, the user's attention is drawn to the risks associated 25 | with loading, using, modifying and/or developing or reproducing the 26 | software by the user in light of its specific status of scientific 27 | software, that may mean that it is complicated to manipulate, and that 28 | also therefore means that it is reserved for developers and experienced 29 | professionals having in-depth computer knowledge. Users are therefore 30 | encouraged to load and test the software's suitability as regards their 31 | requirements in conditions enabling the security of their systems and/or 32 | data to be ensured and, more generally, to use and operate it in the 33 | same conditions as regards security. 34 | 35 | The fact that you are presently reading this means that you have had 36 | knowledge of the CeCILL licence and that you accept its terms. 37 | */ 38 | 39 | #include "field.hh" 40 | 41 | #include 42 | #include 43 | 44 | using namespace aims; 45 | 46 | yl::LinearlyInterpolatedVectorField3d:: 47 | LinearlyInterpolatedVectorField3d(const carto::VolumeRef& fieldx, 48 | const carto::VolumeRef& fieldy, 49 | const carto::VolumeRef& fieldz) 50 | : m_interp_fieldx(fieldx), m_interp_fieldy(fieldy), m_interp_fieldz(fieldz) 51 | { 52 | } 53 | 54 | void 55 | yl::LinearlyInterpolatedVectorField3d:: 56 | evaluate(const Point3df& pos, Point3df& output) const 57 | { 58 | if(! m_interp_fieldx.isValid(pos[0], pos[1], pos[2]) 59 | || ! m_interp_fieldy.isValid(pos[0], pos[1], pos[2]) 60 | || ! m_interp_fieldz.isValid(pos[0], pos[1], pos[2])) 61 | { 62 | throw UndefinedField(); 63 | } 64 | output[0] = m_interp_fieldx.value(pos); 65 | output[1] = m_interp_fieldy.value(pos); 66 | output[2] = m_interp_fieldz.value(pos); 67 | } 68 | 69 | yl::LinearlyInterpolatedScalarFieldGradient:: 70 | LinearlyInterpolatedScalarFieldGradient(const carto::VolumeRef& scalar_field) 71 | : m_interp_gradx(), m_interp_grady(), m_interp_gradz() 72 | { 73 | AimsGradient gradient(AIMS_GRADIENT_DPLUS); 74 | carto::VolumeRef gradx = gradient.X(scalar_field); 75 | m_interp_gradx = getLinearInterpolator(gradx); 76 | carto::VolumeRef grady = gradient.Y(scalar_field); 77 | m_interp_grady = getLinearInterpolator(grady); 78 | carto::VolumeRef gradz = gradient.Z(scalar_field); 79 | m_interp_gradz = getLinearInterpolator(gradz); 80 | 81 | // Problem: the last line of each gradient is filled with zeros, which 82 | // means that the interpolation is meaningless near these borders. 83 | // This is worked around non-elegantly in the evaluate method. 84 | 85 | const std::vector voxel_size = scalar_field->getVoxelSize(); 86 | m_xoffset = -0.5f * voxel_size[0]; 87 | m_yoffset = -0.5f * voxel_size[1]; 88 | m_zoffset = -0.5f * voxel_size[2]; 89 | } 90 | 91 | void 92 | yl::LinearlyInterpolatedScalarFieldGradient:: 93 | evaluate(const Point3df& pos, Point3df& output) const 94 | { 95 | if(! m_interp_gradx->isValid(pos[0] + m_xoffset, pos[1], pos[2]) 96 | || ! m_interp_grady->isValid(pos[0], pos[1] + m_yoffset, pos[2]) 97 | || ! m_interp_gradz->isValid(pos[0], pos[1], pos[2] + m_zoffset)) 98 | { 99 | throw UndefinedField(); 100 | } 101 | 102 | // Workaround for problem described in the constructor: test if we are near 103 | // the border. Should work, but not elegant... 104 | if(! m_interp_gradx->isValid(pos[0] - m_xoffset, pos[1], pos[2]) 105 | || ! m_interp_grady->isValid(pos[0], pos[1] - m_yoffset, pos[2]) 106 | || ! m_interp_gradz->isValid(pos[0], pos[1], pos[2] - m_zoffset)) 107 | { 108 | throw UndefinedField(); 109 | } 110 | 111 | output[0] = m_interp_gradx->value(pos[0] + m_xoffset, pos[1], pos[2]); 112 | output[1] = m_interp_grady->value(pos[0], pos[1] + m_yoffset, pos[2]); 113 | output[2] = m_interp_gradz->value(pos[0], pos[1], pos[2] + m_zoffset); 114 | } 115 | 116 | yl::LinearlyInterpolatedScalarField:: 117 | LinearlyInterpolatedScalarField(const carto::VolumeRef& field_volume) 118 | : m_interp_field(field_volume) 119 | { 120 | } 121 | 122 | float 123 | yl::LinearlyInterpolatedScalarField:: 124 | evaluate(const Point3df& pos) const 125 | { 126 | if(! m_interp_field.isValid(pos[0], pos[1], pos[2])) 127 | { 128 | throw UndefinedField(); 129 | } 130 | return m_interp_field.value(pos); 131 | } 132 | 133 | 134 | yl::BooleanScalarField:: 135 | BooleanScalarField(const carto::VolumeRef& field_volume) 136 | : m_field(field_volume) 137 | { 138 | std::vector vs = field_volume->getVoxelSize(); 139 | m_voxel_size[0] = vs[0]; 140 | m_voxel_size[1] = vs[1]; 141 | m_voxel_size[2] = vs[2]; 142 | } 143 | 144 | float 145 | yl::BooleanScalarField:: 146 | evaluate(const Point3df& pos) const 147 | { 148 | return m_field->at(lround(pos[0] / m_voxel_size[0]), 149 | lround(pos[1] / m_voxel_size[1]), 150 | lround(pos[2] / m_voxel_size[2])) == 0 ? 0.f : 1.f; 151 | } 152 | -------------------------------------------------------------------------------- /src/library/field.hh: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014, 2017). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | Contributor: Denis Rivière . 7 | 8 | This file is part of highres-cortex, a collection of software designed 9 | to process high-resolution magnetic resonance images of the cerebral 10 | cortex. 11 | 12 | This software is governed by the CeCILL licence under French law and 13 | abiding by the rules of distribution of free software. You can use, 14 | modify and/or redistribute the software under the terms of the CeCILL 15 | licence as circulated by CEA, CNRS and INRIA at the following URL: 16 | . 17 | 18 | As a counterpart to the access to the source code and rights to copy, 19 | modify and redistribute granted by the licence, users are provided only 20 | with a limited warranty and the software's author, the holder of the 21 | economic rights, and the successive licensors have only limited 22 | liability. 23 | 24 | In this respect, the user's attention is drawn to the risks associated 25 | with loading, using, modifying and/or developing or reproducing the 26 | software by the user in light of its specific status of scientific 27 | software, that may mean that it is complicated to manipulate, and that 28 | also therefore means that it is reserved for developers and experienced 29 | professionals having in-depth computer knowledge. Users are therefore 30 | encouraged to load and test the software's suitability as regards their 31 | requirements in conditions enabling the security of their systems and/or 32 | data to be ensured and, more generally, to use and operate it in the 33 | same conditions as regards security. 34 | 35 | The fact that you are presently reading this means that you have had 36 | knowledge of the CeCILL licence and that you accept its terms. 37 | */ 38 | 39 | #ifndef YL_FIELD_HH_INCLUDED 40 | #define YL_FIELD_HH_INCLUDED 41 | 42 | #include 43 | #include 44 | 45 | namespace yl 46 | { 47 | 48 | /** Store and access a field (scalar or vector) defined over a 3D domain */ 49 | class Field 50 | { 51 | public: 52 | /** Exception thrown when the field has no defined value */ 53 | class UndefinedField 54 | { 55 | }; 56 | }; 57 | 58 | /** Store a vector field and access it at any coordinates */ 59 | class VectorField3d : public Field 60 | { 61 | public: 62 | // A virtual destructor is needed because this is a polymorphic class 63 | ~VectorField3d() {}; 64 | 65 | /** Evaluate the field's value at possibly non-integer coordinates 66 | 67 | \exception UndefinedField if the field cannot be evaluated at the 68 | given position. 69 | */ 70 | Point3df evaluate(const Point3df& pos) const 71 | { 72 | Point3df ret; 73 | evaluate(pos, ret); 74 | return ret; 75 | }; 76 | 77 | /** Evaluate the field's value at possibly non-integer coordinates 78 | 79 | \exception UndefinedField if the field cannot be evaluated at the 80 | given position. 81 | */ 82 | virtual void evaluate(const Point3df& pos, Point3df& output) const = 0; 83 | }; 84 | 85 | /** Store a scalar field and access it at any coordinates */ 86 | class ScalarField : public Field 87 | { 88 | public: 89 | // A virtual destructor is needed because this is a polymorphic class 90 | ~ScalarField() {}; 91 | 92 | /** Evaluate the field's value at possibly non-integer coordinates 93 | 94 | \exception UndefinedField if the field cannot be evaluated at the 95 | given position. 96 | */ 97 | virtual float evaluate(const Point3df& pos) const = 0; 98 | 99 | }; 100 | 101 | /** Access a vector field stored as three volumes 102 | 103 | The components are linearly interpolated between integer coordinates. 104 | */ 105 | class LinearlyInterpolatedVectorField3d : public VectorField3d 106 | { 107 | public: 108 | LinearlyInterpolatedVectorField3d(const carto::VolumeRef& fieldx, 109 | const carto::VolumeRef& fieldy, 110 | const carto::VolumeRef& fieldz); 111 | 112 | virtual void evaluate(const Point3df& pos, Point3df& output) const; 113 | private: 114 | aims::LinearInterpolator m_interp_fieldx; 115 | aims::LinearInterpolator m_interp_fieldy; 116 | aims::LinearInterpolator m_interp_fieldz; 117 | }; 118 | 119 | class LinearlyInterpolatedScalarFieldGradient : public VectorField3d 120 | { 121 | public: 122 | explicit LinearlyInterpolatedScalarFieldGradient( 123 | const carto::VolumeRef& scalar_field); 124 | virtual void evaluate(const Point3df& pos, Point3df& output) const; 125 | private: 126 | carto::rc_ptr m_interp_gradx; 127 | carto::rc_ptr m_interp_grady; 128 | carto::rc_ptr m_interp_gradz; 129 | float m_xoffset, m_yoffset, m_zoffset; 130 | }; 131 | 132 | /** Access a scalar field stored in a volume 133 | 134 | The field's value is linearly interpolated between integer coordinates. 135 | */ 136 | class LinearlyInterpolatedScalarField : public ScalarField 137 | { 138 | public: 139 | explicit LinearlyInterpolatedScalarField(const carto::VolumeRef& field_volume); 140 | 141 | virtual float evaluate(const Point3df& pos) const; 142 | private: 143 | aims::LinearInterpolator m_interp_field; 144 | }; 145 | 146 | /** Access a boolean field stored in a volume 147 | 148 | The boolean field is using nearest neighbour interpolation, any non-zero 149 | value (including NaN) is returned as true (1.0f). 150 | */ 151 | class BooleanScalarField : public ScalarField 152 | { 153 | public: 154 | explicit BooleanScalarField(const carto::VolumeRef& field_volume); 155 | 156 | virtual float evaluate(const Point3df& pos) const; 157 | private: 158 | const carto::VolumeRef& m_field; 159 | Point3df m_voxel_size; 160 | }; 161 | 162 | } // namespace yl 163 | 164 | #endif // !defined(YL_FIELD_HH_INCLUDED) 165 | -------------------------------------------------------------------------------- /src/library/front.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Télécom ParisTech (2015). 3 | 4 | Contributor: Yann Leprince . 5 | 6 | This file is part of highres-cortex, a collection of software designed 7 | to process high-resolution magnetic resonance images of the cerebral 8 | cortex. 9 | 10 | This software is governed by the CeCILL licence under French law and 11 | abiding by the rules of distribution of free software. You can use, 12 | modify and/or redistribute the software under the terms of the CeCILL 13 | licence as circulated by CEA, CNRS and INRIA at the following URL: 14 | . 15 | 16 | As a counterpart to the access to the source code and rights to copy, 17 | modify and redistribute granted by the licence, users are provided only 18 | with a limited warranty and the software's author, the holder of the 19 | economic rights, and the successive licensors have only limited 20 | liability. 21 | 22 | In this respect, the user's attention is drawn to the risks associated 23 | with loading, using, modifying and/or developing or reproducing the 24 | software by the user in light of its specific status of scientific 25 | software, that may mean that it is complicated to manipulate, and that 26 | also therefore means that it is reserved for developers and experienced 27 | professionals having in-depth computer knowledge. Users are therefore 28 | encouraged to load and test the software's suitability as regards their 29 | requirements in conditions enabling the security of their systems and/or 30 | data to be ensured and, more generally, to use and operate it in the 31 | same conditions as regards security. 32 | 33 | The fact that you are presently reading this means that you have had 34 | knowledge of the CeCILL licence and that you accept its terms. 35 | */ 36 | 37 | #include "front.hh" 38 | 39 | 40 | yl::SortedFront:: 41 | SortedFront(carto::VolumeRef& domain, 42 | const int16_t front_label, 43 | const int16_t done_label) 44 | : m_domain(domain), 45 | m_front_label(front_label), 46 | m_done_label(done_label) 47 | { 48 | } 49 | 50 | Point3d 51 | yl::SortedFront:: 52 | pop() 53 | { 54 | const Point3d point = get(); 55 | // TODO decide where to put this 56 | m_domain(point[0], point[1], point[2]) = m_done_label; 57 | m_queue.pop(); 58 | return point; 59 | } 60 | 61 | void 62 | yl::SortedFront:: 63 | add(const Point3d& point, const float priority) 64 | { 65 | assert(m_domain(point[0], point[1], point[2]) != m_front_label); 66 | 67 | m_queue.push(std::make_pair(priority, point)); 68 | m_domain(point[0], point[1], point[2]) = m_front_label; 69 | } 70 | -------------------------------------------------------------------------------- /src/library/front.hh: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Télécom ParisTech (2015). 3 | 4 | Contributor: Yann Leprince . 5 | 6 | This file is part of highres-cortex, a collection of software designed 7 | to process high-resolution magnetic resonance images of the cerebral 8 | cortex. 9 | 10 | This software is governed by the CeCILL licence under French law and 11 | abiding by the rules of distribution of free software. You can use, 12 | modify and/or redistribute the software under the terms of the CeCILL 13 | licence as circulated by CEA, CNRS and INRIA at the following URL: 14 | . 15 | 16 | As a counterpart to the access to the source code and rights to copy, 17 | modify and redistribute granted by the licence, users are provided only 18 | with a limited warranty and the software's author, the holder of the 19 | economic rights, and the successive licensors have only limited 20 | liability. 21 | 22 | In this respect, the user's attention is drawn to the risks associated 23 | with loading, using, modifying and/or developing or reproducing the 24 | software by the user in light of its specific status of scientific 25 | software, that may mean that it is complicated to manipulate, and that 26 | also therefore means that it is reserved for developers and experienced 27 | professionals having in-depth computer knowledge. Users are therefore 28 | encouraged to load and test the software's suitability as regards their 29 | requirements in conditions enabling the security of their systems and/or 30 | data to be ensured and, more generally, to use and operate it in the 31 | same conditions as regards security. 32 | 33 | The fact that you are presently reading this means that you have had 34 | knowledge of the CeCILL licence and that you accept its terms. 35 | */ 36 | 37 | #ifndef FRONT_HH_INCLUDED 38 | #define FRONT_HH_INCLUDED 39 | 40 | #include 41 | 42 | #include 43 | #include 44 | 45 | #include 46 | #include 47 | 48 | 49 | namespace yl 50 | { 51 | 52 | /** Helper class to use Point3d & friends in hash tables */ 53 | template 54 | struct PointHasher : std::unary_function 55 | { 56 | std::size_t operator()(const Point& point) const 57 | { 58 | std::size_t seed = 0; 59 | for(int i = 0; i < point.size(); ++i) 60 | boost::hash_combine(seed, point[i]); 61 | return seed; 62 | } 63 | }; 64 | 65 | enum { 66 | DEFAULT_FRONT_LABEL = -123, 67 | DEFAULT_DONE_LABEL = -10 68 | }; 69 | 70 | 71 | class SortedFront 72 | { 73 | public: 74 | SortedFront(carto::VolumeRef& domain, 75 | int16_t front_label, 76 | int16_t done_label); 77 | 78 | const Point3d& get() const 79 | { 80 | return m_queue.top().second; 81 | }; 82 | Point3d pop(); 83 | 84 | void add(const Point3d& /*point*/, float priority); 85 | 86 | bool empty() const 87 | { 88 | return m_queue.empty(); 89 | }; 90 | 91 | std::size_t size() const 92 | { 93 | return m_queue.size(); 94 | }; 95 | 96 | private: 97 | struct VoxelOrdering { 98 | bool operator() (const std::pair& left, 99 | const std::pair& right) const 100 | { 101 | return left.first > right.first; 102 | }; 103 | }; 104 | 105 | typedef boost::heap::priority_queue, 106 | boost::heap::compare > 107 | FrontQueue; 108 | FrontQueue m_queue; 109 | 110 | carto::VolumeRef m_domain; 111 | const int16_t m_front_label; 112 | const int16_t m_done_label; 113 | 114 | public: 115 | static const bool constant_time_size = FrontQueue::constant_time_size; 116 | }; 117 | 118 | } // namespace yl 119 | 120 | #endif // !defined(FRONT_HH_INCLUDED) 121 | -------------------------------------------------------------------------------- /src/library/iterative_region_merger.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | 7 | This file is part of highres-cortex, a collection of software designed 8 | to process high-resolution magnetic resonance images of the cerebral 9 | cortex. 10 | 11 | This software is governed by the CeCILL licence under French law and 12 | abiding by the rules of distribution of free software. You can use, 13 | modify and/or redistribute the software under the terms of the CeCILL 14 | licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | . 16 | 17 | As a counterpart to the access to the source code and rights to copy, 18 | modify and redistribute granted by the licence, users are provided only 19 | with a limited warranty and the software's author, the holder of the 20 | economic rights, and the successive licensors have only limited 21 | liability. 22 | 23 | In this respect, the user's attention is drawn to the risks associated 24 | with loading, using, modifying and/or developing or reproducing the 25 | software by the user in light of its specific status of scientific 26 | software, that may mean that it is complicated to manipulate, and that 27 | also therefore means that it is reserved for developers and experienced 28 | professionals having in-depth computer knowledge. Users are therefore 29 | encouraged to load and test the software's suitability as regards their 30 | requirements in conditions enabling the security of their systems and/or 31 | data to be ensured and, more generally, to use and operate it in the 32 | same conditions as regards security. 33 | 34 | The fact that you are presently reading this means that you have had 35 | knowledge of the CeCILL licence and that you accept its terms. 36 | */ 37 | 38 | #include "iterative_region_merger.hh" 39 | #include "cortex_column_region_quality.hh" 40 | 41 | #include "iterative_region_merger.tcc" 42 | 43 | template class yl::IterativeRegionMerger; 44 | -------------------------------------------------------------------------------- /src/library/iterative_region_merger.hh: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | 7 | This file is part of highres-cortex, a collection of software designed 8 | to process high-resolution magnetic resonance images of the cerebral 9 | cortex. 10 | 11 | This software is governed by the CeCILL licence under French law and 12 | abiding by the rules of distribution of free software. You can use, 13 | modify and/or redistribute the software under the terms of the CeCILL 14 | licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | . 16 | 17 | As a counterpart to the access to the source code and rights to copy, 18 | modify and redistribute granted by the licence, users are provided only 19 | with a limited warranty and the software's author, the holder of the 20 | economic rights, and the successive licensors have only limited 21 | liability. 22 | 23 | In this respect, the user's attention is drawn to the risks associated 24 | with loading, using, modifying and/or developing or reproducing the 25 | software by the user in light of its specific status of scientific 26 | software, that may mean that it is complicated to manipulate, and that 27 | also therefore means that it is reserved for developers and experienced 28 | professionals having in-depth computer knowledge. Users are therefore 29 | encouraged to load and test the software's suitability as regards their 30 | requirements in conditions enabling the security of their systems and/or 31 | data to be ensured and, more generally, to use and operate it in the 32 | same conditions as regards security. 33 | 34 | The fact that you are presently reading this means that you have had 35 | knowledge of the CeCILL licence and that you accept its terms. 36 | */ 37 | 38 | #ifndef ITERATIVE_REGION_MERGER_HH_INCLUDED 39 | #define ITERATIVE_REGION_MERGER_HH_INCLUDED 40 | 41 | #include 42 | 43 | #include "label_volume.hh" 44 | 45 | namespace yl 46 | { 47 | 48 | template 49 | class IterativeRegionMerger 50 | { 51 | public: 52 | explicit IterativeRegionMerger( 53 | const LabelVolume& label_vol, 54 | const RegionQualityCriterion& criterion=RegionQualityCriterion(), 55 | int verbosity=0); 56 | virtual ~IterativeRegionMerger() {}; 57 | 58 | void setVerbose(int verbosity=1); 59 | 60 | void merge_worst_regions_iteratively(); 61 | 62 | carto::VolumeRef volume() const 63 | { 64 | return m_label_volume.volume(); 65 | } 66 | 67 | private: 68 | LabelVolume m_label_volume; 69 | RegionQualityCriterion m_criterion; 70 | int m_verbosity; 71 | }; // class IterativeRegionMerger 72 | 73 | }; // namespace yl 74 | 75 | #endif // !defined(ITERATIVE_REGION_MERGER_HH_INCLUDED) 76 | -------------------------------------------------------------------------------- /src/library/label_volume.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | 7 | This file is part of highres-cortex, a collection of software designed 8 | to process high-resolution magnetic resonance images of the cerebral 9 | cortex. 10 | 11 | This software is governed by the CeCILL licence under French law and 12 | abiding by the rules of distribution of free software. You can use, 13 | modify and/or redistribute the software under the terms of the CeCILL 14 | licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | . 16 | 17 | As a counterpart to the access to the source code and rights to copy, 18 | modify and redistribute granted by the licence, users are provided only 19 | with a limited warranty and the software's author, the holder of the 20 | economic rights, and the successive licensors have only limited 21 | liability. 22 | 23 | In this respect, the user's attention is drawn to the risks associated 24 | with loading, using, modifying and/or developing or reproducing the 25 | software by the user in light of its specific status of scientific 26 | software, that may mean that it is complicated to manipulate, and that 27 | also therefore means that it is reserved for developers and experienced 28 | professionals having in-depth computer knowledge. Users are therefore 29 | encouraged to load and test the software's suitability as regards their 30 | requirements in conditions enabling the security of their systems and/or 31 | data to be ensured and, more generally, to use and operate it in the 32 | same conditions as regards security. 33 | 34 | The fact that you are presently reading this means that you have had 35 | knowledge of the CeCILL licence and that you accept its terms. 36 | */ 37 | 38 | #include "label_volume.hh" 39 | 40 | #include "label_volume.tcc" 41 | 42 | template class yl::LabelVolume; 43 | -------------------------------------------------------------------------------- /src/library/label_volume.hh: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | 7 | This file is part of highres-cortex, a collection of software designed 8 | to process high-resolution magnetic resonance images of the cerebral 9 | cortex. 10 | 11 | This software is governed by the CeCILL licence under French law and 12 | abiding by the rules of distribution of free software. You can use, 13 | modify and/or redistribute the software under the terms of the CeCILL 14 | licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | . 16 | 17 | As a counterpart to the access to the source code and rights to copy, 18 | modify and redistribute granted by the licence, users are provided only 19 | with a limited warranty and the software's author, the holder of the 20 | economic rights, and the successive licensors have only limited 21 | liability. 22 | 23 | In this respect, the user's attention is drawn to the risks associated 24 | with loading, using, modifying and/or developing or reproducing the 25 | software by the user in light of its specific status of scientific 26 | software, that may mean that it is complicated to manipulate, and that 27 | also therefore means that it is reserved for developers and experienced 28 | professionals having in-depth computer knowledge. Users are therefore 29 | encouraged to load and test the software's suitability as regards their 30 | requirements in conditions enabling the security of their systems and/or 31 | data to be ensured and, more generally, to use and operate it in the 32 | same conditions as regards security. 33 | 34 | The fact that you are presently reading this means that you have had 35 | knowledge of the CeCILL licence and that you accept its terms. 36 | */ 37 | 38 | #ifndef YL_LABEL_VOLUME_HH_INCLUDED 39 | #define YL_LABEL_VOLUME_HH_INCLUDED 40 | 41 | #include 42 | #include 43 | #include 44 | 45 | #include 46 | #include 47 | 48 | namespace yl 49 | { 50 | 51 | /** Return the first element of a std::pair, like non-standard std::select1st */ 52 | template 53 | class select1st : public std::unary_function 54 | { 55 | public: 56 | typename TPair::first_type& 57 | operator()(TPair& pair) const 58 | { 59 | return pair.first; 60 | } 61 | 62 | const typename TPair::first_type& 63 | operator()(const TPair& pair) const 64 | { 65 | return pair.first; 66 | } 67 | }; 68 | 69 | 70 | template 71 | class LabelVolume 72 | { 73 | public: 74 | typedef aims::BucketMap BucketMap; 75 | typedef BucketMap::Bucket Bucket; 76 | 77 | typedef boost::transform_iterator, 78 | BucketMap::const_iterator> const_regions_iterator; 79 | /** Iterator through a Bucket's points (yields Point3d) */ 80 | typedef boost::transform_iterator, 81 | Bucket::const_iterator> const_point_iterator; 82 | 83 | explicit LabelVolume(const carto::VolumeRef &vol, Tlabel background = 0); 84 | virtual ~LabelVolume() {}; 85 | 86 | void merge_regions(Tlabel eating_label, Tlabel eaten_label); 87 | void discard_region(Tlabel label); 88 | 89 | Tlabel background_label() const 90 | { 91 | return m_background_label; 92 | } 93 | 94 | const carto::VolumeRef& volume() const 95 | { 96 | return m_volume; 97 | } 98 | 99 | BucketMap::size_type n_regions() const 100 | { 101 | return m_bucketmap.size(); 102 | } 103 | 104 | /** Iterate through all region labels */ 105 | const_regions_iterator regions_begin() const 106 | { 107 | return const_regions_iterator(m_bucketmap.begin(), 108 | select1st()); 109 | }; 110 | 111 | /** Iterate through all region labels */ 112 | const_regions_iterator regions_end() const 113 | { 114 | return const_regions_iterator(m_bucketmap.end(), 115 | select1st()); 116 | }; 117 | 118 | BucketMap::size_type region_size(Tlabel label) const 119 | { 120 | const BucketMap::const_iterator region_bucket_it = m_bucketmap.find(label); 121 | assert(region_bucket_it != m_bucketmap.end()); 122 | return region_bucket_it->second.size(); 123 | }; 124 | 125 | /** Iterate through the coordinates of a region's voxels */ 126 | const_point_iterator region_begin(Tlabel label) const 127 | { 128 | const BucketMap::const_iterator region_bucket_it = m_bucketmap.find(label); 129 | assert(region_bucket_it != m_bucketmap.end()); 130 | return const_point_iterator(region_bucket_it->second.begin(), 131 | select1st()); 132 | }; 133 | 134 | /** Iterate through the coordinates of a region's voxels */ 135 | const_point_iterator region_end(Tlabel label) const 136 | { 137 | const BucketMap::const_iterator region_bucket_it = m_bucketmap.find(label); 138 | assert(region_bucket_it != m_bucketmap.end()); 139 | return const_point_iterator(region_bucket_it->second.end(), 140 | select1st()); 141 | }; 142 | 143 | private: 144 | const Tlabel m_background_label; 145 | carto::VolumeRef m_volume; 146 | aims::BucketMap m_bucketmap; 147 | }; // class LabelVolume 148 | 149 | }; // namespace yl 150 | 151 | #endif // !defined(YL_LABEL_VOLUME_HH_INCLUDED) 152 | -------------------------------------------------------------------------------- /src/library/label_volume.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | 7 | This file is part of highres-cortex, a collection of software designed 8 | to process high-resolution magnetic resonance images of the cerebral 9 | cortex. 10 | 11 | This software is governed by the CeCILL licence under French law and 12 | abiding by the rules of distribution of free software. You can use, 13 | modify and/or redistribute the software under the terms of the CeCILL 14 | licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | . 16 | 17 | As a counterpart to the access to the source code and rights to copy, 18 | modify and redistribute granted by the licence, users are provided only 19 | with a limited warranty and the software's author, the holder of the 20 | economic rights, and the successive licensors have only limited 21 | liability. 22 | 23 | In this respect, the user's attention is drawn to the risks associated 24 | with loading, using, modifying and/or developing or reproducing the 25 | software by the user in light of its specific status of scientific 26 | software, that may mean that it is complicated to manipulate, and that 27 | also therefore means that it is reserved for developers and experienced 28 | professionals having in-depth computer knowledge. Users are therefore 29 | encouraged to load and test the software's suitability as regards their 30 | requirements in conditions enabling the security of their systems and/or 31 | data to be ensured and, more generally, to use and operate it in the 32 | same conditions as regards security. 33 | 34 | The fact that you are presently reading this means that you have had 35 | knowledge of the CeCILL licence and that you accept its terms. 36 | */ 37 | 38 | namespace yl 39 | { 40 | 41 | template 42 | LabelVolume:: 43 | LabelVolume(const carto::VolumeRef &vol, 44 | Tlabel background) 45 | : m_background_label(background), m_volume(vol), m_bucketmap() 46 | { 47 | const int size_x = m_volume.getSizeX(); 48 | const int size_y = m_volume.getSizeY(); 49 | const int size_z = m_volume.getSizeZ(); 50 | 51 | for(int z = 0; z < size_z; ++z) 52 | for(int y = 0; y < size_y; ++y) 53 | for(int x = 0; x < size_x; ++x) 54 | { 55 | const Tlabel label = m_volume.at(x, y, z); 56 | if(label != background) { 57 | m_bucketmap[label].insert(Bucket::value_type(Point3d(x, y, z), Void())); 58 | } 59 | } 60 | } 61 | 62 | template 63 | void LabelVolume:: 64 | merge_regions(Tlabel eating_label, Tlabel eaten_label) 65 | { 66 | const BucketMap::iterator eating_bucket_it = m_bucketmap.find(eating_label); 67 | BucketMap::iterator eaten_bucket_it = m_bucketmap.find(eaten_label); 68 | 69 | assert(eating_bucket_it != m_bucketmap.end()); 70 | assert(eaten_bucket_it != m_bucketmap.end()); 71 | 72 | Bucket & eating_bucket = eating_bucket_it->second; 73 | Bucket & eaten_bucket = eaten_bucket_it->second; 74 | 75 | for(Bucket::iterator 76 | point_it = eaten_bucket.begin(), 77 | point_it_end = eaten_bucket.end(); 78 | point_it != point_it_end; 79 | ++point_it) { 80 | const Point3d & point = point_it->first; 81 | const int & x = point[0]; 82 | const int & y = point[1]; 83 | const int & z = point[2]; 84 | m_volume.at(x, y, z) = eating_label; 85 | eating_bucket.insert(*point_it); 86 | } 87 | 88 | m_bucketmap.erase(eaten_bucket_it); 89 | } 90 | 91 | template 92 | void LabelVolume:: 93 | discard_region(Tlabel label) 94 | { 95 | BucketMap::iterator bucket_it = m_bucketmap.find(label); 96 | assert(bucket_it != m_bucketmap.end()); 97 | 98 | Bucket & bucket = bucket_it->second; 99 | 100 | for(Bucket::iterator 101 | point_it = bucket.begin(), 102 | point_it_end = bucket.end(); 103 | point_it != point_it_end; 104 | ++point_it) { 105 | const Point3d & point = point_it->first; 106 | const int & x = point[0]; 107 | const int & y = point[1]; 108 | const int & z = point[2]; 109 | m_volume.at(x, y, z) = m_background_label; 110 | } 111 | 112 | m_bucketmap.erase(bucket_it); 113 | } 114 | 115 | } // namespace yl 116 | -------------------------------------------------------------------------------- /src/library/laplace_solver.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Télécom ParisTech (2015). 3 | 4 | Contributor: Yann Leprince . 5 | 6 | This file is part of highres-cortex, a collection of software designed 7 | to process high-resolution magnetic resonance images of the cerebral 8 | cortex. 9 | 10 | This software is governed by the CeCILL licence under French law and 11 | abiding by the rules of distribution of free software. You can use, 12 | modify and/or redistribute the software under the terms of the CeCILL 13 | licence as circulated by CEA, CNRS and INRIA at the following URL: 14 | . 15 | 16 | As a counterpart to the access to the source code and rights to copy, 17 | modify and redistribute granted by the licence, users are provided only 18 | with a limited warranty and the software's author, the holder of the 19 | economic rights, and the successive licensors have only limited 20 | liability. 21 | 22 | In this respect, the user's attention is drawn to the risks associated 23 | with loading, using, modifying and/or developing or reproducing the 24 | software by the user in light of its specific status of scientific 25 | software, that may mean that it is complicated to manipulate, and that 26 | also therefore means that it is reserved for developers and experienced 27 | professionals having in-depth computer knowledge. Users are therefore 28 | encouraged to load and test the software's suitability as regards their 29 | requirements in conditions enabling the security of their systems and/or 30 | data to be ensured and, more generally, to use and operate it in the 31 | same conditions as regards security. 32 | 33 | The fact that you are presently reading this means that you have had 34 | knowledge of the CeCILL licence and that you accept its terms. 35 | */ 36 | 37 | #include "laplace_solver.hh" 38 | 39 | #include "laplace_solver.tcc" 40 | 41 | template class yl::LaplaceSolver; 42 | -------------------------------------------------------------------------------- /src/library/laplace_solver.hh: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Télécom ParisTech (2015). 3 | 4 | Contributor: Yann Leprince . 5 | 6 | This file is part of highres-cortex, a collection of software designed 7 | to process high-resolution magnetic resonance images of the cerebral 8 | cortex. 9 | 10 | This software is governed by the CeCILL licence under French law and 11 | abiding by the rules of distribution of free software. You can use, 12 | modify and/or redistribute the software under the terms of the CeCILL 13 | licence as circulated by CEA, CNRS and INRIA at the following URL: 14 | . 15 | 16 | As a counterpart to the access to the source code and rights to copy, 17 | modify and redistribute granted by the licence, users are provided only 18 | with a limited warranty and the software's author, the holder of the 19 | economic rights, and the successive licensors have only limited 20 | liability. 21 | 22 | In this respect, the user's attention is drawn to the risks associated 23 | with loading, using, modifying and/or developing or reproducing the 24 | software by the user in light of its specific status of scientific 25 | software, that may mean that it is complicated to manipulate, and that 26 | also therefore means that it is reserved for developers and experienced 27 | professionals having in-depth computer knowledge. Users are therefore 28 | encouraged to load and test the software's suitability as regards their 29 | requirements in conditions enabling the security of their systems and/or 30 | data to be ensured and, more generally, to use and operate it in the 31 | same conditions as regards security. 32 | 33 | The fact that you are presently reading this means that you have had 34 | knowledge of the CeCILL licence and that you accept its terms. 35 | */ 36 | 37 | #ifndef LAPLACE_SOLVER_HH_INCLUDED 38 | #define LAPLACE_SOLVER_HH_INCLUDED 39 | 40 | #include 41 | 42 | #include 43 | 44 | #include 45 | 46 | namespace yl 47 | { 48 | 49 | template 50 | class LaplaceSolver 51 | { 52 | BOOST_STATIC_ASSERT_MSG(std::numeric_limits::is_specialized, 53 | "LaplaceSolver can only be specialized for types" 54 | " with std::numeric_limits support"); 55 | BOOST_STATIC_ASSERT_MSG(!std::numeric_limits::is_integer, 56 | "LaplaceSolver can only be specialized for " 57 | " floating-point (non-integer) types"); 58 | 59 | public: 60 | explicit LaplaceSolver(const carto::VolumeRef& classif); 61 | 62 | /** Initialize the output volume to a reasonable value 63 | * 64 | * 0 in CSF, 1 in white matter, 0.5 in the cortex 65 | */ 66 | void initialize_solution(); 67 | 68 | void SOR(Real absolute_precision, 69 | float typical_cortical_thickness); 70 | void clamp_to_range(Real min, Real max); 71 | void eliminate_extrema(); 72 | 73 | carto::VolumeRef solution() const; 74 | 75 | static Real best_precision() { 76 | return 11 * std::numeric_limits::epsilon(); 77 | } 78 | 79 | void set_verbosity(const int verbosity) { 80 | m_verbosity = verbosity; 81 | } 82 | 83 | private: 84 | static const int s_border_width = 1; 85 | 86 | const carto::VolumeRef m_classif; 87 | carto::VolumeRef m_solution; 88 | int m_verbosity; 89 | }; 90 | 91 | } // namespace yl 92 | 93 | #endif // !defined(LAPLACE_SOLVER_HH_INCLUDED) 94 | -------------------------------------------------------------------------------- /src/library/propagate_along_field.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright CEA (2014). 3 | Copyright Université Paris XI (2014). 4 | 5 | Contributor: Yann Leprince . 6 | 7 | This file is part of highres-cortex, a collection of software designed 8 | to process high-resolution magnetic resonance images of the cerebral 9 | cortex. 10 | 11 | This software is governed by the CeCILL licence under French law and 12 | abiding by the rules of distribution of free software. You can use, 13 | modify and/or redistribute the software under the terms of the CeCILL 14 | licence as circulated by CEA, CNRS and INRIA at the following URL: 15 | . 16 | 17 | As a counterpart to the access to the source code and rights to copy, 18 | modify and redistribute granted by the licence, users are provided only 19 | with a limited warranty and the software's author, the holder of the 20 | economic rights, and the successive licensors have only limited 21 | liability. 22 | 23 | In this respect, the user's attention is drawn to the risks associated 24 | with loading, using, modifying and/or developing or reproducing the 25 | software by the user in light of its specific status of scientific 26 | software, that may mean that it is complicated to manipulate, and that 27 | also therefore means that it is reserved for developers and experienced 28 | professionals having in-depth computer knowledge. Users are therefore 29 | encouraged to load and test the software's suitability as regards their 30 | requirements in conditions enabling the security of their systems and/or 31 | data to be ensured and, more generally, to use and operate it in the 32 | same conditions as regards security. 33 | 34 | The fact that you are presently reading this means that you have had 35 | knowledge of the CeCILL licence and that you accept its terms. 36 | */ 37 | 38 | #include "propagate_along_field.hh" 39 | 40 | #include 41 | #include 42 | 43 | #include 44 | 45 | using carto::VolumeRef; 46 | using std::clog; 47 | using std::endl; 48 | using boost::shared_ptr; 49 | using boost::make_shared; 50 | 51 | 52 | const float yl::PropagateAlongField::default_step = 0.03f; 53 | const unsigned int yl::PropagateAlongField::default_max_iter = 1000; 54 | 55 | yl::PropagateAlongField:: 56 | PropagateAlongField(const shared_ptr& vector_field) 57 | : m_vector_field(vector_field), 58 | m_max_iter(default_max_iter), m_step(default_step), m_verbose(debug_output) 59 | { 60 | } 61 | 62 | yl::PropagateAlongField:: 63 | PropagateAlongField(const VolumeRef& fieldx, 64 | const VolumeRef& fieldy, 65 | const VolumeRef& fieldz) 66 | : m_vector_field(make_shared(fieldx, 67 | fieldy, 68 | fieldz)), 69 | m_max_iter(default_max_iter), m_step(default_step), m_verbose(debug_output) 70 | { 71 | } 72 | 73 | yl::PropagateAlongField::~PropagateAlongField() 74 | { 75 | } 76 | 77 | void 78 | yl::PropagateAlongField::setVerbose(int verbosity) 79 | { 80 | m_verbose = verbosity; 81 | } 82 | 83 | void 84 | yl::PropagateAlongField::setStep(float step) 85 | { 86 | m_step = step; 87 | } 88 | 89 | void 90 | yl::PropagateAlongField::setMaxIter(unsigned int max_iter) 91 | { 92 | m_max_iter = max_iter; 93 | } 94 | 95 | 96 | #include "propagate_along_field.tcc" 97 | 98 | template 99 | int16_t yl::PropagateAlongField::ascend_until_nonzero( 100 | const Point3df &start_point, 101 | const carto::VolumeRef &seeds, 102 | int16_t ignore_label 103 | ) const; 104 | template 105 | carto::VolumeRef 106 | yl::PropagateAlongField::propagate_regions( 107 | const carto::VolumeRef &seeds, 108 | int16_t target_label 109 | ) const; 110 | template 111 | std::pair, carto::VolumeRef > 112 | yl::PropagateAlongField::propagate_regions_keeping_dests( 113 | const carto::VolumeRef &seeds, 114 | int16_t target_label 115 | ) const; 116 | 117 | template 118 | int32_t yl::PropagateAlongField::ascend_until_nonzero( 119 | const Point3df &start_point, 120 | const carto::VolumeRef &seeds, 121 | int32_t ignore_label 122 | ) const; 123 | template 124 | carto::VolumeRef 125 | yl::PropagateAlongField::propagate_regions( 126 | const carto::VolumeRef &seeds, 127 | int32_t target_label 128 | ) const; 129 | template 130 | std::pair, carto::VolumeRef > 131 | yl::PropagateAlongField::propagate_regions_keeping_dests( 132 | const carto::VolumeRef &seeds, 133 | int32_t target_label 134 | ) const; 135 | -------------------------------------------------------------------------------- /src/library/upwinding.hh: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Télécom ParisTech (2015). 3 | 4 | Contributor: Yann Leprince . 5 | 6 | This file is part of highres-cortex, a collection of software designed 7 | to process high-resolution magnetic resonance images of the cerebral 8 | cortex. 9 | 10 | This software is governed by the CeCILL licence under French law and 11 | abiding by the rules of distribution of free software. You can use, 12 | modify and/or redistribute the software under the terms of the CeCILL 13 | licence as circulated by CEA, CNRS and INRIA at the following URL: 14 | . 15 | 16 | As a counterpart to the access to the source code and rights to copy, 17 | modify and redistribute granted by the licence, users are provided only 18 | with a limited warranty and the software's author, the holder of the 19 | economic rights, and the successive licensors have only limited 20 | liability. 21 | 22 | In this respect, the user's attention is drawn to the risks associated 23 | with loading, using, modifying and/or developing or reproducing the 24 | software by the user in light of its specific status of scientific 25 | software, that may mean that it is complicated to manipulate, and that 26 | also therefore means that it is reserved for developers and experienced 27 | professionals having in-depth computer knowledge. Users are therefore 28 | encouraged to load and test the software's suitability as regards their 29 | requirements in conditions enabling the security of their systems and/or 30 | data to be ensured and, more generally, to use and operate it in the 31 | same conditions as regards security. 32 | 33 | The fact that you are presently reading this means that you have had 34 | knowledge of the CeCILL licence and that you accept its terms. 35 | */ 36 | 37 | #ifndef UPWINDING_HH_INCLUDED 38 | #define UPWINDING_HH_INCLUDED 39 | 40 | #include 41 | 42 | #include "front.hh" 43 | 44 | namespace yl 45 | { 46 | 47 | /** Compute the distance along the gradient of a scalar field. 48 | * 49 | * In the object defined by \p domain_label, the distance \f$d\f$ to \p 50 | * origin_label is computed along the field lines of the gradient of \p 51 | * upwind_field (\f$T\f$). This is done by integrating the following equation 52 | * in a single sweep through the domain, using an upwinding condition on 53 | * \f$T\f$: 54 | * 55 | * \f[ 56 | * \nabla d \cdot \frac{\nabla T}{\|\nabla T\|} = 1 57 | * \f] 58 | * 59 | * The \p domain image will be modified in-place for keeping track of the front 60 | * (\p front_label) and visited voxels (\p done_label). 61 | * 62 | * Preconditions: 63 | * \arg \p upwind_field must have at least a 1-voxel border, which must be 64 | * filled with \e NaN 65 | * \arg \p domain must have at least a 1-voxel border, which will must not 66 | * contain \p domain_label 67 | * \arg \p domain_label, \p origin_label, \p done_label, and \p front_label 68 | * must all have different values (except \p origin_label and \p done_label 69 | * can be equal) 70 | */ 71 | carto::VolumeRef 72 | upwind_distance(const carto::VolumeRef& upwind_field, 73 | carto::VolumeRef domain, 74 | int16_t domain_label, 75 | int16_t origin_label, 76 | int16_t done_label = DEFAULT_DONE_LABEL, 77 | int16_t front_label = DEFAULT_FRONT_LABEL, 78 | int verbosity = 0); 79 | 80 | } // namespace yl 81 | 82 | #endif // !defined(UPWINDING_HH_INCLUDED) 83 | -------------------------------------------------------------------------------- /src/library/volume_util.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Télécom ParisTech (2015). 3 | 4 | Contributor: Yann Leprince . 5 | 6 | This file is part of highres-cortex, a collection of software designed 7 | to process high-resolution magnetic resonance images of the cerebral 8 | cortex. 9 | 10 | This software is governed by the CeCILL licence under French law and 11 | abiding by the rules of distribution of free software. You can use, 12 | modify and/or redistribute the software under the terms of the CeCILL 13 | licence as circulated by CEA, CNRS and INRIA at the following URL: 14 | . 15 | 16 | As a counterpart to the access to the source code and rights to copy, 17 | modify and redistribute granted by the licence, users are provided only 18 | with a limited warranty and the software's author, the holder of the 19 | economic rights, and the successive licensors have only limited 20 | liability. 21 | 22 | In this respect, the user's attention is drawn to the risks associated 23 | with loading, using, modifying and/or developing or reproducing the 24 | software by the user in light of its specific status of scientific 25 | software, that may mean that it is complicated to manipulate, and that 26 | also therefore means that it is reserved for developers and experienced 27 | professionals having in-depth computer knowledge. Users are therefore 28 | encouraged to load and test the software's suitability as regards their 29 | requirements in conditions enabling the security of their systems and/or 30 | data to be ensured and, more generally, to use and operate it in the 31 | same conditions as regards security. 32 | 33 | The fact that you are presently reading this means that you have had 34 | knowledge of the CeCILL licence and that you accept its terms. 35 | */ 36 | 37 | #include "volume_util.hh" 38 | 39 | #include 40 | #include 41 | 42 | int 43 | yl::xyz_min_border(const std::vector& borders) 44 | { 45 | std::vector::const_iterator it = 46 | std::min_element(borders.begin(), borders.begin() + 6); 47 | return *it; 48 | } 49 | 50 | #include "volume_util.tcc" 51 | 52 | template int yl::xyz_min_border(const carto::VolumeRef&); 53 | template int yl::xyz_min_border(const carto::VolumeRef&); 54 | -------------------------------------------------------------------------------- /src/library/volume_util.hh: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Télécom ParisTech (2015). 3 | 4 | Contributor: Yann Leprince . 5 | 6 | This file is part of highres-cortex, a collection of software designed 7 | to process high-resolution magnetic resonance images of the cerebral 8 | cortex. 9 | 10 | This software is governed by the CeCILL licence under French law and 11 | abiding by the rules of distribution of free software. You can use, 12 | modify and/or redistribute the software under the terms of the CeCILL 13 | licence as circulated by CEA, CNRS and INRIA at the following URL: 14 | . 15 | 16 | As a counterpart to the access to the source code and rights to copy, 17 | modify and redistribute granted by the licence, users are provided only 18 | with a limited warranty and the software's author, the holder of the 19 | economic rights, and the successive licensors have only limited 20 | liability. 21 | 22 | In this respect, the user's attention is drawn to the risks associated 23 | with loading, using, modifying and/or developing or reproducing the 24 | software by the user in light of its specific status of scientific 25 | software, that may mean that it is complicated to manipulate, and that 26 | also therefore means that it is reserved for developers and experienced 27 | professionals having in-depth computer knowledge. Users are therefore 28 | encouraged to load and test the software's suitability as regards their 29 | requirements in conditions enabling the security of their systems and/or 30 | data to be ensured and, more generally, to use and operate it in the 31 | same conditions as regards security. 32 | 33 | The fact that you are presently reading this means that you have had 34 | knowledge of the CeCILL licence and that you accept its terms. 35 | */ 36 | 37 | #ifndef VOLUME_UTIL_HH_INCLUDED 38 | #define VOLUME_UTIL_HH_INCLUDED 39 | 40 | #include 41 | 42 | #include 43 | 44 | namespace yl 45 | { 46 | 47 | /** Minimum border width along X, Y, and Z dimensions 48 | * 49 | * Call this function like this, or use the overload xyz_min_border(const carto::VolumeRef&): 50 | * \code 51 | * yl::xyz_min_border(volume->getBorders()) 52 | * \endcode 53 | */ 54 | int xyz_min_border(const std::vector& borders); 55 | 56 | /** Minimum border width along X, Y, and Z dimensions */ 57 | template 58 | int xyz_min_border(const carto::VolumeRef& volume); 59 | 60 | template 61 | bool 62 | check_border_values(const carto::VolumeRef& volume, 63 | const Predicate& predicate); 64 | 65 | } // namespace yl 66 | 67 | #endif // !defined(VOLUME_UTIL_HH_INCLUDED) 68 | -------------------------------------------------------------------------------- /src/library/volume_util.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Télécom ParisTech (2015). 3 | 4 | Contributor: Yann Leprince . 5 | 6 | This file is part of highres-cortex, a collection of software designed 7 | to process high-resolution magnetic resonance images of the cerebral 8 | cortex. 9 | 10 | This software is governed by the CeCILL licence under French law and 11 | abiding by the rules of distribution of free software. You can use, 12 | modify and/or redistribute the software under the terms of the CeCILL 13 | licence as circulated by CEA, CNRS and INRIA at the following URL: 14 | . 15 | 16 | As a counterpart to the access to the source code and rights to copy, 17 | modify and redistribute granted by the licence, users are provided only 18 | with a limited warranty and the software's author, the holder of the 19 | economic rights, and the successive licensors have only limited 20 | liability. 21 | 22 | In this respect, the user's attention is drawn to the risks associated 23 | with loading, using, modifying and/or developing or reproducing the 24 | software by the user in light of its specific status of scientific 25 | software, that may mean that it is complicated to manipulate, and that 26 | also therefore means that it is reserved for developers and experienced 27 | professionals having in-depth computer knowledge. Users are therefore 28 | encouraged to load and test the software's suitability as regards their 29 | requirements in conditions enabling the security of their systems and/or 30 | data to be ensured and, more generally, to use and operate it in the 31 | same conditions as regards security. 32 | 33 | The fact that you are presently reading this means that you have had 34 | knowledge of the CeCILL licence and that you accept its terms. 35 | */ 36 | 37 | template 38 | bool 39 | yl::check_border_values(const carto::VolumeRef& volume, 40 | const Predicate& predicate) 41 | { 42 | const std::vector borders = volume->getBorders(); 43 | 44 | // z min-border 45 | for(int z = -borders[4]; z < 0; ++z) 46 | for(int y = -borders[2]; y < volume->getSizeY() + borders[3]; ++y) 47 | for(int x = -borders[0]; x < volume->getSizeX() + borders[1]; ++x) 48 | if(!predicate(volume(x, y, z))) 49 | return false; 50 | 51 | // z max-border 52 | for(int z = volume->getSizeZ(); z < volume->getSizeZ() + borders[5]; ++z) 53 | for(int y = -borders[2]; y < volume->getSizeY() + borders[3]; ++y) 54 | for(int x = -borders[0]; x < volume->getSizeX() + borders[1]; ++x) 55 | if(!predicate(volume(x, y, z))) 56 | return false; 57 | 58 | // y min-border 59 | for(int z = 0; z < volume->getSizeZ(); ++z) 60 | for(int y = -borders[2]; y < 0; ++y) 61 | for(int x = -borders[0]; x < volume->getSizeX() + borders[1]; ++x) 62 | if(!predicate(volume(x, y, z))) 63 | return false; 64 | 65 | // y max-border 66 | for(int z = 0; z < volume->getSizeZ(); ++z) 67 | for(int y = volume->getSizeY(); y < volume->getSizeY() + borders[3]; ++y) 68 | for(int x = -borders[0]; x < volume->getSizeX() + borders[1]; ++x) 69 | if(!predicate(volume(x, y, z))) 70 | return false; 71 | 72 | // x min-border 73 | for(int z = 0; z < volume->getSizeZ(); ++z) 74 | for(int y = 0; y < volume->getSizeY(); ++y) 75 | for(int x = -borders[0]; x < 0; ++x) 76 | if(!predicate(volume(x, y, z))) 77 | return false; 78 | 79 | // x max-border 80 | for(int z = 0; z < volume->getSizeZ(); ++z) 81 | for(int y = 0; y < volume->getSizeY(); ++y) 82 | for(int x = volume->getSizeX(); x < volume->getSizeX() + borders[1]; ++x) 83 | if(!predicate(volume(x, y, z))) 84 | return false; 85 | 86 | return true; 87 | } 88 | 89 | template 90 | int yl::xyz_min_border(const carto::VolumeRef& volume) 91 | { 92 | return xyz_min_border(volume->getBorders()); 93 | } 94 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright Forschungszentrum Jülich GmbH (2017, 2018). 2 | # 3 | # Contributor: Yann Leprince . 4 | # 5 | # Copying and distribution of this file, with or without modification, 6 | # are permitted in any medium without royalty provided the copyright 7 | # notice and this notice are preserved. This file is offered as-is, 8 | # without any warranty. 9 | 10 | # Determine if we are compiling in the BrainVISA build tree. If not, set up 11 | # TEST_ENV to point to a wrapper script which sets the environment. 12 | file(RELATIVE_PATH 13 | PATH_TO_BRAINVISA_TREE 14 | "${CMAKE_BINARY_DIR}" 15 | "${AIMS-FREE_BINARY_DIR}" 16 | ) 17 | 18 | set(TEST_ENV "") 19 | if(NOT PATH_TO_BRAINVISA_TREE STREQUAL "") 20 | message(STATUS "Detected a build outside of the BrainVISA tree (PATH_TO_BRAINVISA_TREE=${PATH_TO_BRAINVISA_TREE}). Activating the test_env.sh wrapper.") 21 | if(WIN32) 22 | message(WARNING "Tests for ${PROJECT_NAME} will fail on Windows when building outside of the BrainVISA tree. You are welcome to contribute a test_env.bat wrapper.") 23 | else() 24 | configure_file(test_env.sh.in test_env.sh @ONLY) 25 | set(TEST_ENV "sh" "-e" "${CMAKE_CURRENT_BINARY_DIR}/test_env.sh") 26 | endif() 27 | endif() 28 | 29 | brainvisa_copy_files( 30 | ${PROJECT_NAME}-test 31 | test_all_scripts.sh run_all_scripts.sh 32 | DESTINATION "${REL_SHARE_DIR}/tests" 33 | ) 34 | 35 | # These tests need /bin/bash, exclude them from Windows cross-builds 36 | if(NOT WIN32) 37 | # We use an extra "sh -e" prefix here, because the test is called through 38 | # bv_env_test, which calls the *basename* of the first argument as the 39 | # command. Without this trick, the basename is "test_all_scripts.sh", which 40 | # cannot be found on the PATH. 41 | brainvisa_add_test( 42 | NAME highres_cortex_example_scripts 43 | COMMAND ${TEST_ENV} "sh" "-e" 44 | "${CMAKE_BINARY_DIR}/${REL_SHARE_DIR}/tests/test_all_scripts.sh" 45 | ) 46 | endif() 47 | 48 | brainvisa_add_test( 49 | NAME highres_cortex_capsul 50 | COMMAND ${TEST_ENV} "${PYTHON_EXECUTABLE_NAME}" -m highres_cortex.test.test_capsul 51 | ) 52 | -------------------------------------------------------------------------------- /tests/bootstrap-docker/.gitignore: -------------------------------------------------------------------------------- 1 | /*/bootstrap_compile.sh 2 | -------------------------------------------------------------------------------- /tests/bootstrap-docker/casa-dev:ubuntu-12.04/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM cati/casa-dev:ubuntu-12.04 2 | 3 | COPY bootstrap_compile.sh / 4 | RUN /bootstrap_compile.sh 5 | RUN echo '. /root/brainvisa/build/bin/bv_env.sh /root/brainvisa/build' \ 6 | >> /root/.bashrc 7 | 8 | RUN cd /root/brainvisa/build && ctest --output-on-failure -R highres_cortex 9 | -------------------------------------------------------------------------------- /tests/bootstrap-docker/casa-dev:ubuntu-12.04/prepare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | cp -p ../../../bootstrap_compile.sh . 3 | echo "You can now run 'docker build .' from $PWD" 4 | -------------------------------------------------------------------------------- /tests/bootstrap-docker/ubuntu14.04/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04 2 | RUN apt-get -qq update 3 | 4 | COPY bootstrap_compile.sh / 5 | RUN /bootstrap_compile.sh 6 | RUN echo '. /root/brainvisa/build/bin/bv_env.sh /root/brainvisa/build' \ 7 | >> /root/.bashrc 8 | 9 | # delete all the apt list files since they're big and get stale quickly 10 | RUN rm -rf /var/lib/apt/lists/* 11 | 12 | RUN cd /root/brainvisa/build && ctest --output-on-failure -R highres_cortex 13 | -------------------------------------------------------------------------------- /tests/bootstrap-docker/ubuntu14.04/prepare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | cp -p ../../../bootstrap_compile.sh . 3 | echo "You can now run 'docker build .' from $PWD" 4 | -------------------------------------------------------------------------------- /tests/bootstrap-docker/ubuntu16.04/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | RUN apt-get -qq update 3 | 4 | COPY bootstrap_compile.sh / 5 | RUN /bootstrap_compile.sh 6 | RUN echo '. /root/brainvisa/build/bin/bv_env.sh /root/brainvisa/build' \ 7 | >> /root/.bashrc 8 | 9 | # delete all the apt list files since they're big and get stale quickly 10 | RUN rm -rf /var/lib/apt/lists/* 11 | 12 | RUN cd /root/brainvisa/build && ctest --output-on-failure -R highres_cortex 13 | -------------------------------------------------------------------------------- /tests/bootstrap-docker/ubuntu16.04/prepare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | cp -p ../../../bootstrap_compile.sh . 3 | echo "You can now run 'docker build .' from $PWD" 4 | -------------------------------------------------------------------------------- /tests/precision/cbs-post.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | 3 | cartoLinearComb.py -f '1-I1' \ 4 | -i CBS/Equivolumic/_layering.nii.gz \ 5 | -o CBS/Equivolumic/inverted_layering.nii.gz 6 | cartoLinearComb.py -f '1-I1' \ 7 | -i CBS/Equidistant/_layering.nii.gz \ 8 | -o CBS/Equidistant/inverted_layering.nii.gz 9 | -------------------------------------------------------------------------------- /tests/precision/cbs-pre.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | 3 | mkdir CBS 4 | mkdir CBS/Equidistant 5 | mkdir CBS/Equivolumic 6 | mkdir CBS/tmp 7 | 8 | layout_template=$(dirname "$0")/evaluate.LayoutXML.in 9 | sed -e "s~EVALUATION_DIR~${PWD}/CBS~g" \ 10 | < "$layout_template" > CBS/evaluate.LayoutXML 11 | 12 | AimsThreshold -b --fg 1 -m eq -t 200 \ 13 | -i classif.nii.gz -o CBS/white_proba.nii.gz 14 | AimsThreshold -b --fg 1 -m di -t 0 \ 15 | -i classif.nii.gz -o CBS/not_CSF_proba.nii.gz 16 | -------------------------------------------------------------------------------- /tests/run_all_scripts.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | 3 | : ${SCRIPTS_DIR:=$(dirname -- "$0")/../examples/scripts} 4 | [ -d "$SCRIPTS_DIR" ] || { 5 | echo "$0: cannot find the directory containing the scripts" >&2 6 | exit 1 7 | } 8 | 9 | run_script_in_subdir() { 10 | mkdir -p "$1" 11 | ( 12 | cd "$1" 13 | "$SCRIPTS_DIR"/"$1"/"$2" 14 | ) 15 | } 16 | 17 | run_script_in_subdir dist distmaps.sh 18 | run_script_in_subdir heat heat.sh 19 | run_script_in_subdir laplace-euclidean laplace-euclidean.sh 20 | run_script_in_subdir upwind-euclidean upwind-euclidean.sh 21 | run_script_in_subdir isovolume isovolume.sh 22 | run_script_in_subdir column-regions column-regions.sh 23 | -------------------------------------------------------------------------------- /tests/test_all_scripts.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | # 3 | # Copyright Forschungszentrum Jülich GmbH (2017). 4 | # 5 | # Contributor: Yann Leprince . 6 | # 7 | # Copying and distribution of this file, with or without modification, 8 | # are permitted in any medium without royalty provided the copyright 9 | # notice and this notice are preserved. This file is offered as-is, 10 | # without any warranty. 11 | 12 | test_dir=$(dirname -- "$0") 13 | [ -f "$test_dir/run_all_scripts.sh" ] || { 14 | echo "$0: cannot find the directory containing run_all_scripts.sh" >&2 15 | exit 1 16 | } 17 | 18 | # Create a temporary directory, make sure that it will be deleted on exit 19 | tmpdir= 20 | cleanup() { 21 | rm -rf "$tmpdir" 22 | } 23 | trap cleanup EXIT 24 | trap 'cleanup; trap - HUP EXIT; kill -HUP $$' HUP 25 | trap 'cleanup; trap - INT EXIT; kill -INT $$' INT 26 | trap 'cleanup; trap - TERM EXIT; kill -TERM $$' TERM 27 | trap 'trap - QUIT EXIT; kill -QUIT $$' QUIT 28 | tmpdir=$(mktemp -d -t hrcortex_XXXX) 29 | 30 | # The Python interpreter below is called through bv_env in order to 31 | # restore the values of the environment variables DYLD_LIBRARY_PATH 32 | # and friends on Mac OS 10.11+, which are not inherited by the shell 33 | # interpreter because it is protected (it resides in the protected 34 | # directory /bin). 35 | BV_ENV=$(which bv_env || echo "") 36 | # (if bv_env is not found, like in a conda install, then it will just not 37 | # be used) 38 | 39 | cd -- "$tmpdir" 40 | $BV_ENV python -m highres_cortex.test.synthetic_data 5 3 0.3 41 | "$test_dir"/run_all_scripts.sh 42 | 43 | $BV_ENV python - <. 4 | # 5 | # Copying and distribution of this file, with or without modification, 6 | # are permitted in any medium without royalty provided the copyright 7 | # notice and this notice are preserved. This file is offered as-is, 8 | # without any warranty. 9 | 10 | # Run the command passed as argument within a suitable environment 11 | 12 | if [ -z "$BRAINVISA_PACKAGE_INSTALL_PREFIX" ]; then 13 | # Paths specific to highres-cortex (needed for out-of-tree build) 14 | export PATH="@CMAKE_RUNTIME_OUTPUT_DIRECTORY@:$PATH" 15 | export LD_LIBRARY_PATH="@CMAKE_LIBRARY_OUTPUT_DIRECTORY@:$LD_LIBRARY_PATH" 16 | export PYTHONPATH="@CMAKE_BINARY_DIR@/python:$PYTHONPATH" 17 | fi 18 | 19 | "$@" 20 | --------------------------------------------------------------------------------