I2T2.io loads and saves common file formats used in medical imaging.
# test
try:
    import gdcm
    print('Successfully imported GDCM')
except ImportError:
    print('Could not import GDCM')
Successfully imported GDCM

Loading dicom data

class dicom_dataframe[source]

dicom_dataframe(path_to_dicom_dir, dicom_extension='dcm', read_single_random_dcm=False)

Class for sorting, selecting and loading portions of dicom data.

Objects of this class are pandas dataframes with at least one main column ('DS') that holds the results of pydicom.read() for each file read during initialization. Users can populate the dataframe with new columns using DICOM tags to facilitate subsequent filtering, sorting and data loading.

Usage

dicom_dataframe takes a path to a folder containing the dicom files of interest.

It then constructs a pandas dataframe whose first column (DS) is the result of pydicom.dcmread for each file encountered.

import pkg_resources

DATA_ROOT = pkg_resources.resource_filename('I2T2', 'data')

data_path = os.path.join(DATA_ROOT,'knee')
# to read a single, random dicom file from the entire directory
dcm_df = dicom_dataframe(path_to_dicom_dir=data_path, dicom_extension='DCM', read_single_random_dcm=True)

dcm_df.dataframe.head(4)
DS SeriesInstanceUID ImagePositionPatient
0 {(0008, 0005): (0008, 0005) Specific Character... 1.2.826.0.1.3680043.8.1055.1.20111103111204584... [-83.2285, -105.586, 73.7768]
# to read all the dicoms and save them to a pandas dataframe
dcm_df = dicom_dataframe(path_to_dicom_dir=data_path)

dcm_df.dataframe.head(4)
DS SeriesInstanceUID ImagePositionPatient
0 {(0008, 0005): (0008, 0005) Specific Character... 1.2.826.0.1.3680043.8.1055.1.20111103111204584... [-105.729, -105.586, 73.7768]
1 {(0008, 0005): (0008, 0005) Specific Character... 1.2.826.0.1.3680043.8.1055.1.20111103111204584... [-101.229, -105.586, 73.7768]
2 {(0008, 0005): (0008, 0005) Specific Character... 1.2.826.0.1.3680043.8.1055.1.20111103111204584... [-110.229, -105.586, 73.7768]
3 {(0008, 0005): (0008, 0005) Specific Character... 1.2.826.0.1.3680043.8.1055.1.20111103111204584... [-56.2285, -105.586, 73.7768]

The dicom dataframe comes pre-populated with a few values of interest. We can add additional keys by using the populate_dataframe function:

dcm_df.populate_dataframe(['SOPClassUID'])

dcm_df.dataframe.head(4)
DS SeriesInstanceUID ImagePositionPatient SOPClassUID
0 {(0008, 0005): (0008, 0005) Specific Character... 1.2.826.0.1.3680043.8.1055.1.20111103111204584... [-105.729, -105.586, 73.7768] 1.2.840.10008.5.1.4.1.1.4
1 {(0008, 0005): (0008, 0005) Specific Character... 1.2.826.0.1.3680043.8.1055.1.20111103111204584... [-101.229, -105.586, 73.7768] 1.2.840.10008.5.1.4.1.1.4
2 {(0008, 0005): (0008, 0005) Specific Character... 1.2.826.0.1.3680043.8.1055.1.20111103111204584... [-110.229, -105.586, 73.7768] 1.2.840.10008.5.1.4.1.1.4
3 {(0008, 0005): (0008, 0005) Specific Character... 1.2.826.0.1.3680043.8.1055.1.20111103111204584... [-56.2285, -105.586, 73.7768] 1.2.840.10008.5.1.4.1.1.4

We can also filter the dataframe by a key. For instance, below we select only the first Series found:

series_list = dcm_df.dataframe['SeriesInstanceUID'].unique()
ID_of_first_series = series_list[0]

dcm_df.filter_dataframe_by_column_value(column='SeriesInstanceUID', value=ID_of_first_series)

Finally, we can also get pixel data sorted by ImagePositionPatient

pixel_data = dcm_df.get_pixel_data()
plt.imshow(pixel_data[:, :, 6])
plt.show()

Loading single slice X-Ray

I2T2 can also load X-rays. A warning will tell us that ImagePositionPatient was not found but I2T2 will just ignore it since no slice sorting is needed.

chest_xray_path = os.path.join(DATA_ROOT,'chest-xray')

dcm_df = dicom_dataframe(path_to_dicom_dir=chest_xray_path, dicom_extension='dcm')
pixel_data = dcm_df.get_pixel_data()
plt.title('Chest X-Ray example from TCIA')
plt.imshow(pixel_data[:,:,0])
plt.yticks([])
plt.xticks([])
plt.show()
ImagePositionPatient  tag was not found! Skipping... (0020, 0032)

Tests

#test if Xray is loading correctly
dcm_df = dicom_dataframe(path_to_dicom_dir=chest_xray_path, dicom_extension='dcm')
pixel_data = dcm_df.get_pixel_data()
assert(pixel_data.shape == (2022, 2022, 1))
ImagePositionPatient  tag was not found! Skipping... (0020, 0032)
#test 
#make sure dataframe is ordered correctly
data_path = os.path.join(DATA_ROOT,'knee')
dcm_df = dicom_dataframe(path_to_dicom_dir=data_path, dicom_extension='dcm')
dcm_df.sort_dataframe_by_IPP_normal()
for i in range(len(dcm_df.dataframe) - 1):
    assert(dcm_df.dataframe['ImagePositionPatient_normal'].iloc[i+1] > dcm_df.dataframe['ImagePositionPatient_normal'].iloc[i])
#test
np.testing.assert_equal(_get_normal_from_dicom_slice(dcm_df.dataframe['DS'].iloc[0]), np.array([-1., -0.,  0.]))

Some handy dicom tests

get_plane[source]

get_plane(dcm)

Returns plane for input dicom Attributes: dcm (FileDataset): dicom slice, result from pydicom.dcmread() Returns: plane (str): axial or coronal or sagittal

is_axial[source]

is_axial(dcm)

is_sagittal[source]

is_sagittal(dcm)

is_coronal[source]

is_coronal(dcm)

is_fat_suppressed[source]

is_fat_suppressed(dcm)

#tests
data_path = os.path.join(DATA_ROOT,'knee')
dcm_df = dicom_dataframe(path_to_dicom_dir=data_path, dicom_extension='dcm')

assert(is_fat_suppressed(dcm_df.dataframe['DS'].iloc[0]) == True)
assert(is_sagittal(dcm_df.dataframe['DS'].iloc[0]) == True)
assert(is_axial(dcm_df.dataframe['DS'].iloc[0]) == False)
assert(is_coronal(dcm_df.dataframe['DS'].iloc[0]) == False)

Load .mat

load_mat[source]

load_mat(path_to_mat_file=None, key='img')

Loads matlab data as a numpy array.

Attributes: path_to_mat_file (str): Path to mat file containing image / segmentation key (str): key to load from matlab dictionary

Returns: pixel_array (arr): Array of pixel data

Load .h5

load_h5[source]

load_h5(path_to_h5_file=None)

Loads h5 files into numpy array.

Attributes: path_to_h5_file (str): Path h5 file for one subject

Returns: h5_file_dict (dict): Dictionary of pixel data

Usage

segmentation_path = os.path.join(DATA_ROOT,'knee-segmentation','knee_segmentation.h5')

h5_file = load_h5(
    path_to_h5_file=segmentation_path)

# Plot
plt.figure(figsize=(10, 10))

plt.subplot(121)
plt.title('Image')
plt.imshow(h5_file['img'][:, :, 30])

plt.subplot(122)
plt.title('Segmentation image')
plt.imshow(h5_file['seg'][:, :, 30])

plt.show()