Esempio n. 1
0
def plot_colorbar(cax,
                  cmap,
                  hue_norm,
                  cnorm=None,
                  label=None,
                  orientation='vertical',
                  labelsize=4,
                  linewidth=0.5):
    if isinstance(cmap, str):
        cmap = copy.copy(get_cmap(cmap))
    if cnorm is None:
        cnorm = Normalize(vmin=hue_norm[0], vmax=hue_norm[1])
    from .utilities import smart_number_format

    colorbar = ColorbarBase(cax,
                            cmap=cmap,
                            norm=cnorm,
                            format=ticker.FuncFormatter(smart_number_format),
                            orientation=orientation,
                            extend='both')
    colorbar.locator = ticker.MaxNLocator(nbins=3)
    colorbar.update_ticks()

    colorbar.set_label(label, fontsize=labelsize)
    colorbar.outline.set_linewidth(linewidth)
    colorbar.ax.tick_params(size=labelsize,
                            labelsize=labelsize,
                            width=linewidth)
    return cax
Esempio n. 2
0
def display_displacements(simulation_folder, lower_percentile=70, upper_percentile=99.7, save_plot = True, arrow_factor=4):
    """
    show the total displacement field or the masked range of displacements by size
    simulation_folder: path to simulation folder
    lower_percentile and upper_percentile give range of deformationsize which is used
    as a mask 
    save_plot: option to save the plot to the simulation folder
    arrow_factor: scales the arrow length in the plot
    To increase plotting speed you might increase the lower percentile (e.g 30 instead 0)
    """
    # load in deformations and coordinates
    r =  np.genfromtxt(os.path.join(simulation_folder, "R.dat"))       # positions
    u =  np.genfromtxt(os.path.join(simulation_folder, "Ufound.dat"))     #deformations  
    uabs = np.sqrt(np.sum(u ** 2., axis=1))   # absolute values for filtering
   
    # filter displacements by absolute size
    mask = (uabs > np.percentile(uabs, lower_percentile)) & (uabs < np.percentile(uabs, upper_percentile))
    r2 = r[mask]
    u2 = u[mask]
    uabs2 = uabs[mask]
    
    # plot the masked deformation
    fig = plt.figure()
    ax1 = fig.gca(projection='3d', label='fitted-displ', rasterized=True)

    color_bounds1 =  np.array([np.percentile(uabs2, 0), np.percentile(uabs2, 99.8)]) * 10 ** 6  

    np.random.seed(1234)
    for r2i, u2i, uabs2i in tqdm(zip(r2 * 10 ** 6, u2 * 10 ** 6, uabs2 * (10 ** 6))):
        # if np.random.uniform(0, 1) < 0.2:  # uabs2i/u_upper:
        color = plt.cm.jet(((uabs2i - color_bounds1[0]) / (color_bounds1[1] - color_bounds1[0])))
        alpha = 1. - (r2i[0] - r2i[1]) / (270. * 0.5)
    
        if alpha > 1:
            alpha = 1.
        if alpha < 0:
            alpha = 0.
    
        plt.quiver(r2i[0], r2i[1], r2i[2], u2i[0], u2i[1], u2i[2], length=uabs2i * arrow_factor ,
                   color=color, arrow_length_ratio=0, alpha=alpha, pivot='tip', linewidth=0.5)
   
    # plot colorbar   ---------------------------------------------------------
    cbaxes = fig.add_axes([0.15, 0.1, 0.125, 0.010])
    cmap = plt.cm.jet
    norm = plt.Normalize(vmin=color_bounds1[0], vmax=color_bounds1[1])
    cb1 = ColorbarBase(cbaxes, cmap=cmap, norm=norm, orientation='horizontal')
    cb1.set_label('Displacements [µm]')
    tick_locator = ticker.MaxNLocator(nbins=3)
    cb1.locator = tick_locator
    cb1.update_ticks()

    ax1.w_xaxis.set_pane_color((0.2, 0.2, 0.2, 1.0))
    ax1.w_yaxis.set_pane_color((0.2, 0.2, 0.2, 1.0))
    ax1.w_zaxis.set_pane_color((0.2, 0.2, 0.2, 1.0))
    
    if save_plot:
        plt.savefig( os.path.join(simulation_folder,'deformations_plot_lower_{}_upper_{}.png'.format(lower_percentile, upper_percentile)), dpi=500, bbox_inches="tight", pad_inches=0)
         
    return
