I'm trying to manufacture a button that, when clicked, will begin a loop that triggers some data collection and several live, updating plots.
I thought I had the plots and the loops sorted out well, but as soon as I try to incorporate the button things go south. My plots are now in my JupyterLab log, not in the command line where they had been appearing (and updating) before. Has anyone encountered this issue before? Or have a potential workaround?
Here is how my code is structured:
import csv
from datetime import datetime
import pyvisa as visa
import serial
import time
from time import sleep
import numpy as np
from IPython import display
from IPython.display import clear_output
import matplotlib.pyplot as plt
import sys
import ipywidgets as widgets
import voila
from ipywidgets import ToggleButtons
from ipywidgets import Button
import asyncio
import nest_asyncio
from asyncio import coroutine
nest_asyncio.apply()
%matplotlib widget #only widget, not notebook or inline, will keep my plots interactive
async def mainexp(n, s): #these all lead to different loops that collect + plot data smoothly
plt.clf()
data = asyncio.create_task(datacollect(n, s))
graphr = asyncio.create_task(graphloopr(n, s))
graphv = asyncio.create_task(graphloopv(n, s))
await asyncio.sleep(s)
## button to start data collection + plotting
startbutton = widgets.Button(description="Start")
out = widgets.Output()
def on_button_clicked(b):
with out:
clear_output(True)
print("Hello")
asyncio.run(datarun(10, 1))
#show()
startbutton.on_click(on_button_clicked)
display(startbutton, out)
At this point my machine tells me it is collecting data, "Hello" prints...the only issue is when it comes to graphing--and it's stored as a blank axis in my list of log entries...?
Related
import camelot
import pandas as pd
import matplotlib
file = 'foo.pdf'
tables = camelot.read_pdf(file, pages='all', flavor='stream')
camelot.plot(tables[0], kind='text').show()
The matplot window opens and suddenly closes in a flash without any user input whatsoever.
I want the window to remain open to examine the contents.
Edit: I am using Windows 11 and Python 3.9, running the code on Pycharm and it's the system interpreter rather than a virtual environment.
Not sure if you ever found your answer, but I will attach what I have found from the following answer by swenzel: https://stackoverflow.com/a/33062819
The plot is opening in a non-blocking window which disappears as soon as the script finishes. You can override this by importing matplotlib and using plot.show(block=True) at the end to show the window as a blocking window, which will keep the script from continuing until closed. See his code snippet below.
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("table.csv")
values = df["blah"]
values.plot()
print 1
df['blahblah'].plot()
print 2
plt.show(block=True)
Your code rewritten would look like the following:
import camelot
import pandas as pd
import matplotlib.pyplot as plt
file = 'foo.pdf'
tables = camelot.read_pdf(file, pages='all', flavor='stream')
camelot.plot(tables[0], kind='text')
plt.show(block=True)
In my Jupyter notebook, I want to execute some long running background jobs and display their status in a cell. I thought, before doing something difficult, I could start with a clock.
I have the following code in one cell
import ipywidgets as widgets
import time
from datetime import datetime as dt
from IPython.display import HTML
from IPython.display import display
import threading
out = widgets.Output()
#out.capture(clear_output=True, wait=True)
def display_time():
now = dt.now().strftime("%H:%M:%S")
display(HTML(f"""<h1><center>{now}</center></h1>"""))
def run_time():
while True:
time.sleep(1)
display_time()
out
When I call run_time() I get the time nicely updated every second, but my notebook is blocking on this cell. So I tried threading.Thread(target=run_time).start() but this somehow only updates the time whenever I do interactions with the notebook. How can I update the notebook even if I do not do any cell interactions?
You want to have a look at ipyrallel to run multi kernels in you notebook.
Here is a solved issue
Here is the documentation
I'm not so much experienced with Python and Matplotlib and ipywidgets. I'm trying to build a jupyter interactive notebook that shows a map and then overplots different marine isobtahs (lines of constant depths). I would like to show/hide some lines with the help of an array of checkboxes. The problem is trying to redraw the map once some lines are selected. So the strategy is
schematically:
%matplotlib inline
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from ipywidgets import *
from IPython.display import display
load_map() # loads isobaths from files (arrays of lat,lon pairs)
def draw_mapa(): #draw the map
mapa = Basemap()
mapa.drawcoastlines()
def draw_level(level): #draw a specific line (z=level)
mapa.plot(x,y)
def on_level_change(change): #handler of checkboxes
draw_mapa()
if button is True:
draw_level(level)
display(container) #container with all the checkboxes
#attaching handler to checkbox through .observe() method
for ilevel in checkboxes:
ilevel.observe(on_level_change,names='value')
Everything is ok except when I start to interact with the checkboxes. Each time I select/deselect a box a new additonal map with the corrected isobaths appears.
So the question is how is the way to "overplot" correctly in one figure avoiding creating new instances each time I check a box.
Thanks
Is there a way to use and plot with opencv2 with ipython notebook?
I am fairly new to python image analysis. I decided to go with the notebook work flow to make nice record as I process and it has been working out quite well using matplotlib/pylab to plot things.
An initial hurdle I had was how to plot things within the notebook. Easy, just use magic:
%matplotlib inline
Later, I wanted to perform manipulations with interactive plots but plotting in a dedicated window would always freeze. Fine, I learnt again that you need to use magic. Instead of just importing the modules:
%pylab
Now I have moved onto working with opencv. I am now back to the same problem, where I either want to plot inline or use dedicated, interactive windows depending on the task at hand. Is there similar magic to use? Is there another way to get things working? Or am I stuck and need to just go back to running a program from IDLE?
As a side note: I know that opencv has installed correctly. Firstly, because I got no errors either installing or importing the cv2 module. Secondly, because I can read in images with cv2 and then plot them with something else.
This is my empty template:
import cv2
import matplotlib.pyplot as plt
import numpy as np
import sys
%matplotlib inline
im = cv2.imread('IMG_FILENAME',0)
h,w = im.shape[:2]
print(im.shape)
plt.imshow(im,cmap='gray')
plt.show()
See online sample
For a Jupyter notebook running on Python 3.5 I had to modify this to:
import io
import cv2
import numpy as np
from IPython.display import clear_output, Image, display
import PIL.Image
def showarray(a, fmt='jpeg'):
a = np.uint8(np.clip(a, 0, 255))
f = io.BytesIO()
PIL.Image.fromarray(a).save(f, fmt)
display(Image(data=f.getvalue()))
There is also that little function that was used into the Google Deepdream Notebook:
import cv2
import numpy as np
from IPython.display import clear_output, Image, display
from cStringIO import StringIO
import PIL.Image
def showarray(a, fmt='jpeg'):
a = np.uint8(np.clip(a, 0, 255))
f = StringIO()
PIL.Image.fromarray(a).save(f, fmt)
display(Image(data=f.getvalue()))
Then you can do :
img = cv2.imread("an_image.jpg")
And simply :
showarray(img)
Each time you need to render the image in a cell
Is there a way that I can make a matplotlib figure disappear and reappear in response to some event? (i.e. a keypress)
I've tried using fig.set_visible(False) but that doesn't seem to do anything for me.
Simple example of code:
import matplotlib
import matplotlib.pyplot as plt
fig=matplotlib.pyplot.figure(figsize=(10, 10))
# Some other code will go here
def toggle_plot():
# This function is called by a keypress to hide/show the figure
fig.set_visible(not fig.get_visible()) # This doesn't work for me
plt.show()
The reason I'm trying to do this is because I have a bunch of plots/animations running on the figure that show the output of a running simulation, but displaying them all the time slows down my computer a lot.
Any ideas?
You have to call plt.draw() to actually instantiate any changes. This should work:
def toggle_plot():
# This function is called by a keypress to hide/show the figure
fig.set_visible(not fig.get_visible())
plt.draw()
There is a small guide to image toggling in the matplotlib gallery. I was able to use set_visible and get_visible() as shown in the example. The calls in the matplotlib gallery example are on AxesImage instances, rather than Figure instances, as in your example code. That is my guess as to why it did not work for you.
You can you use the Toplevel() widget from the tkinter library together with the matplotlib backend.
Here is a full example:
from tkinter import *
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
fig,(ax) = plt.subplots()
x = np.linspace(0, 2 * np.pi)
y = np.transpose([np.sin(x)])
ax.plot(y)
graph = Toplevel()
canvas = FigureCanvasTkAgg(fig,master=graph)
canvas.get_tk_widget().grid()
canvas.show()
import pdb; pdb.set_trace()
Calling:
graph.withdraw()
will hide the plot, and:
graph.deiconify()
will display it again.