Inżynieria

Wykres krzywej oddechowej w Pythonie

Author avatar

Jakub Domaszewicz

Ostatnia aktualizacja3 grudnia 2021

Wykres krzywej oddechowej w Pythonie

Zbuduj w Pythonie wykres krzywej oddechowej w czasie rzeczywistym, korzystając z Aidlab SDK, filtrując dane i rysując go przy użyciu matplotlib.

Aidlab SDK udostępnia w Pythonie nowe możliwości, takie jak filtrowanie sygnałów czy dostęp do modułu wykrywania ćwiczeń. Dzięki nim możemy tworzyć bardziej rozbudowane projekty. Zobaczmy, jak filtrowanie danych przydaje się w projektach wykorzystujących oddech.

Wbudowany w Aidlab impedancyjny czujnik oddechu dostarcza wielu przydatnych danych, m.in. częstości oddechu i aktualnego poziomu wentylacji. Możesz na przykład stworzyć grę podobną do Birds, w której sterujesz ptakiem za pomocą oddechu.

W Aidlab SDK filtrowanie jest domyślnie włączone, dlatego do rozpoczęcia pomiaru oddechu wystarczy stosunkowo prosty kod:

import asyncio

from aidlab import AidlabManager, DataType, DeviceDelegate, DisconnectReason

class MainManager(DeviceDelegate):
    async def run(self):
        devices = await AidlabManager().scan()
        if len(devices) > 0:
            print("Connecting to:", devices[0].address)
            await devices[0].connect(self)
            while True:
                await asyncio.sleep(1)

    def did_connect(self, device):
        print("Connected to:", device.address)
        asyncio.create_task(device.collect([DataType.RESPIRATION], []))

    def did_disconnect(self, device, reason: DisconnectReason):
        print("Disconnected from:", device.address, reason)

    def did_receive_respiration(self, device, timestamp: int, value: float):
        print(value)

asyncio.run(MainManager().run())

Utwórz plik respiration-plotting.py, wklej do niego powyższy fragment i przygotuj następującą strukturę katalogów:

SleepDetector/
  |-- respiration-plotting.py

Zainstaluj Aidlab Python SDK za pomocą pip:

python -m pip install aidlabsdk

W tym poradniku przedstawimy zebrane próbki na wykresie. Użyjemy do tego matplotlib, biblioteki Pythona do tworzenia wykresów. Matplotlib oferuje wiele narzędzi, dzięki którym szybko i łatwo narysujesz różne typy wykresów. Przydaje się zarówno do prezentowania wyników uzyskanych za pomocą Aidlaba, jak i do wizualizacji danych wejściowych. Ta druga możliwość ułatwia zrozumienie problemu, który chcemy rozwiązać, oraz działania naszych modeli i algorytmów.

Zainstaluj matplotlib za pomocą pip:

pip install matplotlib

Jedną z zalet matplotlib jest proste API do rysowania wykresów:

import matplotlib.pyplot as pyplot
pyplot.plot([1,2,3,4])
pyplot.ylabel('some numbers')
pyplot.show()

Najważniejsza funkcja, plot, przyjmuje tablicę próbek i przedstawia je na wykresie:

Przykładowy wykres w matplotlib

Rysowanie wykresu w czasie rzeczywistym

Dane z Aidlaba napływają strumieniowo, więc nasz wykres musi być na bieżąco odświeżany o nowe próbki. Pokażemy dwa sposoby rysowania wykresów w czasie rzeczywistym: z użyciem FuncAnimation i bez tej funkcji.

FuncAnimation

Korzystanie z FuncAnimation jest stosunkowo proste. W naszym przykładzie przekazujemy trzy parametry:

  • obiekt figure, w którym chcemy narysować wykres,
  • funkcję aktualizującą wykres,
  • odstęp między odświeżeniami (w milisekundach).

Kod wygląda następująco:

figure = pyplot.figure()
axis1 = figure.add_subplot(1,1,1)

animation.FuncAnimation(figure, animate, interval=2)
pyplot.show()

Funkcję animate definiujemy tak:

def animate(self, i):
    global y
    axis1.clear()
    axis1.plot(x, y)

Listy x i y zawierają odpowiednio pozycje próbek na osi oraz wartości sygnału oddechowego.

ion

Możemy też skorzystać ze starszego rozwiązania: metody ion z matplotlib.pyplot.

ion włącza tryb interaktywny, który pozwala dynamicznie aktualizować dane na wykresie:

def live_plotter(self):

    if self.line == []:

        # This is the call to matplotlib that allows dynamic plotting
        pyplot.ion()
        self.fig = pyplot.figure(figsize=(13, 6))
        axis = self.fig.add_subplot(111)

        # Create a variable for the line so we can update it later
        self.line, = axis.plot(self.x, self.y, '', alpha=0.8)
        pyplot.show()

    # After the figure, axis, and line are created, we only need to update the
    # y-data
    self.line.set_ydata(self.y)

    # Adjust limits if new data goes beyond bounds
    pyplot.ylim([np.min(self.y) - np.std(self.y), np.max(self.y) + np.std(self.y)])

    # This pauses the data so the figure/axis can catch up - the amount of pause
    # can be altered above
    self.fig.canvas.flush_events()

Utwórzmy funkcję, która będzie odświeżać wykres w stałych odstępach czasu:

    def did_receive_respiration(self, device, timestamp, value):
          
        self.sample_index += 1

        chart_refresh_rate_in_milliseconds = 100
        # shift left
        self.y[:-1] = self.y[1:]
        self.y[-1] = value

        if self.current_time_in_milliseconds() - self.time > chart_refresh_rate_in_milliseconds:
            self.time = self.current_time_in_milliseconds()
            self.live_plotter()

def current_time_in_miliseconds(self):
    global second_in_miliseconds
    return int(round(time.time() * second_in_miliseconds))

Uruchomienie powyższego kodu rozpocznie wyszukiwanie urządzeń w pobliżu. Po nawiązaniu połączenia powinien pojawić się wykres podobny do tego:

Wykres sygnału oddechowego

Wznoszące i opadające fragmenty krzywej odpowiadają wdechom i wydechom.

Jeśli chcesz lepiej poznać matplotlib, zajrzyj do poradników na oficjalnej stronie matplotlib.