Esempio n. 3
0
class PanelColourBar(wx.Panel):

    def __init__(self, parent, colourMap):
        wx.Panel.__init__(self, parent)
        dpi = wx.ScreenDC().GetPPI()[0]
        figure = Figure(facecolor='white', dpi=dpi)
        figure.set_size_inches(200.0 / dpi, 25.0 / dpi)
        self.canvas = FigureCanvas(self, -1, figure)
        axes = figure.add_subplot(111)
        figure.subplots_adjust(0, 0, 1, 1)
        norm = Normalize(vmin=0, vmax=1)
        self.bar = ColorbarBase(axes, norm=norm, orientation='horizontal',
                                cmap=cm.get_cmap(colourMap))
        axes.xaxis.set_visible(False)

    def set_map(self, colourMap):
        self.bar.set_cmap(colourMap)
        self.bar.update_ticks()
        self.bar.draw_all()
        self.canvas.draw()
Esempio n. 4
0
def create_colorbar(cax,
                    cmap_range=(0, 1),
                    cmap_name="jet",
                    colorbar_title="",
                    colorbar_loc="top",
                    ticksize=8,
                    num_ticks=None):
    """ create colorbar

    see https://matplotlib.org/devdocs/tutorials/colors/colorbar_only.html

    Parameters
    ----------
    cax: matplotlib.axes.Axes
    cmap_name: str
    cmap_range: tuple
    colorbar_title: str
    colorbar_loc: str
        'top' or 'bottom'
    ticksize: int

    """
    assert colorbar_loc == "top" or colorbar_loc == "bottom"
    norm = Normalize(vmin=cmap_range[0], vmax=cmap_range[1])
    cmap = get_cmap(cmap_name)
    cbar = ColorbarBase(cax,
                        cmap=cmap,
                        norm=norm,
                        orientation="horizontal",
                        label=colorbar_title,
                        ticklocation=colorbar_loc,
                        extend="both")
    #tick_locator = ticker.MaxNLocator(nbins=5)
    if num_ticks is not None:
        tick_locator = ticker.LinearLocator(numticks=num_ticks)
        cbar.locator = tick_locator
        cbar.update_ticks()
    cax.tick_params(labelsize=ticksize)
    return cbar
