@@ -0,0 +1,2058 @@
+def phase_diagram(xfix=(), xstable=(), size=60, offset=12):%0A    %22%22%22Display a (text) phase diagram%0A%0A    Parameters%0A    ---------%0A    xfix : tuple%0A        The fixed points%0A    xstable : tuple (of tuples)%0A        Boolean stability tuples (from is_stable())%0A    size : int (size %3E 20)%0A        Width of the phase line in characters%0A    offset : int (offset %3E 2; size*.1 %3C offset %3C size*.25)%0A        Min/max offset of fixed points on the line%0A    %22%22%22%0A    %0A    n = len(xfix)%0A    xfix = list(xfix)%0A    xstable = list(xstable)%0A%0A    if n %3C 1:%0A        print(%22No fixed points%22)%0A        return None%0A    %0A    # Set some (hopefully) sane display limits%0A    if len(xfix) != len(xstable):%0A        raise ValueError(%22xfix and xstable must have same number of elements%22)%0A    if size %3C 20:%0A        raise ValueError(%22size must be greater than 20%22)%0A    if offset/float(size) %3C 0.1:%0A        raise ValueError(%22offset must be 10 percent of size%22)%0A    if offset/float(size) %3E 0.25:%0A        raise ValueError(%22offset must be less then 25 percent of size%22)%0A    if offset %3C 1:%0A        raise ValueError(%22offset must be %3E 1%22)        %0A%0A    # Init a phase linees and its annotations%0A    line = %5B%22-%22, %5D * size%0A    annote = %5B%22 %22, %5D * size%0A%0A    # Add fixed points%0A    steps = range(offset, size-offset, (size - 2*offset)/n)%0A    for s, xf in zip(steps, xfix):%0A        line%5Bs%5D = %22*%22%0A        annote%5Bs%5D = str(xf)%0A%0A    # Add stablity arrows%0A    for i in range(len(xstable)):%0A        s = steps%5Bi%5D%0A        xsb = xstable%5Bi%5D%0A%0A        downside = s - int(offset/2)%0A        upside = s + int(offset/2)%0A%0A        # Plus side%0A        if xsb%5B0%5D:%0A            line%5Bdownside%5D = %22%3E%22%0A        elif not xsb%5B0%5D:%0A            # First step or last has no arrow?%0A            if (i == 0) or (not xstable%5Bi-1%5D%5B1%5D):%0A                line%5Bdownside%5D = %22%3C%22%0A%0A        # Minus side%0A        if xsb%5B1%5D:%0A            line%5Bupside%5D = %22%3C%22%0A        elif not xsb%5B1%5D:%0A            # Are we on the end?%0A            if i == len(xstable)-1:%0A                line%5Bupside%5D = %22%3E%22%0A%0A    print(%22%5Cn%22)%0A    print(''.join(line))%0A    print(''.join(annote))%0A    %0A

Split off the visualization into it's own branch