chongxi / spiketag

Next generation of spike sorting package for BMI
BSD 3-Clause "New" or "Revised" License
6 stars 4 forks source link

cluster event has multiple copies of the same _callback (severe bug slowing down the system) #23

Closed chongxi closed 5 years ago

chongxi commented 5 years ago

image

Trace down to the ctrl.update_view() function. Every time this function got executed, there will be another copy.

chongxi commented 5 years ago
    def connect(self, func=None, event=None, set_method=False):
        """Register a callback function to a given event.

        To register a callback function to the `spam` event, where `obj` is
        an instance of a class deriving from `EventEmitter`:

        ```python
        @obj.connect
        def on_spam(arg1, arg2):
            pass
    This is called when `obj.emit('spam', arg1, arg2)` is called.

    Several callback functions can be registered for a given event.

    The registration order is conserved and may matter in applications.

    """
    if func is None:
        return partial(self.connect, set_method=set_method)

    # Get the event name from the function.
    if event is None:
        event = self._get_on_name(func)

    # We register the callback function.
    # if func is not in self._callbacks[event]:
    funcName = func.__module__ + '.' + func.__name__ # + '_id' + str(id(func))
    if funcName not in self._registered_func_name(event):
        self._callbacks[event].append(func)

    # A new method self.event() emitting the event is created.
    if set_method:
        self._create_emitter(event)

    return func
chongxi commented 5 years ago

As the major event emitter, CLU needs a _event_reg_enable flag:

class CLU(EventEmitter):
    """docstring for Clu"""
    def __init__(self, clu, method=None, clusterer=None, treeinfo=None, probmatrix=None):
        super(CLU, self).__init__()
        self.membership = clu.copy()
        if method:
            self._method = method
        if clusterer:
            self._extra_info = self._extract_extra_info(clusterer)       
            self._select_clusters = self._extra_info['default_select_clusters']
        if treeinfo:
            self._extra_info = treeinfo
            self._select_clusters = treeinfo['default_select_clusters']
        if probmatrix is not None:
            self._probmatrix = probmatrix

        self.__membership = self.membership.copy()
        while min(self.membership) < 0:
            self.membership += 1
        self._membership_stack = []
        self.__construct__()
        self.selectlist = np.array([])

        # every new born clu has _event_reg_enable as True. 
        # When the registration process finished, this reg will be set to False to prevent double registration
        self._event_reg_enable = True  
chongxi commented 5 years ago

When the registration process finished, this reg will be set to False to prevent double registration

chongxi commented 5 years ago

Then in the MainView:

    def set_data(self, group_id, mua, spk, fet, clu):
        ### init view and set_data

        self.clu = clu
        chs = self.prb[group_id]
        self.spkview.set_data(spk, clu)
        # self.fetview0.set_data(fet, clu)
        # if fet.shape[1]>3:
        self.fetview0.dimension = [0,1,2]
        self.fetview0.set_data(fet, clu)   #[:,[0,1,2]].copy()
        self.fetview1.dimension = [0,1,3]
        self.fetview1.set_data(fet, clu)   #[:,[0,1,3]].copy()
        # else:
        self.ampview.set_data(spk, clu, mua.spk_times[group_id])
        self.treeview.set_data(clu) 
        self.traceview.set_data(chs, clu, mua.spk_times[group_id])
        try:
            self.corview.set_data(clu, mua.spk_times[group_id])
        except Exception as e:
            pass

        self.traceview.locate_buffer = 1500

        if self.clu._event_reg_enable is True:
            self.register_event()

    def register_event(self):
        self.spkview.register_event()
        self.fetview0.register_event()
        self.fetview1.register_event()
        self.ampview.register_event()
        self.traceview.register_event()
        self.corview.register_event()
        self.clu._event_reg_enable = False
chongxi commented 5 years ago

Therefore, every newborn clu will go through the registration process and after that, no callback registration is allowed.

chongxi commented 5 years ago

image Now no double callback registration happend