Quick Start
This page runs a first feature extraction, and explains the result.
What Is Radiomics?
Radiomics computes numbers (features) from medical images: for example the mean intensity, the shape and the texture of a region (Kolossváry et al., J Thorac Imaging 2018;33(1):26-34). Statistical models and machine learning then use the features, for example to tell tissue types apart.
You give Pictologics an image and a mask of the region of interest (ROI). Pictologics gives the features, as the Image Biomarker Standardisation Initiative (IBSI) defines them.
A First Run
from pictologics import RadiomicsPipeline, format_results, save_results
pipeline = RadiomicsPipeline(load_standard=False)
pipeline.add_config("my_analysis", [
{"step": "resample", "params": {"new_spacing": (1.0, 1.0, 1.0)}},
{"step": "discretise", "params": {"method": "FBN", "n_bins": 32}},
{"step": "extract_features", "params": {"families": ["intensity", "morphology", "texture"]}},
])
results = pipeline.run(
image="ct_scan.nii.gz",
mask="segmentation.nii.gz",
subject_id="patient_001",
config_names=["my_analysis"],
)
row = format_results(results, meta={"subject_id": "patient_001"})
save_results([row], "features.csv")
RadiomicsPipeline(load_standard=False)makes a pipeline without the six standard configurations.add_configadds a configuration: a named list of steps. The steps run in their order:resamplemakes all voxels 1 × 1 × 1 mm, so that images from other scanners compare.discretiseputs the intensities of the ROI into 32 bins. The texture features need this step.extract_featurescomputes the intensity, shape (morphology) and texture features.
runloads the image and the mask, and runs the configurations ofconfig_names. The mask goes onto the grid of the image.subject_idgoes into the processing log.format_resultsmakes one table row, andsave_resultswrites it to a CSV file.
The Result
results is a dictionary with one pandas.Series of features for each configuration:
| Feature key | Family | Description |
|---|---|---|
mean_intensity_Q4LE |
Intensity | The mean intensity of the ROI |
volume_RNU0 |
Morphology | The volume of the ROI, from its marching cubes surface |
sphericity_QCFX |
Morphology | How round the ROI is (1 for a sphere) |
joint_entropy_TU9B |
Texture (GLCM) | The entropy of the grey level co-occurrence matrix |
- IBSI codes: the last part of a feature key is its IBSI code, for example
Q4LEfor the mean intensity. The code identifies the feature in the IBSI reference manual. A number after the code tells the variant, for example_10involume_at_intensity_fraction_0.10_BC2M_10. - Complete rows: each configuration gives all its feature names. A feature that cannot be computed (for example because a step removed all ROI voxels) is
NaN. So the rows of many cases have the same columns. - Columns: in the CSV file, each column is
{configuration}__{feature}, for examplemy_analysis__mean_intensity_Q4LE.
Images and Masks
- The image holds the intensities, for example the CT values in Hounsfield units (HU).
- The mask (a segmentation) marks the ROI: 1 in the ROI, 0 outside. A mask can hold more labels, for example 1 for the liver and 2 for the spleen. Each voxel that is not 0 is in the ROI. To use one label, add a
binarize_maskstep, or run each label withrun_rois(see The Pipeline). - No mask: without a mask, the whole image is the ROI.
- File types: NIfTI, NRRD, MetaImage, DICOM folders and files, DICOM SEG and RTSTRUCT masks (see Data Loading).
Images with a Sentinel Value
Some images hold a fixed value, a sentinel value such as -2048, where they have no data: for example outside the field of view, or around a cropped lesion. A resampling or a filter near these voxels mixes the sentinel into the voxels with data. The source_mode of a configuration keeps them out:
pipeline.add_config(
"padded_ct",
[
{"step": "resample", "params": {"new_spacing": (1.0, 1.0, 1.0)}},
{"step": "resegment", "params": {"range_min": -100, "range_max": 3000, "apply_to": "both"}},
{"step": "extract_features", "params": {"families": ["intensity", "morphology"]}},
],
source_mode="auto",
sentinel_value=-2048, # the padding value of these images
)
results = pipeline.run("lesion_export.nii.gz", config_names=["padded_ct"]) # no mask
source_mode="auto"withsentinel_valuekeeps the voxels with the sentinel out of the resampling and the filters. After the resampling, these voxels are also out of the ROI.- Without
sentinel_value,"auto"looks for common sentinel values, and a warning gives the value that it found. - The
resegmentstep keeps the voxels in an intensity range. By default it changes the intensity mask only, as IBSI re-segmentation does, and the shape features keep the whole ROI. Here there is no mask, so the range is the segmentation:apply_to: bothmakes the shape features describe the voxels in the range too (see Two Masks).
See Source Modes and Sentinel Values for all modes.
The Steps
| Step | Does | Use it |
|---|---|---|
resample |
Gives all images the same voxel spacing | Almost always, so that the features compare |
resegment |
Keeps the ROI voxels in an intensity range, for example -100 to 400 HU | To remove other tissues or sentinel values |
filter_outliers |
Removes the ROI voxels far from the ROI mean | To remove noise or artefacts |
keep_largest_component |
Keeps the largest connected part of the ROI | When the mask has small loose parts |
grow_mask |
Grows or shrinks the mask, or keeps a ring at its edge (in mm) | For the tissue around a lesion or a vessel |
binarize_mask |
Selects labels of a mask | When the mask holds more structures |
normalise |
Normalises the intensities (z-score or percentiles) | For MR images and other images without fixed units |
discretise |
Puts the intensities into bins (FBN or FBS) | Before the texture features |
filter |
Applies an IBSI 2 filter (LoG, Gabor, wavelets and more) | For the features of filtered images |
extract_features |
Computes the features | As the last step |
See Pipeline Steps for the parameters of each step.
Ready-Made Configurations
RadiomicsPipeline() starts with six standard configurations: they resample to 0.5 mm and compute all feature families, with FBN (8, 16 or 32 bins) or FBS (bins of 8, 16 or 32 HU from -1000 HU, for CT).
from pictologics import RadiomicsPipeline
pipeline = RadiomicsPipeline()
results = pipeline.run("ct_scan.nii.gz", "segmentation.nii.gz", config_names=["standard_fbs_16"])
results = pipeline.run("ct_scan.nii.gz", "segmentation.nii.gz", config_names=["all_standard"]) # all six
coronary = RadiomicsPipeline.from_template("coronary") # 30 configurations for coronary plaque
print(coronary.list_configs())
Always give config_names: without it, run() runs every configuration of the pipeline, also the six standard ones, with a warning. See The Pipeline.
Next Steps
- Data Loading: DICOM series, NIfTI files, SEG and RTSTRUCT masks, PET in SUV.
- The Pipeline: configurations, masks, source modes, many ROIs and many cases.
- Pipeline Steps: each step and its parameters.
- Results and Logs: tables, the feature catalog and the processing log.
- Image Filtering: the IBSI 2 filters.
- Configuration & Reproducibility: save and share configurations.
- Cookbook and the tutorials: complete scripts for common tasks.