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:

  1. Detecting and labelling vertebral bodies in the raw scans. This is done using the spinenet.SpineNet.detect_vb() class method.

  2. (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() and spinenet.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