Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita9b012a

Browse files
committed
adding subplotpars to the plot stack
1 parentfe6ee82 commita9b012a

File tree

3 files changed

+222
-3
lines changed

3 files changed

+222
-3
lines changed

‎lib/matplotlib/backend_bases.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2816,12 +2816,14 @@ def _switch_off_zoom_mode(self, event):
28162816

28172817
defpush_current(self):
28182818
"""Push the current view limits and position onto the stack."""
2819+
subplotpars=self.canvas.figure.subplotpars.get_subplotparams().copy()
28192820
self._nav_stack.push(
28202821
WeakKeyDictionary(
28212822
{ax: (ax._get_view(),
28222823
# Store both the original and modified positions.
28232824
(ax.get_position(True).frozen(),
2824-
ax.get_position().frozen()))
2825+
ax.get_position().frozen()),
2826+
subplotpars)
28252827
foraxinself.canvas.figure.axes}))
28262828
self.set_history_buttons()
28272829

@@ -2948,12 +2950,15 @@ def _update_view(self):
29482950
return
29492951
# Retrieve all items at once to avoid any risk of GC deleting an Axes
29502952
# while in the middle of the loop below.
2953+
subplotpars= {}
29512954
items=list(nav_info.items())
2952-
forax, (view, (pos_orig,pos_active))initems:
2955+
forax, (view, (pos_orig,pos_active),subplotpars)initems:
29532956
ax._set_view(view)
29542957
# Restore both the original and modified positions
29552958
ax._set_position(pos_orig,'original')
29562959
ax._set_position(pos_active,'active')
2960+
2961+
self.canvas.figure.subplotpars.update(**subplotpars)
29572962
self.canvas.draw_idle()
29582963

29592964
defsave_figure(self,*args):

