Lemanuel Colon
Lemanuel Colon

Reputation: 72

wxNotebook event only working on last bind

I have this program that has a panel with a notebook that have various panels. These panels have some text because is more specific, and then another panel that its only for plotting that is more general since i send the to the plotting panel the data from his parent. Ok, my problem is that having multiple real time plots at the same time make the application slow.

I'm trying to implement a way to stop and start these animations when changing trough the pages. So' i bind and wx.EVT_NOTEBOOK_PAGE_CHANGED in the panel of the mainframe to a method that handle this the stop and start of the animation. But when i try this, the only bind that execute is only the last one, the first two do not triggers them self. Also in this method I'm trying to and away of know witch is the current pages and witch is the selected pages, so the selected pages receive the event to start, and the current receive the event and stop.

I tried to bind the event in the pages so all the pages got it but with no luck, also tried by creating a method in panel that called the stop method and passed the event to the plot.

This is the plot panel

class live_panel_2(wx.Panel):
    def __init__(self, parent):
        super(live_panel_2, self).__init__(parent)
        sns.set()

        self.parent = parent
        self.x_axis = []
        self.x2_axis = []
        self.y_axis = []
        self.y2_axis = []
        self.line_width = 1
        self.flag = False
        self.flag1 = False
        self.figure = Figure(figsize=(15.5, 3))
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.axis = self.figure.add_subplot(1, 1, 1)
        self.axis2 = self.axis.twinx()
        self.toolbar = NavigationToolbar(self.canvas)
        self.toolbar.Realize()
        #self.button = wx.Button(self, label='Stop')

        self.figure.subplots_adjust(left=0.09, right=0.92, top=0.92, bottom=0.2, wspace=1)
        self.axis.format_xdata = mdates.DateFormatter('%Y-%m-%d')
        #self.axis.tick_params(axis='x', direction='inout', length=5, labelrotation=0)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 0, wx.EXPAND, 5 )
        sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND, 5)
        #sizer.Add(self.button, 0, wx.ALL, 5)

        self.SetSizerAndFit(sizer)
        self.Bind(wx.EVT_CLOSE, self.stop)

        self.canvas.draw()

        #self.Bind(wx.EVT_BUTTON, self.stop, self.button)
        #self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.page_stop, parent.parent)

    def build(self, model, model_2, y, y2, delta, localization):
        if self.flag1:
            self.ani._stop()
            self.x_axis = []
            self.x2_axis = []
            self.y_axis = []
            self.y2_axis = []
        self.delta = delta
        self.ani = animation.FuncAnimation(self.figure, self.animate,
                                           fargs=(self.x_axis, self.x2_axis, self.y_axis, self.y2_axis, model, model_2, y, y2, localization), interval=500)
        self.flag1 = True
        self.ani._start()

    def close(self):
        self.ani._stop()

    def stop(self, event):
        if self.parent == self.parent.parent.GetCurrentPage():
            if self.flag == False and self.flag1 == True:
                self.ani.event_source.stop()
                self.flag = True
                self.button.SetLabel('Start')
            elif self.flag == True and self.flag1 == True:
                self.ani.event_source.start()
                self.flag = False
                self.button.SetLabel('Stop')

    #Animation
    def animate(self, i, x_axis, x2_axis, y_axis, y2_axis, model, model2, y, y2, localization):
        #Data query
        self.now = datetime.now()
        self.now_delta = self.now - timedelta(minutes=self.delta)
        if not self.x_axis:
            with session_scope() as s:
                value = s.query(y).order_by(model.Datetime.desc()).filter(model.Datetime < self.now).filter(model.Datetime > self.now_delta).all()
                value2 = s.query(y2).order_by(model2.Datetime.desc()).filter(model2.Datetime > self.now_delta).filter(model2.Datetime < self.now).all()
                time = s.query(model.Datetime).order_by(model.Datetime.desc()).filter(model.Datetime > self.now_delta).filter(model.Datetime < self.now).all()
                time2 = s.query(model2.Datetime).order_by(model2.Datetime.desc()).filter(model2.Datetime > self.now_delta).filter(model2.Datetime < self.now).all()

            for i in reversed(value):
                self.y_axis.append(i[0])
            for i in reversed(value2):
                self.y2_axis.append(i[0])
            for i in reversed(time):
                self.x_axis.append(i[0])
            for i in reversed(time2):
                self.x2_axis.append(i[0])

        if self.x_axis:
            with session_scope() as s:
                # value = s.query(y).order_by(model.Datetime.desc()).first()
                # value2 = s.query(y2).order_by(model2.Datetime.desc()).first()
                # time = s.query(model.Datetime).order_by(model.Datetime.desc()).first()
                # time2 = s.query(model2.Datetime).order_by(model2.Datetime.desc()).first()

                value = s.query(y).filter(model.Datetime > self.x_axis[-1]).all()
                value2 = s.query(y2).filter(model2.Datetime > self.x2_axis[-1]).all()
                time = s.query(model.Datetime).filter(model.Datetime > self.x_axis[-1]).all()
                time2 = s.query(model2.Datetime).filter(model2.Datetime > self.x2_axis[-1]).all()
                # if type(time) != type(None) and type(value) != type(None):
                #     time = time[0]
                #     time2 = time2[0]
                #     value = round(value[0], 2)
                #     value2 = round(value2[0], 2)

                for i in value:
                    self.y_axis.append(i[0])
                for i in value2:
                    self.y2_axis.append(i[0])
                for i in time:
                    self.x_axis.append(i[0])
                for i in time2:
                    self.x2_axis.append(i[0])

                    # x_axis.append(time)
                    # x2_axis.append(time2)
                    # y_axis.append(value)
                    # y2_axis.append(value2)

        if len(x_axis) < len(y_axis):
            delta = len(y_axis) - len(x_axis)
            y_axis = y_axis[:-delta]
        elif len(x_axis) > len(y_axis):
            delta = len(x_axis) - len(y_axis)
            x_axis = x_axis[:-delta]

        if len(x2_axis) < len(y2_axis):
            delta = len(y2_axis) - len(x2_axis)
            y_axis = y_axis[:-delta]
        elif len(x2_axis) > len(y2_axis):
            delta = len(x2_axis) - len(y2_axis)
            x2_axis = x2_axis[:-delta]



        #Capacity of points
        x_axis = x_axis[-self.delta*60:]
        x2_axis = x2_axis[-self.delta*60:]
        y_axis = y_axis[-self.delta*60:]
        y2_axis = y2_axis[-self.delta*60:]

        #Clear Axis
        self.axis.clear()
        self.axis2.clear()

        #Set axis 2 format
        self.axis.set_title(model.Datetime.name + ' vs ' + y.name + ' vs ' + y2.name)
        self.axis.set_xlim(min(x_axis), max(x_axis))
        self.axis.set_xlabel(model.Datetime.name)
        self.axis.set_ylabel(y.name)
        line_1 = self.axis.plot(x_axis, y_axis, linewidth=self.line_width, label=y.name)
        # self.axis.annotate(str(value), xy=(time, value), xytext=(10, -2), textcoords='offset pixels',
        #                    bbox=dict(boxstyle=custom_box_style, alpha=0.2))

        #Set Axis 2 Format
        self.axis2.set_xlim(min(x2_axis), max(x2_axis))
        self.axis2.set_xlabel(model.Datetime.name)
        self.axis2.set_ylabel(y2.name)
        line_2 = self.axis2.plot(x2_axis, y2_axis, linewidth=self.line_width, color='G', label=y2.name)
        # self.axis2.annotate(str(value2), xy=(time, value2), xytext=(10, -2), textcoords='offset pixels',
        #                    bbox=dict(boxstyle=custom_box_style, alpha=0.2))

        #Get lines and labels for legends
        lines = line_1 + line_2
        labels = [l.get_label() for l in lines]

        #Turn of scientific notation
        self.axis.yaxis.set_major_formatter(mticker.ScalarFormatter())
        self.axis.yaxis.get_major_formatter().set_scientific(False)
        self.axis.yaxis.get_major_formatter().set_useOffset(False)
        self.axis2.yaxis.set_major_formatter(mticker.ScalarFormatter())
        self.axis2.yaxis.get_major_formatter().set_scientific(False)
        self.axis2.yaxis.get_major_formatter().set_useOffset(False)

        #Set legend and turn axes 2 grid off
        self.axis2.legend(lines, labels,  loc=localization)
        self.axis2.grid(False)

        # Format plot
        self.figure.canvas.mpl_connect('close_event', self.close)
        #tm.sleep(1)

and this is the instrument panels.

class ccn(scrolled.ScrolledPanel):
    def __init__(self, parent, title):
        super(ccn, self).__init__(parent, name=title)
        self.parent = parent
        self.visa = visa_instruments()
        self.SetupScrolling()
        locations = ['Best', 'Upper left', 'Upper right', 'Lower left', 'Lower right', 'Center', 'Upper center',
                     'Lower center', 'Center left', 'Center right']

        EVT_RESULT(self, self.update_display)

        mainsizer = wx.BoxSizer(wx.VERTICAL)
        current_ss_sizer = wx.BoxSizer(wx.HORIZONTAL)
        stage_sizer = wx.BoxSizer(wx.HORIZONTAL)
        concentration_sizer = wx.BoxSizer(wx.HORIZONTAL)
        data_header = wx.StaticBoxSizer(wx.VERTICAL, self, label='Data:')
        plot_border = wx.StaticBoxSizer(wx.VERTICAL, self, label='Live Plot')
        plot_selector_sizer = wx.BoxSizer(wx.HORIZONTAL)
        delta_sizer = wx.BoxSizer(wx.HORIZONTAL)
        cmd_sizer = wx.BoxSizer(wx.HORIZONTAL)
        gmd_sizer = wx.BoxSizer(wx.HORIZONTAL)

        variable_1 = wx.StaticText(self, label='Variable 1: ')
        variable_2 = wx.StaticText(self, label='Variable 2: ')
        time_scale = wx.StaticText(self, label='Time Scale(min): ')
        leyend_location_text = wx.StaticText(self, label='Leyend Location: ')

        current_ss_text = wx.StaticText(self, label='Current SS:')
        first_stage_text = wx.StaticText(self, label='First Stage Mon(V):')
        concentration_text = wx.StaticText(self, label='CCN Number Concentration(#/m^3):')
        delta_text = wx.StaticText(self, label='Delta T(C): ')
        cmd_text = wx.StaticText(self, label='CMD: ')
        gmd_text = wx.StaticText(self, label='GMD: ')

        self.current_ss_value = wx.StaticText(self, label='N/A')
        self.stage_value = wx.StaticText(self, label='N/A')
        self.concentration_value = wx.StaticText(self, label='N/A')
        self.delta_value = wx.StaticText(self, label='N/A')
        self.cmd_value = wx.StaticText(self, label='N/A')
        self.gmd_values = wx.StaticText(self, label='N/A')
        self.plot = live_panel_2(self)

        self.x_data_selector = wx.ComboBox(self, value='X-Axis Data')
        self.y_data_selector = wx.ComboBox(self, value='Y-Axis Data')
        self.time_scale = wx.ComboBox(self, value='Time Scale', size=(80, -1))
        self.button = wx.Button(self, label='Enter')
        self.leyend_location_selector = wx.ComboBox(self)

        self.leyend_location_selector.Append(locations)

        time_range = range(60)
        for i in time_range:
            self.time_scale.Append(str(i+1), i+1)

        current_ss_sizer.Add(current_ss_text, 0, wx.ALL, 5)
        current_ss_sizer.Add(self.current_ss_value,  0, wx.ALL|wx.ALIGN_RIGHT, 5)

        concentration_sizer.Add(concentration_text, 0, wx.ALL, 5)
        concentration_sizer.Add(self.concentration_value, 0, wx.ALL|wx.ALIGN_RIGHT, 5)

        stage_sizer.Add(first_stage_text, 0, wx.ALL, 5)
        stage_sizer.Add(self.stage_value, 0, wx.ALL|wx.ALIGN_RIGHT, 5)

        delta_sizer.Add(delta_text, 0, wx.ALL, 5)
        delta_sizer.Add(self.delta_value, 0, wx.ALL|wx.ALIGN_RIGHT, 5)

        cmd_sizer.Add(cmd_text, 0, wx.ALL, 5)
        cmd_sizer.Add(self.cmd_value, 0, wx.ALL|wx.ALIGN_RIGHT, 5)

        gmd_sizer.Add(gmd_text, 0, wx.ALL, 5)
        gmd_sizer.Add(self.gmd_values, 0, wx.ALL|wx.ALIGN_RIGHT, 5)

        data_header.Add(current_ss_sizer, 0, wx.ALL, 5)
        data_header.Add(stage_sizer, 0, wx.ALL, 5)
        data_header.Add(concentration_sizer, 0, wx.ALL, 5)
        data_header.Add(delta_sizer, 0, wx.ALL, 5)
        data_header.Add(cmd_sizer, 0, wx.ALL, 5)
        data_header.Add(gmd_sizer, 0, wx.ALL, 5)

        plot_selector_sizer.Add(variable_1, 0, wx.ALL, 5)
        plot_selector_sizer.Add(self.x_data_selector, 0, wx.ALL, 5)
        plot_selector_sizer.Add(variable_2, 0, wx.ALL, 5)
        plot_selector_sizer.Add(self.y_data_selector, 0, wx.ALL, 5)
        plot_selector_sizer.Add(time_scale, 0, wx.ALL, 5)
        plot_selector_sizer.Add(self.time_scale, 0, wx.ALL, 5)
        plot_selector_sizer.Add(leyend_location_text, 0, wx.ALL, 5)
        plot_selector_sizer.Add(self.leyend_location_selector, 0, wx.ALL, 5)
        plot_selector_sizer.Add(self.button, 0, wx.ALL | wx.ALIGN_RIGHT, 5)

        plot_border.Add(plot_selector_sizer, 0, wx.ALL, 5)
        plot_border.Add(self.plot, 0, wx.ALL, 5)

        mainsizer.Add(data_header,0,wx.ALL|wx.EXPAND,5)
        mainsizer.Add(plot_border,0,wx.ALL|wx.EXPAND,5)
        #mainsizer.Add(self.logbox, 0, wx.ALL|wx.EXPAND, 5)

        self.SetSizeHints(200, 10, 700, 700)  # SetSizeHints(minW, minH, maxW, maxH)
        self.SetSizerAndFit(mainsizer)

        DataThread(self)
        #logupdater(self.logbox)

        self.x_selector(wx.EVT_BUTTON)
        self.Bind(wx.EVT_CLOSE, self.stop)
        self.Bind(wx.EVT_BUTTON, self.builder, self.button)
        #self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.plot.stop, self.parent)

    def stop_plot(self, event):
        self.plot.stop(event)

    def builder(self, event):
        x_selection = self.x_data_selector.GetCurrentSelection()
        y_selection = self.y_data_selector.GetCurrentSelection()

        model = ccn_model
        y = self.x_data_selector.GetClientObject(x_selection)
        y2 = self.y_data_selector.GetClientObject(y_selection)
        location = self.leyend_location_selector.GetStringSelection().lower()

        delta = self.time_scale.GetStringSelection()

        self.plot.build(model, model, y, y2, int(delta), location)

    def x_selector(self, event):
        model = ccn_model
        self.x_data_selector.Clear()
        columns = model_columns(model)
        for i in columns:
            if i[0] != 'Datetime':
                self.x_data_selector.Append(i[0], i[1])
        self.y_selector(model)

    def y_selector(self, model):
        self.y_data_selector.Clear()
        columns = model_columns(model)

        for i in columns:
            if i[0] != 'Datetime':
                self.y_data_selector.Append(i[0], i[1])

    def stop(self, event):
        self.Destroy()

    def update_display(self, data):
        if type(data) is not type(None):
            if self.current_ss_value:
                self.current_ss_value.SetLabel(str(data.Current_ss))
            if self.stage_value:
                self.stage_value.SetLabel(str(data.first_Stage_Mon))
            if self.concentration_value:
                self.concentration_value.SetLabel(str(data.CCN_Number_Conc))
            if self.delta_value:
                self.delta_value.SetLabel(str(data.Delta_T))
            if self.cmd_value:
                self.cmd_value.SetLabel(str(data.CMD))
            if self.gmd_values:
                self.gmd_values.SetLabel(str(data.GMD))

if the code of the first panel(frame) is needed just tell me.

So' i would expect that if I'm browsing trough the pages the live plot of the current pages stops and the live plot of the page that im going starts if they where already started.

Upvotes: 0

Views: 39

Answers (1)

Lemanuel Colon
Lemanuel Colon

Reputation: 72

I continues my research and i solved this by adding event.skip at the end of the method.

    def stop(self, event):
        if self.ani:
            if self.flag == False and self.flag1 == True and self.parent != self.parent.parent.GetCurrentPage():
                self.ani.event_source.stop()
                self.flag = True
                #self.button.SetLabel('Start')
            elif self.flag == True and self.flag1 == True and self.parent == self.parent.parent.GetCurrentPage():
                self.ani.event_source.start()
                self.flag = False
                #self.button.SetLabel('Stop')
        event.Skip()

Also worked on the logic but if i haven't started a live plot in a panel i receive

Traceback (most recent call last):
  File "C:\Users\ACAS\PycharmProjects\ACAS\Main\GUI\plotter.py", line 172, in stop
    if self.ani:
AttributeError: 'live_panel_2' object has no attribute 'ani'

I want to check if the self.ani exist but the if does not do the work.

Upvotes: 0

Related Questions