How to update HTML block in IPython - python

This is related to another question I posted, but is more specific (and hopefully gets more specific answers).
I am trying to display png images on an IPython notebook, and update the display as the png files are updated.
One possible solution is below. Unfortunately, my implementation does not update the file, and creates a new HTML block at the end of the old one. What I want instead, is to replace the old HTML block with the new one -i.e. replace the content only.
As example code, I have two notebooks. One notebook generates pngs and saves them in a figures directory.
import os
import glob
import time
import matplotlib.pyplot as plt
import numpy as np
for ix in range(20):
N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = np.pi * (15 * np.random.rand(N))**2 # 0 to 15 point radiuses
fig = plt.figure(figsize=(8,8))
plt.scatter(x, y, s=area, c=colors, alpha=0.5)
fig.savefig(os.path.join("figures", "fig1.png"), bbox_inches="tight")
plt.close(fig)
time.sleep(3)
A second notebook shows the pngs It is supposed top show a single png which updates. Instead it stacks the same png on itself, every time the png is updated.
import os
import time
from IPython.html.widgets import interact, interactive, fixed
from IPython.html import widgets
from IPython.display import clear_output, display, HTML
def get_latest_file_ts(directory="figures", file_name="fig1.png", strip_directory=True):
"""
Continuously check for modifications to the file file_name in directory. If file has been
modified after touched_on, return the Unix timestamp of the modification time.
:param directory: string / the directory where the file is
:param file_name: string / the file name
:param strip_directory: boolean / if True, strip the directory part of the file name
:return:
"""
if strip_directory:
fname = os.path.join(directory, file_name)
else:
fname = file_name
try:
return os.stat(fname).st_mtime
except:
print "FileNotFoundException: Could not find file %s" % fname
return None
def check_if_modified_file(directory="figures", file_name="fig1.png",
touched_on=1420070400, sleep_time=1, strip_directory=True):
"""
Continuously check for modifications to the file file_name in directory. If file has been
modified after touched_on, return the Unix timestamp of the modification time.
:param directory: string / the directory where the file is
:param file_name: string / the file name
:param touched_on: float / the Unix timestamp on which the file was last modified
:param sleep_time: float / wait time between interactions
:param strip_directory: boolean / if True, strip the directory part of the file name
:return:
"""
if strip_directory:
fname = os.path.join(directory, file_name)
else:
fname = file_name
while True:
try:
latest_touch = os.stat(fname).st_mtime
if latest_touch == touched_on:
time.sleep(sleep_time)
else:
return latest_touch
except:
print "FileNotFoundException: Could not find %s" % fname
return None
def show_figs(directory="figures", file_name="fig1.png"):
s = """<figure>\n\t<img src="%s" alt="The figure" width="304" height="228">\n</figure>""" % os.path.join(directory, file_name)
display(HTML(s))
timestamp = get_latest_file_ts(directory="figures", file_name="fig1.png", strip_directory=True)
show_figs(directory="figures", file_name="fig1.png")
cnt = 1
while True and cnt < 4:
timestamp = check_if_modified_file(directory="figures", file_name="fig1.png", touched_on=timestamp, sleep_time=1, strip_directory=True)
display(HTML(""))
show_figs(directory="figures", file_name="fig1.png")
time.sleep(1)
cnt += 1
(as you can see I have added upper limits on the executions of both the generator and consumer loops)
Any help on how to make widgets update HTML content would be awesome.

The problem that you only see the first image is very likely related to caching of the browser. To overcome this issue a simple solution is to add a varying query string to the image src as shown e.g. here.
Thus your show_figs method could look like:
import time
def show_figs(directory="figures", file_name="fig1.png"):
s = """<figure>\n\t<img src="{0}?{1}" alt="The figure" width="304" height="228">\n</figure>""".format(os.path.join(directory, file_name),time.time())
display(HTML(s))
In combination with the clear_output function you should be able to get your updated image.

Related

Add a forEach or foor loop in python code

