def plot3d(self, ztail=0, zhead=0, **kwds): """ Takes 2D plot and places it in 3D. EXAMPLES:: sage: A = arrow((0,0),(1,1))[0].plot3d() sage: A.jmol_repr(A.testing_render_params())[0] 'draw line_1 diameter 2 arrow {0.0 0.0 0.0} {1.0 1.0 0.0} ' Note that we had to index the arrow to get the Arrow graphics primitive. We can also change the height via the plot3d method of Graphics, but only as a whole:: sage: A = arrow((0,0),(1,1)).plot3d(3) sage: A.jmol_repr(A.testing_render_params())[0][0] 'draw line_1 diameter 2 arrow {0.0 0.0 3.0} {1.0 1.0 3.0} ' Optional arguments place both the head and tail outside the `xy`-plane, but at different heights. This must be done on the graphics primitive obtained by indexing:: sage: A=arrow((0,0),(1,1))[0].plot3d(3,4) sage: A.jmol_repr(A.testing_render_params())[0] 'draw line_1 diameter 2 arrow {0.0 0.0 3.0} {1.0 1.0 4.0} ' """ from sage.plot.plot3d.shapes2 import line3d options = self._plot3d_options() options.update(kwds) return line3d([(self.xtail, self.ytail, ztail), (self.xhead, self.yhead, zhead)], arrow_head=True, **options)
def plot3d(self, z=0, **kwds): """ Returns a 3D plot (Jmol) of the Bezier path. Since a ``BezierPath`` primitive contains only `x,y` coordinates, the path will be drawn in some plane (default is `z=0`). To create a Bezier path with nonzero (and nonidentical) `z` coordinates in the path and control points, use the function :func:`~sage.plot.plot3d.shapes2.bezier3d` instead of :func:`bezier_path`. EXAMPLES:: sage: b = bezier_path([[(0,0),(0,1),(1,0)]]) sage: A = b.plot3d() sage: B = b.plot3d(z=2) sage: A+B :: sage: bezier3d([[(0,0,0),(1,0,0),(0,1,0),(0,1,1)]]) """ from sage.plot.plot3d.shapes2 import bezier3d options = self._plot3d_options() options.update(kwds) return bezier3d([[(x, y, 0) for x, y in self.path[i]] for i in range(len(self.path))], **options)
def plot3d(self, ztail=0, zhead=0, **kwds): """ Takes 2D plot and places it in 3D. EXAMPLES:: sage: A = arrow((0,0),(1,1))[0].plot3d() sage: A.jmol_repr(A.testing_render_params())[0] 'draw line_1 diameter 2 arrow {0.0 0.0 0.0} {1.0 1.0 0.0} ' Note that we had to index the arrow to get the Arrow graphics primitive. We can also change the height via the :meth:`Graphics.plot3d` method, but only as a whole:: sage: A = arrow((0,0),(1,1)).plot3d(3) sage: A.jmol_repr(A.testing_render_params())[0][0] 'draw line_1 diameter 2 arrow {0.0 0.0 3.0} {1.0 1.0 3.0} ' Optional arguments place both the head and tail outside the `xy`-plane, but at different heights. This must be done on the graphics primitive obtained by indexing:: sage: A=arrow((0,0),(1,1))[0].plot3d(3,4) sage: A.jmol_repr(A.testing_render_params())[0] 'draw line_1 diameter 2 arrow {0.0 0.0 3.0} {1.0 1.0 4.0} ' """ from sage.plot.plot3d.shapes2 import line3d options = self._plot3d_options() options.update(kwds) return line3d([(self.xtail, self.ytail, ztail), (self.xhead, self.yhead, zhead)], arrow_head=True, **options)
def plot3d(self, z=0, **kwds): """ Plots a 2D polygon in 3D, with default height zero. INPUT: - ``z`` - optional 3D height above `xy`-plane, or a list of heights corresponding to the list of 2D polygon points. EXAMPLES: A pentagon:: sage: polygon([(cos(t), sin(t)) for t in srange(0, 2*pi, 2*pi/5)]).plot3d() Graphics3d Object Showing behavior of the optional parameter z:: sage: P = polygon([(0,0), (1,2), (0,1), (-1,2)]) sage: p = P[0]; p Polygon defined by 4 points sage: q = p.plot3d() sage: q.obj_repr(q.testing_render_params())[2] ['v 0 0 0', 'v 1 2 0', 'v 0 1 0', 'v -1 2 0'] sage: r = p.plot3d(z=3) sage: r.obj_repr(r.testing_render_params())[2] ['v 0 0 3', 'v 1 2 3', 'v 0 1 3', 'v -1 2 3'] sage: s = p.plot3d(z=[0,1,2,3]) sage: s.obj_repr(s.testing_render_params())[2] ['v 0 0 0', 'v 1 2 1', 'v 0 1 2', 'v -1 2 3'] TESTS: Heights passed as a list should have same length as number of points:: sage: P = polygon([(0,0), (1,2), (0,1), (-1,2)]) sage: p = P[0] sage: q = p.plot3d(z=[2,-2]) Traceback (most recent call last): ... ValueError: Incorrect number of heights given """ from sage.plot.plot3d.index_face_set import IndexFaceSet options = self._plot3d_options() options.update(kwds) zdata = [] if isinstance(z, list): zdata = z else: zdata = [z] * len(self.xdata) if len(zdata) == len(self.xdata): return IndexFaceSet( [[(x, y, z) for x, y, z in zip(self.xdata, self.ydata, zdata)]], **options) else: raise ValueError('Incorrect number of heights given')
def plot3d(self, z=0, **kwds): """ Plots a 2D polygon in 3D, with default height zero. INPUT: - ``z`` - optional 3D height above `xy`-plane, or a list of heights corresponding to the list of 2D polygon points. EXAMPLES: A pentagon:: sage: polygon([(cos(t), sin(t)) for t in srange(0, 2*pi, 2*pi/5)]).plot3d() Graphics3d Object Showing behavior of the optional parameter z:: sage: P = polygon([(0,0), (1,2), (0,1), (-1,2)]) sage: p = P[0]; p Polygon defined by 4 points sage: q = p.plot3d() sage: q.obj_repr(q.testing_render_params())[2] ['v 0 0 0', 'v 1 2 0', 'v 0 1 0', 'v -1 2 0'] sage: r = p.plot3d(z=3) sage: r.obj_repr(r.testing_render_params())[2] ['v 0 0 3', 'v 1 2 3', 'v 0 1 3', 'v -1 2 3'] sage: s = p.plot3d(z=[0,1,2,3]) sage: s.obj_repr(s.testing_render_params())[2] ['v 0 0 0', 'v 1 2 1', 'v 0 1 2', 'v -1 2 3'] TESTS: Heights passed as a list should have same length as number of points:: sage: P = polygon([(0,0), (1,2), (0,1), (-1,2)]) sage: p = P[0] sage: q = p.plot3d(z=[2,-2]) Traceback (most recent call last): ... ValueError: Incorrect number of heights given """ from sage.plot.plot3d.index_face_set import IndexFaceSet options = self._plot3d_options() options.update(kwds) zdata=[] if isinstance(z, list): zdata=z else: zdata=[z]*len(self.xdata) if len(zdata)==len(self.xdata): return IndexFaceSet([[(x, y, z) for x, y, z in zip(self.xdata, self.ydata, zdata)]], **options) else: raise ValueError('Incorrect number of heights given')
def plot3d(self, z=0, **kwds): """ Plots a 2D line in 3D, with default height zero. EXAMPLES:: sage: E = EllipticCurve('37a').plot(thickness=5).plot3d() sage: F = EllipticCurve('37a').plot(thickness=5).plot3d(z=2) sage: E + F # long time (5s on sage.math, 2012) """ from sage.plot.plot3d.shapes2 import line3d options = self._plot3d_options() options.update(kwds) return line3d([(x, y, z) for x, y in zip(self.xdata, self.ydata)], **options)
def plot3d(self, **kwds): """ Plots 2D text in 3D. EXAMPLES:: sage: T = text("ABC",(1,1)) sage: t = T[0] sage: s=t.plot3d() sage: s.jmol_repr(s.testing_render_params())[0][2] 'label "ABC"' sage: s._trans (1.0, 1.0, 0) """ from sage.plot.plot3d.shapes2 import text3d options = self._plot3d_options() options.update(kwds) return text3d(self.string, (self.x, self.y, 0), **options)
def plot3d(self, z=0, **kwds): """ Returns a 3D plot (Jmol) of the Bezier path. Since a ``BezierPath`` primitive contains only `x,y` coordinates, the path will be drawn in some plane (default is `z=0`). To create a Bezier path with nonzero (and nonidentical) `z` coordinates in the path and control points, use the function :func:`~sage.plot.plot3d.shapes2.bezier3d` instead of :func:`bezier_path`. EXAMPLES:: sage: b = bezier_path([[(0,0),(0,1),(1,0)]]) sage: A = b.plot3d() sage: B = b.plot3d(z=2) sage: A + B Graphics3d Object .. PLOT:: b = bezier_path([[(0,0),(0,1),(1,0)]]) A = b.plot3d() B = b.plot3d(z=2) sphinx_plot(A + B) :: sage: bezier3d([[(0,0,0),(1,0,0),(0,1,0),(0,1,1)]]) Graphics3d Object .. PLOT:: sphinx_plot(bezier3d([[(0,0,0),(1,0,0),(0,1,0),(0,1,1)]])) """ from sage.plot.plot3d.shapes2 import bezier3d options = self._plot3d_options() options.update(kwds) return bezier3d([[(x,y,0) for x,y in self.path[i]] for i in range(len(self.path))], **options)
def plot3d(self, z=0, **kwds): """ Plots a two-dimensional point in 3-D, with default height zero. INPUT: - ``z`` - optional 3D height above `xy`-plane. May be a list if self is a list of points. EXAMPLES: One point:: sage: A=point((1,1)) sage: a=A[0];a Point set defined by 1 point(s) sage: b=a.plot3d() One point with a height:: sage: A=point((1,1)) sage: a=A[0];a Point set defined by 1 point(s) sage: b=a.plot3d(z=3) sage: b.loc[2] 3.0 Multiple points:: sage: P=point([(0,0), (1,1)]) sage: p=P[0]; p Point set defined by 2 point(s) sage: q=p.plot3d(size=22) Multiple points with different heights:: sage: P=point([(0,0), (1,1)]) sage: p=P[0] sage: q=p.plot3d(z=[2,3]) sage: q.all[0].loc[2] 2.0 sage: q.all[1].loc[2] 3.0 Note that keywords passed must be valid point3d options:: sage: A=point((1,1),size=22) sage: a=A[0];a Point set defined by 1 point(s) sage: b=a.plot3d() sage: b.size 22 sage: b=a.plot3d(pointsize=23) # only 2D valid option sage: b.size 22 sage: b=a.plot3d(size=23) # correct keyword sage: b.size 23 TESTS: Heights passed as a list should have same length as number of points:: sage: P=point([(0,0), (1,1), (2,3)]) sage: p=P[0] sage: q=p.plot3d(z=2) sage: q.all[1].loc[2] 2.0 sage: q=p.plot3d(z=[2,-2]) Traceback (most recent call last): ... ValueError: Incorrect number of heights given """ from sage.plot.plot3d.base import Graphics3dGroup from sage.plot.plot3d.shapes2 import point3d options = self._plot3d_options() options.update(kwds) zdata = [] if isinstance(z, list): zdata = z else: zdata = [z] * len(self.xdata) if len(zdata) == len(self.xdata): all = [ point3d(list(zip(self.xdata, self.ydata, zdata)), **options) ] if len(all) == 1: return all[0] else: return Graphics3dGroup(all) else: raise ValueError('Incorrect number of heights given')
def plot(self, **kwds): """ Returns a graphics object representing the (di)graph. INPUT: The options accepted by this method are to be found in the documentation of the :mod:`sage.graphs.graph_plot` module, and the :meth:`~sage.plot.graphics.Graphics.show` method. .. NOTE:: See :mod:`the module's documentation <sage.graphs.graph_plot>` for information on default values of this method. We can specify some pretty precise plotting of familiar graphs:: sage: from math import sin, cos, pi sage: P = graphs.PetersenGraph() sage: d = {'#FF0000':[0,5], '#FF9900':[1,6], '#FFFF00':[2,7], '#00FF00':[3,8], '#0000FF':[4,9]} sage: pos_dict = {} sage: for i in range(5): ... x = float(cos(pi/2 + ((2*pi)/5)*i)) ... y = float(sin(pi/2 + ((2*pi)/5)*i)) ... pos_dict[i] = [x,y] ... sage: for i in range(10)[5:]: ... x = float(0.5*cos(pi/2 + ((2*pi)/5)*i)) ... y = float(0.5*sin(pi/2 + ((2*pi)/5)*i)) ... pos_dict[i] = [x,y] ... sage: pl = P.graphplot(pos=pos_dict, vertex_colors=d) sage: pl.show() Here are some more common graphs with typical options:: sage: C = graphs.CubeGraph(8) sage: P = C.graphplot(vertex_labels=False, vertex_size=0, graph_border=True) sage: P.show() sage: G = graphs.HeawoodGraph().copy(sparse=True) sage: for u,v,l in G.edges(): ... G.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')') sage: G.graphplot(edge_labels=True).show() The options for plotting also work with directed graphs:: sage: D = DiGraph( { 0: [1, 10, 19], 1: [8, 2], 2: [3, 6], 3: [19, 4], 4: [17, 5], 5: [6, 15], 6: [7], 7: [8, 14], 8: [9], 9: [10, 13], 10: [11], 11: [12, 18], 12: [16, 13], 13: [14], 14: [15], 15: [16], 16: [17], 17: [18], 18: [19], 19: []}) sage: for u,v,l in D.edges(): ... D.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')') sage: D.graphplot(edge_labels=True, layout='circular').show() This example shows off the coloring of edges:: sage: from sage.plot.colors import rainbow sage: C = graphs.CubeGraph(5) sage: R = rainbow(5) sage: edge_colors = {} sage: for i in range(5): ... edge_colors[R[i]] = [] sage: for u,v,l in C.edges(): ... for i in range(5): ... if u[i] != v[i]: ... edge_colors[R[i]].append((u,v,l)) sage: C.graphplot(vertex_labels=False, vertex_size=0, edge_colors=edge_colors).show() With the ``partition`` option, we can separate out same-color groups of vertices:: sage: D = graphs.DodecahedralGraph() sage: Pi = [[6,5,15,14,7],[16,13,8,2,4],[12,17,9,3,1],[0,19,18,10,11]] sage: D.show(partition=Pi) Loops are also plotted correctly:: sage: G = graphs.PetersenGraph() sage: G.allow_loops(True) sage: G.add_edge(0,0) sage: G.show() :: sage: D = DiGraph({0:[0,1], 1:[2], 2:[3]}, loops=True) sage: D.show() sage: D.show(edge_colors={(0,1,0):[(0,1,None),(1,2,None)],(0,0,0):[(2,3,None)]}) More options:: sage: pos = {0:[0.0, 1.5], 1:[-0.8, 0.3], 2:[-0.6, -0.8], 3:[0.6, -0.8], 4:[0.8, 0.3]} sage: g = Graph({0:[1], 1:[2], 2:[3], 3:[4], 4:[0]}) sage: g.graphplot(pos=pos, layout='spring', iterations=0).plot() Graphics object consisting of 11 graphics primitives sage: G = Graph() sage: P = G.graphplot().plot() sage: P.axes() False sage: G = DiGraph() sage: P = G.graphplot().plot() sage: P.axes() False We can plot multiple graphs:: sage: T = list(graphs.trees(7)) sage: t = T[3] sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot() Graphics object consisting of 14 graphics primitives :: sage: T = list(graphs.trees(7)) sage: t = T[3] sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot() Graphics object consisting of 14 graphics primitives sage: t.set_edge_label(0,1,-7) sage: t.set_edge_label(0,5,3) sage: t.set_edge_label(0,5,99) sage: t.set_edge_label(1,2,1000) sage: t.set_edge_label(3,2,'spam') sage: t.set_edge_label(2,6,3/2) sage: t.set_edge_label(0,4,66) sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}, edge_labels=True).plot() Graphics object consisting of 20 graphics primitives :: sage: T = list(graphs.trees(7)) sage: t = T[3] sage: t.graphplot(layout='tree').show() The tree layout is also useful:: sage: t = DiGraph('JCC???@A??GO??CO??GO??') sage: t.graphplot(layout='tree', tree_root=0, tree_orientation="up").show() More examples:: sage: D = DiGraph({0:[1,2,3], 2:[1,4], 3:[0]}) sage: D.graphplot().show() sage: D = DiGraph(multiedges=True, sparse=True) sage: for i in range(5): ... D.add_edge((i,i+1,'a')) ... D.add_edge((i,i-1,'b')) sage: D.graphplot(edge_labels=True,edge_colors=D._color_by_label()).plot() Graphics object consisting of 34 graphics primitives sage: g = Graph({}, loops=True, multiedges=True, sparse=True) sage: g.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'), ... (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')]) sage: g.graphplot(edge_labels=True, color_by_label=True, edge_style='dashed').plot() Graphics object consisting of 22 graphics primitives The ``edge_style`` option may be provided in the short format too:: sage: g.graphplot(edge_labels=True, color_by_label=True, edge_style='--').plot() Graphics object consisting of 22 graphics primitives TESTS: Make sure that show options work with plot also:: sage: g = Graph({}) sage: g.plot(title='empty graph', axes=True) Graphics object consisting of 0 graphics primitives Check for invalid inputs:: sage: p = graphs.PetersenGraph().plot(egabrag='garbage') Traceback (most recent call last): ... ValueError: Invalid input 'egabrag=garbage' Make sure that no graphics primitive is clipped:: sage: tadpole = Graph({0:[0,1]}).plot() sage: bbox = tadpole.get_minmax_data() sage: for part in tadpole: ....: part_bbox = part.get_minmax_data() ....: assert bbox['xmin'] <= part_bbox['xmin'] <= part_bbox['xmax'] <= bbox['xmax'] ....: assert bbox['ymin'] <= part_bbox['ymin'] <= part_bbox['ymax'] <= bbox['ymax'] """ G = Graphics() options = self._options.copy() options.update(kwds) G._set_extra_kwds(Graphics._extract_kwds_for_show(options)) # Check the arguments for o in options: if o not in graphplot_options and o not in G._extra_kwds: raise ValueError("Invalid input '{}={}'".format(o, options[o])) for comp in self._plot_components.values(): if not isinstance(comp, list): G += comp else: for item in comp: G += item if self._options['graph_border']: xmin = G.xmin() xmax = G.xmax() ymin = G.ymin() ymax = G.ymax() dx = (xmax - xmin) / 10.0 dy = (ymax - ymin) / 10.0 border = (line([(xmin - dx, ymin - dy), (xmin - dx, ymax + dy), (xmax + dx, ymax + dy), (xmax + dx, ymin - dy), (xmin - dx, ymin - dy)], thickness=1.3)) border.axes_range(xmin=(xmin - dx), xmax=(xmax + dx), ymin=(ymin - dy), ymax=(ymax + dy)) G += border G.set_aspect_ratio(1) G.axes(False) return G
def plot3d(self, z=0, **kwds): """ Plots a two-dimensional point in 3-D, with default height zero. INPUT: - ``z`` - optional 3D height above `xy`-plane. May be a list if self is a list of points. EXAMPLES: One point:: sage: A=point((1,1)) sage: a=A[0];a Point set defined by 1 point(s) sage: b=a.plot3d() One point with a height:: sage: A=point((1,1)) sage: a=A[0];a Point set defined by 1 point(s) sage: b=a.plot3d(z=3) sage: b.loc[2] 3.0 Multiple points:: sage: P=point([(0,0), (1,1)]) sage: p=P[0]; p Point set defined by 2 point(s) sage: q=p.plot3d(size=22) Multiple points with different heights:: sage: P=point([(0,0), (1,1)]) sage: p=P[0] sage: q=p.plot3d(z=[2,3]) sage: q.all[0].loc[2] 2.0 sage: q.all[1].loc[2] 3.0 Note that keywords passed must be valid point3d options:: sage: A=point((1,1),size=22) sage: a=A[0];a Point set defined by 1 point(s) sage: b=a.plot3d() sage: b.size 22 sage: b=a.plot3d(pointsize=23) # only 2D valid option sage: b.size 22 sage: b=a.plot3d(size=23) # correct keyword sage: b.size 23 TESTS: Heights passed as a list should have same length as number of points:: sage: P=point([(0,0), (1,1), (2,3)]) sage: p=P[0] sage: q=p.plot3d(z=2) sage: q.all[1].loc[2] 2.0 sage: q=p.plot3d(z=[2,-2]) Traceback (most recent call last): ... ValueError: Incorrect number of heights given """ from sage.plot.plot3d.base import Graphics3dGroup from sage.plot.plot3d.shapes2 import point3d options = self._plot3d_options() options.update(kwds) zdata=[] if isinstance(z, list): zdata=z else: zdata=[z]*len(self.xdata) if len(zdata)==len(self.xdata): all = [point3d([(x, y, z) for x, y, z in zip(self.xdata, self.ydata, zdata)], **options)] if len(all) == 1: return all[0] else: return Graphics3dGroup(all) else: raise ValueError('Incorrect number of heights given')
def plot(self, **kwds): """ Returns a graphics object representing the (di)graph. INPUT: The options accepted by this method are to be found in the documentation of the :mod:`sage.graphs.graph_plot` module, and the :meth:`~sage.plot.graphics.Graphics.show` method. .. NOTE:: See :mod:`the module's documentation <sage.graphs.graph_plot>` for information on default values of this method. We can specify some pretty precise plotting of familiar graphs:: sage: from math import sin, cos, pi sage: P = graphs.PetersenGraph() sage: d = {'#FF0000':[0,5], '#FF9900':[1,6], '#FFFF00':[2,7], '#00FF00':[3,8], '#0000FF':[4,9]} sage: pos_dict = {} sage: for i in range(5): ... x = float(cos(pi/2 + ((2*pi)/5)*i)) ... y = float(sin(pi/2 + ((2*pi)/5)*i)) ... pos_dict[i] = [x,y] ... sage: for i in range(10)[5:]: ... x = float(0.5*cos(pi/2 + ((2*pi)/5)*i)) ... y = float(0.5*sin(pi/2 + ((2*pi)/5)*i)) ... pos_dict[i] = [x,y] ... sage: pl = P.graphplot(pos=pos_dict, vertex_colors=d) sage: pl.show() Here are some more common graphs with typical options:: sage: C = graphs.CubeGraph(8) sage: P = C.graphplot(vertex_labels=False, vertex_size=0, graph_border=True) sage: P.show() sage: G = graphs.HeawoodGraph().copy(sparse=True) sage: for u,v,l in G.edges(): ... G.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')') sage: G.graphplot(edge_labels=True).show() The options for plotting also work with directed graphs:: sage: D = DiGraph( { 0: [1, 10, 19], 1: [8, 2], 2: [3, 6], 3: [19, 4], 4: [17, 5], 5: [6, 15], 6: [7], 7: [8, 14], 8: [9], 9: [10, 13], 10: [11], 11: [12, 18], 12: [16, 13], 13: [14], 14: [15], 15: [16], 16: [17], 17: [18], 18: [19], 19: []}) sage: for u,v,l in D.edges(): ... D.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')') sage: D.graphplot(edge_labels=True, layout='circular').show() This example shows off the coloring of edges:: sage: from sage.plot.colors import rainbow sage: C = graphs.CubeGraph(5) sage: R = rainbow(5) sage: edge_colors = {} sage: for i in range(5): ... edge_colors[R[i]] = [] sage: for u,v,l in C.edges(): ... for i in range(5): ... if u[i] != v[i]: ... edge_colors[R[i]].append((u,v,l)) sage: C.graphplot(vertex_labels=False, vertex_size=0, edge_colors=edge_colors).show() With the ``partition`` option, we can separate out same-color groups of vertices:: sage: D = graphs.DodecahedralGraph() sage: Pi = [[6,5,15,14,7],[16,13,8,2,4],[12,17,9,3,1],[0,19,18,10,11]] sage: D.show(partition=Pi) Loops are also plotted correctly:: sage: G = graphs.PetersenGraph() sage: G.allow_loops(True) sage: G.add_edge(0,0) sage: G.show() :: sage: D = DiGraph({0:[0,1], 1:[2], 2:[3]}, loops=True) sage: D.show() sage: D.show(edge_colors={(0,1,0):[(0,1,None),(1,2,None)],(0,0,0):[(2,3,None)]}) More options:: sage: pos = {0:[0.0, 1.5], 1:[-0.8, 0.3], 2:[-0.6, -0.8], 3:[0.6, -0.8], 4:[0.8, 0.3]} sage: g = Graph({0:[1], 1:[2], 2:[3], 3:[4], 4:[0]}) sage: g.graphplot(pos=pos, layout='spring', iterations=0).plot() Graphics object consisting of 11 graphics primitives sage: G = Graph() sage: P = G.graphplot().plot() sage: P.axes() False sage: G = DiGraph() sage: P = G.graphplot().plot() sage: P.axes() False We can plot multiple graphs:: sage: T = list(graphs.trees(7)) sage: t = T[3] sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot() Graphics object consisting of 14 graphics primitives :: sage: T = list(graphs.trees(7)) sage: t = T[3] sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot() Graphics object consisting of 14 graphics primitives sage: t.set_edge_label(0,1,-7) sage: t.set_edge_label(0,5,3) sage: t.set_edge_label(0,5,99) sage: t.set_edge_label(1,2,1000) sage: t.set_edge_label(3,2,'spam') sage: t.set_edge_label(2,6,3/2) sage: t.set_edge_label(0,4,66) sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}, edge_labels=True).plot() Graphics object consisting of 20 graphics primitives :: sage: T = list(graphs.trees(7)) sage: t = T[3] sage: t.graphplot(layout='tree').show() The tree layout is also useful:: sage: t = DiGraph('JCC???@A??GO??CO??GO??') sage: t.graphplot(layout='tree', tree_root=0, tree_orientation="up").show() More examples:: sage: D = DiGraph({0:[1,2,3], 2:[1,4], 3:[0]}) sage: D.graphplot().show() sage: D = DiGraph(multiedges=True, sparse=True) sage: for i in range(5): ... D.add_edge((i,i+1,'a')) ... D.add_edge((i,i-1,'b')) sage: D.graphplot(edge_labels=True,edge_colors=D._color_by_label()).plot() Graphics object consisting of 34 graphics primitives sage: g = Graph({}, loops=True, multiedges=True, sparse=True) sage: g.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'), ... (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')]) sage: g.graphplot(edge_labels=True, color_by_label=True, edge_style='dashed').plot() Graphics object consisting of 22 graphics primitives The ``edge_style`` option may be provided in the short format too:: sage: g.graphplot(edge_labels=True, color_by_label=True, edge_style='--').plot() Graphics object consisting of 22 graphics primitives TESTS: Make sure that show options work with plot also:: sage: g = Graph({}) sage: g.plot(title='empty graph', axes=True) Graphics object consisting of 0 graphics primitives Check for invalid inputs:: sage: p = graphs.PetersenGraph().plot(egabrag='garbage') Traceback (most recent call last): ... ValueError: Invalid input 'egabrag=garbage' Make sure that no graphics primitive is clipped:: sage: tadpole = Graph({0:[0,1]}).plot() sage: bbox = tadpole.get_minmax_data() sage: for part in tadpole: ....: part_bbox = part.get_minmax_data() ....: assert bbox['xmin'] <= part_bbox['xmin'] <= part_bbox['xmax'] <= bbox['xmax'] ....: assert bbox['ymin'] <= part_bbox['ymin'] <= part_bbox['ymax'] <= bbox['ymax'] """ G = Graphics() options = self._options.copy() options.update(kwds) G._set_extra_kwds(Graphics._extract_kwds_for_show(options)) # Check the arguments for o in options: if o not in graphplot_options and o not in G._extra_kwds: raise ValueError("Invalid input '{}={}'".format(o, options[o])) for comp in self._plot_components.values(): if not isinstance(comp, list): G += comp else: for item in comp: G += item if self._options['graph_border']: xmin = G.xmin() xmax = G.xmax() ymin = G.ymin() ymax = G.ymax() dx = (xmax-xmin)/10.0 dy = (ymax-ymin)/10.0 border = (line([( xmin - dx, ymin - dy), ( xmin - dx, ymax + dy ), ( xmax + dx, ymax + dy ), ( xmax + dx, ymin - dy ), ( xmin - dx, ymin - dy )], thickness=1.3)) border.axes_range(xmin = (xmin - dx), xmax = (xmax + dx), ymin = (ymin - dy), ymax = (ymax + dy)) G += border G.set_aspect_ratio(1) G.axes(False) return G