Пример #1
0
def circle_image(A, B):
    G = Graphics()
    G += circle((0, 0), 1, color='grey')
    from collections import defaultdict
    tmp = defaultdict(int)
    for a in A:
        for j in range(a):
            if gcd(j, a) == 1:
                rational = Rational(j) / Rational(a)
                tmp[(rational.numerator(), rational.denominator())] += 1

    for b in B:
        for j in range(b):
            if gcd(j, b) == 1:
                rational = Rational(j) / Rational(b)
                tmp[(rational.numerator(), rational.denominator())] -= 1
    C = ComplexField()
    for val in tmp:
        if tmp[val] > 0:
            G += text(str(tmp[val]),
                      exp(C(-.2 + 2 * 3.14159 * I * val[0] / val[1])),
                      fontsize=30,
                      axes=False,
                      color="green")
        if tmp[val] < 0:
            G += text(str(abs(tmp[val])),
                      exp(C(.2 + 2 * 3.14159 * I * val[0] / val[1])),
                      fontsize=30,
                      axes=False,
                      color="blue")
    return G
Пример #2
0
    def get_background_graphic(self, **bdry_options):
        r"""
        Return a graphic object that makes the model easier to visualize.
        For the Klein model, the background object is the ideal boundary.

        EXAMPLES::

            sage: circ = HyperbolicPlane().KM().get_background_graphic()
        """
        from sage.plot.circle import circle
        return circle((0,0), 1, axes=False, color='black')
Пример #3
0
    def get_background_graphic(self, **bdry_options):
        r"""
        Return a graphic object that makes the model easier to visualize.
        For the Klein model, the background object is the ideal boundary.

        EXAMPLES::

            sage: circ = HyperbolicPlane().KM().get_background_graphic()
        """
        from sage.plot.circle import circle
        return circle((0, 0), 1, axes=False, color='black')
Пример #4
0
    def plot(self, number=None):
        r"""
        Return a plot of ``self``.

        INPUT:

        - ``number`` -- the number of states to plot

        EXAMPLES::

            sage: G = cellular_automata.GraftalLace([5,1,2,5,4,5,5,0])
            sage: G.evolve(20)
            sage: G.plot()
            Graphics object consisting of 865 graphics primitives
        """
        if number is None:
            number = len(self._states)
        if number > len(self._states):
            for dummy in range(number - len(self._states)):
                self.evolve()

        from sage.plot.circle import circle
        from sage.plot.line import line

        x = len(self._states[:number])
        rad = 0.1
        ret = circle((x, 1), rad, fill=True)
        for i, state in enumerate(self._states[:number]):
            for j, val in enumerate(state):
                if val & 0x4:
                    ret += line([(x + j, -i), (x + j - 1, -i + 1)])
                if val & 0x2:
                    ret += line([(x + j, -i), (x + j, -i + 1)])
                if val & 0x1:
                    ret += line([(x + j, -i), (x + j + 1, -i + 1)])
            for j in range(2 * i + 1):
                ret += circle((x + j, -i), rad, fill=True)
            x -= 1
        ret.set_aspect_ratio(1)
        ret.axes(False)
        return ret
Пример #5
0
def circle_image(A, B):
    G = Graphics()
    G += circle((0, 0), 1, color='black', thickness=3)
    G += circle(
        (0, 0), 1.4, color='black', alpha=0
    )  # This adds an invisible framing circle to the plot, which protects the aspect ratio from being skewed.
    from collections import defaultdict
    tmp = defaultdict(int)
    for a in A:
        for j in range(a):
            if gcd(j, a) == 1:
                rational = Rational(j) / Rational(a)
                tmp[(rational.numerator(), rational.denominator())] += 1

    for b in B:
        for j in range(b):
            if gcd(j, b) == 1:
                rational = Rational(j) / Rational(b)
                tmp[(rational.numerator(), rational.denominator())] -= 1
    C = ComplexField()
    color1 = (41 / 255, 95 / 255, 45 / 255)
    color2 = (0 / 255, 0 / 255, 150 / 255)
    for val in tmp:
        if tmp[val] > 0:
            G += text(str(tmp[val]),
                      exp(C(-.2 + 2 * 3.14159 * I * val[0] / val[1])),
                      fontsize=30,
                      axes=False,
                      color=color1)
        if tmp[val] < 0:
            G += text(str(abs(tmp[val])),
                      exp(C(.2 + 2 * 3.14159 * I * val[0] / val[1])),
                      fontsize=30,
                      axes=False,
                      color=color2)
    return G
