Beispiel #1
0
def demo_fixed_pad_axes():

    fig = plt.figure(2, (6, 6))

    # The first & third items are for padding and the second items are for the axes.
    # sizes are in inch.
    h = [
        Size.Fixed(1.0),
        Size.Scaled(1.),
        Size.Fixed(.2),
    ]
    v = [
        Size.Fixed(0.7),
        Size.Scaled(1.),
        Size.Fixed(.5),
    ]

    divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
    # the width and height of the rectangle is ignored.

    ax = LocatableAxes(fig, divider.get_position())
    ax.set_axes_locator(divider.new_locator(nx=1, ny=1))

    fig.add_axes(ax)

    ax.plot([1, 2, 3])
Beispiel #2
0
    def metric_svg(self,
                   host=None,
                   title="undefined",
                   ylabel="undefined",
                   metrics=[],
                   b64encode=True):
        fig = pyplot.figure(figsize=self.FIGSIZE)

        h = [Size.Fixed(1.2), Size.Scaled(1.), Size.Fixed(.2)]
        v = [Size.Fixed(0.7), Size.Scaled(1.), Size.Fixed(.5)]

        divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
        plt = Axes(fig, divider.get_position())
        plt.set_axes_locator(divider.new_locator(nx=1, ny=1))

        fig.add_axes(plt)

        result = self.result
        runinfo = result.runinfo

        # ----
        # The X limits are -rampupMins, runMins
        # ----
        plt.set_xlim(-int(runinfo['rampupMins']), int(runinfo['runMins']))
        plt.axvspan(-int(runinfo['rampupMins']), 0, facecolor='0.2', alpha=0.1)

        # ----
        # Draw all the requested graphs
        # ----
        x = None
        for m in metrics:
            if x is None:
                x, y = self._get_metric_tree(m)
            else:
                _, y = self._get_metric_tree(m, x)

            plt.plot(x, y, m['color'], label=m['label'])

        # ----
        # Title and labels
        # ----
        plt.set_title(title)
        plt.set_xlabel("Elapsed Minutes")
        plt.set_ylabel(ylabel)
        plt.legend(loc='upper left')
        plt.grid()

        # ----
        # Now turn this into an in-memory SVG and return it as requested
        # (raw or b64-encoded)
        # ----
        buf = io.StringIO()
        pyplot.savefig(buf, format='svg')

        if not b64encode:
            return buf.getvalue()
        return base64.b64encode(buf.getvalue().encode('utf-8')).decode('utf-8')
Beispiel #3
0
def plot_it():
    # fig = plt.figure(1, figsize=(8, 4.5))
    fig = plt.figure(1, figsize=(16, 12))
    # h = [Size.Fixed(0.), Size.Fixed(6.5)]
    # v = [Size.Fixed(0.5), Size.Fixed(3.25)]
    h = [Size.Fixed(0.), Size.Fixed(13)]
    v = [Size.Fixed(0.5), Size.Fixed(7)]
    win = Divider(fig, (0.1, 0.08, 0.8, 0.8), h, v, aspect=False)
    ax = Axes(fig, win.get_position())
    ax.set_axes_locator(win.new_locator(nx=1, ny=1))
    fig.add_axes(ax)
    # fig = plt.figure(figsize=(16, 12))
    # ax = fig.add_subplot(111)
    for ii, ellipse in enumerate(ellipses):
        ax.fill(ellipse[0], ellipse[1], color=cmap(norm_vals[ii]), zorder=0)
        ax.plot(ellipse[0], ellipse[1], 'k-', linewidth=0.2)
    ax.invert_yaxis()
    plt.xlabel('Northing (km)', fontsize=16)
    plt.ylabel(r'$\log_{10}$ Period (s)', fontsize=16)
    # ax.set_aspect(1)
    ax.tick_params(axis='both', labelsize=14)
    # locs, labels = plt.xticks()
    # plt.xticks(locs, [int(x * 10) for x in locs])
    fake_vals = np.linspace(lower, upper, len(fill_vals))
    fake_im = ax.scatter(loc, periods, c=fake_vals, cmap=cmap)
    fake_im.set_visible(False)
    # ax.set_ylim([-2.6, 3.25])
    # ax.set_xlim([526.5, 538.2])
    # ax.invert_yaxis()
    # cb = plt.colorbar(mappable=fake_im)
    #############################################
    # Colour bar and site labelling
    # cbaxes = fig.add_axes([0.925, 0.1351, 0.015, 0.72])
    # cb = plt.colorbar(fake_im)
    # if 'phi' in fill_param[:3]:
    #     label = r'${}{}(\degree)$'.format('\phi', fill_param[-2:])
    # else:
    #     label = r'$\{}(\degree)$'.format(fill_param)
    # cb.set_label(label,
    #              rotation=270,
    #              labelpad=20,
    #              fontsize=18)
    # ax.tick_params(axis='both', labelsize=14)
    # ax.set_xlim(x_lim)
    # for ii, site in enumerate(main_sites):
    #     txt = site[-4:-1]
    #     if linear_xaxis:
    #         ax.text(linear_site[ii],
    #                 label_offset, site, rotation=45)  # 3.6
    #     else:
    #         ax.text(main_transect.sites[site].locations['X'],
    #                 label_offset, site, rotation=45)  # 3.6

    plt.show()
    return fig
Beispiel #4
0
def _set_ax_height_to_cm(fig: Fig, ax: Ax, height: float) -> None:
    from mpl_toolkits.axes_grid1 import Size, Divider

    height /= 2.54  # cm to inches

    bbox = _get_ax_bbox(fig, ax)

    hori = [Size.Fixed(bbox.x0), Size.Fixed(bbox.width), Size.Fixed(bbox.x1)]
    vert = [Size.Fixed(bbox.y0), Size.Fixed(height), Size.Fixed(bbox.y1)]

    divider = Divider(fig, (0.0, 0.0, 1.0, 1.0), hori, vert, aspect=False)

    ax.set_axes_locator(divider.new_locator(nx=1, ny=1))
def demo_fixed_pad_axes():
    fig = plt.figure(2, (6, 6))

    # The first & third items are for padding and the second items are for the
    # axes. Sizes are in inches.
    h = [Size.Fixed(1.0), Size.Scaled(1.), Size.Fixed(.2)]
    v = [Size.Fixed(0.7), Size.Scaled(1.), Size.Fixed(.5)]

    divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
    # the width and height of the rectangle is ignored.

    ax = LocatableAxes(fig, divider.get_position())
    ax.set_axes_locator(divider.new_locator(nx=1, ny=1))

    fig.add_axes(ax)

    ax.plot([1, 2, 3])
def demo_fixed_size_axes():
    fig = plt.figure(figsize=(6, 6))

    # The first items are for padding and the second items are for the axes.
    # sizes are in inch.
    h = [Size.Fixed(1.0), Size.Fixed(4.5)]
    v = [Size.Fixed(0.7), Size.Fixed(5.)]

    divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
    # the width and height of the rectangle is ignored.

    ax = Axes(fig, divider.get_position())
    ax.set_axes_locator(divider.new_locator(nx=1, ny=1))

    fig.add_axes(ax)

    ax.plot([1, 2, 3])
Beispiel #7
0
def demo_fixed_size_axes():
    fig1 = plt.figure(1, (10, 5))

    # The first items are for padding and the second items are for the axes.
    # sizes are in inch.
    h = [Size.Fixed(1.0), Size.Fixed(7.5)]
    v = [Size.Fixed(0.7), Size.Fixed(4.5)]

    divider = Divider(fig1, (0.0, 0.0, 1., 1.), h, v, aspect=False)
    # the width and height of the rectangle is ignored.

    ax = LocatableAxes(fig1, divider.get_position())
    ax.set_axes_locator(divider.new_locator(nx=1, ny=1))

    fig1.add_axes(ax)

    ax.plot([1, 2, 3])
Beispiel #8
0
    def fig(self):

        fig, axes = plt.subplots(nrows=self.nrows, ncols=self.ncols, figsize=self.figsize)

        divider = Divider(fig, (0.0, 0.0, 1.0, 1.0), self.h, self.v, aspect=False)

        if (self.nrows == 1) & (self.ncols == 1):
            axes = [axes]
            axes[0].set_axes_locator(divider.new_locator(nx=1, ny=1))
            if self.n_axes > 1:
                for i in range(self.n_axes-1):
                    axes.append(fig.add_subplot(111))
                    axes[i+1].set_axes_locator(divider.new_locator(nx=1, ny=1))

        elif self.nrows > 1:
            for j in range(self.nrows):
                axes[j].set_axes_locator(divider.new_locator(nx=1, ny=j*2+1))

        elif self.ncols > 1:
            for i in range(self.ncols):
                axes[i].set_axes_locator(divider.new_locator(nx=i*2+1, ny=1))

        if (self.nrows > 1) & (self.ncols > 1):
            for j in range(self.nrows):
                for i in range(self.ncols):
                    axes[i, j].set_axes_locator(divider.new_locator(nx=i*2+1, ny=j*2+1))

        return fig, axes
Beispiel #9
0
def fix_sz_fig(width, height, width_ext=2, padding=.5):
    # These code is to make fixed size article
    # Makesure matplotlib can draw Chinese characters
    plt.rcParams['font.sans-serif'] = ['SimHei']
    # Init figure
    fig = plt.figure(figsize=(width + 2 * padding + width_ext,
                              height + 2 * padding))
    # The first items are for padding and the second items are for the axes.
    # Article width and height
    w = [Size.Fixed(padding), Size.Fixed(width)]
    h = [Size.Fixed(padding), Size.Fixed(height)]
    divider = Divider(fig, (0.0, 0.0, 1., 1.), w, h, aspect=False)
    # the width and height of the rectangle is ignored.
    ax = Axes(fig, divider.get_position())
    ax.set_axes_locator(divider.new_locator(nx=1, ny=1))
    fig.add_axes(ax)

    return fig, ax
Beispiel #10
0
def create_plot(two_sided=False,
                colors=[
                    '#6F4C9B', '#5568B8', '#4D8AC6', '#60AB9E', '#77B77D',
                    '#A6BE54', '#D1B541', '#E49C39', '#DF4828', '#990D38'
                ],
                markers=['o', 'v', '^', 's', 'D', '*'],
                figsize=(5, 3.4)):
    """
    Crée un environnement de plot

    Parameters
    ----------
    twosided : bool
        allows to change the size of the figure accordingly.
    colors : list of strings
        a default list exists but this allows to change it if u want
    markers : list of strings
        a default list of markers exists, but u can change it if needed
    Returns
    -------
    fig, ax : matplotlib objects to be used as normal

    """
    color = cycle(colors)
    marker = cycle(markers)
    if two_sided:
        fig = plt.figure(figsize=(3.4, 3.4))
    else:
        fig = plt.figure(figsize=figsize)
    # The first & third items are for padding and the second items are for the
    # axes. Sizes are in inches.
    h = [Size.Fixed(1.0), Size.Scaled(1.), Size.Fixed(.2)]
    v = [Size.Fixed(0.7), Size.Scaled(1.), Size.Fixed(.5)]

    divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
    # the width and height of the rectangle is ignored.

    ax = Axes(fig, divider.get_position())
    ax.set_axes_locator(divider.new_locator(nx=1, ny=1))

    fig.add_axes(ax)
    return fig, ax, color, marker
Beispiel #11
0
def set_size3(ax, w, h):
    # https://newbedev.com/axes-class-set-explicitly-size-width-height-of-axes-in-given-units
    from mpl_toolkits.axes_grid1 import Divider, Size

    axew = w / 2.54
    axeh = h / 2.54

    # lets use the tight layout function to get a good padding size for our axes labels.
    # fig = plt.gcf()
    # ax = plt.gca()
    fig = ax.get_figure()
    fig.tight_layout()
    # obtain the current ratio values for padding and fix size
    oldw, oldh = fig.get_size_inches()
    l = ax.figure.subplotpars.left
    r = ax.figure.subplotpars.right
    t = ax.figure.subplotpars.top
    b = ax.figure.subplotpars.bottom

    # work out what the new  ratio values for padding are, and the new fig size.
    # ps: adding a bit to neww and newh gives more padding
    # the axis size is set from axew and axeh
    neww = axew + oldw * (1 - r + l) + 0.4
    newh = axeh + oldh * (1 - t + b) + 0.4
    newr = r * oldw / neww - 0.4
    newl = l * oldw / neww + 0.4
    newt = t * oldh / newh - 0.4
    newb = b * oldh / newh + 0.4

    # right(top) padding, fixed axes size, left(bottom) pading
    hori = [Size.Scaled(newr), Size.Fixed(axew), Size.Scaled(newl)]
    vert = [Size.Scaled(newt), Size.Fixed(axeh), Size.Scaled(newb)]

    divider = Divider(fig, (0.0, 0.0, 1.0, 1.0), hori, vert, aspect=False)
    # the width and height of the rectangle is ignored.

    ax.set_axes_locator(divider.new_locator(nx=1, ny=1))

    # we need to resize the figure now, as we have may have made our axes bigger than in.
    fig.set_size_inches(neww, newh)