Esempio n. 5
0
class BaseSlicer(object):
    """ The main purpose of these class is to have auto adjust of axes size
        to the data with different layout of cuts.
    """
    # This actually encodes the figsize for only one axe
    _default_figsize = [2.2, 2.6]
    _axes_class = CutAxes

    def __init__(self, cut_coords, axes=None, black_bg=False, **kwargs):
        """ Create 3 linked axes for plotting orthogonal cuts.

            Parameters
            ----------
            cut_coords: 3 tuple of ints
                The cut position, in world space.
            axes: matplotlib axes object, optional
                The axes that will be subdivided in 3.
            black_bg: boolean, optional
                If True, the background of the figure will be put to
                black. If you wish to save figures with a black background,
                you will need to pass "facecolor='k', edgecolor='k'" to 
                pylab's savefig.

        """
        self.cut_coords = cut_coords
        if axes is None:
            axes = pl.axes((0., 0., 1., 1.))
            axes.axis('off')
        self.frame_axes = axes
        axes.set_zorder(1)
        bb = axes.get_position()
        self.rect = (bb.x0, bb.y0, bb.x1, bb.y1)
        self._black_bg = black_bg
        self._colorbar = False
        self._colorbar_width = 0.05 * bb.width
        self._colorbar_margin = dict(left=0.25 * bb.width,
                                     right=0.02 * bb.width,
                                     top=0.05 * bb.height,
                                     bottom=0.05 * bb.height)
        self._init_axes(**kwargs)

    @staticmethod
    def find_cut_coords(img=None, threshold=None, cut_coords=None):
        # Implement this as a staticmethod or a classmethod when
        # subclassing
        raise NotImplementedError

    @classmethod
    def init_with_figure(cls,
                         img,
                         threshold=None,
                         cut_coords=None,
                         figure=None,
                         axes=None,
                         black_bg=False,
                         leave_space=False,
                         colorbar=False,
                         **kwargs):
        # deal with "fake" 4D images
        if img is not None and img is not False:
            img = _utils.check_niimg(img, ensure_3d=True)

        cut_coords = cls.find_cut_coords(img, threshold, cut_coords)
        facecolor = 'k' if black_bg else 'w'

        if isinstance(axes, pl.Axes) and figure is None:
            figure = axes.figure
            # axes.set_axis_bgcolor(facecolor)

        if not isinstance(figure, pl.Figure):
            # Make sure that we have a figure
            figsize = cls._default_figsize[:]

            # Adjust for the number of axes
            figsize[0] *= len(cut_coords)

            # Make space for the colorbar
            if colorbar:
                figsize[0] += .7

            if leave_space:
                figsize[0] += 3.4
            figure = pl.figure(figure, figsize=figsize, facecolor=facecolor)

        if isinstance(axes, pl.Axes):
            assert axes.figure is figure, ("The axes passed are not "
                                           "in the figure")

        if axes is None:
            axes = [0., 0., 1., 1.]
            if leave_space:
                axes = [0.3, 0, .7, 1.]
        if operator.isSequenceType(axes):
            axes = figure.add_axes(axes)
        # People forget to turn their axis off, or to set the zorder, and
        # then they cannot see their slicer
        axes.axis('off')
        return cls(cut_coords, axes, black_bg, **kwargs)

    def title(self,
              text,
              x=0.01,
              y=0.99,
              size=15,
              color=None,
              bgcolor=None,
              alpha=1,
              **kwargs):
        """ Write a title to the view.

            Parameters
            ----------
            text: string
                The text of the title
            x: float, optional
                The horizontal position of the title on the frame in 
                fraction of the frame width.
            y: float, optional
                The vertical position of the title on the frame in 
                fraction of the frame height.
            size: integer, optional
                The size of the title text.
            color: matplotlib color specifier, optional
                The color of the font of the title.
            bgcolor: matplotlib color specifier, optional
                The color of the background of the title.
            alpha: float, optional
                The alpha value for the background.
            kwargs:
                Extra keyword arguments are passed to matplotlib's text
                function.
        """
        if color is None:
            color = 'k' if self._black_bg else 'w'
        if bgcolor is None:
            bgcolor = 'w' if self._black_bg else 'k'
        if hasattr(self, '_cut_displayed'):
            first_axe = self._cut_displayed[0]
        else:
            first_axe = self.cut_coords[0]
        ax = self.axes[first_axe].ax
        ax.text(x,
                y,
                text,
                transform=self.frame_axes.transAxes,
                horizontalalignment='left',
                verticalalignment='top',
                size=size,
                color=color,
                bbox=dict(boxstyle="square,pad=.3",
                          ec=bgcolor,
                          fc=bgcolor,
                          alpha=alpha),
                zorder=1000,
                **kwargs)
        ax.set_zorder(1000)

    def add_overlay(self, img, threshold=1e-6, colorbar=False, **kwargs):
        """ Plot a 3D map in all the views.

            Parameters
            -----------
            img: Niimg-like object
                See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
                If it is a masked array, only the non-masked part will be
                plotted.
            threshold : a number, None
                If None is given, the maps are not thresholded.
                If a number is given, it is used to threshold the maps:
                values below the threshold (in absolute value) are
                plotted as transparent.
            colorbar: boolean, optional
                If True, display a colorbar on the right of the plots.
            kwargs:
                Extra keyword arguments are passed to imshow.
        """
        if colorbar and self._colorbar:
            raise ValueError("This figure already has an overlay with a "
                             "colorbar.")
        else:
            self._colorbar = colorbar

        img = _utils.check_niimg(img, ensure_3d=True)

        if threshold is not None:
            data = img.get_data()
            if threshold == 0:
                data = np.ma.masked_equal(data, 0, copy=False)
            else:
                data = np.ma.masked_inside(data,
                                           -threshold,
                                           threshold,
                                           copy=False)
            img = nibabel.Nifti1Image(data, img.get_affine())

        # To make sure that add_overlay has a consistant default behavior
        # with plot_stat_map
        kwargs.setdefault('interpolation', 'nearest')
        ims = self._map_show(img, type='imshow', **kwargs)

        if colorbar:
            self._colorbar_show(ims[0], threshold)

        pl.draw_if_interactive()

    def add_contours(self, img, **kwargs):
        """ Contour a 3D map in all the views.

            Parameters
            -----------
            img: Niimg-like object
                See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
                Provides image to plot.
            kwargs:
                Extra keyword arguments are passed to contour, see the
                documentation of pylab.contour
                Useful, arguments are typical "levels", which is a
                list of values to use for plotting a contour, and
                "colors", which is one color or a list of colors for
                these contours.
        """
        self._map_show(img, type='contour', **kwargs)
        pl.draw_if_interactive()

    def _map_show(self,
                  img,
                  type='imshow',
                  resampling_interpolation='continuous',
                  **kwargs):
        img = reorder_img(img, resample=resampling_interpolation)

        affine = img.get_affine()
        data = img.get_data()
        data_bounds = get_bounds(data.shape, affine)
        (xmin, xmax), (ymin, ymax), (zmin, zmax) = data_bounds

        xmin_, xmax_, ymin_, ymax_, zmin_, zmax_ = \
                                        xmin, xmax, ymin, ymax, zmin, zmax

        if hasattr(data, 'mask') and isinstance(data.mask, np.ndarray):
            not_mask = np.logical_not(data.mask)
            xmin_, xmax_, ymin_, ymax_, zmin_, zmax_ = \
                    get_mask_bounds(nibabel.Nifti1Image(not_mask.astype(np.int),
                                    affine))

        data_2d_list = []
        for display_ax in self.axes.itervalues():
            try:
                data_2d = display_ax.transform_to_2d(data, affine)
            except IndexError:
                # We are cutting outside the indices of the data
                data_2d = None

            data_2d_list.append(data_2d)

        if 'vmin' not in kwargs:
            kwargs['vmin'] = min(d.min() for d in data_2d_list
                                 if d is not None)
        if 'vmax' not in kwargs:
            kwargs['vmax'] = max(d.max() for d in data_2d_list
                                 if d is not None)

        bounding_box = (xmin_, xmax_), (ymin_, ymax_), (zmin_, zmax_)

        ims = []
        to_iterate_over = zip(self.axes.values(), data_2d_list)
        for display_ax, data_2d in to_iterate_over:
            if data_2d is not None:
                im = display_ax.draw_2d(data_2d,
                                        data_bounds,
                                        bounding_box,
                                        type=type,
                                        **kwargs)
                ims.append(im)
        return ims

    def _colorbar_show(self, im, threshold):
        if threshold is None:
            offset = 0
        else:
            offset = threshold
        if offset > im.norm.vmax:
            offset = im.norm.vmax

        # create new  axis for the colorbar
        figure = self.frame_axes.figure
        _, y0, x1, y1 = self.rect
        height = y1 - y0
        x_adjusted_width = self._colorbar_width / len(self.axes)
        x_adjusted_margin = self._colorbar_margin['right'] / len(self.axes)
        lt_wid_top_ht = [
            x1 - (x_adjusted_width + x_adjusted_margin),
            y0 + self._colorbar_margin['top'], x_adjusted_width, height -
            (self._colorbar_margin['top'] + self._colorbar_margin['bottom'])
        ]
        self._colorbar_ax = figure.add_axes(lt_wid_top_ht, axis_bgcolor='w')

        our_cmap = im.cmap
        # edge case where the data has a single value
        # yields a cryptic matplotlib error message
        # when trying to plot the color bar
        nb_ticks = 5 if im.norm.vmin != im.norm.vmax else 1
        ticks = np.linspace(im.norm.vmin, im.norm.vmax, nb_ticks)
        bounds = np.linspace(im.norm.vmin, im.norm.vmax, our_cmap.N)

        # some colormap hacking
        cmaplist = [our_cmap(i) for i in range(our_cmap.N)]
        istart = int(im.norm(-offset) * (our_cmap.N - 1))
        istop = int(im.norm(offset) * (our_cmap.N - 1))
        for i in range(istart, istop):
            cmaplist[i] = (0.5, 0.5, 0.5, 1.)  # just an average gray color
        our_cmap = our_cmap.from_list('Custom cmap', cmaplist, our_cmap.N)

        self._cbar = ColorbarBase(self._colorbar_ax,
                                  ticks=ticks,
                                  norm=im.norm,
                                  orientation='vertical',
                                  cmap=our_cmap,
                                  boundaries=bounds,
                                  spacing='proportional')
        self._cbar.set_ticklabels(["%.2g" % t for t in ticks])

        self._colorbar_ax.yaxis.tick_left()
        tick_color = 'w' if self._black_bg else 'k'
        for tick in self._colorbar_ax.yaxis.get_ticklabels():
            tick.set_color(tick_color)
        self._colorbar_ax.yaxis.set_tick_params(width=0)

        self._cbar.update_ticks()

    def add_edges(self, img, color='r'):
        """ Plot the edges of a 3D map in all the views.

            Parameters
            -----------
            map: 3D ndarray
                The 3D map to be plotted. If it is a masked array, only
                the non-masked part will be plotted.
            affine: 4x4 ndarray
                The affine matrix giving the transformation from voxel
                indices to world space.
            color: matplotlib color: string or (r, g, b) value
                The color used to display the edge map
        """
        img = reorder_img(img)
        data = img.get_data()
        affine = img.get_affine()
        single_color_cmap = colors.ListedColormap([color])
        data_bounds = get_bounds(data.shape, img.get_affine())

        # For each ax, cut the data and plot it
        for display_ax in self.axes.itervalues():
            try:
                data_2d = display_ax.transform_to_2d(data, affine)
                edge_mask = _edge_map(data_2d)
            except IndexError:
                # We are cutting outside the indices of the data
                continue
            display_ax.draw_2d(edge_mask,
                               data_bounds,
                               data_bounds,
                               type='imshow',
                               cmap=single_color_cmap)

        pl.draw_if_interactive()

    def annotate(self, left_right=True, positions=True, size=12, **kwargs):
        """ Add annotations to the plot.

            Parameters
            ----------
            left_right: boolean, optional
                If left_right is True, annotations indicating which side
                is left and which side is right are drawn.
            positions: boolean, optional
                If positions is True, annotations indicating the
                positions of the cuts are drawn.
            size: integer, optional
                The size of the text used.
            kwargs:
                Extra keyword arguments are passed to matplotlib's text
                function.
        """
        kwargs = kwargs.copy()
        if not 'color' in kwargs:
            if self._black_bg:
                kwargs['color'] = 'w'
            else:
                kwargs['color'] = 'k'

        for display_ax in self.axes.values():
            if self._black_bg:
                # Remove transparency to avoid slice lines intersecting w/label
                bg_color = (display_ax.ax.get_axis_bgcolor()
                            or display_ax.ax.get_figure().get_facecolor())
            else:
                bg_color = None

            if left_right:
                display_ax.draw_left_right(size=size,
                                           bg_color=bg_color,
                                           **kwargs)
            if positions:
                display_ax.draw_position(size=size,
                                         bg_color=bg_color,
                                         **kwargs)

    def close(self):
        """ Close the figure. This is necessary to avoid leaking memory.
        """
        pl.close(self.frame_axes.figure.number)

    def savefig(self, filename, dpi=None):
        """ Save the figure to a file

            Parameters
            ==========
            filename: string
                The file name to save to. It's extension determines the
                file type, typically '.png', '.svg' or '.pdf'.

            dpi: None or scalar
                The resolution in dots per inch.
        """
        facecolor = edgecolor = 'k' if self._black_bg else 'w'
        self.frame_axes.figure.savefig(filename,
                                       dpi=dpi,
                                       facecolor=facecolor,
                                       edgecolor=edgecolor)
