Ticket #12974: trac_12974-refactor.patch

File trac_12974-refactor.patch, 15.4 KB (added by ppurka, 9 years ago)
  • sage/plot/graphics.py

    # HG changeset patch
    # User Punarbasu Purkayastha <ppurka@gmail.com>
    # Date 1337970087 -28800
    # Node ID e8f0843b0561053bb2d22b2f8dfb63a514512cb3
    # Parent  a225ede259f7484a2fdf5fd1378bbe84b0b49b2a
    refactor the tick formatter in Graphics.matplotlib
    
    diff --git a/sage/plot/graphics.py b/sage/plot/graphics.py
    a b  
    15991599            ymin -= 1
    16001600            ymax += 1
    16011601        return {'xmin':xmin, 'xmax':xmax, 'ymin':ymin, 'ymax':ymax}
    1602        
     1602
     1603    def _matplotlib_tick_formatter(self, subplot, locator_options={},
     1604                            tick_formatter=(None, None), ticks=(None, None),
     1605                            xmax=None, xmin=None, ymax=None, ymin=None):
     1606        r"""
     1607        Take a matplotlib subplot instance representing the graphic and set
     1608        the ticks formatting. This function is only for internal use.
     1609
     1610        INPUT:
     1611        - ``subplot`` -- the subplot instance.
     1612
     1613        EXAMPLES::
     1614
     1615            sage: from matplotlib.figure import Figure
     1616            sage: p = plot(x); d = p.get_minmax_data()
     1617            sage: subplot = Figure().add_subplot(111)
     1618            sage: p._objects[0]._render_on_subplot(subplot)
     1619            sage: p._matplotlib_tick_formatter(subplot, **d)
     1620            (<matplotlib.axes.AxesSubplot object at ...>,
     1621            <matplotlib.ticker.MaxNLocator instance at ...>,
     1622            <matplotlib.ticker.MaxNLocator instance at ...>,
     1623            <matplotlib.ticker.OldScalarFormatter instance at ...>,
     1624            <matplotlib.ticker.OldScalarFormatter instance at ...>)
     1625        """
     1626        # This function is created to refactor some code that is repeated
     1627        # in the matplotlib function
     1628        from matplotlib.ticker import (FixedLocator, Locator, MaxNLocator,
     1629                MultipleLocator, NullLocator, OldScalarFormatter)
     1630
     1631        x_locator, y_locator = ticks
     1632        #---------------------- Location of x-ticks ---------------------#
     1633        if x_locator is None:
     1634            x_locator = MaxNLocator(**locator_options)
     1635        elif isinstance(x_locator,Locator):
     1636            pass
     1637        elif x_locator == []:
     1638            x_locator = NullLocator()
     1639        elif isinstance(x_locator,list):
     1640            x_locator = FixedLocator(x_locator)
     1641        else: # x_locator is a number which can be made a float
     1642            from sage.functions.other import ceil, floor
     1643            if floor(xmax/x_locator)-ceil(xmin/x_locator)>1:
     1644                x_locator=MultipleLocator(float(x_locator))
     1645            else: # not enough room for two major ticks
     1646                raise ValueError('Expand the range of the independent '
     1647                'variable to allow two multiples of your tick locator '
     1648                '(option `ticks`).')
     1649
     1650        #---------------------- Location of y-ticks ---------------------#
     1651        if y_locator is None:
     1652            y_locator = MaxNLocator(**locator_options)
     1653        elif isinstance(y_locator,Locator):
     1654            pass
     1655        elif y_locator == []:
     1656            y_locator = NullLocator()
     1657        elif isinstance(y_locator,list):
     1658            y_locator = FixedLocator(y_locator)
     1659        else: # y_locator is a number which can be made a float
     1660            from sage.functions.other import ceil, floor
     1661            if floor(ymax/y_locator)-ceil(ymin/y_locator)>1:
     1662                y_locator=MultipleLocator(float(y_locator))
     1663            else: # not enough room for two major ticks
     1664                raise ValueError('Expand the range of the dependent '
     1665                'variable to allow two multiples of your tick locator '
     1666                '(option `ticks`).')
     1667
     1668        x_formatter, y_formatter = tick_formatter
     1669        from matplotlib.ticker import FuncFormatter
     1670        from sage.misc.latex import latex
     1671        from sage.symbolic.ring import SR
     1672        #---------------------- Formatting x-ticks ----------------------#
     1673        if x_formatter is None:
     1674            x_formatter = OldScalarFormatter()
     1675        elif x_formatter in SR:
     1676            from misc import _multiple_of_constant
     1677            x_const = x_formatter
     1678            x_formatter = FuncFormatter(lambda n,pos:
     1679                                        _multiple_of_constant(n,pos,x_const))
     1680        elif x_formatter == "latex":
     1681            x_formatter = FuncFormatter(lambda n,pos: '$%s$'%latex(n))
     1682        #---------------------- Formatting y-ticks ----------------------#
     1683        if y_formatter is None:
     1684            y_formatter = OldScalarFormatter()
     1685        elif y_formatter in SR:
     1686            from misc import _multiple_of_constant
     1687            y_const = y_formatter
     1688            y_formatter = FuncFormatter(lambda n,pos:
     1689                                        _multiple_of_constant(n,pos,y_const))
     1690        elif y_formatter == "latex":
     1691            y_formatter = FuncFormatter(lambda n,pos: '$%s$'%latex(n))
     1692
     1693        subplot.xaxis.set_major_locator(x_locator)
     1694        subplot.yaxis.set_major_locator(y_locator)
     1695        subplot.xaxis.set_major_formatter(x_formatter)
     1696        subplot.yaxis.set_major_formatter(y_formatter)
     1697
     1698        return (subplot, x_locator, y_locator, x_formatter, y_formatter)
     1699
    16031700    def matplotlib(self, filename=None,
    16041701                   xmin=None, xmax=None, ymin=None, ymax=None,
    16051702                   figsize=None, figure=None, sub=None,
     
    17441841            # sort of what we are used to.  We should eventually look at
    17451842            # the default one to see if we like it better.
    17461843
    1747             from matplotlib.ticker import OldScalarFormatter, MaxNLocator, MultipleLocator, FixedLocator, NullLocator, Locator
    1748             x_locator, y_locator = ticks
    1749             if x_locator is None:
    1750                 x_locator = MaxNLocator(**locator_options)
    1751             elif isinstance(x_locator,Locator):
    1752                 pass
    1753             elif x_locator == []:
    1754                 x_locator = NullLocator()
    1755             elif isinstance(x_locator,list):
    1756                 x_locator = FixedLocator(x_locator)
    1757             else: # x_locator is a number which can be made a float
    1758                 from sage.functions.other import ceil, floor
    1759                 if floor(xmax/x_locator)-ceil(xmin/x_locator)>1:
    1760                     x_locator=MultipleLocator(float(x_locator))
    1761                 else: # not enough room for two major ticks
    1762                     raise ValueError('Expand the range of the independent variable to allow two multiples of your tick locator (option `ticks`).')
    1763             if y_locator is None:
    1764                 y_locator = MaxNLocator(**locator_options)
    1765             elif isinstance(y_locator,Locator):
    1766                 pass
    1767             elif y_locator == []:
    1768                 y_locator = NullLocator()
    1769             elif isinstance(y_locator,list):
    1770                 y_locator = FixedLocator(y_locator)
    1771             else: # y_locator is a number which can be made a float
    1772                 from sage.functions.other import ceil, floor
    1773                 if floor(ymax/y_locator)-ceil(ymin/y_locator)>1:
    1774                     y_locator=MultipleLocator(float(y_locator))
    1775                 else: # not enough room for two major ticks
    1776                     raise ValueError('Expand the range of the dependent variable to allow two multiples of your tick locator (option `ticks`).')
    1777 
    1778             x_formatter, y_formatter = tick_formatter
    1779             from matplotlib.ticker import FuncFormatter
    1780             from sage.misc.latex import latex
    1781             if x_formatter is None:
    1782                 x_formatter = OldScalarFormatter()
    1783             elif x_formatter in SR:
    1784                 from misc import _multiple_of_constant
    1785                 x_const = x_formatter
    1786                 x_formatter = FuncFormatter(lambda n,pos: _multiple_of_constant(n,pos,x_const))
    1787             elif x_formatter == "latex":
    1788                 x_formatter = FuncFormatter(lambda n,pos: '$%s$'%latex(n))
    1789             if y_formatter is None:
    1790                 y_formatter = OldScalarFormatter()
    1791             elif y_formatter in SR:
    1792                 from misc import _multiple_of_constant
    1793                 y_const = y_formatter
    1794                 y_formatter = FuncFormatter(lambda n,pos: _multiple_of_constant(n,pos,y_const))
    1795             elif y_formatter == "latex":
    1796                 y_formatter = FuncFormatter(lambda n,pos: '$%s$'%latex(n))
    1797 
    1798             subplot.xaxis.set_major_locator(x_locator)
    1799             subplot.yaxis.set_major_locator(y_locator)
    1800             subplot.xaxis.set_major_formatter(x_formatter)
    1801             subplot.yaxis.set_major_formatter(y_formatter)
     1844            (subplot, x_locator, y_locator,
     1845                    x_formatter, y_formatter) = self._matplotlib_tick_formatter(
     1846                            subplot, locator_options=locator_options,
     1847                            tick_formatter=tick_formatter, ticks=ticks,
     1848                            xmax=xmax, xmin=xmin, ymax=ymax, ymin=ymin)
    18021849           
    18031850            subplot.set_frame_on(True)
    18041851            if axes:
     
    18551902            # For now, set the formatter to the old one, since that is
    18561903            # sort of what we are used to.  We should eventually look at
    18571904            # the default one to see if we like it better.
     1905
     1906            (subplot, x_locator, y_locator,
     1907                    x_formatter, y_formatter) = self._matplotlib_tick_formatter(
     1908                            subplot, locator_options=locator_options,
     1909                            tick_formatter=tick_formatter, ticks=ticks,
     1910                            xmax=xmax, xmin=xmin, ymax=ymax, ymin=ymin)
    18581911           
    1859             from matplotlib.ticker import OldScalarFormatter, MaxNLocator, MultipleLocator, FixedLocator, NullLocator, Locator
    1860             x_locator, y_locator = ticks
    1861             if x_locator is None:
    1862                 x_locator = MaxNLocator(**locator_options)
    1863             elif isinstance(x_locator,Locator):
    1864                 pass
    1865             elif x_locator == []:
    1866                 x_locator = NullLocator()
    1867             elif isinstance(x_locator,list):
    1868                 x_locator = FixedLocator(x_locator)
    1869             else: # x_locator is a number which can be made a float
    1870                 from sage.functions.other import ceil, floor
    1871                 if floor(xmax/x_locator)-ceil(xmin/x_locator)>1:
    1872                     x_locator=MultipleLocator(float(x_locator))
    1873                 else: # not enough room for two major ticks
    1874                     raise ValueError('Expand the range of the independent variable to allow two multiples of your tick locator (option `ticks`).')
    1875             if y_locator is None:
    1876                 y_locator = MaxNLocator(**locator_options)
    1877             elif isinstance(y_locator,Locator):
    1878                 pass
    1879             elif y_locator == []:
    1880                 y_locator = NullLocator()
    1881             elif isinstance(y_locator,list):
    1882                 y_locator = FixedLocator(y_locator)
    1883             else: # y_locator is a number which can be made a float
    1884                 from sage.functions.other import ceil, floor
    1885                 if floor(ymax/y_locator)-ceil(ymin/y_locator)>1:
    1886                     y_locator=MultipleLocator(float(y_locator))
    1887                 else: # not enough room for two major ticks
    1888                     raise ValueError('Expand the range of the dependent variable to allow two multiples of your tick locator (option `ticks`).')
    1889 
    1890             x_formatter, y_formatter = tick_formatter
    1891             from matplotlib.ticker import FuncFormatter
    1892             from sage.misc.latex import latex
    1893             from sage.symbolic.ring import SR
    1894             if x_formatter is None:
    1895                 x_formatter = OldScalarFormatter()
    1896             elif x_formatter in SR:
    1897                 from misc import _multiple_of_constant
    1898                 x_const = x_formatter
    1899                 x_formatter = FuncFormatter(lambda n,pos: _multiple_of_constant(n,pos,x_const))
    1900             elif x_formatter == "latex":
    1901                 x_formatter = FuncFormatter(lambda n,pos: '$%s$'%latex(n))
    1902             if y_formatter is None:
    1903                 y_formatter = OldScalarFormatter()
    1904             elif y_formatter in SR:
    1905                 from misc import _multiple_of_constant
    1906                 y_const = y_formatter
    1907                 y_formatter = FuncFormatter(lambda n,pos: _multiple_of_constant(n,pos,y_const))
    1908             elif y_formatter == "latex":
    1909                 y_formatter = FuncFormatter(lambda n,pos: '$%s$'%latex(n))
    1910 
    1911             subplot.xaxis.set_major_locator(x_locator)
    1912             subplot.yaxis.set_major_locator(y_locator)
    1913             subplot.xaxis.set_major_formatter(x_formatter)
    1914             subplot.yaxis.set_major_formatter(y_formatter)
    1915 
    19161912            # Make ticklines go on both sides of the axes
    19171913            #             if xmiddle:
    19181914            #                 for t in subplot.xaxis.get_majorticklines():
     
    19341930            # inside the picture
    19351931            if xmiddle and ymiddle:
    19361932                from sage.plot.plot import SelectiveFormatter
    1937                 subplot.yaxis.set_major_formatter(SelectiveFormatter(subplot.yaxis.get_major_formatter(),skip_values=[0]))
    1938                 subplot.xaxis.set_major_formatter(SelectiveFormatter(subplot.xaxis.get_major_formatter(),skip_values=[0]))
     1933                subplot.yaxis.set_major_formatter(SelectiveFormatter(
     1934                    subplot.yaxis.get_major_formatter(),skip_values=[0]))
     1935                subplot.xaxis.set_major_formatter(SelectiveFormatter(
     1936                    subplot.xaxis.get_major_formatter(),skip_values=[0]))
    19391937
    19401938        else:
    19411939            for spine in subplot.spines.values():
     
    20722070                xlabel.set_horizontalalignment(xaxis_horiz)
    20732071                xlabel.set_verticalalignment(xaxis_vert)
    20742072                trans=subplot.spines[xaxis].get_transform()
    2075                 labeltrans=offset_copy(trans, figure, x=xaxis_labeloffset, y=0, units='points')
    2076                 subplot.xaxis.set_label_coords(x=xaxis_labelx,y=xaxis_labely,transform=labeltrans)
     2073                labeltrans=offset_copy(trans, figure, x=xaxis_labeloffset,
     2074                                    y=0, units='points')
     2075                subplot.xaxis.set_label_coords(x=xaxis_labelx,
     2076                                    y=xaxis_labely, transform=labeltrans)
    20772077
    20782078                ylabel=subplot.yaxis.get_label()
    20792079                ylabel.set_horizontalalignment('center')
    20802080                ylabel.set_verticalalignment(yaxis_vert)
    20812081                ylabel.set_rotation('horizontal')
    20822082                trans=subplot.spines[yaxis].get_transform()
    2083                 labeltrans=offset_copy(trans, figure, x=0, y=yaxis_labeloffset, units='points')
    2084                 subplot.yaxis.set_label_coords(x=yaxis_labelx,y=yaxis_labely,transform=labeltrans)
     2083                labeltrans=offset_copy(trans, figure, x=0,
     2084                                    y=yaxis_labeloffset, units='points')
     2085                subplot.yaxis.set_label_coords(x=yaxis_labelx,
     2086                                    y=yaxis_labely, transform=labeltrans)
    20852087
    20862088        # This option makes the xlim and ylim limits not take effect
    20872089        # todo: figure out which limits were specified, and let the
     
    21972199            SageObject.save(self, filename)
    21982200        else:
    21992201            figure = self.matplotlib(**options)
    2200             # You can output in PNG, PS, EPS, PDF, or SVG format, depending on the file extension.
     2202            # You can output in PNG, PS, EPS, PDF, or SVG format, depending
     2203            # on the file extension.
    22012204            # matplotlib looks at the file extension to see what the renderer should be.
    22022205            # The default is FigureCanvasAgg for PNG's because this is by far the most
    22032206            # common type of files rendered, like in the notebook, for example.