예제 #1
0
파일: interlace.py 프로젝트: BIGtigr/xgcode
 def get_bezier_path(self):
     b = bezier.create_bchunk_hermite(self.t_initial, self.t_final,
                                      self.fp(self.t_initial),
                                      self.fp(self.t_final),
                                      self.fv(self.t_initial),
                                      self.fv(self.t_final))
     return pcurve.BezierPath([b])
예제 #2
0
 def _draw_beam(self, p_mid, color):
     scale = np.array((self.plot_width / self.timescale, self.plot_height))
     xproj = np.array((1, 0))
     yproj = np.array((0, 1))
     out = StringIO()
     print >> out, r'\path[fill=%s,fill opacity=0.5]' % color
     p_upper = p_mid + 0.5 * self.p_width
     p_lower = p_mid - 0.5 * self.p_width
     t_upper = self.f.inv(p_lower)
     t_lower = self.f.inv(p_upper)
     pta = np.array((t_lower, p_upper))
     ptb = np.array((t_upper, p_lower))
     dta = np.array((1, self.f.deriv(t_lower)))
     dtb = np.array((1, self.f.deriv(t_upper)))
     print >> out, tikz.point_to_tikz(pta * scale * yproj) + ' --'
     bchunk = bezier.create_bchunk_hermite(t_lower, t_upper, pta * scale,
                                           ptb * scale, dta * scale,
                                           dtb * scale)
     pts = tuple(tikz.point_to_tikz(p) for p in bchunk.get_points())
     print >> out, '%s .. controls %s and %s .. %s --' % pts
     print >> out, tikz.point_to_tikz(ptb * scale * xproj) + ' --'
     print >> out, tikz.point_to_tikz(pta * scale * xproj) + ' --'
     ptc = np.array((t_lower, p_lower))
     print >> out, tikz.point_to_tikz(ptc * scale) + ' --'
     print >> out, tikz.point_to_tikz(ptb * scale * yproj) + ' -- cycle;'
     return out.getvalue().rstrip()
예제 #3
0
def get_tikz_body(fs):
    out = StringIO()
    # define user variables
    plot_width = fs.plot_width
    plot_height = fs.plot_height
    timescale = fs.t_max
    # create the function objects
    f_a = JC69.IdentitySlopeInformation(fs.a_mu, fs.a_N)
    f_b = JC69.IdentitySlopeInformation(fs.b_mu, fs.b_N)
    # Define some times for evaluation of the curve.
    times = [timescale*2**-i for i in range(10)]
    # define some more intermediate values
    ymax = max(f_a(min(times)), f_b(min(times))) * 1.2
    plotscale = np.array((plot_width / timescale, plot_height / ymax))
    origin = (0, 0)
    # draw the boundary of the plot
    print >> out, r'\draw[color=gray] %s %s {%s} %s;' % (
            tikz.point_to_tikz(origin),
            'edge node[color=black,below]',
            '$t$',
            tikz.point_to_tikz((plot_width, 0)))
    print >> out, r'\draw[color=gray] ' + get_segment(
            origin, (0, plot_height))
    # draw the bezier curves hitting the right knots
    for f in (f_a, f_b):
        bchunks = []
        for a, b in iterutils.pairwise(sorted(times)):
            pta = np.array((a, f(a)))
            ptb = np.array((b, f(b)))
            dta = np.array((1, f.deriv(a)))
            dtb = np.array((1, f.deriv(b)))
            bchunk = bezier.create_bchunk_hermite(
                    a, b,
                    pta * plotscale, ptb * plotscale,
                    dta * plotscale, dtb * plotscale)
            bchunks.append(bchunk)
        print >> out, r'\draw[color=gray] ' + get_tikz_bezier(bchunks)
    # draw filled black dots at some intersections
    dot_points = [origin]
    dot_points.append((0, f_a(0)))
    dot_points.append((0, f_b(0)))
    for p in dot_points:
        print >> out, r'\fill[color=black,inner sep=0pt]',
        print >> out, tikz.point_to_tikz(np.array(p) * plotscale),
        print >> out, 'circle (1pt);'
    # draw some text annotations
    pt_txt_pairs = [
            ((0, 0), '0'),
            ]
    for i, (pt, txt) in enumerate(pt_txt_pairs):
        print >> out, r'\node[anchor=east] (%s) at %s {%s};' % (
                'ylabel%d' % i,
                tikz.point_to_tikz(pt),
                txt)
    #
    return out.getvalue().rstrip()
