2017-08-06 7 views
10

पर आयताकार चयनकर्ता गायब हो जाता है जब मैं this उदाहरण चलाता हूं और एक आयताकार चयन बनाता हूं, यदि चयन के चारों ओर प्लॉट विंडो ज़ूम या स्थानांतरित करता है तब तक गायब हो जाता है जब तक कि मैं चाल या ज़ूम टूल को अचयनित नहीं करता और प्लॉट विंडो पर दोबारा क्लिक करता हूं।आयत

मैं एक आईपीथन नोटबुक में %matplotlib tkinter का उपयोग कर रहा हूं।

मैं दिखाई करने के लिए सीमा परिवर्तन है कि तब होती हैं जब खिड़की ज़ूम इन करता है में hooking और आयताकार चयन स्थापित करने का प्रयास किया है:

def persist_rect(newlims): 
    rs = toggle_selector.RS 
    print(rs.visible) 
    rs.set_visible(True) 
    rs.update() 

current_ax.callbacks.connect('xlim_changed', persist_rect) 
current_ax.callbacks.connect('ylim_changed', persist_rect) 

लेकिन यह कुछ भी करने को नहीं लगता है। यह भी प्रकट नहीं होता है कि toggle_selector.RS.visible कभी भी गलत पर सेट है।

मैं भी source for RectangleSelector पर देख रहा हूं, लेकिन मैंने वहां कुछ भी प्रबुद्ध नहीं देखा है।

मैंने यह भी पाया है कि जब मैं RectangleSelector.extents = new_extents का उपयोग कर चयनित क्षेत्र की सीमा को संशोधित करता हूं तो मुझे यह समस्या है। जब .extents संशोधित किया गया है, उदाहरण के लिए स्लाइडर विजेट के साथ, चयनित क्षेत्र तब तक गायब हो जाता है जब तक कि मैं प्लॉट पर दोबारा क्लिक नहीं करता।

RectangleSelectoruseblit=False के साथ @ImportanceOfBeingErnest के रूप में शुरू किया गया है, लेकिन इन्हें कहते हैं, यह एक बहुत ही सक्षम समाधान नहीं है, लेकिन इन समस्याओं में से सभी समस्याएं दूर हो जाती हैं।

+0

क्या आपने इस प्रश्न का उत्तर देखा है: https://stackoverflow.com/questions/34517484/persistent-rectangle-selector? –

+0

@ जैफर विल्सन: उस प्रश्न को इंगित करने के लिए धन्यवाद। दुर्भाग्य से उत्तर काम नहीं कर रहा है। जब इसका उपयोग किया जा रहा है, आयताकार तुरंत गायब हो जाएगा। यदि 'इंटरैक्टिव = ट्रू' के साथ प्रयोग किया जा रहा है, तो उपरोक्त प्रश्न में एक ही समस्या बनी हुई है। – ImportanceOfBeingErnest

उत्तर

3

draw_event रों के लिए एक कॉलबैक जोड़ना:

def mycallback(event): 
    if RS.active: 
     RS.update() 
plt.connect('draw_event', mycallback) 

RectangleSelector जूमिंग या पैन के बाद जारी रहती है, और useblit=True साथ संगत है।


उदाहरण के लिए, एक आधार के रूप code from the docs का उपयोग कर:

from __future__ import print_function 
from matplotlib.widgets import RectangleSelector 
import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.widgets as widgets 
import threading 
import datetime as DT 

def line_select_callback(eclick, erelease): 
    'eclick and erelease are the press and release events' 
    x1, y1 = eclick.xdata, eclick.ydata 
    x2, y2 = erelease.xdata, erelease.ydata 
    print("(%3.2f, %3.2f) --> (%3.2f, %3.2f)" % (x1, y1, x2, y2)) 
    print(" The button you used were: %s %s" % (eclick.button, erelease.button)) 

def toggle_selector(event): 
    print(' Key pressed: {}'.format(event.key)) 
    if event.key in ['D', 'd'] and RS.active: 
     print(' RectangleSelector deactivated.') 
     RS.set_active(False) 
     RS.set_visible(False) 
     RS.update() 
    if event.key in ['A', 'a'] and not RS.active: 
     print(' RectangleSelector activated.') 
     RS.set_active(True) 
     RS.set_visible(True) 
     RS.update() 

def mycallback(event): 
    if RS.active: 
     # print('mycallback') 
     RS.update() 

# def persist_rect(newlims): 
#  print('persist_rect') 
#  RS.set_visible(True) 
#  RS.update() 

