[Matplotlib-users] Visualization of 3D and 4D image data: problem with spacing between subplots in grid plot
Denis Samuylov
denis.samuylov at gmail.com
Mon Dec 7 15:36:33 EST 2015
Dear matplotlib users,
I have to visualize 3 and 4 dimensional images and overlay on top some data
(e.g. masks, tracking results, etc). I need a solution to explore (e.g.
visualize inline in IPython) and to present my results (e.g. insert pdf
into slides). I wrote a few functions using matplotlib and I can plot a
sequence of projections of 3-D volumes:
[image: Inline image 1]
However, as you can see there is a problem with spacing near projections
which makes the plot look not so nice. In ideal case I would like to have
the same spacing between x- and y-projections and corresponding
z-projection. I spend quite a lot of time trying to figure out how to do
that with matplotlib APIs, but I still haven't found a solution. I would
highly appreciate if you could help.
I also posted this question on stackoverflow:
http://stackoverflow.com/questions/34124267/visualize-3d-and-4d-image-data-in-python
My full code is also available on Github:
https://github.com/DSamuylov/imagend
Minimal code to reproduce the problem is bellow.
Thank you for your help!
Best regards,
Denis
import mathimport numpy as npimport matplotlib.cm as cmimport
matplotlib.pyplot as pltimport matplotlib.gridspec as gridspec
def project_image_stack(img, figwidth=3, axes=None):
dim = len(img.shape)
assert dim == 3
n_slices, n_h, n_w = img.shape
figheight = (figwidth)*np.float64(n_h + n_slices)/(n_w + n_slices)
z_proj = np.mean(img, axis=0)
y_proj = np.mean(img, axis=1)
x_proj = np.mean(img, axis=2).T
if axes is None:
# Create figure
fig = plt.figure(figsize=(figwidth, figheight))
gs = gridspec.GridSpec(2, 2, width_ratios=[n_w, n_slices],
height_ratios=[n_h, n_slices])
gs.update(wspace=0.05, hspace=0.05, bottom=0, top=1, left=0, right=1)
# Create axes:
ax_z = fig.add_subplot(gs[0, 0])
ax_y = fig.add_subplot(gs[1, 0], sharex=ax_z)
ax_x = fig.add_subplot(gs[0, 1], sharey=ax_z)
else:
assert len(axes) == 3
fig = None
ax_z, ax_y, ax_x = axes
# z projection:
ax_z.imshow(z_proj, interpolation='nearest', cmap=cm.gray, aspect=1)
ax_z.set_xlim([-0.5, n_w - 0.5])
ax_z.set_ylim([n_h - 0.5, -0.5])
ax_z.axis('off')
# y projection:
ax_y.imshow(y_proj, interpolation='nearest', cmap=cm.gray, aspect=1)
ax_y.set_xlim([-0.5, n_w-0.5])
ax_y.set_ylim([n_slices-0.5, -0.5])
ax_y.axis('off')
# x projection:
ax_x.imshow(x_proj, interpolation='nearest', cmap=cm.gray, aspect=1)
ax_x.set_xlim([-0.5, n_slices-0.5])
ax_x.set_ylim([n_h-0.5, -0.5])
ax_x.axis('off')
return fig, (ax_z, ax_y, ax_x)
def project_image_sequence(img_sequence, subfigwidth=3, ncol=5):
dim = len(img_sequence.shape)
assert dim == 4
n_frames, n_slices, n_h, n_w = img_sequence.shape
frames = range(0, n_frames)
n_subfig = len(frames)
# Initialize parameters
nrow = int(math.ceil(float(n_subfig)/ncol))
height_subfig = (n_h + n_slices)*np.float64(subfigwidth)/(n_w + n_slices)
# Initialize the figure
fig = plt.figure(figsize=(subfigwidth*ncol, height_subfig*nrow))
# Initialize the layout
gs_master = gridspec.GridSpec(nrow, ncol)
gs_master.update(bottom=0, top=1, left=0, right=1)
# Magic for every (sub-)gridspec:
wspace = 0.05 # [in]
hspace = wspace*float(n_w + n_slices)/(n_h + n_slices)
axes = []
for i in range(nrow):
for j in range(ncol):
ind = i*ncol + j
if ind >= n_subfig:
break
gs = gridspec.GridSpecFromSubplotSpec(
2, 2,
width_ratios=[n_w, n_slices],
height_ratios=[n_h, n_slices],
subplot_spec=gs_master[i, j],
wspace=wspace, hspace=hspace,
)
ax_z = plt.Subplot(fig, gs[0, 0])
ax_z.set_title('frame={}'.format(frames[ind]))
ax_y = plt.Subplot(fig, gs[1, 0], sharex=ax_z)
ax_x = plt.Subplot(fig, gs[0, 1], sharey=ax_z)
project_image_stack(img_sequence[frames[ind]],
axes=[ax_z, ax_y, ax_x])
fig.add_subplot(ax_z)
fig.add_subplot(ax_y)
fig.add_subplot(ax_x)
axes.append((ax_z, ax_y, ax_x))
return fig, axes
if __name__ == "__main__":
image_sequence = np.random.rand(5, 20, 30, 40)
fig, axes = project_image_sequence(image_sequence)
fig.savefig("min_example.png", bbox_inches='tight')
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20151207/b70efaef/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: sequence_of_projections.png
Type: image/png
Size: 41734 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20151207/b70efaef/attachment-0001.png>
More information about the Matplotlib-users
mailing list