http://brain.fuw.edu.pl/edu/api.php?action=feedcontributions&user=Tspus&feedformat=atomBrain-wiki - Wkład użytkownika [pl]2024-03-29T13:50:05ZWkład użytkownikaMediaWiki 1.34.1http://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG/CSP&diff=7128Laboratorium EEG/CSP2017-05-30T14:52:07Z<p>Tspus: /* Ćwiczenie symulacyjne */</p>
<hr />
<div>[[Laboratorium_EEG]]/BSS<br />
=Ślepa separacja źródeł=<br />
Rozważmy ''N''-kanałowy sygnał EEG.<br />
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. <br />
<br />
Taki zbiór punktów wygodniej jest analizować w układzie współrzędnych zgodnym z osiami głównymi macierzy kowariancji.<br />
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. <br />
[[Plik:Kowariancja.png|200px|center]]<br />
<br />
==Filtry przestrzenne i ślepa separacja źródeł==<br />
Sygnał EEG jest superpozycją aktywności elektrycznej wielu źródeł.<br />
Jak można estymować aktywność samych źródeł?<br />
[[Plik:Mieszanie.png|200px|center]]<br />
Niech:<br />
: <math>s(t)</math> - aktywność niezależnych źródeł,<br />
: <math>x(t)</math> mierzony sygnał<br />
: <math>A</math> macierz przejścia taka, że:<br />
::<math>x(t) = A s(t)</math> (*)<br />
:<math>s(t) = A^{-1}x(t) = P x(t)</math><br />
Macierz kowariancji dla sygnałów <math>x(t)</math> estymujemy tak:<br />
:<math> C_x = E[x(t)x(t)^T]</math><br />
Podstawiając (*) mamy:<br />
:<math> C_x = E[x x^T] = E[As(As)^T] = A E[s s^T] A^T = A C_s A^T</math><br />
Z założenia, że źródła są niezależne wynika, że macierz <math>C_s</math> jest diagonalna.<br />
Przekształcając powyższe równanie możemy zapisać:<br />
:<math>A^{-1} C_x (A^T)^{-1} = P C_x P^T = C_s</math><br />
Odwzorowanie <math>P = A^{-1}</math> diagonalizuje macierz <math>C_x</math>. <br />
<br />
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.<br />
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.<br />
<br />
[[Plik:Diagonalizacja.png|200px|center]]<br />
<br />
==Common Spatial Pattern ==<br />
===Koncepcja===<br />
Dla ustalenia uwagi możemy myśleć o eksperymencie wywołującym potencjał P300. Mamy w nim dwie sytuacje eksperymentalne. Oznaczmy <math>T</math> (target) próby, w których pojawił się oczekiwany bodziec, zaś <math>NT</math> (non-target) gdy pojawił się bodziec standardowy.<br />
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.<br />
<br />
===Formalizm===<br />
Metoda ta polega na znalezieniu takiego kierunku <math>w</math> w przestrzeni sygnałów, że sygnał z warunku <math>T</math> rzutowany na ten kierunek ma dużą wariancje a sygnał z warunku <math>NT</math> ma wariancję małą. <br />
<br />
Rzutowanie sygnału <math>x(t)</math> na kierunek <math>w</math> odbywa się przez policzenie iloczynu skalarnego dla każdej chwili czasu <math>t</math>:<br />
:<math> s_w(t) = w^T x(t)</math><br />
Wariancja tego rzutowanego sygnału to:<br />
:<math> \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 </math><br />
Zatem znalezienie właściwego kierunku rzutowania można wyrazić jako szukanie maksimum wyrażenia <math> J(w) </math> (jest to tzw. iloraz Rayleigha):<br />
: <math>J(w) = \frac{w^T C_T w}{w^T C_{NT} w} </math><br />
Ekstremum tego ilorazu można znaleźć poprzez policzenie gradientu <math>J(w)</math> i przyrównanie go do zera:<br />
:<math> \nabla J(w) = \frac{ 1 C_{T} w+w^T C_{T} 1}{w^T C_{NT} w}-\frac{w^T C_{T} w\left( 1 C_{NT} w+w^T C_{NT} 1\right)}{\left(w^T C_{NT} w\right)^2}</math><br />
ponieważ macierze kowariancji są symetryczne <br />
::<math>\nabla J(w) = \frac{ 1}{w^T C_{NT} w}\left[ C_{T} w+ C_{T}w -\frac{w^T C_{T} w}{w^T C_{NT} w} \left( C_{NT} w+ C_{NT}w \right) \right]</math><br />
::<math>= \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]</math><br />
Przyrównując to wyrażenie do zera dostajemy do rozwiązania tzw. uogólnione zagadnienie własne:<br />
:<math> C_{T}w =\frac{w^T C_{T} w}{w^T C_{NT} w} C_{NT} w </math><br />
We wzorze tym liczba <math>\lambda=\frac{w^T C_{T} w}{w^T C_{NT} w}</math> spełniająca to równanie jest uogólnioną wartością własną, wtedy <math>w</math> jest uogólnionym wektorem własnym odpowiadającym tej wartości. <br />
<br />
Aby znaleźć <math> \lambda</math> i <math>w</math> możemy wykorzystać w Matlabie funkcję <tt>eig</tt>. Funkcja ta rozwiązuje (również) uogólnione zagadnienia własne postaci ''Aw''=&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.<br />
<br />
<!--<br />
Odwzorowanie to można przedstawić w postaci macierzy <math>P</math>, której każdy wiersz zawiera wagi dla odpowiednich kanałów. <br />
Macierz zawierająca sygnał <math>X^{\pm}(t)</math> <br />
ma wymiary <math>C \times N</math>, gdzie <br />
<math>C</math> to liczba kanałów EEG, natomiast <br />
<math>N</math> to liczba próbek dla każdego z kanałów. <br />
Macierz <math>P</math> przekształca sygnał <math>X^{\pm}(t)</math> zgodnie ze wzorem:<br />
:<math>X^{\pm}_{CSP}(t)=P^T X^{\pm}(t) </math><br />
Załóżmy dalej, że sygnały <math>X^{+}_{CSP} (t)</math> i <math>X^{-}_{CSP} (t)</math> są generowane przez niezależne procesy stochastyczne, tzn. spełnione są następujące warunki. <br />
# Syganły <math>X^{+}_{CSP} (t)</math> i <math>X^{-}_{CSP} (t)</math> są niezależne.<br />
# Brak korelacji pomiędzy kanałami w sygnałach<math>X^{+}_{CSP} (t)</math> i <math>X^{-}_{CSP} (t)</math>.<br />
# Przynajmniej dla jednego z kanałów wariancja przetransformowanego sygnału jest maksymalna przy wystąpieniu bodźca i minimalna przy jego braku.<br />
Po przemnożeniu równania 2.3 przez <math>(X^{\pm}_{CSP} (t))^T</math> otrzymamy macierz kowariancji przetransformowanych sygnałów uśrednioną po realizacjach:<br />
:<math>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</math> (2.4)<br />
Gdzie <math>R^{\pm}</math> to macierz kowariancji sygnału uśredniona po realizacjach. Z warunków 1 i 2 wynika, że macierze <math>R^{+}_{CSP}</math> i <math>R^{-}_{CSP}</math> muszą być diagonalne, natomiast z warunku 3, że ich suma daje macierz jednostkową:<br />
:<math>R^{+}_{CSP} + R^{-}_{CSP} = 1 </math> (2.5)<br />
Tak więc suma par diagonalnych wartości (<math>k^{+}_{i}</math> i <math>k^{-}_{i}</math>) w macierzach <math>R^{+}_{CSP}</math> i <math>R^{-}_{CSP}</math> musi być równa 1.<br />
Korzystając z równania 2.5 wartości na przekątnej można również zapisać za pomocą wzoru:<br />
<br />
:<math>k^{+}_{i} = \vec{p}^{T}_{i} R^{+} \vec{p}_{i} </math> (2.6)<br />
:<math>k^{-}_{i} = \vec{p}^T_{i} R^{-}\vec{p}_{i} </math> (2.7)<br />
gdzie <math>\vec{p}_{i}</math> to kolumnowy wektor macierzy <math>P</math>. Po przekształceniach ilorazu równań 2.6 i 2.7 można<br />
otrzymać równanie:<br />
<br />
:<math>R^{+} \vec{p}_{i} = \frac{k^{+}_{i}}{k^{-}_{i}} R^{-} \vec{p}_{i} </math> (2.8)<br />
<br />
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.<br />
<br />
<br />
Wektor własny <math>\vec{p}_i</math> jest interpretowany jako filtr przestrzenny. Dzięki transformacie <math>P</math> 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ą <math>k^{+}</math>.<br />
--><br />
<br />
===Ćwiczenie symulacyjne ===<br />
<source lang = matlab><br />
% symulowany eksperyment składa się z sinusoidy udającej alfę spoczynkową i<br />
% funkcji Gaussa udającego potencjał wywołany<br />
% źródła te są symulowane niezależnie a potem mieszane przez macierz A<br />
% symulujemy źródła<br />
% s1 - symuluje alfę<br />
% s2 - symuluje "potencjał wywołany" (ERP)<br />
<br />
%ustawiamy parametry do symulacji sygnałów<br />
Fs = 100;<br />
T = 1;<br />
t = 0:1/Fs:T-1/Fs;<br />
N_rep = 100;<br />
N_chan = 2;<br />
s = zeros(N_rep,N_chan, length(t));<br />
X = zeros(N_rep,N_chan, length(t));<br />
<br />
% filtr przestrzenny - z takimi wagami trzeba wziąść kanały EEG aby odzyskać sygnały źródłowe<br />
P = [1 2<br />
1.5 1.3]; <br />
<br />
<br />
% topografie - z takimi wagami źródła dokładają się do poszczególnych elektrod<br />
A = P^(-1); <br />
<br />
<br />
for r =1:N_rep % tworzymy kolejne realizacje "eksperymentu"<br />
s1 = sin(2*pi*11*t +pi/2+ 0*2*pi*rand())+ 0.02*randn(size(t)); % źródło alfa<br />
s2 = exp(-((t-0.8)/0.05).^2)+ 0.01*randn(size(t)); % źródło ERP<br />
<br />
s(r,1,:) = s1;<br />
s(r,2,:) = s2;<br />
tmp = squeeze(s(r,:,:));<br />
n = 0*randn(size(tmp));<br />
X(r,:,:) = A*tmp +n; % rzutujemy sygnały źródłowe na elektrody s -> x<br />
<br />
end<br />
<br />
% wycinamy warunki <br />
% baseline_ind to indeksy pierwszej połowy każdego powtórzenia "baseline"<br />
% ERP_ind to indeksy drugiej połowy każdego powtórzenia zawierająca "ERP"<br />
baseline_ind = find(t<0.5);<br />
ERP_ind = find(t>=0.5);<br />
<br />
x_baseline_kan_1 = X(:,1,baseline_ind);<br />
x_baseline_kan_2 = X(:,2,baseline_ind);<br />
<br />
x_ERP_kan_1 = X(:,1,ERP_ind);<br />
x_ERP_kan_2 = X(:,2,ERP_ind);<br />
<br />
<br />
<br />
% liczymy średnie macierze kowariancji:<br />
R_E = zeros(N_chan,N_chan);<br />
R_B = zeros(N_chan,N_chan);<br />
for r =1:N_rep<br />
B = squeeze(X(r,:,baseline_ind)); <br />
tmp =cov(B');<br />
R_B = R_B + tmp./trace(tmp);%B*B' ;<br />
<br />
E = squeeze(X(r,:,ERP_ind));<br />
tmp = cov(E');<br />
R_E = R_E + tmp./trace(tmp);%E*E' ;<br />
end<br />
<br />
R_B = R_B/N_rep;<br />
R_E = R_E/N_rep;<br />
<br />
% rozwiązujemy uogólnione zagadnienie własne<br />
[W,Lambda]=eig(R_E,R_B); % możliwa jest też optymalizacja wzg. średniej macierzy kowariancji (R_B+R_A)/2);<br />
<br />
% odzyskujemy sygnały źródeł<br />
for r =1:N_rep<br />
S(r,:,:) = W'*squeeze(X(r,:,:));<br />
end<br />
<br />
% pobieramy wycinki odpowiadające obu częściom eksperymentu z estymowanych<br />
% źródeł<br />
s_baseline_estymowany_kan1 = squeeze( S(:,1,baseline_ind));<br />
s_baseline_estymowany_kan2 = squeeze( S(:,2,baseline_ind));<br />
<br />
s_ERP_estymowany_kan1 = squeeze(S(:,1,ERP_ind));<br />
s_ERP_estymowany_kan2 = squeeze(S(:,2,ERP_ind));<br />
<br />
%%%%%%%%%%%%%% Ilustracje %%%%%%%%%%%%%%%%%%%%%%%<br />
% ilustracja sygnałów mierzonych<br />
figure(1);clf<br />
subplot(2,2,1);<br />
plot(t(baseline_ind),(squeeze(X(:,1,baseline_ind)))','b'); hold on<br />
plot(t(ERP_ind),(squeeze( X(:,1,ERP_ind)))','r'); hold off<br />
xlabel('elektroda 1')<br />
title('ilustracja sytuacji pomiarowej -\newline znane są potencjały na elektrodach w dwóch warunkach eksperymentalnych')<br />
subplot(2,2,3);<br />
plot(t(baseline_ind),(squeeze(X(:,1,baseline_ind)))','b'); hold on<br />
plot(t(ERP_ind),(squeeze( X(:,2,ERP_ind)))','r'); hold off<br />
xlabel('elektroda 2')<br />
subplot(1,2,2)<br />
plot(x_baseline_kan_1(:),x_baseline_kan_2(:),'b.');<br />
hold on<br />
plot(x_ERP_kan_1(:),x_ERP_kan_2(:),'r.');<br />
xlim([-2,2])<br />
ylim([-2,2])<br />
axis equal<br />
<br />
% wektor własny odpowiadający największej wartości własnej jest<br />
% kierunkiem najbardziej różnicującym warunki eksperymentalne<br />
disp('wartości własne znajdują się na przekątnej macierzy Lambda')<br />
disp(Lambda)<br />
% rysujemy wersory jednostkowe w kierunkach wektorów własnych<br />
w1 = W(:,1); <br />
w1 = w1/norm(w1);<br />
w2 = W(:,2); <br />
w2 = w2/norm(w2);<br />
line([0, w1(1) ],[0,w1(2)],'Color',[0,0.3,0])<br />
text(w1(1),w1(2),'wektor własny 1')<br />
line([0, w2(1) ],[0,w2(2)],'Color',[1,0,1])<br />
text(w2(1),w2(2),'wektor własny 2')<br />
<br />
<br />
xlabel('Amplituda na elektrodzie 1')<br />
ylabel('Amplituda na elektrodzie 2') <br />
legend('baseline','ERP')<br />
<br />
% Ilustracja estymowanych źródeł<br />
figure(2);clf<br />
subplot(2,2,1);<br />
plot(t(baseline_ind),(squeeze(S(:,1,baseline_ind)))','b');hold on<br />
plot(t(ERP_ind),(squeeze(S(:,1,ERP_ind)))','r');hold off<br />
xlabel('estymowane zrodlo 1')<br />
title('ilustracja estymacji -\newline estymowane są potencjały źródeł w dwóch warunkach eksperymentalnych') <br />
subplot(2,2,3);<br />
plot(t(baseline_ind),(squeeze(S(:,2,baseline_ind)))','b');hold on<br />
plot(t(ERP_ind),(squeeze(S(:,2,ERP_ind)))','r');hold off<br />
xlabel('estymowane zrodlo 2');<br />
subplot(1,2,2)<br />
plot(s_baseline_estymowany_kan1(:),s_baseline_estymowany_kan2(:),'b.');<br />
hold on<br />
plot(s_ERP_estymowany_kan1(:),s_ERP_estymowany_kan2(:),'r.'); <br />
<br />
xlabel('Amplituda estym. źródła 1')<br />
ylabel('Amplituda estym. źródła 2') <br />
legend('baseline','ERP')<br />
</source><br />
<br />
==Zastosowanie filtra CSP do detekcji potencjału P300==<br />
===Eksperyment===<br />
====Przygotowanie do badania:====<br />
* założyć czepek z elektrodami w systemie 10-20;<br />
* elektrody referencyjne: M1 i M2;<br />
* elektroda GND w pozycji AFz.<br />
<br />
====Przygotowanie scenariuszy obci ====<br />
* w terminalu uruchomić <tt>obci srv</tt>;<br />
* w terminalu uruchomić <tt>obci_gui --preset brain2013</tt>;<br />
* w interfejsie GUI zapisujemy scenariusze do własnego katalogu np &bdquo;P300&rdquo;<br />
** &bdquo;P-Brain2013 Signal (with ID)&rdquo; jako np. &bdquo;Sygnal&rdquo;<br />
** &bdquo;P-Brain2013 Calibration p300&rdquo; jako &bdquo;kalibracjaP300&rdquo;<br />
** &bdquo;P-Brain 2013 p300&rdquo; jako &bdquo;Labirynt&rdquo;<br />
* 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.<br />
* edytujemy parametry peerów.<br />
** 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.<br />
** w naszych scenariuszach zapisanych w plikach Sygnal.ini, kalibracjaP300.ini, Labirynt.ini podmieniamy ścieżkę <tt>config =</tt> w sekcji <tt>[peers.amplifier]</tt> tak, aby pokazywała na ten skopiowany plik global_amplifier.ini<br />
** w tym pliku global_amplifier.ini podmieniamy linijki (tak aby były to listy faktycznie wykorzystywanych kanałów) z:<br />
*** <tt>active_channels</tt><br />
*** <tt>channel_names</tt><br />
** dodajemy też linijkę: <tt>sampling_rate = 256</tt><br />
* wchodzimy po kolei do katalogów: Sygnal_configs, kalibracjaP300_configs, Labirynt_configs i odnajdujemy plik switch_backup.ini. W tym pliku ustawiamy parametr <tt>new_scenario</tt> na pusty. To spowoduje, że scenariusze te nie będą uruchamiać kolejnych scenariuszy po zakończeniu działania.<br />
** edytujemy plik ~/.obci/scenarios/P300/kalibracjaP300_configs/clasifier.ini <br />
*** zmieniamy linię<br />
::: <tt>ignore_channels = DriverSaw;AmpSaw;PO7;PO8</tt><br />
::: na <br />
::: <tt>ignore_channels = DriverSaw;AmpSaw;A1;A2</tt><br />
::* oraz linię:<br />
::: <tt>montage_channels = PO7;PO8</tt><br />
::: na <br />
::: <tt>montage_channels = A1;A2</tt><br />
<br />
====Przeprowadzenie badania:====<br />
# Uruchom scenariusz &bdquo;Sygnał&rdquo;.<br />
# Tworzy on w katalogu domowym plik o nazwie <tt>file_id_name</tt>.<br />
# Uruchamiamy Svaroga z terminala poleceniem <tt>svarog</tt>. W zakładce sygnały on-line odnajdujemy nazwę naszego scenariusza &bdquo;Sygnal&rdquo;. Podłączamy się do niego i poprawiamy ewentualnie źle kontaktujące elektrody.<br />
# Jak już jesteśmy zadowoleni z jakości sygnału to zatrzymujemy scenariusz &bdquo;Sygnal&rdquo; w obci.<br />
# W pliku <tt>file_id_name</tt> znajduje się string, który stanowi rdzeń do tworzenia nazw plików, z których korzystają nasze scenariusze. Proszę zmienić ten string np. na: <tt>test1</tt>.<br />
# Uruchamiamy scenariusz &bdquo;kalibracjaP300&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.<br />
# Po zakończeniu kalibracji uruchamiamy scenariusz &bdquo;Labirynt&rdquo;.<br />
# Danych z kalibracji potrzebować będziemy kilka zestawów. Proszę powtórzyć kilkukrotnie scenariusz &bdquo;kalibracjaP300&rdquo;. Przed każdym uruchomieniem trzeba zmienić string w pliku <tt>file_id_name</tt> np. na <tt>test???</tt> gdzie <tt>???</tt> oznacza kolejne numery.<br />
<br />
===Analiza wstępna===<br />
* Wczytać dane kalibracyjne do Matlaba i pociąć je na realizacje typu T &mdash; &bdquo;target&rdquo; (związane z wystąpieniami litery &bdquo;B&rdquo;) i NT &mdash; &bdquo;non-target&rdquo; (pozostałe litery) o długości &minus;200 do +800 ms wokół triggerów. Dla każdej realizacji odjąć trend liniowy.<br />
* Sygnał zmontować wzgl. &bdquo;połączonych uszu&rdquo; i wyświetlić średnie przebiegi dla warunku T i NT w układzie topograficznym &mdash; wykorzystać w tym celu funkcję <tt>topoplot</tt> z pakietu Eeglab.<br />
<br />
Poniżej zaprezentowany jest przykładowy skrypt do cięcia danych wokół znaczników. Działa on z plikami zawartymi w archiwum:<br />
: [[Plik:KalibracjaP300.tar.gz]] <br />
Korzysta z funkcji pomocniczych dostępnych w dystrybucji obci w katalogu <br />
: /usr/share/openbci/analysis/matlab_obci_signal_processing<br />
Openbci można pobrać z https://github.com/BrainTech/openbci<br />
<br />
<source lang = matlab><br />
% ustalamy nzawy plików z danymi<br />
nazwaPliku = 'p_6301423_calibration_p300.obci';<br />
nameOfXMLFile = strcat(nazwaPliku,'.xml');<br />
nameOfTagFile = strcat(nazwaPliku,'.tag'); %tagi = znaczniki zdarzeń<br />
namesOfDataFiles = strcat(nazwaPliku,'.raw');<br />
<br />
% inicjujemy obiekt rm<br />
rm = ReadManager(nameOfXMLFile,namesOfDataFiles,nameOfTagFile);<br />
<br />
% obieramy przydatne parametry i znaczniki<br />
numberOfChannels = rm.get_param('number_of_channels');<br />
namesOfChannels = rm.get_param('channels_names');<br />
samplingFrequency = rm.get_param('sampling_frequency');<br />
tagsStruct = rm.get_tags();<br />
<br />
% tworzenie list znaczników Target i NonTarget<br />
numberOfStruct = length(tagsStruct);<br />
targetTimeStamps = [];<br />
NonTargetTimeStamps = [];<br />
for structNumber = 1:numberOfStruct % iterujemy się przez tagi<br />
if(strcmp(tagsStruct(structNumber).name,'blink')) % szukamy tagów o nazwie 'blink'<br />
index = tagsStruct(structNumber).children.index; % tu jest numer pola stymulacji<br />
target= tagsStruct(structNumber).children.target;% tu jest numer pola na którym wyświetlany jest target<br />
if index == target % warunek na to, że mamy do czynienia z tagiem target<br />
targetTimeStamps = [targetTimeStamps tagsStruct(structNumber).start_timestamp]; %dodajemy timeStamp do listy targetów<br />
else<br />
NonTargetTimeStamps = [NonTargetTimeStamps tagsStruct(structNumber).start_timestamp];%dodajemy timeStamp do listy non-targetów<br />
end<br />
<br />
end<br />
end<br />
<br />
<br />
<br />
% pobieramy próbki<br />
samples = double(rm.get_samples()); % konwersja na double jest potrzebna żeby dobrze funkcjonowało filtrowanie<br />
samples=samples(1:8,:); % odrzucamy kanały, które nie mają EEG<br />
numberOfChannels =8;<br />
<br />
% filtrujemy dolnoprzepustowo aby odrzucić artefakty sieci i część<br />
% artefaktów mięśniowych<br />
[b,a] = cheby2(6,80,25 /(samplingFrequency/2),'low');<br />
for ch = 1:numberOfChannels<br />
samples(ch,:)=filtfilt(b,a,samples(ch,:));<br />
end<br />
<br />
% montujemy dane do wspólnej średniej (common average)<br />
M = -ones(8,8)/8;<br />
M=M+eye(8,8)*9/8;<br />
samples = 0.0715*M*samples;<br />
<br />
% wycinamy dane wokół znaczników<br />
PRE = -0.2; % czas przed tagiem w sek.<br />
POST = 0.8; % czas po tagu w sek.<br />
wycinek = floor(PRE*samplingFrequency:POST*samplingFrequency); % tablica ze "standardowymi" indeksami do cięcia<br />
<br />
% pobieramy targety<br />
TargetSignal = zeros(length(targetTimeStamps),numberOfChannels, length(wycinek)); % tablica na sygnały target<br />
for trialNumber = 1:length(targetTimeStamps)<br />
trigerOnset = floor(targetTimeStamps(trialNumber)*samplingFrequency);<br />
tenWycinek = wycinek + trigerOnset;<br />
if tenWycinek(1)>0 && tenWycinek(end)<=size(samples,2) % test czy wycinek który chcemy pobrać nie wystaje poza dostępny sygnał<br />
tmpSignal = samples(:,tenWycinek);<br />
tmpSignal = detrend(tmpSignal')'; % usuwanie liniowego trendu - przy krótkich wycinkach działa lepiej niż filtrowanie górnoprzepustowe<br />
TargetSignal(trialNumber, :,:) = tmpSignal;<br />
end<br />
end<br />
<br />
% pobieramy non-targety<br />
NonTargetSignal = zeros(length(NonTargetTimeStamps),numberOfChannels, length(wycinek));% tablica na sygnały non-target<br />
for trialNumber = 1:length(NonTargetTimeStamps)<br />
trigerOnset = floor(NonTargetTimeStamps(trialNumber)*samplingFrequency);<br />
tenWycinek = wycinek + trigerOnset;<br />
if tenWycinek(1)>0 && tenWycinek(end)<=size(samples,2)<br />
tmpSignal = samples(:,tenWycinek);<br />
tmpSignal = detrend(tmpSignal')';<br />
NonTargetSignal(trialNumber, :,:) = tmpSignal;<br />
end<br />
end<br />
%<br />
% dla ilustracji podglądamy średnie po powtórzeniach ze wszystkich targetów<br />
% i non-targetów<br />
plot(squeeze(mean(TargetSignal,1))','r');<br />
hold on<br />
plot(squeeze(mean(NonTargetSignal,1))','b')<br />
</source><br />
<br />
===Analiza CSP===<br />
Link do Read menager [https://drive.google.com/open?id=0BzwQ_Lscn8yDS3RXNWdBbkxEQ2c]<br />
<br />
* Korzystając z danych kalibracyjnych wykonać analizę CSP wzmacniającą potencjał P300.<br />
* 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?<br />
<br />
* Dla kanału najbardziej różnicującego wykonać mapki topograficzne wektorów odpowiadających:<br />
** filtrowi przestrzennemu <br />
** rzutu topograficznego źródła na elektrody.<br />
* Do wykonania tych mapek wykorzystać funkcję <tt>topoplot</tt> z pakietu <tt>eeglab</tt><br />
* Zbadać powtarzalność topografii pomiędzy plikami konfiguracyjnymi.<br />
<br />
===Wybór i separacja cech===<br />
* Przedstaw na rysunkach nałożone na siebie pojedyncze realizacje z warunków target i non-target po rzutowaniu na wektor <math>w</math> odpowiadający największej i kolejnej wartości własnej. <br />
* Przedstaw wykresy punktowe takie, że na jednej osi jest moc sygnału odpowiadającego największej wartości własnej, a na drugiej osi kolejnej wartości własnej; jeden punkt reprezentuje jedno powtórzenie.<br />
* Wykonaj serię wykresów jak w poprzednim punkcie dla uśrednień kolejno po 2, 4, 6, 8 i 10 realizacjach. Zaobserwuj jak zmienia się separacja w grupach target i non-target.<br />
<br />
==Filtry przestrzenne dla SSEP ==<br />
<br />
=== Teoria===<br />
Ciekawa koncepcja filtra przestrzennego dla SSVEP zaprezentowana jest tu: http://www.eurasip.org/Proceedings/Eusipco/Eusipco2009/contents/papers/1569193209.pdf<br />
<br />
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.<br />
<br />
Przyda nam się macierz <math>S</math> 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 <math>S</math> zbudowana jest z wersorów rozpinających przestrzeń, w której powinien znajdować się sygnał SSVEP.<br />
<br />
W matlabie możemy taką macierz zbudować tak:<br />
<source lang = matlab><br />
% Fs - częstość próbkowania<br />
% numberOfSamples - długość sygnału w próbkach<br />
% numberOfHarmonics - liczba harmonicznych, które chcemy włączyć do analizy<br />
t = (0:1:numberOfSamples - 1)/Fs; <br />
S = zeros(numberOfSamples, 2*numberOfHarmonics);<br />
<br />
for harmonicNumber = 1:numberOfHarmonics<br />
c = cos(2*pi*stimulationFrequency*harmonicNumber*t);<br />
s = sin(2*pi*stimulationFrequency*harmonicNumber*t);<br />
S(:,(harmonicNumber - 1)*2 + 1) = c/norm(c);<br />
S(:,(harmonicNumber - 1)*2 + 2) = s/norm(s);<br />
end<br />
</source><br />
<br />
<br />
Aby w badanym sygnale znaleźć składowe odpowiadające SSVEP musimy rzutować sygnał <math>X</math> (macierz sygnałów ''kanały &times; próbki'') na przestrzeń rozpiętą przez <math>S</math>:<br />
:<math>A = X*S</math><br />
Macierz <math>A</math> zawiera współczynniki będące iloczynami skalarnymi sygnałów i wersorów. Mówią one o tym &bdquo;jak dużo&rdquo; jest sinusa bądź cosinusa o danej częstości w pierwotnym sygnale. Komponenty SSVEP zawarte w sygnale <math>X</math> odzyskujemy tak:<br />
:<math>\mathrm{SSVEP} = A S^T</math><br />
<br />
Modelujemy rejestrowany sygnał jako:<br />
:<math>X = \mathrm{SSVEP} + Y </math><br />
gdzie: <br />
:<math>Y = X-\mathrm{SSVEP}</math> <br />
: to wszystkie komponenty sygnału, które nas nie interesują.<br />
<br />
Filtr przestrzenny, który chcemy zbudować powinien maksymalizować stosunek wariancji <math>\mathrm{SSVEP} = A S^T</math> do wariancji <math>Y = X-\mathrm{SSVEP}</math>. 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 <tt>cov</tt> już wykonuje tę operację).<br />
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 <math>\mathrm{SSVEP} </math> i <math>Y </math>.<br />
<br />
===Poniżej prosta demonstracja dla danych zebranych EEG przy stymulacji SSVEP z częstotliwością 38 Hz.===<br />
Spakowane dane: [[Plik:PrzykladoweDaneSSVEP.mat.gz]].<br />
W oparciu o powyższy opis proszę zaimplementować funkcję <tt>cosSinCSP</tt>. Prawidłowo zaimplementowana funkcja wraz z poniższym kodem powinna generować rysunek:<br />
[[Plik:Rys_SSVEP_demo.png|400px|podpis grafiki]] <br />
<source lang = matlab><br />
% wczytujemy dane<br />
load('PrzykladoweDaneSSVEP.mat');<br />
<br />
[numberOfTrials numberOfChannels numberOfSamples] = size(X.data);<br />
namesOfChannels = X.channels;<br />
<br />
% numberOfChannels numberOfSamples numberOfTrials<br />
W = zeros(numberOfChannels,numberOfChannels);<br />
numberOfHarmonics = 3;<br />
signal = X.data; % ( powtórzenie, kanał, próbki)<br />
<br />
S = zeros(size(signal));<br />
W = cosSinCSP(signal,X.stimulation,numberOfHarmonics,X.sampling);<br />
for powt = 1:size(signal,1)<br />
S(powt,:,:) = W'*squeeze(signal(powt,:,:));<br />
end<br />
<br />
figure('Name',['Stymulacja: ',num2str(X.stimulation),' Hz'])<br />
for i =1:numberOfChannels<br />
% rysujemy widma uśrednione po realizacjach dla danych <br />
% z oryginalnych kanałów EEG<br />
subplot(2,8,i)<br />
PP=0;<br />
for rep = 1:numberOfTrials<br />
x = signal(rep,i,:);<br />
[Pxx,ff] = pwelch(x, X.sampling, 1, X.sampling, X.sampling);<br />
PP =PP + Pxx;<br />
end<br />
plot(ff(ff<60),PP(ff<60))<br />
title(namesOfChannels{i})<br />
<br />
% rysujemy widma uśrednione po realizacjach dla danych <br />
% z estymowanych źródeł CSP<br />
subplot(2,8,8+i)<br />
PP=0;<br />
for rep = 1:numberOfTrials<br />
s = S(rep,i,:);<br />
[Pss,ff]=pwelch(s, X.sampling, 1, X.sampling, X.sampling);<br />
PP =PP + Pss;<br />
end<br />
plot(ff(ff<60),PP(ff<60))<br />
title(['źródło CSP: ', num2str(i)])<br />
end<br />
</source><br />
<br />
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]]<br />
<br />
<!--<br />
===Eksperyment ASSR===<br />
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<br />
<br />
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.<br />
<br />
====Rejestracja sygnału====<br />
# Zakładamy czepek i elektrody w systemie 10-10, dbamy o to by opory pomiędzy elektrodami były poniżej 5 k&Omega; i różnice pomiędzy oporami różnych elektrod nie przekraczały 20%.<br />
# Oklejamy kwadrat 3&times;3 elektrod na korze słuchowej z lewej strony (elektrody FT7, FC5, FC3, T7, C5, T3, TP7, CP5, CP3), 3&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.<br />
# Elektrodę GND mocujemy na pozycji AFz.<br />
# Sygnał rejestrujemy z częstością 2048 Hz.<br />
# Do rejestracji stosujemy scenariusz 'ASSR' w interfejsie obci_gui.<br />
<br />
====Analiza====<br />
JZ: zmieniłbym analizę na czas-częstość i zrobił porównanie montażu usznego do filtra G.G. Moliny<br />
<br />
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.<br />
Wyznaczenie pasma częstości odpowiedzi ASSR<br />
# Z sygnału wycinamy fragmenty od 0 do 5 sek. dla wszystkich elektrod położone nad korą słuchową.<br />
# Dla każdej realizacji obliczamy widma metodą Welcha.<br />
# Otrzymane zespolone widma uśredniamy po realizacjach.<br />
# Sprawdzamy czy w uśrednionym widmie występuję maksimum w częstości modulacji tj. 40 Hz.<br />
<br />
====Wyznaczenie przebiegu czasowego ERD i ERS====<br />
# Zaprojektuj filtry pasmowo przepustowe (Czebyszewa 2 rodzaju) zgodne z wyznaczonym pasmem. Zbadaj funkcje przenoszenia i odpowiedzi impulsowej.<br />
# Powycinaj sygnały od &minus;5 do +10 sekund (wszystkie kanały). Przefiltruj każdą realizację.<br />
# Oblicz moc chwilową za pomocą transformaty Hilberta (kwadrat modułu transformaty Hilberta).<br />
# Uśrednij moc chwilową po realizacjach.<br />
# Oblicz względną zmianę mocy chwilowej względem czasu &minus;4 do &minus;2 s. W ten sposób otrzymasz przebieg ERD i ERS w czasie.<br />
# Wykreśl ERD i ERS w układzie topograficznym. (Rozmieść subploty tak, aby z w przybliżeniu odpowiadały pozycjom elektrod).<br />
<br />
====Transformacja Hjortha====<br />
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.<br />
Przelicz potencjały z elektrod, w których występuję odpowiedź ASSR na montaż Hjortha i powtórz analizę ERD/ERS opisaną powyżej.<br />
--><br />
<br />
==ICA jako filtr przestrzenny==<br />
===Definicja ===<br />
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.<br />
Dwie składowe ''s''<sub>1</sub> i ''s''<sub>2</sub> są niezależne jeżeli wiedza o wartości ''s''<sub>1</sub> nie daje żadnych informacji o możliwych wartościach ''s''<sub>2</sub>. ICA może być wyrażona przez prosty model generatywny:<br />
: '''x''' = '''Ds'''<br />
: gdzie '''x''' = {''x''<sup>1</sup>, ''x''<sup>2</sup>, ..., ''x''<sup>''n''</sup>} jest zmierzonym ''n'' kanałowym sygnałem, '''D''' jest macierzą mieszającą zaś '''s''' = {''s''<sup>1</sup>, ''s''<sup>2</sup>, ..., ''s''<sup>''n''</sup>} jest aktywnością ''n'' źródeł. Podstawowym założeniem dotyczącym '''s''' jest to, że ''s''<sup>''i''</sup> są statystycznie niezależne. Aby wyestymować model musimy też założyć, że składowe mają niegaussowskie rozkłady wartości (Hyvärinen, 2000).<br />
<br />
Dodatkowo model ten zakłada następujące fakty:<br />
# Sygnał jest liniową mieszaniną aktywności źródeł<br />
# Sygnały pochodzące z każdego ze źródeł są niezależne od pozostałych<br />
# Źródła oraz proces ich mieszania są stacjonarne, tzn, ich momenty statystyczne nie zależą od czasu<br />
# 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''<sup>''i''</sup> 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''<sup>''i''</sup>] = 1.<br />
# 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'''.<br />
<br />
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:<br />
: '''s''' = '''D'''<sup>&minus;1</sup>'''x'''<br />
<br />
=== Estymacja ===<br />
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.<br />
Aby zrozumieć to podejście prześledźmy heurystykę zaproponowaną przez (Hyvärinen, 2000). <br />
Dla prostoty załóżmy, że poszukiwane źródła niezależne mają identyczne rozkłady. <br />
Zdefiniujmy ''y''&nbsp;= '''w'''<sup>T</sup>'''x'''. Zauważmy, że jeśli '''w'''<sup>T</sup> jest jedną z kolumn macierzy '''D'''<sup>&minus;1</sup>, to ''y'' jest jednym z poszukiwanych komponentów.<br />
Zamieniając zmienne '''z'''&nbsp;= '''D'''<sup>T</sup>'''w''' możemy napisać ''y''&nbsp;= '''w'''<sup>T</sup>'''x'''&nbsp;= '''w'''<sup>T</sup>'''Ds'''&nbsp;= '''z'''<sup>T</sup>'''s'''. Uwidacznia to fakt, że ''y'' jest liniową kombinacją składowych s<sup>''i''</sup> z wagami danymi przez z<sub>''i''</sub>. <br />
Z centralnego twierdzenia granicznego wynika, że suma niezależnych zmiennych losowych ma bardziej gaussowski charakter niż każda z tych zmiennych osobno. <br />
Liniowa kombinacja staje się najmniej gaussowska gdy '''z''' ma tylko jeden element niezerowy. W tym przypadku ''y'' jest proporcjonalny do s<sup>''i''</sup>. <br />
Zatem problem estymacji modelu ICA może być sformułowany jako problem znalezienia takiego wektora '''w''', który maksymalizuje niegaussowskość ''y''&nbsp;= '''w'''<sup>T</sup>'''x'''. <br />
Maksymalizacja niegaussowskości ''y'' daje jeden niezależny komponent odpowiadający jednemu z 2''n'' maksimów (bo mamy s<sup>''i''</sup> i &minus;s<sup>''i''</sup>) 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.<br />
<br />
===Obliczenia===<br />
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. Procedura wykorzystywana w eeglabie (&bdquo;runica&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.<br />
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.<br />
<br />
;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''<sup>2</sup> punktami danych w każdym kanale, gdzie ''N''<sup>2</sup> 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.<br />
<br />
=== Możliwe zastosowania ===<br />
Najczęściej ICA jest stosowana jako narzędzie do:<br />
* usuwania artefaktów z sygnałów EEG (ruchy oczu i mięśnie) <br />
* wydobywania składowych do dalszej analizy (Onton, 2006)<br />
* jako analiza wstępna do lokalizacji źródeł (Grau, 2007).<br />
* ICA jest także stosowana w analize sygnałów EKG i EMG.<br />
<br />
===Bibliografia===<br />
* 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.<br />
* Hyvärinen, A. and Oja, E. (2000). Independent component analysis: Algorithms and applications. Neural Networks, 13(4-5):411–430.<br />
* 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.<br />
* Onton, J., Makeig, S. (2006). Information-based modeling of event-related brain dynamics. Prog Brain Res., 159:99–120.<br />
* Tutorial: http://sccn.ucsd.edu/wiki/Chapter_09:_Decomposing_Data_Using_ICA<br />
* http://sccn.ucsd.edu/~arno/indexica.html<br />
* http://cis.legacy.ics.tkk.fi/aapo/papers/IJCNN99_tutorialweb/<br />
<br />
=== Wydobywanie interesujących komponentów ===<br />
<br />
Dane do tej części ćwiczeń proszę pobrać i rozpakować w swoim katalogu:<br />
http://www.fuw.edu.pl/~jarekz/LabEEG/Dane_do_ICA_alfa.tar.gz<br />
<br />
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.<br />
<br />
Proszę:<br />
* wczytać dane do eeglaba<br />
* wyedytować lokalizację elektrod<br />
* usunąć kanały nie zawierające EEG<br />
* zmienić referencje na średnią z kanałów A1 i A2<br />
* przefiltrować filtrem FIR górnoprzepustowym z częstością odcięcia 0,5 Hz<br />
* obejrzeć wstępnie przygotowane dane<br />
* policzyć ICA na całym sygnale <br />
* obejrzeć właściwości otrzymanych komponentów<br />
** Czy są wśród nich takie, które zawierają znaczny udział rytmu alfa?<br />
** Jaka jest ich topografia?<br />
* usunąć wszystkie komponenty nie zawierające alfy<br />
* odtworzyć z tych komponentów sygnał na elektrodach<br />
* wykonać dekompozycję ICA kilkukrotnie (co najmniej 3) i porównać wyniki<br />
** Czy uzyskiwane komponenty są powtarzalne? <br />
** Swoje wyniki porównać też z sąsiednimi grupami.<br />
<br />
=== Identyfikacja artefaktów ===<br />
Proszę pobrać dane:<br />
<br />
*http://www.fuw.edu.pl/~jarekz/LabEEG/Arousal-10-20-Cap.locs<br />
*http://www.fuw.edu.pl/~jarekz/LabEEG/Arousal1.set<br />
*http://www.fuw.edu.pl/~jarekz/LabEEG/Arousal1.fdt<br />
<br />
Pochodzą one z eksperymentu w którym osoba badana czytała słowa o różnych właściwościach wzbudzania emocji. <br />
<br />
* wczytaj je do eeglaba<br />
* wczytaj lokalizację kanałów z pliku Arousal-10-20-Cap.locs<br />
* obejrzyj przebiegi czasowe<br />
* odrzuć kanał z diodą (21) i z GSR (20)<br />
* zrób dekompozycję ICA<br />
* obejrzyj topografię komponentów<br />
* zidentyfikuj komponenty odpowiadające mruganiu i aktywności mięśniowej.<br />
<br />
<!--<br />
==Filtry przestrzenne dla większej ilości warunków==<br />
===FFDIAG===<br />
===Analiza ERD/S z użyciem FFDIAG===<br />
--></div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Elektroencefalografia/Biofizyczne_podstawy_generacji_sygna%C5%82%C3%B3w_EEG&diff=6228Elektroencefalografia/Biofizyczne podstawy generacji sygnałów EEG2016-12-15T13:44:18Z<p>Tspus: /* Warstwa dipolowa &mdash; najważniejsze źródło sygnału EEG */</p>
<hr />
<div><br />
W rozdziale tym poznamy mechanizmy neuronalne odpowiedzialne za powstawanie potencjałów na czaszce, mierzonych jako sygnały EEG. Rozdział ten jest opracowany w oparciu o Nunez (1981, 1995, 2006).<br />
<br />
==Własności tkanki nerwowej==<br />
Na początku zajmijmy się własnościami tkanki nerwowej, w której generowane są potencjały. Tkanka nerwowa składa się neuronów przekazujących impulsy nerwowe oraz komórek glejowych wspomagających działanie neuronów. W komórkach występuje płyn wewnątrzkomórkowy, a na zewnątrz, płyn zewnątrzkomórkowy. Płyn zewnątrz- i wewnątrzkomórkowy składa się z wody, białek oraz dodatnio i ujemnie naładowanych jonów. W płynie wewnątrzkomórkowym dominują jony K<sup>+</sup>, Mg<sup>2+</sup>, Na<sup>+</sup>, HCO<sub>3</sub><sup>–</sup>, izetionianu. W płynie zewnątrzkomórkowym głównym kationem są jony Na<sup>+</sup>, a anionem jony Cl<sup>–</sup>. Ze względu na występowanie jonów swobodnych, w tkance nerwowej mogą płynąć prądy jonowe, w których biorą udział zarówno dodatnie, jak i ujemne jony. W odróżnieniu od obwodów elektrycznych, w których prąd jest rozłożony równomiernie w całym przekroju poprzecznym elementów obwodu i można operować pojęciem prądu całkowitego, w tkance nerwowej wygodnie operuje się uogólnionym pojęciem tzw. gęstością prądu '''J'''. Gęstość prądu pochodzącego do wielu różnych jonów, można wyrazić jako sumę poszczególnych przyczynków od jonów mających gęstość ładunku &rho;''<sub>i</sub>'' i prędkość '''v'''''<sub>i</sub>'':<br />
<equation id="eq:gestosc pradu"><math>\textbf{J} = \sum_i {\rho}_i \textbf{v}_i</math> </equation> <br />
<br />
Gęstość ładunku jest równa wartości ładunku danego jonu pomnożonej przez liczbę wolnych jonów w elemencie objętości tkanki. Jednostką gęstości ładunku jest C/m<sup>3</sup>. '''v'''''<sub>i</sub>'' są to średnie prędkości jonów wyrażone w metrach na sekundę. Gęstość prądu jest to ilość prądu przepływająca przez jednostkowy przekrój poprzeczny, a jego jednostką jest C/(m<sup>2</sup>s) lub A/m<sup>2</sup>. W skali makroskopowej (np. w próbce materii zawierającej 10<sup>20</sup> lub więcej ładunków w ruchu), tkanka nerwowa spełnia prawo Ohma. Oznacza to liniową zależność pomiędzy gęstością prądu, a przyłożonym polem elektrycznym ('''E'''):<br />
<equation id="eq:prawo Ohma"><math>\textbf{J} = {\sigma} \textbf{E}</math> </equation> <br />
<br />
Stała proporcjonalności &sigma; jest nazywana przewodnictwem elektrycznym ośrodka i wyraża się w jednostkach 1/(&Omega;m) lub równoważnie w Siemens/m (S/m). W tkance biologicznej często wygodniej jest stosować jednostki 1/(&Omega;cm) lub 1/(&Omega;mm) i (S/mm) Oporność jest odwrotnością przewodnictwa i jest mierzona w &Omega;m. Tkanka mózgowa jest słabym przewodnikiem. Np. makroskopowa oporność kory mózgowej jest ok. milion razy większa od oporności miedzi. Na poziomie mikroskopowym, błony komórkowe wykazują zachowanie nieliniowe, odbiegające od prawa Ohma. Gdy potencjał błonowy (pole elektryczne wewnątrz komórki) wzrasta powyżej pewnej wartości progowej, błona staje nieliniowym przewodnikiem, co umożliwia generacje i propagacje impulsów nerwowych.<br />
<br />
==Ładunki w przewodnikach==<br />
<br />
Wykonajmy myślowy eksperyment polegający na umieszczeniu ładunku próbnego w przewodniku np. tkance biologicznej. Gdy umieścimy dodatnio naładowany ładunek w przewodniku, występują dwa oddzielne efekty. Efekt polaryzacji spowodowany reorganizacją ładunków w błonach komórkowych (własności dielektryczne tkanki) oraz efekt przewodnictwa spowodowany ruchem ładunków swobodnych w płynie zewnątrzkomórkowym. Ten drugi efekt spowoduje, że dodatni ładunek próbny będzie wkrótce otoczony chmurą ujemnych ładunków, które będą w dużym stopniu ekranować pole pochodzące od ładunku próbnego. Potencjał w punkcie '''r''', pochodzący od ładunku próbnego umieszczonego w elektrolicie w punkcie '''r'''<sub>1</sub> był wyprowadzony w połowie XX wieku na bazie rozważań statystycznych i wynosi:<br />
<br />
<equation id="eq:prawo_Debye"><math>\Phi(r) = \frac{q}{4 \pi \epsilon_{0} \kappa R} e^{-\frac{R}{R_D}}</math> </equation> <br />
<br />
''R<sub>D</sub>'' jest tzw. długością Debye'a, a &kappa; odpowiada za efekty polaryzacyjne. ''R'' = |'''r''' – '''r'''<sub>1</sub>|. Dla &kappa; = 1 i ''R'' ≪ ''R<sub>D</sub>'', dostajemy potencjał ładunku punktowego w próżni. Jednakże ''R<sub>D</sub>'' jest rzędu kilku angstremów (10<sup>–10</sup> m) w tkance biologicznej, co powoduje, ze eksponent we wzorze <br />
(<xr id="eq:prawo_Debye"></xr>) wynosi ok. 10<sup>–4000000</sup> w odległości ''R'' = 3 mm. Pokazuje to, że potencjał ładunku próbnego umieszczonego w tkance biologicznej jest zaniedbywalnie mały dla wszystkich makroskopowych odległości. Nie można więc powiedzieć, że potencjały w mózgu są spowodowane pewnym rozkładem określonym ładunku. Są one spowodowane nie tylko określonym rozkładem ładunku ale również wszystkimi ładunkami w ośrodku przewodzącym. W tkance biologicznej, źródła prądowe w błonach neuronalnych, a nie ładunki, są generatorami EEG.<br />
<br />
==Podstawowe równania==<br />
Wszystkie zjawiska elektryczne i magnetyczne w mózgu podlegają uniwersalnym prawom Maxwella: <br />
<equation id="eq:Max I"><math>\nabla \textbf{D} = \rho </math> </equation> <br />
<equation id="eq:Max II"><math>\nabla \times \textbf{E} = -\frac{\partial \textbf{B}}{\partial t}</math> </equation> <br />
<equation id="eq:Max III"><math>\nabla \textbf{B} = 0 </math> </equation> <br />
<equation id="eq:Max IV"><math>\nabla \times \textbf{H} = \textbf{J} + \frac{\partial \textbf{{D}}}{\partial t}</math> </equation> <br />
<br />
gdzie '''D''' — indukcja elektryczna , '''E''' — natężenie pola elektrycznego, '''B''' — indukcja magnetyczna, '''H''' — natężenie pola magnetycznego, &rho; — gęstość ładunku, '''J''' — gęstość prądu. W wielu materiałach, również w tkance nerwowej, pola '''D''' i '''B''' zależą liniowo od '''E''' i '''H''':<br />
<br />
<equation id="eq:dielectric"><math>\textbf{D} = \varepsilon \textbf{E} </math> </equation> <br />
<equation id="eq:magnetic"><math>\textbf{B} = \mu \textbf{H} </math> </equation> <br />
<br />
Gdzie: &epsilon; — przenikalność elektryczna, a &mu; — przenikalność magnetyczna ośrodka.<br />
<br />
Do opisu pól elektrycznych w tkance nerwowej stosuje się uproszczoną wersje równań Maxwella oraz równań opisujących liniowe własności ośrodka. Podstawowe równania liniowej elektrofizjologii można podsumować następująco: <br />
<equation id="eq:Conservation of charge"><math>\nabla \textbf{J} + \frac{\partial {\rho}}{\partial t} = 0 </math> </equation> <br />
<equation id="eq:Gauss' law"><math>\nabla \textbf{D} = \rho </math> </equation> <br />
<equation id="eq:Ohm's law"><math>\textbf{J} = {\sigma} \textbf{E}</math> </equation> <br />
<equation id="eq:Linear dielectric"><math>\textbf{D} = \varepsilon \textbf{E} </math> </equation> <br />
<equation id="eq:Scalar potential"><math>\textbf{E} = -\nabla \Phi </math> </equation> <br />
<br />
<br />
Zasada zachowania ładunku (równanie <xr id="eq:Conservation of charge"> %i</xr>) wynika bezpośrednio z 1 i 4 równania Maxwella (równania <xr id="eq:Max I"> %i</xr> i <xr id="eq:Max IV"> %i</xr>), oraz z tożsamości <br />
<equation id="eq:Tozsamosc"><math>\nabla (\nabla \times \textbf{A}) = 0 </math> </equation> <br />
<br />
Równanie potencjału skalarnego dla pola elektrycznego (równanie <xr id="eq:Scalar potential"> %i</xr>) jest spełnione w przybliżeniu wolnych oscylacji pól, co pozwala zaniedbać indukcję magnetyczną.<br />
<br />
==Warunki brzegowe w ośrodkach niejednorodnych ==<br />
Różne obszary mózgu mają różne przewodnictwa, tak więc w praktycznych zagadnieniach występują granice między ośrodkami. W skali makroskopowej, najbardziej oczywiste granice między ośrodkami dotyczą granicy pomiędzy słabo przewodzącą czaszką i powietrzem otaczającym głowę. W skali mikroskopowej mamy do czynienia z granicami tworzonymi przez błonę komórkową z ośrodkiem zarówno zewnętrznym jak i wewnętrznym. Potencjał elektryczny &Phi;('''r''', ''t'') będzie miał różne rozwiązania &Phi;''<sub>i</sub>''('''r''', ''t'') w obszarach ''i'' o przewodnictwie &sigma;''<sub>i</sub>''. Porównajmy najpierw efekty opornościowe i efekty pojemnościowe. Zastosujmy operator &nabla; do czwartego równania Maxwella (równanie <xr id="eq:Max IV"> %i</xr>) oraz skorzystajmy z tożsamości (<xr id="eq:Tozsamosc"></xr>). Dostajemy:<br />
<br />
<equation id="eq:Appendix B.1.1"><math>\nabla \left( \textbf{J} + \frac{\partial \textbf{{D}}}{\partial t} \right)=0</math> </equation> <br />
<br />
Rozważmy składową pola elektrycznego oscylującego z częstością ''f''<br />
<equation id="eq:Appendix B.1.2"><math>\textbf{E}(\textbf{r},t) = \textbf{E}_1(\textbf{r})\exp(2\pi i f t)</math> </equation> <br />
<br />
i wyraźmy równanie (<xr id="eq:Appendix B.1.1"></xr>) stosując prawo Ohma (<xr id="eq:Ohm's law"></xr>) i liniowe równanie dla dielektryka (<xr id="eq:Linear dielectric"></xr>):<br />
<br />
<equation id="eq:Appendix B.1.3"><math>\nabla (\sigma \textbf{E} + 2 \pi i f \varepsilon \textbf{E}) = 0</math> </equation> <br />
<br />
Dwa wyrażenia w nawiasie odpowiadają za efekty opornościowe i pojemnościowe w ośrodku materialnym, tzn. efekty związane z ładunkiem swobodnym i efekty związane z ładunkami związanymi w błonie komórkowej. Oznacza to, że efekty pojemnościowe możemy zaniedbać gdy<br />
<equation id="eq:Appendix B.4.3"><math>\frac {2 \pi f \varepsilon(f)} {\sigma(f)} \ll 1</math> </equation> <br />
<br />
Gdy w obszarze ''i'' oraz ''j'' nie występują źródła, na mocy równania (<xr id="eq:Appendix B.1.1"></xr>) i równania potencjału skalarnego (równanie <xr id="eq:Scalar potential"></xr>), podstawowe równania elektrofizjologii redukują się do:<br />
<equation id="eq:Equation 4.5"><math>\nabla^2 \Phi_i= 0</math> </equation> <br />
<equation id="eq:Equation 4.6"><math>\nabla^2\left(\sigma_j \Phi_j + \varepsilon_j \frac {\partial \Phi_j}{\partial t}\right) = 0</math> </equation> <br />
<br />
równanie (<xr id="eq:Equation 4.5"></xr>) odnosi się do sytuacji, w której można zaniedbać efekty pojemnościowe (np. błony komórkowej) i nosi nazwę równania Laplace’a. Czasem przybliżenie to nazywa się również przybliżeniem quasi-statycznym, gdyż stosuje się dla pól oscylujących z niskim częstościami. Równanie to stosuje się do wszystkich zagadnień w skali makroskopowej. Równanie (<xr id="eq:Equation 4.6"></xr>) stosuje się do błon komórkowych i pól w skali mikro. Równania (<xr id="eq:Equation 4.5"></xr>) i (<xr id="eq:Equation 4.6"></xr>) mają nieskończenie wiele rozwiązań. Aby rozwiązanie w każdym obszarze było jednoznaczne należy zastosować warunki brzegowe na granicy ośrodków oznaczonych symbolami ''m'' i ''n'':<br />
<br />
<equation id="eq:Equation 4.7"><math>\sigma_m \frac {\partial \Phi_m}{\partial u} = \sigma_n \frac {\partial \Phi_n}{\partial u} </math> </equation> <br />
<br />
<equation id="eq:Equation 4.8"><math>\frac {\partial \Phi_m}{\partial w} = \frac {\partial \Phi_n}{\partial w} </math> </equation> <br />
<br />
Warunki brzegowe są wyrażone we współrzędnej ''u'', mającej wszędzie kierunek normalny do granicy między ośrodkami i dwóch współrzędnych stycznych ''w''<sub>1</sub> i ''w''<sub>2</sub>. Pierwszy z warunków określa fizyczne wymaganie by składowa normalna gęstości prądu była ciągła na granicy ośrodków. Warunek ten wynika z zasady zachowania ładunku. Drugi warunek brzegowy określa, że składowa styczna pola elektrycznego musi być ciągła na granicy ośrodków. Warunek ten wynika z drugiego prawa Maxwella. Stosując pierwszy z warunków brzegowych do granicy głowa (''m'')–powietrze (''n'') i przyjmując, że przewodnictwo powietrza wynosi zero, dostajemy:<br />
<br />
<equation id="eq:Equation 4.9"><math>\frac {\partial \Phi_m}{\partial u} = 0 </math> </equation> <br />
<br />
Oznacza to, że pole magnetyczne, elektryczne oraz ich potencjały pochodzące od źródeł w mózgu, rozchodzą się w przestrzeni otaczającej głowę, lecz prąd jest ograniczony do jej wnętrza (składowa normalna prądu wynosi zero).<br />
<br />
==Źródła prądowe w mózgu==<br />
Tzw. problem wprost w EEG polega na obliczeniu potencjału na czaszce na podstawie źródeł prądowych. Równania (<xr id="eq:Equation 4.5"></xr>, <xr id="eq:Equation 4.6"></xr>) w pełni opisują szukany potencjał jednakże potrzebna jest modyfikacja. Wersja niezmodyfikowana wymaga znajomości potencjału i jego pochodnych normalnych na granicy ośrodków, co jest skomplikowane w skali komórkowej. Ponieważ jednak składowa normalna potencjału jest proporcjonalna do gęstości prądu w przewodniku, możemy zastąpić warunki brzegowe na granicy ośrodków poprzez odpowiednie źródła prądowe. <br />
Na początku rozważmy prąd błonowy pojawiający się w wyniku aktywacji pojedynczej synapsy. <br />
[[Grafika:Synaptic_action_currents.jpg|300px|thumb|right|<figure id="fig:Synaptic_action_currents"></figure>Prądy błonowe powstające w wyniku hamującej akcji synaptycznej. Potencjał czynnościowy dochodzący do zakończenia włókna presynaptycznego powoduje uwolnienie neuroprzekaźnika z kolbki synaptycznej, co prowadzi do zmiany przewodnictwa błony postsynaptycznej dla wybranych jonów. W wyniku otwarcia kanałów jonowych, powstaje lokalne źródło prądowe w okolicy synapsy oraz zlew prądowy rozproszony wzdłuż dalszych obszarów błony, tak by spełnione było prawo zachowania ładunku. ]]<br />
W stanie spoczynku, potencjał wewnątrz komórki wynosi ok. –65 mV względem potencjału na zewnątrz. Jeżeli synapsa jest pobudzająca, efektem jej aktywacji będzie zwiększenie przepuszczalności dla dodatnio naładowanych jonów, które zaczną napływać do komórki. Zmiana potencjału błonowego w wyniku akcji synaptycznej nazywana jest pobudzającym potencjałem postsynaptycznym lub EPSP (od ang. ''excitatory postsynaptic potential''). EPSP zmniejsza wartość różnicy potencjału w komórce i podnosi jej wewnątrzkomórkowy potencjał w kierunku odpalenia jej własnego potencjału czynnościowego, przy różnicy potencjałów w poprzek błony ok. –40 mV. Błona w bezpośredniej okolicy synapsy zachowuje się jak zlew prądowy (źródło ujemne) gdyż dodatnio naładowane jony wpływają do wewnątrz. Prąd płynie w przestrzeni wewnątrzkomórkowej i wypływa z komórki w dalszych, rozproszonych obszarach, tak aby zamknąć linie prądu. Całkowity prąd dokomórkowy musi być równy całkowitemu prądowi wypływającemu z komórki, co wynika z zasady zachowania ładunku. Jeżeli synapsa jest hamująca, zmiana potencjału błonowego w wyniku akcji synaptycznej nazywana jest hamującym potencjałem postsynaptycznym lub IPSP (od ang. inhibitory postsynaptic potential). Ma on odwrotne działanie w stosunku do EPSP i zmniejsza prawdopodobieństwo generacji potencjału czynnościowego. IPSP generuje powstanie lokalnego źródła prądu, któremu musi towarzyszyć odpowiedni zlew prądowy rozproszony wzdłuż bardziej odległych obszarów błony (<xr id="fig:Synaptic_action_currents">rys. %i</xr>). Potencjał zewnątrzkomórkowy powstający w wyniku akcji synaptycznej zależy od pełnego rozkładu źródeł i zlewów w błonie s('''r''', ''t''), a nie tylko od lokalnego prądu płynącego w otoczeniu synapsy. W wyniku złożonej geometrii neuronów, geometria rozkładu prądów płynących przez błonę może być skomplikowana, a potencjał zewnątrzkomórkowy trudny do policzenia. Jednakże w zagadnieniach EEG, możemy obejść wiele problemów ze złożonością pojedynczych neuronów poprzez zmianę skali, w której rozpatrujemy generatory prądów. W tym celu zdefiniujmy efektywny prądowy moment dipolowy dla każdej objętości tkanki. Prądowy moment dipolowy na jednostkę objętości tkanki kory mózgowej może być uważany za korowe źródło generujące pole magnetyczne i elektryczne na powierzchni czaszki. Kluczem do zrozumienia tego upraszczającego założenia jest fakt, że pojedyncza komórka kory mózgowej dostaje ok. 10<sup>4</sup>-10<sup>5</sup> wejść synaptycznych, a pod każdym milimetrem kwadratowym powierzchni kory znajduje się ok. 10<sup>5</sup> neuronów. Potencjał zewnątrzkomórkowy mierzony przez małą elektrodę z takiego obszaru będzie bardzo skomplikowany i będzie bardzo czuły na zmianę położenia elektrody. Jednakże w odległościach dużych w porównaniu z charakterystyczną odległością pomiędzy źródłami i zlewami, potencjał generowany przez źródła i zlewy w kolumnie będzie przypominał potencjał dipola. Dla wielu kolumn wykazujących aktywność synaptyczną, potencjał na czaszce będzie ważoną sumą dipolowych przyczynków od poszczególnych kolumn. W komórce piramidowej, charakterystyczna odległość pomiędzy źródłem a zlewem jest rzędu paru milimetrów, podczas gdy odległość do najbliższych obszarów na czaszce wynosi ok. 1-1,5 cm. Tak więc przybliżenie dipolowe dla źródeł w kolumnach korowych jest spełnione w zagadnieniach EEG.<br />
<br />
==Bezpośrednie zastosowanie makroskopowych źródeł prądu==<br />
We wszystkich następujących zagadnieniach będziemy zakładać, że ośrodek jest czysto przewodzący i nie wykazuje efektów pojemnościowych. W takim ośrodku, ładunek nie jest nigdzie gromadzony, gęstość ładunku jest stała, a równanie zachowania ładunku można zapisać: <br />
<br />
<equation id="eq:Equation 4.10"><math>\nabla \textbf{J} = 0</math> </equation> <br />
<br />
Korzystne okazuje się wprowadzenie pojęcia makroskopowej gęstości prądu źródeł '''J'''''<sub>s</sub>'', która pozwala zapisać prawo Ohma następująco:<br />
<br />
<equation id="eq:Equation 4.11"><math>\textbf{J} = \sigma \textbf{E} + \textbf{J}_{s} </math> </equation> <br />
<br />
Oznacza to, że prąd całkowity w ośrodku przewodzącym składa się prądu omowego &sigma;'''E''' oraz prądu źródłowego wypływającego z granicy między ośrodkami np. prąd wypływający przez błonę komórkową. Wstawiając (<xr id="eq:Equation 4.11"></xr>) do (<xr id="eq:Equation 4.10"></xr>) i korzystając z definicji potencjału elektrycznego dostajemy:<br />
<br />
<equation id="eq:Equation 4.12"><math>\nabla \cdot [\sigma (\textbf{r}) \nabla \Phi ]= -s(\textbf{r}, t) </math> </equation> <br />
<br />
gdzie objętościowy prąd źródłowy jest zdefiniowany jako<br />
<br />
<equation id="eq:Equation 4.13"><math>s(\textbf{r}, t) \equiv -\nabla \textbf{J}_s(\textbf{r}, t) </math> </equation> <br />
<br />
[[Grafika:Volume_current_sources.jpg|400px|thumb|right|<figure id="fig:Current_sources"></figure>Potencjał wewnątrz przewodnika oznaczonego zaokrąglonym prostokątem jest określony równaniem Laplace'a (<xr id="eq:Equation 4.5"></xr>). Jednoznaczne rozwiązanie tego równania wymaga znajomości potencjału lub normalnej pochodnej potencjału na powierzchniach granicznych przewodnika. Zamiast podawać warunki brzegowe na granicach przewodnika, możemy podać źródła prądowe s('''r''', ''t'') występujące na tych powierzchniach. W tej sytuacji jednoznaczne rozwiązanie dla potencjału wewnątrz przewodnika jest dane równaniem Poissona (<xr id="eq:Equation 4.12"></xr>). Obszary zaznaczone kolorem szarym są źródłami prądu, pozostałe (białe) obszary są bezźródłowe.]]<br />
<br />
Przewodnictwo &sigma;(''r'') (w S/mm lub S/cm) w ogólności zależy od położenia i dlatego znajduje się wewnątrz operatora &nabla;. Gęstość prądu źródłowego s('''r''', ''t'') ma wymiar prądu na jednostkę objętości &mu;A/mm<sup>2</sup>. Jest to prąd generowany w jednostce objętości. Może być również interpretowany jako objętościowe źródło potencjału generowanego w ośrodku makroskopowym. Rozumowanie stojące za wprowadzeniem prądu źródłowego jest następujące. Dowolny obszar tkanki możemy podzielić tak, że obszary generacji prądu znajdują się pewnych podobszarach oznaczonych kolorem szarym na <xr id="fig:Current_sources">rys. %i</xr>. W pozostałych obszarach (zaznaczonych kolorem białym) potencjał jest określony równaniem Laplace’a (<xr id="eq:Equation 4.5"></xr>) w ośrodku jednorodnym i (<xr id="eq:Equation 4.12"></xr>) w ośrodku niejednorodnym, kładąc s('''r''', ''t'') równe zero. Jednakże jednoznaczne rozwiązanie wymaga by potencjał lub składowa normalna potencjału była określona na całej granicy ośrodków. W formalizmie równania Poissona (<xr id="eq:Equation 4.12"></xr>) zastąpiliśmy warunki brzegowe poprzez prąd objętościowy s('''r''', ''t''). Ujemny znak w równaniu (<xr id="eq:Equation 4.12"></xr>) jest spójny z prądem dodatnim wpływającym do bezźródłowego (białego) obszaru. Inna zaletą tego podejścia jest fakt, że w ośrodku czysto przewodzącym czasowa zależność potencjału &Phi;('''r''', ''t'') jest identyczna z czasową zależnością źródła. Pojedyncze oscylujące źródło s('''r''', ''t'') &sim; sin(2&pi;''ft'') powoduje oscylacje potencjału z tą samą częstością. Jednakże w mózgu będzie zazwyczaj wiele źródeł oscylujących z różnymi częstościami i fazami. Potencjał na czaszce mierzony w EEG będzie liniową superpozycją przyczynków od pojedynczych obszarów źródeł z różnymi wagami zależnymi od własności przewodnictwa ośrodka i odległości pomiędzy źródłami i miejscami pomiaru potencjału na czaszce.<br />
Przeprowadzone tutaj operacje matematyczne mogą się wydawać nieco sztuczne, okazują się jednak bardzo wygodne w zrozumieniu problemów związanych z generacją potencjałów w tkance nerwowej. Porównajmy wzór na potencjał w przewodniku pochodzący od obszaru źródła prądowego s('''r''', ''t'') (<xr id="eq:Equation 4.12"></xr>) ze wzorem na potencjał w dielektryku pochodzący od obszaru źródła z pewną gęstością swobodnego ładunku &rho;('''r''', ''t''). Równanie na potencjał w dielektryku otrzymamy poprzez połączenie równań (<xr id="eq:Max I"></xr>), (<xr id="eq:dielectric"></xr>) i (<xr id="eq:Scalar potential"></xr>). Prowadzi to do równania Poissona w dielektryku:<br />
<br />
<equation id="eq:Equation 4.14"><math>\nabla \cdot [\varepsilon (\textbf{r}) \nabla \Phi(\textbf{r}, t)] = -\rho(\textbf{r}, t) </math> </equation> <br />
<br />
Oba równania (<xr id="eq:Equation 4.14"></xr>) i (<xr id="eq:Equation 4.12"></xr>) są równaniami Poissona lecz ze zmienionymi symbolami. Są one więc matematycznie równoważne lecz reprezentują inne fizycznie procesy. Swobodny ładunek makroskopowy w przewodniku w praktyce wynosi zero, tak więc równanie (<xr id="eq:Equation 4.14"></xr>) nie ma praktycznego zastosowania w elektrofizjologii. Jednakże w fizyce znanych jest wiele rozwiązań równania (<xr id="eq:Equation 4.14"></xr>) dla różnych rodzajów niejednorodności w dielektrykach. Aby zastosować znane z fizyki rozwiązania do przewodnika wystarczy w nich podstawić przewodnictwo &sigma;('''r''', ''t'') w miejsce przenikalności elektrycznej &epsilon;('''r''', ''t''), a źródła ładunku &rho;('''r''', ''t'') zamienić na źródła prądowe s('''r''', ''t''). Np. rozważmy specjalny przypadek ''N'' punktowych źródeł prądowych, co oznacza, że rozmiary (objętość) źródła jest dużo mniejsza niż odległość od elektrod pomiarowych. W nieskończonym, jednorodnym i czysto opornościowym przewodniku, potencjał na zewnątrz źródeł jest analogiczny do potencjału pochodzącego od ''N'' ładunków punktowych i wynosi:<br />
<br />
<equation id="eq:Equation 4.15"><math> \Phi(\textbf{r}, t) = \frac{1}{4 \pi \sigma}\sum_{n=1}^{N} \frac{I_n(t)}{R_n} </math> </equation> <br />
<br />
W typowych jednostkach stosowanych w zagadnieniach EEG, ''I<sub>n</sub>''(''t'') są jednobiegunowymi źródłami prądowymi (&mu;A) wypływającymi z ''n''-tego rejonu źródła do przewodnika o przewodnictwie &sigma; (1/(&Omega;cm)). ''R<sub>n</sub>'' są odległościami pomiędzy miejscem pomiaru a położeniem źródła. Np. potencjał w odległości 1 cm generowany przez źródło prądowe o natężeniu 4&pi; &mu;A w wyidealizowanej korze mózgowej o oporności &eta; = 1/&sigma; = 300 &Omega;cm, wynosi 300 mV. W ośrodku czysto opornościowym, zależność czasowa potencjału jest dana przez sumę ważoną wszystkich źródeł. W ośrodku z własnościami pojemnościowymi wystąpią przesunięcia fazowe pomiędzy źródłami i potencjałem. Gdy zaniedbamy efekty pojemnościowe, otrzymamy ogólną metodę znajdowania potencjału na podstawie rozkładu źródeł prądowych w mózgu.<br />
<br />
==Źródła prądowe w ośrodku przewodzącym==<br />
Większość zjawisk obserwowanych w zapisie EEG może być zrozumiana na podstawie paru rodzajów źródeł. W szczególności jest to dipol prądowy, warstwa dipolowa i rozkład źródeł pochodzący od potencjału czynnościowego. Pole na czaszce, pochodzące od tych źródeł będzie oczywiście silnie zależeć od makroskopowych niejednorodności takich jak czaszka. My zajmiemy się uproszczoną sytuacją i rozważymy różne przykłady źródeł w nieskończonym, jednorodnym i izotropowym ośrodku przewodzącym. Przybliżenie to dostarczy nam ważnej intuicji na temat generatorów rzeczywistych sygnałów EEG. <br />
<br />
===Źródło jednobiegunowe===<br />
Potencjał pojedynczego źródła jednobiegunowego jest szczególnym przypadkiem rozwiązania (<xr id="eq:Equation 4.15"></xr>) i wynosi<br />
<br />
<equation id="eq:Equation 5.3"><math> \Phi(\textbf{r}, t) = \frac{I(t)}{4 \pi \sigma r} </math> </equation> <br />
<br />
Równanie (<xr id="eq:Equation 5.3"></xr>) można też otrzymać przeprowadzając proste rozumowanie. Otoczmy punktowe źródło sferą o promieniu ''r''. Ponieważ prąd całkowity jest zachowany, gęstość prądu na powierzchni sfery wynosi <br />
<equation id="eq:Current_sphere"><math> J(r,t) = \frac{I(t)}{4 \pi r^2} </math> </equation> <br />
<br />
w kierunku radialnym. Z prawa Ohma:<br />
<br />
<equation id="eq:Electric_field_Current_sphere"><math> E(r,t) = \frac{J(r,t)}{\sigma} = \frac{I(t)}{4 \pi \sigma r^2}</math> </equation> <br />
<br />
Stosując równanie potencjału skalarnego (<xr id="eq:Scalar potential"></xr>), dla składowej radialnej dostajemy: <br />
<br />
<equation id="eq:Electric_potential_Current_sphere"><math> -\nabla \Phi = -\frac{\partial \Phi}{\partial r} = \frac{I(t)}{4 \pi \sigma r^2} </math> </equation> <br />
<br />
<br />
Po scałkowaniu (<xr id="eq:Electric_potential_Current_sphere"></xr>) dostajemy równanie (<xr id="eq:Equation 5.3"></xr>). Z równania (<xr id="eq:Equation 5.3"></xr>) wynika, że potencjał w przewodniku staje się nieskończony jeśli odległość między źródłem a punktem pomiaru wynosi zero lub przewodnictwo ośrodka wynosi zero. Ta nie-fizyczna sytuacja wynika z dwóch założeń zrobionych przy wyprowadzaniu równania (<xr id="eq:Equation 5.3"></xr>). Po pierwsze, założyliśmy, że pomiar dokonywany jest punktowo lecz prawdziwe elektrody pomiarowe mają niezerowe rozmiary więc ''r'' nie może być zero. Po drugie, założyliśmy, że jesteśmy w stanie zapewnić stałe natężenie prądu niezależnie od przewodnictwa ośrodka. Jednakże gdy przewodnictwa ośrodka będzie malało, coraz większe napięcie z generatora będzie wymagane, by utrzymać stały prąd w źródle. W rzeczywistości, gdy przewodnictwo ośrodka będzie dążyć do zera, natężenie prądu ''I'' będzie również dążyło do zera, co zapewni skończoną wartość potencjału.<br />
<br />
===Dipol prądowy===<br />
<br />
Dipol prądowy składa się z punktowego źródła ''I'' i zlewu –''I'', oddzielonych o ''d''. Znaczenie dipola w elektrofizjologii jest większe niż jakakolwiek inna konfiguracja źródeł. Jest tak dlatego, że prawie każdy obszar zawierający źródło i zlew, oraz w którym całkowity prąd źródła i zlewu są równe (zasada zachowania prądu), będzie dawał przybliżone pole dipola w odległościach dużych w porównaniu z rozmiarami obszaru źródło-zlew. Np. pole dipola jest generowane w wyniku pobudzenia lub hamowania synaptycznego w neuronach, jak to zostało opisane w sekcji ''Źródła prądowe w mózgu''. Ścisłe wyrażenie na potencjał dipola jest to suma dwóch jednobiegunowch przyczynków o przeciwnej polaryzacji i odległościach odpowiednio ''r''<sub>1</sub>, ''r''<sub>2</sub> od punktu pomiaru:<br />
<br />
<equation id="eq:Dipole potential"><math> \Phi = \frac{I(t)}{4 \pi \sigma}\left(\frac{1}{r_1} - \frac{1}{r_2}\right) </math> </equation> <br />
<br />
Jednakże dużo wygodniej wyrazić potencjał dipola za pomocą jednej współrzędnej radialnej ''r'', mierzonej od środka odcinka łączącego ładunki. W odległościach dużo większych od ''d'', pole dipola można przybliżyć następująco:<br />
<br />
<equation id="eq:Dipole_potential_approx"><math> \Phi = \frac{I d \cos \Theta}{4 \pi \sigma r^2} </math> </equation> <br />
dla ''r'' ≫ ''d''. &Theta; jest kątem pomiędzy osią dipola i wektorem '''r''' wskazującym punkt pomiaru. <br />
Rozważmy lokalny przepływ prądu pomiędzy III i VI warstwą kory mózgowej. Odległość między biegunami prądu wynosi wtedy ''d'' ~ 1 mm. Załóżmy prądowe źródło o natężeniu ''I'' = 10 &mu;A i nieskończony jednorodny ośrodek o oporności &eta; = 1/&sigma; = 300 &Omega;cm odpowiadającej korze mózgowej. Licząc potencjał (względem nieskończości) wzdłuż osi dipola (&Theta; = 0), możemy zastosować (<xr id="eq:Dipole_potential_approx"></xr>) również w pobliżu źródeł. Wstawiając dane dostajemy:<br />
<br />
:&Phi;(''r'', 0) &asymp; 464 &mu;V dla ''r'' = 2,5 mm (na powierzchni kory)<br />
:&Phi;(''r'', 0) &asymp; 12 &mu;V dla ''r'' = 1,5 cm (na czaszce)<br />
<br />
Powyższe oszacowania nie biorą pod uwagę wpływu warstw płynu mózgowo-rdzeniowego, czaszki i skóry na głowie i powietrza nad głową. Szacuje się, że wpływ tych warstw o różnym przewodnictwie zmniejsza potencjał pochodzący od dipola znajdującego się w powierzchownych warstwach kory, a mierzonego na czaszce do ok. 1/4 wartości otrzymanej w jednorodnym modelu kory. Te zgrubne oszacowania pozwalają nam przewidzieć stosunek potencjału mierzonego na czaszce do potencjału mierzonego na powierzchni kory. Dla pojedynczego źródła korowego stosunek ten wynosi 464/(12/4), a więc:<br />
<br />
:Potencjał na korze/potencjał na czaszce ~ 100 do 200<br />
<br />
Średnie amplitudy spontanicznego EEG na korze są zazwyczaj 2 do 5 razy większe od potencjałów mierzonych na czaszce (Cooper et al., 1965). Brak zgodności naszego oszacowania z doświadczeniem sugeruje, że zdecydowana większość zjawisk w EEG jest generowana nie przez pojedyncze dipole lecz przez źródła o znacznie większych rozmiarach np. przez warstwy dipolowe. Z drugiej strony, niektóre iglice epileptyczne (ang. ''epileptic spikes'') i potencjały wywołane (ang. ''evoked potentials'') w pierwszorzędowej korze sensorycznej można z powodzeniem modelować jako pojedynczy dipol lub parę izolowanych dipoli.<br />
<br />
===Źródło kwadrupolowe===<br />
Rozróżniamy dwie konfiguracje prowadzące do źródła kwadrupolowego. Kwadrupol liniowy składa się z dwóch źródeł +''I''/2 i zlewu –''I'' leżących wzdłuż jednej prostej, oddzielonych od siebie o ''d''. Kwadrupol dwuwymiarowy składa się z dwóch identycznych dipoli, umieszczonych równolegle do siebie, o przeciwnej orientacji. Kwadrupol liniowy ma zastosowanie w elektrofizjologii gdyż wykazuje podobieństwo do trójfazowego rozkładu źródeł we włóknie nerwowym podczas potencjału czynnościowego. Potencjał kwadrupola w dowolnym miejscu ośrodka przewodzącego wynika bezpośrednio ze wzoru (<xr id="eq:Equation 5.3"></xr>) na potencjał pojedynczego źródła jednobiegunowego<br />
<br />
<equation id="eq:Quadrupole_potential"><math> \Phi = \frac{I}{4 \pi \sigma}\left(\frac{1}{2r_1} - \frac{1}{r_2} + \frac{1}{2r_3}\right) </math> </equation> <br />
<br />
Trzy wartości ''r'' odpowiadają trzem odległościom pomiędzy źródłami i zlewami, a punktem pomiaru. W średnich lub dużych odległościach, potencjał może być wyrażony we współrzędnych sferycznych (''r'', &theta;, &phi;) jako<br />
<br />
<equation id="eq:Quadrupole_potential_approx"><math> \Phi \cong \frac{I d^2}{32 \pi \sigma r^3}(3 \cos^2 \theta - 1) </math> </equation> <br />
<br />
Potencjał nie zależy od współrzędnej &phi;.<br />
<br />
Podczas generacji potencjału czynnościowego następuje wpływ dodatniego prądu jonów Na<sup>+</sup> do wnętrza komórki. Prądowe źródło na pewnym obszarze błony komórkowej musi mieć odpowiadające mu zlewy prądowe, które znajdują się w obszarach po obu stronach źródła. W ten sposób powstaje konfiguracja źródło-zlew przypominająca kwadrupol liniowy. Ponieważ potencjał kwadrupola zanika jak 1/''r''<sup>3</sup> czyli szybciej niż potencjał dipola (1/''r''<sup>2</sup>), potencjały czynnościowe mają znikomy wpływ na sygnał EEG. Synchronicznie występujące potencjały czynnościowe (ang. compound action potentials) mogą jednak być mierzalne. Istnieją podstawy by sądzić (Jewett, 1970), że potencjały czynnościowe biegnące we nerwie słuchowym są przynajmniej częściowo źródłem słuchowych potencjałów wywołanych z pnia mózgu (BAER od ang. brainstem auditory evoked response).<br />
<br />
===Warstwa dipolowa &mdash; najważniejsze źródło sygnału EEG===<br />
<br />
Około 65 do 75% neuronów korowych u wszystkich gatunków ssaków jest ustawionych prostopadle do powierzchni kory (Scholl, 1956; Bok, 1959). Neurony korowe mają dużą liczbę wzajemnych połączeń powodujących synchronizacje ich aktywności. Istnieją więc zarówno anatomiczne, jak i fizjologiczne podstawy by uznać warstwę dipolową tworzoną przez równoległe, synchronicznie działające komórki, za generator potencjałów korowych. Synchronizacja generatorów odgrywa tutaj kluczową rolę. Rozważmy na początku dwa dipole, których prądy fluktuują z częstościami <math>f_A</math> i <math>f_B</math>. Może to odpowiadać dwóm komórkom, dostającym zarówno wejścia pobudzające, jak i hamujące (<xr id="fig:Two_pyramidal_cells">rys. %i</xr>). Potencjał mierzony przez elektrodę w punkcie ''P'', otrzymamy na podstawie (<xr id="eq:Equation 4.15"></xr>):<br />
<br />
<equation id="eq:Equation 3.22"><math> \Phi(t) = \frac{1}{4 \pi \sigma}\left[ \frac{I_A}{R_1} \cos(2\pi f_A t + \alpha_A) - \frac{I_A}{R_2} \cos(2\pi f_A t + \alpha_A) + \frac{I_B}{R_3} \cos(2\pi f_B t + \alpha_B) - \frac{I_B}{R_4} \cos(2\pi f_B t + \alpha_B) \right]</math> </equation> <br />
<br />
''I<sub>A</sub>'' oraz ''I<sub>B</sub>'' są maksymalnymi wartościami prądu w każdym z dipoli. Dodatkowo, zakładamy, że cały prąd wypływający ze źródła wpływa do zlewu w tym samym dipolu, co jest spełnione gdy odległość między dipolami ''L''jest znacznie większa niż odległość pomiędzy efektywnymi biegunami ''d''. &alpha;''<sub>A</sub>'' i <math>\alpha_B</math> są kątami fazowymi. Dla większej ilości źródeł, w wyrażeniu (<xr id="eq:Equation 3.22"></xr>) pojawią się analogiczne człony. <br />
<br />
[[Grafika:Two_pyramidal_cells.jpg|400px|thumb|right|<figure id="fig:Two_pyramidal_cells"></figure>Dwie komórki piramidalne A i B pobudzane synaptycznie, są przedstawione w wyidealizowanej formie, jako dipole. Potencjał w punkcie ''P'' jest sumą przyczynków pochodzących od obu zlewów (-) i obu źródeł (+) prądu. Odległość między dipolami wynosi ''L'', a odległość pomiędzy efektywnymi biegunami dipoli wynosi ''d''.]]<br />
<br />
Rozważmy wpływ wielu dipoli o podobnej sile (<math>I_A = I_B = I_C</math>, itd) i podobnych częstościach (<math>f_A = f_B = f_C</math>, itd) na średni potencjał <math>|\bar{\Phi}|</math>. Potencjał będzie oczywiście zależał od wszystkich odległości ''R''<sub>1</sub>, ''R''<sub>2</sub>, itd., możemy jednak sformułować pewne ogólne wnioski. <br />
:a. Gdy generatory są ze sobą w fazie (<math>\alpha_A </math> = <math>\alpha_B </math> = <math>\alpha_C </math> , itd), a dipole ustawione równolegle do siebie, wyrażenia we wzorze (<xr id="eq:Equation 3.22"></xr>) dodają się i dla ''m'' dipoli, uśredniony po czasie potencjał będzie proporcjonalny do ilości wszystkich ''m'' generatorów w otoczeniu elektrody, <br />
:<equation id="eq:Equation 3.23"><math> |\bar{\Phi}| \sim m</math> </equation><br />
:Oczywiście, generatory znajdujące się najbliżej elektrody, będą miały największy wpływ na potencjał, lecz im więcej generatorów będzie aktywnych w losowych odległościach od punktu pomiaru, wzór (<xr id="eq:Equation 3.23"></xr>) będzie stanowić tym lepsze przybliżenie. <br />
<br />
:b. Jeśli generatory mają losową orientację, tak że prądy ''I'' w (<xr id="eq:Equation 3.22"></xr>) będą miały losowe znaki lub jeśli losowe będą fazy generatorów, potencjał będzie dużo słabiej zależał od liczby generatorów. Będzie on wynikiem statycznej fluktuacji. Wg. Nunez (1981), można pokazać, że ''m'' członów w wyrażeniu (<xr id="eq:Equation 3.22"></xr>) sumuje się dając średni potencjał, który dla dużych ''m'' można oszacować jako:<br />
:<equation id="eq:Equation 3.24"><math> |\bar{\Phi}| \sim \sqrt{m}</math> </equation><br />
<br />
<br />
Zastosujmy teraz powyższe rozważania do zapisu rejestrowanego elektrodą umieszczoną w pobliżu generatorów. Jeśli elektroda znajduje się wystarczająco blisko źródła prądowego, tak że jeden z ''R''s w (<xr id="eq:Equation 3.22"></xr>) jest bardzo mały, mierzony potencjał będzie stosunkowo duży, bez względu na fazowe relacje pomiędzy źródłem lokalnym i innymi źródłami w otaczającej tkance. Źródła odległe również mogą dawać wkład do mierzonego potencjału. Ich wkład może być mniejszy lub większy od wkładu źródła lokalnego. Źródła odległe będą zachowywały się głównie jak dipole prądowe. Tak więc potencjał mierzony przez elektrodę może być wyrażony następującym przybliżonym wzorem.<br />
<br />
<equation id="eq:Equation 3.25"><math> |\bar{\Phi}| = \frac{1}{8 \pi \sigma}\left[\sum_{i =1}^l\frac{I_{i}}{R_{i}} + m \frac{I_{S}d}{R_{S}^2} + \sqrt{n} \frac{I_{A}d}{R_{A}^2} \right]</math> </equation> <br />
<br />
<br />
Indeksy ''i'', ''S'', oraz ''A'' odnoszą się odpowiednio do źródeł lokalnych, źródeł odległych synchronicznych i źródeł odległych asynchronicznych. ''I''s są prądami efektywnymi, które mogą być mniejsze niż prąd całkowity, w zależności od orientacji odległych synchronicznych źródeł względem elektrody. ''d'' jest odległością pomiędzy efektywnymi biegunami dipoli. ''l'', ''m'' i ''n'' są liczbą źródeł lokalnych, odległych synchronicznych i odległych asynchronicznych, które znajdują się odpowiednio w średnich odległościach ''R''<math>_{i}</math>, ''R''<math>_S</math>, ''R''<math>_A</math>. Należy pamiętać, że (<xr id="eq:Equation 3.25"></xr>) jest idealizacją, gdyż nie wszystkie generatory dają się zaklasyfikować do poszczególnych kategorii, jednakże wzór ten może dać ogólny pogląd na generacje potencjałów w mózgu, a w szczególności potencjałów mierzonych na czaszce czyli EEG. W tym przypadku (EEG) nie ma źródeł lokalnych. Jeśli generatory są podobne ''I<sub>S</sub>'' &asymp; ''I<sub>A</sub>'' oraz generatory synchroniczne i asynchroniczne są w podobnej odległości ''R<sub>S</sub>'' &asymp; ''R<sub>A</sub>'', względny przyczynek od generatorów synchronicznych względem asynchronicznych wynosi: <br />
<equation id="eq:Ratio_generators"><math> \frac{m}{\sqrt{n}}</math> </equation> <br />
<br />
Na podstawie zależności (<xr id="eq:Ratio_generators"></xr>) możemy przeprowadzić następujące rozumowanie. Elektroda umieszczona na czaszce mierzy aktywność ok. 10<math>^8</math> neuronów znajdujących się w paru cm<math>^2</math> kory, Załóżmy, że prawie wszystkie neurony są aktywne lecz tylko 1% (10<math>^6</math>) z nich jest ustawiony równolegle i działa synchronicznie. Przyczynek od synchronicznej frakcji neuronów do potencjału mierzonego na czaszce wynosi:<br />
<equation id="eq:Ratio_generators_electrode"><math> \frac{10^6}{\sqrt{10^8 - 10^6}} \cong 100</math> </equation> <br />
Jest on więc 100 razy większy niż przyczynek od pozostałych 99% neuronów (Elul, 1972). Pokazuje to, że powierzchniowe EEG pochodzi głównie od synchronicznej aktywności równolegle ustawionych neuronów, a zmiana amplitudy sygnału wraz ze stanem fizjologicznym, wiąże się ze zmianą liczby synchronicznie działających komórek. <br />
Wzór (<xr id="eq:Equation 3.25"></xr>) sugeruje, że potencjał od źródeł odległych zanika z odległością jak 1/''R''<math>^2</math>. Warto zauważyć, że dla warstw dipolowych bardzo dużych rozmiarów, zanik ten może być jeszcze wolniejszy. Np. dla nieskończonej warstwy dipolowej potencjał nad (lub pod warstwą) dipolową jest stały i nie zmienia się z odległością. Oznacza to, że dla małych odległości od warstwy, w porównaniu z jej rozmiarami, zanik potencjału będzie niewielki, a im większa warstwa tym zanik potencjału wolniejszy. W przypadku dużych warstw dipolowych zanik potencjału na czaszce względem potencjału na korze jest nieznaczny. Eksperymentalnie obserwowany stosunek potencjału na korze do potencjału na czaszce jest, w większości spontanicznych zapisów EEG, pomiędzy 2 i 5 (Cooper et al., 1965). Po uwzględnieniu niejednorodności takich jak czaszka, płyn mózgowo-rdzeniowy i powietrzne nad głową, oznacza to, że korowe źródła muszą tworzyć warstwy dipolowe o rozmiarach znacznie większych niż odległość pomiędzy czaszką a korą. Mają więc one rozmiary rzędu paru cm<math>^2</math>.<br />
<br />
==Podsumowanie==<br />
Potencjały w ośrodku jednorodnym pochodzące od źródeł i zlewów prądowych zostały otrzymane na podstawie ogólnego równania (<xr id="eq:Equation 4.15"></xr>). Fizjologiczne źródła prądowe, są generowane w błonach komórkowych w wyniku transmisji synaptycznej lub generacji potencjału czynnościowego. Różne konfiguracje źródeł i zlewów mogą generować potencjały o bardzo różnych własnościach przestrzennych. Zanik potencjału wraz z odległością od źródeł-zlewów może być bardzo słaby (tzw. pola dalekie lub długozasięgowe), jak w przypadku warstwy dipolowej. Zanik ten może też być silny np. w przypadku koncentrycznie ustawionych neuronów, tak jak w przypadku kwadrupola (tzw. pola bliskie lub krótkozasięgowe). Znajomość potencjałów generowanych w wyidealizowanym, nieskończonym, jednorodnym ośrodku dostarcza przydatnych oszacowań na temat różnych fizjologicznych procesów np. generacji potencjałów czaszkowych EEG. Na koniec należy zauważyć, że wszystkie wyprowadzone tutaj wzory dotyczyły potencjału w pewnym punkcie. W rzeczywistości, mierzone potencjały są potencjałami uśrednionymi po całej objętości elektrody. Potencjał mierzony przez sferyczną elektrodę <math>\Phi_E</math> o promieniu ''R'' jest związany z teoretycznym potencjałem punktowym <math>\Phi</math> poprzez całkę objętościową: <br />
<br />
<equation id="eq:Volume_average_potential"><math>\Phi_E(r,t,R) = \frac{3}{4 \pi R^3}\iiint\limits_{\mathrm{Vol}(R)} \Phi(r', t)\, d^3r'\ </math> </equation> <br />
<br />
Ze względu na skomplikowaną anatomię kory, zachowanie potencjału <math>\Phi_E</math> wewnątrz mózgu (zapisy śródmózgowe) będzie bardzo silnie zależało od parametru skali ''R''. W przeciwieństwie do tego, potencjały czaszkowe są już silnie uśrednione przestrzennie w wyniku przejścia przez płyn mózgowo-rdzeniowy, czaszkę i skórę. Powoduje to, że rozmiar elektrody nie ma prawie wpływu na zapis czynności EEG.<br />
<br />
==Literatura==<br />
<br />
Bok S.T., Histonomy of the Cerebral Cortex, Elsevier, New York, 1959.<br />
<br />
Cooper R., Winter A.L., Crow H.J., Walter W.G. Comparison of subcortical, cortical and scalp activity using chronically indwelling electrodes in man. Electroencephalogr Clin Neurophysiol. 18:217-228, 1965.<br />
<br />
[http://books.google.pl/books?id=Tvu7Z3QRZkAC&pg=PA227&lpg=PA227&dq=The+genesis+of+the+EEG&source=bl&ots=rEovH1QgTh&sig=9MJUiVz9lIEq3SbDVzs5iSjWNWc&hl=pl&ei=YKZFTJ6rDMyksAbx9uVk&sa=X&oi=book_result&ct=result&resnum=6&ved=0CDsQ6AEwBQ#v=onepage&q=The%20genesis%20of%20the%20EEG&f=false Elul R. The genesis of the EEG. Int Rev Neurobiol 15: 227-272, 1972.]<br />
<br />
Jewett D.L. Volume-conducted potentials in response to auditory stimuli as detected by averaging in the cat. Electroencephalogr. Clin. Neurophysiol. 28(6):609-618, 1970.<br />
<br />
Nunez P.L Electric Fields of the Brain. The Neurophysics of EEG. Oxford University Press, New York, NY, 1981 (First edition).<br />
<br />
Nunez P.L. Neocortical Dynamics and Human EEG Rhythms. Oxford University Press, New York, 1995.<br />
<br />
[http://books.google.pl/books?id=V1LuaISgSzgC&dq=%22Electric+Fields+of+the+Brain%22&printsec=frontcover&source=bn&hl=pl&ei=76ZFTKiCCJSmsAajgKGjAQ&sa=X&oi=book_result&ct=result&resnum=4&ved=0CDMQ6AEwAw#v=onepage&q&f=false Nunez P.L. Electric Fields of the Brain. The Neurophysics of EEG. Oxford University Press, New York, NY, 2006 (Second edition).]<br />
<br />
Scholl D.A. The organization of the Cerebral Cortex, Methuen, London, 1956.</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Elektroencefalografia/Biofizyczne_podstawy_generacji_sygna%C5%82%C3%B3w_EEG&diff=6227Elektroencefalografia/Biofizyczne podstawy generacji sygnałów EEG2016-12-15T13:43:20Z<p>Tspus: /* Warstwa dipolowa &mdash; najważniejsze źródło sygnału EEG */</p>
<hr />
<div><br />
W rozdziale tym poznamy mechanizmy neuronalne odpowiedzialne za powstawanie potencjałów na czaszce, mierzonych jako sygnały EEG. Rozdział ten jest opracowany w oparciu o Nunez (1981, 1995, 2006).<br />
<br />
==Własności tkanki nerwowej==<br />
Na początku zajmijmy się własnościami tkanki nerwowej, w której generowane są potencjały. Tkanka nerwowa składa się neuronów przekazujących impulsy nerwowe oraz komórek glejowych wspomagających działanie neuronów. W komórkach występuje płyn wewnątrzkomórkowy, a na zewnątrz, płyn zewnątrzkomórkowy. Płyn zewnątrz- i wewnątrzkomórkowy składa się z wody, białek oraz dodatnio i ujemnie naładowanych jonów. W płynie wewnątrzkomórkowym dominują jony K<sup>+</sup>, Mg<sup>2+</sup>, Na<sup>+</sup>, HCO<sub>3</sub><sup>–</sup>, izetionianu. W płynie zewnątrzkomórkowym głównym kationem są jony Na<sup>+</sup>, a anionem jony Cl<sup>–</sup>. Ze względu na występowanie jonów swobodnych, w tkance nerwowej mogą płynąć prądy jonowe, w których biorą udział zarówno dodatnie, jak i ujemne jony. W odróżnieniu od obwodów elektrycznych, w których prąd jest rozłożony równomiernie w całym przekroju poprzecznym elementów obwodu i można operować pojęciem prądu całkowitego, w tkance nerwowej wygodnie operuje się uogólnionym pojęciem tzw. gęstością prądu '''J'''. Gęstość prądu pochodzącego do wielu różnych jonów, można wyrazić jako sumę poszczególnych przyczynków od jonów mających gęstość ładunku &rho;''<sub>i</sub>'' i prędkość '''v'''''<sub>i</sub>'':<br />
<equation id="eq:gestosc pradu"><math>\textbf{J} = \sum_i {\rho}_i \textbf{v}_i</math> </equation> <br />
<br />
Gęstość ładunku jest równa wartości ładunku danego jonu pomnożonej przez liczbę wolnych jonów w elemencie objętości tkanki. Jednostką gęstości ładunku jest C/m<sup>3</sup>. '''v'''''<sub>i</sub>'' są to średnie prędkości jonów wyrażone w metrach na sekundę. Gęstość prądu jest to ilość prądu przepływająca przez jednostkowy przekrój poprzeczny, a jego jednostką jest C/(m<sup>2</sup>s) lub A/m<sup>2</sup>. W skali makroskopowej (np. w próbce materii zawierającej 10<sup>20</sup> lub więcej ładunków w ruchu), tkanka nerwowa spełnia prawo Ohma. Oznacza to liniową zależność pomiędzy gęstością prądu, a przyłożonym polem elektrycznym ('''E'''):<br />
<equation id="eq:prawo Ohma"><math>\textbf{J} = {\sigma} \textbf{E}</math> </equation> <br />
<br />
Stała proporcjonalności &sigma; jest nazywana przewodnictwem elektrycznym ośrodka i wyraża się w jednostkach 1/(&Omega;m) lub równoważnie w Siemens/m (S/m). W tkance biologicznej często wygodniej jest stosować jednostki 1/(&Omega;cm) lub 1/(&Omega;mm) i (S/mm) Oporność jest odwrotnością przewodnictwa i jest mierzona w &Omega;m. Tkanka mózgowa jest słabym przewodnikiem. Np. makroskopowa oporność kory mózgowej jest ok. milion razy większa od oporności miedzi. Na poziomie mikroskopowym, błony komórkowe wykazują zachowanie nieliniowe, odbiegające od prawa Ohma. Gdy potencjał błonowy (pole elektryczne wewnątrz komórki) wzrasta powyżej pewnej wartości progowej, błona staje nieliniowym przewodnikiem, co umożliwia generacje i propagacje impulsów nerwowych.<br />
<br />
==Ładunki w przewodnikach==<br />
<br />
Wykonajmy myślowy eksperyment polegający na umieszczeniu ładunku próbnego w przewodniku np. tkance biologicznej. Gdy umieścimy dodatnio naładowany ładunek w przewodniku, występują dwa oddzielne efekty. Efekt polaryzacji spowodowany reorganizacją ładunków w błonach komórkowych (własności dielektryczne tkanki) oraz efekt przewodnictwa spowodowany ruchem ładunków swobodnych w płynie zewnątrzkomórkowym. Ten drugi efekt spowoduje, że dodatni ładunek próbny będzie wkrótce otoczony chmurą ujemnych ładunków, które będą w dużym stopniu ekranować pole pochodzące od ładunku próbnego. Potencjał w punkcie '''r''', pochodzący od ładunku próbnego umieszczonego w elektrolicie w punkcie '''r'''<sub>1</sub> był wyprowadzony w połowie XX wieku na bazie rozważań statystycznych i wynosi:<br />
<br />
<equation id="eq:prawo_Debye"><math>\Phi(r) = \frac{q}{4 \pi \epsilon_{0} \kappa R} e^{-\frac{R}{R_D}}</math> </equation> <br />
<br />
''R<sub>D</sub>'' jest tzw. długością Debye'a, a &kappa; odpowiada za efekty polaryzacyjne. ''R'' = |'''r''' – '''r'''<sub>1</sub>|. Dla &kappa; = 1 i ''R'' ≪ ''R<sub>D</sub>'', dostajemy potencjał ładunku punktowego w próżni. Jednakże ''R<sub>D</sub>'' jest rzędu kilku angstremów (10<sup>–10</sup> m) w tkance biologicznej, co powoduje, ze eksponent we wzorze <br />
(<xr id="eq:prawo_Debye"></xr>) wynosi ok. 10<sup>–4000000</sup> w odległości ''R'' = 3 mm. Pokazuje to, że potencjał ładunku próbnego umieszczonego w tkance biologicznej jest zaniedbywalnie mały dla wszystkich makroskopowych odległości. Nie można więc powiedzieć, że potencjały w mózgu są spowodowane pewnym rozkładem określonym ładunku. Są one spowodowane nie tylko określonym rozkładem ładunku ale również wszystkimi ładunkami w ośrodku przewodzącym. W tkance biologicznej, źródła prądowe w błonach neuronalnych, a nie ładunki, są generatorami EEG.<br />
<br />
==Podstawowe równania==<br />
Wszystkie zjawiska elektryczne i magnetyczne w mózgu podlegają uniwersalnym prawom Maxwella: <br />
<equation id="eq:Max I"><math>\nabla \textbf{D} = \rho </math> </equation> <br />
<equation id="eq:Max II"><math>\nabla \times \textbf{E} = -\frac{\partial \textbf{B}}{\partial t}</math> </equation> <br />
<equation id="eq:Max III"><math>\nabla \textbf{B} = 0 </math> </equation> <br />
<equation id="eq:Max IV"><math>\nabla \times \textbf{H} = \textbf{J} + \frac{\partial \textbf{{D}}}{\partial t}</math> </equation> <br />
<br />
gdzie '''D''' — indukcja elektryczna , '''E''' — natężenie pola elektrycznego, '''B''' — indukcja magnetyczna, '''H''' — natężenie pola magnetycznego, &rho; — gęstość ładunku, '''J''' — gęstość prądu. W wielu materiałach, również w tkance nerwowej, pola '''D''' i '''B''' zależą liniowo od '''E''' i '''H''':<br />
<br />
<equation id="eq:dielectric"><math>\textbf{D} = \varepsilon \textbf{E} </math> </equation> <br />
<equation id="eq:magnetic"><math>\textbf{B} = \mu \textbf{H} </math> </equation> <br />
<br />
Gdzie: &epsilon; — przenikalność elektryczna, a &mu; — przenikalność magnetyczna ośrodka.<br />
<br />
Do opisu pól elektrycznych w tkance nerwowej stosuje się uproszczoną wersje równań Maxwella oraz równań opisujących liniowe własności ośrodka. Podstawowe równania liniowej elektrofizjologii można podsumować następująco: <br />
<equation id="eq:Conservation of charge"><math>\nabla \textbf{J} + \frac{\partial {\rho}}{\partial t} = 0 </math> </equation> <br />
<equation id="eq:Gauss' law"><math>\nabla \textbf{D} = \rho </math> </equation> <br />
<equation id="eq:Ohm's law"><math>\textbf{J} = {\sigma} \textbf{E}</math> </equation> <br />
<equation id="eq:Linear dielectric"><math>\textbf{D} = \varepsilon \textbf{E} </math> </equation> <br />
<equation id="eq:Scalar potential"><math>\textbf{E} = -\nabla \Phi </math> </equation> <br />
<br />
<br />
Zasada zachowania ładunku (równanie <xr id="eq:Conservation of charge"> %i</xr>) wynika bezpośrednio z 1 i 4 równania Maxwella (równania <xr id="eq:Max I"> %i</xr> i <xr id="eq:Max IV"> %i</xr>), oraz z tożsamości <br />
<equation id="eq:Tozsamosc"><math>\nabla (\nabla \times \textbf{A}) = 0 </math> </equation> <br />
<br />
Równanie potencjału skalarnego dla pola elektrycznego (równanie <xr id="eq:Scalar potential"> %i</xr>) jest spełnione w przybliżeniu wolnych oscylacji pól, co pozwala zaniedbać indukcję magnetyczną.<br />
<br />
==Warunki brzegowe w ośrodkach niejednorodnych ==<br />
Różne obszary mózgu mają różne przewodnictwa, tak więc w praktycznych zagadnieniach występują granice między ośrodkami. W skali makroskopowej, najbardziej oczywiste granice między ośrodkami dotyczą granicy pomiędzy słabo przewodzącą czaszką i powietrzem otaczającym głowę. W skali mikroskopowej mamy do czynienia z granicami tworzonymi przez błonę komórkową z ośrodkiem zarówno zewnętrznym jak i wewnętrznym. Potencjał elektryczny &Phi;('''r''', ''t'') będzie miał różne rozwiązania &Phi;''<sub>i</sub>''('''r''', ''t'') w obszarach ''i'' o przewodnictwie &sigma;''<sub>i</sub>''. Porównajmy najpierw efekty opornościowe i efekty pojemnościowe. Zastosujmy operator &nabla; do czwartego równania Maxwella (równanie <xr id="eq:Max IV"> %i</xr>) oraz skorzystajmy z tożsamości (<xr id="eq:Tozsamosc"></xr>). Dostajemy:<br />
<br />
<equation id="eq:Appendix B.1.1"><math>\nabla \left( \textbf{J} + \frac{\partial \textbf{{D}}}{\partial t} \right)=0</math> </equation> <br />
<br />
Rozważmy składową pola elektrycznego oscylującego z częstością ''f''<br />
<equation id="eq:Appendix B.1.2"><math>\textbf{E}(\textbf{r},t) = \textbf{E}_1(\textbf{r})\exp(2\pi i f t)</math> </equation> <br />
<br />
i wyraźmy równanie (<xr id="eq:Appendix B.1.1"></xr>) stosując prawo Ohma (<xr id="eq:Ohm's law"></xr>) i liniowe równanie dla dielektryka (<xr id="eq:Linear dielectric"></xr>):<br />
<br />
<equation id="eq:Appendix B.1.3"><math>\nabla (\sigma \textbf{E} + 2 \pi i f \varepsilon \textbf{E}) = 0</math> </equation> <br />
<br />
Dwa wyrażenia w nawiasie odpowiadają za efekty opornościowe i pojemnościowe w ośrodku materialnym, tzn. efekty związane z ładunkiem swobodnym i efekty związane z ładunkami związanymi w błonie komórkowej. Oznacza to, że efekty pojemnościowe możemy zaniedbać gdy<br />
<equation id="eq:Appendix B.4.3"><math>\frac {2 \pi f \varepsilon(f)} {\sigma(f)} \ll 1</math> </equation> <br />
<br />
Gdy w obszarze ''i'' oraz ''j'' nie występują źródła, na mocy równania (<xr id="eq:Appendix B.1.1"></xr>) i równania potencjału skalarnego (równanie <xr id="eq:Scalar potential"></xr>), podstawowe równania elektrofizjologii redukują się do:<br />
<equation id="eq:Equation 4.5"><math>\nabla^2 \Phi_i= 0</math> </equation> <br />
<equation id="eq:Equation 4.6"><math>\nabla^2\left(\sigma_j \Phi_j + \varepsilon_j \frac {\partial \Phi_j}{\partial t}\right) = 0</math> </equation> <br />
<br />
równanie (<xr id="eq:Equation 4.5"></xr>) odnosi się do sytuacji, w której można zaniedbać efekty pojemnościowe (np. błony komórkowej) i nosi nazwę równania Laplace’a. Czasem przybliżenie to nazywa się również przybliżeniem quasi-statycznym, gdyż stosuje się dla pól oscylujących z niskim częstościami. Równanie to stosuje się do wszystkich zagadnień w skali makroskopowej. Równanie (<xr id="eq:Equation 4.6"></xr>) stosuje się do błon komórkowych i pól w skali mikro. Równania (<xr id="eq:Equation 4.5"></xr>) i (<xr id="eq:Equation 4.6"></xr>) mają nieskończenie wiele rozwiązań. Aby rozwiązanie w każdym obszarze było jednoznaczne należy zastosować warunki brzegowe na granicy ośrodków oznaczonych symbolami ''m'' i ''n'':<br />
<br />
<equation id="eq:Equation 4.7"><math>\sigma_m \frac {\partial \Phi_m}{\partial u} = \sigma_n \frac {\partial \Phi_n}{\partial u} </math> </equation> <br />
<br />
<equation id="eq:Equation 4.8"><math>\frac {\partial \Phi_m}{\partial w} = \frac {\partial \Phi_n}{\partial w} </math> </equation> <br />
<br />
Warunki brzegowe są wyrażone we współrzędnej ''u'', mającej wszędzie kierunek normalny do granicy między ośrodkami i dwóch współrzędnych stycznych ''w''<sub>1</sub> i ''w''<sub>2</sub>. Pierwszy z warunków określa fizyczne wymaganie by składowa normalna gęstości prądu była ciągła na granicy ośrodków. Warunek ten wynika z zasady zachowania ładunku. Drugi warunek brzegowy określa, że składowa styczna pola elektrycznego musi być ciągła na granicy ośrodków. Warunek ten wynika z drugiego prawa Maxwella. Stosując pierwszy z warunków brzegowych do granicy głowa (''m'')–powietrze (''n'') i przyjmując, że przewodnictwo powietrza wynosi zero, dostajemy:<br />
<br />
<equation id="eq:Equation 4.9"><math>\frac {\partial \Phi_m}{\partial u} = 0 </math> </equation> <br />
<br />
Oznacza to, że pole magnetyczne, elektryczne oraz ich potencjały pochodzące od źródeł w mózgu, rozchodzą się w przestrzeni otaczającej głowę, lecz prąd jest ograniczony do jej wnętrza (składowa normalna prądu wynosi zero).<br />
<br />
==Źródła prądowe w mózgu==<br />
Tzw. problem wprost w EEG polega na obliczeniu potencjału na czaszce na podstawie źródeł prądowych. Równania (<xr id="eq:Equation 4.5"></xr>, <xr id="eq:Equation 4.6"></xr>) w pełni opisują szukany potencjał jednakże potrzebna jest modyfikacja. Wersja niezmodyfikowana wymaga znajomości potencjału i jego pochodnych normalnych na granicy ośrodków, co jest skomplikowane w skali komórkowej. Ponieważ jednak składowa normalna potencjału jest proporcjonalna do gęstości prądu w przewodniku, możemy zastąpić warunki brzegowe na granicy ośrodków poprzez odpowiednie źródła prądowe. <br />
Na początku rozważmy prąd błonowy pojawiający się w wyniku aktywacji pojedynczej synapsy. <br />
[[Grafika:Synaptic_action_currents.jpg|300px|thumb|right|<figure id="fig:Synaptic_action_currents"></figure>Prądy błonowe powstające w wyniku hamującej akcji synaptycznej. Potencjał czynnościowy dochodzący do zakończenia włókna presynaptycznego powoduje uwolnienie neuroprzekaźnika z kolbki synaptycznej, co prowadzi do zmiany przewodnictwa błony postsynaptycznej dla wybranych jonów. W wyniku otwarcia kanałów jonowych, powstaje lokalne źródło prądowe w okolicy synapsy oraz zlew prądowy rozproszony wzdłuż dalszych obszarów błony, tak by spełnione było prawo zachowania ładunku. ]]<br />
W stanie spoczynku, potencjał wewnątrz komórki wynosi ok. –65 mV względem potencjału na zewnątrz. Jeżeli synapsa jest pobudzająca, efektem jej aktywacji będzie zwiększenie przepuszczalności dla dodatnio naładowanych jonów, które zaczną napływać do komórki. Zmiana potencjału błonowego w wyniku akcji synaptycznej nazywana jest pobudzającym potencjałem postsynaptycznym lub EPSP (od ang. ''excitatory postsynaptic potential''). EPSP zmniejsza wartość różnicy potencjału w komórce i podnosi jej wewnątrzkomórkowy potencjał w kierunku odpalenia jej własnego potencjału czynnościowego, przy różnicy potencjałów w poprzek błony ok. –40 mV. Błona w bezpośredniej okolicy synapsy zachowuje się jak zlew prądowy (źródło ujemne) gdyż dodatnio naładowane jony wpływają do wewnątrz. Prąd płynie w przestrzeni wewnątrzkomórkowej i wypływa z komórki w dalszych, rozproszonych obszarach, tak aby zamknąć linie prądu. Całkowity prąd dokomórkowy musi być równy całkowitemu prądowi wypływającemu z komórki, co wynika z zasady zachowania ładunku. Jeżeli synapsa jest hamująca, zmiana potencjału błonowego w wyniku akcji synaptycznej nazywana jest hamującym potencjałem postsynaptycznym lub IPSP (od ang. inhibitory postsynaptic potential). Ma on odwrotne działanie w stosunku do EPSP i zmniejsza prawdopodobieństwo generacji potencjału czynnościowego. IPSP generuje powstanie lokalnego źródła prądu, któremu musi towarzyszyć odpowiedni zlew prądowy rozproszony wzdłuż bardziej odległych obszarów błony (<xr id="fig:Synaptic_action_currents">rys. %i</xr>). Potencjał zewnątrzkomórkowy powstający w wyniku akcji synaptycznej zależy od pełnego rozkładu źródeł i zlewów w błonie s('''r''', ''t''), a nie tylko od lokalnego prądu płynącego w otoczeniu synapsy. W wyniku złożonej geometrii neuronów, geometria rozkładu prądów płynących przez błonę może być skomplikowana, a potencjał zewnątrzkomórkowy trudny do policzenia. Jednakże w zagadnieniach EEG, możemy obejść wiele problemów ze złożonością pojedynczych neuronów poprzez zmianę skali, w której rozpatrujemy generatory prądów. W tym celu zdefiniujmy efektywny prądowy moment dipolowy dla każdej objętości tkanki. Prądowy moment dipolowy na jednostkę objętości tkanki kory mózgowej może być uważany za korowe źródło generujące pole magnetyczne i elektryczne na powierzchni czaszki. Kluczem do zrozumienia tego upraszczającego założenia jest fakt, że pojedyncza komórka kory mózgowej dostaje ok. 10<sup>4</sup>-10<sup>5</sup> wejść synaptycznych, a pod każdym milimetrem kwadratowym powierzchni kory znajduje się ok. 10<sup>5</sup> neuronów. Potencjał zewnątrzkomórkowy mierzony przez małą elektrodę z takiego obszaru będzie bardzo skomplikowany i będzie bardzo czuły na zmianę położenia elektrody. Jednakże w odległościach dużych w porównaniu z charakterystyczną odległością pomiędzy źródłami i zlewami, potencjał generowany przez źródła i zlewy w kolumnie będzie przypominał potencjał dipola. Dla wielu kolumn wykazujących aktywność synaptyczną, potencjał na czaszce będzie ważoną sumą dipolowych przyczynków od poszczególnych kolumn. W komórce piramidowej, charakterystyczna odległość pomiędzy źródłem a zlewem jest rzędu paru milimetrów, podczas gdy odległość do najbliższych obszarów na czaszce wynosi ok. 1-1,5 cm. Tak więc przybliżenie dipolowe dla źródeł w kolumnach korowych jest spełnione w zagadnieniach EEG.<br />
<br />
==Bezpośrednie zastosowanie makroskopowych źródeł prądu==<br />
We wszystkich następujących zagadnieniach będziemy zakładać, że ośrodek jest czysto przewodzący i nie wykazuje efektów pojemnościowych. W takim ośrodku, ładunek nie jest nigdzie gromadzony, gęstość ładunku jest stała, a równanie zachowania ładunku można zapisać: <br />
<br />
<equation id="eq:Equation 4.10"><math>\nabla \textbf{J} = 0</math> </equation> <br />
<br />
Korzystne okazuje się wprowadzenie pojęcia makroskopowej gęstości prądu źródeł '''J'''''<sub>s</sub>'', która pozwala zapisać prawo Ohma następująco:<br />
<br />
<equation id="eq:Equation 4.11"><math>\textbf{J} = \sigma \textbf{E} + \textbf{J}_{s} </math> </equation> <br />
<br />
Oznacza to, że prąd całkowity w ośrodku przewodzącym składa się prądu omowego &sigma;'''E''' oraz prądu źródłowego wypływającego z granicy między ośrodkami np. prąd wypływający przez błonę komórkową. Wstawiając (<xr id="eq:Equation 4.11"></xr>) do (<xr id="eq:Equation 4.10"></xr>) i korzystając z definicji potencjału elektrycznego dostajemy:<br />
<br />
<equation id="eq:Equation 4.12"><math>\nabla \cdot [\sigma (\textbf{r}) \nabla \Phi ]= -s(\textbf{r}, t) </math> </equation> <br />
<br />
gdzie objętościowy prąd źródłowy jest zdefiniowany jako<br />
<br />
<equation id="eq:Equation 4.13"><math>s(\textbf{r}, t) \equiv -\nabla \textbf{J}_s(\textbf{r}, t) </math> </equation> <br />
<br />
[[Grafika:Volume_current_sources.jpg|400px|thumb|right|<figure id="fig:Current_sources"></figure>Potencjał wewnątrz przewodnika oznaczonego zaokrąglonym prostokątem jest określony równaniem Laplace'a (<xr id="eq:Equation 4.5"></xr>). Jednoznaczne rozwiązanie tego równania wymaga znajomości potencjału lub normalnej pochodnej potencjału na powierzchniach granicznych przewodnika. Zamiast podawać warunki brzegowe na granicach przewodnika, możemy podać źródła prądowe s('''r''', ''t'') występujące na tych powierzchniach. W tej sytuacji jednoznaczne rozwiązanie dla potencjału wewnątrz przewodnika jest dane równaniem Poissona (<xr id="eq:Equation 4.12"></xr>). Obszary zaznaczone kolorem szarym są źródłami prądu, pozostałe (białe) obszary są bezźródłowe.]]<br />
<br />
Przewodnictwo &sigma;(''r'') (w S/mm lub S/cm) w ogólności zależy od położenia i dlatego znajduje się wewnątrz operatora &nabla;. Gęstość prądu źródłowego s('''r''', ''t'') ma wymiar prądu na jednostkę objętości &mu;A/mm<sup>2</sup>. Jest to prąd generowany w jednostce objętości. Może być również interpretowany jako objętościowe źródło potencjału generowanego w ośrodku makroskopowym. Rozumowanie stojące za wprowadzeniem prądu źródłowego jest następujące. Dowolny obszar tkanki możemy podzielić tak, że obszary generacji prądu znajdują się pewnych podobszarach oznaczonych kolorem szarym na <xr id="fig:Current_sources">rys. %i</xr>. W pozostałych obszarach (zaznaczonych kolorem białym) potencjał jest określony równaniem Laplace’a (<xr id="eq:Equation 4.5"></xr>) w ośrodku jednorodnym i (<xr id="eq:Equation 4.12"></xr>) w ośrodku niejednorodnym, kładąc s('''r''', ''t'') równe zero. Jednakże jednoznaczne rozwiązanie wymaga by potencjał lub składowa normalna potencjału była określona na całej granicy ośrodków. W formalizmie równania Poissona (<xr id="eq:Equation 4.12"></xr>) zastąpiliśmy warunki brzegowe poprzez prąd objętościowy s('''r''', ''t''). Ujemny znak w równaniu (<xr id="eq:Equation 4.12"></xr>) jest spójny z prądem dodatnim wpływającym do bezźródłowego (białego) obszaru. Inna zaletą tego podejścia jest fakt, że w ośrodku czysto przewodzącym czasowa zależność potencjału &Phi;('''r''', ''t'') jest identyczna z czasową zależnością źródła. Pojedyncze oscylujące źródło s('''r''', ''t'') &sim; sin(2&pi;''ft'') powoduje oscylacje potencjału z tą samą częstością. Jednakże w mózgu będzie zazwyczaj wiele źródeł oscylujących z różnymi częstościami i fazami. Potencjał na czaszce mierzony w EEG będzie liniową superpozycją przyczynków od pojedynczych obszarów źródeł z różnymi wagami zależnymi od własności przewodnictwa ośrodka i odległości pomiędzy źródłami i miejscami pomiaru potencjału na czaszce.<br />
Przeprowadzone tutaj operacje matematyczne mogą się wydawać nieco sztuczne, okazują się jednak bardzo wygodne w zrozumieniu problemów związanych z generacją potencjałów w tkance nerwowej. Porównajmy wzór na potencjał w przewodniku pochodzący od obszaru źródła prądowego s('''r''', ''t'') (<xr id="eq:Equation 4.12"></xr>) ze wzorem na potencjał w dielektryku pochodzący od obszaru źródła z pewną gęstością swobodnego ładunku &rho;('''r''', ''t''). Równanie na potencjał w dielektryku otrzymamy poprzez połączenie równań (<xr id="eq:Max I"></xr>), (<xr id="eq:dielectric"></xr>) i (<xr id="eq:Scalar potential"></xr>). Prowadzi to do równania Poissona w dielektryku:<br />
<br />
<equation id="eq:Equation 4.14"><math>\nabla \cdot [\varepsilon (\textbf{r}) \nabla \Phi(\textbf{r}, t)] = -\rho(\textbf{r}, t) </math> </equation> <br />
<br />
Oba równania (<xr id="eq:Equation 4.14"></xr>) i (<xr id="eq:Equation 4.12"></xr>) są równaniami Poissona lecz ze zmienionymi symbolami. Są one więc matematycznie równoważne lecz reprezentują inne fizycznie procesy. Swobodny ładunek makroskopowy w przewodniku w praktyce wynosi zero, tak więc równanie (<xr id="eq:Equation 4.14"></xr>) nie ma praktycznego zastosowania w elektrofizjologii. Jednakże w fizyce znanych jest wiele rozwiązań równania (<xr id="eq:Equation 4.14"></xr>) dla różnych rodzajów niejednorodności w dielektrykach. Aby zastosować znane z fizyki rozwiązania do przewodnika wystarczy w nich podstawić przewodnictwo &sigma;('''r''', ''t'') w miejsce przenikalności elektrycznej &epsilon;('''r''', ''t''), a źródła ładunku &rho;('''r''', ''t'') zamienić na źródła prądowe s('''r''', ''t''). Np. rozważmy specjalny przypadek ''N'' punktowych źródeł prądowych, co oznacza, że rozmiary (objętość) źródła jest dużo mniejsza niż odległość od elektrod pomiarowych. W nieskończonym, jednorodnym i czysto opornościowym przewodniku, potencjał na zewnątrz źródeł jest analogiczny do potencjału pochodzącego od ''N'' ładunków punktowych i wynosi:<br />
<br />
<equation id="eq:Equation 4.15"><math> \Phi(\textbf{r}, t) = \frac{1}{4 \pi \sigma}\sum_{n=1}^{N} \frac{I_n(t)}{R_n} </math> </equation> <br />
<br />
W typowych jednostkach stosowanych w zagadnieniach EEG, ''I<sub>n</sub>''(''t'') są jednobiegunowymi źródłami prądowymi (&mu;A) wypływającymi z ''n''-tego rejonu źródła do przewodnika o przewodnictwie &sigma; (1/(&Omega;cm)). ''R<sub>n</sub>'' są odległościami pomiędzy miejscem pomiaru a położeniem źródła. Np. potencjał w odległości 1 cm generowany przez źródło prądowe o natężeniu 4&pi; &mu;A w wyidealizowanej korze mózgowej o oporności &eta; = 1/&sigma; = 300 &Omega;cm, wynosi 300 mV. W ośrodku czysto opornościowym, zależność czasowa potencjału jest dana przez sumę ważoną wszystkich źródeł. W ośrodku z własnościami pojemnościowymi wystąpią przesunięcia fazowe pomiędzy źródłami i potencjałem. Gdy zaniedbamy efekty pojemnościowe, otrzymamy ogólną metodę znajdowania potencjału na podstawie rozkładu źródeł prądowych w mózgu.<br />
<br />
==Źródła prądowe w ośrodku przewodzącym==<br />
Większość zjawisk obserwowanych w zapisie EEG może być zrozumiana na podstawie paru rodzajów źródeł. W szczególności jest to dipol prądowy, warstwa dipolowa i rozkład źródeł pochodzący od potencjału czynnościowego. Pole na czaszce, pochodzące od tych źródeł będzie oczywiście silnie zależeć od makroskopowych niejednorodności takich jak czaszka. My zajmiemy się uproszczoną sytuacją i rozważymy różne przykłady źródeł w nieskończonym, jednorodnym i izotropowym ośrodku przewodzącym. Przybliżenie to dostarczy nam ważnej intuicji na temat generatorów rzeczywistych sygnałów EEG. <br />
<br />
===Źródło jednobiegunowe===<br />
Potencjał pojedynczego źródła jednobiegunowego jest szczególnym przypadkiem rozwiązania (<xr id="eq:Equation 4.15"></xr>) i wynosi<br />
<br />
<equation id="eq:Equation 5.3"><math> \Phi(\textbf{r}, t) = \frac{I(t)}{4 \pi \sigma r} </math> </equation> <br />
<br />
Równanie (<xr id="eq:Equation 5.3"></xr>) można też otrzymać przeprowadzając proste rozumowanie. Otoczmy punktowe źródło sferą o promieniu ''r''. Ponieważ prąd całkowity jest zachowany, gęstość prądu na powierzchni sfery wynosi <br />
<equation id="eq:Current_sphere"><math> J(r,t) = \frac{I(t)}{4 \pi r^2} </math> </equation> <br />
<br />
w kierunku radialnym. Z prawa Ohma:<br />
<br />
<equation id="eq:Electric_field_Current_sphere"><math> E(r,t) = \frac{J(r,t)}{\sigma} = \frac{I(t)}{4 \pi \sigma r^2}</math> </equation> <br />
<br />
Stosując równanie potencjału skalarnego (<xr id="eq:Scalar potential"></xr>), dla składowej radialnej dostajemy: <br />
<br />
<equation id="eq:Electric_potential_Current_sphere"><math> -\nabla \Phi = -\frac{\partial \Phi}{\partial r} = \frac{I(t)}{4 \pi \sigma r^2} </math> </equation> <br />
<br />
<br />
Po scałkowaniu (<xr id="eq:Electric_potential_Current_sphere"></xr>) dostajemy równanie (<xr id="eq:Equation 5.3"></xr>). Z równania (<xr id="eq:Equation 5.3"></xr>) wynika, że potencjał w przewodniku staje się nieskończony jeśli odległość między źródłem a punktem pomiaru wynosi zero lub przewodnictwo ośrodka wynosi zero. Ta nie-fizyczna sytuacja wynika z dwóch założeń zrobionych przy wyprowadzaniu równania (<xr id="eq:Equation 5.3"></xr>). Po pierwsze, założyliśmy, że pomiar dokonywany jest punktowo lecz prawdziwe elektrody pomiarowe mają niezerowe rozmiary więc ''r'' nie może być zero. Po drugie, założyliśmy, że jesteśmy w stanie zapewnić stałe natężenie prądu niezależnie od przewodnictwa ośrodka. Jednakże gdy przewodnictwa ośrodka będzie malało, coraz większe napięcie z generatora będzie wymagane, by utrzymać stały prąd w źródle. W rzeczywistości, gdy przewodnictwo ośrodka będzie dążyć do zera, natężenie prądu ''I'' będzie również dążyło do zera, co zapewni skończoną wartość potencjału.<br />
<br />
===Dipol prądowy===<br />
<br />
Dipol prądowy składa się z punktowego źródła ''I'' i zlewu –''I'', oddzielonych o ''d''. Znaczenie dipola w elektrofizjologii jest większe niż jakakolwiek inna konfiguracja źródeł. Jest tak dlatego, że prawie każdy obszar zawierający źródło i zlew, oraz w którym całkowity prąd źródła i zlewu są równe (zasada zachowania prądu), będzie dawał przybliżone pole dipola w odległościach dużych w porównaniu z rozmiarami obszaru źródło-zlew. Np. pole dipola jest generowane w wyniku pobudzenia lub hamowania synaptycznego w neuronach, jak to zostało opisane w sekcji ''Źródła prądowe w mózgu''. Ścisłe wyrażenie na potencjał dipola jest to suma dwóch jednobiegunowch przyczynków o przeciwnej polaryzacji i odległościach odpowiednio ''r''<sub>1</sub>, ''r''<sub>2</sub> od punktu pomiaru:<br />
<br />
<equation id="eq:Dipole potential"><math> \Phi = \frac{I(t)}{4 \pi \sigma}\left(\frac{1}{r_1} - \frac{1}{r_2}\right) </math> </equation> <br />
<br />
Jednakże dużo wygodniej wyrazić potencjał dipola za pomocą jednej współrzędnej radialnej ''r'', mierzonej od środka odcinka łączącego ładunki. W odległościach dużo większych od ''d'', pole dipola można przybliżyć następująco:<br />
<br />
<equation id="eq:Dipole_potential_approx"><math> \Phi = \frac{I d \cos \Theta}{4 \pi \sigma r^2} </math> </equation> <br />
dla ''r'' ≫ ''d''. &Theta; jest kątem pomiędzy osią dipola i wektorem '''r''' wskazującym punkt pomiaru. <br />
Rozważmy lokalny przepływ prądu pomiędzy III i VI warstwą kory mózgowej. Odległość między biegunami prądu wynosi wtedy ''d'' ~ 1 mm. Załóżmy prądowe źródło o natężeniu ''I'' = 10 &mu;A i nieskończony jednorodny ośrodek o oporności &eta; = 1/&sigma; = 300 &Omega;cm odpowiadającej korze mózgowej. Licząc potencjał (względem nieskończości) wzdłuż osi dipola (&Theta; = 0), możemy zastosować (<xr id="eq:Dipole_potential_approx"></xr>) również w pobliżu źródeł. Wstawiając dane dostajemy:<br />
<br />
:&Phi;(''r'', 0) &asymp; 464 &mu;V dla ''r'' = 2,5 mm (na powierzchni kory)<br />
:&Phi;(''r'', 0) &asymp; 12 &mu;V dla ''r'' = 1,5 cm (na czaszce)<br />
<br />
Powyższe oszacowania nie biorą pod uwagę wpływu warstw płynu mózgowo-rdzeniowego, czaszki i skóry na głowie i powietrza nad głową. Szacuje się, że wpływ tych warstw o różnym przewodnictwie zmniejsza potencjał pochodzący od dipola znajdującego się w powierzchownych warstwach kory, a mierzonego na czaszce do ok. 1/4 wartości otrzymanej w jednorodnym modelu kory. Te zgrubne oszacowania pozwalają nam przewidzieć stosunek potencjału mierzonego na czaszce do potencjału mierzonego na powierzchni kory. Dla pojedynczego źródła korowego stosunek ten wynosi 464/(12/4), a więc:<br />
<br />
:Potencjał na korze/potencjał na czaszce ~ 100 do 200<br />
<br />
Średnie amplitudy spontanicznego EEG na korze są zazwyczaj 2 do 5 razy większe od potencjałów mierzonych na czaszce (Cooper et al., 1965). Brak zgodności naszego oszacowania z doświadczeniem sugeruje, że zdecydowana większość zjawisk w EEG jest generowana nie przez pojedyncze dipole lecz przez źródła o znacznie większych rozmiarach np. przez warstwy dipolowe. Z drugiej strony, niektóre iglice epileptyczne (ang. ''epileptic spikes'') i potencjały wywołane (ang. ''evoked potentials'') w pierwszorzędowej korze sensorycznej można z powodzeniem modelować jako pojedynczy dipol lub parę izolowanych dipoli.<br />
<br />
===Źródło kwadrupolowe===<br />
Rozróżniamy dwie konfiguracje prowadzące do źródła kwadrupolowego. Kwadrupol liniowy składa się z dwóch źródeł +''I''/2 i zlewu –''I'' leżących wzdłuż jednej prostej, oddzielonych od siebie o ''d''. Kwadrupol dwuwymiarowy składa się z dwóch identycznych dipoli, umieszczonych równolegle do siebie, o przeciwnej orientacji. Kwadrupol liniowy ma zastosowanie w elektrofizjologii gdyż wykazuje podobieństwo do trójfazowego rozkładu źródeł we włóknie nerwowym podczas potencjału czynnościowego. Potencjał kwadrupola w dowolnym miejscu ośrodka przewodzącego wynika bezpośrednio ze wzoru (<xr id="eq:Equation 5.3"></xr>) na potencjał pojedynczego źródła jednobiegunowego<br />
<br />
<equation id="eq:Quadrupole_potential"><math> \Phi = \frac{I}{4 \pi \sigma}\left(\frac{1}{2r_1} - \frac{1}{r_2} + \frac{1}{2r_3}\right) </math> </equation> <br />
<br />
Trzy wartości ''r'' odpowiadają trzem odległościom pomiędzy źródłami i zlewami, a punktem pomiaru. W średnich lub dużych odległościach, potencjał może być wyrażony we współrzędnych sferycznych (''r'', &theta;, &phi;) jako<br />
<br />
<equation id="eq:Quadrupole_potential_approx"><math> \Phi \cong \frac{I d^2}{32 \pi \sigma r^3}(3 \cos^2 \theta - 1) </math> </equation> <br />
<br />
Potencjał nie zależy od współrzędnej &phi;.<br />
<br />
Podczas generacji potencjału czynnościowego następuje wpływ dodatniego prądu jonów Na<sup>+</sup> do wnętrza komórki. Prądowe źródło na pewnym obszarze błony komórkowej musi mieć odpowiadające mu zlewy prądowe, które znajdują się w obszarach po obu stronach źródła. W ten sposób powstaje konfiguracja źródło-zlew przypominająca kwadrupol liniowy. Ponieważ potencjał kwadrupola zanika jak 1/''r''<sup>3</sup> czyli szybciej niż potencjał dipola (1/''r''<sup>2</sup>), potencjały czynnościowe mają znikomy wpływ na sygnał EEG. Synchronicznie występujące potencjały czynnościowe (ang. compound action potentials) mogą jednak być mierzalne. Istnieją podstawy by sądzić (Jewett, 1970), że potencjały czynnościowe biegnące we nerwie słuchowym są przynajmniej częściowo źródłem słuchowych potencjałów wywołanych z pnia mózgu (BAER od ang. brainstem auditory evoked response).<br />
<br />
===Warstwa dipolowa &mdash; najważniejsze źródło sygnału EEG===<br />
<br />
Około 65 do 75% neuronów korowych u wszystkich gatunków ssaków jest ustawionych prostopadle do powierzchni kory (Scholl, 1956; Bok, 1959). Neurony korowe mają dużą liczbę wzajemnych połączeń powodujących synchronizacje ich aktywności. Istnieją więc zarówno anatomiczne, jak i fizjologiczne podstawy by uznać warstwę dipolową tworzoną przez równoległe, synchronicznie działające komórki, za generator potencjałów korowych. Synchronizacja generatorów odgrywa tutaj kluczową rolę. Rozważmy na początku dwa dipole, których prądy fluktuują z częstościami <math>f_A</math> i <math>f_B</math>. Może to odpowiadać dwóm komórkom, dostającym zarówno wejścia pobudzające, jak i hamujące (<xr id="fig:Two_pyramidal_cells">rys. %i</xr>). Potencjał mierzony przez elektrodę w punkcie ''P'', otrzymamy na podstawie (<xr id="eq:Equation 4.15"></xr>):<br />
<br />
<equation id="eq:Equation 3.22"><math> \phi(t) = \frac{1}{4 \pi \sigma}\left[\frac{I_A}{R_1}\cos(2\pi f_A t + \alpha_A) - \frac{I_A}{R_2}\cos(2\pi f_A t + \alpha_A) + \frac{I_B}{R_3}\cos(2\pi f_B t + \alpha_B) - \frac{I_B}{R_4}\cos(2\pi f_B t + \alpha_B)\right]</math> </equation> <br />
<br />
''I<sub>A</sub>'' oraz ''I<sub>B</sub>'' są maksymalnymi wartościami prądu w każdym z dipoli. Dodatkowo, zakładamy, że cały prąd wypływający ze źródła wpływa do zlewu w tym samym dipolu, co jest spełnione gdy odległość między dipolami ''L''jest znacznie większa niż odległość pomiędzy efektywnymi biegunami ''d''. &alpha;''<sub>A</sub>'' i <math>\alpha_B</math> są kątami fazowymi. Dla większej ilości źródeł, w wyrażeniu (<xr id="eq:Equation 3.22"></xr>) pojawią się analogiczne człony. <br />
<br />
[[Grafika:Two_pyramidal_cells.jpg|400px|thumb|right|<figure id="fig:Two_pyramidal_cells"></figure>Dwie komórki piramidalne A i B pobudzane synaptycznie, są przedstawione w wyidealizowanej formie, jako dipole. Potencjał w punkcie ''P'' jest sumą przyczynków pochodzących od obu zlewów (-) i obu źródeł (+) prądu. Odległość między dipolami wynosi ''L'', a odległość pomiędzy efektywnymi biegunami dipoli wynosi ''d''.]]<br />
<br />
Rozważmy wpływ wielu dipoli o podobnej sile (<math>I_A = I_B = I_C</math>, itd) i podobnych częstościach (<math>f_A = f_B = f_C</math>, itd) na średni potencjał <math>|\bar{\Phi}|</math>. Potencjał będzie oczywiście zależał od wszystkich odległości ''R''<sub>1</sub>, ''R''<sub>2</sub>, itd., możemy jednak sformułować pewne ogólne wnioski. <br />
:a. Gdy generatory są ze sobą w fazie (<math>\alpha_A </math> = <math>\alpha_B </math> = <math>\alpha_C </math> , itd), a dipole ustawione równolegle do siebie, wyrażenia we wzorze (<xr id="eq:Equation 3.22"></xr>) dodają się i dla ''m'' dipoli, uśredniony po czasie potencjał będzie proporcjonalny do ilości wszystkich ''m'' generatorów w otoczeniu elektrody, <br />
:<equation id="eq:Equation 3.23"><math> |\bar{\Phi}| \sim m</math> </equation><br />
:Oczywiście, generatory znajdujące się najbliżej elektrody, będą miały największy wpływ na potencjał, lecz im więcej generatorów będzie aktywnych w losowych odległościach od punktu pomiaru, wzór (<xr id="eq:Equation 3.23"></xr>) będzie stanowić tym lepsze przybliżenie. <br />
<br />
:b. Jeśli generatory mają losową orientację, tak że prądy ''I'' w (<xr id="eq:Equation 3.22"></xr>) będą miały losowe znaki lub jeśli losowe będą fazy generatorów, potencjał będzie dużo słabiej zależał od liczby generatorów. Będzie on wynikiem statycznej fluktuacji. Wg. Nunez (1981), można pokazać, że ''m'' członów w wyrażeniu (<xr id="eq:Equation 3.22"></xr>) sumuje się dając średni potencjał, który dla dużych ''m'' można oszacować jako:<br />
:<equation id="eq:Equation 3.24"><math> |\bar{\Phi}| \sim \sqrt{m}</math> </equation><br />
<br />
<br />
Zastosujmy teraz powyższe rozważania do zapisu rejestrowanego elektrodą umieszczoną w pobliżu generatorów. Jeśli elektroda znajduje się wystarczająco blisko źródła prądowego, tak że jeden z ''R''s w (<xr id="eq:Equation 3.22"></xr>) jest bardzo mały, mierzony potencjał będzie stosunkowo duży, bez względu na fazowe relacje pomiędzy źródłem lokalnym i innymi źródłami w otaczającej tkance. Źródła odległe również mogą dawać wkład do mierzonego potencjału. Ich wkład może być mniejszy lub większy od wkładu źródła lokalnego. Źródła odległe będą zachowywały się głównie jak dipole prądowe. Tak więc potencjał mierzony przez elektrodę może być wyrażony następującym przybliżonym wzorem.<br />
<br />
<equation id="eq:Equation 3.25"><math> |\bar{\Phi}| = \frac{1}{8 \pi \sigma}\left[\sum_{i =1}^l\frac{I_{i}}{R_{i}} + m \frac{I_{S}d}{R_{S}^2} + \sqrt{n} \frac{I_{A}d}{R_{A}^2} \right]</math> </equation> <br />
<br />
<br />
Indeksy ''i'', ''S'', oraz ''A'' odnoszą się odpowiednio do źródeł lokalnych, źródeł odległych synchronicznych i źródeł odległych asynchronicznych. ''I''s są prądami efektywnymi, które mogą być mniejsze niż prąd całkowity, w zależności od orientacji odległych synchronicznych źródeł względem elektrody. ''d'' jest odległością pomiędzy efektywnymi biegunami dipoli. ''l'', ''m'' i ''n'' są liczbą źródeł lokalnych, odległych synchronicznych i odległych asynchronicznych, które znajdują się odpowiednio w średnich odległościach ''R''<math>_{i}</math>, ''R''<math>_S</math>, ''R''<math>_A</math>. Należy pamiętać, że (<xr id="eq:Equation 3.25"></xr>) jest idealizacją, gdyż nie wszystkie generatory dają się zaklasyfikować do poszczególnych kategorii, jednakże wzór ten może dać ogólny pogląd na generacje potencjałów w mózgu, a w szczególności potencjałów mierzonych na czaszce czyli EEG. W tym przypadku (EEG) nie ma źródeł lokalnych. Jeśli generatory są podobne ''I<sub>S</sub>'' &asymp; ''I<sub>A</sub>'' oraz generatory synchroniczne i asynchroniczne są w podobnej odległości ''R<sub>S</sub>'' &asymp; ''R<sub>A</sub>'', względny przyczynek od generatorów synchronicznych względem asynchronicznych wynosi: <br />
<equation id="eq:Ratio_generators"><math> \frac{m}{\sqrt{n}}</math> </equation> <br />
<br />
Na podstawie zależności (<xr id="eq:Ratio_generators"></xr>) możemy przeprowadzić następujące rozumowanie. Elektroda umieszczona na czaszce mierzy aktywność ok. 10<math>^8</math> neuronów znajdujących się w paru cm<math>^2</math> kory, Załóżmy, że prawie wszystkie neurony są aktywne lecz tylko 1% (10<math>^6</math>) z nich jest ustawiony równolegle i działa synchronicznie. Przyczynek od synchronicznej frakcji neuronów do potencjału mierzonego na czaszce wynosi:<br />
<equation id="eq:Ratio_generators_electrode"><math> \frac{10^6}{\sqrt{10^8 - 10^6}} \cong 100</math> </equation> <br />
Jest on więc 100 razy większy niż przyczynek od pozostałych 99% neuronów (Elul, 1972). Pokazuje to, że powierzchniowe EEG pochodzi głównie od synchronicznej aktywności równolegle ustawionych neuronów, a zmiana amplitudy sygnału wraz ze stanem fizjologicznym, wiąże się ze zmianą liczby synchronicznie działających komórek. <br />
Wzór (<xr id="eq:Equation 3.25"></xr>) sugeruje, że potencjał od źródeł odległych zanika z odległością jak 1/''R''<math>^2</math>. Warto zauważyć, że dla warstw dipolowych bardzo dużych rozmiarów, zanik ten może być jeszcze wolniejszy. Np. dla nieskończonej warstwy dipolowej potencjał nad (lub pod warstwą) dipolową jest stały i nie zmienia się z odległością. Oznacza to, że dla małych odległości od warstwy, w porównaniu z jej rozmiarami, zanik potencjału będzie niewielki, a im większa warstwa tym zanik potencjału wolniejszy. W przypadku dużych warstw dipolowych zanik potencjału na czaszce względem potencjału na korze jest nieznaczny. Eksperymentalnie obserwowany stosunek potencjału na korze do potencjału na czaszce jest, w większości spontanicznych zapisów EEG, pomiędzy 2 i 5 (Cooper et al., 1965). Po uwzględnieniu niejednorodności takich jak czaszka, płyn mózgowo-rdzeniowy i powietrzne nad głową, oznacza to, że korowe źródła muszą tworzyć warstwy dipolowe o rozmiarach znacznie większych niż odległość pomiędzy czaszką a korą. Mają więc one rozmiary rzędu paru cm<math>^2</math>.<br />
<br />
==Podsumowanie==<br />
Potencjały w ośrodku jednorodnym pochodzące od źródeł i zlewów prądowych zostały otrzymane na podstawie ogólnego równania (<xr id="eq:Equation 4.15"></xr>). Fizjologiczne źródła prądowe, są generowane w błonach komórkowych w wyniku transmisji synaptycznej lub generacji potencjału czynnościowego. Różne konfiguracje źródeł i zlewów mogą generować potencjały o bardzo różnych własnościach przestrzennych. Zanik potencjału wraz z odległością od źródeł-zlewów może być bardzo słaby (tzw. pola dalekie lub długozasięgowe), jak w przypadku warstwy dipolowej. Zanik ten może też być silny np. w przypadku koncentrycznie ustawionych neuronów, tak jak w przypadku kwadrupola (tzw. pola bliskie lub krótkozasięgowe). Znajomość potencjałów generowanych w wyidealizowanym, nieskończonym, jednorodnym ośrodku dostarcza przydatnych oszacowań na temat różnych fizjologicznych procesów np. generacji potencjałów czaszkowych EEG. Na koniec należy zauważyć, że wszystkie wyprowadzone tutaj wzory dotyczyły potencjału w pewnym punkcie. W rzeczywistości, mierzone potencjały są potencjałami uśrednionymi po całej objętości elektrody. Potencjał mierzony przez sferyczną elektrodę <math>\Phi_E</math> o promieniu ''R'' jest związany z teoretycznym potencjałem punktowym <math>\Phi</math> poprzez całkę objętościową: <br />
<br />
<equation id="eq:Volume_average_potential"><math>\Phi_E(r,t,R) = \frac{3}{4 \pi R^3}\iiint\limits_{\mathrm{Vol}(R)} \Phi(r', t)\, d^3r'\ </math> </equation> <br />
<br />
Ze względu na skomplikowaną anatomię kory, zachowanie potencjału <math>\Phi_E</math> wewnątrz mózgu (zapisy śródmózgowe) będzie bardzo silnie zależało od parametru skali ''R''. W przeciwieństwie do tego, potencjały czaszkowe są już silnie uśrednione przestrzennie w wyniku przejścia przez płyn mózgowo-rdzeniowy, czaszkę i skórę. Powoduje to, że rozmiar elektrody nie ma prawie wpływu na zapis czynności EEG.<br />
<br />
==Literatura==<br />
<br />
Bok S.T., Histonomy of the Cerebral Cortex, Elsevier, New York, 1959.<br />
<br />
Cooper R., Winter A.L., Crow H.J., Walter W.G. Comparison of subcortical, cortical and scalp activity using chronically indwelling electrodes in man. Electroencephalogr Clin Neurophysiol. 18:217-228, 1965.<br />
<br />
[http://books.google.pl/books?id=Tvu7Z3QRZkAC&pg=PA227&lpg=PA227&dq=The+genesis+of+the+EEG&source=bl&ots=rEovH1QgTh&sig=9MJUiVz9lIEq3SbDVzs5iSjWNWc&hl=pl&ei=YKZFTJ6rDMyksAbx9uVk&sa=X&oi=book_result&ct=result&resnum=6&ved=0CDsQ6AEwBQ#v=onepage&q=The%20genesis%20of%20the%20EEG&f=false Elul R. The genesis of the EEG. Int Rev Neurobiol 15: 227-272, 1972.]<br />
<br />
Jewett D.L. Volume-conducted potentials in response to auditory stimuli as detected by averaging in the cat. Electroencephalogr. Clin. Neurophysiol. 28(6):609-618, 1970.<br />
<br />
Nunez P.L Electric Fields of the Brain. The Neurophysics of EEG. Oxford University Press, New York, NY, 1981 (First edition).<br />
<br />
Nunez P.L. Neocortical Dynamics and Human EEG Rhythms. Oxford University Press, New York, 1995.<br />
<br />
[http://books.google.pl/books?id=V1LuaISgSzgC&dq=%22Electric+Fields+of+the+Brain%22&printsec=frontcover&source=bn&hl=pl&ei=76ZFTKiCCJSmsAajgKGjAQ&sa=X&oi=book_result&ct=result&resnum=4&ved=0CDMQ6AEwAw#v=onepage&q&f=false Nunez P.L. Electric Fields of the Brain. The Neurophysics of EEG. Oxford University Press, New York, NY, 2006 (Second edition).]<br />
<br />
Scholl D.A. The organization of the Cerebral Cortex, Methuen, London, 1956.</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG/Wprowadzenie_do_Matlaba&diff=4819Laboratorium EEG/Wprowadzenie do Matlaba2016-03-01T12:47:24Z<p>Tspus: /* Ćwiczenia */</p>
<hr />
<div>[[Laboratorium_EEG]]/Wprowadzenie_do_Matlaba<br />
<br />
<br />
==Wprowadzenie==<br />
[[Plik:Matlab_splash.png|200px|thumb|right|Okno powitalne Matlaba]]<br />
Najkrócej można określić Matlab jako pakiet oprogramowania do obliczeń matematycznych wyprodukowany w firmie [http://www.mathworks.com/ MathWorks]. Jest to w istocie zintegrowane ''środowisko obliczeniowe'', w którym mamy do dyspozycji:<br />
* własny język programowania wysokiego poziomu, dający możliwość interaktywnego programowania;<br />
* środowisko zaprojektowane do pracy z macierzami numerycznymi;<br />
* specjalistyczne zestawy procedur obliczeniowych z różnych dziedzin, możliwość zmiany i dodawania własnych funkcji;<br />
* bogate możliwości graficznej prezentacji wyników 2D/3D oraz projektowania własnych interfejsów graficznych (GUI);<br />
* możliwość włączania programów napisanych w innych językach (C, C++, Fortran, Java);<br />
* okienkowo-zorientowane środowiska graficzne do uruchamiania algorytmów na podstawie ich schematów blokowych (np. Simulink);<br />
* wygodne operacje wejścia/wyjścia dla wielu typów danych (np. wav, avi, DICOM)<br />
* zintegrowane interaktywne narzędzia programistyczne: edytor i debugger.<br />
<br />
Dzięki tym możliwościom pakiet [http://www.mathworks.com/products/matlab/ Matlab] (mimo swej relatywnie wysokiej ceny) stał się bardzo popularnym narzędziem obliczeniowym, szczególnie w dziedzinie analizy danych biomedycznych. Pozwala on na dość szybkie pisanie złożonych programów obliczeniowych, pozwalając skupić się na rozwiązywaniu problemu, a nie na samym kodowaniu programu. Warto więc się z nim zapoznać, gdyż jest duża szansa natrafienia na Matlaba w trakcie kariery zawodowej absolwentów naszej specjalności.<br />
<br />
Warto również dodać, że osoby nie dysponujące dostępem do Matlaba, chcące zapoznać się z programowaniem w tym języku lub używać posiadane gotowe programy mogą skorzystać z darmowego pakietu [http://www.gnu.org/software/octave/ GNU Octave]. Język Octave jest bardzo podobny do Matlabowego i większość programów może być bez zmian przenoszona między nimi.<br />
<br />
==Matlab a Python==<br />
<br />
Ponieważ nasz kurs programowania jest oparty zasadniczo o język Python, właściwe będzie porównanie Pythona i Matlaba. W trakcie nauki programowania w Pythonie, wykorzystywaliśmy interfejs użytkownika, pozwalający nie tylko na uruchamianie programów, ale też na pracę interaktywną. Takim interfejsem jest np. stosowany przez nas <tt>idle</tt>. W Matlabie podobny interfejs jest wbudowany w program &mdash; po uruchomieniu programu dostajemy otwarte okno poleceń.<br />
[[Plik:Idle_and_Matlab.png|800px|thumb|center|Okna poleceń: po lewej Pythona (Idle), po prawej Matlaba]]<br />
Jak widać, w obu przypadkach sytuacja jest podobna. Możemy zacząć pracę w sesji interaktywnej wpisując na bieżąco polecenia, które są od razu interpretowane i wykonywane. Wyniki są natychmiast prezentowane na ekranie. Każdy z pakietów daje nam również możliwość napisania programu w osobnym edytorze tekstu, zapisania go na dysku i uruchomienia w dogodnym dla nas momencie.<br />
<br />
Podobieństw między Matlabem a Pythonem jest dużo więcej. Oba języki są językami wysokiego poziomu, co oznacza, że dużą część szczegółów implementacji naszego kodu możemy pozostawić w gestii stosowanego pakietu, pisząc programy w sposób bardziej przypominający ogólny algorytm opisany w sposób zrozumiały dla człowieka, a nie dopasowany do konkretnego komputera czy systemu operacyjnego.<br />
<br />
Python został zaprojektowany jako język ogólnego stosowania, podczas gdy Matlab był projektowany zasadniczo jako język do obliczeń naukowych. W bardziej zaawansowaną funkcjonalność numeryczną Python został wyposażony dopiero dzięki powstaniu modułów [http://www.scipy.org/ NumPy/SciPy] i [http://matplotlib.sourceforge.net/ Matplotlib]. Pakiety te wprowadzają do Pythona m. in. wielowymiarowe macierze (numpy.array), operacje na wszystkich elementach macierzy oraz szereg procedur graficznych do prezentacji wyników, używających składni parametrów niezwykle podobnej do tych z Matlaba. Wydaje się więc, że nie powinno być trudności, aby &bdquo;przesiąść&ldquo; się z jednego języka na drugi i sprawnie pisać programy. Tak w dużej mierze jest, są jednak między tymi językami subtelne różnice, które (szczególnie dla początkujących) mogą stanowić pułapkę. Najistotniejsze z tych różnic postaramy się tutaj zaprezentować.<br />
<br />
{| border="1" class="wikitable topalign"<br />
|+ '''Porównanie cech języków Matlab i Python'''<br />
! Matlab<br />
! Python (2.x)<br />
|- valign="top"<br />
| Podczas pracy interaktywnej Matlab, w odróżnieniu od Pythona, zwraca wartość każdego wyrażenia, które zlecimy mu do wykonania. Wypisywanie wyniku możemy zablokować kończąc wiersz polecenia średnikiem.<br />
| Python wykonuje polecenie, ale nie zwraca jego wyniku. Jeśli zależy nam na takim zachowaniu Pythona, możemy zastosować nakładkę [http://ipython.scipy.org/ IPython], dającą podobną funkcjonalność.<br />
|- valign="top"<br />
| Zmienne nie mają konkretnego typu, dopiero po przypisaniu im wartości możemy określić typ zmiennej.<br />
| Sytuacja jest podobna.<br />
|- valign="top"<br />
| Domyślnym typem numerycznym są liczby zmiennoprzecinkowe podwójnej precyzji. Dodatkowo, każda zmienna jest tak naprawdę macierzą zmiennych danego typu, nawet jeśli zawiera tylko jedną wartość (jest wtedy macierzą rozmiaru 1&times;1).<br />
<div style="line-height: 1"><tt><small><br />
:>> a = 3<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> class(a)<br />
:ans =<br />
:double<br />
:>> size(a)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1</small></tt></div><br />
| Spośród typów zmiennych numerycznych mamy do dyspozycji liczby całkowite i zmiennoprzecinkowe (które zachowują się inaczej w pewnych operacjach matematycznych). Macierze wprowadzone są przy użyciu pakietu NumPy.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = 3<br />
:>>> type(a)<br />
:<type 'int'><br />
:>>> a = 3.<br />
:>>> type(a)<br />
:<type 'float'></small></tt></div><br />
|- valign="top"<br />
| Macierze definiujemy z użyciem nawiasów kwadratowych.<br />
<div style="line-height: 1"><tt><small><br />
:a = [1 4; 7 2];</small></tt></div><br />
| Macierze definiujemy używając odpowiedniej funkcji<br />
<div style="line-height: 1"><tt><small><br />
:a = numpy.array([ [1,4], [7,2] ])<br />
:a = numpy.mat('[1 4; 7 2]')</small></tt></div><br />
|- valign="top"<br />
| Indeksy macierzy piszemy w nawiasach okrągłych. <br />
:<tt>a(1,3,5:7)</tt><br />
| Indeksy macierzy piszemy w nawiasach kwadratowych.<br />
:<tt>a[1,3,5:7]</tt><br />
|- valign="top"<br />
| Pierwszy indeks macierzy na numer 1.<br />
| Pierwszy indeks macierzy na numer 0.<br />
|- valign="top"<br />
| Działanie wycinka: elementy liczone od 1, ostatni zawiera się w wycinku.<br />
<div style="line-height: 1"><tt><small><br />
:>> a = linspace(1,10,10)<br />
:a = <br><br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;10<br />
:>> a(1:5)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br />
:>> a(5:end)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;10</small></tt></div><br />
| Działanie wycinka: elementy liczone od 0, ostatni element wpisany liczbowo nie zawiera się w wycinku.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.linspace(1,10,10)<br />
:>>> a<br><br />
:array([&nbsp;&nbsp;1.,&nbsp;&nbsp;&nbsp;2.,&nbsp;&nbsp;&nbsp;3.,&nbsp;&nbsp;&nbsp;4.,&nbsp;&nbsp;&nbsp;5.,&nbsp;&nbsp;&nbsp;6.,&nbsp;&nbsp;&nbsp;7.,&nbsp;&nbsp;&nbsp;8.,&nbsp;&nbsp;&nbsp;9.,&nbsp;&nbsp;10.])<br />
:>>> a[1:5] # czyli od elementu 2 do 5 (element 6 o indeksie 5 wpisany liczbowo)<br />
:array([ 2.,&nbsp;&nbsp;3.,&nbsp;&nbsp;4.,&nbsp;&nbsp;5.])<br />
:>>> a[5:] &nbsp;# czyli od elementu 6 do ostatniego (nie określonego liczbowo)<br />
:array([&nbsp;&nbsp;6.,&nbsp;&nbsp;&nbsp;7.,&nbsp;&nbsp;&nbsp;8.,&nbsp;&nbsp;&nbsp;9.,&nbsp;&nbsp;10.])</small></tt></div><br />
|- valign="top"<br />
| Łatwe tworzenie wektorów wartości z pewnego zakresu:<br />
<div style="line-height: 1"><tt><small><br />
:>> a = 1:5<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br />
:>> a = linspace(1,5,5)<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5</small></tt></div><br />
| Łatwe tworzenie wektorów wartości z pewnego zakresu z użyciem pakietu NumPy:<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.r_[1:6]<br />
:>>> a<br />
:array([1, 2, 3, 4, 5])<br />
:>>> a = numpy.linspace(1,5,5)<br />
:>>> a<br />
:array([ 1.,&nbsp;&nbsp;2.,&nbsp;&nbsp;3.,&nbsp;&nbsp;4.,&nbsp;&nbsp;5.])</small></tt></div><br />
|- valign = "top"<br />
| Macierze zachowują wszystkie swoje wymiary.<br />
| Macierze mogą zostac &bdquo;spłaszczone&rdquo; do wektorów posiadających tylko długość.<br />
|- valign = "top"<br />
| Wymiary macierzy liczą się od lewej do prawej.<br />
<div style="line-height: 1"><tt><small><br />
:>>&nbsp;c=1:8<br />
:c&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8<br />
:>>&nbsp;cr=reshape(c,[2,2,2])<br />
:cr(:,:,1)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4<br />
:cr(:,:,2)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8<br />
:>>&nbsp;cr(:,:,1)<br />
:ans&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4<br />
:>>&nbsp;cr(1,:,:)<br />
:ans(:,:,1)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:ans(:,:,2)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7</small></tt></div><br />
| Wymiary macierzy liczą się od prawej do lewej.<br />
<div style="line-height: 1"><tt><small><br />
:>>>&nbsp;c=numpy.array(range(1,9))<br />
:>>>&nbsp;c<br />
:array([1,&nbsp;2,&nbsp;3,&nbsp;4,&nbsp;5,&nbsp;6,&nbsp;7,&nbsp;8])<br />
:>>>&nbsp;cr=numpy.reshape(c,(2,2,2))<br />
:>>>&nbsp;cr<br />
:array([[[1,&nbsp;2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[3,&nbsp;4]],<br />
:&nbsp;<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[[5,&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[7,&nbsp;8]]])<br />
:>>>&nbsp;cr[0]<br />
:array([[1,&nbsp;2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[3,&nbsp;4]])<br />
:>>>&nbsp;cr[:,:,0]<br />
:array([[1,&nbsp;3],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[5,&nbsp;7]])</small></tt></div><br />
|- valign = "top"<br />
| Niektóre operatory różnią się od Pythonowych. Niektóre przykłady:<br />
* Potęgowanie: <tt>^</tt><br />
* Nie równa się: <tt>~=</tt><br />
* Dzielenie modulo: <tt>mod(x,y)</tt><br />
* Operatory logiczne &bdquo;i&rdquo;, &bdquo;lub&rdquo;, &bdquo;nie&rdquo;: <tt>& | ~</tt><br />
* Komentarz: <tt>%</tt><br />
| Niektóre operatory różnią się od Matlabowych. Niektóre przykłady:<br />
* Potęgowanie: <tt>**</tt><br />
* Nie równa się: <tt>!=</tt><br />
* Dzielenie modulo: <tt>x % y</tt><br />
* Operatory logiczne &bdquo;i&rdquo;, &bdquo;lub&rdquo;, &bdquo;nie&rdquo;: <tt>and or not</tt><br />
* Komentarz: <tt>#</tt><br />
|- valign="top"<br />
| Przypisanie zmiennych do siebie powoduje skopiowanie ich zawartości.<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 2 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = a<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b(2) = 0<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> a<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3</small></tt></div><br />
| Przypisanie zmiennych do siebie powoduje wyłącznie powstanie drugiej nazwy tego samego obiektu. Zawartość nie jest kopiowana.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = [1,2,3]<br />
:>>> b = a<br />
:>>> b[1] = 0<br />
:>>> b<br />
:[1, 0, 3]<br />
:>>> a<br />
:[1, 0, 3]</small></tt></div><br />
|- valign="top"<br />
| Liczby zespolone są wbudowane w działanie pakietu<br />
<div style="line-height: 1"><tt><small><br />
:>> (-1)^0.5<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;0.0000 + 1.0000i</small></tt></div><br />
|Chcąc użyć liczb zespolonych musimy to explicite zaznaczyć.<br />
<div style="line-height: 1"><tt><small><br />
:>>> (-1)**0.5<br />
:<br><br />
:<font color="red">Traceback (most recent call last):<br />
:&nbsp;&nbsp;File "<pyshell#37>", line 1, in <module><br />
:&nbsp;&nbsp;&nbsp;&nbsp;(-1)**0.5<br />
:ValueError: negative number cannot be raised to a fractional power</font></small></tt></div><br />
ale<br/><br />
<div style="line-height: 1"><tt><small><br />
:>>> (-1+0j)**0.5<br />
:<br><br />
:(6.1230317691118863e-17+1j)</small></tt></div><br />
|- valign="top"<br />
| Niektóre sytuacje wyjątkowe nie powodują przerwania obliczeń, dając użytkownikowi informację o możliwym błędzie w postaci specjalnej wartości.<br />
<div style="line-height: 1"><tt><small> <br />
:>> 1/0<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;Inf</small></tt></div><br />
a także<br />
<div style="line-height: 1"><tt><small> <br />
:>> a = ones(1,3)<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
:>> b = [1 0 2]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br />
:>> a./b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;1.0000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Inf&nbsp;&nbsp;&nbsp;&nbsp;0.5000</small></tt></div><br />
| W &bdquo;czystym&rdquo; Pythonie użytkownik musi sam zadbać o obsługę wszystkich sytuacji wyjątkowych.<br />
<div style="line-height: 1"><tt><small> <br />
:>>> 1/0<br />
:<br><br />
:<font color="red">Traceback (most recent call last):<br />
:&nbsp;&nbsp;File "<pyshell#0>", line 1, in <module><br />
:&nbsp;&nbsp;&nbsp;&nbsp;1/0<br />
:ZeroDivisionError: integer division or modulo by zero</font></small></tt></div><br />
Macierze z modułu NumPy zachowują się podobnie do macierzy Matlaba:<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.ones(3)<br />
:>>> a<br />
:array([ 1.,&nbsp;&nbsp;1.,&nbsp;&nbsp;1.])<br />
:>>> b = numpy.array([1.,0.,2.])<br />
:>>> b<br />
:array([ 1.,&nbsp;&nbsp;0.,&nbsp;&nbsp;2.])<br />
:>>> a/b<br />
:array([ 1. ,&nbsp;&nbsp;inf,&nbsp;&nbsp;0.5])</small></tt></div><br />
|- valign="top"<br />
| Ponieważ każda zmienna numeryczna jest macierzą, podstawowe operatory arytmetyczne opisują działania na macierzach. W szczególności operator mnożenia realizuje mnożenie macierzy:<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = [2;-1]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1<br />
:>> a * b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1<br />
:>> b * a<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1&nbsp;&nbsp;&nbsp;&nbsp;-3</small></tt></div><br />
Aby zrealizować operację osobno dla każdej pary elementów macierzy/wektorów, stosujemy operatory arytmetyczne z kropką (wymiary macierzy muszą być zgodne):<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = [2 1]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
:>> a .* b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b .* a<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3</small></tt></div><br />
| Operatory arytmetyczne zastosowane do macierzy wykonują zadane operacje osobno dla wszystkich par elementów tych macierzy. Tak więc w szczególności operator mnożenia w Pythonie odpowiada operatorowi &bdquo;mnożenia z kropką&rdquo; w Matlabie i nie realizuje mnożenia macierzowego.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.array([1,3])<br />
:>>> a<br />
:array([1, 3])<br />
:>>> b = numpy.array([[2],[-1]])<br />
:>>> b<br />
:array([[ 2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1]])<br />
:>>> a * b<br />
:array([[ 2,&nbsp;&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1, -3]])<br />
:>>> b * a<br />
:array([[ 2,&nbsp;&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1, -3]])<br />
:<br><br />
:<br><br />
:<br><br />
:<br><br />
:<br><br />
:>>> a = numpy.array([1,3])<br />
:>>> a<br />
:array([1, 3])<br />
:>>> b = numpy.array([2,1])<br />
:>>> b<br />
:array([2, 1])<br />
:>>> a*b<br />
:array([2, 3])<br />
:>>> b*a<br />
:array([2, 3])</small></tt></div><br />
|- valign="top"<br />
| Wywołanie pomocy dla obiektu <tt>nazwa</tt>:<br />
<div style="line-height: 1"><tt><small><br />
:help nazwa</small></tt></div><br />
| Wywołanie pomocy dla obiektu <tt>nazwa</tt>:<br />
<div style="line-height: 1"><tt><small><br />
:help(nazwa)</small></tt></div><br />
|- valign="top"<br />
| Funkcje matematyczne są wbudowane.<br />
Listę funkcji elementarnych można zobaczyć pisząc:<br />
<div style="line-height: 1"><tt><small><br />
:help elfun</small></tt></div><br />
Bardziej zaawansowane funkcje można zobaczyć pisząc:<br />
<div style="line-height: 1"><tt><small><br />
:help specfun</small></tt></div><br />
<div style="line-height: 1"><tt><small><br />
:help elmat</small></tt></div><br />
| Funkcje matematyczne są dostępne po załadowaniu modułu NumPy (lub innych,np. math).<br />
|}<br />
<br />
Oczywiście powyższa tabela nie obejmuje wszystkich możliwych różnic, a tylko te najważniejsze, które mogą sprawić kłopot na początku pracy. Nie wydaje się jednak, aby miały one zasadnicze znaczenie dla sprawnego pisania programów w obu omawianych tu językach.<br />
<br />
==Piszemy program w Matlabie==<br />
<br />
Z tego co już zostało tutaj powiedziane widzimy, że osoba, która umie napisać program w Pythonie, nie powinna mieć większego kłopotu z napisaniem go również w Matlabie. Należy tylko pamiętać o pewnych różnicach języków i składni, które jednak zasadniczo, po nabyciu pewnej wprawy, nie sprawiają większych trudności.<br />
<br />
Aby sprawdzić działanie obu języków w praktyce, napiszemy kilka programów realizujących te same założenia w Pythonie i w Matlabie.<br />
<br />
===Drobne różnice składniowe===<br />
*Pisząc w języku Matlab, warto jest używać wcięć, nie są jednak konieczne. Koniec bloku zaznacza się, pisząc <tt>end</tt>.<br />
*Nie używamy dwukropków na końcu instrukcji zaczynających blok np. <tt>for</tt>, czy <tt>if</tt>.<br />
*Wyrażenie warunkowe:<br />
<br />
**<tt>if</tt><br />
<source lang="Matlab"><br />
if a < 30<br />
disp('small')<br />
elseif a < 80<br />
disp('medium')<br />
else<br />
disp('large')<br />
end<br />
</source><br />
**<tt>switch</tt><br />
<source lang="Matlab"><br />
[dayNum, dayString] = weekday(date, 'long', 'en_US');<br />
<br />
switch dayString<br />
case 'Monday'<br />
disp('Start of the work week')<br />
case 'Tuesday'<br />
disp('Day 2')<br />
case 'Wednesday'<br />
disp('Day 3')<br />
case 'Thursday'<br />
disp('Day 4')<br />
case 'Friday'<br />
disp('Last day of the work week')<br />
otherwise<br />
disp('Weekend!')<br />
end<br />
</source><br />
* Pętle<br />
<br />
**<tt>for</tt><br />
<source lang="Matlab"><br />
for i = 1:m<br />
for j = 1:n<br />
H(i,j) = 1/(i+j);<br />
end<br />
end<br />
</source><br />
Pętla <tt>for</tt>, tak samo jak w Pythonie, wymaga sekwencji. Sekwencja może być pewnym wektorem. Można też ją utworzyć w następujący sposób:<br />
<source lang="Matlab"><br />
poczatek:krok:koniec<br />
</source><br />
albo<br />
<source lang="Matlab"><br />
poczatek:koniec<br />
</source><br />
(wtedy <tt>krok = 1</tt>). Wynikiem jest wektor wartości od <tt>poczatek</tt> do <tt>koniec</tt> o kroku <tt>krok</tt>. Jest to analog <tt>range</tt> oraz <tt>numpy.arange</tt>.<br />
**<tt>while</tt><br />
<source lang="Matlab"><br />
n = 1;<br />
nFactorial = 1;<br />
while nFactorial < 1e100<br />
n = n + 1;<br />
nFactorial = nFactorial * n;<br />
end<br />
</source><br />
*Funkcje<br />
<br />
**nagłówek rozpoczyna się słowem <tt>function</tt>, na przykład:<br />
<source lang="Matlab"><br />
function [R,E,V]=R_po(t,t_rec,t_in,U_SE,t_mem,R_0,E_0,V_0,t_0,u,dt)<br />
</source><br />
**Zwykle zachowujemy w oddzielnych plikach o nazwie takiej samej, jak funkcja.<br />
<br />
===Rysujemy wykres funkcji (przykład)===<br />
<br />
Napiszmy program rysujący wykres funkcji kwadratowej na odcinku od &minus;5 do 5.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
x=linspace(-5,5,11);<br />
y=x.^2;<br />
plot(x,y,'r-');<br />
<br />
<br />
</source><br />
| <br />
| <source lang='python'><br />
import numpy<br />
import pylab<br />
x=numpy.linspace(-5,5,11)<br />
y=x**2<br />
pylab.plot(x,y,'r-')<br />
pylab.show()</source><br />
|}<br />
<br />
Zasadnicze różnice: operator potęgowania, użycie operatora z kropką, konieczność importowania modułów numerycznego i graficznego, osobna procedura do pokazania gotowego wykresu na ekranie.<br />
<br />
<br />
<br />
Narysujmy bardziej dokładnie wykres funkcji sin(''x'')/''x''.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
x=linspace(-5,5,101);<br />
y=sin(x)./x;<br />
plot(x,y);</source><br />
| <br />
| <source lang='python'><br />
import numpy as np<br />
import pylab as p<br />
x=np.linspace(-5,5,101)<br />
y=np.sin(x)/x<br />
p.plot(x,y)<br />
p.show()</source><br />
|}<br />
<br />
===Zliczamy liczbę liter===<br />
<br />
Narysujmy histogram liczebności poszczególnych liter z pierwszej księgi &bdquo;Pana Tadeusza&rdquo; A. Mickiewicza. Tekst znajdziemy [http://brain.fuw.edu.pl/edu-wiki/images/5/5b/PanTadeuszX1.txt tu]. Ściągamy plik i zapisujemy w swoim katalogu.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
fid=fopen('PanTadeuszX1.txt','rb');<br />
tekst=fread(fid,'uchar');<br />
fclose(fid);<br />
<br />
hist(tekst,min(tekst):max(tekst));<br />
xlim([double('a')-1 double('z')+1]);<br />
<br />
<br />
<br />
set(gca,'XTick',double('a'):double('z'));<br />
set(gca,'XTickLabel',['a':'z']');<br />
</source><br />
| <br />
| <source lang='python'><br />
import numpy as np<br />
import pylab as p<br />
<br />
tekst=np.fromfile('PanTadeuszX1.txt','uint8')<br />
<br />
<br />
p.hist(tekst,max(tekst)-min(tekst)+1)<br />
p.xlim(ord('a')-1,ord('z')+1)<br />
achars=[]<br />
for code in range(ord('a'),ord('z')+1):<br />
achars.append(chr(code))<br />
p.xticks(range(ord('a'),ord('z')+1),achars)<br />
<br />
p.show()<br />
</source><br />
|}<br />
<br />
Wykorzystaliśmy tutaj fakt, że litery alfabetu angielskiego są w kodzie ASCII ułożone bezpośrednio po sobie, alfabetycznie i w kolejności rosnącej. Gdybyśmy w naszym histogramie chcieli uwzględnić również polskie litery, należałoby kolejność słupków histogramu wybrać ręcznie, zgodnie z kolejnością w alfabecie polskim. Histogram musimy utworzyć z wybranych wartości (wysokości słupków) ustawionych w pożądanej kolejności. Dodatkową trudnością jest fakt, że stosowane są różne sposoby kodowania polskich liter (czyli zamiany liter na odpowiadające im wartości liczbowe). Plik tekstowy zastosowany w przykładzie wykorzystuje kodowanie &bdquo;Windows-1250&rdquo;, a Matlab domyślnie koduje napisy w standardzie Unicode. Nasz program powinien uwzględniać te fakty.<br />
<br />
==Ćwiczenia==<br />
{{Solution|title=Zadanie 1|text=<br />
[[Plik:Albrecht_Durer_Magic_Square.jpg|300px|thumb|right|<figure id="fig:1"/> Szczegół z miedziorytu Albrechta Durera zatytułowanego Melancholia I, 1514 r.]]<br />
<br />
Utwórz w Matlabie macierz z liczbami magicznego kwadratu i policz sumę elementów w każdym wierszu, kolumnie i obu przekątnych.<br />
Dodatkowo, możesz policzyć sumę liczb w narożnikach, każdej ćwiartce kwadratu i w czterech środkowych polach.<br />
<br />
Wskazówki:<br />
* W Matlabie sumę elementów macierzy zwraca funkcja <tt>sum</tt> (sprawdź jak ta funkcja działa).<br />
* Transpozycję macierzy A uzyskuje się za pomocą apostrofa tj. A'.<br />
* Elementy na przekątnej macierzy zwraca funkcja <tt>diag</tt>.<br />
* Odwracanie macierzy z lewa na prawo uzyskuje się za pomocą funkcji <tt>fliplr</tt>.<br />
* Do elementów macierzy można też się odwoływać za pomocą pojedynczego indeksu. W tej sytuacji, macierz odpowiada pojedynczej kolumnie złożonej z kolumn oryginalnej macierzy. Np. dla magicznego kwadratu A(8) odwołuje się do wartości 15 w elemencie macierzy A(4,2).<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 2|text=<br />
<br />
Utwórz w Matlabie program, który tworzy macierz z liczbami magicznego kwadratu dla dowolnego n i zwraca sumę elementów w każdym wierszu, kolumnie i obu przekątnych.<br />
<br />
Wskazówki:<br />
* W Matlabie kwadrat magiczny można wygenerować funkcją <tt>magic</tt>.<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 3|text=<br />
[[Plik:Frequency_axis.jpg|300px|thumb|right|<figure id="fig:2"/> Oś częstości zwracana przez funkcje <tt>fft</tt>. Pierwszy element zawiera częstość zerową, następnie częstości dodatnie do częstości Nyquista, a następnie częstości ujemne. Funkcja <tt>fftshift</tt> zamienia ze sobą lewą i prawą połowę osi pozostawiając częstość zerową w centrum widma.]]<br />
Napisz funkcję, której dostaje argumenty w postaci sygnału i częstości próbkowania, i przedstawia na rysunkach: dyskretną transformatę Fouriera (wielkość i przesunięcie fazowe), periodogram (kwadrat modułu transformaty Fouriera), gęstość widmową mocy oraz numeryczną weryfikację twierdzenia Parsevala.<br />
Następnie wygeneruj sygnał będący sumą dwóch sinusów o częstościach 10 i 40 Hz, długości trwania 2 s i częstości próbkowania 100 Hz i sprawdź działanie funkcji.<br />
<br />
Wskazówki:<br />
* W Matlabie dyskretną transformatę Fouriera oblicza funkcja <tt>fft</tt>.<br />
* Metody szacowania gęstości widmowej mocy można uzyskać pisząc <tt>help spectrum</tt>.<br />
* Przypomnienie: twierdzenie Parsevala mówi, że całka z gęstości widmowej mocy jest miarą całkowitej energii sygnału. Energię sygnału obliczamy jako sumę kwadratów amplitud sygnału.<br />
<br />
<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 4|text=<br />
[[Plik:Binary_tree.svg|thumb|<figure id="fig:3"/> Przykład drzewa binarnego]]Drzewo binarne jest drzewem, w którym stopień każdego wierzchołka (liczba połączeń danego wierzchołka) nie jest wyższy niż 3. Drzewo takie przedstawione jest na rysunku <xr id="fig:3"/>. Drzewo takie można wygodnie reprezentować w tablicy &mdash; jeżeli nadamy wierzchołkowi ''i''-ty element tablicy, jego lewy syn będzie miał indeks 2''i''+1, a prawy 2''i''+2 w przypadku języków, w których wektory numerowane są od zera. <br />
<br />
Jaka będzie reguła reprezentacji drzewa binarnego za pomocą wektora w językach, w których wektory indeksowane są od 1? Jak zapiszesz reprezentację drzewa z rysunku <xr id="fig:3"/> w języku Matlab?<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 5 (trudniejsze)|text=<br />
[[Plik:Histogram_PT1PL.gif|300px|thumb|right|]]Napisz w Matlabie program zliczający ilości liter I księgi &bdquo;Pana Tadeusza&rdquo; z uwzględnieniem również polskich liter.<br />
<br />
Wskazówka:<br />
* Proponowany tekst jest zapisany w kodowaniu &bdquo;Windows-1250&rdquo;.<br />
* W Matlabie jest dostępna funkcja zamieniająca wybrane kodowanie tekstu na Unicode, na przykład:<br />
::<tt>tekst_Unicode = native2unicode(tekst_Win1250,'windows-1250');</tt><br />
* Przypisanie wyniku funkcji <tt>hist</tt> do jakiejś zmiennej anuluje rysowanie histogramu. W zamian, w zmiennej tej zapisane zostaną obliczone wysokości słupków.<br />
* Kolejność polskiego alfabetu (wzbogaconego o litery dodatkowe &bdquo;q&rdquo;, &bdquo;v&rdquo; i &bdquo;x&rdquo;) to:<br />
::aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż<br />
* Aby narysować histogram dla wcześniej wyliczonych wysokości słupków użyj funkcji <tt>bar</tt>.<br />
* Opisy na osi wykresu (ich położenie i tekst) zmienić możemy używając instrukcji:<br />
::<tt>set(gca,'XTick',[1 2 3]);</tt><br />
::<tt>set(gca,'XTickLabel',['abc']')</tt><br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 6|text=<br />
[[Plik:matsurf.png|300px|thumb|]]Zbadaj przebieg zależności <math>\sin(r)/r</math> dla ''r'' będącego odległością od środka biegunowego układu współrzędnych na płaszczyźnie w zakresie &minus;10 < ''x'' < 10, &minus;10 < ''y'' < 10. Narysuj wykresy używając funkcji Matlaba <tt>mesh</tt>, <tt>surf</tt>, <tt>pcolor</tt> i <tt>contour</tt>.<br />
Dlaczego na wykresach brakuje punktu dla ''r'' = 0? Co możemy zrobić, aby wykres był kompletny?<br />
<br />
Wskazówka:<br />
* Zapoznaj się z działaniem następujących funkcji:<br />
::<tt>meshgrid</tt> (co zawierają macierze zwracane przez tę funkcję?);<br />
::<tt>shading</tt>, <tt>hidden</tt>, <tt>colormap</tt>;<br />
::<tt>subplot</tt>, <tt>xlabel</tt>, <tt>ylabel</tt>, <tt>title</tt>.<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 7|text=<br />
[[Plik:matkula.png|300px|thumb|]]Funkcje <tt>mesh</tt> czy <tt>surf</tt> służą w ogólności do rysowania obiektów trójwymiarowych. Używając ich narysuj sferę o promieniu 1.<br />
<br />
Wskazówka:<br />
* Przypomnij sobie jak opisana jest sfera w sferycznym układzie współrzędnych, a w szczególności jak transformują się współrzędne punktów sfery z układu sferycznego (''r'',&theta;,&phi;) do układu kartezjańskiego (''x'',''y'',''z'').<br />
* Aby kula nie wyglądała jak elipsoida należy skorzystać z polecenia <tt>axis equal</tt>, które ujednolica rozmiar rysunku wzdłuż osi ''x'', ''y'' i ''z''.<br />
<br />
<!--Jaką figurę opisuje układ równań<br />
::<math>x=(R+r\cos\phi)\cos\theta</math><br />
::<math>y=(R+r\cos\phi)\sin\theta</math><br />
::<math>z=r\sin\phi</math><br />
--><br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 8|text=<br />
[[Plik:Rys_mapka.png|300px|thumb|]]Matlab umożliwia przechowywanie zmiennych w plikach własnego formatu .MAT zawierających wszystkie niezbędne informacje o typach zapisanych zmiennych i oczywiście ich wartościach. Do zapisu plików służy polecenie <tt>save</tt>, a do ich wczytania polecenie <tt>load</tt>.<br />
<br />
<br />
Plik ([[Plik:Book.tar.gz]]) zawiera strukturę, która opisuje dekompozycję pewnego sygnału na struktury składowe &mdash; &bdquo;atomy&rdquo; za pomocą algorytmu MP. Pobierz ten plik, rozpakuj go, a jego zawartość wczytaj do Matlaba i narysuj wynik dekompozycji (wraz ze źródłowymi sygnałami) zawarty w tym pliku. Napisz funkcję rysującą wyniki dla danego kanału i wybranego atomu uwzględniającą informacje zawarte we wczytanej strukturze.<br />
<br />
{{clear}}<br />
}}<br />
<br />
==Debugger w Matlabie==<br />
<br />
Środowisko programowania w Matlabie dostarcza bardzo użytecznego narzędzia pomagającego śledzić działanie programów i niezwykle ułatwiającego wyszukiwanie błędów. Narzędzie to nazywa się z angielska ''debuggerem'' (czyli &bdquo;odrobaczaczem&rdquo; lub &bdquo;odpluskwiaczem&rdquo;). <br />
<br />
Zasada działania debuggera polega na tym, że możemy zatrzymać wykonujący się program w dowolnym miejscu, nie przerywając wykonania całkowicie, ale tylko chwilowo je wstrzymując. Robimy to przez wcześniejsze wstawienie w tekście programu (który musi być widoczny w oknie Edytora) specjalnych ''punktów zatrzymania'' (ang. ''breakpoints''). Pokażemy to na przykładzie prostego programu. Na rysunku poniżej widzimy fragment okna Edytora Matlaba z widocznym interesującym nas fragmentem programu. <br />
<br />
[[Plik:matldeb1.gif]]<br />
<br />
Załóżmy, że chcemy zobaczyć czy pętla w wierszach 3-5 programu prawidłowo sumuje wartości. W tym celu w wierszu 4 umieszczamy punkt zatrzymania, ustawiając kursor w edytorze na tym wierszu i używając guzika z paska poleceń:<br />
<br />
[[Plik:matldeb2.gif]]<br />
<br />
Po naciśnięciu guzika &bdquo;Set/clear breakpoint&rdquo; (&bdquo;Ustaw/skasuj punkt zatrzymania&rdquo;) po lewej stronie wiersza 4 pojawia się czerwona kropka oznaczająca, że w tym miejscu program zostanie wstrzymany.<br />
<br />
[[Plik:matldeb3.gif]]<br />
<br />
Pozostaje nam teraz uruchomić nasz program. Można to zrobić wpisując odpowiednie polecenie w oknie Poleceń Matlaba (''Command window'') lub naciskając guzik na pasku poleceń:<br />
<br />
[[Plik:matldeb4.gif]]<br />
<br />
Program wykona się aż do napotkania punktu zatrzymania. Wtedy wykonanie zostaje przerwane i w oknie Poleceń zauważymy, że znak zachęty ma dopisaną literę &bdquo;K&rdquo;. Zielona strzałka z lewej strony wiersza programu wskazuje jaka komenda programu oczekuje na wykonanie. W oknie Obszar roboczy (''Workspace'') widzimy wartości wszystkich zmiennych naszego programu, możemy też w oknie Poleceń wpisać dowolne wyrażenie (np. <tt>suma*3</tt>) i zobaczyć jego wynik. Od tej chwili możemy też wykonywać nasz program krok po kroku naciskając odpowiedni guzik z paska poleceń albo wykonać program do końca (lub następnego punktu zatrzymania). <br />
<br />
[[Plik:matldeb5.gif]]<br />
<br />
==Informacje dodatkowe==<br />
<br />
Matlab wyposażony jest w tzw. ''toolboxy'' czyli pakiety procedur powiązanych tematycznie do rozwiązywania problemów z jakiejś dziedziny. Pakiety takie można zakupić u producenta (The MathWorks Inc.); aby sprawdzić jakie są aktualnie zainstalowane, wywołujemy polecenie Matlaba <tt>ver</tt>. W rezultacie dostajemy listę podobną do prezentowanej poniżej.<br />
<br />
<div style="line-height: 1"><tt><small><br />
>> ver<br />
-------------------------------------------------------------------------------------<br />
MATLAB Version 7.11.0.584 (R2010b)<br />
MATLAB License Number: 123456<br />
Operating System: Microsoft Windows 7 Version 6.1 (Build 7600)<br />
Java VM Version: Java 1.6.0_17-b04 with Sun Microsystems Inc. Java HotSpot(TM) Client VM mixed mode<br />
-------------------------------------------------------------------------------------<br />
MATLAB Version 7.11 (R2010b)<br />
Simulink Version 7.6 (R2010b)<br />
Bioinformatics Toolbox Version 3.6 (R2010b)<br />
Communications Blockset Version 5.0 (R2010b)<br />
Communications Toolbox Version 4.6 (R2010b)<br />
Control System Toolbox Version 9.0 (R2010b)<br />
Curve Fitting Toolbox Version 3.0 (R2010b)<br />
Data Acquisition Toolbox Version 2.17 (R2010b)<br />
Database Toolbox Version 3.8 (R2010b)<br />
Filter Design Toolbox Version 4.7.1 (R2010b)<br />
Financial Toolbox Version 3.8 (R2010b)<br />
Fixed-Point Toolbox Version 3.2 (R2010b)<br />
Global Optimization Toolbox Version 3.1 (R2010b)<br />
Image Acquisition Toolbox Version 4.0 (R2010b)<br />
Image Processing Toolbox Version 7.1 (R2010b)<br />
Instrument Control Toolbox Version 2.11 (R2010b)<br />
MATLAB Builder EX Version 1.3 (R2010b)<br />
MATLAB Builder NE Version 3.2 (R2010b)<br />
MATLAB Compiler Version 4.14 (R2010b)<br />
Mapping Toolbox Version 3.2 (R2010b)<br />
Neural Network Toolbox Version 7.0 (R2010b)<br />
Optimization Toolbox Version 5.1 (R2010b)<br />
Parallel Computing Toolbox Version 5.0 (R2010b)<br />
Parallel Computing Toolbox Version 5.0 (R2010b)<br />
Partial Differential Equation Toolbox Version 1.0.17 (R2010b)<br />
Real-Time Workshop Version 7.6 (R2010b)<br />
Robust Control Toolbox Version 3.5 (R2010b)<br />
Signal Processing Blockset Version 7.1 (R2010b)<br />
Signal Processing Toolbox Version 6.14 (R2010b)<br />
Simulink Control Design Version 3.2 (R2010b)<br />
Simulink Design Optimization Version 1.2 (R2010b)<br />
Simulink Fixed Point Version 6.4 (R2010b)<br />
Statistics Toolbox Version 7.4 (R2010b)<br />
Symbolic Math Toolbox Version 5.5 (R2010b)<br />
System Identification Toolbox Version 7.4.1 (R2010b)<br />
Wavelet Toolbox Version 4.6 (R2010b)<br />
</small></tt></div><br />
<br />
Oczywiście możemy sami dopisywać własne procedury, a także korzystać z oprogramowania udostępnionego przez innych twórców. Jako przykład mogą tu posłużyć pakiety do analizy danych biomedycznych [http://sccn.ucsd.edu/eeglab/ EEGLAB] czy obrazów MRI [http://www.fil.ion.ucl.ac.uk/spm/ SPM] rozwijane przez niezależne grupy obejmujące badaczy i programistów. Również procedury [http://octave.sourceforge.net/ Octave-Forge] tworzone w ramach projektu GNU Octave mogą współpracować wymiennie z Matlabem.<br />
<br />
Python również pozwala na korzystanie z pisanych dla niego pakietów oprogramowania. Musimy je jednak odszukać, ściągnąć i zainstalować sami. W wersji podstawowej będą to:<br />
* python &mdash; podstawowy interpreter/kompilator języka Python;<br />
* numpy &mdash; biblioteka funkcji matematycznych i obliczeniowych;<br />
* scipy &mdash; zestaw bardziej zaawansowanych procedur numerycznych;<br />
* matplotlib &mdash; procedury graficzne do sporządzania wykresów i wizualizacji wyników.<br />
:(Uwaga: Mając zainstalowane bilioteki numpy, scipy i matplotlib możemy w programie używać podstawowych funkcji wszystkich tych modułów jedną komendą: <tt>import&nbsp;pylab</tt>.)<br />
<br />
[http://pypi.python.org/pypi?%3Aaction=index Lista projektów programistycznych w Pythonie] obejmuje różnorodne tematy i jest duża szansa znalezienia czegoś dla siebie. <br />
<br />
Warto też zwrócić uwagę na pakiet [http://mlabwrap.sourceforge.net/ mlabwrap], który pozwala korzystać z Matlaba (musi być zainstalowany w systemie) jakby był on biblioteką Pythona (z pewnymi ograniczeniami, ale wciąż rozwijany).<br />
<br />
<br />
[[Laboratorium_EEG]]/Wprowadzenie_do_Matlaba</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG/Wprowadzenie_do_Matlaba&diff=4818Laboratorium EEG/Wprowadzenie do Matlaba2016-03-01T12:46:36Z<p>Tspus: /* Ćwiczenia */</p>
<hr />
<div>[[Laboratorium_EEG]]/Wprowadzenie_do_Matlaba<br />
<br />
<br />
==Wprowadzenie==<br />
[[Plik:Matlab_splash.png|200px|thumb|right|Okno powitalne Matlaba]]<br />
Najkrócej można określić Matlab jako pakiet oprogramowania do obliczeń matematycznych wyprodukowany w firmie [http://www.mathworks.com/ MathWorks]. Jest to w istocie zintegrowane ''środowisko obliczeniowe'', w którym mamy do dyspozycji:<br />
* własny język programowania wysokiego poziomu, dający możliwość interaktywnego programowania;<br />
* środowisko zaprojektowane do pracy z macierzami numerycznymi;<br />
* specjalistyczne zestawy procedur obliczeniowych z różnych dziedzin, możliwość zmiany i dodawania własnych funkcji;<br />
* bogate możliwości graficznej prezentacji wyników 2D/3D oraz projektowania własnych interfejsów graficznych (GUI);<br />
* możliwość włączania programów napisanych w innych językach (C, C++, Fortran, Java);<br />
* okienkowo-zorientowane środowiska graficzne do uruchamiania algorytmów na podstawie ich schematów blokowych (np. Simulink);<br />
* wygodne operacje wejścia/wyjścia dla wielu typów danych (np. wav, avi, DICOM)<br />
* zintegrowane interaktywne narzędzia programistyczne: edytor i debugger.<br />
<br />
Dzięki tym możliwościom pakiet [http://www.mathworks.com/products/matlab/ Matlab] (mimo swej relatywnie wysokiej ceny) stał się bardzo popularnym narzędziem obliczeniowym, szczególnie w dziedzinie analizy danych biomedycznych. Pozwala on na dość szybkie pisanie złożonych programów obliczeniowych, pozwalając skupić się na rozwiązywaniu problemu, a nie na samym kodowaniu programu. Warto więc się z nim zapoznać, gdyż jest duża szansa natrafienia na Matlaba w trakcie kariery zawodowej absolwentów naszej specjalności.<br />
<br />
Warto również dodać, że osoby nie dysponujące dostępem do Matlaba, chcące zapoznać się z programowaniem w tym języku lub używać posiadane gotowe programy mogą skorzystać z darmowego pakietu [http://www.gnu.org/software/octave/ GNU Octave]. Język Octave jest bardzo podobny do Matlabowego i większość programów może być bez zmian przenoszona między nimi.<br />
<br />
==Matlab a Python==<br />
<br />
Ponieważ nasz kurs programowania jest oparty zasadniczo o język Python, właściwe będzie porównanie Pythona i Matlaba. W trakcie nauki programowania w Pythonie, wykorzystywaliśmy interfejs użytkownika, pozwalający nie tylko na uruchamianie programów, ale też na pracę interaktywną. Takim interfejsem jest np. stosowany przez nas <tt>idle</tt>. W Matlabie podobny interfejs jest wbudowany w program &mdash; po uruchomieniu programu dostajemy otwarte okno poleceń.<br />
[[Plik:Idle_and_Matlab.png|800px|thumb|center|Okna poleceń: po lewej Pythona (Idle), po prawej Matlaba]]<br />
Jak widać, w obu przypadkach sytuacja jest podobna. Możemy zacząć pracę w sesji interaktywnej wpisując na bieżąco polecenia, które są od razu interpretowane i wykonywane. Wyniki są natychmiast prezentowane na ekranie. Każdy z pakietów daje nam również możliwość napisania programu w osobnym edytorze tekstu, zapisania go na dysku i uruchomienia w dogodnym dla nas momencie.<br />
<br />
Podobieństw między Matlabem a Pythonem jest dużo więcej. Oba języki są językami wysokiego poziomu, co oznacza, że dużą część szczegółów implementacji naszego kodu możemy pozostawić w gestii stosowanego pakietu, pisząc programy w sposób bardziej przypominający ogólny algorytm opisany w sposób zrozumiały dla człowieka, a nie dopasowany do konkretnego komputera czy systemu operacyjnego.<br />
<br />
Python został zaprojektowany jako język ogólnego stosowania, podczas gdy Matlab był projektowany zasadniczo jako język do obliczeń naukowych. W bardziej zaawansowaną funkcjonalność numeryczną Python został wyposażony dopiero dzięki powstaniu modułów [http://www.scipy.org/ NumPy/SciPy] i [http://matplotlib.sourceforge.net/ Matplotlib]. Pakiety te wprowadzają do Pythona m. in. wielowymiarowe macierze (numpy.array), operacje na wszystkich elementach macierzy oraz szereg procedur graficznych do prezentacji wyników, używających składni parametrów niezwykle podobnej do tych z Matlaba. Wydaje się więc, że nie powinno być trudności, aby &bdquo;przesiąść&ldquo; się z jednego języka na drugi i sprawnie pisać programy. Tak w dużej mierze jest, są jednak między tymi językami subtelne różnice, które (szczególnie dla początkujących) mogą stanowić pułapkę. Najistotniejsze z tych różnic postaramy się tutaj zaprezentować.<br />
<br />
{| border="1" class="wikitable topalign"<br />
|+ '''Porównanie cech języków Matlab i Python'''<br />
! Matlab<br />
! Python (2.x)<br />
|- valign="top"<br />
| Podczas pracy interaktywnej Matlab, w odróżnieniu od Pythona, zwraca wartość każdego wyrażenia, które zlecimy mu do wykonania. Wypisywanie wyniku możemy zablokować kończąc wiersz polecenia średnikiem.<br />
| Python wykonuje polecenie, ale nie zwraca jego wyniku. Jeśli zależy nam na takim zachowaniu Pythona, możemy zastosować nakładkę [http://ipython.scipy.org/ IPython], dającą podobną funkcjonalność.<br />
|- valign="top"<br />
| Zmienne nie mają konkretnego typu, dopiero po przypisaniu im wartości możemy określić typ zmiennej.<br />
| Sytuacja jest podobna.<br />
|- valign="top"<br />
| Domyślnym typem numerycznym są liczby zmiennoprzecinkowe podwójnej precyzji. Dodatkowo, każda zmienna jest tak naprawdę macierzą zmiennych danego typu, nawet jeśli zawiera tylko jedną wartość (jest wtedy macierzą rozmiaru 1&times;1).<br />
<div style="line-height: 1"><tt><small><br />
:>> a = 3<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> class(a)<br />
:ans =<br />
:double<br />
:>> size(a)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1</small></tt></div><br />
| Spośród typów zmiennych numerycznych mamy do dyspozycji liczby całkowite i zmiennoprzecinkowe (które zachowują się inaczej w pewnych operacjach matematycznych). Macierze wprowadzone są przy użyciu pakietu NumPy.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = 3<br />
:>>> type(a)<br />
:<type 'int'><br />
:>>> a = 3.<br />
:>>> type(a)<br />
:<type 'float'></small></tt></div><br />
|- valign="top"<br />
| Macierze definiujemy z użyciem nawiasów kwadratowych.<br />
<div style="line-height: 1"><tt><small><br />
:a = [1 4; 7 2];</small></tt></div><br />
| Macierze definiujemy używając odpowiedniej funkcji<br />
<div style="line-height: 1"><tt><small><br />
:a = numpy.array([ [1,4], [7,2] ])<br />
:a = numpy.mat('[1 4; 7 2]')</small></tt></div><br />
|- valign="top"<br />
| Indeksy macierzy piszemy w nawiasach okrągłych. <br />
:<tt>a(1,3,5:7)</tt><br />
| Indeksy macierzy piszemy w nawiasach kwadratowych.<br />
:<tt>a[1,3,5:7]</tt><br />
|- valign="top"<br />
| Pierwszy indeks macierzy na numer 1.<br />
| Pierwszy indeks macierzy na numer 0.<br />
|- valign="top"<br />
| Działanie wycinka: elementy liczone od 1, ostatni zawiera się w wycinku.<br />
<div style="line-height: 1"><tt><small><br />
:>> a = linspace(1,10,10)<br />
:a = <br><br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;10<br />
:>> a(1:5)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br />
:>> a(5:end)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;10</small></tt></div><br />
| Działanie wycinka: elementy liczone od 0, ostatni element wpisany liczbowo nie zawiera się w wycinku.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.linspace(1,10,10)<br />
:>>> a<br><br />
:array([&nbsp;&nbsp;1.,&nbsp;&nbsp;&nbsp;2.,&nbsp;&nbsp;&nbsp;3.,&nbsp;&nbsp;&nbsp;4.,&nbsp;&nbsp;&nbsp;5.,&nbsp;&nbsp;&nbsp;6.,&nbsp;&nbsp;&nbsp;7.,&nbsp;&nbsp;&nbsp;8.,&nbsp;&nbsp;&nbsp;9.,&nbsp;&nbsp;10.])<br />
:>>> a[1:5] # czyli od elementu 2 do 5 (element 6 o indeksie 5 wpisany liczbowo)<br />
:array([ 2.,&nbsp;&nbsp;3.,&nbsp;&nbsp;4.,&nbsp;&nbsp;5.])<br />
:>>> a[5:] &nbsp;# czyli od elementu 6 do ostatniego (nie określonego liczbowo)<br />
:array([&nbsp;&nbsp;6.,&nbsp;&nbsp;&nbsp;7.,&nbsp;&nbsp;&nbsp;8.,&nbsp;&nbsp;&nbsp;9.,&nbsp;&nbsp;10.])</small></tt></div><br />
|- valign="top"<br />
| Łatwe tworzenie wektorów wartości z pewnego zakresu:<br />
<div style="line-height: 1"><tt><small><br />
:>> a = 1:5<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br />
:>> a = linspace(1,5,5)<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5</small></tt></div><br />
| Łatwe tworzenie wektorów wartości z pewnego zakresu z użyciem pakietu NumPy:<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.r_[1:6]<br />
:>>> a<br />
:array([1, 2, 3, 4, 5])<br />
:>>> a = numpy.linspace(1,5,5)<br />
:>>> a<br />
:array([ 1.,&nbsp;&nbsp;2.,&nbsp;&nbsp;3.,&nbsp;&nbsp;4.,&nbsp;&nbsp;5.])</small></tt></div><br />
|- valign = "top"<br />
| Macierze zachowują wszystkie swoje wymiary.<br />
| Macierze mogą zostac &bdquo;spłaszczone&rdquo; do wektorów posiadających tylko długość.<br />
|- valign = "top"<br />
| Wymiary macierzy liczą się od lewej do prawej.<br />
<div style="line-height: 1"><tt><small><br />
:>>&nbsp;c=1:8<br />
:c&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8<br />
:>>&nbsp;cr=reshape(c,[2,2,2])<br />
:cr(:,:,1)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4<br />
:cr(:,:,2)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8<br />
:>>&nbsp;cr(:,:,1)<br />
:ans&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4<br />
:>>&nbsp;cr(1,:,:)<br />
:ans(:,:,1)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:ans(:,:,2)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7</small></tt></div><br />
| Wymiary macierzy liczą się od prawej do lewej.<br />
<div style="line-height: 1"><tt><small><br />
:>>>&nbsp;c=numpy.array(range(1,9))<br />
:>>>&nbsp;c<br />
:array([1,&nbsp;2,&nbsp;3,&nbsp;4,&nbsp;5,&nbsp;6,&nbsp;7,&nbsp;8])<br />
:>>>&nbsp;cr=numpy.reshape(c,(2,2,2))<br />
:>>>&nbsp;cr<br />
:array([[[1,&nbsp;2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[3,&nbsp;4]],<br />
:&nbsp;<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[[5,&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[7,&nbsp;8]]])<br />
:>>>&nbsp;cr[0]<br />
:array([[1,&nbsp;2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[3,&nbsp;4]])<br />
:>>>&nbsp;cr[:,:,0]<br />
:array([[1,&nbsp;3],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[5,&nbsp;7]])</small></tt></div><br />
|- valign = "top"<br />
| Niektóre operatory różnią się od Pythonowych. Niektóre przykłady:<br />
* Potęgowanie: <tt>^</tt><br />
* Nie równa się: <tt>~=</tt><br />
* Dzielenie modulo: <tt>mod(x,y)</tt><br />
* Operatory logiczne &bdquo;i&rdquo;, &bdquo;lub&rdquo;, &bdquo;nie&rdquo;: <tt>& | ~</tt><br />
* Komentarz: <tt>%</tt><br />
| Niektóre operatory różnią się od Matlabowych. Niektóre przykłady:<br />
* Potęgowanie: <tt>**</tt><br />
* Nie równa się: <tt>!=</tt><br />
* Dzielenie modulo: <tt>x % y</tt><br />
* Operatory logiczne &bdquo;i&rdquo;, &bdquo;lub&rdquo;, &bdquo;nie&rdquo;: <tt>and or not</tt><br />
* Komentarz: <tt>#</tt><br />
|- valign="top"<br />
| Przypisanie zmiennych do siebie powoduje skopiowanie ich zawartości.<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 2 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = a<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b(2) = 0<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> a<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3</small></tt></div><br />
| Przypisanie zmiennych do siebie powoduje wyłącznie powstanie drugiej nazwy tego samego obiektu. Zawartość nie jest kopiowana.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = [1,2,3]<br />
:>>> b = a<br />
:>>> b[1] = 0<br />
:>>> b<br />
:[1, 0, 3]<br />
:>>> a<br />
:[1, 0, 3]</small></tt></div><br />
|- valign="top"<br />
| Liczby zespolone są wbudowane w działanie pakietu<br />
<div style="line-height: 1"><tt><small><br />
:>> (-1)^0.5<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;0.0000 + 1.0000i</small></tt></div><br />
|Chcąc użyć liczb zespolonych musimy to explicite zaznaczyć.<br />
<div style="line-height: 1"><tt><small><br />
:>>> (-1)**0.5<br />
:<br><br />
:<font color="red">Traceback (most recent call last):<br />
:&nbsp;&nbsp;File "<pyshell#37>", line 1, in <module><br />
:&nbsp;&nbsp;&nbsp;&nbsp;(-1)**0.5<br />
:ValueError: negative number cannot be raised to a fractional power</font></small></tt></div><br />
ale<br/><br />
<div style="line-height: 1"><tt><small><br />
:>>> (-1+0j)**0.5<br />
:<br><br />
:(6.1230317691118863e-17+1j)</small></tt></div><br />
|- valign="top"<br />
| Niektóre sytuacje wyjątkowe nie powodują przerwania obliczeń, dając użytkownikowi informację o możliwym błędzie w postaci specjalnej wartości.<br />
<div style="line-height: 1"><tt><small> <br />
:>> 1/0<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;Inf</small></tt></div><br />
a także<br />
<div style="line-height: 1"><tt><small> <br />
:>> a = ones(1,3)<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
:>> b = [1 0 2]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br />
:>> a./b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;1.0000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Inf&nbsp;&nbsp;&nbsp;&nbsp;0.5000</small></tt></div><br />
| W &bdquo;czystym&rdquo; Pythonie użytkownik musi sam zadbać o obsługę wszystkich sytuacji wyjątkowych.<br />
<div style="line-height: 1"><tt><small> <br />
:>>> 1/0<br />
:<br><br />
:<font color="red">Traceback (most recent call last):<br />
:&nbsp;&nbsp;File "<pyshell#0>", line 1, in <module><br />
:&nbsp;&nbsp;&nbsp;&nbsp;1/0<br />
:ZeroDivisionError: integer division or modulo by zero</font></small></tt></div><br />
Macierze z modułu NumPy zachowują się podobnie do macierzy Matlaba:<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.ones(3)<br />
:>>> a<br />
:array([ 1.,&nbsp;&nbsp;1.,&nbsp;&nbsp;1.])<br />
:>>> b = numpy.array([1.,0.,2.])<br />
:>>> b<br />
:array([ 1.,&nbsp;&nbsp;0.,&nbsp;&nbsp;2.])<br />
:>>> a/b<br />
:array([ 1. ,&nbsp;&nbsp;inf,&nbsp;&nbsp;0.5])</small></tt></div><br />
|- valign="top"<br />
| Ponieważ każda zmienna numeryczna jest macierzą, podstawowe operatory arytmetyczne opisują działania na macierzach. W szczególności operator mnożenia realizuje mnożenie macierzy:<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = [2;-1]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1<br />
:>> a * b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1<br />
:>> b * a<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1&nbsp;&nbsp;&nbsp;&nbsp;-3</small></tt></div><br />
Aby zrealizować operację osobno dla każdej pary elementów macierzy/wektorów, stosujemy operatory arytmetyczne z kropką (wymiary macierzy muszą być zgodne):<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = [2 1]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
:>> a .* b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b .* a<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3</small></tt></div><br />
| Operatory arytmetyczne zastosowane do macierzy wykonują zadane operacje osobno dla wszystkich par elementów tych macierzy. Tak więc w szczególności operator mnożenia w Pythonie odpowiada operatorowi &bdquo;mnożenia z kropką&rdquo; w Matlabie i nie realizuje mnożenia macierzowego.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.array([1,3])<br />
:>>> a<br />
:array([1, 3])<br />
:>>> b = numpy.array([[2],[-1]])<br />
:>>> b<br />
:array([[ 2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1]])<br />
:>>> a * b<br />
:array([[ 2,&nbsp;&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1, -3]])<br />
:>>> b * a<br />
:array([[ 2,&nbsp;&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1, -3]])<br />
:<br><br />
:<br><br />
:<br><br />
:<br><br />
:<br><br />
:>>> a = numpy.array([1,3])<br />
:>>> a<br />
:array([1, 3])<br />
:>>> b = numpy.array([2,1])<br />
:>>> b<br />
:array([2, 1])<br />
:>>> a*b<br />
:array([2, 3])<br />
:>>> b*a<br />
:array([2, 3])</small></tt></div><br />
|- valign="top"<br />
| Wywołanie pomocy dla obiektu <tt>nazwa</tt>:<br />
<div style="line-height: 1"><tt><small><br />
:help nazwa</small></tt></div><br />
| Wywołanie pomocy dla obiektu <tt>nazwa</tt>:<br />
<div style="line-height: 1"><tt><small><br />
:help(nazwa)</small></tt></div><br />
|- valign="top"<br />
| Funkcje matematyczne są wbudowane.<br />
Listę funkcji elementarnych można zobaczyć pisząc:<br />
<div style="line-height: 1"><tt><small><br />
:help elfun</small></tt></div><br />
Bardziej zaawansowane funkcje można zobaczyć pisząc:<br />
<div style="line-height: 1"><tt><small><br />
:help specfun</small></tt></div><br />
<div style="line-height: 1"><tt><small><br />
:help elmat</small></tt></div><br />
| Funkcje matematyczne są dostępne po załadowaniu modułu NumPy (lub innych,np. math).<br />
|}<br />
<br />
Oczywiście powyższa tabela nie obejmuje wszystkich możliwych różnic, a tylko te najważniejsze, które mogą sprawić kłopot na początku pracy. Nie wydaje się jednak, aby miały one zasadnicze znaczenie dla sprawnego pisania programów w obu omawianych tu językach.<br />
<br />
==Piszemy program w Matlabie==<br />
<br />
Z tego co już zostało tutaj powiedziane widzimy, że osoba, która umie napisać program w Pythonie, nie powinna mieć większego kłopotu z napisaniem go również w Matlabie. Należy tylko pamiętać o pewnych różnicach języków i składni, które jednak zasadniczo, po nabyciu pewnej wprawy, nie sprawiają większych trudności.<br />
<br />
Aby sprawdzić działanie obu języków w praktyce, napiszemy kilka programów realizujących te same założenia w Pythonie i w Matlabie.<br />
<br />
===Drobne różnice składniowe===<br />
*Pisząc w języku Matlab, warto jest używać wcięć, nie są jednak konieczne. Koniec bloku zaznacza się, pisząc <tt>end</tt>.<br />
*Nie używamy dwukropków na końcu instrukcji zaczynających blok np. <tt>for</tt>, czy <tt>if</tt>.<br />
*Wyrażenie warunkowe:<br />
<br />
**<tt>if</tt><br />
<source lang="Matlab"><br />
if a < 30<br />
disp('small')<br />
elseif a < 80<br />
disp('medium')<br />
else<br />
disp('large')<br />
end<br />
</source><br />
**<tt>switch</tt><br />
<source lang="Matlab"><br />
[dayNum, dayString] = weekday(date, 'long', 'en_US');<br />
<br />
switch dayString<br />
case 'Monday'<br />
disp('Start of the work week')<br />
case 'Tuesday'<br />
disp('Day 2')<br />
case 'Wednesday'<br />
disp('Day 3')<br />
case 'Thursday'<br />
disp('Day 4')<br />
case 'Friday'<br />
disp('Last day of the work week')<br />
otherwise<br />
disp('Weekend!')<br />
end<br />
</source><br />
* Pętle<br />
<br />
**<tt>for</tt><br />
<source lang="Matlab"><br />
for i = 1:m<br />
for j = 1:n<br />
H(i,j) = 1/(i+j);<br />
end<br />
end<br />
</source><br />
Pętla <tt>for</tt>, tak samo jak w Pythonie, wymaga sekwencji. Sekwencja może być pewnym wektorem. Można też ją utworzyć w następujący sposób:<br />
<source lang="Matlab"><br />
poczatek:krok:koniec<br />
</source><br />
albo<br />
<source lang="Matlab"><br />
poczatek:koniec<br />
</source><br />
(wtedy <tt>krok = 1</tt>). Wynikiem jest wektor wartości od <tt>poczatek</tt> do <tt>koniec</tt> o kroku <tt>krok</tt>. Jest to analog <tt>range</tt> oraz <tt>numpy.arange</tt>.<br />
**<tt>while</tt><br />
<source lang="Matlab"><br />
n = 1;<br />
nFactorial = 1;<br />
while nFactorial < 1e100<br />
n = n + 1;<br />
nFactorial = nFactorial * n;<br />
end<br />
</source><br />
*Funkcje<br />
<br />
**nagłówek rozpoczyna się słowem <tt>function</tt>, na przykład:<br />
<source lang="Matlab"><br />
function [R,E,V]=R_po(t,t_rec,t_in,U_SE,t_mem,R_0,E_0,V_0,t_0,u,dt)<br />
</source><br />
**Zwykle zachowujemy w oddzielnych plikach o nazwie takiej samej, jak funkcja.<br />
<br />
===Rysujemy wykres funkcji (przykład)===<br />
<br />
Napiszmy program rysujący wykres funkcji kwadratowej na odcinku od &minus;5 do 5.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
x=linspace(-5,5,11);<br />
y=x.^2;<br />
plot(x,y,'r-');<br />
<br />
<br />
</source><br />
| <br />
| <source lang='python'><br />
import numpy<br />
import pylab<br />
x=numpy.linspace(-5,5,11)<br />
y=x**2<br />
pylab.plot(x,y,'r-')<br />
pylab.show()</source><br />
|}<br />
<br />
Zasadnicze różnice: operator potęgowania, użycie operatora z kropką, konieczność importowania modułów numerycznego i graficznego, osobna procedura do pokazania gotowego wykresu na ekranie.<br />
<br />
<br />
<br />
Narysujmy bardziej dokładnie wykres funkcji sin(''x'')/''x''.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
x=linspace(-5,5,101);<br />
y=sin(x)./x;<br />
plot(x,y);</source><br />
| <br />
| <source lang='python'><br />
import numpy as np<br />
import pylab as p<br />
x=np.linspace(-5,5,101)<br />
y=np.sin(x)/x<br />
p.plot(x,y)<br />
p.show()</source><br />
|}<br />
<br />
===Zliczamy liczbę liter===<br />
<br />
Narysujmy histogram liczebności poszczególnych liter z pierwszej księgi &bdquo;Pana Tadeusza&rdquo; A. Mickiewicza. Tekst znajdziemy [http://brain.fuw.edu.pl/edu-wiki/images/5/5b/PanTadeuszX1.txt tu]. Ściągamy plik i zapisujemy w swoim katalogu.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
fid=fopen('PanTadeuszX1.txt','rb');<br />
tekst=fread(fid,'uchar');<br />
fclose(fid);<br />
<br />
hist(tekst,min(tekst):max(tekst));<br />
xlim([double('a')-1 double('z')+1]);<br />
<br />
<br />
<br />
set(gca,'XTick',double('a'):double('z'));<br />
set(gca,'XTickLabel',['a':'z']');<br />
</source><br />
| <br />
| <source lang='python'><br />
import numpy as np<br />
import pylab as p<br />
<br />
tekst=np.fromfile('PanTadeuszX1.txt','uint8')<br />
<br />
<br />
p.hist(tekst,max(tekst)-min(tekst)+1)<br />
p.xlim(ord('a')-1,ord('z')+1)<br />
achars=[]<br />
for code in range(ord('a'),ord('z')+1):<br />
achars.append(chr(code))<br />
p.xticks(range(ord('a'),ord('z')+1),achars)<br />
<br />
p.show()<br />
</source><br />
|}<br />
<br />
Wykorzystaliśmy tutaj fakt, że litery alfabetu angielskiego są w kodzie ASCII ułożone bezpośrednio po sobie, alfabetycznie i w kolejności rosnącej. Gdybyśmy w naszym histogramie chcieli uwzględnić również polskie litery, należałoby kolejność słupków histogramu wybrać ręcznie, zgodnie z kolejnością w alfabecie polskim. Histogram musimy utworzyć z wybranych wartości (wysokości słupków) ustawionych w pożądanej kolejności. Dodatkową trudnością jest fakt, że stosowane są różne sposoby kodowania polskich liter (czyli zamiany liter na odpowiadające im wartości liczbowe). Plik tekstowy zastosowany w przykładzie wykorzystuje kodowanie &bdquo;Windows-1250&rdquo;, a Matlab domyślnie koduje napisy w standardzie Unicode. Nasz program powinien uwzględniać te fakty.<br />
<br />
==Ćwiczenia==<br />
{{Solution|title=Zadanie 1|text=<br />
[[Plik:Albrecht_Durer_Magic_Square.jpg|300px|thumb|right|<figure id="fig:1"/> Szczegół z miedziorytu Albrechta Durera zatytułowanego Melancholia I, 1514 r.]]<br />
<br />
Utwórz w Matlabie macierz z liczbami magicznego kwadratu i policz sumę elementów w każdym wierszu, kolumnie i obu przekątnych.<br />
Dodatkowo, możesz policzyć sumę liczb w narożnikach, każdej ćwiartce kwadratu i w czterech środkowych polach.<br />
<br />
Wskazówki:<br />
* W Matlabie sumę elementów macierzy zwraca funkcja <tt>sum</tt> (sprawdź jak ta funkcja działa).<br />
* Transpozycję macierzy A uzyskuje się za pomocą apostrofa tj. A'.<br />
* Elementy na przekątnej macierzy zwraca funkcja <tt>diag</tt>.<br />
* Odwracanie macierzy z lewa na prawo uzyskuje się za pomocą funkcji <tt>fliplr</tt>.<br />
* Do elementów macierzy można też się odwoływać za pomocą pojedynczego indeksu. W tej sytuacji, macierz odpowiada pojedynczej kolumnie złożonej z kolumn oryginalnej macierzy. Np. dla magicznego kwadratu A(8) odwołuje się do wartości 15 w elemencie macierzy A(4,2).<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 2|text=<br />
<br />
Utwórz w Matlabie program, który tworzy macierz z liczbami magicznego kwadratu dla dowolnego n i zwraca sumę elementów w każdym wierszu, kolumnie i obu przekątnych.<br />
<br />
Wskazówki:<br />
* W Matlabie kwadrat magiczny można wygenerować funkcją <tt>magic</tt>.<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 3|text=<br />
[[Plik:Frequency_axis.jpg|300px|thumb|right|<figure id="fig:2"/> Oś częstości zwracana przez funkcje <tt>fft</tt>. Pierwszy element zawiera częstość zerową, następnie częstości dodatnie do częstości Nyquista, a następnie częstości ujemne. Funkcja <tt>fftshift</tt> zamienia ze sobą lewą i prawą połowę osi pozostawiając częstość zerową w centrum widma.]]<br />
Napisz funkcję, której dostaje argumenty w postaci sygnału i częstości próbkowania, i przedstawia na rysunkach: dyskretną transformatę Fouriera (wielkość i przesunięcie fazowe), periodogram (kwadrat modułu transformaty Fouriera), gęstość widmową mocy oraz numeryczną weryfikację twierdzenia Parsevala.<br />
Następnie wygeneruj sygnał będący sumą dwóch sinusów o częstościach 10 i 40 Hz, długości trwania 2 s i częstości próbkowania 100 Hz i sprawdź działanie funkcji.<br />
<br />
Wskazówki:<br />
* W Matlabie dyskretną transformatę Fouriera oblicza funkcja <tt>fft</tt>.<br />
* Metody szacowania gęstości widmowej mocy można uzyskać pisząc <tt>help spectrum</tt>.<br />
* Przypomnienie: twierdzenie Parsevala mówi, że całka z gęstości widmowej mocy jest miarą całkowitej energii sygnału. Energię sygnału obliczamy jako sumę kwadratów amplitud sygnału.<br />
<br />
<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 4|text=<br />
[[Plik:Binary_tree.svg|thumb|<figure id="fig:3"/> Przykład drzewa binarnego]]Drzewo binarne jest drzewem, w którym stopień każdego wierzchołka (liczba połączeń danego wierzchołka) nie jest wyższy niż 3. Drzewo takie przedstawione jest na rysunku <xr id="fig:3"/>. Drzewo takie można wygodnie reprezentować w tablicy &mdash; jeżeli nadamy wierzchołkowi ''i''-ty element tablicy, jego lewy syn będzie miał indeks 2''i''+1, a prawy 2''i''+2 w przypadku języków, w których wektory numerowane są od zera. <br />
<br />
Jaka będzie reguła reprezentacji drzewa binarnego za pomocą wektora w językach, w których wektory indeksowane są od 1? Jak zapiszesz reprezentację drzewa z rysunku <xr id="fig:3"/> w języku Matlab?<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 5 (trudniejsze)|text=<br />
[[Plik:Histogram_PT1PL.gif|300px|thumb|right|]]Napisz w Matlabie program zliczający ilości liter I księgi &bdquo;Pana Tadeusza&rdquo; z uwzględnieniem również polskich liter.<br />
<br />
Wskazówka:<br />
* Proponowany tekst jest zapisany w kodowaniu &bdquo;Windows-1250&rdquo;.<br />
* W Matlabie jest dostępna funkcja zamieniająca wybrane kodowanie tekstu na Unicode, na przykład:<br />
::<tt>tekst_Unicode = native2unicode(tekst_Win1250,'windows-1250');</tt><br />
* Przypisanie wyniku funkcji <tt>hist</tt> do jakiejś zmiennej anuluje rysowanie histogramu. W zamian, w zmiennej tej zapisane zostaną obliczone wysokości słupków.<br />
* Kolejność polskiego alfabetu (wzbogaconego o litery dodatkowe &bdquo;q&rdquo;, &bdquo;v&rdquo; i &bdquo;x&rdquo;) to:<br />
::aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż<br />
* Aby narysować histogram dla wcześniej wyliczonych wysokości słupków użyj funkcji <tt>bar</tt>.<br />
* Opisy na osi wykresu (ich położenie i tekst) zmienić możemy używając instrukcji:<br />
::<tt>set(gca,'XTick',[1 2 3]);</tt><br />
::<tt>set(gca,'XTickLabel',['abc']')</tt><br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 6|text=<br />
[[Plik:matsurf.png|300px|thumb|]]Zbadaj przebieg zależności <math>\sin(r)/r</math> dla ''r'' będącego odległością od środka biegunowego układu współrzędnych na płaszczyźnie w zakresie &minus;10 < ''x'' < 10, &minus;10 < ''y'' < 10. Narysuj wykresy używając funkcji Matlaba <tt>mesh</tt>, <tt>surf</tt>, <tt>pcolor</tt> i <tt>contour</tt>.<br />
Dlaczego na wykresach brakuje punktu dla ''r'' = 0? Co możemy zrobić, aby wykres był kompletny?<br />
<br />
Wskazówka:<br />
* Zapoznaj się z działaniem następujących funkcji:<br />
::<tt>meshgrid</tt> (co zawierają macierze zwracane przez tę funkcję?);<br />
::<tt>shading</tt>, <tt>hidden</tt>, <tt>colormap</tt>;<br />
::<tt>subplot</tt>, <tt>xlabel</tt>, <tt>ylabel</tt>, <tt>title</tt>.<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 7|text=<br />
[[Plik:matkula.png|300px|thumb|]]Funkcje <tt>mesh</tt> czy <tt>surf</tt> służą w ogólności do rysowania obiektów trójwymiarowych. Używając ich narysuj sferę o promieniu 1.<br />
<br />
Wskazówka:<br />
* Przypomnij sobie jak opisana jest sfera w sferycznym układzie współrzędnych, a w szczególności jak transformują się współrzędne punktów sfery z układu sferycznego (''r'',&theta;,&phi;) do układu kartezjańskiego (''x'',''y'',''z'').<br />
* Aby kula nie wyglądała jak elipsoida należy skorzystać z polecenia <tt>axis equal</tt>, które ujednolica rozmiar rysunku wzdłuż osi ''x'', ''y'' i ''z''.<br />
<br />
<!--Jaką figurę opisuje układ równań<br />
::<math>x=(R+r\cos\phi)\cos\theta</math><br />
::<math>y=(R+r\cos\phi)\sin\theta</math><br />
::<math>z=r\sin\phi</math><br />
--><br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 8|text=<br />
[[Plik:Rys_mapka.png|300px|thumb|]]Matlab umożliwia przechowywanie zmiennych w plikach własnego formatu .MAT zawierających wszystkie niezbędne informacje o typach zapisanych zmiennych i oczywiście ich wartościach. Do zapisu plików służy polecenie <tt>save</tt>, a do ich wczytania polecenie <tt>load</tt>.<br />
<br />
<br />
Plik [[brain.fuw.edu.pl/edu/images/4/4a/Book.tar.gz]] ([[Plik:Book.tar.gz]]) zawiera strukturę, która opisuje dekompozycję pewnego sygnału na struktury składowe &mdash; &bdquo;atomy&rdquo; za pomocą algorytmu MP. Pobierz ten plik, rozpakuj go, a jego zawartość wczytaj do Matlaba i narysuj wynik dekompozycji (wraz ze źródłowymi sygnałami) zawarty w tym pliku. Napisz funkcję rysującą wyniki dla danego kanału i wybranego atomu uwzględniającą informacje zawarte we wczytanej strukturze.<br />
<br />
{{clear}}<br />
}}<br />
<br />
==Debugger w Matlabie==<br />
<br />
Środowisko programowania w Matlabie dostarcza bardzo użytecznego narzędzia pomagającego śledzić działanie programów i niezwykle ułatwiającego wyszukiwanie błędów. Narzędzie to nazywa się z angielska ''debuggerem'' (czyli &bdquo;odrobaczaczem&rdquo; lub &bdquo;odpluskwiaczem&rdquo;). <br />
<br />
Zasada działania debuggera polega na tym, że możemy zatrzymać wykonujący się program w dowolnym miejscu, nie przerywając wykonania całkowicie, ale tylko chwilowo je wstrzymując. Robimy to przez wcześniejsze wstawienie w tekście programu (który musi być widoczny w oknie Edytora) specjalnych ''punktów zatrzymania'' (ang. ''breakpoints''). Pokażemy to na przykładzie prostego programu. Na rysunku poniżej widzimy fragment okna Edytora Matlaba z widocznym interesującym nas fragmentem programu. <br />
<br />
[[Plik:matldeb1.gif]]<br />
<br />
Załóżmy, że chcemy zobaczyć czy pętla w wierszach 3-5 programu prawidłowo sumuje wartości. W tym celu w wierszu 4 umieszczamy punkt zatrzymania, ustawiając kursor w edytorze na tym wierszu i używając guzika z paska poleceń:<br />
<br />
[[Plik:matldeb2.gif]]<br />
<br />
Po naciśnięciu guzika &bdquo;Set/clear breakpoint&rdquo; (&bdquo;Ustaw/skasuj punkt zatrzymania&rdquo;) po lewej stronie wiersza 4 pojawia się czerwona kropka oznaczająca, że w tym miejscu program zostanie wstrzymany.<br />
<br />
[[Plik:matldeb3.gif]]<br />
<br />
Pozostaje nam teraz uruchomić nasz program. Można to zrobić wpisując odpowiednie polecenie w oknie Poleceń Matlaba (''Command window'') lub naciskając guzik na pasku poleceń:<br />
<br />
[[Plik:matldeb4.gif]]<br />
<br />
Program wykona się aż do napotkania punktu zatrzymania. Wtedy wykonanie zostaje przerwane i w oknie Poleceń zauważymy, że znak zachęty ma dopisaną literę &bdquo;K&rdquo;. Zielona strzałka z lewej strony wiersza programu wskazuje jaka komenda programu oczekuje na wykonanie. W oknie Obszar roboczy (''Workspace'') widzimy wartości wszystkich zmiennych naszego programu, możemy też w oknie Poleceń wpisać dowolne wyrażenie (np. <tt>suma*3</tt>) i zobaczyć jego wynik. Od tej chwili możemy też wykonywać nasz program krok po kroku naciskając odpowiedni guzik z paska poleceń albo wykonać program do końca (lub następnego punktu zatrzymania). <br />
<br />
[[Plik:matldeb5.gif]]<br />
<br />
==Informacje dodatkowe==<br />
<br />
Matlab wyposażony jest w tzw. ''toolboxy'' czyli pakiety procedur powiązanych tematycznie do rozwiązywania problemów z jakiejś dziedziny. Pakiety takie można zakupić u producenta (The MathWorks Inc.); aby sprawdzić jakie są aktualnie zainstalowane, wywołujemy polecenie Matlaba <tt>ver</tt>. W rezultacie dostajemy listę podobną do prezentowanej poniżej.<br />
<br />
<div style="line-height: 1"><tt><small><br />
>> ver<br />
-------------------------------------------------------------------------------------<br />
MATLAB Version 7.11.0.584 (R2010b)<br />
MATLAB License Number: 123456<br />
Operating System: Microsoft Windows 7 Version 6.1 (Build 7600)<br />
Java VM Version: Java 1.6.0_17-b04 with Sun Microsystems Inc. Java HotSpot(TM) Client VM mixed mode<br />
-------------------------------------------------------------------------------------<br />
MATLAB Version 7.11 (R2010b)<br />
Simulink Version 7.6 (R2010b)<br />
Bioinformatics Toolbox Version 3.6 (R2010b)<br />
Communications Blockset Version 5.0 (R2010b)<br />
Communications Toolbox Version 4.6 (R2010b)<br />
Control System Toolbox Version 9.0 (R2010b)<br />
Curve Fitting Toolbox Version 3.0 (R2010b)<br />
Data Acquisition Toolbox Version 2.17 (R2010b)<br />
Database Toolbox Version 3.8 (R2010b)<br />
Filter Design Toolbox Version 4.7.1 (R2010b)<br />
Financial Toolbox Version 3.8 (R2010b)<br />
Fixed-Point Toolbox Version 3.2 (R2010b)<br />
Global Optimization Toolbox Version 3.1 (R2010b)<br />
Image Acquisition Toolbox Version 4.0 (R2010b)<br />
Image Processing Toolbox Version 7.1 (R2010b)<br />
Instrument Control Toolbox Version 2.11 (R2010b)<br />
MATLAB Builder EX Version 1.3 (R2010b)<br />
MATLAB Builder NE Version 3.2 (R2010b)<br />
MATLAB Compiler Version 4.14 (R2010b)<br />
Mapping Toolbox Version 3.2 (R2010b)<br />
Neural Network Toolbox Version 7.0 (R2010b)<br />
Optimization Toolbox Version 5.1 (R2010b)<br />
Parallel Computing Toolbox Version 5.0 (R2010b)<br />
Parallel Computing Toolbox Version 5.0 (R2010b)<br />
Partial Differential Equation Toolbox Version 1.0.17 (R2010b)<br />
Real-Time Workshop Version 7.6 (R2010b)<br />
Robust Control Toolbox Version 3.5 (R2010b)<br />
Signal Processing Blockset Version 7.1 (R2010b)<br />
Signal Processing Toolbox Version 6.14 (R2010b)<br />
Simulink Control Design Version 3.2 (R2010b)<br />
Simulink Design Optimization Version 1.2 (R2010b)<br />
Simulink Fixed Point Version 6.4 (R2010b)<br />
Statistics Toolbox Version 7.4 (R2010b)<br />
Symbolic Math Toolbox Version 5.5 (R2010b)<br />
System Identification Toolbox Version 7.4.1 (R2010b)<br />
Wavelet Toolbox Version 4.6 (R2010b)<br />
</small></tt></div><br />
<br />
Oczywiście możemy sami dopisywać własne procedury, a także korzystać z oprogramowania udostępnionego przez innych twórców. Jako przykład mogą tu posłużyć pakiety do analizy danych biomedycznych [http://sccn.ucsd.edu/eeglab/ EEGLAB] czy obrazów MRI [http://www.fil.ion.ucl.ac.uk/spm/ SPM] rozwijane przez niezależne grupy obejmujące badaczy i programistów. Również procedury [http://octave.sourceforge.net/ Octave-Forge] tworzone w ramach projektu GNU Octave mogą współpracować wymiennie z Matlabem.<br />
<br />
Python również pozwala na korzystanie z pisanych dla niego pakietów oprogramowania. Musimy je jednak odszukać, ściągnąć i zainstalować sami. W wersji podstawowej będą to:<br />
* python &mdash; podstawowy interpreter/kompilator języka Python;<br />
* numpy &mdash; biblioteka funkcji matematycznych i obliczeniowych;<br />
* scipy &mdash; zestaw bardziej zaawansowanych procedur numerycznych;<br />
* matplotlib &mdash; procedury graficzne do sporządzania wykresów i wizualizacji wyników.<br />
:(Uwaga: Mając zainstalowane bilioteki numpy, scipy i matplotlib możemy w programie używać podstawowych funkcji wszystkich tych modułów jedną komendą: <tt>import&nbsp;pylab</tt>.)<br />
<br />
[http://pypi.python.org/pypi?%3Aaction=index Lista projektów programistycznych w Pythonie] obejmuje różnorodne tematy i jest duża szansa znalezienia czegoś dla siebie. <br />
<br />
Warto też zwrócić uwagę na pakiet [http://mlabwrap.sourceforge.net/ mlabwrap], który pozwala korzystać z Matlaba (musi być zainstalowany w systemie) jakby był on biblioteką Pythona (z pewnymi ograniczeniami, ale wciąż rozwijany).<br />
<br />
<br />
[[Laboratorium_EEG]]/Wprowadzenie_do_Matlaba</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG/Wprowadzenie_do_Matlaba&diff=4817Laboratorium EEG/Wprowadzenie do Matlaba2016-03-01T12:45:11Z<p>Tspus: /* Ćwiczenia */</p>
<hr />
<div>[[Laboratorium_EEG]]/Wprowadzenie_do_Matlaba<br />
<br />
<br />
==Wprowadzenie==<br />
[[Plik:Matlab_splash.png|200px|thumb|right|Okno powitalne Matlaba]]<br />
Najkrócej można określić Matlab jako pakiet oprogramowania do obliczeń matematycznych wyprodukowany w firmie [http://www.mathworks.com/ MathWorks]. Jest to w istocie zintegrowane ''środowisko obliczeniowe'', w którym mamy do dyspozycji:<br />
* własny język programowania wysokiego poziomu, dający możliwość interaktywnego programowania;<br />
* środowisko zaprojektowane do pracy z macierzami numerycznymi;<br />
* specjalistyczne zestawy procedur obliczeniowych z różnych dziedzin, możliwość zmiany i dodawania własnych funkcji;<br />
* bogate możliwości graficznej prezentacji wyników 2D/3D oraz projektowania własnych interfejsów graficznych (GUI);<br />
* możliwość włączania programów napisanych w innych językach (C, C++, Fortran, Java);<br />
* okienkowo-zorientowane środowiska graficzne do uruchamiania algorytmów na podstawie ich schematów blokowych (np. Simulink);<br />
* wygodne operacje wejścia/wyjścia dla wielu typów danych (np. wav, avi, DICOM)<br />
* zintegrowane interaktywne narzędzia programistyczne: edytor i debugger.<br />
<br />
Dzięki tym możliwościom pakiet [http://www.mathworks.com/products/matlab/ Matlab] (mimo swej relatywnie wysokiej ceny) stał się bardzo popularnym narzędziem obliczeniowym, szczególnie w dziedzinie analizy danych biomedycznych. Pozwala on na dość szybkie pisanie złożonych programów obliczeniowych, pozwalając skupić się na rozwiązywaniu problemu, a nie na samym kodowaniu programu. Warto więc się z nim zapoznać, gdyż jest duża szansa natrafienia na Matlaba w trakcie kariery zawodowej absolwentów naszej specjalności.<br />
<br />
Warto również dodać, że osoby nie dysponujące dostępem do Matlaba, chcące zapoznać się z programowaniem w tym języku lub używać posiadane gotowe programy mogą skorzystać z darmowego pakietu [http://www.gnu.org/software/octave/ GNU Octave]. Język Octave jest bardzo podobny do Matlabowego i większość programów może być bez zmian przenoszona między nimi.<br />
<br />
==Matlab a Python==<br />
<br />
Ponieważ nasz kurs programowania jest oparty zasadniczo o język Python, właściwe będzie porównanie Pythona i Matlaba. W trakcie nauki programowania w Pythonie, wykorzystywaliśmy interfejs użytkownika, pozwalający nie tylko na uruchamianie programów, ale też na pracę interaktywną. Takim interfejsem jest np. stosowany przez nas <tt>idle</tt>. W Matlabie podobny interfejs jest wbudowany w program &mdash; po uruchomieniu programu dostajemy otwarte okno poleceń.<br />
[[Plik:Idle_and_Matlab.png|800px|thumb|center|Okna poleceń: po lewej Pythona (Idle), po prawej Matlaba]]<br />
Jak widać, w obu przypadkach sytuacja jest podobna. Możemy zacząć pracę w sesji interaktywnej wpisując na bieżąco polecenia, które są od razu interpretowane i wykonywane. Wyniki są natychmiast prezentowane na ekranie. Każdy z pakietów daje nam również możliwość napisania programu w osobnym edytorze tekstu, zapisania go na dysku i uruchomienia w dogodnym dla nas momencie.<br />
<br />
Podobieństw między Matlabem a Pythonem jest dużo więcej. Oba języki są językami wysokiego poziomu, co oznacza, że dużą część szczegółów implementacji naszego kodu możemy pozostawić w gestii stosowanego pakietu, pisząc programy w sposób bardziej przypominający ogólny algorytm opisany w sposób zrozumiały dla człowieka, a nie dopasowany do konkretnego komputera czy systemu operacyjnego.<br />
<br />
Python został zaprojektowany jako język ogólnego stosowania, podczas gdy Matlab był projektowany zasadniczo jako język do obliczeń naukowych. W bardziej zaawansowaną funkcjonalność numeryczną Python został wyposażony dopiero dzięki powstaniu modułów [http://www.scipy.org/ NumPy/SciPy] i [http://matplotlib.sourceforge.net/ Matplotlib]. Pakiety te wprowadzają do Pythona m. in. wielowymiarowe macierze (numpy.array), operacje na wszystkich elementach macierzy oraz szereg procedur graficznych do prezentacji wyników, używających składni parametrów niezwykle podobnej do tych z Matlaba. Wydaje się więc, że nie powinno być trudności, aby &bdquo;przesiąść&ldquo; się z jednego języka na drugi i sprawnie pisać programy. Tak w dużej mierze jest, są jednak między tymi językami subtelne różnice, które (szczególnie dla początkujących) mogą stanowić pułapkę. Najistotniejsze z tych różnic postaramy się tutaj zaprezentować.<br />
<br />
{| border="1" class="wikitable topalign"<br />
|+ '''Porównanie cech języków Matlab i Python'''<br />
! Matlab<br />
! Python (2.x)<br />
|- valign="top"<br />
| Podczas pracy interaktywnej Matlab, w odróżnieniu od Pythona, zwraca wartość każdego wyrażenia, które zlecimy mu do wykonania. Wypisywanie wyniku możemy zablokować kończąc wiersz polecenia średnikiem.<br />
| Python wykonuje polecenie, ale nie zwraca jego wyniku. Jeśli zależy nam na takim zachowaniu Pythona, możemy zastosować nakładkę [http://ipython.scipy.org/ IPython], dającą podobną funkcjonalność.<br />
|- valign="top"<br />
| Zmienne nie mają konkretnego typu, dopiero po przypisaniu im wartości możemy określić typ zmiennej.<br />
| Sytuacja jest podobna.<br />
|- valign="top"<br />
| Domyślnym typem numerycznym są liczby zmiennoprzecinkowe podwójnej precyzji. Dodatkowo, każda zmienna jest tak naprawdę macierzą zmiennych danego typu, nawet jeśli zawiera tylko jedną wartość (jest wtedy macierzą rozmiaru 1&times;1).<br />
<div style="line-height: 1"><tt><small><br />
:>> a = 3<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> class(a)<br />
:ans =<br />
:double<br />
:>> size(a)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1</small></tt></div><br />
| Spośród typów zmiennych numerycznych mamy do dyspozycji liczby całkowite i zmiennoprzecinkowe (które zachowują się inaczej w pewnych operacjach matematycznych). Macierze wprowadzone są przy użyciu pakietu NumPy.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = 3<br />
:>>> type(a)<br />
:<type 'int'><br />
:>>> a = 3.<br />
:>>> type(a)<br />
:<type 'float'></small></tt></div><br />
|- valign="top"<br />
| Macierze definiujemy z użyciem nawiasów kwadratowych.<br />
<div style="line-height: 1"><tt><small><br />
:a = [1 4; 7 2];</small></tt></div><br />
| Macierze definiujemy używając odpowiedniej funkcji<br />
<div style="line-height: 1"><tt><small><br />
:a = numpy.array([ [1,4], [7,2] ])<br />
:a = numpy.mat('[1 4; 7 2]')</small></tt></div><br />
|- valign="top"<br />
| Indeksy macierzy piszemy w nawiasach okrągłych. <br />
:<tt>a(1,3,5:7)</tt><br />
| Indeksy macierzy piszemy w nawiasach kwadratowych.<br />
:<tt>a[1,3,5:7]</tt><br />
|- valign="top"<br />
| Pierwszy indeks macierzy na numer 1.<br />
| Pierwszy indeks macierzy na numer 0.<br />
|- valign="top"<br />
| Działanie wycinka: elementy liczone od 1, ostatni zawiera się w wycinku.<br />
<div style="line-height: 1"><tt><small><br />
:>> a = linspace(1,10,10)<br />
:a = <br><br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;10<br />
:>> a(1:5)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br />
:>> a(5:end)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;10</small></tt></div><br />
| Działanie wycinka: elementy liczone od 0, ostatni element wpisany liczbowo nie zawiera się w wycinku.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.linspace(1,10,10)<br />
:>>> a<br><br />
:array([&nbsp;&nbsp;1.,&nbsp;&nbsp;&nbsp;2.,&nbsp;&nbsp;&nbsp;3.,&nbsp;&nbsp;&nbsp;4.,&nbsp;&nbsp;&nbsp;5.,&nbsp;&nbsp;&nbsp;6.,&nbsp;&nbsp;&nbsp;7.,&nbsp;&nbsp;&nbsp;8.,&nbsp;&nbsp;&nbsp;9.,&nbsp;&nbsp;10.])<br />
:>>> a[1:5] # czyli od elementu 2 do 5 (element 6 o indeksie 5 wpisany liczbowo)<br />
:array([ 2.,&nbsp;&nbsp;3.,&nbsp;&nbsp;4.,&nbsp;&nbsp;5.])<br />
:>>> a[5:] &nbsp;# czyli od elementu 6 do ostatniego (nie określonego liczbowo)<br />
:array([&nbsp;&nbsp;6.,&nbsp;&nbsp;&nbsp;7.,&nbsp;&nbsp;&nbsp;8.,&nbsp;&nbsp;&nbsp;9.,&nbsp;&nbsp;10.])</small></tt></div><br />
|- valign="top"<br />
| Łatwe tworzenie wektorów wartości z pewnego zakresu:<br />
<div style="line-height: 1"><tt><small><br />
:>> a = 1:5<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br />
:>> a = linspace(1,5,5)<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5</small></tt></div><br />
| Łatwe tworzenie wektorów wartości z pewnego zakresu z użyciem pakietu NumPy:<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.r_[1:6]<br />
:>>> a<br />
:array([1, 2, 3, 4, 5])<br />
:>>> a = numpy.linspace(1,5,5)<br />
:>>> a<br />
:array([ 1.,&nbsp;&nbsp;2.,&nbsp;&nbsp;3.,&nbsp;&nbsp;4.,&nbsp;&nbsp;5.])</small></tt></div><br />
|- valign = "top"<br />
| Macierze zachowują wszystkie swoje wymiary.<br />
| Macierze mogą zostac &bdquo;spłaszczone&rdquo; do wektorów posiadających tylko długość.<br />
|- valign = "top"<br />
| Wymiary macierzy liczą się od lewej do prawej.<br />
<div style="line-height: 1"><tt><small><br />
:>>&nbsp;c=1:8<br />
:c&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8<br />
:>>&nbsp;cr=reshape(c,[2,2,2])<br />
:cr(:,:,1)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4<br />
:cr(:,:,2)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8<br />
:>>&nbsp;cr(:,:,1)<br />
:ans&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4<br />
:>>&nbsp;cr(1,:,:)<br />
:ans(:,:,1)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:ans(:,:,2)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7</small></tt></div><br />
| Wymiary macierzy liczą się od prawej do lewej.<br />
<div style="line-height: 1"><tt><small><br />
:>>>&nbsp;c=numpy.array(range(1,9))<br />
:>>>&nbsp;c<br />
:array([1,&nbsp;2,&nbsp;3,&nbsp;4,&nbsp;5,&nbsp;6,&nbsp;7,&nbsp;8])<br />
:>>>&nbsp;cr=numpy.reshape(c,(2,2,2))<br />
:>>>&nbsp;cr<br />
:array([[[1,&nbsp;2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[3,&nbsp;4]],<br />
:&nbsp;<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[[5,&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[7,&nbsp;8]]])<br />
:>>>&nbsp;cr[0]<br />
:array([[1,&nbsp;2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[3,&nbsp;4]])<br />
:>>>&nbsp;cr[:,:,0]<br />
:array([[1,&nbsp;3],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[5,&nbsp;7]])</small></tt></div><br />
|- valign = "top"<br />
| Niektóre operatory różnią się od Pythonowych. Niektóre przykłady:<br />
* Potęgowanie: <tt>^</tt><br />
* Nie równa się: <tt>~=</tt><br />
* Dzielenie modulo: <tt>mod(x,y)</tt><br />
* Operatory logiczne &bdquo;i&rdquo;, &bdquo;lub&rdquo;, &bdquo;nie&rdquo;: <tt>& | ~</tt><br />
* Komentarz: <tt>%</tt><br />
| Niektóre operatory różnią się od Matlabowych. Niektóre przykłady:<br />
* Potęgowanie: <tt>**</tt><br />
* Nie równa się: <tt>!=</tt><br />
* Dzielenie modulo: <tt>x % y</tt><br />
* Operatory logiczne &bdquo;i&rdquo;, &bdquo;lub&rdquo;, &bdquo;nie&rdquo;: <tt>and or not</tt><br />
* Komentarz: <tt>#</tt><br />
|- valign="top"<br />
| Przypisanie zmiennych do siebie powoduje skopiowanie ich zawartości.<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 2 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = a<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b(2) = 0<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> a<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3</small></tt></div><br />
| Przypisanie zmiennych do siebie powoduje wyłącznie powstanie drugiej nazwy tego samego obiektu. Zawartość nie jest kopiowana.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = [1,2,3]<br />
:>>> b = a<br />
:>>> b[1] = 0<br />
:>>> b<br />
:[1, 0, 3]<br />
:>>> a<br />
:[1, 0, 3]</small></tt></div><br />
|- valign="top"<br />
| Liczby zespolone są wbudowane w działanie pakietu<br />
<div style="line-height: 1"><tt><small><br />
:>> (-1)^0.5<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;0.0000 + 1.0000i</small></tt></div><br />
|Chcąc użyć liczb zespolonych musimy to explicite zaznaczyć.<br />
<div style="line-height: 1"><tt><small><br />
:>>> (-1)**0.5<br />
:<br><br />
:<font color="red">Traceback (most recent call last):<br />
:&nbsp;&nbsp;File "<pyshell#37>", line 1, in <module><br />
:&nbsp;&nbsp;&nbsp;&nbsp;(-1)**0.5<br />
:ValueError: negative number cannot be raised to a fractional power</font></small></tt></div><br />
ale<br/><br />
<div style="line-height: 1"><tt><small><br />
:>>> (-1+0j)**0.5<br />
:<br><br />
:(6.1230317691118863e-17+1j)</small></tt></div><br />
|- valign="top"<br />
| Niektóre sytuacje wyjątkowe nie powodują przerwania obliczeń, dając użytkownikowi informację o możliwym błędzie w postaci specjalnej wartości.<br />
<div style="line-height: 1"><tt><small> <br />
:>> 1/0<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;Inf</small></tt></div><br />
a także<br />
<div style="line-height: 1"><tt><small> <br />
:>> a = ones(1,3)<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
:>> b = [1 0 2]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br />
:>> a./b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;1.0000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Inf&nbsp;&nbsp;&nbsp;&nbsp;0.5000</small></tt></div><br />
| W &bdquo;czystym&rdquo; Pythonie użytkownik musi sam zadbać o obsługę wszystkich sytuacji wyjątkowych.<br />
<div style="line-height: 1"><tt><small> <br />
:>>> 1/0<br />
:<br><br />
:<font color="red">Traceback (most recent call last):<br />
:&nbsp;&nbsp;File "<pyshell#0>", line 1, in <module><br />
:&nbsp;&nbsp;&nbsp;&nbsp;1/0<br />
:ZeroDivisionError: integer division or modulo by zero</font></small></tt></div><br />
Macierze z modułu NumPy zachowują się podobnie do macierzy Matlaba:<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.ones(3)<br />
:>>> a<br />
:array([ 1.,&nbsp;&nbsp;1.,&nbsp;&nbsp;1.])<br />
:>>> b = numpy.array([1.,0.,2.])<br />
:>>> b<br />
:array([ 1.,&nbsp;&nbsp;0.,&nbsp;&nbsp;2.])<br />
:>>> a/b<br />
:array([ 1. ,&nbsp;&nbsp;inf,&nbsp;&nbsp;0.5])</small></tt></div><br />
|- valign="top"<br />
| Ponieważ każda zmienna numeryczna jest macierzą, podstawowe operatory arytmetyczne opisują działania na macierzach. W szczególności operator mnożenia realizuje mnożenie macierzy:<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = [2;-1]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1<br />
:>> a * b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1<br />
:>> b * a<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1&nbsp;&nbsp;&nbsp;&nbsp;-3</small></tt></div><br />
Aby zrealizować operację osobno dla każdej pary elementów macierzy/wektorów, stosujemy operatory arytmetyczne z kropką (wymiary macierzy muszą być zgodne):<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = [2 1]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
:>> a .* b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b .* a<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3</small></tt></div><br />
| Operatory arytmetyczne zastosowane do macierzy wykonują zadane operacje osobno dla wszystkich par elementów tych macierzy. Tak więc w szczególności operator mnożenia w Pythonie odpowiada operatorowi &bdquo;mnożenia z kropką&rdquo; w Matlabie i nie realizuje mnożenia macierzowego.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.array([1,3])<br />
:>>> a<br />
:array([1, 3])<br />
:>>> b = numpy.array([[2],[-1]])<br />
:>>> b<br />
:array([[ 2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1]])<br />
:>>> a * b<br />
:array([[ 2,&nbsp;&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1, -3]])<br />
:>>> b * a<br />
:array([[ 2,&nbsp;&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1, -3]])<br />
:<br><br />
:<br><br />
:<br><br />
:<br><br />
:<br><br />
:>>> a = numpy.array([1,3])<br />
:>>> a<br />
:array([1, 3])<br />
:>>> b = numpy.array([2,1])<br />
:>>> b<br />
:array([2, 1])<br />
:>>> a*b<br />
:array([2, 3])<br />
:>>> b*a<br />
:array([2, 3])</small></tt></div><br />
|- valign="top"<br />
| Wywołanie pomocy dla obiektu <tt>nazwa</tt>:<br />
<div style="line-height: 1"><tt><small><br />
:help nazwa</small></tt></div><br />
| Wywołanie pomocy dla obiektu <tt>nazwa</tt>:<br />
<div style="line-height: 1"><tt><small><br />
:help(nazwa)</small></tt></div><br />
|- valign="top"<br />
| Funkcje matematyczne są wbudowane.<br />
Listę funkcji elementarnych można zobaczyć pisząc:<br />
<div style="line-height: 1"><tt><small><br />
:help elfun</small></tt></div><br />
Bardziej zaawansowane funkcje można zobaczyć pisząc:<br />
<div style="line-height: 1"><tt><small><br />
:help specfun</small></tt></div><br />
<div style="line-height: 1"><tt><small><br />
:help elmat</small></tt></div><br />
| Funkcje matematyczne są dostępne po załadowaniu modułu NumPy (lub innych,np. math).<br />
|}<br />
<br />
Oczywiście powyższa tabela nie obejmuje wszystkich możliwych różnic, a tylko te najważniejsze, które mogą sprawić kłopot na początku pracy. Nie wydaje się jednak, aby miały one zasadnicze znaczenie dla sprawnego pisania programów w obu omawianych tu językach.<br />
<br />
==Piszemy program w Matlabie==<br />
<br />
Z tego co już zostało tutaj powiedziane widzimy, że osoba, która umie napisać program w Pythonie, nie powinna mieć większego kłopotu z napisaniem go również w Matlabie. Należy tylko pamiętać o pewnych różnicach języków i składni, które jednak zasadniczo, po nabyciu pewnej wprawy, nie sprawiają większych trudności.<br />
<br />
Aby sprawdzić działanie obu języków w praktyce, napiszemy kilka programów realizujących te same założenia w Pythonie i w Matlabie.<br />
<br />
===Drobne różnice składniowe===<br />
*Pisząc w języku Matlab, warto jest używać wcięć, nie są jednak konieczne. Koniec bloku zaznacza się, pisząc <tt>end</tt>.<br />
*Nie używamy dwukropków na końcu instrukcji zaczynających blok np. <tt>for</tt>, czy <tt>if</tt>.<br />
*Wyrażenie warunkowe:<br />
<br />
**<tt>if</tt><br />
<source lang="Matlab"><br />
if a < 30<br />
disp('small')<br />
elseif a < 80<br />
disp('medium')<br />
else<br />
disp('large')<br />
end<br />
</source><br />
**<tt>switch</tt><br />
<source lang="Matlab"><br />
[dayNum, dayString] = weekday(date, 'long', 'en_US');<br />
<br />
switch dayString<br />
case 'Monday'<br />
disp('Start of the work week')<br />
case 'Tuesday'<br />
disp('Day 2')<br />
case 'Wednesday'<br />
disp('Day 3')<br />
case 'Thursday'<br />
disp('Day 4')<br />
case 'Friday'<br />
disp('Last day of the work week')<br />
otherwise<br />
disp('Weekend!')<br />
end<br />
</source><br />
* Pętle<br />
<br />
**<tt>for</tt><br />
<source lang="Matlab"><br />
for i = 1:m<br />
for j = 1:n<br />
H(i,j) = 1/(i+j);<br />
end<br />
end<br />
</source><br />
Pętla <tt>for</tt>, tak samo jak w Pythonie, wymaga sekwencji. Sekwencja może być pewnym wektorem. Można też ją utworzyć w następujący sposób:<br />
<source lang="Matlab"><br />
poczatek:krok:koniec<br />
</source><br />
albo<br />
<source lang="Matlab"><br />
poczatek:koniec<br />
</source><br />
(wtedy <tt>krok = 1</tt>). Wynikiem jest wektor wartości od <tt>poczatek</tt> do <tt>koniec</tt> o kroku <tt>krok</tt>. Jest to analog <tt>range</tt> oraz <tt>numpy.arange</tt>.<br />
**<tt>while</tt><br />
<source lang="Matlab"><br />
n = 1;<br />
nFactorial = 1;<br />
while nFactorial < 1e100<br />
n = n + 1;<br />
nFactorial = nFactorial * n;<br />
end<br />
</source><br />
*Funkcje<br />
<br />
**nagłówek rozpoczyna się słowem <tt>function</tt>, na przykład:<br />
<source lang="Matlab"><br />
function [R,E,V]=R_po(t,t_rec,t_in,U_SE,t_mem,R_0,E_0,V_0,t_0,u,dt)<br />
</source><br />
**Zwykle zachowujemy w oddzielnych plikach o nazwie takiej samej, jak funkcja.<br />
<br />
===Rysujemy wykres funkcji (przykład)===<br />
<br />
Napiszmy program rysujący wykres funkcji kwadratowej na odcinku od &minus;5 do 5.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
x=linspace(-5,5,11);<br />
y=x.^2;<br />
plot(x,y,'r-');<br />
<br />
<br />
</source><br />
| <br />
| <source lang='python'><br />
import numpy<br />
import pylab<br />
x=numpy.linspace(-5,5,11)<br />
y=x**2<br />
pylab.plot(x,y,'r-')<br />
pylab.show()</source><br />
|}<br />
<br />
Zasadnicze różnice: operator potęgowania, użycie operatora z kropką, konieczność importowania modułów numerycznego i graficznego, osobna procedura do pokazania gotowego wykresu na ekranie.<br />
<br />
<br />
<br />
Narysujmy bardziej dokładnie wykres funkcji sin(''x'')/''x''.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
x=linspace(-5,5,101);<br />
y=sin(x)./x;<br />
plot(x,y);</source><br />
| <br />
| <source lang='python'><br />
import numpy as np<br />
import pylab as p<br />
x=np.linspace(-5,5,101)<br />
y=np.sin(x)/x<br />
p.plot(x,y)<br />
p.show()</source><br />
|}<br />
<br />
===Zliczamy liczbę liter===<br />
<br />
Narysujmy histogram liczebności poszczególnych liter z pierwszej księgi &bdquo;Pana Tadeusza&rdquo; A. Mickiewicza. Tekst znajdziemy [http://brain.fuw.edu.pl/edu-wiki/images/5/5b/PanTadeuszX1.txt tu]. Ściągamy plik i zapisujemy w swoim katalogu.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
fid=fopen('PanTadeuszX1.txt','rb');<br />
tekst=fread(fid,'uchar');<br />
fclose(fid);<br />
<br />
hist(tekst,min(tekst):max(tekst));<br />
xlim([double('a')-1 double('z')+1]);<br />
<br />
<br />
<br />
set(gca,'XTick',double('a'):double('z'));<br />
set(gca,'XTickLabel',['a':'z']');<br />
</source><br />
| <br />
| <source lang='python'><br />
import numpy as np<br />
import pylab as p<br />
<br />
tekst=np.fromfile('PanTadeuszX1.txt','uint8')<br />
<br />
<br />
p.hist(tekst,max(tekst)-min(tekst)+1)<br />
p.xlim(ord('a')-1,ord('z')+1)<br />
achars=[]<br />
for code in range(ord('a'),ord('z')+1):<br />
achars.append(chr(code))<br />
p.xticks(range(ord('a'),ord('z')+1),achars)<br />
<br />
p.show()<br />
</source><br />
|}<br />
<br />
Wykorzystaliśmy tutaj fakt, że litery alfabetu angielskiego są w kodzie ASCII ułożone bezpośrednio po sobie, alfabetycznie i w kolejności rosnącej. Gdybyśmy w naszym histogramie chcieli uwzględnić również polskie litery, należałoby kolejność słupków histogramu wybrać ręcznie, zgodnie z kolejnością w alfabecie polskim. Histogram musimy utworzyć z wybranych wartości (wysokości słupków) ustawionych w pożądanej kolejności. Dodatkową trudnością jest fakt, że stosowane są różne sposoby kodowania polskich liter (czyli zamiany liter na odpowiadające im wartości liczbowe). Plik tekstowy zastosowany w przykładzie wykorzystuje kodowanie &bdquo;Windows-1250&rdquo;, a Matlab domyślnie koduje napisy w standardzie Unicode. Nasz program powinien uwzględniać te fakty.<br />
<br />
==Ćwiczenia==<br />
{{Solution|title=Zadanie 1|text=<br />
[[Plik:Albrecht_Durer_Magic_Square.jpg|300px|thumb|right|<figure id="fig:1"/> Szczegół z miedziorytu Albrechta Durera zatytułowanego Melancholia I, 1514 r.]]<br />
<br />
Utwórz w Matlabie macierz z liczbami magicznego kwadratu i policz sumę elementów w każdym wierszu, kolumnie i obu przekątnych.<br />
Dodatkowo, możesz policzyć sumę liczb w narożnikach, każdej ćwiartce kwadratu i w czterech środkowych polach.<br />
<br />
Wskazówki:<br />
* W Matlabie sumę elementów macierzy zwraca funkcja <tt>sum</tt> (sprawdź jak ta funkcja działa).<br />
* Transpozycję macierzy A uzyskuje się za pomocą apostrofa tj. A'.<br />
* Elementy na przekątnej macierzy zwraca funkcja <tt>diag</tt>.<br />
* Odwracanie macierzy z lewa na prawo uzyskuje się za pomocą funkcji <tt>fliplr</tt>.<br />
* Do elementów macierzy można też się odwoływać za pomocą pojedynczego indeksu. W tej sytuacji, macierz odpowiada pojedynczej kolumnie złożonej z kolumn oryginalnej macierzy. Np. dla magicznego kwadratu A(8) odwołuje się do wartości 15 w elemencie macierzy A(4,2).<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 2|text=<br />
<br />
Utwórz w Matlabie program, który tworzy macierz z liczbami magicznego kwadratu dla dowolnego n i zwraca sumę elementów w każdym wierszu, kolumnie i obu przekątnych.<br />
<br />
Wskazówki:<br />
* W Matlabie kwadrat magiczny można wygenerować funkcją <tt>magic</tt>.<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 3|text=<br />
[[Plik:Frequency_axis.jpg|300px|thumb|right|<figure id="fig:2"/> Oś częstości zwracana przez funkcje <tt>fft</tt>. Pierwszy element zawiera częstość zerową, następnie częstości dodatnie do częstości Nyquista, a następnie częstości ujemne. Funkcja <tt>fftshift</tt> zamienia ze sobą lewą i prawą połowę osi pozostawiając częstość zerową w centrum widma.]]<br />
Napisz funkcję, której dostaje argumenty w postaci sygnału i częstości próbkowania, i przedstawia na rysunkach: dyskretną transformatę Fouriera (wielkość i przesunięcie fazowe), periodogram (kwadrat modułu transformaty Fouriera), gęstość widmową mocy oraz numeryczną weryfikację twierdzenia Parsevala.<br />
Następnie wygeneruj sygnał będący sumą dwóch sinusów o częstościach 10 i 40 Hz, długości trwania 2 s i częstości próbkowania 100 Hz i sprawdź działanie funkcji.<br />
<br />
Wskazówki:<br />
* W Matlabie dyskretną transformatę Fouriera oblicza funkcja <tt>fft</tt>.<br />
* Metody szacowania gęstości widmowej mocy można uzyskać pisząc <tt>help spectrum</tt>.<br />
* Przypomnienie: twierdzenie Parsevala mówi, że całka z gęstości widmowej mocy jest miarą całkowitej energii sygnału. Energię sygnału obliczamy jako sumę kwadratów amplitud sygnału.<br />
<br />
<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 4|text=<br />
[[Plik:Binary_tree.svg|thumb|<figure id="fig:3"/> Przykład drzewa binarnego]]Drzewo binarne jest drzewem, w którym stopień każdego wierzchołka (liczba połączeń danego wierzchołka) nie jest wyższy niż 3. Drzewo takie przedstawione jest na rysunku <xr id="fig:3"/>. Drzewo takie można wygodnie reprezentować w tablicy &mdash; jeżeli nadamy wierzchołkowi ''i''-ty element tablicy, jego lewy syn będzie miał indeks 2''i''+1, a prawy 2''i''+2 w przypadku języków, w których wektory numerowane są od zera. <br />
<br />
Jaka będzie reguła reprezentacji drzewa binarnego za pomocą wektora w językach, w których wektory indeksowane są od 1? Jak zapiszesz reprezentację drzewa z rysunku <xr id="fig:3"/> w języku Matlab?<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 5 (trudniejsze)|text=<br />
[[Plik:Histogram_PT1PL.gif|300px|thumb|right|]]Napisz w Matlabie program zliczający ilości liter I księgi &bdquo;Pana Tadeusza&rdquo; z uwzględnieniem również polskich liter.<br />
<br />
Wskazówka:<br />
* Proponowany tekst jest zapisany w kodowaniu &bdquo;Windows-1250&rdquo;.<br />
* W Matlabie jest dostępna funkcja zamieniająca wybrane kodowanie tekstu na Unicode, na przykład:<br />
::<tt>tekst_Unicode = native2unicode(tekst_Win1250,'windows-1250');</tt><br />
* Przypisanie wyniku funkcji <tt>hist</tt> do jakiejś zmiennej anuluje rysowanie histogramu. W zamian, w zmiennej tej zapisane zostaną obliczone wysokości słupków.<br />
* Kolejność polskiego alfabetu (wzbogaconego o litery dodatkowe &bdquo;q&rdquo;, &bdquo;v&rdquo; i &bdquo;x&rdquo;) to:<br />
::aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż<br />
* Aby narysować histogram dla wcześniej wyliczonych wysokości słupków użyj funkcji <tt>bar</tt>.<br />
* Opisy na osi wykresu (ich położenie i tekst) zmienić możemy używając instrukcji:<br />
::<tt>set(gca,'XTick',[1 2 3]);</tt><br />
::<tt>set(gca,'XTickLabel',['abc']')</tt><br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 6|text=<br />
[[Plik:matsurf.png|300px|thumb|]]Zbadaj przebieg zależności <math>\sin(r)/r</math> dla ''r'' będącego odległością od środka biegunowego układu współrzędnych na płaszczyźnie w zakresie &minus;10 < ''x'' < 10, &minus;10 < ''y'' < 10. Narysuj wykresy używając funkcji Matlaba <tt>mesh</tt>, <tt>surf</tt>, <tt>pcolor</tt> i <tt>contour</tt>.<br />
Dlaczego na wykresach brakuje punktu dla ''r'' = 0? Co możemy zrobić, aby wykres był kompletny?<br />
<br />
Wskazówka:<br />
* Zapoznaj się z działaniem następujących funkcji:<br />
::<tt>meshgrid</tt> (co zawierają macierze zwracane przez tę funkcję?);<br />
::<tt>shading</tt>, <tt>hidden</tt>, <tt>colormap</tt>;<br />
::<tt>subplot</tt>, <tt>xlabel</tt>, <tt>ylabel</tt>, <tt>title</tt>.<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 7|text=<br />
[[Plik:matkula.png|300px|thumb|]]Funkcje <tt>mesh</tt> czy <tt>surf</tt> służą w ogólności do rysowania obiektów trójwymiarowych. Używając ich narysuj sferę o promieniu 1.<br />
<br />
Wskazówka:<br />
* Przypomnij sobie jak opisana jest sfera w sferycznym układzie współrzędnych, a w szczególności jak transformują się współrzędne punktów sfery z układu sferycznego (''r'',&theta;,&phi;) do układu kartezjańskiego (''x'',''y'',''z'').<br />
* Aby kula nie wyglądała jak elipsoida należy skorzystać z polecenia <tt>axis equal</tt>, które ujednolica rozmiar rysunku wzdłuż osi ''x'', ''y'' i ''z''.<br />
<br />
<!--Jaką figurę opisuje układ równań<br />
::<math>x=(R+r\cos\phi)\cos\theta</math><br />
::<math>y=(R+r\cos\phi)\sin\theta</math><br />
::<math>z=r\sin\phi</math><br />
--><br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 8|text=<br />
[[Plik:Rys_mapka.png|300px|thumb|]]Matlab umożliwia przechowywanie zmiennych w plikach własnego formatu .MAT zawierających wszystkie niezbędne informacje o typach zapisanych zmiennych i oczywiście ich wartościach. Do zapisu plików służy polecenie <tt>save</tt>, a do ich wczytania polecenie <tt>load</tt>.<br />
<br />
<br />
Plik [brain.fuw.edu.pl/edu/images/4/4a/Book.tar.gz] ([[Plik:Book.tar.gz]]) zawiera strukturę, która opisuje dekompozycję pewnego sygnału na struktury składowe &mdash; &bdquo;atomy&rdquo; za pomocą algorytmu MP. Pobierz ten plik, rozpakuj go, a jego zawartość wczytaj do Matlaba i narysuj wynik dekompozycji (wraz ze źródłowymi sygnałami) zawarty w tym pliku. Napisz funkcję rysującą wyniki dla danego kanału i wybranego atomu uwzględniającą informacje zawarte we wczytanej strukturze.<br />
<br />
{{clear}}<br />
}}<br />
<br />
==Debugger w Matlabie==<br />
<br />
Środowisko programowania w Matlabie dostarcza bardzo użytecznego narzędzia pomagającego śledzić działanie programów i niezwykle ułatwiającego wyszukiwanie błędów. Narzędzie to nazywa się z angielska ''debuggerem'' (czyli &bdquo;odrobaczaczem&rdquo; lub &bdquo;odpluskwiaczem&rdquo;). <br />
<br />
Zasada działania debuggera polega na tym, że możemy zatrzymać wykonujący się program w dowolnym miejscu, nie przerywając wykonania całkowicie, ale tylko chwilowo je wstrzymując. Robimy to przez wcześniejsze wstawienie w tekście programu (który musi być widoczny w oknie Edytora) specjalnych ''punktów zatrzymania'' (ang. ''breakpoints''). Pokażemy to na przykładzie prostego programu. Na rysunku poniżej widzimy fragment okna Edytora Matlaba z widocznym interesującym nas fragmentem programu. <br />
<br />
[[Plik:matldeb1.gif]]<br />
<br />
Załóżmy, że chcemy zobaczyć czy pętla w wierszach 3-5 programu prawidłowo sumuje wartości. W tym celu w wierszu 4 umieszczamy punkt zatrzymania, ustawiając kursor w edytorze na tym wierszu i używając guzika z paska poleceń:<br />
<br />
[[Plik:matldeb2.gif]]<br />
<br />
Po naciśnięciu guzika &bdquo;Set/clear breakpoint&rdquo; (&bdquo;Ustaw/skasuj punkt zatrzymania&rdquo;) po lewej stronie wiersza 4 pojawia się czerwona kropka oznaczająca, że w tym miejscu program zostanie wstrzymany.<br />
<br />
[[Plik:matldeb3.gif]]<br />
<br />
Pozostaje nam teraz uruchomić nasz program. Można to zrobić wpisując odpowiednie polecenie w oknie Poleceń Matlaba (''Command window'') lub naciskając guzik na pasku poleceń:<br />
<br />
[[Plik:matldeb4.gif]]<br />
<br />
Program wykona się aż do napotkania punktu zatrzymania. Wtedy wykonanie zostaje przerwane i w oknie Poleceń zauważymy, że znak zachęty ma dopisaną literę &bdquo;K&rdquo;. Zielona strzałka z lewej strony wiersza programu wskazuje jaka komenda programu oczekuje na wykonanie. W oknie Obszar roboczy (''Workspace'') widzimy wartości wszystkich zmiennych naszego programu, możemy też w oknie Poleceń wpisać dowolne wyrażenie (np. <tt>suma*3</tt>) i zobaczyć jego wynik. Od tej chwili możemy też wykonywać nasz program krok po kroku naciskając odpowiedni guzik z paska poleceń albo wykonać program do końca (lub następnego punktu zatrzymania). <br />
<br />
[[Plik:matldeb5.gif]]<br />
<br />
==Informacje dodatkowe==<br />
<br />
Matlab wyposażony jest w tzw. ''toolboxy'' czyli pakiety procedur powiązanych tematycznie do rozwiązywania problemów z jakiejś dziedziny. Pakiety takie można zakupić u producenta (The MathWorks Inc.); aby sprawdzić jakie są aktualnie zainstalowane, wywołujemy polecenie Matlaba <tt>ver</tt>. W rezultacie dostajemy listę podobną do prezentowanej poniżej.<br />
<br />
<div style="line-height: 1"><tt><small><br />
>> ver<br />
-------------------------------------------------------------------------------------<br />
MATLAB Version 7.11.0.584 (R2010b)<br />
MATLAB License Number: 123456<br />
Operating System: Microsoft Windows 7 Version 6.1 (Build 7600)<br />
Java VM Version: Java 1.6.0_17-b04 with Sun Microsystems Inc. Java HotSpot(TM) Client VM mixed mode<br />
-------------------------------------------------------------------------------------<br />
MATLAB Version 7.11 (R2010b)<br />
Simulink Version 7.6 (R2010b)<br />
Bioinformatics Toolbox Version 3.6 (R2010b)<br />
Communications Blockset Version 5.0 (R2010b)<br />
Communications Toolbox Version 4.6 (R2010b)<br />
Control System Toolbox Version 9.0 (R2010b)<br />
Curve Fitting Toolbox Version 3.0 (R2010b)<br />
Data Acquisition Toolbox Version 2.17 (R2010b)<br />
Database Toolbox Version 3.8 (R2010b)<br />
Filter Design Toolbox Version 4.7.1 (R2010b)<br />
Financial Toolbox Version 3.8 (R2010b)<br />
Fixed-Point Toolbox Version 3.2 (R2010b)<br />
Global Optimization Toolbox Version 3.1 (R2010b)<br />
Image Acquisition Toolbox Version 4.0 (R2010b)<br />
Image Processing Toolbox Version 7.1 (R2010b)<br />
Instrument Control Toolbox Version 2.11 (R2010b)<br />
MATLAB Builder EX Version 1.3 (R2010b)<br />
MATLAB Builder NE Version 3.2 (R2010b)<br />
MATLAB Compiler Version 4.14 (R2010b)<br />
Mapping Toolbox Version 3.2 (R2010b)<br />
Neural Network Toolbox Version 7.0 (R2010b)<br />
Optimization Toolbox Version 5.1 (R2010b)<br />
Parallel Computing Toolbox Version 5.0 (R2010b)<br />
Parallel Computing Toolbox Version 5.0 (R2010b)<br />
Partial Differential Equation Toolbox Version 1.0.17 (R2010b)<br />
Real-Time Workshop Version 7.6 (R2010b)<br />
Robust Control Toolbox Version 3.5 (R2010b)<br />
Signal Processing Blockset Version 7.1 (R2010b)<br />
Signal Processing Toolbox Version 6.14 (R2010b)<br />
Simulink Control Design Version 3.2 (R2010b)<br />
Simulink Design Optimization Version 1.2 (R2010b)<br />
Simulink Fixed Point Version 6.4 (R2010b)<br />
Statistics Toolbox Version 7.4 (R2010b)<br />
Symbolic Math Toolbox Version 5.5 (R2010b)<br />
System Identification Toolbox Version 7.4.1 (R2010b)<br />
Wavelet Toolbox Version 4.6 (R2010b)<br />
</small></tt></div><br />
<br />
Oczywiście możemy sami dopisywać własne procedury, a także korzystać z oprogramowania udostępnionego przez innych twórców. Jako przykład mogą tu posłużyć pakiety do analizy danych biomedycznych [http://sccn.ucsd.edu/eeglab/ EEGLAB] czy obrazów MRI [http://www.fil.ion.ucl.ac.uk/spm/ SPM] rozwijane przez niezależne grupy obejmujące badaczy i programistów. Również procedury [http://octave.sourceforge.net/ Octave-Forge] tworzone w ramach projektu GNU Octave mogą współpracować wymiennie z Matlabem.<br />
<br />
Python również pozwala na korzystanie z pisanych dla niego pakietów oprogramowania. Musimy je jednak odszukać, ściągnąć i zainstalować sami. W wersji podstawowej będą to:<br />
* python &mdash; podstawowy interpreter/kompilator języka Python;<br />
* numpy &mdash; biblioteka funkcji matematycznych i obliczeniowych;<br />
* scipy &mdash; zestaw bardziej zaawansowanych procedur numerycznych;<br />
* matplotlib &mdash; procedury graficzne do sporządzania wykresów i wizualizacji wyników.<br />
:(Uwaga: Mając zainstalowane bilioteki numpy, scipy i matplotlib możemy w programie używać podstawowych funkcji wszystkich tych modułów jedną komendą: <tt>import&nbsp;pylab</tt>.)<br />
<br />
[http://pypi.python.org/pypi?%3Aaction=index Lista projektów programistycznych w Pythonie] obejmuje różnorodne tematy i jest duża szansa znalezienia czegoś dla siebie. <br />
<br />
Warto też zwrócić uwagę na pakiet [http://mlabwrap.sourceforge.net/ mlabwrap], który pozwala korzystać z Matlaba (musi być zainstalowany w systemie) jakby był on biblioteką Pythona (z pewnymi ograniczeniami, ale wciąż rozwijany).<br />
<br />
<br />
[[Laboratorium_EEG]]/Wprowadzenie_do_Matlaba</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG/Wprowadzenie_do_Matlaba&diff=4816Laboratorium EEG/Wprowadzenie do Matlaba2016-03-01T12:44:19Z<p>Tspus: /* Ćwiczenia */</p>
<hr />
<div>[[Laboratorium_EEG]]/Wprowadzenie_do_Matlaba<br />
<br />
<br />
==Wprowadzenie==<br />
[[Plik:Matlab_splash.png|200px|thumb|right|Okno powitalne Matlaba]]<br />
Najkrócej można określić Matlab jako pakiet oprogramowania do obliczeń matematycznych wyprodukowany w firmie [http://www.mathworks.com/ MathWorks]. Jest to w istocie zintegrowane ''środowisko obliczeniowe'', w którym mamy do dyspozycji:<br />
* własny język programowania wysokiego poziomu, dający możliwość interaktywnego programowania;<br />
* środowisko zaprojektowane do pracy z macierzami numerycznymi;<br />
* specjalistyczne zestawy procedur obliczeniowych z różnych dziedzin, możliwość zmiany i dodawania własnych funkcji;<br />
* bogate możliwości graficznej prezentacji wyników 2D/3D oraz projektowania własnych interfejsów graficznych (GUI);<br />
* możliwość włączania programów napisanych w innych językach (C, C++, Fortran, Java);<br />
* okienkowo-zorientowane środowiska graficzne do uruchamiania algorytmów na podstawie ich schematów blokowych (np. Simulink);<br />
* wygodne operacje wejścia/wyjścia dla wielu typów danych (np. wav, avi, DICOM)<br />
* zintegrowane interaktywne narzędzia programistyczne: edytor i debugger.<br />
<br />
Dzięki tym możliwościom pakiet [http://www.mathworks.com/products/matlab/ Matlab] (mimo swej relatywnie wysokiej ceny) stał się bardzo popularnym narzędziem obliczeniowym, szczególnie w dziedzinie analizy danych biomedycznych. Pozwala on na dość szybkie pisanie złożonych programów obliczeniowych, pozwalając skupić się na rozwiązywaniu problemu, a nie na samym kodowaniu programu. Warto więc się z nim zapoznać, gdyż jest duża szansa natrafienia na Matlaba w trakcie kariery zawodowej absolwentów naszej specjalności.<br />
<br />
Warto również dodać, że osoby nie dysponujące dostępem do Matlaba, chcące zapoznać się z programowaniem w tym języku lub używać posiadane gotowe programy mogą skorzystać z darmowego pakietu [http://www.gnu.org/software/octave/ GNU Octave]. Język Octave jest bardzo podobny do Matlabowego i większość programów może być bez zmian przenoszona między nimi.<br />
<br />
==Matlab a Python==<br />
<br />
Ponieważ nasz kurs programowania jest oparty zasadniczo o język Python, właściwe będzie porównanie Pythona i Matlaba. W trakcie nauki programowania w Pythonie, wykorzystywaliśmy interfejs użytkownika, pozwalający nie tylko na uruchamianie programów, ale też na pracę interaktywną. Takim interfejsem jest np. stosowany przez nas <tt>idle</tt>. W Matlabie podobny interfejs jest wbudowany w program &mdash; po uruchomieniu programu dostajemy otwarte okno poleceń.<br />
[[Plik:Idle_and_Matlab.png|800px|thumb|center|Okna poleceń: po lewej Pythona (Idle), po prawej Matlaba]]<br />
Jak widać, w obu przypadkach sytuacja jest podobna. Możemy zacząć pracę w sesji interaktywnej wpisując na bieżąco polecenia, które są od razu interpretowane i wykonywane. Wyniki są natychmiast prezentowane na ekranie. Każdy z pakietów daje nam również możliwość napisania programu w osobnym edytorze tekstu, zapisania go na dysku i uruchomienia w dogodnym dla nas momencie.<br />
<br />
Podobieństw między Matlabem a Pythonem jest dużo więcej. Oba języki są językami wysokiego poziomu, co oznacza, że dużą część szczegółów implementacji naszego kodu możemy pozostawić w gestii stosowanego pakietu, pisząc programy w sposób bardziej przypominający ogólny algorytm opisany w sposób zrozumiały dla człowieka, a nie dopasowany do konkretnego komputera czy systemu operacyjnego.<br />
<br />
Python został zaprojektowany jako język ogólnego stosowania, podczas gdy Matlab był projektowany zasadniczo jako język do obliczeń naukowych. W bardziej zaawansowaną funkcjonalność numeryczną Python został wyposażony dopiero dzięki powstaniu modułów [http://www.scipy.org/ NumPy/SciPy] i [http://matplotlib.sourceforge.net/ Matplotlib]. Pakiety te wprowadzają do Pythona m. in. wielowymiarowe macierze (numpy.array), operacje na wszystkich elementach macierzy oraz szereg procedur graficznych do prezentacji wyników, używających składni parametrów niezwykle podobnej do tych z Matlaba. Wydaje się więc, że nie powinno być trudności, aby &bdquo;przesiąść&ldquo; się z jednego języka na drugi i sprawnie pisać programy. Tak w dużej mierze jest, są jednak między tymi językami subtelne różnice, które (szczególnie dla początkujących) mogą stanowić pułapkę. Najistotniejsze z tych różnic postaramy się tutaj zaprezentować.<br />
<br />
{| border="1" class="wikitable topalign"<br />
|+ '''Porównanie cech języków Matlab i Python'''<br />
! Matlab<br />
! Python (2.x)<br />
|- valign="top"<br />
| Podczas pracy interaktywnej Matlab, w odróżnieniu od Pythona, zwraca wartość każdego wyrażenia, które zlecimy mu do wykonania. Wypisywanie wyniku możemy zablokować kończąc wiersz polecenia średnikiem.<br />
| Python wykonuje polecenie, ale nie zwraca jego wyniku. Jeśli zależy nam na takim zachowaniu Pythona, możemy zastosować nakładkę [http://ipython.scipy.org/ IPython], dającą podobną funkcjonalność.<br />
|- valign="top"<br />
| Zmienne nie mają konkretnego typu, dopiero po przypisaniu im wartości możemy określić typ zmiennej.<br />
| Sytuacja jest podobna.<br />
|- valign="top"<br />
| Domyślnym typem numerycznym są liczby zmiennoprzecinkowe podwójnej precyzji. Dodatkowo, każda zmienna jest tak naprawdę macierzą zmiennych danego typu, nawet jeśli zawiera tylko jedną wartość (jest wtedy macierzą rozmiaru 1&times;1).<br />
<div style="line-height: 1"><tt><small><br />
:>> a = 3<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> class(a)<br />
:ans =<br />
:double<br />
:>> size(a)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1</small></tt></div><br />
| Spośród typów zmiennych numerycznych mamy do dyspozycji liczby całkowite i zmiennoprzecinkowe (które zachowują się inaczej w pewnych operacjach matematycznych). Macierze wprowadzone są przy użyciu pakietu NumPy.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = 3<br />
:>>> type(a)<br />
:<type 'int'><br />
:>>> a = 3.<br />
:>>> type(a)<br />
:<type 'float'></small></tt></div><br />
|- valign="top"<br />
| Macierze definiujemy z użyciem nawiasów kwadratowych.<br />
<div style="line-height: 1"><tt><small><br />
:a = [1 4; 7 2];</small></tt></div><br />
| Macierze definiujemy używając odpowiedniej funkcji<br />
<div style="line-height: 1"><tt><small><br />
:a = numpy.array([ [1,4], [7,2] ])<br />
:a = numpy.mat('[1 4; 7 2]')</small></tt></div><br />
|- valign="top"<br />
| Indeksy macierzy piszemy w nawiasach okrągłych. <br />
:<tt>a(1,3,5:7)</tt><br />
| Indeksy macierzy piszemy w nawiasach kwadratowych.<br />
:<tt>a[1,3,5:7]</tt><br />
|- valign="top"<br />
| Pierwszy indeks macierzy na numer 1.<br />
| Pierwszy indeks macierzy na numer 0.<br />
|- valign="top"<br />
| Działanie wycinka: elementy liczone od 1, ostatni zawiera się w wycinku.<br />
<div style="line-height: 1"><tt><small><br />
:>> a = linspace(1,10,10)<br />
:a = <br><br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;10<br />
:>> a(1:5)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br />
:>> a(5:end)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;10</small></tt></div><br />
| Działanie wycinka: elementy liczone od 0, ostatni element wpisany liczbowo nie zawiera się w wycinku.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.linspace(1,10,10)<br />
:>>> a<br><br />
:array([&nbsp;&nbsp;1.,&nbsp;&nbsp;&nbsp;2.,&nbsp;&nbsp;&nbsp;3.,&nbsp;&nbsp;&nbsp;4.,&nbsp;&nbsp;&nbsp;5.,&nbsp;&nbsp;&nbsp;6.,&nbsp;&nbsp;&nbsp;7.,&nbsp;&nbsp;&nbsp;8.,&nbsp;&nbsp;&nbsp;9.,&nbsp;&nbsp;10.])<br />
:>>> a[1:5] # czyli od elementu 2 do 5 (element 6 o indeksie 5 wpisany liczbowo)<br />
:array([ 2.,&nbsp;&nbsp;3.,&nbsp;&nbsp;4.,&nbsp;&nbsp;5.])<br />
:>>> a[5:] &nbsp;# czyli od elementu 6 do ostatniego (nie określonego liczbowo)<br />
:array([&nbsp;&nbsp;6.,&nbsp;&nbsp;&nbsp;7.,&nbsp;&nbsp;&nbsp;8.,&nbsp;&nbsp;&nbsp;9.,&nbsp;&nbsp;10.])</small></tt></div><br />
|- valign="top"<br />
| Łatwe tworzenie wektorów wartości z pewnego zakresu:<br />
<div style="line-height: 1"><tt><small><br />
:>> a = 1:5<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br />
:>> a = linspace(1,5,5)<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5</small></tt></div><br />
| Łatwe tworzenie wektorów wartości z pewnego zakresu z użyciem pakietu NumPy:<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.r_[1:6]<br />
:>>> a<br />
:array([1, 2, 3, 4, 5])<br />
:>>> a = numpy.linspace(1,5,5)<br />
:>>> a<br />
:array([ 1.,&nbsp;&nbsp;2.,&nbsp;&nbsp;3.,&nbsp;&nbsp;4.,&nbsp;&nbsp;5.])</small></tt></div><br />
|- valign = "top"<br />
| Macierze zachowują wszystkie swoje wymiary.<br />
| Macierze mogą zostac &bdquo;spłaszczone&rdquo; do wektorów posiadających tylko długość.<br />
|- valign = "top"<br />
| Wymiary macierzy liczą się od lewej do prawej.<br />
<div style="line-height: 1"><tt><small><br />
:>>&nbsp;c=1:8<br />
:c&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8<br />
:>>&nbsp;cr=reshape(c,[2,2,2])<br />
:cr(:,:,1)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4<br />
:cr(:,:,2)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8<br />
:>>&nbsp;cr(:,:,1)<br />
:ans&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4<br />
:>>&nbsp;cr(1,:,:)<br />
:ans(:,:,1)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:ans(:,:,2)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7</small></tt></div><br />
| Wymiary macierzy liczą się od prawej do lewej.<br />
<div style="line-height: 1"><tt><small><br />
:>>>&nbsp;c=numpy.array(range(1,9))<br />
:>>>&nbsp;c<br />
:array([1,&nbsp;2,&nbsp;3,&nbsp;4,&nbsp;5,&nbsp;6,&nbsp;7,&nbsp;8])<br />
:>>>&nbsp;cr=numpy.reshape(c,(2,2,2))<br />
:>>>&nbsp;cr<br />
:array([[[1,&nbsp;2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[3,&nbsp;4]],<br />
:&nbsp;<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[[5,&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[7,&nbsp;8]]])<br />
:>>>&nbsp;cr[0]<br />
:array([[1,&nbsp;2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[3,&nbsp;4]])<br />
:>>>&nbsp;cr[:,:,0]<br />
:array([[1,&nbsp;3],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[5,&nbsp;7]])</small></tt></div><br />
|- valign = "top"<br />
| Niektóre operatory różnią się od Pythonowych. Niektóre przykłady:<br />
* Potęgowanie: <tt>^</tt><br />
* Nie równa się: <tt>~=</tt><br />
* Dzielenie modulo: <tt>mod(x,y)</tt><br />
* Operatory logiczne &bdquo;i&rdquo;, &bdquo;lub&rdquo;, &bdquo;nie&rdquo;: <tt>& | ~</tt><br />
* Komentarz: <tt>%</tt><br />
| Niektóre operatory różnią się od Matlabowych. Niektóre przykłady:<br />
* Potęgowanie: <tt>**</tt><br />
* Nie równa się: <tt>!=</tt><br />
* Dzielenie modulo: <tt>x % y</tt><br />
* Operatory logiczne &bdquo;i&rdquo;, &bdquo;lub&rdquo;, &bdquo;nie&rdquo;: <tt>and or not</tt><br />
* Komentarz: <tt>#</tt><br />
|- valign="top"<br />
| Przypisanie zmiennych do siebie powoduje skopiowanie ich zawartości.<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 2 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = a<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b(2) = 0<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> a<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3</small></tt></div><br />
| Przypisanie zmiennych do siebie powoduje wyłącznie powstanie drugiej nazwy tego samego obiektu. Zawartość nie jest kopiowana.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = [1,2,3]<br />
:>>> b = a<br />
:>>> b[1] = 0<br />
:>>> b<br />
:[1, 0, 3]<br />
:>>> a<br />
:[1, 0, 3]</small></tt></div><br />
|- valign="top"<br />
| Liczby zespolone są wbudowane w działanie pakietu<br />
<div style="line-height: 1"><tt><small><br />
:>> (-1)^0.5<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;0.0000 + 1.0000i</small></tt></div><br />
|Chcąc użyć liczb zespolonych musimy to explicite zaznaczyć.<br />
<div style="line-height: 1"><tt><small><br />
:>>> (-1)**0.5<br />
:<br><br />
:<font color="red">Traceback (most recent call last):<br />
:&nbsp;&nbsp;File "<pyshell#37>", line 1, in <module><br />
:&nbsp;&nbsp;&nbsp;&nbsp;(-1)**0.5<br />
:ValueError: negative number cannot be raised to a fractional power</font></small></tt></div><br />
ale<br/><br />
<div style="line-height: 1"><tt><small><br />
:>>> (-1+0j)**0.5<br />
:<br><br />
:(6.1230317691118863e-17+1j)</small></tt></div><br />
|- valign="top"<br />
| Niektóre sytuacje wyjątkowe nie powodują przerwania obliczeń, dając użytkownikowi informację o możliwym błędzie w postaci specjalnej wartości.<br />
<div style="line-height: 1"><tt><small> <br />
:>> 1/0<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;Inf</small></tt></div><br />
a także<br />
<div style="line-height: 1"><tt><small> <br />
:>> a = ones(1,3)<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
:>> b = [1 0 2]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br />
:>> a./b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;1.0000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Inf&nbsp;&nbsp;&nbsp;&nbsp;0.5000</small></tt></div><br />
| W &bdquo;czystym&rdquo; Pythonie użytkownik musi sam zadbać o obsługę wszystkich sytuacji wyjątkowych.<br />
<div style="line-height: 1"><tt><small> <br />
:>>> 1/0<br />
:<br><br />
:<font color="red">Traceback (most recent call last):<br />
:&nbsp;&nbsp;File "<pyshell#0>", line 1, in <module><br />
:&nbsp;&nbsp;&nbsp;&nbsp;1/0<br />
:ZeroDivisionError: integer division or modulo by zero</font></small></tt></div><br />
Macierze z modułu NumPy zachowują się podobnie do macierzy Matlaba:<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.ones(3)<br />
:>>> a<br />
:array([ 1.,&nbsp;&nbsp;1.,&nbsp;&nbsp;1.])<br />
:>>> b = numpy.array([1.,0.,2.])<br />
:>>> b<br />
:array([ 1.,&nbsp;&nbsp;0.,&nbsp;&nbsp;2.])<br />
:>>> a/b<br />
:array([ 1. ,&nbsp;&nbsp;inf,&nbsp;&nbsp;0.5])</small></tt></div><br />
|- valign="top"<br />
| Ponieważ każda zmienna numeryczna jest macierzą, podstawowe operatory arytmetyczne opisują działania na macierzach. W szczególności operator mnożenia realizuje mnożenie macierzy:<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = [2;-1]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1<br />
:>> a * b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1<br />
:>> b * a<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1&nbsp;&nbsp;&nbsp;&nbsp;-3</small></tt></div><br />
Aby zrealizować operację osobno dla każdej pary elementów macierzy/wektorów, stosujemy operatory arytmetyczne z kropką (wymiary macierzy muszą być zgodne):<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = [2 1]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
:>> a .* b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b .* a<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3</small></tt></div><br />
| Operatory arytmetyczne zastosowane do macierzy wykonują zadane operacje osobno dla wszystkich par elementów tych macierzy. Tak więc w szczególności operator mnożenia w Pythonie odpowiada operatorowi &bdquo;mnożenia z kropką&rdquo; w Matlabie i nie realizuje mnożenia macierzowego.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.array([1,3])<br />
:>>> a<br />
:array([1, 3])<br />
:>>> b = numpy.array([[2],[-1]])<br />
:>>> b<br />
:array([[ 2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1]])<br />
:>>> a * b<br />
:array([[ 2,&nbsp;&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1, -3]])<br />
:>>> b * a<br />
:array([[ 2,&nbsp;&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1, -3]])<br />
:<br><br />
:<br><br />
:<br><br />
:<br><br />
:<br><br />
:>>> a = numpy.array([1,3])<br />
:>>> a<br />
:array([1, 3])<br />
:>>> b = numpy.array([2,1])<br />
:>>> b<br />
:array([2, 1])<br />
:>>> a*b<br />
:array([2, 3])<br />
:>>> b*a<br />
:array([2, 3])</small></tt></div><br />
|- valign="top"<br />
| Wywołanie pomocy dla obiektu <tt>nazwa</tt>:<br />
<div style="line-height: 1"><tt><small><br />
:help nazwa</small></tt></div><br />
| Wywołanie pomocy dla obiektu <tt>nazwa</tt>:<br />
<div style="line-height: 1"><tt><small><br />
:help(nazwa)</small></tt></div><br />
|- valign="top"<br />
| Funkcje matematyczne są wbudowane.<br />
Listę funkcji elementarnych można zobaczyć pisząc:<br />
<div style="line-height: 1"><tt><small><br />
:help elfun</small></tt></div><br />
Bardziej zaawansowane funkcje można zobaczyć pisząc:<br />
<div style="line-height: 1"><tt><small><br />
:help specfun</small></tt></div><br />
<div style="line-height: 1"><tt><small><br />
:help elmat</small></tt></div><br />
| Funkcje matematyczne są dostępne po załadowaniu modułu NumPy (lub innych,np. math).<br />
|}<br />
<br />
Oczywiście powyższa tabela nie obejmuje wszystkich możliwych różnic, a tylko te najważniejsze, które mogą sprawić kłopot na początku pracy. Nie wydaje się jednak, aby miały one zasadnicze znaczenie dla sprawnego pisania programów w obu omawianych tu językach.<br />
<br />
==Piszemy program w Matlabie==<br />
<br />
Z tego co już zostało tutaj powiedziane widzimy, że osoba, która umie napisać program w Pythonie, nie powinna mieć większego kłopotu z napisaniem go również w Matlabie. Należy tylko pamiętać o pewnych różnicach języków i składni, które jednak zasadniczo, po nabyciu pewnej wprawy, nie sprawiają większych trudności.<br />
<br />
Aby sprawdzić działanie obu języków w praktyce, napiszemy kilka programów realizujących te same założenia w Pythonie i w Matlabie.<br />
<br />
===Drobne różnice składniowe===<br />
*Pisząc w języku Matlab, warto jest używać wcięć, nie są jednak konieczne. Koniec bloku zaznacza się, pisząc <tt>end</tt>.<br />
*Nie używamy dwukropków na końcu instrukcji zaczynających blok np. <tt>for</tt>, czy <tt>if</tt>.<br />
*Wyrażenie warunkowe:<br />
<br />
**<tt>if</tt><br />
<source lang="Matlab"><br />
if a < 30<br />
disp('small')<br />
elseif a < 80<br />
disp('medium')<br />
else<br />
disp('large')<br />
end<br />
</source><br />
**<tt>switch</tt><br />
<source lang="Matlab"><br />
[dayNum, dayString] = weekday(date, 'long', 'en_US');<br />
<br />
switch dayString<br />
case 'Monday'<br />
disp('Start of the work week')<br />
case 'Tuesday'<br />
disp('Day 2')<br />
case 'Wednesday'<br />
disp('Day 3')<br />
case 'Thursday'<br />
disp('Day 4')<br />
case 'Friday'<br />
disp('Last day of the work week')<br />
otherwise<br />
disp('Weekend!')<br />
end<br />
</source><br />
* Pętle<br />
<br />
**<tt>for</tt><br />
<source lang="Matlab"><br />
for i = 1:m<br />
for j = 1:n<br />
H(i,j) = 1/(i+j);<br />
end<br />
end<br />
</source><br />
Pętla <tt>for</tt>, tak samo jak w Pythonie, wymaga sekwencji. Sekwencja może być pewnym wektorem. Można też ją utworzyć w następujący sposób:<br />
<source lang="Matlab"><br />
poczatek:krok:koniec<br />
</source><br />
albo<br />
<source lang="Matlab"><br />
poczatek:koniec<br />
</source><br />
(wtedy <tt>krok = 1</tt>). Wynikiem jest wektor wartości od <tt>poczatek</tt> do <tt>koniec</tt> o kroku <tt>krok</tt>. Jest to analog <tt>range</tt> oraz <tt>numpy.arange</tt>.<br />
**<tt>while</tt><br />
<source lang="Matlab"><br />
n = 1;<br />
nFactorial = 1;<br />
while nFactorial < 1e100<br />
n = n + 1;<br />
nFactorial = nFactorial * n;<br />
end<br />
</source><br />
*Funkcje<br />
<br />
**nagłówek rozpoczyna się słowem <tt>function</tt>, na przykład:<br />
<source lang="Matlab"><br />
function [R,E,V]=R_po(t,t_rec,t_in,U_SE,t_mem,R_0,E_0,V_0,t_0,u,dt)<br />
</source><br />
**Zwykle zachowujemy w oddzielnych plikach o nazwie takiej samej, jak funkcja.<br />
<br />
===Rysujemy wykres funkcji (przykład)===<br />
<br />
Napiszmy program rysujący wykres funkcji kwadratowej na odcinku od &minus;5 do 5.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
x=linspace(-5,5,11);<br />
y=x.^2;<br />
plot(x,y,'r-');<br />
<br />
<br />
</source><br />
| <br />
| <source lang='python'><br />
import numpy<br />
import pylab<br />
x=numpy.linspace(-5,5,11)<br />
y=x**2<br />
pylab.plot(x,y,'r-')<br />
pylab.show()</source><br />
|}<br />
<br />
Zasadnicze różnice: operator potęgowania, użycie operatora z kropką, konieczność importowania modułów numerycznego i graficznego, osobna procedura do pokazania gotowego wykresu na ekranie.<br />
<br />
<br />
<br />
Narysujmy bardziej dokładnie wykres funkcji sin(''x'')/''x''.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
x=linspace(-5,5,101);<br />
y=sin(x)./x;<br />
plot(x,y);</source><br />
| <br />
| <source lang='python'><br />
import numpy as np<br />
import pylab as p<br />
x=np.linspace(-5,5,101)<br />
y=np.sin(x)/x<br />
p.plot(x,y)<br />
p.show()</source><br />
|}<br />
<br />
===Zliczamy liczbę liter===<br />
<br />
Narysujmy histogram liczebności poszczególnych liter z pierwszej księgi &bdquo;Pana Tadeusza&rdquo; A. Mickiewicza. Tekst znajdziemy [http://brain.fuw.edu.pl/edu-wiki/images/5/5b/PanTadeuszX1.txt tu]. Ściągamy plik i zapisujemy w swoim katalogu.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
fid=fopen('PanTadeuszX1.txt','rb');<br />
tekst=fread(fid,'uchar');<br />
fclose(fid);<br />
<br />
hist(tekst,min(tekst):max(tekst));<br />
xlim([double('a')-1 double('z')+1]);<br />
<br />
<br />
<br />
set(gca,'XTick',double('a'):double('z'));<br />
set(gca,'XTickLabel',['a':'z']');<br />
</source><br />
| <br />
| <source lang='python'><br />
import numpy as np<br />
import pylab as p<br />
<br />
tekst=np.fromfile('PanTadeuszX1.txt','uint8')<br />
<br />
<br />
p.hist(tekst,max(tekst)-min(tekst)+1)<br />
p.xlim(ord('a')-1,ord('z')+1)<br />
achars=[]<br />
for code in range(ord('a'),ord('z')+1):<br />
achars.append(chr(code))<br />
p.xticks(range(ord('a'),ord('z')+1),achars)<br />
<br />
p.show()<br />
</source><br />
|}<br />
<br />
Wykorzystaliśmy tutaj fakt, że litery alfabetu angielskiego są w kodzie ASCII ułożone bezpośrednio po sobie, alfabetycznie i w kolejności rosnącej. Gdybyśmy w naszym histogramie chcieli uwzględnić również polskie litery, należałoby kolejność słupków histogramu wybrać ręcznie, zgodnie z kolejnością w alfabecie polskim. Histogram musimy utworzyć z wybranych wartości (wysokości słupków) ustawionych w pożądanej kolejności. Dodatkową trudnością jest fakt, że stosowane są różne sposoby kodowania polskich liter (czyli zamiany liter na odpowiadające im wartości liczbowe). Plik tekstowy zastosowany w przykładzie wykorzystuje kodowanie &bdquo;Windows-1250&rdquo;, a Matlab domyślnie koduje napisy w standardzie Unicode. Nasz program powinien uwzględniać te fakty.<br />
<br />
==Ćwiczenia==<br />
{{Solution|title=Zadanie 1|text=<br />
[[Plik:Albrecht_Durer_Magic_Square.jpg|300px|thumb|right|<figure id="fig:1"/> Szczegół z miedziorytu Albrechta Durera zatytułowanego Melancholia I, 1514 r.]]<br />
<br />
Utwórz w Matlabie macierz z liczbami magicznego kwadratu i policz sumę elementów w każdym wierszu, kolumnie i obu przekątnych.<br />
Dodatkowo, możesz policzyć sumę liczb w narożnikach, każdej ćwiartce kwadratu i w czterech środkowych polach.<br />
<br />
Wskazówki:<br />
* W Matlabie sumę elementów macierzy zwraca funkcja <tt>sum</tt> (sprawdź jak ta funkcja działa).<br />
* Transpozycję macierzy A uzyskuje się za pomocą apostrofa tj. A'.<br />
* Elementy na przekątnej macierzy zwraca funkcja <tt>diag</tt>.<br />
* Odwracanie macierzy z lewa na prawo uzyskuje się za pomocą funkcji <tt>fliplr</tt>.<br />
* Do elementów macierzy można też się odwoływać za pomocą pojedynczego indeksu. W tej sytuacji, macierz odpowiada pojedynczej kolumnie złożonej z kolumn oryginalnej macierzy. Np. dla magicznego kwadratu A(8) odwołuje się do wartości 15 w elemencie macierzy A(4,2).<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 2|text=<br />
<br />
Utwórz w Matlabie program, który tworzy macierz z liczbami magicznego kwadratu dla dowolnego n i zwraca sumę elementów w każdym wierszu, kolumnie i obu przekątnych.<br />
<br />
Wskazówki:<br />
* W Matlabie kwadrat magiczny można wygenerować funkcją <tt>magic</tt>.<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 3|text=<br />
[[Plik:Frequency_axis.jpg|300px|thumb|right|<figure id="fig:2"/> Oś częstości zwracana przez funkcje <tt>fft</tt>. Pierwszy element zawiera częstość zerową, następnie częstości dodatnie do częstości Nyquista, a następnie częstości ujemne. Funkcja <tt>fftshift</tt> zamienia ze sobą lewą i prawą połowę osi pozostawiając częstość zerową w centrum widma.]]<br />
Napisz funkcję, której dostaje argumenty w postaci sygnału i częstości próbkowania, i przedstawia na rysunkach: dyskretną transformatę Fouriera (wielkość i przesunięcie fazowe), periodogram (kwadrat modułu transformaty Fouriera), gęstość widmową mocy oraz numeryczną weryfikację twierdzenia Parsevala.<br />
Następnie wygeneruj sygnał będący sumą dwóch sinusów o częstościach 10 i 40 Hz, długości trwania 2 s i częstości próbkowania 100 Hz i sprawdź działanie funkcji.<br />
<br />
Wskazówki:<br />
* W Matlabie dyskretną transformatę Fouriera oblicza funkcja <tt>fft</tt>.<br />
* Metody szacowania gęstości widmowej mocy można uzyskać pisząc <tt>help spectrum</tt>.<br />
* Przypomnienie: twierdzenie Parsevala mówi, że całka z gęstości widmowej mocy jest miarą całkowitej energii sygnału. Energię sygnału obliczamy jako sumę kwadratów amplitud sygnału.<br />
<br />
<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 4|text=<br />
[[Plik:Binary_tree.svg|thumb|<figure id="fig:3"/> Przykład drzewa binarnego]]Drzewo binarne jest drzewem, w którym stopień każdego wierzchołka (liczba połączeń danego wierzchołka) nie jest wyższy niż 3. Drzewo takie przedstawione jest na rysunku <xr id="fig:3"/>. Drzewo takie można wygodnie reprezentować w tablicy &mdash; jeżeli nadamy wierzchołkowi ''i''-ty element tablicy, jego lewy syn będzie miał indeks 2''i''+1, a prawy 2''i''+2 w przypadku języków, w których wektory numerowane są od zera. <br />
<br />
Jaka będzie reguła reprezentacji drzewa binarnego za pomocą wektora w językach, w których wektory indeksowane są od 1? Jak zapiszesz reprezentację drzewa z rysunku <xr id="fig:3"/> w języku Matlab?<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 5 (trudniejsze)|text=<br />
[[Plik:Histogram_PT1PL.gif|300px|thumb|right|]]Napisz w Matlabie program zliczający ilości liter I księgi &bdquo;Pana Tadeusza&rdquo; z uwzględnieniem również polskich liter.<br />
<br />
Wskazówka:<br />
* Proponowany tekst jest zapisany w kodowaniu &bdquo;Windows-1250&rdquo;.<br />
* W Matlabie jest dostępna funkcja zamieniająca wybrane kodowanie tekstu na Unicode, na przykład:<br />
::<tt>tekst_Unicode = native2unicode(tekst_Win1250,'windows-1250');</tt><br />
* Przypisanie wyniku funkcji <tt>hist</tt> do jakiejś zmiennej anuluje rysowanie histogramu. W zamian, w zmiennej tej zapisane zostaną obliczone wysokości słupków.<br />
* Kolejność polskiego alfabetu (wzbogaconego o litery dodatkowe &bdquo;q&rdquo;, &bdquo;v&rdquo; i &bdquo;x&rdquo;) to:<br />
::aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż<br />
* Aby narysować histogram dla wcześniej wyliczonych wysokości słupków użyj funkcji <tt>bar</tt>.<br />
* Opisy na osi wykresu (ich położenie i tekst) zmienić możemy używając instrukcji:<br />
::<tt>set(gca,'XTick',[1 2 3]);</tt><br />
::<tt>set(gca,'XTickLabel',['abc']')</tt><br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 6|text=<br />
[[Plik:matsurf.png|300px|thumb|]]Zbadaj przebieg zależności <math>\sin(r)/r</math> dla ''r'' będącego odległością od środka biegunowego układu współrzędnych na płaszczyźnie w zakresie &minus;10 < ''x'' < 10, &minus;10 < ''y'' < 10. Narysuj wykresy używając funkcji Matlaba <tt>mesh</tt>, <tt>surf</tt>, <tt>pcolor</tt> i <tt>contour</tt>.<br />
Dlaczego na wykresach brakuje punktu dla ''r'' = 0? Co możemy zrobić, aby wykres był kompletny?<br />
<br />
Wskazówka:<br />
* Zapoznaj się z działaniem następujących funkcji:<br />
::<tt>meshgrid</tt> (co zawierają macierze zwracane przez tę funkcję?);<br />
::<tt>shading</tt>, <tt>hidden</tt>, <tt>colormap</tt>;<br />
::<tt>subplot</tt>, <tt>xlabel</tt>, <tt>ylabel</tt>, <tt>title</tt>.<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 7|text=<br />
[[Plik:matkula.png|300px|thumb|]]Funkcje <tt>mesh</tt> czy <tt>surf</tt> służą w ogólności do rysowania obiektów trójwymiarowych. Używając ich narysuj sferę o promieniu 1.<br />
<br />
Wskazówka:<br />
* Przypomnij sobie jak opisana jest sfera w sferycznym układzie współrzędnych, a w szczególności jak transformują się współrzędne punktów sfery z układu sferycznego (''r'',&theta;,&phi;) do układu kartezjańskiego (''x'',''y'',''z'').<br />
* Aby kula nie wyglądała jak elipsoida należy skorzystać z polecenia <tt>axis equal</tt>, które ujednolica rozmiar rysunku wzdłuż osi ''x'', ''y'' i ''z''.<br />
<br />
<!--Jaką figurę opisuje układ równań<br />
::<math>x=(R+r\cos\phi)\cos\theta</math><br />
::<math>y=(R+r\cos\phi)\sin\theta</math><br />
::<math>z=r\sin\phi</math><br />
--><br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 8|text=<br />
[[Plik:Rys_mapka.png|300px|thumb|]]Matlab umożliwia przechowywanie zmiennych w plikach własnego formatu .MAT zawierających wszystkie niezbędne informacje o typach zapisanych zmiennych i oczywiście ich wartościach. Do zapisu plików służy polecenie <tt>save</tt>, a do ich wczytania polecenie <tt>load</tt>.<br />
<br />
<br />
Plik [[Plik:Book.tar.gz]] zawiera strukturę, która opisuje dekompozycję pewnego sygnału na struktury składowe &mdash; &bdquo;atomy&rdquo; za pomocą algorytmu MP. Pobierz ten plik, rozpakuj go, a jego zawartość wczytaj do Matlaba i narysuj wynik dekompozycji (wraz ze źródłowymi sygnałami) zawarty w tym pliku. Napisz funkcję rysującą wyniki dla danego kanału i wybranego atomu uwzględniającą informacje zawarte we wczytanej strukturze.<br />
<br />
{{clear}}<br />
}}<br />
<br />
==Debugger w Matlabie==<br />
<br />
Środowisko programowania w Matlabie dostarcza bardzo użytecznego narzędzia pomagającego śledzić działanie programów i niezwykle ułatwiającego wyszukiwanie błędów. Narzędzie to nazywa się z angielska ''debuggerem'' (czyli &bdquo;odrobaczaczem&rdquo; lub &bdquo;odpluskwiaczem&rdquo;). <br />
<br />
Zasada działania debuggera polega na tym, że możemy zatrzymać wykonujący się program w dowolnym miejscu, nie przerywając wykonania całkowicie, ale tylko chwilowo je wstrzymując. Robimy to przez wcześniejsze wstawienie w tekście programu (który musi być widoczny w oknie Edytora) specjalnych ''punktów zatrzymania'' (ang. ''breakpoints''). Pokażemy to na przykładzie prostego programu. Na rysunku poniżej widzimy fragment okna Edytora Matlaba z widocznym interesującym nas fragmentem programu. <br />
<br />
[[Plik:matldeb1.gif]]<br />
<br />
Załóżmy, że chcemy zobaczyć czy pętla w wierszach 3-5 programu prawidłowo sumuje wartości. W tym celu w wierszu 4 umieszczamy punkt zatrzymania, ustawiając kursor w edytorze na tym wierszu i używając guzika z paska poleceń:<br />
<br />
[[Plik:matldeb2.gif]]<br />
<br />
Po naciśnięciu guzika &bdquo;Set/clear breakpoint&rdquo; (&bdquo;Ustaw/skasuj punkt zatrzymania&rdquo;) po lewej stronie wiersza 4 pojawia się czerwona kropka oznaczająca, że w tym miejscu program zostanie wstrzymany.<br />
<br />
[[Plik:matldeb3.gif]]<br />
<br />
Pozostaje nam teraz uruchomić nasz program. Można to zrobić wpisując odpowiednie polecenie w oknie Poleceń Matlaba (''Command window'') lub naciskając guzik na pasku poleceń:<br />
<br />
[[Plik:matldeb4.gif]]<br />
<br />
Program wykona się aż do napotkania punktu zatrzymania. Wtedy wykonanie zostaje przerwane i w oknie Poleceń zauważymy, że znak zachęty ma dopisaną literę &bdquo;K&rdquo;. Zielona strzałka z lewej strony wiersza programu wskazuje jaka komenda programu oczekuje na wykonanie. W oknie Obszar roboczy (''Workspace'') widzimy wartości wszystkich zmiennych naszego programu, możemy też w oknie Poleceń wpisać dowolne wyrażenie (np. <tt>suma*3</tt>) i zobaczyć jego wynik. Od tej chwili możemy też wykonywać nasz program krok po kroku naciskając odpowiedni guzik z paska poleceń albo wykonać program do końca (lub następnego punktu zatrzymania). <br />
<br />
[[Plik:matldeb5.gif]]<br />
<br />
==Informacje dodatkowe==<br />
<br />
Matlab wyposażony jest w tzw. ''toolboxy'' czyli pakiety procedur powiązanych tematycznie do rozwiązywania problemów z jakiejś dziedziny. Pakiety takie można zakupić u producenta (The MathWorks Inc.); aby sprawdzić jakie są aktualnie zainstalowane, wywołujemy polecenie Matlaba <tt>ver</tt>. W rezultacie dostajemy listę podobną do prezentowanej poniżej.<br />
<br />
<div style="line-height: 1"><tt><small><br />
>> ver<br />
-------------------------------------------------------------------------------------<br />
MATLAB Version 7.11.0.584 (R2010b)<br />
MATLAB License Number: 123456<br />
Operating System: Microsoft Windows 7 Version 6.1 (Build 7600)<br />
Java VM Version: Java 1.6.0_17-b04 with Sun Microsystems Inc. Java HotSpot(TM) Client VM mixed mode<br />
-------------------------------------------------------------------------------------<br />
MATLAB Version 7.11 (R2010b)<br />
Simulink Version 7.6 (R2010b)<br />
Bioinformatics Toolbox Version 3.6 (R2010b)<br />
Communications Blockset Version 5.0 (R2010b)<br />
Communications Toolbox Version 4.6 (R2010b)<br />
Control System Toolbox Version 9.0 (R2010b)<br />
Curve Fitting Toolbox Version 3.0 (R2010b)<br />
Data Acquisition Toolbox Version 2.17 (R2010b)<br />
Database Toolbox Version 3.8 (R2010b)<br />
Filter Design Toolbox Version 4.7.1 (R2010b)<br />
Financial Toolbox Version 3.8 (R2010b)<br />
Fixed-Point Toolbox Version 3.2 (R2010b)<br />
Global Optimization Toolbox Version 3.1 (R2010b)<br />
Image Acquisition Toolbox Version 4.0 (R2010b)<br />
Image Processing Toolbox Version 7.1 (R2010b)<br />
Instrument Control Toolbox Version 2.11 (R2010b)<br />
MATLAB Builder EX Version 1.3 (R2010b)<br />
MATLAB Builder NE Version 3.2 (R2010b)<br />
MATLAB Compiler Version 4.14 (R2010b)<br />
Mapping Toolbox Version 3.2 (R2010b)<br />
Neural Network Toolbox Version 7.0 (R2010b)<br />
Optimization Toolbox Version 5.1 (R2010b)<br />
Parallel Computing Toolbox Version 5.0 (R2010b)<br />
Parallel Computing Toolbox Version 5.0 (R2010b)<br />
Partial Differential Equation Toolbox Version 1.0.17 (R2010b)<br />
Real-Time Workshop Version 7.6 (R2010b)<br />
Robust Control Toolbox Version 3.5 (R2010b)<br />
Signal Processing Blockset Version 7.1 (R2010b)<br />
Signal Processing Toolbox Version 6.14 (R2010b)<br />
Simulink Control Design Version 3.2 (R2010b)<br />
Simulink Design Optimization Version 1.2 (R2010b)<br />
Simulink Fixed Point Version 6.4 (R2010b)<br />
Statistics Toolbox Version 7.4 (R2010b)<br />
Symbolic Math Toolbox Version 5.5 (R2010b)<br />
System Identification Toolbox Version 7.4.1 (R2010b)<br />
Wavelet Toolbox Version 4.6 (R2010b)<br />
</small></tt></div><br />
<br />
Oczywiście możemy sami dopisywać własne procedury, a także korzystać z oprogramowania udostępnionego przez innych twórców. Jako przykład mogą tu posłużyć pakiety do analizy danych biomedycznych [http://sccn.ucsd.edu/eeglab/ EEGLAB] czy obrazów MRI [http://www.fil.ion.ucl.ac.uk/spm/ SPM] rozwijane przez niezależne grupy obejmujące badaczy i programistów. Również procedury [http://octave.sourceforge.net/ Octave-Forge] tworzone w ramach projektu GNU Octave mogą współpracować wymiennie z Matlabem.<br />
<br />
Python również pozwala na korzystanie z pisanych dla niego pakietów oprogramowania. Musimy je jednak odszukać, ściągnąć i zainstalować sami. W wersji podstawowej będą to:<br />
* python &mdash; podstawowy interpreter/kompilator języka Python;<br />
* numpy &mdash; biblioteka funkcji matematycznych i obliczeniowych;<br />
* scipy &mdash; zestaw bardziej zaawansowanych procedur numerycznych;<br />
* matplotlib &mdash; procedury graficzne do sporządzania wykresów i wizualizacji wyników.<br />
:(Uwaga: Mając zainstalowane bilioteki numpy, scipy i matplotlib możemy w programie używać podstawowych funkcji wszystkich tych modułów jedną komendą: <tt>import&nbsp;pylab</tt>.)<br />
<br />
[http://pypi.python.org/pypi?%3Aaction=index Lista projektów programistycznych w Pythonie] obejmuje różnorodne tematy i jest duża szansa znalezienia czegoś dla siebie. <br />
<br />
Warto też zwrócić uwagę na pakiet [http://mlabwrap.sourceforge.net/ mlabwrap], który pozwala korzystać z Matlaba (musi być zainstalowany w systemie) jakby był on biblioteką Pythona (z pewnymi ograniczeniami, ale wciąż rozwijany).<br />
<br />
<br />
[[Laboratorium_EEG]]/Wprowadzenie_do_Matlaba</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Laboratorium_EEG/Wprowadzenie_do_Matlaba&diff=4815Laboratorium EEG/Wprowadzenie do Matlaba2016-03-01T12:43:09Z<p>Tspus: /* Ćwiczenia */</p>
<hr />
<div>[[Laboratorium_EEG]]/Wprowadzenie_do_Matlaba<br />
<br />
<br />
==Wprowadzenie==<br />
[[Plik:Matlab_splash.png|200px|thumb|right|Okno powitalne Matlaba]]<br />
Najkrócej można określić Matlab jako pakiet oprogramowania do obliczeń matematycznych wyprodukowany w firmie [http://www.mathworks.com/ MathWorks]. Jest to w istocie zintegrowane ''środowisko obliczeniowe'', w którym mamy do dyspozycji:<br />
* własny język programowania wysokiego poziomu, dający możliwość interaktywnego programowania;<br />
* środowisko zaprojektowane do pracy z macierzami numerycznymi;<br />
* specjalistyczne zestawy procedur obliczeniowych z różnych dziedzin, możliwość zmiany i dodawania własnych funkcji;<br />
* bogate możliwości graficznej prezentacji wyników 2D/3D oraz projektowania własnych interfejsów graficznych (GUI);<br />
* możliwość włączania programów napisanych w innych językach (C, C++, Fortran, Java);<br />
* okienkowo-zorientowane środowiska graficzne do uruchamiania algorytmów na podstawie ich schematów blokowych (np. Simulink);<br />
* wygodne operacje wejścia/wyjścia dla wielu typów danych (np. wav, avi, DICOM)<br />
* zintegrowane interaktywne narzędzia programistyczne: edytor i debugger.<br />
<br />
Dzięki tym możliwościom pakiet [http://www.mathworks.com/products/matlab/ Matlab] (mimo swej relatywnie wysokiej ceny) stał się bardzo popularnym narzędziem obliczeniowym, szczególnie w dziedzinie analizy danych biomedycznych. Pozwala on na dość szybkie pisanie złożonych programów obliczeniowych, pozwalając skupić się na rozwiązywaniu problemu, a nie na samym kodowaniu programu. Warto więc się z nim zapoznać, gdyż jest duża szansa natrafienia na Matlaba w trakcie kariery zawodowej absolwentów naszej specjalności.<br />
<br />
Warto również dodać, że osoby nie dysponujące dostępem do Matlaba, chcące zapoznać się z programowaniem w tym języku lub używać posiadane gotowe programy mogą skorzystać z darmowego pakietu [http://www.gnu.org/software/octave/ GNU Octave]. Język Octave jest bardzo podobny do Matlabowego i większość programów może być bez zmian przenoszona między nimi.<br />
<br />
==Matlab a Python==<br />
<br />
Ponieważ nasz kurs programowania jest oparty zasadniczo o język Python, właściwe będzie porównanie Pythona i Matlaba. W trakcie nauki programowania w Pythonie, wykorzystywaliśmy interfejs użytkownika, pozwalający nie tylko na uruchamianie programów, ale też na pracę interaktywną. Takim interfejsem jest np. stosowany przez nas <tt>idle</tt>. W Matlabie podobny interfejs jest wbudowany w program &mdash; po uruchomieniu programu dostajemy otwarte okno poleceń.<br />
[[Plik:Idle_and_Matlab.png|800px|thumb|center|Okna poleceń: po lewej Pythona (Idle), po prawej Matlaba]]<br />
Jak widać, w obu przypadkach sytuacja jest podobna. Możemy zacząć pracę w sesji interaktywnej wpisując na bieżąco polecenia, które są od razu interpretowane i wykonywane. Wyniki są natychmiast prezentowane na ekranie. Każdy z pakietów daje nam również możliwość napisania programu w osobnym edytorze tekstu, zapisania go na dysku i uruchomienia w dogodnym dla nas momencie.<br />
<br />
Podobieństw między Matlabem a Pythonem jest dużo więcej. Oba języki są językami wysokiego poziomu, co oznacza, że dużą część szczegółów implementacji naszego kodu możemy pozostawić w gestii stosowanego pakietu, pisząc programy w sposób bardziej przypominający ogólny algorytm opisany w sposób zrozumiały dla człowieka, a nie dopasowany do konkretnego komputera czy systemu operacyjnego.<br />
<br />
Python został zaprojektowany jako język ogólnego stosowania, podczas gdy Matlab był projektowany zasadniczo jako język do obliczeń naukowych. W bardziej zaawansowaną funkcjonalność numeryczną Python został wyposażony dopiero dzięki powstaniu modułów [http://www.scipy.org/ NumPy/SciPy] i [http://matplotlib.sourceforge.net/ Matplotlib]. Pakiety te wprowadzają do Pythona m. in. wielowymiarowe macierze (numpy.array), operacje na wszystkich elementach macierzy oraz szereg procedur graficznych do prezentacji wyników, używających składni parametrów niezwykle podobnej do tych z Matlaba. Wydaje się więc, że nie powinno być trudności, aby &bdquo;przesiąść&ldquo; się z jednego języka na drugi i sprawnie pisać programy. Tak w dużej mierze jest, są jednak między tymi językami subtelne różnice, które (szczególnie dla początkujących) mogą stanowić pułapkę. Najistotniejsze z tych różnic postaramy się tutaj zaprezentować.<br />
<br />
{| border="1" class="wikitable topalign"<br />
|+ '''Porównanie cech języków Matlab i Python'''<br />
! Matlab<br />
! Python (2.x)<br />
|- valign="top"<br />
| Podczas pracy interaktywnej Matlab, w odróżnieniu od Pythona, zwraca wartość każdego wyrażenia, które zlecimy mu do wykonania. Wypisywanie wyniku możemy zablokować kończąc wiersz polecenia średnikiem.<br />
| Python wykonuje polecenie, ale nie zwraca jego wyniku. Jeśli zależy nam na takim zachowaniu Pythona, możemy zastosować nakładkę [http://ipython.scipy.org/ IPython], dającą podobną funkcjonalność.<br />
|- valign="top"<br />
| Zmienne nie mają konkretnego typu, dopiero po przypisaniu im wartości możemy określić typ zmiennej.<br />
| Sytuacja jest podobna.<br />
|- valign="top"<br />
| Domyślnym typem numerycznym są liczby zmiennoprzecinkowe podwójnej precyzji. Dodatkowo, każda zmienna jest tak naprawdę macierzą zmiennych danego typu, nawet jeśli zawiera tylko jedną wartość (jest wtedy macierzą rozmiaru 1&times;1).<br />
<div style="line-height: 1"><tt><small><br />
:>> a = 3<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> class(a)<br />
:ans =<br />
:double<br />
:>> size(a)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1</small></tt></div><br />
| Spośród typów zmiennych numerycznych mamy do dyspozycji liczby całkowite i zmiennoprzecinkowe (które zachowują się inaczej w pewnych operacjach matematycznych). Macierze wprowadzone są przy użyciu pakietu NumPy.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = 3<br />
:>>> type(a)<br />
:<type 'int'><br />
:>>> a = 3.<br />
:>>> type(a)<br />
:<type 'float'></small></tt></div><br />
|- valign="top"<br />
| Macierze definiujemy z użyciem nawiasów kwadratowych.<br />
<div style="line-height: 1"><tt><small><br />
:a = [1 4; 7 2];</small></tt></div><br />
| Macierze definiujemy używając odpowiedniej funkcji<br />
<div style="line-height: 1"><tt><small><br />
:a = numpy.array([ [1,4], [7,2] ])<br />
:a = numpy.mat('[1 4; 7 2]')</small></tt></div><br />
|- valign="top"<br />
| Indeksy macierzy piszemy w nawiasach okrągłych. <br />
:<tt>a(1,3,5:7)</tt><br />
| Indeksy macierzy piszemy w nawiasach kwadratowych.<br />
:<tt>a[1,3,5:7]</tt><br />
|- valign="top"<br />
| Pierwszy indeks macierzy na numer 1.<br />
| Pierwszy indeks macierzy na numer 0.<br />
|- valign="top"<br />
| Działanie wycinka: elementy liczone od 1, ostatni zawiera się w wycinku.<br />
<div style="line-height: 1"><tt><small><br />
:>> a = linspace(1,10,10)<br />
:a = <br><br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;10<br />
:>> a(1:5)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br />
:>> a(5:end)<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;10</small></tt></div><br />
| Działanie wycinka: elementy liczone od 0, ostatni element wpisany liczbowo nie zawiera się w wycinku.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.linspace(1,10,10)<br />
:>>> a<br><br />
:array([&nbsp;&nbsp;1.,&nbsp;&nbsp;&nbsp;2.,&nbsp;&nbsp;&nbsp;3.,&nbsp;&nbsp;&nbsp;4.,&nbsp;&nbsp;&nbsp;5.,&nbsp;&nbsp;&nbsp;6.,&nbsp;&nbsp;&nbsp;7.,&nbsp;&nbsp;&nbsp;8.,&nbsp;&nbsp;&nbsp;9.,&nbsp;&nbsp;10.])<br />
:>>> a[1:5] # czyli od elementu 2 do 5 (element 6 o indeksie 5 wpisany liczbowo)<br />
:array([ 2.,&nbsp;&nbsp;3.,&nbsp;&nbsp;4.,&nbsp;&nbsp;5.])<br />
:>>> a[5:] &nbsp;# czyli od elementu 6 do ostatniego (nie określonego liczbowo)<br />
:array([&nbsp;&nbsp;6.,&nbsp;&nbsp;&nbsp;7.,&nbsp;&nbsp;&nbsp;8.,&nbsp;&nbsp;&nbsp;9.,&nbsp;&nbsp;10.])</small></tt></div><br />
|- valign="top"<br />
| Łatwe tworzenie wektorów wartości z pewnego zakresu:<br />
<div style="line-height: 1"><tt><small><br />
:>> a = 1:5<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br />
:>> a = linspace(1,5,5)<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5</small></tt></div><br />
| Łatwe tworzenie wektorów wartości z pewnego zakresu z użyciem pakietu NumPy:<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.r_[1:6]<br />
:>>> a<br />
:array([1, 2, 3, 4, 5])<br />
:>>> a = numpy.linspace(1,5,5)<br />
:>>> a<br />
:array([ 1.,&nbsp;&nbsp;2.,&nbsp;&nbsp;3.,&nbsp;&nbsp;4.,&nbsp;&nbsp;5.])</small></tt></div><br />
|- valign = "top"<br />
| Macierze zachowują wszystkie swoje wymiary.<br />
| Macierze mogą zostac &bdquo;spłaszczone&rdquo; do wektorów posiadających tylko długość.<br />
|- valign = "top"<br />
| Wymiary macierzy liczą się od lewej do prawej.<br />
<div style="line-height: 1"><tt><small><br />
:>>&nbsp;c=1:8<br />
:c&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8<br />
:>>&nbsp;cr=reshape(c,[2,2,2])<br />
:cr(:,:,1)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4<br />
:cr(:,:,2)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8<br />
:>>&nbsp;cr(:,:,1)<br />
:ans&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4<br />
:>>&nbsp;cr(1,:,:)<br />
:ans(:,:,1)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:ans(:,:,2)&nbsp;=<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7</small></tt></div><br />
| Wymiary macierzy liczą się od prawej do lewej.<br />
<div style="line-height: 1"><tt><small><br />
:>>>&nbsp;c=numpy.array(range(1,9))<br />
:>>>&nbsp;c<br />
:array([1,&nbsp;2,&nbsp;3,&nbsp;4,&nbsp;5,&nbsp;6,&nbsp;7,&nbsp;8])<br />
:>>>&nbsp;cr=numpy.reshape(c,(2,2,2))<br />
:>>>&nbsp;cr<br />
:array([[[1,&nbsp;2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[3,&nbsp;4]],<br />
:&nbsp;<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[[5,&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[7,&nbsp;8]]])<br />
:>>>&nbsp;cr[0]<br />
:array([[1,&nbsp;2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[3,&nbsp;4]])<br />
:>>>&nbsp;cr[:,:,0]<br />
:array([[1,&nbsp;3],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[5,&nbsp;7]])</small></tt></div><br />
|- valign = "top"<br />
| Niektóre operatory różnią się od Pythonowych. Niektóre przykłady:<br />
* Potęgowanie: <tt>^</tt><br />
* Nie równa się: <tt>~=</tt><br />
* Dzielenie modulo: <tt>mod(x,y)</tt><br />
* Operatory logiczne &bdquo;i&rdquo;, &bdquo;lub&rdquo;, &bdquo;nie&rdquo;: <tt>& | ~</tt><br />
* Komentarz: <tt>%</tt><br />
| Niektóre operatory różnią się od Matlabowych. Niektóre przykłady:<br />
* Potęgowanie: <tt>**</tt><br />
* Nie równa się: <tt>!=</tt><br />
* Dzielenie modulo: <tt>x % y</tt><br />
* Operatory logiczne &bdquo;i&rdquo;, &bdquo;lub&rdquo;, &bdquo;nie&rdquo;: <tt>and or not</tt><br />
* Komentarz: <tt>#</tt><br />
|- valign="top"<br />
| Przypisanie zmiennych do siebie powoduje skopiowanie ich zawartości.<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 2 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = a<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b(2) = 0<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> a<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3</small></tt></div><br />
| Przypisanie zmiennych do siebie powoduje wyłącznie powstanie drugiej nazwy tego samego obiektu. Zawartość nie jest kopiowana.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = [1,2,3]<br />
:>>> b = a<br />
:>>> b[1] = 0<br />
:>>> b<br />
:[1, 0, 3]<br />
:>>> a<br />
:[1, 0, 3]</small></tt></div><br />
|- valign="top"<br />
| Liczby zespolone są wbudowane w działanie pakietu<br />
<div style="line-height: 1"><tt><small><br />
:>> (-1)^0.5<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;0.0000 + 1.0000i</small></tt></div><br />
|Chcąc użyć liczb zespolonych musimy to explicite zaznaczyć.<br />
<div style="line-height: 1"><tt><small><br />
:>>> (-1)**0.5<br />
:<br><br />
:<font color="red">Traceback (most recent call last):<br />
:&nbsp;&nbsp;File "<pyshell#37>", line 1, in <module><br />
:&nbsp;&nbsp;&nbsp;&nbsp;(-1)**0.5<br />
:ValueError: negative number cannot be raised to a fractional power</font></small></tt></div><br />
ale<br/><br />
<div style="line-height: 1"><tt><small><br />
:>>> (-1+0j)**0.5<br />
:<br><br />
:(6.1230317691118863e-17+1j)</small></tt></div><br />
|- valign="top"<br />
| Niektóre sytuacje wyjątkowe nie powodują przerwania obliczeń, dając użytkownikowi informację o możliwym błędzie w postaci specjalnej wartości.<br />
<div style="line-height: 1"><tt><small> <br />
:>> 1/0<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;Inf</small></tt></div><br />
a także<br />
<div style="line-height: 1"><tt><small> <br />
:>> a = ones(1,3)<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
:>> b = [1 0 2]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br />
:>> a./b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;1.0000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Inf&nbsp;&nbsp;&nbsp;&nbsp;0.5000</small></tt></div><br />
| W &bdquo;czystym&rdquo; Pythonie użytkownik musi sam zadbać o obsługę wszystkich sytuacji wyjątkowych.<br />
<div style="line-height: 1"><tt><small> <br />
:>>> 1/0<br />
:<br><br />
:<font color="red">Traceback (most recent call last):<br />
:&nbsp;&nbsp;File "<pyshell#0>", line 1, in <module><br />
:&nbsp;&nbsp;&nbsp;&nbsp;1/0<br />
:ZeroDivisionError: integer division or modulo by zero</font></small></tt></div><br />
Macierze z modułu NumPy zachowują się podobnie do macierzy Matlaba:<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.ones(3)<br />
:>>> a<br />
:array([ 1.,&nbsp;&nbsp;1.,&nbsp;&nbsp;1.])<br />
:>>> b = numpy.array([1.,0.,2.])<br />
:>>> b<br />
:array([ 1.,&nbsp;&nbsp;0.,&nbsp;&nbsp;2.])<br />
:>>> a/b<br />
:array([ 1. ,&nbsp;&nbsp;inf,&nbsp;&nbsp;0.5])</small></tt></div><br />
|- valign="top"<br />
| Ponieważ każda zmienna numeryczna jest macierzą, podstawowe operatory arytmetyczne opisują działania na macierzach. W szczególności operator mnożenia realizuje mnożenie macierzy:<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = [2;-1]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1<br />
:>> a * b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1<br />
:>> b * a<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6<br />
:&nbsp;&nbsp;&nbsp;&nbsp;-1&nbsp;&nbsp;&nbsp;&nbsp;-3</small></tt></div><br />
Aby zrealizować operację osobno dla każdej pary elementów macierzy/wektorów, stosujemy operatory arytmetyczne z kropką (wymiary macierzy muszą być zgodne):<br />
<div style="line-height: 1"><tt><small><br />
:>> a = [1 3]<br />
:a =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b = [2 1]<br />
:b =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
:>> a .* b<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br />
:>> b .* a<br />
:ans =<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3</small></tt></div><br />
| Operatory arytmetyczne zastosowane do macierzy wykonują zadane operacje osobno dla wszystkich par elementów tych macierzy. Tak więc w szczególności operator mnożenia w Pythonie odpowiada operatorowi &bdquo;mnożenia z kropką&rdquo; w Matlabie i nie realizuje mnożenia macierzowego.<br />
<div style="line-height: 1"><tt><small><br />
:>>> a = numpy.array([1,3])<br />
:>>> a<br />
:array([1, 3])<br />
:>>> b = numpy.array([[2],[-1]])<br />
:>>> b<br />
:array([[ 2],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1]])<br />
:>>> a * b<br />
:array([[ 2,&nbsp;&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1, -3]])<br />
:>>> b * a<br />
:array([[ 2,&nbsp;&nbsp;6],<br />
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[-1, -3]])<br />
:<br><br />
:<br><br />
:<br><br />
:<br><br />
:<br><br />
:>>> a = numpy.array([1,3])<br />
:>>> a<br />
:array([1, 3])<br />
:>>> b = numpy.array([2,1])<br />
:>>> b<br />
:array([2, 1])<br />
:>>> a*b<br />
:array([2, 3])<br />
:>>> b*a<br />
:array([2, 3])</small></tt></div><br />
|- valign="top"<br />
| Wywołanie pomocy dla obiektu <tt>nazwa</tt>:<br />
<div style="line-height: 1"><tt><small><br />
:help nazwa</small></tt></div><br />
| Wywołanie pomocy dla obiektu <tt>nazwa</tt>:<br />
<div style="line-height: 1"><tt><small><br />
:help(nazwa)</small></tt></div><br />
|- valign="top"<br />
| Funkcje matematyczne są wbudowane.<br />
Listę funkcji elementarnych można zobaczyć pisząc:<br />
<div style="line-height: 1"><tt><small><br />
:help elfun</small></tt></div><br />
Bardziej zaawansowane funkcje można zobaczyć pisząc:<br />
<div style="line-height: 1"><tt><small><br />
:help specfun</small></tt></div><br />
<div style="line-height: 1"><tt><small><br />
:help elmat</small></tt></div><br />
| Funkcje matematyczne są dostępne po załadowaniu modułu NumPy (lub innych,np. math).<br />
|}<br />
<br />
Oczywiście powyższa tabela nie obejmuje wszystkich możliwych różnic, a tylko te najważniejsze, które mogą sprawić kłopot na początku pracy. Nie wydaje się jednak, aby miały one zasadnicze znaczenie dla sprawnego pisania programów w obu omawianych tu językach.<br />
<br />
==Piszemy program w Matlabie==<br />
<br />
Z tego co już zostało tutaj powiedziane widzimy, że osoba, która umie napisać program w Pythonie, nie powinna mieć większego kłopotu z napisaniem go również w Matlabie. Należy tylko pamiętać o pewnych różnicach języków i składni, które jednak zasadniczo, po nabyciu pewnej wprawy, nie sprawiają większych trudności.<br />
<br />
Aby sprawdzić działanie obu języków w praktyce, napiszemy kilka programów realizujących te same założenia w Pythonie i w Matlabie.<br />
<br />
===Drobne różnice składniowe===<br />
*Pisząc w języku Matlab, warto jest używać wcięć, nie są jednak konieczne. Koniec bloku zaznacza się, pisząc <tt>end</tt>.<br />
*Nie używamy dwukropków na końcu instrukcji zaczynających blok np. <tt>for</tt>, czy <tt>if</tt>.<br />
*Wyrażenie warunkowe:<br />
<br />
**<tt>if</tt><br />
<source lang="Matlab"><br />
if a < 30<br />
disp('small')<br />
elseif a < 80<br />
disp('medium')<br />
else<br />
disp('large')<br />
end<br />
</source><br />
**<tt>switch</tt><br />
<source lang="Matlab"><br />
[dayNum, dayString] = weekday(date, 'long', 'en_US');<br />
<br />
switch dayString<br />
case 'Monday'<br />
disp('Start of the work week')<br />
case 'Tuesday'<br />
disp('Day 2')<br />
case 'Wednesday'<br />
disp('Day 3')<br />
case 'Thursday'<br />
disp('Day 4')<br />
case 'Friday'<br />
disp('Last day of the work week')<br />
otherwise<br />
disp('Weekend!')<br />
end<br />
</source><br />
* Pętle<br />
<br />
**<tt>for</tt><br />
<source lang="Matlab"><br />
for i = 1:m<br />
for j = 1:n<br />
H(i,j) = 1/(i+j);<br />
end<br />
end<br />
</source><br />
Pętla <tt>for</tt>, tak samo jak w Pythonie, wymaga sekwencji. Sekwencja może być pewnym wektorem. Można też ją utworzyć w następujący sposób:<br />
<source lang="Matlab"><br />
poczatek:krok:koniec<br />
</source><br />
albo<br />
<source lang="Matlab"><br />
poczatek:koniec<br />
</source><br />
(wtedy <tt>krok = 1</tt>). Wynikiem jest wektor wartości od <tt>poczatek</tt> do <tt>koniec</tt> o kroku <tt>krok</tt>. Jest to analog <tt>range</tt> oraz <tt>numpy.arange</tt>.<br />
**<tt>while</tt><br />
<source lang="Matlab"><br />
n = 1;<br />
nFactorial = 1;<br />
while nFactorial < 1e100<br />
n = n + 1;<br />
nFactorial = nFactorial * n;<br />
end<br />
</source><br />
*Funkcje<br />
<br />
**nagłówek rozpoczyna się słowem <tt>function</tt>, na przykład:<br />
<source lang="Matlab"><br />
function [R,E,V]=R_po(t,t_rec,t_in,U_SE,t_mem,R_0,E_0,V_0,t_0,u,dt)<br />
</source><br />
**Zwykle zachowujemy w oddzielnych plikach o nazwie takiej samej, jak funkcja.<br />
<br />
===Rysujemy wykres funkcji (przykład)===<br />
<br />
Napiszmy program rysujący wykres funkcji kwadratowej na odcinku od &minus;5 do 5.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
x=linspace(-5,5,11);<br />
y=x.^2;<br />
plot(x,y,'r-');<br />
<br />
<br />
</source><br />
| <br />
| <source lang='python'><br />
import numpy<br />
import pylab<br />
x=numpy.linspace(-5,5,11)<br />
y=x**2<br />
pylab.plot(x,y,'r-')<br />
pylab.show()</source><br />
|}<br />
<br />
Zasadnicze różnice: operator potęgowania, użycie operatora z kropką, konieczność importowania modułów numerycznego i graficznego, osobna procedura do pokazania gotowego wykresu na ekranie.<br />
<br />
<br />
<br />
Narysujmy bardziej dokładnie wykres funkcji sin(''x'')/''x''.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
x=linspace(-5,5,101);<br />
y=sin(x)./x;<br />
plot(x,y);</source><br />
| <br />
| <source lang='python'><br />
import numpy as np<br />
import pylab as p<br />
x=np.linspace(-5,5,101)<br />
y=np.sin(x)/x<br />
p.plot(x,y)<br />
p.show()</source><br />
|}<br />
<br />
===Zliczamy liczbę liter===<br />
<br />
Narysujmy histogram liczebności poszczególnych liter z pierwszej księgi &bdquo;Pana Tadeusza&rdquo; A. Mickiewicza. Tekst znajdziemy [http://brain.fuw.edu.pl/edu-wiki/images/5/5b/PanTadeuszX1.txt tu]. Ściągamy plik i zapisujemy w swoim katalogu.<br />
<br />
{| <br />
|- bgcolor="#CCCCCC"<br />
! bgcolor="#CCCCCC" | Matlab <br />
! bgcolor="#FFFFFF" | &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;<br />
! bgcolor="#CCCCCC" | Python <br />
|- valign="top"<br />
| <br />
<source lang='Matlab'><br />
<br />
<br />
fid=fopen('PanTadeuszX1.txt','rb');<br />
tekst=fread(fid,'uchar');<br />
fclose(fid);<br />
<br />
hist(tekst,min(tekst):max(tekst));<br />
xlim([double('a')-1 double('z')+1]);<br />
<br />
<br />
<br />
set(gca,'XTick',double('a'):double('z'));<br />
set(gca,'XTickLabel',['a':'z']');<br />
</source><br />
| <br />
| <source lang='python'><br />
import numpy as np<br />
import pylab as p<br />
<br />
tekst=np.fromfile('PanTadeuszX1.txt','uint8')<br />
<br />
<br />
p.hist(tekst,max(tekst)-min(tekst)+1)<br />
p.xlim(ord('a')-1,ord('z')+1)<br />
achars=[]<br />
for code in range(ord('a'),ord('z')+1):<br />
achars.append(chr(code))<br />
p.xticks(range(ord('a'),ord('z')+1),achars)<br />
<br />
p.show()<br />
</source><br />
|}<br />
<br />
Wykorzystaliśmy tutaj fakt, że litery alfabetu angielskiego są w kodzie ASCII ułożone bezpośrednio po sobie, alfabetycznie i w kolejności rosnącej. Gdybyśmy w naszym histogramie chcieli uwzględnić również polskie litery, należałoby kolejność słupków histogramu wybrać ręcznie, zgodnie z kolejnością w alfabecie polskim. Histogram musimy utworzyć z wybranych wartości (wysokości słupków) ustawionych w pożądanej kolejności. Dodatkową trudnością jest fakt, że stosowane są różne sposoby kodowania polskich liter (czyli zamiany liter na odpowiadające im wartości liczbowe). Plik tekstowy zastosowany w przykładzie wykorzystuje kodowanie &bdquo;Windows-1250&rdquo;, a Matlab domyślnie koduje napisy w standardzie Unicode. Nasz program powinien uwzględniać te fakty.<br />
<br />
==Ćwiczenia==<br />
{{Solution|title=Zadanie 1|text=<br />
[[Plik:Albrecht_Durer_Magic_Square.jpg|300px|thumb|right|<figure id="fig:1"/> Szczegół z miedziorytu Albrechta Durera zatytułowanego Melancholia I, 1514 r.]]<br />
<br />
Utwórz w Matlabie macierz z liczbami magicznego kwadratu i policz sumę elementów w każdym wierszu, kolumnie i obu przekątnych.<br />
Dodatkowo, możesz policzyć sumę liczb w narożnikach, każdej ćwiartce kwadratu i w czterech środkowych polach.<br />
<br />
Wskazówki:<br />
* W Matlabie sumę elementów macierzy zwraca funkcja <tt>sum</tt> (sprawdź jak ta funkcja działa).<br />
* Transpozycję macierzy A uzyskuje się za pomocą apostrofa tj. A'.<br />
* Elementy na przekątnej macierzy zwraca funkcja <tt>diag</tt>.<br />
* Odwracanie macierzy z lewa na prawo uzyskuje się za pomocą funkcji <tt>fliplr</tt>.<br />
* Do elementów macierzy można też się odwoływać za pomocą pojedynczego indeksu. W tej sytuacji, macierz odpowiada pojedynczej kolumnie złożonej z kolumn oryginalnej macierzy. Np. dla magicznego kwadratu A(8) odwołuje się do wartości 15 w elemencie macierzy A(4,2).<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 2|text=<br />
<br />
Utwórz w Matlabie program, który tworzy macierz z liczbami magicznego kwadratu dla dowolnego n i zwraca sumę elementów w każdym wierszu, kolumnie i obu przekątnych.<br />
<br />
Wskazówki:<br />
* W Matlabie kwadrat magiczny można wygenerować funkcją <tt>magic</tt>.<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 3|text=<br />
[[Plik:Frequency_axis.jpg|300px|thumb|right|<figure id="fig:2"/> Oś częstości zwracana przez funkcje <tt>fft</tt>. Pierwszy element zawiera częstość zerową, następnie częstości dodatnie do częstości Nyquista, a następnie częstości ujemne. Funkcja <tt>fftshift</tt> zamienia ze sobą lewą i prawą połowę osi pozostawiając częstość zerową w centrum widma.]]<br />
Napisz funkcję, której dostaje argumenty w postaci sygnału i częstości próbkowania, i przedstawia na rysunkach: dyskretną transformatę Fouriera (wielkość i przesunięcie fazowe), periodogram (kwadrat modułu transformaty Fouriera), gęstość widmową mocy oraz numeryczną weryfikację twierdzenia Parsevala.<br />
Następnie wygeneruj sygnał będący sumą dwóch sinusów o częstościach 10 i 40 Hz, długości trwania 2 s i częstości próbkowania 100 Hz i sprawdź działanie funkcji.<br />
<br />
Wskazówki:<br />
* W Matlabie dyskretną transformatę Fouriera oblicza funkcja <tt>fft</tt>.<br />
* Metody szacowania gęstości widmowej mocy można uzyskać pisząc <tt>help spectrum</tt>.<br />
* Przypomnienie: twierdzenie Parsevala mówi, że całka z gęstości widmowej mocy jest miarą całkowitej energii sygnału. Energię sygnału obliczamy jako sumę kwadratów amplitud sygnału.<br />
<br />
<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 4|text=<br />
[[Plik:Binary_tree.svg|thumb|<figure id="fig:3"/> Przykład drzewa binarnego]]Drzewo binarne jest drzewem, w którym stopień każdego wierzchołka (liczba połączeń danego wierzchołka) nie jest wyższy niż 3. Drzewo takie przedstawione jest na rysunku <xr id="fig:3"/>. Drzewo takie można wygodnie reprezentować w tablicy &mdash; jeżeli nadamy wierzchołkowi ''i''-ty element tablicy, jego lewy syn będzie miał indeks 2''i''+1, a prawy 2''i''+2 w przypadku języków, w których wektory numerowane są od zera. <br />
<br />
Jaka będzie reguła reprezentacji drzewa binarnego za pomocą wektora w językach, w których wektory indeksowane są od 1? Jak zapiszesz reprezentację drzewa z rysunku <xr id="fig:3"/> w języku Matlab?<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 5 (trudniejsze)|text=<br />
[[Plik:Histogram_PT1PL.gif|300px|thumb|right|]]Napisz w Matlabie program zliczający ilości liter I księgi &bdquo;Pana Tadeusza&rdquo; z uwzględnieniem również polskich liter.<br />
<br />
Wskazówka:<br />
* Proponowany tekst jest zapisany w kodowaniu &bdquo;Windows-1250&rdquo;.<br />
* W Matlabie jest dostępna funkcja zamieniająca wybrane kodowanie tekstu na Unicode, na przykład:<br />
::<tt>tekst_Unicode = native2unicode(tekst_Win1250,'windows-1250');</tt><br />
* Przypisanie wyniku funkcji <tt>hist</tt> do jakiejś zmiennej anuluje rysowanie histogramu. W zamian, w zmiennej tej zapisane zostaną obliczone wysokości słupków.<br />
* Kolejność polskiego alfabetu (wzbogaconego o litery dodatkowe &bdquo;q&rdquo;, &bdquo;v&rdquo; i &bdquo;x&rdquo;) to:<br />
::aąbcćdeęfghijklłmnńoópqrsśtuvwxyzźż<br />
* Aby narysować histogram dla wcześniej wyliczonych wysokości słupków użyj funkcji <tt>bar</tt>.<br />
* Opisy na osi wykresu (ich położenie i tekst) zmienić możemy używając instrukcji:<br />
::<tt>set(gca,'XTick',[1 2 3]);</tt><br />
::<tt>set(gca,'XTickLabel',['abc']')</tt><br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 6|text=<br />
[[Plik:matsurf.png|300px|thumb|]]Zbadaj przebieg zależności <math>\sin(r)/r</math> dla ''r'' będącego odległością od środka biegunowego układu współrzędnych na płaszczyźnie w zakresie &minus;10 < ''x'' < 10, &minus;10 < ''y'' < 10. Narysuj wykresy używając funkcji Matlaba <tt>mesh</tt>, <tt>surf</tt>, <tt>pcolor</tt> i <tt>contour</tt>.<br />
Dlaczego na wykresach brakuje punktu dla ''r'' = 0? Co możemy zrobić, aby wykres był kompletny?<br />
<br />
Wskazówka:<br />
* Zapoznaj się z działaniem następujących funkcji:<br />
::<tt>meshgrid</tt> (co zawierają macierze zwracane przez tę funkcję?);<br />
::<tt>shading</tt>, <tt>hidden</tt>, <tt>colormap</tt>;<br />
::<tt>subplot</tt>, <tt>xlabel</tt>, <tt>ylabel</tt>, <tt>title</tt>.<br />
<br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 7|text=<br />
[[Plik:matkula.png|300px|thumb|]]Funkcje <tt>mesh</tt> czy <tt>surf</tt> służą w ogólności do rysowania obiektów trójwymiarowych. Używając ich narysuj sferę o promieniu 1.<br />
<br />
Wskazówka:<br />
* Przypomnij sobie jak opisana jest sfera w sferycznym układzie współrzędnych, a w szczególności jak transformują się współrzędne punktów sfery z układu sferycznego (''r'',&theta;,&phi;) do układu kartezjańskiego (''x'',''y'',''z'').<br />
* Aby kula nie wyglądała jak elipsoida należy skorzystać z polecenia <tt>axis equal</tt>, które ujednolica rozmiar rysunku wzdłuż osi ''x'', ''y'' i ''z''.<br />
<br />
<!--Jaką figurę opisuje układ równań<br />
::<math>x=(R+r\cos\phi)\cos\theta</math><br />
::<math>y=(R+r\cos\phi)\sin\theta</math><br />
::<math>z=r\sin\phi</math><br />
--><br />
{{clear}}<br />
}}<br />
<br />
{{Solution|title=Zadanie 8|text=<br />
[[Plik:Rys_mapka.png|300px|thumb|]]Matlab umożliwia przechowywanie zmiennych w plikach własnego formatu .MAT zawierających wszystkie niezbędne informacje o typach zapisanych zmiennych i oczywiście ich wartościach. Do zapisu plików służy polecenie <tt>save</tt>, a do ich wczytania polecenie <tt>load</tt>.<br />
[https://brain.fuw.edu.pl/edu-wiki/images/6/69/Book.mat Tutaj]<br />
<br />
[[Plik:Book.tar.gz]]<br />
<br />
znajduje się plik zawierający strukturę, która opisuje dekompozycję pewnego sygnału na struktury składowe &mdash; &bdquo;atomy&rdquo; za pomocą algorytmu MP. Pobierz ten plik, wczytaj do Matlaba i narysuj wynik dekompozycji (wraz ze źródłowymi sygnałami) zawarty w tym pliku. Napisz funkcję rysującą wyniki dla danego kanału i wybranego atomu uwzględniającą informacje zawarte we wczytanej strukturze.<br />
<br />
{{clear}}<br />
}}<br />
<br />
==Debugger w Matlabie==<br />
<br />
Środowisko programowania w Matlabie dostarcza bardzo użytecznego narzędzia pomagającego śledzić działanie programów i niezwykle ułatwiającego wyszukiwanie błędów. Narzędzie to nazywa się z angielska ''debuggerem'' (czyli &bdquo;odrobaczaczem&rdquo; lub &bdquo;odpluskwiaczem&rdquo;). <br />
<br />
Zasada działania debuggera polega na tym, że możemy zatrzymać wykonujący się program w dowolnym miejscu, nie przerywając wykonania całkowicie, ale tylko chwilowo je wstrzymując. Robimy to przez wcześniejsze wstawienie w tekście programu (który musi być widoczny w oknie Edytora) specjalnych ''punktów zatrzymania'' (ang. ''breakpoints''). Pokażemy to na przykładzie prostego programu. Na rysunku poniżej widzimy fragment okna Edytora Matlaba z widocznym interesującym nas fragmentem programu. <br />
<br />
[[Plik:matldeb1.gif]]<br />
<br />
Załóżmy, że chcemy zobaczyć czy pętla w wierszach 3-5 programu prawidłowo sumuje wartości. W tym celu w wierszu 4 umieszczamy punkt zatrzymania, ustawiając kursor w edytorze na tym wierszu i używając guzika z paska poleceń:<br />
<br />
[[Plik:matldeb2.gif]]<br />
<br />
Po naciśnięciu guzika &bdquo;Set/clear breakpoint&rdquo; (&bdquo;Ustaw/skasuj punkt zatrzymania&rdquo;) po lewej stronie wiersza 4 pojawia się czerwona kropka oznaczająca, że w tym miejscu program zostanie wstrzymany.<br />
<br />
[[Plik:matldeb3.gif]]<br />
<br />
Pozostaje nam teraz uruchomić nasz program. Można to zrobić wpisując odpowiednie polecenie w oknie Poleceń Matlaba (''Command window'') lub naciskając guzik na pasku poleceń:<br />
<br />
[[Plik:matldeb4.gif]]<br />
<br />
Program wykona się aż do napotkania punktu zatrzymania. Wtedy wykonanie zostaje przerwane i w oknie Poleceń zauważymy, że znak zachęty ma dopisaną literę &bdquo;K&rdquo;. Zielona strzałka z lewej strony wiersza programu wskazuje jaka komenda programu oczekuje na wykonanie. W oknie Obszar roboczy (''Workspace'') widzimy wartości wszystkich zmiennych naszego programu, możemy też w oknie Poleceń wpisać dowolne wyrażenie (np. <tt>suma*3</tt>) i zobaczyć jego wynik. Od tej chwili możemy też wykonywać nasz program krok po kroku naciskając odpowiedni guzik z paska poleceń albo wykonać program do końca (lub następnego punktu zatrzymania). <br />
<br />
[[Plik:matldeb5.gif]]<br />
<br />
==Informacje dodatkowe==<br />
<br />
Matlab wyposażony jest w tzw. ''toolboxy'' czyli pakiety procedur powiązanych tematycznie do rozwiązywania problemów z jakiejś dziedziny. Pakiety takie można zakupić u producenta (The MathWorks Inc.); aby sprawdzić jakie są aktualnie zainstalowane, wywołujemy polecenie Matlaba <tt>ver</tt>. W rezultacie dostajemy listę podobną do prezentowanej poniżej.<br />
<br />
<div style="line-height: 1"><tt><small><br />
>> ver<br />
-------------------------------------------------------------------------------------<br />
MATLAB Version 7.11.0.584 (R2010b)<br />
MATLAB License Number: 123456<br />
Operating System: Microsoft Windows 7 Version 6.1 (Build 7600)<br />
Java VM Version: Java 1.6.0_17-b04 with Sun Microsystems Inc. Java HotSpot(TM) Client VM mixed mode<br />
-------------------------------------------------------------------------------------<br />
MATLAB Version 7.11 (R2010b)<br />
Simulink Version 7.6 (R2010b)<br />
Bioinformatics Toolbox Version 3.6 (R2010b)<br />
Communications Blockset Version 5.0 (R2010b)<br />
Communications Toolbox Version 4.6 (R2010b)<br />
Control System Toolbox Version 9.0 (R2010b)<br />
Curve Fitting Toolbox Version 3.0 (R2010b)<br />
Data Acquisition Toolbox Version 2.17 (R2010b)<br />
Database Toolbox Version 3.8 (R2010b)<br />
Filter Design Toolbox Version 4.7.1 (R2010b)<br />
Financial Toolbox Version 3.8 (R2010b)<br />
Fixed-Point Toolbox Version 3.2 (R2010b)<br />
Global Optimization Toolbox Version 3.1 (R2010b)<br />
Image Acquisition Toolbox Version 4.0 (R2010b)<br />
Image Processing Toolbox Version 7.1 (R2010b)<br />
Instrument Control Toolbox Version 2.11 (R2010b)<br />
MATLAB Builder EX Version 1.3 (R2010b)<br />
MATLAB Builder NE Version 3.2 (R2010b)<br />
MATLAB Compiler Version 4.14 (R2010b)<br />
Mapping Toolbox Version 3.2 (R2010b)<br />
Neural Network Toolbox Version 7.0 (R2010b)<br />
Optimization Toolbox Version 5.1 (R2010b)<br />
Parallel Computing Toolbox Version 5.0 (R2010b)<br />
Parallel Computing Toolbox Version 5.0 (R2010b)<br />
Partial Differential Equation Toolbox Version 1.0.17 (R2010b)<br />
Real-Time Workshop Version 7.6 (R2010b)<br />
Robust Control Toolbox Version 3.5 (R2010b)<br />
Signal Processing Blockset Version 7.1 (R2010b)<br />
Signal Processing Toolbox Version 6.14 (R2010b)<br />
Simulink Control Design Version 3.2 (R2010b)<br />
Simulink Design Optimization Version 1.2 (R2010b)<br />
Simulink Fixed Point Version 6.4 (R2010b)<br />
Statistics Toolbox Version 7.4 (R2010b)<br />
Symbolic Math Toolbox Version 5.5 (R2010b)<br />
System Identification Toolbox Version 7.4.1 (R2010b)<br />
Wavelet Toolbox Version 4.6 (R2010b)<br />
</small></tt></div><br />
<br />
Oczywiście możemy sami dopisywać własne procedury, a także korzystać z oprogramowania udostępnionego przez innych twórców. Jako przykład mogą tu posłużyć pakiety do analizy danych biomedycznych [http://sccn.ucsd.edu/eeglab/ EEGLAB] czy obrazów MRI [http://www.fil.ion.ucl.ac.uk/spm/ SPM] rozwijane przez niezależne grupy obejmujące badaczy i programistów. Również procedury [http://octave.sourceforge.net/ Octave-Forge] tworzone w ramach projektu GNU Octave mogą współpracować wymiennie z Matlabem.<br />
<br />
Python również pozwala na korzystanie z pisanych dla niego pakietów oprogramowania. Musimy je jednak odszukać, ściągnąć i zainstalować sami. W wersji podstawowej będą to:<br />
* python &mdash; podstawowy interpreter/kompilator języka Python;<br />
* numpy &mdash; biblioteka funkcji matematycznych i obliczeniowych;<br />
* scipy &mdash; zestaw bardziej zaawansowanych procedur numerycznych;<br />
* matplotlib &mdash; procedury graficzne do sporządzania wykresów i wizualizacji wyników.<br />
:(Uwaga: Mając zainstalowane bilioteki numpy, scipy i matplotlib możemy w programie używać podstawowych funkcji wszystkich tych modułów jedną komendą: <tt>import&nbsp;pylab</tt>.)<br />
<br />
[http://pypi.python.org/pypi?%3Aaction=index Lista projektów programistycznych w Pythonie] obejmuje różnorodne tematy i jest duża szansa znalezienia czegoś dla siebie. <br />
<br />
Warto też zwrócić uwagę na pakiet [http://mlabwrap.sourceforge.net/ mlabwrap], który pozwala korzystać z Matlaba (musi być zainstalowany w systemie) jakby był on biblioteką Pythona (z pewnymi ograniczeniami, ale wciąż rozwijany).<br />
<br />
<br />
[[Laboratorium_EEG]]/Wprowadzenie_do_Matlaba</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Plik:Book.tar.gz&diff=4814Plik:Book.tar.gz2016-03-01T12:39:15Z<p>Tspus: </p>
<hr />
<div></div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Biologia_kom%C3%B3rki&diff=4782Biologia komórki2016-02-26T15:21:21Z<p>Tspus: </p>
<hr />
<div>[[Category:Biologia]]<br />
<br />
==Ramowy program wykładu z Biologii Komórki dla II roku Fizyki Medycznej i Neuroinformatyki==<br />
<br />
#[[Biologia_Komórki/Wstęp|Wstęp. Podstawowe pojęcia w biologii komórki]]<br />
#[[Biologia_Komórki/Metody badania komórek|Metody badania komórek]]<br />
#[[Biologia_Komórki/Skład molekularny komórek|Skład molekularny komórek]]<br />
#[[Biologia_Komórki/Różnorodność_kształtu_i_struktury|Różnorodność kształtu i struktury: podobieństwa i różnice pomiędzy Prokaryota i Eukaryota]]<br />
#[[Biologia_Komórki/Budowa_i_funkcje_struktur|Budowa i funkcje struktur wewnątrzkomórkowych]]<br />
#Podstawowe procesy wewnątrzkomórkowe<br />
#*[[Biologia_Komórki/Utrzymywanie_stałego_składu_środowiska_wewnętrznego|Utrzymywanie stałego składu środowiska wewnętrznego, pobieranie i wydalanie substancji]]<br />
#*[[Biologia_Komórki/Metabolizm|Metabolizm]]<br />
#*[[Biologia_Komórki/Podział_komórki_Cykl_komórkowy|Podział komórki. Cykl komórkowy]]<br />
#*[[Biologia_Komórki/Starzenie_się_śmierć_komórki|Starzenie się i śmierć komórki]]<br />
#[[Biologia_Komórki/Wpływ_czynników_egzogennych_na_homeostazę|Wpływ czynników egzogennych na homeostazę komórki oraz nowotworzenie]]<br />
#[[Biologia_Komórki/Komórki_macierzyste|Komórki macierzyste]]<br />
<br />
===Literatura===<br />
# Alberts B., Bray D., Hopkin K. i wsp. '''Podstawy Biologii Komórki Tom I i II''' Wydawnictwo Naukowe PWN, 2007 <br />
# Kilarski W. '''Strukturalne Podstawy Biologii Komórki''' Wydawnictwo Naukowe PWN, 2003 <br />
# Sawicki W. '''Histologia''' Wydawnictwo Lekarskie PZWL, 2008 <br />
<br />
autor dr Magdalena Błaszak</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Biologia_kom%C3%B3rki&diff=4684Biologia komórki2016-02-10T19:51:18Z<p>Tspus: /* Ramowy program wykładu z Biologii Komórki dla II roku Fizyki Medycznej i Neuroinformatyki */</p>
<hr />
<div>[[Category:Biologia]]<br />
<br />
==Ramowy program wykładu z Biologii Komórki dla II roku Fizyki Medycznej i Neuroinformatyki==<br />
<br />
{{EquationRef|(Eq. 1)}} <math>x^2+x+1=0</math><br />
<br />
#[[Biologia_Komórki/Wstęp|Wstęp. Podstawowe pojęcia w biologii komórki]]<br />
#[[Biologia_Komórki/Metody badania komórek|Metody badania komórek]]<br />
#[[Biologia_Komórki/Skład molekularny komórek|Skład molekularny komórek]]<br />
#[[Biologia_Komórki/Różnorodność_kształtu_i_struktury|Różnorodność kształtu i struktury: podobieństwa i różnice pomiędzy Prokaryota i Eukaryota]]<br />
#[[Biologia_Komórki/Budowa_i_funkcje_struktur|Budowa i funkcje struktur wewnątrzkomórkowych]]<br />
#Podstawowe procesy wewnątrzkomórkowe<br />
#*[[Biologia_Komórki/Utrzymywanie_stałego_składu_środowiska_wewnętrznego|Utrzymywanie stałego składu środowiska wewnętrznego, pobieranie i wydalanie substancji]]<br />
#*[[Biologia_Komórki/Metabolizm|Metabolizm]]<br />
#*[[Biologia_Komórki/Podział_komórki_Cykl_komórkowy|Podział komórki. Cykl komórkowy]]<br />
#*[[Biologia_Komórki/Starzenie_się_śmierć_komórki|Starzenie się i śmierć komórki]]<br />
#[[Biologia_Komórki/Wpływ_czynników_egzogennych_na_homeostazę|Wpływ czynników egzogennych na homeostazę komórki oraz nowotworzenie]]<br />
#[[Biologia_Komórki/Komórki_macierzyste|Komórki macierzyste]]<br />
<br />
===Literatura===<br />
# Alberts B., Bray D., Hopkin K. i wsp. '''Podstawy Biologii Komórki Tom I i II''' Wydawnictwo Naukowe PWN, 2007 <br />
# Kilarski W. '''Strukturalne Podstawy Biologii Komórki''' Wydawnictwo Naukowe PWN, 2003 <br />
# Sawicki W. '''Histologia''' Wydawnictwo Lekarskie PZWL, 2008 <br />
<br />
autor dr Magdalena Błaszak</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Biologia_kom%C3%B3rki&diff=4683Biologia komórki2016-02-10T19:51:01Z<p>Tspus: /* Ramowy program wykładu z Biologii Komórki dla II roku Fizyki Medycznej i Neuroinformatyki */</p>
<hr />
<div>[[Category:Biologia]]<br />
<br />
==Ramowy program wykładu z Biologii Komórki dla II roku Fizyki Medycznej i Neuroinformatyki==<br />
<br />
{{EquationRef|(Eq. 1)&nbsp}} <math>x^2+x+1=0</math><br />
<br />
#[[Biologia_Komórki/Wstęp|Wstęp. Podstawowe pojęcia w biologii komórki]]<br />
#[[Biologia_Komórki/Metody badania komórek|Metody badania komórek]]<br />
#[[Biologia_Komórki/Skład molekularny komórek|Skład molekularny komórek]]<br />
#[[Biologia_Komórki/Różnorodność_kształtu_i_struktury|Różnorodność kształtu i struktury: podobieństwa i różnice pomiędzy Prokaryota i Eukaryota]]<br />
#[[Biologia_Komórki/Budowa_i_funkcje_struktur|Budowa i funkcje struktur wewnątrzkomórkowych]]<br />
#Podstawowe procesy wewnątrzkomórkowe<br />
#*[[Biologia_Komórki/Utrzymywanie_stałego_składu_środowiska_wewnętrznego|Utrzymywanie stałego składu środowiska wewnętrznego, pobieranie i wydalanie substancji]]<br />
#*[[Biologia_Komórki/Metabolizm|Metabolizm]]<br />
#*[[Biologia_Komórki/Podział_komórki_Cykl_komórkowy|Podział komórki. Cykl komórkowy]]<br />
#*[[Biologia_Komórki/Starzenie_się_śmierć_komórki|Starzenie się i śmierć komórki]]<br />
#[[Biologia_Komórki/Wpływ_czynników_egzogennych_na_homeostazę|Wpływ czynników egzogennych na homeostazę komórki oraz nowotworzenie]]<br />
#[[Biologia_Komórki/Komórki_macierzyste|Komórki macierzyste]]<br />
<br />
===Literatura===<br />
# Alberts B., Bray D., Hopkin K. i wsp. '''Podstawy Biologii Komórki Tom I i II''' Wydawnictwo Naukowe PWN, 2007 <br />
# Kilarski W. '''Strukturalne Podstawy Biologii Komórki''' Wydawnictwo Naukowe PWN, 2003 <br />
# Sawicki W. '''Histologia''' Wydawnictwo Lekarskie PZWL, 2008 <br />
<br />
autor dr Magdalena Błaszak</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Biologia_kom%C3%B3rki&diff=4682Biologia komórki2016-02-10T19:50:43Z<p>Tspus: /* Ramowy program wykładu z Biologii Komórki dla II roku Fizyki Medycznej i Neuroinformatyki */</p>
<hr />
<div>[[Category:Biologia]]<br />
<br />
==Ramowy program wykładu z Biologii Komórki dla II roku Fizyki Medycznej i Neuroinformatyki==<br />
<br />
{{EquationRef|(Eq. 1) }} <math>x^2+x+1=0</math><br />
<br />
#[[Biologia_Komórki/Wstęp|Wstęp. Podstawowe pojęcia w biologii komórki]]<br />
#[[Biologia_Komórki/Metody badania komórek|Metody badania komórek]]<br />
#[[Biologia_Komórki/Skład molekularny komórek|Skład molekularny komórek]]<br />
#[[Biologia_Komórki/Różnorodność_kształtu_i_struktury|Różnorodność kształtu i struktury: podobieństwa i różnice pomiędzy Prokaryota i Eukaryota]]<br />
#[[Biologia_Komórki/Budowa_i_funkcje_struktur|Budowa i funkcje struktur wewnątrzkomórkowych]]<br />
#Podstawowe procesy wewnątrzkomórkowe<br />
#*[[Biologia_Komórki/Utrzymywanie_stałego_składu_środowiska_wewnętrznego|Utrzymywanie stałego składu środowiska wewnętrznego, pobieranie i wydalanie substancji]]<br />
#*[[Biologia_Komórki/Metabolizm|Metabolizm]]<br />
#*[[Biologia_Komórki/Podział_komórki_Cykl_komórkowy|Podział komórki. Cykl komórkowy]]<br />
#*[[Biologia_Komórki/Starzenie_się_śmierć_komórki|Starzenie się i śmierć komórki]]<br />
#[[Biologia_Komórki/Wpływ_czynników_egzogennych_na_homeostazę|Wpływ czynników egzogennych na homeostazę komórki oraz nowotworzenie]]<br />
#[[Biologia_Komórki/Komórki_macierzyste|Komórki macierzyste]]<br />
<br />
===Literatura===<br />
# Alberts B., Bray D., Hopkin K. i wsp. '''Podstawy Biologii Komórki Tom I i II''' Wydawnictwo Naukowe PWN, 2007 <br />
# Kilarski W. '''Strukturalne Podstawy Biologii Komórki''' Wydawnictwo Naukowe PWN, 2003 <br />
# Sawicki W. '''Histologia''' Wydawnictwo Lekarskie PZWL, 2008 <br />
<br />
autor dr Magdalena Błaszak</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Biologia_kom%C3%B3rki&diff=4681Biologia komórki2016-02-10T19:50:18Z<p>Tspus: /* Ramowy program wykładu z Biologii Komórki dla II roku Fizyki Medycznej i Neuroinformatyki */</p>
<hr />
<div>[[Category:Biologia]]<br />
<br />
==Ramowy program wykładu z Biologii Komórki dla II roku Fizyki Medycznej i Neuroinformatyki==<br />
<br />
{{EquationRef|(Eq. 1){{spaces|5}}}} <math>x^2+x+1=0</math><br />
<br />
#[[Biologia_Komórki/Wstęp|Wstęp. Podstawowe pojęcia w biologii komórki]]<br />
#[[Biologia_Komórki/Metody badania komórek|Metody badania komórek]]<br />
#[[Biologia_Komórki/Skład molekularny komórek|Skład molekularny komórek]]<br />
#[[Biologia_Komórki/Różnorodność_kształtu_i_struktury|Różnorodność kształtu i struktury: podobieństwa i różnice pomiędzy Prokaryota i Eukaryota]]<br />
#[[Biologia_Komórki/Budowa_i_funkcje_struktur|Budowa i funkcje struktur wewnątrzkomórkowych]]<br />
#Podstawowe procesy wewnątrzkomórkowe<br />
#*[[Biologia_Komórki/Utrzymywanie_stałego_składu_środowiska_wewnętrznego|Utrzymywanie stałego składu środowiska wewnętrznego, pobieranie i wydalanie substancji]]<br />
#*[[Biologia_Komórki/Metabolizm|Metabolizm]]<br />
#*[[Biologia_Komórki/Podział_komórki_Cykl_komórkowy|Podział komórki. Cykl komórkowy]]<br />
#*[[Biologia_Komórki/Starzenie_się_śmierć_komórki|Starzenie się i śmierć komórki]]<br />
#[[Biologia_Komórki/Wpływ_czynników_egzogennych_na_homeostazę|Wpływ czynników egzogennych na homeostazę komórki oraz nowotworzenie]]<br />
#[[Biologia_Komórki/Komórki_macierzyste|Komórki macierzyste]]<br />
<br />
===Literatura===<br />
# Alberts B., Bray D., Hopkin K. i wsp. '''Podstawy Biologii Komórki Tom I i II''' Wydawnictwo Naukowe PWN, 2007 <br />
# Kilarski W. '''Strukturalne Podstawy Biologii Komórki''' Wydawnictwo Naukowe PWN, 2003 <br />
# Sawicki W. '''Histologia''' Wydawnictwo Lekarskie PZWL, 2008 <br />
<br />
autor dr Magdalena Błaszak</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Szablon:EquationRef&diff=4680Szablon:EquationRef2016-02-10T19:47:23Z<p>Tspus: </p>
<hr />
<div>{{#if: {{{2|}}}|{{{2 }}}|{{{1}}}}}</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Szablon:EquationRef&diff=4679Szablon:EquationRef2016-02-10T19:44:41Z<p>Tspus: </p>
<hr />
<div>{{#if: {{{2|}}}|{{{2}}}|{{{1}}}}}</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Szablon:EquationRef&diff=4678Szablon:EquationRef2016-02-10T19:40:52Z<p>Tspus: Utworzono nową stronę "{{#ifeq:{{{noid}}}|noid||id="math_{{{1}}}"}}"</p>
<hr />
<div>{{#ifeq:{{{noid}}}|noid||id="math_{{{1}}}"}}</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Biologia_kom%C3%B3rki&diff=4677Biologia komórki2016-02-10T19:33:47Z<p>Tspus: /* Ramowy program wykładu z Biologii Komórki dla II roku Fizyki Medycznej i Neuroinformatyki */</p>
<hr />
<div>[[Category:Biologia]]<br />
<br />
==Ramowy program wykładu z Biologii Komórki dla II roku Fizyki Medycznej i Neuroinformatyki==<br />
<br />
{{EquationRef|Eq. 1}} <math>x^2+x+1=0</math><br />
<br />
#[[Biologia_Komórki/Wstęp|Wstęp. Podstawowe pojęcia w biologii komórki]]<br />
#[[Biologia_Komórki/Metody badania komórek|Metody badania komórek]]<br />
#[[Biologia_Komórki/Skład molekularny komórek|Skład molekularny komórek]]<br />
#[[Biologia_Komórki/Różnorodność_kształtu_i_struktury|Różnorodność kształtu i struktury: podobieństwa i różnice pomiędzy Prokaryota i Eukaryota]]<br />
#[[Biologia_Komórki/Budowa_i_funkcje_struktur|Budowa i funkcje struktur wewnątrzkomórkowych]]<br />
#Podstawowe procesy wewnątrzkomórkowe<br />
#*[[Biologia_Komórki/Utrzymywanie_stałego_składu_środowiska_wewnętrznego|Utrzymywanie stałego składu środowiska wewnętrznego, pobieranie i wydalanie substancji]]<br />
#*[[Biologia_Komórki/Metabolizm|Metabolizm]]<br />
#*[[Biologia_Komórki/Podział_komórki_Cykl_komórkowy|Podział komórki. Cykl komórkowy]]<br />
#*[[Biologia_Komórki/Starzenie_się_śmierć_komórki|Starzenie się i śmierć komórki]]<br />
#[[Biologia_Komórki/Wpływ_czynników_egzogennych_na_homeostazę|Wpływ czynników egzogennych na homeostazę komórki oraz nowotworzenie]]<br />
#[[Biologia_Komórki/Komórki_macierzyste|Komórki macierzyste]]<br />
<br />
===Literatura===<br />
# Alberts B., Bray D., Hopkin K. i wsp. '''Podstawy Biologii Komórki Tom I i II''' Wydawnictwo Naukowe PWN, 2007 <br />
# Kilarski W. '''Strukturalne Podstawy Biologii Komórki''' Wydawnictwo Naukowe PWN, 2003 <br />
# Sawicki W. '''Histologia''' Wydawnictwo Lekarskie PZWL, 2008 <br />
<br />
autor dr Magdalena Błaszak</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Metody_Biofizyki_Molekularnej_-_wyk%C5%82ad&diff=4338Metody Biofizyki Molekularnej - wykład2015-10-24T13:18:44Z<p>Tspus: Tspus przeniósł stronę Metody Biofizyki Molekularnej - lecture do Metody Biofizyki Molekularnej - wykład</p>
<hr />
<div>[[Category:Biologia]]<br />
<br />
#[[Metody_Biofizyki_Molekularnej/Wstęp|Wstęp]]<br />
#[[Metody_Biofizyki_Molekularnej/Chromatografia|Chromatografia]]<br />
#[[Metody_Biofizyki_Molekularnej/Elektroforeza|Elektroforeza]]<br />
#[[Metody_Biofizyki_Molekularnej/Wiskozymetria|Wiskozymetria]]<br />
#[[Metody_Biofizyki_Molekularnej/Ultrawirowanie_analityczne|Ultrawirowanie analityczne]]<br />
#[[Metody_Biofizyki_Molekularnej/Spektrometria_mas|Spektrometria mas]]<br />
#[[Metody_Biofizyki_Molekularnej/Krystalografia_białek|Krystalografia białek]]<br />
#[[Metody_Biofizyki_Molekularnej/Kalorymetria|Kalorymetria]]<br />
#[[Metody_Biofizyki_Molekularnej/Osmometria|Osmometria]]<br />
#[[Metody_Biofizyki_Molekularnej/Metody_relaksacyjne|Metody relaksacyjne]]<br />
#[[Metody_Biofizyki_Molekularnej/Mikroskopia_optyczna_elektronowa|Mikroskopia optyczna i elektronowa]]<br />
#[[Metody_Biofizyki_Molekularnej/Mikroskopy_ze_skanującą_sondą|Mikroskopy ze skanującą sondą]]<br />
#[[Metody_Biofizyki_Molekularnej/Szczypce_optyczne|Szczypce optyczne]]<br />
#[[Metody_Biofizyki_Molekularnej/Literatura|Literatura]]<br />
<br />
Autor: dr Beata Wielgus-Kutrowska</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Metody_Biofizyki_Molekularnej_-_lecture&diff=4339Metody Biofizyki Molekularnej - lecture2015-10-24T13:18:44Z<p>Tspus: Tspus przeniósł stronę Metody Biofizyki Molekularnej - lecture do Metody Biofizyki Molekularnej - wykład</p>
<hr />
<div>#PATRZ [[Metody Biofizyki Molekularnej - wykład]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Metody_Biofizyki_Molekularnej_-_%C4%87wiczenia&diff=4336Metody Biofizyki Molekularnej - ćwiczenia2015-10-24T13:18:34Z<p>Tspus: Tspus przeniósł stronę Metody Biofizyki Molekularnej - exercises do Metody Biofizyki Molekularnej - ćwiczenia</p>
<hr />
<div>[[Category:Biologia]]<br />
#[[Podstawy_fizyczne_metod_biofizyki_molekularnej|Podstawy fizyczne metod biofizyki molekularnej]]<br />
#[[Chromatografia_elektroforeza|Chromatografia i elektroforeza]]<br />
#[[Metody_hydrodynamiczne|Metody hydrodynamiczne]]<br />
#[[Spektrometria_mas|Spektrometria mas]]<br />
#[[Rentgenografia|Rentgenografia]]<br />
#[[Kalorymetria|Kalorymetria]]<br />
<br />
(autor dr Anna Modrak-Wójcik)<br />
<br />
<!--[[Metody_biofizyki_molekularnej_Ćwiczenia_Wersja_druk|Wersja do druku]]--></div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Metody_Biofizyki_Molekularnej_-_exercises&diff=4337Metody Biofizyki Molekularnej - exercises2015-10-24T13:18:34Z<p>Tspus: Tspus przeniósł stronę Metody Biofizyki Molekularnej - exercises do Metody Biofizyki Molekularnej - ćwiczenia</p>
<hr />
<div>#PATRZ [[Metody Biofizyki Molekularnej - ćwiczenia]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Chemia_og%C3%B3lna_-_pracownia&diff=4334Chemia ogólna - pracownia2015-10-24T13:18:15Z<p>Tspus: Tspus przeniósł stronę Chemia ogólna - workshop do Chemia ogólna - pracownia</p>
<hr />
<div>[[Category:Chemia]]<br />
#[[Chemia_ogolna_pracownia/Reakcje utleniania i redukcji (redoks)|Reakcje utleniania i redukcji (redoks) (Miareczkowanie manganometryczne)]]<br />
#[[Chemia_ogolna_pracownia/Właściwości roztworów buforowych|Właściwości roztworów buforowych (Potencjometryczne pomiary pH)]]<br />
#[[Chemia_ogolna_pracownia/Iloczyn rozpuszczalności|Iloczyn rozpuszczalności &mdash; Reakcje strącania trudno rozpuszczalnych osadów]]<br />
#[[Chemia_ogolna_pracownia/Związki kompleksowe|Związki kompleksowe (Reakcje tworzenia kompleksów, izomeria, stałe trwałości)]]<br />
#[[Chemia_ogolna_pracownia/Analiza wody|Analiza wody (oznaczanie twardości wody, wykrywanie jonów metali)]]<br />
<br />
:[[Chemia_ogolna_pracownia/Regulamin pracowni|Regulamin pracowni]]<br />
:[[Chemia_ogolna_pracownia/Wskazówki do wykonania opisu|Wskazówki do wykonania opisu]]<br />
<br />
autor: dr Elżbieta Bojarska<br />
<br />
<!---[[edu:Książki/Praktikum_z_chemii_ogólnej|Wersja do druku]]<br />
<br />
[[category:Dział]]<br />
[[category:Praktikum z chemii ogólnej]]<br />
[[category:Chemia ogólna]] --></div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Chemia_og%C3%B3lna_-_workshop&diff=4335Chemia ogólna - workshop2015-10-24T13:18:15Z<p>Tspus: Tspus przeniósł stronę Chemia ogólna - workshop do Chemia ogólna - pracownia</p>
<hr />
<div>#PATRZ [[Chemia ogólna - pracownia]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Chemia_og%C3%B3lna_-_wyk%C5%82ad&diff=4332Chemia ogólna - wykład2015-10-24T13:18:00Z<p>Tspus: Tspus przeniósł stronę Chemia ogólna - lecture do Chemia ogólna - wykład</p>
<hr />
<div>[[Category:Chemia]]<br />
#[[Chemia/Budowa atomu|Budowa atomu]]<br />
#[[Chemia/Prawidłowości w układzie okresowym|Prawidłowości w układzie okresowym]]<br />
#[[Chemia/Reakcje jądrowe|Reakcje jądrowe]]<br />
#[[Chemia/Wiązania w cząsteczkach chemicznych|Wiązania w cząsteczkach chemicznych]]<br />
#[[Chemia/Kształty przestrzenne cząsteczek wieloatomowych|Kształty przestrzenne cząsteczek wieloatomowych]]<br />
#[[Chemia/Gaz doskonały i rzeczywisty|Gaz doskonały i rzeczywisty]]<br />
#[[Chemia/Roztwory doskonałe i rzeczywiste|Roztwory doskonałe i rzeczywiste]]<br />
#[[Chemia/Dysocjacja elektrolityczna w roztworach wodnych|Dysocjacja elektrolityczna w roztworach wodnych]]<br />
#[[Chemia/Równowagi kwasowo-zasadowe|Równowagi kwasowo-zasadowe]]<br />
#[[Chemia/Reakcje redoks (utleniania i redukcji)|Reakcje redoks (utleniania i redukcji)]]<br />
#[[Chemia/Pierwiastki grupy 1 - litowce|Pierwiastki grupy 1 &mdash; litowce]]<br />
#[[Chemia/Pierwiastki grupy 2 - berylowce|Pierwiastki grupy 2 &mdash; berylowce]]<br />
#[[Chemia/Pierwiastki grupy 13 - borowce|Pierwiastki grupy 13 &mdash; borowce]]<br />
#[[Chemia/Węglowce|Węglowce]]<br />
#[[Chemia/Pierwiastki grupy 15 - azotowce|Pierwiastki grupy 15 &mdash; azotowce]]<br />
#[[Chemia/Pierwiastki grupy 16 - tlenowce|Pierwiastki grupy 16 &mdash; tlenowce]]<br />
#[[Chemia/Pierwiastki grupy 17 - fluorowce|Pierwiastki grupy 17 &mdash; fluorowce]]<br />
#[[Chemia/Pierwiastki grupy 18 - helowce|Pierwiastki grupy 18 &mdash; helowce]]<br />
#[[Chemia/Pierwiastki bloku d|Pierwiastki bloku d]]<br />
#[[Chemia/Związki chemiczne w środowisku – wpływ na organizmy żywe|Związki chemiczne w środowisku &mdash; wpływ na organizmy żywe]]<br />
<br />
autor: dr Elżbieta Bojarska<br />
<br />
<!-- [[edu:Książki/Chemia_ogólna|Wersja do druku]]<br />
<br />
[[category:Dział]]<br />
[[category:Chemia ogólna]] --></div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Chemia_og%C3%B3lna_-_lecture&diff=4333Chemia ogólna - lecture2015-10-24T13:18:00Z<p>Tspus: Tspus przeniósł stronę Chemia ogólna - lecture do Chemia ogólna - wykład</p>
<hr />
<div>#PATRZ [[Chemia ogólna - wykład]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Fizyka_II_-_OO_%C4%87wiczenia&diff=4330Fizyka II - OO ćwiczenia2015-10-24T13:17:32Z<p>Tspus: Tspus przeniósł stronę Fizyka II - OO exercises do Fizyka II - OO ćwiczenia</p>
<hr />
<div>[[category:Fizyka]]<br />
<br />
#[[Fizyka_II_OO/Ćwiczenia I: Praktyczne zastosowania indukcji elektromagnetycznej|Ćwiczenia I: Praktyczne zastosowania indukcji elektromagnetycznej]]<br />
#[[Fizyka_II_OO/Ćwiczenia II: Kondensator płaski. Pojęcie energii pola elektrycznego i magnetycznego|Ćwiczenia II: Kondensator płaski. Pojęcie energii pola elektrycznego i magnetycznego]]<br />
#[[Fizyka_II_OO/Ćwiczenia III: Prąd przesunięcia oraz obwód drgający LC|Ćwiczenia III: Prąd przesunięcia oraz obwód drgający LC]]<br />
#[[Fizyka_II_OO/Ćwiczenia IV: Budowa i własności fal elektromagnetycznych|Ćwiczenia IV: Budowa i własności fal elektromagnetycznych]]<br />
#[[Fizyka_II_OO/Ćwiczenia V: Poprawa kolokwium|Ćwiczenia V: Poprawa kolokwium]]<br />
#[[Fizyka_II_OO/Ćwiczenia VI: Załamanie światła na granicy ośrodków|Ćwiczenia VI: Załamanie światła na granicy ośrodków]]<br />
#[[Fizyka_II_OO/Ćwiczenia VII: Analiza wiązki światła przechodzącej przez polaryzatory i analizatory|Ćwiczenia VII: Analiza wiązki światła przechodzącej przez polaryzatory i analizatory]]<br />
#[[Fizyka_II_OO/Ćwiczenia VIII: Interferencja fal z dwóch źródeł punktowych. Analiza wzorów Fresnela|Ćwiczenia VIII: Interferencja fal z dwóch źródeł punktowych. Analiza wzorów Fresnela]]<br />
#[[Fizyka_II_OO/Ćwiczenia IX: Budowa interferometru Michelsona oraz interferencja światła na cienkich błonkach|Ćwiczenia IX: Budowa interferometru Michelsona oraz interferencja światła na cienkich błonkach]]<br />
#[[Fizyka_II_OO/Ćwiczenia X: Poprawa kolokwium|Ćwiczenia X: Poprawa kolokwium]]<br />
#[[Fizyka_II_OO/Ćwiczenia XI: Praktyczne zastosowania zjawiska fotoelektrycznego|Ćwiczenia XI: Praktyczne zastosowania zjawiska fotoelektrycznego]]<br />
#[[Fizyka_II_OO/Ćwiczenia XII: Dyfrakcja na szczelinie oraz siatka dyfrakcyjna|Ćwiczenia XII: Dyfrakcja na szczelinie oraz siatka dyfrakcyjna]]<br />
#[[Fizyka_II_OO/Ćwiczenia XIII: Praktyczne zastosowania zjawiska fotoelektrycznego|Ćwiczenia XIII: Praktyczne zastosowania zjawiska fotoelektrycznego]]<br />
#[[Fizyka_II_OO/Ćwiczenia XIV: Ciśnienie światła i emisja promieniowania przez atomy|Ćwiczenia XIV: Ciśnienie światła i emisja promieniowania przez atomy]]<br />
#[[Fizyka_II_OO/Ćwiczenia XV: Poprawa kolokwium|Ćwiczenia XV: Poprawa kolokwium]]<br />
<br />
Autor: dr Magdalena Błaszak<br />
<br />
<br />
[[category:Fizyka]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Fizyka_II_-_OO_exercises&diff=4331Fizyka II - OO exercises2015-10-24T13:17:32Z<p>Tspus: Tspus przeniósł stronę Fizyka II - OO exercises do Fizyka II - OO ćwiczenia</p>
<hr />
<div>#PATRZ [[Fizyka II - OO ćwiczenia]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Fizyka_II_-_FMiN_%C4%87wiczenia&diff=4328Fizyka II - FMiN ćwiczenia2015-10-24T13:17:22Z<p>Tspus: Tspus przeniósł stronę Fizyka II - FMiN exercises do Fizyka II - FMiN ćwiczenia</p>
<hr />
<div>[[category:Fizyka]]<br />
<br />
#[[FizykaII_NI/Ćwiczenia_I|Spotkanie I]]<br />
#[[FizykaII_NI/Ćwiczenia_II|Spotkanie II]]<br />
#[[FizykaII_NI/Ćwiczenia_III|Spotkanie III]]<br />
#[[FizykaII_NI/Ćwiczenia_IV|Spotkanie IV]]<br />
#[[FizykaII_NI/Ćwiczenia_V|Spotkanie V]]<br />
#[[FizykaII_NI/Ćwiczenia_VI|Spotkanie VI]]<br />
#[[FizykaII_NI/Ćwiczenia_VII|Spotkanie VII]]<br />
#[[FizykaII_NI/Ćwiczenia_VIII|Spotkanie VIII]]<br />
#[[FizykaII_NI/Ćwiczenia_IX|Spotkanie IX]]<br />
#[[FizykaII_NI/Ćwiczenia_X|Spotkanie X]]<br />
#[[FizykaII_NI/Ćwiczenia_XI|Spotkanie XI]]<br />
#[[FizykaII_NI/Ćwiczenia_XII|Spotkanie XII]]<br />
<br />
Autorzy: prof. Jacek Ciborowski, dr hab. Maciej Kamiński, prof. Danuta Kiełczewska, dr Rafał Kuś, dr Krzysztof Miernik, dr hab. Zygmunt Szefliński</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Fizyka_II_-_FMiN_exercises&diff=4329Fizyka II - FMiN exercises2015-10-24T13:17:22Z<p>Tspus: Tspus przeniósł stronę Fizyka II - FMiN exercises do Fizyka II - FMiN ćwiczenia</p>
<hr />
<div>#PATRZ [[Fizyka II - FMiN ćwiczenia]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Fizyka_III_-_FMiN_wyk%C5%82ad&diff=4326Fizyka III - FMiN wykład2015-10-24T13:17:07Z<p>Tspus: Tspus przeniósł stronę Fizyka III - FMiN lecture do Fizyka III - FMiN wykład</p>
<hr />
<div>[[category:Fizyka]]<br />
#[[Fizyka:Fizyka III/Wstęp|Wstęp]]<br />
#Drgania<br />
##[[Fizyka_III/Oscylator harmoniczny swobodny|Oscylator harmoniczny swobodny]]<br />
##[[Fizyka_III/Drgania tłumione| Drgania tłumione]]<br />
##[[Fizyka_III/Drgania wymuszone|Drgania wymuszone]]<br />
##[[Fizyka_III/Składanie drgań harmonicznych|Składanie drgań harmonicznych]]<br />
##[[Fizyka_III/Drgania układów o wielu stopniach swobody|Drgania układów o wielu stopniach swobody]]<br />
#[[Fizyka_III/Fale mechaniczne|Fale mechaniczne]]<br />
## [[Fizyka_III/Matematyczny opis fali|Matematyczny opis fali]]<br />
## [[Fizyka_III/Fale dźwiękowe|Fale dźwiękowe]]<br />
## [[Fizyka_III/Opis fal w dwóch i trzech wymiarach|Opis fal w dwóch i trzech wymiarach]]<br />
## [[Fizyka_III/Fale na granicy ośrodków|Fale na granicy ośrodków]]<br />
## [[Fizyka_III/Fale na powierzchni wody|Fale na powierzchni wody]] <br />
## [[Fizyka_III/Fale w ośrodkach o strukturze periodycznej|Fale w ośrodkach o strukturze periodycznej]]<br />
## [[Fizyka_III/Ośrodki dyspersyjne|Ośrodki dyspersyjne]]<br />
#[[Fizyka_III/Fale elektromagnetyczne|Fale elektromagnetyczne]]<br />
## [[Fizyka_III/Fale elektromagnetyczne w próżni|Fale elektromagnetyczne w próżni]]<br />
## [[Fizyka_III/Fale elektromagnetyczne w ośrodkach|Fale elektromagnetyczne w ośrodkach]]<br />
##[[Fizyka_III/Fale elektromagnetyczne w kryształach dwójłomnych|Fale elektromagnetyczne w kryształach dwójłomnych]]<br />
##[[Fizyka_III/Współczynnik załamania dielektryka i przewodnika|Współczynnik załamania dielektryka i przewodnika]]<br />
##[[Fizyka_III/Interferencja|Interferencja]]<br />
##[[Fizyka_III/Dyfrakcja|Dyfrakcja]]<br />
<br />
Autor: dr hab. Dariusz Wasik</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Fizyka_III_-_FMiN_lecture&diff=4327Fizyka III - FMiN lecture2015-10-24T13:17:07Z<p>Tspus: Tspus przeniósł stronę Fizyka III - FMiN lecture do Fizyka III - FMiN wykład</p>
<hr />
<div>#PATRZ [[Fizyka III - FMiN wykład]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Fizyka_II_-_OO_wyk%C5%82ad&diff=4324Fizyka II - OO wykład2015-10-24T13:16:55Z<p>Tspus: Tspus przeniósł stronę Fizyka II - OO lecture do Fizyka II - OO wykład</p>
<hr />
<div><br />
[[Category:Fizyka]]<br />
<br />
Fizyka II<br />
<br />
#[[FizykaII_OO/Prawa_Maxwella|Prawa Maxwella]]<br />
#[[FizykaII_OO/Układ_drgający_LC|Układ drgający LC]]<br />
#[[FizykaII_OO/Źródła_i_widmo_fal_elektromagnetycznych|Źródła i widmo fal elektromagnetycznych]]<br />
#[[FizykaII_OO/Energia_fali_elektromagnetycznej|Energia fali elektromagnetycznej]]<br />
#[[FizykaII_OO/Odbicie_i_załamanie_światła|Odbicie i załamanie światła]]<br />
#[[FizykaII_OO/Klasyczna_teoria_dyspersji|Klasyczna teoria dyspersji]]<br />
#[[FizykaII_OO/Obrazy_w_soczewkach|Obrazy w soczewkach]]<br />
#[[FizykaII_OO/Polaryzacja_fal_elektromagnetycznych|Polaryzacja fal elektromagnetycznych]]<br />
#[[FizykaII_OO/Interferencja_światła|Interferencja światła]]<br />
#[[FizykaII_OO/Dyfrakcja_światła|Dyfrakcja światła]]<br />
#[[FizykaII_OO/Dyfrakcja_światła_w_siatkach_dyfrakcyjnych|Dyfrakcja światła w siatkach dyfrakcyjnych]]<br />
#[[FizykaII_OO/Zjawisko_fotoelektryczne_zewnętrzne|Zjawisko fotoelektryczne zewnętrzne]]<br />
#[[FizykaII_OO/Budowa_atomu_a_promieniowanie_światła|Budowa atomu a promieniowanie światła]]<br />
#[[FizykaII_OO/Kwanty|Kwanty]]<br />
#[[FizykaII_OO/Zasada_działania_lasera|Zasada działania lasera]]<br />
<br />
autor dr Anna Kaczorowska</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Fizyka_II_-_OO_lecture&diff=4325Fizyka II - OO lecture2015-10-24T13:16:55Z<p>Tspus: Tspus przeniósł stronę Fizyka II - OO lecture do Fizyka II - OO wykład</p>
<hr />
<div>#PATRZ [[Fizyka II - OO wykład]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Fizyka_I_-_OO_wyk%C5%82ad&diff=4322Fizyka I - OO wykład2015-10-24T13:16:44Z<p>Tspus: Tspus przeniósł stronę Fizyka I - OO lecture do Fizyka I - OO wykład</p>
<hr />
<div>[[Category:Fizyka]]<br />
<br />
#[[Fizyka_I_OO/Wykład I|Świat wielkości fizycznych, czyli co jest we Wszechświecie małe a co duże]]<br />
#[[Fizyka_I_OO/Wykład II|Opis ruchu punktu materialnego]]<br />
#[[Fizyka_I_OO/Wykład III|Siły zrównoważone i niezrównoważone]]<br />
#[[Fizyka_I_OO/Wykład IV|Ruch przy niezrównoważonej sile: siła tarcia, siła ciężkości]]<br />
#[[Fizyka_I_OO/Wykład V|Energia, praca, moc]]<br />
#[[Fizyka_I_OO/Wykład VI|Ruch harmoniczny prosty]]<br />
#[[Fizyka_I_OO/Wykład VII|Ruch harmoniczny &mdash; tłumienie i rezonans]]<br />
#[[Fizyka_I_OO/Wykład VIII|Fale mechaniczne]]<br />
#[[Fizyka_I_OO/Wykład IX|Fale mechaniczne c.d.]]<br />
#[[Fizyka_I_OO/Wykład X|Pole oddziaływań elektrycznych]]<br />
#[[Fizyka_I_OO/Wykład XI|Prawo Gaussa]]<br />
#[[Fizyka_I_OO/Wykład XII|Prąd elektryczny &mdash; wiadomości wstępne]]<br />
#[[Fizyka_I_OO/Wykład XIII|Prawa prądu elektrycznego]]<br />
#[[Fizyka_I_OO/Wykład XIV|Pole magnetyczne wokół przewodników z prądem]]<br />
#[[Fizyka_I_OO/Wykład XV|Indukcja elektromagnetyczna]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Fizyka_I_-_OO_lecture&diff=4323Fizyka I - OO lecture2015-10-24T13:16:44Z<p>Tspus: Tspus przeniósł stronę Fizyka I - OO lecture do Fizyka I - OO wykład</p>
<hr />
<div>#PATRZ [[Fizyka I - OO wykład]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Fizyka_I_-_FMiN_wyk%C5%82ad&diff=4320Fizyka I - FMiN wykład2015-10-24T13:16:29Z<p>Tspus: Tspus przeniósł stronę Fizyka I - FMiN lecture do Fizyka I - FMiN wykład</p>
<hr />
<div><br />
[[Category:Fizyka]]<br />
<br />
<!--<br />
<categorytree mode=pages>Biologia</categorytree><br />
--><br />
<br />
<b>Fizyka I: mechanika</b><br />
<br />
Poniższe materiały zostały przygotowane na podstawie wykładu prowadzonego w roku akademickim 2009/2010.<br />
#[[FizykaI_FMiN/Wprowadzenie | Wprowadzenie]]<br />
#[[FizykaI_FMiN/Kinematyka|Kinematyka: opis ruchu]]<br />
#[[FizykaI_FMiN/Dynamika_laws|Dynamika: prawa ruchu]]<br />
#[[FizykaI_FMiN/Dynamika_equations|Dynamika: równania ruchu]]<br />
#[[FizykaI_FMiN/Dynamika_inertials|Dynamika: układy nieinercjalne]]<br />
#[[FizykaI_FMiN/Zasada_Zachowania_Pedu|Zasada zachowania pędu]]<br />
#[[FizykaI_FMiN/Zasada_Zachowania_Energii|Zasada zachowania energii]]<br />
#[[FizykaI_FMiN/Grawitacja|Grawitacja]]<br />
#[[FizykaI_FMiN/Bryła_sztywna_1|Bryła sztywna część 1]]<br />
#[[FizykaI_FMiN/Bryła_sztywna_2|Bryła sztywna część 2]]<br />
#[[FizykaI_FMiN/STW|Szczególna teoria względności]]<br />
#[[FizykaI_FMiN/Kinematyka_relativity|Kinematyka relatywistyczna]]<br />
#[[FizykaI_FMiN/Dynamika_relativity|Dynamika relatywistyczna]]<br />
#[[FizykaI_FMiN/Zderzenia_relatywistyczneZderzenia relatywistyczne]]<br />
#[[FizykaI_FMiN/Literatura|Literatura]]<br />
#[[FizykaI_FMiN/Mathematics|Aparat matematyczny wymagany/przydatny w poszczególnych zagadnieniach]]<br />
<br />
autor prof. dr hab. Aleksander Filip Żarnecki</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Fizyka_I_-_FMiN_lecture&diff=4321Fizyka I - FMiN lecture2015-10-24T13:16:29Z<p>Tspus: Tspus przeniósł stronę Fizyka I - FMiN lecture do Fizyka I - FMiN wykład</p>
<hr />
<div>#PATRZ [[Fizyka I - FMiN wykład]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Matematyka_II_-_FMiN_wyk%C5%82ad&diff=4318Matematyka II - FMiN wykład2015-10-24T13:16:12Z<p>Tspus: Tspus przeniósł stronę Matematyka II - FMiN lecture do Matematyka II - FMiN wykład</p>
<hr />
<div>[[Category:Matematyka]]<br />
:[[Matematyka:Matematyka_II_NI/Całka_Riemanna_Całka_nieoznaczona|Całka Riemanna]]<br />
:[[Matematyka:Matematyka_II_NI/Całka_nieoznaczona|Całka nieoznaczona]]<br />
:[[Matematyka:Matematyka_II_NI/Własności_RN|Własności <math> \mathbb R^N</math>]]<br />
:[[Matematyka:Matematyka_II_NI/Odwzorowania|Odwzorowania]]<br />
:[[Matematyka:Matematyka_II_NI/Rachunek_różniczkowy|Rachunek różniczkowy]]<br />
:[[Matematyka:Matematyka_II_NI/Twierdzenie_o_lokalnej odwracalności|Twierdzenie o lokalnej odwracalności]]<br />
:[[Matematyka:Matematyka_II_NI/Wzór_Taylora_dla_funkcji|Wzór Taylora dla funkcji wielu zmiennych]]<br />
:[[Matematyka:Matematyka_II_NI/Równania_różniczkowe|Równania różniczkowe]]<br />
<br />
Autor: dr hab. Jacek Wojtkiewicz</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Matematyka_II_-_FMiN_lecture&diff=4319Matematyka II - FMiN lecture2015-10-24T13:16:12Z<p>Tspus: Tspus przeniósł stronę Matematyka II - FMiN lecture do Matematyka II - FMiN wykład</p>
<hr />
<div>#PATRZ [[Matematyka II - FMiN wykład]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Matematyka_II_-_FMiN_%C4%87wiczenia&diff=4316Matematyka II - FMiN ćwiczenia2015-10-24T13:15:58Z<p>Tspus: Tspus przeniósł stronę Matematyka II - FMiN exercises do Matematyka II - FMiN ćwiczenia</p>
<hr />
<div>[[Category:Matematyka]]<br />
#[[Matematyka_II_NI/Liczby_zespolone|Liczby zespolone]]<br />
#[[Matematyka_II_NI/Algebra_liniowa|Algebra liniowa]]<br />
#[[Matematyka_II_NI/Przestrzenie_wektorowe|Przestrzenie wektorowe]]<br />
#[[Matematyka_II_NI/Wyznacznik|Wyznacznik]]<br />
#[[Matematyka_II_NI/Równania_różniczkowe_zwyczajne|Równania różniczkowe zwyczajne]]<br />
<br />
autor dr Maciej Nieszporski</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Matematyka_II_-_FMiN_exercises&diff=4317Matematyka II - FMiN exercises2015-10-24T13:15:58Z<p>Tspus: Tspus przeniósł stronę Matematyka II - FMiN exercises do Matematyka II - FMiN ćwiczenia</p>
<hr />
<div>#PATRZ [[Matematyka II - FMiN ćwiczenia]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Matematyka_I_-_OO_%C4%87wiczenia&diff=4314Matematyka I - OO ćwiczenia2015-10-24T13:15:37Z<p>Tspus: Tspus przeniósł stronę Matematyka I - OO exercises do Matematyka I - OO ćwiczenia</p>
<hr />
<div>[[Category:Matematyka]]<br />
<b>Ćwiczenia z Matematyki I dla kierunku Optyka Okularowa. Autor: Marek Olechowski</b><br />
#[[Matematyka_1_OO/Funkcje_elementarne_jednej_zmiennej_rzeczywistej|Funkcje elementarne jednej zmiennej rzeczywistej]]<br />
#[[Matematyka_1_OO/Funkcje_elementarne_dwóch_zmiennych_rzeczywistych|Funkcje elementarne dwóch zmiennych rzeczywistych]]<br />
#[[Matematyka_1_OO/Granice_ciągów_liczbowych|Granice ciągów liczbowych]]<br />
#[[Matematyka_1_OO/Sumy_szeregów_liczbowych|Sumy szeregów liczbowych]]<br />
#[[Matematyka_1_OO/Szeregi_funkcyjne|Szeregi funkcyjne]]<br />
#[[Matematyka_1_OO/Obliczanie_granic_funkcji (przy użyciu definicji Heinego)|Obliczanie granic funkcji]]<br />
#[[Matematyka_1_OO/Dodawanie_wektorów_i_rozkład_wektorów|Dodawanie wektorów i rozkład wektorów w bazie]]<br />
#[[Matematyka_1_OO/Niestandardowe_metryki|Niestandardowe metryki]]<br />
#[[Matematyka_1_OO/Zderzenia|Zderzenia]]<br />
#[[Matematyka_1_OO/Pochodne_funkcji|Pochodne funkcji]]<br />
#[[Matematyka_1_OO/Reguła_de_l'Hospitala|Reguła de l'Hospitala]]<br />
#[[Matematyka_1_OO/Badanie_przebiegu_zmienności_funkcji|Badanie przebiegu zmienności funkcji]]<br />
#[[Matematyka_1_OO/Całki_nieoznaczone|Całki nieoznaczone]]<br />
#[[Matematyka_1_OO/Całki_oznaczone|Całki oznaczone]]<br />
#[[Matematyka_1_OO/Elementy_rachunku_macierzowego|Elementy rachunku macierzowego]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Matematyka_I_-_OO_exercises&diff=4315Matematyka I - OO exercises2015-10-24T13:15:37Z<p>Tspus: Tspus przeniósł stronę Matematyka I - OO exercises do Matematyka I - OO ćwiczenia</p>
<hr />
<div>#PATRZ [[Matematyka I - OO ćwiczenia]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Matematyka_I_-_FMiN_wyk%C5%82ad&diff=4312Matematyka I - FMiN wykład2015-10-24T13:15:20Z<p>Tspus: Tspus przeniósł stronę Matematyka I - FMiN lecture do Matematyka I - FMiN wykład</p>
<hr />
<div>[[Category:Matematyka]]<br />
<br />
<center><big><math>\mathfrak{Matematyka}</math> <math>\mathfrak{1}</math></big></center><br />
<br />
<br />
#[[Logika i zbiory]]<br />
#[[Funkcje]]<br />
#[[Funkcje trygonometryczne]]<br />
#[[Wielomiany]]<br />
#[[Funkcja wykładnicza i logarytmiczna]]<br />
#[[Indukcja matematyczna]]<br />
#[[Liczby rzeczywiste]]<br />
#[[Ciągi]]<br />
#[[Ciągi 2]]<br />
#[[Funkcje i granice]]<br />
#[[Funkcje ciągłe]]<br />
#[[Pochodne]]<br />
#[[Pochodne 2]]<br />
#[[Pochodne wyższe i szereg Taylora]]<br />
#[[Szeregi]]<br />
#[[Szeregi 2]]<br />
#[[Szeregi potęgowe]]<br />
#[[Funkcje pierwotne]]<br />
<br />
<br />
autor dr hab. Jacek Wojtkiewicz<br />
<br />
<!---<br />
[[category:Matematyka I]]<br />
--></div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Matematyka_I_-_FMiN_lecture&diff=4313Matematyka I - FMiN lecture2015-10-24T13:15:20Z<p>Tspus: Tspus przeniósł stronę Matematyka I - FMiN lecture do Matematyka I - FMiN wykład</p>
<hr />
<div>#PATRZ [[Matematyka I - FMiN wykład]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Matematyka_I_-_FMiN_%C4%87wiczenia&diff=4310Matematyka I - FMiN ćwiczenia2015-10-24T13:15:07Z<p>Tspus: Tspus przeniósł stronę Matematyka I - FMiN exercises do Matematyka I - FMiN ćwiczenia</p>
<hr />
<div>[[Category:Matematyka]]<br />
<ol><br />
<li>[[Matematyka_1NI/Elementy_logiki_i_teorii_zbiorów|Elementy logiki i teorii zbiorów]]<br />
<li>Liczby naturalne:<br />
* [[Matematyka_1NI/Indukcja_matematyczna|Indukcja matematyczna]]<br />
* [[Matematyka_1NI/Dwumian_Newtona|Dwumian Newtona]]<br />
<li>Ciągi liczbowe:<br />
* [[Matematyka_1NI/Ciągi_zwykłe|Ciągi zwykłe]]<br />
* [[Matematyka_1NI/Ciągi_rekurencyjne|Ciągi rekurencyjne]]<br />
<li>[[Matematyka_1NI/Podstawowe_własności_funkcji|Podstawowe własności funkcji]]<br />
<li>Przegląd funkcji elementarnych:<br />
* [[Matematyka_1NI/Wielomiany_i_funkcje_wymierne_część_I|Wielomiany i funkcje wymierne część I]]<br />
* [[Matematyka_1NI/Funkcje_trygonometryczne|Funkcje trygonometryczne]]<br />
* [[Matematyka_1NI/Funkcje_cyklometryczne|Funkcje cyklometryczne]]<br />
* [[Matematyka_1NI/Funkcja_potęgowa|Funkcja potęgowa]]<br />
* [[Matematyka_1NI/Wartość_bezwzględna|Wartość bezwzględna]]<br />
* [[Matematyka_1NI/Funkcja_wykładnicza_i_logarytm|Funkcja wykładnicza i logarytm]]<br />
* [[Matematyka_1NI/Funkcje_hiperboliczne_i_polowe|Funkcje hiperboliczne i polowe]]<br />
<li>[[Matematyka_1NI/Granice_funkcji|Granice funkcji]]<br />
<li>Ciągłość funkcji:<br />
* [[Matematyka_1NI/Ciągłość_zwykła|Ciągłość zwykła]]<br />
* [[Matematyka_1NI/Ciągłość_jednostajna|Ciągłość jednostajna]]<br />
<li>Znajdowanie pochodnych funkcji:<br />
* [[Matematyka_1NI/Obliczanie_pochodnych_z_definicji|Obliczanie pochodnych z definicji]]<br />
* [[Matematyka_1NI/Wykorzystywanie_pochodnych_funkcji_odwrotnych|Wykorzystywanie pochodnych funkcji odwrotnych]]<br />
* [[Matematyka_1NI/Obliczanie_pochodnych_skomplikowanych_funkcji|Obliczanie pochodnych skomplikowanych funkcji]]<br />
<li>[[Matematyka_1NI/Różniczkowalność_funkcji|Różniczkowalność funkcji]]<br />
<li>Zastosowania pochodnych:<br />
* [[Matematyka_1NI/Kąty_przecięcia_krzywych|Kąty przecięcia krzywych]]<br />
* [[Matematyka_1NI/Dowodzenie_tożsamości_i_nierówności|Dowodzenie tożsamości i nierówności]]<br />
* [[Matematyka_1NI/Badanie_funkcji|Badanie funkcji]]<br />
* [[Matematyka_1NI/Twierdzenia_Rolle'a_i_Lagrange'a|Twierdzenia Rolle'a i Lagrange'a]]<br />
* [[Matematyka_1NI/Reguła_de_l'Hospitala|Reguła de l'Hospitala]]<br />
* [[Matematyka_1NI/Wzór_Taylora|Wzór Taylora]]<br />
<li>[[Matematyka_1NI/Szeregi_liczbowe|Szeregi liczbowe]]<br />
<li>[[Matematyka_1NI/Szeregi_potegowe|Szeregi potęgowe]]<br />
<li>[[Matematyka_1NI/Calka_nieoznaczona|Całka nieoznaczona]]<br />
<li>[[Matematyka_1NI/Calka_Riemanna|Całka Riemanna]]<br />
</ol><br />
<br />
autorzy dr Tomasz Radożycki i dr Maciej Nieszporski</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Matematyka_I_-_FMiN_exercises&diff=4311Matematyka I - FMiN exercises2015-10-24T13:15:07Z<p>Tspus: Tspus przeniósł stronę Matematyka I - FMiN exercises do Matematyka I - FMiN ćwiczenia</p>
<hr />
<div>#PATRZ [[Matematyka I - FMiN ćwiczenia]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Wnioskowanie_Statystyczne_-_lecture&diff=4309Wnioskowanie Statystyczne - lecture2015-10-24T13:14:11Z<p>Tspus: Tspus przeniósł stronę Wnioskowanie Statystyczne - lecture do Wnioskowanie Statystyczne - wykład</p>
<hr />
<div>#PATRZ [[Wnioskowanie Statystyczne - wykład]]</div>Tspushttp://brain.fuw.edu.pl/edu/index.php?title=Wnioskowanie_Statystyczne_-_wyk%C5%82ad&diff=4308Wnioskowanie Statystyczne - wykład2015-10-24T13:14:10Z<p>Tspus: Tspus przeniósł stronę Wnioskowanie Statystyczne - lecture do Wnioskowanie Statystyczne - wykład</p>
<hr />
<div>[[Category:Przedmioty specjalizacyjne]]<br />
Wnioskowanie statystyczne<br />
<br />
# [[WnioskowanieStatystyczne/wstep|Wstęp]]<br />
# [[WnioskowanieStatystyczne/Z_komputerem|Statystyka z komputerem]]<br />
## [[WnioskowanieStatystyczne/Bootstrap|Bootstrap]]<br />
## [[WnioskowanieStatystyczne/Testy_permutacyjne|Testy permutacyjne]]<br />
# [[WnioskowanieStatystyczne/Klasyczna_teoria|Teoria klasyczna]]<br />
## [[WnioskowanieStatystyczne/Prawdopodobienstwo|Prawdopodobieństwo]]<br />
## [[WnioskowanieStatystyczne/Rozklady|Rozkłady gęstości prawdopodobieństwa]]<br />
## [[WnioskowanieStatystyczne/Momenty|Wariancja, mediana...]]<br />
## [[WnioskowanieStatystyczne/Rozklady-przyklady|Przykładowe rozkłady]]<br />
## [[WnioskowanieStatystyczne/CLT|Centralne Twierdzenie Graniczne]]<br />
# [[WnioskowanieStatystyczne/Twierdzenie_Bayesa|Twierdzenie Bayesa]]<br />
# [[WnioskowanieStatystyczne/Statystyki_i_estymatory|Statystyki i estymatory]]<br />
# [[WnioskowanieStatystyczne/Weryfikacja_hipotez|Weryfikacja hipotez statystycznych]]<br />
## [[WnioskowanieStatystyczne/Test_t|Test ''t'' Studenta]]<br />
## [[WnioskowanieStatystyczne/Test_chi2|Test <math>\chi^2</math>]]<br />
# [[WnioskowanieStatystyczne/Testy_nieprametryczne|Testy nieparametryczne]]<br />
## [[WnioskowanieStatystyczne/Test_serii|Test serii]]<br />
## [[WnioskowanieStatystyczne/Test_Wilcoxona|Test Wilcoxona-Manna-Whitneya]]<br />
# [[WnioskowanieStatystyczne/MLF|Metoda największej wiarygodności]]<br />
# [[WnioskowanieStatystyczne/Regresja_liniowa|Regresja liniowa]]<br />
# [[WnioskowanieStatystyczne/Analiza_wariancji|Analiza wariancji]]<br />
# [[WnioskowanieStatystyczne/Elementy_statystyki_wielowymiarowej|Elementy statystyki wielowymiarowej]]<br />
<br />
{{color|green|'''Całość podręcznika jest udostępniona na licencji [http://creativecommons.org/licenses/by-sa/3.0/pl Creative Commons Uznanie autorstwa-Na tych samych zasadach 3.0 Polska].'''}} [[Grafika:CC-88x31.png]]<br />
Autor: [http://durka.name Piotr Durka].</div>Tspus