Vasanth Nag K V
Vasanth Nag K V

Reputation: 4988

Python - live graph update from a changing text file

i have a thread that writes continuously into a text file for every 2 seconds. the same file is referenced by a Matplotlib graph (live updating graph).

so when i start the script, i open up a graph and start the file writing process on a thread. the file is getting updated but not my graph. only after the file writing is complete the data on the file gets represented on the graph.

but this is not the concept of live graphs. i want the data representation to be shown as and when the data is being written into the file. what am i doing wrong here?

this is my Main function

def Main():
    t1=Thread(target=FileWriter)
    t1.start()
    ani = animation.FuncAnimation(fig, animate, interval=1000)
    plt.show()
    print("done")

My file writing function

def FileWriter():
    f=open('F:\\home\\WorkSpace\\FIrstPyProject\\TestModules\\sampleText.txt','w')
    k=0
    i=0
    while (k < 20):
        i+=1
        j=randint(10,19)
        data = f.write(str(i)+','+str(j)+'\n')
        print("wrote data")
        time.sleep(2)
        k += 1

my Graph function

def animate(i):
    pullData = open("sampleText.txt","r").read()
    dataArray = pullData.split('\n')
    xar = []
    yar = []
    for eachLine in dataArray:
        if len(eachLine)>1:
            x,y = eachLine.split(',')
            xar.append(int(x))
            yar.append(int(y))
    ax1.clear()
    ax1.plot(xar,yar)

Upvotes: 3

Views: 4976

Answers (2)

I_Literally_Cannot
I_Literally_Cannot

Reputation: 170

Its been a few years since this was posted, but I was working with this and I ran into an issue where I needed the graph to update after every cycle.

I tried to use ali_m's suggestion: f=open('./dynamicgraph.txt','a', 0), but there was an error with buffering "cannot be set to 0".

If you put a flush() function into the FileWriter while loop, it will update the graph after each cycle. Here is the complete code for the program which will draw a graph as it is running:

#!usr/bin/python3
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time
from random import randrange
from threading import Thread

fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)


def FileWriter():
    f=open('./dynamicgraph.txt','a')
    i=0
    while True:
        i+=1
        j=randrange(10)
        data = f.write(str(i)+','+str(j)+'\n')
        print("wrote data")
        time.sleep(1)
        f.flush()


def animate(i):
    pullData = open("dynamicgraph.txt","r").read()
    dataArray = pullData.split('\n')
    xar = []
    yar = []
    for eachLine in dataArray:
        if len(eachLine)>1:
            x,y = eachLine.split(',')
            xar.append(int(x))
            yar.append(int(y))
    ax1.clear()
    ax1.plot(xar,yar)

def Main():
    t1=Thread(target=FileWriter)
    t1.start()
    ani = animation.FuncAnimation(fig, animate, interval=1000)
    plt.show()
    print("done")

Main()

Upvotes: 2

ali_m
ali_m

Reputation: 74242

The problem is unrelated to matplotlib, but rather it has to do with how you're reading and writing your data to the text file.

Python file objects are usually line-buffered by default, so when you call f.write(str(i)+','+str(j)+'\n') from inside your FileWriter thread, your text file is not immediately updated on disk. Because of this, open("sampleText.txt","r").read() is returning an empty string, and therefore you have no data to plot.

To force the text file to be updated "instantly", you could either call f.flush() immediately after writing to it, or you could set the buffer size to zero when you open the file, e.g. f = open('sampleText.txt', 'w', 0) (see this previous SO question as well).

Upvotes: 2

Related Questions