I am using this library midi2img to generate midi from images
From this library, this is the file am using:
from PIL import Image
import numpy as np
from music21 import instrument, note, chord, stream
lowerBoundNote = 21
def column2notes(column):
notes = []
for i in range(len(column)):
if column[i] > 255/2:
notes.append(i+lowerBoundNote)
return notes
resolution = 0.25
def updateNotes(newNotes,prevNotes):
res = {}
for note in newNotes:
if note in prevNotes:
res[note] = prevNotes[note] + resolution
else:
res[note] = resolution
return res
def image2midi(image_path):
with Image.open(image_path) as image:
im_arr = np.fromstring(image.tobytes(), dtype=np.uint8)
try:
im_arr = im_arr.reshape((image.size[1], image.size[0]))
except:
im_arr = im_arr.reshape((image.size[1], image.size[0],3))
im_arr = np.dot(im_arr, [0.33, 0.33, 0.33])
""" convert the output from the prediction to notes and create a midi file
from the notes """
offset = 0
output_notes = []
# create note and chord objects based on the values generated by the model
prev_notes = updateNotes(im_arr.T[0,:],{})
for column in im_arr.T[1:,:]:
notes = column2notes(column)
# pattern is a chord
notes_in_chord = notes
old_notes = prev_notes.keys()
for old_note in old_notes:
if not old_note in notes_in_chord:
new_note = note.Note(old_note,quarterLength=prev_notes[old_note])
new_note.storedInstrument = instrument.Piano()
if offset - prev_notes[old_note] >= 0:
new_note.offset = offset - prev_notes[old_note]
output_notes.append(new_note)
elif offset == 0:
new_note.offset = offset
output_notes.append(new_note)
else:
print(offset,prev_notes[old_note],old_note)
prev_notes = updateNotes(notes_in_chord,prev_notes)
# increase offset each iteration so that notes do not stack
offset += resolution
for old_note in prev_notes.keys():
new_note = note.Note(old_note,quarterLength=prev_notes[old_note])
new_note.storedInstrument = instrument.Piano()
new_note.offset = offset - prev_notes[old_note]
output_notes.append(new_note)
prev_notes = updateNotes(notes_in_chord,prev_notes)
midi_stream = stream.Stream(output_notes)
midi_stream.write('midi', fp=image_path.split("/")[-1].replace(".jpeg",".mid"))
import sys
image_path = sys.argv[1]
image2midi(image_path)
and this is the code I execute in terminal to geneate midi from image:
python img2midi.py samples/image.png
I need to make the above code to loop over all input images I put inside samples folder and generate midi for each, not just one file at a time.
Any help would be much appreciated.
You can do this by getting list of images from directory and iterate over them.
import sys
import os
sample_folder_path = sys.argv[1]
images = os.listdir(sample_folder_path) # getting all images stored in sample folder
images_path = [os.path.abspath(f"{sample_folder_path}/{image}") for image in images] # gets absolute path for all images
for image_path in images_path:
image2midi(image_path)
Usage:
python img2midi.py folder_path
Here folder_path is the path of folder that contains images. It can

How to set an ImageDocument to be not dirty in dm-script

How do I set an ImageDocument not to be dirty anymore in python dm-script without saving?
I have the python code posted below which can be represented by the following dm-script code.
String file_path = GetApplicationDirectory(0, 1).PathConcatenate("test-image.dm4");
Image img := realimage("test", 4, 64, 64);
ImageDocument doc = img.ImageGetOrCreateImageDocument();
doc.ImageDocumentSaveToFile("Gatan Format", file_path);
doc.ImageDocumentShowAtRect(100, 100, 164, 164);
The (python code below) creates and shows an ImageDocument. The image is saved already. But even saving it directly in DigitalMicrograph with its own module it does not recognize that it is saved. I can link the file manually (by executing dm-script code from python) but I cannot tell the program that the images are not modified.
There is a function ImageDocumentIsDirty(). But this function only returns whether the image is modified or not. I cannot set it.
My program creates a new workspace and loads more than 100 images. When closing DigitalMicrograph, it asks for every single of the 100 images if it should be saved. I cannot leave the user with 100 times clicking No. Especially because the files are saved.
So, how do I tell dm-script that the image is saved already?
try:
import DigitalMicrograph as DM
import numpy as np
import execdmscript
import os
name = "Test image"
file_path = os.path.join(os.getcwd(), "test-image.dm4")
# create image
image_data = np.random.random((64, 64))
image = DM.CreateImage(image_data)
image.SetName(name)
# create, save and show image document
image_doc = image.GetOrCreateImageDocument()
image_doc.SetName(name)
image_doc.SaveToFile("Gatan Format", file_path)
print("Saving image to", file_path)
image_doc.ShowAtRect(100, 100, 164, 164)
# link the image to the file
dmscript = "\n".join((
"for(number i = CountImageDocuments() - 1; i >= 0; i--){",
"ImageDocument img_doc = GetImageDocument(i);",
"if(img_doc.ImageDocumentGetName() == name){",
"img_doc.ImageDocumentSetCurrentFile(path);",
"break;",
"}",
"}"
))
svars = {
"name": image_doc.GetName(),
"path": file_path
}
with execdmscript.exec_dmscript(dmscript, setvars=svars):
pass
except Exception as e:
print("{}: ".format(e.__class__.__name__), e)
import traceback
traceback.print_exc()
the command you're looking for is
void ImageDocumentClean( ImageDocument imgDoc )
as in
image img := realimage("test",4,100,100)
img.ShowImage()
imageDocument doc = img.ImageGetOrCreateImageDocument()
Result("\n Dirty? " + doc.ImageDocumentIsDirty())
doc.ImageDocumentClean()
Result("\n Dirty? " + doc.ImageDocumentIsDirty())
Also: The reason it becomes dirty in a first place is, that window-positions are stored as part of the document. (Other things, like tags, could also apply.)

