Source code for phasemap.plot

# © 2015-2018, ETH Zurich, Institut für Theoretische Physik
# Author: Dominik Gresch <greschd@gmx.ch>
"""
This module contains functions for plotting the phase diagram. The functions are based upon the :py:mod:`matplotlib <matplotlib.pyplot>` package.
"""

from collections import defaultdict, ChainMap

import decorator
import numpy as np
from fsc.export import export

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.colorbar import ColorbarBase
from matplotlib.colors import Normalize, ListedColormap

from ._box import PHASE_UNDEFINED


@decorator.decorator
def _plot(func, result, *, ax=None, add_cbar=True, **kwargs):
    # create ax if it does not exist
    if ax is None:
        fig = plt.figure(figsize=[4, 4])
        ax = fig.add_subplot(111)
    # else just get the figure
    else:
        fig = ax.figure

    xlim = [0, 1]
    ylim = [0, 1]
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)
    ax.set_xticks(xlim)
    ax.set_yticks(ylim)
    ax.set_xticklabels(result.limits[0])
    ax.set_yticklabels(result.limits[1])

    ax, cmap, norm, vals = func(result, ax=ax, **kwargs)

    if add_cbar:
        fig.subplots_adjust(right=0.9)
        cbar_ax = fig.add_axes([0.95, 0.1, 0.04, 0.8])

        color_vals = [norm(c) for c in vals]
        cbar_cmap = ListedColormap([cmap(v) for v in color_vals])
        c_bar = ColorbarBase(
            cbar_ax,
            cmap=cbar_cmap,
            norm=norm,
            ticks=np.linspace(min(vals), max(vals), 2 * len(vals) + 1)[1::2],
        )
        c_bar.solids.set_edgecolor("k")
        c_bar.set_ticklabels(vals)

    return fig


[docs]@export @_plot def boxes( result, *, ax=None, scale_val=None, plot_undefined=False, cmap=None, **kwargs ): """ Plots the phase diagram as a collection of boxes, which are colored according to the estimate of the phase in a given box. Parameters ---------- result: .Result Result of the :func:`.run` phase diagram calculation. ax: :py:mod:`matplotlib <matplotlib.pyplot>` ax Axes where the plot is drawn. add_cbar: bool Determines whether a colorbar is added to the figure. scale_val: list Values to which the colormap is scaled. By default, the colormap is scaled to the set of values which occur in the boxes. plot_undefined: bool Specifies whether the boxes of undefined phase should be plotted (in white). cmap: The colormap which is used to plot the phases. The colormap should take values normalized to [0, 1] and return a 4-tuple specifying the RGBA value (again normalized to [0, 1]. kwargs: Keyword arguments passed to :py:class:`matplotlib.patches.Rectangle`. """ if cmap is None: # don't do this in the signature, otherwise it gets set at import time cmap = plt.get_cmap() all_vals = sorted(set(result.points.values())) or [0] sqrs = [s for s in result.boxes if s.phase not in (None, PHASE_UNDEFINED)] vals = [s.phase for s in sqrs] norm = Normalize() if scale_val is None: norm.autoscale(all_vals) else: norm.autoscale(scale_val) box_colors = cmap([norm(v) for v in vals]) rect_properties = ChainMap(kwargs, dict(lw=0)) for color, box in zip(box_colors, sqrs): ax.add_patch( Rectangle( xy=box.corner, width=box.size[0], height=box.size[1], **ChainMap(rect_properties, dict(facecolor=color, edgecolor=color)) ) ) if plot_undefined: for box in [b for b in result.boxes if b.phase is PHASE_UNDEFINED]: ax.add_patch( Rectangle( xy=box.corner, width=box.size[0], height=box.size[1], **ChainMap(rect_properties, dict(facecolor="white")) ) ) return ax, cmap, norm, all_vals
[docs]@export @_plot def points(result, *, ax=None, scale_val=None, cmap=None, **kwargs): """ Plots the phase diagram as a collection of boxes, which are colored according to the estimate of the phase in a given box. Parameters ---------- result: Result Result of the :func:`.run` phase diagram calculation. ax: :py:mod:`matplotlib <matplotlib.pyplot>` ax Axes where the plot is drawn. add_cbar: bool Determines whether a colorbar is added to the figure. scale_val: list Values to which the colormap is scaled. By default, the colormap is scaled to the set of values which occur in the boxes. cmap: The colormap which is used to plot the phases. The colormap should take values normalized to [0, 1] and return a 4-tuple specifying the RGBA value (again normalized to [0, 1]. kwargs: Keyword arguments passed to :py:meth:`scatter <matplotlib.axes.Axes.scatter>`. """ if cmap is None: # don't do this in the signature, otherwise it gets set at import time cmap = plt.get_cmap() pts = result.points all_vals = sorted(set(pts.values())) or [0] norm = Normalize() if scale_val is None: norm.autoscale(all_vals) else: norm.autoscale(scale_val) point_colors = defaultdict(list) for coord, phase in pts.items(): point_colors[cmap(norm(phase))].append(coord) for color, coordinates in point_colors.items(): ax.scatter( *np.array(coordinates).T, # pylint: disable=not-an-iterable color=color, **kwargs ) return ax, cmap, norm, all_vals