You can subscribe to this list here.
| 2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(115) |
Aug
(120) |
Sep
(137) |
Oct
(170) |
Nov
(461) |
Dec
(263) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2008 |
Jan
(120) |
Feb
(74) |
Mar
(35) |
Apr
(74) |
May
(245) |
Jun
(356) |
Jul
(240) |
Aug
(115) |
Sep
(78) |
Oct
(225) |
Nov
(98) |
Dec
(271) |
| 2009 |
Jan
(132) |
Feb
(84) |
Mar
(74) |
Apr
(56) |
May
(90) |
Jun
(79) |
Jul
(83) |
Aug
(296) |
Sep
(214) |
Oct
(76) |
Nov
(82) |
Dec
(66) |
| 2010 |
Jan
(46) |
Feb
(58) |
Mar
(51) |
Apr
(77) |
May
(58) |
Jun
(126) |
Jul
(128) |
Aug
(64) |
Sep
(50) |
Oct
(44) |
Nov
(48) |
Dec
(54) |
| 2011 |
Jan
(68) |
Feb
(52) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <fer...@us...> - 2009-03-18 07:39:53
|
Revision: 6987
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6987&view=rev
Author: fer_perez
Date: 2009-03-18 07:39:43 +0000 (Wed, 18 Mar 2009)
Log Message:
-----------
Update to current versions of tools, add API auto generation.
Modified Paths:
--------------
trunk/py4science/examples/sphinx_template2/Makefile
trunk/py4science/examples/sphinx_template2/conf.py
trunk/py4science/examples/sphinx_template2/index.rst
trunk/py4science/examples/sphinx_template2/model/sphinx_helpers.rst
trunk/py4science/examples/sphinx_template2/simulations/finale.rst
trunk/py4science/examples/sphinx_template2/simulations/preliminary.rst
trunk/py4science/examples/sphinx_template2/tools/sphinxext/inheritance_diagram.py
Added Paths:
-----------
trunk/py4science/examples/sphinx_template2/_static/
trunk/py4science/examples/sphinx_template2/_templates/
trunk/py4science/examples/sphinx_template2/api/
trunk/py4science/examples/sphinx_template2/api/generated/
trunk/py4science/examples/sphinx_template2/api/index.rst
trunk/py4science/examples/sphinx_template2/autogen_api.py
trunk/py4science/examples/sphinx_template2/tools/sphinxext/apigen.py
trunk/py4science/examples/sphinx_template2/tools/sphinxext/docscrape.py
trunk/py4science/examples/sphinx_template2/tools/sphinxext/docscrape_sphinx.py
trunk/py4science/examples/sphinx_template2/tools/sphinxext/numpydoc.py
Removed Paths:
-------------
trunk/py4science/examples/sphinx_template2/tools/sphinxext/mathmpl.py
trunk/py4science/examples/sphinx_template2/tools/sphinxext/only_directives.py
trunk/py4science/examples/sphinx_template2/tools/sphinxext/plot_directive.py
trunk/py4science/examples/sphinx_template2/tools/static/
trunk/py4science/examples/sphinx_template2/tools/templates/
Modified: trunk/py4science/examples/sphinx_template2/Makefile
===================================================================
--- trunk/py4science/examples/sphinx_template2/Makefile 2009-03-17 19:45:05 UTC (rev 6986)
+++ trunk/py4science/examples/sphinx_template2/Makefile 2009-03-18 07:39:43 UTC (rev 6987)
@@ -14,7 +14,8 @@
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRCDIR)
-.PHONY: help clean html web pickle htmlhelp latex changes linkcheck pdf all dist
+.PHONY: help clean html web pickle htmlhelp latex changes linkcheck pdf all \
+ dist api
help:
@echo "Please use \`make <target>' where <target> is one of"
@@ -31,7 +32,7 @@
@echo " dist all, and then puts the results in dist/"
clean:
- -rm -rf build/ dist/ _static/ pyplots/*png pyplots/*pdf
+ -rm -rf build/ dist/ _static/* api/generated/*rst pyplots/*png pyplots/*pdf
pdf: latex
cd build/latex && make all-pdf
@@ -44,12 +45,16 @@
cp -al build/html dist/
@echo "Build finished. Final docs are in dist/"
-html:
+html: api
mkdir -p build/html build/doctrees
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html
@echo
@echo "Build finished. The HTML pages are in build/html."
+api:
+ python autogen_api.py
+ @echo "Build API docs finished."
+
pickle:
mkdir -p build/pickle build/doctrees
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle
@@ -60,14 +65,14 @@
web: pickle
-htmlhelp:
+htmlhelp: api
mkdir -p build/htmlhelp build/doctrees
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in build/htmlhelp."
-latex:
+latex: api
mkdir -p build/latex build/doctrees
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex
@echo
Property changes on: trunk/py4science/examples/sphinx_template2/_static
___________________________________________________________________
Added: svn:mergeinfo
+
Property changes on: trunk/py4science/examples/sphinx_template2/_templates
___________________________________________________________________
Added: svn:mergeinfo
+
Added: trunk/py4science/examples/sphinx_template2/api/index.rst
===================================================================
--- trunk/py4science/examples/sphinx_template2/api/index.rst (rev 0)
+++ trunk/py4science/examples/sphinx_template2/api/index.rst 2009-03-18 07:39:43 UTC (rev 6987)
@@ -0,0 +1,12 @@
+.. _api-index:
+
+########################
+ The Python email API
+########################
+
+.. htmlonly::
+
+ :Release: |version|
+ :Date: |today|
+
+.. include:: generated/gen.rst
Added: trunk/py4science/examples/sphinx_template2/autogen_api.py
===================================================================
--- trunk/py4science/examples/sphinx_template2/autogen_api.py (rev 0)
+++ trunk/py4science/examples/sphinx_template2/autogen_api.py 2009-03-18 07:39:43 UTC (rev 6987)
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+"""Script to auto-generate our API docs.
+"""
+# stdlib imports
+import os
+import sys
+
+# local imports
+sys.path.append(os.path.abspath('tools/sphinxext'))
+from apigen import ApiDocWriter
+
+#*****************************************************************************
+if __name__ == '__main__':
+ pjoin = os.path.join
+ package = 'email'
+ outdir = pjoin('api','generated')
+ docwriter = ApiDocWriter(package,rst_extension='.rst')
+ # Skip packages you don't want to document
+ docwriter.package_skip_patterns += [r'\.mime',
+ ]
+ # For modules, there are also skip patterns
+ docwriter.module_skip_patterns += [ r'\.mime',
+ ]
+ docwriter.write_api_docs(outdir)
+ docwriter.write_index(outdir, 'gen',
+ relative_to = 'api'
+ )
+ print '%d files written' % len(docwriter.written_modules)
Property changes on: trunk/py4science/examples/sphinx_template2/autogen_api.py
___________________________________________________________________
Added: svn:executable
+ *
Modified: trunk/py4science/examples/sphinx_template2/conf.py
===================================================================
--- trunk/py4science/examples/sphinx_template2/conf.py 2009-03-17 19:45:05 UTC (rev 6986)
+++ trunk/py4science/examples/sphinx_template2/conf.py 2009-03-18 07:39:43 UTC (rev 6987)
@@ -28,14 +28,17 @@
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = [#'mathmpl',
- 'ipython_console_highlighting', 'sphinx.ext.autodoc',
- 'inheritance_diagram', 'only_directives', 'plot_directive',
- 'sphinx.ext.pngmath',
- ]
+extensions = ['matplotlib.sphinxext.mathmpl',
+ 'matplotlib.sphinxext.only_directives',
+ 'matplotlib.sphinxext.plot_directive',
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.doctest',
+ 'ipython_console_highlighting',
+ 'inheritance_diagram',
+ 'numpydoc']
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['tools/templates']
+templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
@@ -102,7 +105,7 @@
# 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 = ['tools/static','_static']
+html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
Modified: trunk/py4science/examples/sphinx_template2/index.rst
===================================================================
--- trunk/py4science/examples/sphinx_template2/index.rst 2009-03-17 19:45:05 UTC (rev 6986)
+++ trunk/py4science/examples/sphinx_template2/index.rst 2009-03-18 07:39:43 UTC (rev 6987)
@@ -13,8 +13,9 @@
.. toctree::
:maxdepth: 2
- model/index.rst
- simulations/index.rst
+ model/index
+ simulations/index
+ api/index
.. htmlonly::
Modified: trunk/py4science/examples/sphinx_template2/model/sphinx_helpers.rst
===================================================================
--- trunk/py4science/examples/sphinx_template2/model/sphinx_helpers.rst 2009-03-17 19:45:05 UTC (rev 6986)
+++ trunk/py4science/examples/sphinx_template2/model/sphinx_helpers.rst 2009-03-18 07:39:43 UTC (rev 6987)
@@ -157,7 +157,7 @@
original source code, a high-resolution PNG and a PDF. In the PDF
version of the document, the plot is included as a scalable PDF.
-.. plot:: ../pyplots/elegant.py
+.. plot:: pyplots/elegant.py
:include-source:
Inheritance diagrams
Modified: trunk/py4science/examples/sphinx_template2/simulations/finale.rst
===================================================================
--- trunk/py4science/examples/sphinx_template2/simulations/finale.rst 2009-03-17 19:45:05 UTC (rev 6986)
+++ trunk/py4science/examples/sphinx_template2/simulations/finale.rst 2009-03-18 07:39:43 UTC (rev 6987)
@@ -8,5 +8,6 @@
After much head scratching, I wrote this big elegant piece of code, to
produce this much more elegant figure:
-.. plot:: ../pyplots/elegant.py
+.. plot:: pyplots/fancy.py
:include-source:
+
Modified: trunk/py4science/examples/sphinx_template2/simulations/preliminary.rst
===================================================================
--- trunk/py4science/examples/sphinx_template2/simulations/preliminary.rst 2009-03-17 19:45:05 UTC (rev 6986)
+++ trunk/py4science/examples/sphinx_template2/simulations/preliminary.rst 2009-03-18 07:39:43 UTC (rev 6987)
@@ -6,6 +6,6 @@
I wrote this big hairy piece of code to make the following plot:
-.. plot:: ../pyplots/hairy.py
+.. plot:: pyplots/hairy.py
:include-source:
Added: trunk/py4science/examples/sphinx_template2/tools/sphinxext/apigen.py
===================================================================
--- trunk/py4science/examples/sphinx_template2/tools/sphinxext/apigen.py (rev 0)
+++ trunk/py4science/examples/sphinx_template2/tools/sphinxext/apigen.py 2009-03-18 07:39:43 UTC (rev 6987)
@@ -0,0 +1,426 @@
+"""Attempt to generate templates for module reference with Sphinx
+
+XXX - we exclude extension modules
+
+To include extension modules, first identify them as valid in the
+``_uri2path`` method, then handle them in the ``_parse_module`` script.
+
+We get functions and classes by parsing the text of .py files.
+Alternatively we could import the modules for discovery, and we'd have
+to do that for extension modules. This would involve changing the
+``_parse_module`` method to work via import and introspection, and
+might involve changing ``discover_modules`` (which determines which
+files are modules, and therefore which module URIs will be passed to
+``_parse_module``).
+
+NOTE: this is a modified version of a script originally shipped with the
+PyMVPA project, which we've adapted for NIPY use. PyMVPA is an MIT-licensed
+project."""
+
+# Stdlib imports
+import os
+import re
+
+# Functions and classes
+class ApiDocWriter(object):
+ ''' Class for automatic detection and parsing of API docs
+ to Sphinx-parsable reST format'''
+
+ # only separating first two levels
+ rst_section_levels = ['*', '=', '-', '~', '^']
+
+ def __init__(self,
+ package_name,
+ rst_extension='.rst',
+ package_skip_patterns=None,
+ module_skip_patterns=None,
+ ):
+ ''' Initialize package for parsing
+
+ Parameters
+ ----------
+ package_name : string
+ Name of the top-level package. *package_name* must be the
+ name of an importable package
+ rst_extension : string, optional
+ Extension for reST files, default '.rst'
+ package_skip_patterns : None or sequence of {strings, regexps}
+ Sequence of strings giving URIs of packages to be excluded
+ Operates on the package path, starting at (including) the
+ first dot in the package path, after *package_name* - so,
+ if *package_name* is ``sphinx``, then ``sphinx.util`` will
+ result in ``.util`` being passed for earching by these
+ regexps. If is None, gives default. Default is:
+ ['\.tests$']
+ module_skip_patterns : None or sequence
+ Sequence of strings giving URIs of modules to be excluded
+ Operates on the module name including preceding URI path,
+ back to the first dot after *package_name*. For example
+ ``sphinx.util.console`` results in the string to search of
+ ``.util.console``
+ If is None, gives default. Default is:
+ ['\.setup$', '\._']
+ '''
+ if package_skip_patterns is None:
+ package_skip_patterns = ['\\.tests$']
+ if module_skip_patterns is None:
+ module_skip_patterns = ['\\.setup$', '\\._']
+ self.package_name = package_name
+ self.rst_extension = rst_extension
+ self.package_skip_patterns = package_skip_patterns
+ self.module_skip_patterns = module_skip_patterns
+
+ def get_package_name(self):
+ return self._package_name
+
+ def set_package_name(self, package_name):
+ ''' Set package_name
+
+ >>> docwriter = ApiDocWriter('sphinx')
+ >>> import sphinx
+ >>> docwriter.root_path == sphinx.__path__[0]
+ True
+ >>> docwriter.package_name = 'docutils'
+ >>> import docutils
+ >>> docwriter.root_path == docutils.__path__[0]
+ True
+ '''
+ # It's also possible to imagine caching the module parsing here
+ self._package_name = package_name
+ self.root_module = __import__(package_name)
+ self.root_path = self.root_module.__path__[0]
+ self.written_modules = None
+
+ package_name = property(get_package_name, set_package_name, None,
+ 'get/set package_name')
+
+ def _get_object_name(self, line):
+ ''' Get second token in line
+ >>> docwriter = ApiDocWriter('sphinx')
+ >>> docwriter._get_object_name(" def func(): ")
+ 'func'
+ >>> docwriter._get_object_name(" class Klass(object): ")
+ 'Klass'
+ >>> docwriter._get_object_name(" class Klass: ")
+ 'Klass'
+ '''
+ name = line.split()[1].split('(')[0].strip()
+ # in case we have classes which are not derived from object
+ # ie. old style classes
+ return name.rstrip(':')
+
+ def _uri2path(self, uri):
+ ''' Convert uri to absolute filepath
+
+ Parameters
+ ----------
+ uri : string
+ URI of python module to return path for
+
+ Returns
+ -------
+ path : None or string
+ Returns None if there is no valid path for this URI
+ Otherwise returns absolute file system path for URI
+
+ Examples
+ --------
+ >>> docwriter = ApiDocWriter('sphinx')
+ >>> import sphinx
+ >>> modpath = sphinx.__path__[0]
+ >>> res = docwriter._uri2path('sphinx.builder')
+ >>> res == os.path.join(modpath, 'builder.py')
+ True
+ >>> res = docwriter._uri2path('sphinx')
+ >>> res == os.path.join(modpath, '__init__.py')
+ True
+ >>> docwriter._uri2path('sphinx.does_not_exist')
+
+ '''
+ if uri == self.package_name:
+ return os.path.join(self.root_path, '__init__.py')
+ path = uri.replace('.', os.path.sep)
+ path = path.replace(self.package_name + os.path.sep, '')
+ path = os.path.join(self.root_path, path)
+ # XXX maybe check for extensions as well?
+ if os.path.exists(path + '.py'): # file
+ path += '.py'
+ elif os.path.exists(os.path.join(path, '__init__.py')):
+ path = os.path.join(path, '__init__.py')
+ else:
+ return None
+ return path
+
+ def _path2uri(self, dirpath):
+ ''' Convert directory path to uri '''
+ relpath = dirpath.replace(self.root_path, self.package_name)
+ if relpath.startswith(os.path.sep):
+ relpath = relpath[1:]
+ return relpath.replace(os.path.sep, '.')
+
+ def _parse_module(self, uri):
+ ''' Parse module defined in *uri* '''
+ filename = self._uri2path(uri)
+ if filename is None:
+ # nothing that we could handle here.
+ return ([],[])
+ f = open(filename, 'rt')
+ functions, classes = self._parse_lines(f)
+ f.close()
+ return functions, classes
+
+ def _parse_lines(self, linesource):
+ ''' Parse lines of text for functions and classes '''
+ functions = []
+ classes = []
+ for line in linesource:
+ if line.startswith('def ') and line.count('('):
+ # exclude private stuff
+ name = self._get_object_name(line)
+ if not name.startswith('_'):
+ functions.append(name)
+ elif line.startswith('class '):
+ # exclude private stuff
+ name = self._get_object_name(line)
+ if not name.startswith('_'):
+ classes.append(name)
+ else:
+ pass
+ functions.sort()
+ classes.sort()
+ return functions, classes
+
+ def generate_api_doc(self, uri):
+ '''Make autodoc documentation template string for a module
+
+ Parameters
+ ----------
+ uri : string
+ python location of module - e.g 'sphinx.builder'
+
+ Returns
+ -------
+ S : string
+ Contents of API doc
+ '''
+ # get the names of all classes and functions
+ functions, classes = self._parse_module(uri)
+ if not len(functions) and not len(classes):
+ print 'WARNING: Empty -',uri # dbg
+ return ''
+
+ # Make a shorter version of the uri that omits the package name for
+ # titles
+ uri_short = re.sub(r'^%s\.' % self.package_name,'',uri)
+
+ ad = '.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n'
+
+ chap_title = uri_short
+ ad += (chap_title+'\n'+ self.rst_section_levels[1] * len(chap_title)
+ + '\n\n')
+
+ # Set the chapter title to read 'module' for all modules except for the
+ # main packages
+ if '.' in uri:
+ title = 'Module: :mod:`' + uri_short + '`'
+ else:
+ title = ':mod:`' + uri_short + '`'
+ ad += title + '\n' + self.rst_section_levels[2] * len(title)
+
+ if len(classes):
+ ad += '\nInheritance diagram for ``%s``:\n\n' % uri
+ ad += '.. inheritance-diagram:: %s \n' % uri
+ ad += ' :parts: 3\n'
+
+ ad += '\n.. automodule:: ' + uri + '\n'
+ ad += '\n.. currentmodule:: ' + uri + '\n'
+ multi_class = len(classes) > 1
+ multi_fx = len(functions) > 1
+ if multi_class:
+ ad += '\n' + 'Classes' + '\n' + \
+ self.rst_section_levels[2] * 7 + '\n'
+ elif len(classes) and multi_fx:
+ ad += '\n' + 'Class' + '\n' + \
+ self.rst_section_levels[2] * 5 + '\n'
+ for c in classes:
+ ad += '\n:class:`' + c + '`\n' \
+ + self.rst_section_levels[multi_class + 2 ] * \
+ (len(c)+9) + '\n\n'
+ ad += '\n.. autoclass:: ' + c + '\n'
+ # must NOT exclude from index to keep cross-refs working
+ ad += ' :members:\n' \
+ ' :undoc-members:\n' \
+ ' :show-inheritance:\n' \
+ '\n' \
+ ' .. automethod:: __init__\n'
+ if multi_fx:
+ ad += '\n' + 'Functions' + '\n' + \
+ self.rst_section_levels[2] * 9 + '\n\n'
+ elif len(functions) and multi_class:
+ ad += '\n' + 'Function' + '\n' + \
+ self.rst_section_levels[2] * 8 + '\n\n'
+ for f in functions:
+ # must NOT exclude from index to keep cross-refs working
+ ad += '\n.. autofunction:: ' + uri + '.' + f + '\n\n'
+ return ad
+
+ def _survives_exclude(self, matchstr, match_type):
+ ''' Returns True if *matchstr* does not match patterns
+
+ ``self.package_name`` removed from front of string if present
+
+ Examples
+ --------
+ >>> dw = ApiDocWriter('sphinx')
+ >>> dw._survives_exclude('sphinx.okpkg', 'package')
+ True
+ >>> dw.package_skip_patterns.append('^\\.badpkg$')
+ >>> dw._survives_exclude('sphinx.badpkg', 'package')
+ False
+ >>> dw._survives_exclude('sphinx.badpkg', 'module')
+ True
+ >>> dw._survives_exclude('sphinx.badmod', 'module')
+ True
+ >>> dw.module_skip_patterns.append('^\\.badmod$')
+ >>> dw._survives_exclude('sphinx.badmod', 'module')
+ False
+ '''
+ if match_type == 'module':
+ patterns = self.module_skip_patterns
+ elif match_type == 'package':
+ patterns = self.package_skip_patterns
+ else:
+ raise ValueError('Cannot interpret match type "%s"'
+ % match_type)
+ # Match to URI without package name
+ L = len(self.package_name)
+ if matchstr[:L] == self.package_name:
+ matchstr = matchstr[L:]
+ for pat in patterns:
+ try:
+ pat.search
+ except AttributeError:
+ pat = re.compile(pat)
+ if pat.search(matchstr):
+ return False
+ return True
+
+ def discover_modules(self):
+ ''' Return module sequence discovered from ``self.package_name``
+
+
+ Parameters
+ ----------
+ None
+
+ Returns
+ -------
+ mods : sequence
+ Sequence of module names within ``self.package_name``
+
+ Examples
+ --------
+ >>> dw = ApiDocWriter('sphinx')
+ >>> mods = dw.discover_modules()
+ >>> 'sphinx.util' in mods
+ True
+ >>> dw.package_skip_patterns.append('\.util$')
+ >>> 'sphinx.util' in dw.discover_modules()
+ False
+ >>>
+ '''
+ modules = [self.package_name]
+ # raw directory parsing
+ for dirpath, dirnames, filenames in os.walk(self.root_path):
+ # Check directory names for packages
+ root_uri = self._path2uri(os.path.join(self.root_path,
+ dirpath))
+ for dirname in dirnames[:]: # copy list - we modify inplace
+ package_uri = '.'.join((root_uri, dirname))
+ if (self._uri2path(package_uri) and
+ self._survives_exclude(package_uri, 'package')):
+ modules.append(package_uri)
+ else:
+ dirnames.remove(dirname)
+ # Check filenames for modules
+ for filename in filenames:
+ module_name = filename[:-3]
+ module_uri = '.'.join((root_uri, module_name))
+ if (self._uri2path(module_uri) and
+ self._survives_exclude(module_uri, 'module')):
+ modules.append(module_uri)
+ return sorted(modules)
+
+ def write_modules_api(self, modules,outdir):
+ # write the list
+ written_modules = []
+ for m in modules:
+ api_str = self.generate_api_doc(m)
+ if not api_str:
+ continue
+ # write out to file
+ outfile = os.path.join(outdir,
+ m + self.rst_extension)
+ fileobj = open(outfile, 'wt')
+ fileobj.write(api_str)
+ fileobj.close()
+ written_modules.append(m)
+ self.written_modules = written_modules
+
+ def write_api_docs(self, outdir):
+ """Generate API reST files.
+
+ Parameters
+ ----------
+ outdir : string
+ Directory name in which to store files
+ We create automatic filenames for each module
+
+ Returns
+ -------
+ None
+
+ Notes
+ -----
+ Sets self.written_modules to list of written modules
+ """
+ if not os.path.exists(outdir):
+ os.mkdir(outdir)
+ # compose list of modules
+ modules = self.discover_modules()
+ self.write_modules_api(modules,outdir)
+
+ def write_index(self, outdir, froot='gen', relative_to=None):
+ """Make a reST API index file from written files
+
+ Parameters
+ ----------
+ path : string
+ Filename to write index to
+ outdir : string
+ Directory to which to write generated index file
+ froot : string, optional
+ root (filename without extension) of filename to write to
+ Defaults to 'gen'. We add ``self.rst_extension``.
+ relative_to : string
+ path to which written filenames are relative. This
+ component of the written file path will be removed from
+ outdir, in the generated index. Default is None, meaning,
+ leave path as it is.
+ """
+ if self.written_modules is None:
+ raise ValueError('No modules written')
+ # Get full filename path
+ path = os.path.join(outdir, froot+self.rst_extension)
+ # Path written into index is relative to rootpath
+ if relative_to is not None:
+ relpath = outdir.replace(relative_to + os.path.sep, '')
+ else:
+ relpath = outdir
+ idx = open(path,'wt')
+ w = idx.write
+ w('.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n')
+ w('.. toctree::\n\n')
+ for f in self.written_modules:
+ w(' %s\n' % os.path.join(relpath,f))
+ idx.close()
Added: trunk/py4science/examples/sphinx_template2/tools/sphinxext/docscrape.py
===================================================================
--- trunk/py4science/examples/sphinx_template2/tools/sphinxext/docscrape.py (rev 0)
+++ trunk/py4science/examples/sphinx_template2/tools/sphinxext/docscrape.py 2009-03-18 07:39:43 UTC (rev 6987)
@@ -0,0 +1,497 @@
+"""Extract reference documentation from the NumPy source tree.
+
+"""
+
+import inspect
+import textwrap
+import re
+import pydoc
+from StringIO import StringIO
+from warnings import warn
+4
+class Reader(object):
+ """A line-based string reader.
+
+ """
+ def __init__(self, data):
+ """
+ Parameters
+ ----------
+ data : str
+ String with lines separated by '\n'.
+
+ """
+ if isinstance(data,list):
+ self._str = data
+ else:
+ self._str = data.split('\n') # store string as list of lines
+
+ self.reset()
+
+ def __getitem__(self, n):
+ return self._str[n]
+
+ def reset(self):
+ self._l = 0 # current line nr
+
+ def read(self):
+ if not self.eof():
+ out = self[self._l]
+ self._l += 1
+ return out
+ else:
+ return ''
+
+ def seek_next_non_empty_line(self):
+ for l in self[self._l:]:
+ if l.strip():
+ break
+ else:
+ self._l += 1
+
+ def eof(self):
+ return self._l >= len(self._str)
+
+ def read_to_condition(self, condition_func):
+ start = self._l
+ for line in self[start:]:
+ if condition_func(line):
+ return self[start:self._l]
+ self._l += 1
+ if self.eof():
+ return self[start:self._l+1]
+ return []
+
+ def read_to_next_empty_line(self):
+ self.seek_next_non_empty_line()
+ def is_empty(line):
+ return not line.strip()
+ return self.read_to_condition(is_empty)
+
+ def read_to_next_unindented_line(self):
+ def is_unindented(line):
+ return (line.strip() and (len(line.lstrip()) == len(line)))
+ return self.read_to_condition(is_unindented)
+
+ def peek(self,n=0):
+ if self._l + n < len(self._str):
+ return self[self._l + n]
+ else:
+ return ''
+
+ def is_empty(self):
+ return not ''.join(self._str).strip()
+
+
+class NumpyDocString(object):
+ def __init__(self,docstring):
+ docstring = textwrap.dedent(docstring).split('\n')
+
+ self._doc = Reader(docstring)
+ self._parsed_data = {
+ 'Signature': '',
+ 'Summary': [''],
+ 'Extended Summary': [],
+ 'Parameters': [],
+ 'Returns': [],
+ 'Raises': [],
+ 'Warns': [],
+ 'Other Parameters': [],
+ 'Attributes': [],
+ 'Methods': [],
+ 'See Also': [],
+ 'Notes': [],
+ 'Warnings': [],
+ 'References': '',
+ 'Examples': '',
+ 'index': {}
+ }
+
+ self._parse()
+
+ def __getitem__(self,key):
+ return self._parsed_data[key]
+
+ def __setitem__(self,key,val):
+ if not self._parsed_data.has_key(key):
+ warn("Unknown section %s" % key)
+ else:
+ self._parsed_data[key] = val
+
+ def _is_at_section(self):
+ self._doc.seek_next_non_empty_line()
+
+ if self._doc.eof():
+ return False
+
+ l1 = self._doc.peek().strip() # e.g. Parameters
+
+ if l1.startswith('.. index::'):
+ return True
+
+ l2 = self._doc.peek(1).strip() # ---------- or ==========
+ return l2.startswith('-'*len(l1)) or l2.startswith('='*len(l1))
+
+ def _strip(self,doc):
+ i = 0
+ j = 0
+ for i,line in enumerate(doc):
+ if line.strip(): break
+
+ for j,line in enumerate(doc[::-1]):
+ if line.strip(): break
+
+ return doc[i:len(doc)-j]
+
+ def _read_to_next_section(self):
+ section = self._doc.read_to_next_empty_line()
+
+ while not self._is_at_section() and not self._doc.eof():
+ if not self._doc.peek(-1).strip(): # previous line was empty
+ section += ['']
+
+ section += self._doc.read_to_next_empty_line()
+
+ return section
+
+ def _read_sections(self):
+ while not self._doc.eof():
+ data = self._read_to_next_section()
+ name = data[0].strip()
+
+ if name.startswith('..'): # index section
+ yield name, data[1:]
+ elif len(data) < 2:
+ yield StopIteration
+ else:
+ yield name, self._strip(data[2:])
+
+ def _parse_param_list(self,content):
+ r = Reader(content)
+ params = []
+ while not r.eof():
+ header = r.read().strip()
+ if ' : ' in header:
+ arg_name, arg_type = header.split(' : ')[:2]
+ else:
+ arg_name, arg_type = header, ''
+
+ desc = r.read_to_next_unindented_line()
+ desc = dedent_lines(desc)
+
+ params.append((arg_name,arg_type,desc))
+
+ return params
+
+
+ _name_rgx = re.compile(r"^\s*(:(?P<role>\w+):`(?P<name>[a-zA-Z0-9_.-]+)`|"
+ r" (?P<name2>[a-zA-Z0-9_.-]+))\s*", re.X)
+ def _parse_see_also(self, content):
+ """
+ func_name : Descriptive text
+ continued text
+ another_func_name : Descriptive text
+ func_name1, func_name2, :meth:`func_name`, func_name3
+
+ """
+ items = []
+
+ def parse_item_name(text):
+ """Match ':role:`name`' or 'name'"""
+ m = self._name_rgx.match(text)
+ if m:
+ g = m.groups()
+ if g[1] is None:
+ return g[3], None
+ else:
+ return g[2], g[1]
+ raise ValueError("%s is not a item name" % text)
+
+ def push_item(name, rest):
+ if not name:
+ return
+ name, role = parse_item_name(name)
+ items.append((name, list(rest), role))
+ del rest[:]
+
+ current_func = None
+ rest = []
+
+ for line in content:
+ if not line.strip(): continue
+
+ m = self._name_rgx.match(line)
+ if m and line[m.end():].strip().startswith(':'):
+ push_item(current_func, rest)
+ current_func, line = line[:m.end()], line[m.end():]
+ rest = [line.split(':', 1)[1].strip()]
+ if not rest[0]:
+ rest = []
+ elif not line.startswith(' '):
+ push_item(current_func, rest)
+ current_func = None
+ if ',' in line:
+ for func in line.split(','):
+ push_item(func, [])
+ elif line.strip():
+ current_func = line
+ elif current_func is not None:
+ rest.append(line.strip())
+ push_item(current_func, rest)
+ return items
+
+ def _parse_index(self, section, content):
+ """
+ .. index: default
+ :refguide: something, else, and more
+
+ """
+ def strip_each_in(lst):
+ return [s.strip() for s in lst]
+
+ out = {}
+ section = section.split('::')
+ if len(section) > 1:
+ out['default'] = strip_each_in(section[1].split(','))[0]
+ for line in content:
+ line = line.split(':')
+ if len(line) > 2:
+ out[line[1]] = strip_each_in(line[2].split(','))
+ return out
+
+ def _parse_summary(self):
+ """Grab signature (if given) and summary"""
+ if self._is_at_section():
+ return
+
+ summary = self._doc.read_to_next_empty_line()
+ summary_str = " ".join([s.strip() for s in summary]).strip()
+ if re.compile('^([\w., ]+=)?\s*[\w\.]+\(.*\)$').match(summary_str):
+ self['Signature'] = summary_str
+ if not self._is_at_section():
+ self['Summary'] = self._doc.read_to_next_empty_line()
+ else:
+ self['Summary'] = summary
+
+ if not self._is_at_section():
+ self['Extended Summary'] = self._read_to_next_section()
+
+ def _parse(self):
+ self._doc.reset()
+ self._parse_summary()
+
+ for (section,content) in self._read_sections():
+ if not section.startswith('..'):
+ section = ' '.join([s.capitalize() for s in section.split(' ')])
+ if section in ('Parameters', 'Attributes', 'Methods',
+ 'Returns', 'Raises', 'Warns'):
+ self[section] = self._parse_param_list(content)
+ elif section.startswith('.. index::'):
+ self['index'] = self._parse_index(section, content)
+ elif section == 'See Also':
+ self['See Also'] = self._parse_see_also(content)
+ else:
+ self[section] = content
+
+ # string conversion routines
+
+ def _str_header(self, name, symbol='-'):
+ return [name, len(name)*symbol]
+
+ def _str_indent(self, doc, indent=4):
+ out = []
+ for line in doc:
+ out += [' '*indent + line]
+ return out
+
+ def _str_signature(self):
+ if self['Signature']:
+ return [self['Signature'].replace('*','\*')] + ['']
+ else:
+ return ['']
+
+ def _str_summary(self):
+ if self['Summary']:
+ return self['Summary'] + ['']
+ else:
+ return []
+
+ def _str_extended_summary(self):
+ if self['Extended Summary']:
+ return self['Extended Summary'] + ['']
+ else:
+ return []
+
+ def _str_param_list(self, name):
+ out = []
+ if self[name]:
+ out += self._str_header(name)
+ for param,param_type,desc in self[name]:
+ out += ['%s : %s' % (param, param_type)]
+ out += self._str_indent(desc)
+ out += ['']
+ return out
+
+ def _str_section(self, name):
+ out = []
+ if self[name]:
+ out += self._str_header(name)
+ out += self[name]
+ out += ['']
+ return out
+
+ def _str_see_also(self, func_role):
+ if not self['See Also']: return []
+ out = []
+ out += self._str_header("See Also")
+ last_had_desc = True
+ for func, desc, role in self['See Also']:
+ if role:
+ link = ':%s:`%s`' % (role, func)
+ elif func_role:
+ link = ':%s:`%s`' % (func_role, func)
+ else:
+ link = "`%s`_" % func
+ if desc or last_had_desc:
+ out += ['']
+ out += [link]
+ else:
+ out[-1] += ", %s" % link
+ if desc:
+ out += self._str_indent([' '.join(desc)])
+ last_had_desc = True
+ else:
+ last_had_desc = False
+ out += ['']
+ return out
+
+ def _str_index(self):
+ idx = self['index']
+ out = []
+ out += ['.. index:: %s' % idx.get('default','')]
+ for section, references in idx.iteritems():
+ if section == 'default':
+ continue
+ out += [' :%s: %s' % (section, ', '.join(references))]
+ return out
+
+ def __str__(self, func_role=''):
+ out = []
+ out += self._str_signature()
+ out += self._str_summary()
+ out += self._str_extended_summary()
+ for param_list in ('Parameters','Returns','Raises'):
+ out += self._str_param_list(param_list)
+ out += self._str_section('Warnings')
+ out += self._str_see_also(func_role)
+ for s in ('Notes','References','Examples'):
+ out += self._str_section(s)
+ out += self._str_index()
+ return '\n'.join(out)
+
+
+def indent(str,indent=4):
+ indent_str = ' '*indent
+ if str is None:
+ return indent_str
+ lines = str.split('\n')
+ return '\n'.join(indent_str + l for l in lines)
+
+def dedent_lines(lines):
+ """Deindent a list of lines maximally"""
+ return textwrap.dedent("\n".join(lines)).split("\n")
+
+def header(text, style='-'):
+ return text + '\n' + style*len(text) + '\n'
+
+
+class FunctionDoc(NumpyDocString):
+ def __init__(self, func, role='func', doc=None):
+ self._f = func
+ self._role = role # e.g. "func" or "meth"
+ if doc is None:
+ doc = inspect.getdoc(func) or ''
+ try:
+ NumpyDocString.__init__(self, doc)
+ except ValueError, e:
+ print '*'*78
+ print "ERROR: '%s' while parsing `%s`" % (e, self._f)
+ print '*'*78
+ #print "Docstring follows:"
+ #print doclines
+ #print '='*78
+
+ if not self['Signature']:
+ func, func_name = self.get_func()
+ try:
+ # try to read signature
+ argspec = inspect.getargspec(func)
+ argspec = inspect.formatargspec(*argspec)
+ argspec = argspec.replace('*','\*')
+ signature = '%s%s' % (func_name, argspec)
+ except TypeError, e:
+ signature = '%s()' % func_name
+ self['Signature'] = signature
+
+ def get_func(self):
+ func_name = getattr(self._f, '__name__', self.__class__.__name__)
+ if inspect.isclass(self._f):
+ func = getattr(self._f, '__call__', self._f.__init__)
+ else:
+ func = self._f
+ return func, func_name
+
+ def __str__(self):
+ out = ''
+
+ func, func_name = self.get_func()
+ signature = self['Signature'].replace('*', '\*')
+
+ roles = {'func': 'function',
+ 'meth': 'method'}
+
+ if self._role:
+ if not roles.has_key(self._role):
+ print "Warning: invalid role %s" % self._role
+ out += '.. %s:: %s\n \n\n' % (roles.get(self._role,''),
+ func_name)
+
+ out += super(FunctionDoc, self).__str__(func_role=self._role)
+ return out
+
+
+class ClassDoc(NumpyDocString):
+ def __init__(self,cls,modulename='',func_doc=FunctionDoc,doc=None):
+ if not inspect.isclass(cls):
+ raise ValueError("Initialise using a class. Got %r" % cls)
+ self._cls = cls
+
+ if modulename and not modulename.endswith('.'):
+ modulename += '.'
+ self._mod = modulename
+ self._name = cls.__name__
+ self._func_doc = func_doc
+
+ if doc is None:
+ doc = pydoc.getdoc(cls)
+
+ NumpyDocString.__init__(self, doc)
+
+ @property
+ def methods(self):
+ return [name for name,func in inspect.getmembers(self._cls)
+ if not name.startswith('_') and callable(func)]
+
+ def __str__(self):
+ out = ''
+ out += super(ClassDoc, self).__str__()
+ out += "\n\n"
+
+ #for m in self.methods:
+ # print "Parsing `%s`" % m
+ # out += str(self._func_doc(getattr(self._cls,m), 'meth')) + '\n\n'
+ # out += '.. index::\n single: %s; %s\n\n' % (self._name, m)
+
+ return out
+
+
Added: trunk/py4science/examples/sphinx_template2/tools/sphinxext/docscrape_sphinx.py
===================================================================
--- trunk/py4science/examples/sphinx_template2/tools/sphinxext/docscrape_sphinx.py (rev 0)
+++ trunk/py4science/examples/sphinx_template2/tools/sphinxext/docscrape_sphinx.py 2009-03-18 07:39:43 UTC (rev 6987)
@@ -0,0 +1,136 @@
+import re, inspect, textwrap, pydoc
+from docscrape import NumpyDocString, FunctionDoc, ClassDoc
+
+class SphinxDocString(NumpyDocString):
+ # string conversion routines
+ def _str_header(self, name, symbol='`'):
+ return ['.. rubric:: ' + name, '']
+
+ def _str_field_list(self, name):
+ return [':' + name + ':']
+
+ def _str_indent(self, doc, indent=4):
+ out = []
+ for line in doc:
+ out += [' '*indent + line]
+ return out
+
+ def _str_signature(self):
+ return ['']
+ if self['Signature']:
+ return ['``%s``' % self['Signature']] + ['']
+ else:
+ return ['']
+
+ def _str_summary(self):
+ return self['Summary'] + ['']
+
+ def _str_extended_summary(self):
+ return self['Extended Summary'] + ['']
+
+ def _str_param_list(self, name):
+ out = []
+ if self[name]:
+ out += self._str_field_list(name)
+ out += ['']
+ for param,param_type,desc in self[name]:
+ out += self._str_indent(['**%s** : %s' % (param.strip(),
+ param_type)])
+ out += ['']
+ out += self._str_indent(desc,8)
+ out += ['']
+ return out
+
+ def _str_section(self, name):
+ out = []
+ if self[name]:
+ out += self._str_header(name)
+ out += ['']
+ content = textwrap.dedent("\n".join(self[name])).split("\n")
+ out += content
+ out += ['']
+ return out
+
+ def _str_see_also(self, func_role):
+ out = []
+ if self['See Also']:
+ see_also = super(SphinxDocString, self)._str_see_also(func_role)
+ out = ['.. seealso::', '']
+ out += self._str_indent(see_also[2:])
+ return out
+
+ def _str_warnings(self):
+ out = []
+ if self['Warnings']:
+ out = ['.. warning::', '']
+ out += self._str_indent(self['Warnings'])
+ return out
+
+ def _str_index(self):
+ idx = self['index']
+ out = []
+ if len(idx) == 0:
+ return out
+
+ out += ['.. index:: %s' % idx.get('default','')]
+ for section, references in idx.iteritems():
+ if section == 'default':
+ continue
+ elif section == 'refguide':
+ out += [' single: %s' % (', '.join(references))]
+ else:
+ out += [' %s: %s' % (section, ','.join(references))]
+ return out
+
+ def _str_references(self):
+ out = []
+ if self['References']:
+ out += self._str_header('References')
+ if isinstance(self['References'], str):
+ self['References'] = [self['References']]
+ out.extend(self['References'])
+ out += ['']
+ return out
+
+ def __str__(self, indent=0, func_role="obj"):
+ out = []
+ out += self._str_signature()
+ out += self._str_index() + ['']
+ out += self._str_summary()
+ out += self._str_extended_summary()
+ for param_list in ('Parameters', 'Attributes', 'Methods',
+ 'Returns','Raises'):
+ out += self._str_param_list(param_list)
+ out += self._str_warnings()
+ out += self._str_see_also(func_role)
+ out += self._str_section('Notes')
+ out += self._str_references()
+ out += self._str_section('Examples')
+ out = self._str_indent(out,indent)
+ return '\n'.join(out)
+
+class SphinxFunctionDoc(SphinxDocString, FunctionDoc):
+ pass
+
+class SphinxClassDoc(SphinxDocString, ClassDoc):
+ pass
+
+def get_doc_object(obj, what=None, doc=None):
+ if what is None:
+ if inspect.isclass(obj):
+ what = 'class'
+ elif inspect.ismodule(obj):
+ what = 'module'
+ elif callable(obj):
+ what = 'function'
+ else:
+ what = 'object'
+ if what == 'class':
+ return SphinxClassDoc(obj, '', func_doc=SphinxFunctionDoc, doc=doc)
+ elif what in ('function', 'method'):
+ return SphinxFunctionDoc(obj, '', doc=doc)
+ else:
+ if doc is None:
+ doc = pydoc.getdoc(obj)
+ return SphinxDocString(doc)
+
Modified: trunk/py4science/examples/sphinx_template2/tools/sphinxext/inheritance_diagram.py
===================================================================
--- trunk/py4science/examples/sphinx_template2/tools/sphinxext/inheritance_diagram.py 2009-03-17 19:45:05 UTC (rev 6986)
+++ trunk/py4science/examples/sphinx_template2/tools/sphinxext/inheritance_diagram.py 2009-03-18 07:39:43 UTC (rev 6987)
@@ -29,42 +29,30 @@
LaTeX.
"""
-#-----------------------------------------------------------------------------
-# Module and package imports
-
-# From the standard library
-
import inspect
import os
import re
import subprocess
-
try:
from hashlib import md5
except ImportError:
from md5 import md5
-# Third party
from docutils.nodes import Body, Element
-from docutils.writers.html4css1 import HTMLTranslator
from docutils.parsers.rst import directives
-
-from sphinx.latexwriter import LaTeXTranslator
from sphinx.roles import xfileref_role
-#-----------------------------------------------------------------------------
-# Global Constants
-# Sphinx automatically copies out the contents of this directory to the html
-# output, so by putting things in here they get correctly picked up in the end
-STATIC_DIR='_static'
+def my_import(name):
+ """Module importer - taken from the python documentation.
-options_spec = {
- 'parts': directives.nonnegative_int
- }
+ This function allows importing names with dots in them."""
+
+ mod = __import__(name)
+ components = name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
-#-----------------------------------------------------------------------------
-# Main code begins, classes and functions
-
class DotException(Exception):
pass
@@ -105,11 +93,15 @@
path = (path and path.rstrip('.'))
if not path:
path = base
- if not path:
- raise ValueError(
- "Invalid class or module '%s' specified for inheritance diagram" % name)
try:
module = __import__(path, None, None, [])
+ # We must do an import of the fully qualified name. Otherwise if a
+ # subpackage 'a.b' is requested where 'import a' does NOT provide
+ # 'a.b' automatically, then 'a.b' will not be found below. This
+ # second call will force the equivalent of 'import a.b' to happen
+ # after the top-level import above.
+ my_import(fullname)
+
except ImportError:
raise ValueError(
"Could not import class or module '%s' specified for inheritance diagram" % name)
@@ -201,7 +193,6 @@
def _format_node_options(self, options):
return ','.join(["%s=%s" % x for x in options.items()])
-
def _format_graph_options(self, options):
return ''.join(["%s=%s;\n" % x for x in options.items()])
@@ -292,7 +283,6 @@
raise DotException("'dot' returned the errorcode %d" % returncode)
return result
-
class inheritance_diagram(Body, Element):
"""
A docutils node to use as a placeholder for the inheritance
@@ -300,13 +290,16 @@
"""
pass
-
-def inheritance_diagram_directive_run(class_names, options, state):
+def inheritance_diagram_directive(name, arguments, options, content, lineno,
+ content_offset, block_text, state,
+ state_machine):
"""
Run when the inheritance_diagram directive is first encountered.
"""
node = inheritance_diagram()
+ class_names = arguments
+
# Create a graph starting with the list of classes
graph = InheritanceGraph(class_names)
@@ -326,11 +319,9 @@
node['content'] = " ".join(class_names)
return [node]
-
def get_graph_hash(node):
return md5(node['content'] + str(node['parts'])).hexdigest()[-10:]
-
def html_output_graph(self, node):
"""
Output the graph for HTML. This will insert a PNG with clickable
@@ -341,16 +332,13 @@
graph_hash = get_graph_hash(node)
name = "inheritance%s" % graph_hash
- png_path = os.path.join(STATIC_DIR, name + ".png")
+ path = '_images'
+ dest_path = os.path.join(setup.app.builder.outdir, path)
+ if not os.path.exists(dest_path):
+ os.makedirs(dest_path)
+ png_path = os.path.join(dest_path, name + ".png")
+ path = setup.app.builder.imgpath
- path = STATIC_DIR
- source = self.document.attributes['source']
- 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
-
# Create a mapping from fully-qualified class names to URLs.
urls = {}
for child in node:
@@ -366,7 +354,6 @@
return ('<img src="%s/%s.png" usemap="#%s" class="inheritance"/>%s' %
(path, name, name, image_map))
-
def latex_output_graph(self, node):
"""
Output the graph for LaTeX. This will insert a PDF.
@@ -376,13 +363,15 @@
graph_hash = get_graph_hash(node)
name = "inheritance%s" % graph_hash
- pdf_path = os.path.join(STATIC_DIR, name + ".pdf")
+ dest_path = os.path.abspath(os.path.join(setup.app.builder.outdir, '_images'))
+ if not os.path.exists(dest_path):
+ os.makedirs(dest_path)
+ pdf_path = os.path.abspath(os.path.join(dest_path, name + ".pdf"))
graph.run_dot(['-Tpdf', '-o%s' % pdf_path],
name, parts, graph_options={'size': '"6.0,6.0"'})
- return '\\includegraphics{../../%s}' % pdf_path
+ return '\n\\includegraphics{%s}\n\n' % pdf_path
-
def visit_inheritance_diagram(inner_func):
"""
This is just a wrapper around html/latex_output_graph to make it
@@ -402,57 +391,17 @@
node.children = []
return visitor
-
def do_nothing(self, node):
pass
-
def setup(app):
- app.add_node(inheritance_diagram)
+ setup.app = app
+ setup.confdir = app.confdir
- HTMLTranslator.visit_inheritance_diagram = \
- visit_inheritance_diagram(html_output_graph)
- HTMLTranslator.depart_inheritance_diagram = do_nothing
-
- LaTeXTranslator.visit_inheritance_diagram = \
- visit_inheritance_diagram(latex_output_graph)
- LaTeXTranslator.depart_inheritance_diagram = do_nothing
-
-#-----------------------------------------------------------------------------
-# Main code - register the directives. Do it in a way that's compatible with
-# the old and current docutils APIs.
-
-try:
- from docutils.parsers.rst import Directive
-except ImportError:
- # Legacy API
- from docutils.parsers.rst.directives import _directives
-
- def inheritance_diagram_directive(name, arguments, options, content, lineno,
- content_offset, block_text, state,
- state_machine):
- return inheritance_diagram_directive_run(arguments, options, state)
-
- inheritance_diagram_directive.__doc__ = __doc__
- inheritance_diagram_directive.arguments = (1, 100, 0)
- inheritance_diagram_directive.options = options_spec
- inheritance_diagram_directive.content = 0
- _directives['inheritance-diagram'] = inheritance_diagram_directive
-
-else:
- # New API
- class inheritance_diagram_directive(Directive):
- has_content = False
- required_arguments = 1
- optional_arguments = 100
- final_argument_whitespace = False
- option_spec = options_spec
-
- def run(self):
- return inheritance_diagram_directive_run(
- self.arguments, self.options, self.state)
-
- inheritance_diagram_directive.__doc__ = __doc__
-
- directives.register_directive('inheritance-diagram',
- inheritance_diagram_directive)
+ app.add_node(
+ inheritance_diagram,
+ latex=(visit_inheritance_diagram(latex_output_graph), do_nothing),
+ html=(visit_inheritance_diagram(html_output_graph), do_nothing))
+ app.add_directive(
+ 'inheritance-diagram', inheritance_diagram_directive,
+ False, (1, 100, 0), parts = directives.nonnegative_int)
Deleted: trunk/py4science/examples/sphinx_template2/tools/sphinxext/mathmpl.py
===================================================================
--- trunk/py4science/examples/sphinx_template2/tools/sphinxext/mathmpl.py 2009-03-17 19:45:05 UTC (rev 6986)
+++ trunk/py4science/examples/sphinx_template2/tools/sphinxext/mathmpl.py 2009-03-18 07:39:43 UTC (rev 6987)
@@ -1,166 +0,0 @@
-"""matplotlib-based directive for math rendering in reST using sphinx.
-
-To use this extension, add ``mathmpl`` to the list of extensions in
-:file:`conf.py`.
-
-*Warning*: this code is currently untested. ***MAY NOT WORK***
-
-Note:
-
-Current SVN versions of Sphinx now include built-in support for math.
-There are two flavors:
-
- - pngmath: uses dvipng to render the equation
-
- - jsmath: renders the math in the browser using Javascript
-
-To use these extensions instead of the code in this module, add
-``sphinx.ext.pngmath`` or ``sphinx.ext.jsmath`` to the list of extensions in
-:file:`conf.py`.
-
-All three of these options for math are designed to behave in the same
-way.
-"""
-
-import os
-try:
- from hashlib import md5
-except ImportError:
- from md5 import md5
-
-from docutils import nodes
-from docutils.parsers.rst import directives
-from docutils.writers.html4css1 import HTMLTranslator
-from sphinx.latexwriter import LaTeXTranslator
-import warnings
-
-# Constants
-STATIC_DIR='_static'
-
-# Define LaTeX math node:
-class latex_math(nodes.General, nodes.Element):
- pass
-
-def fontset_choice(arg):
- return directives.choice(arg, ['cm', 'stix', 'stixsans'])
-
-options_spec = {'fontset': fontset_choice}
-
-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
- node['fontset'] = options.get('fontset', 'cm')
- return [node], []
-math_role.options = options_spec
-
-def math_directive_run(content, block_text, options):
- latex = ''.join(content)
- node = latex_math(block_text)
- node['latex'] = latex
- node['fontset'] = options.get('fontset', 'cm')
- 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):
- return math_directive_run(content, block_text, options)
- math_directive.arguments = None
- math_directive.options = options_spec
- math_directive.content = 1
- _directives['math'] = math_directive
-else:
- class math_directive(Directive):
- has_content = True
- option_spec = options_spec
-
- def run(self):
- return math_directive_run(self.content, self.block_text,
- self.options)
- 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 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, fontset='cm'):
- latex = "$%s$" % latex
- orig_fontset = rcParams['mathtext.fontset']
- rcParams['mathtext.fontset'] = fontset
- if os.path.exists(filename):
- depth = mathtext_parser.get_depth(latex, dpi=100)
- else:
- print latex.encode("ascii", "backslashreplace")
- try:
- depth = mathtext_parser.to_png(filename, latex, dpi=100)
- except:
- warnings.warn("Could not render math expression %s" % latex,
- Warning)
- depth = 0
- rcParams['mathtext.fontset'] = orig_fontset
- return depth
-
-# LaTeX to HTML translation stuff:
-def latex2html(node, source):
- inline = isinstance(node.parent, nodes.TextElement)
- latex = node['latex']
- name = 'math-%s' % md5(latex).hexdigest()[-10:]
- dest = os.path.join(STATIC_DIR, name + ".png")
-
- depth = latex2png(latex, dest, node.get('fontset',
- rcParams['mathtext.fontset']))
-
- path = STATIC_DIR
- count = source.split('/doc/')[-1].count('/')
- for i in range(count):
- if os.path.exists(path): break
- path = '../'+path
- path = '../'+path #s...
[truncated message content] |
|
From: <ef...@us...> - 2009-03-17 19:45:15
|
Revision: 6986
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6986&view=rev
Author: efiring
Date: 2009-03-17 19:45:05 +0000 (Tue, 17 Mar 2009)
Log Message:
-----------
Merged revisions 6984-6985 via svnmerge from
https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint
........
r6984 | efiring | 2009-03-17 09:15:01 -1000 (Tue, 17 Mar 2009) | 4 lines
Fix bug in alpha handling.
The alpha kwarg was multiplying the existing alpha instead
of replacing it. Thanks to Jae-Joon Lee.
........
r6985 | efiring | 2009-03-17 09:34:27 -1000 (Tue, 17 Mar 2009) | 2 lines
In contourf, don't accidentally set the edgecolor.
........
Modified Paths:
--------------
trunk/matplotlib/CHANGELOG
trunk/matplotlib/lib/matplotlib/colors.py
trunk/matplotlib/lib/matplotlib/contour.py
Property Changed:
----------------
trunk/matplotlib/
trunk/matplotlib/doc/pyplots/README
trunk/matplotlib/doc/sphinxext/gen_gallery.py
trunk/matplotlib/doc/sphinxext/gen_rst.py
trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py
trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py
trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py
Property changes on: trunk/matplotlib
___________________________________________________________________
Modified: svnmerge-integrated
- /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6972
+ /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6985
Modified: svn:mergeinfo
- /branches/v0_91_maint:5753-5771
/branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972
+ /branches/v0_91_maint:5753-5771
/branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2009-03-17 19:34:27 UTC (rev 6985)
+++ trunk/matplotlib/CHANGELOG 2009-03-17 19:45:05 UTC (rev 6986)
@@ -1,4 +1,7 @@
-2009-03-14 Added 'lightsource' class to colors module for
+2009-03-17 Fix bugs in edge color handling by contourf, found
+ by Jae-Joon Lee. - EF
+
+2009-03-14 Added 'lightsource' class to colors module for
creating shaded relief maps. shading_example.py
added to illustrate usage. - JSW
Property changes on: trunk/matplotlib/doc/pyplots/README
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972
+ /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985
Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771
/branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972
+ /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771
/branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985
Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771
/branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972
+ /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771
/branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985
Modified: trunk/matplotlib/lib/matplotlib/colors.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/colors.py 2009-03-17 19:34:27 UTC (rev 6985)
+++ trunk/matplotlib/lib/matplotlib/colors.py 2009-03-17 19:45:05 UTC (rev 6986)
@@ -331,7 +331,7 @@
return tuple(arg)
if alpha < 0.0 or alpha > 1.0:
raise ValueError("alpha must be in range 0-1")
- return arg[0], arg[1], arg[2], arg[3] * alpha
+ return arg[0], arg[1], arg[2], alpha
r,g,b = arg[:3]
if [x for x in (r,g,b) if (float(x) < 0) or (x > 1)]:
raise ValueError('number in rbg sequence outside 0-1 range')
Modified: trunk/matplotlib/lib/matplotlib/contour.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/contour.py 2009-03-17 19:34:27 UTC (rev 6985)
+++ trunk/matplotlib/lib/matplotlib/contour.py 2009-03-17 19:45:05 UTC (rev 6986)
@@ -629,8 +629,10 @@
self.to_rgba(self.cvalues, alpha=self.alpha)]
self.tcolors = tcolors
for color, collection in zip(tcolors, self.collections):
- collection.set_alpha(self.alpha)
- collection.set_color(color)
+ if self.filled:
+ collection.set_facecolor(color)
+ else:
+ collection.set_color(color)
for label, cv in zip(self.labelTexts, self.labelCValues):
label.set_alpha(self.alpha)
label.set_color(self.labelMappable.to_rgba(cv))
Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771
/branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972
+ /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771
/branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985
Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771
/branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972
+ /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771
/branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985
Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771
/branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972
+ /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771
/branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ef...@us...> - 2009-03-17 19:34:45
|
Revision: 6985
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6985&view=rev
Author: efiring
Date: 2009-03-17 19:34:27 +0000 (Tue, 17 Mar 2009)
Log Message:
-----------
In contourf, don't accidentally set the edgecolor.
Modified Paths:
--------------
branches/v0_98_5_maint/CHANGELOG
branches/v0_98_5_maint/lib/matplotlib/contour.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG 2009-03-17 19:15:01 UTC (rev 6984)
+++ branches/v0_98_5_maint/CHANGELOG 2009-03-17 19:34:27 UTC (rev 6985)
@@ -1,3 +1,6 @@
+2009-03-17 Fix bugs in edge color handling by contourf, found
+ by Jae-Joon Lee. - EF
+
2009-03-11 Ensure wx version >= 2.8; thanks to Sandro Tosi and
Chris Barker. - EF
Modified: branches/v0_98_5_maint/lib/matplotlib/contour.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/contour.py 2009-03-17 19:15:01 UTC (rev 6984)
+++ branches/v0_98_5_maint/lib/matplotlib/contour.py 2009-03-17 19:34:27 UTC (rev 6985)
@@ -629,8 +629,10 @@
self.to_rgba(self.cvalues, alpha=self.alpha)]
self.tcolors = tcolors
for color, collection in zip(tcolors, self.collections):
- collection.set_alpha(self.alpha)
- collection.set_color(color)
+ if self.filled:
+ collection.set_facecolor(color)
+ else:
+ collection.set_color(color)
for label, cv in zip(self.labelTexts, self.labelCValues):
label.set_alpha(self.alpha)
label.set_color(self.labelMappable.to_rgba(cv))
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ef...@us...> - 2009-03-17 19:15:44
|
Revision: 6984
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6984&view=rev
Author: efiring
Date: 2009-03-17 19:15:01 +0000 (Tue, 17 Mar 2009)
Log Message:
-----------
Fix bug in alpha handling.
The alpha kwarg was multiplying the existing alpha instead
of replacing it. Thanks to Jae-Joon Lee.
Modified Paths:
--------------
branches/v0_98_5_maint/lib/matplotlib/colors.py
Modified: branches/v0_98_5_maint/lib/matplotlib/colors.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/colors.py 2009-03-17 11:49:57 UTC (rev 6983)
+++ branches/v0_98_5_maint/lib/matplotlib/colors.py 2009-03-17 19:15:01 UTC (rev 6984)
@@ -331,7 +331,7 @@
return tuple(arg)
if alpha < 0.0 or alpha > 1.0:
raise ValueError("alpha must be in range 0-1")
- return arg[0], arg[1], arg[2], arg[3] * alpha
+ return arg[0], arg[1], arg[2], alpha
r,g,b = arg[:3]
if [x for x in (r,g,b) if (float(x) < 0) or (x > 1)]:
raise ValueError('number in rbg sequence outside 0-1 range')
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2009-03-17 11:50:02
|
Revision: 6983
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6983&view=rev
Author: mdboom
Date: 2009-03-17 11:49:57 +0000 (Tue, 17 Mar 2009)
Log Message:
-----------
Bugfix for Mac OS-X backend build.
Modified Paths:
--------------
trunk/matplotlib/setupext.py
Modified: trunk/matplotlib/setupext.py
===================================================================
--- trunk/matplotlib/setupext.py 2009-03-16 19:32:22 UTC (rev 6982)
+++ trunk/matplotlib/setupext.py 2009-03-17 11:49:57 UTC (rev 6983)
@@ -1160,12 +1160,16 @@
global BUILT_MACOSX
if BUILT_MACOSX: return # only build it if you you haven't already
deps = ['src/_macosx.m',
+ 'CXX/cxx_extensions.cxx',
+ 'CXX/cxxextensions.c',
+ 'CXX/cxxsupport.cxx',
+ 'CXX/IndirectPythonInterface.cxx',
'src/agg_py_transforms.cpp',
- 'src/path_cleanup.cpp',
- 'src/_path.cpp']
+ 'src/path_cleanup.cpp']
module = Extension('matplotlib.backends._macosx',
deps,
extra_link_args = ['-framework','Cocoa'],
+ define_macros=[('PY_ARRAY_UNIQUE_SYMBOL', 'MPL_ARRAY_API')]
)
add_numpy_flags(module)
add_agg_flags(module)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-16 19:32:33
|
Revision: 6982
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6982&view=rev
Author: jswhit
Date: 2009-03-16 19:32:22 +0000 (Mon, 16 Mar 2009)
Log Message:
-----------
fix small bug in relief plot shading algorithm
Modified Paths:
--------------
trunk/matplotlib/examples/pylab_examples/shading_example.py
trunk/matplotlib/lib/matplotlib/colors.py
Modified: trunk/matplotlib/examples/pylab_examples/shading_example.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/shading_example.py 2009-03-16 17:22:07 UTC (rev 6981)
+++ trunk/matplotlib/examples/pylab_examples/shading_example.py 2009-03-16 19:32:22 UTC (rev 6982)
@@ -9,10 +9,10 @@
# (http://gmt.soest.hawaii.edu/gmt/doc/gmt/html/GMT_Docs/node145.html)
# test data
-X,Y=np.mgrid[-5:5:0.1,-5:5:0.1]
-Z=X+np.sin(X**2+Y**2)
+X,Y=np.mgrid[-5:5:0.05,-5:5:0.05]
+Z=np.sqrt(X**2+Y**2)+np.sin(X**2+Y**2)
# creat light source object.
-ls = lightsource(azdeg=270,altdeg=60)
+ls = lightsource(azdeg=0,altdeg=65)
# shade data, creating an rgb array.
rgb = ls.shade(Z,plt.cm.copper)
# plot un-shaded and shaded images.
Modified: trunk/matplotlib/lib/matplotlib/colors.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/colors.py 2009-03-16 17:22:07 UTC (rev 6981)
+++ trunk/matplotlib/lib/matplotlib/colors.py 2009-03-16 19:32:22 UTC (rev 6982)
@@ -1018,11 +1018,11 @@
# modify hsv values to simulate illumination.
hsv[:,:,1] = np.where(np.logical_and(np.abs(hsv[:,:,1])>1.e-10,intensity>0),\
(1.-intensity)*hsv[:,:,1]+intensity*self.hsv_max_sat, hsv[:,:,1])
- hsv[:,:,2] = np.where(intensity > 0, (1.-intensity)*hsv[:,:,1] +\
+ hsv[:,:,2] = np.where(intensity > 0, (1.-intensity)*hsv[:,:,2] +\
intensity*self.hsv_max_val, hsv[:,:,2])
hsv[:,:,1] = np.where(np.logical_and(np.abs(hsv[:,:,1])>1.e-10,intensity<0),\
(1.+intensity)*hsv[:,:,1]-intensity*self.hsv_min_sat, hsv[:,:,1])
- hsv[:,:,2] = np.where(intensity < 0, (1.+intensity)*hsv[:,:,1] -\
+ hsv[:,:,2] = np.where(intensity < 0, (1.+intensity)*hsv[:,:,2] -\
intensity*self.hsv_min_val, hsv[:,:,2])
hsv[:,:,1:] = np.where(hsv[:,:,1:]<0.,0,hsv[:,:,1:])
hsv[:,:,1:] = np.where(hsv[:,:,1:]>1.,1,hsv[:,:,1:])
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ry...@us...> - 2009-03-16 17:22:22
|
Revision: 6981
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6981&view=rev
Author: ryanmay
Date: 2009-03-16 17:22:07 +0000 (Mon, 16 Mar 2009)
Log Message:
-----------
Remove duplicate debugging print.
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/backends/backend_gtkagg.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gtkagg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_gtkagg.py 2009-03-16 15:59:45 UTC (rev 6980)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_gtkagg.py 2009-03-16 17:22:07 UTC (rev 6981)
@@ -88,7 +88,6 @@
if DEBUG: print 'FigureCanvasGTKAgg.render_figure done'
def blit(self, bbox=None):
- if DEBUG: print 'FigureCanvasGTKAgg.blit'
if DEBUG: print 'FigureCanvasGTKAgg.blit', self._pixmap
agg_to_gtk_drawable(self._pixmap, self.renderer._renderer, bbox)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-16 15:59:57
|
Revision: 6980
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6980&view=rev
Author: jswhit
Date: 2009-03-16 15:59:45 +0000 (Mon, 16 Mar 2009)
Log Message:
-----------
add some comments.
Modified Paths:
--------------
trunk/toolkits/basemap/examples/plotmap_shaded.py
Modified: trunk/toolkits/basemap/examples/plotmap_shaded.py
===================================================================
--- trunk/toolkits/basemap/examples/plotmap_shaded.py 2009-03-14 23:44:09 UTC (rev 6979)
+++ trunk/toolkits/basemap/examples/plotmap_shaded.py 2009-03-16 15:59:45 UTC (rev 6980)
@@ -26,12 +26,15 @@
# transform to nx x ny regularly spaced native projection grid
nx = int((m.xmax-m.xmin)/40000.)+1; ny = int((m.ymax-m.ymin)/40000.)+1
topodat,x,y = m.transform_scalar(topoin,lons,lats,nx,ny,returnxy=True)
+# create light source object.
ls = lightsource(azdeg = 90, altdeg = 20)
-print topodat.shape
+# convert data to rgb array including shading from light source.
+# (must specify color map)
rgb = ls.shade(topodat, plt.cm.jet)
# create the figure.
fig=plt.figure(figsize=(8,8))
-# plot image over map with imshow.
+# plot image over map with imshow (pass rgb values
+# that include light shading).
im = m.imshow(rgb)
# draw coastlines and political boundaries.
m.drawcoastlines()
@@ -44,5 +47,4 @@
m.drawmeridians(meridians,labels=[1,1,0,1])
# set title.
plt.title('ETOPO Shaded Relief - Lambert Conformal Conic')
-#plt.savefig('plotmap.pdf')
plt.show()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-14 23:44:15
|
Revision: 6979
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6979&view=rev
Author: jswhit
Date: 2009-03-14 23:44:09 +0000 (Sat, 14 Mar 2009)
Log Message:
-----------
change sun elevation angle.
Modified Paths:
--------------
trunk/matplotlib/examples/pylab_examples/shading_example.py
Modified: trunk/matplotlib/examples/pylab_examples/shading_example.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/shading_example.py 2009-03-14 13:54:37 UTC (rev 6978)
+++ trunk/matplotlib/examples/pylab_examples/shading_example.py 2009-03-14 23:44:09 UTC (rev 6979)
@@ -12,7 +12,7 @@
X,Y=np.mgrid[-5:5:0.1,-5:5:0.1]
Z=X+np.sin(X**2+Y**2)
# creat light source object.
-ls = lightsource(azdeg=270,altdeg=20)
+ls = lightsource(azdeg=270,altdeg=60)
# shade data, creating an rgb array.
rgb = ls.shade(Z,plt.cm.copper)
# plot un-shaded and shaded images.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-14 13:54:39
|
Revision: 6978
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6978&view=rev
Author: jswhit
Date: 2009-03-14 13:54:37 +0000 (Sat, 14 Mar 2009)
Log Message:
-----------
docstring fix for lightsource class
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/colors.py
Modified: trunk/matplotlib/lib/matplotlib/colors.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/colors.py 2009-03-14 13:53:24 UTC (rev 6977)
+++ trunk/matplotlib/lib/matplotlib/colors.py 2009-03-14 13:54:37 UTC (rev 6978)
@@ -959,7 +959,7 @@
"""
Create a light source coming from the specified azimuth and elevation.
Angles are in degrees, with the azimuth measured
- clockwise from south and elevation up from the zero plane of the surface.
+ clockwise from north and elevation up from the zero plane of the surface.
The :meth:`shade` is used to produce rgb values for a shaded relief image
given a data array.
"""
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-14 13:53:42
|
Revision: 6977
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6977&view=rev
Author: jswhit
Date: 2009-03-14 13:53:24 +0000 (Sat, 14 Mar 2009)
Log Message:
-----------
added shaded relief plot example.
Modified Paths:
--------------
trunk/toolkits/basemap/Changelog
trunk/toolkits/basemap/MANIFEST.in
trunk/toolkits/basemap/examples/README
Added Paths:
-----------
trunk/toolkits/basemap/examples/plotmap_shaded.py
Modified: trunk/toolkits/basemap/Changelog
===================================================================
--- trunk/toolkits/basemap/Changelog 2009-03-14 13:49:09 UTC (rev 6976)
+++ trunk/toolkits/basemap/Changelog 2009-03-14 13:53:24 UTC (rev 6977)
@@ -1,4 +1,5 @@
version 0.99.4 (not yet released)
+ * added new example "plotmap_shaded.py" (shaded relief plot).
* added new example "plothighsandlows.py".
* add fix_aspect kwarg to Basemap.__init__, when False
axes.set_aspect is set to 'auto' instead of default 'equal'.
Modified: trunk/toolkits/basemap/MANIFEST.in
===================================================================
--- trunk/toolkits/basemap/MANIFEST.in 2009-03-14 13:49:09 UTC (rev 6976)
+++ trunk/toolkits/basemap/MANIFEST.in 2009-03-14 13:53:24 UTC (rev 6977)
@@ -40,6 +40,7 @@
include examples/plotmap.py
include examples/plotmap_oo.py
include examples/plotmap_masked.py
+include examples/plotmap_shaded.py
include examples/contour_demo.py
include examples/customticks.py
include examples/quiver_demo.py
Modified: trunk/toolkits/basemap/examples/README
===================================================================
--- trunk/toolkits/basemap/examples/README 2009-03-14 13:49:09 UTC (rev 6976)
+++ trunk/toolkits/basemap/examples/README 2009-03-14 13:53:24 UTC (rev 6977)
@@ -20,6 +20,9 @@
in test.py) which shows the ETOPO topography as an image on a Lambert
Conformal projection (using imshow).
+plotmap_shaded.py shows how to make a 'shaded relief' plot by specifying
+the location of a lightsource.
+
plotmap_oo.py is a version of plotmap.py that does not import pylab - it uses
the matplotlib OO interface instead.
Added: trunk/toolkits/basemap/examples/plotmap_shaded.py
===================================================================
--- trunk/toolkits/basemap/examples/plotmap_shaded.py (rev 0)
+++ trunk/toolkits/basemap/examples/plotmap_shaded.py 2009-03-14 13:53:24 UTC (rev 6977)
@@ -0,0 +1,48 @@
+# make shaded relief plot of etopo bathymetry/topography data on
+# lambert conformal conic map projection.
+
+# the data is interpolated to the native projection grid.
+
+from mpl_toolkits.basemap import Basemap, shiftgrid
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.mlab as mlab
+from matplotlib.colors import lightsource
+
+# read in topo data (on a regular lat/lon grid)
+# longitudes go from 20 to 380.
+topoin = mlab.load('etopo20data.gz')
+lons = mlab.load('etopo20lons.gz')
+lats = mlab.load('etopo20lats.gz')
+# shift data so lons go from -180 to 180 instead of 20 to 380.
+topoin,lons = shiftgrid(180.,topoin,lons,start=False)
+
+# setup of basemap ('lcc' = lambert conformal conic).
+# use major and minor sphere radii from WGS84 ellipsoid.
+m = Basemap(llcrnrlon=-145.5,llcrnrlat=1.,urcrnrlon=-2.566,urcrnrlat=46.352,\
+ rsphere=(6378137.00,6356752.3142),\
+ resolution='l',area_thresh=1000.,projection='lcc',\
+ lat_1=50.,lon_0=-107.)
+# transform to nx x ny regularly spaced native projection grid
+nx = int((m.xmax-m.xmin)/40000.)+1; ny = int((m.ymax-m.ymin)/40000.)+1
+topodat,x,y = m.transform_scalar(topoin,lons,lats,nx,ny,returnxy=True)
+ls = lightsource(azdeg = 90, altdeg = 20)
+print topodat.shape
+rgb = ls.shade(topodat, plt.cm.jet)
+# create the figure.
+fig=plt.figure(figsize=(8,8))
+# plot image over map with imshow.
+im = m.imshow(rgb)
+# draw coastlines and political boundaries.
+m.drawcoastlines()
+m.drawcountries()
+# draw parallels and meridians.
+# label on left, right and bottom of map.
+parallels = np.arange(0.,80,20.)
+m.drawparallels(parallels,labels=[1,1,0,1])
+meridians = np.arange(10.,360.,30.)
+m.drawmeridians(meridians,labels=[1,1,0,1])
+# set title.
+plt.title('ETOPO Shaded Relief - Lambert Conformal Conic')
+#plt.savefig('plotmap.pdf')
+plt.show()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-14 13:49:16
|
Revision: 6976
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6976&view=rev
Author: jswhit
Date: 2009-03-14 13:49:09 +0000 (Sat, 14 Mar 2009)
Log Message:
-----------
fix bug in hsv_to_rgb (returned rgb array wrong shape)
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/colors.py
Modified: trunk/matplotlib/lib/matplotlib/colors.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/colors.py 2009-03-14 13:22:32 UTC (rev 6975)
+++ trunk/matplotlib/lib/matplotlib/colors.py 2009-03-14 13:49:09 UTC (rev 6976)
@@ -951,7 +951,9 @@
r[idx] = v[idx]; g[idx] = p[idx]; b[idx] = q[idx]
idx = s == 0
r[idx] = v[idx]; g[idx] = v[idx]; b[idx] = v[idx]
- return np.array((r,g,b)).T
+ rgb = np.empty_like(hsv)
+ rgb[:,:,0]=r; rgb[:,:,1]=g; rgb[:,:,2]=b
+ return rgb
class lightsource(object):
"""
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-14 13:22:41
|
Revision: 6975
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6975&view=rev
Author: jswhit
Date: 2009-03-14 13:22:32 +0000 (Sat, 14 Mar 2009)
Log Message:
-----------
added 'lightsource' class to colors module, shading_example.py
to illustrate it's usage to create shaded relief maps with imshow.
Modified Paths:
--------------
trunk/matplotlib/CHANGELOG
trunk/matplotlib/lib/matplotlib/colors.py
Added Paths:
-----------
trunk/matplotlib/examples/pylab_examples/shading_example.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2009-03-13 17:13:49 UTC (rev 6974)
+++ trunk/matplotlib/CHANGELOG 2009-03-14 13:22:32 UTC (rev 6975)
@@ -1,3 +1,7 @@
+2009-03-14 Added 'lightsource' class to colors module for
+ creating shaded relief maps. shading_example.py
+ added to illustrate usage. - JSW
+
2009-03-11 Ensure wx version >= 2.8; thanks to Sandro Tosi and
Chris Barker. - EF
Added: trunk/matplotlib/examples/pylab_examples/shading_example.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/shading_example.py (rev 0)
+++ trunk/matplotlib/examples/pylab_examples/shading_example.py 2009-03-14 13:22:32 UTC (rev 6975)
@@ -0,0 +1,28 @@
+import numpy as np
+import matplotlib.pyplot as plt
+from matplotlib.colors import lightsource
+
+# example showing how to make shaded relief plots
+# like mathematica
+# (http://reference.wolfram.com/mathematica/ref/ReliefPlot.html )
+# or Generic Mapping Tools
+# (http://gmt.soest.hawaii.edu/gmt/doc/gmt/html/GMT_Docs/node145.html)
+
+# test data
+X,Y=np.mgrid[-5:5:0.1,-5:5:0.1]
+Z=X+np.sin(X**2+Y**2)
+# creat light source object.
+ls = lightsource(azdeg=270,altdeg=20)
+# shade data, creating an rgb array.
+rgb = ls.shade(Z,plt.cm.copper)
+# plot un-shaded and shaded images.
+plt.figure(figsize=(12,5))
+plt.subplot(121)
+plt.imshow(Z,cmap=plt.cm.copper)
+plt.title('imshow')
+plt.xticks([]); plt.yticks([])
+plt.subplot(122)
+plt.imshow(rgb)
+plt.title('imshow with shading')
+plt.xticks([]); plt.yticks([])
+plt.show()
Modified: trunk/matplotlib/lib/matplotlib/colors.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/colors.py 2009-03-13 17:13:49 UTC (rev 6974)
+++ trunk/matplotlib/lib/matplotlib/colors.py 2009-03-14 13:22:32 UTC (rev 6975)
@@ -900,3 +900,130 @@
# compatibility with earlier class names that violated convention:
normalize = Normalize
no_norm = NoNorm
+
+def rgb_to_hsv(arr):
+ """
+ convert rgb values in a numpy array to hsv values
+ input and output arrays should have shape (M,N,3)
+ """
+ out = np.empty_like(arr)
+ arr_max = arr.max(-1)
+ delta = arr.ptp(-1)
+ s = delta / arr_max
+ s[delta==0] = 0
+ # red is max
+ idx = (arr[:,:,0] == arr_max)
+ out[idx, 0] = (arr[idx, 1] - arr[idx, 2]) / delta[idx]
+ # green is max
+ idx = (arr[:,:,1] == arr_max)
+ out[idx, 0] = 2. + (arr[idx, 2] - arr[idx, 0] ) / delta[idx]
+ # blue is max
+ idx = (arr[:,:,2] == arr_max)
+ out[idx, 0] = 4. + (arr[idx, 0] - arr[idx, 1] ) / delta[idx]
+ out[:,:,0] = (out[:,:,0]/6.0) % 1.0
+ out[:,:,1] = s
+ out[:,:,2] = arr_max
+ return out
+
+def hsv_to_rgb(hsv):
+ """
+ convert hsv values in a numpy array to rgb values
+ both input and output arrays have shape (M,N,3)
+ """
+ h = hsv[:,:,0]; s = hsv[:,:,1]; v = hsv[:,:,2]
+ r = np.empty_like(h); g = np.empty_like(h); b = np.empty_like(h)
+ i = (h*6.0).astype(np.int)
+ f = (h*6.0) - i
+ p = v*(1.0 - s)
+ q = v*(1.0 - s*f)
+ t = v*(1.0 - s*(1.0-f))
+ idx = i%6 == 0
+ r[idx] = v[idx]; g[idx] = t[idx]; b[idx] = p[idx]
+ idx = i == 1
+ r[idx] = q[idx]; g[idx] = v[idx]; b[idx] = p[idx]
+ idx = i == 2
+ r[idx] = p[idx]; g[idx] = v[idx]; b[idx] = t[idx]
+ idx = i == 3
+ r[idx] = p[idx]; g[idx] = q[idx]; b[idx] = v[idx]
+ idx = i == 4
+ r[idx] = t[idx]; g[idx] = p[idx]; b[idx] = v[idx]
+ idx = i == 5
+ r[idx] = v[idx]; g[idx] = p[idx]; b[idx] = q[idx]
+ idx = s == 0
+ r[idx] = v[idx]; g[idx] = v[idx]; b[idx] = v[idx]
+ return np.array((r,g,b)).T
+
+class lightsource(object):
+ """
+ Create a light source coming from the specified azimuth and elevation.
+ Angles are in degrees, with the azimuth measured
+ clockwise from south and elevation up from the zero plane of the surface.
+ The :meth:`shade` is used to produce rgb values for a shaded relief image
+ given a data array.
+ """
+ def __init__(self,azdeg=315,altdeg=45,\
+ hsv_min_val=0,hsv_max_val=1,hsv_min_sat=1,hsv_max_sat=0):
+ """
+ Specify the azimuth (measured clockwise from south) and altitude
+ (measured up from the plane of the surface) of the light source
+ in degrees.
+
+ The color of the resulting image will be darkened
+ by moving the (s,v) values (in hsv colorspace) toward
+ (hsv_min_sat, hsv_min_val) in the shaded regions, or
+ lightened by sliding (s,v) toward
+ (hsv_max_sat hsv_max_val) in regions that are illuminated.
+ The default extremes are chose so that completely shaded points
+ are nearly black (s = 1, v = 0) and completely illuminated points
+ are nearly white (s = 0, v = 1).
+ """
+ self.azdeg = azdeg
+ self.altdeg = altdeg
+ self.hsv_min_val = hsv_min_val
+ self.hsv_max_val = hsv_max_val
+ self.hsv_min_sat = hsv_min_sat
+ self.hsv_max_sat = hsv_max_sat
+
+ def shade(self,data,cmap):
+ """
+ Take the input data array, convert to HSV values in the
+ given colormap, then adjust those color values
+ to given the impression of a shaded relief map with a
+ specified light source.
+ RGBA values are returned, which can then be used to
+ plot the shaded image with imshow.
+ """
+ # imagine an artificial sun placed at infinity in
+ # some azimuth and elevation position illuminating our surface. The parts of
+ # the surface that slope toward the sun should brighten while those sides
+ # facing away should become darker.
+ # convert alt, az to radians
+ az = self.azdeg*np.pi/180.0
+ alt = self.altdeg*np.pi/180.0
+ # gradient in x and y directions
+ dx, dy = np.gradient(data)
+ slope = 0.5*np.pi - np.arctan(np.hypot(dx, dy))
+ aspect = np.arctan2(dx, dy)
+ intensity = np.sin(alt)*np.sin(slope) + np.cos(alt)*np.cos(slope)*np.cos(-az -\
+ aspect - 0.5*np.pi)
+ # rescale to interval -1,1
+ # +1 means maximum sun exposure and -1 means complete shade.
+ intensity = (intensity - intensity.min())/(intensity.max() - intensity.min())
+ intensity = 2.*intensity - 1.
+ # convert to rgb, then rgb to hsv
+ rgb = cmap((data-data.min())/(data.max()-data.min()))
+ hsv = rgb_to_hsv(rgb[:,:,0:3])
+ # modify hsv values to simulate illumination.
+ hsv[:,:,1] = np.where(np.logical_and(np.abs(hsv[:,:,1])>1.e-10,intensity>0),\
+ (1.-intensity)*hsv[:,:,1]+intensity*self.hsv_max_sat, hsv[:,:,1])
+ hsv[:,:,2] = np.where(intensity > 0, (1.-intensity)*hsv[:,:,1] +\
+ intensity*self.hsv_max_val, hsv[:,:,2])
+ hsv[:,:,1] = np.where(np.logical_and(np.abs(hsv[:,:,1])>1.e-10,intensity<0),\
+ (1.+intensity)*hsv[:,:,1]-intensity*self.hsv_min_sat, hsv[:,:,1])
+ hsv[:,:,2] = np.where(intensity < 0, (1.+intensity)*hsv[:,:,1] -\
+ intensity*self.hsv_min_val, hsv[:,:,2])
+ hsv[:,:,1:] = np.where(hsv[:,:,1:]<0.,0,hsv[:,:,1:])
+ hsv[:,:,1:] = np.where(hsv[:,:,1:]>1.,1,hsv[:,:,1:])
+ # convert modified hsv back to rgb.
+ rgb[:,:,0:3] = hsv_to_rgb(hsv)
+ return rgb
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2009-03-13 17:14:03
|
Revision: 6974
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6974&view=rev
Author: mdboom
Date: 2009-03-13 17:13:49 +0000 (Fri, 13 Mar 2009)
Log Message:
-----------
Commit Michiel de Hoon's integration of path simplification into the
Mac OS-X backend. Thanks, Michiel!
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py
trunk/matplotlib/setupext.py
trunk/matplotlib/src/_macosx.m
trunk/matplotlib/src/path_cleanup.h
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py 2009-03-11 19:45:23 UTC (rev 6973)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_macosx.py 2009-03-13 17:13:49 UTC (rev 6974)
@@ -128,13 +128,13 @@
def get_text_width_height_descent(self, s, prop, ismath):
if ismath=='TeX':
- # TODO: handle props
+ # todo: handle props
size = prop.get_size_in_points()
texmanager = self.get_texmanager()
- Z = texmanager.get_grey(s, size, self.dpi)
- m,n = Z.shape
- # TODO: handle descent; This is based on backend_agg.py
- return n, m, 0
+ fontsize = prop.get_size_in_points()
+ w, h, d = texmanager.get_text_width_height_descent(s, fontsize,
+ renderer=self)
+ return w, h, d
if ismath:
ox, oy, width, height, descent, fonts, used_characters = \
self.mathtext_parser.parse(s, self.dpi, prop)
@@ -143,7 +143,8 @@
size = prop.get_size_in_points()
weight = prop.get_weight()
style = prop.get_style()
- return self.gc.get_text_width_height_descent(unicode(s), family, size, weight, style)
+ width, height, descent = self.gc.get_text_width_height_descent(unicode(s), family, size, weight, style)
+ return width, height, 0.0*descent
def flipy(self):
return False
@@ -230,6 +231,14 @@
key_press_event, and key_release_event are called from there.
"""
+ filetypes = FigureCanvasBase.filetypes.copy()
+ filetypes['bmp'] = 'Windows bitmap'
+ filetypes['jpeg'] = 'JPEG'
+ filetypes['jpg'] = 'JPEG'
+ filetypes['gif'] = 'Graphics Interchange Format'
+ filetypes['tif'] = 'Tagged Image Format File'
+ filetypes['tiff'] = 'Tagged Image Format File'
+
def __init__(self, figure):
FigureCanvasBase.__init__(self, figure)
width, height = self.get_width_height()
@@ -243,55 +252,41 @@
height /= dpi
self.figure.set_size_inches(width, height)
- def print_figure(self, filename, dpi=None, facecolor='w', edgecolor='w',
- orientation='portrait', **kwargs):
- if dpi is None: dpi = matplotlib.rcParams['savefig.dpi']
+ def _print_bitmap(self, filename, *args, **kwargs):
+ # In backend_bases.py, print_figure changes the dpi of the figure.
+ # But since we are essentially redrawing the picture, we need the
+ # original dpi. Pick it up from the renderer.
+ dpi = kwargs['dpi']
+ old_dpi = self.figure.dpi
+ self.figure.dpi = self.renderer.dpi
+ width, height = self.figure.get_size_inches()
+ width, height = width*dpi, height*dpi
filename = unicode(filename)
- root, ext = os.path.splitext(filename)
- ext = ext[1:].lower()
- if not ext:
- ext = "png"
- filename = root + "." + ext
- if ext=="jpg": ext = "jpeg"
+ self.write_bitmap(filename, width, height)
+ self.figure.dpi = old_dpi
- # save the figure settings
- origfacecolor = self.figure.get_facecolor()
- origedgecolor = self.figure.get_edgecolor()
+ def print_bmp(self, filename, *args, **kwargs):
+ self._print_bitmap(filename, *args, **kwargs)
- # set the new parameters
- self.figure.set_facecolor(facecolor)
- self.figure.set_edgecolor(edgecolor)
+ def print_jpg(self, filename, *args, **kwargs):
+ self._print_bitmap(filename, *args, **kwargs)
- if ext in ('jpeg', 'png', 'tiff', 'gif', 'bmp'):
- width, height = self.figure.get_size_inches()
- width, height = width*dpi, height*dpi
- self.write_bitmap(filename, width, height)
- elif ext == 'pdf':
- self.write_pdf(filename)
- elif ext in ('ps', 'eps'):
- from backend_ps import FigureCanvasPS
- # Postscript backend changes figure.dpi, but doesn't change it back
- origDPI = self.figure.dpi
- fc = self.switch_backends(FigureCanvasPS)
- fc.print_figure(filename, dpi, facecolor, edgecolor,
- orientation, **kwargs)
- self.figure.dpi = origDPI
- self.figure.set_canvas(self)
- elif ext=='svg':
- from backend_svg import FigureCanvasSVG
- fc = self.switch_backends(FigureCanvasSVG)
- fc.print_figure(filename, dpi, facecolor, edgecolor,
- orientation, **kwargs)
- self.figure.set_canvas(self)
- else:
- raise ValueError("Figure format not available (extension %s)" % ext)
+ def print_jpeg(self, filename, *args, **kwargs):
+ self._print_bitmap(filename, *args, **kwargs)
- # restore original figure settings
- self.figure.set_facecolor(origfacecolor)
- self.figure.set_edgecolor(origedgecolor)
+ def print_tif(self, filename, *args, **kwargs):
+ self._print_bitmap(filename, *args, **kwargs)
+ def print_tiff(self, filename, *args, **kwargs):
+ self._print_bitmap(filename, *args, **kwargs)
+ def print_gif(self, filename, *args, **kwargs):
+ self._print_bitmap(filename, *args, **kwargs)
+ def get_default_filetype(self):
+ return 'png'
+
+
class FigureManagerMac(_macosx.FigureManager, FigureManagerBase):
"""
Wrap everything up into a window for the pylab interface
Modified: trunk/matplotlib/setupext.py
===================================================================
--- trunk/matplotlib/setupext.py 2009-03-11 19:45:23 UTC (rev 6973)
+++ trunk/matplotlib/setupext.py 2009-03-13 17:13:49 UTC (rev 6974)
@@ -1156,20 +1156,22 @@
ext_modules.append(module)
BUILT_WXAGG = True
-
def build_macosx(ext_modules, packages):
global BUILT_MACOSX
if BUILT_MACOSX: return # only build it if you you haven't already
+ deps = ['src/_macosx.m',
+ 'src/agg_py_transforms.cpp',
+ 'src/path_cleanup.cpp',
+ 'src/_path.cpp']
module = Extension('matplotlib.backends._macosx',
- ['src/_macosx.m'],
+ deps,
extra_link_args = ['-framework','Cocoa'],
- define_macros=[('PY_ARRAY_UNIQUE_SYMBOL', 'MPL_ARRAY_API')]
)
add_numpy_flags(module)
+ add_agg_flags(module)
ext_modules.append(module)
BUILT_MACOSX = True
-
def build_png(ext_modules, packages):
global BUILT_PNG
if BUILT_PNG: return # only build it if you you haven't already
Modified: trunk/matplotlib/src/_macosx.m
===================================================================
--- trunk/matplotlib/src/_macosx.m 2009-03-11 19:45:23 UTC (rev 6973)
+++ trunk/matplotlib/src/_macosx.m 2009-03-13 17:13:49 UTC (rev 6974)
@@ -3,7 +3,9 @@
#include <sys/socket.h>
#include <Python.h>
#include "numpy/arrayobject.h"
+#include "path_cleanup.h"
+
static int nwin = 0; /* The number of open windows */
static int ngc = 0; /* The number of graphics contexts in use */
@@ -17,24 +19,7 @@
#define CGFloat float
#endif
-/* This is the same as CGAffineTransform, except that the data members are
- * doubles rather than CGFloats.
- * Matrix structure:
- * [ a b 0]
- * [ c d 0]
- * [ tx ty 1]
- */
-typedef struct
-{
- double a;
- double b;
- double c;
- double d;
- double tx;
- double ty;
-} AffineTransform;
-
/* Various NSApplicationDefined event subtypes */
#define STDIN_READY 0
#define SIGINT_CALLED 1
@@ -186,19 +171,6 @@
return 1;
}
-static AffineTransform
-AffineTransformConcat(AffineTransform t1, AffineTransform t2)
-{
- AffineTransform t;
- t.a = t1.a * t2.a + t1.b * t2.c;
- t.b = t1.a * t2.b + t1.b * t2.d;
- t.c = t1.c * t2.a + t1.d * t2.c;
- t.d = t1.c * t2.b + t1.d * t2.d;
- t.tx = t1.tx * t2.a + t1.ty * t2.c + t2.tx;
- t.ty = t1.tx * t2.b + t1.ty * t2.d + t2.ty;
- return t;
-}
-
static int _init_atsui(void)
{
OSStatus status;
@@ -237,243 +209,91 @@
PyErr_WarnEx(PyExc_RuntimeWarning, "ATSUDisposeTextLayout failed", 1);
}
-static int
-_draw_path(CGContextRef cr, PyObject* path, AffineTransform affine)
+static int _draw_path(CGContextRef cr, void* iterator)
{
double x1, y1, x2, y2, x3, y3;
- CGFloat fx1, fy1, fx2, fy2, fx3, fy3;
+ int n = 0;
+ unsigned code;
- PyObject* vertices = PyObject_GetAttrString(path, "vertices");
- if (vertices==NULL)
+ while (true)
{
- PyErr_SetString(PyExc_AttributeError, "path has no vertices");
- return -1;
- }
- Py_DECREF(vertices); /* Don't keep a reference here */
-
- PyObject* codes = PyObject_GetAttrString(path, "codes");
- if (codes==NULL)
- {
- PyErr_SetString(PyExc_AttributeError, "path has no codes");
- return -1;
- }
- Py_DECREF(codes); /* Don't keep a reference here */
-
- PyArrayObject* coordinates;
- coordinates = (PyArrayObject*)PyArray_FromObject(vertices,
- NPY_DOUBLE, 2, 2);
- if (!coordinates)
- {
- PyErr_SetString(PyExc_ValueError, "failed to convert vertices array");
- return -1;
- }
-
- if (PyArray_NDIM(coordinates) != 2 || PyArray_DIM(coordinates, 1) != 2)
- {
- Py_DECREF(coordinates);
- PyErr_SetString(PyExc_ValueError, "invalid vertices array");
- return -1;
- }
-
- npy_intp n = PyArray_DIM(coordinates, 0);
-
- if (n==0) /* Nothing to do here */
- {
- Py_DECREF(coordinates);
- return 0;
- }
-
- PyArrayObject* codelist = NULL;
- if (codes != Py_None)
- {
- codelist = (PyArrayObject*)PyArray_FromObject(codes,
- NPY_UINT8, 1, 1);
- if (!codelist)
+ code = get_vertex(iterator, &x1, &y1);
+ if (code == CLOSEPOLY)
{
- Py_DECREF(coordinates);
- PyErr_SetString(PyExc_ValueError, "invalid codes array");
- return -1;
+ CGContextClosePath(cr);
+ n++;
}
- }
-
- if (codelist==NULL)
- {
- npy_intp i;
- npy_uint8 code = MOVETO;
- for (i = 0; i < n; i++)
+ else if (code == STOP)
{
- x1 = *(double*)PyArray_GETPTR2(coordinates, i, 0);
- y1 = *(double*)PyArray_GETPTR2(coordinates, i, 1);
- if (isnan(x1) || isnan(y1))
- {
- code = MOVETO;
- }
- else
- {
- fx1 = (CGFloat)(affine.a*x1 + affine.c*y1 + affine.tx);
- fy1 = (CGFloat)(affine.b*x1 + affine.d*y1 + affine.ty);
- switch (code)
- {
- case MOVETO:
- CGContextMoveToPoint(cr, fx1, fy1);
- break;
- case LINETO:
- CGContextAddLineToPoint(cr, fx1, fy1);
- break;
- }
- code = LINETO;
- }
+ break;
}
- }
- else
- {
- npy_intp i = 0;
- BOOL was_nan = false;
- npy_uint8 code;
- while (i < n)
+ else if (code == MOVETO)
{
- code = *(npy_uint8*)PyArray_GETPTR1(codelist, i);
- if (code == CLOSEPOLY)
- {
- CGContextClosePath(cr);
- i++;
- }
- else if (code == STOP)
- {
- break;
- }
- else if (was_nan)
- {
- if (code==CURVE3) i++;
- else if (code==CURVE4) i+=2;
- x1 = *(double*)PyArray_GETPTR2(coordinates, i, 0);
- y1 = *(double*)PyArray_GETPTR2(coordinates, i, 1);
- i++;
- if (isnan(x1) || isnan(y1))
- {
- was_nan = true;
- }
- else
- {
- fx1 = (CGFloat) (affine.a*x1 + affine.c*y1 + affine.tx);
- fy1 = (CGFloat) (affine.b*x1 + affine.d*y1 + affine.ty);
- CGContextMoveToPoint(cr, fx1, fy1);
- was_nan = false;
- }
- }
- else if (code==MOVETO)
- {
- x1 = *(double*)PyArray_GETPTR2(coordinates, i, 0);
- y1 = *(double*)PyArray_GETPTR2(coordinates, i, 1);
- i++;
- if (isnan(x1) || isnan(y1))
- {
- was_nan = true;
- }
- else
- {
- fx1 = (CGFloat) (affine.a*x1 + affine.c*y1 + affine.tx);
- fy1 = (CGFloat) (affine.b*x1 + affine.d*y1 + affine.ty);
- CGContextMoveToPoint(cr, fx1, fy1);
- was_nan = false;
- }
- }
- else if (code==LINETO)
- {
- x1 = *(double*)PyArray_GETPTR2(coordinates, i, 0);
- y1 = *(double*)PyArray_GETPTR2(coordinates, i, 1);
- i++;
- if (isnan(x1) || isnan(y1))
- {
- was_nan = true;
- }
- else
- {
- fx1 = (CGFloat) (affine.a*x1 + affine.c*y1 + affine.tx);
- fy1 = (CGFloat) (affine.b*x1 + affine.d*y1 + affine.ty);
- CGContextAddLineToPoint(cr, fx1, fy1);
- was_nan = false;
- }
- }
- else if (code==CURVE3)
- {
- x1 = *(double*)PyArray_GETPTR2(coordinates, i, 0);
- y1 = *(double*)PyArray_GETPTR2(coordinates, i, 1);
- i++;
- x2 = *(double*)PyArray_GETPTR2(coordinates, i, 0);
- y2 = *(double*)PyArray_GETPTR2(coordinates, i, 1);
- i++;
- if (isnan(x1) || isnan(y1) || isnan(x2) || isnan(y2))
- {
- was_nan = true;
- }
- else
- {
- fx1 = (CGFloat) (affine.a*x1 + affine.c*y1 + affine.tx);
- fy1 = (CGFloat) (affine.b*x1 + affine.d*y1 + affine.ty);
- fx2 = (CGFloat) (affine.a*x2 + affine.c*y2 + affine.tx);
- fy2 = (CGFloat) (affine.b*x2 + affine.d*y2 + affine.ty);
- CGContextAddQuadCurveToPoint(cr, fx1, fy1, fx2, fy2);
- was_nan = false;
- }
- }
- else if (code==CURVE4)
- {
- x1 = *(double*)PyArray_GETPTR2(coordinates, i, 0);
- y1 = *(double*)PyArray_GETPTR2(coordinates, i, 1);
- i++;
- x2 = *(double*)PyArray_GETPTR2(coordinates, i, 0);
- y2 = *(double*)PyArray_GETPTR2(coordinates, i, 1);
- i++;
- x3 = *(double*)PyArray_GETPTR2(coordinates, i, 0);
- y3 = *(double*)PyArray_GETPTR2(coordinates, i, 1);
- i++;
- if (isnan(x1) || isnan(y1) || isnan(x2) || isnan(y2) || isnan(x3) || isnan(y3))
- {
- was_nan = true;
- }
- else
- {
- fx1 = (CGFloat) (affine.a*x1 + affine.c*y1 + affine.tx);
- fy1 = (CGFloat) (affine.b*x1 + affine.d*y1 + affine.ty);
- fx2 = (CGFloat) (affine.a*x2 + affine.c*y2 + affine.tx);
- fy2 = (CGFloat) (affine.b*x2 + affine.d*y2 + affine.ty);
- fx3 = (CGFloat) (affine.a*x3 + affine.c*y3 + affine.tx);
- fy3 = (CGFloat) (affine.b*x3 + affine.d*y3 + affine.ty);
- CGContextAddCurveToPoint(cr, fx1, fy1, fx2, fy2, fx3, fy3);
- was_nan = false;
- }
- }
+ CGContextMoveToPoint(cr, x1, y1);
+ n++;
}
+ else if (code==LINETO)
+ {
+ CGContextAddLineToPoint(cr, x1, y1);
+ n++;
+ }
+ else if (code==CURVE3)
+ {
+ get_vertex(iterator, &x2, &y2);
+ CGContextAddQuadCurveToPoint(cr, x1, y1, x2, y2);
+ n+=2;
+ }
+ else if (code==CURVE4)
+ {
+ get_vertex(iterator, &x2, &y2);
+ get_vertex(iterator, &x3, &y3);
+ CGContextAddCurveToPoint(cr, x1, y1, x2, y2, x3, y3);
+ n+=3;
+ }
}
-
- Py_DECREF(coordinates);
- Py_XDECREF(codelist);
return n;
}
-static void _draw_hatch (void *info, CGContextRef cr)
+static void _draw_hatch(void *info, CGContextRef cr)
{
PyObject* hatchpath = (PyObject*)info;
- AffineTransform affine = {HATCH_SIZE, 0, 0, HATCH_SIZE, 0, 0};
- int n = _draw_path(cr, hatchpath, affine);
- if (n < 0)
+ PyObject* transform;
+ int nd = 2;
+ npy_intp dims[2] = {3, 3};
+ int typenum = NPY_DOUBLE;
+ double data[9] = {HATCH_SIZE, 0, 0, 0, HATCH_SIZE, 0, 0, 0, 1};
+ double rect[4] = { 0.0, 0.0, HATCH_SIZE, HATCH_SIZE};
+ int n;
+ transform = PyArray_SimpleNewFromData(nd, dims, typenum, data);
+ if (!transform)
{
PyGILState_STATE gstate = PyGILState_Ensure();
PyErr_Print();
PyGILState_Release(gstate);
return;
}
- else if (n==0)
+ void* iterator = get_path_iterator(hatchpath,
+ transform,
+ 0,
+ 0,
+ rect,
+ QUANTIZE_FALSE,
+ 0);
+ Py_DECREF(transform);
+ if (!iterator)
{
+ PyGILState_STATE gstate = PyGILState_Ensure();
+ PyErr_SetString(PyExc_RuntimeError, "failed to obtain path iterator for hatching");
+ PyErr_Print();
+ PyGILState_Release(gstate);
return;
}
- else
- {
- CGContextSetLineWidth(cr, 1.0);
- CGContextSetLineCap(cr, kCGLineCapSquare);
- CGContextDrawPath(cr, kCGPathFillStroke);
- }
+ n = _draw_path(cr, iterator);
+ free_path_iterator(iterator);
+ if (n==0) return;
+ CGContextSetLineWidth(cr, 1.0);
+ CGContextSetLineCap(cr, kCGLineCapSquare);
+ CGContextDrawPath(cr, kCGPathFillStroke);
}
static void _release_hatch(void* info)
@@ -553,8 +373,64 @@
typedef struct {
PyObject_HEAD
CGContextRef cr;
+ NSSize size;
} GraphicsContext;
+static CGMutablePathRef _create_path(void* iterator)
+{
+ unsigned code;
+ CGMutablePathRef p;
+ double x1, y1, x2, y2, x3, y3;
+
+ p = CGPathCreateMutable();
+ if (!p) return NULL;
+
+ while (true)
+ {
+ code = get_vertex(iterator, &x1, &y1);
+ if (code == CLOSEPOLY)
+ {
+ CGPathCloseSubpath(p);
+ }
+ else if (code == STOP)
+ {
+ break;
+ }
+ else if (code == MOVETO)
+ {
+ CGPathMoveToPoint(p, NULL, x1, y1);
+ }
+ else if (code==LINETO)
+ {
+ CGPathAddLineToPoint(p, NULL, x1, y1);
+ }
+ else if (code==CURVE3)
+ {
+ get_vertex(iterator, &x2, &y2);
+ CGPathAddQuadCurveToPoint(p, NULL, x1, y1, x2, y2);
+ }
+ else if (code==CURVE4)
+ {
+ get_vertex(iterator, &x2, &y2);
+ get_vertex(iterator, &x3, &y3);
+ CGPathAddCurveToPoint(p, NULL, x1, y1, x2, y2, x3, y3);
+ }
+ }
+
+ return p;
+}
+
+static int _get_snap(GraphicsContext* self, enum e_quantize_mode* mode)
+{
+ PyObject* snap = PyObject_CallMethod((PyObject*)self, "get_snap", "");
+ if(!snap) return 0;
+ if(snap==Py_None) *mode = QUANTIZE_AUTO;
+ else if (PyBool_Check(snap)) *mode = QUANTIZE_TRUE;
+ else *mode = QUANTIZE_FALSE;
+ Py_DECREF(snap);
+ return 1;
+}
+
static PyObject*
GraphicsContext_new(PyTypeObject* type, PyObject *args, PyObject *kwds)
{
@@ -587,7 +463,7 @@
static PyObject*
GraphicsContext_repr(GraphicsContext* self)
{
- return PyString_FromFormat("GraphicsContext object %p wrapping the Quartz 2D graphics context %p", self, self->cr);
+ return PyString_FromFormat("GraphicsContext object %p wrapping the Quartz 2D graphics context %p", (void*)self, (void*)(self->cr));
}
static PyObject*
@@ -622,18 +498,30 @@
return Py_None;
}
+static BOOL
+_set_antialiased(CGContextRef cr, PyObject* antialiased)
+{
+ const int shouldAntialias = PyObject_IsTrue(antialiased);
+ if (shouldAntialias < 0)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "Failed to read antialiaseds variable");
+ return false;
+ }
+ CGContextSetShouldAntialias(cr, shouldAntialias);
+ return true;
+}
+
static PyObject*
GraphicsContext_set_antialiased (GraphicsContext* self, PyObject* args)
{
- int shouldAntialias;
- if (!PyArg_ParseTuple(args, "i", &shouldAntialias)) return NULL;
CGContextRef cr = self->cr;
if (!cr)
{
PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
return NULL;
}
- CGContextSetShouldAntialias(cr, shouldAntialias);
+ if (!_set_antialiased(cr, args)) return NULL;
Py_INCREF(Py_None);
return Py_None;
}
@@ -694,218 +582,64 @@
static PyObject*
GraphicsContext_set_clip_path (GraphicsContext* self, PyObject* args)
{
+ int n;
CGContextRef cr = self->cr;
+
+ PyObject* path;
+ int nd = 2;
+ npy_intp dims[2] = {3, 3};
+ int typenum = NPY_DOUBLE;
+ double data[] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
+
if (!cr)
{
PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
return NULL;
}
- PyObject* path;
-
if(!PyArg_ParseTuple(args, "O", &path)) return NULL;
- PyObject* vertices = PyObject_GetAttrString(path, "vertices");
- if (vertices==NULL)
- {
- PyErr_SetString(PyExc_AttributeError, "path has no vertices");
- return NULL;
- }
- Py_DECREF(vertices); /* Don't keep a reference here */
+ PyObject* transform = PyArray_SimpleNewFromData(nd, dims, typenum, data);
+ if (!transform) return NULL;
- PyObject* codes = PyObject_GetAttrString(path, "codes");
- if (codes==NULL)
+ double rect[4] = {0.0, 0.0, self->size.width, self->size.height};
+ void* iterator = get_path_iterator(path,
+ transform,
+ 0,
+ 0,
+ rect,
+ QUANTIZE_AUTO,
+ 0);
+ Py_DECREF(transform);
+ if (!iterator)
{
- PyErr_SetString(PyExc_AttributeError, "path has no codes");
+ PyErr_SetString(PyExc_RuntimeError,
+ "set_clip_path: failed to obtain path iterator for clipping");
return NULL;
}
- Py_DECREF(codes); /* Don't keep a reference here */
+ n = _draw_path(cr, iterator);
+ free_path_iterator(iterator);
- PyArrayObject* coordinates;
- coordinates = (PyArrayObject*)PyArray_FromObject(vertices,
- NPY_DOUBLE, 2, 2);
- if (!coordinates)
- {
- PyErr_SetString(PyExc_ValueError, "failed to convert vertices array");
- return NULL;
- }
+ if (n > 0) CGContextClip(cr);
- if (PyArray_NDIM(coordinates) != 2 || PyArray_DIM(coordinates, 1) != 2)
- {
- Py_DECREF(coordinates);
- PyErr_SetString(PyExc_ValueError, "invalid vertices array");
- return NULL;
- }
-
- npy_intp n = PyArray_DIM(coordinates, 0);
-
- if (n==0) /* Nothing to do here */
- {
- Py_DECREF(coordinates);
- return NULL;
- }
-
- PyArrayObject* codelist = NULL;
- if (codes != Py_None)
- {
- codelist = (PyArrayObject*)PyArray_FromObject(codes,
- NPY_UINT8, 1, 1);
- if (!codelist)
- {
- Py_DECREF(coordinates);
- PyErr_SetString(PyExc_ValueError, "invalid codes array");
- return NULL;
- }
- }
-
- CGFloat x, y;
-
- if (codelist==NULL)
- {
- npy_intp i;
- npy_uint8 code = MOVETO;
- for (i = 0; i < n; i++)
- {
- x = (CGFloat)(*(double*)PyArray_GETPTR2(coordinates, i, 0));
- y = (CGFloat)(*(double*)PyArray_GETPTR2(coordinates, i, 1));
- if (isnan(x) || isnan(y))
- {
- code = MOVETO;
- }
- else
- {
- switch (code)
- {
- case MOVETO:
- CGContextMoveToPoint(cr, x, y);
- break;
- case LINETO:
- CGContextAddLineToPoint(cr, x, y);
- break;
- }
- code = LINETO;
- }
- }
- }
- else
- {
- npy_intp i = 0;
- BOOL was_nan = false;
- npy_uint8 code;
- CGFloat x1, y1, x2, y2, x3, y3;
- while (i < n)
- {
- code = *(npy_uint8*)PyArray_GETPTR1(codelist, i);
- if (code == CLOSEPOLY)
- {
- CGContextClosePath(cr);
- i++;
- }
- else if (code == STOP)
- {
- break;
- }
- else if (was_nan)
- {
- if (code==CURVE3) i++;
- else if (code==CURVE4) i+=2;
- x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
- y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
- i++;
- if (isnan(x1) || isnan(y1))
- {
- was_nan = true;
- }
- else
- {
- CGContextMoveToPoint(cr, x1, y1);
- was_nan = false;
- }
- }
- else if (code==MOVETO)
- {
- x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
- y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
- i++;
- if (isnan(x1) || isnan(y1))
- {
- was_nan = true;
- }
- else
- {
- CGContextMoveToPoint(cr, x1, y1);
- was_nan = false;
- }
- }
- else if (code==LINETO)
- {
- x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
- y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
- i++;
- if (isnan(x1) || isnan(y1))
- {
- was_nan = true;
- }
- else
- {
- CGContextAddLineToPoint(cr, x1, y1);
- was_nan = false;
- }
- }
- else if (code==CURVE3)
- {
- x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
- y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
- i++;
- x2 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
- y2 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
- i++;
- if (isnan(x1) || isnan(y1) || isnan(x2) || isnan(y2))
- {
- was_nan = true;
- }
- else
- {
- CGContextAddQuadCurveToPoint(cr, x1, y1, x2, y2);
- was_nan = false;
- }
- }
- else if (code==CURVE4)
- {
- x1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
- y1 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
- i++;
- x2 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
- y2 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
- i++;
- x3 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 0));
- y3 = (CGFloat) (*(double*)PyArray_GETPTR2(coordinates, i, 1));
- i++;
- if (isnan(x1) || isnan(y1) || isnan(x2) || isnan(y2) || isnan(x3) || isnan(y3))
- {
- was_nan = true;
- }
- else
- {
- CGContextAddCurveToPoint(cr, x1, y1, x2, y2, x3, y3);
- was_nan = false;
- }
- }
- }
- Py_DECREF(codelist);
- }
-
- Py_DECREF(coordinates);
-
- CGContextClip(cr);
Py_INCREF(Py_None);
return Py_None;
}
static BOOL
-_set_dashes(CGContextRef cr, PyObject* offset, PyObject* dashes)
+_set_dashes(CGContextRef cr, PyObject* linestyle)
{
float phase = 0.0;
+ PyObject* offset;
+ PyObject* dashes;
+
+ if (!PyArg_ParseTuple(linestyle, "OO", &offset, &dashes))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "failed to obtain the offset and dashes from the linestyle");
+ return false;
+ }
+
if (offset!=Py_None)
{
if (PyFloat_Check(offset)) phase = PyFloat_AsDouble(offset);
@@ -965,11 +699,6 @@
static PyObject*
GraphicsContext_set_dashes (GraphicsContext* self, PyObject* args)
{
- PyObject* offset;
- PyObject* dashes;
-
- if (!PyArg_ParseTuple(args, "OO", &offset, &dashes)) return NULL;
-
CGContextRef cr = self->cr;
if (!cr)
{
@@ -977,14 +706,11 @@
return NULL;
}
- BOOL ok = _set_dashes(cr, offset, dashes);
- if (ok)
- {
- Py_INCREF(Py_None);
- return Py_None;
- }
- else
+ if (!_set_dashes(cr, args))
return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
}
static PyObject*
@@ -1072,54 +798,6 @@
return Py_None;
}
-static int
-_convert_affine_transform(PyObject* object, AffineTransform* transform)
-/* Reads a Numpy affine transformation matrix and returns an
- * AffineTransform structure
- */
-{
- PyArrayObject* matrix = NULL;
- if (object==Py_None)
- {
- PyErr_SetString(PyExc_ValueError,
- "Found affine transformation matrix equal to None");
- return 0;
- }
- matrix = (PyArrayObject*) PyArray_FromObject(object, NPY_DOUBLE, 2, 2);
- if (!matrix)
- {
- PyErr_SetString(PyExc_ValueError,
- "Invalid affine transformation matrix");
- return 0;
- }
- if (PyArray_NDIM(matrix) != 2 || PyArray_DIM(matrix, 0) != 3 || PyArray_DIM(matrix, 1) != 3)
- {
- Py_DECREF(matrix);
- PyErr_SetString(PyExc_ValueError,
- "Affine transformation matrix has invalid dimensions");
- return 0;
- }
-
- size_t stride0 = (size_t)PyArray_STRIDE(matrix, 0);
- size_t stride1 = (size_t)PyArray_STRIDE(matrix, 1);
- char* row0 = PyArray_BYTES(matrix);
- char* row1 = row0 + stride0;
-
- transform->a = *(double*)(row0);
- row0 += stride1;
- transform->c = *(double*)(row0);
- row0 += stride1;
- transform->tx = *(double*)(row0);
- transform->b = *(double*)(row1);
- row1 += stride1;
- transform->d = *(double*)(row1);
- row1 += stride1;
- transform->ty = *(double*)(row1);
-
- Py_DECREF(matrix);
- return 1;
-}
-
static PyObject*
GraphicsContext_draw_path (GraphicsContext* self, PyObject* args)
{
@@ -1127,9 +805,12 @@
PyObject* transform;
PyObject* rgbFace;
- int ok;
+ int n;
+ void* iterator;
+
CGContextRef cr = self->cr;
+ double rect[4] = { 0.0, 0.0, self->size.width, self->size.height};
if (!cr)
{
@@ -1144,24 +825,30 @@
if(rgbFace==Py_None) rgbFace = NULL;
- AffineTransform affine;
- ok = _convert_affine_transform(transform, &affine);
- if (!ok) return NULL;
+ iterator = get_path_iterator(path,
+ transform,
+ 1,
+ 0,
+ rect,
+ QUANTIZE_AUTO,
+ 1);
+ if (!iterator)
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "draw_path: failed to obtain path iterator");
+ return NULL;
+ }
+ n = _draw_path(cr, iterator);
+ free_path_iterator(iterator);
- int n = _draw_path(cr, path, affine);
- if (n==-1) return NULL;
-
if (n > 0)
{
PyObject* hatchpath;
if(rgbFace)
{
float r, g, b;
- ok = PyArg_ParseTuple(rgbFace, "fff", &r, &g, &b);
- if (!ok)
- {
+ if (!PyArg_ParseTuple(rgbFace, "fff", &r, &g, &b))
return NULL;
- }
CGContextSaveGState(cr);
CGContextSetRGBFillColor(cr, r, g, b, 1.0);
CGContextDrawPath(cr, kCGPathFillStroke);
@@ -1180,8 +867,11 @@
}
else
{
+ int ok;
float color[4] = {0, 0, 0, 1};
CGPatternRef pattern;
+ CGColorSpaceRef baseSpace;
+ CGColorSpaceRef patternSpace;
static const CGPatternCallbacks callbacks = {0,
&_draw_hatch,
&_release_hatch};
@@ -1199,9 +889,23 @@
return NULL;
}
- CGColorSpaceRef baseSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
- CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(baseSpace);
+ baseSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ if (!baseSpace)
+ {
+ Py_DECREF(hatchpath);
+ PyErr_SetString(PyExc_RuntimeError,
+ "draw_path: CGColorSpaceCreateWithName failed");
+ return NULL;
+ }
+ patternSpace = CGColorSpaceCreatePattern(baseSpace);
CGColorSpaceRelease(baseSpace);
+ if (!patternSpace)
+ {
+ Py_DECREF(hatchpath);
+ PyErr_SetString(PyExc_RuntimeError,
+ "draw_path: CGColorSpaceCreatePattern failed");
+ return NULL;
+ }
CGContextSetFillColorSpace(cr, patternSpace);
CGColorSpaceRelease(patternSpace);
@@ -1214,7 +918,22 @@
&callbacks);
CGContextSetFillPattern(cr, pattern, color);
CGPatternRelease(pattern);
- _draw_path(cr, path, affine);
+ iterator = get_path_iterator(path,
+ transform,
+ 1,
+ 0,
+ rect,
+ QUANTIZE_AUTO,
+ 1);
+ if (!iterator)
+ {
+ Py_DECREF(hatchpath);
+ PyErr_SetString(PyExc_RuntimeError,
+ "draw_path: failed to obtain path iterator for hatching");
+ return NULL;
+ }
+ n = _draw_path(cr, iterator);
+ free_path_iterator(iterator);
CGContextFillPath(cr);
}
}
@@ -1234,8 +953,14 @@
int ok;
float r, g, b;
- double x, y;
+ CGMutablePathRef marker;
+ void* iterator;
+ double rect[4] = {0.0, 0.0, self->size.width, self->size.height};
+ enum e_quantize_mode mode;
+ double xc, yc;
+ unsigned code;
+
CGContextRef cr = self->cr;
if (!cr)
@@ -1263,60 +988,68 @@
CGContextSetRGBFillColor(cr, r, g, b, 1.0);
}
- AffineTransform affine;
- ok = _convert_affine_transform(transform, &affine);
- if (!ok) return NULL;
-
- AffineTransform marker_affine;
- ok = _convert_affine_transform(marker_transform, &marker_affine);
- if (!ok) return NULL;
-
- PyObject* vertices = PyObject_GetAttrString(path, "vertices");
- if (vertices==NULL)
+ ok = _get_snap(self, &mode);
+ if (!ok)
{
- PyErr_SetString(PyExc_AttributeError, "path has no vertices");
return NULL;
}
- Py_DECREF(vertices); /* Don't keep a reference here */
- PyArrayObject* coordinates;
- coordinates = (PyArrayObject*)PyArray_FromObject(vertices,
- NPY_DOUBLE, 2, 2);
- if (!coordinates)
+ iterator = get_path_iterator(marker_path,
+ marker_transform,
+ 0,
+ 0,
+ rect,
+ mode,
+ 0);
+ if (!iterator)
{
- PyErr_SetString(PyExc_ValueError, "failed to convert vertices array");
+ PyErr_SetString(PyExc_RuntimeError,
+ "draw_markers: failed to obtain path iterator for marker");
return NULL;
}
-
- if (PyArray_NDIM(coordinates) != 2 || PyArray_DIM(coordinates, 1) != 2)
+ marker = _create_path(iterator);
+ free_path_iterator(iterator);
+ if (!marker)
{
- Py_DECREF(coordinates);
- PyErr_SetString(PyExc_ValueError, "invalid vertices array");
+ PyErr_SetString(PyExc_RuntimeError,
+ "draw_markers: failed to draw marker path");
return NULL;
}
-
- npy_intp i;
- npy_intp n = PyArray_DIM(coordinates, 0);
- AffineTransform t;
- int m = 0;
- for (i = 0; i < n; i++)
+ iterator = get_path_iterator(path,
+ transform,
+ 1,
+ 1,
+ rect,
+ QUANTIZE_TRUE,
+ 0);
+ if (!iterator)
{
- x = *(double*)PyArray_GETPTR2(coordinates, i, 0);
- y = *(double*)PyArray_GETPTR2(coordinates, i, 1);
- t = marker_affine;
- t.tx += affine.a*x + affine.c*y + affine.tx;
- t.ty += affine.b*x + affine.d*y + affine.ty;
- m = _draw_path(cr, marker_path, t);
+ CGPathRelease(marker);
+ PyErr_SetString(PyExc_RuntimeError,
+ "draw_markers: failed to obtain path iterator");
+ return NULL;
+ }
- if (m > 0)
+ while (true)
+ {
+ code = get_vertex(iterator, &xc, &yc);
+ if (code == STOP)
{
- if(rgbFace) CGContextDrawPath(cr, kCGPathFillStroke);
- else CGContextStrokePath(cr);
+ break;
}
+ else if (code == MOVETO || code == LINETO || code == CURVE3 || code ==CURVE4)
+ {
+ CGContextSaveGState(cr);
+ CGContextTranslateCTM(cr, xc, yc);
+ CGContextAddPath(cr, marker);
+ CGContextRestoreGState(cr);
+ }
+ if(rgbFace) CGContextDrawPath(cr, kCGPathFillStroke);
+ else CGContextStrokePath(cr);
}
+ free_path_iterator(iterator);
+ CGPathRelease(marker);
- Py_DECREF(coordinates);
-
Py_INCREF(Py_None);
return Py_None;
}
@@ -1358,20 +1091,53 @@
return true;
}
+static BOOL
+_set_offset(CGContextRef cr, PyObject* offsets, int index, PyObject* transform)
+{
+ CGFloat tx;
+ CGFloat ty;
+ double x = *(double*)PyArray_GETPTR2(offsets, index, 0);
+ double y = *(double*)PyArray_GETPTR2(offsets, index, 1);
+ PyObject* translation = PyObject_CallMethod(transform, "transform_point",
+ "((ff))", x, y);
+ if (!translation)
+ {
+ return false;
+ }
+ if (!PyArray_Check(translation))
+ {
+ Py_DECREF(translation);
+ PyErr_SetString(PyExc_ValueError,
+ "transform_point did not return a NumPy array");
+ return false;
+ }
+ if (PyArray_NDIM(translation)!=1 || PyArray_DIM(translation, 0)!=2)
+ {
+ Py_DECREF(translation);
+ PyErr_SetString(PyExc_ValueError,
+ "transform_point did not return an approriate array");
+ return false;
+ }
+ tx = (CGFloat)(*(double*)PyArray_GETPTR1(translation, 0));
+ ty = (CGFloat)(*(double*)PyArray_GETPTR1(translation, 1));
+ Py_DECREF(translation);
+ CGContextTranslateCTM(cr, tx, ty);
+ return true;
+}
static PyObject*
GraphicsContext_draw_path_collection (GraphicsContext* self, PyObject* args)
{
- PyObject* master_transform_obj;
+ PyObject* master_transform;
PyObject* cliprect;
PyObject* clippath;
PyObject* clippath_transform;
PyObject* paths;
- PyObject* transforms_obj;
- PyObject* offsets_obj;
- PyObject* offset_transform_obj;
- PyObject* facecolors_obj;
- PyObject* edgecolors_obj;
+ PyObject* transforms;
+ PyObject* offsets;
+ PyObject* offset_transform;
+ PyObject* facecolors;
+ PyObject* edgecolors;
PyObject* linewidths;
PyObject* linestyles;
PyObject* antialiaseds;
@@ -1384,172 +1150,298 @@
return NULL;
}
- if(!PyArg_ParseTuple(args, "OOOOOOOOOOOOO", &master_transform_obj,
+ if(!PyArg_ParseTuple(args, "OOOOOOOOOOOOO", &master_transform,
&cliprect,
&clippath,
&clippath_transform,
&paths,
- &transforms_obj,
- &offsets_obj,
- &offset_transform_obj,
- &facecolors_obj,
- &edgecolors_obj,
+ &transforms,
+ &offsets,
+ &offset_transform,
+ &facecolors,
+ &edgecolors,
&linewidths,
&linestyles,
&antialiaseds))
return NULL;
- CGContextSaveGState(cr);
+ int ok = 1;
+ Py_ssize_t i;
+ Py_ssize_t Np = 0;
+ Py_ssize_t N = 0;
- AffineTransform transform;
- AffineTransform master_transform;
- AffineTransform offset_transform;
- AffineTransform* transforms = NULL;
+ CGMutablePathRef* p = NULL;
- if (!_convert_affine_transform(master_transform_obj, &master_transform)) return NULL;
- if (!_convert_affine_transform(offset_transform_obj, &offset_transform)) return NULL;
+ /* --------- Prepare some variables for the path iterator ------------- */
+ void* iterator;
+ double rect[4] = {0.0, 0.0, self->size.width, self->size.height};
+ enum e_quantize_mode mode;
+ ok = _get_snap(self, &mode);
+ if (!ok)
+ {
+ return NULL;
+ }
- if (!_clip(cr, cliprect)) return NULL;
- if (clippath!=Py_None)
+ /* ------------------- Check paths ------------------------------------ */
+
+ if (!PySequence_Check(paths))
{
- if (!_convert_affine_transform(clippath_transform, &transform)) return NULL;
- int n = _draw_path(cr, clippath, transform);
- if (n==-1) return NULL;
- else if (n > 0) CGContextClip(cr);
+ PyErr_SetString(PyExc_ValueError, "paths must be a sequence object");
+ return NULL;
}
+ const Py_ssize_t Npaths = PySequence_Size(paths);
- PyArrayObject* offsets = NULL;
- PyArrayObject* facecolors = NULL;
- PyArrayObject* edgecolors = NULL;
+ /* ------------------- Check transforms ------------------------------- */
+ if (!PySequence_Check(transforms))
+ {
+ PyErr_SetString(PyExc_ValueError, "transforms must be a sequence object");
+ return NULL;
+ }
+ Py_ssize_t Ntransforms = PySequence_Size(transforms);
+
+ CGContextSaveGState(cr);
+ /* ------------------- Set master transform --------------------------- */
+
+ if (Ntransforms)
+ {
+ PyObject* values = PyObject_CallMethod(master_transform, "to_values", "");
+ if (!values)
+ {
+ ok = 0;
+ goto exit;
+ }
+ if (!PyTuple_Check(values))
+ {
+ Py_DECREF(values);
+ ok = 0;
+ goto exit;
+ }
+ CGAffineTransform master;
+ ok = PyArg_ParseTuple(values, "ffffff",
+ &master.a,
+ &master.b,
+ &master.c,
+ &master.d,
+ &master.tx,
+ &master.ty);
+ Py_DECREF(values);
+ if (!ok) goto exit;
+ CGContextConcatCTM(cr, master);
+ }
+
/* ------------------- Check offsets array ---------------------------- */
- offsets = (PyArrayObject*)PyArray_FromObject(offsets_obj, NPY_DOUBLE, 0, 2);
+ offsets = PyArray_FromObject(offsets, NPY_DOUBLE, 0, 2);
if (!offsets ||
(PyArray_NDIM(offsets)==2 && PyArray_DIM(offsets, 1)!=2) ||
(PyArray_NDIM(offsets)==1 && PyArray_DIM(offsets, 0)!=0))
{
PyErr_SetString(PyExc_ValueError, "Offsets array must be Nx2");
- goto error;
+ ok = 0;
+ goto exit;
}
+ const Py_ssize_t Noffsets = PyArray_DIM(offsets, 0);
+ /* -------------------------------------------------------------------- */
+
+ Np = Npaths > Ntransforms ? Npaths : Ntransforms;
+ N = Np > Noffsets ? Np : Noffsets;
+ if (N < Ntransforms) Ntransforms = N;
+
+ p = malloc(Np*sizeof(CGMutablePathRef));
+ if (!p)
+ {
+ ok = 0;
+ goto exit;
+ }
+ for (i = 0; i < Np; i++)
+ {
+ PyObject* path;
+ PyObject* transform;
+ p[i] = NULL;
+ path = PySequence_ITEM(paths, i % Npaths);
+ if (!path)
+ {
+ ok = 0;
+ goto exit;
+ }
+ if (Ntransforms)
+ {
+ transform = PySequence_ITEM(transforms, i % Ntransforms);
+ if (!transform)
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "failed to obtain transform");
+ ok = 0;
+ goto exit;
+ }
+ iterator = get_path_iterator(path,
+ transform,
+ 1,
+ 0,
+ rect,
+ mode,
+ 0);
+ Py_DECREF(transform);
+ }
+ else
+ {
+ iterator = get_path_iterator(path,
+ master_transform,
+ 1,
+ 0,
+ rect,
+ mode,
+ 0);
+ }
+ Py_DECREF(path);
+ if (!iterator)
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "failed to obtain path iterator");
+ ok = 0;
+ goto exit;
+ }
+ p[i] = _create_path(iterator);
+ free_path_iterator(iterator);
+ if (!p[i])
+ {
+ PyErr_SetString(PyExc_RuntimeError, "failed to create path");
+ ok = 0;
+ goto exit;
+ }
+ }
+
+ /* ------------------- Set clipping path ------------------------------ */
+
+ if (!_clip(cr, cliprect))
+ {
+ ok = 0;
+ goto exit;
+ }
+ if (clippath!=Py_None)
+ {
+ int n;
+ iterator = get_path_iterator(clippath,
+ clippath_transform,
+ 0,
+ 0,
+ rect,
+ QUANTIZE_AUTO,
+ 0);
+ if (!iterator)
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "draw_path_collection: failed to obtain path iterator for clipping");
+ ok = 0;
+ goto exit;
+ }
+ n = _draw_path(cr, iterator);
+ free_path_iterator(iterator);
+ if (n > 0) CGContextClip(cr);
+ }
+
/* ------------------- Check facecolors array ------------------------- */
- facecolors = (PyArrayObject*)PyArray_FromObject(facecolors_obj,
- NPY_DOUBLE, 1, 2);
+ facecolors = PyArray_FromObject(facecolors, NPY_DOUBLE, 1, 2);
if (!facecolors ||
(PyArray_NDIM(facecolors)==1 && PyArray_DIM(facecolors, 0)!=0) ||
(PyArray_NDIM(facecolors)==2 && PyArray_DIM(facecolors, 1)!=4))
{
PyErr_SetString(PyExc_ValueError, "Facecolors must by a Nx4 numpy array or empty");
- goto error;
+ ok = 0;
+ goto exit;
}
/* ------------------- Check edgecolors array ------------------------- */
- edgecolors = (PyArrayObject*)PyArray_FromObject(edgecolors_obj,
- NPY_DOUBLE, 1, 2);
+ edgecolors = PyArray_FromObject(edgecolors, NPY_DOUBLE, 1, 2);
if (!edgecolors ||
(PyArray_NDIM(edgecolors)==1 && PyArray_DIM(edgecolors, 0)!=0) ||
(PyArray_NDIM(edgecolors)==2 && PyArray_DIM(edgecolors, 1)!=4))
{
PyErr_SetString(PyExc_ValueError, "Edgecolors must by a Nx4 numpy array or empty");
- goto error;
+ ok = 0;
+ goto exit;
}
/* ------------------- Check the other arguments ---------------------- */
- if (!PySequence_Check(paths))
- {
- PyErr_SetString(PyExc_ValueError, "paths must be a sequence object");
- goto error;
- }
- if (!PySequence_Check(transforms_obj))
- {
- PyErr_SetString(PyExc_ValueError, "transforms must be a sequence object");
- goto error;
- }
if (!PySequence_Check(linewidths))
{
PyErr_SetString(PyExc_ValueError, "linewidths must be a sequence object");
- goto error;
+ ok = 0;
+ goto exit;
}
if (!PySequence_Check(linestyles))
{
PyErr_SetString(PyExc_ValueError, "linestyles must be a sequence object");
- goto error;
+ ok = 0;
+ goto exit;
}
if (!PySequence_Check(antialiaseds))
{
PyErr_SetString(PyExc_ValueError, "antialiaseds must be a sequence object");
- goto error;
+ ok = 0;
+ goto exit;
}
- size_t Npaths = (size_t) PySequence_Size(paths);
- size_t Noffsets = (size_t) PyArray_DIM(offsets, 0);
- size_t N = Npaths > Noffsets ? Npaths : Noffsets;
- size_t Ntransforms = (size_t) PySequence_Size(transforms_obj);
- size_t Nfacecolors = (size_t) PyArray_DIM(facecolors, 0);
- size_t Nedgecolors = (size_t) PyArray_DIM(edgecolors, 0);
- size_t Nlinewidths = (size_t) PySequence_Size(linewidths);
- size_t Nlinestyles = (size_t) PySequence_Size(linestyles);
- size_t Naa = (size_t) PySequence_Size(antialiaseds);
- if (N < Ntransforms) Ntransforms = N;
+ Py_ssize_t Nfacecolors = PyArray_DIM(facecolors, 0);
+ Py_ssize_t Nedgecolors = PyArray_DIM(edgecolors, 0);
+ Py_ssize_t Nlinewidths = PySequence_Size(linewidths);
+ Py_ssize_t Nlinestyles = PySequence_Size(linestyles);
+ Py_ssize_t Naa = PySequence_Size(antialiaseds);
if (N < Nlinestyles) Nlinestyles = N;
- if ((Nfacecolors == 0 && Nedgecolors == 0) || Npaths == 0)
- {
- goto success;
- }
+ if ((Nfacecolors == 0 && Nedgecolors == 0) || Np == 0) goto exit;
- size_t i = 0;
-
- /* Convert all of the transforms up front */
- if (Ntransforms > 0)
- {
- transforms = malloc(Ntransforms*sizeof(AffineTransform));
- if (!transforms) goto error;
- for (i = 0; i < Ntransforms; i++)
- {
- PyObject* transform_obj = PySequence_ITEM(transforms_obj, i);
- if(!_convert_affine_transform(transform_obj, &transforms[i])) goto error;
- transforms[i] = AffineTransformConcat(transforms[i], master_transform);
- }
- }
-
- PyObject* path;
- double x, y;
-
/* Preset graphics context properties if possible */
if (Naa==1)
{
- switch(PyObject_IsTrue(PySequence_ITEM(antialiaseds, 0)))
+ PyObject* antialiased = PySequence_ITEM(antialiaseds, 0);
+ if (antialiased)
{
- case 1: CGContextSetShouldAntialias(cr, true); break;
- case 0: CGContextSetShouldAntialias(cr, false); break;
- case -1:
- {
- PyErr_SetString(PyExc_ValueError,
- "Failed to read antialiaseds array");
- goto error;
- }
+ ok = _set_antialiased(cr, antialiased);
+ Py_DECREF(antialiased);
}
+ else
+ {
+ PyErr_SetString(PyExc_SystemError,
+ "Failed to read element from antialiaseds array");
+ ok = 0;
+ }
+ if (!ok) goto exit;
}
if (Nlinewidths==1)
{
- double linewidth = PyFloat_AsDouble(PySequence_ITEM(linewidths, 0));
- CGContextSetLineWidth(cr, (CGFloat)linewidth);
+ PyObject* linewidth = PySequence_ITEM(linewidths, 0);
+ if (!linewidth)
+ {
+ PyErr_SetString(PyExc_SystemError,
+ "Failed to read element from linewidths array");
+ ok = 0;
+ goto exit;
+ }
+ CGContextSetLineWidth(cr, (CGFloat)PyFloat_AsDouble(linewidth));
+ Py_DECREF(linewidth);
}
else if (Nlinewidths==0)
CGContextSetLineWidth(cr, 0.0);
if (Nlinestyles==1)
{
- PyObject* offset;
- PyObject* dashes;
PyObject* linestyle = PySequence_ITEM(linestyles, 0);
- if (!PyArg_ParseTuple(linestyle, "OO", &offset, &dashes)) goto error;
- if (!_set_dashes(cr, offset, dashes)) goto error;
+ if (!linestyle)
+ {
+ PyErr_SetString(PyExc_SystemError,
+ "Failed to read element from linestyles array");
+ ok = 0;
+ goto exit;
+ }
+ ok = _set_dashes(cr, linestyle);
+ Py_DECREF(linestyle);
+ if (!ok) goto exit;
}
if (Nedgecolors==1)
@@ -1572,57 +1464,63 @@
for (i = 0; i < N; i++)
{
+ if (CGPathIsEmpty(p[i % Np])) continue;
- if (Ntransforms)
- {
- transform = transforms[i % Ntransforms];
- }
- else
- {
- transform = master_transform;
- }
-
+ CGContextSaveGState(cr);
if (Noffsets)
{
- x = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 0);
- y = *(double*)PyArray_GETPTR2(offsets, i % Noffsets, 1);
- transform.tx += offset_transform.a*x + offset_transform.c*y + offset_transform.tx;
- transform.ty += offset_transform.b*x + offset_transform.d*y + offset_transform.ty;
+ ok = _set_offset(cr, offsets, i % Noffsets, offset_transform);
+ if (!ok)
+ {
+ CGContextRestoreGState(cr);
+ goto exit;
+ }
}
if (Naa > 1)
{
- switch(PyObject_IsTrue(PySequence_ITEM(antialiaseds, i % Naa)))
+ PyObject* antialiased = PySequence_ITEM(antialiaseds, i % Naa);
+ if (antialiased)
{
- case 1: CGContextSetShouldAntialias(cr, true); break;
- case 0: CGContextSetShouldAntialias(cr, false); break;
- case -1:
- {
- PyErr_SetString(PyExc_ValueError,
- "Failed to read antialiaseds array");
- goto error;
- }
+ ok = _set_antialiased(cr, antialiased);
+ Py_DECREF(antialiased);
}
+ else
+ {
+ PyErr_SetString(PyExc_SystemError,
+ "Failed to read element from antialiaseds array");
+ ok = 0;
+ }
+ if (!ok) goto exit;
}
- path = PySequence_ITEM(paths, i % Npaths);
- int n = _draw_path(cr, path, transform);
- if (n==-1) goto error;
- else if (n==0) continue;
-
if (Nlinewidths > 1)
{
- double linewidth = PyFloat_AsDouble(PySequence_ITEM(linewidths, i % Nlinewidths));
- CGContextSetLineWidth(cr, (CGFloat)linewidth);
+ PyObject* linewidth = PySequence_ITEM(linewidths, i % Nlinewidths);
+ if (!linewidth)
+ {
+ PyErr_SetString(PyExc_SystemError,
+ "Failed to read element from linewidths array");
+ ok = 0;
+ goto exit;
+ }
+ CGContextSetLineWidth(cr, (CGFloat)PyFloat_AsDouble(linewidth));
+ Py_DECREF(linewidth);
}
if (Nlinestyles > 1)
{
- PyObject* offset;
- PyObject* dashes;
PyObject* linestyle = PySequence_ITEM(linestyles, i % Nlinestyles);
- if (!PyArg_ParseTuple(linestyle, "OO", &offset, &dashes)) goto error;
- if (!_set_dashes(cr, offset, dashes)) goto error;
+ if (!linestyle)
+ {
+ PyErr_SetString(PyExc_SystemError,
+ "Failed to read element from linestyles array");
+ ok = 0;
+ goto exit;
+ }
+ ok = _set_dashes(cr, linestyle);
+ Py_DECREF(linestyle);
+ if (!ok) goto exit;
}
if (Nedgecolors > 1)
@@ -1635,6 +1533,8 @@
CGContextSetRGBStrokeColor(cr, r, g, b, a);
}
+ CGContextAddPath(cr, p[i % Np]);
+
if (Nfacecolors > 1)
{
npy_intp fi = i % Nfacecolors;
@@ -1649,41 +1549,42 @@
CGContextDrawPath(cr, kCGPathFillStroke);
else
CGContextStrokePath(cr);
+ CGContextRestoreGState(cr);
}
-success:
+exit:
CGContextRestoreGState(cr);
- if (transforms) free(transforms);
- Py_DECREF(offsets);
- Py_DECREF(facecolors);
- Py_DECREF(edgecolors);
-
- Py_INCREF(Py_None);
- return Py_None;
-
-error:
- CGContextRestoreGState(cr);
- if (transforms) free(transforms);
Py_XDECREF(offsets);
Py_XDECREF(facecolors);
Py_XDECREF(edgecolors);
+ if (p)
+ {
+ for (i = 0; i < Np; i++)
+ {
+ if (!p[i]) break;
+ CGPathRelease(p[i]);
+ }
+ free(p);
+ }
+ if (!ok) return NULL;
- return NULL;
+ Py_INCREF(Py_None);
+ return Py_None;
}
static PyObject*
GraphicsContext_draw_quad_mesh (GraphicsContext* self, PyObject* args)
{
- PyObject* mas...
[truncated message content] |
|
From: <ef...@us...> - 2009-03-11 20:40:45
|
Revision: 6973
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6973&view=rev
Author: efiring
Date: 2009-03-11 19:45:23 +0000 (Wed, 11 Mar 2009)
Log Message:
-----------
Merged revisions 6972 via svnmerge from
https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint
........
r6972 | efiring | 2009-03-11 09:36:22 -1000 (Wed, 11 Mar 2009) | 2 lines
Ensure wx version >= 2.8; Sandro Tosi patch plus change to backend
........
Modified Paths:
--------------
trunk/matplotlib/CHANGELOG
trunk/matplotlib/examples/user_interfaces/embedding_in_wx2.py
trunk/matplotlib/examples/user_interfaces/embedding_in_wx3.py
trunk/matplotlib/examples/user_interfaces/embedding_in_wx4.py
trunk/matplotlib/examples/user_interfaces/embedding_in_wx5.py
trunk/matplotlib/lib/matplotlib/backends/backend_wx.py
trunk/matplotlib/lib/matplotlib/backends/backend_wxagg.py
Property Changed:
----------------
trunk/matplotlib/
trunk/matplotlib/doc/pyplots/README
trunk/matplotlib/doc/sphinxext/gen_gallery.py
trunk/matplotlib/doc/sphinxext/gen_rst.py
trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py
trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py
trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py
Property changes on: trunk/matplotlib
___________________________________________________________________
Modified: svnmerge-integrated
- /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6960
+ /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6972
Modified: svn:mergeinfo
- /branches/v0_91_maint:5753-5771
/branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960
+ /branches/v0_91_maint:5753-5771
/branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2009-03-11 19:36:22 UTC (rev 6972)
+++ trunk/matplotlib/CHANGELOG 2009-03-11 19:45:23 UTC (rev 6973)
@@ -1,3 +1,6 @@
+2009-03-11 Ensure wx version >= 2.8; thanks to Sandro Tosi and
+ Chris Barker. - EF
+
2009-03-10 Fix join style bug in pdf. - JKS
2009-03-07 Add pyplot access to figure number list - EF
Property changes on: trunk/matplotlib/doc/pyplots/README
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960
+ /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972
Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771
/branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960
+ /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771
/branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972
Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771
/branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960
+ /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771
/branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972
Modified: trunk/matplotlib/examples/user_interfaces/embedding_in_wx2.py
===================================================================
--- trunk/matplotlib/examples/user_interfaces/embedding_in_wx2.py 2009-03-11 19:36:22 UTC (rev 6972)
+++ trunk/matplotlib/examples/user_interfaces/embedding_in_wx2.py 2009-03-11 19:45:23 UTC (rev 6973)
@@ -4,6 +4,10 @@
toolbar - comment out the setA_toolbar line for no toolbar
"""
+# Used to guarantee to use at least Wx2.8
+import wxversion
+wxversion.ensureMinimal('2.8')
+
from numpy import arange, sin, pi
import matplotlib
@@ -20,15 +24,15 @@
from matplotlib.figure import Figure
-from wx import *
+import wx
-class CanvasFrame(Frame):
+class CanvasFrame(wx.Frame):
def __init__(self):
- Frame.__init__(self,None,-1,
+ wx.Frame.__init__(self,None,-1,
'CanvasFrame',size=(550,350))
- self.SetBackgroundColour(NamedColor("WHITE"))
+ self.SetBackgroundColour(wx.NamedColor("WHITE"))
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
@@ -38,8 +42,8 @@
self.axes.plot(t,s)
self.canvas = FigureCanvas(self, -1, self.figure)
- self.sizer = BoxSizer(VERTICAL)
- self.sizer.Add(self.canvas, 1, LEFT | TOP | GROW)
+ self.sizer = wx.BoxSizer(wx.VERTICAL)
+ self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.SetSizer(self.sizer)
self.Fit()
@@ -49,7 +53,7 @@
def add_toolbar(self):
self.toolbar = NavigationToolbar2Wx(self.canvas)
self.toolbar.Realize()
- if Platform == '__WXMAC__':
+ if wx.Platform == '__WXMAC__':
# Mac platform (OSX 10.3, MacPython) does not seem to cope with
# having a toolbar in a sizer. This work-around gets the buttons
# back, but at the expense of having the toolbar at the top
@@ -62,8 +66,8 @@
# By adding toolbar in sizer, we are able to put it at the bottom
# of the frame - so appearance is closer to GTK version.
# As noted above, doesn't work for Mac.
- self.toolbar.SetSize(Size(fw, th))
- self.sizer.Add(self.toolbar, 0, LEFT | EXPAND)
+ self.toolbar.SetSize(wx.Size(fw, th))
+ self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
# update the axes menu on the toolbar
self.toolbar.update()
@@ -71,7 +75,7 @@
def OnPaint(self, event):
self.canvas.draw()
-class App(App):
+class App(wx.App):
def OnInit(self):
'Create the main window and insert the custom frame'
Modified: trunk/matplotlib/examples/user_interfaces/embedding_in_wx3.py
===================================================================
--- trunk/matplotlib/examples/user_interfaces/embedding_in_wx3.py 2009-03-11 19:36:22 UTC (rev 6972)
+++ trunk/matplotlib/examples/user_interfaces/embedding_in_wx3.py 2009-03-11 19:45:23 UTC (rev 6973)
@@ -18,6 +18,11 @@
Thanks to matplotlib and wx teams for creating such great software!
"""
+
+# Used to guarantee to use at least Wx2.8
+import wxversion
+wxversion.ensureMinimal('2.8')
+
import sys, time, os, gc
import matplotlib
matplotlib.use('WXAgg')
@@ -26,18 +31,18 @@
from matplotlib.figure import Figure
import numpy as npy
-from wx import *
-from wx.xrc import *
+import wx
+import wx.xrc as xrc
ERR_TOL = 1e-5 # floating point slop for peak-detection
matplotlib.rc('image', origin='lower')
-class PlotPanel(Panel):
+class PlotPanel(wx.Panel):
def __init__(self, parent):
- Panel.__init__(self, parent, -1)
+ wx.Panel.__init__(self, parent, -1)
self.fig = Figure((5,4), 75)
self.canvas = FigureCanvasWxAgg(self, -1, self.fig)
@@ -46,11 +51,11 @@
#self.toolbar.set_active([0,1])
# Now put all into a sizer
- sizer = BoxSizer(VERTICAL)
+ sizer = wx.BoxSizer(wx.VERTICAL)
# This way of adding to sizer allows resizing
- sizer.Add(self.canvas, 1, LEFT|TOP|GROW)
+ sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
# Best to allow the toolbar to resize!
- sizer.Add(self.toolbar, 0, GROW)
+ sizer.Add(self.toolbar, 0, wx.GROW)
self.SetSizer(sizer)
self.Fit()
@@ -94,43 +99,43 @@
# this is supposed to prevent redraw flicker on some X servers...
pass
-class MyApp(App):
+class MyApp(wx.App):
def OnInit(self):
xrcfile = os.path.join(os.path.dirname(__file__),"..","data",
"embedding_in_wx3.xrc")
- self.res = XmlResource(xrcfile)
+ self.res = xrc.XmlResource(xrcfile)
# main frame and panel ---------
self.frame = self.res.LoadFrame(None,"MainFrame")
- self.panel = XRCCTRL(self.frame,"MainPanel")
+ self.panel = xrc.XRCCTRL(self.frame,"MainPanel")
# matplotlib panel -------------
# container for matplotlib panel (I like to make a container
# panel for our panel so I know where it'll go when in XRCed.)
- plot_container = XRCCTRL(self.frame,"plot_container_panel")
- sizer = BoxSizer(VERTICAL)
+ plot_container = xrc.XRCCTRL(self.frame,"plot_container_panel")
+ sizer = wx.BoxSizer(wx.VERTICAL)
# matplotlib panel itself
self.plotpanel = PlotPanel(plot_container)
self.plotpanel.init_plot_data()
# wx boilerplate
- sizer.Add(self.plotpanel, 1, EXPAND)
+ sizer.Add(self.plotpanel, 1, wx.EXPAND)
plot_container.SetSizer(sizer)
# whiz button ------------------
- whiz_button = XRCCTRL(self.frame,"whiz_button")
- EVT_BUTTON(whiz_button, whiz_button.GetId(),
- self.plotpanel.OnWhiz)
+ whiz_button = xrc.XRCCTRL(self.frame,"whiz_button")
+ wx.EVT_BUTTON(whiz_button, whiz_button.GetId(),
+ self.plotpanel.OnWhiz)
# bang button ------------------
- bang_button = XRCCTRL(self.frame,"bang_button")
- EVT_BUTTON(bang_button, bang_button.GetId(),
- self.OnBang)
+ bang_button = xrc.XRCCTRL(self.frame,"bang_button")
+ wx.EVT_BUTTON(bang_button, bang_button.GetId(),
+ self.OnBang)
# final setup ------------------
Modified: trunk/matplotlib/examples/user_interfaces/embedding_in_wx4.py
===================================================================
--- trunk/matplotlib/examples/user_interfaces/embedding_in_wx4.py 2009-03-11 19:36:22 UTC (rev 6972)
+++ trunk/matplotlib/examples/user_interfaces/embedding_in_wx4.py 2009-03-11 19:45:23 UTC (rev 6973)
@@ -4,6 +4,10 @@
toolbar
"""
+# Used to guarantee to use at least Wx2.8
+import wxversion
+wxversion.ensureMinimal('2.8')
+
from numpy import arange, sin, pi
import matplotlib
@@ -16,13 +20,13 @@
from matplotlib.figure import Figure
from numpy.random import rand
-from wx import *
+import wx
class MyNavigationToolbar(NavigationToolbar2WxAgg):
"""
Extend the default wx toolbar with your own event handlers
"""
- ON_CUSTOM = NewId()
+ ON_CUSTOM = wx.NewId()
def __init__(self, canvas, cankill):
NavigationToolbar2WxAgg.__init__(self, canvas)
@@ -30,7 +34,7 @@
# probably want to add your own.
self.AddSimpleTool(self.ON_CUSTOM, _load_bitmap('stock_left.xpm'),
'Click me', 'Activate custom contol')
- EVT_TOOL(self, self.ON_CUSTOM, self._on_custom)
+ wx.EVT_TOOL(self, self.ON_CUSTOM, self._on_custom)
def _on_custom(self, evt):
# add some text to the axes in a random location in axes (0,1)
@@ -51,13 +55,13 @@
evt.Skip()
-class CanvasFrame(Frame):
+class CanvasFrame(wx.Frame):
def __init__(self):
- Frame.__init__(self,None,-1,
+ wx.Frame.__init__(self,None,-1,
'CanvasFrame',size=(550,350))
- self.SetBackgroundColour(NamedColor("WHITE"))
+ self.SetBackgroundColour(wx.NamedColor("WHITE"))
self.figure = Figure(figsize=(5,4), dpi=100)
self.axes = self.figure.add_subplot(111)
@@ -68,14 +72,14 @@
self.canvas = FigureCanvas(self, -1, self.figure)
- self.sizer = BoxSizer(VERTICAL)
- self.sizer.Add(self.canvas, 1, TOP | LEFT | EXPAND)
+ self.sizer = wx.BoxSizer(wx.VERTICAL)
+ self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND)
# Capture the paint message
- EVT_PAINT(self, self.OnPaint)
+ wx.EVT_PAINT(self, self.OnPaint)
self.toolbar = MyNavigationToolbar(self.canvas, True)
self.toolbar.Realize()
- if Platform == '__WXMAC__':
+ if wx.Platform == '__WXMAC__':
# Mac platform (OSX 10.3, MacPython) does not seem to cope with
# having a toolbar in a sizer. This work-around gets the buttons
# back, but at the expense of having the toolbar at the top
@@ -88,8 +92,8 @@
# By adding toolbar in sizer, we are able to put it at the bottom
# of the frame - so appearance is closer to GTK version.
# As noted above, doesn't work for Mac.
- self.toolbar.SetSize(Size(fw, th))
- self.sizer.Add(self.toolbar, 0, LEFT | EXPAND)
+ self.toolbar.SetSize(wx.Size(fw, th))
+ self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
# update the axes menu on the toolbar
self.toolbar.update()
@@ -101,7 +105,7 @@
self.canvas.draw()
event.Skip()
-class App(App):
+class App(wx.App):
def OnInit(self):
'Create the main window and insert the custom frame'
Modified: trunk/matplotlib/examples/user_interfaces/embedding_in_wx5.py
===================================================================
--- trunk/matplotlib/examples/user_interfaces/embedding_in_wx5.py 2009-03-11 19:36:22 UTC (rev 6972)
+++ trunk/matplotlib/examples/user_interfaces/embedding_in_wx5.py 2009-03-11 19:45:23 UTC (rev 6973)
@@ -1,3 +1,7 @@
+# Used to guarantee to use at least Wx2.8
+import wxversion
+wxversion.ensureMinimal('2.8')
+
import wx
import wx.aui
import matplotlib as mpl
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wx.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2009-03-11 19:36:22 UTC (rev 6972)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2009-03-11 19:45:23 UTC (rev 6973)
@@ -108,12 +108,23 @@
import traceback, pdb
_DEBUG_lvls = {1 : 'Low ', 2 : 'Med ', 3 : 'High', 4 : 'Error' }
+missingwx = "Matplotlib backend_wx and backend_wxagg require wxPython >=2.8"
try:
+ import wxversion
+except ImportError:
+ raise ImportError(missingwx)
+
+try:
+ wxversion.ensureMinimal('2.8')
+except wxversion.AlreadyImportedError:
+ pass
+
+try:
import wx
backend_version = wx.VERSION_STRING
-except:
- raise ImportError("Matplotlib backend_wx requires wxPython be installed")
+except ImportError:
+ raise ImportError(missingwx)
#!!! this is the call that is causing the exception swallowing !!!
#wx.InitAllImageHandlers()
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wxagg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_wxagg.py 2009-03-11 19:36:22 UTC (rev 6972)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_wxagg.py 2009-03-11 19:45:23 UTC (rev 6973)
@@ -16,17 +16,16 @@
"""
-import wx
import matplotlib
from matplotlib.figure import Figure
from backend_agg import FigureCanvasAgg
-import backend_wx
+import backend_wx # already uses wxversion.ensureMinimal('2.8')
from backend_wx import FigureManager, FigureManagerWx, FigureCanvasWx, \
FigureFrameWx, DEBUG_MSG, NavigationToolbar2Wx, error_msg_wx, \
draw_if_interactive, show, Toolbar, backend_version
+import wx
-
class FigureFrameWxAgg(FigureFrameWx):
def get_canvas(self, fig):
return FigureCanvasWxAgg(self, -1, fig)
Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771
/branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960
+ /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771
/branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972
Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771
/branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960
+ /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771
/branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972
Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771
/branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960
+ /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771
/branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ef...@us...> - 2009-03-11 19:37:06
|
Revision: 6972
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6972&view=rev
Author: efiring
Date: 2009-03-11 19:36:22 +0000 (Wed, 11 Mar 2009)
Log Message:
-----------
Ensure wx version >= 2.8; Sandro Tosi patch plus change to backend
Modified Paths:
--------------
branches/v0_98_5_maint/CHANGELOG
branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx2.py
branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx3.py
branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx4.py
branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx5.py
branches/v0_98_5_maint/lib/matplotlib/backends/backend_wx.py
branches/v0_98_5_maint/lib/matplotlib/backends/backend_wxagg.py
Modified: branches/v0_98_5_maint/CHANGELOG
===================================================================
--- branches/v0_98_5_maint/CHANGELOG 2009-03-10 20:45:44 UTC (rev 6971)
+++ branches/v0_98_5_maint/CHANGELOG 2009-03-11 19:36:22 UTC (rev 6972)
@@ -1,3 +1,6 @@
+2009-03-11 Ensure wx version >= 2.8; thanks to Sandro Tosi and
+ Chris Barker. - EF
+
2009-02-26 Support image clipping in pdf backend. - JKS
2009-02-16 Move plot_directive.py to the installed source tree. Add
Modified: branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx2.py
===================================================================
--- branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx2.py 2009-03-10 20:45:44 UTC (rev 6971)
+++ branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx2.py 2009-03-11 19:36:22 UTC (rev 6972)
@@ -4,6 +4,10 @@
toolbar - comment out the setA_toolbar line for no toolbar
"""
+# Used to guarantee to use at least Wx2.8
+import wxversion
+wxversion.ensureMinimal('2.8')
+
from numpy import arange, sin, pi
import matplotlib
@@ -20,15 +24,15 @@
from matplotlib.figure import Figure
-from wx import *
+import wx
-class CanvasFrame(Frame):
+class CanvasFrame(wx.Frame):
def __init__(self):
- Frame.__init__(self,None,-1,
+ wx.Frame.__init__(self,None,-1,
'CanvasFrame',size=(550,350))
- self.SetBackgroundColour(NamedColor("WHITE"))
+ self.SetBackgroundColour(wx.NamedColor("WHITE"))
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
@@ -38,8 +42,8 @@
self.axes.plot(t,s)
self.canvas = FigureCanvas(self, -1, self.figure)
- self.sizer = BoxSizer(VERTICAL)
- self.sizer.Add(self.canvas, 1, LEFT | TOP | GROW)
+ self.sizer = wx.BoxSizer(wx.VERTICAL)
+ self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.SetSizer(self.sizer)
self.Fit()
@@ -49,7 +53,7 @@
def add_toolbar(self):
self.toolbar = NavigationToolbar2Wx(self.canvas)
self.toolbar.Realize()
- if Platform == '__WXMAC__':
+ if wx.Platform == '__WXMAC__':
# Mac platform (OSX 10.3, MacPython) does not seem to cope with
# having a toolbar in a sizer. This work-around gets the buttons
# back, but at the expense of having the toolbar at the top
@@ -62,8 +66,8 @@
# By adding toolbar in sizer, we are able to put it at the bottom
# of the frame - so appearance is closer to GTK version.
# As noted above, doesn't work for Mac.
- self.toolbar.SetSize(Size(fw, th))
- self.sizer.Add(self.toolbar, 0, LEFT | EXPAND)
+ self.toolbar.SetSize(wx.Size(fw, th))
+ self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
# update the axes menu on the toolbar
self.toolbar.update()
@@ -71,7 +75,7 @@
def OnPaint(self, event):
self.canvas.draw()
-class App(App):
+class App(wx.App):
def OnInit(self):
'Create the main window and insert the custom frame'
Modified: branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx3.py
===================================================================
--- branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx3.py 2009-03-10 20:45:44 UTC (rev 6971)
+++ branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx3.py 2009-03-11 19:36:22 UTC (rev 6972)
@@ -18,6 +18,11 @@
Thanks to matplotlib and wx teams for creating such great software!
"""
+
+# Used to guarantee to use at least Wx2.8
+import wxversion
+wxversion.ensureMinimal('2.8')
+
import sys, time, os, gc
import matplotlib
matplotlib.use('WXAgg')
@@ -26,18 +31,18 @@
from matplotlib.figure import Figure
import numpy as npy
-from wx import *
-from wx.xrc import *
+import wx
+import wx.xrc as xrc
ERR_TOL = 1e-5 # floating point slop for peak-detection
matplotlib.rc('image', origin='lower')
-class PlotPanel(Panel):
+class PlotPanel(wx.Panel):
def __init__(self, parent):
- Panel.__init__(self, parent, -1)
+ wx.Panel.__init__(self, parent, -1)
self.fig = Figure((5,4), 75)
self.canvas = FigureCanvasWxAgg(self, -1, self.fig)
@@ -46,11 +51,11 @@
#self.toolbar.set_active([0,1])
# Now put all into a sizer
- sizer = BoxSizer(VERTICAL)
+ sizer = wx.BoxSizer(wx.VERTICAL)
# This way of adding to sizer allows resizing
- sizer.Add(self.canvas, 1, LEFT|TOP|GROW)
+ sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
# Best to allow the toolbar to resize!
- sizer.Add(self.toolbar, 0, GROW)
+ sizer.Add(self.toolbar, 0, wx.GROW)
self.SetSizer(sizer)
self.Fit()
@@ -94,43 +99,43 @@
# this is supposed to prevent redraw flicker on some X servers...
pass
-class MyApp(App):
+class MyApp(wx.App):
def OnInit(self):
xrcfile = os.path.join(os.path.dirname(__file__),"..","data",
"embedding_in_wx3.xrc")
- self.res = XmlResource(xrcfile)
+ self.res = xrc.XmlResource(xrcfile)
# main frame and panel ---------
self.frame = self.res.LoadFrame(None,"MainFrame")
- self.panel = XRCCTRL(self.frame,"MainPanel")
+ self.panel = xrc.XRCCTRL(self.frame,"MainPanel")
# matplotlib panel -------------
# container for matplotlib panel (I like to make a container
# panel for our panel so I know where it'll go when in XRCed.)
- plot_container = XRCCTRL(self.frame,"plot_container_panel")
- sizer = BoxSizer(VERTICAL)
+ plot_container = xrc.XRCCTRL(self.frame,"plot_container_panel")
+ sizer = wx.BoxSizer(wx.VERTICAL)
# matplotlib panel itself
self.plotpanel = PlotPanel(plot_container)
self.plotpanel.init_plot_data()
# wx boilerplate
- sizer.Add(self.plotpanel, 1, EXPAND)
+ sizer.Add(self.plotpanel, 1, wx.EXPAND)
plot_container.SetSizer(sizer)
# whiz button ------------------
- whiz_button = XRCCTRL(self.frame,"whiz_button")
- EVT_BUTTON(whiz_button, whiz_button.GetId(),
- self.plotpanel.OnWhiz)
+ whiz_button = xrc.XRCCTRL(self.frame,"whiz_button")
+ wx.EVT_BUTTON(whiz_button, whiz_button.GetId(),
+ self.plotpanel.OnWhiz)
# bang button ------------------
- bang_button = XRCCTRL(self.frame,"bang_button")
- EVT_BUTTON(bang_button, bang_button.GetId(),
- self.OnBang)
+ bang_button = xrc.XRCCTRL(self.frame,"bang_button")
+ wx.EVT_BUTTON(bang_button, bang_button.GetId(),
+ self.OnBang)
# final setup ------------------
Modified: branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx4.py
===================================================================
--- branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx4.py 2009-03-10 20:45:44 UTC (rev 6971)
+++ branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx4.py 2009-03-11 19:36:22 UTC (rev 6972)
@@ -4,6 +4,10 @@
toolbar
"""
+# Used to guarantee to use at least Wx2.8
+import wxversion
+wxversion.ensureMinimal('2.8')
+
from numpy import arange, sin, pi
import matplotlib
@@ -16,13 +20,13 @@
from matplotlib.figure import Figure
from numpy.random import rand
-from wx import *
+import wx
class MyNavigationToolbar(NavigationToolbar2WxAgg):
"""
Extend the default wx toolbar with your own event handlers
"""
- ON_CUSTOM = NewId()
+ ON_CUSTOM = wx.NewId()
def __init__(self, canvas, cankill):
NavigationToolbar2WxAgg.__init__(self, canvas)
@@ -30,7 +34,7 @@
# probably want to add your own.
self.AddSimpleTool(self.ON_CUSTOM, _load_bitmap('stock_left.xpm'),
'Click me', 'Activate custom contol')
- EVT_TOOL(self, self.ON_CUSTOM, self._on_custom)
+ wx.EVT_TOOL(self, self.ON_CUSTOM, self._on_custom)
def _on_custom(self, evt):
# add some text to the axes in a random location in axes (0,1)
@@ -51,13 +55,13 @@
evt.Skip()
-class CanvasFrame(Frame):
+class CanvasFrame(wx.Frame):
def __init__(self):
- Frame.__init__(self,None,-1,
+ wx.Frame.__init__(self,None,-1,
'CanvasFrame',size=(550,350))
- self.SetBackgroundColour(NamedColor("WHITE"))
+ self.SetBackgroundColour(wx.NamedColor("WHITE"))
self.figure = Figure(figsize=(5,4), dpi=100)
self.axes = self.figure.add_subplot(111)
@@ -68,14 +72,14 @@
self.canvas = FigureCanvas(self, -1, self.figure)
- self.sizer = BoxSizer(VERTICAL)
- self.sizer.Add(self.canvas, 1, TOP | LEFT | EXPAND)
+ self.sizer = wx.BoxSizer(wx.VERTICAL)
+ self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND)
# Capture the paint message
- EVT_PAINT(self, self.OnPaint)
+ wx.EVT_PAINT(self, self.OnPaint)
self.toolbar = MyNavigationToolbar(self.canvas, True)
self.toolbar.Realize()
- if Platform == '__WXMAC__':
+ if wx.Platform == '__WXMAC__':
# Mac platform (OSX 10.3, MacPython) does not seem to cope with
# having a toolbar in a sizer. This work-around gets the buttons
# back, but at the expense of having the toolbar at the top
@@ -88,8 +92,8 @@
# By adding toolbar in sizer, we are able to put it at the bottom
# of the frame - so appearance is closer to GTK version.
# As noted above, doesn't work for Mac.
- self.toolbar.SetSize(Size(fw, th))
- self.sizer.Add(self.toolbar, 0, LEFT | EXPAND)
+ self.toolbar.SetSize(wx.Size(fw, th))
+ self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
# update the axes menu on the toolbar
self.toolbar.update()
@@ -101,7 +105,7 @@
self.canvas.draw()
event.Skip()
-class App(App):
+class App(wx.App):
def OnInit(self):
'Create the main window and insert the custom frame'
Modified: branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx5.py
===================================================================
--- branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx5.py 2009-03-10 20:45:44 UTC (rev 6971)
+++ branches/v0_98_5_maint/examples/user_interfaces/embedding_in_wx5.py 2009-03-11 19:36:22 UTC (rev 6972)
@@ -1,3 +1,7 @@
+# Used to guarantee to use at least Wx2.8
+import wxversion
+wxversion.ensureMinimal('2.8')
+
import wx
import wx.aui
import matplotlib as mpl
Modified: branches/v0_98_5_maint/lib/matplotlib/backends/backend_wx.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/backends/backend_wx.py 2009-03-10 20:45:44 UTC (rev 6971)
+++ branches/v0_98_5_maint/lib/matplotlib/backends/backend_wx.py 2009-03-11 19:36:22 UTC (rev 6972)
@@ -108,12 +108,23 @@
import traceback, pdb
_DEBUG_lvls = {1 : 'Low ', 2 : 'Med ', 3 : 'High', 4 : 'Error' }
+missingwx = "Matplotlib backend_wx and backend_wxagg require wxPython >=2.8"
try:
+ import wxversion
+except ImportError:
+ raise ImportError(missingwx)
+
+try:
+ wxversion.ensureMinimal('2.8')
+except wxversion.AlreadyImportedError:
+ pass
+
+try:
import wx
backend_version = wx.VERSION_STRING
-except:
- raise ImportError("Matplotlib backend_wx requires wxPython be installed")
+except ImportError:
+ raise ImportError(missingwx)
#!!! this is the call that is causing the exception swallowing !!!
#wx.InitAllImageHandlers()
Modified: branches/v0_98_5_maint/lib/matplotlib/backends/backend_wxagg.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/backends/backend_wxagg.py 2009-03-10 20:45:44 UTC (rev 6971)
+++ branches/v0_98_5_maint/lib/matplotlib/backends/backend_wxagg.py 2009-03-11 19:36:22 UTC (rev 6972)
@@ -16,17 +16,16 @@
"""
-import wx
import matplotlib
from matplotlib.figure import Figure
from backend_agg import FigureCanvasAgg
-import backend_wx
+import backend_wx # already uses wxversion.ensureMinimal('2.8')
from backend_wx import FigureManager, FigureManagerWx, FigureCanvasWx, \
FigureFrameWx, DEBUG_MSG, NavigationToolbar2Wx, error_msg_wx, \
draw_if_interactive, show, Toolbar, backend_version
+import wx
-
class FigureFrameWxAgg(FigureFrameWx):
def get_canvas(self, fig):
return FigureCanvasWxAgg(self, -1, fig)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jo...@us...> - 2009-03-10 20:45:59
|
Revision: 6971
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6971&view=rev
Author: jouni
Date: 2009-03-10 20:45:44 +0000 (Tue, 10 Mar 2009)
Log Message:
-----------
Fix join style bug in pdf.
Modified Paths:
--------------
trunk/matplotlib/CHANGELOG
trunk/matplotlib/examples/tests/backend_driver.py
trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
Added Paths:
-----------
trunk/matplotlib/examples/api/joinstyle.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2009-03-09 15:19:49 UTC (rev 6970)
+++ trunk/matplotlib/CHANGELOG 2009-03-10 20:45:44 UTC (rev 6971)
@@ -1,3 +1,5 @@
+2009-03-10 Fix join style bug in pdf. - JKS
+
2009-03-07 Add pyplot access to figure number list - EF
2009-02-28 hashing of FontProperties accounts current rcParams - JJL
Added: trunk/matplotlib/examples/api/joinstyle.py
===================================================================
--- trunk/matplotlib/examples/api/joinstyle.py (rev 0)
+++ trunk/matplotlib/examples/api/joinstyle.py 2009-03-10 20:45:44 UTC (rev 6971)
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+"""
+Illustrate the three different join styles
+"""
+
+import numpy as np
+import matplotlib
+import matplotlib.pyplot as plt
+
+def plot_angle(ax, x, y, angle, style):
+ phi = angle/180*np.pi
+ xx = [x+.5,x,x+.5*np.cos(phi)]
+ yy = [y,y,y+.5*np.sin(phi)]
+ ax.plot(xx, yy, lw=8, color='blue', solid_joinstyle=style)
+ ax.plot(xx[1:], yy[1:], lw=1, color='black')
+ ax.plot(xx[1::-1], yy[1::-1], lw=1, color='black')
+ ax.plot(xx[1:2], yy[1:2], 'o', color='red', markersize=3)
+ ax.text(x,y+.2,'%.0f degrees' % angle)
+
+fig = plt.figure()
+ax = fig.add_subplot(111)
+ax.set_title('Join style')
+
+for x,style in enumerate((('miter', 'round', 'bevel'))):
+ ax.text(x, 5, style)
+ for i in range(5):
+ plot_angle(ax, x, i, pow(2.0,3+i), style)
+
+ax.set_xlim(-.5,2.75)
+ax.set_ylim(-.5,5.5)
+plt.show()
Modified: trunk/matplotlib/examples/tests/backend_driver.py
===================================================================
--- trunk/matplotlib/examples/tests/backend_driver.py 2009-03-09 15:19:49 UTC (rev 6970)
+++ trunk/matplotlib/examples/tests/backend_driver.py 2009-03-10 20:45:44 UTC (rev 6971)
@@ -211,6 +211,7 @@
'font_family_rc.py',
'histogram_demo.py',
'image_zcoord.py',
+ 'joinstyle.py',
'legend_demo.py',
'line_with_text.py',
'logo2.py',
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-03-09 15:19:49 UTC (rev 6970)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-03-10 20:45:44 UTC (rev 6971)
@@ -427,6 +427,9 @@
self.beginStream(contentObject.id,
self.reserveObject('length of content stream'))
+ # Initialize the pdf graphics state to match the default mpl
+ # graphics context: currently only the join style needs to be set
+ self.output(GraphicsContextPdf.joinstyles['round'], Op.setlinejoin)
def close(self):
self.endStream()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-09 15:20:08
|
Revision: 6970
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6970&view=rev
Author: jswhit
Date: 2009-03-09 15:19:49 +0000 (Mon, 09 Mar 2009)
Log Message:
-----------
tweak interp docstring to be more general (xout, yout don't actually have to be rank-2)
Modified Paths:
--------------
trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py 2009-03-08 13:29:00 UTC (rev 6969)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py 2009-03-09 15:19:49 UTC (rev 6970)
@@ -3598,8 +3598,7 @@
y, 2nd dimension x.
xin, yin rank-1 arrays containing x and y of
datain grid in increasing order.
- xout, yout rank-2 arrays containing x and y of desired output
- grid.
+ xout, yout arrays containing x and y of desired output grid.
============== ====================================================
.. tabularcolumns:: |l|L|
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-08 13:29:04
|
Revision: 6969
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6969&view=rev
Author: jswhit
Date: 2009-03-08 13:29:00 +0000 (Sun, 08 Mar 2009)
Log Message:
-----------
streamline extrema function
Modified Paths:
--------------
trunk/toolkits/basemap/examples/plothighsandlows.py
Modified: trunk/toolkits/basemap/examples/plothighsandlows.py
===================================================================
--- trunk/toolkits/basemap/examples/plothighsandlows.py 2009-03-08 13:18:34 UTC (rev 6968)
+++ trunk/toolkits/basemap/examples/plothighsandlows.py 2009-03-08 13:29:00 UTC (rev 6969)
@@ -9,15 +9,14 @@
from scipy.ndimage.filters import minimum_filter, maximum_filter
def extrema(mat,mode='wrap',window=10):
+ """find the indices of local extrema (min and max)
+ in the input array."""
mn = minimum_filter(mat, size=window, mode=mode)
mx = maximum_filter(mat, size=window, mode=mode)
# (mat == mx) true if pixel is equal to the local max
- # The next computation suppresses responses where
- # the function is flat.
- local_maxima = ((mat == mx) & (mat != mn))
- local_minima = ((mat == mn) & (mat != mx))
- # Get the indices of the maxima, minima
- return np.nonzero(local_minima), np.nonzero(local_maxima)
+ # (mat == mn) true if pixel is equal to the local in
+ # Return the indices of the maxima, minima
+ return np.nonzero(mat == mn), np.nonzero(mat == mx)
if len(sys.argv) < 2:
print 'enter date to plot (YYYYMMDDHH) on command line'
@@ -65,8 +64,8 @@
# plot lows as blue L's, with min pressure value underneath.
xyplotted = []
# don't plot if there is already a L or H within dmin meters.
-dmin = 500000
yoffset = 0.022*(m.ymax-m.ymin)
+dmin = yoffset
for x,y,p in zip(xlows, ylows, lowvals):
if x < m.xmax and x > m.xmin and y < m.ymax and y > m.ymin:
dist = [np.sqrt((x-x0)**2+(y-y0)**2) for x0,y0 in xyplotted]
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-08 13:18:49
|
Revision: 6968
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6968&view=rev
Author: jswhit
Date: 2009-03-08 13:18:34 +0000 (Sun, 08 Mar 2009)
Log Message:
-----------
make central pressures more readable by making text boxes semi-transparent
Modified Paths:
--------------
trunk/toolkits/basemap/examples/plothighsandlows.py
Modified: trunk/toolkits/basemap/examples/plothighsandlows.py
===================================================================
--- trunk/toolkits/basemap/examples/plothighsandlows.py 2009-03-08 13:05:11 UTC (rev 6967)
+++ trunk/toolkits/basemap/examples/plothighsandlows.py 2009-03-08 13:18:34 UTC (rev 6968)
@@ -72,11 +72,10 @@
dist = [np.sqrt((x-x0)**2+(y-y0)**2) for x0,y0 in xyplotted]
if not dist or min(dist) > dmin:
plt.text(x,y,'L',fontsize=14,fontweight='bold',
- horizontalalignment='center',
- verticalalignment='center',color='blue')
+ ha='center',va='center',color='b')
plt.text(x,y-yoffset,repr(int(p)),fontsize=9,
- horizontalalignment='center',
- verticalalignment='top',color='blue')
+ ha='center',va='top',color='b',
+ bbox = dict(boxstyle="square",ec='None',fc=(1,1,1,0.5)))
xyplotted.append((x,y))
# plot highs as red H's, with max pressure value underneath.
xyplotted = []
@@ -85,11 +84,10 @@
dist = [np.sqrt((x-x0)**2+(y-y0)**2) for x0,y0 in xyplotted]
if not dist or min(dist) > dmin:
plt.text(x,y,'H',fontsize=14,fontweight='bold',
- horizontalalignment='center',
- verticalalignment='center',color='red')
+ ha='center',va='center',color='r')
plt.text(x,y-yoffset,repr(int(p)),fontsize=9,
- horizontalalignment='center',
- verticalalignment='top',color='red')
+ ha='center',va='top',color='r',
+ bbox = dict(boxstyle="square",ec='None',fc=(1,1,1,0.5)))
xyplotted.append((x,y))
plt.title('Mean Sea-Level Pressure (with Highs and Lows) %s' % YYYYMMDDHH)
plt.show()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-08 13:05:19
|
Revision: 6967
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6967&view=rev
Author: jswhit
Date: 2009-03-08 13:05:11 +0000 (Sun, 08 Mar 2009)
Log Message:
-----------
cosmetic changes.
Modified Paths:
--------------
trunk/toolkits/basemap/examples/plothighsandlows.py
Modified: trunk/toolkits/basemap/examples/plothighsandlows.py
===================================================================
--- trunk/toolkits/basemap/examples/plothighsandlows.py 2009-03-08 06:37:06 UTC (rev 6966)
+++ trunk/toolkits/basemap/examples/plothighsandlows.py 2009-03-08 13:05:11 UTC (rev 6967)
@@ -43,7 +43,8 @@
# (higher value, fewer highs and lows)
local_min, local_max = extrema(prmsl, mode='wrap', window=25)
# create Basemap instance.
-m = Basemap(llcrnrlon=0,llcrnrlat=-65,urcrnrlon=360,urcrnrlat=65,projection='merc')
+m =\
+Basemap(llcrnrlon=0,llcrnrlat=-80,urcrnrlon=360,urcrnrlat=80,projection='mill')
# add wrap-around point in longitude.
prmsl, lons = addcyclic(prmsl, lons1)
# contour levels
@@ -56,8 +57,8 @@
cs = m.contour(x,y,prmsl,clevs,colors='k',linewidths=1.)
m.drawcoastlines(linewidth=1.25)
m.fillcontinents(color='0.8')
-m.drawparallels(np.arange(-80,81,20))
-m.drawmeridians(np.arange(0,360,60))
+m.drawparallels(np.arange(-80,81,20),labels=[1,1,0,0])
+m.drawmeridians(np.arange(0,360,60),labels=[0,0,0,1])
xlows = x[local_min]; xhighs = x[local_max]
ylows = y[local_min]; yhighs = y[local_max]
lowvals = prmsl[local_min]; highvals = prmsl[local_max]
@@ -65,6 +66,7 @@
xyplotted = []
# don't plot if there is already a L or H within dmin meters.
dmin = 500000
+yoffset = 0.022*(m.ymax-m.ymin)
for x,y,p in zip(xlows, ylows, lowvals):
if x < m.xmax and x > m.xmin and y < m.ymax and y > m.ymin:
dist = [np.sqrt((x-x0)**2+(y-y0)**2) for x0,y0 in xyplotted]
@@ -72,7 +74,7 @@
plt.text(x,y,'L',fontsize=14,fontweight='bold',
horizontalalignment='center',
verticalalignment='center',color='blue')
- plt.text(x,y-400000,repr(int(p)),fontsize=9,
+ plt.text(x,y-yoffset,repr(int(p)),fontsize=9,
horizontalalignment='center',
verticalalignment='top',color='blue')
xyplotted.append((x,y))
@@ -85,7 +87,7 @@
plt.text(x,y,'H',fontsize=14,fontweight='bold',
horizontalalignment='center',
verticalalignment='center',color='red')
- plt.text(x,y-400000,repr(int(p)),fontsize=9,
+ plt.text(x,y-yoffset,repr(int(p)),fontsize=9,
horizontalalignment='center',
verticalalignment='top',color='red')
xyplotted.append((x,y))
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ef...@us...> - 2009-03-08 06:37:15
|
Revision: 6966
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6966&view=rev
Author: efiring
Date: 2009-03-08 06:37:06 +0000 (Sun, 08 Mar 2009)
Log Message:
-----------
Let pyplot users find out if a figure number exists, or list fignums.
Modified Paths:
--------------
trunk/matplotlib/CHANGELOG
trunk/matplotlib/doc/api/api_changes.rst
trunk/matplotlib/lib/matplotlib/pyplot.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2009-03-07 23:47:02 UTC (rev 6965)
+++ trunk/matplotlib/CHANGELOG 2009-03-08 06:37:06 UTC (rev 6966)
@@ -1,3 +1,5 @@
+2009-03-07 Add pyplot access to figure number list - EF
+
2009-02-28 hashing of FontProperties accounts current rcParams - JJL
2009-02-28 Prevent double-rendering of shared axis in twinx, twiny - EF
Modified: trunk/matplotlib/doc/api/api_changes.rst
===================================================================
--- trunk/matplotlib/doc/api/api_changes.rst 2009-03-07 23:47:02 UTC (rev 6965)
+++ trunk/matplotlib/doc/api/api_changes.rst 2009-03-08 06:37:06 UTC (rev 6966)
@@ -19,8 +19,12 @@
Changes for 0.98.x
==================
-* Removed numerix package.
+* Added new :func:`matplotlib.pyplot.fignum_exists` and
+ :func:`matplotlib.pyplot.get_fignums`; they merely expose
+ information that had been hidden in :mod:`matplotlib._pylab_helpers`.
+* Deprecated numerix package.
+
* Added new :func:`matplotlib.image.imsave` and exposed it to the
:mod:`matplotlib.pyplot` interface.
@@ -46,7 +50,7 @@
================ ================
-* Removed the configobj and experiemtnal traits rc support
+* Removed the configobj and experimental traits rc support
* Modified :func:`matplotlib.mlab.psd`, :func:`matplotlib.mlab.csd`,
:func:`matplotlib.mlab.cohere`, and :func:`matplotlib.mlab.specgram`
Modified: trunk/matplotlib/lib/matplotlib/pyplot.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/pyplot.py 2009-03-07 23:47:02 UTC (rev 6965)
+++ trunk/matplotlib/lib/matplotlib/pyplot.py 2009-03-08 06:37:06 UTC (rev 6966)
@@ -273,6 +273,14 @@
else:
return figure()
+fignum_exists = _pylab_helpers.Gcf.has_fignum
+
+def get_fignums():
+ "Return a list of existing figure numbers."
+ fignums = _pylab_helpers.Gcf.figs.keys()
+ fignums.sort()
+ return fignums
+
def get_current_fig_manager():
figManager = _pylab_helpers.Gcf.get_active()
if figManager is None:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-07 23:47:24
|
Revision: 6965
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6965&view=rev
Author: jswhit
Date: 2009-03-07 23:47:02 +0000 (Sat, 07 Mar 2009)
Log Message:
-----------
add new example, fix formatting
Modified Paths:
--------------
trunk/toolkits/basemap/Changelog
Modified: trunk/toolkits/basemap/Changelog
===================================================================
--- trunk/toolkits/basemap/Changelog 2009-03-07 22:44:16 UTC (rev 6964)
+++ trunk/toolkits/basemap/Changelog 2009-03-07 23:47:02 UTC (rev 6965)
@@ -1,8 +1,9 @@
version 0.99.4 (not yet released)
+ * added new example "plothighsandlows.py".
* add fix_aspect kwarg to Basemap.__init__, when False
- axes.set_aspect is set to 'auto' instead of default 'equal'.
- Can be used to make plot fill whole plot region, even if the
- plot region doesn't match the aspect ratio of the map region.
+ axes.set_aspect is set to 'auto' instead of default 'equal'.
+ Can be used to make plot fill whole plot region, even if the
+ plot region doesn't match the aspect ratio of the map region.
* added date2index function, updated netcdftime to 0.7.1.
* added maskoceans function.
* update pupynere to version 1.0.8 (supports writing large files).
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-07 22:44:21
|
Revision: 6964
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6964&view=rev
Author: jswhit
Date: 2009-03-07 22:44:16 +0000 (Sat, 07 Mar 2009)
Log Message:
-----------
fix URL
Modified Paths:
--------------
trunk/toolkits/basemap/examples/plothighsandlows.py
Modified: trunk/toolkits/basemap/examples/plothighsandlows.py
===================================================================
--- trunk/toolkits/basemap/examples/plothighsandlows.py 2009-03-07 21:55:59 UTC (rev 6963)
+++ trunk/toolkits/basemap/examples/plothighsandlows.py 2009-03-07 22:44:16 UTC (rev 6964)
@@ -27,7 +27,10 @@
YYYYMMDDHH = sys.argv[1]
# open OpenDAP dataset.
-data=NetCDFFile("http://nomad1.ncep.noaa.gov:9090/dods/gdas/rotating/gdas"+YYYYMMDDHH)
+try:
+ data=NetCDFFile("http://nomad1.ncep.noaa.gov:9090/dods/gdas/rotating/gdas"+YYYYMMDDHH)
+except:
+ data=NetCDFFile("http://nomad1.ncep.noaa.gov:9090/dods/gdas/rotating/"+YYYYMMDDHH[0:6]+"/gdas"+YYYYMMDDHH)
# read lats,lons.
lats = data.variables['lat'][:]
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <js...@us...> - 2009-03-07 21:56:10
|
Revision: 6963
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6963&view=rev
Author: jswhit
Date: 2009-03-07 21:55:59 +0000 (Sat, 07 Mar 2009)
Log Message:
-----------
add comment
Modified Paths:
--------------
trunk/toolkits/basemap/examples/plothighsandlows.py
Modified: trunk/toolkits/basemap/examples/plothighsandlows.py
===================================================================
--- trunk/toolkits/basemap/examples/plothighsandlows.py 2009-03-07 21:52:21 UTC (rev 6962)
+++ trunk/toolkits/basemap/examples/plothighsandlows.py 2009-03-07 21:55:59 UTC (rev 6963)
@@ -1,5 +1,6 @@
"""
plot H's and L's on a sea-level pressure map
+(uses scipy.ndimage.filters)
"""
import numpy as np
import matplotlib.pyplot as plt
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|