2010-03-29 44 views
21

Al trazar un gráfico con una discontinuidad/asíntota/singularidad/lo que sea, ¿hay alguna manera automática de evitar que Matplotlib 'junte los puntos' a través del 'quiebre'? (ver código/imagen a continuación).
leí que Sage tiene una facilidad [detect_poles] que se veía bien, pero realmente quiero que funcione con Matplotlib.cómo manejar una asíntota/discontinuidad con 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

+1

gracias por esta pregunta; aunque lo etiquetó 'python', tenga en cuenta que, en general, es una pregunta' matplotlib'; Me usé una de las respuestas de Julia en lugar de Python. Saludos. –

Respuesta

11

Esto puede no ser la solución elegante que busca, pero si sólo quiere resultados para la mayoría de los casos, puede "recortar" grande y valores pequeños de sus datos representados a +∞ y -∞ respectivamente. Matplotlib no traza estos. Por supuesto, debe tener cuidado de no hacer que su resolución sea demasiado baja o su umbral de recorte demasiado alto.

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') 
+0

Esto funciona muy bien. También es posible usar 'np.nan' en lugar de' np.inf' si tuviera otra razón para evitar '∞' – MackM

5

No, creo que no hay manera integrada para contar matplotlib hacer caso omiso de estos puntos. Después de todo, sólo se conecta puntos y no sabe nada acerca de las funciones o lo que ocurre en entre los puntos.

Sin embargo, puede utilizar sympy para encontrar los polos, y luego arreglar las piezas continuas de la función juntos. Aquí un poco de código es cierto fea que hace exactamente eso:

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

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

+0

Esto es muy limitado en la aplicabilidad: si la función era tan (x) en lugar de 1/(x-2), el comando resolver no encontraría ninguna raíz de 1/tan (x). Solo funciona aquí porque 1/(1/(x-2)) se simplifica a x-2. –

20

Mediante el uso de masked arrays puede evitar el trazado de regiones seleccionadas de una curva.

Para eliminar la singularidad en 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) 

Esta curva simple podría ser un poco más claro en el que se excluyen puntos:

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

+0

por qué es que cuando ejecuto el código sigo teniendo la línea vertical recta que conecta las curvas rojas? –

Cuestiones relacionadas