Example #1
0
def _plot_2d_breakdowns(ax, seeds, seed_args):
    breakdowns = np.zeros((0, 3))
    ec_kwargs = {}
    for seed, args in zip(seeds, seed_args):
        breakdowns = np.concatenate((breakdowns, seed.breakdown))
        n_c = len(seed.breakdown)
        for key, val in args.items():
            val_list = ec_kwargs.get(key, [])
            val_list.extend(n_c * [val])
            ec_kwargs[key] = val_list
    d = 2 * breakdowns[:, -1]
    xy = breakdowns[:, :-1]
    a = np.full(len(breakdowns), 0)

    # abbreviate kwargs if all the same
    for key, val in ec_kwargs.items():
        v1 = val[0]
        same = True
        for v in val:
            same &= v == v1
        if same:
            ec_kwargs[key] = v1

    ec = collections.EllipseCollection(d,
                                       d,
                                       a,
                                       units='x',
                                       offsets=xy,
                                       transOffset=ax.transData,
                                       **ec_kwargs)
    ax.add_collection(ec)
    ax.autoscale_view()
Example #2
0
def ellipse_collection(ax, P):
    xy = np.array([p.x[::2].flatten() for p in P])
    sizes = np.array([p.a for p in P])
    coll = collections.EllipseCollection(sizes,
                                         sizes,
                                         np.zeros_like(sizes),
                                         offsets=xy,
                                         units='x',
                                         facecolors=[p.color for p in P],
                                         transOffset=ax.transData,
                                         alpha=0.7)
    return coll
Example #3
0
def test_size_in_xy():
    fig, ax = plt.subplots()

    widths, heights, angles = (10, 10), 10, 0
    widths = 10, 10
    coords = [(10, 10), (15, 15)]
    e = mcollections.EllipseCollection(
        widths, heights, angles, units='xy',
        offsets=coords, offset_transform=ax.transData)

    ax.add_collection(e)

    ax.set_xlim(0, 30)
    ax.set_ylim(0, 30)
Example #4
0
 def ellipse_collection(self, ax):
     "for matplotlib plotting"
     xz = self.x[:, [0, 2]]
     #xz = self.rz
     sizes = 2. * self.params.rMolecule * np.ones(self.N)
     colors = ["b"] * self.N
     coll = collections.EllipseCollection(sizes,
                                          sizes,
                                          np.zeros_like(sizes),
                                          offsets=xz,
                                          units="xy",
                                          facecolors=colors,
                                          transOffset=ax.transData,
                                          alpha=0.7)
     return coll
Example #5
0
    def __init__(self, fig, ax, configuration, anchors):
        self.fig = fig
        self.ax = ax
        self.conf = configuration
        self.anchors = anchors
        
        ax.set(title = "Particle filter state", xlabel = "$x$, meters", ylabel = "$y$, meters")

        conf = self.conf
        self.robot = Robot(conf['robot_start_x'], conf['robot_start_y'], conf['robot_start_theta'])
        self.particleFilter = ParticleFilter(
            conf['MIN_X'], conf['MAX_X'], 
            conf['MIN_Y'], conf['MAX_Y'], 
            conf['PARTICLES_NUM'])
        
        self.ax.set(aspect = "equal", xlim = (conf['MIN_X'], conf['MAX_X']), ylim=(conf['MIN_Y'], conf['MAX_Y']))

        normcolor = plt.Normalize(0.0, 0.01)
        self.particlesScatter = self.ax.scatter(
            [p.x for p in self.particleFilter.particles], [p.y for p in self.particleFilter.particles], 
            c=np.arange(conf['PARTICLES_NUM']), marker='.', alpha=0.5, cmap=plt.cm.rainbow, norm=normcolor, s=0.5,
            label='particles')
        cb = fig.colorbar(plt.cm.ScalarMappable(cmap=plt.cm.rainbow), ax = ax, shrink=0.8)
        cb.set_label('Relative particle weight')
        
        self.anchorsScatter = self.ax.scatter([a.x for a in anchors], [a.y for a in anchors], 
                                              color='red', marker='x', label='anchors')
        
        lines_coordinates = [[(0.0, 0.0), (0.0, 0.0)]]
        lc = mc.LineCollection(lines_coordinates, linewidths=1)
        self.lines = self.ax.add_collection(lc)
        
        self.positionEst, = self.ax.plot([0.0], [0.0], marker='x', markersize=9, color="green", alpha=0.98,
                                        label='Estimated position')
        self.positionTrue, = self.ax.plot([0.0], [0.0], marker='+', markersize=9, color="black",
                                        label='True position')
        
        self.text = ax.text(conf['MIN_X'] + (conf['MIN_X'] + conf['MAX_X']) * 0.5, 
                            conf['MIN_Y'] + (conf['MIN_Y'] + conf['MAX_Y']) * 0.05, "")


        centers = np.array([[a.x, a.y] for a in anchors])
        cl = mc.EllipseCollection([1.] * len(anchors), [1.] * len(anchors), [1.] * len(anchors), 
            offsets=centers, transOffset=ax.transData, units='xy', facecolors='none', color='black', alpha=0.5)
        self.circles = ax.add_collection(cl)
        self.circles.set_facecolor('none')
        
        self.ax.legend(loc = 'upper left')
Example #6
0
def test_EllipseCollection():
    # Test basic functionality
    fig, ax = plt.subplots()
    x = np.arange(4)
    y = np.arange(3)
    X, Y = np.meshgrid(x, y)
    XY = np.vstack((X.ravel(), Y.ravel())).T

    ww = X / x[-1]
    hh = Y / y[-1]
    aa = np.ones_like(ww) * 20  # first axis is 20 degrees CCW from x axis

    ec = mcollections.EllipseCollection(
        ww, hh, aa, units='x', offsets=XY, offset_transform=ax.transData,
        facecolors='none')
    ax.add_collection(ec)
    ax.autoscale_view()
Example #7
0
    def init_matplotlib(self):
        plt.ion()

        fig = plt.figure(figsize=(6, 6))
        ax = fig.add_subplot(111, aspect="equal")
        ax.set_xlim(0.0 - self.thickness, 1.0 + self.thickness)
        ax.set_ylim(0.0 - self.thickness, 1.0 + self.thickness)
        ax.set_xticks([])
        ax.set_yticks([])

        obstacles = self.geoms.geom_objs
        rects = []
        for i, obst in enumerate(obstacles):
            x, y = obst.placement.translation[:2]
            half_side = obst.geometry.halfSide
            w, h = 2 * half_side[:2]
            rects.append(
                patches.Rectangle(
                    (x - w / 2, y - h / 2),
                    w,
                    h  # (x,y)  # width  # height
                ))
        coll = collections.PatchCollection(rects, zorder=1)
        coll.set_alpha(0.6)
        ax.add_collection(coll)

        size = self.robot_props["dist_goal"]
        offsets = np.stack((self.state.q, self.goal_state.q), 0)[:, :2]
        sg = collections.EllipseCollection(
            widths=size,
            heights=size,
            facecolors=[(1, 0, 0, 0.8), (0, 1, 0, 0.8)],
            angles=0,
            units="xy",
            offsets=offsets,
            transOffset=ax.transData,
        )
        ax.add_collection(sg)

        plt.tight_layout()
        self.fig = fig
        self.ax = ax