‎lib/matplotlib/figure.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ def __init__(self, left=None, bottom=None, right=None, top=None,
201201
self.validate=True
202202
self.update(left,bottom,right,top,wspace,hspace)
203203

204+
defget_subplotparams(self):
205+
""" Returns a dict with the subplot parameters"""
206+
207+
names= ('left','right','top','bottom','wspace','hspace')
208+
return {name:getattr(self,name,None)fornameinnames}
209+
204210
defupdate(self,left=None,bottom=None,right=None,top=None,
205211
wspace=None,hspace=None):
206212
"""

‎lib/matplotlib/tests/test_backend_bases.py

Lines changed: 209 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
frommatplotlib.backend_basesimport (
2-
FigureCanvasBase,LocationEvent,RendererBase)
2+
FigureCanvasBase,LocationEvent,RendererBase,MouseEvent)
33
importmatplotlib.pyplotasplt
44
importmatplotlib.transformsastransforms
55
importmatplotlib.pathaspath
6+
frommatplotlib.testing.decoratorsimportcheck_figures_equal
7+
frommpl_toolkits.axes_grid1importAxesGrid
68

79
importnumpyasnp
810
importpytest
@@ -90,3 +92,209 @@ def test_location_event_position():
9092
else:
9193
assertevent.y==int(y)
9294
assertisinstance(event.y,int)
95+
96+
97+
classButtonTest():
98+
def__init__(self,fig_test,fig_ref,button_call,plots=None,
99+
layout='none'):
100+
101+
"""
102+
Class for testing the home, back and forwards buttons togheter with
103+
layout managers for several types of "subplots".
104+
105+
Parameters
106+
----------
107+
fig_test, fig_ref: `.figure.figures`
108+
The figure to compare
109+
110+
button_call: {'home', 'back'}
111+
Which buttons to test
112+
113+
plots: {'subplots', 'subplots_gridspec', 'add_subplopt', 'add_axes'\
114+
'axesgrid'}
115+
Which plot configuration to test.
116+
117+
pause : float
118+
The pause time between events.
119+
"""
120+
self.rows_cols=1,2
121+
self.figs=fig_test,fig_ref
122+
self.trans=None,None
123+
self.layout=layout
124+
self.zoom0= (0.5,0.5), (0.5,0.5)
125+
self.zoom1= (0.5,0.5), (0.6,0.54)
126+
self.zoom2= (0.52,0.52), (0.58,0.53)
127+
128+
self.set_layout(True)
129+
self.add_subplots(plots)
130+
self.add_suptitle('Test button: {}, axes: {}, layout manager: {}'.
131+
format(button_call,plots,layout))
132+
133+
ifbutton_call=='home':
134+
self.home_button()
135+
elifbutton_call=='back':
136+
self.back_button()
137+
138+
# set layout managers to False so that the figures don't change
139+
# during saving.
140+
self.set_layout(False)
141+
142+
defadd_suptitle(self,title):
143+
forfiginself.figs:
144+
fig.suptitle(title)
145+
146+
defset_layout(self,bool_):
147+
forfiginself.figs:
148+
ifself.layout=='constrained':
149+
fig.set_constrained_layout(bool_)
150+
elifself.layout=='tight':
151+
arg=dict(rect=(0,0,1,0.95))ifbool_elsebool_
152+
fig.set_tight_layout(arg)
153+
154+
defadd_subplots(self,plots):
155+
rows,cols=self.rows_cols
156+
self.trans= []
157+
forfiginself.figs:
158+
ifplots=='subplots':
159+
ax=fig.subplots(rows,cols,squeeze=False)[rows-1,cols-1]
160+
elifplots=='subplots_gridspec':
161+
ax=fig.subplots(rows,cols,squeeze=False,
162+
gridspec_kw={'left':0.01})[rows-1,cols-1]
163+
elifplots=='add_subplot':
164+
foriinrange(1,rows*cols+1):
165+
ax=fig.add_subplot(rows,cols,i)
166+
elifplots=='add_axes':
167+
width= (1-0.1)/cols-0.1
168+
height= (1-0.1)/rows-0.1
169+
foriinrange(rows):
170+
forjinrange(cols):
171+
x0=j*(width+0.1)+0.1
172+
y0=i*(height+0.1)+0.1
173+
ax=fig.add_axes((x0,y0,width,height))
174+
elifplots=='axesgrid':
175+
ax=AxesGrid(fig,111,nrows_ncols=(2,2),
176+
axes_pad=0.1)[-1]
177+
178+
self.trans.append(ax.transData.transform)
179+
self.draw()
180+
181+
defdraw(self):
182+
forfiginself.figs:
183+
fig.canvas.flush_events()
184+
185+
defhome_button(self):
186+
"""Zoom twice and get back to home with the home button."""
187+
188+
fig_test,fig_ref=self.figs
189+
trans_test,trans_ref=self.trans
190+
#No zoom happens but this is sometimes necessary to get equal results
191+
self.zoom_event(fig_ref,trans_ref,self.zoom0)
192+
self.zoom_event(fig_test,trans_test,self.zoom1)
193+
self.zoom_event(fig_test,trans_test,self.zoom2)
194+
195+
self.move(fig_test,'home')
196+
197+
defback_button(self):
198+
"""
199+
Zoom once in the ref figure, zoom twice in the test figure and use
200+
the back button twice followed by the forward button
201+
"""
202+
fig_test,fig_ref=self.figs
203+
trans_test,trans_ref=self.trans
204+
205+
self.zoom_event(fig_ref,trans_ref,self.zoom1)
206+
self.zoom_event(fig_test,trans_test,self.zoom1)
207+
self.zoom_event(fig_test,trans_test,self.zoom2)
208+
209+
self.move(fig_test,'back')
210+
self.move(fig_test,'back')
211+
self.move(fig_test,'forward')
212+
213+
defzoom_event(self,fig,trans,zoom):
214+
"""Simulate a zoom event from zoom[0] to zoom[1]"""
215+
xy1,xy2=trans(zoom[0]),trans(zoom[1])
216+
press_zoom=MouseEvent('',fig.canvas,xy1[0],xy1[1],button=1)
217+
drag=MouseEvent('',fig.canvas,xy2[0],xy2[1],button=1)
218+
release_zoom=MouseEvent('',fig.canvas,xy2[0],xy2[1],button=1)
219+
220+
fig.canvas.toolbar.press_zoom(press_zoom)
221+
fig.canvas.toolbar.drag_zoom(drag)
222+
fig.canvas.toolbar.release_zoom(release_zoom)
223+
self.draw()
224+
225+
defmove(self,fig,direction):
226+
"""Simulate the back or forward button on fig"""
227+
getattr(fig.canvas.toolbar,direction)()
228+
self.draw()
229+
230+
231+
"""
232+
The tests are designed to test some known failures at writting time and that
233+
there are no problem with the actual implementation for different use cases
234+
235+
test_back_button 2 and 4 and test_home_button 2 fails on master.
236+
The home_button tests would probably fail on v2.1.0
237+
"""
238+
239+
240+
@pytest.mark.backend('QT5Agg')
241+
@check_figures_equal(extensions=["png"])
242+
deftest_back_button1(fig_test,fig_ref):
243+
ButtonTest(fig_test,fig_ref,'back',plots='subplots',layout='none')
244+
245+
246+
@pytest.mark.backend('QT5Agg')
247+
@check_figures_equal(extensions=["png"])
248+
deftest_back_button2(fig_test,fig_ref):
249+
ButtonTest(fig_test,fig_ref,'back',plots='subplots',layout='tight')
250+
251+
252+
@pytest.mark.backend('QT5Agg')
253+
@check_figures_equal(extensions=["png"])
254+
deftest_back_button3(fig_test,fig_ref):
255+
ButtonTest(fig_test,fig_ref,'back',plots='subplots',
256+
layout='constrained')
257+
258+
259+
@pytest.mark.backend('QT5Agg')
260+
@check_figures_equal(extensions=["png"])
261+
deftest_back_button4(fig_test,fig_ref):
262+
ButtonTest(fig_test,fig_ref,'back',plots='add_subplot',layout='tight')
263+
264+
265+
@pytest.mark.backend('QT5Agg')
266+
@check_figures_equal(extensions=["png"])
267+
deftest_back_button5(fig_test,fig_ref):
268+
ButtonTest(fig_test,fig_ref,'back',plots='add_axes',layout='none')
269+
270+
271+
@pytest.mark.backend('QT5Agg')
272+
@check_figures_equal(extensions=["png"])
273+
deftest_back_button6(fig_test,fig_ref):
274+
ButtonTest(fig_test,fig_ref,'back',plots='axesgrid',layout='none')
275+
276+
277+
@pytest.mark.backend('QT5Agg')
278+
@check_figures_equal(extensions=["png"])
279+
deftest_back_button7(fig_test,fig_ref):
280+
ButtonTest(fig_test,fig_ref,'back',plots='subplots_gridspec',
281+
layout='none')
282+
283+
284+
@pytest.mark.backend('QT5Agg')
285+
@check_figures_equal(extensions=["png"])
286+
deftest_home_button1(fig_test,fig_ref):
287+
ButtonTest(fig_test,fig_ref,'home',plots='subplots',layout='none')
288+
289+
290+
@pytest.mark.backend('QT5Agg')
291+
@check_figures_equal(extensions=["png"])
292+
deftest_home_button2(fig_test,fig_ref):
293+
ButtonTest(fig_test,fig_ref,'home',plots='subplots',layout='tight')
294+
295+
296+
@pytest.mark.backend('QT5Agg')
297+
@check_figures_equal(extensions=["png"])
298+
deftest_home_button3(fig_test,fig_ref):
299+
ButtonTest(fig_test,fig_ref,'home',plots='subplots',
300+
layout='constrained')

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp