wie eine Asymptote / Diskontinuität mit Matplotlib zu handhaben
-
23-09-2019 - |
Frage
Wenn Sie ein Diagramm mit einer Diskontinuität Plotten / Asymptote / Singularität / was auch immer, gibt es eine automatische Weise Matplotlib von ‚Verbinden der Punkte‘ über den ‚Bruch‘ zu verhindern? (Siehe Code / Bild unten).
Ich lese, dass Sage eine [detect_poles] Anlage hat, dass gut ausgesehen, aber ich will es wirklich Arbeit mit Matplotlib.
import matplotlib.pyplot as plt
import numpy as np
from sympy import sympify, lambdify
from sympy.abc import x
fig = plt.figure(1)
ax = fig.add_subplot(111)
# set up axis
ax.spines['left'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
# setup x and y ranges and precision
xx = np.arange(-0.5,5.5,0.01)
# draw my curve
myfunction=sympify(1/(x-2))
mylambdifiedfunction=lambdify(x,myfunction,'numpy')
ax.plot(xx, mylambdifiedfunction(xx),zorder=100,linewidth=3,color='red')
#set bounds
ax.set_xbound(-1,6)
ax.set_ybound(-4,4)
plt.show()
Lösung
Das ist vielleicht nicht die eleganteste Lösung, die Sie für suchen, aber wenn nur Ergebnisse für die meisten Fälle können Sie „Clip“ große und kleine Werte Ihrer gezeichneten Daten zu +∞
und -∞
sind. Matplotlib nicht plotten diese nicht. Natürlich müssen Sie nicht machen Ihre Auflösung zu niedrig oder Ihre Clipping-Schwelle zu hoch vorsichtig sein.
utol = 100.
ltol = -100.
yy = 1/(xx-2)
yy[yy>utol] = np.inf
yy[yy<ltol] = -np.inf
ax.plot(xx, yy, zorder=100, linewidth=3, color='red')
Andere Tipps
Durch die Verwendung von maskierten Arrays Sie vermeiden können ausgewählte Bereiche Plotten Eine Kurve.
die Singularität entfernen bei x = 2:
import matplotlib.numerix.ma as M # for older versions, prior to .98
#import numpy.ma as M # for newer versions of matplotlib
from pylab import *
figure()
xx = np.arange(-0.5,5.5,0.01)
vals = 1/(xx-2)
vals = M.array(vals)
mvals = M.masked_where(xx==2, vals)
subplot(121)
plot(xx, mvals, linewidth=3, color='red')
xlim(-1,6)
ylim(-5,5)
Diese einfache Kurve könnte ein bisschen mehr klar, auf welche Punkte werden ausgeschlossen sind:
xx = np.arange(0,6,.2)
vals = M.array(xx)
mvals = M.masked_where(vals%2==0, vals)
subplot(122)
plot(xx, mvals, color='b', linewidth=3)
plot(xx, vals, 'rx')
show()
Nein, ich denke, es gibt keine integrierte Möglichkeit matplotlib
zu sagen, diese zu ignorieren
Punkte. Immerhin verbindet es nur Punkte und weiß nichts über Funktionen
oder was zwischen den Punkten geschieht in.
Sie können jedoch sympy
verwenden, um die Pole zu finden, und dann die kontinuierlichen Teile Ihrer Funktion zusammen flicken. Hier einige zwar hässlich Code, der genau das tut:
from pylab import *
from sympy import solve
from sympy.abc import x
from sympy.functions.elementary.complexes import im
xmin = -0.5
xmax = 5.5
xstep = 0.01
# solve for 1/f(x)=0 -- we will have poles there
discontinuities = sort(solve(1/(1/(x-2)),x))
# pieces from xmin to last discontinuity
last_b = xmin
for b in discontinuities:
# check that this discontinuity is inside our range, also make sure it's real
if b<last_b or b>xmax or im(b):
continue
xi = np.arange(last_b, b, xstep)
plot(xi, 1./(xi-2),'r-')
last_b = b
# from last discontinuity to xmax
xi = np.arange(last_b, xmax, xstep)
plot(xi, 1./(xi-2),'r-')
xlim(xmin, xmax)
ylim(-4,4)
show()