Beispiel #1
0
def test_tickedstroke():
    fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(12, 4))
    path = Path.unit_circle()
    patch = patches.PathPatch(path,
                              facecolor='none',
                              lw=2,
                              path_effects=[
                                  path_effects.withTickedStroke(angle=-90,
                                                                spacing=10,
                                                                length=1)
                              ])

    ax1.add_patch(patch)
    ax1.axis('equal')
    ax1.set_xlim(-2, 2)
    ax1.set_ylim(-2, 2)

    ax2.plot(
        [0, 1], [0, 1],
        label=' ',
        path_effects=[path_effects.withTickedStroke(spacing=7, angle=135)])
    nx = 101
    x = np.linspace(0.0, 1.0, nx)
    y = 0.3 * np.sin(x * 8) + 0.4
    ax2.plot(x, y, label=' ', path_effects=[path_effects.withTickedStroke()])

    ax2.legend()

    nx = 101
    ny = 105

    # Set up survey vectors
    xvec = np.linspace(0.001, 4.0, nx)
    yvec = np.linspace(0.001, 4.0, ny)

    # Set up survey matrices.  Design disk loading and gear ratio.
    x1, x2 = np.meshgrid(xvec, yvec)

    # Evaluate some stuff to plot
    g1 = -(3 * x1 + x2 - 5.5)
    g2 = -(x1 + 2 * x2 - 4)
    g3 = .8 + x1**-3 - x2

    cg1 = ax3.contour(x1, x2, g1, [0], colors=('k', ))
    plt.setp(cg1.collections,
             path_effects=[path_effects.withTickedStroke(angle=135)])

    cg2 = ax3.contour(x1, x2, g2, [0], colors=('r', ))
    plt.setp(cg2.collections,
             path_effects=[path_effects.withTickedStroke(angle=60, length=2)])

    cg3 = ax3.contour(x1, x2, g3, [0], colors=('b', ))
    plt.setp(cg3.collections,
             path_effects=[path_effects.withTickedStroke(spacing=7)])

    ax3.set_xlim(0, 4)
    ax3.set_ylim(0, 4)
Beispiel #2
0
def plotOptProb(
    obj,
    xRange,
    yRange,
    ineqCon=None,
    eqCon=None,
    nPoints=51,
    optPoint=None,
    conStyle="shaded",
    ax=None,
    colors=None,
    cmap=None,
    levels=None,
    labelAxes=True,
):
    """Generate a contour plot of a 2D constrained optimisation problem

    Parameters
    ----------
    obj : function
        Objective function, should accept inputs in the form f = obj(x, y) where x and y are 2D arrays
    xRange : list or array
        Upper and lower limits of the plot in x
    yRange : list or array
        Upper and lower limits of the plot in y
    ineqCon : function or list of functions, optional
        Inequality constraint functions, should accept inputs in the form g = g(x, y) where x and y are 2D arrays.
        Constraints are assumed to be of the form g <= 0
    eqCon : functions or list of functions, optional
        Equality constraint functions, should accept inputs in the form h = h(x, y) where x and y are 2D arrays.
        Constraints are assumed to be of the form h == 0
    nPoints : int, optional
        Number of points in each direction to evaluate the objective and constraint functions at
    optPoint : list or array, optional
        Optimal Point, if you want to plot a point there, by default None
    conStyle : str, optional
        Controls how inequality constraints are represented, "shaded" will shade the infeasible regions while "hashed"
        will place hashed lines on the infeasible side of the feasible boundary, by default "shaded", note the "hashed"
        option only works for matplotlib >= 3.4
    ax : matplotlib axes object, optional
        axes to plot, by default None, in which case a new figure will be created and returned by the function
    colors : list, optional
        List of colors to use for the constraint lines, by default uses the current matplotlib color cycle
    cmap : colormap, optional
        Colormap to use for the objective contours, by default will use nicePlots' parula map
    levels : list, array, int, optional
        Number or values of contour lines to plot for the objective function
    labelAxes : bool, optional
        Whether to label the x and y axes, by default True, in which case the axes will be labelled, "$X_1$" and "$X_2$"

    Returns
    -------
    fig : matplotlib figure object
        Figure containing the plot. Returned only if no input ax object is specified
    ax : matplotlib axes object, but only if no ax object is specified
        Axis with the colored line. Returned only if no input ax object is specified
    """

    # --- Create a new figure if the user did not supply an ax object ---
    returnFig = False
    if ax is None:
        fig, ax = plt.subplots()
        returnFig = True

    # --- If user provided only single inequality or equality constraint, convert it to an iterable  ---
    cons = {}
    for inp, key in zip([eqCon, ineqCon], ["eqCon", "ineqCon"]):
        if inp is not None:
            if not hasattr(inp, "__iter__"):
                cons[key] = [inp]
            else:
                cons[key] = inp
        else:
            cons[key] = []

    # --- Check that conStyle contains a supported value to avoid random conStyle arguments ---
    if conStyle.lower() not in ["shaded", "hashed"]:
        raise ValueError(f"conStyle: {conStyle} is not supported")

    # --- Check if user has a recent enough version of matplotlib to use hashed boundaries ---
    if conStyle.lower() == "hashed":
        try:
            patheffects.withTickedStroke
        except AttributeError:
            warnings.warn(
                "matplotlib >= 3.4 is required for hashed inequality constrain boundaries, switching to shaded inequality constraint style"
            )
            conStyle = "shaded"

    # --- Define some default values if the user didn't provide them ---
    if cmap is None:
        cmap = parula_map

    if colors is None:
        colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
    nColor = len(colors)

    # --- Create grid of points for evaluating functions ---
    X, Y = np.meshgrid(np.linspace(xRange[0], xRange[1], nPoints),
                       np.linspace(yRange[0], yRange[1], nPoints))

    # --- Evaluate objective and constraint functions ---
    Fobj = obj(X, Y)
    g = []
    for ineq in cons["ineqCon"]:
        g.append(ineq(X, Y))
    h = []
    for eq in cons["eqCon"]:
        h.append(eq(X, Y))

    # --- Plot objective contours ---
    adjust_spines(ax, outward=True)
    ax.contour(
        X,
        Y,
        Fobj,
        levels=levels,
        cmap=cmap,
    )

    # --- Plot constraint boundaries ---
    colorIndex = 0
    for conValue in g:
        contour = ax.contour(X,
                             Y,
                             conValue,
                             levels=[0.0],
                             colors=colors[colorIndex % nColor])
        if conStyle.lower() == "hashed":
            plt.setp(contour.collections,
                     path_effects=[
                         patheffects.withTickedStroke(angle=60, length=2)
                     ])
        elif conStyle.lower() == "shaded":
            ax.contourf(X,
                        Y,
                        conValue,
                        levels=[0.0, np.inf],
                        colors=colors[colorIndex % nColor],
                        alpha=0.4)

        colorIndex += 1

    for conValue in h:
        ax.contour(X,
                   Y,
                   conValue,
                   levels=[0.0],
                   colors=colors[colorIndex % nColor])

    # --- Plot optimal point if provided ---
    if optPoint is not None:
        ax.plot(
            optPoint[0],
            optPoint[1],
            "o",
            color="black",
            markeredgecolor=ax.get_facecolor(),
            markersize=10,
            clip_on=False,
        )

    # --- Label axes if required ---
    if labelAxes:
        ax.set_xlabel("$x_1$")
        ax.set_ylabel("$x_2$", rotation="horizontal", ha="right")

    if returnFig:
        return fig, ax
    else:
        return
Beispiel #3
0
# Applying TickedStroke to paths
# ==============================
import matplotlib.patches as patches
from matplotlib.path import Path
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patheffects as patheffects

fig, ax = plt.subplots(figsize=(6, 6))
path = Path.unit_circle()
patch = patches.PathPatch(path,
                          facecolor='none',
                          lw=2,
                          path_effects=[
                              patheffects.withTickedStroke(angle=-90,
                                                           spacing=10,
                                                           length=1)
                          ])

ax.add_patch(patch)
ax.axis('equal')
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)

plt.show()

###############################################################################
# Applying TickedStroke to lines
# ==============================
fig, ax = plt.subplots(figsize=(6, 6))
ax.plot([0, 1], [0, 1],
Beispiel #4
0
x1, x2 = np.meshgrid(xvec, yvec)

# Evaluate some stuff to plot
obj = x1**2 + x2**2 - 2 * x1 - 2 * x2 + 2
g1 = -(3 * x1 + x2 - 5.5)
g2 = -(x1 + 2 * x2 - 4.5)
g3 = 0.8 + x1**-3 - x2

cntr = ax.contour(x1,
                  x2,
                  obj, [0.01, 0.1, 0.5, 1, 2, 4, 8, 16],
                  colors='black')
ax.clabel(cntr, fmt="%2.1f", use_clabeltext=True)

cg1 = ax.contour(x1, x2, g1, [0], colors='sandybrown')
plt.setp(cg1.collections,
         path_effects=[patheffects.withTickedStroke(angle=135)])

cg2 = ax.contour(x1, x2, g2, [0], colors='orangered')
plt.setp(cg2.collections,
         path_effects=[patheffects.withTickedStroke(angle=60, length=2)])

cg3 = ax.contour(x1, x2, g3, [0], colors='mediumblue')
plt.setp(cg3.collections,
         path_effects=[patheffects.withTickedStroke(spacing=7)])

ax.set_xlim(0, 4)
ax.set_ylim(0, 4)

plt.show()
"""
==============================
Lines with a ticked patheffect
==============================

Ticks can be added along a line to mark one side as a barrier using
`~matplotlib.patheffects.TickedStroke`.  You can control the angle,
spacing, and length of the ticks.

The ticks will also appear appropriately in the legend.

"""

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import patheffects

fig, ax = plt.subplots(figsize=(6, 6))
ax.plot([0, 1], [0, 1], label="Line",
        path_effects=[patheffects.withTickedStroke(spacing=7, angle=135)])

nx = 101
x = np.linspace(0.0, 1.0, nx)
y = 0.3*np.sin(x*8) + 0.4
ax.plot(x, y, label="Curve", path_effects=[patheffects.withTickedStroke()])

ax.legend()

plt.show()