fig, ax = plt.subplots() 
# figtype = type(fig) 
# figtype._draw = figtype.draw 
# def mydraw(self, renderer): 
#  print('figure.draw') 
#  self._draw(renderer) 
# figtype.draw = mydraw 

N = 100000    
x = np.linspace(0.0, 10.0, N) 

RS = RectangleSelector(ax, line_select_callback, 
         drawtype='box', useblit=True, 
         button=[1, 3], # don't use middle button 
         minspanx=5, minspany=5, 
         spancoords='pixels', 
         interactive=True) 

plt.plot(x, +np.sin(.2*np.pi*x), lw=3.5, c='b', alpha=.7) 
plt.plot(x, +np.cos(.2*np.pi*x), lw=3.5, c='r', alpha=.5) 
plt.plot(x, -np.sin(.2*np.pi*x), lw=3.5, c='g', alpha=.3) 

plt.connect('key_press_event', toggle_selector) 
plt.connect('draw_event', mycallback) 
# ax.callbacks.connect('xlim_changed', persist_rect) 
# ax.callbacks.connect('ylim_changed', persist_rect) 

plt.show() 

क्यों mycallback काम लेकिन persist_rect नहीं करता है?जबकि mycallback बाद में कहा जाता है persist_rectfigure.draw से पहले कहा जाता हो जाता है

figure.draw 
mycallback 
figure.draw 
mycallback 
(4.09, -0.53) --> (8.15, 0.38) 
The button you used were: 1 1 
persist_rect 
persist_rect 
figure.draw 
mycallback 
Key pressed: q 

ध्यान दें कि,:

आप ऊपर टिप्पणी की-आउट बयान uncomment हैं, तो आप कुछ मुद्रित आउटपुट जो इस रूप में कुछ ऐसी दिखाई देगी मिलेगा। figure.drawRectangleSelection नहीं खींचता है, लेकिन यह पृष्ठभूमि के लिए इस्तेमाल Rectangle खींचता है। तो figure.draw अस्पष्ट RectangleSelection। इस प्रकार persist_rect क्षणिक रूप से RectangleSelection प्रदर्शित करता है, लेकिन यह जारी रखने में विफल रहता है। mycallback काम करता है क्योंकि इसे figure.draw के बाद बुलाया जाता है।

+0

! क्या इसके लिए कोई अच्छी व्याख्या है? सिद्धांत रूप में यह सीमा परिवर्तन पर कॉलबैक के साथ ओपी की कोशिश करने के बहुत करीब है (और जो काम नहीं करता है)। यह भी '.update' को कॉल करने के लिए अनजान प्रतीत होता है, जो वास्तव में एक ड्रा घटना के कॉलबैक * पर आयत खींचता है। सांप की तरह थोड़ा लगता है जैसे अपनी पूंछ काटता है, लेकिन यह स्पष्ट रूप से काम कर रहा है। – ImportanceOfBeingErnest

+1

मुझे लगता है कि यह उस क्रम में उबाल जाता है जिसमें कॉलबैक को 'figure.draw' के सापेक्ष कहा जाता है। 'persist_rect' को' figure.draw' से पहले बुलाया जाता है, जबकि 'mycallback' को बाद में बुलाया जाता है। चूंकि 'figure.draw'' आयताकार चयनकर्ता 'के शीर्ष पर खींचता है,' persist_rect' 'आयताकार चयनकर्ता' को लगातार दिखाई देने में विफल रहता है। मैंने उपरोक्त कुछ बंदर-पैचिंग कोड को दिखाने के लिए जोड़ा है जब 'figure.draw' कॉल किया जाता है। – unutbu

5

यदि मैं सही ढंग से समझता हूं, आयताकार चयनकर्ता को पैनिंग या ज़ूमिंग की प्रक्रिया में दिखाई देना चाहिए। यह blitting का उपयोग नहीं करके प्राप्त किया जा सकता है,

toggle_selector.RS = RectangleSelector(ax, ..., useblit=False, ...) 

इस का एक पक्ष प्रभाव है कि साजिश धीमी गति से भूखंड की जटिलता पर निर्भर करता है, blitting बिना के रूप में, पूरा साजिश लगातार दोबारा बनाई है आयत का उपयोग करते समय हो सकता है है चयनकर्ता।

+1

आपकी मदद के लिए धन्यवाद, दुर्भाग्य से यह मेरे लिए एक इष्टतम समाधान नहीं है। मैं आयत के साथ खींचे गए झरने वाले भूखंडों पर क्षेत्रों का चयन करने के लिए आयताकार चयनकर्ता का उपयोग करना चाहता था। इनमें से सबसे छोटा झरना सरणी ~ 18 एमबी है और सबसे बड़ा ~ 220 एमबी है। 'RectangleSelector' इस redrawing समस्या को छोड़कर blitting के साथ अद्भुत काम करता है। ज़ूम/चाल के बाद क्या मैं इसे मैन्युअल रूप से पुन: निकालने के लिए मजबूर कर सकता हूं? – alessandro

