Example #1
0
 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
Example #2
0
 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
Example #3
0
 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)
Example #4
0
 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)
Example #5
0
 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)
Example #6
0
    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.]))
Example #7
0
    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))
Example #8
0
    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.]))
Example #9
0
    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))
Example #10
0
    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