diff --git a/INSTALLATION.md b/INSTALLATION.md index 0dced7895..cb65c8a18 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -20,6 +20,25 @@ For RTK developpers, it may be useful to compile RTK independently from ITK. Thi * Manually download RTK's source repository from [GitHub](https://github.com/RTKConsortium/RTK) with `git` (recommended) or as a [zip package](https://codeload.github.com/RTKConsortium/RTK/zip/main). * Configure the project with CMake pointing to RTK's source directory and setting the CMake option `ITK_DIR` to ITK's compilation directory. All CMake options above can be set except `Module_RTK`. +#### Installing the Python wrapping into a Python environment +Configure and build RTK pointing `-DITK_DIR` to an ITK build tree with Python wrapping enabled (`ITK_WRAP_PYTHON=ON`) and, when using CUDA, `-DRTK_USE_CUDA=ON`. RTK's Python files are installed as plain copies by default. For local development, the optional `-DRTK_EDITABLE_PYTHON_PACKAGES=ON` (off by default) installs those files as symbolic links back to the RTK source tree instead, so edits to the Python scripts are picked up without reinstalling. + +The `itk` Python package is installed into the directory given by `-DPY_SITE_PACKAGES_PATH`; this destination is fixed at configure time. If left unset, ITK detects it automatically from the Python executable it finds. Set it explicitly to install into a self-contained folder as an alternative to a `site-packages` directory, then add that folder to `PYTHONPATH`. + +Then install RTK with `cmake --install build-dir --component RuntimeLibraries`. + +**Note**: unlike a wheel installed with `pip install itk-rtk`, this CMake install does not put the `rtk*` command-line applications (e.g. `rtkfdk`) on the `PATH`. Run them with `python -m itk.rtkfdk` instead. + +[utilities/rtk_install_bindings.sh](https://github.com/RTKConsortium/RTK/blob/main/utilities/rtk_install_bindings.sh) builds ITK from source with RTK as a local remote module and installs the bindings into a self-contained folder; edit the configuration variables at the top of the script, then run it. After it finishes, add the install folder to your `PYTHONPATH` for the current session, or permanently in your shell profile: +``` +export PYTHONPATH=/path/to/bindings:$PYTHONPATH +``` +Then run the RTK applications as Python modules, e.g.: +``` +python3 -m itk.rtkfdk -g geometry.xml --path . --regexp '*.mha' -o output.mha +``` + + ## Python pre-compiled binaries We only provide pre-compiled binaries for the Python package which depends on ITK. Use the following commands to install the RTK module with `pip`. ``` diff --git a/utilities/rtk_install_bindings.sh b/utilities/rtk_install_bindings.sh new file mode 100755 index 000000000..d13596d04 --- /dev/null +++ b/utilities/rtk_install_bindings.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +# Build ITK with RTK as a remote module and install the Python bindings into a +# self-contained folder usable via PYTHONPATH. +# Edit the configuration variables below, then run it. + +exec > >(tee "$(basename "$0" .sh).log") +exec 2> >(tee "$(basename "$0" .sh).err" >&2) + +set -e +set -x + +# ==================== Config (edit these) ==================== +ITK_SRC=/path/to/ITK +RTK_SRC=/path/to/RTK +DEST_DIR=/path/to/bindings +NTHREADS=${NTHREADS:-24} +RTK_USE_CUDA=OFF +EDITABLE=OFF # symlink the RTK Python files back to $RTK_SRC +# ============================================================= + +BUILD_DIR=PythonWrapping +INSTALL_PATH=${BUILD_DIR}-install + +echo "ITK source: $ITK_SRC" +echo "RTK source: $RTK_SRC" +echo "Install folder: $DEST_DIR" +echo "Editable: $EDITABLE" +echo "RTK_USE_CUDA: $RTK_USE_CUDA" + +mkdir -p "$ITK_SRC/Modules/Remote" +ln -sfn "$RTK_SRC" "$ITK_SRC/Modules/Remote/RTK" + +CMAKE_EXTRA= +if [ "$RTK_USE_CUDA" = "ON" ]; then + CMAKE_EXTRA=-DModule_CudaCommon:BOOL=ON +fi + +mkdir -p "$BUILD_DIR" "$DEST_DIR" + +cmake "$ITK_SRC" \ + -B"$BUILD_DIR" \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DBUILD_EXAMPLES=OFF \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_TESTING=OFF \ + -DITK_BUILD_DEFAULT_MODULES=ON \ + -DITK_WRAP_PYTHON=ON \ + -DCMAKE_INSTALL_PREFIX="$INSTALL_PATH" \ + -DPY_SITE_PACKAGES_PATH:STRING="$DEST_DIR" \ + -DITK_WRAP_unsigned_short:BOOL=ON \ + -DITK_WRAP_double:BOOL=ON \ + -DITK_WRAP_complex_double:BOOL=ON \ + -DITK_WRAP_IMAGE_DIMS:STRING="2;3;4" \ + -DModule_RTK:BOOL=ON \ + -DModule_RTK_GIT_TAG:STRING="" \ + -DRTK_USE_CUDA:BOOL="$RTK_USE_CUDA" \ + -DRTK_BUILD_APPLICATIONS:BOOL=OFF \ + -DRTK_EDITABLE_PYTHON_PACKAGES:BOOL="$EDITABLE" \ + $CMAKE_EXTRA + +cmake --build "$BUILD_DIR" --parallel "$NTHREADS" -- -k +cmake --install "$BUILD_DIR" + +echo "Done. Export $DEST_DIR for this session, or add it permanently to your shell profile:" +echo " export PYTHONPATH=$DEST_DIR:\$PYTHONPATH" +echo "Then run the RTK applications as Python modules, e.g.:" +echo " python3 -m itk.rtkfdk -g geometry.xml --path . --regexp *.mha -o output.mha" diff --git a/wrapping/CMakeLists.txt b/wrapping/CMakeLists.txt index 9a25c21c5..370a259d9 100644 --- a/wrapping/CMakeLists.txt +++ b/wrapping/CMakeLists.txt @@ -48,11 +48,45 @@ file( "${RTK_SOURCE_DIR}/applications/rtk*/rtk*.py" ) -wrap_itk_python_bindings_install(/itk "RTK" - __init_rtk__.py +set( + RTK_PYTHON_FILES + "${RTK_SOURCE_DIR}/wrapping/__init_rtk__.py" ${RTK_GROUP_SCRIPTS} ${RTK_APP_SCRIPTS} - ${RTK_BINARY_DIR}/Wrapping/Generators/Python/rtkConfig.py - ${RTK_SOURCE_DIR}/wrapping/rtkExtras.py - ${RTK_SOURCE_DIR}/applications/rtkargumentparser.py + "${RTK_BINARY_DIR}/Wrapping/Generators/Python/rtkConfig.py" + "${RTK_SOURCE_DIR}/wrapping/rtkExtras.py" + "${RTK_SOURCE_DIR}/applications/rtkargumentparser.py" ) + +# Editable dev mode: install the Python files above as symbolic links back to +# the source tree instead of copies, so edits are picked up without +# reinstalling. Off by default: keep plain copies. +option( + RTK_EDITABLE_PYTHON_PACKAGES + "Install RTK Python scripts into the itk package as symbolic links (editable dev mode)." + OFF +) + +if(RTK_EDITABLE_PYTHON_PACKAGES) + set(_rtk_editable_dir "${RTK_BINARY_DIR}/rtk_editable_python") + file(REMOVE_RECURSE "${_rtk_editable_dir}") + file(MAKE_DIRECTORY "${_rtk_editable_dir}") + foreach(_rtk_src IN LISTS RTK_PYTHON_FILES) + get_filename_component(_rtk_name "${_rtk_src}" NAME) + file( + CREATE_LINK + "${_rtk_src}" + "${_rtk_editable_dir}/${_rtk_name}" + SYMBOLIC + COPY_ON_ERROR + ) + endforeach() + install( + DIRECTORY + "${_rtk_editable_dir}/" + DESTINATION "${PY_SITE_PACKAGES_PATH}/itk" + COMPONENT RuntimeLibraries + ) +else() + wrap_itk_python_bindings_install(/itk "RTK" ${RTK_PYTHON_FILES}) +endif()