Example #8
0
def addCircles(centers, radii, **kwargs):
    """Adds a set of circles to an already initialized figure.

    Parameters
    ----------
    centers: object
        Complex numpy array with the circle central coordinates. 
    radii: object
        Numpy array with the circle radii. 
    kwargs: collections.EllipseCollection properties
        Any additional property that should be passed to the ellipse collection.
         
    Returns
    -------
    object
        The circles ellipse collection. 

    """
    # Create the ellipse collection
    diameters = 2 * radii
    offsets = np.hstack(
        (centers.real[:, np.newaxis], centers.imag[:, np.newaxis]))
    angles = np.zeros(len(centers))
    params = {
        "offsets": offsets,
        "units": "xy",
        "transOffset": plt.gca().transData
    }
    params.update(kwargs)
    ellipseCollection = collections.EllipseCollection(diameters, diameters,
                                                      angles, **params)

    # Plot the ellipses in the current figure
    plt.gca().add_collection(ellipseCollection)

    return ellipseCollection
Example #9
0
    def plot_breakdown(self, index_by='seed', material=[], loc=0, **kwargs):
        """Plot the breakdowns of the seeds in seed list.

        This function plots the breakdowns of seeds contained in the seed list.
        In 2D, the breakdowns are grouped into matplotlib collections to reduce
        the computational load. In 3D, matplotlib does not have patches, so
        each breakdown is rendered as its own surface.

        Additional keyword arguments can be specified and passed through to
        matplotlib. These arguments should be either single values
        (e.g. ``edgecolors='k'``), or lists of values that have the same
        length as the seed list.

        Args:
            index_by (str): *(optional)* {'material' | 'seed'}
                Flag for indexing into the other arrays passed into the
                function. For example,
                ``plot(index_by='material', color=['blue', 'red'])`` will plot
                the seeds with ``phase`` equal to 0 in blue, and seeds with
                ``phase`` equal to 1 in red. Defaults to 'seed'.
            material (list): *(optional)* Names of material phases. One entry
                per material phase (the ``index_by`` argument is ignored).
                If this argument is set, a legend is added to the plot with
                one entry per material.
            loc (int or str): *(optional)* The location of the legend,
                if 'material' is specified. This argument is passed directly
                through to :func:`matplotlib.pyplot.legend`. Defaults to 0,
                which is 'best' in matplotlib.
            **kwargs: Keyword arguments to pass to matplotlib

        """
        seed_args = [{} for seed in self]
        for seed_num, seed in enumerate(self):
            phase_num = seed.phase
            for key, val in kwargs.items():
                if type(val) in (list, np.array):
                    if index_by == 'seed' and len(val) > seed_num:
                        seed_args[seed_num][key] = val[seed_num]
                    elif index_by == 'material' and len(val) > phase_num:
                        seed_args[seed_num][key] = val[phase_num]
                else:
                    seed_args[seed_num][key] = val

        n = self[0].geometry.n_dim
        if n == 2:
            ax = plt.gca()
        else:
            ax = plt.gcf().gca(projection=Axes3D.name)
        n_obj = _misc.ax_objects(ax)
        if n_obj > 0:
            xlim = ax.get_xlim()
            ylim = ax.get_ylim()
        else:
            xlim = [float('inf'), -float('inf')]
            ylim = [float('inf'), -float('inf')]

        if n == 3:
            if n_obj > 0:
                zlim = ax.get_zlim()
            else:
                zlim = [float('inf'), -float('inf')]

            for seed, args in zip(self, seed_args):
                seed.plot_breakdown(**args)

        elif n == 2:
            breakdowns = np.zeros((0, 3))
            ec_kwargs = {}
            for seed, args in zip(self, seed_args):
                breakdowns = np.concatenate((breakdowns, seed.breakdown))
                n_c = len(seed.breakdown)
                for key, val in args.items():
                    val_list = ec_kwargs.get(key, [])
                    val_list.extend(n_c * [val])
                    ec_kwargs[key] = val_list
            d = 2 * breakdowns[:, -1]
            xy = breakdowns[:, :-1]
            a = np.full(len(breakdowns), 0)

            # abbreviate kwargs if all the same
            for key, val in ec_kwargs.items():
                v1 = val[0]
                same = True
                for v in val:
                    same &= v == v1
                if same:
                    ec_kwargs[key] = v1

            ax = plt.gca()
            ec = collections.EllipseCollection(d,
                                               d,
                                               a,
                                               units='x',
                                               offsets=xy,
                                               transOffset=ax.transData,
                                               **ec_kwargs)
            ax.add_collection(ec)
            ax.autoscale_view()

        # Add legend
        if material:
            p_kwargs = [{'label': m} for m in material]
            if index_by == 'seed':
                for seed_kwargs, seed in zip(seed_args, self):
                    p = seed.phase
                    p_kwargs[p].update(seed_kwargs)
            else:
                for key, val in kwargs.items():
                    if type(val) in (list, np.array):
                        for i, elem in enumerate(val):
                            p_kwargs[i][key] = elem
                    else:
                        for i in range(len(p_kwargs)):
                            p_kwargs[i][key] = val

            # Replace plural keywords
            for p_kw in p_kwargs:
                for kw in _misc.mpl_plural_kwargs:
                    if kw in p_kw:
                        p_kw[kw[:-1]] = p_kw[kw]
                        del p_kw[kw]
            handles = [patches.Patch(**p_kw) for p_kw in p_kwargs]
            if n == 2:
                ax.legend(handles=handles, loc=loc)
            else:
                plt.gca().legend(handles=handles, loc=loc)

        # Adjust Axes
        seed_lims = [np.array(s.geometry.limits).flatten() for s in self]
        mins = np.array(seed_lims)[:, 0::2].min(axis=0)
        maxs = np.array(seed_lims)[:, 1::2].max(axis=0)
        xlim = (min(xlim[0], mins[0]), max(xlim[1], maxs[0]))
        ylim = (min(ylim[0], mins[1]), max(ylim[1], maxs[1]))
        if n == 2:
            plt.axis('square')
            ax.set_xlim(xlim)
            ax.set_ylim(ylim)
        if n == 3:
            zlim = (min(zlim[0], mins[2]), max(zlim[1], maxs[2]))
            ax.set_xlim(xlim)
            ax.set_ylim(ylim)
            ax.set_zlim(zlim)
            _misc.axisEqual3D(ax)
Example #10
0
    def plot(self, index_by='seed', material=[], loc=0, **kwargs):
        """Plot the seeds in the seed list.

        This function plots the seeds contained in the seed list.
        In 2D, the seeds are grouped into matplotlib collections to reduce
        the computational load. In 3D, matplotlib does not have patches, so
        each seed is rendered as its own surface.

        Additional keyword arguments can be specified and passed through to
        matplotlib. These arguments should be either single values
        (e.g. ``edgecolors='k'``), or lists of values that have the same
        length as the seed list.

        Args:
            index_by (str): *(optional)* {'material' | 'seed'}
                Flag for indexing into the other arrays passed into the
                function. For example,
                ``plot(index_by='material', color=['blue', 'red'])`` will plot
                the seeds with ``phase`` equal to 0 in blue, and seeds with
                ``phase`` equal to 1 in red. Defaults to 'seed'.
            material (list): *(optional)* Names of material phases. One entry
                per material phase (the ``index_by`` argument is ignored).
                If this argument is set, a legend is added to the plot with
                one entry per material.
            loc (int or str): *(optional)* The location of the legend,
                if 'material' is specified. This argument is passed directly
                through to :func:`matplotlib.pyplot.legend`. Defaults to 0,
                which is 'best' in matplotlib.
            **kwargs: Keyword arguments to pass to matplotlib

        """
        seed_args = [{} for seed in self]
        for seed_num, seed in enumerate(self):
            phase_num = seed.phase
            for key, val in kwargs.items():
                if type(val) in (list, np.array):
                    if index_by == 'seed' and len(val) > seed_num:
                        seed_args[seed_num][key] = val[seed_num]
                    elif index_by == 'material' and len(val) > phase_num:
                        seed_args[seed_num][key] = val[phase_num]
                else:
                    seed_args[seed_num][key] = val

        n = self[0].geometry.n_dim
        if n == 2:
            ax = plt.gca()
        else:
            ax = plt.gcf().gca(projection=Axes3D.name)
        n_obj = _misc.ax_objects(ax)
        if n_obj > 0:
            xlim = ax.get_xlim()
            ylim = ax.get_ylim()
        else:
            xlim = [float('inf'), -float('inf')]
            ylim = [float('inf'), -float('inf')]

        if n == 3:
            if n_obj > 0:
                zlim = ax.get_zlim()
            else:
                zlim = [float('inf'), -float('inf')]

            for seed, args in zip(self, seed_args):
                seed.plot(**args)

        elif n == 2:
            ellipse_data = {'w': [], 'h': [], 'a': [], 'xy': []}
            ec_kwargs = {}

            rect_data = {'xy': [], 'w': [], 'h': [], 'angle': []}
            rect_kwargs = {}

            pc_verts = []
            pc_kwargs = {}
            for seed, args in zip(self, seed_args):
                geom_name = type(seed.geometry).__name__.lower().strip()
                if geom_name == 'ellipse':
                    a, b = seed.geometry.axes
                    cen = np.array(seed.position)
                    t = seed.geometry.angle_deg

                    ellipse_data['w'].append(2 * a)
                    ellipse_data['h'].append(2 * b)
                    ellipse_data['a'].append(t)
                    ellipse_data['xy'].append(cen)

                    for key, val in args.items():
                        val_list = ec_kwargs.get(key, [])
                        val_list.append(val)
                        ec_kwargs[key] = val_list

                elif geom_name == 'circle':
                    diam = seed.geometry.diameter
                    cen = np.array(seed.position)

                    ellipse_data['w'].append(diam)
                    ellipse_data['h'].append(diam)
                    ellipse_data['a'].append(0)
                    ellipse_data['xy'].append(cen)

                    for key, val in args.items():
                        val_list = ec_kwargs.get(key, [])
                        val_list.append(val)
                        ec_kwargs[key] = val_list

                elif geom_name in ['rectangle', 'square']:
                    w, h = seed.geometry.side_lengths
                    corner = seed.geometry.corner
                    t = seed.geometry.angle_deg

                    rect_data['w'].append(w)
                    rect_data['h'].append(h)
                    rect_data['angle'].append(t)
                    rect_data['xy'].append(corner)

                    for key, val in args.items():
                        val_list = rect_kwargs.get(key, [])
                        val_list.append(val)
                        rect_kwargs[key] = val_list

                elif geom_name == 'curl':
                    xy = seed.geometry.plot_xy()
                    pc_verts.append(xy)
                    for key, val in args.items():
                        val_list = pc_kwargs.get(key, [])
                        val_list.append(val)
                        pc_kwargs[key] = val_list

                elif geom_name == 'nonetype':
                    pass

                else:
                    e_str = 'Cannot plot groups of ' + geom_name
                    e_str += ' yet.'
                    raise NotImplementedError(e_str)

            # abbreviate kwargs if all the same
            for key, val in ec_kwargs.items():
                v1 = val[0]
                same = True
                for v in val:
                    same &= v == v1
                if same:
                    ec_kwargs[key] = v1

            for key, val in pc_kwargs.items():
                v1 = val[0]
                same = True
                for v in val:
                    same &= v == v1
                if same:
                    pc_kwargs[key] = v1

            # Plot Circles and Ellipses
            ax = plt.gca()

            w = np.array(ellipse_data['w'])
            h = np.array(ellipse_data['h'])
            a = np.array(ellipse_data['a'])
            xy = np.array(ellipse_data['xy'])
            ec = collections.EllipseCollection(w,
                                               h,
                                               a,
                                               units='x',
                                               offsets=xy,
                                               transOffset=ax.transData,
                                               **ec_kwargs)
            ax.add_collection(ec)

            # Plot Rectangles
            rects = [
                Rectangle(xy=xyi, width=wi, height=hi, angle=ai)
                for xyi, wi, hi, ai in zip(rect_data['xy'], rect_data['w'],
                                           rect_data['h'], rect_data['angle'])
            ]
            rc = collections.PatchCollection(rects, False, **rect_kwargs)
            ax.add_collection(rc)

            # Plot Polygons
            pc = collections.PolyCollection(pc_verts, **pc_kwargs)
            ax.add_collection(pc)

            ax.autoscale_view()

        # Add legend
        if material:
            p_kwargs = [{'label': m} for m in material]
            if index_by == 'seed':
                for seed_kwargs, seed in zip(seed_args, self):
                    p = seed.phase
                    p_kwargs[p].update(seed_kwargs)
            else:
                for key, val in kwargs.items():
                    if type(val) in (list, np.array):
                        for i, elem in enumerate(val):
                            p_kwargs[i][key] = elem
                    else:
                        for i in range(len(p_kwargs)):
                            p_kwargs[i][key] = val

            # Replace plural keywords
            for p_kw in p_kwargs:
                for kw in _misc.mpl_plural_kwargs:
                    if kw in p_kw:
                        p_kw[kw[:-1]] = p_kw[kw]
                        del p_kw[kw]
            handles = [patches.Patch(**p_kw) for p_kw in p_kwargs]
            ax.legend(handles=handles, loc=loc)

        # Adjust Axes
        seed_lims = [np.array(s.geometry.limits).flatten() for s in self]
        mins = np.array(seed_lims)[:, 0::2].min(axis=0)
        maxs = np.array(seed_lims)[:, 1::2].max(axis=0)
        xlim = (min(xlim[0], mins[0]), max(xlim[1], maxs[0]))
        ylim = (min(ylim[0], mins[1]), max(ylim[1], maxs[1]))
        if n == 2:
            plt.axis('square')
            ax.set_xlim(xlim)
            ax.set_ylim(ylim)
        if n == 3:
            zlim = (min(zlim[0], mins[2]), max(zlim[1], maxs[2]))
            ax.set_xlim(xlim)
            ax.set_ylim(ylim)
            ax.set_zlim(zlim)
            _misc.axisEqual3D(ax)
Example #11
0
def _plot_2d(ax, seeds, seed_args):
    ellipse_data = {'w': [], 'h': [], 'a': [], 'xy': []}
    ec_kwargs = {}

    rect_data = []
    rect_kwargs = {}
    for seed, args in zip(seeds, seed_args):
        geom_name = type(seed.geometry).__name__.lower().strip()
        if geom_name == 'ellipse':
            ellipse_data['w'].append(2 * seed.geometry.a)
            ellipse_data['h'].append(2 * seed.geometry.b)
            ellipse_data['a'].append(seed.geometry.angle_deg)
            ellipse_data['xy'].append(np.array(seed.position))

            for key, val in args.items():
                val_list = ec_kwargs.get(key, []) + [val]
                ec_kwargs[key] = val_list

        elif geom_name == 'circle':
            ellipse_data['w'].append(seed.geometry.diameter)
            ellipse_data['h'].append(seed.geometry.diameter)
            ellipse_data['a'].append(0)
            ellipse_data['xy'].append(np.array(seed.position))

            for key, val in args.items():
                val_list = ec_kwargs.get(key, []) + [val]
                ec_kwargs[key] = val_list

        elif geom_name in ['rectangle', 'square']:
            w, h = seed.geometry.side_lengths
            corner = seed.geometry.corner
            t = seed.geometry.angle_deg
            rect_inputs = {'width': w, 'height': h, 'angle': t, 'xy': corner}
            rect_data.append(rect_inputs)

            for key, val in args.items():
                val_list = rect_kwargs.get(key, []) + [val]
                rect_kwargs[key] = val_list

        elif geom_name == 'nonetype':
            pass

        else:
            e_str = 'Cannot plot groups of ' + geom_name + ' yet.'
            raise NotImplementedError(e_str)

    # abbreviate kwargs if all the same
    for key, val in ec_kwargs.items():
        v1 = val[0]
        same = True
        for v in val:
            same &= v == v1
        if same:
            ec_kwargs[key] = v1

    # Plot Circles and Ellipses
    w = np.array(ellipse_data['w'])
    h = np.array(ellipse_data['h'])
    a = np.array(ellipse_data['a'])
    xy = np.array(ellipse_data['xy'])
    ec = collections.EllipseCollection(w,
                                       h,
                                       a,
                                       units='x',
                                       offsets=xy,
                                       transOffset=ax.transData,
                                       **ec_kwargs)
    ax.add_collection(ec)

    # Plot Rectangles
    rects = [Rectangle(**rect_inps) for rect_inps in rect_data]
    rc = collections.PatchCollection(rects, False, **rect_kwargs)
    ax.add_collection(rc)

    ax.autoscale_view()
Example #12
0
ax.add_patch(P.Circle((xc, yc), rout, **patch_args))
ax.subfigure_label('(a)')
fig.tight_layout()
fig.nice_colorbar(im, ticks=[])

ax = fig.add_subplot(1, 2, 2, polar=True, frame_on=False)
ellipse_args = {
    'units': 'xy',
    'facecolors': 'none',
    'linewidth': 0.5,
    'transOffset': ax.transData
}
ec_RHCP = collections.EllipseCollection(
    widths=widths[rhcp_mask],
    heights=heights[rhcp_mask],
    angles=angles[rhcp_mask],
    edgecolors=tango.skyblue3,
    offsets=offsets[rhcp_mask],
    **ellipse_args)
ec_LHCP = collections.EllipseCollection(
    widths=widths[lhcp_mask],
    heights=heights[lhcp_mask],
    angles=angles[lhcp_mask],
    edgecolors=tango.scarletred3,
    offsets=offsets[lhcp_mask],
    **ellipse_args)