Cannot get tiff image resolution

I'm trying to read 16 bit .tif microscope images from
https://data.broadinstitute.org/bbbc/BBBC006/
and analyze them using
https://github.com/sakoho81/pyimagequalityranking/tree/master/pyimq
however I got an error in the part of the code that loads the tif image.
It uses the PIL tiffimageplugin:
https://pillow.readthedocs.io/en/3.0.0/_modules/PIL/TiffImagePlugin.html
and when it tries to get the resolution tag, it gives me a keyerror
Any ideas why? Advice? Fixes?
Thanks!
import os
import numpy
import scipy.ndimage.interpolation as itp
import argparse
from PIL import Image
from PIL.TiffImagePlugin import X_RESOLUTION, Y_RESOLUTION
from matplotlib import pyplot as plt
from math import log10, ceil, floor
def get_image_from_imagej_tiff(cls, path):
"""
A class method for opening a ImageJ tiff file. Using this method
will enable the use of correct pixel size during analysis.
:param path: Path to an image
:return: An object of the MyImage class
"""
assert os.path.isfile(path)
assert path.endswith(('.tif', '.tiff'))
print(path) #my own little debug thingamajig
image = Image.open(path)
xresolution = image.tag.tags[X_RESOLUTION][0][0] #line that errors out
yresolution = image.tag.tags[Y_RESOLUTION][0][0]
#data = utils.rescale_to_min_max(numpy.array(image), 0, 255)
if data.shape[0] == 1:
data = data[0]
return cls(images=data, spacing=[1.0/xresolution, 1.0/yresolution])
terminal input:
pyimq.main --mode=directory --mode=analyze --mode=plot --working-directory=/home/myufa/predxion/BBBC/a_1_s1 --normalize-power --result=fstd --imagej
output:
Mode option is ['directory', 'analyze', 'plot']
/home/myufa/predxion/BBBC/a_1_s1/z0_a_1_s1_w1.tif
Traceback (most recent call last):
File "/home/myufa/.local/bin/pyimq.main", line 11, in <module>
load_entry_point('PyImageQualityRanking==0.1', 'console_scripts', 'pyimq.main')()
File "/home/myufa/anaconda3/lib/python3.7/site-packages/PyImageQualityRanking-0.1-py3.7.egg/pyimq/bin/main.py", line 148, in main
File "/home/myufa/anaconda3/lib/python3.7/site-packages/PyImageQualityRanking-0.1-py3.7.egg/pyimq/myimage.py", line 81, in get_image_from_imagej_tiff
KeyError: 282
Edit: Here's what I got when I tried some suggestions/indexed the tag, which makes even less sense
I guess the tiff in question isn't following the normal image conventions. The [XY]Resolution tags, number 282 and 283, are mandatory or required in a whole bunch of specifications, but none the less may not be present in all applications. I have some TIFFs (DNG format) that wouldn't load with PIL (Pillow) at all; that prompted me to write a script to dump the primary tag structure:
# TIFF structure program
import struct
import PIL.TiffTags
class DE:
def __init__(self, tiff):
self.tiff = tiff
(self.tag, self.type, self.count, self.valueoroffset) = struct.unpack(
tiff.byteorder+b'HHI4s', self.tiff.file.read(12))
# TODO: support reading the value
def getstring(self):
offset = struct.unpack(self.tiff.byteorder+b'I', self.valueoroffset)[0]
self.tiff.file.seek(offset)
return self.tiff.file.read(self.count)
class IFD:
def __init__(self, tiff):
self.tiff = tiff
self.offset = tiff.file.tell()
(self.len,) = struct.unpack(self.tiff.byteorder+b'H', self.tiff.file.read(2))
def __len__(self):
return self.len
def __getitem__(self, index):
if index>=self.len or index<0:
raise IndexError()
self.tiff.file.seek(self.offset+2+12*index)
return DE(self.tiff)
def nextoffset(self):
self.tiff.file.seek(self.offset+2+12*self.len)
(offset,) = struct.unpack(self.tiff.byteorder+b'I', self.tiff.file.read(4))
return (offset if offset!=0 else None)
class TIFF:
def __init__(self, file):
self.file = file
header = self.file.read(8)
self.byteorder = {b'II': b'<', b'MM': b'>'}[header[:2]]
(magic, self.ifdoffset) = struct.unpack(self.byteorder+b'HI', header[2:])
assert magic == 42
def __iter__(self):
offset = self.ifdoffset
while offset:
self.file.seek(offset)
ifd = IFD(self)
yield ifd
offset = ifd.nextoffset()
def main():
tifffile = open('c:/users/yann/pictures/img.tiff', 'rb')
tiff = TIFF(tifffile)
for ifd in tiff:
print(f'IFD at {ifd.offset}, {ifd.len} entries')
for entry in ifd:
print(f' tag={entry.tag} {PIL.TiffTags.lookup(entry.tag).name}')
if __name__=='__main__':
main()
A quicker way, since you at least have the image object, might be:
import pprint, PIL.TiffTags
pprint.pprint(list(map(PIL.TiffTags.lookup, img.tag)))
One of these might give you a clue what the actual contents of the TIFF are. Since PIL could load it, it probably has pixel counts but not physical resolution.
Figured out a quick fix, writing
image.tag[X_RESOLUTION]
before
xresolution = image.tag.tags[X_RESOLUTION][0][0]
made the info available in the tag.tags dictionary for some reason. Can anyone chime in and explain why this might be? Would love to learn/make sure I didn't mess it up

