From: <md...@us...> - 2008-06-04 13:09:57
|
Revision: 5380 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5380&view=rev Author: mdboom Date: 2008-06-04 06:09:55 -0700 (Wed, 04 Jun 2008) Log Message: ----------- Update pyparsing to get better error reporting from mathtext. Update mathtext_examples to include "$$" as a test. Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/mathtext_examples.py trunk/matplotlib/lib/matplotlib/mathtext.py trunk/matplotlib/lib/matplotlib/pyparsing.py Modified: trunk/matplotlib/examples/pylab_examples/mathtext_examples.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/mathtext_examples.py 2008-06-03 20:57:02 UTC (rev 5379) +++ trunk/matplotlib/examples/pylab_examples/mathtext_examples.py 2008-06-04 13:09:55 UTC (rev 5380) @@ -5,7 +5,7 @@ import gc stests = [ - r'Kerning: AVA $AVA$', + r'Kerning: AVA $AVA$ $$', r'\$100.00 $\alpha \_$', r'$\frac{\$100.00}{y}$', r'$x y$', Modified: trunk/matplotlib/lib/matplotlib/mathtext.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mathtext.py 2008-06-03 20:57:02 UTC (rev 5379) +++ trunk/matplotlib/lib/matplotlib/mathtext.py 2008-06-04 13:09:55 UTC (rev 5380) @@ -2024,7 +2024,7 @@ lbrace = Literal('{').suppress() rbrace = Literal('}').suppress() - start_group = (Optional(latexfont) + lbrace) + start_group = (Optional(latexfont) - lbrace) start_group.setParseAction(self.start_group) end_group = rbrace.copy() end_group.setParseAction(self.end_group) @@ -2049,9 +2049,9 @@ ).setParseAction(self.space).setName('space') customspace =(Literal(r'\hspace') - + (( lbrace - + float - + rbrace + - (( lbrace + - float + - rbrace ) | Error(r"Expected \hspace{n}")) ).setParseAction(self.customspace).setName('customspace') @@ -2070,7 +2070,7 @@ accent = Group( Suppress(bslash) + accent - + placeable + - placeable ).setParseAction(self.accent).setName("accent") function =(Suppress(bslash) @@ -2082,7 +2082,7 @@ + ZeroOrMore( autoDelim | simple) - + end_group + - end_group ).setParseAction(self.group).setName("group") font <<(Suppress(bslash) @@ -2101,20 +2101,30 @@ Suppress(Literal(r"\sqrt")) + Optional( Suppress(Literal("[")) - + Regex("[0-9]+") - + Suppress(Literal("]")), + - Regex("[0-9]+") + - Suppress(Literal("]")), default = None ) + (group | Error("Expected \sqrt{value}")) ).setParseAction(self.sqrt).setName("sqrt") + print (accent + ^ function + ^ (c_over_c | symbol) + ^ group + ^ frac + ^ sqrt + ) | Error("Expected symbol or group") + + print Error("Expected symbol or group") + placeable <<(accent ^ function ^ (c_over_c | symbol) ^ group ^ frac ^ sqrt - ) | Error("Expected symbol or group") + ) simple <<(space | customspace @@ -2128,7 +2138,7 @@ ( Optional(placeable) + OneOrMore( subsuperop - + placeable + - placeable ) ) | placeable @@ -2160,7 +2170,7 @@ non_math + ZeroOrMore( Suppress(math_delim) - + math + + Optional(math) + (Suppress(math_delim) | Error("Expected end of math '$'")) + non_math Modified: trunk/matplotlib/lib/matplotlib/pyparsing.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyparsing.py 2008-06-03 20:57:02 UTC (rev 5379) +++ trunk/matplotlib/lib/matplotlib/pyparsing.py 2008-06-04 13:09:55 UTC (rev 5380) @@ -1,6 +1,6 @@ # module pyparsing.py # -# Copyright (c) 2003-2007 Paul T. McGuire +# Copyright (c) 2003-2008 Paul T. McGuire # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -58,8 +58,8 @@ - embedded comments """ -__version__ = "1.4.8" -__versionTime__ = "7 October 2007 00:25" +__version__ = "1.5.0" +__versionTime__ = "28 May 2008 10:05" __author__ = "Paul McGuire <pt...@us...>" import string @@ -68,50 +68,68 @@ import warnings import re import sre_constants -try: - from xml.sax.saxutils import escape as xml_escape -except ImportError: - def xml_escape(data, entities={}): - """Escape &, <, and > in a string of data. +import xml.sax.saxutils +#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) - You can escape other strings of data by passing a dictionary as - the optional entities parameter. The keys and values must all be - strings; each key will be replaced with its corresponding value. - """ +__all__ = [ +'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', +'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', +'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', +'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', +'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', +'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', 'Upcase', +'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', +'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', +'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', +'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'getTokensEndLoc', 'hexnums', +'htmlComment', 'javaStyleComment', 'keepOriginalText', 'line', 'lineEnd', 'lineStart', 'lineno', +'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', +'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', +'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', +'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', +'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', +'indentedBlock', +] - # must do ampersand first - data = data.replace("&", "&") - data = data.replace(">", ">") - data = data.replace("<", "<") - if entities: - data = __dict_replace(data, entities) - return data -#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) +""" +Detect if we are running version 3.X and make appropriate changes +Robert A. Clark +""" +if sys.version_info[0] > 2: + _PY3K = True + _MAX_INT = sys.maxsize + basestring = str +else: + _PY3K = False + _MAX_INT = sys.maxint -def _ustr(obj): - """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries - str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It - then < returns the unicode object | encodes it with the default encoding | ... >. - """ - try: - # If this works, then _ustr(obj) has the same behaviour as str(obj), so - # it won't break any existing code. - return str(obj) +if not _PY3K: + def _ustr(obj): + """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries + str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It + then < returns the unicode object | encodes it with the default encoding | ... >. + """ + try: + # If this works, then _ustr(obj) has the same behaviour as str(obj), so + # it won't break any existing code. + return str(obj) - except UnicodeEncodeError, e: - # The Python docs (http://docs.python.org/ref/customization.html#l2h-182) - # state that "The return value must be a string object". However, does a - # unicode object (being a subclass of basestring) count as a "string - # object"? - # If so, then return a unicode object: - return unicode(obj) - # Else encode it... but how? There are many choices... :) - # Replace unprintables with escape codes? - #return unicode(obj).encode(sys.getdefaultencoding(), 'backslashreplace_errors') - # Replace unprintables with question marks? - #return unicode(obj).encode(sys.getdefaultencoding(), 'replace') - # ... + except UnicodeEncodeError: + # The Python docs (http://docs.python.org/ref/customization.html#l2h-182) + # state that "The return value must be a string object". However, does a + # unicode object (being a subclass of basestring) count as a "string + # object"? + # If so, then return a unicode object: + return unicode(obj) + # Else encode it... but how? There are many choices... :) + # Replace unprintables with escape codes? + #return unicode(obj).encode(sys.getdefaultencoding(), 'backslashreplace_errors') + # Replace unprintables with question marks? + #return unicode(obj).encode(sys.getdefaultencoding(), 'replace') + # ... +else: + _ustr = str def _str2dict(strg): return dict( [(c,0) for c in strg] ) @@ -120,10 +138,15 @@ class _Constants(object): pass -alphas = string.lowercase + string.uppercase +if not _PY3K: + alphas = string.lowercase + string.uppercase +else: + alphas = string.ascii_lowercase + string.ascii_uppercase nums = string.digits hexnums = nums + "ABCDEFabcdef" alphanums = alphas + nums +_bslash = "\\" +printables = "".join( [ c for c in string.printable if c not in string.whitespace ] ) class ParseBaseException(Exception): """base exception class for all parsing runtime exceptions""" @@ -153,7 +176,7 @@ elif( aname == "line" ): return line( self.loc, self.pstr ) else: - raise AttributeError, aname + raise AttributeError(aname) def __str__( self ): return "%s (at char %d), (line:%d, col:%d)" % \ @@ -185,6 +208,14 @@ is found; stops all parsing immediately""" pass +class ParseSyntaxException(ParseFatalException): + """just like ParseFatalException, but thrown internally when an + ErrorStop indicates that parsing is to stop immediately because + an unbacktrackable syntax error has been found""" + def __init__(self, pe): + super(ParseSyntaxException, self).__init__( + pe.pstr, pe.loc, pe.msg, pe.parserElement) + #~ class ReparseException(ParseBaseException): #~ """Experimental class - parse actions can raise this exception to cause #~ pyparsing to reparse the input string: @@ -283,31 +314,72 @@ self.__toklist[k] = v sub = v else: - self.__tokdict[k] = self.__tokdict.get(k,list()) + [(v,0)] + self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] sub = v if isinstance(sub,ParseResults): sub.__parent = wkref(self) def __delitem__( self, i ): if isinstance(i,(int,slice)): + mylen = len( self.__toklist ) del self.__toklist[i] + + # convert int to slice + if isinstance(i, int): + if i < 0: + i += mylen + i = slice(i, i+1) + # get removed indices + removed = list(range(*i.indices(mylen))) + removed.reverse() + # fixup indices in token dictionary + for name in self.__tokdict: + occurrences = self.__tokdict[name] + for j in removed: + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) else: del self.__tokdict[i] def __contains__( self, k ): - return self.__tokdict.has_key(k) + return k in self.__tokdict def __len__( self ): return len( self.__toklist ) def __bool__(self): return len( self.__toklist ) > 0 - def __nonzero__( self ): return self.__bool__() + __nonzero__ = __bool__ def __iter__( self ): return iter( self.__toklist ) + def __reversed__( self ): return iter( reversed(self.__toklist) ) def keys( self ): """Returns all named result keys.""" return self.__tokdict.keys() + def pop( self, index=-1 ): + """Removes and returns item at specified index (default=last). + Will work with either numeric indices or dict-key indicies.""" + ret = self[index] + del self[index] + return ret + + def get(self, key, defaultValue=None): + """Returns named result matching the given key, or if there is no + such name, then returns the given defaultValue or None if no + defaultValue is specified.""" + if key in self: + return self[key] + else: + return defaultValue + + def insert( self, index, insStr ): + self.__toklist.insert(index, insStr) + # fixup indices in token dictionary + for name in self.__tokdict: + occurrences = self.__tokdict[name] + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position + (position > j)) + def items( self ): """Returns all named result keys and values as a list of tuples.""" - return [(k,self[k]) for k in self.__tokdict.keys()] + return [(k,self[k]) for k in self.__tokdict] def values( self ): """Returns all named result values.""" @@ -315,7 +387,7 @@ def __getattr__( self, name ): if name not in self.__slots__: - if self.__tokdict.has_key( name ): + if name in self.__tokdict: if name not in self.__accumNames: return self.__tokdict[name][-1][0] else: @@ -446,7 +518,7 @@ continue else: resTag = "ITEM" - xmlBodyText = xml_escape(_ustr(res)) + xmlBodyText = xml.sax.saxutils.escape(_ustr(res)) out += [ nl, nextLevelIndent, "<", resTag, ">", xmlBodyText, "</", resTag, ">" ] @@ -559,13 +631,13 @@ return strg[lastCR+1:] def _defaultStartDebugAction( instring, loc, expr ): - print "Match",_ustr(expr),"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ) + print ("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): - print "Matched",_ustr(expr),"->",toks.asList() + print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) def _defaultExceptionDebugAction( instring, loc, expr, exc ): - print "Exception raised:", _ustr(exc) + print ("Exception raised:" + _ustr(exc)) def nullDebugAction(*args): """'Do-nothing' debug action, to suppress debugging output during parsing.""" @@ -652,7 +724,7 @@ self._parse = self._parse._originalParseMethod return self - def normalizeParseActionArgs( f ): + def _normalizeParseActionArgs( f ): """Internal method used to decorate parse actions that take fewer than 3 arguments, so that all parse actions can be called as f(s,l,t).""" STAR_ARGS = 4 @@ -662,34 +734,63 @@ if isinstance(f,type): restore = f f = f.__init__ - if f.func_code.co_flags & STAR_ARGS: + if not _PY3K: + codeObj = f.func_code + else: + codeObj = f.code + if codeObj.co_flags & STAR_ARGS: return f - numargs = f.func_code.co_argcount - if hasattr(f,"im_self"): - numargs -= 1 + numargs = codeObj.co_argcount + if not _PY3K: + if hasattr(f,"im_self"): + numargs -= 1 + else: + if hasattr(f,"__self__"): + numargs -= 1 if restore: f = restore except AttributeError: try: + if not _PY3K: + call_im_func_code = f.__call__.im_func.func_code + else: + call_im_func_code = f.__code__ + # not a function, must be a callable object, get info from the # im_func binding of its bound __call__ method - if f.__call__.im_func.func_code.co_flags & STAR_ARGS: + if call_im_func_code.co_flags & STAR_ARGS: return f - numargs = f.__call__.im_func.func_code.co_argcount - if hasattr(f.__call__,"im_self"): - numargs -= 1 + numargs = call_im_func_code.co_argcount + if not _PY3K: + if hasattr(f.__call__,"im_self"): + numargs -= 1 + else: + if hasattr(f.__call__,"__self__"): + numargs -= 0 except AttributeError: + if not _PY3K: + call_func_code = f.__call__.func_code + else: + call_func_code = f.__call__.__code__ # not a bound method, get info directly from __call__ method - if f.__call__.func_code.co_flags & STAR_ARGS: + if call_func_code.co_flags & STAR_ARGS: return f - numargs = f.__call__.func_code.co_argcount - if hasattr(f.__call__,"im_self"): - numargs -= 1 + numargs = call_func_code.co_argcount + if not _PY3K: + if hasattr(f.__call__,"im_self"): + numargs -= 1 + else: + if hasattr(f.__call__,"__self__"): + numargs -= 1 - #~ print "adding function %s with %d args" % (f.func_name,numargs) + + #~ print ("adding function %s with %d args" % (f.func_name,numargs)) if numargs == 3: return f else: + if numargs > 3: + def tmp(s,l,t): + return f(f.__call__.__self__, s,l,t) if numargs == 2: def tmp(s,l,t): return f(l,t) @@ -701,21 +802,21 @@ return f() try: tmp.__name__ = f.__name__ - except AttributeError: + except (AttributeError,TypeError): # no need for special handling if attribute doesnt exist pass try: tmp.__doc__ = f.__doc__ - except AttributeError: + except (AttributeError,TypeError): # no need for special handling if attribute doesnt exist pass try: tmp.__dict__.update(f.__dict__) - except AttributeError: + except (AttributeError,TypeError): # no need for special handling if attribute doesnt exist pass return tmp - normalizeParseActionArgs = staticmethod(normalizeParseActionArgs) + _normalizeParseActionArgs = staticmethod(_normalizeParseActionArgs) def setParseAction( self, *fns, **kwargs ): """Define action to perform when successfully matching parse element definition. @@ -734,13 +835,13 @@ consistent view of the parsed string, the parse location, and line and column positions within the parsed string. """ - self.parseAction = map(self.normalizeParseActionArgs, list(fns)) + self.parseAction = list(map(self._normalizeParseActionArgs, list(fns))) self.callDuringTry = ("callDuringTry" in kwargs and kwargs["callDuringTry"]) return self def addParseAction( self, *fns, **kwargs ): """Add parse action to expression's list of parse actions. See L{I{setParseAction}<setParseAction>}.""" - self.parseAction += map(self.normalizeParseActionArgs, list(fns)) + self.parseAction += list(map(self._normalizeParseActionArgs, list(fns))) self.callDuringTry = self.callDuringTry or ("callDuringTry" in kwargs and kwargs["callDuringTry"]) return self @@ -757,7 +858,7 @@ self.failAction = fn return self - def skipIgnorables( self, instring, loc ): + def _skipIgnorables( self, instring, loc ): exprsFound = True while exprsFound: exprsFound = False @@ -772,7 +873,7 @@ def preParse( self, instring, loc ): if self.ignoreExprs: - loc = self.skipIgnorables( instring, loc ) + loc = self._skipIgnorables( instring, loc ) if self.skipWhitespace: wt = self.whiteChars @@ -793,7 +894,7 @@ debugging = ( self.debug ) #and doActions ) if debugging or self.failAction: - #~ print "Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ) + #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) if (self.debugActions[0] ): self.debugActions[0]( instring, loc, self ) if callPreParse and self.callPreparse: @@ -806,8 +907,8 @@ loc,tokens = self.parseImpl( instring, preloc, doActions ) except IndexError: raise ParseException( instring, len(instring), self.errmsg, self ) - except ParseException, err: - #~ print "Exception raised:", err + except ParseBaseException, err: + #~ print ("Exception raised:", err) if self.debugActions[2]: self.debugActions[2]( instring, tokensStart, self, err ) if self.failAction: @@ -840,7 +941,7 @@ self.resultsName, asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), modal=self.modalResults ) - except ParseException, err: + except ParseBaseException, err: #~ print "Exception raised in user parse action:", err if (self.debugActions[2] ): self.debugActions[2]( instring, tokensStart, self, err ) @@ -855,14 +956,17 @@ modal=self.modalResults ) if debugging: - #~ print "Matched",self,"->",retTokens.asList() + #~ print ("Matched",self,"->",retTokens.asList()) if (self.debugActions[1] ): self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) return loc, retTokens def tryParse( self, instring, loc ): - return self._parse( instring, loc, doActions=False )[0] + try: + return self._parse( instring, loc, doActions=False )[0] + except ParseFatalException: + raise ParseException( instring, loc, self.errmsg, self) # this method gets repeatedly called during backtracking with the same arguments - # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression @@ -871,10 +975,8 @@ if lookup in ParserElement._exprArgCache: value = ParserElement._exprArgCache[ lookup ] if isinstance(value,Exception): - if isinstance(value,ParseBaseException): - value.loc = loc raise value - return (value[0],value[1].copy()) + return value else: try: value = self._parseNoCache( instring, loc, doActions, callPreParse ) @@ -914,11 +1016,15 @@ ParserElement._parse = ParserElement._parseCache enablePackrat = staticmethod(enablePackrat) - def parseString( self, instring ): + def parseString( self, instring, parseAll=False ): """Execute the parse expression with the given string. This is the main interface to the client code, once the complete expression has been built. + If you want the grammar to require that the entire input string be + successfully parsed, then set parseAll to True (equivalent to ending + the grammar with StringEnd()). + Note: parseString implicitly calls expandtabs() on the input string, in order to report proper column numbers in parse actions. If the input string contains tabs and @@ -938,13 +1044,14 @@ #~ self.saveAsList = True for e in self.ignoreExprs: e.streamline() - if self.keepTabs: - loc, tokens = self._parse( instring, 0 ) - else: - loc, tokens = self._parse( instring.expandtabs(), 0 ) + if not self.keepTabs: + instring = instring.expandtabs() + loc, tokens = self._parse( instring, 0 ) + if parseAll: + StringEnd()._parse( instring, loc ) return tokens - def scanString( self, instring, maxMatches=sys.maxint ): + def scanString( self, instring, maxMatches=_MAX_INT ): """Scan the input string for expression matches. Each match will return the matching tokens, start location, and end location. May be called with optional maxMatches argument, to clip scanning after 'n' matches are found. @@ -1001,7 +1108,7 @@ out.append(instring[lastE:]) return "".join(map(_ustr,out)) - def searchString( self, instring, maxMatches=sys.maxint ): + def searchString( self, instring, maxMatches=_MAX_INT ): """Another extension to scanString, simplifying the access to the tokens found to match the given parse expression. May be called with optional maxMatches argument, to clip searching after 'n' matches are found. @@ -1013,35 +1120,117 @@ if isinstance( other, basestring ): other = Literal( other ) if not isinstance( other, ParserElement ): - warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), SyntaxWarning, stacklevel=2) + return None return And( [ self, other ] ) def __radd__(self, other ): - """Implementation of += operator""" + """Implementation of + operator when left operand is not a ParserElement""" if isinstance( other, basestring ): other = Literal( other ) if not isinstance( other, ParserElement ): - warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), SyntaxWarning, stacklevel=2) + return None return other + self + def __sub__(self, other): + """Implementation of - operator, returns And with error stop""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return And( [ self, And._ErrorStop(), other ] ) + + def __rsub__(self, other ): + """Implementation of - operator when left operand is not a ParserElement""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other - self + + def __mul__(self,other): + if isinstance(other,int): + minElements, optElements = other,0 + elif isinstance(other,tuple): + if len(other)==0: + other = (None,None) + elif len(other)==1: + other = (other[0],None) + if len(other)==2: + if other[0] is None: + other = (0, other[1]) + if isinstance(other[0],int) and other[1] is None: + if other[0] == 0: + return ZeroOrMore(self) + if other[0] == 1: + return OneOrMore(self) + else: + return self*other[0] + ZeroOrMore(self) + elif isinstance(other[0],int) and isinstance(other[1],int): + minElements, optElements = other + optElements -= minElements + else: + raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) + else: + raise TypeError("can only multiply 'ParserElement' and int or (int,int) objects") + else: + raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) + + if minElements < 0: + raise ValueError("cannot multiply ParserElement by negative value") + if optElements < 0: + raise ValueError("second tuple value must be greater or equal to first tuple value") + if minElements == optElements == 0: + raise ValueError("cannot multiply ParserElement by 0 or (0,0)") + + if (optElements): + def makeOptionalList(n): + if n>1: + return Optional(self + makeOptionalList(n-1)) + else: + return Optional(self) + if minElements: + if minElements == 1: + ret = self + makeOptionalList(optElements) + else: + ret = And([self]*minElements) + makeOptionalList(optElements) + else: + ret = makeOptionalList(optElements) + else: + if minElements == 1: + ret = self + else: + ret = And([self]*minElements) + return ret + + def __rmul__(self, other): + return self.__mul__(other) + def __or__(self, other ): """Implementation of | operator - returns MatchFirst""" if isinstance( other, basestring ): other = Literal( other ) if not isinstance( other, ParserElement ): - warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), SyntaxWarning, stacklevel=2) + return None return MatchFirst( [ self, other ] ) def __ror__(self, other ): - """Implementation of |= operator""" + """Implementation of | operator when left operand is not a ParserElement""" if isinstance( other, basestring ): other = Literal( other ) if not isinstance( other, ParserElement ): - warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), SyntaxWarning, stacklevel=2) + return None return other | self def __xor__(self, other ): @@ -1049,17 +1238,19 @@ if isinstance( other, basestring ): other = Literal( other ) if not isinstance( other, ParserElement ): - warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), SyntaxWarning, stacklevel=2) + return None return Or( [ self, other ] ) def __rxor__(self, other ): - """Implementation of ^= operator""" + """Implementation of ^ operator when left operand is not a ParserElement""" if isinstance( other, basestring ): other = Literal( other ) if not isinstance( other, ParserElement ): - warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), SyntaxWarning, stacklevel=2) + return None return other ^ self def __and__(self, other ): @@ -1067,17 +1258,19 @@ if isinstance( other, basestring ): other = Literal( other ) if not isinstance( other, ParserElement ): - warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), SyntaxWarning, stacklevel=2) + return None return Each( [ self, other ] ) def __rand__(self, other ): - """Implementation of right-& operator""" + """Implementation of & operator when left operand is not a ParserElement""" if isinstance( other, basestring ): other = Literal( other ) if not isinstance( other, ParserElement ): - warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), SyntaxWarning, stacklevel=2) + return None return other & self def __invert__( self ): @@ -1189,8 +1382,25 @@ self.myException = ret = self.getException(); return ret; else: - raise AttributeError, "no such attribute " + aname + raise AttributeError("no such attribute " + aname) + def __eq__(self,other): + if isinstance(other, basestring): + try: + (self + StringEnd()).parseString(_ustr(other)) + return True + except ParseBaseException: + return False + else: + return super(ParserElement,self)==other + + def __hash__(self): + return hash(id(self)) + + def __req__(self,other): + return self == other + + class Token(ParserElement): """Abstract ParserElement subclass, for defining atomic matching patterns.""" def __init__( self ): @@ -1261,6 +1471,7 @@ exc.loc = loc exc.pstr = instring raise exc +_L = Literal class Keyword(Token): """Token to exactly match a specified string as a keyword, that is, it must be @@ -1383,14 +1594,14 @@ self.maxSpecified = max > 0 if min < 1: - raise ValueError, "cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted" + raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") self.minLen = min if max > 0: self.maxLen = max else: - self.maxLen = sys.maxint + self.maxLen = _MAX_INT if exact > 0: self.maxLen = exact @@ -1506,7 +1717,7 @@ try: self.re = re.compile(self.pattern, self.flags) self.reString = self.pattern - except sre_constants.error,e: + except sre_constants.error: warnings.warn("invalid pattern (%s) passed to Regex" % pattern, SyntaxWarning, stacklevel=2) raise @@ -1529,7 +1740,7 @@ d = result.groupdict() ret = ParseResults(result.group()) if d: - for k in d.keys(): + for k in d: ret[k] = d[k] return loc,ret @@ -1551,12 +1762,12 @@ def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None): """ Defined with the following parameters: - - quoteChar - string of one or more characters defining the quote delimiting string - - escChar - character to escape quotes, typically backslash (default=None) - - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=None) - - multiline - boolean indicating whether quotes can span multiple lines (default=False) - - unquoteResults - boolean indicating whether the matched text should be unquoted (default=True) - - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=None => same as quoteChar) + - quoteChar - string of one or more characters defining the quote delimiting string + - escChar - character to escape quotes, typically backslash (default=None) + - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=None) + - multiline - boolean indicating whether quotes can span multiple lines (default=False) + - unquoteResults - boolean indicating whether the matched text should be unquoted (default=True) + - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=None => same as quoteChar) """ super(QuotedString,self).__init__() @@ -1611,7 +1822,7 @@ try: self.re = re.compile(self.pattern, self.flags) self.reString = self.pattern - except sre_constants.error,e: + except sre_constants.error: warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, SyntaxWarning, stacklevel=2) raise @@ -1674,14 +1885,14 @@ self.notChars = notChars if min < 1: - raise ValueError, "cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted" + raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") self.minLen = min if max > 0: self.maxLen = max else: - self.maxLen = sys.maxint + self.maxLen = _MAX_INT if exact > 0: self.maxLen = exact @@ -1760,7 +1971,7 @@ if max > 0: self.maxLen = max else: - self.maxLen = sys.maxint + self.maxLen = _MAX_INT if exact > 0: self.maxLen = exact @@ -1807,7 +2018,7 @@ if col(loc,instring) != self.col: instrlen = len(instring) if self.ignoreExprs: - loc = self.skipIgnorables( instring, loc ) + loc = self._skipIgnorables( instring, loc ) while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : loc += 1 return loc @@ -1913,7 +2124,54 @@ exc.pstr = instring raise exc +class WordStart(_PositionToken): + """Matches if the current position is at the beginning of a Word, and + is not preceded by any character in a given set of wordChars + (default=printables). To emulate the \b behavior of regular expressions, + use WordStart(alphanums). WordStart will also match at the beginning of + the string being parsed, or at the beginning of a line. + """ + def __init__(self, wordChars = printables): + super(WordStart,self).__init__() + self.wordChars = _str2dict(wordChars) + self.errmsg = "Not at the start of a word" + def parseImpl(self, instring, loc, doActions=True ): + if loc != 0: + if (instring[loc-1] in self.wordChars or + instring[loc] not in self.wordChars): + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + return loc, [] + +class WordEnd(_PositionToken): + """Matches if the current position is at the end of a Word, and + is not followed by any character in a given set of wordChars + (default=printables). To emulate the \b behavior of regular expressions, + use WordEnd(alphanums). WordEnd will also match at the end of + the string being parsed, or at the end of a line. + """ + def __init__(self, wordChars = printables): + super(WordEnd,self).__init__() + self.wordChars = _str2dict(wordChars) + self.skipWhitespace = False + self.errmsg = "Not at the end of a word" + + def parseImpl(self, instring, loc, doActions=True ): + instrlen = len(instring) + if instrlen>0 and loc<instrlen: + if (instring[loc] in self.wordChars or + instring[loc-1] not in self.wordChars): + #~ raise ParseException( instring, loc, "Expected end of word" ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + return loc, [] + + class ParseExpression(ParserElement): """Abstract subclass of ParserElement, for combining and post-processing parsed tokens.""" def __init__( self, exprs, savelist = False ): @@ -2012,6 +2270,13 @@ Expressions may be separated by whitespace. May be constructed using the '+' operator. """ + + class _ErrorStop(Empty): + def __new__(cls,*args,**kwargs): + return And._ErrorStop.instance + _ErrorStop.instance = Empty() + _ErrorStop.instance.leaveWhitespace() + def __init__( self, exprs, savelist = True ): super(And,self).__init__(exprs, savelist) self.mayReturnEmpty = True @@ -2027,8 +2292,20 @@ # pass False as last arg to _parse for first element, since we already # pre-parsed the string as part of our And pre-parsing loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False ) + errorStop = False for e in self.exprs[1:]: - loc, exprtokens = e._parse( instring, loc, doActions ) + if e is And._ErrorStop.instance: + errorStop = True + continue + if errorStop: + try: + loc, exprtokens = e._parse( instring, loc, doActions ) + except ParseBaseException, pe: + raise ParseSyntaxException(pe) + except IndexError, ie: + raise ParseSyntaxException( ParseException(instring, len(instring), self.errmsg, self) ) + else: + loc, exprtokens = e._parse( instring, loc, doActions ) if exprtokens or exprtokens.keys(): resultlist += exprtokens return loc, resultlist @@ -2071,6 +2348,7 @@ def parseImpl( self, instring, loc, doActions=True ): maxExcLoc = -1 maxMatchLoc = -1 + maxException = None for e in self.exprs: try: loc2 = e.tryParse( instring, loc ) @@ -2078,7 +2356,7 @@ if err.loc > maxExcLoc: maxException = err maxExcLoc = err.loc - except IndexError, err: + except IndexError: if len(instring) > maxExcLoc: maxException = ParseException(instring,len(instring),e.errmsg,self) maxExcLoc = len(instring) @@ -2088,7 +2366,7 @@ maxMatchExp = e if maxMatchLoc < 0: - if self.exprs: + if maxException is not None: raise maxException else: raise ParseException(instring, loc, "no defined alternatives to match", self) @@ -2133,6 +2411,7 @@ def parseImpl( self, instring, loc, doActions=True ): maxExcLoc = -1 + maxException = None for e in self.exprs: try: ret = e._parse( instring, loc, doActions ) @@ -2141,14 +2420,14 @@ if err.loc > maxExcLoc: maxException = err maxExcLoc = err.loc - except IndexError, err: + except IndexError: if len(instring) > maxExcLoc: maxException = ParseException(instring,len(instring),e.errmsg,self) maxExcLoc = len(instring) # only got here if no expression matched, raise exception for match that made it the furthest else: - if self.exprs: + if maxException is not None: raise maxException else: raise ParseException(instring, loc, "no defined alternatives to match", self) @@ -2186,13 +2465,16 @@ self.mayReturnEmpty = False break self.skipWhitespace = True - self.optionals = [ e.expr for e in exprs if isinstance(e,Optional) ] - self.multioptionals = [ e.expr for e in exprs if isinstance(e,ZeroOrMore) ] - self.multirequired = [ e.expr for e in exprs if isinstance(e,OneOrMore) ] - self.required = [ e for e in exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] - self.required += self.multirequired + self.initExprGroups = True def parseImpl( self, instring, loc, doActions=True ): + if self.initExprGroups: + self.optionals = [ e.expr for e in self.exprs if isinstance(e,Optional) ] + self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] + self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] + self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] + self.required += self.multirequired + self.initExprGroups = False tmpLoc = loc tmpReqd = self.required[:] tmpOpt = self.optionals[:] @@ -2220,6 +2502,9 @@ missing = ", ".join( [ _ustr(e) for e in tmpReqd ] ) raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) + # add any unmatched Optionals, in case they have default values defined + matchOrder += list(e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt) + resultlist = [] for e in matchOrder: loc,results = e._parse(instring,loc,doActions) @@ -2268,6 +2553,7 @@ self.skipWhitespace = expr.skipWhitespace self.saveAsList = expr.saveAsList self.callPreparse = expr.callPreparse + self.ignoreExprs.extend(expr.ignoreExprs) def parseImpl( self, instring, loc, doActions=True ): if self.expr is not None: @@ -2388,7 +2674,7 @@ hasIgnoreExprs = ( len(self.ignoreExprs) > 0 ) while 1: if hasIgnoreExprs: - preloc = self.skipIgnorables( instring, loc ) + preloc = self._skipIgnorables( instring, loc ) else: preloc = loc loc, tmptokens = self.expr._parse( instring, preloc, doActions ) @@ -2423,7 +2709,7 @@ hasIgnoreExprs = ( len(self.ignoreExprs) > 0 ) while 1: if hasIgnoreExprs: - preloc = self.skipIgnorables( instring, loc ) + preloc = self._skipIgnorables( instring, loc ) else: preloc = loc loc, tmptokens = self.expr._parse( instring, preloc, doActions ) @@ -2451,6 +2737,7 @@ class _NullToken(object): def __bool__(self): return False + __nonzero__ = __bool__ def __str__(self): return "" @@ -2470,7 +2757,11 @@ loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) except (ParseException,IndexError): if self.defaultValue is not _optionalNotMatched: - tokens = [ self.defaultValue ] + if self.expr.resultsName: + tokens = ParseResults([ self.defaultValue ]) + tokens[self.expr.resultsName] = self.defaultValue + else: + tokens = [ self.defaultValue ] else: tokens = [] return loc, tokens @@ -2509,7 +2800,7 @@ expr = self.expr while loc <= instrlen: try: - loc = expr.skipIgnorables( instring, loc ) + loc = expr._skipIgnorables( instring, loc ) expr._parse( instring, loc, doActions=False, callPreParse=False ) if self.includeMatch: skipText = instring[startLoc:loc] @@ -2557,7 +2848,8 @@ self.setWhitespaceChars( self.expr.whiteChars ) self.skipWhitespace = self.expr.skipWhitespace self.saveAsList = self.expr.saveAsList - return self + self.ignoreExprs.extend(self.expr.ignoreExprs) + return None def leaveWhitespace( self ): self.skipWhitespace = False @@ -2617,7 +2909,7 @@ DeprecationWarning,stacklevel=2) def postParse( self, instring, loc, tokenlist ): - return map( string.upper, tokenlist ) + return list(map( string.upper, tokenlist )) class Combine(TokenConverter): @@ -2706,7 +2998,7 @@ class OnlyOnce(object): """Wrapper for parse actions, to ensure they are only called once.""" def __init__(self, methodCall): - self.callable = ParserElement.normalizeParseActionArgs(methodCall) + self.callable = ParserElement._normalizeParseActionArgs(methodCall) self.called = False def __call__(self,s,l,t): if not self.called: @@ -2719,7 +3011,7 @@ def traceParseAction(f): """Decorator for debugging parse actions.""" - f = ParserElement.normalizeParseActionArgs(f) + f = ParserElement._normalizeParseActionArgs(f) def z(*paArgs): thisFunc = f.func_name s,l,t = paArgs[-3:] @@ -2864,23 +3156,23 @@ warnings.warn("Invalid argument to oneOf, expected string or list", SyntaxWarning, stacklevel=2) - try: - symbols.sort(reverse=True) - except TypeError: - symbols.sort() - symbols.reverse() i = 0 while i < len(symbols)-1: cur = symbols[i] - for j, other in enumerate(symbols[i+1:]): + for j,other in enumerate(symbols[i+1:]): if ( isequal(other, cur) ): del symbols[i+j+1] - else: break - i += 1 + elif ( masks(cur, other) ): + del symbols[i+j+1] + symbols.insert(i,other) + cur = other + break + else: + i += 1 if not caseless and useRegex: - #~ print strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] ) + #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) try: if len(symbols)==len("".join(symbols)): return Regex( "[%s]" % "".join( [ _escapeRegexRangeChars(sym) for sym in symbols] ) ) @@ -2904,9 +3196,6 @@ """ return Dict( ZeroOrMore( Group ( key + value ) ) ) -_bslash = "\\" -printables = "".join( [ c for c in string.printable if c not in string.whitespace ] ) - # convenience constants for positional expressions empty = Empty().setName("empty") lineStart = LineStart().setName("lineStart") @@ -2945,6 +3234,15 @@ except: return "" +def matchOnlyAtCol(n): + """Helper method for defining parse actions that require matching at a specific + column in the input text. + """ + def verifyCol(strg,locn,toks): + if col(locn,strg) != n: + raise ParseException(strg,locn,"matched token not at column %d" % n) + return verifyCol + def replaceWith(replStr): """Helper method for common parse actions that simply return a literal value. Especially useful when used with transformString(). @@ -2974,7 +3272,7 @@ try: endloc = getTokensEndLoc() except ParseException: - raise ParseFatalException, "incorrect usage of keepOriginalText - may only be called as a parse action" + raise ParseFatalException("incorrect usage of keepOriginalText - may only be called as a parse action") del t[:] t += ParseResults(s[startLoc:endloc]) return t @@ -2991,7 +3289,7 @@ endloc = f[0].f_locals["loc"] return endloc else: - raise ParseFatalException, "incorrect usage of getTokensEndLoc - may only be called from within a parse action" + raise ParseFatalException("incorrect usage of getTokensEndLoc - may only be called from within a parse action") finally: del fstack @@ -3016,7 +3314,7 @@ Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ Optional( Suppress("=") + tagAttrValue ) ))) + \ Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") - closeTag = Combine("</" + tagStr + ">") + closeTag = Combine(_L("</") + tagStr + ">") openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % tagStr) closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("</%s>" % tagStr) @@ -3043,35 +3341,29 @@ - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) For attribute names with a namespace prefix, you must use the second form. Attribute names are matched insensitive to upper/lower case. + + To verify that the attribute exists, but without specifying a value, pass + withAttribute.ANY_VALUE as the value. """ if args: attrs = args[:] else: attrs = attrDict.items() - attrs = [(k.lower(),v) for k,v in attrs] + attrs = [(k,v) for k,v in attrs] def pa(s,l,tokens): for attrName,attrValue in attrs: if attrName not in tokens: raise ParseException(s,l,"no matching attribute " + attrName) - if tokens[attrName] != attrValue: + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % (attrName, tokens[attrName], attrValue)) return pa +withAttribute.ANY_VALUE = object() opAssoc = _Constants() opAssoc.LEFT = object() opAssoc.RIGHT = object() -def _flattenOpPrecTokens(tokens): - if isinstance(tokens,ParseResults): - if len(tokens)==1: - if isinstance(tokens[0],ParseResults): - return _flattenOpPrecTokens(tokens[0]) - else: - return tokens[0] - return map(_flattenOpPrecTokens,tokens) - return tokens - def operatorPrecedence( baseExpr, opList ): """Helper method for constructing grammars of expressions made up of operators working in a precedence hierarchy. Operators may be unary or @@ -3084,9 +3376,11 @@ expression grammar; each tuple is of the form (opExpr, numTerms, rightLeftAssoc, parseAction), where: - opExpr is the pyparsing expression for the operator; - may also be a string, which will be converted to a Literal + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms - numTerms is the number of terms for this operator (must - be 1 or 2) + be 1, 2, or 3) - rightLeftAssoc is the indicator whether the operator is right or left associative, using the pyparsing-defined constants opAssoc.RIGHT and opAssoc.LEFT. @@ -3098,38 +3392,53 @@ lastExpr = baseExpr | ( Suppress('(') + ret + Suppress(')') ) for i,operDef in enumerate(opList): opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr thisExpr = Forward()#.setName("expr%d" % i) if rightLeftAssoc == opAssoc.LEFT: if arity == 1: - matchExpr = Group( lastExpr + ZeroOrMore( opExpr ) ) + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) elif arity == 2: - matchExpr = Group( lastExpr + ZeroOrMore( opExpr + lastExpr ) ) + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) else: - raise ValueError, "operator must be unary (1) or binary (2)" + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") elif rightLeftAssoc == opAssoc.RIGHT: if arity == 1: # try to avoid LR with this extra test if not isinstance(opExpr, Optional): opExpr = Optional(opExpr) matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) - matchExpr |= lastExpr elif arity == 2: - matchExpr = Group( lastExpr + ZeroOrMore( opExpr + thisExpr ) ) + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisEx... [truncated message content] |
From: <sa...@us...> - 2008-06-04 16:54:30
|
Revision: 5382 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5382&view=rev Author: sameerd Date: 2008-06-04 09:53:48 -0700 (Wed, 04 Jun 2008) Log Message: ----------- Merged revisions 5381 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_91_maint ........ r5381 | sameerd | 2008-06-04 11:49:19 -0500 (Wed, 04 Jun 2008) | 3 lines Docstring changes ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/mlab.py Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Name: svnmerge-integrated - /branches/v0_91_maint:1-5360 + /branches/v0_91_maint:1-5381 Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2008-06-04 16:49:19 UTC (rev 5381) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2008-06-04 16:53:48 UTC (rev 5382) @@ -48,7 +48,7 @@ * rec2txt : pretty print a record array * rec2csv : store record array in CSV file * csv2rec : import record array from CSV file with type inspection - * rec_append_field : add a field/array to record array + * rec_append_fields: adds field(s)/array(s) to record array * rec_drop_fields : drop fields from record array * rec_join : join two record arrays on sequence of fields * rec_groupby : summarize data by groups (similar to SQL GROUP BY) @@ -1955,7 +1955,10 @@ else: return b def rec_append_field(rec, name, arr, dtype=None): - 'return a new record array with field name populated with data from array arr' + """ + return a new record array with field name populated with data from array arr. + This function is Depreacted. Please use rec_append_fields. + """ warnings.warn("use rec_append_fields", DeprecationWarning) return rec_append_fields(rec, name, arr, dtype) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-06-04 18:15:20
|
Revision: 5384 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5384&view=rev Author: jdh2358 Date: 2008-06-04 11:15:05 -0700 (Wed, 04 Jun 2008) Log Message: ----------- Merged revisions 5383 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_91_maint ........ r5383 | jdh2358 | 2008-06-04 12:49:17 -0500 (Wed, 04 Jun 2008) | 1 line try to handle xaxis_date more gracefully when no data has been added ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Name: svnmerge-integrated - /branches/v0_91_maint:1-5381 + /branches/v0_91_maint:1-5383 Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-06-04 17:49:17 UTC (rev 5383) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-06-04 18:15:05 UTC (rev 5384) @@ -1,5 +1,5 @@ from __future__ import division, generators -import math, warnings, new +import math, sys, warnings, datetime, new import numpy as np from numpy import ma @@ -1309,6 +1309,8 @@ # limits and set the bound to be the bounds of the xydata. # Otherwise, it will compute the bounds of it's current data # and the data in xydata + + if iterable(xys) and not len(xys): return if not ma.isMaskedArray(xys): xys = np.asarray(xys) self.dataLim.update_from_data_xy(xys, self.ignore_existing_data_limits) @@ -1320,6 +1322,7 @@ # limits and set the bound to be the bounds of the xydata. # Otherwise, it will compute the bounds of it's current data # and the data in xydata + if iterable(x) and not len(x): return self.dataLim.update_from_data(x, y, self.ignore_existing_data_limits) self.ignore_existing_data_limits = False @@ -1985,11 +1988,24 @@ tz is the time zone to use in labeling dates. Defaults to rc value. """ + if self.ignore_existing_data_limits: + # no data has been added - let's set the default datalim. + # We should probably use a better proxy for the datalim + # have been updated than the ignore setting + dmax = today = datetime.date.today() + dmin = today-datetime.timedelta(days=10) + self._process_unit_info(xdata=(dmin, dmax)) + dmin, dmax = self.convert_xunits([dmin, dmax]) + self.viewLim.intervalx = dmin, dmax + self.dataLim.intervalx = dmin, dmax + locator = self.xaxis.get_major_locator() if not isinstance(locator, mdates.DateLocator): locator = mdates.AutoDateLocator(tz) self.xaxis.set_major_locator(locator) + locator.refresh() + formatter = self.xaxis.get_major_formatter() if not isinstance(formatter, mdates.DateFormatter): formatter = mdates.AutoDateFormatter(locator) @@ -2000,11 +2016,24 @@ tz is the time zone to use in labeling dates. Defaults to rc value. """ + if self.ignore_existing_data_limits: + # no data has been added - let's set the default datalim. + # We should probably use a better proxy for the datalim + # have been updated than the ignore setting + dmax = today = datetime.date.today() + dmin = today-datetime.timedelta(days=10) + self._process_unit_info(ydata=(dmin, dmax)) + dmin, dmax = self.convert_yunits([dmin, dmax]) + self.viewLim.intervaly = dmin, dmax + self.dataLim.intervaly = dmin, dmax + + locator = self.yaxis.get_major_locator() if not isinstance(locator, mdates.DateLocator): locator = mdates.AutoDateLocator(tz) self.yaxis.set_major_locator(locator) + locator.refresh() formatter = self.xaxis.get_major_formatter() if not isinstance(formatter, mdates.DateFormatter): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-06-04 19:11:19
|
Revision: 5390 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5390&view=rev Author: jdh2358 Date: 2008-06-04 12:11:16 -0700 (Wed, 04 Jun 2008) Log Message: ----------- added suptitle Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/pylab_examples/figtext.py trunk/matplotlib/lib/matplotlib/figure.py trunk/matplotlib/lib/matplotlib/pylab.py trunk/matplotlib/lib/matplotlib/pyplot.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-04 18:52:07 UTC (rev 5389) +++ trunk/matplotlib/CHANGELOG 2008-06-04 19:11:16 UTC (rev 5390) @@ -1,3 +1,6 @@ +2006-06-04 Added a figure title command subtitle as a Figure method + and pyplot command -- see examples/figure_title.py - JDH + 2008-06-02 Added support for log to hist with histtype='step' and fixed a bug for log-scale stacked histograms - MM Modified: trunk/matplotlib/examples/pylab_examples/figtext.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/figtext.py 2008-06-04 18:52:07 UTC (rev 5389) +++ trunk/matplotlib/examples/pylab_examples/figtext.py 2008-06-04 19:11:16 UTC (rev 5390) @@ -16,10 +16,7 @@ plot(t1, f(t1), 'bo', t2, f(t2), 'k') title('subplot 1') ylabel('Damped oscillation') -figtitle = 'This is a somewhat long figure title' -t = gcf().text(0.5, 0.95, figtitle, - horizontalalignment='center', - fontproperties=FontProperties(size=16)) +suptitle('This is a somewhat long figure title', fontsize=16) subplot(122) Modified: trunk/matplotlib/lib/matplotlib/figure.py =================================================================== --- trunk/matplotlib/lib/matplotlib/figure.py 2008-06-04 18:52:07 UTC (rev 5389) +++ trunk/matplotlib/lib/matplotlib/figure.py 2008-06-04 19:11:16 UTC (rev 5390) @@ -313,6 +313,35 @@ 'get the figure bounding box in display space; kwargs are void' return self.bbox + def suptitle(self, t, **kwargs): + """ + add a centered title to the figure + + kwargs are matplotlib.text.Text properties. Using figure + coordinates, the defaults are + + x = 0.5 + y = 0.98 + horizontalalignment = 'center' + verticalalignment = 'top' + + The matplotlib.text.Text instance is returned + + Example: + + fig.subtitle('this is the figure title', fontsize=12) + """ + x = kwargs.pop('x', 0.5) + y = kwargs.pop('y', 0.98) + if ('horizontalalignment' not in kwargs) and ('ha' not in kwargs): + kwargs['horizontalalignment'] = 'center' + + if ('verticalalignment' not in kwargs) and ('va' not in kwargs): + kwargs['verticalalignment'] = 'top' + + t = self.text(x, y, t, **kwargs) + return t + def set_canvas(self, canvas): """ Set the canvas the contains the figure Modified: trunk/matplotlib/lib/matplotlib/pylab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pylab.py 2008-06-04 18:52:07 UTC (rev 5389) +++ trunk/matplotlib/lib/matplotlib/pylab.py 2008-06-04 19:11:16 UTC (rev 5390) @@ -78,6 +78,7 @@ subplot - make a subplot (numrows, numcols, axesnum) subplots_adjust - change the params controlling the subplot positions of current figure subplot_tool - launch the subplot configuration tool + suptitle - add a figure title table - add a table to the plot text - add some text at location x,y to the current axes thetagrids - customize the radial theta grids and labels for polar Modified: trunk/matplotlib/lib/matplotlib/pyplot.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyplot.py 2008-06-04 18:52:07 UTC (rev 5389) +++ trunk/matplotlib/lib/matplotlib/pyplot.py 2008-06-04 19:11:16 UTC (rev 5390) @@ -303,6 +303,13 @@ if Figure.text.__doc__ is not None: figtext.__doc__ = dedent(Figure.text.__doc__) +def suptitle(*args, **kwargs): + ret = gcf().suptitle(*args, **kwargs) + draw_if_interactive() + return ret +if Figure.suptitle.__doc__ is not None: + suptitle.__doc__ = dedent(Figure.suptitle.__doc__) + def figimage(*args, **kwargs): # allow callers to override the hold state by passing hold=True|False ret = gcf().figimage(*args, **kwargs) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2008-06-05 13:45:29
|
Revision: 5394 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5394&view=rev Author: mdboom Date: 2008-06-05 06:45:27 -0700 (Thu, 05 Jun 2008) Log Message: ----------- Add transformations/paths information to developer docs. Modified Paths: -------------- trunk/matplotlib/doc/conf.py trunk/matplotlib/doc/devel/index.rst trunk/matplotlib/lib/matplotlib/path.py trunk/matplotlib/lib/matplotlib/transforms.py Added Paths: ----------- trunk/matplotlib/doc/devel/transformations.rst Modified: trunk/matplotlib/doc/conf.py =================================================================== --- trunk/matplotlib/doc/conf.py 2008-06-05 11:57:31 UTC (rev 5393) +++ trunk/matplotlib/doc/conf.py 2008-06-05 13:45:27 UTC (rev 5394) @@ -159,3 +159,7 @@ latex_use_modindex = True latex_use_parts = True + +# Show both class-level docstring and __init__ docstring in class +# documentation +autoclass_content = 'both' Modified: trunk/matplotlib/doc/devel/index.rst =================================================================== --- trunk/matplotlib/doc/devel/index.rst 2008-06-05 11:57:31 UTC (rev 5393) +++ trunk/matplotlib/doc/devel/index.rst 2008-06-05 13:45:27 UTC (rev 5394) @@ -11,4 +11,6 @@ coding_guide.rst documenting_mpl.rst + transformations.rst add_new_projection.rst + Added: trunk/matplotlib/doc/devel/transformations.rst =================================================================== --- trunk/matplotlib/doc/devel/transformations.rst (rev 0) +++ trunk/matplotlib/doc/devel/transformations.rst 2008-06-05 13:45:27 UTC (rev 5394) @@ -0,0 +1,21 @@ +============================== + Working with transformations +============================== + +:mod:`matplotlib.transforms` +============================= + +.. automodule:: matplotlib.transforms + :members: TransformNode, BboxBase, Bbox, TransformedBbox, Transform, + TransformWrapper, AffineBase, Affine2DBase, Affine2D, IdentityTransform, + BlendedGenericTransform, BlendedAffine2D, blended_transform_factory, + CompositeGenericTransform, CompositeAffine2D, + composite_transform_factory, BboxTransform, BboxTransformTo, + BboxTransformFrom, ScaledTranslation, TransformedPath, nonsingular, + interval_contains, interval_contains_open + +:mod:`matplotlib.path` +============================= + +.. automodule:: matplotlib.path + :members: Path, get_path_collection_extents Modified: trunk/matplotlib/lib/matplotlib/path.py =================================================================== --- trunk/matplotlib/lib/matplotlib/path.py 2008-06-05 11:57:31 UTC (rev 5393) +++ trunk/matplotlib/lib/matplotlib/path.py 2008-06-05 13:45:27 UTC (rev 5394) @@ -1,7 +1,5 @@ """ Contains a class for managing paths (polylines). - -October 2007 Michael Droettboom """ import math @@ -21,42 +19,42 @@ closed, line and curve segments. The underlying storage is made up of two parallel numpy arrays: - vertices: an Nx2 float array of vertices - codes: an N-length uint8 array of vertex types + - vertices: an Nx2 float array of vertices + - codes: an N-length uint8 array of vertex types These two arrays always have the same length in the first - dimension. Therefore, to represent a cubic curve, you must + dimension. For example, to represent a cubic curve, you must provide three vertices as well as three codes "CURVE3". The code types are: - STOP : 1 vertex (ignored) - A marker for the end of the entire path (currently not - required and ignored) + - ``STOP`` : 1 vertex (ignored) + A marker for the end of the entire path (currently not + required and ignored) - MOVETO : 1 vertex - Pick up the pen and move to the given vertex. + - ``MOVETO`` : 1 vertex + Pick up the pen and move to the given vertex. - LINETO : 1 vertex - Draw a line from the current position to the given vertex. + - ``LINETO`` : 1 vertex + Draw a line from the current position to the given vertex. - CURVE3 : 1 control point, 1 endpoint + - ``CURVE3`` : 1 control point, 1 endpoint Draw a quadratic Bezier curve from the current position, with the given control point, to the given end point. - CURVE4 : 2 control points, 1 endpoint + - ``CURVE4`` : 2 control points, 1 endpoint Draw a cubic Bezier curve from the current position, with the given control points, to the given end point. - CLOSEPOLY : 1 vertex (ignored) + - ``CLOSEPOLY`` : 1 vertex (ignored) Draw a line segment to the start point of the current polyline. Users of Path objects should not access the vertices and codes - arrays directly. Instead, they should use iter_segments to get - the vertex/code pairs. This is important since many Paths do not - store a codes array at all, but have a default one provided for - them by iter_segments. + arrays directly. Instead, they should use :meth:`iter_segments` + to get the vertex/code pairs. This is important since many Paths, + as an optimization, do not store a codes array at all, but have a + default one provided for them by :meth:`iter_segments`. """ # Path codes @@ -81,9 +79,6 @@ codes is an N-length numpy array or Python sequence of type Path.code_type. - See the docstring of Path for a description of the various - codes. - These two arrays must have the same length in the first dimension. @@ -133,8 +128,8 @@ #@staticmethod def make_compound_path(*args): """ - Make a compound path from a list of Path objects. Only - polygons (not curves) are supported. + (staticmethod) Make a compound path from a list of Path + objects. Only polygons (not curves) are supported. """ for p in args: assert p.codes is None @@ -162,7 +157,10 @@ def iter_segments(self): """ - Iterates over all of the curve segments in the path. + Iterates over all of the curve segments in the path. Each + iteration returns a 2-tuple ``(vertices, code)``, where + vertices is a sequence of 1 - 3 coordinate pairs, and code is + one of the ``Path`` codes. """ vertices = self.vertices if not len(vertices): @@ -213,9 +211,9 @@ """ Return a transformed copy of the path. - See transforms.TransformedPath for a path that will cache the - transformed result and automatically update when the transform - changes. + See :class:`matplotlib.transforms.TransformedPath` for a path + that will cache the transformed result and automatically + update when the transform changes. """ return Path(transform.transform(self.vertices), self.codes) @@ -233,6 +231,9 @@ def contains_path(self, path, transform=None): """ Returns True if this path completely contains the given path. + + If transform is not None, the path will be transformed before + performing the test. """ if transform is not None: transform = transform.frozen() @@ -259,7 +260,8 @@ def intersects_bbox(self, bbox): """ - Returns True if this path intersects a given Bbox. + Returns True if this path intersects a given + :class:`~matplotlib.transforms.Bbox`. """ from transforms import BboxTransformTo rectangle = self.unit_rectangle().transformed( @@ -285,7 +287,9 @@ """ Convert this path to a list of polygons. Each polygon is an Nx2 array of vertices. In other words, each polygon has no - "move to" instructions or curves. + ``MOVETO`` instructions or curves. This is useful for + displaying in backends that do not support compound paths or + Bezier curves, such as GDK. """ if transform is not None: transform = transform.frozen() @@ -302,7 +306,8 @@ #@classmethod def unit_rectangle(cls): """ - Returns a Path of the unit rectangle from (0, 0) to (1, 1). + (staticmethod) Returns a :class:`Path` of the unit rectangle + from (0, 0) to (1, 1). """ if cls._unit_rectangle is None: cls._unit_rectangle = \ @@ -314,8 +319,9 @@ #@classmethod def unit_regular_polygon(cls, numVertices): """ - Returns a Path for a unit regular polygon with the given - numVertices and radius of 1.0, centered at (0, 0). + (staticmethod) Returns a :class:`Path` for a unit regular + polygon with the given numVertices and radius of 1.0, centered + at (0, 0). """ if numVertices <= 16: path = cls._unit_regular_polygons.get(numVertices) @@ -337,8 +343,9 @@ #@classmethod def unit_regular_star(cls, numVertices, innerCircle=0.5): """ - Returns a Path for a unit regular star with the given - numVertices and radius of 1.0, centered at (0, 0). + (staticmethod) Returns a :class:`Path` for a unit regular star + with the given numVertices and radius of 1.0, centered at (0, + 0). """ if numVertices <= 16: path = cls._unit_regular_stars.get((numVertices, innerCircle)) @@ -361,8 +368,9 @@ #@classmethod def unit_regular_asterisk(cls, numVertices): """ - Returns a Path for a unit regular asterisk with the given - numVertices and radius of 1.0, centered at (0, 0). + (staticmethod) Returns a :class:`Path` for a unit regular + asterisk with the given numVertices and radius of 1.0, + centered at (0, 0). """ return cls.unit_regular_star(numVertices, 0.0) unit_regular_asterisk = classmethod(unit_regular_asterisk) @@ -371,14 +379,13 @@ #@classmethod def unit_circle(cls): """ - Returns a Path of the unit circle. The circle is approximated - using cubic Bezier curves. This uses 8 splines around the - circle using the approach presented here: + (staticmethod) Returns a :class:`Path` of the unit circle. + The circle is approximated using cubic Bezier curves. This + uses 8 splines around the circle using the approach presented + here: - Lancaster, Don. Approximating a Circle or an Ellipse Using Four - Bezier Cubic Splines. - - http://www.tinaja.com/glib/ellipse4.pdf + Lancaster, Don. `Approximating a Circle or an Ellipse Using Four + Bezier Cubic Splines <http://www.tinaja.com/glib/ellipse4.pdf>`_. """ if cls._unit_circle is None: MAGIC = 0.2652031 @@ -434,18 +441,17 @@ #@classmethod def arc(cls, theta1, theta2, n=None, is_wedge=False): """ - Returns an arc on the unit circle from angle theta1 to angle - theta2 (in degrees). + (staticmethod) Returns an arc on the unit circle from angle + theta1 to angle theta2 (in degrees). If n is provided, it is the number of spline segments to make. - If n is not provided, the number of spline segments is determined - based on the delta between theta1 and theta2. + If n is not provided, the number of spline segments is + determined based on the delta between theta1 and theta2. + + Masionobe, L. 2003. `Drawing an elliptical arc using + polylines, quadratic or cubic Bezier curves + <http://www.spaceroots.org/documents/ellipse/index.html>`_. """ - # From Masionobe, L. 2003. "Drawing an elliptical arc using - # polylines, quadratic or cubic Bezier curves". - # - # http://www.spaceroots.org/documents/ellipse/index.html - # degrees to radians theta1 *= np.pi / 180.0 theta2 *= np.pi / 180.0 @@ -514,14 +520,18 @@ #@classmethod def wedge(cls, theta1, theta2, n=None): """ - Returns a wedge of the unit circle from angle theta1 to angle - theta2 (in degrees). + (staticmethod) Returns a wedge of the unit circle from angle + theta1 to angle theta2 (in degrees). """ return cls.arc(theta1, theta2, n, True) wedge = classmethod(wedge) _get_path_collection_extents = get_path_collection_extents def get_path_collection_extents(*args): + """ + Given a sequence of :class:`Path` objects, returns the bounding + box that encapsulates all of them. + """ from transforms import Bbox if len(args[1]) == 0: raise ValueError("No paths provided") Modified: trunk/matplotlib/lib/matplotlib/transforms.py =================================================================== --- trunk/matplotlib/lib/matplotlib/transforms.py 2008-06-05 11:57:31 UTC (rev 5393) +++ trunk/matplotlib/lib/matplotlib/transforms.py 2008-06-05 13:45:27 UTC (rev 5394) @@ -1,26 +1,32 @@ """ -This module contains a framework for arbitrary transformations. +matplotlib includes a framework for arbitrary geometric +transformations that is used determine the final position of all +elements drawn on the canvas. -Transforms are composed into a 'transform tree', made of transforms -whose value depends on other transforms (their children). When the -contents of children change, their parents are automatically updated -to reflect those changes. To do this an "invalidation" method is -used: when children change, all of their ancestors are marked as -"invalid". When the value of a transform is accessed at a later time, -its value is recomputed only if it is invalid, otherwise a cached -value may be used. This prevents unnecessary recomputations of -transforms, and contributes to better interactive performance. +Transforms are composed into trees of ``TransformNode`` objects whose +actual value depends on their children. When the contents of children +change, their parents are automatically invalidated. The next time an +invalidated transform is accessed, it is recomputed to reflect those +changes. This invalidation/caching approach prevents unnecessary +recomputations of transforms, and contributes to better interactive +performance. +For example, here is a graph of the transform tree used to plot data +to the graph: + +.. image:: ../_static/transforms.png + The framework can be used for both affine and non-affine transformations. However, for speed, we want use the backend renderers to perform affine transformations whenever possible. Therefore, it is possible to perform just the affine or non-affine part of a transformation on a set of data. The affine is always -assumed to occur after the non-affine. For any transform: +assumed to occur after the non-affine. For any transform:: - full transform == non-affine + affine + full transform == non-affine part + affine part -2007 Michael Droettboom +The backends are not expected to handle non-affine transformations +themselves. """ import numpy as np @@ -30,6 +36,7 @@ from weakref import WeakKeyDictionary import warnings +import sets import cbook from path import Path @@ -43,11 +50,11 @@ class TransformNode(object): """ - TransformNode is the base class for anything that participates in - the transform tree and needs to invalidate its parents or be - invalidated. It can include classes that are not technically - transforms, such as bounding boxes, since some transforms depend - on bounding boxes to compute their values. + :class:`TransformNode` is the base class for anything that + participates in the transform tree and needs to invalidate its + parents or be invalidated. This includes classes that are not + really transforms, such as bounding boxes, since some transforms + depend on bounding boxes to compute their values. """ _gid = 0 @@ -88,8 +95,8 @@ def invalidate(self): """ - Invalidate this transform node and all of its parents. Should - be called anytime the transform changes. + Invalidate this transform node and all of its ancestors. + Should be called any time the transform changes. """ # If we are an affine transform being changed, we can set the # flag to INVALID_AFFINE_ONLY @@ -116,8 +123,10 @@ def set_children(self, *children): """ - Set the children of the transform. Should be called from the - constructor of any transforms that depend on other transforms. + Set the children of the transform, to let the invalidation + system know which transforms can invalidate this transform. + Should be called from the constructor of any transforms that + depend on other transforms. """ for child in children: child._parents[self] = None @@ -127,6 +136,7 @@ def set_children(self, *children): self._set_children(*children) self._children = children + set_children.__doc__ = _set_children.__doc__ def frozen(self): """ @@ -151,7 +161,7 @@ fobj: A Python file-like object """ - seen = cbook.set() + seen = sets.Set() def recurse(root): if root in seen: @@ -163,10 +173,7 @@ label = '[%s]' % label if root in highlight: props['style'] = 'bold' - if root.is_affine: - props['shape'] = 'parallelogram' - if root.is_bbox: - props['shape'] = 'box' + props['shape'] = 'box' props['label'] = '"%s"' % label props = ' '.join(['%s=%s' % (key, val) for key, val in props.items()]) @@ -197,7 +204,13 @@ class BboxBase(TransformNode): """ This is the base class of all bounding boxes, and provides - read-only access to its data. + read-only access to its data. A mutable bounding box is provided + by the :class:`Bbox` class. + + The canonical representation is as two points, with no + restrictions on their ordering. Convenience properties are + provided to get the left, bottom, right and top edges and width + and height, but these are not stored explicity. """ is_bbox = True is_affine = True @@ -225,109 +238,165 @@ return self.get_points() def is_unit(self): + """ + Returns True if the Bbox is the unit bounding box from (0, 0) + to (1, 1). + """ return list(self.get_points().flatten()) == [0., 0., 1., 1.] def _get_x0(self): return self.get_points()[0, 0] - x0 = property(_get_x0) + x0 = property(_get_x0, None, None, """ + (property) :attr:`x0` is the first of the pair of *x* coordinates that + define the bounding box. :attr:`x0` is not guaranteed to be + less than :attr:`x1`. If you require that, use :attr:`xmin`.""") def _get_y0(self): return self.get_points()[0, 1] - y0 = property(_get_y0) + y0 = property(_get_y0, None, None, """ + (property) :attr:`y0` is the first of the pair of *y* coordinates that + define the bounding box. :attr:`y0` is not guaranteed to be + less than :attr:`y1`. If you require that, use :attr:`ymin`.""") def _get_x1(self): return self.get_points()[1, 0] - x1 = property(_get_x1) + x1 = property(_get_x1, None, None, """ + (property) :attr:`x1` is the second of the pair of *x* coordinates that + define the bounding box. :attr:`x1` is not guaranteed to be + greater than :attr:`x0`. If you require that, use :attr:`xmax`.""") def _get_y1(self): return self.get_points()[1, 1] - y1 = property(_get_y1) + y1 = property(_get_y1, None, None, """ + (property) :attr:`y1` is the second of the pair of *y* coordinates that + define the bounding box. :attr:`y1` is not guaranteed to be + greater than :attr:`y0`. If you require that, use :attr:`ymax`.""") def _get_p0(self): return self.get_points()[0] - p0 = property(_get_p0) + p0 = property(_get_p0, None, None, """ + (property) :attr:`p0` is the first pair of (*x*, *y*) coordinates that + define the bounding box. It is not guaranteed to be the bottom-left + corner. For that, use :attr:`min`.""") def _get_p1(self): return self.get_points()[1] - p1 = property(_get_p1) + p1 = property(_get_p1, None, None, """ + (property) :attr:`p1` is the second pair of (*x*, *y*) coordinates that + define the bounding box. It is not guaranteed to be the top-right + corner. For that, use :attr:`max`.""") def _get_xmin(self): return min(self.get_points()[:, 0]) - xmin = property(_get_xmin) + xmin = property(_get_xmin, None, None, """ + (property) :attr:`xmin` is the left edge of the bounding box.""") def _get_ymin(self): return min(self.get_points()[:, 1]) - ymin = property(_get_ymin) + ymin = property(_get_ymin, None, None, """ + (property) :attr:`ymin` is the bottom edge of the bounding box.""") def _get_xmax(self): return max(self.get_points()[:, 0]) - xmax = property(_get_xmax) + xmax = property(_get_xmax, None, None, """ + (property) :attr:`xmax` is the right edge of the bounding box.""") def _get_ymax(self): return max(self.get_points()[:, 1]) - ymax = property(_get_ymax) + ymax = property(_get_ymax, None, None, """ + (property) :attr:`ymax` is the top edge of the bounding box.""") def _get_min(self): return [min(self.get_points()[:, 0]), min(self.get_points()[:, 1])] - min = property(_get_min) + min = property(_get_min, None, None, """ + (property) :attr:`min` is the bottom-left corner of the bounding box.""") def _get_max(self): return [max(self.get_points()[:, 0]), max(self.get_points()[:, 1])] - max = property(_get_max) + max = property(_get_max, None, None, """ + (property) :attr:`max` is the top-right corner of the bounding box.""") def _get_intervalx(self): return self.get_points()[:, 0] - intervalx = property(_get_intervalx) + intervalx = property(_get_intervalx, None, None, """ + (property) :attr:`intervalx` is the pair of *x* coordinates that define the + bounding box. It is not guaranteed to be sorted from left to right.""") def _get_intervaly(self): return self.get_points()[:, 1] - intervaly = property(_get_intervaly) + intervaly = property(_get_intervaly, None, None, """ + (property) :attr:`intervaly` is the pair of *y* coordinates that define the + bounding box. It is not guaranteed to be sorted from bottom to top.""") def _get_width(self): points = self.get_points() return points[1, 0] - points[0, 0] - width = property(_get_width) + width = property(_get_width, None, None, """ + (property) The width of the bounding box. It may be negative if :attr:`x1` < + :attr:`x0`.""") def _get_height(self): points = self.get_points() return points[1, 1] - points[0, 1] - height = property(_get_height) + height = property(_get_height, None, None, """ + (property) The height of the bounding box. It may be negative if :attr:`y1` < + :attr:`y0`.""") def _get_size(self): points = self.get_points() return points[1] - points[0] - size = property(_get_size) + size = property(_get_size, None, None, """ + (property) The width and height of the bounding box. May be negative, in the same + way as :attr:`width` and :attr:`height`.""") def _get_bounds(self): x0, y0, x1, y1 = self.get_points().flatten() return (x0, y0, x1 - x0, y1 - y0) - bounds = property(_get_bounds) + bounds = property(_get_bounds, None, None, """ + (property) Returns (:attr:`x0`, :attr:`y0`, :attr:`width`, :attr:`height`).""") def _get_extents(self): return self.get_points().flatten().copy() - extents = property(_get_extents) + extents = property(_get_extents, None, None, """ + (property) Returns (:attr:`x0`, :attr:`y0`, :attr:`x1`, :attr:`y1`).""") def get_points(self): return NotImplementedError() def containsx(self, x): + """ + Returns True if x is between or equal to :attr:`x0` and + :attr:`x1`. + """ x0, x1 = self.intervalx return ((x0 < x1 and (x >= x0 and x <= x1)) or (x >= x1 and x <= x0)) def containsy(self, y): + """ + Returns True if y is between or equal to :attr:`y0` and + :attr:`y1`. + """ y0, y1 = self.intervaly return ((y0 < y1 and (y >= y0 and y <= y1)) or (y >= y1 and y <= y0)) def contains(self, x, y): + """ + Returns True if (x, y) is a coordinate inside the bounding + box or on its edge. + """ return self.containsx(x) and self.containsy(y) def overlaps(self, other): + """ + Returns True if this bounding box overlaps with the given + bounding box ``other``. + """ ax1, ay1, ax2, ay2 = self._get_extents() bx1, by1, bx2, by2 = other._get_extents() @@ -346,22 +415,37 @@ (by1 > ay2)) def fully_containsx(self, x): + """ + Returns True if x is between but not equal to :attr:`x0` and + :attr:`x1`. + """ x0, x1 = self.intervalx return ((x0 < x1 and (x > x0 and x < x1)) or (x > x1 and x < x0)) def fully_containsy(self, y): + """ + Returns True if y is between but not equal to :attr:`y0` and + :attr:`y1`. + """ y0, y1 = self.intervaly return ((y0 < y1 and (x > y0 and x < y1)) or (x > y1 and x < y0)) def fully_contains(self, x, y): + """ + Returns True if (x, y) is a coordinate inside the bounding + box, but not on its edge. + """ return self.fully_containsx(x) \ and self.fully_containsy(y) def fully_overlaps(self, other): + """ + Returns True if this bounding box overlaps with the given + bounding box ``other``, but not on its edge alone.""" ax1, ay1, ax2, ay2 = self._get_extents() bx1, by1, bx2, by2 = other._get_extents() @@ -381,14 +465,15 @@ def transformed(self, transform): """ - Return a new Bbox object, transformed by the given transform. + Return a new :class:`Bbox` object, statically transformed by + the given transform. """ return Bbox(transform.transform(self.get_points())) def inverse_transformed(self, transform): """ - Return a new Bbox object, transformed by the inverse of the - given transform. + Return a new :class:`Bbox` object, statically transformed by + the inverse of the given transform. """ return Bbox(transform.inverted().transform(self.get_points())) @@ -406,13 +491,20 @@ Return a copy of the Bbox, shifted to position c within a container. - c: may be either a) a sequence (cx, cy) where cx, cy range - from 0 to 1, where 0 is left or bottom and 1 is right or top; - or b) a string: C for centered, S for bottom-center, SE for - bottom-left, E for left, etc. + c: may be either: - Optional arg container is the box within which the BBox - is positioned; it defaults to the initial BBox. + * a sequence (cx, cy) where cx, cy range + from 0 to 1, where 0 is left or bottom and 1 is right or top + + * a string: + - C for centered + - S for bottom-center + - SE for bottom-left + - E for left + - etc. + + Optional argument ``container`` is the box within which the :class:`Bbox` + is positioned; it defaults to the initial :class:`Bbox`. """ if container is None: container = self @@ -428,10 +520,10 @@ def shrunk(self, mx, my): """ - Return a copy of the Bbox, shurnk by the factor mx in the x - direction and the factor my in the y direction. The lower - left corner of the box remains unchanged. Normally mx and my - will be <= 1, but this is not enforced. + Return a copy of the :class:`Bbox`, shurnk by the factor mx in + the *x* direction and the factor my in the *y* direction. The + lower left corner of the box remains unchanged. Normally mx + and my will be less than 1, but this is not enforced. """ w, h = self.size return Bbox([self._points[0], @@ -439,13 +531,13 @@ def shrunk_to_aspect(self, box_aspect, container = None, fig_aspect = 1.0): """ - Return a copy of the Bbox, shrunk so that it is as large as it - can be while having the desired aspect ratio, box_aspect. If - the box coordinates are relative--that is, fractions of a - larger box such as a figure--then the physical aspect ratio of - that figure is specified with fig_aspect, so that box_aspect - can also be given as a ratio of the absolute dimensions, not - the relative dimensions. + Return a copy of the :class:`Bbox`, shrunk so that it is as + large as it can be while having the desired aspect ratio, + ``box_aspect``. If the box coordinates are relative---that + is, fractions of a larger box such as a figure---then the + physical aspect ratio of that figure is specified with + ``fig_aspect``, so that ``box_aspect`` can also be given as a + ratio of the absolute dimensions, not the relative dimensions. """ assert box_aspect > 0 and fig_aspect > 0 if container is None: @@ -462,11 +554,11 @@ def splitx(self, *args): """ - e.g., bbox.splitx(f1, f2, ...) + e.g., ``bbox.splitx(f1, f2, ...)`` - Returns a list of new BBoxes formed by - splitting the original one with vertical lines - at fractional positions f1, f2, ... + Returns a list of new :class:`Bbox` objects formed by + splitting the original one with vertical lines at fractional + positions f1, f2, ... """ boxes = [] xf = [0] + list(args) + [1] @@ -478,11 +570,11 @@ def splity(self, *args): """ - e.g., bbox.splitx(f1, f2, ...) + e.g., ``bbox.splitx(f1, f2, ...)`` - Returns a list of new PBoxes formed by - splitting the original one with horizontal lines - at fractional positions f1, f2, ... + Returns a list of new :class:`Bbox` objects formed by + splitting the original one with horizontal lines at fractional + positions f1, f2, ... """ boxes = [] yf = [0] + list(args) + [1] @@ -513,14 +605,15 @@ """ Count the number of bounding boxes that overlap this one. - bboxes is a sequence of Bbox objects + bboxes is a sequence of :class:`BboxBase` objects """ return count_bboxes_overlapping_bbox(self, bboxes) def expanded(self, sw, sh): """ - Return a new Bbox which is this Bbox expanded around its - center by the given factors sw and sh. + Return a new :class:`Bbox` which is this :class:`Bbox` + expanded around its center by the given factors ``sw`` and + ``sh``. """ width = self.width height = self.height @@ -531,31 +624,34 @@ def padded(self, p): """ - Return a new Bbox that is padded on all four sides by the - given value. + Return a new :class:`Bbox` that is padded on all four sides by + the given value. """ points = self._points return Bbox(points + [[-p, -p], [p, p]]) def translated(self, tx, ty): """ - Return a copy of the Bbox, translated by tx and ty. + Return a copy of the :class:`Bbox`, statically translated by + tx and ty. """ return Bbox(self._points + (tx, ty)) def corners(self): """ Return an array of points which are the four corners of this - rectangle. + rectangle. For example, if this :class:`Bbox` is defined by + the points (a, b) and (c, d), ``corners`` returns (a, b), (a, + d), (c, b) and (c, d). """ l, b, r, t = self.get_points().flatten() return np.array([[l, b], [l, t], [r, b], [r, t]]) def rotated(self, radians): """ - Return a new bounding box that bounds a rotated version of this - bounding box. The new bounding box is still aligned with the - axes, of course. + Return a new bounding box that bounds a rotated version of + this bounding box by the given radians. The new bounding box + is still aligned with the axes, of course. """ corners = self.corners() corners_rotated = Affine2D().rotate(radians).transform(corners) @@ -566,7 +662,7 @@ #@staticmethod def union(bboxes): """ - Return a Bbox that contains all of the given bboxes. + Return a :class:`Bbox` that contains all of the given bboxes. """ assert(len(bboxes)) @@ -592,14 +688,17 @@ class Bbox(BboxBase): + """ + A mutable bounding box. + """ + def __init__(self, points): """ - Create a new bounding box. - points: a 2x2 numpy array of the form [[x0, y0], [x1, y1]] - If you need to create Bbox from another form of data, consider the - class methods unit, from_bounds and from_extents. + If you need to create a :class:`Bbox` object from another form + of data, consider the static methods unit, from_bounds and + from_extents. """ BboxBase.__init__(self) self._points = np.asarray(points, np.float_) @@ -620,7 +719,8 @@ #@staticmethod def unit(): """ - Create a new unit BBox from (0, 0) to (1, 1). + (staticmethod) Create a new unit :class:`Bbox` from (0, 0) to + (1, 1). """ return Bbox(Bbox._unit_values.copy()) unit = staticmethod(unit) @@ -628,7 +728,8 @@ #@staticmethod def from_bounds(x0, y0, width, height): """ - Create a new Bbox from x0, y0, width and height. + (staticmethod) Create a new :class:`Bbox` from x0, y0, width + and height. width and height may be negative. """ @@ -638,7 +739,8 @@ #@staticmethod def from_extents(*args): """ - Create a new Bbox from left, bottom, right and top. + (staticmethod) Create a new Bbox from left, bottom, right and + top. The y-axis increases upwards. """ @@ -653,26 +755,32 @@ def ignore(self, value): """ Set whether the existing bounds of the box should be ignored - by subsequent calls to update_from_data or - update_from_data_xy. + by subsequent calls to :meth:`update_from_data` or + :meth:`update_from_data_xy`. - value: When True, subsequent calls to update_from_data will - ignore the existing bounds of the Bbox. - When False, subsequent calls to update_from_data will - include the existing bounds of the Bbox. + value: + + - When True, subsequent calls to :meth:`update_from_data` + will ignore the existing bounds of the :class:`Bbox`. + + - When False, subsequent calls to :meth:`update_from_data` + will include the existing bounds of the :class:`Bbox`. """ self._ignore = value def update_from_data(self, x, y, ignore=None): """ - Update the bounds of the Bbox based on the passed in data. + Update the bounds of the :class:`Bbox` based on the passed in + data. x: a numpy array of x-values + y: a numpy array of y-values + ignore: - when True, ignore the existing bounds of the Bbox. - when False, include the existing bounds of the Bbox. - when None, use the last value passed to Bbox.ignore(). + - when True, ignore the existing bounds of the Bbox. + - when False, include the existing bounds of the Bbox. + - when None, use the last value passed to :meth:`ignore`. """ warnings.warn("update_from_data requires a memory copy -- please replace with update_from_data_xy") xy = np.hstack((x.reshape((len(x), 1)), y.reshape((len(y), 1)))) @@ -680,13 +788,15 @@ def update_from_data_xy(self, xy, ignore=None): """ - Update the bounds of the Bbox based on the passed in data. + Update the bounds of the :class:`Bbox` based on the passed in + data. xy: a numpy array of 2D points + ignore: - when True, ignore the existing bounds of the Bbox. - when False, include the existing bounds of the Bbox. - when None, use the last value passed to Bbox.ignore(). + - when True, ignore the existing bounds of the Bbox. + - when False, include the existing bounds of the Bbox. + - when None, use the last value passed to :meth:`ignore`. """ if ignore is None: ignore = self._ignore @@ -767,7 +877,7 @@ def get_points(self): """ - Set the points of the bounding box directly as a numpy array + Get the points of the bounding box directly as a numpy array of the form: [[x0, y0], [x1, y1]]. """ self._invalid = 0 @@ -794,13 +904,14 @@ class TransformedBbox(BboxBase): """ - A Bbox that is automatically transformed by a given Transform. When - either the child bbox or transform changes, the bounds of this bbox - will update accordingly. + A :class:`Bbox` that is automatically transformed by a given + transform. When either the child bounding box or transform + changes, the bounds of this bbox will update accordingly. """ def __init__(self, bbox, transform): """ bbox: a child bbox + transform: a 2D transform """ assert bbox.is_bbox @@ -827,6 +938,7 @@ self._points = points self._invalid = 0 return self._points + get_points.__doc__ = Bbox.get_points.__doc__ if DEBUG: _get_points = get_points @@ -840,24 +952,25 @@ The base class of all TransformNodes that actually perform a transformation. - All non-affine transformations should be subclass this class. New - affine transformations should subclass Affine2D. + All non-affine transformations should be subclasses of this class. + New affine transformations should be subclasses of + :class:`Affine2D`. Subclasses of this class should override the following members (at minimum): - input_dims - output_dims - transform - is_separable - has_inverse - inverted (if has_inverse will return True) + - :attr:`input_dims` + - :attr:`output_dims` + - :meth:`transform` + - :attr:`is_separable` + - :attr:`has_inverse` + - :meth:`inverted` (if :meth:`has_inverse` can return True) - If the transform needs to do something non-standard with Paths, - such as adding curves where there were once line segments, it - should override: + If the transform needs to do something non-standard with + :class:`mathplotlib.path.Path` objects, such as adding curves + where there were once line segments, it should override: - transform_path + - :meth:`transform_path` """ # The number of input and output dimensions for this transform. # These must be overridden (with integers) in the subclass. @@ -885,6 +998,9 @@ "Can not add Transform to object of type '%s'" % type(other)) def __radd__(self, other): + """ + Composes two transforms together such that self is followed by other. + """ if isinstance(other, Transform): return composite_transform_factory(other, self) raise TypeError( @@ -900,8 +1016,8 @@ """ Performs the transformation on the given array of values. - Accepts a numpy array of shape (N x self.input_dims) and - returns a numpy array of shape (N x self.output_dims). + Accepts a numpy array of shape (N x :attr:`input_dims`) and + returns a numpy array of shape (N x :attr:`output_dims`). """ raise NotImplementedError() @@ -910,15 +1026,15 @@ Performs only the affine part of this transformation on the given array of values. - transform(values) is equivalent to - transform_affine(transform_non_affine(values)). + ``transform(values)`` is always equivalent to + ``transform_affine(transform_non_affine(values))``. In non-affine transformations, this is generally a no-op. In affine transformations, this is equivalent to - transform(values). + ``transform(values)``. - Accepts a numpy array of shape (N x self.input_dims) and - returns a numpy array of shape (N x self.output_dims). + Accepts a numpy array of shape (N x :attr:`input_dims`) and + returns a numpy array of shape (N x :attr:`output_dims`). """ return values @@ -926,15 +1042,15 @@ """ Performs only the non-affine part of the transformation. - transform(values) is equivalent to - transform_affine(transform_non_affine(values)). + ``transform(values)`` is always equivalent to + ``transform_affine(transform_non_affine(values))``. In non-affine transformations, this is generally equivalent to - transform(values). In affine transformations, this is a - no-op. + ``transform(values)``. In affine transformations, this is + always a no-op. - Accepts a numpy array of shape (N x self.input_dims) and - returns a numpy array of shape (N x self.output_dims). + Accepts a numpy array of shape (N x :attr:`input_dims`) and + returns a numpy array of shape (N x :attr:`output_dims`). """ return self.transform(points) @@ -949,11 +1065,11 @@ A convenience function that returns the transformed copy of a single point. - The point is given as a sequence of length self.input_dims. + The point is given as a sequence of length :attr:`input_dims`. The transformed point is returned as a sequence of length - self.output_dims. + :attr:`output_dims`. """ - assert len(point) == 2 + assert len(point) == self.input_dims return self.transform(np.asarray([point]))[0] def transform_path(self, path): @@ -974,8 +1090,8 @@ path: a Path instance - transform_path(path) is equivalent to - transform_path_affine(transform_path_non_affine(values)). + ``transform_path(path)`` is equivalent to + ``transform_path_affine(transform_path_non_affine(values))``. """ return path @@ -986,8 +1102,8 @@ path: a Path instance - transform_path(path) is equivalent to - transform_path_affine(transform_path_non_affine(values)). + ``transform_path(path)`` is equivalent to + ``transform_path_affine(transform_path_non_affine(values))``. """ return Path(self.transform_non_affine(path.vertices), path.codes) @@ -999,7 +1115,7 @@ temporary. An update to 'self' does not cause a corresponding update to its inverted copy. - x === self.inverted().transform(self.transform(x)) + ``x === self.inverted().transform(self.transform(x))`` """ raise NotImplementedError() @@ -1013,17 +1129,17 @@ run time with a transform of a different type. This class allows that replacement to correctly trigger invalidation. - Note that TransformWrapper instances must have the same input and - output dimensions during their entire lifetime, so the child - transform may only be replaced with another child transform of the - same dimensions. + Note that :class:`TransformWrapper` instances must have the same + input and output dimensions during their entire lifetime, so the + child transform may only be replaced with another child transform + of the same dimensions. """ pass_through = True def __init__(self, child): """ child: A Transform instance. This child may later be replaced - with set(). + with :meth:`set`. """ assert isinstance(child, Transform) @@ -1133,13 +1249,14 @@ """ The base class of all 2D affine transformations. - 2D affine transformations are performed using a 3x3 numpy array: + 2D affine transformations are performed using a 3x3 numpy array:: a c e b d f 0 0 1 - Provides the read-only interface. + This class provides the read-only interface. For a mutable 2D + affine transformation, use :class:`Affine2D`. Subclasses of this class will generally only need to override a constructor and 'get_matrix' that generates a custom 3x3 matrix. @@ -1175,7 +1292,8 @@ #@staticmethod def matrix_from_values(a, b, c, d, e, f): """ - Create a new transformation matrix as a 3x3 numpy array of the form: + (staticmethod) Create a new transformation matrix as a 3x3 + numpy array of the form:: a c e b d f @@ -1194,6 +1312,7 @@ def transform_point(self, point): mtx = self.get_matrix() return affine_transform(point, mtx) + transform_point.__doc__ = AffineBase.transform_point.__doc__ if DEBUG: _transform = transform @@ -1223,9 +1342,13 @@ class Affine2D(Affine2DBase): + """ + A mutable 2D affine transformation. + """ + def __init__(self, matrix = None): """ - Initialize an Affine transform from a 3x3 numpy float array: + Initialize an Affine transform from a 3x3 numpy float array:: a c e b d f @@ -1255,7 +1378,8 @@ #@staticmethod def from_values(a, b, c, d, e, f): """ - Create a new Affine2D instance from the given values: + (staticmethod) Create a new Affine2D instance from the given + values:: a c e b d f @@ -1268,7 +1392,7 @@ def get_matrix(self): """ - Get the underlying transformation matrix as a 3x3 numpy array: + Get the underlying transformation matrix as a 3x3 numpy array:: a c e b d f @@ -1279,7 +1403,7 @@ def set_matrix(self, mtx): """ - Set the underlying transformation matrix from a 3x3 numpy array: + Set the underlying transformation matrix from a 3x3 numpy array:: a c e b d f @@ -1291,7 +1415,7 @@ def set(self, other): """ Set this transformation from the frozen copy of another - Affine2DBase instance. + :class:`Affine2DBase` object. """ assert isinstance(other, Affine2DBase) self._mtx = other.get_matrix() @@ -1300,10 +1424,11 @@ #@staticmethod def identity(): """ - Return a new Affine2D instance that is the identity transform. + (staticmethod) Return a new :class:`Affine2D` object that is + the identity transform. Unless this transform will be mutated later on, consider using - the faster IdentityTransform class instead. + the faster :class:`IdentityTransform` class instead. """ return Affine2D(np.identity(3)) identity = staticmethod(identity) @@ -1321,7 +1446,8 @@ Add a rotation (in radians) to this transform in place. Returns self, so this method can easily be chained with more - calls to rotate(), rotate_deg(), translate() and scale(). + calls to :meth:`rotate`, :meth:`rotate_deg, :meth:`translate` + and :meth:`scale`. """ a = np.cos(theta) b = np.sin(theta) @@ -1337,7 +1463,8 @@ Add a rotation (in degrees) to this transform in place. Returns self, so this method can easily be chained with more - calls to rotate(), rotate_deg(), translate() and scale(). + calls to :meth:`rotate`, :meth:`rotate_deg, :meth:`translate` + and :meth:`scale`. """ return self.rotate(degrees*np.pi/180.) @@ -1346,7 +1473,8 @@ Add a rotation (in radians) around the point (x, y) in place. Returns self, so this method can easily be chained with more - calls to rotate(), rotate_deg(), translate() and scale(). + calls to :meth:`rotate`, :meth:`rotate_deg, :meth:`translate` + and :meth:`scale`. """ return self.translate(-x, -y).rotate(theta).translate(x, y) @@ -1355,7 +1483,8 @@ Add a rotation (in degrees) around the point (x, y) in place. Returns self, so this method can easily be chained with more - calls to rotate(), rotate_deg(), translate() and scale(). + calls to :meth:`rotate`, :meth:`rotate_deg, :meth:`translate` + and :meth:`scale`. """ return self.translate(-x, -y).rotate_deg(degrees).translate(x, y) @@ -1364,7 +1493,8 @@ Adds a translation in place. Returns self, so this method can easily be chained with more - calls to rotate(), rotate_deg(), translate() and scale(). + calls to :meth:`rotate`, :meth:`rotate_deg, :meth:`translate` + and :meth:`scale`. """ translate_mtx = np.array( [[1.0, 0.0, tx], [0.0, 1.0, ty], [0.0, 0.0, 1.0]], @@ -1381,7 +1511,8 @@ y-directions. Returns self, so this method can easily be chained with more - calls to rotate(), rotate_deg(), translate() and scale(). + calls to :meth:`rotate`, :meth:`rotate_deg, :meth:`translate` + and :meth:`scale`. """ if sy is None: sy = sx @@ -1464,8 +1595,8 @@ transform the x-axis and y_transform to transform the y_axis. You will generally not call this constructor directly but use - the blended_transform_factory function instead, which can - determine automatically which kind of blended transform to + the :func:`blended_transform_factory` function instead, which + can determine automatically which kind of blended transform to create. """ # Here we ask: "Does it blend?" @@ -1565,8 +1696,8 @@ Both x_transform and y_transform must be 2D affine transforms. You will generally not call this constructor directly but use - the blended_transform_factory function instead, which can - determine automatically which kind of blended transform to + the :func:`blended_transform_factory` function instead, which + can determine automatically which kind of blended transform to create. """ assert x_transform.is_affine @@ -1608,8 +1739,8 @@ Create a new "blended" transform using x_transform to transform the x-axis and y_transform to transform the y_axis. - Shortcut versions of the blended transform are provided for the - case where both child transforms are affine. + A faster version of the blended transform is returned for the case + where both child transforms are affine. """ if (isinstance(x_transform, Affine2DBase) and isinstance(y_transform, Affine2DBase)): @@ -1631,9 +1762,9 @@ applying transform a then transform b. You will generally not call this constructor directly but use - the composite_transform_factory function instead, which can - automatically choose the best kind of composite transform - instance to create. + the :func:`composite_transform_factory` function instead, + which can automatically choose the best kind of composite + transform instance to create. """ assert a.output_dims == b.input_dims self.input_dims = a.input_dims @@ -1722,12 +1853,12 @@ Create a new composite transform that is the result of applying transform a then transform b. - Both a and b must be instances of Affine2DBase. + Both a and b must be instances of :class:`Affine2DBase`. You will generally not call this constructor directly but use - the composite_transform_factory function instead, which can - automatically choose the best kind of composite transform - instance to create. + the :func:`composite_transform_factory` function instead, + which can automatically choose the best kind of composite + transform instance to create. """ assert a.output_dims == b.input_dims self.input_dims = a.input_dims @@ -1765,7 +1896,8 @@ case where both child transforms are affine, or one or the other is the identity transform. - Composite TransformNodes may also be created using the '+' operator, e.g.: + Composite transforms may also be created using the '+' operator, + e.g.: c = a + b """ @@ -1823,15 +1955,15 @@ class BboxTransformTo(Affine2DBase): """ - BboxTransformSimple linearly transforms points from the unit Bbox - to another Bbox. + BboxTransformTo is a transformation that linearly transforms + points from the unit bounding box to a given :class:`Bbox`. """ is_separable = True def __init__(self, boxout): """ - Create a new BboxTransform that linearly transforms points - from the unit Bbox to boxout. + Create a new :class:`BboxTransformTo` that linearly transforms + points from the unit bounding box to boxout. """ assert boxout.is_bbox @@ -1862,16 +1994,12 @@ class BboxTransformFrom(Affine2DBase): """ - BboxTransform linearly transforms points from one Bbox to the unit - Bbox. + BboxTransform linearly transforms points from a given + :class:`Bbox` to the unit bounding box. """ is_separable = True def __init__(self, boxin): - """ - Create a new BboxTransform that linearly transforms points - from boxin to the unit Bbox. - """ assert boxin.is_bbox Affine2DBase.__init__(self) @@ -1902,6 +2030,10 @@ class ScaledTranslation(Affine2DBase): + """ + A transformation that translates by xt and yt, after xt and yt + have been transformaed by the given transform scale_trans. + """ def __init__(self, xt, yt, scale_trans): Affine2DBase.__init__(self) self._t = (xt, yt) @@ -1978,7 +2110,7 @@ Ensure the endpoints of a range are not too close together. "too close" means the interval is smaller than 'tiny' times - the maximum absolute value. + the maximum absolute value. If they are too close, each will be moved by the 'expander'. If 'increasing' is True and vmin > vmax, they will be swapped, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-06-05 14:18:43
|
Revision: 5395 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5395&view=rev Author: jdh2358 Date: 2008-06-05 07:18:31 -0700 (Thu, 05 Jun 2008) Log Message: ----------- some fixes for classic toolbar Modified Paths: -------------- trunk/matplotlib/examples/user_interfaces/embedding_in_gtk2.py trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py trunk/matplotlib/lib/matplotlib/ticker.py Modified: trunk/matplotlib/examples/user_interfaces/embedding_in_gtk2.py =================================================================== --- trunk/matplotlib/examples/user_interfaces/embedding_in_gtk2.py 2008-06-05 13:45:27 UTC (rev 5394) +++ trunk/matplotlib/examples/user_interfaces/embedding_in_gtk2.py 2008-06-05 14:18:31 UTC (rev 5395) @@ -14,8 +14,8 @@ #from matplotlib.backends.backend_gtkcairo import FigureCanvasGTKCairo as FigureCanvas # or NavigationToolbar for classic -from matplotlib.backends.backend_gtk import NavigationToolbar2GTK as NavigationToolbar -#from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar +#from matplotlib.backends.backend_gtk import NavigationToolbar2GTK as NavigationToolbar +from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar win = gtk.Window() Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-06-05 13:45:27 UTC (rev 5394) +++ trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-06-05 14:18:31 UTC (rev 5395) @@ -353,12 +353,12 @@ # for self.window(for pixmap) and has a side effect of altering # figure width,height (via configure-event?) gtk.DrawingArea.realize(self) - + width, height = self.get_width_height() pixmap = gdk.Pixmap (self.window, width, height) self._renderer.set_pixmap (pixmap) self._render_figure(pixmap, width, height) - + # jpg colors don't match the display very well, png colors match # better pixbuf = gdk.Pixbuf(gdk.COLORSPACE_RGB, 0, 8, width, height) @@ -382,18 +382,18 @@ raise ValueError("Saving to a Python file-like object is only supported by PyGTK >= 2.8") else: raise ValueError("filename must be a path or a file-like object") - + def get_default_filetype(self): return 'png' def flush_events(self): - gtk.gdk.threads_enter() + gtk.gdk.threads_enter() while gtk.events_pending(): gtk.main_iteration(True) gtk.gdk.flush() gtk.gdk.threads_leave() - - + + class FigureManagerGTK(FigureManagerBase): """ Public attributes @@ -410,7 +410,7 @@ self.window = gtk.Window() self.window.set_title("Figure %d" % num) - + self.vbox = gtk.VBox() self.window.add(self.vbox) self.vbox.show() @@ -462,7 +462,7 @@ def show(self): # show the figure window self.window.show() - + def full_screen_toggle (self): self._full_screen_flag = not self._full_screen_flag if self._full_screen_flag: @@ -742,8 +742,8 @@ self.fileselect = FileChooserDialog( title='Save the figure', parent=self.win, - formats=self.canvas.get_supported_filetypes(), - default_type=self.canvas.get_default_filetype()) + filetypes=self.canvas.get_supported_filetypes(), + default_filetype=self.canvas.get_default_filetype()) else: self._create_toolitems_2_2() self.update = self._update_2_2 @@ -912,53 +912,32 @@ self._ind = ind self._active = [ self._axes[i] for i in self._ind ] - def panx(self, button, arg): - """arg is either user callback data or a scroll event - """ - try: - if arg.direction == gdk.SCROLL_UP: direction=1 - else: direction=-1 - except AttributeError: - direction = arg + def panx(self, button, direction): + 'panx in direction' for a in self._active: - a.panx(direction) + a.xaxis.pan(direction) self.canvas.draw() return True - def pany(self, button, arg): - try: - if arg.direction == gdk.SCROLL_UP: direction=1 - else: direction=-1 - except AttributeError: - direction = arg - + def pany(self, button, direction): + 'pany in direction' for a in self._active: - a.pany(direction) + a.yaxis.pan(direction) self.canvas.draw() return True - def zoomx(self, button, arg): - try: - if arg.direction == gdk.SCROLL_UP: direction=1 - else: direction=-1 - except AttributeError: - direction = arg - + def zoomx(self, button, direction): + 'zoomx in direction' for a in self._active: - a.zoomx(direction) + a.xaxis.zoom(direction) self.canvas.draw() return True - def zoomy(self, button, arg): - try: - if arg.direction == gdk.SCROLL_UP: direction=1 - else: direction=-1 - except AttributeError: - direction = arg - + def zoomy(self, button, direction): + 'zoomy in direction' for a in self._active: - a.zoomy(direction) + a.yaxis.zoom(direction) self.canvas.draw() return True @@ -1043,7 +1022,7 @@ break filename = self.get_filename() break - + self.hide() return filename, self.ext else: @@ -1075,8 +1054,8 @@ if ext.startswith('.'): ext = ext[1:] return filename, ext - + class DialogLineprops: """ A GUI dialog for controlling lineprops Modified: trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2008-06-05 13:45:27 UTC (rev 5394) +++ trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2008-06-05 14:18:31 UTC (rev 5395) @@ -487,46 +487,26 @@ self._ind = ind self._active = [ self._axes[i] for i in self._ind ] - def panx(self, arg): - try: arg.direction - except AttributeError: direction = arg - else: - if arg.direction == Tk.SCROLL_UP: direction=1 - else: direction=-1 + def panx(self, direction): for a in self._active: - a.panx(direction) + a.xaxis.pan(direction) self.canvas.draw() - def pany(self, arg): - try: arg.direction - except AttributeError: direction = arg - else: - if arg.direction == Tk.SCROLL_UP: direction=1 - else: direction=-1 + def pany(self, direction): for a in self._active: - a.pany(direction) + a.yaxis.pan(direction) self.canvas.draw() - def zoomx(self, arg): - try: arg.direction - except AttributeError: direction = arg - else: - if arg.direction == Tk.SCROLL_UP: direction=1 - else: direction=-1 + def zoomx(self, direction): for a in self._active: - a.zoomx(direction) + a.xaxis.zoom(direction) self.canvas.draw() - def zoomy(self, arg): - try: arg.direction - except AttributeError: direction = arg - else: - if arg.direction == Tk.SCROLL_UP: direction=1 - else: direction=-1 + def zoomy(self, direction): for a in self._active: - a.zoomy(direction) + a.yaxis.zoom(direction) self.canvas.draw() def save_figure(self): @@ -666,14 +646,14 @@ # so we just have to put it first default_filetype_name = filetypes[default_filetype] del filetypes[default_filetype] - + sorted_filetypes = filetypes.items() sorted_filetypes.sort() sorted_filetypes.insert(0, (default_filetype, default_filetype_name)) - + tk_filetypes = [ (name, '*.%s' % ext) for (ext, name) in sorted_filetypes] - + fname = asksaveasfilename( master=self.window, title='Save the figure', Modified: trunk/matplotlib/lib/matplotlib/ticker.py =================================================================== --- trunk/matplotlib/lib/matplotlib/ticker.py 2008-06-05 13:45:27 UTC (rev 5394) +++ trunk/matplotlib/lib/matplotlib/ticker.py 2008-06-05 14:18:31 UTC (rev 5395) @@ -639,17 +639,17 @@ ticks = self() numticks = len(ticks) + vmin, vmax = self.axis.get_view_interval() + vmin, vmax = mtransforms.nonsingular(vmin, vmax, expander = 0.05) if numticks>2: step = numsteps*abs(ticks[0]-ticks[1]) else: - vmin, vmax = self.axis.get_view_interval() - vmin, vmax = mtransforms.nonsingular(vmin, vmax, expander = 0.05) d = abs(vmax-vmin) step = numsteps*d/6. vmin += step vmax += step - self.axis.set_view_interval(vmin, vmax) + self.axis.set_view_interval(vmin, vmax, ignore=True) def zoom(self, direction): @@ -658,12 +658,9 @@ vmin, vmax = self.axis.get_view_interval() vmin, vmax = mtransforms.nonsingular(vmin, vmax, expander = 0.05) interval = abs(vmax-vmin) - interval = self.viewInterval.span() step = 0.1*interval*direction + self.axis.set_view_interval(vmin + step, vmax - step, ignore=True) - - self.axis.set_view_interval(vmin + step, vmax - step) - def refresh(self): 'refresh internal information based on current lim' pass This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-06-05 14:44:13
|
Revision: 5397 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5397&view=rev Author: jdh2358 Date: 2008-06-05 07:44:07 -0700 (Thu, 05 Jun 2008) Log Message: ----------- getting classic toolbar in sync on branch and trunk for svnmerge Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Name: svnmerge-integrated - /branches/v0_91_maint:1-5385 + /branches/v0_91_maint:1-5396 Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-06-05 14:37:03 UTC (rev 5396) +++ trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-06-05 14:44:07 UTC (rev 5397) @@ -386,6 +386,7 @@ def get_default_filetype(self): return 'png' + def flush_events(self): gtk.gdk.threads_enter() while gtk.events_pending(): @@ -393,7 +394,6 @@ gtk.gdk.flush() gtk.gdk.threads_leave() - class FigureManagerGTK(FigureManagerBase): """ Public attributes @@ -950,6 +950,7 @@ except Exception, e: error_msg_gtk(str(e), parent=self) + if gtk.pygtk_version >= (2,4,0): class FileChooserDialog(gtk.FileChooserDialog): """GTK+ 2.4 file selector which remembers the last file/directory This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-06-05 16:18:00
|
Revision: 5401 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5401&view=rev Author: jdh2358 Date: 2008-06-05 09:17:57 -0700 (Thu, 05 Jun 2008) Log Message: ----------- fixed collection demo to remove deprecated dpi Modified Paths: -------------- trunk/matplotlib/doc/users/navigation_toolbar.rst trunk/matplotlib/examples/api/collections_demo.py Added Paths: ----------- trunk/matplotlib/doc/_static/toolbar.png Added: trunk/matplotlib/doc/_static/toolbar.png =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/doc/_static/toolbar.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Modified: trunk/matplotlib/doc/users/navigation_toolbar.rst =================================================================== --- trunk/matplotlib/doc/users/navigation_toolbar.rst 2008-06-05 15:08:28 UTC (rev 5400) +++ trunk/matplotlib/doc/users/navigation_toolbar.rst 2008-06-05 16:17:57 UTC (rev 5401) @@ -3,6 +3,9 @@ Interactive navigation ====================== +.. image:: ../_static/toolbar.png + :scale: 100 + All figure windows come with a navigation toolbar, which can be used to navigate through the data set. Here is a description of each of the buttons at the bottom of the toolbar Modified: trunk/matplotlib/examples/api/collections_demo.py =================================================================== --- trunk/matplotlib/examples/api/collections_demo.py 2008-06-05 15:08:28 UTC (rev 5400) +++ trunk/matplotlib/examples/api/collections_demo.py 2008-06-05 16:17:57 UTC (rev 5401) @@ -86,7 +86,7 @@ a = fig.add_subplot(2,2,3) -col = collections.RegularPolyCollection(fig.dpi, 7, +col = collections.RegularPolyCollection(7, sizes = N.fabs(xx)*10.0, offsets=xyo, transOffset=a.transData) trans = transforms.Affine2D().scale(fig.dpi/72.0) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2008-06-05 17:06:18
|
Revision: 5402 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5402&view=rev Author: mdboom Date: 2008-06-05 10:06:16 -0700 (Thu, 05 Jun 2008) Log Message: ----------- Fix one-pixel space between images and axes border. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/image.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-05 16:17:57 UTC (rev 5401) +++ trunk/matplotlib/CHANGELOG 2008-06-05 17:06:16 UTC (rev 5402) @@ -1,3 +1,6 @@ +2008-06-05 Fix image drawing so there is no extra space to the right + or bottom - MGD + 2006-06-04 Added a figure title command subtitle as a Figure method and pyplot command -- see examples/figure_title.py - JDH Modified: trunk/matplotlib/lib/matplotlib/image.py =================================================================== --- trunk/matplotlib/lib/matplotlib/image.py 2008-06-05 16:17:57 UTC (rev 5401) +++ trunk/matplotlib/lib/matplotlib/image.py 2008-06-05 17:06:16 UTC (rev 5402) @@ -205,7 +205,9 @@ tx = (xmin-self.axes.viewLim.x0)/dxintv * numcols ty = (ymin-self.axes.viewLim.y0)/dyintv * numrows - l, b, widthDisplay, heightDisplay = self.axes.bbox.bounds + l, b, r, t = self.axes.bbox.extents + widthDisplay = (round(r) + 0.5) - (round(l) - 0.5) + heightDisplay = (round(t) + 0.5) - (round(b) - 0.5) widthDisplay *= magnification heightDisplay *= magnification im.apply_translation(tx, ty) @@ -226,7 +228,7 @@ warnings.warn("Images are not supported on non-linear axes.") im = self.make_image(renderer.get_image_magnification()) l, b, widthDisplay, heightDisplay = self.axes.bbox.bounds - renderer.draw_image(l, b, im, self.axes.bbox.frozen(), + renderer.draw_image(round(l), round(b), im, self.axes.bbox.frozen(), *self.get_transformed_clip_path_and_affine()) def contains(self, mouseevent): @@ -378,7 +380,9 @@ raise RuntimeError('You must first set the image array') x0, y0, v_width, v_height = self.axes.viewLim.bounds - l, b, width, height = self.axes.bbox.bounds + l, b, r, t = self.axes.bbox.extents + width = (round(r) + 0.5) - (round(l) - 0.5) + height = (round(t) + 0.5) - (round(b) - 0.5) width *= magnification height *= magnification im = _image.pcolor(self._Ax, self._Ay, self._A, @@ -487,8 +491,11 @@ fc = self.axes.get_frame().get_facecolor() bg = mcolors.colorConverter.to_rgba(fc, 0) bg = (np.array(bg)*255).astype(np.uint8) - width = self.axes.bbox.width * magnification - height = self.axes.bbox.height * magnification + l, b, r, t = self.axes.bbox.extents + width = (round(r) + 0.5) - (round(l) - 0.5) + height = (round(t) + 0.5) - (round(b) - 0.5) + width = width * magnification + height = height * magnification if self.check_update('array'): A = self.to_rgba(self._A, alpha=self._alpha, bytes=True) self._rgbacache = A @@ -508,8 +515,8 @@ def draw(self, renderer, *args, **kwargs): if not self.get_visible(): return im = self.make_image(renderer.get_image_magnification()) - renderer.draw_image(self.axes.bbox.xmin, - self.axes.bbox.ymin, + renderer.draw_image(round(self.axes.bbox.xmin), + round(self.axes.bbox.ymin), im, self.axes.bbox.frozen(), *self.get_transformed_clip_path_and_affine()) @@ -638,7 +645,7 @@ def draw(self, renderer, *args, **kwargs): if not self.get_visible(): return im = self.make_image() - renderer.draw_image(self.ox, self.oy, im, self.figure.bbox, + renderer.draw_image(round(self.ox), round(self.oy), im, self.figure.bbox, *self.get_transformed_clip_path_and_affine()) def write_png(self, fname): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2008-06-05 17:09:10
|
Revision: 5403 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5403&view=rev Author: mdboom Date: 2008-06-05 10:09:04 -0700 (Thu, 05 Jun 2008) Log Message: ----------- Fix dpi-changing-related bugs in Axes.scatter() Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/api/collections_demo.py trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/collections.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-05 17:06:16 UTC (rev 5402) +++ trunk/matplotlib/CHANGELOG 2008-06-05 17:09:04 UTC (rev 5403) @@ -1,3 +1,6 @@ +2008-06-05 Fix some dpi-changing-related problems with PolyCollection, + as called by Axes.scatter() - MGD + 2008-06-05 Fix image drawing so there is no extra space to the right or bottom - MGD Modified: trunk/matplotlib/examples/api/collections_demo.py =================================================================== --- trunk/matplotlib/examples/api/collections_demo.py 2008-06-05 17:06:16 UTC (rev 5402) +++ trunk/matplotlib/examples/api/collections_demo.py 2008-06-05 17:09:04 UTC (rev 5403) @@ -33,8 +33,9 @@ spiral = zip(xx,yy) # Make some offsets -xo = N.random.randn(npts) -yo = N.random.randn(npts) +rs = N.random.RandomState([12345678]) +xo = rs.randn(npts) +yo = rs.randn(npts) xyo = zip(xo, yo) # Make a list of colors cycling through the rgbcmyk series. @@ -45,7 +46,7 @@ a = fig.add_subplot(2,2,1) col = collections.LineCollection([spiral], offsets=xyo, transOffset=a.transData) -trans = transforms.Affine2D().scale(fig.dpi/72.0) +trans = fig.dpi_scale_trans + transforms.Affine2D().scale(1.0/72.0) col.set_transform(trans) # the points to pixels transform # Note: the first argument to the collection initializer # must be a list of sequences of x,y tuples; we have only @@ -112,7 +113,7 @@ xx = (0.2 + (ym-yy)/ym)**2 * N.cos(yy-0.4) * 0.5 segs = [] for i in range(ncurves): - xxx = xx + 0.02*N.random.randn(nverts) + xxx = xx + 0.02*rs.randn(nverts) curve = zip(xxx, yy*100) segs.append(curve) Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-06-05 17:06:16 UTC (rev 5402) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-06-05 17:09:04 UTC (rev 5403) @@ -4603,15 +4603,8 @@ rescale = np.sqrt(max(verts[:,0]**2+verts[:,1]**2)) verts /= rescale - scales = np.asarray(scales) - scales = np.sqrt(scales * self.figure.dpi / 72.) - if len(scales)==1: - verts = [scales[0]*verts] - else: - # todo -- make this nx friendly - verts = [verts*s for s in scales] collection = mcoll.PolyCollection( - verts, + verts, scales, facecolors = colors, edgecolors = edgecolors, linewidths = linewidths, Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2008-06-05 17:06:16 UTC (rev 5402) +++ trunk/matplotlib/lib/matplotlib/collections.py 2008-06-05 17:09:04 UTC (rev 5403) @@ -492,15 +492,19 @@ renderer.close_group(self.__class__.__name__) class PolyCollection(Collection): - def __init__(self, verts, **kwargs): + def __init__(self, verts, sizes = (1, ), **kwargs): """ verts is a sequence of ( verts0, verts1, ...) where verts_i is a sequence of xy tuples of vertices, or an equivalent numpy array of shape (nv,2). + sizes gives the area of the circle circumscribing the + polygon in points^2 + %(Collection)s """ Collection.__init__(self,**kwargs) + self._sizes = sizes self.set_verts(verts) __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd @@ -511,6 +515,15 @@ def get_paths(self): return self._paths + def draw(self, renderer): + # sizes is the area of the circle circumscribing the polygon + # in points^2 + self._transforms = [ + transforms.Affine2D().scale( + (np.sqrt(x) * renderer.dpi / 72.0)) + for x in self._sizes] + return Collection.draw(self, renderer) + class BrokenBarHCollection(PolyCollection): """ A colleciton of horizontal bars spanning yrange with a sequence of This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2008-06-06 12:57:51
|
Revision: 5410 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5410&view=rev Author: mdboom Date: 2008-06-06 05:57:24 -0700 (Fri, 06 Jun 2008) Log Message: ----------- Fix polygon closing and provide option not to close (used by hist(histtype="step")) Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/patches.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-06 12:07:53 UTC (rev 5409) +++ trunk/matplotlib/CHANGELOG 2008-06-06 12:57:24 UTC (rev 5410) @@ -1,3 +1,6 @@ +2008-06-06 Fix closed polygon patch and also provide the option to + not close the polygon - MGD + 2008-06-05 Fix some dpi-changing-related problems with PolyCollection, as called by Axes.scatter() - MGD Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-06-06 12:07:53 UTC (rev 5409) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-06-06 12:57:24 UTC (rev 5410) @@ -345,12 +345,16 @@ seg = mpatches.Polygon(zip(x, y), facecolor = facecolor, fill=True, + closed=closed ) self.set_patchprops(seg, **kwargs) ret.append(seg) - if self.command == 'plot': func = makeline - else: func = makefill + if self.command == 'plot': + func = makeline + else: + closed = kwargs.pop("closed") + func = makefill if multicol: for j in range(y.shape[1]): func(x[:,j], y[:,j]) @@ -387,12 +391,16 @@ seg = mpatches.Polygon(zip(x, y), facecolor = facecolor, fill=True, + closed=closed ) self.set_patchprops(seg, **kwargs) ret.append(seg) - if self.command == 'plot': func = makeline - else: func = makefill + if self.command == 'plot': + func = makeline + else: + closed = kwargs.pop('closed') + func = makefill if multicol: for j in range(y.shape[1]): @@ -4934,6 +4942,8 @@ See examples/fill_between.py for more examples. + The closed kwarg will close the polygon when True (default). + kwargs control the Polygon properties: %(Polygon)s """ @@ -5809,7 +5819,7 @@ x,y = y,x elif orientation != 'vertical': raise ValueError, 'invalid orientation: %s' % orientation - patches.append( self.fill(x,y) ) + patches.append( self.fill(x,y,closed=False) ) # adopted from adjust_x/ylim part of the bar method if orientation == 'horizontal': Modified: trunk/matplotlib/lib/matplotlib/patches.py =================================================================== --- trunk/matplotlib/lib/matplotlib/patches.py 2008-06-06 12:07:53 UTC (rev 5409) +++ trunk/matplotlib/lib/matplotlib/patches.py 2008-06-06 12:57:24 UTC (rev 5410) @@ -531,7 +531,7 @@ def __str__(self): return "Poly((%g, %g) ...)" % tuple(self._path.vertices[0]) - def __init__(self, xy, **kwargs): + def __init__(self, xy, closed=True, **kwargs): """ xy is a numpy array with shape Nx2 @@ -541,7 +541,7 @@ """ Patch.__init__(self, **kwargs) xy = np.asarray(xy, np.float_) - if len(xy) and xy[0] != xy[-1]: + if closed and len(xy) and (xy[0] != xy[-1]).any(): xy = np.concatenate([xy, [xy[0]]]) self._path = Path(xy) __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mme...@us...> - 2008-06-06 16:34:10
|
Revision: 5411 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5411&view=rev Author: mmetz_bn Date: 2008-06-06 09:34:00 -0700 (Fri, 06 Jun 2008) Log Message: ----------- a further hist() update Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/pylab_examples/histogram_demo_extended.py trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-06 12:57:24 UTC (rev 5410) +++ trunk/matplotlib/CHANGELOG 2008-06-06 16:34:00 UTC (rev 5411) @@ -1,3 +1,9 @@ +2008-06-06 hist() revision, applied ideas proposed by Erik Tollerud and + Olle Engdegard: make histtype='step' unfilled by default + and introduce histtype='stepfilled'; use default color + cycle; introduce reverse cumulative histogram; new align + keyword - MM + 2008-06-06 Fix closed polygon patch and also provide the option to not close the polygon - MGD Modified: trunk/matplotlib/examples/pylab_examples/histogram_demo_extended.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/histogram_demo_extended.py 2008-06-06 12:57:24 UTC (rev 5410) +++ trunk/matplotlib/examples/pylab_examples/histogram_demo_extended.py 2008-06-06 16:34:00 UTC (rev 5411) @@ -12,7 +12,7 @@ x = mu + sigma*P.randn(10000) # the histogram of the data with histtype='step' -n, bins, patches = P.hist(x, 50, normed=1, histtype='step') +n, bins, patches = P.hist(x, 50, normed=1, histtype='stepfilled') P.setp(patches, 'facecolor', 'g', 'alpha', 0.75) # add a line showing the expected distribution @@ -35,7 +35,6 @@ P.figure() n, bins, patches = P.hist(x, 50, normed=1, histtype='step', cumulative=True) -P.setp(patches, 'facecolor', 'b', 'alpha', 0.75) # add a line showing the expected distribution y = P.normpdf( bins, mu, sigma).cumsum() @@ -47,13 +46,17 @@ x = mu + sigma2*P.randn(10000) n, bins, patches = P.hist(x, bins=bins, normed=1, histtype='step', cumulative=True) -P.setp(patches, 'facecolor', 'r', 'alpha', 0.5) # add a line showing the expected distribution y = P.normpdf( bins, mu, sigma2).cumsum() y /= y[-1] l = P.plot(bins, y, 'r--', linewidth=1.5) +# finally overplot a reverted cumulative histogram +n, bins, patches = P.hist(x, bins=bins, normed=1, + histtype='step', cumulative=-1) + + P.grid(True) P.ylim(0, 1.05) Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-06-06 12:57:24 UTC (rev 5410) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-06-06 16:34:00 UTC (rev 5411) @@ -5634,7 +5634,7 @@ def hist(self, x, bins=10, normed=False, cumulative=False, - bottom=None, histtype='bar', align='edge', + bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, **kwargs): """ call signature:: @@ -5667,20 +5667,26 @@ cumulative: if True then a histogram is computed where each bin gives the counts in that bin plus all bins for smaller values. - The last bin gives the total number of datapoints. If normed is - also True then the histogram is normalized such that the last bin - equals one. + The last bin gives the total number of datapoints. If normed + is also True then the histogram is normalized such that the + last bin equals one. If cumulative evaluates to less that one + (e.g. -1), the direction of accumulation is reversed. In this + case, If normed is also True then the histogram is normalized + such that the first bin equals one. histtype: - [ 'bar' | 'barstacked' | 'step' ] The type of histogram - to draw. 'bar' is a traditional bar-type histogram, + [ 'bar' | 'barstacked' | 'step' | 'stepfilled' ] The type of + histogram to draw. 'bar' is a traditional bar-type histogram, 'barstacked' is a bar-type histogram where multiple data are - stacked on top of each other, and 'step' generates a lineplot. + stacked on top of each other. step' generates a lineplot that + is by default unfilled, and 'stepfilled' generates a lineplot + that this by default filled. align: - ['edge' | 'center' ] Controles how the histogram is plotted. - If 'edge', bars are centered between the bin edges. - If 'center', bars are centered on the left bin edges + ['left' | 'mid' | 'right' ] Controles how the histogram is + plotted. If 'left', bars are centered on the left bin edges. + If 'mid', bars are centered between the bin edges. If 'right', + bars are centered on the right bin edges. orientation: [ 'horizontal' | 'vertical' ] If horizontal, barh will be used @@ -5716,7 +5722,6 @@ warnings.warn('2D hist should be nsamples x nvariables; this looks transposed') if len(x.shape)==2: - n = [] for i in xrange(x.shape[1]): # this will automatically overwrite bins, @@ -5730,13 +5735,16 @@ n = [n,] if cumulative: + slc = slice(None) + if cbook.is_numlike(cumulative): + if cumulative < 0: + slc = slice(None,None,-1) + if normed: - n = [(m * np.diff(bins)).cumsum() for m in n] + n = [(m * np.diff(bins))[slc].cumsum()[slc] for m in n] else: - n = [m.cumsum() for m in n] + n = [m[slc].cumsum()[slc] for m in n] - ccount = 0 - colors = _process_plot_var_args.defaultColors[:] patches = [] if histtype.startswith('bar'): @@ -5763,14 +5771,16 @@ else: raise ValueError, 'invalid histtype: %s' % histtype - if align=='edge': + if align == 'mid' or align == 'edge': boffset += 0.5*totwidth - elif align != 'center': + elif align == 'right': + boffset += totwidth + elif align != 'left' and align != 'center': raise ValueError, 'invalid align: %s' % align if orientation == 'horizontal': for m in n: - color = colors[ccount % len(colors)] + color = self._get_lines._get_next_cycle_color() patch = self.barh(bins[:-1]+boffset, m, height=width, left=bottom, align='center', log=log, color=color) @@ -5779,10 +5789,9 @@ if bottom is None: bottom = 0.0 bottom += m boffset += dw - ccount += 1 elif orientation == 'vertical': for m in n: - color = colors[ccount % len(colors)] + color = self._get_lines._get_next_cycle_color() patch = self.bar(bins[:-1]+boffset, m, width=width, bottom=bottom, align='center', log=log, color=color) @@ -5791,19 +5800,20 @@ if bottom is None: bottom = 0.0 bottom += m boffset += dw - ccount += 1 else: raise ValueError, 'invalid orientation: %s' % orientation - elif histtype == 'step': + elif histtype.startswith('step'): x = np.zeros( 2*len(bins), np.float_ ) y = np.zeros( 2*len(bins), np.float_ ) x[0::2], x[1::2] = bins, bins - if align == 'center': + if align == 'left' or align == 'center': x -= 0.5*(bins[1]-bins[0]) - elif align != 'edge': + elif align == 'right': + x += 0.5*(bins[1]-bins[0]) + elif align != 'mid' and align != 'edge': raise ValueError, 'invalid align: %s' % align if log: @@ -5812,6 +5822,12 @@ self.set_xscale('log') elif orientation == 'vertical': self.set_yscale('log') + + fill = False + if histtype == 'stepfilled': + fill = True + elif histtype != 'step': + raise ValueError, 'invalid histtype: %s' % histtype for m in n: y[1:-1:2], y[2::2] = m, m @@ -5819,7 +5835,14 @@ x,y = y,x elif orientation != 'vertical': raise ValueError, 'invalid orientation: %s' % orientation - patches.append( self.fill(x,y,closed=False) ) + + color = self._get_lines._get_next_cycle_color() + if fill: + patches.append( self.fill(x, y, + closed=False, facecolor=color) ) + else: + patches.append( self.fill(x, y, + closed=False, edgecolor=color, fill=False) ) # adopted from adjust_x/ylim part of the bar method if orientation == 'horizontal': This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2008-06-08 01:23:25
|
Revision: 5419 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5419&view=rev Author: efiring Date: 2008-06-07 18:23:21 -0700 (Sat, 07 Jun 2008) Log Message: ----------- List backends only in rcsetup Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/tests/backend_driver.py trunk/matplotlib/lib/matplotlib/__init__.py trunk/matplotlib/lib/matplotlib/backends/__init__.py trunk/matplotlib/lib/matplotlib/rcsetup.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-07 21:51:26 UTC (rev 5418) +++ trunk/matplotlib/CHANGELOG 2008-06-08 01:23:21 UTC (rev 5419) @@ -1,4 +1,8 @@ -2008-06-06 hist() revision, applied ideas proposed by Erik Tollerud and +2008=06-07 Moved list of backends to rcsetup.py; made use of lower + case for backend names consistent; use validate_backend + when importing backends subpackage - EF + +2008-06-06 hist() revision, applied ideas proposed by Erik Tollerud and Olle Engdegard: make histtype='step' unfilled by default and introduce histtype='stepfilled'; use default color cycle; introduce reverse cumulative histogram; new align Modified: trunk/matplotlib/examples/tests/backend_driver.py =================================================================== --- trunk/matplotlib/examples/tests/backend_driver.py 2008-06-07 21:51:26 UTC (rev 5418) +++ trunk/matplotlib/examples/tests/backend_driver.py 2008-06-08 01:23:21 UTC (rev 5419) @@ -17,9 +17,10 @@ from __future__ import division import os, time, sys, glob -import matplotlib.backends as mplbe -all_backends = [b.lower() for b in mplbe.all_backends] +import matplotlib.rcsetup as rcsetup + +all_backends = list(rcsetup.all_backends) # to leave the original list alone all_backends.extend(['cairo.png', 'cairo.ps', 'cairo.pdf', 'cairo.svg']) pylab_dir = os.path.join('..', 'pylab_examples') @@ -189,7 +190,7 @@ line_lstrip.startswith('show')): continue tmpfile.write(line) - if backend in mplbe.interactive_bk: + if backend in rcsetup.interactive_bk: tmpfile.write('show()') else: tmpfile.write('savefig("%s", dpi=150)' % outfile) @@ -205,12 +206,13 @@ if __name__ == '__main__': times = {} - default_backends = ['Agg', 'PS', 'SVG', 'PDF', 'Template'] + default_backends = ['agg', 'ps', 'svg', 'pdf', 'template'] if len(sys.argv)==2 and sys.argv[1]=='--clean': localdirs = [d for d in glob.glob('*') if os.path.isdir(d)] all_backends_set = set(all_backends) for d in localdirs: - if d.lower() not in all_backends_set: continue + if d.lower() not in all_backends_set: + continue print 'removing %s'%d for fname in glob.glob(os.path.join(d, '*')): os.remove(fname) Modified: trunk/matplotlib/lib/matplotlib/__init__.py =================================================================== --- trunk/matplotlib/lib/matplotlib/__init__.py 2008-06-07 21:51:26 UTC (rev 5418) +++ trunk/matplotlib/lib/matplotlib/__init__.py 2008-06-08 01:23:21 UTC (rev 5419) @@ -763,14 +763,15 @@ """ if 'matplotlib.backends' in sys.modules: if warn: warnings.warn(_use_error_msg) + arg = arg.lower() be_parts = arg.split('.') name = validate_backend(be_parts[0]) rcParams['backend'] = name - if name == 'Cairo' and len(be_parts) > 1: + if name == 'cairo' and len(be_parts) > 1: rcParams['cairo.format'] = validate_cairo_format(be_parts[1]) def get_backend(): - return rcParams['backend'] + return rcParams['backend'].lower() def interactive(b): """ Modified: trunk/matplotlib/lib/matplotlib/backends/__init__.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/__init__.py 2008-06-07 21:51:26 UTC (rev 5418) +++ trunk/matplotlib/lib/matplotlib/backends/__init__.py 2008-06-08 01:23:21 UTC (rev 5419) @@ -1,25 +1,19 @@ -import sys + import matplotlib -import time +from matplotlib.rcsetup import interactive_bk +from matplotlib.rcsetup import validate_backend __all__ = ['backend','show','draw_if_interactive', 'new_figure_manager', 'backend_version'] -interactive_bk = ['GTK', 'GTKAgg', 'GTKCairo', 'FltkAgg', 'QtAgg', 'Qt4Agg', - 'TkAgg', 'WX', 'WXAgg', 'CocoaAgg'] -non_interactive_bk = ['Agg2', 'Agg', 'Cairo', 'EMF', 'GDK', - 'Pdf', 'PS', 'SVG', 'Template'] -all_backends = interactive_bk + non_interactive_bk +backend = matplotlib.get_backend() # makes sure it is lower case +validate_backend(backend) -backend = matplotlib.get_backend() -if backend not in all_backends: - raise ValueError, 'Unrecognized backend %s' % backend - def pylab_setup(): 'return new_figure_manager, draw_if_interactive and show for pylab' # Import the requested backend into a generic module object - backend_name = 'backend_'+backend.lower() + backend_name = 'backend_'+backend backend_mod = __import__('matplotlib.backends.'+backend_name, globals(),locals(),[backend_name]) @@ -42,7 +36,7 @@ # Additional imports which only happen for certain backends. This section # should probably disappear once all backends are uniform. - if backend in ['WX','WXAgg']: + if backend in ['wx','wxagg']: Toolbar = backend_mod.Toolbar __all__.append('Toolbar') Modified: trunk/matplotlib/lib/matplotlib/rcsetup.py =================================================================== --- trunk/matplotlib/lib/matplotlib/rcsetup.py 2008-06-07 21:51:26 UTC (rev 5418) +++ trunk/matplotlib/lib/matplotlib/rcsetup.py 2008-06-08 01:23:21 UTC (rev 5419) @@ -12,6 +12,13 @@ from matplotlib.fontconfig_pattern import parse_fontconfig_pattern from matplotlib.colors import is_color_like +interactive_bk = ['GTK', 'GTKAgg', 'GTKCairo', 'FltkAgg', 'QtAgg', 'Qt4Agg', + 'TkAgg', 'WX', 'WXAgg', 'CocoaAgg'] +non_interactive_bk = ['Agg', 'Cairo', 'EMF', 'GDK', + 'Pdf', 'PS', 'SVG', 'Template'] +all_backends = interactive_bk + non_interactive_bk + + class ValidateInStrings: def __init__(self, key, valid, ignorecase=False): 'valid is a list of legal strings' @@ -80,11 +87,7 @@ raise ValueError('Supported Postscript/PDF font types are %s' % fonttypes.values()) return fonttype -validate_backend = ValidateInStrings('backend',[ - 'Agg2', 'Agg', 'Aqt', 'Cairo', 'CocoaAgg', 'EMF', 'GD', 'GDK', - 'GTK', 'GTKAgg', 'GTKCairo', 'FltkAgg', 'Paint', 'Pdf', 'PS', - 'QtAgg', 'Qt4Agg', 'SVG', 'Template', 'TkAgg', 'WX', 'WXAgg', - ], ignorecase=True) +validate_backend = ValidateInStrings('backend', all_backends, ignorecase=True) validate_numerix = ValidateInStrings('numerix',[ 'Numeric','numarray','numpy', This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ds...@us...> - 2008-06-08 18:02:08
|
Revision: 5423 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5423&view=rev Author: dsdale Date: 2008-06-08 11:01:58 -0700 (Sun, 08 Jun 2008) Log Message: ----------- added documentation for usetex added a static_figs directory for scripts that require optional features to generate images for the documentation Modified Paths: -------------- trunk/matplotlib/doc/devel/outline.rst trunk/matplotlib/doc/faq/index.rst trunk/matplotlib/doc/faq/installing_faq.rst trunk/matplotlib/doc/static_figs/README trunk/matplotlib/doc/users/figures/make.py trunk/matplotlib/doc/users/index.rst trunk/matplotlib/examples/pylab_examples/tex_demo.py trunk/matplotlib/examples/pylab_examples/tex_unicode_demo.py Added Paths: ----------- trunk/matplotlib/doc/_static/tex_demo.png trunk/matplotlib/doc/_static/tex_unicode_demo.png trunk/matplotlib/doc/faq/environment_variables_faq.rst trunk/matplotlib/doc/static_figs/make.py trunk/matplotlib/doc/static_figs/tex_demo.png trunk/matplotlib/doc/static_figs/tex_demo.py trunk/matplotlib/doc/static_figs/tex_unicode_demo.py trunk/matplotlib/doc/users/usetex.rst Added: trunk/matplotlib/doc/_static/tex_demo.png =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/doc/_static/tex_demo.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/matplotlib/doc/_static/tex_unicode_demo.png =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/doc/_static/tex_unicode_demo.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Modified: trunk/matplotlib/doc/devel/outline.rst =================================================================== --- trunk/matplotlib/doc/devel/outline.rst 2008-06-08 02:25:39 UTC (rev 5422) +++ trunk/matplotlib/doc/devel/outline.rst 2008-06-08 18:01:58 UTC (rev 5423) @@ -32,7 +32,7 @@ mathtext Michael ? submitted John fonts et al Michael ? no author Darren pyplot tut John submitted Eric ? -usetex Darren has author ? +usetex Darren submitted ? configuration Darren preliminary ? colormapping Perry ? no author Eric ? win32 install Charlie ? no author Darren @@ -64,8 +64,7 @@ the artist John has author ? transforms Michael submitted John documenting mpl Darren submitted ? -coding guide John submitted Eric (Darren -suggests)? +coding guide John submitted Eric ? and_much_more ? ? ? =============================== ==================== =========== =================== Added: trunk/matplotlib/doc/faq/environment_variables_faq.rst =================================================================== --- trunk/matplotlib/doc/faq/environment_variables_faq.rst (rev 0) +++ trunk/matplotlib/doc/faq/environment_variables_faq.rst 2008-06-08 18:01:58 UTC (rev 5423) @@ -0,0 +1,28 @@ +.. _environment-variables: + +********************* +Environment Variables +********************* + +====================== ======================================================= +Environment Variable Description +====================== ======================================================= +.. envvar:: PATH The list of directories searched to find executable + programs +.. envvar:: PYTHONPATH The list of directories that is searched to find Python + packages and modules +====================== ======================================================= + + + + +Setting Environment Variables +============================= + +Linux/OS-X +---------- + + + +Windows +------- Modified: trunk/matplotlib/doc/faq/index.rst =================================================================== --- trunk/matplotlib/doc/faq/index.rst 2008-06-08 02:25:39 UTC (rev 5422) +++ trunk/matplotlib/doc/faq/index.rst 2008-06-08 18:01:58 UTC (rev 5423) @@ -14,4 +14,4 @@ installing_faq.rst troubleshooting_faq.rst howto_faq.rst - + environment_variables_faq.rst Modified: trunk/matplotlib/doc/faq/installing_faq.rst =================================================================== --- trunk/matplotlib/doc/faq/installing_faq.rst 2008-06-08 02:25:39 UTC (rev 5422) +++ trunk/matplotlib/doc/faq/installing_faq.rst 2008-06-08 18:01:58 UTC (rev 5423) @@ -1,8 +1,8 @@ .. _installing-faq: -================== +****************** Installation FAQ -================== +****************** How do I report a compilation problem? ====================================== Modified: trunk/matplotlib/doc/static_figs/README =================================================================== --- trunk/matplotlib/doc/static_figs/README 2008-06-08 02:25:39 UTC (rev 5422) +++ trunk/matplotlib/doc/static_figs/README 2008-06-08 18:01:58 UTC (rev 5423) @@ -1,4 +1,9 @@ -Scripts that require optional system configurations to generate scripts should go here. The -figures will be generated in doc/_static, and will be named based on the name of the script, -so we can avoid unintentionally overwriting any existing figures. Please add a line to this -file for any additional requirements necessary to generate a new figure. +Scripts that require optional system configurations to generate scripts should +go here. The figures will be generated in doc/_static, and will be named based +on the name of the script, so we can avoid unintentionally overwriting any +existing figures. Please add a line to this file for any additional +requirements necessary to generate a new figure. + +tex demos: + latex + dvipng Added: trunk/matplotlib/doc/static_figs/make.py =================================================================== --- trunk/matplotlib/doc/static_figs/make.py (rev 0) +++ trunk/matplotlib/doc/static_figs/make.py 2008-06-08 18:01:58 UTC (rev 5423) @@ -0,0 +1,58 @@ +#!/usr/bin/env python +import sys, os, glob +import matplotlib +import IPython.Shell +matplotlib.rcdefaults() +matplotlib.use('Agg') + +mplshell = IPython.Shell.MatplotlibShell('mpl') + +def figs(): + print 'making figs' + import matplotlib.pyplot as plt + for fname in glob.glob('*.py'): + if fname.split('/')[-1] == __file__.split('/')[-1]: continue + basename, ext = os.path.splitext(fname) + outfile = '../_static/%s.png'%basename + + if os.path.exists(outfile): + print ' already have %s'%outfile + continue + else: + print ' building %s'%fname + plt.close('all') # we need to clear between runs + mplshell.magic_run(basename) + plt.savefig(outfile) + print 'all figures made' + + +def clean(): + patterns = ['#*', '*~', '*.png', '*pyc'] + for pattern in patterns: + for fname in glob.glob(pattern): + os.remove(fname) + print 'all clean' + + + +def all(): + figs() + +funcd = {'figs':figs, + 'clean':clean, + 'all':all, + } + +if len(sys.argv)>1: + for arg in sys.argv[1:]: + func = funcd.get(arg) + if func is None: + raise SystemExit('Do not know how to handle %s; valid args are'%( + arg, funcd.keys())) + func() +else: + all() + + + + Property changes on: trunk/matplotlib/doc/static_figs/make.py ___________________________________________________________________ Name: svn:executable + * Added: trunk/matplotlib/doc/static_figs/tex_demo.png =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/doc/static_figs/tex_demo.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/matplotlib/doc/static_figs/tex_demo.py =================================================================== --- trunk/matplotlib/doc/static_figs/tex_demo.py (rev 0) +++ trunk/matplotlib/doc/static_figs/tex_demo.py 2008-06-08 18:01:58 UTC (rev 5423) @@ -0,0 +1 @@ +link ../mpl_examples/pylab_examples/tex_demo.py \ No newline at end of file Property changes on: trunk/matplotlib/doc/static_figs/tex_demo.py ___________________________________________________________________ Name: svn:special + * Added: trunk/matplotlib/doc/static_figs/tex_unicode_demo.py =================================================================== --- trunk/matplotlib/doc/static_figs/tex_unicode_demo.py (rev 0) +++ trunk/matplotlib/doc/static_figs/tex_unicode_demo.py 2008-06-08 18:01:58 UTC (rev 5423) @@ -0,0 +1 @@ +link ../mpl_examples/pylab_examples/tex_unicode_demo.py \ No newline at end of file Property changes on: trunk/matplotlib/doc/static_figs/tex_unicode_demo.py ___________________________________________________________________ Name: svn:special + * Modified: trunk/matplotlib/doc/users/figures/make.py =================================================================== --- trunk/matplotlib/doc/users/figures/make.py 2008-06-08 02:25:39 UTC (rev 5422) +++ trunk/matplotlib/doc/users/figures/make.py 2008-06-08 18:01:58 UTC (rev 5423) @@ -22,7 +22,7 @@ print ' building %s'%fname plt.close('all') # we need to clear between runs mplshell.magic_run(basename) - plt.savefig('%s.png'%basename) + plt.savefig(outfile) print 'all figures made' Modified: trunk/matplotlib/doc/users/index.rst =================================================================== --- trunk/matplotlib/doc/users/index.rst 2008-06-08 02:25:39 UTC (rev 5422) +++ trunk/matplotlib/doc/users/index.rst 2008-06-08 18:01:58 UTC (rev 5423) @@ -16,5 +16,6 @@ customizing.rst artists.rst event_handling.rst + usetex.rst Added: trunk/matplotlib/doc/users/usetex.rst =================================================================== --- trunk/matplotlib/doc/users/usetex.rst (rev 0) +++ trunk/matplotlib/doc/users/usetex.rst 2008-06-08 18:01:58 UTC (rev 5423) @@ -0,0 +1,129 @@ +.. _usetex-tutorial: + +************************* +Text Rendering With LaTeX +************************* + +Matplotlib has the option to use LaTeX to manage all text layout. This +option is available with the following backends: + +* \*Agg +* PS +* PDF + +The LaTeX option is activated by setting text.usetex : true in your rc +settings. Text handling with matplotlib's LaTeX support is slower than +matplotlib's very capable :ref:`mathtext <mathtext-tutorial>`, but is more +flexible, since different LaTeX packages (font packages, math packages, etc.) +can be used. The results can be striking, especially when you take care to use +the same fonts in your figures as in the main document. + +Matplotlib's LaTeX support requires a working LaTeX_ installation, dvipng_ +(which may be included with your LaTeX installation), and Ghostscript_ +(GPL Ghostscript 8.60 or later is recommended). The executables for these +external dependencies must all be located on your :envvar:`PATH`. + +There are a couple of options to mention, which can be changed using :ref:`rc +settings <customizing-matplotlib>`. Here is an example matplotlibrc file:: + + font.family : serif + font.serif : Times, Palatino, New Century Schoolbook, Bookman, Computer Modern Roman + font.sans-serif : Helvetica, Avant Garde, Computer Modern Sans serif + font.cursive : Zapf Chancery + font.monospace : Courier, Computer Modern Typewriter + + text.usetex : true + +The first valid font in each family is the one that will be loaded. If the +fonts are not specified, the Computer Modern fonts are used by default. All of +the other fonts are Adobe fonts. Times and Palatino each have their own +accompanying math fonts, while the other Adobe serif fonts make use of the +Computer Modern math fonts. See the PSNFSS_ documentation for more details. + +To use LaTeX and select Helvetica as the default font, without editing +matplotlibrc use:: + + from matplotlib import rc + rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']}) + ## for Palatino and other serif fonts use: + #rc('font',**{'family':'serif','serif':['Palatino'])) + rc('text', usetex=True) + +Here is the standard example, `tex_demo.py`: + + .. literalinclude:: ../mpl_examples/pylab_examples/tex_demo.py + +.. image:: ../_static/tex_demo.png + +Note that display math mode (``$$ e=mc^2 $$``) is not supported, but adding the +command ``\displaystyle``, as in `tex_demo.py`, will produce the same +results. + +It is also possible to use unicode strings with the LaTeX text manager, here is +an example taken from `tex_unicode_demo.py`: + + .. literalinclude:: ../mpl_examples/pylab_examples/tex_unicode_demo.py + +.. image:: ../_static/tex_unicode_demo.png + +In order to produce encapsulated postscript files that can be embedded in a new +LaTeX document, the default behavior of matplotlib is to distill the output, +which removes some postscript operators used by LaTeX that are illegal in an +eps file. This step produces fonts which may be unacceptable to some users. One +workaround is to to set ``ps.distiller.res`` to a higher value (perhaps 6000) in +your rc settings. A better workaround, which requires Poppler_ or Xpdf_, can be +activated by changing the ``ps.usedistiller`` rc setting to ``xpdf``. This +alternative produces postscript with text that can be edited in Adobe +Illustrator, and searched text in pdf documents. + + += Possible Hangups = + + * On Windows, the PATH environment variable may need to be modified to find + the latex, dvipng and ghostscript executables. This is done by going to the + control panel, selecting the "system" icon, selecting the "advanced" tab, + and clicking the "environment variables" button (and people think Linux is + complicated. Sheesh.) Select the PATH variable, and add the appropriate + directories. + + * Using MiKTeX with Computer Modern fonts, if you get odd -Agg and PNG + results, go to MiKTeX/Options and update your format files + + * The fonts look terrible on screen. You are probably running Mac OS, and + there is some funny business with dvipng on the mac. Set text.dvipnghack : + True in your matplotlibrc file. + + * On Ubuntu and Gentoo, the base texlive install does not ship with the + type1cm package. You may need to install some of the extra packages to get + all the goodies that come bundled with other latex distributions. + + * Some progress has been made so Matplotlib uses the dvi files directly for + text layout. This allows latex to be used for text layout with the pdf and + svg backends, as well as the \*Agg and PS backends. In the future, a latex + installation may be the only external dependency. + += In the event that things dont work = + * Try deleting `tex.cache` from your :envvar:`MATPLOTLIBDATA` directory + + * Make sure LaTeX, dvipng and ghostscript are each working and on your PATH. + + * Make sure what you are trying to do is possible in a LaTeX document, that + your LaTeX syntax is valid and that you are using raw strings if necessary + to avoid unintended escape sequences. + + * Most problems reported on the mailing list have been cleared up by + upgrading Ghostscript_. If possible, please try upgrading to the latest + release before reporting problems to the list. + + * The text.latex.preample rc setting is not officially supported. This option + provides lots of flexibility, and lots of ways to cause problems. Please + disable this option before reporting problems to the mailing list. + + * If you still need help, please see :ref:`reporting-problems` + +.. _LaTeX: http://www.tug.org +.. _dvipng: http://sourceforge.net/projects/dvipng +.. _Ghostscript: http://www.cs.wisc.edu/~ghost/ +.. _PSNFSS: http://www.ctan.org/tex-archive/macros/latex/required/psnfss/psnfss2e.pdf +.. _Poppler: http://poppler.freedesktop.org/ +.. _Xpdf: http://www.foolabs.com/xpdf \ No newline at end of file Modified: trunk/matplotlib/examples/pylab_examples/tex_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/tex_demo.py 2008-06-08 02:25:39 UTC (rev 5422) +++ trunk/matplotlib/examples/pylab_examples/tex_demo.py 2008-06-08 18:01:58 UTC (rev 5423) @@ -17,7 +17,8 @@ rc('text', usetex=True) -figure(1) +rc('font', family='serif') +figure(1, figsize=(6,4)) ax = axes([0.1, 0.1, 0.8, 0.7]) t = arange(0.0, 1.0+0.01, 0.01) s = cos(2*2*pi*t)+2 Modified: trunk/matplotlib/examples/pylab_examples/tex_unicode_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/tex_unicode_demo.py 2008-06-08 02:25:39 UTC (rev 5422) +++ trunk/matplotlib/examples/pylab_examples/tex_unicode_demo.py 2008-06-08 18:01:58 UTC (rev 5423) @@ -11,14 +11,13 @@ from matplotlib.pyplot import figure, axes, plot, xlabel, ylabel, title, \ grid, savefig, show -figure(1) +figure(1, figsize=(6,4)) ax = axes([0.1, 0.1, 0.8, 0.7]) t = arange(0.0, 1.0+0.01, 0.01) s = cos(2*2*pi*t)+2 plot(t, s) xlabel(r'\textbf{time (s)}') -s = unicode(r'\textit{Velocity (\xB0/sec)}','latin-1') ylabel(unicode(r'\textit{Velocity (\xB0/sec)}','latin-1'),fontsize=16) title(r"\TeX\ is Number $\displaystyle\sum_{n=1}^\infty\frac{-e^{i\pi}}{2^n}$!", fontsize=16, color='r') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ds...@us...> - 2008-06-08 23:34:05
|
Revision: 5426 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5426&view=rev Author: dsdale Date: 2008-06-08 16:34:01 -0700 (Sun, 08 Jun 2008) Log Message: ----------- finish converting axes.py docstrings to ReST Modified Paths: -------------- trunk/matplotlib/doc/api/index.rst trunk/matplotlib/doc/api/pyplot_api.rst trunk/matplotlib/doc/faq/environment_variables_faq.rst trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/doc/api/index.rst =================================================================== --- trunk/matplotlib/doc/api/index.rst 2008-06-08 20:31:47 UTC (rev 5425) +++ trunk/matplotlib/doc/api/index.rst 2008-06-08 23:34:01 UTC (rev 5426) @@ -12,5 +12,6 @@ .. toctree:: artist_api.rst + axes_api.rst pyplot_api.rst Modified: trunk/matplotlib/doc/api/pyplot_api.rst =================================================================== --- trunk/matplotlib/doc/api/pyplot_api.rst 2008-06-08 20:31:47 UTC (rev 5425) +++ trunk/matplotlib/doc/api/pyplot_api.rst 2008-06-08 23:34:01 UTC (rev 5426) @@ -7,4 +7,5 @@ ============================= .. automodule:: matplotlib.pyplot - :members: \ No newline at end of file + :members: + :undoc-members: \ No newline at end of file Modified: trunk/matplotlib/doc/faq/environment_variables_faq.rst =================================================================== --- trunk/matplotlib/doc/faq/environment_variables_faq.rst 2008-06-08 20:31:47 UTC (rev 5425) +++ trunk/matplotlib/doc/faq/environment_variables_faq.rst 2008-06-08 23:34:01 UTC (rev 5426) @@ -4,18 +4,12 @@ Environment Variables ********************* -====================== ======================================================= -Environment Variable Description -====================== ======================================================= -.. envvar:: PATH The list of directories searched to find executable - programs -.. envvar:: PYTHONPATH The list of directories that is searched to find Python - packages and modules -====================== ======================================================= +.. envvar:: PATH: + The list of directories searched to find executable programs +.. envvar:: PYTHONPATH: + The list of directories that is searched to find Python packages and modules - - Setting Environment Variables ============================= Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-06-08 20:31:47 UTC (rev 5425) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-06-08 23:34:01 UTC (rev 5426) @@ -452,7 +452,6 @@ connect to are 'xlim_changed' and 'ylim_changed' and the callback will be called with func(ax) where ax is the Axes instance - """ name = "rectilinear" @@ -574,7 +573,7 @@ def set_figure(self, fig): """ - Set the Axes figure + Set the Axes' figure accepts a Figure instance """ @@ -926,24 +925,24 @@ adjustable: - ======== ============================ - value description - ======== ============================ - 'box' change physical size of axes - 'datalim' change xlim or ylim - ======== ============================ + ========= ============================ + value description + ========= ============================ + 'box' change physical size of axes + 'datalim' change xlim or ylim + ========= ============================ anchor: - ==== ===================== - value description - ==== ===================== - 'C' centered - 'SW' lower left corner - 'S' middle of bottom edge - 'SE' lower right corner + ===== ===================== + value description + ===== ===================== + 'C' centered + 'SW' lower left corner + 'S' middle of bottom edge + 'SE' lower right corner etc. - ==== ===================== + ===== ===================== """ if aspect in ('normal', 'auto'): @@ -963,7 +962,7 @@ def set_adjustable(self, adjustable): """ - ACCEPTS: ['box' | 'datalim'] + ACCEPTS: [ 'box' | 'datalim' ] """ if adjustable in ('box', 'datalim'): self._adjustable = adjustable @@ -1105,8 +1104,6 @@ #print 'New x0, x1:', x0, x1 #print 'New xsize, ysize/xsize', x1-x0, ysize/(x1-x0) - - def axis(self, *v, **kwargs): ''' Convenience method for manipulating the x and y view limits @@ -1165,7 +1162,6 @@ return v - def get_child_artists(self): """ Return a list of artists the axes contains. Deprecated @@ -1434,6 +1430,7 @@ self.set_position(new_position, 'active') #### Drawing + def draw(self, renderer=None, inframe=False): "Draw everything (plot lines, axes, labels)" if renderer is None: @@ -1551,7 +1548,7 @@ """ Set whether the axes rectangle patch is drawn - ACCEPTS: True|False + ACCEPTS: [ True | False ] """ self._frameon = b @@ -1565,7 +1562,7 @@ """ Set whether the axis ticks and gridlines are above or below most artists - ACCEPTS: True|False + ACCEPTS: [ True | False ] """ self._axisbelow = b @@ -1822,8 +1819,10 @@ def set_xticklabels(self, labels, fontdict=None, minor=False, **kwargs): """ - set_xticklabels(labels, fontdict=None, minor=False, **kwargs) + call signature:: + set_xticklabels(labels, fontdict=None, minor=False, **kwargs) + Set the xtick labels with list of strings labels Return a list of axis text instances. @@ -1884,21 +1883,26 @@ def set_ylim(self, ymin=None, ymax=None, emit=True, **kwargs): """ - set_ylim(self, *args, **kwargs): + call signature:: - Set the limits for the yaxis; v = [ymin, ymax] + set_ylim(self, *args, **kwargs): - set_ylim((valmin, valmax)) - set_ylim(valmin, valmax) - set_ylim(ymin=1) # ymax unchanged - set_ylim(ymax=1) # ymin unchanged + Set the limits for the yaxis; v = [ymin, ymax]:: - Valid kwargs: + set_ylim((valmin, valmax)) + set_ylim(valmin, valmax) + set_ylim(ymin=1) # ymax unchanged + set_ylim(ymax=1) # ymin unchanged - ymin : the min of the ylim - ymax : the max of the ylim - emit : notify observers of lim change + Keyword arguments: + ymin: scalar + the min of the ylim + ymax: scalar + the max of the ylim + emit: [ True | False ] + notify observers of lim change + Returns the current ylimits as a length 2 tuple ACCEPTS: len(2) sequence of floats @@ -1937,8 +1941,10 @@ def set_yscale(self, value, **kwargs): """ - SET_YSCALE(value) + call signature:: + set_yscale(value) + Set the scaling of the y-axis: %(scale)s ACCEPTS: [%(scale)s] @@ -1960,6 +1966,11 @@ Set the y ticks with list of ticks ACCEPTS: sequence of floats + + Keyword arguments: + + minor: [ False | True ] + Sets the minor ticks if True """ return self.yaxis.set_ticks(ticks, minor=minor) @@ -1977,8 +1988,10 @@ def set_yticklabels(self, labels, fontdict=None, minor=False, **kwargs): """ - set_yticklabels(labels, fontdict=None, minor=False, **kwargs) + call signature:: + set_yticklabels(labels, fontdict=None, minor=False, **kwargs) + Set the ytick labels with list of strings labels. Return a list of Text instances. @@ -2100,7 +2113,7 @@ """ Set whether the axes responds to navigation toolbar commands - ACCEPTS: True|False + ACCEPTS: [ True | False ] """ self._navigate = b @@ -2124,10 +2137,11 @@ x, y are the mouse coordinates in display coords. button is the mouse button number: - 1: LEFT - 2: MIDDLE - 3: RIGHT + * 1: LEFT + * 2: MIDDLE + * 3: RIGHT + Intended to be overridden by new projection types. """ self._pan_start = cbook.Bunch( @@ -2153,10 +2167,11 @@ Called when the mouse moves during a pan operation. button is the mouse button number: - 1: LEFT - 2: MIDDLE - 3: RIGHT + * 1: LEFT + * 2: MIDDLE + * 3: RIGHT + key is a "shift" key x, y are the mouse coordinates in display coords. @@ -2221,10 +2236,14 @@ def set_cursor_props(self, *args): """ - Set the cursor property as - ax.set_cursor_props(linewidth, color) OR - ax.set_cursor_props((linewidth, color)) + Set the cursor property as:: + ax.set_cursor_props(linewidth, color) + + or:: + + ax.set_cursor_props((linewidth, color)) + ACCEPTS: a (float, color) tuple """ if len(args)==1: @@ -2240,7 +2259,7 @@ """ Register observers to be notified when certain events occur. Register with callback functions with the following signatures. The function - has the following signature + has the following signature:: func(ax) # where ax is the instance making the callback. @@ -2365,8 +2384,6 @@ ds.sort() return ds[0][1] - - #### Labelling def get_title(self): @@ -2377,8 +2394,10 @@ def set_title(self, label, fontdict=None, **kwargs): """ - SET_TITLE(label, fontdict=None, **kwargs): + call signature:: + set_title(label, fontdict=None, **kwargs): + Set the title for the axes. See the text docstring for information of how override and the optional args work @@ -2409,8 +2428,10 @@ def set_xlabel(self, xlabel, fontdict=None, **kwargs): """ - SET_XLABEL(xlabel, fontdict=None, **kwargs) + call signature:: + set_xlabel(xlabel, fontdict=None, **kwargs) + Set the label for the xaxis. See the text docstring for information of how override and the optional args work. @@ -2435,8 +2456,10 @@ def set_ylabel(self, ylabel, fontdict=None, **kwargs): """ - SET_YLABEL(ylabel, fontdict=None, **kwargs) + call signature:: + set_ylabel(ylabel, fontdict=None, **kwargs) + Set the label for the yaxis See the text doctstring for information of how override and @@ -2535,13 +2558,10 @@ """ call signature:: - annotate(s, xy, - xytext=None, - xycoords='data', - textcoords='data', - arrowprops=None, - **props) + annotate(s, xy, xytext=None, xycoords='data', + textcoords='data', arrowprops=None, **kwargs) + Keyword arguments: %(Annotation)s """ a = mtext.Annotation(*args, **kwargs) @@ -2802,8 +2822,10 @@ def vlines(self, x, ymin, ymax, colors='k', linestyles='solid', label='', **kwargs): """ - VLINES(x, ymin, ymax, color='k') + call signature:: + vlines(x, ymin, ymax, color='k') + Plot vertical lines at each x from ymin to ymax. ymin or ymax can be scalars or len(x) numpy arrays. If they are scalars, then the respective values are constant, else the heights of the lines are @@ -2813,7 +2835,7 @@ colors is a line collections color args, either a single color or a len(x) list of colors - linestyle is one of solid|dashed|dashdot|dotted + linestyle is one of [ 'solid' | 'dashed' | 'dashdot' | 'dotted' ] Returns the collections.LineCollection that was added @@ -3199,8 +3221,11 @@ def xcorr(self, x, y, normed=False, detrend=mlab.detrend_none, usevlines=False, maxlags=None, **kwargs): """ - XCORR(x, y, normed=False, detrend=mlab.detrend_none, usevlines=False, \*\*kwargs): + call signature:: + xcorr(x, y, normed=False, detrend=mlab.detrend_none, + usevlines=False, **kwargs): + Plot the cross correlation between x and y. If normed=True, normalize the data but the cross correlation at 0-th lag. x and y are detrended by the detrend callable (default no @@ -3220,10 +3245,11 @@ to draw vertical lines from the origin to the acorr. Otherwise the plotstyle is determined by the kwargs, which are Line2D properties. If usevlines, the return value is lags, c, - linecol, b where linecol is the collections.LineCollection and b is the x-axis + linecol, b where linecol is the collections.LineCollection and b is the + x-axis - if usevlines=True, kwargs are passed onto Axes.vlines - if usevlines=False, kwargs are passed onto Axes.plot + if ``usevlines=True``, kwargs are passed onto Axes.vlines + if ``usevlines=False``, kwargs are passed onto Axes.plot maxlags is a positive integer detailing the number of lags to show. The default value of None will return all ``(2*len(x)-1)`` lags. @@ -3401,7 +3427,6 @@ self.legend_ = mlegend.Legend(self, handles, labels, **kwargs) return self.legend_ - #### Specialized plotting def step(self, x, y, *args, **kwargs): @@ -3959,9 +3984,6 @@ if autopct is None: return slices, texts else: return slices, texts, autotexts - - - def errorbar(self, x, y, yerr=None, xerr=None, fmt='-', ecolor=None, elinewidth=None, capsize=3, barsabove=False, lolims=False, uplims=False, @@ -4946,9 +4968,9 @@ self.autoscale_view() return patches fill.__doc__ = cbook.dedent(fill.__doc__) % martist.kwdocd + #### plotting z(x,y): imshow, pcolor and relatives, contour - def imshow(self, X, cmap=None, norm=None, aspect=None, interpolation=None, alpha=1.0, vmin=None, vmax=None, origin=None, extent=None, shape=None, filternorm=1, @@ -5384,15 +5406,15 @@ def pcolorfast(self, *args, **kwargs): """ + pseudocolor plot of a 2-D array + Experimental; this is a version of pcolor that does not draw lines, that provides the fastest possible rendering with the Agg backend, and that can handle any quadrilateral grid. - pcolor(*args, **kwargs): pseudocolor plot of a 2-D array + Call signatures:: - Function signatures - pcolor(C, **kwargs) pcolor(xr, yr, C, **kwargs) pcolor(x, y, C, **kwargs) @@ -5401,8 +5423,8 @@ C is the 2D array of color values corresponding to quadrilateral cells. Let (nr, nc) be its shape. C may be a masked array. - pcolor(C, **kwargs) is equivalent to - pcolor([0,nc], [0,nr], C, **kwargs) + ``pcolor(C, **kwargs)`` is equivalent to + ``pcolor([0,nc], [0,nr], C, **kwargs)`` xr, yr specify the ranges of x and y corresponding to the rectangular region bounding C. If xr = [x0, x1] and yr = [y0,y1] then @@ -5430,21 +5452,21 @@ and the row index corresponds to y; for details, see the "Grid Orientation" section below. - Optional keyword args are shown with their defaults below (you must - use kwargs for these): + Optional keyword arguments: - * cmap = cm.jet : a cm Colormap instance from cm + cmap: [ None | Colormap ] + A cm Colormap instance from cm. If None, use rc settings. + norm: [ None | Normalize ] + An mcolors.Normalize instance is used to scale luminance data to + 0,1. If None, defaults to normalize() + vmin/vmax: [ None | scalar ] + vmin and vmax are used in conjunction with norm to normalize + luminance data. If either are None, the min and max of the color + array C is used. If you pass a norm instance, vmin and vmax will + be None. + alpha: 0 <= scalar <= 1 + the alpha blending value - * norm = Normalize() : mcolors.Normalize instance - is used to scale luminance data to 0,1. - - * vmin=None and vmax=None : vmin and vmax are used in conjunction - with norm to normalize luminance data. If either are None, the - min and max of the color array C is used. If you pass a norm - instance, vmin and vmax will be None - - * alpha=1.0 : the alpha blending value - Return value is an image if a regular or rectangular grid is specified, and a QuadMesh collection in the general quadrilateral case. @@ -5567,12 +5589,14 @@ def table(self, **kwargs): """ - TABLE(cellText=None, cellColours=None, - cellLoc='right', colWidths=None, - rowLabels=None, rowColours=None, rowLoc='left', - colLabels=None, colColours=None, colLoc='center', - loc='bottom', bbox=None): + call signature:: + table(cellText=None, cellColours=None, + cellLoc='right', colWidths=None, + rowLabels=None, rowColours=None, rowLoc='left', + colLabels=None, colColours=None, colLoc='center', + loc='bottom', bbox=None): + Add a table to the current axes. Returns a table instance. For finer grained control over tables, use the Table class and add it to the axes with add_table. @@ -5587,8 +5611,10 @@ def twinx(self): """ - ax = twinx() + call signature:: + ax = twinx() + create a twin of Axes for generating a plot with a sharex x-axis but independent y axis. The y-axis of self will have ticks on left and the returned axes will have ticks on the @@ -5604,8 +5630,10 @@ def twiny(self): """ - ax = twiny() + call signature:: + ax = twiny() + create a twin of Axes for generating a plot with a shared y-axis but independent x axis. The x-axis of self will have ticks on bottom and the returned axes will have ticks on the @@ -5619,10 +5647,8 @@ self.xaxis.tick_bottom() return ax2 - #### Data analysis - def hist(self, x, bins=10, normed=False, cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, **kwargs): @@ -6238,13 +6264,13 @@ fig is a figure instance args is numRows, numCols, plotNum - where the array of subplots in the figure has dimensions - numRows, numCols, and where plotNum is the number of the - subplot being created. plotNum starts at 1 in the upper - right corner and increases to the right. + where the array of subplots in the figure has dimensions + numRows, numCols, and where plotNum is the number of the + subplot being created. plotNum starts at 1 in the upper + right corner and increases to the right. - If numRows<=numCols<=plotNum<10, args can be the decimal - integer numRows*100 + numCols*10 + plotNum. + If numRows<=numCols<=plotNum<10, args can be the decimal + integer numRows*100 + numCols*10 + plotNum. """ self.figure = fig This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mme...@us...> - 2008-06-09 12:13:49
|
Revision: 5430 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5430&view=rev Author: mmetz_bn Date: 2008-06-09 05:13:20 -0700 (Mon, 09 Jun 2008) Log Message: ----------- Added range keyword arg to hist() Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-09 07:22:56 UTC (rev 5429) +++ trunk/matplotlib/CHANGELOG 2008-06-09 12:13:20 UTC (rev 5430) @@ -1,4 +1,6 @@ -2008=06-07 Moved list of backends to rcsetup.py; made use of lower +2008-06-09 Added range keyword arg to hist() - MM + +2008-06-07 Moved list of backends to rcsetup.py; made use of lower case for backend names consistent; use validate_backend when importing backends subpackage - EF Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-06-09 07:22:56 UTC (rev 5429) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-06-09 12:13:20 UTC (rev 5430) @@ -5649,7 +5649,7 @@ #### Data analysis - def hist(self, x, bins=10, normed=False, cumulative=False, + def hist(self, x, bins=10, range=None, normed=False, cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, **kwargs): """ @@ -5669,6 +5669,10 @@ either an integer number of bins or a sequence giving the bins. x are the data to be binned. x can be an array or a 2D array with multiple data in its columns. + + range: + The lower and upper range of the bins. Lower and upper outliers + are ignored. If not provided, range is (x.min(), x.max()). normed: if True, the first element of the return tuple will @@ -5742,11 +5746,11 @@ for i in xrange(x.shape[1]): # this will automatically overwrite bins, # so that each histogram uses the same bins - m, bins = np.histogram(x[:,i], bins, range=None, + m, bins = np.histogram(x[:,i], bins, range=range, normed=bool(normed), new=True) n.append(m) else: - n, bins = np.histogram(x, bins, range=None, + n, bins = np.histogram(x, bins, range=range, normed=bool(normed), new=True) n = [n,] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ds...@us...> - 2008-06-09 15:59:50
|
Revision: 5431 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5431&view=rev Author: dsdale Date: 2008-06-09 08:58:45 -0700 (Mon, 09 Jun 2008) Log Message: ----------- dont install enthought.traits Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/artist.py trunk/matplotlib/setup.cfg.template trunk/matplotlib/setupext.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-09 12:13:20 UTC (rev 5430) +++ trunk/matplotlib/CHANGELOG 2008-06-09 15:58:45 UTC (rev 5431) @@ -1,3 +1,8 @@ +2008-06-09 Don't install Enthought.Traits along with matplotlib. For + matplotlib developers convenience, it can still be + installed by setting an option in setup.cfg while we figure + decide if there is a future for the traited config - DSD + 2008-06-09 Added range keyword arg to hist() - MM 2008-06-07 Moved list of backends to rcsetup.py; made use of lower Modified: trunk/matplotlib/lib/matplotlib/artist.py =================================================================== --- trunk/matplotlib/lib/matplotlib/artist.py 2008-06-09 12:13:20 UTC (rev 5430) +++ trunk/matplotlib/lib/matplotlib/artist.py 2008-06-09 15:58:45 UTC (rev 5431) @@ -179,7 +179,7 @@ def set_contains(self,picker): """Replace the contains test used by this artist. The new picker should be a callable function which determines whether the artist is hit by the - mouse event: + mouse event:: hit, props = picker(artist, mouseevent) Modified: trunk/matplotlib/setup.cfg.template =================================================================== --- trunk/matplotlib/setup.cfg.template 2008-06-09 12:13:20 UTC (rev 5430) +++ trunk/matplotlib/setup.cfg.template 2008-06-09 15:58:45 UTC (rev 5431) @@ -25,7 +25,8 @@ #pytz = False #dateutil = False # -## Experimental config package support: +## Experimental config package support, this should only be enabled by +## matplotlib developers, for matplotlib development #enthought.traits = False #configobj = False Modified: trunk/matplotlib/setupext.py =================================================================== --- trunk/matplotlib/setupext.py 2008-06-09 12:13:20 UTC (rev 5430) +++ trunk/matplotlib/setupext.py 2008-06-09 15:58:45 UTC (rev 5431) @@ -106,7 +106,7 @@ 'provide_pytz': 'auto', 'provide_dateutil': 'auto', 'provide_configobj': 'auto', - 'provide_traits': 'auto', + 'provide_traits': False, 'build_agg': True, 'build_gtk': 'auto', 'build_gtkagg': 'auto', @@ -141,7 +141,7 @@ try: options['provide_traits'] = config.getboolean("provide_packages", "enthought.traits") - except: options['provide_traits'] = 'auto' + except: options['provide_traits'] = False try: options['build_gtk'] = config.getboolean("gui_support", "gtk") except: options['build_gtk'] = 'auto' @@ -462,9 +462,11 @@ return False def check_provide_traits(): - if options['provide_traits'] is True: - print_status("enthought.traits", "matplotlib will provide") - return True + # Let's not install traits by default for now, unless it is specifically + # asked for in setup.cfg AND it is not already installed +# if options['provide_traits'] is True: +# print_status("enthought.traits", "matplotlib will provide") +# return True try: from enthought import traits try: @@ -478,12 +480,16 @@ version = version.version except AttributeError: version = version.__version__ - if version.endswith('mpl'): - print_status("enthought.traits", "matplotlib will provide") - return True - else: - print_status("enthought.traits", version) - return False + # next 2 lines added temporarily while we figure out what to do + # with traits: + print_status("enthought.traits", version) + return False +# if version.endswith('mpl'): +# print_status("enthought.traits", "matplotlib will provide") +# return True +# else: +# print_status("enthought.traits", version) +# return False except ImportError: if options['provide_traits']: print_status("enthought.traits", "matplotlib will provide") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-06-09 17:01:21
|
Revision: 5433 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5433&view=rev Author: jdh2358 Date: 2008-06-09 10:00:08 -0700 (Mon, 09 Jun 2008) Log Message: ----------- applied gregors agg resample patch Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/api/artist_api.rst trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/image.py trunk/matplotlib/lib/matplotlib/mlab.py trunk/matplotlib/lib/matplotlib/patches.py trunk/matplotlib/lib/matplotlib/rcsetup.py trunk/matplotlib/src/_image.cpp trunk/matplotlib/src/_image.h Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-09 16:48:50 UTC (rev 5432) +++ trunk/matplotlib/CHANGELOG 2008-06-09 17:00:08 UTC (rev 5433) @@ -1,3 +1,7 @@ +2008-06-09 Committed Gregor's image resample patch to downsampling + images with new rcparam image.resample - JDH + + 2008-06-09 Don't install Enthought.Traits along with matplotlib. For matplotlib developers convenience, it can still be installed by setting an option in setup.cfg while we figure @@ -3,4 +7,5 @@ decide if there is a future for the traited config - DSD + 2008-06-09 Added range keyword arg to hist() - MM Modified: trunk/matplotlib/doc/api/artist_api.rst =================================================================== --- trunk/matplotlib/doc/api/artist_api.rst 2008-06-09 16:48:50 UTC (rev 5432) +++ trunk/matplotlib/doc/api/artist_api.rst 2008-06-09 17:00:08 UTC (rev 5433) @@ -1,6 +1,6 @@ -****************** +******************* matplotlib artists -****************** +******************* :mod:`matplotlib.artist` ============================= Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-06-09 16:48:50 UTC (rev 5432) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-06-09 17:00:08 UTC (rev 5433) @@ -4974,7 +4974,7 @@ def imshow(self, X, cmap=None, norm=None, aspect=None, interpolation=None, alpha=1.0, vmin=None, vmax=None, origin=None, extent=None, shape=None, filternorm=1, - filterrad=4.0, imlim=None, **kwargs): + filterrad=4.0, imlim=None, resample=None, **kwargs): """ call signature:: @@ -5061,7 +5061,7 @@ self.set_aspect(aspect) im = mimage.AxesImage(self, cmap, norm, interpolation, origin, extent, filternorm=filternorm, - filterrad=filterrad, **kwargs) + filterrad=filterrad, resample=resample, **kwargs) im.set_data(X) im.set_alpha(alpha) @@ -5666,9 +5666,13 @@ Keyword arguments: bins: + either an integer number of bins or a sequence giving the - bins. x are the data to be binned. x can be an array or a 2D - array with multiple data in its columns. + bins. x are the data to be binned. x can be an array or a + 2D array with multiple data in its columns. Note, if bins + is an integer input argument=numbins, numbins+1 bin edges + will be returned, compatabile with the semantics of + np.histogram with the new=True argument. range: The lower and upper range of the bins. Lower and upper outliers @@ -5726,6 +5730,45 @@ kwargs are used to update the properties of the hist Rectangles: %(Rectangle)s + + + Here is an example which generates a histogram of normally + distributed random numbers and plot the analytic PDF over it:: + + + import numpy as np + import matplotlib.pyplot as plt + import matplotlib.mlab as mlab + + mu, sigma = 100, 15 + x = mu + sigma * np.random.randn(10000) + + fig = plt.figure() + ax = fig.add_subplot(111) + + # the histogram of the data + n, bins, patches = ax.hist(x, 50, normed=1, facecolor='green', alpha=0.75) + + # hist uses np.histogram under the hood to create 'n' and 'bins'. + # np.histogram returns the bin edges, so there will be 50 probability + # density values in n, 51 bin edges in bins and 50 patches. To get + # everything lined up, we'll compute the bin centers + bincenters = 0.5*(bins[1:]+bins[:-1]) + + # add a 'best fit' line for the normal PDF + y = mlab.normpdf( bincenters, mu, sigma) + l = ax.plot(bincenters, y, 'r--', linewidth=1) + + ax.set_xlabel('Smarts') + ax.set_ylabel('Probability') + ax.set_title(r'$\mathrm{Histogram\ of\ IQ:}\ \mu=100,\ \sigma=15$') + ax.set_xlim(40, 160) + ax.set_ylim(0, 0.03) + ax.grid(True) + + #fig.savefig('histogram_demo',dpi=72) + plt.show() + """ if not self._hold: self.cla() Modified: trunk/matplotlib/lib/matplotlib/image.py =================================================================== --- trunk/matplotlib/lib/matplotlib/image.py 2008-06-09 16:48:50 UTC (rev 5432) +++ trunk/matplotlib/lib/matplotlib/image.py 2008-06-09 17:00:08 UTC (rev 5433) @@ -57,6 +57,7 @@ extent=None, filternorm=1, filterrad=4.0, + resample = False, **kwargs ): @@ -86,6 +87,7 @@ self.set_interpolation(interpolation) + self.set_resample(resample) self.axes = ax @@ -200,6 +202,7 @@ im.set_interpolation(self._interpd[self._interpolation]) + im.set_resample(self._resample) # the viewport translation tx = (xmin-self.axes.viewLim.x0)/dxintv * numcols @@ -325,6 +328,13 @@ raise ValueError('Illegal interpolation string') self._interpolation = s + def set_resample(self, v): + if v is None: v = rcParams['image.resample'] + self._resample = v + + def get_interpolation(self): + return self._resample + def get_extent(self): 'get the image extent: left, right, bottom, top' if self._extent is not None: Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2008-06-09 16:48:50 UTC (rev 5432) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2008-06-09 17:00:08 UTC (rev 5433) @@ -716,7 +716,7 @@ def normpdf(x, *args): "Return the normal pdf evaluated at x; args provides mu, sigma" mu, sigma = args - return 1/(np.sqrt(2*np.pi)*sigma)*np.exp(-0.5 * (1/sigma*(x - mu))**2) + return 1./(np.sqrt(2*np.pi)*sigma)*np.exp(-0.5 * (1./sigma*(x - mu))**2) def levypdf(x, gamma, alpha): Modified: trunk/matplotlib/lib/matplotlib/patches.py =================================================================== --- trunk/matplotlib/lib/matplotlib/patches.py 2008-06-09 16:48:50 UTC (rev 5432) +++ trunk/matplotlib/lib/matplotlib/patches.py 2008-06-09 17:00:08 UTC (rev 5433) @@ -34,6 +34,7 @@ visible [True | False] zorder any number ================= ============================================== + """ class Patch(artist.Artist): """ Modified: trunk/matplotlib/lib/matplotlib/rcsetup.py =================================================================== --- trunk/matplotlib/lib/matplotlib/rcsetup.py 2008-06-09 16:48:50 UTC (rev 5432) +++ trunk/matplotlib/lib/matplotlib/rcsetup.py 2008-06-09 17:00:08 UTC (rev 5433) @@ -379,6 +379,7 @@ 'image.cmap' : ['jet', str], # one of gray, jet, etc 'image.lut' : [256, validate_int], # lookup table 'image.origin' : ['upper', str], # lookup table + 'image.resample' : [False, validate_bool], 'contour.negative_linestyle' : ['dashed', validate_negative_linestyle_legacy], Modified: trunk/matplotlib/src/_image.cpp =================================================================== --- trunk/matplotlib/src/_image.cpp 2008-06-09 16:48:50 UTC (rev 5432) +++ trunk/matplotlib/src/_image.cpp 2008-06-09 17:00:08 UTC (rev 5433) @@ -426,11 +426,22 @@ case HAMMING: filter.calculate(agg::image_filter_hamming(), norm); break; case HERMITE: filter.calculate(agg::image_filter_hermite(), norm); break; } - typedef agg::span_image_filter_rgba_2x2<img_accessor_type, interpolator_type> span_gen_type; - typedef agg::renderer_scanline_aa<renderer_base, span_alloc_type, span_gen_type> renderer_type; - span_gen_type sg(ia, interpolator, filter); - renderer_type ri(rb, sa, sg); - agg::render_scanlines(ras, sl, ri); + if (resample) + { + typedef agg::span_image_resample_rgba_affine<img_accessor_type> span_gen_type; + typedef agg::renderer_scanline_aa<renderer_base, span_alloc_type, span_gen_type> renderer_type; + span_gen_type sg(ia, interpolator, filter); + renderer_type ri(rb, sa, sg); + agg::render_scanlines(ras, sl, ri); + } + else + { + typedef agg::span_image_filter_rgba_2x2<img_accessor_type, interpolator_type> span_gen_type; + typedef agg::renderer_scanline_aa<renderer_base, span_alloc_type, span_gen_type> renderer_type; + span_gen_type sg(ia, interpolator, filter); + renderer_type ri(rb, sa, sg); + agg::render_scanlines(ras, sl, ri); + } } break; case BILINEAR: @@ -464,11 +475,22 @@ case LANCZOS: filter.calculate(agg::image_filter_lanczos(radius), norm); break; case BLACKMAN: filter.calculate(agg::image_filter_blackman(radius), norm); break; } - typedef agg::span_image_filter_rgba<img_accessor_type, interpolator_type> span_gen_type; - typedef agg::renderer_scanline_aa<renderer_base, span_alloc_type, span_gen_type> renderer_type; - span_gen_type sg(ia, interpolator, filter); - renderer_type ri(rb, sa, sg); - agg::render_scanlines(ras, sl, ri); + if (resample) + { + typedef agg::span_image_resample_rgba_affine<img_accessor_type> span_gen_type; + typedef agg::renderer_scanline_aa<renderer_base, span_alloc_type, span_gen_type> renderer_type; + span_gen_type sg(ia, interpolator, filter); + renderer_type ri(rb, sa, sg); + agg::render_scanlines(ras, sl, ri); + } + else + { + typedef agg::span_image_filter_rgba<img_accessor_type, interpolator_type> span_gen_type; + typedef agg::renderer_scanline_aa<renderer_base, span_alloc_type, span_gen_type> renderer_type; + span_gen_type sg(ia, interpolator, filter); + renderer_type ri(rb, sa, sg); + agg::render_scanlines(ras, sl, ri); + } } break; @@ -530,6 +552,20 @@ } +char Image::get_resample__doc__[] = +"get_resample()\n" +"\n" +"Get the resample flag." +; + +Py::Object +Image::get_resample(const Py::Tuple& args) { + _VERBOSE("Image::get_resample"); + + args.verify_length(0); + return Py::Int((int)resample); +} + char Image::get_size_out__doc__[] = "numrows, numcols = get_size()\n" "\n" @@ -593,6 +629,21 @@ } +char Image::set_resample__doc__[] = +"set_resample(boolean)\n" +"\n" +"Set the resample flag." +; + +Py::Object +Image::set_resample(const Py::Tuple& args) { + _VERBOSE("Image::set_resample"); + args.verify_length(1); + int flag = Py::Int(args[0]); + resample = (bool)flag; + return Py::Object(); +} + static void write_png_data(png_structp png_ptr, png_bytep data, png_size_t length) { PyObject* py_file_obj = (PyObject*)png_get_io_ptr(png_ptr); PyObject* write_method = PyObject_GetAttrString(py_file_obj, "write"); @@ -752,12 +803,14 @@ add_varargs_method( "buffer_rgba", &Image::buffer_rgba, Image::buffer_rgba__doc__); add_varargs_method( "get_aspect", &Image::get_aspect, Image::get_aspect__doc__); add_varargs_method( "get_interpolation", &Image::get_interpolation, Image::get_interpolation__doc__); + add_varargs_method( "get_resample", &Image::get_resample, Image::get_resample__doc__); add_varargs_method( "get_size", &Image::get_size, Image::get_size__doc__); add_varargs_method( "get_size_out", &Image::get_size_out, Image::get_size_out__doc__); add_varargs_method( "reset_matrix", &Image::reset_matrix, Image::reset_matrix__doc__); add_varargs_method( "get_matrix", &Image::get_matrix, Image::get_matrix__doc__); add_keyword_method( "resize", &Image::resize, Image::resize__doc__); add_varargs_method( "set_interpolation", &Image::set_interpolation, Image::set_interpolation__doc__); + add_varargs_method( "set_resample", &Image::set_resample, Image::set_resample__doc__); add_varargs_method( "set_aspect", &Image::set_aspect, Image::set_aspect__doc__); add_varargs_method( "write_png", &Image::write_png, Image::write_png__doc__); add_varargs_method( "set_bg", &Image::set_bg, Image::set_bg__doc__); Modified: trunk/matplotlib/src/_image.h =================================================================== --- trunk/matplotlib/src/_image.h 2008-06-09 16:48:50 UTC (rev 5432) +++ trunk/matplotlib/src/_image.h 2008-06-09 17:00:08 UTC (rev 5433) @@ -42,6 +42,8 @@ Py::Object set_bg(const Py::Tuple& args); Py::Object flipud_out(const Py::Tuple& args); Py::Object flipud_in(const Py::Tuple& args); + Py::Object set_resample(const Py::Tuple& args); + Py::Object get_resample(const Py::Tuple& args); std::pair<agg::int8u*, bool> _get_output_buffer(); @@ -78,6 +80,7 @@ unsigned interpolation, aspect; agg::rgba bg; + bool resample; private: Py::Dict __dict__; agg::trans_affine srcMatrix, imageMatrix; @@ -101,6 +104,8 @@ static char set_bg__doc__[]; static char flipud_out__doc__[]; static char flipud_in__doc__[]; + static char get_resample__doc__[]; + static char set_resample__doc__[]; }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ds...@us...> - 2008-06-09 17:09:03
|
Revision: 5434 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5434&view=rev Author: dsdale Date: 2008-06-09 10:07:33 -0700 (Mon, 09 Jun 2008) Log Message: ----------- fixed a doc error in patches Modified Paths: -------------- trunk/matplotlib/doc/faq/environment_variables_faq.rst trunk/matplotlib/lib/matplotlib/patches.py trunk/matplotlib/lib/matplotlib/pyplot.py Added Paths: ----------- trunk/matplotlib/doc/api/axes_api.rst Added: trunk/matplotlib/doc/api/axes_api.rst =================================================================== --- trunk/matplotlib/doc/api/axes_api.rst (rev 0) +++ trunk/matplotlib/doc/api/axes_api.rst 2008-06-09 17:07:33 UTC (rev 5434) @@ -0,0 +1,11 @@ +*************** +matplotlib axes +*************** + + +:mod:`matplotlib.axes` +====================== + +.. automodule:: matplotlib.axes + :members: + :undoc-members: Modified: trunk/matplotlib/doc/faq/environment_variables_faq.rst =================================================================== --- trunk/matplotlib/doc/faq/environment_variables_faq.rst 2008-06-09 17:00:08 UTC (rev 5433) +++ trunk/matplotlib/doc/faq/environment_variables_faq.rst 2008-06-09 17:07:33 UTC (rev 5434) @@ -4,12 +4,15 @@ Environment Variables ********************* -.. envvar:: PATH: - The list of directories searched to find executable programs -.. envvar:: PYTHONPATH: - The list of directories that is searched to find Python packages and modules +.. envvar:: PATH + The list of directories searched to find executable programs +.. envvar:: PYTHONPATH + + The list of directories that is searched to find Python packages and modules + + Setting Environment Variables ============================= Modified: trunk/matplotlib/lib/matplotlib/patches.py =================================================================== --- trunk/matplotlib/lib/matplotlib/patches.py 2008-06-09 17:00:08 UTC (rev 5433) +++ trunk/matplotlib/lib/matplotlib/patches.py 2008-06-09 17:07:33 UTC (rev 5434) @@ -13,7 +13,8 @@ # these are not available for the object inspector until after the # class is built so we define an initial set here for the init # function and they will be overridden after object definition -artist.kwdocd['Patch'] = """\ +artist.kwdocd['Patch'] = """ + ================= ============================================== Property Description ================= ============================================== @@ -36,6 +37,7 @@ ================= ============================================== """ + class Patch(artist.Artist): """ A patch is a 2D thingy with a face color and an edge color Modified: trunk/matplotlib/lib/matplotlib/pyplot.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyplot.py 2008-06-09 17:00:08 UTC (rev 5433) +++ trunk/matplotlib/lib/matplotlib/pyplot.py 2008-06-09 17:07:33 UTC (rev 5434) @@ -424,7 +424,6 @@ * examples/axes_demo.py places custom axes. * examples/shared_axis_demo.py uses sharex and sharey - """ nargs = len(args) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ds...@us...> - 2008-06-09 20:13:24
|
Revision: 5444 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5444&view=rev Author: dsdale Date: 2008-06-09 13:13:23 -0700 (Mon, 09 Jun 2008) Log Message: ----------- merged traits fix on branch and trunk Modified Paths: -------------- trunk/matplotlib/CHANGELOG Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Name: svnmerge-integrated - /branches/v0_91_maint:1-5396 + /branches/v0_91_maint:1-5443 Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-09 20:08:23 UTC (rev 5443) +++ trunk/matplotlib/CHANGELOG 2008-06-09 20:13:23 UTC (rev 5444) @@ -1,13 +1,11 @@ 2008-06-09 Committed Gregor's image resample patch to downsampling images with new rcparam image.resample - JDH - 2008-06-09 Don't install Enthought.Traits along with matplotlib. For matplotlib developers convenience, it can still be installed by setting an option in setup.cfg while we figure decide if there is a future for the traited config - DSD - 2008-06-09 Added range keyword arg to hist() - MM 2008-06-07 Moved list of backends to rcsetup.py; made use of lower This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-06-10 14:25:50
|
Revision: 5458 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5458&view=rev Author: jdh2358 Date: 2008-06-10 07:25:49 -0700 (Tue, 10 Jun 2008) Log Message: ----------- implemented a cross wx version set size func Modified Paths: -------------- trunk/matplotlib/doc/devel/index.rst trunk/matplotlib/doc/faq/index.rst trunk/matplotlib/doc/users/artists.rst trunk/matplotlib/doc/users/index.rst trunk/matplotlib/doc/users/pyplot_tutorial.rst trunk/matplotlib/lib/matplotlib/backends/backend_wx.py Modified: trunk/matplotlib/doc/devel/index.rst =================================================================== --- trunk/matplotlib/doc/devel/index.rst 2008-06-10 13:57:12 UTC (rev 5457) +++ trunk/matplotlib/doc/devel/index.rst 2008-06-10 14:25:49 UTC (rev 5458) @@ -8,6 +8,7 @@ :Date: |today| .. toctree:: + :maxdepth: 2 coding_guide.rst documenting_mpl.rst Modified: trunk/matplotlib/doc/faq/index.rst =================================================================== --- trunk/matplotlib/doc/faq/index.rst 2008-06-10 13:57:12 UTC (rev 5457) +++ trunk/matplotlib/doc/faq/index.rst 2008-06-10 14:25:49 UTC (rev 5458) @@ -10,6 +10,7 @@ Frequently asked questions about matplotlib .. toctree:: + :maxdepth: 2 installing_faq.rst troubleshooting_faq.rst Modified: trunk/matplotlib/doc/users/artists.rst =================================================================== --- trunk/matplotlib/doc/users/artists.rst 2008-06-10 13:57:12 UTC (rev 5457) +++ trunk/matplotlib/doc/users/artists.rst 2008-06-10 14:25:49 UTC (rev 5458) @@ -256,7 +256,7 @@ .. _figure-container: Figure container ----------------- +================ The top level container ``Artist`` is the :class:`matplotlib.figure.Figure`, and it contains everything in the @@ -349,7 +349,7 @@ .. _axes-container: Axes container --------------- +============== The :class:`matplotlib.axes.Axes` is the center of the matplotlib universe -- it contains the vast majority of all the ``Artists`` used @@ -527,7 +527,7 @@ .. _axis-container: Axis containers ---------------- +=============== The :class:`matplotlib.axis.Axis` instances handle the drawing of the tick lines, the grid lines, the tick labels and the axis label. You @@ -613,7 +613,7 @@ .. _tick-container: Tick containers ---------------- +=============== The :class:`matplotlib.axis.Tick` is the final container object in our descent from the :class:`~matplotlib.figure.Figure` to the Modified: trunk/matplotlib/doc/users/index.rst =================================================================== --- trunk/matplotlib/doc/users/index.rst 2008-06-10 13:57:12 UTC (rev 5457) +++ trunk/matplotlib/doc/users/index.rst 2008-06-10 14:25:49 UTC (rev 5458) @@ -8,6 +8,7 @@ :Date: |today| .. toctree:: + :maxdepth: 2 intro.rst pyplot_tutorial.rst Modified: trunk/matplotlib/doc/users/pyplot_tutorial.rst =================================================================== --- trunk/matplotlib/doc/users/pyplot_tutorial.rst 2008-06-10 13:57:12 UTC (rev 5457) +++ trunk/matplotlib/doc/users/pyplot_tutorial.rst 2008-06-10 14:25:49 UTC (rev 5458) @@ -197,16 +197,24 @@ import matplotlib.pyplot as plt plt.figure(1) # the first figure + plt.subplot(211) # the first subplot in the first figure plt.plot([1,2,3]) + plt.subplot(212) # the second subplot in the first figure + plt.plot([4,5,6]) + plt.figure(2) # a second figure - plt.plot([4,5,6]) + plt.plot([4,5,6]) # creates a subplot(111) by default - plt.figure(1) # figure 1 current - plt.title('Easy as 1,2,3') # figure 1 title + plt.figure(1) # figure 1 current; subplot(212) still current + plt.subplot(211) # make subplot(211) in figure1 current + plt.title('Easy as 1,2,3') # subplot 211 title You can clear the current figure with :func:`~matplotlib.pyplot.clf` -and the current axes with :func:`~matplotlib.pyplot.cla`. +and the current axes with :func:`~matplotlib.pyplot.cla`. If you find +this statefulness, annoying, don't despair, this is just a thin +stateful wrapper around an object oriented API, which you can use +instead (see :ref:`artist-tutorial`) .. _working-with-text: @@ -216,7 +224,8 @@ The :func:`~matplotlib.pyplot.text` command can be used to add text in an arbitrary location, and the :func:`~matplotlib.pyplot.xlabel`, :func:`~matplotlib.pyplot.ylabel` and :func:`~matplotlib.pyplot.title` -are used to add text in the indicated locations. +are used tox add text in the indicated locations (see :ref:`text-intro` +for a more detailed example) .. literalinclude:: figures/pyplot_text.py @@ -224,11 +233,10 @@ :scale: 50 -All of the text commands The :func:`~matplotlib.pyplot.text` commands -return an :class:`matplotlib.text.Text` instance. Just as with with -lines above, you can customize the properties by passing keyword -arguments into the text functions or using -:func:`~matplotlib.pyplot.setp`:: +All of the :func:`~matplotlib.pyplot.text` commands return an +:class:`matplotlib.text.Text` instance. Just as with with lines +above, you can customize the properties by passing keyword arguments +into the text functions or using :func:`~matplotlib.pyplot.setp`:: t = plt.xlabel('my data', fontsize=14, color='red') Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wx.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2008-06-10 13:57:12 UTC (rev 5457) +++ trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2008-06-10 14:25:49 UTC (rev 5458) @@ -1234,7 +1234,13 @@ statbar = StatusBarWx(self) self.SetStatusBar(statbar) self.canvas = self.get_canvas(fig) - self.canvas.SetInitialSize(wx.Size(fig.bbox.width, fig.bbox.height)) + + def do_nothing(*args, **kwargs): pass + + # try to find the set size func across wx versions + self.SetSizeFunc = getattr(self.canvas, 'SetInitialSize', + getattr(self.canvas, 'SetBestFittingSize', do_nothing)) + self.SetSizeFunc(wx.Size(fig.bbox.width, fig.bbox.height)) self.sizer =wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND) # By adding toolbar in sizer, we are able to put it at the bottom @@ -1355,7 +1361,7 @@ def resize(self, width, height): 'Set the canvas size in pixels' - self.canvas.SetInitialSize(wx.Size(width, height)) + self.canvas.SetSizeFunc(wx.Size(width, height)) self.window.GetSizer().Fit(self.window) # Identifiers for toolbar controls - images_wx contains bitmaps for the images This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2008-06-10 15:35:18
|
Revision: 5460 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5460&view=rev Author: mdboom Date: 2008-06-10 08:35:13 -0700 (Tue, 10 Jun 2008) Log Message: ----------- [ 1985420 ] Repair of baseline alignment in Text._get_layout Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/text.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-10 14:29:43 UTC (rev 5459) +++ trunk/matplotlib/CHANGELOG 2008-06-10 15:35:13 UTC (rev 5460) @@ -1,8 +1,12 @@ +2008-06-10 Fix text baseline alignment bug. [ 1985420 ] Repair of + baseline alignment in Text._get_layout. Thanks Stan West - + MGD + 2008-06-09 Committed Gregor's image resample patch to downsampling images with new rcparam image.resample - JDH -2008-06-09 Don't install Enthought.Traits along with matplotlib. For - matplotlib developers convenience, it can still be +2008-06-09 Don't install Enthought.Traits along with matplotlib. For + matplotlib developers convenience, it can still be installed by setting an option in setup.cfg while we figure decide if there is a future for the traited config - DSD Modified: trunk/matplotlib/lib/matplotlib/text.py =================================================================== --- trunk/matplotlib/lib/matplotlib/text.py 2008-06-10 14:29:43 UTC (rev 5459) +++ trunk/matplotlib/lib/matplotlib/text.py 2008-06-10 15:35:13 UTC (rev 5460) @@ -246,7 +246,7 @@ if valign=='center': offsety = (ymin + height/2.0) elif valign=='top': offsety = (ymin + height) - elif valign=='baseline': offsety = (ymin + height) + baseline + elif valign=='baseline': offsety = (ymin + height) - baseline else: offsety = ymin xmin -= offsetx This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-06-10 15:51:51
|
Revision: 5461 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5461&view=rev Author: jdh2358 Date: 2008-06-10 08:50:55 -0700 (Tue, 10 Jun 2008) Log Message: ----------- fixed auto-legend wart for bar and friends Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-10 15:35:13 UTC (rev 5460) +++ trunk/matplotlib/CHANGELOG 2008-06-10 15:50:55 UTC (rev 5461) @@ -1,3 +1,7 @@ +2008-06-10 Bar now applies the label only to the frist patch, and + sets _nolegend_ for the other patch labels. This let's + autolegend work as expected for hist and bar + 2008-06-10 Fix text baseline alignment bug. [ 1985420 ] Repair of baseline alignment in Text._get_layout. Thanks Stan West - MGD Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-06-10 15:35:13 UTC (rev 5460) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-06-10 15:50:55 UTC (rev 5461) @@ -3530,6 +3530,7 @@ """ if not self._hold: self.cla() + label = kwargs.pop('label', '') def make_iterable(x): if not iterable(x): return [x] @@ -3667,8 +3668,11 @@ facecolor=c, edgecolor=e, linewidth=lw, + label=label ) + label = '_nolegend_' r.update(kwargs) + #print r.get_label(), label, 'label' in kwargs self.add_patch(r) patches.append(r) @@ -5673,10 +5677,10 @@ is an integer input argument=numbins, numbins+1 bin edges will be returned, compatabile with the semantics of np.histogram with the new=True argument. - + range: The lower and upper range of the bins. Lower and upper outliers - are ignored. If not provided, range is (x.min(), x.max()). + are ignored. If not provided, range is (x.min(), x.max()). normed: if True, the first element of the return tuple will @@ -5925,9 +5929,15 @@ else: raise ValueError, 'invalid histtype: %s' % histtype + label = kwargs.pop('label', '') + for patch in patches: for p in patch: p.update(kwargs) + p.set_label(label) + label = '_nolegend' + + if len(n)==1: return n[0], bins, cbook.silent_list('Patch', patches[0]) else: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-06-10 18:10:15
|
Revision: 5463 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5463&view=rev Author: jdh2358 Date: 2008-06-10 11:08:50 -0700 (Tue, 10 Jun 2008) Log Message: ----------- added backend bases api Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/api/index.rst trunk/matplotlib/doc/users/event_handling.rst trunk/matplotlib/doc/users/figures/text_commands.py trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/text.py Added Paths: ----------- trunk/matplotlib/doc/api/backend_api.rst Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2008-06-10 15:53:19 UTC (rev 5462) +++ trunk/matplotlib/CHANGELOG 2008-06-10 18:08:50 UTC (rev 5463) @@ -1,6 +1,8 @@ -2008-06-10 Bar now applies the label only to the frist patch, and - sets _nolegend_ for the other patch labels. This let's - autolegend work as expected for hist and bar +2008-06-10 Bar now applies the label only to the first patch only, and + sets '_nolegend_' for the other patch labels. This lets + autolegend work as expected for hist and bar - see + https://sourceforge.net/tracker/index.php?func=detail&aid=1986597&group_id=80706&atid=560720 + JDH 2008-06-10 Fix text baseline alignment bug. [ 1985420 ] Repair of baseline alignment in Text._get_layout. Thanks Stan West - Added: trunk/matplotlib/doc/api/backend_api.rst =================================================================== --- trunk/matplotlib/doc/api/backend_api.rst (rev 0) +++ trunk/matplotlib/doc/api/backend_api.rst 2008-06-10 18:08:50 UTC (rev 5463) @@ -0,0 +1,11 @@ +******************* +matplotlib backends +******************* + + +:mod:`matplotlib.backend_bases` +================================ + +.. automodule:: matplotlib.backend_bases + :members: + :undoc-members: Modified: trunk/matplotlib/doc/api/index.rst =================================================================== --- trunk/matplotlib/doc/api/index.rst 2008-06-10 15:53:19 UTC (rev 5462) +++ trunk/matplotlib/doc/api/index.rst 2008-06-10 18:08:50 UTC (rev 5463) @@ -7,11 +7,9 @@ :Release: |version| :Date: |today| -Introduction to developer's guide here **TODO**. - .. toctree:: artist_api.rst axes_api.rst pyplot_api.rst - + backend_api.rst Modified: trunk/matplotlib/doc/users/event_handling.rst =================================================================== --- trunk/matplotlib/doc/users/event_handling.rst 2008-06-10 15:53:19 UTC (rev 5462) +++ trunk/matplotlib/doc/users/event_handling.rst 2008-06-10 18:08:50 UTC (rev 5463) @@ -13,9 +13,10 @@ handling API is GUI neutral, it is based on the GTK model, which was the first user interface matplotlib supported. The events that are triggered are also a bit richer vis-a-vis matplotlib than standard GUI -events, including information like which Axes the event occurred in. -The events also understand the matplotlib coordinate system, and -report event locations in both pixel and data coordinates. +events, including information like which :class:`matplotlib.axes.Axes` +the event occurred in. The events also understand the matplotlib +coordinate system, and report event locations in both pixel and data +coordinates. .. _event-connections: @@ -24,8 +25,9 @@ To receive events, you need to write a callback function and then connect your function to the event manager, which is part of the -FigureCanvas. Here is a simple example that prints the location of -the mouse click and which button was pressed:: +:class:`~matplotlib.backend_bases.FigureCanvasBase`. Here is a simple +example that prints the location of the mouse click and which button +was pressed:: fig = plt.figure() ax = fig.add_subplot(111) @@ -37,9 +39,10 @@ cid = fig.canvas.mpl_connect('button_press_event', onclick) -The FigureCanvas method mpl_connect returns a connection id which is -simply an integer. When you want to disconnect the callback, just -call:: +The ``FigureCanvas`` method +:meth:`~matplotlib.backend_bases.FigureCanvasBase.mpl_connect` returns +a connection id which is simply an integer. When you want to +disconnect the callback, just call:: fig.canvas.mpl_disconnect(cid) @@ -47,19 +50,19 @@ are sent back to you when the event occurs, and the event descriptions -===================== =========== =================================== -Event name Class Description -===================== =========== =================================== -button_press_event MouseEvent mouse button is pressed -button_release_event MouseEvent mouse button is released -draw_event DrawEvent canvas draw -key_press_event KeyEvent key is pressed -key_release_event KeyEvent key is released -motion_notify_event MouseEvent mouse motion -pick_event PickEvent an object in the canvas is selected -resize_event ResizeEvent figure canvas is resized -scroll_event MouseEvent mouse scroll wheel is rolled -===================== =========== =================================== +======================= ====================================================================================== +Event name Class and description +======================= ====================================================================================== +'button_press_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse button is pressed +'button_release_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse button is released +'draw_event' :class:`~matplotlib.backend_bases.DrawEvent` - canvas draw +'key_press_event' :class:`~matplotlib.backend_bases.KeyEvent` - key is pressed +'key_release_event' :class:`~matplotlib.backend_bases.KeyEvent` - key is released +'motion_notify_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse motion +'pick_event' :class:`~matplotlib.backend_bases.PickEvent` - an object in the canvas is selected +'resize_event' :class:`~matplotlib.backend_bases.ResizeEvent` - figure canvas is resized +'scroll_event' :class:`~matplotlib.backend_bases.MouseEvent` - mouse scroll wheel is rolled +======================= ====================================================================================== .. _event-attributes: @@ -67,31 +70,32 @@ ================ All matplotlib events inherit from the base class -matplotlib.backend_bases.Event, which store the attributes +:class:`matplotlib.backend_bases.Event`, which store the attributes =============== ================================================= Event attribute Description =============== ================================================= -name the event name -canvas the FigureCanvas instance generating the event -guiEvent the GUI event that triggered the matplotlib event +``name`` the event name +``canvas`` the FigureCanvas instance generating the event +``guiEvent`` the GUI event that triggered the matplotlib event =============== ================================================= The most common events that are the bread and butter of event handling are key press/release events and mouse press/release and movement -events. The KeyEvent and MouseEvent classes that handle these events -are both derived from the LocationEvent, which has the following -attributes +events. The :class:`~matplotlib.backend_bases.KeyEvent` and +:class:`~matplotlib.backend_bases.MouseEvent` classes that handle +these events are both derived from the LocationEvent, which has the +following attributes ======================= ======================================== LocationEvent attribute Description ======================= ======================================== -x x position - pixels from left of canvas -y y position - pixels from right of canvas -button button pressed None, 1, 2, 3 -inaxes the Axes instance if mouse us over axes -xdata x coord of mouse in data coords -ydata y coord of mouse in data coords +``x`` x position - pixels from left of canvas +``y`` y position - pixels from right of canvas +``button`` button pressed None, 1, 2, 3 +``inaxes`` the Axes instance if mouse us over axes +``xdata`` x coord of mouse in data coords +``ydata`` y coord of mouse in data coords ======================= ======================================== Let's look a simple example of a canvas, where a simple line segment @@ -120,31 +124,33 @@ -The MouseEvent that we just used is a LocationEvent, so we have access -to the data and pixel coordinates in event.x and event.xdata. In -addition to the LocationEvent attributes, it has +The :class:`~matplotlib.backend_bases.MouseEvent` that we just used is a +:class:`~matplotlib.backend_bases.LocationEvent`, so we have access to +the data and pixel coordinates in event.x and event.xdata. In +addition to the ``LocationEvent`` attributes, it has ==================== ============================================================== MouseEvent attribute Description ==================== ============================================================== -button button pressed None, 1, 2, 3 -key the key pressed: None, chr(range(255)), shift, win, or control +``button`` button pressed None, 1, 2, 3 +``key`` the key pressed: None, chr(range(255)), shift, win, or control ==================== ============================================================== Draggable Rectangle Exercise ---------------------------- -Write draggable rectangle class that is initialized with a Rectangle -instance but will move its x,y location when dragged. Hint: you will -need to store the orginal xy location of the rectangle which is stored -as rect.xy and connect to the press, motion and release mouse events. -When the mouse is pressed, check to see if the click occurs over your -rectangle (see rect.contains) and if it does, store the rectangle xy -and the location of the mouse click in data coords. In the motion -event callback, compute the deltax and deltay of the mouse movement, -and add those deltas to the origin of the rectangle you stored. The -redraw the figure. On the button release event, just reset all the -button press data you stored as None. +Write draggable rectangle class that is initialized with a +:class:`~matplotlib.patches.Rectangle` instance but will move its x,y +location when dragged. Hint: you will need to store the orginal +``xy`` location of the rectangle which is stored as rect.xy and +connect to the press, motion and release mouse events. When the mouse +is pressed, check to see if the click occurs over your rectangle (see +:meth:`matplotlib.patches.Rectangle.contains`) and if it does, store +the rectangle xy and the location of the mouse click in data coords. +In the motion event callback, compute the deltax and deltay of the +mouse movement, and add those deltas to the origin of the rectangle +you stored. The redraw the figure. On the button release event, just +reset all the button press data you stored as None. Here is the solution:: @@ -212,8 +218,9 @@ plt.show() -**Extra credit**: use the animation blit techniques discussed at -http://www.scipy.org/Cookbook/Matplotlib/Animations to make the +**Extra credit**: use the animation blit techniques discussed in the +`animations recipe +<http://www.scipy.org/Cookbook/Matplotlib/Animations>`_ to make the animated drawing faster and smoother. Extra credit solution:: @@ -325,30 +332,32 @@ Object Picking ============== -You can enable picking by setting the ``picker`` property of an Artist -(eg a matplotlib Line2D, Text, Patch, Polygon, AxesImage, -etc...) +You can enable picking by setting the ``picker`` property of an +:class:`~matplotlib.artist.Artist` (eg a matplotlib +:class:`~matplotlib.lines.Line2D`, :class:`~matplotlib.text.Text`, +:class:`~matplotlib.patches.Patch`, :class:`~matplotlib.patches.Polygon`, +:class:`~matplotlib.patches.AxesImage`, etc...) -There are a variety of meanings of the picker property: +There are a variety of meanings of the ``picker`` property: -- None : picking is disabled for this artist (default) +- ``None`` : picking is disabled for this artist (default) -- boolean : if True then picking will be enabled and the artist will +- ``boolean`` : if True then picking will be enabled and the artist will fire a pick event if the mouse event is over the artist -- float : if picker is a number it is interpreted as an epsilon +- ``float`` : if picker is a number it is interpreted as an epsilon tolerance in points and the the artist will fire off an event if its data is within epsilon of the mouse event. For some artists like lines and patch collections, the artist may provide additional data to the pick event that is generated, eg the indices of the data within epsilon of the pick event. -- function : if picker is callable, it is a user supplied function +- ``function`` : if picker is callable, it is a user supplied function which determines whether the artist is hit by the mouse event. The signature is ``hit, props = picker(artist, mouseevent)`` to determine the hit test. If the mouse event is over the artist, - return hit=True and props is a dictionary of properties you want - added to the PickEvent attributes + return ``hit=True`` and props is a dictionary of properties you want + added to the :class:`~matplotlib.backend_bases.PickEvent` attributes After you have enabled an artist for picking by setting the ``picker`` @@ -361,22 +370,24 @@ # now do something with this... -The pick event (matplotlib.backend_bases.PickEvent) which is passed to +The :class:`~matplotlib.backend_bases.PickEvent` which is passed to your callback is always fired with two attributes: -- mouseevent : the mouse event that generate the pick event. The - mouse event in turn has attributes like x and y (the coords in +- ``mouseevent`` : the mouse event that generate the pick event. The + mouse event in turn has attributes like ``x`` and ``y`` (the coords in display space, eg pixels from left, bottom) and xdata, ydata (the coords in data space). Additionally, you can get information about which buttons were pressed, which keys were pressed, which Axes the - mouse is over, etc. See matplotlib.backend_bases.MouseEvent for + mouse is over, etc. See :class:`matplotlib.backend_bases.MouseEvent` for details. -- artist : the matplotlib.artist that generated the pick event. +- ``artist`` : the :class:`matplotlib.artist.Artist` that generated + the pick event. -Additionally, certain artists like Line2D and PatchCollection may -attach additional meta data like the indices into the data that meet -the picker criteria (eg all the points in the line that are within the +Additionally, certain artists like :class:`~matplotlib.lines.Line2D` +and :class:`~matplotlib.collections.PatchCollection` may attach +additional meta data like the indices into the data that meet the +picker criteria (eg all the points in the line that are within the specified epsilon tolerance) Simple picking example @@ -389,10 +400,10 @@ vertices that are within the pick distance tolerance. Our onpick callback function simply prints the data that are under the pick location. Different matplotlib Artists can attach different data to -the PickEvent. For example, Line2D attaches the ind property, which -are the indices into the line data under the pick point. See -Line2D.pick for details on the PickEvent properties of the line. Here -is the code:: +the PickEvent. For example, ``Line2D`` attaches the ind property, +which are the indices into the line data under the pick point. See +:meth:`~matplotlib.lines.Line2D.pick` for details on the ``PickEvent`` +properties of the line. Here is the code:: import numpy as np import matplotlib.pyplot as plt Modified: trunk/matplotlib/doc/users/figures/text_commands.py =================================================================== --- trunk/matplotlib/doc/users/figures/text_commands.py 2008-06-10 15:53:19 UTC (rev 5462) +++ trunk/matplotlib/doc/users/figures/text_commands.py 2008-06-10 18:08:50 UTC (rev 5463) @@ -10,10 +10,15 @@ ax.set_xlabel('xlabel') ax.set_ylabel('ylabel') -ax.text(5, 8, 'italics text in data coords', style='italic') + +ax.text(5, 8, 'boxed italics text in data coords', style='italic', + bbox={'facecolor':'red', 'alpha':0.5, 'pad':10}) + ax.text(2, 6, r'an equation: $E=mc^2$', fontsize=20) -ax.text(0.95, 0.01, 'text in axes coords', +ax.text(4, 3, unicode('unicode: Institut f\374r Festk\366rperphysik', 'latin-1')) + +ax.text(0.95, 0.01, 'colored text in axes coords', verticalalignment='bottom', horizontalalignment='right', transform=ax.transAxes, color='green', fontsize=20) Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-06-10 15:53:19 UTC (rev 5462) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-06-10 18:08:50 UTC (rev 5463) @@ -1,6 +1,24 @@ """ Abstract base classes define the primitives that renderers and graphics contexts must implement to serve as a matplotlib backend + +:class:`RendererBase` + An abstract base class to handle drawing/rendering operations. + +:class:`FigureCanvasBase` + The abstraction layer that separates the + :class:`matplotlib.figure.Figure` from the backend specific + details like a user interface drawing area + +:class:`GraphicsContextBase` + An abstract base class that provides color, line styles, etc... + +:class:`Event` + The base class for all of the matplotlib event + handling. Derived classes suh as :class:`KeyEvent` and + :class:`MouseEvent` store the meta data like keys and buttons + pressed, x and y locations in pixel and + :class:`~matplotlib.axes.Axes` coordinates. """ from __future__ import division @@ -20,36 +38,39 @@ The following methods *must* be implemented in the backend: - draw_path - draw_image - draw_text - get_text_width_height_descent + * draw_path + * draw_image + * draw_text + * get_text_width_height_descent The following methods *should* be implemented in the backend for optimization reasons: - draw_markers - draw_path_collection - draw_quad_mesh + * draw_markers + * draw_path_collection + * draw_quad_mesh """ def __init__(self): self._texmanager = None def open_group(self, s): - """open a grouping element with label s - Is only currently used by backend_svg """ + Open a grouping element with label ``s.`` Is only currently used by + :mod:`~matplotlib.backends.backend_svg` + """ pass def close_group(self, s): - """close a grouping element with label s - Is only currently used by backend_svg """ + Close a grouping element with label ``s`` + Is only currently used by :mod:`~matplotlib.backends.backend_svg` + """ pass def draw_path(self, gc, path, transform, rgbFace=None): """ - Draws a Path instance using the given affine transform. + Draws a :class:`~matplotlib.path.Path` instance using the + given affine transform. """ raise NotImplementedError @@ -60,13 +81,14 @@ that behavior, those vertices should be removed before calling this function. - marker_trans is an affine transform applied to the marker. - trans is an affine transform applied to the path. + ``marker_trans`` is an affine transform applied to the marker. + ``trans`` is an affine transform applied to the path. This provides a fallback implementation of draw_markers that - makes multiple calls to draw_path. Some backends may want to - override this method in order to draw the marker only once and - reuse it multiple times. + makes multiple calls to + :meth:`draw_path`. Some + backends may want to override this method in order to draw the + marker only once and reuse it multiple times. """ tpath = trans.transform_path(path) for x, y in tpath.vertices: @@ -80,20 +102,24 @@ linestyles, antialiaseds): """ Draws a collection of paths, selecting drawing properties from - the lists facecolors, edgecolors, linewidths, linestyles and - antialiaseds. offsets is a list of offsets to apply to each - of the paths. The offsets in offsets are first transformed by - offsetTrans before being applied. + the lists ``facecolors``, ``edgecolors``, ``linewidths``, + ``linestyles`` and ``antialiaseds``. `` offsets`` is a list of + offsets to apply to each of the paths. The offsets in + ``offsets`` are first transformed by ``offsetTrans`` before + being applied. This provides a fallback implementation of draw_path_collection that makes multiple calls to draw_path. Some backends may want to override this in order to render each set of path data only once, and then reference that path multiple times with the different offsets, colors, styles etc. - The generator methods _iter_collection_raw_paths and - _iter_collection are provided to help with (and standardize) - the implementation across backends. It is highly recommended - to use those generators, so that changes to the behavior of + The generator methods + :meth:`_iter_collection_raw_paths` + and + :meth:`_iter_collection` + are provided to help with (and standardize) the implementation + across backends. It is highly recommended to use those + generators, so that changes to the behavior of draw_path_collection can be made globally. """ path_ids = [] @@ -115,7 +141,7 @@ showedges): """ This provides a fallback implementation of draw_quad_mesh that - generates paths and then calls draw_path_collection. + generates paths and then calls :meth:`draw_path_collection`. """ from matplotlib.collections import QuadMesh paths = QuadMesh.convert_mesh_to_paths( @@ -135,8 +161,8 @@ def _iter_collection_raw_paths(self, master_transform, paths, all_transforms): """ - This is a helper method (along with _iter_collection) to make - it easier to write a space-efficent draw_path_collection + This is a helper method (along with :meth:`_iter_collection`) to make + it easier to write a space-efficent :meth:`draw_path_collection` implementation in a backend. This method yields all of the base path/transform @@ -144,7 +170,7 @@ list of transforms. The arguments should be exactly what is passed in to - draw_path_collection. + :meth:`draw_path_collection`. The backend should take each yielded path and transform and create an object can be referenced (reused) later. @@ -168,8 +194,8 @@ linewidths, linestyles, antialiaseds): """ This is a helper method (along with - _iter_collection_raw_paths) to make it easier to write a - space-efficent draw_path_collection implementation in a + :meth:`_iter_collection_raw_paths`) to make it easier to write + a space-efficent :meth:`draw_path_collection` implementation in a backend. This method yields all of the path, offset and graphics @@ -237,7 +263,7 @@ def get_image_magnification(self): """ - Get the factor by which to magnify images passed to draw_image. + Get the factor by which to magnify images passed to :meth:`draw_image`. Allows a backend to have images at a different resolution to other artists. """ @@ -245,13 +271,13 @@ def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None): """ - Draw the Image instance into the current axes; x is the - distance in pixels from the left hand side of the canvas. y is - the distance from the origin. That is, if origin is upper, y - is the distance from top. If origin is lower, y is the - distance from bottom + Draw the :class:`~matplotlib.image.Image` instance into the + current axes; ``x`` is the distance in pixels from the left + hand side of the canvas. ``y`` is the distance from the + origin. That is, if origin is upper, y is the distance from + top. If origin is lower, y is the distance from bottom - bbox is a matplotlib.transforms.BBox instance for clipping, or + bbox is a :class:`~matplotlib.transforms.Bbox` instance for clipping, or None """ raise NotImplementedError @@ -268,8 +294,10 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False): """ - Draw the text.Text instance s at x,y (display coords) with font - properties instance prop at angle in degrees, using GraphicsContext gc + Draw the :class:`~matplotlib.text.Text` instance s at ``x``, + ``y`` (display coords) with + :class:`~matplotlib.font_manager.FontProperties` instance + ``prop`` at ``angle`` in degrees, using :class:`GraphicsContextBase` gc **backend implementers note** @@ -285,9 +313,11 @@ raise NotImplementedError def flipy(self): - """return true if y small numbers are top for renderer - Is used for drawing text (text.py) and images (image.py) only """ + Return true if y small numbers are top for renderer Is used + for drawing text (:mod:`matplotlib.text`) and images + (:mod:`matplotlib.image`) only + """ return True def get_canvas_width_height(self): @@ -295,6 +325,9 @@ return 1, 1 def get_texmanager(self): + """ + return the :class:matplotlib.texmanager.TexManager` instance + """ if self._texmanager is None: from matplotlib.texmanager import TexManager self._texmanager = TexManager() @@ -304,13 +337,13 @@ """ get the width and height, and the offset from the bottom to the baseline (descent), in display coords of the string s with - FontPropertry prop + :class:`~matplotlib.font_manager.FontProperties` prop """ raise NotImplementedError def new_gc(self): """ - Return an instance of a GraphicsContextBase + Return an instance of a :class:`GraphicsContextBase` """ return GraphicsContextBase() @@ -322,8 +355,9 @@ You need to override this function (unless your backend doesn't have a dpi, eg, postscript or svg). - Some imaging systems assume some value for pixels per inch. - points to pixels = points * pixels_per_inch/72.0 * dpi/72.0 + Some imaging systems assume some value for pixels per inch"" + + points to pixels = points * pixels_per_inch/72.0 * dpi/72.0 """ return points @@ -338,8 +372,9 @@ class GraphicsContextBase: - """An abstract base class that provides color, line styles, etc... """ + An abstract base class that provides color, line styles, etc... + """ # a mapping from dash styles to suggested offset, dash pairs dashd = { @@ -395,15 +430,15 @@ def get_clip_rectangle(self): """ - Return the clip rectangle as a Bbox instance + Return the clip rectangle as a :class:`~matplotlib.transforms.Bbox` instance """ return self._cliprect def get_clip_path(self): """ Return the clip path in the form (path, transform), where path - is a path.Path instance, and transform as an affine transform - to apply to the path before clipping. + is a :class:`~matplotlib.path.Path` instance, and transform as + an affine transform to apply to the path before clipping. """ if self._clippath is not None: return self._clippath.get_transformed_path_and_affine() @@ -413,7 +448,9 @@ """ Return the dash information as an offset dashlist tuple The dash list is a even size list that gives the ink on, ink off - in pixels. See p107 of to postscript BLUEBOOK for more info + in pixels. See p107 of to postscript `BLUEBOOK + <http://www-cdf.fnal.gov/offline/PostScript/BLUEBOOK.PDF>`_ + for more info Default value is None """ @@ -479,7 +516,7 @@ def set_clip_path(self, path): """ Set the clip path and transformation. Path should be a - transforms.TransformedPath instance. + :class:`~matplotlib.transforms.TransformedPath` instance. """ assert path is None or isinstance(path, transforms.TransformedPath) self._clippath = path @@ -487,9 +524,12 @@ def set_dashes(self, dash_offset, dash_list): """ Set the dash style for the gc. - dash_offset is the offset (usually 0). - dash_list specifies the on-off sequence as points - (None, None) specifies a solid line + + ``dash_offset`` + is the offset (usually 0). + + ``dash_list`` + specifies the on-off sequence as points. ``(None, None)`` specifies a solid line """ self._dashes = dash_offset, dash_list @@ -499,8 +539,8 @@ html hex color string, an rgb unit tuple, or a float between 0 and 1. In the latter case, grayscale is used. - The GraphicsContext converts colors to rgb internally. If you - know the color is rgb already, you can set isRGB to True to + The :class:`GraphicsContextBase` converts colors to rgb internally. If you + know the color is rgb already, you can set ``isRGB=True`` to avoid the performace hit of the conversion """ if isRGB: @@ -510,7 +550,7 @@ def set_graylevel(self, frac): """ - Set the foreground color to be a gray level with frac frac + Set the foreground color to be a gray level with ``frac`` frac """ self._rgb = (frac, frac, frac) @@ -556,11 +596,15 @@ class Event: """ A matplotlib event. Attach additional attributes as defined in - FigureCanvas.connect. The following attributes are defined and + :meth:`FigureCanvasBase.connect`. The following attributes are defined and shown with their default values - name # the event name - canvas # the FigureCanvas instance generating the event + ``name`` + the event name + + ``canvas`` + the FigureCanvas instance generating the event + """ def __init__(self, name, canvas,guiEvent=None): self.name = name @@ -572,10 +616,10 @@ """ An event triggered by a draw operation on the canvas - Attributes are - name - canvas - renderer - the Renderer instance + In addition to the :class`Event` attributes, the following event attributes are defined: + + ``renderer`` + the :class:`RendererBase` instance for the draw event """ def __init__(self, name, canvas, renderer): Event.__init__(self, name, canvas) @@ -585,11 +629,13 @@ """ An event triggered by a canvas resize - Attributes are - name - canvas - width # width of the canvas in pixels - height # height of the canvas in pixels + In addition to the :class`Event` attributes, the following event attributes are defined: + + ``width`` + width of the canvas in pixels + + ``height`` + height of the canvas in pixels """ def __init__(self, name, canvas): Event.__init__(self, name, canvas) @@ -602,24 +648,33 @@ The following additional attributes are defined and shown with their default values - x = None # x position - pixels from left of canvas - y = None # y position - pixels from bottom of canvas - inaxes = None # the Axes instance if mouse us over axes - xdata = None # x coord of mouse in data coords - ydata = None # y coord of mouse in data coords + In addition to the :class`Event` attributes, the following event attributes are defined: + ``x`` + x position - pixels from left of canvas + + ``y`` + y position - pixels from bottom of canvas + + ``inaxes`` + the :class:`~matplotlib.axes.Axes` instance if mouse is over axes + + ``xdata`` + x coord of mouse in data coords + + ``ydata`` + y coord of mouse in data coords + """ x = None # x position - pixels from left of canvas y = None # y position - pixels from right of canvas - button = None # button pressed None, 1, 2, 3 inaxes = None # the Axes instance if mouse us over axes xdata = None # x coord of mouse in data coords ydata = None # y coord of mouse in data coords def __init__(self, name, canvas, x, y,guiEvent=None): """ - x, y in figure coords, 0,0 = bottom, left - button pressed None, 1, 2, 3 + ``x``, ``y`` in figure coords, 0,0 = bottom, left """ Event.__init__(self, name, canvas,guiEvent=guiEvent) self.x = x @@ -653,20 +708,16 @@ class MouseEvent(LocationEvent): """ - A mouse event (button_press_event, button_release_event, scroll_event, - motion_notify_event). + A mouse event ('button_press_event', 'button_release_event', 'scroll_event', + 'motion_notify_event'). - The following attributes are defined and shown with their default - values + In addition to the :class`Event` and :class:`LocationEvent` + attributes, the following attributes are defined: - x = None # x position - pixels from left of canvas - y = None # y position - pixels from bottom of canvas - button = None # button pressed None, 1, 2, 3, 'up', 'down' - (up and down are used for scroll events) - key = None # the key pressed: None, chr(range(255), shift, win, or control - inaxes = None # the Axes instance if mouse us over axes - xdata = None # x coord of mouse in data coords - ydata = None # y coord of mouse in data coords + ``button`` + button pressed None, 1, 2, 3, 'up', 'down' (up and down are used for scroll events) + ``key`` + the key pressed: None, chr(range(255), shift, win, or control """ x = None # x position - pixels from left of canvas @@ -691,12 +742,18 @@ a pick event, fired when the user picks a location on the canvas sufficiently close to an artist. - Attrs: all the Event attrs plus - mouseevent : the MouseEvent that generated the pick - artist : the artist picked + Attrs: all the :class:`Event` attributes plus - extra class dependent attrs -- eg a Line2D pick may define - different extra attributes than a PatchCollection pick event + ``mouseevent`` + the :class:`MouseEvent` that generated the pick + + ``artist`` + the :class:`~matplotlib.artist.Artist` picked + + extra class dependent attrs -- eg a + :class:`~matplotlib.lines.Line2D` pick may define different extra + attributes than a :class:`~matplotlib.collections.PatchCollection` + pick event """ def __init__(self, name, canvas, mouseevent, artist, guiEvent=None, **kwargs): Event.__init__(self, name, canvas, guiEvent) @@ -710,17 +767,13 @@ A key event (key press, key release). Attach additional attributes as defined in - FigureCanvas.connect. + :meth:`FigureCanvasBase.connect`. - The following attributes are defined and shown with their default - values + In addition to the :class`Event` and :class:`LocationEvent` + attributes, the following attributes are defined: - x = None # x position - pixels from left of canvas - y = None # y position - pixels from bottom of canvas - key = None # the key pressed: None, chr(range(255), shift, win, or control - inaxes = None # the Axes instance if mouse us over axes - xdata = None # x coord of mouse in data coords - ydata = None # y coord of mouse in data coords + ``key`` + the key pressed: None, chr(range(255), shift, win, or control This interface may change slightly when better support for modifier keys is included @@ -735,9 +788,10 @@ """ The canvas the figure renders into. - Public attribute + Public attributes - figure - A Figure instance + ``figure`` + A :class:`matplotlib.figure.Figure` instance """ events = ( @@ -775,8 +829,10 @@ def onRemove(self, ev): """ Mouse event processor which removes the top artist - under the cursor. Connect this to the mouse_press_event - using canvas.mpl_connect('mouse_press_event',canvas.onRemove) + under the cursor. Connect this to the 'mouse_press_event' + using:: + + canvas.mpl_connect('mouse_press_event',canvas.onRemove) """ def sort_artists(artists): # This depends on stable sort and artists returned @@ -807,8 +863,10 @@ def onHilite(self, ev): """ Mouse event processor which highlights the artists - under the cursor. Connect this to the motion_notify_event - using canvas.mpl_connect('motion_notify_event',canvas.onHilite) + under the cursor. Connect this to the 'motion_notify_event' + using:: + + canvas.mpl_connect('motion_notify_event',canvas.onHilite) """ if not hasattr(self,'_active'): self._active = dict() @@ -862,22 +920,40 @@ pass def draw_event(self, renderer): + """ + This method will be call all functions connected to the + 'draw_event' with a :class:`DrawEvent` + """ + s = 'draw_event' event = DrawEvent(s, self, renderer) self.callbacks.process(s, event) def resize_event(self): + """ + This method will be call all functions connected to the + 'resize_event' with a :class:`ResizeEvent` + """ + s = 'resize_event' event = ResizeEvent(s, self) self.callbacks.process(s, event) def key_press_event(self, key, guiEvent=None): + """ + This method will be call all functions connected to the + 'key_press_event' with a :class:`KeyEvent` + """ self._key = key s = 'key_press_event' event = KeyEvent(s, self, key, self._lastx, self._lasty, guiEvent=guiEvent) self.callbacks.process(s, event) def key_release_event(self, key, guiEvent=None): + """ + This method will be call all functions connected to the + 'key_release_event' with a :class:`KeyEvent` + """ s = 'key_release_event' event = KeyEvent(s, self, key, self._lastx, self._lasty, guiEvent=guiEvent) self.callbacks.process(s, event) @@ -886,7 +962,7 @@ def pick_event(self, mouseevent, artist, **kwargs): """ This method will be called by artists who are picked and will - fire off PickEvent callbacks registered listeners + fire off :class:`PickEvent` callbacks registered listeners """ s = 'pick_event' event = PickEvent(s, self, mouseevent, artist, **kwargs) @@ -896,7 +972,10 @@ """ Backend derived classes should call this function on any scroll wheel event. x,y are the canvas coords: 0,0 is lower, - left. button and key are as defined in MouseEvent + left. button and key are as defined in MouseEvent. + + This method will be call all functions connected to the + 'scroll_event' with a :class:`MouseEvent` instance. """ self._button = button s = 'scroll_event' @@ -908,7 +987,11 @@ """ Backend derived classes should call this function on any mouse button press. x,y are the canvas coords: 0,0 is lower, left. - button and key are as defined in MouseEvent + button and key are as defined in :class:`MouseEvent`. + + This method will be call all functions connected to the + 'button_press_event' with a :class:`MouseEvent` instance. + """ self._button = button s = 'button_press_event' @@ -919,7 +1002,11 @@ """ Backend derived classes should call this function on any mouse button release. x,y are the canvas coords: 0,0 is lower, left. - button and key are as defined in MouseEvent + button and key are as defined in :class:`MouseEvent` + + This method will be call all functions connected to the + 'button_release_event' with a :class:`MouseEvent` instance. + """ s = 'button_release_event' event = MouseEvent(s, self, x, y, button, self._key, guiEvent=guiEvent) @@ -931,6 +1018,10 @@ Backend derived classes should call this function on any motion-notify-event. x,y are the canvas coords: 0,0 is lower, left. button and key are as defined in MouseEvent + + This method will be call all functions connected to the + 'motion_notify_event' with a :class:`MouseEvent` instance. + """ self._lastx, self._lasty = x, y s = 'motion_notify_event' @@ -940,13 +1031,13 @@ def draw(self, *args, **kwargs): """ - Render the figure + Render the :class:`~matplotlib.figure.Figure` """ pass def draw_idle(self, *args, **kwargs): """ - draw only if idle; defaults to draw but backends can overrride + :meth:`draw` only if idle; defaults to draw but backends can overrride """ self.draw(*args, **kwargs) @@ -958,8 +1049,10 @@ pass def get_width_height(self): - """return the figure width and height in points or pixels - (depending on the backend), truncated to integers""" + """ + return the figure width and height in points or pixels + (depending on the backend), truncated to integers + """ return int(self.figure.bbox.width), int(self.figure.bbox.height) filetypes = { @@ -1038,13 +1131,28 @@ face color background and you'll probably want to override this on hardcopy. - filename - can also be a file object on image backends - orientation - only currently applies to PostScript printing. - dpi - the dots per inch to save the figure in; if None, use savefig.dpi - facecolor - the facecolor of the figure - edgecolor - the edgecolor of the figure - orientation - 'landscape' | 'portrait' (not supported on all backends) - format - when set, forcibly set the file format to save to + Arguments are: + + ``filename`` + can also be a file object on image backends + + ``orientation`` + only currently applies to PostScript printing. + + ``dpi`` + the dots per inch to save the figure in; if None, use savefig.dpi + + ``facecolor`` + the facecolor of the figure + + ``edgecolor`` + the edgecolor of the figure + + ``orientation`` ' + landscape' | 'portrait' (not supported on all backends) + + ``format`` + when set, forcibly set the file format to save to """ if format is None: if cbook.is_string_like(filename): @@ -1123,24 +1231,24 @@ where event is a MplEvent. The following events are recognized - * 'resize_event' - * 'draw_event' - * 'key_press_event' - * 'key_release_event' - * 'button_press_event' - * 'button_release_event' - * 'scroll_event' - * 'motion_notify_event' - * 'pick_event' + - 'button_press_event' + - 'button_release_event' + - 'draw_event' + - 'key_press_event' + - 'key_release_event' + - 'motion_notify_event' + - 'pick_event' + - 'resize_event' + - 'scroll_event' For the three events above, if the mouse is over the axes, the variable event.inaxes will be set to the axes it is over, and additionally, the variables event.xdata and event.ydata will be defined. This is the mouse location in data coords. - See backend_bases.MplEvent. + See :class`MplEvent` return value is a connection id that can be used with - mpl_disconnect + :meth:`mpl_disconnect` """ return self.callbacks.connect(s, func) @@ -1162,9 +1270,13 @@ """ Helper class for matlab mode, wraps everything up into a neat bundle - Public attibutes - canvas - A FigureCanvas instance - num - The figure number + Public attibutes: + + ``canvas`` + A :class:`FigureCanvasBase` instance + + ``num`` + The figure nuamber """ def __init__(self, canvas, num): self.canvas = canvas @@ -1248,7 +1360,7 @@ backends must implement a canvas that handles connections for 'button_press_event' and 'button_release_event'. See - FigureCanvas.connect for more information + :meth:`FigureCanvasBase.connect` for more information They must also define @@ -1262,18 +1374,18 @@ * draw_rubberband (optional) : draw the zoom to rect "rubberband" rectangle - * press : (optional) whenever a mouse button is pressed, you'll be + * press : (optional) whenever a mouse button is pressed, you'll be notified with the event - * release : (optional) whenever a mouse button is released, - you'll be notified with the event + * release : (optional) whenever a mouse button is released, + you'll be notified with the event - * dynamic_update (optional) dynamically update the window while - navigating + * dynamic_update (optional) dynamically update the window while + navigating - * set_message (optional) - display message + * set_message (optional) - display message - * set_history_buttons (optional) - you can change the history + * set_history_buttons (optional) - you can change the history back / forward buttons to indicate disabled / enabled state. That's it, we'll do the rest! @@ -1332,8 +1444,8 @@ def _init_toolbar(self): """ This is where you actually build the GUI widgets (called by - __init__). The icons home.xpm, back.xpm, forward.xpm, - hand.xpm, zoom_to_rect.xpm and filesave.xpm are standard + __init__). The icons ``home.xpm``, ``back.xpm``, ``forward.xpm``, + ``hand.xpm``, ``zoom_to_rect.xpm`` and ``filesave.xpm`` are standard across backends (there are ppm versions in CVS also). You just need to set the callbacks @@ -1647,7 +1759,7 @@ def set_cursor(self, cursor): """ - Set the current cursor to one of the backend_bases.Cursors + Set the current cursor to one of the :class:`Cursors` enums values """ pass Modified: trunk/matplotlib/lib/matplotlib/text.py =================================================================== --- trunk/matplotlib/lib/matplotlib/text.py 2008-06-10 15:53:19 UTC (rev 5462) +++ trunk/matplotlib/lib/matplotlib/text.py 2008-06-10 18:08:50 UTC (rev 5463) @@ -42,35 +42,38 @@ # class is build so we define an initial set here for the init # function and they will be overridden after object defn artist.kwdocd['Text'] = """\ - alpha: float - animated: [True | False] - backgroundcolor: any matplotlib color - bbox: rectangle prop dict plus key 'pad' which is a pad in points - clip_box: a matplotlib.transform.Bbox instance - clip_on: [True | False] - color: any matplotlib color - family: [ 'serif' | 'sans-serif' | 'cursive' | 'fantasy' | 'monospace' ] - figure: a matplotlib.figure.Figure instance - fontproperties: a matplotlib.font_manager.FontProperties instance - horizontalalignment or ha: [ 'center' | 'right' | 'left' ] - label: any string - linespacing: float - lod: [True | False] - multialignment: ['left' | 'right' | 'center' ] - name or fontname: string eg, ['Sans' | 'Courier' | 'Helvetica' ...] - position: (x,y) - rotation: [ angle in degrees 'vertical' | 'horizontal' - size or fontsize: [ size in points | relative size eg 'smaller', 'x-large' ] - style or fontstyle: [ 'normal' | 'italic' | 'oblique'] - text: string - transform: a matplotlib.transform transformation instance - variant: [ 'normal' | 'small-caps' ] - verticalalignment or va: [ 'center' | 'top' | 'bottom' | 'baseline' ] - visible: [True | False] - weight or fontweight: [ 'normal' | 'bold' | 'heavy' | 'light' | 'ultrabold' | 'ultralight'] - x: float - y: float - zorder: any number + ========================== ========================================================================= + alpha float + ========================== ========================================================================= + animated [True | False] + backgroundcolor any matplotlib color + bbox rectangle prop dict plus key 'pad' which is a pad in points + clip_box a matplotlib.transform.Bbox instance + clip_on [True | False] + color any matplotlib color + family [ 'serif' | 'sans-serif' | 'cursive' | 'fantasy' | 'monospace' ] + figure a matplotlib.figure.Figure instance + fontproperties a matplotlib.font_manager.FontProperties instance + horizontalalignment or ha [ 'center' | 'right' | 'left' ] + label any string + linespacing float + lod [True | False] + multialignment ['left' | 'right' | 'center' ] + name or fontname string eg, ['Sans' | 'Courier' | 'Helvetica' ...] + position (x,y) + rotation [ angle in degrees 'vertical' | 'horizontal' + size or fontsize [ size in points | relative size eg 'smaller', 'x-large' ] + style or fontstyle [ 'normal' | 'italic' | 'oblique'] + text string + transform a matplotlib.transform transformation instance + variant [ 'normal' | 'small-caps' ] + verticalalignment or va [ 'center' | 'top' | 'bottom' | 'baseline' ] + visible [True | False] + weight or fontweight [ 'normal' | 'bold' | 'heavy' | 'light' | 'ultrabold' | 'ultralight'] + x float + y float + zorder any number + ========================== ========================================================================= """ class Text(Artist): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-06-10 22:49:05
|
Revision: 5465 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5465&view=rev Author: jdh2358 Date: 2008-06-10 15:49:02 -0700 (Tue, 10 Jun 2008) Log Message: ----------- some tweaks to image size and backend docs Modified Paths: -------------- trunk/matplotlib/doc/devel/outline.rst trunk/matplotlib/doc/users/annotations.rst trunk/matplotlib/doc/users/event_handling.rst trunk/matplotlib/doc/users/figures/make.py trunk/matplotlib/doc/users/figures/pyplot_simple.py trunk/matplotlib/doc/users/mathtext.rst trunk/matplotlib/doc/users/pyplot_tutorial.rst trunk/matplotlib/doc/users/text_intro.rst trunk/matplotlib/doc/users/text_props.rst trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/backends/backend_template.py Modified: trunk/matplotlib/doc/devel/outline.rst =================================================================== --- trunk/matplotlib/doc/devel/outline.rst 2008-06-10 18:36:33 UTC (rev 5464) +++ trunk/matplotlib/doc/devel/outline.rst 2008-06-10 22:49:02 UTC (rev 5465) @@ -103,20 +103,20 @@ submission, you can put them here. As the author cleans them up or addresses them, they should be removed. -mathtext user's guide-- reviewd by JDH --------------------------------------- +mathtext user's guide-- reviewed by JDH +--------------------------------------- This looks good (see :ref:`mathtext-tutorial`) -- there are a few -minor things to close the book on this chapter. +minor things to close the book on this chapter: #. The main thing to wrap this up is getting the mathtext module -ported over to rest and included in the API so the links from the -user's guide tutorial work. + ported over to rest and included in the API so the links from the + user's guide tutorial work. #. This section might also benefit from a little more detail on the -customizations that are possible (eg an example fleshing out the rc -options a little bit). Admittedly, this is pretty clear from readin -ghte rc file, but it might be helpful to a newbie. + customizations that are possible (eg an example fleshing out the rc + options a little bit). Admittedly, this is pretty clear from + readin ghte rc file, but it might be helpful to a newbie. #. There is still a TODO in the file to include a complete list of symbols Modified: trunk/matplotlib/doc/users/annotations.rst =================================================================== --- trunk/matplotlib/doc/users/annotations.rst 2008-06-10 18:36:33 UTC (rev 5464) +++ trunk/matplotlib/doc/users/annotations.rst 2008-06-10 22:49:02 UTC (rev 5465) @@ -15,7 +15,7 @@ .. literalinclude:: figures/annotation_basic.py .. image:: figures/annotation_basic.png - :scale: 50 + :scale: 75 In this example, both the ``xy`` (arrow tip) and ``xytext`` locations (text location) are in data coordinates. There are a variety of other @@ -76,7 +76,7 @@ .. literalinclude:: figures/annotation_polar.py .. image:: figures/annotation_polar.png - :scale: 50 + :scale: 75 See the `annotations demo <http://matplotlib.sf.net/examples/pylab_examples/annotation_demo.py>`_ for more Modified: trunk/matplotlib/doc/users/event_handling.rst =================================================================== --- trunk/matplotlib/doc/users/event_handling.rst 2008-06-10 18:36:33 UTC (rev 5464) +++ trunk/matplotlib/doc/users/event_handling.rst 2008-06-10 22:49:02 UTC (rev 5465) @@ -70,16 +70,18 @@ ================ All matplotlib events inherit from the base class -:class:`matplotlib.backend_bases.Event`, which store the attributes +:class:`matplotlib.backend_bases.Event`, which store the attributes: -=============== ================================================= -Event attribute Description -=============== ================================================= -``name`` the event name -``canvas`` the FigureCanvas instance generating the event -``guiEvent`` the GUI event that triggered the matplotlib event -=============== ================================================= + ``name`` + the event name + ``canvas`` + the FigureCanvas instance generating the event + + ``guiEvent`` + the GUI event that triggered the matplotlib event + + The most common events that are the bread and butter of event handling are key press/release events and mouse press/release and movement events. The :class:`~matplotlib.backend_bases.KeyEvent` and @@ -87,17 +89,21 @@ these events are both derived from the LocationEvent, which has the following attributes -======================= ======================================== -LocationEvent attribute Description -======================= ======================================== -``x`` x position - pixels from left of canvas -``y`` y position - pixels from right of canvas -``button`` button pressed None, 1, 2, 3 -``inaxes`` the Axes instance if mouse us over axes -``xdata`` x coord of mouse in data coords -``ydata`` y coord of mouse in data coords -======================= ======================================== + ``x`` + x position - pixels from left of canvas + ``y`` + y position - pixels from bottom of canvas + + ``inaxes`` + the :class:`~matplotlib.axes.Axes` instance if mouse is over axes + + ``xdata`` + x coord of mouse in data coords + + ``ydata`` + y coord of mouse in data coords + Let's look a simple example of a canvas, where a simple line segment is created every time a mouse is pressed:: @@ -129,13 +135,12 @@ the data and pixel coordinates in event.x and event.xdata. In addition to the ``LocationEvent`` attributes, it has -==================== ============================================================== -MouseEvent attribute Description -==================== ============================================================== -``button`` button pressed None, 1, 2, 3 -``key`` the key pressed: None, chr(range(255)), shift, win, or control -==================== ============================================================== + ``button`` + button pressed None, 1, 2, 3, 'up', 'down' (up and down are used for scroll events) + ``key`` + the key pressed: None, chr(range(255), 'shift', 'win', or 'control' + Draggable Rectangle Exercise ---------------------------- @@ -281,7 +286,6 @@ self.rect.set_x(x0+dx) self.rect.set_y(y0+dy) - canvas = self.rect.figure.canvas axes = self.rect.axes # restore the background region @@ -293,8 +297,6 @@ # blit just the redrawn area canvas.blit(axes.bbox) - - def on_release(self, event): 'on release we reset the press data' if DraggableRectangle.lock is not self: @@ -309,6 +311,7 @@ # redraw the full figure self.rect.figure.canvas.draw() + def disconnect(self): 'disconnect all the stored connection ids' self.rect.figure.canvas.mpl_disconnect(self.cidpress) @@ -340,24 +343,29 @@ There are a variety of meanings of the ``picker`` property: -- ``None`` : picking is disabled for this artist (default) + ``None`` + picking is disabled for this artist (default) -- ``boolean`` : if True then picking will be enabled and the artist will - fire a pick event if the mouse event is over the artist + ``boolean`` + if True then picking will be enabled and the artist will fire a + pick event if the mouse event is over the artist -- ``float`` : if picker is a number it is interpreted as an epsilon - tolerance in points and the the artist will fire off an event if its - data is within epsilon of the mouse event. For some artists like - lines and patch collections, the artist may provide additional data - to the pick event that is generated, eg the indices of the data - within epsilon of the pick event. + ``float`` + if picker is a number it is interpreted as an epsilon tolerance in + points and the the artist will fire off an event if its data is + within epsilon of the mouse event. For some artists like lines + and patch collections, the artist may provide additional data to + the pick event that is generated, eg the indices of the data + within epsilon of the pick event. -- ``function`` : if picker is callable, it is a user supplied function - which determines whether the artist is hit by the mouse event. The - signature is ``hit, props = picker(artist, mouseevent)`` to - determine the hit test. If the mouse event is over the artist, - return ``hit=True`` and props is a dictionary of properties you want - added to the :class:`~matplotlib.backend_bases.PickEvent` attributes + ``function`` + if picker is callable, it is a user supplied function which + determines whether the artist is hit by the mouse event. The + signature is ``hit, props = picker(artist, mouseevent)`` to + determine the hit test. If the mouse event is over the artist, + return ``hit=True`` and props is a dictionary of properties you + want added to the :class:`~matplotlib.backend_bases.PickEvent` + attributes After you have enabled an artist for picking by setting the ``picker`` @@ -373,16 +381,18 @@ The :class:`~matplotlib.backend_bases.PickEvent` which is passed to your callback is always fired with two attributes: -- ``mouseevent`` : the mouse event that generate the pick event. The - mouse event in turn has attributes like ``x`` and ``y`` (the coords in - display space, eg pixels from left, bottom) and xdata, ydata (the - coords in data space). Additionally, you can get information about - which buttons were pressed, which keys were pressed, which Axes the - mouse is over, etc. See :class:`matplotlib.backend_bases.MouseEvent` for - details. + ``mouseevent`` the mouse event that generate the pick event. The + mouse event in turn has attributes like ``x`` and ``y`` (the + coords in display space, eg pixels from left, bottom) and xdata, + ydata (the coords in data space). Additionally, you can get + information about which buttons were pressed, which keys were + pressed, which :class:`~matplotlib.axes.Axes` the mouse is over, + etc. See :class:`matplotlib.backend_bases.MouseEvent` for + details. -- ``artist`` : the :class:`matplotlib.artist.Artist` that generated - the pick event. + ``artist`` + the :class:`~matplotlib.artist.Artist` that generated the pick + event. Additionally, certain artists like :class:`~matplotlib.lines.Line2D` and :class:`~matplotlib.collections.PatchCollection` may attach Modified: trunk/matplotlib/doc/users/figures/make.py =================================================================== --- trunk/matplotlib/doc/users/figures/make.py 2008-06-10 18:36:33 UTC (rev 5464) +++ trunk/matplotlib/doc/users/figures/make.py 2008-06-10 22:49:02 UTC (rev 5465) @@ -2,7 +2,7 @@ import sys, os, glob import matplotlib import IPython.Shell -matplotlib.rcdefaults() +#matplotlib.rcdefaults() matplotlib.use('Agg') mplshell = IPython.Shell.MatplotlibShell('mpl') Modified: trunk/matplotlib/doc/users/figures/pyplot_simple.py =================================================================== --- trunk/matplotlib/doc/users/figures/pyplot_simple.py 2008-06-10 18:36:33 UTC (rev 5464) +++ trunk/matplotlib/doc/users/figures/pyplot_simple.py 2008-06-10 22:49:02 UTC (rev 5465) @@ -1,4 +1,4 @@ import matplotlib.pyplot as plt plt.plot([1,2,3]) plt.ylabel('some numbers') - +plt.show() Modified: trunk/matplotlib/doc/users/mathtext.rst =================================================================== --- trunk/matplotlib/doc/users/mathtext.rst 2008-06-10 18:36:33 UTC (rev 5464) +++ trunk/matplotlib/doc/users/mathtext.rst 2008-06-10 22:49:02 UTC (rev 5465) @@ -233,7 +233,7 @@ .. literalinclude:: figures/pyplot_mathtext.py .. image:: figures/pyplot_mathtext.png - :scale: 50 + :scale: 75 Modified: trunk/matplotlib/doc/users/pyplot_tutorial.rst =================================================================== --- trunk/matplotlib/doc/users/pyplot_tutorial.rst 2008-06-10 18:36:33 UTC (rev 5464) +++ trunk/matplotlib/doc/users/pyplot_tutorial.rst 2008-06-10 22:49:02 UTC (rev 5465) @@ -4,18 +4,18 @@ pyplot tutorial *************** -:mod:`matplotlib.pyplot` is a collection of functions that make -matplotlib work like matlab. Each ``pyplot`` function makes some -change to a figure: eg, create a figure, create a plotting area in a -figure, plot some lines in a plotting area, decorate the plot with -labels, etc.... :mod:`matplotlib.pyplot` is stateful, in that it +:mod:`matplotlib.pyplot` is a collection of command style functions +that make matplotlib work like matlab. Each ``pyplot`` function makes +some change to a figure: eg, create a figure, create a plotting area +in a figure, plot some lines in a plotting area, decorate the plot +with labels, etc.... :mod:`matplotlib.pyplot` is stateful, in that it keeps track of the current figure and plotting area, and the plotting functions are directed to the current axes .. literalinclude:: figures/pyplot_simple.py .. image:: figures/pyplot_simple.png - :scale: 50 + :scale: 75 You may be wondering why the x-axis ranges from 0-3 and the y-axis @@ -42,7 +42,7 @@ .. literalinclude:: figures/pyplot_formatstr.py .. image:: figures/pyplot_formatstr.png - :scale: 50 + :scale: 75 See the :func:`~matplotlib.pyplot.plot` documentation for a complete list of line styles and format strings. The @@ -60,10 +60,8 @@ .. literalinclude:: figures/pyplot_three.py .. image:: figures/pyplot_three.png - :scale: 50 + :scale: 75 - - .. _controlling-line-properties: Controlling line properties @@ -169,7 +167,7 @@ .. literalinclude:: figures/pyplot_two_subplots.py .. image:: figures/pyplot_two_subplots.png - :scale: 50 + :scale: 75 The :func:`~matplotlib.pyplot.figure` command here is optional because ``figure(1)`` will be created by default, just as a ``subplot(111)`` @@ -230,7 +228,7 @@ .. literalinclude:: figures/pyplot_text.py .. image:: figures/pyplot_text.png - :scale: 50 + :scale: 75 All of the :func:`~matplotlib.pyplot.text` commands return an @@ -278,7 +276,7 @@ .. literalinclude:: figures/pyplot_annotate.py .. image:: figures/pyplot_annotate.png - :scale: 50 + :scale: 75 In this basic example, both the ``xy`` (arrow tip) and ``xytext`` locations (text location) are in data coordinates. There are a Modified: trunk/matplotlib/doc/users/text_intro.rst =================================================================== --- trunk/matplotlib/doc/users/text_intro.rst 2008-06-10 18:36:33 UTC (rev 5464) +++ trunk/matplotlib/doc/users/text_intro.rst 2008-06-10 22:49:02 UTC (rev 5465) @@ -58,5 +58,5 @@ .. literalinclude:: figures/text_commands.py .. image:: figures/text_commands.png - :scale: 50 + :scale: 75 Modified: trunk/matplotlib/doc/users/text_props.rst =================================================================== --- trunk/matplotlib/doc/users/text_props.rst 2008-06-10 18:36:33 UTC (rev 5464) +++ trunk/matplotlib/doc/users/text_props.rst 2008-06-10 22:49:02 UTC (rev 5465) @@ -60,4 +60,4 @@ .. literalinclude:: figures/text_layout.py .. image:: figures/text_layout.png - :scale: 50 + :scale: 75 Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-06-10 18:36:33 UTC (rev 5464) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-06-10 22:49:02 UTC (rev 5465) @@ -640,6 +640,10 @@ ``canvas`` the FigureCanvas instance generating the event + ``guiEvent`` + the GUI event that triggered the matplotlib event + + """ def __init__(self, name, canvas,guiEvent=None): self.name = name Modified: trunk/matplotlib/lib/matplotlib/backends/backend_template.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_template.py 2008-06-10 18:36:33 UTC (rev 5464) +++ trunk/matplotlib/lib/matplotlib/backends/backend_template.py 2008-06-10 22:49:02 UTC (rev 5465) @@ -1,4 +1,4 @@ -""" +M""" This is a fully functional do nothing backend to provide a template to backend writers. It is fully functional in that you can select it as a backend with This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |