• 0

using python matplotlib to read serial data and plot bar graph dynamically


Question

I'm new to the matplotlib library but saw there is a new animation function for dynamic graphs. In this code I am reading serial data then parsing it and inputting it into a bar graph.  This all works fine if there is no dynamic animation.  I added the functions to get it dynamic but it keeps erroring out with "AttributeError: 'function' object has no attribute 'FuncAnimation'" and I'm not sure why.  I also have another code for the "manual way" to update the graph but I've read this isn't as efficient.  This way works though but only for a few updates before the graph freezes. At this point whatever I can get working would be fine. Thank you.

from matplotlib import pyplot as plt
from matplotlib import animation
import serial

# sensor data placeholder
sensorSerial = [" "," "," "," "," "," "," "," "," "]
humidityData = [.01, .01, .01, .01,.01,.01,.01,.01,.01]
tempData = [.01, .01, .01, .01,.01,.01,.01,.01,.01]

# bar details
bar_width = 0.25
opacity = 0.4

# create serial port
serobject = serial.Serial("COM4", 9600)

# create subplot object for 2 y-axis scales
fig, ax = plt.subplots()
# set graph colors
ax.set_axis_bgcolor('black')
fig.patch.set_facecolor('black')
ax.tick_params(axis='x', colors='white', length=0)
# setup axis ticks
ax.set_yticks(range(0,100,20))
ax.set_xticks(range(1,10))
# add x axis labels
ax.set_xticklabels(('Sensor1', 'Sensor2', 'Sensor3', 'Sensor4'))
tempBar = ax.bar([],[])
humidBar = ax.bar([],[])

def init():
    tempBar.set_data([],[])
    humidBar.set_data([],[])
    return tempBar, humidBar

def animation(i):
    # get sensor string data and parse
    data1 = serobject.readline().split(" ")
    data2 = serobject.readline().split(" ")

    # add data to arrays
    sensorSerial[0] = data1[0]
    humidityData[0] = int(data1[1])
    tempData[0] = int(data1[2])

    sensorSerial[1] = data2[0]
    humidityData[1] = int(data2[1])
    tempData[1] = int(data2[2])
    
    # create new bar graphs
    tempBar = ax.bar([i+0.25 for i in range(1,10)], tempData, bar_width, alpha=opacity,
            color='r', label='Temperature', edgecolor='white', linewidth = 3)
    humidBar = ax.bar([i+0.5 for i in range(1,10)], humidityData, bar_width, alpha=opacity,
            color='b', label='Humidity', edgecolor='white', linewidth = 3)
    return tempBar, humidBar

anim = animation.FuncAnimation(fig, animation, init_func=init)
plt.show()
#import libraries
import matplotlib.pyplot as plt
import serial
import time
import matplotlib.animation as animation

# sensor data placeholder
sensorSerial = [" "," "," "," "," "," "," "," "," "]
humidityData = [.01, .01, .01, .01,.01,.01,.01,.01,.01]
tempData = [.01, .01, .01, .01,.01,.01,.01,.01,.01]

# bar details
bar_width = 0.25
opacity = 0.4

# create serial port
serobject = serial.Serial("COM4", 9600)

# create subplot object for 2 y-axis scales
fig, ax = plt.subplots()
# set graph colors
ax.set_axis_bgcolor('black')
fig.patch.set_facecolor('black')
ax.tick_params(axis='x', colors='white', length=0)
# setup axis ticks
ax.set_yticks(range(0,100,20))
ax.set_xticks(range(1,10))
# add x axis labels
ax.set_xticklabels(('Sensor1', 'Sensor2', 'Sensor3', 'Sensor4'))
tempBar = ax.bar([],[])
humidBar = ax.bar([],[])

# dynamic plotting
plt.ion()
# show plot
plt.show()