Uploading files using Browse Button in Jupyter and Using/Saving them

I came across this snippet for uploading files in Jupyter however I don't know how to save this file on the machine that executes the code or how to show the first 5 lines of the uploaded file. Basically I am looking for proper commands for accessing the file after it has been uploaded:
import io
from IPython.display import display
import fileupload
def _upload():
_upload_widget = fileupload.FileUploadWidget()
def _cb(change):
decoded = io.StringIO(change['owner'].data.decode('utf-8'))
filename = change['owner'].filename
print('Uploaded `{}` ({:.2f} kB)'.format(
filename, len(decoded.read()) / 2 **10))
_upload_widget.observe(_cb, names='data')
display(_upload_widget)
_upload()
_cb is called when the upload finishes. As described in the comment above, you can write to a file there, or store it in a variable. For example:
from IPython.display import display
import fileupload
uploader = fileupload.FileUploadWidget()
def _handle_upload(change):
w = change['owner']
with open(w.filename, 'wb') as f:
f.write(w.data)
print('Uploaded `{}` ({:.2f} kB)'.format(
w.filename, len(w.data) / 2**10))
uploader.observe(_handle_upload, names='data')
display(uploader)
After the upload has finished, you can access the filename as:
uploader.filename
I am working on ML with Jupyter notebook, and I was looking for a solution to select the local files containing the datasets by browsing amongst the local file system. Although, the question here refers more to uploading than selecting a file. I am putting here a snippet that I found here because when I was looking for a solution for my particular case, the result of the search took me several times to here.
import os
import ipywidgets as widgets
class FileBrowser(object):
def __init__(self):
self.path = os.getcwd()
self._update_files()
def _update_files(self):
self.files = list()
self.dirs = list()
if(os.path.isdir(self.path)):
for f in os.listdir(self.path):
ff = os.path.join(self.path, f)
if os.path.isdir(ff):
self.dirs.append(f)
else:
self.files.append(f)
def widget(self):
box = widgets.VBox()
self._update(box)
return box
def _update(self, box):
def on_click(b):
if b.description == '..':
self.path = os.path.split(self.path)[0]
else:
self.path = os.path.join(self.path, b.description)
self._update_files()
self._update(box)
buttons = []
if self.files:
button = widgets.Button(description='..', background_color='#d0d0ff')
button.on_click(on_click)
buttons.append(button)
for f in self.dirs:
button = widgets.Button(description=f, background_color='#d0d0ff')
button.on_click(on_click)
buttons.append(button)
for f in self.files:
button = widgets.Button(description=f)
button.on_click(on_click)
buttons.append(button)
box.children = tuple([widgets.HTML("<h2>%s</h2>" % (self.path,))] + buttons)
And to use it:
f = FileBrowser()
f.widget()
# <interact with widget, select a path>
# in a separate cell:
f.path # returns the selected path
4 years later this remains an interesting question, though Fileupload has slightly changed and belongs to ipywidgets....
Here is some demo that shows how to get the file/files after the button click and reset the button to get more files....
from ipywidgets import FileUpload
def on_upload_change(change):
if not change.new:
return
up = change.owner
for filename,data in up.value.items():
print(f'writing [{filename}] to ./')
with open(filename, 'wb') as f:
f.write(data['content'])
up.value.clear()
up._counter = 0
upload_btn = FileUpload()
upload_btn.observe(on_upload_change, names='_counter')
upload_btn
And here is a "debug" version that shows what is going on / why things work...
from ipywidgets import FileUpload
def on_upload_change(change):
if change.new==0:
print ('cleared')
return
up = change.owner
print (type(up.value))
for filename,data in up.value.items():
print('==========================================================================================')
print(filename)
for k,v in data['metadata'].items():
print(f' -{k:13}:[{v}]')
print(f' -content len :[{len(data["content"])}]')
print('==========================================================================================')
up.value.clear()
up._counter = 0
upload_btn = FileUpload()
upload_btn.observe(on_upload_change, names='_counter')
upload_btn
I stumbled into this thread ~2 years late. For those still confused about how to work with the fileupload widget I have built off of the excellent answer posted by minrk with some other usage examples below.
from IPython.display import display
import fileupload
uploader = fileupload.FileUploadWidget()
def _handle_upload(change):
w = change['owner']
with open(w.filename, 'wb') as f:
f.write(w.data)
print('Uploaded `{}` ({:.2f} kB)'.format(
w.filename, len(w.data) / 2**10))
uploader.observe(_handle_upload, names='data')
display(uploader)
From the widget documentation:
class FileUploadWidget(ipywidgets.DOMWidget):
'''File Upload Widget.
This widget provides file upload using `FileReader`.
'''
_view_name = traitlets.Unicode('FileUploadView').tag(sync=True)
_view_module = traitlets.Unicode('fileupload').tag(sync=True)
label = traitlets.Unicode(help='Label on button.').tag(sync=True)
filename = traitlets.Unicode(help='Filename of `data`.').tag(sync=True)
data_base64 = traitlets.Unicode(help='File content, base64 encoded.'
).tag(sync=True)
data = traitlets.Bytes(help='File content.')
def __init__(self, label="Browse", *args, **kwargs):
super(FileUploadWidget, self).__init__(*args, **kwargs)
self._dom_classes += ('widget_item', 'btn-group')
self.label = label
def _data_base64_changed(self, *args):
self.data = base64.b64decode(self.data_base64.split(',', 1)[1])
Get the data in bytestring format:
uploader.data
Get the data in a regular utf-8 string:
datastr= str(uploader.data,'utf-8')
Make a new pandas dataframe from the utf-8 string (e.g. from a .csv input):
import pandas as pd
from io import StringIO
datatbl = StringIO(datastr)
newdf = pd.read_table(datatbl,sep=',',index_col=None)
You have to enable the file upload option in your code, to enable the browse button to appear in your notebook.
Run the following
!jupyter nbextension enable fileupload --user --py