예제 #4
0
 def draw_curve(self):
     scale = np.array((self.plot_width / self.timescale, self.plot_height))
     times = self._get_knot_times()
     bchunks = []
     for a, b in iterutils.pairwise(times):
         pta = np.array((a, self.f(a)))
         ptb = np.array((b, self.f(b)))
         dta = np.array((1, self.f.deriv(a)))
         dtb = np.array((1, self.f.deriv(b)))
         bchunk = bezier.create_bchunk_hermite(a, b, pta * scale, ptb * scale, dta * scale, dtb * scale)
         bchunks.append(bchunk)
     return r"\draw " + get_tikz_bezier(bchunks)
예제 #5
0
파일: 20120516a.py 프로젝트: BIGtigr/xgcode
def get_tikz_body(fs):
    out = StringIO()
    # define user variables
    plot_width = fs.plot_width
    plot_height = fs.plot_height
    timescale = fs.t_max
    # create the function objects
    f_a = JC69.IdentitySlopeInformation(fs.a_mu, fs.a_N)
    f_b = JC69.IdentitySlopeInformation(fs.b_mu, fs.b_N)
    # Define some times for evaluation of the curve.
    times = [timescale * 2**-i for i in range(10)]
    # define some more intermediate values
    ymax = max(f_a(min(times)), f_b(min(times))) * 1.2
    plotscale = np.array((plot_width / timescale, plot_height / ymax))
    origin = (0, 0)
    # draw the boundary of the plot
    print >> out, r'\draw[color=gray] %s %s {%s} %s;' % (
        tikz.point_to_tikz(origin), 'edge node[color=black,below]', '$t$',
        tikz.point_to_tikz((plot_width, 0)))
    print >> out, r'\draw[color=gray] ' + get_segment(origin, (0, plot_height))
    # draw the bezier curves hitting the right knots
    for f in (f_a, f_b):
        bchunks = []
        for a, b in iterutils.pairwise(sorted(times)):
            pta = np.array((a, f(a)))
            ptb = np.array((b, f(b)))
            dta = np.array((1, f.deriv(a)))
            dtb = np.array((1, f.deriv(b)))
            bchunk = bezier.create_bchunk_hermite(a, b, pta * plotscale,
                                                  ptb * plotscale,
                                                  dta * plotscale,
                                                  dtb * plotscale)
            bchunks.append(bchunk)
        print >> out, r'\draw[color=gray] ' + get_tikz_bezier(bchunks)
    # draw filled black dots at some intersections
    dot_points = [origin]
    dot_points.append((0, f_a(0)))
    dot_points.append((0, f_b(0)))
    for p in dot_points:
        print >> out, r'\fill[color=black,inner sep=0pt]',
        print >> out, tikz.point_to_tikz(np.array(p) * plotscale),
        print >> out, 'circle (1pt);'
    # draw some text annotations
    pt_txt_pairs = [
        ((0, 0), '0'),
    ]
    for i, (pt, txt) in enumerate(pt_txt_pairs):
        print >> out, r'\node[anchor=east] (%s) at %s {%s};' % (
            'ylabel%d' % i, tikz.point_to_tikz(pt), txt)
    #
    return out.getvalue().rstrip()
예제 #6
0
 def draw_curve(self):
     scale = np.array((self.plot_width / self.timescale, self.plot_height))
     times = self._get_knot_times()
     bchunks = []
     for a, b in iterutils.pairwise(times):
         pta = np.array((a, self.f(a)))
         ptb = np.array((b, self.f(b)))
         dta = np.array((1, self.f.deriv(a)))
         dtb = np.array((1, self.f.deriv(b)))
         bchunk = bezier.create_bchunk_hermite(a, b, pta * scale,
                                               ptb * scale, dta * scale,
                                               dtb * scale)
         bchunks.append(bchunk)
     return r'\draw ' + get_tikz_bezier(bchunks)
