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

Skip to content

Commit bf96ff5

Browse files
committed
POC
1 parent b58217b commit bf96ff5

File tree

1 file changed

+233
-0
lines changed

1 file changed

+233
-0
lines changed
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
import collections
2+
import numpy as np
3+
import numbers
4+
5+
import matplotlib.ticker as mticker
6+
import matplotlib.transforms as mtransforms
7+
8+
from matplotlib.axes._base import _AxesBase, _process_plot_format
9+
10+
# DUPE FROM AXES. FIXME...
11+
12+
def _make_inset_locator(rect, trans, parent):
13+
"""
14+
Helper function to locate inset axes, used in
15+
`.Axes.inset_axes_from_bounds`.
16+
17+
A locator gets used in `Axes.set_aspect` to override the default
18+
locations... It is a function that takes an axes object and
19+
a renderer and tells `set_aspect` where it is to be placed.
20+
21+
Here *rect* is a rectangle [l, b, w, h] that specifies the
22+
location for the axes in the transform given by *trans* on the
23+
*parent*.
24+
"""
25+
_rect = mtransforms.Bbox.from_bounds(*rect)
26+
_trans = trans
27+
_parent = parent
28+
29+
def inset_locator(ax, renderer):
30+
bbox = _rect
31+
bb = mtransforms.TransformedBbox(bbox, _trans)
32+
tr = _parent.figure.transFigure.inverted()
33+
bb = mtransforms.TransformedBbox(bb, tr)
34+
return bb
35+
36+
return inset_locator
37+
38+
39+
class Secondary_Xaxis(_AxesBase):
40+
"""
41+
A class to hold a Secondary_Xaxis.
42+
43+
See `~.axes._axes.Axes.secondary_xaxis` for usage.
44+
45+
"""
46+
def __init__(self, parent, location, conversion, **kwargs):
47+
self._conversion = conversion
48+
self._parent = parent
49+
50+
51+
super().__init__(self._parent.figure, [0, 1., 1, 0.0001], **kwargs)
52+
53+
self.set_location(location)
54+
55+
# styling:
56+
self.yaxis.set_major_locator(mticker.NullLocator())
57+
self.yaxis.set_ticks_position('none')
58+
self.spines['right'].set_visible(False)
59+
self.spines['left'].set_visible(False)
60+
if self._y > 0.5:
61+
self.set_axis_orientation('top')
62+
else:
63+
self.set_axis_orientation('bottom')
64+
self.set_conversion(conversion)
65+
66+
def set_axis_orientation(self, orient):
67+
"""
68+
Set if axes spine and labels are drawn at top or bottom of the
69+
axes.
70+
71+
Parameters
72+
----------
73+
orient :: string
74+
either 'top' or 'bottom'
75+
76+
"""
77+
78+
self.spines[orient].set_visible(True)
79+
if orient == 'top':
80+
self.spines['bottom'].set_visible(False)
81+
else:
82+
self.spines['top'].set_visible(False)
83+
84+
self.xaxis.set_ticks_position(orient)
85+
self.xaxis.set_label_position(orient)
86+
87+
def set_location(self, location):
88+
"""
89+
Set the vertical location of the axes in parent-normalized
90+
co-ordinates.
91+
92+
Parameters
93+
----------
94+
location : string or scalar
95+
The position to put the secondary axis. Strings can be 'top' or
96+
'bottom', scalar can be a float indicating the relative position
97+
on the parent axes to put the new axes, 0 being the bottom, and
98+
1.0 being the top.
99+
"""
100+
self._loc = location
101+
# This puts the rectangle into figure-relative coordinates.
102+
if isinstance(self._loc, str):
103+
if self._loc == 'top':
104+
y = 1.
105+
elif self._loc == 'bottom':
106+
y = 0.
107+
else:
108+
y = self._loc
109+
bounds = [0, y, 1., 1e-10]
110+
transform = self._parent.transAxes
111+
secondary_locator = _make_inset_locator(bounds,
112+
transform, self._parent)
113+
bb = secondary_locator(None, None)
114+
115+
# this locator lets the axes move if in data coordinates.
116+
# it gets called in `ax.apply_aspect() (of all places)
117+
self.set_axes_locator(secondary_locator)
118+
self._y = y
119+
120+
def set_conversion(self, conversion):
121+
"""
122+
Set how the secondary axis converts limits from the parent axes.
123+
124+
Parameters
125+
----------
126+
conversion : tuple of floats or function
127+
conversion between the parent xaxis values and the secondary xaxis
128+
values. If a tuple of floats, the floats are polynomial
129+
co-efficients, with the first entry the highest exponent's
130+
co-efficient (i.e. [2, 3, 1] is the same as
131+
``xnew = 2 x**2 + 3 * x + 1``, passed to `numpy.polyval`).
132+
If a function is specified it should accept a float as input and
133+
return a float as the result.
134+
"""
135+
136+
# make the _convert function...
137+
if callable(conversion):
138+
self._convert = conversion
139+
else:
140+
if isinstance(conversion, numbers.Number):
141+
conversion = np.asanyarray([conversion])
142+
shp = len(conversion)
143+
if shp < 2:
144+
conversion = np.array([conversion, 0.])
145+
self._convert = lambda x : np.polyval(conversion, x)
146+
147+
def draw(self, renderer=None, inframe=False):
148+
"""
149+
Draw the secondary axes.
150+
151+
Consults the parent axes for its xlimits and converts them
152+
using the converter specified by
153+
`~.axes._secondary_axes.set_conversion` (or *conversion*
154+
parameter when axes initialized.)
155+
156+
"""
157+
lims = self._parent.get_xlim()
158+
self.set_xlim(self._convert(lims))
159+
super().draw(renderer=renderer, inframe=inframe)
160+
161+
def set_xlabel(self, xlabel, fontdict=None, labelpad=None, **kwargs):
162+
"""
163+
Set the label for the secondary x-axis.
164+
165+
Parameters
166+
----------
167+
xlabel : str
168+
The label text.
169+
170+
labelpad : scalar, optional, default: None
171+
Spacing in points between the label and the x-axis.
172+
173+
Other Parameters
174+
----------------
175+
**kwargs : `.Text` properties
176+
`.Text` properties control the appearance of the label.
177+
178+
See also
179+
--------
180+
text : for information on how override and the optional args work
181+
"""
182+
if labelpad is not None:
183+
self.xaxis.labelpad = labelpad
184+
return self.xaxis.set_label_text(xlabel, fontdict, **kwargs)
185+
186+
def set_color(self, color):
187+
"""
188+
Change the color of the secondary axes and all decorators
189+
190+
Parameters
191+
----------
192+
color : Matplotlib color
193+
"""
194+
195+
self.tick_params(axis='x', colors=color)
196+
self.spines['bottom'].set_color(color)
197+
self.spines['top'].set_color(color)
198+
self.xaxis.label.set_color(color)
199+
200+
def get_tightbbox(self, renderer, call_axes_locator=True):
201+
"""
202+
Return the tight bounding box of the axes.
203+
The dimension of the Bbox in canvas coordinate.
204+
205+
If *call_axes_locator* is *False*, it does not call the
206+
_axes_locator attribute, which is necessary to get the correct
207+
bounding box. ``call_axes_locator==False`` can be used if the
208+
caller is only intereted in the relative size of the tightbbox
209+
compared to the axes bbox.
210+
"""
211+
212+
bb = []
213+
214+
if not self.get_visible():
215+
return None
216+
217+
locator = self.get_axes_locator()
218+
if locator and call_axes_locator:
219+
pos = locator(self, renderer)
220+
self.apply_aspect(pos)
221+
else:
222+
self.apply_aspect()
223+
224+
bb_xaxis = self.xaxis.get_tightbbox(renderer)
225+
if bb_xaxis:
226+
bb.append(bb_xaxis)
227+
228+
bb.append(self.get_window_extent(renderer))
229+
230+
_bbox = mtransforms.Bbox.union(
231+
[b for b in bb if b.width != 0 or b.height != 0])
232+
233+
return _bbox

0 commit comments

Comments
 (0)