Beispiel #12
0
 def subplot_array(self, hsize, vsize=(1.0, ), figsize=(10, 10)):
     """ Use the axes_divider module to make a single row of plots
     hsize : list of floats
         horizontal spacing: alternates Scaled for plot, Fixed for between plots
     vsize : list of floats
         vertical spacing
         
     ref:   http://matplotlib.org/mpl_toolkits/axes_grid/users/axes_divider.html
     """
     nx = (len(hsize) + 1) / 2
     ny = (len(vsize) + 1) / 2
     fig, axx = plt.subplots(
         ny, nx, squeeze=False,
         figsize=figsize)  # just to make the axes, will move them
     sizer = lambda x, i: axes_size.Scaled(
         x) if i % 2 == 0 else axes_size.Fixed(x)
     horiz = [sizer(h, i) for i, h in enumerate(hsize)]
     vert = [sizer(v, i) for i, v in enumerate(vsize)]
     divider = Divider(fig, (0.1, 0.1, 0.8, 0.8), horiz, vert, aspect=False)
     for i, ax in enumerate(axx.flatten()):
         iy = i // nx
         ix = i % nx
         ax.set_axes_locator(divider.new_locator(nx=2 * ix, ny=2 * iy))
     return fig, axx
Beispiel #13
0
 def get_divider(self, fig):
     self.border = 0.1
     while self.actual_size[0] < (
             self.size_on_screen[0] - 2 * self.border
     ) and self.actual_size[1] < (self.size_on_screen[1] - 2 * self.border):
         self.border += 0.1
     x_factor = self.actual_size[0] / (self.size_on_screen[0] -
                                       2 * self.border)
     y_factor = self.actual_size[1] / (self.size_on_screen[1] -
                                       2 * self.border)
     self.scale = max(x_factor, y_factor)
     draw_size = (self.actual_size[0] / self.scale,
                  self.actual_size[1] / self.scale)
     h = [Size.Fixed(self.border), Size.Fixed(draw_size[0])]
     v = [Size.Fixed(self.border), Size.Fixed(draw_size[1])]
     return Divider(
         fig,
         (self.location_on_screen[0], self.location_on_screen[1], 1, 1),
         h,
         v,
         aspect=False)
Beispiel #14
0
    def __init__(self,
                 ax_size,
                 wspace,
                 dpi,
                 cbar,
                 cbar_width,
                 left,
                 bottom,
                 right,
                 top,
                 fig_func=None):
        if not cbar:
            wspace = 0
            cbar_width = 0

        # convert arguments from pixels to inches
        ax_size = np.asarray(ax_size) / dpi
        wspace, cbar_width, left, bottom, right, top = np.array(
            (wspace, cbar_width, left, bottom, right, top)) / dpi

        horiz = [left, ax_size[0], wspace, cbar_width, right]
        vert = [bottom, ax_size[1], top]

        figsize = (sum(horiz), sum(vert))
        fig_func = plt.figure if fig_func is None else fig_func
        fig = fig_func(figsize=figsize, dpi=dpi)

        horiz, vert = list(map(Size.Fixed, horiz)), list(map(Size.Fixed, vert))
        divider = Divider(fig, (0.0, 0.0, 1., 1.), horiz, vert, aspect=False)

        ax = LocatableAxes(fig, divider.get_position())
        ax.set_axes_locator(divider.new_locator(nx=1, ny=1))
        fig.add_axes(ax)

        if cbar:
            cax = LocatableAxes(fig, divider.get_position())
            cax.set_axes_locator(divider.new_locator(nx=3, ny=1))
            fig.add_axes(cax)

        self.fig = fig
        self.ax = ax
        self.cax = cax if cbar else None
        os.remove(temppath)
        size(W, HEIGHT+dy+40)
else:
    def pltshow(mplpyplot):
        mplpyplot.show()
# nodebox section end

fig1 = plt.figure(1, (5.5, 4.))

# the rect parameter will be ignore as we will set axes_locator
rect = (0.1, 0.1, 0.8, 0.8)
ax = [fig1.add_axes(rect, label="%d" % i) for i in range(4)]

horiz = [Size.Scaled(1.5), Size.Fixed(.5), Size.Scaled(1.),
         Size.Scaled(.5)]

vert = [Size.Scaled(1.), Size.Fixed(.5), Size.Scaled(1.5)]

# divide the axes rectangle into grid whose size is specified by horiz * vert
divider = Divider(fig1, rect, horiz, vert, aspect=False)

ax[0].set_axes_locator(divider.new_locator(nx=0, ny=0))
ax[1].set_axes_locator(divider.new_locator(nx=0, ny=2))
ax[2].set_axes_locator(divider.new_locator(nx=2, ny=2))
ax[3].set_axes_locator(divider.new_locator(nx=2, nx1=4, ny=0))

for ax1 in ax:
    ax1.tick_params(labelbottom=False, labelleft=False)

pltshow(plt)
from mpl_toolkits.axes_grid1 import Divider
import matplotlib.pyplot as plt


fig = plt.figure(figsize=(5.5, 4))

# the rect parameter will be ignore as we will set axes_locator
rect = (0.1, 0.1, 0.8, 0.8)
ax = [fig.add_axes(rect, label="%d" % i) for i in range(4)]


horiz = [Size.AxesX(ax[0]), Size.Fixed(.5), Size.AxesX(ax[1])]
vert = [Size.AxesY(ax[0]), Size.Fixed(.5), Size.AxesY(ax[2])]

# divide the axes rectangle into grid whose size is specified by horiz * vert
divider = Divider(fig, rect, horiz, vert, aspect=False)


ax[0].set_axes_locator(divider.new_locator(nx=0, ny=0))
ax[1].set_axes_locator(divider.new_locator(nx=2, ny=0))
ax[2].set_axes_locator(divider.new_locator(nx=0, ny=2))
ax[3].set_axes_locator(divider.new_locator(nx=2, ny=2))

ax[0].set_xlim(0, 2)
ax[1].set_xlim(0, 1)

ax[0].set_ylim(0, 1)
ax[2].set_ylim(0, 2)

divider.set_aspect(1.)
        os.remove(temppath)
        size(W, HEIGHT+dy+40)
else:
    def pltshow(mplpyplot):
        mplpyplot.show()
# nodebox section end

fig1 = plt.figure(1, (6, 6))

# fixed size in inch
horiz = [Size.Fixed(1.), Size.Fixed(.5), Size.Fixed(1.5),
         Size.Fixed(.5)]
vert = [Size.Fixed(1.5), Size.Fixed(.5), Size.Fixed(1.)]

rect = (0.1, 0.1, 0.8, 0.8)
# divide the axes rectangle into grid whose size is specified by horiz * vert
divider = Divider(fig1, rect, horiz, vert, aspect=False)

# the rect parameter will be ignore as we will set axes_locator
ax1 = fig1.add_axes(rect, label="1")
ax2 = fig1.add_axes(rect, label="2")
ax3 = fig1.add_axes(rect, label="3")
ax4 = fig1.add_axes(rect, label="4")

ax1.set_axes_locator(divider.new_locator(nx=0, ny=0))
ax2.set_axes_locator(divider.new_locator(nx=0, ny=2))
ax3.set_axes_locator(divider.new_locator(nx=2, ny=2))
ax4.set_axes_locator(divider.new_locator(nx=2, nx1=4, ny=0))

pltshow(plt)
Beispiel #18
0
    def _setup_image_grid(self, figure, dims):
        """
            An example of how grid, parameter and view numbers change
            for dims = 4
            
            The numbers in the grid are:
            
            parameter x, parameter y
            grid x, grid y
        
            -----------------------------------------------------
            |            |            |            |            |
            |    0, 0    |    1, 0    |    2, 0    |    3, 0    |
            |    -, -    |    -, -    |    -, -    |    -, -    |
            |            |            |            |            |
            ==============------------|------------|------------|
            I            I            |            |            |
            I    0, 1    I    1, 1    |    2, 1    |    3, 1    |
            I    0, 0    I    1, 0    |    2, 0    |    -, -    |
            I            I            |            |            |
            I------------==============------------|------------|
            I            |            I            |            |
            I    0, 2    |    1, 2    I    2, 2    |    3, 2    |
            I    0, 1    |    1, 1    I    2, 1    |    -, -    |
            I            |            I            |            |
            I------------|------------==============------------|
            I            |            |            I            |
            I    0, 3    |    1, 3    |    2, 3    I    3, 3    |
            I    0, 2    |    1, 2    |    2, 2    I    -, -    |
            I            |            |            I            |
            I======================================I------------|
            From the above it should be clear that:
            
            parameter x = grid x
            parameter y = grid y + 1
            grid nr = grid y + grid x * (dims - 1)
            view nr = grid nr - (grid nr / dims) * ((grid nr / dims) +1) / 2
            

        """
        image_grid = ImageGrid(
            figure,
            111,
            nrows_ncols=(dims - 1, dims - 1),
            cbar_location="right",
            cbar_mode="single",
            # add_all=False,
            aspect=False,
            axes_pad=0.1,
            direction="column")

        rect = (0.1, 0.1, 0.8, 0.8)
        horiz = [Size.Fixed(.1)
                 ] + [Size.Scaled(1.), Size.Fixed(.1)] * max(dims - 1, 1) + [
                     Size.Fixed(0.15)
                 ]
        vert = [Size.Fixed(.1)
                ] + [Size.Scaled(1.), Size.Fixed(.1)] * max(dims - 1, 1)

        # divide the axes rectangle into grid whose size is specified by horiz * vert
        divider = Divider(figure, rect, horiz, vert)  # , aspect=False)

        # Helper to get the axis for par x and y:
        def get_grid(parx, pary):
            gridx = parx
            gridy = pary - 1
            return image_grid[gridy + gridx * (dims - 1)]

        # Helper to get the grid locator for par x and par y
        def get_locator(parx, pary):
            gridx = parx
            gridy = pary - 1
            nx = 1 + gridx * 2
            ny = 1 + (dims - gridy - 2) * 2
            return divider.new_locator(nx=nx, ny=ny)

        # Hide the unused plots & setup the used ones:
        for parx, pary in itertools.product(list(range(self.num_params - 1)),
                                            list(range(1, self.num_params))):

            # Calculate the grid position:
            ax = get_grid(parx, pary)

            # Setup axes:
            if pary <= parx:
                ax.set_visible(False)
            else:
                ax.set_axes_locator(get_locator(parx, pary))
                ax.set_visible(True)

        return image_grid, divider, get_grid
=====================

