Revision: 5497
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5497&view=rev
Author:   jdh2358
Date:     2008-06-12 14:37:11 -0700 (Thu, 12 Jun 2008)

Log Message:
-----------
added mathpng and ipy extensions

Modified Paths:
--------------
    trunk/py4science/examples/sphinx_template/README.txt
    trunk/py4science/examples/sphinx_template/conf.py
    trunk/py4science/examples/sphinx_template/model/index.rst
    trunk/py4science/examples/sphinx_template/model/introduction.rst
    trunk/py4science/examples/sphinx_template/model/sphinx_helpers.rst

Added Paths:
-----------
    trunk/py4science/examples/sphinx_template/model/api_docs.rst
    trunk/py4science/examples/sphinx_template/sphinxext/
    
trunk/py4science/examples/sphinx_template/sphinxext/ipython_console_highlighting.py
    trunk/py4science/examples/sphinx_template/sphinxext/mathml.py
    trunk/py4science/examples/sphinx_template/sphinxext/mathpng.py

Removed Paths:
-------------
    trunk/py4science/examples/sphinx_template/build/

Modified: trunk/py4science/examples/sphinx_template/README.txt
===================================================================
--- trunk/py4science/examples/sphinx_template/README.txt        2008-06-12 
20:51:59 UTC (rev 5496)
+++ trunk/py4science/examples/sphinx_template/README.txt        2008-06-12 
21:37:11 UTC (rev 5497)
@@ -7,7 +7,8 @@
 contains
 
 
-* model - A document describing a model
+* model - A document describing a model.  Be sure to see the cheat
+  sheet file model/sphinx_helpers.rst
 
 * simulations - A document describing the simulations -- contains a
   code subdir with python scripts and a make.py file to build them
@@ -16,6 +17,9 @@
 * make.py - the build script to build the html or PDF docs.  Do
   `python make.py html` or `python make.py latex` for PDF
 
+* sphinxext - some extensions to sphinx to handle math, ipython syntax
+  highlighting, autodocs
+
 * index.rst - the top level include document for sampledocs document
 
 * conf.py - the sphinx configuration

Modified: trunk/py4science/examples/sphinx_template/conf.py
===================================================================
--- trunk/py4science/examples/sphinx_template/conf.py   2008-06-12 20:51:59 UTC 
(rev 5496)
+++ trunk/py4science/examples/sphinx_template/conf.py   2008-06-12 21:37:11 UTC 
(rev 5497)
@@ -16,14 +16,19 @@
 # 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('some/directory'))
+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 = []
+extensions = ['mathpng', 'sphinx.ext.autodoc']
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']

Added: trunk/py4science/examples/sphinx_template/model/api_docs.rst
===================================================================
--- trunk/py4science/examples/sphinx_template/model/api_docs.rst                
                (rev 0)
+++ trunk/py4science/examples/sphinx_template/model/api_docs.rst        
2008-06-12 21:37:11 UTC (rev 5497)
@@ -0,0 +1,16 @@
+.. _samplecode-api:
+
+**************
+Samplecode API
+**************
+
+It is easy to autodocument API code if the code has REST docstrings
+using the sphinx `autodoc <http://sphinx.pocoo.org/ext/autodoc.html>`_
+facilites.
+
+:mod:`matplotlib.backend_bases`
+================================
+
+.. automodule:: matplotlib.backend_bases
+   :members:
+   :undoc-members:

Modified: trunk/py4science/examples/sphinx_template/model/index.rst
===================================================================
--- trunk/py4science/examples/sphinx_template/model/index.rst   2008-06-12 
20:51:59 UTC (rev 5496)
+++ trunk/py4science/examples/sphinx_template/model/index.rst   2008-06-12 
21:37:11 UTC (rev 5497)
@@ -12,3 +12,4 @@
    introduction.rst
    next_steps.rst
    sphinx_helpers.rst
+   api_docs.rst
\ No newline at end of file

Modified: trunk/py4science/examples/sphinx_template/model/introduction.rst
===================================================================
--- trunk/py4science/examples/sphinx_template/model/introduction.rst    
2008-06-12 20:51:59 UTC (rev 5496)
+++ trunk/py4science/examples/sphinx_template/model/introduction.rst    
2008-06-12 21:37:11 UTC (rev 5497)
@@ -4,8 +4,15 @@
 Model Introduction
 ******************
 
-Wherein I describe my fancy model
+Wherein I describe my fancy model  :math:`E=MC^2`
+and also
 
+.. math::
+
+    \frac{5 - \frac{1}{x}}{4}
+
+For more details, see :ref:`using-math`.
+
 .. _other-models:
 
 Other Models

Modified: trunk/py4science/examples/sphinx_template/model/sphinx_helpers.rst
===================================================================
--- trunk/py4science/examples/sphinx_template/model/sphinx_helpers.rst  
2008-06-12 20:51:59 UTC (rev 5496)
+++ trunk/py4science/examples/sphinx_template/model/sphinx_helpers.rst  
2008-06-12 21:37:11 UTC (rev 5497)
@@ -63,6 +63,31 @@
 section inside this document (see :ref:`making-a-table`) or another
 document (see :ref:`final-results`).
 
