<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl">
	<id>http://brain.fuw.edu.pl/edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jarekz</id>
	<title>Brain-wiki - Wkład użytkownika [pl]</title>
	<link rel="self" type="application/atom+xml" href="http://brain.fuw.edu.pl/edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jarekz"/>
	<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php/Specjalna:Wk%C5%82ad/Jarekz"/>
	<updated>2026-04-13T04:58:39Z</updated>
	<subtitle>Wkład użytkownika</subtitle>
	<generator>MediaWiki 1.34.1</generator>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11712</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11712"/>
		<updated>2026-04-08T09:32:21Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2025: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
##  [[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Wprowadzenie]]&lt;br /&gt;
&lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|EKG]] &lt;br /&gt;
## Wstęp teoretyczny i pomiary&lt;br /&gt;
## detekcja pików R i tętno&lt;br /&gt;
## analiza HRV&lt;br /&gt;
przesyłanie notebooków z EKG/HRV do 1.04&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|EMG]] (Zaczynamy 25 i 27 marca 2026)&lt;br /&gt;
##  wprowadzenie, pomiary, analiza ćwiczenie I (25 i 27 marca 2026)&lt;br /&gt;
##  analiza ćwiczenie I (8 i 10 kwietnia 2026)&lt;br /&gt;
##  analiza ćwiczenie I (15 i 17 kwietnia 2026)&lt;br /&gt;
##  analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III  (22 i 24 kwietnia)&lt;br /&gt;
## -&amp;gt; przesyłanie notebooków z EMG do 8.05.2026&lt;br /&gt;
##  &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]] (Zaczynamy 29 kwietnia i 6 maja 2026)&lt;br /&gt;
##  podstawowe własności EOG - rejestracja&lt;br /&gt;
##  podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 06.06&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
##  [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
##  [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11711</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11711"/>
		<updated>2026-04-08T09:31:56Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2025: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
##  [[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Wprowadzenie]]&lt;br /&gt;
&lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|EKG]] &lt;br /&gt;
## Wstęp teoretyczny i pomiary&lt;br /&gt;
## detekcja pików R i tętno&lt;br /&gt;
## analiza HRV&lt;br /&gt;
przesyłanie notebooków z EKG/HRV do 1.04&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|EMG]] (Zaczynamy 25 i 27 marca 2026)&lt;br /&gt;
##  wprowadzenie, pomiary, analiza ćwiczenie I (25 i 27 marca 2026)&lt;br /&gt;
##  analiza ćwiczenie I (8 i 10 kwietnia 2026)&lt;br /&gt;
##  analiza ćwiczenie I (15 i 17 kwietnia 2026)&lt;br /&gt;
##  analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III  (22 i 24 kwietnia)&lt;br /&gt;
-&amp;gt; przesyłanie notebooków z EMG do 8.05.2026&lt;br /&gt;
##  &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]] (Zaczynamy 29 kwietnia i 6 maja 2026)&lt;br /&gt;
##  podstawowe własności EOG - rejestracja&lt;br /&gt;
##  podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 06.06&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
##  [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
##  [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11687</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11687"/>
		<updated>2026-03-25T08:28:15Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Obserwacje wstępne */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
Artefakty ruchowe&lt;br /&gt;
&lt;br /&gt;
Aktywacja mięśnia powoduje jego skrócenie i przemieszczenie względem elektrody oraz skóry. Skutkuje to trzema rodzajami zakłóceń sygnału EMG:&lt;br /&gt;
&lt;br /&gt;
1. Zmiana amplitudy&lt;br /&gt;
Elektroda oddala się od aktywnego mięśnia, co obniża rejestrowany sygnał.&lt;br /&gt;
&lt;br /&gt;
2. Zmiana potencjału DC&lt;br /&gt;
Przemieszczenie wpływa na potencjał elektrochemiczny na granicy skóra–elektrolit.&lt;br /&gt;
&lt;br /&gt;
3. Artefakt rozciągnięcia skóry&lt;br /&gt;
Potencjał przeznaskórkowy (PTP) w spoczynku wynosi około 30 mV. Podczas rozciągania&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będą to 100 Hz, 150 Hz, 200 Hz itd.). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. &lt;br /&gt;
&lt;br /&gt;
Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz, należy:&lt;br /&gt;
* zadbać o niską impedancję pomiędzy elektrodą a skórą, &lt;br /&gt;
* mierzyć sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z '''prawem indukcji Faradaya''' zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
* Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. &lt;br /&gt;
* Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. &lt;br /&gt;
* Innym rozwiązaniem tego problemu jest zastosowanie '''kabli ekranowanych'''. Kable TMSI, których używamy na Pracowni, są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Umieść elektrodę GND na obojczyku,&lt;br /&gt;
* Umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* Ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** przyjrzyj się przebiegowi i widmu sygnałów dla różnych wartości siły napięcia mięśnia - czy uda się zaobserwować &amp;quot;salwy&amp;quot; odpowiadające aktywacji pojedynczej jednostki ruchowej?&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie   ściskasz 1 s i rozluźniasz pięść 2 s (dla badania mięśnia przedramienia). Powtórz 30 razy.&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20 s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak, aby rozdzielczość częstotliwościowa była 1 Hz.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia.Badanie efektu zmęczenia mięśnia w EMG&lt;br /&gt;
** Zmęczenie mięśnia w elektromiografii bada się głównie poprzez analizę zmian sygnału podczas długotrwałego skurczu izometrycznego. Kluczowe metody:&lt;br /&gt;
*** Analiza widmowa (spektralna): Podczas zmęczenia obserwuje się przesunięcie widma mocy w kierunku niskich częstotliwości, co opisują dwa wskaźniki:&lt;br /&gt;
**** Częstotliwość medianowa (MNF/MDF) – wartość częstotliwości, poniżej której i powyżej której leży po 50% całkowitej mocy widma. Podczas zmęczenia systematycznie spada.&lt;br /&gt;
**** Częstotliwość średnia (Mean Power Frequency, MPF) – ważona średnia częstotliwości widma. Również maleje wraz ze zmęczeniem.&lt;br /&gt;
** Spadek tych parametrów wynika z wolniejszego przewodzenia potencjałów wzdłuż włókien mięśniowych (obniżenie prędkości przewodzenia) oraz akumulacji metabolitów (mleczany, jony H⁺, K⁺).&lt;br /&gt;
* Przedstaw ewolucję czasową środka ciężkości widma częstości&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11686</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11686"/>
		<updated>2026-03-25T08:25:56Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Artefakty sieciowo-ruchowe */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
Artefakty ruchowe&lt;br /&gt;
&lt;br /&gt;
Aktywacja mięśnia powoduje jego skrócenie i przemieszczenie względem elektrody oraz skóry. Skutkuje to trzema rodzajami zakłóceń sygnału EMG:&lt;br /&gt;
&lt;br /&gt;
1. Zmiana amplitudy&lt;br /&gt;
Elektroda oddala się od aktywnego mięśnia, co obniża rejestrowany sygnał.&lt;br /&gt;
&lt;br /&gt;
2. Zmiana potencjału DC&lt;br /&gt;
Przemieszczenie wpływa na potencjał elektrochemiczny na granicy skóra–elektrolit.&lt;br /&gt;
&lt;br /&gt;
3. Artefakt rozciągnięcia skóry&lt;br /&gt;
Potencjał przeznaskórkowy (PTP) w spoczynku wynosi około 30 mV. Podczas rozciągania&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będą to 100 Hz, 150 Hz, 200 Hz itd.). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. &lt;br /&gt;
&lt;br /&gt;
Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz, należy:&lt;br /&gt;
* zadbać o niską impedancję pomiędzy elektrodą a skórą, &lt;br /&gt;
* mierzyć sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z '''prawem indukcji Faradaya''' zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
* Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. &lt;br /&gt;
* Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. &lt;br /&gt;
* Innym rozwiązaniem tego problemu jest zastosowanie '''kabli ekranowanych'''. Kable TMSI, których używamy na Pracowni, są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Umieść elektrodę GND na obojczyku,&lt;br /&gt;
* Umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* Ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie   ściskasz 1 s i rozluźniasz pięść 2 s (dla badania mięśnia przedramienia). Powtórz 30 razy.&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20 s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak, aby rozdzielczość częstotliwościowa była 1 Hz.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia.Badanie efektu zmęczenia mięśnia w EMG&lt;br /&gt;
** Zmęczenie mięśnia w elektromiografii bada się głównie poprzez analizę zmian sygnału podczas długotrwałego skurczu izometrycznego. Kluczowe metody:&lt;br /&gt;
*** Analiza widmowa (spektralna): Podczas zmęczenia obserwuje się przesunięcie widma mocy w kierunku niskich częstotliwości, co opisują dwa wskaźniki:&lt;br /&gt;
**** Częstotliwość medianowa (MNF/MDF) – wartość częstotliwości, poniżej której i powyżej której leży po 50% całkowitej mocy widma. Podczas zmęczenia systematycznie spada.&lt;br /&gt;
**** Częstotliwość średnia (Mean Power Frequency, MPF) – ważona średnia częstotliwości widma. Również maleje wraz ze zmęczeniem.&lt;br /&gt;
** Spadek tych parametrów wynika z wolniejszego przewodzenia potencjałów wzdłuż włókien mięśniowych (obniżenie prędkości przewodzenia) oraz akumulacji metabolitów (mleczany, jony H⁺, K⁺).&lt;br /&gt;
* Przedstaw ewolucję czasową środka ciężkości widma częstości&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11685</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11685"/>
		<updated>2026-03-25T08:23:05Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Artefakty sieciowe */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
Artefakty ruchowe&lt;br /&gt;
&lt;br /&gt;
Aktywacja mięśnia powoduje jego skrócenie i przemieszczenie względem elektrody oraz skóry. Skutkuje to trzema rodzajami zakłóceń sygnału EMG:&lt;br /&gt;
&lt;br /&gt;
1. Zmiana amplitudy&lt;br /&gt;
Elektroda oddala się od aktywnego mięśnia, co obniża rejestrowany sygnał.&lt;br /&gt;
&lt;br /&gt;
2. Zmiana potencjału DC&lt;br /&gt;
Przemieszczenie wpływa na potencjał elektrochemiczny na granicy skóra–elektrolit.&lt;br /&gt;
&lt;br /&gt;
3. Artefakt rozciągnięcia skóry&lt;br /&gt;
Potencjał przeznaskórkowy (PTP) w spoczynku wynosi około 30 mV. Podczas rozciągania&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będą to 100 Hz, 150 Hz, 200 Hz itd.). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. &lt;br /&gt;
&lt;br /&gt;
Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz, należy:&lt;br /&gt;
* zadbać o niską impedancję pomiędzy elektrodą a skórą, &lt;br /&gt;
* mierzyć sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne, wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z Prawem Indukcji Faraday'a zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. Innym rozwiązaniem tego problemu jest zastosowanie kabli ekranowanych. Kable TMSI, których używamy na Pracowni są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu, zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo, aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Umieść elektrodę GND na obojczyku,&lt;br /&gt;
* Umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* Ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie   ściskasz 1 s i rozluźniasz pięść 2 s (dla badania mięśnia przedramienia). Powtórz 30 razy.&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20 s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak, aby rozdzielczość częstotliwościowa była 1 Hz.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia.Badanie efektu zmęczenia mięśnia w EMG&lt;br /&gt;
** Zmęczenie mięśnia w elektromiografii bada się głównie poprzez analizę zmian sygnału podczas długotrwałego skurczu izometrycznego. Kluczowe metody:&lt;br /&gt;
*** Analiza widmowa (spektralna): Podczas zmęczenia obserwuje się przesunięcie widma mocy w kierunku niskich częstotliwości, co opisują dwa wskaźniki:&lt;br /&gt;
**** Częstotliwość medianowa (MNF/MDF) – wartość częstotliwości, poniżej której i powyżej której leży po 50% całkowitej mocy widma. Podczas zmęczenia systematycznie spada.&lt;br /&gt;
**** Częstotliwość średnia (Mean Power Frequency, MPF) – ważona średnia częstotliwości widma. Również maleje wraz ze zmęczeniem.&lt;br /&gt;
** Spadek tych parametrów wynika z wolniejszego przewodzenia potencjałów wzdłuż włókien mięśniowych (obniżenie prędkości przewodzenia) oraz akumulacji metabolitów (mleczany, jony H⁺, K⁺).&lt;br /&gt;
* Przedstaw ewolucję czasową środka ciężkości widma częstości&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11684</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11684"/>
		<updated>2026-03-25T08:20:58Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Artefakty ruchowe */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
Artefakty ruchowe&lt;br /&gt;
&lt;br /&gt;
Aktywacja mięśnia powoduje jego skrócenie i przemieszczenie względem elektrody oraz skóry. Skutkuje to trzema rodzajami zakłóceń sygnału EMG:&lt;br /&gt;
&lt;br /&gt;
1. Zmiana amplitudy&lt;br /&gt;
Elektroda oddala się od aktywnego mięśnia, co obniża rejestrowany sygnał.&lt;br /&gt;
&lt;br /&gt;
2. Zmiana potencjału DC&lt;br /&gt;
Przemieszczenie wpływa na potencjał elektrochemiczny na granicy skóra–elektrolit.&lt;br /&gt;
&lt;br /&gt;
3. Artefakt rozciągnięcia skóry&lt;br /&gt;
Potencjał przeznaskórkowy (PTP) w spoczynku wynosi około 30 mV. Podczas rozciągania&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będzie to 100 Hz, 150 Hz, 200 Hz, itd). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz należy zadbać o niską impedancję pomiędzy elektrodą a skóra oraz powinno mierzyć się sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne, wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z Prawem Indukcji Faraday'a zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. Innym rozwiązaniem tego problemu jest zastosowanie kabli ekranowanych. Kable TMSI, których używamy na Pracowni są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu, zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo, aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Umieść elektrodę GND na obojczyku,&lt;br /&gt;
* Umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* Ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie   ściskasz 1 s i rozluźniasz pięść 2 s (dla badania mięśnia przedramienia). Powtórz 30 razy.&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20 s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak, aby rozdzielczość częstotliwościowa była 1 Hz.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia.Badanie efektu zmęczenia mięśnia w EMG&lt;br /&gt;
** Zmęczenie mięśnia w elektromiografii bada się głównie poprzez analizę zmian sygnału podczas długotrwałego skurczu izometrycznego. Kluczowe metody:&lt;br /&gt;
*** Analiza widmowa (spektralna): Podczas zmęczenia obserwuje się przesunięcie widma mocy w kierunku niskich częstotliwości, co opisują dwa wskaźniki:&lt;br /&gt;
**** Częstotliwość medianowa (MNF/MDF) – wartość częstotliwości, poniżej której i powyżej której leży po 50% całkowitej mocy widma. Podczas zmęczenia systematycznie spada.&lt;br /&gt;
**** Częstotliwość średnia (Mean Power Frequency, MPF) – ważona średnia częstotliwości widma. Również maleje wraz ze zmęczeniem.&lt;br /&gt;
** Spadek tych parametrów wynika z wolniejszego przewodzenia potencjałów wzdłuż włókien mięśniowych (obniżenie prędkości przewodzenia) oraz akumulacji metabolitów (mleczany, jony H⁺, K⁺).&lt;br /&gt;
* Przedstaw ewolucję czasową środka ciężkości widma częstości&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11682</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11682"/>
		<updated>2026-03-20T08:50:29Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Analiza */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
W wyniku aktywacji mięśnia, ulega on skróceniu, co powoduje przemieszczanie się względem siebie mięśnia, skóry i elektrody. Przemieszczenie to powoduje zmianę amplitudy mierzonego sygnału (np. elektroda oddala się od mięśnia), zmianę potencjału DC (potencjału powstającego na granicy skóra-elektrolit) oraz rozciągniecie skóry. Jak pamiętamy z pierwszych zajęć&lt;br /&gt;
pomiędzy naskórkiem a skórą właściwą istnieje różnica potencjałów o amplitudzie dochodzącej do 30 mV. W trakcie rozciągania skóry, wartość to spada do 25 mV. Powstająca zmiana potencjału, o wartości około 5 mV jest w porównaniu z sygnałem EMG bardzo znacząca.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będzie to 100 Hz, 150 Hz, 200 Hz, itd). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz należy zadbać o niską impedancję pomiędzy elektrodą a skóra oraz powinno mierzyć się sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne, wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z Prawem Indukcji Faraday'a zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. Innym rozwiązaniem tego problemu jest zastosowanie kabli ekranowanych. Kable TMSI, których używamy na Pracowni są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu, zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo, aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Umieść elektrodę GND na obojczyku,&lt;br /&gt;
* Umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* Ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie   ściskasz 1 s i rozluźniasz pięść 2 s (dla badania mięśnia przedramienia). Powtórz 30 razy.&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20 s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak, aby rozdzielczość częstotliwościowa była 1 Hz.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia.Badanie efektu zmęczenia mięśnia w EMG&lt;br /&gt;
** Zmęczenie mięśnia w elektromiografii bada się głównie poprzez analizę zmian sygnału podczas długotrwałego skurczu izometrycznego. Kluczowe metody:&lt;br /&gt;
*** Analiza widmowa (spektralna): Podczas zmęczenia obserwuje się przesunięcie widma mocy w kierunku niskich częstotliwości, co opisują dwa wskaźniki:&lt;br /&gt;
**** Częstotliwość medianowa (MNF/MDF) – wartość częstotliwości, poniżej której i powyżej której leży po 50% całkowitej mocy widma. Podczas zmęczenia systematycznie spada.&lt;br /&gt;
**** Częstotliwość średnia (Mean Power Frequency, MPF) – ważona średnia częstotliwości widma. Również maleje wraz ze zmęczeniem.&lt;br /&gt;
** Spadek tych parametrów wynika z wolniejszego przewodzenia potencjałów wzdłuż włókien mięśniowych (obniżenie prędkości przewodzenia) oraz akumulacji metabolitów (mleczany, jony H⁺, K⁺).&lt;br /&gt;
* Przedstaw ewolucję czasową środka ciężkości widma częstości&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11681</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11681"/>
		<updated>2026-03-20T08:44:14Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Analiza */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
W wyniku aktywacji mięśnia, ulega on skróceniu, co powoduje przemieszczanie się względem siebie mięśnia, skóry i elektrody. Przemieszczenie to powoduje zmianę amplitudy mierzonego sygnału (np. elektroda oddala się od mięśnia), zmianę potencjału DC (potencjału powstającego na granicy skóra-elektrolit) oraz rozciągniecie skóry. Jak pamiętamy z pierwszych zajęć&lt;br /&gt;
pomiędzy naskórkiem a skórą właściwą istnieje różnica potencjałów o amplitudzie dochodzącej do 30 mV. W trakcie rozciągania skóry, wartość to spada do 25 mV. Powstająca zmiana potencjału, o wartości około 5 mV jest w porównaniu z sygnałem EMG bardzo znacząca.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będzie to 100 Hz, 150 Hz, 200 Hz, itd). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz należy zadbać o niską impedancję pomiędzy elektrodą a skóra oraz powinno mierzyć się sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne, wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z Prawem Indukcji Faraday'a zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. Innym rozwiązaniem tego problemu jest zastosowanie kabli ekranowanych. Kable TMSI, których używamy na Pracowni są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu, zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo, aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Umieść elektrodę GND na obojczyku,&lt;br /&gt;
* Umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* Ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie   ściskasz 1 s i rozluźniasz pięść 2 s (dla badania mięśnia przedramienia). Powtórz 30 razy.&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20 s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak, aby rozdzielczość częstotliwościowa była 1 Hz.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia:&lt;br /&gt;
** Przedstaw ewolucję czasową środka ciężkości widma częstości&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11680</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11680"/>
		<updated>2026-03-20T08:39:47Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Pomiar */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
W wyniku aktywacji mięśnia, ulega on skróceniu, co powoduje przemieszczanie się względem siebie mięśnia, skóry i elektrody. Przemieszczenie to powoduje zmianę amplitudy mierzonego sygnału (np. elektroda oddala się od mięśnia), zmianę potencjału DC (potencjału powstającego na granicy skóra-elektrolit) oraz rozciągniecie skóry. Jak pamiętamy z pierwszych zajęć&lt;br /&gt;
pomiędzy naskórkiem a skórą właściwą istnieje różnica potencjałów o amplitudzie dochodzącej do 30 mV. W trakcie rozciągania skóry, wartość to spada do 25 mV. Powstająca zmiana potencjału, o wartości około 5 mV jest w porównaniu z sygnałem EMG bardzo znacząca.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będzie to 100 Hz, 150 Hz, 200 Hz, itd). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz należy zadbać o niską impedancję pomiędzy elektrodą a skóra oraz powinno mierzyć się sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne, wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z Prawem Indukcji Faraday'a zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. Innym rozwiązaniem tego problemu jest zastosowanie kabli ekranowanych. Kable TMSI, których używamy na Pracowni są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu, zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo, aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Umieść elektrodę GND na obojczyku,&lt;br /&gt;
* Umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* Ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie   ściskasz 1 s i rozluźniasz pięść 2 s (dla badania mięśnia przedramienia). Powtórz 30 razy.&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20 s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak aby rodzielczość częstotliwościowa była 1Hz.&lt;br /&gt;
** Przedstaw mapę czas-częstość (rozważ spectrogram i scalogram - czy któraś z technik jest tu lepsza?) dla całego zapisu. Zaobserwuj jakie zmiany następują w widmie wraz ze wzrostem obciążenia.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia:&lt;br /&gt;
** Przedstaw mapę czas-częstość dla całego czasu rejestracji. Zaobserwuj jakie zmiany następują w widmie wraz z czasem.&lt;br /&gt;
** Przedstaw ewolucję czasową środka ciężkości widma częstości&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11679</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11679"/>
		<updated>2026-03-20T08:36:25Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Rejestracja 1: napinanie i rozluźnianie ręki */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
W wyniku aktywacji mięśnia, ulega on skróceniu, co powoduje przemieszczanie się względem siebie mięśnia, skóry i elektrody. Przemieszczenie to powoduje zmianę amplitudy mierzonego sygnału (np. elektroda oddala się od mięśnia), zmianę potencjału DC (potencjału powstającego na granicy skóra-elektrolit) oraz rozciągniecie skóry. Jak pamiętamy z pierwszych zajęć&lt;br /&gt;
pomiędzy naskórkiem a skórą właściwą istnieje różnica potencjałów o amplitudzie dochodzącej do 30 mV. W trakcie rozciągania skóry, wartość to spada do 25 mV. Powstająca zmiana potencjału, o wartości około 5 mV jest w porównaniu z sygnałem EMG bardzo znacząca.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będzie to 100 Hz, 150 Hz, 200 Hz, itd). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz należy zadbać o niską impedancję pomiędzy elektrodą a skóra oraz powinno mierzyć się sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne, wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z Prawem Indukcji Faraday'a zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. Innym rozwiązaniem tego problemu jest zastosowanie kabli ekranowanych. Kable TMSI, których używamy na Pracowni są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu, zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo, aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* umieść elektrodę GND na wewnętrznej części przedramienia, w połowie jego długości,&lt;br /&gt;
* umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie   ściskasz 1 s i rozluźniasz pięść 2 s (dla badania mięśnia przedramienia). Powtórz 30 razy.&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak aby rodzielczość częstotliwościowa była 1Hz.&lt;br /&gt;
** Przedstaw mapę czas-częstość (rozważ spectrogram i scalogram - czy któraś z technik jest tu lepsza?) dla całego zapisu. Zaobserwuj jakie zmiany następują w widmie wraz ze wzrostem obciążenia.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia:&lt;br /&gt;
** Przedstaw mapę czas-częstość dla całego czasu rejestracji. Zaobserwuj jakie zmiany następują w widmie wraz z czasem.&lt;br /&gt;
** Przedstaw ewolucję czasową środka ciężkości widma częstości&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11678</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11678"/>
		<updated>2026-03-20T08:33:14Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
W wyniku aktywacji mięśnia, ulega on skróceniu, co powoduje przemieszczanie się względem siebie mięśnia, skóry i elektrody. Przemieszczenie to powoduje zmianę amplitudy mierzonego sygnału (np. elektroda oddala się od mięśnia), zmianę potencjału DC (potencjału powstającego na granicy skóra-elektrolit) oraz rozciągniecie skóry. Jak pamiętamy z pierwszych zajęć&lt;br /&gt;
pomiędzy naskórkiem a skórą właściwą istnieje różnica potencjałów o amplitudzie dochodzącej do 30 mV. W trakcie rozciągania skóry, wartość to spada do 25 mV. Powstająca zmiana potencjału, o wartości około 5 mV jest w porównaniu z sygnałem EMG bardzo znacząca.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będzie to 100 Hz, 150 Hz, 200 Hz, itd). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz należy zadbać o niską impedancję pomiędzy elektrodą a skóra oraz powinno mierzyć się sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne, wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z Prawem Indukcji Faraday'a zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. Innym rozwiązaniem tego problemu jest zastosowanie kabli ekranowanych. Kable TMSI, których używamy na Pracowni są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu, zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo, aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* umieść elektrodę GND na wewnętrznej części przedramienia, w połowie jego długości,&lt;br /&gt;
* umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie po około 5 s napinasz i rozluźniasz biceps lub ściskasz i rozluźniasz pięść (dla badania mięśnia przedramienia).&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak aby rodzielczość częstotliwościowa była 1Hz.&lt;br /&gt;
** Przedstaw mapę czas-częstość (rozważ spectrogram i scalogram - czy któraś z technik jest tu lepsza?) dla całego zapisu. Zaobserwuj jakie zmiany następują w widmie wraz ze wzrostem obciążenia.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia:&lt;br /&gt;
** Przedstaw mapę czas-częstość dla całego czasu rejestracji. Zaobserwuj jakie zmiany następują w widmie wraz z czasem.&lt;br /&gt;
** Przedstaw ewolucję czasową środka ciężkości widma częstości&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11677</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11677"/>
		<updated>2026-03-20T08:31:22Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2025: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
##  [[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Wprowadzenie]]&lt;br /&gt;
&lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|EKG]] &lt;br /&gt;
## Wstęp teoretyczny i pomiary&lt;br /&gt;
## detekcja pików R i tętno&lt;br /&gt;
## analiza HRV&lt;br /&gt;
przesyłanie notebooków z EKG/HRV do 1.04&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|EMG]] (Zaczynamy 25 i 27 marca 2026)&lt;br /&gt;
##  wprowadzenie, pomiary, analiza ćwiczenie I&lt;br /&gt;
##  analiza ćwiczenie I&lt;br /&gt;
##  analiza ćwiczenie I&lt;br /&gt;
##  analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III -&amp;gt; przesyłanie notebooków z EMG do 16.05&lt;br /&gt;
##  &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]]&lt;br /&gt;
##  podstawowe własności EOG - rejestracja&lt;br /&gt;
##  podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 06.06&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
##  [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
##  [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11676</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11676"/>
		<updated>2026-03-20T08:30:28Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2025: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
##  [[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Wprowadzenie]]&lt;br /&gt;
&lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|EKG]] &lt;br /&gt;
## Wstęp teoretyczny i pomiary&lt;br /&gt;
## detekcja pików R i tętno&lt;br /&gt;
## analiza HRV&lt;br /&gt;
przesyłanie notebooków z EKG/HRV do 4.04&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|EMG]] (Zaczynamy 25 i 27 marca 2026)&lt;br /&gt;
##  wprowadzenie, pomiary, analiza ćwiczenie I&lt;br /&gt;
##  analiza ćwiczenie I&lt;br /&gt;
##  analiza ćwiczenie I&lt;br /&gt;
##  analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III -&amp;gt; przesyłanie notebooków z EMG do 16.05&lt;br /&gt;
##  &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]]&lt;br /&gt;
##  podstawowe własności EOG - rejestracja&lt;br /&gt;
##  podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 06.06&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
##  [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
##  [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11675</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 2 4</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11675"/>
		<updated>2026-03-18T08:33:28Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Ćwiczenie 5: HRV */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EKG&lt;br /&gt;
&lt;br /&gt;
==Rejestracja i analiza sygnału EKG==&lt;br /&gt;
&lt;br /&gt;
Lektura:  [http://www.bem.fi/book/15/15.htm Electric and Magnetic Measurement of the Electric Activity of the Heart/12-Lead ECG System]&lt;br /&gt;
[[Plik:einthoven_ekg.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Aparat do rejestracji czynności elektrycznej serca skonstruowany przez W. Einthovena. Proszę zauważyć w jakich miejscach na ciele zbierana jest sygnał.]]&lt;br /&gt;
[[Plik:ekg_animacja.gif|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Rozchodzenie się sygnału stymulujacego pracę serca i związane z tym powstawanie sygnału EKG. Rysunek po brany ze strony Wikipedii.]]&lt;br /&gt;
[[Plik:ekg_opis.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Oznaczenia kolejnych składowych sygnału EKG.]]&lt;br /&gt;
[[Plik:wilson.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:wilson&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Umiejscowienie elektrod do pomiaru czynności elektrycznej serca z powierzchni klatki piersiowej, rysunek pobrany ze stron Wikipedii.]]&lt;br /&gt;
 &lt;br /&gt;
Mechanizm powstawania czynności elektrycznej serca został omówiony na zajęciach &amp;amp;bdquo;Sygnały Bioelektryczne&amp;quot;. W tym miejscu przypomnimy tylko kilka ważnych (i ciekawych) faktów.&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Czynność elektryczna serca znana jest od połowy XIX, jednakże za początek narodzin elektrokardiografii uznaje się rok 1903, kiedy to W. Einthoven dokonał pomiaru czynności elektrycznej serca z powierzchni ciała (&amp;lt;xr id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). Jako metoda diagnostyczna, elektrokardiografia zaczęła się szybko rozwijać po roku 1936, kiedy to do rejestracji czynności elektrycznej serca zastosowano wzmacniacz lampowy oraz system zapisu pomiaru na papierze.&lt;br /&gt;
&amp;lt;li&amp;gt; Serce posiada specjalny, wzbudzany samoczynnie układ, który generuje i przewodzi bodźce elektryczne. Następstwem działania tego układu jest rytmiczna praca serca o częstości od 70 do 180 cykli na minutę (częstość ta ulega zmianom pod wpływem czynników biochemicznych, powstałych np. w skutek stresu).&lt;br /&gt;
&amp;lt;li&amp;gt; Elektroda rejestrująca sygnał EKG zbiera czynność elektryczną wszystkich komórek serca, a zatem zarówno komórek wchodzących w skład układu generującego i przewodzącego impulsy elektryczne oraz kurczących się pod wpływem impulsów sterujących mięśni, które kurcząc się, również wytwarzają sygnał elektryczny. Jednakże, z uwagi na nieporównywalnie dużo większą masę mięśni serca w porównaniu z masą komórek układu stymulującego przyjmuje się, że głównym składnikiem sygnału EKG jest czynność elektryczna mięśnia sercowego.&lt;br /&gt;
&amp;lt;li&amp;gt; W przybliżeniu, sygnał stymulujący pracę serca rozchodzi się z jego prawej górnej części w kierunku dolnym i na lewą stronę. Na skutek pobudzania kolejnych partii mięśnia sercowego, powstaje charakterystyczny kształt sygnału EKG (&amp;lt;xr id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, &amp;lt;xr id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). &lt;br /&gt;
&amp;lt;li&amp;gt; Oznaczenia kolejnych składowych sygnału EKG:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; odchylenia od linii poziomej (izoelektrycznej) nazywamy załamkami,&lt;br /&gt;
&amp;lt;li&amp;gt; odległość w czasie pomiędzy końcem załamka P i początkiem załamka Q oraz końcem załamka S i początkiem załamka T nazywamy odcinkami &amp;amp;mdash; odpowiednio PQ i ST.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Elektrody pomiarowe połączone do aparatury rejestrujących nazywamy odprowadzeniami. Uwaga &amp;amp;mdash; przyjęto odprowadzeniami oznaczać także sygnały EKG będące liniowymi kombinacjami sygnałów zebranych przez elektrody.&lt;br /&gt;
&amp;lt;li&amp;gt; W konwencjonalnej elektroencefalografii stosuje się 12 tzw. odprowadzeń klasycznych:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Trzy odprowadzenia kończynowe biegunowe, zaproponowane jeszcze przez Einthoven i oznaczane rzymskimi cyframi I, II i III. Elektrody w tym systemie umieszcza się prawej (R) (ang. ''right'') i lewej (L) (ang. ''left'') kończynie górnej (najczęściej w okolicy nadgarstka, czasem ramieniu lub czy barku) oraz lewej nodze w okolicy stopy (F) (ang. ''foot''). Elektrodę umieszczaną na prawym nadgarstku oznacza się kolorem czerwonym, na lewym żółtym, na lewej kostce zielonym. Elektrodę masy umieszcza się zwykle na lewej kostce (choć teoretycznie można ją aplikować gdziekolwiek) i jest ona oznaczona kolorem czarnym. Odprowadzenia kończynowe mierzą różnicę napięć pomiędzy miejscami przyłożenia elektrod w następujący sposób:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
I   &amp;amp; = V_{L} - V_{R} \\&lt;br /&gt;
II  &amp;amp; = V_{F} - V_{R} \\&lt;br /&gt;
III &amp;amp; = V_{F} - V_{L}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
gdzie: &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;V_{R}, V_{L}, V_{F}&amp;lt;/math&amp;gt; to potencjały odpowiednio na prawym i lewym nadgarstku oraz stopie mierzone względem elektrody masy.&amp;lt;br/&amp;gt;&lt;br /&gt;
Jak łatwo zauważyć, tylko dwa spośród powyższych napięć są liniowo niezależne, co można zapisać w postaci związku:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_2&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;I + III = II&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
który nazywany jest prawem Einthovena. Proszę zauważyć, iż w tym przypadku wzmacniane jest sygnał będący różnicą napięć dwóch kolejnych elektrod, stąd też te odprowadzenia nazywamy dwubiegunowymi (bipolarnymi).&lt;br /&gt;
&amp;lt;li&amp;gt; Trzy odprowadzenia jednobiegunowe Goldberga. W odprowadzeniach tych sygnał w danym odprowadzeniu jest różnicą napięć pomiędzy elektrodą pomiarową a średnim napięciem na dwóch pozostałych elektrodach:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
aV_{R} &amp;amp; = V_{R} - \frac{V_{L}+V_{F}}{2} \\&lt;br /&gt;
aV_{L} &amp;amp; = V_{L} - \frac{V_{R}+V_{F}}{2} \\&lt;br /&gt;
aV_{F} &amp;amp; = V_{F} - \frac{V_{L}+V_{R}}{2}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Sześć odprowadzeń jednobiegunowych Wilsona. W przypadku warto zapoznać się z z historią tych odprowadzeń. Początkowo Wilson zaproponował układ jednobiegunowych doniesień dla kończyn w następujący sposób:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_4&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
V_{LW} &amp;amp; = V_{L} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{RW} &amp;amp; = V_{R} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{FW} &amp;amp; = V_{F} - \frac{V_{R}+V_{L}+ V_{F}}{3}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
Jak widzimy, jako elektrodę odniesienia wybrał on średnie napięcie rejestrowane przez elektrody. Niestety, sygnały prezentowane w tym systemie miały małą amplitudę, w związku z czym tego rodzaju odprowadzenia nie stosowano w praktyce. Z systemu zaproponowanego przez Wilsona wywodzi się jednak system odniesień Goldberga, który zauważył, że napięcie na trzeciej kończynie można zwiększyć o 50% jeśli do wyznaczenia napięcia odniesienia zastosuje się dwie, a nie trzy elektrody. Metoda wyznaczania potencjału odniesienia zaproponowana przez Wilsona znalazła jednak zastosowanie przy mierzeniu czynności elektrycznej serca mierzonej z powierzchni klatki piersiowej. W tym celu elektrody umieszcza się w pewnych ustalonych miejscach (&amp;lt;xr id=&amp;quot;fig:wilson&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, zaś odprowadzenia oznacza się symbolami &amp;lt;math&amp;gt;V_1, V_2, \dots, V_6&amp;lt;/math&amp;gt;. Odniesieniem w tym przypadku jest średni sygnał rejestrowany na kończynach górnych i lewej stopie. &lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ćwiczenia==&lt;br /&gt;
&lt;br /&gt;
Aby uruchomić zbieranie sygnału należy wykonać następujące operacje:&lt;br /&gt;
* przykleić elektrody do badanego;&lt;br /&gt;
* włożyć przewody do elektrod, a potem do wzmacniacza;&lt;br /&gt;
* podłączyć zasilanie wzmacniacza;&lt;br /&gt;
* podłączyć wzmacniacz do komputera (przejściówka optyczna i kabel USB);&lt;br /&gt;
* uruchomić program SVAROG&lt;br /&gt;
* otworzyć sygnał on-line ze wzmacniacza. &lt;br /&gt;
**  Po tym poleceniu wzmacniacz powinien wyświetlać napis &amp;amp;bdquo;Fiber&amp;amp;rdquo;; napis &amp;amp;bdquo;Connect&amp;amp;rdquo; oznacza, że połączenie wzmacniacza z komputerem nie udało się. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie 0: wstępne  ===&lt;br /&gt;
* Podaj związek pomiędzy sygnałami mierzonymi w systemie Goldbergera, a systemem Einthovena.&lt;br /&gt;
* Podaj analogiczny związek pomiędzy sygnałami w odniesieniach Goldberga co ''Prawo Einthovena''. &lt;br /&gt;
* Pokaż, że w systemie Goldbergera uzyskuje się sygnały o amplitudzie o 50% wyższej niż w pierwotnym systemie Wilsona.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Realizacja w grupie ==&lt;br /&gt;
=== Ćwiczenie 1: rejestracja sygnału === &lt;br /&gt;
&lt;br /&gt;
Podłącz elektrody:&lt;br /&gt;
* lewa ręka, &lt;br /&gt;
* prawa ręka, &lt;br /&gt;
* lewa noga, &lt;br /&gt;
* uziemienie do prawej nogi.&lt;br /&gt;
&lt;br /&gt;
Zbierz 3 fragment sygnału EKG przy pomocy Svaroga. &lt;br /&gt;
&lt;br /&gt;
* Częstotliwość próbkowania 2048 Hz.&lt;br /&gt;
* Długość zapisu 300 s.&lt;br /&gt;
* Proszę zapisać sygnały w następujących warunkach:&lt;br /&gt;
** spoczynkowe&lt;br /&gt;
** po wysiłku fizycznym (odpiąć zatrzaskowe elektrody, przejść się po schodach i podłączyć ponownie )&lt;br /&gt;
** podczas obciążenia poznawczego, np. odejmując w pamięci kolejno 17 od 1000.&lt;br /&gt;
* zebrane sygnały zapisz na dysku classroom&lt;br /&gt;
&lt;br /&gt;
Zapoznaj się z zagadnieniem filtrowania dla sygnałów EKG:&lt;br /&gt;
* Proszę przejrzeć pracę: Shen Luo, Paul Johnston. A review of electrocardiogram filtering,  ''Journal of Electrocardiology'', 2010, Volume 43, Issue 6,  Pages 486-496 (https://www.sciencedirect.com/science/article/pii/S0022073610002852?via%3Dihub) &lt;br /&gt;
* popróbować uzyskać opisane tam filtry w SVAROGU i zaaplikować je do zebranych danych&lt;br /&gt;
&lt;br /&gt;
== Realizacja indywidualna w notebooku ==&lt;br /&gt;
===Ćwiczenie 2: Wstępna obróbka sygnału EKG ===&lt;br /&gt;
Napisz fragment notebooka, który:&lt;br /&gt;
* wczytuje sygnał przykład: [https://colab.research.google.com/drive/1QWfjnuf_LkdOnQzaBej0itD9yxWzlA6R?usp=sharing przykład]&lt;br /&gt;
* wykonuje stosowne filtracje (stosujemy filtrację z zerowym przesunięciem fazowym: filtfilt):  &lt;br /&gt;
** Filtr górnoprzepustowy:&lt;br /&gt;
*** z częstością odcięcia  0.67 Hz (przy tej częstości wymagamy 3dB tłumienia) &lt;br /&gt;
*** poniżej 0.5-dB tętnień w paśmie 1 - 30 Hz. &lt;br /&gt;
*** projekt z wykorzystaniem funkcji scipy.signal.iirfilter; trzeba dobrać rząd i sprawdzić charakterystyki funkcji transmitancji - dobrać zakres osi i dodać linie pomocnicze pionowe i poziome (matplotlib.pyplot.axvline i matplotlib.pyplot.axhline) tak aby było widać że zaprojektowany filtr spełnia powyższe kryteria.&lt;br /&gt;
** Filtr dolnoprzepustowy z częstością odcięcia 150Hz &lt;br /&gt;
*** wymagania te powinien spełnić np. filtr 2 rzędu, Butterwortha, - proszę sprawdzić charakterystyki).&lt;br /&gt;
** Filtr pasmowo-zaporowy (notch) dla 50 Hz iirnotch (scipy.signal.iirnotch())&lt;br /&gt;
* rysuje sygnał w odprowadzeniach Einthovena i Goldbergera,&lt;br /&gt;
* wybierz &amp;quot;czysty&amp;quot; fragment sygnału i zidentyfikuj poszczególne załamki. (można wykorzystać funkcję matplotlib.pyplot.axvspan)&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 3: Detekcja pików R ===&lt;br /&gt;
* Zaproponuj metodę rozpoznawania pików R w sygnale, &lt;br /&gt;
** wybierz do tego optymalny kanał&lt;br /&gt;
** rozważ zastosowanie filtra górnoprzepustowego o wyższej częstości odcięcia niż w ćwiczeniu 2&lt;br /&gt;
** skorzystaj z funkcji [https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks.html scipy.signal.find_peaks] - zaprezentuj dobór parametrów funkcji na podsdtawie histogramów odpowiednich parametrów, które zwraca ona w słowniku.&lt;br /&gt;
* Przedstaw fragment sygnału z zaznaczonymi pikami R dla różnych warunków rejestracji sygnału EKG. &lt;br /&gt;
&lt;br /&gt;
Przydatne pojęcie: (ang.) [https://pl.wikipedia.org/wiki/Minimalna_deniwelacja_wzgl%C4%99dna prominence - wybitność piku]&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 4: Tętno ===&lt;br /&gt;
Napisz program, który:&lt;br /&gt;
* wczyta plik z sygnałem i na jego podstawie &lt;br /&gt;
* wyznaczy i wykreśli tętno - liczbę uderzeń serca na minutę (ang. ''heart rate'').&lt;br /&gt;
* Oblicz średnie tętno i jego standardowe odchylenie.&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 5: HRV ===&lt;br /&gt;
Zmienność zatokowego rytmu serca: HRV - heart rate variability. &lt;br /&gt;
* zapoznaj się z koncepcją [https://en.wikipedia.org/wiki/Heart_rate_variability#cite_note-29 HRV]&lt;br /&gt;
* Literatura [https://link.springer.com/article/10.1007/s11517-006-0119-0 Heart rate variability: a review]. &lt;br /&gt;
* przedstaw interwały R-R jako szereg czasowy&lt;br /&gt;
* przedstaw miarę RMSSD obliczaną dla okien 30s przesuwanych co jedną odległość RR jako szereg czasowy&lt;br /&gt;
* wykonaj interpolację sygnału RR do stałej częstości próbkowania 4Hz &lt;br /&gt;
** Uwaga: oryginalne próbki RR są pobierane w różnych odstępach!&lt;br /&gt;
** można zinterpolować punkty na równomiernie próbkowanej siatce https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html#scipy.interpolate.interp1d i zastosować standardową funkcję do estymacji:&lt;br /&gt;
***  periodogramów&lt;br /&gt;
*** widma metodą AR&lt;br /&gt;
* wyestymuj widmo częstotliwościowe sygnału RR, z sygnału wysiłkowego postaraj się usunąć trend&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* porównaj widma HRV w poszczególnych warunkach eksperymentalnych; zwróć uwagę na proporcje mocy w pasmach wysokich częstości (HF: 0.15 do 0.4 Hz), niskich częstości (LF: 0.04 do 0.15 Hz) i bardzo niskich częstości (VLF: 0.0033 do 0.04 Hz).&lt;br /&gt;
&lt;br /&gt;
==Literatura uzupełniająca==&lt;br /&gt;
&lt;br /&gt;
[http://www.bem.fi/book/19/19.htm#00 podstawowa diagnostyka EKG]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;!--;Ćwiczenie 8: Wykorzystując poniższe fragmenty kodu, stwórz program, który będzie wyrysowywał zmiany tętna w czasie rzeczywistym.&lt;br /&gt;
Pierwszy fragment kodu, to moduł buforujący sygnał, drugi to moduł pobierający dane z bufora. Należy dopisać do modułu pobierającego dane z bufora przetwarzanie ich (wyrysowywanie tętna) we wskazanym miejscu. &lt;br /&gt;
Uruchamianie całości będzie polegało na:&lt;br /&gt;
* uruchomieniu wzmacniacza&lt;br /&gt;
* uruchomieniu modułu &amp;lt;tt&amp;gt;signal_catcher.py&amp;lt;/tt&amp;gt;&lt;br /&gt;
* uruchomienie &amp;lt;tt&amp;gt;heartrate.py&amp;lt;/tt&amp;gt;, ktory jest dostepny [http://escher.fuw.edu.pl/~mm/zajecia/heartrate.py tu], po wstawieniu do niego w odpowiednie miejsce oznaczone w komentarzu własnego kodu obliczającego tętno.&lt;br /&gt;
* Trochę zmieniona wersja &amp;amp;mdash; [http://escher.fuw.edu.pl/~mm/zajecia/heartrate_new.py &amp;lt;tt&amp;gt;heartrate_new.py&amp;lt;/tt&amp;gt;] oraz  [http://escher.fuw.edu.pl/~mm/zajecia/signal_catcher_pracownia.py &amp;lt;tt&amp;gt;signal_catcher_pracownia.py&amp;lt;/tt&amp;gt;]&lt;br /&gt;
(moduły importują inne moduły, więc trzeba się upewnić że zmienna środowiskowa &amp;lt;tt&amp;gt;PYTHONPATH&amp;lt;/tt&amp;gt; ma odpowiednią wartość, w szczególności musi się w niej znaleźć ścieżka do &amp;lt;tt&amp;gt;azouk-libraries/build/&amp;lt;/tt&amp;gt; aby można było zaimportować moduł &amp;lt;tt&amp;gt;multiplexer&amp;lt;/tt&amp;gt;. Eksportować ścieżki można np tak:&lt;br /&gt;
&amp;lt;tt&amp;gt;export PYTHONPATH=./:openbci/:azouk-libraries/build/:PYTHONPATH&amp;lt;/tt&amp;gt;, tzn. dodajemy ścieżki oddzielone dwukropkiem, tylko należy się upewnić, że dodajemy odpowiednie ścieżki)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# signal_catcher.py&lt;br /&gt;
&lt;br /&gt;
import time&lt;br /&gt;
from multiplexer.multiplexer_constants import peers, types&lt;br /&gt;
from multiplexer.clients import BaseMultiplexerServer&lt;br /&gt;
import collections, variables_pb2&lt;br /&gt;
&lt;br /&gt;
class SignalCatcher(BaseMultiplexerServer):&lt;br /&gt;
    def __init__(self, addresses):&lt;br /&gt;
        super(SignalCatcher, self).__init__(addresses=addresses, type=peers.SIGNAL_CATCHER)&lt;br /&gt;
        self.number_of_channels = len(self.conn.query(message=&amp;quot;AmplifierChannelsToRecord&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message.split(&amp;amp;rdquo; &amp;amp;bdquo;))&lt;br /&gt;
        self.buffer = [collections.deque() for z in range(self.number_of_channels)]&lt;br /&gt;
        self.buffer_size = int(self.conn.query(message=&amp;quot;SignalCatcherBufferSize&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message)&lt;br /&gt;
&lt;br /&gt;
    def add(self, value):&lt;br /&gt;
        sampleVector = variables_pb2.SampleVector()&lt;br /&gt;
        sampleVector.ParseFromString(value)&lt;br /&gt;
&lt;br /&gt;
        i = 0&lt;br /&gt;
        for s in values:&lt;br /&gt;
            self.buffer[i].append(s)&lt;br /&gt;
            if len(self.buffer[i]) &amp;gt; self.buffer_size:&lt;br /&gt;
                self.buffer[i].popleft()&lt;br /&gt;
            i += 1&lt;br /&gt;
      &lt;br /&gt;
    def handle_message(self, mxmsg):&lt;br /&gt;
        if mxmsg.type == types.SIGNAL_CATCHER_REQUEST_MESSAGE:&lt;br /&gt;
            vector = variables_pb2.SampleVector()&lt;br /&gt;
            ind = int(mxmsg.message)&lt;br /&gt;
            &lt;br /&gt;
            for i in range(len(self.buffer[ind])):&lt;br /&gt;
                s = vector.samples.add()&lt;br /&gt;
                s.CopyFrom(self.buffer[ind][i])&lt;br /&gt;
            m = vector.SerializeToString()&lt;br /&gt;
            self.send_message(message = m, type = types.SIGNAL_CATCHER_RESPONSE_MESSAGE)&lt;br /&gt;
        elif mxmsg.type == types.AMPLIFIER_SIGNAL_MESSAGE:&lt;br /&gt;
            self.add(mxmsg.message)&lt;br /&gt;
            self.no_response()&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;amp;bdquo;__main__&amp;quot;:&lt;br /&gt;
    SignalCatcher(settings.MULTIPLEXER_ADDRESSES).loop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* próba obejrzenia zmiany tętna po wysiłku fizycznym, bądź w spoczynku--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11674</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 2 4</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11674"/>
		<updated>2026-03-18T08:29:45Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Ćwiczenie 5: HRV */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EKG&lt;br /&gt;
&lt;br /&gt;
==Rejestracja i analiza sygnału EKG==&lt;br /&gt;
&lt;br /&gt;
Lektura:  [http://www.bem.fi/book/15/15.htm Electric and Magnetic Measurement of the Electric Activity of the Heart/12-Lead ECG System]&lt;br /&gt;
[[Plik:einthoven_ekg.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Aparat do rejestracji czynności elektrycznej serca skonstruowany przez W. Einthovena. Proszę zauważyć w jakich miejscach na ciele zbierana jest sygnał.]]&lt;br /&gt;
[[Plik:ekg_animacja.gif|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Rozchodzenie się sygnału stymulujacego pracę serca i związane z tym powstawanie sygnału EKG. Rysunek po brany ze strony Wikipedii.]]&lt;br /&gt;
[[Plik:ekg_opis.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Oznaczenia kolejnych składowych sygnału EKG.]]&lt;br /&gt;
[[Plik:wilson.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:wilson&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Umiejscowienie elektrod do pomiaru czynności elektrycznej serca z powierzchni klatki piersiowej, rysunek pobrany ze stron Wikipedii.]]&lt;br /&gt;
 &lt;br /&gt;
Mechanizm powstawania czynności elektrycznej serca został omówiony na zajęciach &amp;amp;bdquo;Sygnały Bioelektryczne&amp;quot;. W tym miejscu przypomnimy tylko kilka ważnych (i ciekawych) faktów.&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Czynność elektryczna serca znana jest od połowy XIX, jednakże za początek narodzin elektrokardiografii uznaje się rok 1903, kiedy to W. Einthoven dokonał pomiaru czynności elektrycznej serca z powierzchni ciała (&amp;lt;xr id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). Jako metoda diagnostyczna, elektrokardiografia zaczęła się szybko rozwijać po roku 1936, kiedy to do rejestracji czynności elektrycznej serca zastosowano wzmacniacz lampowy oraz system zapisu pomiaru na papierze.&lt;br /&gt;
&amp;lt;li&amp;gt; Serce posiada specjalny, wzbudzany samoczynnie układ, który generuje i przewodzi bodźce elektryczne. Następstwem działania tego układu jest rytmiczna praca serca o częstości od 70 do 180 cykli na minutę (częstość ta ulega zmianom pod wpływem czynników biochemicznych, powstałych np. w skutek stresu).&lt;br /&gt;
&amp;lt;li&amp;gt; Elektroda rejestrująca sygnał EKG zbiera czynność elektryczną wszystkich komórek serca, a zatem zarówno komórek wchodzących w skład układu generującego i przewodzącego impulsy elektryczne oraz kurczących się pod wpływem impulsów sterujących mięśni, które kurcząc się, również wytwarzają sygnał elektryczny. Jednakże, z uwagi na nieporównywalnie dużo większą masę mięśni serca w porównaniu z masą komórek układu stymulującego przyjmuje się, że głównym składnikiem sygnału EKG jest czynność elektryczna mięśnia sercowego.&lt;br /&gt;
&amp;lt;li&amp;gt; W przybliżeniu, sygnał stymulujący pracę serca rozchodzi się z jego prawej górnej części w kierunku dolnym i na lewą stronę. Na skutek pobudzania kolejnych partii mięśnia sercowego, powstaje charakterystyczny kształt sygnału EKG (&amp;lt;xr id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, &amp;lt;xr id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). &lt;br /&gt;
&amp;lt;li&amp;gt; Oznaczenia kolejnych składowych sygnału EKG:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; odchylenia od linii poziomej (izoelektrycznej) nazywamy załamkami,&lt;br /&gt;
&amp;lt;li&amp;gt; odległość w czasie pomiędzy końcem załamka P i początkiem załamka Q oraz końcem załamka S i początkiem załamka T nazywamy odcinkami &amp;amp;mdash; odpowiednio PQ i ST.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Elektrody pomiarowe połączone do aparatury rejestrujących nazywamy odprowadzeniami. Uwaga &amp;amp;mdash; przyjęto odprowadzeniami oznaczać także sygnały EKG będące liniowymi kombinacjami sygnałów zebranych przez elektrody.&lt;br /&gt;
&amp;lt;li&amp;gt; W konwencjonalnej elektroencefalografii stosuje się 12 tzw. odprowadzeń klasycznych:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Trzy odprowadzenia kończynowe biegunowe, zaproponowane jeszcze przez Einthoven i oznaczane rzymskimi cyframi I, II i III. Elektrody w tym systemie umieszcza się prawej (R) (ang. ''right'') i lewej (L) (ang. ''left'') kończynie górnej (najczęściej w okolicy nadgarstka, czasem ramieniu lub czy barku) oraz lewej nodze w okolicy stopy (F) (ang. ''foot''). Elektrodę umieszczaną na prawym nadgarstku oznacza się kolorem czerwonym, na lewym żółtym, na lewej kostce zielonym. Elektrodę masy umieszcza się zwykle na lewej kostce (choć teoretycznie można ją aplikować gdziekolwiek) i jest ona oznaczona kolorem czarnym. Odprowadzenia kończynowe mierzą różnicę napięć pomiędzy miejscami przyłożenia elektrod w następujący sposób:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
I   &amp;amp; = V_{L} - V_{R} \\&lt;br /&gt;
II  &amp;amp; = V_{F} - V_{R} \\&lt;br /&gt;
III &amp;amp; = V_{F} - V_{L}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
gdzie: &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;V_{R}, V_{L}, V_{F}&amp;lt;/math&amp;gt; to potencjały odpowiednio na prawym i lewym nadgarstku oraz stopie mierzone względem elektrody masy.&amp;lt;br/&amp;gt;&lt;br /&gt;
Jak łatwo zauważyć, tylko dwa spośród powyższych napięć są liniowo niezależne, co można zapisać w postaci związku:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_2&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;I + III = II&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
który nazywany jest prawem Einthovena. Proszę zauważyć, iż w tym przypadku wzmacniane jest sygnał będący różnicą napięć dwóch kolejnych elektrod, stąd też te odprowadzenia nazywamy dwubiegunowymi (bipolarnymi).&lt;br /&gt;
&amp;lt;li&amp;gt; Trzy odprowadzenia jednobiegunowe Goldberga. W odprowadzeniach tych sygnał w danym odprowadzeniu jest różnicą napięć pomiędzy elektrodą pomiarową a średnim napięciem na dwóch pozostałych elektrodach:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
aV_{R} &amp;amp; = V_{R} - \frac{V_{L}+V_{F}}{2} \\&lt;br /&gt;
aV_{L} &amp;amp; = V_{L} - \frac{V_{R}+V_{F}}{2} \\&lt;br /&gt;
aV_{F} &amp;amp; = V_{F} - \frac{V_{L}+V_{R}}{2}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Sześć odprowadzeń jednobiegunowych Wilsona. W przypadku warto zapoznać się z z historią tych odprowadzeń. Początkowo Wilson zaproponował układ jednobiegunowych doniesień dla kończyn w następujący sposób:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_4&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
V_{LW} &amp;amp; = V_{L} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{RW} &amp;amp; = V_{R} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{FW} &amp;amp; = V_{F} - \frac{V_{R}+V_{L}+ V_{F}}{3}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
Jak widzimy, jako elektrodę odniesienia wybrał on średnie napięcie rejestrowane przez elektrody. Niestety, sygnały prezentowane w tym systemie miały małą amplitudę, w związku z czym tego rodzaju odprowadzenia nie stosowano w praktyce. Z systemu zaproponowanego przez Wilsona wywodzi się jednak system odniesień Goldberga, który zauważył, że napięcie na trzeciej kończynie można zwiększyć o 50% jeśli do wyznaczenia napięcia odniesienia zastosuje się dwie, a nie trzy elektrody. Metoda wyznaczania potencjału odniesienia zaproponowana przez Wilsona znalazła jednak zastosowanie przy mierzeniu czynności elektrycznej serca mierzonej z powierzchni klatki piersiowej. W tym celu elektrody umieszcza się w pewnych ustalonych miejscach (&amp;lt;xr id=&amp;quot;fig:wilson&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, zaś odprowadzenia oznacza się symbolami &amp;lt;math&amp;gt;V_1, V_2, \dots, V_6&amp;lt;/math&amp;gt;. Odniesieniem w tym przypadku jest średni sygnał rejestrowany na kończynach górnych i lewej stopie. &lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ćwiczenia==&lt;br /&gt;
&lt;br /&gt;
Aby uruchomić zbieranie sygnału należy wykonać następujące operacje:&lt;br /&gt;
* przykleić elektrody do badanego;&lt;br /&gt;
* włożyć przewody do elektrod, a potem do wzmacniacza;&lt;br /&gt;
* podłączyć zasilanie wzmacniacza;&lt;br /&gt;
* podłączyć wzmacniacz do komputera (przejściówka optyczna i kabel USB);&lt;br /&gt;
* uruchomić program SVAROG&lt;br /&gt;
* otworzyć sygnał on-line ze wzmacniacza. &lt;br /&gt;
**  Po tym poleceniu wzmacniacz powinien wyświetlać napis &amp;amp;bdquo;Fiber&amp;amp;rdquo;; napis &amp;amp;bdquo;Connect&amp;amp;rdquo; oznacza, że połączenie wzmacniacza z komputerem nie udało się. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie 0: wstępne  ===&lt;br /&gt;
* Podaj związek pomiędzy sygnałami mierzonymi w systemie Goldbergera, a systemem Einthovena.&lt;br /&gt;
* Podaj analogiczny związek pomiędzy sygnałami w odniesieniach Goldberga co ''Prawo Einthovena''. &lt;br /&gt;
* Pokaż, że w systemie Goldbergera uzyskuje się sygnały o amplitudzie o 50% wyższej niż w pierwotnym systemie Wilsona.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Realizacja w grupie ==&lt;br /&gt;
=== Ćwiczenie 1: rejestracja sygnału === &lt;br /&gt;
&lt;br /&gt;
Podłącz elektrody:&lt;br /&gt;
* lewa ręka, &lt;br /&gt;
* prawa ręka, &lt;br /&gt;
* lewa noga, &lt;br /&gt;
* uziemienie do prawej nogi.&lt;br /&gt;
&lt;br /&gt;
Zbierz 3 fragment sygnału EKG przy pomocy Svaroga. &lt;br /&gt;
&lt;br /&gt;
* Częstotliwość próbkowania 2048 Hz.&lt;br /&gt;
* Długość zapisu 300 s.&lt;br /&gt;
* Proszę zapisać sygnały w następujących warunkach:&lt;br /&gt;
** spoczynkowe&lt;br /&gt;
** po wysiłku fizycznym (odpiąć zatrzaskowe elektrody, przejść się po schodach i podłączyć ponownie )&lt;br /&gt;
** podczas obciążenia poznawczego, np. odejmując w pamięci kolejno 17 od 1000.&lt;br /&gt;
* zebrane sygnały zapisz na dysku classroom&lt;br /&gt;
&lt;br /&gt;
Zapoznaj się z zagadnieniem filtrowania dla sygnałów EKG:&lt;br /&gt;
* Proszę przejrzeć pracę: Shen Luo, Paul Johnston. A review of electrocardiogram filtering,  ''Journal of Electrocardiology'', 2010, Volume 43, Issue 6,  Pages 486-496 (https://www.sciencedirect.com/science/article/pii/S0022073610002852?via%3Dihub) &lt;br /&gt;
* popróbować uzyskać opisane tam filtry w SVAROGU i zaaplikować je do zebranych danych&lt;br /&gt;
&lt;br /&gt;
== Realizacja indywidualna w notebooku ==&lt;br /&gt;
===Ćwiczenie 2: Wstępna obróbka sygnału EKG ===&lt;br /&gt;
Napisz fragment notebooka, który:&lt;br /&gt;
* wczytuje sygnał przykład: [https://colab.research.google.com/drive/1QWfjnuf_LkdOnQzaBej0itD9yxWzlA6R?usp=sharing przykład]&lt;br /&gt;
* wykonuje stosowne filtracje (stosujemy filtrację z zerowym przesunięciem fazowym: filtfilt):  &lt;br /&gt;
** Filtr górnoprzepustowy:&lt;br /&gt;
*** z częstością odcięcia  0.67 Hz (przy tej częstości wymagamy 3dB tłumienia) &lt;br /&gt;
*** poniżej 0.5-dB tętnień w paśmie 1 - 30 Hz. &lt;br /&gt;
*** projekt z wykorzystaniem funkcji scipy.signal.iirfilter; trzeba dobrać rząd i sprawdzić charakterystyki funkcji transmitancji - dobrać zakres osi i dodać linie pomocnicze pionowe i poziome (matplotlib.pyplot.axvline i matplotlib.pyplot.axhline) tak aby było widać że zaprojektowany filtr spełnia powyższe kryteria.&lt;br /&gt;
** Filtr dolnoprzepustowy z częstością odcięcia 150Hz &lt;br /&gt;
*** wymagania te powinien spełnić np. filtr 2 rzędu, Butterwortha, - proszę sprawdzić charakterystyki).&lt;br /&gt;
** Filtr pasmowo-zaporowy (notch) dla 50 Hz iirnotch (scipy.signal.iirnotch())&lt;br /&gt;
* rysuje sygnał w odprowadzeniach Einthovena i Goldbergera,&lt;br /&gt;
* wybierz &amp;quot;czysty&amp;quot; fragment sygnału i zidentyfikuj poszczególne załamki. (można wykorzystać funkcję matplotlib.pyplot.axvspan)&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 3: Detekcja pików R ===&lt;br /&gt;
* Zaproponuj metodę rozpoznawania pików R w sygnale, &lt;br /&gt;
** wybierz do tego optymalny kanał&lt;br /&gt;
** rozważ zastosowanie filtra górnoprzepustowego o wyższej częstości odcięcia niż w ćwiczeniu 2&lt;br /&gt;
** skorzystaj z funkcji [https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks.html scipy.signal.find_peaks] - zaprezentuj dobór parametrów funkcji na podsdtawie histogramów odpowiednich parametrów, które zwraca ona w słowniku.&lt;br /&gt;
* Przedstaw fragment sygnału z zaznaczonymi pikami R dla różnych warunków rejestracji sygnału EKG. &lt;br /&gt;
&lt;br /&gt;
Przydatne pojęcie: (ang.) [https://pl.wikipedia.org/wiki/Minimalna_deniwelacja_wzgl%C4%99dna prominence - wybitność piku]&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 4: Tętno ===&lt;br /&gt;
Napisz program, który:&lt;br /&gt;
* wczyta plik z sygnałem i na jego podstawie &lt;br /&gt;
* wyznaczy i wykreśli tętno - liczbę uderzeń serca na minutę (ang. ''heart rate'').&lt;br /&gt;
* Oblicz średnie tętno i jego standardowe odchylenie.&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 5: HRV ===&lt;br /&gt;
HRV - heart rate variability. &lt;br /&gt;
* zapoznaj się z koncepcją [https://en.wikipedia.org/wiki/Heart_rate_variability#cite_note-29 HRV]&lt;br /&gt;
* Literatura [https://link.springer.com/article/10.1007/s11517-006-0119-0 Heart rate variability: a review]. &lt;br /&gt;
* przedstaw interwały R-R jako szereg czasowy&lt;br /&gt;
* przedstaw miarę RMSSD obliczaną dla okien 30s przesuwanych co jedną odległość RR jako szereg czasowy&lt;br /&gt;
* wykonaj interpolację sygnału RR do stałej częstości próbkowania 4Hz &lt;br /&gt;
** Uwaga: oryginalne próbki RR są pobierane w różnych odstępach!&lt;br /&gt;
** można zinterpolować punkty na równomiernie próbkowanej siatce https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html#scipy.interpolate.interp1d i zastosować standardową funkcję do estymacji:&lt;br /&gt;
***  periodogramów&lt;br /&gt;
*** widma metodą AR&lt;br /&gt;
* wyestymuj widmo częstotliwościowe sygnału RR, z sygnału wysiłkowego postaraj się usunąć trend&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* porównaj widma HRV w poszczególnych warunkach eksperymentalnych; zwróć uwagę na proporcje mocy w pasmach wysokich częstości (HF: 0.15 do 0.4 Hz), niskich częstości (LF: 0.04 do 0.15 Hz) i bardzo niskich częstości (VLF: 0.0033 do 0.04 Hz).&lt;br /&gt;
&lt;br /&gt;
==Literatura uzupełniająca==&lt;br /&gt;
&lt;br /&gt;
[http://www.bem.fi/book/19/19.htm#00 podstawowa diagnostyka EKG]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;!--;Ćwiczenie 8: Wykorzystując poniższe fragmenty kodu, stwórz program, który będzie wyrysowywał zmiany tętna w czasie rzeczywistym.&lt;br /&gt;
Pierwszy fragment kodu, to moduł buforujący sygnał, drugi to moduł pobierający dane z bufora. Należy dopisać do modułu pobierającego dane z bufora przetwarzanie ich (wyrysowywanie tętna) we wskazanym miejscu. &lt;br /&gt;
Uruchamianie całości będzie polegało na:&lt;br /&gt;
* uruchomieniu wzmacniacza&lt;br /&gt;
* uruchomieniu modułu &amp;lt;tt&amp;gt;signal_catcher.py&amp;lt;/tt&amp;gt;&lt;br /&gt;
* uruchomienie &amp;lt;tt&amp;gt;heartrate.py&amp;lt;/tt&amp;gt;, ktory jest dostepny [http://escher.fuw.edu.pl/~mm/zajecia/heartrate.py tu], po wstawieniu do niego w odpowiednie miejsce oznaczone w komentarzu własnego kodu obliczającego tętno.&lt;br /&gt;
* Trochę zmieniona wersja &amp;amp;mdash; [http://escher.fuw.edu.pl/~mm/zajecia/heartrate_new.py &amp;lt;tt&amp;gt;heartrate_new.py&amp;lt;/tt&amp;gt;] oraz  [http://escher.fuw.edu.pl/~mm/zajecia/signal_catcher_pracownia.py &amp;lt;tt&amp;gt;signal_catcher_pracownia.py&amp;lt;/tt&amp;gt;]&lt;br /&gt;
(moduły importują inne moduły, więc trzeba się upewnić że zmienna środowiskowa &amp;lt;tt&amp;gt;PYTHONPATH&amp;lt;/tt&amp;gt; ma odpowiednią wartość, w szczególności musi się w niej znaleźć ścieżka do &amp;lt;tt&amp;gt;azouk-libraries/build/&amp;lt;/tt&amp;gt; aby można było zaimportować moduł &amp;lt;tt&amp;gt;multiplexer&amp;lt;/tt&amp;gt;. Eksportować ścieżki można np tak:&lt;br /&gt;
&amp;lt;tt&amp;gt;export PYTHONPATH=./:openbci/:azouk-libraries/build/:PYTHONPATH&amp;lt;/tt&amp;gt;, tzn. dodajemy ścieżki oddzielone dwukropkiem, tylko należy się upewnić, że dodajemy odpowiednie ścieżki)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# signal_catcher.py&lt;br /&gt;
&lt;br /&gt;
import time&lt;br /&gt;
from multiplexer.multiplexer_constants import peers, types&lt;br /&gt;
from multiplexer.clients import BaseMultiplexerServer&lt;br /&gt;
import collections, variables_pb2&lt;br /&gt;
&lt;br /&gt;
class SignalCatcher(BaseMultiplexerServer):&lt;br /&gt;
    def __init__(self, addresses):&lt;br /&gt;
        super(SignalCatcher, self).__init__(addresses=addresses, type=peers.SIGNAL_CATCHER)&lt;br /&gt;
        self.number_of_channels = len(self.conn.query(message=&amp;quot;AmplifierChannelsToRecord&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message.split(&amp;amp;rdquo; &amp;amp;bdquo;))&lt;br /&gt;
        self.buffer = [collections.deque() for z in range(self.number_of_channels)]&lt;br /&gt;
        self.buffer_size = int(self.conn.query(message=&amp;quot;SignalCatcherBufferSize&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message)&lt;br /&gt;
&lt;br /&gt;
    def add(self, value):&lt;br /&gt;
        sampleVector = variables_pb2.SampleVector()&lt;br /&gt;
        sampleVector.ParseFromString(value)&lt;br /&gt;
&lt;br /&gt;
        i = 0&lt;br /&gt;
        for s in values:&lt;br /&gt;
            self.buffer[i].append(s)&lt;br /&gt;
            if len(self.buffer[i]) &amp;gt; self.buffer_size:&lt;br /&gt;
                self.buffer[i].popleft()&lt;br /&gt;
            i += 1&lt;br /&gt;
      &lt;br /&gt;
    def handle_message(self, mxmsg):&lt;br /&gt;
        if mxmsg.type == types.SIGNAL_CATCHER_REQUEST_MESSAGE:&lt;br /&gt;
            vector = variables_pb2.SampleVector()&lt;br /&gt;
            ind = int(mxmsg.message)&lt;br /&gt;
            &lt;br /&gt;
            for i in range(len(self.buffer[ind])):&lt;br /&gt;
                s = vector.samples.add()&lt;br /&gt;
                s.CopyFrom(self.buffer[ind][i])&lt;br /&gt;
            m = vector.SerializeToString()&lt;br /&gt;
            self.send_message(message = m, type = types.SIGNAL_CATCHER_RESPONSE_MESSAGE)&lt;br /&gt;
        elif mxmsg.type == types.AMPLIFIER_SIGNAL_MESSAGE:&lt;br /&gt;
            self.add(mxmsg.message)&lt;br /&gt;
            self.no_response()&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;amp;bdquo;__main__&amp;quot;:&lt;br /&gt;
    SignalCatcher(settings.MULTIPLEXER_ADDRESSES).loop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* próba obejrzenia zmiany tętna po wysiłku fizycznym, bądź w spoczynku--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG&amp;diff=11667</id>
		<title>Laboratorium EEG</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG&amp;diff=11667"/>
		<updated>2026-03-12T14:46:53Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały dydaktyczne */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Pracownie specjalistyczne]]&lt;br /&gt;
__NOTOC__&lt;br /&gt;
==Informacje bieżące==&lt;br /&gt;
&amp;lt;!--:[[Laboratorium_EEG/Info_1| Grupa 1: MK+JR]]&lt;br /&gt;
:[[Laboratorium_EEG/Info_2| Grupa 2: JZ+AG]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zajęcia są prowadzone przez Macieja Kamińskiego i Jarosława Żygierewicza&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zajęcia odbywają się w sali 4.59:&lt;br /&gt;
* we wtorki w godzinach 11:15 - 13:45&lt;br /&gt;
* w czwartki w godzinach 13:15 - 15:45&lt;br /&gt;
&lt;br /&gt;
== Warunki zaliczenia ==&lt;br /&gt;
Ćwiczenia zostaną zaliczone osobom, które spełnią dwa niezwykle proste warunki:&lt;br /&gt;
* Posiadanie maksymalnie dwóch nieusprawiedliwionych nieobecności na ćwiczeniach,&lt;br /&gt;
* Posiadanie przynajmniej połowy sumy punktów ze wszystkich prezentacji,&lt;br /&gt;
* ... ''(do ustalenia).''&lt;br /&gt;
&lt;br /&gt;
=== Elementy oceniane w prezentacji:===&lt;br /&gt;
* poprawność zastosowanego algorytmu -&amp;gt; należy przygotować opis ideowy algorytmu w punktach/na schemacie &lt;br /&gt;
* prezentacja wykonanych testów pokazujacych, że algorytm działa poprawnie &lt;br /&gt;
* jakość kodu (czytelność, komentarze, struktura, czy ktoś komu mielibyśmy przekazać ten kod ma sznsę go zrozumieć)&lt;br /&gt;
* wykazanie się zrozumieniem otrzymanych wyników.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--* Posiadanie przynajmniej połowy sumy punktów ze wszystkich kartkówek&lt;br /&gt;
* Osobom spełniającym powyższe warunki zaproponowana zostanie pozytywna ocena końcowa z Laboratorium.&lt;br /&gt;
* Osoby nie mające tego szczęścia, otrzymają ocenę negatywną.&lt;br /&gt;
&lt;br /&gt;
* Możliwe będzie poprawienie zaproponowanej oceny na wyższą poprzez zrealizowanie dodatkowego projektu. Jego cel zostanie ustalony indywidualnie.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały dydaktyczne==&lt;br /&gt;
Zestaw przykładowych materiałów dotyczących analizy danych w Matlabie towarzyszący książce autorstwa Katarzyny J. Blinowskiej i Jarosława Żygierewicza zatytułowanej &amp;quot;Practical Biomedical Signal Analysis Using MATLAB® Second Edition]&amp;quot; ([https://books.google.pl/books?id=hSpHEAAAQBAJ&amp;amp;pg=PA1&amp;amp;hl=pl&amp;amp;source=gbs_toc_r&amp;amp;cad=3#v=onepage&amp;amp;q&amp;amp;f=false spis treści]):&lt;br /&gt;
 &lt;br /&gt;
https://static.routledge.com/9781138364417/matlab.zip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Wprowadzenie do przetwarzania sygnałów online===&lt;br /&gt;
* [[Laboratorium_EEG/Wprowadzenie_do_syg_online|ONLINE]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 10.03.2021 Pomiar EEG spoczynkowe, artefakty i alfa +P300 ===&lt;br /&gt;
Proszę powtórzyć informacje z : &lt;br /&gt;
* [[Pracownia_Sygnałów_Biologicznych/Zajecia_9]]. W szczególności proszę zwrócić uwagę na:&lt;br /&gt;
** porcedurę zakładania czepka&lt;br /&gt;
** przygotowanie skóry do pomiaru&lt;br /&gt;
** kolejność mocowania elektrod w czepku&lt;br /&gt;
* [[Pracownia_EEG/EEG_spoczynkowe]]&lt;br /&gt;
** Jakie wyróżniamy rytmy i na jakiej podstawie?&lt;br /&gt;
** Jakie są główne źródła artefaktów?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* [[Pracownia_EEG/Potencjały_wywołane#Zadanie_3:_rejestracja_i_analiza_potencja.C5.82u_P3]]&lt;br /&gt;
** Co to jest potencjał P300&lt;br /&gt;
Lektura uzupełniająca o P300:&lt;br /&gt;
Linden, D. E. J. (2005). The P300: Where in the Brain Is It Produced and What Does It Tell Us? The Neuroscientist, 11(6), 563–576. https://doi.org/10.1177/1073858405280524&lt;br /&gt;
(Z IP wydziałowego można pobrać ten art. w pdf)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Wprowadzenie do Matlaba===&lt;br /&gt;
* [[Laboratorium_EEG/Wprowadzenie_do_Matlaba|Wprowadzenie do Matlaba]]&amp;lt;br&amp;gt;&lt;br /&gt;
* [[Laboratorium_EEG/Konwerter_plików_Svarog–Matlab|Wczytywanie do Matlaba plików binarnych z programu Svarog]]&lt;br /&gt;
===EEGLAB===&lt;br /&gt;
* [[Laboratorium_EEG/EEGLAB|Pakiet EEGLAB]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Metody czas-częstość===&lt;br /&gt;
&amp;lt;!--* [[Wstęp do analizy obrazu]]--&amp;gt;&lt;br /&gt;
Motywacja - główne paradygmaty BCI:&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1hMbkzn07pVDfeJ4fk9JPHhZaIckz-PVL/view?usp=share_link&lt;br /&gt;
&lt;br /&gt;
Wstęp o analizie ERD/ERS:&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1hP5VglC8jYnoGHJ2j06m1AOMe8ItwCkb/view?usp=share_link&lt;br /&gt;
&lt;br /&gt;
* [[Laboratorium_EEG/Analiza czas-częstość w matlabie|Analiza czas-częstość w matlabie]]&lt;br /&gt;
* [[Laboratorium_EEG/Analiza zjawiska ERD/ERS|Analiza zjawiska ERD/ERS]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Filtry przestrzenne===&lt;br /&gt;
* [[Laboratorium_EEG/CSP|Filtry przestrzenne]]:  metody ślepej separacji źródeł&lt;br /&gt;
&lt;br /&gt;
===Zależności przyczynowe===&lt;br /&gt;
* [[Laboratorium_EEG/AR_1|Wielokanałowa analiza parametryczna/Zależności przyczynowe]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Słuchowe potencjały stanu ustalonego: zmiany mocy pasmowej i metody ślepej separacji źródeł===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MP===&lt;br /&gt;
* [[Laboratorium_EEG/MMP|MMP]]&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG&amp;diff=11658</id>
		<title>Laboratorium EEG</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG&amp;diff=11658"/>
		<updated>2026-03-12T13:12:00Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały dydaktyczne */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Pracownie specjalistyczne]]&lt;br /&gt;
__NOTOC__&lt;br /&gt;
==Informacje bieżące==&lt;br /&gt;
&amp;lt;!--:[[Laboratorium_EEG/Info_1| Grupa 1: MK+JR]]&lt;br /&gt;
:[[Laboratorium_EEG/Info_2| Grupa 2: JZ+AG]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zajęcia są prowadzone przez Macieja Kamińskiego i Jarosława Żygierewicza&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zajęcia odbywają się w sali 4.59:&lt;br /&gt;
* we wtorki w godzinach 11:15 - 13:45&lt;br /&gt;
* w czwartki w godzinach 13:15 - 15:45&lt;br /&gt;
&lt;br /&gt;
== Warunki zaliczenia ==&lt;br /&gt;
Ćwiczenia zostaną zaliczone osobom, które spełnią dwa niezwykle proste warunki:&lt;br /&gt;
* Posiadanie maksymalnie dwóch nieusprawiedliwionych nieobecności na ćwiczeniach,&lt;br /&gt;
* Posiadanie przynajmniej połowy sumy punktów ze wszystkich prezentacji,&lt;br /&gt;
* ... ''(do ustalenia).''&lt;br /&gt;
&lt;br /&gt;
=== Elementy oceniane w prezentacji:===&lt;br /&gt;
* poprawność zastosowanego algorytmu -&amp;gt; należy przygotować opis ideowy algorytmu w punktach/na schemacie &lt;br /&gt;
* prezentacja wykonanych testów pokazujacych, że algorytm działa poprawnie &lt;br /&gt;
* jakość kodu (czytelność, komentarze, struktura, czy ktoś komu mielibyśmy przekazać ten kod ma sznsę go zrozumieć)&lt;br /&gt;
* wykazanie się zrozumieniem otrzymanych wyników.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--* Posiadanie przynajmniej połowy sumy punktów ze wszystkich kartkówek&lt;br /&gt;
* Osobom spełniającym powyższe warunki zaproponowana zostanie pozytywna ocena końcowa z Laboratorium.&lt;br /&gt;
* Osoby nie mające tego szczęścia, otrzymają ocenę negatywną.&lt;br /&gt;
&lt;br /&gt;
* Możliwe będzie poprawienie zaproponowanej oceny na wyższą poprzez zrealizowanie dodatkowego projektu. Jego cel zostanie ustalony indywidualnie.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały dydaktyczne==&lt;br /&gt;
Zestaw przykładowych materiałów dotyczących analizy danych w Matlabie towarzyszący książce autorstwa Katarzyny J. Blinowskiej i Jarosława Żygierewicza zatytułowanej &amp;quot;Practical Biomedical Signal Analysis Using MATLAB® Second Edition]&amp;quot; ([https://books.google.pl/books?id=hSpHEAAAQBAJ&amp;amp;pg=PA1&amp;amp;hl=pl&amp;amp;source=gbs_toc_r&amp;amp;cad=3#v=onepage&amp;amp;q&amp;amp;f=false spis treści]):&lt;br /&gt;
 &lt;br /&gt;
https://static.routledge.com/9781138364417/matlab.zip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Wprowadzenie do przetwarzania sygnałów online===&lt;br /&gt;
* [[Laboratorium_EEG/Wprowadzenie_do_syg_online|ONLINE]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 10.03.2021 Pomiar EEG spoczynkowe, artefakty i alfa +P300 ===&lt;br /&gt;
Proszę powtórzyć informacje z : &lt;br /&gt;
* [[Pracownia_Sygnałów_Biologicznych/Zajecia_9]]. W szczególności proszę zwrócić uwagę na:&lt;br /&gt;
** porcedurę zakładania czepka&lt;br /&gt;
** przygotowanie skóry do pomiaru&lt;br /&gt;
** kolejność mocowania elektrod w czepku&lt;br /&gt;
* [[Pracownia_EEG/EEG_spoczynkowe]]&lt;br /&gt;
** Jakie wyróżniamy rytmy i na jakiej podstawie?&lt;br /&gt;
** Jakie są główne źródła artefaktów?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* [[Pracownia_EEG/Potencjały_wywołane#Zadanie_3:_rejestracja_i_analiza_potencja.C5.82u_P3]]&lt;br /&gt;
** Co to jest potencjał P300&lt;br /&gt;
Lektura uzupełniająca o P300:&lt;br /&gt;
Linden, D. E. J. (2005). The P300: Where in the Brain Is It Produced and What Does It Tell Us? The Neuroscientist, 11(6), 563–576. https://doi.org/10.1177/1073858405280524&lt;br /&gt;
(Z IP wydziałowego można pobrać ten art. w pdf)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Wprowadzenie do Matlaba===&lt;br /&gt;
* [[Laboratorium_EEG/Wprowadzenie_do_Matlaba|Wprowadzenie do Matlaba]]&amp;lt;br&amp;gt;&lt;br /&gt;
* [[Laboratorium_EEG/Konwerter_plików_Svarog–Matlab|Wczytywanie do Matlaba plików binarnych z programu Svarog]]&lt;br /&gt;
===EEGLAB===&lt;br /&gt;
* [[Laboratorium_EEG/EEGLAB|Pakiet EEGLAB]]&lt;br /&gt;
&lt;br /&gt;
===Filtry przestrzenne===&lt;br /&gt;
* [[Laboratorium_EEG/CSP|Filtry przestrzenne]]:  metody ślepej separacji źródeł&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Metody czas-częstość===&lt;br /&gt;
&amp;lt;!--* [[Wstęp do analizy obrazu]]--&amp;gt;&lt;br /&gt;
Motywacja - główne paradygmaty BCI:&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1hMbkzn07pVDfeJ4fk9JPHhZaIckz-PVL/view?usp=share_link&lt;br /&gt;
&lt;br /&gt;
Wstęp o analizie ERD/ERS:&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1hP5VglC8jYnoGHJ2j06m1AOMe8ItwCkb/view?usp=share_link&lt;br /&gt;
&lt;br /&gt;
* [[Laboratorium_EEG/Analiza czas-częstość w matlabie|Analiza czas-częstość w matlabie]]&lt;br /&gt;
* [[Laboratorium_EEG/Analiza zjawiska ERD/ERS|Analiza zjawiska ERD/ERS]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Zależności przyczynowe===&lt;br /&gt;
* [[Laboratorium_EEG/AR_1|Wielokanałowa analiza parametryczna/Zależności przyczynowe]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Słuchowe potencjały stanu ustalonego: zmiany mocy pasmowej i metody ślepej separacji źródeł===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MP===&lt;br /&gt;
* [[Laboratorium_EEG/MMP|MMP]]&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11657</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 2 4</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11657"/>
		<updated>2026-03-11T09:02:55Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Ćwiczenie 3: Detekcja pików R */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EKG&lt;br /&gt;
&lt;br /&gt;
==Rejestracja i analiza sygnału EKG==&lt;br /&gt;
&lt;br /&gt;
Lektura:  [http://www.bem.fi/book/15/15.htm Electric and Magnetic Measurement of the Electric Activity of the Heart/12-Lead ECG System]&lt;br /&gt;
[[Plik:einthoven_ekg.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Aparat do rejestracji czynności elektrycznej serca skonstruowany przez W. Einthovena. Proszę zauważyć w jakich miejscach na ciele zbierana jest sygnał.]]&lt;br /&gt;
[[Plik:ekg_animacja.gif|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Rozchodzenie się sygnału stymulujacego pracę serca i związane z tym powstawanie sygnału EKG. Rysunek po brany ze strony Wikipedii.]]&lt;br /&gt;
[[Plik:ekg_opis.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Oznaczenia kolejnych składowych sygnału EKG.]]&lt;br /&gt;
[[Plik:wilson.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:wilson&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Umiejscowienie elektrod do pomiaru czynności elektrycznej serca z powierzchni klatki piersiowej, rysunek pobrany ze stron Wikipedii.]]&lt;br /&gt;
 &lt;br /&gt;
Mechanizm powstawania czynności elektrycznej serca został omówiony na zajęciach &amp;amp;bdquo;Sygnały Bioelektryczne&amp;quot;. W tym miejscu przypomnimy tylko kilka ważnych (i ciekawych) faktów.&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Czynność elektryczna serca znana jest od połowy XIX, jednakże za początek narodzin elektrokardiografii uznaje się rok 1903, kiedy to W. Einthoven dokonał pomiaru czynności elektrycznej serca z powierzchni ciała (&amp;lt;xr id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). Jako metoda diagnostyczna, elektrokardiografia zaczęła się szybko rozwijać po roku 1936, kiedy to do rejestracji czynności elektrycznej serca zastosowano wzmacniacz lampowy oraz system zapisu pomiaru na papierze.&lt;br /&gt;
&amp;lt;li&amp;gt; Serce posiada specjalny, wzbudzany samoczynnie układ, który generuje i przewodzi bodźce elektryczne. Następstwem działania tego układu jest rytmiczna praca serca o częstości od 70 do 180 cykli na minutę (częstość ta ulega zmianom pod wpływem czynników biochemicznych, powstałych np. w skutek stresu).&lt;br /&gt;
&amp;lt;li&amp;gt; Elektroda rejestrująca sygnał EKG zbiera czynność elektryczną wszystkich komórek serca, a zatem zarówno komórek wchodzących w skład układu generującego i przewodzącego impulsy elektryczne oraz kurczących się pod wpływem impulsów sterujących mięśni, które kurcząc się, również wytwarzają sygnał elektryczny. Jednakże, z uwagi na nieporównywalnie dużo większą masę mięśni serca w porównaniu z masą komórek układu stymulującego przyjmuje się, że głównym składnikiem sygnału EKG jest czynność elektryczna mięśnia sercowego.&lt;br /&gt;
&amp;lt;li&amp;gt; W przybliżeniu, sygnał stymulujący pracę serca rozchodzi się z jego prawej górnej części w kierunku dolnym i na lewą stronę. Na skutek pobudzania kolejnych partii mięśnia sercowego, powstaje charakterystyczny kształt sygnału EKG (&amp;lt;xr id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, &amp;lt;xr id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). &lt;br /&gt;
&amp;lt;li&amp;gt; Oznaczenia kolejnych składowych sygnału EKG:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; odchylenia od linii poziomej (izoelektrycznej) nazywamy załamkami,&lt;br /&gt;
&amp;lt;li&amp;gt; odległość w czasie pomiędzy końcem załamka P i początkiem załamka Q oraz końcem załamka S i początkiem załamka T nazywamy odcinkami &amp;amp;mdash; odpowiednio PQ i ST.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Elektrody pomiarowe połączone do aparatury rejestrujących nazywamy odprowadzeniami. Uwaga &amp;amp;mdash; przyjęto odprowadzeniami oznaczać także sygnały EKG będące liniowymi kombinacjami sygnałów zebranych przez elektrody.&lt;br /&gt;
&amp;lt;li&amp;gt; W konwencjonalnej elektroencefalografii stosuje się 12 tzw. odprowadzeń klasycznych:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Trzy odprowadzenia kończynowe biegunowe, zaproponowane jeszcze przez Einthoven i oznaczane rzymskimi cyframi I, II i III. Elektrody w tym systemie umieszcza się prawej (R) (ang. ''right'') i lewej (L) (ang. ''left'') kończynie górnej (najczęściej w okolicy nadgarstka, czasem ramieniu lub czy barku) oraz lewej nodze w okolicy stopy (F) (ang. ''foot''). Elektrodę umieszczaną na prawym nadgarstku oznacza się kolorem czerwonym, na lewym żółtym, na lewej kostce zielonym. Elektrodę masy umieszcza się zwykle na lewej kostce (choć teoretycznie można ją aplikować gdziekolwiek) i jest ona oznaczona kolorem czarnym. Odprowadzenia kończynowe mierzą różnicę napięć pomiędzy miejscami przyłożenia elektrod w następujący sposób:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
I   &amp;amp; = V_{L} - V_{R} \\&lt;br /&gt;
II  &amp;amp; = V_{F} - V_{R} \\&lt;br /&gt;
III &amp;amp; = V_{F} - V_{L}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
gdzie: &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;V_{R}, V_{L}, V_{F}&amp;lt;/math&amp;gt; to potencjały odpowiednio na prawym i lewym nadgarstku oraz stopie mierzone względem elektrody masy.&amp;lt;br/&amp;gt;&lt;br /&gt;
Jak łatwo zauważyć, tylko dwa spośród powyższych napięć są liniowo niezależne, co można zapisać w postaci związku:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_2&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;I + III = II&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
który nazywany jest prawem Einthovena. Proszę zauważyć, iż w tym przypadku wzmacniane jest sygnał będący różnicą napięć dwóch kolejnych elektrod, stąd też te odprowadzenia nazywamy dwubiegunowymi (bipolarnymi).&lt;br /&gt;
&amp;lt;li&amp;gt; Trzy odprowadzenia jednobiegunowe Goldberga. W odprowadzeniach tych sygnał w danym odprowadzeniu jest różnicą napięć pomiędzy elektrodą pomiarową a średnim napięciem na dwóch pozostałych elektrodach:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
aV_{R} &amp;amp; = V_{R} - \frac{V_{L}+V_{F}}{2} \\&lt;br /&gt;
aV_{L} &amp;amp; = V_{L} - \frac{V_{R}+V_{F}}{2} \\&lt;br /&gt;
aV_{F} &amp;amp; = V_{F} - \frac{V_{L}+V_{R}}{2}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Sześć odprowadzeń jednobiegunowych Wilsona. W przypadku warto zapoznać się z z historią tych odprowadzeń. Początkowo Wilson zaproponował układ jednobiegunowych doniesień dla kończyn w następujący sposób:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_4&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
V_{LW} &amp;amp; = V_{L} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{RW} &amp;amp; = V_{R} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{FW} &amp;amp; = V_{F} - \frac{V_{R}+V_{L}+ V_{F}}{3}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
Jak widzimy, jako elektrodę odniesienia wybrał on średnie napięcie rejestrowane przez elektrody. Niestety, sygnały prezentowane w tym systemie miały małą amplitudę, w związku z czym tego rodzaju odprowadzenia nie stosowano w praktyce. Z systemu zaproponowanego przez Wilsona wywodzi się jednak system odniesień Goldberga, który zauważył, że napięcie na trzeciej kończynie można zwiększyć o 50% jeśli do wyznaczenia napięcia odniesienia zastosuje się dwie, a nie trzy elektrody. Metoda wyznaczania potencjału odniesienia zaproponowana przez Wilsona znalazła jednak zastosowanie przy mierzeniu czynności elektrycznej serca mierzonej z powierzchni klatki piersiowej. W tym celu elektrody umieszcza się w pewnych ustalonych miejscach (&amp;lt;xr id=&amp;quot;fig:wilson&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, zaś odprowadzenia oznacza się symbolami &amp;lt;math&amp;gt;V_1, V_2, \dots, V_6&amp;lt;/math&amp;gt;. Odniesieniem w tym przypadku jest średni sygnał rejestrowany na kończynach górnych i lewej stopie. &lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ćwiczenia==&lt;br /&gt;
&lt;br /&gt;
Aby uruchomić zbieranie sygnału należy wykonać następujące operacje:&lt;br /&gt;
* przykleić elektrody do badanego;&lt;br /&gt;
* włożyć przewody do elektrod, a potem do wzmacniacza;&lt;br /&gt;
* podłączyć zasilanie wzmacniacza;&lt;br /&gt;
* podłączyć wzmacniacz do komputera (przejściówka optyczna i kabel USB);&lt;br /&gt;
* uruchomić program SVAROG&lt;br /&gt;
* otworzyć sygnał on-line ze wzmacniacza. &lt;br /&gt;
**  Po tym poleceniu wzmacniacz powinien wyświetlać napis &amp;amp;bdquo;Fiber&amp;amp;rdquo;; napis &amp;amp;bdquo;Connect&amp;amp;rdquo; oznacza, że połączenie wzmacniacza z komputerem nie udało się. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie 0: wstępne  ===&lt;br /&gt;
* Podaj związek pomiędzy sygnałami mierzonymi w systemie Goldbergera, a systemem Einthovena.&lt;br /&gt;
* Podaj analogiczny związek pomiędzy sygnałami w odniesieniach Goldberga co ''Prawo Einthovena''. &lt;br /&gt;
* Pokaż, że w systemie Goldbergera uzyskuje się sygnały o amplitudzie o 50% wyższej niż w pierwotnym systemie Wilsona.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Realizacja w grupie ==&lt;br /&gt;
=== Ćwiczenie 1: rejestracja sygnału === &lt;br /&gt;
&lt;br /&gt;
Podłącz elektrody:&lt;br /&gt;
* lewa ręka, &lt;br /&gt;
* prawa ręka, &lt;br /&gt;
* lewa noga, &lt;br /&gt;
* uziemienie do prawej nogi.&lt;br /&gt;
&lt;br /&gt;
Zbierz 3 fragment sygnału EKG przy pomocy Svaroga. &lt;br /&gt;
&lt;br /&gt;
* Częstotliwość próbkowania 2048 Hz.&lt;br /&gt;
* Długość zapisu 300 s.&lt;br /&gt;
* Proszę zapisać sygnały w następujących warunkach:&lt;br /&gt;
** spoczynkowe&lt;br /&gt;
** po wysiłku fizycznym (odpiąć zatrzaskowe elektrody, przejść się po schodach i podłączyć ponownie )&lt;br /&gt;
** podczas obciążenia poznawczego, np. odejmując w pamięci kolejno 17 od 1000.&lt;br /&gt;
* zebrane sygnały zapisz na dysku classroom&lt;br /&gt;
&lt;br /&gt;
Zapoznaj się z zagadnieniem filtrowania dla sygnałów EKG:&lt;br /&gt;
* Proszę przejrzeć pracę: Shen Luo, Paul Johnston. A review of electrocardiogram filtering,  ''Journal of Electrocardiology'', 2010, Volume 43, Issue 6,  Pages 486-496 (https://www.sciencedirect.com/science/article/pii/S0022073610002852?via%3Dihub) &lt;br /&gt;
* popróbować uzyskać opisane tam filtry w SVAROGU i zaaplikować je do zebranych danych&lt;br /&gt;
&lt;br /&gt;
== Realizacja indywidualna w notebooku ==&lt;br /&gt;
===Ćwiczenie 2: Wstępna obróbka sygnału EKG ===&lt;br /&gt;
Napisz fragment notebooka, który:&lt;br /&gt;
* wczytuje sygnał przykład: [https://colab.research.google.com/drive/1QWfjnuf_LkdOnQzaBej0itD9yxWzlA6R?usp=sharing przykład]&lt;br /&gt;
* wykonuje stosowne filtracje (stosujemy filtrację z zerowym przesunięciem fazowym: filtfilt):  &lt;br /&gt;
** Filtr górnoprzepustowy:&lt;br /&gt;
*** z częstością odcięcia  0.67 Hz (przy tej częstości wymagamy 3dB tłumienia) &lt;br /&gt;
*** poniżej 0.5-dB tętnień w paśmie 1 - 30 Hz. &lt;br /&gt;
*** projekt z wykorzystaniem funkcji scipy.signal.iirfilter; trzeba dobrać rząd i sprawdzić charakterystyki funkcji transmitancji - dobrać zakres osi i dodać linie pomocnicze pionowe i poziome (matplotlib.pyplot.axvline i matplotlib.pyplot.axhline) tak aby było widać że zaprojektowany filtr spełnia powyższe kryteria.&lt;br /&gt;
** Filtr dolnoprzepustowy z częstością odcięcia 150Hz &lt;br /&gt;
*** wymagania te powinien spełnić np. filtr 2 rzędu, Butterwortha, - proszę sprawdzić charakterystyki).&lt;br /&gt;
** Filtr pasmowo-zaporowy (notch) dla 50 Hz iirnotch (scipy.signal.iirnotch())&lt;br /&gt;
* rysuje sygnał w odprowadzeniach Einthovena i Goldbergera,&lt;br /&gt;
* wybierz &amp;quot;czysty&amp;quot; fragment sygnału i zidentyfikuj poszczególne załamki. (można wykorzystać funkcję matplotlib.pyplot.axvspan)&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 3: Detekcja pików R ===&lt;br /&gt;
* Zaproponuj metodę rozpoznawania pików R w sygnale, &lt;br /&gt;
** wybierz do tego optymalny kanał&lt;br /&gt;
** rozważ zastosowanie filtra górnoprzepustowego o wyższej częstości odcięcia niż w ćwiczeniu 2&lt;br /&gt;
** skorzystaj z funkcji [https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks.html scipy.signal.find_peaks] - zaprezentuj dobór parametrów funkcji na podsdtawie histogramów odpowiednich parametrów, które zwraca ona w słowniku.&lt;br /&gt;
* Przedstaw fragment sygnału z zaznaczonymi pikami R dla różnych warunków rejestracji sygnału EKG. &lt;br /&gt;
&lt;br /&gt;
Przydatne pojęcie: (ang.) [https://pl.wikipedia.org/wiki/Minimalna_deniwelacja_wzgl%C4%99dna prominence - wybitność piku]&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 4: Tętno ===&lt;br /&gt;
Napisz program, który:&lt;br /&gt;
* wczyta plik z sygnałem i na jego podstawie &lt;br /&gt;
* wyznaczy i wykreśli tętno - liczbę uderzeń serca na minutę (ang. ''heart rate'').&lt;br /&gt;
* Oblicz średnie tętno i jego standardowe odchylenie.&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 5: HRV ===&lt;br /&gt;
HRV - heart rate variability. &lt;br /&gt;
* zapoznaj się z koncepcją [https://en.wikipedia.org/wiki/Heart_rate_variability#cite_note-29 HRV]&lt;br /&gt;
* Literatura [https://link.springer.com/article/10.1007/s11517-006-0119-0 Heart rate variability: a review]. &lt;br /&gt;
* napisz program, który przedstawiwa interwały R-R jako szereg czasowy&lt;br /&gt;
* wyestymuj widmo częstotliwościowe tego sygnału&lt;br /&gt;
** uwaga: próbki są pobierane w różnych odstępach! &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
** Możliwa do zastosowania technika to periodogram Lomb-Scarglea &lt;br /&gt;
*** https://link.springer.com/content/pdf/10.1007%2FBF00648343.pdf &lt;br /&gt;
*** implementacja: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.lombscargle.html#r0520a0371844-2&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
** można zinterpolować punkty na równomiernie próbkowanej siatce https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html#scipy.interpolate.interp1d i zastosować standardową funkcję do estymacji:&lt;br /&gt;
***  periodogramów&lt;br /&gt;
*** widma metodą AR&lt;br /&gt;
* porównaj widma HRV w poszczególnych warunkach eksperymentalnych; zwróć uwagę na proporcje mocy w pasmach wysokich częstości (HF: 0.15 do 0.4 Hz), niskich częśtości (LF: 0.04 do 0.15 Hz) i bardzo niskich częstości (VLF: 0.0033 do 0.04 Hz).&lt;br /&gt;
&lt;br /&gt;
==Literatura uzupełniająca==&lt;br /&gt;
&lt;br /&gt;
[http://www.bem.fi/book/19/19.htm#00 podstawowa diagnostyka EKG]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;!--;Ćwiczenie 8: Wykorzystując poniższe fragmenty kodu, stwórz program, który będzie wyrysowywał zmiany tętna w czasie rzeczywistym.&lt;br /&gt;
Pierwszy fragment kodu, to moduł buforujący sygnał, drugi to moduł pobierający dane z bufora. Należy dopisać do modułu pobierającego dane z bufora przetwarzanie ich (wyrysowywanie tętna) we wskazanym miejscu. &lt;br /&gt;
Uruchamianie całości będzie polegało na:&lt;br /&gt;
* uruchomieniu wzmacniacza&lt;br /&gt;
* uruchomieniu modułu &amp;lt;tt&amp;gt;signal_catcher.py&amp;lt;/tt&amp;gt;&lt;br /&gt;
* uruchomienie &amp;lt;tt&amp;gt;heartrate.py&amp;lt;/tt&amp;gt;, ktory jest dostepny [http://escher.fuw.edu.pl/~mm/zajecia/heartrate.py tu], po wstawieniu do niego w odpowiednie miejsce oznaczone w komentarzu własnego kodu obliczającego tętno.&lt;br /&gt;
* Trochę zmieniona wersja &amp;amp;mdash; [http://escher.fuw.edu.pl/~mm/zajecia/heartrate_new.py &amp;lt;tt&amp;gt;heartrate_new.py&amp;lt;/tt&amp;gt;] oraz  [http://escher.fuw.edu.pl/~mm/zajecia/signal_catcher_pracownia.py &amp;lt;tt&amp;gt;signal_catcher_pracownia.py&amp;lt;/tt&amp;gt;]&lt;br /&gt;
(moduły importują inne moduły, więc trzeba się upewnić że zmienna środowiskowa &amp;lt;tt&amp;gt;PYTHONPATH&amp;lt;/tt&amp;gt; ma odpowiednią wartość, w szczególności musi się w niej znaleźć ścieżka do &amp;lt;tt&amp;gt;azouk-libraries/build/&amp;lt;/tt&amp;gt; aby można było zaimportować moduł &amp;lt;tt&amp;gt;multiplexer&amp;lt;/tt&amp;gt;. Eksportować ścieżki można np tak:&lt;br /&gt;
&amp;lt;tt&amp;gt;export PYTHONPATH=./:openbci/:azouk-libraries/build/:PYTHONPATH&amp;lt;/tt&amp;gt;, tzn. dodajemy ścieżki oddzielone dwukropkiem, tylko należy się upewnić, że dodajemy odpowiednie ścieżki)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# signal_catcher.py&lt;br /&gt;
&lt;br /&gt;
import time&lt;br /&gt;
from multiplexer.multiplexer_constants import peers, types&lt;br /&gt;
from multiplexer.clients import BaseMultiplexerServer&lt;br /&gt;
import collections, variables_pb2&lt;br /&gt;
&lt;br /&gt;
class SignalCatcher(BaseMultiplexerServer):&lt;br /&gt;
    def __init__(self, addresses):&lt;br /&gt;
        super(SignalCatcher, self).__init__(addresses=addresses, type=peers.SIGNAL_CATCHER)&lt;br /&gt;
        self.number_of_channels = len(self.conn.query(message=&amp;quot;AmplifierChannelsToRecord&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message.split(&amp;amp;rdquo; &amp;amp;bdquo;))&lt;br /&gt;
        self.buffer = [collections.deque() for z in range(self.number_of_channels)]&lt;br /&gt;
        self.buffer_size = int(self.conn.query(message=&amp;quot;SignalCatcherBufferSize&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message)&lt;br /&gt;
&lt;br /&gt;
    def add(self, value):&lt;br /&gt;
        sampleVector = variables_pb2.SampleVector()&lt;br /&gt;
        sampleVector.ParseFromString(value)&lt;br /&gt;
&lt;br /&gt;
        i = 0&lt;br /&gt;
        for s in values:&lt;br /&gt;
            self.buffer[i].append(s)&lt;br /&gt;
            if len(self.buffer[i]) &amp;gt; self.buffer_size:&lt;br /&gt;
                self.buffer[i].popleft()&lt;br /&gt;
            i += 1&lt;br /&gt;
      &lt;br /&gt;
    def handle_message(self, mxmsg):&lt;br /&gt;
        if mxmsg.type == types.SIGNAL_CATCHER_REQUEST_MESSAGE:&lt;br /&gt;
            vector = variables_pb2.SampleVector()&lt;br /&gt;
            ind = int(mxmsg.message)&lt;br /&gt;
            &lt;br /&gt;
            for i in range(len(self.buffer[ind])):&lt;br /&gt;
                s = vector.samples.add()&lt;br /&gt;
                s.CopyFrom(self.buffer[ind][i])&lt;br /&gt;
            m = vector.SerializeToString()&lt;br /&gt;
            self.send_message(message = m, type = types.SIGNAL_CATCHER_RESPONSE_MESSAGE)&lt;br /&gt;
        elif mxmsg.type == types.AMPLIFIER_SIGNAL_MESSAGE:&lt;br /&gt;
            self.add(mxmsg.message)&lt;br /&gt;
            self.no_response()&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;amp;bdquo;__main__&amp;quot;:&lt;br /&gt;
    SignalCatcher(settings.MULTIPLEXER_ADDRESSES).loop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* próba obejrzenia zmiany tętna po wysiłku fizycznym, bądź w spoczynku--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11656</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 2 4</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11656"/>
		<updated>2026-03-11T08:55:20Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Ćwiczenie 3: Detekcja pików R */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EKG&lt;br /&gt;
&lt;br /&gt;
==Rejestracja i analiza sygnału EKG==&lt;br /&gt;
&lt;br /&gt;
Lektura:  [http://www.bem.fi/book/15/15.htm Electric and Magnetic Measurement of the Electric Activity of the Heart/12-Lead ECG System]&lt;br /&gt;
[[Plik:einthoven_ekg.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Aparat do rejestracji czynności elektrycznej serca skonstruowany przez W. Einthovena. Proszę zauważyć w jakich miejscach na ciele zbierana jest sygnał.]]&lt;br /&gt;
[[Plik:ekg_animacja.gif|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Rozchodzenie się sygnału stymulujacego pracę serca i związane z tym powstawanie sygnału EKG. Rysunek po brany ze strony Wikipedii.]]&lt;br /&gt;
[[Plik:ekg_opis.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Oznaczenia kolejnych składowych sygnału EKG.]]&lt;br /&gt;
[[Plik:wilson.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:wilson&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Umiejscowienie elektrod do pomiaru czynności elektrycznej serca z powierzchni klatki piersiowej, rysunek pobrany ze stron Wikipedii.]]&lt;br /&gt;
 &lt;br /&gt;
Mechanizm powstawania czynności elektrycznej serca został omówiony na zajęciach &amp;amp;bdquo;Sygnały Bioelektryczne&amp;quot;. W tym miejscu przypomnimy tylko kilka ważnych (i ciekawych) faktów.&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Czynność elektryczna serca znana jest od połowy XIX, jednakże za początek narodzin elektrokardiografii uznaje się rok 1903, kiedy to W. Einthoven dokonał pomiaru czynności elektrycznej serca z powierzchni ciała (&amp;lt;xr id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). Jako metoda diagnostyczna, elektrokardiografia zaczęła się szybko rozwijać po roku 1936, kiedy to do rejestracji czynności elektrycznej serca zastosowano wzmacniacz lampowy oraz system zapisu pomiaru na papierze.&lt;br /&gt;
&amp;lt;li&amp;gt; Serce posiada specjalny, wzbudzany samoczynnie układ, który generuje i przewodzi bodźce elektryczne. Następstwem działania tego układu jest rytmiczna praca serca o częstości od 70 do 180 cykli na minutę (częstość ta ulega zmianom pod wpływem czynników biochemicznych, powstałych np. w skutek stresu).&lt;br /&gt;
&amp;lt;li&amp;gt; Elektroda rejestrująca sygnał EKG zbiera czynność elektryczną wszystkich komórek serca, a zatem zarówno komórek wchodzących w skład układu generującego i przewodzącego impulsy elektryczne oraz kurczących się pod wpływem impulsów sterujących mięśni, które kurcząc się, również wytwarzają sygnał elektryczny. Jednakże, z uwagi na nieporównywalnie dużo większą masę mięśni serca w porównaniu z masą komórek układu stymulującego przyjmuje się, że głównym składnikiem sygnału EKG jest czynność elektryczna mięśnia sercowego.&lt;br /&gt;
&amp;lt;li&amp;gt; W przybliżeniu, sygnał stymulujący pracę serca rozchodzi się z jego prawej górnej części w kierunku dolnym i na lewą stronę. Na skutek pobudzania kolejnych partii mięśnia sercowego, powstaje charakterystyczny kształt sygnału EKG (&amp;lt;xr id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, &amp;lt;xr id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). &lt;br /&gt;
&amp;lt;li&amp;gt; Oznaczenia kolejnych składowych sygnału EKG:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; odchylenia od linii poziomej (izoelektrycznej) nazywamy załamkami,&lt;br /&gt;
&amp;lt;li&amp;gt; odległość w czasie pomiędzy końcem załamka P i początkiem załamka Q oraz końcem załamka S i początkiem załamka T nazywamy odcinkami &amp;amp;mdash; odpowiednio PQ i ST.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Elektrody pomiarowe połączone do aparatury rejestrujących nazywamy odprowadzeniami. Uwaga &amp;amp;mdash; przyjęto odprowadzeniami oznaczać także sygnały EKG będące liniowymi kombinacjami sygnałów zebranych przez elektrody.&lt;br /&gt;
&amp;lt;li&amp;gt; W konwencjonalnej elektroencefalografii stosuje się 12 tzw. odprowadzeń klasycznych:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Trzy odprowadzenia kończynowe biegunowe, zaproponowane jeszcze przez Einthoven i oznaczane rzymskimi cyframi I, II i III. Elektrody w tym systemie umieszcza się prawej (R) (ang. ''right'') i lewej (L) (ang. ''left'') kończynie górnej (najczęściej w okolicy nadgarstka, czasem ramieniu lub czy barku) oraz lewej nodze w okolicy stopy (F) (ang. ''foot''). Elektrodę umieszczaną na prawym nadgarstku oznacza się kolorem czerwonym, na lewym żółtym, na lewej kostce zielonym. Elektrodę masy umieszcza się zwykle na lewej kostce (choć teoretycznie można ją aplikować gdziekolwiek) i jest ona oznaczona kolorem czarnym. Odprowadzenia kończynowe mierzą różnicę napięć pomiędzy miejscami przyłożenia elektrod w następujący sposób:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
I   &amp;amp; = V_{L} - V_{R} \\&lt;br /&gt;
II  &amp;amp; = V_{F} - V_{R} \\&lt;br /&gt;
III &amp;amp; = V_{F} - V_{L}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
gdzie: &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;V_{R}, V_{L}, V_{F}&amp;lt;/math&amp;gt; to potencjały odpowiednio na prawym i lewym nadgarstku oraz stopie mierzone względem elektrody masy.&amp;lt;br/&amp;gt;&lt;br /&gt;
Jak łatwo zauważyć, tylko dwa spośród powyższych napięć są liniowo niezależne, co można zapisać w postaci związku:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_2&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;I + III = II&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
który nazywany jest prawem Einthovena. Proszę zauważyć, iż w tym przypadku wzmacniane jest sygnał będący różnicą napięć dwóch kolejnych elektrod, stąd też te odprowadzenia nazywamy dwubiegunowymi (bipolarnymi).&lt;br /&gt;
&amp;lt;li&amp;gt; Trzy odprowadzenia jednobiegunowe Goldberga. W odprowadzeniach tych sygnał w danym odprowadzeniu jest różnicą napięć pomiędzy elektrodą pomiarową a średnim napięciem na dwóch pozostałych elektrodach:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
aV_{R} &amp;amp; = V_{R} - \frac{V_{L}+V_{F}}{2} \\&lt;br /&gt;
aV_{L} &amp;amp; = V_{L} - \frac{V_{R}+V_{F}}{2} \\&lt;br /&gt;
aV_{F} &amp;amp; = V_{F} - \frac{V_{L}+V_{R}}{2}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Sześć odprowadzeń jednobiegunowych Wilsona. W przypadku warto zapoznać się z z historią tych odprowadzeń. Początkowo Wilson zaproponował układ jednobiegunowych doniesień dla kończyn w następujący sposób:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_4&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
V_{LW} &amp;amp; = V_{L} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{RW} &amp;amp; = V_{R} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{FW} &amp;amp; = V_{F} - \frac{V_{R}+V_{L}+ V_{F}}{3}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
Jak widzimy, jako elektrodę odniesienia wybrał on średnie napięcie rejestrowane przez elektrody. Niestety, sygnały prezentowane w tym systemie miały małą amplitudę, w związku z czym tego rodzaju odprowadzenia nie stosowano w praktyce. Z systemu zaproponowanego przez Wilsona wywodzi się jednak system odniesień Goldberga, który zauważył, że napięcie na trzeciej kończynie można zwiększyć o 50% jeśli do wyznaczenia napięcia odniesienia zastosuje się dwie, a nie trzy elektrody. Metoda wyznaczania potencjału odniesienia zaproponowana przez Wilsona znalazła jednak zastosowanie przy mierzeniu czynności elektrycznej serca mierzonej z powierzchni klatki piersiowej. W tym celu elektrody umieszcza się w pewnych ustalonych miejscach (&amp;lt;xr id=&amp;quot;fig:wilson&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, zaś odprowadzenia oznacza się symbolami &amp;lt;math&amp;gt;V_1, V_2, \dots, V_6&amp;lt;/math&amp;gt;. Odniesieniem w tym przypadku jest średni sygnał rejestrowany na kończynach górnych i lewej stopie. &lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ćwiczenia==&lt;br /&gt;
&lt;br /&gt;
Aby uruchomić zbieranie sygnału należy wykonać następujące operacje:&lt;br /&gt;
* przykleić elektrody do badanego;&lt;br /&gt;
* włożyć przewody do elektrod, a potem do wzmacniacza;&lt;br /&gt;
* podłączyć zasilanie wzmacniacza;&lt;br /&gt;
* podłączyć wzmacniacz do komputera (przejściówka optyczna i kabel USB);&lt;br /&gt;
* uruchomić program SVAROG&lt;br /&gt;
* otworzyć sygnał on-line ze wzmacniacza. &lt;br /&gt;
**  Po tym poleceniu wzmacniacz powinien wyświetlać napis &amp;amp;bdquo;Fiber&amp;amp;rdquo;; napis &amp;amp;bdquo;Connect&amp;amp;rdquo; oznacza, że połączenie wzmacniacza z komputerem nie udało się. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie 0: wstępne  ===&lt;br /&gt;
* Podaj związek pomiędzy sygnałami mierzonymi w systemie Goldbergera, a systemem Einthovena.&lt;br /&gt;
* Podaj analogiczny związek pomiędzy sygnałami w odniesieniach Goldberga co ''Prawo Einthovena''. &lt;br /&gt;
* Pokaż, że w systemie Goldbergera uzyskuje się sygnały o amplitudzie o 50% wyższej niż w pierwotnym systemie Wilsona.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Realizacja w grupie ==&lt;br /&gt;
=== Ćwiczenie 1: rejestracja sygnału === &lt;br /&gt;
&lt;br /&gt;
Podłącz elektrody:&lt;br /&gt;
* lewa ręka, &lt;br /&gt;
* prawa ręka, &lt;br /&gt;
* lewa noga, &lt;br /&gt;
* uziemienie do prawej nogi.&lt;br /&gt;
&lt;br /&gt;
Zbierz 3 fragment sygnału EKG przy pomocy Svaroga. &lt;br /&gt;
&lt;br /&gt;
* Częstotliwość próbkowania 2048 Hz.&lt;br /&gt;
* Długość zapisu 300 s.&lt;br /&gt;
* Proszę zapisać sygnały w następujących warunkach:&lt;br /&gt;
** spoczynkowe&lt;br /&gt;
** po wysiłku fizycznym (odpiąć zatrzaskowe elektrody, przejść się po schodach i podłączyć ponownie )&lt;br /&gt;
** podczas obciążenia poznawczego, np. odejmując w pamięci kolejno 17 od 1000.&lt;br /&gt;
* zebrane sygnały zapisz na dysku classroom&lt;br /&gt;
&lt;br /&gt;
Zapoznaj się z zagadnieniem filtrowania dla sygnałów EKG:&lt;br /&gt;
* Proszę przejrzeć pracę: Shen Luo, Paul Johnston. A review of electrocardiogram filtering,  ''Journal of Electrocardiology'', 2010, Volume 43, Issue 6,  Pages 486-496 (https://www.sciencedirect.com/science/article/pii/S0022073610002852?via%3Dihub) &lt;br /&gt;
* popróbować uzyskać opisane tam filtry w SVAROGU i zaaplikować je do zebranych danych&lt;br /&gt;
&lt;br /&gt;
== Realizacja indywidualna w notebooku ==&lt;br /&gt;
===Ćwiczenie 2: Wstępna obróbka sygnału EKG ===&lt;br /&gt;
Napisz fragment notebooka, który:&lt;br /&gt;
* wczytuje sygnał przykład: [https://colab.research.google.com/drive/1QWfjnuf_LkdOnQzaBej0itD9yxWzlA6R?usp=sharing przykład]&lt;br /&gt;
* wykonuje stosowne filtracje (stosujemy filtrację z zerowym przesunięciem fazowym: filtfilt):  &lt;br /&gt;
** Filtr górnoprzepustowy:&lt;br /&gt;
*** z częstością odcięcia  0.67 Hz (przy tej częstości wymagamy 3dB tłumienia) &lt;br /&gt;
*** poniżej 0.5-dB tętnień w paśmie 1 - 30 Hz. &lt;br /&gt;
*** projekt z wykorzystaniem funkcji scipy.signal.iirfilter; trzeba dobrać rząd i sprawdzić charakterystyki funkcji transmitancji - dobrać zakres osi i dodać linie pomocnicze pionowe i poziome (matplotlib.pyplot.axvline i matplotlib.pyplot.axhline) tak aby było widać że zaprojektowany filtr spełnia powyższe kryteria.&lt;br /&gt;
** Filtr dolnoprzepustowy z częstością odcięcia 150Hz &lt;br /&gt;
*** wymagania te powinien spełnić np. filtr 2 rzędu, Butterwortha, - proszę sprawdzić charakterystyki).&lt;br /&gt;
** Filtr pasmowo-zaporowy (notch) dla 50 Hz iirnotch (scipy.signal.iirnotch())&lt;br /&gt;
* rysuje sygnał w odprowadzeniach Einthovena i Goldbergera,&lt;br /&gt;
* wybierz &amp;quot;czysty&amp;quot; fragment sygnału i zidentyfikuj poszczególne załamki. (można wykorzystać funkcję matplotlib.pyplot.axvspan)&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 3: Detekcja pików R ===&lt;br /&gt;
* Zaproponuj metodę rozpoznawania pików R w sygnale, &lt;br /&gt;
** wybierz do tego optymalny kanał&lt;br /&gt;
** rozważ zastosowanie filtra górnoprzepustowego o wyższej częstości odcięcia niż w ćwiczeniu 2&lt;br /&gt;
** skorzystaj z funkcji `scipy.signal.find_peaks` - zaprezentuj dobór parametrów funkcji na podsdtawie histogramów odpowiednich parametrów, które zwraca ona w słowniku.&lt;br /&gt;
* Przedstaw fragment sygnału z zaznaczonymi pikami R dla różnych warunków rejestracji sygnału EKG. &lt;br /&gt;
&lt;br /&gt;
Przydatne pojęcie: (ang.) [https://pl.wikipedia.org/wiki/Minimalna_deniwelacja_wzgl%C4%99dna prominence - wybitność piku]&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 4: Tętno ===&lt;br /&gt;
Napisz program, który:&lt;br /&gt;
* wczyta plik z sygnałem i na jego podstawie &lt;br /&gt;
* wyznaczy i wykreśli tętno - liczbę uderzeń serca na minutę (ang. ''heart rate'').&lt;br /&gt;
* Oblicz średnie tętno i jego standardowe odchylenie.&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 5: HRV ===&lt;br /&gt;
HRV - heart rate variability. &lt;br /&gt;
* zapoznaj się z koncepcją [https://en.wikipedia.org/wiki/Heart_rate_variability#cite_note-29 HRV]&lt;br /&gt;
* Literatura [https://link.springer.com/article/10.1007/s11517-006-0119-0 Heart rate variability: a review]. &lt;br /&gt;
* napisz program, który przedstawiwa interwały R-R jako szereg czasowy&lt;br /&gt;
* wyestymuj widmo częstotliwościowe tego sygnału&lt;br /&gt;
** uwaga: próbki są pobierane w różnych odstępach! &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
** Możliwa do zastosowania technika to periodogram Lomb-Scarglea &lt;br /&gt;
*** https://link.springer.com/content/pdf/10.1007%2FBF00648343.pdf &lt;br /&gt;
*** implementacja: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.lombscargle.html#r0520a0371844-2&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
** można zinterpolować punkty na równomiernie próbkowanej siatce https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html#scipy.interpolate.interp1d i zastosować standardową funkcję do estymacji:&lt;br /&gt;
***  periodogramów&lt;br /&gt;
*** widma metodą AR&lt;br /&gt;
* porównaj widma HRV w poszczególnych warunkach eksperymentalnych; zwróć uwagę na proporcje mocy w pasmach wysokich częstości (HF: 0.15 do 0.4 Hz), niskich częśtości (LF: 0.04 do 0.15 Hz) i bardzo niskich częstości (VLF: 0.0033 do 0.04 Hz).&lt;br /&gt;
&lt;br /&gt;
==Literatura uzupełniająca==&lt;br /&gt;
&lt;br /&gt;
[http://www.bem.fi/book/19/19.htm#00 podstawowa diagnostyka EKG]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;!--;Ćwiczenie 8: Wykorzystując poniższe fragmenty kodu, stwórz program, który będzie wyrysowywał zmiany tętna w czasie rzeczywistym.&lt;br /&gt;
Pierwszy fragment kodu, to moduł buforujący sygnał, drugi to moduł pobierający dane z bufora. Należy dopisać do modułu pobierającego dane z bufora przetwarzanie ich (wyrysowywanie tętna) we wskazanym miejscu. &lt;br /&gt;
Uruchamianie całości będzie polegało na:&lt;br /&gt;
* uruchomieniu wzmacniacza&lt;br /&gt;
* uruchomieniu modułu &amp;lt;tt&amp;gt;signal_catcher.py&amp;lt;/tt&amp;gt;&lt;br /&gt;
* uruchomienie &amp;lt;tt&amp;gt;heartrate.py&amp;lt;/tt&amp;gt;, ktory jest dostepny [http://escher.fuw.edu.pl/~mm/zajecia/heartrate.py tu], po wstawieniu do niego w odpowiednie miejsce oznaczone w komentarzu własnego kodu obliczającego tętno.&lt;br /&gt;
* Trochę zmieniona wersja &amp;amp;mdash; [http://escher.fuw.edu.pl/~mm/zajecia/heartrate_new.py &amp;lt;tt&amp;gt;heartrate_new.py&amp;lt;/tt&amp;gt;] oraz  [http://escher.fuw.edu.pl/~mm/zajecia/signal_catcher_pracownia.py &amp;lt;tt&amp;gt;signal_catcher_pracownia.py&amp;lt;/tt&amp;gt;]&lt;br /&gt;
(moduły importują inne moduły, więc trzeba się upewnić że zmienna środowiskowa &amp;lt;tt&amp;gt;PYTHONPATH&amp;lt;/tt&amp;gt; ma odpowiednią wartość, w szczególności musi się w niej znaleźć ścieżka do &amp;lt;tt&amp;gt;azouk-libraries/build/&amp;lt;/tt&amp;gt; aby można było zaimportować moduł &amp;lt;tt&amp;gt;multiplexer&amp;lt;/tt&amp;gt;. Eksportować ścieżki można np tak:&lt;br /&gt;
&amp;lt;tt&amp;gt;export PYTHONPATH=./:openbci/:azouk-libraries/build/:PYTHONPATH&amp;lt;/tt&amp;gt;, tzn. dodajemy ścieżki oddzielone dwukropkiem, tylko należy się upewnić, że dodajemy odpowiednie ścieżki)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# signal_catcher.py&lt;br /&gt;
&lt;br /&gt;
import time&lt;br /&gt;
from multiplexer.multiplexer_constants import peers, types&lt;br /&gt;
from multiplexer.clients import BaseMultiplexerServer&lt;br /&gt;
import collections, variables_pb2&lt;br /&gt;
&lt;br /&gt;
class SignalCatcher(BaseMultiplexerServer):&lt;br /&gt;
    def __init__(self, addresses):&lt;br /&gt;
        super(SignalCatcher, self).__init__(addresses=addresses, type=peers.SIGNAL_CATCHER)&lt;br /&gt;
        self.number_of_channels = len(self.conn.query(message=&amp;quot;AmplifierChannelsToRecord&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message.split(&amp;amp;rdquo; &amp;amp;bdquo;))&lt;br /&gt;
        self.buffer = [collections.deque() for z in range(self.number_of_channels)]&lt;br /&gt;
        self.buffer_size = int(self.conn.query(message=&amp;quot;SignalCatcherBufferSize&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message)&lt;br /&gt;
&lt;br /&gt;
    def add(self, value):&lt;br /&gt;
        sampleVector = variables_pb2.SampleVector()&lt;br /&gt;
        sampleVector.ParseFromString(value)&lt;br /&gt;
&lt;br /&gt;
        i = 0&lt;br /&gt;
        for s in values:&lt;br /&gt;
            self.buffer[i].append(s)&lt;br /&gt;
            if len(self.buffer[i]) &amp;gt; self.buffer_size:&lt;br /&gt;
                self.buffer[i].popleft()&lt;br /&gt;
            i += 1&lt;br /&gt;
      &lt;br /&gt;
    def handle_message(self, mxmsg):&lt;br /&gt;
        if mxmsg.type == types.SIGNAL_CATCHER_REQUEST_MESSAGE:&lt;br /&gt;
            vector = variables_pb2.SampleVector()&lt;br /&gt;
            ind = int(mxmsg.message)&lt;br /&gt;
            &lt;br /&gt;
            for i in range(len(self.buffer[ind])):&lt;br /&gt;
                s = vector.samples.add()&lt;br /&gt;
                s.CopyFrom(self.buffer[ind][i])&lt;br /&gt;
            m = vector.SerializeToString()&lt;br /&gt;
            self.send_message(message = m, type = types.SIGNAL_CATCHER_RESPONSE_MESSAGE)&lt;br /&gt;
        elif mxmsg.type == types.AMPLIFIER_SIGNAL_MESSAGE:&lt;br /&gt;
            self.add(mxmsg.message)&lt;br /&gt;
            self.no_response()&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;amp;bdquo;__main__&amp;quot;:&lt;br /&gt;
    SignalCatcher(settings.MULTIPLEXER_ADDRESSES).loop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* próba obejrzenia zmiany tętna po wysiłku fizycznym, bądź w spoczynku--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11652</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 2 4</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11652"/>
		<updated>2026-03-06T07:39:02Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Ćwiczenie 2: Wstępna obróbka sygnału EKG */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EKG&lt;br /&gt;
&lt;br /&gt;
==Rejestracja i analiza sygnału EKG==&lt;br /&gt;
&lt;br /&gt;
Lektura:  [http://www.bem.fi/book/15/15.htm Electric and Magnetic Measurement of the Electric Activity of the Heart/12-Lead ECG System]&lt;br /&gt;
[[Plik:einthoven_ekg.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Aparat do rejestracji czynności elektrycznej serca skonstruowany przez W. Einthovena. Proszę zauważyć w jakich miejscach na ciele zbierana jest sygnał.]]&lt;br /&gt;
[[Plik:ekg_animacja.gif|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Rozchodzenie się sygnału stymulujacego pracę serca i związane z tym powstawanie sygnału EKG. Rysunek po brany ze strony Wikipedii.]]&lt;br /&gt;
[[Plik:ekg_opis.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Oznaczenia kolejnych składowych sygnału EKG.]]&lt;br /&gt;
[[Plik:wilson.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:wilson&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Umiejscowienie elektrod do pomiaru czynności elektrycznej serca z powierzchni klatki piersiowej, rysunek pobrany ze stron Wikipedii.]]&lt;br /&gt;
 &lt;br /&gt;
Mechanizm powstawania czynności elektrycznej serca został omówiony na zajęciach &amp;amp;bdquo;Sygnały Bioelektryczne&amp;quot;. W tym miejscu przypomnimy tylko kilka ważnych (i ciekawych) faktów.&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Czynność elektryczna serca znana jest od połowy XIX, jednakże za początek narodzin elektrokardiografii uznaje się rok 1903, kiedy to W. Einthoven dokonał pomiaru czynności elektrycznej serca z powierzchni ciała (&amp;lt;xr id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). Jako metoda diagnostyczna, elektrokardiografia zaczęła się szybko rozwijać po roku 1936, kiedy to do rejestracji czynności elektrycznej serca zastosowano wzmacniacz lampowy oraz system zapisu pomiaru na papierze.&lt;br /&gt;
&amp;lt;li&amp;gt; Serce posiada specjalny, wzbudzany samoczynnie układ, który generuje i przewodzi bodźce elektryczne. Następstwem działania tego układu jest rytmiczna praca serca o częstości od 70 do 180 cykli na minutę (częstość ta ulega zmianom pod wpływem czynników biochemicznych, powstałych np. w skutek stresu).&lt;br /&gt;
&amp;lt;li&amp;gt; Elektroda rejestrująca sygnał EKG zbiera czynność elektryczną wszystkich komórek serca, a zatem zarówno komórek wchodzących w skład układu generującego i przewodzącego impulsy elektryczne oraz kurczących się pod wpływem impulsów sterujących mięśni, które kurcząc się, również wytwarzają sygnał elektryczny. Jednakże, z uwagi na nieporównywalnie dużo większą masę mięśni serca w porównaniu z masą komórek układu stymulującego przyjmuje się, że głównym składnikiem sygnału EKG jest czynność elektryczna mięśnia sercowego.&lt;br /&gt;
&amp;lt;li&amp;gt; W przybliżeniu, sygnał stymulujący pracę serca rozchodzi się z jego prawej górnej części w kierunku dolnym i na lewą stronę. Na skutek pobudzania kolejnych partii mięśnia sercowego, powstaje charakterystyczny kształt sygnału EKG (&amp;lt;xr id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, &amp;lt;xr id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). &lt;br /&gt;
&amp;lt;li&amp;gt; Oznaczenia kolejnych składowych sygnału EKG:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; odchylenia od linii poziomej (izoelektrycznej) nazywamy załamkami,&lt;br /&gt;
&amp;lt;li&amp;gt; odległość w czasie pomiędzy końcem załamka P i początkiem załamka Q oraz końcem załamka S i początkiem załamka T nazywamy odcinkami &amp;amp;mdash; odpowiednio PQ i ST.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Elektrody pomiarowe połączone do aparatury rejestrujących nazywamy odprowadzeniami. Uwaga &amp;amp;mdash; przyjęto odprowadzeniami oznaczać także sygnały EKG będące liniowymi kombinacjami sygnałów zebranych przez elektrody.&lt;br /&gt;
&amp;lt;li&amp;gt; W konwencjonalnej elektroencefalografii stosuje się 12 tzw. odprowadzeń klasycznych:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Trzy odprowadzenia kończynowe biegunowe, zaproponowane jeszcze przez Einthoven i oznaczane rzymskimi cyframi I, II i III. Elektrody w tym systemie umieszcza się prawej (R) (ang. ''right'') i lewej (L) (ang. ''left'') kończynie górnej (najczęściej w okolicy nadgarstka, czasem ramieniu lub czy barku) oraz lewej nodze w okolicy stopy (F) (ang. ''foot''). Elektrodę umieszczaną na prawym nadgarstku oznacza się kolorem czerwonym, na lewym żółtym, na lewej kostce zielonym. Elektrodę masy umieszcza się zwykle na lewej kostce (choć teoretycznie można ją aplikować gdziekolwiek) i jest ona oznaczona kolorem czarnym. Odprowadzenia kończynowe mierzą różnicę napięć pomiędzy miejscami przyłożenia elektrod w następujący sposób:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
I   &amp;amp; = V_{L} - V_{R} \\&lt;br /&gt;
II  &amp;amp; = V_{F} - V_{R} \\&lt;br /&gt;
III &amp;amp; = V_{F} - V_{L}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
gdzie: &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;V_{R}, V_{L}, V_{F}&amp;lt;/math&amp;gt; to potencjały odpowiednio na prawym i lewym nadgarstku oraz stopie mierzone względem elektrody masy.&amp;lt;br/&amp;gt;&lt;br /&gt;
Jak łatwo zauważyć, tylko dwa spośród powyższych napięć są liniowo niezależne, co można zapisać w postaci związku:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_2&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;I + III = II&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
który nazywany jest prawem Einthovena. Proszę zauważyć, iż w tym przypadku wzmacniane jest sygnał będący różnicą napięć dwóch kolejnych elektrod, stąd też te odprowadzenia nazywamy dwubiegunowymi (bipolarnymi).&lt;br /&gt;
&amp;lt;li&amp;gt; Trzy odprowadzenia jednobiegunowe Goldberga. W odprowadzeniach tych sygnał w danym odprowadzeniu jest różnicą napięć pomiędzy elektrodą pomiarową a średnim napięciem na dwóch pozostałych elektrodach:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
aV_{R} &amp;amp; = V_{R} - \frac{V_{L}+V_{F}}{2} \\&lt;br /&gt;
aV_{L} &amp;amp; = V_{L} - \frac{V_{R}+V_{F}}{2} \\&lt;br /&gt;
aV_{F} &amp;amp; = V_{F} - \frac{V_{L}+V_{R}}{2}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Sześć odprowadzeń jednobiegunowych Wilsona. W przypadku warto zapoznać się z z historią tych odprowadzeń. Początkowo Wilson zaproponował układ jednobiegunowych doniesień dla kończyn w następujący sposób:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_4&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
V_{LW} &amp;amp; = V_{L} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{RW} &amp;amp; = V_{R} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{FW} &amp;amp; = V_{F} - \frac{V_{R}+V_{L}+ V_{F}}{3}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
Jak widzimy, jako elektrodę odniesienia wybrał on średnie napięcie rejestrowane przez elektrody. Niestety, sygnały prezentowane w tym systemie miały małą amplitudę, w związku z czym tego rodzaju odprowadzenia nie stosowano w praktyce. Z systemu zaproponowanego przez Wilsona wywodzi się jednak system odniesień Goldberga, który zauważył, że napięcie na trzeciej kończynie można zwiększyć o 50% jeśli do wyznaczenia napięcia odniesienia zastosuje się dwie, a nie trzy elektrody. Metoda wyznaczania potencjału odniesienia zaproponowana przez Wilsona znalazła jednak zastosowanie przy mierzeniu czynności elektrycznej serca mierzonej z powierzchni klatki piersiowej. W tym celu elektrody umieszcza się w pewnych ustalonych miejscach (&amp;lt;xr id=&amp;quot;fig:wilson&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, zaś odprowadzenia oznacza się symbolami &amp;lt;math&amp;gt;V_1, V_2, \dots, V_6&amp;lt;/math&amp;gt;. Odniesieniem w tym przypadku jest średni sygnał rejestrowany na kończynach górnych i lewej stopie. &lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ćwiczenia==&lt;br /&gt;
&lt;br /&gt;
Aby uruchomić zbieranie sygnału należy wykonać następujące operacje:&lt;br /&gt;
* przykleić elektrody do badanego;&lt;br /&gt;
* włożyć przewody do elektrod, a potem do wzmacniacza;&lt;br /&gt;
* podłączyć zasilanie wzmacniacza;&lt;br /&gt;
* podłączyć wzmacniacz do komputera (przejściówka optyczna i kabel USB);&lt;br /&gt;
* uruchomić program SVAROG&lt;br /&gt;
* otworzyć sygnał on-line ze wzmacniacza. &lt;br /&gt;
**  Po tym poleceniu wzmacniacz powinien wyświetlać napis &amp;amp;bdquo;Fiber&amp;amp;rdquo;; napis &amp;amp;bdquo;Connect&amp;amp;rdquo; oznacza, że połączenie wzmacniacza z komputerem nie udało się. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie 0: wstępne  ===&lt;br /&gt;
* Podaj związek pomiędzy sygnałami mierzonymi w systemie Goldbergera, a systemem Einthovena.&lt;br /&gt;
* Podaj analogiczny związek pomiędzy sygnałami w odniesieniach Goldberga co ''Prawo Einthovena''. &lt;br /&gt;
* Pokaż, że w systemie Goldbergera uzyskuje się sygnały o amplitudzie o 50% wyższej niż w pierwotnym systemie Wilsona.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Realizacja w grupie ==&lt;br /&gt;
=== Ćwiczenie 1: rejestracja sygnału === &lt;br /&gt;
&lt;br /&gt;
Podłącz elektrody:&lt;br /&gt;
* lewa ręka, &lt;br /&gt;
* prawa ręka, &lt;br /&gt;
* lewa noga, &lt;br /&gt;
* uziemienie do prawej nogi.&lt;br /&gt;
&lt;br /&gt;
Zbierz 3 fragment sygnału EKG przy pomocy Svaroga. &lt;br /&gt;
&lt;br /&gt;
* Częstotliwość próbkowania 2048 Hz.&lt;br /&gt;
* Długość zapisu 300 s.&lt;br /&gt;
* Proszę zapisać sygnały w następujących warunkach:&lt;br /&gt;
** spoczynkowe&lt;br /&gt;
** po wysiłku fizycznym (odpiąć zatrzaskowe elektrody, przejść się po schodach i podłączyć ponownie )&lt;br /&gt;
** podczas obciążenia poznawczego, np. odejmując w pamięci kolejno 17 od 1000.&lt;br /&gt;
* zebrane sygnały zapisz na dysku classroom&lt;br /&gt;
&lt;br /&gt;
Zapoznaj się z zagadnieniem filtrowania dla sygnałów EKG:&lt;br /&gt;
* Proszę przejrzeć pracę: Shen Luo, Paul Johnston. A review of electrocardiogram filtering,  ''Journal of Electrocardiology'', 2010, Volume 43, Issue 6,  Pages 486-496 (https://www.sciencedirect.com/science/article/pii/S0022073610002852?via%3Dihub) &lt;br /&gt;
* popróbować uzyskać opisane tam filtry w SVAROGU i zaaplikować je do zebranych danych&lt;br /&gt;
&lt;br /&gt;
== Realizacja indywidualna w notebooku ==&lt;br /&gt;
===Ćwiczenie 2: Wstępna obróbka sygnału EKG ===&lt;br /&gt;
Napisz fragment notebooka, który:&lt;br /&gt;
* wczytuje sygnał przykład: [https://colab.research.google.com/drive/1QWfjnuf_LkdOnQzaBej0itD9yxWzlA6R?usp=sharing przykład]&lt;br /&gt;
* wykonuje stosowne filtracje (stosujemy filtrację z zerowym przesunięciem fazowym: filtfilt):  &lt;br /&gt;
** Filtr górnoprzepustowy:&lt;br /&gt;
*** z częstością odcięcia  0.67 Hz (przy tej częstości wymagamy 3dB tłumienia) &lt;br /&gt;
*** poniżej 0.5-dB tętnień w paśmie 1 - 30 Hz. &lt;br /&gt;
*** projekt z wykorzystaniem funkcji scipy.signal.iirfilter; trzeba dobrać rząd i sprawdzić charakterystyki funkcji transmitancji - dobrać zakres osi i dodać linie pomocnicze pionowe i poziome (matplotlib.pyplot.axvline i matplotlib.pyplot.axhline) tak aby było widać że zaprojektowany filtr spełnia powyższe kryteria.&lt;br /&gt;
** Filtr dolnoprzepustowy z częstością odcięcia 150Hz &lt;br /&gt;
*** wymagania te powinien spełnić np. filtr 2 rzędu, Butterwortha, - proszę sprawdzić charakterystyki).&lt;br /&gt;
** Filtr pasmowo-zaporowy (notch) dla 50 Hz iirnotch (scipy.signal.iirnotch())&lt;br /&gt;
* rysuje sygnał w odprowadzeniach Einthovena i Goldbergera,&lt;br /&gt;
* wybierz &amp;quot;czysty&amp;quot; fragment sygnału i zidentyfikuj poszczególne załamki. (można wykorzystać funkcję matplotlib.pyplot.axvspan)&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 3: Detekcja pików R ===&lt;br /&gt;
* Zaproponuj metodę rozpoznawania pików R w sygnale, wybierz do tego optymalny kanał. Przedstaw fragment sygnału z zaznaczonymi pikami R. (można skorzystać z funkcji scipy.signal.find_peaks - dobór parametrów funkcji oprzyj na badaniu histogramów odpowiednich parametrów)&lt;br /&gt;
&lt;br /&gt;
Przydatne pojęcie: (ang.) [https://pl.wikipedia.org/wiki/Minimalna_deniwelacja_wzgl%C4%99dna prominence - wybitność piku]&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 4: Tętno ===&lt;br /&gt;
Napisz program, który:&lt;br /&gt;
* wczyta plik z sygnałem i na jego podstawie &lt;br /&gt;
* wyznaczy i wykreśli tętno - liczbę uderzeń serca na minutę (ang. ''heart rate'').&lt;br /&gt;
* Oblicz średnie tętno i jego standardowe odchylenie.&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 5: HRV ===&lt;br /&gt;
HRV - heart rate variability. &lt;br /&gt;
* zapoznaj się z koncepcją [https://en.wikipedia.org/wiki/Heart_rate_variability#cite_note-29 HRV]&lt;br /&gt;
* Literatura [https://link.springer.com/article/10.1007/s11517-006-0119-0 Heart rate variability: a review]. &lt;br /&gt;
* napisz program, który przedstawiwa interwały R-R jako szereg czasowy&lt;br /&gt;
* wyestymuj widmo częstotliwościowe tego sygnału&lt;br /&gt;
** uwaga: próbki są pobierane w różnych odstępach! &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
** Możliwa do zastosowania technika to periodogram Lomb-Scarglea &lt;br /&gt;
*** https://link.springer.com/content/pdf/10.1007%2FBF00648343.pdf &lt;br /&gt;
*** implementacja: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.lombscargle.html#r0520a0371844-2&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
** można zinterpolować punkty na równomiernie próbkowanej siatce https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html#scipy.interpolate.interp1d i zastosować standardową funkcję do estymacji:&lt;br /&gt;
***  periodogramów&lt;br /&gt;
*** widma metodą AR&lt;br /&gt;
* porównaj widma HRV w poszczególnych warunkach eksperymentalnych; zwróć uwagę na proporcje mocy w pasmach wysokich częstości (HF: 0.15 do 0.4 Hz), niskich częśtości (LF: 0.04 do 0.15 Hz) i bardzo niskich częstości (VLF: 0.0033 do 0.04 Hz).&lt;br /&gt;
&lt;br /&gt;
==Literatura uzupełniająca==&lt;br /&gt;
&lt;br /&gt;
[http://www.bem.fi/book/19/19.htm#00 podstawowa diagnostyka EKG]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;!--;Ćwiczenie 8: Wykorzystując poniższe fragmenty kodu, stwórz program, który będzie wyrysowywał zmiany tętna w czasie rzeczywistym.&lt;br /&gt;
Pierwszy fragment kodu, to moduł buforujący sygnał, drugi to moduł pobierający dane z bufora. Należy dopisać do modułu pobierającego dane z bufora przetwarzanie ich (wyrysowywanie tętna) we wskazanym miejscu. &lt;br /&gt;
Uruchamianie całości będzie polegało na:&lt;br /&gt;
* uruchomieniu wzmacniacza&lt;br /&gt;
* uruchomieniu modułu &amp;lt;tt&amp;gt;signal_catcher.py&amp;lt;/tt&amp;gt;&lt;br /&gt;
* uruchomienie &amp;lt;tt&amp;gt;heartrate.py&amp;lt;/tt&amp;gt;, ktory jest dostepny [http://escher.fuw.edu.pl/~mm/zajecia/heartrate.py tu], po wstawieniu do niego w odpowiednie miejsce oznaczone w komentarzu własnego kodu obliczającego tętno.&lt;br /&gt;
* Trochę zmieniona wersja &amp;amp;mdash; [http://escher.fuw.edu.pl/~mm/zajecia/heartrate_new.py &amp;lt;tt&amp;gt;heartrate_new.py&amp;lt;/tt&amp;gt;] oraz  [http://escher.fuw.edu.pl/~mm/zajecia/signal_catcher_pracownia.py &amp;lt;tt&amp;gt;signal_catcher_pracownia.py&amp;lt;/tt&amp;gt;]&lt;br /&gt;
(moduły importują inne moduły, więc trzeba się upewnić że zmienna środowiskowa &amp;lt;tt&amp;gt;PYTHONPATH&amp;lt;/tt&amp;gt; ma odpowiednią wartość, w szczególności musi się w niej znaleźć ścieżka do &amp;lt;tt&amp;gt;azouk-libraries/build/&amp;lt;/tt&amp;gt; aby można było zaimportować moduł &amp;lt;tt&amp;gt;multiplexer&amp;lt;/tt&amp;gt;. Eksportować ścieżki można np tak:&lt;br /&gt;
&amp;lt;tt&amp;gt;export PYTHONPATH=./:openbci/:azouk-libraries/build/:PYTHONPATH&amp;lt;/tt&amp;gt;, tzn. dodajemy ścieżki oddzielone dwukropkiem, tylko należy się upewnić, że dodajemy odpowiednie ścieżki)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# signal_catcher.py&lt;br /&gt;
&lt;br /&gt;
import time&lt;br /&gt;
from multiplexer.multiplexer_constants import peers, types&lt;br /&gt;
from multiplexer.clients import BaseMultiplexerServer&lt;br /&gt;
import collections, variables_pb2&lt;br /&gt;
&lt;br /&gt;
class SignalCatcher(BaseMultiplexerServer):&lt;br /&gt;
    def __init__(self, addresses):&lt;br /&gt;
        super(SignalCatcher, self).__init__(addresses=addresses, type=peers.SIGNAL_CATCHER)&lt;br /&gt;
        self.number_of_channels = len(self.conn.query(message=&amp;quot;AmplifierChannelsToRecord&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message.split(&amp;amp;rdquo; &amp;amp;bdquo;))&lt;br /&gt;
        self.buffer = [collections.deque() for z in range(self.number_of_channels)]&lt;br /&gt;
        self.buffer_size = int(self.conn.query(message=&amp;quot;SignalCatcherBufferSize&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message)&lt;br /&gt;
&lt;br /&gt;
    def add(self, value):&lt;br /&gt;
        sampleVector = variables_pb2.SampleVector()&lt;br /&gt;
        sampleVector.ParseFromString(value)&lt;br /&gt;
&lt;br /&gt;
        i = 0&lt;br /&gt;
        for s in values:&lt;br /&gt;
            self.buffer[i].append(s)&lt;br /&gt;
            if len(self.buffer[i]) &amp;gt; self.buffer_size:&lt;br /&gt;
                self.buffer[i].popleft()&lt;br /&gt;
            i += 1&lt;br /&gt;
      &lt;br /&gt;
    def handle_message(self, mxmsg):&lt;br /&gt;
        if mxmsg.type == types.SIGNAL_CATCHER_REQUEST_MESSAGE:&lt;br /&gt;
            vector = variables_pb2.SampleVector()&lt;br /&gt;
            ind = int(mxmsg.message)&lt;br /&gt;
            &lt;br /&gt;
            for i in range(len(self.buffer[ind])):&lt;br /&gt;
                s = vector.samples.add()&lt;br /&gt;
                s.CopyFrom(self.buffer[ind][i])&lt;br /&gt;
            m = vector.SerializeToString()&lt;br /&gt;
            self.send_message(message = m, type = types.SIGNAL_CATCHER_RESPONSE_MESSAGE)&lt;br /&gt;
        elif mxmsg.type == types.AMPLIFIER_SIGNAL_MESSAGE:&lt;br /&gt;
            self.add(mxmsg.message)&lt;br /&gt;
            self.no_response()&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;amp;bdquo;__main__&amp;quot;:&lt;br /&gt;
    SignalCatcher(settings.MULTIPLEXER_ADDRESSES).loop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* próba obejrzenia zmiany tętna po wysiłku fizycznym, bądź w spoczynku--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11651</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 2 4</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11651"/>
		<updated>2026-03-06T07:37:17Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Ćwiczenie 2: Wstępna obróbka sygnału EKG */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EKG&lt;br /&gt;
&lt;br /&gt;
==Rejestracja i analiza sygnału EKG==&lt;br /&gt;
&lt;br /&gt;
Lektura:  [http://www.bem.fi/book/15/15.htm Electric and Magnetic Measurement of the Electric Activity of the Heart/12-Lead ECG System]&lt;br /&gt;
[[Plik:einthoven_ekg.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Aparat do rejestracji czynności elektrycznej serca skonstruowany przez W. Einthovena. Proszę zauważyć w jakich miejscach na ciele zbierana jest sygnał.]]&lt;br /&gt;
[[Plik:ekg_animacja.gif|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Rozchodzenie się sygnału stymulujacego pracę serca i związane z tym powstawanie sygnału EKG. Rysunek po brany ze strony Wikipedii.]]&lt;br /&gt;
[[Plik:ekg_opis.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Oznaczenia kolejnych składowych sygnału EKG.]]&lt;br /&gt;
[[Plik:wilson.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:wilson&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Umiejscowienie elektrod do pomiaru czynności elektrycznej serca z powierzchni klatki piersiowej, rysunek pobrany ze stron Wikipedii.]]&lt;br /&gt;
 &lt;br /&gt;
Mechanizm powstawania czynności elektrycznej serca został omówiony na zajęciach &amp;amp;bdquo;Sygnały Bioelektryczne&amp;quot;. W tym miejscu przypomnimy tylko kilka ważnych (i ciekawych) faktów.&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Czynność elektryczna serca znana jest od połowy XIX, jednakże za początek narodzin elektrokardiografii uznaje się rok 1903, kiedy to W. Einthoven dokonał pomiaru czynności elektrycznej serca z powierzchni ciała (&amp;lt;xr id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). Jako metoda diagnostyczna, elektrokardiografia zaczęła się szybko rozwijać po roku 1936, kiedy to do rejestracji czynności elektrycznej serca zastosowano wzmacniacz lampowy oraz system zapisu pomiaru na papierze.&lt;br /&gt;
&amp;lt;li&amp;gt; Serce posiada specjalny, wzbudzany samoczynnie układ, który generuje i przewodzi bodźce elektryczne. Następstwem działania tego układu jest rytmiczna praca serca o częstości od 70 do 180 cykli na minutę (częstość ta ulega zmianom pod wpływem czynników biochemicznych, powstałych np. w skutek stresu).&lt;br /&gt;
&amp;lt;li&amp;gt; Elektroda rejestrująca sygnał EKG zbiera czynność elektryczną wszystkich komórek serca, a zatem zarówno komórek wchodzących w skład układu generującego i przewodzącego impulsy elektryczne oraz kurczących się pod wpływem impulsów sterujących mięśni, które kurcząc się, również wytwarzają sygnał elektryczny. Jednakże, z uwagi na nieporównywalnie dużo większą masę mięśni serca w porównaniu z masą komórek układu stymulującego przyjmuje się, że głównym składnikiem sygnału EKG jest czynność elektryczna mięśnia sercowego.&lt;br /&gt;
&amp;lt;li&amp;gt; W przybliżeniu, sygnał stymulujący pracę serca rozchodzi się z jego prawej górnej części w kierunku dolnym i na lewą stronę. Na skutek pobudzania kolejnych partii mięśnia sercowego, powstaje charakterystyczny kształt sygnału EKG (&amp;lt;xr id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, &amp;lt;xr id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). &lt;br /&gt;
&amp;lt;li&amp;gt; Oznaczenia kolejnych składowych sygnału EKG:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; odchylenia od linii poziomej (izoelektrycznej) nazywamy załamkami,&lt;br /&gt;
&amp;lt;li&amp;gt; odległość w czasie pomiędzy końcem załamka P i początkiem załamka Q oraz końcem załamka S i początkiem załamka T nazywamy odcinkami &amp;amp;mdash; odpowiednio PQ i ST.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Elektrody pomiarowe połączone do aparatury rejestrujących nazywamy odprowadzeniami. Uwaga &amp;amp;mdash; przyjęto odprowadzeniami oznaczać także sygnały EKG będące liniowymi kombinacjami sygnałów zebranych przez elektrody.&lt;br /&gt;
&amp;lt;li&amp;gt; W konwencjonalnej elektroencefalografii stosuje się 12 tzw. odprowadzeń klasycznych:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Trzy odprowadzenia kończynowe biegunowe, zaproponowane jeszcze przez Einthoven i oznaczane rzymskimi cyframi I, II i III. Elektrody w tym systemie umieszcza się prawej (R) (ang. ''right'') i lewej (L) (ang. ''left'') kończynie górnej (najczęściej w okolicy nadgarstka, czasem ramieniu lub czy barku) oraz lewej nodze w okolicy stopy (F) (ang. ''foot''). Elektrodę umieszczaną na prawym nadgarstku oznacza się kolorem czerwonym, na lewym żółtym, na lewej kostce zielonym. Elektrodę masy umieszcza się zwykle na lewej kostce (choć teoretycznie można ją aplikować gdziekolwiek) i jest ona oznaczona kolorem czarnym. Odprowadzenia kończynowe mierzą różnicę napięć pomiędzy miejscami przyłożenia elektrod w następujący sposób:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
I   &amp;amp; = V_{L} - V_{R} \\&lt;br /&gt;
II  &amp;amp; = V_{F} - V_{R} \\&lt;br /&gt;
III &amp;amp; = V_{F} - V_{L}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
gdzie: &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;V_{R}, V_{L}, V_{F}&amp;lt;/math&amp;gt; to potencjały odpowiednio na prawym i lewym nadgarstku oraz stopie mierzone względem elektrody masy.&amp;lt;br/&amp;gt;&lt;br /&gt;
Jak łatwo zauważyć, tylko dwa spośród powyższych napięć są liniowo niezależne, co można zapisać w postaci związku:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_2&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;I + III = II&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
który nazywany jest prawem Einthovena. Proszę zauważyć, iż w tym przypadku wzmacniane jest sygnał będący różnicą napięć dwóch kolejnych elektrod, stąd też te odprowadzenia nazywamy dwubiegunowymi (bipolarnymi).&lt;br /&gt;
&amp;lt;li&amp;gt; Trzy odprowadzenia jednobiegunowe Goldberga. W odprowadzeniach tych sygnał w danym odprowadzeniu jest różnicą napięć pomiędzy elektrodą pomiarową a średnim napięciem na dwóch pozostałych elektrodach:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
aV_{R} &amp;amp; = V_{R} - \frac{V_{L}+V_{F}}{2} \\&lt;br /&gt;
aV_{L} &amp;amp; = V_{L} - \frac{V_{R}+V_{F}}{2} \\&lt;br /&gt;
aV_{F} &amp;amp; = V_{F} - \frac{V_{L}+V_{R}}{2}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Sześć odprowadzeń jednobiegunowych Wilsona. W przypadku warto zapoznać się z z historią tych odprowadzeń. Początkowo Wilson zaproponował układ jednobiegunowych doniesień dla kończyn w następujący sposób:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_4&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
V_{LW} &amp;amp; = V_{L} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{RW} &amp;amp; = V_{R} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{FW} &amp;amp; = V_{F} - \frac{V_{R}+V_{L}+ V_{F}}{3}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
Jak widzimy, jako elektrodę odniesienia wybrał on średnie napięcie rejestrowane przez elektrody. Niestety, sygnały prezentowane w tym systemie miały małą amplitudę, w związku z czym tego rodzaju odprowadzenia nie stosowano w praktyce. Z systemu zaproponowanego przez Wilsona wywodzi się jednak system odniesień Goldberga, który zauważył, że napięcie na trzeciej kończynie można zwiększyć o 50% jeśli do wyznaczenia napięcia odniesienia zastosuje się dwie, a nie trzy elektrody. Metoda wyznaczania potencjału odniesienia zaproponowana przez Wilsona znalazła jednak zastosowanie przy mierzeniu czynności elektrycznej serca mierzonej z powierzchni klatki piersiowej. W tym celu elektrody umieszcza się w pewnych ustalonych miejscach (&amp;lt;xr id=&amp;quot;fig:wilson&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, zaś odprowadzenia oznacza się symbolami &amp;lt;math&amp;gt;V_1, V_2, \dots, V_6&amp;lt;/math&amp;gt;. Odniesieniem w tym przypadku jest średni sygnał rejestrowany na kończynach górnych i lewej stopie. &lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ćwiczenia==&lt;br /&gt;
&lt;br /&gt;
Aby uruchomić zbieranie sygnału należy wykonać następujące operacje:&lt;br /&gt;
* przykleić elektrody do badanego;&lt;br /&gt;
* włożyć przewody do elektrod, a potem do wzmacniacza;&lt;br /&gt;
* podłączyć zasilanie wzmacniacza;&lt;br /&gt;
* podłączyć wzmacniacz do komputera (przejściówka optyczna i kabel USB);&lt;br /&gt;
* uruchomić program SVAROG&lt;br /&gt;
* otworzyć sygnał on-line ze wzmacniacza. &lt;br /&gt;
**  Po tym poleceniu wzmacniacz powinien wyświetlać napis &amp;amp;bdquo;Fiber&amp;amp;rdquo;; napis &amp;amp;bdquo;Connect&amp;amp;rdquo; oznacza, że połączenie wzmacniacza z komputerem nie udało się. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie 0: wstępne  ===&lt;br /&gt;
* Podaj związek pomiędzy sygnałami mierzonymi w systemie Goldbergera, a systemem Einthovena.&lt;br /&gt;
* Podaj analogiczny związek pomiędzy sygnałami w odniesieniach Goldberga co ''Prawo Einthovena''. &lt;br /&gt;
* Pokaż, że w systemie Goldbergera uzyskuje się sygnały o amplitudzie o 50% wyższej niż w pierwotnym systemie Wilsona.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Realizacja w grupie ==&lt;br /&gt;
=== Ćwiczenie 1: rejestracja sygnału === &lt;br /&gt;
&lt;br /&gt;
Podłącz elektrody:&lt;br /&gt;
* lewa ręka, &lt;br /&gt;
* prawa ręka, &lt;br /&gt;
* lewa noga, &lt;br /&gt;
* uziemienie do prawej nogi.&lt;br /&gt;
&lt;br /&gt;
Zbierz 3 fragment sygnału EKG przy pomocy Svaroga. &lt;br /&gt;
&lt;br /&gt;
* Częstotliwość próbkowania 2048 Hz.&lt;br /&gt;
* Długość zapisu 300 s.&lt;br /&gt;
* Proszę zapisać sygnały w następujących warunkach:&lt;br /&gt;
** spoczynkowe&lt;br /&gt;
** po wysiłku fizycznym (odpiąć zatrzaskowe elektrody, przejść się po schodach i podłączyć ponownie )&lt;br /&gt;
** podczas obciążenia poznawczego, np. odejmując w pamięci kolejno 17 od 1000.&lt;br /&gt;
* zebrane sygnały zapisz na dysku classroom&lt;br /&gt;
&lt;br /&gt;
Zapoznaj się z zagadnieniem filtrowania dla sygnałów EKG:&lt;br /&gt;
* Proszę przejrzeć pracę: Shen Luo, Paul Johnston. A review of electrocardiogram filtering,  ''Journal of Electrocardiology'', 2010, Volume 43, Issue 6,  Pages 486-496 (https://www.sciencedirect.com/science/article/pii/S0022073610002852?via%3Dihub) &lt;br /&gt;
* popróbować uzyskać opisane tam filtry w SVAROGU i zaaplikować je do zebranych danych&lt;br /&gt;
&lt;br /&gt;
== Realizacja indywidualna w notebooku ==&lt;br /&gt;
===Ćwiczenie 2: Wstępna obróbka sygnału EKG ===&lt;br /&gt;
Napisz fragment notebooka, który:&lt;br /&gt;
* wczytuje sygnał&lt;br /&gt;
* wykonuje stosowne filtracje (stosujemy filtrację z zerowym przesunięciem fazowym: filtfilt):  &lt;br /&gt;
** Filtr górnoprzepustowy:&lt;br /&gt;
*** z częstością odcięcia  0.67 Hz (przy tej częstości wymagamy 3dB tłumienia) &lt;br /&gt;
*** poniżej 0.5-dB tętnień w paśmie 1 - 30 Hz. &lt;br /&gt;
*** projekt z wykorzystaniem funkcji scipy.signal.iirfilter; trzeba dobrać rząd i sprawdzić charakterystyki funkcji transmitancji - dobrać zakres osi i dodać linie pomocnicze pionowe i poziome (matplotlib.pyplot.axvline i matplotlib.pyplot.axhline) tak aby było widać że zaprojektowany filtr spełnia powyższe kryteria.&lt;br /&gt;
** Filtr dolnoprzepustowy z częstością odcięcia 150Hz &lt;br /&gt;
*** wymagania te powinien spełnić np. filtr 2 rzędu, Butterwortha, - proszę sprawdzić charakterystyki).&lt;br /&gt;
** Filtr pasmowo-zaporowy (notch) dla 50 Hz iirnotch (scipy.signal.iirnotch())&lt;br /&gt;
* rysuje sygnał w odprowadzeniach Einthovena i Goldbergera,&lt;br /&gt;
* wybierz &amp;quot;czysty&amp;quot; fragment sygnału i zidentyfikuj poszczególne załamki. (można wykorzystać funkcję matplotlib.pyplot.axvspan)&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 3: Detekcja pików R ===&lt;br /&gt;
* Zaproponuj metodę rozpoznawania pików R w sygnale, wybierz do tego optymalny kanał. Przedstaw fragment sygnału z zaznaczonymi pikami R. (można skorzystać z funkcji scipy.signal.find_peaks - dobór parametrów funkcji oprzyj na badaniu histogramów odpowiednich parametrów)&lt;br /&gt;
&lt;br /&gt;
Przydatne pojęcie: (ang.) [https://pl.wikipedia.org/wiki/Minimalna_deniwelacja_wzgl%C4%99dna prominence - wybitność piku]&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 4: Tętno ===&lt;br /&gt;
Napisz program, który:&lt;br /&gt;
* wczyta plik z sygnałem i na jego podstawie &lt;br /&gt;
* wyznaczy i wykreśli tętno - liczbę uderzeń serca na minutę (ang. ''heart rate'').&lt;br /&gt;
* Oblicz średnie tętno i jego standardowe odchylenie.&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 5: HRV ===&lt;br /&gt;
HRV - heart rate variability. &lt;br /&gt;
* zapoznaj się z koncepcją [https://en.wikipedia.org/wiki/Heart_rate_variability#cite_note-29 HRV]&lt;br /&gt;
* Literatura [https://link.springer.com/article/10.1007/s11517-006-0119-0 Heart rate variability: a review]. &lt;br /&gt;
* napisz program, który przedstawiwa interwały R-R jako szereg czasowy&lt;br /&gt;
* wyestymuj widmo częstotliwościowe tego sygnału&lt;br /&gt;
** uwaga: próbki są pobierane w różnych odstępach! &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
** Możliwa do zastosowania technika to periodogram Lomb-Scarglea &lt;br /&gt;
*** https://link.springer.com/content/pdf/10.1007%2FBF00648343.pdf &lt;br /&gt;
*** implementacja: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.lombscargle.html#r0520a0371844-2&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
** można zinterpolować punkty na równomiernie próbkowanej siatce https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html#scipy.interpolate.interp1d i zastosować standardową funkcję do estymacji:&lt;br /&gt;
***  periodogramów&lt;br /&gt;
*** widma metodą AR&lt;br /&gt;
* porównaj widma HRV w poszczególnych warunkach eksperymentalnych; zwróć uwagę na proporcje mocy w pasmach wysokich częstości (HF: 0.15 do 0.4 Hz), niskich częśtości (LF: 0.04 do 0.15 Hz) i bardzo niskich częstości (VLF: 0.0033 do 0.04 Hz).&lt;br /&gt;
&lt;br /&gt;
==Literatura uzupełniająca==&lt;br /&gt;
&lt;br /&gt;
[http://www.bem.fi/book/19/19.htm#00 podstawowa diagnostyka EKG]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;!--;Ćwiczenie 8: Wykorzystując poniższe fragmenty kodu, stwórz program, który będzie wyrysowywał zmiany tętna w czasie rzeczywistym.&lt;br /&gt;
Pierwszy fragment kodu, to moduł buforujący sygnał, drugi to moduł pobierający dane z bufora. Należy dopisać do modułu pobierającego dane z bufora przetwarzanie ich (wyrysowywanie tętna) we wskazanym miejscu. &lt;br /&gt;
Uruchamianie całości będzie polegało na:&lt;br /&gt;
* uruchomieniu wzmacniacza&lt;br /&gt;
* uruchomieniu modułu &amp;lt;tt&amp;gt;signal_catcher.py&amp;lt;/tt&amp;gt;&lt;br /&gt;
* uruchomienie &amp;lt;tt&amp;gt;heartrate.py&amp;lt;/tt&amp;gt;, ktory jest dostepny [http://escher.fuw.edu.pl/~mm/zajecia/heartrate.py tu], po wstawieniu do niego w odpowiednie miejsce oznaczone w komentarzu własnego kodu obliczającego tętno.&lt;br /&gt;
* Trochę zmieniona wersja &amp;amp;mdash; [http://escher.fuw.edu.pl/~mm/zajecia/heartrate_new.py &amp;lt;tt&amp;gt;heartrate_new.py&amp;lt;/tt&amp;gt;] oraz  [http://escher.fuw.edu.pl/~mm/zajecia/signal_catcher_pracownia.py &amp;lt;tt&amp;gt;signal_catcher_pracownia.py&amp;lt;/tt&amp;gt;]&lt;br /&gt;
(moduły importują inne moduły, więc trzeba się upewnić że zmienna środowiskowa &amp;lt;tt&amp;gt;PYTHONPATH&amp;lt;/tt&amp;gt; ma odpowiednią wartość, w szczególności musi się w niej znaleźć ścieżka do &amp;lt;tt&amp;gt;azouk-libraries/build/&amp;lt;/tt&amp;gt; aby można było zaimportować moduł &amp;lt;tt&amp;gt;multiplexer&amp;lt;/tt&amp;gt;. Eksportować ścieżki można np tak:&lt;br /&gt;
&amp;lt;tt&amp;gt;export PYTHONPATH=./:openbci/:azouk-libraries/build/:PYTHONPATH&amp;lt;/tt&amp;gt;, tzn. dodajemy ścieżki oddzielone dwukropkiem, tylko należy się upewnić, że dodajemy odpowiednie ścieżki)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# signal_catcher.py&lt;br /&gt;
&lt;br /&gt;
import time&lt;br /&gt;
from multiplexer.multiplexer_constants import peers, types&lt;br /&gt;
from multiplexer.clients import BaseMultiplexerServer&lt;br /&gt;
import collections, variables_pb2&lt;br /&gt;
&lt;br /&gt;
class SignalCatcher(BaseMultiplexerServer):&lt;br /&gt;
    def __init__(self, addresses):&lt;br /&gt;
        super(SignalCatcher, self).__init__(addresses=addresses, type=peers.SIGNAL_CATCHER)&lt;br /&gt;
        self.number_of_channels = len(self.conn.query(message=&amp;quot;AmplifierChannelsToRecord&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message.split(&amp;amp;rdquo; &amp;amp;bdquo;))&lt;br /&gt;
        self.buffer = [collections.deque() for z in range(self.number_of_channels)]&lt;br /&gt;
        self.buffer_size = int(self.conn.query(message=&amp;quot;SignalCatcherBufferSize&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message)&lt;br /&gt;
&lt;br /&gt;
    def add(self, value):&lt;br /&gt;
        sampleVector = variables_pb2.SampleVector()&lt;br /&gt;
        sampleVector.ParseFromString(value)&lt;br /&gt;
&lt;br /&gt;
        i = 0&lt;br /&gt;
        for s in values:&lt;br /&gt;
            self.buffer[i].append(s)&lt;br /&gt;
            if len(self.buffer[i]) &amp;gt; self.buffer_size:&lt;br /&gt;
                self.buffer[i].popleft()&lt;br /&gt;
            i += 1&lt;br /&gt;
      &lt;br /&gt;
    def handle_message(self, mxmsg):&lt;br /&gt;
        if mxmsg.type == types.SIGNAL_CATCHER_REQUEST_MESSAGE:&lt;br /&gt;
            vector = variables_pb2.SampleVector()&lt;br /&gt;
            ind = int(mxmsg.message)&lt;br /&gt;
            &lt;br /&gt;
            for i in range(len(self.buffer[ind])):&lt;br /&gt;
                s = vector.samples.add()&lt;br /&gt;
                s.CopyFrom(self.buffer[ind][i])&lt;br /&gt;
            m = vector.SerializeToString()&lt;br /&gt;
            self.send_message(message = m, type = types.SIGNAL_CATCHER_RESPONSE_MESSAGE)&lt;br /&gt;
        elif mxmsg.type == types.AMPLIFIER_SIGNAL_MESSAGE:&lt;br /&gt;
            self.add(mxmsg.message)&lt;br /&gt;
            self.no_response()&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;amp;bdquo;__main__&amp;quot;:&lt;br /&gt;
    SignalCatcher(settings.MULTIPLEXER_ADDRESSES).loop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* próba obejrzenia zmiany tętna po wysiłku fizycznym, bądź w spoczynku--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11635</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 2 4</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11635"/>
		<updated>2026-03-04T08:31:44Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Ćwiczenie 2: Wstępna obróbka sygnału EKG */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EKG&lt;br /&gt;
&lt;br /&gt;
==Rejestracja i analiza sygnału EKG==&lt;br /&gt;
&lt;br /&gt;
Lektura:  [http://www.bem.fi/book/15/15.htm Electric and Magnetic Measurement of the Electric Activity of the Heart/12-Lead ECG System]&lt;br /&gt;
[[Plik:einthoven_ekg.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Aparat do rejestracji czynności elektrycznej serca skonstruowany przez W. Einthovena. Proszę zauważyć w jakich miejscach na ciele zbierana jest sygnał.]]&lt;br /&gt;
[[Plik:ekg_animacja.gif|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Rozchodzenie się sygnału stymulujacego pracę serca i związane z tym powstawanie sygnału EKG. Rysunek po brany ze strony Wikipedii.]]&lt;br /&gt;
[[Plik:ekg_opis.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Oznaczenia kolejnych składowych sygnału EKG.]]&lt;br /&gt;
[[Plik:wilson.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:wilson&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Umiejscowienie elektrod do pomiaru czynności elektrycznej serca z powierzchni klatki piersiowej, rysunek pobrany ze stron Wikipedii.]]&lt;br /&gt;
 &lt;br /&gt;
Mechanizm powstawania czynności elektrycznej serca został omówiony na zajęciach &amp;amp;bdquo;Sygnały Bioelektryczne&amp;quot;. W tym miejscu przypomnimy tylko kilka ważnych (i ciekawych) faktów.&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Czynność elektryczna serca znana jest od połowy XIX, jednakże za początek narodzin elektrokardiografii uznaje się rok 1903, kiedy to W. Einthoven dokonał pomiaru czynności elektrycznej serca z powierzchni ciała (&amp;lt;xr id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). Jako metoda diagnostyczna, elektrokardiografia zaczęła się szybko rozwijać po roku 1936, kiedy to do rejestracji czynności elektrycznej serca zastosowano wzmacniacz lampowy oraz system zapisu pomiaru na papierze.&lt;br /&gt;
&amp;lt;li&amp;gt; Serce posiada specjalny, wzbudzany samoczynnie układ, który generuje i przewodzi bodźce elektryczne. Następstwem działania tego układu jest rytmiczna praca serca o częstości od 70 do 180 cykli na minutę (częstość ta ulega zmianom pod wpływem czynników biochemicznych, powstałych np. w skutek stresu).&lt;br /&gt;
&amp;lt;li&amp;gt; Elektroda rejestrująca sygnał EKG zbiera czynność elektryczną wszystkich komórek serca, a zatem zarówno komórek wchodzących w skład układu generującego i przewodzącego impulsy elektryczne oraz kurczących się pod wpływem impulsów sterujących mięśni, które kurcząc się, również wytwarzają sygnał elektryczny. Jednakże, z uwagi na nieporównywalnie dużo większą masę mięśni serca w porównaniu z masą komórek układu stymulującego przyjmuje się, że głównym składnikiem sygnału EKG jest czynność elektryczna mięśnia sercowego.&lt;br /&gt;
&amp;lt;li&amp;gt; W przybliżeniu, sygnał stymulujący pracę serca rozchodzi się z jego prawej górnej części w kierunku dolnym i na lewą stronę. Na skutek pobudzania kolejnych partii mięśnia sercowego, powstaje charakterystyczny kształt sygnału EKG (&amp;lt;xr id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, &amp;lt;xr id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). &lt;br /&gt;
&amp;lt;li&amp;gt; Oznaczenia kolejnych składowych sygnału EKG:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; odchylenia od linii poziomej (izoelektrycznej) nazywamy załamkami,&lt;br /&gt;
&amp;lt;li&amp;gt; odległość w czasie pomiędzy końcem załamka P i początkiem załamka Q oraz końcem załamka S i początkiem załamka T nazywamy odcinkami &amp;amp;mdash; odpowiednio PQ i ST.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Elektrody pomiarowe połączone do aparatury rejestrujących nazywamy odprowadzeniami. Uwaga &amp;amp;mdash; przyjęto odprowadzeniami oznaczać także sygnały EKG będące liniowymi kombinacjami sygnałów zebranych przez elektrody.&lt;br /&gt;
&amp;lt;li&amp;gt; W konwencjonalnej elektroencefalografii stosuje się 12 tzw. odprowadzeń klasycznych:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Trzy odprowadzenia kończynowe biegunowe, zaproponowane jeszcze przez Einthoven i oznaczane rzymskimi cyframi I, II i III. Elektrody w tym systemie umieszcza się prawej (R) (ang. ''right'') i lewej (L) (ang. ''left'') kończynie górnej (najczęściej w okolicy nadgarstka, czasem ramieniu lub czy barku) oraz lewej nodze w okolicy stopy (F) (ang. ''foot''). Elektrodę umieszczaną na prawym nadgarstku oznacza się kolorem czerwonym, na lewym żółtym, na lewej kostce zielonym. Elektrodę masy umieszcza się zwykle na lewej kostce (choć teoretycznie można ją aplikować gdziekolwiek) i jest ona oznaczona kolorem czarnym. Odprowadzenia kończynowe mierzą różnicę napięć pomiędzy miejscami przyłożenia elektrod w następujący sposób:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
I   &amp;amp; = V_{L} - V_{R} \\&lt;br /&gt;
II  &amp;amp; = V_{F} - V_{R} \\&lt;br /&gt;
III &amp;amp; = V_{F} - V_{L}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
gdzie: &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;V_{R}, V_{L}, V_{F}&amp;lt;/math&amp;gt; to potencjały odpowiednio na prawym i lewym nadgarstku oraz stopie mierzone względem elektrody masy.&amp;lt;br/&amp;gt;&lt;br /&gt;
Jak łatwo zauważyć, tylko dwa spośród powyższych napięć są liniowo niezależne, co można zapisać w postaci związku:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_2&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;I + III = II&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
który nazywany jest prawem Einthovena. Proszę zauważyć, iż w tym przypadku wzmacniane jest sygnał będący różnicą napięć dwóch kolejnych elektrod, stąd też te odprowadzenia nazywamy dwubiegunowymi (bipolarnymi).&lt;br /&gt;
&amp;lt;li&amp;gt; Trzy odprowadzenia jednobiegunowe Goldberga. W odprowadzeniach tych sygnał w danym odprowadzeniu jest różnicą napięć pomiędzy elektrodą pomiarową a średnim napięciem na dwóch pozostałych elektrodach:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
aV_{R} &amp;amp; = V_{R} - \frac{V_{L}+V_{F}}{2} \\&lt;br /&gt;
aV_{L} &amp;amp; = V_{L} - \frac{V_{R}+V_{F}}{2} \\&lt;br /&gt;
aV_{F} &amp;amp; = V_{F} - \frac{V_{L}+V_{R}}{2}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Sześć odprowadzeń jednobiegunowych Wilsona. W przypadku warto zapoznać się z z historią tych odprowadzeń. Początkowo Wilson zaproponował układ jednobiegunowych doniesień dla kończyn w następujący sposób:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_4&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
V_{LW} &amp;amp; = V_{L} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{RW} &amp;amp; = V_{R} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{FW} &amp;amp; = V_{F} - \frac{V_{R}+V_{L}+ V_{F}}{3}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
Jak widzimy, jako elektrodę odniesienia wybrał on średnie napięcie rejestrowane przez elektrody. Niestety, sygnały prezentowane w tym systemie miały małą amplitudę, w związku z czym tego rodzaju odprowadzenia nie stosowano w praktyce. Z systemu zaproponowanego przez Wilsona wywodzi się jednak system odniesień Goldberga, który zauważył, że napięcie na trzeciej kończynie można zwiększyć o 50% jeśli do wyznaczenia napięcia odniesienia zastosuje się dwie, a nie trzy elektrody. Metoda wyznaczania potencjału odniesienia zaproponowana przez Wilsona znalazła jednak zastosowanie przy mierzeniu czynności elektrycznej serca mierzonej z powierzchni klatki piersiowej. W tym celu elektrody umieszcza się w pewnych ustalonych miejscach (&amp;lt;xr id=&amp;quot;fig:wilson&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, zaś odprowadzenia oznacza się symbolami &amp;lt;math&amp;gt;V_1, V_2, \dots, V_6&amp;lt;/math&amp;gt;. Odniesieniem w tym przypadku jest średni sygnał rejestrowany na kończynach górnych i lewej stopie. &lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ćwiczenia==&lt;br /&gt;
&lt;br /&gt;
Aby uruchomić zbieranie sygnału należy wykonać następujące operacje:&lt;br /&gt;
* przykleić elektrody do badanego;&lt;br /&gt;
* włożyć przewody do elektrod, a potem do wzmacniacza;&lt;br /&gt;
* podłączyć zasilanie wzmacniacza;&lt;br /&gt;
* podłączyć wzmacniacz do komputera (przejściówka optyczna i kabel USB);&lt;br /&gt;
* uruchomić program SVAROG&lt;br /&gt;
* otworzyć sygnał on-line ze wzmacniacza. &lt;br /&gt;
**  Po tym poleceniu wzmacniacz powinien wyświetlać napis &amp;amp;bdquo;Fiber&amp;amp;rdquo;; napis &amp;amp;bdquo;Connect&amp;amp;rdquo; oznacza, że połączenie wzmacniacza z komputerem nie udało się. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie 0: wstępne  ===&lt;br /&gt;
* Podaj związek pomiędzy sygnałami mierzonymi w systemie Goldbergera, a systemem Einthovena.&lt;br /&gt;
* Podaj analogiczny związek pomiędzy sygnałami w odniesieniach Goldberga co ''Prawo Einthovena''. &lt;br /&gt;
* Pokaż, że w systemie Goldbergera uzyskuje się sygnały o amplitudzie o 50% wyższej niż w pierwotnym systemie Wilsona.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Realizacja w grupie ==&lt;br /&gt;
=== Ćwiczenie 1: rejestracja sygnału === &lt;br /&gt;
&lt;br /&gt;
Podłącz elektrody:&lt;br /&gt;
* lewa ręka, &lt;br /&gt;
* prawa ręka, &lt;br /&gt;
* lewa noga, &lt;br /&gt;
* uziemienie do prawej nogi.&lt;br /&gt;
&lt;br /&gt;
Zbierz 3 fragment sygnału EKG przy pomocy Svaroga. &lt;br /&gt;
&lt;br /&gt;
* Częstotliwość próbkowania 2048 Hz.&lt;br /&gt;
* Długość zapisu 300 s.&lt;br /&gt;
* Proszę zapisać sygnały w następujących warunkach:&lt;br /&gt;
** spoczynkowe&lt;br /&gt;
** po wysiłku fizycznym (odpiąć zatrzaskowe elektrody, przejść się po schodach i podłączyć ponownie )&lt;br /&gt;
** podczas obciążenia poznawczego, np. odejmując w pamięci kolejno 17 od 1000.&lt;br /&gt;
* zebrane sygnały zapisz na dysku classroom&lt;br /&gt;
&lt;br /&gt;
Zapoznaj się z zagadnieniem filtrowania dla sygnałów EKG:&lt;br /&gt;
* Proszę przejrzeć pracę: Shen Luo, Paul Johnston. A review of electrocardiogram filtering,  ''Journal of Electrocardiology'', 2010, Volume 43, Issue 6,  Pages 486-496 (https://www.sciencedirect.com/science/article/pii/S0022073610002852?via%3Dihub) &lt;br /&gt;
* popróbować uzyskać opisane tam filtry w SVAROGU i zaaplikować je do zebranych danych&lt;br /&gt;
&lt;br /&gt;
== Realizacja indywidualna w notebooku ==&lt;br /&gt;
===Ćwiczenie 2: Wstępna obróbka sygnału EKG ===&lt;br /&gt;
Napisz program który:&lt;br /&gt;
* wczytuje sygnał&lt;br /&gt;
* wykonuje stosowne filtracje (stosujemy filtrację z zerowym przesunięciem fazowym: filtfilt):  &lt;br /&gt;
** Filtr górnoprzepustowy z częstością odcięcia  0.67 Hz (przy tej częstości wymagamy 3dB tłumienia) i poniżej 0.5-dB tętnień w paśmie 1 - 30 Hz. Proszę sprawdzić charakterystyki).  &lt;br /&gt;
&amp;lt;!--(wymagania te powinien spełnić np. filtr 1 rzędu, Butterwortha, częstość odcięcia 0.25Hz  - --&amp;gt; &lt;br /&gt;
&lt;br /&gt;
** Filtr dolnoprzepustowy z częstością odcięcia 150Hz (wymagania te powinien spełnić np. filtr 2 rzędu, Butterwortha, - proszę sprawdzić charakterystyki). &amp;lt;!--150 Hz i płaskim pasmem przenoszenia w zakresie 1  &lt;br /&gt;
częstość odcięcia 150 Hz  --&amp;gt;&lt;br /&gt;
** Filtr pasmowo-zaporowy (notch) dla 50 Hz iirnotch (scipy.signal.iirnotch())&lt;br /&gt;
&amp;lt;!--(proszę sprawdzić charakterystyki dla filtra Chebysheva 2 rodzaju, 2 rzędu z częstościami odcięcia 49 i 51 Hz i rs = 25 dB)--&amp;gt;&lt;br /&gt;
* rysuje sygnał w odprowadzeniach Einthovena i Goldbergera,&lt;br /&gt;
* wybierz &amp;quot;czysty&amp;quot; fragment sygnału i zidentyfikuj poszczególne załamki. (można wykorzystać funkcję matplotlib.pyplot.axvspan)&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 3: Detekcja pików R ===&lt;br /&gt;
* Zaproponuj metodę rozpoznawania pików R w sygnale, wybierz do tego optymalny kanał. Przedstaw fragment sygnału z zaznaczonymi pikami R. (można skorzystać z funkcji scipy.signal.find_peaks - dobór parametrów funkcji oprzyj na badaniu histogramów odpowiednich parametrów)&lt;br /&gt;
&lt;br /&gt;
Przydatne pojęcie: (ang.) [https://pl.wikipedia.org/wiki/Minimalna_deniwelacja_wzgl%C4%99dna prominence - wybitność piku]&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 4: Tętno ===&lt;br /&gt;
Napisz program, który:&lt;br /&gt;
* wczyta plik z sygnałem i na jego podstawie &lt;br /&gt;
* wyznaczy i wykreśli tętno - liczbę uderzeń serca na minutę (ang. ''heart rate'').&lt;br /&gt;
* Oblicz średnie tętno i jego standardowe odchylenie.&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 5: HRV ===&lt;br /&gt;
HRV - heart rate variability. &lt;br /&gt;
* zapoznaj się z koncepcją [https://en.wikipedia.org/wiki/Heart_rate_variability#cite_note-29 HRV]&lt;br /&gt;
* Literatura [https://link.springer.com/article/10.1007/s11517-006-0119-0 Heart rate variability: a review]. &lt;br /&gt;
* napisz program, który przedstawiwa interwały R-R jako szereg czasowy&lt;br /&gt;
* wyestymuj widmo częstotliwościowe tego sygnału&lt;br /&gt;
** uwaga: próbki są pobierane w różnych odstępach! &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
** Możliwa do zastosowania technika to periodogram Lomb-Scarglea &lt;br /&gt;
*** https://link.springer.com/content/pdf/10.1007%2FBF00648343.pdf &lt;br /&gt;
*** implementacja: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.lombscargle.html#r0520a0371844-2&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
** można zinterpolować punkty na równomiernie próbkowanej siatce https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html#scipy.interpolate.interp1d i zastosować standardową funkcję do estymacji:&lt;br /&gt;
***  periodogramów&lt;br /&gt;
*** widma metodą AR&lt;br /&gt;
* porównaj widma HRV w poszczególnych warunkach eksperymentalnych; zwróć uwagę na proporcje mocy w pasmach wysokich częstości (HF: 0.15 do 0.4 Hz), niskich częśtości (LF: 0.04 do 0.15 Hz) i bardzo niskich częstości (VLF: 0.0033 do 0.04 Hz).&lt;br /&gt;
&lt;br /&gt;
==Literatura uzupełniająca==&lt;br /&gt;
&lt;br /&gt;
[http://www.bem.fi/book/19/19.htm#00 podstawowa diagnostyka EKG]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;!--;Ćwiczenie 8: Wykorzystując poniższe fragmenty kodu, stwórz program, który będzie wyrysowywał zmiany tętna w czasie rzeczywistym.&lt;br /&gt;
Pierwszy fragment kodu, to moduł buforujący sygnał, drugi to moduł pobierający dane z bufora. Należy dopisać do modułu pobierającego dane z bufora przetwarzanie ich (wyrysowywanie tętna) we wskazanym miejscu. &lt;br /&gt;
Uruchamianie całości będzie polegało na:&lt;br /&gt;
* uruchomieniu wzmacniacza&lt;br /&gt;
* uruchomieniu modułu &amp;lt;tt&amp;gt;signal_catcher.py&amp;lt;/tt&amp;gt;&lt;br /&gt;
* uruchomienie &amp;lt;tt&amp;gt;heartrate.py&amp;lt;/tt&amp;gt;, ktory jest dostepny [http://escher.fuw.edu.pl/~mm/zajecia/heartrate.py tu], po wstawieniu do niego w odpowiednie miejsce oznaczone w komentarzu własnego kodu obliczającego tętno.&lt;br /&gt;
* Trochę zmieniona wersja &amp;amp;mdash; [http://escher.fuw.edu.pl/~mm/zajecia/heartrate_new.py &amp;lt;tt&amp;gt;heartrate_new.py&amp;lt;/tt&amp;gt;] oraz  [http://escher.fuw.edu.pl/~mm/zajecia/signal_catcher_pracownia.py &amp;lt;tt&amp;gt;signal_catcher_pracownia.py&amp;lt;/tt&amp;gt;]&lt;br /&gt;
(moduły importują inne moduły, więc trzeba się upewnić że zmienna środowiskowa &amp;lt;tt&amp;gt;PYTHONPATH&amp;lt;/tt&amp;gt; ma odpowiednią wartość, w szczególności musi się w niej znaleźć ścieżka do &amp;lt;tt&amp;gt;azouk-libraries/build/&amp;lt;/tt&amp;gt; aby można było zaimportować moduł &amp;lt;tt&amp;gt;multiplexer&amp;lt;/tt&amp;gt;. Eksportować ścieżki można np tak:&lt;br /&gt;
&amp;lt;tt&amp;gt;export PYTHONPATH=./:openbci/:azouk-libraries/build/:PYTHONPATH&amp;lt;/tt&amp;gt;, tzn. dodajemy ścieżki oddzielone dwukropkiem, tylko należy się upewnić, że dodajemy odpowiednie ścieżki)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# signal_catcher.py&lt;br /&gt;
&lt;br /&gt;
import time&lt;br /&gt;
from multiplexer.multiplexer_constants import peers, types&lt;br /&gt;
from multiplexer.clients import BaseMultiplexerServer&lt;br /&gt;
import collections, variables_pb2&lt;br /&gt;
&lt;br /&gt;
class SignalCatcher(BaseMultiplexerServer):&lt;br /&gt;
    def __init__(self, addresses):&lt;br /&gt;
        super(SignalCatcher, self).__init__(addresses=addresses, type=peers.SIGNAL_CATCHER)&lt;br /&gt;
        self.number_of_channels = len(self.conn.query(message=&amp;quot;AmplifierChannelsToRecord&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message.split(&amp;amp;rdquo; &amp;amp;bdquo;))&lt;br /&gt;
        self.buffer = [collections.deque() for z in range(self.number_of_channels)]&lt;br /&gt;
        self.buffer_size = int(self.conn.query(message=&amp;quot;SignalCatcherBufferSize&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message)&lt;br /&gt;
&lt;br /&gt;
    def add(self, value):&lt;br /&gt;
        sampleVector = variables_pb2.SampleVector()&lt;br /&gt;
        sampleVector.ParseFromString(value)&lt;br /&gt;
&lt;br /&gt;
        i = 0&lt;br /&gt;
        for s in values:&lt;br /&gt;
            self.buffer[i].append(s)&lt;br /&gt;
            if len(self.buffer[i]) &amp;gt; self.buffer_size:&lt;br /&gt;
                self.buffer[i].popleft()&lt;br /&gt;
            i += 1&lt;br /&gt;
      &lt;br /&gt;
    def handle_message(self, mxmsg):&lt;br /&gt;
        if mxmsg.type == types.SIGNAL_CATCHER_REQUEST_MESSAGE:&lt;br /&gt;
            vector = variables_pb2.SampleVector()&lt;br /&gt;
            ind = int(mxmsg.message)&lt;br /&gt;
            &lt;br /&gt;
            for i in range(len(self.buffer[ind])):&lt;br /&gt;
                s = vector.samples.add()&lt;br /&gt;
                s.CopyFrom(self.buffer[ind][i])&lt;br /&gt;
            m = vector.SerializeToString()&lt;br /&gt;
            self.send_message(message = m, type = types.SIGNAL_CATCHER_RESPONSE_MESSAGE)&lt;br /&gt;
        elif mxmsg.type == types.AMPLIFIER_SIGNAL_MESSAGE:&lt;br /&gt;
            self.add(mxmsg.message)&lt;br /&gt;
            self.no_response()&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;amp;bdquo;__main__&amp;quot;:&lt;br /&gt;
    SignalCatcher(settings.MULTIPLEXER_ADDRESSES).loop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* próba obejrzenia zmiany tętna po wysiłku fizycznym, bądź w spoczynku--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11634</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11634"/>
		<updated>2026-03-04T08:28:14Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2025: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
##  [[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Wprowadzenie]]&lt;br /&gt;
&lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|EKG]] &lt;br /&gt;
## Wstęp teoretyczny i pomiary&lt;br /&gt;
## detekcja pików R i tętno&lt;br /&gt;
## analiza HRV&lt;br /&gt;
przesyłanie notebooków z EKG/HRV do 4.04&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|EMG]]&lt;br /&gt;
##  wprowadzenie, pomiary, analiza ćwiczenie I&lt;br /&gt;
##  analiza ćwiczenie I&lt;br /&gt;
##  analiza ćwiczenie I&lt;br /&gt;
##  analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III -&amp;gt; przesyłanie notebooków z EMG do 16.05&lt;br /&gt;
##  &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]]&lt;br /&gt;
##  podstawowe własności EOG - rejestracja&lt;br /&gt;
##  podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 06.06&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
##  [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
##  [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11633</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11633"/>
		<updated>2026-03-04T08:27:37Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2025: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Wprowadzenie]]&lt;br /&gt;
## &lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|EKG]] &lt;br /&gt;
## Wstęp teoretyczny i pomiary&lt;br /&gt;
## detekcja pików R i tętno&lt;br /&gt;
## analiza HRV&lt;br /&gt;
przesyłanie notebooków z EKG/HRV do 4.04&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|EMG]]&lt;br /&gt;
##  wprowadzenie, pomiary, analiza ćwiczenie I&lt;br /&gt;
##  analiza ćwiczenie I&lt;br /&gt;
##  analiza ćwiczenie I&lt;br /&gt;
##  analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III -&amp;gt; przesyłanie notebooków z EMG do 16.05&lt;br /&gt;
##  &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]]&lt;br /&gt;
##  podstawowe własności EOG - rejestracja&lt;br /&gt;
##  podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 06.06&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
##  [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
##  [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11630</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 2 4</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_2_4&amp;diff=11630"/>
		<updated>2026-02-27T09:30:27Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Ćwiczenie 1: rejestracja sygnału */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EKG&lt;br /&gt;
&lt;br /&gt;
==Rejestracja i analiza sygnału EKG==&lt;br /&gt;
&lt;br /&gt;
Lektura:  [http://www.bem.fi/book/15/15.htm Electric and Magnetic Measurement of the Electric Activity of the Heart/12-Lead ECG System]&lt;br /&gt;
[[Plik:einthoven_ekg.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Aparat do rejestracji czynności elektrycznej serca skonstruowany przez W. Einthovena. Proszę zauważyć w jakich miejscach na ciele zbierana jest sygnał.]]&lt;br /&gt;
[[Plik:ekg_animacja.gif|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Rozchodzenie się sygnału stymulujacego pracę serca i związane z tym powstawanie sygnału EKG. Rysunek po brany ze strony Wikipedii.]]&lt;br /&gt;
[[Plik:ekg_opis.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Oznaczenia kolejnych składowych sygnału EKG.]]&lt;br /&gt;
[[Plik:wilson.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:wilson&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Umiejscowienie elektrod do pomiaru czynności elektrycznej serca z powierzchni klatki piersiowej, rysunek pobrany ze stron Wikipedii.]]&lt;br /&gt;
 &lt;br /&gt;
Mechanizm powstawania czynności elektrycznej serca został omówiony na zajęciach &amp;amp;bdquo;Sygnały Bioelektryczne&amp;quot;. W tym miejscu przypomnimy tylko kilka ważnych (i ciekawych) faktów.&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Czynność elektryczna serca znana jest od połowy XIX, jednakże za początek narodzin elektrokardiografii uznaje się rok 1903, kiedy to W. Einthoven dokonał pomiaru czynności elektrycznej serca z powierzchni ciała (&amp;lt;xr id=&amp;quot;fig:einthoven_ekg&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). Jako metoda diagnostyczna, elektrokardiografia zaczęła się szybko rozwijać po roku 1936, kiedy to do rejestracji czynności elektrycznej serca zastosowano wzmacniacz lampowy oraz system zapisu pomiaru na papierze.&lt;br /&gt;
&amp;lt;li&amp;gt; Serce posiada specjalny, wzbudzany samoczynnie układ, który generuje i przewodzi bodźce elektryczne. Następstwem działania tego układu jest rytmiczna praca serca o częstości od 70 do 180 cykli na minutę (częstość ta ulega zmianom pod wpływem czynników biochemicznych, powstałych np. w skutek stresu).&lt;br /&gt;
&amp;lt;li&amp;gt; Elektroda rejestrująca sygnał EKG zbiera czynność elektryczną wszystkich komórek serca, a zatem zarówno komórek wchodzących w skład układu generującego i przewodzącego impulsy elektryczne oraz kurczących się pod wpływem impulsów sterujących mięśni, które kurcząc się, również wytwarzają sygnał elektryczny. Jednakże, z uwagi na nieporównywalnie dużo większą masę mięśni serca w porównaniu z masą komórek układu stymulującego przyjmuje się, że głównym składnikiem sygnału EKG jest czynność elektryczna mięśnia sercowego.&lt;br /&gt;
&amp;lt;li&amp;gt; W przybliżeniu, sygnał stymulujący pracę serca rozchodzi się z jego prawej górnej części w kierunku dolnym i na lewą stronę. Na skutek pobudzania kolejnych partii mięśnia sercowego, powstaje charakterystyczny kształt sygnału EKG (&amp;lt;xr id=&amp;quot;fig:ekg_animacja&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, &amp;lt;xr id=&amp;quot;fig:ekg_opis&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;). &lt;br /&gt;
&amp;lt;li&amp;gt; Oznaczenia kolejnych składowych sygnału EKG:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; odchylenia od linii poziomej (izoelektrycznej) nazywamy załamkami,&lt;br /&gt;
&amp;lt;li&amp;gt; odległość w czasie pomiędzy końcem załamka P i początkiem załamka Q oraz końcem załamka S i początkiem załamka T nazywamy odcinkami &amp;amp;mdash; odpowiednio PQ i ST.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Elektrody pomiarowe połączone do aparatury rejestrujących nazywamy odprowadzeniami. Uwaga &amp;amp;mdash; przyjęto odprowadzeniami oznaczać także sygnały EKG będące liniowymi kombinacjami sygnałów zebranych przez elektrody.&lt;br /&gt;
&amp;lt;li&amp;gt; W konwencjonalnej elektroencefalografii stosuje się 12 tzw. odprowadzeń klasycznych:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt; Trzy odprowadzenia kończynowe biegunowe, zaproponowane jeszcze przez Einthoven i oznaczane rzymskimi cyframi I, II i III. Elektrody w tym systemie umieszcza się prawej (R) (ang. ''right'') i lewej (L) (ang. ''left'') kończynie górnej (najczęściej w okolicy nadgarstka, czasem ramieniu lub czy barku) oraz lewej nodze w okolicy stopy (F) (ang. ''foot''). Elektrodę umieszczaną na prawym nadgarstku oznacza się kolorem czerwonym, na lewym żółtym, na lewej kostce zielonym. Elektrodę masy umieszcza się zwykle na lewej kostce (choć teoretycznie można ją aplikować gdziekolwiek) i jest ona oznaczona kolorem czarnym. Odprowadzenia kończynowe mierzą różnicę napięć pomiędzy miejscami przyłożenia elektrod w następujący sposób:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
I   &amp;amp; = V_{L} - V_{R} \\&lt;br /&gt;
II  &amp;amp; = V_{F} - V_{R} \\&lt;br /&gt;
III &amp;amp; = V_{F} - V_{L}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
gdzie: &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;V_{R}, V_{L}, V_{F}&amp;lt;/math&amp;gt; to potencjały odpowiednio na prawym i lewym nadgarstku oraz stopie mierzone względem elektrody masy.&amp;lt;br/&amp;gt;&lt;br /&gt;
Jak łatwo zauważyć, tylko dwa spośród powyższych napięć są liniowo niezależne, co można zapisać w postaci związku:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_2&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;I + III = II&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
który nazywany jest prawem Einthovena. Proszę zauważyć, iż w tym przypadku wzmacniane jest sygnał będący różnicą napięć dwóch kolejnych elektrod, stąd też te odprowadzenia nazywamy dwubiegunowymi (bipolarnymi).&lt;br /&gt;
&amp;lt;li&amp;gt; Trzy odprowadzenia jednobiegunowe Goldberga. W odprowadzeniach tych sygnał w danym odprowadzeniu jest różnicą napięć pomiędzy elektrodą pomiarową a średnim napięciem na dwóch pozostałych elektrodach:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_3&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
aV_{R} &amp;amp; = V_{R} - \frac{V_{L}+V_{F}}{2} \\&lt;br /&gt;
aV_{L} &amp;amp; = V_{L} - \frac{V_{R}+V_{F}}{2} \\&lt;br /&gt;
aV_{F} &amp;amp; = V_{F} - \frac{V_{L}+V_{R}}{2}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Sześć odprowadzeń jednobiegunowych Wilsona. W przypadku warto zapoznać się z z historią tych odprowadzeń. Początkowo Wilson zaproponował układ jednobiegunowych doniesień dla kończyn w następujący sposób:&lt;br /&gt;
&amp;lt;equation id = &amp;quot;eq_4&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
V_{LW} &amp;amp; = V_{L} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{RW} &amp;amp; = V_{R} - \frac{V_{R}+V_{L}+ V_{F}}{3} \\&lt;br /&gt;
V_{FW} &amp;amp; = V_{F} - \frac{V_{R}+V_{L}+ V_{F}}{3}&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/equation&amp;gt;&lt;br /&gt;
Jak widzimy, jako elektrodę odniesienia wybrał on średnie napięcie rejestrowane przez elektrody. Niestety, sygnały prezentowane w tym systemie miały małą amplitudę, w związku z czym tego rodzaju odprowadzenia nie stosowano w praktyce. Z systemu zaproponowanego przez Wilsona wywodzi się jednak system odniesień Goldberga, który zauważył, że napięcie na trzeciej kończynie można zwiększyć o 50% jeśli do wyznaczenia napięcia odniesienia zastosuje się dwie, a nie trzy elektrody. Metoda wyznaczania potencjału odniesienia zaproponowana przez Wilsona znalazła jednak zastosowanie przy mierzeniu czynności elektrycznej serca mierzonej z powierzchni klatki piersiowej. W tym celu elektrody umieszcza się w pewnych ustalonych miejscach (&amp;lt;xr id=&amp;quot;fig:wilson&amp;quot;&amp;gt;rys. %i&amp;lt;/xr&amp;gt;, zaś odprowadzenia oznacza się symbolami &amp;lt;math&amp;gt;V_1, V_2, \dots, V_6&amp;lt;/math&amp;gt;. Odniesieniem w tym przypadku jest średni sygnał rejestrowany na kończynach górnych i lewej stopie. &lt;br /&gt;
&amp;lt;/ul&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ćwiczenia==&lt;br /&gt;
&lt;br /&gt;
Aby uruchomić zbieranie sygnału należy wykonać następujące operacje:&lt;br /&gt;
* przykleić elektrody do badanego;&lt;br /&gt;
* włożyć przewody do elektrod, a potem do wzmacniacza;&lt;br /&gt;
* podłączyć zasilanie wzmacniacza;&lt;br /&gt;
* podłączyć wzmacniacz do komputera (przejściówka optyczna i kabel USB);&lt;br /&gt;
* uruchomić program SVAROG&lt;br /&gt;
* otworzyć sygnał on-line ze wzmacniacza. &lt;br /&gt;
**  Po tym poleceniu wzmacniacz powinien wyświetlać napis &amp;amp;bdquo;Fiber&amp;amp;rdquo;; napis &amp;amp;bdquo;Connect&amp;amp;rdquo; oznacza, że połączenie wzmacniacza z komputerem nie udało się. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie 0: wstępne  ===&lt;br /&gt;
* Podaj związek pomiędzy sygnałami mierzonymi w systemie Goldbergera, a systemem Einthovena.&lt;br /&gt;
* Podaj analogiczny związek pomiędzy sygnałami w odniesieniach Goldberga co ''Prawo Einthovena''. &lt;br /&gt;
* Pokaż, że w systemie Goldbergera uzyskuje się sygnały o amplitudzie o 50% wyższej niż w pierwotnym systemie Wilsona.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Realizacja w grupie ==&lt;br /&gt;
=== Ćwiczenie 1: rejestracja sygnału === &lt;br /&gt;
&lt;br /&gt;
Podłącz elektrody:&lt;br /&gt;
* lewa ręka, &lt;br /&gt;
* prawa ręka, &lt;br /&gt;
* lewa noga, &lt;br /&gt;
* uziemienie do prawej nogi.&lt;br /&gt;
&lt;br /&gt;
Zbierz 3 fragment sygnału EKG przy pomocy Svaroga. &lt;br /&gt;
&lt;br /&gt;
* Częstotliwość próbkowania 2048 Hz.&lt;br /&gt;
* Długość zapisu 300 s.&lt;br /&gt;
* Proszę zapisać sygnały w następujących warunkach:&lt;br /&gt;
** spoczynkowe&lt;br /&gt;
** po wysiłku fizycznym (odpiąć zatrzaskowe elektrody, przejść się po schodach i podłączyć ponownie )&lt;br /&gt;
** podczas obciążenia poznawczego, np. odejmując w pamięci kolejno 17 od 1000.&lt;br /&gt;
* zebrane sygnały zapisz na dysku classroom&lt;br /&gt;
&lt;br /&gt;
Zapoznaj się z zagadnieniem filtrowania dla sygnałów EKG:&lt;br /&gt;
* Proszę przejrzeć pracę: Shen Luo, Paul Johnston. A review of electrocardiogram filtering,  ''Journal of Electrocardiology'', 2010, Volume 43, Issue 6,  Pages 486-496 (https://www.sciencedirect.com/science/article/pii/S0022073610002852?via%3Dihub) &lt;br /&gt;
* popróbować uzyskać opisane tam filtry w SVAROGU i zaaplikować je do zebranych danych&lt;br /&gt;
&lt;br /&gt;
== Realizacja indywidualna w notebooku ==&lt;br /&gt;
===Ćwiczenie 2: Wstępna obróbka sygnału EKG ===&lt;br /&gt;
Napisz program który:&lt;br /&gt;
* wczytuje sygnał&lt;br /&gt;
* wykonuje stosowne filtracje (stosujemy filtrację z zerowym przesunięciem fazowym: filtfilt):  &lt;br /&gt;
** Filtr górnoprzepustowy z częstością odcięcia  0.67 Hz (przy tej częstości wymagamy 3dB tłumienia) i poniżej 0.5-dB tętnień w paśmie 1 - 30 Hz. Proszę sprawdzić charakterystyki).  &lt;br /&gt;
&amp;lt;!--(wymagania te powinien spełnić np. filtr 1 rzędu, Butterwortha, częstość odcięcia 0.25Hz  - --&amp;gt; &lt;br /&gt;
&lt;br /&gt;
** Filtr dolnoprzepustowy z częstością odcięcia 150Hz (wymagania te powinien spełnić np. filtr 2 rzędu, Butterwortha, - proszę sprawdzić charakterystyki). &amp;lt;!--150 Hz i płaskim pasmem przenoszenia w zakresie 1  &lt;br /&gt;
częstość odcięcia 150 Hz  --&amp;gt;&lt;br /&gt;
** Filtr pasmowo-zaporowy (notch) dla 50 Hz iirnotch (scipy.signal.iirnotch())&lt;br /&gt;
&amp;lt;!--(proszę sprawdzić charakterystyki dla filtra Chebysheva 2 rodzaju, 2 rzędu z częstościami odcięcia 49 i 51 Hz i rs = 25 dB)--&amp;gt;&lt;br /&gt;
* rysuje sygnał w odprowadzeniach Einthovena i Goldberga,&lt;br /&gt;
* wybierz &amp;quot;czysty&amp;quot; fragment sygnału i zidentyfikuj poszczególne załamki. (można wykorzystać funkcję matplotlib.pyplot.axvspan)&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 3: Detekcja pików R ===&lt;br /&gt;
* Zaproponuj metodę rozpoznawania pików R w sygnale, wybierz do tego optymalny kanał. Przedstaw fragment sygnału z zaznaczonymi pikami R. (można skorzystać z funkcji scipy.signal.find_peaks - dobór parametrów funkcji oprzyj na badaniu histogramów odpowiednich parametrów)&lt;br /&gt;
&lt;br /&gt;
Przydatne pojęcie: (ang.) [https://pl.wikipedia.org/wiki/Minimalna_deniwelacja_wzgl%C4%99dna prominence - wybitność piku]&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 4: Tętno ===&lt;br /&gt;
Napisz program, który:&lt;br /&gt;
* wczyta plik z sygnałem i na jego podstawie &lt;br /&gt;
* wyznaczy i wykreśli tętno - liczbę uderzeń serca na minutę (ang. ''heart rate'').&lt;br /&gt;
* Oblicz średnie tętno i jego standardowe odchylenie.&lt;br /&gt;
&lt;br /&gt;
===Ćwiczenie 5: HRV ===&lt;br /&gt;
HRV - heart rate variability. &lt;br /&gt;
* zapoznaj się z koncepcją [https://en.wikipedia.org/wiki/Heart_rate_variability#cite_note-29 HRV]&lt;br /&gt;
* Literatura [https://link.springer.com/article/10.1007/s11517-006-0119-0 Heart rate variability: a review]. &lt;br /&gt;
* napisz program, który przedstawiwa interwały R-R jako szereg czasowy&lt;br /&gt;
* wyestymuj widmo częstotliwościowe tego sygnału&lt;br /&gt;
** uwaga: próbki są pobierane w różnych odstępach! &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
** Możliwa do zastosowania technika to periodogram Lomb-Scarglea &lt;br /&gt;
*** https://link.springer.com/content/pdf/10.1007%2FBF00648343.pdf &lt;br /&gt;
*** implementacja: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.lombscargle.html#r0520a0371844-2&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
** można zinterpolować punkty na równomiernie próbkowanej siatce https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html#scipy.interpolate.interp1d i zastosować standardową funkcję do estymacji:&lt;br /&gt;
***  periodogramów&lt;br /&gt;
*** widma metodą AR&lt;br /&gt;
* porównaj widma HRV w poszczególnych warunkach eksperymentalnych; zwróć uwagę na proporcje mocy w pasmach wysokich częstości (HF: 0.15 do 0.4 Hz), niskich częśtości (LF: 0.04 do 0.15 Hz) i bardzo niskich częstości (VLF: 0.0033 do 0.04 Hz).&lt;br /&gt;
&lt;br /&gt;
==Literatura uzupełniająca==&lt;br /&gt;
&lt;br /&gt;
[http://www.bem.fi/book/19/19.htm#00 podstawowa diagnostyka EKG]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;!--;Ćwiczenie 8: Wykorzystując poniższe fragmenty kodu, stwórz program, który będzie wyrysowywał zmiany tętna w czasie rzeczywistym.&lt;br /&gt;
Pierwszy fragment kodu, to moduł buforujący sygnał, drugi to moduł pobierający dane z bufora. Należy dopisać do modułu pobierającego dane z bufora przetwarzanie ich (wyrysowywanie tętna) we wskazanym miejscu. &lt;br /&gt;
Uruchamianie całości będzie polegało na:&lt;br /&gt;
* uruchomieniu wzmacniacza&lt;br /&gt;
* uruchomieniu modułu &amp;lt;tt&amp;gt;signal_catcher.py&amp;lt;/tt&amp;gt;&lt;br /&gt;
* uruchomienie &amp;lt;tt&amp;gt;heartrate.py&amp;lt;/tt&amp;gt;, ktory jest dostepny [http://escher.fuw.edu.pl/~mm/zajecia/heartrate.py tu], po wstawieniu do niego w odpowiednie miejsce oznaczone w komentarzu własnego kodu obliczającego tętno.&lt;br /&gt;
* Trochę zmieniona wersja &amp;amp;mdash; [http://escher.fuw.edu.pl/~mm/zajecia/heartrate_new.py &amp;lt;tt&amp;gt;heartrate_new.py&amp;lt;/tt&amp;gt;] oraz  [http://escher.fuw.edu.pl/~mm/zajecia/signal_catcher_pracownia.py &amp;lt;tt&amp;gt;signal_catcher_pracownia.py&amp;lt;/tt&amp;gt;]&lt;br /&gt;
(moduły importują inne moduły, więc trzeba się upewnić że zmienna środowiskowa &amp;lt;tt&amp;gt;PYTHONPATH&amp;lt;/tt&amp;gt; ma odpowiednią wartość, w szczególności musi się w niej znaleźć ścieżka do &amp;lt;tt&amp;gt;azouk-libraries/build/&amp;lt;/tt&amp;gt; aby można było zaimportować moduł &amp;lt;tt&amp;gt;multiplexer&amp;lt;/tt&amp;gt;. Eksportować ścieżki można np tak:&lt;br /&gt;
&amp;lt;tt&amp;gt;export PYTHONPATH=./:openbci/:azouk-libraries/build/:PYTHONPATH&amp;lt;/tt&amp;gt;, tzn. dodajemy ścieżki oddzielone dwukropkiem, tylko należy się upewnić, że dodajemy odpowiednie ścieżki)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# signal_catcher.py&lt;br /&gt;
&lt;br /&gt;
import time&lt;br /&gt;
from multiplexer.multiplexer_constants import peers, types&lt;br /&gt;
from multiplexer.clients import BaseMultiplexerServer&lt;br /&gt;
import collections, variables_pb2&lt;br /&gt;
&lt;br /&gt;
class SignalCatcher(BaseMultiplexerServer):&lt;br /&gt;
    def __init__(self, addresses):&lt;br /&gt;
        super(SignalCatcher, self).__init__(addresses=addresses, type=peers.SIGNAL_CATCHER)&lt;br /&gt;
        self.number_of_channels = len(self.conn.query(message=&amp;quot;AmplifierChannelsToRecord&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message.split(&amp;amp;rdquo; &amp;amp;bdquo;))&lt;br /&gt;
        self.buffer = [collections.deque() for z in range(self.number_of_channels)]&lt;br /&gt;
        self.buffer_size = int(self.conn.query(message=&amp;quot;SignalCatcherBufferSize&amp;quot;, type=types.DICT_GET_REQUEST_MESSAGE).message)&lt;br /&gt;
&lt;br /&gt;
    def add(self, value):&lt;br /&gt;
        sampleVector = variables_pb2.SampleVector()&lt;br /&gt;
        sampleVector.ParseFromString(value)&lt;br /&gt;
&lt;br /&gt;
        i = 0&lt;br /&gt;
        for s in values:&lt;br /&gt;
            self.buffer[i].append(s)&lt;br /&gt;
            if len(self.buffer[i]) &amp;gt; self.buffer_size:&lt;br /&gt;
                self.buffer[i].popleft()&lt;br /&gt;
            i += 1&lt;br /&gt;
      &lt;br /&gt;
    def handle_message(self, mxmsg):&lt;br /&gt;
        if mxmsg.type == types.SIGNAL_CATCHER_REQUEST_MESSAGE:&lt;br /&gt;
            vector = variables_pb2.SampleVector()&lt;br /&gt;
            ind = int(mxmsg.message)&lt;br /&gt;
            &lt;br /&gt;
            for i in range(len(self.buffer[ind])):&lt;br /&gt;
                s = vector.samples.add()&lt;br /&gt;
                s.CopyFrom(self.buffer[ind][i])&lt;br /&gt;
            m = vector.SerializeToString()&lt;br /&gt;
            self.send_message(message = m, type = types.SIGNAL_CATCHER_RESPONSE_MESSAGE)&lt;br /&gt;
        elif mxmsg.type == types.AMPLIFIER_SIGNAL_MESSAGE:&lt;br /&gt;
            self.add(mxmsg.message)&lt;br /&gt;
            self.no_response()&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;amp;bdquo;__main__&amp;quot;:&lt;br /&gt;
    SignalCatcher(settings.MULTIPLEXER_ADDRESSES).loop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* próba obejrzenia zmiany tętna po wysiłku fizycznym, bądź w spoczynku--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Analiza_sygna%C5%82%C3%B3w_-_%C4%87wiczenia&amp;diff=11617</id>
		<title>Analiza sygnałów - ćwiczenia</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Analiza_sygna%C5%82%C3%B3w_-_%C4%87wiczenia&amp;diff=11617"/>
		<updated>2026-01-26T08:59:54Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Przedmioty specjalizacyjne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[ZasadyZaliczenia|Zasady zaliczenia ćwiczeń]]&lt;br /&gt;
&lt;br /&gt;
KOLOKWIUM Dodatkowe 2025/26: &lt;br /&gt;
&lt;br /&gt;
https://colab.research.google.com/drive/1tuR6O_Ye-v-8YWAQpYCijzy2SSwEipmH?usp=sharing&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
KOLOKWIUM II 2025/26: https://colab.research.google.com/drive/12EWWd0jG0lqOBCiRqH6_pBXPsSJrNeQS?usp=sharing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
https://colab.research.google.com/drive/1ZUG5l0Ceb-cR7KNG8akp-hmDxZAiatyl?usp=sharing&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dla grupy o 10:15 link do podłączania się: Analiza Sygnałów &lt;br /&gt;
https://meet.google.com/inx-rxqe-fku&lt;br /&gt;
&lt;br /&gt;
# [https://drive.google.com/file/d/1Cr8CCPoh_G-iAq8x2Bm0YxwAcsrNwqir/view?usp=sharing Sygnały AS_1.ipynb]  &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
[https://drive.google.com/file/d/1J_7pyTO00r-OyhyrMd1v_dAoiIU0C-3k/view?usp=sharing notebook wypełniony]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
#  [https://colab.research.google.com/drive/1y81wGZHwpUf4J6IIApPdqahgUN9Bad0p?usp=sharing Transformata Fouriera 1 (FFT) AS2_Transformata_fouriera.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/18nU5rWKinO697M3Pgnp6luiC-NcBYD-9?usp=sharing Transformata Fouriera 2 AS3_Transformata_fouriera_2.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1b6djG2_uE_yc0-QEyD1Yl-dd8Ezelf2m?usp=sharing Okienkowanie AS4_okienkowanie.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1Lr-fkC4oFl2Tf4Y2w2w27bARpvwWRSmG?usp=sharing Estymacja widma mocy AS5_Widmo_mocy.ipynb ] &lt;br /&gt;
# kontynuacja notebook AS5&lt;br /&gt;
#[https://colab.research.google.com/drive/1mKjXYKICL1vp5z0MpWrfM8JuXCDlc_HK?usp=sharing Model AR AS6_1_ProcesyAR.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1NRzWBr5j5YzwfaZDwJC5yaPEVgi6rc6U?usp=sharing Estymacja parametryczna widma procesu AS6_2_Widmo_Procesu_AR.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1e8_SIPFqAJA7WGsPiWudplubHtrgkSq0?usp=sharing Filtry notebook7] &lt;br /&gt;
# kontynuacja notebook7  -&amp;gt; notebook z grupy porannej: https://colab.research.google.com/drive/1bBzlxf7krP7KI_SYIgZLMPfD0bnleXVo?usp=sharing&lt;br /&gt;
#[https://drive.google.com/file/d/1Ey1yYgVMbu3n9djb2LzPZ4dT03gYFcAw/view?usp=sharing Metody czas-częstość STFT i falki: notebook8]      &amp;lt;br&amp;gt;[https://drive.google.com/open?id=0BzwQ_Lscn8yDdUlLVXp1XzF0elE notebook 10] &amp;lt;br&amp;gt;lektura uzupełniająca: [https://www.math.ucdavis.edu/~saito/data/sonar/boashash1.pdf  Estimating and Interpreting The Instantaneous Frequency of a Signal-Part 1: Fundamentals ]&lt;br /&gt;
# [https://drive.google.com/file/d/13Jvt1po_Brk49fRe-dOxOvVfRz1VVieW/view?usp=sharing Notebook o metodzie MP]&lt;br /&gt;
&lt;br /&gt;
== Materiały pomocnicze do samokształcenia: ==&lt;br /&gt;
&lt;br /&gt;
* Zbiór zadań z Analizy sygnałów wraz z rozwiązaniami przygotowany w ramach Projektu zespołowego przez Monikę Tutaj i Marcina Syca pod kierunkiem mgr. Piotra Biegańskiego https://www.fuw.edu.pl/~jarekz/ZadaniaAS/Zadania_Analiza_Sygnałów.zip&lt;br /&gt;
* Zbiór zadań z pythona, które mają na celu pomoc w opanowaniu podstaw Pythona, ze szczególnym naciskiem na rozwinięcie kompetencji potrzebnych w analizie sygnałów, takich jak: pogłębiona znajomość biblioteki numpy, praca z plikami multipleksowanymi, wykorzystanie Pythona jako narzędzia do analizy danych. https://gitlab.com/pbieganski/podstawy-pythona&lt;br /&gt;
* Notatnik z kolokwium poprawkowym 2025: https://colab.research.google.com/drive/1_DQ7rG7aIMq_XgkPZIM4bGAAf8VlFVGc?usp=sharing&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
https://colab.research.google.com/drive/1WZwnu_YgmsRfBdC6Oy5AHULT6b4RInn5?usp=sharing&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1IlY0KsqxMuW7s-Aic_hnChc5sN7QCIgL/view?usp=sharing &lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Okladka.jpeg|thumb|upright=0.25| Dostępna w bibliotece]] W bibliotece Wydziału Fizyki dostępne są książki: Practical biomedical signal analysis using Matlab / K. J. Blinowska J. Żygierewicz. (katalog: https://chamo.buw.uw.edu.pl:8443/lib/item?id=chamo:895791&amp;amp;fromLocationLink=false&amp;amp;theme=system)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Materiały dodatkowe: ==&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/playlist?list=PLXJDR4jmaWX795PLOwLt5pR59H2BrZAsK playlista na YouTube z filmami nagranymi w czasie zdalnych ćwiczeń w roku 2020/21]&lt;br /&gt;
&lt;br /&gt;
[https://tftb.nongnu.org/tutorial.pdf Tutorial o technikach analizy czas-częstość]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Przed kolokwium 1&lt;br /&gt;
# [[kolokwia2014_2015_kol1|Zagadnienia przygotowawcze do 1 kolokwium]] &lt;br /&gt;
# [https://drive.google.com/open?id=1RKIHgfuqtBvg65PUpIuQI3rYeyvdIXMi zadania powtórzeniowe do kolokwium  1]&lt;br /&gt;
&lt;br /&gt;
autorzy: Jarosław Żygierewicz, Maciej Kamiński, Magdalena Zieleniewska, wersja z notebookami Jan Mąka i Piotr Biegański&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== INFORMACJE DODATKOWE ==&lt;br /&gt;
Materiały 2014/2015&lt;br /&gt;
# [[kolokwia2013_2014|Informacje o zaliczeniu ćwiczeń]] &lt;br /&gt;
# [[kolokwia2014_2015_kol1|Zagadnienia przygotowawcze do 1 kolokwium]] &lt;br /&gt;
# [[Projekt2014|Projekt zaliczeniowy]]&lt;br /&gt;
&lt;br /&gt;
Materiały 2013/2014&lt;br /&gt;
# [[Plik:Zadania_powtorzeniowe.pdf|Zadania powtorzeniowe do 2 kolokwium]]&lt;br /&gt;
&lt;br /&gt;
#[[Systemy liniowe niezmiennicze w czasie | Systemy liniowe niezmiennicze w czasie]]&lt;br /&gt;
[[Ćwiczenia 8|Filtrowanie obrazów]]&lt;br /&gt;
[[Ćwiczenia 9|Analiza czas-częstość]]&lt;br /&gt;
[[Ćwiczenia 10|Analiza czas-częstość &amp;amp;mdash; STFT i transformata falkowa]]&lt;br /&gt;
[[Ćwiczenia 11|Analiza czas-częstość &amp;amp;mdash; reprezentacje energetyczne]]&lt;br /&gt;
#[[AS cwiczenia ICA| ICA]] montaże, ICA &lt;br /&gt;
#[[AS cwiczenia DTF| DTF]]wielokanałowy AR , DTF &lt;br /&gt;
&lt;br /&gt;
#[[AS cwiczeniaMP|Matching pursuit]] MP w Svarogu, zabawa parametrami dekompozycji, zabawa filtrowaniem map w Svarogu, postprocessing w Pythonie &lt;br /&gt;
&lt;br /&gt;
# Uśrednianie gęstości energii vs gęstość energii uśrednionego sygnału: symulacje, ERD/S&lt;br /&gt;
#[[Ćwiczenia UNIFIKACJA]] ostatnie ćwiczenia na ktrych porównujemy na tych samych sygnałach rzeczywistych i symulowanych działanie różnych metod -- MMP vs DTF vs ICA, STFT vs WT vs MP itp, potrzebne fajne przykłady&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Analiza_sygna%C5%82%C3%B3w_-_%C4%87wiczenia&amp;diff=11616</id>
		<title>Analiza sygnałów - ćwiczenia</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Analiza_sygna%C5%82%C3%B3w_-_%C4%87wiczenia&amp;diff=11616"/>
		<updated>2026-01-26T08:59:38Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Przedmioty specjalizacyjne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[ZasadyZaliczenia|Zasady zaliczenia ćwiczeń]]&lt;br /&gt;
KOLOKWIUM Dodatkowe 2025/26: &lt;br /&gt;
&lt;br /&gt;
https://colab.research.google.com/drive/1tuR6O_Ye-v-8YWAQpYCijzy2SSwEipmH?usp=sharing&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
KOLOKWIUM II 2025/26: https://colab.research.google.com/drive/12EWWd0jG0lqOBCiRqH6_pBXPsSJrNeQS?usp=sharing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
https://colab.research.google.com/drive/1ZUG5l0Ceb-cR7KNG8akp-hmDxZAiatyl?usp=sharing&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dla grupy o 10:15 link do podłączania się: Analiza Sygnałów &lt;br /&gt;
https://meet.google.com/inx-rxqe-fku&lt;br /&gt;
&lt;br /&gt;
# [https://drive.google.com/file/d/1Cr8CCPoh_G-iAq8x2Bm0YxwAcsrNwqir/view?usp=sharing Sygnały AS_1.ipynb]  &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
[https://drive.google.com/file/d/1J_7pyTO00r-OyhyrMd1v_dAoiIU0C-3k/view?usp=sharing notebook wypełniony]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
#  [https://colab.research.google.com/drive/1y81wGZHwpUf4J6IIApPdqahgUN9Bad0p?usp=sharing Transformata Fouriera 1 (FFT) AS2_Transformata_fouriera.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/18nU5rWKinO697M3Pgnp6luiC-NcBYD-9?usp=sharing Transformata Fouriera 2 AS3_Transformata_fouriera_2.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1b6djG2_uE_yc0-QEyD1Yl-dd8Ezelf2m?usp=sharing Okienkowanie AS4_okienkowanie.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1Lr-fkC4oFl2Tf4Y2w2w27bARpvwWRSmG?usp=sharing Estymacja widma mocy AS5_Widmo_mocy.ipynb ] &lt;br /&gt;
# kontynuacja notebook AS5&lt;br /&gt;
#[https://colab.research.google.com/drive/1mKjXYKICL1vp5z0MpWrfM8JuXCDlc_HK?usp=sharing Model AR AS6_1_ProcesyAR.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1NRzWBr5j5YzwfaZDwJC5yaPEVgi6rc6U?usp=sharing Estymacja parametryczna widma procesu AS6_2_Widmo_Procesu_AR.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1e8_SIPFqAJA7WGsPiWudplubHtrgkSq0?usp=sharing Filtry notebook7] &lt;br /&gt;
# kontynuacja notebook7  -&amp;gt; notebook z grupy porannej: https://colab.research.google.com/drive/1bBzlxf7krP7KI_SYIgZLMPfD0bnleXVo?usp=sharing&lt;br /&gt;
#[https://drive.google.com/file/d/1Ey1yYgVMbu3n9djb2LzPZ4dT03gYFcAw/view?usp=sharing Metody czas-częstość STFT i falki: notebook8]      &amp;lt;br&amp;gt;[https://drive.google.com/open?id=0BzwQ_Lscn8yDdUlLVXp1XzF0elE notebook 10] &amp;lt;br&amp;gt;lektura uzupełniająca: [https://www.math.ucdavis.edu/~saito/data/sonar/boashash1.pdf  Estimating and Interpreting The Instantaneous Frequency of a Signal-Part 1: Fundamentals ]&lt;br /&gt;
# [https://drive.google.com/file/d/13Jvt1po_Brk49fRe-dOxOvVfRz1VVieW/view?usp=sharing Notebook o metodzie MP]&lt;br /&gt;
&lt;br /&gt;
== Materiały pomocnicze do samokształcenia: ==&lt;br /&gt;
&lt;br /&gt;
* Zbiór zadań z Analizy sygnałów wraz z rozwiązaniami przygotowany w ramach Projektu zespołowego przez Monikę Tutaj i Marcina Syca pod kierunkiem mgr. Piotra Biegańskiego https://www.fuw.edu.pl/~jarekz/ZadaniaAS/Zadania_Analiza_Sygnałów.zip&lt;br /&gt;
* Zbiór zadań z pythona, które mają na celu pomoc w opanowaniu podstaw Pythona, ze szczególnym naciskiem na rozwinięcie kompetencji potrzebnych w analizie sygnałów, takich jak: pogłębiona znajomość biblioteki numpy, praca z plikami multipleksowanymi, wykorzystanie Pythona jako narzędzia do analizy danych. https://gitlab.com/pbieganski/podstawy-pythona&lt;br /&gt;
* Notatnik z kolokwium poprawkowym 2025: https://colab.research.google.com/drive/1_DQ7rG7aIMq_XgkPZIM4bGAAf8VlFVGc?usp=sharing&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
https://colab.research.google.com/drive/1WZwnu_YgmsRfBdC6Oy5AHULT6b4RInn5?usp=sharing&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1IlY0KsqxMuW7s-Aic_hnChc5sN7QCIgL/view?usp=sharing &lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Okladka.jpeg|thumb|upright=0.25| Dostępna w bibliotece]] W bibliotece Wydziału Fizyki dostępne są książki: Practical biomedical signal analysis using Matlab / K. J. Blinowska J. Żygierewicz. (katalog: https://chamo.buw.uw.edu.pl:8443/lib/item?id=chamo:895791&amp;amp;fromLocationLink=false&amp;amp;theme=system)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Materiały dodatkowe: ==&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/playlist?list=PLXJDR4jmaWX795PLOwLt5pR59H2BrZAsK playlista na YouTube z filmami nagranymi w czasie zdalnych ćwiczeń w roku 2020/21]&lt;br /&gt;
&lt;br /&gt;
[https://tftb.nongnu.org/tutorial.pdf Tutorial o technikach analizy czas-częstość]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Przed kolokwium 1&lt;br /&gt;
# [[kolokwia2014_2015_kol1|Zagadnienia przygotowawcze do 1 kolokwium]] &lt;br /&gt;
# [https://drive.google.com/open?id=1RKIHgfuqtBvg65PUpIuQI3rYeyvdIXMi zadania powtórzeniowe do kolokwium  1]&lt;br /&gt;
&lt;br /&gt;
autorzy: Jarosław Żygierewicz, Maciej Kamiński, Magdalena Zieleniewska, wersja z notebookami Jan Mąka i Piotr Biegański&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== INFORMACJE DODATKOWE ==&lt;br /&gt;
Materiały 2014/2015&lt;br /&gt;
# [[kolokwia2013_2014|Informacje o zaliczeniu ćwiczeń]] &lt;br /&gt;
# [[kolokwia2014_2015_kol1|Zagadnienia przygotowawcze do 1 kolokwium]] &lt;br /&gt;
# [[Projekt2014|Projekt zaliczeniowy]]&lt;br /&gt;
&lt;br /&gt;
Materiały 2013/2014&lt;br /&gt;
# [[Plik:Zadania_powtorzeniowe.pdf|Zadania powtorzeniowe do 2 kolokwium]]&lt;br /&gt;
&lt;br /&gt;
#[[Systemy liniowe niezmiennicze w czasie | Systemy liniowe niezmiennicze w czasie]]&lt;br /&gt;
[[Ćwiczenia 8|Filtrowanie obrazów]]&lt;br /&gt;
[[Ćwiczenia 9|Analiza czas-częstość]]&lt;br /&gt;
[[Ćwiczenia 10|Analiza czas-częstość &amp;amp;mdash; STFT i transformata falkowa]]&lt;br /&gt;
[[Ćwiczenia 11|Analiza czas-częstość &amp;amp;mdash; reprezentacje energetyczne]]&lt;br /&gt;
#[[AS cwiczenia ICA| ICA]] montaże, ICA &lt;br /&gt;
#[[AS cwiczenia DTF| DTF]]wielokanałowy AR , DTF &lt;br /&gt;
&lt;br /&gt;
#[[AS cwiczeniaMP|Matching pursuit]] MP w Svarogu, zabawa parametrami dekompozycji, zabawa filtrowaniem map w Svarogu, postprocessing w Pythonie &lt;br /&gt;
&lt;br /&gt;
# Uśrednianie gęstości energii vs gęstość energii uśrednionego sygnału: symulacje, ERD/S&lt;br /&gt;
#[[Ćwiczenia UNIFIKACJA]] ostatnie ćwiczenia na ktrych porównujemy na tych samych sygnałach rzeczywistych i symulowanych działanie różnych metod -- MMP vs DTF vs ICA, STFT vs WT vs MP itp, potrzebne fajne przykłady&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Analiza_sygna%C5%82%C3%B3w_-_%C4%87wiczenia&amp;diff=11602</id>
		<title>Analiza sygnałów - ćwiczenia</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Analiza_sygna%C5%82%C3%B3w_-_%C4%87wiczenia&amp;diff=11602"/>
		<updated>2026-01-12T08:57:33Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Przedmioty specjalizacyjne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[ZasadyZaliczenia|Zasady zaliczenia ćwiczeń]]&lt;br /&gt;
&lt;br /&gt;
KOLOKWIUM II 2025/26: https://colab.research.google.com/drive/12EWWd0jG0lqOBCiRqH6_pBXPsSJrNeQS?usp=sharing&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
https://colab.research.google.com/drive/1ZUG5l0Ceb-cR7KNG8akp-hmDxZAiatyl?usp=sharing&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dla grupy o 10:15 link do podłączania się: Analiza Sygnałów &lt;br /&gt;
https://meet.google.com/inx-rxqe-fku&lt;br /&gt;
&lt;br /&gt;
# [https://drive.google.com/file/d/1Cr8CCPoh_G-iAq8x2Bm0YxwAcsrNwqir/view?usp=sharing Sygnały AS_1.ipynb]  &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
[https://drive.google.com/file/d/1J_7pyTO00r-OyhyrMd1v_dAoiIU0C-3k/view?usp=sharing notebook wypełniony]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
#  [https://colab.research.google.com/drive/1y81wGZHwpUf4J6IIApPdqahgUN9Bad0p?usp=sharing Transformata Fouriera 1 (FFT) AS2_Transformata_fouriera.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/18nU5rWKinO697M3Pgnp6luiC-NcBYD-9?usp=sharing Transformata Fouriera 2 AS3_Transformata_fouriera_2.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1b6djG2_uE_yc0-QEyD1Yl-dd8Ezelf2m?usp=sharing Okienkowanie AS4_okienkowanie.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1Lr-fkC4oFl2Tf4Y2w2w27bARpvwWRSmG?usp=sharing Estymacja widma mocy AS5_Widmo_mocy.ipynb ] &lt;br /&gt;
# kontynuacja notebook AS5&lt;br /&gt;
#[https://colab.research.google.com/drive/1mKjXYKICL1vp5z0MpWrfM8JuXCDlc_HK?usp=sharing Model AR AS6_1_ProcesyAR.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1NRzWBr5j5YzwfaZDwJC5yaPEVgi6rc6U?usp=sharing Estymacja parametryczna widma procesu AS6_2_Widmo_Procesu_AR.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1e8_SIPFqAJA7WGsPiWudplubHtrgkSq0?usp=sharing Filtry notebook7] &lt;br /&gt;
# kontynuacja notebook7  -&amp;gt; notebook z grupy porannej: https://colab.research.google.com/drive/1bBzlxf7krP7KI_SYIgZLMPfD0bnleXVo?usp=sharing&lt;br /&gt;
#[https://drive.google.com/file/d/1Ey1yYgVMbu3n9djb2LzPZ4dT03gYFcAw/view?usp=sharing Metody czas-częstość STFT i falki: notebook8]      &amp;lt;br&amp;gt;[https://drive.google.com/open?id=0BzwQ_Lscn8yDdUlLVXp1XzF0elE notebook 10] &amp;lt;br&amp;gt;lektura uzupełniająca: [https://www.math.ucdavis.edu/~saito/data/sonar/boashash1.pdf  Estimating and Interpreting The Instantaneous Frequency of a Signal-Part 1: Fundamentals ]&lt;br /&gt;
# [https://drive.google.com/file/d/13Jvt1po_Brk49fRe-dOxOvVfRz1VVieW/view?usp=sharing Notebook o metodzie MP]&lt;br /&gt;
&lt;br /&gt;
== Materiały pomocnicze do samokształcenia: ==&lt;br /&gt;
&lt;br /&gt;
* Zbiór zadań z Analizy sygnałów wraz z rozwiązaniami przygotowany w ramach Projektu zespołowego przez Monikę Tutaj i Marcina Syca pod kierunkiem mgr. Piotra Biegańskiego https://www.fuw.edu.pl/~jarekz/ZadaniaAS/Zadania_Analiza_Sygnałów.zip&lt;br /&gt;
* Zbiór zadań z pythona, które mają na celu pomoc w opanowaniu podstaw Pythona, ze szczególnym naciskiem na rozwinięcie kompetencji potrzebnych w analizie sygnałów, takich jak: pogłębiona znajomość biblioteki numpy, praca z plikami multipleksowanymi, wykorzystanie Pythona jako narzędzia do analizy danych. https://gitlab.com/pbieganski/podstawy-pythona&lt;br /&gt;
* Notatnik z kolokwium poprawkowym 2025: https://colab.research.google.com/drive/1_DQ7rG7aIMq_XgkPZIM4bGAAf8VlFVGc?usp=sharing&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
https://colab.research.google.com/drive/1WZwnu_YgmsRfBdC6Oy5AHULT6b4RInn5?usp=sharing&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1IlY0KsqxMuW7s-Aic_hnChc5sN7QCIgL/view?usp=sharing &lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Okladka.jpeg|thumb|upright=0.25| Dostępna w bibliotece]] W bibliotece Wydziału Fizyki dostępne są książki: Practical biomedical signal analysis using Matlab / K. J. Blinowska J. Żygierewicz. (katalog: https://chamo.buw.uw.edu.pl:8443/lib/item?id=chamo:895791&amp;amp;fromLocationLink=false&amp;amp;theme=system)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Materiały dodatkowe: ==&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/playlist?list=PLXJDR4jmaWX795PLOwLt5pR59H2BrZAsK playlista na YouTube z filmami nagranymi w czasie zdalnych ćwiczeń w roku 2020/21]&lt;br /&gt;
&lt;br /&gt;
[https://tftb.nongnu.org/tutorial.pdf Tutorial o technikach analizy czas-częstość]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Przed kolokwium 1&lt;br /&gt;
# [[kolokwia2014_2015_kol1|Zagadnienia przygotowawcze do 1 kolokwium]] &lt;br /&gt;
# [https://drive.google.com/open?id=1RKIHgfuqtBvg65PUpIuQI3rYeyvdIXMi zadania powtórzeniowe do kolokwium  1]&lt;br /&gt;
&lt;br /&gt;
autorzy: Jarosław Żygierewicz, Maciej Kamiński, Magdalena Zieleniewska, wersja z notebookami Jan Mąka i Piotr Biegański&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== INFORMACJE DODATKOWE ==&lt;br /&gt;
Materiały 2014/2015&lt;br /&gt;
# [[kolokwia2013_2014|Informacje o zaliczeniu ćwiczeń]] &lt;br /&gt;
# [[kolokwia2014_2015_kol1|Zagadnienia przygotowawcze do 1 kolokwium]] &lt;br /&gt;
# [[Projekt2014|Projekt zaliczeniowy]]&lt;br /&gt;
&lt;br /&gt;
Materiały 2013/2014&lt;br /&gt;
# [[Plik:Zadania_powtorzeniowe.pdf|Zadania powtorzeniowe do 2 kolokwium]]&lt;br /&gt;
&lt;br /&gt;
#[[Systemy liniowe niezmiennicze w czasie | Systemy liniowe niezmiennicze w czasie]]&lt;br /&gt;
[[Ćwiczenia 8|Filtrowanie obrazów]]&lt;br /&gt;
[[Ćwiczenia 9|Analiza czas-częstość]]&lt;br /&gt;
[[Ćwiczenia 10|Analiza czas-częstość &amp;amp;mdash; STFT i transformata falkowa]]&lt;br /&gt;
[[Ćwiczenia 11|Analiza czas-częstość &amp;amp;mdash; reprezentacje energetyczne]]&lt;br /&gt;
#[[AS cwiczenia ICA| ICA]] montaże, ICA &lt;br /&gt;
#[[AS cwiczenia DTF| DTF]]wielokanałowy AR , DTF &lt;br /&gt;
&lt;br /&gt;
#[[AS cwiczeniaMP|Matching pursuit]] MP w Svarogu, zabawa parametrami dekompozycji, zabawa filtrowaniem map w Svarogu, postprocessing w Pythonie &lt;br /&gt;
&lt;br /&gt;
# Uśrednianie gęstości energii vs gęstość energii uśrednionego sygnału: symulacje, ERD/S&lt;br /&gt;
#[[Ćwiczenia UNIFIKACJA]] ostatnie ćwiczenia na ktrych porównujemy na tych samych sygnałach rzeczywistych i symulowanych działanie różnych metod -- MMP vs DTF vs ICA, STFT vs WT vs MP itp, potrzebne fajne przykłady&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Analiza_sygna%C5%82%C3%B3w_-_%C4%87wiczenia&amp;diff=11484</id>
		<title>Analiza sygnałów - ćwiczenia</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Analiza_sygna%C5%82%C3%B3w_-_%C4%87wiczenia&amp;diff=11484"/>
		<updated>2025-11-17T08:59:25Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Przedmioty specjalizacyjne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[ZasadyZaliczenia|Zasady zaliczenia ćwiczeń]]&lt;br /&gt;
&lt;br /&gt;
KOLOKWIUM I 2025: https://colab.research.google.com/drive/1ZUG5l0Ceb-cR7KNG8akp-hmDxZAiatyl?usp=sharing&lt;br /&gt;
&lt;br /&gt;
Dla grupy o 10:15 link do podłączania się: Analiza Sygnałów &lt;br /&gt;
https://meet.google.com/inx-rxqe-fku&lt;br /&gt;
&lt;br /&gt;
# [https://drive.google.com/file/d/1Cr8CCPoh_G-iAq8x2Bm0YxwAcsrNwqir/view?usp=sharing Sygnały AS_1.ipynb]  &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
[https://drive.google.com/file/d/1J_7pyTO00r-OyhyrMd1v_dAoiIU0C-3k/view?usp=sharing notebook wypełniony]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
#  [https://colab.research.google.com/drive/1y81wGZHwpUf4J6IIApPdqahgUN9Bad0p?usp=sharing Transformata Fouriera 1 (FFT) AS2_Transformata_fouriera.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/18nU5rWKinO697M3Pgnp6luiC-NcBYD-9?usp=sharing Transformata Fouriera 2 AS3_Transformata_fouriera_2.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1b6djG2_uE_yc0-QEyD1Yl-dd8Ezelf2m?usp=sharing Okienkowanie AS4_okienkowanie.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1Lr-fkC4oFl2Tf4Y2w2w27bARpvwWRSmG?usp=sharing Estymacja widma mocy AS5_Widmo_mocy.ipynb ] &lt;br /&gt;
# kontynuacja notebook AS5&lt;br /&gt;
#[https://colab.research.google.com/drive/1mKjXYKICL1vp5z0MpWrfM8JuXCDlc_HK?usp=sharing Model AR AS6_1_ProcesyAR.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1NRzWBr5j5YzwfaZDwJC5yaPEVgi6rc6U?usp=sharing Estymacja parametryczna widma procesu AS6_2_Widmo_Procesu_AR.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1e8_SIPFqAJA7WGsPiWudplubHtrgkSq0?usp=sharing Filtry notebook7] &lt;br /&gt;
# kontynuacja notebook7  -&amp;gt; notebook z grupy porannej: https://colab.research.google.com/drive/1bBzlxf7krP7KI_SYIgZLMPfD0bnleXVo?usp=sharing&lt;br /&gt;
#[https://drive.google.com/file/d/1Ey1yYgVMbu3n9djb2LzPZ4dT03gYFcAw/view?usp=sharing Metody czas-częstość STFT i falki: notebook8]      &amp;lt;br&amp;gt;[https://drive.google.com/open?id=0BzwQ_Lscn8yDdUlLVXp1XzF0elE notebook 10] &amp;lt;br&amp;gt;lektura uzupełniająca: [https://www.math.ucdavis.edu/~saito/data/sonar/boashash1.pdf  Estimating and Interpreting The Instantaneous Frequency of a Signal-Part 1: Fundamentals ]&lt;br /&gt;
# [https://drive.google.com/file/d/13Jvt1po_Brk49fRe-dOxOvVfRz1VVieW/view?usp=sharing Notebook o metodzie MP]&lt;br /&gt;
&lt;br /&gt;
== Materiały pomocnicze do samokształcenia: ==&lt;br /&gt;
&lt;br /&gt;
* Zbiór zadań z Analizy sygnałów wraz z rozwiązaniami przygotowany w ramach Projektu zespołowego przez Monikę Tutaj i Marcina Syca pod kierunkiem mgr. Piotra Biegańskiego https://www.fuw.edu.pl/~jarekz/ZadaniaAS/Zadania_Analiza_Sygnałów.zip&lt;br /&gt;
* Zbiór zadań z pythona, które mają na celu pomoc w opanowaniu podstaw Pythona, ze szczególnym naciskiem na rozwinięcie kompetencji potrzebnych w analizie sygnałów, takich jak: pogłębiona znajomość biblioteki numpy, praca z plikami multipleksowanymi, wykorzystanie Pythona jako narzędzia do analizy danych. https://gitlab.com/pbieganski/podstawy-pythona&lt;br /&gt;
* Notatnik z kolokwium poprawkowym 2025: https://colab.research.google.com/drive/1_DQ7rG7aIMq_XgkPZIM4bGAAf8VlFVGc?usp=sharing&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
https://colab.research.google.com/drive/1WZwnu_YgmsRfBdC6Oy5AHULT6b4RInn5?usp=sharing&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1IlY0KsqxMuW7s-Aic_hnChc5sN7QCIgL/view?usp=sharing &lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Okladka.jpeg|thumb|upright=0.25| Dostępna w bibliotece]] W bibliotece Wydziału Fizyki dostępne są książki: Practical biomedical signal analysis using Matlab / K. J. Blinowska J. Żygierewicz. (katalog: https://chamo.buw.uw.edu.pl:8443/lib/item?id=chamo:895791&amp;amp;fromLocationLink=false&amp;amp;theme=system)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Materiały dodatkowe: ==&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/playlist?list=PLXJDR4jmaWX795PLOwLt5pR59H2BrZAsK playlista na YouTube z filmami nagranymi w czasie zdalnych ćwiczeń w roku 2020/21]&lt;br /&gt;
&lt;br /&gt;
[https://tftb.nongnu.org/tutorial.pdf Tutorial o technikach analizy czas-częstość]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Przed kolokwium 1&lt;br /&gt;
# [[kolokwia2014_2015_kol1|Zagadnienia przygotowawcze do 1 kolokwium]] &lt;br /&gt;
# [https://drive.google.com/open?id=1RKIHgfuqtBvg65PUpIuQI3rYeyvdIXMi zadania powtórzeniowe do kolokwium  1]&lt;br /&gt;
&lt;br /&gt;
autorzy: Jarosław Żygierewicz, Maciej Kamiński, Magdalena Zieleniewska, wersja z notebookami Jan Mąka i Piotr Biegański&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== INFORMACJE DODATKOWE ==&lt;br /&gt;
Materiały 2014/2015&lt;br /&gt;
# [[kolokwia2013_2014|Informacje o zaliczeniu ćwiczeń]] &lt;br /&gt;
# [[kolokwia2014_2015_kol1|Zagadnienia przygotowawcze do 1 kolokwium]] &lt;br /&gt;
# [[Projekt2014|Projekt zaliczeniowy]]&lt;br /&gt;
&lt;br /&gt;
Materiały 2013/2014&lt;br /&gt;
# [[Plik:Zadania_powtorzeniowe.pdf|Zadania powtorzeniowe do 2 kolokwium]]&lt;br /&gt;
&lt;br /&gt;
#[[Systemy liniowe niezmiennicze w czasie | Systemy liniowe niezmiennicze w czasie]]&lt;br /&gt;
[[Ćwiczenia 8|Filtrowanie obrazów]]&lt;br /&gt;
[[Ćwiczenia 9|Analiza czas-częstość]]&lt;br /&gt;
[[Ćwiczenia 10|Analiza czas-częstość &amp;amp;mdash; STFT i transformata falkowa]]&lt;br /&gt;
[[Ćwiczenia 11|Analiza czas-częstość &amp;amp;mdash; reprezentacje energetyczne]]&lt;br /&gt;
#[[AS cwiczenia ICA| ICA]] montaże, ICA &lt;br /&gt;
#[[AS cwiczenia DTF| DTF]]wielokanałowy AR , DTF &lt;br /&gt;
&lt;br /&gt;
#[[AS cwiczeniaMP|Matching pursuit]] MP w Svarogu, zabawa parametrami dekompozycji, zabawa filtrowaniem map w Svarogu, postprocessing w Pythonie &lt;br /&gt;
&lt;br /&gt;
# Uśrednianie gęstości energii vs gęstość energii uśrednionego sygnału: symulacje, ERD/S&lt;br /&gt;
#[[Ćwiczenia UNIFIKACJA]] ostatnie ćwiczenia na ktrych porównujemy na tych samych sygnałach rzeczywistych i symulowanych działanie różnych metod -- MMP vs DTF vs ICA, STFT vs WT vs MP itp, potrzebne fajne przykłady&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=ZasadyZaliczenia&amp;diff=11475</id>
		<title>ZasadyZaliczenia</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=ZasadyZaliczenia&amp;diff=11475"/>
		<updated>2025-10-30T12:46:48Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Kolokwia */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Analiza_sygnałów_-_ćwiczenia]]/Zasady zaliczenia&lt;br /&gt;
&lt;br /&gt;
== Zasady zaliczenia ćwiczeń z [[Analiza_sygnałów - exercises|Analizy Sygnałów]] ==&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Kartkówki===&lt;br /&gt;
Na początku większości zajęć będą kartkówki. Z kartkówek można uzyskać ''k'' procent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
=== Kolokwia ===&lt;br /&gt;
W trakcie semestru odbędą się dwa kolokwia. Z każdego z nich będzie można uzyskać ''1/2 x'' procent, z czego do zaliczenia przedmiotu konieczne będzie zdobycie łącznie 50% z kolokwiów. Kolokwia będą wspólne dla wszystkich grup, będą się odbywać w następujących terminach:&lt;br /&gt;
* 2025.11.17	10:00 – 13:00	1.27komp. + 1.28komp.	Kolokwium I	&lt;br /&gt;
* 2026.01.12	10:00 – 13:00	1.29komp. + 1.28komp.	Kolokwium II&lt;br /&gt;
* 2026.01.26    10:00 – 13:00	1.27komp. + 1.28komp.	Kolokwium poprawkowe/dodatkowe dla osób, które nie mogły uczestniczyć w jednym ze standardowych terminów. Wiedza wymagana dotyczy tego samego zakresu materiału, który obowiązywał na I i II kolokwium łącznie.&lt;br /&gt;
&lt;br /&gt;
=== Materiały dostępne w czasie kolokwium ===&lt;br /&gt;
Jedynym materiałem dostępnym w trakcie trwania kolokwium jest oficjalna dokumentacja Python oraz własnoręczne notatki.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* '''Kolokwium poprawkowe: 27 stycznia 2020, 10:00-13, sale: 1.27, 1.28''' &lt;br /&gt;
Wiedza wymagana dotyczy tego samego zakresu materiału, który obowiązywał na I i II kolokwium łącznie.&lt;br /&gt;
W trakcie kolokwium możliwe jest poprawienie łącznej sumy punktów na kolokwia, czyli 20 pkt.&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/AS_Kolokwium_Poprawkowe_xxxx.ipynb AS_Kolokwium_Poprawkowe_xxxx.ipynb]&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/zad1_syg.bin zad1_syg.bin]&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/zad2_syg.bin zad2_syg.bin]&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/zad3_syg.bin zad3_syg.bin]&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/zad4_syg.bin zad4_syg.bin]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--[https://drive.google.com/drive/folders/0B7k6Z_ViZid5ZXNac0swalRuMkk?usp=sharing]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[STATLAB/kolokwium2_wymagania|Zakres wymagań do II kolokwium.]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Projekt ===&lt;br /&gt;
Wymagane będzie wykonanie jednego z projektów indywidualnych. Termin wykonania - 10 stycznia 2024. Projekty będą oceniane w procentach.&lt;br /&gt;
&lt;br /&gt;
# Pierwszy projekt [[STATLAB/Zadanie zaliczeniowe3|Analiza spektralna sygnału audio]] &lt;br /&gt;
&lt;br /&gt;
# Drugi projekt: [[Zjawisko ERDS]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
[[STATLAB/Zadanie_zaliczeniowe6| Detekcja wrzecion snu ]] &lt;br /&gt;
# Drugi projekt: [[STATLAB/Zadanie_zaliczeniowe5|Filtrowanie i przepróbkowanie sygnału]] należy oddać do końca zajęć dydaktycznych.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Praca w domu ===&lt;br /&gt;
Do większości  zajęć są przygotowane skrypty w jupyter-notebook.  Zawierają one opisy teoretyczne i fragmenty kodu. &lt;br /&gt;
&lt;br /&gt;
* Zadaniem studentów będzie '''przeczytanie ze zrozumieniem''' skryptu oraz '''uzupełnienie kodów w zadaniach'''. &lt;br /&gt;
* To co się liczy to '''próba samodzielnego rozwiązania''' zadania, lub '''sformułowanie konkretnego pytania'''  na temat zadania, które jest niezrozumiałe w notebooku.&lt;br /&gt;
* Rozwiązania i wątpliwości będą omawiane w trakcie zajęć.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Dodatkowo na platformie kampus będą pojawiać się zadania domowe do rozwiązania.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
=== Skala ocen ===&lt;br /&gt;
&amp;lt;!--Punkty z kolokwiów i projektów uśredniają się. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
W sesji porawkowej przewidujemy kolokwium poprawkowe umożliwiające poprawę obu kolokwiów.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Wynik procentowy z kolokwiów i kartkówek się sumuje w sposób ważony:&lt;br /&gt;
&lt;br /&gt;
''w = 0.2 k +0.8 x''&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
Wynik średni z kolokwiów przelicza się na ocenę z ćwiczeń:&lt;br /&gt;
# [50–60) %: 3.0 (dst)&lt;br /&gt;
# [60-70) %: 3.5 (dst+)&lt;br /&gt;
# [70-80) %: 4.0 (db)&lt;br /&gt;
# [80-90) %: 4.5 (db+)&lt;br /&gt;
# [100-90] %: 5.0 (bdb)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Nieobecności ===&lt;br /&gt;
Dozwolone są maksymalnie dwie nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 kilka dodatkowych funkcji, które zostały udostępnione na  [[STATLAB/ListaFunkcji|oddzielnej stronie]].&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
[[Analiza_sygnałów_-_ćwiczenia]]/Zasady zaliczenia&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=ZasadyZaliczenia&amp;diff=11435</id>
		<title>ZasadyZaliczenia</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=ZasadyZaliczenia&amp;diff=11435"/>
		<updated>2025-10-08T08:07:09Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Zasady zaliczenia ćwiczeń z Analizy Sygnałów */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Analiza_sygnałów_-_ćwiczenia]]/Zasady zaliczenia&lt;br /&gt;
&lt;br /&gt;
== Zasady zaliczenia ćwiczeń z [[Analiza_sygnałów - exercises|Analizy Sygnałów]] ==&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Kartkówki===&lt;br /&gt;
Na początku większości zajęć będą kartkówki. Z kartkówek można uzyskać ''k'' procent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
=== Kolokwia ===&lt;br /&gt;
W trakcie semestru odbędą się dwa kolokwia. Z każdego z nich będzie można uzyskać ''1/2 x'' procent, z czego do zaliczenia przedmiotu konieczne będzie zdobycie łącznie 50% z kolokwiów. Kolokwia będą wspólne dla wszystkich grup, będą się odbywać w następujących terminach:&lt;br /&gt;
* 2025.11.17	10:00 – 13:00	1.27komp. + 1.28komp.	Analiza Sygnałów	&lt;br /&gt;
* 2026.01.12	10:00 – 13:00	1.27komp. + 1.28komp.	Analiza Sygnałów&lt;br /&gt;
&lt;br /&gt;
=== Materiały dostępne w czasie kolokwium ===&lt;br /&gt;
Jedynym materiałem dostępnym w trakcie trwania kolokwium jest oficjalna dokumentacja Python oraz własnoręczne notatki.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* '''Kolokwium poprawkowe: 27 stycznia 2020, 10:00-13, sale: 1.27, 1.28''' &lt;br /&gt;
Wiedza wymagana dotyczy tego samego zakresu materiału, który obowiązywał na I i II kolokwium łącznie.&lt;br /&gt;
W trakcie kolokwium możliwe jest poprawienie łącznej sumy punktów na kolokwia, czyli 20 pkt.&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/AS_Kolokwium_Poprawkowe_xxxx.ipynb AS_Kolokwium_Poprawkowe_xxxx.ipynb]&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/zad1_syg.bin zad1_syg.bin]&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/zad2_syg.bin zad2_syg.bin]&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/zad3_syg.bin zad3_syg.bin]&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/zad4_syg.bin zad4_syg.bin]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--[https://drive.google.com/drive/folders/0B7k6Z_ViZid5ZXNac0swalRuMkk?usp=sharing]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[STATLAB/kolokwium2_wymagania|Zakres wymagań do II kolokwium.]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Projekt ===&lt;br /&gt;
Wymagane będzie wykonanie jednego z projektów indywidualnych. Termin wykonania - 10 stycznia 2024. Projekty będą oceniane w procentach.&lt;br /&gt;
&lt;br /&gt;
# Pierwszy projekt [[STATLAB/Zadanie zaliczeniowe3|Analiza spektralna sygnału audio]] &lt;br /&gt;
&lt;br /&gt;
# Drugi projekt: [[Zjawisko ERDS]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
[[STATLAB/Zadanie_zaliczeniowe6| Detekcja wrzecion snu ]] &lt;br /&gt;
# Drugi projekt: [[STATLAB/Zadanie_zaliczeniowe5|Filtrowanie i przepróbkowanie sygnału]] należy oddać do końca zajęć dydaktycznych.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Praca w domu ===&lt;br /&gt;
Do większości  zajęć są przygotowane skrypty w jupyter-notebook.  Zawierają one opisy teoretyczne i fragmenty kodu. &lt;br /&gt;
&lt;br /&gt;
* Zadaniem studentów będzie '''przeczytanie ze zrozumieniem''' skryptu oraz '''uzupełnienie kodów w zadaniach'''. &lt;br /&gt;
* To co się liczy to '''próba samodzielnego rozwiązania''' zadania, lub '''sformułowanie konkretnego pytania'''  na temat zadania, które jest niezrozumiałe w notebooku.&lt;br /&gt;
* Rozwiązania i wątpliwości będą omawiane w trakcie zajęć.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Dodatkowo na platformie kampus będą pojawiać się zadania domowe do rozwiązania.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
=== Skala ocen ===&lt;br /&gt;
&amp;lt;!--Punkty z kolokwiów i projektów uśredniają się. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
W sesji porawkowej przewidujemy kolokwium poprawkowe umożliwiające poprawę obu kolokwiów.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Wynik procentowy z kolokwiów i kartkówek się sumuje w sposób ważony:&lt;br /&gt;
&lt;br /&gt;
''w = 0.2 k +0.8 x''&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
Wynik średni z kolokwiów przelicza się na ocenę z ćwiczeń:&lt;br /&gt;
# [50–60) %: 3.0 (dst)&lt;br /&gt;
# [60-70) %: 3.5 (dst+)&lt;br /&gt;
# [70-80) %: 4.0 (db)&lt;br /&gt;
# [80-90) %: 4.5 (db+)&lt;br /&gt;
# [100-90] %: 5.0 (bdb)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Nieobecności ===&lt;br /&gt;
Dozwolone są maksymalnie dwie nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 kilka dodatkowych funkcji, które zostały udostępnione na  [[STATLAB/ListaFunkcji|oddzielnej stronie]].&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
[[Analiza_sygnałów_-_ćwiczenia]]/Zasady zaliczenia&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=ZasadyZaliczenia&amp;diff=11434</id>
		<title>ZasadyZaliczenia</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=ZasadyZaliczenia&amp;diff=11434"/>
		<updated>2025-10-08T08:05:10Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Kolokwia */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Analiza_sygnałów_-_ćwiczenia]]/Zasady zaliczenia&lt;br /&gt;
&lt;br /&gt;
== Zasady zaliczenia ćwiczeń z [[Analiza_sygnałów - exercises|Analizy Sygnałów]] ==&lt;br /&gt;
===Kartkówki===&lt;br /&gt;
Na początku większości zajęć będą kartkówki. Z kartkówek można uzyskać ''k'' procent.&lt;br /&gt;
&lt;br /&gt;
=== Kolokwia ===&lt;br /&gt;
W trakcie semestru odbędą się dwa kolokwia. Z każdego z nich będzie można uzyskać ''1/2 x'' procent, z czego do zaliczenia przedmiotu konieczne będzie zdobycie łącznie 50% z kolokwiów. Kolokwia będą wspólne dla wszystkich grup, będą się odbywać w następujących terminach:&lt;br /&gt;
* 2025.11.17	10:00 – 13:00	1.27komp. + 1.28komp.	Analiza Sygnałów	&lt;br /&gt;
* 2026.01.12	10:00 – 13:00	1.27komp. + 1.28komp.	Analiza Sygnałów&lt;br /&gt;
&lt;br /&gt;
=== Materiały dostępne w czasie kolokwium ===&lt;br /&gt;
Jedynym materiałem dostępnym w trakcie trwania kolokwium jest oficjalna dokumentacja Python oraz własnoręczne notatki.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* '''Kolokwium poprawkowe: 27 stycznia 2020, 10:00-13, sale: 1.27, 1.28''' &lt;br /&gt;
Wiedza wymagana dotyczy tego samego zakresu materiału, który obowiązywał na I i II kolokwium łącznie.&lt;br /&gt;
W trakcie kolokwium możliwe jest poprawienie łącznej sumy punktów na kolokwia, czyli 20 pkt.&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/AS_Kolokwium_Poprawkowe_xxxx.ipynb AS_Kolokwium_Poprawkowe_xxxx.ipynb]&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/zad1_syg.bin zad1_syg.bin]&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/zad2_syg.bin zad2_syg.bin]&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/zad3_syg.bin zad3_syg.bin]&lt;br /&gt;
** [https://www.fuw.edu.pl/~jarekz/KOLOKWIUM_AS/zad4_syg.bin zad4_syg.bin]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--[https://drive.google.com/drive/folders/0B7k6Z_ViZid5ZXNac0swalRuMkk?usp=sharing]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[STATLAB/kolokwium2_wymagania|Zakres wymagań do II kolokwium.]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Projekt ===&lt;br /&gt;
Wymagane będzie wykonanie jednego z projektów indywidualnych. Termin wykonania - 10 stycznia 2024. Projekty będą oceniane w procentach.&lt;br /&gt;
&lt;br /&gt;
# Pierwszy projekt [[STATLAB/Zadanie zaliczeniowe3|Analiza spektralna sygnału audio]] &lt;br /&gt;
&lt;br /&gt;
# Drugi projekt: [[Zjawisko ERDS]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
[[STATLAB/Zadanie_zaliczeniowe6| Detekcja wrzecion snu ]] &lt;br /&gt;
# Drugi projekt: [[STATLAB/Zadanie_zaliczeniowe5|Filtrowanie i przepróbkowanie sygnału]] należy oddać do końca zajęć dydaktycznych.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Praca w domu ===&lt;br /&gt;
Do większości  zajęć są przygotowane skrypty w jupyter-notebook.  Zawierają one opisy teoretyczne i fragmenty kodu. &lt;br /&gt;
&lt;br /&gt;
* Zadaniem studentów będzie '''przeczytanie ze zrozumieniem''' skryptu oraz '''uzupełnienie kodów w zadaniach'''. &lt;br /&gt;
* To co się liczy to '''próba samodzielnego rozwiązania''' zadania, lub '''sformułowanie konkretnego pytania'''  na temat zadania, które jest niezrozumiałe w notebooku.&lt;br /&gt;
* Rozwiązania i wątpliwości będą omawiane w trakcie zajęć.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Dodatkowo na platformie kampus będą pojawiać się zadania domowe do rozwiązania.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
=== Skala ocen ===&lt;br /&gt;
&amp;lt;!--Punkty z kolokwiów i projektów uśredniają się. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
W sesji porawkowej przewidujemy kolokwium poprawkowe umożliwiające poprawę obu kolokwiów.&lt;br /&gt;
&lt;br /&gt;
Wynik procentowy z kolokwiów i kartkówek się sumuje w sposób ważony:&lt;br /&gt;
&lt;br /&gt;
''w = 0.2 k +0.8 x''&lt;br /&gt;
&lt;br /&gt;
Wynik ''w'' przelicza się na ocenę z ćwiczeń:&lt;br /&gt;
# [50–60) %: 3.0 (dst)&lt;br /&gt;
# [60-70) %: 3.5 (dst+)&lt;br /&gt;
# [70-80) %: 4.0 (db)&lt;br /&gt;
# [80-90) %: 4.5 (db+)&lt;br /&gt;
# [100-90] %: 5.0 (bdb)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Nieobecności ===&lt;br /&gt;
Dozwolone są maksymalnie dwie nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 kilka dodatkowych funkcji, które zostały udostępnione na  [[STATLAB/ListaFunkcji|oddzielnej stronie]].&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
[[Analiza_sygnałów_-_ćwiczenia]]/Zasady zaliczenia&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Uczenie_maszynowe_i_sztuczne_sieci_neuronowe&amp;diff=11418</id>
		<title>Uczenie maszynowe i sztuczne sieci neuronowe</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Uczenie_maszynowe_i_sztuczne_sieci_neuronowe&amp;diff=11418"/>
		<updated>2025-10-01T14:20:19Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Przedmioty specjalizacyjne]]&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Uwaga: ta strona ma charakter historyczny. Aktualna wersja wykładu jest na stronie&amp;lt;/big&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
https://kampus-kursy.ckc.uw.edu.pl/course/view.php?id=5184&lt;br /&gt;
&lt;br /&gt;
[[Zasady zaliczenia| Zasady zaliczenia ]]&lt;br /&gt;
&lt;br /&gt;
[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/konfiguracja|Konfiguracja środowiska]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Przejście do: [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe_cw|Ćwiczeń]]&lt;br /&gt;
&lt;br /&gt;
=Wykłady=&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 1|Wstęp, regresja liniowa i metoda najmniejszych kwadratów]] [https://drive.google.com/open?id=0BzwQ_Lscn8yDUTFmVnJ1QXpuVGs (wersja w notebooku)]&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 6|Klasyfikacja i regresja logistyczna]] [https://drive.google.com/open?id=0BzwQ_Lscn8yDZ3lxUkFCeUxmUlE (wersja w notebooku)]&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład Ocena jakości klasyfikacji|Ocena jakości klasyfikacji]] [https://drive.google.com/open?id=0BzwQ_Lscn8yDQ3Vpbnd2U2pOd0k (wersja w notebooku)] &lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 7|Algorytmy generatywne]] [https://drive.google.com/open?id=0BzwQ_Lscn8yDNUpWYTdycWVLa0E (wersja w notebooku)]&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 8|Maszyny wektorów wspierających I]] [https://drive.google.com/open?id=0BzwQ_Lscn8yDQ3poLWdZOG90c2M (wersja w notebooku)]&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 9|Maszyny wektorów wspierających II]] [https://drive.google.com/open?id=0BzwQ_Lscn8yDQVplcGo3bmllODA (wersja w notebooku)]&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/DrzewaDecyzyjne|Drzewa decyzyjne]][https://drive.google.com/open?id=0BzwQ_Lscn8yDLU1wUFBsRURzWEk (wersja w notebooku)]&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 10|Uczenie bez nadzoru]] [https://drive.google.com/open?id=0BzwQ_Lscn8yDaC0wZWJuRUdIMk0 (wersja w notebooku)]&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 2|Wstęp o sieciach neuronowych, sieci neuronowe liniowe.]]  /  [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 3|Perceptron Rosenblatta.]] [https://drive.google.com/open?id=0BzwQ_Lscn8yDYWFkUTJxU1ZTcHc (wersja w notebooku)]&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 4|Nieliniowości różniczkowalne i metoda wstecznej propagacji błędu]] [https://drive.google.com/open?id=0BzwQ_Lscn8yDWTR6TTVfTlJjNUU (wersja w notebooku)]&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 5|Wsteczna propagacja błędu: jak poprawić zbieżność?]] [https://drive.google.com/open?id=0BzwQ_Lscn8yDdDRJbmhVdFFLQWs (wersja w notebooku)]&lt;br /&gt;
#[https://drive.google.com/open?id=0BzwQ_Lscn8yDRHFhcmZIRTlHU2M Sieci konwolucyjne] [https://drive.google.com/open?id=0BzwQ_Lscn8yDNjgxZTkyNFppRGs (wersja w notebooku)]&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 11|Uczenie ze wzmocnieniem]] [https://drive.google.com/open?id=15n9lM2OdT9TZVS_pfn7x_xswPeuy_r0Q (wersja w notebooku)]&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 12|Uczenie ze wzmocnieniem cz.2]] [https://drive.google.com/open?id=17YVwJ479qn74B_n2v_IlCv9dyCSQt5Wa  (wersja w notebooku)]&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! &lt;br /&gt;
! Wykłady&lt;br /&gt;
! Ćwiczenia&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 1|Wstęp, regresja liniowa i metoda najmniejszych kwadratów]] [https://drive.google.com/file/d/0BzwQ_Lscn8yDUTFmVnJ1QXpuVGs/view?usp=sharing&amp;amp;resourcekey=0-VTr-BMBrfkYGI0sGhTJ8Pg (wersja w notebooku)]&lt;br /&gt;
| [https://drive.google.com/file/d/1E4W5j8Z5yxfe0n804I8zJIM1QyQs-oZK/view?usp=sharing Powtórka numpy]&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
|&lt;br /&gt;
| [https://drive.google.com/file/d/1P86RKJfMFU54xYT9umP7fwCRF800iC0v/view?usp=sharing Regresja liniowa].&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 6|Klasyfikacja i regresja logistyczna]] [https://drive.google.com/file/d/11JKqVTSjeQNSUSkzhHZEML5hrggDJx8b/view?usp=sharing (wersja w notebooku)]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [https://drive.google.com/file/d/11JKqVTSjeQNSUSkzhHZEML5hrggDJx8b/view?usp=sharing Ćwiczenie regresji logistycznej]&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład Ocena jakości klasyfikacji|Ocena jakości klasyfikacji]] [https://drive.google.com/file/d/0BzwQ_Lscn8yDQ3Vpbnd2U2pOd0k/view?usp=sharing&amp;amp;resourcekey=0-lba-gcj-vx584pcxqMzkuw (wersja w notebooku)]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [https://drive.google.com/file/d/1UYCo2wuC8BHnssZJRBZJfyvdQFsmwS1O/view?usp=sharing Ćwiczenie z miarami jakości]&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 7|Algorytmy generatywne]] [https://drive.google.com/file/d/0BzwQ_Lscn8yDNUpWYTdycWVLa0E/view?usp=sharing&amp;amp;resourcekey=0-Kd3aqboblVwFrkp5KXn4uQ (wersja w notebooku)]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [https://drive.google.com/file/d/17T3h2QUwCJA7QqnC-IHuIQeEBOZ8kJqW/view?usp=sharing Ćwiczenie z  klasyfikacji bayesowskiej] &amp;lt;br&amp;gt; [https://drive.google.com/file/d/1mO64cJnEWJ98K8NTvGHfI1rA7fEb2DLi/view?usp=sharing Ćwiczenie z klasyfikacji tekstów za pomocą klasyfikacji bayesowskiej (notebook)]&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 8|Maszyny wektorów wspierających I]] [https://drive.google.com/file/d/0BzwQ_Lscn8yDQ3poLWdZOG90c2M/view?usp=sharing&amp;amp;resourcekey=0-uuk3FrTQiAentJixVjaeZA (wersja w notebooku)]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [https://drive.google.com/file/d/1QTOK6B8jPrP3J7NW2I93q3WZJ1CAWN_H/view?usp=sharing Klasyfikacja z użyciem SVM]&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 9|Maszyny wektorów wspierających II]] [https://drive.google.com/file/d/0BzwQ_Lscn8yDQVplcGo3bmllODA/view?usp=sharing&amp;amp;resourcekey=0-TE8SmXSjQHeZvMQX7qbSYA (wersja w notebooku)]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/SVM2 | Klasyfikacja z użuciem SVM 2]]&lt;br /&gt;
|-&lt;br /&gt;
| 7&lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/DrzewaDecyzyjne|Drzewa decyzyjne]][https://drive.google.com/file/d/0BzwQ_Lscn8yDLU1wUFBsRURzWEk/view?usp=sharing&amp;amp;resourcekey=0-1F1twtCbJV6UAfO537IbmA (wersja w notebooku)]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wybor_cech |Wybor optymalnych cech]]&lt;br /&gt;
&lt;br /&gt;
[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/DrzewaDecyzyjne_cw|Drzewa decyzyjne]] [https://drive.google.com/file/d/1hvGjF1fofv0tBNfZj5-eD2gYF94CqFTf/view?usp=sharing Drzewa decyzyjne (notebook)]&lt;br /&gt;
|-&lt;br /&gt;
| 8&lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 10|Uczenie bez nadzoru]] [https://drive.google.com/file/d/0BzwQ_Lscn8yDaC0wZWJuRUdIMk0/view?usp=sharing&amp;amp;resourcekey=0-n9MM42-AMfRRToEyBYpv3w (wersja w notebooku)]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Ćwiczenia 11|Uczenie bez nadzoru i analiza skupień]]  [https://drive.google.com/file/d/1hNxYTzh541JhFoaYbo3Pc6LHnzsrsMX6/view?usp=sharing notebook]&lt;br /&gt;
|-&lt;br /&gt;
| 9&lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 2|Wstęp o sieciach neuronowych, sieci neuronowe liniowe.]],/,[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 3|Perceptron Rosenblatta.]] [https://drive.google.com/file/d/13CG5kuEKV1riA8vhBfMxGfCpECJCh-ql/view?usp=sharing (wersja w notebooku)]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Ćwiczenia 4|Nieliniowe sieci neuronowe: problem XOR]]&lt;br /&gt;
&lt;br /&gt;
[https://drive.google.com/file/d/1B7nS1zs2begRPK6ye2IH4p__sZDccLs_/view?usp=sharing Sieci głębokie (notebook)]&lt;br /&gt;
|-&lt;br /&gt;
| 10&lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 4|Nieliniowości różniczkowalne i metoda wstecznej propagacji błędu]] [https://drive.google.com/file/d/0BzwQ_Lscn8yDdDRJbmhVdFFLQWs/view?usp=sharing&amp;amp;resourcekey=0-LeOlls1dq7lJVs7Cw_h4Xw (wersja w notebooku)]&lt;br /&gt;
&lt;br /&gt;
[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 5|Wsteczna propagacja błędu: jak poprawić zbieżność?]] [https://drive.google.com/open?id=0BzwQ_Lscn8yDdDRJbmhVdFFLQWs (wersja w notebooku)]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [https://drive.google.com/open?id=1hU0nVe6l9ubPbHFgRoMGn2PRGAhAnQCu Regresja nielinowa implementacja w keras(notebook)]&lt;br /&gt;
|-&lt;br /&gt;
| 11&lt;br /&gt;
|  [https://drive.google.com/file/d/0BzwQ_Lscn8yDNjgxZTkyNFppRGs/view?usp=sharing&amp;amp;resourcekey=0-_KtF79jjjKe4Bw_tGcs-lw Sieci konwolucyjne (wersja w notebooku)]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [https://drive.google.com/file/d/1MX6CSJH7bQ6dcsulN3kyit4SgKtGUlTj/view?usp=sharing Augmentacja danych]&amp;lt;br&amp;gt;[https://drive.google.com/open?id=13MNs6R9le49DfexN6rnIsgVQlixJMJ0Z Porównanie kalsyfikacji cyfr za pomoca sieci gęstej i głębokiej (notebook)]&lt;br /&gt;
|-&lt;br /&gt;
| 12&lt;br /&gt;
| [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 11|Uczenie ze wzmocnieniem]] [https://drive.google.com/file/d/15n9lM2OdT9TZVS_pfn7x_xswPeuy_r0Q/view?usp=sharing (wersja w notebooku)]&lt;br /&gt;
&lt;br /&gt;
[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład 12|Uczenie ze wzmocnieniem cz.2]] [https://drive.google.com/file/d/17YVwJ479qn74B_n2v_IlCv9dyCSQt5Wa/view?usp=sharing,(wersja w notebooku)]&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [https://drive.google.com/open?id=18j357je8pSXi3SOYZgK1qp1KWrMsEc2Z Uczenie ze wzmocnieniem (notebook)]&lt;br /&gt;
|-&lt;br /&gt;
| 13 &lt;br /&gt;
|&lt;br /&gt;
[https://drive.google.com/file/d/1nO8QiHru6CE_txzUrBj4N9qhCLGlLvUE/view?usp=sharing Interpretacja i wyjaśnianie decyzji podejmowanych przez sieci ] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://brain.fuw.edu.pl/edu/images/2/2a/Zastosowania_DNN_do_analizy_EEG.pdf Zastosowanie sieci do analizy danych EEG]&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [https://drive.google.com/file/d/1mAspITelZmAMZP3JkghETcB7UbIbEt5x/view?usp=sharing Interpretowalne ML]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Powtórka=&lt;br /&gt;
#[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Pytania| Zagadnienia do powtórki]]&lt;br /&gt;
=Projekty=&lt;br /&gt;
[[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Projekty|Projekty]]&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Analiza_sygna%C5%82%C3%B3w_-_%C4%87wiczenia&amp;diff=11356</id>
		<title>Analiza sygnałów - ćwiczenia</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Analiza_sygna%C5%82%C3%B3w_-_%C4%87wiczenia&amp;diff=11356"/>
		<updated>2025-07-31T18:07:46Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Przedmioty specjalizacyjne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[ZasadyZaliczenia|Zasady zaliczenia ćwiczeń]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dla grupy o 10:15 link do podłączania się: Analiza Sygnałów &lt;br /&gt;
https://meet.google.com/inx-rxqe-fku&lt;br /&gt;
&lt;br /&gt;
# [https://drive.google.com/file/d/1Cr8CCPoh_G-iAq8x2Bm0YxwAcsrNwqir/view?usp=sharing Sygnały AS_1.ipynb]  [https://drive.google.com/file/d/1J_7pyTO00r-OyhyrMd1v_dAoiIU0C-3k/view?usp=sharing notebook wypełniony]&lt;br /&gt;
#  [https://colab.research.google.com/drive/1y81wGZHwpUf4J6IIApPdqahgUN9Bad0p?usp=sharing Transformata Fouriera 1 (FFT) AS2_Transformata_fouriera.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/18nU5rWKinO697M3Pgnp6luiC-NcBYD-9?usp=sharing Transformata Fouriera 2 AS3_Transformata_fouriera_2.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1b6djG2_uE_yc0-QEyD1Yl-dd8Ezelf2m?usp=sharing Okienkowanie AS4_okienkowanie.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1Lr-fkC4oFl2Tf4Y2w2w27bARpvwWRSmG?usp=sharing Estymacja widma mocy AS5_Widmo_mocy.ipynb ] &lt;br /&gt;
# kontynuacja notebook AS5&lt;br /&gt;
#[https://colab.research.google.com/drive/1mKjXYKICL1vp5z0MpWrfM8JuXCDlc_HK?usp=sharing Model AR AS6_1_ProcesyAR.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1NRzWBr5j5YzwfaZDwJC5yaPEVgi6rc6U?usp=sharing Estymacja parametryczna widma procesu AS6_2_Widmo_Procesu_AR.ipynb]&lt;br /&gt;
#[https://colab.research.google.com/drive/1e8_SIPFqAJA7WGsPiWudplubHtrgkSq0?usp=sharing Filtry notebook7] &lt;br /&gt;
# kontynuacja notebook7  -&amp;gt; notebook z grupy porannej: https://colab.research.google.com/drive/1bBzlxf7krP7KI_SYIgZLMPfD0bnleXVo?usp=sharing&lt;br /&gt;
#[https://drive.google.com/file/d/1Ey1yYgVMbu3n9djb2LzPZ4dT03gYFcAw/view?usp=sharing Metody czas-częstość STFT i falki: notebook8]      &amp;lt;br&amp;gt;[https://drive.google.com/open?id=0BzwQ_Lscn8yDdUlLVXp1XzF0elE notebook 10] &amp;lt;br&amp;gt;lektura uzupełniająca: [https://www.math.ucdavis.edu/~saito/data/sonar/boashash1.pdf  Estimating and Interpreting The Instantaneous Frequency of a Signal-Part 1: Fundamentals ]&lt;br /&gt;
# [https://drive.google.com/file/d/13Jvt1po_Brk49fRe-dOxOvVfRz1VVieW/view?usp=sharing Notebook o metodzie MP]&lt;br /&gt;
&lt;br /&gt;
== Materiały pomocnicze do samokształcenia: ==&lt;br /&gt;
&lt;br /&gt;
* Zbiór zadań z Analizy sygnałów wraz z rozwiązaniami przygotowany w ramach Projektu zespołowego przez Monikę Tutaj i Marcina Syca pod kierunkiem mgr. Piotra Biegańskiego https://www.fuw.edu.pl/~jarekz/ZadaniaAS/Zadania_Analiza_Sygnałów.zip&lt;br /&gt;
* Zbiór zadań z pythona, które mają na celu pomoc w opanowaniu podstaw Pythona, ze szczególnym naciskiem na rozwinięcie kompetencji potrzebnych w analizie sygnałów, takich jak: pogłębiona znajomość biblioteki numpy, praca z plikami multipleksowanymi, wykorzystanie Pythona jako narzędzia do analizy danych. https://gitlab.com/pbieganski/podstawy-pythona&lt;br /&gt;
* Notatnik z kolokwium poprawkowym 2025: https://colab.research.google.com/drive/1_DQ7rG7aIMq_XgkPZIM4bGAAf8VlFVGc?usp=sharing&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
https://colab.research.google.com/drive/1WZwnu_YgmsRfBdC6Oy5AHULT6b4RInn5?usp=sharing&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1IlY0KsqxMuW7s-Aic_hnChc5sN7QCIgL/view?usp=sharing &lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Okladka.jpeg|thumb|upright=0.25| Dostępna w bibliotece]] W bibliotece Wydziału Fizyki dostępne są książki: Practical biomedical signal analysis using Matlab / K. J. Blinowska J. Żygierewicz. (katalog: https://chamo.buw.uw.edu.pl:8443/lib/item?id=chamo:895791&amp;amp;fromLocationLink=false&amp;amp;theme=system)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Materiały dodatkowe: ==&lt;br /&gt;
&lt;br /&gt;
[https://www.youtube.com/playlist?list=PLXJDR4jmaWX795PLOwLt5pR59H2BrZAsK playlista na YouTube z filmami nagranymi w czasie zdalnych ćwiczeń w roku 2020/21]&lt;br /&gt;
&lt;br /&gt;
[https://tftb.nongnu.org/tutorial.pdf Tutorial o technikach analizy czas-częstość]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Przed kolokwium 1&lt;br /&gt;
# [[kolokwia2014_2015_kol1|Zagadnienia przygotowawcze do 1 kolokwium]] &lt;br /&gt;
# [https://drive.google.com/open?id=1RKIHgfuqtBvg65PUpIuQI3rYeyvdIXMi zadania powtórzeniowe do kolokwium  1]&lt;br /&gt;
&lt;br /&gt;
autorzy: Jarosław Żygierewicz, Maciej Kamiński, Magdalena Zieleniewska, wersja z notebookami Jan Mąka i Piotr Biegański&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== INFORMACJE DODATKOWE ==&lt;br /&gt;
Materiały 2014/2015&lt;br /&gt;
# [[kolokwia2013_2014|Informacje o zaliczeniu ćwiczeń]] &lt;br /&gt;
# [[kolokwia2014_2015_kol1|Zagadnienia przygotowawcze do 1 kolokwium]] &lt;br /&gt;
# [[Projekt2014|Projekt zaliczeniowy]]&lt;br /&gt;
&lt;br /&gt;
Materiały 2013/2014&lt;br /&gt;
# [[Plik:Zadania_powtorzeniowe.pdf|Zadania powtorzeniowe do 2 kolokwium]]&lt;br /&gt;
&lt;br /&gt;
#[[Systemy liniowe niezmiennicze w czasie | Systemy liniowe niezmiennicze w czasie]]&lt;br /&gt;
[[Ćwiczenia 8|Filtrowanie obrazów]]&lt;br /&gt;
[[Ćwiczenia 9|Analiza czas-częstość]]&lt;br /&gt;
[[Ćwiczenia 10|Analiza czas-częstość &amp;amp;mdash; STFT i transformata falkowa]]&lt;br /&gt;
[[Ćwiczenia 11|Analiza czas-częstość &amp;amp;mdash; reprezentacje energetyczne]]&lt;br /&gt;
#[[AS cwiczenia ICA| ICA]] montaże, ICA &lt;br /&gt;
#[[AS cwiczenia DTF| DTF]]wielokanałowy AR , DTF &lt;br /&gt;
&lt;br /&gt;
#[[AS cwiczeniaMP|Matching pursuit]] MP w Svarogu, zabawa parametrami dekompozycji, zabawa filtrowaniem map w Svarogu, postprocessing w Pythonie &lt;br /&gt;
&lt;br /&gt;
# Uśrednianie gęstości energii vs gęstość energii uśrednionego sygnału: symulacje, ERD/S&lt;br /&gt;
#[[Ćwiczenia UNIFIKACJA]] ostatnie ćwiczenia na ktrych porównujemy na tych samych sygnałach rzeczywistych i symulowanych działanie różnych metod -- MMP vs DTF vs ICA, STFT vs WT vs MP itp, potrzebne fajne przykłady&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11344</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11344"/>
		<updated>2025-05-16T09:26:46Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2025: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Wprowadzenie]]&lt;br /&gt;
## 28.02.2025 &lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|EKG]] &lt;br /&gt;
## 07.03.2025 - Wstęp teoretyczny i pomiary&lt;br /&gt;
## 14.03.2025 - detekcja pików R i tętno&lt;br /&gt;
## 21.03.2025 - analiza HRV&lt;br /&gt;
przesyłanie notebooków z EKG/HRV do 4.04&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|EMG]]&lt;br /&gt;
## 28.03.2025 - wprowadzenie, pomiary, analiza ćwiczenie I&lt;br /&gt;
## 4.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 11.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 25.04.2025 - analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III -&amp;gt; przesyłanie notebooków z EMG do 16.05&lt;br /&gt;
## 07.05.2025 - seminarium SYNCC IN &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]]&lt;br /&gt;
## 16.05.2025 - podstawowe własności EOG - rejestracja&lt;br /&gt;
## 23.05.2025 - podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 06.06&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
## 30.05.2025 - [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
## 06.06.2025 - [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## 13.06.2025&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11341</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11341"/>
		<updated>2025-05-15T14:05:57Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2025: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Wprowadzenie]]&lt;br /&gt;
## 28.02.2025 &lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|EKG]] &lt;br /&gt;
## 07.03.2025 - Wstęp teoretyczny i pomiary&lt;br /&gt;
## 14.03.2025 - detekcja pików R i tętno&lt;br /&gt;
## 21.03.2025 - analiza HRV&lt;br /&gt;
przesyłanie notebooków z EKG/HRV do 4.04&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|EMG]]&lt;br /&gt;
## 28.03.2025 - wprowadzenie, pomiary, analiza ćwiczenie I&lt;br /&gt;
## 4.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 11.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 25.04.2025 - analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III -&amp;gt; przesyłanie notebooków z EMG do 16.05&lt;br /&gt;
## 07.05.2025 - seminarium SYNCC IN &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]]&lt;br /&gt;
## 16.05.2025 - podstawowe własności EOG - rejestracja&lt;br /&gt;
## 23.05.2025 - podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 30.05&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
## 30.05.2025 - [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
## 06.06.2025 - [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## 13.06.2025&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11261</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11261"/>
		<updated>2025-04-25T07:46:23Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Analiza */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
W wyniku aktywacji mięśnia, ulega on skróceniu, co powoduje przemieszczanie się względem siebie mięśnia, skóry i elektrody. Przemieszczenie to powoduje zmianę amplitudy mierzonego sygnału (np. elektroda oddala się od mięśnia), zmianę potencjału DC (potencjału powstającego na granicy skóra-elektrolit) oraz rozciągniecie skóry. Jak pamiętamy z pierwszych zajęć&lt;br /&gt;
pomiędzy naskórkiem a skórą właściwą istnieje różnica potencjałów o amplitudzie dochodzącej do 30 mV. W trakcie rozciągania skóry, wartość to spada do 25 mV. Powstająca zmiana potencjału, o wartości około 5 mV jest w porównaniu z sygnałem EMG bardzo znacząca.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będzie to 100 Hz, 150 Hz, 200 Hz, itd). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz należy zadbać o niską impedancję pomiędzy elektrodą a skóra oraz powinno mierzyć się sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne, wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z Prawem Indukcji Faraday'a zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. Innym rozwiązaniem tego problemu jest zastosowanie kabli ekranowanych. Kable TMSI, których używamy na Pracowni są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu, zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo, aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* umieść elektrodę GND na wewnętrznej części przedramienia, w połowie jego długości,&lt;br /&gt;
* umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie po około 5 s napinasz i rozluźniasz biceps lub ściskasz i rozluźniasz pięść (dla badania mięśnia przedramienia).&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak aby rodzielczość częstotliwościowa była 1Hz.&lt;br /&gt;
** Przedstaw mapę czas-częstość (rozważ spectrogram i scalogram - czy któraś z technik jest tu lepsza?) dla całego zapisu. Zaobserwuj jakie zmiany następują w widmie wraz ze wzrostem obciążenia.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia:&lt;br /&gt;
** Przedstaw mapę czas-częstość dla całego czasu rejestracji. Zaobserwuj jakie zmiany następują w widmie wraz z czasem.&lt;br /&gt;
** Przedstaw ewolucję czasową środka ciężkości widma częstości&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11260</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11260"/>
		<updated>2025-04-25T07:26:09Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Analiza */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
W wyniku aktywacji mięśnia, ulega on skróceniu, co powoduje przemieszczanie się względem siebie mięśnia, skóry i elektrody. Przemieszczenie to powoduje zmianę amplitudy mierzonego sygnału (np. elektroda oddala się od mięśnia), zmianę potencjału DC (potencjału powstającego na granicy skóra-elektrolit) oraz rozciągniecie skóry. Jak pamiętamy z pierwszych zajęć&lt;br /&gt;
pomiędzy naskórkiem a skórą właściwą istnieje różnica potencjałów o amplitudzie dochodzącej do 30 mV. W trakcie rozciągania skóry, wartość to spada do 25 mV. Powstająca zmiana potencjału, o wartości około 5 mV jest w porównaniu z sygnałem EMG bardzo znacząca.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będzie to 100 Hz, 150 Hz, 200 Hz, itd). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz należy zadbać o niską impedancję pomiędzy elektrodą a skóra oraz powinno mierzyć się sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne, wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z Prawem Indukcji Faraday'a zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. Innym rozwiązaniem tego problemu jest zastosowanie kabli ekranowanych. Kable TMSI, których używamy na Pracowni są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu, zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo, aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* umieść elektrodę GND na wewnętrznej części przedramienia, w połowie jego długości,&lt;br /&gt;
* umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie po około 5 s napinasz i rozluźniasz biceps lub ściskasz i rozluźniasz pięść (dla badania mięśnia przedramienia).&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak aby rodzielczość częstotliwościowa była 1Hz.&lt;br /&gt;
** Przedstaw mapę czas-częstość (rozważ spectrogram i scalogram - czy któraś z technik jest tu lepsza?) dla całego zapisu. Zaobserwuj jakie zmiany następują w widmie wraz ze wzrostem obciążenia.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia:&lt;br /&gt;
** Przedstaw mapę czas-częstość dla całego czasu rejestracji. Zaobserwuj jakie zmiany następują w widmie wraz z czasem.&lt;br /&gt;
** Przedstaw ewolucję czasową mediany częstości widma&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11259</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11259"/>
		<updated>2025-04-25T06:40:32Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2025: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Wprowadzenie]]&lt;br /&gt;
## 28.02.2025 &lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|EKG]] &lt;br /&gt;
## 07.03.2025 - Wstęp teoretyczny i pomiary&lt;br /&gt;
## 14.03.2025 - detekcja pików R i tętno&lt;br /&gt;
## 21.03.2025 - analiza HRV&lt;br /&gt;
przesyłanie notebooków z EKG/HRV do 4.04&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|EMG]]&lt;br /&gt;
## 28.03.2025 - wprowadzenie, pomiary, analiza ćwiczenie I&lt;br /&gt;
## 4.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 11.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 25.04.2025 - analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III -&amp;gt; przesyłanie notebooków z EMG do 16.05&lt;br /&gt;
## 07.05.2025 - seminarium SYNCC IN &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]]&lt;br /&gt;
## 16.05.2025 - podstawowe własności EOG - rejestracja&lt;br /&gt;
## 23.05.2025 - podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 24.05&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
## 30.05.2025 - [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
## 06.06.2025 - [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## 13.06.2025&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11258</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11258"/>
		<updated>2025-04-25T06:39:32Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
W wyniku aktywacji mięśnia, ulega on skróceniu, co powoduje przemieszczanie się względem siebie mięśnia, skóry i elektrody. Przemieszczenie to powoduje zmianę amplitudy mierzonego sygnału (np. elektroda oddala się od mięśnia), zmianę potencjału DC (potencjału powstającego na granicy skóra-elektrolit) oraz rozciągniecie skóry. Jak pamiętamy z pierwszych zajęć&lt;br /&gt;
pomiędzy naskórkiem a skórą właściwą istnieje różnica potencjałów o amplitudzie dochodzącej do 30 mV. W trakcie rozciągania skóry, wartość to spada do 25 mV. Powstająca zmiana potencjału, o wartości około 5 mV jest w porównaniu z sygnałem EMG bardzo znacząca.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będzie to 100 Hz, 150 Hz, 200 Hz, itd). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz należy zadbać o niską impedancję pomiędzy elektrodą a skóra oraz powinno mierzyć się sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne, wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z Prawem Indukcji Faraday'a zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. Innym rozwiązaniem tego problemu jest zastosowanie kabli ekranowanych. Kable TMSI, których używamy na Pracowni są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu, zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo, aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* umieść elektrodę GND na wewnętrznej części przedramienia, w połowie jego długości,&lt;br /&gt;
* umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie po około 5 s napinasz i rozluźniasz biceps lub ściskasz i rozluźniasz pięść (dla badania mięśnia przedramienia).&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak aby rodzielczość częstotliwościowa była 1Hz.&lt;br /&gt;
** Przedstaw mapę czas-częstość (rozważ spectrogram i scalogram - czy któraś z technik jest tu lepsza?) dla całego zapisu. Zaobserwuj jakie zmiany następują w widmie wraz ze wzrostem obciążenia.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia:&lt;br /&gt;
** Przedstaw mapę czas-częstość dla całego czasu rejestracji. Zaobserwuj jakie zmiany następują w widmie wraz z czasem.&lt;br /&gt;
** Przedstaw ewolucję czasową mediany widma&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11257</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11257"/>
		<updated>2025-04-25T06:38:15Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
W wyniku aktywacji mięśnia, ulega on skróceniu, co powoduje przemieszczanie się względem siebie mięśnia, skóry i elektrody. Przemieszczenie to powoduje zmianę amplitudy mierzonego sygnału (np. elektroda oddala się od mięśnia), zmianę potencjału DC (potencjału powstającego na granicy skóra-elektrolit) oraz rozciągniecie skóry. Jak pamiętamy z pierwszych zajęć&lt;br /&gt;
pomiędzy naskórkiem a skórą właściwą istnieje różnica potencjałów o amplitudzie dochodzącej do 30 mV. W trakcie rozciągania skóry, wartość to spada do 25 mV. Powstająca zmiana potencjału, o wartości około 5 mV jest w porównaniu z sygnałem EMG bardzo znacząca.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będzie to 100 Hz, 150 Hz, 200 Hz, itd). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz należy zadbać o niską impedancję pomiędzy elektrodą a skóra oraz powinno mierzyć się sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne, wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z Prawem Indukcji Faraday'a zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. Innym rozwiązaniem tego problemu jest zastosowanie kabli ekranowanych. Kable TMSI, których używamy na Pracowni są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu, zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo, aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* umieść elektrodę GND na wewnętrznej części przedramienia, w połowie jego długości,&lt;br /&gt;
* umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie po około 5 s napinasz i rozluźniasz biceps lub ściskasz i rozluźniasz pięść (dla badania mięśnia przedramienia).&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak aby rodzielczość częstotliwościowa była 1Hz.&lt;br /&gt;
** Przedstaw mapę czas-częstość (rozważ spectrogram i scalogram - czy któraś z technik jest tu lepsza?) dla całego zapisu. Zaobserwuj jakie zmiany następują w widmie wraz ze wzrostem obciążenia.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia:&lt;br /&gt;
** Przedstaw mapę czas-częstość dla całego czasu rejestracji. Zaobserwuj jakie zmiany następują w widmie wraz z czasem.&lt;br /&gt;
** Przedstaw ewolucję czasową mediany widma&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11256</id>
		<title>Pracownia Sygnałów Biologicznych/Zajecia 5 6</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Biologicznych/Zajecia_5_6&amp;diff=11256"/>
		<updated>2025-04-25T06:37:42Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Pracownia Sygnałów Bioelektrycznych]]/EMG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Pomiar EMG&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Wstęp==&lt;br /&gt;
[https://www.youtube.com/watch?v=w_R5t2-C5cA Filmik ilustrujący działanie mięśni]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sygnały elektro-fizjologiczne pochodzące z mięśni nazywa się elektromiogramem (EMG). &lt;br /&gt;
Elektromiografia jest jednym z podstawowych badań w rozpoznawaniu chorób mięśni i nerwów obwodowych. Ma ona również wiele zastosowań naukowych. Amplituda sygnału EMG wynosi od około kilkudziesięciu &amp;amp;mu;V do 10 mV, zaś pasmo sygnału obejmuje zakres częstości od 2 do 5000 Hz, przy czym największa energia sygnału znajduje się w przedziale od 50 do 150 Hz.&lt;br /&gt;
&lt;br /&gt;
Istnieją dwa sposoby pomiaru sygnałów EMG &amp;amp;mdash; badanie igłowe i powierzchniowe. W badaniu igłowym EMG, elektroda igłowa lub igła z dwoma elektrodami wbijana jest w mięsień lub w nerw ruchowy. Następnie obserwuje się aktywność elektryczną mięśni w spoczynku i podczas wysiłku.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Electromyogram.png|250px|thumb|right|&amp;lt;figure id=&amp;quot;fig:Electromyogram&amp;quot;&amp;gt;&amp;lt;/figure&amp;gt; Przykłady elektromiogramów. Panel górny &amp;amp;mdash; pacjent zdrowy. Panel środkowy &amp;amp;mdash; pacjent ze zmianami w nerwach obwodowych (neuropatia). Panel dolny &amp;amp;mdash; pacjent ze zmianami w mięśniach (miopatia).]]&lt;br /&gt;
&lt;br /&gt;
Badanie powierzchniowe EMG wykonuje się z użyciem elektrod samoprzylepnych, umieszczonych na powierzchni skóry, zwykle elektrody bipolarne są rozmieszczone na linii równoległej do włókien. Ocenie podlegają mięśnie położone powierzchownie lub grupy mięśni. &lt;br /&gt;
Obydwie metody mają swoje wady i zalety. Metoda &amp;amp;bdquo;igłowa&amp;amp;rdquo; umożliwia rejestrację sygnału EMG z wybranego mięśnia, podczas gdy metoda powierzchniowa rejestruje zbiorczą aktywność wielu jednostek ruchowych. Jednakże, w przeciwieństwie do metody powierzchniowej, metoda igłowa jest badaniem inwazyjnym i czasem bolesnym, które wykonywane jest w ośrodku klinicznym. &lt;br /&gt;
&lt;br /&gt;
Na zajęciach przeprowadzimy powierzchniowy pomiar EMG (w literaturze często takie badanie oznacza się skrótem sEMG, ''s'' od ang. ''surface'' &amp;amp;mdash; powierzchnia). W tym celu umieścimy elektrody na skórze, nad mięśniami, których aktywność chcemy zbadać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://youtu.be/afHpvABLCTo Filmik o zastosowaniach klinicznych EMG]&lt;br /&gt;
&lt;br /&gt;
Lektura uzupełniająca: Reaz MBI, Hussain MS and Mohd-Yasin F. Techniques of EMG signal analysis: detection, processing, classification and applications. Biol. Proced. Online 2006; 8(1): 11-35. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1455479/pdf/bpo_v8_p11_m115.pdf&lt;br /&gt;
&lt;br /&gt;
==Źródła błędu==&lt;br /&gt;
Rejestracja sygnału EMG, podobnie jak pomiar innych sygnały bioelektrycznych podlega pewnym zakłóceniom. Są to przede wszystkim &lt;br /&gt;
*artefakty ruchowe,&lt;br /&gt;
*artefakty związane z obecnością zewnętrznych pól elektromagnetycznych.&lt;br /&gt;
&lt;br /&gt;
===Artefakty ruchowe ===&lt;br /&gt;
W wyniku aktywacji mięśnia, ulega on skróceniu, co powoduje przemieszczanie się względem siebie mięśnia, skóry i elektrody. Przemieszczenie to powoduje zmianę amplitudy mierzonego sygnału (np. elektroda oddala się od mięśnia), zmianę potencjału DC (potencjału powstającego na granicy skóra-elektrolit) oraz rozciągniecie skóry. Jak pamiętamy z pierwszych zajęć&lt;br /&gt;
pomiędzy naskórkiem a skórą właściwą istnieje różnica potencjałów o amplitudzie dochodzącej do 30 mV. W trakcie rozciągania skóry, wartość to spada do 25 mV. Powstająca zmiana potencjału, o wartości około 5 mV jest w porównaniu z sygnałem EMG bardzo znacząca.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowe ===&lt;br /&gt;
Artefakty sieciowe stanowią poważny problem w przypadku rejestracji sygnału EMG. Zwykle bowiem nie obserwujemy tylko zakłócenia o jednej częstości, równej częstości zmian napięcia w gniazdku zasilającym (np. w Polsce jest to 50 Hz), lecz również wyższe harmoniczne tej częstości (w Polsce będzie to 100 Hz, 150 Hz, 200 Hz, itd). Jak można zauważyć, częstości 50 Hz, 100 Hz i 150 Hz znajdują się w paśmie, w którym sygnał EMG ma największą energię. Stosowanie filtrów pasmowo zaporowych w takim przypadku nie jest wskazane, bowiem filtry jak wiemy nie tłumią ściśle określonych częstości tylko pasma o pewnej szerokości (np. 45-55 Hz, 95-105 Hz, itd). W efekcie znaczna część interesującego nas pasma sygnału EMG zostałaby odrzucona. Aby zminimalizować przenikanie od rejestrowanego sygnału EMG sygnału sieciowego o częstości 50 Hz należy zadbać o niską impedancję pomiędzy elektrodą a skóra oraz powinno mierzyć się sygnały różnicowe.&lt;br /&gt;
&lt;br /&gt;
===Artefakty sieciowo-ruchowe ===&lt;br /&gt;
Podczas ruchu mięśnia ciało może ulec przemieszczeniu, co spowoduje ruch kabla w przestrzeni pomiędzy elektrodą a wzmacniaczem. W przestrzeni tej istnieje pole elektromagnetyczne, wywołane zasilaniem sieci elektrycznej. Ruch kabla w polu elektromagnetycznym może powodować zaburzenia sygnału o częstości 50 Hz. Ponadto układ elektrody-kable-wzmacniacz, tworzy pewne ramki, które w trakcie ruchu zmieniają kształt a także powierzchnię. Zgodnie z Prawem Indukcji Faraday'a zmiana strumienia magnetycznego powoduje powstawanie siły elektromotorycznej, która również może zakłócać pomiar.&lt;br /&gt;
&lt;br /&gt;
Artefakty ruchowe można w większości wyeliminować przez zastosowanie filtru górnoprzepustowego, którego częstość odcięcia ustawia się w granicy od 10 do 20 Hz. Aby wyeliminować artefakty związane z ruchem kabla w polu elektromagnetycznym można zastosować tzw. elektrody aktywne. W elektrodach tych (miniaturowy) wzmacniacz znajduje się na elektrodzie. Wzmacnianie sygnału na elektrodzie zwiększa względną czułość układu na sygnał mierzony na elektrodzie w stosunku do zaburzenia związanego z ruchem kabla. Innym rozwiązaniem tego problemu jest zastosowanie kabli ekranowanych. Kable TMSI, których używamy na Pracowni są kablami ekranowanymi. W kablach tych, pomiędzy dwiema warstwami izolatora, istnieje dodatkowa osłona z przewodnika podłączona do wzmacniacza. Dzięki temu, zewnętrzne pole elektromagnetyczne nie przenika do środka kabla. Dodatkowo, aby wyeliminować indukowanie się ładunków w wyniku tarcia pomiędzy izolatorami a osłoną, jest ona częściowo pokryta warstwą węgla.&lt;br /&gt;
&lt;br /&gt;
Sygnały do naszych zajęć znajdują się w tym katalogu: &lt;br /&gt;
https://drive.google.com/drive/folders/18skluB3j2CHMXX8l1UmIvNXR1tZYGU0C?usp=sharing&lt;br /&gt;
Proszę je pobrać.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ćwiczenia ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie I: Badanie zależności sygnału EMG od obciążenia ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* umieść elektrodę GND na wewnętrznej części przedramienia, w połowie jego długości,&lt;br /&gt;
* umieść dwie elektrody do rejestracji sygnału EMG na mięśniu dwugłowym ramienia (popularnie zwanym bicepsem). Kable tych elektrod połącz z unipolarnymi wejściami wzmacniacza numer 1 i 2. &lt;br /&gt;
* ustaw częstość próbkowania sygnału na 2048&lt;br /&gt;
===== Obserwacje wstępne =====&lt;br /&gt;
W tej części proszę wykonać wskazane poniżej obserwacje i zarejestrować fragmenty sygnałów, które mogłyby ilustrować ciekawe obserwacje, aby można je było wykorzystać w końcowej prezentacji.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* W SVAROGU:&lt;br /&gt;
** badać będziemy mięsień przedramienia&lt;br /&gt;
** przetestuj sygnały rejestrowane w kilku różnych lokalizacjach względem mięśnia&lt;br /&gt;
** Przyjrzyj się przebiegowi i widmu sygnałów&lt;br /&gt;
** dobierz odpowiednio filtry górnoprzepustowe&lt;br /&gt;
** zaobserwuj czy i kiedy w sygnale pojawiają się artefakty&lt;br /&gt;
** porównaj sygnały rejestrowane przez elektrody bipolarne i przez elektrody monopolarne zmontowane bipolarnie&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 1: napinanie i rozluźnianie ręki =====&lt;br /&gt;
Zarejestruj sygnał, w którym naprzemiennie po około 5 s napinasz i rozluźniasz biceps lub ściskasz i rozluźniasz pięść (dla badania mięśnia przedramienia).&lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 2: zwiększanie obciążenia ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 1 min. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części będziemy stopniowo zwiększać obciążenie: co około 20 s kolejne zwiększenie obciążenia - 5 lub 6 poziomów &lt;br /&gt;
&lt;br /&gt;
===== Rejestracja 3: stałe obciążenie ręki =====&lt;br /&gt;
Rejestrujemy dwa stany: spoczynek, narastajace obciążenie:&lt;br /&gt;
* zarejestruj około 20s. sygnału spoczynkowego &lt;br /&gt;
* w dalszej części dokładamy obciążenie (środkowy poziom z poprzedniego ćwiczenia) i rejestrujemy 1 min. sygnału  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
w 2021 AD:&amp;quot;każda grupa robiła eksperyment, w którym mieli na zmianę ruszać lewą bądź prawą reką (~ 5s na ruch) (wszystko było przez psychopy, powinny być tagi w plikach *.tag). Potem tym, co szło szybciej zadałam badanie EMG pod wpływem obciązenia - tutaj mieli sobie zmodyfikowac procedurę poprzednią i np. na nową komendę dokładać książki, każda grupa oceniała sama ile książek udźwignie, więc te dane będą trochę różne. To nie wszystcy dali radę zrobić - Ci co byli w tyle przeszli do badania EMG z twarzy. Tutaj były dwa warunki: bierne patrzenie i naśladowanie - każda grupa miała sobie wybrać po 3 mięśnie w zależności jakie emocje wybrali do eksperymentu (każda grupa wybierała  z 7 zdjęć: 6 emocji podst. i 1 neurtr.). &amp;quot;&lt;br /&gt;
(&amp;lt;strong&amp;gt; w roku 2020 analizujemy plik 'spoczynek_wysilek.raw'&amp;lt;/strong&amp;gt;):&lt;br /&gt;
** oblicz ich średnią amplitudę (odchylenie standardowe) &lt;br /&gt;
&lt;br /&gt;
Do wczytywanie sygnałów w pythonie wykorzystaj biblioteke ReadManager (http://moduly-analizy-danych.braintech.pl)&lt;br /&gt;
&lt;br /&gt;
Porównaj wyniki detekcji z zapisami tagów w pliku *.tag&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Dalsze analizy robimy w pythonie (notebook).&lt;br /&gt;
** wykreśl sygnał&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** Przedstaw przebieg średniej mocy sygnałów. Aby to zrobić podnieś próbki do kwadratu i uśrednij za pomocą średniej biegnącej o długości 0.1 s (filtrowanie oknem prostokątnym). Porównaj uzyskane przebiegi z przebiegiem sygnałów wejściowych.&lt;br /&gt;
** Zaproponuj algorytm detektora, wykrywającego ruch ręki. &lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** Predstaw wykres średnią amplitudę (odchylenie standardowe) od obciążenia&lt;br /&gt;
** Przedstaw widma dla kolejnych obciążeń (na wspólnym wykresie). Do estymacji wykorzystaj metodę Welcha, dobierając parametry tak aby rodzielczość częstotliwościowa była 1Hz.&lt;br /&gt;
** Przedstaw mapę czas-częstość (rozważ spectrogram i scalogram - czy któraś z technik jest tu lepsza?) dla całego zapisu. Zaobserwuj jakie zmiany następują w widmie wraz ze wzrostem obciążenia.&lt;br /&gt;
&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od zmęczenia mięśnia:&lt;br /&gt;
** Przedstaw mapę czas-częstość dla całego czasu rejestracji. Zaobserwuj jakie zmiany następują w widmie wraz z czasem.&lt;br /&gt;
** Przedstaw ewolucję czasową mediany widma&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Zbadaj zależność parametrów sygnału EMG od obciązenia mięśnia:&lt;br /&gt;
** dla kilku wartości obciążenia (np. do siatki na zakupy dokładamy kolejno 0.5 litrowe butelki z wodą) wykonaj pomiar sygnału przez 30 s&lt;br /&gt;
** pomiędzy pomiarami robić przerwy na odpoczynek mięśnia&lt;br /&gt;
** pomiar powtórzyć w odwrotnej kolejności obciązania&lt;br /&gt;
** sporządzić odpowiednie wykresy &lt;br /&gt;
* Zbadaj zależność sygnału EMG od czasu obciążania przy znacznym obciążeniu. Pytanie badawcze: czy jakieś paramtery tego sygnału ulegają zmianie wraz ze zmęczeniem mięśnia?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie II: Analiza napięcia mięśni twarzy pod wpływem bodźców emocjonalnych ===&lt;br /&gt;
====Pomiar====&lt;br /&gt;
* Zamontuj pary elektrod nad wybranymi trzema mięśniami uczestniczącymi w wyrażaniu prezentowanych emocji. Uziemienie umieść na obojczyku.  &lt;br /&gt;
* Ustaw częstość rejestracji na 2048 Hz&lt;br /&gt;
* Uruchom procedurę eksperymentalną w SVAROGU (menu psychopy). &lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
* Analizę oprzemy na art. https://www.researchgate.net/publication/247901198_Dynamic_facial_expressions-_EMG_study&lt;br /&gt;
** sygnały filtrujemy:  30 Hz high-pass, 500 Hz low-pass and 50 Hz notch,&lt;br /&gt;
** podnosimy próbki do kwadratu&lt;br /&gt;
** wygładzamy średnią biegnącą o  długości 50 ms.&lt;br /&gt;
&lt;br /&gt;
* Zaczniemy od analizy sygnałów z procedury czynnej (Blok 2). &lt;br /&gt;
** korzystając z tagów wytnij fragmenty sygnału (wygładzonego) od -1s do 1 s po bodźcu wg. typów emocji&lt;br /&gt;
** zastosuj &amp;quot;baseline correction&amp;quot; tzn. odejmij od otrzymanych wycinków średnią z sek. poprzedzającej bodziec&lt;br /&gt;
** nałóż na siebie wycięte fragmenty z każdej pary elektrod osobno w każdej z kategorii emocji.&lt;br /&gt;
** zaobserwuj powtarzalność aktywacji mięśni. Czy występują jakieś wyraźne artefakty? Jeśli tak, to usuń je z zestawu danych i uśrednij pozostałe fragmenty.  &lt;br /&gt;
&lt;br /&gt;
* W procedurze biernej powtórz powyższe kroki analizy i porównaj występujące wzorce z procedurą aktywną&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie III: zapoznanie się z sygnałami rejestrowanymi przez inwazyjne EMG===&lt;br /&gt;
Proszę wczytać i przyjrzeć się sygnałom &lt;br /&gt;
[https://drive.google.com/file/d/1AO7w4m2F3nkSzISYXAeDGCpjMIRDx5NS/view?usp=sharing zdrowy.bin], &lt;br /&gt;
[https://drive.google.com/file/d/1APY5xDQJrwFuPY_V7Uza9JrKSgew1Yx1/view?usp=sharing miopatia.bin],&lt;br /&gt;
[https://drive.google.com/file/d/1ARzqLlYYLmhyefkBsOkoQBx4ToYpQ3yK/view?usp=sharing neuropatia.bin]. Sygnały są zapisane jako dtype='float64'&lt;br /&gt;
Częstość próbkowania 4000Hz, amplitudy zapisane są w mV. Dane pochodzą z bazy Physionet: https://physionet.org/content/emgdb/1.0.0/&lt;br /&gt;
&lt;br /&gt;
Proszę przeczytać informację o tych danych. W raporcie proszę napisać istotne informacje o tych sygnałach i  wybrać charakterystyczne fragmenty typowe dla danego stanu klinicznego.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;--&lt;br /&gt;
=== Ćwiczenie IV: detekcja aktywności wybranej jednostki ruchowej===&lt;br /&gt;
Wstępna symulacja:&lt;br /&gt;
&lt;br /&gt;
Proszę wykonać i przmyśleć wynik następującej symulacji:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
import matplotlib.pylab as plt&lt;br /&gt;
import numpy as np&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
&lt;br /&gt;
x = np.array([0,0, 1, 2, 3, 4, 4, 4, 6, 0], dtype=float)&lt;br /&gt;
y = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1, 2, 3, 4, 4, 4, 6, 0,0, 0,0, 0,0, 0,0, 0,0], dtype=float)&lt;br /&gt;
&lt;br /&gt;
h = np.flip(x)/np.linalg.norm(x)&lt;br /&gt;
z = ss.lfilter(h,[1],y)&lt;br /&gt;
&lt;br /&gt;
wzorzec = x/np.linalg.norm(x)&lt;br /&gt;
Nw = len(wzorzec)&lt;br /&gt;
zz = np.zeros(y.shape)&lt;br /&gt;
for i in range(len(y)-Nw):&lt;br /&gt;
  zz[i+Nw-1] = np.dot(wzorzec,y[i:i+Nw])&lt;br /&gt;
&lt;br /&gt;
plt.plot(x)&lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(zz,'.')&lt;br /&gt;
plt.legend(('x','y','z','zz'))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Będziemy analizować sygnał: zdrowy.bin&lt;br /&gt;
* jako wzorzec poszukiwany przyjmij fragment sygnału pomiędzy: 0.110 do 0.124 s&lt;br /&gt;
* za pomocą analogicznej techniki spróbuj określić  wystąpienia struktur podobnych do wzorca.&lt;br /&gt;
* wykryj wystąpienia poszczególnych jednostek ruchowych w sygnale z neuropatii.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Ćwiczenie II: Badnanie przebiegu sygnału EMG względem triggera ===&lt;br /&gt;
'''W roku 2020 skorzystamy z wcześniej zarejestrowanych danych zgodnie z poniższym opisem. Dane znajdują się w pliku KCIUK.raw, są to 3 kanałowe zapisy  (dtype ='&amp;lt;f'), próbkowane 2048Hz. Dwa pierwsze kanały to monopolarnie rejestrowane kanały u nasady kciuka, kanał trzeci zawiera sygnał z triggera.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
''Wykonaj następujące doświadczenie:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Elektrodę GND umieść na wewnętrznej stronie przedramienia w połowie jego długości.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Umieść elektrody do rejestracji sygnału EMG na kciuku lub u nasady kciuka.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Do wejścia '''trigger''' wzmacniacza podłącz przycisk.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Uruchom program Svarog, skonfiguruj go do rejestracji sygnału EMG i rozpocznij nagrywanie sygnału.&amp;lt;br/&amp;gt;&lt;br /&gt;
5. Naciśnij 50 razy przycisk kciukiem, przy czym zachowaj około 2 sekundowy odstęp w czasie pomiędzy kolejnymi naciśnięciami.&amp;lt;br/&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
Naciśniecie przycisku spowoduje wysłanie na wejście ''trigger'' wzmacniacza sygnału w kształcie schodka prostokątnego. W momencie kiedy podejmiesz decyzję o naciśnięciu przycisku, upłynie pewien krótki okres czasu, zanim kciuk opadnie na przycisk, który z kolei uruchomi obwód generujące sygnał wysyłany na wejście ''trigger''. Możemy się spodziewać, że sygnał EMG związany z wykonywanym przez kciuk ruchem będzie poprzedzał sygnał elektryczny wysłany przez układ przycisku. Po wykonaniu eksperymentu Twoim zadaniem będzie oszacowanie różnicy w czasie pomiędzy pojawieniem się sygnału na kanale ''trigger'' i sygnałem EMG. W tym celu napisz program, który:&amp;lt;br/&amp;gt;&lt;br /&gt;
1. Wczyta zarejestrowany sygnał.&amp;lt;br/&amp;gt;&lt;br /&gt;
2. Przefiltruje filtrem górnoprzepustowym sygnał EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
3. Wyznaczy początki wykonywanych przez kciuk ruchów, w oparciu o analizę amplitudy sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
4. Narysuje histogram różnicy czasu &amp;lt;math&amp;gt;\Delta T = t_p - t_{emg}&amp;lt;/math&amp;gt;, gdzie &amp;lt;math&amp;gt;t_p&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony przy pomocy sygnału z kanału ''trigger'', &amp;lt;math&amp;gt;t_{emg}&amp;lt;/math&amp;gt; &amp;amp;mdash; czas wykonania ruchu kciukiem wyznaczony na podstawie sygnału EMG.&amp;lt;br/&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ćwiczenie V: Wykorzystanie pomiaru EMG do sterowania on-line ===&lt;br /&gt;
&lt;br /&gt;
Przykładowy fragment kodu &amp;lt;tt&amp;gt;example.py&amp;lt;/tt&amp;gt; umożliwiający odbieranie sygnału on line w pythonie przedstawiony jest poniżej.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Proszę dodać fragment analizujący sygnał on-line i wykrywający moment napięcia mięśnia. Po wykryciu w najprostszej wersji niech w terminalu pojawia się komunikat o wykryciu kliknięcia. W wersji max proszę zrobić wizualizację napięcia mięśnia albo podpiąć ten sygnał do sterowania jakimś prostym interfejsem.&lt;br /&gt;
==== Wersja działająca z pythonem z pakietu Svarog-Lab ====&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
#!/opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
# powinno się odpalać pythonem z pakietu Svarog-Lab&lt;br /&gt;
# lub python w którym są zainstalowane sterowniki z&lt;br /&gt;
# https://braintech.pl/pliki/svarog/svarog-streamer-src/svarog-streamer-src-latest.zip&lt;br /&gt;
# zaletą jest dostęp wprost do sterownika wzmacniacza&lt;br /&gt;
# /opt/braintech-svarog-lab-python/bin/python3&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Alternatywne wzmacniacze&lt;br /&gt;
# from braintech.drivers.perun32.amplifier import Perun32Amplifier as Amplifier # duży wzmacniacz na 32 kanały na USB&lt;br /&gt;
# from braintech.drivers.perun8.amplifiers import PerunCppAmplifier as Amplifier # headset na 8 kanałów&lt;br /&gt;
from braintech.drivers.tmsi.amplifiers import TmsiCppAmplifier as Amplifier # wzmacniacze TMSI&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
# Szukamy wzmacniaczy&lt;br /&gt;
amps = Amplifier.get_available_amplifiers()&lt;br /&gt;
if len(amps) &amp;lt; 1:&lt;br /&gt;
    raise Exception(&amp;quot;Amplifier not connected&amp;quot;)&lt;br /&gt;
amp = Amplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 1024 # dla TMSI&lt;br /&gt;
# amp.sampling_rate = 500 # dla Perun8, Perun32&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # amplifier podaje próbki w integerach, wprost z ADC&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
while True:&lt;br /&gt;
    # pobieramy 16 próbek&lt;br /&gt;
    # Proponuje używać IPython dla eksperymentowania&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wersja dla protokołu LSL ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
# gdy nie ma możliwości używać pythona wbudowanego w svarog-lab możliwe jest używanie streamowania do standardu LSL&lt;br /&gt;
&lt;br /&gt;
# włączenie streamowania do LSL:&lt;br /&gt;
# w terminalu:&lt;br /&gt;
# svarog_streamer -l &lt;br /&gt;
# wypisze listę wzmacniaczy&lt;br /&gt;
# szukamy ID odpowiedniego wzmacniacza np:&lt;br /&gt;
# * Perun-8 Headset&lt;br /&gt;
#       id: &amp;quot;Perun8 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# odpalamy stream LSL danego wzmacniacza:&lt;br /&gt;
# svarog_streamer -a &amp;quot;Perun8 1&amp;quot; -n &amp;quot;nazwa_streamu&amp;quot;&lt;br /&gt;
# nazwa streamu jest ważna, ponieważ streamy są widoczne w sieci LAN&lt;br /&gt;
# zaleta streamu jest też taka, że można podglądać go w Svarogu jednocześnie z naszym skryptem python&lt;br /&gt;
# po odpaleniu streamu można odpalać poniższy skrypt dowolnym pythonem z zainstalowanym numpy oraz pylsl&lt;br /&gt;
&lt;br /&gt;
from pylsl import StreamInlet, resolve_stream&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
nazwa_streamu = &amp;quot;nazwa_streamu&amp;quot; # należy odpowiednio zmienić na nazwę użytą w svarog_streamer -n&lt;br /&gt;
&lt;br /&gt;
# znajdujemy streamy&lt;br /&gt;
print(&amp;quot;szukamy streamy LSL&amp;quot;)&lt;br /&gt;
streams = resolve_stream('type', 'EEG')&lt;br /&gt;
&lt;br /&gt;
selected_stream = None&lt;br /&gt;
# wybieramy nasz&lt;br /&gt;
for stream in streams:&lt;br /&gt;
	if stream.name() in nazwa_streamu:&lt;br /&gt;
		selected_stream = stream&lt;br /&gt;
if selected_stream is None:&lt;br /&gt;
	print(&amp;quot;Nie znalesiono streamu&amp;quot;, nazwa_streamu, &amp;quot;w liście&amp;quot;, [i.name() for i in streams])&lt;br /&gt;
	exit()&lt;br /&gt;
&lt;br /&gt;
# używamy streama&lt;br /&gt;
inlet = StreamInlet(selected_stream)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
	# pobieramy próbki (w mikrowoltach)&lt;br /&gt;
    sample, timestamp = inlet.pull_chunk(timeout=1.0, max_samples=10)&lt;br /&gt;
    print(sample, timestamp, time.monotonic())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dodatek ===&lt;br /&gt;
Do działania on-line przydatne może być filtrowanie sygnału w sposób biegnący. Najlepiej zastosować do tego funkcję lfilter z ustalonymi warunkami początkowymi.  Używa się tego w następujący sposób:&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
import scipy.signal as ss&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
Fs = 256&lt;br /&gt;
T = 1&lt;br /&gt;
t = np.arange(0,T,1/Fs)&lt;br /&gt;
f0 = 10&lt;br /&gt;
f1 = 17&lt;br /&gt;
f2 = 23&lt;br /&gt;
x = (np.sin(2*np.pi*f0*t) +&lt;br /&gt;
     np.sin(2*np.pi*f1*t ) +&lt;br /&gt;
     np.cos(2*np.pi*f2*t))&lt;br /&gt;
xn = x + np.random.randn(len(t)) * 0.08&lt;br /&gt;
&lt;br /&gt;
b, a = ss.butter(3, 11/(Fs/2))&lt;br /&gt;
&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
z, _ = ss.lfilter(b, a, xn, zi=zi*xn[0])&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Filtrowanie online ====&lt;br /&gt;
&lt;br /&gt;
Symulacja zastosowania tego sposobu on-line; filtrujemy za każdą iteracją pętli to co przychodzi ze wzmacniacza [s]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang =python&amp;gt;&lt;br /&gt;
zi = ss.lfilter_zi(b, a)&lt;br /&gt;
y = np.zeros(xn.shape)&lt;br /&gt;
for  ind, s  in enumerate(xn):&lt;br /&gt;
  y_tmp, zi = ss.lfilter(b, a, [s], zi=zi)&lt;br /&gt;
  y[ind]=y_tmp[-1]&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
plt.plot(y)&lt;br /&gt;
plt.plot(z)&lt;br /&gt;
plt.plot(xn)&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Dodatek 2====&lt;br /&gt;
Dla zabawy detektor napięcia mięśni mógłby generować kliknięcia myszki, aby np. zagrać w:&lt;br /&gt;
&lt;br /&gt;
https://dino-chrome.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
W tym celu trzeba doinstalować bibliotekę pynput:&lt;br /&gt;
  pip3 install --user pynput&lt;br /&gt;
&lt;br /&gt;
a potem zastosować kod ze strony:&lt;br /&gt;
https://pynput.readthedocs.io/en/latest/keyboard.html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.keyboard import Key, Controller&lt;br /&gt;
&lt;br /&gt;
keyboard = Controller()&lt;br /&gt;
&lt;br /&gt;
def spacja():&lt;br /&gt;
# Press and release space&lt;br /&gt;
	keyboard.press(Key.space)&lt;br /&gt;
	keyboard.release(Key.space)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from pynput.mouse import Button, Controller&lt;br /&gt;
mouse = Controller()&lt;br /&gt;
&lt;br /&gt;
def click():&lt;br /&gt;
#lewy klik myszy&lt;br /&gt;
	mouse.press(Button.left)&lt;br /&gt;
	time.sleep(500)&lt;br /&gt;
	mouse.release(Button.left)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== wersja dla systemu dostępnego w Labie 4.59 na Ubuntu 18 ====&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
from obci_cpp_amplifiers.amplifiers import TmsiCppAmplifier&lt;br /&gt;
import numpy as np&lt;br /&gt;
amps = TmsiCppAmplifier.get_available_amplifiers('usb')&lt;br /&gt;
amp = TmsiCppAmplifier(amps[0])&lt;br /&gt;
&lt;br /&gt;
amp.sampling_rate = 512&lt;br /&gt;
&lt;br /&gt;
amp.start_sampling()&lt;br /&gt;
gains = np.array(amp.current_description.channel_gains)&lt;br /&gt;
offsets = np.array(amp.current_description.channel_offsets)&lt;br /&gt;
&lt;br /&gt;
def samples_to_microvolts(samples):  # z jednostek wzmacniacza do mikrowoltów&lt;br /&gt;
    return samples * gains + offsets&lt;br /&gt;
    &lt;br /&gt;
while True:&lt;br /&gt;
    # 16 próbek w pakiecie, nieodebrane próbki się bufurują i można odebrać je później&lt;br /&gt;
    packet = amp.get_samples(16)&lt;br /&gt;
    print(samples_to_microvolts(packet.samples))&lt;br /&gt;
    print(packet.ts[0])&lt;br /&gt;
    print(packet.samples.shape, amp.current_description.channel_names)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aby wykonać go w terminalu należy uruchomić polecenie, Uwaga,  aby zadziałał trzeba wyłączyć SVAROGa.  Proszę przetestować czy po podłączeniu wzmacniacza i uruchomieniu tego skryptu pojawiają się w terminalu wartości próbek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 /opt/braintech/bin/python3 example.py&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Ćwiczenie polega pomiarze czasu reakcji badanej osoby. W tym celu:&lt;br /&gt;
# Na zajęciach z Zaawansowanego Programowania w Pythonie napisz program, który będzie wyświetlał na ekranie szachownicę o rozmiarze 3&amp;amp;times;3 pola. W określonych chwilach czasu, np. co 2 sekundy, losowo wybrane pola szachownicy zostaną podświetlone. Zadaniem badanej osoby będzie jak najszybsze naciśniecie przycisku w reakcji na bodziec, którym będzie krzyż utworzony przez podświetlone na ekranie pola szachownicy. Czas reakcji będzie to czas jaki upłynie od momentu pojawienia się bodźca na ekranie komputera, a naciśnięciem przycisku przez badaną osobę. Poprawny pomiar czasu reakcji wymaga zsynchronizowania programu rejestrującego sygnał EEG z programem generującym bodźce. Zazwyczaj taką synchronizację osiąga się poprzez wysyłanie przez program generujący bodźce sygnału na wejście ''trigger'' wzmacniacza, w chwili gdy bodziec pojawi się na ekranie. W naszym eksperymencie do synchronizacji tych dwóch programów wykorzystamy zegar czasu systemowego. Program do rejestracji danych oraz do generacji bodźców będą odmierzały czas od pewnej ustalonej daty, to jest od godziny 24, 1 stycznia 1970 r. Za pomocą wywołań odpowiednich funkcji w języku Python można uzyskać liczbę sekund która upłynęła od tego momentu.&lt;br /&gt;
# Wykorzystując program opisany w poprzednim punkcie, wykonaj eksperyment, w którym ruch palca związany z reakcją badanej osoby na bodziec będziesz wykrywał na podstawie sygnału EMG. Przeanalizuj zarejestrowany sygnał, utwórz histogram czasów reakcji oraz oblicz średni czas reakcji i jego rozrzut.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden begin|title=Moduł keystroke:}}&lt;br /&gt;
&amp;lt;source lang = python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Author:&lt;br /&gt;
#     Mateusz Kruszyński &amp;lt;mateusz.kruszynski@gmail.com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
from Xlib import X, display, Xutil, XK&lt;br /&gt;
import Xlib&lt;br /&gt;
special_X_keysyms = {&lt;br /&gt;
    ' ' : &amp;quot;space&amp;quot;,&lt;br /&gt;
    '\t' : &amp;quot;Tab&amp;quot;,&lt;br /&gt;
    '\n' : &amp;quot;Return&amp;quot;,  # for some reason this needs to be cr, not lf&lt;br /&gt;
    '\r' : &amp;quot;Return&amp;quot;,&lt;br /&gt;
    '\e' : &amp;quot;Escape&amp;quot;,&lt;br /&gt;
    '!' : &amp;quot;exclam&amp;quot;,&lt;br /&gt;
    '#' : &amp;quot;numbersign&amp;quot;,&lt;br /&gt;
    '%' : &amp;quot;percent&amp;quot;,&lt;br /&gt;
    '$' : &amp;quot;dollar&amp;quot;,&lt;br /&gt;
    '&amp;amp;' : &amp;quot;ampersand&amp;quot;,&lt;br /&gt;
    '&amp;quot;' : &amp;quot;quotedbl&amp;quot;,&lt;br /&gt;
    '\'' : &amp;quot;apostrophe&amp;quot;,&lt;br /&gt;
    '(' : &amp;quot;parenleft&amp;quot;,&lt;br /&gt;
    ')' : &amp;quot;parenright&amp;quot;,&lt;br /&gt;
    '*' : &amp;quot;asterisk&amp;quot;,&lt;br /&gt;
    '=' : &amp;quot;equal&amp;quot;,&lt;br /&gt;
    '+' : &amp;quot;plus&amp;quot;,&lt;br /&gt;
    ',' : &amp;quot;comma&amp;quot;,&lt;br /&gt;
    '-' : &amp;quot;minus&amp;quot;,&lt;br /&gt;
    '.' : &amp;quot;period&amp;quot;,&lt;br /&gt;
    '/' : &amp;quot;slash&amp;quot;,&lt;br /&gt;
    ':' : &amp;quot;colon&amp;quot;,&lt;br /&gt;
    ';' : &amp;quot;semicolon&amp;quot;,&lt;br /&gt;
    '&amp;lt;' : &amp;quot;less&amp;quot;,&lt;br /&gt;
    '&amp;gt;' : &amp;quot;greater&amp;quot;,&lt;br /&gt;
    '?' : &amp;quot;question&amp;quot;,&lt;br /&gt;
    '@' : &amp;quot;at&amp;quot;,&lt;br /&gt;
    '[' : &amp;quot;bracketleft&amp;quot;,&lt;br /&gt;
    ']' : &amp;quot;bracketright&amp;quot;,&lt;br /&gt;
    '\\' : &amp;quot;backslash&amp;quot;,&lt;br /&gt;
    '^' : &amp;quot;asciicircum&amp;quot;,&lt;br /&gt;
    '_' : &amp;quot;underscore&amp;quot;,&lt;br /&gt;
    '`' : &amp;quot;grave&amp;quot;,&lt;br /&gt;
    '{' : &amp;quot;braceleft&amp;quot;,&lt;br /&gt;
    '|' : &amp;quot;bar&amp;quot;,&lt;br /&gt;
    '}' : &amp;quot;braceright&amp;quot;,&lt;br /&gt;
    '~' : &amp;quot;asciitilde&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
display = display.Display()&lt;br /&gt;
window = display.screen().root&lt;br /&gt;
&lt;br /&gt;
def wait(p_keys_list):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Block the whole keyboard!!! And wait until some key from p_keys_list&lt;br /&gt;
    is pressed. By now p_keys_list is a list of strings, so use single&lt;br /&gt;
    ascii symbols.&lt;br /&gt;
    There is a way out of this hell - hit 'Escape'.&lt;br /&gt;
    The function returns hit button`s string representation&lt;br /&gt;
    Eg. for p_keys_list == ['1','2','3'] the function will hand untill&lt;br /&gt;
    1,2 or 3 key is preseed or Escape is pressed.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ds = display&lt;br /&gt;
    window.grab_keyboard(1, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)&lt;br /&gt;
    while True:&lt;br /&gt;
        ev = ds.next_event()&lt;br /&gt;
        if ev.type == X.KeyPress:&lt;br /&gt;
            keysym = ds.keycode_to_keysym(ev._data['detail'], 0)&lt;br /&gt;
            keystr = XK.keysym_to_string(keysym)&lt;br /&gt;
            print(&amp;quot;Got keysym/keystr: &amp;quot;+str(keysym)+ ' / '+str(keystr))&lt;br /&gt;
            if keystr in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keystr&lt;br /&gt;
            elif str(keysym) in p_keys_list:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return keysym&lt;br /&gt;
            elif keysym == 65307:&lt;br /&gt;
                ds.ungrab_keyboard(X.CurrentTime)&lt;br /&gt;
                ds.flush()&lt;br /&gt;
                return 'Escape'&lt;br /&gt;
&lt;br /&gt;
def char_to_keysym(ch) :&lt;br /&gt;
    keysym = Xlib.XK.string_to_keysym(ch)&lt;br /&gt;
    if keysym == 0 :&lt;br /&gt;
        # Unfortunately, although this works to get the correct keysym&lt;br /&gt;
        # i.e. keysym for '#' is returned as &amp;quot;numbersign&amp;quot;&lt;br /&gt;
        # the subsequent display.keysym_to_keycode(&amp;quot;numbersign&amp;quot;) is 0.&lt;br /&gt;
        keysym = Xlib.XK.string_to_keysym(special_X_keysyms[ch])&lt;br /&gt;
    return keysym&lt;br /&gt;
&lt;br /&gt;
def keysym_to_keycode(keysym):&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    shift_mask = 0&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
def char_to_keycode(ch) :&lt;br /&gt;
    keysym = char_to_keysym(ch)&lt;br /&gt;
    keycode = display.keysym_to_keycode(keysym)&lt;br /&gt;
    if keycode == 0 :&lt;br /&gt;
        print &amp;quot;Sorry, can't map&amp;quot;, ch&lt;br /&gt;
&lt;br /&gt;
    if (is_shifted(ch)) :&lt;br /&gt;
        shift_mask = Xlib.X.ShiftMask&lt;br /&gt;
    else :&lt;br /&gt;
        shift_mask = 0&lt;br /&gt;
&lt;br /&gt;
    return keycode, shift_mask&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def is_shifted(ch) :&lt;br /&gt;
    if ch.isupper() :&lt;br /&gt;
        return True&lt;br /&gt;
    if &amp;quot;~!@#$%^&amp;amp;*()_+{}|:\&amp;quot;&amp;lt;&amp;gt;?&amp;quot;.find(ch) &amp;gt;= 0 :&lt;br /&gt;
        return True&lt;br /&gt;
    return False&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def send_string(str) :&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;I am not working. I dont know why:(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for ch in str :&lt;br /&gt;
        #print &amp;quot;sending&amp;quot;, ch, &amp;quot;=&amp;quot;,&lt;br /&gt;
display.keysym_to_keycode(Xlib.XK.string_to_keysym(ch))&lt;br /&gt;
        keycode, shift_mask = char_to_keycode(ch)&lt;br /&gt;
        event = Xlib.protocol.event.KeyPress(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
        event = Xlib.protocol.event.KeyRelease(&lt;br /&gt;
            time = int(time.time()),&lt;br /&gt;
            root = display.screen().root,&lt;br /&gt;
            window = window,&lt;br /&gt;
            same_screen = 0, child = Xlib.X.NONE,&lt;br /&gt;
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,&lt;br /&gt;
            state = shift_mask,&lt;br /&gt;
            detail = keycode&lt;br /&gt;
            )&lt;br /&gt;
        window.send_event(event, propagate = True)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import sys,time&lt;br /&gt;
    print(wait(sys.argv[1:]))&lt;br /&gt;
    #send_string(&amp;quot;aBcd&amp;quot;)&lt;br /&gt;
    #time.sleep(10)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Używa się tak:&lt;br /&gt;
import keystroke&lt;br /&gt;
keystroke.wait(['a','b'])&lt;br /&gt;
i to wisi dopóki ktoś nie wciśnie a lub b.&lt;br /&gt;
&lt;br /&gt;
Z innymi klawiszam jest tak, że trzeba ich numery podać, np żeby czakać &lt;br /&gt;
na SPACE można zrobić&lt;br /&gt;
keystroke.wait(['32'])&lt;br /&gt;
&lt;br /&gt;
w razie czego funkcja się 'odwiesza' jak się wciśnie ESC.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG/CSP&amp;diff=11255</id>
		<title>Laboratorium EEG/CSP</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG/CSP&amp;diff=11255"/>
		<updated>2025-04-16T09:06:45Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Definicja */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Laboratorium_EEG]]/BSS&lt;br /&gt;
&lt;br /&gt;
=Prezentacja=&lt;br /&gt;
[https://brain.fuw.edu.pl/edu/images/2/2f/BSS.pdf slajdy z prezentacji]&lt;br /&gt;
&lt;br /&gt;
=Ślepa separacja źródeł (BSS)=&lt;br /&gt;
{{hidden begin|title=Wstęp teoretyczny do BSS}}&lt;br /&gt;
Rozważmy ''N''-kanałowy sygnał EEG.&lt;br /&gt;
Próbkę tego sygnału możemy przedstawić jako punkt w przestrzeni rozpiętej przez osie, z których każda reprezentuje wartość potencjału w jednym kanale. Cały sygnał tworzy w tej przestrzeni chmurę punktów. Rozciągłość tej chmury w danym kierunku mówi nam o wariancji (zmienności) sygnału w tym kierunku. &lt;br /&gt;
&lt;br /&gt;
Taki zbiór punktów wygodniej jest analizować w układzie współrzędnych zgodnym z osiami głównymi macierzy kowariancji.&lt;br /&gt;
W dalszej części rozważań założymy, że te przestrzenie, w których rozważamy sygnały są przestrzeniami wektorowymi, a pojedyncze próbki wielokanałowego sygnału są wektorami. &lt;br /&gt;
[[Plik:Kowariancja.png|200px|center]]&lt;br /&gt;
&lt;br /&gt;
==Filtry przestrzenne i ślepa separacja źródeł==&lt;br /&gt;
Sygnał EEG jest superpozycją aktywności elektrycznej wielu źródeł.&lt;br /&gt;
Jak można estymować aktywność samych źródeł?&lt;br /&gt;
[[Plik:Mieszanie.png|200px|center]]&lt;br /&gt;
Niech:&lt;br /&gt;
: &amp;lt;math&amp;gt;s(t)&amp;lt;/math&amp;gt; - aktywność niezależnych źródeł,&lt;br /&gt;
: &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; mierzony sygnał&lt;br /&gt;
: &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; macierz przejścia taka, że:&lt;br /&gt;
::&amp;lt;math&amp;gt;x(t) = A s(t)&amp;lt;/math&amp;gt; (*)&lt;br /&gt;
:&amp;lt;math&amp;gt;s(t) = A^{-1}x(t) = P x(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
Macierz kowariancji dla sygnałów &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; estymujemy tak:&lt;br /&gt;
:&amp;lt;math&amp;gt; C_x = E[x(t)x(t)^T]&amp;lt;/math&amp;gt;&lt;br /&gt;
Podstawiając (*) mamy:&lt;br /&gt;
:&amp;lt;math&amp;gt; C_x = E[x x^T] = E[As(As)^T] = A E[s s^T] A^T = A C_s A^T&amp;lt;/math&amp;gt;&lt;br /&gt;
Z założenia, że źródła są niezależne wynika, że macierz &amp;lt;math&amp;gt;C_s&amp;lt;/math&amp;gt; jest diagonalna.&lt;br /&gt;
Przekształcając powyższe równanie możemy zapisać:&lt;br /&gt;
:&amp;lt;math&amp;gt;A^{-1} C_x (A^T)^{-1} = P C_x P^T = C_s&amp;lt;/math&amp;gt;&lt;br /&gt;
Odwzorowanie &amp;lt;math&amp;gt;P = A^{-1}&amp;lt;/math&amp;gt; diagonalizuje macierz &amp;lt;math&amp;gt;C_x&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Powyższe rozumowanie jest słuszne w przypadku gdy mamy do czynienia z sygnałem stacjonarnym, tzn. jego macierz kowariancji jest niezależna od czasu, czyli przez cały czas aktywna jest ta sama konfiguracja źródeł niezależnych.&lt;br /&gt;
W przypadku gdy tak nie jest to konstrukcję filtra przestrzennego można oprzeć o  jednoczesną diagonalizację macierzy kowariancji odpowiadających różnym stanom osoby badanej.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Diagonalizacja.png|200px|center]]&lt;br /&gt;
&lt;br /&gt;
==Common Spatial Pattern ==&lt;br /&gt;
===Koncepcja===&lt;br /&gt;
Dla ustalenia uwagi możemy myśleć o eksperymencie wywołującym potencjał P300. Mamy w nim dwie sytuacje eksperymentalne. Oznaczmy &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; (target) próby, w których pojawił się oczekiwany bodziec, zaś  &amp;lt;math&amp;gt;NT&amp;lt;/math&amp;gt; (non-target) gdy pojawił się bodziec standardowy.&lt;br /&gt;
Chcielibyśmy znaleźć taki montaż (czyli taką kombinację liniową kanałów), który maksymalizuje stosunek mocy (wariancji) sygnałów rejestrowanych w dwóch rożnych warunkach eksperymentalnych.&lt;br /&gt;
&lt;br /&gt;
===Formalizm===&lt;br /&gt;
Metoda ta polega na znalezieniu takiego kierunku &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; w przestrzeni sygnałów, że sygnał z warunku &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; rzutowany na ten kierunek ma dużą wariancje a sygnał z warunku &amp;lt;math&amp;gt;NT&amp;lt;/math&amp;gt; ma wariancję małą. &lt;br /&gt;
&lt;br /&gt;
Rzutowanie sygnału &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; na kierunek &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; odbywa się przez policzenie iloczynu skalarnego dla każdej chwili czasu &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt; s_w(t) = w^T x(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
Wariancja tego rzutowanego sygnału to:&lt;br /&gt;
:&amp;lt;math&amp;gt; \mathrm{var}(s_w) = E[s_w s_w^T] = E[ w^T x (w^T x)^T] = w^T E[x x^T] w = w^T C_x w &amp;lt;/math&amp;gt;&lt;br /&gt;
Zatem znalezienie właściwego kierunku rzutowania można wyrazić jako szukanie maksimum wyrażenia &amp;lt;math&amp;gt; J(w) &amp;lt;/math&amp;gt; (jest to tzw. iloraz Rayleigha):&lt;br /&gt;
: &amp;lt;math&amp;gt;J(w) = \frac{w^T C_T w}{w^T C_{NT} w}  &amp;lt;/math&amp;gt;&lt;br /&gt;
Ekstremum tego ilorazu można znaleźć poprzez policzenie gradientu &amp;lt;math&amp;gt;J(w)&amp;lt;/math&amp;gt; i przyrównanie go do zera:&lt;br /&gt;
:&amp;lt;math&amp;gt; \nabla J(w) =  \frac{ 2 C_{T} w \left(w^T  C_{NT} w\right)  -2C_{NT} w \left(w^T  C_{T} w \right)}{\left(w^T  C_{NT} w\right)^2} = \frac{   2}{w^T  C_{NT} w}\left[     C_{T}w  -\frac{w^T  C_{T} w}{w^T  C_{NT} w}   C_{NT} w \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
Przyrównując to wyrażenie do zera dostajemy do rozwiązania tzw. uogólnione zagadnienie własne:&lt;br /&gt;
:&amp;lt;math&amp;gt;       C_{T}w  =\frac{w^T  C_{T} w}{w^T  C_{NT} w}   C_{NT} w   &amp;lt;/math&amp;gt;&lt;br /&gt;
We wzorze tym liczba &amp;lt;math&amp;gt;\lambda=\frac{w^T  C_{T} w}{w^T  C_{NT} w}&amp;lt;/math&amp;gt; spełniająca to równanie jest uogólnioną wartością własną, wtedy &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; jest uogólnionym wektorem własnym odpowiadającym tej wartości. &lt;br /&gt;
&lt;br /&gt;
Aby znaleźć &amp;lt;math&amp;gt; \lambda&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; możemy wykorzystać w Matlabie funkcję &amp;lt;tt&amp;gt;eig&amp;lt;/tt&amp;gt;. Funkcja ta rozwiązuje (również) uogólnione zagadnienia własne postaci ''Aw''=&amp;amp;lambda;''Bw'' dostarczając w wyniku macierz wektorów własnych (w kolumnach) oraz macierz zawierającą na przekątnej odpowiadające im wartości własne.&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Odwzorowanie to można przedstawić w postaci macierzy &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, której każdy wiersz zawiera wagi dla odpowiednich kanałów. &lt;br /&gt;
Macierz zawierająca sygnał &amp;lt;math&amp;gt;X^{\pm}(t)&amp;lt;/math&amp;gt; &lt;br /&gt;
ma wymiary &amp;lt;math&amp;gt;C \times  N&amp;lt;/math&amp;gt;, gdzie &lt;br /&gt;
&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; to liczba kanałów EEG, natomiast &lt;br /&gt;
&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; to liczba próbek dla każdego z kanałów. &lt;br /&gt;
Macierz &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; przekształca sygnał &amp;lt;math&amp;gt;X^{\pm}(t)&amp;lt;/math&amp;gt;  zgodnie ze wzorem:&lt;br /&gt;
:&amp;lt;math&amp;gt;X^{\pm}_{CSP}(t)=P^T  X^{\pm}(t) &amp;lt;/math&amp;gt;&lt;br /&gt;
Załóżmy dalej, że sygnały &amp;lt;math&amp;gt;X^{+}_{CSP} (t)&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;X^{-}_{CSP} (t)&amp;lt;/math&amp;gt; są generowane przez niezależne procesy stochastyczne, tzn. spełnione są następujące warunki. &lt;br /&gt;
# Syganły &amp;lt;math&amp;gt;X^{+}_{CSP} (t)&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;X^{-}_{CSP} (t)&amp;lt;/math&amp;gt; są niezależne.&lt;br /&gt;
# Brak korelacji pomiędzy kanałami w sygnałach&amp;lt;math&amp;gt;X^{+}_{CSP} (t)&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;X^{-}_{CSP} (t)&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Przynajmniej dla jednego z kanałów wariancja przetransformowanego sygnału jest maksymalna przy wystąpieniu bodźca i minimalna przy jego braku.&lt;br /&gt;
Po przemnożeniu równania 2.3 przez &amp;lt;math&amp;gt;(X^{\pm}_{CSP} (t))^T&amp;lt;/math&amp;gt; otrzymamy macierz kowariancji przetransformowanych sygnałów uśrednioną po realizacjach:&lt;br /&gt;
:&amp;lt;math&amp;gt;R^{\pm}_{CSP} (t) = X^{\pm}_{CSP} (t)(X^{\pm}_{CSP} (t))^T = P^T X^{\pm} (t) (X^{\pm}(t))^T P = P^T R^{\pm}P&amp;lt;/math&amp;gt;  (2.4)&lt;br /&gt;
Gdzie &amp;lt;math&amp;gt;R^{\pm}&amp;lt;/math&amp;gt; to macierz kowariancji sygnału uśredniona po realizacjach. Z warunków 1 i 2 wynika, że macierze &amp;lt;math&amp;gt;R^{+}_{CSP}&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;R^{-}_{CSP}&amp;lt;/math&amp;gt; muszą być diagonalne, natomiast z warunku 3, że ich suma daje macierz jednostkową:&lt;br /&gt;
:&amp;lt;math&amp;gt;R^{+}_{CSP} + R^{-}_{CSP} = 1 &amp;lt;/math&amp;gt;  (2.5)&lt;br /&gt;
Tak więc suma par diagonalnych wartości (&amp;lt;math&amp;gt;k^{+}_{i}&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;k^{-}_{i}&amp;lt;/math&amp;gt;) w macierzach &amp;lt;math&amp;gt;R^{+}_{CSP}&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;R^{-}_{CSP}&amp;lt;/math&amp;gt; musi być równa 1.&lt;br /&gt;
Korzystając z równania 2.5 wartości na przekątnej można również zapisać za pomocą wzoru:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;k^{+}_{i} = \vec{p}^{T}_{i} R^{+} \vec{p}_{i}    &amp;lt;/math&amp;gt; (2.6)&lt;br /&gt;
:&amp;lt;math&amp;gt;k^{-}_{i} = \vec{p}^T_{i} R^{-}\vec{p}_{i} &amp;lt;/math&amp;gt; (2.7)&lt;br /&gt;
gdzie &amp;lt;math&amp;gt;\vec{p}_{i}&amp;lt;/math&amp;gt; to kolumnowy wektor macierzy &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;. Po przekształceniach ilorazu równań 2.6 i 2.7 można&lt;br /&gt;
otrzymać równanie:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;R^{+} \vec{p}_{i} = \frac{k^{+}_{i}}{k^{-}_{i}} R^{-} \vec{p}_{i} &amp;lt;/math&amp;gt;  (2.8)&lt;br /&gt;
￼&lt;br /&gt;
Równanie to przedstawia ogólną formę zagadnienia wartości własnych. Takie przedstawienie problemu umożliwia zastosowanie do jego rozwiązania wydajnych metod algebraicznych.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wektor własny &amp;lt;math&amp;gt;\vec{p}_i&amp;lt;/math&amp;gt; jest interpretowany jako filtr przestrzenny. Dzięki transformacie &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; sygnał zostaje przeniesiony do przestrzeni, dla której różnica wariancji dla poszczególnych klas jest największa. Zgodnie z równaniem 2.5 najbardziej różniące się od siebie kanały są skorelowane z największą wartością własną &amp;lt;math&amp;gt;k^{+}&amp;lt;/math&amp;gt;.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Ćwiczenie symulacyjne ====&lt;br /&gt;
{{hidden begin|title=kod przykładowy}}&lt;br /&gt;
&amp;lt;source lang  = matlab&amp;gt;&lt;br /&gt;
% symulowany eksperyment składa się z sinusoidy udającej alfę spoczynkową i&lt;br /&gt;
% funkcji Gaussa udającego potencjał wywołany&lt;br /&gt;
% źródła te są symulowane niezależnie a potem mieszane przez macierz A&lt;br /&gt;
% symulujemy źródła&lt;br /&gt;
% s1 - symuluje alfę&lt;br /&gt;
% s2 - symuluje &amp;quot;potencjał wywołany&amp;quot; (ERP)&lt;br /&gt;
&lt;br /&gt;
%ustawiamy parametry do symulacji sygnałów&lt;br /&gt;
Fs = 100;&lt;br /&gt;
T = 1;&lt;br /&gt;
t = 0:1/Fs:T-1/Fs;&lt;br /&gt;
N_rep = 100;&lt;br /&gt;
N_chan = 2;&lt;br /&gt;
s = zeros(N_rep,N_chan, length(t));&lt;br /&gt;
X = zeros(N_rep,N_chan, length(t));&lt;br /&gt;
&lt;br /&gt;
% filtr przestrzenny - z takimi wagami trzeba wziąść kanały EEG aby odzyskać sygnały źródłowe&lt;br /&gt;
P = [1 2&lt;br /&gt;
    1.5 1.3]; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
% topografie - z takimi wagami źródła dokładają się do poszczególnych elektrod&lt;br /&gt;
A = P^(-1); &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for r =1:N_rep % tworzymy kolejne realizacje &amp;quot;eksperymentu&amp;quot;&lt;br /&gt;
    s1 = sin(2*pi*11*t +pi/2+ 0*2*pi*rand())+ 0.02*randn(size(t));  % źródło alfa&lt;br /&gt;
    s2 = exp(-((t-0.8)/0.05).^2)+ 0.01*randn(size(t));              % źródło ERP&lt;br /&gt;
       &lt;br /&gt;
    s(r,1,:) = s1;&lt;br /&gt;
    s(r,2,:) = s2;&lt;br /&gt;
    tmp = squeeze(s(r,:,:));&lt;br /&gt;
    n = 0*randn(size(tmp));&lt;br /&gt;
    X(r,:,:) = A*tmp +n; % rzutujemy sygnały źródłowe na elektrody s -&amp;gt; x&lt;br /&gt;
    &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
% wycinamy warunki &lt;br /&gt;
% baseline_ind   to indeksy pierwszej połowy każdego powtórzenia &amp;quot;baseline&amp;quot;&lt;br /&gt;
% ERP_ind        to indeksy drugiej połowy każdego powtórzenia zawierająca &amp;quot;ERP&amp;quot;&lt;br /&gt;
baseline_ind = find(t&amp;lt;0.5);&lt;br /&gt;
ERP_ind = find(t&amp;gt;=0.5);&lt;br /&gt;
&lt;br /&gt;
x_baseline_kan_1 = X(:,1,baseline_ind);&lt;br /&gt;
x_baseline_kan_2 = X(:,2,baseline_ind);&lt;br /&gt;
&lt;br /&gt;
x_ERP_kan_1 = X(:,1,ERP_ind);&lt;br /&gt;
x_ERP_kan_2 = X(:,2,ERP_ind);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
% liczymy średnie macierze kowariancji:&lt;br /&gt;
R_E = zeros(N_chan,N_chan);&lt;br /&gt;
R_B = zeros(N_chan,N_chan);&lt;br /&gt;
for r =1:N_rep&lt;br /&gt;
    B = squeeze(X(r,:,baseline_ind)); &lt;br /&gt;
    tmp =cov(B');&lt;br /&gt;
    R_B = R_B + tmp./trace(tmp);%B*B' ;&lt;br /&gt;
 &lt;br /&gt;
    E = squeeze(X(r,:,ERP_ind));&lt;br /&gt;
    tmp = cov(E');&lt;br /&gt;
    R_E = R_E + tmp./trace(tmp);%E*E' ;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
R_B = R_B/N_rep;&lt;br /&gt;
R_E = R_E/N_rep;&lt;br /&gt;
&lt;br /&gt;
% rozwiązujemy uogólnione zagadnienie własne&lt;br /&gt;
[W,Lambda]=eig(R_E,R_B); % możliwa jest też optymalizacja wzg. średniej macierzy kowariancji (R_B+R_A)/2);&lt;br /&gt;
&lt;br /&gt;
% odzyskujemy sygnały źródeł&lt;br /&gt;
for r =1:N_rep&lt;br /&gt;
    S(r,:,:) = W'*squeeze(X(r,:,:));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
% pobieramy wycinki odpowiadające obu częściom eksperymentu z estymowanych&lt;br /&gt;
% źródeł&lt;br /&gt;
s_baseline_estymowany_kan1 = squeeze(  S(:,1,baseline_ind));&lt;br /&gt;
s_baseline_estymowany_kan2 = squeeze(  S(:,2,baseline_ind));&lt;br /&gt;
&lt;br /&gt;
s_ERP_estymowany_kan1 = squeeze(S(:,1,ERP_ind));&lt;br /&gt;
s_ERP_estymowany_kan2 = squeeze(S(:,2,ERP_ind));&lt;br /&gt;
&lt;br /&gt;
%%%%%%%%%%%%%% Ilustracje %%%%%%%%%%%%%%%%%%%%%%%&lt;br /&gt;
% ilustracja sygnałów mierzonych&lt;br /&gt;
figure(1);clf&lt;br /&gt;
subplot(2,2,1);&lt;br /&gt;
    plot(t(baseline_ind),(squeeze(X(:,1,baseline_ind)))','b'); hold on&lt;br /&gt;
    plot(t(ERP_ind),(squeeze(  X(:,1,ERP_ind)))','r'); hold off&lt;br /&gt;
    xlabel('elektroda 1')&lt;br /&gt;
    title('ilustracja sytuacji pomiarowej -\newline znane są potencjały na elektrodach w dwóch warunkach eksperymentalnych')&lt;br /&gt;
subplot(2,2,3);&lt;br /&gt;
    plot(t(baseline_ind),(squeeze(X(:,2,baseline_ind)))','b'); hold on&lt;br /&gt;
    plot(t(ERP_ind),(squeeze(  X(:,2,ERP_ind)))','r'); hold off&lt;br /&gt;
    xlabel('elektroda 2')&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
    plot(x_baseline_kan_1(:),x_baseline_kan_2(:),'b.');&lt;br /&gt;
    hold on&lt;br /&gt;
    plot(x_ERP_kan_1(:),x_ERP_kan_2(:),'r.');&lt;br /&gt;
    xlim([-2,2])&lt;br /&gt;
    ylim([-2,2])&lt;br /&gt;
    axis equal&lt;br /&gt;
    &lt;br /&gt;
    % wektor własny odpowiadający największej wartości własnej jest&lt;br /&gt;
    % kierunkiem najbardziej różnicującym warunki eksperymentalne&lt;br /&gt;
    disp('wartości własne znajdują się na przekątnej macierzy Lambda')&lt;br /&gt;
    disp(Lambda)&lt;br /&gt;
    % rysujemy wersory jednostkowe w kierunkach wektorów własnych&lt;br /&gt;
    w1 = W(:,1); &lt;br /&gt;
    w1 = w1/norm(w1);&lt;br /&gt;
    w2 = W(:,2); &lt;br /&gt;
    w2 = w2/norm(w2);&lt;br /&gt;
    line([0, w1(1) ],[0,w1(2)],'Color',[0,0.3,0])&lt;br /&gt;
    text(w1(1),w1(2),'wektor własny 1')&lt;br /&gt;
    line([0, w2(1) ],[0,w2(2)],'Color',[1,0,1])&lt;br /&gt;
    text(w2(1),w2(2),'wektor własny 2')&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    xlabel('Amplituda na elektrodzie 1')&lt;br /&gt;
    ylabel('Amplituda na elektrodzie 2')   &lt;br /&gt;
    legend('baseline','ERP')&lt;br /&gt;
&lt;br /&gt;
% Ilustracja estymowanych źródeł&lt;br /&gt;
figure(2);clf&lt;br /&gt;
subplot(2,2,1);&lt;br /&gt;
    plot(t(baseline_ind),(squeeze(S(:,1,baseline_ind)))','b');hold on&lt;br /&gt;
    plot(t(ERP_ind),(squeeze(S(:,1,ERP_ind)))','r');hold off&lt;br /&gt;
    xlabel('estymowane zrodlo  1')&lt;br /&gt;
    title('ilustracja estymacji -\newline estymowane są potencjały źródeł w dwóch warunkach eksperymentalnych')    &lt;br /&gt;
subplot(2,2,3);&lt;br /&gt;
    plot(t(baseline_ind),(squeeze(S(:,2,baseline_ind)))','b');hold on&lt;br /&gt;
    plot(t(ERP_ind),(squeeze(S(:,2,ERP_ind)))','r');hold off&lt;br /&gt;
    xlabel('estymowane zrodlo  2');&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
    plot(s_baseline_estymowany_kan1(:),s_baseline_estymowany_kan2(:),'b.');&lt;br /&gt;
    hold on&lt;br /&gt;
    plot(s_ERP_estymowany_kan1(:),s_ERP_estymowany_kan2(:),'r.');   &lt;br /&gt;
    &lt;br /&gt;
    xlabel('Amplituda estym. źródła 1')&lt;br /&gt;
    ylabel('Amplituda estym. źródła 2')   &lt;br /&gt;
    legend('baseline','ERP')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
==Zastosowanie filtra CSP do detekcji potencjału P300==&lt;br /&gt;
{{hidden begin|title=Eksperyment}}&lt;br /&gt;
===Eksperyment===&lt;br /&gt;
* Proszę zapoznać się z instrukcją: http://laboratorium-eeg.braintech.pl/rozdz10.html&lt;br /&gt;
* Proszę wczytać i uruchomić (na sucho) demo Demos-&amp;gt;EEG_P300wz&lt;br /&gt;
* Wspólne omówienie konstrukcji i potencjalnych modyfikacji tego scenariusza &lt;br /&gt;
&lt;br /&gt;
====Przygotowanie do badania:====&lt;br /&gt;
* założyć czepek z elektrodami w systemie 10-20;&lt;br /&gt;
* elektrody referencyjne: M1 i M2;&lt;br /&gt;
* elektroda GND w pozycji AFz.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
====Przygotowanie scenariuszy obci ====&lt;br /&gt;
* w terminalu uruchomić &amp;lt;tt&amp;gt;obci srv&amp;lt;/tt&amp;gt;;&lt;br /&gt;
* w terminalu uruchomić &amp;lt;tt&amp;gt;obci_gui --preset brain2013&amp;lt;/tt&amp;gt;;&lt;br /&gt;
* w interfejsie GUI zapisujemy scenariusze do własnego katalogu np &amp;amp;bdquo;P300&amp;amp;rdquo;&lt;br /&gt;
** &amp;amp;bdquo;P-Brain2013 Signal (with ID)&amp;amp;rdquo; jako np. &amp;amp;bdquo;Sygnal&amp;amp;rdquo;&lt;br /&gt;
** &amp;amp;bdquo;P-Brain2013 Calibration p300&amp;amp;rdquo; jako &amp;amp;bdquo;kalibracjaP300&amp;amp;rdquo;&lt;br /&gt;
** &amp;amp;bdquo;P-Brain 2013 p300&amp;amp;rdquo; jako &amp;amp;bdquo;Labirynt&amp;amp;rdquo;&lt;br /&gt;
* w przeglądarce plików otwórz katalog ~/.obci/scenarios/P300. Powinien on zawierać pliki: Sygnal.ini, kalibracjaP300.ini, Labirynt.ini oraz katalogi  Sygnal_configs, kalibracjaP300_configs, Labirynt_configs.&lt;br /&gt;
*  edytujemy parametry peerów.&lt;br /&gt;
** z katalogu ~/.obci/scenarios/P300/Sygnal_configs kopiujemy plik amplifier.ini do katalogu ~/.obci/scenarios/P300 jako global_amplifier.ini. To pozwoli nam zmieniać ustawienia wzmacniacza dla wszystkich scenariuszy jednocześnie.&lt;br /&gt;
** w naszych scenariuszach zapisanych w plikach Sygnal.ini, kalibracjaP300.ini, Labirynt.ini podmieniamy ścieżkę &amp;lt;tt&amp;gt;config =&amp;lt;/tt&amp;gt; w sekcji &amp;lt;tt&amp;gt;[peers.amplifier]&amp;lt;/tt&amp;gt; tak, aby pokazywała na ten skopiowany plik global_amplifier.ini&lt;br /&gt;
** w tym pliku global_amplifier.ini podmieniamy linijki (tak aby były to listy faktycznie wykorzystywanych kanałów) z:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;active_channels&amp;lt;/tt&amp;gt;&lt;br /&gt;
*** &amp;lt;tt&amp;gt;channel_names&amp;lt;/tt&amp;gt;&lt;br /&gt;
** dodajemy też linijkę: &amp;lt;tt&amp;gt;sampling_rate = 256&amp;lt;/tt&amp;gt;&lt;br /&gt;
* wchodzimy po kolei do katalogów: Sygnal_configs, kalibracjaP300_configs, Labirynt_configs i odnajdujemy plik switch_backup.ini. W tym pliku ustawiamy parametr &amp;lt;tt&amp;gt;new_scenario&amp;lt;/tt&amp;gt; na pusty. To spowoduje, że scenariusze te nie będą uruchamiać kolejnych scenariuszy po zakończeniu działania.&lt;br /&gt;
** edytujemy plik ~/.obci/scenarios/P300/kalibracjaP300_configs/clasifier.ini &lt;br /&gt;
*** zmieniamy linię&lt;br /&gt;
::: &amp;lt;tt&amp;gt;ignore_channels = DriverSaw;AmpSaw;PO7;PO8&amp;lt;/tt&amp;gt;&lt;br /&gt;
::: na &lt;br /&gt;
::: &amp;lt;tt&amp;gt;ignore_channels = DriverSaw;AmpSaw;A1;A2&amp;lt;/tt&amp;gt;&lt;br /&gt;
::* oraz linię:&lt;br /&gt;
::: &amp;lt;tt&amp;gt;montage_channels = PO7;PO8&amp;lt;/tt&amp;gt;&lt;br /&gt;
::: na &lt;br /&gt;
::: &amp;lt;tt&amp;gt;montage_channels = A1;A2&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Przeprowadzenie badania:====&lt;br /&gt;
# Uruchom scenariusz &amp;amp;bdquo;Sygnał&amp;amp;rdquo;.&lt;br /&gt;
# Tworzy on w katalogu domowym plik o nazwie &amp;lt;tt&amp;gt;file_id_name&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# Uruchamiamy Svaroga z terminala poleceniem &amp;lt;tt&amp;gt;svarog&amp;lt;/tt&amp;gt;. W zakładce sygnały on-line odnajdujemy nazwę naszego scenariusza &amp;amp;bdquo;Sygnal&amp;amp;rdquo;. Podłączamy się do niego i poprawiamy ewentualnie źle kontaktujące elektrody.&lt;br /&gt;
# Jak już jesteśmy zadowoleni z jakości sygnału to zatrzymujemy scenariusz &amp;amp;bdquo;Sygnal&amp;amp;rdquo; w obci.&lt;br /&gt;
# W pliku &amp;lt;tt&amp;gt;file_id_name&amp;lt;/tt&amp;gt;  znajduje się string, który stanowi rdzeń do tworzenia nazw plików, z których korzystają nasze scenariusze. Proszę zmienić ten string np. na: &amp;lt;tt&amp;gt;test1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# Uruchamiamy scenariusz &amp;amp;bdquo;kalibracjaP300&amp;amp;rdquo;. Badany będzie oglądał interfejs z trzema literami A B C migającymi w losowej kolejności. Zadaniem jest zliczanie mignięć litery B.&lt;br /&gt;
# Po zakończeniu kalibracji uruchamiamy scenariusz &amp;amp;bdquo;Labirynt&amp;amp;rdquo;.&lt;br /&gt;
# Danych z kalibracji potrzebować będziemy kilka zestawów.  Proszę powtórzyć kilkukrotnie scenariusz &amp;amp;bdquo;kalibracjaP300&amp;amp;rdquo;. Przed każdym uruchomieniem trzeba zmienić string w pliku &amp;lt;tt&amp;gt;file_id_name&amp;lt;/tt&amp;gt; np. na &amp;lt;tt&amp;gt;test???&amp;lt;/tt&amp;gt; gdzie &amp;lt;tt&amp;gt;???&amp;lt;/tt&amp;gt; oznacza kolejne numery.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
===Analiza wstępna===&lt;br /&gt;
Poszczególne etapy analizy proszę kodować w osobnych funkcjach. Funkcje te powinny być wywoływane z nadrzędnego skryptu, który powinien umożliwic wykoanie całości analiz.&lt;br /&gt;
 &lt;br /&gt;
* Wczytać dane kalibracyjne do Matlaba i pociąć je na realizacje typu T &amp;amp;mdash; &amp;amp;bdquo;target&amp;amp;rdquo; (związane z wystąpieniami litery &amp;amp;bdquo;B&amp;amp;rdquo;) i NT &amp;amp;mdash; &amp;amp;bdquo;non-target&amp;amp;rdquo; (pozostałe litery) o długości &amp;amp;minus;200 do +800 ms wokół triggerów. Dla każdej realizacji odjąć trend liniowy.&lt;br /&gt;
* Sygnał zmontować wzgl. &amp;amp;bdquo;połączonych uszu&amp;amp;rdquo; i wyświetlić średnie przebiegi dla warunku T i NT w układzie topograficznym &amp;amp;mdash; można wykorzystać w tym celu poniższy fragment kodu.&lt;br /&gt;
{{hidden begin|title= fragment kodu do rysowania dwóch ERPów -- zamiast funkcji plottopo}}&lt;br /&gt;
&amp;lt;source lang = matlab&amp;gt;&lt;br /&gt;
%% stworzenie osi&lt;br /&gt;
      % zakładam, że dane do rysowania są w dwóch strukturach EEG1 i EEG2 (struktury eeglab), &lt;br /&gt;
      % te dane są podzielone na realizacje i mają kształt (kanały , czas, epoki)&lt;br /&gt;
      % i że mamy już załadowane położenia elektrod we współrzędnych&lt;br /&gt;
      % biegunowych &lt;br /&gt;
      w = 0.125;&lt;br /&gt;
      h = 0.125;&lt;br /&gt;
      sc = 0.8;&lt;br /&gt;
      figure()&lt;br /&gt;
     for chanNum = 1:length(EEG1.chanlocs)&lt;br /&gt;
         r =EEG1.chanlocs(chanNum).radius;&lt;br /&gt;
         theta = EEG1.chanlocs(chanNum).theta;&lt;br /&gt;
         x = r* sin(theta/180*pi)*sc+0.46;&lt;br /&gt;
         y = r* cos(theta/180*pi)*sc+0.46;&lt;br /&gt;
         ax(chanNum) = axes('Position', [x, y, w, h]);&lt;br /&gt;
     end&lt;br /&gt;
%%uśredniam EEG po powtórzeniach aby otrzymać ERP&lt;br /&gt;
  ERP1 =squeeze( mean( EEG1.data,3)) ;&lt;br /&gt;
  ERP2 =squeeze( mean( EEG2.data,3)) ; &lt;br /&gt;
%% rysowanie uśrednionych potencjałów z dwóch struktur EEG &lt;br /&gt;
 for chanNum = 1:length(EEG1.chanlocs)&lt;br /&gt;
     hold(ax(chanNum),'on');&lt;br /&gt;
     plot(ax(chanNum), EEG1.times, ERP1(chanNum ,:));&lt;br /&gt;
     plot(ax(chanNum), EEG2.times, ERP2(chanNum ,:));&lt;br /&gt;
     title(ax(chanNum),EEG1.chanlocs(chanNum).labels );&lt;br /&gt;
     hold(ax(chanNum),'off');&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Poniżej zaprezentowany jest przykładowy skrypt do cięcia danych wokół znaczników. Działa on z plikami zawartymi w archiwum:&lt;br /&gt;
: [[Plik:KalibracjaP300.tar.gz]] &lt;br /&gt;
Korzysta z funkcji pomocniczych dostępnych w dystrybucji obci w katalogu &lt;br /&gt;
: /usr/share/openbci/analysis/matlab_obci_signal_processing&lt;br /&gt;
Openbci można pobrać z https://github.com/BrainTech/openbci&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{hidden begin|title=przykładowy skrypt}}&lt;br /&gt;
&amp;lt;source lang = matlab&amp;gt;&lt;br /&gt;
% ustalamy nzawy plików z danymi&lt;br /&gt;
nazwaPliku = 'p_6301423_calibration_p300.obci';&lt;br /&gt;
nameOfXMLFile = strcat(nazwaPliku,'.xml');&lt;br /&gt;
nameOfTagFile = strcat(nazwaPliku,'.tag'); %tagi = znaczniki zdarzeń&lt;br /&gt;
namesOfDataFiles = strcat(nazwaPliku,'.raw');&lt;br /&gt;
&lt;br /&gt;
% inicjujemy obiekt rm&lt;br /&gt;
rm = ReadManager(nameOfXMLFile,namesOfDataFiles,nameOfTagFile);&lt;br /&gt;
&lt;br /&gt;
% obieramy przydatne parametry i znaczniki&lt;br /&gt;
numberOfChannels  = rm.get_param('number_of_channels');&lt;br /&gt;
namesOfChannels   = rm.get_param('channels_names');&lt;br /&gt;
samplingFrequency = rm.get_param('sampling_frequency');&lt;br /&gt;
tagsStruct        = rm.get_tags();&lt;br /&gt;
&lt;br /&gt;
% tworzenie list znaczników Target i NonTarget&lt;br /&gt;
numberOfStruct = length(tagsStruct);&lt;br /&gt;
targetTimeStamps = [];&lt;br /&gt;
NonTargetTimeStamps = [];&lt;br /&gt;
for structNumber = 1:numberOfStruct % iterujemy się przez tagi&lt;br /&gt;
    if(strcmp(tagsStruct(structNumber).name,'blink')) % szukamy tagów o nazwie 'blink'&lt;br /&gt;
        index = tagsStruct(structNumber).children.index; % tu jest numer pola stymulacji&lt;br /&gt;
        target= tagsStruct(structNumber).children.target;% tu jest numer pola na którym wyświetlany jest target&lt;br /&gt;
        if index == target % warunek na to, że mamy do czynienia z tagiem target&lt;br /&gt;
            targetTimeStamps = [targetTimeStamps tagsStruct(structNumber).start_timestamp]; %dodajemy timeStamp do listy targetów&lt;br /&gt;
        else&lt;br /&gt;
            NonTargetTimeStamps = [NonTargetTimeStamps tagsStruct(structNumber).start_timestamp];%dodajemy timeStamp do listy non-targetów&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
% pobieramy próbki&lt;br /&gt;
samples = double(rm.get_samples()); % konwersja na double jest potrzebna żeby dobrze funkcjonowało filtrowanie&lt;br /&gt;
samples=samples(1:8,:); % odrzucamy kanały, które nie mają EEG&lt;br /&gt;
numberOfChannels =8;&lt;br /&gt;
&lt;br /&gt;
% filtrujemy dolnoprzepustowo aby odrzucić artefakty sieci i część&lt;br /&gt;
% artefaktów mięśniowych&lt;br /&gt;
[b,a] = cheby2(6,80,25 /(samplingFrequency/2),'low');&lt;br /&gt;
for ch = 1:numberOfChannels&lt;br /&gt;
    samples(ch,:)=filtfilt(b,a,samples(ch,:));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
% montujemy dane do wspólnej średniej (common average)&lt;br /&gt;
M = -ones(8,8)/8;&lt;br /&gt;
M=M+eye(8,8)*9/8;&lt;br /&gt;
samples = 0.0715*M*samples;&lt;br /&gt;
&lt;br /&gt;
% wycinamy dane wokół znaczników&lt;br /&gt;
PRE = -0.2; % czas przed tagiem w sek.&lt;br /&gt;
POST = 0.8; % czas po tagu w sek.&lt;br /&gt;
wycinek = floor(PRE*samplingFrequency:POST*samplingFrequency); % tablica ze &amp;quot;standardowymi&amp;quot; indeksami do cięcia&lt;br /&gt;
&lt;br /&gt;
% pobieramy targety&lt;br /&gt;
TargetSignal = zeros(length(targetTimeStamps),numberOfChannels, length(wycinek)); % tablica na sygnały target&lt;br /&gt;
for trialNumber = 1:length(targetTimeStamps)&lt;br /&gt;
    trigerOnset = floor(targetTimeStamps(trialNumber)*samplingFrequency);&lt;br /&gt;
    tenWycinek = wycinek + trigerOnset;&lt;br /&gt;
    if tenWycinek(1)&amp;gt;0 &amp;amp;&amp;amp; tenWycinek(end)&amp;lt;=size(samples,2) % test czy wycinek który chcemy pobrać nie wystaje poza dostępny sygnał&lt;br /&gt;
        tmpSignal = samples(:,tenWycinek);&lt;br /&gt;
        tmpSignal = detrend(tmpSignal')'; % usuwanie liniowego trendu - przy krótkich wycinkach działa lepiej niż filtrowanie górnoprzepustowe&lt;br /&gt;
        TargetSignal(trialNumber, :,:) = tmpSignal;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
% pobieramy non-targety&lt;br /&gt;
NonTargetSignal = zeros(length(NonTargetTimeStamps),numberOfChannels, length(wycinek));% tablica na sygnały non-target&lt;br /&gt;
for trialNumber = 1:length(NonTargetTimeStamps)&lt;br /&gt;
    trigerOnset = floor(NonTargetTimeStamps(trialNumber)*samplingFrequency);&lt;br /&gt;
    tenWycinek = wycinek + trigerOnset;&lt;br /&gt;
    if tenWycinek(1)&amp;gt;0 &amp;amp;&amp;amp; tenWycinek(end)&amp;lt;=size(samples,2)&lt;br /&gt;
        tmpSignal = samples(:,tenWycinek);&lt;br /&gt;
        tmpSignal = detrend(tmpSignal')';&lt;br /&gt;
        NonTargetSignal(trialNumber, :,:) = tmpSignal;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
%&lt;br /&gt;
% dla ilustracji podglądamy średnie po powtórzeniach ze wszystkich targetów&lt;br /&gt;
% i non-targetów&lt;br /&gt;
plot(squeeze(mean(TargetSignal,1))','r');&lt;br /&gt;
hold on&lt;br /&gt;
plot(squeeze(mean(NonTargetSignal,1))','b')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
===ZADANIE: Analiza CSP===&lt;br /&gt;
&lt;br /&gt;
Przegląd badań o P300: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2715154/&lt;br /&gt;
&lt;br /&gt;
Link do Read menager [https://drive.google.com/file/d/1OgOduK5Zn7GgNl5XdCyLWXHJ7wTJIWcC/view?usp=share_link]&lt;br /&gt;
&amp;lt;!---&lt;br /&gt;
[https://drive.google.com/open?id=0BzwQ_Lscn8yDS3RXNWdBbkxEQ2c]&lt;br /&gt;
---&amp;gt;&lt;br /&gt;
* Wykonać analizę CSP wzmacniającą potencjał P300.&lt;br /&gt;
* Zaprezentować średnią ze wszystkich kanałów źródłowych z warunku target (jeden kolor) i non-target (inny kolor) w subplotach ułożonych w prostokątnej siatce. Zaobserwować dla którego kanału średnie różnią się najbardziej. Czy jest związek tego kanału z wartościami własnymi?&lt;br /&gt;
&lt;br /&gt;
* Dla kanału najbardziej różnicującego wykonać mapki topograficzne (do wykonania tych mapek wykorzystać funkcję &amp;lt;tt&amp;gt;topoplot&amp;lt;/tt&amp;gt; z pakietu &amp;lt;tt&amp;gt;eeglab&amp;lt;/tt&amp;gt;) wektorów odpowiadających:&lt;br /&gt;
** filtrowi przestrzennemu &lt;br /&gt;
** rzutu topograficznego źródła na elektrody.&lt;br /&gt;
&amp;lt;!---&lt;br /&gt;
* Zbadać powtarzalność topografii pomiędzy plikami konfiguracyjnymi.&lt;br /&gt;
---&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{hidden begin|title=Wybór i separacja cech}}&lt;br /&gt;
&lt;br /&gt;
===Wybór i separacja cech===&lt;br /&gt;
* Przedstaw na rysunkach nałożone na siebie pojedyncze realizacje z warunków target i non-target po rzutowaniu na wektor &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; odpowiadający największej i kolejnej wartości  własnej. &lt;br /&gt;
* Przedstaw wykresy punktowe takie, że na jednej osi jest moc sygnału (suma kwadratów wartości próbek w wybranym zakresie czasu) odpowiadającego największej wartości własnej, a na drugiej osi kolejnej (mniejszej) wartości własnej; jeden punkt reprezentuje jedno powtórzenie.&lt;br /&gt;
* Wykonaj serię wykresów jak w poprzednim punkcie dla uśrednień sygnałów kolejno po 2, 4, 6, 8 i 10 realizacjach:&lt;br /&gt;
**  Liczymy potencjał wywołany dla danej liczby powtórzeń. &lt;br /&gt;
** Następnie podnosimy wartości próbek do kwadratu&lt;br /&gt;
**  i sumujemy je w wybranym zakresie czasu.&lt;br /&gt;
* Zaobserwuj jak zmienia się separacja w grupach target i non-target.&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
==Filtry przestrzenne dla SSEP ==&lt;br /&gt;
{{hidden begin|title=Filtry przestrzenne dla SSEP}}&lt;br /&gt;
=== Teoria===&lt;br /&gt;
Ciekawa koncepcja filtra przestrzennego dla SSVEP zaprezentowana jest  tu: http://www.eurasip.org/Proceedings/Eusipco/Eusipco2009/contents/papers/1569193209.pdf&lt;br /&gt;
&lt;br /&gt;
Pokrótce można ją rozumieć podobnie do tego co robiliśmy rozważając filtry przestrzenne CSP z tym, że dla SSVEP oraz innych potencjałów wywołanych stanu ustalonego możemy skorzystać z dodatkowych informacji dotyczących poszukiwanych źródeł. Wiemy mianowicie, że powinny one oscylować z częstością bodźca, i być może jej harmonicznych.&lt;br /&gt;
&lt;br /&gt;
Przyda nam się macierz &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; zbudowana tak, że w kolejnych kolumnach znajdują się sinusy i cosinusy kolejnych częstości harmonicznych. Wektory te unormujemy, żeby miały energię równą 1. Innymi słowy macierz &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; zbudowana jest z wersorów rozpinających przestrzeń, w której powinien znajdować się sygnał SSVEP.&lt;br /&gt;
&lt;br /&gt;
W matlabie możemy taką macierz zbudować tak:&lt;br /&gt;
&amp;lt;source lang = matlab&amp;gt;&lt;br /&gt;
% Fs - częstość próbkowania&lt;br /&gt;
% numberOfSamples - długość sygnału w próbkach&lt;br /&gt;
% numberOfHarmonics - liczba harmonicznych, które chcemy włączyć do analizy&lt;br /&gt;
t = (0:1:numberOfSamples - 1)/Fs; &lt;br /&gt;
S = zeros(numberOfSamples, 2*numberOfHarmonics);&lt;br /&gt;
&lt;br /&gt;
for harmonicNumber = 1:numberOfHarmonics&lt;br /&gt;
    c = cos(2*pi*stimulationFrequency*harmonicNumber*t);&lt;br /&gt;
    s = sin(2*pi*stimulationFrequency*harmonicNumber*t);&lt;br /&gt;
    S(:,(harmonicNumber - 1)*2 + 1) = c/norm(c);&lt;br /&gt;
    S(:,(harmonicNumber - 1)*2 + 2) = s/norm(s);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aby w badanym sygnale znaleźć składowe odpowiadające SSVEP musimy rzutować sygnał &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; (macierz sygnałów ''kanały &amp;amp;times; próbki'')  na przestrzeń rozpiętą przez &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = X*S&amp;lt;/math&amp;gt;&lt;br /&gt;
Macierz &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; zawiera współczynniki będące iloczynami skalarnymi sygnałów i wersorów. Mówią one o tym &amp;amp;bdquo;jak dużo&amp;amp;rdquo; jest sinusa bądź cosinusa o danej częstości w pierwotnym sygnale. Komponenty SSVEP zawarte w sygnale &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; odzyskujemy tak:&lt;br /&gt;
:&amp;lt;math&amp;gt;\mathrm{SSVEP} = A S^T&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modelujemy rejestrowany sygnał jako:&lt;br /&gt;
:&amp;lt;math&amp;gt;X = \mathrm{SSVEP} + Y &amp;lt;/math&amp;gt;&lt;br /&gt;
gdzie: &lt;br /&gt;
:&amp;lt;math&amp;gt;Y = X-\mathrm{SSVEP}&amp;lt;/math&amp;gt; &lt;br /&gt;
: to wszystkie komponenty sygnału, które nas nie interesują.&lt;br /&gt;
&lt;br /&gt;
Filtr przestrzenny, który chcemy zbudować powinien maksymalizować stosunek wariancji &amp;lt;math&amp;gt;\mathrm{SSVEP} = A S^T&amp;lt;/math&amp;gt; do wariancji &amp;lt;math&amp;gt;Y = X-\mathrm{SSVEP}&amp;lt;/math&amp;gt;. Macierz kowariancji powinna być uśredniona po powtórzeniach a kowariancja sygnału w każdym powtórzeniu powinna być znormalizowana poprzez podzielenie przez jej ślad (Matlabowa funkcja &amp;lt;tt&amp;gt;cov&amp;lt;/tt&amp;gt; już wykonuje tę operację).&lt;br /&gt;
Dalej możemy zastosować technikę znaną z konstrukcji filtrów CSP, tzn. maksymalizacji ilorazu Rayleigha za pomocą rozwiązania uogólnionego zagadnienia własnego dla macierzy kowariancji &amp;lt;math&amp;gt;\mathrm{SSVEP} &amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;Y &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Poniżej prosta demonstracja dla danych zebranych EEG przy stymulacji SSVEP z częstotliwością 38 Hz.===&lt;br /&gt;
Spakowane dane: [[Plik:PrzykladoweDaneSSVEP.mat.gz]].&lt;br /&gt;
W oparciu o powyższy opis proszę zaimplementować  funkcję &amp;lt;tt&amp;gt;cosSinCSP&amp;lt;/tt&amp;gt;. Prawidłowo zaimplementowana funkcja wraz z poniższym kodem powinna generować rysunek:&lt;br /&gt;
[[Plik:Rys_SSVEP_demo.png|400px|podpis grafiki]] &lt;br /&gt;
Przykładowy skrypt i dane prezentujący konstrukcję i działanie tego typu filtrów przestrzennych dla pełnych danych z eksperymentu SSVEP: [[Plik:SSVEP_demo_csp.tar.gz]]&lt;br /&gt;
&lt;br /&gt;
{{hidden begin|title=przykładowy skrypt}}&lt;br /&gt;
&amp;lt;source lang = matlab&amp;gt;&lt;br /&gt;
% wczytujemy dane&lt;br /&gt;
load('PrzykladoweDaneSSVEP.mat');&lt;br /&gt;
&lt;br /&gt;
[numberOfTrials numberOfChannels numberOfSamples] = size(X.data);&lt;br /&gt;
namesOfChannels = X.channels;&lt;br /&gt;
 &lt;br /&gt;
% numberOfChannels numberOfSamples numberOfTrials&lt;br /&gt;
W = zeros(numberOfChannels,numberOfChannels);&lt;br /&gt;
numberOfHarmonics = 3;&lt;br /&gt;
signal = X.data; % (  powtórzenie,  kanał, próbki)&lt;br /&gt;
 &lt;br /&gt;
S = zeros(size(signal));&lt;br /&gt;
W = cosSinCSP(signal,X.stimulation,numberOfHarmonics,X.sampling);&lt;br /&gt;
for powt = 1:size(signal,1)&lt;br /&gt;
    S(powt,:,:) = W'*squeeze(signal(powt,:,:));&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
figure('Name',['Stymulacja: ',num2str(X.stimulation),' Hz'])&lt;br /&gt;
for i =1:numberOfChannels&lt;br /&gt;
    % rysujemy widma uśrednione po realizacjach dla danych &lt;br /&gt;
    % z oryginalnych kanałów EEG&lt;br /&gt;
    subplot(2,8,i)&lt;br /&gt;
    PP=0;&lt;br /&gt;
    for rep = 1:numberOfTrials&lt;br /&gt;
        x = squeeze(signal(rep,i,:));&lt;br /&gt;
        [Pxx,ff] = pwelch(x, X.sampling, 1, X.sampling, X.sampling);&lt;br /&gt;
        PP =PP + Pxx;&lt;br /&gt;
    end&lt;br /&gt;
    plot(ff(ff&amp;lt;60),PP(ff&amp;lt;60))&lt;br /&gt;
    title(namesOfChannels{i})&lt;br /&gt;
 &lt;br /&gt;
    % rysujemy widma uśrednione po realizacjach dla danych &lt;br /&gt;
    % z estymowanych źródeł CSP&lt;br /&gt;
    subplot(2,8,8+i)&lt;br /&gt;
    PP=0;&lt;br /&gt;
    for rep = 1:numberOfTrials&lt;br /&gt;
        s = squeeze(S(rep,i,:));&lt;br /&gt;
        [Pss,ff]=pwelch(s, X.sampling, 1, X.sampling, X.sampling);&lt;br /&gt;
        PP =PP + Pss;&lt;br /&gt;
    end&lt;br /&gt;
    plot(ff(ff&amp;lt;60),PP(ff&amp;lt;60))&lt;br /&gt;
    title(['źródło CSP: ', num2str(i)])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====ZADANIE: Analiza danych z eksperymentu własnego ====&lt;br /&gt;
# Przefiltruj sygnały EEG w paśmie 1-45 Hz za pomocą procedury &amp;lt;tt&amp;gt;filtfilt&amp;lt;/tt&amp;gt;. &lt;br /&gt;
# Na podstawie sygnału trigger oraz danych zapisanych w pliku wyodrębnij sygnały EEG zarejestrowane w trakcie stymulacji z odpowiednimi częstościami.&lt;br /&gt;
# Uśrednij sygnały odpowiadające stymulacji tą samą częstością. &lt;br /&gt;
# Obejrzyj uśrednione sygnały. (Zaprezentuj je).&lt;br /&gt;
&lt;br /&gt;
#* Sposób I:&lt;br /&gt;
#**Dla każdej realizacji wyestymuj przy pomocy metody Welcha widmo mocy sygnału EEG. &lt;br /&gt;
#**Dla każdej częstości stymulacji wyznacz poziom tła na podstawie widm pochodzących ze stymulacji innymi częstościami. Np. dla stymulacji częstością 10 Hz poziom tła można wyznaczyć jako 95 centyl ze zbioru wartości widma w częstości 10 Hz dla stymulacji częstościami {4, 7, 13, 16, 20, 25, 30, 35, 40} Hz. &lt;br /&gt;
#**Dla każdej częstości stymulacji wyznacz miarę odpowiedzi SSVEP (amplitudę widma odpowiadającą częstości stymulacji powyżej poziomy tła dla pojedynczej próby). &lt;br /&gt;
#**Zaprezentuj widma otrzymane przy stymulacjach różnymi częstościami wraz z korytarzem odpowwiadajacym 95% przedziałowi ufności wyznaczonemu dla widm z pojedynczych realizacji.&lt;br /&gt;
#**Sporządź wykres odpowiedzi SSVEP od częstości z zaznaczeniem przedziałów ufności i poziomu tła. &lt;br /&gt;
#* Sposób II:&lt;br /&gt;
#**Wyestumuj filtr CSP-SSVEP wspólny dla wszystkich częstości stymulacji &lt;br /&gt;
#**Powtórz kroki ze sposobu I dla uzyskanych komponentów.&lt;br /&gt;
#**Zaprezentuj filtry przestrzenne i topografie dla poszczególnych komponentów&lt;br /&gt;
#**Dla przypomnienia:&lt;br /&gt;
#***Filtr to zestaw współczynników z jakimi należy zsumować sygnały z poszczególnych kanałów EEG aby dostać komponenty odpowiadające hipotetycznym źródłom nieskorelowanym. Filtr można zilustrować na głowie, przypisując poszczególnym pozycjom elektrod wagi równe współrzędnym wektora w (kolumna macierzy W).&lt;br /&gt;
#***Topografia źródła to zestaw współczynników z jakimi docierają one do poszczególnych kanałów EEG. Topografia zawarta jest w wierszach macierzy odwrotnej do W. &lt;br /&gt;
#**Można rysunki wykonać jako macierze 5x5 i w pozycji elektrody kolorujemy proporcjonalnie do współczynnika.&lt;br /&gt;
&lt;br /&gt;
===SSVEP-BCI===&lt;br /&gt;
W zajęciach tych przydadzą nam się informacje z:&lt;br /&gt;
https://brain.fuw.edu.pl/edu/index.php/Laboratorium_EEG/Wprowadzenie_do_syg_online&lt;br /&gt;
====Wstęp====&lt;br /&gt;
Naszym celem będzie stworzenie prostego interfejsu wykorzystującego zjawisko SSVEP. &lt;br /&gt;
Po dwóch stronach monitora zamocujemy diody. Każda będzie migać ze swoją ustaloną częstością (np. 16 i 22 Hz) - warto zadbać aby nie były to częstości powiązane ze sobą harmonicznie, a z drugiej strony aby, biorąc pod uwagę wyniki poprzedniego zadania, dawały dobra odpowiedź SSVEP.&lt;br /&gt;
&lt;br /&gt;
Eksperyment będzie miał dwie cześci: sesję kalibracje i sesję on-line. Pomiędzy tymi sesjami będziemy uczyć kalsyfikator. Na podstawie części kalibracyjnej ustalimy jakie parametry przetwarznego on-line sygnału świadczą o patrzeniu się na diodę z lewej a jakie na tą z prawej strony ekranu.&lt;br /&gt;
&lt;br /&gt;
Potem w sesji online będziemy porównywać (za pomocą predykcji klasyfikatora) rejestrowany sygnał z tymi warościami kalibracyjnymi i na tej podstawie system będzie zwracał informację o wyborze lewej lub prawej diody. To powinno umożliwić prostą komunikację na zasadzie pytanie i odpowiedź TAK/NIE.&lt;br /&gt;
&lt;br /&gt;
==== Sesja kalibracycjna====&lt;br /&gt;
* Zakładamy czepek&lt;br /&gt;
* Częstość próbkowania ustawiamy na 256Hz&lt;br /&gt;
* Na podstawie kodu: https://brain.fuw.edu.pl/edu/index.php/Laboratorium_EEG/Wprowadzenie_do_syg_online#.C4.86wiczenie:_Wykorzystanie_pomiaru_EMG_do_sterowania_on-line&lt;br /&gt;
tworzymy programik, który zamiast pętli while tworzy odpowiednie pętle for aby:&lt;br /&gt;
* pięciokrotnie zarejestrować sekwencję trzech warunków eksperymentalnych:&lt;br /&gt;
** patrz 5s na diodę z lewej (warunek l)&lt;br /&gt;
** patrz 5s na środek ekranu (warunek s)&lt;br /&gt;
** patrz 5s na diodę z prawej (warunek p)&lt;br /&gt;
* w czasie tego patrzenia:&lt;br /&gt;
** odbieramy próbki w pakietach o długości 0.5s &lt;br /&gt;
** każdy pakiet filtrujem (technika filtrowania on-line) w pasmach dookoła wybranych dwóch częstości (PASMO_LEWE / PASMO_PRAWE)&lt;br /&gt;
** przefiltrowany pakiet przeliczamy na RMS&lt;br /&gt;
** zbieramy sześć zbiorów wyników -  zestawy RMSów związane z każdym z waunków kalibracyjnych (LEWY/SPOCZYNEK/PRAWY) dla PASMO_LEWE i PASMO_PRAWE.&lt;br /&gt;
* Normalizujemy RMSy. Dla pasma lewego obliczamy (RMS_(l/p/s) - np.mean(RMS_s)) / np.sdt(RMS_s) i analogicznie dla pasma prawego. Małe indeksy oznaczaają tu warunki. Zapamiętujemy współczynniki normalizacyjne.&lt;br /&gt;
** Ogladamy rozkłady uzyskanych wielkości (znormalizowanych RMSów). &lt;br /&gt;
** Uczymy klasyfikator np. regresję logistyczną (https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html) do rozpoznawania, z którym warunkiem patrzenia mamy do czynienia.&lt;br /&gt;
&lt;br /&gt;
==== Sesja online====&lt;br /&gt;
* wczytujemy wyuczony model i kalibracyjne wartości np.mean(RMS_s)) i np.sdt(RMS_s) dla pasm lewego i prawego&lt;br /&gt;
* Odbieramy próbki w pakietach o długości 0.5s &lt;br /&gt;
** każdy pakiet filtrujem (technika filtrowania on-line) w pasmach dookoła wybranych dwóch częstości (PASMO_LEWE / PASMO_PRAWE)&lt;br /&gt;
** przefiltrowany pakiet przeliczamy na RMS&lt;br /&gt;
** Normalizujemy RMSy. Dla pasma lewego obliczamy (RMS_(l/p/s) - np.mean(RMS_s)) / np.sdt(RMS_s) i analogicznie dla pasma prawego. Małe indeksy oznaczaają tu warunki.&lt;br /&gt;
** robimy predykcję klasyfikatora, z którym warunkiem patrzenia mamy do czynienia. Wyświetlamy na ekranie komunikat.&lt;br /&gt;
* Testujemy czy powyższy schemat analizy pozwala na komunikację.&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Eksperyment ASSR===&lt;br /&gt;
W eksprymencie wykorzystujemy układ do generacji potencjałów słuchowych stanu ustalonego (ASSR). Wejście układu ASSR typu mini-jack wkładamy w wyjście słuchawkowe w laptopie. Drugie wejście układu ASSR wkładamy do wyjścia triggera we wzmacniaczu. Uruchamiamy plik dźwiękowy MM40tr.wav. Można go znalezc w: http://www.fuw.edu.pl/~suffa/LabEEG/MM40tr.wav&lt;br /&gt;
&lt;br /&gt;
Stymulacja dźwiękowa składa sie z fali nośnej o częstości 400 Hz modulowanej z częstością 40 Hz. Plik dźwiękowy zawiera 5 sekund ciszy i 5 sekund stymulacji, powtórzone 40 razy.&lt;br /&gt;
&lt;br /&gt;
====Rejestracja sygnału====&lt;br /&gt;
# Zakładamy czepek i elektrody w systemie 10-10, dbamy o to by opory pomiędzy elektrodami były poniżej 5 k&amp;amp;Omega; i różnice pomiędzy oporami różnych elektrod nie przekraczały 20%.&lt;br /&gt;
# Oklejamy kwadrat 3&amp;amp;times;3 elektrod na korze słuchowej z lewej strony (elektrody FT7, FC5, FC3, T7, C5, T3, TP7, CP5, CP3), 3&amp;amp;times;3 elektrod na korze słuchowej z prawej strony (elektrody FT8, FC6, FC4, T8, C6, T4, TP8, CP6, CP4), elektrody Fz, Cz, Pz i Oz, elektrody referencyjne A1 i A2. W sumie powinno być 24 elektrody.&lt;br /&gt;
# Elektrodę GND mocujemy na pozycji AFz.&lt;br /&gt;
# Sygnał rejestrujemy z częstością 2048 Hz.&lt;br /&gt;
# Do rejestracji stosujemy scenariusz 'ASSR' w interfejsie obci_gui.&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
 JZ: zmieniłbym analizę na czas-częstość i zrobił porównanie montażu usznego do filtra G.G. Moliny&lt;br /&gt;
&lt;br /&gt;
Początek stymulacji dźwiękowej oznaczymy jako 0. Poniższą analizę zastosuj dla sygnałów w referencji do uśrednionych odprowadzeń usznych A1 i A2.&lt;br /&gt;
Wyznaczenie pasma częstości odpowiedzi ASSR&lt;br /&gt;
# Z sygnału wycinamy fragmenty od 0 do 5 sek. dla wszystkich elektrod położone nad korą słuchową.&lt;br /&gt;
# Dla każdej realizacji obliczamy widma metodą Welcha.&lt;br /&gt;
# Otrzymane zespolone widma uśredniamy po realizacjach.&lt;br /&gt;
# Sprawdzamy czy w uśrednionym widmie występuję maksimum w częstości modulacji tj. 40 Hz.&lt;br /&gt;
&lt;br /&gt;
====Wyznaczenie przebiegu czasowego ERD i ERS====&lt;br /&gt;
# Zaprojektuj filtry pasmowo przepustowe (Czebyszewa 2 rodzaju) zgodne z wyznaczonym pasmem. Zbadaj funkcje przenoszenia i odpowiedzi impulsowej.&lt;br /&gt;
# Powycinaj sygnały od &amp;amp;minus;5 do +10 sekund (wszystkie kanały). Przefiltruj każdą realizację.&lt;br /&gt;
# Oblicz moc chwilową za pomocą transformaty Hilberta (kwadrat modułu transformaty Hilberta).&lt;br /&gt;
# Uśrednij moc chwilową po realizacjach.&lt;br /&gt;
# Oblicz względną zmianę mocy chwilowej względem czasu &amp;amp;minus;4 do &amp;amp;minus;2 s. W ten sposób otrzymasz przebieg ERD i ERS w czasie.&lt;br /&gt;
# Wykreśl ERD i ERS w układzie topograficznym. (Rozmieść subploty tak, aby z w przybliżeniu odpowiadały pozycjom elektrod).&lt;br /&gt;
&lt;br /&gt;
====Transformacja Hjortha====&lt;br /&gt;
Transformacja Hjortha jest przybliżeniem numerycznym transformacji Laplace'a, czyli drugiej pochodnej przestrzennej. Obliczamy ją jako różnicę potencjału pomiędzy daną elektrodą i średnią z czterech sąsiednich elektrod.&lt;br /&gt;
Przelicz potencjały z elektrod, w których występuję odpowiedź ASSR na montaż Hjortha i powtórz analizę ERD/ERS opisaną powyżej.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ICA jako filtr przestrzenny==&lt;br /&gt;
{{hidden begin|title=Wstęp teoretyczny do ICA}}&lt;br /&gt;
===Definicja ===&lt;br /&gt;
Independent Component Analysis (ICA) jest metodą statystycznej analizy sygnałów, która dokonuje dekompozycji wielokanałowych zapisów na składowe niezależne w sensie statystycznym.&lt;br /&gt;
Dwie składowe ''s''&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; i ''s''&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; są niezależne jeżeli wiedza o wartości ''s''&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; nie daje żadnych informacji o możliwych wartościach ''s''&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. ICA może być wyrażona przez prosty model generatywny:&lt;br /&gt;
: '''x''' = '''Ds'''&lt;br /&gt;
: gdzie '''x''' = {''x''&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;, ''x''&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;, ..., ''x''&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;} jest zmierzonym ''n'' kanałowym sygnałem, '''D''' jest macierzą mieszającą zaś '''s''' = {''s''&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;, ''s''&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;, ..., ''s''&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;} jest aktywnością ''n'' źródeł. Podstawowym założeniem dotyczącym '''s''' jest to, że ''s''&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt; są statystycznie niezależne.  Aby wyestymować model musimy też założyć, że składowe mają niegaussowskie rozkłady wartości (Hyvärinen, 2000).&lt;br /&gt;
&lt;br /&gt;
Dodatkowo model ten zakłada następujące fakty:&lt;br /&gt;
# Sygnał jest liniową mieszaniną aktywności źródeł&lt;br /&gt;
# Sygnały pochodzące z każdego ze źródeł są niezależne od pozostałych&lt;br /&gt;
# Źródła oraz proces ich mieszania są stacjonarne, tzn, ich momenty statystyczne nie zależą od czasu&lt;br /&gt;
# Energie (wariancje) źródeł nie mogą być wyznaczone jednoznacznie. Dzieje się tak ponieważ pomnożenie amplitudy ''i''-tego źródła może być uzyskane poprzez przemnożenie albo ''s''&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt; albo przez przemnożenie ''i''-tej kolumny macierzy '''D'''.  Naturalnym rozwiązaniem tej niejednoznaczności jest wprowadzenie konwencji, że komponenty są normowane tak aby miały wariancję 1: E[(''s''&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt;)&amp;lt;sup&amp;gt;''2''&amp;lt;/sup&amp;gt;] = 1.&lt;br /&gt;
# Kolejność komponentów jest dowolna.  Bo jeśli w ten sam sposób zmienimy kolejność komponentów w '''s''' i kolumn w '''D''' to dostaniemy dokładnie ten sam sygnał '''x'''.&lt;br /&gt;
&lt;br /&gt;
Głównym wyzwaniem w analizie ICA jest estymacja macierzy mieszającej '''D'''. Gdy jest ona znana to komponenty mogą być wyliczone w następujący sposób:&lt;br /&gt;
: '''s''' = '''D'''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt;'''x'''&lt;br /&gt;
&lt;br /&gt;
=== Estymacja ===&lt;br /&gt;
Znalezienie niezależnych komponentów może być rozważane w świetle Centralnego Twierdzenia Granicznego jako poszukiwanie komponentów o możliwie nie gaussowskim rozkładzie.&lt;br /&gt;
Aby zrozumieć to podejście prześledźmy heurystykę zaproponowaną przez (Hyvärinen, 2000). &lt;br /&gt;
Dla prostoty załóżmy, że poszukiwane źródła niezależne mają identyczne rozkłady. &lt;br /&gt;
Zdefiniujmy &lt;br /&gt;
&lt;br /&gt;
''y''&amp;amp;nbsp;= '''w'''&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt;'''x'''.&lt;br /&gt;
&lt;br /&gt;
Zauważmy, że jeśli &lt;br /&gt;
&lt;br /&gt;
'''w''' &lt;br /&gt;
&lt;br /&gt;
jest jedną z kolumn macierzy &lt;br /&gt;
&lt;br /&gt;
'''D'''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt;, &lt;br /&gt;
&lt;br /&gt;
to ''y'' jest jednym z poszukiwanych komponentów.&lt;br /&gt;
Zamieniając zmienne &lt;br /&gt;
&lt;br /&gt;
'''z'''&amp;amp;nbsp;= '''D'''&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt;'''w''' &lt;br /&gt;
&lt;br /&gt;
możemy napisać &lt;br /&gt;
&lt;br /&gt;
''y''&amp;amp;nbsp;= '''w'''&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt;'''x'''&amp;amp;nbsp;= '''w'''&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt;'''Ds'''&amp;amp;nbsp;= '''z'''&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt;'''s'''. &lt;br /&gt;
&lt;br /&gt;
Uwidacznia to fakt, że ''y'' jest liniową kombinacją składowych s&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt; z wagami danymi przez z&amp;lt;sub&amp;gt;''i''&amp;lt;/sub&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Z centralnego twierdzenia granicznego wynika, że suma niezależnych zmiennych losowych ma  bardziej gaussowski charakter niż każda z tych zmiennych osobno. &lt;br /&gt;
Liniowa kombinacja staje się najmniej gaussowska gdy '''z''' ma tylko jeden element niezerowy. W tym przypadku ''y'' jest proporcjonalny do s&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt;. &lt;br /&gt;
Zatem problem estymacji modelu ICA może być sformułowany jako problem znalezienia takiego wektora '''w''', który maksymalizuje niegaussowskość &lt;br /&gt;
&lt;br /&gt;
''y''&amp;amp;nbsp;= '''w'''&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt;'''x'''. &lt;br /&gt;
&lt;br /&gt;
Maksymalizacja niegaussowskości ''y'' daje jeden niezależny komponent odpowiadający jednemu z 2''n'' maksimów (bo mamy s&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt; i &amp;amp;minus;s&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt;) w krajobrazie optymalizacyjnym. Aby znaleźć wszystkie niezależne komponenty musimy znaleźć wszystkie maksima. Ponieważ komponenty są nieskorelowane, to poszukiwania kolejnych komponentów można kontynuować w podprzestrzeni ortogonalnej do już znalezionych komponentów.&lt;br /&gt;
&lt;br /&gt;
===Obliczenia===&lt;br /&gt;
Intuicyjna heurystyka poszukiwania najbardziej niegaussowskich składowych może być użyta do wyprowadzenia różnych funkcji kosztu, których optymalizacja daje model ICA, np. kurtoza.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;kurt(y) = E\{y^4\} - 3(E{y^2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inną miarą gassowskości jest neg-entropia, którą można wyprowadzić z entropii: &lt;br /&gt;
Entropia jest miarą średniego zdziwienia wynikiem obserwacji zmiennej losowej:&lt;br /&gt;
&amp;lt;math&amp;gt;H(Y) = - \sum_i P(Y= a_i) \log(P(Y=a_i)) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Negentropia jest zdefiniowana:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; J(y) = H(y_{gauss}) -H(y)&amp;lt;/math&amp;gt;&lt;br /&gt;
gdzie &amp;lt;math&amp;gt; y_{gauss} &amp;lt;/math&amp;gt; jest gassuwską zmienną losową o takiej samej kowaiancji jak &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Negentropia jest skomplikowana obliczeniow, więc w praktyce używana jest formuła przybliżona:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; J(y) \varpropto   [E\{G (y)\}  - E\{G(\nu)\}]&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\nu &amp;lt;/math&amp;gt; jest zmienną losową ze standardowego rozkładu normalnego , a G są pewnymi niekwadratowymi funkcjami.&lt;br /&gt;
&lt;br /&gt;
W algorytmie FastICA extremum negentropii jest znajdowane w procedurze bazującej na optymalizacji Netwona.&lt;br /&gt;
(szczegóły np.: sekcja 6 w https://www.cs.helsinki.fi/u/ahyvarin/papers/NN00new.pdf)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedura wykorzystywana w eeglabie (&amp;amp;bdquo;runica&amp;amp;rdquo;, Makeig 1996) dąży do minimalizacji informacji wzajemnej. Oba podejścia są w przybliżeniu równoważne (Hyvärinen, 2000), chociaż owo przybliżenie dla  sygnałów elektrofizjologicznych nie zostało to jeszcze w pełni wyeksplorowane.&lt;br /&gt;
Dla sygnałów o niskiej wymiarowości i spełniających dokładnie założenia ICA wszystkie powszechnie wykorzystywane algorytmy dają niemal identyczne wyniki.&lt;br /&gt;
&lt;br /&gt;
;Bardzo ważna uwaga: ogólną zasadą jest, że jeśli estymujemy ''N'' stabilnych komponentów  (z ''N''-kanałowych danych) to musimy dysponować ''kN''&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; punktami danych w każdym kanale, gdzie ''N''&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; jest liczbą elementów w macierzy '''D''', którą ICA próbuje wyestymować, ''k'' jest liczbą całkowitą. Nie ma dobrych oszacowań teoretycznych na wielkość ''k'', z praktycznych obserwacji wynika, że rośnie ona z liczbą kanałów.&lt;br /&gt;
&lt;br /&gt;
=== Możliwe zastosowania ===&lt;br /&gt;
Najczęściej ICA jest stosowana jako narzędzie do:&lt;br /&gt;
* usuwania artefaktów z sygnałów EEG (ruchy oczu i mięśnie) &lt;br /&gt;
* wydobywania składowych do dalszej analizy (Onton, 2006)&lt;br /&gt;
* jako analiza wstępna do lokalizacji źródeł (Grau, 2007).&lt;br /&gt;
* ICA jest także stosowana w analize sygnałów EKG i EMG.&lt;br /&gt;
&lt;br /&gt;
===Bibliografia===&lt;br /&gt;
Bazowa praca:&lt;br /&gt;
* A. Hyvärinen. Fast and Robust Fixed-Point Algorithms for Independent Component Analysis. IEEE Transactions on Neural Networks 10(3):626-634, 1999 http://www.cs.helsinki.fi/u/ahyvarin/papers/TNN99_reprint.pdf&lt;br /&gt;
&lt;br /&gt;
Nieco prościej opisana wersja z przykładami:&lt;br /&gt;
* Hyvärinen, A. and Oja, E. (2000). Independent component analysis: Algorithms and applications. Neural Networks, 13(4-5):411–430.&lt;br /&gt;
https://www.cs.helsinki.fi/u/ahyvarin/papers/NN00new.pdf&lt;br /&gt;
&lt;br /&gt;
* Grau, C., Fuentemilla, L., Marco-Pallars, J. (2007). Functional neural dynamics underlying auditory event-related n1 and n1 suppression response. Neuroimage, 36(6):522–31.&lt;br /&gt;
* Makeig, S., Bell, A., Jung, T.-P., Sejnowski,T. (1996). Independent component analysis of electroencephalographic data. W: Touretzky, D., Mozer, M., and Hasselmo, M., editors, Advances in Neural Information Processing Systems, volume 8, pages 145–151. MIT Press, Cambridge, MA.&lt;br /&gt;
* Onton, J., Makeig, S. (2006). Information-based modeling of event-related brain dynamics. Prog Brain Res., 159:99–120.&lt;br /&gt;
* Tutorial: http://sccn.ucsd.edu/wiki/Chapter_09:_Decomposing_Data_Using_ICA&lt;br /&gt;
* http://sccn.ucsd.edu/~arno/indexica.html&lt;br /&gt;
* http://cis.legacy.ics.tkk.fi/aapo/papers/IJCNN99_tutorialweb/&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
{{hidden begin|title=Wydobywanie interesujących komponentów}}&lt;br /&gt;
&lt;br /&gt;
=== ZADANIE: Wydobywanie interesujących komponentów ===&lt;br /&gt;
&lt;br /&gt;
Dane do tej części ćwiczeń proszę pobrać i rozpakować w swoim katalogu:&lt;br /&gt;
http://www.fuw.edu.pl/~jarekz/LabEEG/Dane_do_ICA_alfa.tar.gz&lt;br /&gt;
&lt;br /&gt;
Pochodzą one z eksperymentu, w którym osoba badana siedziała z zamkniętymi oczami słuchając nagrania czytanego spokojnym głosem. Metadane opisujące sygnał znajdują się w pliku Miro.xml, zaś lokalizacje elektrod w pliku Miro-10-20-Cap.locs.&lt;br /&gt;
&lt;br /&gt;
Proszę:&lt;br /&gt;
* wczytać dane do eeglaba&lt;br /&gt;
* wyedytować lokalizację elektrod&lt;br /&gt;
* usunąć kanały nie zawierające EEG&lt;br /&gt;
* zmienić referencje na średnią z kanałów A1 i A2&lt;br /&gt;
* przefiltrować filtrem FIR górnoprzepustowym z częstością odcięcia 0,5 Hz&lt;br /&gt;
* obejrzeć wstępnie przygotowane dane&lt;br /&gt;
* policzyć ICA na całym sygnale &lt;br /&gt;
* obejrzeć właściwości otrzymanych komponentów&lt;br /&gt;
** Czy są wśród nich takie, które zawierają znaczny udział rytmu alfa?&lt;br /&gt;
** Jaka jest ich topografia?&lt;br /&gt;
* usunąć wszystkie komponenty nie zawierające alfy&lt;br /&gt;
* odtworzyć z tych komponentów sygnał na elektrodach&lt;br /&gt;
* wykonać dekompozycję ICA kilkukrotnie (co najmniej 3) i porównać wyniki&lt;br /&gt;
** Czy uzyskiwane komponenty są powtarzalne? &lt;br /&gt;
** Swoje wyniki porównać też z sąsiednimi grupami.&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
===ZADANIE: Identyfikacja artefaktów ===&lt;br /&gt;
Proszę pobrać dane:&lt;br /&gt;
&lt;br /&gt;
*http://www.fuw.edu.pl/~jarekz/LabEEG/Arousal-10-20-Cap.locs&lt;br /&gt;
*http://www.fuw.edu.pl/~jarekz/LabEEG/Arousal1.set&lt;br /&gt;
*http://www.fuw.edu.pl/~jarekz/LabEEG/Arousal1.fdt&lt;br /&gt;
&lt;br /&gt;
Pochodzą one z eksperymentu w którym osoba badana czytała słowa o różnych właściwościach wzbudzania emocji. &lt;br /&gt;
&lt;br /&gt;
* wczytaj je do eeglaba&lt;br /&gt;
* wczytaj lokalizację kanałów z pliku Arousal-10-20-Cap.locs&lt;br /&gt;
* obejrzyj przebiegi czasowe&lt;br /&gt;
* odrzuć kanał z diodą (21) i z GSR (20)&lt;br /&gt;
* zrób dekompozycję ICA&lt;br /&gt;
* obejrzyj topografię komponentów&lt;br /&gt;
* zidentyfikuj komponenty odpowiadające mruganiu i aktywności mięśniowej.&lt;br /&gt;
;UWAGA: Aktualnie do wykrywania komponentów artefaktowych warto posłużyć się wtyczkami do eeglaba dostępnymi przez stronę:&lt;br /&gt;
&lt;br /&gt;
https://sccn.ucsd.edu/eeglab/plugin_uploader/plugin_list_all.php&lt;br /&gt;
&lt;br /&gt;
* ICLabel&lt;br /&gt;
* MARA&lt;br /&gt;
&lt;br /&gt;
====W raporcie: ====&lt;br /&gt;
* zaprezentuj fragmenty sygnału zawierającego artefakty oczne i mięśniowe przed i po zastosowaniu czyszczenia poprzez usuwanie komponentów zdominowanych przez artefakty. &lt;br /&gt;
* zaprezentuj topografię i przebiegi czasowe komponentów zidentyfikowanych jako artefakty oczne i mięśniowe. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
==Filtry przestrzenne dla większej ilości warunków==&lt;br /&gt;
===FFDIAG===&lt;br /&gt;
===Analiza ERD/S z użyciem FFDIAG===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!---&lt;br /&gt;
==Eksperyment ASSR==&lt;br /&gt;
W eksprymencie wykorzystujemy układ do generacji potencjałów słuchowych stanu ustalonego (ASSR). Wejście układu ASSR typu mini-jack wkładamy w wyjście słuchawkowe w laptopie. Drugie wejście układu ASSR wkładamy do wyjścia triggera we wzmacniaczu. Uruchamiamy plik dźwiękowy MM40tr.wav. Można go znalezc w: http://www.fuw.edu.pl/~suffa/LabEEG/MM40tr.wav&lt;br /&gt;
&lt;br /&gt;
Stymulacja dźwiękowa składa sie z fali nośnej o częstości 400 Hz modulowanej z częstością 40 Hz. Plik dźwiękowy zawiera 5 sekund ciszy i 5 sekund stymulacji, powtórzone 40 razy.&lt;br /&gt;
&lt;br /&gt;
===Rejestracja sygnału===&lt;br /&gt;
# Zakładamy czepek i elektrody w systemie 10-10, dbamy o to by opory pomiędzy elektrodami były poniżej 5 k&amp;amp;Omega; i różnice pomiędzy oporami różnych elektrod nie przekraczały 20%.&lt;br /&gt;
# Oklejamy kwadrat 3&amp;amp;times;3 elektrod na korze słuchowej z lewej strony (elektrody FT7, FC5, FC3, T7, C5, T3, TP7, CP5, CP3), 3&amp;amp;times;3 elektrod na korze słuchowej z prawej strony (elektrody FT8, FC6, FC4, T8, C6, T4, TP8, CP6, CP4), elektrody Fz, Cz, Pz i Oz, elektrody referencyjne A1 i A2. W sumie powinno być 24 elektrody.&lt;br /&gt;
# Elektrodę GND mocujemy na pozycji AFz.&lt;br /&gt;
# Sygnał rejestrujemy z częstością 2048 Hz.&lt;br /&gt;
# Do rejestracji stosujemy scenariusz 'ASSR' w interfejsie obci_gui.&lt;br /&gt;
&lt;br /&gt;
===Analiza===&lt;br /&gt;
Początek stymulacji dźwiękowej oznaczymy jako 0. Poniższą analizę zastosuj dla sygnałów w referencji do uśrednionych odprowadzeń usznych A1 i A2.&lt;br /&gt;
Wyznaczenie pasma częstości odpowiedzi ASSR&lt;br /&gt;
# Z sygnału wycinamy fragmenty od 0 do 5 sek. dla wszystkich elektrod położone nad korą słuchową (odcinki podczas stymulacji oraz bez niej).&lt;br /&gt;
# Dla każdej realizacji (odpowiedniego typu) obliczamy widma metodą Welcha.&lt;br /&gt;
# Otrzymane zespolone widma uśredniamy po realizacjach.&lt;br /&gt;
# Sprawdzamy czy w uśrednionym widmie występuję maksimum w częstości modulacji tj. 40 Hz i czy jest różnica między odcinkami ze stymulacją i bez niej.&lt;br /&gt;
&lt;br /&gt;
===Wyznaczenie przebiegu czasowego ERD i ERS===&lt;br /&gt;
# Zaprojektuj filtry pasmowo przepustowe (Czebyszewa 2 rodzaju) zgodne z wyznaczonym pasmem. Zbadaj funkcje przenoszenia i odpowiedzi impulsowej.&lt;br /&gt;
# Powycinaj sygnały od &amp;amp;minus;5 do +10 sekund (wszystkie kanały). Przefiltruj każdą realizację.&lt;br /&gt;
# Oblicz moc chwilową za pomocą transformaty Hilberta (kwadrat modułu transformaty Hilberta).&lt;br /&gt;
# Uśrednij moc chwilową po realizacjach.&lt;br /&gt;
# Oblicz względną zmianę mocy chwilowej względem czasu &amp;amp;minus;4 do &amp;amp;minus;2 s. W ten sposób otrzymasz przebieg ERD i ERS w czasie.&lt;br /&gt;
# Wykreśl ERD i ERS w układzie topograficznym. (Rozmieść subploty tak, aby z w przybliżeniu odpowiadały pozycjom elektrod).&lt;br /&gt;
&lt;br /&gt;
===Transformacja Hjortha===&lt;br /&gt;
Transformacja Hjortha jest przybliżeniem numerycznym transformacji Laplace'a, czyli drugiej pochodnej przestrzennej. Obliczamy ją jako różnicę potencjału pomiędzy daną elektrodą i średnią z czterech sąsiednich elektrod.&lt;br /&gt;
Przelicz potencjały z elektrod, w których występuję odpowiedź ASSR na montaż Hjortha i powtórz analizę opisaną powyżej.&lt;br /&gt;
---&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG/CSP&amp;diff=11254</id>
		<title>Laboratorium EEG/CSP</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG/CSP&amp;diff=11254"/>
		<updated>2025-04-16T09:01:59Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Estymacja */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Laboratorium_EEG]]/BSS&lt;br /&gt;
&lt;br /&gt;
=Prezentacja=&lt;br /&gt;
[https://brain.fuw.edu.pl/edu/images/2/2f/BSS.pdf slajdy z prezentacji]&lt;br /&gt;
&lt;br /&gt;
=Ślepa separacja źródeł (BSS)=&lt;br /&gt;
{{hidden begin|title=Wstęp teoretyczny do BSS}}&lt;br /&gt;
Rozważmy ''N''-kanałowy sygnał EEG.&lt;br /&gt;
Próbkę tego sygnału możemy przedstawić jako punkt w przestrzeni rozpiętej przez osie, z których każda reprezentuje wartość potencjału w jednym kanale. Cały sygnał tworzy w tej przestrzeni chmurę punktów. Rozciągłość tej chmury w danym kierunku mówi nam o wariancji (zmienności) sygnału w tym kierunku. &lt;br /&gt;
&lt;br /&gt;
Taki zbiór punktów wygodniej jest analizować w układzie współrzędnych zgodnym z osiami głównymi macierzy kowariancji.&lt;br /&gt;
W dalszej części rozważań założymy, że te przestrzenie, w których rozważamy sygnały są przestrzeniami wektorowymi, a pojedyncze próbki wielokanałowego sygnału są wektorami. &lt;br /&gt;
[[Plik:Kowariancja.png|200px|center]]&lt;br /&gt;
&lt;br /&gt;
==Filtry przestrzenne i ślepa separacja źródeł==&lt;br /&gt;
Sygnał EEG jest superpozycją aktywności elektrycznej wielu źródeł.&lt;br /&gt;
Jak można estymować aktywność samych źródeł?&lt;br /&gt;
[[Plik:Mieszanie.png|200px|center]]&lt;br /&gt;
Niech:&lt;br /&gt;
: &amp;lt;math&amp;gt;s(t)&amp;lt;/math&amp;gt; - aktywność niezależnych źródeł,&lt;br /&gt;
: &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; mierzony sygnał&lt;br /&gt;
: &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; macierz przejścia taka, że:&lt;br /&gt;
::&amp;lt;math&amp;gt;x(t) = A s(t)&amp;lt;/math&amp;gt; (*)&lt;br /&gt;
:&amp;lt;math&amp;gt;s(t) = A^{-1}x(t) = P x(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
Macierz kowariancji dla sygnałów &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; estymujemy tak:&lt;br /&gt;
:&amp;lt;math&amp;gt; C_x = E[x(t)x(t)^T]&amp;lt;/math&amp;gt;&lt;br /&gt;
Podstawiając (*) mamy:&lt;br /&gt;
:&amp;lt;math&amp;gt; C_x = E[x x^T] = E[As(As)^T] = A E[s s^T] A^T = A C_s A^T&amp;lt;/math&amp;gt;&lt;br /&gt;
Z założenia, że źródła są niezależne wynika, że macierz &amp;lt;math&amp;gt;C_s&amp;lt;/math&amp;gt; jest diagonalna.&lt;br /&gt;
Przekształcając powyższe równanie możemy zapisać:&lt;br /&gt;
:&amp;lt;math&amp;gt;A^{-1} C_x (A^T)^{-1} = P C_x P^T = C_s&amp;lt;/math&amp;gt;&lt;br /&gt;
Odwzorowanie &amp;lt;math&amp;gt;P = A^{-1}&amp;lt;/math&amp;gt; diagonalizuje macierz &amp;lt;math&amp;gt;C_x&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Powyższe rozumowanie jest słuszne w przypadku gdy mamy do czynienia z sygnałem stacjonarnym, tzn. jego macierz kowariancji jest niezależna od czasu, czyli przez cały czas aktywna jest ta sama konfiguracja źródeł niezależnych.&lt;br /&gt;
W przypadku gdy tak nie jest to konstrukcję filtra przestrzennego można oprzeć o  jednoczesną diagonalizację macierzy kowariancji odpowiadających różnym stanom osoby badanej.&lt;br /&gt;
&lt;br /&gt;
[[Plik:Diagonalizacja.png|200px|center]]&lt;br /&gt;
&lt;br /&gt;
==Common Spatial Pattern ==&lt;br /&gt;
===Koncepcja===&lt;br /&gt;
Dla ustalenia uwagi możemy myśleć o eksperymencie wywołującym potencjał P300. Mamy w nim dwie sytuacje eksperymentalne. Oznaczmy &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; (target) próby, w których pojawił się oczekiwany bodziec, zaś  &amp;lt;math&amp;gt;NT&amp;lt;/math&amp;gt; (non-target) gdy pojawił się bodziec standardowy.&lt;br /&gt;
Chcielibyśmy znaleźć taki montaż (czyli taką kombinację liniową kanałów), który maksymalizuje stosunek mocy (wariancji) sygnałów rejestrowanych w dwóch rożnych warunkach eksperymentalnych.&lt;br /&gt;
&lt;br /&gt;
===Formalizm===&lt;br /&gt;
Metoda ta polega na znalezieniu takiego kierunku &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; w przestrzeni sygnałów, że sygnał z warunku &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; rzutowany na ten kierunek ma dużą wariancje a sygnał z warunku &amp;lt;math&amp;gt;NT&amp;lt;/math&amp;gt; ma wariancję małą. &lt;br /&gt;
&lt;br /&gt;
Rzutowanie sygnału &amp;lt;math&amp;gt;x(t)&amp;lt;/math&amp;gt; na kierunek &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; odbywa się przez policzenie iloczynu skalarnego dla każdej chwili czasu &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt; s_w(t) = w^T x(t)&amp;lt;/math&amp;gt;&lt;br /&gt;
Wariancja tego rzutowanego sygnału to:&lt;br /&gt;
:&amp;lt;math&amp;gt; \mathrm{var}(s_w) = E[s_w s_w^T] = E[ w^T x (w^T x)^T] = w^T E[x x^T] w = w^T C_x w &amp;lt;/math&amp;gt;&lt;br /&gt;
Zatem znalezienie właściwego kierunku rzutowania można wyrazić jako szukanie maksimum wyrażenia &amp;lt;math&amp;gt; J(w) &amp;lt;/math&amp;gt; (jest to tzw. iloraz Rayleigha):&lt;br /&gt;
: &amp;lt;math&amp;gt;J(w) = \frac{w^T C_T w}{w^T C_{NT} w}  &amp;lt;/math&amp;gt;&lt;br /&gt;
Ekstremum tego ilorazu można znaleźć poprzez policzenie gradientu &amp;lt;math&amp;gt;J(w)&amp;lt;/math&amp;gt; i przyrównanie go do zera:&lt;br /&gt;
:&amp;lt;math&amp;gt; \nabla J(w) =  \frac{ 2 C_{T} w \left(w^T  C_{NT} w\right)  -2C_{NT} w \left(w^T  C_{T} w \right)}{\left(w^T  C_{NT} w\right)^2} = \frac{   2}{w^T  C_{NT} w}\left[     C_{T}w  -\frac{w^T  C_{T} w}{w^T  C_{NT} w}   C_{NT} w \right]&amp;lt;/math&amp;gt;&lt;br /&gt;
Przyrównując to wyrażenie do zera dostajemy do rozwiązania tzw. uogólnione zagadnienie własne:&lt;br /&gt;
:&amp;lt;math&amp;gt;       C_{T}w  =\frac{w^T  C_{T} w}{w^T  C_{NT} w}   C_{NT} w   &amp;lt;/math&amp;gt;&lt;br /&gt;
We wzorze tym liczba &amp;lt;math&amp;gt;\lambda=\frac{w^T  C_{T} w}{w^T  C_{NT} w}&amp;lt;/math&amp;gt; spełniająca to równanie jest uogólnioną wartością własną, wtedy &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; jest uogólnionym wektorem własnym odpowiadającym tej wartości. &lt;br /&gt;
&lt;br /&gt;
Aby znaleźć &amp;lt;math&amp;gt; \lambda&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; możemy wykorzystać w Matlabie funkcję &amp;lt;tt&amp;gt;eig&amp;lt;/tt&amp;gt;. Funkcja ta rozwiązuje (również) uogólnione zagadnienia własne postaci ''Aw''=&amp;amp;lambda;''Bw'' dostarczając w wyniku macierz wektorów własnych (w kolumnach) oraz macierz zawierającą na przekątnej odpowiadające im wartości własne.&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Odwzorowanie to można przedstawić w postaci macierzy &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;, której każdy wiersz zawiera wagi dla odpowiednich kanałów. &lt;br /&gt;
Macierz zawierająca sygnał &amp;lt;math&amp;gt;X^{\pm}(t)&amp;lt;/math&amp;gt; &lt;br /&gt;
ma wymiary &amp;lt;math&amp;gt;C \times  N&amp;lt;/math&amp;gt;, gdzie &lt;br /&gt;
&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; to liczba kanałów EEG, natomiast &lt;br /&gt;
&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; to liczba próbek dla każdego z kanałów. &lt;br /&gt;
Macierz &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; przekształca sygnał &amp;lt;math&amp;gt;X^{\pm}(t)&amp;lt;/math&amp;gt;  zgodnie ze wzorem:&lt;br /&gt;
:&amp;lt;math&amp;gt;X^{\pm}_{CSP}(t)=P^T  X^{\pm}(t) &amp;lt;/math&amp;gt;&lt;br /&gt;
Załóżmy dalej, że sygnały &amp;lt;math&amp;gt;X^{+}_{CSP} (t)&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;X^{-}_{CSP} (t)&amp;lt;/math&amp;gt; są generowane przez niezależne procesy stochastyczne, tzn. spełnione są następujące warunki. &lt;br /&gt;
# Syganły &amp;lt;math&amp;gt;X^{+}_{CSP} (t)&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;X^{-}_{CSP} (t)&amp;lt;/math&amp;gt; są niezależne.&lt;br /&gt;
# Brak korelacji pomiędzy kanałami w sygnałach&amp;lt;math&amp;gt;X^{+}_{CSP} (t)&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;X^{-}_{CSP} (t)&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Przynajmniej dla jednego z kanałów wariancja przetransformowanego sygnału jest maksymalna przy wystąpieniu bodźca i minimalna przy jego braku.&lt;br /&gt;
Po przemnożeniu równania 2.3 przez &amp;lt;math&amp;gt;(X^{\pm}_{CSP} (t))^T&amp;lt;/math&amp;gt; otrzymamy macierz kowariancji przetransformowanych sygnałów uśrednioną po realizacjach:&lt;br /&gt;
:&amp;lt;math&amp;gt;R^{\pm}_{CSP} (t) = X^{\pm}_{CSP} (t)(X^{\pm}_{CSP} (t))^T = P^T X^{\pm} (t) (X^{\pm}(t))^T P = P^T R^{\pm}P&amp;lt;/math&amp;gt;  (2.4)&lt;br /&gt;
Gdzie &amp;lt;math&amp;gt;R^{\pm}&amp;lt;/math&amp;gt; to macierz kowariancji sygnału uśredniona po realizacjach. Z warunków 1 i 2 wynika, że macierze &amp;lt;math&amp;gt;R^{+}_{CSP}&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;R^{-}_{CSP}&amp;lt;/math&amp;gt; muszą być diagonalne, natomiast z warunku 3, że ich suma daje macierz jednostkową:&lt;br /&gt;
:&amp;lt;math&amp;gt;R^{+}_{CSP} + R^{-}_{CSP} = 1 &amp;lt;/math&amp;gt;  (2.5)&lt;br /&gt;
Tak więc suma par diagonalnych wartości (&amp;lt;math&amp;gt;k^{+}_{i}&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;k^{-}_{i}&amp;lt;/math&amp;gt;) w macierzach &amp;lt;math&amp;gt;R^{+}_{CSP}&amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;R^{-}_{CSP}&amp;lt;/math&amp;gt; musi być równa 1.&lt;br /&gt;
Korzystając z równania 2.5 wartości na przekątnej można również zapisać za pomocą wzoru:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;k^{+}_{i} = \vec{p}^{T}_{i} R^{+} \vec{p}_{i}    &amp;lt;/math&amp;gt; (2.6)&lt;br /&gt;
:&amp;lt;math&amp;gt;k^{-}_{i} = \vec{p}^T_{i} R^{-}\vec{p}_{i} &amp;lt;/math&amp;gt; (2.7)&lt;br /&gt;
gdzie &amp;lt;math&amp;gt;\vec{p}_{i}&amp;lt;/math&amp;gt; to kolumnowy wektor macierzy &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;. Po przekształceniach ilorazu równań 2.6 i 2.7 można&lt;br /&gt;
otrzymać równanie:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;R^{+} \vec{p}_{i} = \frac{k^{+}_{i}}{k^{-}_{i}} R^{-} \vec{p}_{i} &amp;lt;/math&amp;gt;  (2.8)&lt;br /&gt;
￼&lt;br /&gt;
Równanie to przedstawia ogólną formę zagadnienia wartości własnych. Takie przedstawienie problemu umożliwia zastosowanie do jego rozwiązania wydajnych metod algebraicznych.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wektor własny &amp;lt;math&amp;gt;\vec{p}_i&amp;lt;/math&amp;gt; jest interpretowany jako filtr przestrzenny. Dzięki transformacie &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; sygnał zostaje przeniesiony do przestrzeni, dla której różnica wariancji dla poszczególnych klas jest największa. Zgodnie z równaniem 2.5 najbardziej różniące się od siebie kanały są skorelowane z największą wartością własną &amp;lt;math&amp;gt;k^{+}&amp;lt;/math&amp;gt;.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Ćwiczenie symulacyjne ====&lt;br /&gt;
{{hidden begin|title=kod przykładowy}}&lt;br /&gt;
&amp;lt;source lang  = matlab&amp;gt;&lt;br /&gt;
% symulowany eksperyment składa się z sinusoidy udającej alfę spoczynkową i&lt;br /&gt;
% funkcji Gaussa udającego potencjał wywołany&lt;br /&gt;
% źródła te są symulowane niezależnie a potem mieszane przez macierz A&lt;br /&gt;
% symulujemy źródła&lt;br /&gt;
% s1 - symuluje alfę&lt;br /&gt;
% s2 - symuluje &amp;quot;potencjał wywołany&amp;quot; (ERP)&lt;br /&gt;
&lt;br /&gt;
%ustawiamy parametry do symulacji sygnałów&lt;br /&gt;
Fs = 100;&lt;br /&gt;
T = 1;&lt;br /&gt;
t = 0:1/Fs:T-1/Fs;&lt;br /&gt;
N_rep = 100;&lt;br /&gt;
N_chan = 2;&lt;br /&gt;
s = zeros(N_rep,N_chan, length(t));&lt;br /&gt;
X = zeros(N_rep,N_chan, length(t));&lt;br /&gt;
&lt;br /&gt;
% filtr przestrzenny - z takimi wagami trzeba wziąść kanały EEG aby odzyskać sygnały źródłowe&lt;br /&gt;
P = [1 2&lt;br /&gt;
    1.5 1.3]; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
% topografie - z takimi wagami źródła dokładają się do poszczególnych elektrod&lt;br /&gt;
A = P^(-1); &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for r =1:N_rep % tworzymy kolejne realizacje &amp;quot;eksperymentu&amp;quot;&lt;br /&gt;
    s1 = sin(2*pi*11*t +pi/2+ 0*2*pi*rand())+ 0.02*randn(size(t));  % źródło alfa&lt;br /&gt;
    s2 = exp(-((t-0.8)/0.05).^2)+ 0.01*randn(size(t));              % źródło ERP&lt;br /&gt;
       &lt;br /&gt;
    s(r,1,:) = s1;&lt;br /&gt;
    s(r,2,:) = s2;&lt;br /&gt;
    tmp = squeeze(s(r,:,:));&lt;br /&gt;
    n = 0*randn(size(tmp));&lt;br /&gt;
    X(r,:,:) = A*tmp +n; % rzutujemy sygnały źródłowe na elektrody s -&amp;gt; x&lt;br /&gt;
    &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
% wycinamy warunki &lt;br /&gt;
% baseline_ind   to indeksy pierwszej połowy każdego powtórzenia &amp;quot;baseline&amp;quot;&lt;br /&gt;
% ERP_ind        to indeksy drugiej połowy każdego powtórzenia zawierająca &amp;quot;ERP&amp;quot;&lt;br /&gt;
baseline_ind = find(t&amp;lt;0.5);&lt;br /&gt;
ERP_ind = find(t&amp;gt;=0.5);&lt;br /&gt;
&lt;br /&gt;
x_baseline_kan_1 = X(:,1,baseline_ind);&lt;br /&gt;
x_baseline_kan_2 = X(:,2,baseline_ind);&lt;br /&gt;
&lt;br /&gt;
x_ERP_kan_1 = X(:,1,ERP_ind);&lt;br /&gt;
x_ERP_kan_2 = X(:,2,ERP_ind);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
% liczymy średnie macierze kowariancji:&lt;br /&gt;
R_E = zeros(N_chan,N_chan);&lt;br /&gt;
R_B = zeros(N_chan,N_chan);&lt;br /&gt;
for r =1:N_rep&lt;br /&gt;
    B = squeeze(X(r,:,baseline_ind)); &lt;br /&gt;
    tmp =cov(B');&lt;br /&gt;
    R_B = R_B + tmp./trace(tmp);%B*B' ;&lt;br /&gt;
 &lt;br /&gt;
    E = squeeze(X(r,:,ERP_ind));&lt;br /&gt;
    tmp = cov(E');&lt;br /&gt;
    R_E = R_E + tmp./trace(tmp);%E*E' ;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
R_B = R_B/N_rep;&lt;br /&gt;
R_E = R_E/N_rep;&lt;br /&gt;
&lt;br /&gt;
% rozwiązujemy uogólnione zagadnienie własne&lt;br /&gt;
[W,Lambda]=eig(R_E,R_B); % możliwa jest też optymalizacja wzg. średniej macierzy kowariancji (R_B+R_A)/2);&lt;br /&gt;
&lt;br /&gt;
% odzyskujemy sygnały źródeł&lt;br /&gt;
for r =1:N_rep&lt;br /&gt;
    S(r,:,:) = W'*squeeze(X(r,:,:));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
% pobieramy wycinki odpowiadające obu częściom eksperymentu z estymowanych&lt;br /&gt;
% źródeł&lt;br /&gt;
s_baseline_estymowany_kan1 = squeeze(  S(:,1,baseline_ind));&lt;br /&gt;
s_baseline_estymowany_kan2 = squeeze(  S(:,2,baseline_ind));&lt;br /&gt;
&lt;br /&gt;
s_ERP_estymowany_kan1 = squeeze(S(:,1,ERP_ind));&lt;br /&gt;
s_ERP_estymowany_kan2 = squeeze(S(:,2,ERP_ind));&lt;br /&gt;
&lt;br /&gt;
%%%%%%%%%%%%%% Ilustracje %%%%%%%%%%%%%%%%%%%%%%%&lt;br /&gt;
% ilustracja sygnałów mierzonych&lt;br /&gt;
figure(1);clf&lt;br /&gt;
subplot(2,2,1);&lt;br /&gt;
    plot(t(baseline_ind),(squeeze(X(:,1,baseline_ind)))','b'); hold on&lt;br /&gt;
    plot(t(ERP_ind),(squeeze(  X(:,1,ERP_ind)))','r'); hold off&lt;br /&gt;
    xlabel('elektroda 1')&lt;br /&gt;
    title('ilustracja sytuacji pomiarowej -\newline znane są potencjały na elektrodach w dwóch warunkach eksperymentalnych')&lt;br /&gt;
subplot(2,2,3);&lt;br /&gt;
    plot(t(baseline_ind),(squeeze(X(:,2,baseline_ind)))','b'); hold on&lt;br /&gt;
    plot(t(ERP_ind),(squeeze(  X(:,2,ERP_ind)))','r'); hold off&lt;br /&gt;
    xlabel('elektroda 2')&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
    plot(x_baseline_kan_1(:),x_baseline_kan_2(:),'b.');&lt;br /&gt;
    hold on&lt;br /&gt;
    plot(x_ERP_kan_1(:),x_ERP_kan_2(:),'r.');&lt;br /&gt;
    xlim([-2,2])&lt;br /&gt;
    ylim([-2,2])&lt;br /&gt;
    axis equal&lt;br /&gt;
    &lt;br /&gt;
    % wektor własny odpowiadający największej wartości własnej jest&lt;br /&gt;
    % kierunkiem najbardziej różnicującym warunki eksperymentalne&lt;br /&gt;
    disp('wartości własne znajdują się na przekątnej macierzy Lambda')&lt;br /&gt;
    disp(Lambda)&lt;br /&gt;
    % rysujemy wersory jednostkowe w kierunkach wektorów własnych&lt;br /&gt;
    w1 = W(:,1); &lt;br /&gt;
    w1 = w1/norm(w1);&lt;br /&gt;
    w2 = W(:,2); &lt;br /&gt;
    w2 = w2/norm(w2);&lt;br /&gt;
    line([0, w1(1) ],[0,w1(2)],'Color',[0,0.3,0])&lt;br /&gt;
    text(w1(1),w1(2),'wektor własny 1')&lt;br /&gt;
    line([0, w2(1) ],[0,w2(2)],'Color',[1,0,1])&lt;br /&gt;
    text(w2(1),w2(2),'wektor własny 2')&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    xlabel('Amplituda na elektrodzie 1')&lt;br /&gt;
    ylabel('Amplituda na elektrodzie 2')   &lt;br /&gt;
    legend('baseline','ERP')&lt;br /&gt;
&lt;br /&gt;
% Ilustracja estymowanych źródeł&lt;br /&gt;
figure(2);clf&lt;br /&gt;
subplot(2,2,1);&lt;br /&gt;
    plot(t(baseline_ind),(squeeze(S(:,1,baseline_ind)))','b');hold on&lt;br /&gt;
    plot(t(ERP_ind),(squeeze(S(:,1,ERP_ind)))','r');hold off&lt;br /&gt;
    xlabel('estymowane zrodlo  1')&lt;br /&gt;
    title('ilustracja estymacji -\newline estymowane są potencjały źródeł w dwóch warunkach eksperymentalnych')    &lt;br /&gt;
subplot(2,2,3);&lt;br /&gt;
    plot(t(baseline_ind),(squeeze(S(:,2,baseline_ind)))','b');hold on&lt;br /&gt;
    plot(t(ERP_ind),(squeeze(S(:,2,ERP_ind)))','r');hold off&lt;br /&gt;
    xlabel('estymowane zrodlo  2');&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
    plot(s_baseline_estymowany_kan1(:),s_baseline_estymowany_kan2(:),'b.');&lt;br /&gt;
    hold on&lt;br /&gt;
    plot(s_ERP_estymowany_kan1(:),s_ERP_estymowany_kan2(:),'r.');   &lt;br /&gt;
    &lt;br /&gt;
    xlabel('Amplituda estym. źródła 1')&lt;br /&gt;
    ylabel('Amplituda estym. źródła 2')   &lt;br /&gt;
    legend('baseline','ERP')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
==Zastosowanie filtra CSP do detekcji potencjału P300==&lt;br /&gt;
{{hidden begin|title=Eksperyment}}&lt;br /&gt;
===Eksperyment===&lt;br /&gt;
* Proszę zapoznać się z instrukcją: http://laboratorium-eeg.braintech.pl/rozdz10.html&lt;br /&gt;
* Proszę wczytać i uruchomić (na sucho) demo Demos-&amp;gt;EEG_P300wz&lt;br /&gt;
* Wspólne omówienie konstrukcji i potencjalnych modyfikacji tego scenariusza &lt;br /&gt;
&lt;br /&gt;
====Przygotowanie do badania:====&lt;br /&gt;
* założyć czepek z elektrodami w systemie 10-20;&lt;br /&gt;
* elektrody referencyjne: M1 i M2;&lt;br /&gt;
* elektroda GND w pozycji AFz.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
====Przygotowanie scenariuszy obci ====&lt;br /&gt;
* w terminalu uruchomić &amp;lt;tt&amp;gt;obci srv&amp;lt;/tt&amp;gt;;&lt;br /&gt;
* w terminalu uruchomić &amp;lt;tt&amp;gt;obci_gui --preset brain2013&amp;lt;/tt&amp;gt;;&lt;br /&gt;
* w interfejsie GUI zapisujemy scenariusze do własnego katalogu np &amp;amp;bdquo;P300&amp;amp;rdquo;&lt;br /&gt;
** &amp;amp;bdquo;P-Brain2013 Signal (with ID)&amp;amp;rdquo; jako np. &amp;amp;bdquo;Sygnal&amp;amp;rdquo;&lt;br /&gt;
** &amp;amp;bdquo;P-Brain2013 Calibration p300&amp;amp;rdquo; jako &amp;amp;bdquo;kalibracjaP300&amp;amp;rdquo;&lt;br /&gt;
** &amp;amp;bdquo;P-Brain 2013 p300&amp;amp;rdquo; jako &amp;amp;bdquo;Labirynt&amp;amp;rdquo;&lt;br /&gt;
* w przeglądarce plików otwórz katalog ~/.obci/scenarios/P300. Powinien on zawierać pliki: Sygnal.ini, kalibracjaP300.ini, Labirynt.ini oraz katalogi  Sygnal_configs, kalibracjaP300_configs, Labirynt_configs.&lt;br /&gt;
*  edytujemy parametry peerów.&lt;br /&gt;
** z katalogu ~/.obci/scenarios/P300/Sygnal_configs kopiujemy plik amplifier.ini do katalogu ~/.obci/scenarios/P300 jako global_amplifier.ini. To pozwoli nam zmieniać ustawienia wzmacniacza dla wszystkich scenariuszy jednocześnie.&lt;br /&gt;
** w naszych scenariuszach zapisanych w plikach Sygnal.ini, kalibracjaP300.ini, Labirynt.ini podmieniamy ścieżkę &amp;lt;tt&amp;gt;config =&amp;lt;/tt&amp;gt; w sekcji &amp;lt;tt&amp;gt;[peers.amplifier]&amp;lt;/tt&amp;gt; tak, aby pokazywała na ten skopiowany plik global_amplifier.ini&lt;br /&gt;
** w tym pliku global_amplifier.ini podmieniamy linijki (tak aby były to listy faktycznie wykorzystywanych kanałów) z:&lt;br /&gt;
*** &amp;lt;tt&amp;gt;active_channels&amp;lt;/tt&amp;gt;&lt;br /&gt;
*** &amp;lt;tt&amp;gt;channel_names&amp;lt;/tt&amp;gt;&lt;br /&gt;
** dodajemy też linijkę: &amp;lt;tt&amp;gt;sampling_rate = 256&amp;lt;/tt&amp;gt;&lt;br /&gt;
* wchodzimy po kolei do katalogów: Sygnal_configs, kalibracjaP300_configs, Labirynt_configs i odnajdujemy plik switch_backup.ini. W tym pliku ustawiamy parametr &amp;lt;tt&amp;gt;new_scenario&amp;lt;/tt&amp;gt; na pusty. To spowoduje, że scenariusze te nie będą uruchamiać kolejnych scenariuszy po zakończeniu działania.&lt;br /&gt;
** edytujemy plik ~/.obci/scenarios/P300/kalibracjaP300_configs/clasifier.ini &lt;br /&gt;
*** zmieniamy linię&lt;br /&gt;
::: &amp;lt;tt&amp;gt;ignore_channels = DriverSaw;AmpSaw;PO7;PO8&amp;lt;/tt&amp;gt;&lt;br /&gt;
::: na &lt;br /&gt;
::: &amp;lt;tt&amp;gt;ignore_channels = DriverSaw;AmpSaw;A1;A2&amp;lt;/tt&amp;gt;&lt;br /&gt;
::* oraz linię:&lt;br /&gt;
::: &amp;lt;tt&amp;gt;montage_channels = PO7;PO8&amp;lt;/tt&amp;gt;&lt;br /&gt;
::: na &lt;br /&gt;
::: &amp;lt;tt&amp;gt;montage_channels = A1;A2&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Przeprowadzenie badania:====&lt;br /&gt;
# Uruchom scenariusz &amp;amp;bdquo;Sygnał&amp;amp;rdquo;.&lt;br /&gt;
# Tworzy on w katalogu domowym plik o nazwie &amp;lt;tt&amp;gt;file_id_name&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# Uruchamiamy Svaroga z terminala poleceniem &amp;lt;tt&amp;gt;svarog&amp;lt;/tt&amp;gt;. W zakładce sygnały on-line odnajdujemy nazwę naszego scenariusza &amp;amp;bdquo;Sygnal&amp;amp;rdquo;. Podłączamy się do niego i poprawiamy ewentualnie źle kontaktujące elektrody.&lt;br /&gt;
# Jak już jesteśmy zadowoleni z jakości sygnału to zatrzymujemy scenariusz &amp;amp;bdquo;Sygnal&amp;amp;rdquo; w obci.&lt;br /&gt;
# W pliku &amp;lt;tt&amp;gt;file_id_name&amp;lt;/tt&amp;gt;  znajduje się string, który stanowi rdzeń do tworzenia nazw plików, z których korzystają nasze scenariusze. Proszę zmienić ten string np. na: &amp;lt;tt&amp;gt;test1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# Uruchamiamy scenariusz &amp;amp;bdquo;kalibracjaP300&amp;amp;rdquo;. Badany będzie oglądał interfejs z trzema literami A B C migającymi w losowej kolejności. Zadaniem jest zliczanie mignięć litery B.&lt;br /&gt;
# Po zakończeniu kalibracji uruchamiamy scenariusz &amp;amp;bdquo;Labirynt&amp;amp;rdquo;.&lt;br /&gt;
# Danych z kalibracji potrzebować będziemy kilka zestawów.  Proszę powtórzyć kilkukrotnie scenariusz &amp;amp;bdquo;kalibracjaP300&amp;amp;rdquo;. Przed każdym uruchomieniem trzeba zmienić string w pliku &amp;lt;tt&amp;gt;file_id_name&amp;lt;/tt&amp;gt; np. na &amp;lt;tt&amp;gt;test???&amp;lt;/tt&amp;gt; gdzie &amp;lt;tt&amp;gt;???&amp;lt;/tt&amp;gt; oznacza kolejne numery.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
===Analiza wstępna===&lt;br /&gt;
Poszczególne etapy analizy proszę kodować w osobnych funkcjach. Funkcje te powinny być wywoływane z nadrzędnego skryptu, który powinien umożliwic wykoanie całości analiz.&lt;br /&gt;
 &lt;br /&gt;
* Wczytać dane kalibracyjne do Matlaba i pociąć je na realizacje typu T &amp;amp;mdash; &amp;amp;bdquo;target&amp;amp;rdquo; (związane z wystąpieniami litery &amp;amp;bdquo;B&amp;amp;rdquo;) i NT &amp;amp;mdash; &amp;amp;bdquo;non-target&amp;amp;rdquo; (pozostałe litery) o długości &amp;amp;minus;200 do +800 ms wokół triggerów. Dla każdej realizacji odjąć trend liniowy.&lt;br /&gt;
* Sygnał zmontować wzgl. &amp;amp;bdquo;połączonych uszu&amp;amp;rdquo; i wyświetlić średnie przebiegi dla warunku T i NT w układzie topograficznym &amp;amp;mdash; można wykorzystać w tym celu poniższy fragment kodu.&lt;br /&gt;
{{hidden begin|title= fragment kodu do rysowania dwóch ERPów -- zamiast funkcji plottopo}}&lt;br /&gt;
&amp;lt;source lang = matlab&amp;gt;&lt;br /&gt;
%% stworzenie osi&lt;br /&gt;
      % zakładam, że dane do rysowania są w dwóch strukturach EEG1 i EEG2 (struktury eeglab), &lt;br /&gt;
      % te dane są podzielone na realizacje i mają kształt (kanały , czas, epoki)&lt;br /&gt;
      % i że mamy już załadowane położenia elektrod we współrzędnych&lt;br /&gt;
      % biegunowych &lt;br /&gt;
      w = 0.125;&lt;br /&gt;
      h = 0.125;&lt;br /&gt;
      sc = 0.8;&lt;br /&gt;
      figure()&lt;br /&gt;
     for chanNum = 1:length(EEG1.chanlocs)&lt;br /&gt;
         r =EEG1.chanlocs(chanNum).radius;&lt;br /&gt;
         theta = EEG1.chanlocs(chanNum).theta;&lt;br /&gt;
         x = r* sin(theta/180*pi)*sc+0.46;&lt;br /&gt;
         y = r* cos(theta/180*pi)*sc+0.46;&lt;br /&gt;
         ax(chanNum) = axes('Position', [x, y, w, h]);&lt;br /&gt;
     end&lt;br /&gt;
%%uśredniam EEG po powtórzeniach aby otrzymać ERP&lt;br /&gt;
  ERP1 =squeeze( mean( EEG1.data,3)) ;&lt;br /&gt;
  ERP2 =squeeze( mean( EEG2.data,3)) ; &lt;br /&gt;
%% rysowanie uśrednionych potencjałów z dwóch struktur EEG &lt;br /&gt;
 for chanNum = 1:length(EEG1.chanlocs)&lt;br /&gt;
     hold(ax(chanNum),'on');&lt;br /&gt;
     plot(ax(chanNum), EEG1.times, ERP1(chanNum ,:));&lt;br /&gt;
     plot(ax(chanNum), EEG2.times, ERP2(chanNum ,:));&lt;br /&gt;
     title(ax(chanNum),EEG1.chanlocs(chanNum).labels );&lt;br /&gt;
     hold(ax(chanNum),'off');&lt;br /&gt;
 end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Poniżej zaprezentowany jest przykładowy skrypt do cięcia danych wokół znaczników. Działa on z plikami zawartymi w archiwum:&lt;br /&gt;
: [[Plik:KalibracjaP300.tar.gz]] &lt;br /&gt;
Korzysta z funkcji pomocniczych dostępnych w dystrybucji obci w katalogu &lt;br /&gt;
: /usr/share/openbci/analysis/matlab_obci_signal_processing&lt;br /&gt;
Openbci można pobrać z https://github.com/BrainTech/openbci&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{hidden begin|title=przykładowy skrypt}}&lt;br /&gt;
&amp;lt;source lang = matlab&amp;gt;&lt;br /&gt;
% ustalamy nzawy plików z danymi&lt;br /&gt;
nazwaPliku = 'p_6301423_calibration_p300.obci';&lt;br /&gt;
nameOfXMLFile = strcat(nazwaPliku,'.xml');&lt;br /&gt;
nameOfTagFile = strcat(nazwaPliku,'.tag'); %tagi = znaczniki zdarzeń&lt;br /&gt;
namesOfDataFiles = strcat(nazwaPliku,'.raw');&lt;br /&gt;
&lt;br /&gt;
% inicjujemy obiekt rm&lt;br /&gt;
rm = ReadManager(nameOfXMLFile,namesOfDataFiles,nameOfTagFile);&lt;br /&gt;
&lt;br /&gt;
% obieramy przydatne parametry i znaczniki&lt;br /&gt;
numberOfChannels  = rm.get_param('number_of_channels');&lt;br /&gt;
namesOfChannels   = rm.get_param('channels_names');&lt;br /&gt;
samplingFrequency = rm.get_param('sampling_frequency');&lt;br /&gt;
tagsStruct        = rm.get_tags();&lt;br /&gt;
&lt;br /&gt;
% tworzenie list znaczników Target i NonTarget&lt;br /&gt;
numberOfStruct = length(tagsStruct);&lt;br /&gt;
targetTimeStamps = [];&lt;br /&gt;
NonTargetTimeStamps = [];&lt;br /&gt;
for structNumber = 1:numberOfStruct % iterujemy się przez tagi&lt;br /&gt;
    if(strcmp(tagsStruct(structNumber).name,'blink')) % szukamy tagów o nazwie 'blink'&lt;br /&gt;
        index = tagsStruct(structNumber).children.index; % tu jest numer pola stymulacji&lt;br /&gt;
        target= tagsStruct(structNumber).children.target;% tu jest numer pola na którym wyświetlany jest target&lt;br /&gt;
        if index == target % warunek na to, że mamy do czynienia z tagiem target&lt;br /&gt;
            targetTimeStamps = [targetTimeStamps tagsStruct(structNumber).start_timestamp]; %dodajemy timeStamp do listy targetów&lt;br /&gt;
        else&lt;br /&gt;
            NonTargetTimeStamps = [NonTargetTimeStamps tagsStruct(structNumber).start_timestamp];%dodajemy timeStamp do listy non-targetów&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
% pobieramy próbki&lt;br /&gt;
samples = double(rm.get_samples()); % konwersja na double jest potrzebna żeby dobrze funkcjonowało filtrowanie&lt;br /&gt;
samples=samples(1:8,:); % odrzucamy kanały, które nie mają EEG&lt;br /&gt;
numberOfChannels =8;&lt;br /&gt;
&lt;br /&gt;
% filtrujemy dolnoprzepustowo aby odrzucić artefakty sieci i część&lt;br /&gt;
% artefaktów mięśniowych&lt;br /&gt;
[b,a] = cheby2(6,80,25 /(samplingFrequency/2),'low');&lt;br /&gt;
for ch = 1:numberOfChannels&lt;br /&gt;
    samples(ch,:)=filtfilt(b,a,samples(ch,:));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
% montujemy dane do wspólnej średniej (common average)&lt;br /&gt;
M = -ones(8,8)/8;&lt;br /&gt;
M=M+eye(8,8)*9/8;&lt;br /&gt;
samples = 0.0715*M*samples;&lt;br /&gt;
&lt;br /&gt;
% wycinamy dane wokół znaczników&lt;br /&gt;
PRE = -0.2; % czas przed tagiem w sek.&lt;br /&gt;
POST = 0.8; % czas po tagu w sek.&lt;br /&gt;
wycinek = floor(PRE*samplingFrequency:POST*samplingFrequency); % tablica ze &amp;quot;standardowymi&amp;quot; indeksami do cięcia&lt;br /&gt;
&lt;br /&gt;
% pobieramy targety&lt;br /&gt;
TargetSignal = zeros(length(targetTimeStamps),numberOfChannels, length(wycinek)); % tablica na sygnały target&lt;br /&gt;
for trialNumber = 1:length(targetTimeStamps)&lt;br /&gt;
    trigerOnset = floor(targetTimeStamps(trialNumber)*samplingFrequency);&lt;br /&gt;
    tenWycinek = wycinek + trigerOnset;&lt;br /&gt;
    if tenWycinek(1)&amp;gt;0 &amp;amp;&amp;amp; tenWycinek(end)&amp;lt;=size(samples,2) % test czy wycinek który chcemy pobrać nie wystaje poza dostępny sygnał&lt;br /&gt;
        tmpSignal = samples(:,tenWycinek);&lt;br /&gt;
        tmpSignal = detrend(tmpSignal')'; % usuwanie liniowego trendu - przy krótkich wycinkach działa lepiej niż filtrowanie górnoprzepustowe&lt;br /&gt;
        TargetSignal(trialNumber, :,:) = tmpSignal;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
% pobieramy non-targety&lt;br /&gt;
NonTargetSignal = zeros(length(NonTargetTimeStamps),numberOfChannels, length(wycinek));% tablica na sygnały non-target&lt;br /&gt;
for trialNumber = 1:length(NonTargetTimeStamps)&lt;br /&gt;
    trigerOnset = floor(NonTargetTimeStamps(trialNumber)*samplingFrequency);&lt;br /&gt;
    tenWycinek = wycinek + trigerOnset;&lt;br /&gt;
    if tenWycinek(1)&amp;gt;0 &amp;amp;&amp;amp; tenWycinek(end)&amp;lt;=size(samples,2)&lt;br /&gt;
        tmpSignal = samples(:,tenWycinek);&lt;br /&gt;
        tmpSignal = detrend(tmpSignal')';&lt;br /&gt;
        NonTargetSignal(trialNumber, :,:) = tmpSignal;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
%&lt;br /&gt;
% dla ilustracji podglądamy średnie po powtórzeniach ze wszystkich targetów&lt;br /&gt;
% i non-targetów&lt;br /&gt;
plot(squeeze(mean(TargetSignal,1))','r');&lt;br /&gt;
hold on&lt;br /&gt;
plot(squeeze(mean(NonTargetSignal,1))','b')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
===ZADANIE: Analiza CSP===&lt;br /&gt;
&lt;br /&gt;
Przegląd badań o P300: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2715154/&lt;br /&gt;
&lt;br /&gt;
Link do Read menager [https://drive.google.com/file/d/1OgOduK5Zn7GgNl5XdCyLWXHJ7wTJIWcC/view?usp=share_link]&lt;br /&gt;
&amp;lt;!---&lt;br /&gt;
[https://drive.google.com/open?id=0BzwQ_Lscn8yDS3RXNWdBbkxEQ2c]&lt;br /&gt;
---&amp;gt;&lt;br /&gt;
* Wykonać analizę CSP wzmacniającą potencjał P300.&lt;br /&gt;
* Zaprezentować średnią ze wszystkich kanałów źródłowych z warunku target (jeden kolor) i non-target (inny kolor) w subplotach ułożonych w prostokątnej siatce. Zaobserwować dla którego kanału średnie różnią się najbardziej. Czy jest związek tego kanału z wartościami własnymi?&lt;br /&gt;
&lt;br /&gt;
* Dla kanału najbardziej różnicującego wykonać mapki topograficzne (do wykonania tych mapek wykorzystać funkcję &amp;lt;tt&amp;gt;topoplot&amp;lt;/tt&amp;gt; z pakietu &amp;lt;tt&amp;gt;eeglab&amp;lt;/tt&amp;gt;) wektorów odpowiadających:&lt;br /&gt;
** filtrowi przestrzennemu &lt;br /&gt;
** rzutu topograficznego źródła na elektrody.&lt;br /&gt;
&amp;lt;!---&lt;br /&gt;
* Zbadać powtarzalność topografii pomiędzy plikami konfiguracyjnymi.&lt;br /&gt;
---&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{hidden begin|title=Wybór i separacja cech}}&lt;br /&gt;
&lt;br /&gt;
===Wybór i separacja cech===&lt;br /&gt;
* Przedstaw na rysunkach nałożone na siebie pojedyncze realizacje z warunków target i non-target po rzutowaniu na wektor &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; odpowiadający największej i kolejnej wartości  własnej. &lt;br /&gt;
* Przedstaw wykresy punktowe takie, że na jednej osi jest moc sygnału (suma kwadratów wartości próbek w wybranym zakresie czasu) odpowiadającego największej wartości własnej, a na drugiej osi kolejnej (mniejszej) wartości własnej; jeden punkt reprezentuje jedno powtórzenie.&lt;br /&gt;
* Wykonaj serię wykresów jak w poprzednim punkcie dla uśrednień sygnałów kolejno po 2, 4, 6, 8 i 10 realizacjach:&lt;br /&gt;
**  Liczymy potencjał wywołany dla danej liczby powtórzeń. &lt;br /&gt;
** Następnie podnosimy wartości próbek do kwadratu&lt;br /&gt;
**  i sumujemy je w wybranym zakresie czasu.&lt;br /&gt;
* Zaobserwuj jak zmienia się separacja w grupach target i non-target.&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
==Filtry przestrzenne dla SSEP ==&lt;br /&gt;
{{hidden begin|title=Filtry przestrzenne dla SSEP}}&lt;br /&gt;
=== Teoria===&lt;br /&gt;
Ciekawa koncepcja filtra przestrzennego dla SSVEP zaprezentowana jest  tu: http://www.eurasip.org/Proceedings/Eusipco/Eusipco2009/contents/papers/1569193209.pdf&lt;br /&gt;
&lt;br /&gt;
Pokrótce można ją rozumieć podobnie do tego co robiliśmy rozważając filtry przestrzenne CSP z tym, że dla SSVEP oraz innych potencjałów wywołanych stanu ustalonego możemy skorzystać z dodatkowych informacji dotyczących poszukiwanych źródeł. Wiemy mianowicie, że powinny one oscylować z częstością bodźca, i być może jej harmonicznych.&lt;br /&gt;
&lt;br /&gt;
Przyda nam się macierz &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; zbudowana tak, że w kolejnych kolumnach znajdują się sinusy i cosinusy kolejnych częstości harmonicznych. Wektory te unormujemy, żeby miały energię równą 1. Innymi słowy macierz &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; zbudowana jest z wersorów rozpinających przestrzeń, w której powinien znajdować się sygnał SSVEP.&lt;br /&gt;
&lt;br /&gt;
W matlabie możemy taką macierz zbudować tak:&lt;br /&gt;
&amp;lt;source lang = matlab&amp;gt;&lt;br /&gt;
% Fs - częstość próbkowania&lt;br /&gt;
% numberOfSamples - długość sygnału w próbkach&lt;br /&gt;
% numberOfHarmonics - liczba harmonicznych, które chcemy włączyć do analizy&lt;br /&gt;
t = (0:1:numberOfSamples - 1)/Fs; &lt;br /&gt;
S = zeros(numberOfSamples, 2*numberOfHarmonics);&lt;br /&gt;
&lt;br /&gt;
for harmonicNumber = 1:numberOfHarmonics&lt;br /&gt;
    c = cos(2*pi*stimulationFrequency*harmonicNumber*t);&lt;br /&gt;
    s = sin(2*pi*stimulationFrequency*harmonicNumber*t);&lt;br /&gt;
    S(:,(harmonicNumber - 1)*2 + 1) = c/norm(c);&lt;br /&gt;
    S(:,(harmonicNumber - 1)*2 + 2) = s/norm(s);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aby w badanym sygnale znaleźć składowe odpowiadające SSVEP musimy rzutować sygnał &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; (macierz sygnałów ''kanały &amp;amp;times; próbki'')  na przestrzeń rozpiętą przez &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = X*S&amp;lt;/math&amp;gt;&lt;br /&gt;
Macierz &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; zawiera współczynniki będące iloczynami skalarnymi sygnałów i wersorów. Mówią one o tym &amp;amp;bdquo;jak dużo&amp;amp;rdquo; jest sinusa bądź cosinusa o danej częstości w pierwotnym sygnale. Komponenty SSVEP zawarte w sygnale &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; odzyskujemy tak:&lt;br /&gt;
:&amp;lt;math&amp;gt;\mathrm{SSVEP} = A S^T&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modelujemy rejestrowany sygnał jako:&lt;br /&gt;
:&amp;lt;math&amp;gt;X = \mathrm{SSVEP} + Y &amp;lt;/math&amp;gt;&lt;br /&gt;
gdzie: &lt;br /&gt;
:&amp;lt;math&amp;gt;Y = X-\mathrm{SSVEP}&amp;lt;/math&amp;gt; &lt;br /&gt;
: to wszystkie komponenty sygnału, które nas nie interesują.&lt;br /&gt;
&lt;br /&gt;
Filtr przestrzenny, który chcemy zbudować powinien maksymalizować stosunek wariancji &amp;lt;math&amp;gt;\mathrm{SSVEP} = A S^T&amp;lt;/math&amp;gt; do wariancji &amp;lt;math&amp;gt;Y = X-\mathrm{SSVEP}&amp;lt;/math&amp;gt;. Macierz kowariancji powinna być uśredniona po powtórzeniach a kowariancja sygnału w każdym powtórzeniu powinna być znormalizowana poprzez podzielenie przez jej ślad (Matlabowa funkcja &amp;lt;tt&amp;gt;cov&amp;lt;/tt&amp;gt; już wykonuje tę operację).&lt;br /&gt;
Dalej możemy zastosować technikę znaną z konstrukcji filtrów CSP, tzn. maksymalizacji ilorazu Rayleigha za pomocą rozwiązania uogólnionego zagadnienia własnego dla macierzy kowariancji &amp;lt;math&amp;gt;\mathrm{SSVEP} &amp;lt;/math&amp;gt; i &amp;lt;math&amp;gt;Y &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Poniżej prosta demonstracja dla danych zebranych EEG przy stymulacji SSVEP z częstotliwością 38 Hz.===&lt;br /&gt;
Spakowane dane: [[Plik:PrzykladoweDaneSSVEP.mat.gz]].&lt;br /&gt;
W oparciu o powyższy opis proszę zaimplementować  funkcję &amp;lt;tt&amp;gt;cosSinCSP&amp;lt;/tt&amp;gt;. Prawidłowo zaimplementowana funkcja wraz z poniższym kodem powinna generować rysunek:&lt;br /&gt;
[[Plik:Rys_SSVEP_demo.png|400px|podpis grafiki]] &lt;br /&gt;
Przykładowy skrypt i dane prezentujący konstrukcję i działanie tego typu filtrów przestrzennych dla pełnych danych z eksperymentu SSVEP: [[Plik:SSVEP_demo_csp.tar.gz]]&lt;br /&gt;
&lt;br /&gt;
{{hidden begin|title=przykładowy skrypt}}&lt;br /&gt;
&amp;lt;source lang = matlab&amp;gt;&lt;br /&gt;
% wczytujemy dane&lt;br /&gt;
load('PrzykladoweDaneSSVEP.mat');&lt;br /&gt;
&lt;br /&gt;
[numberOfTrials numberOfChannels numberOfSamples] = size(X.data);&lt;br /&gt;
namesOfChannels = X.channels;&lt;br /&gt;
 &lt;br /&gt;
% numberOfChannels numberOfSamples numberOfTrials&lt;br /&gt;
W = zeros(numberOfChannels,numberOfChannels);&lt;br /&gt;
numberOfHarmonics = 3;&lt;br /&gt;
signal = X.data; % (  powtórzenie,  kanał, próbki)&lt;br /&gt;
 &lt;br /&gt;
S = zeros(size(signal));&lt;br /&gt;
W = cosSinCSP(signal,X.stimulation,numberOfHarmonics,X.sampling);&lt;br /&gt;
for powt = 1:size(signal,1)&lt;br /&gt;
    S(powt,:,:) = W'*squeeze(signal(powt,:,:));&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
figure('Name',['Stymulacja: ',num2str(X.stimulation),' Hz'])&lt;br /&gt;
for i =1:numberOfChannels&lt;br /&gt;
    % rysujemy widma uśrednione po realizacjach dla danych &lt;br /&gt;
    % z oryginalnych kanałów EEG&lt;br /&gt;
    subplot(2,8,i)&lt;br /&gt;
    PP=0;&lt;br /&gt;
    for rep = 1:numberOfTrials&lt;br /&gt;
        x = squeeze(signal(rep,i,:));&lt;br /&gt;
        [Pxx,ff] = pwelch(x, X.sampling, 1, X.sampling, X.sampling);&lt;br /&gt;
        PP =PP + Pxx;&lt;br /&gt;
    end&lt;br /&gt;
    plot(ff(ff&amp;lt;60),PP(ff&amp;lt;60))&lt;br /&gt;
    title(namesOfChannels{i})&lt;br /&gt;
 &lt;br /&gt;
    % rysujemy widma uśrednione po realizacjach dla danych &lt;br /&gt;
    % z estymowanych źródeł CSP&lt;br /&gt;
    subplot(2,8,8+i)&lt;br /&gt;
    PP=0;&lt;br /&gt;
    for rep = 1:numberOfTrials&lt;br /&gt;
        s = squeeze(S(rep,i,:));&lt;br /&gt;
        [Pss,ff]=pwelch(s, X.sampling, 1, X.sampling, X.sampling);&lt;br /&gt;
        PP =PP + Pss;&lt;br /&gt;
    end&lt;br /&gt;
    plot(ff(ff&amp;lt;60),PP(ff&amp;lt;60))&lt;br /&gt;
    title(['źródło CSP: ', num2str(i)])&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====ZADANIE: Analiza danych z eksperymentu własnego ====&lt;br /&gt;
# Przefiltruj sygnały EEG w paśmie 1-45 Hz za pomocą procedury &amp;lt;tt&amp;gt;filtfilt&amp;lt;/tt&amp;gt;. &lt;br /&gt;
# Na podstawie sygnału trigger oraz danych zapisanych w pliku wyodrębnij sygnały EEG zarejestrowane w trakcie stymulacji z odpowiednimi częstościami.&lt;br /&gt;
# Uśrednij sygnały odpowiadające stymulacji tą samą częstością. &lt;br /&gt;
# Obejrzyj uśrednione sygnały. (Zaprezentuj je).&lt;br /&gt;
&lt;br /&gt;
#* Sposób I:&lt;br /&gt;
#**Dla każdej realizacji wyestymuj przy pomocy metody Welcha widmo mocy sygnału EEG. &lt;br /&gt;
#**Dla każdej częstości stymulacji wyznacz poziom tła na podstawie widm pochodzących ze stymulacji innymi częstościami. Np. dla stymulacji częstością 10 Hz poziom tła można wyznaczyć jako 95 centyl ze zbioru wartości widma w częstości 10 Hz dla stymulacji częstościami {4, 7, 13, 16, 20, 25, 30, 35, 40} Hz. &lt;br /&gt;
#**Dla każdej częstości stymulacji wyznacz miarę odpowiedzi SSVEP (amplitudę widma odpowiadającą częstości stymulacji powyżej poziomy tła dla pojedynczej próby). &lt;br /&gt;
#**Zaprezentuj widma otrzymane przy stymulacjach różnymi częstościami wraz z korytarzem odpowwiadajacym 95% przedziałowi ufności wyznaczonemu dla widm z pojedynczych realizacji.&lt;br /&gt;
#**Sporządź wykres odpowiedzi SSVEP od częstości z zaznaczeniem przedziałów ufności i poziomu tła. &lt;br /&gt;
#* Sposób II:&lt;br /&gt;
#**Wyestumuj filtr CSP-SSVEP wspólny dla wszystkich częstości stymulacji &lt;br /&gt;
#**Powtórz kroki ze sposobu I dla uzyskanych komponentów.&lt;br /&gt;
#**Zaprezentuj filtry przestrzenne i topografie dla poszczególnych komponentów&lt;br /&gt;
#**Dla przypomnienia:&lt;br /&gt;
#***Filtr to zestaw współczynników z jakimi należy zsumować sygnały z poszczególnych kanałów EEG aby dostać komponenty odpowiadające hipotetycznym źródłom nieskorelowanym. Filtr można zilustrować na głowie, przypisując poszczególnym pozycjom elektrod wagi równe współrzędnym wektora w (kolumna macierzy W).&lt;br /&gt;
#***Topografia źródła to zestaw współczynników z jakimi docierają one do poszczególnych kanałów EEG. Topografia zawarta jest w wierszach macierzy odwrotnej do W. &lt;br /&gt;
#**Można rysunki wykonać jako macierze 5x5 i w pozycji elektrody kolorujemy proporcjonalnie do współczynnika.&lt;br /&gt;
&lt;br /&gt;
===SSVEP-BCI===&lt;br /&gt;
W zajęciach tych przydadzą nam się informacje z:&lt;br /&gt;
https://brain.fuw.edu.pl/edu/index.php/Laboratorium_EEG/Wprowadzenie_do_syg_online&lt;br /&gt;
====Wstęp====&lt;br /&gt;
Naszym celem będzie stworzenie prostego interfejsu wykorzystującego zjawisko SSVEP. &lt;br /&gt;
Po dwóch stronach monitora zamocujemy diody. Każda będzie migać ze swoją ustaloną częstością (np. 16 i 22 Hz) - warto zadbać aby nie były to częstości powiązane ze sobą harmonicznie, a z drugiej strony aby, biorąc pod uwagę wyniki poprzedniego zadania, dawały dobra odpowiedź SSVEP.&lt;br /&gt;
&lt;br /&gt;
Eksperyment będzie miał dwie cześci: sesję kalibracje i sesję on-line. Pomiędzy tymi sesjami będziemy uczyć kalsyfikator. Na podstawie części kalibracyjnej ustalimy jakie parametry przetwarznego on-line sygnału świadczą o patrzeniu się na diodę z lewej a jakie na tą z prawej strony ekranu.&lt;br /&gt;
&lt;br /&gt;
Potem w sesji online będziemy porównywać (za pomocą predykcji klasyfikatora) rejestrowany sygnał z tymi warościami kalibracyjnymi i na tej podstawie system będzie zwracał informację o wyborze lewej lub prawej diody. To powinno umożliwić prostą komunikację na zasadzie pytanie i odpowiedź TAK/NIE.&lt;br /&gt;
&lt;br /&gt;
==== Sesja kalibracycjna====&lt;br /&gt;
* Zakładamy czepek&lt;br /&gt;
* Częstość próbkowania ustawiamy na 256Hz&lt;br /&gt;
* Na podstawie kodu: https://brain.fuw.edu.pl/edu/index.php/Laboratorium_EEG/Wprowadzenie_do_syg_online#.C4.86wiczenie:_Wykorzystanie_pomiaru_EMG_do_sterowania_on-line&lt;br /&gt;
tworzymy programik, który zamiast pętli while tworzy odpowiednie pętle for aby:&lt;br /&gt;
* pięciokrotnie zarejestrować sekwencję trzech warunków eksperymentalnych:&lt;br /&gt;
** patrz 5s na diodę z lewej (warunek l)&lt;br /&gt;
** patrz 5s na środek ekranu (warunek s)&lt;br /&gt;
** patrz 5s na diodę z prawej (warunek p)&lt;br /&gt;
* w czasie tego patrzenia:&lt;br /&gt;
** odbieramy próbki w pakietach o długości 0.5s &lt;br /&gt;
** każdy pakiet filtrujem (technika filtrowania on-line) w pasmach dookoła wybranych dwóch częstości (PASMO_LEWE / PASMO_PRAWE)&lt;br /&gt;
** przefiltrowany pakiet przeliczamy na RMS&lt;br /&gt;
** zbieramy sześć zbiorów wyników -  zestawy RMSów związane z każdym z waunków kalibracyjnych (LEWY/SPOCZYNEK/PRAWY) dla PASMO_LEWE i PASMO_PRAWE.&lt;br /&gt;
* Normalizujemy RMSy. Dla pasma lewego obliczamy (RMS_(l/p/s) - np.mean(RMS_s)) / np.sdt(RMS_s) i analogicznie dla pasma prawego. Małe indeksy oznaczaają tu warunki. Zapamiętujemy współczynniki normalizacyjne.&lt;br /&gt;
** Ogladamy rozkłady uzyskanych wielkości (znormalizowanych RMSów). &lt;br /&gt;
** Uczymy klasyfikator np. regresję logistyczną (https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html) do rozpoznawania, z którym warunkiem patrzenia mamy do czynienia.&lt;br /&gt;
&lt;br /&gt;
==== Sesja online====&lt;br /&gt;
* wczytujemy wyuczony model i kalibracyjne wartości np.mean(RMS_s)) i np.sdt(RMS_s) dla pasm lewego i prawego&lt;br /&gt;
* Odbieramy próbki w pakietach o długości 0.5s &lt;br /&gt;
** każdy pakiet filtrujem (technika filtrowania on-line) w pasmach dookoła wybranych dwóch częstości (PASMO_LEWE / PASMO_PRAWE)&lt;br /&gt;
** przefiltrowany pakiet przeliczamy na RMS&lt;br /&gt;
** Normalizujemy RMSy. Dla pasma lewego obliczamy (RMS_(l/p/s) - np.mean(RMS_s)) / np.sdt(RMS_s) i analogicznie dla pasma prawego. Małe indeksy oznaczaają tu warunki.&lt;br /&gt;
** robimy predykcję klasyfikatora, z którym warunkiem patrzenia mamy do czynienia. Wyświetlamy na ekranie komunikat.&lt;br /&gt;
* Testujemy czy powyższy schemat analizy pozwala na komunikację.&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Eksperyment ASSR===&lt;br /&gt;
W eksprymencie wykorzystujemy układ do generacji potencjałów słuchowych stanu ustalonego (ASSR). Wejście układu ASSR typu mini-jack wkładamy w wyjście słuchawkowe w laptopie. Drugie wejście układu ASSR wkładamy do wyjścia triggera we wzmacniaczu. Uruchamiamy plik dźwiękowy MM40tr.wav. Można go znalezc w: http://www.fuw.edu.pl/~suffa/LabEEG/MM40tr.wav&lt;br /&gt;
&lt;br /&gt;
Stymulacja dźwiękowa składa sie z fali nośnej o częstości 400 Hz modulowanej z częstością 40 Hz. Plik dźwiękowy zawiera 5 sekund ciszy i 5 sekund stymulacji, powtórzone 40 razy.&lt;br /&gt;
&lt;br /&gt;
====Rejestracja sygnału====&lt;br /&gt;
# Zakładamy czepek i elektrody w systemie 10-10, dbamy o to by opory pomiędzy elektrodami były poniżej 5 k&amp;amp;Omega; i różnice pomiędzy oporami różnych elektrod nie przekraczały 20%.&lt;br /&gt;
# Oklejamy kwadrat 3&amp;amp;times;3 elektrod na korze słuchowej z lewej strony (elektrody FT7, FC5, FC3, T7, C5, T3, TP7, CP5, CP3), 3&amp;amp;times;3 elektrod na korze słuchowej z prawej strony (elektrody FT8, FC6, FC4, T8, C6, T4, TP8, CP6, CP4), elektrody Fz, Cz, Pz i Oz, elektrody referencyjne A1 i A2. W sumie powinno być 24 elektrody.&lt;br /&gt;
# Elektrodę GND mocujemy na pozycji AFz.&lt;br /&gt;
# Sygnał rejestrujemy z częstością 2048 Hz.&lt;br /&gt;
# Do rejestracji stosujemy scenariusz 'ASSR' w interfejsie obci_gui.&lt;br /&gt;
&lt;br /&gt;
====Analiza====&lt;br /&gt;
 JZ: zmieniłbym analizę na czas-częstość i zrobił porównanie montażu usznego do filtra G.G. Moliny&lt;br /&gt;
&lt;br /&gt;
Początek stymulacji dźwiękowej oznaczymy jako 0. Poniższą analizę zastosuj dla sygnałów w referencji do uśrednionych odprowadzeń usznych A1 i A2.&lt;br /&gt;
Wyznaczenie pasma częstości odpowiedzi ASSR&lt;br /&gt;
# Z sygnału wycinamy fragmenty od 0 do 5 sek. dla wszystkich elektrod położone nad korą słuchową.&lt;br /&gt;
# Dla każdej realizacji obliczamy widma metodą Welcha.&lt;br /&gt;
# Otrzymane zespolone widma uśredniamy po realizacjach.&lt;br /&gt;
# Sprawdzamy czy w uśrednionym widmie występuję maksimum w częstości modulacji tj. 40 Hz.&lt;br /&gt;
&lt;br /&gt;
====Wyznaczenie przebiegu czasowego ERD i ERS====&lt;br /&gt;
# Zaprojektuj filtry pasmowo przepustowe (Czebyszewa 2 rodzaju) zgodne z wyznaczonym pasmem. Zbadaj funkcje przenoszenia i odpowiedzi impulsowej.&lt;br /&gt;
# Powycinaj sygnały od &amp;amp;minus;5 do +10 sekund (wszystkie kanały). Przefiltruj każdą realizację.&lt;br /&gt;
# Oblicz moc chwilową za pomocą transformaty Hilberta (kwadrat modułu transformaty Hilberta).&lt;br /&gt;
# Uśrednij moc chwilową po realizacjach.&lt;br /&gt;
# Oblicz względną zmianę mocy chwilowej względem czasu &amp;amp;minus;4 do &amp;amp;minus;2 s. W ten sposób otrzymasz przebieg ERD i ERS w czasie.&lt;br /&gt;
# Wykreśl ERD i ERS w układzie topograficznym. (Rozmieść subploty tak, aby z w przybliżeniu odpowiadały pozycjom elektrod).&lt;br /&gt;
&lt;br /&gt;
====Transformacja Hjortha====&lt;br /&gt;
Transformacja Hjortha jest przybliżeniem numerycznym transformacji Laplace'a, czyli drugiej pochodnej przestrzennej. Obliczamy ją jako różnicę potencjału pomiędzy daną elektrodą i średnią z czterech sąsiednich elektrod.&lt;br /&gt;
Przelicz potencjały z elektrod, w których występuję odpowiedź ASSR na montaż Hjortha i powtórz analizę ERD/ERS opisaną powyżej.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ICA jako filtr przestrzenny==&lt;br /&gt;
{{hidden begin|title=Wstęp teoretyczny do ICA}}&lt;br /&gt;
===Definicja ===&lt;br /&gt;
Independent Component Analysis (ICA) jest metodą statystycznej analizy sygnałów, która dokonuje dekompozycji wielokanałowych zapisów na składowe niezależne w sensie statystycznym.&lt;br /&gt;
Dwie składowe ''s''&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; i ''s''&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; są niezależne jeżeli wiedza o wartości ''s''&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; nie daje żadnych informacji o możliwych wartościach ''s''&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. ICA może być wyrażona przez prosty model generatywny:&lt;br /&gt;
: '''x''' = '''Ds'''&lt;br /&gt;
: gdzie '''x''' = {''x''&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;, ''x''&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;, ..., ''x''&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;} jest zmierzonym ''n'' kanałowym sygnałem, '''D''' jest macierzą mieszającą zaś '''s''' = {''s''&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;, ''s''&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;, ..., ''s''&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;} jest aktywnością ''n'' źródeł. Podstawowym założeniem dotyczącym '''s''' jest to, że ''s''&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt; są statystycznie niezależne.  Aby wyestymować model musimy też założyć, że składowe mają niegaussowskie rozkłady wartości (Hyvärinen, 2000).&lt;br /&gt;
&lt;br /&gt;
Dodatkowo model ten zakłada następujące fakty:&lt;br /&gt;
# Sygnał jest liniową mieszaniną aktywności źródeł&lt;br /&gt;
# Sygnały pochodzące z każdego ze źródeł są niezależne od pozostałych&lt;br /&gt;
# Źródła oraz proces ich mieszania są stacjonarne, tzn, ich momenty statystyczne nie zależą od czasu&lt;br /&gt;
# Energie (wariancje) źródeł nie mogą być wyznaczone jednoznacznie. Dzieje się tak ponieważ pomnożenie amplitudy ''i''-tego źródła może być uzyskane poprzez przemnożenie albo ''s''&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt; albo przez przemnożenie ''i''-tej kolumny macierzy '''D'''.  Naturalnym rozwiązaniem tej niejednoznaczności jest wprowadzenie konwencji, że komponenty są normowane tak aby miały wariancję 1: E[''s''&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt;] = 1.&lt;br /&gt;
# Kolejność komponentów jest dowolna.  Bo jeśli w ten sam sposób zmienimy kolejność komponentów w '''s''' i kolumn w '''D''' to dostaniemy dokładnie ten sam sygnał '''x'''.&lt;br /&gt;
&lt;br /&gt;
Głównym wyzwaniem w analizie ICA jest estymacja macierzy mieszającej '''D'''. Gdy jest ona znana to komponenty mogą być wyliczone w następujący sposób:&lt;br /&gt;
: '''s''' = '''D'''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt;'''x'''&lt;br /&gt;
&lt;br /&gt;
=== Estymacja ===&lt;br /&gt;
Znalezienie niezależnych komponentów może być rozważane w świetle Centralnego Twierdzenia Granicznego jako poszukiwanie komponentów o możliwie nie gaussowskim rozkładzie.&lt;br /&gt;
Aby zrozumieć to podejście prześledźmy heurystykę zaproponowaną przez (Hyvärinen, 2000). &lt;br /&gt;
Dla prostoty załóżmy, że poszukiwane źródła niezależne mają identyczne rozkłady. &lt;br /&gt;
Zdefiniujmy &lt;br /&gt;
&lt;br /&gt;
''y''&amp;amp;nbsp;= '''w'''&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt;'''x'''.&lt;br /&gt;
&lt;br /&gt;
Zauważmy, że jeśli &lt;br /&gt;
&lt;br /&gt;
'''w''' &lt;br /&gt;
&lt;br /&gt;
jest jedną z kolumn macierzy &lt;br /&gt;
&lt;br /&gt;
'''D'''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt;, &lt;br /&gt;
&lt;br /&gt;
to ''y'' jest jednym z poszukiwanych komponentów.&lt;br /&gt;
Zamieniając zmienne &lt;br /&gt;
&lt;br /&gt;
'''z'''&amp;amp;nbsp;= '''D'''&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt;'''w''' &lt;br /&gt;
&lt;br /&gt;
możemy napisać &lt;br /&gt;
&lt;br /&gt;
''y''&amp;amp;nbsp;= '''w'''&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt;'''x'''&amp;amp;nbsp;= '''w'''&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt;'''Ds'''&amp;amp;nbsp;= '''z'''&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt;'''s'''. &lt;br /&gt;
&lt;br /&gt;
Uwidacznia to fakt, że ''y'' jest liniową kombinacją składowych s&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt; z wagami danymi przez z&amp;lt;sub&amp;gt;''i''&amp;lt;/sub&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Z centralnego twierdzenia granicznego wynika, że suma niezależnych zmiennych losowych ma  bardziej gaussowski charakter niż każda z tych zmiennych osobno. &lt;br /&gt;
Liniowa kombinacja staje się najmniej gaussowska gdy '''z''' ma tylko jeden element niezerowy. W tym przypadku ''y'' jest proporcjonalny do s&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt;. &lt;br /&gt;
Zatem problem estymacji modelu ICA może być sformułowany jako problem znalezienia takiego wektora '''w''', który maksymalizuje niegaussowskość &lt;br /&gt;
&lt;br /&gt;
''y''&amp;amp;nbsp;= '''w'''&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt;'''x'''. &lt;br /&gt;
&lt;br /&gt;
Maksymalizacja niegaussowskości ''y'' daje jeden niezależny komponent odpowiadający jednemu z 2''n'' maksimów (bo mamy s&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt; i &amp;amp;minus;s&amp;lt;sup&amp;gt;''i''&amp;lt;/sup&amp;gt;) w krajobrazie optymalizacyjnym. Aby znaleźć wszystkie niezależne komponenty musimy znaleźć wszystkie maksima. Ponieważ komponenty są nieskorelowane, to poszukiwania kolejnych komponentów można kontynuować w podprzestrzeni ortogonalnej do już znalezionych komponentów.&lt;br /&gt;
&lt;br /&gt;
===Obliczenia===&lt;br /&gt;
Intuicyjna heurystyka poszukiwania najbardziej niegaussowskich składowych może być użyta do wyprowadzenia różnych funkcji kosztu, których optymalizacja daje model ICA, np. kurtoza.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;kurt(y) = E\{y^4\} - 3(E{y^2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inną miarą gassowskości jest neg-entropia, którą można wyprowadzić z entropii: &lt;br /&gt;
Entropia jest miarą średniego zdziwienia wynikiem obserwacji zmiennej losowej:&lt;br /&gt;
&amp;lt;math&amp;gt;H(Y) = - \sum_i P(Y= a_i) \log(P(Y=a_i)) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Negentropia jest zdefiniowana:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; J(y) = H(y_{gauss}) -H(y)&amp;lt;/math&amp;gt;&lt;br /&gt;
gdzie &amp;lt;math&amp;gt; y_{gauss} &amp;lt;/math&amp;gt; jest gassuwską zmienną losową o takiej samej kowaiancji jak &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Negentropia jest skomplikowana obliczeniow, więc w praktyce używana jest formuła przybliżona:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; J(y) \varpropto   [E\{G (y)\}  - E\{G(\nu)\}]&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\nu &amp;lt;/math&amp;gt; jest zmienną losową ze standardowego rozkładu normalnego , a G są pewnymi niekwadratowymi funkcjami.&lt;br /&gt;
&lt;br /&gt;
W algorytmie FastICA extremum negentropii jest znajdowane w procedurze bazującej na optymalizacji Netwona.&lt;br /&gt;
(szczegóły np.: sekcja 6 w https://www.cs.helsinki.fi/u/ahyvarin/papers/NN00new.pdf)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedura wykorzystywana w eeglabie (&amp;amp;bdquo;runica&amp;amp;rdquo;, Makeig 1996) dąży do minimalizacji informacji wzajemnej. Oba podejścia są w przybliżeniu równoważne (Hyvärinen, 2000), chociaż owo przybliżenie dla  sygnałów elektrofizjologicznych nie zostało to jeszcze w pełni wyeksplorowane.&lt;br /&gt;
Dla sygnałów o niskiej wymiarowości i spełniających dokładnie założenia ICA wszystkie powszechnie wykorzystywane algorytmy dają niemal identyczne wyniki.&lt;br /&gt;
&lt;br /&gt;
;Bardzo ważna uwaga: ogólną zasadą jest, że jeśli estymujemy ''N'' stabilnych komponentów  (z ''N''-kanałowych danych) to musimy dysponować ''kN''&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; punktami danych w każdym kanale, gdzie ''N''&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; jest liczbą elementów w macierzy '''D''', którą ICA próbuje wyestymować, ''k'' jest liczbą całkowitą. Nie ma dobrych oszacowań teoretycznych na wielkość ''k'', z praktycznych obserwacji wynika, że rośnie ona z liczbą kanałów.&lt;br /&gt;
&lt;br /&gt;
=== Możliwe zastosowania ===&lt;br /&gt;
Najczęściej ICA jest stosowana jako narzędzie do:&lt;br /&gt;
* usuwania artefaktów z sygnałów EEG (ruchy oczu i mięśnie) &lt;br /&gt;
* wydobywania składowych do dalszej analizy (Onton, 2006)&lt;br /&gt;
* jako analiza wstępna do lokalizacji źródeł (Grau, 2007).&lt;br /&gt;
* ICA jest także stosowana w analize sygnałów EKG i EMG.&lt;br /&gt;
&lt;br /&gt;
===Bibliografia===&lt;br /&gt;
Bazowa praca:&lt;br /&gt;
* A. Hyvärinen. Fast and Robust Fixed-Point Algorithms for Independent Component Analysis. IEEE Transactions on Neural Networks 10(3):626-634, 1999 http://www.cs.helsinki.fi/u/ahyvarin/papers/TNN99_reprint.pdf&lt;br /&gt;
&lt;br /&gt;
Nieco prościej opisana wersja z przykładami:&lt;br /&gt;
* Hyvärinen, A. and Oja, E. (2000). Independent component analysis: Algorithms and applications. Neural Networks, 13(4-5):411–430.&lt;br /&gt;
https://www.cs.helsinki.fi/u/ahyvarin/papers/NN00new.pdf&lt;br /&gt;
&lt;br /&gt;
* Grau, C., Fuentemilla, L., Marco-Pallars, J. (2007). Functional neural dynamics underlying auditory event-related n1 and n1 suppression response. Neuroimage, 36(6):522–31.&lt;br /&gt;
* Makeig, S., Bell, A., Jung, T.-P., Sejnowski,T. (1996). Independent component analysis of electroencephalographic data. W: Touretzky, D., Mozer, M., and Hasselmo, M., editors, Advances in Neural Information Processing Systems, volume 8, pages 145–151. MIT Press, Cambridge, MA.&lt;br /&gt;
* Onton, J., Makeig, S. (2006). Information-based modeling of event-related brain dynamics. Prog Brain Res., 159:99–120.&lt;br /&gt;
* Tutorial: http://sccn.ucsd.edu/wiki/Chapter_09:_Decomposing_Data_Using_ICA&lt;br /&gt;
* http://sccn.ucsd.edu/~arno/indexica.html&lt;br /&gt;
* http://cis.legacy.ics.tkk.fi/aapo/papers/IJCNN99_tutorialweb/&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
{{hidden begin|title=Wydobywanie interesujących komponentów}}&lt;br /&gt;
&lt;br /&gt;
=== ZADANIE: Wydobywanie interesujących komponentów ===&lt;br /&gt;
&lt;br /&gt;
Dane do tej części ćwiczeń proszę pobrać i rozpakować w swoim katalogu:&lt;br /&gt;
http://www.fuw.edu.pl/~jarekz/LabEEG/Dane_do_ICA_alfa.tar.gz&lt;br /&gt;
&lt;br /&gt;
Pochodzą one z eksperymentu, w którym osoba badana siedziała z zamkniętymi oczami słuchając nagrania czytanego spokojnym głosem. Metadane opisujące sygnał znajdują się w pliku Miro.xml, zaś lokalizacje elektrod w pliku Miro-10-20-Cap.locs.&lt;br /&gt;
&lt;br /&gt;
Proszę:&lt;br /&gt;
* wczytać dane do eeglaba&lt;br /&gt;
* wyedytować lokalizację elektrod&lt;br /&gt;
* usunąć kanały nie zawierające EEG&lt;br /&gt;
* zmienić referencje na średnią z kanałów A1 i A2&lt;br /&gt;
* przefiltrować filtrem FIR górnoprzepustowym z częstością odcięcia 0,5 Hz&lt;br /&gt;
* obejrzeć wstępnie przygotowane dane&lt;br /&gt;
* policzyć ICA na całym sygnale &lt;br /&gt;
* obejrzeć właściwości otrzymanych komponentów&lt;br /&gt;
** Czy są wśród nich takie, które zawierają znaczny udział rytmu alfa?&lt;br /&gt;
** Jaka jest ich topografia?&lt;br /&gt;
* usunąć wszystkie komponenty nie zawierające alfy&lt;br /&gt;
* odtworzyć z tych komponentów sygnał na elektrodach&lt;br /&gt;
* wykonać dekompozycję ICA kilkukrotnie (co najmniej 3) i porównać wyniki&lt;br /&gt;
** Czy uzyskiwane komponenty są powtarzalne? &lt;br /&gt;
** Swoje wyniki porównać też z sąsiednimi grupami.&lt;br /&gt;
{{hidden end}}&lt;br /&gt;
&lt;br /&gt;
===ZADANIE: Identyfikacja artefaktów ===&lt;br /&gt;
Proszę pobrać dane:&lt;br /&gt;
&lt;br /&gt;
*http://www.fuw.edu.pl/~jarekz/LabEEG/Arousal-10-20-Cap.locs&lt;br /&gt;
*http://www.fuw.edu.pl/~jarekz/LabEEG/Arousal1.set&lt;br /&gt;
*http://www.fuw.edu.pl/~jarekz/LabEEG/Arousal1.fdt&lt;br /&gt;
&lt;br /&gt;
Pochodzą one z eksperymentu w którym osoba badana czytała słowa o różnych właściwościach wzbudzania emocji. &lt;br /&gt;
&lt;br /&gt;
* wczytaj je do eeglaba&lt;br /&gt;
* wczytaj lokalizację kanałów z pliku Arousal-10-20-Cap.locs&lt;br /&gt;
* obejrzyj przebiegi czasowe&lt;br /&gt;
* odrzuć kanał z diodą (21) i z GSR (20)&lt;br /&gt;
* zrób dekompozycję ICA&lt;br /&gt;
* obejrzyj topografię komponentów&lt;br /&gt;
* zidentyfikuj komponenty odpowiadające mruganiu i aktywności mięśniowej.&lt;br /&gt;
;UWAGA: Aktualnie do wykrywania komponentów artefaktowych warto posłużyć się wtyczkami do eeglaba dostępnymi przez stronę:&lt;br /&gt;
&lt;br /&gt;
https://sccn.ucsd.edu/eeglab/plugin_uploader/plugin_list_all.php&lt;br /&gt;
&lt;br /&gt;
* ICLabel&lt;br /&gt;
* MARA&lt;br /&gt;
&lt;br /&gt;
====W raporcie: ====&lt;br /&gt;
* zaprezentuj fragmenty sygnału zawierającego artefakty oczne i mięśniowe przed i po zastosowaniu czyszczenia poprzez usuwanie komponentów zdominowanych przez artefakty. &lt;br /&gt;
* zaprezentuj topografię i przebiegi czasowe komponentów zidentyfikowanych jako artefakty oczne i mięśniowe. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
==Filtry przestrzenne dla większej ilości warunków==&lt;br /&gt;
===FFDIAG===&lt;br /&gt;
===Analiza ERD/S z użyciem FFDIAG===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!---&lt;br /&gt;
==Eksperyment ASSR==&lt;br /&gt;
W eksprymencie wykorzystujemy układ do generacji potencjałów słuchowych stanu ustalonego (ASSR). Wejście układu ASSR typu mini-jack wkładamy w wyjście słuchawkowe w laptopie. Drugie wejście układu ASSR wkładamy do wyjścia triggera we wzmacniaczu. Uruchamiamy plik dźwiękowy MM40tr.wav. Można go znalezc w: http://www.fuw.edu.pl/~suffa/LabEEG/MM40tr.wav&lt;br /&gt;
&lt;br /&gt;
Stymulacja dźwiękowa składa sie z fali nośnej o częstości 400 Hz modulowanej z częstością 40 Hz. Plik dźwiękowy zawiera 5 sekund ciszy i 5 sekund stymulacji, powtórzone 40 razy.&lt;br /&gt;
&lt;br /&gt;
===Rejestracja sygnału===&lt;br /&gt;
# Zakładamy czepek i elektrody w systemie 10-10, dbamy o to by opory pomiędzy elektrodami były poniżej 5 k&amp;amp;Omega; i różnice pomiędzy oporami różnych elektrod nie przekraczały 20%.&lt;br /&gt;
# Oklejamy kwadrat 3&amp;amp;times;3 elektrod na korze słuchowej z lewej strony (elektrody FT7, FC5, FC3, T7, C5, T3, TP7, CP5, CP3), 3&amp;amp;times;3 elektrod na korze słuchowej z prawej strony (elektrody FT8, FC6, FC4, T8, C6, T4, TP8, CP6, CP4), elektrody Fz, Cz, Pz i Oz, elektrody referencyjne A1 i A2. W sumie powinno być 24 elektrody.&lt;br /&gt;
# Elektrodę GND mocujemy na pozycji AFz.&lt;br /&gt;
# Sygnał rejestrujemy z częstością 2048 Hz.&lt;br /&gt;
# Do rejestracji stosujemy scenariusz 'ASSR' w interfejsie obci_gui.&lt;br /&gt;
&lt;br /&gt;
===Analiza===&lt;br /&gt;
Początek stymulacji dźwiękowej oznaczymy jako 0. Poniższą analizę zastosuj dla sygnałów w referencji do uśrednionych odprowadzeń usznych A1 i A2.&lt;br /&gt;
Wyznaczenie pasma częstości odpowiedzi ASSR&lt;br /&gt;
# Z sygnału wycinamy fragmenty od 0 do 5 sek. dla wszystkich elektrod położone nad korą słuchową (odcinki podczas stymulacji oraz bez niej).&lt;br /&gt;
# Dla każdej realizacji (odpowiedniego typu) obliczamy widma metodą Welcha.&lt;br /&gt;
# Otrzymane zespolone widma uśredniamy po realizacjach.&lt;br /&gt;
# Sprawdzamy czy w uśrednionym widmie występuję maksimum w częstości modulacji tj. 40 Hz i czy jest różnica między odcinkami ze stymulacją i bez niej.&lt;br /&gt;
&lt;br /&gt;
===Wyznaczenie przebiegu czasowego ERD i ERS===&lt;br /&gt;
# Zaprojektuj filtry pasmowo przepustowe (Czebyszewa 2 rodzaju) zgodne z wyznaczonym pasmem. Zbadaj funkcje przenoszenia i odpowiedzi impulsowej.&lt;br /&gt;
# Powycinaj sygnały od &amp;amp;minus;5 do +10 sekund (wszystkie kanały). Przefiltruj każdą realizację.&lt;br /&gt;
# Oblicz moc chwilową za pomocą transformaty Hilberta (kwadrat modułu transformaty Hilberta).&lt;br /&gt;
# Uśrednij moc chwilową po realizacjach.&lt;br /&gt;
# Oblicz względną zmianę mocy chwilowej względem czasu &amp;amp;minus;4 do &amp;amp;minus;2 s. W ten sposób otrzymasz przebieg ERD i ERS w czasie.&lt;br /&gt;
# Wykreśl ERD i ERS w układzie topograficznym. (Rozmieść subploty tak, aby z w przybliżeniu odpowiadały pozycjom elektrod).&lt;br /&gt;
&lt;br /&gt;
===Transformacja Hjortha===&lt;br /&gt;
Transformacja Hjortha jest przybliżeniem numerycznym transformacji Laplace'a, czyli drugiej pochodnej przestrzennej. Obliczamy ją jako różnicę potencjału pomiędzy daną elektrodą i średnią z czterech sąsiednich elektrod.&lt;br /&gt;
Przelicz potencjały z elektrod, w których występuję odpowiedź ASSR na montaż Hjortha i powtórz analizę opisaną powyżej.&lt;br /&gt;
---&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11249</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11249"/>
		<updated>2025-03-21T12:33:27Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2025: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Wprowadzenie]]&lt;br /&gt;
## 28.02.2025 &lt;br /&gt;
[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|EKG]] &lt;br /&gt;
## 07.03.2025 - Wstęp teoretyczny i pomiary&lt;br /&gt;
## 14.03.2025 - detekcja pików R i tętno&lt;br /&gt;
## 21.03.2025 - analiza HRV&lt;br /&gt;
przesyłanie notebooków z EKG/HRV do 4.04&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|EMG]]&lt;br /&gt;
## 28.03.2025 - wprowadzenie, pomiary, analiza ćwiczenie I&lt;br /&gt;
## 4.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 11.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 25.04.2025 - analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III i ćwiczenie IV -&amp;gt; przesyłanie notebooków z EMG do 16.05&lt;br /&gt;
## 07.05.2025 - seminarium SYNCC IN &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]]&lt;br /&gt;
## 16.05.2025 - podstawowe własności EOG - rejestracja&lt;br /&gt;
## 23.05.2025 - podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 24.05&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
## 30.05.2025 - [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
## 06.06.2025 - [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## 13.06.2025&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG&amp;diff=11247</id>
		<title>Laboratorium EEG</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG&amp;diff=11247"/>
		<updated>2025-03-11T12:58:02Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Metody czas-częstość */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Pracownie specjalistyczne]]&lt;br /&gt;
__NOTOC__&lt;br /&gt;
==Informacje bieżące==&lt;br /&gt;
&amp;lt;!--:[[Laboratorium_EEG/Info_1| Grupa 1: MK+JR]]&lt;br /&gt;
:[[Laboratorium_EEG/Info_2| Grupa 2: JZ+AG]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zajęcia są prowadzone przez Macieja Kamińskiego i Jarosława Żygierewicza&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zajęcia odbywają się w sali 4.59:&lt;br /&gt;
* we wtorki w godzinach 11:15 - 13:30&lt;br /&gt;
* w środy w godzinach 10:45 - 13:00&lt;br /&gt;
&lt;br /&gt;
== Warunki zaliczenia ==&lt;br /&gt;
Ćwiczenia zostaną zaliczone osobom, które spełnią dwa niezwykle proste warunki:&lt;br /&gt;
* Posiadanie maksymalnie dwóch nieusprawiedliwionych nieobecności na ćwiczeniach,&lt;br /&gt;
* Posiadanie przynajmniej połowy sumy punktów ze wszystkich prezentacji,&lt;br /&gt;
* ... ''(do ustalenia).''&lt;br /&gt;
&lt;br /&gt;
=== Elementy oceniane w prezentacji:===&lt;br /&gt;
* poprawność zastosowanego algorytmu -&amp;gt; należy przygotować opis ideowy algorytmu w punktach/na schemacie &lt;br /&gt;
* prezentacja wykonanych testów pokazujacych, że algorytm działa poprawnie &lt;br /&gt;
* jakość kodu (czytelność, komentarze, struktura, czy ktoś komu mielibyśmy przekazać ten kod ma sznsę go zrozumieć)&lt;br /&gt;
* wykazanie się zrozumieniem otrzymanych wyników.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--* Posiadanie przynajmniej połowy sumy punktów ze wszystkich kartkówek&lt;br /&gt;
* Osobom spełniającym powyższe warunki zaproponowana zostanie pozytywna ocena końcowa z Laboratorium.&lt;br /&gt;
* Osoby nie mające tego szczęścia, otrzymają ocenę negatywną.&lt;br /&gt;
&lt;br /&gt;
* Możliwe będzie poprawienie zaproponowanej oceny na wyższą poprzez zrealizowanie dodatkowego projektu. Jego cel zostanie ustalony indywidualnie.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały dydaktyczne==&lt;br /&gt;
Zestaw przykładowych materiałów dotyczących analizy danych w Matlabie towarzyszący książce autorstwa Katarzyny J. Blinowskiej i Jarosława Żygierewicza zatytułowanej &amp;quot;Practical Biomedical Signal Analysis Using MATLAB® Second Edition]&amp;quot; ([https://books.google.pl/books?id=hSpHEAAAQBAJ&amp;amp;pg=PA1&amp;amp;hl=pl&amp;amp;source=gbs_toc_r&amp;amp;cad=3#v=onepage&amp;amp;q&amp;amp;f=false spis treści]):&lt;br /&gt;
 &lt;br /&gt;
https://static.routledge.com/9781138364417/matlab.zip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Wprowadzenie do przetwarzania sygnałów online===&lt;br /&gt;
* [[Laboratorium_EEG/Wprowadzenie_do_syg_online|ONLINE]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 10.03.2021 Pomiar EEG spoczynkowe, artefakty i alfa +P300 ===&lt;br /&gt;
Proszę powtórzyć informacje z : &lt;br /&gt;
* [[Pracownia_Sygnałów_Biologicznych/Zajecia_9]]. W szczególności proszę zwrócić uwagę na:&lt;br /&gt;
** porcedurę zakładania czepka&lt;br /&gt;
** przygotowanie skóry do pomiaru&lt;br /&gt;
** kolejność mocowania elektrod w czepku&lt;br /&gt;
* [[Pracownia_EEG/EEG_spoczynkowe]]&lt;br /&gt;
** Jakie wyróżniamy rytmy i na jakiej podstawie?&lt;br /&gt;
** Jakie są główne źródła artefaktów?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* [[Pracownia_EEG/Potencjały_wywołane#Zadanie_3:_rejestracja_i_analiza_potencja.C5.82u_P3]]&lt;br /&gt;
** Co to jest potencjał P300&lt;br /&gt;
Lektura uzupełniająca o P300:&lt;br /&gt;
Linden, D. E. J. (2005). The P300: Where in the Brain Is It Produced and What Does It Tell Us? The Neuroscientist, 11(6), 563–576. https://doi.org/10.1177/1073858405280524&lt;br /&gt;
(Z IP wydziałowego można pobrać ten art. w pdf)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Wprowadzenie do Matlaba===&lt;br /&gt;
* [[Laboratorium_EEG/Wprowadzenie_do_Matlaba|Wprowadzenie do Matlaba]]&amp;lt;br&amp;gt;&lt;br /&gt;
* [[Laboratorium_EEG/Konwerter_plików_Svarog–Matlab|Wczytywanie do Matlaba plików binarnych z programu Svarog]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Metody czas-częstość===&lt;br /&gt;
&amp;lt;!--* [[Wstęp do analizy obrazu]]--&amp;gt;&lt;br /&gt;
Motywacja - główne paradygmaty BCI:&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1hMbkzn07pVDfeJ4fk9JPHhZaIckz-PVL/view?usp=share_link&lt;br /&gt;
&lt;br /&gt;
Wstęp o analizie ERD/ERS:&lt;br /&gt;
&lt;br /&gt;
https://drive.google.com/file/d/1hP5VglC8jYnoGHJ2j06m1AOMe8ItwCkb/view?usp=share_link&lt;br /&gt;
&lt;br /&gt;
* [[Laboratorium_EEG/Analiza czas-częstość w matlabie|Analiza czas-częstość w matlabie]]&lt;br /&gt;
* [[Laboratorium_EEG/Analiza zjawiska ERD/ERS|Analiza zjawiska ERD/ERS]]&lt;br /&gt;
&lt;br /&gt;
===Filtry przestrzenne===&lt;br /&gt;
* [[Laboratorium_EEG/CSP|Filtry przestrzenne]]:  metody ślepej separacji źródeł&lt;br /&gt;
&lt;br /&gt;
===Zależności przyczynowe===&lt;br /&gt;
* [[Laboratorium_EEG/AR_1|Wielokanałowa analiza parametryczna/Zależności przyczynowe]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Słuchowe potencjały stanu ustalonego: zmiany mocy pasmowej i metody ślepej separacji źródeł===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* [[Laboratorium_EEG/EEGLAB|Pakiet EEGLAB]]&lt;br /&gt;
=== MP===&lt;br /&gt;
* [[Laboratorium_EEG/MMP|MMP]]&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG&amp;diff=11246</id>
		<title>Laboratorium EEG</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG&amp;diff=11246"/>
		<updated>2025-03-11T12:29:20Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Pracownie specjalistyczne]]&lt;br /&gt;
__NOTOC__&lt;br /&gt;
==Informacje bieżące==&lt;br /&gt;
&amp;lt;!--:[[Laboratorium_EEG/Info_1| Grupa 1: MK+JR]]&lt;br /&gt;
:[[Laboratorium_EEG/Info_2| Grupa 2: JZ+AG]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zajęcia są prowadzone przez Macieja Kamińskiego i Jarosława Żygierewicza&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zajęcia odbywają się w sali 4.59:&lt;br /&gt;
* we wtorki w godzinach 11:15 - 13:30&lt;br /&gt;
* w środy w godzinach 10:45 - 13:00&lt;br /&gt;
&lt;br /&gt;
== Warunki zaliczenia ==&lt;br /&gt;
Ćwiczenia zostaną zaliczone osobom, które spełnią dwa niezwykle proste warunki:&lt;br /&gt;
* Posiadanie maksymalnie dwóch nieusprawiedliwionych nieobecności na ćwiczeniach,&lt;br /&gt;
* Posiadanie przynajmniej połowy sumy punktów ze wszystkich prezentacji,&lt;br /&gt;
* ... ''(do ustalenia).''&lt;br /&gt;
&lt;br /&gt;
=== Elementy oceniane w prezentacji:===&lt;br /&gt;
* poprawność zastosowanego algorytmu -&amp;gt; należy przygotować opis ideowy algorytmu w punktach/na schemacie &lt;br /&gt;
* prezentacja wykonanych testów pokazujacych, że algorytm działa poprawnie &lt;br /&gt;
* jakość kodu (czytelność, komentarze, struktura, czy ktoś komu mielibyśmy przekazać ten kod ma sznsę go zrozumieć)&lt;br /&gt;
* wykazanie się zrozumieniem otrzymanych wyników.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--* Posiadanie przynajmniej połowy sumy punktów ze wszystkich kartkówek&lt;br /&gt;
* Osobom spełniającym powyższe warunki zaproponowana zostanie pozytywna ocena końcowa z Laboratorium.&lt;br /&gt;
* Osoby nie mające tego szczęścia, otrzymają ocenę negatywną.&lt;br /&gt;
&lt;br /&gt;
* Możliwe będzie poprawienie zaproponowanej oceny na wyższą poprzez zrealizowanie dodatkowego projektu. Jego cel zostanie ustalony indywidualnie.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały dydaktyczne==&lt;br /&gt;
Zestaw przykładowych materiałów dotyczących analizy danych w Matlabie towarzyszący książce autorstwa Katarzyny J. Blinowskiej i Jarosława Żygierewicza zatytułowanej &amp;quot;Practical Biomedical Signal Analysis Using MATLAB® Second Edition]&amp;quot; ([https://books.google.pl/books?id=hSpHEAAAQBAJ&amp;amp;pg=PA1&amp;amp;hl=pl&amp;amp;source=gbs_toc_r&amp;amp;cad=3#v=onepage&amp;amp;q&amp;amp;f=false spis treści]):&lt;br /&gt;
 &lt;br /&gt;
https://static.routledge.com/9781138364417/matlab.zip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Wprowadzenie do przetwarzania sygnałów online===&lt;br /&gt;
* [[Laboratorium_EEG/Wprowadzenie_do_syg_online|ONLINE]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 10.03.2021 Pomiar EEG spoczynkowe, artefakty i alfa +P300 ===&lt;br /&gt;
Proszę powtórzyć informacje z : &lt;br /&gt;
* [[Pracownia_Sygnałów_Biologicznych/Zajecia_9]]. W szczególności proszę zwrócić uwagę na:&lt;br /&gt;
** porcedurę zakładania czepka&lt;br /&gt;
** przygotowanie skóry do pomiaru&lt;br /&gt;
** kolejność mocowania elektrod w czepku&lt;br /&gt;
* [[Pracownia_EEG/EEG_spoczynkowe]]&lt;br /&gt;
** Jakie wyróżniamy rytmy i na jakiej podstawie?&lt;br /&gt;
** Jakie są główne źródła artefaktów?&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* [[Pracownia_EEG/Potencjały_wywołane#Zadanie_3:_rejestracja_i_analiza_potencja.C5.82u_P3]]&lt;br /&gt;
** Co to jest potencjał P300&lt;br /&gt;
Lektura uzupełniająca o P300:&lt;br /&gt;
Linden, D. E. J. (2005). The P300: Where in the Brain Is It Produced and What Does It Tell Us? The Neuroscientist, 11(6), 563–576. https://doi.org/10.1177/1073858405280524&lt;br /&gt;
(Z IP wydziałowego można pobrać ten art. w pdf)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Wprowadzenie do Matlaba===&lt;br /&gt;
* [[Laboratorium_EEG/Wprowadzenie_do_Matlaba|Wprowadzenie do Matlaba]]&amp;lt;br&amp;gt;&lt;br /&gt;
* [[Laboratorium_EEG/Konwerter_plików_Svarog–Matlab|Wczytywanie do Matlaba plików binarnych z programu Svarog]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Metody czas-częstość===&lt;br /&gt;
&amp;lt;!--* [[Wstęp do analizy obrazu]]--&amp;gt;&lt;br /&gt;
* [[Laboratorium_EEG/Analiza czas-częstość w matlabie|Analiza czas-częstość w matlabie]]&lt;br /&gt;
* [[Laboratorium_EEG/Analiza zjawiska ERD/ERS|Analiza zjawiska ERD/ERS]]&lt;br /&gt;
===Filtry przestrzenne===&lt;br /&gt;
* [[Laboratorium_EEG/CSP|Filtry przestrzenne]]:  metody ślepej separacji źródeł&lt;br /&gt;
&lt;br /&gt;
===Zależności przyczynowe===&lt;br /&gt;
* [[Laboratorium_EEG/AR_1|Wielokanałowa analiza parametryczna/Zależności przyczynowe]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Słuchowe potencjały stanu ustalonego: zmiany mocy pasmowej i metody ślepej separacji źródeł===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* [[Laboratorium_EEG/EEGLAB|Pakiet EEGLAB]]&lt;br /&gt;
=== MP===&lt;br /&gt;
* [[Laboratorium_EEG/MMP|MMP]]&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11236</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11236"/>
		<updated>2025-02-27T14:01:25Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2025: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Spotkanie I (Wprowadzenie)]]&lt;br /&gt;
## 28.02.2025 &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|Spotkania II - V (EKG)]] &lt;br /&gt;
## 07.03.2025 - Wstęp teoretyczny i pomiary&lt;br /&gt;
## 14.03.2025 - detekcja pików R i tętno&lt;br /&gt;
## 21.03.2025 - analiza HRV&lt;br /&gt;
## 28.03.2025 - analiza HRV -&amp;gt; przesyłanie notebooków z EKG/HRV do 4.04&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|Spotkanie VI - VIII (EMG)]]&lt;br /&gt;
## 4.04.2025 - wprowadzenie, pomiary, analiza ćwiczenie I&lt;br /&gt;
## 11.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 25.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 07.05.2025 - analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III i ćwiczenie IV -&amp;gt; przesyłanie notebooków z EMG do 16.05&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]]&lt;br /&gt;
## 16.05.2025 - podstawowe własności EOG - rejestracja&lt;br /&gt;
## 23.05.2025 - podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 24.05&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
## 30.05.2025 - [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
## 06.06.2025 - [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## 13.06.2025&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11235</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11235"/>
		<updated>2025-02-27T13:31:40Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2025: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Spotkanie I (Wprowadzenie)]]&lt;br /&gt;
## 28.02.2025 &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|Spotkania II - V (EKG)]] &lt;br /&gt;
## 07.03.2025 - Wstęp teoretyczny i pomiary&lt;br /&gt;
## 14.03.2025 - detekcja pików R i tętno&lt;br /&gt;
## 21.03.2025 - analiza HRV&lt;br /&gt;
## 28.03.2025 - analiza HRV -&amp;gt; przesyłanie notebooków z EKG/HRV do 5.04&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|Spotkanie VI - VIII (EMG)]]&lt;br /&gt;
## 4.04.2025 - wprowadzenie, pomiary, analiza ćwiczenie I&lt;br /&gt;
## 11.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 25.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 07.05.2025 - analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III i ćwiczenie IV -&amp;gt; przesyłanie notebooków z EMG do 13.05&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]]&lt;br /&gt;
## 16.05.2025 - podstawowe własności EOG - rejestracja&lt;br /&gt;
## 23.05.2025 - podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 24.05&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
## 30.05.2025 - [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
## 06.06.2025 - [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## 13.06.2025&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11234</id>
		<title>Pracownia Sygnałów Bioelektrycznych</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=Pracownia_Sygna%C5%82%C3%B3w_Bioelektrycznych&amp;diff=11234"/>
		<updated>2025-02-27T13:31:30Z</updated>

		<summary type="html">&lt;p&gt;Jarekz: /* Materiały */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Pracownie specjalistyczne]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zajęcia w roku 2024: 8:45-12&lt;br /&gt;
&lt;br /&gt;
'''UWAGA: godzina 8:45 to początek zajęć, a nie schodzenia się na zajęcia'''&lt;br /&gt;
&lt;br /&gt;
Dla NI link do classroom: https://classroom.google.com/c/NjY2MjI3NDU2NDA3?cjc=mvvocie&lt;br /&gt;
&lt;br /&gt;
==Zasady zaliczenia pracowni==&lt;br /&gt;
&lt;br /&gt;
* Obecność na zajęciach jest obowiązkowa, dopuszczalne są 2 nieusprawiedliwione nieobecności.&lt;br /&gt;
&lt;br /&gt;
Materiał zajęć jest podzielony na bloki tematyczne. W każdym bloku studenci mają do wykonania zestaw ćwiczeń. Pod koniec każdego bloku konieczne będzie przesłanie raportu w postaci notebooka na adres jarekz@fuw.edu.pl&lt;br /&gt;
&lt;br /&gt;
# Prezentacja wyników w notebooku powinna uwzględniać:&lt;br /&gt;
#* przypomnienie, co było liczone (i jak, jeśli trzeba);&lt;br /&gt;
#* na co należy zwrócić uwagę w prezentowanych wynikach;&lt;br /&gt;
#* interpretację wykresów.&amp;lt;br&amp;gt;Część z tych informacji można dołożyć do rysunków w postaci krótkich wyjaśnień.&lt;br /&gt;
# Należy zadbać o prawidłową postać wykresów, w tym w szczególności:&lt;br /&gt;
#* obecność opisów osi (w miarę możliwości jednostek);&lt;br /&gt;
#* spójne zakresy osi i skalowanie wykresów;&lt;br /&gt;
#* właściwy dobór skali (tak, aby uwidocznić najważniejsze rzeczy);&lt;br /&gt;
#* obecność tytułów i innych podpisów ułatwiających zrozumienie prezentowanych treści.&lt;br /&gt;
# Ocenie podlegają:&lt;br /&gt;
#* kompletność prezentacji;&lt;br /&gt;
#* poprawność kodu;&lt;br /&gt;
#* czytelność prezentowanych wielkości i zjawisk;&lt;br /&gt;
#* merytoryczna poprawność wypowiedzi.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--# &lt;br /&gt;
# Każdy z powyższych elementów będzie uwzględniony w ocenie prezentacji w 10-punktowej skali. Do wyniku końcowego będą liczyły się punkty z trzech (na cztery) najlepszych prezentacji.&lt;br /&gt;
Każde zajęcia rozpoczynają się od wejściówki, za którą można uzyskać od 0 do 2 punktów.&lt;br /&gt;
# Aby zaliczyć przedmiot trzeba uzyskać połowę punktów za prezentacje. Wszystkie razem zsumowane punkty zadecydują o ocenie końcowej.&lt;br /&gt;
# Wyniki dodatkowe, ponadprogramowe, są mile widziane i mogą skutkować lepszą oceną.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Materiały==&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_1|Spotkanie I (Wprowadzenie)]]&lt;br /&gt;
## 28.02.2025 &lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_2_4|Spotkania II - V (EKG)]] &lt;br /&gt;
## 07.03.2025 - Wstęp teoretyczny i pomiary&lt;br /&gt;
## 14.03.2025 - detekcja pików R i tętno&lt;br /&gt;
## 21.03.2025 - analiza HRV&lt;br /&gt;
## 28.03.2025 - analiza HRV -&amp;gt; przesyłanie notebooków z EKG/HRV do 5.04&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_5_6|Spotkanie VI - VIII (EMG)]]&lt;br /&gt;
## 4.04.2025 - wprowadzenie, pomiary, analiza ćwiczenie I&lt;br /&gt;
## 11.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 25.04.2025 - analiza ćwiczenie I&lt;br /&gt;
## 07.05.2025 - analiza sygnału online (ćwiczenie V),  analiza ćwiczenie III i ćwiczenie IV -&amp;gt; przesyłanie notebooków z EMG do 13.05&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_7|Spotkanie IX - XI (EOG)]]&lt;br /&gt;
## 16.05.2025 - podstawowe własności EOG - rejestracja&lt;br /&gt;
## 23.05.2025 - podstawowe własności EOG - analiza i szykowanie raportów: zwrot raportów z EOG 24.05&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_9|Spotkanie XII - XIV (Wprowadzenie EEG)]]&lt;br /&gt;
## 30.05.2025 - [[Pracownia_EEG/EEG_spoczynkowe|EEG spoczynkowe, artefakty ]]&lt;br /&gt;
## 06.06.2025 - [[Pracownia_Sygnałów_Biologicznych/Zajecia_10|Analiza EEG]]&lt;br /&gt;
## 13.06.2025&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#[[Pracownia_Sygnałów_Biologicznych/Zajecia_8|Spotkanie  (GSR)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Autor: dr hab. Piotr Suffczyński&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
</feed>