के साथ मैटलप्लिब्ब प्लॉट ज़ूमिंग क्या कर्सर एक matplotlib प्लॉट पर होवर करते समय ज़ूम इन/आउट करने के लिए स्क्रॉल व्हील को बांधना संभव है?स्क्रॉल व्हील
उत्तर
यह काम करना चाहिए। जब आप स्क्रॉल करते हैं तो यह पॉइंटर के स्थान पर ग्राफ़ को फिर से केंद्रित करता है।
import matplotlib.pyplot as plt
def zoom_factory(ax,base_scale = 2.):
def zoom_fun(event):
# get the current x and y limits
cur_xlim = ax.get_xlim()
cur_ylim = ax.get_ylim()
cur_xrange = (cur_xlim[1] - cur_xlim[0])*.5
cur_yrange = (cur_ylim[1] - cur_ylim[0])*.5
xdata = event.xdata # get event x location
ydata = event.ydata # get event y location
if event.button == 'up':
# deal with zoom in
scale_factor = 1/base_scale
elif event.button == 'down':
# deal with zoom out
scale_factor = base_scale
else:
# deal with something that should never happen
scale_factor = 1
print event.button
# set new limits
ax.set_xlim([xdata - cur_xrange*scale_factor,
xdata + cur_xrange*scale_factor])
ax.set_ylim([ydata - cur_yrange*scale_factor,
ydata + cur_yrange*scale_factor])
plt.draw() # force re-draw
fig = ax.get_figure() # get the figure of interest
# attach the call back
fig.canvas.mpl_connect('scroll_event',zoom_fun)
#return the function
return zoom_fun
मान लें कि आप एक धुरी वस्तु ax
ax.plot(range(10))
scale = 1.5
f = zoom_factory(ax,base_scale = scale)
वैकल्पिक तर्क base_scale
आप क्या कभी आप चाहते होने के लिए पैमाने कारक स्थापित करने के लिए अनुमति देता है।
सुनिश्चित करें कि आप f
की प्रतिलिपि बना लें। कॉल बैक कमजोर-रेफरी का उपयोग करता है, इसलिए यदि आप f
की प्रति नहीं रखते हैं तो यह कचरा एकत्र हो सकता है।
इस जवाब लिखने के बाद मैं इस वास्तव में काफी उपयोगी फैसला किया और में रख एक gist
मैंने स्वतंत्र रूप से यह भी किया! मेरी इच्छा है कि मैंने पहले एसओ की जांच की हो। मैं भी योगदान देना चाहता हूं। – RodericDay
@RodericDay आप इसे पकड़ सकते हैं और इसे बेहतर बना सकते हैं – tacaswell
मैं उस चरण में नहीं हूं जहां मैं अन्य लोगों के उपयोग के लिए वास्तविक कोड सबमिट करता हूं, लेकिन अगर उपयोगकर्ता संबंधित सापेक्ष निर्देशांक में रुचि रखते हैं तो मैं नीचे एक फिक्स की सिफारिश करूंगा – RodericDay
def zoom(self, event, factor):
curr_xlim = self.ax.get_xlim()
curr_ylim = self.ax.get_ylim()
new_width = (curr_xlim[1]-curr_ylim[0])*factor
new_height= (curr_xlim[1]-curr_ylim[0])*factor
relx = (curr_xlim[1]-event.xdata)/(curr_xlim[1]-curr_xlim[0])
rely = (curr_ylim[1]-event.ydata)/(curr_ylim[1]-curr_ylim[0])
self.ax.set_xlim([event.xdata-new_width*(1-relx),
event.xdata+new_width*(relx)])
self.ax.set_ylim([event.ydata-new_width*(1-rely),
event.ydata+new_width*(rely)])
self.draw()
इस थोड़ा बदल कोड के प्रयोजन के नए ज़ूम केंद्र के लिए कर्सर रिश्तेदार की स्थिति पर नज़र रखने के लिए है । इस तरह, यदि आप केंद्र के अलावा अन्य बिंदुओं पर चित्र को ज़ूम इन और आउट करते हैं तो आप एक ही बिंदु पर रहते हैं।
धन्यवाद दोस्तों, उदाहरण बहुत उपयोगी थे। मुझे स्कैटर प्लॉट के साथ काम करने में कुछ बदलाव करना पड़ा और मैंने बाएं बटन ड्रैग के साथ पैनिंग जोड़ा। उम्मीद है कि किसी को यह उपयोगी लगेगा।
from matplotlib.pyplot import figure, show
import numpy
class ZoomPan:
def __init__(self):
self.press = None
self.cur_xlim = None
self.cur_ylim = None
self.x0 = None
self.y0 = None
self.x1 = None
self.y1 = None
self.xpress = None
self.ypress = None
def zoom_factory(self, ax, base_scale = 2.):
def zoom(event):
cur_xlim = ax.get_xlim()
cur_ylim = ax.get_ylim()
xdata = event.xdata # get event x location
ydata = event.ydata # get event y location
if event.button == 'down':
# deal with zoom in
scale_factor = 1/base_scale
elif event.button == 'up':
# deal with zoom out
scale_factor = base_scale
else:
# deal with something that should never happen
scale_factor = 1
print event.button
new_width = (cur_xlim[1] - cur_xlim[0]) * scale_factor
new_height = (cur_ylim[1] - cur_ylim[0]) * scale_factor
relx = (cur_xlim[1] - xdata)/(cur_xlim[1] - cur_xlim[0])
rely = (cur_ylim[1] - ydata)/(cur_ylim[1] - cur_ylim[0])
ax.set_xlim([xdata - new_width * (1-relx), xdata + new_width * (relx)])
ax.set_ylim([ydata - new_height * (1-rely), ydata + new_height * (rely)])
ax.figure.canvas.draw()
fig = ax.get_figure() # get the figure of interest
fig.canvas.mpl_connect('scroll_event', zoom)
return zoom
def pan_factory(self, ax):
def onPress(event):
if event.inaxes != ax: return
self.cur_xlim = ax.get_xlim()
self.cur_ylim = ax.get_ylim()
self.press = self.x0, self.y0, event.xdata, event.ydata
self.x0, self.y0, self.xpress, self.ypress = self.press
def onRelease(event):
self.press = None
ax.figure.canvas.draw()
def onMotion(event):
if self.press is None: return
if event.inaxes != ax: return
dx = event.xdata - self.xpress
dy = event.ydata - self.ypress
self.cur_xlim -= dx
self.cur_ylim -= dy
ax.set_xlim(self.cur_xlim)
ax.set_ylim(self.cur_ylim)
ax.figure.canvas.draw()
fig = ax.get_figure() # get the figure of interest
# attach the call back
fig.canvas.mpl_connect('button_press_event',onPress)
fig.canvas.mpl_connect('button_release_event',onRelease)
fig.canvas.mpl_connect('motion_notify_event',onMotion)
#return the function
return onMotion
fig = figure()
ax = fig.add_subplot(111, xlim=(0,1), ylim=(0,1), autoscale_on=False)
ax.set_title('Click to zoom')
x,y,s,c = numpy.random.rand(4,200)
s *= 200
ax.scatter(x,y,s,c)
scale = 1.1
zp = ZoomPan()
figZoom = zp.zoom_factory(ax, base_scale = scale)
figPan = zp.pan_factory(ax)
show()
बहुत बहुत धन्यवाद। यह बहुत अच्छा काम किया। हालांकि, भूखंडों के लिए जहां स्केल अब रैखिक नहीं है (उदाहरण के लिए लॉग प्लॉट), यह टूट जाता है। मैंने इसके लिए एक नया संस्करण लिखा है। मुझे उम्मीद है कि यह किसी की मदद करेगा।
असल में, मैं धुरी निर्देशांक में ज़ूम करता हूं जो [0,1] होने के लिए सामान्यीकृत होते हैं। इसलिए, यदि मैं एक्स में दो से ज़ूम करता हूं, तो अब मैं [.25, .75] रेंज में रहना चाहता हूं। मैंने एक्स अक्ष में सीधे या नीचे होने पर केवल ज़ूम इन करने के लिए एक सुविधा भी जोड़ दी है, और केवल वाई में यदि आप सीधे वाई या अक्ष के दाएं हैं। अगर आपको इसकी आवश्यकता नहीं है, तो बस zoomx = True सेट करें, और ज़ूमी = सही करें और अगर कथन को अनदेखा करें। http://matplotlib.org/users/transforms_tutorial.html
यह समारोह एक वस्तु है कि कुल्हाड़ियों (self.ax) के लिए सूचक होता है के भीतर है:
इस संदर्भ जो समझते हैं कि कैसे matplotlib अलग समन्वय प्रणालियों के बीच बदल देती चाहते लोगों के लिए बहुत उपयोगी है।
def zoom(self,event):
'''This function zooms the image upon scrolling the mouse wheel.
Scrolling it in the plot zooms the plot. Scrolling above or below the
plot scrolls the x axis. Scrolling to the left or the right of the plot
scrolls the y axis. Where it is ambiguous nothing happens.
NOTE: If expanding figure to subplots, you will need to add an extra
check to make sure you are not in any other plot. It is not clear how to
go about this.
Since we also want this to work in loglog plot, we work in axes
coordinates and use the proper scaling transform to convert to data
limits.'''
x = event.x
y = event.y
#convert pixels to axes
tranP2A = self.ax.transAxes.inverted().transform
#convert axes to data limits
tranA2D= self.ax.transLimits.inverted().transform
#convert the scale (for log plots)
tranSclA2D = self.ax.transScale.inverted().transform
if event.button == 'down':
# deal with zoom in
scale_factor = self.zoom_scale
elif event.button == 'up':
# deal with zoom out
scale_factor = 1/self.zoom_scale
else:
# deal with something that should never happen
scale_factor = 1
#get my axes position to know where I am with respect to them
xa,ya = tranP2A((x,y))
zoomx = False
zoomy = False
if(ya < 0):
if(xa >= 0 and xa <= 1):
zoomx = True
zoomy = False
elif(ya <= 1):
if(xa <0):
zoomx = False
zoomy = True
elif(xa <= 1):
zoomx = True
zoomy = True
else:
zoomx = False
zoomy = True
else:
if(xa >=0 and xa <= 1):
zoomx = True
zoomy = False
new_alimx = (0,1)
new_alimy = (0,1)
if(zoomx):
new_alimx = (np.array([1,1]) + np.array([-1,1])*scale_factor)*.5
if(zoomy):
new_alimy = (np.array([1,1]) + np.array([-1,1])*scale_factor)*.5
#now convert axes to data
new_xlim0,new_ylim0 = tranSclA2D(tranA2D((new_alimx[0],new_alimy[0])))
new_xlim1,new_ylim1 = tranSclA2D(tranA2D((new_alimx[1],new_alimy[1])))
#and set limits
self.ax.set_xlim([new_xlim0,new_xlim1])
self.ax.set_ylim([new_ylim0,new_ylim1])
self.redraw()
ज़ूम कर रहे हैं की बेहतर भावना/समझ दे रहे हैं क्या आप इसे अपस्ट्रीम सबमिट कर सकते हैं? लगभग https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/backend_tools.py#L625 – tacaswell
में पैच होना चाहिए। https://github.com/matplotlib/matplotlib/pull/4970 पहली बार ऐसा करने के बाद, तो मुझे बताएं कि मुझे कुछ करना चाहिए था, या बेहतर हो सकता था। धन्यवाद! – julienl
मुझे वास्तव में आकृति भूखंडों में "एक्स केवल" या "वाई केवल" मोड पसंद हैं। आप एक्स और वाई कुंजी को बांध सकते हैं ताकि ज़ूमिंग केवल एक दिशा में हो। ध्यान रखें कि आप अगर आप एक एंट्री बॉक्स या कुछ और पर क्लिक करें कैनवास पर वापस ध्यान केंद्रित रखने के लिए हो सकता है -
canvas.mpl_connect('button_press_event', lambda event:canvas._tkcanvas.focus_set())
संशोधित कोड के बाकी नीचे है:
from matplotlib.pyplot import figure, show
import numpy
class ZoomPan:
def __init__(self):
self.press = None
self.cur_xlim = None
self.cur_ylim = None
self.x0 = None
self.y0 = None
self.x1 = None
self.y1 = None
self.xpress = None
self.ypress = None
self.xzoom = True
self.yzoom = True
self.cidBP = None
self.cidBR = None
self.cidBM = None
self.cidKeyP = None
self.cidKeyR = None
self.cidScroll = None
def zoom_factory(self, ax, base_scale = 2.):
def zoom(event):
cur_xlim = ax.get_xlim()
cur_ylim = ax.get_ylim()
xdata = event.xdata # get event x location
ydata = event.ydata # get event y location
if(xdata is None):
return()
if(ydata is None):
return()
if event.button == 'down':
# deal with zoom in
scale_factor = 1/base_scale
elif event.button == 'up':
# deal with zoom out
scale_factor = base_scale
else:
# deal with something that should never happen
scale_factor = 1
print(event.button)
new_width = (cur_xlim[1] - cur_xlim[0]) * scale_factor
new_height = (cur_ylim[1] - cur_ylim[0]) * scale_factor
relx = (cur_xlim[1] - xdata)/(cur_xlim[1] - cur_xlim[0])
rely = (cur_ylim[1] - ydata)/(cur_ylim[1] - cur_ylim[0])
if(self.xzoom):
ax.set_xlim([xdata - new_width * (1-relx), xdata + new_width * (relx)])
if(self.yzoom):
ax.set_ylim([ydata - new_height * (1-rely), ydata + new_height * (rely)])
ax.figure.canvas.draw()
ax.figure.canvas.flush_events()
def onKeyPress(event):
if event.key == 'x':
self.xzoom = True
self.yzoom = False
if event.key == 'y':
self.xzoom = False
self.yzoom = True
def onKeyRelease(event):
self.xzoom = True
self.yzoom = True
fig = ax.get_figure() # get the figure of interest
self.cidScroll = fig.canvas.mpl_connect('scroll_event', zoom)
self.cidKeyP = fig.canvas.mpl_connect('key_press_event',onKeyPress)
self.cidKeyR = fig.canvas.mpl_connect('key_release_event',onKeyRelease)
return zoom
def pan_factory(self, ax):
def onPress(event):
if event.inaxes != ax: return
self.cur_xlim = ax.get_xlim()
self.cur_ylim = ax.get_ylim()
self.press = self.x0, self.y0, event.xdata, event.ydata
self.x0, self.y0, self.xpress, self.ypress = self.press
def onRelease(event):
self.press = None
ax.figure.canvas.draw()
def onMotion(event):
if self.press is None: return
if event.inaxes != ax: return
dx = event.xdata - self.xpress
dy = event.ydata - self.ypress
self.cur_xlim -= dx
self.cur_ylim -= dy
ax.set_xlim(self.cur_xlim)
ax.set_ylim(self.cur_ylim)
ax.figure.canvas.draw()
ax.figure.canvas.flush_events()
fig = ax.get_figure() # get the figure of interest
self.cidBP = fig.canvas.mpl_connect('button_press_event',onPress)
self.cidBR = fig.canvas.mpl_connect('button_release_event',onRelease)
self.cidBM = fig.canvas.mpl_connect('motion_notify_event',onMotion)
# attach the call back
#return the function
return onMotion
यह ऊपर दिए गए कोड में मामूली संशोधन के लिए एक सुझाव है - यह ज़ूम केंद्रित अधिक प्रबंधनीय बनाए रखता है।
cur_xrange = (cur_xlim[1] - cur_xlim[0])*.5
cur_yrange = (cur_ylim[1] - cur_ylim[0])*.5
xmouse = event.xdata # get event x location
ymouse = event.ydata # get event y location
cur_xcentre = (cur_xlim[1] + cur_xlim[0])*.5
cur_ycentre = (cur_ylim[1] + cur_ylim[0])*.5
xdata = cur_xcentre+ 0.25*(xmouse-cur_xcentre)
ydata = cur_ycentre+ 0.25*(ymouse-cur_ycentre)
- 1. स्क्रॉल व्हील घटनाक्रम कैप्चरिंग
- 2. माउस व्हील
- 3. माउस व्हील tmux
- 4. JSCrollPane स्क्रॉल 1 लाइन प्रति माउस व्हील चरण कैसे बनाएं?
- 5. सी # सूची दृश्य के बिना माउस व्हील स्क्रॉल
- 6. TListView और माउस व्हील स्क्रॉलिंग
- 7. माउस व्हील
- 8. कलर व्हील
- 9. एंड्रॉइड टाइमपिकर (व्हील स्टाइल) ScrollView
- 10. स्क्रॉल करने योग्य लेकिन कोई स्क्रॉल बार
- 11. हाई लेवल डिज़ाइन पैटर्न या व्हील रीइन्वेंटिंग द व्हील
- 12. AVPlayerLayer - व्हील रीप्रोग्रामिंग?
- 13. वर्टिकल माउस स्क्रॉलिंग व्हील वीएस 2010 अल्टीमेट
- 14. यूआईआई में विंडो स्क्रॉल या स्क्रॉल वाई स्थिति प्राप्त करें
- 15. डब्लूपीएफ स्क्रॉलव्यूयर स्क्रॉल राशि
- 16. जावास्क्रिप्ट: माउस व्हील इवेंट कैप्चर करें और पृष्ठ को स्क्रॉल न करें?
- 17. माउस व्हील का उपयोग कर एक समय में DataGridView स्क्रॉल एक आइटम कैसे बना सकते हैं?
- 18. माउस व्हील और स्क्रॉल बार का उपयोग करके चिकना लंबवत पृष्ठ स्क्रॉलिंग
- 19. स्क्रॉल व्हील कस्टम स्ट्रीट व्यू में अक्षम किया जा सकता है?
- 20. माउस व्हील डाउन इवेंट वाली वेबसाइट पर कितने पिक्सल स्क्रॉल किए जाते हैं?
- 21. मूसहेल स्क्रॉल?
- 22. मैं विंडो माउस व्हील स्क्रॉलिंग को कैसे दबा सकता हूं ...?
- 23. एचटीएमएल 5 में स्पिन व्हील छवि (उदाहरण के लिए, रूले व्हील)?
- 24. पैनल पर माउस व्हील कैप्चर कैसे करें?
- 25. कताई व्हील एनीमेशन लोड हो रहा है
- 26. एचटीएमएल 5 कैनवास माउस व्हील इवेंट
- 27. स्पिनिंग व्हील एंड्रॉइड के लिए ट्यूटोरियल?
- 28. एसएसएल व्हील reinventing oauth_signature नहीं है?
- 29. स्क्रॉल
- 30. स्क्रॉल
आप एक फोन वापस समारोह लिखते हैं कि http://matplotlib.sourceforge.net/api/backend_bases_api.html?highlight=mpl_connect#matplotlib.backend_bases.FigureCanvasBase.mpl_connect – tacaswell
इस के किसी भी उदाहरण ऐसा करने के लिए कर सकते हैं? – dimka