|
From: <jd...@us...> - 2008-06-12 21:37:31
|
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 = {'<': '<', '>': '>'}
+ 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.
|