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?
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
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
)
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:
real=True
. This will compute real solutions.list_2d
to plot list of points.rendering_kw
is a dictionary of keyword arguments that will be provided to matplotlib to customize the appearance. In this case, it will be passed to Matplotlib's plot
function.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
)
Instead, in this code block I'll modify the axis ticks. Note that:
ticks
and ticks_labels
. You can be creative with ticks_labels
, as long as it has the same number of elements of ticks
.plt.show()
to visualize the plot.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()
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.