This function rescales the y-axis based on the data that is visible given the current xlim of the axis.
    ax -- a matplotlib axes object
    margin -- the fraction of the total height of the y-data to pad the upper and lower ylims

def autoscale_y(ax,margin=0.1):
    """This function rescales the y-axis based on the data that is visible given the current xlim of the axis.
    ax -- a matplotlib axes object
    margin -- the fraction of the total height of the y-data to pad the upper and lower ylims"""
    # Thanks to http://stackoverflow.com/questions/29461608/matplotlib-fixing-x-axis-scale-and-autoscale-y-axis for inspiring this!
    
    import numpy as np

    def get_bottom_top(line,lo,hi):
        xd = line.get_xdata()
        yd = line.get_ydata()
        y_displayed = yd[((xd>lo) & (xd<hi))]
        if len(y_displayed)==0:
            #No plotted data is inside the xlims
            return None, None
        else:
            h = np.max(y_displayed) - np.min(y_displayed)
            bot = np.min(y_displayed)-margin*h
            top = np.max(y_displayed)+margin*h
            return bot,top

    lines = ax.get_lines()
     
    lo,hi = ax.get_xlim()
    
    # Do a quick check to see if the x-axis has been inverted
    if lo>hi: # Reverse them for now
        lo,hi = hi,lo
        
    # Initialize limits
    bot,top = np.inf, -np.inf

    for line in lines:
        new_bot, new_top = get_bottom_top(line,lo,hi)
        if new_bot is not None:
            if new_bot < bot: bot = new_bot
            if new_top > top: top = new_top

    # Check to see if it is appropriate to change the boundaries
    if bot !=np.inf and top != -np.inf:    
        ax.set_ylim(bot,top)
    
    return ax