예제 #7
0
파일: pcurve.py 프로젝트: argriffing/xgcode
def get_bezier_path(fp, fv, t_initial, t_final, nchunks):
    """
    @param fp: a python function from t to position vector
    @param fv: a python function from t to velocity vector
    @param t_initial: initial time
    @param t_final: final time
    @param nchunks: use this many chunks in the piecewise approximation
    @return: a BezierPath
    """
    bchunks = []
    npoints = nchunks + 1
    duration = t_final - t_initial
    incr = duration / nchunks
    times = [t_initial + i*incr for i in range(npoints)]
    for ta, tb in iterutils.pairwise(times):
        b = bezier.create_bchunk_hermite(
                ta, tb, fp(ta), fp(tb), fv(ta), fv(tb))
        bchunks.append(b)
    return BezierPath(bchunks)
예제 #8
0
파일: pcurve.py 프로젝트: BIGtigr/xgcode
def get_bezier_path(fp, fv, t_initial, t_final, nchunks):
    """
    @param fp: a python function from t to position vector
    @param fv: a python function from t to velocity vector
    @param t_initial: initial time
    @param t_final: final time
    @param nchunks: use this many chunks in the piecewise approximation
    @return: a BezierPath
    """
    bchunks = []
    npoints = nchunks + 1
    duration = t_final - t_initial
    incr = duration / nchunks
    times = [t_initial + i * incr for i in range(npoints)]
    for ta, tb in iterutils.pairwise(times):
        b = bezier.create_bchunk_hermite(ta, tb, fp(ta), fp(tb), fv(ta),
                                         fv(tb))
        bchunks.append(b)
    return BezierPath(bchunks)
예제 #9
0
 def _draw_beam(self, p_mid, color):
     scale = np.array((self.plot_width / self.timescale, self.plot_height))
     xproj = np.array((1, 0))
     yproj = np.array((0, 1))
     out = StringIO()
     print >> out, r"\path[fill=%s,fill opacity=0.5]" % color
     p_upper = p_mid + 0.5 * self.p_width
     p_lower = p_mid - 0.5 * self.p_width
     t_upper = self.f.inv(p_lower)
     t_lower = self.f.inv(p_upper)
     pta = np.array((t_lower, p_upper))
     ptb = np.array((t_upper, p_lower))
     dta = np.array((1, self.f.deriv(t_lower)))
     dtb = np.array((1, self.f.deriv(t_upper)))
     print >> out, tikz.point_to_tikz(pta * scale * yproj) + " --"
     bchunk = bezier.create_bchunk_hermite(t_lower, t_upper, pta * scale, ptb * scale, dta * scale, dtb * scale)
     pts = tuple(tikz.point_to_tikz(p) for p in bchunk.get_points())
     print >> out, "%s .. controls %s and %s .. %s --" % pts
     print >> out, tikz.point_to_tikz(ptb * scale * xproj) + " --"
     print >> out, tikz.point_to_tikz(pta * scale * xproj) + " --"
     ptc = np.array((t_lower, p_lower))
     print >> out, tikz.point_to_tikz(ptc * scale) + " --"
     print >> out, tikz.point_to_tikz(ptb * scale * yproj) + " -- cycle;"
     return out.getvalue().rstrip()
