def circle_image(A, B): G = Graphics() G += circle((0, 0), 1, color='grey') from collections import defaultdict tmp = defaultdict(int) for a in A: for j in range(a): if gcd(j, a) == 1: rational = Rational(j) / Rational(a) tmp[(rational.numerator(), rational.denominator())] += 1 for b in B: for j in range(b): if gcd(j, b) == 1: rational = Rational(j) / Rational(b) tmp[(rational.numerator(), rational.denominator())] -= 1 C = ComplexField() for val in tmp: if tmp[val] > 0: G += text(str(tmp[val]), exp(C(-.2 + 2 * 3.14159 * I * val[0] / val[1])), fontsize=30, axes=False, color="green") if tmp[val] < 0: G += text(str(abs(tmp[val])), exp(C(.2 + 2 * 3.14159 * I * val[0] / val[1])), fontsize=30, axes=False, color="blue") return G
def plot(self, polygon_label=True): r""" Returns a plot of the GraphicalPolygon. EXAMPLES:: sage: from flatsurf import * sage: s = similarity_surfaces.example() sage: from flatsurf.graphical.surface import GraphicalSurface sage: gs = GraphicalSurface(s) sage: gs.graphical_polygon(0).set_fill_color("red") sage: gs.graphical_polygon(0).plot() Graphics object consisting of 5 graphics primitives """ from sage.plot.point import point2d from sage.plot.polygon import polygon2d from sage.plot.graphics import Graphics from sage.plot.text import text p = polygon2d(self._v, **self.polygon_options()) if self._label is not None and polygon_label: p += text(str(self._label), sum(self._v) / len(self._v), **self.polygon_label_options()) if self._edge_labels: opt = self.edge_label_options() n = self.base_polygon().num_edges() for i in range(n): lab = str(i) if self._edge_labels is True else self._edge_labels[i] if lab: e = self._v[(i + 1) % n] - self._v[i] no = V((-e[1], e[0])) p += text(lab, self._v[i] + 0.3 * e + 0.05 * no, **self.edge_label_options()) return p
def plot3d_cube(self, mv, title=True): """ Displays F,U,R faces of the cube after the given move mv, where mv is a string in the Singmaster notation. Mostly included for the purpose of drawing pictures and checking moves. The first one below is "superflip+4 spot" (in 26q\* moves) and the second one is the superflip (in 20f\* moves). Type show(P) to view them. EXAMPLES:: sage: rubik = CubeGroup() sage: P = rubik.plot3d_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^3*U*L^3*R*D*R^3*L^3*D^2") sage: P = rubik.plot3d_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^3*F^2*D^3*R^2*U^3*F^2*D^3") """ g = self.parse(mv) state = self.facets(g) clr_any = white shown_labels = range(1, 9) + range(17, 33) clr = [color_of_square(state[c - 1]) for c in shown_labels] cubiesR = [ plot3d_cubie(cubie_centers(c), cubie_colors(c, state)) for c in [32, 31, 30, 29, 28, 27, 26, 25] ] cubeR = sum(cubiesR) cubiesU = [ plot3d_cubie(cubie_centers(c), cubie_colors(c, state)) for c in range(1, 9) ] cubeU = sum(cubiesU) cubiesF = [ plot3d_cubie(cubie_centers(c), cubie_colors(c, state)) for c in [22, 23, 24, 20, 21] ] cubeF = sum(cubiesF) centerR = polygon_plot3d( [[1, 3, 1], [2, 3, 1], [2, 3, 2], [1, 3, 2], [1, 3, 1]], rgbcolor=green) centerF = polygon_plot3d( [[3, 1, 1], [3, 2, 1], [3, 2, 2], [3, 1, 2], [3, 1, 1]], rgbcolor=red) centerU = polygon_plot3d( [[1, 1, 3], [1, 2, 3], [2, 2, 3], [2, 1, 3], [1, 1, 3]], rgbcolor=lpurple) centers = centerF + centerR + centerU P = cubeR + cubeF + cubeU + centers P.axes(show=False) if title == True: t1 = text('Up, Front, and Right faces. ', (-0.2, -2.5)) t2 = text(' sagemath.org', (0.8, -3.1), rgbcolor=lgrey) t3 = text(" ", (3.5, 0), rgbcolor=white) P = P + t1 + t2 + t3 P.axes(show=False) return P return P
def plot_label(self, label, **options): r""" Write the label of the polygon as text. Set ``position`` to a pair (x,y) to determine where the label is drawn (in graphical coordinates). If this parameter is not provided, the label is positioned in the baricenter of the polygon. Other options are processed as in sage.plot.text.text. """ if "position" in options: return text(str(label), options.pop("position"), **options) else: return text(str(label), sum(self._v) / len(self._v), **options)
def plot_n_cylinders(self, n, labels=True): r""" EXAMPLES:: sage: from slabbe.markov_transformation import markov_transformations sage: T = markov_transformations.Selmer() sage: G = T.plot_n_cylinders(3) TESTS:: sage: G = T.plot_n_cylinders(0) """ from sage.plot.graphics import Graphics from sage.plot.polygon import polygon from sage.plot.text import text M3to2 = projection_matrix(3, 2) G = Graphics() for w, cyl in self.n_cylinders_iterator(n): columns = cyl.columns() G += polygon((M3to2 * col / col.norm(1) for col in columns), fill=False) if labels: sum_cols = sum(columns) G += text("{}".format(w), M3to2 * sum_cols / sum_cols.norm(1)) return G
def plot_cube(self, mv, title=True, colors = [lpurple, yellow, red, green, orange, blue]): """ Input the move mv, as a string in the Singmaster notation, and output the 2-d plot of the cube in that state. Type P.show() to display any of the plots below. EXAMPLES:: sage: rubik = CubeGroup() sage: P = rubik.plot_cube("R^2*U^2*R^2*U^2*R^2*U^2", title = False) sage: # (R^2U^2)^3 permutes 2 pairs of edges (uf,ub)(fr,br) sage: P = rubik.plot_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^3*F^2*D^3*R^2*U^3*F^2*D^3") sage: # the superflip (in 20f* moves) sage: P = rubik.plot_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^3*U*L^3*R*D*R^3*L^3*D^2") sage: # "superflip+4 spot" (in 26q* moves) """ g = self.parse(mv) state = self.facets(g) #print state cubies = [create_poly(index2singmaster(state[x]), color_of_square(x+1, colors)) for x in range(48)] centers = [create_poly('%s_center' % "ulfrbd"[i], colors[i]) for i in range(6)] clrs = sum(cubies) + sum(centers) clrs.axes(show=False) if title == True: t = text('sagemath.org', (7.8,-3.5),rgbcolor=lgrey) P = clrs+t P.axes(show=False) return P return clrs
def return_plot(self, interval=(0,1), adaptive_recursion=4, plot_points=4, adaptive_tolerance=0.10): r""" Return a plot of percolation probability using basic sage plot settings. INPUT: - ``interval``, default=(0,1) - ``adaptive_recursion``, default=0 - ``plot_points``, default=10 - ``adaptive_tolerance`` default=0.10 EXAMPLES:: sage: from slabbe import PercolationProbability sage: T = PercolationProbability(d=2, n=10, stop=100) sage: T.return_plot() # optional long Graphics object consisting of 1 graphics primitive """ P = plot(self, interval, adaptive_recursion=adaptive_recursion, plot_points=plot_points, adaptive_tolerance=adaptive_tolerance) P += text(repr(self), (0.8,0.2)) return P
def return_plot(self, interval=(0, 1), adaptive_recursion=4, plot_points=4, adaptive_tolerance=0.10): r""" Return a plot of percolation probability using basic sage plot settings. INPUT: - ``interval``, default=(0,1) - ``adaptive_recursion``, default=0 - ``plot_points``, default=10 - ``adaptive_tolerance`` default=0.10 EXAMPLES:: sage: from slabbe import PercolationProbability sage: T = PercolationProbability(d=2, n=10, stop=100) sage: T.return_plot() # optional long Graphics object consisting of 1 graphics primitive """ P = plot(self, interval, adaptive_recursion=adaptive_recursion, plot_points=plot_points, adaptive_tolerance=adaptive_tolerance) P += text(repr(self), (0.8, 0.2)) return P
def plot(self): from sage.functions.trig import sin, cos from sage.plot.circle import circle from sage.plot.point import point from sage.plot.text import text p = circle((0,0),1) for i in range(self._dimension): a = self._alpha[i] p += point([cos(2*pi*a),sin(2*pi*a)], color='blue', size=100) p += text(r"$\alpha_%i$"%(self._i_alpha[i]+1), [1.2*cos(2*pi*a),1.2*sin(2*pi*a)],fontsize=40) for i in range(self._dimension): b = self._beta[i] p += point([cos(2*pi*b),sin(2*pi*b)], color='red', size=100) p += text(r"$\beta_%i$"%(self._i_beta[i]+1), [1.2*cos(2*pi*b),1.2*sin(2*pi*b)],fontsize=40) p.show(axes=False, xmin=-1, xmax=1, ymin=-1, ymax=1)
def eqn_list_to_curve_plot(L, rat_pts): xpoly_rng = PolynomialRing(QQ, 'x') poly_tup = [xpoly_rng(tup) for tup in L] f = poly_tup[0] h = poly_tup[1] g = f + h**2 / 4 if len(g.real_roots()) == 0 and g(0) < 0: return text(r"$X(\mathbb{R})=\emptyset$", (1, 1), fontsize=50) X0 = [real(z[0]) for z in g.base_extend(CC).roots() ] + [real(z[0]) for z in g.derivative().base_extend(CC).roots()] a, b = inflate_interval(min(X0), max(X0), 1.5) groots = [a] + g.real_roots() + [b] if b - a < 1e-7: a = -3 b = 3 groots = [a, b] ngints = len(groots) - 1 plotzones = [] npts = 100 for j in range(ngints): c = groots[j] d = groots[j + 1] if g((c + d) / 2) < 0: continue (c, d) = inflate_interval(c, d, 1.1) s = (d - c) / npts u = c yvals = [] for i in range(npts + 1): v = g(u) if v > 0: v = sqrt(v) w = -h(u) / 2 yvals.append(w + v) yvals.append(w - v) u += s (m, M) = inflate_interval(min(yvals), max(yvals), 1.2) plotzones.append((c, d, m, M)) x = var('x') y = var('y') plot = sum( implicit_plot(y**2 + y * h(x) - f(x), (x, R[0], R[1]), (y, R[2], R[3]), aspect_ratio='automatic', plot_points=500, zorder=1) for R in plotzones) xmin = min([R[0] for R in plotzones]) xmax = max([R[1] for R in plotzones]) ymin = min([R[2] for R in plotzones]) ymax = max([R[3] for R in plotzones]) for P in rat_pts: (x, y, z) = P z = ZZ(z) if z: # Do not attempt to plot points at infinity x = ZZ(x) / z y = ZZ(y) / z**3 if x >= xmin and x <= xmax and y >= ymin and y <= ymax: plot += point((x, y), color='red', size=40, zorder=2) return plot
def plot_profile(self): from sage.plot.line import line2d from sage.plot.point import point from sage.plot.text import text p_color, p_number, p_ev = self.profile() d = len(p_color) color = lambda i: 'blue' if p_color[i] else 'red' p = lambda i: [0,0] if i == -1 else [i+1,p_number[i]] plt = point([0,0],marker='x',size=100) for i in range(d): plt += line2d([p(i-1),p(i)],alpha=.5) plt += point(p(i), color=color(i), size=100) if p_color[i]: [x,y] = p(i) plt += text(r"$\alpha_%i$"%(self._i_alpha[p_ev[i]]+1), [x,y+.2], fontsize = 40) else: [x,y] = p(i) plt += text(r"$\beta_%i$"%(self._i_beta[p_ev[i]]+1), [x,y+.2], fontsize = 40) plt.show(axes=False, ymin=0, xmin=0, xmax=d)
def plot3d_cube(self,mv,title=True): """ Displays F,U,R faces of the cube after the given move mv, where mv is a string in the Singmaster notation. Mostly included for the purpose of drawing pictures and checking moves. The first one below is "superflip+4 spot" (in 26q\* moves) and the second one is the superflip (in 20f\* moves). Type show(P) to view them. EXAMPLES:: sage: rubik = CubeGroup() sage: P = rubik.plot3d_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^3*U*L^3*R*D*R^3*L^3*D^2") sage: P = rubik.plot3d_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^3*F^2*D^3*R^2*U^3*F^2*D^3") """ g = self.parse(mv) state = self.facets(g) clr_any = white shown_labels = range(1,9)+range(17,33) clr = [color_of_square(state[c-1]) for c in shown_labels] cubiesR = [plot3d_cubie(cubie_centers(c),cubie_colors(c,state)) for c in [32,31,30,29,28,27,26,25]] cubeR = sum(cubiesR) cubiesU = [plot3d_cubie(cubie_centers(c),cubie_colors(c,state)) for c in range(1,9)] cubeU = sum(cubiesU) cubiesF = [plot3d_cubie(cubie_centers(c),cubie_colors(c,state)) for c in [22,23,24,20,21]] cubeF = sum(cubiesF) centerR = polygon_plot3d([[1,3,1],[2,3,1],[2,3,2],[1,3,2],[1,3,1]],rgbcolor=green) centerF = polygon_plot3d([[3,1,1],[3,2,1],[3,2,2],[3,1,2],[3,1,1]],rgbcolor=red) centerU = polygon_plot3d([[1,1,3],[1,2,3],[2,2,3],[2,1,3],[1,1,3]],rgbcolor=lpurple) centers = centerF+centerR+centerU P = cubeR+cubeF+cubeU+centers P.axes(show=False) if title == True: t1 = text('Up, Front, and Right faces. ' , (-0.2,-2.5)) t2 = text(' sagemath.org', (0.8,-3.1),rgbcolor=lgrey) t3 = text(" ",(3.5,0),rgbcolor=white) P = P+t1+t2+t3 P.axes(show=False) return P return P
def eqn_list_to_curve_plot(L,rat_pts): xpoly_rng = PolynomialRing(QQ,'x') poly_tup = [xpoly_rng(tup) for tup in L] f = poly_tup[0] h = poly_tup[1] g = f+h**2/4 if len(g.real_roots())==0 and g(0)<0: return text("$X(\mathbb{R})=\emptyset$",(1,1),fontsize=50) X0 = [real(z[0]) for z in g.base_extend(CC).roots()]+[real(z[0]) for z in g.derivative().base_extend(CC).roots()] a,b = inflate_interval(min(X0),max(X0),1.5) groots = [a]+g.real_roots()+[b] if b-a<1e-7: a=-3 b=3 groots=[a,b] ngints = len(groots)-1 plotzones = [] npts = 100 for j in range(ngints): c = groots[j] d = groots[j+1] if g((c+d)/2)<0: continue (c,d) = inflate_interval(c,d,1.1) s = (d-c)/npts u = c yvals = [] for i in range(npts+1): v = g(u) if v>0: v = sqrt(v) w = -h(u)/2 yvals.append(w+v) yvals.append(w-v) u += s (m,M) = inflate_interval(min(yvals),max(yvals),1.2) plotzones.append((c,d,m,M)) x = var('x') y = var('y') plot=sum(implicit_plot(y**2 + y*h(x) - f(x), (x,R[0],R[1]),(y,R[2],R[3]), aspect_ratio='automatic', plot_points=500, zorder=1) for R in plotzones) xmin=min([R[0] for R in plotzones]) xmax=max([R[1] for R in plotzones]) ymin=min([R[2] for R in plotzones]) ymax=max([R[3] for R in plotzones]) for P in rat_pts: (x,y,z)=eval(P.replace(':',',')) z=ZZ(z) if z: # Do not attempt to plot points at infinity x=ZZ(x)/z y=ZZ(y)/z**3 if x >= xmin and x <= xmax and y >= ymin and y <= ymax: plot += point((x,y),color='red',size=40,zorder=2) return plot
def text(self, label, position): r""" Return text widget with label ``label`` at position ``position`` INPUT: - ``label`` -- a string, or a Sage object upon which latex will be called - ``position`` -- a position EXAMPLES:: sage: L = RootSystem(["A",2]).root_lattice() sage: options = L.plot_parse_options() sage: list(options.text("coucou", [0,1])) [Text 'coucou' at the point (0.0,1.0)] sage: list(options.text(L.simple_root(1), [0,1])) [Text '$\alpha_{1}$' at the point (0.0,1.0)] sage: options = RootSystem(["A",2]).root_lattice().plot_parse_options(labels=False) sage: options.text("coucou", [0,1]) 0 sage: options = RootSystem(["B",3]).root_lattice().plot_parse_options() sage: print options.text("coucou", [0,1,2]).x3d_str() <Transform translation='0 1 2'> <Shape><Text string='coucou' solid='true'/><Appearance><Material diffuseColor='0.0 0.0 0.0' shininess='1' specularColor='0.0 0.0 0.0'/></Appearance></Shape> <BLANKLINE> </Transform> """ if self.labels: if self.dimension <= 2: if not isinstance(label, basestring): label = "$" + str(latex(label)) + "$" from sage.plot.text import text return text(label, position, fontsize=15) elif self.dimension == 3: # LaTeX labels not yet supported in 3D if isinstance(label, basestring): label = label.replace("{", "").replace("}", "").replace("$", "").replace("_", "") else: label = str(label) from sage.plot.plot3d.shapes2 import text3d return text3d(label, position) else: raise NotImplementedError("Plots in dimension > 3") else: return self.empty()
def text(self, label, position): r""" Return text widget with label ``label`` at position ``position`` INPUT: - ``label`` -- a string, or a Sage object upon which latex will be called - ``position`` -- a position EXAMPLES:: sage: L = RootSystem(["A",2]).root_lattice() sage: options = L.plot_parse_options() sage: list(options.text("coucou", [0,1])) [Text 'coucou' at the point (0.0,1.0)] sage: list(options.text(L.simple_root(1), [0,1])) [Text '$\alpha_{1}$' at the point (0.0,1.0)] sage: options = RootSystem(["A",2]).root_lattice().plot_parse_options(labels=False) sage: options.text("coucou", [0,1]) 0 sage: options = RootSystem(["B",3]).root_lattice().plot_parse_options() sage: print options.text("coucou", [0,1,2]).x3d_str() <Transform translation='0 1 2'> <Shape><Text string='coucou' solid='true'/><Appearance><Material diffuseColor='0.0 0.0 0.0' shininess='1' specularColor='0.0 0.0 0.0'/></Appearance></Shape> <BLANKLINE> </Transform> """ if self.labels: if self.dimension <= 2: if not isinstance(label, basestring): label = "$" + str(latex(label)) + "$" from sage.plot.text import text return text(label, position, fontsize=15) elif self.dimension == 3: # LaTeX labels not yet supported in 3D if isinstance(label, basestring): label = label.replace("{", "").replace("}", "").replace( "$", "").replace("_", "") else: label = str(label) from sage.plot.plot3d.shapes2 import text3d return text3d(label, position) else: raise NotImplementedError("Plots in dimension > 3") else: return self.empty()
def circle_image(A,B): G = Graphics() G += circle((0,0), 1 , color = 'grey') from collections import defaultdict tmp = defaultdict(int) for a in A: for j in range(a): if gcd(j,a) == 1: rational = Rational(j)/Rational(a) tmp[(rational.numerator(),rational.denominator())] += 1 for b in B: for j in range(b): if gcd(j,b) == 1: rational = Rational(j)/Rational(b) tmp[(rational.numerator(),rational.denominator())] -= 1 C = ComplexField() for val in tmp: if tmp[val] > 0: G += text(str(tmp[val]),exp(C(2*3.14159*I*val[0]/val[1])), fontsize = 30, axes = False, color = "green") if tmp[val] < 0: G += text(str(abs(tmp[val])),exp(C(2*3.14159*I*val[0]/val[1])), fontsize = 30, axes = False, color = "red") return G
def plot(self): from sage.functions.trig import sin, cos from sage.plot.circle import circle from sage.plot.point import point from sage.plot.text import text p = circle((0, 0), 1) for i in range(self._dimension): a = self._alpha[i] p += point([cos(2 * pi * a), sin(2 * pi * a)], color='blue', size=100) p += text(r"$\alpha_%i$" % (self._i_alpha[i] + 1), [1.2 * cos(2 * pi * a), 1.2 * sin(2 * pi * a)], fontsize=40) for i in range(self._dimension): b = self._beta[i] p += point([cos(2 * pi * b), sin(2 * pi * b)], color='red', size=100) p += text(r"$\beta_%i$" % (self._i_beta[i] + 1), [1.2 * cos(2 * pi * b), 1.2 * sin(2 * pi * b)], fontsize=40) p.show(axes=False, xmin=-1, xmax=1, ymin=-1, ymax=1)
def plot_profile(self): from sage.plot.line import line2d from sage.plot.point import point from sage.plot.text import text p_color, p_number, p_ev = self.profile() d = len(p_color) color = lambda i: 'blue' if p_color[i] else 'red' p = lambda i: [0, 0] if i == -1 else [i + 1, p_number[i]] plt = point([0, 0], marker='x', size=100) for i in range(d): plt += line2d([p(i - 1), p(i)], alpha=.5) plt += point(p(i), color=color(i), size=100) if p_color[i]: [x, y] = p(i) plt += text(r"$\alpha_%i$" % (self._i_alpha[p_ev[i]] + 1), [x, y + .2], fontsize=40) else: [x, y] = p(i) plt += text(r"$\beta_%i$" % (self._i_beta[p_ev[i]] + 1), [x, y + .2], fontsize=40) plt.show(axes=False, ymin=0, xmin=0, xmax=d)
def circle_image(A, B): G = Graphics() G += circle((0, 0), 1, color='black', thickness=3) G += circle( (0, 0), 1.4, color='black', alpha=0 ) # This adds an invisible framing circle to the plot, which protects the aspect ratio from being skewed. from collections import defaultdict tmp = defaultdict(int) for a in A: for j in range(a): if gcd(j, a) == 1: rational = Rational(j) / Rational(a) tmp[(rational.numerator(), rational.denominator())] += 1 for b in B: for j in range(b): if gcd(j, b) == 1: rational = Rational(j) / Rational(b) tmp[(rational.numerator(), rational.denominator())] -= 1 C = ComplexField() color1 = (41 / 255, 95 / 255, 45 / 255) color2 = (0 / 255, 0 / 255, 150 / 255) for val in tmp: if tmp[val] > 0: G += text(str(tmp[val]), exp(C(-.2 + 2 * 3.14159 * I * val[0] / val[1])), fontsize=30, axes=False, color=color1) if tmp[val] < 0: G += text(str(abs(tmp[val])), exp(C(.2 + 2 * 3.14159 * I * val[0] / val[1])), fontsize=30, axes=False, color=color2) return G
def plot_n_matrices_eigenvectors(self, n, side='right', color_index=0, draw_line=False): r""" INPUT: - ``n`` -- integer, length - ``side`` -- ``'left'`` or ``'right'``, drawing left or right eigenvectors - ``color_index`` -- 0 for first letter, -1 for last letter - ``draw_line`` -- boolean EXAMPLES:: sage: from slabbe.matrix_cocycle import cocycles sage: ARP = cocycles.ARP() sage: G = ARP.plot_n_matrices_eigenvectors(2) """ from sage.plot.graphics import Graphics from sage.plot.point import point from sage.plot.line import line from sage.plot.text import text from sage.plot.colors import hue from sage.modules.free_module_element import vector from .matrices import M3to2 R = self.n_matrices_eigenvectors(n) L = [(w, M3to2*(a/sum(a)), M3to2*(b/sum(b))) for (w,a,b) in R] G = Graphics() alphabet = self._language._alphabet color_ = dict( (letter, hue(i/float(len(alphabet)))) for i,letter in enumerate(alphabet)) for letter in alphabet: L_filtered = [(w,p1,p2) for (w,p1,p2) in L if w[color_index] == letter] words,rights,lefts = zip(*L_filtered) if side == 'right': G += point(rights, color=color_[letter], legend_label=letter) elif side == 'left': G += point(lefts, color=color_[letter], legend_label=letter) else: raise ValueError("side(=%s) should be left or right" % side) if draw_line: for (a,b) in L: G += line([a,b], color='black', linestyle=":") G += line([M3to2*vector(a) for a in [(1,0,0), (0,1,0), (0,0,1), (1,0,0)]]) title = "%s eigenvectors, colored by letter w[%s] of cylinder w" % (side, color_index) G += text(title, (0.5, 1.05), axis_coords=True) G.axes(False) return G
def plot_n_matrices_eigenvectors(self, n, side='right', color_index=0, draw_line=False): r""" INPUT: - ``n`` -- integer, length - ``side`` -- ``'left'`` or ``'right'``, drawing left or right eigenvectors - ``color_index`` -- 0 for first letter, -1 for last letter - ``draw_line`` -- boolean EXAMPLES:: sage: from slabbe.matrix_cocycle import cocycles sage: ARP = cocycles.ARP() sage: G = ARP.plot_n_matrices_eigenvectors(2) """ from sage.plot.graphics import Graphics from sage.plot.point import point from sage.plot.line import line from sage.plot.text import text from sage.plot.colors import hue from sage.modules.free_module_element import vector from matrices import M3to2 R = self.n_matrices_eigenvectors(n) L = [(w, M3to2*(a/sum(a)), M3to2*(b/sum(b))) for (w,a,b) in R] G = Graphics() alphabet = self._language._alphabet color_ = dict( (letter, hue(i/float(len(alphabet)))) for i,letter in enumerate(alphabet)) for letter in alphabet: L_filtered = [(w,p1,p2) for (w,p1,p2) in L if w[color_index] == letter] words,rights,lefts = zip(*L_filtered) if side == 'right': G += point(rights, color=color_[letter], legend_label=letter) elif side == 'left': G += point(lefts, color=color_[letter], legend_label=letter) else: raise ValueError("side(=%s) should be left or right" % side) if draw_line: for (a,b) in L: G += line([a,b], color='black', linestyle=":") G += line([M3to2*vector(a) for a in [(1,0,0), (0,1,0), (0,0,1), (1,0,0)]]) title = "%s eigenvectors, colored by letter w[%s] of cylinder w" % (side, color_index) G += text(title, (0.5, 1.05), axis_coords=True) G.axes(False) return G
def triangulation(self): r""" Plot a regular polygon with some diagonals. If ``self`` is positive and integral then this will be a triangulation. .. PLOT:: :width: 600 px G = path_tableaux.FriezePattern([1,2,7,5,3,7,4,1]).triangulation() p = graphics_array(G, 7, 6) sphinx_plot(p) EXAMPLES:: sage: path_tableaux.FriezePattern([1,2,7,5,3,7,4,1]).triangulation() Graphics object consisting of 25 graphics primitives sage: path_tableaux.FriezePattern([1,2,1/7,5,3]).triangulation() Graphics object consisting of 12 graphics primitives sage: K.<sqrt2> = NumberField(x^2-2) sage: path_tableaux.FriezePattern([1,sqrt2,1,sqrt2,3,2*sqrt2,5,3*sqrt2,1], field=K).triangulation() Graphics object consisting of 24 graphics primitives """ n = len(self) - 1 cd = CylindricalDiagram(self).diagram from sage.plot.plot import Graphics from sage.plot.line import line from sage.plot.text import text from sage.functions.trig import sin, cos from sage.all import pi G = Graphics() G.set_aspect_ratio(1.0) vt = [(cos(2 * theta * pi / (n)), sin(2 * theta * pi / (n))) for theta in range(n + 1)] for i, p in enumerate(vt): G += text(str(i), [1.05 * p[0], 1.05 * p[1]]) for i, r in enumerate(cd): for j, a in enumerate(r[:n]): if a == 1: G += line([vt[i], vt[j]]) G.axes(False) return G
def eqn_list_to_curve_plot(L): xpoly_rng = PolynomialRing(QQ, 'x') poly_tup = [xpoly_rng(tup) for tup in L] f = poly_tup[0] h = poly_tup[1] g = f + h**2 / 4 if len(g.real_roots()) == 0 and g(0) < 0: return text("$X(\mathbb{R})=\emptyset$", (1, 1), fontsize=50) X0 = [real(z[0]) for z in g.base_extend(CC).roots() ] + [real(z[0]) for z in g.derivative().base_extend(CC).roots()] a, b = inflate_interval(min(X0), max(X0), 1.5) groots = [a] + g.real_roots() + [b] if b - a < 1e-7: a = -3 b = 3 groots = [a, b] ngints = len(groots) - 1 plotzones = [] npts = 100 for j in range(ngints): c = groots[j] d = groots[j + 1] if g((c + d) / 2) < 0: continue (c, d) = inflate_interval(c, d, 1.1) s = (d - c) / npts u = c yvals = [] for i in range(npts + 1): v = g(u) if v > 0: v = sqrt(v) w = -h(u) / 2 yvals.append(w + v) yvals.append(w - v) u += s (m, M) = inflate_interval(min(yvals), max(yvals), 1.2) plotzones.append((c, d, m, M)) x = var('x') y = var('y') return sum( implicit_plot(y**2 + y * h(x) - f(x), (x, R[0], R[1]), (y, R[2], R[3]), aspect_ratio='automatic', plot_points=500) for R in plotzones)
def eqn_list_to_curve_plot(L): xpoly_rng = PolynomialRing(QQ,'x') poly_tup = [xpoly_rng(tup) for tup in L] f = poly_tup[0] h = poly_tup[1] g = f+h**2/4 if len(g.real_roots())==0 and g(0)<0: return text("$X(\mathbb{R})=\emptyset$",(1,1),fontsize=50) X0 = [real(z[0]) for z in g.base_extend(CC).roots()]+[real(z[0]) for z in g.derivative().base_extend(CC).roots()] a,b = inflate_interval(min(X0),max(X0),1.5) groots = [a]+g.real_roots()+[b] if b-a<1e-7: a=-3 b=3 groots=[a,b] ngints = len(groots)-1 plotzones = [] npts = 100 for j in range(ngints): c = groots[j] d = groots[j+1] if g((c+d)/2)<0: continue (c,d) = inflate_interval(c,d,1.1) s = (d-c)/npts u = c yvals = [] for i in range(npts+1): v = g(u) if v>0: v = sqrt(v) w = -h(u)/2 yvals.append(w+v) yvals.append(w-v) u += s (m,M) = inflate_interval(min(yvals),max(yvals),1.2) plotzones.append((c,d,m,M)) x = var('x') y = var('y') return sum(implicit_plot(y**2 + y*h(x) - f(x), (x,R[0],R[1]), (y,R[2],R[3]), aspect_ratio='automatic', plot_points=500) for R in plotzones)
def plot_n_cylinders(self, n, labels=True): r""" EXAMPLES:: sage: from slabbe.matrix_cocycle import cocycles sage: C = cocycles.Sorted_ARP() sage: G = C.plot_n_cylinders(3) """ from sage.plot.graphics import Graphics from sage.plot.polygon import polygon from sage.plot.text import text from matrices import M3to2 G = Graphics() for w,cyl in self.n_cylinders_iterator(n): columns = cyl.columns() G += polygon((M3to2*col/col.norm(1) for col in columns), fill=False) if labels: sum_cols = sum(columns) G += text("{}".format(w), M3to2*sum_cols/sum_cols.norm(1)) return G
def plot_n_cylinders(self, n, labels=True): r""" EXAMPLES:: sage: from slabbe.matrix_cocycle import cocycles sage: C = cocycles.Sorted_ARP() sage: G = C.plot_n_cylinders(3) """ from sage.plot.graphics import Graphics from sage.plot.polygon import polygon from sage.plot.text import text from .matrices import M3to2 G = Graphics() for w,cyl in self.n_cylinders_iterator(n): columns = cyl.columns() G += polygon((M3to2*col/col.norm(1) for col in columns), fill=False) if labels: sum_cols = sum(columns) G += text("{}".format(w), M3to2*sum_cols/sum_cols.norm(1)) return G
def plot(self): r""" EXAMPLES:: sage: from slabbe import PolyhedronPartition sage: h = 1/2 sage: p = Polyhedron([(0,h),(0,1),(h,1)]) sage: q = Polyhedron([(0,0), (0,h), (h,1), (1,1), (1,h), (h,0)]) sage: r = Polyhedron([(h,0), (1,0), (1,h)]) sage: P = PolyhedronPartition([p,q,r]) sage: P.plot() Graphics object consisting of 21 graphics primitives """ from sage.plot.graphics import Graphics from sage.plot.text import text G = Graphics() for key,P in self: G += P.plot(fill='white') G += text(key, P.center()) return G
def plot(self, m, pointsize=100, thickness=3, axes=False): r""" Return 2d graphics object contained in the primal box [-m,m]^d. INPUT: - ``pointsize``, integer (default:``100``), - ``thickness``, integer (default:``3``), - ``axes``, bool (default:``False``), EXAMPLES:: sage: from slabbe import BondPercolationSample sage: S = BondPercolationSample(0.5,2) sage: S.plot(2) # optional long It works in 3d!!:: sage: S = BondPercolationSample(0.5,3) sage: S.plot(3, pointsize=10, thickness=1) # optional long Graphics3d Object """ s = "" s += "\\begin{tikzpicture}\n" s += "[inner sep=0pt,thick,\n" s += "reddot/.style={fill=red,draw=red,circle,minimum size=5pt}]\n" s += "\\clip %s rectangle %s;\n" % ((-m - .4, -m - .4), (m + .4, m + .4)) G = Graphics() for u in self.cluster_in_box(m + 1): G += point(u, color='blue', size=pointsize) for (u, v) in self.edges_in_box(m + 1): G += line((u, v), thickness=thickness, alpha=0.8) G += text("p=%.3f" % self._p, (0.5, 1.03), axis_coords=True, color='black') G += circle((0, 0), 0.5, color='red', thickness=thickness) if self._dimension == 2: G.axes(axes) return G
def plot(self, m, pointsize=100, thickness=3, axes=False): r""" Return 2d graphics object contained in the primal box [-m,m]^d. INPUT: - ``pointsize``, integer (default:``100``), - ``thickness``, integer (default:``3``), - ``axes``, bool (default:``False``), EXAMPLES:: sage: from slabbe import BondPercolationSample sage: S = BondPercolationSample(0.5,2) sage: S.plot(2) # optional long It works in 3d!!:: sage: S = BondPercolationSample(0.5,3) sage: S.plot(3, pointsize=10, thickness=1) # optional long Graphics3d Object """ s = "" s += "\\begin{tikzpicture}\n" s += "[inner sep=0pt,thick,\n" s += "reddot/.style={fill=red,draw=red,circle,minimum size=5pt}]\n" s += "\\clip %s rectangle %s;\n" % ((-m-.4,-m-.4), (m+.4,m+.4)) G = Graphics() for u in self.cluster_in_box(m+1): G += point(u, color='blue', size=pointsize) for (u,v) in self.edges_in_box(m+1): G += line((u,v), thickness=thickness, alpha=0.8) G += text("p=%.3f" % self._p, (0.5,1.03), axis_coords=True, color='black') G += circle((0,0), 0.5, color='red', thickness=thickness) if self._dimension == 2: G.axes(axes) return G
def plot_n_cylinders(self, n, labels=True): r""" EXAMPLES:: sage: from slabbe.markov_transformation import markov_transformations sage: T = markov_transformations.Selmer() sage: G = T.plot_n_cylinders(3) TESTS:: sage: G = T.plot_n_cylinders(0) """ from sage.plot.graphics import Graphics from sage.plot.polygon import polygon from sage.plot.text import text M3to2 = projection_matrix(3, 2) G = Graphics() for w,cyl in self.n_cylinders_iterator(n): columns = cyl.columns() G += polygon((M3to2*col/col.norm(1) for col in columns), fill=False) if labels: sum_cols = sum(columns) G += text("{}".format(w), M3to2*sum_cols/sum_cols.norm(1)) return G
def show(self, **args): r""" Displays the pseudoline arrangement as a wiring diagram. INPUT: - ``**args`` -- any arguments to be forwarded to the ``show`` method. In particular, to tune the dimensions, use the ``figsize`` argument (example below). EXAMPLES:: sage: from sage.geometry.pseudolines import PseudolineArrangement sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]] sage: p = PseudolineArrangement(permutations) sage: p.show(figsize=[7,5]) TESTS:: sage: from sage.geometry.pseudolines import PseudolineArrangement sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 0, 1], [2, 0, 1]] sage: p = PseudolineArrangement(permutations) sage: p.show() Traceback (most recent call last): ... ValueError: There has been a problem while plotting the figure... """ x = 1 from sage.plot.line import line from sage.plot.text import text lines = [[(0, self._n - 1 - i)] for i in range(self._n)] for i, j in self.transpositions(): iy = lines[i][-1][1] jy = lines[j][-1][1] lines[i].append((x, iy)) lines[j].append((x, jy)) if abs(iy - jy) != 1: raise ValueError( "There has been a problem while plotting the figure. It " + "seems that the lines are not correctly ordered. Please " + "check the pseudolines modules documentation, there is a " + "warning about that. ") lines[i].append((x + 2, jy)) lines[j].append((x + 2, iy)) x += 2 L = line([(1, 1)]) for i, l in enumerate(lines): l.append((x + 2, l[-1][1])) L += line(l) L += text(str(i), (0, l[0][1] + .3), horizontal_alignment="right") L += text(str(i), (x + 2, l[-1][1] + .3), horizontal_alignment="left") return L.show(axes=False, **args)
def plot_edge_label(self, i, label, **options): r""" Write label on the i-th edge. A parameter ``t`` in the interval [0,1] can be provided to position the label along the edge. A value of t=0 will position it at the starting vertex and t=1 will position it at the terminating vertex. Defaults to 0.3. If the parameter ``position`` can take the values "outside", "inside" or "edge" to indicate if the label should be drawn outside the polygon, inside the polygon or on the edge. Defaults to "inside". A ``push_off`` perturbation parameter controls how far off the edge the label is pushed. Other options are processed as in sage.plot.text.text. """ e = self._v[(i + 1) % self.base_polygon().num_edges()] - self._v[i] if "position" in options: if options["position"] not in ["inside", "outside", "edge"]: raise ValueError( "The 'position' parameter must take the value 'inside', 'outside', or 'edge'." ) pos = options.pop("position") else: pos = "inside" if pos == "outside": # position outside polygon. if "horizontal_alignment" in options: pass elif e[1] > 0: options["horizontal_alignment"] = "left" elif e[1] < 0: options["horizontal_alignment"] = "right" else: options["horizontal_alignment"] = "center" if "vertical_alignment" in options: pass elif e[0] > 0: options["vertical_alignment"] = "top" elif e[0] < 0: options["vertical_alignment"] = "bottom" else: options["vertical_alignment"] = "center" elif pos == "inside": # position inside polygon. if "horizontal_alignment" in options: pass elif e[1] < 0: options["horizontal_alignment"] = "left" elif e[1] > 0: options["horizontal_alignment"] = "right" else: options["horizontal_alignment"] = "center" if "vertical_alignment" in options: pass elif e[0] < 0: options["vertical_alignment"] = "top" elif e[0] > 0: options["vertical_alignment"] = "bottom" else: options["vertical_alignment"] = "center" else: # centered on edge. if "horizontal_alignment" in options: pass else: options["horizontal_alignment"] = "center" if "vertical_alignment" in options: pass else: options["vertical_alignment"] = "center" if "t" in options: t = RDF(options.pop("t")) else: t = 0.3 if "push_off" in options: push_off = RDF(options.pop("push_off")) else: push_off = 0.03 if pos == "outside": push_off = -push_off # Now push_off stores the amount it should be pushed into the polygon no = V((-e[1], e[0])) return text(label, self._v[i] + t * e + push_off * no, **options)
def plot_edge_label(self, i, label, **options): r""" Write label on the i-th edge. A parameter ``t`` in the interval [0,1] can be provided to position the label along the edge. A value of t=0 will position it at the starting vertex and t=1 will position it at the terminating vertex. Defaults to 0.3. If the parameter ``position`` can take the values "outside", "inside" or "edge" to indicate if the label should be drawn outside the polygon, inside the polygon or on the edge. Defaults to "inside". A ``push_off`` perturbation parameter controls how far off the edge the label is pushed. Other options are processed as in sage.plot.text.text. """ e = self._v[(i+1)%self.base_polygon().num_edges()] - self._v[i] if "position" in options: if options["position"] not in ["inside", "outside", "edge"]: raise ValueError("The 'position' parameter must take the value 'inside', 'outside', or 'edge'.") pos = options.pop("position") else: pos = "inside" if pos == "outside": # position outside polygon. if "horizontal_alignment" in options: pass elif e[1] > 0: options["horizontal_alignment"]="left" elif e[1] < 0: options["horizontal_alignment"]="right" else: options["horizontal_alignment"]="center" if "vertical_alignment" in options: pass elif e[0] > 0: options["vertical_alignment"]="top" elif e[0] < 0: options["vertical_alignment"]="bottom" else: options["vertical_alignment"]="center" elif pos == "inside": # position inside polygon. if "horizontal_alignment" in options: pass elif e[1] < 0: options["horizontal_alignment"]="left" elif e[1] > 0: options["horizontal_alignment"]="right" else: options["horizontal_alignment"]="center" if "vertical_alignment" in options: pass elif e[0] < 0: options["vertical_alignment"]="top" elif e[0] > 0: options["vertical_alignment"]="bottom" else: options["vertical_alignment"]="center" else: # centered on edge. if "horizontal_alignment" in options: pass else: options["horizontal_alignment"]="center" if "vertical_alignment" in options: pass else: options["vertical_alignment"]="center" if "t" in options: t = RDF(options.pop("t")) else: t = 0.3 if "push_off" in options: push_off = RDF(options.pop("push_off")) else: push_off = 0.03 if pos == "outside": push_off = -push_off # Now push_off stores the amount it should be pushed into the polygon no = V((-e[1], e[0])) return text(label, self._v[i] + t * e + push_off * no, **options)
def plot(self, chart=None, ambient_coords=None, mapping=None, size=10, color='black', label=None, label_color=None, fontsize=10, label_offset=0.1, parameters=None): r""" Plot the current point (``self``) in a Cartesian graph based on the coordinates of some ambient chart. The point is drawn in terms of two (2D graphics) or three (3D graphics) coordinates of a given chart, called hereafter the *ambient chart*. The domain of the ambient chart must contain the point, or its image by a differentiable mapping `\Phi`. INPUT: - ``chart`` -- (default: ``None``) the ambient chart (see above); if ``None``, the ambient chart is set the default chart of ``self.containing_set()`` - ``ambient_coords`` -- (default: ``None``) tuple containing the 2 or 3 coordinates of the ambient chart in terms of which the plot is performed; if ``None``, all the coordinates of the ambient chart are considered - ``mapping`` -- (default: ``None``) differentiable mapping `\Phi` (instance of :class:`~sage.geometry.manifolds.diffmapping.DiffMapping`) providing the link between the point `p` represented by ``self`` and the ambient chart ``chart``: the domain of ``chart`` must contain `\Phi(p)`; if ``None``, the identity mapping is assumed - ``size`` -- (default: 10) size of the point once drawn as a small disk or sphere - ``color`` -- (default: 'black') color of the point - ``label`` -- (default: ``None``) label printed next to the point; if ``None``, the point's name is used. - ``label_color`` -- (default: ``None``) color to print the label; if ``None``, the value of ``color`` is used - ``fontsize`` -- (default: 10) size of the font used to print the label - ``label_offset`` -- (default: 0.1) determines the separation between the point and its label - ``parameters`` -- (default: ``None``) dictionary giving the numerical values of the parameters that may appear in the point coordinates OUTPUT: - a graphic object, either an instance of :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on 2 coordinates of the ambient chart) or an instance of :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e. based on 3 coordinates of the ambient chart) EXAMPLES: Drawing a point on a 2-dimensional manifold:: sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: p = M.point((1,3), name='p') sage: g = p.plot(X) sage: print g Graphics object consisting of 2 graphics primitives sage: gX = X.plot() # plot of the coordinate grid sage: show(g+gX) # display of the point atop the coordinate grid Actually, since ``X`` is the default chart of the open set in which ``p`` has been defined, it can be skipped in the arguments of ``plot``:: sage: g = p.plot() sage: show(g+gX) Call with some options:: sage: g = p.plot(chart=X, size=40, color='green', label='$P$', ....: label_color='blue', fontsize=20, label_offset=0.3) sage: show(g+gX) Use of the ``parameters`` option to set a numerical value of some symbolic variable:: sage: a = var('a') sage: q = M.point((a,2*a), name='q') sage: gq = q.plot(parameters={a:-2}) sage: show(g+gX+gq) The numerical value is used only for the plot:: sage: q.coord() (a, 2*a) Drawing a point on a 3-dimensional manifold:: sage: M = Manifold(3, 'M') sage: X.<x,y,z> = M.chart() sage: p = M.point((2,1,3), name='p') sage: g = p.plot() sage: print g Graphics3d Object sage: gX = X.plot(nb_values=5) # coordinate mesh cube sage: show(g+gX) # display of the point atop the coordinate mesh Call with some options:: sage: g = p.plot(chart=X, size=40, color='green', label='P_1', ....: label_color='blue', fontsize=20, label_offset=0.3) sage: show(g+gX) An example of plot via a differential mapping: plot of a point on a 2-sphere viewed in the 3-dimensional space ``M``:: sage: S2 = Manifold(2, 'S^2') sage: U = S2.open_subset('U') # the open set covered by spherical coord. sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') sage: p = U.point((pi/4, pi/8), name='p') sage: F = S2.diff_mapping(M, {(XS, X): [sin(th)*cos(ph), ....: sin(th)*sin(ph), cos(th)]}, name='F') sage: F.display() F: S^2 --> M on U: (th, ph) |--> (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th)) sage: g = p.plot(chart=X, mapping=F) sage: gS2 = XS.plot(chart=X, mapping=F, nb_values=9) sage: show(g+gS2) Use of the option ``ambient_coords`` for plots on a 4-dimensional manifold:: sage: M = Manifold(4, 'M') sage: X.<t,x,y,z> = M.chart() sage: p = M.point((1,2,3,4), name='p') sage: g = p.plot(X, ambient_coords=(t,x,y)) # the coordinate z is skipped sage: gX = X.plot(X, ambient_coords=(t,x,y), nb_values=5) sage: show(g+gX) # 3D plot sage: g = p.plot(X, ambient_coords=(t,y,z)) # the coordinate x is skipped sage: gX = X.plot(X, ambient_coords=(t,y,z), nb_values=5) sage: show(g+gX) # 3D plot sage: g = p.plot(X, ambient_coords=(y,z)) # the coordinates t and x are skipped sage: gX = X.plot(X, ambient_coords=(y,z)) sage: show(g+gX) # 2D plot """ from sage.plot.point import point2d from sage.plot.text import text from sage.plot.graphics import Graphics from sage.plot.plot3d.shapes2 import point3d, text3d from sage.geometry.manifolds.chart import Chart # The ambient chart: if chart is None: chart = self.containing_set().default_chart() elif not isinstance(chart, Chart): raise TypeError("the argument 'chart' must be a coordinate chart") # The effective point to be plotted: if mapping is None: eff_point = self else: eff_point = mapping(self) # The coordinates of the ambient chart used for the plot: if ambient_coords is None: ambient_coords = chart._xx elif not isinstance(ambient_coords, tuple): ambient_coords = tuple(ambient_coords) nca = len(ambient_coords) if nca != 2 and nca != 3: raise TypeError("Bad number of ambient coordinates: " + str(nca)) # The point coordinates: coords = eff_point.coord(chart) xx = chart[:] xp = [coords[xx.index(c)] for c in ambient_coords] if parameters is not None: xps = [coord.substitute(parameters) for coord in xp] xp = xps xlab = [coord + label_offset for coord in xp] if label_color is None: label_color = color resu = Graphics() if nca == 2: if label is None: label = r'$' + self._latex_name + r'$' resu += point2d(xp, color=color, size=size) + \ text(label, xlab, fontsize=fontsize, color=label_color) else: if label is None: label = self._name resu += point3d(xp, color=color, size=size) + \ text3d(label, xlab, fontsize=fontsize, color=label_color) return resu
def plot(self, chart=None, ambient_coords=None, mapping=None, label=None, parameters=None, **kwds): r""" For real manifolds, plot ``self`` in a Cartesian graph based on the coordinates of some ambient chart. The point is drawn in terms of two (2D graphics) or three (3D graphics) coordinates of a given chart, called hereafter the *ambient chart*. The domain of the ambient chart must contain the point, or its image by a continuous manifold map `\Phi`. INPUT: - ``chart`` -- (default: ``None``) the ambient chart (see above); if ``None``, the ambient chart is set the default chart of ``self.parent()`` - ``ambient_coords`` -- (default: ``None``) tuple containing the 2 or 3 coordinates of the ambient chart in terms of which the plot is performed; if ``None``, all the coordinates of the ambient chart are considered - ``mapping`` -- (default: ``None``) :class:`~sage.manifolds.continuous_map.ContinuousMap`; continuous manifold map `\Phi` providing the link between the current point `p` and the ambient chart ``chart``: the domain of ``chart`` must contain `\Phi(p)`; if ``None``, the identity map is assumed - ``label`` -- (default: ``None``) label printed next to the point; if ``None``, the point's name is used - ``parameters`` -- (default: ``None``) dictionary giving the numerical values of the parameters that may appear in the point coordinates - ``size`` -- (default: 10) size of the point once drawn as a small disk or sphere - ``color`` -- (default: ``'black'``) color of the point - ``label_color`` -- (default: ``None``) color to print the label; if ``None``, the value of ``color`` is used - ``fontsize`` -- (default: 10) size of the font used to print the label - ``label_offset`` -- (default: 0.1) determines the separation between the point and its label OUTPUT: - a graphic object, either an instance of :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on 2 coordinates of the ambient chart) or an instance of :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e. based on 3 coordinates of the ambient chart) EXAMPLES: Drawing a point on a 2-dimensional manifold:: sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: p = M.point((1,3), name='p') sage: g = p.plot(X) sage: print(g) Graphics object consisting of 2 graphics primitives sage: gX = X.plot(max_range=4) # plot of the coordinate grid sage: g + gX # display of the point atop the coordinate grid Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(2, 'M', structure='topological') X = M.chart('x y'); x,y = X[:] p = M.point((1,3), name='p') g = p.plot(X) gX = X.plot(max_range=4) sphinx_plot(g+gX) Actually, since ``X`` is the default chart of the open set in which ``p`` has been defined, it can be skipped in the arguments of ``plot``:: sage: g = p.plot() sage: g + gX Graphics object consisting of 20 graphics primitives Call with some options:: sage: g = p.plot(chart=X, size=40, color='green', label='$P$', ....: label_color='blue', fontsize=20, label_offset=0.3) sage: g + gX Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(2, 'M', structure='topological') X = M.chart('x y'); x,y = X[:] p = M.point((1,3), name='p') g = p.plot(chart=X, size=40, color='green', label='$P$', \ label_color='blue', fontsize=20, label_offset=0.3) gX = X.plot(max_range=4) sphinx_plot(g+gX) Use of the ``parameters`` option to set a numerical value of some symbolic variable:: sage: a = var('a') sage: q = M.point((a,2*a), name='q') sage: gq = q.plot(parameters={a:-2}, label_offset=0.2) sage: g + gX + gq Graphics object consisting of 22 graphics primitives .. PLOT:: M = Manifold(2, 'M', structure='topological') X = M.chart('x y'); x,y = X[:] p = M.point((1,3), name='p') g = p.plot(chart=X, size=40, color='green', label='$P$', \ label_color='blue', fontsize=20, label_offset=0.3) var('a') q = M.point((a,2*a), name='q') gq = q.plot(parameters={a:-2}, label_offset=0.2) gX = X.plot(max_range=4) sphinx_plot(g+gX+gq) The numerical value is used only for the plot:: sage: q.coord() (a, 2*a) Drawing a point on a 3-dimensional manifold:: sage: M = Manifold(3, 'M', structure='topological') sage: X.<x,y,z> = M.chart() sage: p = M.point((2,1,3), name='p') sage: g = p.plot() sage: print(g) Graphics3d Object sage: gX = X.plot(number_values=5) # coordinate mesh cube sage: g + gX # display of the point atop the coordinate mesh Graphics3d Object Call with some options:: sage: g = p.plot(chart=X, size=40, color='green', label='P_1', ....: label_color='blue', fontsize=20, label_offset=0.3) sage: g + gX Graphics3d Object An example of plot via a mapping: plot of a point on a 2-sphere viewed in the 3-dimensional space ``M``:: sage: S2 = Manifold(2, 'S^2', structure='topological') sage: U = S2.open_subset('U') # the open set covered by spherical coord. sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') sage: p = U.point((pi/4, pi/8), name='p') sage: F = S2.continuous_map(M, {(XS, X): [sin(th)*cos(ph), ....: sin(th)*sin(ph), cos(th)]}, name='F') sage: F.display() F: S^2 --> M on U: (th, ph) |--> (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th)) sage: g = p.plot(chart=X, mapping=F) sage: gS2 = XS.plot(chart=X, mapping=F, number_values=9) sage: g + gS2 Graphics3d Object Use of the option ``ambient_coords`` for plots on a 4-dimensional manifold:: sage: M = Manifold(4, 'M', structure='topological') sage: X.<t,x,y,z> = M.chart() sage: p = M.point((1,2,3,4), name='p') sage: g = p.plot(X, ambient_coords=(t,x,y), label_offset=0.4) # the coordinate z is skipped sage: gX = X.plot(X, ambient_coords=(t,x,y), number_values=5) # long time sage: g + gX # 3D plot # long time Graphics3d Object sage: g = p.plot(X, ambient_coords=(t,y,z), label_offset=0.4) # the coordinate x is skipped sage: gX = X.plot(X, ambient_coords=(t,y,z), number_values=5) # long time sage: g + gX # 3D plot # long time Graphics3d Object sage: g = p.plot(X, ambient_coords=(y,z), label_offset=0.4) # the coordinates t and x are skipped sage: gX = X.plot(X, ambient_coords=(y,z)) sage: g + gX # 2D plot Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(4, 'M', structure='topological') X = M.chart('t x y z'); t,x,y,z = X[:] p = M.point((1,2,3,4), name='p') g = p.plot(X, ambient_coords=(y,z), label_offset=0.4) gX = X.plot(X, ambient_coords=(y,z)) sphinx_plot(g+gX) """ from sage.plot.point import point2d from sage.plot.text import text from sage.plot.graphics import Graphics from sage.plot.plot3d.shapes2 import point3d, text3d from sage.manifolds.chart import Chart if self._manifold.base_field_type() != 'real': raise NotImplementedError( 'plot of points on manifolds over fields different' ' from the real field is not implemented') # The ambient chart: if chart is None: chart = self.parent().default_chart() elif not isinstance(chart, Chart): raise TypeError("the argument 'chart' must be a coordinate chart") # The effective point to be plotted: if mapping is None: eff_point = self else: eff_point = mapping(self) # The coordinates of the ambient chart used for the plot: if ambient_coords is None: ambient_coords = chart[:] elif not isinstance(ambient_coords, tuple): ambient_coords = tuple(ambient_coords) nca = len(ambient_coords) if nca != 2 and nca != 3: raise TypeError( "invalid number of ambient coordinates: {}".format(nca)) # Extract the kwds options size = kwds['size'] color = kwds['color'] label_color = kwds['label_color'] fontsize = kwds['fontsize'] label_offset = kwds['label_offset'] # The point coordinates: coords = eff_point.coord(chart) xx = chart[:] xp = [coords[xx.index(c)] for c in ambient_coords] if parameters is not None: xps = [coord.substitute(parameters) for coord in xp] xp = xps xlab = [coord + label_offset for coord in xp] if label_color is None: label_color = color resu = Graphics() if nca == 2: if label is None: label = r'$' + self._latex_name + r'$' resu += (point2d(xp, color=color, size=size) + text(label, xlab, fontsize=fontsize, color=label_color)) else: if label is None: label = self._name resu += (point3d(xp, color=color, size=size) + text3d(label, xlab, fontsize=fontsize, color=label_color)) return resu
def plot_two_intervals(self, position=(0,0), vertical_alignment='center', horizontal_alignment='left', interval_height=0.1, labels_height=0.05, fontsize=14, labels=True, colors=None): r""" Returns a picture of the interval exchange transformation. INPUT: - ``position`` - a 2-uple of the position - ``horizontal_alignment`` - left (default), center or right - ``labels`` - boolean (default: True) - ``fontsize`` - the size of the label OUTPUT: 2d plot -- a plot of the two intervals (domain and range) EXAMPLES:: sage: t = iet.IntervalExchangeTransformation(('a b','b a'),[1,1]) sage: t.plot_two_intervals() Graphics object consisting of 8 graphics primitives """ from sage.plot.all import Graphics from sage.plot.line import line2d from sage.plot.text import text from sage.plot.colors import rainbow G = Graphics() lengths = [float(_) for _ in self._lengths] total_length = sum(lengths) if colors is None: colors = rainbow(len(self._permutation), 'rgbtuple') if horizontal_alignment == 'left': s = position[0] elif horizontal_alignment == 'center': s = position[0] - total_length / 2 elif horizontal_alignment == 'right': s = position[0] - total_length else: raise ValueError("horizontal_alignement must be left, center or right") top_height = position[1] + interval_height for i in self._permutation._intervals[0]: G += line2d([(s,top_height), (s+lengths[i],top_height)], rgbcolor=colors[i]) if labels: G += text(str(self._permutation._alphabet.unrank(i)), (s+float(lengths[i])/2, top_height+labels_height), horizontal_alignment='center', rgbcolor=colors[i], fontsize=fontsize) s += lengths[i] if horizontal_alignment == 'left': s = position[0] elif horizontal_alignment == 'center': s = position[0] - total_length / 2 elif horizontal_alignment == 'right': s = position[0] - total_length else: raise ValueError("horizontal_alignement must be left, center or right") bottom_height = position[1] - interval_height for i in self._permutation._intervals[1]: G += line2d([(s,bottom_height), (s+lengths[i],bottom_height)], rgbcolor=colors[i]) if labels: G += text(str(self._permutation._alphabet.unrank(i)), (s+float(lengths[i])/2, bottom_height-labels_height), horizontal_alignment='center', rgbcolor=colors[i], fontsize=fontsize) s += lengths[i] return G
def plot(self, chart=None, ambient_coords=None, mapping=None, color='blue', print_label=True, label=None, label_color=None, fontsize=10, label_offset=0.1, parameters=None, **extra_options): r""" Plot the vector in a Cartesian graph based on the coordinates of some ambient chart. The vector is drawn in terms of two (2D graphics) or three (3D graphics) coordinates of a given chart, called hereafter the *ambient chart*. The vector's base point `p` (or its image `\Phi(p)` by some differentiable mapping `\Phi`) must lie in the ambient chart's domain. If `\Phi` is different from the identity mapping, the vector actually depicted is `\mathrm{d}\Phi_p(v)`, where `v` is the current vector (``self``) (see the example of a vector tangent to the 2-sphere below, where `\Phi: S^2 \to \RR^3`). INPUT: - ``chart`` -- (default: ``None``) the ambient chart (see above); if ``None``, it is set to the default chart of the open set containing the point at which the vector (or the vector image via the differential `\mathrm{d}\Phi_p` of ``mapping``) is defined - ``ambient_coords`` -- (default: ``None``) tuple containing the 2 or 3 coordinates of the ambient chart in terms of which the plot is performed; if ``None``, all the coordinates of the ambient chart are considered - ``mapping`` -- (default: ``None``) :class:`~sage.manifolds.differentiable.diff_map.DiffMap`; differentiable mapping `\Phi` providing the link between the point `p` at which the vector is defined and the ambient chart ``chart``: the domain of ``chart`` must contain `\Phi(p)`; if ``None``, the identity mapping is assumed - ``scale`` -- (default: 1) value by which the length of the arrow representing the vector is multiplied - ``color`` -- (default: 'blue') color of the arrow representing the vector - ``print_label`` -- (boolean; default: ``True``) determines whether a label is printed next to the arrow representing the vector - ``label`` -- (string; default: ``None``) label printed next to the arrow representing the vector; if ``None``, the vector's symbol is used, if any - ``label_color`` -- (default: ``None``) color to print the label; if ``None``, the value of ``color`` is used - ``fontsize`` -- (default: 10) size of the font used to print the label - ``label_offset`` -- (default: 0.1) determines the separation between the vector arrow and the label - ``parameters`` -- (default: ``None``) dictionary giving the numerical values of the parameters that may appear in the coordinate expression of ``self`` (see example below) - ``**extra_options`` -- extra options for the arrow plot, like ``linestyle``, ``width`` or ``arrowsize`` (see :func:`~sage.plot.arrow.arrow2d` and :func:`~sage.plot.plot3d.shapes.arrow3d` for details) OUTPUT: - a graphic object, either an instance of :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on 2 coordinates of ``chart``) or an instance of :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e. based on 3 coordinates of ``chart``) EXAMPLES: Vector tangent to a 2-dimensional manifold:: sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: p = M((2,2), name='p') sage: Tp = M.tangent_space(p) sage: v = Tp((2, 1), name='v') ; v Tangent vector v at Point p on the 2-dimensional differentiable manifold M Plot of the vector alone (arrow + label):: sage: v.plot() Graphics object consisting of 2 graphics primitives Plot atop of the chart grid:: sage: X.plot() + v.plot() Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(2, 'M') X = M.chart('x y'); x, y = X[:] p = M((2,2), name='p'); Tp = M.tangent_space(p) v = Tp((2, 1), name='v') g = X.plot() + v.plot() sphinx_plot(g) Plots with various options:: sage: X.plot() + v.plot(color='green', scale=2, label='V') Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(2, 'M') X = M.chart('x y'); x, y = X[:] p = M((2,2), name='p'); Tp = M.tangent_space(p) v = Tp((2, 1), name='v') g = X.plot() + v.plot(color='green', scale=2, label='V') sphinx_plot(g) :: sage: X.plot() + v.plot(print_label=False) Graphics object consisting of 19 graphics primitives .. PLOT:: M = Manifold(2, 'M') X = M.chart('x y'); x, y = X[:] p = M((2,2), name='p'); Tp = M.tangent_space(p) v = Tp((2, 1), name='v') g = X.plot() + v.plot(print_label=False) sphinx_plot(g) :: sage: X.plot() + v.plot(color='green', label_color='black', ....: fontsize=20, label_offset=0.2) Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(2, 'M') X = M.chart('x y'); x, y = X[:] p = M((2,2), name='p'); Tp = M.tangent_space(p) v = Tp((2, 1), name='v') g = X.plot() + v.plot(color='green', label_color='black', fontsize=20, label_offset=0.2) sphinx_plot(g) :: sage: X.plot() + v.plot(linestyle=':', width=4, arrowsize=8, ....: fontsize=20) Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(2, 'M') X = M.chart('x y'); x, y = X[:] p = M((2,2), name='p'); Tp = M.tangent_space(p) v = Tp((2, 1), name='v') g = X.plot() + v.plot(linestyle=':', width=4, arrowsize=8, fontsize=20) sphinx_plot(g) Plot with specific values of some free parameters:: sage: var('a b') (a, b) sage: v = Tp((1+a, -b^2), name='v') ; v.display() v = (a + 1) d/dx - b^2 d/dy sage: X.plot() + v.plot(parameters={a: -2, b: 3}) Graphics object consisting of 20 graphics primitives Special case of the zero vector:: sage: v = Tp.zero() ; v Tangent vector zero at Point p on the 2-dimensional differentiable manifold M sage: X.plot() + v.plot() Graphics object consisting of 19 graphics primitives Vector tangent to a 4-dimensional manifold:: sage: M = Manifold(4, 'M') sage: X.<t,x,y,z> = M.chart() sage: p = M((0,1,2,3), name='p') sage: Tp = M.tangent_space(p) sage: v = Tp((5,4,3,2), name='v') ; v Tangent vector v at Point p on the 4-dimensional differentiable manifold M We cannot make a 4D plot directly:: sage: v.plot() Traceback (most recent call last): ... ValueError: the number of coordinates involved in the plot must be either 2 or 3, not 4 Rather, we have to select some chart coordinates for the plot, via the argument ``ambient_coords``. For instance, for a 2-dimensional plot in terms of the coordinates `(x, y)`:: sage: v.plot(ambient_coords=(x,y)) Graphics object consisting of 2 graphics primitives .. PLOT:: M = Manifold(4, 'M') X = M.chart('t x y z'); t,x,y,z = X[:] p = M((0,1,2,3), name='p'); Tp = M.tangent_space(p) v = Tp((5,4,3,2), name='v') g = X.plot(ambient_coords=(x,y)) + v.plot(ambient_coords=(x,y)) sphinx_plot(g) This plot involves only the components `v^x` and `v^y` of `v`. Similarly, for a 3-dimensional plot in terms of the coordinates `(t, x, y)`:: sage: g = v.plot(ambient_coords=(t,x,z)) sage: print(g) Graphics3d Object This plot involves only the components `v^t`, `v^x` and `v^z` of `v`. A nice 3D view atop the coordinate grid is obtained via:: sage: (X.plot(ambient_coords=(t,x,z)) # long time ....: + v.plot(ambient_coords=(t,x,z), ....: label_offset=0.5, width=6)) Graphics3d Object .. PLOT:: M = Manifold(4, 'M') X = M.chart('t x y z'); t,x,y,z = X[:] p = M((0,1,2,3), name='p'); Tp = M.tangent_space(p) v = Tp((5,4,3,2), name='v') g = X.plot(ambient_coords=(t,x,z)) + v.plot(ambient_coords=(t,x,z), label_offset=0.5, width=6) sphinx_plot(g) An example of plot via a differential mapping: plot of a vector tangent to a 2-sphere viewed in `\RR^3`:: sage: S2 = Manifold(2, 'S^2') sage: U = S2.open_subset('U') # the open set covered by spherical coord. sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') sage: R3 = Manifold(3, 'R^3') sage: X3.<x,y,z> = R3.chart() sage: F = S2.diff_map(R3, {(XS, X3): [sin(th)*cos(ph), ....: sin(th)*sin(ph), ....: cos(th)]}, name='F') sage: F.display() # the standard embedding of S^2 into R^3 F: S^2 --> R^3 on U: (th, ph) |--> (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th)) sage: p = U.point((pi/4, 7*pi/4), name='p') sage: v = XS.frame()[1].at(p) ; v # the coordinate vector d/dphi at p Tangent vector d/dph at Point p on the 2-dimensional differentiable manifold S^2 sage: graph_v = v.plot(mapping=F) sage: graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9) # long time sage: graph_v + graph_S2 # long time Graphics3d Object .. PLOT:: S2 = Manifold(2, 'S^2') U = S2.open_subset('U') XS = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') th, ph = XS[:] R3 = Manifold(3, 'R^3') X3 = R3.chart('x y z') F = S2.diff_map(R3, {(XS, X3): [sin(th)*cos(ph), sin(th)*sin(ph), cos(th)]}, name='F') p = U.point((pi/4, 7*pi/4), name='p') v = XS.frame()[1].at(p) graph_v = v.plot(mapping=F) graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9) sphinx_plot(graph_v + graph_S2) """ from sage.plot.arrow import arrow2d from sage.plot.text import text from sage.plot.graphics import Graphics from sage.plot.plot3d.shapes import arrow3d from sage.plot.plot3d.shapes2 import text3d from sage.misc.functional import numerical_approx from sage.manifolds.differentiable.chart import DiffChart scale = extra_options.pop("scale") # # The "effective" vector to be plotted # if mapping is None: eff_vector = self base_point = self._point else: #!# check # For efficiency, the method FiniteRankFreeModuleMorphism._call_() # is called instead of FiniteRankFreeModuleMorphism.__call__() eff_vector = mapping.differential(self._point)._call_(self) base_point = mapping(self._point) # # The chart w.r.t. which the vector is plotted # if chart is None: chart = base_point.parent().default_chart() elif not isinstance(chart, DiffChart): raise TypeError("{} is not a chart".format(chart)) # # Coordinates of the above chart w.r.t. which the vector is plotted # if ambient_coords is None: ambient_coords = chart[:] # all chart coordinates are used n_pc = len(ambient_coords) if n_pc != 2 and n_pc != 3: raise ValueError("the number of coordinates involved in the " + "plot must be either 2 or 3, not {}".format(n_pc)) # indices coordinates involved in the plot: ind_pc = [chart[:].index(pc) for pc in ambient_coords] # # Components of the vector w.r.t. the chart frame # basis = chart.frame().at(base_point) vcomp = eff_vector.comp(basis=basis)[:] xp = base_point.coord(chart=chart) # # The arrow # resu = Graphics() if parameters is None: coord_tail = [numerical_approx(xp[i]) for i in ind_pc] coord_head = [ numerical_approx(xp[i] + scale * vcomp[i]) for i in ind_pc ] else: coord_tail = [ numerical_approx(xp[i].substitute(parameters)) for i in ind_pc ] coord_head = [ numerical_approx( (xp[i] + scale * vcomp[i]).substitute(parameters)) for i in ind_pc ] if coord_head != coord_tail: if n_pc == 2: resu += arrow2d(tailpoint=coord_tail, headpoint=coord_head, color=color, **extra_options) else: resu += arrow3d(coord_tail, coord_head, color=color, **extra_options) # # The label # if print_label: if label is None: if n_pc == 2 and self._latex_name is not None: label = r'$' + self._latex_name + r'$' if n_pc == 3 and self._name is not None: label = self._name if label is not None: xlab = [xh + label_offset for xh in coord_head] if label_color is None: label_color = color if n_pc == 2: resu += text(label, xlab, fontsize=fontsize, color=label_color) else: resu += text3d(label, xlab, fontsize=fontsize, color=label_color) return resu
def plot_two_intervals(self, position=(0, 0), vertical_alignment='center', horizontal_alignment='left', interval_height=0.1, labels_height=0.05, fontsize=14, labels=True, colors=None): r""" Returns a picture of the interval exchange transformation. INPUT: - ``position`` - a 2-uple of the position - ``horizontal_alignment`` - left (default), center or right - ``labels`` - boolean (default: True) - ``fontsize`` - the size of the label OUTPUT: 2d plot -- a plot of the two intervals (domain and range) EXAMPLES:: sage: t = iet.IntervalExchangeTransformation(('a b','b a'),[1,1]) sage: t.plot_two_intervals() Graphics object consisting of 8 graphics primitives """ from sage.plot.all import Graphics from sage.plot.line import line2d from sage.plot.text import text from sage.plot.colors import rainbow G = Graphics() lengths = [float(_) for _ in self._lengths] total_length = sum(lengths) if colors is None: colors = rainbow(len(self._permutation), 'rgbtuple') if horizontal_alignment == 'left': s = position[0] elif horizontal_alignment == 'center': s = position[0] - total_length / 2 elif horizontal_alignment == 'right': s = position[0] - total_length else: raise ValueError( "horizontal_alignement must be left, center or right") top_height = position[1] + interval_height for i in self._permutation._intervals[0]: G += line2d([(s, top_height), (s + lengths[i], top_height)], rgbcolor=colors[i]) if labels: G += text( str(self._permutation._alphabet.unrank(i)), (s + float(lengths[i]) / 2, top_height + labels_height), horizontal_alignment='center', rgbcolor=colors[i], fontsize=fontsize) s += lengths[i] if horizontal_alignment == 'left': s = position[0] elif horizontal_alignment == 'center': s = position[0] - total_length / 2 elif horizontal_alignment == 'right': s = position[0] - total_length else: raise ValueError( "horizontal_alignement must be left, center or right") bottom_height = position[1] - interval_height for i in self._permutation._intervals[1]: G += line2d([(s, bottom_height), (s + lengths[i], bottom_height)], rgbcolor=colors[i]) if labels: G += text( str(self._permutation._alphabet.unrank(i)), (s + float(lengths[i]) / 2, bottom_height - labels_height), horizontal_alignment='center', rgbcolor=colors[i], fontsize=fontsize) s += lengths[i] return G
def show(self, **args): r""" Displays the pseudoline arrangement as a wiring diagram. INPUT: - ``**args`` -- any arguments to be forwarded to the ``show`` method. In particular, to tune the dimensions, use the ``figsize`` argument (example below). EXAMPLES:: sage: from sage.geometry.pseudolines import PseudolineArrangement sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]] sage: p = PseudolineArrangement(permutations) sage: p.show(figsize=[7,5]) TESTS:: sage: from sage.geometry.pseudolines import PseudolineArrangement sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 0, 1], [2, 0, 1]] sage: p = PseudolineArrangement(permutations) sage: p.show() Traceback (most recent call last): ... ValueError: There has been a problem while plotting the figure... """ x = 1 from sage.plot.line import line from sage.plot.text import text lines = [[(0,self._n-1-i)] for i in range(self._n)] for i,j in self.transpositions(): iy = lines[i][-1][1] jy = lines[j][-1][1] lines[i].append((x, iy)) lines[j].append((x, jy)) if abs(iy-jy) != 1: raise ValueError( "There has been a problem while plotting the figure. It "+ "seems that the lines are not correctly ordered. Please "+ "check the pseudolines modules documentation, there is a " +"warning about that. ") lines[i].append((x+2,jy)) lines[j].append((x+2,iy)) x += 2 L = line([(1,1)]) for i, l in enumerate(lines): l.append((x+2, l[-1][1])) L += line(l) L += text(str(i), (0, l[0][1]+.3), horizontal_alignment="right") L += text(str(i), (x+2, l[-1][1]+.3), horizontal_alignment="left") return L.show(axes = False, **args)
def plot_hyperplane(hyperplane, **kwds): r""" Return the plot of a single hyperplane. INPUT: - ``**kwds`` -- plot options: see below OUTPUT: A graphics object of the plot. .. RUBRIC:: Plot Options Beside the usual plot options (enter ``plot?``), the plot command for hyperplanes includes the following: - ``hyperplane_label`` -- Boolean value or string (default: ``True``). If ``True``, the hyperplane is labeled with its equation, if a string, it is labeled by that string, otherwise it is not labeled. - ``label_color`` -- (Default: ``'black'``) Color for hyperplane_label. - ``label_fontsize`` -- Size for ``hyperplane_label`` font (default: 14) (does not work in 3d, yet). - ``label_offset`` -- (Default: 0-dim: 0.1, 1-dim: (0,1), 2-dim: (0,0,0.2)) Amount by which label is offset from ``hyperplane.point()``. - ``point_size`` -- (Default: 50) Size of points in a zero-dimensional arrangement or of an arrangement over a finite field. - ``ranges`` -- Range for the parameters for the parametric plot of the hyperplane. If a single positive number ``r`` is given for the value of ``ranges``, then the ranges for all parameters are set to `[-r, r]`. Otherwise, for a line in the plane, ``ranges`` has the form ``[a, b]`` (default: [-3,3]), and for a plane in 3-space, the ``ranges`` has the form ``[[a, b], [c, d]]`` (default: [[-3,3],[-3,3]]). (The ranges are centered around ``hyperplane.point()``.) EXAMPLES:: sage: H1.<x> = HyperplaneArrangements(QQ) sage: a = 3*x + 4 sage: a.plot() # indirect doctest Graphics object consisting of 3 graphics primitives sage: a.plot(point_size=100,hyperplane_label='hello') Graphics object consisting of 3 graphics primitives sage: H2.<x,y> = HyperplaneArrangements(QQ) sage: b = 3*x + 4*y + 5 sage: b.plot() Graphics object consisting of 2 graphics primitives sage: b.plot(ranges=(1,5),label_offset=(2,-1)) Graphics object consisting of 2 graphics primitives sage: opts = {'hyperplane_label':True, 'label_color':'green', ....: 'label_fontsize':24, 'label_offset':(0,1.5)} sage: b.plot(**opts) Graphics object consisting of 2 graphics primitives sage: H3.<x,y,z> = HyperplaneArrangements(QQ) sage: c = 2*x + 3*y + 4*z + 5 sage: c.plot() Graphics3d Object sage: c.plot(label_offset=(1,0,1), color='green', label_color='red', frame=False) Graphics3d Object sage: d = -3*x + 2*y + 2*z + 3 sage: d.plot(opacity=0.8) Graphics3d Object sage: e = 4*x + 2*z + 3 sage: e.plot(ranges=[[-1,1],[0,8]], label_offset=(2,2,1), aspect_ratio=1) Graphics3d Object """ if hyperplane.base_ring().characteristic() != 0: raise NotImplementedError('base field must have characteristic zero') elif hyperplane.dimension() not in [0, 1, 2]: # dimension of hyperplane, not ambient space raise ValueError('can only plot hyperplanes in dimensions 1, 2, 3') # handle extra keywords if 'hyperplane_label' in kwds: hyp_label = kwds.pop('hyperplane_label') if not hyp_label: has_hyp_label = False else: has_hyp_label = True else: # default hyp_label = True has_hyp_label = True if has_hyp_label: if hyp_label: # then label hyperplane with its equation if hyperplane.dimension() == 2: # jmol does not like latex label = hyperplane._repr_linear(include_zero=False) else: label = hyperplane._latex_() else: label = hyp_label # a string if 'label_color' in kwds: label_color = kwds.pop('label_color') else: label_color = 'black' if 'label_fontsize' in kwds: label_fontsize = kwds.pop('label_fontsize') else: label_fontsize = 14 if 'label_offset' in kwds: has_offset = True label_offset = kwds.pop('label_offset') else: has_offset = False # give default values below if 'point_size' in kwds: pt_size = kwds.pop('point_size') else: pt_size = 50 if 'ranges' in kwds: ranges_set = True ranges = kwds.pop('ranges') else: ranges_set = False # give default values below # the extra keywords have now been handled # now create the plot if hyperplane.dimension() == 0: # a point on a line x, = hyperplane.A() d = hyperplane.b() p = point((d/x,0), size = pt_size, **kwds) if has_hyp_label: if not has_offset: label_offset = 0.1 p += text(label, (d/x,label_offset), color=label_color,fontsize=label_fontsize) p += text('',(d/x,label_offset+0.4)) # add space at top if 'ymax' not in kwds: kwds['ymax'] = 0.5 elif hyperplane.dimension() == 1: # a line in the plane pnt = hyperplane.point() w = hyperplane.linear_part().matrix() x, y = hyperplane.A() d = hyperplane.b() t = SR.var('t') if ranges_set: if type(ranges) in [list,tuple]: t0, t1 = ranges else: # ranges should be a single positive number t0, t1 = -ranges, ranges else: # default t0, t1 = -3, 3 p = parametric_plot(pnt+t*w[0], (t,t0,t1), **kwds) if has_hyp_label: if has_offset: b0, b1 = label_offset else: b0, b1 = 0, 0.2 label = text(label,(pnt[0]+b0,pnt[1]+b1), color=label_color,fontsize=label_fontsize) p += label elif hyperplane.dimension() == 2: # a plane in 3-space pnt = hyperplane.point() w = hyperplane.linear_part().matrix() a, b, c = hyperplane.A() d = hyperplane.b() s,t = SR.var('s t') if ranges_set: if type(ranges) in [list,tuple]: s0, s1 = ranges[0] t0, t1 = ranges[1] else: # ranges should be a single positive integers s0, s1 = -ranges, ranges t0, t1 = -ranges, ranges else: # default s0, s1 = -3, 3 t0, t1 = -3, 3 p = parametric_plot3d(pnt+s*w[0]+t*w[1],(s,s0,s1),(t,t0,t1),**kwds) if has_hyp_label: if has_offset: b0, b1, b2 = label_offset else: b0, b1, b2 = 0, 0, 0 label = text3d(label,(pnt[0]+b0,pnt[1]+b1,pnt[2]+b2), color=label_color,fontsize=label_fontsize) p += label return p
def plot(self, chart=None, ambient_coords=None, mapping=None, size=10, color='black', label=None, label_color=None, fontsize=10, label_offset=0.1, parameters=None): r""" Plot the current point (``self``) in a Cartesian graph based on the coordinates of some ambient chart. The point is drawn in terms of two (2D graphics) or three (3D graphics) coordinates of a given chart, called hereafter the *ambient chart*. The domain of the ambient chart must contain the point, or its image by a differentiable mapping `\Phi`. INPUT: - ``chart`` -- (default: ``None``) the ambient chart (see above); if ``None``, the ambient chart is set the default chart of ``self.containing_set()`` - ``ambient_coords`` -- (default: ``None``) tuple containing the 2 or 3 coordinates of the ambient chart in terms of which the plot is performed; if ``None``, all the coordinates of the ambient chart are considered - ``mapping`` -- (default: ``None``) differentiable mapping `\Phi` (instance of :class:`~sage.geometry.manifolds.diffmapping.DiffMapping`) providing the link between the point `p` represented by ``self`` and the ambient chart ``chart``: the domain of ``chart`` must contain `\Phi(p)`; if ``None``, the identity mapping is assumed - ``size`` -- (default: 10) size of the point once drawn as a small disk or sphere - ``color`` -- (default: 'black') color of the point - ``label`` -- (default: ``None``) label printed next to the point; if ``None``, the point's name is used. - ``label_color`` -- (default: ``None``) color to print the label; if ``None``, the value of ``color`` is used - ``fontsize`` -- (default: 10) size of the font used to print the label - ``label_offset`` -- (default: 0.1) determines the separation between the point and its label - ``parameters`` -- (default: ``None``) dictionary giving the numerical values of the parameters that may appear in the point coordinates OUTPUT: - a graphic object, either an instance of :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on 2 coordinates of the ambient chart) or an instance of :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e. based on 3 coordinates of the ambient chart) EXAMPLES: Drawing a point on a 2-dimensional manifold:: sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: p = M.point((1,3), name='p') sage: g = p.plot(X) sage: print g Graphics object consisting of 2 graphics primitives sage: gX = X.plot() # plot of the coordinate grid sage: show(g+gX) # display of the point atop the coordinate grid Actually, since ``X`` is the default chart of the open set in which ``p`` has been defined, it can be skipped in the arguments of ``plot``:: sage: g = p.plot() sage: show(g+gX) Call with some options:: sage: g = p.plot(chart=X, size=40, color='green', label='$P$', ....: label_color='blue', fontsize=20, label_offset=0.3) sage: show(g+gX) Use of the ``parameters`` option to set a numerical value of some symbolic variable:: sage: a = var('a') sage: q = M.point((a,2*a), name='q') sage: gq = q.plot(parameters={a:-2}) sage: show(g+gX+gq) The numerical value is used only for the plot:: sage: q.coord() (a, 2*a) Drawing a point on a 3-dimensional manifold:: sage: M = Manifold(3, 'M') sage: X.<x,y,z> = M.chart() sage: p = M.point((2,1,3), name='p') sage: g = p.plot() sage: print g Graphics3d Object sage: gX = X.plot(nb_values=5) # coordinate mesh cube sage: show(g+gX) # display of the point atop the coordinate mesh Call with some options:: sage: g = p.plot(chart=X, size=40, color='green', label='P_1', ....: label_color='blue', fontsize=20, label_offset=0.3) sage: show(g+gX) An example of plot via a differential mapping: plot of a point on a 2-sphere viewed in the 3-dimensional space ``M``:: sage: S2 = Manifold(2, 'S^2') sage: U = S2.open_subset('U') # the open set covered by spherical coord. sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') sage: p = U.point((pi/4, pi/8), name='p') sage: F = S2.diff_mapping(M, {(XS, X): [sin(th)*cos(ph), ....: sin(th)*sin(ph), cos(th)]}, name='F') sage: F.display() F: S^2 --> M on U: (th, ph) |--> (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th)) sage: g = p.plot(chart=X, mapping=F) sage: gS2 = XS.plot(chart=X, mapping=F, nb_values=9) sage: show(g+gS2) Use of the option ``ambient_coords`` for plots on a 4-dimensional manifold:: sage: M = Manifold(4, 'M') sage: X.<t,x,y,z> = M.chart() sage: p = M.point((1,2,3,4), name='p') sage: g = p.plot(X, ambient_coords=(t,x,y)) # the coordinate z is skipped sage: gX = X.plot(X, ambient_coords=(t,x,y), nb_values=5) sage: show(g+gX) # 3D plot sage: g = p.plot(X, ambient_coords=(t,y,z)) # the coordinate x is skipped sage: gX = X.plot(X, ambient_coords=(t,y,z), nb_values=5) sage: show(g+gX) # 3D plot sage: g = p.plot(X, ambient_coords=(y,z)) # the coordinates t and x are skipped sage: gX = X.plot(X, ambient_coords=(y,z)) sage: show(g+gX) # 2D plot """ from sage.plot.point import point2d from sage.plot.text import text from sage.plot.graphics import Graphics from sage.plot.plot3d.shapes2 import point3d, text3d from sage.geometry.manifolds.chart import Chart # The ambient chart: if chart is None: chart = self.containing_set().default_chart() elif not isinstance(chart, Chart): raise TypeError("the argument 'chart' must be a coordinate chart") # The effective point to be plotted: if mapping is None: eff_point = self else: eff_point = mapping(self) # The coordinates of the ambient chart used for the plot: if ambient_coords is None: ambient_coords = chart._xx elif not isinstance(ambient_coords, tuple): ambient_coords = tuple(ambient_coords) nca = len(ambient_coords) if nca != 2 and nca !=3: raise TypeError("Bad number of ambient coordinates: " + str(nca)) # The point coordinates: coords = eff_point.coord(chart) xx = chart[:] xp = [coords[xx.index(c)] for c in ambient_coords] if parameters is not None: xps = [coord.substitute(parameters) for coord in xp] xp = xps xlab = [coord + label_offset for coord in xp] if label_color is None: label_color = color resu = Graphics() if nca == 2: if label is None: label = r'$' + self._latex_name + r'$' resu += point2d(xp, color=color, size=size) + \ text(label, xlab, fontsize=fontsize, color=label_color) else: if label is None: label = self._name resu += point3d(xp, color=color, size=size) + \ text3d(label, xlab, fontsize=fontsize, color=label_color) return resu
def plot(self, chart=None, ambient_coords=None, mapping=None, label=None, parameters=None, **kwds): r""" For real manifolds, plot ``self`` in a Cartesian graph based on the coordinates of some ambient chart. The point is drawn in terms of two (2D graphics) or three (3D graphics) coordinates of a given chart, called hereafter the *ambient chart*. The domain of the ambient chart must contain the point, or its image by a continuous manifold map `\Phi`. INPUT: - ``chart`` -- (default: ``None``) the ambient chart (see above); if ``None``, the ambient chart is set the default chart of ``self.parent()`` - ``ambient_coords`` -- (default: ``None``) tuple containing the 2 or 3 coordinates of the ambient chart in terms of which the plot is performed; if ``None``, all the coordinates of the ambient chart are considered - ``mapping`` -- (default: ``None``) :class:`~sage.manifolds.continuous_map.ContinuousMap`; continuous manifold map `\Phi` providing the link between the current point `p` and the ambient chart ``chart``: the domain of ``chart`` must contain `\Phi(p)`; if ``None``, the identity map is assumed - ``label`` -- (default: ``None``) label printed next to the point; if ``None``, the point's name is used - ``parameters`` -- (default: ``None``) dictionary giving the numerical values of the parameters that may appear in the point coordinates - ``size`` -- (default: 10) size of the point once drawn as a small disk or sphere - ``color`` -- (default: ``'black'``) color of the point - ``label_color`` -- (default: ``None``) color to print the label; if ``None``, the value of ``color`` is used - ``fontsize`` -- (default: 10) size of the font used to print the label - ``label_offset`` -- (default: 0.1) determines the separation between the point and its label OUTPUT: - a graphic object, either an instance of :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on 2 coordinates of the ambient chart) or an instance of :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e. based on 3 coordinates of the ambient chart) EXAMPLES: Drawing a point on a 2-dimensional manifold:: sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart() sage: p = M.point((1,3), name='p') sage: g = p.plot(X) sage: print(g) Graphics object consisting of 2 graphics primitives sage: gX = X.plot(max_range=4) # plot of the coordinate grid sage: g + gX # display of the point atop the coordinate grid Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(2, 'M', structure='topological') X = M.chart('x y'); x,y = X[:] p = M.point((1,3), name='p') g = p.plot(X) gX = X.plot(max_range=4) sphinx_plot(g+gX) Actually, since ``X`` is the default chart of the open set in which ``p`` has been defined, it can be skipped in the arguments of ``plot``:: sage: g = p.plot() sage: g + gX Graphics object consisting of 20 graphics primitives Call with some options:: sage: g = p.plot(chart=X, size=40, color='green', label='$P$', ....: label_color='blue', fontsize=20, label_offset=0.3) sage: g + gX Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(2, 'M', structure='topological') X = M.chart('x y'); x,y = X[:] p = M.point((1,3), name='p') g = p.plot(chart=X, size=40, color='green', label='$P$', \ label_color='blue', fontsize=20, label_offset=0.3) gX = X.plot(max_range=4) sphinx_plot(g+gX) Use of the ``parameters`` option to set a numerical value of some symbolic variable:: sage: a = var('a') sage: q = M.point((a,2*a), name='q') sage: gq = q.plot(parameters={a:-2}, label_offset=0.2) sage: g + gX + gq Graphics object consisting of 22 graphics primitives .. PLOT:: M = Manifold(2, 'M', structure='topological') X = M.chart('x y'); x,y = X[:] p = M.point((1,3), name='p') g = p.plot(chart=X, size=40, color='green', label='$P$', \ label_color='blue', fontsize=20, label_offset=0.3) var('a') q = M.point((a,2*a), name='q') gq = q.plot(parameters={a:-2}, label_offset=0.2) gX = X.plot(max_range=4) sphinx_plot(g+gX+gq) The numerical value is used only for the plot:: sage: q.coord() (a, 2*a) Drawing a point on a 3-dimensional manifold:: sage: M = Manifold(3, 'M', structure='topological') sage: X.<x,y,z> = M.chart() sage: p = M.point((2,1,3), name='p') sage: g = p.plot() sage: print(g) Graphics3d Object sage: gX = X.plot(nb_values=5) # coordinate mesh cube sage: g + gX # display of the point atop the coordinate mesh Graphics3d Object Call with some options:: sage: g = p.plot(chart=X, size=40, color='green', label='P_1', ....: label_color='blue', fontsize=20, label_offset=0.3) sage: g + gX Graphics3d Object An example of plot via a mapping: plot of a point on a 2-sphere viewed in the 3-dimensional space ``M``:: sage: S2 = Manifold(2, 'S^2', structure='topological') sage: U = S2.open_subset('U') # the open set covered by spherical coord. sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') sage: p = U.point((pi/4, pi/8), name='p') sage: F = S2.continuous_map(M, {(XS, X): [sin(th)*cos(ph), ....: sin(th)*sin(ph), cos(th)]}, name='F') sage: F.display() F: S^2 --> M on U: (th, ph) |--> (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th)) sage: g = p.plot(chart=X, mapping=F) sage: gS2 = XS.plot(chart=X, mapping=F, nb_values=9) sage: g + gS2 Graphics3d Object Use of the option ``ambient_coords`` for plots on a 4-dimensional manifold:: sage: M = Manifold(4, 'M', structure='topological') sage: X.<t,x,y,z> = M.chart() sage: p = M.point((1,2,3,4), name='p') sage: g = p.plot(X, ambient_coords=(t,x,y), label_offset=0.4) # the coordinate z is skipped sage: gX = X.plot(X, ambient_coords=(t,x,y), nb_values=5) # long time sage: g + gX # 3D plot # long time Graphics3d Object sage: g = p.plot(X, ambient_coords=(t,y,z), label_offset=0.4) # the coordinate x is skipped sage: gX = X.plot(X, ambient_coords=(t,y,z), nb_values=5) # long time sage: g + gX # 3D plot # long time Graphics3d Object sage: g = p.plot(X, ambient_coords=(y,z), label_offset=0.4) # the coordinates t and x are skipped sage: gX = X.plot(X, ambient_coords=(y,z)) sage: g + gX # 2D plot Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(4, 'M', structure='topological') X = M.chart('t x y z'); t,x,y,z = X[:] p = M.point((1,2,3,4), name='p') g = p.plot(X, ambient_coords=(y,z), label_offset=0.4) gX = X.plot(X, ambient_coords=(y,z)) sphinx_plot(g+gX) """ from sage.plot.point import point2d from sage.plot.text import text from sage.plot.graphics import Graphics from sage.plot.plot3d.shapes2 import point3d, text3d from sage.manifolds.chart import Chart if self._manifold.base_field_type() != "real": raise NotImplementedError( "plot of points on manifolds over fields different" " from the real field is not implemented" ) # The ambient chart: if chart is None: chart = self.parent().default_chart() elif not isinstance(chart, Chart): raise TypeError("the argument 'chart' must be a coordinate chart") # The effective point to be plotted: if mapping is None: eff_point = self else: eff_point = mapping(self) # The coordinates of the ambient chart used for the plot: if ambient_coords is None: ambient_coords = chart[:] elif not isinstance(ambient_coords, tuple): ambient_coords = tuple(ambient_coords) nca = len(ambient_coords) if nca != 2 and nca != 3: raise TypeError("invalid number of ambient coordinates: {}".format(nca)) # Extract the kwds options size = kwds["size"] color = kwds["color"] label_color = kwds["label_color"] fontsize = kwds["fontsize"] label_offset = kwds["label_offset"] # The point coordinates: coords = eff_point.coord(chart) xx = chart[:] xp = [coords[xx.index(c)] for c in ambient_coords] if parameters is not None: xps = [coord.substitute(parameters) for coord in xp] xp = xps xlab = [coord + label_offset for coord in xp] if label_color is None: label_color = color resu = Graphics() if nca == 2: if label is None: label = r"$" + self._latex_name + r"$" resu += point2d(xp, color=color, size=size) + text(label, xlab, fontsize=fontsize, color=label_color) else: if label is None: label = self._name resu += point3d(xp, color=color, size=size) + text3d(label, xlab, fontsize=fontsize, color=label_color) return resu
def plot_hyperplane(hyperplane, **kwds): r""" Return the plot of a single hyperplane. INPUT: - ``**kwds`` -- plot options: see below OUTPUT: A graphics object of the plot. .. RUBRIC:: Plot Options Beside the usual plot options (enter ``plot?``), the plot command for hyperplanes includes the following: - ``hyperplane_label`` -- Boolean value or string (default: ``True``). If ``True``, the hyperplane is labeled with its equation, if a string, it is labeled by that string, otherwise it is not labeled. - ``label_color`` -- (Default: ``'black'``) Color for hyperplane_label. - ``label_fontsize`` -- Size for ``hyperplane_label`` font (default: 14) (does not work in 3d, yet). - ``label_offset`` -- (Default: 0-dim: 0.1, 1-dim: (0,1), 2-dim: (0,0,0.2)) Amount by which label is offset from ``hyperplane.point()``. - ``point_size`` -- (Default: 50) Size of points in a zero-dimensional arrangement or of an arrangement over a finite field. - ``ranges`` -- Range for the parameters for the parametric plot of the hyperplane. If a single positive number ``r`` is given for the value of ``ranges``, then the ranges for all parameters are set to `[-r, r]`. Otherwise, for a line in the plane, ``ranges`` has the form ``[a, b]`` (default: [-3,3]), and for a plane in 3-space, the ``ranges`` has the form ``[[a, b], [c, d]]`` (default: [[-3,3],[-3,3]]). (The ranges are centered around ``hyperplane.point()``.) EXAMPLES:: sage: H1.<x> = HyperplaneArrangements(QQ) sage: a = 3*x + 4 sage: a.plot() # indirect doctest Graphics object consisting of 3 graphics primitives sage: a.plot(point_size=100,hyperplane_label='hello') Graphics object consisting of 3 graphics primitives sage: H2.<x,y> = HyperplaneArrangements(QQ) sage: b = 3*x + 4*y + 5 sage: b.plot() Graphics object consisting of 2 graphics primitives sage: b.plot(ranges=(1,5),label_offset=(2,-1)) Graphics object consisting of 2 graphics primitives sage: opts = {'hyperplane_label':True, 'label_color':'green', ....: 'label_fontsize':24, 'label_offset':(0,1.5)} sage: b.plot(**opts) Graphics object consisting of 2 graphics primitives sage: H3.<x,y,z> = HyperplaneArrangements(QQ) sage: c = 2*x + 3*y + 4*z + 5 sage: c.plot() Graphics3d Object sage: c.plot(label_offset=(1,0,1), color='green', label_color='red', frame=False) Graphics3d Object sage: d = -3*x + 2*y + 2*z + 3 sage: d.plot(opacity=0.8) Graphics3d Object sage: e = 4*x + 2*z + 3 sage: e.plot(ranges=[[-1,1],[0,8]], label_offset=(2,2,1), aspect_ratio=1) Graphics3d Object """ if hyperplane.base_ring().characteristic(): raise NotImplementedError('base field must have characteristic zero') elif hyperplane.dimension() not in [ 0, 1, 2 ]: # dimension of hyperplane, not ambient space raise ValueError('can only plot hyperplanes in dimensions 1, 2, 3') # handle extra keywords if 'hyperplane_label' in kwds: hyp_label = kwds.pop('hyperplane_label') if not hyp_label: has_hyp_label = False else: has_hyp_label = True else: # default hyp_label = True has_hyp_label = True if has_hyp_label: if hyp_label: # then label hyperplane with its equation if hyperplane.dimension() == 2: # jmol does not like latex label = hyperplane._repr_linear(include_zero=False) else: label = hyperplane._latex_() else: label = hyp_label # a string if 'label_color' in kwds: label_color = kwds.pop('label_color') else: label_color = 'black' if 'label_fontsize' in kwds: label_fontsize = kwds.pop('label_fontsize') else: label_fontsize = 14 if 'label_offset' in kwds: has_offset = True label_offset = kwds.pop('label_offset') else: has_offset = False # give default values below if 'point_size' in kwds: pt_size = kwds.pop('point_size') else: pt_size = 50 if 'ranges' in kwds: ranges_set = True ranges = kwds.pop('ranges') else: ranges_set = False # give default values below # the extra keywords have now been handled # now create the plot if hyperplane.dimension() == 0: # a point on a line x, = hyperplane.A() d = hyperplane.b() p = point((d / x, 0), size=pt_size, **kwds) if has_hyp_label: if not has_offset: label_offset = 0.1 p += text(label, (d / x, label_offset), color=label_color, fontsize=label_fontsize) p += text('', (d / x, label_offset + 0.4)) # add space at top if 'ymax' not in kwds: kwds['ymax'] = 0.5 elif hyperplane.dimension() == 1: # a line in the plane pnt = hyperplane.point() w = hyperplane.linear_part().matrix() t = SR.var('t') if ranges_set: if isinstance(ranges, (list, tuple)): t0, t1 = ranges else: # ranges should be a single positive number t0, t1 = -ranges, ranges else: # default t0, t1 = -3, 3 p = parametric_plot(pnt + t * w[0], (t, t0, t1), **kwds) if has_hyp_label: if has_offset: b0, b1 = label_offset else: b0, b1 = 0, 0.2 label = text(label, (pnt[0] + b0, pnt[1] + b1), color=label_color, fontsize=label_fontsize) p += label elif hyperplane.dimension() == 2: # a plane in 3-space pnt = hyperplane.point() w = hyperplane.linear_part().matrix() s, t = SR.var('s t') if ranges_set: if isinstance(ranges, (list, tuple)): s0, s1 = ranges[0] t0, t1 = ranges[1] else: # ranges should be a single positive integers s0, s1 = -ranges, ranges t0, t1 = -ranges, ranges else: # default s0, s1 = -3, 3 t0, t1 = -3, 3 p = parametric_plot3d(pnt + s * w[0] + t * w[1], (s, s0, s1), (t, t0, t1), **kwds) if has_hyp_label: if has_offset: b0, b1, b2 = label_offset else: b0, b1, b2 = 0, 0, 0 label = text3d(label, (pnt[0] + b0, pnt[1] + b1, pnt[2] + b2), color=label_color, fontsize=label_fontsize) p += label return p
def plot(self, chart=None, ambient_coords=None, mapping=None, color='blue', print_label=True, label=None, label_color=None, fontsize=10, label_offset=0.1, parameters=None, **extra_options): r""" Plot the vector in a Cartesian graph based on the coordinates of some ambient chart. The vector is drawn in terms of two (2D graphics) or three (3D graphics) coordinates of a given chart, called hereafter the *ambient chart*. The vector's base point `p` (or its image `\Phi(p)` by some differentiable mapping `\Phi`) must lie in the ambient chart's domain. If `\Phi` is different from the identity mapping, the vector actually depicted is `\mathrm{d}\Phi_p(v)`, where `v` is the current vector (``self``) (see the example of a vector tangent to the 2-sphere below, where `\Phi: S^2 \to \RR^3`). INPUT: - ``chart`` -- (default: ``None``) the ambient chart (see above); if ``None``, it is set to the default chart of the open set containing the point at which the vector (or the vector image via the differential `\mathrm{d}\Phi_p` of ``mapping``) is defined - ``ambient_coords`` -- (default: ``None``) tuple containing the 2 or 3 coordinates of the ambient chart in terms of which the plot is performed; if ``None``, all the coordinates of the ambient chart are considered - ``mapping`` -- (default: ``None``) :class:`~sage.manifolds.differentiable.diff_map.DiffMap`; differentiable mapping `\Phi` providing the link between the point `p` at which the vector is defined and the ambient chart ``chart``: the domain of ``chart`` must contain `\Phi(p)`; if ``None``, the identity mapping is assumed - ``scale`` -- (default: 1) value by which the length of the arrow representing the vector is multiplied - ``color`` -- (default: 'blue') color of the arrow representing the vector - ``print_label`` -- (boolean; default: ``True``) determines whether a label is printed next to the arrow representing the vector - ``label`` -- (string; default: ``None``) label printed next to the arrow representing the vector; if ``None``, the vector's symbol is used, if any - ``label_color`` -- (default: ``None``) color to print the label; if ``None``, the value of ``color`` is used - ``fontsize`` -- (default: 10) size of the font used to print the label - ``label_offset`` -- (default: 0.1) determines the separation between the vector arrow and the label - ``parameters`` -- (default: ``None``) dictionary giving the numerical values of the parameters that may appear in the coordinate expression of ``self`` (see example below) - ``**extra_options`` -- extra options for the arrow plot, like ``linestyle``, ``width`` or ``arrowsize`` (see :func:`~sage.plot.arrow.arrow2d` and :func:`~sage.plot.plot3d.shapes.arrow3d` for details) OUTPUT: - a graphic object, either an instance of :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on 2 coordinates of ``chart``) or an instance of :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e. based on 3 coordinates of ``chart``) EXAMPLES: Vector tangent to a 2-dimensional manifold:: sage: M = Manifold(2, 'M') sage: X.<x,y> = M.chart() sage: p = M((2,2), name='p') sage: Tp = M.tangent_space(p) sage: v = Tp((2, 1), name='v') ; v Tangent vector v at Point p on the 2-dimensional differentiable manifold M Plot of the vector alone (arrow + label):: sage: v.plot() Graphics object consisting of 2 graphics primitives Plot atop of the chart grid:: sage: X.plot() + v.plot() Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(2, 'M') X = M.chart('x y'); x, y = X[:] p = M((2,2), name='p'); Tp = M.tangent_space(p) v = Tp((2, 1), name='v') g = X.plot() + v.plot() sphinx_plot(g) Plots with various options:: sage: X.plot() + v.plot(color='green', scale=2, label='V') Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(2, 'M') X = M.chart('x y'); x, y = X[:] p = M((2,2), name='p'); Tp = M.tangent_space(p) v = Tp((2, 1), name='v') g = X.plot() + v.plot(color='green', scale=2, label='V') sphinx_plot(g) :: sage: X.plot() + v.plot(print_label=False) Graphics object consisting of 19 graphics primitives .. PLOT:: M = Manifold(2, 'M') X = M.chart('x y'); x, y = X[:] p = M((2,2), name='p'); Tp = M.tangent_space(p) v = Tp((2, 1), name='v') g = X.plot() + v.plot(print_label=False) sphinx_plot(g) :: sage: X.plot() + v.plot(color='green', label_color='black', ....: fontsize=20, label_offset=0.2) Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(2, 'M') X = M.chart('x y'); x, y = X[:] p = M((2,2), name='p'); Tp = M.tangent_space(p) v = Tp((2, 1), name='v') g = X.plot() + v.plot(color='green', label_color='black', fontsize=20, label_offset=0.2) sphinx_plot(g) :: sage: X.plot() + v.plot(linestyle=':', width=4, arrowsize=8, ....: fontsize=20) Graphics object consisting of 20 graphics primitives .. PLOT:: M = Manifold(2, 'M') X = M.chart('x y'); x, y = X[:] p = M((2,2), name='p'); Tp = M.tangent_space(p) v = Tp((2, 1), name='v') g = X.plot() + v.plot(linestyle=':', width=4, arrowsize=8, fontsize=20) sphinx_plot(g) Plot with specific values of some free parameters:: sage: var('a b') (a, b) sage: v = Tp((1+a, -b^2), name='v') ; v.display() v = (a + 1) d/dx - b^2 d/dy sage: X.plot() + v.plot(parameters={a: -2, b: 3}) Graphics object consisting of 20 graphics primitives Special case of the zero vector:: sage: v = Tp.zero() ; v Tangent vector zero at Point p on the 2-dimensional differentiable manifold M sage: X.plot() + v.plot() Graphics object consisting of 19 graphics primitives Vector tangent to a 4-dimensional manifold:: sage: M = Manifold(4, 'M') sage: X.<t,x,y,z> = M.chart() sage: p = M((0,1,2,3), name='p') sage: Tp = M.tangent_space(p) sage: v = Tp((5,4,3,2), name='v') ; v Tangent vector v at Point p on the 4-dimensional differentiable manifold M We cannot make a 4D plot directly:: sage: v.plot() Traceback (most recent call last): ... ValueError: the number of coordinates involved in the plot must be either 2 or 3, not 4 Rather, we have to select some chart coordinates for the plot, via the argument ``ambient_coords``. For instance, for a 2-dimensional plot in terms of the coordinates `(x, y)`:: sage: v.plot(ambient_coords=(x,y)) Graphics object consisting of 2 graphics primitives .. PLOT:: M = Manifold(4, 'M') X = M.chart('t x y z'); t,x,y,z = X[:] p = M((0,1,2,3), name='p'); Tp = M.tangent_space(p) v = Tp((5,4,3,2), name='v') g = X.plot(ambient_coords=(x,y)) + v.plot(ambient_coords=(x,y)) sphinx_plot(g) This plot involves only the components `v^x` and `v^y` of `v`. Similarly, for a 3-dimensional plot in terms of the coordinates `(t, x, y)`:: sage: g = v.plot(ambient_coords=(t,x,z)) sage: print(g) Graphics3d Object This plot involves only the components `v^t`, `v^x` and `v^z` of `v`. A nice 3D view atop the coordinate grid is obtained via:: sage: (X.plot(ambient_coords=(t,x,z)) # long time ....: + v.plot(ambient_coords=(t,x,z), ....: label_offset=0.5, width=6)) Graphics3d Object .. PLOT:: M = Manifold(4, 'M') X = M.chart('t x y z'); t,x,y,z = X[:] p = M((0,1,2,3), name='p'); Tp = M.tangent_space(p) v = Tp((5,4,3,2), name='v') g = X.plot(ambient_coords=(t,x,z)) + v.plot(ambient_coords=(t,x,z), label_offset=0.5, width=6) sphinx_plot(g) An example of plot via a differential mapping: plot of a vector tangent to a 2-sphere viewed in `\RR^3`:: sage: S2 = Manifold(2, 'S^2') sage: U = S2.open_subset('U') # the open set covered by spherical coord. sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') sage: R3 = Manifold(3, 'R^3') sage: X3.<x,y,z> = R3.chart() sage: F = S2.diff_map(R3, {(XS, X3): [sin(th)*cos(ph), ....: sin(th)*sin(ph), ....: cos(th)]}, name='F') sage: F.display() # the standard embedding of S^2 into R^3 F: S^2 --> R^3 on U: (th, ph) |--> (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th)) sage: p = U.point((pi/4, 7*pi/4), name='p') sage: v = XS.frame()[1].at(p) ; v # the coordinate vector d/dphi at p Tangent vector d/dph at Point p on the 2-dimensional differentiable manifold S^2 sage: graph_v = v.plot(mapping=F) sage: graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9) # long time sage: graph_v + graph_S2 # long time Graphics3d Object .. PLOT:: S2 = Manifold(2, 'S^2') U = S2.open_subset('U') XS = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') th, ph = XS[:] R3 = Manifold(3, 'R^3') X3 = R3.chart('x y z') F = S2.diff_map(R3, {(XS, X3): [sin(th)*cos(ph), sin(th)*sin(ph), cos(th)]}, name='F') p = U.point((pi/4, 7*pi/4), name='p') v = XS.frame()[1].at(p) graph_v = v.plot(mapping=F) graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9) sphinx_plot(graph_v + graph_S2) """ from sage.plot.arrow import arrow2d from sage.plot.text import text from sage.plot.graphics import Graphics from sage.plot.plot3d.shapes import arrow3d from sage.plot.plot3d.shapes2 import text3d from sage.misc.functional import numerical_approx from sage.manifolds.differentiable.chart import DiffChart scale = extra_options.pop("scale") # # The "effective" vector to be plotted # if mapping is None: eff_vector = self base_point = self._point else: #!# check # For efficiency, the method FiniteRankFreeModuleMorphism._call_() # is called instead of FiniteRankFreeModuleMorphism.__call__() eff_vector = mapping.differential(self._point)._call_(self) base_point = mapping(self._point) # # The chart w.r.t. which the vector is plotted # if chart is None: chart = base_point.parent().default_chart() elif not isinstance(chart, DiffChart): raise TypeError("{} is not a chart".format(chart)) # # Coordinates of the above chart w.r.t. which the vector is plotted # if ambient_coords is None: ambient_coords = chart[:] # all chart coordinates are used n_pc = len(ambient_coords) if n_pc != 2 and n_pc !=3: raise ValueError("the number of coordinates involved in the " + "plot must be either 2 or 3, not {}".format(n_pc)) # indices coordinates involved in the plot: ind_pc = [chart[:].index(pc) for pc in ambient_coords] # # Components of the vector w.r.t. the chart frame # basis = chart.frame().at(base_point) vcomp = eff_vector.comp(basis=basis)[:] xp = base_point.coord(chart=chart) # # The arrow # resu = Graphics() if parameters is None: coord_tail = [numerical_approx(xp[i]) for i in ind_pc] coord_head = [numerical_approx(xp[i] + scale*vcomp[i]) for i in ind_pc] else: coord_tail = [numerical_approx(xp[i].substitute(parameters)) for i in ind_pc] coord_head = [numerical_approx( (xp[i] + scale*vcomp[i]).substitute(parameters)) for i in ind_pc] if coord_head != coord_tail: if n_pc == 2: resu += arrow2d(tailpoint=coord_tail, headpoint=coord_head, color=color, **extra_options) else: resu += arrow3d(coord_tail, coord_head, color=color, **extra_options) # # The label # if print_label: if label is None: if n_pc == 2 and self._latex_name is not None: label = r'$' + self._latex_name + r'$' if n_pc == 3 and self._name is not None: label = self._name if label is not None: xlab = [xh + label_offset for xh in coord_head] if label_color is None: label_color = color if n_pc == 2: resu += text(label, xlab, fontsize=fontsize, color=label_color) else: resu += text3d(label, xlab, fontsize=fontsize, color=label_color) return resu