Zapisz jako PDF
Transkrypt
Zapisz jako PDF
Pomiar Elektrookulogramu Spis treści 1 Wstęp 1.1 Ćwiczenie I 1.2 Ćwiczenie II 1.3 Ćwiczenie III 1.4 Ćwiczenie IV 1.4.1 Napisz moduł: 1.4.2 Przetestuj moduł Wstęp Kolejnym narządem, w którym znajdują się generatory czynności bioelektrycznej jest oko. W narządzie tym zachodzą skomplikowane procesy biochemiczne i elektryczne, umożliwiające widzenie. Procesy te zostaną omówione na oddzielnym wykładzie, w tym miejscu zaś wymienimy tylko te zjawiska, które mają wpływ na powstawanie w oku czynności elektrycznej. 1. Jednym z najważniejszych części oka jest siatkówka, której zadaniem jest odbieranie bodźców świetlnych oraz zamiana ich na sygnały elektryczne, przekazywane dalej do kory wzrokowej. W siatkówce płynie nieustannie prąd, którego natężenie zmienia się wraz z intensywnością padającego na nią światła. Związane z tym sygnały bioelektryczne można rejestrować za pomocą elektrod umieszczonych na powierzchni oka lub nawet za pomocą elektrod umieszczonych na powierzchni skóry wokół oka. Tak zarejestrowany sygnał elektryczny, powstały w oku w trakcie widzenia, nazywamy Elektroretinogramem (ERG). Sygnał ten ma amplitudę od kilku nanowoltów do kilku μV i jest wykorzystywany w diagnostyce wielu chorób siatkówki. 2. Rogówka (zewnętrzna warstwa oka znajdująca się w jego przedniej części) jest naładowana dodatnio względem siatkówki umiejscowionej po przeciwnej stronie oka. Rogówka wraz z siatkówką tworzą zatem w przybliżeniu układ dipola elektrycznego. W momencie ruchu okiem, dipol ten zmienia orientację w przestrzeni, zaburzając rozkład natężenia pola elektrycznego. Związany z tym sygnał o amplitudzie kilku miliwoltów można zmierzyć za pomocą elektrod umieszczonych na skórze wokół oka. Widoczny jest ona także na elektrodach umieszczonych na powierzchni głowy w trakcie pomiary czynności elektrycznej mózgu. Sygnał ten, czyli elektryczny zapis ruchu gałek ocznych, nazywamy Elektrookulogramem (EOG). Czynność elektryczną związaną z ruchem gałek ocznych obserwuje się również w trakcie mrugania, kiedy to gałki oczne skręcają nieco ku górze (tzw. zjawiska Bella), a także w trakcie badań diagnostycznych zaburzeń snu (w różnych etapach snu występują wolne lub szybkie ruchy gałek ocznych). Sygnał EOG można też wykorzystać do konstrukcji interfejsów [[1]]. 1. Ruch oka sterowany jest za pomocą mięśni. W trakcie rejestracji Elektrookulogramu widoczne będą również wyładowania elektryczne związane z działaniem mięśni. Ćwiczenie I Wykonaj pomiar Elektrokulogramu za pomocą dwóch par elektrod połączonych w montażu dwubiegunowym. Jedną parę elektrod umieść poniżej i powyżej oka, drugą w pobliżu lewej i prawej skroni. Skonfiguruj program do rejestracji i przeglądania mierzonego sygnału w czasie rzeczywistym. Wykonaj ruch oczami w górę i opisz zarejestrowany sygnał. Wykonaj ruch oczami w dół i opisz zarejestrowany sygnał. Wykonaj mrugnięcie i opisz zarejestrowany sygnał. Przeczytaj fragment tekstu, zaobserwuj efekty związane z ruchem sakadowym oka. Zarejestruj sygnały w wyżej wymienionych sytuacjach. Wyświetl te sygnały w programie napisanym samodzielnie, bez stosowania filtra grórnoprzepustowego. Ćwiczenie II Powtórz ćwiczenie I, łącząc elektrody z monopolarnymi wejściami wzmacniacza, elektrodę odniesienia umieść na lewym płatku uszu lub wyrostku sutkowatym. Ćwiczenie III Napisz program wyświetlający na macierzy 5x5 następujące sekwencje: kwadrat środkowy - kwadrat górny - kwadrat środkowy kwadrat środkowy - kwadrat prawy - kwadrat środkowy kwadrat środkowy - kwadrat dolny - kwadrat środkowy kwadrat środkowy - kwadrat lewy - kwadrat środkowy Zapisuj do pliku tekstowego czasy i kody poszczególnych sekwencji. Wyświetl te sygnały w programie napisanym samodzielnie, bez stosowania filtra grórnoprzepustowego. Zaprojektuj detektor, wykrywający, która sekwencja została wykonana. Ćwiczenie IV Zrealizuj prosty system do rejestracji ruchu gałki ocznej, tzw. Eye tracker. w tym celu: Napisz moduł: Korzystając detektora sekwencji napisanego w ramach ćwiczenia III napisz moduł wykrywający sekwencje w czasie rzeczywistym. Niech Twój moduł wypisuje wynik detekcji na konsolę. Opis korzystania i pisania modułów do systemu OBCI znajduje się [tutaj]. W dużym skrócie to co należy zrobić to: W katalogu domowym utwórz podkatalog: ~/obci/scenarios w katalogu tym umieść plik: eog.ini powinien on zawierać następującą treść: [peers] scenario_dir= ;*********************************************** [peers.mx] path=multiplexer-install/bin/mxcontrol ;*********************************************** [peers.config_server] path=control/peer/config_server.py ;*********************************************** ;*********************************************** [peers.amplifier] path = drivers/eeg/cpp_amplifiers/amplifier_tmsi.py ;ponizsza sciezka pokazuje na plik zaierajacy nasze ustawienia parametrow wzmacniacza config=~/obci/scenarios/eog_local_params.ini [peers.analysis] path=~/obci/analysis/eog_realtime.py config=~/obci/analysis/eog_realtime.ini W powyższym pliku zadeklarowaliśmy, że lokalne parametry dla wzmacniacza znajduję się w pliku: ~/obci/scenarios/eog_local_params.ini zatem musimy ten plik wytworzyć i wypełnić go np. taką treścią: [local_params] channel_names=gora;dol;lewa;prawa active_channels=0;1;2;3 sampling_rate=256 W pliku ze scenariuszem zadeklarowaliśmy też, że nasz moduł analizy danych znajduje się w pliku: ~/obci/analysis/eog_realtime.py tak więc musimy ten plik stworzyć i tam właśnie wpisać algorytm detekcji. Dla zachowania konwencji w tym samym katalogu powinien znajdować się plik na ewentualne parametry dla modułu eog_realtime.py. Musi on się nazywać tak samo, tyle, że ma rozszerzenie .ini. Musimy więc wytworzyć pusty plik: ~/obci/analysis/eog_realtime.ini Ponieważ nasz algorytm musi on się komunikować z resztą systemu obci trzeba go opakować w poniższy kod-szkielet: #!/usr/bin/env python # -*- coding: utf-8 -*import random, time, numpy from multiplexer.multiplexer_constants import peers, types from obci.control.peer.configured_multiplexer_server import ConfiguredMultiplexerServer from obci.configs import settings, variables_pb2 from collections import deque import obci.utils.openbci_logging as logger #LOGGER = logger.get_logger("sample_analysis", "info") LOGGER = logger.get_logger("sample_analysis", "debug") class SampleAnalysis(ConfiguredMultiplexerServer): """A class responsible for handling signal message and making proper decision. The class inherits from generic class for convinience - all technical stuff is being done in this super-class""" def __init__(self, addresses): """Initialization - super() and ready() calls are required...""" super(SampleAnalysis, self).__init__(addresses=addresses, type=peers.ANALYSIS) self.ready() LOGGER.info("Sample analysis init finished!") def handle_message(self, mxmsg): """The only required function in the class that will be fired every time message is received""" if mxmsg.type == types.AMPLIFIER_SIGNAL_MESSAGE: # Got proper message, let`s unpack it ... # Messages are transmitted in bunches so lets define SampleVector # in order to unpack bunch of Sample messages ... l_vect = variables_pb2.SampleVector() l_vect.ParseFromString(mxmsg.message) # Now we have message unpacked, lets iterate over every sample ... for s in l_vect.samples: # Every sample has two fields: # timestamp - system clock time of a moment of Sample`s creation # channels - a list of values - one for every channel LOGGER.debug("Got sample with timestamp: "+str(s.timestamp)) # One can copy samples to numpy array ... a = numpy.array(s.channels) # w tym miejscu mamy w tablicy a "paczke" próbek (domyślnie 4próbki ) ze wszystkich zadeklarowanych kanalow #################### TU TRZEBA WPISAC SWOJ KOD BUFOROWANIA i ANALIZY ############## print a #na dobry poczatek wypiszmy probki #################################################################### # Or just iterate over values ... for ch in s.channels: LOGGER.debug(ch) # Having a new bunch of values one can fire some magic analysis and # generate decision .... # Below we have quite simple decision-maker - it generates a random # decision every ~100 samples-bunch ########## TU NA PODSTAWIE ANALLIZY PODEJMUJEMY DECYZJE I MOZEMY JA PRZEKAZAC DO RESZTY SYSTEMU OBCI ###################### ########## W TYM PRZYKLADZIE JEST TO LOSOWA DECYZJA ############## ########## W TYM CWICZENIU WYSTARCZY JESLI WYPISZECIE DECYZJE NA EKRAN ########### if random.random() > 0.99: # Here we send DECISION message somewhere-to-the-system ... # It's up to scenario's configuration how the decision will be used ... # Eg. it might be used by LOGIC module to push some button in speller. self.conn.send_message(message = str(random.randint(,7)), type = types.DECISION_MESSAGE, flush=True) else: LOGGER.warning("Got unrecognised message type: "+str(mxmsg.type)) # Tell the system 'I`ll not respond to this message, I`m just receiving' self.no_response() if __name__ == "__main__": # Initialize and run an object in order to have your analysis up and running SampleAnalysis(settings.MULTIPLEXER_ADDRESSES).loop() Aby uruchomić nasz scenariusz trzeba wywołać: obci launch ~/obci/scenarios/eog.ini Zatrzymanie scenariusza robimy tak: obci kill eog W tym momencie komunikaty ze wszystkich modułów wypisywane są na jednej konsoli. Przydatne jest korzystanie z obiektu 'LOGGER' zamiast funkcji 'print' - w konsoli mamy informację o źródle komunikatu i jego czasie. OpenBCI działa tak, że jeśli w jednym module pojawi się błąd, to wszystkie inne moduły są zamykane, stąd komunikat podobny do poniższego sugeruje, że w którymś module wystąpił błąd. W takim wypadku należy przejrzeć konsolę i wyszukać komunikat błędu. Niezbędne jest ustawienie bufora konsoli na 'nieograniczony' wykonując: Edycja->Preferencje profilu->Przewijanie->Nieograniczone . Przetestuj moduł Umieść elektrody do rejestracji ruchu gałki ocznej jak w ćwiczeniu I i przetestuj działanie modułu. Miłej zabawy :-)