Running SpineNet¶
This section assumes that you have already installed SpineNet, see Getting Started if you have not already done this.
SpineNet interacts with sagittally-sliced DICOM spinal MRIs using the spinenet.io.SpinalScan class. For information on creating instances of this scan from your data, consult the Loading Scans page.
There are two stages in the SpineNet pipeline:
Detecting and labelling vertebral bodies in the raw scans. This is done using the
spinenet.SpineNet.detect_vb()class method.(T2 Lumbar Scans Only) Grading intervertebral disc volumes for a range of common degenerative conditions, including:
Pfirrman Grading (5 Classes)
Disc Narrowing (4 Classes)
Central Canal Stenosis (4 Classes)
Upper & Lower Endplate Defects (Binary)
Upper & Lower Marrow Changes (Binary)
Left/Right Foraminal Stenosis (Binary)
Spondylolisthesis (Binary)
Disc Herniation (Binary)
This is done by using the
spinenet.SpineNet.get_ivds_from_vert_dicts()andspinenet.SpineNet.grade_ivds()methods.
Before running any of the above steps, you must first initialize the SpineNet model. This can be done as follows:
# Run this if you have not already downloaded the model weights
spinenet.download_weights(verbose=True, force=False)
# load in spinenet. Replace device with 'cpu' if you are not using a CUDA-enabled machine.
spnt = SpineNet(device='cuda:0', verbose=True)
Detecting Vertebral Bodies¶
To detect vertebral bodies in a spinal scan, pass the corresponding SpinalScan
object the initialised spinenet object’s detect_vb() method:
# `scan` is a `spinenet.io.SpinalScan` object
vert_dicts = spnt.detect_vb(scan.volume, scan.pixel_spacing)
Here vert_dicts is a list of dictionaries. Each dictionary contains information about the vertebra detected, including the following keys:
predicted_label: The predicted label of the vertebra, e.g. S1, T12, etc.
slice_nos: List of indicies of the sagittal slices in which the vertebra was detected.
polys: A list of co-ordinates describing the four corners of the vertebral body quadrilateral detected. The co-ordinates at element i in the list, describe the polygon detected in vert_dict[‘slice_nos’][i].
- spinenet.SpineNet.detect_vb(self, volume: ndarray, pixel_spacing: Union[ndarray, List[float], Tensor], debug: bool = False, penalise_skips: bool = True, remove_single_slice_detections: bool = True) VertDicts¶
Use SpineNet to detect and label vertebral bodies in a volume.
- Parameters
volume (np.ndarray) – The volume to detect vertebrae in. Should have shape (height,width, number of sagittal slices).
pixel_spacing (Union[np.ndarray, List[float], torch.Tensor]) – The pixel spacing of the volume, specifically the distance between adjacent pixels in the sagittal direction. This has order height, width
debug (bool, optional) – Whether to print out debug information. The default is False.
penalise_skips (bool, optional) – Whether to penalise skipping a vertebrae in the detection sequence. Essentially, enabling this ensures the vertebrae labels will be in order (i.e. T12, L5, L4, etc). However, this may not be desired if you expect to miss detections (perhaps due to image artifacts)
- Returns
A list of dictionaries containing the vertebrae labels, their corresponding polygons and the slices in which they appear.
- Return type
VertDicts
You can save the vert_dicts to a CSV file using spinenet.io.save_vert_dicts_to_csv:
spinenet.io.save_vert_dicts_to_csv(vert_dicts, 'my_vert_dicts.csv')
- spinenet.io.save_vert_dicts_to_csv(vert_dicts: List[Dict], filename: str) None¶
Saves a list of vert_dicts to a file in csv format.
- Parameters
vert_dicts (List[Dict]) – A list of dictionaries with the following keys: ‘polys’, ‘average_polygon’, ‘slice_nos’, ‘predicted_label’ Each entry corresponds to a detected vertebral body
filename (str) – The name of the file to save the vert_dicts to.
Grading IVDS¶
- note
Please bear in mind that the grading models are only trained on T2 lumbar scans and thus will not work for other fields of view or sequences.
Now the vertebra have been detected, you can use them to extract volumes surrounding each IVD from L5-S1 to T12-L1.
To do this, you can use the spinenet.SpineNet.get_ivds_from_vert_dicts()
ivd_dicts = spnt.get_ivds_from_vert_dicts(vert_dicts, scan.vol)
- spinenet.SpineNet.get_ivds_from_vert_dicts(self, vert_dicts: VertDicts, scan_volume: ndarray) IVDDicts¶
Use detected vertebrae from SpineNet’s detect_vb function to generate volumes surrounding each IVD.
- Parameters
vert_dicts (VertDicts) – The vertebrae labels, their corresponding polygons and the slices in which they appear. Generated by SpineNet.detect_vb function
scan_volume (np.ndarray) – The volume to extract the IVDs from. Should have shape (height,width, number of sagittal slices).
- Returns
A list of dictionaries containing resampled IVD volumes and the corresponding names
- Return type
IVDDicts
Similar to vert_dicts, this is also a list of dictionaries. However, each dictionary contains information about extracted IVD detected, including the following keys:
volume: a np.array of the extracted IVD volume, resized for the grading network.
level_name: The predicted label of the IVD, e.g. L5-S1, T12-L1, etc.
ivd_dicts is then passed to the grading network to grade the IVD volumes:
ivd_grades = spnt.grade_ivds(ivd_dicts)
# ivd grades is a pd.DataFrame where each row contains the gradings for a
# single IVD. You can save it as follows:
ivd_grades.to_csv('my_ivd_grades.csv')
- spinenet.SpineNet.grade_ivds(self, ivd_dicts: IVDDicts) DataFrame¶
Grade all intervertebral discs extracted from a volume. See the technical paper for details on the specific grading schemes: https://arxiv.org/abs/2205.01683.
- Parameters
ivd_dicts (IVDDicts) – A list of dictionaries containing resampled IVD volumes and the corresponding names. Generated by SpineNet.get_ivds_from_vert_dicts function
- Returns
gradings – A pandas dataframe containing the IVD names and their corresponding grades.
- Return type
pd.DataFrame