Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3df8dd1

Browse files
committed
Add support for mathtext markers (thanks to tcb for original work)
svn path=/trunk/matplotlib/; revision=8059
1 parent 7851aac commit 3df8dd1

6 files changed

Lines changed: 97 additions & 37 deletions

File tree

CHANGELOG

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2009-12-31 Add support for using math text as marker symbols (Thanks to tcb)
2+
- MGD
3+
14
2009-12-31 Commit a workaround for a regression in PyQt4-4.6.{0,1} - DSD
25

36
2009-12-22 Fix cmap data for gist_earth_r, etc. -JJL
@@ -20,7 +23,7 @@
2023
Added new examples. - JJL
2124

2225
2009-12-01 Applied Laurent Dufrechou's patch to improve blitting with
23-
the qt4 backend - DSD
26+
the qt4 backend - DSD
2427

2528
2009-11-13 The pdf backend now allows changing the contents of
2629
a pdf file's information dictionary via PdfPages.infodict. - JKS
@@ -153,35 +156,35 @@
153156

154157
2009-08-06 Tagging the 0.99.0 release at svn r7397 - JDH
155158

156-
* fixed an alpha colormapping bug posted on sf 2832575
159+
* fixed an alpha colormapping bug posted on sf 2832575
157160

158-
* fix typo in axes_divider.py. use nanmin, nanmax in angle_helper.py
161+
* fix typo in axes_divider.py. use nanmin, nanmax in angle_helper.py
159162
(patch by Christoph Gohlke)
160163

161-
* remove dup gui event in enter/leave events in gtk
164+
* remove dup gui event in enter/leave events in gtk
162165

163-
* lots of fixes for os x binaries (Thanks Russell Owen)
166+
* lots of fixes for os x binaries (Thanks Russell Owen)
164167

165-
* attach gtk events to mpl events -- fixes sf bug 2816580
168+
* attach gtk events to mpl events -- fixes sf bug 2816580
166169

167-
* applied sf patch 2815064 (middle button events for wx) and
170+
* applied sf patch 2815064 (middle button events for wx) and
168171
patch 2818092 (resize events for wx)
169172

170-
* fixed boilerplate.py so it doesn't break the ReST docs.
173+
* fixed boilerplate.py so it doesn't break the ReST docs.
171174

172-
* removed a couple of cases of mlab.load
175+
* removed a couple of cases of mlab.load
173176

174-
* fixed rec2csv win32 file handle bug from sf patch 2831018
177+
* fixed rec2csv win32 file handle bug from sf patch 2831018
175178

176-
* added two examples from Josh Hemann: examples/pylab_examples/barchart_demo2.py
179+
* added two examples from Josh Hemann: examples/pylab_examples/barchart_demo2.py
177180
and examples/pylab_examples/boxplot_demo2.py
178181

179-
* handled sf bugs 2831556 and 2830525; better bar error messages and
182+
* handled sf bugs 2831556 and 2830525; better bar error messages and
180183
backend driver configs
181184

182-
* added miktex win32 patch from sf patch 2820194
185+
* added miktex win32 patch from sf patch 2820194
183186

184-
* apply sf patches 2830233 and 2823885 for osx setup and 64 bit; thanks Michiel
187+
* apply sf patches 2830233 and 2823885 for osx setup and 64 bit; thanks Michiel
185188

186189
2009-08-04 Made cbook.get_sample_data make use of the ETag and Last-Modified
187190
headers of mod_dav_svn. - JKS

examples/pylab_examples/line_styles.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,28 @@
1717
except TypeError:
1818
pass
1919

20-
styles = linestyles + markers
20+
styles = markers + [
21+
r'$\lambda$',
22+
r'$\bowtie$',
23+
r'$\circlearrowleft$',
24+
r'$\clubsuit$',
25+
r'$\checkmark$']
2126

2227
colors = ('b', 'g', 'r', 'c', 'm', 'y', 'k')
2328

29+
plt.figure(figsize=(8,8))
2430

2531
axisNum = 0
26-
for row in range(5):
32+
for row in range(6):
2733
for col in range(5):
2834
axisNum += 1
29-
ax = plt.subplot(5, 5, axisNum)
30-
style = styles[axisNum % len(styles) ]
31-
color = colors[axisNum % len(colors) ]
32-
plt.plot(t,s, style + color, markersize=10)
35+
ax = plt.subplot(6, 5, axisNum)
36+
color = colors[axisNum % len(colors)]
37+
if axisNum < len(linestyles):
38+
plt.plot(t, s, linestyles[axisNum], color=color, markersize=10)
39+
else:
40+
style = styles[(axisNum - len(linestyles)) % len(styles)]
41+
plt.plot(t, s, linestyle='None', marker=style, color=color, markersize=10)
3342
ax.set_yticklabels([])
3443
ax.set_xticklabels([])
3544

lib/matplotlib/cbook.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,6 +1676,15 @@ def __call__(self, key):
16761676
else:
16771677
break
16781678

1679+
def is_math_text(s):
1680+
# Did we find an even number of non-escaped dollar signs?
1681+
# If so, treat is as math text.
1682+
s = unicode(s)
1683+
1684+
dollar_count = s.count(r'$') - s.count(r'\$')
1685+
even_dollars = (dollar_count > 0 and dollar_count % 2 == 0)
1686+
1687+
return even_dollars
16791688

16801689

16811690
if __name__=='__main__':

lib/matplotlib/lines.py

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@
1212
import artist
1313
from artist import Artist
1414
from cbook import iterable, is_string_like, is_numlike, ls_mapper, dedent,\
15-
flatten
15+
flatten, is_math_text
1616
from colors import colorConverter
1717
from path import Path
1818
from transforms import Affine2D, Bbox, TransformedPath, IdentityTransform
1919

2020
from matplotlib import rcParams
2121
from artist import allow_rasterization
2222
from matplotlib import docstring
23+
from matplotlib.font_manager import FontProperties
2324

2425
# special-purpose marker identifiers:
2526
(TICKLEFT, TICKRIGHT, TICKUP, TICKDOWN,
@@ -139,7 +140,7 @@ class Line2D(Artist):
139140
}
140141

141142
filled_markers = ('o', '^', 'v', '<', '>',
142-
's', 'd', 'D', 'h', 'H', 'p', '*')
143+
's', 'd', 'D', 'h', 'H', 'p', '*')
143144

144145
zorder = 2
145146
validCap = ('butt', 'round', 'projecting')
@@ -535,7 +536,7 @@ def draw(self, renderer):
535536
gc.set_foreground(self.get_markeredgecolor())
536537
gc.set_linewidth(self._markeredgewidth)
537538
gc.set_alpha(self._alpha)
538-
funcname = self._markers.get(self._marker, '_draw_nothing')
539+
funcname = self._markerFunc
539540
if funcname != '_draw_nothing':
540541
tpath, affine = self._transformed_path.get_transformed_points_and_affine()
541542
if len(tpath.vertices):
@@ -573,7 +574,8 @@ def get_marker(self): return self._marker
573574
def get_markeredgecolor(self):
574575
if (is_string_like(self._markeredgecolor) and
575576
self._markeredgecolor == 'auto'):
576-
if self._marker in self.filled_markers:
577+
if (self._marker in self.filled_markers or
578+
is_math_text(self._marker)):
577579
return 'k'
578580
else:
579581
return self._color
@@ -774,6 +776,7 @@ def set_marker(self, marker):
774776
'None' nothing
775777
' ' nothing
776778
'' nothing
779+
'$...$' render the string using mathtext
777780
========== ==========================
778781
779782
@@ -782,16 +785,18 @@ def set_marker(self, marker):
782785
| '<' | '>' | 'D' | 'H' | '^' | '_' | 'd'
783786
| 'h' | 'o' | 'p' | 's' | 'v' | 'x' | '|'
784787
| TICKUP | TICKDOWN | TICKLEFT | TICKRIGHT
785-
| 'None' | ' ' | '' ]
788+
| 'None' | ' ' | '' | '$...$']
786789
787790
"""
788-
if marker not in self._markers:
791+
if marker in self._markers:
792+
self._marker = marker
793+
self._markerFunc = self._markers[marker]
794+
elif is_math_text(marker):
795+
self._marker = marker
796+
self._markerFunc = '_draw_mathtext_path'
797+
else: #already handle ' ', '' in marker list
789798
verbose.report('Unrecognized marker style %s, %s' %
790799
(marker, type(marker)))
791-
if marker in [' ','']:
792-
marker = 'None'
793-
self._marker = marker
794-
self._markerFunc = self._markers[marker]
795800

796801
def set_markeredgecolor(self, ec):
797802
"""
@@ -867,6 +872,38 @@ def set_dashes(self, seq):
867872
def _draw_lines(self, renderer, gc, path, trans):
868873
self._lineFunc(renderer, gc, path, trans)
869874

