Skip to main content

Tutorial: How to Plot Sensor Data Using Python

This tutorial shows how to plot Project Aria sensor data using Python. This example covers how to:

  • Save images as PNGs
  • Plot raw sensor data from a VRS file and store the plots in PDF files
    • Data is plotted with matplotlib

We start by opening a VRS file:

from projectaria_tools.core import data_provider, image
from projectaria_tools.core.stream_id import StreamId

vrsfile = "example.vrs"
provider = data_provider.create_vrs_data_provider(vrsfile)

Save Images as PNGs

Because we support converting image data to numpy arrays, images can be converted to PIL images and saved as PNG files.

from PIL import Image
stream_mappings = {
"camera-slam-left": StreamId("1201-1"),
"camera-slam-right": StreamId("1201-2"),
"camera-rgb": StreamId("214-1"),
"camera-eyetracking": StreamId("211-1"),
}

index = 1 # sample index (as an example)
for [stream_name, stream_id] in stream_mappings.items():
image = provider.get_image_data_by_index(stream_id, index)
Image.fromarray(image[0].to_numpy_array()).save(f'{stream_name}.png')

The above snippets will save the following images to the local folder:

SLAM imagescamera-slam-leftcamera-slam-right
Eye Tracking imagescamera-et
RGB imagescamera-rgb

Plotting IMU

  1. Organize the data into 6 lists. Each list stores one axis of a specific IMU.
stream_id = provider.get_stream_id_from_label("imu-left")
accel_x = []
accel_y = []
accel_z = []
gyro_x = []
gyro_y = []
gyro_z = []
timestamps = []
for index in range(0, provider.get_num_data(stream_id)):
imu_data = provider.get_imu_data_by_index(stream_id, index)
accel_x.append(imu_data.accel_msec2[0])
accel_y.append(imu_data.accel_msec2[1])
accel_z.append(imu_data.accel_msec2[2])
gyro_x.append(imu_data.gyro_radsec[0])
gyro_y.append(imu_data.gyro_radsec[1])
gyro_z.append(imu_data.gyro_radsec[2])
timestamps.append(imu_data.capture_timestamp_ns * 1e-9)
  1. Plot the data with matplotlib
plt.figure()
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
fig.suptitle(f"{stream_id.get_name()}")

axes[0].plot(timestamps, accel_x, 'r-', label="x")
axes[0].plot(timestamps, accel_y, 'g-', label="y")
axes[0].plot(timestamps, accel_z, 'b-', label="z")
axes[0].legend(loc='upper left')
axes[0].grid('on')
axes[0].set_xlabel('timestamps (s)')
axes[0].set_ylabel('accelerometer readout (m/sec2)')

axes[1].plot(timestamps, gyro_x, 'r-', label="x")
axes[1].plot(timestamps, gyro_y, 'g-', label="y")
axes[1].plot(timestamps, gyro_z, 'b-', label="z")
axes[1].legend(loc='upper left')
axes[1].grid('on')
axes[1].set_xlabel('timestamps (s)')
axes[1].set_ylabel('gyroscope readout (rad/sec)')

The plotted image looks like this: Image

  1. Save the plot to PDF
plt.savefig("imu.pdf", format="pdf", bbox_inches="tight")

Magnetometer

Plotting magnetometer is similar to plotting IMU.

  1. Organize the data into 3 lists. Each list stores one axis of magnetometer data.
stream_id = provider.get_stream_id_from_label("mag0")
mag_x = []
mag_y = []
mag_z = []
timestamps = []
for index in range(0, provider.get_num_data(stream_id)):
mag_data = provider.get_magnetometer_data_by_index(stream_id, index)
mag_x.append(mag_data.mag_tesla[0] * 1e6)
mag_y.append(mag_data.mag_tesla[1] * 1e6)
mag_z.append(mag_data.mag_tesla[2] * 1e6)
timestamps.append(mag_data.capture_timestamp_ns * 1e-9)
  1. Plot the data with matplotlib
plt.figure()
fig, axes = plt.subplots(1, 1, figsize=(12, 5))
fig.suptitle(f"Magnetometer signal")

axes.plot(timestamps, mag_x, 'r-', label="x")
axes.plot(timestamps, mag_y, 'g-', label="y")
axes.plot(timestamps, mag_z, 'b-', label="z")
axes.legend(loc='upper left')
axes.grid('on')
axes.set_xlabel('timestamps (s)')
axes.set_ylabel('magnetometer readout (uT)')
plt.savefig("mag.pdf", format="pdf", bbox_inches="tight")

Image

Audio

Audio data is interesting since each data is in fact a 7x4096 chunk

  1. Load the audio data
stream_id = provider.get_stream_id_from_label("mic")
timestamps = []
audio = [[] for c in range(0, 7)]
for index in range(0, 2):
audio_data_i = provider.get_audio_data_by_index(stream_id, index)
audio_signal_block = audio_data_i[0].data
timestamps_block = [t * 1e-9 for t in audio_data_i[1].capture_timestamps_ns];
timestamps += timestamps_block
for c in range(0, 7):
audio[c] += audio_signal_block[c::7]
  1. Plot the data with matplotlib
plt.figure()
fig, axes = plt.subplots(1, 1, figsize=(12, 5))
fig.suptitle(f"Microphone signal")
for c in range(0, 7):
plt.plot(timestamps, audio[c], '-', label = f"channel {c}")
axes.legend(loc='upper left')
axes.grid('on')
axes.set_xlabel('timestamps (s)')
axes.set_ylabel('audio readout')
plt.savefig("audio.pdf", format="pdf", bbox_inches="tight")

