Skip to content
Permalink
Browse files

ENH add save_3d_views and plot_panels functions (#337)

* ENH add save_3d_views and plot_panels functions

* ENH rename file, fix filename

* FIX leftover
  • Loading branch information...
TomDLT authored and mvdoc committed Sep 16, 2019
1 parent 431ce87 commit a672dea2a2e666af729c9ee40e2323c670e3aae8
Showing with 513 additions and 2 deletions.
  1. +1 −0 cortex/__init__.py
  2. +11 −0 cortex/export/__init__.py
  3. +213 −0 cortex/export/panels.py
  4. +206 −0 cortex/export/save_views.py
  5. +80 −0 examples/utils/plot_multi_panels.py
  6. +2 −2 setup.py
@@ -8,6 +8,7 @@
from cortex.utils import *
from cortex.quickflat import make_figure as quickshow
from cortex.volume import mosaic, unmask
import cortex.export

try:
from cortex import formats
@@ -0,0 +1,11 @@
from .save_views import save_3d_views
from .panels import plot_panels
from .panels import params_flatmap_lateral_medial
from .panels import params_occipital_triple_view

__all__ = [
save_3d_views,
plot_panels,
params_flatmap_lateral_medial,
params_occipital_triple_view,
]
@@ -0,0 +1,213 @@
import os
import errno
import shutil
import tempfile

import numpy as np
import matplotlib.pyplot as plt

from .save_views import save_3d_views


def plot_panels(volume, panels, figsize=(16, 9), save_name=None):
"""Plot on the same figure a number of views, as defined by a list of panel
Parameters
----------
volume : cortex.Volume
The data to plot.
panels : list of dict
List of parameters for each panel. An example of panel is:
{
'extent': [0.000, 0.000, 0.300, 0.300],
'view': {
'hemisphere': 'left',
'angle': 'lateral_pivot',
'surface': 'inflated',
}
}
The `extent` and `zoom` entries are ordered as
[left, bottom, width, height] with values in [0, 1].
figsize : tuple of float
Size of the figure.
save_name : str or None
Name of the file where the figure is saved. None to not save.
Can end with different extensions, such as '.png' of '.pdf'.
Returns
-------
fig : matplotlib.Figure
Created figure. Can be used for instance for custom save functions.
Example
-------
>>> from cortex.export import plot_panels, params_flatmap_lateral_medial
>>> plot_panels(volume, **params_flatmap_lateral_medial)
"""
# list of couple of angles and surfaces
angles_and_surfaces = [(panel['view']['angle'], panel['view']['surface'])
for panel in panels]
# remove redundant couples, e.g. left and right
angles_and_surfaces = list(set(angles_and_surfaces))
list_angles, list_surfaces = list(zip(*angles_and_surfaces))

# create all images
temp_dir = tempfile.mkdtemp()
base_name = os.path.join(temp_dir, 'fig')
filenames = save_3d_views(volume, base_name, list_angles=list_angles,
list_surfaces=list_surfaces, trim=True,
size=(1600 * 4, 900 * 4))

fig = plt.figure(figsize=figsize)
for panel in panels:

# load image
angle_and_surface = (panel['view']['angle'], panel['view']['surface'])
index = angles_and_surfaces.index(angle_and_surface)
image = plt.imread(filenames[index])

# chose hemisphere
if 'hemisphere' in panel['view']:
left, right = np.split(image, [image.shape[1] // 2], axis=1)
if panel['view']['hemisphere'] == 'left':
image = left
else:
image = right

# trim white borders
image = image[image.sum(axis=1).sum(axis=1) > 0]
image = image[:, image.sum(axis=0).sum(axis=1) > 0]

# zoom
if 'zoom' in panel['view']:
left, bottom, width, height = panel['view']['zoom']
left = int(left * image.shape[1])
width = int(width * image.shape[1])
bottom = int(bottom * image.shape[0])
height = int(height * image.shape[0])
image = image[bottom:bottom + height]
image = image[:, left:left + width]

# add ax and image
ax = plt.axes(panel['extent'])
ax.axis('off')
ax.imshow(image)

# note that you might get a slightly different layout with `plt.show()`
# since it might use a different backend
if save_name is not None:
fig.savefig(save_name, bbox_inches='tight', dpi=100)

# delete temporary directory
try:
shutil.rmtree(temp_dir)
except OSError as e:
# reraise if the directory has not already been deleted
if e.errno != errno.ENOENT:
raise

return fig


params_flatmap_lateral_medial = {
'figsize': [16, 9],
'panels': [
{
'extent': [0.000, 0.200, 1.000, 0.800],
'view': {
'angle': 'flatmap',
'surface': 'flatmap'
},
},
{
'extent': [0.300, 0.000, 0.200, 0.200],
'view': {
'hemisphere': 'left',
'angle': 'medial_pivot',
'surface': 'inflated'
}
},
{
'extent': [0.500, 0.000, 0.200, 0.200],
'view': {
'hemisphere': 'right',
'angle': 'medial_pivot',
'surface': 'inflated'
},
},
{
'extent': [0.000, 0.000, 0.300, 0.300],
'view': {
'hemisphere': 'left',
'angle': 'lateral_pivot',
'surface': 'inflated'
}
},
{
'extent': [0.700, 0.000, 0.300, 0.300],
'view': {
'hemisphere': 'right',
'angle': 'lateral_pivot',
'surface': 'inflated'
},
},
]
}

params_occipital_triple_view = {
'figsize': [16, 9],
'panels': [{
'extent': [0.260, 0.000, 0.480, 1.000],
'view': {
'angle': 'flatmap',
'surface': 'flatmap',
'zoom': [0.250, 0.000, 0.500, 1.000]
}
}, {
'extent': [0.000, 0.000, 0.250, 0.333],
'view': {
'hemisphere': 'left',
'angle': 'bottom_pivot',
'surface': 'inflated'
}
}, {
'extent': [0.000, 0.333, 0.250, 0.333],
'view': {
'hemisphere': 'left',
'angle': 'medial_pivot',
'surface': 'inflated'
}
}, {
'extent': [0.000, 0.666, 0.250, 0.333],
'view': {
'hemisphere': 'left',
'angle': 'lateral_pivot',
'surface': 'inflated'
}
}, {
'extent': [0.750, 0.000, 0.250, 0.333],
'view': {
'hemisphere': 'right',
'angle': 'bottom_pivot',
'surface': 'inflated'
}
}, {
'extent': [0.750, 0.333, 0.250, 0.333],
'view': {
'hemisphere': 'right',
'angle': 'medial_pivot',
'surface': 'inflated'
}
}, {
'extent': [0.750, 0.666, 0.250, 0.333],
'view': {
'hemisphere': 'right',
'angle': 'lateral_pivot',
'surface': 'inflated'
}
}]
}

0 comments on commit a672dea

Please sign in to comment.
You can’t perform that action at this time.