def plot(self, disks=False, **kwds): gr = plot.point2d(self.dop._singularities(CC), marker='*', color='red', **kwds) gr += plot.line([z.iv().mid() for z in self.vert]) gr.set_aspect_ratio(1) if disks: for step in self: z = step.start.iv().mid() gr += plot.circle((z.real(), z.imag()), step.start.dist_to_sing().lower(), linestyle='dotted', color='red') gr += plot.circle((z.real(), z.imag()), step.length().lower(), linestyle='dashed') return gr
def plot(self, disks=False): gr = plot.point2d(dop_singularities(self.dop, CC), marker='*', size=200, color='red') for step in self: gr += step.plot() gr.set_aspect_ratio(1) if disks: for step in self: z = step.start.iv().mid() gr += plot.circle((z.real(), z.imag()), step.start.dist_to_sing().lower(), linestyle='dotted', color='red') gr += plot.circle((z.real(), z.imag()), step.length().lower(), linestyle='dashed') return gr
def circle_plot(self): pts = [] pi = RR.pi() for angle in self.angles: angle = RR(angle) * pi c = angle.cos() s = angle.sin() if abs(s) < 0.00000001: pts.append((c, s)) else: pts.extend([(c, s), (c, -s)]) P = points(pts, size=100) + circle((0, 0), 1, color='black') P.axes(False) P.set_aspect_ratio(1) return encode_plot(P)
def circle_plot(self): pts = [] pi = RR.pi() for angle in self.angles: angle = RR(angle)*pi c = angle.cos() s = angle.sin() if abs(s) < 0.00000001: pts.append((c,s)) else: pts.extend([(c,s),(c,-s)]) P = points(pts,size=100) + circle((0,0),1,color='black') P.axes(False) P.set_aspect_ratio(1) return encode_plot(P)
def circle_plot(self): pts = [] pi = RR.pi() for angle in self.angles: angle = RR(angle) * pi c = angle.cos() s = angle.sin() if abs(s) < 0.00000001: pts.append((c, s)) else: pts.extend([(c, s), (c, -s)]) P = circle((0, 0), 1, color="black", thickness=2.5) P[0].set_zorder(-1) P += points(pts, size=300, rgbcolor="darkblue") P.axes(False) P.set_aspect_ratio(1) return encode_plot(P, pad=0, pad_inches=None, transparent=True, axes_pad=0.04)
def set_edges(self, **edge_options): """ Sets the edge (or arrow) plotting parameters for the GraphPlot object. This function is called by the constructor but can also be called to make updates to the vertex options of an existing GraphPlot object. Note that the changes are cumulative. EXAMPLES:: 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: GP = g.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed') sage: GP.set_edges(edge_style='solid') sage: GP.plot() sage: GP.set_edges(edge_color='black') sage: GP.plot() sage: d = DiGraph({}, loops=True, multiedges=True, sparse=True) sage: d.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: GP = d.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed') sage: GP.set_edges(edge_style='solid') sage: GP.plot() sage: GP.set_edges(edge_color='black') sage: GP.plot() TESTS:: sage: G = Graph("Fooba") sage: G.show(edge_colors={'red':[(3,6),(2,5)]}) Verify that default edge labels are pretty close to being between the vertices in some cases where they weren't due to truncating division (trac #10124):: sage: test_graphs = graphs.FruchtGraph(), graphs.BullGraph() sage: tol = 0.001 sage: for G in test_graphs: ... E=G.edges() ... for e0, e1, elab in E: ... G.set_edge_label(e0, e1, '%d %d' % (e0, e1)) ... gp = G.graphplot(save_pos=True,edge_labels=True) ... vx = gp._plot_components['vertices'][0].xdata ... vy = gp._plot_components['vertices'][0].ydata ... for elab in gp._plot_components['edge_labels']: ... textobj = elab[0] ... x, y, s = textobj.x, textobj.y, textobj.string ... v0, v1 = map(int, s.split()) ... vn = vector(((x-(vx[v0]+vx[v1])/2.),y-(vy[v0]+vy[v1])/2.)).norm() ... assert vn < tol """ for arg in edge_options: self._options[arg] = edge_options[arg] if 'edge_colors' in edge_options: self._options['color_by_label'] = False # Handle base edge options: thickness, linestyle eoptions={} if 'edge_style' in self._options: eoptions['linestyle'] = self._options['edge_style'] if 'thickness' in self._options: eoptions['thickness'] = self._options['thickness'] # Set labels param to add labels on the fly labels = False if self._options['edge_labels']: labels = True self._plot_components['edge_labels'] = [] # Make dict collection of all edges (keep label and edge color) edges_to_draw = {} if self._options['color_by_label'] or isinstance(self._options['edge_colors'], dict): if self._options['color_by_label']: edge_colors = self._graph._color_by_label() else: edge_colors = self._options['edge_colors'] for color in edge_colors: for edge in edge_colors[color]: key = tuple(sorted([edge[0],edge[1]])) if key == (edge[0],edge[1]): head = 1 else: head = 0 if len(edge) < 3: label = self._graph.edge_label(edge[0],edge[1]) if isinstance(label, list): if key in edges_to_draw: edges_to_draw[key].append((label[-1], color, head)) else: edges_to_draw[key] = [(label[-1], color, head)] for i in range(len(label)-1): edges_to_draw[key].append((label[-1], color, head)) else: label = edge[2] if key in edges_to_draw: edges_to_draw[key].append((label, color, head)) else: edges_to_draw[key] = [(label, color, head)] # add unspecified edges in (default color black) for edge in self._graph.edge_iterator(): key = tuple(sorted([edge[0],edge[1]])) label = edge[2] specified = False if key in edges_to_draw: for old_label, old_color, old_head in edges_to_draw[key]: if label == old_label: specified = True break if not specified: if key == (edge[0],edge[1]): head = 1 else: head = 0 edges_to_draw[key] = [(label, 'black', head)] else: for edge in self._graph.edges(sort=True): key = tuple(sorted([edge[0],edge[1]])) if key == (edge[0],edge[1]): head = 1 else: head = 0 if key in edges_to_draw: edges_to_draw[key].append((edge[2], self._options['edge_color'], head)) else: edges_to_draw[key] = [(edge[2], self._options['edge_color'], head)] if edges_to_draw: self._plot_components['edges'] = [] else: return # Check for multi-edges or loops if self._arcs or self._loops: tmp = edges_to_draw.copy() dist = self._options['dist']*2. loop_size = self._options['loop_size'] max_dist = self._options['max_dist'] from sage.functions.all import sqrt for (a,b) in tmp: if a == b: # Loops distance = dist local_labels = edges_to_draw.pop((a,b)) if len(local_labels)*dist > max_dist: distance = float(max_dist)/len(local_labels) curr_loop_size = loop_size for i in range(len(local_labels)): self._plot_components['edges'].append(circle((self._pos[a][0],self._pos[a][1]-curr_loop_size), curr_loop_size, rgbcolor=local_labels[i][1], **eoptions)) if labels: self._plot_components['edge_labels'].append(text(local_labels[i][0], (self._pos[a][0], self._pos[a][1]-2*curr_loop_size))) curr_loop_size += distance/4 elif len(edges_to_draw[(a,b)]) > 1: # Multi-edge local_labels = edges_to_draw.pop((a,b)) # Compute perpendicular bisector p1 = self._pos[a] p2 = self._pos[b] M = ((p1[0]+p2[0])/2., (p1[1]+p2[1])/2.) # midpoint if not p1[1] == p2[1]: S = float(p1[0]-p2[0])/(p2[1]-p1[1]) # perp slope y = lambda x : S*x-S*M[0]+M[1] # perp bisector line # f,g are functions of distance d to determine x values # on line y at d from point M f = lambda d : sqrt(d**2/(1.+S**2)) + M[0] g = lambda d : -sqrt(d**2/(1.+S**2)) + M[0] odd_x = f even_x = g if p1[0] == p2[0]: odd_y = lambda d : M[1] even_y = odd_y else: odd_y = lambda x : y(f(x)) even_y = lambda x : y(g(x)) else: odd_x = lambda d : M[0] even_x = odd_x odd_y = lambda d : M[1] + d even_y = lambda d : M[1] - d # We now have the control points for each bezier curve # in terms of distance parameter d. # Also note that the label for each edge should be drawn at d/2. # (This is because we're using the perp bisectors). distance = dist if len(local_labels)*dist > max_dist: distance = float(max_dist)/len(local_labels) for i in range(len(local_labels)/2): k = (i+1.0)*distance if self._arcdigraph: odd_start = self._polar_hack_for_multidigraph(p1, [odd_x(k),odd_y(k)], self._vertex_radius)[0] odd_end = self._polar_hack_for_multidigraph([odd_x(k),odd_y(k)], p2, self._vertex_radius)[1] even_start = self._polar_hack_for_multidigraph(p1, [even_x(k),even_y(k)], self._vertex_radius)[0] even_end = self._polar_hack_for_multidigraph([even_x(k),even_y(k)], p2, self._vertex_radius)[1] self._plot_components['edges'].append(arrow(path=[[odd_start,[odd_x(k),odd_y(k)],odd_end]], head=local_labels[2*i][2], zorder=1, rgbcolor=local_labels[2*i][1], **eoptions)) self._plot_components['edges'].append(arrow(path=[[even_start,[even_x(k),even_y(k)],even_end]], head=local_labels[2*i+1][2], zorder=1, rgbcolor=local_labels[2*i+1][1], **eoptions)) else: self._plot_components['edges'].append(bezier_path([[p1,[odd_x(k),odd_y(k)],p2]],zorder=1, rgbcolor=local_labels[2*i][1], **eoptions)) self._plot_components['edges'].append(bezier_path([[p1,[even_x(k),even_y(k)],p2]],zorder=1, rgbcolor=local_labels[2*i+1][1], **eoptions)) if labels: j = k/2.0 self._plot_components['edge_labels'].append(text(local_labels[2*i][0],[odd_x(j),odd_y(j)])) self._plot_components['edge_labels'].append(text(local_labels[2*i+1][0],[even_x(j),even_y(j)])) if len(local_labels)%2 == 1: edges_to_draw[(a,b)] = [local_labels[-1]] # draw line for last odd dir = self._graph.is_directed() for (a,b) in edges_to_draw: if self._arcdigraph: C,D = self._polar_hack_for_multidigraph(self._pos[a], self._pos[b], self._vertex_radius) self._plot_components['edges'].append(arrow(C,D, rgbcolor=edges_to_draw[(a,b)][0][1], head=edges_to_draw[(a,b)][0][2], **eoptions)) if labels: self._plot_components['edge_labels'].append(text(str(edges_to_draw[(a,b)][0][0]),[(C[0]+D[0])/2., (C[1]+D[1])/2.])) elif dir: self._plot_components['edges'].append(arrow(self._pos[a],self._pos[b], rgbcolor=edges_to_draw[(a,b)][0][1], arrowshorten=self._arrowshorten, head=edges_to_draw[(a,b)][0][2], **eoptions)) else: self._plot_components['edges'].append(line([self._pos[a],self._pos[b]], rgbcolor=edges_to_draw[(a,b)][0][1], **eoptions)) if labels and not self._arcdigraph: self._plot_components['edge_labels'].append(text(str(edges_to_draw[(a,b)][0][0]),[(self._pos[a][0]+self._pos[b][0])/2., (self._pos[a][1]+self._pos[b][1])/2.]))
def set_vertices(self, **vertex_options): """ Sets the vertex plotting parameters for this GraphPlot. This function is called by the constructor but can also be called to make updates to the vertex options of an existing GraphPlot object. Note that the changes are cumulative. EXAMPLES:: 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: GP = g.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed') sage: GP.set_vertices(talk=True) sage: GP.plot() sage: GP.set_vertices(vertex_colors='pink', vertex_shape='^') sage: GP.plot() """ # Handle base vertex options voptions = {} for arg in vertex_options: self._options[arg] = vertex_options[arg] # First set defaults for styles vertex_colors = None if self._options['talk']: voptions['markersize'] = 500 if self._options['partition'] is None: vertex_colors = '#ffffff' else: voptions['markersize'] = self._options['vertex_size'] if 'vertex_colors' not in self._options or self._options['vertex_colors'] is None: if self._options['partition'] is not None: from sage.plot.colors import rainbow,rgbcolor partition = self._options['partition'] l = len(partition) R = rainbow(l) vertex_colors = {} for i in range(l): vertex_colors[R[i]] = partition[i] elif len(self._graph._boundary) != 0: vertex_colors = {} bdy_verts = [] int_verts = [] for v in self._graph.vertex_iterator(): if v in self._graph._boundary: bdy_verts.append(v) else: int_verts.append(v) vertex_colors['#fec7b8'] = int_verts vertex_colors['#b3e8ff'] = bdy_verts elif not vertex_colors: vertex_colors='#fec7b8' else: vertex_colors = self._options['vertex_colors'] if 'vertex_shape' in self._options: voptions['marker'] = self._options['vertex_shape'] if self._graph.is_directed(): self._vertex_radius = sqrt(voptions['markersize']/pi) self._arrowshorten = 2*self._vertex_radius if self._arcdigraph: self._vertex_radius = sqrt(voptions['markersize']/(20500*pi)) voptions['zorder'] = 7 if not isinstance(vertex_colors, dict): voptions['facecolor'] = vertex_colors if self._arcdigraph: self._plot_components['vertices'] = [circle(center, self._vertex_radius, fill=True, facecolor=vertex_colors, clip=False) for center in self._pos.values()] else: self._plot_components['vertices'] = scatter_plot( self._pos.values(), clip=False, **voptions) else: # Color list must be ordered: pos = [] colors = [] for i in vertex_colors: pos += [self._pos[j] for j in vertex_colors[i]] colors += [i]*len(vertex_colors[i]) # If all the vertices have not been assigned a color if len(self._pos)!=len(pos): from sage.plot.colors import rainbow,rgbcolor vertex_colors_rgb=[rgbcolor(c) for c in vertex_colors] for c in rainbow(len(vertex_colors)+1): if rgbcolor(c) not in vertex_colors_rgb: break leftovers=[j for j in self._pos.values() if j not in pos] pos+=leftovers colors+=[c]*len(leftovers) if self._arcdigraph: self._plot_components['vertices'] = [circle(pos[i], self._vertex_radius, fill=True, facecolor=colors[i], clip=False) for i in range(len(pos))] else: self._plot_components['vertices'] = scatter_plot(pos, facecolor=colors, clip=False, **voptions) if self._options['vertex_labels']: self._plot_components['vertex_labels'] = [] # TODO: allow text options for v in self._nodelist: self._plot_components['vertex_labels'].append(text(str(v), self._pos[v], rgbcolor=(0,0,0), zorder=8))
def set_edges(self, **edge_options): """ Sets the edge (or arrow) plotting parameters for the GraphPlot object. This function is called by the constructor but can also be called to make updates to the vertex options of an existing GraphPlot object. Note that the changes are cumulative. EXAMPLES:: 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: GP = g.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed') sage: GP.set_edges(edge_style='solid') sage: GP.plot() sage: GP.set_edges(edge_color='black') sage: GP.plot() sage: d = DiGraph({}, loops=True, multiedges=True, sparse=True) sage: d.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: GP = d.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed') sage: GP.set_edges(edge_style='solid') sage: GP.plot() sage: GP.set_edges(edge_color='black') sage: GP.plot() TESTS:: sage: G = Graph("Fooba") sage: G.show(edge_colors={'red':[(3,6),(2,5)]}) Verify that default edge labels are pretty close to being between the vertices in some cases where they weren't due to truncating division (trac #10124):: sage: test_graphs = graphs.FruchtGraph(), graphs.BullGraph() sage: tol = 0.001 sage: for G in test_graphs: ... E=G.edges() ... for e0, e1, elab in E: ... G.set_edge_label(e0, e1, '%d %d' % (e0, e1)) ... gp = G.graphplot(save_pos=True,edge_labels=True) ... vx = gp._plot_components['vertices'][0].xdata ... vy = gp._plot_components['vertices'][0].ydata ... for elab in gp._plot_components['edge_labels']: ... textobj = elab[0] ... x, y, s = textobj.x, textobj.y, textobj.string ... v0, v1 = map(int, s.split()) ... vn = vector(((x-(vx[v0]+vx[v1])/2.),y-(vy[v0]+vy[v1])/2.)).norm() ... assert vn < tol """ for arg in edge_options: self._options[arg] = edge_options[arg] if 'edge_colors' in edge_options: self._options['color_by_label'] = False # Handle base edge options: thickness, linestyle eoptions = {} if 'edge_style' in self._options: eoptions['linestyle'] = self._options['edge_style'] if 'thickness' in self._options: eoptions['thickness'] = self._options['thickness'] # Set labels param to add labels on the fly labels = False if self._options['edge_labels']: labels = True self._plot_components['edge_labels'] = [] # Make dict collection of all edges (keep label and edge color) edges_to_draw = {} if self._options['color_by_label'] or isinstance( self._options['edge_colors'], dict): if self._options['color_by_label']: edge_colors = self._graph._color_by_label() else: edge_colors = self._options['edge_colors'] for color in edge_colors: for edge in edge_colors[color]: key = tuple(sorted([edge[0], edge[1]])) if key == (edge[0], edge[1]): head = 1 else: head = 0 if len(edge) < 3: label = self._graph.edge_label(edge[0], edge[1]) if isinstance(label, list): if key in edges_to_draw: edges_to_draw[key].append( (label[-1], color, head)) else: edges_to_draw[key] = [(label[-1], color, head)] for i in range(len(label) - 1): edges_to_draw[key].append( (label[-1], color, head)) else: label = edge[2] if key in edges_to_draw: edges_to_draw[key].append((label, color, head)) else: edges_to_draw[key] = [(label, color, head)] # add unspecified edges in (default color black) for edge in self._graph.edge_iterator(): key = tuple(sorted([edge[0], edge[1]])) label = edge[2] specified = False if key in edges_to_draw: for old_label, old_color, old_head in edges_to_draw[key]: if label == old_label: specified = True break if not specified: if key == (edge[0], edge[1]): head = 1 else: head = 0 edges_to_draw[key] = [(label, 'black', head)] else: for edge in self._graph.edges(sort=True): key = tuple(sorted([edge[0], edge[1]])) if key == (edge[0], edge[1]): head = 1 else: head = 0 if key in edges_to_draw: edges_to_draw[key].append( (edge[2], self._options['edge_color'], head)) else: edges_to_draw[key] = [(edge[2], self._options['edge_color'], head)] if edges_to_draw: self._plot_components['edges'] = [] else: return # Check for multi-edges or loops if self._arcs or self._loops: tmp = edges_to_draw.copy() dist = self._options['dist'] * 2. loop_size = self._options['loop_size'] max_dist = self._options['max_dist'] from sage.functions.all import sqrt for (a, b) in tmp: if a == b: # Loops distance = dist local_labels = edges_to_draw.pop((a, b)) if len(local_labels) * dist > max_dist: distance = float(max_dist) / len(local_labels) curr_loop_size = loop_size for i in range(len(local_labels)): self._plot_components['edges'].append( circle((self._pos[a][0], self._pos[a][1] - curr_loop_size), curr_loop_size, rgbcolor=local_labels[i][1], **eoptions)) if labels: self._plot_components['edge_labels'].append( text(local_labels[i][0], (self._pos[a][0], self._pos[a][1] - 2 * curr_loop_size))) curr_loop_size += distance / 4 elif len(edges_to_draw[(a, b)]) > 1: # Multi-edge local_labels = edges_to_draw.pop((a, b)) # Compute perpendicular bisector p1 = self._pos[a] p2 = self._pos[b] M = ( (p1[0] + p2[0]) / 2., (p1[1] + p2[1]) / 2.) # midpoint if not p1[1] == p2[1]: S = float(p1[0] - p2[0]) / (p2[1] - p1[1] ) # perp slope y = lambda x: S * x - S * M[0] + M[ 1] # perp bisector line # f,g are functions of distance d to determine x values # on line y at d from point M f = lambda d: sqrt(d**2 / (1. + S**2)) + M[0] g = lambda d: -sqrt(d**2 / (1. + S**2)) + M[0] odd_x = f even_x = g if p1[0] == p2[0]: odd_y = lambda d: M[1] even_y = odd_y else: odd_y = lambda x: y(f(x)) even_y = lambda x: y(g(x)) else: odd_x = lambda d: M[0] even_x = odd_x odd_y = lambda d: M[1] + d even_y = lambda d: M[1] - d # We now have the control points for each bezier curve # in terms of distance parameter d. # Also note that the label for each edge should be drawn at d/2. # (This is because we're using the perp bisectors). distance = dist if len(local_labels) * dist > max_dist: distance = float(max_dist) / len(local_labels) for i in range(len(local_labels) / 2): k = (i + 1.0) * distance if self._arcdigraph: odd_start = self._polar_hack_for_multidigraph( p1, [odd_x(k), odd_y(k)], self._vertex_radius)[0] odd_end = self._polar_hack_for_multidigraph( [odd_x(k), odd_y(k)], p2, self._vertex_radius)[1] even_start = self._polar_hack_for_multidigraph( p1, [even_x(k), even_y(k)], self._vertex_radius)[0] even_end = self._polar_hack_for_multidigraph( [even_x(k), even_y(k)], p2, self._vertex_radius)[1] self._plot_components['edges'].append( arrow(path=[[ odd_start, [odd_x(k), odd_y(k)], odd_end ]], head=local_labels[2 * i][2], zorder=1, rgbcolor=local_labels[2 * i][1], **eoptions)) self._plot_components['edges'].append( arrow(path=[[ even_start, [even_x(k), even_y(k)], even_end ]], head=local_labels[2 * i + 1][2], zorder=1, rgbcolor=local_labels[2 * i + 1][1], **eoptions)) else: self._plot_components['edges'].append( bezier_path( [[p1, [odd_x(k), odd_y(k)], p2]], zorder=1, rgbcolor=local_labels[2 * i][1], **eoptions)) self._plot_components['edges'].append( bezier_path( [[p1, [even_x(k), even_y(k)], p2]], zorder=1, rgbcolor=local_labels[2 * i + 1][1], **eoptions)) if labels: j = k / 2.0 self._plot_components['edge_labels'].append( text(local_labels[2 * i][0], [odd_x(j), odd_y(j)])) self._plot_components['edge_labels'].append( text(local_labels[2 * i + 1][0], [even_x(j), even_y(j)])) if len(local_labels) % 2 == 1: edges_to_draw[(a, b)] = [local_labels[-1] ] # draw line for last odd dir = self._graph.is_directed() for (a, b) in edges_to_draw: if self._arcdigraph: C, D = self._polar_hack_for_multidigraph( self._pos[a], self._pos[b], self._vertex_radius) self._plot_components['edges'].append( arrow(C, D, rgbcolor=edges_to_draw[(a, b)][0][1], head=edges_to_draw[(a, b)][0][2], **eoptions)) if labels: self._plot_components['edge_labels'].append( text(str(edges_to_draw[(a, b)][0][0]), [(C[0] + D[0]) / 2., (C[1] + D[1]) / 2.])) elif dir: self._plot_components['edges'].append( arrow(self._pos[a], self._pos[b], rgbcolor=edges_to_draw[(a, b)][0][1], arrowshorten=self._arrowshorten, head=edges_to_draw[(a, b)][0][2], **eoptions)) else: self._plot_components['edges'].append( line([self._pos[a], self._pos[b]], rgbcolor=edges_to_draw[(a, b)][0][1], **eoptions)) if labels and not self._arcdigraph: self._plot_components['edge_labels'].append( text(str(edges_to_draw[(a, b)][0][0]), [(self._pos[a][0] + self._pos[b][0]) / 2., (self._pos[a][1] + self._pos[b][1]) / 2.]))
def set_vertices(self, **vertex_options): """ Sets the vertex plotting parameters for this GraphPlot. This function is called by the constructor but can also be called to make updates to the vertex options of an existing GraphPlot object. Note that the changes are cumulative. EXAMPLES:: 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: GP = g.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed') sage: GP.set_vertices(talk=True) sage: GP.plot() sage: GP.set_vertices(vertex_colors='pink', vertex_shape='^') sage: GP.plot() """ # Handle base vertex options voptions = {} for arg in vertex_options: self._options[arg] = vertex_options[arg] # First set defaults for styles vertex_colors = None if self._options['talk']: voptions['markersize'] = 500 if self._options['partition'] is None: vertex_colors = '#ffffff' else: voptions['markersize'] = self._options['vertex_size'] if 'vertex_colors' not in self._options: if self._options['partition'] is not None: from sage.plot.colors import rainbow, rgbcolor partition = self._options['partition'] l = len(partition) R = rainbow(l) vertex_colors = {} for i in range(l): vertex_colors[R[i]] = partition[i] elif len(self._graph._boundary) != 0: vertex_colors = {} bdy_verts = [] int_verts = [] for v in self._graph.vertex_iterator(): if v in self._graph._boundary: bdy_verts.append(v) else: int_verts.append(v) vertex_colors['#fec7b8'] = int_verts vertex_colors['#b3e8ff'] = bdy_verts elif not vertex_colors: vertex_colors = '#fec7b8' else: vertex_colors = self._options['vertex_colors'] if 'vertex_shape' in self._options: voptions['marker'] = self._options['vertex_shape'] if self._graph.is_directed(): self._vertex_radius = sqrt(voptions['markersize'] / pi) self._arrowshorten = 2 * self._vertex_radius if self._arcdigraph: self._vertex_radius = sqrt(voptions['markersize'] / (20500 * pi)) voptions['zorder'] = 7 if not isinstance(vertex_colors, dict): voptions['facecolor'] = vertex_colors if self._arcdigraph: self._plot_components['vertices'] = [ circle(center, self._vertex_radius, fill=True, facecolor=vertex_colors, clip=False) for center in self._pos.values() ] else: self._plot_components['vertices'] = scatter_plot( self._pos.values(), clip=False, **voptions) else: # Color list must be ordered: pos = [] colors = [] for i in vertex_colors: pos += [self._pos[j] for j in vertex_colors[i]] colors += [i] * len(vertex_colors[i]) # If all the vertices have not been assigned a color if len(self._pos) != len(pos): from sage.plot.colors import rainbow, rgbcolor vertex_colors_rgb = [rgbcolor(c) for c in vertex_colors] for c in rainbow(len(vertex_colors) + 1): if rgbcolor(c) not in vertex_colors_rgb: break leftovers = [j for j in self._pos.values() if j not in pos] pos += leftovers colors += [c] * len(leftovers) if self._arcdigraph: self._plot_components['vertices'] = [ circle(pos[i], self._vertex_radius, fill=True, facecolor=colors[i], clip=False) for i in range(len(pos)) ] else: self._plot_components['vertices'] = scatter_plot( pos, facecolor=colors, clip=False, **voptions) if self._options['vertex_labels']: self._plot_components['vertex_labels'] = [] # TODO: allow text options for v in self._nodelist: self._plot_components['vertex_labels'].append( text(str(v), self._pos[v], rgbcolor=(0, 0, 0), zorder=8))
def plot_heap(self): r""" Display the Hasse diagram of the heap of ``self``. The Hasse diagram is rendered in the lattice `S \times \NN`, with every element `i` in the poset drawn as a point labelled by its label `s_i`. Every point is placed in the column for its label at a certain level. The levels start at 0 and the level k of an element `i` is the maximal number `k` such that the heap contains a chain `i_0\prec i_1\prec ... \prec i_k` where `i_k=i`. See [Ste1996]_ and [GX2020]_. OUTPUT: GraphicsObject EXAMPLES:: sage: FC = CoxeterGroup(['B', 5]).fully_commutative_elements() sage: FC([3,2,4,3,1]).plot_heap() Graphics object consisting of 15 graphics primitives .. PLOT:: :width: 400px FC = CoxeterGroup(['B', 5]).fully_commutative_elements() g = FC([3,2,4,3,1]).plot_heap() sphinx_plot(g) """ import sage.plot.all as plot m = self.parent().coxeter_group().coxeter_matrix() letters = self.parent().coxeter_group().index_set() graphics = [] h = self.heap() levels = h.level_sets() letters_at_level = [set(self[i] for i in level) for level in levels] for (level_zero_index, members) in enumerate(levels): level = level_zero_index + 1 for i in members: x = self[i] # Draw the node graphics.append( plot.circle((x, level), 0.1, fill=True, facecolor='white', edgecolor='blue', zorder=1)) graphics.append( plot.text(str(x), (x, level), color='blue', zorder=2)) neighbors = {z for z in letters if m[x, z] >= 3} for other in neighbors: highest_level = max((j + 1 for j in range(level_zero_index) if other in letters_at_level[j]), default=None) if highest_level: graphics.append( plot.line([(other, highest_level), (x, level)], color='black', zorder=0)) g = sum(graphics) g.axes(False) return g