def _render_on_subplot(self, subplot): """ TESTS:: sage: C = circle((2,pi), 2, edgecolor='black', facecolor='green', fill=True) """ import matplotlib.patches as patches from sage.plot.misc import get_matplotlib_linestyle options = self.options() p = patches.Circle((float(self.x), float(self.y)), float(self.r), clip_on=options['clip']) if not options['clip']: self._bbox_extra_artists = [p] p.set_linewidth(float(options['thickness'])) p.set_fill(options['fill']) a = float(options['alpha']) p.set_alpha(a) ec = to_mpl_color(options['edgecolor']) fc = to_mpl_color(options['facecolor']) if 'rgbcolor' in options: ec = fc = to_mpl_color(options['rgbcolor']) p.set_edgecolor(ec) p.set_facecolor(fc) p.set_linestyle( get_matplotlib_linestyle(options['linestyle'], return_type='long')) p.set_label(options['legend_label']) z = int(options.pop('zorder', 0)) p.set_zorder(z) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ TESTS:: sage: P = polygon([(0,0), (1,2), (0,1), (-1,2)]) """ import matplotlib.patches as patches options = self.options() p = patches.Polygon([(self.xdata[i], self.ydata[i]) for i in range(len(self.xdata))]) p.set_linewidth(float(options['thickness'])) a = float(options['alpha']) z = int(options.pop('zorder', 1)) p.set_alpha(a) f = options.pop('fill') p.set_fill(f) c = to_mpl_color(options['rgbcolor']) if f: ec = options['edgecolor'] if ec is None: p.set_color(c) else: p.set_facecolor(c) p.set_edgecolor(to_mpl_color(ec)) else: p.set_color(c) p.set_label(options['legend_label']) p.set_zorder(z) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ Render this ellipse in a subplot. This is the key function that defines how this ellipse graphics primitive is rendered in matplotlib's library. TESTS:: sage: ellipse((0,0),3,1,pi/6,fill=True,alpha=0.3) :: sage: ellipse((3,2),1,2) """ import matplotlib.patches as patches options = self.options() p = patches.Ellipse((self.x, self.y), self.r1 * 2., self.r2 * 2., self.angle / pi * 180.) p.set_linewidth(float(options['thickness'])) p.set_fill(options['fill']) a = float(options['alpha']) p.set_alpha(a) ec = to_mpl_color(options['edgecolor']) fc = to_mpl_color(options['facecolor']) if 'rgbcolor' in options: ec = fc = to_mpl_color(options['rgbcolor']) p.set_edgecolor(ec) p.set_facecolor(fc) p.set_linestyle(options['linestyle']) p.set_label(options['legend_label']) z = int(options.pop('zorder', 0)) p.set_zorder(z) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ TESTS:: sage: P = polygon([(0,0), (1,2), (0,1), (-1,2)]) """ import matplotlib.patches as patches options = self.options() p = patches.Polygon([(self.xdata[i],self.ydata[i]) for i in xrange(len(self.xdata))]) p.set_linewidth(float(options['thickness'])) a = float(options['alpha']) z = int(options.pop('zorder', 1)) p.set_alpha(a) f = options.pop('fill') p.set_fill(f) c = to_mpl_color(options['rgbcolor']) if f: ec = options['edgecolor'] if ec is None: p.set_color(c) else: p.set_facecolor(c) p.set_edgecolor(to_mpl_color(ec)) else: p.set_color(c) p.set_label(options['legend_label']) p.set_zorder(z) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ TESTS:: sage: C = circle((2,pi), 2, edgecolor='black', facecolor='green', fill=True) """ import matplotlib.patches as patches options = self.options() p = patches.Circle((float(self.x), float(self.y)), float(self.r), clip_on=options['clip']) if not options['clip']: self._bbox_extra_artists=[p] p.set_linewidth(float(options['thickness'])) p.set_fill(options['fill']) a = float(options['alpha']) p.set_alpha(a) ec = to_mpl_color(options['edgecolor']) fc = to_mpl_color(options['facecolor']) if 'rgbcolor' in options: ec = fc = to_mpl_color(options['rgbcolor']) p.set_edgecolor(ec) p.set_facecolor(fc) p.set_linestyle(options['linestyle']) p.set_label(options['legend_label']) z = int(options.pop('zorder', 0)) p.set_zorder(z) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ Render this ellipse in a subplot. This is the key function that defines how this ellipse graphics primitive is rendered in matplotlib's library. TESTS:: sage: ellipse((0,0),3,1,pi/6,fill=True,alpha=0.3) :: sage: ellipse((3,2),1,2) """ import matplotlib.patches as patches options = self.options() p = patches.Ellipse( (self.x,self.y), self.r1*2.,self.r2*2.,self.angle/pi*180.) p.set_linewidth(float(options['thickness'])) p.set_fill(options['fill']) a = float(options['alpha']) p.set_alpha(a) ec = to_mpl_color(options['edgecolor']) fc = to_mpl_color(options['facecolor']) if 'rgbcolor' in options: ec = fc = to_mpl_color(options['rgbcolor']) p.set_edgecolor(ec) p.set_facecolor(fc) p.set_linestyle(options['linestyle']) z = int(options.pop('zorder', 0)) p.set_zorder(z) subplot.add_patch(p)
def _render_on_subplot(self,subplot): r""" TESTS: We check to make sure that \#2076 is fixed by verifying all the points are red:: sage: point(((1,1), (2,2), (3,3)), rgbcolor=hue(1), size=30) """ options = self.options() #Convert the color to a hex string so that the scatter #method does not interpret it as a list of 3 floating #point color specifications when there are #three points. This is mentioned in the matplotlib 0.98 #documentation and fixes \#2076 from matplotlib.colors import rgb2hex c = rgb2hex(to_mpl_color(options['rgbcolor'])) a = float(options['alpha']) z = int(options.pop('zorder', 0)) s = int(options['size']) faceted = options['faceted'] #faceted=True colors the edge of point scatteroptions={} if not faceted: scatteroptions['edgecolors'] = 'none' subplot.scatter(self.xdata, self.ydata, s=s, c=c, alpha=a, zorder=z, label=options['legend_label'], **scatteroptions)
def _render_on_subplot(self, subplot): """ Render this line on a matplotlib subplot. INPUT: - ``subplot`` -- a matplotlib subplot EXAMPLES: This implicitly calls this function:: sage: line([(1,2), (3,-4), (2, 5), (1,2)]) """ import matplotlib.lines as lines options = dict(self.options()) for o in ("alpha", "legend_color", "legend_label", "linestyle", "rgbcolor", "thickness"): if o in options: del options[o] p = lines.Line2D(self.xdata, self.ydata, **options) options = self.options() a = float(options["alpha"]) p.set_alpha(a) p.set_linewidth(float(options["thickness"])) p.set_color(to_mpl_color(options["rgbcolor"])) p.set_label(options["legend_label"]) # we don't pass linestyle in directly since the drawstyles aren't # pulled off automatically. This (I think) is a bug in matplotlib 1.0.1 if "linestyle" in options: from sage.plot.misc import get_matplotlib_linestyle p.set_linestyle(get_matplotlib_linestyle(options["linestyle"], return_type="short")) subplot.add_line(p)
def _render_on_subplot(self, subplot): """ Render this line on a matplotlib subplot. INPUT: - ``subplot`` -- a matplotlib subplot EXAMPLES: This implicitly calls this function:: sage: line([(1,2), (3,-4), (2, 5), (1,2)]) Graphics object consisting of 1 graphics primitive """ import matplotlib.lines as lines options = dict(self.options()) for o in ('alpha', 'legend_color', 'legend_label', 'linestyle', 'rgbcolor', 'thickness'): if o in options: del options[o] p = lines.Line2D(self.xdata, self.ydata, **options) options = self.options() a = float(options['alpha']) p.set_alpha(a) p.set_linewidth(float(options['thickness'])) p.set_color(to_mpl_color(options['rgbcolor'])) p.set_label(options['legend_label']) # we don't pass linestyle in directly since the drawstyles aren't # pulled off automatically. This (I think) is a bug in matplotlib 1.0.1 if 'linestyle' in options: from sage.plot.misc import get_matplotlib_linestyle p.set_linestyle(get_matplotlib_linestyle(options['linestyle'], return_type='short')) subplot.add_line(p)
def _render_on_subplot(self, subplot): """ TESTS:: sage: D = disk((2,-1), 2, (0, pi), color='black', thickness=3, fill=False); D Graphics object consisting of 1 graphics primitive Save alpha information in pdf (see :trac:`13732`):: sage: f = tmp_filename(ext='.pdf') sage: p = disk((0,0), 5, (0, pi/4), alpha=0.5) sage: p.save(f) """ import matplotlib.patches as patches options = self.options() deg1 = self.rad1*(180./pi) #convert radians to degrees deg2 = self.rad2*(180./pi) z = int(options.pop('zorder', 0)) p = patches.Wedge((float(self.x), float(self.y)), float(self.r), float(deg1), float(deg2), zorder=z) a = float(options['alpha']) p.set_alpha(a) p.set_linewidth(float(options['thickness'])) p.set_fill(options['fill']) c = to_mpl_color(options['rgbcolor']) p.set_edgecolor(c) p.set_facecolor(c) p.set_label(options['legend_label']) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ TESTS:: sage: D = disk((2,-1), 2, (0, pi), color='black', thickness=3, fill=False); D Save alpha information in pdf (see :trac:`13732`):: sage: f = tmp_filename(ext='.pdf') sage: p = disk((0,0), 5, (0, pi/4), alpha=0.5) sage: p.save(f) """ import matplotlib.patches as patches options = self.options() deg1 = self.rad1*(180./pi) #convert radians to degrees deg2 = self.rad2*(180./pi) z = int(options.pop('zorder', 0)) p = patches.Wedge((float(self.x), float(self.y)), float(self.r), float(deg1), float(deg2), zorder=z) a = float(options['alpha']) p.set_alpha(a) p.set_linewidth(float(options['thickness'])) p.set_fill(options['fill']) c = to_mpl_color(options['rgbcolor']) p.set_edgecolor(c) p.set_facecolor(c) p.set_label(options['legend_label']) subplot.add_patch(p)
def _render_on_subplot(self, subplot): r""" TESTS: We check to make sure that \#2076 is fixed by verifying all the points are red:: sage: point(((1,1), (2,2), (3,3)), rgbcolor=hue(1), size=30) """ options = self.options() #Convert the color to a hex string so that the scatter #method does not interpret it as a list of 3 floating #point color specifications when there are #three points. This is mentioned in the matplotlib 0.98 #documentation and fixes \#2076 from matplotlib.colors import rgb2hex c = rgb2hex(to_mpl_color(options['rgbcolor'])) a = float(options['alpha']) z = int(options.pop('zorder', 0)) s = int(options['size']) faceted = options['faceted'] #faceted=True colors the edge of point scatteroptions = {} if not faceted: scatteroptions['edgecolors'] = 'none' subplot.scatter(self.xdata, self.ydata, s=s, c=c, alpha=a, zorder=z, label=options['legend_label'], **scatteroptions)
def _render_on_subplot(self, subplot): """ TESTS:: sage: A = arc((1,1),3,4,pi/4,(pi,4*pi/3)); A """ import matplotlib.patches as patches options = self.options() p = patches.Arc( (self.x,self.y), 2.*self.r1, 2.*self.r2, fmod(self.angle,2*pi)*(180./pi), self.s1*(180./pi), self.s2*(180./pi)) p.set_linewidth(float(options['thickness'])) a = float(options['alpha']) p.set_alpha(a) z = int(options.pop('zorder',1)) p.set_zorder(z) c = to_mpl_color(options['rgbcolor']) p.set_linestyle(options['linestyle']) p.set_edgecolor(c) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ Render this line on a matplotlib subplot. INPUT: - ``subplot`` -- a matplotlib subplot EXAMPLES: This implicitly calls this function:: sage: line([(1,2), (3,-4), (2, 5), (1,2)]) Graphics object consisting of 1 graphics primitive """ import matplotlib.lines as lines options = dict(self.options()) for o in ('alpha', 'legend_color', 'legend_label', 'linestyle', 'rgbcolor', 'thickness'): if o in options: del options[o] p = lines.Line2D(self.xdata, self.ydata, **options) options = self.options() a = float(options['alpha']) p.set_alpha(a) p.set_linewidth(float(options['thickness'])) p.set_color(to_mpl_color(options['rgbcolor'])) p.set_label(options['legend_label']) # we don't pass linestyle in directly since the drawstyles aren't # pulled off automatically. This (I think) is a bug in matplotlib 1.0.1 if 'linestyle' in options: from sage.plot.misc import get_matplotlib_linestyle p.set_linestyle(get_matplotlib_linestyle(options['linestyle'], return_type='short')) subplot.add_line(p)
def _render_on_subplot(self, subplot): """ Render this arrow in a subplot. This is the key function that defines how this arrow graphics primitive is rendered in matplotlib's library. EXAMPLES:: This function implicitly ends up rendering this arrow on a matplotlib subplot: sage: arrow(path=[[(0,1), (2,-1), (4,5)]]) """ options = self.options() width = float(options['width']) head = options.pop('head') if head == 0: style = '<|-' elif head == 1: style = '-|>' elif head == 2: style = '<|-|>' else: raise KeyError('head parameter must be one of 0 (start), 1 (end) or 2 (both).') arrowsize = float(options.get('arrowsize',5)) head_width=arrowsize head_length=arrowsize*2.0 color = to_mpl_color(options['rgbcolor']) from matplotlib.patches import FancyArrowPatch from matplotlib.path import Path bpath = Path(self.vertices, self.codes) p = FancyArrowPatch(path=bpath, lw=width, arrowstyle='%s,head_width=%s,head_length=%s'%(style,head_width, head_length), fc=color, ec=color, linestyle=options['linestyle']) p.set_zorder(options['zorder']) p.set_label(options['legend_label']) subplot.add_patch(p) return p
def _render_on_subplot(self, subplot): """ Render this line on a matplotlib subplot. INPUT: - ``subplot`` -- a matplotlib subplot EXAMPLES: This implicitly calls this function:: sage: line([(1,2), (3,-4), (2, 5), (1,2)]) """ import matplotlib.lines as lines options = dict(self.options()) del options['alpha'] del options['thickness'] del options['rgbcolor'] del options['legend_label'] if 'linestyle' in options: del options['linestyle'] p = lines.Line2D(self.xdata, self.ydata, **options) options = self.options() a = float(options['alpha']) p.set_alpha(a) p.set_linewidth(float(options['thickness'])) p.set_color(to_mpl_color(options['rgbcolor'])) p.set_label(options['legend_label']) # we don't pass linestyle in directly since the drawstyles aren't # pulled off automatically. This (I think) is a bug in matplotlib 1.0.1 if 'linestyle' in options: p.set_linestyle(options['linestyle']) subplot.add_line(p)
def _render_on_subplot(self, subplot): """ Render this arrow in a subplot. This is the key function that defines how this arrow graphics primitive is rendered in matplotlib's library. EXAMPLES: This function implicitly ends up rendering this arrow on a matplotlib subplot:: sage: arrow((0,1), (2,-1)) TESTS: The length of the ends (shrinkA and shrinkB) should not depend on the width of the arrow, because Matplotlib already takes this into account. See :trac:`12836`:: sage: fig = Graphics().matplotlib() sage: sp = fig.add_subplot(1,1,1) sage: a = arrow((0,0), (1,1)) sage: b = arrow((0,0), (1,1), width=20) sage: p1 = a[0]._render_on_subplot(sp) sage: p2 = b[0]._render_on_subplot(sp) sage: p1.shrinkA == p2.shrinkA True sage: p1.shrinkB == p2.shrinkB True """ options = self.options() head = options.pop('head') if head == 0: style = '<|-' elif head == 1: style = '-|>' elif head == 2: style = '<|-|>' else: raise KeyError( 'head parameter must be one of 0 (start), 1 (end) or 2 (both).' ) width = float(options['width']) arrowshorten_end = float(options.get('arrowshorten', 0)) / 2.0 arrowsize = float(options.get('arrowsize', 5)) head_width = arrowsize head_length = arrowsize * 2.0 color = to_mpl_color(options['rgbcolor']) from matplotlib.patches import FancyArrowPatch p = FancyArrowPatch((self.xtail, self.ytail), (self.xhead, self.yhead), lw=width, arrowstyle='%s,head_width=%s,head_length=%s' % (style, head_width, head_length), shrinkA=arrowshorten_end, shrinkB=arrowshorten_end, fc=color, ec=color, linestyle=options['linestyle']) p.set_zorder(options['zorder']) p.set_label(options['legend_label']) subplot.add_patch(p) return p
def _render_on_subplot(self, subplot): """ TESTS:: sage: A = arc((1,1),3,4,pi/4,(pi,4*pi/3)); A """ import matplotlib.patches as patches options = self.options() p = patches.Arc( (self.x,self.y), 2.*self.r1, 2.*self.r2, fmod(self.angle,2*pi)*(180./pi), self.s1*(180./pi), self.s2*(180./pi)) p.set_linewidth(float(options['thickness'])) a = float(options['alpha']) p.set_alpha(a) z = int(options.pop('zorder',1)) p.set_zorder(z) c = to_mpl_color(options['rgbcolor']) p.set_linestyle(options['linestyle']) p.set_edgecolor(c) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ Render this line on a matplotlib subplot. INPUT: - ``subplot`` -- a matplotlib subplot EXAMPLES: This implicitly calls this function:: sage: line([(1,2), (3,-4), (2, 5), (1,2)]) """ import matplotlib.lines as lines options = dict(self.options()) del options['alpha'] del options['thickness'] del options['rgbcolor'] del options['legend_label'] if 'linestyle' in options: del options['linestyle'] p = lines.Line2D(self.xdata, self.ydata, **options) options = self.options() a = float(options['alpha']) p.set_alpha(a) p.set_linewidth(float(options['thickness'])) p.set_color(to_mpl_color(options['rgbcolor'])) p.set_label(options['legend_label']) # we don't pass linestyle in directly since the drawstyles aren't # pulled off automatically. This (I think) is a bug in matplotlib 1.0.1 if 'linestyle' in options: p.set_linestyle(options['linestyle']) subplot.add_line(p)
def _render_on_subplot(self, subplot): """ TESTS:: sage: A = arc((1,1),3,4,pi/4,(pi,4*pi/3)); A Graphics object consisting of 1 graphics primitive """ import matplotlib.patches as patches from sage.plot.misc import get_matplotlib_linestyle options = self.options() p = patches.Arc( (self.x,self.y), 2.*self.r1, 2.*self.r2, fmod(self.angle,2*pi)*(180./pi), self.s1*(180./pi), self.s2*(180./pi)) p.set_linewidth(float(options['thickness'])) a = float(options['alpha']) p.set_alpha(a) z = int(options.pop('zorder',1)) p.set_zorder(z) c = to_mpl_color(options['rgbcolor']) p.set_linestyle(get_matplotlib_linestyle(options['linestyle'],return_type='long')) p.set_edgecolor(c) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ Render this arrow in a subplot. This is the key function that defines how this arrow graphics primitive is rendered in matplotlib's library. EXAMPLES: This function implicitly ends up rendering this arrow on a matplotlib subplot:: sage: arrow((0,1), (2,-1)) TESTS: The length of the ends (shrinkA and shrinkB) should not depend on the width of the arrow, because Matplotlib already takes this into account. See :trac:`12836`:: sage: fig = Graphics().matplotlib() sage: sp = fig.add_subplot(1,1,1) sage: a = arrow((0,0), (1,1)) sage: b = arrow((0,0), (1,1), width=20) sage: p1 = a[0]._render_on_subplot(sp) sage: p2 = b[0]._render_on_subplot(sp) sage: p1.shrinkA == p2.shrinkA True sage: p1.shrinkB == p2.shrinkB True """ options = self.options() head = options.pop('head') if head == 0: style = '<|-' elif head == 1: style = '-|>' elif head == 2: style = '<|-|>' else: raise KeyError('head parameter must be one of 0 (start), 1 (end) or 2 (both).') width = float(options['width']) arrowshorten_end = float(options.get('arrowshorten',0))/2.0 arrowsize = float(options.get('arrowsize',5)) head_width=arrowsize head_length=arrowsize*2.0 color = to_mpl_color(options['rgbcolor']) from matplotlib.patches import FancyArrowPatch p = FancyArrowPatch((self.xtail, self.ytail), (self.xhead, self.yhead), lw=width, arrowstyle='%s,head_width=%s,head_length=%s'%(style,head_width, head_length), shrinkA=arrowshorten_end, shrinkB=arrowshorten_end, fc=color, ec=color, linestyle=options['linestyle']) p.set_zorder(options['zorder']) p.set_label(options['legend_label']) subplot.add_patch(p) return p
def _render_on_subplot(self, subplot): """ Render this arrow in a subplot. This is the key function that defines how this arrow graphics primitive is rendered in matplotlib's library. EXAMPLES: This function implicitly ends up rendering this arrow on a matplotlib subplot:: sage: arrow(path=[[(0,1), (2,-1), (4,5)]]) Graphics object consisting of 1 graphics primitive """ from sage.plot.misc import get_matplotlib_linestyle options = self.options() width = float(options['width']) head = options.pop('head') if head == 0: style = '<|-' elif head == 1: style = '-|>' elif head == 2: style = '<|-|>' else: raise KeyError( 'head parameter must be one of 0 (start), 1 (end) or 2 (both).' ) arrowsize = float(options.get('arrowsize', 5)) head_width = arrowsize head_length = arrowsize * 2.0 color = to_mpl_color(options['rgbcolor']) from matplotlib.patches import FancyArrowPatch from matplotlib.path import Path bpath = Path(self.vertices, self.codes) p = FancyArrowPatch(path=bpath, lw=width, arrowstyle='%s,head_width=%s,head_length=%s' % (style, head_width, head_length), fc=color, ec=color, linestyle=get_matplotlib_linestyle( options['linestyle'], return_type='long')) p.set_zorder(options['zorder']) p.set_label(options['legend_label']) subplot.add_patch(p) return p
def _render_on_subplot(self, subplot): """ Render this ellipse in a subplot. This is the key function that defines how this ellipse graphics primitive is rendered in matplotlib's library. TESTS:: sage: ellipse((0,0),3,1,pi/6,fill=True,alpha=0.3) Graphics object consisting of 1 graphics primitive :: sage: ellipse((3,2),1,2) Graphics object consisting of 1 graphics primitive """ import matplotlib.patches as patches from sage.plot.misc import get_matplotlib_linestyle options = self.options() p = patches.Ellipse((self.x, self.y), self.r1 * 2.0, self.r2 * 2.0, self.angle / pi * 180.0) p.set_linewidth(float(options["thickness"])) p.set_fill(options["fill"]) a = float(options["alpha"]) p.set_alpha(a) ec = to_mpl_color(options["edgecolor"]) fc = to_mpl_color(options["facecolor"]) if "rgbcolor" in options: ec = fc = to_mpl_color(options["rgbcolor"]) p.set_edgecolor(ec) p.set_facecolor(fc) p.set_linestyle(get_matplotlib_linestyle(options["linestyle"], return_type="long")) p.set_label(options["legend_label"]) z = int(options.pop("zorder", 0)) p.set_zorder(z) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ Render this arrow in a subplot. This is the key function that defines how this arrow graphics primitive is rendered in matplotlib's library. EXAMPLES:: This function implicitly ends up rendering this arrow on a matplotlib subplot: sage: arrow(path=[[(0,1), (2,-1), (4,5)]]) Graphics object consisting of 1 graphics primitive """ from sage.plot.misc import get_matplotlib_linestyle options = self.options() width = float(options["width"]) head = options.pop("head") if head == 0: style = "<|-" elif head == 1: style = "-|>" elif head == 2: style = "<|-|>" else: raise KeyError("head parameter must be one of 0 (start), 1 (end) or 2 (both).") arrowsize = float(options.get("arrowsize", 5)) head_width = arrowsize head_length = arrowsize * 2.0 color = to_mpl_color(options["rgbcolor"]) from matplotlib.patches import FancyArrowPatch from matplotlib.path import Path bpath = Path(self.vertices, self.codes) p = FancyArrowPatch( path=bpath, lw=width, arrowstyle="%s,head_width=%s,head_length=%s" % (style, head_width, head_length), fc=color, ec=color, ) p.set_linestyle(get_matplotlib_linestyle(options["linestyle"], return_type="long")) p.set_zorder(options["zorder"]) p.set_label(options["legend_label"]) subplot.add_patch(p) return p
def _render_on_subplot(self, subplot): """ Render this Bezier path in a subplot. This is the key function that defines how this Bezier path graphics primitive is rendered in matplotlib's library. TESTS:: sage: bezier_path([[(0,1),(.5,0),(1,1)]]) Graphics object consisting of 1 graphics primitive :: sage: bezier_path([[(0,1),(.5,0),(1,1),(-3,5)]]) Graphics object consisting of 1 graphics primitive """ from matplotlib.patches import PathPatch from matplotlib.path import Path from sage.plot.misc import get_matplotlib_linestyle options = dict(self.options()) del options['alpha'] del options['thickness'] del options['rgbcolor'] del options['zorder'] del options['fill'] del options['linestyle'] bpath = Path(self.vertices, self.codes) bpatch = PathPatch(bpath, **options) options = self.options() bpatch.set_linewidth(float(options['thickness'])) bpatch.set_fill(options['fill']) bpatch.set_zorder(options['zorder']) a = float(options['alpha']) bpatch.set_alpha(a) c = to_mpl_color(options['rgbcolor']) bpatch.set_edgecolor(c) bpatch.set_facecolor(c) bpatch.set_linestyle( get_matplotlib_linestyle(options['linestyle'], return_type='long')) subplot.add_patch(bpatch)
def _render_on_subplot(self, subplot): """ Render this arrow in a subplot. This is the key function that defines how this arrow graphics primitive is rendered in matplotlib's library. EXAMPLES: This function implicitly ends up rendering this arrow on a matplotlib subplot:: sage: arrow((0,1), (2,-1)) """ options = self.options() head = options.pop('head') if head == 0: style = '<|-' elif head == 1: style = '-|>' elif head == 2: style = '<|-|>' else: raise KeyError( 'head parameter must be one of 0 (start), 1 (end) or 2 (both).' ) width = float(options['width']) arrowshorten_end = float(options.get('arrowshorten', 0)) / 2.0 + width * 2 arrowsize = float(options.get('arrowsize', 5)) head_width = arrowsize head_length = arrowsize * 2.0 color = to_mpl_color(options['rgbcolor']) from matplotlib.patches import FancyArrowPatch p = FancyArrowPatch((self.xtail, self.ytail), (self.xhead, self.yhead), lw=width, arrowstyle='%s,head_width=%s,head_length=%s' % (style, head_width, head_length), shrinkA=arrowshorten_end, shrinkB=arrowshorten_end, fc=color, ec=color, linestyle=options['linestyle']) p.set_zorder(options['zorder']) p.set_label(options['legend_label']) subplot.add_patch(p) return p
def _render_on_subplot(self, subplot): """ Render this Bezier path in a subplot. This is the key function that defines how this Bezier path graphics primitive is rendered in matplotlib's library. TESTS:: sage: bezier_path([[(0,1),(.5,0),(1,1)]]) Graphics object consisting of 1 graphics primitive :: sage: bezier_path([[(0,1),(.5,0),(1,1),(-3,5)]]) Graphics object consisting of 1 graphics primitive """ from matplotlib.patches import PathPatch from matplotlib.path import Path from sage.plot.misc import get_matplotlib_linestyle options = dict(self.options()) del options['alpha'] del options['thickness'] del options['rgbcolor'] del options['zorder'] del options['fill'] del options['linestyle'] bpath = Path(self.vertices, self.codes) bpatch = PathPatch(bpath, **options) options = self.options() bpatch.set_linewidth(float(options['thickness'])) bpatch.set_fill(options['fill']) bpatch.set_zorder(options['zorder']) a = float(options['alpha']) bpatch.set_alpha(a) c = to_mpl_color(options['rgbcolor']) bpatch.set_edgecolor(c) bpatch.set_facecolor(c) bpatch.set_linestyle(get_matplotlib_linestyle(options['linestyle'], return_type='long')) subplot.add_patch(bpatch)
def _render_on_subplot(self, subplot): """ TESTS:: sage: D = disk((2,-1), 2, (0, pi), color='black', thickness=3, fill=False); D """ import matplotlib.patches as patches options = self.options() deg1 = self.rad1*(180./pi) #convert radians to degrees deg2 = self.rad2*(180./pi) z = int(options.pop('zorder', 0)) p = patches.Wedge((float(self.x), float(self.y)), float(self.r), float(deg1), float(deg2), zorder=z) p.set_linewidth(float(options['thickness'])) p.set_fill(options['fill']) p.set_alpha(options['alpha']) c = to_mpl_color(options['rgbcolor']) p.set_edgecolor(c) p.set_facecolor(c) p.set_label(options['legend_label']) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ TESTS:: sage: D = disk((2,-1), 2, (0, pi), color='black', thickness=3, fill=False); D """ import matplotlib.patches as patches options = self.options() deg1 = self.rad1*(180./pi) #convert radians to degrees deg2 = self.rad2*(180./pi) z = int(options.pop('zorder', 0)) p = patches.Wedge((float(self.x), float(self.y)), float(self.r), float(deg1), float(deg2), zorder=z) p.set_linewidth(float(options['thickness'])) p.set_fill(options['fill']) p.set_alpha(options['alpha']) c = to_mpl_color(options['rgbcolor']) p.set_edgecolor(c) p.set_facecolor(c) p.set_label(options['legend_label']) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ TESTS:: sage: A = arc((1,1),3,4,pi/4,(pi,4*pi/3)); A Graphics object consisting of 1 graphics primitive """ from sage.plot.misc import get_matplotlib_linestyle options = self.options() p = self._matplotlib_arc() p.set_linewidth(float(options['thickness'])) a = float(options['alpha']) p.set_alpha(a) z = int(options.pop('zorder', 1)) p.set_zorder(z) c = to_mpl_color(options['rgbcolor']) p.set_linestyle( get_matplotlib_linestyle(options['linestyle'], return_type='long')) p.set_edgecolor(c) subplot.add_patch(p)
def _render_on_subplot(self, subplot): """ TESTS:: sage: A = arc((1,1),3,4,pi/4,(pi,4*pi/3)); A Graphics object consisting of 1 graphics primitive """ from sage.plot.misc import get_matplotlib_linestyle options = self.options() p = self._matplotlib_arc() p.set_linewidth(float(options['thickness'])) a = float(options['alpha']) p.set_alpha(a) z = int(options.pop('zorder', 1)) p.set_zorder(z) c = to_mpl_color(options['rgbcolor']) p.set_linestyle(get_matplotlib_linestyle(options['linestyle'], return_type='long')) p.set_edgecolor(c) subplot.add_patch(p)
def _render_on_subplot(self, subplot): r""" Render this arrow in a subplot. This version of the method uses a narrower arrow head, which is not customizable by parameters in the Sage class. """ from sage.plot.misc import get_matplotlib_linestyle options = self.options() head = options.pop('head') if head == 0: style = '<|-' elif head == 1: style = '-|>' elif head == 2: style = '<|-|>' else: raise KeyError('head parameter must be one of 0 (start), 1 (end) or 2 (both).') style='fancy' width = float(options['width']) arrowshorten_end = float(options.get('arrowshorten', 0)) / 2.0 arrowsize = float(options.get('arrowsize', 5)) #head_width = arrowsize * 0.5 head_width = arrowsize * 0.7 tail_width = arrowsize * 0.7 head_length = arrowsize * 2.0 color = to_mpl_color(options['rgbcolor']) from matplotlib.patches import FancyArrowPatch p = FancyArrowPatch((self.xtail, self.ytail), (self.xhead, self.yhead), lw=width, arrowstyle='%s,head_width=%s,head_length=%s,tail_width=%s' % (style, head_width, head_length, tail_width), shrinkA=arrowshorten_end, shrinkB=arrowshorten_end, fc=color, ec=color, linestyle=get_matplotlib_linestyle(options['linestyle'], return_type='long')) p.set_zorder(options['zorder']) p.set_label(options['legend_label']) subplot.add_patch(p) return p
def text(string, xy, **options): r""" Returns a 2D text graphics object at the point `(x,y)`. Type ``text.options`` for a dictionary of options for 2D text. 2D OPTIONS: - ``fontsize`` - How big the text is. Either an integer that specifies the size in points or a string which specifies a size (one of 'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large') - ``fontstyle`` - A string either 'normal', 'italic' or 'oblique' - ``fontweight`` - A numeric value in the range 0-1000 or a string (one of 'ultralight', 'light', 'normal', 'regular', 'book',' 'medium', 'roman', 'semibold', 'demibold', 'demi', 'bold', 'heavy', 'extra bold', 'black') - ``rgbcolor`` - The color as an RGB tuple - ``hue`` - The color given as a hue - ``alpha`` - A float (0.0 transparent through 1.0 opaque) - ``background_color`` - The background color - ``rotation`` - How to rotate the text: angle in degrees, vertical, horizontal - ``vertical_alignment`` - How to align vertically: top, center, bottom - ``horizontal_alignment`` - How to align horizontally: left, center, right - ``zorder`` - The layer level in which to draw - ``clip`` - (default: False) Whether to clip or not - ``axis_coords`` - (default: False) If True, use axis coordinates, so that (0,0) is the lower left and (1,1) upper right, regardless of the x and y range of plotted values. - ``bounding_box`` - A dictionary specifying a bounding box. Currently the text location. EXAMPLES:: sage: text("Sage graphics are really neat because they use matplotlib!", (2,12)) Graphics object consisting of 1 graphics primitive .. PLOT:: t = "Sage graphics are really neat because they use matplotlib!" sphinx_plot(text(t,(2,12))) Larger font, bold, colored red and transparent text:: sage: text("I had a dream!", (2,12), alpha=0.3, fontsize='large', fontweight='bold', color='red') Graphics object consisting of 1 graphics primitive .. PLOT:: sphinx_plot(text("I had a dream!", (2,12), alpha=0.3, fontsize='large', fontweight='bold', color='red')) By setting ``horizontal_alignment`` to 'left' the text is guaranteed to be in the lower left no matter what:: sage: text("I got a horse and he lives in a tree", (0,0), axis_coords=True, horizontal_alignment='left') Graphics object consisting of 1 graphics primitive .. PLOT:: t = "I got a horse and he lives in a tree" sphinx_plot(text(t, (0,0), axis_coords=True, horizontal_alignment='left')) Various rotations:: sage: text("noitator", (0,0), rotation=45.0, horizontal_alignment='left', vertical_alignment='bottom') Graphics object consisting of 1 graphics primitive .. PLOT:: sphinx_plot(text("noitator", (0,0), rotation=45.0, horizontal_alignment='left', vertical_alignment='bottom')) :: sage: text("Sage is really neat!!",(0,0), rotation="vertical") Graphics object consisting of 1 graphics primitive .. PLOT:: sphinx_plot(text("Sage is really neat!!",(0,0), rotation="vertical")) You can also align text differently:: sage: t1 = text("Hello",(1,1), vertical_alignment="top") sage: t2 = text("World", (1,0.5), horizontal_alignment="left") sage: t1 + t2 # render the sum Graphics object consisting of 2 graphics primitives .. PLOT:: t1 = text("Hello",(1,1), vertical_alignment="top") t2 = text("World", (1,0.5), horizontal_alignment="left") sphinx_plot(t1 + t2) You can save text as part of PDF output:: sage: text("sage", (0,0), rgbcolor=(0,0,0)).save(os.path.join(SAGE_TMP, 'a.pdf')) Some examples of bounding box:: sage: bbox = {'boxstyle':"rarrow,pad=0.3", 'fc':"cyan", 'ec':"b", 'lw':2} sage: text("I feel good", (1,2), bounding_box=bbox) Graphics object consisting of 1 graphics primitive .. PLOT:: bbox = {'boxstyle':"rarrow,pad=0.3", 'fc':"cyan", 'ec':"b", 'lw':2} sphinx_plot(text("I feel good", (1,2), bounding_box=bbox)) :: sage: text("So good", (0,0), bounding_box={'boxstyle':'round', 'fc':'w'}) Graphics object consisting of 1 graphics primitive .. PLOT:: bbox = {'boxstyle':'round', 'fc':'w'} sphinx_plot(text("So good", (0,0), bounding_box=bbox)) The possible options of the bounding box are 'boxstyle' (one of 'larrow', 'rarrow', 'round', 'round4', 'roundtooth', 'sawtooth', 'square'), 'fc' or 'facecolor', 'ec' or 'edgecolor', 'ha' or 'horizontalalignment', 'va' or 'verticalalignment', 'lw' or 'linewidth'. A text with a background color:: sage: text("So good", (-2,2), background_color='red') Graphics object consisting of 1 graphics primitive .. PLOT:: sphinx_plot(text("So good", (-2,2), background_color='red')) Text must be 2D (use the text3d command for 3D text):: sage: t = text("hi",(1,2,3)) Traceback (most recent call last): ... ValueError: use text3d instead for text in 3d sage: t = text3d("hi",(1,2,3)) Extra options will get passed on to show(), as long as they are valid:: sage: text("MATH IS AWESOME", (0, 0), fontsize=40, axes=False) Graphics object consisting of 1 graphics primitive sage: text("MATH IS AWESOME", (0, 0), fontsize=40).show(axes=False) # These are equivalent """ try: x, y = xy except ValueError: if isinstance(xy, (list, tuple)) and len(xy) == 3: raise ValueError("use text3d instead for text in 3d") raise from sage.plot.all import Graphics options['rgbcolor'] = to_mpl_color(options['rgbcolor']) point = (float(x), float(y)) g = Graphics() g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore='fontsize')) g.add_primitive(Text(string, point, options)) return g
def _render_on_subplot(self, subplot): r""" Render this arrow in a subplot. This is the key function that defines how this arrow graphics primitive is rendered in matplotlib's library. EXAMPLES: This function implicitly ends up rendering this arrow on a matplotlib subplot:: sage: arrow((0,1), (2,-1)) Graphics object consisting of 1 graphics primitive TESTS: The length of the ends (shrinkA and shrinkB) should not depend on the width of the arrow, because Matplotlib already takes this into account. See :trac:`12836`:: sage: fig = Graphics().matplotlib() sage: sp = fig.add_subplot(1,1,1) sage: a = arrow((0,0), (1,1)) sage: b = arrow((0,0), (1,1), width=20) sage: p1 = a[0]._render_on_subplot(sp) sage: p2 = b[0]._render_on_subplot(sp) sage: p1.shrinkA == p2.shrinkA True sage: p1.shrinkB == p2.shrinkB True Dashed arrows should have solid arrowheads, :trac:`12852`. This test saves the plot of a dashed arrow to an EPS file. Within the EPS file, ``stroke`` will be called twice: once to draw the line, and again to draw the arrowhead. We check that both calls do not occur while the dashed line style is enabled:: sage: a = arrow((0,0), (1,1), linestyle='dashed') sage: filename = tmp_filename(ext='.eps') sage: a.save(filename=filename) sage: with open(filename, 'r') as f: ....: contents = f.read().replace('\n', ' ') sage: two_stroke_pattern = r'setdash.*stroke.*stroke.*setdash' sage: import re sage: two_stroke_re = re.compile(two_stroke_pattern) sage: two_stroke_re.search(contents) is None True """ from sage.plot.misc import get_matplotlib_linestyle options = self.options() head = options.pop('head') if head == 0: style = '<|-' elif head == 1: style = '-|>' elif head == 2: style = '<|-|>' else: raise KeyError( 'head parameter must be one of 0 (start), 1 (end) or 2 (both).' ) width = float(options['width']) arrowshorten_end = float(options.get('arrowshorten', 0)) / 2.0 arrowsize = float(options.get('arrowsize', 5)) head_width = arrowsize head_length = arrowsize * 2.0 color = to_mpl_color(options['rgbcolor']) from matplotlib.patches import FancyArrowPatch p = FancyArrowPatch((self.xtail, self.ytail), (self.xhead, self.yhead), lw=width, arrowstyle='%s,head_width=%s,head_length=%s' % (style, head_width, head_length), shrinkA=arrowshorten_end, shrinkB=arrowshorten_end, fc=color, ec=color) p.set_linestyle( get_matplotlib_linestyle(options['linestyle'], return_type='long')) p.set_zorder(options['zorder']) p.set_label(options['legend_label']) if options['linestyle'] != 'solid': # The next few lines work around a design issue in matplotlib. Currently, the specified # linestyle is used to draw both the path and the arrowhead. If linestyle is 'dashed', this # looks really odd. This code is from Jae-Joon Lee in response to a post to the matplotlib mailing # list. See http://sourceforge.net/mailarchive/forum.php?thread_name=CAG%3DuJ%2Bnw2dE05P9TOXTz_zp-mGP3cY801vMH7yt6vgP9_WzU8w%40mail.gmail.com&forum_name=matplotlib-users import matplotlib.patheffects as pe class CheckNthSubPath(object): def __init__(self, patch, n): """ creates an callable object that returns True if the provided path is the n-th path from the patch. """ self._patch = patch self._n = n def get_paths(self, renderer): self._patch.set_dpi_cor(renderer.points_to_pixels(1.)) paths, fillables = self._patch.get_path_in_displaycoord() return paths def __call__(self, renderer, gc, tpath, affine, rgbFace): path = self.get_paths(renderer)[self._n] vert1, code1 = path.vertices, path.codes import numpy as np return np.array_equal(vert1, tpath.vertices) and np.array_equal( code1, tpath.codes) class ConditionalStroke(pe.RendererBase): def __init__(self, condition_func, pe_list): """ path effect that is only applied when the condition_func returns True. """ super(ConditionalStroke, self).__init__() self._pe_list = pe_list self._condition_func = condition_func def draw_path(self, renderer, gc, tpath, affine, rgbFace): if self._condition_func(renderer, gc, tpath, affine, rgbFace): for pe1 in self._pe_list: pe1.draw_path(renderer, gc, tpath, affine, rgbFace) pe1 = ConditionalStroke(CheckNthSubPath(p, 0), [pe.Stroke()]) pe2 = ConditionalStroke(CheckNthSubPath(p, 1), [pe.Stroke(linestyle="solid")]) p.set_path_effects([pe1, pe2]) subplot.add_patch(p) return p
def _render_on_subplot(self, subplot): r""" Render this arrow in a subplot. This is the key function that defines how this arrow graphics primitive is rendered in matplotlib's library. EXAMPLES: This function implicitly ends up rendering this arrow on a matplotlib subplot:: sage: arrow((0,1), (2,-1)) Graphics object consisting of 1 graphics primitive TESTS: The length of the ends (shrinkA and shrinkB) should not depend on the width of the arrow, because Matplotlib already takes this into account. See :trac:`12836`:: sage: fig = Graphics().matplotlib() sage: sp = fig.add_subplot(1,1,1, label='axis1') sage: a = arrow((0,0), (1,1)) sage: b = arrow((0,0), (1,1), width=20) sage: p1 = a[0]._render_on_subplot(sp) sage: p2 = b[0]._render_on_subplot(sp) sage: p1.shrinkA == p2.shrinkA True sage: p1.shrinkB == p2.shrinkB True Dashed arrows should have solid arrowheads, :trac:`12852`. We tried to make up a test for this, which turned out to be fragile and hence was removed. In general, robust testing of graphics seems basically need a human eye or AI. """ from sage.plot.misc import get_matplotlib_linestyle options = self.options() head = options.pop('head') if head == 0: style = '<|-' elif head == 1: style = '-|>' elif head == 2: style = '<|-|>' else: raise KeyError( 'head parameter must be one of 0 (start), 1 (end) or 2 (both).' ) width = float(options['width']) arrowshorten_end = float(options.get('arrowshorten', 0)) / 2.0 arrowsize = float(options.get('arrowsize', 5)) head_width = arrowsize head_length = arrowsize * 2.0 color = to_mpl_color(options['rgbcolor']) from matplotlib.patches import FancyArrowPatch p = FancyArrowPatch( (self.xtail, self.ytail), (self.xhead, self.yhead), lw=width, arrowstyle='%s,head_width=%s,head_length=%s' % (style, head_width, head_length), shrinkA=arrowshorten_end, shrinkB=arrowshorten_end, fc=color, ec=color, linestyle=get_matplotlib_linestyle(options['linestyle'], return_type='long')) p.set_zorder(options['zorder']) p.set_label(options['legend_label']) if options['linestyle'] != 'solid': # The next few lines work around a design issue in matplotlib. # Currently, the specified linestyle is used to draw both the path # and the arrowhead. If linestyle is 'dashed', this looks really # odd. This code is from Jae-Joon Lee in response to a post to the # matplotlib mailing list. # See http://sourceforge.net/mailarchive/forum.php?thread_name=CAG%3DuJ%2Bnw2dE05P9TOXTz_zp-mGP3cY801vMH7yt6vgP9_WzU8w%40mail.gmail.com&forum_name=matplotlib-users import matplotlib.patheffects as pe class CheckNthSubPath(object): def __init__(self, patch, n): """ creates an callable object that returns True if the provided path is the n-th path from the patch. """ self._patch = patch self._n = n def get_paths(self, renderer): self._patch.set_dpi_cor(renderer.points_to_pixels(1.)) paths, fillables = self._patch.get_path_in_displaycoord() return paths def __call__(self, renderer, gc, tpath, affine, rgbFace): path = self.get_paths(renderer)[self._n] vert1, code1 = path.vertices, path.codes import numpy as np return np.array_equal(vert1, tpath.vertices) and np.array_equal( code1, tpath.codes) class ConditionalStroke(pe.RendererBase): def __init__(self, condition_func, pe_list): """ path effect that is only applied when the condition_func returns True. """ super(ConditionalStroke, self).__init__() self._pe_list = pe_list self._condition_func = condition_func def draw_path(self, renderer, gc, tpath, affine, rgbFace): if self._condition_func(renderer, gc, tpath, affine, rgbFace): for pe1 in self._pe_list: pe1.draw_path(renderer, gc, tpath, affine, rgbFace) pe1 = ConditionalStroke(CheckNthSubPath(p, 0), [pe.Stroke()]) pe2 = ConditionalStroke( CheckNthSubPath(p, 1), [pe.Stroke(dashes={ 'dash_offset': 0, 'dash_list': None })]) p.set_path_effects([pe1, pe2]) subplot.add_patch(p) return p
def text(string, xy, **options): r""" Returns a 2D text graphics object at the point `(x,y)`. Type ``text.options`` for a dictionary of options for 2D text. 2D OPTIONS: - ``fontsize`` - How big the text is - ``rgbcolor`` - The color as an RGB tuple - ``hue`` - The color given as a hue - ``rotation`` - How to rotate the text: angle in degrees, vertical, horizontal - ``vertical_alignment`` - How to align vertically: top, center, bottom - ``horizontal_alignment`` - How to align horizontally: left, center, right - ``axis_coords`` - (default: False) if True, use axis coordinates, so that (0,0) is the lower left and (1,1) upper right, regardless of the x and y range of plotted values. EXAMPLES:: sage: text("Sage is really neat!!",(2,12)) Graphics object consisting of 1 graphics primitive The same text in larger font and colored red:: sage: text("Sage is really neat!!",(2,12),fontsize=20,rgbcolor=(1,0,0)) Graphics object consisting of 1 graphics primitive Same text but guaranteed to be in the lower left no matter what:: sage: text("Sage is really neat!!",(0,0), axis_coords=True, horizontal_alignment='left') Graphics object consisting of 1 graphics primitive Same text rotated around the left, bottom corner of the text:: sage: text("Sage is really neat!!",(0,0), rotation=45.0, horizontal_alignment='left', vertical_alignment='bottom') Graphics object consisting of 1 graphics primitive Same text oriented vertically:: sage: text("Sage is really neat!!",(0,0), rotation="vertical") Graphics object consisting of 1 graphics primitive You can also align text differently:: sage: t1 = text("Hello",(1,1), vertical_alignment="top") sage: t2 = text("World", (1,0.5), horizontal_alignment="left") sage: t1 + t2 # render the sum Graphics object consisting of 2 graphics primitives You can save text as part of PDF output:: sage: text("sage", (0,0), rgbcolor=(0,0,0)).save(os.path.join(SAGE_TMP, 'a.pdf')) Text must be 2D (use the text3d command for 3D text):: sage: t = text("hi",(1,2,3)) Traceback (most recent call last): ... ValueError: use text3d instead for text in 3d sage: t = text3d("hi",(1,2,3)) Extra options will get passed on to show(), as long as they are valid:: sage: text("MATH IS AWESOME", (0, 0), fontsize=40, axes=False) Graphics object consisting of 1 graphics primitive sage: text("MATH IS AWESOME", (0, 0), fontsize=40).show(axes=False) # These are equivalent """ try: x, y = xy except ValueError: if isinstance(xy, (list, tuple)) and len(xy) == 3: raise ValueError("use text3d instead for text in 3d") raise from sage.plot.all import Graphics options['rgbcolor'] = to_mpl_color(options['rgbcolor']) point = (float(x), float(y)) g = Graphics() g._set_extra_kwds( Graphics._extract_kwds_for_show(options, ignore='fontsize')) g.add_primitive(Text(string, point, options)) return g
def text(string, xy, **options): r""" Returns a 2D text graphics object at the point `(x,y)`. Type ``text.options`` for a dictionary of options for 2D text. 2D OPTIONS: - ``fontsize`` - How big the text is. Either an integer that specifies the size in points or a string which specifies a size (one of 'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large') - ``fontstyle`` - A string either 'normal', 'italic' or 'oblique' - ``fontweight`` - A numeric value in the range 0-1000 or a string (one of 'ultralight', 'light', 'normal', 'regular', 'book',' 'medium', 'roman', 'semibold', 'demibold', 'demi', 'bold', 'heavy', 'extra bold', 'black') - ``rgbcolor`` - The color as an RGB tuple - ``hue`` - The color given as a hue - ``alpha`` - A float (0.0 transparent through 1.0 opaque) - ``background_color`` - The background color - ``rotation`` - How to rotate the text: angle in degrees, vertical, horizontal - ``vertical_alignment`` - How to align vertically: top, center, bottom - ``horizontal_alignment`` - How to align horizontally: left, center, right - ``zorder`` - The layer level in which to draw - ``clip`` - (default: False) Whether to clip or not - ``axis_coords`` - (default: False) If True, use axis coordinates, so that (0,0) is the lower left and (1,1) upper right, regardless of the x and y range of plotted values. - ``bounding_box`` - A dictionary specifying a bounding box. Currently the text location. EXAMPLES:: sage: text("Sage graphics are really neat because they use matplotlib!", (2,12)) Graphics object consisting of 1 graphics primitive .. PLOT:: t = "Sage graphics are really neat because they use matplotlib!" sphinx_plot(text(t,(2,12))) Larger font, bold, colored red and transparent text:: sage: text("I had a dream!", (2,12), alpha=0.3, fontsize='large', fontweight='bold', color='red') Graphics object consisting of 1 graphics primitive .. PLOT:: sphinx_plot(text("I had a dream!", (2,12), alpha=0.3, fontsize='large', fontweight='bold', color='red')) By setting ``horizontal_alignment`` to 'left' the text is guaranteed to be in the lower left no matter what:: sage: text("I got a horse and he lives in a tree", (0,0), axis_coords=True, horizontal_alignment='left') Graphics object consisting of 1 graphics primitive .. PLOT:: t = "I got a horse and he lives in a tree" sphinx_plot(text(t, (0,0), axis_coords=True, horizontal_alignment='left')) Various rotations:: sage: text("noitator", (0,0), rotation=45.0, horizontal_alignment='left', vertical_alignment='bottom') Graphics object consisting of 1 graphics primitive .. PLOT:: sphinx_plot(text("noitator", (0,0), rotation=45.0, horizontal_alignment='left', vertical_alignment='bottom')) :: sage: text("Sage is really neat!!",(0,0), rotation="vertical") Graphics object consisting of 1 graphics primitive .. PLOT:: sphinx_plot(text("Sage is really neat!!",(0,0), rotation="vertical")) You can also align text differently:: sage: t1 = text("Hello",(1,1), vertical_alignment="top") sage: t2 = text("World", (1,0.5), horizontal_alignment="left") sage: t1 + t2 # render the sum Graphics object consisting of 2 graphics primitives .. PLOT:: t1 = text("Hello",(1,1), vertical_alignment="top") t2 = text("World", (1,0.5), horizontal_alignment="left") sphinx_plot(t1 + t2) You can save text as part of PDF output:: sage: text("sage", (0,0), rgbcolor=(0,0,0)).save(os.path.join(SAGE_TMP, 'a.pdf')) Some examples of bounding box:: sage: bbox = {'boxstyle':"rarrow,pad=0.3", 'fc':"cyan", 'ec':"b", 'lw':2} sage: text("I feel good", (1,2), bounding_box=bbox) Graphics object consisting of 1 graphics primitive .. PLOT:: bbox = {'boxstyle':"rarrow,pad=0.3", 'fc':"cyan", 'ec':"b", 'lw':2} sphinx_plot(text("I feel good", (1,2), bounding_box=bbox)) :: sage: text("So good", (0,0), bounding_box={'boxstyle':'round', 'fc':'w'}) Graphics object consisting of 1 graphics primitive .. PLOT:: bbox = {'boxstyle':'round', 'fc':'w'} sphinx_plot(text("So good", (0,0), bounding_box=bbox)) The possible options of the bounding box are 'boxstyle' (one of 'larrow', 'rarrow', 'round', 'round4', 'roundtooth', 'sawtooth', 'square'), 'fc' or 'facecolor', 'ec' or 'edgecolor', 'ha' or 'horizontalalignment', 'va' or 'verticalalignment', 'lw' or 'linewidth'. A text with a background color:: sage: text("So good", (-2,2), background_color='red') Graphics object consisting of 1 graphics primitive .. PLOT:: sphinx_plot(text("So good", (-2,2), background_color='red')) Text must be 2D (use the text3d command for 3D text):: sage: t = text("hi",(1,2,3)) Traceback (most recent call last): ... ValueError: use text3d instead for text in 3d sage: t = text3d("hi",(1,2,3)) Extra options will get passed on to show(), as long as they are valid:: sage: text("MATH IS AWESOME", (0, 0), fontsize=40, axes=False) Graphics object consisting of 1 graphics primitive sage: text("MATH IS AWESOME", (0, 0), fontsize=40).show(axes=False) # These are equivalent """ try: x, y = xy except ValueError: if isinstance(xy, (list, tuple)) and len(xy) == 3: raise ValueError("use text3d instead for text in 3d") raise from sage.plot.all import Graphics options['rgbcolor'] = to_mpl_color(options['rgbcolor']) point = (float(x), float(y)) g = Graphics() g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore='fontsize')) g.add_primitive(Text(string, point, options)) return g
def _render_on_subplot(self, subplot): r""" Render this arrow in a subplot. This is the key function that defines how this arrow graphics primitive is rendered in matplotlib's library. EXAMPLES: This function implicitly ends up rendering this arrow on a matplotlib subplot:: sage: arrow((0,1), (2,-1)) TESTS: The length of the ends (shrinkA and shrinkB) should not depend on the width of the arrow, because Matplotlib already takes this into account. See :trac:`12836`:: sage: fig = Graphics().matplotlib() sage: sp = fig.add_subplot(1,1,1) sage: a = arrow((0,0), (1,1)) sage: b = arrow((0,0), (1,1), width=20) sage: p1 = a[0]._render_on_subplot(sp) sage: p2 = b[0]._render_on_subplot(sp) sage: p1.shrinkA == p2.shrinkA True sage: p1.shrinkB == p2.shrinkB True Dashed arrows should have solid arrowheads, :trac:`12852`. This test saves the plot of a dashed arrow to an EPS file. Within the EPS file, ``stroke`` will be called twice: once to draw the line, and again to draw the arrowhead. We check that both calls do not occur while the dashed line style is enabled:: sage: a = arrow((0,0), (1,1), linestyle='dashed') sage: filename = tmp_filename(ext='.eps') sage: a.save(filename=filename) sage: with open(filename, 'r') as f: ....: contents = f.read().replace('\n', ' ') sage: two_stroke_pattern = r'setdash.*stroke.*stroke.*setdash' sage: import re sage: two_stroke_re = re.compile(two_stroke_pattern) sage: two_stroke_re.search(contents) is None True """ options = self.options() head = options.pop('head') if head == 0: style = '<|-' elif head == 1: style = '-|>' elif head == 2: style = '<|-|>' else: raise KeyError('head parameter must be one of 0 (start), 1 (end) or 2 (both).') width = float(options['width']) arrowshorten_end = float(options.get('arrowshorten',0))/2.0 arrowsize = float(options.get('arrowsize',5)) head_width=arrowsize head_length=arrowsize*2.0 color = to_mpl_color(options['rgbcolor']) from matplotlib.patches import FancyArrowPatch p = FancyArrowPatch((self.xtail, self.ytail), (self.xhead, self.yhead), lw=width, arrowstyle='%s,head_width=%s,head_length=%s'%(style,head_width, head_length), shrinkA=arrowshorten_end, shrinkB=arrowshorten_end, fc=color, ec=color, linestyle=options['linestyle']) p.set_zorder(options['zorder']) p.set_label(options['legend_label']) if options['linestyle']!='solid': # The next few lines work around a design issue in matplotlib. Currently, the specified # linestyle is used to draw both the path and the arrowhead. If linestyle is 'dashed', this # looks really odd. This code is from Jae-Joon Lee in response to a post to the matplotlib mailing # list. See http://sourceforge.net/mailarchive/forum.php?thread_name=CAG%3DuJ%2Bnw2dE05P9TOXTz_zp-mGP3cY801vMH7yt6vgP9_WzU8w%40mail.gmail.com&forum_name=matplotlib-users import matplotlib.patheffects as pe class CheckNthSubPath(object): def __init__(self, patch, n): """ creates an callable object that returns True if the provided path is the n-th path from the patch. """ self._patch = patch self._n = n def get_paths(self, renderer): self._patch.set_dpi_cor(renderer.points_to_pixels(1.)) paths, fillables = self._patch.get_path_in_displaycoord() return paths def __call__(self, renderer, gc, tpath, affine, rgbFace): path = self.get_paths(renderer)[self._n] vert1, code1 = path.vertices, path.codes import numpy as np if np.all(vert1 == tpath.vertices) and np.all(code1 == tpath.codes): return True else: return False class ConditionalStroke(pe._Base): def __init__(self, condition_func, pe_list): """ path effect that is only applied when the condition_func returns True. """ super(ConditionalStroke, self).__init__() self._pe_list = pe_list self._condition_func = condition_func def draw_path(self, renderer, gc, tpath, affine, rgbFace): if self._condition_func(renderer, gc, tpath, affine, rgbFace): for pe1 in self._pe_list: pe1.draw_path(renderer, gc, tpath, affine, rgbFace) pe1 = ConditionalStroke(CheckNthSubPath(p, 0),[pe.Stroke()]) pe2 = ConditionalStroke(CheckNthSubPath(p, 1),[pe.Stroke(linestyle="solid")]) p.set_path_effects([pe1, pe2]) subplot.add_patch(p) return p
def text(string, xy, **options): r""" Returns a 2D text graphics object at the point `(x,y)`. Type ``text.options`` for a dictionary of options for 2D text. 2D OPTIONS: - ``fontsize`` - How big the text is - ``rgbcolor`` - The color as an RGB tuple - ``hue`` - The color given as a hue - ``rotation`` - How to rotate the text: angle in degrees, vertical, horizontal - ``vertical_alignment`` - How to align vertically: top, center, bottom - ``horizontal_alignment`` - How to align horizontally: left, center, right - ``axis_coords`` - (default: False) if True, use axis coordinates, so that (0,0) is the lower left and (1,1) upper right, regardless of the x and y range of plotted values. EXAMPLES:: sage: text("Sage is really neat!!",(2,12)) The same text in larger font and colored red:: sage: text("Sage is really neat!!",(2,12),fontsize=20,rgbcolor=(1,0,0)) Same text but guaranteed to be in the lower left no matter what:: sage: text("Sage is really neat!!",(0,0), axis_coords=True, horizontal_alignment='left') Same text rotated around the left, bottom corner of the text:: sage: text("Sage is really neat!!",(0,0), rotation=45.0, horizontal_alignment='left', vertical_alignment='bottom') Same text oriented vertically:: sage: text("Sage is really neat!!",(0,0), rotation="vertical") You can also align text differently:: sage: t1 = text("Hello",(1,1), vertical_alignment="top") sage: t2 = text("World", (1,0.5), horizontal_alignment="left") sage: t1 + t2 # render the sum You can save text as part of PDF output:: sage: text("sage", (0,0), rgbcolor=(0,0,0)).save(SAGE_TMP + 'a.pdf') Text must be 2D (use the text3d command for 3D text):: sage: t = text("hi",(1,2,3)) Traceback (most recent call last): ... ValueError: use text3d instead for text in 3d sage: t = text3d("hi",(1,2,3)) Extra options will get passed on to show(), as long as they are valid:: sage: text("MATH IS AWESOME", (0, 0), fontsize=40, axes=False) sage: text("MATH IS AWESOME", (0, 0), fontsize=40).show(axes=False) # These are equivalent """ try: x, y = xy except ValueError: if isinstance(xy, (list, tuple)) and len(xy) == 3: raise ValueError, "use text3d instead for text in 3d" raise from sage.plot.plot import Graphics options['rgbcolor'] = to_mpl_color(options['rgbcolor']) point = (float(x), float(y)) g = Graphics() g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore='fontsize')) g.add_primitive(Text(string, point, options)) return g