while(True):
    # get sensor string data and parse
    data1 = serobject.readline().split(" ")
    data2 = serobject.readline().split(" ")

    # add data to arrays
    sensorSerial[0] = data1[0]
    humidityData[0] = int(data1[1])
    tempData[0] = int(data1[2])

    sensorSerial[1] = data2[0]
    humidityData[1] = int(data2[1])
    tempData[1] = int(data2[2])
    #remove old data from plot
    tempBar.remove()
    humidBar.remove()
    # redraw new data
    tempBar = ax.bar([i+0.25 for i in range(1,10)], tempData, bar_width, alpha=opacity,
            color='r', label='Temperature', edgecolor='white', linewidth = 3)
    humidBar = ax.bar([i+0.25*2 for i in range(1,10)], humidityData, bar_width, alpha=opacity,
            color='b', label='Humidity', edgecolor='white', linewidth = 3)
    plt.draw()

6 answers to this question

Recommended Posts

  • 0

You named your own function animation, which is clobbering over the matplotlib.animation object.

 

e.g.

def animation(i):

...

... = animation.FuncAnimation(fig, animation, ...)

Just switch the call to matplotlib.animation.FuncAnimation(...) instead. That is what I use.

  • 0

okay, that fixed that but now i get "AttributeError: 'BarContainer' object has no attribute 'axes'" but dont see a reference to the line where the error is at. here is my full error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
    return self.func(*args)
  File "C:\Python27\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 276, in resize
    self.show()
  File "C:\Python27\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 348, in draw
    FigureCanvasAgg.draw(self)
  File "C:\Python27\lib\site-packages\matplotlib\backends\backend_agg.py", line 451, in draw
    self.figure.draw(self.renderer)
  File "C:\Python27\lib\site-packages\matplotlib\artist.py", line 55, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Python27\lib\site-packages\matplotlib\figure.py", line 1040, in draw
    self.canvas.draw_event(renderer)
  File "C:\Python27\lib\site-packages\matplotlib\backend_bases.py", line 1693, in draw_event
    self.callbacks.process(s, event)
  File "C:\Python27\lib\site-packages\matplotlib\cbook.py", line 527, in process
    proxy(*args, **kwargs)
  File "C:\Python27\lib\site-packages\matplotlib\cbook.py", line 405, in __call__
    return mtd(*args, **kwargs)
  File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 832, in _end_redraw
    self._post_draw(None, self._blit)
  File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 778, in _post_draw
    self._blit_draw(self._drawn_artists, self._blit_cache)
  File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 791, in _blit_draw
    if a.axes not in bg_cache:
AttributeError: 'BarContainer' object has no attribute 'axes'
from matplotlib import pyplot as plt
from matplotlib import animation
import serial

# sensor data placeholder
sensorSerial = [" "," "," "," "," "," "," "," "," "]
humidityData = [.01, .01, .01, .01,.01,.01,.01,.01,.01]
tempData = [.01, .01, .01, .01,.01,.01,.01,.01,.01]

# bar details
bar_width = 0.25
opacity = 0.4

# create serial port
serobject = serial.Serial("COM4", 9600)

# create subplot object for 2 y-axis scales
fig, ax = plt.subplots()
# set graph colors
ax.set_axis_bgcolor('black')
fig.patch.set_facecolor('black')
ax.tick_params(axis='x', colors='white', length=0)
# setup axis ticks
ax.set_yticks(range(0,100,20))
ax.set_xticks(range(1,10))
# add x axis labels
ax.set_xticklabels(('Sensor1', 'Sensor2', 'Sensor3', 'Sensor4'))
tempBar = ax.bar([],[])
humidBar = ax.bar([],[])

def init():
    tempBar = ax.bar([],[])
    humidBar = ax.bar([],[])
    return tempBar, humidBar

def animator(i):
    # get sensor string data and parse
    data1 = serobject.readline().split(" ")
    data2 = serobject.readline().split(" ")

    print(data1)
    print(data2)

    # add data to arrays
    sensorSerial[0] = data1[0]
    humidityData[0] = int(data1[1])
    tempData[0] = int(data1[2])

    sensorSerial[1] = data2[0]
    humidityData[1] = int(data2[1])
    tempData[1] = int(data2[2])
    
    # create new bar graphs
    tempBar = ax.bar([i+0.25 for i in range(1,10)], tempData, bar_width, alpha=opacity,
            color='r', label='Temperature', edgecolor='white', linewidth = 3)
    humidBar = ax.bar([i+0.5 for i in range(1,10)], humidityData, bar_width, alpha=opacity,
            color='b', label='Humidity', edgecolor='white', linewidth = 3)
    return tempBar, humidBar

anim = animation.FuncAnimation(fig, animator, init_func=init, frames=100, interval=2000, blit=True)
plt.show()
  • 0

I believe it doesn't like your return value for animation() or init(). When I've used animatefunc(), I haven't actually return anything (for example if I'm using ax.pcolormesh). I would try without the returns and see if it works that way. You can also try returning your ax or your plot there. I'm not 100% how the return works, but it looks like it is to tell the animator what part of the plot to update. Perhaps, if you don't return anything it just updates everything?

  • 0

hmm, with the return gone for init function i get "TypeError: 'NoneType' object is not iterable" taking out the return for the animator function does nothing. 

 

returning 'ax' gives me a "TypeError: 'AxesSubplot' object is not iterable" error.

 

returning 'plt' gives me a "TypeError: 'module' object is not iterable" error.

 

This is the guide i followed and it works that way and seemed straigh forward but alas im here

http://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/


EDIT: oh, so i changed it so both functions only return tempBar and not both and it works that way but doenst show humidBar at all. I guess it didnt like the double return.  Is there any way to have it update more bars?

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • And this is why I always wait at least a week after a Patch Tuesday before updating the servers. No headaches over here.
    • Windows is a scam for many decades, it's good if some people are realizing it now
    • Latest Patch Tuesday has broken DHCP Server in all Windows Server editions by Usama Jawad Microsoft released Patch Tuesday updates for Windows and Windows Server releases roughly a week ago, on June 10. In the latter, the release contained new functions for Narrator scan mode, along with tons of fixes for File Explorer, GDI+, Hyper-V, and more. At that time, Microsoft noted a known issue for Noto fonts, where Chinese, Japanese, and Korean text appears blurry or unclear under certain conditions. Now, it has highlighted another known issue following user reports. For the past couple of days, users on Reddit have been reporting issues with the DHCP service after applying the latest Patch Tuesday update. Apparently, rebooting the system fixes the issue, which can be understandably annoying. Now, Microsoft has updated the documentation for the June 10 release notes across Windows Server 2016, 2019, 2022, and 2025, to mention that the DHCP Server service may "intermittently" stop working after installing Patch Tuesday's update, which will impact IP renewal processes on client machines. Redmond has assured customers that it is working on a fix, which will likely be rolled out within the next few days. Of course, this problem is rather frustrating for IT admins, and that annoyance is reflected in the Reddit thread where customers are blaming Microsoft's software quality assurance practices. The fact that it's currently unclear when a fix will be rolled out may further add to customer grievances. For those unaware, the DHCP Server service in Windows is responsible for network management such as allocation and configuration of IP addresses in a centralized environment with robust logging and monitoring mechanisms. And for those keeping track, this is not the only Windows Server issue that has cropped up in recent memory. Last month, Microsoft pushed an out-of-band (OOB) hotfix to patch a Hyper-V bug that was plaguing the platform. Of course, one can argue that problems like these are happening because of incomplete testing, but it is also important to remember that Windows is running on hundreds of millions of devices all over the globe, so comprehensive test case coverage is very difficult, if not impossible.
    • And still, no Windows Hello support for protected "tabs" in the "old"/Win32 OneNote app, a feature that was available for a long time in the UWP version. Please, Microsoft, get back to feature parity...
    • Like jupe, for me, the most exciting news from Windows for a few weeks ( / months ?) now is the return of the clock in the taskbar calendar. I filed a feedback hub post so long ago about this. Finally!
  • Recent Achievements

    • Week One Done
      patrickft456 earned a badge
      Week One Done
    • One Month Later
      patrickft456 earned a badge
      One Month Later
    • One Month Later
      Jdoe25 earned a badge
      One Month Later
    • Explorer
      Legend20 went up a rank
      Explorer
    • One Month Later
      jezzzy earned a badge
      One Month Later
  • Popular Contributors

    1. 1
      +primortal
      617
    2. 2
      ATLien_0
      281
    3. 3
      +FloatingFatMan
      174
    4. 4
      Michael Scrip
      153
    5. 5
      Steven P.
      124
  • Tell a friend

    Love Neowin? Tell a friend!