Updating Axis In Matplotlib Based on Dynamic Values

I am working on a project in which I read in values from a text file that dynamically updates with two values separated by a space. These values are taken put into a list and then both plotted with each being a point on the y-axis and time being on the x-axis. In the first set of code provided below I am able to take in the values and plot them, then save that plot as a png. However, the plot does not seem to update the time values as more data comes in. But the graph does reflect the changes in the values.
# -*- coding: utf-8 -*-
"""
Created on Mon Jul 25 11:23:14 2016
#author: aruth3
"""
import matplotlib.pyplot as plt
import sys
import time
import datetime
class reader():
"""Reads in a comma seperated txt file and stores the two strings in two variables"""
def __init__(self, file_path):
"""Initialize Reader Class"""
self.file_path = file_path
# Read File store in f -- Change the file to your file path
def read_file(self):
"""Reads in opens file, then stores it into file_string as a string"""
f = open(self.file_path)
# Read f, stores string in x
self.file_string = f.read()
def split_string(self):
"""Splits file_string into two variables and then prints them"""
# Splits string into two variables
try:
self.val1, self.val2 = self.file_string.split(' ', 1)
except ValueError:
print('Must Have Two Values Seperated By a Space in the .txt!!')
sys.exit('Terminating Program -- Contact Austin')
#print(val1) # This is where you could store each into a column on the mysql server
#print(val2)
def getVal1(self):
return self.val1
def getVal2(self):
return self.val2
read = reader('testFile.txt')
run = True
tempList = []
humList = []
numList = [] # Represents 2 Secs
my_xticks = []
i = 0
while(run):
plt.ion()
read.read_file()
read.split_string()
tempList.append(read.getVal1())
humList.append(read.getVal2())
numList.append(i)
i = i + 1
my_xticks.append(datetime.datetime.now().strftime('%I:%M'))
plt.ylim(0,125)
plt.xticks(numList,my_xticks)
plt.locator_params(axis='x',nbins=4)
plt.plot(numList,tempList, 'r', numList, humList, 'k')
plt.savefig('plot.png')
time.sleep(10) # Runs every 2 seconds
The testFile.txt has two values 100 90 and can be updated on the fly and change in the graph. But as time goes on you will notice (if you run the code) that the times are not updating.
To remedy the time not updating issue I figure that modifying the lists using pop would allow the first value to leave and then another value when it loops back around. This worked as far as the time updating was concerned, however this ended up messing up the graph:
Link To Bad Graph Image
Code:
# -*- coding: utf-8 -*-
"""
Created on Tue Aug 2 09:42:16 2016
#author: aruth3
"""
# -*- coding: utf-8 -*-
"""
Created on Mon Jul 25 11:23:14 2016
#author:
"""
import matplotlib.pyplot as plt
import sys
import time
import datetime
class reader():
"""Reads in a comma seperated txt file and stores the two strings in two variables"""
def __init__(self, file_path):
"""Initialize Reader Class"""
self.file_path = file_path
# Read File store in f -- Change the file to your file path
def read_file(self):
"""Reads in opens file, then stores it into file_string as a string"""
f = open(self.file_path)
# Read f, stores string in x
self.file_string = f.read()
def split_string(self):
"""Splits file_string into two variables and then prints them"""
# Splits string into two variables
try:
self.val1, self.val2 = self.file_string.split(' ', 1)
except ValueError:
print('Must Have Two Values Seperated By a Space in the .txt!!')
sys.exit('Terminating Program -- Contact')
#print(val1) # This is where you could store each into a column on the mysql server
#print(val2)
def getVal1(self):
return self.val1
def getVal2(self):
return self.val2
read = reader('testFile.txt')
run = True
tempList = []
humList = []
numList = [] # Represents 2 Secs
my_xticks = []
i = 0
n = 0 # DEBUG
while(run):
plt.ion()
read.read_file()
read.split_string()
if n == 4:
my_xticks.pop(0)
tempList.pop(0)
humList.pop(0)
numList = [0,1,2]
i = 3
n = 3
tempList.append(read.getVal1())
humList.append(read.getVal2())
numList.append(i)
i = i + 1
my_xticks.append(datetime.datetime.now().strftime('%I:%M:%S')) # Added seconds for debug
plt.ylim(0,125)
plt.xticks(numList,my_xticks)
plt.locator_params(axis='x',nbins=4)
plt.plot(numList,tempList, 'r', numList, humList, 'k')
plt.savefig('plot.png')
time.sleep(10) # Runs every 2 seconds
n = n + 1
print(n) # DEBUG
print(numList)# DEBUG
print('-------')# DEBUG
print(my_xticks)# DEBUG
print('-------')# DEBUG
print(tempList)# DEBUG
print('-------')# DEBUG
print(humList)# DEBUG
So my question is how can I create a graph that when new values come in it kicks out the first value in the list, thus updating the time, but also provides an accurate graph of the data without the glitching?
The pop off the list seems like a good idea but I am not sure why it is messing up the graph?
Thanks!
This question may be more appropriate at https://codereview.stackexchange.com/
Pseudo Code
plotData = []
for (1 to desired size)
plotData[i] = 0
while data
update time
plotData.push(data with time)
plotData.popTop(oldest data)
Draw plotData
end while

Categories

Resources