0

I am using the MPL widget that comes with QT in the Python(x,y) package. I am attempting to refresh or redraw my plot with new data. The method fig.canvas.draw() refreshes the main plot only. The subplots are where my issue lies. The previous subplots and everything associated with them (axes scale, annotations, etc) are left on the chart. When I refresh, new subplot data are plotted over the old data, creating quite a mess. Everything associated with the main plot gets redrawn correctly. I have tried everything that I know to try, including clf, and cla. How does one refresh subplots with the QT MPL Widget that is included in Python(x,y)?

Here's my code:

def mpl_plot(self, plot_page, replot = 0):  #Data stored in lists  

    if plot_page == 1:             #Plot 1st Page                        
        plt = self.mplwidget.axes                                
        fig = self.mplwidget.figure #Add a figure           

    if plot_page == 2:          #Plot 2nd Page
        plt = self.mplwidget_2.axes 
        fig = self.mplwidget_2.figure    #Add a figure

    if plot_page == 3:           #Plot 3rd Page
        plt = self.mplwidget_3.axes 
        fig = self.mplwidget_3.figure    #Add a figure    

    if replot == 1:

        #self.mplwidget_2.figure.clear()          

        print replot

    par1 = fig.add_subplot(111)
    par2 = fig.add_subplot(111)      


    #Add Axes
    ax1 = par1.twinx()        
    ax2 = par2.twinx() 



    impeller = str(self.comboBox_impellers.currentText())  #Get Impeller
    fac_curves = self.mpl_factory_specs(impeller)    
    fac_lift = fac_curves[0]        
    fac_power = fac_curves[1]
    fac_flow = fac_curves[2]
    fac_eff = fac_curves[3]        
    fac_max_eff = fac_curves[4]
    fac_max_eff_bpd = fac_curves[5]
    fac_ranges = self.mpl_factory_ranges()
    min_range = fac_ranges[0]
    max_range = fac_ranges[1]
    #bep = fac_ranges[2]
    #Plot Chart
    plt.hold(False)    #Has to be included for  multiple curves
    #Plot Factory Pressure
    plt.plot(fac_flow, fac_lift, 'b', linestyle = "dashed", linewidth = 1)



    #Plot Factory Power
    ax1.plot(fac_flow, fac_power, 'r', linestyle = "dashed", linewidth = 1)       
    ax2.plot(fac_flow, fac_eff, 'g', linestyle = "dashed", linewidth = 1)


    #Move spines
    ax2.spines["right"].set_position(("outward", 25))
    self.make_patch_spines_invisible(ax2)
    ax2.spines["right"].set_visible(True)  
    #Plot x axis minor tick marks
    minorLocatorx = AutoMinorLocator()        
    ax1.xaxis.set_minor_locator(minorLocatorx)
    ax1.tick_params(which='both', width= 0.5)
    ax1.tick_params(which='major', length=7)
    ax1.tick_params(which='minor', length=4, color='k')

    #Plot y axis minor tick marks
    minorLocatory = AutoMinorLocator()
    plt.yaxis.set_minor_locator(minorLocatory)
    plt.tick_params(which='both', width= 0.5)
    plt.tick_params(which='major', length=7)
    plt.tick_params(which='minor', length=4, color='k')
    #Make Border of Chart White


    #Plot Grid        
    plt.grid(b=True, which='both', color='k', linestyle='-') 

    #set shaded Area 
    plt.axvspan(min_range, max_range, facecolor='#9BE2FA', alpha=0.5)    #Yellow rectangular shaded area

    #Set Vertical Lines
    plt.axvline(fac_max_eff_bpd, color = '#69767A')

    #BEP MARKER   *** Can change marker style if needed
    bep = fac_max_eff * 0.90     #bep is 90% of maximum efficiency point

    bep_corrected = bep * 0.90   # We knock off another 10% to place the arrow correctly on chart

    ax2.annotate('BEP', xy=(fac_max_eff_bpd, bep_corrected), xycoords='data',   #Subtract 2.5 shows up correctly on chart
            xytext=(-50, 30), textcoords='offset points',
            bbox=dict(boxstyle="round", fc="0.8"),
            arrowprops=dict(arrowstyle="-|>",
                            shrinkA=0, shrinkB=10,
                            connectionstyle="angle,angleA=0,angleB=90,rad=10"),
                    )
    #Set Scales         
    plt.set_ylim(0,max(fac_lift) + (max(fac_lift) * 0.40))    #Pressure 
    #plt.set_xlim(0,max(fac_flow))

    ax1.set_ylim(0,max(fac_power) + (max(fac_power) * 0.40))     #Power
    ax2.set_ylim(0,max(fac_eff) + (max(fac_eff) * 0.40))    #Effiency


    # Set Axes Colors
    plt.tick_params(axis='y', colors='b')
    ax1.tick_params(axis='y', colors='r')
    ax2.tick_params(axis='y', colors='g')

    # Set Chart Labels        
    plt.set_xlabel("BPD")
    plt.set_ylabel("Feet" , color = 'b')

    #To redraw plot


    fig.canvas.draw()

def mpl_plot(self, plot_page, replot = 0):  #Data stored in lists  

    if plot_page == 1:             #Plot 1st Page                        
        plt = self.mplwidget.axes                                
        fig = self.mplwidget.figure #Add a figure           

    if plot_page == 2:          #Plot 2nd Page
        plt = self.mplwidget_2.axes 
        fig = self.mplwidget_2.figure    #Add a figure

    if plot_page == 3:           #Plot 3rd Page
        plt = self.mplwidget_3.axes 
        fig = self.mplwidget_3.figure    #Add a figure    

    if replot == 1:

        #self.mplwidget_2.figure.clear()          

        print replot

    par1 = fig.add_subplot(111)
    par2 = fig.add_subplot(111)      


    #Add Axes
    ax1 = par1.twinx()        
    ax2 = par2.twinx() 



    impeller = str(self.comboBox_impellers.currentText())  #Get Impeller
    fac_curves = self.mpl_factory_specs(impeller)    
    fac_lift = fac_curves[0]        
    fac_power = fac_curves[1]
    fac_flow = fac_curves[2]
    fac_eff = fac_curves[3]        
    fac_max_eff = fac_curves[4]
    fac_max_eff_bpd = fac_curves[5]
    fac_ranges = self.mpl_factory_ranges()
    min_range = fac_ranges[0]
    max_range = fac_ranges[1]
    #bep = fac_ranges[2]
    #Plot Chart
    plt.hold(False)    #Has to be included for  multiple curves
    #Plot Factory Pressure
    plt.plot(fac_flow, fac_lift, 'b', linestyle = "dashed", linewidth = 1)



    #Plot Factory Power
    ax1.plot(fac_flow, fac_power, 'r', linestyle = "dashed", linewidth = 1)       
    ax2.plot(fac_flow, fac_eff, 'g', linestyle = "dashed", linewidth = 1)


    #Move spines
    ax2.spines["right"].set_position(("outward", 25))
    self.make_patch_spines_invisible(ax2)
    ax2.spines["right"].set_visible(True)  
    #Plot x axis minor tick marks
    minorLocatorx = AutoMinorLocator()        
    ax1.xaxis.set_minor_locator(minorLocatorx)
    ax1.tick_params(which='both', width= 0.5)
    ax1.tick_params(which='major', length=7)
    ax1.tick_params(which='minor', length=4, color='k')

    #Plot y axis minor tick marks
    minorLocatory = AutoMinorLocator()
    plt.yaxis.set_minor_locator(minorLocatory)
    plt.tick_params(which='both', width= 0.5)
    plt.tick_params(which='major', length=7)
    plt.tick_params(which='minor', length=4, color='k')
    #Make Border of Chart White


    #Plot Grid        
    plt.grid(b=True, which='both', color='k', linestyle='-') 

    #set shaded Area 
    plt.axvspan(min_range, max_range, facecolor='#9BE2FA', alpha=0.5)    #Yellow rectangular shaded area

    #Set Vertical Lines
    plt.axvline(fac_max_eff_bpd, color = '#69767A')

    #BEP MARKER   *** Can change marker style if needed
    bep = fac_max_eff * 0.90     #bep is 90% of maximum efficiency point

    bep_corrected = bep * 0.90   # We knock off another 10% to place the arrow correctly on chart

    ax2.annotate('BEP', xy=(fac_max_eff_bpd, bep_corrected), xycoords='data',   #Subtract 2.5 shows up correctly on chart
            xytext=(-50, 30), textcoords='offset points',
            bbox=dict(boxstyle="round", fc="0.8"),
            arrowprops=dict(arrowstyle="-|>",
                            shrinkA=0, shrinkB=10,
                            connectionstyle="angle,angleA=0,angleB=90,rad=10"),
                    )
    #Set Scales         
    plt.set_ylim(0,max(fac_lift) + (max(fac_lift) * 0.40))    #Pressure 
    #plt.set_xlim(0,max(fac_flow))

    ax1.set_ylim(0,max(fac_power) + (max(fac_power) * 0.40))     #Power
    ax2.set_ylim(0,max(fac_eff) + (max(fac_eff) * 0.40))    #Effiency


    # Set Axes Colors
    plt.tick_params(axis='y', colors='b')
    ax1.tick_params(axis='y', colors='r')
    ax2.tick_params(axis='y', colors='g')

    # Set Chart Labels        
    plt.set_xlabel("BPD")
    plt.set_ylabel("Feet" , color = 'b')

    #To redraw plot


    fig.canvas.draw()
Mike C.
  • 1,761
  • 2
  • 22
  • 46

1 Answers1

1

From the example it is not clear how self.mpl_widget.axes is created. It is not used and as explained below, drawing to an old reference of an axes instance might cause the problem.

Because mpl_widget.axes is not used at all I would suggest to not hold a reference on the axes. Then the use of twinx in the example is not correct. The following could work:

if plot_page == 1:             #Plot 1st Page
    widget = self.mplwidget
if plot_page == 2:          #Plot 2nd Page
    widget = self.mplwidget_3
if plot_page == 3:           #Plot 3rd Page
    widget = self.mplwidget_3
if replot == 1:
    widget.figure.clear()
ax1 = widget.figure.add_subplot(111)
ax2 = ax1.twinx()

...

widget.figure.canvas.draw()

Another issue is that self.mpl_widgetXX.axes is assigned to plt and further below in the example plt is used to draw the new data. Because self.mpl_widgetXX.axes is not updated to contain one of the newly created axes instances, the example code draws to an old axes, thus potentially leading to the effects described in the question. You should only use ax1 and ax2 for plotting and tick setup and widget.figure to access the figure instance.

Niemerds
  • 932
  • 7
  • 12
  • When I moved the plt axis to a subplot I lost my vertical grid lines and mpl is now showing an unwanted axis. Do you know a solution to either of these issues? – Mike C. Aug 20 '16 at 13:00