From: <jd...@us...> - 2008-05-24 20:49:35
|
Revision: 5253 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5253&view=rev Author: jdh2358 Date: 2008-05-24 13:49:31 -0700 (Sat, 24 May 2008) Log Message: ----------- added new docs dir Added Paths: ----------- trunk/matplotlib/docs/ trunk/matplotlib/docs/_static/ trunk/matplotlib/docs/_templates/ trunk/matplotlib/docs/api/ trunk/matplotlib/docs/api/artist_api.rst trunk/matplotlib/docs/api/index.rst trunk/matplotlib/docs/conf.py trunk/matplotlib/docs/devel/ trunk/matplotlib/docs/devel/add_new_projection.rst trunk/matplotlib/docs/devel/coding_guide.rst trunk/matplotlib/docs/devel/documenting_mpl.rst trunk/matplotlib/docs/devel/index.rst trunk/matplotlib/docs/index.rst trunk/matplotlib/docs/make.py trunk/matplotlib/docs/mpl_data trunk/matplotlib/docs/mpl_examples trunk/matplotlib/docs/sphinxext/ trunk/matplotlib/docs/sphinxext/ipython_console_highlighting.py trunk/matplotlib/docs/sphinxext/mathml.py trunk/matplotlib/docs/sphinxext/mathpng.py trunk/matplotlib/docs/users/ trunk/matplotlib/docs/users/artists.rst trunk/matplotlib/docs/users/customizing.rst trunk/matplotlib/docs/users/event_handling.rst trunk/matplotlib/docs/users/figures/ trunk/matplotlib/docs/users/figures/dollar_ticks.py trunk/matplotlib/docs/users/figures/fig_axes_customize_simple.py trunk/matplotlib/docs/users/figures/fig_axes_labels_simple.py trunk/matplotlib/docs/users/figures/fig_x.py trunk/matplotlib/docs/users/figures/make.py trunk/matplotlib/docs/users/figures/pyplot_formatstr.py trunk/matplotlib/docs/users/figures/pyplot_mathtext.py trunk/matplotlib/docs/users/figures/pyplot_simple.py trunk/matplotlib/docs/users/figures/pyplot_text.py trunk/matplotlib/docs/users/figures/pyplot_three.py trunk/matplotlib/docs/users/figures/pyplot_two_subplots.py trunk/matplotlib/docs/users/index.rst trunk/matplotlib/docs/users/navigation_toolbar.rst trunk/matplotlib/docs/users/pyplot_tutorial.rst Added: trunk/matplotlib/docs/api/artist_api.rst =================================================================== --- trunk/matplotlib/docs/api/artist_api.rst (rev 0) +++ trunk/matplotlib/docs/api/artist_api.rst 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1,31 @@ +****************** +matplotlib artists +****************** + +:mod:`matplotlib.artist` +============================= + +.. automodule:: matplotlib.artist + :members: + :undoc-members: + +:mod:`matplotlib.lines` +============================= + +.. automodule:: matplotlib.lines + :members: + :undoc-members: + +:mod:`matplotlib.patches` +============================= + +.. automodule:: matplotlib.patches + :members: + :undoc-members: + +:mod:`matplotlib.text` +============================= + +.. automodule:: matplotlib.text + :members: + :undoc-members: Added: trunk/matplotlib/docs/api/index.rst =================================================================== --- trunk/matplotlib/docs/api/index.rst (rev 0) +++ trunk/matplotlib/docs/api/index.rst 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1,15 @@ +.. _api-index: + +#################### + The Matplotlib API +#################### + +:Release: |version| +:Date: |today| + +Introduction to developer's guide here **TODO**. + +.. toctree:: + + artist_api.rst + Added: trunk/matplotlib/docs/conf.py =================================================================== --- trunk/matplotlib/docs/conf.py (rev 0) +++ trunk/matplotlib/docs/conf.py 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1,159 @@ +# -*- coding: utf-8 -*- +# +# Matplotlib documentation build configuration file, created by +# sphinx-quickstart on Fri May 2 12:33:25 2008. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# The contents of this file are pickled, so don't put values in the namespace +# that aren't pickleable (module imports are okay, they're removed automatically). +# +# All configuration values have a default value; values that are commented out +# serve to show the default value. + +import sys, os + +# If your extensions are in another directory, add it here. If the directory +# is relative to the documentation root, use os.path.abspath to make it +# absolute, like shown here. +sys.path.append(os.path.abspath('sphinxext')) + +# Import support for ipython console session syntax highlighting (lives +# in the sphinxext directory defined above) +import ipython_console_highlighting + +# General configuration +# --------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['mathpng', 'sphinx.ext.autodoc'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General substitutions. +project = 'Matplotlib' +copyright = '2008, John Hunter, Darren Dale, Michael Droettboom' + +# The default replacements for |version| and |release|, also used in various +# other places throughout the built documents. +# +# The short X.Y version. +version = '0.98' +# The full version, including alpha/beta/rc tags. +release = '0.98pre' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +unused_docs = [] + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# Options for HTML output +# ----------------------- + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +html_style = 'default.css' + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# The name of an image file (within the static path) to place at the top of +# the sidebar. +#html_logo = 'logo.png' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If nonempty, this is the file name suffix for generated HTML files. The +# default is ``".html"``. +#html_file_suffix = '.xhtml' + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If true, the reST sources are included in the HTML build as _sources/<name>. +#html_copy_source = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. +html_use_opensearch = 'False' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Matplotlibdoc' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +latex_font_size = '11pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, document class [howto/manual]). +latex_documents = [ + ('index', 'Matplotlib.tex', 'Matplotlib', 'John Hunter, Darren Dale', 'Michael Droettboom', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +latex_logo = None + +# Additional stuff for the LaTeX preamble. +latex_preamble = '' + +# Documents to append as an appendix to all manuals. +latex_appendices = [] + +# If false, no module index is generated. +latex_use_modindex = True + +latex_use_parts = True Added: trunk/matplotlib/docs/devel/add_new_projection.rst =================================================================== --- trunk/matplotlib/docs/devel/add_new_projection.rst (rev 0) +++ trunk/matplotlib/docs/devel/add_new_projection.rst 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1,105 @@ +*********************************************** +Adding new scales and projections to matplotlib +*********************************************** + +.. ::author Michael Droettboom + +Matplotlib supports the addition of custom procedures that transform +the data before it is displayed. + +There is an important distinction between two kinds of +transformations. Separable transformations, working on a single +dimension, are called "scales", and non-separable transformations, +that handle data in two or more dimensions at a time, are called +"projections". + +From the user's perspective, the scale of a plot can be set with +:meth:`~matplotlib.axes.Axes.set_xscale` and +:meth:`~matplotlib.axes.Axes.set_xscale`. Projections can be chosen +using the ``projection`` keyword argument to the +:func:`~matplotlib.pylab.plot` or :func:`~matplotlib.pylab.subplot` +functions, e.g.:: + + plot(x, y, projection="custom") + +This document is intended for developers and advanced users who need +to create new scales and projections for matplotlib. The necessary +code for scales and projections can be included anywhere: directly +within a plot script, in third-party code, or in the matplotlib source +tree itself. + + +Creating a new scale +==================== + +Adding a new scale consists of defining a subclass of +:class:`matplotlib.scale.ScaleBase`, that includes the following +elements: + + - A transformation from data coordinates into display coordinates. + + - An inverse of that transformation. This is used, for example, to + convert mouse positions from screen space back into data space. + + - A function to limit the range of the axis to acceptable values + (``limit_range_for_scale()``). A log scale, for instance, would + prevent the range from including values less than or equal to + zero. + + - Locators (major and minor) that determine where to place ticks in + the plot, and optionally, how to adjust the limits of the plot to + some "good" values. Unlike ``limit_range_for_scale()``, which is + always enforced, the range setting here is only used when + automatically setting the range of the plot. + + - Formatters (major and minor) that specify how the tick labels + should be drawn. + +Once the class is defined, it must be registered with matplotlib so +that the user can select it. + +A full-fledged and heavily annotated example is in +:file:`examples/api/custom_scale_example.py`. There are also some classes +in :mod:`matplotlib.scale` that may be used as starting points. + + +Creating a new projection +========================= + +Adding a new projection consists of defining a subclass of +:class:`matplotlib.axes.Axes`, that includes the following elements: + + - A transformation from data coordinates into display coordinates. + + - An inverse of that transformation. This is used, for example, to + convert mouse positions from screen space back into data space. + + - Transformations for the gridlines, ticks and ticklabels. Custom + projections will often need to place these elements in special + locations, and matplotlib has a facility to help with doing so. + + - Setting up default values (overriding + :meth:`~matplotlib.axes.Axes.cla`), since the defaults for a + rectilinear axes may not be appropriate. + + - Defining the shape of the axes, for example, an elliptical axes, + that will be used to draw the background of the plot and for + clipping any data elements. + + - Defining custom locators and formatters for the projection. For + example, in a geographic projection, it may be more convenient to + display the grid in degrees, even if the data is in radians. + + - Set up interactive panning and zooming. This is left as an + "advanced" feature left to the reader, but there is an example of + this for polar plots in :mod:`matplotlib.projections.polar`. + + - Any additional methods for additional convenience or features. + +Once the class is defined, it must be registered with matplotlib +so that the user can select it. + +A full-fledged and heavily annotated example is in +:file:`examples/api/custom_projection_example.py`. The polar plot +functionality in :mod:`matplotlib.projections.polar` may also be of +interest. Added: trunk/matplotlib/docs/devel/coding_guide.rst =================================================================== --- trunk/matplotlib/docs/devel/coding_guide.rst (rev 0) +++ trunk/matplotlib/docs/devel/coding_guide.rst 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1,317 @@ +*************** +Version Control +*************** + +svn checkouts +============= + +Checking out everything in the trunk (matplotlib and toolkits):: + + svn co https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/trunk \ + matplotlib --username=youruser --password=yourpass + +Checking out the main source:: + + svn co https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/trunk/\ + matplotlib matplotlib --username=youruser --password=yourpass + +Branch checkouts, eg the maintenance branch:: + + svn co https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/\ + v0_91_maint mplv0_91_maint + +Committing changes +================== + +When committing changes to matplotlib, there are a few things to bear +in mind. + +* if your changes are non-trivial, please make an entry in the + CHANGELOG +* if you change the API, please document it in API_CHANGES, and + consider posting to mpl-devel +* Are your changes python2.3 compatible? We are still trying to + support 2.3, so avoid 2.4 only features like decorators until we + remove 2.3 support +* Can you pass examples/backend_driver.py? This is our poor man's + unit test. +* If you have altered extension code, do you pass + unit/memleak_hawaii.py? +* if you have added new files or directories, or reorganized + existing ones, are the new files included in the match patterns in + MANIFEST.in. This file determines what goes into the src + distribution of the mpl build. +* Keep the maintenance branch and trunk in sync where it makes sense. + If there is a bug on both that needs fixing, use svnmerge.py to + keep them in sync. http://www.orcaware.com/svn/wiki/Svnmerge.py. The + basic procedure is: + + * install svnmerge.py in your PATH:: + + wget http://svn.collab.net/repos/svn/trunk/contrib/client-side/\ + svnmerge/svnmerge.py + + * get a svn copy of the maintenance branch and the trunk (see above) + * Michael advises making the change on the branch and committing + it. Make sure you svn upped on the trunk and have no local + modifications, and then from the svn trunk do:: + + > svnmerge.py merge -rNNN1,NNN2 + + where the NNN* are the revision numbers. Ranges arealso acceptable. + svnmergy.py automatically creates a file containing the commit messages, + so you are ready to make the commit:: + + > svn commit -F svnmerge-commit-message.txt + +*********** +Style Guide +*********** + +Importing and name spaces +========================= + +For numpy, use:: + + import numpy as np + a = np.array([1,2,3]) + +For masked arrays, use:: + + from numpy import ma + +(The earlier recommendation, 'import matplotlib.numerix.npyma as ma', +was needed temporarily during the development of the maskedarray +implementation as a separate package. As of numpy 1.1, it replaces the +old implementation. Note: "from numpy import ma" works with numpy < 1.1 +*and* with numpy >= 1.1. "import numpy.ma as ma" works *only* with +numpy >= 1.1, so for now we must not use it.) + +For matplotlib main module, use:: + + import matplotlib as mpl + mpl.rcParams['xtick.major.pad'] = 6 + +For matplotlib modules (or any other modules), use:: + + import matplotlib.cbook as cbook + + if cbook.iterable(z): + pass + +We prefer this over the equivalent 'from matplotlib import cbook' +because the latter is ambiguous whether cbook is a module or a +function to the new developer. The former makes it explcit that +you are importing a module or package. + +Naming, spacing, and formatting conventions +=========================================== + +In general, we want to hew as closely as possible to the standard +coding guidelines for python written by Guido in +http://www.python.org/dev/peps/pep-0008, though we do not do this +throughout. + +* functions and class methods: lower or lower_underscore_separated + +* attributes and variables: lower or lowerUpper + +* classes: Upper or MixedCase + +Personally, I prefer the shortest names that are still readable. + +Also, use an editor that does not put tabs in files. Four spaces +should be used for indentation everywhere and if there is a file with +tabs or more or less spaces it is a bug -- please fix it. + +Please avoid spurious invisible spaces at the ends of lines. +(Tell your editor to strip whitespace from line ends when saving +a file.) + +Keep docstrings uniformly indented as in the example below, with +nothing to the left of the triple quotes. The dedent() function +is needed to remove excess indentation only if something will be +interpolated into the docstring, again as in the example above. + +Limit line length to 80 characters. If a logical line needs to be +longer, use parentheses to break it; do not use an escaped +newline. It may be preferable to use a temporary variable +to replace a single long line with two shorter and more +readable lines. + +Please do not commit lines with trailing white space, as it causes +noise in svn diffs. If you are an emacs user, the following in your +.emacs will cause emacs to strip trailing white space on save for +python, C and C++:: + + ; and similarly for c++-mode-hook and c-mode-hook + (add-hook 'python-mode-hook + (lambda () + (add-hook 'write-file-functions 'delete-trailing-whitespace))) + +for older versions of emacs (emacs<22) you need to do:: + + (add-hook 'python-mode-hook + (lambda () + (add-hook 'local-write-file-hooks 'delete-trailing-whitespace))) + +Keyword argument processing +=========================== + +Matplotlib makes extensive use of ``**kwargs`` for pass through +customizations from one function to another. A typical example is in +pylab.text, The definition of the pylab text function is a simple +pass-through to axes.Axes.text:: + + # in pylab.py + def text(*args, **kwargs): + ret = gca().text(*args, **kwargs) + draw_if_interactive() + return ret + +axes.Axes.text in simplified form looks like this, ie it just passes +them on to text.Text.__init__:: + + # in axes.py + def text(self, x, y, s, fontdict=None, withdash=False, **kwargs): + t = Text(x=x, y=y, text=s, **kwargs) + +and Text.__init__ (again with liberties for illustration) just passes +them on to the artist.Artist.update method:: + + # in text.py + def __init__(self, x=0, y=0, text='', **kwargs): + Artist.__init__(self) + self.update(kwargs) + +'update' does the work looking for methods named like 'set_property' +if 'property' is a keyword argument. Ie, noone looks at the keywords, +they just get passed through the API to the artist constructor which +looks for suitably named methods and calls them with the value. + +As a general rule, the use of ``**kwargs`` should be reserved for +pass-through keyword arguments, as in the examaple above. If I intend +for all the keyword args to be used in some function and not passed +on, I just use the key/value keyword args in the function definition +rather than the ``**kwargs`` idiom. + +In some cases I want to consume some keys and pass through the others, +in which case I pop the ones I want to use locally and pass on the +rest, eg I pop scalex and scaley in Axes.plot and assume the rest are +Line2D keyword arguments. As an example of a pop, passthrough +usage, see Axes.plot:: + + # in axes.py + def plot(self, *args, **kwargs): + scalex = kwargs.pop('scalex', True) + scaley = kwargs.pop('scaley', True) + if not self._hold: self.cla() + lines = [] + for line in self._get_lines(*args, **kwargs): + self.add_line(line) + lines.append(line) + +The matplotlib.cbook function popd() is rendered +obsolete by the pop() dictionary method introduced in Python 2.3, +so it should not be used for new code. + +Note there is a use case when kwargs are meant to be used locally in +the function (not passed on), but you still need the ``**kwargs`` idiom. +That is when you want to use ``*args`` to allow variable numbers of +non-keyword args. In this case, python will not allow you to use +named keyword args after the ``*args`` usage, so you will be forced to use +``**kwargs``. An example is matplotlib.contour.ContourLabeler.clabel:: + + # in contour.py + def clabel(self, *args, **kwargs): + fontsize = kwargs.get('fontsize', None) + inline = kwargs.get('inline', 1) + self.fmt = kwargs.get('fmt', '%1.3f') + colors = kwargs.get('colors', None) + if len(args) == 0: + levels = self.levels + indices = range(len(self.levels)) + elif len(args) == 1: + ...etc... + +Documentation and Docstrings +============================ + +matplotlib uses artist instrospection of docstrings to support +properties. All properties that you want to support through setp and +getp should have a set_property and get_property method in the Artist +class. Yes, this is not ideal given python properties or enthought +traits, but it is a historical legacy for now. The setter methods use +the docstring with the ACCEPTS token to indicate the type of argument +the method accepts. Eg in matplotlib.lines.Line2D:: + + # in lines.py + def set_linestyle(self, linestyle): + """ + Set the linestyle of the line + + ACCEPTS: [ '-' | '--' | '-.' | ':' | 'steps' | 'None' | ' ' | '' ] + """ + +Since matplotlib uses a lot of pass through kwargs, eg in every +function that creates a line (plot, semilogx, semilogy, etc...), it +can be difficult for the new user to know which kwargs are supported. +I have developed a docstring interpolation scheme to support +documentation of every function that takes a ``**kwargs``. The +requirements are: + +1. single point of configuration so changes to the properties don't + require multiple docstring edits + +2. as automated as possible so that as properties change the docs + are updated automagically. + +I have added a matplotlib.artist.kwdocd and kwdoc() to faciliate this. +They combines python string interpolation in the docstring with the +matplotlib artist introspection facility that underlies setp and getp. +The kwdocd is a single dictionary that maps class name to a docstring +of kwargs. Here is an example from matplotlib.lines:: + + # in lines.py + artist.kwdocd['Line2D'] = artist.kwdoc(Line2D) + +Then in any function accepting Line2D passthrough kwargs, eg +matplotlib.axes.Axes.plot:: + + # in axes.py + def plot(self, *args, **kwargs): + """ + Some stuff omitted + + The kwargs are Line2D properties: + %(Line2D)s + + kwargs scalex and scaley, if defined, are passed on + to autoscale_view to determine whether the x and y axes are + autoscaled; default True. See Axes.autoscale_view for more + information + """ + pass + plot.__doc__ = cbook.dedent(plot.__doc__) % artist.kwdocd + +Note there is a problem for Artist __init__ methods, eg Patch.__init__ +which supports Patch kwargs, since the artist inspector cannot work +until the class is fully defined and we can't modify the +Patch.__init__.__doc__ docstring outside the class definition. I have +made some manual hacks in this case which violates the "single entry +point" requirement above; hopefully we'll find a more elegant solution +before too long + +******** +Licenses +******** + +Matplotlib only uses BSD compatible code. If you bring in code from +another project make sure it has a PSF, BSD, MIT or compatible +license. If not, you may consider contacting the author and asking +them to relicense it. GPL and LGPL code are not acceptible in the +main code base, though we are considering an alternative way of +distributing L/GPL code through an separate channel, possibly a +toolkit. If you include code, make sure you include a copy of that +code's license in the license directory if the code's license requires +you to distribute the license with it. \ No newline at end of file Added: trunk/matplotlib/docs/devel/documenting_mpl.rst =================================================================== --- trunk/matplotlib/docs/devel/documenting_mpl.rst (rev 0) +++ trunk/matplotlib/docs/devel/documenting_mpl.rst 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1,76 @@ +********************** +Documenting Matplotlib +********************** + +The documentation for matplotlib is generated from ReStructured Text +using the Sphinx_ documentation generation tool. Sphinx-0.4 or later +is required. Currently this means we need to install from the svn +repository by doing:: + + svn co http://svn.python.org/projects/doctools/trunk sphinx + cd sphinx + python setup.py install + +.. _Sphinx: http://sphinx.pocoo.org/ + +The documentation sources are found in the doc/ directory in the trunk. +To build the users guid in html format, cd into doc/users_guide and do:: + + python make.py html + +you can also pass a ``latex`` flag to make.py to build a pdf, or pass no +arguments to build everything. The same procedure can be followed for +the sources in doc/api_reference. + +The actual ReStructured Text files are kept in doc/users_guide/source +and doc/api_reference/source. The main entry point is index.rst. +Additional files can be added by including their base file name +(dropping the .rst extension) in the table of contents. It is also +possible to include other documents through the use of an include +statement. For example, in the Developers Guide, index.rst lists +coding_guide, which automatically inserts coding_guide.rst. + +Mathematical expressions can be rendered as png images in html, and in +the usual way by latex. For example: + +``math:`sin(x_n^2)`` yields: :math:`sin(x_n^2)`, and:: + + .. math:: + + \int_{-\infty}^{\infty}\frac{e^{i\phi}}{1+x^2\frac{e^{i\phi}}{1+x^2}}`` + +yields: + +.. math:: + + \int_{-\infty}^{\infty}\frac{e^{i\phi}}{1+x^2\frac{e^{i\phi}}{1+x^2}} + +The output produced by Sphinx can be configured by editing the conf.py +files located in the documentation source directories. + +The Sphinx website contains plenty of documentation_ concerning ReST +markup and working with Sphinx in general. + +.. _documentation: http://sphinx.pocoo.org/contents.html + +Referring to mpl documents +========================== + +In the documentation, you may want to include to a document in the +matplotlib src, eg a license file, an image file from ``mpl-data``, or an +example. When you include these files, include them using a symbolic +link from the documentation parent directory. This way, if we +relocate the mpl documentation directory, all of the internal pointers +to files will not have to change, just the top level symlinks. For +example, In the top level doc directory we have symlinks pointing to +the mpl ``examples`` and ``mpl-data``:: + + home:~/mpl/doc2> ls -l mpl_* + mpl_data -> ../lib/matplotlib/mpl-data + mpl_examples -> ../examples + + +In the ``users`` subdirectory, if I want to refer to a file in the mpl-data directory, I use the symlink direcotry. For example, from ``customizing.rst``:: + + .. literalinclude:: ../mpl_data/matplotlibrc + Added: trunk/matplotlib/docs/devel/index.rst =================================================================== --- trunk/matplotlib/docs/devel/index.rst (rev 0) +++ trunk/matplotlib/docs/devel/index.rst 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1,16 @@ +.. _developers_guide-index: + +################################### + The Matplotlib Developers's Guide +################################### + +:Release: |version| +:Date: |today| + +Introduction to developer's guide here **TODO**. + +.. toctree:: + + coding_guide.rst + documenting_mpl.rst + add_new_projection.rst Added: trunk/matplotlib/docs/index.rst =================================================================== --- trunk/matplotlib/docs/index.rst (rev 0) +++ trunk/matplotlib/docs/index.rst 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1,23 @@ +.. matplotlib documentation master file, created by sphinx-quickstart on Sat May 24 15:37:00 2008. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to matplotlib's documentation! +====================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + users/index.rst + devel/index.rst + api/index.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + Added: trunk/matplotlib/docs/make.py =================================================================== --- trunk/matplotlib/docs/make.py (rev 0) +++ trunk/matplotlib/docs/make.py 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1,68 @@ +#!/usr/bin/env python +import fileinput +import glob +import os +import shutil +import sys + +def check_build(): + build_dirs = ['build', 'build/doctrees', 'build/html', 'build/latex', + '_static', '_templates'] + for d in build_dirs: + try: + os.mkdir(d) + except OSError: + pass + +def figs(): + os.system('cd users/figures/ && python make.py') + +def html(): + check_build() + os.system('sphinx-build -b html -d build/doctrees . build/html') + +def latex(): + if sys.platform != 'win32': + # LaTeX format. + os.system('sphinx-build -b latex -d build/doctrees . build/latex') + + # Produce pdf. + os.chdir('build/latex') + + # Copying the makefile produced by sphinx... + os.system('pdflatex Matplotlib_Users_Guide.tex') + os.system('pdflatex Matplotlib_Users_Guide.tex') + os.system('makeindex -s python.ist Matplotlib_Users_Guide.idx') + os.system('makeindex -s python.ist modMatplotlib_Users_Guide.idx') + os.system('pdflatex Matplotlib_Users_Guide.tex') + + os.chdir('../..') + else: + print 'latex build has not been tested on windows' + +def clean(): + shutil.rmtree('build') + +def all(): + figs() + html() + latex() + + +funcd = {'figs':figs, + 'html':html, + 'latex':latex, + 'clean':clean, + 'all':all, + } + + +if len(sys.argv)>1: + for arg in sys.argv[1:]: + func = funcd.get(arg) + if func is None: + raise SystemExit('Do not know how to handle %s; valid args are'%( + arg, funcd.keys())) + func() +else: + all() Property changes on: trunk/matplotlib/docs/make.py ___________________________________________________________________ Name: svn:executable + * Added: trunk/matplotlib/docs/mpl_data =================================================================== --- trunk/matplotlib/docs/mpl_data (rev 0) +++ trunk/matplotlib/docs/mpl_data 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1 @@ +link ../lib/matplotlib/mpl-data/ \ No newline at end of file Property changes on: trunk/matplotlib/docs/mpl_data ___________________________________________________________________ Name: svn:special + * Added: trunk/matplotlib/docs/mpl_examples =================================================================== --- trunk/matplotlib/docs/mpl_examples (rev 0) +++ trunk/matplotlib/docs/mpl_examples 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1 @@ +link ../examples/ \ No newline at end of file Property changes on: trunk/matplotlib/docs/mpl_examples ___________________________________________________________________ Name: svn:special + * Added: trunk/matplotlib/docs/sphinxext/ipython_console_highlighting.py =================================================================== --- trunk/matplotlib/docs/sphinxext/ipython_console_highlighting.py (rev 0) +++ trunk/matplotlib/docs/sphinxext/ipython_console_highlighting.py 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1,75 @@ +from pygments.lexer import Lexer, do_insertions +from pygments.lexers.agile import PythonConsoleLexer, PythonLexer, \ + PythonTracebackLexer +from pygments.token import Comment, Generic +from sphinx import highlighting +import re + +line_re = re.compile('.*?\n') + +class IPythonConsoleLexer(Lexer): + """ + For IPython console output or doctests, such as: + + Tracebacks are not currently supported. + + .. sourcecode:: pycon + + In [1]: a = 'foo' + + In [2]: a + Out[2]: 'foo' + + In [3]: print a + foo + + In [4]: 1 / 0 + """ + name = 'IPython console session' + aliases = ['ipython'] + mimetypes = ['text/x-ipython-console'] + input_prompt = re.compile("(In \[[0-9]+\]: )|( \.\.\.+:)") + output_prompt = re.compile("(Out\[[0-9]+\]: )|( \.\.\.+:)") + continue_prompt = re.compile(" \.\.\.+:") + tb_start = re.compile("\-+") + + def get_tokens_unprocessed(self, text): + pylexer = PythonLexer(**self.options) + tblexer = PythonTracebackLexer(**self.options) + + curcode = '' + insertions = [] + for match in line_re.finditer(text): + line = match.group() + input_prompt = self.input_prompt.match(line) + continue_prompt = self.continue_prompt.match(line.rstrip()) + output_prompt = self.output_prompt.match(line) + if line.startswith("#"): + insertions.append((len(curcode), + [(0, Comment, line)])) + elif input_prompt is not None: + insertions.append((len(curcode), + [(0, Generic.Prompt, input_prompt.group())])) + curcode += line[input_prompt.end():] + elif continue_prompt is not None: + insertions.append((len(curcode), + [(0, Generic.Prompt, continue_prompt.group())])) + curcode += line[continue_prompt.end():] + elif output_prompt is not None: + insertions.append((len(curcode), + [(0, Generic.Output, output_prompt.group())])) + curcode += line[output_prompt.end():] + else: + if curcode: + for item in do_insertions(insertions, + pylexer.get_tokens_unprocessed(curcode)): + yield item + curcode = '' + insertions = [] + yield match.start(), Generic.Output, line + if curcode: + for item in do_insertions(insertions, + pylexer.get_tokens_unprocessed(curcode)): + yield item + +highlighting.lexers['ipython'] = IPythonConsoleLexer() Added: trunk/matplotlib/docs/sphinxext/mathml.py =================================================================== --- trunk/matplotlib/docs/sphinxext/mathml.py (rev 0) +++ trunk/matplotlib/docs/sphinxext/mathml.py 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1,552 @@ +from docutils import nodes +from docutils.writers.html4css1 import HTMLTranslator +from sphinx.latexwriter import LaTeXTranslator + +# Define LaTeX math node: +class latex_math(nodes.General, nodes.Element): + pass + +def math_role(role, rawtext, text, lineno, inliner, + options={}, content=[]): + i = rawtext.find('`') + latex = rawtext[i+1:-1] + try: + mathml_tree = parse_latex_math(latex, inline=True) + except SyntaxError, msg: + msg = inliner.reporter.error(msg, line=lineno) + prb = inliner.problematic(rawtext, rawtext, msg) + return [prb], [msg] + node = latex_math(rawtext) + node['latex'] = latex + node['mathml_tree'] = mathml_tree + return [node], [] + + +try: + from docutils.parsers.rst import Directive +except ImportError: + # Register directive the old way: + from docutils.parsers.rst.directives import _directives + def math_directive(name, arguments, options, content, lineno, + content_offset, block_text, state, state_machine): + latex = ''.join(content) + try: + mathml_tree = parse_latex_math(latex, inline=False) + except SyntaxError, msg: + error = state_machine.reporter.error( + msg, nodes.literal_block(block_text, block_text), line=lineno) + return [error] + node = latex_math(block_text) + node['latex'] = latex + node['mathml_tree'] = mathml_tree + return [node] + math_directive.arguments = None + math_directive.options = {} + math_directive.content = 1 + _directives['math'] = math_directive +else: + class math_directive(Directive): + has_content = True + def run(self): + latex = ' '.join(self.content) + try: + mathml_tree = parse_latex_math(latex, inline=False) + except SyntaxError, msg: + error = self.state_machine.reporter.error( + msg, nodes.literal_block(self.block_text, self.block_text), + line=self.lineno) + return [error] + node = latex_math(self.block_text) + node['latex'] = latex + node['mathml_tree'] = mathml_tree + return [node] + from docutils.parsers.rst import directives + directives.register_directive('math', math_directive) + +def setup(app): + app.add_node(latex_math) + app.add_role('math', math_role) + + # Add visit/depart methods to HTML-Translator: + def visit_latex_math_html(self, node): + mathml = ''.join(node['mathml_tree'].xml()) + self.body.append(mathml) + def depart_latex_math_html(self, node): + pass + HTMLTranslator.visit_latex_math = visit_latex_math_html + HTMLTranslator.depart_latex_math = depart_latex_math_html + + # Add visit/depart methods to LaTeX-Translator: + def visit_latex_math_latex(self, node): + inline = isinstance(node.parent, nodes.TextElement) + if inline: + self.body.append('$%s$' % node['latex']) + else: + self.body.extend(['\\begin{equation}', + node['latex'], + '\\end{equation}']) + def depart_latex_math_latex(self, node): + pass + LaTeXTranslator.visit_latex_math = visit_latex_math_latex + LaTeXTranslator.depart_latex_math = depart_latex_math_latex + + +# LaTeX to MathML translation stuff: +class math: + """Base class for MathML elements.""" + + nchildren = 1000000 + """Required number of children""" + + def __init__(self, children=None, inline=None): + """math([children]) -> MathML element + + children can be one child or a list of children.""" + + self.children = [] + if children is not None: + if type(children) is list: + for child in children: + self.append(child) + else: + # Only one child: + self.append(children) + + if inline is not None: + self.inline = inline + + def __repr__(self): + if hasattr(self, 'children'): + return self.__class__.__name__ + '(%s)' % \ + ','.join([repr(child) for child in self.children]) + else: + return self.__class__.__name__ + + def full(self): + """Room for more children?""" + + return len(self.children) >= self.nchildren + + def append(self, child): + """append(child) -> element + + Appends child and returns self if self is not full or first + non-full parent.""" + + assert not self.full() + self.children.append(child) + child.parent = self + node = self + while node.full(): + node = node.parent + return node + + def delete_child(self): + """delete_child() -> child + + Delete last child and return it.""" + + child = self.children[-1] + del self.children[-1] + return child + + def close(self): + """close() -> parent + + Close element and return first non-full element.""" + + parent = self.parent + while parent.full(): + parent = parent.parent + return parent + + def xml(self): + """xml() -> xml-string""" + + return self.xml_start() + self.xml_body() + self.xml_end() + + def xml_start(self): + if not hasattr(self, 'inline'): + return ['<%s>' % self.__class__.__name__] + xmlns = 'http://www.w3.org/1998/Math/MathML' + if self.inline: + return ['<math xmlns="%s">' % xmlns] + else: + return ['<math xmlns="%s" mode="display">' % xmlns] + + def xml_end(self): + return ['</%s>' % self.__class__.__name__] + + def xml_body(self): + xml = [] + for child in self.children: + xml.extend(child.xml()) + return xml + +class mrow(math): pass +class mtable(math): pass +class mtr(mrow): pass +class mtd(mrow): pass + +class mx(math): + """Base class for mo, mi, and mn""" + + nchildren = 0 + def __init__(self, data): + self.data = data + + def xml_body(self): + return [self.data] + +class mo(mx): + translation = {'<': '<', '>': '>'} + def xml_body(self): + return [self.translation.get(self.data, self.data)] + +class mi(mx): pass +class mn(mx): pass + +class msub(math): + nchildren = 2 + +class msup(math): + nchildren = 2 + +class msqrt(math): + nchildren = 1 + +class mroot(math): + nchildren = 2 + +class mfrac(math): + nchildren = 2 + +class msubsup(math): + nchildren = 3 + def __init__(self, children=None, reversed=False): + self.reversed = reversed + math.__init__(self, children) + + def xml(self): + if self.reversed: +## self.children[1:3] = self.children[2:0:-1] + self.children[1:3] = [self.children[2], self.children[1]] + self.reversed = False + return math.xml(self) + +class mfenced(math): + translation = {'\\{': '{', '\\langle': u'\u2329', + '\\}': '}', '\\rangle': u'\u232A', + '.': ''} + def __init__(self, par): + self.openpar = par + math.__init__(self) + + def xml_start(self): + open = self.translation.get(self.openpar, self.openpar) + close = self.translation.get(self.closepar, self.closepar) + return ['<mfenced open="%s" close="%s">' % (open, close)] + +class mspace(math): + nchildren = 0 + +class mstyle(math): + def __init__(self, children=None, nchildren=None, **kwargs): + if nchildren is not None: + self.nchildren = nchildren + math.__init__(self, children) + self.attrs = kwargs + + def xml_start(self): + return ['<mstyle '] + ['%s="%s"' % item + for item in self.attrs.items()] + ['>'] + +class mover(math): + nchildren = 2 + def __init__(self, children=None, reversed=False): + self.reversed = reversed + math.__init__(self, children) + + def xml(self): + if self.reversed: + self.children.reverse() + self.reversed = False + return math.xml(self) + +class munder(math): + nchildren = 2 + +class munderover(math): + nchildren = 3 + def __init__(self, children=None): + math.__init__(self, children) + +class mtext(math): + nchildren = 0 + def __init__(self, text): + self.text = text + + def xml_body(self): + return [self.text] + + +over = {'tilde': '~', + 'hat': '^', + 'bar': '_', + 'vec': u'\u2192'} + +Greek = { + # Upper case greek letters: + 'Phi': u'\u03a6', 'Xi': u'\u039e', 'Sigma': u'\u03a3', 'Psi': u'\u03a8', 'Delta': u'\u0394', 'Theta': u'\u0398', 'Upsilon': u'\u03d2', 'Pi': u'\u03a0', 'Omega': u'\u03a9', 'Gamma': u'\u0393', 'Lambda': u'\u039b'} +greek = { + # Lower case greek letters: + 'tau': u'\u03c4', 'phi': u'\u03d5', 'xi': u'\u03be', 'iota': u'\u03b9', 'epsilon': u'\u03f5', 'varrho': u'\u03f1', 'varsigma': u'\u03c2', 'beta': u'\u03b2', 'psi': u'\u03c8', 'rho': u'\u03c1', 'delta': u'\u03b4', 'alpha': u'\u03b1', 'zeta': u'\u03b6', 'omega': u'\u03c9', 'varepsilon': u'\u03b5', 'kappa': u'\u03ba', 'vartheta': u'\u03d1', 'chi': u'\u03c7', 'upsilon': u'\u03c5', 'sigma': u'\u03c3', 'varphi': u'\u03c6', 'varpi': u'\u03d6', 'mu': u'\u03bc', 'eta': u'\u03b7', 'theta': u'\u03b8', 'pi': u'\u03c0', 'varkappa': u'\u03f0', 'nu': u'\u03bd', 'gamma': u'\u03b3', 'lambda': u'\u03bb'} + +special = { + # Binary operation symbols: + 'wedge': u'\u2227', 'diamond': u'\u22c4', 'star': u'\u22c6', 'amalg': u'\u2a3f', 'ast': u'\u2217', 'odot': u'\u2299', 'triangleleft': u'\u25c1', 'bigtriangleup': u'\u25b3', 'ominus': u'\u2296', 'ddagger': u'\u2021', 'wr': u'\u2240', 'otimes': u'\u2297', 'sqcup': u'\u2294', 'oplus': u'\u2295', 'bigcirc': u'\u25cb', 'oslash': u'\u2298', 'sqcap': u'\u2293', 'bullet': u'\u2219', 'cup': u'\u222a', 'cdot': u'\u22c5', 'cap': u'\u2229', 'bigtriangledown': u'\u25bd', 'times': u'\xd7', 'setminus': u'\u2216', 'circ': u'\u2218', 'vee': u'\u2228', 'uplus': u'\u228e', 'mp': u'\u2213', 'dagger': u'\u2020', 'triangleright': u'\u25b7', 'div': u'\xf7', 'pm': u'\xb1', + # Relation symbols: + 'subset': u'\u2282', 'propto': u'\u221d', 'geq': u'\u2265', 'ge': u'\u2265', 'sqsubset': u'\u228f', 'Join': u'\u2a1d', 'frown': u'\u2322', 'models': u'\u22a7', 'supset': u'\u2283', 'in': u'\u2208', 'doteq': u'\u2250', 'dashv': u'\u22a3', 'gg': u'\u226b', 'leq': u'\u2264', 'succ': u'\u227b', 'vdash': u'\u22a2', 'cong': u'\u2245', 'simeq': u'\u2243', 'subseteq': u'\u2286', 'parallel': u'\u2225', 'equiv': u'\u2261', 'ni': u'\u220b', 'le': u'\u2264', 'approx': u'\u2248', 'precsim': u'\u227e', 'sqsupset': u'\u2290', 'll': u'\u226a', 'sqsupseteq': u'\u2292', 'mid': u'\u2223', 'prec': u'\u227a', 'succsim': u'\u227f', 'bowtie': u'\u22c8', 'perp': u'\u27c2', 'sqsubseteq': u'\u2291', 'asymp': u'\u224d', 'smile': u'\u2323', 'supseteq': u'\u2287', 'sim': u'\u223c', 'neq': u'\u2260', + # Arrow symbols: + 'searrow': u'\u2198', 'updownarrow': u'\u2195', 'Uparrow': u'\u21d1', 'longleftrightarrow': u'\u27f7', 'Leftarrow': u'\u21d0', 'longmapsto': u'\u27fc', 'Longleftarrow': u'\u27f8', 'nearrow': u'\u2197', 'hookleftarrow': u'\u21a9', 'downarrow': u'\u2193', 'Leftrightarrow': u'\u21d4', 'longrightarrow': u'\u27f6', 'rightharpoondown': u'\u21c1', 'longleftarrow': u'\u27f5', 'rightarrow': u'\u2192', 'Updownarrow': u'\u21d5', 'rightharpoonup': u'\u21c0', 'Longleftrightarrow': u'\u27fa', 'leftarrow': u'\u2190', 'mapsto': u'\u21a6', 'nwarrow': u'\u2196', 'uparrow': u'\u2191', 'leftharpoonup': u'\u21bc', 'leftharpoondown': u'\u21bd', 'Downarrow': u'\u21d3', 'leftrightarrow': u'\u2194', 'Longrightarrow': u'\u27f9', 'swarrow': u'\u2199', 'hookrightarrow': u'\u21aa', 'Rightarrow': u'\u21d2', + # Miscellaneous symbols: + 'infty': u'\u221e', 'surd': u'\u221a', 'partial': u'\u2202', 'ddots': u'\u22f1', 'exists': u'\u2203', 'flat': u'\u266d', 'diamondsuit': u'\u2662', 'wp': u'\u2118', 'spadesuit': u'\u2660', 'Re': u'\u211c', 'vdots': u'\u22ee', 'aleph': u'\u2135', 'clubsuit': u'\u2663', 'sharp': u'\u266f', 'angle': u'\u2220', 'prime': u'\u2032', 'natural': u'\u266e', 'ell': u'\u2113', 'neg': u'\xac', 'top': u'\u22a4', 'nabla': u'\u2207', 'bot': u'\u22a5', 'heartsuit': u'\u2661', 'cdots': u'\u22ef', 'Im': u'\u2111', 'forall': u'\u2200', 'imath': u'\u0131', 'hbar': u'\u210f', 'emptyset': u'\u2205', + # Variable-sized symbols: + 'bigotimes': u'\u2a02', 'coprod': u'\u2210', 'int': u'\u222b', 'sum': u'\u2211', 'bigodot': u'\u2a00', 'bigcup': u'\u22c3', 'biguplus': u'\u2a04', 'bigcap': u'\u22c2', 'bigoplus': u'\u2a01', 'oint': u'\u222e', 'bigvee': u'\u22c1', 'bigwedge': u'\u22c0', 'prod': u'\u220f', + # Braces: + 'langle': u'\u2329', 'rangle': u'\u232A'} + +sumintprod = ''.join([special[symbol] for symbol in + ['sum', 'int', 'oint', 'prod']]) + +functions = ['arccos', 'arcsin', 'arctan', 'arg', 'cos', 'cosh', + 'cot', 'coth', 'csc', 'deg', 'det', 'dim', + 'exp', 'gcd', 'hom', 'inf', 'ker', 'lg', + 'lim', 'liminf', 'limsup', 'ln', 'log', 'max', + 'min', 'Pr', 'sec', 'sin', 'sinh', 'sup', + 'tan', 'tanh', + 'injlim', 'varinjlim', 'varlimsup', + 'projlim', 'varliminf', 'varprojlim'] + + +def parse_latex_math(string, inline=True): + """parse_latex_math(string [,inline]) -> MathML-tree + + Returns a MathML-tree parsed from string. inline=True is for + inline math and inline=False is for displayed math. + + tree is the whole tree and node is the current element.""" + + # Normalize white-space: + string = ' '.join(string.split()) + + if inline: + node = mrow() + tree = math(node, inline=True) + else: + node = mtd() + tree = math(mtable(mtr(node)), inline=False) + + while len(string) > 0: + n = len(string) + c = string[0] + skip = 1 # number of characters consumed + if n > 1: + c2 = string[1] + else: + c2 = '' +## print n, string, c, c2, node.__class__.__name__ + if c == ' ': + pass + elif c == '\\': + if c2 in '{}': + node = node.append(mo(c2)) + skip = 2 + elif c2 == ' ': + node = node.append(mspace()) + skip = 2 + elif c2.isalpha(): + # We have a LaTeX-name: + i = 2 + while i < n and string[i].isalpha(): + i += 1 + name = string[1:i] + node, skip = handle_keyword(name, node, string[i:]) + skip += i + elif c2 == '\\': + # End of a row: + entry = mtd() + row = mtr(entry) + node.close().close().append(row) + node = entry + skip = 2 + else: + raise SyntaxError('Syntax error: "%s%s"' % (c, c2)) + elif c.isalpha(): + node = node.append(mi(c)) + elif c.isdigit(): + node = node.append(mn(c)) + elif c in "+-/()[]|=<>,.!'": + node = node.append(mo(c)) + elif c == '_': + child = node.delete_child() + if isinstance(child, msup): + sub = msubsup(child.children, reversed=True) + elif isinstance(child, mo) and child.data in sumintprod: + sub = munder(child) + else: + sub = msub(child) + node.append(sub) + node = sub + elif c == '^': + child = node.delete_child() + if isinstance(child, msub): + sup = msubsup(child.children) + elif isinstance(child, mo) and child.data in sumintprod: + sup = mover(child) + elif (isinstance(child, munder) and + child.children[0].data in sumintprod): + sup = munderover(child.children) + else: + sup = msup(child) + node.append(sup) + node = sup + elif c == '{': + row = mrow() + node.append(row) + node = row + elif c == '}': + node = node.close() + elif c == '&': + entry = mtd() + node.close().append(entry) + node = entry + else: + raise SyntaxError('Illegal character: "%s"' % c) + string = string[skip:] + return tree + + +mathbb = {'A': u'\U0001D538', + 'B': u'\U0001D539', + 'C': u'\u2102', + 'D': u'\U0001D53B', + 'E': u'\U0001D53C', + 'F': u'\U0001D53D', + 'G': u'\U0001D53E', + 'H': u'\u210D', + 'I': u'\U0001D540', + 'J': u'\U0001D541', + 'K': u'\U0001D542', + 'L': u'\U0001D543', + 'M': u'\U0001D544', + 'N': u'\u2115', + 'O': u'\U0001D546', + 'P': u'\u2119', + 'Q': u'\u211A', + 'R': u'\u211D', + 'S': u'\U0001D54A', + 'T': u'\U0001D54B', + 'U': u'\U0001D54C', + 'V': u'\U0001D54D', + 'W': u'\U0001D54E', + 'X': u'\U0001D54F', + 'Y': u'\U0001D550', + 'Z': u'\u2124'} + +negatables = {'=': u'\u2260', + '\in': u'\u2209', + '\equiv': u'\u2262'} + + +def handle_keyword(name, node, string): + skip = 0 + if len(string) > 0 and string[0] == ' ': + string = string[1:] + skip = 1 + if name == 'begin': + if not string.startswith('{matrix}'): + raise SyntaxError('Expected "\begin{matrix}"!') + skip += 8 + entry = mtd() + table = mtable(mtr(entry)) + node.append(table) + node = entry + elif name == 'end': + if not string.startswith('{matrix}'): + raise SyntaxError('Expected "\end{matrix}"!') + skip += 8 + node = node.close().close().close() + elif name == 'text': + if string[0] != '{': + raise SyntaxError('Expected "\text{...}"!') + i = string.find('}') + if i == -1: + raise SyntaxError('Expected "\text{...}"!') + node = node.append(mtext(string[1:i])) + skip += i + 1 + elif name == 'sqrt': + sqrt = msqrt() + node.append(sqrt) + node = sqrt + elif name == 'frac': + frac = mfrac() + node.append(frac) + node = frac + elif name == 'left': + for par in ['(', '[', '|', '\\{', '\\langle', '.']: + if string.startswith(par): + break + else: + raise SyntaxError('Missing left-brace!') + fenced = mfenced(par) + node.append(fenced) + row = mrow() + fenced.append(row) + node = row + skip += len(par) + elif name == 'right': + for par in [')', ']', '|', '\\}', '\\rangle', '.']: + if string.startswith(par): + break + else: + raise SyntaxError('Missing right-brace!') + node = node.close() + node.closepar = par + node = node.close() + skip += len(par) + elif name == 'not': + for operator in negatables: + if string.startswith(operator): + break + else: + raise SyntaxError('Expected something to negate: "\\not ..."!') + node = node.append(mo(negatables[operator])) + skip += len(operator) + elif name == 'mathbf': + style = mstyle(nchildren=1, fontweight='bold') + node.append(style) + node = style + elif name == 'mathbb': + if string[0] != '{' or not string[1].isupper() or string[2] != '}': + raise SyntaxError('Expected something like "\mathbb{A}"!') + node = node.append(mi(mathbb[string[1]])) + skip += 3 + elif name in greek: + node = node.append(mi(greek[name])) + elif name in Greek: + node = node.append(mo(Greek[name])) + elif name in special: + node = node.append(mo(special[name])) + elif name in functions: + node = node.append(mo(name)) + else: + chr = over.get(name) + if chr is not None: + ovr = mover(mo(chr), reversed=True) + node.append(ovr) + node = ovr + else: + raise SyntaxError('Unknown LaTeX command: ' + name) + + return node, skip Added: trunk/matplotlib/docs/sphinxext/mathpng.py =================================================================== --- trunk/matplotlib/docs/sphinxext/mathpng.py (rev 0) +++ trunk/matplotlib/docs/sphinxext/mathpng.py 2008-05-24 20:49:31 UTC (rev 5253) @@ -0,0 +1,111 @@ +import os +try: + from hashlib import md5 +except ImportError: + from md5 import md5 + +from docutils import nodes +from docutils.writers.html4css1 import HTMLTranslator +from sphinx.latexwriter import LaTeXTranslator + +# Define LaTeX math node: +class latex_math(nodes.General, nodes.Element): + pass + +def math_role(role, rawtext, text, lineno, inliner, + options={}, content=[]): + i = rawtext.find('`') + latex = rawtext[i+1:-1] + node = latex_math(rawtext) + node['latex'] = latex + return [node], [] + + +try: + from docutils.parsers.rst import Directive +except ImportError: + # Register directive the old way: + from docutils.parsers.rst.directives import _directives + def math_directive(name, arguments, options, content, lineno, + content_offset, block_text, state, state_machine): + latex = ''.join(content) + node = latex_math(block_text) + node['latex'] = latex + return [node] + math_directive.arguments = None + math_directive.options = {} + math_directive.content = 1 + _directives['math'] = math_directive +else: + class math_directive(Directive): + has_content = True + def run(self): + latex = ' '.join(self.content) + node = latex_math(self.block_text) + node['latex'] = latex + return [node] + from docutils.parsers.rst import directives + directives.register_directive('math', math_directive) + +def setup(app): + app.add_node(latex_math) + app.add_role('math', math_role) + + # Add visit/depart methods to HTML-Translator: + def visit_latex_math_html(self, node): + source = self.document.attributes['source'] + self.body.append(latex2html(node, source)) + def depart_latex_math_html(self, node): + pass + HTMLTranslator.visit_latex_math = visit_latex_math_html + HTMLTranslator.depart_latex_math = depart_latex_math_html + + # Add visit/depart methods to LaTeX-Translator: + def visit_latex_math_latex(self, node): + inline = isinstance(node.parent, nodes.TextElement) + if inline: + self.body.append('$%s$' % node['latex']) + else: + self.body.extend(['\\begin{equation}', + node['latex'], + '\\end{equation}']) + def depart_latex_math_latex(self, node): + pass + LaTeXTranslator.visit_latex_math = visit_latex_math_latex + LaTeXTranslator.depart_latex_math = depart_latex_math_latex + +from os.path import isfile +# LaTeX to HTML translation stuff: +def latex2html(node, source): + inline = isinstance(node.parent, nodes.TextElement) + latex = node['latex'] + print latex + name = 'math-' + md5(latex).hexdigest()[-10:] + if not isfile('_static/%s.png' % name): + f = open('math.tex', 'w') + f.write(r... [truncated message content] |