Utilities¶
Image processing, the vertebra-labeling path solver, disc labeling and other helpers.
spineps.utils.proc_functions¶
spineps.utils.proc_functions
¶
Segmentation post-processing helpers: n4 bias correction, connected-component cleaning and instance fixes.
n4_bias
¶
n4_bias(
nii: NII,
threshold: int = 60,
spline_param: int = 100,
dtype2nii: bool = False,
norm: int = -1,
) -> tuple[NII, NII]
Apply N4 bias field correction to a NIfTI image.
Builds a foreground mask by thresholding (and filling its bounding box), runs N4 correction restricted to that mask, optionally rescales the result to a target maximum and optionally casts back to the input dtype.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
nii
|
NII
|
Input image to correct. |
required |
threshold
|
int
|
Intensity threshold for the foreground mask; voxels below it are excluded. Defaults to 60. |
60
|
spline_param
|
int
|
Spline distance parameter passed to the N4 correction. Defaults to 100. |
100
|
dtype2nii
|
bool
|
If True, cast the corrected image back to the input image's dtype. Defaults to False. |
False
|
norm
|
int
|
If not -1, rescale the corrected image so its maximum equals this value. Defaults to -1. |
-1
|
Returns:
| Type | Description |
|---|---|
tuple[NII, NII]
|
tuple[NII, NII]: The bias-corrected image and the binary foreground mask used for correction. |
Source code in spineps/utils/proc_functions.py
clean_cc_artifacts
¶
clean_cc_artifacts(
mask: NII | ndarray,
logger: Logger_Interface,
labels: list[int] = [1, 2, 3],
cc_size_threshold: int | list[int] = 100,
neighbor_factor_2_delete: float = 0.1,
verbose: bool = True,
only_delete: bool = False,
ignore_missing_labels: bool = False,
) -> np.ndarray
Clean small connected-component artifacts in a segmentation mask.
For each requested label, finds connected components below the size threshold and either deletes them or, if they border enough other foreground voxels, relabels them by majority vote of their dilated neighborhood.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mask
|
NII | ndarray
|
Input segmentation mask. |
required |
logger
|
Logger_Interface
|
Logger for progress and cleaning reports. |
required |
labels
|
list[int]
|
Labels to analyze. Defaults to [1, 2, 3]. |
[1, 2, 3]
|
cc_size_threshold
|
int | list[int]
|
Minimum component size in voxels; a single value applies to all labels, or one value per label. Defaults to 100. |
100
|
neighbor_factor_2_delete
|
float
|
Fraction of neighboring foreground voxels below which a component is deleted instead of relabeled. Defaults to 0.1. |
0.1
|
verbose
|
bool
|
If True, log per-component details and show a progress bar. Defaults to True. |
True
|
only_delete
|
bool
|
If True, delete every analyzed component without majority-vote relabeling. Defaults to False. |
False
|
ignore_missing_labels
|
bool
|
If True, skip labels not present instead of asserting. Defaults to False. |
False
|
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: The cleaned segmentation array. |
Raises:
| Type | Description |
|---|---|
AssertionError
|
If requested labels are missing (when |
Source code in spineps/utils/proc_functions.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | |
connected_components_3d
¶
connected_components_3d(
mask_image: ndarray,
connectivity: int = 3,
verbose: bool = False,
) -> tuple[dict, dict]
Compute 3D connected components per label together with their statistics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mask_image
|
ndarray
|
Input (multi-label) mask. |
required |
connectivity
|
int
|
Voxel connectivity in range [1, 3]. For 2D images 2 and 3 are equivalent. Defaults to 3. |
3
|
verbose
|
bool
|
Currently unused. Defaults to False. |
False
|
Returns:
| Type | Description |
|---|---|
dict
|
tuple[dict, dict]: A dict mapping each label to its connected-component array, and a dict mapping each |
dict
|
label to its |
Source code in spineps/utils/proc_functions.py
fix_wrong_posterior_instance_label
¶
Reassign misattributed posterior vertebra fragments to the correct instance label.
For every vertebra instance that splits into multiple connected components, each extra component consisting only of posterior elements (arcus vertebrae and/or spinous process) is relabeled to the single neighboring instance it touches, if any. Operates on copies and restores the original orientation before returning.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seg_sem
|
NII
|
Semantic segmentation (subregion labels) aligned with |
required |
seg_inst
|
NII
|
Vertebra instance segmentation to correct. |
required |
logger
|
Logger_Interface
|
Logger used to report each relabeling decision. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
NII |
NII
|
The corrected instance segmentation in the original orientation. |
Raises:
| Type | Description |
|---|---|
AssertionError
|
If |
Source code in spineps/utils/proc_functions.py
spineps.utils.find_min_cost_path¶
spineps.utils.find_min_cost_path
¶
Min-cost path solver that assigns the most probable vertebra label sequence from a per-vertebra cost matrix.
argmin
¶
Return the index and value of the smallest element in a list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lst
|
list
|
A non-empty sequence supporting |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
tuple[int, ...]
|
|
Source code in spineps/utils/find_min_cost_path.py
softmax_T
¶
c_to_region_idx
¶
Map a class index to the index of the spinal region it falls into.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
c
|
int
|
Class (label) index along the cost matrix's class axis. |
required |
regions
|
list[int]
|
Sorted region start indices (e.g. cervical, thoracic, lumbar). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
Index of the region containing class |
Source code in spineps/utils/find_min_cost_path.py
internal_to_real_path
¶
Convert an internal (row, class) path into the ordered list of class indices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p
|
list
|
Iterable of |
required |
Returns:
| Name | Type | Description |
|---|---|---|
list |
list
|
Class indices ordered by ascending row (vertebra) index. |
Source code in spineps/utils/find_min_cost_path.py
find_most_probably_sequence
¶
find_most_probably_sequence(
cost: ndarray | list[int],
min_start_class: int = 0,
region_rel_cost: ndarray | list[int] | None = None,
vertt13_cost: ndarray | list[int] | None = None,
regions: list[int] | None = None,
invert_cost: bool = True,
softmax_cost: bool = False,
softmax_temp: float = DEFAULT_SOFTMAX_TEMP,
allow_multiple_at_class: list[int] | None = None,
punish_multiple_sequence: float = 0.0,
allow_skip_at_class: list[int] | None = None,
punish_skip_sequence: float = 0.0,
allow_skip_at_region: list[int] | None = None,
punish_skip_at_region_sequence: float = 0.2,
verbose: bool = False,
) -> tuple[float, list[int], list]
Find the most probable vertebra-label sequence as a min-cost monotone path through a cost matrix.
Each matrix row corresponds to a detected vertebra (top to bottom) and each column to a candidate label
class. The path moves one row down per step, normally advancing one class (diagonal). Special constraints
model spinal anatomy: certain transitional classes (e.g. T12, L5) may repeat, certain classes/regions allow
a single skip, and optional region- and T13-related transition costs adjust the path. Extra moves incur the
configured penalties; classes flagged as repeatable may appear at most MAX_REPEATS_PER_CLASS times.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cost
|
ndarray | list[int]
|
2D cost matrix of shape |
required |
min_start_class
|
int
|
Smallest class index the path may start at. Defaults to 0. |
0
|
region_rel_cost
|
ndarray | list[int] | None
|
Per-vertebra costs for being the first/last vertebra of each region; enables region-transition costs when given. Defaults to None. |
None
|
vertt13_cost
|
ndarray | list[int] | None
|
Per-vertebra cost contribution for the T13/T12 (class 18) repeat case. Defaults to None. |
None
|
regions
|
list[int] | None
|
Region start indices along the class axis. Defaults to
|
None
|
invert_cost
|
bool
|
Negate the cost so that high input scores are preferred. Defaults to True. |
True
|
softmax_cost
|
bool
|
Apply a softmax over the cost columns (deprecated path). Defaults to False. |
False
|
softmax_temp
|
float
|
Temperature for the softmax. Defaults to |
DEFAULT_SOFTMAX_TEMP
|
allow_multiple_at_class
|
list[int] | None
|
Classes allowed to repeat (e.g. T12 and L5).
Defaults to |
None
|
punish_multiple_sequence
|
float
|
Extra cost added for repeating a class. Defaults to 0.0. |
0.0
|
allow_skip_at_class
|
list[int] | None
|
Classes after which a single class may be skipped (e.g.
T11). Defaults to |
None
|
punish_skip_sequence
|
float
|
Extra cost added for a class-level skip. Defaults to 0.0. |
0.0
|
allow_skip_at_region
|
list[int] | None
|
Regions in which a single skip is permitted. Defaults
to |
None
|
punish_skip_at_region_sequence
|
float
|
Extra cost added for a region-level skip. Defaults to 0.2. |
0.2
|
verbose
|
bool
|
Enable verbose logging of the recursion. Defaults to False. |
False
|
Returns:
| Type | Description |
|---|---|
float
|
tuple[float, list[int], list]: The total path cost, the chosen class index per vertebra (top to bottom), |
list[int]
|
and the internal memoization table of best |
Raises:
| Type | Description |
|---|---|
AssertionError
|
If |
Source code in spineps/utils/find_min_cost_path.py
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | |
spineps.utils.generate_disc_labels¶
spineps.utils.generate_disc_labels
¶
This script generates discs labels using SPINEPS' vertebrae segmentation
Author: Nathan Molinier
get_parser
¶
Build the command-line argument parser for disc-label generation.
Returns:
| Type | Description |
|---|---|
ArgumentParser
|
argparse.ArgumentParser: Parser accepting the input vertebrae label path and the optional output path. |
Source code in spineps/utils/generate_disc_labels.py
main
¶
Run the disc-label generation CLI.
Parses arguments, loads the SPINEPS vertebrae segmentation, derives single-voxel disc labels from it and writes the result to the chosen (or default) output path.
Source code in spineps/utils/generate_disc_labels.py
default_name_discs
¶
Derive the default output path for disc labels by swapping in a disc suffix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path_in
|
Path | str
|
Path to the input vertebrae label file (may include compound extensions like |
required |
suffix
|
str
|
Suffix inserted before the extension. Defaults to |
'_label-discs_dlabel'
|
Returns:
| Name | Type | Description |
|---|---|---|
Path |
Path
|
The default output path with the disc suffix applied. |
Source code in spineps/utils/generate_disc_labels.py
extract_discs_label
¶
Derive single-voxel disc labels from a vertebrae segmentation.
Remaps vertebra label values to disc values, locates each disc's posterior tip by shifting a centerline (interpolated through the disc centroids) posteriorly and picking the closest segmented voxel, inserts disc 2 between discs 1 and 3 when both are present, and writes one labeled voxel per disc into the image.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
Image
|
Vertebrae segmentation image; its data is replaced in place with the disc labels. |
required |
mapping
|
dict
|
Mapping from vertebra label values to disc label values. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Image |
Image
|
The image holding the disc labels, restored to its original orientation. |
Source code in spineps/utils/generate_disc_labels.py
extract_centroids_3d
¶
Extract connected-component centroids and bounding boxes from a 3D array, sorted along the vertical axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
arr
|
ndarray
|
3D label array (assumed RSP orientation, so axis 1 is the superior-inferior axis). |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
tuple[np.ndarray, np.ndarray]: Integer centroid coordinates and the matching bounding boxes, both sorted |
ndarray
|
by the vertical (axis-1) coordinate, with the background component removed. |
Source code in spineps/utils/generate_disc_labels.py
project_point_on_line
¶
Project a point onto a polyline by finding the closest line point.
Copied from https://github.com/spinalcordtoolbox/spinalcordtoolbox.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
point
|
ndarray
|
Coordinates of the point, |
required |
line
|
ndarray
|
Coordinates of the points composing the line. |
required |
Returns:
| Type | Description |
|---|---|
tuple[ndarray, float]
|
tuple[np.ndarray, float]: The closest point on the line and the squared distance to it. |
Source code in spineps/utils/generate_disc_labels.py
closest_point_seg_to_line
¶
closest_point_seg_to_line(
discs_seg: ndarray,
centerline: ndarray,
bounding_boxes: ndarray,
) -> np.ndarray
Find, per disc, the segmented voxel closest to a reference centerline.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
discs_seg
|
ndarray
|
Disc-labeled segmentation array. |
required |
centerline
|
ndarray
|
Coordinates of the points composing the reference line. |
required |
bounding_boxes
|
ndarray
|
Bounding box (slice tuple) for each disc, used to isolate it. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: Array of |
Source code in spineps/utils/generate_disc_labels.py
spineps.utils.filepaths¶
spineps.utils.filepaths
¶
File-path helpers for locating the SPINEPS model weights directory and individual model folders.
get_mri_segmentor_models_dir
¶
Returns the path to the models weight directory, reading from environment variable, specified override or backup
Returns:
| Name | Type | Description |
|---|---|---|
Path |
Path
|
Path to the overall models folder |
Source code in spineps/utils/filepaths.py
filepath_model
¶
Returns the path to a model folder with specified model id name
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_folder_name
|
str
|
Name of the model (corresponds to its folder name) |
required |
model_dir
|
str | Path | None
|
Base path to the models directory. If none, will calculate that itself. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Path |
Path
|
Path to the model specified by name |
Source code in spineps/utils/filepaths.py
search_path
¶
search_path(
basepath: str | Path,
query: str,
verbose: bool = False,
suppress: bool = False,
) -> list[Path]
Searches from basepath with query
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
basepath
|
str | Path
|
ground path to look into |
required |
query
|
str
|
search query, can contain wildcards like .npz or /.npz |
required |
verbose
|
bool
|
|
False
|
suppress
|
bool
|
if true, will not throwing warnings if nothing is found |
False
|
Returns:
| Type | Description |
|---|---|
list[Path]
|
All found paths |
Source code in spineps/utils/filepaths.py
spineps.utils.auto_download¶
spineps.utils.auto_download
¶
Automatic download and extraction of pretrained SPINEPS model weights from the GitHub releases.
download_if_missing
¶
Return the local model folder for a model, downloading and extracting its weights if absent.
The target folder name combines the model's download name with the version resolved for its phase (and the phase/key-specific override when one exists, e.g. CT models).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Model key identifying the model within its phase (e.g. |
required |
url
|
Union[Path, str]
|
Release URL of the model's weights zip archive. |
required |
phase
|
SpinepsPhase
|
Pipeline phase the model belongs to. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Path |
Path
|
Path to the local model folder containing the (possibly just downloaded) weights. |
Source code in spineps/utils/auto_download.py
download_weights
¶
Download a weights zip archive, extract it into out_path and remove the archive.
Shows a progress bar during download. If the extracted archive nests its contents in an extra subfolder
(no inference_config.json at the top level), the inner contents are moved up one level. Returns early
without raising if the initial size request fails.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
weights_url
|
Union[Path, str]
|
URL of the weights zip archive to download. |
required |
out_path
|
Union[Path, str]
|
Destination folder for the extracted weights (the archive is downloaded next to it as |
required |
Raises:
| Type | Description |
|---|---|
AssertionError
|
If the nested archive layout is detected but the extra entry is not a directory. |
Source code in spineps/utils/auto_download.py
spineps.utils.citation_reminder¶
spineps.utils.citation_reminder
¶
Citation reminder utilities that prompt users to cite SPINEPS when the package is used.
citation_reminder
¶
Decorator to remind users to cite SPINEPS.
Source code in spineps/utils/citation_reminder.py
print_citation_reminder
¶
Print a formatted reminder with the SPINEPS GitHub and ArXiv links asking users to cite the work.
Source code in spineps/utils/citation_reminder.py
spineps.utils.compat¶
spineps.utils.compat
¶
zip_strict
¶
A strict version of zip that raises a ValueError if the input iterables have different lengths.
Converts each iterable to a list to check lengths. This assumes all iterables are finite.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*iterables
|
Iterable
|
Finite iterables to be zipped together. |
()
|
Returns:
| Type | Description |
|---|---|
zip
|
An iterator of tuples, where the i-th tuple contains the i-th element from each iterable. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the input iterables have different lengths. |