Skip to content
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

wellmap.show(toml) prints map layout twice #19

Open
rediaz111 opened this issue Jun 9, 2021 · 3 comments
Open

wellmap.show(toml) prints map layout twice #19

rediaz111 opened this issue Jun 9, 2021 · 3 comments

Comments

@rediaz111
Copy link

rediaz111 commented Jun 9, 2021

`f = '~/4MU_Kinetic_Purified_Quick_3641_singleread_20210608_pH7_Na2CO3.xlsx'

f_toml = '~/4MU_Kinetic_Purified_Quick_3641_singleread_20210608_pH7_Na2CO3.toml'

wellmap.show(f_toml)`
Screen Shot 2021-06-09 at 11 50 16

@kalekundert
Copy link
Owner

I looked into this today, but I'm on the fence about whether or not to fix it. The issue is that show() both creates and returns a figure. Jupyter somehow notices when the figure is created in the first place, and shows it. Then Jupyter also notices when the figure is returned, and shows it again. As far as I can tell, there's no way to prevent Jupyter from noticing when the figure is first created (that doesn't also break other things). So the only way to fix this would be to create a second version of the show() function that doesn't return anything. This version of the function wouldn't be useful in any other context. That might be the best thing to do (after all, Jupyter is the primary use-case for this function, although it—and it's return value—are used elsewhere), but it doesn't feel right.

Also, there's a simple but non-obvious way to avoid this problem: put a semi-colon after wellmap.show(f_toml). This tells Jupyter to not display the value returned by the function, so the plot will only be displayed once. That's pretty easy, but I know it's annoying to have to remember stupid things like that.

I need to think more about what to do. Let me know if you have any thoughts, as well!

@kalekundert
Copy link
Owner

I learned more about what's going on with this issue today. There are two ways to create figures with matplotlib:

With plain matplotlib:

from matplotlib.figure import Figure
fig = Figure()

With matplotlib.pyplot:

import matplotlib.pyplot as plt
fig = plt.figure()

There's a subtle difference between these two approaches, which is that the latter prepares the figure to be displayed by the built-in matplotlib GUI. Because Jupyter is the GUI when it's running, that means that the latter informs Jupyter about the figure and the former does not. Ultimately that leads to the figure being shown twice by Jupyter. So by avoiding the pyplot interface, we can avoid this problem. Avoiding the pyplot interface is appealing anyways, because I'd rather not invoke any GUI code unless I really want to show a GUI.

Unfortunately, figures created with plain matplotlib cannot be used with the built-in matplotlib GUI, and that's still an important use case. See matplotlib/matplotlib#19956 and matplotlib/matplotlib#14024. The immediate solution to this problem is to write my own GUI event loop. I've actually wanted to do that anyways, because it'd let me do some cool things like showing each plot in its own pane and automatically updating the GUI when the underlying file changes. The biggest problem is finding a way to do this without turning installation into a huge chore. I might look into PyQT6. It seems like the most popular GUI framework for python, and it can be installed from PyPI.

@bifidotftw
Copy link

TLDR: Use wellmap.show("std_curve.toml"); which has a semicolon at the end, instead of wellmap.show("std_curve.toml").
For me that is an easy enough workaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants