You can subscribe to this list here.
| 2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(115) |
Aug
(120) |
Sep
(137) |
Oct
(170) |
Nov
(461) |
Dec
(263) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2008 |
Jan
(120) |
Feb
(74) |
Mar
(35) |
Apr
(74) |
May
(245) |
Jun
(356) |
Jul
(240) |
Aug
(115) |
Sep
(78) |
Oct
(225) |
Nov
(98) |
Dec
(271) |
| 2009 |
Jan
(132) |
Feb
(84) |
Mar
(74) |
Apr
(56) |
May
(90) |
Jun
(79) |
Jul
(83) |
Aug
(296) |
Sep
(214) |
Oct
(76) |
Nov
(82) |
Dec
(66) |
| 2010 |
Jan
(46) |
Feb
(58) |
Mar
(51) |
Apr
(77) |
May
(58) |
Jun
(126) |
Jul
(128) |
Aug
(64) |
Sep
(50) |
Oct
(44) |
Nov
(48) |
Dec
(54) |
| 2011 |
Jan
(68) |
Feb
(52) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <md...@us...> - 2007-07-30 19:46:57
|
Revision: 3636
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3636&view=rev
Author: mdboom
Date: 2007-07-30 12:46:53 -0700 (Mon, 30 Jul 2007)
Log Message:
-----------
Fix numpification typo affecting mathtext output with Cairo backend.
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py 2007-07-30 18:57:09 UTC (rev 3635)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py 2007-07-30 19:46:53 UTC (rev 3636)
@@ -335,7 +335,7 @@
Xall[:,i] = npy.fromstring(s, npy.uint8)
# get the max alpha at each pixel
- Xs = npy.mlab.max (Xall,1)
+ Xs = npy.max (Xall,1)
# convert it to it's proper shape
Xs.shape = imh, imw
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2007-07-30 18:57:15
|
Revision: 3635
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3635&view=rev
Author: mdboom
Date: 2007-07-30 11:57:09 -0700 (Mon, 30 Jul 2007)
Log Message:
-----------
Improving spacing operators.
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/mathtext.py
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-07-30 18:44:36 UTC (rev 3634)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-07-30 18:57:09 UTC (rev 3635)
@@ -1698,13 +1698,17 @@
space =(FollowedBy(bslash)
+ (Literal(r'\ ')
| Literal(r'\/')
- | Group(Literal(r'\hspace{') + number + Literal('}'))
- )
+ | Literal(r'\,')
+ | Literal(r'\;')
+ | Literal(r'\quad')
+ | Literal(r'\qquad')
+ | Literal(r'\!')
+ )
).setParseAction(self.space).setName('space')
symbol = Regex("(" + ")|(".join(
[
- r"\\(?!left[^a-z])(?!right[^a-z])[a-zA-Z0-9]+(?!{)",
+ r"\\(?!quad)(?!qquad)(?!left[^a-z])(?!right[^a-z])[a-zA-Z0-9]+(?!{)",
r"[a-zA-Z0-9 ]",
r"[+\-*/]",
r"[<>=]",
@@ -1794,7 +1798,7 @@
ambiDelim = oneOf(r"""| \| / \backslash \uparrow \downarrow
\updownarrow \Uparrow \Downarrow
- \Updownarrow""")
+ \Updownarrow .""")
leftDelim = oneOf(r"( [ { \lfloor \langle \lceil")
rightDelim = oneOf(r") ] } \rfloor \rangle \rceil")
autoDelim <<(Suppress(Literal(r"\left"))
@@ -1886,16 +1890,19 @@
state = self.get_state()
metrics = state.font_output.get_metrics(
state.font, 'm', state.fontsize, state.dpi)
- em = metrics.width
- return Hbox(em * percentage)
-
+ em = metrics.advance
+ return Kern(em * percentage)
+
+ _space_widths = { r'\ ' : 0.3,
+ r'\,' : 0.4,
+ r'\;' : 0.8,
+ r'\quad' : 1.6,
+ r'\qquad' : 3.2,
+ r'\!' : -0.4,
+ r'\/' : 0.4 }
def space(self, s, loc, toks):
assert(len(toks)==1)
- if toks[0]==r'\ ': num = 0.30 # 30% of fontsize
- elif toks[0]==r'\/': num = 0.1 # 10% of fontsize
- else: # hspace
- num = float(toks[0][1]) # get the num out of \hspace{num}
-
+ num = self._space_widths[toks[0]]
box = self._make_space(num)
return [box]
@@ -2179,10 +2186,13 @@
state = self.get_state()
height = max([x.height for x in middle])
depth = max([x.depth for x in middle])
- hlist = Hlist(
- [AutoSizedDelim(front, height, depth, state)] +
- middle.asList() +
- [AutoSizedDelim(back, height, depth, state)])
+ parts = []
+ if front != '.':
+ parts.append(AutoSizedDelim(front, height, depth, state))
+ parts.extend(middle.asList())
+ if back != '.':
+ parts.append(AutoSizedDelim(back, height, depth, state))
+ hlist = Hlist(parts)
return hlist
####
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ds...@us...> - 2007-07-30 18:45:42
|
Revision: 3634
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3634&view=rev
Author: dsdale
Date: 2007-07-30 11:44:36 -0700 (Mon, 30 Jul 2007)
Log Message:
-----------
minor changes to traited configs
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/__init__.py
trunk/matplotlib/lib/matplotlib/config/__init__.py
trunk/matplotlib/lib/matplotlib/config/mplconfig.py
trunk/matplotlib/lib/matplotlib/config/mpltraits.py
trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc
Modified: trunk/matplotlib/lib/matplotlib/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/__init__.py 2007-07-30 18:05:14 UTC (rev 3633)
+++ trunk/matplotlib/lib/matplotlib/__init__.py 2007-07-30 18:44:36 UTC (rev 3634)
@@ -708,7 +708,7 @@
rcParams.update(rcParamsDefault)
if NEWCONFIG:
- print "importing from reorganized config system!"
+ #print "importing from reorganized config system!"
from config import rcParams, rcdefaults
try:
from config import mplConfig, save_config
Modified: trunk/matplotlib/lib/matplotlib/config/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/__init__.py 2007-07-30 18:05:14 UTC (rev 3633)
+++ trunk/matplotlib/lib/matplotlib/config/__init__.py 2007-07-30 18:44:36 UTC (rev 3634)
@@ -1,12 +1,12 @@
# Please keep this file empty
-USE_TRAITED_CONFIG = False
+USE_TRAITED_CONFIG = True
from rcparams import rc
from cutils import get_config_file
if USE_TRAITED_CONFIG:
- print 'Using new config system!'
+ #print 'Using new config system!'
from mplconfig import rcParams, mplConfig, save_config, rcdefaults
else:
from rcparams import rcParams, rcdefaults
Modified: trunk/matplotlib/lib/matplotlib/config/mplconfig.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/mplconfig.py 2007-07-30 18:05:14 UTC (rev 3633)
+++ trunk/matplotlib/lib/matplotlib/config/mplconfig.py 2007-07-30 18:44:36 UTC (rev 3634)
@@ -88,7 +88,7 @@
fonttype = T.Trait(3, 42)
class distiller(TConfig):
- use = T.Trait(None, None, 'ghostscript', 'xpdf')
+ use = T.Trait(None, None, 'ghostscript', 'xpdf', False)
resolution = T.Float(6000)
class pdf(TConfig):
@@ -267,7 +267,7 @@
dpi = T.Float(100)
facecolor = T.Trait('white', mplT.ColorHandler())
edgecolor = T.Trait('white', mplT.ColorHandler())
- orientation = T.Trait('portrait', 'portrait', 'landscape')
+ orientation = T.Trait('portrait', 'portrait', 'landscape')
class verbose(TConfig):
level = T.Trait('silent', 'silent', 'helpful', 'debug', 'debug-annoying')
@@ -457,13 +457,19 @@
return self.tconfig_map.has_key(val)
-config_file = cutils.get_config_file(tconfig=True)
old_config_file = cutils.get_config_file(tconfig=False)
+old_config_path = os.path.split(old_config_file)[0]
+config_file = os.path.join(old_config_path, 'matplotlib.conf')
+
if os.path.exists(old_config_file) and not os.path.exists(config_file):
+ print 'convert!'
CONVERT = True
-else: CONVERT = False
+else:
+ config_file = cutils.get_config_file(tconfig=True)
+ CONVERT = False
+
configManager = TConfigManager(MPLConfig,
- cutils.get_config_file(tconfig=True),
+ config_file,
filePriority=True)
mplConfig = configManager.tconf
mplConfigDefault = MPLConfig()
Modified: trunk/matplotlib/lib/matplotlib/config/mpltraits.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/mpltraits.py 2007-07-30 18:05:14 UTC (rev 3633)
+++ trunk/matplotlib/lib/matplotlib/config/mpltraits.py 2007-07-30 18:44:36 UTC (rev 3634)
@@ -32,7 +32,7 @@
'ps': 'PS',
'pdf': 'PDF',
'svg': 'SVG',
- 'template': 'Templates' }
+ 'template': 'Template' }
def validate(self, object, name, value):
try:
@@ -143,4 +143,4 @@
'gist_yarg', 'gist_yarg_r', 'gray', 'gray_r', 'hot', 'hot_r',
'hsv', 'hsv_r', 'jet', 'jet_r', 'pink', 'pink_r',
'prism', 'prism_r', 'spectral', 'spectral_r', 'spring',
- 'spring_r', 'summer', 'summer_r', 'winter', 'winter_r']
\ No newline at end of file
+ 'spring_r', 'summer', 'summer_r', 'winter', 'winter_r']
Modified: trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc
===================================================================
--- trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc 2007-07-30 18:05:14 UTC (rev 3633)
+++ trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc 2007-07-30 18:44:36 UTC (rev 3634)
@@ -243,6 +243,7 @@
#savefig.dpi : 100 # figure dots per inch
#savefig.facecolor : white # figure facecolor when saving
#savefig.edgecolor : white # figure edgecolor when saving
+#savefig.orientation : portrait # portrait or landscape
#cairo.format : png # png, ps, pdf, svg
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2007-07-30 18:05:23
|
Revision: 3633
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3633&view=rev
Author: mdboom
Date: 2007-07-30 11:05:14 -0700 (Mon, 30 Jul 2007)
Log Message:
-----------
Various minor bugfixes.
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/_mathtext_data.py
trunk/matplotlib/lib/matplotlib/mathtext.py
Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2007-07-30 17:41:14 UTC (rev 3632)
+++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2007-07-30 18:05:14 UTC (rev 3633)
@@ -2214,7 +2214,7 @@
'combiningbreve' : 774,
'combiningoverline' : 772,
'combininggraveaccent' : 768,
-'combiningacuteaccent' : 764,
+'combiningacuteaccent' : 714,
'combiningdiaeresis' : 776,
'combiningtilde' : 771,
'combiningrightarrowabove' : 8407,
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-07-30 17:41:14 UTC (rev 3632)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-07-30 18:05:14 UTC (rev 3633)
@@ -617,7 +617,7 @@
return alternatives
return [(fontname, sym)]
-class UnicodeFonts(BakomaFonts):
+class UnicodeFonts(TruetypeFonts):
"""An abstract base class for handling Unicode fonts.
"""
fontmap = { 'cal' : 'cmsy10',
@@ -628,7 +628,7 @@
'sf' : 'DejaVuSans',
None : 'DejaVuSerif-Italic'
}
-
+
def _get_offset(self, cached_font, glyph, fontsize, dpi):
return 0.
@@ -637,6 +637,7 @@
try:
uniindex = get_unicode_index(sym)
+ found_symbol = True
except ValueError:
# This is a total hack, but it works for now
if sym.startswith('\\big'):
@@ -658,7 +659,7 @@
glyphindex = cached_font.charmap[uniindex]
except KeyError:
warn("Font '%s' does not have a glyph for '%s'" %
- (cached_font.postscript_name, sym),
+ (cached_font.font.postscript_name, sym),
MathTextWarning)
found_symbol = False
@@ -2228,7 +2229,7 @@
font_output = BakomaFonts(prop, backend)
# When we have a decent Unicode font, we should test and
# then make this available as an option
- # font_output = UnicodeFonts(prop, backend)
+ #~ font_output = UnicodeFonts(prop, backend)
fontsize = prop.get_size_in_points()
if self._parser is None:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ds...@us...> - 2007-07-30 17:41:37
|
Revision: 3632
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3632&view=rev
Author: dsdale
Date: 2007-07-30 10:41:14 -0700 (Mon, 30 Jul 2007)
Log Message:
-----------
Ability to use new, traited configuration system in mpl
Modified Paths:
--------------
trunk/matplotlib/CHANGELOG
trunk/matplotlib/lib/matplotlib/__init__.py
trunk/matplotlib/lib/matplotlib/config/__init__.py
trunk/matplotlib/lib/matplotlib/config/cutils.py
trunk/matplotlib/lib/matplotlib/config/mplconfig.py
trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc
trunk/matplotlib/setup.py
Removed Paths:
-------------
trunk/matplotlib/lib/matplotlib/config/api.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2007-07-30 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/CHANGELOG 2007-07-30 17:41:14 UTC (rev 3632)
@@ -1,3 +1,12 @@
+2007-07-30 Reorganized configuration code to work with traited config
+ objects. The new config system is located in the
+ matplotlib.config package, but it is disabled by default.
+ To enable it, set NEWCONFIG=True in matplotlib.__init__.py.
+ The new configuration system will still use the old
+ matplotlibrc files by default. To switch to the experimental,
+ traited configuration, set USE_TRAITED_CONFIG=True in
+ config.__init__.py.
+
2007-07-29 Changed default pcolor shading to flat; added aliases
to make collection kwargs agree with setter names, so
updating works; related minor cleanups.
Modified: trunk/matplotlib/lib/matplotlib/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/__init__.py 2007-07-30 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/lib/matplotlib/__init__.py 2007-07-30 17:41:14 UTC (rev 3632)
@@ -55,6 +55,7 @@
"""
from __future__ import generators
+NEWCONFIG = False
__version__ = '0.90.1'
__revision__ = '$Revision$'
@@ -706,6 +707,13 @@
"""
rcParams.update(rcParamsDefault)
+if NEWCONFIG:
+ print "importing from reorganized config system!"
+ from config import rcParams, rcdefaults
+ try:
+ from config import mplConfig, save_config
+ except:
+ pass
def use(arg):
"""
Modified: trunk/matplotlib/lib/matplotlib/config/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/__init__.py 2007-07-30 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/lib/matplotlib/config/__init__.py 2007-07-30 17:41:14 UTC (rev 3632)
@@ -1 +1,12 @@
-# Please keep this file empty
\ No newline at end of file
+# Please keep this file empty
+
+USE_TRAITED_CONFIG = False
+
+from rcparams import rc
+from cutils import get_config_file
+
+if USE_TRAITED_CONFIG:
+ print 'Using new config system!'
+ from mplconfig import rcParams, mplConfig, save_config, rcdefaults
+else:
+ from rcparams import rcParams, rcdefaults
Deleted: trunk/matplotlib/lib/matplotlib/config/api.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/api.py 2007-07-30 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/lib/matplotlib/config/api.py 2007-07-30 17:41:14 UTC (rev 3632)
@@ -1,12 +0,0 @@
-"""
-"""
-
-USE_NEW_CONFIG = True
-
-from rcparams import rc
-from cutils import get_config_file
-
-if USE_NEW_CONFIG:
- from mplconfig import rcParams, mplConfig, save_config
-else:
- from rcparams import rcParams
Modified: trunk/matplotlib/lib/matplotlib/config/cutils.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/cutils.py 2007-07-30 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/lib/matplotlib/config/cutils.py 2007-07-30 17:41:14 UTC (rev 3632)
@@ -179,4 +179,4 @@
fname = os.path.join(path, filename)
if not os.path.exists(fname):
warnings.warn('Could not find %s; using defaults'%filename)
- return fname
\ No newline at end of file
+ return fname
Modified: trunk/matplotlib/lib/matplotlib/config/mplconfig.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/mplconfig.py 2007-07-30 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/lib/matplotlib/config/mplconfig.py 2007-07-30 17:41:14 UTC (rev 3632)
@@ -10,6 +10,7 @@
# internal imports
import mpltraits as mplT
import cutils
+import checkdep
from tconfig import TConfig, TConfigManager
import pytz
@@ -266,210 +267,220 @@
dpi = T.Float(100)
facecolor = T.Trait('white', mplT.ColorHandler())
edgecolor = T.Trait('white', mplT.ColorHandler())
- orientation = T.Trait('portrait', 'portrait', 'landscape')
+ orientation = T.Trait('portrait', 'portrait', 'landscape')
class verbose(TConfig):
level = T.Trait('silent', 'silent', 'helpful', 'debug', 'debug-annoying')
fileo = T.Trait('sys.stdout', 'sys.stdout', T.File)
-config_file = cutils.get_config_file(tconfig=True)
-old_config_file = cutils.get_config_file(tconfig=False)
-print
-if os.path.exists(old_config_file) and not os.path.exists(config_file):
- CONVERT = True
-else: CONVERT = False
-configManager = TConfigManager(MPLConfig,
- cutils.get_config_file(tconfig=True),
- filePriority=True)
-mplConfig = configManager.tconf
-
-
-def save_config():
- """Save mplConfig customizations to current matplotlib.conf
- """
- configManager.write()
-
-
class RcParamsWrapper(dict):
"""A backwards-compatible interface to a traited config object
"""
- tconf = {
- 'backend' : (mplConfig.backend, 'use'),
- 'numerix' : (mplConfig, 'numerix'),
- 'maskedarray' : (mplConfig, 'maskedarray'),
- 'toolbar' : (mplConfig, 'toolbar'),
- 'datapath' : (mplConfig, 'datapath'),
- 'units' : (mplConfig, 'units'),
- 'interactive' : (mplConfig, 'interactive'),
- 'timezone' : (mplConfig, 'timezone'),
+ def __init__(self, tconfig):
+ self.tconfig = tconfig
+
+ self.tconfig_map = {
+ 'backend' : (self.tconfig.backend, 'use'),
+ 'numerix' : (self.tconfig, 'numerix'),
+ 'maskedarray' : (self.tconfig, 'maskedarray'),
+ 'toolbar' : (self.tconfig, 'toolbar'),
+ 'datapath' : (self.tconfig, 'datapath'),
+ 'units' : (self.tconfig, 'units'),
+ 'interactive' : (self.tconfig, 'interactive'),
+ 'timezone' : (self.tconfig, 'timezone'),
- # the verbosity setting
- 'verbose.level' : (mplConfig.verbose, 'level'),
- 'verbose.fileo' : (mplConfig.verbose, 'fileo'),
+ # the verbosity setting
+ 'verbose.level' : (self.tconfig.verbose, 'level'),
+ 'verbose.fileo' : (self.tconfig.verbose, 'fileo'),
- # line props
- 'lines.linewidth' : (mplConfig.lines, 'linewidth'),
- 'lines.linestyle' : (mplConfig.lines, 'linestyle'),
- 'lines.color' : (mplConfig.lines, 'color'),
- 'lines.marker' : (mplConfig.lines, 'marker'),
- 'lines.markeredgewidth' : (mplConfig.lines, 'markeredgewidth'),
- 'lines.markersize' : (mplConfig.lines, 'markersize'),
- 'lines.antialiased' : (mplConfig.lines, 'antialiased'),
- 'lines.dash_joinstyle' : (mplConfig.lines, 'dash_joinstyle'),
- 'lines.solid_joinstyle' : (mplConfig.lines, 'solid_joinstyle'),
- 'lines.dash_capstyle' : (mplConfig.lines, 'dash_capstyle'),
- 'lines.solid_capstyle' : (mplConfig.lines, 'solid_capstyle'),
+ # line props
+ 'lines.linewidth' : (self.tconfig.lines, 'linewidth'),
+ 'lines.linestyle' : (self.tconfig.lines, 'linestyle'),
+ 'lines.color' : (self.tconfig.lines, 'color'),
+ 'lines.marker' : (self.tconfig.lines, 'marker'),
+ 'lines.markeredgewidth' : (self.tconfig.lines, 'markeredgewidth'),
+ 'lines.markersize' : (self.tconfig.lines, 'markersize'),
+ 'lines.antialiased' : (self.tconfig.lines, 'antialiased'),
+ 'lines.dash_joinstyle' : (self.tconfig.lines, 'dash_joinstyle'),
+ 'lines.solid_joinstyle' : (self.tconfig.lines, 'solid_joinstyle'),
+ 'lines.dash_capstyle' : (self.tconfig.lines, 'dash_capstyle'),
+ 'lines.solid_capstyle' : (self.tconfig.lines, 'solid_capstyle'),
- # patch props
- 'patch.linewidth' : (mplConfig.patch, 'linewidth'),
- 'patch.edgecolor' : (mplConfig.patch, 'edgecolor'),
- 'patch.facecolor' : (mplConfig.patch, 'facecolor'),
- 'patch.antialiased' : (mplConfig.patch, 'antialiased'),
+ # patch props
+ 'patch.linewidth' : (self.tconfig.patch, 'linewidth'),
+ 'patch.edgecolor' : (self.tconfig.patch, 'edgecolor'),
+ 'patch.facecolor' : (self.tconfig.patch, 'facecolor'),
+ 'patch.antialiased' : (self.tconfig.patch, 'antialiased'),
- # font props
- 'font.family' : (mplConfig.font, 'family'),
- 'font.style' : (mplConfig.font, 'style'),
- 'font.variant' : (mplConfig.font, 'variant'),
- 'font.stretch' : (mplConfig.lines, 'color'),
- 'font.weight' : (mplConfig.font, 'weight'),
- 'font.size' : (mplConfig.font, 'size'),
- 'font.serif' : (mplConfig.font, 'serif'),
- 'font.sans-serif' : (mplConfig.font, 'sans_serif'),
- 'font.cursive' : (mplConfig.font, 'cursive'),
- 'font.fantasy' : (mplConfig.font, 'fantasy'),
- 'font.monospace' : (mplConfig.font, 'monospace'),
+ # font props
+ 'font.family' : (self.tconfig.font, 'family'),
+ 'font.style' : (self.tconfig.font, 'style'),
+ 'font.variant' : (self.tconfig.font, 'variant'),
+ 'font.stretch' : (self.tconfig.lines, 'color'),
+ 'font.weight' : (self.tconfig.font, 'weight'),
+ 'font.size' : (self.tconfig.font, 'size'),
+ 'font.serif' : (self.tconfig.font, 'serif'),
+ 'font.sans-serif' : (self.tconfig.font, 'sans_serif'),
+ 'font.cursive' : (self.tconfig.font, 'cursive'),
+ 'font.fantasy' : (self.tconfig.font, 'fantasy'),
+ 'font.monospace' : (self.tconfig.font, 'monospace'),
- # text props
- 'text.color' : (mplConfig.text, 'color'),
- 'text.usetex' : (mplConfig.text, 'usetex'),
- 'text.latex.unicode' : (mplConfig.text.latex, 'unicode'),
- 'text.latex.preamble' : (mplConfig.text.latex, 'preamble'),
- 'text.dvipnghack' : (mplConfig.text.latex, 'dvipnghack'),
+ # text props
+ 'text.color' : (self.tconfig.text, 'color'),
+ 'text.usetex' : (self.tconfig.text, 'usetex'),
+ 'text.latex.unicode' : (self.tconfig.text.latex, 'unicode'),
+ 'text.latex.preamble' : (self.tconfig.text.latex, 'preamble'),
+ 'text.dvipnghack' : (self.tconfig.text.latex, 'dvipnghack'),
- 'image.aspect' : (mplConfig.image, 'aspect'),
- 'image.interpolation' : (mplConfig.image, 'interpolation'),
- 'image.cmap' : (mplConfig.image, 'cmap'),
- 'image.lut' : (mplConfig.image, 'lut'),
- 'image.origin' : (mplConfig.image, 'origin'),
+ 'image.aspect' : (self.tconfig.image, 'aspect'),
+ 'image.interpolation' : (self.tconfig.image, 'interpolation'),
+ 'image.cmap' : (self.tconfig.image, 'cmap'),
+ 'image.lut' : (self.tconfig.image, 'lut'),
+ 'image.origin' : (self.tconfig.image, 'origin'),
- 'contour.negative_linestyle' : (mplConfig.contour, 'negative_linestyle'),
+ 'contour.negative_linestyle' : (self.tconfig.contour, 'negative_linestyle'),
- # axes props
- 'axes.axisbelow' : (mplConfig.axes, 'axisbelow'),
- 'axes.hold' : (mplConfig.axes, 'hold'),
- 'axes.facecolor' : (mplConfig.axes, 'facecolor'),
- 'axes.edgecolor' : (mplConfig.axes, 'edgecolor'),
- 'axes.linewidth' : (mplConfig.axes, 'linewidth'),
- 'axes.titlesize' : (mplConfig.axes, 'titlesize'),
- 'axes.grid' : (mplConfig.axes, 'grid'),
- 'axes.labelsize' : (mplConfig.axes, 'labelsize'),
- 'axes.labelcolor' : (mplConfig.axes, 'labelcolor'),
- 'axes.formatter.limits' : (mplConfig.axes.formatter, 'limits'),
+ # axes props
+ 'axes.axisbelow' : (self.tconfig.axes, 'axisbelow'),
+ 'axes.hold' : (self.tconfig.axes, 'hold'),
+ 'axes.facecolor' : (self.tconfig.axes, 'facecolor'),
+ 'axes.edgecolor' : (self.tconfig.axes, 'edgecolor'),
+ 'axes.linewidth' : (self.tconfig.axes, 'linewidth'),
+ 'axes.titlesize' : (self.tconfig.axes, 'titlesize'),
+ 'axes.grid' : (self.tconfig.axes, 'grid'),
+ 'axes.labelsize' : (self.tconfig.axes, 'labelsize'),
+ 'axes.labelcolor' : (self.tconfig.axes, 'labelcolor'),
+ 'axes.formatter.limits' : (self.tconfig.axes.formatter, 'limits'),
- 'polaraxes.grid' : (mplConfig.axes, 'polargrid'),
+ 'polaraxes.grid' : (self.tconfig.axes, 'polargrid'),
- #legend properties
- 'legend.loc' : (mplConfig.legend, 'loc'),
- 'legend.isaxes' : (mplConfig.legend, 'isaxes'),
- 'legend.numpoints' : (mplConfig.legend, 'numpoints'),
- 'legend.fontsize' : (mplConfig.legend, 'fontsize'),
- 'legend.pad' : (mplConfig.legend, 'pad'),
- 'legend.markerscale' : (mplConfig.legend, 'markerscale'),
- 'legend.labelsep' : (mplConfig.legend, 'labelsep'),
- 'legend.handlelen' : (mplConfig.legend, 'handlelen'),
- 'legend.handletextsep' : (mplConfig.legend, 'handletextsep'),
- 'legend.axespad' : (mplConfig.legend, 'axespad'),
- 'legend.shadow' : (mplConfig.legend, 'shadow'),
+ #legend properties
+ 'legend.loc' : (self.tconfig.legend, 'loc'),
+ 'legend.isaxes' : (self.tconfig.legend, 'isaxes'),
+ 'legend.numpoints' : (self.tconfig.legend, 'numpoints'),
+ 'legend.fontsize' : (self.tconfig.legend, 'fontsize'),
+ 'legend.pad' : (self.tconfig.legend, 'pad'),
+ 'legend.markerscale' : (self.tconfig.legend, 'markerscale'),
+ 'legend.labelsep' : (self.tconfig.legend, 'labelsep'),
+ 'legend.handlelen' : (self.tconfig.legend, 'handlelen'),
+ 'legend.handletextsep' : (self.tconfig.legend, 'handletextsep'),
+ 'legend.axespad' : (self.tconfig.legend, 'axespad'),
+ 'legend.shadow' : (self.tconfig.legend, 'shadow'),
- # tick properties
- 'xtick.major.size' : (mplConfig.xticks.major, 'size'),
- 'xtick.minor.size' : (mplConfig.xticks.minor, 'size'),
- 'xtick.major.pad' : (mplConfig.xticks.major, 'pad'),
- 'xtick.minor.pad' : (mplConfig.xticks.minor, 'pad'),
- 'xtick.color' : (mplConfig.xticks, 'color'),
- 'xtick.labelsize' : (mplConfig.xticks, 'labelsize'),
- 'xtick.direction' : (mplConfig.xticks, 'direction'),
+ # tick properties
+ 'xtick.major.size' : (self.tconfig.xticks.major, 'size'),
+ 'xtick.minor.size' : (self.tconfig.xticks.minor, 'size'),
+ 'xtick.major.pad' : (self.tconfig.xticks.major, 'pad'),
+ 'xtick.minor.pad' : (self.tconfig.xticks.minor, 'pad'),
+ 'xtick.color' : (self.tconfig.xticks, 'color'),
+ 'xtick.labelsize' : (self.tconfig.xticks, 'labelsize'),
+ 'xtick.direction' : (self.tconfig.xticks, 'direction'),
- 'ytick.major.size' : (mplConfig.yticks.major, 'size'),
- 'ytick.minor.size' : (mplConfig.yticks.minor, 'size'),
- 'ytick.major.pad' : (mplConfig.yticks.major, 'pad'),
- 'ytick.minor.pad' : (mplConfig.yticks.minor, 'pad'),
- 'ytick.color' : (mplConfig.yticks, 'color'),
- 'ytick.labelsize' : (mplConfig.yticks, 'labelsize'),
- 'ytick.direction' : (mplConfig.yticks, 'direction'),
+ 'ytick.major.size' : (self.tconfig.yticks.major, 'size'),
+ 'ytick.minor.size' : (self.tconfig.yticks.minor, 'size'),
+ 'ytick.major.pad' : (self.tconfig.yticks.major, 'pad'),
+ 'ytick.minor.pad' : (self.tconfig.yticks.minor, 'pad'),
+ 'ytick.color' : (self.tconfig.yticks, 'color'),
+ 'ytick.labelsize' : (self.tconfig.yticks, 'labelsize'),
+ 'ytick.direction' : (self.tconfig.yticks, 'direction'),
- 'grid.color' : (mplConfig.grid, 'color'),
- 'grid.linestyle' : (mplConfig.grid, 'linestyle'),
- 'grid.linewidth' : (mplConfig.grid, 'linewidth'),
+ 'grid.color' : (self.tconfig.grid, 'color'),
+ 'grid.linestyle' : (self.tconfig.grid, 'linestyle'),
+ 'grid.linewidth' : (self.tconfig.grid, 'linewidth'),
- # figure props
- 'figure.figsize' : (mplConfig.figure, 'figsize'),
- 'figure.dpi' : (mplConfig.figure, 'dpi'),
- 'figure.facecolor' : (mplConfig.figure, 'facecolor'),
- 'figure.edgecolor' : (mplConfig.figure, 'edgecolor'),
+ # figure props
+ 'figure.figsize' : (self.tconfig.figure, 'figsize'),
+ 'figure.dpi' : (self.tconfig.figure, 'dpi'),
+ 'figure.facecolor' : (self.tconfig.figure, 'facecolor'),
+ 'figure.edgecolor' : (self.tconfig.figure, 'edgecolor'),
- 'figure.subplot.left' : (mplConfig.figure.subplot, 'left'),
- 'figure.subplot.right' : (mplConfig.figure.subplot, 'right'),
- 'figure.subplot.bottom' : (mplConfig.figure.subplot, 'bottom'),
- 'figure.subplot.top' : (mplConfig.figure.subplot, 'top'),
- 'figure.subplot.wspace' : (mplConfig.figure.subplot, 'wspace'),
- 'figure.subplot.hspace' : (mplConfig.figure.subplot, 'hspace'),
+ 'figure.subplot.left' : (self.tconfig.figure.subplot, 'left'),
+ 'figure.subplot.right' : (self.tconfig.figure.subplot, 'right'),
+ 'figure.subplot.bottom' : (self.tconfig.figure.subplot, 'bottom'),
+ 'figure.subplot.top' : (self.tconfig.figure.subplot, 'top'),
+ 'figure.subplot.wspace' : (self.tconfig.figure.subplot, 'wspace'),
+ 'figure.subplot.hspace' : (self.tconfig.figure.subplot, 'hspace'),
- 'savefig.dpi' : (mplConfig.savefig, 'dpi'),
- 'savefig.facecolor' : (mplConfig.savefig, 'facecolor'),
- 'savefig.edgecolor' : (mplConfig.savefig, 'edgecolor'),
- 'savefig.orientation' : (mplConfig.savefig, 'orientation'),
+ 'savefig.dpi' : (self.tconfig.savefig, 'dpi'),
+ 'savefig.facecolor' : (self.tconfig.savefig, 'facecolor'),
+ 'savefig.edgecolor' : (self.tconfig.savefig, 'edgecolor'),
+ 'savefig.orientation' : (self.tconfig.savefig, 'orientation'),
- 'cairo.format' : (mplConfig.backend.cairo, 'format'),
- 'tk.window_focus' : (mplConfig.backend.tk, 'window_focus'),
- 'tk.pythoninspect' : (mplConfig.backend.tk, 'pythoninspect'),
- 'ps.papersize' : (mplConfig.backend.ps, 'papersize'),
- 'ps.useafm' : (mplConfig.backend.ps, 'useafm'),
- 'ps.usedistiller' : (mplConfig.backend.ps.distiller, 'use'),
- 'ps.distiller.res' : (mplConfig.backend.ps.distiller, 'resolution'),
- 'ps.fonttype' : (mplConfig.backend.ps, 'fonttype'),
- 'pdf.compression' : (mplConfig.backend.pdf, 'compression'),
- 'pdf.inheritcolor' : (mplConfig.backend.pdf, 'inheritcolor'),
- 'pdf.use14corefonts' : (mplConfig.backend.pdf, 'use14corefonts'),
- 'pdf.fonttype' : (mplConfig.backend.pdf, 'fonttype'),
- 'svg.image_inline' : (mplConfig.backend.svg, 'image_inline'),
- 'svg.image_noscale' : (mplConfig.backend.svg, 'image_noscale'),
- 'svg.embed_char_paths' : (mplConfig.backend.svg, 'embed_chars'),
+ 'cairo.format' : (self.tconfig.backend.cairo, 'format'),
+ 'tk.window_focus' : (self.tconfig.backend.tk, 'window_focus'),
+ 'tk.pythoninspect' : (self.tconfig.backend.tk, 'pythoninspect'),
+ 'ps.papersize' : (self.tconfig.backend.ps, 'papersize'),
+ 'ps.useafm' : (self.tconfig.backend.ps, 'useafm'),
+ 'ps.usedistiller' : (self.tconfig.backend.ps.distiller, 'use'),
+ 'ps.distiller.res' : (self.tconfig.backend.ps.distiller, 'resolution'),
+ 'ps.fonttype' : (self.tconfig.backend.ps, 'fonttype'),
+ 'pdf.compression' : (self.tconfig.backend.pdf, 'compression'),
+ 'pdf.inheritcolor' : (self.tconfig.backend.pdf, 'inheritcolor'),
+ 'pdf.use14corefonts' : (self.tconfig.backend.pdf, 'use14corefonts'),
+ 'pdf.fonttype' : (self.tconfig.backend.pdf, 'fonttype'),
+ 'svg.image_inline' : (self.tconfig.backend.svg, 'image_inline'),
+ 'svg.image_noscale' : (self.tconfig.backend.svg, 'image_noscale'),
+ 'svg.embed_char_paths' : (self.tconfig.backend.svg, 'embed_chars'),
- # mathtext settings
- 'mathtext.mathtext2' : (mplConfig.text.math, 'mathtext2'),
- 'mathtext.rm' : (mplConfig.text.math, 'rm'),
- 'mathtext.it' : (mplConfig.text.math, 'it'),
- 'mathtext.tt' : (mplConfig.text.math, 'tt'),
- 'mathtext.mit' : (mplConfig.text.math, 'mit'),
- 'mathtext.cal' : (mplConfig.text.math, 'cal'),
- 'mathtext.nonascii' : (mplConfig.text.math, 'nonascii'),
- }
+ # mathtext settings
+ 'mathtext.mathtext2' : (self.tconfig.text.math, 'mathtext2'),
+ 'mathtext.rm' : (self.tconfig.text.math, 'rm'),
+ 'mathtext.it' : (self.tconfig.text.math, 'it'),
+ 'mathtext.tt' : (self.tconfig.text.math, 'tt'),
+ 'mathtext.mit' : (self.tconfig.text.math, 'mit'),
+ 'mathtext.cal' : (self.tconfig.text.math, 'cal'),
+ 'mathtext.nonascii' : (self.tconfig.text.math, 'nonascii'),
+ }
def __setitem__(self, key, val):
try:
- obj, attr = self.tconf[key]
+ obj, attr = self.tconfig_map[key]
setattr(obj, attr, val)
except KeyError:
raise KeyError('%s is not a valid rc parameter.\
See rcParams.keys() for a list of valid parameters.'%key)
def __getitem__(self, key):
- obj, attr = self.tconf[key]
+ obj, attr = self.tconfig_map[key]
return getattr(obj, attr)
- def keys():
- return self.tconf.keys()
+ def keys(self):
+ return self.tconfig_map.keys()
+
+ def has_key(self, val):
+ return self.tconfig_map.has_key(val)
-rcParams = RcParamsWrapper()
+config_file = cutils.get_config_file(tconfig=True)
+old_config_file = cutils.get_config_file(tconfig=False)
+if os.path.exists(old_config_file) and not os.path.exists(config_file):
+ CONVERT = True
+else: CONVERT = False
+configManager = TConfigManager(MPLConfig,
+ cutils.get_config_file(tconfig=True),
+ filePriority=True)
+mplConfig = configManager.tconf
+mplConfigDefault = MPLConfig()
+# TODO: move into traits validation
+mplConfig.backend.ps.distiller.use = \
+ checkdep.ps_distiller(mplConfig.backend.ps.distiller.use)
+mplConfig.text.usetex = checkdep.usetex(mplConfig.text.usetex)
+
+def save_config():
+ """Save mplConfig customizations to current matplotlib.conf
+ """
+ configManager.write()
+
+rcParams = RcParamsWrapper(mplConfig)
+rcParamsDefault = RcParamsWrapper(mplConfigDefault)
+
# convert old matplotlibrc to new matplotlib.conf
if CONVERT:
from rcparams import rcParams as old_rcParams
@@ -479,6 +490,10 @@
print '%s converted to %s'%(cutils.get_config_file(tconfig=False),
config_file)
+def rcdefaults():
+ mplConfig = MPLConfig()
+ rcParams = RcParamsWrapper(mplConfig)
+
##############################################################################
# Simple testing
##############################################################################
Modified: trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc
===================================================================
--- trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc 2007-07-30 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc 2007-07-30 17:41:14 UTC (rev 3632)
@@ -34,7 +34,6 @@
#interactive : False # see http://matplotlib.sourceforge.net/interactive.html
#toolbar : toolbar2 # None | classic | toolbar2
#timezone : UTC # a pytz timezone string, eg US/Central or Europe/Paris
-#units : False
# Where your matplotlib data lives if you installed to a non-default
# location. This is where the matplotlib fonts, bitmaps, etc reside
@@ -197,7 +196,6 @@
#grid.linewidth : 0.5 # in points
### Legend
-#legend.loc : upper right
#legend.isaxes : True
#legend.numpoints : 2 # the number of points in the legend line
#legend.fontsize : 14
@@ -245,7 +243,6 @@
#savefig.dpi : 100 # figure dots per inch
#savefig.facecolor : white # figure facecolor when saving
#savefig.edgecolor : white # figure edgecolor when saving
-#savefig.orientation: portrait
#cairo.format : png # png, ps, pdf, svg
@@ -267,8 +264,6 @@
#pdf.compression : 6 # integer from 0 to 9
# 0 disables compression (good for debugging)
#pdf.fonttype : 3 # Output Type 3 (Type3) or Type 42 (TrueType)
-#pdf.inheritcolor : False
-#pdf.use14corefonts : False
# svg backend params
#svg.image_inline : True # write raster image data directly into the svg file
Modified: trunk/matplotlib/setup.py
===================================================================
--- trunk/matplotlib/setup.py 2007-07-30 16:41:53 UTC (rev 3631)
+++ trunk/matplotlib/setup.py 2007-07-30 17:41:14 UTC (rev 3632)
@@ -130,7 +130,7 @@
'matplotlib.numerix.linear_algebra',
'matplotlib.numerix.random_array',
'matplotlib.numerix.fft',
-
+ 'matplotlib.config'
]
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2007-07-30 16:41:56
|
Revision: 3631
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3631&view=rev
Author: mdboom
Date: 2007-07-30 09:41:53 -0700 (Mon, 30 Jul 2007)
Log Message:
-----------
Major refactor to separate out backend-specific stuff from
fontset-specific stuff. What used to be the Fonts class heirarchy is
now both a Fonts heirarchy and MathtextBackend heirarchy. This should
be further improved in the future when the backends themselves are
refactored to be more consistent.
Now uses the multi-sized delimiters in the BaKoMa fonts. This
prevents the square root symbol from getting overly wide as it gets
tall. (As auto-sized parens, brackets and braces etc.)
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/_mathtext_data.py
trunk/matplotlib/lib/matplotlib/mathtext.py
Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2007-07-30 07:03:47 UTC (rev 3630)
+++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2007-07-30 16:41:53 UTC (rev 3631)
@@ -14,8 +14,9 @@
print charcode, glyphind
"""
-latex_to_bakoma = {
+from sets import Set
+latex_to_bakoma = {
r'\oint' : ('cmex10', 45),
r'\bigodot' : ('cmex10', 50),
r'\bigoplus' : ('cmex10', 55),
@@ -29,13 +30,7 @@
r'\bigwedge' : ('cmex10', 4),
r'\bigvee' : ('cmex10', 37),
r'\coprod' : ('cmex10', 42),
- r'\Leftbracket' : ('cmex10', 29),
- r'\Rightbracket' : ('cmex10', 61),
- r'\Leftbrace' : ('cmex10', 43),
- r'\Rightbrace' : ('cmex10', 16),
r'\sqrt' : ('cmex10', 48),
- r'\Sqrt' : ('cmex10', 21),
- r'\SQRT' : ('cmex10', 53),
r'\leftbrace' : ('cmex10', 92),
r'{' : ('cmex10', 92),
r'\{' : ('cmex10', 92),
@@ -44,16 +39,6 @@
r'\}' : ('cmex10', 130),
r'\leftangle' : ('cmex10', 97),
r'\rightangle' : ('cmex10', 64),
- r'\Leftparen' : ('cmex10', 112),
- r'\Rightparen' : ('cmex10', 81),
- r'\LEFTparen' : ('cmex10', 119),
- r'\RIGHTparen' : ('cmex10', 87),
- r'\LEFTbracket' : ('cmex10', 125),
- r'\RIGHTbracket' : ('cmex10', 93),
- r'\LEFTbrace' : ('cmex10', 70),
- r'\RIGHTbrace' : ('cmex10', 107),
- r'\LEFTangle' : ('cmex10', 76),
- r'\RIGHTangle' : ('cmex10', 113),
r'\omega' : ('cmmi10', 29),
r'\varepsilon' : ('cmmi10', 20),
@@ -144,15 +129,15 @@
# these are mathml names, I think. I'm just using them for the
# tex methods noted
- r'\circumflexaccent' : ('cmr10', 124), # for \hat
- r'\combiningbreve' : ('cmr10', 81), # for \breve
- r'\combiningoverline' : ('cmr10', 131), # for \bar
- r'\combininggraveaccent' : ('cmr10', 114), # for \grave
- r'\combiningacuteaccent' : ('cmr10', 63), # for \accute
- r'\combiningdiaeresis' : ('cmr10', 91), # for \ddot
- r'\combiningtilde' : ('cmr10', 75), # for \tilde
+ r'\circumflexaccent' : ('cmr10', 124), # for \hat
+ r'\combiningbreve' : ('cmr10', 81), # for \breve
+ r'\combiningoverline' : ('cmr10', 131), # for \bar
+ r'\combininggraveaccent' : ('cmr10', 114), # for \grave
+ r'\combiningacuteaccent' : ('cmr10', 63), # for \accute
+ r'\combiningdiaeresis' : ('cmr10', 91), # for \ddot
+ r'\combiningtilde' : ('cmr10', 75), # for \tilde
r'\combiningrightarrowabove' : ('cmmi10', 110), # for \vec
- r'\combiningdotabove' : ('cmr10', 26), # for \dot
+ r'\combiningdotabove' : ('cmr10', 26), # for \dot
r'\leftarrow' : ('cmsy10', 10),
r'\uparrow' : ('cmsy10', 25),
@@ -199,8 +184,6 @@
r'\rceil' : ('cmsy10', 81),
r'\lbrace' : ('cmsy10', 92),
r'\rbrace' : ('cmsy10', 105),
- r'\langle' : ('cmsy10', 3),
- r'\rangle' : ('cmsy10', 88),
r'\mid' : ('cmsy10', 47),
r'\vert' : ('cmsy10', 47),
r'\Vert' : ('cmsy10', 44),
@@ -258,417 +241,6 @@
r'\spadesuit' : ('cmsy10', 7),
}
-# the kerning dictionary in design space units
-cmkern = {
- 'cmr10' :
- {
- ('A', 't') : -0.027779,
- ('A', 'C') : -0.027779,
- ('A', 'O') : -0.027779,
- ('A', 'G') : -0.027779,
- ('A', 'U') : -0.027779,
- ('A', 'Q') : -0.027779,
- ('A', 'T') : -0.083334,
- ('A', 'Y') : -0.083334,
- ('A', 'V') : -0.111112,
- ('A', 'W') : -0.111112,
- ('D', 'X') : -0.027779,
- ('D', 'W') : -0.027779,
- ('D', 'A') : -0.027779,
- ('D', 'V') : -0.027779,
- ('D', 'Y') : -0.027779,
- ('F', 'o') : -0.083334,
- ('F', 'e') : -0.083334,
- ('F', 'u') : -0.083334,
- ('F', 'r') : -0.083334,
- ('F', 'a') : -0.083334,
- ('F', 'A') : -0.111112,
- ('F', 'O') : -0.027779,
- ('F', 'C') : -0.027779,
- ('F', 'G') : -0.027779,
- ('F', 'Q') : -0.027779,
- ('I', 'I') : 0.027779,
- ('K', 'O') : -0.027779,
- ('K', 'C') : -0.027779,
- ('K', 'G') : -0.027779,
- ('K', 'Q') : -0.027779,
- ('L', 'T') : -0.083334,
- ('L', 'Y') : -0.083334,
- ('L', 'V') : -0.111112,
- ('L', 'W') : -0.111112,
- ('O', 'X') : -0.027779,
- ('O', 'W') : -0.027779,
- ('O', 'A') : -0.027779,
- ('O', 'V') : -0.027779,
- ('O', 'Y') : -0.027779,
- ('P', 'A') : -0.083334,
- ('P', 'o') : -0.027779,
- ('P', 'e') : -0.027779,
- ('P', 'a') : -0.027779,
- ('R', 't') : -0.027779,
- ('R', 'C') : -0.027779,
- ('R', 'O') : -0.027779,
- ('R', 'G') : -0.027779,
- ('R', 'U') : -0.027779,
- ('R', 'Q') : -0.027779,
- ('R', 'T') : -0.083334,
- ('R', 'Y') : -0.083334,
- ('R', 'V') : -0.111112,
- ('R', 'W') : -0.111112,
- ('T', 'y') : -0.027779,
- ('T', 'e') : -0.083334,
- ('T', 'o') : -0.083334,
- ('T', 'r') : -0.083334,
- ('T', 'a') : -0.083334,
- ('T', 'A') : -0.083334,
- ('T', 'u') : -0.083334,
- ('V', 'o') : -0.083334,
- ('V', 'e') : -0.083334,
- ('V', 'u') : -0.083334,
- ('V', 'r') : -0.083334,
- ('V', 'a') : -0.083334,
- ('V', 'A') : -0.111112,
- ('V', 'O') : -0.027779,
- ('V', 'C') : -0.027779,
- ('V', 'G') : -0.027779,
- ('V', 'Q') : -0.027779,
- ('W', 'o') : -0.083334,
- ('W', 'e') : -0.083334,
- ('W', 'u') : -0.083334,
- ('W', 'r') : -0.083334,
- ('W', 'a') : -0.083334,
- ('W', 'A') : -0.111112,
- ('W', 'O') : -0.027779,
- ('W', 'C') : -0.027779,
- ('W', 'G') : -0.027779,
- ('W', 'Q') : -0.027779,
- ('X', 'O') : -0.027779,
- ('X', 'C') : -0.027779,
- ('X', 'G') : -0.027779,
- ('X', 'Q') : -0.027779,
- ('Y', 'e') : -0.083334,
- ('Y', 'o') : -0.083334,
- ('Y', 'r') : -0.083334,
- ('Y', 'a') : -0.083334,
- ('Y', 'A') : -0.083334,
- ('Y', 'u') : -0.083334,
- ('a', 'v') : -0.027779,
- ('a', 'j') : 0.055555,
- ('a', 'y') : -0.027779,
- ('a', 'w') : -0.027779,
- ('b', 'e') : 0.027779,
- ('b', 'o') : 0.027779,
- ('b', 'x') : -0.027779,
- ('b', 'd') : 0.027779,
- ('b', 'c') : 0.027779,
- ('b', 'q') : 0.027779,
- ('b', 'v') : -0.027779,
- ('b', 'j') : 0.055555,
- ('b', 'y') : -0.027779,
- ('b', 'w') : -0.027779,
- ('c', 'h') : -0.027779,
- ('c', 'k') : -0.027779,
- ('g', 'j') : 0.027779,
- ('h', 't') : -0.027779,
- ('h', 'u') : -0.027779,
- ('h', 'b') : -0.027779,
- ('h', 'y') : -0.027779,
- ('h', 'v') : -0.027779,
- ('h', 'w') : -0.027779,
- ('k', 'a') : -0.055555,
- ('k', 'e') : -0.027779,
- ('k', 'a') : -0.027779,
- ('k', 'o') : -0.027779,
- ('k', 'c') : -0.027779,
- ('m', 't') : -0.027779,
- ('m', 'u') : -0.027779,
- ('m', 'b') : -0.027779,
- ('m', 'y') : -0.027779,
- ('m', 'v') : -0.027779,
- ('m', 'w') : -0.027779,
- ('n', 't') : -0.027779,
- ('n', 'u') : -0.027779,
- ('n', 'b') : -0.027779,
- ('n', 'y') : -0.027779,
- ('n', 'v') : -0.027779,
- ('n', 'w') : -0.027779,
- ('o', 'e') : 0.027779,
- ('o', 'o') : 0.027779,
- ('o', 'x') : -0.027779,
- ('o', 'd') : 0.027779,
- ('o', 'c') : 0.027779,
- ('o', 'q') : 0.027779,
- ('o', 'v') : -0.027779,
- ('o', 'j') : 0.055555,
- ('o', 'y') : -0.027779,
- ('o', 'w') : -0.027779,
- ('p', 'e') : 0.027779,
- ('p', 'o') : 0.027779,
- ('p', 'x') : -0.027779,
- ('p', 'd') : 0.027779,
- ('p', 'c') : 0.027779,
- ('p', 'q') : 0.027779,
- ('p', 'v') : -0.027779,
- ('p', 'j') : 0.055555,
- ('p', 'y') : -0.027779,
- ('p', 'w') : -0.027779,
- ('t', 'y') : -0.027779,
- ('t', 'w') : -0.027779,
- ('u', 'w') : -0.027779,
- ('v', 'a') : -0.055555,
- ('v', 'e') : -0.027779,
- ('v', 'a') : -0.027779,
- ('v', 'o') : -0.027779,
- ('v', 'c') : -0.027779,
- ('w', 'e') : -0.027779,
- ('w', 'a') : -0.027779,
- ('w', 'o') : -0.027779,
- ('w', 'c') : -0.027779,
- ('y', 'o') : -0.027779,
- ('y', 'e') : -0.027779,
- ('y', 'a') : -0.027779,
- },
- 'cmex10' : {},
- 'cmtt10' : {},
- 'cmsy10' : {},
- 'cmmi10' :
- {
- ('9', 'A') : -0.055555,
- ('9', 'M') : -0.055555,
- ('9', 'N') : -0.055555,
- ('9', 'Y') : 0.055555,
- ('9', 'Z') : -0.055555,
- ('d', 'Y') : 0.055555,
- ('d', 'Z') : -0.055555,
- ('d', 'j') : -0.111112,
- ('d', 'f') : -0.166667,
- },
- }
-ams_type1 = {
- r'\Leftbracket' : ( 'cmex10', '02'),
- r'\Rightbracket' : ( 'cmex10', '03'),
- r'\Leftbrace' : ( 'cmex10', '08'),
- r'\leftbrace' : ( 'cmex10', '08'),
- '{' : ( 'cmex10', '08'),
- r'\Rightbrace' : ( 'cmex10', '09'),
- r'\rightbrace' : ( 'cmex10', '09'),
- '}' : ( 'cmex10', '09'),
- r'\Leftparen' : ( 'cmex10', '10'),
- r'\Rightparen' : ( 'cmex10', '11'),
- r'\LEFTparen' : ( 'cmex10', '20'),
- r'\RIGHTparen' : ( 'cmex10', '21'),
- r'\LEFTbracket' : ( 'cmex10', '22'),
- r'\RIGHTbracket' : ( 'cmex10', '23'),
- '6' : ( 'cmex10', '26'),
- '(' : ( 'cmex10', '28'),
- r'\LEFTbrace' : ( 'cmex10', '28'),
- r'\leftparen' : ( 'cmex10', '28'),
- ')' : ( 'cmex10', '29'),
- r'\RIGHTbrace' : ( 'cmex10', '29'),
- r'\rightparen' : ( 'cmex10', '29'),
- r'\LEFTangle' : ( 'cmex10', '2A'),
- '+' : ( 'cmex10', '2B'),
- '0' : ( 'cmex10', '30'),
- '1' : ( 'cmex10', '31'),
- '2' : ( 'cmex10', '32'),
- '3' : ( 'cmex10', '33'),
- '4' : ( 'cmex10', '34'),
- '5' : ( 'cmex10', '35'),
- '7' : ( 'cmex10', '37'),
- '8' : ( 'cmex10', '38'),
- '9' : ( 'cmex10', '39'),
- ':' : ( 'cmex10', '3A'),
- ';' : ( 'cmex10', '3B'),
- '=' : ( 'cmex10', '3D'),
- r'\leftangle' : ( 'cmex10', '44'),
- r'\rightangle' : ( 'cmex10', '45'),
- r'\oint' : ( 'cmex10', '49'),
- r'\bigodot' : ( 'cmex10', '4B'),
- r'\bigoplus' : ( 'cmex10', '4D'),
- r'\bigotimes' : ( 'cmex10', '4F'),
- r'\sum' : ( 'cmex10', '58'),
- r'\prod' : ( 'cmex10', '59'),
- r'\int' : ( 'cmex10', '5A'),
- '[' : ( 'cmex10', '5B'),
- r'\bigcup' : ( 'cmex10', '5B'),
- r'\leftbracket' : ( 'cmex10', '5B'),
- r'\bigcap' : ( 'cmex10', '5C'),
- r'\biguplus' : ( 'cmex10', '5D'),
- r'\rightbracket' : ( 'cmex10', '5D'),
- ']' : ( 'cmex10', '5D'),
- r'\bigwedge' : ( 'cmex10', '5E'),
- r'\bigvee' : ( 'cmex10', '5F'),
- r'\coprod' : ( 'cmex10', '61'),
- r'\Sqrt' : ( 'cmex10', '70'),
- r'\sqrt' : ( 'cmex10', '70'),
- r'\SQRT' : ( 'cmex10', '72'),
- r'\Sigma' : ( 'cmmi10', '06'),
- r'\Upsilon' : ( 'cmmi10', '07'),
- r'\Phi' : ( 'cmmi10', '08'),
- r'\Psi' : ( 'cmmi10', '09'),
- r'\alpha' : ( 'cmmi10', '0B'),
- r'\beta' : ( 'cmmi10', '0C'),
- r'\gamma' : ( 'cmmi10', '0D'),
- r'\delta' : ( 'cmmi10', '0E'),
- r'\epsilon' : ( 'cmmi10', '0F'),
- r'\zeta' : ( 'cmmi10', '10'),
- r'\eta' : ( 'cmmi10', '11'),
- r'\theta' : ( 'cmmi10', '12'),
- r'\iota' : ( 'cmmi10', '13'),
- r'\lambda' : ( 'cmmi10', '15'),
- r'\mu' : ( 'cmmi10', '16'),
- r'\nu' : ( 'cmmi10', '17'),
- r'\xi' : ( 'cmmi10', '18'),
- r'\pi' : ( 'cmmi10', '19'),
- r'\kappa' : ( 'cmmi10', '19'),
- r'\rho' : ( 'cmmi10', '1A'),
- r'\sigma' : ( 'cmmi10', '1B'),
- r'\tau' : ( 'cmmi10', '1C'),
- r'\upsilon' : ( 'cmmi10', '1D'),
- r'\phi' : ( 'cmmi10', '1E'),
- r'\chi' : ( 'cmmi10', '1F'),
- r'\psi' : ( 'cmmi10', '20'),
- r'\omega' : ( 'cmmi10', '21'),
- r'\varepsilon' : ( 'cmmi10', '22'),
- r'\vartheta' : ( 'cmmi10', '23'),
- r'\varrho' : ( 'cmmi10', '25'),
- r'\varsigma' : ( 'cmmi10', '26'),
- r'\varphi' : ( 'cmmi10', '27'),
- r'\leftharpoonup' : ( 'cmmi10', '28'),
- r'\leftharpoondown' : ( 'cmmi10', '29'),
- r'\rightharpoonup' : ( 'cmmi10', '2A'),
- r'\rightharpoondown' : ( 'cmmi10', '2B'),
- r'\triangleright' : ( 'cmmi10', '2E'),
- r'\triangleleft' : ( 'cmmi10', '2F'),
- '.' : ( 'cmmi10', '3A'),
- ',' : ( 'cmmi10', '3B'),
- '<' : ( 'cmmi10', '3C'),
- '/' : ( 'cmmi10', '3D'),
- '>' : ( 'cmmi10', '3E'),
- r'\flat' : ( 'cmmi10', '5B'),
- r'\natural' : ( 'cmmi10', '5C'),
- r'\sharp' : ( 'cmmi10', '5D'),
- r'\smile' : ( 'cmmi10', '5E'),
- r'\frown' : ( 'cmmi10', '5F'),
- r'\ell' : ( 'cmmi10', '60'),
- r'\imath' : ( 'cmmi10', '7B'),
- r'\jmath' : ( 'cmmi10', '7C'),
- r'\wp' : ( 'cmmi10', '7D'),
- r'\Gamma' : ( 'cmr10', '00'),
- r'\Delta' : ( 'cmr10', '01'),
- r'\Theta' : ( 'cmr10', '02'),
- r'\Lambda' : ( 'cmr10', '03'),
- r'\Xi' : ( 'cmr10', '04'),
- r'\Pi' : ( 'cmr10', '05'),
- r'\Omega' : ( 'cmr10', '0A'),
- '-' : ( 'cmsy10', '00'),
- r'\cdot' : ( 'cmsy10', '01'),
- r'\times' : ( 'cmsy10', '02'),
- '*' : ( 'cmsy10', '03'),
- r'\ast' : ( 'cmsy10', '03'),
- r'\div' : ( 'cmsy10', '04'),
- r'\diamond' : ( 'cmsy10', '05'),
- r'\pm' : ( 'cmsy10', '06'),
- r'\mp' : ( 'cmsy10', '07'),
- r'\oplus' : ( 'cmsy10', '08'),
- r'\ominus' : ( 'cmsy10', '09'),
- r'\otimes' : ( 'cmsy10', '0A'),
- r'\oslash' : ( 'cmsy10', '0B'),
- r'\odot' : ( 'cmsy10', '0C'),
- r'\bigcirc' : ( 'cmsy10', '0D'),
- r'\circ' : ( 'cmsy10', '0E'),
- r'\bullet' : ( 'cmsy10', '0F'),
- r'\simeq' : ( 'cmsy10', '10'),
- r'\asymp' : ( 'cmsy10', '11'),
- r'\subseteq' : ( 'cmsy10', '12'),
- r'\supseteq' : ( 'cmsy10', '13'),
- r'\leq' : ( 'cmsy10', '14'),
- r'\geq' : ( 'cmsy10', '15'),
- r'\preceq' : ( 'cmsy10', '16'),
- r'\succeq' : ( 'cmsy10', '17'),
- r'\sim' : ( 'cmsy10', '18'),
- r'\approx' : ( 'cmsy10', '19'),
- r'\subset' : ( 'cmsy10', '1A'),
- r'\supset' : ( 'cmsy10', '1B'),
- r'\ll' : ( 'cmsy10', '1C'),
- r'\gg' : ( 'cmsy10', '1D'),
- r'\prec' : ( 'cmsy10', '1E'),
- r'\succ' : ( 'cmsy10', '1F'),
- r'\rightarrow' : ( 'cmsy10', '20'),
- r'\leftarrow' : ( 'cmsy10', '21'),
- r'\uparrow' : ( 'cmsy10', '22'),
- r'\downarrow' : ( 'cmsy10', '23'),
- r'\leftrightarrow' : ( 'cmsy10', '24'),
- r'\nearrow' : ( 'cmsy10', '25'),
- r'\searrow' : ( 'cmsy10', '26'),
- r'\Leftarrow' : ( 'cmsy10', '28'),
- r'\Rightarrow' : ( 'cmsy10', '29'),
- r'\Uparrow' : ( 'cmsy10', '2A'),
- r'\Downarrow' : ( 'cmsy10', '2B'),
- r'\Leftrightarrow' : ( 'cmsy10', '2C'),
- r'\nwarrow' : ( 'cmsy10', '2D'),
- r'\swarrow' : ( 'cmsy10', '2E'),
- r'\propto' : ( 'cmsy10', '2F'),
- r'\prime' : ( 'cmsy10', '30'),
- r'\infty' : ( 'cmsy10', '31'),
- r'\in' : ( 'cmsy10', '32'),
- r'\ni' : ( 'cmsy10', '33'),
- r'\bigtriangleup' : ( 'cmsy10', '34'),
- r'\bigtriangledown' : ( 'cmsy10', '35'),
- r'\slash' : ( 'cmsy10', '36'),
- r'\forall' : ( 'cmsy10', '38'),
- r'\exists' : ( 'cmsy10', '39'),
- r'\neg' : ( 'cmsy10', '3A'),
- r'\emptyset' : ( 'cmsy10', '3B'),
- r'\Re' : ( 'cmsy10', '3C'),
- r'\Im' : ( 'cmsy10', '3D'),
- r'\top' : ( 'cmsy10', '3E'),
- r'\bot' : ( 'cmsy10', '3F'),
- r'\aleph' : ( 'cmsy10', '40'),
- r'\cup' : ( 'cmsy10', '5B'),
- r'\cap' : ( 'cmsy10', '5C'),
- r'\uplus' : ( 'cmsy10', '5D'),
- r'\wedge' : ( 'cmsy10', '5E'),
- r'\vee' : ( 'cmsy10', '5F'),
- r'\vdash' : ( 'cmsy10', '60'),
- r'\dashv' : ( 'cmsy10', '61'),
- r'\lfloor' : ( 'cmsy10', '62'),
- r'\rfloor' : ( 'cmsy10', '63'),
- r'\lceil' : ( 'cmsy10', '64'),
- r'\rceil' : ( 'cmsy10', '65'),
- r'\lbrace' : ( 'cmsy10', '66'),
- r'\rbrace' : ( 'cmsy10', '67'),
- r'\langle' : ( 'cmsy10', '68'),
- r'\rangle' : ( 'cmsy10', '69'),
- r'\mid' : ( 'cmsy10', '6A'),
- r'\vert' : ( 'cmsy10', '6A'),
- r'\Vert' : ( 'cmsy10', '6B'),
- r'\updownarrow' : ( 'cmsy10', '6C'),
- r'\Updownarrow' : ( 'cmsy10', '6D'),
- r'\backslash' : ( 'cmsy10', '6E'),
- r'\wr' : ( 'cmsy10', '6F'),
- r'\nabla' : ( 'cmsy10', '72'),
- r'\sqcup' : ( 'cmsy10', '74'),
- r'\sqcap' : ( 'cmsy10', '75'),
- r'\sqsubseteq' : ( 'cmsy10', '76'),
- r'\sqsupseteq' : ( 'cmsy10', '77'),
- r'\S' : ( 'cmsy10', '78'),
- r'\dag' : ( 'cmsy10', '79'),
- r'\ddag' : ( 'cmsy10', '7A'),
- r'\P' : ( 'cmsy10', '7B'),
- r'\clubsuit' : ( 'cmsy10', '7C'),
- r'\diamondsuit' : ( 'cmsy10', '7D'),
- r'\heartsuit' : ( 'cmsy10', '7E'),
- r'\spadesuit' : ( 'cmsy10', '7F'),
-}
-
-"""
-no mlname for \RIGHTangle
-no type1 key \equiv # could not find in ASM
-no type1 key \kappa # could not find kappa
-no type1 key \RIGHTangle # could not find
-"""
-
latex_to_standard = {
r'\cong' : ('psyr', 64),
r'\Delta' : ('psyr', 68),
@@ -757,17 +329,60 @@
r'\langle' : ('psyr', 225),
r'\Sigma' : ('psyr', 229),
r'\sum' : ('psyr', 229),
- # these are mathml names, I think. I'm just using them for the
- # tex methods noted
- r'\circumflexaccent' : ('pncri8a', 124), # for \hat
- r'\combiningbreve' : ('pncri8a', 81), # for \breve
- r'\combininggraveaccent' : ('pncri8a', 114), # for \grave
- r'\combiningacuteaccent' : ('pncri8a', 63), # for \accute
- r'\combiningdiaeresis' : ('pncri8a', 91), # for \ddot
- r'\combiningtilde' : ('pncri8a', 75), # for \tilde
+ r'\forall' : ('psyr', 34),
+ r'\exists' : ('psyr', 36),
+ r'\lceil' : ('psyr', 233),
+ r'\lbrace' : ('psyr', 123),
+ r'\Psi' : ('psyr', 89),
+ r'\bot' : ('psyr', 0136),
+ r'\Omega' : ('psyr', 0127),
+ r'\leftbracket' : ('psyr', 0133),
+ r'\rightbracket' : ('psyr', 0135),
+ r'\leftbrace' : ('psyr', 123),
+ r'\leftparen' : ('psyr', 050),
+ r'\prime' : ('psyr', 0242),
+ r'\sharp' : ('psyr', 043),
+ r'\slash' : ('psyr', 057),
+ r'\Lamda' : ('psyr', 0114),
+ r'\neg' : ('psyr', 0330),
+ r'\Upsilon' : ('psyr', 0241),
+ r'\rightbrace' : ('psyr', 0175),
+ r'\rfloor' : ('psyr', 0373),
+ r'\lambda' : ('psyr', 0154),
+ r'\to' : ('psyr', 0256),
+ r'\Xi' : ('psyr', 0130),
+ r'\emptyset' : ('psyr', 0306),
+ r'\lfloor' : ('psyr', 0353),
+ r'\rightparen' : ('psyr', 051),
+ r'\rceil' : ('psyr', 0371),
+ r'\ni' : ('psyr', 047),
+ r'\epsilon' : ('psyr', 0145),
+ r'\Theta' : ('psyr', 0121),
+ r'\langle' : ('psyr', 0341),
+ r'\leftangle' : ('psyr', 0341),
+ r'\rangle' : ('psyr', 0361),
+ r'\rightangle' : ('psyr', 0361),
+ r'\rbrace' : ('psyr', 0175),
+ r'\circ' : ('psyr', 0260),
+ r'\diamond' : ('psyr', 0340),
+ r'\mu' : ('psyr', 0155),
+ r'\mid' : ('psyr', 0352),
+ r'\imath' : ('pncri8a', 105),
+ r'\%' : ('pncr8a', 37),
+ r'\$' : ('pncr8a', 36),
+ r'\{' : ('pncr8a', 123),
+ r'\}' : ('pncr8a', 125),
+ r'\backslash' : ('pncr8a', 92),
+ r'\ast' : ('pncr8a', 42),
+
+ r'\circumflexaccent' : ('pncri8a', 124), # for \hat
+ r'\combiningbreve' : ('pncri8a', 81), # for \breve
+ r'\combininggraveaccent' : ('pncri8a', 114), # for \grave
+ r'\combiningacuteaccent' : ('pncri8a', 63), # for \accute
+ r'\combiningdiaeresis' : ('pncri8a', 91), # for \ddot
+ r'\combiningtilde' : ('pncri8a', 75), # for \tilde
r'\combiningrightarrowabove' : ('pncri8a', 110), # for \vec
- r'\combiningdotabove' : ('pncri8a', 26), # for \dot
- r'\imath' : ('pncri8a', 105)
+ r'\combiningdotabove' : ('pncri8a', 26), # for \dot
}
# Automatically generated.
@@ -2214,7 +1829,7 @@
'updownarrows': 8645,
'heartsuit': 9825,
'trianglelefteq': 8884,
-'ddagger': 8225,
+'ddag': 8225,
'sqsubseteq': 8849,
'mapsfrom': 8612,
'boxbar': 9707,
@@ -2516,7 +2131,7 @@
'succcurlyeq': 8829,
'gamma': 947,
'scrR': 8475,
-'dagger': 8224,
+'dag': 8224,
'thickspace': 8197,
'frakZ': 8488,
'lessdot': 8918,
@@ -2589,7 +2204,39 @@
'divideontimes': 8903,
'lbrack': 91,
'textquotedblright': 8221,
-'Colon': 8759}
+'Colon': 8759,
+'%': 37,
+'$': 36,
+'{': 123,
+'}': 125,
+'imath': 0xfd,
+'circumflexaccent' : 770,
+'combiningbreve' : 774,
+'combiningoverline' : 772,
+'combininggraveaccent' : 768,
+'combiningacuteaccent' : 764,
+'combiningdiaeresis' : 776,
+'combiningtilde' : 771,
+'combiningrightarrowabove' : 8407,
+'combiningdotabove' : 775,
+'to': 8594,
+'succeq': 8829,
+'emptyset': 8709,
+'leftparen': 40,
+'rightparen': 41,
+'bigoplus': 10753,
+'leftangle': 10216,
+'rightangle': 10217,
+'leftbrace': 124,
+'rightbrace': 125,
+'jmath': 567,
+'bigodot': 10752,
+'preceq': 8828,
+'biguplus': 10756,
+'epsilon': 949,
+'vartheta': 977,
+'bigotimes': 10754
+}
uni2tex = dict([(v,k) for k,v in tex2uni.items()])
@@ -2692,7 +2339,7 @@
'updownarrows': 'uni21C5',
'heartsuit': 'uni2661',
'trianglelefteq': 'uni22B4',
-'ddagger': 'daggerdbl',
+'ddag': 'daggerdbl',
'sqsubseteq': 'uni2291',
'mapsfrom': 'uni21A4',
'boxbar': 'uni25EB',
@@ -2994,7 +2641,7 @@
'succcurlyeq': 'uni227D',
'gamma': 'uni03B3',
'scrR': 'uni211B',
-'dagger': 'dagger',
+'dag': 'dagger',
'thickspace': 'uni2005',
'frakZ': 'uni2128',
'lessdot': 'uni22D6',
@@ -3070,4 +2717,3 @@
'Colon': 'uni2237'}
type12tex = dict([(v,k) for k,v in tex2type1.items()])
-
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-07-30 07:03:47 UTC (rev 3630)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-07-30 16:41:53 UTC (rev 3631)
@@ -131,7 +131,9 @@
from __future__ import division
import os, sys
from cStringIO import StringIO
+from math import floor, ceil
from sets import Set
+from unicodedata import category
from warnings import warn
from matplotlib import verbose
@@ -146,7 +148,7 @@
is_string_like
from matplotlib.ft2font import FT2Font, KERNING_UNFITTED
from matplotlib.font_manager import fontManager, FontProperties
-from matplotlib._mathtext_data import latex_to_bakoma, cmkern, \
+from matplotlib._mathtext_data import latex_to_bakoma, \
latex_to_standard, tex2uni, type12uni, tex2type1, uni2type1
from matplotlib import get_data_path, rcParams
@@ -164,14 +166,6 @@
##############################################################################
# FONTS
-def font_open(filename):
- ext = filename.rsplit('.',1)[1]
- if ext == 'afm':
- return AFM(str(filename))
- else:
- return FT2Font(str(filename))
-
-
def get_unicode_index(symbol):
"""get_unicode_index(symbol) -> integer
@@ -187,10 +181,6 @@
try:# Is symbol a TeX symbol (i.e. \alpha)
return tex2uni[symbol.strip("\\")]
except KeyError:
- pass
- try:# Is symbol a Type1 name (i.e. degree)? If not raise error
- return type12uni[symbol]
- except KeyError:
message = """'%(symbol)s' is not a valid Unicode character or
TeX/Type1 symbol"""%locals()
raise ValueError, message
@@ -219,574 +209,473 @@
# The user did not suply a valid symbol, show usage
raise ValueError, get_type1_name.__doc__
+class MathtextBackend(object):
+ def __init__(self):
+ fonts_object = None
-class Fonts:
- """
- An abstract base class for fonts that want to render mathtext
+ def set_canvas_size(self, w, h):
+ 'Dimension the drawing canvas; may be a noop'
+ self.width = w
+ self.height = h
- The class must be able to take symbol keys and font file names and
- return the character metrics as well as do the drawing
- """
-
- def get_kern(self, facename, symleft, symright, fontsize, dpi):
- """
- Get the kerning distance for font between symleft and symright.
+ def render_glyph(self, ox, oy, info):
+ raise NotImplementedError()
- facename is one of tt, it, rm, cal or None
+ def render_filled_rect(self, x1, y1, x2, y2):
+ raise NotImplementedError()
- sym is a single symbol(alphanum, punct) or a special symbol
- like \sigma.
-
- """
- return 0
-
- def get_metrics(self, facename, sym, fontsize, dpi):
- """
- facename is one of tt, it, rm, cal or None
-
- sym is a single symbol(alphanum, punct) or a special symbol
- like \sigma.
-
- fontsize is in points
-
- Return object has attributes - see
- http://www.freetype.org/freetype2/docs/tutorial/step2.html for
- a pictoral representation of these attributes
-
- advance
- height
- width
- xmin, xmax, ymin, ymax - the ink rectangle of the glyph
- """
- raise NotImplementedError('Derived must override')
-
+ def get_results(self):
+ """Return a backend specific tuple of things to return to the
+ backend after all processing is done."""
+ raise NotImplementedError()
+
+class MathtextBackendAgg(MathtextBackend):
def set_canvas_size(self, w, h):
- 'Dimension the drawing canvas; may be a noop'
- self.width, self.height = w, h
+ MathtextBackend.set_canvas_size(self, w, h)
+ for font in self.fonts_object.get_fonts():
+ font.set_bitmap_size(int(w), int(h))
- def render(self, ox, oy, facename, sym, fontsize, dpi):
- pass
+ def render_glyph(self, ox, oy, info):
+ info.font.draw_glyph_to_bitmap(
+ int(ox), int(oy - info.metrics.ymax), info.glyph)
def render_rect_filled(self, x1, y1, x2, y2):
- pass
+ font = self.fonts_object.get_fonts()[0]
+ font.draw_rect_filled(
+ floor(max(0, x1 - 1)),
+ floor(y1),
+ ceil(max(x2 - 1, x1)),
+ ceil(max(y2 - 1, y1)))
+
+ def get_results(self):
+ return (self.width,
+ self.height,
+ self.fonts_object.get_fonts(),
+ self.fonts_object.get_used_characters())
- def get_used_characters(self):
- return {}
+class MathtextBackendPs(MathtextBackend):
+ def __init__(self):
+ self.pswriter = StringIO()
-
-class DummyFonts(Fonts):
- 'dummy class for debugging parser'
- def get_metrics(self, font, sym, fontsize, dpi):
-
- metrics = Bunch(
- advance = 0,
- height = 0,
- width = 0,
- xmin = 0,
- xmax = 0,
- ymin = 0,
- ymax = 0,
- )
- return metrics
-
-
-class UnicodeFonts(Fonts):
- """An abstract base class for handling Unicode fonts.
-
-Specific terminology:
- * fontface: an FT2Font object, corresponding to a facename
- * facename: a string that defines the (type)face's name - 'rm', 'it' etc.
- * filename: a string that is used for generating a fontface object
- * symbol*: a single Unicode character or a TeX command,
- or to be precise, a TeX symbol command like \alpha (but not \frac) or
- even a Type1/PS name
- * filenamesd: a dict that maps the face's name to the filename:
- filenamesd = { 'cal' : 'fontnamecal.ext',
- 'rm' : 'fontnamerm.ext',
- 'tt' : 'fontnamett.ext',
- 'it' : 'fontnameit.ext',
- None : 'fontnamesmth.ext'}
- filenamesd should be declared as a class atribute
- * glyphdict: a dict used for caching of glyph specific data
- * fonts: a dict of facename -> fontface pairs
- * charmaps: a dict of facename -> charmap pairs. Charmap maps character
- codes to glyph indices
- * glyphmaps: a dict of facename -> glyphmap pairs. A glyphmap is an
- inverted charmap
- * output: a string in ['Agg','SVG','PS'], coresponding to the backends
- * index: Fontfile specific index of a glyph.
-
-"""
-
- # The path to the dir with the fontfiles
- def __init__(self, output='Agg'):
- self.facenames = self.filenamesd.keys()
- # Set the filenames to full path
- for facename in self.filenamesd:
- self.filenamesd[facename] = self.filenamesd[facename]
- if output:
- self.output = output
- # self.glyphdict[key] = facename, metrics, glyph, offset
- self.glyphdict = {}
-
- self.fonts = dict(
- [ (facename, font_open(self.filenamesd[facename])) for
- facename in self.facenames])
- # a dict of charcode -> glyphindex pairs
- self.charmaps = dict(
- [ (facename, self.fonts[facename].get_charmap())
- for facename in self.facenames])
- # a dict of glyphindex -> charcode pairs
- self.glyphmaps = {}
- for facename in self.facenames:
- charmap = self.charmaps[facename]
- self.glyphmaps[facename] = dict([(glyphind, charcode)
- for charcode, glyphind in charmap.items()])
- for fontface in self.fonts.values():
- fontface.clear()
- if self.output == 'SVG':
- # a list of "glyphs" we need to render this thing in SVG
- self.svg_glyphs=[]
-
- def set_canvas_size(self, w, h, pswriter=None):
- 'Dimension the drawing canvas; may be a noop'
- # self.width = int(w)
- # self.height = int(h)
- # I don't know why this was different than the PS version
- self.width = w
- self.height = h
- if pswriter:
- self.pswriter = pswriter
- else:
- for fontface in self.fonts.values():
- fontface.set_bitmap_size(int(w), int(h))
-
- def render(self, ox, oy, facename, symbol, fontsize, dpi):
- filename = self.filenamesd[facename]
- uniindex, metrics, glyph, offset = self._get_info(facename,
- symbol, fontsize, dpi)
- if self.output == 'SVG':
- oy += offset - 512/2048.*10.
- # TO-DO - make a method for it
- # This gets the name of the font.
- familyname = self.fonts[facename].get_sfnt()[(1,0,0,1)]
- thetext = unichr(uniindex)
- thetext.encode('utf-8')
- self.svg_glyphs.append((familyname, fontsize, thetext, ox, oy,
- metrics))
- elif self.output == 'PS':
- # This should be changed to check for math mode or smth.
- #if filename == 'cmex10.ttf':
- # oy += offset - 512/2048.*10.
-
- # Get the PS name of a glyph (his unicode integer code)
- # from the font object
- symbolname = self._get_glyph_name(uniindex, facename)
- psfontname = self.fonts[facename].postscript_name
- ps = """/%(psfontname)s findfont
+ def render_glyph(self, ox, oy, info):
+ oy = self.height - oy + info.offset
+ postscript_name = info.postscript_name
+ fontsize = info.fontsize
+ symbol_name = info.symbol_name
+
+ ps = """/%(postscript_name)s findfont
%(fontsize)s scalefont
setfont
%(ox)f %(oy)f moveto
-/%(symbolname)s glyphshow
+/%(symbol_name)s glyphshow
""" % locals()
- self.pswriter.write(ps)
- else: # Agg
- fontface = self.fonts[facename]
- fontface.draw_glyph_to_bitmap(
- int(ox), int(self.height - oy - metrics.ymax), glyph)
+ self.pswriter.write(ps)
- def get_metrics(self, facename, symbol, fontsize, dpi):
- uniindex, metrics, glyph, offset = \
- self._get_info(facename, symbol, fontsize, dpi)
- return metrics
+ def render_rect_filled(self, x1, y1, x2, y2):
+ ps = "%f %f %f %f rectfill" % (x1, self.height - y2, x2 - x1, y2 - y1)
+ self.pswriter.write(ps)
- # Methods that must be overridden for fonts that are not unicode aware
+ def get_results(self):
+ return (self.width,
+ self.height,
+ self.pswriter,
+ self.fonts_object.get_used_characters())
+
+class MathtextBackendPdf(MathtextBackend):
+ def __init__(self):
+ self.pswriter = []
+
+ def render_glyph(self, ox, oy, info):
+ filename = info.font.fname
+ oy = self.height - oy + info.offset
- def _get_unicode_index(self, symbol):
- return get_unicode_index(symbol)
+ self.pswriter.append(('glyph', ox, oy, filename, info.fontsize, info.num))
- def _get_glyph_name(self, uniindex, facename):
- """get_glyph_name(self, uniindex, facename) -> string
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.pswriter.append(('rect', x1, self.height - y2, x2 - x1, y2 - y1))
-Returns the name of the glyph directly from the font object.
+ def get_results(self):
+ return (self.width,
+ self.height,
+ self.pswriter,
+ self.fonts_object.get_used_characters())
-"""
- font = self.fonts[facename]
- glyphindex = self.glyphmaps[facename][uniindex]
- return font.get_glyph_name(glyphindex)
-
- def _get_info(self, facename, symbol, fontsize, dpi):
- 'load the facename, metrics and glyph'
- #print hex(index), symbol, filename, facename
- key = facename, symbol, fontsize, dpi
- tup = self.glyphdict.get(key)
- if tup is not None:
- return tup
- filename = self.filenamesd[facename]
- fontface = self.fonts[facename]
- fontface.set_size(fontsize, dpi)
- head = fontface.get_sfnt_table('head')
- uniindex = self._get_unicode_index(symbol)
- glyphindex = self.glyphmaps[facename][uniindex]
- glyph = fontface.load_char(uniindex)
- xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- # This is black magic to me (Edin)
- if filename == 'cmex10.ttf':
- if self.output == 'PS':
- offset = -(head['yMin']+512)/head['unitsPerEm']*10.
- else:
- offset = glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
- else:
- offset = 0.
- metrics = Bunch(
- advance = glyph.linearHoriAdvance/65536.0,
- height = glyph.height/64.0,
- width = glyph.width/64.0,
- xmin = xmin,
- xmax = xmax,
- ymin = ymin+offset,
- ymax = ymax+offset,
- )
- self.glyphdict[key] = uniindex, metrics, glyph, offset
- return self.glyphdict[key]
-
-
-class MyUnicodeFonts(UnicodeFonts):
- _initialized = False
+class MathtextBackendSvg(MathtextBackend):
def __init__(self):
- if not MyUnicodeFonts._initialized:
- prop = FontProperties()
- prop.set_family('serif')
- self.rmfile = fontManager.findfont(prop)
+ self.svg_glyphs = []
+ self.svg_rects = []
+
+ def render_glyph(self, ox, oy, info):
+ oy = self.height - oy + info.offset
+ thetext = unichr(info.num)
+ self.svg_glyphs.append(
+ (info.font, info.fontsize, thetext, ox, oy, info.metrics))
- prop.set_family('fantasy')
- self.calfile = fontManager.findfont(prop)
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.svg_rects.append(
+ (x1, self.height - y1, x2 - x1, y2 - y1))
- prop.set_family('monospace')
- self.ttfile = fontManager.findfont(prop)
+ def get_results(self):
+ svg_elements = Bunch(svg_glyphs = self.svg_glyphs,
+ svg_rects = self.svg_rects)
+ return (self.width,
+ self.height,
+ svg_elements,
+ self.fonts_object.get_used_characters())
+
+class Fonts(object):
+ """
+ An abstract base class for fonts that want to render mathtext
- prop.set_family('serif')
- prop.set_style('italic')
- self.itfile = fontManager.findfont(prop)
- self.filenamesd = { 'rm' : self.rmfile,
- 'it' : self.itfile,
- 'cal' : self.calfile,
- 'tt' : self.ttfile,
- }
- MyUnicodeFonts._initialized = True
+ The class must be able to take symbol keys and font file names and
+ return the character metrics. It also delegates to a backend class
+ to do the actual drawing.
+ """
+ def __init__(self, default_font_prop, mathtext_backend):
+ """default_font_prop: A FontProperties object to use for the
+ default non-math font, or the base font for Unicode font
+ rendering.
+ mathtext_backend: A subclass of MathTextBackend used to
+ delegate the actual rendering."""
+ self.default_font_prop = default_font_prop
+ self.mathtext_backend = mathtext_backend
+ # Make these classes doubly-linked
+ self.mathtext_backend.fonts_object = self
+ self.used_characters = {}
+
+ def get_kern(self, font1, sym1, fontsize1,
+ font2, sym2, fontsize2, dpi):
+ """
+ Get the kerning distance for font between sym1 and sym2.
-# TO-DO: pretty much everything
-class BakomaUnicodeFonts(UnicodeFonts):
- """A class that simulates Unicode support in the BaKoMa fonts"""
+ fontX: one of the TeX font names, tt, it, rm, cal, sf, bf or
+ default (non-math)
+ symX: a symbol in raw TeX form. e.g. '1', 'x' or '\sigma'
+ fontsizeX: the fontsize in points
+ dpi: the current dots-per-inch
+
+ sym is a single symbol(alphanum, punct) or a special symbol
+ like \sigma.
- filenamesd = { 'cal' : 'cmsy10.ttf',
- 'rm' : 'cmr10.ttf',
- 'tt' : 'cmtt10.ttf',
- 'it' : 'cmmi10.ttf',
- 'bf' : 'cmb10.ttf',
- 'sf' : 'cmss10.ttf',
- None : 'cmmi10.ttf',
- }
+ """
+ return 0.
- # We override the UnicodeFonts methods, that depend on Unicode support
- def _get_unicode_index(self, symbol):
- uniindex = get_unicode_index(symbol)
+ def get_metrics(self, font, sym, fontsize, dpi):
+ """
+ font: one of the TeX font names, tt, it, rm, cal, sf, bf or
+ default (non-math)
+ sym: a symbol in raw TeX form. e.g. '1', 'x' or '\sigma'
+ fontsize: font size in points
+ dpi: current dots-per-inch
- # Should be deleted
- def _get_glyph_name(self, uniindex, facename):
- """get_glyph_name(self, uniindex, facename) -> string
+ advance
+ height
+ width
+ xmin, xmax, ymin, ymax - the ink rectangle of the glyph
+ iceberg - the distance from the baseline to the top of the glyph.
+ horiBearingY in Truetype parlance, height in TeX parlance
+ """
+ info = self._get_info(font, sym, fontsize, dpi)
+ return info.metrics
-Returns the name of the glyph directly from the font object.
-Because BaKoma fonts don't support Unicode, 'uniindex' is misleading
+ def set_canvas_size(self, w, h):
+ 'Dimension the drawing canvas; may be a noop'
+ self.width, self.height = ceil(w), ceil(h)
+ self.mathtext_backend.set_canvas_size(self.width, self.height)
-"""
- font = self.fonts[facename]
- glyphindex = self.glyphmaps[facename][uniindex]
- return font.get_glyph_name(glyphindex)
+ def render_glyph(self, ox, oy, facename, sym, fontsize, dpi):
+ info = self._get_info(facename, sym, fontsize, dpi)
+ realpath, stat_key = get_realpath_and_stat(info.font.fname)
+ used_characters = self.used_characters.setdefault(
+ stat_key, (realpath, Set()))
+ used_characters[1].update(unichr(info.num))
+ self.mathtext_backend.render_glyph(ox, oy, info)
- def _get_info(self, facename, symbol, fontsize, dpi):
- 'load the facename, metrics and glyph'
- #print hex(index), symbol, filename, facename
- key = facename, symbol, fontsize, dpi
- tup = self.glyphdict.get(key)
- if tup is not None:
- return tup
- filename = self.filenamesd[facename]
- fontface = self.fonts[facename]
- fontface.set_size(fontsize, dpi)
- head = fontface.get_sfnt_table('head')
- uniindex = self._get_unicode_index(symbol)
- glyphindex = self.glyphmaps[facename][uniindex]
- glyph = fontface.load_char(uniindex)
- xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- # This is black magic to me (Edin)
- if filename == 'cmex10.ttf':
- if self.output == 'PS':
- offset = -(head['yMin']+512)/head['unitsPerEm']*10.
- else:
- offset = glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
- else:
- offset = 0.
- metrics = Bunch(
- advance = glyph.linearHoriAdvance/65536.0,
- height = glyph.height/64.0,
- width = glyph.width/64.0,
- xmin = xmin,
- xmax = xmax,
- ymin = ymin+offset,
- ymax = ymax+offset,
- )
- self.glyphdict[key] = uniindex, metrics, glyph, offset
- return self.glyphdict[key]
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.mathtext_backend.render_rect_filled(x1, y1, x2, y2)
+ def get_xheight(self, font, fontsize, dpi):
+ raise NotImplementedError()
-# TO-DO: Implement all methods
-class CMUUnicodeFonts(UnicodeFonts):
- """A class representing Computer Modern Unicode Fonts, made by
-Andrey V. Panov
-panov /at/ canopus. iacp. dvo. ru
-They are distributed under the X11 License.
+ def get_underline_thickness(self, font, fontsize, dpi):
+ raise NotImplementedError()
+
+ def get_used_characters(self):
+ return self.used_characters
-"""
+ def get_results(self):
+ return self.mathtext_backend.get_results()
-
-# Old classes
-
-class BakomaFonts(Fonts):
+ def get_sized_alternatives_for_symbol(self, fontname, sym):
+ """Override if your font provides multiple sizes of the same
+ symbol."""
+ return [(fontname, sym)]
+
+class TruetypeFonts(Fonts):
"""
+ A generic base class for all font setups that use Truetype fonts
+ (through ft2font)
+ """
+ """
Use the Bakoma true type fonts for rendering
"""
# allocate a new set of fonts
basepath = os.path.join( get_data_path(), 'fonts', 'ttf' )
- fontmap = { 'cal' : 'Cmsy10',
- 'rm' : 'Cmr10',
- 'tt' : 'Cmtt10',
- 'it' : 'Cmmi10',
- 'bf' : 'Cmb10',
- 'sf' : 'Cmss10',
- None : 'Cmmi10',
- 'ex' : 'Cmex10'
- }
-
class CachedFont:
def __init__(self, font):
self.font = font
self.charmap = font.get_charmap()
self.glyphmap = dict(
[(glyphind, ccode) for ccode, glyphind in self.charmap.items()])
-
- def __init__(self):
- self.glyphd = {}
- self.fonts = {}
- self.used_characters = {}
+ def __repr__(self):
+ return repr(self.font)
+
+ def __init__(self, default_font_prop, mathtext_backend):
+ Fonts.__init__(self, default_font_prop, mathtext_backend)
+ self.glyphd = {}
+ self.fonts = {}
+
+ filename = fontManager.findfont(default_font_prop)
+ default_font = self.CachedFont(FT2Font(str(filename)))
+
+ self.fonts['default'] = default_font
+
def _get_font(self, font):
"""Looks up a CachedFont with its charmap and inverse charmap.
- font may be a TeX font name (cal, rm, it etc.), a Computer Modern
- font name (cmtt10, cmr10, etc.) or an FT2Font object."""
- if isinstance(font, str):
- if font not in self.fontmap.values():
- basename = self.fontmap[font]
- else:
- basename = font
+ font may be a TeX font name (cal, rm, it etc.), or postscript name."""
+ if font in self.fontmap:
+ basename = self.fontmap[font]
else:
- basename = font.postscript_name
+ basename = font
cached_font = self.fonts.get(basename)
if cached_font is None:
- if isinstance(font, str):
- font = FT2Font(os.path.join(self.basepath, basename.lower() + ".ttf"))
- basename = font.postscript_name
+ font = FT2Font(os.path.join(self.basepath, basename + ".ttf"))
cached_font = self.CachedFont(font)
self.fonts[basename] = cached_font
- return basename, cached_font
+ self.fonts[font.postscript_name] = cached_font
+ self.fonts[font.postscript_name.lower()] = cached_font
+ return cached_font
- def get_font(self, font):
- return self._get_font(font)[1].font
-
def get_fonts(self):
- return [x.font for x in self.fonts.values()]
-
- def get_metrics(self, font, sym, fontsize, dpi):
- basename, font, metrics, symbol_name, num, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
- return metrics
+ return list(set([x.font for x in self.fonts.values()]))
- def _get_offset(self, basename, cached_font, glyph, fontsize, dpi):
- if basename.lower() == 'cmex10':
- return glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
+ def _get_offset(self, cached_font, glyph, fontsize, dpi):
return 0.
-
- def _get_info (self, font, sym, fontsize, dpi):
+
+ def _get_info (self, fontname, sym, fontsize, dpi, mark_as_used=True):
'load the cmfont, metrics and glyph with caching'
- if hasattr(font, 'postscript_name'):
- fontname = font.postscript_name
- else:
- fontname = font
-
key = fontname, sym, fontsize, dpi
- tup = self.glyphd.get(key)
+ bunch = self.glyphd.get(key)
+ if bunch is not None:
+ return bunch
- if tup is not None: return tup
-
- if font in self.fontmap and latex_to_bakoma.has_key(sym):
- basename, num = latex_to_bakoma[sym]
- basename, cached_font = self._get_font(basename.capitalize())
- symbol_name = cached_font.font.get_glyph_name(num)
- num = cached_font.glyphmap[num]
- elif len(sym) == 1:
- basename, cached_font = self._get_font(font)
- num = ord(sym)
- symbol_name = cached_font.font.get_glyph_name(cached_font.charmap[num])
- else:
- num = 0
- raise ValueError('unrecognized symbol "%s"' % sym)
+ cached_font, num, symbol_name, fontsize = \
+ self._get_glyph(fontname, sym, fontsize)
font = cached_font.font
font.set_size(fontsize, dpi)
glyph = font.load_char(num)
- realpath, stat_key = get_realpath_and_stat(font.fname)
- used_characters = self.used_characters.setdefault(
- stat_key, (realpath, Set()))
- used_characters[1].update(unichr(num))
-
xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- offset = self._get_offset(basename, cached_font, glyph, fontsize, dpi)
+ offset = self._get_offset(cached_font, glyph, fontsize, dpi)
metrics = Bunch(
- advance = glyph.linearHoriAdvance/65536.0,
- height = glyph.height/64.0,
- width = glyph.width/64.0,
- xmin = xmin,
- xmax = xmax,
- ymin = ymin+offset,
- ymax = ymax+offset,
+ advance = glyph.linearHoriAdvance/65536.0,
+ height = glyph.height/64.0 + offset,
+ width = glyph.width/64.0,
+ xmin = xmin,
+ xmax = xmax,
+ ymin = ymin+offset,
+ ymax = ymax+offset,
# iceberg is the equivalent of TeX's "height"
iceberg = glyph.horiBearingY/64.0 + offset
)
- self.glyphd[key] = basename, font, metrics, symbol_name, num, glyph, offset
+ self.glyphd[key] = Bunch(
+ font = font,
+ fontsize = fontsize,
+ postscript_name = font.postscript_name,
+ metrics = metrics,
+ symbol_name = symbol_name,
+ num = num,
+ glyph = glyph,
+ offset = offset
+ )
return self.glyphd[key]
- def set_canvas_size(self, w, h):
- 'Dimension the drawing canvas; may be a noop'
- self.width = int(w)
- self.height = int(h)
- for cached_font in self.fonts.values():
- cached_font.font.set_bitmap_size(int(w), int(h))
-
- def render(self, ox, oy, font, sym, fontsize, dpi):
- basename, font, metrics, symbol_name, num, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
-
- font.draw_glyph_to_bitmap(
- int(ox), int(oy - metrics.ymax), glyph)
-
- def render_rect_filled(self, x1, y1, x2, y2):
- assert len(self.fonts)
- font = self.fonts.values()[0]
- font.font.draw_rect_filled(
- max(0, x1 - 1),
- y1,
- max(x2 - 1, x1),
- max(y2 - 1, y1))
-
- def get_used_characters(self):
- return self.used_characters
-
def get_xheight(self, font, fontsize, dpi):
- basename, cached_font = self._get_font(font)
+ cached_font = self._get_font(font)
cached_font.font.set_size(fontsize, dpi)
pclt = cached_font.font.get_sfnt_table('pclt')
+ if pclt is None:
+ # Some fonts don't store the xHeight, so we do a poor man's xHeight
+ metrics = self.get_metrics(font, 'x', fontsize, dpi)
+ return metrics.iceberg
xHeight = pclt['xHeight'] / 64.0
return xHeight
def get_underline_thickness(self, font, fontsize, dpi):
- basename, cached_font = self._get_font(font)
+ cached_font = self._get_font(font)
cached_font.font.set_size(fontsize, dpi)
return max(1.0, cached_font.font.underline_thickness / 64.0)
- def get_kern(self, fontleft, symleft, fontsizeleft,
- fontright, symright, fontsizeright, dpi):
- if fontsizeleft == fontsizeright:
- basename, font1, metrics, symbol_name, num1, glyph1, offset = \
- self._get_info(fontleft, symleft, fontsizeleft, dpi)
- basename, font2, metrics, symbol_name, num2, glyph2, offset = \
- self._get_info(fontright, symright, fontsizeright, dpi)
- if font1 == font2:
- basename, font = self._get_font(font1)
- return font.font.get_kerning(num1, num2, KERNING_UNFITTED) / 64.0
+ def get_kern(self, font1, sym1, fontsize1,
+ font2, sym2, fontsize2, dpi):
+ if font1 == font2 and fontsize1 == fontsize2:
+ info1 = self._get_info(font1, sym1, fontsize1, dpi)
+ info2 = self._get_info(font2, sym2, fontsize2, dpi)
+ font = info1.font
+ return font.get_kerning(info1.num, info2.num, KERNING_UNFITTED) / 64.0
return 0.0
-class BakomaPSFonts(BakomaFonts):
+class BakomaFonts(TruetypeFonts):
"""
- Use the Bakoma postscript fonts for rendering to backend_ps
+ Use the Bakoma true type fonts for rendering
"""
-
- def set_canvas_size(self, w, h, pswriter):
- 'Dimension the drawing canvas; may be a noop'
- self.width = w
- self.height = h
- self.pswriter = pswriter
-
- def render(self, ox, oy, font, sym, fontsize, dpi):
- basename, font, metrics, symbol_name, num, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
- oy = self.height - oy + offset
-
- ps = """/%(basename)s findfont
-%(fontsize)s scalefont
-setfont
-%(ox)f %(oy)f moveto
-/%(symbol_name)s glyphshow
-""" % locals()
- self.pswriter.write(ps)
-
- def render_rect_filled(self, x1, y1, x2, y2):
- ps = "%f %f %f %f rectfill" % (x1, self.height - y2, x2 - x1, y2 - y1)
- self.pswriter.write(ps)
+ fontmap = { 'cal' : 'cmsy10',
+ 'rm' : 'cmr10',
+ 'tt' : 'cmtt10',
+ 'it' : 'cmmi10',
+ 'bf' : 'cmb10',
+ 'sf' : 'cmss10',
+ 'ex' : 'cmex10'
+ }
-class BakomaPDFFonts(BakomaPSFonts):
- """Hack of BakomaPSFonts for PDF support."""
+ def _get_offset(self, cached_font, glyph, fontsize, dpi):
+ if cached_font.font.postscript_name == 'cmex10':
+ return glyph.height/64.0/2 + 256.0/64.0 * dpi/72.0
+ return 0.
- def render(self, ox, oy, font, sym, fontsize, dpi):
- basename, font, metrics, symbol_name, num, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
- filename = font.fname
- oy = self.height - oy + offset
+ def _get_glyph(self, fontname, sym, fontsize):
+ if fontname in self.fontmap and latex_to_bakoma.has_key(sym):
+ basename, num = latex_to_bakoma[sym]
+ cached_font = self._get_font(basename)
+ symbol_name = cached_font.font.get_glyph_name(num)
+ num = cached_font.glyphmap[num]
+ elif len(sym) == 1:
+ cached_font = self._get_font(fontname)
+ num = ord(sym)
+ symbol_name = cached_font.font.get_glyph_name(
+ cached_font.charmap[num])
+ else:
+ raise ValueError('unrecognized symbol "%s"' % sym)
- self.pswriter.append(('glyph', ox, oy, filename, fontsize, num))
+ return cached_font, num, symbol_name, fontsize
- def render_rect_filled(self, x1, y1, x2, y2):
- self.pswriter.append(('rect', x1, self.height - y2, x2 - x1, y2 - y1))
+ # The Bakoma fonts contain many pre-sized alternatives for the
+ # delimiters. The AutoSizedChar class will use these alternatives
+ # and select the best (closest sized) glyph.
+ _size_alternatives = {
+ '(' : [('rm', '('), ('ex', '\xa1'), ('ex', '\xb3'),
+ ('ex', '\xb5'), ('ex', '\xc3')],
+ ')' : [('rm', ')'), ('ex', '\xa2'), ('ex', '\xb4'),
+ ('ex', '\xb6'), ('ex', '\x21')],
+ '{' : [('cal', '{'), ('ex', '\xa9'), ('ex', '\x6e'),
+ ('ex', '\xbd'), ('ex', '\x28')],
+ '}' : [('cal', '}'), ('ex', '\xaa'), ('ex', '\x6f'),
+ ('ex', '\xbe'), ('ex', '\x29')],
+ # The fourth size of '[' is mysteriously missing from the BaKoMa font,
+ # so I've ommitted it for both
+ '[' : [('rm', '['), ('ex', '\xa3'), ('ex', '\x68'),
+ ('ex', '\x22')],
+ ']' : [('rm', ']'), ('ex', '\xa4'), ('ex', '\x69'),
+ ('ex', '\x23')],
+ r'\lfloor' : [('cal', '\x62'), ('ex', '\xa5'), ('ex', '\x6a'),
+ ('ex', '\xb9'), ('ex', '\x24')],
+ r'\rfloor' : [('cal', '\x63'), ('ex', '\xa6'), ('ex', '\x6b'),
+ ('ex', '\xba'), ('ex', '\x25')],
+ r'\lceil' : [('cal', '\x64'), ('ex', '\xa7'), ('ex', '\x6c'),
+ ('ex', '\xbb'), ('ex', '\x26')],
+ r'\rceil' : [('cal', '\x65'), ('ex', '\xa8'), ('ex', '\x6d'),
+ ('ex', '\xbc'), ('ex', '\x27')],
+ r'\langle' : [('cal', '\x68'), ('ex', '\xad'), ('ex', '\x44'),
+ ('ex', '\xbf'), ('ex', '\x2a')],
+ r'\rangle' : [('cal', '\x69'), ('ex', '\xae'), ('ex', '\x45'),
+ ...
[truncated message content] |
|
From: <ef...@us...> - 2007-07-30 07:03:49
|
Revision: 3630
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3630&view=rev
Author: efiring
Date: 2007-07-30 00:03:47 -0700 (Mon, 30 Jul 2007)
Log Message:
-----------
Removed last vestiges of old pcolor, scatter, quiver versions.
Modified Paths:
--------------
trunk/matplotlib/CHANGELOG
trunk/matplotlib/boilerplate.py
trunk/matplotlib/lib/matplotlib/axes.py
trunk/matplotlib/lib/matplotlib/pylab.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2007-07-30 06:04:41 UTC (rev 3629)
+++ trunk/matplotlib/CHANGELOG 2007-07-30 07:03:47 UTC (rev 3630)
@@ -1,6 +1,7 @@
2007-07-29 Changed default pcolor shading to flat; added aliases
to make collection kwargs agree with setter names, so
updating works; related minor cleanups.
+ Removed quiver_classic, scatter_classic, pcolor_classic. - EF
2007-07-26 Major rewrite of mathtext.py, using the TeX box layout model.
Modified: trunk/matplotlib/boilerplate.py
===================================================================
--- trunk/matplotlib/boilerplate.py 2007-07-30 06:04:41 UTC (rev 3629)
+++ trunk/matplotlib/boilerplate.py 2007-07-30 07:03:47 UTC (rev 3630)
@@ -82,7 +82,6 @@
'stem',
'vlines',
'quiver',
- 'quiver2',
'quiverkey',
'xcorr',
)
Modified: trunk/matplotlib/lib/matplotlib/axes.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/axes.py 2007-07-30 06:04:41 UTC (rev 3629)
+++ trunk/matplotlib/lib/matplotlib/axes.py 2007-07-30 07:03:47 UTC (rev 3630)
@@ -4051,34 +4051,6 @@
scatter.__doc__ = cbook.dedent(scatter.__doc__) % martist.kwdocd
- def scatter_classic(self, x, y, s=None, c='b'):
- """
- scatter_classic is no longer available; please use scatter.
- To help in porting, for comparison to the scatter docstring,
- here is the scatter_classic docstring:
-
- SCATTER_CLASSIC(x, y, s=None, c='b')
-
- Make a scatter plot of x versus y. s is a size (in data coords) and
- can be either a scalar or an array of the same length as x or y. c is
- a color and can be a single color format string or an length(x) array
- of intensities which will be mapped by the colormap jet.
-
- If size is None a default size will be used
- """
- raise NotImplementedError('scatter_classic has been removed;\n'
- + 'please use scatter instead')
-
- def pcolor_classic(self, *args):
- """
- pcolor_classic is no longer available; please use pcolor,
- which is a drop-in replacement.
- """
- raise NotImplementedError('pcolor_classic has been removed;\n'
- + 'please use pcolor instead')
-
-
-
def arrow(self, x, y, dx, dy, **kwargs):
"""
Draws arrow on specified axis from (x,y) to (x+dx,y+dy).
@@ -4097,164 +4069,14 @@
return qk
quiverkey.__doc__ = mquiver.QuiverKey.quiverkey_doc
- def quiver2(self, *args, **kw):
+ def quiver(self, *args, **kw):
q = mquiver.Quiver(self, *args, **kw)
self.add_collection(q)
self.update_datalim_numerix(q.X, q.Y)
self.autoscale_view()
return q
- quiver2.__doc__ = mquiver.Quiver.quiver_doc
-
- def quiver(self, *args, **kw):
- if (len(args) == 3 or len(args) == 5) and not iterable(args[-1]):
- return self.quiver_classic(*args, **kw)
- c = kw.get('color', None)
- if c is not None:
- if not mcolors.is_color_like(c):
- assert npy.shape(npy.asarray(c)) == npy.shape(npy.asarray(args[-1]))
- return self.quiver_classic(*args, **kw)
- return self.quiver2(*args, **kw)
quiver.__doc__ = mquiver.Quiver.quiver_doc
- def quiver_classic(self, U, V, *args, **kwargs ):
- """
- QUIVER( X, Y, U, V )
- QUIVER( U, V )
- QUIVER( X, Y, U, V, S)
- QUIVER( U, V, S )
- QUIVER( ..., color=None, width=1.0, cmap=None, norm=None )
-
- Make a vector plot (U, V) with arrows on a grid (X, Y)
-
- If X and Y are not specified, U and V must be 2D arrays.
- Equally spaced X and Y grids are then generated using the
- meshgrid command.
-
- color can be a color value or an array of colors, so that the
- arrows can be colored according to another dataset. If cmap
- is specified and color is 'length', the colormap is used to
- give a color according to the vector's length.
-
- If color is a scalar field, the colormap is used to map the
- scalar to a color If a colormap is specified and color is an
- array of color triplets, then the colormap is ignored
-
- width is a scalar that controls the width of the arrows
-
- if S is specified it is used to scale the vectors. Use S=0 to
- disable automatic scaling. If S!=0, vectors are scaled to fit
- within the grid and then are multiplied by S.
-
-
- """
- msg = '''This version of quiver is obsolete and will be
- phased out; please use the new quiver.
- '''
- warnings.warn(msg, DeprecationWarning)
- if not self._hold: self.cla()
- do_scale = True
- S = 1.0
- if len(args)==0:
- # ( U, V )
- U = npy.asarray(U)
- V = npy.asarray(V)
- X,Y = mlab.meshgrid( npy.arange(U.shape[1]), npy.arange(U.shape[0]) )
- elif len(args)==1:
- # ( U, V, S )
- U = npy.asarray(U)
- V = npy.asarray(V)
- X,Y = mlab.meshgrid( npy.arange(U.shape[1]), npy.arange(U.shape[0]) )
- S = float(args[0])
- do_scale = ( S != 0.0 )
- elif len(args)==2:
- # ( X, Y, U, V )
- X = npy.asarray(U)
- Y = npy.asarray(V)
- U = npy.asarray(args[0])
- V = npy.asarray(args[1])
- elif len(args)==3:
- # ( X, Y, U, V )
- X = npy.asarray(U)
- Y = npy.asarray(V)
- U = npy.asarray(args[0])
- V = npy.asarray(args[1])
- S = float(args[2])
- do_scale = ( S != 0.0 )
-
- assert U.shape == V.shape
- assert X.shape == Y.shape
- assert U.shape == X.shape
-
- U = U.ravel()
- V = V.ravel()
- X = X.ravel()
- Y = Y.ravel()
-
- arrows = []
- N = npy.sqrt( U**2+V**2 )
- if do_scale:
- Nmax = maximum.reduce(N) or 1 # account for div by zero
- U = U*(S/Nmax)
- V = V*(S/Nmax)
- N = N*Nmax
-
- alpha = kwargs.pop('alpha', 1.0)
- width = kwargs.pop('width', .5)
- norm = kwargs.pop('norm', None)
- cmap = kwargs.pop('cmap', None)
- vmin = kwargs.pop('vmin', None)
- vmax = kwargs.pop('vmax', None)
- color = kwargs.pop('color', None)
- shading = kwargs.pop('shading', 'faceted')
-
- if len(kwargs):
- raise TypeError(
- "quiver() got an unexpected keyword argument '%s'"%kwargs.keys()[0])
-
- C = None
- if color == 'length' or color is True:
- if color is True:
- warnings.warn('''Use "color='length'",
- not "color=True"''', DeprecationWarning)
- C = N
- elif color is None:
- color = (0,0,0,1)
- else:
- clr = npy.asarray(color).ravel()
- if clr.shape == U.shape:
- C = clr
-
- I = U.shape[0]
- arrows = [mpatches.FancyArrow(X[i],Y[i],U[i],V[i],0.1*S ).get_verts()
- for i in xrange(I)]
-
- collection = mcoll.PolyCollection(
- arrows,
- edgecolors = 'None',
- antialiaseds = (1,),
- linewidths = (width,),
- )
- if C is not None:
- collection.set_array( C.ravel() )
- collection.set_cmap(cmap)
- collection.set_norm(norm)
- if norm is not None:
- collection.set_clim( vmin, vmax )
- else:
- collection.set_facecolor(color)
- self.add_collection( collection )
-
- lims = npy.asarray(arrows)
- _max = maximum.reduce( maximum.reduce( lims ))
- _min = minimum.reduce( minimum.reduce( lims ))
- self.update_datalim( [ tuple(_min), tuple(_max) ] )
- self.autoscale_view()
- return collection
-
-
-
-
-
def fill(self, *args, **kwargs):
"""
FILL(*args, **kwargs)
Modified: trunk/matplotlib/lib/matplotlib/pylab.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/pylab.py 2007-07-30 06:04:41 UTC (rev 3629)
+++ trunk/matplotlib/lib/matplotlib/pylab.py 2007-07-30 07:03:47 UTC (rev 3630)
@@ -335,64 +335,6 @@
colorbar.__doc__ = colorbar_doc
-def colorbar_classic(mappable = None,
- cax=None,
- orientation='vertical',
- tickfmt='%1.1f',
- cspacing='proportional',
- clabels=None,
- drawedges=False,
- edgewidth=0.5,
- edgecolor='k'):
- """
- Create a colorbar for mappable; if mappable is None,
- use current image.
-
- tickfmt is a format string to format the colorbar ticks
-
- cax is a colorbar axes instance in which the colorbar will be
- placed. If None, as default axesd will be created resizing the
- current aqxes to make room for it. If not None, the supplied axes
- will be used and the other axes positions will be unchanged.
-
- orientation is the colorbar orientation: one of 'vertical' | 'horizontal'
-
- cspacing controls how colors are distributed on the colorbar.
- if cspacing == 'linear', each color occupies an equal area
- on the colorbar, regardless of the contour spacing.
- if cspacing == 'proportional' (Default), the area each color
- occupies on the the colorbar is proportional to the contour interval.
- Only relevant for a Contour image.
-
- clabels can be a sequence containing the
- contour levels to be labelled on the colorbar, or None (Default).
- If clabels is None, labels for all contour intervals are
- displayed. Only relevant for a Contour image.
-
- if drawedges == True, lines are drawn at the edges between
- each color on the colorbar. Default False.
-
- edgecolor is the line color delimiting the edges of the colors
- on the colorbar (if drawedges == True). Default black ('k')
-
- edgewidth is the width of the lines delimiting the edges of
- the colors on the colorbar (if drawedges == True). Default 0.5
-
- return value is the colorbar axes instance
- """
- if mappable is None:
- mappable = gci()
- ret = gcf().colorbar_classic(mappable, cax = cax,
- orientation = orientation,
- tickfmt = tickfmt,
- cspacing=cspacing,
- clabels=clabels,
- drawedges=drawedges,
- edgewidth=edgewidth,
- edgecolor=edgecolor)
- draw_if_interactive()
- return ret
-
def colors():
"""
This is a do nothing function to provide you with help on how
@@ -1606,19 +1548,6 @@
draw_if_interactive()
-### Deprecated functions:
-def scatter_classic(*args, **kwargs):
- return gca().scatter_classic(*args, **kwargs)
-if Axes.scatter_classic.__doc__ is not None:
- scatter_classic.__doc__ = dedent(Axes.scatter_classic.__doc__)
-
-def pcolor_classic(*args, **kwargs):
- return gca().pcolor_classic(*args, **kwargs)
-if Axes.pcolor_classic.__doc__ is not None:
- pcolor_classic.__doc__ = dedent(Axes.pcolor_classic.__doc__)
-
-
-
### Do not edit below this point
# This function was autogenerated by boilerplate.py. Do not edit as
# changes will be lost
@@ -2357,27 +2286,6 @@
# This function was autogenerated by boilerplate.py. Do not edit as
# changes will be lost
-def quiver2(*args, **kwargs):
- # allow callers to override the hold state by passing hold=True|False
- b = ishold()
- h = popd(kwargs, 'hold', None)
- if h is not None:
- hold(h)
- try:
- ret = gca().quiver2(*args, **kwargs)
- draw_if_interactive()
- except:
- hold(b)
- raise
- gci._current = ret
- hold(b)
- return ret
-if Axes.quiver2.__doc__ is not None:
- quiver2.__doc__ = dedent(Axes.quiver2.__doc__) + """
-Addition kwargs: hold = [True|False] overrides default hold state"""
-
-# This function was autogenerated by boilerplate.py. Do not edit as
-# changes will be lost
def quiverkey(*args, **kwargs):
# allow callers to override the hold state by passing hold=True|False
b = ishold()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fer...@us...> - 2007-07-30 06:04:43
|
Revision: 3629
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3629&view=rev
Author: fer_perez
Date: 2007-07-29 23:04:41 -0700 (Sun, 29 Jul 2007)
Log Message:
-----------
cleaner fill implementation
Modified Paths:
--------------
trunk/py4science/examples/schrodinger/schrod_fdtd.py
Modified: trunk/py4science/examples/schrodinger/schrod_fdtd.py
===================================================================
--- trunk/py4science/examples/schrodinger/schrod_fdtd.py 2007-07-30 02:04:46 UTC (rev 3628)
+++ trunk/py4science/examples/schrodinger/schrod_fdtd.py 2007-07-30 06:04:41 UTC (rev 3629)
@@ -80,6 +80,16 @@
v[npts/2:npts/2+thickness] = v0
return v
+def fillax(x,y,*args,**kw):
+ """Fill the space between an array of y values and the x axis.
+
+ All args/kwargs are passed to the pylab.fill function.
+ Returns the value of the pylab.fill() call.
+ """
+ xx = np.concatenate((x,np.array([x[-1],x[0]],x.dtype)))
+ yy = np.concatenate((y,np.zeros(2,y.dtype)))
+ return pylab.fill(xx, yy, *args,**kw)
+
#=============================================================================
#
# Simulation Constants. Be sure to include decimal points on appropriate
@@ -213,14 +223,12 @@
# in light red, as well as drawing a green line at the wavepacket's total
# energy, in the same units the potential is being plotted.
if Vmax !=0 :
+ # Scaling factor for energies, so they fit in the same plot as the
+ # wavefunctions
Efac = ymax/2.0/Vmax
V_plot = V*Efac
pylab.plot(X,V_plot,':k',zorder=0) # Potential line.
- # reverse x and y2 so the polygon fills in order
- y1 = free(N) # lower boundary for polygon drawing
- x = np.concatenate( (X,X[::-1]) )
- y = np.concatenate( (y1,V_plot[::-1]) )
- pylab.fill(x, y, facecolor='y', alpha=0.2,zorder=0)
+ fillax(X,V_plot, facecolor='y', alpha=0.2,zorder=0)
# Plot the wavefunction energy, in the same scale as the potential
pylab.axhline(E*Efac,color='g',label='Energy',zorder=1)
pylab.legend(loc='lower right')
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ef...@us...> - 2007-07-30 02:04:54
|
Revision: 3628
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3628&view=rev
Author: efiring
Date: 2007-07-29 19:04:46 -0700 (Sun, 29 Jul 2007)
Log Message:
-----------
changed pcolor default to shading='flat'; related cleanups
Modified Paths:
--------------
trunk/matplotlib/API_CHANGES
trunk/matplotlib/CHANGELOG
trunk/matplotlib/examples/pcolor_demo.py
trunk/matplotlib/examples/pcolor_log.py
trunk/matplotlib/examples/pcolor_small.py
trunk/matplotlib/lib/matplotlib/artist.py
trunk/matplotlib/lib/matplotlib/axes.py
trunk/matplotlib/lib/matplotlib/collections.py
Modified: trunk/matplotlib/API_CHANGES
===================================================================
--- trunk/matplotlib/API_CHANGES 2007-07-29 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/API_CHANGES 2007-07-30 02:04:46 UTC (rev 3628)
@@ -1,3 +1,6 @@
+ Changed pcolor default to shading='flat'; but as noted now in the
+ docstring, it is preferable to simply use the edgecolor kwarg.
+
The mathtext font commands (\cal, \rm, \it, \tt) now behave as TeX
does: they are in effect until the next font change command or the
end of the grouping. Therefore uses of $\cal{R}$ should be
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2007-07-29 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/CHANGELOG 2007-07-30 02:04:46 UTC (rev 3628)
@@ -1,54 +1,58 @@
+2007-07-29 Changed default pcolor shading to flat; added aliases
+ to make collection kwargs agree with setter names, so
+ updating works; related minor cleanups.
+
2007-07-26 Major rewrite of mathtext.py, using the TeX box layout model.
- There is one (known) backward incompatible change. The
- font commands (\cal, \rm, \it, \tt) now behave as TeX does:
- they are in effect until the next font change command or
- the end of the grouping. Therefore uses of $\cal{R}$
- should be changed to ${\cal R}$. Alternatively, you may
- use the new LaTeX-style font commands (\mathcal, \mathrm,
- \mathit, \mathtt) which do affect the following group,
- eg. $\mathcal{R}$.
+ There is one (known) backward incompatible change. The
+ font commands (\cal, \rm, \it, \tt) now behave as TeX does:
+ they are in effect until the next font change command or
+ the end of the grouping. Therefore uses of $\cal{R}$
+ should be changed to ${\cal R}$. Alternatively, you may
+ use the new LaTeX-style font commands (\mathcal, \mathrm,
+ \mathit, \mathtt) which do affect the following group,
+ eg. $\mathcal{R}$.
- Other new features include:
+ Other new features include:
- - Math may be interspersed with non-math text. Any text
+ - Math may be interspersed with non-math text. Any text
with an even number of $'s (non-escaped) will be sent to
- the mathtext parser for layout.
+ the mathtext parser for layout.
- - Sub/superscripts are less likely to accidentally overlap.
+ - Sub/superscripts are less likely to accidentally overlap.
- - Support for sub/superscripts in either order, eg. $x^i_j$
+ - Support for sub/superscripts in either order, eg. $x^i_j$
and $x_j^i$ are equivalent.
- - Double sub/superscripts (eg. $x_i_j$) are considered
+ - Double sub/superscripts (eg. $x_i_j$) are considered
ambiguous and raise an exception. Use braces to disambiguate.
- - $\frac{x}{y}$ can be used for displaying fractions.
+ - $\frac{x}{y}$ can be used for displaying fractions.
- - $\sqrt[3]{x}$ can be used to display the radical symbol
+ - $\sqrt[3]{x}$ can be used to display the radical symbol
with a root number and body.
- - $\left(\frac{x}{y}\right)$ may be used to create
+ - $\left(\frac{x}{y}\right)$ may be used to create
parentheses and other delimiters that automatically
resize to the height of their contents.
- - Spacing around operators etc. is now generally more like
+ - Spacing around operators etc. is now generally more like
TeX.
- - Added support (and fonts) for boldface (\bf) and
+ - Added support (and fonts) for boldface (\bf) and
sans-serif (\sf) symbols.
- - Log-like function name shortcuts are supported. For
+ - Log-like function name shortcuts are supported. For
example, $\sin(x)$ may be used instead of ${\rm sin}(x)$
- - Limited use of kerning for the easy case (same font)
+ - Limited use of kerning for the easy case (same font)
- Behind the scenes, the pyparsing.py module used for doing
- the math parsing was updated to the latest stable version
- (1.4.6). A lot of duplicate code was refactored out of the
- Font classes.
+ Behind the scenes, the pyparsing.py module used for doing
+ the math parsing was updated to the latest stable version
+ (1.4.6). A lot of duplicate code was refactored out of the
+ Font classes.
- - MGD
+ - MGD
2007-07-19 completed numpification of most trivial cases - NN
@@ -56,11 +60,11 @@
2007-07-19 replaced the Python code in numerix/ by a minimal wrapper around
numpy that explicitly mentions all symbols that need to be
- addressed for further numpification - NN
+ addressed for further numpification - NN
-2007-07-18 make usetex respect changes to rcParams. texmanager used to
- only configure itself when it was created, now it
- reconfigures when rcParams are changed. Thank you Alexander
+2007-07-18 make usetex respect changes to rcParams. texmanager used to
+ only configure itself when it was created, now it
+ reconfigures when rcParams are changed. Thank you Alexander
Schmolck for contributing a patch - DSD
2007-07-17 added validation to setting and changing rcParams - DSD
@@ -71,7 +75,7 @@
2007-07-16 clean up some code in ticker.ScalarFormatter, use unicode to
render multiplication sign in offset ticklabel - DSD
-2007-07-16 fixed a formatting bug in ticker.ScalarFormatter's scientific
+2007-07-16 fixed a formatting bug in ticker.ScalarFormatter's scientific
notation (10^0 was being rendered as 10 in some cases) - DSD
2007-07-13 Add MPL_isfinite64() and MPL_isinf64() for testing
@@ -83,7 +87,7 @@
2007-07-13 Removed the rest of the numerix extension code detritus,
numpified axes.py, and cleaned up the imports in axes.py
- - JDH
+ - JDH
2007-07-13 Added legend.loc as configurable option that could in
future default to 'best'. - NN
@@ -552,35 +556,35 @@
2006-10-10 deactivated rcfile-configurability of markerfacecolor
and markeredgecolor. Both are now hardcoded to the special value
- 'auto' to follow the line color. Configurability at run-time
- (using function arguments) remains functional. - NN
+ 'auto' to follow the line color. Configurability at run-time
+ (using function arguments) remains functional. - NN
2006-10-07 introduced dummy argument magnification=1.0 to
FigImage.make_image to satisfy unit test figimage_demo.py
The argument is not yet handled correctly, which should only
- show up when using non-standard DPI settings in PS backend,
- introduced by patch #1562394. - NN
+ show up when using non-standard DPI settings in PS backend,
+ introduced by patch #1562394. - NN
2006-10-06 add backend-agnostic example: simple3d.py - NN
2006-09-29 fix line-breaking for SVG-inline images (purely cosmetic) - NN
2006-09-29 reworked set_linestyle and set_marker
- markeredgecolor and markerfacecolor now default to
- a special value "auto" that keeps the color in sync with
- the line color
- further, the intelligence of axes.plot is cleaned up,
- improved and simplified. Complete compatibility cannot be
- guaranteed, but the new behavior should be much more predictable
- (see patch #1104615 for details) - NN
+ markeredgecolor and markerfacecolor now default to
+ a special value "auto" that keeps the color in sync with
+ the line color
+ further, the intelligence of axes.plot is cleaned up,
+ improved and simplified. Complete compatibility cannot be
+ guaranteed, but the new behavior should be much more predictable
+ (see patch #1104615 for details) - NN
2006-09-29 changed implementation of clip-path in SVG to work around a
limitation in inkscape - NN
2006-09-29 added two options to matplotlibrc:
- svg.image_inline
- svg.image_noscale
- see patch #1533010 for details - NN
+ svg.image_inline
+ svg.image_noscale
+ see patch #1533010 for details - NN
2006-09-29 axes.py: cleaned up kwargs checking - NN
@@ -611,8 +615,8 @@
2006-09-05 Released 0.87.5 at revision 2761
2006-09-04 Added nxutils for some numeric add-on extension code --
- specifically a better/more efficient inside polygon tester (see
- unit/inside_poly_*.py) - JDH
+ specifically a better/more efficient inside polygon tester (see
+ unit/inside_poly_*.py) - JDH
2006-09-04 Made bitstream fonts the rc default - JDH
@@ -957,7 +961,7 @@
2006-03-20 Added contour.negative_linestyle rcParam - ADS
2006-03-20 Added _isnan extension module to test for nan with Numeric
- - ADS
+ - ADS
2006-03-17 Added Paul and Alex's support for faceting with quadmesh
in sf patch 1411223 - JDH
@@ -1304,7 +1308,7 @@
2005-11-09 added axisbelow attr for Axes to determine whether ticks and such
- are above or below the actors
+ are above or below the actors
2005-11-08 Added Nicolas' irregularly spaced image patch
@@ -1461,7 +1465,7 @@
2005-07-24 backend_gtk.py: modify print_figure() use own pixmap, fixing
problems where print_figure() overwrites the display pixmap.
- return False from all button/key etc events - to allow the event
+ return False from all button/key etc events - to allow the event
to propagate further - SC
2005-07-23 backend_gtk.py: change expose_event from using set_back_pixmap();
@@ -1483,7 +1487,7 @@
2005-07-14 Fixed a Windows related bug (#1238412) in texmanager - DSD
2005-07-11 Fixed color kwarg bug, setting color=1 or 0 caused an
- exception - DSD
+ exception - DSD
2005-07-07 Added Eric's MA set_xdata Line2D fix - JDH
@@ -1585,10 +1589,10 @@
2005-06-13 Exposed cap and join style for lines with new rc params and
line properties
- lines.dash_joinstyle : miter # miter|round|bevel
- lines.dash_capstyle : butt # butt|round|projecting
- lines.solid_joinstyle : miter # miter|round|bevel
- lines.solid_capstyle : projecting # butt|round|projecting
+ lines.dash_joinstyle : miter # miter|round|bevel
+ lines.dash_capstyle : butt # butt|round|projecting
+ lines.solid_joinstyle : miter # miter|round|bevel
+ lines.solid_capstyle : projecting # butt|round|projecting
2005-06-13 Added kwargs to Axes init
@@ -1702,9 +1706,9 @@
for the interp kwarg are
'nearest', 'bilinear', 'bicubic', 'spline16', 'spline36',
- 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric',
- 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc',
- 'lanczos', 'blackman'
+ 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric',
+ 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc',
+ 'lanczos', 'blackman'
See help(imshow) for details, particularly the
interpolation, filternorm and filterrad kwargs
Modified: trunk/matplotlib/examples/pcolor_demo.py
===================================================================
--- trunk/matplotlib/examples/pcolor_demo.py 2007-07-29 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/examples/pcolor_demo.py 2007-07-30 02:04:46 UTC (rev 3628)
@@ -19,7 +19,7 @@
X,Y = meshgrid(x, y)
Z = func3(X, Y)
-pcolor(X, Y, Z, shading='flat')
+pcolor(X, Y, Z)
colorbar()
axis([-3,3,-3,3])
savefig('pcolor_demo')
Modified: trunk/matplotlib/examples/pcolor_log.py
===================================================================
--- trunk/matplotlib/examples/pcolor_log.py 2007-07-29 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/examples/pcolor_log.py 2007-07-30 02:04:46 UTC (rev 3628)
@@ -15,11 +15,11 @@
Z1 = bivariate_normal(X, Y, 0.1, 0.2, 1.0, 1.0) + 0.1*bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
subplot(2,1,1)
-pcolor(X, Y, Z1, shading='flat', norm=LogNorm(vmin=Z1.min(), vmax=Z1.max()))
+pcolor(X, Y, Z1, norm=LogNorm(vmin=Z1.min(), vmax=Z1.max()))
colorbar()
subplot(2,1,2)
-pcolor(X, Y, Z1, shading='flat')
+pcolor(X, Y, Z1)
colorbar()
Modified: trunk/matplotlib/examples/pcolor_small.py
===================================================================
--- trunk/matplotlib/examples/pcolor_small.py 2007-07-29 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/examples/pcolor_small.py 2007-07-30 02:04:46 UTC (rev 3628)
@@ -2,15 +2,14 @@
from pylab import *
-#Z = arange(60)
-#Z.shape = 6,10
-#Z.shape = 10,6
-#print Z
-Z = rand(10,6)
+Z = rand(6,10)
-#c = pcolor(Z, shading='flat') # default 'faceted'
+subplot(2,1,1)
c = pcolor(Z)
-c.set_linewidth(4)
+title('default: no edges')
-#savefig('pcolor_small')
+subplot(2,1,2)
+c = pcolor(Z, edgecolors='k', linewidths=4)
+title('thick edges')
+
show()
Modified: trunk/matplotlib/lib/matplotlib/artist.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/artist.py 2007-07-29 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/lib/matplotlib/artist.py 2007-07-30 02:04:46 UTC (rev 3628)
@@ -55,7 +55,7 @@
Remove the artist from the figure if possible. The effect will not
be visible until the figure is redrawn, e.g., with ax.draw_idle().
Call ax.relim() to update the axes limits if desired.
-
+
Note: relim() will not see collections even if the collection
was added to axes with autolim=True.
@@ -63,10 +63,10 @@
'''
# There is no method to set the callback. Instead the parent should set
- # the _remove_method attribute directly. This would be a protected
+ # the _remove_method attribute directly. This would be a protected
# attribute if Python supported that sort of thing. The callback
# has one parameter, which is the child to be removed.
- if self._remove_method != None:
+ if self._remove_method != None:
self._remove_method(self)
else:
raise NotImplementedError('cannot remove artist')
Modified: trunk/matplotlib/lib/matplotlib/axes.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/axes.py 2007-07-29 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/lib/matplotlib/axes.py 2007-07-30 02:04:46 UTC (rev 3628)
@@ -3853,7 +3853,7 @@
will be plotted.
Other keyword args; the color mapping and normalization arguments will
- on be used if c is an array of floats
+ be used only if c is an array of floats
* cmap = cm.jet : a colors.Colormap instance from cm.
defaults to rc image.cmap
@@ -3876,7 +3876,12 @@
* faceted: if True, will use the default edgecolor for the
markers. If False, will set the edgecolors to be the same
- as the facecolors
+ as the facecolors.
+ This kwarg is deprecated;
+ please use the edgecolors kwarg instead:
+ shading='flat' --> edgecolors='None'
+ shading='faceted --> edgecolors=None
+ edgecolors also can be any mpl color or sequence of colors.
Optional kwargs control the PatchCollection properties:
%(PatchCollection)s
@@ -4468,7 +4473,14 @@
instance, vmin and vmax will be None
* shading = 'flat' : or 'faceted'. If 'faceted', a black grid is
- drawn around each rectangle; if 'flat', edges are not drawn
+ drawn around each rectangle; if 'flat', edges are not drawn.
+ Default is 'flat', contrary to Matlab(TM).
+ This kwarg is deprecated;
+ please use the edgecolors kwarg instead:
+ shading='flat' --> edgecolors='None'
+ shading='faceted --> edgecolors='k'
+ edgecolors can also be None to specify the rcParams
+ default, or any mpl color or sequence of colors.
* alpha=1.0 : the alpha blending value
@@ -4526,7 +4538,7 @@
cmap = kwargs.pop('cmap', None)
vmin = kwargs.pop('vmin', None)
vmax = kwargs.pop('vmax', None)
- shading = kwargs.pop('shading', 'faceted')
+ shading = kwargs.pop('shading', 'flat')
if len(args)==1:
C = args[0]
@@ -4586,14 +4598,11 @@
edgecolors = (0,0,0,1),
else:
edgecolors = 'None'
+ kwargs.setdefault('edgecolors', edgecolors)
+ kwargs.setdefault('antialiaseds', (0,))
+ kwargs.setdefault('linewidths', (0.25,))
- collection = mcoll.PolyCollection(
- verts,
- edgecolors = edgecolors,
- antialiaseds = (0,),
- linewidths = (0.25,),
- **kwargs
- )
+ collection = mcoll.PolyCollection(verts, **kwargs)
collection.set_alpha(alpha)
collection.set_array(C)
@@ -4652,8 +4661,14 @@
min and max of the color array C is used.
* shading = 'flat' : or 'faceted'. If 'faceted', a black grid is
- drawn around each rectangle; if 'flat', edge colors are same as
- face colors
+ drawn around each rectangle; if 'flat', edges are not drawn.
+ Default is 'flat', contrary to Matlab(TM).
+ This kwarg is deprecated;
+ please use the edgecolors kwarg instead:
+ shading='flat' --> edgecolors='None'
+ shading='faceted --> edgecolors='k'
+ More flexible specification of edgecolors, as in pcolor,
+ is not presently supported.
* alpha=1.0 : the alpha blending value
@@ -4675,7 +4690,8 @@
cmap = kwargs.pop('cmap', None)
vmin = kwargs.pop('vmin', None)
vmax = kwargs.pop('vmax', None)
- shading = kwargs.pop('shading', 'faceted')
+ shading = kwargs.pop('shading', 'flat')
+ edgecolors = kwargs.pop('edgecolors', 'None')
if len(args)==1:
C = args[0]
@@ -4703,13 +4719,13 @@
coords[:, 0] = X
coords[:, 1] = Y
- if shading == 'faceted':
+ if shading == 'faceted' or edgecolors != 'None':
showedges = 1
else:
showedges = 0
collection = mcoll.QuadMesh(
- Nx - 1, Ny - 1, coords, showedges, **kwargs)
+ Nx - 1, Ny - 1, coords, showedges) # kwargs are not used
collection.set_alpha(alpha)
collection.set_array(C)
if norm is not None: assert(isinstance(norm, mcolors.Normalize))
Modified: trunk/matplotlib/lib/matplotlib/collections.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/collections.py 2007-07-29 08:03:12 UTC (rev 3627)
+++ trunk/matplotlib/lib/matplotlib/collections.py 2007-07-30 02:04:46 UTC (rev 3628)
@@ -21,16 +21,12 @@
class Collection(artist.Artist):
"""
- All properties in a collection must be sequences. The
+ All properties in a collection must be sequences or scalars;
+ if scalars, they will be converted to sequences. The
property of the ith element of the collection is the
prop[i % len(props)].
- This implies that the properties cycle if the len of props is less
- than the number of elements of the collection. A length 1
- property is shared by all the elements of the collection
-
- All color args to a collection are sequences of rgba tuples
"""
def __init__(self):
@@ -133,8 +129,8 @@
linewidths = (0,)
else:
self._edgecolors = _colors.colorConverter.to_rgba_list(edgecolors)
- self._linewidths = linewidths
- self._antialiaseds = antialiaseds
+ self._linewidths = self._get_value(linewidths)
+ self._antialiaseds = self._get_value(antialiaseds)
#self._offsets = offsets
self._offsets = offsets
self._transOffset = transOffset
@@ -221,6 +217,8 @@
ACCEPTS: float or sequence of floats
"""
self._linewidths = self._get_value(lw)
+ def set_linewidths(self, lw):
+ self.set_linewidth(lw)
def set_color(self, c):
"""
@@ -242,16 +240,23 @@
ACCEPTS: matplotlib color arg or sequence of rgba tuples
"""
self._facecolors = _colors.colorConverter.to_rgba_list(c)
+ def set_facecolors(self, c):
+ self.set_facecolor(c)
def set_edgecolor(self, c):
"""
- Set the facecolor(s) of the collection. c can be a matplotlib color
+ Set the edgecolor(s) of the collection. c can be a matplotlib color
arg (all patches have same color), or a a sequence or rgba tuples; if
it is a sequence the patches will cycle through the sequence
ACCEPTS: matplotlib color arg or sequence of rgba tuples
"""
- self._edgecolors = _colors.colorConverter.to_rgba_list(c)
+ if c == 'None':
+ self._linewidths = (0.0,)
+ else:
+ self._edgecolors = _colors.colorConverter.to_rgba_list(c)
+ def set_edgecolors(self, c):
+ self.set_edgecolor(c)
def set_alpha(self, alpha):
"""
@@ -568,7 +573,8 @@
class LineCollection(Collection, cm.ScalarMappable):
"""
- All parameters must be sequences. The property of the ith line
+ All parameters must be sequences or scalars; if scalars, they will
+ be converted to sequences. The property of the ith line
segment is the prop[i % len(props)], ie the properties cycle if
the len of props is less than the number of sements
"""
@@ -637,8 +643,8 @@
antialiaseds = (mpl.rcParams['lines.antialiased'], )
self._colors = _colors.colorConverter.to_rgba_list(colors)
- self._aa = antialiaseds
- self._lw = linewidths
+ self._aa = self._get_value(antialiaseds)
+ self._lw = self._get_value(linewidths)
self.set_linestyle(linestyle)
self._uniform_offsets = None
if offsets is not None:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fer...@us...> - 2007-07-29 08:03:17
|
Revision: 3627
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3627&view=rev
Author: fer_perez
Date: 2007-07-29 01:03:12 -0700 (Sun, 29 Jul 2007)
Log Message:
-----------
Small optimization.
Modified Paths:
--------------
trunk/py4science/examples/schrodinger/schrod_fdtd.py
Modified: trunk/py4science/examples/schrodinger/schrod_fdtd.py
===================================================================
--- trunk/py4science/examples/schrodinger/schrod_fdtd.py 2007-07-29 06:50:34 UTC (rev 3626)
+++ trunk/py4science/examples/schrodinger/schrod_fdtd.py 2007-07-29 08:03:12 UTC (rev 3627)
@@ -237,22 +237,26 @@
IDX2 = range(2,N) # psi [ k + 1 ]
IDX3 = range(0,N-2) # psi [ k - 1 ]
-for t in range(0,T+1):
+for t in range(T+1):
+ # Precompute a couple of indexing constants, this speeds up the computation
+ psi_rPR = psi_r[PR]
+ psi_iPR = psi_i[PR]
+
# Apply the update equations.
psi_i[FU,IDX1] = psi_i[PA,IDX1] + \
- c1*(psi_r[PR,IDX2] - 2*psi_r[PR,IDX1] +
- psi_r[PR,IDX3])
- psi_i[FU] = psi_i[FU] - c2V*psi_r[PR]
+ c1*(psi_rPR[IDX2] - 2*psi_rPR[IDX1] +
+ psi_rPR[IDX3])
+ psi_i[FU] -= c2V*psi_r[PR]
psi_r[FU,IDX1] = psi_r[PA,IDX1] - \
- c1*(psi_i[PR,IDX2] - 2*psi_i[PR,IDX1] +
- psi_i[PR,IDX3])
- psi_r[FU] = psi_r[FU] + c2V*psi_i[PR]
+ c1*(psi_iPR[IDX2] - 2*psi_iPR[IDX1] +
+ psi_iPR[IDX3])
+ psi_r[FU] += c2V*psi_i[PR]
# Increment the time steps. PR -> PA and FU -> PR
- psi_r[PA] = psi_r[PR]
+ psi_r[PA] = psi_rPR
psi_r[PR] = psi_r[FU]
- psi_i[PA] = psi_i[PR]
+ psi_i[PA] = psi_iPR
psi_i[PR] = psi_i[FU]
# Only plot after a few iterations to make the simulation run faster.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fer...@us...> - 2007-07-29 06:50:35
|
Revision: 3626
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3626&view=rev
Author: fer_perez
Date: 2007-07-28 23:50:34 -0700 (Sat, 28 Jul 2007)
Log Message:
-----------
Add energy display in the same units as the potential
Modified Paths:
--------------
trunk/py4science/examples/schrodinger/schrod_fdtd.py
Modified: trunk/py4science/examples/schrodinger/schrod_fdtd.py
===================================================================
--- trunk/py4science/examples/schrodinger/schrod_fdtd.py 2007-07-28 21:31:18 UTC (rev 3625)
+++ trunk/py4science/examples/schrodinger/schrod_fdtd.py 2007-07-29 06:50:34 UTC (rev 3626)
@@ -88,7 +88,7 @@
N = 1200 # Number of spatial points.
T = 5*N # Number of time steps. 5*N is a nice value for terminating
# before anything reaches the boundaries.
-Tp = 40 # Number of time steps to increment before updating the plot.
+Tp = 50 # Number of time steps to increment before updating the plot.
dx = 1.0e0 # Spatial resolution
m = 1.0e0 # Particle mass
hbar = 1.0e0 # Plank's constant
@@ -98,7 +98,7 @@
# and thickness (for barriers), you'll see the various transmission/reflection
# regimes of quantum mechanical tunneling.
V0 = 1.0e-2 # Potential amplitude (used for steps and barriers)
-THCK = 10 # "Thickness" of the potential barrier (if appropriate
+THCK = 15 # "Thickness" of the potential barrier (if appropriate
# V-function is chosen)
# Uncomment the potential type you want to use here:
@@ -108,12 +108,12 @@
# Potential step. The height (V0) of the potential chosen above will determine
# the amount of reflection/transmission you'll observe
-#POTENTIAL = 'step'
+POTENTIAL = 'step'
# Potential barrier. Note that BOTH the potential height (V0) and thickness
# of the barrier (THCK) affect the amount of tunneling vs reflection you'll
# observe.
-POTENTIAL = 'barrier'
+#POTENTIAL = 'barrier'
# Initial wave function constants
sigma = 40.0 # Standard deviation on the Gaussian envelope (remember Heisenberg
@@ -121,6 +121,11 @@
x0 = round(N/2) - 5*sigma # Time shift
k0 = np.pi/20 # Wavenumber (note that energy is a function of k)
+# Energy for a localized gaussian wavepacket interacting with a localized
+# potential (so the interaction term can be neglected by computing the energy
+# integral over a region where V=0)
+E = (hbar**2/2.0/m)*(k0**2+0.5/sigma**2)
+
#=============================================================================
# Code begins
#
@@ -140,7 +145,7 @@
# More simulation parameters. The maximum stable time step is a function of
# the potential, V.
-Vmax = max(V) # Maximum potential of the domain.
+Vmax = V.max() # Maximum potential of the domain.
dt = hbar/(2*hbar**2/(m*dx**2)+Vmax) # Critical time step.
c1 = hbar*dt/(m*dx**2) # Constant coefficient 1.
c2 = 2*dt/hbar # Constant coefficient 2.
@@ -148,6 +153,7 @@
# Print summary info
print 'One-dimensional Schrodinger equation - time evolution'
+print 'Wavepacket energy: ',E
print 'Potential type: ',POTENTIAL
print 'Potential height V0: ',V0
print 'Barrier thickness: ',THCK
@@ -190,30 +196,40 @@
# Initialize the figure and axes.
pylab.figure()
+xmin = X.min()
+xmax = X.max()
ymax = 1.5*(psi_r[PR]).max()
-pylab.axis([X.min(),X.max(),-ymax,ymax])
+pylab.axis([xmin,xmax,-ymax,ymax])
# Initialize the plots with their own line objects. The figures plot MUCH
# faster if you simply update the lines as opposed to redrawing the entire
# figure. For reference, include the potential function as well.
-lineR, = pylab.plot(X,psi_r[PR],'b',alpha=0.7) # "Real" line
-lineI, = pylab.plot(X,psi_i[PR],'r',alpha=0.7) # "Imag" line.
-lineP, = pylab.plot(X,psi_p,'k') # "Probability" line
+lineR, = pylab.plot(X,psi_r[PR],'b',alpha=0.7,label='Real')
+lineI, = pylab.plot(X,psi_i[PR],'r',alpha=0.7,label='Imag')
+lineP, = pylab.plot(X,6*psi_p,'k',label='Prob')
pylab.title('Potential height: %.2e' % V0)
-pylab.legend(('Real','Imag','Prob'))
# For non-zero potentials, plot them and shade the classically forbidden region
-# in light red
-if V.max() !=0 :
- V_plot = V/V.max()*ymax/2
+# in light red, as well as drawing a green line at the wavepacket's total
+# energy, in the same units the potential is being plotted.
+if Vmax !=0 :
+ Efac = ymax/2.0/Vmax
+ V_plot = V*Efac
pylab.plot(X,V_plot,':k',zorder=0) # Potential line.
# reverse x and y2 so the polygon fills in order
y1 = free(N) # lower boundary for polygon drawing
x = np.concatenate( (X,X[::-1]) )
y = np.concatenate( (y1,V_plot[::-1]) )
pylab.fill(x, y, facecolor='y', alpha=0.2,zorder=0)
+ # Plot the wavefunction energy, in the same scale as the potential
+ pylab.axhline(E*Efac,color='g',label='Energy',zorder=1)
+pylab.legend(loc='lower right')
pylab.draw()
+# I think there's a problem with pylab, because it resets the xlim after
+# plotting the E line. Fix it back manually.
+pylab.xlim(xmin,xmax)
+
# Direct index assignment is MUCH faster than using a spatial FOR loop, so
# these constants are used in the update equations. Remember that Python uses
# zero-based indexing.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fer...@us...> - 2007-07-28 21:31:24
|
Revision: 3625
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3625&view=rev
Author: fer_perez
Date: 2007-07-28 14:31:18 -0700 (Sat, 28 Jul 2007)
Log Message:
-----------
Add Schrodinger equation example, contributed by James Nagel <na...@me...>
Added Paths:
-----------
trunk/py4science/examples/schrodinger/
trunk/py4science/examples/schrodinger/Schrodinger_FDTD.pdf
trunk/py4science/examples/schrodinger/schrod_fdtd.py
Added: trunk/py4science/examples/schrodinger/Schrodinger_FDTD.pdf
===================================================================
(Binary files differ)
Property changes on: trunk/py4science/examples/schrodinger/Schrodinger_FDTD.pdf
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/py4science/examples/schrodinger/schrod_fdtd.py
===================================================================
--- trunk/py4science/examples/schrodinger/schrod_fdtd.py (rev 0)
+++ trunk/py4science/examples/schrodinger/schrod_fdtd.py 2007-07-28 21:31:18 UTC (rev 3625)
@@ -0,0 +1,258 @@
+#!/usr/bin/env python
+#=============================================================================
+#
+# Quantum Mechanical Simulation using Finite-Difference
+# Time-Domain (FDTD) Method
+#
+# This script simulates a probability wave in the presence of multiple
+# potentials. The simulation is c arried out by using the FDTD algorithm
+# applied to the Schrodinger equation. The program is intended to act as
+# a demonstration of the FDTD algorithm and can be used as an educational
+# aid for quantum mechanics and numerical methods. The simulation
+# parameters are defined in the code constants and can be freely
+# manipulated to see different behaviors.
+#
+# NOTES
+#
+# The probability density plots are amplified by a factor for visual
+# purposes. The psi_p quanity contains the actual probability density
+# without any rescaling.
+#
+# BEWARE: The time step, dt, has strict requirements or else the
+# simulation becomes unstable.
+#
+# The code has three built-in potential functions for demonstration.
+#
+# 1) Constant potential: Demonstrates a free particle with dispersion.
+#
+# 2) Step potential: Demonstrates transmission and reflection.
+#
+# 3) Potential barrier: Demonstrates tunneling.
+#
+# By tweaking the height of the potential (V0 below) as well as the
+# barrier thickness (THCK below), you can see different behaviors: full
+# reflection with no noticeable transmission, transmission and
+# reflection, or mostly transmission with tunneling.
+#
+# This script requires pylab and numpy to be installed with
+# Python or else it will not run.
+#
+#============================================================================
+# Author: James Nagel <na...@me...>
+# 5/25/07
+#
+# Updates by Fernando Perez <Fer...@co...>, 7/28/07
+#============================================================================
+
+# Numerical and plotting libraries
+import numpy as np
+import pylab
+
+# Set pylab to interactive mode so plots update when run outside ipython
+pylab.ion()
+
+#=============================================================================
+
+# Utility functions
+
+# Defines a quick Gaussian pulse function to act as an envelope to the wave
+# function.
+def Gaussian(x,t,sigma):
+ """ A Gaussian curve.
+ x = Variable
+ t = time shift
+ sigma = standard deviation """
+ return np.exp(-(x-t)**2/(2*sigma**2))
+
+def free(npts):
+ "Free particle."
+ return np.zeros(npts)
+
+def step(npts,v0):
+ "Potential step"
+ v = free(npts)
+ v[npts/2:] = v0
+ return v
+
+def barrier(npts,v0,thickness):
+ "Barrier potential"
+ v = free(npts)
+ v[npts/2:npts/2+thickness] = v0
+ return v
+
+#=============================================================================
+#
+# Simulation Constants. Be sure to include decimal points on appropriate
+# variables so they become floats instead of integers.
+#
+N = 1200 # Number of spatial points.
+T = 5*N # Number of time steps. 5*N is a nice value for terminating
+ # before anything reaches the boundaries.
+Tp = 40 # Number of time steps to increment before updating the plot.
+dx = 1.0e0 # Spatial resolution
+m = 1.0e0 # Particle mass
+hbar = 1.0e0 # Plank's constant
+X = dx*np.linspace(0,N,N) # Spatial axis.
+
+# Potential parameters. By playing with the type of potential and the height
+# and thickness (for barriers), you'll see the various transmission/reflection
+# regimes of quantum mechanical tunneling.
+V0 = 1.0e-2 # Potential amplitude (used for steps and barriers)
+THCK = 10 # "Thickness" of the potential barrier (if appropriate
+ # V-function is chosen)
+
+# Uncomment the potential type you want to use here:
+
+# Zero potential, packet propagates freely.
+#POTENTIAL = 'free'
+
+# Potential step. The height (V0) of the potential chosen above will determine
+# the amount of reflection/transmission you'll observe
+#POTENTIAL = 'step'
+
+# Potential barrier. Note that BOTH the potential height (V0) and thickness
+# of the barrier (THCK) affect the amount of tunneling vs reflection you'll
+# observe.
+POTENTIAL = 'barrier'
+
+# Initial wave function constants
+sigma = 40.0 # Standard deviation on the Gaussian envelope (remember Heisenberg
+ # uncertainty).
+x0 = round(N/2) - 5*sigma # Time shift
+k0 = np.pi/20 # Wavenumber (note that energy is a function of k)
+
+#=============================================================================
+# Code begins
+#
+# You shouldn't need to change anything below unless you want to actually play
+# with the numerical algorithm or modify the plotting.
+#
+# Fill in the appropriate potential function (is there a Python equivalent to
+# the SWITCH statement?).
+if POTENTIAL=='free':
+ V = free(N)
+elif POTENTIAL=='step':
+ V = step(N,V0)
+elif POTENTIAL=='barrier':
+ V = barrier(N,V0,THCK)
+else:
+ raise ValueError("Unrecognized potential type: %s" % POTENTIAL)
+
+# More simulation parameters. The maximum stable time step is a function of
+# the potential, V.
+Vmax = max(V) # Maximum potential of the domain.
+dt = hbar/(2*hbar**2/(m*dx**2)+Vmax) # Critical time step.
+c1 = hbar*dt/(m*dx**2) # Constant coefficient 1.
+c2 = 2*dt/hbar # Constant coefficient 2.
+c2V = c2*V # pre-compute outside of update loop
+
+# Print summary info
+print 'One-dimensional Schrodinger equation - time evolution'
+print 'Potential type: ',POTENTIAL
+print 'Potential height V0: ',V0
+print 'Barrier thickness: ',THCK
+
+# Wave functions. Three states represent past, present, and future.
+psi_r = np.zeros((3,N)) # Real
+psi_i = np.zeros((3,N)) # Imaginary
+psi_p = np.zeros(N,) # Observable probability (magnitude-squared
+ # of the complex wave function).
+
+# Temporal indexing constants, used for accessing rows of the wavefunctions.
+PA = 0 # Past
+PR = 1 # Present
+FU = 2 # Future
+
+# Initialize wave function. A present-only state will "split" with half the
+# wave function propagating to the left and the other half to the right.
+# Including a "past" state will cause it to propagate one way.
+xn = range(1,N/2)
+x = X[xn]/dx # Normalized position coordinate
+gg = Gaussian(x,x0,sigma)
+cx = np.cos(k0*x)
+sx = np.sin(k0*x)
+psi_r[PR,xn] = cx*gg
+psi_i[PR,xn] = sx*gg
+psi_r[PA,xn] = cx*gg
+psi_i[PA,xn] = sx*gg
+
+# Initial normalization of wavefunctions
+# Compute the observable probability.
+psi_p = psi_r[PR]**2 + psi_i[PR]**2
+
+# Normalize the wave functions so that the total probability in the simulation
+# is equal to 1.
+P = dx * psi_p.sum() # Total probability.
+nrm = np.sqrt(P)
+psi_r /= nrm
+psi_i /= nrm
+psi_p /= P
+
+# Initialize the figure and axes.
+pylab.figure()
+ymax = 1.5*(psi_r[PR]).max()
+pylab.axis([X.min(),X.max(),-ymax,ymax])
+
+# Initialize the plots with their own line objects. The figures plot MUCH
+# faster if you simply update the lines as opposed to redrawing the entire
+# figure. For reference, include the potential function as well.
+lineR, = pylab.plot(X,psi_r[PR],'b',alpha=0.7) # "Real" line
+lineI, = pylab.plot(X,psi_i[PR],'r',alpha=0.7) # "Imag" line.
+lineP, = pylab.plot(X,psi_p,'k') # "Probability" line
+pylab.title('Potential height: %.2e' % V0)
+pylab.legend(('Real','Imag','Prob'))
+
+# For non-zero potentials, plot them and shade the classically forbidden region
+# in light red
+if V.max() !=0 :
+ V_plot = V/V.max()*ymax/2
+ pylab.plot(X,V_plot,':k',zorder=0) # Potential line.
+ # reverse x and y2 so the polygon fills in order
+ y1 = free(N) # lower boundary for polygon drawing
+ x = np.concatenate( (X,X[::-1]) )
+ y = np.concatenate( (y1,V_plot[::-1]) )
+ pylab.fill(x, y, facecolor='y', alpha=0.2,zorder=0)
+pylab.draw()
+
+# Direct index assignment is MUCH faster than using a spatial FOR loop, so
+# these constants are used in the update equations. Remember that Python uses
+# zero-based indexing.
+IDX1 = range(1,N-1) # psi [ k ]
+IDX2 = range(2,N) # psi [ k + 1 ]
+IDX3 = range(0,N-2) # psi [ k - 1 ]
+
+for t in range(0,T+1):
+ # Apply the update equations.
+ psi_i[FU,IDX1] = psi_i[PA,IDX1] + \
+ c1*(psi_r[PR,IDX2] - 2*psi_r[PR,IDX1] +
+ psi_r[PR,IDX3])
+ psi_i[FU] = psi_i[FU] - c2V*psi_r[PR]
+
+ psi_r[FU,IDX1] = psi_r[PA,IDX1] - \
+ c1*(psi_i[PR,IDX2] - 2*psi_i[PR,IDX1] +
+ psi_i[PR,IDX3])
+ psi_r[FU] = psi_r[FU] + c2V*psi_i[PR]
+
+ # Increment the time steps. PR -> PA and FU -> PR
+ psi_r[PA] = psi_r[PR]
+ psi_r[PR] = psi_r[FU]
+ psi_i[PA] = psi_i[PR]
+ psi_i[PR] = psi_i[FU]
+
+ # Only plot after a few iterations to make the simulation run faster.
+ if t % Tp == 0:
+ # Compute observable probability for the plot.
+ psi_p = psi_r[PR]**2 + psi_i[PR]**2
+
+ # Update the plots.
+ lineR.set_ydata(psi_r[PR])
+ lineI.set_ydata(psi_i[PR])
+ # Note: we plot the probability density amplified by a factor so it's a
+ # bit easier to see.
+ lineP.set_ydata(6*psi_p)
+
+ pylab.draw()
+
+# So the windows don't auto-close at the end if run outside ipython
+pylab.ioff()
+pylab.show()
Property changes on: trunk/py4science/examples/schrodinger/schrod_fdtd.py
___________________________________________________________________
Name: svn:executable
+ *
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ef...@us...> - 2007-07-27 23:34:33
|
Revision: 3624
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3624&view=rev
Author: efiring
Date: 2007-07-27 16:34:29 -0700 (Fri, 27 Jul 2007)
Log Message:
-----------
tweaked cbook.dedent, inspired by Fernando's version
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/cbook.py
Modified: trunk/matplotlib/lib/matplotlib/cbook.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/cbook.py 2007-07-27 15:45:26 UTC (rev 3623)
+++ trunk/matplotlib/lib/matplotlib/cbook.py 2007-07-27 23:34:29 UTC (rev 3624)
@@ -543,6 +543,8 @@
first line. It differs from textwrap.dedent in its
deletion of leading blank lines and its use of the
first non-blank line to determine the indentation.
+
+ It is also faster in most cases.
"""
if not s: # includes case of s is None
return ''
@@ -552,6 +554,9 @@
ii += 1
lines = lines[ii:]
nshift = len(lines[0]) - len(lines[0].lstrip())
+ # Don't use first line in case of """blah...
+ if ii == 0 and len(lines) > 1:
+ nshift = len(lines[1]) - len(lines[1].lstrip())
for i, line in enumerate(lines):
nwhite = len(line) - len(line.lstrip())
lines[i] = line[min(nshift, nwhite):]
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ds...@us...> - 2007-07-27 15:45:29
|
Revision: 3623
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3623&view=rev
Author: dsdale
Date: 2007-07-27 08:45:26 -0700 (Fri, 27 Jul 2007)
Log Message:
-----------
added config module, for testing a traited config system
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/mpl-data/matplotlibrc
Added Paths:
-----------
trunk/matplotlib/lib/matplotlib/config/
trunk/matplotlib/lib/matplotlib/config/__init__.py
trunk/matplotlib/lib/matplotlib/config/api.py
trunk/matplotlib/lib/matplotlib/config/checkdep.py
trunk/matplotlib/lib/matplotlib/config/configobj.py
trunk/matplotlib/lib/matplotlib/config/configtest.py
trunk/matplotlib/lib/matplotlib/config/cutils.py
trunk/matplotlib/lib/matplotlib/config/matplotlib.conf.default
trunk/matplotlib/lib/matplotlib/config/mplconfig.py
trunk/matplotlib/lib/matplotlib/config/mpltraits.py
trunk/matplotlib/lib/matplotlib/config/rcparams.py
trunk/matplotlib/lib/matplotlib/config/rcsetup.py
trunk/matplotlib/lib/matplotlib/config/tconfig.py
trunk/matplotlib/lib/matplotlib/config/verbose.py
trunk/matplotlib/lib/matplotlib/mpl-data/matplotlib.conf
Added: trunk/matplotlib/lib/matplotlib/config/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/__init__.py (rev 0)
+++ trunk/matplotlib/lib/matplotlib/config/__init__.py 2007-07-27 15:45:26 UTC (rev 3623)
@@ -0,0 +1 @@
+# Please keep this file empty
\ No newline at end of file
Property changes on: trunk/matplotlib/lib/matplotlib/config/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/matplotlib/lib/matplotlib/config/api.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/api.py (rev 0)
+++ trunk/matplotlib/lib/matplotlib/config/api.py 2007-07-27 15:45:26 UTC (rev 3623)
@@ -0,0 +1,12 @@
+"""
+"""
+
+USE_NEW_CONFIG = True
+
+from rcparams import rc
+from cutils import get_config_file
+
+if USE_NEW_CONFIG:
+ from mplconfig import rcParams, mplConfig, save_config
+else:
+ from rcparams import rcParams
Property changes on: trunk/matplotlib/lib/matplotlib/config/api.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/matplotlib/lib/matplotlib/config/checkdep.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/checkdep.py (rev 0)
+++ trunk/matplotlib/lib/matplotlib/config/checkdep.py 2007-07-27 15:45:26 UTC (rev 3623)
@@ -0,0 +1,133 @@
+import os, re, sys
+import distutils.version as version
+
+def dvipng():
+ try:
+ stdin, stdout = os.popen4('dvipng -version')
+ line = stdout.readlines()[1]
+ v = line.split()[-1]
+ float(v)
+ return v
+ except (IndexError, ValueError):
+ return None
+
+def ghostscript():
+ try:
+ if sys.platform == 'win32':
+ command = 'gswin32c -v'
+ else:
+ command = 'gs -v'
+ stdin, stdout = os.popen4(command)
+ line = stdout.readlines()[0]
+ v = line.split()[2]
+ vtest = '.'.join(v.split('.')[:2]) # deal with version numbers like '7.07.1'
+ float(vtest)
+ return vtest
+ except (IndexError, ValueError):
+ return None
+
+def tex():
+ try:
+ stdin, stdout = os.popen4('tex -version')
+ line = stdout.readlines()[0]
+ pattern = '3\.1\d+'
+ match = re.search(pattern, line)
+ v = match.group(0)
+ float(v)
+ return v
+ except (IndexError, ValueError):
+ return None
+
+def pdftops():
+ try:
+ stdin, stdout = os.popen4('pdftops -v')
+ for line in stdout.readlines():
+ if 'version' in line:
+ v = line.split()[-1]
+ float(v)
+ return v
+ except (IndexError, ValueError):
+ return None
+
+def compare_versions(a, b):
+ "return True if a is greater than or equal to b"
+ if a:
+ a = version.LooseVersion(a)
+ b = version.LooseVersion(b)
+ if a>=b: return True
+ else: return False
+ else: return False
+
+def ps_distiller(s):
+ if not s:
+ return False
+
+ flag = True
+ gs_req = '7.07'
+ gs_sugg = '7.07'
+ gs_v = ghostscript()
+ if compare_versions(gs_v, gs_sugg): pass
+ elif compare_versions(gs_v, gs_req):
+ verbose.report(('ghostscript-%s found. ghostscript-%s or later '
+ 'is recommended to use the ps.usedistiller option.') %\
+ (gs_v, gs_sugg))
+ else:
+ flag = False
+ warnings.warn(('matplotlibrc ps.usedistiller option can not be used '
+ 'unless ghostscript-%s or later is installed on your '
+ 'system.') % gs_req)
+
+ if s == 'xpdf':
+ pdftops_req = '3.0'
+ pdftops_v = pdftops()
+ if compare_versions(pdftops_v, pdftops_req): pass
+ else:
+ flag = False
+ warnings.warn(('matplotlibrc ps.usedistiller can not be set to '
+ 'xpdf unless xpdf-%s or later is installed on your '
+ 'system.') % pdftops_req)
+
+ if flag:
+ return s
+ else:
+ return False
+
+def usetex(s):
+ if not s:
+ return False
+
+ tex_req = '3.1415'
+ gs_req = '7.07'
+ gs_sugg = '7.07'
+ dvipng_req = '1.5'
+ flag = True
+
+ tex_v = tex()
+ if compare_versions(tex_v, tex_req): pass
+ else:
+ flag = False
+ warnings.warn(('matplotlibrc text.usetex option can not be used '
+ 'unless TeX-%s or later is '
+ 'installed on your system') % tex_req)
+
+ dvipng_v = dvipng()
+ if compare_versions(dvipng_v, dvipng_req): pass
+ else:
+ flag = False
+ warnings.warn( 'matplotlibrc text.usetex can not be used with *Agg '
+ 'backend unless dvipng-1.5 or later is '
+ 'installed on your system')
+
+ gs_v = ghostscript()
+ if compare_versions(gs_v, gs_sugg): pass
+ elif compare_versions(gs_v, gs_req):
+ verbose.report(('ghostscript-%s found. ghostscript-%s or later is '
+ 'recommended for use with the text.usetex '
+ 'option.') % (gs_v, gs_sugg))
+ else:
+ flag = False
+ warnings.warn(('matplotlibrc text.usetex can not be used '
+ 'unless ghostscript-%s or later is '
+ 'installed on your system') % gs_req)
+
+ return flag
\ No newline at end of file
Property changes on: trunk/matplotlib/lib/matplotlib/config/checkdep.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/matplotlib/lib/matplotlib/config/configobj.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/configobj.py (rev 0)
+++ trunk/matplotlib/lib/matplotlib/config/configobj.py 2007-07-27 15:45:26 UTC (rev 3623)
@@ -0,0 +1,2279 @@
+# configobj.py
+# A config file reader/writer that supports nested sections in config files.
+# Copyright (C) 2005-2006 Michael Foord, Nicola Larosa
+# E-mail: fuzzyman AT voidspace DOT org DOT uk
+# nico AT tekNico DOT net
+
+# ConfigObj 4
+# http://www.voidspace.org.uk/python/configobj.html
+
+# Released subject to the BSD License
+# Please see http://www.voidspace.org.uk/python/license.shtml
+
+# Scripts maintained at http://www.voidspace.org.uk/python/index.shtml
+# For information about bugfixes, updates and support, please join the
+# ConfigObj mailing list:
+# http://lists.sourceforge.net/lists/listinfo/configobj-develop
+# Comments, suggestions and bug reports welcome.
+
+from __future__ import generators
+
+import sys
+INTP_VER = sys.version_info[:2]
+if INTP_VER < (2, 2):
+ raise RuntimeError("Python v.2.2 or later needed")
+
+import os, re
+compiler = None
+try:
+ import compiler
+except ImportError:
+ # for IronPython
+ pass
+from types import StringTypes
+from warnings import warn
+try:
+ from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE
+except ImportError:
+ # Python 2.2 does not have these
+ # UTF-8
+ BOM_UTF8 = '\xef\xbb\xbf'
+ # UTF-16, little endian
+ BOM_UTF16_LE = '\xff\xfe'
+ # UTF-16, big endian
+ BOM_UTF16_BE = '\xfe\xff'
+ if sys.byteorder == 'little':
+ # UTF-16, native endianness
+ BOM_UTF16 = BOM_UTF16_LE
+ else:
+ # UTF-16, native endianness
+ BOM_UTF16 = BOM_UTF16_BE
+
+# A dictionary mapping BOM to
+# the encoding to decode with, and what to set the
+# encoding attribute to.
+BOMS = {
+ BOM_UTF8: ('utf_8', None),
+ BOM_UTF16_BE: ('utf16_be', 'utf_16'),
+ BOM_UTF16_LE: ('utf16_le', 'utf_16'),
+ BOM_UTF16: ('utf_16', 'utf_16'),
+ }
+# All legal variants of the BOM codecs.
+# TODO: the list of aliases is not meant to be exhaustive, is there a
+# better way ?
+BOM_LIST = {
+ 'utf_16': 'utf_16',
+ 'u16': 'utf_16',
+ 'utf16': 'utf_16',
+ 'utf-16': 'utf_16',
+ 'utf16_be': 'utf16_be',
+ 'utf_16_be': 'utf16_be',
+ 'utf-16be': 'utf16_be',
+ 'utf16_le': 'utf16_le',
+ 'utf_16_le': 'utf16_le',
+ 'utf-16le': 'utf16_le',
+ 'utf_8': 'utf_8',
+ 'u8': 'utf_8',
+ 'utf': 'utf_8',
+ 'utf8': 'utf_8',
+ 'utf-8': 'utf_8',
+ }
+
+# Map of encodings to the BOM to write.
+BOM_SET = {
+ 'utf_8': BOM_UTF8,
+ 'utf_16': BOM_UTF16,
+ 'utf16_be': BOM_UTF16_BE,
+ 'utf16_le': BOM_UTF16_LE,
+ None: BOM_UTF8
+ }
+
+try:
+ from validate import VdtMissingValue
+except ImportError:
+ VdtMissingValue = None
+
+try:
+ enumerate
+except NameError:
+ def enumerate(obj):
+ """enumerate for Python 2.2."""
+ i = -1
+ for item in obj:
+ i += 1
+ yield i, item
+
+try:
+ True, False
+except NameError:
+ True, False = 1, 0
+
+
+__version__ = '4.4.0'
+
+__revision__ = '$Id: configobj.py 156 2006-01-31 14:57:08Z fuzzyman $'
+
+__docformat__ = "restructuredtext en"
+
+__all__ = (
+ '__version__',
+ 'DEFAULT_INDENT_TYPE',
+ 'DEFAULT_INTERPOLATION',
+ 'ConfigObjError',
+ 'NestingError',
+ 'ParseError',
+ 'DuplicateError',
+ 'ConfigspecError',
+ 'ConfigObj',
+ 'SimpleVal',
+ 'InterpolationError',
+ 'InterpolationLoopError',
+ 'MissingInterpolationOption',
+ 'RepeatSectionError',
+ 'UnreprError',
+ 'UnknownType',
+ '__docformat__',
+ 'flatten_errors',
+)
+
+DEFAULT_INTERPOLATION = 'configparser'
+DEFAULT_INDENT_TYPE = ' '
+MAX_INTERPOL_DEPTH = 10
+
+OPTION_DEFAULTS = {
+ 'interpolation': True,
+ 'raise_errors': False,
+ 'list_values': True,
+ 'create_empty': False,
+ 'file_error': False,
+ 'configspec': None,
+ 'stringify': True,
+ # option may be set to one of ('', ' ', '\t')
+ 'indent_type': None,
+ 'encoding': None,
+ 'default_encoding': None,
+ 'unrepr': False,
+ 'write_empty_values': False,
+}
+
+
+def getObj(s):
+ s = "a=" + s
+ if compiler is None:
+ raise ImportError('compiler module not available')
+ p = compiler.parse(s)
+ return p.getChildren()[1].getChildren()[0].getChildren()[1]
+
+class UnknownType(Exception):
+ pass
+
+class Builder:
+
+ def build(self, o):
+ m = getattr(self, 'build_' + o.__class__.__name__, None)
+ if m is None:
+ raise UnknownType(o.__class__.__name__)
+ return m(o)
+
+ def build_List(self, o):
+ return map(self.build, o.getChildren())
+
+ def build_Const(self, o):
+ return o.value
+
+ def build_Dict(self, o):
+ d = {}
+ i = iter(map(self.build, o.getChildren()))
+ for el in i:
+ d[el] = i.next()
+ return d
+
+ def build_Tuple(self, o):
+ return tuple(self.build_List(o))
+
+ def build_Name(self, o):
+ if o.name == 'None':
+ return None
+ if o.name == 'True':
+ return True
+ if o.name == 'False':
+ return False
+
+ # An undefinted Name
+ raise UnknownType('Undefined Name')
+
+ def build_Add(self, o):
+ real, imag = map(self.build_Const, o.getChildren())
+ try:
+ real = float(real)
+ except TypeError:
+ raise UnknownType('Add')
+ if not isinstance(imag, complex) or imag.real != 0.0:
+ raise UnknownType('Add')
+ return real+imag
+
+ def build_Getattr(self, o):
+ parent = self.build(o.expr)
+ return getattr(parent, o.attrname)
+
+ def build_UnarySub(self, o):
+ return -self.build_Const(o.getChildren()[0])
+
+ def build_UnaryAdd(self, o):
+ return self.build_Const(o.getChildren()[0])
+
+def unrepr(s):
+ if not s:
+ return s
+ return Builder().build(getObj(s))
+
+def _splitlines(instring):
+ """Split a string on lines, without losing line endings or truncating."""
+
+
+class ConfigObjError(SyntaxError):
+ """
+ This is the base class for all errors that ConfigObj raises.
+ It is a subclass of SyntaxError.
+ """
+ def __init__(self, message='', line_number=None, line=''):
+ self.line = line
+ self.line_number = line_number
+ self.message = message
+ SyntaxError.__init__(self, message)
+
+class NestingError(ConfigObjError):
+ """
+ This error indicates a level of nesting that doesn't match.
+ """
+
+class ParseError(ConfigObjError):
+ """
+ This error indicates that a line is badly written.
+ It is neither a valid ``key = value`` line,
+ nor a valid section marker line.
+ """
+
+class DuplicateError(ConfigObjError):
+ """
+ The keyword or section specified already exists.
+ """
+
+class ConfigspecError(ConfigObjError):
+ """
+ An error occured whilst parsing a configspec.
+ """
+
+class InterpolationError(ConfigObjError):
+ """Base class for the two interpolation errors."""
+
+class InterpolationLoopError(InterpolationError):
+ """Maximum interpolation depth exceeded in string interpolation."""
+
+ def __init__(self, option):
+ InterpolationError.__init__(
+ self,
+ 'interpolation loop detected in value "%s".' % option)
+
+class RepeatSectionError(ConfigObjError):
+ """
+ This error indicates additional sections in a section with a
+ ``__many__`` (repeated) section.
+ """
+
+class MissingInterpolationOption(InterpolationError):
+ """A value specified for interpolation was missing."""
+
+ def __init__(self, option):
+ InterpolationError.__init__(
+ self,
+ 'missing option "%s" in interpolation.' % option)
+
+class UnreprError(ConfigObjError):
+ """An error parsing in unrepr mode."""
+
+
+class InterpolationEngine(object):
+ """
+ A helper class to help perform string interpolation.
+
+ This class is an abstract base class; its descendants perform
+ the actual work.
+ """
+
+ # compiled regexp to use in self.interpolate()
+ _KEYCRE = re.compile(r"%\(([^)]*)\)s")
+
+ def __init__(self, section):
+ # the Section instance that "owns" this engine
+ self.section = section
+
+ def interpolate(self, key, value):
+ def recursive_interpolate(key, value, section, backtrail):
+ """The function that does the actual work.
+
+ ``value``: the string we're trying to interpolate.
+ ``section``: the section in which that string was found
+ ``backtrail``: a dict to keep track of where we've been,
+ to detect and prevent infinite recursion loops
+
+ This is similar to a depth-first-search algorithm.
+ """
+ # Have we been here already?
+ if backtrail.has_key((key, section.name)):
+ # Yes - infinite loop detected
+ raise InterpolationLoopError(key)
+ # Place a marker on our backtrail so we won't come back here again
+ backtrail[(key, section.name)] = 1
+
+ # Now start the actual work
+ match = self._KEYCRE.search(value)
+ while match:
+ # The actual parsing of the match is implementation-dependent,
+ # so delegate to our helper function
+ k, v, s = self._parse_match(match)
+ if k is None:
+ # That's the signal that no further interpolation is needed
+ replacement = v
+ else:
+ # Further interpolation may be needed to obtain final value
+ replacement = recursive_interpolate(k, v, s, backtrail)
+ # Replace the matched string with its final value
+ start, end = match.span()
+ value = ''.join((value[:start], replacement, value[end:]))
+ new_search_start = start + len(replacement)
+ # Pick up the next interpolation key, if any, for next time
+ # through the while loop
+ match = self._KEYCRE.search(value, new_search_start)
+
+ # Now safe to come back here again; remove marker from backtrail
+ del backtrail[(key, section.name)]
+
+ return value
+
+ # Back in interpolate(), all we have to do is kick off the recursive
+ # function with appropriate starting values
+ value = recursive_interpolate(key, value, self.section, {})
+ return value
+
+ def _fetch(self, key):
+ """Helper function to fetch values from owning section.
+
+ Returns a 2-tuple: the value, and the section where it was found.
+ """
+ # switch off interpolation before we try and fetch anything !
+ save_interp = self.section.main.interpolation
+ self.section.main.interpolation = False
+
+ # Start at section that "owns" this InterpolationEngine
+ current_section = self.section
+ while True:
+ # try the current section first
+ val = current_section.get(key)
+ if val is not None:
+ break
+ # try "DEFAULT" next
+ val = current_section.get('DEFAULT', {}).get(key)
+ if val is not None:
+ break
+ # move up to parent and try again
+ # top-level's parent is itself
+ if current_section.parent is current_section:
+ # reached top level, time to give up
+ break
+ current_section = current_section.parent
+
+ # restore interpolation to previous value before returning
+ self.section.main.interpolation = save_interp
+ if val is None:
+ raise MissingInterpolationOption(key)
+ return val, current_section
+
+ def _parse_match(self, match):
+ """Implementation-dependent helper function.
+
+ Will be passed a match object corresponding to the interpolation
+ key we just found (e.g., "%(foo)s" or "$foo"). Should look up that
+ key in the appropriate config file section (using the ``_fetch()``
+ helper function) and return a 3-tuple: (key, value, section)
+
+ ``key`` is the name of the key we're looking for
+ ``value`` is the value found for that key
+ ``section`` is a reference to the section where it was found
+
+ ``key`` and ``section`` should be None if no further
+ interpolation should be performed on the resulting value
+ (e.g., if we interpolated "$$" and returned "$").
+ """
+ raise NotImplementedError
+
+
+class ConfigParserInterpolation(InterpolationEngine):
+ """Behaves like ConfigParser."""
+ _KEYCRE = re.compile(r"%\(([^)]*)\)s")
+
+ def _parse_match(self, match):
+ key = match.group(1)
+ value, section = self._fetch(key)
+ return key, value, section
+
+
+class TemplateInterpolation(InterpolationEngine):
+ """Behaves like string.Template."""
+ _delimiter = '$'
+ _KEYCRE = re.compile(r"""
+ \$(?:
+ (?P<escaped>\$) | # Two $ signs
+ (?P<named>[_a-z][_a-z0-9]*) | # $name format
+ {(?P<braced>[^}]*)} # ${name} format
+ )
+ """, re.IGNORECASE | re.VERBOSE)
+
+ def _parse_match(self, match):
+ # Valid name (in or out of braces): fetch value from section
+ key = match.group('named') or match.group('braced')
+ if key is not None:
+ value, section = self._fetch(key)
+ return key, value, section
+ # Escaped delimiter (e.g., $$): return single delimiter
+ if match.group('escaped') is not None:
+ # Return None for key and section to indicate it's time to stop
+ return None, self._delimiter, None
+ # Anything else: ignore completely, just return it unchanged
+ return None, match.group(), None
+
+interpolation_engines = {
+ 'configparser': ConfigParserInterpolation,
+ 'template': TemplateInterpolation,
+}
+
+class Section(dict):
+ """
+ A dictionary-like object that represents a section in a config file.
+
+ It does string interpolation if the 'interpolation' attribute
+ of the 'main' object is set to True.
+
+ Interpolation is tried first from this object, then from the 'DEFAULT'
+ section of this object, next from the parent and its 'DEFAULT' section,
+ and so on until the main object is reached.
+
+ A Section will behave like an ordered dictionary - following the
+ order of the ``scalars`` and ``sections`` attributes.
+ You can use this to change the order of members.
+
+ Iteration follows the order: scalars, then sections.
+ """
+
+ def __init__(self, parent, depth, main, indict=None, name=None):
+ """
+ * parent is the section above
+ * depth is the depth level of this section
+ * main is the main ConfigObj
+ * indict is a dictionary to initialise the section with
+ """
+ if indict is None:
+ indict = {}
+ dict.__init__(self)
+ # used for nesting level *and* interpolation
+ self.parent = parent
+ # used for the interpolation attribute
+ self.main = main
+ # level of nesting depth of this Section
+ self.depth = depth
+ # the sequence of scalar values in this Section
+ self.scalars = []
+ # the sequence of sections in this Section
+ self.sections = []
+ # purely for information
+ self.name = name
+ # for comments :-)
+ self.comments = {}
+ self.inline_comments = {}
+ # for the configspec
+ self.configspec = {}
+ self._order = []
+ self._configspec_comments = {}
+ self._configspec_inline_comments = {}
+ self._cs_section_comments = {}
+ self._cs_section_inline_comments = {}
+ # for defaults
+ self.defaults = []
+ #
+ # we do this explicitly so that __setitem__ is used properly
+ # (rather than just passing to ``dict.__init__``)
+ for entry in indict:
+ self[entry] = indict[entry]
+
+ def _interpolate(self, key, value):
+ try:
+ # do we already have an interpolation engine?
+ engine = self._interpolation_engine
+ except AttributeError:
+ # not yet: first time running _interpolate(), so pick the engine
+ name = self.main.interpolation
+ if name == True: # note that "if name:" would be incorrect here
+ # backwards-compatibility: interpolation=True means use default
+ name = DEFAULT_INTERPOLATION
+ name = name.lower() # so that "Template", "template", etc. all work
+ class_ = interpolation_engines.get(name, None)
+ if class_ is None:
+ # invalid value for self.main.interpolation
+ self.main.interpolation = False
+ return value
+ else:
+ # save reference to engine so we don't have to do this again
+ engine = self._interpolation_engine = class_(self)
+ # let the engine do the actual work
+ return engine.interpolate(key, value)
+
+ def __getitem__(self, key):
+ """Fetch the item and do string interpolation."""
+ val = dict.__getitem__(self, key)
+ if self.main.interpolation and isinstance(val, StringTypes):
+ return self._interpolate(key, val)
+ return val
+
+ def __setitem__(self, key, value, unrepr=False):
+ """
+ Correctly set a value.
+
+ Making dictionary values Section instances.
+ (We have to special case 'Section' instances - which are also dicts)
+
+ Keys must be strings.
+ Values need only be strings (or lists of strings) if
+ ``main.stringify`` is set.
+
+ `unrepr`` must be set when setting a value to a dictionary, without
+ creating a new sub-section.
+ """
+ if not isinstance(key, StringTypes):
+ raise ValueError, 'The key "%s" is not a string.' % key
+ # add the comment
+ if not self.comments.has_key(key):
+ self.comments[key] = []
+ self.inline_comments[key] = ''
+ # remove the entry from defaults
+ if key in self.defaults:
+ self.defaults.remove(key)
+ #
+ if isinstance(value, Section):
+ if not self.has_key(key):
+ self.sections.append(key)
+ dict.__setitem__(self, key, value)
+ elif isinstance(value, dict) and not unrepr:
+ # First create the new depth level,
+ # then create the section
+ if not self.has_key(key):
+ self.sections.append(key)
+ new_depth = self.depth + 1
+ dict.__setitem__(
+ self,
+ key,
+ Section(
+ self,
+ new_depth,
+ self.main,
+ indict=value,
+ name=key))
+ else:
+ if not self.has_key(key):
+ self.scalars.append(key)
+ if not self.main.stringify:
+ if isinstance(value, StringTypes):
+ pass
+ elif isinstance(value, (list, tuple)):
+ for entry in value:
+ if not isinstance(entry, StringTypes):
+ raise TypeError, (
+ 'Value is not a string "%s".' % entry)
+ else:
+ raise TypeError, 'Value is not a string "%s".' % value
+ dict.__setitem__(self, key, value)
+
+ def __delitem__(self, key):
+ """Remove items from the sequence when deleting."""
+ dict. __delitem__(self, key)
+ if key in self.scalars:
+ self.scalars.remove(key)
+ else:
+ self.sections.remove(key)
+ del self.comments[key]
+ del self.inline_comments[key]
+
+ def get(self, key, default=None):
+ """A version of ``get`` that doesn't bypass string interpolation."""
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ def update(self, indict):
+ """
+ A version of update that uses our ``__setitem__``.
+ """
+ for entry in indict:
+ self[entry] = indict[entry]
+
+ def pop(self, key, *args):
+ """ """
+ val = dict.pop(self, key, *args)
+ if key in self.scalars:
+ del self.comments[key]
+ del self.inline_comments[key]
+ self.scalars.remove(key)
+ elif key in self.sections:
+ del self.comments[key]
+ del self.inline_comments[key]
+ self.sections.remove(key)
+ if self.main.interpolation and isinstance(val, StringTypes):
+ return self._interpolate(key, val)
+ return val
+
+ def popitem(self):
+ """Pops the first (key,val)"""
+ sequence = (self.scalars + self.sections)
+ if not sequence:
+ raise KeyError, ": 'popitem(): dictionary is empty'"
+ key = sequence[0]
+ val = self[key]
+ del self[key]
+ return key, val
+
+ def clear(self):
+ """
+ A version of clear that also affects scalars/sections
+ Also clears comments and configspec.
+
+ Leaves other attributes alone :
+ depth/main/parent are not affected
+ """
+ dict.clear(self)
+ self.scalars = []
+ self.sections = []
+ self.comments = {}
+ self.inline_comments = {}
+ self.configspec = {}
+
+ def setdefault(self, key, default=None):
+ """A version of setdefault that sets sequence if appropriate."""
+ try:
+ return self[key]
+ except KeyError:
+ self[key] = default
+ return self[key]
+
+ def items(self):
+ """ """
+ return zip((self.scalars + self.sections), self.values())
+
+ def keys(self):
+ """ """
+ return (self.scalars + self.sections)
+
+ def values(self):
+ """ """
+ return [self[key] for key in (self.scalars + self.sections)]
+
+ def iteritems(self):
+ """ """
+ return iter(self.items())
+
+ def iterkeys(self):
+ """ """
+ return iter((self.scalars + self.sections))
+
+ __iter__ = iterkeys
+
+ def itervalues(self):
+ """ """
+ return iter(self.values())
+
+ def __repr__(self):
+ return '{%s}' % ', '.join([('%s: %s' % (repr(key), repr(self[key])))
+ for key in (self.scalars + self.sections)])
+
+ __str__ = __repr__
+
+ # Extra methods - not in a normal dictionary
+
+ def dict(self):
+ """
+ Return a deepcopy of self as a dictionary.
+
+ All members that are ``Section`` instances are recursively turned to
+ ordinary dictionaries - by calling their ``dict`` method.
+
+ >>> n = a.dict()
+ >>> n == a
+ 1
+ >>> n is a
+ 0
+ """
+ newdict = {}
+ for entry in self:
+ this_entry = self[entry]
+ if isinstance(this_entry, Section):
+ this_entry = this_entry.dict()
+ elif isinstance(this_entry, list):
+ # create a copy rather than a reference
+ this_entry = list(this_entry)
+ elif isinstance(this_entry, tuple):
+ # create a copy rather than a reference
+ this_entry = tuple(this_entry)
+ newdict[entry] = this_entry
+ return newdict
+
+ def merge(self, indict):
+ """
+ A recursive update - useful for merging config files.
+
+ >>> a = '''[section1]
+ ... option1 = True
+ ... [[subsection]]
+ ... more_options = False
+ ... # end of file'''.splitlines()
+ >>> b = '''# File is user.ini
+ ... [section1]
+ ... option1 = False
+ ... # end of file'''.splitlines()
+ >>> c1 = ConfigObj(b)
+ >>> c2 = ConfigObj(a)
+ >>> c2.merge(c1)
+ >>> c2
+ {'section1': {'option1': 'False', 'subsection': {'more_options': 'False'}}}
+ """
+ for key, val in indict.items():
+ if (key in self and isinstance(self[key], dict) and
+ isinstance(val, dict)):
+ self[key].merge(val)
+ else:
+ self[key] = val
+
+ def rename(self, oldkey, newkey):
+ """
+ Change a keyname to another, without changing position in sequence.
+
+ Implemented so that transformations can be made on keys,
+ as well as on values. (used by encode and decode)
+
+ Also renames comments.
+ """
+ if oldkey in self.scalars:
+ the_list = self.scalars
+ elif oldkey in self.sections:
+ the_list = self.sections
+ else:
+ raise KeyError, 'Key "%s" not found.' % oldkey
+ pos = the_list.index(oldkey)
+ #
+ val = self[oldkey]
+ dict.__delitem__(self, oldkey)
+ dict.__setitem__(self, newkey, val)
+ the_list.remove(oldkey)
+ the_list.insert(pos, newkey)
+ comm = self.comments[oldkey]
+ inline_comment = self.inline_comments[oldkey]
+ del self.comments[oldkey]
+ del self.inline_comments[oldkey]
+ self.comments[newkey] = comm
+ self.inline_comments[newkey] = inline_comment
+
+ def walk(self, function, raise_errors=True,
+ call_on_sections=False, **keywargs):
+ """
+ Walk every member and call a function on the keyword and value.
+
+ Return a dictionary of the return values
+
+ If the function raises an exception, raise the errror
+ unless ``raise_errors=False``, in which case set the return value to
+ ``False``.
+
+ Any unrecognised keyword arguments you pass to walk, will be pased on
+ to the function you pass in.
+
+ Note: if ``call_on_sections`` is ``True`` then - on encountering a
+ subsection, *first* the function is called for the *whole* subsection,
+ and then recurses into it's members. This means your function must be
+ able to handle strings, dictionaries and lists. This allows you
+ to change the key of subsections as well as for ordinary members. The
+ return value when called on the whole subsection has to be discarded.
+
+ See the encode and decode methods for examples, including functions.
+
+ .. caution::
+
+ You can use ``walk`` to transform the names of members of a section
+ but you mustn't add or delete members.
+
+ >>> config = '''[XXXXsection]
+ ... XXXXkey = XXXXvalue'''.splitlines()
+ >>> cfg = ConfigObj(config)
+ >>> cfg
+ {'XXXXsection': {'XXXXkey': 'XXXXvalue'}}
+ >>> def transform(section, key):
+ ... val = section[key]
+ ... newkey = key.replace('XXXX', 'CLIENT1')
+ ... section.rename(key, newkey)
+ ... if isinstance(val, (tuple, list, dict)):
+ ... pass
+ ... else:
+ ... val = val.replace('XXXX', 'CLIENT1')
+ ... section[newkey] = val
+ >>> cfg.walk(transform, call_on_sections=True)
+ {'CLIENT1section': {'CLIENT1key': None}}
+ >>> cfg
+ {'CLIENT1section': {'CLIENT1key': 'CLIENT1value'}}
+ """
+ out = {}
+ # scalars first
+ for i in range(len(self.scalars)):
+ entry = self.scalars[i]
+ try:
+ val = function(self, entry, **keywargs)
+ # bound again in case name has changed
+ entry = self.scalars[i]
+ out[entry] = val
+ except Exception:
+ if raise_errors:
+ raise
+ else:
+ entry = self.scalars[i]
+ out[entry] = False
+ # then sections
+ for i in range(len(self.sections)):
+ entry = self.sections[i]
+ if call_on_sections:
+ try:
+ function(self, entry, **keywargs)
+ except Exception:
+ if raise_errors:
+ raise
+ else:
+ entry = self.sections[i]
+ out[entry] = False
+ # bound again in case name has changed
+ entry = self.sections[i]
+ # previous result is discarded
+ out[entry] = self[entry].walk(
+ function,
+ raise_errors=raise_errors,
+ call_on_sections=call_on_sections,
+ **keywargs)
+ return out
+
+ def decode(self, encoding):
+ """
+ Decode all strings and values to unicode, using the specified encoding.
+
+ Works with subsections and list values.
+
+ Uses the ``walk`` method.
+
+ Testing ``encode`` and ``decode``.
+ >>> m = ConfigObj(a)
+ >>> m.decode('ascii')
+ >>> def testuni(val):
+ ... for entry in val:
+ ... if not isinstance(entry, unicode):
+ ... print >> sys.stderr, type(entry)
+ ... raise AssertionError, 'decode failed.'
+ ... if isinstance(val[entry], dict):
+ ... testuni(val[entry])
+ ... elif not isinstance(val[entry], unicode):
+ ... raise AssertionError, 'decode failed.'
+ >>> testuni(m)
+ >>> m.encode('ascii')
+ >>> a == m
+ 1
+ """
+ warn('use of ``decode`` is deprecated.', DeprecationWarning)
+ def decode(section, key, encoding=encoding, warn=True):
+ """ """
+ val = section[key]
+ if isinstance(val, (list, tuple)):
+ newval = []
+ for entry in val:
+ newval.append(entry.decode(encoding))
+ elif isinstance(val, dict):
+ newval = val
+ else:
+ newval = val.decode(encoding)
+ newkey = key.decode(encoding)
+ section.rename(key, newkey)
+ section[newkey] = newval
+ # using ``call_on_sections`` allows us to modify section names
+ self.walk(decode, call_on_sections=True)
+
+ def encode(self, encoding):
+ """
+ Encode all strings and values from unicode,
+ using the specified encoding.
+
+ Works with subsections and list values.
+ Uses the ``walk`` method.
+ """
+ warn('use of ``encode`` is deprecated.', DeprecationWarning)
+ def encode(section, key, encoding=encoding):
+ """ """
+ val = section[key]
+ if isinstance(val, (list, tuple)):
+ newval = []
+ for entry in val:
+ newval.append(entry.encode(encoding))
+ elif isinstance(val, dict):
+ newval = val
+ else:
+ newval = val.encode(encoding)
+ newkey = key.encode(encoding)
+ section.rename(key, newkey)
+ section[newkey] = newval
+ self.walk(encode, call_on_sections=True)
+
+ def istrue(self, key):
+ """A deprecated version of ``as_bool``."""
+ warn('use of ``istrue`` is deprecated. Use ``as_bool`` method '
+ 'instead.', DeprecationWarning)
+ return self.as_bool(key)
+
+ def as_bool(self, key):
+ """
+ Accepts a key as input. The corresponding value must be a string or
+ the objects (``True`` or 1) or (``False`` or 0). We allow 0 and 1 to
+ retain compatibility with Python 2.2.
+
+ If the string is one of ``True``, ``On``, ``Yes``, or ``1`` it returns
+ ``True``.
+
+ If the string is one of ``False``, ``Off``, ``No``, or ``0`` it returns
+ ``False``.
+
+ ``as_bool`` is not case sensitive.
+
+ Any other input will raise a ``ValueError``.
+
+ >>> a = ConfigObj()
+ >>> a['a'] = 'fish'
+ >>> a.as_bool('a')
+ Traceback (most recent call last):
+ ValueError: Value "fish" is neither True nor False
+ >>> a['b'] = 'True'
+ >>> a.as_bool('b')
+ 1
+ >>> a['b'] = 'off'
+ >>> a.as_bool('b')
+ 0
+ """
+ val = self[key]
+ if val == True:
+ return True
+ elif val == False:
+ return False
+ else:
+ try:
+ if not isinstance(val, StringTypes):
+ raise KeyError
+ else:
+ return self.main._bools[val.lower()]
+ except KeyError:
+ raise ValueError('Value "%s" is neither True nor False' % val)
+
+ def as_int(self, key):
+ """
+ A convenience method which coerces the specified value to an integer.
+
+ If the value is an invalid literal for ``int``, a ``ValueError`` will
+ be raised.
+
+ >>> a = ConfigObj()
+ >>> a['a'] = 'fish'
+ >>> a.as_int('a')
+ Traceback (most recent call last):
+ ValueError: invalid literal for int(): fish
+ >>> a['b'] = '1'
+ >>> a.as_int('b')
+ 1
+ >>> a['b'] = '3.2'
+ >>> a.as_int('b')
+ Traceback (most recent call last):
+ ValueError: invalid literal for int(): 3.2
+ """
+ return int(self[key])
+
+ def as_float(self, key):
+ """
+ A convenience method which coerces the specified value to a float.
+
+ If the value is an invalid literal for ``float``, a ``ValueError`` will
+ be raised.
+
+ >>> a = ConfigObj()
+ >>> a['a'] = 'fish'
+ >>> a.as_float('a')
+ Traceback (most recent call last):
+ ValueError: invalid literal for float(): fish
+ >>> a['b'] = '1'
+ >>> a.as_float('b')
+ 1.0
+ >>> a['b'] = '3.2'
+ >>> a.as_float('b')
+ 3.2000000000000002
+ """
+ return float(self[key])
+
+
+class ConfigObj(Section):
+ """An object to read, create, and write config files."""
+
+ _keyword = re.compile(r'''^ # line start
+ (\s*) # indentation
+ ( # keyword
+ (?:".*?")| # double quotes
+ (?:'.*?')| # single quotes
+ (?:[^'"=].*?) # no quotes
+ )
+ \s*=\s* # divider
+ (.*) # value (including list values and comments)
+ $ # line end
+ ''',
+ re.VERBOSE)
+
+ _sectionmarker = re.compile(r'''^
+ (\s*) # 1: indentation
+ ((?:\[\s*)+) # 2: section marker open
+ ( # 3: section name open
+ (?:"\s*\S.*?\s*")| # at least one non-space with double quotes
+ (?:'\s*\S.*?\s*')| # at least one non-space with single quotes
+ (?:[^'"\s].*?) # at least one non-space unquoted
+ ) # section name close
+ ((?:\s*\])+) # 4: section marker close
+ \s*(\#.*)? # 5: optional comment
+ $''',
+ re.VERBOSE)
+
+ # this regexp pulls list values out as a single string
+ # or single values and comments
+ # FIXME: this regex adds a '' to the end of comma terminated lists
+ # workaround in ``_handle_value``
+ _valueexp = re.compile(r'''^
+ (?:
+ (?:
+ (
+ (?:
+ (?:
+ (?:".*?")| # double quotes
+ (?:'.*?')| # single quotes
+ (?:[^'",\#][^,\#]*?) # unquoted
+ )
+ \s*,\s* # comma
+ )* # match all list items ending in a comma (if any)
+ )
+ (
+ (?:".*?")| # double quotes
+ (?:'.*?')| # single quotes
+ (?:[^'",\#\s][^,]*?)| # unquoted
+ (?:(?<!,)) # Empty value
+ )? # last item in a list - or string value
+ )|
+ (,) # alternatively a single comma - empty list
+ )
+ \s*(\#.*)? # optional comment
+ $''',
+ re.VERBOSE)
+
+ # use findall to get the members of a list value
+ _listvalueexp = re.compile(r'''
+ (
+ (?:".*?")| # double quotes
+ (?:'.*?')| # single quotes
+ (?:[^'",\#].*?) # unquoted
+ )
+ \s*,\s* # comma
+ ''',
+ re.VERBOSE)
+
+ # this regexp is used for the value
+ # when lists are switched off
+ _nolistvalue = re.compile(r'''^
+ (
+ (?:".*?")| # double quotes
+ (?:'.*?')| # single quotes
+ (?:[^'"\#].*?)| # unquoted
+ (?:) # Empty value
+ )
+ \s*(\#.*)? # optional comment
+ $''',
+ re.VERBOSE)
+
+ # regexes for finding triple quoted values on one line
+ _single_line_single = re.compile(r"^'''(.*?)'''\s*(#.*)?$")
+ _single_line_double = re.compile(r'^"""(.*?)"""\s*(#.*)?$')
+ _multi_line_single = re.compile(r"^(.*?)'''\s*(#.*)?$")
+ _multi_line_double = re.compile(r'^(.*?)"""\s*(#.*)?$')
+
+ _triple_quote = {
+ "'''": (_single_line_single, _multi_line_single),
+ '"""': (_single_line_double, _multi_line_double),
+ }
+
+ # Used by the ``istrue`` Section method
+ _bools = {
+ 'yes': True, 'no': False,
+ 'on': True, 'off': False,
+ '1': True, '0': False,
+ 'true': True, 'false': False,
+ }
+
+ def __init__(self, infile=None, options=None, **kwargs):
+ """
+ Parse or create a config file object.
+
+ ``ConfigObj(infile=None, options=None, **kwargs)``
+ """
+ if infile is None:
+ infile = []
+ if options is None:
+ options = {}
+ else:
+ options = dict(options)
+ # keyword arguments take precedence over an options dictionary
+ options.update(kwargs)
+ # init the superclass
+ Section.__init__(self, self, 0, self)
+ #
+ defaults = OPTION_DEFAULTS.copy()
+ for entry in options.keys():
+ if entry not in defaults.keys():
+ raise TypeError, 'Unrecognised option "%s".' % entry
+ # TODO: check the values too.
+ #
+ # Add any explicit options to the defaults
+ defaults.update(options)
+ #
+ # initialise a few variables
+ self.filename = None
+ self._errors = []
+ self.raise_errors = defaults['raise_errors']
+ self.interpolation = defaults['interpolation']
+ self.list_values = defaults['list_values']
+ self.create_empty = defaults['create_empty']
+ self.file_error = defaults['file_error']
+ self.stringify = defaults['stringify']
+ self.indent_type = defaults['indent_type']
+ self.encoding = defaults['encoding']
+ self.default_encoding = defaults['default_encoding']
+ self.BOM = False
+ self.newlines = None
+ self.write_empty_values = defaults['write_empty_values']
+ self.unrepr = defaults['unrepr']
+ #
+ self.initial_comment = []
+ self.final_comment = []
+ #
+ self._terminated = False
+ #
+ if isinstance(infile, StringTypes):
+ self.filename = infile
+ if os.path.isfile(infile):
+ infile = open(infile).read() or []
+ elif self.file_error:
+ # raise an error if the file doesn't exist
+ raise IOError, 'Config file not found: "%s".' % self.filename
+ else:
+ # file doesn't already exist
+ if self.create_empty:
+ # this is a good test that the filename specified
+ # isn't impossible - like on a non existent device
+ h = open(infile, 'w')
+ h.write('')
+ h.close()
+ infile = []
+ elif isinstance(infile, (list, tuple)):
+ infile = list(infile)
+ elif isinstance(infile, dict):
+ # initialise self
+ # the Section class handles creating subsections
+ if isinstance(infile, ConfigObj):
+ # get a copy of our ConfigObj
+ infile = infile.dict()
+ for entry in infile:
+ self[entry] = infile[entry]
+ del self._errors
+ if defaults['configspec'] is not None:
+ self._handle_configspec(defaults['configspec'])
+ else:
+ self.configspec = None
+ return
+ elif hasattr(infile, 'read'):
+ # This supports file like objects
+ infile = infile.read() or []
+ # needs splitting into lines - but needs doing *after* decoding
+ # in case it's not an 8 bit encoding
+ else:
+ raise TypeError, ('infile must be a filename,'
+ ' file like object, or list of lines.')
+ #
+ if infile:
+ # don't do it for the empty ConfigObj
+ infile = self._handle_bom(infile)
+ # infile is now *always* a list
+ #
+ # Set the newlines attribute (first line ending it finds)
+ # and strip trailing '\n' or '\r' from lines
+ for line in infile:
+ if (not line) or (line[-1] not in ('\r', '\n', '\r\n')):
+ continue
+ for end in ('\r\n', '\n', '\r'):
+ if line.endswith(end):
+ self.newlines = end
+ break
+ break
+ if infile[-1] and infile[-1] in ('\r', '\n', '\r\n'):
+ self._terminated = True
+ infile = [line.rstrip('\r\n') for line in infile]
+ #
+ self._parse(infile)
+ # if we had any errors, now is the time to raise them
+ if self._errors:
+ info = "at line %s." % self._errors[0].line_number
+ if len(self._errors) > 1:
+ msg = ("Parsing failed with several errors.\nFirst error %s" %
+ info)
+ error = ConfigObjError(msg)
+ else:
+ error = self._errors[0]
+ # set the errors attribute; it's a list of tuples:
+ # (error_type, message, line_number)
+ error.errors = self._errors
+ # set the config attribute
+ error.config = self
+ raise error
+ # delete private attributes
+ del self._errors
+ #
+ if defaults['configspec'] is None:
+ self.configspec = None
+ else:
+ self._handle_configspec(defaults['configspec'])
+
+ def __repr__(self):
+ return 'ConfigObj({%s})' % ', '.join(
+ [('%s: %s' % (repr(key), repr(self[key]))) for key in
+ (self.scalars + self.sections)])
+
+ def _handle_bom(self, infile):
+ """
+ Handle any BOM, and decode if necessary.
+
+ If an encoding is specified, that *must* be used - but the BOM should
+ still be removed (and the BOM attribute set).
+
+ (If the encoding is wrongly specified, then a BOM for an alternative
+ encoding won't be discovered or removed.)
+
+ If an encoding is not specified, UTF8 or UTF16 BOM will be detected and
+ removed. The BOM attribute will be set. UTF16 will be decoded to
+ unicode.
+
+ NOTE: This method must not be called with an empty ``infile``.
+
+ Specifying the *wrong* encoding is likely to cause a
+ ``UnicodeDecodeError``.
+
+ ``infile`` must always be returned as a list of lines, but may be
+ passed in as a single string.
+ """
+ if ((self.encoding is not None) and
+ (self.encoding.lower() not in BOM_LIST)):
+ # No need to check for a BOM
+ # the encoding specified doesn't have one
+ # just decode
+ return self._decode(infile, self.encoding)
+ #
+ if isinstance(infile, (list, tuple)):
+ line = infile[0]
+ else:
+ line = infile
+ if self.encoding is not None:
+ # encoding explicitly supplied
+ # And it could have an associated BOM
+ # TODO: if encoding is just UTF16 - we ought to check for both
+ # TODO: big endian and little endian versions.
+ enc = BOM_LIST[self.encoding.lower()]
+ if enc == 'utf_16':
+ # For UTF16 we try big endian and little endian
+ for BOM, (encoding, final_encoding) in BOMS.items():
+ if not final_encoding:
+ # skip UTF8
+ continue
+ if infile.startswith(BOM):
+ ### BOM discovered
+ ##self.BOM = True
+ # Don't need to remove BOM
+ return self._decode(infile, encoding)
+ #
+ # If we get this far, will *probably* raise a DecodeError
+ # As it doesn't appear to start with a BOM
+ return self._decode(infile, self.encoding)
+ #
+ # Must be UTF8
+ BOM = BOM_SET[enc]
+ if not line.startswith(BOM):
+ return self._decode(infile, self.encoding)
+ #
+ newline = line[len(BOM):]
+ #
+ # BOM removed
+ if isinstance(infile, (list, tuple)):
+ infile[0] = newline
+ else:
+ infile = newline
+ self.BOM = True
+ return self._decode(infile, self.encoding)
+ #
+ # No encoding specified - so we need to check for UTF8/UTF16
+ for BOM, (encoding, final_encoding) in BOMS.items():
+ if not line.startswith(BOM):
+ continue
+ else:
+ # BOM discovered
+ self.encoding = final_encoding
+ if not final_encoding:
+ self.BOM = True
+ # UTF8
+ # remove BOM
+ newline = line[len(BOM):]
+ if isinstance(infile, (list, tuple)):
+ infile[0] = newline
+ else:
+ infile = newline
+ # UTF8 - don't decode
+ if isinstance(infile, StringTypes):
+ return infile.splitlines(True)
+ else:
+ return infile
+ # UTF16 - have to decode
+ return self._decode(infile, encoding)
+ #
+ # No BOM discovered and no encoding specified, just return
+ if isinstance(infile, StringTypes):
+ # infile read from a file will be a single string
+ return infile.splitlines(True)
+ else:
+ return infile
+
+ def _a_to_u(self, aString):
+ """Decode ASCII strings to unicode if a self.encoding is specified."""
+ if self.encoding:
+ return aString.decode('ascii')
+ else:
+ return aString
+
+ def _decode(self, infile, encoding):
+ """
+ Decode infile to unicode. Using the specified encoding.
+
+ if is a string, it also needs converting to a list.
+ """
+ if isinstance(infile, StringTypes):
+ # can't be unicode
+ # NOTE: Could raise a ``UnicodeDecodeError``
+ return infile.decode(encoding).splitlines(True)
+ for i, line in enumerate(infile):
+ if not isinstance(line, unicode):
+ # NOTE: The isinstance test here handles mixed lists of unicode/string
+ # NOTE: But the decode will break on any non-string values
+ # NOTE: Or could raise a ``UnicodeDecodeError``
+ infile[i] = line.decode(encoding)
+ return infile
+
+ def _decode_element(self, line):
+ """Decode element to unicode if necessary."""
+ if not self.encoding:
+ return line
+ if isinstance(line, str) and self.default_encoding:
+ return line.decode(self.default_encoding)
+ return line
+
+ def _str(self, value):
+ """
+ Used by ``stringify`` within validate, to turn non-string values
+ into strings.
+ """
+ if not isinstance(value, StringTypes):
+ return str(value)
+ else:
+ return value
+
+ def _parse(self, infile):
+ """Actually parse the config file."""
+ temp_list_values = self.list_values
+ if self.unrepr:
+ self.list_values = False
+ comment_list = []
+ done_start = False
+ this_section = self
+ maxline = len(infile) - 1
+ cur_index = -1
+ reset_comment = False
+ while cur_index < maxline:
+ if reset_comment:
+ comment_list = []
+ cur_index += 1
+ line = infile[cur_index]
+ sline = line.strip()
+ # do we have anything on the line ?
+ if not sline or sline.startswith('#'):
+ reset_comment = False
+ comment_list.append(line)
+ continue
+ if not done_start:
+ # preserve initial comment
+ self.initial_comment = comment_list
+ comment_list = []
+ done_start = True
+ reset_comment = True
+ # first we check if it's a section marker
+ mat = self._sectionmarker.match(line)
+ if mat is not None:
+ # is a section line
+ (indent, sect_open, sect_name, sect_close, comment) = (
+ mat.groups())
+ if indent and (self.indent_type is None):
+ self.indent_type = indent
+ cur_depth = sect_open.count('[')
+ if cur_depth != sect_close.count(']'):
+ self._handle_error(
+ "Cannot compute the section depth at line %s.",
+ NestingError, infile, cur_index)
+ continue
+ #
+ if cur_depth < this_section.depth:
+ # the new section is dropping back to a previous level
+ try:
+ parent = self._match_depth(
+ this_section,
+ cur_depth).parent
+ except SyntaxError:
+ self._handle_error(
+ "Cannot compute nesting level at line %s.",
+ NestingError, infile, cur_index)
+ continue
+ elif cur_depth == this_section.depth:
+ # the new section is a sibling of the current section
+ parent = this_section.parent
+ elif cur_depth == this_section.depth + 1:
+ # the new section is a child the current section
+ parent = this_section
+ else:
+ self._handle_error(
+ "Section too nested at line %s.",
+ NestingError, infile, cur_index)
+ #
+ sect_name = self._unquote(sect_name)
+ if parent.has_key(sect_name):
+ self._handle_error(
+ 'Duplicate section name at line %s.',
+ DuplicateError, infile, cur_index)
+ continue
+ # create the new section
+ this_section = Section(
+ parent,
+ cur_depth,
+ self,
+ name=sect_name)
+ parent[sect_name] = this_section
+ parent.inline_comments[sect_name] = comment
+ parent.comments[sect_name] = comment_list
+ continue
+ #
+ # it's not a section...
[truncated message content] |
|
From: <jo...@us...> - 2007-07-26 21:14:01
|
Revision: 3622
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3622&view=rev
Author: jouni
Date: 2007-07-26 14:13:58 -0700 (Thu, 26 Jul 2007)
Log Message:
-----------
Numpy has isfinite, unlike the old numerix
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-07-26 19:44:35 UTC (rev 3621)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-07-26 21:13:58 UTC (rev 3622)
@@ -112,7 +112,7 @@
# need to use %f with some precision. Perhaps the precision
# should adapt to the magnitude of the number?
elif isinstance(obj, float):
- if npy.isnan(obj) or obj in (-npy.inf, npy.inf):
+ if not npy.isfinite(obj):
raise ValueError, "Can only output finite numbers in PDF"
r = "%.10f" % obj
return r.rstrip('0').rstrip('.')
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2007-07-26 19:44:40
|
Revision: 3621
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3621&view=rev
Author: mdboom
Date: 2007-07-26 12:44:35 -0700 (Thu, 26 Jul 2007)
Log Message:
-----------
Some examples to go with the last commit.
Modified Paths:
--------------
trunk/matplotlib/examples/mathtext_examples.py
Modified: trunk/matplotlib/examples/mathtext_examples.py
===================================================================
--- trunk/matplotlib/examples/mathtext_examples.py 2007-07-26 19:44:09 UTC (rev 3620)
+++ trunk/matplotlib/examples/mathtext_examples.py 2007-07-26 19:44:35 UTC (rev 3621)
@@ -7,7 +7,7 @@
r'$x y$',
r'$x+y\ x=y\ x<y\ x:y\ x,y\ x@y$',
r'$100\%y\ x*y\ x/y x\$y$',
- r'$x\leftarrow y\ x\forall y$',
+ r'$x\leftarrow y\ x\forall y\ x-y$',
r'$x \sf x \bf x {\cal X} \rm x$',
r'$\{ \rm braces \}$',
r'$\left[\left\lfloor\frac{5}{\frac{\left(3\right)}{4}} y\right)\right]$',
@@ -30,8 +30,13 @@
r'$_i$',
r"$\arccos((x^i))$",
r"$\gamma = \frac{x=\frac{6}{8}}{y} \delta$",
- r'$\"o\ddot o \'e\`e\~n\.x\^y$',
-
+ r'$\limsup_{x\to\infty}$',
+ r'$\oint^\infty_0$',
+ r"$f'$",
+ r'$\frac{x_2888}{y}$',
+ r"$\sqrt[3]{\frac{X_2}{Y}}=5$",
+ r"$\sqrt[3]{x}=5$",
+ r'$\frac{X}{\frac{X}{Y}}$'
]
from pylab import *
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2007-07-26 19:44:15
|
Revision: 3620
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3620&view=rev
Author: mdboom
Date: 2007-07-26 12:44:09 -0700 (Thu, 26 Jul 2007)
Log Message:
-----------
Lots of sizing and layout tweaks. Support $\sqrt[3]{foo}. The line
meets up with the check mark rather clumsily on the Agg backends due
to rounding errors and lack of subpixel placement... will look into that.
Modified Paths:
--------------
trunk/matplotlib/CHANGELOG
trunk/matplotlib/lib/matplotlib/_mathtext_data.py
trunk/matplotlib/lib/matplotlib/mathtext.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2007-07-26 18:40:36 UTC (rev 3619)
+++ trunk/matplotlib/CHANGELOG 2007-07-26 19:44:09 UTC (rev 3620)
@@ -23,8 +23,11 @@
- Double sub/superscripts (eg. $x_i_j$) are considered
ambiguous and raise an exception. Use braces to disambiguate.
- - $\frac{x}{y}$ can be used for displaying fractions
+ - $\frac{x}{y}$ can be used for displaying fractions.
+ - $\sqrt[3]{x}$ can be used to display the radical symbol
+ with a root number and body.
+
- $\left(\frac{x}{y}\right)$ may be used to create
parentheses and other delimiters that automatically
resize to the height of their contents.
Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2007-07-26 18:40:36 UTC (rev 3619)
+++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2007-07-26 19:44:09 UTC (rev 3620)
@@ -170,6 +170,7 @@
r'\swarrow' : ('cmsy10', 116),
r'\propto' : ('cmsy10', 15),
r'\prime' : ('cmsy10', 73),
+ r"'" : ('cmsy10', 73),
r'\infty' : ('cmsy10', 32),
r'\in' : ('cmsy10', 59),
r'\ni' : ('cmsy10', 122),
@@ -253,6 +254,7 @@
r'\prec' : ('cmsy10', 93),
r'\succ' : ('cmsy10', 49),
r'\rightarrow' : ('cmsy10', 12),
+ r'\to' : ('cmsy10', 12),
r'\spadesuit' : ('cmsy10', 7),
}
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-07-26 18:40:36 UTC (rev 3619)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-07-26 19:44:09 UTC (rev 3620)
@@ -138,7 +138,8 @@
from matplotlib.pyparsing import Literal, Word, OneOrMore, ZeroOrMore, \
Combine, Group, Optional, Forward, NotAny, alphas, nums, alphanums, \
StringStart, StringEnd, ParseFatalException, FollowedBy, Regex, \
- operatorPrecedence, opAssoc, ParseResults, Or, Suppress, oneOf
+ operatorPrecedence, opAssoc, ParseResults, Or, Suppress, oneOf, \
+ ParseException, MatchFirst
from matplotlib.afm import AFM
from matplotlib.cbook import enumerate, iterable, Bunch, get_realpath_and_stat, \
@@ -151,13 +152,7 @@
####################
-# symbols that have the sub and superscripts over/under
-overunder_symbols = {
- r'\sum' : 1,
- r'\int' : 1,
- r'\prod' : 1,
- r'\coprod' : 1,
- }
+
# a character over another character
charOverChars = {
# The first 2 entires in the tuple are (font, char, sizescale) for
@@ -692,7 +687,11 @@
def render_rect_filled(self, x1, y1, x2, y2):
assert len(self.fonts)
font = self.fonts.values()[0]
- font.font.draw_rect_filled(x1, y1, max(x2 - 1, x1), max(y2 - 1, y1))
+ font.font.draw_rect_filled(
+ max(0, x1 - 1),
+ y1,
+ max(x2 - 1, x1),
+ max(y2 - 1, y1))
def get_used_characters(self):
return self.used_characters
@@ -956,14 +955,16 @@
# The number of different sizes of chars to use, beyond which they will not
# get any smaller
NUM_SIZE_LEVELS = 3
-# Percentage of x-height that subscripts drop below the baseline
-SUBDROP = 0.05
+# Percentage of x-height of additional horiz. space after sub/superscripts
+SCRIPT_SPACE = 0.3
+# Percentage of x-height that sub/superscripts drop below the baseline
+SUBDROP = 0.4
# Percentage of x-height that superscripts drop below the baseline
-SUP1 = 0.2
+SUP1 = 0.7
# Percentage of x-height that subscripts drop below the baseline
-SUB1 = 0.3
+SUB1 = 0.0
# Percentage of x-height that superscripts are offset relative to the subscript
-DELTA = 0.05
+DELTA = 0.1
class MathTextWarning(Warning):
pass
@@ -991,10 +992,6 @@
def set_link(self, other):
self.link = other
- def pack(self):
- if self.link:
- self.link.pack()
-
def shrink(self):
"""Shrinks one level smaller. There are only three levels of sizes,
after which things will no longer get smaller."""
@@ -1062,7 +1059,10 @@
def _update_metrics(self):
metrics = self._metrics = self.font_output.get_metrics(
self.font, self.c, self.fontsize, self.dpi)
- self.width = metrics.width
+ if self.c == ' ':
+ self.width = metrics.advance
+ else:
+ self.width = metrics.width
self.height = metrics.iceberg
self.depth = -(metrics.iceberg - metrics.height)
@@ -1124,7 +1124,9 @@
elem = next
def __repr__(self):
- s = '[' + self.__internal_repr__() + " <%d %d %d %d> " % (self.width, self.height, self.depth, self.shift_amount)
+ s = '[%s <%d %d %d %d> ' % (self.__internal_repr__(),
+ self.width, self.height,
+ self.depth, self.shift_amount)
if self.list_head:
s += ' ' + self.list_head.__repr__()
s += ']'
@@ -1162,6 +1164,7 @@
Box.shrink(self)
if self.size < NUM_SIZE_LEVELS:
self.shift_amount *= SHRINK_FACTOR
+ self.glue_set *= SHRINK_FACTOR
class Hlist(List):
"""A horizontal list of boxes.
@@ -1186,12 +1189,6 @@
kern.link = next
elem = next
- def pack(self):
- if self.list_head:
- self.list_head.pack()
- self.hpack()
- Node.pack(self)
-
def hpack(self, w=0., m='additional'):
"""The main duty of hpack is to compute the dimensions of the
resulting boxes, and to adjust the glue if one of those dimensions is
@@ -1265,12 +1262,6 @@
List.__init__(self, elements)
self.vpack()
- def pack(self):
- if self.list_head:
- self.list_head.pack()
- self.vpack()
- Node.pack(self)
-
def vpack(self, h=0., m='additional', l=float('inf')):
"""The main duty of vpack is to compute the dimensions of the
resulting boxes, and to adjust the glue if one of those dimensions is
@@ -1386,6 +1377,13 @@
glue_spec = glue_spec.copy()
self.glue_spec = glue_spec
+ def shrink(self):
+ Node.shrink(self)
+ if self.size < NUM_SIZE_LEVELS:
+ if self.glue_spec.width != 0.:
+ self.glue_spec = self.glue_spec.copy()
+ self.glue_spec.width *= SHRINK_FACTOR
+
class GlueSpec(object):
"""@150, @151"""
def __init__(self, width=0., stretch=0., stretch_order=0, shrink=0., shrink_order=0):
@@ -1406,7 +1404,7 @@
def factory(cls, glue_type):
return cls._types[glue_type]
factory = classmethod(factory)
-
+
GlueSpec._types = {
'fil': GlueSpec(0., 1., 1, 0., 0),
'fill': GlueSpec(0., 1., 2, 0., 0),
@@ -1444,11 +1442,6 @@
def __init__(self):
Glue.__init__(self, 'neg_filll')
-class FixedGlue(Glue):
- def __init__(self, width):
- Glue.__init__(self, 'empty', copy=True)
- self.glue_spec.width = width
-
class SsGlue(Glue):
def __init__(self):
Glue.__init__(self, 'ss')
@@ -1463,7 +1456,7 @@
"""A convenience class to create an Vlist whose contents are centered
within its enclosing box."""
def __init__(self, elements):
- Vlist.__init__(self, [Fill()] + elements + [Fill()])
+ Vlist.__init__(self, [SsGlue()] + elements + [SsGlue()])
class Kern(Node):
"""A Kern node has a width field to specify a (normally negative)
@@ -1668,7 +1661,7 @@
class Parser(object):
_binary_operators = Set(r'''
- + - *
+ + *
\pm \sqcap \rhd
\mp \sqcup \unlhd
\times \vee \unrhd
@@ -1711,6 +1704,16 @@
_spaced_symbols = _binary_operators | _relation_symbols | _arrow_symbols
_punctuation_symbols = Set(r', ; . ! \ldotp \cdotp'.split())
+
+ _overunder_symbols = Set(r'''
+ \sum \int \prod \coprod \oint \bigcap \bigcup \bigsqcup \bigvee
+ \bigwedge \bigodot \bigotimes \bigoplus \biguplus
+ '''.split()
+ )
+
+ _overunder_functions = Set(
+ r"lim liminf limsup sup max min".split()
+ )
def __init__(self):
# All forward declarations are here
@@ -1761,14 +1764,14 @@
r"[a-zA-Z0-9 ]",
r"[+\-*/]",
r"[<>=]",
- r"[:,.;!]",
- r"[!@%&]",
- r"[[\]()]",
+ r"[:,.;!'@[()]",
r"\\[$%{}]",
])
+ ")"
).setParseAction(self.symbol).leaveWhitespace()
+ rightBracket = Literal("[").setParseAction(self.symbol).leaveWhitespace()
+
accent = Group(
Combine(bslash + accent)
+ placeable
@@ -1800,11 +1803,30 @@
+ group
).setParseAction(self.frac).setName("frac")
+ sqrt = Group(
+ Suppress(
+ bslash
+ + Literal("sqrt")
+ )
+ + Optional(
+ Suppress(Literal("["))
+ + OneOrMore(
+ symbol
+ ^ font
+ )
+ + Suppress(Literal("]")),
+ default = None
+ )
+ + group
+ ).setParseAction(self.sqrt).setName("sqrt")
+
placeable <<(accent
^ function
^ symbol
+ ^ rightBracket
^ group
^ frac
+ ^ sqrt
)
simple <<(space
@@ -1939,7 +1961,10 @@
elif c in self._punctuation_symbols:
return [Hlist([Char(c, self.get_state()),
self._make_space(0.3)])]
- return [Char(toks[0], self.get_state())]
+ try:
+ return [Char(toks[0], self.get_state())]
+ except:
+ raise ParseException()
_accent_map = {
r'\hat' : r'\circumflexaccent',
@@ -1971,7 +1996,7 @@
centered.shift_amount = accent._metrics.xmin
return Vlist([
centered,
- FixedGlue(thickness * 2.0),
+ Vbox(0., thickness * 2.0),
Hlist([sym])
])
@@ -1982,6 +2007,7 @@
state.font = 'rm'
hlist = Hlist([Char(c, state) for c in toks[0]])
self.pop_state()
+ hlist.function_name = toks[0]
return hlist
def start_group(self, s, loc, toks):
@@ -2007,7 +2033,9 @@
def is_overunder(self, nucleus):
if isinstance(nucleus, Char):
- return overunder_symbols.has_key(nucleus.c)
+ return nucleus.c in self._overunder_symbols
+ elif isinstance(nucleus, Hlist) and hasattr(nucleus, 'function_name'):
+ return nucleus.function_name in self._overunder_functions
return False
def subsuperscript(self, s, loc, toks):
@@ -2061,24 +2089,22 @@
width = nucleus.width
if super is not None:
super.shrink()
- super.pack()
width = max(width, super.width)
if sub is not None:
sub.shrink()
- sub.pack()
width = max(width, sub.width)
if super is not None:
hlist = HCentered([super])
hlist.hpack(width, 'exactly')
- vlist.extend([hlist, FixedGlue(rule_thickness * 2.0)])
+ vlist.extend([hlist, Vbox(0., rule_thickness * 2.0)])
hlist = HCentered([nucleus])
hlist.hpack(width, 'exactly')
vlist.append(hlist)
if sub is not None:
hlist = HCentered([sub])
hlist.hpack(width, 'exactly')
- vlist.extend([FixedGlue(rule_thickness), hlist])
+ vlist.extend([Vbox(0., rule_thickness), hlist])
shift = hlist.height + hlist.depth + rule_thickness * 2.0
vlist = Vlist(vlist)
vlist.shift_amount = shift
@@ -2086,12 +2112,12 @@
return [result]
shift_up = nucleus.height - SUBDROP * xHeight
- shift_down = nucleus.depth + SUBDROP * xHeight
+ shift_down = SUBDROP * xHeight
if super is None:
# @757
sub.shrink()
x = Hlist([sub])
- #x.width += SCRIPT_SPACE
+ x.width += SCRIPT_SPACE * xHeight
shift_down = max(shift_down, SUB1)
clr = x.height - (abs(xHeight * 4.0) / 5.0)
shift_down = max(shift_down, clr)
@@ -2099,7 +2125,7 @@
else:
super.shrink()
x = Hlist([super])
- #x.width += SCRIPT_SPACE
+ x.width += SCRIPT_SPACE * xHeight
clr = SUP1 * xHeight
shift_up = max(shift_up, clr)
clr = x.depth + (abs(xHeight) / 4.0)
@@ -2109,13 +2135,13 @@
else: # Both sub and superscript
sub.shrink()
y = Hlist([sub])
- #y.width += SCRIPT_SPACE
+ y.width += SCRIPT_SPACE * xHeight
shift_down = max(shift_down, SUB1 * xHeight)
clr = 4.0 * rule_thickness - ((shift_up - x.depth) - (y.height - shift_down))
if clr > 0.:
shift_up += clr
shift_down += clr
- x.shift_amount = DELTA
+ x.shift_amount = DELTA * xHeight
x = Vlist([x,
Kern((shift_up - x.depth) - (y.height - shift_down)),
y])
@@ -2127,33 +2153,78 @@
def frac(self, s, loc, toks):
assert(len(toks)==1)
assert(len(toks[0])==2)
+ state = self.get_state()
+ thickness = state.font_output.get_underline_thickness(
+ state.font, state.fontsize, state.dpi)
+
num, den = toks[0]
num.shrink()
den.shrink()
cnum = HCentered([num])
cden = HCentered([den])
- width = max(num.width, den.height)
+ width = max(num.width, den.width) + thickness * 10.
cnum.hpack(width, 'exactly')
cden.hpack(width, 'exactly')
- state = self.get_state()
- thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize, state.dpi)
- space = thickness * 3.0
vlist = Vlist([cnum,
- FixedGlue(thickness * 2.0),
- Hrule(self.get_state()),
- FixedGlue(thickness * 3.0),
+ Vbox(0, thickness * 2.0),
+ Hrule(state),
+ Vbox(0, thickness * 4.0),
cden
])
+ # Shift so the fraction line sits in the middle of the
+ # equals sign
metrics = state.font_output.get_metrics(
state.font, '=', state.fontsize, state.dpi)
- shift = cden.height - (metrics.ymax + metrics.ymin) / 2 + thickness * 2.5
+ shift = (cden.height -
+ (metrics.ymax + metrics.ymin) / 2 +
+ thickness * 2.5)
vlist.shift_amount = shift
- hlist = Hlist([vlist, FixedGlue(thickness * 2.)])
+ hlist = Hlist([vlist, Hbox(thickness * 2.)])
return [hlist]
+ def sqrt(self, s, loc, toks):
+ #~ print "sqrt", toks
+ root, body = toks[0]
+ state = self.get_state()
+ thickness = state.font_output.get_underline_thickness(
+ state.font, state.fontsize, state.dpi)
+
+ if root is None:
+ root = Box()
+ else:
+ root.shrink()
+ root.shrink()
+
+ # Add a little extra to the height so the body
+ # doesn't seem cramped
+ height = body.height - body.shift_amount + thickness * 5.0
+ depth = body.depth + body.shift_amount
+ check = AutoSizedDelim(r'\sqrt', height, depth, state)
+
+ height = check.height - check.shift_amount
+ depth = check.depth + check.shift_amount
+ rightside = Vlist([Hrule(state),
+ Fill(),
+ # Pack a little extra to the left and right
+ # of the body
+ Hlist([Hbox(thickness * 2.0),
+ body,
+ Hbox(thickness * 2.0)])])
+ # Stretch the glue between the hrule and the body
+ rightside.vpack(height + 1.0, depth, 'exactly')
+
+ root_vlist = Vlist([Hlist([root])])
+ root_vlist.shift_amount = -height * 0.5
+
+ hlist = Hlist([root_vlist,
+ Kern(-check.width * 0.5),
+ check,
+ Kern(-thickness * 0.5),
+ rightside])
+ return [hlist]
+
def auto_sized_delimiter(self, s, loc, toks):
#~ print "auto_sized_delimiter", toks
front, middle, back = toks
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2007-07-26 18:40:39
|
Revision: 3619
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3619&view=rev
Author: mdboom
Date: 2007-07-26 11:40:36 -0700 (Thu, 26 Jul 2007)
Log Message:
-----------
Fix bug in pdf backend (numpy.inf not numpy.infinity)
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-07-26 14:47:27 UTC (rev 3618)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-07-26 18:40:36 UTC (rev 3619)
@@ -112,7 +112,7 @@
# need to use %f with some precision. Perhaps the precision
# should adapt to the magnitude of the number?
elif isinstance(obj, float):
- if npy.isnan(obj) or obj in (-npy.infinity, npy.infinity):
+ if npy.isnan(obj) or obj in (-npy.inf, npy.inf):
raise ValueError, "Can only output finite numbers in PDF"
r = "%.10f" % obj
return r.rstrip('0').rstrip('.')
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2007-07-26 14:47:28
|
Revision: 3618
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3618&view=rev
Author: mdboom
Date: 2007-07-26 07:47:27 -0700 (Thu, 26 Jul 2007)
Log Message:
-----------
Update information about mathtext improvements.
Modified Paths:
--------------
trunk/matplotlib/API_CHANGES
trunk/matplotlib/CHANGELOG
Modified: trunk/matplotlib/API_CHANGES
===================================================================
--- trunk/matplotlib/API_CHANGES 2007-07-26 14:45:57 UTC (rev 3617)
+++ trunk/matplotlib/API_CHANGES 2007-07-26 14:47:27 UTC (rev 3618)
@@ -1,3 +1,10 @@
+ The mathtext font commands (\cal, \rm, \it, \tt) now behave as TeX
+ does: they are in effect until the next font change command or the
+ end of the grouping. Therefore uses of $\cal{R}$ should be
+ changed to ${\cal R}$. Alternatively, you may use the new
+ LaTeX-style font commands (\mathcal, \mathrm, \mathit, \mathtt)
+ which do affect the following group, eg. $\mathcal{R}$.
+
Text creation commands have a new default linespacing and
a new linespacing kwarg, which is a multiple of the maximum
vertical extent of a line of ordinary text. The default is
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2007-07-26 14:45:57 UTC (rev 3617)
+++ trunk/matplotlib/CHANGELOG 2007-07-26 14:47:27 UTC (rev 3618)
@@ -1,3 +1,52 @@
+2007-07-26 Major rewrite of mathtext.py, using the TeX box layout model.
+
+ There is one (known) backward incompatible change. The
+ font commands (\cal, \rm, \it, \tt) now behave as TeX does:
+ they are in effect until the next font change command or
+ the end of the grouping. Therefore uses of $\cal{R}$
+ should be changed to ${\cal R}$. Alternatively, you may
+ use the new LaTeX-style font commands (\mathcal, \mathrm,
+ \mathit, \mathtt) which do affect the following group,
+ eg. $\mathcal{R}$.
+
+ Other new features include:
+
+ - Math may be interspersed with non-math text. Any text
+ with an even number of $'s (non-escaped) will be sent to
+ the mathtext parser for layout.
+
+ - Sub/superscripts are less likely to accidentally overlap.
+
+ - Support for sub/superscripts in either order, eg. $x^i_j$
+ and $x_j^i$ are equivalent.
+
+ - Double sub/superscripts (eg. $x_i_j$) are considered
+ ambiguous and raise an exception. Use braces to disambiguate.
+
+ - $\frac{x}{y}$ can be used for displaying fractions
+
+ - $\left(\frac{x}{y}\right)$ may be used to create
+ parentheses and other delimiters that automatically
+ resize to the height of their contents.
+
+ - Spacing around operators etc. is now generally more like
+ TeX.
+
+ - Added support (and fonts) for boldface (\bf) and
+ sans-serif (\sf) symbols.
+
+ - Log-like function name shortcuts are supported. For
+ example, $\sin(x)$ may be used instead of ${\rm sin}(x)$
+
+ - Limited use of kerning for the easy case (same font)
+
+ Behind the scenes, the pyparsing.py module used for doing
+ the math parsing was updated to the latest stable version
+ (1.4.6). A lot of duplicate code was refactored out of the
+ Font classes.
+
+ - MGD
+
2007-07-19 completed numpification of most trivial cases - NN
2007-07-19 converted non-numpy relicts troughout the code - NN
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2007-07-26 14:45:59
|
Revision: 3617
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3617&view=rev
Author: mdboom
Date: 2007-07-26 07:45:57 -0700 (Thu, 26 Jul 2007)
Log Message:
-----------
Merging mathtext changes into trunk.
Modified Paths:
--------------
trunk/matplotlib/examples/mathtext_demo.py
trunk/matplotlib/lib/matplotlib/_mathtext_data.py
trunk/matplotlib/lib/matplotlib/afm.py
trunk/matplotlib/lib/matplotlib/backends/backend_agg.py
trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py
trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py
trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
trunk/matplotlib/lib/matplotlib/backends/backend_svg.py
trunk/matplotlib/lib/matplotlib/mathtext.py
trunk/matplotlib/lib/matplotlib/pyparsing.py
trunk/matplotlib/lib/matplotlib/text.py
trunk/matplotlib/src/ft2font.cpp
trunk/matplotlib/src/mplutils.h
Added Paths:
-----------
trunk/matplotlib/examples/mathtext_examples.py
trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/cmb10.ttf
trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/cmss10.ttf
Modified: trunk/matplotlib/examples/mathtext_demo.py
===================================================================
--- trunk/matplotlib/examples/mathtext_demo.py 2007-07-26 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/examples/mathtext_demo.py 2007-07-26 14:45:57 UTC (rev 3617)
@@ -1,28 +1,25 @@
#!/usr/bin/env python
"""
+Use matplotlib's internal LaTex parser and layout engine. For true
+latex rendering, see the text.usetex option
+"""
+import numpy as npy
+from pylab import figure, show
+fig = figure()
+fig.subplots_adjust(bottom=0.2)
-In order to use mathtext, you must build matplotlib.ft2font. This is
-built by default in the windows installer.
+ax = fig.add_subplot(111, axisbg='y')
+ax.plot([1,2,3], 'r')
+x = npy.arange(0.0, 3.0, 0.1)
-For other platforms, edit setup.py and set
+ax.grid(True)
+ax.set_xlabel(r'$\Delta_i^j$', fontsize=20)
+ax.set_ylabel(r'$\Delta_{i+1}^j$', fontsize=20)
+tex = r'$\mathcal{R}\prod_{i=\alpha_{i+1}}^\infty a_i\sin(2 \pi f x_i)$'
-BUILD_FT2FONT = True
+ax.text(1, 1.6, tex, fontsize=20, va='bottom')
-"""
-from pylab import *
-subplot(111, axisbg='y')
-plot([1,2,3], 'r')
-x = arange(0.0, 3.0, 0.1)
-
-grid(True)
-xlabel(r'$\Delta_i^j$', fontsize=20)
-ylabel(r'$\Delta_{i+1}^j$', fontsize=20)
-tex = r'$\cal{R}\prod_{i=\alpha_{i+1}}^\infty a_i\rm{sin}(2 \pi f x_i)$'
-text(1, 1.6, tex, fontsize=20)
-
#title(r'$\Delta_i^j \hspace{0.4} \rm{versus} \hspace{0.4} \Delta_{i+1}^j$', fontsize=20)
-savefig('mathtext_demo')
+fig.savefig('mathtext_demo')
-
-
show()
Copied: trunk/matplotlib/examples/mathtext_examples.py (from rev 3616, branches/mathtext_mgd/examples/mathtext_examples.py)
===================================================================
--- trunk/matplotlib/examples/mathtext_examples.py (rev 0)
+++ trunk/matplotlib/examples/mathtext_examples.py 2007-07-26 14:45:57 UTC (rev 3617)
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+import os, sys
+
+stests = [
+ r'Kerning: AVA $AVA$',
+ r'$x y$',
+ r'$x+y\ x=y\ x<y\ x:y\ x,y\ x@y$',
+ r'$100\%y\ x*y\ x/y x\$y$',
+ r'$x\leftarrow y\ x\forall y$',
+ r'$x \sf x \bf x {\cal X} \rm x$',
+ r'$\{ \rm braces \}$',
+ r'$\left[\left\lfloor\frac{5}{\frac{\left(3\right)}{4}} y\right)\right]$',
+ r'$\left(x\right)$',
+ r'$\sin(x)$',
+ r'$x_2$',
+ r'$x^2$',
+ r'$x^2_y$',
+ r'$x_y^2$',
+ r'$\prod_{i=\alpha_{i+1}}^\infty$',
+ r'$x = \frac{x+\frac{5}{2}}{\frac{y+3}{8}}$',
+ r'$dz/dt \/ = \/ \gamma x^2 \/ + \/ {\rm sin}(2\pi y+\phi)$',
+ r'Foo: $\alpha_{i+1}^j \/ = \/ {\rm sin}(2\pi f_j t_i) e^{-5 t_i/\tau}$',
+ r'$\mathcal{R}\prod_{i=\alpha_{i+1}}^\infty a_i \sin(2 \pi f x_i)$',
+# r'$\bigodot \bigoplus {\sf R} a_i{\rm sin}(2 \pi f x_i)$',
+ r'Variable $i$ is good',
+ r'$\Delta_i^j$',
+ r'$\Delta^j_{i+1}$',
+ r'$\ddot{o}\acute{e}\grave{e}\hat{O}\breve{\imath}\tilde{n}\vec{q}$',
+ r'$_i$',
+ r"$\arccos((x^i))$",
+ r"$\gamma = \frac{x=\frac{6}{8}}{y} \delta$",
+ r'$\"o\ddot o \'e\`e\~n\.x\^y$',
+
+ ]
+
+from pylab import *
+
+if '--latex' in sys.argv:
+ fd = open("mathtext_examples.ltx", "w")
+ fd.write("\\documentclass{article}\n")
+ fd.write("\\begin{document}\n")
+ fd.write("\\begin{enumerate}\n")
+
+ for i, s in enumerate(stests):
+ fd.write("\\item %s\n" % s)
+
+ fd.write("\\end{enumerate}\n")
+ fd.write("\\end{document}\n")
+ fd.close()
+
+ os.system("pdflatex mathtext_examples.ltx")
+else:
+ for i, s in enumerate(stests):
+ print "%02d: %s" % (i, s)
+ plot([1,2,3], 'r')
+ x = arange(0.0, 3.0, 0.1)
+
+ grid(True)
+ text(1, 1.6, s, fontsize=20)
+
+ savefig('mathtext_example%02d' % i)
+ figure()
+
Property changes on: trunk/matplotlib/examples/mathtext_examples.py
___________________________________________________________________
Name: svn:executable
+ *
Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2007-07-26 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2007-07-26 14:45:57 UTC (rev 3617)
@@ -38,8 +38,10 @@
r'\SQRT' : ('cmex10', 53),
r'\leftbrace' : ('cmex10', 92),
r'{' : ('cmex10', 92),
+ r'\{' : ('cmex10', 92),
r'\rightbrace' : ('cmex10', 130),
r'}' : ('cmex10', 130),
+ r'\}' : ('cmex10', 130),
r'\leftangle' : ('cmex10', 97),
r'\rightangle' : ('cmex10', 64),
r'\Leftparen' : ('cmex10', 112),
@@ -112,7 +114,7 @@
r'\phi' : ('cmmi10', 42),
r'\chi' : ('cmmi10', 17),
r'\psi' : ('cmmi10', 31),
-
+
r'(' : ('cmr10', 119),
r'\leftparen' : ('cmr10', 119),
r'\rightparen' : ('cmr10', 68),
@@ -135,7 +137,11 @@
r'[' : ('cmr10', 62),
r'\rightbracket' : ('cmr10', 72),
r']' : ('cmr10', 72),
-
+ r'\%' : ('cmr10', 48),
+ r'%' : ('cmr10', 48),
+ r'\$' : ('cmr10', 99),
+ r'@' : ('cmr10', 111),
+
# these are mathml names, I think. I'm just using them for the
# tex methods noted
r'\circumflexaccent' : ('cmr10', 124), # for \hat
@@ -749,7 +755,17 @@
r'\langle' : ('psyr', 225),
r'\Sigma' : ('psyr', 229),
r'\sum' : ('psyr', 229),
-
+ # these are mathml names, I think. I'm just using them for the
+ # tex methods noted
+ r'\circumflexaccent' : ('pncri8a', 124), # for \hat
+ r'\combiningbreve' : ('pncri8a', 81), # for \breve
+ r'\combininggraveaccent' : ('pncri8a', 114), # for \grave
+ r'\combiningacuteaccent' : ('pncri8a', 63), # for \accute
+ r'\combiningdiaeresis' : ('pncri8a', 91), # for \ddot
+ r'\combiningtilde' : ('pncri8a', 75), # for \tilde
+ r'\combiningrightarrowabove' : ('pncri8a', 110), # for \vec
+ r'\combiningdotabove' : ('pncri8a', 26), # for \dot
+ r'\imath' : ('pncri8a', 105)
}
# Automatically generated.
Modified: trunk/matplotlib/lib/matplotlib/afm.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/afm.py 2007-07-26 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/afm.py 2007-07-26 14:45:57 UTC (rev 3617)
@@ -394,7 +394,14 @@
"Return the fontangle as float"
return self._header['ItalicAngle']
+ def get_xheight(self):
+ "Return the xheight as float"
+ return self._header['XHeight']
+ def get_underline_thickness(self):
+ "Return the underline thickness as float"
+ return self._header['UnderlineThickness']
+
if __name__=='__main__':
#pathname = '/usr/local/lib/R/afm/'
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_agg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2007-07-26 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2007-07-26 14:45:57 UTC (rev 3617)
@@ -173,10 +173,9 @@
"""
if __debug__: verbose.report('RendererAgg.draw_mathtext',
'debug-annoying')
- size = prop.get_size_in_points()
- width, height, fonts = math_parse_s_ft2font(
- s, self.dpi.get(), size, angle)
-
+ width, height, fonts, used_characters = math_parse_s_ft2font(
+ s, self.dpi.get(), prop, angle)
+
if angle == 90:
width, height = height, width
for font in fonts:
@@ -225,7 +224,6 @@
# texmanager more efficient. It is not meant to be used
# outside the backend
"""
-
if ismath=='TeX':
# todo: handle props
size = prop.get_size_in_points()
@@ -235,8 +233,8 @@
return n,m
if ismath:
- width, height, fonts = math_parse_s_ft2font(
- s, self.dpi.get(), prop.get_size_in_points())
+ width, height, fonts, used_characters = math_parse_s_ft2font(
+ s, self.dpi.get(), prop)
return width, height
font = self._get_agg_font(prop)
font.set_text(s, 0.0) # the width and height of unrotated string
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py 2007-07-26 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py 2007-07-26 14:45:57 UTC (rev 3617)
@@ -314,9 +314,8 @@
# "_draw_mathtext()")
# return
- size = prop.get_size_in_points()
- width, height, fonts = math_parse_s_ft2font(
- s, self.dpi.get(), size)
+ width, height, fonts, used_characters = math_parse_s_ft2font(
+ s, self.dpi.get(), prop)
if angle==90:
width, height = height, width
@@ -372,8 +371,8 @@
def get_text_width_height(self, s, prop, ismath):
if _debug: print '%s.%s()' % (self.__class__.__name__, _fn_name())
if ismath:
- width, height, fonts = math_parse_s_ft2font(
- s, self.dpi.get(), prop.get_size_in_points())
+ width, height, fonts, used_characters = math_parse_s_ft2font(
+ s, self.dpi.get(), prop)
return width, height
ctx = self.text_ctx
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py 2007-07-26 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py 2007-07-26 14:45:57 UTC (rev 3617)
@@ -198,9 +198,8 @@
def _draw_mathtext(self, gc, x, y, s, prop, angle):
- size = prop.get_size_in_points()
- width, height, fonts = math_parse_s_ft2font(
- s, self.dpi.get(), size)
+ width, height, fonts, used_characters = math_parse_s_ft2font(
+ s, self.dpi.get(), prop)
if angle==90:
width, height = height, width
@@ -342,8 +341,8 @@
def get_text_width_height(self, s, prop, ismath):
if ismath:
- width, height, fonts = math_parse_s_ft2font(
- s, self.dpi.get(), prop.get_size_in_points())
+ width, height, fonts, used_characters = math_parse_s_ft2font(
+ s, self.dpi.get(), prop)
return width, height
layout, inkRect, logicalRect = self._get_pango_layout(s, prop)
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-07-26 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-07-26 14:45:57 UTC (rev 3617)
@@ -457,8 +457,9 @@
fontdictObject = self._write_afm_font(filename)
else:
realpath, stat_key = get_realpath_and_stat(filename)
- fontdictObject = self.embedTTF(
- *self.used_characters[stat_key])
+ chars = self.used_characters.get(stat_key)
+ if chars is not None and len(chars[1]):
+ fontdictObject = self.embedTTF(realpath, chars[1])
fonts[Fx] = fontdictObject
#print >>sys.stderr, filename
self.writeObject(self.fontObject, fonts)
@@ -1092,37 +1093,36 @@
def draw_mathtext(self, gc, x, y, s, prop, angle):
# TODO: fix positioning and encoding
- fontsize = prop.get_size_in_points()
width, height, pswriter, used_characters = \
- math_parse_s_pdf(s, 72, fontsize, 0)
+ math_parse_s_pdf(s, 72, prop, 0)
self.merge_used_characters(used_characters)
-
+
self.check_gc(gc, gc._rgb)
self.file.output(Op.begin_text)
prev_font = None, None
oldx, oldy = 0, 0
- for ox, oy, fontname, fontsize, glyph in pswriter:
- #print ox, oy, glyph
- fontname = fontname.lower()
- a = angle / 180.0 * pi
- newx = x + cos(a)*ox - sin(a)*oy
- newy = y + sin(a)*ox + cos(a)*oy
- self._setup_textpos(newx, newy, angle, oldx, oldy)
- oldx, oldy = newx, newy
- if (fontname, fontsize) != prev_font:
- self.file.output(self.file.fontName(fontname), fontsize,
- Op.selectfont)
- prev_font = fontname, fontsize
+ for record in pswriter:
+ if record[0] == 'glyph':
+ rec_type, ox, oy, fontname, fontsize, glyph = record
+ a = angle / 180.0 * pi
+ newx = x + cos(a)*ox - sin(a)*oy
+ newy = y + sin(a)*ox + cos(a)*oy
+ self._setup_textpos(newx, newy, angle, oldx, oldy)
+ oldx, oldy = newx, newy
+ if (fontname, fontsize) != prev_font:
+ self.file.output(self.file.fontName(fontname), fontsize,
+ Op.selectfont)
+ prev_font = fontname, fontsize
- #if fontname.endswith('cmsy10.ttf') or \
- #fontname.endswith('cmmi10.ttf') or \
- #fontname.endswith('cmex10.ttf'):
- # string = '\0' + chr(glyph)
-
- string = chr(glyph)
- self.file.output(string, Op.show)
+ string = chr(glyph)
+ self.file.output(string, Op.show)
self.file.output(Op.end_text)
+ for record in pswriter:
+ if record[0] == 'rect':
+ rec_type, ox, oy, width, height = record
+ self.file.output(Op.gsave, x + ox, y + oy, width, height, Op.rectangle, Op.fill, Op.grestore)
+
def _draw_tex(self, gc, x, y, s, prop, angle):
# Rename to draw_tex to enable, but note the following:
# TODO:
@@ -1208,9 +1208,7 @@
s = s.encode('cp1252', 'replace')
if ismath:
- fontsize = prop.get_size_in_points()
- w, h, pswriter, used_characters = math_parse_s_pdf(
- s, 72, fontsize, 0)
+ w, h, pswriter, used_characters = math_parse_s_pdf(s, 72, prop, 0)
elif rcParams['pdf.use14corefonts']:
font = self._get_font_afm(prop)
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2007-07-26 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2007-07-26 14:45:57 UTC (rev 3617)
@@ -278,7 +278,7 @@
if ismath:
width, height, pswriter, used_characters = math_parse_s_ps(
- s, 72, prop.get_size_in_points(), 0)
+ s, 72, prop, 0)
return width, height
if rcParams['ps.useafm']:
@@ -813,11 +813,9 @@
if debugPS:
self._pswriter.write("% mathtext\n")
- fontsize = prop.get_size_in_points()
width, height, pswriter, used_characters = \
- math_parse_s_ps(s, 72, fontsize, angle)
+ math_parse_s_ps(s, 72, prop, angle)
self.merge_used_characters(used_characters)
-
self.set_color(*gc.get_rgb())
thetext = pswriter.getvalue()
ps = """gsave
@@ -1038,13 +1036,14 @@
print >>fh, l.strip()
if not rcParams['ps.useafm']:
for font_filename, chars in renderer.used_characters.values():
- font = FT2Font(font_filename)
- cmap = font.get_charmap()
- glyph_ids = []
- for c in chars:
- gind = cmap.get(ord(c)) or 0
- glyph_ids.append(gind)
- convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids)
+ if len(chars):
+ font = FT2Font(font_filename)
+ cmap = font.get_charmap()
+ glyph_ids = []
+ for c in chars:
+ gind = cmap.get(ord(c)) or 0
+ glyph_ids.append(gind)
+ convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids)
print >>fh, "end"
print >>fh, "%%EndProlog"
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2007-07-26 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2007-07-26 14:45:57 UTC (rev 3617)
@@ -291,9 +291,12 @@
self._svgwriter.write (svg)
def _add_char_def(self, prop, char):
- newprop = prop.copy()
- newprop.set_size(self.FONT_SCALE)
- font = self._get_font(newprop)
+ if isinstance(prop, FontProperties):
+ newprop = prop.copy()
+ font = self._get_font(newprop)
+ else:
+ font = prop
+ font.set_size(self.FONT_SCALE, 72)
ps_name = font.get_sfnt()[(1,0,0,6)]
char_id = urllib.quote('%s-%d' % (ps_name, ord(char)))
if char_id in self._char_defs:
@@ -332,10 +335,10 @@
"""
Draw math text using matplotlib.mathtext
"""
- fontsize = prop.get_size_in_points()
- width, height, svg_elements = math_parse_s_ft2font_svg(s, 72, fontsize)
+ width, height, svg_elements, used_characters = \
+ math_parse_s_ft2font_svg(s, 72, prop)
svg_glyphs = svg_elements.svg_glyphs
- svg_lines = svg_elements.svg_lines
+ svg_rects = svg_elements.svg_rects
color = rgb2hex(gc.get_rgb())
self.open_group("mathtext")
@@ -349,10 +352,9 @@
svg.append('translate(%f,%f)' % (x, y))
svg.append('">\n')
- for fontname, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs:
- prop = FontProperties(family=fontname, size=fontsize)
- charid = self._add_char_def(prop, thetext)
-
+ for font, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs:
+ charid = self._add_char_def(font, thetext)
+
svg.append('<use xlink:href="#%s" transform="translate(%s, %s) scale(%s)"/>\n' %
(charid, new_x, -new_y_mtc, fontsize / self.FONT_SCALE))
svg.append('</g>\n')
@@ -366,7 +368,7 @@
curr_x,curr_y = 0.0,0.0
- for fontname, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs:
+ for font, fontsize, thetext, new_x, new_y_mtc, metrics in svg_glyphs:
if rcParams["mathtext.mathtext2"]:
new_y = new_y_mtc - height
else:
@@ -392,13 +394,20 @@
svg.append('</text>\n')
+ if len(svg_rects):
+ svg.append('<g style="fill: black; stroke: none" transform="')
+ if angle != 0:
+ svg.append('translate(%f,%f) rotate(%1.1f)'
+ % (x,y,-angle) )
+ else:
+ svg.append('translate(%f,%f)' % (x, y))
+ svg.append('">\n')
+
+ for x, y, width, height in svg_rects:
+ svg.append('<rect x="%s" y="%s" width="%s" height="%s" fill="black" stroke="none" />' % (x, -y + height, width, height))
+ svg.append("</g>")
+
self._svgwriter.write (''.join(svg))
- rgbFace = gc.get_rgb()
- for xmin, ymin, xmax, ymax in svg_lines:
- newx, newy = x + xmin, y + height - ymax#-(ymax-ymin)/2#-height
- self.draw_rectangle(gc, rgbFace, newx, newy, xmax-xmin, ymax-ymin)
- #~ self.draw_line(gc, x + xmin, y + ymin,# - height,
- #~ x + xmax, y + ymax)# - height)
self.close_group("mathtext")
def finish(self):
@@ -417,8 +426,8 @@
def get_text_width_height(self, s, prop, ismath):
if ismath:
- width, height, trash = math_parse_s_ft2font_svg(
- s, 72, prop.get_size_in_points())
+ width, height, trash, used_characters = \
+ math_parse_s_ft2font_svg(s, 72, prop)
return width, height
font = self._get_font(prop)
font.set_text(s, 0.0)
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-07-26 13:46:56 UTC (rev 3616)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-07-26 14:45:57 UTC (rev 3617)
@@ -14,7 +14,7 @@
handle fairly complex TeX expressions Eg, the following renders
correctly
- s = r'$\cal{R}\prod_{i=\alpha\cal{B}}^\infty a_i\rm{sin}(2 \pi f x_i)$'
+ s = r'$\mathcal{R}\prod_{i=\alpha\mathcal{B}}^\infty a_i\sin(2 \pi f x_i)$'
The fonts \cal, \rm, \it, and \tt are allowed.
@@ -59,17 +59,10 @@
^
use raw strings
- The $ symbols must be the first and last symbols in the string. Eg,
- you cannot do
+ Math and non-math can be interpresed in the same string. E.g.,
r'My label $x_i$'.
- but you can change fonts, as in
-
- r'$\rm{My label} x_i$'
-
- to achieve the same effect.
-
A large set of the TeX symbols are provided. Subscripting and
superscripting are supported, as well as the over/under style of
subscripting with \sum, \int, etc.
@@ -77,6 +70,8 @@
Allowed TeX symbols:
+ [MGDTODO: This list is no longer exhaustive and needs to be updated]
+
\/ \Delta \Downarrow \Gamma \Im \LEFTangle \LEFTbrace \LEFTbracket
\LEFTparen \Lambda \Leftarrow \Leftbrace \Leftbracket \Leftparen
\Leftrightarrow \Omega \P \Phi \Pi \Psi \RIGHTangle \RIGHTbrace
@@ -119,11 +114,16 @@
KNOWN ISSUES:
- - nested subscripts, eg, x_i_j not working; but you can do x_{i_j}
- - nesting fonts changes in sub/superscript groups not parsing
- - I would also like to add a few more layout commands, like \frac.
+ - Certainly there are some...
+STATUS:
+ The *Unicode* classes were incomplete when I found them, and have
+ not been refactored to support intermingling of regular text and
+ math text yet. They are most likely broken. -- Michael Droettboom, July 2007
+
Author : John Hunter <jdh...@ac...>
+ Michael Droettboom <md...@st...>
+ (rewrite based on TeX box layout algorithms)
Copyright : John Hunter (2004,2005)
License : matplotlib license (PSF compatible)
@@ -132,26 +132,32 @@
import os, sys
from cStringIO import StringIO
from sets import Set
+from warnings import warn
from matplotlib import verbose
from matplotlib.pyparsing import Literal, Word, OneOrMore, ZeroOrMore, \
Combine, Group, Optional, Forward, NotAny, alphas, nums, alphanums, \
- StringStart, StringEnd, ParseException, FollowedBy, Regex
+ StringStart, StringEnd, ParseFatalException, FollowedBy, Regex, \
+ operatorPrecedence, opAssoc, ParseResults, Or, Suppress, oneOf
from matplotlib.afm import AFM
-from matplotlib.cbook import enumerate, iterable, Bunch, get_realpath_and_stat
-from matplotlib.ft2font import FT2Font
+from matplotlib.cbook import enumerate, iterable, Bunch, get_realpath_and_stat, \
+ is_string_like
+from matplotlib.ft2font import FT2Font, KERNING_UNFITTED
from matplotlib.font_manager import fontManager, FontProperties
from matplotlib._mathtext_data import latex_to_bakoma, cmkern, \
latex_to_standard, tex2uni, type12uni, tex2type1, uni2type1
from matplotlib import get_data_path, rcParams
+####################
+
# symbols that have the sub and superscripts over/under
-overunder = { r'\sum' : 1,
- r'\int' : 1,
- r'\prod' : 1,
- r'\coprod' : 1,
- }
+overunder_symbols = {
+ r'\sum' : 1,
+ r'\int' : 1,
+ r'\prod' : 1,
+ r'\coprod' : 1,
+ }
# a character over another character
charOverChars = {
# The first 2 entires in the tuple are (font, char, sizescale) for
@@ -160,6 +166,8 @@
r'\angstrom' : ( ('rm', 'A', 1.0), (None, '\circ', 0.5), 0.0 ),
}
+##############################################################################
+# FONTS
def font_open(filename):
ext = filename.rsplit('.',1)[1]
@@ -224,7 +232,7 @@
The class must be able to take symbol keys and font file names and
return the character metrics as well as do the drawing
"""
-
+
def get_kern(self, facename, symleft, symright, fontsize, dpi):
"""
Get the kerning distance for font between symleft and symright.
@@ -264,7 +272,13 @@
def render(self, ox, oy, facename, sym, fontsize, dpi):
pass
-
+ def render_rect_filled(self, x1, y1, x2, y2):
+ pass
+
+ def get_used_characters(self):
+ return {}
+
+
class DummyFonts(Fonts):
'dummy class for debugging parser'
def get_metrics(self, font, sym, fontsize, dpi):
@@ -475,6 +489,8 @@
'rm' : 'cmr10.ttf',
'tt' : 'cmtt10.ttf',
'it' : 'cmmi10.ttf',
+ 'bf' : 'cmb10.ttf',
+ 'sf' : 'cmss10.ttf',
None : 'cmmi10.ttf',
}
@@ -542,78 +558,108 @@
# Old classes
-class BakomaTrueTypeFonts(Fonts):
+class BakomaFonts(Fonts):
"""
Use the Bakoma true type fonts for rendering
"""
- fnames = ('cmmi10', 'cmsy10', 'cmex10',
- 'cmtt10', 'cmr10')
# allocate a new set of fonts
basepath = os.path.join( get_data_path(), 'fonts', 'ttf' )
- fontmap = { 'cal' : 'cmsy10',
- 'rm' : 'cmr10',
- 'tt' : 'cmtt10',
- 'it' : 'cmmi10',
- None : 'cmmi10',
+ fontmap = { 'cal' : 'Cmsy10',
+ 'rm' : 'Cmr10',
+ 'tt' : 'Cmtt10',
+ 'it' : 'Cmmi10',
+ 'bf' : 'Cmb10',
+ 'sf' : 'Cmss10',
+ None : 'Cmmi10',
+ 'ex' : 'Cmex10'
}
- def __init__(self, useSVG=False):
- self.glyphd = {}
- self.fonts = dict(
- [ (name, FT2Font(os.path.join(self.basepath, name) + '.ttf'))
- for name in self.fnames])
+ class CachedFont:
+ def __init__(self, font):
+ self.font = font
+ self.charmap = font.get_charmap()
+ self.glyphmap = dict(
+ [(glyphind, ccode) for ccode, glyphind in self.charmap.items()])
+
+ def __init__(self):
+ self.glyphd = {}
+ self.fonts = {}
+ self.used_characters = {}
- self.charmaps = dict(
- [ (name, self.fonts[name].get_charmap()) for name in self.fnames])
- # glyphmaps is a dict names to a dict of glyphindex -> charcode
- self.glyphmaps = {}
- for name in self.fnames:
- cmap = self.charmaps[name]
- self.glyphmaps[name] = dict([(glyphind, ccode) for ccode, glyphind in cmap.items()])
+ def _get_font(self, font):
+ """Looks up a CachedFont with its charmap and inverse charmap.
+ font may be a TeX font name (cal, rm, it etc.), a Computer Modern
+ font name (cmtt10, cmr10, etc.) or an FT2Font object."""
+ if isinstance(font, str):
+ if font not in self.fontmap.values():
+ basename = self.fontmap[font]
+ else:
+ basename = font
+ else:
+ basename = font.postscript_name
- for font in self.fonts.values():
- font.clear()
- if useSVG:
- self.svg_glyphs=[] # a list of "glyphs" we need to render this thing in SVG
- else: pass
- self.usingSVG = useSVG
+ cached_font = self.fonts.get(basename)
+ if cached_font is None:
+ if isinstance(font, str):
+ font = FT2Font(os.path.join(self.basepath, basename.lower() + ".ttf"))
+ basename = font.postscript_name
+ cached_font = self.CachedFont(font)
+ self.fonts[basename] = cached_font
+ return basename, cached_font
+ def get_font(self, font):
+ return self._get_font(font)[1].font
+
+ def get_fonts(self):
+ return [x.font for x in self.fonts.values()]
+
def get_metrics(self, font, sym, fontsize, dpi):
- cmfont, metrics, glyph, offset = \
+ basename, font, metrics, symbol_name, num, glyph, offset = \
self._get_info(font, sym, fontsize, dpi)
return metrics
+ def _get_offset(self, basename, cached_font, glyph, fontsize, dpi):
+ if basename.lower() == 'cmex10':
+ return glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
+ return 0.
+
def _get_info (self, font, sym, fontsize, dpi):
'load the cmfont, metrics and glyph with caching'
- key = font, sym, fontsize, dpi
+ if hasattr(font, 'postscript_name'):
+ fontname = font.postscript_name
+ else:
+ fontname = font
+
+ key = fontname, sym, fontsize, dpi
tup = self.glyphd.get(key)
if tup is not None: return tup
-
- basename = self.fontmap[font]
-
- if latex_to_bakoma.has_key(sym):
+
+ if font in self.fontmap and latex_to_bakoma.has_key(sym):
basename, num = latex_to_bakoma[sym]
- num = self.glyphmaps[basename][num]
+ basename, cached_font = self._get_font(basename.capitalize())
+ symbol_name = cached_font.font.get_glyph_name(num)
+ num = cached_font.glyphmap[num]
elif len(sym) == 1:
+ basename, cached_font = self._get_font(font)
num = ord(sym)
+ symbol_name = cached_font.font.get_glyph_name(cached_font.charmap[num])
else:
num = 0
raise ValueError('unrecognized symbol "%s"' % sym)
- #print sym, basename, num
- cmfont = self.fonts[basename]
- cmfont.set_size(fontsize, dpi)
- head = cmfont.get_sfnt_table('head')
- glyph = cmfont.load_char(num)
+ font = cached_font.font
+ font.set_size(fontsize, dpi)
+ glyph = font.load_char(num)
+ realpath, stat_key = get_realpath_and_stat(font.fname)
+ used_characters = self.used_characters.setdefault(
+ stat_key, (realpath, Set()))
+ used_characters[1].update(unichr(num))
+
xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- if basename == 'cmex10':
- offset = glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
- #offset = -(head['yMin']+512)/head['unitsPerEm']*10.
- else:
- offset = 0.
+ offset = self._get_offset(basename, cached_font, glyph, fontsize, dpi)
metrics = Bunch(
advance = glyph.linearHoriAdvance/65536.0,
height = glyph.height/64.0,
@@ -622,211 +668,120 @@
xmax = xmax,
ymin = ymin+offset,
ymax = ymax+offset,
+ # iceberg is the equivalent of TeX's "height"
+ iceberg = glyph.horiBearingY/64.0 + offset
)
- self.glyphd[key] = cmfont, metrics, glyph, offset
+ self.glyphd[key] = basename, font, metrics, symbol_name, num, glyph, offset
return self.glyphd[key]
def set_canvas_size(self, w, h):
'Dimension the drawing canvas; may be a noop'
self.width = int(w)
self.height = int(h)
- for font in self.fonts.values():
- font.set_bitmap_size(int(w), int(h))
+ for cached_font in self.fonts.values():
+ cached_font.font.set_bitmap_size(int(w), int(h))
def render(self, ox, oy, font, sym, fontsize, dpi):
- cmfont, metrics, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
+ basename, font, metrics, symbol_name, num, glyph, offset = \
+ self._get_info(font, sym, fontsize, dpi)
- if not self.usingSVG:
- cmfont.draw_glyph_to_bitmap(
- int(ox), int(self.height - oy - metrics.ymax), glyph)
- else:
- oy += offset - 512/2048.*10.
- basename = self.fontmap[font]
- if latex_to_bakoma.has_key(sym):
- basename, num = latex_to_bakoma[sym]
- num = self.glyphmaps[basename][num]
- elif len(sym) == 1:
- num = ord(sym)
- else:
- num = 0
- print >>sys.stderr, 'unrecognized symbol "%s"' % sym
- thetext = unichr(num)
- thetext.encode('utf-8')
- self.svg_glyphs.append((basename, fontsize, thetext, ox, oy, metrics))
+ font.draw_glyph_to_bitmap(
+ int(ox), int(oy - metrics.ymax), glyph)
+ def render_rect_filled(self, x1, y1, x2, y2):
+ assert len(self.fonts)
+ font = self.fonts.values()[0]
+ font.font.draw_rect_filled(x1, y1, max(x2 - 1, x1), max(y2 - 1, y1))
+
+ def get_used_characters(self):
+ return self.used_characters
- def _old_get_kern(self, font, symleft, symright, fontsize, dpi):
- """
- Get the kerning distance for font between symleft and symright.
+ def get_xheight(self, font, fontsize, dpi):
+ basename, cached_font = self._get_font(font)
+ cached_font.font.set_size(fontsize, dpi)
+ pclt = cached_font.font.get_sfnt_table('pclt')
+ xHeight = pclt['xHeight'] / 64.0
+ return xHeight
- font is one of tt, it, rm, cal or None
+ def get_underline_thickness(self, font, fontsize, dpi):
+ basename, cached_font = self._get_font(font)
+ cached_font.font.set_size(fontsize, dpi)
+ return max(1.0, cached_font.font.underline_thickness / 64.0)
- sym is a single symbol(alphanum, punct) or a special symbol
- like \sigma.
-
- """
- basename = self.fontmap[font]
- cmfont = self.fonts[basename]
- cmfont.set_size(fontsize, dpi)
- kernd = cmkern[basename]
- key = symleft, symright
- kern = kernd.get(key,0)
- #print basename, symleft, symright, key, kern
- return kern
-
- def _get_num(self, font, sym):
- 'get charcode for sym'
- basename = self.fontmap[font]
- if latex_to_bakoma.has_key(sym):
- basename, num = latex_to_bakoma[sym]
- num = self.glyphmaps[basename][num]
- elif len(sym) == 1:
- num = ord(sym)
- else:
- num = 0
- return num
-
-
-class BakomaPSFonts(Fonts):
+ def get_kern(self, fontleft, symleft, fontsizeleft,
+ fontright, symright, fontsizeright, dpi):
+ if fontsizeleft == fontsizeright:
+ basename, font1, metrics, symbol_name, num1, glyph1, offset = \
+ self._get_info(fontleft, symleft, fontsizeleft, dpi)
+ basename, font2, metrics, symbol_name, num2, glyph2, offset = \
+ self._get_info(fontright, symright, fontsizeright, dpi)
+ if font1 == font2:
+ basename, font = self._get_font(font1)
+ return font.font.get_kerning(num1, num2, KERNING_UNFITTED) / 64.0
+ return 0.0
+
+class BakomaPSFonts(BakomaFonts):
"""
Use the Bakoma postscript fonts for rendering to backend_ps
"""
- facenames = ('cmmi10', 'cmsy10', 'cmex10',
- 'cmtt10', 'cmr10')
- # allocate a new set of fonts
- basepath = os.path.join( get_data_path(), 'fonts', 'ttf' )
- fontmap = { 'cal' : 'cmsy10',
- 'rm' : 'cmr10',
- 'tt' : 'cmtt10',
- 'it' : 'cmmi10',
- None : 'cmmi10',
- }
-
- def __init__(self):
- self.glyphd = {}
- self.fonts = dict(
- [ (name, FT2Font(os.path.join(self.basepath, name) + '.ttf'))
- for name in self.facenames])
-
- self.glyphmaps = {}
- for facename in self.facenames:
- charmap = self.fonts[facename].get_charmap()
- self.glyphmaps[facename] = dict([(glyphind, charcode)
- for charcode, glyphind in charmap.items()])
- for font in self.fonts.values():
- font.clear()
-
- self.used_characters = {}
-
- def _get_info (self, font, sym, fontsize, dpi):
- 'load the cmfont, metrics and glyph with caching'
- key = font, sym, fontsize, dpi
- tup = self.glyphd.get(key)
-
- if tup is not None:
- return tup
-
- basename = self.fontmap[font]
-
- if latex_to_bakoma.has_key(sym):
- basename, num = latex_to_bakoma[sym]
- sym = self.fonts[basename].get_glyph_name(num)
- num = self.glyphmaps[basename][num]
- elif len(sym) == 1:
- num = ord(sym)
- else:
- num = 0
- #sym = '.notdef'
- raise ValueError('unrecognized symbol "%s, %d"' % (sym, num))
-
- cmfont = self.fonts[basename]
- cmfont.set_size(fontsize, dpi)
- head = cmfont.get_sfnt_table('head')
- glyph = cmfont.load_char(num)
-
- realpath, stat_key = get_realpath_and_stat(cmfont.fname)
- used_characters = self.used_characters.setdefault(
- stat_key, (realpath, Set()))
- used_characters[1].update(unichr(num))
-
- xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- if basename == 'cmex10':
- offset = -(head['yMin']+512)/head['unitsPerEm']*10.
- else:
- offset = 0.
- metrics = Bunch(
- advance = glyph.linearHoriAdvance/65536.0,
- height = glyph.height/64.0,
- width = glyph.width/64.0,
- xmin = xmin,
- xmax = xmax,
- ymin = ymin+offset,
- ymax = ymax+offset
- )
-
- self.glyphd[key] = basename, metrics, sym, offset
- return basename, metrics, '/'+sym, offset
-
def set_canvas_size(self, w, h, pswriter):
'Dimension the drawing canvas; may be a noop'
self.width = w
self.height = h
self.pswriter = pswriter
-
def render(self, ox, oy, font, sym, fontsize, dpi):
- fontname, metrics, glyphname, offset = \
+ basename, font, metrics, symbol_name, num, glyph, offset = \
self._get_info(font, sym, fontsize, dpi)
- fontname = fontname.capitalize()
- if fontname == 'Cmex10':
- oy += offset - 512/2048.*10.
-
- ps = """/%(fontname)s findfont
+ oy = self.height - oy + offset
+
+ ps = """/%(basename)s findfont
%(fontsize)s scalefont
setfont
%(ox)f %(oy)f moveto
-/%(glyphname)s glyphshow
+/%(symbol_name)s glyphshow
""" % locals()
self.pswriter.write(ps)
-
- def get_metrics(self, font, sym, fontsize, dpi):
- basename, metrics, sym, offset = \
- self._get_info(font, sym, fontsize, dpi)
- return metrics
-
+ def render_rect_filled(self, x1, y1, x2, y2):
+ ps = "%f %f %f %f rectfill" % (x1, self.height - y2, x2 - x1, y2 - y1)
+ self.pswriter.write(ps)
+
class BakomaPDFFonts(BakomaPSFonts):
"""Hack of BakomaPSFonts for PDF support."""
- def _get_filename_and_num (self, font, sym, fontsize, dpi):
- 'should be part of _get_info'
- basename = self.fontmap[font]
+ def render(self, ox, oy, font, sym, fontsize, dpi):
+ basename, font, metrics, symbol_name, num, glyph, offset = \
+ self._get_info(font, sym, fontsize, dpi)
+ filename = font.fname
+ oy = self.height - oy + offset
- if latex_to_bakoma.has_key(sym):
- basename, num = latex_to_bakoma[sym]
- sym = self.fonts[basename].get_glyph_name(num)
- num = self.glyphmaps[basename][num]
- elif len(sym) == 1:
- num = ord(sym)
- else:
- num = 0
- raise ValueError('unrecognized symbol "%s"' % (sym,))
+ self.pswriter.append(('glyph', ox, oy, filename, fontsize, num))
- return os.path.join(self.basepath, basename) + '.ttf', num
-
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.pswriter.append(('rect', x1, self.height - y2, x2 - x1, y2 - y1))
+
+class BakomaSVGFonts(BakomaFonts):
+ """Hack of BakomaFonts for SVG support."""
+ def __init__(self):
+ BakomaFonts.__init__(self)
+ self.svg_glyphs = []
+ self.svg_rects = []
+
def render(self, ox, oy, font, sym, fontsize, dpi):
- fontname, metrics, glyphname, offset = \
+ basename, font, metrics, symbol_name, num, glyph, offset = \
self._get_info(font, sym, fontsize, dpi)
- filename, num = self._get_filename_and_num(font, sym, fontsize, dpi)
- if fontname.lower() == 'cmex10':
- oy += offset - 512/2048.*10.
- self.pswriter.append((ox, oy, filename, fontsize, num))
+ oy = self.height - oy + offset
+ thetext = unichr(num)
+ thetext.encode('utf-8')
+ self.svg_glyphs.append((font, fontsize, thetext, ox, oy, metrics))
-
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.svg_rects.append((x1, self.height - y2, x2 - x1, y2 - y1))
+
class StandardPSFonts(Fonts):
"""
Use the standard postscript fonts for rendering to backend_ps
@@ -835,21 +790,51 @@
# allocate a new set of fonts
basepath = os.path.join( get_data_path(), 'fonts', 'afm' )
- fontmap = { 'cal' : 'pzcmi8a',
- 'rm' : 'pncr8a',
- 'tt' : 'pcrr8a',
- 'it' : 'pncri8a',
+ fontmap = { 'cal' : 'pzcmi8a', # Zapf Chancery
+ 'rm' : 'pncr8a', # New Century Schoolbook
+ 'tt' : 'pcrr8a', # Courier
+ 'it' : 'pncri8a', # New Century Schoolbook Italic
+ 'sf' : 'phvr8a', # Helvetica
+ 'bf' : 'pncb8a', # New Century Schoolbook Bold
+ None : 'psyr' # Symbol
}
def __init__(self):
self.glyphd = {}
- self.fonts = dict(
- [ (name, AFM(file(os.path.join(self.basepath, name) + '.afm')))
- for name in self.fnames])
+ self.fonts = {}
+ def _get_font(self, font):
+ if isinstance(font, str):
+ if font not in self.fontmap.values():
+ basename = self.fontmap[font]
+ else:
+ basename = font
+ else:
+ basename = font.get_fontname()
+
+ cached_font = self.fonts.get(basename)
+ if cached_font is None:
+ if isinstance(font, str):
+ fname = os.path.join(self.basepath, basename + ".afm")
+ cached_font = AFM(file(fname, 'r'))
+ cached_font.fname = fname
+ basename = cached_font.get_fontname()
+ else:
+ cached_font = font
+ self.fonts[basename] = cached_font
+ return basename, cached_font
+
+ def get_fonts(self):
+ return [x.font for x in self.fonts.values()]
+
def _get_info (self, font, sym, fontsize, dpi):
'load the cmfont, metrics and glyph with caching'
- key = font, sym, fontsize, dpi
+ if hasattr(font, 'get_fontname'):
+ fontname = font.get_fontname()
+ else:
+ fontname = font
+
+ key = fontname, sym, fontsize, dpi
tup = self.glyphd.get(key)
if tup is not None:
@@ -857,41 +842,42 @@
if sym in "0123456789()" and font == 'it':
font = 'rm'
- basename = self.fontmap[font]
if latex_to_standard.has_key(sym):
- basename, num = latex_to_standard[sym]
- char = chr(num)
+ font, num = latex_to_standard[sym]
+ glyph = chr(num)
elif len(sym) == 1:
- char = sym
+ glyph = sym
+ num = ord(glyph)
else:
raise ValueError('unrecognized symbol "%s"' % (sym))
-
+ basename, font = self._get_font(font)
+
try:
- sym = self.fonts[basename].get_name_char(char)
+ symbol_name = font.get_name_char(glyph)
except KeyError:
raise ValueError('unrecognized symbol "%s"' % (sym))
offset = 0
- cmfont = self.fonts[basename]
- fontname = cmfont.get_fontname()
scale = 0.001 * fontsize
xmin, ymin, xmax, ymax = [val * scale
- for val in cmfont.get_bbox_char(char)]
+ for val in font.get_bbox_char(glyph)]
metrics = Bunch(
advance = (xmax-xmin),
- width = cmfont.get_width_char(char) * scale,
- height = cmfont.get_width_char(char) * scale,
+ width = font.get_width_char(glyph) * scale,
+ height = font.get_height_char(glyph) * scale,
xmin = xmin,
xmax = xmax,
ymin = ymin+offset,
- ymax = ymax+offset
+ ymax = ymax+offset,
+ # iceberg is the equivalent of TeX's "height"
+ iceberg = ymax + offset
)
- self.glyphd[key] = fontname, basename, metrics, sym, offset, char
- return fontname, basename, metrics, '/'+sym, offset, char
+ self.glyphd[key] = basename, font, metrics, symbol_name, num, glyph, offset
+ return self.glyphd[key]
def set_canvas_size(self, w, h, pswriter):
'Dimension the drawing canvas; may be a noop'
@@ -899,637 +885,1292 @@
self.height = h
self.pswriter = pswriter
-
def render(self, ox, oy, font, sym, fontsize, dpi):
- fontname, basename, metrics, glyphname, offset, char = \
+ basename, font, metrics, symbol_name, num, glyph, offset = \
self._get_info(font, sym, fontsize, dpi)
- ps = """/%(fontname)s findfont
+ oy = self.height - oy
+ ps = """/%(basename)s findfont
%(fontsize)s scalefont
setfont
%(ox)f %(oy)f moveto
-/%(glyphname)s glyphshow
+/%(symbol_name)s glyphshow
""" % locals()
self.pswriter.write(ps)
def get_metrics(self, font, sym, fontsize, dpi):
- fontname, basename, metrics, sym, offset, char = \
+ basename, font, metrics, symbol_name, num, glyph, offset = \
self._get_info(font, sym, fontsize, dpi)
return metrics
- def get_kern(self, font, symleft, symright, fontsize, dpi):
- fontname, basename, metrics, sym, offset, char1 = \
- self._get_info(font, symleft, fontsize, dpi)
- fontname, basename, metrics, sym, offset, char2 = \
- self._get_info(font, symright, fontsize, dpi)
- cmfont = self.fonts[basename]
- return cmfont.get_kern_dist(char1, char2) * 0.001 * fontsize
+ def get_kern(self, fontleft, symleft, fontsizeleft,
+ fontright, symright, fontsizeright, dpi):
+ if fontsizeleft == fontsizeright:
+ basename, font1, metrics, symbol_name, num, glyph1, offset = \
+ self._get_info(fontleft, symleft, fontsizeleft, dpi)
+ basename, font2, metrics, symbol_name, num, glyph2, offset = \
+ self._get_info(fontright, symright, fontsizeright, dpi)
+ if font1.get_fontname() == font2.get_fontname():
+ basename, font = self._get_font(font1)
+ return font.get_kern_dist(glyph1, glyph2) * 0.001 * fontsizeleft
+ return 0.0
-class Element:
- fontsize = 12
- dpi = 72
- font = 'it'
- _padx, _pady = 2, 2 # the x and y padding in points
- _scale = 1.0
+ def render_rect_filled(self, x1, y1, x2, y2):
+ ps = "%f %f %f %f rectfill" % (x1, self.height - y2, x2 - x1, y2 - y1)
+ self.pswriter.write(ps)
- def __init__(self):
- # a dict mapping the keys above, below, subscript,
- # superscript, right to Elements in that position
- self.neighbors = {}
- self.ox, self.oy = 0, 0
+ def get_xheight(self, font, fontsize, dpi):
+ basename, cached_font = self._get_font(font)
+ return cached_font.get_xheight() * 0.001 * fontsize
- def advance(self):
- 'get the horiz advance'
- raise NotImplementedError('derived must override')
+ def get_underline_thickness(self, font, fontsize, dpi):
+ basename, cached_font = self._get_font(font)
+ return cached_font.get_underline_thickness() * 0.001 * fontsize
+
+##############################################################################
+# TeX-LIKE BOX MODEL
- def height(self):
- 'get the element height: ymax-ymin'
- raise NotImplementedError('derived must override')
+# The following is based directly on the document 'woven' from the
+# TeX82 source code. This information is also available in printed
+# form:
+#
+# Knuth, Donald E.. 1986. Computers and Typesetting, Volume B:
+# TeX: The Program. Addison-Wesley Professional.
+#
+# The most relevant "chapters" are:
+# Data structures for boxes and their friends
+# Shipping pages out (Ship class)
+# Packaging (hpack and vpack)
+# Data structures for math mode
+# Subroutines for math mode
+# Typesetting math formulas
+#
+# Many of the docstrings below refer to a numbered "node" in that
+# book, e.g. @123
+#
+# Note that (as TeX) y increases downward, unlike many other parts of
+# matplotlib.
- def width(self):
- 'get the element width: xmax-xmin'
- raise NotImplementedError('derived must override')
+# How much text shrinks when going to the next-smallest level
+SHRINK_FACTOR = 0.7
+# The number of different sizes of chars to use, beyond which they will not
+# get any smaller
+NUM_SIZE_LEVELS = 3
+# Percentage of x-height that subscripts drop below the baseline
+SUBDROP = 0.05
+# Percentage of x-height that superscripts drop below the baseline
+SUP1 = 0.2
+# Percentage of x-height that subscripts drop below the baseline
+SUB1 = 0.3
+# Percentage of x-height that superscripts are offset relative to the subscript
+DELTA = 0.05
+
+class MathTextWarning(Warning):
+ pass
+
+class Node(object):
+ """A node in a linked list.
+ @133
+ """
+ def __init__(self):
+ self.link = None
+ self.size = 0
+
+ def __repr__(self):
+ s = self.__internal_repr__()
+ if self.link:
+ s += ' ' + self.link.__repr__()
+ return s
- def xmin(self):
- 'get the xmin of ink rect'
- raise NotImplementedError('derived must override')
+ def __internal_repr__(self):
+ return self.__class__.__name__
- def xmax(self):
- 'get the xmax of ink rect'
- raise NotImplementedError('derived must override')
+ def get_kerning(self, next):
+ return 0.0
- def ymin(self):
- 'get the ymin of ink rect'
- raise NotImplementedError('derived must override')
+ def set_link(self, other):
+ self.link = other
- def ymax(self):
- 'get the ymax of ink rect'
- raise NotImplementedError('derived must override')
+ def pack(self):
+ if self.link:
+ self.link.pack()
- def set_font(self, font):
- 'set the font (one of tt, it, rm , cal)'
- raise NotImplementedError('derived must override')
+ def shrink(self):
+ """Shrinks one level smaller. There are only three levels of sizes,
+ after which things will no longer get smaller."""
+ if self.link:
+ self.link.shrink()
+ self.size += 1
+
+ def render(self, x, y):
+ pass
- def render(self):
- 'render to the fonts canvas'
- for element in self.neighbors.values():
- element.render()
+class Box(Node):
+ """Represents any node with a physical location.
+ @135"""
+ def __init__(self, width, height, depth):
+ Node.__init__(self)
+ self.width = width
+ self.height = height
+ self.depth = depth
- def set_origin(self, ox, oy):
- self.ox, self.oy = ox, oy
+ def shrink(self):
+ Node.shrink(self)
+ if self.size < NUM_SIZE_LEVELS:
+ if self.width is not None:
+ self.width *= SHRINK_FACTOR
+ if self.height is not None:
+ self.height *= SHRINK_FACTOR
+ if self.depth is not None:
+ self.depth *= SHRINK_FACTOR
- # order matters! right needs to be evaled last
- keys = ('above', 'below', 'subscript', 'superscript', 'right')
- for loc in keys:
- element = self.neighbors.get(loc)
- if element is None: continue
+ def render(self, x1, y1, x2, y2):
+ pass
- if loc=='above':
- nx = self.centerx() - element.width()/2.0
- ny = self.ymax() + self.pady() + (element.oy - element.ymax() + element.height())
- #print element, self.ymax(), element.height(), element.ymax(), element.ymin(), ny
- elif loc=='below':
- nx = self.centerx() - element.width()/2.0
- ny = self.ymin() - self.pady() - element.height()
- elif loc=='superscript':
- nx = self.xmax()
- ny = self.ymax() - self.pady()
- elif loc=='subscript':
- nx = self.xmax()
- ny = self.oy - 0.5*element.height()
- elif loc=='right':
- nx = self.ox + self.advance()
- if self.neighbors.has_key('subscript'):
- o = self.neighbors['subscript']
- nx = max(nx, o.ox + o.advance())
- if self.neighbors.has_key('superscript'):
- o = self.neighbors['superscript']
- nx = max(nx, o.ox + o.advance())
+class Vbox(Box):
+ def __init__(self, height, depth):
+ Box.__init__(self, 0., height, depth)
- ny = self.oy
- element.set_origin(nx, ny)
+class Hbox(Box):
+ def __init__(self, width):
+ Box.__init__(self, width, 0., 0.)
+
+class Char(Node):
+ """Represents a single character. Unlike TeX, the font
+ information and metrics are stored with each Char to make it
+ easier to lookup the font metrics when needed. Note that TeX
+ boxes have a width, height, and depth, unlike Type1 and Truetype
+ which use a full bounding box and an advance in the x-direction.
+ The metrics must be converted to the TeX way, and the advance (if
+ different from width) must be converted into a Kern node when the
+ Char is added to its parent Hlist.
+ @134"""
+ def __init__(self, c, state):
+ Node.__init__(self)
+ self.c = c
+ self.font_output = state.font_output
+ self.font = state.font
+ self.fontsize = state.fontsize
+ self.dpi = state.dpi
+ # The real width, height and depth will be set during the
+ # pack phase, after we know the real fontsize
+ self._update_metrics()
+
+ def __internal_repr__(self):
+ return '`%s`' % self.c
- def set_size_info(self, fontsize, dpi):
- self.fontsize = self._scale*fontsize
- self.dpi = dpi
- for loc, element in self.neighbors.items():
- if loc in ('subscript', 'superscript'):
- element.set_size_info(0.7*self.fontsize, dpi)
- else:
- element.set_size_info(self.fontsize, dpi)
+ def _update_metrics(self):
+ metrics = self._metrics = self.font_output.get_metrics(
+ self.font, self.c, self.fontsize, self.dpi)
+ self.width = metrics.width
+ self.height = metrics.iceberg
+ self.depth = -(metrics.iceberg - metrics.height)
+
+ def get_kerning(self, next):
+ """Return the amount of kerning between this and the given
+ character. Called when characters are strung together into
+ Hlists to create Kern nodes."""
+ advance = self._metrics.advance - self.width
+ kern = 0.
+ if isinstance(next, Char):
+ kern = self.font_output.get_kern(self.font, self.c, self.fontsize, next.font, next.c, next.fontsize, self.dpi)
+ return advance + kern
+
+ def render(self, x, y):
+ """Render the character to the canvas"""
+ self.font_output.render(
+ x, y,
+ self.font, self.c, self.fontsize, self.dpi)
- def pady(self):
- return self.dpi/72.0*self._pady
+ def shrink(self):
+ Node.shrink(self)
+ if self.size < NUM_SIZE_LEVELS:
+ self.fontsize *= SHRINK_FACTOR
+ self._update_metrics()
- def padx(self):
- return self.dpi/72.0*self._padx
+class Accent(Char):
+ """The font metrics need to be dealt with differently for accents, since they
+ are already offset correctly from the baseline in TrueType fonts."""
+ def _update_metrics(self):
+ metrics = self._metrics = self.font_output.get_metrics(
+ self.font, self.c, self.fontsize, self.dpi)
+ self.width = metrics.width
+ self.height = metrics.ymax - metrics.ymin
+ self.depth = 0
- def set_padx(self, pad):
- 'set the y padding in points'
- self._padx = pad
+ def render(self, x, y):
+ """Render the character to the canvas"""
+ self.font_output.render(
+ x, y + (self._metrics.ymax - self.height),
+ self.font, self.c, self.fontsize, self.dpi)
+
+class List(Box):
+ """A list of nodes (either horizontal or vertical).
+ @135"""
+ def __init__(self, elements):
+ Box.__init__(self, 0., 0., 0.)
+ self.shift_amount = 0. # An arbitrary offset
+ self.list_head = None # The head of a linked list of Nodes in this box
+ # The following parameters are set in the vpack and hpack functions
+ self.glue_set = 0. # The glue setting of this list
+ self.glue_sign = 0 # 0: normal, -1: shrinking, 1: stretching
+ self.glue_order = 0 # The order of infinity (0 - 3) for the glue
+
+ # Convert the Python list to a linked list
+ if len(elements):
+ elem = self.list_head = elements[0]
+ for next in elements[1:]:
+ elem.set_link(next)
+ elem = next
- def set_pady(self, pad):
- 'set the y padding in points'
- self._pady = pad
+ def ...
[truncated message content] |
|
From: <md...@us...> - 2007-07-26 13:46:59
|
Revision: 3616
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3616&view=rev
Author: mdboom
Date: 2007-07-26 06:46:56 -0700 (Thu, 26 Jul 2007)
Log Message:
-----------
Committing in preparation for merge
Modified Paths:
--------------
branches/mathtext_mgd/examples/mathtext_examples.py
branches/mathtext_mgd/lib/matplotlib/mathtext.py
Modified: branches/mathtext_mgd/examples/mathtext_examples.py
===================================================================
--- branches/mathtext_mgd/examples/mathtext_examples.py 2007-07-26 13:26:26 UTC (rev 3615)
+++ branches/mathtext_mgd/examples/mathtext_examples.py 2007-07-26 13:46:56 UTC (rev 3616)
@@ -10,7 +10,7 @@
r'$x\leftarrow y\ x\forall y$',
r'$x \sf x \bf x {\cal X} \rm x$',
r'$\{ \rm braces \}$',
- r'$\left[\left\lfloor\frac{5}{\frac{3}{4}} y\right)\right]$',
+ r'$\left[\left\lfloor\frac{5}{\frac{\left(3\right)}{4}} y\right)\right]$',
r'$\left(x\right)$',
r'$\sin(x)$',
r'$x_2$',
Modified: branches/mathtext_mgd/lib/matplotlib/mathtext.py
===================================================================
--- branches/mathtext_mgd/lib/matplotlib/mathtext.py 2007-07-26 13:26:26 UTC (rev 3615)
+++ branches/mathtext_mgd/lib/matplotlib/mathtext.py 2007-07-26 13:46:56 UTC (rev 3616)
@@ -1728,24 +1728,16 @@
bslash = Literal('\\')
- accent = oneOf("hat check dot breve acute ddot grave tilde bar vec "
- "\" ` ' ~ . ^")
+ accent = oneOf("hat check dot breve acute ddot grave tilde bar "
+ "vec \" ` ' ~ . ^")
- function = oneOf("arccos csc ker min arcsin deg lg Pr arctan det lim sec "
- "arg dim liminf sin cos exp limsup sinh cosh gcd ln sup "
- "cot hom log tan coth inf max tanh")
+ function = oneOf("arccos csc ker min arcsin deg lg Pr arctan det "
+ "lim sec arg dim liminf sin cos exp limsup sinh "
+ "cosh gcd ln sup cot hom log tan coth inf max "
+ "tanh")
number = Combine(Word(nums) + Optional(Literal('.')) + Optional( Word(nums) ))
- plus = Literal('+')
- minus = Literal('-')
- times = Literal('*')
- div = Literal('/')
- binop =(plus
- | minus
- | times
- | div)
-
fontname = oneOf("rm cal it tt sf bf")
latex2efont = oneOf("mathrm mathcal mathit mathtt mathsf mathbf")
@@ -1784,7 +1776,9 @@
group = Group(
start_group
- + OneOrMore(simple)
+ + OneOrMore(
+ autoDelim
+ | simple)
+ end_group
).setParseAction(self.group).setName("group")
@@ -1833,8 +1827,7 @@
\updownarrow \Uparrow \Downarrow
\Updownarrow""")
leftDelim = oneOf(r"( [ { \lfloor \langle \lceil")
- rightDelim = oneOf(r") ] } \rfloot \rangle \rceil")
-
+ rightDelim = oneOf(r") ] } \rfloor \rangle \rceil")
autoDelim <<(Suppress(Literal(r"\left"))
+ (leftDelim | ambiDelim)
+ Group(
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2007-07-26 13:26:29
|
Revision: 3615
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3615&view=rev
Author: mdboom
Date: 2007-07-26 06:26:26 -0700 (Thu, 26 Jul 2007)
Log Message:
-----------
Important bugfix (many expressions were silently failing)
Modified Paths:
--------------
branches/mathtext_mgd/examples/mathtext_examples.py
branches/mathtext_mgd/lib/matplotlib/_mathtext_data.py
branches/mathtext_mgd/lib/matplotlib/mathtext.py
Modified: branches/mathtext_mgd/examples/mathtext_examples.py
===================================================================
--- branches/mathtext_mgd/examples/mathtext_examples.py 2007-07-25 20:19:25 UTC (rev 3614)
+++ branches/mathtext_mgd/examples/mathtext_examples.py 2007-07-26 13:26:26 UTC (rev 3615)
@@ -52,7 +52,7 @@
os.system("pdflatex mathtext_examples.ltx")
else:
for i, s in enumerate(stests):
- print s
+ print "%02d: %s" % (i, s)
plot([1,2,3], 'r')
x = arange(0.0, 3.0, 0.1)
Modified: branches/mathtext_mgd/lib/matplotlib/_mathtext_data.py
===================================================================
--- branches/mathtext_mgd/lib/matplotlib/_mathtext_data.py 2007-07-25 20:19:25 UTC (rev 3614)
+++ branches/mathtext_mgd/lib/matplotlib/_mathtext_data.py 2007-07-26 13:26:26 UTC (rev 3615)
@@ -38,8 +38,10 @@
r'\SQRT' : ('cmex10', 53),
r'\leftbrace' : ('cmex10', 92),
r'{' : ('cmex10', 92),
+ r'\{' : ('cmex10', 92),
r'\rightbrace' : ('cmex10', 130),
r'}' : ('cmex10', 130),
+ r'\}' : ('cmex10', 130),
r'\leftangle' : ('cmex10', 97),
r'\rightangle' : ('cmex10', 64),
r'\Leftparen' : ('cmex10', 112),
Modified: branches/mathtext_mgd/lib/matplotlib/mathtext.py
===================================================================
--- branches/mathtext_mgd/lib/matplotlib/mathtext.py 2007-07-25 20:19:25 UTC (rev 3614)
+++ branches/mathtext_mgd/lib/matplotlib/mathtext.py 2007-07-26 13:26:26 UTC (rev 3615)
@@ -59,17 +59,10 @@
^
use raw strings
- The $ symbols must be the first and last symbols in the string. Eg,
- you cannot do
+ Math and non-math can be interpresed in the same string. E.g.,
r'My label $x_i$'.
- but you can change fonts, as in
-
- r'$\rm{My label} x_i$'
-
- to achieve the same effect.
-
A large set of the TeX symbols are provided. Subscripting and
superscripting are supported, as well as the over/under style of
subscripting with \sum, \int, etc.
@@ -1714,7 +1707,7 @@
_spaced_symbols = _binary_operators | _relation_symbols | _arrow_symbols
- _punctuation_symbols = Set(r', ; . !'.split())
+ _punctuation_symbols = Set(r', ; . ! \ldotp \cdotp'.split())
def __init__(self):
# All forward declarations are here
@@ -1769,15 +1762,14 @@
symbol = Regex("(" + ")|(".join(
[
- r"\\(?!right)(?!left)[a-zA-Z0-9]+(?!{)",
+ r"\\(?!left[^a-z])(?!right[^a-z])[a-zA-Z0-9]+(?!{)",
r"[a-zA-Z0-9 ]",
r"[+\-*/]",
r"[<>=]",
r"[:,.;!]",
r"[!@%&]",
r"[[\]()]",
- r"\\\$",
- r"\\\%"
+ r"\\[$%{}]",
])
+ ")"
).setParseAction(self.symbol).leaveWhitespace()
@@ -1828,7 +1820,7 @@
)
subsuper << Group(
- ( placeable
+ ( Optional(placeable)
+ OneOrMore(
subsuperop
+ placeable
@@ -1837,7 +1829,9 @@
| placeable
)
- ambiDelim = oneOf(r"| \| / \backslash \uparrow \downarrow \updownarrow \Uparrow \Downarrow \Updownarrow")
+ ambiDelim = oneOf(r"""| \| / \backslash \uparrow \downarrow
+ \updownarrow \Uparrow \Downarrow
+ \Updownarrow""")
leftDelim = oneOf(r"( [ { \lfloor \langle \lceil")
rightDelim = oneOf(r") ] } \rfloot \rangle \rceil")
@@ -1861,9 +1855,9 @@
non_math = Regex(r"(?:[^$]|(?:\\\$))*"
).setParseAction(self.non_math).setName("non_math").leaveWhitespace()
- self._expression <<(
+ self._expression <<(
non_math
- + ZeroOrMore(
+ + OneOrMore(
Suppress(math_delim)
+ math
+ Suppress(math_delim)
@@ -1908,6 +1902,7 @@
return [self._expr]
def math(self, s, loc, toks):
+ #~ print "math", toks
hlist = Hlist(toks)
self.pop_state()
return [hlist]
@@ -2164,6 +2159,7 @@
return [hlist]
def auto_sized_delimiter(self, s, loc, toks):
+ #~ print "auto_sized_delimiter", toks
front, middle, back = toks
state = self.get_state()
height = max([x.height for x in middle])
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2007-07-25 20:19:29
|
Revision: 3614
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3614&view=rev
Author: mdboom
Date: 2007-07-25 13:19:25 -0700 (Wed, 25 Jul 2007)
Log Message:
-----------
Support auto-sized delimiters (e.g. \left(\frac{3}{2}\right)).
Commit mathtext_examples.py
Modified Paths:
--------------
branches/mathtext_mgd/lib/matplotlib/mathtext.py
Added Paths:
-----------
branches/mathtext_mgd/examples/mathtext_examples.py
Added: branches/mathtext_mgd/examples/mathtext_examples.py
===================================================================
--- branches/mathtext_mgd/examples/mathtext_examples.py (rev 0)
+++ branches/mathtext_mgd/examples/mathtext_examples.py 2007-07-25 20:19:25 UTC (rev 3614)
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+import os, sys
+
+stests = [
+ r'Kerning: AVA $AVA$',
+ r'$x y$',
+ r'$x+y\ x=y\ x<y\ x:y\ x,y\ x@y$',
+ r'$100\%y\ x*y\ x/y x\$y$',
+ r'$x\leftarrow y\ x\forall y$',
+ r'$x \sf x \bf x {\cal X} \rm x$',
+ r'$\{ \rm braces \}$',
+ r'$\left[\left\lfloor\frac{5}{\frac{3}{4}} y\right)\right]$',
+ r'$\left(x\right)$',
+ r'$\sin(x)$',
+ r'$x_2$',
+ r'$x^2$',
+ r'$x^2_y$',
+ r'$x_y^2$',
+ r'$\prod_{i=\alpha_{i+1}}^\infty$',
+ r'$x = \frac{x+\frac{5}{2}}{\frac{y+3}{8}}$',
+ r'$dz/dt \/ = \/ \gamma x^2 \/ + \/ {\rm sin}(2\pi y+\phi)$',
+ r'Foo: $\alpha_{i+1}^j \/ = \/ {\rm sin}(2\pi f_j t_i) e^{-5 t_i/\tau}$',
+ r'$\mathcal{R}\prod_{i=\alpha_{i+1}}^\infty a_i \sin(2 \pi f x_i)$',
+# r'$\bigodot \bigoplus {\sf R} a_i{\rm sin}(2 \pi f x_i)$',
+ r'Variable $i$ is good',
+ r'$\Delta_i^j$',
+ r'$\Delta^j_{i+1}$',
+ r'$\ddot{o}\acute{e}\grave{e}\hat{O}\breve{\imath}\tilde{n}\vec{q}$',
+ r'$_i$',
+ r"$\arccos((x^i))$",
+ r"$\gamma = \frac{x=\frac{6}{8}}{y} \delta$",
+ r'$\"o\ddot o \'e\`e\~n\.x\^y$',
+
+ ]
+
+from pylab import *
+
+if '--latex' in sys.argv:
+ fd = open("mathtext_examples.ltx", "w")
+ fd.write("\\documentclass{article}\n")
+ fd.write("\\begin{document}\n")
+ fd.write("\\begin{enumerate}\n")
+
+ for i, s in enumerate(stests):
+ fd.write("\\item %s\n" % s)
+
+ fd.write("\\end{enumerate}\n")
+ fd.write("\\end{document}\n")
+ fd.close()
+
+ os.system("pdflatex mathtext_examples.ltx")
+else:
+ for i, s in enumerate(stests):
+ print s
+ plot([1,2,3], 'r')
+ x = arange(0.0, 3.0, 0.1)
+
+ grid(True)
+ text(1, 1.6, s, fontsize=20)
+
+ savefig('mathtext_example%02d' % i)
+ figure()
+
Property changes on: branches/mathtext_mgd/examples/mathtext_examples.py
___________________________________________________________________
Name: svn:executable
+ *
Modified: branches/mathtext_mgd/lib/matplotlib/mathtext.py
===================================================================
--- branches/mathtext_mgd/lib/matplotlib/mathtext.py 2007-07-25 16:17:22 UTC (rev 3613)
+++ branches/mathtext_mgd/lib/matplotlib/mathtext.py 2007-07-25 20:19:25 UTC (rev 3614)
@@ -739,12 +739,6 @@
Use the Bakoma postscript fonts for rendering to backend_ps
"""
- def _get_offset(self, basename, cached_font, glyph, fontsize, dpi):
- head = cached_font.font.get_sfnt_table("head")
- if basename.lower() == 'cmex10':
- return -(head['yMin']+512)/head['unitsPerEm']*10.
- return 0.
-
def set_canvas_size(self, w, h, pswriter):
'Dimension the drawing canvas; may be a noop'
self.width = w
@@ -756,7 +750,7 @@
self._get_info(font, sym, fontsize, dpi)
oy = self.height - oy
if basename.lower() == 'cmex10':
- oy += offset - 512/2048.*10.
+ oy += offset
ps = """/%(basename)s findfont
%(fontsize)s scalefont
@@ -1067,7 +1061,7 @@
self._update_metrics()
def __internal_repr__(self):
- return repr(self.c)
+ return '`%s`' % self.c
def _update_metrics(self):
metrics = self._metrics = self.font_output.get_metrics(
@@ -1097,7 +1091,7 @@
if self.size < NUM_SIZE_LEVELS:
self.fontsize *= SHRINK_FACTOR
self._update_metrics()
-
+
class Accent(Char):
"""The font metrics need to be dealt with differently for accents, since they
are already offset correctly from the baseline in TrueType fonts."""
@@ -1305,7 +1299,7 @@
p = self.list_head
while p is not None:
if isinstance(p, Char):
- raise RuntimeError("Internal error in mathtext")
+ raise RuntimeError("Internal mathtext error: Char node found in Vlist.")
elif isinstance(p, Box):
x += d + p.height
d = p.depth
@@ -1504,6 +1498,19 @@
self.super = None
Hlist.__init__(self, [])
+class AutoSizedDelim(Hlist):
+ def __init__(self, c, height, depth, state):
+ char = Char(c, state)
+ shift = 0.
+ if char.height + char.depth < height + depth:
+ factor = (height + depth) / (char.height + char.depth)
+ fontsize = char.fontsize * factor
+ state = state.copy()
+ state.fontsize = fontsize
+ char = Char(c, state)
+ shift = (depth - char.depth)
+ Hlist.__init__(self, [char])
+ self.shift_amount = shift
class Ship(object):
"""Once the boxes have been set up, this sends them to output.
@@ -1612,7 +1619,7 @@
while p:
if isinstance(p, Char):
- raise RuntimeError("Internal error in mathtext")
+ raise RuntimeError("Internal mathtext error: Char node found in vlist")
elif isinstance(p, List):
if p.list_head is None:
self.cur_v += p.height + p.depth
@@ -1663,7 +1670,7 @@
##############################################################################
# PARSER
-class Parser:
+class Parser(object):
_binary_operators = Set(r'''
+ - *
\pm \sqcap \rhd
@@ -1707,7 +1714,7 @@
_spaced_symbols = _binary_operators | _relation_symbols | _arrow_symbols
- _delimiter_symbols = Set(r', ; . !'.split())
+ _punctuation_symbols = Set(r', ; . !'.split())
def __init__(self):
# All forward declarations are here
@@ -1716,6 +1723,7 @@
subsuper = Forward().setParseAction(self.subsuperscript).setName("subsuper")
placeable = Forward().setName("placeable")
simple = Forward().setName("simple")
+ autoDelim = Forward().setParseAction(self.auto_sized_delimiter)
self._expression = Forward().setParseAction(self.finish).setName("finish")
lbrace = Literal('{').suppress()
@@ -1724,42 +1732,9 @@
start_group.setParseAction(self.start_group)
end_group = rbrace
end_group.setParseAction(self.end_group)
- lbrack = Literal('[')
- rbrack = Literal(']')
- lparen = Literal('(')
- rparen = Literal(')')
- grouping =(lbrack
- | rbrack
- | lparen
- | rparen)
bslash = Literal('\\')
- langle = Literal('<')
- rangle = Literal('>')
- equals = Literal('=')
- relation =(langle
- | rangle
- | equals)
-
- colon = Literal(':')
- comma = Literal(',')
- period = Literal('.')
- semicolon = Literal(';')
- exclamation = Literal('!')
- punctuation =(colon
- | comma
- | period
- | semicolon)
-
- at = Literal('@')
- percent = Literal('%')
- ampersand = Literal('&')
- misc =(exclamation
- | at
- | percent
- | ampersand)
-
accent = oneOf("hat check dot breve acute ddot grave tilde bar vec "
"\" ` ' ~ . ^")
@@ -1794,7 +1769,7 @@
symbol = Regex("(" + ")|(".join(
[
- r"\\[a-zA-Z0-9]+(?!{)",
+ r"\\(?!right)(?!left)[a-zA-Z0-9]+(?!{)",
r"[a-zA-Z0-9 ]",
r"[+\-*/]",
r"[<>=]",
@@ -1845,7 +1820,8 @@
simple <<(space
| font
- | subsuper)
+ | subsuper
+ )
subsuperop =(Literal("_")
| Literal("^")
@@ -1861,8 +1837,22 @@
| placeable
)
+ ambiDelim = oneOf(r"| \| / \backslash \uparrow \downarrow \updownarrow \Uparrow \Downarrow \Updownarrow")
+ leftDelim = oneOf(r"( [ { \lfloor \langle \lceil")
+ rightDelim = oneOf(r") ] } \rfloot \rangle \rceil")
+
+ autoDelim <<(Suppress(Literal(r"\left"))
+ + (leftDelim | ambiDelim)
+ + Group(
+ autoDelim
+ ^ OneOrMore(simple))
+ + Suppress(Literal(r"\right"))
+ + (rightDelim | ambiDelim)
+ )
+
math = OneOrMore(
- simple
+ autoDelim
+ | simple
).setParseAction(self.math).setName("math")
math_delim =(~bslash
@@ -1955,7 +1945,7 @@
return [Hlist([self._make_space(0.3),
Char(c, self.get_state()),
self._make_space(0.3)])]
- elif c in self._delimiter_symbols:
+ elif c in self._punctuation_symbols:
return [Hlist([Char(c, self.get_state()),
self._make_space(0.3)])]
return [Char(toks[0], self.get_state())]
@@ -2173,8 +2163,17 @@
hlist = Hlist([vlist, FixedGlue(thickness * 2.)])
return [hlist]
+ def auto_sized_delimiter(self, s, loc, toks):
+ front, middle, back = toks
+ state = self.get_state()
+ height = max([x.height for x in middle])
+ depth = max([x.depth for x in middle])
+ hlist = Hlist(
+ [AutoSizedDelim(front, height, depth, state)] +
+ middle.asList() +
+ [AutoSizedDelim(back, height, depth, state)])
+ return hlist
-
####
##############################################################################
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jd...@us...> - 2007-07-25 16:17:27
|
Revision: 3613
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3613&view=rev
Author: jdh2358
Date: 2007-07-25 09:17:22 -0700 (Wed, 25 Jul 2007)
Log Message:
-----------
rewrote mathext demo to use pythonic api
Modified Paths:
--------------
branches/mathtext_mgd/examples/mathtext_demo.py
Modified: branches/mathtext_mgd/examples/mathtext_demo.py
===================================================================
--- branches/mathtext_mgd/examples/mathtext_demo.py 2007-07-25 15:34:52 UTC (rev 3612)
+++ branches/mathtext_mgd/examples/mathtext_demo.py 2007-07-25 16:17:22 UTC (rev 3613)
@@ -1,27 +1,26 @@
#!/usr/bin/env python
"""
-
-In order to use mathtext, you must build matplotlib.ft2font. This is
-built by default in the windows installer.
-
-For other platforms, edit setup.py and set
-
-BUILD_FT2FONT = True
-
+Use matplotlib's internal LaTex parser and layout engine. For true
+latex rendering, see the text.usetex option
"""
-from pylab import *
-subplot(111, axisbg='y')
-plot([1,2,3], 'r')
-x = arange(0.0, 3.0, 0.1)
+import numpy as npy
+from pylab import figure, show
+fig = figure()
+fig.subplots_adjust(bottom=0.2)
-grid(True)
-xlabel(r'$\Delta_i^j$', fontsize=20)
-ylabel(r'$\Delta_{i+1}^j$', fontsize=20)
+ax = fig.add_subplot(111, axisbg='y')
+ax.plot([1,2,3], 'r')
+x = npy.arange(0.0, 3.0, 0.1)
+
+ax.grid(True)
+ax.set_xlabel(r'$\Delta_i^j$', fontsize=20)
+ax.set_ylabel(r'$\Delta_{i+1}^j$', fontsize=20)
tex = r'$\mathcal{R}\prod_{i=\alpha_{i+1}}^\infty a_i\sin(2 \pi f x_i)$'
-text(1, 1.6, tex, fontsize=20, va='bottom')
+ax.text(1, 1.6, tex, fontsize=20, va='bottom')
+
#title(r'$\Delta_i^j \hspace{0.4} \rm{versus} \hspace{0.4} \Delta_{i+1}^j$', fontsize=20)
-savefig('mathtext_demo')
+fig.savefig('mathtext_demo')
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <md...@us...> - 2007-07-25 15:40:14
|
Revision: 3612
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3612&view=rev
Author: mdboom
Date: 2007-07-25 08:34:52 -0700 (Wed, 25 Jul 2007)
Log Message:
-----------
Fix for get_xheight/get_underline_thickness. Update examples to use
new math syntax.
Modified Paths:
--------------
branches/mathtext_mgd/examples/mathtext_demo.py
branches/mathtext_mgd/lib/matplotlib/mathtext.py
Modified: branches/mathtext_mgd/examples/mathtext_demo.py
===================================================================
--- branches/mathtext_mgd/examples/mathtext_demo.py 2007-07-25 14:43:13 UTC (rev 3611)
+++ branches/mathtext_mgd/examples/mathtext_demo.py 2007-07-25 15:34:52 UTC (rev 3612)
@@ -17,8 +17,8 @@
grid(True)
xlabel(r'$\Delta_i^j$', fontsize=20)
ylabel(r'$\Delta_{i+1}^j$', fontsize=20)
-tex = r'$\cal{R}\prod_{i=\alpha_{i+1}}^\infty a_i\rm{sin}(2 \pi f x_i)$'
-text(1, 1.6, tex, fontsize=20)
+tex = r'$\mathcal{R}\prod_{i=\alpha_{i+1}}^\infty a_i\sin(2 \pi f x_i)$'
+text(1, 1.6, tex, fontsize=20, va='bottom')
#title(r'$\Delta_i^j \hspace{0.4} \rm{versus} \hspace{0.4} \Delta_{i+1}^j$', fontsize=20)
savefig('mathtext_demo')
Modified: branches/mathtext_mgd/lib/matplotlib/mathtext.py
===================================================================
--- branches/mathtext_mgd/lib/matplotlib/mathtext.py 2007-07-25 14:43:13 UTC (rev 3611)
+++ branches/mathtext_mgd/lib/matplotlib/mathtext.py 2007-07-25 15:34:52 UTC (rev 3612)
@@ -699,7 +699,6 @@
basename, font, metrics, symbol_name, num, glyph, offset = \
self._get_info(font, sym, fontsize, dpi)
- font.draw_rect(0, 0, self.width - 1, self.height - 1)
font.draw_glyph_to_bitmap(
int(ox), int(oy - metrics.ymax), glyph)
@@ -711,16 +710,16 @@
def get_used_characters(self):
return self.used_characters
- def get_xheight(self, font, fontsize):
+ def get_xheight(self, font, fontsize, dpi):
basename, cached_font = self._get_font(font)
- cached_font.font.set_size(fontsize)
+ cached_font.font.set_size(fontsize, dpi)
pclt = cached_font.font.get_sfnt_table('pclt')
xHeight = pclt['xHeight'] / 64.0
return xHeight
- def get_underline_thickness(self, font, fontsize):
+ def get_underline_thickness(self, font, fontsize, dpi):
basename, cached_font = self._get_font(font)
- cached_font.font.set_size(fontsize)
+ cached_font.font.set_size(fontsize, dpi)
return max(1.0, cached_font.font.underline_thickness / 64.0)
def get_kern(self, fontleft, symleft, fontsizeleft,
@@ -944,11 +943,11 @@
ps = "%f %f %f %f rectfill" % (x1, self.height - y2, x2 - x1, y2 - y1)
self.pswriter.write(ps)
- def get_xheight(self, font, fontsize):
+ def get_xheight(self, font, fontsize, dpi):
basename, cached_font = self._get_font(font)
return cached_font.get_xheight() * 0.001 * fontsize
- def get_underline_thickness(self, font, fontsize):
+ def get_underline_thickness(self, font, fontsize, dpi):
basename, cached_font = self._get_font(font)
return cached_font.get_underline_thickness() * 0.001 * fontsize
@@ -1367,7 +1366,7 @@
"""Convenience class to create a horizontal rule."""
def __init__(self, state):
thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize)
+ state.font, state.fontsize, state.dpi)
height = depth = thickness * 0.5
Rule.__init__(self, None, height, depth, state)
@@ -1375,7 +1374,7 @@
"""Convenience class to create a vertical rule."""
def __init__(self, state):
thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize)
+ state.font, state.fontsize, state.dpi)
Rule.__init__(self, thickness, None, None, state)
class Glue(Node):
@@ -1950,6 +1949,7 @@
return [box]
def symbol(self, s, loc, toks):
+ # print "symbol", toks
c = toks[0]
if c in self._spaced_symbols:
return [Hlist([self._make_space(0.3),
@@ -1982,7 +1982,7 @@
assert(len(toks)==1)
state = self.get_state()
thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize)
+ state.font, state.fontsize, state.dpi)
accent, sym = toks[0]
accent = Accent(self._accent_map[accent], self.get_state())
centered = HCentered([accent])
@@ -2067,11 +2067,12 @@
sub = next2
else:
raise ParseFatalException("Subscript/superscript string is too long.")
-
+
state = self.get_state()
rule_thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize)
- xHeight = state.font_output.get_xheight(state.font, state.fontsize)
+ state.font, state.fontsize, state.dpi)
+ xHeight = state.font_output.get_xheight(
+ state.font, state.fontsize, state.dpi)
if self.is_overunder(nucleus):
vlist = []
@@ -2155,7 +2156,7 @@
cden.hpack(width, 'exactly')
state = self.get_state()
thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize)
+ state.font, state.fontsize, state.dpi)
space = thickness * 3.0
vlist = Vlist([cnum,
FixedGlue(thickness * 2.0),
@@ -2243,7 +2244,7 @@
pswriter = list()
font_output.set_canvas_size(w, h, pswriter)
ship(2, 2, box)
-
+
if self.output == 'SVG':
# The empty list at the end is for lines
svg_elements = Bunch(svg_glyphs=font_output.svg_glyphs,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|