예제 #10
0
def get_tikz_body(fs):
    out = StringIO()
    # define user variables
    plot_width = fs.plot_width
    plot_height = fs.plot_height
    timescale = fs.t_max
    fast_mu = fs.fast_mu
    slow_mu = fs.slow_mu
    if fs.info_identity_slope:
        f_fast = JC69.IdentitySlopeInformation(fast_mu)
        f_slow = JC69.IdentitySlopeInformation(slow_mu)
    elif fs.info_mi:
        f_fast = JC69.MutualInformation(fast_mu)
        f_slow = JC69.MutualInformation(slow_mu)
    elif fs.info_fi:
        #f_fast = JC69.FisherInformationTheano(fast_mu)
        #f_slow = JC69.FisherInformationTheano(slow_mu)
        f_fast = JC69.FisherInformation(fast_mu)
        f_slow = JC69.FisherInformation(slow_mu)
    # Define some times for evaluation of the curve.
    times = [timescale * 2**-i for i in range(10)]
    if fs.info_identity_slope:
        # Compute the intersection time.
        t_x = math.log(fast_mu / slow_mu) / (fast_mu - slow_mu)
        times.extend([t_x / 2, t_x, (t_x + timescale) / 2])
    # define some more intermediate values
    ymax = max(f_fast(min(times)), f_slow(min(times))) * 1.2
    plotscale = np.array((plot_width / timescale, plot_height / ymax))
    origin = (0, 0)
    # draw the boundary of the plot
    print >> out, r'\draw[color=gray] %s %s {%s} %s;' % (
        tikz.point_to_tikz(origin), 'edge node[color=black,below]', '$t$',
        tikz.point_to_tikz((plot_width, 0)))
    print >> out, r'\draw[color=gray] ' + get_segment(origin, (0, plot_height))
    # draw the bezier curves hitting the right knots
    for f in (f_slow, f_fast):
        bchunks = []
        for a, b in iterutils.pairwise(sorted(times)):
            pta = np.array((a, f(a)))
            ptb = np.array((b, f(b)))
            dta = np.array((1, f.deriv(a)))
            dtb = np.array((1, f.deriv(b)))
            bchunk = bezier.create_bchunk_hermite(a, b, pta * plotscale,
                                                  ptb * plotscale,
                                                  dta * plotscale,
                                                  dtb * plotscale)
            bchunks.append(bchunk)
        print >> out, r'\draw[color=gray] ' + get_tikz_bezier(bchunks)
    # draw filled black dots at some intersections
    dot_points = [origin]
    if not fs.info_fi:
        dot_points.append((0, f_fast(0)))
        dot_points.append((0, f_slow(0)))
    if fs.info_identity_slope:
        dot_points.append((t_x, f_slow(t_x)))
    for p in dot_points:
        print >> out, r'\fill[color=black,inner sep=0pt]',
        print >> out, tikz.point_to_tikz(np.array(p) * plotscale),
        print >> out, 'circle (1pt);'
    # draw some text annotations
    pt_txt_pairs = [
        ((0, 0), '0'),
    ]
    for i, (pt, txt) in enumerate(pt_txt_pairs):
        print >> out, r'\node[anchor=east] (%s) at %s {%s};' % (
            'ylabel%d' % i, tikz.point_to_tikz(pt), txt)
    #
    return out.getvalue().rstrip()
