Search code examples
pythonmatplotlibgraphasymptote

how to draw an asymptote with a dashed line?


I would like the asymptote on the tg(x) function be draw with a dashed line, but I don't know how to change it in this code:

import matplotlib.ticker as tck
import matplotlib.pyplot as plt
import numpy as np
f,ax=plt.subplots(figsize=(8,5))
x=np.linspace(-np.pi, np.pi,100)
y=np.sin(x)/np.cos(x)
plt.ylim([-4, 4])
plt.title("f(x) = tg(x)")
plt.xlabel("x")
plt.ylabel("y")
ax.plot(x/np.pi,y)
ax.xaxis.set_major_formatter(tck.FormatStrFormatter('%g $\pi$'))

Solution

  • Interesting question. My approach is to look for the discontinuities by examining the derivative of the function, and separating the original function based on the location o these discontinuities.

    So for tan(x), since the derivative is always positive (outside of the asymptotes) we look for points where np.diff(y) < 0. Based on all the locations where the previous condition is true, we split up the original function into segments and plot those individually (with the same plot properties so the lines look the same) and then plot black dashed lines separately. The following code shows this working:

    import matplotlib.ticker as tck
    import matplotlib.pyplot as plt
    import numpy as np
    f,ax=plt.subplots(figsize=(8,5))
    x=np.linspace(-np.pi, np.pi,100)
    y=np.sin(x)/np.cos(x)
    plt.ylim([-4, 4])
    plt.title("f(x) = tg(x)")
    plt.xlabel("x")
    plt.ylabel("y")
    ax.xaxis.set_major_formatter(tck.FormatStrFormatter('%g $\pi$'))
    
    # Search for points with negative slope
    dydx = np.diff(y)
    negativeSlopeIdx = np.nonzero(dydx < 0)[0]
    
    # Take those points and parse the original function into segments to plot
    yasymptote = np.array([-4, 4])
    iprev = 0
    for i in negativeSlopeIdx:
        ax.plot(x[iprev:i-1]/np.pi, y[iprev:i-1], "b", linewidth=2)
        ax.plot(np.array([x[i], x[i]])/np.pi, yasymptote, "--k")
        iprev = i+1
    
    
    ax.plot(x[iprev:]/np.pi, y[iprev:], "b", linewidth=2)
    plt.show()
    

    With a final plot looking like:

    enter image description here