875+
def _draw_mathtext_path(self, renderer, gc, path, trans):
876+
"""
877+
Draws mathtext markers '$...$' using TextPath object.
878+
879+
Submitted by tcb
880+
"""
881+
from matplotlib.patches import PathPatch
882+
from matplotlib.text import TextPath
883+
884+
gc.set_snap(False)
885+
886+
# again, the properties could be initialised just once outside
887+
# this function
888+
# Font size is irrelevant here, it will be rescaled based on
889+
# the drawn size later
890+
props = FontProperties(size=1.0)
891+
text = TextPath(xy=(0,0), s=self.get_marker(), fontproperties=props,
892+
usetex=rcParams['text.usetex'])
893+
if len(text.vertices) == 0:
894+
return
895+
xmin, ymin = text.vertices.min(axis=0)
896+
xmax, ymax = text.vertices.max(axis=0)
897+
width = xmax - xmin
898+
height = ymax - ymin
899+
max_dim = max(width, height)
900+
path_trans = Affine2D() \
901+
.translate(0.5 * -width, 0.5 * -height) \
902+
.scale((renderer.points_to_pixels(self.get_markersize()) / max_dim))
903+
904+
rgbFace = self._get_rgb_face()
905+
renderer.draw_markers(gc, text, path_trans, path, trans, rgbFace)
906+
870907
def _draw_steps_pre(self, renderer, gc, path, trans):
871908
vertices = self._xy
872909
steps = ma.zeros((2*len(vertices)-1, 2), np.float_)
@@ -1288,6 +1325,7 @@ def update_from(self, other):
12881325

12891326
self._linestyle = other._linestyle
12901327
self._marker = other._marker
1328+
self._markerFunc = other._markerFunc
12911329
self._drawstyle = other._drawstyle
12921330

12931331

lib/matplotlib/text.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -997,13 +997,10 @@ def is_math_text(self, s):
997997
"""
998998
# Did we find an even number of non-escaped dollar signs?
999999
# If so, treat is as math text.
1000-
dollar_count = s.count(r'$') - s.count(r'\$')
1001-
even_dollars = (dollar_count > 0 and dollar_count % 2 == 0)
1002-
10031000
if rcParams['text.usetex']:
10041001
return s, 'TeX'
10051002

1006-
if even_dollars:
1003+
if cbook.is_math_text(s):
10071004
return s, True
10081005
else:
10091006
return s.replace(r'\$', '$'), False

src/_path.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -922,9 +922,13 @@ Py::Object _path_module::affine_transform(const Py::Tuple& args)
922922
vertices = (PyArrayObject*)PyArray_FromObject
923923
(vertices_obj.ptr(), PyArray_DOUBLE, 1, 2);
924924
if (!vertices ||
925-
(PyArray_NDIM(vertices) == 2 && PyArray_DIM(vertices, 1) != 2) ||
926-
(PyArray_NDIM(vertices) == 1 && PyArray_DIM(vertices, 0) != 2))
925+
(PyArray_NDIM(vertices) == 2 && PyArray_DIM(vertices, 0) != 0 &&
926+
PyArray_DIM(vertices, 1) != 2) ||
927+
(PyArray_NDIM(vertices) == 1 &&
928+
PyArray_DIM(vertices, 0) != 2 && PyArray_DIM(vertices, 0) != 0))
929+
{
927930
throw Py::ValueError("Invalid vertices array.");
931+
}
928932

929933
transform = (PyArrayObject*) PyArray_FromObject
930934
(transform_obj.ptr(), PyArray_DOUBLE, 2, 2);
@@ -979,7 +983,7 @@ Py::Object _path_module::affine_transform(const Py::Tuple& args)
979983
vertex_in += stride0;
980984
}
981985
}
982-
else
986+
else if (PyArray_DIM(vertices, 0) != 0)
983987
{
984988
char* vertex_in = PyArray_BYTES(vertices);
985989
double* vertex_out = (double*)PyArray_DATA(result);

0 commit comments

Comments
 (0)