예제 #11
0
def get_tikz_body(fs):
    out = StringIO()
    # predefined variables
    mu = 1.0
    origin = (0, 0)
    f = MyCurve(mu)
    # define user variables
    plot_width = fs.plot_width
    plot_height = fs.plot_height
    timescale = fs.t_max
    ta = f.inv(fs.p_high) / timescale
    tb = f.inv(fs.p_low) / timescale
    # validate
    if tb <= ta:
        raise ValueError('interval lower bound should be below upper bound')
    plotscale = np.array((plot_width, plot_height))
    # draw the boundary of the plot
    print >> out, r'\draw[color=gray] ' + get_segment(
            origin, (plot_width, 0))
    print >> out, r'\draw[color=gray] ' + get_segment(
            origin, (0, plot_height))
    print >> out, r'\draw[color=gray] ' + get_segment(
            (0,plot_height), (plot_width, plot_height))
    print >> out, r'\draw[dotted,color=gray] ' + get_segment(
            (0,0.25*plot_height), (plot_width, 0.25*plot_height))
    # define times of interest
    t0 = 0
    tx = (tb + 1) / 2
    t1 = 1
    # draw the bezier curve hitting the right knots
    scale = np.array((plot_width / timescale, plot_height))
    times = (t0, ta, tb, tx, t1)
    bchunks = []
    for a, b in iterutils.pairwise(times):
        a = timescale * a
        b = timescale * b
        pta = np.array((a, f(a)))
        ptb = np.array((b, f(b)))
        dta = np.array((1, f.deriv(a)))
        dtb = np.array((1, f.deriv(b)))
        bchunk = bezier.create_bchunk_hermite(
                a, b,
                pta * scale, ptb * scale,
                dta * scale, dtb * scale)
        bchunks.append(bchunk)
    print >> out, r'\draw[color=gray] ' + get_tikz_bezier(bchunks)
    # redraw a piece of the curve
    a = timescale * ta
    b = timescale * tb
    pta = np.array((a, f(a)))
    ptb = np.array((b, f(b)))
    dta = np.array((1, f.deriv(a)))
    dtb = np.array((1, f.deriv(b)))
    bchunk = bezier.create_bchunk_hermite(
            a, b,
            pta * scale, ptb * scale,
            dta * scale, dtb * scale)
    pts = tuple(tikz.point_to_tikz(p) for p in bchunk.get_points())
    print >> out, r'\draw[color=black] %s .. controls %s and %s .. %s;' % pts
    """
    print >> out, r'\draw[color=black] ' + get_segment(
            pta * scale, ptb * scale)
    """
    # draw the projections of the secant onto the axes
    xproj = np.array((1, 0))
    yproj = np.array((0, 1))
    print >> out, r'\draw[color=black] ' + get_segment(
            pta * scale * xproj, ptb * scale * xproj)
    print >> out, r'\draw[color=black] ' + get_segment(
            pta * scale * yproj, ptb * scale * yproj)
    print >> out, r'\draw[dotted,color=gray] ' + get_segment(
            pta * scale, pta * scale * xproj)
    print >> out, r'\draw[dotted,color=gray] ' + get_segment(
            ptb * scale, ptb * scale * xproj)
    print >> out, r'\draw[dotted,color=gray] ' + get_segment(
            pta * scale, pta * scale * yproj)
    print >> out, r'\draw[dotted,color=gray] ' + get_segment(
            ptb * scale, ptb * scale * yproj)
    # draw filled black dots at some intersections
    dot_points = [
            origin,
            (0, plot_height),
            (0, 0.25 * plot_height),
            pta * scale,
            ptb * scale,
            pta * scale * xproj,
            pta * scale * yproj,
            ptb * scale * xproj,
            ptb * scale * yproj,
            ]
    for dot_point in dot_points:
        print >> out, r'\fill[color=black,inner sep=0pt]',
        print >> out, tikz.point_to_tikz(dot_point),
        print >> out, 'circle (1pt);'
    # draw braces
    brace_terms = [
        r'\draw[decorate,decoration={brace},yshift=-2pt] ',
        get_seg(ptb * scale * xproj, pta * scale * xproj),
        r'node [black,midway,yshift=-2pt]',
        #r'{$\Delta t_{\text{divergence}}$};']
        r'{$\Delta t$};']
    print >> out, ' '.join(brace_terms)
    brace_terms = [
        r'\draw[decorate,decoration={brace},xshift=-2pt] ',
        get_seg(ptb * scale * yproj, pta * scale * yproj),
        r'node [black,midway,xshift=-2pt]',
        #r'{$\Delta P_{\text{identity}}$};']
        r'{$\Delta p$};']
    print >> out, ' '.join(brace_terms)
    # draw some text annotations
    pt_txt_pairs = [
            ((0, 0), '0'),
            ((0, 0.25 * plot_height), r'$\frac{1}{4}$'),
            ((0, 1.0 * plot_height), '1')]
    for i, (pt, txt) in enumerate(pt_txt_pairs):
        print >> out, r'\node[anchor=east] (%s) at %s {%s};' % (
                'ylabel%d' % i,
                tikz.point_to_tikz(pt),
                txt)
    #
    return out.getvalue().rstrip()
예제 #12
0
 def get_bezier_path(self):
     b = bezier.create_bchunk_hermite(
             self.t_initial, self.t_final,
             self.fp(self.t_initial), self.fp(self.t_final),
             self.fv(self.t_initial), self.fv(self.t_final))
     return pcurve.BezierPath([b])
