# Pythonic Syntactic Sugar¶

The Image Basics Notebook was straight forward and closely follows ITK's C++ interface.

Sugar is great it gives your energy to get things done faster! SimpleITK has applied a generous about of syntactic sugar to help get things done faster too.

In [1]:
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rc('image', aspect='equal')
import SimpleITK as sitk


Let us begin by developing a convenient method for displaying images in our notebooks.

In [2]:
img = sitk.GaussianSource(size=[64]*2)
plt.imshow(sitk.GetArrayViewFromImage(img))

Out[2]:
<matplotlib.image.AxesImage at 0x124078390>
In [3]:
img = sitk.GaborSource(size=[64]*2, frequency=.03)
plt.imshow(sitk.GetArrayViewFromImage(img))

Out[3]:
<matplotlib.image.AxesImage at 0x1241f0c18>
In [4]:
def myshow(img):
nda = sitk.GetArrayViewFromImage(img)
plt.imshow(nda)
myshow(img)


## Multi-dimension slice indexing¶

If you are familiar with numpy, sliced index then this should be cake for the SimpleITK image. The Python standard slice interface for 1-D object:

 Operation Result d[i] i-th item of d, starting index 0 d[i:j] slice of d from i to j d[i:j:k] slice of d from i to j with step k

With this convenient syntax many basic tasks can be easily done.

In [5]:
img[24,24]

Out[5]:
0.048901304602622986

### Cropping¶

In [6]:
myshow(img[16:48,:])

In [7]:
myshow(img[:,16:-16])

In [8]:
myshow(img[:32,:32])


### Flipping¶

In [9]:
img_corner = img[:32,:32]
myshow(img_corner)

In [10]:
myshow(img_corner[::-1,:])

In [11]:
myshow(sitk.Tile(img_corner, img_corner[::-1,::],img_corner[::,::-1],img_corner[::-1,::-1], [2,2]))


### Slice Extraction¶

A 2D image can be extracted from a 3D one.

In [12]:
img = sitk.GaborSource(size=[64]*3, frequency=0.05)

# Why does this produce an error?
myshow(img)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-e30b71f2ae99> in <module>
2
3 # Why does this produce an error?
----> 4 myshow(img)

<ipython-input-4-66f5146c4fb2> in myshow(img)
1 def myshow(img):
2     nda = sitk.GetArrayViewFromImage(img)
----> 3     plt.imshow(nda)
4 myshow(img)

~/toolkits/anaconda3/envs/sitkMaster3.7/lib/python3.7/site-packages/matplotlib/pyplot.py in imshow(X, cmap, norm, aspect, interpolation, alpha, vmin, vmax, origin, extent, shape, filternorm, filterrad, imlim, resample, url, data, **kwargs)
2682         resample=resample, url=url, **({"data": data} if data is not
-> 2683         None else {}), **kwargs)
2684     sci(__ret)
2685     return __ret

~/toolkits/anaconda3/envs/sitkMaster3.7/lib/python3.7/site-packages/matplotlib/__init__.py in inner(ax, data, *args, **kwargs)
1599     def inner(ax, *args, data=None, **kwargs):
1600         if data is None:
-> 1601             return func(ax, *map(sanitize_sequence, args), **kwargs)
1602
1603         bound = new_sig.bind(ax, *args, **kwargs)

~/toolkits/anaconda3/envs/sitkMaster3.7/lib/python3.7/site-packages/matplotlib/cbook/deprecation.py in wrapper(*args, **kwargs)
367                 f"%(removal)s.  If any parameter follows {name!r}, they "
368                 f"should be pass as keyword, not positionally.")
--> 369         return func(*args, **kwargs)
370
371     return wrapper

~/toolkits/anaconda3/envs/sitkMaster3.7/lib/python3.7/site-packages/matplotlib/cbook/deprecation.py in wrapper(*args, **kwargs)
367                 f"%(removal)s.  If any parameter follows {name!r}, they "
368                 f"should be pass as keyword, not positionally.")
--> 369         return func(*args, **kwargs)
370
371     return wrapper

~/toolkits/anaconda3/envs/sitkMaster3.7/lib/python3.7/site-packages/matplotlib/axes/_axes.py in imshow(self, X, cmap, norm, aspect, interpolation, alpha, vmin, vmax, origin, extent, shape, filternorm, filterrad, imlim, resample, url, **kwargs)
5669                               resample=resample, **kwargs)
5670
-> 5671         im.set_data(X)
5672         im.set_alpha(alpha)
5673         if im.get_clip_path() is None:

~/toolkits/anaconda3/envs/sitkMaster3.7/lib/python3.7/site-packages/matplotlib/image.py in set_data(self, A)
688                 or self._A.ndim == 3 and self._A.shape[-1] in [3, 4]):
689             raise TypeError("Invalid shape {} for image data"
--> 690                             .format(self._A.shape))
691
692         if self._A.ndim == 3:

TypeError: Invalid shape (64, 64, 64) for image data
In [13]:
myshow(img[:,:,32])

In [14]:
myshow(img[16,:,:])


### Subsampling¶

In [15]:
myshow(img[:,::3,32])


## Mathematical Operators¶

Most python mathematical operators are overloaded to call the SimpleITK filter which does that same operation on a per-pixel basis. They can operate on a two images or an image and a scalar.

If two images are used then both must have the same pixel type. The output image type is usually the same.

As these operators basically call ITK filter, which just use raw C++ operators, care must be taken to prevent overflow, and divide by zero etc.

 Operators + - * / // **
In [16]:
img = sitk.ReadImage(fdata("cthead1.png"))
img = sitk.Cast(img,sitk.sitkFloat32)
myshow(img)
img[150,150]

Fetching cthead1.png

Out[16]:
140.0
In [17]:
timg = img**2
myshow(timg)
timg[150,150]

Out[17]:
19600.0

### Division Operators¶

All three Python division operators are implemented __floordiv__, __truediv__, and __div__.

The true division's output is a double pixel type.

See PEP 238 to see why Python changed the division operator in Python 3.

### Bitwise Logic Operators¶

 Operators & | ^ ~
In [18]:
img = sitk.ReadImage(fdata("cthead1.png"))
myshow(img)

Fetching cthead1.png


## Comparative Operators¶

 Operators > >= < <= ==

These comparative operators follow the same convention as the reset of SimpleITK for binary images. They have the pixel type of sitkUInt8 with values of 0 and 1.

In [19]:
img = sitk.ReadImage(fdata("cthead1.png"))
myshow(img)

Fetching cthead1.png


### Amazingly make common trivial tasks really trivial¶

In [20]:
myshow(img>90)

In [21]:
myshow(img>150)

In [22]:
myshow((img>90)+(img>150))