def triangulation_render_2d(triangulation, **kwds): r""" Return a graphical representation of a 2-d triangulation. INPUT: - ``triangulation`` -- a :class:`Triangulation`. - ``**kwds`` -- keywords that are passed on to the graphics primitives. OUTPUT: A 2-d graphics object. EXAMPLES:: sage: points = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) sage: triang = points.triangulate() sage: triang.plot(axes=False, aspect_ratio=1) # indirect doctest Graphics object consisting of 12 graphics primitives """ from sage.plot.all import point2d, line2d, arrow, polygon2d points = [ point.reduced_affine() for point in triangulation.point_configuration() ] coord = [ [p[0], p[1]] for p in points ] plot_points = sum([ point2d(p, zorder=2, pointsize=10, **kwds) for p in coord ]) tmp_lines = [] for t in triangulation: if len(t)>=2: tmp_lines.append([t[0], t[1]]) if len(t)>=3: tmp_lines.append([t[0], t[2]]) tmp_lines.append([t[1], t[2]]) all_lines = [] interior_lines = [] for l in tmp_lines: if l not in all_lines: all_lines.append(l) else: interior_lines.append(l) exterior_lines = [ l for l in all_lines if not l in interior_lines ] plot_interior_lines = sum([ line2d([ coord[l[0]], coord[l[1]] ], zorder=1, rgbcolor=(0,1,0), **kwds) for l in interior_lines ]) plot_exterior_lines = sum([ line2d([ coord[l[0]], coord[l[1]] ], zorder=1, rgbcolor=(0,0,1), **kwds) for l in exterior_lines ]) plot_triangs = sum([ polygon2d([coord[t[0]], coord[t[1]], coord[t[2]]], zorder=0, rgbcolor=(0.8, 1, 0.8), **kwds) for t in triangulation if len(t)>=3 ]) return \ plot_points + \ plot_interior_lines + plot_exterior_lines + \ plot_triangs
def triangulation_render_2d(triangulation, **kwds): r""" Return a graphical representation of a 2-d triangulation. INPUT: - ``triangulation`` -- a :class:`Triangulation`. - ``**kwds`` -- keywords that are passed on to the graphics primitives. OUTPUT: A 2-d graphics object. EXAMPLES:: sage: points = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) sage: triang = points.triangulate() sage: triang.plot(axes=False, aspect_ratio=1) # indirect doctest Graphics object consisting of 12 graphics primitives """ from sage.plot.all import point2d, line2d, arrow, polygon2d points = [point.reduced_affine() for point in triangulation.point_configuration()] coord = [[p[0], p[1]] for p in points] plot_points = sum([point2d(p, zorder=2, pointsize=10, **kwds) for p in coord]) tmp_lines = [] for t in triangulation: if len(t) >= 2: tmp_lines.append([t[0], t[1]]) if len(t) >= 3: tmp_lines.append([t[0], t[2]]) tmp_lines.append([t[1], t[2]]) all_lines = [] interior_lines = [] for l in tmp_lines: if l not in all_lines: all_lines.append(l) else: interior_lines.append(l) exterior_lines = [l for l in all_lines if not l in interior_lines] plot_interior_lines = sum( [line2d([coord[l[0]], coord[l[1]]], zorder=1, rgbcolor=(0, 1, 0), **kwds) for l in interior_lines] ) plot_exterior_lines = sum( [line2d([coord[l[0]], coord[l[1]]], zorder=1, rgbcolor=(0, 0, 1), **kwds) for l in exterior_lines] ) plot_triangs = sum( [ polygon2d([coord[t[0]], coord[t[1]], coord[t[2]]], zorder=0, rgbcolor=(0.8, 1, 0.8), **kwds) for t in triangulation if len(t) >= 3 ] ) return plot_points + plot_interior_lines + plot_exterior_lines + plot_triangs
def render_fill_2d(self, **kwds): """ Return the filled interior (a polygon) of a polyhedron in 2d. EXAMPLES:: sage: cps = [i^3 for i in srange(-2,2,1/5)] sage: p = Polyhedron(vertices = [[(t^2-1)/(t^2+1),2*t/(t^2+1)] for t in cps]) sage: proj = p.projection() sage: filled_poly = proj.render_fill_2d() sage: filled_poly.axes_width() 0.8 """ poly = [polygon2d(self.coordinates_of(p), **kwds) for p in self.polygons] return sum(poly)
def plot_completely_periodic(self): from sage.plot.all import polygon2d, Graphics, point2d, text O = self.orbit G = [] u = self.u # direction (that we put horizontal) m = matrix(2, [u[1], -u[0], u[1], u[0]]) indices = {} xmin = xmax = ymin = ymax = 0 for comp in self.decomposition.components(): H = Graphics() x = O.V2._isomorphic_vector_space.zero() pts = [x] below = True for p in comp.perimeter(): sc = p.saddleConnection() y = x + m * O.V2._isomorphic_vector_space( O.V2(p.saddleConnection().vector())) if p.vertical(): if sc in indices: i = indices[sc] else: i = len(indices) // 2 indices[sc] = i indices[-sc] = i if below: H += text(str(i), (x + y) / 2, color='black') x = y xmin = min(xmin, x[0]) xmax = max(xmax, x[0]) ymin = min(ymin, x[1]) ymax = max(ymax, x[1]) pts.append(x) H += polygon2d(pts, color='blue', alpha=0.3) H += point2d(pts, color='red', pointsize=20) G.append(H) aspect_ratio = float(xmax - xmin) / float(ymax - ymin) for H in G: H.set_axes_range(xmin, xmax, ymin, ymax) H.axes(False) H.set_aspect_ratio(aspect_ratio) return G
def geomrep(M1, B1=None, lineorders1=None, pd=None, sp=False): """ Return a sage graphics object containing geometric representation of matroid M1. INPUT: - ``M1`` -- A matroid. - ``B1`` -- (optional) A list of elements in ``M1.groundset()`` that correspond to a basis of ``M1`` and will be placed as vertices of the triangle in the geometric representation of ``M1``. - ``lineorders1`` -- (optional) A list of ordered lists of elements of ``M1.grondset()`` such that if a line in geometric representation is setwise same as any of these then points contained will be traversed in that order thus overriding internal order deciding heuristic. - ``pd`` - (optional) A dictionary mapping ground set elements to their (x,y) positions. - ``sp`` -- (optional) If True, a positioning dictionary and line orders will be placed in ``M._cached_info``. OUTPUT: A sage graphics object of type <class 'sage.plot.graphics.Graphics'> that corresponds to the geometric representation of the matroid. EXAMPLES:: sage: from sage.matroids import matroids_plot_helpers sage: M=matroids.named_matroids.P7() sage: G=matroids_plot_helpers.geomrep(M) sage: G.show(xmin=-2, xmax=3, ymin=-2, ymax=3) sage: M=matroids.named_matroids.P7() sage: G=matroids_plot_helpers.geomrep(M,lineorders1=[['f','e','d']]) sage: G.show(xmin=-2, xmax=3, ymin=-2, ymax=3) .. NOTE:: This method does NOT do any checks. """ G = Graphics() # create lists of loops and parallel elements and simplify given matroid [M, L, P] = slp(M1, pos_dict=pd, B=B1) if B1 is None: B1 = list(M.basis()) M._cached_info = M1._cached_info if M.rank() == 0: limits = None loops = L looptext = ", ".join([str(l) for l in loops]) rectx = -1 recty = -1 rectw = 0.5 + 0.4*len(loops) + 0.5 # controlled based on len(loops) recth = 0.6 G += polygon2d([[rectx, recty], [rectx, recty+recth], [rectx+rectw, recty+recth], [rectx+rectw, recty]], color='black', fill=False, thickness=4) G += text(looptext, (rectx+0.5, recty+0.3), color='black', fontsize=13) G += point((rectx+0.2, recty+0.3), color=Color('#BDBDBD'), size=300, zorder=2) G += text('Loop(s)', (rectx+0.5+0.4*len(loops)+0.1, recty+0.3), fontsize=13, color='black') limits = tracklims(limits, [rectx, rectx+rectw], [recty, recty+recth]) G.axes(False) G.axes_range(xmin=limits[0]-0.5, xmax=limits[1]+0.5, ymin=limits[2]-0.5, ymax=limits[3]+0.5) return G elif M.rank() == 1: if M._cached_info is not None and \ 'plot_positions' in M._cached_info.keys() and \ M._cached_info['plot_positions'] is not None: pts = M._cached_info['plot_positions'] else: pts = {} gnd = sorted(M.groundset()) pts[gnd[0]] = (1, float(2)/3) G += point((1, float(2)/3), size=300, color=Color('#BDBDBD'), zorder=2) pt = [1, float(2)/3] if len(P) == 0: G += text(gnd[0], (float(pt[0]), float(pt[1])), color='black', fontsize=13) pts2 = pts # track limits [xmin,xmax,ymin,ymax] pl = [list(x) for x in pts2.values()] lims = tracklims([None, None, None, None], [pt[0] for pt in pl], [pt[1] for pt in pl]) elif M.rank() == 2: nB1 = list(set(list(M.groundset())) - set(B1)) bline = [] for j in nB1: if M.is_dependent([j, B1[0], B1[1]]): bline.append(j) interval = len(bline)+1 if M._cached_info is not None and \ 'plot_positions' in M._cached_info.keys() and \ M._cached_info['plot_positions'] is not None: pts2 = M._cached_info['plot_positions'] else: pts2 = {} pts2[B1[0]] = (0, 0) pts2[B1[1]] = (2, 0) lpt = list(pts2[B1[0]]) rpt = list(pts2[B1[1]]) for k in range(len(bline)): cc = (float(1)/interval)*(k+1) pts2[bline[k]] = (cc*lpt[0]+(1-cc)*rpt[0], cc*lpt[1]+(1-cc)*rpt[1]) if sp is True: M._cached_info['plot_positions'] = pts2 # track limits [xmin,xmax,ymin,ymax] pl = [list(x) for x in pts2.values()] lims = tracklims([None, None, None, None], [pt[0] for pt in pl], [pt[1] for pt in pl]) bline.extend(B1) ptsx, ptsy, x_i, y_i = createline(pts2, bline, lineorders1) lims = tracklims(lims, x_i, y_i) G += line(zip(x_i, y_i), color='black', thickness=3, zorder=1) pels = [p for p in pts2.keys() if any([M1.rank([p, q]) == 1 for q in P])] allpts = [list(pts2[i]) for i in M.groundset()] xpts = [float(k[0]) for k in allpts] ypts = [float(k[1]) for k in allpts] G += points(zip(xpts, ypts), color=Color('#BDBDBD'), size=300, zorder=2) for i in pts2: if i not in pels: pt = list(pts2[i]) G += text(i, (float(pt[0]), float(pt[1])), color='black', fontsize=13) else: if M._cached_info is None or \ 'plot_positions' not in M._cached_info.keys() or \ M._cached_info['plot_positions'] is None: (pts, trilines, nontripts, curvedlines) = it(M1, B1, list(set(M.groundset())-set(B1)), list(set(L) | set(P))) pts2 = addnontripts([B1[0], B1[1], B1[2]], nontripts, pts) trilines.extend(curvedlines) else: pts2 = M._cached_info['plot_positions'] trilines = [list(set(list(x)).difference(L | P)) for x in M1.flats(2) if len(list(x)) >= 3] pl = [list(x) for x in pts2.values()] lims = tracklims([None, None, None, None], [pt[0] for pt in pl], [pt[1] for pt in pl]) j = 0 for ll in trilines: if len(ll) >= 3: ptsx, ptsy, x_i, y_i = createline(pts2, ll, lineorders1) lims = tracklims(lims, x_i, y_i) G += line(zip(x_i, y_i), color='black', thickness=3, zorder=1) pels = [p for p in pts2.keys() if any([M1.rank([p, q]) == 1 for q in P])] allpts = [list(pts2[i]) for i in M.groundset()] xpts = [float(k[0]) for k in allpts] ypts = [float(k[1]) for k in allpts] G += points(zip(xpts, ypts), color=Color('#BDBDBD'), size=300, zorder=2) for i in pts2: if i not in pels: pt = list(pts2[i]) G += text(i, (float(pt[0]), float(pt[1])), color='black', fontsize=13) if sp is True: M1._cached_info['plot_positions'] = pts2 M1._cached_info['plot_lineorders'] = lineorders1 # deal with loops and parallel elements G, lims = addlp(M1, M, L, P, pts2, G, lims) G.axes(False) G.axes_range(xmin=lims[0]-0.5, xmax=lims[1]+0.5, ymin=lims[2]-0.5, ymax=lims[3]+0.5) return G
def addlp(M, M1, L, P, ptsdict, G=None, limits=None): """ Return a graphics object containing loops (in inset) and parallel elements of matroid. INPUT: - ``M`` -- A matroid. - ``M1`` -- A simple matroid corresponding to ``M``. - ``L`` -- List of elements in ``M.groundset()`` that are loops of matroid ``M``. - ``P`` -- List of elements in ``M.groundset()`` not in ``M.simplify.groundset()`` or ``L``. - ``ptsdict`` -- A dictionary containing elements in ``M.groundset()`` not necessarily containing elements of ``L``. - ``G`` -- (optional) A sage graphics object to which loops and parallel elements of matroid `M` added . - ``limits``-- (optional) Current axes limits [xmin,xmax,ymin,ymax]. OUTPUT: A 2-tuple containing: 1. A sage graphics object containing loops and parallel elements of matroid ``M`` 2. axes limits array EXAMPLES:: sage: from sage.matroids import matroids_plot_helpers sage: M=Matroid(ring=GF(2), matrix=[[1, 0, 0, 0, 1, 1, 1,0,1], ....: [0, 1, 0, 1, 0, 1, 1,0,0],[0, 0, 1, 1, 1, 0, 1,0,0]]) sage: [M1,L,P]=matroids_plot_helpers.slp(M) sage: G,lims=matroids_plot_helpers.addlp(M,M1,L,P,{0:(0,0)}) sage: G.show(axes=False) .. NOTE:: This method does NOT do any checks. """ if G is None: G = Graphics() # deal with loops if len(L) > 0: loops = L looptext = ", ".join([str(l) for l in loops]) if(limits is None): rectx = -1 recty = -1 else: rectx = limits[0] recty = limits[2]-1 rectw = 0.5 + 0.4*len(loops) + 0.5 # controlled based on len(loops) recth = 0.6 G += polygon2d([[rectx, recty], [rectx, recty+recth], [rectx+rectw, recty+recth], [rectx+rectw, recty]], color='black', fill=False, thickness=4) G += text(looptext, (rectx+0.5, recty+0.3), color='black', fontsize=13) G += point((rectx+0.2, recty+0.3), color=Color('#BDBDBD'), size=300, zorder=2) G += text('Loop(s)', (rectx+0.5+0.4*len(loops)+0.1, recty+0.3), fontsize=13, color='black') limits = tracklims(limits, [rectx, rectx+rectw], [recty, recty+recth]) # deal with parallel elements if len(P) > 0: # create list of lists where inner lists are parallel classes pcls = [] gnd = sorted(list(M1.groundset())) for g in gnd: pcl = [g] for p in P: if M.rank([g, p]) == 1: pcl.extend([p]) pcls.append(pcl) ext_gnd = list(M.groundset()) for pcl in pcls: if len(pcl) > 1: basept = list(ptsdict[pcl[0]]) if len(pcl) <= 2: # add side by side ptsdict[pcl[1]] = (basept[0], basept[1]-0.13) G += points(zip([basept[0]], [basept[1]-0.13]), color=Color('#BDBDBD'), size=300, zorder=2) G += text(pcl[0], (float(basept[0]), float(basept[1])), color='black', fontsize=13) G += text(pcl[1], (float(basept[0]), float(basept[1])-0.13), color='black', fontsize=13) limits = tracklims(limits, [basept[0]], [basept[1]-0.13]) else: # add in a bracket pce = sorted([str(kk) for kk in pcl]) l = newlabel(set(ext_gnd)) ext_gnd.append(l) G += text(l+'={ '+", ".join(pce)+' }', (float(basept[0]), float(basept[1]-0.2)-0.034), color='black', fontsize=13) G += text(l, (float(basept[0]), float(basept[1])), color='black', fontsize=13) limits = tracklims(limits, [basept[0]], [(basept[1]-0.2)-0.034]) return G, limits
def geomrep(M1, B1=None, lineorders1=None, pd=None, sp=False): """ Return a sage graphics object containing geometric representation of matroid M1. INPUT: - ``M1`` -- A matroid. - ``B1`` -- (optional) A list of elements in ``M1.groundset()`` that correspond to a basis of ``M1`` and will be placed as vertices of the triangle in the geometric representation of ``M1``. - ``lineorders1`` -- (optional) A list of ordered lists of elements of ``M1.grondset()`` such that if a line in geometric representation is setwise same as any of these then points contained will be traversed in that order thus overriding internal order deciding heuristic. - ``pd`` - (optional) A dictionary mapping ground set elements to their (x,y) positions. - ``sp`` -- (optional) If True, a positioning dictionary and line orders will be placed in ``M._cached_info``. OUTPUT: A sage graphics object of type <class 'sage.plot.graphics.Graphics'> that corresponds to the geometric representation of the matroid. EXAMPLES:: sage: from sage.matroids import matroids_plot_helpers sage: M=matroids.named_matroids.P7() sage: G=matroids_plot_helpers.geomrep(M) sage: G.show(xmin=-2, xmax=3, ymin=-2, ymax=3) sage: M=matroids.named_matroids.P7() sage: G=matroids_plot_helpers.geomrep(M,lineorders1=[['f','e','d']]) sage: G.show(xmin=-2, xmax=3, ymin=-2, ymax=3) .. NOTE:: This method does NOT do any checks. """ G = Graphics() # create lists of loops and parallel elements and simplify given matroid [M, L, P] = slp(M1, pos_dict=pd, B=B1) if B1 is None: B1 = list(M.basis()) M._cached_info = M1._cached_info if M.rank() == 0: limits = None loops = L looptext = ", ".join([str(l) for l in loops]) rectx = -1 recty = -1 rectw = 0.5 + 0.4 * len(loops) + 0.5 # controlled based on len(loops) recth = 0.6 G += polygon2d( [[rectx, recty], [rectx, recty + recth], [rectx + rectw, recty + recth], [rectx + rectw, recty]], color='black', fill=False, thickness=4) G += text(looptext, (rectx + 0.5, recty + 0.3), color='black', fontsize=13) G += point((rectx + 0.2, recty + 0.3), color=Color('#BDBDBD'), size=300, zorder=2) G += text('Loop(s)', (rectx + 0.5 + 0.4 * len(loops) + 0.1, recty + 0.3), fontsize=13, color='black') limits = tracklims(limits, [rectx, rectx + rectw], [recty, recty + recth]) G.axes(False) G.axes_range(xmin=limits[0] - 0.5, xmax=limits[1] + 0.5, ymin=limits[2] - 0.5, ymax=limits[3] + 0.5) return G elif M.rank() == 1: if M._cached_info is not None and \ 'plot_positions' in M._cached_info.keys() and \ M._cached_info['plot_positions'] is not None: pts = M._cached_info['plot_positions'] else: pts = {} gnd = sorted(M.groundset()) pts[gnd[0]] = (1, float(2) / 3) G += point((1, float(2) / 3), size=300, color=Color('#BDBDBD'), zorder=2) pt = [1, float(2) / 3] if len(P) == 0: G += text(gnd[0], (float(pt[0]), float(pt[1])), color='black', fontsize=13) pts2 = pts # track limits [xmin,xmax,ymin,ymax] pl = [list(x) for x in pts2.values()] lims = tracklims([None, None, None, None], [pt[0] for pt in pl], [pt[1] for pt in pl]) elif M.rank() == 2: nB1 = list(set(list(M.groundset())) - set(B1)) bline = [] for j in nB1: if M.is_dependent([j, B1[0], B1[1]]): bline.append(j) interval = len(bline) + 1 if M._cached_info is not None and \ 'plot_positions' in M._cached_info.keys() and \ M._cached_info['plot_positions'] is not None: pts2 = M._cached_info['plot_positions'] else: pts2 = {} pts2[B1[0]] = (0, 0) pts2[B1[1]] = (2, 0) lpt = list(pts2[B1[0]]) rpt = list(pts2[B1[1]]) for k in range(len(bline)): cc = (float(1) / interval) * (k + 1) pts2[bline[k]] = (cc * lpt[0] + (1 - cc) * rpt[0], cc * lpt[1] + (1 - cc) * rpt[1]) if sp is True: M._cached_info['plot_positions'] = pts2 # track limits [xmin,xmax,ymin,ymax] pl = [list(x) for x in pts2.values()] lims = tracklims([None, None, None, None], [pt[0] for pt in pl], [pt[1] for pt in pl]) bline.extend(B1) ptsx, ptsy, x_i, y_i = createline(pts2, bline, lineorders1) lims = tracklims(lims, x_i, y_i) G += line(zip(x_i, y_i), color='black', thickness=3, zorder=1) pels = [ p for p in pts2.keys() if any([M1.rank([p, q]) == 1 for q in P]) ] allpts = [list(pts2[i]) for i in M.groundset()] xpts = [float(k[0]) for k in allpts] ypts = [float(k[1]) for k in allpts] G += points(zip(xpts, ypts), color=Color('#BDBDBD'), size=300, zorder=2) for i in pts2: if i not in pels: pt = list(pts2[i]) G += text(i, (float(pt[0]), float(pt[1])), color='black', fontsize=13) else: if M._cached_info is None or \ 'plot_positions' not in M._cached_info.keys() or \ M._cached_info['plot_positions'] is None: (pts, trilines, nontripts, curvedlines) = it(M1, B1, list(set(M.groundset()) - set(B1)), list(set(L) | set(P))) pts2 = addnontripts([B1[0], B1[1], B1[2]], nontripts, pts) trilines.extend(curvedlines) else: pts2 = M._cached_info['plot_positions'] trilines = [ list(set(list(x)).difference(L | P)) for x in M1.flats(2) if len(list(x)) >= 3 ] pl = [list(x) for x in pts2.values()] lims = tracklims([None, None, None, None], [pt[0] for pt in pl], [pt[1] for pt in pl]) j = 0 for ll in trilines: if len(ll) >= 3: ptsx, ptsy, x_i, y_i = createline(pts2, ll, lineorders1) lims = tracklims(lims, x_i, y_i) G += line(zip(x_i, y_i), color='black', thickness=3, zorder=1) pels = [ p for p in pts2.keys() if any([M1.rank([p, q]) == 1 for q in P]) ] allpts = [list(pts2[i]) for i in M.groundset()] xpts = [float(k[0]) for k in allpts] ypts = [float(k[1]) for k in allpts] G += points(zip(xpts, ypts), color=Color('#BDBDBD'), size=300, zorder=2) for i in pts2: if i not in pels: pt = list(pts2[i]) G += text(i, (float(pt[0]), float(pt[1])), color='black', fontsize=13) if sp is True: M1._cached_info['plot_positions'] = pts2 M1._cached_info['plot_lineorders'] = lineorders1 # deal with loops and parallel elements G, lims = addlp(M1, M, L, P, pts2, G, lims) G.axes(False) G.axes_range(xmin=lims[0] - 0.5, xmax=lims[1] + 0.5, ymin=lims[2] - 0.5, ymax=lims[3] + 0.5) return G
def addlp(M, M1, L, P, ptsdict, G=None, limits=None): """ Return a graphics object containing loops (in inset) and parallel elements of matroid. INPUT: - ``M`` -- A matroid. - ``M1`` -- A simple matroid corresponding to ``M``. - ``L`` -- List of elements in ``M.groundset()`` that are loops of matroid ``M``. - ``P`` -- List of elements in ``M.groundset()`` not in ``M.simplify.groundset()`` or ``L``. - ``ptsdict`` -- A dictionary containing elements in ``M.groundset()`` not necessarily containing elements of ``L``. - ``G`` -- (optional) A sage graphics object to which loops and parallel elements of matroid `M` added . - ``limits``-- (optional) Current axes limits [xmin,xmax,ymin,ymax]. OUTPUT: A 2-tuple containing: 1. A sage graphics object containing loops and parallel elements of matroid ``M`` 2. axes limits array EXAMPLES:: sage: from sage.matroids import matroids_plot_helpers sage: M=Matroid(ring=GF(2), matrix=[[1, 0, 0, 0, 1, 1, 1,0,1], ....: [0, 1, 0, 1, 0, 1, 1,0,0],[0, 0, 1, 1, 1, 0, 1,0,0]]) sage: [M1,L,P]=matroids_plot_helpers.slp(M) sage: G,lims=matroids_plot_helpers.addlp(M,M1,L,P,{0:(0,0)}) sage: G.show(axes=False) .. NOTE:: This method does NOT do any checks. """ if G is None: G = Graphics() # deal with loops if len(L) > 0: loops = L looptext = ", ".join([str(l) for l in loops]) if (limits is None): rectx = -1 recty = -1 else: rectx = limits[0] recty = limits[2] - 1 rectw = 0.5 + 0.4 * len(loops) + 0.5 # controlled based on len(loops) recth = 0.6 G += polygon2d( [[rectx, recty], [rectx, recty + recth], [rectx + rectw, recty + recth], [rectx + rectw, recty]], color='black', fill=False, thickness=4) G += text(looptext, (rectx + 0.5, recty + 0.3), color='black', fontsize=13) G += point((rectx + 0.2, recty + 0.3), color=Color('#BDBDBD'), size=300, zorder=2) G += text('Loop(s)', (rectx + 0.5 + 0.4 * len(loops) + 0.1, recty + 0.3), fontsize=13, color='black') limits = tracklims(limits, [rectx, rectx + rectw], [recty, recty + recth]) # deal with parallel elements if len(P) > 0: # create list of lists where inner lists are parallel classes pcls = [] gnd = sorted(list(M1.groundset())) for g in gnd: pcl = [g] for p in P: if M.rank([g, p]) == 1: pcl.extend([p]) pcls.append(pcl) ext_gnd = list(M.groundset()) for pcl in pcls: if len(pcl) > 1: basept = list(ptsdict[pcl[0]]) if len(pcl) <= 2: # add side by side ptsdict[pcl[1]] = (basept[0], basept[1] - 0.13) G += points(zip([basept[0]], [basept[1] - 0.13]), color=Color('#BDBDBD'), size=300, zorder=2) G += text(pcl[0], (float(basept[0]), float(basept[1])), color='black', fontsize=13) G += text(pcl[1], (float(basept[0]), float(basept[1]) - 0.13), color='black', fontsize=13) limits = tracklims(limits, [basept[0]], [basept[1] - 0.13]) else: # add in a bracket pce = sorted([str(kk) for kk in pcl]) l = newlabel(set(ext_gnd)) ext_gnd.append(l) G += text( l + '={ ' + ", ".join(pce) + ' }', (float(basept[0]), float(basept[1] - 0.2) - 0.034), color='black', fontsize=13) G += text(l, (float(basept[0]), float(basept[1])), color='black', fontsize=13) limits = tracklims(limits, [basept[0]], [(basept[1] - 0.2) - 0.034]) return G, limits