Welcome to Pictologics

Pictologics is a Python library for radiomic feature extraction from medical images. It follows IBSI 1 (the features) and IBSI 2 (the filters), and it checks its results against the IBSI reference values.
See the NOTICE file for the attribution and the third-party libraries.
Why Pictologics?
- 🚀 Fast: Numba compiles the computations for your computer, and they run on its fast cores. The Benchmarks page gives the time of each part.
- ✅ IBSI compliant: checked against the IBSI phantoms and data sets:
- IBSI 1 (features): 675 feature values pass; 21 more have a reference value without a tolerance (report).
- IBSI 2 Phase 1 (filters): 28 of 28 compared tests pass (report).
- IBSI 2 Phase 2 (filtered features): 9 of 9 tests pass (report).
- IBSI 2 Phase 3 (reproducibility): 153 scans, compared with 9 teams (report).
- 🔧 Versatile: reads NIfTI, NRRD, MetaImage and DICOM images, DICOM SEG, DICOM RTSTRUCT and 3D Slicer segmentations, and DICOM SR reports.
- ✨ Easy to use: pip installs it. One pipeline runs the preprocessing and the features, for one image or for a whole study.
- 🛡️ Predictable results: each configuration gives all its feature columns, also when a step fails (the values are then
NaN). A study table never has missing columns. - 🛠️ Maintained: Pictologics is developed to give robust radiomic features that describe the morphology of diseases on radiological images.
What Is New in 1.0.0
Pictologics 1.0.0 is the first stable release. The code, the tests and the developer scripts are cleaned of old comments and dead code; the API does not change.
- Pipeline: a large float64 image is cut to the ROI region at the start of each configuration that reads only that region: on a 512×512×200 CT, a lesion run with outlier filtering, resegmentation and FBN takes 0.14 of the time, and
run_roiswith 20 ROIs 0.04. Agrow_maskstep withnearest_roiinrun_roisreads only the box of the grown mask (0.12 s instead of 2.3 s for 20 ROIs).run_batchwrites each case record in one JSON pass. - Morphology: the surface area and the volume come from the corner cases of the marching cubes, without the mesh (0.53 to 0.71 of the time on cubes, the volume exact to rounding); the hull candidates take fewer sorts; the MVEE keeps the Mahalanobis value of each hull point (0.60 of the morphology time for a CT lesion).
- Textures: the NGTDM features come from one compiled kernel (1.7 µs instead of 19 µs a call); the GLCM sums the upper triangle; the zone fill checks only the later neighbours of a seed; the NGLDM counts in one vectorized loop; the threaded distance map and grey-level volume write every voxel in the threads.
- Intensity: the first-order family takes the mean, the minimum, the maximum and the energy from one pass (0.53 of the time for 20 million values); the IVH counts whole values with no copy (0.42 to 0.63 of the time); Moran's I and Geary's C keep only the folded quarter of the kernel spectrum.
- Filters: the Laws and wavelet rotation-invariant averages add in compiled kernels in threads (0.63 to 0.84 of the time); the FFT filters with a non-periodic boundary cut the padded border after each axis (0.83 to 0.89 of the memory or time).
- Files:
save_imagewrites int16 and uint16 images in 0.1 of the time; a.seg.nrrdlayer loads in 0.69 of the time;load_and_merge_imagesmerges stored-type masks with no relabelled copy (0.30 of the time); a single-file PET in SUV scales in place;load_segcopies only the slices of each segment. - Preprocessing:
discretise_imagewith a bool mask finds the ROI range in one pass (0.29 of the time);keep_largest_componentcounts its components in threads (0.72 of the time, 0.46 of the memory). - Fixes: a one-voxel image gives the texture features of a one-voxel ROI; a SEG with dimension index values from 0 loads its first frame into the first slice; information correlation 2 of a GLCM with independent grey levels is 0, not NaN; the IVH volume fractions keep a given range end (IBSI 4.3); the threaded level count handles infinite and huge values as the one-thread count does; the warm-up runs on two threads when one thread is set after numba started.
- Changes: the
resegmentandfilter_outlierssteps change the intensity mask only by default, as IBSI re-segmentation does (giveapply_to: bothfor the old behaviour; thelvandcoronarytemplates do). The IBSI compliance is the same. See the Changelog.
Key Features
- Loaders: NIfTI, NRRD, MetaImage and DICOM images (also compressed and multiframe DICOM, cardiac phases and PET in SUV), DICOM SEG, DICOM RTSTRUCT and 3D Slicer
.seg.nrrdmasks, and DICOM SR reports. - Preprocessing: resampling, resegmentation, outlier filtering, the largest component, mask growing and rings in mm, label selection, MR normalisation and discretisation (FBN, FBS and fixed cutoffs).
- Features: the IBSI 1 families: morphology, intensity statistics, intensity histogram, intensity-volume histogram (IVH), local and spatial intensity, and the texture matrices GLCM, GLRLM, GLSZM, GLDZM, NGTDM and NGLDM.
- Filters: the IBSI 2 filters: mean, Gaussian, Laplacian of Gaussian, Laws, Gabor, separable wavelets, Simoncelli and Riesz.
- Pipeline: named configurations of steps, many ROIs (
run_rois), many cases in parallel (run_batch), templates, and shared work between configurations. - Reproducibility: configurations as YAML or JSON files, a feature catalog (
describe_features), and a processing log with the configuration hash and the versions. - Utilities: a DICOM database of patients, studies and series, slice viewers for quality checks, and DICOM SR measurement tables.
A First Example
from pictologics import RadiomicsPipeline, format_results, save_results
pipeline = RadiomicsPipeline()
results = pipeline.run("ct.nii.gz", "lesion.nii.gz", subject_id="p001", config_names=["standard_fbs_16"])
save_results([format_results(results, meta={"subject_id": "p001"})], "features.csv")
Getting Started
- Install: see Installation.
- Run a first example: see the Quick Start.
- Learn the pipeline: see The Pipeline and Pipeline Steps.
- Find a script for your task: see the Cookbook and the tutorials.
- Look up a function: see the API Reference.