Issue
I am at the moment working on medical images and writing code for preparing a training set. To do this, I need to scroll through slices of volume data.
My main IDE is Spyder, but the standard implementation of the IndexTracker object does not work for me WITHIN a function.
This standard implementation works for me: https://matplotlib.org/gallery/animation/image_slices_viewer.html
But as soon as I put the creation of the plot into a function, the created plot is no longer scrollable:
import numpy as np
import matplotlib
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
class IndexTracker(object):
def __init__(self, ax, X):
self.ax = ax
ax.set_title('use scroll wheel to navigate images')
self.X = X
rows, cols, self.slices = X.shape
self.ind = self.slices//2
self.im = ax.imshow(self.X[:, :, self.ind])
self.update()
def onscroll(self, event):
print("%s %s" % (event.button, event.step))
if event.button == 'up':
self.ind = (self.ind + 1) % self.slices
else:
self.ind = (self.ind - 1) % self.slices
self.update()
def update(self):
self.im.set_data(self.X[:, :, self.ind])
self.ax.set_ylabel('slice %s' % self.ind)
self.im.axes.figure.canvas.draw()
def plot(X):
fig, ax = plt.subplots(1, 1)
tracker = IndexTracker(ax, X)
fig.canvas.mpl_connect('scroll_event', tracker.onscroll)
plt.show()
plot(np.random.rand(200, 200, 500))
What could be the problem? How do I create my scrollable plot from within a function?
Solution
I've solved the problem myself: The issue is, that matplotlib does not correctly identify the plot instance and thus it must be set in the function. A basic and NOT UNIVERSAL OR PRACTICAL application would be the following:
figList,axList=[],[]
def plotSlices(image, view):
fig, ax = plt.subplots(1, 1)
figList.append(fig)
axList.append(ax)
axList[-1].set_title(view)
tracker = IndexTracker(axList[-1], image)
figList[-1].canvas.mpl_connect('scroll_event', tracker.onscroll)
plt.show(figList[-1],block=False)
In which a numpy array is read together with the perspective of the image. This is used only for the title, so you can remove it/hardcode the title. The fig and ax objects are appended to respective lists, from which only the last added elements are given to matplotlib to plot.
This way, scrolling through plots defined in the function works. One issue is that I'm apparently overloading the .show() method, which should only accept a block=False/True argument, but does actually correctly identify the correct plot like this: plt.show(fig,block=False) It throws an error adressing this, but ultimately works. Perfect!
Answered By - HadRik
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.