comment manipuler un asymptote / discontinuité avec Matplotlib

quand vous tracez un graphique avec une discontinuité/asymptote/singularité/quoi que ce soit, y a-t-il un moyen automatique d'empêcher Matplotlib de "rejoindre les points" à travers la "rupture"? (veuillez consulter le code de l'image ci-dessous).

J'ai lu que Sage a une installation [detect_poles] qui semble bonne, mais je veux vraiment qu'elle fonctionne avec 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()

Discontinuity

22
demandé sur Adaline Valentina Simonian 2010-03-29 22:27:09

3 réponses

ce n'est peut-être pas la solution élégante que vous recherchez, mais si vous voulez juste des résultats pour la plupart des cas, vous pouvez "clip" de grandes et petites valeurs de vos données tracées à +∞ et -∞ respectivement. Matplotlib ne les trace pas. Bien sûr, vous devez faire attention à ne pas rendre votre résolution trop basse ou votre seuil de coupure trop élevé.

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') 
13
répondu Paul 2010-03-31 03:19:27

En utilisant masqué tableaux vous pouvez éviter le traçage des régions sélectionnées d'une courbe.

Pour supprimer la singularité à 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) 
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()

enter image description here

21
répondu tom10 2018-02-13 18:10:19

Non, je pense qu'il n'est pas intégré dans le moyen de dire matplotlib pour ignorer ces point. Après tout, il connecte juste des points et ne sait rien sur les fonctions ou ce qui se passe entre les points.

cependant, vous pouvez utiliser sympy pour trouver les poteaux, et puis rapiécer les morceaux continus de votre fonction ensemble. Voici un code certes laid qui fait exactement cela:

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

exemple http://i43.tinypic.com/30mvbzb.jpg

5
répondu Benjamin Bannier 2010-03-29 23:04:49