"""
import mpl_toolkits.axes_grid1.axes_size as Size
from mpl_toolkits.axes_grid1 import Divider
import matplotlib.pyplot as plt

fig1 = plt.figure(1, (5.5, 4.))

# the rect parameter will be ignore as we will set axes_locator
rect = (0.1, 0.1, 0.8, 0.8)
ax = [fig1.add_axes(rect, label="%d" % i) for i in range(4)]

horiz = [Size.Scaled(1.5), Size.Fixed(.5), Size.Scaled(1.), Size.Scaled(.5)]

vert = [Size.Scaled(1.), Size.Fixed(.5), Size.Scaled(1.5)]

# divide the axes rectangle into grid whose size is specified by horiz * vert
divider = Divider(fig1, rect, horiz, vert, aspect=False)

ax[0].set_axes_locator(divider.new_locator(nx=0, ny=0))
ax[1].set_axes_locator(divider.new_locator(nx=0, ny=2))
ax[2].set_axes_locator(divider.new_locator(nx=2, ny=2))
ax[3].set_axes_locator(divider.new_locator(nx=2, nx1=4, ny=0))

for ax1 in ax:
    plt.setp(ax1.get_xticklabels() + ax1.get_yticklabels(), visible=False)

plt.draw()
plt.show()
                   labelleft=False)


##############################################################################
# Fixed axes sizes; fixed paddings.

fig = plt.figure(figsize=(6, 6))
fig.suptitle("Fixed axes sizes, fixed paddings")

# Sizes are in inches.
horiz = [Size.Fixed(1.), Size.Fixed(.5), Size.Fixed(1.5), Size.Fixed(.5)]
vert = [Size.Fixed(1.5), Size.Fixed(.5), Size.Fixed(1.)]

rect = (0.1, 0.1, 0.8, 0.8)
# Divide the axes rectangle into a grid with sizes specified by horiz * vert.
div = Divider(fig, rect, horiz, vert, aspect=False)

# The rect parameter will actually be ignored and overridden by axes_locator.
ax1 = fig.add_axes(rect, axes_locator=div.new_locator(nx=0, ny=0))
label_axes(ax1, "nx=0, ny=0")
ax2 = fig.add_axes(rect, axes_locator=div.new_locator(nx=0, ny=2))
label_axes(ax2, "nx=0, ny=2")
ax3 = fig.add_axes(rect, axes_locator=div.new_locator(nx=2, ny=2))
label_axes(ax3, "nx=2, ny=2")
ax4 = fig.add_axes(rect, axes_locator=div.new_locator(nx=2, nx1=4, ny=0))
label_axes(ax4, "nx=2, nx1=4, ny=0")

##############################################################################
# Axes sizes that scale with the figure size; fixed paddings.

fig = plt.figure(figsize=(6, 6))
Beispiel #21
0
def setup_axes(df, plates, attrs):
    from mpl_toolkits.axes_grid1 import Divider
    from mpl_toolkits.axes_grid1.axes_size import Fixed

    # These assumptions let us simplify some code, and should always be true.
    assert len(plates) > 0
    assert len(attrs) > 0

    # Determine how much data will be shown in the figure:
    num_plates = len(plates)
    num_attrs = len(attrs)
    dims = Dimensions(df)

    bar_label_width = guess_attr_label_width(df, attrs)

    # Define the grid on which the axes will live:
    h_divs = [
        LEFT_MARGIN,
    ]
    for _ in plates:
        h_divs += [
            CELL_SIZE * dims.num_cols,
            PAD_WIDTH,
        ]
    h_divs[-1:] = [
        BAR_PAD_WIDTH,
        BAR_WIDTH,
        RIGHT_MARGIN + bar_label_width,
    ]

    v_divs = [
        TOP_MARGIN,
    ]
    for attr in attrs:
        v_divs += [
            max(
                CELL_SIZE * dims.num_rows,
                BAR_WIDTH * dims.num_values[attr],
            ),
            PAD_HEIGHT,
        ]
    v_divs[-1:] = [
        BOTTOM_MARGIN,
    ]

    # Add up all the divisions to get the width and height of the figure:
    figsize = sum(h_divs), sum(v_divs)

    # Make the figure:
    fig, axes = plt.subplots(
        num_attrs,
        num_plates + 1,  # +1 for the colorbar axes.
        figsize=figsize,
        squeeze=False,
    )

    # Position the axes:
    rect = 0.0, 0.0, 1, 1
    h_divs = [Fixed(x) for x in h_divs]
    v_divs = [Fixed(x) for x in reversed(v_divs)]
    divider = Divider(fig, rect, h_divs, v_divs, aspect=False)

    for i in range(num_attrs):
        for j in range(num_plates + 1):
            loc = divider.new_locator(nx=2 * j + 1, ny=2 * (num_attrs - i) - 1)
            axes[i, j].set_axes_locator(loc)

    return fig, axes, dims
Beispiel #22
0
    def cpu_svg(self,
                host=None,
                title="CPU Usage",
                ylabel="Percent",
                b64encode=True):
        fig = pyplot.figure(figsize=self.FIGSIZE)

        h = [Size.Fixed(1.2), Size.Scaled(1.), Size.Fixed(.2)]
        v = [Size.Fixed(0.7), Size.Scaled(1.), Size.Fixed(.5)]

        divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
        plt = Axes(fig, divider.get_position())
        plt.set_axes_locator(divider.new_locator(nx=1, ny=1))

        fig.add_axes(plt)

        result = self.result
        runinfo = result.runinfo

        # ----
        # The X limits are -rampupMins, runMins, Y limits are 0..100
        # ----
        plt.set_xlim(-int(runinfo['rampupMins']), int(runinfo['runMins']))
        plt.set_ylim(0, 100)
        plt.axvspan(-int(runinfo['rampupMins']), 0, facecolor='0.2', alpha=0.1)

        # ----
        # Gather all the relevant data
        # ----
        x, y_user = self._get_metric_xy({
            'host': host,
            'metric': 'cpu.percent-user',
        })
        _, y_sys = self._get_metric_xy(
            {
                'host': host,
                'metric': 'cpu.percent-system',
            }, x)
        _, y_wait = self._get_metric_xy(
            {
                'host': host,
                'metric': 'cpu.percent-wait',
            }, x)
        _, y_intr = self._get_metric_xy(
            {
                'host': host,
                'metric': 'cpu.percent-interrupt',
            }, x)
        _, y_softirq = self._get_metric_xy(
            {
                'host': host,
                'metric': 'cpu.percent-softirq',
            }, x)
        _, y_idle = self._get_metric_xy(
            {
                'host': host,
                'metric': 'cpu.percent-idle',
            }, x)

        # ----
        # It is possible that the mqtt based metric collector produces
        # CSV files with different numbers of lines. We cut all of them
        # to a combined minimum length.
        # ----
        min_len = min(len(x), len(y_user), len(y_sys), len(y_wait),
                      len(y_intr), len(y_softirq), len(y_idle))
        x = x[:min_len]
        y_user = y_user[:min_len]
        y_sys = y_sys[:min_len]
        y_wait = y_wait[:min_len]
        y_intr = y_intr[:min_len]
        y_softirq = y_softirq[:min_len]
        y_idle = y_idle[:min_len]

        # ----
        # Plot the CPU usage
        # ----
        plt.stackplot(x,
                      y_user,
                      y_sys,
                      y_wait,
                      y_intr,
                      y_softirq,
                      y_idle,
                      colors=[
                          'g',
                          'b',
                          'r',
                          'c',
                          'm',
                          'y',
                      ],
                      labels=[
                          'User',
                          'System',
                          'Wait',
                          'Interrupt',
                          'SoftIrq',
                          'Idle',
                      ])

        # ----
        # Title and labels
        # ----
        plt.set_title(title)
        plt.set_xlabel("Elapsed Minutes")
        plt.set_ylabel(ylabel)
        plt.legend(loc='upper left')
        plt.grid()

        # ----
        # Now turn this into an in-memory SVG and return it as requested
        # (raw or b64-encoded)
        # ----
        buf = io.StringIO()
        pyplot.savefig(buf, format='svg')

        if not b64encode:
            return buf.getvalue()
        return base64.b64encode(buf.getvalue().encode('utf-8')).decode('utf-8')
Beispiel #23
0
    def tpmc_svg(self, b64encode=True):
        fig = pyplot.figure(figsize=self.FIGSIZE)

        h = [Size.Fixed(1.2), Size.Scaled(1.), Size.Fixed(.2)]
        v = [Size.Fixed(0.7), Size.Scaled(1.), Size.Fixed(.5)]

        divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
        plt = Axes(fig, divider.get_position())
        plt.set_axes_locator(divider.new_locator(nx=1, ny=1))

        fig.add_axes(plt)

        result = self.result
        runinfo = result.runinfo

        # ----
        # The X limits are -rampupMins, runMins
        # ----
        plt.set_xlim(-int(runinfo['rampupMins']), int(runinfo['runMins']))
        plt.axvspan(-int(runinfo['rampupMins']), 0, facecolor='0.2', alpha=0.1)

        # ----
        # offset the timestamps by -rampupMins so that the graph
        # starts with negative minutes elapsed and switches to
        # positive when the measurement begins.
        # ----
        offset = (int(runinfo['rampupMins'])) * 60.0

        # ----
        # NEW_ORDER transactions per minute. First get the timestamp
        # and number of transactions from the result data.
        # The X vector then is the sorted unique timestamps rounded
        # to an interval.
        # ----
        interval = 10
        data = numpy.array([[(int(tup[0] / interval) * interval - offset) / 60,
                             tup[1] * (60 / interval)]
                            for tup in result.result_ttype['NEW_ORDER']])
        x = sorted(numpy.unique(data[:, 0]))

        # ----
        # The Y vector is the sums of transactions grouped by X
        # ----
        y = []
        for ts in x:
            tmp = data[numpy.where(data[:, 0] == ts)]
            y.append(numpy.sum(tmp[:, 1]))

        # ----
        # Plot the NOPM and add all the decorations
        # ----
        plt.plot(x, y, 'b')
        plt.set_title("NEW_ORDER Transactions per Minute (tpmC)")
        plt.set_xlabel("Elapsed Minutes")
        plt.set_ylabel("tpmC")
        plt.grid()

        buf = io.StringIO()
        pyplot.savefig(buf, format='svg')

        if not b64encode:
            return buf.getvalue()
        return base64.b64encode(buf.getvalue().encode('utf-8')).decode('utf-8')
Beispiel #24
0
    sumFinalAnalysis = sum(lstFinalAnalysis)
    sumFinalAnalysisTE = np.matmul(-np.transpose(npTE), lstFinalAnalysis)
    A = np.array([[ndados, sumTE], [sumTE, prodTE]])
    B = np.array([[sumFinalAnalysis], [sumFinalAnalysisTE]])
    invA = np.linalg.inv(A)
    P = np.matmul(invA, B)
    T2[indexValue] = (P[1][0])

for i, t in enumerate(T2):
    T2[i] = math.inf if t[0] == 0 else 1000 / t[0]

T2Star = np.reshape(T2, (400, 400))
fig = plt.figure(figsize=(6, 6))
h = [Size.Fixed(1.0), Size.Fixed(5.)]
v = [Size.Fixed(1.0), Size.Fixed(5.)]
divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
ax = Axes(fig, divider.get_position())
ax.set_axes_locator(divider.new_locator(nx=1, ny=1))
fig.add_axes(ax)
plt.pcolor(np.flip(T2Star, 0), cmap=jet_combined, vmin=0, vmax=180)
toc = time.perf_counter()
print(f"Executed in {toc - tic:0.4f} seconds")

# toggle_selector.RS = RectangleSelector(ax, line_select_callback,
#                                        drawtype='box', useblit=True,
#                                        button=[1, 3],  # don't use middle button
#                                        minspanx=5, minspany=5,
#                                        spancoords='pixels',
#                                        interactive=True)

# plt.connect('key_press_event', toggle_selector)
Beispiel #25
0
    def memory_svg(self,
                   host=None,
                   title="Memory Usage",
                   unit="Bytes",
                   factor=1.0,
                   b64encode=True):
        fig = pyplot.figure(figsize=self.FIGSIZE)

        h = [Size.Fixed(1.2), Size.Scaled(1.), Size.Fixed(.2)]
        v = [Size.Fixed(0.7), Size.Scaled(1.), Size.Fixed(.5)]

        divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
        plt = Axes(fig, divider.get_position())
        plt.set_axes_locator(divider.new_locator(nx=1, ny=1))

        fig.add_axes(plt)

        result = self.result
        runinfo = result.runinfo

        # ----
        # The X limits are -rampupMins, runMins
        # ----
        plt.set_xlim(-int(runinfo['rampupMins']), int(runinfo['runMins']))
        plt.axvspan(-int(runinfo['rampupMins']), 0, facecolor='0.2', alpha=0.1)

        x, y_used = self._get_metric_xy({
            'host': host,
            'metric': 'memory.memory-used',
            'factor': factor,
        })
        _, y_cached = self._get_metric_xy(
            {
                'host': host,
                'metric': 'memory.memory-cached',
                'factor': factor,
            }, x)
        _, y_buffered = self._get_metric_xy(
            {
                'host': host,
                'metric': 'memory.memory-buffered',
                'factor': factor,
            }, x)
        _, y_free = self._get_metric_xy(
            {
                'host': host,
                'metric': 'memory.memory-free',
                'factor': factor,
            }, x)

        # ----
        # It is possible that the mqtt based metric collector produces
        # CSV files with different numbers of lines. We cut all of them
        # to a combined minimum length.
        # ----
        min_len = min(len(x), len(y_used), len(y_cached), len(y_buffered),
                      len(y_free))
        x = x[:min_len]
        y_used = y_used[:min_len]
        y_cached = y_cached[:min_len]
        y_buffered = y_buffered[:min_len]
        y_free = y_free[:min_len]

        plt.stackplot(x,
                      y_used,
                      y_cached,
                      y_buffered,
                      y_free,
                      colors=[
                          'b',
                          'y',
                          'g',
                          'gray',
                      ],
                      labels=[
                          'Used',
                          'Cached',
                          'Buffered',
                          'Free',
                      ])

        # ----
        # Title and labels
        # ----
        plt.set_title(title)
        plt.set_xlabel("Elapsed Minutes")
        plt.set_ylabel(unit)
        plt.legend(loc='upper left')
        plt.grid()

        # ----
        # Now turn this into an in-memory SVG and return it as requested
        # (raw or b64-encoded)
        # ----
        buf = io.StringIO()
        pyplot.savefig(buf, format='svg')

        if not b64encode:
            return buf.getvalue()
        return base64.b64encode(buf.getvalue().encode('utf-8')).decode('utf-8')
Beispiel #26
0
def plot_variance_multi(savefile,
                        data,
                        labels,
                        colors,
                        ylabel,
                        ylim,
                        ylim_unit=1,
                        ylim_scale=5,
                        colors2=None,
                        hline=None,
                        vline=None,
                        locator=-1,
                        draw_dist=True,
                        subsample=1):
    plt.clf()
    plt.rcParams["font.size"] = 14
    colors2 = colors if colors2 is None else colors2
    m = len(data)
    #fig, ax = plt.subplots(1, 1)

    fig = plt.figure(1, figsize=(4, 4))

    # The first items are for padding and the second items are for the axes.
    # sizes are in inch.
    h = [Size.Fixed(0.65), Size.Fixed(5.5)]
    v = [Size.Fixed(0.7), Size.Fixed(4.)]

    divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
    # the width and height of the rectangle is ignored.

    ax = LocatableAxes(fig, divider.get_position())
    ax.set_axes_locator(divider.new_locator(nx=1, ny=1))

    fig.add_axes(ax)

    if not hasattr(draw_dist, '__getitem__'):
        v = draw_dist
        draw_dist = [v for i in range(m)]
    print(draw_dist)

    for k in range(m)[::-1]:
        plot_m = numpy.median(data[k], 0)
        sorted = numpy.sort(data[k], 0)
        n = data[k].shape[0]
        T = data[k].shape[1]
        t = numpy.arange(0, T)
        fin = plot_m[-1]
        best = sorted[0][-1]
        alpha = 1.0 / (n // 2) * 0.4
        if subsample > 1:
            t = subsample_data(t, subsample)
            plot_m = subsample_data(plot_m, subsample)
            sorted = subsample_data(sorted, subsample)

        if k == 0:
            if ylim is None:
                ymax = min([fin * ylim_scale, sorted[-1, 0], 90])
                ymin = numpy.floor(numpy.max(best / ylim_unit - 0.5,
                                             0)) * ylim_unit
                ymin = 0
                ylim = [ymin, numpy.ceil(ymax / ylim_unit) * ylim_unit]
            else:
                ylim = ylim

        # 3: 0
        if draw_dist[k]:
            print('k', k)
            for i in range(n // 2):
                ax.fill_between(t,
                                sorted[-1 - i],
                                sorted[i],
                                facecolor=colors2[k],
                                alpha=alpha)

    for k in range(m)[::-1]:
        plot_m = numpy.median(data[k], 0)
        t = numpy.arange(0, T)
        if subsample > 1:
            t = subsample_data(t, subsample)
            plot_m = subsample_data(plot_m, subsample)

        ax.plot(t, plot_m, lw=1, color=colors[k], ls='-', label=labels[k])

    if hline is not None:
        ax.plot((0, T), (hline, hline), color='gray', ls=':')

    if vline is not None:
        ax.plot((vline, vline), (ylim[0], ylim[1]), color='gray', ls=':')

    ax.legend(loc='upper right')
    ax.set_xlabel('Iterations')
    ax.set_ylabel(ylabel)
    ax.set_xlim([0, T])
    ax.set_ylim(ylim)
    if locator >= 0:
        ax.yaxis.set_major_locator(MultipleLocator(locator))
    ax.grid()
    plt.savefig(savefile + '.png')
    plt.savefig(savefile + '.pdf')
import mpl_toolkits.axes_grid1.axes_size as Size
from mpl_toolkits.axes_grid1 import Divider
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(5.5, 4))

rect = (0.1, 0.1, 0.8, 0.8)
ax = [fig.add_axes(rect, label="%d" % i) for i in range(4)]

horiz = [Size.AxesX(ax[0]), Size.Fixed(.5), Size.AxesX(ax[1])]
vert = [Size.AxesY(ax[0]), Size.Fixed(.5), Size.AxesY(ax[2])]

divider = Divider(fig, rect, horiz, vert, aspect=False)

ax[0].set_axes_locator(divider.new_locator(nx=0, ny=0))
ax[1].set_axes_locator(divider.new_locator(nx=2, ny=0))
ax[2].set_axes_locator(divider.new_locator(nx=0, ny=2))
ax[3].set_axes_locator(divider.new_locator(nx=2, ny=2))

ax[0].set_xlim(0, 2)
ax[1].set_xlim(0, 1)

ax[0].set_ylim(0, 1)
ax[2].set_ylim(0, 2)

divider.set_aspect(1.)

for ax1 in ax:
    ax1.tick_params(labelbottom=False, labelleft=False)

plt.show()
Beispiel #28
0
    def plot_legend(self, legend_unit_height=0.25):
        """
        Plot a legend for this Style object.

        If the color and width labels are the same, a single legend will
        be created. Otherwise, two legends will be created - one with
        the color labels, and the other with the width labels.

        Parameters
        ----------
        legend_unit_height : float
            A scaling factor to modify the height of each unit in the
            legend only.

        Returns
        -------
        fig : matplotlib Figure
            Figure handle.

        ax : matplotlib Axes
            Axis handle.
        """
        # print some plotting values
        print('stratigraphic height scaling : 1 distance unit = 1 inch * {}'.
              format(self.height_scaling_factor))
        print('width value of 1 will be     : {} inches'.format(
            self.width_inches))

        # extract attributes
        color_labels = self.color_labels
        width_labels = self.width_labels
        color_values = self.color_values
        width_values = self.width_values

        # if the color and width labels are different
        if np.any(~(color_labels == width_labels)):

            # sort the widths
            width_sort_inds = np.argsort(width_values)
            width_labels = width_labels[width_sort_inds]
            width_values = width_values[width_sort_inds]

            # initialize the figure
            fig, ax = plt.subplots(nrows=1, ncols=2, sharey=True)

            # determine the axis height and limits first
            if self.n_color_labels > self.n_width_labels:
                ax_height = legend_unit_height * self.n_color_labels
                ax[0].set_ylim(0, self.n_color_labels)
                ax[1].set_ylim(0, self.n_color_labels)
            else:
                ax_height = legend_unit_height * self.n_width_labels
                ax[0].set_ylim(0, self.n_width_labels)
                ax[1].set_ylim(0, self.n_width_labels)

            # plot the colors
            strat_height_colors = 0

            for i in range(len(color_labels)):

                # create the rectangle - with thickness of 1
                ax[0].add_patch(
                    Rectangle((0.0, strat_height_colors),
                              1,
                              1,
                              facecolor=color_values[i],
                              edgecolor='k'))

                # label the unit
                ax[0].text(1.2,
                           strat_height_colors + 0.5,
                           color_labels[i],
                           horizontalalignment='left',
                           verticalalignment='center')

                # count the height
                strat_height_colors = strat_height_colors + 1

            # set the axis dimensions (values below are all in inches)
            ax0_lower_left_x = 0.5
            ax0_lower_left_y = 0.5
            ax0_width = 0.5
            h = [Size.Fixed(ax0_lower_left_x), Size.Fixed(ax0_width)]
            v = [Size.Fixed(ax0_lower_left_y), Size.Fixed(ax_height)]
            divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
            ax[0].set_axes_locator(divider.new_locator(nx=1, ny=1))

            # set the limits
            ax[0].set_xlim(0, 1)

            # prettify
            ax[0].set_xticks([])
            ax[0].set_yticklabels([])
            ax[0].set_yticks([])

            # plot the widths
            strat_height_widths = 0

            for i in range(len(width_labels)):

                # create the rectangle
                ax[1].add_patch(
                    Rectangle((0.0, strat_height_widths),
                              width_values[i],
                              1,
                              facecolor='grey',
                              edgecolor='k'))

                # the label
                ax[1].text(1.1,
                           strat_height_widths + 0.5,
                           width_labels[i],
                           horizontalalignment='left',
                           verticalalignment='center')

                # count the height
                strat_height_widths = strat_height_widths + 1

            # set the axis dimensions (values below are all in inches)
            ax1_lower_left_x = ax0_lower_left_x + ax0_width + 2
            ax1_lower_left_y = ax0_lower_left_y
            ax1_width = self.width_inches
            h = [Size.Fixed(ax1_lower_left_x), Size.Fixed(ax1_width)]
            v = [Size.Fixed(ax1_lower_left_y), Size.Fixed(ax_height)]
            divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
            ax[1].set_axes_locator(divider.new_locator(nx=1, ny=1))

            # prettify
            ax[1].set_xlim(0, 1)
            ax[1].set_xticks([0, 0.2, 0.4, 0.6, 0.8, 1])
            for label in ax[1].get_xticklabels():
                label.set_rotation(270)
                label.set_ha('center')
                label.set_va('top')
            ax[1].set_axisbelow(True)
            ax[1].xaxis.grid(ls='--')
            ax[1].set_yticklabels([])
            ax[1].set_yticks([])
            ax[1].spines['top'].set_visible(False)
            ax[1].spines['right'].set_visible(False)

            # turning the spines off creates some clipping mask issues
            # so just turn the clipping masks off
            for obj in fig.findobj():
                obj.set_clip_on(False)

            # not really necessary since the axis sizes are already
            # forced, but we may as well set the figsize here too
            fig.set_size_inches(
                ax1_lower_left_x + ax1_width + ax0_lower_left_x,
                ax1_lower_left_y * 2 + ax_height)

        # if the color and width labels are the same
        else:

            # sort by width
            width_sort_inds = np.argsort(width_values)
            color_labels = color_labels[width_sort_inds]
            width_labels = width_labels[width_sort_inds]
            color_values = color_values[width_sort_inds]
            width_values = width_values[width_sort_inds]

            # initiate fig and ax
            fig, ax = plt.subplots()

            # determine the axis height and limits first
            ax_height = legend_unit_height * self.n_color_labels
            ax.set_ylim(0, self.n_color_labels)

            # initiate counting of the stratigraphic height
            strat_height = 0

            # loop over each item
            for i in range(len(color_labels)):

                # create the rectangle - with thickness of 1
                ax.add_patch(
                    Rectangle((0.0, strat_height),
                              width_values[i],
                              1,
                              facecolor=color_values[i],
                              edgecolor='k'))

                # label the unit
                ax.text(1.1,
                        strat_height + 0.5,
                        color_labels[i],
                        horizontalalignment='left',
                        verticalalignment='center')

                # count the stratigraphic height
                strat_height = strat_height + 1

            # set the axis dimensions (values below are all in inches)
            ax_lower_left_x = 0.5
            ax_lower_left_y = 0.5
            ax_width = self.width_inches
            h = [Size.Fixed(ax_lower_left_x), Size.Fixed(ax_width)]
            v = [Size.Fixed(ax_lower_left_y), Size.Fixed(ax_height)]
            divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
            ax.set_axes_locator(divider.new_locator(nx=1, ny=1))

            # prettify
            ax.set_xlim(0, 1)
            ax.set_xticks([0, 0.2, 0.4, 0.6, 0.8, 1])
            for label in ax.get_xticklabels():
                label.set_rotation(270)
                label.set_ha('center')
                label.set_va('top')
            ax.set_axisbelow(True)
            ax.xaxis.grid(ls='--')
            ax.set_yticklabels([])
            ax.set_yticks([])
            ax.spines['top'].set_visible(False)
            ax.spines['right'].set_visible(False)

            # turning the spines off creates some clipping mask issues
            # so just turn the clipping masks off
            for obj in fig.findobj():
                obj.set_clip_on(False)

            # not really necessary since the axis sizes are already
            # forced, but we may as well set the figsize here too
            fig.set_size_inches(ax_lower_left_x * 2 + ax_width,
                                ax_lower_left_y * 2 + ax_height)

        return fig, ax
ax3 = divider.append_axes('right', size='33%', pad=0.5)
ax3.plot(t, x3)

# <markdowncell>

# make_axes_locatable() gives one way to handle this, by giving the append_axes() method. Another way is by creating a Divider object and giving it the layout up front.

# <codecell>

from mpl_toolkits.axes_grid1 import Size, Divider
fig = plt.figure()
ax = [fig.add_axes([0.1,0.1,0.8,0.8], label='%d'%i) for i in range(3)] # Create 3 Axes to be sized later
horiz = [Size.Scaled(2), Size.Fixed(0.5), Size.Scaled(3), Size.Fixed(0.01)]
vert = [Size.Scaled(1), Size.Fixed(0.5), Size.Scaled(1)]

div = Divider(fig, (0.1, 0.1, 0.8, 0.8), horiz, vert, aspect=False)

ax[0].set_axes_locator(div.new_locator(nx=0, ny=0))
ax[1].set_axes_locator(div.new_locator(nx=2, ny=0))
ax[2].set_axes_locator(div.new_locator(nx=0, nx1=2, ny=2))

ax[0].plot(t, x1)
ax[1].plot(t, x2)
ax[2].plot(t, x3)

# <rawcell>

# One obvious application of this is for doing grid of plots with colorbars. For this use case we can go one step further and make use of the ImageGrid class.

# <codecell>
Beispiel #30
0
def plot_stratigraphy(section,
                      style,
                      ncols=1,
                      linewidth=1,
                      col_spacings=0.5,
                      col_widths=1):
    """
    Initialize a figure and subplots, with the stratigraphic section
    already plotted on the first axis.

    This function is intended to act similar to `plt.subplots()` in that
    it will initialize the figure and axis handles. However, given that
    controlling the exact width and height of the axes is critical, this
    function is necessary to initialize the handles correctly.

    Note that setting the figsize itself is not sufficient to control
    the width and height of the axes exactly, since the figsize includes
    the size of the padding around the axes.

    Parameters
    ----------
    section : Section
        A Section object.

    style : Style
        A Style object.

    ncols : int
        The number of axes that will be in the figure (including the
        axis with the stratigraphic section.)

    linewidth : float
        The linewidth when drawing the stratigraphic section.

    col_spacings : float or array_like
        The spacing between the axes in inches. If a float, this value
        will be interpreted as uniform spacing between the axes. If an
        array, the length of the array must be ncols - 1, and the values
        will be the spacing between the individual axes.

    col_widths : float or array_like
        The width of the axes as a ratio relative to the width of the
        stratigraphic column. If a float, this value will be interpreted
        as a uniform width of the axes, excluding the stratigraphic
        column, for which the width is explicitly set in the Style. If
        an array, the length of the array must be ncols - 1, and the
        values will be the widths of the individual axes excluding the
        stratigraphic column.

    Returns
    -------
    fig : matplotlib Figure
        Figure handle.

    ax : matplotlib Axes
        Axis handle.
    """
    # get the attributes - implicitly checks if the attributes exist
    color_attribute = getattr(section, style.color_attribute)
    width_attribute = getattr(section, style.width_attribute)

    # initialize
    fig, ax = plt.subplots(nrows=1, ncols=ncols, sharey=True)

    # get the first axis
    if ncols == 1:
        ax0 = ax
    else:
        ax0 = ax[0]

    # determine the axis height and limits first
    ax_height = style.height_scaling_factor * section.total_thickness
    ax0.set_ylim(0, section.total_thickness)

    # initiate counting of the stratigraphic height
    strat_height = 0.0

    # loop over elements of the data
    for i in range(section.n_units):

        # pull out the thickness
        this_thickness = section.thicknesses[i]

        # loop over the elements in Style to get the color and width
        for j in range(style.n_color_labels):
            if color_attribute[i] == style.color_labels[j]:
                this_color = style.color_values[j]
        for j in range(style.n_width_labels):
            if width_attribute[i] == style.width_labels[j]:
                this_width = style.width_values[j]

        # create the rectangle
        ax0.add_patch(
            Rectangle((0.0, strat_height),
                      this_width,
                      this_thickness,
                      facecolor=this_color,
                      edgecolor='k',
                      linewidth=linewidth))

        # count the stratigraphic height
        strat_height = strat_height + this_thickness

    # set the axis dimensions (values below are all in inches)
    ax0_lower_left_x = 0.5
    ax0_lower_left_y = 0.5
    ax0_width = style.width_inches
    h = [Size.Fixed(ax0_lower_left_x), Size.Fixed(ax0_width)]
    v = [Size.Fixed(ax0_lower_left_y), Size.Fixed(ax_height)]
    divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
    ax0.set_axes_locator(divider.new_locator(nx=1, ny=1))

    # prettify
    ax0.set_xlim(0, 1)
    ax0.set_xticks([0, 0.2, 0.4, 0.6, 0.8, 1])
    for label in ax0.get_xticklabels():
        label.set_rotation(270)
        label.set_ha('center')
        label.set_va('top')
    ax0.set_axisbelow(True)
    ax0.xaxis.grid(ls='--')
    ax0.spines['top'].set_visible(False)
    ax0.spines['right'].set_visible(False)
    ax0.set_ylabel('stratigraphic height [m]')

    # turning the spines off creates some clipping mask issues
    # so just turn the clipping masks off
    for obj in ax0.findobj():
        obj.set_clip_on(False)

    # check if the col_spacing and col_widths is of the correct format
    if type(col_spacings) == list or type(col_spacings) == np.ndarray:
        if len(col_spacings) != ncols - 1:
            raise Exception('col_spacings must be either a float or '
                            'array_like with length ncols-1.')
    if type(col_widths) == list or type(col_widths) == np.ndarray:
        if len(col_widths) != ncols - 1:
            raise Exception('col_widths must be either a float or '
                            'array_like with length ncols-1.')

    # set up the other axes
    if ncols != 1:

        # iterate through the axes
        for i in range(1, ncols):

            # get the spacing and width values
            if type(col_spacings) == list or type(col_spacings) == np.ndarray:
                col_spacing = col_spacings[i - 1]
            else:
                col_spacing = col_spacings
            if type(col_widths) == list or type(col_widths) == np.ndarray:
                col_width = col_widths[i - 1] * ax0_width
            else:
                col_width = col_widths * ax0_width

            # adjust the axis
            if i == 1:
                axn_lower_left_x = ax0_lower_left_x + ax0_width + col_spacing
            else:
                axn_lower_left_x = axn_lower_left_x + axn_width + col_spacing
            axn_lower_left_y = ax0_lower_left_y
            axn_width = col_width
            h = [Size.Fixed(axn_lower_left_x), Size.Fixed(axn_width)]
            v = [Size.Fixed(axn_lower_left_y), Size.Fixed(ax_height)]
            divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
            ax[i].set_axes_locator(divider.new_locator(nx=1, ny=1))

    # set the figsize here too to account for the axis size manipulation
    if ncols != 1:
        fig.set_size_inches(
            ax0_lower_left_x * 2 + np.sum(col_spacings) + np.sum(col_widths) +
            ax0_width, ax0_lower_left_y * 2 + ax_height)
    else:
        fig.set_size_inches(ax0_lower_left_x * 2 + ax0_width,
                            ax0_lower_left_y * 2 + ax_height)

    return fig, ax
Beispiel #31
0
class MatPlotLibBase(QWidget):
    def __init__(self,
                 parent,
                 file_dialog_service,
                 h_margin=(0.8, 0.1),
                 v_margin=(0.5, 0.15),
                 h_axes=[Size.Scaled(1.0)],
                 v_axes=[Size.Scaled(1.0)],
                 nx_default=1,
                 ny_default=1):
        QWidget.__init__(self, parent)
        self._file_dialog_service = file_dialog_service
        self._figure = Figure()
        self._canvas = FigureCanvas(self._figure)
        h = [Size.Fixed(h_margin[0]), *h_axes, Size.Fixed(h_margin[1])]
        v = [Size.Fixed(v_margin[0]), *v_axes, Size.Fixed(v_margin[1])]
        self._divider = Divider(self._figure, (0.0, 0.0, 1.0, 1.0),
                                h,
                                v,
                                aspect=False)
        self._axes = LocatableAxes(self._figure, self._divider.get_position())
        self._axes.set_axes_locator(
            self._divider.new_locator(nx=nx_default, ny=ny_default))
        self._axes.set_zorder(2)
        self._axes.patch.set_visible(False)
        for spine in ['top', 'right']:
            self._axes.spines[spine].set_visible(False)
        self._figure.add_axes(self._axes)

        self._canvas.setParent(self)

        self._layout = QVBoxLayout(self)
        self._layout.setContentsMargins(0, 0, 0, 0)
        self._layout.addWidget(self._canvas)
        self.setLayout(self._layout)

        self._figure.canvas.mpl_connect('scroll_event', self._on_scroll)
        self._xy_extents = None
        self._background_cache = None
        self._decoration_artists = []
        self._is_panning = False

        self._zoom_selector = _RectangleSelector(self._axes,
                                                 self._zoom_selected)
        self._zoom_selector.set_active(False)
        self._x_extent_padding = 0.01
        self._y_extent_padding = 0.01
        self._axes.ticklabel_format(style='sci', axis='x', scilimits=(-4, 4))
        self._axes.ticklabel_format(style='sci', axis='y', scilimits=(-4, 4))
        self._active_tools = {}
        self._span = _SpanSeletor(self._axes,
                                  self._handle_span_select,
                                  'horizontal',
                                  rectprops=dict(alpha=0.2,
                                                 facecolor='red',
                                                 edgecolor='k'),
                                  span_stays=True)
        self._span.set_on_select_none(self._handle_span_select_none)
        self.span = self._previous_span = None
        self._span_center_mouse_event = None
        self._span_left_mouse_event = None
        self._span_right_mouse_event = None
        self._figure.canvas.mpl_connect('button_press_event',
                                        self._handle_press)
        self._figure.canvas.mpl_connect('motion_notify_event',
                                        self._handle_move)
        self._figure.canvas.mpl_connect('button_release_event',
                                        self._handle_release)
        self._figure.canvas.mpl_connect('resize_event', self._handle_resize)
        self.activateTool(ToolType.span, self.isActiveDefault(ToolType.span))
        self._pan_event = None
        self._pending_draw = None
        self._pending_artists_draw = None
        self._other_draw_events = []
        self._draw_timer = QTimer(self)
        self._draw_timer.timeout.connect(self._do_draw_events)
        self._draw_timer.start(20)
        self._zoom_skew = None

        self._menu = QMenu(self)
        self._copy_image_action = QAction(self.tr('Copy To Clipboard'), self)
        self._copy_image_action.triggered.connect(self.copyToClipboard)
        self._copy_image_action.setShortcuts(QKeySequence.Copy)
        self._save_image_action = QAction(self.tr('Save As Image'), self)
        self._save_image_action.triggered.connect(self.saveAsImage)
        self._show_table_action = QAction(self.tr('Show Table'), self)
        self._show_table_action.triggered.connect(self.showTable)
        self._menu.addAction(self._copy_image_action)
        self._menu.addAction(self._save_image_action)
        self._menu.addAction(self._show_table_action)
        self.addAction(self._copy_image_action)

        self._table_view = None
        self._single_axis_zoom_enabled = True
        self._cached_label_width_height = None

        if hasattr(type(self), 'dataChanged'):
            self.dataChanged.connect(self._on_data_changed)

        self._options_view = None
        self._secondary_axes = self._secondary_y_extent = self._secondary_x_extent = None
        self._legend = None
        self._draggable_legend = None
        self._setting_axis_limits = False

        self.hasHiddenSeries = False

    enabledToolsChanged = pyqtSignal()
    spanChanged = pyqtSignal(SpanModel)
    hasHiddenSeriesChanged = pyqtSignal(bool)

    span = AutoProperty(SpanModel)
    hasHiddenSeries = AutoProperty(bool)

    def setOptionsView(self, options_view):
        self._options_view = options_view
        self._options_view.setSecondaryYLimitsEnabled(
            self._secondary_y_enabled())
        self._options_view.setSecondaryXLimitsEnabled(
            self._secondary_x_enabled())

        self._options_view.showGridLinesChanged.connect(
            self._update_grid_lines)
        self._options_view.xAxisLowerLimitChanged.connect(
            self._handle_options_view_limit_changed(x_min_changed=True))
        self._options_view.xAxisUpperLimitChanged.connect(
            self._handle_options_view_limit_changed(x_max_changed=True))
        self._options_view.yAxisLowerLimitChanged.connect(
            self._handle_options_view_limit_changed(y_min_changed=True))
        self._options_view.yAxisUpperLimitChanged.connect(
            self._handle_options_view_limit_changed(y_max_changed=True))
        self._options_view.xAxisLimitsChanged.connect(
            self._handle_options_view_limit_changed(x_min_changed=True,
                                                    x_max_changed=True))
        self._options_view.yAxisLimitsChanged.connect(
            self._handle_options_view_limit_changed(y_min_changed=True,
                                                    y_max_changed=True))

        self._options_view.secondaryXAxisLowerLimitChanged.connect(
            self._handle_options_view_secondary_limit_changed(
                x_min_changed=True))
        self._options_view.secondaryXAxisUpperLimitChanged.connect(
            self._handle_options_view_secondary_limit_changed(
                x_max_changed=True))
        self._options_view.secondaryYAxisLowerLimitChanged.connect(
            self._handle_options_view_secondary_limit_changed(
                y_min_changed=True))
        self._options_view.secondaryYAxisUpperLimitChanged.connect(
            self._handle_options_view_secondary_limit_changed(
                y_max_changed=True))
        self._options_view.secondaryXAxisLimitsChanged.connect(
            self._handle_options_view_secondary_limit_changed(
                x_min_changed=True, x_max_changed=True))
        self._options_view.secondaryYAxisLimitsChanged.connect(
            self._handle_options_view_secondary_limit_changed(
                y_min_changed=True, y_max_changed=True))

    def setLegendControl(self, legend_control):
        self._legend_control = legend_control
        self._legend_control.seriesUpdated.connect(self._legend_series_updated)
        self._legend_control.showLegendChanged.connect(self._show_legend)
        self._legend_control.seriesNameChanged.connect(
            self._handle_series_name_changed)
        self._legend_control.showSeriesChanged.connect(
            self._handle_show_series_changed)
        bind(self._legend_control, self, 'hasHiddenSeries', two_way=False)

    def _legend_series_updated(self):
        if self._legend is not None:
            self._show_legend(self._legend_control.showLegend)

    def _show_legend(self, show):
        if self._legend and not show:
            self._legend.remove()
            self._legend = None
            self.draw()
        elif show:
            if self._legend:
                self._legend.remove()
            show_series = self._legend_control.showSeries
            handles = [
                h for h, s in zip(self._legend_control.seriesHandles,
                                  show_series) if s
            ]
            names = [
                n
                for n, s in zip(self._legend_control.seriesNames, show_series)
                if s
            ]
            axes = (self._secondary_axes if self._secondary_axes
                    and self._secondary_axes.get_visible()
                    and self._secondary_axes.get_zorder() >
                    self._axes.get_zorder() else self._axes)
            self._legend = self._create_legend(
                axes,
                handles,
                names,
                markerscale=self._get_legend_markerscale())
            if self._get_legend_text_color() is not None:
                for text in self._legend.texts:
                    text.set_color(self._get_legend_text_color())
            self._draggable_legend = DraggableLegend(self._legend)
            self.draw()

    def _get_legend_markerscale(self):
        return 5

    def _create_legend(self, axes, handles, names, **kwargs):
        return axes.legend(handles, names, **kwargs)

    def _get_legend_text_color(self):
        return None

    def _handle_series_name_changed(self, index, series_name):
        if self._legend is not None and index < len(
                self._legend_control.seriesHandles):
            visible_handles = [
                h for h, s in zip(self._legend_control.seriesHandles,
                                  self._legend_control.showSeries)
                if s and h is not None
            ]
            try:
                legend_index = visible_handles.index(
                    self._legend_control.seriesHandles[index])
            except ValueError:
                return
            if legend_index < len(self._legend.texts):
                self._legend.texts[legend_index].set_text(series_name)
                self.draw()

    def _handle_show_series_changed(self, index, show_series):
        if index < len(self._legend_control.seriesHandles):
            self._set_series_visibility(
                self._legend_control.seriesHandles[index], show_series)
        if self._legend is not None:
            self._show_legend(self._legend_control.showLegend)
        else:
            self.draw()

    def _set_series_visibility(self, handle, visible):
        if not handle:
            return
        if hasattr(handle, 'set_visible'):
            handle.set_visible(visible)
        elif hasattr(handle, 'get_children'):
            for child in handle.get_children():
                self._set_series_visibility(child, visible)

    def _update_grid_lines(self):
        show_grid_lines = False if self._options_view is None else self._options_view.showGridLines
        gridline_color = self._axes.spines['bottom'].get_edgecolor()
        gridline_color = gridline_color[0], gridline_color[1], gridline_color[
            2], 0.5
        kwargs = dict(color=gridline_color,
                      alpha=0.5) if show_grid_lines else {}
        self._axes.grid(show_grid_lines, **kwargs)
        self.draw()

    def _handle_options_view_limit_changed(self,
                                           x_min_changed=False,
                                           x_max_changed=False,
                                           y_min_changed=False,
                                           y_max_changed=False):
        def _():
            if self._options_view is None or self._setting_axis_limits:
                return
            (x_min, x_max), (y_min, y_max) = (new_x_min, new_x_max), (
                new_y_min, new_y_max) = self._get_xy_extents()
            (x_opt_min,
             x_opt_max), (y_opt_min,
                          y_opt_max) = self._get_options_view_xy_extents()
            if x_min_changed:
                new_x_min = x_opt_min
            if x_max_changed:
                new_x_max = x_opt_max
            if y_min_changed:
                new_y_min = y_opt_min
            if y_max_changed:
                new_y_max = y_opt_max
            if [new_x_min, new_x_max, new_y_min, new_y_max
                ] != [x_min, x_max, y_min, y_max]:
                self._xy_extents = (new_x_min, new_x_max), (new_y_min,
                                                            new_y_max)
                self._set_axes_limits()
                self.draw()

        return _

    def _get_options_view_xy_extents(self):
        (x_data_min, x_data_max), (y_data_min,
                                   y_data_max) = self._get_data_xy_extents()
        x_min = x_data_min if np.isnan(
            self._options_view.xAxisLowerLimit
        ) else self._options_view.xAxisLowerLimit
        x_max = x_data_max if np.isnan(
            self._options_view.xAxisUpperLimit
        ) else self._options_view.xAxisUpperLimit
        y_min = y_data_min if np.isnan(
            self._options_view.yAxisLowerLimit
        ) else self._options_view.yAxisLowerLimit
        y_max = y_data_max if np.isnan(
            self._options_view.yAxisUpperLimit
        ) else self._options_view.yAxisUpperLimit
        return (x_min, x_max), (y_min, y_max)

    def _handle_options_view_secondary_limit_changed(self,
                                                     x_min_changed=False,
                                                     x_max_changed=False,
                                                     y_min_changed=False,
                                                     y_max_changed=False):
        def _():
            if self._options_view is None or self._setting_axis_limits:
                return
            updated = False
            (x_opt_min, x_opt_max), (
                y_opt_min,
                y_opt_max) = self._get_options_view_secondary_xy_extents()
            if self._has_secondary_y_extent() and (y_min_changed
                                                   or y_max_changed):
                y_min, y_max = new_y_min, new_y_max = self._get_secondary_y_extent(
                )
                if y_min_changed:
                    new_y_min = y_opt_min
                if y_max_changed:
                    new_y_max = y_opt_max
                if [new_y_min, new_y_max] != [y_min, y_max]:
                    self._secondary_y_extent = (new_y_min, new_y_max)
                    updated = True
            if self._has_secondary_x_extent() and (x_min_changed
                                                   or x_max_changed):
                x_min, x_max = new_x_min, new_x_max = self._get_secondary_x_extent(
                )
                if x_min_changed:
                    new_x_min = x_opt_min
                if x_max_changed:
                    new_x_max = x_opt_max
                if [new_x_min, new_x_max] != [x_min, x_max]:
                    self._secondary_x_extent = (new_x_min, new_x_max)
                    updated = True
            if updated:
                self._set_axes_limits()
                self.draw()

        return _

    def _get_options_view_secondary_xy_extents(self):
        x_data_min, x_data_max = self._get_data_secondary_x_extent()
        y_data_min, y_data_max = self._get_data_secondary_y_extent()
        x_min = x_data_min if np.isnan(
            self._options_view.secondaryXAxisLowerLimit
        ) else self._options_view.secondaryXAxisLowerLimit
        x_max = x_data_max if np.isnan(
            self._options_view.secondaryXAxisUpperLimit
        ) else self._options_view.secondaryXAxisUpperLimit
        y_min = y_data_min if np.isnan(
            self._options_view.secondaryYAxisLowerLimit
        ) else self._options_view.secondaryYAxisLowerLimit
        y_max = y_data_max if np.isnan(
            self._options_view.secondaryYAxisUpperLimit
        ) else self._options_view.secondaryYAxisUpperLimit
        return (x_min, x_max), (y_min, y_max)

    def _on_data_changed(self):
        self._cached_label_width_height = None

    def closeEvent(self, event):
        QWidget.closeEvent(self, event)
        if event.isAccepted():
            self._zoom_selector.onselect = self._span.onselect = self._span._select_none_handler = None

    def set_divider_h_margin(self, h_margin):
        h = [
            Size.Fixed(h_margin[0]),
            Size.Scaled(1.0),
            Size.Fixed(h_margin[1])
        ]
        self._divider.set_horizontal(h)

    def set_divider_v_margin(self, v_margin):
        v = [
            Size.Fixed(v_margin[0]),
            Size.Scaled(1.0),
            Size.Fixed(v_margin[1])
        ]
        self._divider.set_vertical(v)

    @property
    def x_extent_padding(self):
        return self._x_extent_padding

    @x_extent_padding.setter
    def x_extent_padding(self, value):
        self._x_extent_padding = value

    @property
    def y_extent_padding(self):
        return self._y_extent_padding

    @y_extent_padding.setter
    def y_extent_padding(self, value):
        self._y_extent_padding = value

    def _in_interval(self, value, interval):
        return interval[0] <= value <= interval[1]

    def _interval_skew(self, value, interval):
        return (value - interval[0]) / (interval[1] - interval[0])

    def _in_x_scroll_zone(self, event):
        return self._in_interval(event.x, self._axes.bbox.intervalx
                                 ) and event.y <= self._axes.bbox.intervaly[1]

    def _in_y_scroll_zone(self, event):
        return self._in_interval(event.y, self._axes.bbox.intervaly
                                 ) and event.x <= self._axes.bbox.intervalx[1]

    def _on_scroll(self, event):
        if self._secondary_axes is not None:
            self._handle_scroll_secondary(event)
        in_x = self._in_x_scroll_zone(event)
        in_y = self._in_y_scroll_zone(event)
        if in_x or in_y and event.button in ['up', 'down']:
            (x_min, x_max), (y_min, y_max) = self._get_actual_xy_extents()
            if (in_x and self._single_axis_zoom_enabled) or (in_x and in_y):
                skew = self._zoom_skew and self._zoom_skew[0]
                skew = self._interval_skew(
                    event.x,
                    self._axes.bbox.intervalx) if skew is None else skew
                x_min, x_max = self._zoom(x_min, x_max, skew, event.button)
            if (in_y and self._single_axis_zoom_enabled) or (in_x and in_y):
                skew = self._zoom_skew and self._zoom_skew[1]
                skew = self._interval_skew(
                    event.y,
                    self._axes.bbox.intervaly) if skew is None else skew
                y_min, y_max = self._zoom(y_min, y_max, skew, event.button)
            self._xy_extents = (x_min, x_max), (y_min, y_max)
        self._set_axes_limits()
        self.draw()

    def _in_secondary_y_scroll_zone(self, event):
        return self._in_interval(event.y, self._axes.bbox.intervaly) and \
                event.x >= self._axes.bbox.intervalx[1]

    def _in_secondary_x_scroll_zone(self, event):
        return self._in_interval(event.x, self._axes.bbox.intervalx) and \
                event.y >= self._axes.bbox.intervaly[1]

    def _handle_scroll_secondary(self, event):
        if self._has_secondary_y_extent():
            in_secondary_y = self._in_secondary_y_scroll_zone(event)
            if in_secondary_y and event.button in ['up', 'down']:
                self._secondary_y_extent = self._zoom(
                    *self._get_secondary_y_extent(),
                    self._interval_skew(event.y, self._axes.bbox.intervaly),
                    event.button)
        if self._has_secondary_x_extent():
            in_secondary_x = self._in_secondary_x_scroll_zone(event)
            if in_secondary_x and event.button in ['up', 'down']:
                self._secondary_x_extent = self._zoom(
                    *self._get_secondary_x_extent(),
                    self._interval_skew(event.x, self._axes.bbox.intervalx),
                    event.button)

    def _get_zoom_multiplier(self):
        return 20 / 19

    def _zoom(self, min_, max_, skew, direction):
        zoom_multiplier = self._get_zoom_multiplier(
        ) if direction == 'up' else 1 / self._get_zoom_multiplier()
        range_ = max_ - min_
        diff = (range_ * (1 / zoom_multiplier)) - range_
        max_ += diff * (1 - skew)
        min_ -= diff * skew
        return min_, max_

    def _set_axes_limits(self):
        try:
            self._setting_axis_limits = True
            if self._secondary_axes is not None:
                self._set_secondary_axes_limits()
            self._update_ticks()
            (x_min, x_max), (y_min, y_max) = self._get_xy_extents()
            if self._options_view is not None:
                if self._options_view.x_limits:
                    self._options_view.setXLimits(float(x_min), float(x_max))
                if self._options_view.y_limits:
                    self._options_view.setYLimits(float(y_min), float(y_max))
            self._axes.set_xlim(*_safe_limits(x_min, x_max))
            self._axes.set_ylim(*_safe_limits(y_min, y_max))
        finally:
            self._setting_axis_limits = False

    def _set_secondary_axes_limits(self):
        if self._options_view is not None:
            if self._options_view.secondary_y_limits:
                enabled = self._secondary_y_enabled()
                secondary_y_min, secondary_y_max = self._get_secondary_y_extent(
                ) if enabled else (float('nan'), float('nan'))
                self._options_view.setSecondaryYLimitsEnabled(enabled)
                self._options_view.setSecondaryYLimits(float(secondary_y_min),
                                                       float(secondary_y_max))
            if self._options_view.secondary_x_limits:
                enabled = self._secondary_x_enabled()
                secondary_x_min, secondary_x_max = self._get_secondary_x_extent(
                ) if enabled else (float('nan'), float('nan'))
                self._options_view.setSecondaryXLimitsEnabled(enabled)
                self._options_view.setSecondaryXLimits(float(secondary_x_min),
                                                       float(secondary_x_max))
        if self._has_secondary_y_extent():
            self._secondary_axes.set_ylim(*_safe_limits(
                *self._get_secondary_y_extent()))
        if self._has_secondary_x_extent():
            self._secondary_axes.set_xlim(*_safe_limits(
                *self._get_secondary_x_extent()))

    def _secondary_y_enabled(self):
        return True if self._secondary_axes and self._secondary_axes.get_visible(
        ) and self._has_secondary_y_extent() else False

    def _secondary_x_enabled(self):
        return True if self._secondary_axes and self._secondary_axes.get_visible(
        ) and self._has_secondary_x_extent() else False

    def _set_axes_labels(self):
        self._axes.set_xlabel(self.data.xAxisTitle)
        self._axes.set_ylabel(self.data.yAxisTitle)

    def _set_center(self, center):
        if not all(c is not None for c in center):
            center = (0, 0)
        x_extent, y_extent = self._get_xy_extents()
        span = x_extent[1] - x_extent[0], y_extent[1] - y_extent[0]
        x_extent = center[0] - span[0] / 2, center[0] + span[0] / 2
        y_extent = center[1] - span[1] / 2, center[1] + span[1] / 2
        self._xy_extents = x_extent, y_extent

    def _get_xy_extents(self):
        if self.data is None:
            return (0, 0), (0, 0)
        if self._xy_extents is None:
            return self._get_data_xy_extents()
        return self._xy_extents

    def _get_data_xy_extents(self):
        if self.data is None:
            return (0, 0), (0, 0)
        (x_min, x_max), (y_min, y_max) = self.data.get_xy_extents()
        return self._pad_extent(x_min, x_max,
                                self.x_extent_padding), self._pad_extent(
                                    y_min, y_max, self.y_extent_padding)

    def _has_secondary_y_extent(self):
        return hasattr(self.data, 'get_secondary_y_extent')

    def _get_secondary_y_extent(self):
        if self._secondary_y_extent is not None:
            return self._secondary_y_extent
        if self.data is not None:
            return self._get_data_secondary_y_extent()
        return (0, 0)

    def _get_data_secondary_y_extent(self):
        if self.data is None:
            return (0, 0)
        return self._pad_extent(*self.data.get_secondary_y_extent(),
                                self.y_extent_padding)

    def _has_secondary_x_extent(self):
        return hasattr(self.data, 'get_secondary_x_extent')

    def _get_secondary_x_extent(self):
        if self._secondary_x_extent is not None:
            return self._secondary_x_extent
        if self.data is not None:
            return self._get_data_secondary_x_extent()
        return (0, 0)

    def _get_data_secondary_x_extent(self):
        if self.data is None or not hasattr(self.data,
                                            'get_secondary_x_extent'):
            return (0, 0)
        return self._pad_extent(*self.data.get_secondary_x_extent(),
                                self.x_extent_padding)

    def _get_actual_xy_extents(self):
        return self._axes.get_xlim(), self._axes.get_ylim()

    def _pad_extent(self, min_, max_, padding):
        min_, max_ = self._zero_if_nan(min_), self._zero_if_nan(max_)
        range_ = max_ - min_
        return min_ - padding * range_, max_ + padding * range_

    def _zoom_selected(self, start_pos, end_pos):
        x_min, x_max = min(start_pos.xdata,
                           end_pos.xdata), max(start_pos.xdata, end_pos.xdata)
        y_min, y_max = min(start_pos.ydata,
                           end_pos.ydata), max(start_pos.ydata, end_pos.ydata)
        self._xy_extents = (x_min, x_max), (y_min, y_max)
        self._set_axes_limits()
        self.draw()

    def _handle_span_select(self, x_min, x_max):
        x_min, x_max = self._round_to_bin_width(x_min, x_max)
        self._update_span_rect(x_min, x_max)
        self.span = SpanModel(self, x_min, x_max)
        self.draw()

    def _handle_span_select_none(self):
        self.span = None

    def _handle_press(self, event):
        if event.button == 1:
            if self._is_panning:
                self._pan_event = event
            elif self._span.active:
                self._handle_span_press(event)

    def _handle_move(self, event):
        if event.xdata and self._pan_event:
            self._handle_pan_move(event)
        elif event.xdata and any(self._span_events()):
            self._handle_span_move(event)

    def _handle_release(self, event):
        if self._pan_event:
            self._pan_event = None
        elif any(self._span_events()):
            self._handle_span_release(event)

    def _handle_pan_move(self, event):
        from_x, from_y = self._axes.transData.inverted().transform(
            (self._pan_event.x, self._pan_event.y))
        to_x, to_y = self._axes.transData.inverted().transform(
            (event.x, event.y))
        self._pan(from_x - to_x, from_y - to_y)
        self._pan_event = event

    def _pan(self, delta_x, delta_y):
        (x_min, x_max), (y_min, y_max) = self._get_xy_extents()
        self._xy_extents = (x_min + delta_x,
                            x_max + delta_x), (y_min + delta_y,
                                               y_max + delta_y)
        self._set_axes_limits()
        self.draw()

    def _span_events(self):
        return self._span_center_mouse_event, self._span_left_mouse_event, self._span_right_mouse_event

    def _handle_span_press(self, event):
        if not event.xdata:
            return
        span_min, span_max = (self.span.left,
                              self.span.right) if self.span else (0, 0)
        edge_tolerance = self._span_tolerance()
        if abs(span_min - event.xdata) < edge_tolerance:
            self._span.active = False
            self._span_left_mouse_event = event
        elif abs(span_max - event.xdata) < edge_tolerance:
            self._span.active = False
            self._span_right_mouse_event = event
        elif span_min < event.xdata < span_max:
            self._span.active = False
            self._span_center_mouse_event = event

    def _handle_span_move(self, event):
        if not self.span:
            return
        x_min, x_max = self.span.left, self.span.right
        last_event = next(x for x in self._span_events() if x)
        diff_x = event.xdata - last_event.xdata
        if self._span_center_mouse_event is not None:
            self._update_span_rect(x_min + diff_x)
        elif self._span_left_mouse_event is not None:
            self._update_span_rect(x_min + diff_x, x_max)
        elif self._span_right_mouse_event is not None:
            self._update_span_rect(x_min, x_max + diff_x)
        self.draw([self._span.rect])

    def _handle_span_release(self, _event):
        x_min = self._span.rect.get_x()
        x_max = x_min + self._span.rect.get_width()
        x_min, x_max = self._round_to_bin_width(x_min, x_max)
        self._update_span_rect(x_min, x_max)
        self.span = SpanModel(self, x_min, x_max)
        self.draw()
        self._span.active = True
        self._span_center_mouse_event = self._span_left_mouse_event = self._span_right_mouse_event = None

    def _update_span_rect(self, x_min, x_max=None):
        self._span.rect.set_x(x_min)
        self._span.stay_rect.set_x(x_min)
        if x_max:
            self._span.rect.set_width(x_max - x_min)
            self._span.stay_rect.set_width(x_max - x_min)

    def _round_to_bin_width(self, x_min, x_max):
        return x_min, x_max

    def _span_tolerance(self):
        return 5

    def toolEnabled(self, _tool_type):
        return False

    def toolAvailable(self, _tool_type):
        return False

    def activateTool(self, tool_type, active):
        if tool_type == ToolType.zoom:
            self._zoom_selector.set_active(active)
        elif tool_type == ToolType.span:
            if self._span.active and not active:
                self._previous_span = self.span
                self.span = None
                for r in [self._span.rect, self._span.stay_rect]:
                    self._remove_artist(r)
            elif not self._span.active and active:
                self.span = self._previous_span
                for r in [self._span.rect, self._span.stay_rect]:
                    self._add_artist(r)
            self._span.active = active
            self.draw()
        elif tool_type == ToolType.pan:
            self._is_panning = active
        self._active_tools[tool_type] = active

    def toolActive(self, tool_type):
        return self._active_tools.get(tool_type, False)

    def isActiveDefault(self, _tool_type):
        return False

    def _add_artist(self, artist):
        self._axes.add_artist(artist)
        self._decoration_artists.append(artist)

    def _remove_artist(self, artist):
        artist.remove()
        if artist in self._decoration_artists:
            self._decoration_artists.remove(artist)

    def _handle_resize(self, _event):
        self._update_ticks()
        return self.draw()

    def draw(self, artists=None):
        if artists is None:

            def _update():
                for a in self._decoration_artists:
                    a.remove()
                self._canvas.draw()
                self._background_cache = self._canvas.copy_from_bbox(
                    self._figure.bbox)
                for a in self._decoration_artists:
                    self._axes.add_artist(a)
                    self._axes.draw_artist(a)
                self._canvas.update()

            self._pending_draw = _update
        else:

            def _update():
                if self._background_cache is None:
                    raise RuntimeError('Must run draw before drawing artists!')
                self._canvas.restore_region(self._background_cache)
                for a in artists:
                    self._axes.draw_artist(a)
                self._canvas.update()

            self._pending_artists_draw = _update

    def _do_draw_events(self):
        if self._pending_draw is not None:
            self._pending_draw()
            self._pending_draw = None
        if self._pending_artists_draw is not None:
            self._pending_artists_draw()
            self._pending_artists_draw = None
        if self._other_draw_events:
            for draw_event in self._other_draw_events:
                draw_event()
            self._other_draw_events = []

    def addDrawEvent(self, draw_event):
        self._other_draw_events.append(draw_event)

    def resetZoom(self):
        self._secondary_y_extent = self._secondary_x_extent = None
        self._xy_extents = None
        self._set_axes_limits()
        self.draw()

    def _twinx(self, ylabel):
        axes = self._axes.twinx()
        for spine in ['top', 'left']:
            axes.spines[spine].set_visible(False)
        axes.set_ylabel(ylabel)
        axes.set_zorder(1)
        return axes

    @property
    def axes(self):
        return self._axes

    @property
    def secondary_axes(self):
        if self._secondary_axes is None:
            self._set_secondary_axes(self._twinx(''))
        return self._secondary_axes

    def _set_secondary_axes(self, axes):
        self._secondary_axes = axes

    @staticmethod
    def sizeHint():
        """function::sizeHint()
        Override the default sizeHint to ensure the plot has an initial size
        """
        return QSize(600, 400)

    def minimumSizeHint(self):
        """function::sizeHint()
        Override the default sizeHint to ensure the plot does not shrink below minimum size
        """
        return self.sizeHint()

    @staticmethod
    def _zero_if_nan(value):
        return value if not isinstance(value,
                                       float) or not np.isnan(value) else 0

    def canShowTable(self):
        return hasattr(self, 'data') and self.data is not None and hasattr(
            self.data, 'table')

    def contextMenuEvent(self, event):
        self._show_table_action.setEnabled(self.canShowTable())
        self._menu.exec_(event.globalPos())

    def copyToClipboard(self):
        with BytesIO() as buffer:
            self._figure.savefig(buffer,
                                 facecolor=self._figure.get_facecolor())
            QApplication.clipboard().setImage(
                QImage.fromData(buffer.getvalue()))

    def saveAsImage(self):
        filename = self._file_dialog_service.get_save_filename(
            self, self.tr('Portable Network Graphics (*.png)'))
        if filename:
            self._figure.savefig(filename,
                                 facecolor=self._figure.get_facecolor())

    def showTable(self):
        if self.canShowTable():
            self._table_view = TableView(None)
            self._table_view.pasteEnabled = False
            self._table_view.setModel(self.data.table)
            self._table_view.setMinimumSize(800, 600)
            self._table_view.show()

    def _update_ticks(self):
        if not self.data:
            return
        if hasattr(self.data, 'x_labels'):
            step = self.data.x_tick_interval if hasattr(
                self.data, 'x_tick_interval') else None
            x_ticks, x_labels = self._get_labels(self.data.x_labels,
                                                 step,
                                                 horizontal=True)
            self._axes.set_xticks(x_ticks)
            self._axes.set_xticklabels(x_labels)
        if hasattr(self.data, 'y_labels'):
            step = self.data.y_tick_interval if hasattr(
                self.data, 'y_tick_interval') else None
            y_ticks, y_labels = self._get_labels(self.data.y_labels,
                                                 step,
                                                 horizontal=False)
            self._axes.set_yticks(y_ticks)
            self._axes.set_yticklabels(y_labels)

    def _get_labels(self, labels, step, horizontal=True):
        (x0, x1), (y0, y1) = self._get_xy_extents()
        start, end = (int(x0), int(x1)) if horizontal else (int(y0), int(y1))
        visible_points = end - start
        if not (step and step > 0):
            width, height = self._get_label_width_height(labels)
            axes_bbox = self._axes.get_window_extent(
                self._figure.canvas.get_renderer()).transformed(
                    self._figure.dpi_scale_trans.inverted())
            plot_size = (axes_bbox.width if horizontal else
                         axes_bbox.height) * self._figure.dpi
            size = (width if horizontal else height)
            if plot_size == 0 or size == 0:
                n_labels = 16
            else:
                n_labels = int(plot_size / size)
                if n_labels == 0:
                    n_labels = 16
            step = int(visible_points / n_labels) + 1
        else:
            step = int(step)
        indexes = list(range(len(labels)))
        display_labels = list(labels)
        for i in indexes:
            if i % step:
                display_labels[i] = ''
        return indexes, display_labels

    def _get_label_width_height(self, labels):
        if not self._cached_label_width_height:
            font = MatPlotLibFont.default()
            width = 0
            height = 0
            for label in labels:
                next_width, next_height = font.get_size(
                    str(label), matplotlib.rcParams['font.size'],
                    self._figure.dpi)
                width = max(width, next_width)
                height = max(height, next_height)
            self._cached_label_width_height = width, height
        return self._cached_label_width_height

    def _create_new_axes(self, nx=1, ny=1) -> LocatableAxes:
        axes = LocatableAxes(self._figure, self._divider.get_position())
        axes.set_axes_locator(self._divider.new_locator(nx=nx, ny=ny))
        self._figure.add_axes(axes)
        return axes

    @staticmethod
    def _create_secondary_xy_axes(figure,
                                  divider,
                                  nx=1,
                                  ny=1,
                                  visible=False,
                                  z_order=1):
        axes = LocatableAxes(figure, divider.get_position())
        axes.set_axes_locator(divider.new_locator(nx=nx, ny=ny))
        axes.xaxis.tick_top()
        axes.xaxis.set_label_position('top')
        axes.yaxis.tick_right()
        axes.yaxis.set_label_position('right')
        axes.patch.set_visible(visible)
        axes.set_zorder(z_order)
        figure.add_axes(axes)
        axes.ticklabel_format(style='sci', axis='x', scilimits=(-4, 4))
        axes.ticklabel_format(style='sci', axis='y', scilimits=(-4, 4))
        return axes

    @staticmethod
    def _create_shared_axes(figure,
                            divider,
                            shared_axes,
                            nx=1,
                            ny=1,
                            visible=False,
                            z_order=1):
        axes = LocatableAxes(figure,
                             divider.get_position(),
                             sharex=shared_axes,
                             sharey=shared_axes,
                             frameon=False)
        axes.set_axes_locator(divider.new_locator(nx=nx, ny=ny))
        for spine in axes.spines.values():
            spine.set_visible(False)
        for axis in axes.axis.values():
            axis.set_visible(False)
        axes.patch.set_visible(False)
        axes.set_visible(False)
        axes.set_zorder(z_order)
        figure.add_axes(axes)
        return axes
Beispiel #32
0
    def delay_avg_svg(self, ttype, b64encode=True):
        fig = pyplot.figure(figsize=self.FIGSIZE)

        h = [Size.Fixed(1.2), Size.Scaled(1.), Size.Fixed(.2)]
        v = [Size.Fixed(0.7), Size.Scaled(1.), Size.Fixed(.5)]

        divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False)
        plt = Axes(fig, divider.get_position())
        plt.set_axes_locator(divider.new_locator(nx=1, ny=1))

        fig.add_axes(plt)

        result = self.result
        runinfo = result.runinfo

        # ----
        # The X limits are -rampupMins, runMins
        # ----
        plt.set_xlim(-int(runinfo['rampupMins']), int(runinfo['runMins']))
        plt.axvspan(-int(runinfo['rampupMins']), 0, facecolor='0.2', alpha=0.1)

        # ----
        # offset the timestamps by -rampupMins so that the graph
        # starts with negative minutes elapsed and switches to
        # positive when the measurement begins.
        # ----
        offset = (int(runinfo['rampupMins'])) * 60.0

        # ----
        # ttype transaction delay. First get the timestamp
        # and delay numbers from the result data.
        # The X vector then is the sorted unique timestamps rounded
        # to an interval.
        # ----
        interval = 10
        data = numpy.array([[(int(tup[0] / interval) * interval - offset) / 60,
                             tup[1], tup[5]]
                            for tup in result.result_ttype[ttype]])
        x = sorted(numpy.unique(data[:, 0]))

        # ----
        # The Y vector is the sums of transactions delay divided by
        # the sums of the count, grouped by X.
        # ----
        y = []
        for ts in x:
            tmp = data[numpy.where(data[:, 0] == ts)]
            y.append(numpy.sum(tmp[:, 2]) / (numpy.sum(tmp[:, 1]) + 0.000001))

        # ----
        # Plot the ttype delay and add all the decorations
        # ----
        plt.plot(x, y, 'r', label='Delay')

        # ----
        # Now do the same aggregation for the latency
        # ----
        data = numpy.array([[(int(tup[0] / interval) * interval - offset) / 60,
                             tup[1], tup[2]]
                            for tup in result.result_ttype[ttype]])

        # ----
        # The Y vector is similar by based on latency
        # ----
        y = []
        for ts in x:
            tmp = data[numpy.where(data[:, 0] == ts)]
            y.append(numpy.sum(tmp[:, 2]) / (numpy.sum(tmp[:, 1]) + 0.000001))
        plt.plot(x, y, 'b', label='Latency')

        plt.set_title("{} Average Latency and Delay".format(ttype))
        plt.set_xlabel("Elapsed Minutes")
        plt.set_ylabel("Latency/Delay in ms")
        plt.legend(loc='upper left')
        plt.grid()

        buf = io.StringIO()
        pyplot.savefig(buf, format='svg')

        if not b64encode:
            return buf.getvalue()
        return base64.b64encode(buf.getvalue().encode('utf-8')).decode('utf-8')
    # # if use_alpha:
    # rgba = colors.hsv_to_rgb(hsv)
    # rgba = np.dstack([rgba, alpha])
    # # else:
    # hsv[:, :, 2] = alpha.clip(min=0.2, max=value)
    # rgba_l = colors.hsv_to_rgb(hsv)
    # alpha_l = np.abs(1 - alpha).clip(min=value, max=1)
    # hsv[:, :, 2] = alpha_l
    # rgba_lr = colors.hsv_to_rgb(hsv)

    cmap = colors.ListedColormap(cmap, name='test1')

fig = plt.figure(1, figsize=(12, 8))
h = [Size.Fixed(0.), Size.Fixed(6.5)]
v = [Size.Fixed(0.5), Size.Fixed(3.25)]
win = Divider(fig, (0.1, 0.1, 0.8, 0.8), h, v, aspect=False)
ax = Axes(fig, win.get_position())
ax.set_axes_locator(win.new_locator(nx=1, ny=1))
fig.add_axes(ax)
# fig = plt.gcf()
for ii in range(1, 2):
    if ii == 0:
        to_plot = rgb
        title = 'Model'
    elif ii == 1:
        to_plot = rgba
        title = 'Model + Resolution (Transparency)'
    elif ii == 2:
        to_plot = rgba_l
        title = 'Model + Resolution (Lightness)'
    else:
Beispiel #34
0
    def __init__(self,
                 parent,
                 file_dialog_service,
                 h_margin=(0.8, 0.1),
                 v_margin=(0.5, 0.15),
                 h_axes=[Size.Scaled(1.0)],
                 v_axes=[Size.Scaled(1.0)],
                 nx_default=1,
                 ny_default=1):
        QWidget.__init__(self, parent)
        self._file_dialog_service = file_dialog_service
        self._figure = Figure()
        self._canvas = FigureCanvas(self._figure)
        h = [Size.Fixed(h_margin[0]), *h_axes, Size.Fixed(h_margin[1])]
        v = [Size.Fixed(v_margin[0]), *v_axes, Size.Fixed(v_margin[1])]
        self._divider = Divider(self._figure, (0.0, 0.0, 1.0, 1.0),
                                h,
                                v,
                                aspect=False)
        self._axes = LocatableAxes(self._figure, self._divider.get_position())
        self._axes.set_axes_locator(
            self._divider.new_locator(nx=nx_default, ny=ny_default))
        self._axes.set_zorder(2)
        self._axes.patch.set_visible(False)
        for spine in ['top', 'right']:
            self._axes.spines[spine].set_visible(False)
        self._figure.add_axes(self._axes)

        self._canvas.setParent(self)

        self._layout = QVBoxLayout(self)
        self._layout.setContentsMargins(0, 0, 0, 0)
        self._layout.addWidget(self._canvas)
        self.setLayout(self._layout)

        self._figure.canvas.mpl_connect('scroll_event', self._on_scroll)
        self._xy_extents = None
        self._background_cache = None
        self._decoration_artists = []
        self._is_panning = False

        self._zoom_selector = _RectangleSelector(self._axes,
                                                 self._zoom_selected)
        self._zoom_selector.set_active(False)
        self._x_extent_padding = 0.01
        self._y_extent_padding = 0.01
        self._axes.ticklabel_format(style='sci', axis='x', scilimits=(-4, 4))
        self._axes.ticklabel_format(style='sci', axis='y', scilimits=(-4, 4))
        self._active_tools = {}
        self._span = _SpanSeletor(self._axes,
                                  self._handle_span_select,
                                  'horizontal',
                                  rectprops=dict(alpha=0.2,
                                                 facecolor='red',
                                                 edgecolor='k'),
                                  span_stays=True)
        self._span.set_on_select_none(self._handle_span_select_none)
        self.span = self._previous_span = None
        self._span_center_mouse_event = None
        self._span_left_mouse_event = None
        self._span_right_mouse_event = None
        self._figure.canvas.mpl_connect('button_press_event',
                                        self._handle_press)
        self._figure.canvas.mpl_connect('motion_notify_event',
                                        self._handle_move)
        self._figure.canvas.mpl_connect('button_release_event',
                                        self._handle_release)
        self._figure.canvas.mpl_connect('resize_event', self._handle_resize)
        self.activateTool(ToolType.span, self.isActiveDefault(ToolType.span))
        self._pan_event = None
        self._pending_draw = None
        self._pending_artists_draw = None
        self._other_draw_events = []
        self._draw_timer = QTimer(self)
        self._draw_timer.timeout.connect(self._do_draw_events)
        self._draw_timer.start(20)
        self._zoom_skew = None

        self._menu = QMenu(self)
        self._copy_image_action = QAction(self.tr('Copy To Clipboard'), self)
        self._copy_image_action.triggered.connect(self.copyToClipboard)
        self._copy_image_action.setShortcuts(QKeySequence.Copy)
        self._save_image_action = QAction(self.tr('Save As Image'), self)
        self._save_image_action.triggered.connect(self.saveAsImage)
        self._show_table_action = QAction(self.tr('Show Table'), self)
        self._show_table_action.triggered.connect(self.showTable)
        self._menu.addAction(self._copy_image_action)
        self._menu.addAction(self._save_image_action)
        self._menu.addAction(self._show_table_action)
        self.addAction(self._copy_image_action)

        self._table_view = None
        self._single_axis_zoom_enabled = True
        self._cached_label_width_height = None

        if hasattr(type(self), 'dataChanged'):
            self.dataChanged.connect(self._on_data_changed)

        self._options_view = None
        self._secondary_axes = self._secondary_y_extent = self._secondary_x_extent = None
        self._legend = None
        self._draggable_legend = None
        self._setting_axis_limits = False

        self.hasHiddenSeries = False
                data = extract_csvs(stacked_boxplot.visualization, './data/temp/csv')
                level_4 = data[4]

                # Filters the level 4 data to CD and UC
                IBD_level_4 = level_4.loc[level_4['dx'].isin(["CD", "UC"])]
                IBD_level_4 = IBD_level_4.drop(columns=metadata_columns)
                IBD_level_4 = IBD_level_4.set_index('index')

                # Normalise the data around 0
                standardised = (IBD_level_4 - IBD_level_4.mean()) / IBD_level_4.std()

                # sets the sizing so as much of the label can be shown as possible
                fig = plt.figure(figsize=(11.7, 8.27))
                h = [Size.Fixed(6.), Size.Scaled(.5), Size.Fixed(.2)]
                v = [Size.Fixed(0.7), Size.Scaled(.5), Size.Fixed(.5)]
                divider = Divider(fig, (0, 0, 1, 1), h, v, aspect=False)
                ax = fig.add_axes(divider.get_position(),
                                  axes_locator=divider.new_locator(nx=1, ny=1))

                # Plots the relative frequency
                sns.boxplot(y="variable", x="value", data=pd.melt(standardised), showfliers=False, width=.6, ax=ax)
                ax.xaxis.grid(True)
                ax.set(ylabel="Bacteria", xlabel="Relative Abundance",
                       title="Relative Abundance for IBD for taxa at level 4")
                sns.despine(trim=True, left=True)
                plt.savefig(out_individual_boxplot)

                this_experiment = {
                    "_id": experiment_id,
                    "parent": parent_name,
                    "stage": CURRENT_STAGE,
    ax.tick_params(bottom=False, labelbottom=False,
                   left=False, labelleft=False)


fig = plt.figure(figsize=(12, 6))
sfs = fig.subfigures(1, 2)


sfs[0].suptitle("Fixed axes sizes, fixed paddings")
# Sizes are in inches.
horiz = [Size.Fixed(1.), Size.Fixed(.5), Size.Fixed(1.5), Size.Fixed(.5)]
vert = [Size.Fixed(1.5), Size.Fixed(.5), Size.Fixed(1.)]

rect = (0.1, 0.1, 0.8, 0.8)
# Divide the axes rectangle into a grid with sizes specified by horiz * vert.
div = Divider(sfs[0], rect, horiz, vert, aspect=False)

# The rect parameter will actually be ignored and overridden by axes_locator.
ax1 = sfs[0].add_axes(rect, axes_locator=div.new_locator(nx=0, ny=0))
label_axes(ax1, "nx=0, ny=0")
ax2 = sfs[0].add_axes(rect, axes_locator=div.new_locator(nx=0, ny=2))
label_axes(ax2, "nx=0, ny=2")
ax3 = sfs[0].add_axes(rect, axes_locator=div.new_locator(nx=2, ny=2))
label_axes(ax3, "nx=2, ny=2")
ax4 = sfs[0].add_axes(rect, axes_locator=div.new_locator(nx=2, nx1=4, ny=0))
label_axes(ax4, "nx=2, nx1=4, ny=0")


sfs[1].suptitle("Scalable axes sizes, fixed paddings")
# Fixed sizes are in inches, scaled sizes are relative.
horiz = [Size.Scaled(1.5), Size.Fixed(.5), Size.Scaled(1.), Size.Scaled(.5)]