I am trying to plot the expression 4*sin(2*x)/cos3(2*x) in Sympy:
from sympy import *
from sympy.plotting import plot
x = symbols('x')
expr = 4*sin(2*x)/cos(2*x)**3
plot(expr)
when it should look a bit like a horizontally-squished tangent graph:
SymPy's plotting module doesn't handle very well functions with poles. But SymPy Plotting Backends (which is a more advanced plotting module) is up for the task:
from spb import plot
plot(expr, (x, -2*pi, 2*pi), detect_poles=True, ylim=(-3, 3))
In particular:
detect_poles=True
: run the algorithm to detect poles (singularities).ylim=(-3, 3)
: limit the visualization on the y-axis in the specified range. Failing to set this keywork argument will get you a plot similar to what you shown.If you are interested in using that module, here is the installation page. The documentation is also full with examples.
EDIT to reply to comment: Yes, it is necessary to manually activate the algorithm, otherwise false positive might be introduced, depending on the function. Since I'm here, I'm going to better explain this algorithms:
detect_poles=False
: used by default, no detection will be used. You will end up with something like this:
Here, the vertical lines should not be present.
detect_poles=True
(the result of this algorithm is shown above): run a gradient-based algorithm on the numerical data. In short, if the gradient of the function computed between two consecutive points along the x-axis, is greater than some threshold, then a singularity is found and the algorithm insert a NaN point between them, which forces the vertical line to disappear. However, this strategy can be fooled by some functions that exhibits very high gradients: in this cases, the algorithm will insert NaN values even though there might not be any singularity. There are some parameters that can be used to fine tune the results of the visualization. The easiest one is to increasing the number of discretization points (n=1000
by default).
detect_poles="symbolic"
: it runs both a gradient-based algorithm on the numerical data, as well as a symbolic algorithm on the expression to be plotted, which involves the use of SymPy's solve
. Depending on the symbolic expression, solve
might not be able to solve for all singularities. Or worse, it could take forever to complete the task. Here is the output:
Here, the vertical dotted lines indicate where the singularities are found by the symbolic algorithm.
Given the limitations of both the gradient-based and symbolic algorithms, I (developer of that module) decided that it is best to leave detect_poles=False
by default, and let the user enable the algorithm that better suits its needs. :)
More examples of plotting discountinuities can be found on this tutorial page.