How to live update Matplotlib plot on top of a background image?

Viewed 300

I'm trying to have my matplotlib plot update in real-time as data is added to a CSV file. The plot is of a small geographic location, axes given by longitude and latitude. This is what I have so far:

import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt

df = pd.read_csv("cayugacoords.txt")
BoundaryBox = [-76.5119, -76.5013, 42.4596, 42.4642]
ruh_m = plt.imread('map.png')
fig, ax = plt.subplots(figsize=(8, 7))

ax.scatter(df.longitude, df.latitude, zorder=1, alpha=1, c='r', s=10)
ax.set_title('Cayuga Lake Shore')
ax.set_xlim(BoundaryBox[0], BoundaryBox[1])
ax.set_ylim(BoundaryBox[2], BoundaryBox[3])
ax.imshow(ruh_m, zorder=0, extent=BoundaryBox, aspect='equal')
plt.show()

And this is what shows when I run the code (the three points on the bottom left are already in the CSV file): Current plot

And here's the background image on its own: Cayuga Lake

I want the map to be regularly updated as new coordinates are added to the CSV file. How can this be done? I've looked into animation tools but I'm having trouble retaining the background image of the map while updating the plot. For reference, the CSV file "cayugacoords.txt" looks like this:

longitude,latitude
-76.51,42.46
-76.511,42.46
-76.5105,42.46

Thank you!

2 Answers

An alternative solution which updates only the points on the background image is provided by using ax.collections = [] which clears ALL lines plotted on the image. For the sake of demonstration I plot each coordinate per frame.

import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation

df = pd.read_csv("cayugacoords.txt")
BoundaryBox = [-76.5119, -76.5013, 42.4596, 42.4642]
ruh_m = plt.imread('map.png')
fig, ax = plt.subplots(figsize=(8, 7))

ax.set_title('Cayuga Lake Shore')
ax.set_xlim(BoundaryBox[0], BoundaryBox[1])
ax.set_ylim(BoundaryBox[2], BoundaryBox[3])
ax.imshow(ruh_m, zorder=0, extent=BoundaryBox, aspect='equal')

def animate(nframe):
    ax.collections = []
    points = ax.scatter(df.longitude[nframe], df.latitude[nframe], zorder=1,
                        alpha=1, c='r', s=10)
    return

anim = animation.FuncAnimation(fig, animate, frames=3)

This code worked for me. It seems quite hacky but it works. You can adjust the time.sleep to your liking.

from matplotlib import pyplot as plt
from IPython.display import clear_output
import pandas as pd
import numpy as np
import time
%matplotlib inline

ruh_m = plt.imread('map.png')
BoundaryBox = [-76.5119, -76.5013, 42.4596, 42.4642]
while True:
    clear_output(wait=True)
    df = pd.read_csv("cayugacoords.txt")
    fig, ax = plt.subplots(figsize=(10, 10))
    ax.scatter(df.longitude, df.latitude, zorder=1, alpha=1, c='r', s=10)
    ax.set_title('Cayuga Lake Shore')
    ax.set_xlim(BoundaryBox[0], BoundaryBox[1])
    ax.set_ylim(BoundaryBox[2], BoundaryBox[3])
    ax.imshow(ruh_m, zorder=0, extent=BoundaryBox, aspect='equal')
    plt.show()
    time.sleep(1E-3)
Related