ANTsPy Documentation

repository·main·Indexed 21 days ago

https://github.com/antsx/antspy

A fast medical imaging analysis library in Python (package name antspyx) that serves as a wrapper for the ANTs (Advanced Normalization Tools) C++ framework. It provides high-performance tools for biomedical image processing, including registration, segmentation (via ants.atropos), N4 bias field correction, and visualization. The library includes specialized utilities for deep learning preprocessing such as image patching, cropping, padding, and data augmentation, and supports seamless conversion between ANTs images and NumPy arrays.

Tokens
20K
Snippets
55
Records
88
Agent score
72%

What's inside ANTsPy

  1. Perform segmentation using ANTsPy

    main

    ANTsPy provides several specialized segmentation algorithms within the ants module. Depending on your data and requirements, you can use different approaches:

    • Atropos: A multi-atlas segmentation tool.
    • Joint Label Fusion: Combines multiple segmentations into a single consensus segmentation.
    • Kelly Kapowski: A specific segmentation method (likely for brain structures).
    • K-means Segmentation: Standard unsupervised clustering-based segmentation.
    • Fuzzy Spatial C-means Segmentation: A fuzzy clustering approach that accounts for spatial information.
    • Prior-based Segmentation: Uses anatomical priors to guide the segmentation process.

    All these functions are accessible via the ants namespace.

  2. Identify ANTsPy Data Classes

    main

    ANTsPy uses specific S4 classes to manage complex data structures. Understanding these is essential for interacting with the API correctly:

    • antsImage-class: Represents an image.
    • antsMatrix-class: An S4 class used to hold an antsMatrix imported from ITK types.
    • antsRegion-class: An S4 class used to hold a region of an antsImage.
  3. Naming conventions in ANTsPy

    main

    ANTsPy follows Pythonic naming conventions, diverging from the original ANTsR (R) versions in two main ways:

    1. Snake Case: Camel case used in ANTsR is converted to underscore case (e.g., resampleImage becomes resample_image).
    2. Namespace usage: Prefixes like ants or antsr are removed from function names because they are accessed via the ants namespace (e.g., antsImageRead becomes ants.image_read).
  4. Quickstart: Basic ANTsPy operations

    main

    This example demonstrates the core workflow in ANTsPy, including image I/O, basic arithmetic, advanced processing, NumPy conversion, segmentation, registration, and plotting.

    import ants
    
    # read / write images
    img = ants.image_read('path/to/image.nii.gz')
    ants.image_write(img, 'path/to/image.nii.gz')
    
    # basic operations
    img + img2
    img - img2
    img[:20,:20,:20] # indexing returns an image
    
    # advanced operations
    img = ants.smooth_image(img, 2)
    img = ants.resample_image(img, (3,3,3))
    img.smooth_image(2).resample_image((3,3,3)) # chaining
    
    # convert to or from numpy
    arr = img.numpy()
    img2 = ants.from_numpy(arr * 2)
    
    # segmentation
    result = ants.atropos(a=img, m='[0.2,1x1]', c='[2,0]', i='kmeans[3]', x=ants.get_mask(img))
    
    # registration
    result = ants.registration(fixed_image, moving_image, type_of_transform = 'SyN' )
    
    # plotting
    ants.plot(img, overlay = img > img.mean())
  5. Set up an editable development installation

    main

    For active development of the Python codebase, use an 'editable' installation. This allows you to modify Python code without needing to reinstall the package.

    Note: This method will not recompile C++ code (ANTsPy, ANTs, or ITK). If you modify C++ files, you must recompile.

    git clone https://github.com/ANTsX/ANTsPy.git
    cd ANTsPy
    pip install -e .
  6. Build ANTsPy Docker images

    main

    Standard Docker builds are tested on Ubuntu Linux (amd64). For cross-platform builds targeting multiple architectures (e.g., amd64, ppc64le, arm64), use docker buildx with QEMU emulation.

    # Standard build for amd64
    cd ANTsPy
    docker build -t antspy:latest .
    
    # Cross-platform build using buildx
    # 1. Enable QEMU emulation
    docker run --rm --privileged aptman/qus -s -- -p ppc64le aarch64
    
    # 2. Create and use a buildx builder
    docker buildx create --name moc_builder --use
    
    # 3. Build for multiple platforms and push
    docker buildx build --pull --build-arg j=6 -t dockeruser/antspy:latest --platform linux/amd64,linux/ppc64le,linux/arm64 --push .
    
    # 4. Cleanup
    docker buildx rm
    docker run --rm --privileged aptman/qus -- -r
  7. Wrap C++ ITK functions for Python using pybind11

    main

    To wrap an existing ITK C++ function for use in Python, follow these steps to modify your C++ code:

    1. Change Argument Types: Convert input and output ImageType::Pointer arguments to py::capsule. These capsules hold the underlying ITK smartpointer.
    2. Add Headers: Include <pybind11/pybind11.h> and <pybind11/stl.h> for type casting, and #include "LOCAL_antsImage.h" to enable unwrapping/wrapping.
    3. Unwrap/Wrap Images:
      • Use as< ImageType >( antsImage ) to unwrap a py::capsule into an ITK smartpointer.
      • Use wrap< ImageType >( itkPointer ) to wrap an ITK smartpointer back into a py::capsule for return.
    4. Declare Module: Use the PYBIND11_MODULE macro to define your module and explicitly declare the function for each required image type (e.g., 2D float, 3D float).
    #include <pybind11/pybind11.h>
    #include <pybind11/stl.h>
    #include "itkImage.h"
    #include "itkRescaleIntensityImageFilter.h"
    #include "LOCAL_antsImage.h"
    
    namespace py = pybind11;
    
    template <typename ImageType>
    py::capsule rescaleAntsImage( py::capsule & antsImage, float outputMinimum, float outputMaximum )
    {
        // Unwrapping
        typename ImageType::Pointer itkImage = as< ImageType >( antsImage );
    
        typedef itk::RescaleIntensityImageFilter< ImageType, ImageType > RescaleFilterType;
        typename RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New();
        rescaleFilter->SetInput( itkImage );
        rescaleFilter->SetOutputMinimum( outputMinimum );
        rescaleFilter->SetOutputMaximum( outputMaximum );
        rescaleFilter->Update();
    
        // Wrapping
        return wrap< ImageType >( rescaleFilter->GetOutput() );
    }
    
    PYBIND11_MODULE(rescaleImageModule, m)
    {
        m.def("rescaleImageF2", &rescaleAntsImage<itk::Image<float,2>>);
        m.def("rescaleImageF3", &rescaleAntsImage<itk::Image<float,3>>);
    }
  8. Install ANTsPy from source

    main

    You can install ANTsPy by cloning the repository and using pip. You can install the current state of the repository, or target a specific version using a tag or commit hash.

    # Option 1: Clone and install locally
    git clone https://github.com/ANTsX/ANTsPy.git
    cd ANTsPy
    pip install .
    
    # Option 2: Install directly via git URL
    pip install git+https://github.com/ANTsX/ANTsPy.git
    
    # Option 3: Install a specific version (tag or commit hash)
    pip install git+https://github.com/ANTsX/ANTsPy.git@${antspyx_version}
  9. Install ANTsPy via pip or conda

    main

    The easiest way to install ANTsPy is using pre-compiled binaries.

    Using pip:

    pip install antspyx

    Using conda:

    conda install conda-forge::antspyx

    Note for macOS users: If you encounter compatibility issues where pip attempts to compile from source instead of using binaries, you can disable compatibility checks by setting the environment variable SYSTEM_VERSION_COMPAT=0.

    Note for Windows users: You must have a compatible Microsoft Visual C++ Redistributable installed.

  10. Create an abstract Python interface for C++ functions

    main

    To provide a clean API for end-users, wrap the low-level C++ module call in a Python function. This allows for argument checking and seamless integration with the ants namespace.

    Key steps:

    1. Use get_lib_fn to retrieve the function from the compiled module using the image's _libsuffix (e.g., rescaleAntsImageF3).
    2. Pass image.pointer to the library function.
    3. Convert the returned py::capsule back into an ants.ANTsImage using ants.from_pointer(rescaled_img_ptr).

    Example implementation:

    import ants
    
    def rescale_image(image, min_val, max_val):
        image = image.clone('float')
        # Retrieve function based on image dimensionality/suffix
        lib_fn = get_lib_fn('rescaleAntsImage%s' % (image._libsuffix))
        
        # Call C++ function
        rescaled_img_ptr = lib_fn(image.pointer, min_val, max_val)
    
        # Wrap capsule back to ANTsImage
        return ants.from_pointer(rescaled_img_ptr)
    import ants
    
    def rescale_image(image, min_val, max_val):
        image = image.clone('float')
    
        # get function from its name
        lib_fn = get_lib_fn('rescaleAntsImage%s' % (image._libsuffix))
    
        # apply the function to my image
        rescaled_img_ptr = lib_fn(image.pointer, min_val, max_val)
    
        # wrap the py::capsule back in ANTsImage class
        rescaled_img = ants.from_pointer(rescaled_img_ptr)
        return rescaled_img