ec_lin = collections.EllipseCollection(
    widths=widths[lin_mask],
    heights=heights[lin_mask],
    angles=angles[lin_mask],
    edgecolors='black',
Example #13
0
    def __init__(self,x,y, s=None, linewidths=None, values=None, cmap=None, norm=None, colors=None, edgecolors=None, alphas=1.0, zorder=None, transform=mtransforms.IdentityTransform(), dpi=72):
        assert len(x.shape) == 1
        assert len(y.shape) == 1
        assert x.shape == y.shape
        self._npts = x.shape[0]
        ref_colour_nitems = None
        # == colour composition or colour mapping == #
        if values is None or cmap is None:
            # use colors as facecolors - check sizes
            if colors is not None:
                assert isinstance(colors, np.ndarray)
                if len(colors.shape) > 1:
                    assert x.shape[0] == colors.shape[0]
                color_dims = colors.shape[0] if len(colors.shape) == 1 else colors.shape[1]
                if color_dims == 3:  # RGB - check and merge with alpha(s)
                    if len(colors.shape) > 1:
                        alpha_array = alphas if isinstance(alphas, np.ndarray) else np.ones(colors.shape[0], dtype=np.float32) * alphas
                        colours = np.column_stack([colors, alpha_array])
                    else:
                        colours = np.concatenate([colors, alphas])
                else:
                    assert color_dims == 4
                    colours = colors
                ref_colour_nitems = -1
                if len(colours.shape) > 1:
                    ref_colour_nitems = colours.shape[0]
                self._facecolors = colours
            if edgecolors is not None:
                assert isinstance(edgecolors, np.ndarray)
                if len(edgecolors.shape) > 1:
                    assert x.shape[0] == edgecolors.shape[0]
                color_dims = edgecolors.shape[0] if len(edgecolors.shape) == 1 else edgecolors.shape[1]
                if color_dims == 3:  # RGB - check and merge with alpha(s)
                    if len(edgecolors.shape) > 1:
                        ecolours = np.column_stack([edgecolors, np.ones(colors.shape[0], dtype=np.float32)])
                    else:
                        ecolours = np.concatenate([edgecolors, alphas])
                else:
                    assert color_dims == 4
                    ecolours = edgecolors
                self._edgecolors = ecolours
                assert self._facecolors.shape == self._edgecolors.shape
            else:
                raise ValueError("No color information available for scatter plot circles.")
        else:  # use the colour mapping - no face or edge colors
            self._facecolors = None
            self._edgecolors = None
            if edgecolors is not None:
                self._edgecolors = edgecolors
            self._cmap = cmap
            if norm is not None and not isinstance(norm, mcolors.Normalize):
                msg = "'norm' must be an instance of 'mcolors.Normalize'"
                raise ValueError(msg)
            self._norm = norm
            self._values = values
            assert x.shape[0] == values.shape[0]
            ref_colour_nitems = self._values.shape[0]
        if alphas not in [None, False] and type(alphas) not in [list, np.ndarray]:
            self._uniform_alpha = alphas

        self._linewidths = linewidths
        self._create_path_collection()
        if ref_colour_nitems > 0 and (isinstance(self._linewidths, np.ndarray) or type(self._linewidths) in [list, ]):
            assert self._linewidths.shape[0] == ref_colour_nitems
        else:
            assert type(self._linewidths) in [np.float, np.float32, np.float64, float]
        self._markersizes = s if s is not None else 1.0
        if ref_colour_nitems > 0 and (isinstance(self._markersizes, np.ndarray) or type(self._markersizes) in [list, ]):
            assert self._markersizes.shape[0] == ref_colour_nitems
        else:
            assert type(self._markersizes) in [np.float, np.float32, np.float64, float]
            self._markersizes = np.ones(self._npts, dtype=np.float32) * self._markersizes
        # self._offsets = np.c_[x, y].reshape(-1, 1, 2)
        self._offsets = np.column_stack((x, y))  # .reshape(-1, 1, 2)
        self._plotorder = np.arange(0, x.shape[0])
        # self._offsets = np.concatenate((x, y), axis=1).reshape(-1, 1, 2)
        self._zorder = zorder
        self._transform = transform
        self._dpi = dpi

        # self._collection = mcoll.PathCollection(
        #     (self._markerpath,), self._markersizes,
        #     cmap=self._cmap,
        #     norm=self._norm,
        #     facecolors=self._facecolors,
        #     edgecolors=self._edgecolors,
        #     linewidths=self._linewidths,
        #     offsets=self._offsets,
        #     transOffset=self._transform,
        #     alpha=self._uniform_alpha,
        #     zorder=self._zorder
        # )
        # sizes = np.array([self._markersizes,] * self._npts)
        sizes = self._markersizes
        self._collection = mcoll.EllipseCollection(
            widths=sizes,
            heights=sizes,
            angles=np.zeros(self._npts),
            units='x',
            cmap=self._cmap,
            norm=self._norm,
            facecolors=self._facecolors,
            edgecolors=self._edgecolors,
            linewidths=self._linewidths,
            offsets=self._offsets,
            transOffset=self._transform,
            alpha=self._uniform_alpha,
            zorder=self._zorder
        )
        print(self._collection.get_offsets())

        if self._facecolors is None and self._values is not None and self._cmap is not None and self._norm is not None:
            self.update_plotorder()
            self._collection.set_array(np.asarray(self._values))
Example #14
0
    def __init__(self, fig, ax, landmarksTruePositions, robot, ekfSlam, extendPlot, controller):
        self.fig = fig
        self.ax = ax[0]
        self.landmarks = landmarksTruePositions
        self.robot = robot
        self.ekfSlam = ekfSlam

        ax[0].set(title = "EKF State", xlabel = "$x$, meters", ylabel = "$y$, meters")
        ax[1].set(title = "Covariance matrix", xlabel = "$\Sigma$ column $j$", ylabel = "$\Sigma$ row $i$")

        self.ax.set(aspect = "equal", 
            xlim = (landmarksTruePositions['x'].min() - extendPlot, landmarksTruePositions['x'].max() + extendPlot), 
            ylim = (landmarksTruePositions['y'].min() - extendPlot, landmarksTruePositions['y'].max() + extendPlot) )

        self.landmarksTruePositionsScatter = self.ax.scatter(
            landmarksTruePositions['x'], landmarksTruePositions['y'],
            color='black', marker='x', label = 'true landmark positions', zorder=3, s=150)

        self.positionTrue = self.ax.quiver([0.0], [0.0], [1.0], [0.0], 
            pivot='mid', color='black', units='inches', scale=4.0, label='True position')

        self.positionEst = self.ax.quiver([0.0], [0.0], [1.0], [0.0], 
            pivot='mid', color='violet', units='inches', scale=4.0, label='Estimated position')

        self.distanceAndBearingLines = self.ax.add_collection(
            mc.LineCollection([[(0.0, 0.0), (0.0, 0.0)]], linewidths=2, alpha=0.7, linestyles='dashed',
                              colors = cm.jet(np.linspace(0, 1, len(self.landmarks)))))

        self.landmarksEstimatedPositionsScatter = self.ax.scatter(
            [], [],
            color='magenta', marker='o', label = 'estimated landmark positions')

        data = np.zeros(1000)
        data[:] = np.nan
        self.landmarkMeasurementsScatter = self.ax.scatter(
            data, data,
            marker='.', alpha = 0.4, zorder=0, s=20.0, edgecolor='none', c=np.zeros((1000, 4)),
        )
        
        self.ax.legend(loc = 'upper left')

        self.im = ax[1].imshow(self.ekfSlam.Sigma, interpolation='none', vmin=-1, vmax=1, cmap=plt.cm.PiYG)
        fig.colorbar(self.im, ax=ax[1], shrink=0.7)

        self.localcm = cm.jet(np.linspace(0, 1, len(self.landmarks)))
        self.localcm[:,3] = 0.4

        self.text = self.ax.text(self.ax.get_xlim()[0] + (self.ax.get_xlim()[0] + self.ax.get_xlim()[1]) * 0.5,
                            self.ax.get_ylim()[0] + (self.ax.get_ylim()[0] + self.ax.get_ylim()[1]) * 0.05, "", fontsize=15)

        ellipses = mc.EllipseCollection(self.landmarks['x'], self.landmarks['y'], [0.0] * len(self.landmarks), 
            offsets = np.vstack((self.landmarks['x'], self.landmarks['y'])).T, 
            transOffset = self.ax.transData, units='xy', facecolors='none', edgecolors=cm.jet(np.linspace(0, 1, len(self.landmarks))), 
            alpha=0.95)
        self.confidenceEllipses = self.ax.add_collection(ellipses)
        self.confidenceEllipses.set_facecolor('none')

        self.positionConfidenceEllipse = Ellipse((0.0, 0.0), 0.0, 0.0, 0.0, edgecolor='magenta', facecolor='none')
        self.ax.add_patch(self.positionConfidenceEllipse)

        self.i = 0

        self.controller = controller

        plt.tight_layout()
Example #15
0
def run_script(args):

    matplotlib.interactive(False)

    args.plot_type = 'dashboard'
    Rprop0 = args.Rock0

    Rprop1 = args.Rock1

    theta = np.arange(0, 90)

    vp0, vs0, rho0 = make_normal_dist(Rprop0, args.iterations)
    vp1, vs1, rho1 = make_normal_dist(Rprop1, args.iterations)
    reflect = []

    hist_titles = [[r'$V_\mathrm{P}$', r'$m/s$'],
                   [r'$V_\mathrm{S}$', r'$m/s$'], [r'$\rho$', r'$kg / m^3$']]
    nbins = 15

    vp_lim = (np.amin(
        (Rprop1.vp - (3. * Rprop1.vp_sig), Rprop0.vp - (3. * Rprop1.vp_sig))),
              np.amax((Rprop1.vp + (3. * Rprop1.vp_sig),
                       Rprop0.vp + (3. * Rprop1.vp_sig))))

    vs_lim = (np.amin(
        (Rprop1.vs - (3. * Rprop1.vs_sig), Rprop0.vs - (3. * Rprop1.vs_sig))),
              np.amax((Rprop1.vs + (3. * Rprop1.vs_sig),
                       Rprop0.vs + (3. * Rprop1.vs_sig))))

    rho_lim = (np.amin((Rprop1.rho - (3. * Rprop1.rho_sig),
                        Rprop0.rho - (3. * Rprop1.rho_sig))),
               np.amax((Rprop1.rho + (3. * Rprop1.rho_sig),
                        Rprop0.rho + (3. * Rprop1.rho_sig))))

    limits = np.array([[vp_lim, vs_lim, rho_lim], [vp_lim, vs_lim, rho_lim]])

    for i in range(args.iterations):

        reflect.append(
            args.reflectivity_method(vp0[i], vs0[i], rho0[i], vp1[i], vs1[i],
                                     rho1[i], theta))
    reflect = np.array(reflect)
    reflect = np.nan_to_num(reflect)
    #temp = np.concatenate( (vp0, rho0, vs0, vp1, rho1, vs1,), axis=0)

    temp = np.concatenate((vp0, vs0, rho0, vp1, vs1, rho1), axis=0)

    prop_samples = np.reshape(temp, (6, args.iterations))
    ave_reflect = np.mean(reflect, axis=0)
    nbins = 15
    # DO PLOTTING

    plt.figure(figsize=(5, 13))
    plt.subplots_adjust(bottom=0.1, left=0.1, top=1, right=0.9)
    plt.hold(True)
    if args.plot_type == 'dashboard':
        G = matplotlib.gridspec.GridSpec(9, 2, hspace=0.5)
        shift = 3
    else:
        G = matplotlib.gridspec.GridSpec(2, 6)
        shift = 0

    # histogram plots (ax_3, ax_4, ax_5, ax_6, ax_7, ax_8)
    hist_max = 0

    for k in np.arange(len(prop_samples)):

        # find the max bar height of the histogram for scaling the plots
        hist_max = max(hist_max,
                       max(np.histogram(prop_samples[k], density=True)[0]))

    for j in np.arange(2):

        upper_color = 'blue'  #color of upper histogram
        lower_color = 'green'  #color of lower histogram

        for i in np.arange(3):

            plt.subplot(G[3 + i + shift, 0])

            plt.hist(prop_samples[i],
                     nbins,
                     facecolor=upper_color,
                     histtype='stepfilled',
                     alpha=0.25,
                     normed=True)
            plt.hist(prop_samples[i + (3)],
                     nbins,
                     facecolor=lower_color,
                     histtype='stepfilled',
                     alpha=0.25,
                     normed=True)
            temp = plt.gca()

            # Annotation and making it look nice
            plt.axis(
                [limits[j][i][0], limits[j][i][1],
                 temp.axis()[2], hist_max])
            plt.yticks([])
            plt.xticks(rotation=90, horizontalalignment='left')
            ax = plt.gca()
            ax.spines['right'].set_color('none')
            ax.spines['left'].set_color('none')
            ax.spines['top'].set_color('none')
            ax.spines['bottom'].set_alpha(0.5)

            for label in ax.get_xticklabels() + ax.get_yticklabels():
                label.set_fontsize(6)
                label.set_alpha(0.5)

            for tick in ax.xaxis.get_major_ticks():
                tick.tick1On = True
                tick.tick2On = False

            # upper text label

            mean_props = [[Rprop0.vp, Rprop1.vp], [Rprop0.vs, Rprop1.vs],
                          [Rprop0.rho, Rprop1.rho]]

            which_label = ['upper', 'lower']

            # Main label
            ax.text(x=limits[0, i, 1],
                    y=hist_max * 0.5,
                    s=hist_titles[i][0],
                    color='black',
                    fontsize=14,
                    alpha=0.75,
                    horizontalalignment='left',
                    verticalalignment='center')
            # Label for units
            ax.text(x=limits[0, i, 1],
                    y=hist_max * 0.25,
                    s=hist_titles[i][1],
                    color='black',
                    fontsize=10,
                    alpha=0.75,
                    horizontalalignment='left',
                    verticalalignment='center')

            ax.text(
                x=float(mean_props[i][0]),
                y=hist_max / 5.0,
                s=which_label[0],
                alpha=0.75,
                color=upper_color,
                fontsize='9',
                horizontalalignment='center',
                verticalalignment='center',
            )

            #lower text label
            ax.text(x=float(mean_props[i][1]),
                    y=hist_max / 5.0,
                    s=which_label[1],
                    alpha=0.75,
                    color=lower_color,
                    fontsize='9',
                    horizontalalignment='center',
                    verticalalignment='center')
    #
    # ax_1 the AVO plot
    #
    plt.subplot(G[0:3, :])
    plt.hold(True)
    critical_angles = []
    for i in range(args.iterations - 1):
        # Do the AVO template as an underlay
        # HERE

        # Do the plots --> This step might not need to be in a loop
        plt.plot(theta,
                 reflect[i],
                 color='grey',
                 lw=1.0,
                 alpha=np.min((30. / args.iterations, 0.08)))
        if vp1[i] > vp0[i]:
            theta_crit = arcsin(vp0[i] / vp1[i]) * 180 / np.pi
            plt.axvline(x=theta_crit,
                        color='black',
                        lw=1.0,
                        alpha=np.min((30. / args.iterations, 0.5)))
            critical_angles.append(theta_crit)

    if len(critical_angles) > 0:
        critical_angle = np.mean(critical_angles)
    else:
        critical_angle = 'N/A'

    plt.plot(theta, ave_reflect, color='black', alpha=0.5, lw=1.5)
    plt.grid()

    # Annotation and making it look nice
    ax = plt.gca()
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')
    ax.xaxis.set_ticks_position('bottom')
    ax.spines['bottom'].set_position(('data', 0))
    ax.spines['bottom'].set_alpha(0.5)
    ax.yaxis.set_ticks_position('left')
    ax.spines['left'].set_position(('data', 0))
    ax.spines['left'].set_alpha(0.5)

    for label in ax.get_xticklabels() + ax.get_yticklabels():
        label.set_fontsize(6)
        label.set_alpha(0.5)

    plt.grid()
    plt.ylim((-.5, .5))
    ax.text(0.95,
            0.45,
            'angle',
            verticalalignment='top',
            horizontalalignment='right',
            transform=ax.transAxes,
            color='black',
            fontsize=8,
            alpha=0.5)
    ax.text(0.05,
            0.95,
            'amplitude',
            verticalalignment='top',
            horizontalalignment='right',
            transform=ax.transAxes,
            rotation=90,
            color='black',
            fontsize=8,
            alpha=0.5)

    #
    # Patches for the Background template AVO plot STARTS here
    #

    a1 = 0.10  # transparency for AVO background template patches
    rangex = 90
    band = 0.04  # thickness of Class 2 band
    # CLASS 1

    Path1 = mpath.Path
    path_data1 = [
        (Path1.MOVETO, (rangex * 0, 0.04)),
        (Path1.CURVE4, (rangex * 0.4, 0.05)),
        (Path1.CURVE4, (rangex * 0.6, -0.015)),
        (Path1.CURVE4, (rangex * 1.0, -band)),
        (Path1.LINETO, (rangex * 1.0, 1.0)),
        (Path1.LINETO, (rangex * 0.0, 1.0)),
        (Path1.CLOSEPOLY, (rangex * 0.0, 1.0)),
    ]
    codes1, verts1 = zip(*path_data1)
    path1 = mpath.Path(verts1, codes1)
    patch1 = mpatches.PathPatch(path1, facecolor='r', alpha=a1, ec='none')
    ax.add_patch(patch1)

    # plot control points and connecting lines
    x1, y1 = zip(*path1.vertices)
    #line1, = ax.plot(x1, y1, 'go-')

    # CLASS 2p

    Path2P = mpath.Path
    path_data2P = [
        (Path2P.MOVETO, (rangex * 0, band)),
        (Path2P.CURVE4, (rangex * 0.4, 0.05)),
        (Path2P.CURVE4, (rangex * 0.6, -0.015)),
        (Path2P.CURVE4, (rangex * 1.0, -band)),
        (Path2P.LINETO, (rangex * 1.0, -(band + band))),
        (Path2P.CURVE4, (rangex * 0.6, -(0.015 + band))),
        (Path2P.CURVE4, (rangex * 0.4, 0.05 - band)),
        (Path2P.CURVE4, (rangex * 0.0, 0.0)),
        (Path2P.CLOSEPOLY, (rangex * 0.0, 0.0)),
    ]
    codes2P, verts2P = zip(*path_data2P)
    path2P = mpath.Path(verts2P, codes2P)
    patch2P = mpatches.PathPatch(path2P,
                                 facecolor='yellow',
                                 alpha=a1,
                                 ec='none')
    ax.add_patch(patch2P)

    # plot control points and connecting lines
    x2, y2 = zip(*path2P.vertices)
    #line2, = ax.plot(x2, y2, 'ro-')

    # CLASS 2

    Path2 = mpath.Path
    path_data2 = [
        (Path2.MOVETO, (rangex * 0.0, 0.0)),
        (Path2.CURVE4, (rangex * 0.4, 0.05 - band)),
        (Path2.CURVE4, (rangex * 0.6, -(0.015 + band))),
        (Path2.CURVE4, (rangex * 1.0, -(band + band))),
        (Path2.LINETO, (rangex * 1.0, -(3 * band))),
        (Path2.CURVE4, (rangex * 0.6, -(0.015 + 2 * band))),
        (Path2.CURVE4, (rangex * 0.4, 0.05 - (0.0 + 2 * band))),
        (Path2.CURVE4, (rangex * 0.0, -band)),
        (Path2.CLOSEPOLY, (rangex * 0.0, 0.0)),
    ]
    codes2, verts2 = zip(*path_data2)
    path2 = mpath.Path(verts2, codes2)
    patch2 = mpatches.PathPatch(path2, facecolor='green', alpha=a1, ec='none')
    ax.add_patch(patch2)

    # plot control points and connecting lines
    x2, y2 = zip(*path2.vertices)

    #line2, = ax.plot(x2, y2, 'ro-')

    # CLASS 3
    Path3 = mpath.Path
    path_data3 = [
        (Path3.MOVETO, (rangex * 0.0, -band)),
        (Path3.CURVE4, (rangex * 0.4, 0.05 - (0.0 + 2 * band))),
        (Path3.CURVE4, (rangex * 0.6, -(0.015 + 2 * band))),
        (Path3.CURVE4, (rangex * 1.0, -(3 * band))),
        (Path3.LINETO, (rangex * 1.0, -1.0)),
        (Path3.LINETO, (rangex * 0.0, -1.0)),
        (Path3.CLOSEPOLY, (rangex * 0.0, -1.0)),
    ]
    codes3, verts3 = zip(*path_data3)
    path3 = mpath.Path(verts3, codes3)
    patch3 = mpatches.PathPatch(path3, facecolor='blue', alpha=a1, ec='none')
    ax.add_patch(patch3)

    # plot control points and connecting lines
    x3, y3 = zip(*path3.vertices)
    #line2, = ax.plot(x2, y2, 'ro-')

    ax.grid()

    ax.text(0.98,
            0.98,
            'Amplitude vs angle',
            verticalalignment='top',
            horizontalalignment='right',
            transform=ax.transAxes,
            color='black',
            fontsize=9,
            fontweight='bold',
            alpha=0.5)

    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')
    ax.xaxis.set_ticks_position('bottom')
    ax.spines['bottom'].set_position(('data', 0))
    ax.yaxis.set_ticks_position('left')
    ax.spines['left'].set_position(('data', 0))

    for label in ax.get_xticklabels() + ax.get_yticklabels():
        label.set_fontsize(8)
        label.set_alpha(0.5)

    plt.grid()

    # Class 1 label

    # y-values for class labels 1,2p, 2, 3, and 4 respectively
    ylabelcntrs = [0.35, 0.025, -0.025, -0.4, -0.2]
    xctrs = 10

    fs = 10  # fontsize

    a2 = 0.4  # transparency value for Gradient vs Intercept text

    ax.text(xctrs,
            ylabelcntrs[0],
            'CLASS 1',
            verticalalignment='center',
            horizontalalignment='left',
            color='red',
            fontsize=fs,
            fontweight='bold',
            alpha=a2)

    # Class 2p label
    ax.text(xctrs,
            ylabelcntrs[1],
            'CLASS 2p',
            verticalalignment='center',
            horizontalalignment='left',
            rotation=-3,
            color='#EEC900',
            fontsize=fs,
            fontweight='bold',
            alpha=a2 * 1.5)

    # Class 2 label
    ax.text(xctrs,
            ylabelcntrs[2],
            'CLASS 2',
            verticalalignment='center',
            horizontalalignment='left',
            rotation=-3,
            color='green',
            fontsize=fs,
            fontweight='bold',
            alpha=a2)

    # Class 3 label
    ax.text(xctrs,
            ylabelcntrs[3],
            'CLASS 3',
            verticalalignment='center',
            horizontalalignment='left',
            rotation=-15,
            color='blue',
            fontsize=fs,
            fontweight='bold',
            alpha=a2)

    # Class 4 label
    ax.text(xctrs,
            ylabelcntrs[4],
            'CLASS 4',
            verticalalignment='center',
            horizontalalignment='left',
            rotation=15,
            color='#B048B5',
            fontsize=fs,
            fontweight='bold',
            alpha=a2)
    #
    # Patches for background template AVO plot ENDS here
    #

    # ax_2 the AB plot
    plt.subplot(G[0 + shift:3 + shift, :])
    plt.hold(True)

    max_ang = args.max_angle  # Max ang for computing gradient

    for i in range(args.iterations - 1):

        plt.scatter(reflect[i, 0], (reflect[i, max_ang] - reflect[i, 0]),
                    color='grey',
                    s=20,
                    alpha=np.max((30. / args.iterations, 0.2)))

    # Plot the average of the dots
    plt.scatter(ave_reflect[0],
                ave_reflect[max_ang] - ave_reflect[0],
                color='black',
                s=40,
                alpha=0.5)

    # Annotation and making it nice
    plt.xticks([]), plt.yticks([])

    ax = plt.gca()
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')
    ax.xaxis.set_ticks_position('bottom')
    ax.spines['bottom'].set_position(('data', 0))
    ax.spines['bottom'].set_alpha(0.5)
    ax.yaxis.set_ticks_position('left')
    ax.spines['left'].set_position(('data', 0))
    ax.spines['left'].set_alpha(0.5)

    plt.grid()

    # axis limits

    ylimits = (np.amin((-.3, np.nanmin(reflect[:, 50] - reflect[:, 0]))),
               np.amax((.3, np.nanmax(reflect[:, 50] - reflect[:, 0]))))
    xlimits = (np.amin(
        (-.3, np.nanmin(reflect[:,
                                0]))), np.amax((.3, np.nanmax(reflect[:, 0]))))

    plt.ylim(ylimits)

    plt.xlim(xlimits)

    # axis labels

    ax.text(
        xlimits[1] - 0.05,
        0.025,
        'intercept',
        verticalalignment='center',
        horizontalalignment='right',
        #transform=ax.transAxes,
        color='black',
        fontsize=8,
        alpha=0.5)

    ax.text(
        0.025,
        ylimits[1] - 0.05,
        'gradient',
        rotation=90,
        verticalalignment='top',
        horizontalalignment='center',
        #transform=ax.transAxes,
        color='black',
        fontsize=8,
        alpha=0.5)
    #
    # Patches for background Gradient vs Intercept template STARTS here
    #

    x = np.arange(xlimits[0], xlimits[1], 0.01)
    y = np.arange(ylimits[0], ylimits[1], 0.01)

    s0 = -x

    shift2 = 0.04  #width for class2 width in plot

    height_ellipse = 0.05
    width_ellipse = 3.0

    # Plot background trend (diagonal line)
    ax.plot(x, s0, color='black', alpha=a1)

    # add a rectangle for class 2 neg
    lowleft2 = (-shift2, -1.0)

    class2neg = mpatches.Rectangle(lowleft2,
                                   width=abs(lowleft2[0]),
                                   height=1.0,
                                   color='green',
                                   alpha=a1,
                                   ec="white",
                                   lw=4)
    ax.add_patch(class2neg)

    # add a rectange for class 2 pos
    lowleft2pos = (0.0, 0.0)
    class2pos = mpatches.Rectangle(lowleft2pos,
                                   width=abs(lowleft2[0]),
                                   height=1.0,
                                   color='green',
                                   alpha=a1,
                                   ec="white",
                                   lw=4)
    ax.add_patch(class2pos)

    # add a rectange for class 2p pos
    lowleft2Ppos = (-shift2, 0.0)
    class2Ppos = mpatches.Rectangle(lowleft2Ppos,
                                    width=abs(lowleft2[0]),
                                    height=1.0,
                                    color='yellow',
                                    alpha=a1,
                                    ec="white",
                                    lw=4)
    ax.add_patch(class2Ppos)

    # add a rectange for class 2p neg
    lowleft2Pneg = (0.0, -1.0)
    class2Ppos = mpatches.Rectangle(lowleft2Pneg,
                                    width=abs(lowleft2[0]),
                                    height=1.0,
                                    color='yellow',
                                    alpha=a1,
                                    ec="white",
                                    lw=4)
    ax.add_patch(class2Ppos)

    # add rectangle for lower left quadrant class 3
    lowleft3neg = (-1.0, -1.0)
    class3neg = mpatches.Rectangle(lowleft3neg,
                                   width=1.0 + lowleft2[0],
                                   height=1.0,
                                   color='blue',
                                   alpha=a1,
                                   ec='none')
    ax.add_patch(class3neg)

    # add rectange for upper right quadrant class 3
    lowleft3pos = (shift2, 0)
    class3pos = mpatches.Rectangle(lowleft3pos,
                                   width=1.0 + lowleft2[0],
                                   height=1.0,
                                   color='blue',
                                   alpha=a1,
                                   ec='none')
    ax.add_patch(class3pos)

    # add a Polygon for Class 4 upper left quadrant
    # add a path patch
    Path4u = mpath.Path
    path_data4u = [(Path4u.MOVETO, [-1.0, 0.0]), (Path4u.LINETO, [-1.0, 1.0]),
                   (Path4u.LINETO, [-shift2, shift2]),
                   (Path4u.LINETO, [-shift2, 0]),
                   (Path4u.CLOSEPOLY, [-shift2, 0.0])]
    codes4u, verts4u = zip(*path_data4u)
    path4u = mpath.Path(verts4u, codes4u)
    patch4u = mpatches.PathPatch(
        path4u,
        facecolor='#B048B5',  # purple
        alpha=a1,
        ec='none')
    ax.add_patch(patch4u)

    # add a Polygon for Class 4 lower right quadrant

    Path4l = mpath.Path
    path_data4l = [(Path4l.MOVETO, [shift2, 0.0]), (Path4l.LINETO, [1.0, 0.0]),
                   (Path4l.LINETO, [1.0, -1.0]),
                   (Path4l.LINETO, [shift2, -shift2]),
                   (Path4l.CLOSEPOLY, [shift2, -shift2])]
    codes4l, verts4l = zip(*path_data4l)
    path4l = mpath.Path(verts4l, codes4l)
    patch4l = mpatches.PathPatch(
        path4l,
        facecolor='#B048B5',  # purple
        alpha=a1,
        ec='none')
    ax.add_patch(patch4l)

    # Add a Polygon for the Class 1 upper right quadrant

    Path1u = mpath.Path
    path_data1u = [(Path1u.MOVETO, [-shift2, shift2]),
                   (Path1u.LINETO, [-1.0, 1.0]),
                   (Path1u.LINETO, [-shift2, 1.0]),
                   (Path1u.CLOSEPOLY, [-shift2, shift2])]
    codes1u, verts1u = zip(*path_data1u)
    path1u = mpath.Path(verts1u, codes1u)
    patch1u = mpatches.PathPatch(path1u, facecolor='red', alpha=a1, ec='none')
    ax.add_patch(patch1u)

    # Add a Polygone for the Class 1 lower left quadrant
    Path1l = mpath.Path
    path_data1l = [(Path1l.MOVETO, [shift2, -shift2]),
                   (Path1l.LINETO, [shift2, -1.0]),
                   (Path1l.LINETO, [1.0, -1.0]),
                   (Path1l.CLOSEPOLY, [shift2, -shift2])]
    codes1l, verts1l = zip(*path_data1l)
    path1l = mpath.Path(verts1l, codes1l)
    patch1l = mpatches.PathPatch(path1l, facecolor='red', alpha=a1, ec='none')
    ax.add_patch(patch1l)

    # Draw ellipse
    xy = np.hstack((0, 0))

    bkgd = collections.EllipseCollection(widths=width_ellipse,
                                         heights=height_ellipse,
                                         angles=135,
                                         units='xy',
                                         offsets=xy,
                                         transOffset=ax.transData,
                                         facecolor='grey',
                                         edgecolor='none',
                                         alpha=0.15)

    ax.add_collection(bkgd)

    #Get rid of axes spines

    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')
    ax.xaxis.set_ticks_position('bottom')
    ax.spines['bottom'].set_position(('data', 0))
    ax.spines['bottom'].set_alpha(0.5)
    ax.yaxis.set_ticks_position('left')
    ax.spines['left'].set_position(('data', 0))
    ax.spines['left'].set_alpha(0.5)

    # Annotation for Gradient vs Intercept annotation

    ax.text(0.98,
            0.98,
            'Gradient vs intercept',
            verticalalignment='top',
            horizontalalignment='right',
            transform=ax.transAxes,
            color='black',
            fontsize=9,
            fontweight='bold',
            alpha=0.50)

    for label in ax.get_xticklabels() + ax.get_yticklabels():
        label.set_fontsize(8)
        label.set_alpha(0.5)

    # Class 1 label

    ax.text(3 * shift2,
            ylimits[0] + shift2,
            'CLASS 1',
            verticalalignment='center',
            horizontalalignment='center',
            color='red',
            fontsize=fs,
            fontweight='bold',
            alpha=a2)

    # Class 2 label
    ax.text(-0.5 * shift2,
            ylimits[0] + 0.5 * shift2,
            'CLASS 2',
            verticalalignment='bottom',
            horizontalalignment='center',
            rotation=90,
            color='green',
            fontsize=fs,
            fontweight='bold',
            alpha=a2)

    # Class 2P label
    ax.text(0.5 * shift2,
            ylimits[0] + 0.5 * shift2,
            'CLASS 2p',
            verticalalignment='bottom',
            horizontalalignment='center',
            rotation=90,
            color='#EEC900',
            fontsize=fs,
            fontweight='bold',
            alpha=a2 * 1.5)

    # Class 3 label
    ax.text(-3 * shift2,
            ylimits[0] + shift2,
            'CLASS 3',
            verticalalignment='center',
            horizontalalignment='right',
            color='blue',
            fontsize=fs,
            fontweight='bold',
            alpha=a2)

    # Class 4 label
    ax.text(-3 * shift2,
            shift2,
            'CLASS 4',
            verticalalignment='center',
            horizontalalignment='right',
            color='#B048B5',
            fontsize=fs,
            fontweight='bold',
            alpha=a2)

    # Background label
    angle = -45

    ax.text(0.1 * height_ellipse,
            0.1 * height_ellipse,
            'background',
            verticalalignment='center',
            horizontalalignment='center',
            rotation=angle,
            transform=ax.transData,
            color='black',
            fontsize=fs,
            fontweight='bold',
            alpha=a2 / 2.0)

    return get_figure_data(), {"mean critical angle": critical_angle}