+You can also reference classes, modules, functions, etc that are
+documented using the sphinx `autodoc
+<http://sphinx.pocoo.org/ext/autodoc.html>`_ facilites.  For example,
+see the module :mod:`matplotlib.backend_bases` documentation, or the
+class :class:`~matplotlib.backend_bases.LocationEvent`, or the method
+:meth:`~matplotlib.backend_bases.FigureCanvasBase.mpl_connect`.
+
+.. _ipython-highlighting:
+
+ipython sessions
+================
+
+Michael Droettboom contributed a sphinx extension which does pygments
+syntax highlighting on ipython sessions
+
+.. sourcecode:: ipython
+
+    In [69]: lines = plot([1,2,3])
+
+    In [70]: setp(lines)
+      alpha: float
+      animated: [True | False]
+      antialiased or aa: [True | False]
+      ...snip
+
 .. _formatting-text:
 
 Formatting text
@@ -80,6 +105,36 @@
 .. literalinclude:: ../simulations/code/elegant.py
 
 
+.. _using-math:
+
+Using math
+==========
+
+In sphinx you can include inline math :math:`x\leftarrow y\ x\forall
+y\ x-y` or display math
+
+.. math::
+
+  W^{3\beta}_{\delta_1 \rho_1 \sigma_2} = U^{3\beta}_{\delta_1 \rho_1} + 
\frac{1}{8 \pi 2} \int^{\alpha_2}_{\alpha_2} d \alpha^\prime_2 \left[\frac{ 
U^{2\beta}_{\delta_1 \rho_1} - \alpha^\prime_2U^{1\beta}_{\rho_1 \sigma_2} 
}{U^{0\beta}_{\rho_1 \sigma_2}}\right]
+
+
+There is a :file:`spinxext/mathml.py` file in the
+:file:`spinx_template` directory which can be enabled via the
+:file:`conf.py` configuration file.  However, we have found that
+resultant html is not supported across many browsers, so have added a
+sphinx extension for translating math to png.  In the file
+:file:`sphinxext/mathpng.py` there are two functions ``latex2png``. 
+The first one requires latex and dvipng, and the second one uses
+matplotlib mathtext (requires mpl svn rxx or later).  Because the 2nd
+function replaces the first one, the matplotlib mathtext support is on
+by default, so you can generate equation enabled html anywhere
+matplotlib is installed (for PDF you will still need pdflatex
+installed).  If you would rather use latex and dvipng, simply hide the
+second ``latex2png`` definition, eg by renaming the second function
+``_latex2png``.
+
+
+
 .. _emacs-helpers:
 
 Emacs helpers

Added: 
trunk/py4science/examples/sphinx_template/sphinxext/ipython_console_highlighting.py
===================================================================
--- 
trunk/py4science/examples/sphinx_template/sphinxext/ipython_console_highlighting.py
                         (rev 0)
+++ 
trunk/py4science/examples/sphinx_template/sphinxext/ipython_console_highlighting.py
 2008-06-12 21:37:11 UTC (rev 5497)
@@ -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/py4science/examples/sphinx_template/sphinxext/mathml.py
===================================================================
--- trunk/py4science/examples/sphinx_template/sphinxext/mathml.py               
                (rev 0)
+++ trunk/py4science/examples/sphinx_template/sphinxext/mathml.py       
2008-06-12 21:37:11 UTC (rev 5497)
@@ -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 = {'<': '&lt;', '>': '&gt;'}
+    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/py4science/examples/sphinx_template/sphinxext/mathpng.py
===================================================================
--- trunk/py4science/examples/sphinx_template/sphinxext/mathpng.py              
                (rev 0)
+++ trunk/py4science/examples/sphinx_template/sphinxext/mathpng.py      
2008-06-12 21:37:11 UTC (rev 5497)
@@ -0,0 +1,134 @@
+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
+
+# This calls out to LaTeX to render the expression
+def latex2png(latex, name):
+    f = open('math.tex', 'w')
+    f.write(r"""\documentclass[12pt]{article}
+                \pagestyle{empty}
+                \begin{document}""")
+    if inline:
+        f.write('$%s$' % latex)
+    else:
+        f.write(r'\[ %s \]' % latex)
+    f.write('\end{document}')
+    f.close()
+    os.system('latex --interaction=nonstopmode math.tex > /dev/null')
+    os.system('dvipng -bgTransparent -Ttight --noghostscript -l10 ' +
+              '-o %s math.dvi > /dev/null' % name)
+
+
+from matplotlib import rcParams
+from matplotlib.mathtext import MathTextParser
+rcParams['mathtext.fontset'] = 'cm'
+mathtext_parser = MathTextParser("Bitmap")
+
+
+# This uses mathtext to render the expression
+def latex2png(latex, filename):
+    if os.path.exists(filename):
+        return
+    mathtext_parser.to_png(filename, "$%s$" % latex, dpi=120)
+
+
+# LaTeX to HTML translation stuff:
+def latex2html(node, source):
+    inline = isinstance(node.parent, nodes.TextElement)
+    latex = node['latex']
+    print latex.encode("ascii", "backslashreplace")
+    name = 'math-%s' % md5(latex).hexdigest()[-10:]
+    dest = '_static/%s.png' % name
+    if not isfile(dest):
+        latex2png(latex, dest)
+
+    path = '_static'
+    count = source.split('/doc/')[-1].count('/')
+    for i in range(count):
+        if os.path.exists(path): break
+        path = '../'+path
+    path = '../'+path #specifically added for matplotlib
+    if inline and '_' in latex:
+        align = 'align="absmiddle" '
+    else:
+        align = ''
+    if inline:
+        cls = ''
+    else:
+        cls = 'class="center" '
+    return '<img src="%s/%s.png" %s%s/>' % (path, name, align, cls)
+


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to