예제 #13
0
파일: 20120515a.py 프로젝트: BIGtigr/xgcode
def get_tikz_body(fs):
    out = StringIO()
    # predefined variables
    mu = 1.0
    origin = (0, 0)
    f = MyCurve(mu)
    # define user variables
    plot_width = fs.plot_width
    plot_height = fs.plot_height
    timescale = fs.t_max
    ta = f.inv(fs.p_high) / timescale
    tb = f.inv(fs.p_low) / timescale
    # validate
    if tb <= ta:
        raise ValueError('interval lower bound should be below upper bound')
    plotscale = np.array((plot_width, plot_height))
    # draw the boundary of the plot
    print >> out, r'\draw[color=gray] ' + get_segment(origin, (plot_width, 0))
    print >> out, r'\draw[color=gray] ' + get_segment(origin, (0, plot_height))
    print >> out, r'\draw[color=gray] ' + get_segment(
        (0, plot_height), (plot_width, plot_height))
    print >> out, r'\draw[dotted,color=gray] ' + get_segment(
        (0, 0.25 * plot_height), (plot_width, 0.25 * plot_height))
    # define times of interest
    t0 = 0
    tx = (tb + 1) / 2
    t1 = 1
    # draw the bezier curve hitting the right knots
    scale = np.array((plot_width / timescale, plot_height))
    times = (t0, ta, tb, tx, t1)
    bchunks = []
    for a, b in iterutils.pairwise(times):
        a = timescale * a
        b = timescale * b
        pta = np.array((a, f(a)))
        ptb = np.array((b, f(b)))
        dta = np.array((1, f.deriv(a)))
        dtb = np.array((1, f.deriv(b)))
        bchunk = bezier.create_bchunk_hermite(a, b, pta * scale, ptb * scale,
                                              dta * scale, dtb * scale)
        bchunks.append(bchunk)
    print >> out, r'\draw[color=gray] ' + get_tikz_bezier(bchunks)
    # redraw a piece of the curve
    a = timescale * ta
    b = timescale * tb
    pta = np.array((a, f(a)))
    ptb = np.array((b, f(b)))
    dta = np.array((1, f.deriv(a)))
    dtb = np.array((1, f.deriv(b)))
    bchunk = bezier.create_bchunk_hermite(a, b, pta * scale, ptb * scale,
                                          dta * scale, dtb * scale)
    pts = tuple(tikz.point_to_tikz(p) for p in bchunk.get_points())
    print >> out, r'\draw[color=black] %s .. controls %s and %s .. %s;' % pts
    """
    print >> out, r'\draw[color=black] ' + get_segment(
            pta * scale, ptb * scale)
    """
    # draw the projections of the secant onto the axes
    xproj = np.array((1, 0))
    yproj = np.array((0, 1))
    print >> out, r'\draw[color=black] ' + get_segment(pta * scale * xproj,
                                                       ptb * scale * xproj)
    print >> out, r'\draw[color=black] ' + get_segment(pta * scale * yproj,
                                                       ptb * scale * yproj)
    print >> out, r'\draw[dotted,color=gray] ' + get_segment(
        pta * scale, pta * scale * xproj)
    print >> out, r'\draw[dotted,color=gray] ' + get_segment(
        ptb * scale, ptb * scale * xproj)
    print >> out, r'\draw[dotted,color=gray] ' + get_segment(
        pta * scale, pta * scale * yproj)
    print >> out, r'\draw[dotted,color=gray] ' + get_segment(
        ptb * scale, ptb * scale * yproj)
    # draw filled black dots at some intersections
    dot_points = [
        origin,
        (0, plot_height),
        (0, 0.25 * plot_height),
        pta * scale,
        ptb * scale,
        pta * scale * xproj,
        pta * scale * yproj,
        ptb * scale * xproj,
        ptb * scale * yproj,
    ]
    for dot_point in dot_points:
        print >> out, r'\fill[color=black,inner sep=0pt]',
        print >> out, tikz.point_to_tikz(dot_point),
        print >> out, 'circle (1pt);'
    # draw braces
    brace_terms = [
        r'\draw[decorate,decoration={brace},yshift=-2pt] ',
        get_seg(ptb * scale * xproj, pta * scale * xproj),
        r'node [black,midway,yshift=-2pt]',
        #r'{$\Delta t_{\text{divergence}}$};']
        r'{$\Delta t$};'
    ]
    print >> out, ' '.join(brace_terms)
    brace_terms = [
        r'\draw[decorate,decoration={brace},xshift=-2pt] ',
        get_seg(ptb * scale * yproj, pta * scale * yproj),
        r'node [black,midway,xshift=-2pt]',
        #r'{$\Delta P_{\text{identity}}$};']
        r'{$\Delta p$};'
    ]
    print >> out, ' '.join(brace_terms)
    # draw some text annotations
    pt_txt_pairs = [((0, 0), '0'), ((0, 0.25 * plot_height), r'$\frac{1}{4}$'),
                    ((0, 1.0 * plot_height), '1')]
    for i, (pt, txt) in enumerate(pt_txt_pairs):
        print >> out, r'\node[anchor=east] (%s) at %s {%s};' % (
            'ylabel%d' % i, tikz.point_to_tikz(pt), txt)
    #
    return out.getvalue().rstrip()
예제 #14
0
def get_tikz_body(fs):
    out = StringIO()
    # define user variables
    plot_width = fs.plot_width
    plot_height = fs.plot_height
    timescale = fs.t_max
    fast_mu = fs.fast_mu
    slow_mu = fs.slow_mu
    if fs.info_identity_slope:
        f_fast = JC69.IdentitySlopeInformation(fast_mu)
        f_slow = JC69.IdentitySlopeInformation(slow_mu)
    elif fs.info_mi:
        f_fast = JC69.MutualInformation(fast_mu)
        f_slow = JC69.MutualInformation(slow_mu)
    elif fs.info_fi:
        #f_fast = JC69.FisherInformationTheano(fast_mu)
        #f_slow = JC69.FisherInformationTheano(slow_mu)
        f_fast = JC69.FisherInformation(fast_mu)
        f_slow = JC69.FisherInformation(slow_mu)
    # Define some times for evaluation of the curve.
    times = [timescale*2**-i for i in range(10)]
    if fs.info_identity_slope:
        # Compute the intersection time.
        t_x = math.log(fast_mu / slow_mu) / (fast_mu - slow_mu)
        times.extend([t_x / 2, t_x, (t_x + timescale)/2])
    # define some more intermediate values
    ymax = max(f_fast(min(times)), f_slow(min(times))) * 1.2
    plotscale = np.array((plot_width / timescale, plot_height / ymax))
    origin = (0, 0)
    # draw the boundary of the plot
    print >> out, r'\draw[color=gray] %s %s {%s} %s;' % (
            tikz.point_to_tikz(origin),
            'edge node[color=black,below]',
            '$t$',
            tikz.point_to_tikz((plot_width, 0)))
    print >> out, r'\draw[color=gray] ' + get_segment(
            origin, (0, plot_height))
    # draw the bezier curves hitting the right knots
    for f in (f_slow, f_fast):
        bchunks = []
        for a, b in iterutils.pairwise(sorted(times)):
            pta = np.array((a, f(a)))
            ptb = np.array((b, f(b)))
            dta = np.array((1, f.deriv(a)))
            dtb = np.array((1, f.deriv(b)))
            bchunk = bezier.create_bchunk_hermite(
                    a, b,
                    pta * plotscale, ptb * plotscale,
                    dta * plotscale, dtb * plotscale)
            bchunks.append(bchunk)
        print >> out, r'\draw[color=gray] ' + get_tikz_bezier(bchunks)
    # draw filled black dots at some intersections
    dot_points = [origin]
    if not fs.info_fi:
        dot_points.append((0, f_fast(0)))
        dot_points.append((0, f_slow(0)))
    if fs.info_identity_slope:
        dot_points.append((t_x, f_slow(t_x)))
    for p in dot_points:
        print >> out, r'\fill[color=black,inner sep=0pt]',
        print >> out, tikz.point_to_tikz(np.array(p) * plotscale),
        print >> out, 'circle (1pt);'
    # draw some text annotations
    pt_txt_pairs = [
            ((0, 0), '0'),
            ]
    for i, (pt, txt) in enumerate(pt_txt_pairs):
        print >> out, r'\node[anchor=east] (%s) at %s {%s};' % (
                'ylabel%d' % i,
                tikz.point_to_tikz(pt),
                txt)
    #
    return out.getvalue().rstrip()