+1

यह सरल भूखंडों के लिए अद्भुत काम करता है। मेरे पास पर्याप्त प्रतिनिधि होने पर खुशी से +1 होगा। – alessandro

0

RectangularSelector के लिए स्रोत कोड में रिलीज विधि (line 2119) चयनकर्ता की दृश्यता

def _release(self, event): 
"""on button release event""" 
    if not self.interactive: 
     self.to_draw.set_visible(False) 

उपवर्ग RectangleSelector doc उदाहरण

का उपयोग कर रिहाई विधि

class visibleRectangleSelector(RectangleSelector): 
    def release(self, event): 
     super(visibleRectangleSelector, self).release(event) 
     self.to_draw.set_visible(True) 
     self.canvas.draw() ##updates canvas for new selection 

नमूना कोड को संशोधित करने के हैंडल

from __future__ import print_function 
""" 
Do a mouseclick somewhere, move the mouse to some destination, release 
the button. This class gives click- and release-events and also draws 
a line or a box from the click-point to the actual mouseposition 
(within the same axes) until the button is released. Within the 
method 'self.ignore()' it is checked whether the button from eventpress 
and eventrelease are the same. 

""" 
from matplotlib.widgets import RectangleSelector 
import numpy as np 
import matplotlib.pyplot as plt 


class visibleRectangleSelector(RectangleSelector): 
    def release(self, event): 
     super(visibleRectangleSelector, self).release(event) 
     self.to_draw.set_visible(True) 
     self.canvas.draw() 


def line_select_callback(eclick, erelease): 
    'eclick and erelease are the press and release events' 
    x1, y1 = eclick.xdata, eclick.ydata 
    x2, y2 = erelease.xdata, erelease.ydata 
    print("(%3.2f, %3.2f) --> (%3.2f, %3.2f)" % (x1, y1, x2, y2)) 
    print(" The button you used were: %s %s" % (eclick.button, 
               erelease.button)) 


def toggle_selector(event): 
    print(' Key pressed.') 
    if event.key in ['Q', 'q'] and toggle_selector.RS.active: 
     print(' RectangleSelector deactivated.') 
     toggle_selector.RS.set_active(False) 
    if event.key in ['A', 'a'] and not toggle_selector.RS.active: 
     print(' RectangleSelector activated.') 
     toggle_selector.RS.set_active(True) 


fig, current_ax = plt.subplots() # make a new plotting range 
N = 100000 # If N is large one can see 
x = np.linspace(0.0, 10.0, N) # improvement by use blitting! 

plt.plot(x, +np.sin(.2 * np.pi * x), lw=3.5, c='b', alpha=.7) # plot something 
plt.plot(x, +np.cos(.2 * np.pi * x), lw=3.5, c='r', alpha=.5) 
plt.plot(x, -np.sin(.2 * np.pi * x), lw=3.5, c='g', alpha=.3) 

print("\n  click --> release") 

# drawtype is 'box' or 'line' or 'none' 
toggle_selector.RS = RectangleSelector(
    current_ax, 
    line_select_callback, 
    drawtype='box', 
    useblit=False, 
    button=[1, 3], # don't use middle button 
    minspanx=5, 
    minspany=5, 
    spancoords='pixels', 
    interactive=True) 
plt.connect('key_press_event', toggle_selector) 
plt.show() 
+1

इस मुद्दे को देखने के लिए धन्यवाद। हालांकि, ऐसा लगता है कि यह समाधान केवल काम कर रहा है क्योंकि आपने [blit = false' का उपयोग [मेरे उत्तर] में किया है (https://stackoverflow.com/a/45531329/4124317)। 'Blit = False' का उपयोग करते समय, कोई सबक्लासिंग की आवश्यकता नहीं है। 'Blit = True' के साथ इस समाधान को आजमाते समय, आयताकार चयनकर्ता अभी भी गायब हो जाता है। तो यह इस मुद्दे को हल करने के लिए प्रतीत नहीं होता है। – ImportanceOfBeingErnest

+0

से ऊपर @ जैफर विल्सन की टिप्पणी से देखा गया, यह उत्तर [इस प्रश्न] के उत्तर का एक ** चोरी ** है (https://stackoverflow.com/questions/34517484/persistent-rectangle-selector)। वास्तव में – ImportanceOfBeingErnest

संबंधित मुद्दे