plotsympyimplicitxticksyticks

Adjusting axis’ ticks in plotting with SymPy


Here is the problem: I have two implicit functions F and G. I am trying to find a way to plot them using SymPy.

My question is, how to adjust ticks on x- and y-axis, so I can see a crossing point of my functions? How to add visual quality to my plot?

enter image description here

enter image description here

I’ve tried to add “points” to increase the quality, but it didn’t work well. I have no idea how to deal with ticks though


Solution

  • With quality, I assume you would like to improve the smoothness of the lines. Sadly, the way sympy.plotting.MatplotlibBackend is coded makes it impossible to improve it.

    To achieve a better result you should use SymPy Plotting Backend, which solves a tons of problems affecting sympy.plotting:

    from sympy import *
    from spb import *
    var("x, y")
    
    e1 = (x**2 + y**2) * (x + y) - 15 * x * y
    e2 = (x**4 + y**4) * (x**2 + y**2) - 85 * x**2 * y**2
    ranges = (x, -10, 10), (y, -10, 10)
    graphics(
        implicit_2d(e1, *ranges, color="purple", label="e1"),
        implicit_2d(e2, *ranges, color="pink", n=301, label="e2"),
        grid=False
    )
    

    enter image description here

    Note that I used n=301 when plotting the second expression (odd number of discretization points). Given your current ranges, it will place a discretization point on x=0 and y=0, making the visualization more accurate.

    SymPy Plotting Backend by default uses standard Matplotlib layout, which places the ticks on the bottom and on the left of the figure. This make your intersection point visible.

    Final note: next time copy your code as text, not as an image.

    EDIT to satisfy user request:

    In this code block I'm going to plot all solutions where the two curves intersect each other. Note that:

    from sympy import *
    from spb import *
    import numpy as np
    var("x, y", real=True)
    
    e1 = (x**2 + y**2) * (x + y) - 15 * x * y
    e2 = (x**4 + y**4) * (x**2 + y**2) - 85 * x**2 * y**2
    sols = solve([e1, e2], [x, y])
    print("solutions:", sols)
    # solutions: [(0, 0), (2, 4), (4, 2)]
    xx = [s[0] for s in sols]
    yy = [s[1] for s in sols]
    ranges = (x, -10, 10), (y, -10, 10)
    graphics(
        implicit_2d(e1, *ranges, color="purple", label="e1"),
        implicit_2d(e2, *ranges, color="pink", n=301, label="e2"),
        list_2d(xx, yy, scatter=True, label="all solutions"),
        list_2d([0], [0], scatter=True, label="my marker", rendering_kw={"marker": "x", "markersize": 10}),
        grid=True, show_minor_grid=True
    )
    

    enter image description here

    Instead, in this code block I'll modify the axis ticks. Note that:

    import numpy as np
    import matplotlib.pyplot as plt
    
    p = graphics(
        implicit_2d(e1, *ranges, color="purple", label="e1"),
        implicit_2d(e2, *ranges, color="pink", n=301, label="e2"),
        list_2d(xx, yy, scatter=True, label="all solutions"),
        list_2d([0], [0], scatter=True, label="my marker", rendering_kw={"marker": "x", "markersize": 10}),
        grid=False, show=False
    )
    # extract Matplotlib's axes from the plot object, p
    ax = p.ax
    
    # create ticks
    ticks = np.arange(-10, 10, 0.5)
    ticks_labels = [str(t) for t in ticks]
    ax.set_xticks(ticks, ticks_labels)
    plt.show()
    

    enter image description here

    As you can see, adding ticks with a step of 0.5 is going to make the ticks very difficult to read. You will have to play with the step.