Esempio n. 6
0
class BaseSlicer(object):
    """ The main purpose of these class is to have auto adjust of axes size
        to the data with different layout of cuts.
    """
    # This actually encodes the figsize for only one axe
    _default_figsize = [2.2, 2.6]
    _axes_class = CutAxes

    def __init__(self, cut_coords, axes=None, black_bg=False, **kwargs):
        """ Create 3 linked axes for plotting orthogonal cuts.

            Parameters
            ----------
            cut_coords: 3 tuple of ints
                The cut position, in world space.
            axes: matplotlib axes object, optional
                The axes that will be subdivided in 3.
            black_bg: boolean, optional
                If True, the background of the figure will be put to
                black. If you wish to save figures with a black background,
                you will need to pass "facecolor='k', edgecolor='k'" to 
                pylab's savefig.

        """
        self.cut_coords = cut_coords
        if axes is None:
            axes = plt.axes((0., 0., 1., 1.))
            axes.axis('off')
        self.frame_axes = axes
        axes.set_zorder(1)
        bb = axes.get_position()
        self.rect = (bb.x0, bb.y0, bb.x1, bb.y1)
        self._black_bg = black_bg
        self._colorbar = False
        self._colorbar_width = 0.05 * bb.width
        self._colorbar_margin = dict(left=0.25 * bb.width,
                                     right=0.02 * bb.width,
                                     top=0.05 * bb.height,
                                     bottom=0.05 * bb.height)
        self._init_axes(**kwargs)

    @staticmethod
    def find_cut_coords(img=None, threshold=None, cut_coords=None):
        # Implement this as a staticmethod or a classmethod when
        # subclassing
        raise NotImplementedError

    @classmethod
    def init_with_figure(cls, img, threshold=None,
                         cut_coords=None, figure=None, axes=None,
                         black_bg=False, leave_space=False, colorbar=False,
                         **kwargs):
        # deal with "fake" 4D images
        if img is not None and img is not False:
            img = _utils.check_niimg_3d(img)

        cut_coords = cls.find_cut_coords(img, threshold, cut_coords)

        if isinstance(axes, plt.Axes) and figure is None:
            figure = axes.figure

        if not isinstance(figure, plt.Figure):
            # Make sure that we have a figure
            figsize = cls._default_figsize[:]
            
            # Adjust for the number of axes
            figsize[0] *= len(cut_coords)
            
            # Make space for the colorbar
            if colorbar:
                figsize[0] += .7
                
            facecolor = 'k' if black_bg else 'w'

            if leave_space:
                figsize[0] += 3.4
            figure = plt.figure(figure, figsize=figsize,
                            facecolor=facecolor)
        if isinstance(axes, plt.Axes):
            assert axes.figure is figure, ("The axes passed are not "
                    "in the figure")

        if axes is None:
            axes = [0., 0., 1., 1.]
            if leave_space:
                axes = [0.3, 0, .7, 1.]
        if isinstance(axes, collections.Sequence):
            axes = figure.add_axes(axes)
        # People forget to turn their axis off, or to set the zorder, and
        # then they cannot see their slicer
        axes.axis('off')
        return cls(cut_coords, axes, black_bg, **kwargs)


    def title(self, text, x=0.01, y=0.99, size=15, color=None, bgcolor=None,
              alpha=1, **kwargs):
        """ Write a title to the view.

            Parameters
            ----------
            text: string
                The text of the title
            x: float, optional
                The horizontal position of the title on the frame in 
                fraction of the frame width.
            y: float, optional
                The vertical position of the title on the frame in 
                fraction of the frame height.
            size: integer, optional
                The size of the title text.
            color: matplotlib color specifier, optional
                The color of the font of the title.
            bgcolor: matplotlib color specifier, optional
                The color of the background of the title.
            alpha: float, optional
                The alpha value for the background.
            kwargs:
                Extra keyword arguments are passed to matplotlib's text
                function.
        """
        if color is None:
            color = 'k' if self._black_bg else 'w'
        if bgcolor is None:
            bgcolor = 'w' if self._black_bg else 'k'
        if hasattr(self, '_cut_displayed'):
            first_axe = self._cut_displayed[0]
        else:
            first_axe = self.cut_coords[0]
        ax = self.axes[first_axe].ax
        ax.text(x, y, text,
                transform=self.frame_axes.transAxes,
                horizontalalignment='left',
                verticalalignment='top',
                size=size, color=color,
                bbox=dict(boxstyle="square,pad=.3",
                          ec=bgcolor, fc=bgcolor, alpha=alpha),
                zorder=1000,
                **kwargs)
        ax.set_zorder(1000)


    def add_overlay(self, img, threshold=1e-6, colorbar=False, **kwargs):
        """ Plot a 3D map in all the views.

            Parameters
            -----------
            img: Niimg-like object
                See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
                If it is a masked array, only the non-masked part will be
                plotted.
            threshold : a number, None
                If None is given, the maps are not thresholded.
                If a number is given, it is used to threshold the maps:
                values below the threshold (in absolute value) are
                plotted as transparent.
            colorbar: boolean, optional
                If True, display a colorbar on the right of the plots.
            kwargs:
                Extra keyword arguments are passed to imshow.
        """
        if colorbar and self._colorbar:
            raise ValueError("This figure already has an overlay with a "
                             "colorbar.")
        else:
            self._colorbar = colorbar

        img = _utils.check_niimg_3d(img)

        if threshold is not None:
            data = img.get_data()
            if threshold == 0:
                data = np.ma.masked_equal(data, 0, copy=False)
            else:
                data = np.ma.masked_inside(data, -threshold, threshold,
                                           copy=False)
            img = new_img_like(img, data, img.get_affine())

        # Make sure that add_overlay shows consistent default behavior
        # with plot_stat_map
        kwargs.setdefault('interpolation', 'nearest')
        ims = self._map_show(img, type='imshow', **kwargs)

        if colorbar:
            self._colorbar_show(ims[0], threshold)

        plt.draw_if_interactive()

    def add_contours(self, img, **kwargs):
        """ Contour a 3D map in all the views.

            Parameters
            -----------
            img: Niimg-like object
                See http://nilearn.github.io/building_blocks/manipulating_mr_images.html#niimg.
                Provides image to plot.
            kwargs:
                Extra keyword arguments are passed to contour, see the
                documentation of pylab.contour
                Useful, arguments are typical "levels", which is a
                list of values to use for plotting a contour, and
                "colors", which is one color or a list of colors for
                these contours.
        """
        self._map_show(img, type='contour', **kwargs)
        plt.draw_if_interactive()

    def _map_show(self, img, type='imshow', resampling_interpolation='continuous', **kwargs):
        img = reorder_img(img, resample=resampling_interpolation)

        affine = img.get_affine()
        data = img.get_data()
        data_bounds = get_bounds(data.shape, affine)
        (xmin, xmax), (ymin, ymax), (zmin, zmax) = data_bounds

        xmin_, xmax_, ymin_, ymax_, zmin_, zmax_ = \
                                        xmin, xmax, ymin, ymax, zmin, zmax

        if hasattr(data, 'mask') and isinstance(data.mask, np.ndarray):
            not_mask = np.logical_not(data.mask)
            xmin_, xmax_, ymin_, ymax_, zmin_, zmax_ = \
                    get_mask_bounds(new_img_like(img, not_mask, affine))

        data_2d_list = []
        for display_ax in self.axes.values():
            try:
                data_2d = display_ax.transform_to_2d(data, affine)
            except IndexError:
                # We are cutting outside the indices of the data
                data_2d = None

            data_2d_list.append(data_2d)

        if 'vmin' not in kwargs:
            kwargs['vmin'] = min(d.min() for d in data_2d_list
                                 if d is not None)
        if 'vmax' not in kwargs:
            kwargs['vmax'] = max(d.max() for d in data_2d_list
                                 if d is not None)

        bounding_box = (xmin_, xmax_), (ymin_, ymax_), (zmin_, zmax_)

        ims = []
        to_iterate_over = zip(self.axes.values(), data_2d_list)
        for display_ax, data_2d in to_iterate_over:
            if data_2d is not None:
                im = display_ax.draw_2d(data_2d, data_bounds, bounding_box,
                                        type=type, **kwargs)
                ims.append(im)
        return ims

    def _colorbar_show(self, im, threshold):
        if threshold is None:
            offset = 0
        else:
            offset = threshold
        if offset > im.norm.vmax:
            offset = im.norm.vmax

        # create new  axis for the colorbar
        figure = self.frame_axes.figure
        _, y0, x1, y1 = self.rect
        height = y1 - y0
        x_adjusted_width = self._colorbar_width / len(self.axes)
        x_adjusted_margin = self._colorbar_margin['right'] / len(self.axes)
        lt_wid_top_ht = [x1 - (x_adjusted_width + x_adjusted_margin),
                         y0 + self._colorbar_margin['top'],
                         x_adjusted_width,
                         height - (self._colorbar_margin['top'] +
                                   self._colorbar_margin['bottom'])]
        self._colorbar_ax = figure.add_axes(lt_wid_top_ht, axis_bgcolor='w')

        our_cmap = im.cmap
        # edge case where the data has a single value
        # yields a cryptic matplotlib error message
        # when trying to plot the color bar
        nb_ticks = 5 if im.norm.vmin != im.norm.vmax else 1
        ticks = np.linspace(im.norm.vmin, im.norm.vmax, nb_ticks)
        bounds = np.linspace(im.norm.vmin, im.norm.vmax, our_cmap.N)

        # some colormap hacking
        cmaplist = [our_cmap(i) for i in range(our_cmap.N)]
        istart = int(im.norm(-offset, clip=True) * (our_cmap.N - 1))
        istop = int(im.norm(offset, clip=True) * (our_cmap.N - 1))
        for i in range(istart, istop):
            cmaplist[i] = (0.5, 0.5, 0.5, 1.)  # just an average gray color
        if im.norm.vmin == im.norm.vmax:  # len(np.unique(data)) == 1 ?
            return
        else:
            our_cmap = our_cmap.from_list('Custom cmap', cmaplist, our_cmap.N)

        self._cbar = ColorbarBase(
            self._colorbar_ax, ticks=ticks, norm=im.norm,
            orientation='vertical', cmap=our_cmap, boundaries=bounds,
            spacing='proportional')
        self._cbar.set_ticklabels(["%.2g" % t for t in ticks])

        self._colorbar_ax.yaxis.tick_left()
        tick_color = 'w' if self._black_bg else 'k'
        for tick in self._colorbar_ax.yaxis.get_ticklabels():
            tick.set_color(tick_color)
        self._colorbar_ax.yaxis.set_tick_params(width=0)

        self._cbar.update_ticks()

    def add_edges(self, img, color='r'):
        """ Plot the edges of a 3D map in all the views.

            Parameters
            -----------
            map: 3D ndarray
                The 3D map to be plotted. If it is a masked array, only
                the non-masked part will be plotted.
            affine: 4x4 ndarray
                The affine matrix giving the transformation from voxel
                indices to world space.
            color: matplotlib color: string or (r, g, b) value
                The color used to display the edge map
        """
        img = reorder_img(img)
        data = img.get_data()
        affine = img.get_affine()
        single_color_cmap = colors.ListedColormap([color])
        data_bounds = get_bounds(data.shape, img.get_affine())

        # For each ax, cut the data and plot it
        for display_ax in self.axes.values():
            try:
                data_2d = display_ax.transform_to_2d(data, affine)
                edge_mask = _edge_map(data_2d)
            except IndexError:
                # We are cutting outside the indices of the data
                continue
            display_ax.draw_2d(edge_mask, data_bounds, data_bounds,
                               type='imshow', cmap=single_color_cmap)

        plt.draw_if_interactive()

    def annotate(self, left_right=True, positions=True, size=12, **kwargs):
        """ Add annotations to the plot.

            Parameters
            ----------
            left_right: boolean, optional
                If left_right is True, annotations indicating which side
                is left and which side is right are drawn.
            positions: boolean, optional
                If positions is True, annotations indicating the
                positions of the cuts are drawn.
            size: integer, optional
                The size of the text used.
            kwargs:
                Extra keyword arguments are passed to matplotlib's text
                function.
        """
        kwargs = kwargs.copy()
        if not 'color' in kwargs:
            if self._black_bg:
                kwargs['color'] = 'w'
            else:
                kwargs['color'] = 'k'

        bg_color = ('k' if self._black_bg else 'w')
        if left_right:
            for display_ax in self.axes.values():
                display_ax.draw_left_right(size=size, bg_color=bg_color,
                                       **kwargs)

        if positions:
            for display_ax in self.axes.values():
                display_ax.draw_position(size=size, bg_color=bg_color,
                                       **kwargs)

    def close(self):
        """ Close the figure. This is necessary to avoid leaking memory.
        """
        plt.close(self.frame_axes.figure.number)

    def savefig(self, filename, dpi=None):
        """ Save the figure to a file

            Parameters
            ==========
            filename: string
                The file name to save to. It's extension determines the
                file type, typically '.png', '.svg' or '.pdf'.

            dpi: None or scalar
                The resolution in dots per inch.
        """
        facecolor = edgecolor = 'k' if self._black_bg else 'w'
        self.frame_axes.figure.savefig(filename, dpi=dpi,
                                       facecolor=facecolor,
                                       edgecolor=edgecolor)