Пример #6
0
 def plot(self):
     from sage.functions.trig import sin, cos
     from sage.plot.circle import circle
     from sage.plot.point import point
     from sage.plot.text import text
     p = circle((0,0),1)
     for i in range(self._dimension):
         a = self._alpha[i]
         p += point([cos(2*pi*a),sin(2*pi*a)], color='blue', size=100)
         p += text(r"$\alpha_%i$"%(self._i_alpha[i]+1),
                   [1.2*cos(2*pi*a),1.2*sin(2*pi*a)],fontsize=40)
     for i in range(self._dimension):
         b = self._beta[i]
         p += point([cos(2*pi*b),sin(2*pi*b)], color='red', size=100)
         p += text(r"$\beta_%i$"%(self._i_beta[i]+1),
                   [1.2*cos(2*pi*b),1.2*sin(2*pi*b)],fontsize=40)
     p.show(axes=False, xmin=-1, xmax=1, ymin=-1, ymax=1)
Пример #7
0
    def plot(self, m, pointsize=100, thickness=3, axes=False):
        r"""
        Return 2d graphics object contained in the primal box [-m,m]^d.

        INPUT:

        - ``pointsize``, integer (default:``100``),
        - ``thickness``, integer (default:``3``),
        - ``axes``, bool (default:``False``),

        EXAMPLES::

            sage: from slabbe import BondPercolationSample
            sage: S = BondPercolationSample(0.5,2)
            sage: S.plot(2)           # optional long

        It works in 3d!!::

            sage: S = BondPercolationSample(0.5,3)
            sage: S.plot(3, pointsize=10, thickness=1)     # optional long
            Graphics3d Object

        """
        s = ""
        s += "\\begin{tikzpicture}\n"
        s += "[inner sep=0pt,thick,\n"
        s += "reddot/.style={fill=red,draw=red,circle,minimum size=5pt}]\n"
        s += "\\clip %s rectangle %s;\n" % ((-m - .4, -m - .4),
                                            (m + .4, m + .4))
        G = Graphics()
        for u in self.cluster_in_box(m + 1):
            G += point(u, color='blue', size=pointsize)
        for (u, v) in self.edges_in_box(m + 1):
            G += line((u, v), thickness=thickness, alpha=0.8)
        G += text("p=%.3f" % self._p, (0.5, 1.03),
                  axis_coords=True,
                  color='black')
        G += circle((0, 0), 0.5, color='red', thickness=thickness)
        if self._dimension == 2:
            G.axes(axes)
        return G
Пример #8
0
    def plot(self, m, pointsize=100, thickness=3, axes=False):
        r"""
        Return 2d graphics object contained in the primal box [-m,m]^d.

        INPUT:

        - ``pointsize``, integer (default:``100``),
        - ``thickness``, integer (default:``3``),
        - ``axes``, bool (default:``False``),

        EXAMPLES::

            sage: from slabbe import BondPercolationSample
            sage: S = BondPercolationSample(0.5,2)
            sage: S.plot(2)           # optional long

        It works in 3d!!::

            sage: S = BondPercolationSample(0.5,3)
            sage: S.plot(3, pointsize=10, thickness=1)     # optional long
            Graphics3d Object

        """
        s = ""
        s += "\\begin{tikzpicture}\n"
        s += "[inner sep=0pt,thick,\n"
        s += "reddot/.style={fill=red,draw=red,circle,minimum size=5pt}]\n"
        s += "\\clip %s rectangle %s;\n" % ((-m-.4,-m-.4), (m+.4,m+.4))
        G = Graphics()
        for u in self.cluster_in_box(m+1):
            G += point(u, color='blue', size=pointsize)
        for (u,v) in self.edges_in_box(m+1):
            G += line((u,v), thickness=thickness, alpha=0.8)
        G += text("p=%.3f" % self._p, (0.5,1.03), axis_coords=True, color='black')
        G += circle((0,0), 0.5, color='red', thickness=thickness)
        if self._dimension == 2:
            G.axes(axes)
        return G