Image

Barometer

  1. Load and plot the data using the following commands
plt.figure()
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
fig.suptitle(f"Barometer signal")

stream_id = provider.get_stream_id_from_label("baro0")
pressure = []
temperature = []
timestamps = []
for index in range(0, provider.get_num_data(stream_id)):
baro_data = provider.get_barometer_data_by_index(stream_id, index)
pressure.append(baro_data.pressure * 1e-3)
temperature.append(baro_data.temperature)
timestamps.append(baro_data.capture_timestamp_ns * 1e-9)

axes[0].plot(timestamps, pressure, 'r-')
axes[0].grid('on')
axes[0].set_xlabel('timestamps (s)')
axes[0].set_ylabel('pressure readout (kPascal)')

axes[1].plot(timestamps, temperature, 'r-')
axes[1].grid('on')
axes[1].set_xlabel('timestamps (s)')
axes[1].set_ylabel('temperature readout (C)')

plt.savefig("baro.pdf", format="pdf", bbox_inches="tight")

ImageImage

GPS

GPS data can be visualized with 2D or 3D plots.

2D plots

plt.figure()
fig, axes = plt.subplots(1, 3, figsize=(12, 3))
fig.suptitle(f"GPS signal")

stream_id = provider.get_stream_id_from_label("gnss")
latitude = []
longitude = []
altitude = []
timestamps = []
for index in range(100, 300):
gps_data = provider.get_gps_data_by_index(stream_id, index)
latitude.append(gps_data.latitude)
longitude.append(gps_data.longitude)
altitude.append(gps_data.altitude)
timestamps.append(gps_data.capture_timestamp_ns * 1e-9)

ax = axes[0]
ax.plot(timestamps, latitude, 'r-')
ax.grid('on')
ax.set_xlabel('timestamps (s)')
ax.set_ylabel('latitude')
ax.yaxis.set_major_formatter(ticker.ScalarFormatter(useMathText=True, useOffset=False))

ax = axes[1]
ax.plot(timestamps, longitude, 'r-')
ax.grid('on')
ax.set_xlabel('timestamps (s)')
ax.set_ylabel('longitude')
ax.yaxis.set_major_formatter(ticker.ScalarFormatter(useMathText=True, useOffset=False))

ax = axes[2]
ax.plot(timestamps, altitude, 'r-')
ax.grid('on')
ax.set_xlabel('timestamps (s)')
ax.set_ylabel('altitude')
ax.yaxis.set_major_formatter(ticker.ScalarFormatter(useMathText=True, useOffset=False))

fig.tight_layout()
plt.savefig("gps.pdf", format="pdf", bbox_inches="tight")

Image

3D plots

plt.figure()
fig = plt.figure()

axes = fig.add_subplot(projection='3d')
axes.plot(latitude, longitude, altitude)
axes.view_init(elev=20., azim=-35, roll=0)
plt.savefig("gps3d.pdf", format="pdf", bbox_inches="tight")

Image

Wi-Fi beacon

  1. Group the Wi-Fi beacon data by mac bssid
stream_id = provider.get_stream_id_from_label("wps")
rssi = {}
timestamps = {}
print(provider.get_num_data(stream_id))
for index in range(0, provider.get_num_data(stream_id)):
wps_data = provider.get_wps_data_by_index(stream_id, index)
if wps_data.bssid_mac not in rssi:
rssi[wps_data.bssid_mac] = []
timestamps[wps_data.bssid_mac] = []
rssi[wps_data.bssid_mac].append(wps_data.rssi)
timestamps[wps_data.bssid_mac].append(wps_data.board_timestamp_ns * 1e-9)
  1. Plot the mac address
    • This example has > 15 samples
plt.figure()
fig, ax = plt.subplots(1, 1, figsize=(6, 5))
fig.suptitle(f"Wi-Fi beacon signal")

for ssid in list(timestamps.keys()):
if len(timestamps[ssid]) < 15:
continue
ax.scatter(timestamps[ssid], rssi[ssid], label=ssid)

ax.grid('on')
ax.set_xlabel('timestamps (s)')
ax.set_ylabel('Wi-Fi RSSI(dBm)')
plt.legend(loc='upper left')
plt.savefig("wifi.pdf", format="pdf", bbox_inches="tight")

Image

Bluetooth beacon

  1. Group data by unique_id (similar to Wi-Fi grouping)
stream_id = provider.get_stream_id_from_label("bluetooth")
rssi = {}
timestamps = {}

for index in range(0, provider.get_num_data(stream_id)):
bluetooth_data = provider.get_bluetooth_data_by_index(stream_id, index)
if bluetooth_data.unique_id not in rssi:
rssi[bluetooth_data.unique_id] = []
timestamps[bluetooth_data.unique_id] = []
rssi[bluetooth_data.unique_id].append(bluetooth_data.rssi)
timestamps[bluetooth_data.unique_id].append(bluetooth_data.board_timestamp_ns * 1e-9)
  1. Plot the data per unique_id
plt.figure()
fig, ax = plt.subplots(1, 1, figsize=(6, 5))
fig.suptitle(f"Bluetooth beacon signal")

for ssid in list(timestamps.keys()):
ax.plot(timestamps[ssid], rssi[ssid], '.')
ax.grid('on')
ax.set_xlabel('timestamps (s)')
ax.set_ylabel('bluetooth RSSI(dBm')
fig.tight_layout()

plt.savefig("ble.pdf", format="pdf", bbox_inches="tight")

Image