# handle division by zero
# http://stackoverflow.com/questions/1528237/how-can-i-handle-exceptions-in-a-list-comprehension-in-python
def catch(func, handle=lambda e : e, *args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception as e:
        #return handle(e)
        return NaN
# graphic, table, labeled points, point of interest                
def go(fx=0, gx=0, xmin=-3, xmax=3, ymin=None, ymax=None, step=1, x1=None, label=True, simple=False, rotation=0):
    """Show a graph, table of values, and points of interest """
    import numpy as np # for arange
    x = var('x'); fn = 'plot' + str(int(random()*10000)) + '.png'
    
    f(x) = fx
    g(x) = gx
    
    if simple == True:
        s = abs(xmin/ceil(step))
    else:
        s = step
    
    # data
    fv = [(i, catch(lambda: f(i).n())) for i in np.arange(xmin,xmax,s)] # include xmax
    gv = [(i, catch(lambda: g(i).n())) for i in np.arange(xmin,xmax,s)] # include xmax
    
    # plot with points
    G = plot(f(x),(x,xmin,xmax), ymin=ymin, ymax=ymax, detect_poles='show', color='green');
    G += plot(g(x),(x,xmin,xmax),ymin=ymin, ymax=ymax, detect_poles='show', color='red'); 
    G += points(fv+gv,pointsize=40,color='black'); 
    
    for p in fv+gv:  # label points
        if label:
            if math.isnan(p[1])==False: # don't plot NaNs
                G += text(' (%.1f,%.1f)'%(p[0],p[1]),p,horizontal_alignment='left',rotation=rotation,color='black',fontsize=10, fontweight='normal')
    
        if math.isnan(p[1]): # plot NaNs
            q=(p[0],.5)
            G += text(' (%.1f,Div0)'%q[0],q,horizontal_alignment='left',rotation=rotation,color='black',fontsize=10, fontweight='normal')
            G += points(q,pointsize=40,color='blue'); 
                
    # horizontal asymptotes
    a1 = limit(f,x=+infinity)
    a2 = limit(f,x=-infinity)
    G += line([(-100,a1),(100,a2)], xmin=xmin,xmax=xmax,ymin=ymin, ymax=ymax, color='gray', linestyle='dashed')
    
    if x1:
        p1 = (x1, catch(lambda: f(x1))) # point of interest
        G += points(p1,pointsize=40,color='blue')
        G += text(' (%.1f,%.1f)'%(p1[0],p1[1]),p1,horizontal_alignment='left',rotation=rotation,color='blue',fontsize=10, fontweight='bold')
    else:
        p1 = (None, None)
         
    G.save(DATA + fn) # required due to Sage object caching
    
    html('<div style="float:left;">')
    html("<img src="+fn+"></img>")
    html('</div><div style="float:left; padding-left:50px;">Green Graph')
    html.table([["$x$", f]] + fv, header = True)
    html('</div><div style="float:left; padding-left:50px;">Red Graph')
    html.table([["$x$", g]] + gv, header = True)
    html('</div><div style="float:left; padding-left:50px;">Interesting Points')
    html.table([["$x$", "$y$"]] + [p1], header = True)
    html('</div>') # html
    
    import time; time.sleep(1); os.remove(DATA + fn) # cleanup
    returnNOTE: The 4 comma-separated numbers following f(x), g(x) are the minimum x and y values.
f(x)=3*x^2/(x^2+2)
g(x)=f(x)+1
go(f(x),g(x),-5,5,0,6,x1=.5)
Add new comment