Пример #9
0
 def plot(self):
     from sage.functions.trig import sin, cos
     from sage.plot.circle import circle
     from sage.plot.point import point
     from sage.plot.text import text
     p = circle((0, 0), 1)
     for i in range(self._dimension):
         a = self._alpha[i]
         p += point([cos(2 * pi * a), sin(2 * pi * a)],
                    color='blue',
                    size=100)
         p += text(r"$\alpha_%i$" % (self._i_alpha[i] + 1),
                   [1.2 * cos(2 * pi * a), 1.2 * sin(2 * pi * a)],
                   fontsize=40)
     for i in range(self._dimension):
         b = self._beta[i]
         p += point([cos(2 * pi * b), sin(2 * pi * b)],
                    color='red',
                    size=100)
         p += text(r"$\beta_%i$" % (self._i_beta[i] + 1),
                   [1.2 * cos(2 * pi * b), 1.2 * sin(2 * pi * b)],
                   fontsize=40)
     p.show(axes=False, xmin=-1, xmax=1, ymin=-1, ymax=1)
Пример #10
0
def circle_image(A,B):
    G = Graphics()
    G += circle((0,0), 1 , color = 'grey')
    from collections import defaultdict
    tmp = defaultdict(int)
    for a in A:
        for j in range(a):
            if gcd(j,a) == 1:
                rational = Rational(j)/Rational(a)
                tmp[(rational.numerator(),rational.denominator())] += 1
    
    for b in B:
        for j in range(b):
            if gcd(j,b) == 1:
                rational = Rational(j)/Rational(b)
                tmp[(rational.numerator(),rational.denominator())] -= 1
    C = ComplexField()
    for val in tmp:
        if tmp[val] > 0:
            G += text(str(tmp[val]),exp(C(2*3.14159*I*val[0]/val[1])), fontsize = 30, axes = False, color = "green")
        if tmp[val] < 0:
            G += text(str(abs(tmp[val])),exp(C(2*3.14159*I*val[0]/val[1])), fontsize = 30, axes = False, color = "red")
    return G
