同时使用两个RectangularSelector-奇怪的“纸牌模式”

时间:2018-07-04 13:31:31

标签: python matplotlib matplotlib-widget

我正在尝试向图中添加两个矩形选择器(docs):

当前,我在按下键盘按键时创建AreaBackground类(均包含矩形选择器)。按下另一个键后,我又创建了两个类,分别从AreaBackground类中获取属性。

import numpy as np
import matplotlib.pyplot as plt


from matplotlib.widgets import RectangleSelector

class AreaSelector():
    """ lets the user select an area"""
    def __init__(self, fig, ax, im):
        self.x1                         = None
        self.y1                         = None
        self.x2                         = None
        self.y2                         = None

        self.observers                  = []

        toggle_selector.RS              = RectangleSelector(ax, self.line_select_callback,
                                                            drawtype='box', useblit=True,
                                                            button=[1],  # don't use middle button
                                                            minspanx=1, minspany=1,
                                                            spancoords='pixels',
                                                            interactive=True,
                                                            rectprops=dict(facecolor='green',edgecolor='black', alpha=0.3))

    def line_select_callback(self, eclick, erelease):
        """ gets the positions and sends them to the observer"""
        'eclick and erelease are the press and release events'
        self.x1, self.y1 = eclick.xdata, eclick.ydata
        self.x2, self.y2 = erelease.xdata, erelease.ydata
        self.set_new_position(self.x1, self.y1, self.x2, self.y2)

    def set_new_position(self, x1, y1, x2, y2):
        """ informs the observer about the new positions"""
        self.x1                     = x1
        self.y1                     = y1
        self.x2                     = x2
        self.y2                     = y2 
        for callback in self.observers:
            callback(self.x1, self.y1, self.x2, self.y2)

    def bind_to(self, callback):
        """ binds the observer"""
        self.observers.append(callback)

class ExtractSpectra():
    def __init__(self, cube, area_selector):
        """ class that will do fancy things with the selected area"""
        self.cube                   = cube
        self.x1_area                = None
        self.y1_area                = None
        self.x2_area                = None
        self.y2_area                = None
        self.sum_area               = None
        self.sum_background         = None

        self.area_selector          = area_selector

        self.area_selector.bind_to(self.update_position_area)

    def update_position_area(self, x1, y1, x2, y2):
        """ updates position upon changes in Area Selector"""
        self.x1_area                = x1
        self.y1_area                = y1
        self.x2_area                = x2
        self.y2_area                = y2

    def get_spectra(self): 
        """ some math on the selected area"""
        if self.x1_area != None:
            self.sum_area           = np.sum(self.cube[np.round(self.y1_area,0).astype(int) : np.round(self.y2_area,0).astype(int),
                                                       np.round(self.x1_area,0).astype(int) : np.round(self.x2_area,0).astype(int)])
            print(self.sum_area)


        else:
            print("Area not selected!")


class BackgroundSelector():
    """ lets the user select an area, same structur as other selector"""
    def __init__(self, fig, ax, im):
        self.x1                     = None
        self.y1                     = None
        self.x2                     = None
        self.y2                     = None

        self.observers              = []

        toggle_selector.RS          = RectangleSelector(ax, self.line_select_callback,
                                                            drawtype='box', useblit=True,
                                                            button=[1],  # don't use middle button
                                                            minspanx=1, minspany=1,
                                                            spancoords='pixels',
                                                            interactive=True,
                                                            rectprops=dict(facecolor='red',edgecolor='black', alpha=0.3))        

    def line_select_callback(self, eclick, erelease):
        'eclick and erelease are the press and release events'
        self.x1, self.y1            = eclick.xdata,   eclick.ydata
        self.x2, self.y2            = erelease.xdata, erelease.ydata
        self.set_new_position(self.x1, self.y1, self.x2, self.y2)

    def set_new_position(self, x1, y1, x2, y2):
        self.x1                     = x1
        self.y1                     = y1
        self.x2                     = x2
        self.y2                     = y2 
        for callback in self.observers:
            callback(self.x1, self.y1, self.x2, self.y2)

    def bind_to(self, callback):
        self.observers.append(callback)

class ExtractBackground():
    def __init__(self, cube, background_selector):
        self.cube                   = cube
        self.x1_background          = None
        self.y1_background          = None
        self.x2_background          = None
        self.y2_background          = None
        self.sum_background         = None

        self.background_selector    = background_selector

        self.background_selector.bind_to(self.update_position_background)


    def update_position_background(self, x1, y1, x2, y2):
        self.x1_background          = x1
        self.y1_background          = y1
        self.x2_background          = x2
        self.y2_background          = y2


    def get_background(self):
        if self.x1_background != None:
            self.sum_background     = np.sum(self.cube[np.round(self.y1_background,0).astype(int) : np.round(self.y2_background,0).astype(int),
                                                       np.round(self.x1_background,0).astype(int) : np.round(self.x2_background,0).astype(int)])
            print(self.sum_background)            
        else:
            print("Background not selected!")







def sample_plot():
    fig                             = plt.figure()
    ax                              = plt.subplot()

    im                              = np.ones((100,100))*-1
    im[10:20,10:40]                 = 1.

    img                             = ax.imshow(im, origin='lower', cmap='inferno')

    return(fig, ax, img, im)





if __name__ == "__main__":



    def toggle_selector( event):
        print(' Key pressed.')        

        if event.key in ['E', 'e']:
            area_selector                   = AreaSelector(fig, ax, im)
            extractor_area                  = ExtractSpectra(im, area_selector)
            global extractor_area
            print('e')

        if event.key in ['C', 'c']:
            background_selector             = BackgroundSelector(fig, ax, im)
            extractor_background            = ExtractBackground(im, background_selector)
            global extractor_background
            print('c')

        if event.key in ['Y', 'y']:

            try: extractor_area.get_spectra()
            except: print('extrator area not designated')
            try: extractor_background.get_background()
            except: print('background area not designated')
            print('y')


    fig, ax, img, im                = sample_plot()


    plt.connect('key_press_event', toggle_selector)
    plt.show()

这基本上可以正常工作(即使我对编写此方法的方式并不满意(为什么要使用4个类?使用全局变量等),但是AreaSelector在屏幕上移动时会在屏幕上创建一个奇怪的图案(单人纸牌游戏玩家会认出它!)

enter image description here

发生了什么事?如果您有心情,我该怎么做呢?我正在尝试升级我的编程游戏!

谢谢!

0 个答案:

没有答案