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
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')
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')
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
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
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)
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
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
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)
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
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
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
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