New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

matplotlib loosing axis labels and legend after update #242

Closed
gh0st42 opened this Issue Sep 2, 2017 · 11 comments

Comments

Projects
None yet
2 participants
@gh0st42

gh0st42 commented Sep 2, 2017

After updating a plot xlabel, ylabel and legend is lost. Since updatePlot() does not return an axis object one cannot add the information again.

The following code triggers the bug:

from numpy import sin, pi, arange
from appJar import gui

def press(btn):
    x = arange(0.0, 3.0, 0.01)
    y = sin(3*pi*x)
    a = app.updatePlot("p1", x, y)
    print a

x = arange(0.0, 3.0, 0.01)
y = sin(2*pi*x)

app = gui()
axes = app.addPlot("p1", x, y)
axes.legend(['key data'])
axes.set_xlabel("bla")
app.addButton("Update", press)
app.go()
@jarvisteach

This comment has been minimized.

Owner

jarvisteach commented Sep 2, 2017

Calling app.updatePlot() modifies the existing axes - so its the same axes object you already have.
However, I will modify .updatePlot() to return the axes object as well.

The issue is that the canvas needs redrawing.

If you modify the function to include:

axes.legend(['key data'])
axes.set_xlabel("bla")

Then they are added to the plot, but not shown until the canvas is redrawn - try resizing it to prove that.

To do it programatically, you'll need to force a redraw, after updating the axes: app.refreshPlot("p1")

So, the full function would look like:

def press(btn):
    x = arange(0.0, 3.0, 0.01)
    y = sin(3*pi*x)
    app.updatePlot("p1", x, y)
    axes.legend(['key data'])
    axes.set_xlabel("bla")
    app.refreshPlot("p1")
@jarvisteach

This comment has been minimized.

Owner

jarvisteach commented Sep 2, 2017

That's quite a mouthful! So you might want to put that bit of code in its own function:

def showLabels(axes):
    axes.legend(['key data'])
    axes.set_xlabel("bla")
    app.refreshPlot("p1")

You can then call that from both places.

FYI - the initial label/legend only show as they're added before the GUI is drawn, I'll update the docs to make this more clear.

@jarvisteach

This comment has been minimized.

Owner

jarvisteach commented Sep 2, 2017

PS. the matplotlib support is very rudimentary - there are various difficulties getting tkinter and matplotlib to play together nicely - I think I've overcome them...

Do let me know how you get on, any issues you come across or features you'd like - I don't have too much experience with it myself, and haven't seen many people use it in appJar.

@jarvisteach jarvisteach added the question label Sep 2, 2017

@jarvisteach

This comment has been minimized.

Owner

jarvisteach commented Sep 2, 2017

This is the updated code I'm going to put in the example (I borrowed bits from yours):

from numpy import sin, pi, arange
from appJar import gui 
import random

def getXY():
    x = arange(0.0, 3.0, 0.01)
    y = sin(random.randint(1,10)*pi*x)
    return x,y 

def press(btn):
    app.updatePlot("p1", *getXY())
    showLabels()

def showLabels():
    axes.legend(['The curve'])
    axes.set_xlabel("X Axes")
    axes.set_ylabel("Y Axes")
    app.refreshPlot("p1")

app = gui()
axes = app.addPlot("p1", *getXY())
showLabels()
app.addButton("Update", press)
app.go()

jarvisteach added a commit that referenced this issue Sep 2, 2017

@gh0st42

This comment has been minimized.

gh0st42 commented Sep 2, 2017

Okay thanks for the quick workaround!
Preserving the axes information when calling updatePlot() would be preferable but having a function to get the axes object for an existing plot would also be okay. Having many global variables or managing all of them in your main program does not seem like good coding practice.

But for a "beta widget" it is really cool to have such a powerful plotting function available in an easy UI lib such as appJar!

@jarvisteach

This comment has been minimized.

Owner

jarvisteach commented Sep 2, 2017

I'll look into preserving the axes information - like I said, don't really know much about it.

There is a fairly generic function for getting widgets, which will then give you access to the axes object:
axes = app.getWidget(app.PLOT, "p1").axes

That will save you having to keep a reference to the axes...

@jarvisteach

This comment has been minimized.

Owner

jarvisteach commented Sep 2, 2017

At the moment, app.updatePlot() really doesn't do much - it just calls 2 matplotlib functions: clear() & plot() followed by a canvas refresh.

I guess the clear() removes the labels/legend as well as the plot.

If this isn't the desired result, then you can perform whichever actions you'd like directly on the axes - just make sure you call app.refreshPlot() at the end to redraw the canvas holding the plot.

I'll keep digging into matplotlib on how to persist the labels and change the plot - let me know if you know how to do this already...

@jarvisteach

This comment has been minimized.

Owner

jarvisteach commented Sep 3, 2017

I've looked into this a bit - there are LOTS of settings a user could configure on the axes.

I can see a way to get the title & x/y labels, and therefore set them again when the axes is updated, I'm struggling to get the legend to work though.

I actually think this might be a feature I don't want. I don't think appJar should be doing any of the work for matplotlib. I've set it up so tkinter & matplotlib play nicely together, and given a way to add a widget containing a plot, the rest should be down to the user.

If the user is changing the plot, then the title/labels/legend may need to be changed as well. If not, then it's not a big job to set them again.

I might provide a boolean flag (defaulting to False) on .updatePlot() that allows the user to request the labels & title are kept (and legend if I can work it out) and leave it at that.

@jarvisteach

This comment has been minimized.

Owner

jarvisteach commented Sep 3, 2017

I've also noticed that the code for Plots seems to be repeated in appJar - that needs to be fixed.

@jarvisteach jarvisteach modified the milestone: 0.09 Sep 5, 2017

jarvisteach added a commit that referenced this issue Sep 16, 2017

jarvisteach added a commit that referenced this issue Sep 17, 2017

Removed duplicate matpoltlib #242
Also added in code to attempt to retain labels.
Some landscape tidying up.
@jarvisteach

This comment has been minimized.

Owner

jarvisteach commented Sep 17, 2017

Now have a flag to 'retain' labels - but doesn't get the legend.

@jarvisteach jarvisteach referenced this issue Oct 14, 2017

Open

MatPlotLib Updates #267

3 of 6 tasks complete
@jarvisteach

This comment has been minimized.

Owner

jarvisteach commented Oct 14, 2017

Closing, see #267

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment