Developer ========= Below are a few introductory notes for anyone who wants to compile QUIT from source or might be interested in contributing to QUIT. Although I hope that most QUIT code is fairly clear, the following is provided to give a high-level overview of how most QUIT commands are structured. Basic Requirements ------------------ 1. A C++17 compliant compiler (GCC 7.0.0+, Clang 3.9+) 2. CMake version 3.10.2 or higher (http://www.cmake.org) WARNING - You will require a recent compiler for QUIT as it uses C++17 features. On Mac simply having the most recent software updates is enough, on Linux you will need GCC 7.0.0. No one has been brave enough to compile QUIT on Windows to date. External Libraries ------------------ QUIT is built using several C++ libraries. These are currently included in the project as git submodules. The easiest way to initialise these is with the ``bootstrap.sh`` script. However, if you are already have some of them available you may wish to not run the script and instead configure them yourself. This is discussed further below. The libraries are: - `Eigen `_ A high performace linear algebra library. Used for all signal equations in QUIT. - `Ceres `_ A high performace, high quality collection of non-linear least squares solvers. - `ITK `_ The Insight Tool-Kit. This is intended as a registration library for medical images. Although the registration features are not used in QUIT, the overall framework is extremely useful. In particular, ITK reads a large variety of common file-formats, and all ITK filters automatically check that their inputs share a common space / co-ordinate definition. This single feature alone prevents the vast majority of easy user mistakes - e.g. trying to use a B1 map that has a different voxel spacing to the input data. Compilation ----------- If you are unfamiliar with C++/CMake/git etc. a script is provided that should be able to build the tools provided the right software is available on your system. To use it, in a terminal window, change directory to where you unpacked QUIT. Then type ``./bootstrap.sh``. This should correctly checkout the git repositories for each external library, build Ceres and ITK, and then configure and build QUIT. CMake projects separate the ``build`` and ``install`` phases. The binaries are only moved to a single folder during ``install``. By default, the install directory is ``/usr/local/bin``. If you run ``./bootstrap.sh -i``it will run the install step to this directory. You can also ``cd`` into the ``build/`` directory and then type ``make install`` (or ``ninja install``) to avoid re-running the entire ``bootstrap.sh`` script. If you want to change where the binaries are installed, you can either: - Run ``./bootstrap.sh -i -p /path/to/install`` - ``cd /build; ccmake ./``, change the ``INSTALL_PREFIX_DIR``, configure (press c), generate (press g), exit, then ``make install`` Note that the binaries will end up in ``/bin`` inside the install prefix. If you are familiar with C++/CMake/git etc. then compiling QUIT should be straightforward. The rough steps are: 1. Ensure you have all the libraries above available. If you do not have system versions, then run ``git submodule init; git submodule update`` in the QUIT directory. 2. Compile the Ceres library. Make sure it uses the same version of Eigen that you will use for QUIT. 3. Compile ITK following their instructions. 4. Create a build directory for QUIT and use cmake/ccmake to configure the project. Specify the paths to the library when prompted. It is likely that CMake will report an error on the first 'Configure' attempt if it cannot locate Eigen, specify the correct directory and run the configure step again. 5. Compile QUIT. File Formats ------------ The available file formats are controlled by the main ``CMakeLists.txt`` in the root QUIT directory, by listing them as ``COMPONENTS`` in the ITK ``find_package()`` step. Add any additional file formats you wish to use here. Tests ----- QUIT commands are tested using the ``nipype`` wrappers and ``unittest``. To run the tests, first build and install ``QUIT`` (so that the executables are available in your ``$PATH`` variable), then ``cd`` into ``Python/Tests`` and then run ``python -m unittest discover``, which will run all of the tests. It is possible to run the test files individually as well. Most QUIT commands are tested by generating ground-truth parameter files with ``qi newimage``, feeding these into each ``QUIT`` command with the ``--simulate`` argument to generate simulated MR images with added noise, and then running them back through the ``QUIT`` command to calculate the parameter maps, and comparing these to the ground-truth with ``qi diff``. ``qi diff`` calculates a figure-of-merit based on noise factors, i.e. they are a measure of how much the signal noise is amplified in the final maps. In this way the tests also serve to illustrate the quality of the methods as well as whether the commands run correctly. For commands where a ground-truth image cannot be generated easily, the tests at least ensure that the command runs and does not crash. The ModelFitFilter ------------------ The core part of QUIT is the ``ModelFitFilter`` and its dependent type ``FitFunction``, found in ``Source/Core/``. This is a sub-class of the ITK ``ImageToImageFilter``. The vast majority of QUIT commands declare an `Model` and `FitFunction` sub-class and use these to process the data. ``ModelFitFilter`` abstracts out most of the heavy lifting of extracting voxel-wise data from multiple inputs and writing it out to multiple outputs, leaving the ``FitFunction`` to process a single-voxel. A ``Model`` defines the number of expected inputs and their size, the number of fixed & varying parameters, and the number of outputs. Example: ``qi despot1`` ----------------------- The structure of ``qi despot1`` is similar to most QUIT commands, and is a good example of most features. At the start are the includes (obviously). After that several ``FitFunction`` subclasses are defined, as well as a Ceres cost-function. The Ceres documentation is excellent, so refer to that for more information. After all the ``FitFunction`` classes are defined, the main command body begins. At the start of the command, all the command-line options are defined and then parsed. Then the various inputs are read and passed to the ``ModelFitFilter``, which is then updated. Finally, the outputs are written back to disk.