pythonpython-3.xmatplotlibsympy

How to plot 4*sin(2*x)/cos(2*x)**3 using Sympy?


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)

But all I get is: enter image description here

when it should look a bit like a horizontally-squished tangent graph: enter image description here


Solution

  • 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))
    

    figure

    In particular:

    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:

    1. detect_poles=False: used by default, no detection will be used. You will end up with something like this:

      enter image description here

      Here, the vertical lines should not be present.

    2. 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).

    3. 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:

      enter image description here

      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.