Esempio n. 7
0
def display_forces(simulation_folder, lower_percentile=97.5, upper_percentile=99, save_plot = True, arrow_factor=5):
    """
    show the force density field of the masked force components
    
    simulation_folder: path to simulation folder
    lower_percentile and upper_percentile give range of forces which is used
    as a mask 
    save_plot: option to save the plot to the simulation folder
    arrow_factor: scales the arrow length in the plot
    """    
     # load in forces and coordinates
    r =  np.genfromtxt(os.path.join(simulation_folder, "R.dat"))       # positions
    f =  np.genfromtxt(os.path.join(simulation_folder, "Fden.dat"))     # force densities  
    fabs = np.sqrt(np.sum(f ** 2., axis=1))   # absolute values for filtering    

    # filter 
    mask = (fabs > np.percentile(fabs, lower_percentile)) & (fabs < np.percentile(fabs, upper_percentile))
    r2 = r[mask]
    f2 = f[mask]
    fabs2 = fabs[mask]

    # Force
    fig2 = plt.figure()
    ax2 = fig2.gca(projection='3d', label='fitted-forces', rasterized=True)
    color_bounds2 = np.array([np.percentile(fabs2, 0.1), np.percentile(fabs2, 99.9)]) * 10 ** -6


    for r2i, f2i, fabs2i in tqdm(zip(r2 * 10 ** 6, f2 * 10 ** -6, fabs2 * (10 ** -6))):  #*f_scale
        color = plt.cm.hot(((fabs2i - color_bounds2[0]) / (color_bounds2[1] - color_bounds2[0])))
        # alpha = 1. - (r2i[0] - r2i[1]) / (270. * 1.25)
        # if alpha > 1:
        #     alpha = 1.
        alpha = 1.        
        ax2.quiver(r2i[0], r2i[1], r2i[2], f2i[0], f2i[1], f2i[2], length=fabs2i * arrow_factor ,
                    color=color, arrow_length_ratio=0, alpha=alpha, pivot='tip', linewidth=0.5)
    
    # plot colorbar   ---------------------------------------------------------
    cbaxes = fig2.add_axes([0.15, 0.1, 0.125, 0.010])
    cmap = plt.cm.hot
    norm = plt.Normalize(vmin=color_bounds2[0], vmax=color_bounds2[1])
    cb1 = ColorbarBase(cbaxes, cmap=cmap, norm=norm, orientation='horizontal')
    cb1.set_label('Force Den. [pN/µm³]')
    tick_locator = ticker.MaxNLocator(nbins=3)
    cb1.locator = tick_locator
    cb1.update_ticks()
    # -------------------------------------------------------------------------
    #ax2.set_xlim([-150, 150])   can be used to make an individual plot
    #ax2.set_ylim([-150, 150])
    #ax2.set_zlim([-150, 150])
    #ax2.set_xticks([-100, -50, 0, 50, 100])
    #ax2.set_yticks([-100, -50, 0, 50, 100])
    #ax2.set_zticks([-100, -50, 0, 50, 100])
    # ax2.set_xticklabels(['']*5)
    # ax2.set_yticklabels(['']*5)
    # ax2.set_zticklabels(['']*5)
    ax2.w_xaxis.set_pane_color((0.2, 0.2, 0.2, 1.0))
    ax2.w_yaxis.set_pane_color((0.2, 0.2, 0.2, 1.0))
    ax2.w_zaxis.set_pane_color((0.2, 0.2, 0.2, 1.0))

    if save_plot:
     plt.savefig( os.path.join(simulation_folder,'force_density_plot_lower_{}_upper_{}.png'.format(lower_percentile, upper_percentile)), dpi=500 , bbox_inches="tight", pad_inches=0)
  
    return