Search code examples
matplotlibplotdicomsimpleitkniftynet

Threshold Otsu: AttributeError: 'AxesSubplot' object has no attribute 'ravel'


I loaded nifty files(These were as well converted from .pack CT scans). My goal is to use the threashold otsu algorithm to mask it from the background and compare the two images. When I try to plot I get the error

AttributeError: 'AxesSubplot' object has no attribute 'ravel'

Below is the code and attached is a screenshot.

import SimpleITK as sitk
import matplotlib.pyplot as plt
import numpy as np
from skimage.filters import threshold_otsu

#THRESHOLD OTSU
img = sitk.GetArrayFromImage(sitk.ReadImage("\\\\x.x.x.x/users/ddff/python/nifts/prr_ipsi.nii"))
print(img.shape)
thresh = threshold_otsu(img.flatten())
#thresh = thresh.reshape(img.shape)
binary = img <= thresh

#I can plot this image slice fine
plt.imshow(img[20,:,:])

fig, axes = plt.subplots(ncols=1)
ax = axes.ravel()
ax[0] = plt.subplot(1, 3, 1)
ax[1] = plt.subplot(1, 3, 2)
ax[2] = plt.subplot(1, 3, 3, sharex=ax[0], sharey=ax[0])

ax[0].imshow(img[20,:,:], cmap=plt.cm.gray)
ax[0].set_title('Original Breast Delineation')
ax[0].axis('off')

ax[1].hist(thresh, bins=256)
ax[1].set_title('Histogram ')
ax[1].axvline(thresh, color='r')

ax[2].imshow(binary[20,:,:], cmap=plt.cm.gray)
ax[2].set_title('Thresholded')
ax[2].axis('off')

plt.show()[enter image description here][1]

Solution

  • axes is just a single figure with 1 column so there is nothing to ravel or flatten. It will work if you have more than one sub plot. Nevertheless, you can do the following without ravel if you have only a single row or a single column.

    fig, ax = plt.subplots(ncols=3, sharex=True, sharey=True)
    
    ax[0].imshow(img[20,:,:], cmap=plt.cm.gray)
    ax[0].set_title('Original Breast Delineation')
    ax[0].axis('off')
    
    ax[1].hist(thresh, bins=256)
    ax[1].set_title('Histogram ')
    ax[1].axvline(thresh, color='r')
    
    ax[2].imshow(binary[20,:,:], cmap=plt.cm.gray)
    ax[2].set_title('Thresholded')
    ax[2].axis('off')
    

    In case you want a 2d matrix of subplot instances, you can use Thomas Kühn's suggestion.

    fig, ax = plt.subplots(ncols=3, sharex=True, sharey=True, squeeze=False)
    

    and then you can access the subplots as

    ax[0][0].imshow()
    ax[0][1].imshow()
    ......