QRS_DET
Transkrypt
QRS_DET
AKADEMIA GÓRNICZO-HUTNICZA im. St. Staszica w Krakowie WEAIiE, Katedra Automatyki Laboratorium Biocybernetyki Przedmiot: Przetwarzanie sygnałów w systemach diagnostyki medycznej. QRS_DET Temat projektu: Detekcja i synchronizacja reprezentacji uderzenia serca (zespołu QRS) Raport końcowy Wykonali: Kozera Tomasz, Rębisz Paweł V rok Informatyka Stosowana Wydział EAIiE prowadzący: dr hab. inŜ. Piotr Augustyniak Wersja 1.0 Kraków, październik 2009 – styczeń 2010 -1- Spis treści: 1 ABSTRAKT.................................................................................................................................................. 3 1.1 1.2 1.3 1.4 1.5 2 Główne cele i załoŜenia projektu .........................................................................................3 Opis wybranej metody .........................................................................................................3 Podsumowanie najwaŜniejszych osiągnięć i rezultatów......................................................3 Główne wnioski i ich znaczenie...........................................................................................3 Słowa kluczowe ...................................................................................................................3 WSTĘP.......................................................................................................................................................... 4 2.1 2.2 2.3 Główne cele i załoŜenia projektu .........................................................................................4 Opis wybranej metody .........................................................................................................4 Dyskusja alternatywnych rozwiązań....................................................................................6 3 KONCEPCJA PROPONOWANEGO ROZWIĄZANIA......................................................................... 6 4 REZULTATY I WNIOSKI ......................................................................................................................... 6 5 PODSUMOWANIE ..................................................................................................................................... 8 6 LITERATURA ............................................................................................................................................. 8 7 DODATEK A: OPIS OPRACOWANYCH NARZĘDZI I METODY POSTĘPOWANIA .................. 9 7.1 7.2 7.3 7.4 8 Opis plików aplikacji ...........................................................................................................9 UŜytkowanie aplikacji..........................................................................................................9 Interpretacja otrzymanych wyników..................................................................................12 Wyświetlenie otrzymanych wyników................................................................................12 DODATEK B: REALIZACJA PROPONOWANEGO ROZWIĄZANIA............................................ 14 8.1 Opis zastosowanej metody wraz z modyfikacjami usprawniającymi................................14 8.2 Napotkane problemy ..........................................................................................................15 8.2.1 Ekstrakcja danych z MIT-BIH..........................................................................................15 8.2.2 Problemy z wykrywaniem załamków ...............................................................................16 8.2.3 Problemy z aplikacją daubwave........................................................................................16 8.2.4 Niuanse języka C++..........................................................................................................16 8.2.5 Niuansów ciąg dalszy: problem z delete [].......................................................................17 8.2.6 Problem z ‘Build clean’ ...................................................................................................18 8.2.7 RozbieŜność działania.......................................................................................................19 9 DODATEK C. OPIS INFORMATYCZNY PROCEDUR...................................................................... 19 10 DODATEK D. SPIS ZAWARTOŚCI DOŁĄCZONYCH NOŚNIKÓW (DYSKIETEK, CD ROMU)19 -2- 1 Abstrakt 1.1 Główne cele i załoŜenia projektu Celem projektu jest wybranie i zaimplementowanie algorytmu detekcji zespołów QRS w sygnałach EKG. Wyniki pracy naleŜy sprawdzić na sygnałach bazy MIT-BIH dostępnych w ramach witryny Physionet.org. 1.2 Opis wybranej metody Wybrana przez nas metoda została zaprezentowana w pracy [1]. Głównym jej załoŜeniem jest zastosowanie transformaty falkowej z uŜyciem falek Daubechies do wykrywania załamków P-QRST. Dokładny opis znajduje się w rozdziale 2.2. 1.3 Podsumowanie najwaŜniejszych osiągnięć i rezultatów Zastosowana metoda okazała się być niewystarczająco skuteczna. Konieczne było wprowadzenie własnych usprawnień, po których udało nam się uzyskać poprawność detekcji rzędu 95%. Średni czas działania algorytmu dla 1024 próbek wynosi 383 ms. Sprawność stworzonego algorytmu nie zaleŜy od częstotliwości próbkowania. Algorytm został przetestowany na 46 sygnałach testowych z bazy danych MIT-BIH. 1.4 Główne wnioski i ich znaczenie Przytoczona w pracy [1] metoda okazała się być mało skuteczna i podatna na ilość próbek badanego sygnału. Konieczne było wprowadzenie własnych modyfikacji w celu poprawienia działania algorytmu. Metoda nie spełniła naszych oczekiwań – okazała się mieć niewystarczającą jakość detekcji, jednocześnie będąc stosunkowo skomplikowaną metodą. Wprowadzenie poprawek zajęło nam większą część pracy nad niniejszym projektem. Dodatkowo IDE, z którego korzystaliśmy (Dev-Cpp) okazało się być mało funkcjonalne i obarczone błędami (więcej w dziale 8). 1.5 Słowa kluczowe EKG, detekcja QRS, zastosowanie falek Daubechies -3- 2 Wstęp 2.1 Główne cele i załoŜenia projektu Celem projektu jest wybranie i zaimplementowanie algorytmu detekcji zespołów QRS w sygnałach EKG. Wyniki pracy naleŜy sprawdzić na sygnałach bazy MIT-BIH dostępnych w ramach witryny Physionet.org. 2.2 Opis wybranej metody Wybrana przez nas metoda została zaprezentowana w pracy [1]. Głównym jej załoŜeniem jest zastosowanie transformaty falkowej z uŜyciem falek Daubechies do wykrywania załamków P-QRST. Transformata falkowa jest splotem funkcji falkowej Ψ(t) z sygnałem x(t). Ortonormalne dyskretne falki są skojarzone z funkcją skalującą φ(t). Po dokonaniu splotu funkcji skalującej z sygnałem otrzymamy współczynniki aproksymacji S. Dyskretna transformata falkowa moŜe być zapisana jako: Tm, n = ∞ ∫ x(t )ψ m, n (t )dt (2.2.1) −∞ Współczynniki aproksymacji w skali m i połoŜeniu n moŜna rozpisać jako: S m, n = ∞ ∫ x(t )ϕ m, n (t )dt (2.2.2) −∞ W praktyce, sygnał S0,n posiada skończoną długość N taką, Ŝe N = 2M. Zatem zakres osiągalnych skal m wynosi 0 < m < M. Dyskretna aproksymacja sygnału x(t) wyraŜa się wzorem: M x0 (t ) = xM (t ) + ∑ d m (t ) (2.2.3) m =1 gdzie średnia aproksymacja sygnału w skali M to xM (t ) = S M , nϕ M , n (t ) (2.2.4) a dokładna aproksymacja sygnału w skali m d m (t ) = 2 M − m −1 ∑T n =0 ψ m,n (t ) (2.2.5) m ,n Dodając aproksymację sygnału w skali M do sumy wszystkich otrzymanych aproksymacji sygnału we wszystkich osiągalnych skalach otrzymujemy aproksymację oryginalnego sygnału w -4- skali 0. Aproksymacja sygnału w określonej skali jest kombinacją aproksymacji i przybliŜenia w niŜszej skali: xm(t) = xm-1(t)-dm(t) (2.2.6) przykładowo, jeŜeli skala m=3 to x3(t) = x0(t) – d1(t) –d2(t) – d3(t) (2.2.7) Oznacza to sukcesywne pozbywanie się informacji odnośnie wyŜszych częstotliwości z oryginalnego sygnału w kaŜdym kroku. Nosi to nazwę wielorozdzielczej analizy sygnału przy uŜyciu transformaty falkowej (multiresolution analysis of a signal using wavelet transform) i jest to metoda wykorzystana w pracy [1]. Falki Daubechies moŜna podzielić na 10 grup D2-D20 (tylko liczby parzyste). Liczba oznacza tutaj ilość współczynników falki. Wyznaczają one zdolność falki do reprezentacji sygnału w formie wielomianu. JeŜeli dana jest grupa Dn to falka jest w stanie opisywać wielomiany rzędu n lub niŜszego. 2 W metodzie zaproponowanej w pracy [1] najpierw przystępujemy do wykrycia załamka R. Jest on najbardziej charakterystyczny i najłatwiejszy do odnalezienia. Następnie, zwiększając poziom szczegółowości (skalę falki), szukamy sąsiednich załamków (Q i S). Dalsza część metody nie jest nam potrzebna w tej pracy (wykrycie załamków P i T). W pracy [1] wykorzystano grupy D4 i D6 do detekcji załamków P-QRS-T. Wyniki przytoczone są zadowalające – osiągnięto dokładność detekcji zespołów P-QRS-T rzędu 99.18%. 2.2.8 Schemat blokowy algorytmu zaproponowanego w pracy [1] -5- 2.3 Dyskusja alternatywnych rozwiązań Inne rozwaŜane przez nas metody opisane w pracach [2], [3] i [4] charakteryzują się gorszym współczynnikiem detekcji zespołów QRS i niekiedy brakiem moŜliwości detekcji w sygnałach próbkowanych częstotliwościami innymi niŜ ta którą narzuca dana metoda. Przeglądając róŜne artykuły z zakresu zespołów QRS czy ogólnie badań EKG, zauwaŜyliśmy, Ŝe bardzo często wykorzystuje się podejście bazujące na transformatach falkowych co potwierdza celowość naszego wyboru. 3 Koncepcja proponowanego rozwiązania Pierwszym etapem jest stworzenie oddzielnej aplikacji umoŜliwiającej wyświetlenie sygnału EKG z zaznaczeniem załamków QRS. Program taki pomoŜe nam na etapie pisania aplikacji we wstępnej analizie poprawności działania – umoŜliwi nam on wizualne sprawdzenie czy załamki są poprawnie wykrywane, a w dalszej kolejności sprawdzenie czy pokrywają się one z faktycznymi umiejscowieniami załamków, zaznaczonych w plikach dostarczonych z bazy MIT-BIH. Kolejnym etapem jest stworzenie właściwej części aplikacji poczynając od procedur do wczytywania danych z pliku z sygnałem, poprzez detekcję QRS aŜ do zapisania wyników do struktury Beats.Det wraz z opcją eksportu do pliku. Do wykrywania załamków QRS zostanie zastosowana falka Daubechies o poziomie skali m=3, poniewaŜ zgodnie z wynikami ukazanymi w pracy [1] daje ona moŜliwość stosowania dobrej detekcji (rzędu 99,18%) przy braku duŜych narzutów obliczeniowych. Do wykonania obliczeń falkowych została uŜyta aplikacja ‘Daubwave’ Stevena Gollmera – pracownika Purdue University of West Lafayette (strona internetowa projektu podana w [5]). 4 Rezultaty i wnioski Po zastosowaniu detekcji zespołów QRS opisaną metodą okazało się, Ŝe wyniki są wysoce nie zadawalające i rozbieŜne z danymi przytoczonymi w pracy [1]. W praktyce uzyskaliśmy detekcję zespołów QRS na poziomie ok. 80-90%, a błędne wykrycie nieistniejących zespołów sięgało rzędu 5-10%. Dokładna przyczyna rozbieŜności wyników nie jest dla nas jasna, aczkolwiek biorąc pod uwagę drobne niuanse związane z aplikacją ‘Daubwave’ mamy podstawy ku temu by sądzić, iŜ -6- moŜe to być wina tej aplikacji (więcej na ten temat w rozdziale 8), natomiast metoda przytoczona w [1] jako taka, moŜe być dobra. W związku z wystąpieniem powyŜszego problemu musieliśmy zastosować środki mające na celu korekcję błędnych detekcji, zaczynając od skorygowania wykrycia wierzchołków R. W tym celu napisaliśmy procedury, które miały za zadanie przeszukanie sąsiedztwa rzekomego wystąpienia wierzchołka R i sprawdzenie czy nie znajduje się on zbyt blisko innego juŜ wykrytego wierzchołka, bądź teŜ czy w sąsiedztwie nie znajduje się punkt o większej amplitudzie. Dzięki zastosowaniu takiego podejścia udało nam się zmniejszyć błąd detekcji z ok. 10-15% do ok. 95% oraz błąd wykrywania nieistniejących załamków z ok. 5-10% do ok. 5%. Następnym problemem okazało się wykrywanie załamków Q i S, które pomimo podobnych zabiegów nie przyniosło widocznej poprawy. W związku z tym dokonaliśmy modyfikacji metody polegającej na tym, Ŝe wierzchołki Q oraz S są wykrywane metodą znalezienia minimum lokalnego funkcji sygnału odpowiednio po lewej lub prawej stronie wykrytego wierzchołka R. Efekty okazały się bardzo dobre – o ile wierzchołek R jest wykryty poprawnie, to wierzchołki Q oraz S równieŜ są wykrywane poprawnie. Średni czas działania algorytmu dla 1024 próbek wynosi 383 ms, co daje czas rzędu 24,31 sek. dla sygnału posiadającego 650 000 próbek (sygnały testowe z bazy MIT-BIH, 30 minutowe zapisy EKG z próbkowaniem 360Hz). Działanie algorytmu zostało sprawdzone dla róŜnych częstotliwości próbkowania (90, 180, 360 Hz) – sprawność algorytmu jest taka sama niezaleŜnie od częstotliwości. Testy zostały wykonane na 46 sygnałach dostępnych w ramach bazy MIT-BIH. Jako wnioski z powyŜszej pracy musimy stwierdzić, Ŝe zastosowana metoda nie osiągnęła zamierzonych rezultatów a jej jakość detekcji jest niezadowalająca z medycznego punktu widzenia. Błąd wykrywania zespołów QRS na poziomie 95% jest według nas niedopuszczalny w systemie mającym na celu wykrywanie poprawnej pracy serca. Kolejnym problemem jest to, Ŝe wykrywanie zespołów QRS powyŜszą metodą wnosi wymóg aby ilość próbek badanego sygnału była niewiele mniejsza lub równa 2n, n ∈ N . W praktyce okazało się, Ŝe jeŜeli liczba próbek jest niewiele większa niŜ 2n to detekcja działa źle – skuteczność jest poniŜej 50%. Wynika to z faktu, Ŝe w przypadku niedostatecznej ilości próbek dostarczonych do programu daubwave brakujące elementy są uzupełniane zerami i jeŜeli takich elementów jest odpowiednio duŜo to otrzymane wyniki bardzo odbiegają od stanu faktycznego. -7- 5 Podsumowanie Metoda, którą wybraliśmy okazała się mało skuteczna i bardzo czuła na ilość próbek jaką posiada badany sygnał. W celu usprawnienia detekcji musieliśmy zastosować szereg działań korygujących, co pozwoliło na znaczną poprawę detekcji zespołów QRS. Średni czas trwania detekcji dla 1024 próbek wynosi 383 ms. Poprawność wykrywania załamków QRS jest na poziomie 95%. Metoda okazała się być mniej skuteczna niŜ przedstawiono w pracy [1]. Pomimo zastosowania usprawnień metoda nie spełniła naszych oczekiwań. 6 Literatura [1] S. Z. Mahmoodabadi, A. Ahmadian, M. D. Abolhasani, “ECG FEATURE EXTRACTION USING DAUBECHIES WAVELETS” [2] JC Hsieh, WC Tzeng, YC Yang, SM Shieh, „Detecting ECG Characteristic Points by Novel Hybrid Wavelet Transforms: Evaluation of Clinical SCP-ECG Database„ [3] P Castiglioni, L Piccini, M Di Rienzo, “Interpolation Technique for Extracting Features from ECG Signals Sampled at Low Sampling Rates” [4] F Chiarugi, V Sakkalis, D Emmanouilidou, T Krontiris, M Varanini, I Tollis, “Adaptive Threshold QRS Detector with Best Channel Selection Based on a Noise Rating System” [5] strona projektu ‘Daubwave’ autorstwa Stevena Gollmera: http://archives.math.utk.edu/software/msdos/modelling/daubwave/.html [6] Baza danych MIT-BIH zawierająca sygnały w formacie 212: http://physionet.org/physiobank/database/mitdb/ [7] Specyfikacja uŜytkowania aplikacji rdsamp: http://www.physionet.org/physiotools/wag/rdsamp-1.htm -8- 7 DODATEK A: Opis opracowanych narzędzi i metody postępowania 7.1 Opis plików aplikacji W katalogu z aplikacją powinny znajdować się: • daubwave.exe – aplikacja autorstwa Stevena Gollmera (do pogrania z [5]) wykonująca transformatę falkową falkami Daubechies, • rdsamp.exe - aplikacja z witryny Physionet.org mająca na celu umoŜliwienie ekstrakcji danych z bazy MIT-BIH do formatu tekstowego (aplikacja wymaga bibliotek: cygcrypto0.9.8.dll, cygcurl-4.dll, cygssh2-1.dll, cygssl-0.9.8.dll, cygwfdb-10-4.dll, cygwin1.dll, cygz.dll). Opis rdsamp jest dostępny w [7], • qrs_det.exe – nasza aplikacja, • disp_dat.m - skrypt w Matlabie mający na celu wyświetlanie wyników działania aplikacji, • signals (katalog) – katalog zawierający badane sygnały w formie tekstowej bądź MIT-BIH (zgodne z formatem 212 i posiadające kanał MLII; moŜliwe do pobrania z [6] - są to wszystkie dostępne tam sygnały za wyjątkiem 102 i 104, które nie posiadają kanału MLII). 7.2 UŜytkowanie aplikacji W celu dokonania detekcji zespołów QRS stworzyliśmy aplikację, którą moŜna uruchomić z poziomu konsoli systemowej. Aplikacją jest plik qrs_det.exe. Po uruchomieniu bez Ŝadnych parametrów otrzymamy informację na temat dostępnych opcji: 7.2.1 Zrzut ekranu o dostępnych opcjach -9- Aplikacja moŜe działać z plikami sygnału przygotowanymi w formie tekstowej (kaŜda linijka to kolejne wartości próbki, typu float) lub z danymi dostępnymi w ramach bazy danych MIT-BIH. Sygnały te moŜna pobrać z [6]. W przypadku pracy na sygnałach z bazy MIT-BIH konieczna jest konwersja z formatu 212 na format tekstowy. W tym celu uŜywana jest aplikacja rdsamp (opis w [7]). Ekstrakcja działa w przypadku sygnałów posiadających kanał MLII, dlatego teŜ sygnały 102 i 104 dostępne w [6] nie są obsługiwane. Tym nie mniej dostępnych jest 46 z 48 zamieszczonych sygnałów. Pliki z sygnałami do badania muszą znajdować się w katalogu signals/. W celu dokonania detekcji zespołów QRS na przykładowym pliku 100.dat (format MITBIH) naleŜy wywołać aplikację z parametrem będącym nazwą pliku bez rozszerzenia oraz opcją ‘-f360’. Opcja ta ustala częstotliwość próbkowania badanego sygnału (w Hz) – wszystkie sygnały zawarte w [6] posiadają częstotliwość próbkowania równą 360 Hz. Zatem pełna komenda do wywołania wygląda następująco: qrs_det 100 –f360 Po uruchomieniu nastąpi ekstrakcja danych do formy tekstowej oraz detekcja zespołów QRS. 7.2.2 Zrzut ekranu w czasie działania aplikacji W przypadku gdy posiadamy dane gotowe w formie tekstowej naleŜy dodać jeszcze opcję ‘-t’, która informuje program o tym Ŝe dane są w formie tekstowej. -10- Gdy dane są w formie pliku z bazy MIT-BIH po skończeniu działa programu w katalogu signals/ powstanie plik o nazwie takiej jak badany sygnał z dodatkiem ‘_extracted’ na końcu nazwy (np.: ‘100_extracted.dat’ dla sygnału ‘100’). Plik ten zawiera dane w formie tekstowej wyeksportowane z sygnału MIT-BIH, moŜna go zatem uŜywać w przyszłości. Dzięki temu nie będzie konieczne kaŜdorazowe wyciąganie danych z plików MIT-BIH, co zajmuje dość duŜo czasu. Dodatkową opcją programu jest wykonanie detekcji nie na całym sygnale lecz na wyznaczonej części. UŜywa się do tego opcji ‘-b’ (begin) oraz ‘-e’ (end), po których podajemy liczby (bez spacji) wyznaczające początek oraz koniec obszaru detekcji. Obszar ten jest podawany w sekundach i jest obustronnie domknięty. Przykład 1: Uruchomienie aplikacji na danych MIT-BIH dla całego sygnału: qrs_det 100 –f360 Przykład 2: Uruchomienie aplikacji na danych w formie tekstowej dla całego sygnału: qrs_det 100_extracted –f360 –t Przykład 3: Uruchomienie aplikacji na danych w formie tekstowej dla okresu od 30s do 190s: qrs_det 100_extracted –f360 –t –b30 –e190 Przykład 4: Uruchomienie aplikacji na danych w formie tekstowej dla okresu od 30s do 190s, z częstotliwością próbkowania 200 Hz: qrs_det 100_extracted –f200 –t –b30 –e190 Przykład 5: Wyświetlenie informacji o składni parametrów programu: qrs_det lub qrs_det -? -11- 7.3 Interpretacja otrzymanych wyników Wyniki znajdują się w katalogu output. Plik z wynikiem posiada rozszerzenie .qrs. Plik jest plikiem tekstowym, w którym kaŜda kolejna linijka zawiera informację o kolejnych zespołach QRS zgodnie z poniŜszą specyfikacją: Q Qtime Qval R Rtime Rval S Stime Sval gdzie: • Q, R, S – numer próbki w której występuje dany wierzchołek (int32), • Qtime, Rtime, Stime – czas wystąpienia wierzchołka podany w sekundach (float), • Qval, Rval, Sval – wartość sygnału w tym punkcie (float), 7.4 Wyświetlenie otrzymanych wyników Do obejrzenia wyników słuŜy załączony skrypt w Matlabie (disp_dat.m). Przed uruchomieniem naleŜy ustawić wartości zmiennych singalFile oraz detectionFile tak aby wskazywały odpowiednio na plik z sygnałem w postaci tekstowej oraz plik z wynikami działania aplikacji. Przykład ustawienia zmiennych dla wyświetlania wyników detekcji wykonanej na pliku 100 z bazy MIT-BIH: signalFile = 'signals/100_extracted.dat'; detectionFile = 'output/100.qrs'; Po ustawieniu zmiennych moŜna uruchomić skrypt. Wyświetlony zostanie wykres przedstawiający sygnał oraz wykryte wierzchołki zespołów QRS. -12- 7.4.1 Wykresy przedstawiające badany sygnał wraz z zaznaczonymi zespołami QRS • Kolorem niebieskim zaznaczono badany sygnał (wykres punktowy oraz liniowy), • Kolorem czerwonym zaznaczono wierzchołki Q, • Kolorem zielonym zaznaczono wierzchołki R, • Kolorem czarnym zaznaczono wierzchołki S, -13- 8 DODATEK B: Realizacja proponowanego rozwiązania 8.1 Opis zastosowanej metody wraz z modyfikacjami usprawniającymi PoniŜej zamieszczamy opis działania części programu odpowiedzialnej za przygotowanie danych potrzebnych do rozpoczęcia rozpoznania załamków. Detekcja odbywa się w funkcji QRS_DET(). PoniŜsze operacje mają na celu przygotowanie danych i parametrów w sposób symulujący ustawienie tych informacji przez inne części wspólnej aplikacji „Analiza Elektrokardiogramu”: • Sprawdzenie poprawności danych przekazanych z konsoli. W przypadku błędu wyświetlona zostaje informacja o błędzie oraz składna opcji programu (help). Program kończy działanie. • Inicjalizacja wspólnych struktur programu „Analiza Elektrokardiogramu” danymi potrzebnymi do działania niniejszej aplikacji (np.: typ rozszerzenia plików z danymi, maksymalna długość sygnału). • Ewentualna ekstrakcja danych z pliku MIT-BIH do formy tekstowej. • Przepisanie przekazanych parametrów do struktury sterującej działaniem aplikacji QRS_DET. • Uruchomienie funkcji QRS_DET() odpowiedzialnej za działanie właściwej aplikacji. • Zwolnienie pamięci zajmowanej przez wspólne struktury danych. • Usunięcie plików tymczasowych. Opis działania QRS_DET(): • Pobranie danych sterujących ze struktury DetConf oraz danych z innych wspólnych struktur. • Sprawdzenie poprawności pobranych danych (np.: czy podany zakres czasowy jest poprawny). • Utworzenie tymczasowych katalogów do przechowania potrzebnych plików. • Ustalenie zakresu detekcji. • W pętli wykonywane są operacje mające na celu detekcję załamków QRS na zadanym przedziale: stworzenie tymczasowego pliku z próbkami z aktualnie badanego zakresu (konieczne dla daubwave), wywołanie na powyŜszym pliku aplikacji daubwave – detekcja załamków R metodą falkową, -14- wywołanie metody weryfikującej i poprawiającej detekcję oraz zapisującej wyniki do pliku tekstowego (funkcja detection(...)). • Zapisanie danych do wspólnych struktur. PoniŜej znajduje się schemat blokowy działania funkcji detection(...). Jest to kluczowa funkcja algorytmu w której odbywa się korekcja wyników uzyskanych przez daubwave: F-DWT Poziom szczeg . R-DWT Weź kolejny domniemany R T Czy nowy R jest odległy od poprzedniego o co najmniej 0.25 sek? Jako R wybierz maksimum lokalne z sąsiedztwa domniemanego R Podniesienie do kwadratu Thresholding 5% z MAX N Znajdź Q jako minimum lokalne lewego sąsiedztwa R Znajdź S jako minimum lokalne prawego sąsiedztwa R Zapisz Q,R,S 8.1.1 Schemat blokowy funkcjonalności odpowiedzialnej za detekcję załamków QRS 8.2 Napotkane problemy 8.2.1 Ekstrakcja danych z MIT-BIH Pierwszym powaŜnym problemem było skorzystanie z danych udostępnionych w [6]. Nie udało nam się uzyskać informacji o formacie udostępnianego pliku .dat w ramach witryny Physionet.org. Informacje te udało nam się znaleźć dopiero po wyszukaniu ich na innych stronach internetowych. Tam teŜ znaleźliśmy informacje o aplikacji rdsamp udostępnianej w ramach witryny Physionet.org (link w [7]). Tym nie mniej problemem okazało się jej skompilowanie ze względu na brak duŜej ilości wymaganych bibliotek oraz liczne błędy kompilacji oraz linkowania. Ponownie zmuszeni byliśmy do szukania pomocy poza witryną Physionet.org. W efekcie udało nam się znaleźć skompilowaną i działającą wersję rdsamp wraz ze wszystkimi wymaganymi bibliotekami. -15- 8.2.2 Problemy z wykrywaniem załamków Następnym problemem było niezadawalające działanie metody przytoczonej w [1]. W celu poprawy działania algorytmu wprowadziliśmy własne usprawnienia do tej metody o czym moŜna przeczytać w Rozdziałach 4 oraz 8.1. 8.2.3 Problemy z aplikacją daubwave Aplikacja daubwave jak się okazało, jest bardzo czuła na rozmiar sygnału i w przypadku gdy jest on nieznacznie większy od 2n, n ∈ N detekcja zaczyna odbywać się nieprawidłowo. Początkowo nie wiedzieliśmy co jest przyczyną bardzo złych wyników wykrywania załamków. Podejrzewaliśmy, Ŝe być moŜe uŜywaliśmy tej aplikacji w zły sposób (np.: podając złe parametry). Okazało się, Ŝe w przypadku gdy liczba próbek jest za mała program uzupełnia sygnał zerami tak by otrzymać liczbę próbek równą 2n. JeŜeli ilość tak dopisanych zer jest niewielka (np.: podajemy 1000 próbek, dopisane zostają 24 zera) to aplikacja generuje dobre wyniki. W przeciwnym przypadku są one bardzo odległe od prawidłowych. Rozwiązaniem problemu było podzielenie sygnału przekazywanego do daubwave na częściowe sygnały o długości 1024 próbek. 8.2.4 Niuanse języka C++ W pewnym momencie pisania aplikacji występował u nas błąd, który objawiał się tym, Ŝe wartość zmiennej nie była przepisywana do elementu tablicy. Sytuacja wyglądała następująco: for(int i=0; i<cnt; i++){ cout << R[i] << endl; //1 R[i] = i; cout << R[i] << endl; //2 } Przy wykonywaniu powyŜszego kodu okazywało się, Ŝe wartości w R[i] były takie same w 1 jak w 2. Z praktycznego punktu widzenia wyglądało to tak jakby operacja przypisania wartości nie miała miejsca. Dokonaliśmy sprawdzenia czy tablica nie jest równa NULL i czy nie wychodzimy poza jej zakres – wszystko było w porządku. -16- Rozwiązanie problemu trwało kilka dni. Okazało się, Ŝe zmienna której uŜywaliśmy do określenia ilości pamięci potrzebnej do dynamicznego zaalokowania na tablicę R miała wartość ujemną. Było to z kolei konsekwencją dzielenia przez 0. To co jest dla nas bardzo ciekawe w tym problemie jest to, Ŝe podczas działania aplikacji nie dostawaliśmy błędu dzielenia przez zero czy alokowania pamięci na ujemną liczbę bajtów. Jak się okazało taki fakt rzeczywiście istnieje w języku C++ i jest moŜliwy do odtworzenia. PoniŜszy kod wykonuje się bez Ŝadnych błędów, pomimo Ŝe występuje w nim dzielenie przez 0 oraz alokowanie pamięci na ujemną liczbę bajtów: int main(int argc, char *argv[]){ double b,d; int c,a; int* p; a=10; b=1; d=0; c = (int)( ( (double)(a)+b )/d ); //dzielenie przez 0 cout << c; //wypisuje się -2147483648 p = new int[c]; //alokujemy pamięć na tablicę która ma -2147483648 elementów delete [] p; system("PAUSE"); return EXIT_SUCCESS; } 8.2.5 Niuansów ciąg dalszy: problem z delete [] Kolejnym ciekawym problemem była sytuacja w której aplikacja kończyła się z błędem (bez określenia typu błędu) w chwili gdy wykonywana była linijka delete [] p; Tutaj ponownie sprawdziliśmy wskaźniki oraz zakres tablicy. Wszystko wydawało się w porządku i w efekcie doszliśmy do momentu w którym aplikacja kończyła się z błędem w poniŜszej sytuacji: int* p; p = new int[2]; if(p!=NULL) delete [] p; //błąd -17- Problem ten równieŜ był cięŜki do wyśledzenia. Z pomocą przyszedł jeden z naszych znajomych (doświadczony programista), który stwierdził Ŝe problem nie koniecznie musi leŜeć po stronie delete []. W przypadku gdy istnieje problem z pamięcią znajdującą się na stosie i wykonamy operację delete moŜe wystąpić błąd pamięci związany z tym co leŜy na stosie. Okazało się, Ŝe znacznie wcześniej jedna z tablic była alokowana na zbyt małą ilość elementów. To z kolei powodowało wyjście poza zakres tablicy w pewnych miejscach programu. Błąd powodujący zaprzestanie działania aplikacji występował natomiast znacznie później, w innej części kodu gdy operacja delete [] wykonywała działania na stosie. 8.2.6 Problem z ‘Build clean’ Jeden z problemów, który nastąpił w dość wczesnej fazie tworzenia projektu był problem złej obsługi plików pośrednich przez IDE. Większość kompilatorów (z róŜnych języków kompilowanych) posiada opcję ‘build clean’ (zwaną teŜ często ‘rebuild’, ‘clean’). Generalnie rzecz biorąc w trakcie kompilacji, kompilator sprawdza czy dany plik źródłowy się zmienił. JeŜeli tak to zostaje on skompilowany, jeŜeli nie to nie jest on ponownie kompilowany i w efekcie pozostaje stary plik pośredni (.obj czy .o). Problem jest tutaj dwojaki. Po pierwsze, nie zawsze kompilatory dobrze wykrywają czy plik się zmienił. W efekcie tego plik .obj nie zostaje stworzony na nowo i uŜywana jest jego stara wersja. Po drugie, często opcja ‘clean’, która powinna wymusić przekompilowanie wszystkich plików i nadpisanie starych plików .obj nie działa poprawnie i niektóre z plików mogą pozostać w starej wersji (moŜna to sprawdzić po dacie stworzenia pliku). Efektem któregokolwiek z powyŜszych problemów jest sytuacja w której program przestaje działać w ‘losowych’ momentach lub gdy dostajemy nagle duŜą ilość błędów linkowania, których wcześniej nie mieliśmy. JeŜeli w takiej sytuacji ręcznie skasujemy pliki .obj i skompilujemy od nowa cały projekt to wszystko działa w porządku. Problem ten jest uciąŜliwy poniewaŜ jest cięŜki do zdiagnozowania a wina nie leŜy po stronie programisty. Osobiście jak dotąd spotykaliśmy się z tym problemem dość często w róŜnych językach programowania i róŜnych IDE/kompilatorach (Dev-Cpp, Visual Studio 6.0, Visual Studio 2003, Visual Studio 2007, Borland C++ Builder, NetBeans, Gnat). W związku z tym, Ŝe problem ten był nam znany udało nam się go dość szybko zdiagnozować. W efekcie stworzyliśmy plik .bat, który kasował wszystkie pliki pośrednie i plik -18- wykonywalny .exe. Przed kaŜdą kompilacją uruchamialiśmy powyŜszego batcha i dopiero wtedy przystępowaliśmy do kompilacji. 8.2.7 RozbieŜność działania W ramach pracy nad aplikacją zostaliśmy poproszeni przez kolegów z innych grup o udostępnienie plików z wynikami detekcji zespołów QRS. Wyniki te były im potrzebne do testowania swoich aplikacji. Udostępniliśmy naszą aplikację kolegom tak aby mogli z niej korzystać. Okazało się, Ŝe u nas aplikacja działa zawsze poprawnie natomiast u jednego z kolegów zawsze kończyła się z błędem i to zawsze w tym samym momencie. Problem przestał występować po przesłaniu nowego pliku wykonywalnego – w aplikacji nie wprowadziliśmy Ŝadnych zmian. Usunęliśmy pliki pośrednie i skompilowaliśmy program na nowo. Od tego momentu aplikacja zaczęła działać sprawnie. Nie udało nam się odkryć przyczyny tego błędu. W związku z zaistniałą sytuacją dodaliśmy do aplikacji logowanie wykonywanych operacji i następne wersje wysyłane do kolegów posiadały juŜ taką funkcjonalność. Od tego czasu nie został do nas zgłoszony Ŝaden błąd. 9 DODATEK C. Opis informatyczny procedur Ogólny opis rozwiązania wraz ze schematem moŜna znaleźć w Rozdziale 8. Szczegółowy opis procedur znajduje się w zamieszczonej dokumentacji kodu źródłowego aplikacji (patrz rozdział 10). 10 DODATEK D. Spis zawartości dołączonych nośników (dyskietek, CD ROMu) Spis plików na załączonym nośniku: katalog BIN: o daubwave.exe – aplikacja autorstwa Stevena Gollmera (do pogrania z [5]) wykonująca transformatę falkową falkami Daubechies, -19- o rdsamp.exe - aplikacja z witryny Physionet.org mająca na celu umoŜliwienie ekstrakcji danych z bazy MIT-BIH do formatu tekstowego (aplikacja wymaga bibliotek: cygcrypto-0.9.8.dll, cygcurl-4.dll, cygssh2-1.dll, cygssl-0.9.8.dll, cygwfdb10-4.dll, cygwin1.dll, cygz.dll. Biblioteki te znajdują się w katalogu BIN wraz z aplikacją), o qrs_det.exe – nasza aplikacja, o disp_dat.m - skrypt w Matlabie mający na celu wyświetlanie wyników działania aplikacji, o signals (katalog) – katalog zawierający badane sygnały w formie tekstowej bądź MITBIH (zgodne z formatem 212 i posiadające kanał MLII, do pobrania z [6], wszystkie dostępne badania za wyjątkiem 102 i 104, które nie posiadają kanału MLII). Dane z bazy MIT-BIH posiadają nazwy typu 100.hea, 100.atr, 100.dat natomiast sygnały wyeksportowane z powyŜszej bazy mają nazwy typu 100ex.dat, katalog DOC: o QRS_DET_-_raport_częściowy.doc – raport częściowy z pracy nad projektem, o QRS_DET_-_raport_końcowy.doc – aktualnie czytany dokument, o QRS_DET_DOC – katalog zawierający dokumentację kodu źródłowego aplikacji, katalog LIT: o 0157.pdf – pdf zawierający pracę [4], o 0751.pdf – pdf zawierający pracę [2], o 481.pdf – pdf zawierający pracę [3], o daubechies.pdf – pdf zawierający pracę [1], katalog SRC: o katalog QRS_DET – katalog ze źródłami projektu oraz plikiem projektu do Dev-Cpp, o katalog daubwave – katalog ze źródłami oraz plikiem projektu i dokumentacją do aplikacji daubwave -20-