Skip to content

Commit 5f22822

Browse files
committed
AxesGrid: implemented axisline style
svn path=/trunk/matplotlib/; revision=7721
1 parent d634fc9 commit 5f22822

File tree

4 files changed

+231
-8
lines changed

4 files changed

+231
-8
lines changed

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2009-09-07 AxesGrid : implemented axisline style.
2+
Added a demo examples/axes_grid/demo_axisline_style.py- JJL
3+
14
2009-09-04 Make the textpath class as a separate moduel
25
(textpath.py). Add support for mathtext and tex.- JJL
36

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
from mpl_toolkits.axes_grid.axislines import SubplotZero
3+
import matplotlib.pyplot as plt
4+
import numpy as np
5+
6+
if __name__ == "__main__":
7+
fig = plt.figure(1)
8+
ax = SubplotZero(fig, 111)
9+
fig.add_subplot(ax)
10+
11+
for direction in ["xzero", "yzero"]:
12+
ax.axis[direction].set_axisline_style("->")
13+
ax.axis[direction].set_visible(True)
14+
15+
for direction in ["left", "right", "bottom", "top"]:
16+
ax.axis[direction].set_visible(False)
17+
18+
x = np.linspace(-0.5, 1., 100)
19+
ax.plot(x, np.sin(x*np.pi))
20+
21+
plt.show()
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
from matplotlib.patches import _Style, FancyArrowPatch
2+
from matplotlib.transforms import IdentityTransform
3+
from matplotlib.path import Path
4+
import numpy as np
5+
6+
class AxislineStyle(_Style):
7+
"""
8+
:class:`AxislineStyle` is a container class which defines style classes
9+
for AxisArtists.
10+
11+
An instance of any axisline style class is an callable object,
12+
whose call signature is ::
13+
14+
__call__(self, axis_artist, path, transform)
15+
16+
When called, this should return a mpl artist with following
17+
methods implemented. ::
18+
19+
def set_path(self, path):
20+
# set the path for axisline.
21+
22+
def set_line_mutation_scale(self, scale):
23+
# set the scale
24+
25+
def draw(self, renderer):
26+
# draw
27+
28+
29+
"""
30+
31+
_style_list = {}
32+
33+
34+
class _Base(object):
35+
# The derived classes are required to be able to be initialized
36+
# w/o arguments, i.e., all its argument (except self) must have
37+
# the default values.
38+
39+
def __init__(self):
40+
"""
41+
initializtion.
42+
"""
43+
super(AxislineStyle._Base, self).__init__()
44+
45+
46+
47+
48+
def __call__(self, axis_artist, transform):
49+
"""
50+
Given the AxisArtist instance, and transform for the path
51+
(set_path method), return the mpl artist for drawing the axis line.
52+
"""
53+
54+
return self.new_line(axis_artist, transform)
55+
56+
57+
class SimpleArrow(_Base):
58+
"""
59+
A simple arrow.
60+
"""
61+
62+
63+
class ArrowAxisline(FancyArrowPatch):
64+
"""
65+
The artist class that will be returend for SimpleArrow style.
66+
"""
67+
def __init__(self, axis_artist, line_path, transform,
68+
line_mutation_scale):
69+
self._axis_artist = axis_artist
70+
self._line_transform = transform
71+
self._line_path = line_path
72+
self._line_mutation_scale = line_mutation_scale
73+
74+
FancyArrowPatch.__init__(self,
75+
path=self._line_path,
76+
arrowstyle="->",
77+
arrow_transmuter=None,
78+
patchA=None,
79+
patchB=None,
80+
shrinkA=0.,
81+
shrinkB=0.,
82+
mutation_scale=line_mutation_scale,
83+
mutation_aspect=None,
84+
transform=IdentityTransform(),
85+
)
86+
87+
def set_line_mutation_scale(self, scale):
88+
self.set_mutation_scale(scale*self._line_mutation_scale)
89+
90+
def _extend_path(self, path, mutation_size=10):
91+
"""
92+
Extend the path to make a room for drawing arrow.
93+
"""
94+
from matplotlib.bezier import get_cos_sin
95+
96+
x0, y0 = path.vertices[-2]
97+
x1, y1 = path.vertices[-1]
98+
cost, sint = get_cos_sin(x0, y0, x1, y1)
99+
100+
d = mutation_size * 1.
101+
x2, y2 = x1 + cost*d, y1+sint*d
102+
103+
if path.codes is None:
104+
_path = Path(np.concatenate([path.vertices, [[x2, y2]]]))
105+
else:
106+
_path = Path(np.concatenate([path.vertices, [[x2, y2]]]),
107+
np.concatenate([path.codes, [Path.LINETO]]))
108+
109+
return _path
110+
111+
def set_path(self, path):
112+
self._line_path = path
113+
114+
def draw(self, renderer):
115+
"""
116+
Draw the axis line.
117+
1) transform the path to the display cooridnate.
118+
2) extend the path to make a room for arrow
119+
3) update the path of the FancyArrowPatch.
120+
4) draw
121+
"""
122+
path_in_disp = self._line_transform.transform_path(self._line_path)
123+
mutation_size = self.get_mutation_scale() #line_mutation_scale()
124+
extented_path = self._extend_path(path_in_disp,
125+
mutation_size=mutation_size)
126+
127+
self._path_original = extented_path
128+
FancyArrowPatch.draw(self, renderer)
129+
130+
131+
def __init__(self, size=1):
132+
"""
133+
*size*
134+
size of the arrow as a fraction of the ticklabel size.
135+
"""
136+
137+
self.size = size
138+
super(AxislineStyle.SimpleArrow, self).__init__()
139+
140+
def new_line(self, axis_artist, transform):
141+
142+
linepath = Path([(0,0), (0, 1)])
143+
axisline = self.ArrowAxisline(axis_artist, linepath, transform,
144+
line_mutation_scale=self.size)
145+
return axisline
146+
147+
148+
_style_list["->"] = SimpleArrow

lib/mpl_toolkits/axes_grid/axislines.py

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363

6464

6565
import matplotlib.lines as mlines
66-
66+
from axisline_style import AxislineStyle
6767

6868

6969
class BezierPath(mlines.Line2D):
@@ -184,6 +184,8 @@ def __init__(self, label_direction):
184184
"""
185185
self.label_direction = label_direction
186186

187+
self.delta1, self.delta2 = 0.00001, 0.00001
188+
187189
def update_lim(self, axes):
188190
pass
189191

@@ -463,8 +465,8 @@ def _f(locs, labels):
463465

464466
# check if the tick point is inside axes
465467
c2 = tr2ax.transform_point(c)
466-
delta=0.00001
467-
if 0. -delta<= c2[self.nth_coord] <= 1.+delta:
468+
#delta=0.00001
469+
if 0. -self.delta1<= c2[self.nth_coord] <= 1.+self.delta2:
468470
yield c, angle, l
469471

470472
return _f(majorLocs, majorLabels), _f(minorLocs, minorLabels)
@@ -551,7 +553,8 @@ def _f(locs, labels):
551553
c[self.nth_coord] = x
552554
c1, c2 = tr2ax.transform_point(c)
553555
if 0. <= c1 <= 1. and 0. <= c2 <= 1.:
554-
yield c, angle, l
556+
if 0. - self.delta1 <= [c1, c2][self.nth_coord] <= 1. + self.delta2:
557+
yield c, angle, l
555558

556559
return _f(majorLocs, majorLabels), _f(minorLocs, minorLabels)
557560

@@ -964,6 +967,8 @@ def __init__(self, axes,
964967
if minor_tick_pad is None:
965968
self.minor_tick_pad = rcParams['%s.minor.pad'%axis_name]
966969

970+
self._axisline_style = None
971+
967972
self._init_line()
968973
self._init_ticks()
969974
self._init_offsetText(self._axis_artist_helper.label_direction)
@@ -973,6 +978,7 @@ def __init__(self, axes,
973978

974979
self._rotate_label_along_line = False
975980

981+
976982
def set_rotate_label_along_line(self, b):
977983
self._rotate_label_along_line = b
978984

@@ -986,16 +992,61 @@ def get_helper(self):
986992
return self._axis_artist_helper
987993

988994

995+
def set_axisline_style(self, axisline_style=None, **kw):
996+
"""
997+
Set the axisline style.
998+
999+
*axislin_style* can be a string with axisline style name with optional
1000+
comma-separated attributes. Alternatively, the attrs can
1001+
be provided as keywords.
1002+
1003+
set_arrowstyle("->,size=1.5")
1004+
set_arrowstyle("->", size=1.5)
1005+
1006+
Old attrs simply are forgotten.
1007+
1008+
Without argument (or with arrowstyle=None), return
1009+
available styles as a list of strings.
1010+
"""
1011+
1012+
if axisline_style==None:
1013+
return AxislineStyle.pprint_styles()
1014+
1015+
if isinstance(axisline_style, AxislineStyle._Base):
1016+
self._axisline_style = axisline_style
1017+
else:
1018+
self._axisline_style = AxislineStyle(axisline_style, **kw)
1019+
1020+
1021+
self._init_line()
1022+
1023+
1024+
def get_axisline_style(self):
1025+
"""
1026+
return the current axisline style.
1027+
"""
1028+
return self._axisline_style
1029+
9891030
def _init_line(self):
1031+
"""
1032+
Initialize the *line* artist that is responsible to draw the axis line.
1033+
"""
9901034
tran = self._axis_artist_helper.get_line_transform(self.axes) \
9911035
+ self.offset_transform
992-
self.line = BezierPath(self._axis_artist_helper.get_line(self.axes),
993-
color=rcParams['axes.edgecolor'],
994-
linewidth=rcParams['axes.linewidth'],
995-
transform=tran)
1036+
1037+
axisline_style = self.get_axisline_style()
1038+
if axisline_style is None:
1039+
self.line = BezierPath(self._axis_artist_helper.get_line(self.axes),
1040+
color=rcParams['axes.edgecolor'],
1041+
linewidth=rcParams['axes.linewidth'],
1042+
transform=tran)
1043+
else:
1044+
self.line = axisline_style(self, transform=tran)
9961045

9971046
def _draw_line(self, renderer):
9981047
self.line.set_path(self._axis_artist_helper.get_line(self.axes))
1048+
if self.get_axisline_style() is not None:
1049+
self.line.set_line_mutation_scale(self.major_ticklabels.get_size())
9991050
self.line.draw(renderer)
10001051

10011052

0 commit comments

Comments
 (0)