Пример #11
0
    def plot(self, **kwds):
        r"""
        Plot the initial triangulation associated to ``self``.

        INPUT:

        - ``radius`` - the radius of the disk; by default the length of
          the circle is the number of vertices
        - ``points_color`` - the color of the vertices; default 'black'
        - ``points_size`` - the size of the vertices; default 7
        - ``triangulation_color`` - the color of the arcs; default 'black'
        - ``triangulation_thickness`` - the thickness of the arcs; default 0.5
        - ``shading_color`` - the color of the shading used on neuter
          intervals; default 'lightgray'
        - ``reflections_color`` - the color of the reflection axes; default
          'blue'
        - ``reflections_thickness`` - the thickness of the reflection axes;
          default 1

        EXAMPLES::

            sage: Y = SineGordonYsystem('A',(6,4,3))
            sage: Y.plot()  # long time 2s
            Graphics object consisting of 219 graphics primitives
        """
        # Set up plotting options
        if 'radius' in kwds:
            radius = kwds['radius']
        else:
            radius = ceil(self.r() / (2 * pi))
        points_opts = {}
        if 'points_color' in kwds:
            points_opts['color'] = kwds['points_color']
        else:
            points_opts['color'] = 'black'
        if 'points_size' in kwds:
            points_opts['size'] = kwds['points_size']
        else:
            points_opts['size'] = 7
        triangulation_opts = {}
        if 'triangulation_color' in kwds:
            triangulation_opts['color'] = kwds['triangulation_color']
        else:
            triangulation_opts['color'] = 'black'
        if 'triangulation_thickness' in kwds:
            triangulation_opts['thickness'] = kwds['triangulation_thickness']
        else:
            triangulation_opts['thickness'] = 0.5
        shading_opts = {}
        if 'shading_color' in kwds:
            shading_opts['color'] = kwds['shading_color']
        else:
            shading_opts['color'] = 'lightgray'
        reflections_opts = {}
        if 'reflections_color' in kwds:
            reflections_opts['color'] = kwds['reflections_color']
        else:
            reflections_opts['color'] = 'blue'
        if 'reflections_thickness' in kwds:
            reflections_opts['thickness'] = kwds['reflections_thickness']
        else:
            reflections_opts['thickness'] = 1
        # Helper functions

        def triangle(x):
            (a, b) = sorted(x[:2])
            for p in self.vertices():
                if (p, a) in self.triangulation() or (a, p) in self.triangulation():
                    if (p, b) in self.triangulation() or (b, p) in self.triangulation():
                        if p < a or p > b:
                            return sorted((a, b, p))

        def plot_arc(radius, p, q, **opts):
            # TODO: THIS SHOULD USE THE EXISTING PLOT OF ARCS!
            # plot the arc from p to q differently depending on the type of self
            p = ZZ(p)
            q = ZZ(q)
            t = var('t')
            if p - q in [1, -1]:
                def f(t):
                    return (radius * cos(t), radius * sin(t))
                (p, q) = sorted([p, q])
                angle_p = vertex_to_angle(p)
                angle_q = vertex_to_angle(q)
                return parametric_plot(f(t), (t, angle_q, angle_p), **opts)
            if self.type() == 'A':
                angle_p = vertex_to_angle(p)
                angle_q = vertex_to_angle(q)
                if angle_p < angle_q:
                    angle_p += 2 * pi
                internal_angle = angle_p - angle_q
                if internal_angle > pi:
                    (angle_p, angle_q) = (angle_q + 2 * pi, angle_p)
                    internal_angle = angle_p - angle_q
                angle_center = (angle_p+angle_q) / 2
                hypotenuse = radius / cos(internal_angle / 2)
                radius_arc = hypotenuse * sin(internal_angle / 2)
                center = (hypotenuse * cos(angle_center),
                          hypotenuse * sin(angle_center))
                center_angle_p = angle_p + pi / 2
                center_angle_q = angle_q + 3 * pi / 2

                def f(t):
                    return (radius_arc * cos(t) + center[0],
                            radius_arc * sin(t) + center[1])
                return parametric_plot(f(t), (t, center_angle_p,
                                              center_angle_q), **opts)
            elif self.type() == 'D':
                if p >= q:
                    q += self.r()
                px = -2 * pi * p / self.r() + pi / 2
                qx = -2 * pi * q / self.r() + pi / 2
                arc_radius = (px - qx) / 2
                arc_center = qx + arc_radius

                def f(t):
                    return exp(I * ((cos(t) + I * sin(t)) *
                                    arc_radius + arc_center)) * radius
                return parametric_plot((real_part(f(t)), imag_part(f(t))),
                                       (t, 0, pi), **opts)

        def vertex_to_angle(v):
            # v==0 corresponds to pi/2
            return -2 * pi * RR(v) / self.r() + 5 * pi / 2

        # Begin plotting
        P = Graphics()
        # Shade neuter intervals
        neuter_intervals = [x for x in flatten(self.intervals()[:-1],
                                               max_level=1)
                            if x[2] in ["NR", "NL"]]
        shaded_triangles = map(triangle, neuter_intervals)
        for (p, q, r) in shaded_triangles:
            points = list(plot_arc(radius, p, q)[0])
            points += list(plot_arc(radius, q, r)[0])
            points += list(reversed(plot_arc(radius, p, r)[0]))
            P += polygon2d(points, **shading_opts)
        # Disk boundary
        P += circle((0, 0), radius, **triangulation_opts)
        # Triangulation
        for (p, q) in self.triangulation():
            P += plot_arc(radius, p, q, **triangulation_opts)
        if self.type() == 'D':
            s = radius / 50.0
            P += polygon2d([(s, 5 * s), (s, 7 * s),
                            (3 * s, 5 * s), (3 * s, 7 * s)],
                           color=triangulation_opts['color'])
            P += bezier_path([[(0, 0), (2 * s, 1 * s), (2 * s, 6 * s)],
                              [(2 * s, 10 * s), (s, 20 * s)],
                              [(0, 30 * s), (0, radius)]],
                             **triangulation_opts)
            P += bezier_path([[(0, 0), (-2 * s, 1 * s), (-2 * s, 6 * s)],
                              [(-2 * s, 10 * s), (-s, 20 * s)],
                              [(0, 30 * s), (0, radius)]],
                             **triangulation_opts)
            P += point((0, 0), zorder=len(P), **points_opts)
        # Vertices
        v_points = {x: (radius * cos(vertex_to_angle(x)),
                        radius * sin(vertex_to_angle(x)))
                    for x in self.vertices()}
        for v in v_points:
            P += point(v_points[v], zorder=len(P), **points_opts)
        # Reflection axes
        P += line([(0, 1.1 * radius), (0, -1.1 * radius)],
                  zorder=len(P), **reflections_opts)
        axis_angle = vertex_to_angle(-0.5 * (self.rk() + (1, 1))[1])
        (a, b) = (1.1 * radius * cos(axis_angle),
                  1.1 * radius * sin(axis_angle))
        P += line([(a, b), (-a, -b)], zorder=len(P), **reflections_opts)
        # Wrap up
        P.set_aspect_ratio(1)
        P.axes(False)
        return P
Пример #12
0
    def plot(self, **kwds):
        r"""
        Plot the initial triangulation associated to ``self``.

        INPUT:

        - ``radius`` - the radius of the disk; by default the length of
          the circle is the number of vertices
        - ``points_color`` - the color of the vertices; default 'black'
        - ``points_size`` - the size of the vertices; default 7
        - ``triangulation_color`` - the color of the arcs; default 'black'
        - ``triangulation_thickness`` - the thickness of the arcs; default 0.5
        - ``shading_color`` - the color of the shading used on neuter
          intervals; default 'lightgray'
        - ``reflections_color`` - the color of the reflection axes; default
          'blue'
        - ``reflections_thickness`` - the thickness of the reflection axes;
          default 1

        EXAMPLES::

            sage: Y = SineGordonYsystem('A',(6,4,3));
            sage: Y.plot()      # not tested
        """
        # Set up plotting options
        if 'radius' in kwds:
            radius = kwds['radius']
        else:
            radius = ceil(self.r() / (2 * pi))
        points_opts = {}
        if 'points_color' in kwds:
            points_opts['color'] = kwds['points_color']
        else:
            points_opts['color'] = 'black'
        if 'points_size' in kwds:
            points_opts['size'] = kwds['points_size']
        else:
            points_opts['size'] = 7
        triangulation_opts = {}
        if 'triangulation_color' in kwds:
            triangulation_opts['color'] = kwds['triangulation_color']
        else:
            triangulation_opts['color'] = 'black'
        if 'triangulation_thickness' in kwds:
            triangulation_opts['thickness'] = kwds['triangulation_thickness']
        else:
            triangulation_opts['thickness'] = 0.5
        shading_opts = {}
        if 'shading_color' in kwds:
            shading_opts['color'] = kwds['shading_color']
        else:
            shading_opts['color'] = 'lightgray'
        reflections_opts = {}
        if 'reflections_color' in kwds:
            reflections_opts['color'] = kwds['reflections_color']
        else:
            reflections_opts['color'] = 'blue'
        if 'reflections_thickness' in kwds:
            reflections_opts['thickness'] = kwds['reflections_thickness']
        else:
            reflections_opts['thickness'] = 1
        # Helper functions

        def triangle(x):
            (a, b) = sorted(x[:2])
            for p in self.vertices():
                if (p, a) in self.triangulation() or (a, p) in self.triangulation():
                    if (p, b) in self.triangulation() or (b, p) in self.triangulation():
                        if p < a or p > b:
                            return sorted((a, b, p))

        def plot_arc(radius, p, q, **opts):
            # plot the arc from p to q differently depending on the type of self
            p = ZZ(p)
            q = ZZ(q)
            t = var('t')
            if p - q in [1, -1]:
                def f(t):
                    return (radius * cos(t), radius * sin(t))
                (p, q) = sorted([p, q])
                angle_p = vertex_to_angle(p)
                angle_q = vertex_to_angle(q)
                return parametric_plot(f(t), (t, angle_q, angle_p), **opts)
            if self.type() == 'A':
                angle_p = vertex_to_angle(p)
                angle_q = vertex_to_angle(q)
                if angle_p < angle_q:
                    angle_p += 2 * pi
                internal_angle = angle_p - angle_q
                if internal_angle > pi:
                    (angle_p, angle_q) = (angle_q + 2 * pi, angle_p)
                    internal_angle = angle_p - angle_q
                angle_center = (angle_p+angle_q) / 2
                hypotenuse = radius / cos(internal_angle / 2)
                radius_arc = hypotenuse * sin(internal_angle / 2)
                center = (hypotenuse * cos(angle_center),
                          hypotenuse * sin(angle_center))
                center_angle_p = angle_p + pi / 2
                center_angle_q = angle_q + 3 * pi / 2

                def f(t):
                    return (radius_arc * cos(t) + center[0],
                            radius_arc * sin(t) + center[1])
                return parametric_plot(f(t), (t, center_angle_p,
                                              center_angle_q), **opts)
            elif self.type() == 'D':
                if p >= q:
                    q += self.r()
                px = -2 * pi * p / self.r() + pi / 2
                qx = -2 * pi * q / self.r() + pi / 2
                arc_radius = (px - qx) / 2
                arc_center = qx + arc_radius

                def f(t):
                    return exp(I * ((cos(t) + I * sin(t)) *
                                    arc_radius + arc_center)) * radius
                return parametric_plot((real_part(f(t)), imag_part(f(t))),
                                       (t, 0, pi), **opts)

        def vertex_to_angle(v):
            # v==0 corresponds to pi/2
            return -2 * pi * RR(v) / self.r() + 5 * pi / 2

        # Begin plotting
        P = Graphics()
        # Shade neuter intervals
        neuter_intervals = [x for x in flatten(self.intervals()[:-1],
                                               max_level=1)
                            if x[2] in ["NR", "NL"]]
        shaded_triangles = map(triangle, neuter_intervals)
        for (p, q, r) in shaded_triangles:
            points = list(plot_arc(radius, p, q)[0])
            points += list(plot_arc(radius, q, r)[0])
            points += list(reversed(plot_arc(radius, p, r)[0]))
            P += polygon2d(points, **shading_opts)
        # Disk boundary
        P += circle((0, 0), radius, **triangulation_opts)
        # Triangulation
        for (p, q) in self.triangulation():
            P += plot_arc(radius, p, q, **triangulation_opts)
        if self.type() == 'D':
            s = radius / 50.0
            P += polygon2d([(s, 5 * s), (s, 7 * s),
                            (3 * s, 5 * s), (3 * s, 7 * s)],
                           color=triangulation_opts['color'])
            P += bezier_path([[(0, 0), (2 * s, 1 * s), (2 * s, 6 * s)],
                              [(2 * s, 10 * s), (s, 20 * s)],
                              [(0, 30 * s), (0, radius)]],
                             **triangulation_opts)
            P += bezier_path([[(0, 0), (-2 * s, 1 * s), (-2 * s, 6 * s)],
                              [(-2 * s, 10 * s), (-s, 20 * s)],
                              [(0, 30 * s), (0, radius)]],
                             **triangulation_opts)
            P += point((0, 0), zorder=len(P), **points_opts)
        # Vertices
        v_points = {x: (radius * cos(vertex_to_angle(x)),
                        radius * sin(vertex_to_angle(x)))
                    for x in self.vertices()}
        for v in v_points:
            P += point(v_points[v], zorder=len(P), **points_opts)
        # Reflection axes
        P += line([(0, 1.1 * radius), (0, -1.1 * radius)],
                  zorder=len(P), **reflections_opts)
        axis_angle = vertex_to_angle(-0.5 * (self.rk() + (1, 1))[1])
        (a, b) = (1.1 * radius * cos(axis_angle),
                  1.1 * radius * sin(axis_angle))
        P += line([(a, b), (-a, -b)], zorder=len(P), **reflections_opts)
        # Wrap up
        P.set_aspect_ratio(1)
        P.axes(False)
        return P
Пример #13
0
    def plot(self,
             coordinates='xyz',
             prange=None,
             solution_key=None,
             style='-',
             thickness=1,
             plot_points=1000,
             color='red',
             include_end_point=(True, True),
             end_point_offset=(0.001, 0.001),
             verbose=False,
             label_axes=None,
             plot_horizon=True,
             horizon_color='black',
             fill_BH_region=True,
             BH_region_color='grey',
             display_tangent=False,
             color_tangent='blue',
             plot_points_tangent=10,
             width_tangent=1,
             scale=1,
             aspect_ratio='automatic',
             **kwds):
        r"""
        Plot the geodesic in terms of the coordinates `(t,x,y,z)` deduced from
        the Boyer-Lindquist coordinates `(t,r,\theta,\phi)` via the standard
        polar to Cartesian transformations.

        INPUT:

        - ``coordinates`` -- (default: ``'xyz'``) string indicating which of
          the coordinates `(t,x,y,z)` to use for the plot
        - ``prange`` -- (default: ``None``) range of the affine parameter
          `\lambda` for the plot; if ``None``, the entire range declared during
          the construction of the geodesic is considered
        - ``solution_key`` -- (default: ``None``) string denoting the numerical
          solution to use for the plot; if ``None``, the latest solution
          computed by :meth:`integrate` is used.
        - ``verbose`` -- (default: ``False``) determines whether information is
          printed about the plotting in progress
        - ``plot_horizon``  -- (default: ``True``) determines whether the
          black hole event horizon is drawn
        - ``horizon_color`` -- (default: ``'black'``) color of the event horizon
        - ``fill_BH_region``  -- (default: ``True``) determines whether the
          black hole region is colored (for 2D plots only)
        - ``BH_region_color`` -- (default: ``'grey'``) color of the event horizon
        - ``display_tangent`` -- (default: ``False``) determines whether
          some tangent vectors should also be plotted
        - ``color_tangent`` -- (default: ``blue``) color of the tangent
          vectors when these are plotted
        - ``plot_points_tangent`` -- (default: 10) number of tangent
          vectors to display when these are plotted
        - ``width_tangent`` -- (default: 1) sets the width of the arrows
          representing the tangent vectors
        - ``scale`` -- (default: 1) scale applied to the tangent vectors
          before displaying them

        .. SEEALSO::
            `DifferentiableCurve.plot <https://doc.sagemath.org/html/en/reference/manifolds/sage/manifolds/differentiable/curve.html#sage.manifolds.differentiable.curve.DifferentiableCurve.plot>`_
            for the other input parameters

        OUTPUT:

        - either a 2D graphic oject (2 coordinates specified in the parameter
          ``coordinates``) or a 3D graphic object (3 coordinates in
          ``coordinates``)

        """
        bad_format_msg = ("the argument 'coordinates' must be a string of "
                          "2 or 3 characters among {t,x,y,z} denoting the "
                          "coordinates involved in the plot")
        if len(coordinates) < 2 or len(coordinates) > 3:
            raise ValueError(bad_format_msg)
        map_to_Euclidean = self._spacetime.map_to_Euclidean()
        X4 = map_to_Euclidean.codomain().cartesian_coordinates()
        t, x, y, z = X4[:]
        coord_dict = {'t': t, 'x': x, 'y': y, 'z': z}
        try:
            ambient_coords = [coord_dict[c] for c in coordinates]
        except KeyError:
            raise ValueError(bad_format_msg)
        if ambient_coords[0] == t:
            ambient_coords = ambient_coords[1:] + [t]
        axes_labels = kwds.get('axes_labels')
        if label_axes is None:  # the default
            if len(ambient_coords) == 2:
                label_axes = True
            else:
                label_axes = False  # since three.js has its own mechanism to
                # label axes
                axes_labels = [repr(c) for c in ambient_coords]
        if solution_key is None:
            solution_key = self._latest_solution
        graph = self.plot_integrated(chart=X4,
                                     mapping=map_to_Euclidean,
                                     ambient_coords=ambient_coords,
                                     prange=prange,
                                     interpolation_key=solution_key,
                                     style=style,
                                     thickness=thickness,
                                     plot_points=plot_points,
                                     color=color,
                                     include_end_point=include_end_point,
                                     end_point_offset=end_point_offset,
                                     verbose=verbose,
                                     label_axes=label_axes,
                                     display_tangent=display_tangent,
                                     color_tangent=color_tangent,
                                     plot_points_tangent=plot_points_tangent,
                                     width_tangent=width_tangent,
                                     scale=scale,
                                     aspect_ratio=aspect_ratio,
                                     **kwds)
        if plot_horizon:
            rH = self._spacetime.event_horizon_radius()
            rH = rH.substitute(self._numerical_substitutions())
            if len(ambient_coords) == 3:
                if t in ambient_coords:
                    BLchart = self._spacetime.boyer_lindquist_coordinates()
                    lambda_min = self.domain().lower_bound()
                    lambda_max = self.domain().upper_bound()
                    tmin = BLchart(self(lambda_min))[0]
                    tmax = BLchart(self(lambda_max))[0]
                    graph += Cylinder(rH,
                                      tmax - tmin,
                                      color=horizon_color,
                                      aspect_ratio=aspect_ratio)
                else:
                    graph += sphere(size=rH,
                                    color=horizon_color,
                                    aspect_ratio=aspect_ratio)
            if len(ambient_coords) == 2 and t not in ambient_coords:
                if fill_BH_region:
                    graph += circle((0, 0),
                                    rH,
                                    edgecolor=horizon_color,
                                    thickness=2,
                                    fill=True,
                                    facecolor=BH_region_color,
                                    alpha=0.5)
                else:
                    graph += circle((0, 0),
                                    rH,
                                    edgecolor=horizon_color,
                                    thickness=2)
        if axes_labels:
            graph._extra_kwds['axes_labels'] = axes_labels
        return graph