diff --git a/Makefile b/Makefile index 16301a5..78e4a2f 100644 --- a/Makefile +++ b/Makefile @@ -3,24 +3,44 @@ BASENAME=scientificcomputing-script SUBDIRS=programming plotting programmingstyle statistics bootstrap regression likelihood pointprocesses designpattern SUBTEXS=$(foreach subd, $(SUBDIRS), $(subd)/lecture/$(subd).tex) -pdf : chapters $(BASENAME).pdf +all : script chapters chapters : - for sd in $(SUBDIRS); do $(MAKE) -C $$sd/lecture pdf; done + for sd in $(SUBDIRS); do $(MAKE) -C $$sd/lecture chapter; done + +script : plots $(BASENAME).pdf + + +plots : + for sd in $(SUBDIRS); do $(MAKE) -C $$sd/lecture plots; done + + +pdf : $(BASENAME).pdf $(BASENAME).pdf : $(BASENAME).tex header.tex $(SUBTEXS) - export TEXMFOUTPUT=.; pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex -interaction=scrollmode $< || true + pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex -interaction=scrollmode $< || true + splitindex $(BASENAME).idx index : - splitindex $(BASENAME).idx - export TEXMFOUTPUT=.; pdflatex -interaction=scrollmode $(BASENAME).tex + pdflatex -interaction=scrollmode $(BASENAME).tex + splitindex $(BASENAME).idx + pdflatex -interaction=scrollmode $(BASENAME).tex | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex $(BASENAME).tex || true + +again : + pdflatex $(BASENAME).tex + +watchpdf : + while true; do ! make -s -q pdf && make pdf; sleep 0.5; done + + +watchscript : + while true; do ! make -s -q script && make script; sleep 0.5; done + clean : - rm -f *~ $(BASENAME).aux $(BASENAME).log $(BASENAME).out $(BASENAME).toc + rm -f *~ $(BASENAME).aux $(BASENAME).log $(BASENAME).out $(BASENAME).toc $(BASENAME).lo? $(BASENAME).idx $(BASENAME)-term.i* $(BASENAME)-enterm.i* $(BASENAME)-code.i* for sd in $(SUBDIRS); do $(MAKE) -C $$sd/lecture clean; done cleanall : clean - rm -f $(PDFFILE) - -watchpdf : - while true; do ! make -q pdf && make pdf; sleep 0.5; done + rm -f $(BASENAME).pdf + for sd in $(SUBDIRS); do $(MAKE) -C $$sd/lecture cleanall; done diff --git a/bootstrap/lecture/Makefile b/bootstrap/lecture/Makefile index 7abf35f..3f9c4f6 100644 --- a/bootstrap/lecture/Makefile +++ b/bootstrap/lecture/Makefile @@ -1,32 +1,13 @@ BASENAME=bootstrap -PYFILES=$(wildcard *.py) -PYPDFFILES=$(PYFILES:.py=.pdf) - all : pdf -# script: -pdf : $(BASENAME)-chapter.pdf - -$(BASENAME)-chapter.pdf : $(BASENAME)-chapter.tex $(BASENAME).tex $(PYPDFFILES) - CHAPTER=$$(( $$(sed -n -e '/contentsline {chapter}/{s/.*numberline {\([0123456789]*\)}.*/\1/; p}' $(BASENAME).aux) - 1 )); \ - PAGE=$$(sed -n -e '/contentsline {chapter}/{s/.*numberline {.*}.*}{\(.*\)}{chapter.*/\1/; p}' $(BASENAME).aux); \ - sed -i -e "s/setcounter{page}{.*}/setcounter{page}{$$PAGE}/; s/setcounter{chapter}{.*}/setcounter{chapter}{$$CHAPTER}/" $(BASENAME)-chapter.tex - pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex -interaction=scrollmode $< || true +include ../../chapter.mk -$(PYPDFFILES) : %.pdf : %.py - python $< - -clean : - rm -f *~ - rm -f $(BASENAME).aux $(BASENAME).log - rm -f $(BASENAME)-chapter.aux $(BASENAME)-chapter.log $(BASENAME)-chapter.out - rm -f $(PYPDFFILES) $(GPTTEXFILES) - -cleanall : clean - rm -f $(BASENAME)-chapter.pdf +# script: +pdf : chapter -watchpdf : - while true; do ! make -q pdf && make pdf; sleep 0.5; done +clean : cleanchapter +cleanall : clean cleanchapter diff --git a/bootstrap/lecture/bootstrap-chapter.tex b/bootstrap/lecture/bootstrap-chapter.tex index 7ecd9a5..dc5b25b 100644 --- a/bootstrap/lecture/bootstrap-chapter.tex +++ b/bootstrap/lecture/bootstrap-chapter.tex @@ -5,8 +5,10 @@ \lstset{inputpath=../code} \graphicspath{{figures/}} -\setcounter{page}{81} -\setcounter{chapter}{4} +\typein[\pagenumber]{Number of first page} +\typein[\chapternumber]{Chapter number} +\setcounter{page}{\pagenumber} +\setcounter{chapter}{\chapternumber} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -14,4 +16,10 @@ \input{bootstrap} +\section{TODO} +\begin{itemize} +\item Proper introduction of confidence intervals +\item Proper introduction of statistical tests (significance, power, etc.) +\end{itemize} + \end{document} diff --git a/bootstrap/lecture/bootstrap.tex b/bootstrap/lecture/bootstrap.tex index 0cf4cb0..30fd834 100644 --- a/bootstrap/lecture/bootstrap.tex +++ b/bootstrap/lecture/bootstrap.tex @@ -2,7 +2,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{\tr{Bootstrap Methods}{Bootstrap Methoden}} -Beim Bootstrap erzeugt man sich die Verteilung von Statistiken durch Resampling +Beim \determ{Bootstrap} erzeugt man sich die Verteilung von Statistiken durch Resampling aus der Stichprobe. Das hat mehrere Vorteile: \begin{itemize} \item Weniger Annahmen (z.B. muss eine Stichprobe nicht normalverteilt sein). @@ -21,21 +21,22 @@ aus der Stichprobe. Das hat mehrere Vorteile: \end{figure} Zur Erinnerung: In der Statistik interessieren wir uns f\"ur -Eigenschaften einer Grundgesamtheit. z.B. die mittlere L\"ange von -sauren Gurken (\figref{statisticalpopulationfig}). Aus der -Grundgesamtheit wird eine Stichprobe (simple random sample, SRS) -gezogen, da niemals die gesamte Grundgesamtheit gemessen werden kann. -Dann wird aus dieser einzigen Stichprobe die gew\"unschte Gr\"o{\ss}e -berechnet (die mittlere Gr\"o{\ss}e der sauren Gurken) und man hofft, -dass die erhaltene Zahl an der entsprechenden unbekannten Gr\"o{\ss}e -der Grundgesamtheit (der Populationsparameter) m\"oglichst nah dran +Eigenschaften einer \determ{Grundgesamtheit}. z.B. die mittlere +L\"ange von sauren Gurken (\figref{statisticalpopulationfig}). Aus der +Grundgesamtheit wird eine \determ{Stichprobe} (\enterm{simple random + sample}, \enterm[SRS|see{simple random sample}]{SRS}) gezogen, da +niemals die gesamte Grundgesamtheit gemessen werden kann. Dann wird +aus dieser einzigen Stichprobe die gew\"unschte Gr\"o{\ss}e berechnet +(die mittlere Gr\"o{\ss}e der sauren Gurken) und man hofft, dass die +erhaltene Zahl an der entsprechenden unbekannten Gr\"o{\ss}e der +Grundgesamtheit (der \determ{Populationsparameter}) m\"oglichst nah dran ist. Eine Aufgabe der Statistik ist es, herauszubekommen wie gut der Populationsparameter abgesch\"atzt worden ist. Wenn wir viele Stichproben ziehen w\"urden, dann k\"onnte man f\"ur jede Stichprobe den gew\"unschten Parameter berechnen, und von diesen die Wahrscheinlichkeitsverteilung \"uber ein Histogramm bestimmen --- -die ``Stichprobenverteilung'' (sampling distribution, +die \determ{Stichprobenverteilung} (\enterm{sampling distribution}, \subfigref{bootstrapsamplingdistributionfig}{a}). \begin{figure}[tp] @@ -43,7 +44,7 @@ die ``Stichprobenverteilung'' (sampling distribution, \includegraphics[height=0.2\textheight]{srs2}\\[2ex] \includegraphics[height=0.2\textheight]{srs3} \titlecaption{\label{bootstrapsamplingdistributionfig}Bootstrap der - Stichprobenverteilung}{(a) Von der Grundgesamtheit (population) mit + Stichprobenverteilung.}{(a) Von der Grundgesamtheit (population) mit unbekanntem Parameter (z.B. Mittelwert $\mu$) zieht man Stichproben (SRS: simple random samples). Die Statistik (hier Bestimmung von $\bar x$) kann f\"ur jede Stichprobe berechnet @@ -68,9 +69,9 @@ Mittelwerte der Stichproben um den Populationsmittelwert streuen \subfigref{bootstrapsamplingdistributionfig}{b}). Wir k\"onnen aber auch aus der einen Stichprobe die wir haben durch -Resampling viele neue Stichproben generieren (Bootstrap). Von diesen +\determ{Resampling} viele neue Stichproben generieren (Bootstrap). Von diesen k\"onnen wir jeweils die gew\"unschte Gr\"o{\ss}e berechnen und ihre -Verteilung bestimmen (Bootstrap Verteilung, +Verteilung bestimmen (\determ{Bootstrapverteilung}, \subfigref{bootstrapsamplingdistributionfig}{c}). Diese Verteilung ist interessanterweise in ihrer Breite und Form der Stichprobenverteilung sehr \"ahnlich. Nur streut sie nicht um den Populationswert sonder um @@ -92,7 +93,7 @@ Stichprobe vorkommen. Am besten l\"asst sich die Bootstrap Methode am Beispiel des Standardfehlers des Mittelwertes veranschaulichen. Aus der Stichprobe -k\"onnen wir den Mittelwert berechnen. Der Standardfehler des +k\"onnen wir den Mittelwert berechnen. Der \determ{Standardfehler} des Mittelwerts gibt die Standardabweichung an, mit der wir erwarten, dass der gemessene Mittelwert um den Populationsmittelwert streut. @@ -115,6 +116,7 @@ eine ganze Verteilung von Mittelwerten generieren (\figref{bootstrapsemfig}). Die Standardabweichung dieser Verteilung ist dann der gesuchte Standardfehler des Mittelwerts. +\pagebreak[4] \begin{exercise}{bootstrapsem.m}{bootstrapsem.out} Erzeuge die Verteilung der Mittelwerte einer Stichprobe durch Bottstrapping, um daraus den Standardfehler des Mittelwerts zu bestimmen. @@ -147,7 +149,7 @@ Nullhypothese aus den Daten selbst gewonnen werden. Dabei m\"ussen die Daten entsprechend der Nullhypothese neu aus der Stichprobe gezogen werden. -Diese ``Permutationstests'' haben den Vorteil, dass nur die +Diese \determ{Permutationstests} haben den Vorteil, dass nur die Eigenschaft von Interesse zerst\"ort wird, um die Nullhypothese zu generieren. Alle anderen Eigenschaften der Daten bleiben erhalten. @@ -166,16 +168,18 @@ generieren. Alle anderen Eigenschaften der Daten bleiben erhalten. Sehr sch\"on lassen sich Permutationstest am Beispiel von Korrelationen veranschaulichen. Gegeben sind Datenpaare $(x_i, y_i)$. -Daraus k\"onnen wir den Korrelationskoeffizienten berechnen. Wir -wissen dann aber noch nicht, ob der berechnete Wert tats\"achlich eine -Korrelation anzeigt. Die Nullhypothese ist, dass die Daten nicht -miteinander korreliert sind. Indem wir die $x$-Werte und die $y$-Werte -unabh\"angig voneinander permutieren (ihre Reihenfolge zuf\"allig neu -anordnen), werden die Korrelationen der Datenpaare zerst\"ort. Wenn -wir das viele Male wiederholen, bekommen wir die Verteilung der -Korrelationskoeffizienten f\"ur nichtkorrelierte Daten. Aus dieser -Verteilung der Nullhypothese k\"onnen wir dann dann die Signifikanz -der tats\"achlich gemessenen Korrelation bestimmen. +Daraus k\"onnen wir den +\determ[Korrelationskoeffizient]{Korrelationskoeffizienten} +berechnen. Wir wissen dann aber noch nicht, ob der berechnete Wert +tats\"achlich eine Korrelation anzeigt. Die Nullhypothese ist, dass +die Daten nicht miteinander korreliert sind. Indem wir die $x$-Werte +und die $y$-Werte unabh\"angig voneinander permutieren (ihre +Reihenfolge zuf\"allig neu anordnen), werden die Korrelationen der +Datenpaare zerst\"ort. Wenn wir das viele Male wiederholen, bekommen +wir die Verteilung der Korrelationskoeffizienten f\"ur +nichtkorrelierte Daten. Aus dieser Verteilung der Nullhypothese +k\"onnen wir dann dann die Signifikanz der tats\"achlich gemessenen +Korrelation bestimmen. \begin{exercise}{correlationsignificance.m}{correlationsignificance.out} Bestimme die Signifikanz eines Korrelationskoeffizienten. @@ -186,7 +190,7 @@ Bestimme die Signifikanz eines Korrelationskoeffizienten. \item Berechne den Korrelationskoeffizient dieser Datenpaare. \item Generiere die Verteilung der Nullhypothese ``unkorrelierte Daten'' indem die $x$- und $y$-Daten 1000-mal unabh\"angig - permutiert werden \matlabfun{randperm} und jeweils der + permutiert werden \matlabfun{randperm()} und jeweils der Korrelationskoeffizient berechnet wird. \item Bestimme aus den Nullhypothesendaten das 95\,\%-Perzentil und vergleiche es mit dem tats\"achlichen Korrelationskoeffizienten. diff --git a/bootstrap/lecture/bootstrapsem.py b/bootstrap/lecture/bootstrapsem.py index 7b9ac22..347f40f 100644 --- a/bootstrap/lecture/bootstrapsem.py +++ b/bootstrap/lecture/bootstrapsem.py @@ -2,7 +2,7 @@ import numpy as np import matplotlib.pyplot as plt plt.xkcd() -fig = plt.figure( figsize=(6,4) ) +fig = plt.figure( figsize=(6,3.5) ) rng = np.random.RandomState(637281) nsamples = 100 diff --git a/bootstrap/lecture/permutecorrelation.py b/bootstrap/lecture/permutecorrelation.py index 580e12b..0f2ac14 100644 --- a/bootstrap/lecture/permutecorrelation.py +++ b/bootstrap/lecture/permutecorrelation.py @@ -2,7 +2,7 @@ import numpy as np import matplotlib.pyplot as plt plt.xkcd() -fig = plt.figure( figsize=(6,4) ) +fig = plt.figure( figsize=(6,3.5) ) rng = np.random.RandomState(637281) # generate correlated data: diff --git a/chapter.mk b/chapter.mk new file mode 100644 index 0000000..8a0e56e --- /dev/null +++ b/chapter.mk @@ -0,0 +1,52 @@ +# plots: +plots : pythonplots gnuplots + +# python plots: +PYFILES=$(wildcard *.py) +PYPDFFILES=$(PYFILES:.py=.pdf) + +pythonplots : $(PYPDFFILES) + +$(PYPDFFILES) : %.pdf: %.py + python $< + +cleanpythonplots : + rm -f $(PYPDFFILES) + + +# gnuplot plots: +GPTFILES=$(wildcard *.gpt) +GPTTEXFILES=$(GPTFILES:.gpt=.tex) + +gnuplots : $(GPTTEXFILES) + +$(GPTTEXFILES) : %.tex: %.gpt whitestyles.gp + gnuplot whitestyles.gp $< + epstopdf $*.eps + +cleangnuplots : + rm -f $(GPTTEXFILES) + + +# script: +chapter : $(BASENAME)-chapter.pdf + +$(BASENAME)-chapter.pdf : $(BASENAME)-chapter.tex $(BASENAME).tex $(wildcard $(BASENAME).aux) $(PYPDFFILES) $(GPTTEXFILES) ../../header.tex + if test -f $(BASENAME).aux; then \ + CHAPTER=$$(( $$(sed -n -e '/contentsline {chapter}/{s/.*numberline {\([0123456789]*\)}.*/\1/; p}' $(BASENAME).aux) - 1 )); \ + PAGE=$$(sed -n -e '/contentsline {chapter}/{s/.*numberline {.*}.*}{\(.*\)}{chapter.*/\1/; p}' $(BASENAME).aux); \ + fi; \ + { echo $${PAGE:=1}; echo $${CHAPTER:=0}; } | pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && { echo $${PAGE:=1}; echo $${CHAPTER:=0}; } | pdflatex -interaction=scrollmode $< || true + +watchchapter : + while true; do ! make -q chapter && make chapter; sleep 0.5; done + + +cleanchapter : cleanpythonplots cleangnuplots + rm -f *~ + rm -f $(BASENAME).aux $(BASENAME).log + rm -f $(BASENAME)-chapter.aux $(BASENAME)-chapter.log $(BASENAME)-chapter.out $(BASENAME)-chapter.idx + + +cleanallchapter : cleanchapter + rm -f $(BASENAME)-chapter.pdf diff --git a/designpattern/lecture/Makefile b/designpattern/lecture/Makefile index 145c35c..e7312a5 100644 --- a/designpattern/lecture/Makefile +++ b/designpattern/lecture/Makefile @@ -1,32 +1,13 @@ BASENAME=designpattern -PYFILES=$(wildcard *.py) -PYPDFFILES=$(PYFILES:.py=.pdf) - all : pdf -# script: -pdf : $(BASENAME)-chapter.pdf - -$(BASENAME)-chapter.pdf : $(BASENAME)-chapter.tex $(BASENAME).tex $(PYPDFFILES) - CHAPTER=$$(( $$(sed -n -e '/contentsline {chapter}/{s/.*numberline {\([0123456789]*\)}.*/\1/; p}' $(BASENAME).aux) - 1 )); \ - PAGE=$$(sed -n -e '/contentsline {chapter}/{s/.*numberline {.*}.*}{\(.*\)}{chapter.*/\1/; p}' $(BASENAME).aux); \ - sed -i -e "s/setcounter{page}{.*}/setcounter{page}{$$PAGE}/; s/setcounter{chapter}{.*}/setcounter{chapter}{$$CHAPTER}/" $(BASENAME)-chapter.tex - pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex -interaction=scrollmode $< || true +include ../../chapter.mk -$(PYPDFFILES) : %.pdf : %.py - python $< - -clean : - rm -f *~ - rm -f $(BASENAME).aux $(BASENAME).log - rm -f $(BASENAME)-chapter.aux $(BASENAME)-chapter.log $(BASENAME)-chapter.out - rm -f $(PYPDFFILES) $(GPTTEXFILES) - -cleanall : clean - rm -f $(BASENAME)-chapter.pdf +# script: +pdf : chapter -watchpdf : - while true; do ! make -q pdf && make pdf; sleep 0.5; done +clean : cleanchapter +cleanall : clean cleanchapter diff --git a/designpattern/lecture/designpattern-chapter.tex b/designpattern/lecture/designpattern-chapter.tex index 0f3596c..4bb7291 100644 --- a/designpattern/lecture/designpattern-chapter.tex +++ b/designpattern/lecture/designpattern-chapter.tex @@ -5,8 +5,10 @@ \lstset{inputpath=../code} \graphicspath{{figures/}} -\setcounter{page}{125} -\setcounter{chapter}{8} +\typein[\pagenumber]{Number of first page} +\typein[\chapternumber]{Chapter number} +\setcounter{page}{\pagenumber} +\setcounter{chapter}{\chapternumber} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/designpattern/lecture/designpattern.tex b/designpattern/lecture/designpattern.tex index a13c290..1c1a8be 100644 --- a/designpattern/lecture/designpattern.tex +++ b/designpattern/lecture/designpattern.tex @@ -10,7 +10,7 @@ einige dieser ``Design pattern'' zusammen. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{for Schleifen \"uber Vektoren} Grundlegend ist das Iterieren \"uber den Inhalt eines Vektors mit einer \code{for}-Schleife: -\begin{lstlisting}[caption={for-Schleife mit Indexen \"uber einen Vektor}] +\begin{lstlisting}[caption={\varcode{for}-Schleife mit Indexen \"uber einen Vektor}] x = [2:3:20]; % irgendein Vektor for i=1:length(x) % Mit der for-Schleife "loopen" wir ueber den Vektor i % das ist der Index, der die Elemente des Vektors indiziert. @@ -24,7 +24,7 @@ end Wenn in der Schleife das Ergebnis in einen Vektor gespeichert werden soll, sollten wir vor der Schleife schon einen Vektor f\"ur die Ergebnisse erstellen: -\begin{lstlisting}[caption={for-Schleife zum Schreiben eines Vektors}] +\begin{lstlisting}[caption={\varcode{for}-Schleife zum Schreiben eines Vektors}] x = [1.2 2.3 2.6 3.1]; % irgendein Vektor y = zeros(length(x),1); % Platz fuer die Ergebnisse, genauso viele wie Loops der Schleife for i=1:length(x) @@ -39,7 +39,7 @@ mean(y) Die Berechnungen in der Schleife k\"onnen statt einer Zahl auch einen Vektor zur\"uckgeben. Wenn die L\"ange diese Vektors bekannt ist, dann kann vorher eine entsprechend gro{\ss}e Matrix angelegt werden: -\begin{lstlisting}[caption={for-Schleife zum Schreiben von Zeilen einer Matrix}] +\begin{lstlisting}[caption={\varcode{for}-Schleife zum Schreiben von Zeilen einer Matrix}] x = [2:3:20]; % irgendein Vektor y = zeros(length(x),10); % Platz fuer die Ergebnisse for i=1:length(x) @@ -54,7 +54,7 @@ mean(y, 1) Alternativ k\"onnen die in der Schleife erzeugten Vektoren zu einem einzigen, durchgehenden Vektor zusammengestellt werden: -\begin{lstlisting}[caption={for-Schleife zum Aneinanderh\"angen von Vektoren}] +\begin{lstlisting}[caption={\varcode{for}-Schleife zum Aneinanderh\"angen von Vektoren}] x = [2:3:20]; % irgendein Vektor y = []; % Leerer Vektor fuer die Ergebnisse for i=1:length(x) @@ -75,7 +75,6 @@ Zufallsgeneratoren geben oft nur Zufallszahlen mit festen Mittelwerten und Standardabweichungen (auch Skalierungen) zur\"uck. Multiplikation mit einem Faktor skaliert die Standardabweichung und Addition einer Zahl verschiebt den Mittelwert. - \begin{lstlisting}[caption={Skalierung von Zufallszahlen}] % 100 random numbers draw from a Gaussian distribution with mean 0 and standard deviation 1. x = randn(100, 1); @@ -85,9 +84,8 @@ mu = 4.8; sigma = 2.3; y = randn(100, 1)*sigma + mu; \end{lstlisting} - -Das gleiche Prinzip ist manchmal auch sinnvoll f\"ur \code{zeros} oder \code{ones}: -\begin{lstlisting}[caption={Skalierung von zeros und ones}] +Das gleiche Prinzip ist manchmal auch sinnvoll f\"ur \code{zeros()} oder \code{ones()}: +\begin{lstlisting}[caption={Skalierung von \varcode{zeros()} und \varcode{ones()}}] x = -1:0.01:2; % Vektor mit x-Werten plot(x, exp(-x.*x)); % Plotte f\"ur die gleichen x-Werte eine Linie mit y=0.8: @@ -141,26 +139,23 @@ Meistens sollten Histogramme normiert werden, damit sie vergleichbar mit anderen Histogrammen oder mit theoretischen Wahrscheinlichkeitsverteilungen werden. -Die \code{histogram} Funktion macht das mit den entsprechenden Parametern automatisch: -\begin{lstlisting}[caption={Probability-density-function mit der histogram-Funktion}] +Die \code{histogram()} Funktion macht das mit den entsprechenden Parametern automatisch: +\begin{lstlisting}[caption={Probability-density-function mit der \varcode{histogram()}-Funktion}] x = randn(100, 1); % irgendwelche reellwertige Daten histogram(x, 'Normalization', 'pdf'); \end{lstlisting} - -\begin{lstlisting}[caption={Probability mit der histogram-Funktion}] +\begin{lstlisting}[caption={Probability mit der \varcode{histogram()}-Funktion}] x = randi(6, 100, 1); % irgendwelche integer Daten histogram(x, 'Normalization', 'probability'); \end{lstlisting} - -So geht es aber auch: -\begin{lstlisting}[caption={Probability-density-function mit der hist- und bar-Funktion}] +So geht es mit der \code{hist()}-Funktion: +\begin{lstlisting}[caption={Probability-density-function mit der \varcode{hist()}- und \varcode{bar()}-Funktion}] x = randn(100, 1); % irgendwelche reellwertige Daten [h, b] = hist(x); % Histogram berechnen h = h/sum(h)/(b(2)-b(1)); % normieren zu einer Wahrscheinlichkeitsdichte bar(b, h); % und plotten. \end{lstlisting} - -\begin{lstlisting}[caption={Probability mit der hist- und bar-Funktion}] +\begin{lstlisting}[caption={Probability mit der \varcode{hist()}- und \varcode{bar()}-Funktion}] x = randi(6, 100, 1); % irgendwelche integer Daten [h, b] = hist(x); % Histogram berechnen h = h/sum(h); % normieren zu Wahrscheinlichkeiten diff --git a/header.tex b/header.tex index d067f4c..2e3face 100644 --- a/header.tex +++ b/header.tex @@ -26,8 +26,10 @@ %%%%% index %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \usepackage[makeindex]{splitidx} \makeindex +\usepackage[totoc]{idxlayout} \newindex[Fachbegriffe]{term} -\newindex[Code]{code} +\newindex[Englische Fachbegriffe]{enterm} +\newindex[MATLAB Code]{code} %%%%% units %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \usepackage[mediumspace,mediumqspace,Gray]{SIunits} % \ohm, \micro @@ -66,9 +68,9 @@ % float placement fractions: \renewcommand{\textfraction}{0.2} -\renewcommand{\topfraction}{0.8} +\renewcommand{\topfraction}{0.9} \renewcommand{\bottomfraction}{0.0} -\renewcommand{\floatpagefraction}{0.5} +\renewcommand{\floatpagefraction}{0.7} % spacing for floats: \setlength{\floatsep}{12pt plus 2pt minus 2pt} @@ -138,6 +140,11 @@ \newcommand{\tabrefb}[1]{\tabb~\tref{#1}} \newcommand{\tabsrefb}[1]{\tabsb~\tref{#1}} +% invisible rule for expanding the height of a row in a table header: +\newcommand{\erh}{\rule[-1.2ex]{0pt}{3.5ex}} +% invisible rule for expanding the height of a row in a table body: +\newcommand{\erb}{\rule{0pt}{2.5ex}} + %%%%% equation references %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %\newcommand{\eqref}[1]{(\ref{#1})} \newcommand{\eqn}{\tr{Eq}{Gl}.} @@ -166,7 +173,7 @@ frame=single, caption={\protect\filename@parse{\lstname}\protect\filename@base}, captionpos=t, - xleftmargin=2.5em, + xleftmargin=21pt, xrightmargin=1mm, aboveskip=1ex, belowskip=2ex @@ -189,11 +196,15 @@ \newcommand{\koZ}{\mathds{C}} %%%%% english, german, code and file terms: %%%%%%%%%%%%%%% -\newcommand{\enterm}[1]{``#1''\sindex[term]{#1}} -\newcommand{\determ}[1]{\textit{#1}\sindex[term]{#1}} -\newcommand{\codeterm}[1]{\textit{#1}\sindex[term]{#1}} +\usepackage{ifthen} +\newcommand{\enterm}[2][]{``#2''\ifthenelse{\equal{#1}{}}{\protect\sindex[enterm]{#2}}{\protect\sindex[enterm]{#1}}} +\newcommand{\determ}[2][]{\textit{#2}\ifthenelse{\equal{#1}{}}{\protect\sindex[term]{#2}}{\protect\sindex[term]{#1}}} +\newcommand{\codeterm}[2][]{\textit{#2}\ifthenelse{\equal{#1}{}}{\protect\sindex[term]{#2}}{\protect\sindex[term]{#1}}} \newcommand{\file}[1]{\texttt{#1}} +% for escaping special characters into the index: +\newcommand{\scor}{"|} + %%%%% key-shortcuts %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \usepackage{tikz} \usetikzlibrary{shapes} @@ -202,9 +213,17 @@ %%%%% code/matlab commands: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \usepackage{textcomp} -\newcommand{\code}[1]{\setlength{\fboxsep}{0.5ex}\colorbox{codeback}{\texttt{#1}}\sindex[code]{#1}} -\newcommand{\matlab}{MATLAB$^{\copyright}$} -\newcommand{\matlabfun}[1]{(\tr{\matlab{}-function}{\matlab-Funktion} \setlength{\fboxsep}{0.5ex}\colorbox{codeback}{\texttt{#1}})\sindex[code]{#1}} +\newcommand{\varcode}[1]{\setlength{\fboxsep}{0.5ex}\colorbox{codeback}{\texttt{#1\protect\rule[-0.1ex]{0pt}{1.6ex}}}} +\newcommand{\code}[2][]{\varcode{#2}\ifthenelse{\equal{#1}{}}{\protect\sindex[code]{#2}}{\protect\sindex[code]{#1}}} +\newcommand{\matlab}{\texorpdfstring{MATLAB$^{\copyright}$}{MATLAB}} +\newcommand{\matlabfun}[2][]{(\tr{\matlab-function}{\matlab-Funktion} \setlength{\fboxsep}{0.5ex}\colorbox{codeback}{\texttt{#2}})\ifthenelse{\equal{#1}{}}{\protect\sindex[code]{#2}}{\protect\sindex[code]{#1}}} + +%%%%% shortquote and widequote commands: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \shortquote{Something to be quoted}{Source} +\newcommand{\shortquote}[2]{\begin{list}{}{\rightmargin\leftmargin}\item\relax\itshape #1 \hfill \upshape #2\end{list}} + +% \widequote{Something to be quoted}{Source} +\newcommand{\widequote}[2]{{\itshape #1} \hfill #2} %%%%% exercises environment: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % usage: @@ -223,7 +242,6 @@ % content of someoutput.out % % Innerhalb der exercise Umgebung ist enumerate umdefiniert, um (a), (b), (c), .. zu erzeugen. -\usepackage{ifthen} \usepackage{mdframed} \usepackage{xstring} \newcommand{\codepath}{} @@ -241,18 +259,20 @@ \newcommand{\exerciseoutput}{#2}% \setlength{\fboxsep}{2mm}% \newcommand{\saveenumi}{\theenumi}\renewcommand{\labelenumi}{(\alph{enumi})}% - \captionsetup{singlelinecheck=off,hypcap=false,labelfont={large,sf,it,bf},font={large,sf,it,bf},skip={0.5ex}} + \captionsetup{singlelinecheck=off,hypcap=false,labelfont={large,sf,it,bf},font={large,sf,it,bf},skip={0.5ex}}% \begin{mdframed}[linewidth=0pt,backgroundcolor=exerciseback]% \captionof{exercisef}[\exercisefile]{}% \captionsetup{font={normal,sf,it}}% }% - {\ifthenelse{\equal{\exercisesource}{}}{}% - {\ifthenelse{\value{exercise}>\value{maxexercise}}{}% + {\hypersetup{hypertexnames=false}% + \ifthenelse{\equal{\exercisesource}{}}{}% + {\ifthenelse{\value{exercisef}>\value{maxexercise}}{}% {\addtocounter{lstlisting}{-1}% - \lstinputlisting[belowskip=0pt,aboveskip=1ex,nolol=true,title={\textbf{Listing:} \exercisefile}]{\codepath\exercisesource}% + \lstinputlisting[belowskip=0pt,aboveskip=1ex,nolol=true,title={\textbf{\tr{Solution}{L\"osung}:} \exercisefile}]{\codepath\exercisesource}% \ifthenelse{\equal{\exerciseoutput}{}}{}% {\addtocounter{lstlisting}{-1}% \lstinputlisting[language={},title={\textbf{\tr{Output}{Ausgabe}:}},nolol=true,belowskip=0pt]{\codepath\exerciseoutput}}}}% + \hypersetup{hypertexnames=true}% \end{mdframed}% \renewcommand{\theenumi}{\saveenumi}} @@ -277,11 +297,13 @@ \newenvironment{ibox}[2][tp] {\SetupFloatingEnvironment{iboxf}{placement=#1}% \begin{iboxf}% - \captionsetup{singlelinecheck=off,labelfont={large,sf,it,bf},font={large,sf,it,bf}} + \captionsetup{singlelinecheck=off,labelfont={large,sf,it,bf},font={large,sf,it,bf}}% \begin{mdframed}[linecolor=infoline,linewidth=1ex,% backgroundcolor=infoback,font={\sffamily},% frametitle={\caption{#2}},frametitleaboveskip=-1ex,% - frametitlebackgroundcolor=infoline]}% + frametitlebackgroundcolor=infoline]% + \setlength{\parindent}{0pt}\setlength{\parskip}{1ex}% + \captionsetup{singlelinecheck=off,labelfont={normalsize,sf,bf},font={normalsize,sf}}}% {\end{mdframed}% \end{iboxf}} @@ -303,14 +325,16 @@ % placement=t % ]{importantf} \newenvironment{important}[1][]% -{\captionsetup{singlelinecheck=off,labelformat={empty},labelfont={large,sf,it,bf},font={large,sf,it,bf}} +{\captionsetup{singlelinecheck=off,hypcap=false,labelformat={empty},labelfont={large,sf,it,bf},font={large,sf,it,bf}} \ifthenelse{\equal{#1}{}}% {\begin{mdframed}[linecolor=importantline,linewidth=1ex,% - backgroundcolor=importantback,font={\sffamily}]}% + backgroundcolor=importantback,font={\sffamily}]% + \setlength{\parindent}{0pt}\setlength{\parskip}{1ex}}% {\begin{mdframed}[linecolor=importantline,linewidth=1ex,% backgroundcolor=importantback,font={\sffamily},% frametitle={\captionof{iboxf}{#1}},frametitleaboveskip=-1ex,% - frametitlebackgroundcolor=importantline]}% + frametitlebackgroundcolor=importantline]% + \setlength{\parindent}{0pt}\setlength{\parskip}{1ex}}% }% {\end{mdframed}} @@ -318,5 +342,6 @@ %%%%% hyperref %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \usepackage[bookmarks=true,bookmarksopen=true,% pdfpagemode=UseNone,pdfstartview=FitH,% + plainpages=false,pdfpagelabels,% breaklinks=true,colorlinks=true,% citecolor=blue!50!black,linkcolor=red!70!black,urlcolor=blue!50!black]{hyperref} diff --git a/likelihood/lecture/Makefile b/likelihood/lecture/Makefile index 51e7876..17f92ae 100644 --- a/likelihood/lecture/Makefile +++ b/likelihood/lecture/Makefile @@ -1,32 +1,12 @@ BASENAME=likelihood -PYFILES=$(wildcard *.py) -PYPDFFILES=$(PYFILES:.py=.pdf) - all : pdf -# script: -pdf : $(BASENAME)-chapter.pdf - -$(BASENAME)-chapter.pdf : $(BASENAME)-chapter.tex $(BASENAME).tex $(PYPDFFILES) - CHAPTER=$$(( $$(sed -n -e '/contentsline {chapter}/{s/.*numberline {\([0123456789]*\)}.*/\1/; p}' $(BASENAME).aux) - 1 )); \ - PAGE=$$(sed -n -e '/contentsline {chapter}/{s/.*numberline {.*}.*}{\(.*\)}{chapter.*/\1/; p}' $(BASENAME).aux); \ - sed -i -e "s/setcounter{page}{.*}/setcounter{page}{$$PAGE}/; s/setcounter{chapter}{.*}/setcounter{chapter}{$$CHAPTER}/" $(BASENAME)-chapter.tex - pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex -interaction=scrollmode $< || true - -$(PYPDFFILES) : %.pdf : %.py - python $< +include ../../chapter.mk -clean : - rm -f *~ - rm -f $(BASENAME).aux $(BASENAME).log - rm -f $(BASENAME)-chapter.aux $(BASENAME)-chapter.log $(BASENAME)-chapter.out - rm -f $(PYPDFFILES) $(GPTTEXFILES) - -cleanall : clean - rm -f $(BASENAME)-chapter.pdf - -watchpdf : - while true; do ! make -q pdf && make pdf; sleep 0.5; done +# script: +pdf : chapter +clean : cleanchapter +cleanall : clean cleanchapter diff --git a/likelihood/lecture/likelihood-chapter.tex b/likelihood/lecture/likelihood-chapter.tex index 0f74fe3..2bcc35b 100644 --- a/likelihood/lecture/likelihood-chapter.tex +++ b/likelihood/lecture/likelihood-chapter.tex @@ -5,8 +5,10 @@ \lstset{inputpath=../code} \graphicspath{{figures/}} -\setcounter{page}{101} -\setcounter{chapter}{6} +\typein[\pagenumber]{Number of first page} +\typein[\chapternumber]{Chapter number} +\setcounter{page}{\pagenumber} +\setcounter{chapter}{\chapternumber} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -14,4 +16,9 @@ \input{likelihood} +\section{TODO} +\begin{itemize} +\item GLM model fitting? +\end{itemize} + \end{document} diff --git a/likelihood/lecture/likelihood.tex b/likelihood/lecture/likelihood.tex index bdeb82d..6c98f37 100644 --- a/likelihood/lecture/likelihood.tex +++ b/likelihood/lecture/likelihood.tex @@ -7,7 +7,8 @@ In vielen Situationen wollen wir einen oder mehrere Parameter $\theta$ einer Wahrscheinlichkeitsverteilung sch\"atzen, so dass die Verteilung die Daten $x_1, x_2, \ldots x_n$ am besten beschreibt. -Maximum-Likelihood-Sch\"atzer (maximum likelihood estimate, mle) +\determ{Maximum-Likelihood-Sch\"atzer} (\enterm{maximum likelihood + estimator}, \determ[mle|see{Maximum-Likelihood-Sch\"atzer}]{mle}) w\"ahlen die Parameter so, dass die Wahrscheinlichkeit, dass die Daten aus der Verteilung stammen, am gr\"o{\ss}ten ist. @@ -31,8 +32,10 @@ Auftretens der Werte $x_1, x_2, \ldots x_n$ gegeben ein bestimmtes $\theta$ p(x_1,x_2, \ldots x_n|\theta) = p(x_1|\theta) \cdot p(x_2|\theta) \ldots p(x_n|\theta) = \prod_{i=1}^n p(x_i|\theta) \; . \end{equation} -Andersherum gesehen ist das die Likelihood (deutsch immer noch ``Wahrscheinlichleit'') -den Parameter $\theta$ zu haben, gegeben die Me{\ss}werte $x_1, x_2, \ldots x_n$, +Andersherum gesehen ist das die \determ{Likelihood} +(\enterm{likelihood}, deutsch immer noch ``Wahrscheinlichleit'') den +Parameter $\theta$ zu haben, gegeben die Me{\ss}werte $x_1, x_2, +\ldots x_n$, \begin{equation} {\cal L}(\theta|x_1,x_2, \ldots x_n) = p(x_1,x_2, \ldots x_n|\theta) \end{equation} @@ -55,7 +58,7 @@ An der Stelle eines Maximums einer Funktion \"andert sich nichts, wenn man die Funktionswerte mit einer streng monoton steigenden Funktion transformiert. Aus numerischen und gleich ersichtlichen mathematischen Gr\"unden wird meistens das Maximum der logarithmierten Likelihood -(``Log-Likelihood'') gesucht: +(\determ{log-Likelihood}, \enterm{log-likelihood}) gesucht: \begin{eqnarray} \theta_{mle} & = & \text{argmax}_{\theta}\; {\cal L}(\theta|x_1,x_2, \ldots x_n) \nonumber \\ & = & \text{argmax}_{\theta}\; \log {\cal L}(\theta|x_1,x_2, \ldots x_n) \nonumber \\ @@ -73,7 +76,7 @@ $\theta$ maximiert dessen Likelhood? \begin{figure}[t] \includegraphics[width=1\textwidth]{mlemean} - \titlecaption{\label{mlemeanfig} Maximum Likelihood Estimation des + \titlecaption{\label{mlemeanfig} Maximum Likelihood Sch\"atzung des Mittelwerts.}{Oben: Die Daten zusammen mit drei m\"oglichen Normalverteilungen mit unterschiedlichen Mittelwerten (Pfeile) aus denen die Daten stammen k\"onnten. Unteln links: Die Likelihood @@ -115,13 +118,14 @@ diesem Mittelwert gezogen worden sind (\figref{mlemeanfig}). Wahrscheinlichkeiten) f\"ur den Mittelwert als Parameter. Vergleiche die Position der Maxima mit dem aus den Daten berechneten Mittelwert. - \newpage + \pagebreak[4] \end{exercise} +\pagebreak[4] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Kurvenfit als Maximum-Likelihood Sch\"atzung} -Beim Kurvenfit soll eine Funktion $f(x;\theta)$ mit den Parametern +Beim \determ{Kurvenfit} soll eine Funktion $f(x;\theta)$ mit den Parametern $\theta$ an die Datenpaare $(x_i|y_i)$ durch Anpassung der Parameter $\theta$ gefittet werden. Wenn wir annehmen, dass die $y_i$ um die entsprechenden Funktionswerte $f(x_i;\theta)$ mit einer @@ -195,7 +199,7 @@ die Steigung $m$ und der y-Achsenabschnitt $b$ einer Geradengleichung \[ y = m \cdot x +b \] oder allgemeiner die Koeffizienten $a_k$ eines Polynoms \[ y = \sum_{k=0}^N a_k x^k = a_o + a_1x + a_2x^2 + a_3x^4 + \ldots \] -\matlabfun{polyfit}. +\matlabfun{polyfit()}. Parameter, die nichtlinear in einer Funktion enthalten sind, k\"onnen im Gegensatz dazu nicht analytisch aus den Daten berechnet @@ -203,28 +207,28 @@ werden. z.B. die Rate $\lambda$ eines exponentiellen Zerfalls \[ y = c \cdot e^{\lambda x} \quad , \quad c, \lambda \in \reZ \; . \] F\"ur diesen Fall bleibt dann nur auf numerische Verfahren zur Optimierung der Kostenfunktion, wie z.B. der Gradientenabstieg, -zur\"uckzugreifen \matlabfun{lsqcurvefit}. +zur\"uckzugreifen \matlabfun{lsqcurvefit()}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Fits von Wahrscheinlichkeitsverteilungen} Jetzt betrachten wir noch den Fall, bei dem wir die Parameter einer Wahrscheinlichkeitsdichtefunktion (z.B. den shape-Parameter einer -Gamma-Verteilung) an ein Datenset fitten wollen. +\determ{Gamma-Verteilung}) an ein Datenset fitten wollen. Ein erster Gedanke k\"onnte sein, die -Wahrscheinlichkeitsdichtefunktion durch Minimierung des quadratischen -Abstands an ein Histogramm der Daten zu fitten. Das ist aber aus -folgenden Gr\"unden nicht die Methode der Wahl: (i) -Wahrscheinlichkeitsdichten k\"onnen nur positiv sein. Darum k\"onnen -insbesondere bei kleinen Werten die Daten nicht symmetrisch streuen, -wie es bei normalverteilten Daten der Fall ist. (ii) Die Datenwerte -sind nicht unabh\"angig, da das normierte Histogram sich zu Eins -aufintegriert. Die beiden Annahmen normalverteilte und unabh\"angige -Daten, die die Minimierung des quadratischen Abstands -\eqnref{chisqmin} zu einem Maximum-Likelihood Sch\"atzer machen, sind -also verletzt. (iii) Das Histogramm h\"angt von der Wahl der -Klassenbreite ab (\figref{mlepdffig}). +\determ[Wahrscheinlichkeitsdichte]{Wahrscheinlichkeitsdichtefunktion} +durch Minimierung des quadratischen Abstands an ein Histogramm der +Daten zu fitten. Das ist aber aus folgenden Gr\"unden nicht die +Methode der Wahl: (i) Wahrscheinlichkeitsdichten k\"onnen nur positiv +sein. Darum k\"onnen insbesondere bei kleinen Werten die Daten nicht +symmetrisch streuen, wie es bei normalverteilten Daten der Fall +ist. (ii) Die Datenwerte sind nicht unabh\"angig, da das normierte +Histogram sich zu Eins aufintegriert. Die beiden Annahmen +normalverteilte und unabh\"angige Daten, die die Minimierung des +quadratischen Abstands \eqnref{chisqmin} zu einem Maximum-Likelihood +Sch\"atzer machen, sind also verletzt. (iii) Das Histogramm h\"angt +von der Wahl der Klassenbreite ab (\figref{mlepdffig}). \begin{figure}[t] \includegraphics[width=1\textwidth]{mlepdf} @@ -243,12 +247,12 @@ Maximum Likelihood! Wir suchen einfach die Parameter $\theta$ der gesuchten Wahrscheinlichkeitsdichtefunktion bei der die Log-Likelihood \eqnref{loglikelihood} maximal wird. Das ist im allgemeinen ein nichtlinieares Optimierungsproblem, das mit numerischen Verfahren, wie -z.B. dem Gradientenabstieg, gel\"ost wird \matlabfun{mle}. +z.B. dem Gradientenabstieg, gel\"ost wird \matlabfun{mle()}. \begin{exercise}{mlegammafit.m}{mlegammafit.out} Erzeuge Gammaverteilte Zufallszahlen und benutze Maximum-Likelihood, um die Parameter der Gammafunktion aus den Daten zu bestimmen. - \newpage + \pagebreak \end{exercise} @@ -259,8 +263,9 @@ Aktivit\"at Eigenschaften von sensorischen Stimuli. z.B. im visuellen Kortex V1 die Orientierung eines Balkens. Traditionell wird die Antwort der Neurone f\"ur verschiedene Stimuli (z.B. verschiedene Orientierungen des Balkens) gemessen. Die mittlere Antwort der Neurone -als Funktion eines Stimulusparameters ist dann die ``Tuning-curve'' -(z.B. Feuerrate als Funktion des Orientierungswinkels). +als Funktion eines Stimulusparameters ist dann die +\enterm{Tuning-curve} (deutsch \determ{Abstimmkurve}, z.B. Feuerrate +als Funktion des Orientierungswinkels). \begin{figure}[tp] \includegraphics[width=1\textwidth]{mlecoding} diff --git a/likelihood/lecture/mlepropline.py b/likelihood/lecture/mlepropline.py index fc28d48..fcaa97a 100644 --- a/likelihood/lecture/mlepropline.py +++ b/likelihood/lecture/mlepropline.py @@ -2,7 +2,7 @@ import numpy as np import matplotlib.pyplot as plt plt.xkcd() -fig = plt.figure( figsize=(6,4) ) +fig = plt.figure( figsize=(6,3.5) ) # the line: slope = 2.0 diff --git a/plotting/code/automatic_plot.m b/plotting/code/automatic_plot.m index a923324..0b26a39 100644 --- a/plotting/code/automatic_plot.m +++ b/plotting/code/automatic_plot.m @@ -1,15 +1,11 @@ -clear all -close all - load('pyramidal_response.mat') threshold = 20; % mV -figure() hold on -plot(time*1000.0, neuronal_data, 'color', [0.2 0.5 0.7], 'linewidth', 1., ... - 'displayname', 'Membrane voltage') -plot(spikes*1000.0, ones(size(spikes)) .* threshold, 'r.', 'markersize', 15, ... - 'displayname', 'Spike times') +plot(time*1000.0, neuronal_data, 'color', [0.2 0.5 0.7], ... + 'linewidth', 1., 'displayname', 'Membrane voltage') +plot(spikes*1000.0, ones(size(spikes)) .* threshold, 'r.', ... + 'markersize', 15, 'displayname', 'Spike times') line([time(1) time(end)], [threshold threshold], 'linestyle', '--', ... 'linewidth', 0.75, 'color', [0.5 0.5 0.5], 'displayname', 'Threshold') @@ -24,7 +20,7 @@ set(l,'location','northeast', 'fontsize', 11, 'linewidth', 1.); set(gca, 'xminortick','on','yminortick','on') set(gca, 'tickdir','out', 'linewidth', 1.5, 'fontname', 'times', ... 'fontsize', 11) -set(gcf, 'paperunits', 'centimeters', 'papersize', [15 7.5]); -set(gcf, 'paperposition',[0.0 0.0 15, 7.5], 'color', 'white') +set(gcf, 'paperunits', 'centimeters', 'papersize', [15 7]); +set(gcf, 'paperposition',[0.0 0.0 15, 7], 'color', 'white') -saveas(gcf, [pwd '/../lecture/images/spike_detection.pdf'], 'pdf') +saveas(gcf, 'spike_detection.pdf', 'pdf') \ No newline at end of file diff --git a/plotting/lecture/Makefile b/plotting/lecture/Makefile index 3fa9e21..5e11607 100644 --- a/plotting/lecture/Makefile +++ b/plotting/lecture/Makefile @@ -1,21 +1,12 @@ BASENAME=plotting -PYFILES=$(wildcard *.py) -PYPDFFILES=$(PYFILES:.py=.pdf) - -GPTFILES=$(wildcard *.gpt) -GPTTEXFILES=$(GPTFILES:.gpt=.tex) - all: pdf slides thumbs +include ../../chapter.mk + # script: -pdf : $(BASENAME)-chapter.pdf -$(BASENAME)-chapter.pdf : $(BASENAME)-chapter.tex $(BASENAME).tex $(GPTTEXFILES) $(PYPDFFILES) ../../header.tex - CHAPTER=$$(( $$(sed -n -e '/contentsline {chapter}/{s/.*numberline {\([0123456789]*\)}.*/\1/; p}' $(BASENAME).aux) - 1 )); \ - PAGE=$$(sed -n -e '/contentsline {chapter}/{s/.*numberline {.*}.*}{\(.*\)}{chapter.*/\1/; p}' $(BASENAME).aux); \ - sed -i -e "s/setcounter{page}{.*}/setcounter{page}{$$PAGE}/; s/setcounter{chapter}{.*}/setcounter{chapter}{$$CHAPTER}/" $(BASENAME)-chapter.tex - pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex -interaction=scrollmode $< || true +pdf : chapter # slides: @@ -31,31 +22,15 @@ $(BASENAME)-handout.pdf: $(BASENAME)-slides.tex $(GPTTEXFILES) pdfnup --nup 2x4 --no-landscape --paper a4paper --trim "-1cm -1cm -1cm -1cm" --outfile $@ thumbsfoils.pdf # 1-19 rm thumbsfoils.* -watchpdf : - while true; do ! make -q pdf && make pdf; sleep 0.5; done - watchslides : while true; do ! make -q slides && make slides; sleep 0.5; done -# python plots: -$(PYPDFFILES) : %.pdf: %.py - python $< - -# gnuplot plots: -$(GPTTEXFILES) : %.tex: %.gpt whitestyles.gp - gnuplot whitestyles.gp $< - epstopdf $*.eps - -clean : - rm -f *~ - rm -f $(BASENAME).aux $(BASENAME).log - rm -f $(BASENAME)-chapter.aux $(BASENAME)-chapter.log $(BASENAME)-chapter.out +clean : cleanchapter rm -f $(BASENAME)-slides.aux $(BASENAME)-slides.log $(BASENAME)-slides.out $(BASENAME)-slides.toc $(BASENAME)-slides.nav $(BASENAME)-slides.snm $(BASENAME)-slides.vrb - rm -f $(PYPDFFILES) $(GPTTEXFILES) -cleanall : clean - rm -f $(BASENAME)-chapter.pdf $(BASENAME)-slides.pdf $(BASENAME)-handout.pdf +cleanall : clean cleanallchapter + rm -f $(BASENAME)-slides.pdf $(BASENAME)-handout.pdf help : diff --git a/plotting/lecture/images/spike_detection.pdf b/plotting/lecture/images/spike_detection.pdf index 1864b4b..e27de96 100644 Binary files a/plotting/lecture/images/spike_detection.pdf and b/plotting/lecture/images/spike_detection.pdf differ diff --git a/plotting/lecture/plotting-chapter.tex b/plotting/lecture/plotting-chapter.tex index faab54e..9383d63 100644 --- a/plotting/lecture/plotting-chapter.tex +++ b/plotting/lecture/plotting-chapter.tex @@ -5,8 +5,10 @@ \lstset{inputpath=../code} \graphicspath{{images/}} -\setcounter{page}{45} -\setcounter{chapter}{1} +\typein[\pagenumber]{Number of first page} +\typein[\chapternumber]{Chapter number} +\setcounter{page}{\pagenumber} +\setcounter{chapter}{\chapternumber} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -14,5 +16,13 @@ \input{plotting} +\section{TODO} +\begin{itemize} +\item Beispiele schlechter plots sollten mehr Bezug zu den Typen von + plots haben, die wir machen! +\item subplot +\item Uebersicht zu wichtigen plot Befehlen (plot, scatter, bar, step, ...) +\end{itemize} + \end{document} diff --git a/plotting/lecture/plotting.tex b/plotting/lecture/plotting.tex index a37bb1d..530616e 100644 --- a/plotting/lecture/plotting.tex +++ b/plotting/lecture/plotting.tex @@ -1,4 +1,4 @@ -\chapter{\tr{Data plotting}{Graphische Darstellung von Daten}} +\chapter{Graphische Darstellung von Daten} Die F\"ahigkeit zur ad\"aquaten Darstellung wissenschaftlicher Daten darf durchaus zu den notwendigen Kernkompetenzen gez\"ahlt werden. Wir @@ -34,13 +34,13 @@ Zwecken genutzt wird. Ein Datenplot muss ausreichend beschriftet werden: \begin{itemize} \item Alle Achsen m\"ussen eine Bezeichnung und eine Einheit erhalten\\ - (z.B. \code{xlabel('Geschwindigkeit [m/s]'}). + (z.B. \code[xlabel()]{xlabel('Geschwindigkeit [m/s]'}). \item Wenn mehrere Dinge in einem Plot dargestellt werden, m\"ussen diese mit einer Legende oder \"ahnlichem benannt werden \matlabfun{legend()}. \item Mehrere Plots mit den gleichen Gr\"o{\ss}en auf den Achsen, m\"ussen den gleichen Wertebereich auf den Achsen zeigen - (z.B. \code{xlim([0 100])}.\\ + (z.B. \code[xlim()]{xlim([0 100])}.\\ Ausnahmen sind m\"oglich, sollten aber in der Abbildungsunterschrift erw\"ahnt werden. \item Die Beschriftung mu{\ss} gro{\ss} genug sein, um lesbar zu sein. @@ -142,13 +142,30 @@ darzustellen (\figref{misleadingsymbolsfig}). \section{Das Plottingsystem von \matlab{}} Plotten in \matlab{} ist zun\"achst einmal einfach. Durch den Aufruf -von \code{plot(x, y)} wird ein einfacher, schlichter Linienplot +von \code[plot()]{plot(x, y)} wird ein einfacher, schlichter Linienplot erstellt. Diesem Plot fehlen jedoch jegliche Annotationen wie Achsbeschriftungen, Legenden, etc. Es gibt zwei M\"oglichkeiten diese hinzuzuf\"ugen: (i) das Graphische User Interface oder (ii) die Kommandozeile. Beide haben ihre Berechtigung sowie Vor- und Nachteile. +\begin{figure} + \begin{minipage}[t]{0.6\textwidth} + \includegraphics[height=0.29\textheight]{plot_editor} + \end{minipage} + \begin{minipage}[t]{0.3\textwidth} + \includegraphics[height=0.29\textheight]{property_editor} + \end{minipage} + \titlecaption{Der \matlab{} Plot-Editor.}{\"Uber das Menu + ``Tools $\rightarrow$ Edit Plot'' erreicht man den Plot Editor. Je nachdem + welches Element des Plots ausgew\"ahlt wurde, ver\"andern sich + die Einstellungsm\"oglichkeiten. Weitere Eigenschaften und + Einstellungen k\"onnen \"uber den ``Property Editor'', rechts, + eingesehen und ver\"andert werden. Der ``Property Editor'' ist + \"uber die Schaltfl\"ache ``More Properties'' + erreichbar.}\label{ploteditorfig} +\end{figure} + W\"ahrend es bequem ist, die Abbildung mit der GUI (\figref{ploteditorfig}) zu bearbeiten sind die erhaltenen Ergebnisse nicht einfach reproduzierbar oder \"ubertragbar. Wenn eine Abbildung @@ -156,37 +173,20 @@ korrigiert werden musss, wird es schwierig und zeitaufwendig. Plots in \matlab{} bestehen aus mehreren Elementen: \begin{enumerate} -\item \enterm{Figure}: Dieses Element stellt die gesamte +\item \enterm[figure]{Figure}: Dieses Element stellt die gesamte Zeichenf\"ache, das Blatt Papier, dar. -\item \enterm{Axes}: Das Koordinatensystem in welches gezeichnet wird. -\item \enterm{Lines}: Die gezeichneten Datenplots wie Linien, +\item \enterm[axes]{Axes}: Das Koordinatensystem in welches gezeichnet wird. +\item \enterm[lines]{Lines}: Die gezeichneten Datenplots wie Linien, Fl\"achen, etc. -\item \enterm{Annotations}: Annotationen wie Textboxen oder auch - Pfeile, die zum Hervorheben von Punkten, oder Abschnitten gedacht - sind. -\item \enterm{Legends}: Legenden der Datenplots. +\item \enterm[annotations]{Annotations}: Annotationen wie Textboxen + oder auch Pfeile, die zum Hervorheben von Punkten, oder Abschnitten + gedacht sind. +\item \enterm[legends]{Legends}: Legenden der Datenplots. \end{enumerate} Jedes dieser Elemente bietet eine Vielzahl von Einstellungsm\"oglichkeiten. Wie schon erw\"ahnt, k\"onnen diese \"uber die GUI (Abbildung \ref{ploteditorfig}) bearbeitet werden. -\begin{figure} - \begin{minipage}[t]{0.6\columnwidth} - \includegraphics[width=0.9\textwidth]{plot_editor} - \end{minipage} - \begin{minipage}[t]{0.3\columnwidth} - \includegraphics[width=0.9\textwidth]{property_editor} - \end{minipage} - \titlecaption{Graphisches Interface ``Plot Editor''.}{\"Uber das Menu - ``Tools $\rightarrow$ Edit Plot'' erreicht man den Plot Editor. Je nachdem - welches Element des Plots ausgew\"ahlt wurde, ver\"andern sich - die Einstellungsm\"oglichkeiten. Weitere Eigenschaften und - Einstellungen k\"onnen \"uber den ``Property Editor'', rechts, - eingesehen und ver\"andert werden. Der ``Property Editor'' ist - \"uber die Schaltfl\"ache ``More Properties'' - erreichbar.}\label{ploteditorfig} -\end{figure} - Alle Einstellungen, die \"uber das graphische Interface vorgenommen werden k\"onnen, sind auch \"uber Befehle auf der Kommandozeile m\"oglich. Auf diese Weise k\"onnen Einstellungen problemlos in ein @@ -212,9 +212,9 @@ Datens\"atzen erstellt werden soll. \subsection{Einfaches Plotten} Einen einfachen Linienplot zu erstellen ist denkbar -einfach. Angenommen, es existiert einer Variable \code{y} im +einfach. Angenommen, es existiert einer Variable \varcode{y} im \enterm{Workspace}, die die darzustellenden Daten enth\"alt. Es -gen\"ugt folgender Funktionsaufruf: \code{plot(y)}. Wenn bislang noch +gen\"ugt folgender Funktionsaufruf: \code[plot()]{plot(y)}. Wenn bislang noch keine Abbildung erstellt wurde, \"offnet \matlab{} ein neues Fenster und stellt die Daten als Linienplot dar. Dabei werden die Datenpunkte durch eine Linie verbunden. Die Messpunkte selbst sind nicht @@ -223,14 +223,14 @@ ersetzt. Das Festhalten von bestehenden Plots kann an- oder abgestellt werden indem \code{hold on} bzw. \code{hold off} vor dem \code{plot()} Befehl aufgerufen wird. -Im obigen Plot Aufruf wird nur ein Argument, das \code{y}, an die -Funktion \code{plot} \"ubergeben. \code{plot} erh\"alt nur die +Im obigen Plot Aufruf wird nur ein Argument, das \varcode{y}, an die +Funktion \code{plot()} \"ubergeben. \code{plot()} erh\"alt nur die y-Werte. \matlab{} substituiert in diesem Fall die fehlenden x-Werte, indem eine Schrittweite von 1 angenommen wird. Die x-Achse reicht also -von 1 bis zur L\"ange des Vektors \code{y}. Diese Skalierung der +von 1 bis zur L\"ange des Vektors \varcode{y}. Diese Skalierung der x-Achse ist nur in den wenigsten F\"allen erw\"unscht. Besser ist es, die zugeh\"origen x-Werte explixit zu \"ubergeben und so z.B. die -y-Werte als Funktion der Zeit darzustellen (\code{plot(x, y)}). +y-Werte als Funktion der Zeit darzustellen (\code[plot()]{plot(x, y)}). Standard\"a{\ss}ig wird der erste Lininenplot in blau, mit durchgezogener Linie, ohne Marker und der Strichst\"arke 1 dargestellt. Der zweite Linienplot erh\"alt automatisch die Farbe @@ -241,64 +241,54 @@ Farben ist vordefiniert kann aber durch das Setzen einer die Farbe und die verschiedenen Marker. \begin{table}[tp] - \titlecaption{Vordefinierte Linienstile (links), Farben (Mitte) und Markersymbole (rechts).}{}\label{plotlinestyles} - \begin{minipage}[t]{0.3\textwidth} - \vspace{0pt} - \begin{tabular}{lc} \hline - \textbf{Linienstil} & \textbf{K\"urzel} \\\hline - durchgezogen & '\verb|-|' \\ - gestrichelt & '\verb|--|' \\ - gepunktet & '\verb|:|' \\ - Strichpunkte & '\verb|.-|' \\\hline - \end{tabular} - \end{minipage} - \vspace{0pt} - \begin{minipage}[t]{.3\textwidth} - \vspace{0pt} - \hspace{0.05\textwidth} - \begin{tabular}{lc} \hline - \textbf{Farbe} & \textbf{K\"urzel} \\ \hline - Rot & 'r'\\ - Gr\"un & 'g' \\ - Blau & 'b' \\ - Cyan & 'c' \\ - Magenta & 'm' \\ - Gelb & 'y' \\ - Schwarz & 'k' \\ \hline - \end{tabular} - \end{minipage} - \vspace{0pt} - \begin{minipage}[t]{0.3\textwidth} - \vspace{0pt} - \begin{tabular}{lc} \hline - \textbf{Markersymbol} & \textbf{K\"urzel} \\ \hline - Kreis & 'o'\\ - Stern & '*' \\ - Plus & '+' \\ - Kreuz & 'x' \\ - Diamant & 'd' \\ - Pentagramm & 'p' \\ - Hexagramm & 'h' \\ - Quadrat & 's' \\ - Dreieck & '\^{}' \\ - Umgekehrtes Dreieck & 'v' \\ - Dreieck links & '$<$'\\ - Dreieck rechts & '$>$'\\\hline - \end{tabular} - \end{minipage} + \titlecaption{Vordefinierte Linienstile (links), Farben (Mitte) und Markersymbole (rechts).}{}\label{plotlinestyles} + \begin{tabular}[t]{lc} \hline + \textbf{Linienstil} & \textbf{K\"urzel} \erh \\\hline + durchgezogen & '\verb|-|' \erb \\ + gestrichelt & '\verb|--|' \\ + gepunktet & '\verb|:|' \\ + Strichpunkte & '\verb|.-|' \\\hline + \end{tabular} + \hfill + \begin{tabular}[t]{lc} \hline + \textbf{Farbe} & \textbf{K\"urzel} \erh \\ \hline + Rot & 'r' \erb \\ + Gr\"un & 'g' \\ + Blau & 'b' \\ + Cyan & 'c' \\ + Magenta & 'm' \\ + Gelb & 'y' \\ + Schwarz & 'k' \\ \hline + \end{tabular} + \hfill + \begin{tabular}[t]{lc} \hline + \textbf{Markersymbol} & \textbf{K\"urzel} \erh \\ \hline + Kreis & 'o' \erb \\ + Stern & '*' \\ + Plus & '+' \\ + Kreuz & 'x' \\ + Diamant & 'd' \\ + Pentagramm & 'p' \\ + Hexagramm & 'h' \\ + Quadrat & 's' \\ + Dreieck & '\^{}' \\ + Umgekehrtes Dreieck & 'v' \\ + Dreieck links & '$<$'\\ + Dreieck rechts & '$>$'\\\hline + \end{tabular} \end{table} \subsection{Ver\"andern von Linieneigenschaften} Die Eigenschaften des Linienplots k\"onnen \"uber weitere Argumente -des \code{plot} Befehls ver\"andert werden. Folgender Aufruf (Listing +der \code{plot()} Funktion ver\"andert werden. Folgender Aufruf (Listing \ref{settinglineprops})erzeugt einen roten Linienplot mit gepunkteter Linie der St\"arke 1.5 und Sternmarkern an den Positionen der Datenpunkte. Zus\"atzlich wird noch die Eigenschaft -\codeterm{displayname} gesetzt, um dem Linienplot einen Namen zu +\code{displayname} gesetzt, um dem Linienplot einen Namen zu geben, der in einer Legende verwendet werden kann. -\begin{lstlisting}[label=settinglineprops, caption={Setzen von Linieneigenschaften beim \code{plot} Aufruf}] +\begin{lstlisting}[label=settinglineprops, caption={Setzen von Linieneigenschaften beim \varcode{plot} Aufruf}] x = 0:0.1:2*pi; y = sin(x); plot( x, y, 'color', 'r', 'linestyle', ':', 'marker', '*', 'linewidth', 1.5, 'displayname', 'plot 1') @@ -307,46 +297,47 @@ geben, der in einer Legende verwendet werden kann. \subsection{Ver\"andern von Achseneigenschaften} Das erste, was ein Plot zus\"atzlich braucht, ist eine -Achsenbeschriftung. Mithilfe der Funktionen \code{xlabel('Time [ms]')} -und \code{ylabel('Voltage [V]')} k\"onnen diese gesetzt +Achsenbeschriftung. Mithilfe der Funktionen \code[xlabel()]{xlabel('Time [ms]')} +und \code[ylabel()]{ylabel('Voltage [V]')} k\"onnen diese gesetzt werden. Standardm\"a{\ss}ig setzt Matlab die Grenzen der x- und y-Achse so, dass die Daten hineinpassen. Dabei wird meist auf den n\"achsten -ganzzahligen Wert aufgerundet. Mit den Funktionen \code{xlim} und -\code{ylim} k\"onnen die Grenezen der Achsen aber auch manuell -eingestellt werden. Die Funktionen \code{xlim} und \code{ylim} +ganzzahligen Wert aufgerundet. Mit den Funktionen \code{xlim()} und +\code{ylim()} k\"onnen die Grenezen der Achsen aber auch manuell +eingestellt werden. Die Funktionen \code{xlim()} und \code{ylim()} erwarten als Argument einen 2-elementigen Vektor mit dem Minimum und dem Maximum der jeweiligen Achse. Tabelle \ref{plotaxisprops} listet -weitere h\"aufig genutzte Einstellungen der Achsen. Mit der \code{set} -- Funktion k\"onnen diese ver\"andert werden wie in Zeile 15 in -Listing \ref{niceplotlisting} gezeigt. Die \code{set} - Funktion -erwartet als erstes Argument ein sogenanntes Handle der Achse, dieses -wird gefolgt von einer beliebig langen Reihe von Eigenschaft-Wert -Paaren. Soll z.B. das Gitternetz der x-Achse gezeigt werden, wird die -Eigenschaft \codeterm{XGrid} auf den Wert \codeterm{'on'} gesetzt: -\code{set(gca, 'XGrid', 'on');}. Das erste Argument ist ein Aufruf der -Funktion \code{gca}, ``get-current-axis'' und ist das Achsenhandle der -gerade aktiven Achse. +weitere h\"aufig genutzte Einstellungen der Achsen. Mit der +\code{set()} - Funktion k\"onnen diese ver\"andert werden wie in Zeile +15 in Listing \ref{niceplotlisting} gezeigt. Die \code{set()} - +Funktion erwartet als erstes Argument ein sogenanntes Handle der +Achse, dieses wird gefolgt von einer beliebig langen Reihe von +Eigenschaft-Wert Paaren. Soll z.B. das Gitternetz der x-Achse gezeigt +werden, wird die Eigenschaft \code{XGrid} auf den Wert +\varcode{'on'} gesetzt: \code[set()!set(gca, 'XGrid', +'on')]{set(gca, 'XGrid', 'on');}. Das erste Argument ist ein Aufruf +der Funktion \code{gca}, \enterm{get-current-axis} und ist das Achsenhandle +der gerade aktiven Achse. \begin{table}[tp] - \titlecaption{Ausgew\"ahlte Eigenschaften der Achse.}{ Alle Eigenschaften der Achse findet man in der Hilfe oder im \codeterm{Property Editor} (\figref{ploteditorfig}). Wenn es eine definierte Auswahl von Einstellungen gibt, z.B. bei der Eigenschaft \codeterm{Box}, dann ist die Standardeinstellungen als erstes gelistet.}\label{plotaxisprops} - \begin{tabular*}{1\textwidth}{lp{6.3cm}p{6cm}} \hline - \textbf{Eigenschaft} & \textbf{Beschreibung} & \textbf{Optionen} \\ \hline - \codeterm{Box} & Definiert, ob der Rahmen der Achse vollst\"andig gezeichnet wird. & $\{'on'|'off'\}$ \\ - \codeterm{Color} & Hintergrundfarbe des Koordinatensystems. & Beliebige RGB, CMYK ... Werte. \\ - \codeterm{Fontname} & Der Name der Schriftart. & Im System installierte Schriften. \\ - \codeterm{FontSize} & Gr\"o{\ss}e der Schrift. & Skalarer Wert.\\ - \codeterm{FontUnit} & Einheit, in der die Schriftgr\"o{\ss}e bestimmt wird. & $\{'points' | 'centimeters' | 'inches', ...\}$\\ - \codeterm{FontWeight} & Fett- oder Normalsatz der Schrift. & $\{'normal' | 'bold'\}$\\ + \titlecaption{Ausgew\"ahlte Eigenschaften der Achse.}{ Alle Eigenschaften der Achse findet man in der Hilfe oder im \codeterm{Property Editor} (\figref{ploteditorfig}). Wenn es eine definierte Auswahl von Einstellungen gibt, z.B. bei der Eigenschaft \code{Box}, dann ist die Standardeinstellungen als erstes gelistet.}\label{plotaxisprops} + \begin{tabular*}{1\textwidth}{lp{5.8cm}p{5.5cm}} \hline + \textbf{Eigenschaft} & \textbf{Beschreibung} & \textbf{Optionen} \erh \\ \hline + \code{Box} & Definiert, ob der Rahmen der Achse vollst\"andig gezeichnet wird. & $\{'on'|'off'\}$ \erb \\ + \code{Color} & Hintergrundfarbe des Koordinatensystems. & Beliebige RGB, CMYK Werte. \\ + \code{Fontname} & Der Name der Schriftart. & Im System installierte Schriften. \\ + \code{FontSize} & Gr\"o{\ss}e der Schrift. & Skalarer Wert.\\ + \code{FontUnit} & Einheit, in der die Schriftgr\"o{\ss}e bestimmt wird. & $\{'points' | 'centimeters' | 'inches', ...\}$\\ + \code{FontWeight} & Fett- oder Normalsatz der Schrift. & $\{'normal' | 'bold'\}$\\ % & 'd' \\ ?????? - \codeterm{TickDir} & Richtung der Teilstriche auf der Achse. & $\{'in' | 'out'\}$\\ - \codeterm{TickLength} & L\"ange der Haupt- und Nebenteilstriche & \\ - \codeterm{X-, Y-, ZDir} & Richtung der Achsskalierung. & $\{'normal' | 'reversed'\}$\\ - \codeterm{X-, Y-, ZGrid} & Sollen Gitternetzlinien gezeigt werden? & $\{'off'|'on'\}$ \\ - \codeterm{X-, Y-, ZScale} & Lineare oder logarithmische Skalierung der Achse. & $\{'linear' | 'log'\}$\\ - \codeterm{X-, Y-, ZTick} & Position der Teilstriche auf der Achse. & Vektor mit Positionen.\\ - \codeterm{X-, Y-, ZTickLabel} & Beschriftung der Teilstriche. & Vektor mit entsprechenden Zahlen oder Cell-Array mit Strings.\\ \hline + \code{TickDir} & Richtung der Teilstriche auf der Achse. & $\{'in' | 'out'\}$\\ + \code{TickLength} & L\"ange der Haupt- und Nebenteilstriche & \\ + \code{X-, Y-, ZDir} & Richtung der Achsskalierung. & $\{'normal' | 'reversed'\}$\\ + \code{X-, Y-, ZGrid} & Sollen Gitternetzlinien gezeigt werden? & $\{'off'|'on'\}$ \\ + \code{X-, Y-, ZScale} & Lineare oder logarithmische Skalierung der Achse. & $\{'linear' | 'log'\}$\\ + \code{X-, Y-, ZTick} & Position der Teilstriche auf der Achse. & Vektor mit Positionen.\\ + \code{X-, Y-, ZTickLabel} & Beschriftung der Teilstriche. & Vektor mit entsprechenden Zahlen oder Cell-Array mit Strings.\\ \hline \end{tabular*} \end{table} @@ -354,19 +345,19 @@ gerade aktiven Achse. \subsection{Ver\"andern von Figure-Einstellungen} \begin{table}[tp] - \titlecaption{Ausgew\"ahlte Eigenschaften der \codeterm{Figure}.}{Alle Eigenschaften der Figure findet man in der Hilfe von \matlab{} oder im \codeterm{Property Editor} wenn die Abbildung ausgew\"ahlt wurde (\figref{ploteditorfig}).}\label{plotfigureprops} - \begin{tabular*}{1\textwidth}{lp{6.3cm}p{6cm}} \hline - \textbf{Eigenschaft} & \textbf{Beschreibung} & \textbf{Optionen} \\ \hline - \codeterm{Color} & Hintergrundfarbe der Zeichenfl\"ache. & Beliebige RGB, CMYK ... Werte. \\ - \codeterm{PaperPosition} & Position der Abbildung auf dem Papier & 4-elementiger Vektor mit den Positionen der linken-unteren, und rechten-oberen Ecke. \\ - \codeterm{PaperSize} & Gr\"o{\ss}e der des Papiers. & 2-elementiger Vektor mit der Papiergr\"o{\ss}e.\\ - \codeterm{PaperUnits} & Einheit, in der die Papiergr\"o{\ss}e bestimmt wird. & $\{'inches' | 'centimeters' | 'normalized' | 'points'\}$\\ - \codeterm{Visible} & Hilfreich, wenn ein Plot aus Performanzgr\"unden nicht auf dem Bildschirm gezeigt, sondern direkt gespeichert werden soll. & $\{'on' | 'off'\}$\\ \hline + \titlecaption{Ausgew\"ahlte Eigenschaften der Figure.}{Alle Eigenschaften der \enterm[figure]{Figure} findet man in der Hilfe von \matlab{} oder im \codeterm{Property Editor} wenn die Abbildung ausgew\"ahlt wurde (\figref{ploteditorfig}).}\label{plotfigureprops} + \begin{tabular*}{1\textwidth}{lp{6.6cm}p{5.7cm}} \hline + \textbf{Eigenschaft} & \textbf{Beschreibung} & \textbf{Optionen} \erh \\ \hline + \code{Color} & Hintergrundfarbe der Zeichenfl\"ache. & Beliebige RGB, CMYK Werte. \erb \\ + \code{PaperPosition} & Position der Abbildung auf dem Papier & 4-elementiger Vektor mit den Positionen der linken-unteren, und rechten-oberen Ecke. \\ + \code{PaperSize} & Gr\"o{\ss}e der des Papiers. & 2-elementiger Vektor mit der Papiergr\"o{\ss}e.\\ + \code{PaperUnits} & Einheit, in der die Papiergr\"o{\ss}e bestimmt wird. & $\{'inches' | 'centimeters' | 'normalized' | 'points'\}$\\ + \code{Visible} & Hilfreich, wenn ein Plot aus Performanzgr\"unden nicht auf dem Bildschirm gezeigt, sondern direkt gespeichert werden soll. & $\{'on' | 'off'\}$\\ \hline \end{tabular*} \end{table} Wie die Achse, hat auch das \codeterm{Figure} Element eine Reihe von -Eigenschaften, die nach Bedarf mit der \code{set} - Funktion gesetzt +Eigenschaften, die nach Bedarf mit der \code{set()} - Funktion gesetzt werden k\"onnen (Tabelle \ref{plotfigureprops} listet die meistverwendeten). Das erste Argument f\"ur \code{set()} ist jetzt aber eine Handle f\"ur die Abbildung, nicht das @@ -380,25 +371,17 @@ Aufruf des Skripts wird exakt der gleiche Plot (Abbildung sind hier vor allem die Zeilen 2 und 3 in denen die Gr\"o{\ss}e der Abbildung in Zentimetern definiert wird. In Zeile 16 wird die Abbildung dann in genau der angegebenen Gr\"o{\ss}e im ``pdf'' Format -gespeichert. Dazu wird die Funktion \code{saveas} verwendet, die als +gespeichert. Dazu wird die Funktion \code{saveas()} verwendet, die als erstes Argument wieder ein Handle auf die Figure erwartet. Das zweite Argument ist der Dateiname, und zuletzt muss das gew\"unschte Format (Box \ref{graphicsformatbox}) angegeben werden. -\lstinputlisting[caption={Skript zur Erstellung des Plots in \figref{spikedetectionfig}.}, label=niceplotlisting]{automatic_plot.m} - \begin{figure}[t] \includegraphics{spike_detection} \titlecaption{Automatisch erstellter Plot.}{Dieser Plot wurde vollst\"andig mit dem Skript in Listing \ref{niceplotlisting} erstellt und gespeichert.}\label{spikedetectionfig} \end{figure} - -Neben den Standard-Linienplots gibt es eine ganze Reihe weiterer -M\"oglichkeiten Daten zu Visualisieren. Mathworks zeigt auf seiner -Homepage viele Beispiele mit zugeh\"origem Code -\url{http://www.mathworks.de/discovery/gallery.html}. - \begin{ibox}[t]{\label{graphicsformatbox}Dateiformate f\"ur Abbildungen.} Es gibt zwei grunds\"atzlich verschiedene Arten von Dateiformaten f\"ur Graphiken: @@ -406,7 +389,6 @@ Homepage viele Beispiele mit zugeh\"origem Code \item \determ{Rastergraphik} (\enterm{bitmap}) \item \determ{Vektorgraphik} (\enterm{vector graphics}) \end{enumerate} - Bei Rastergraphiken wird f\"ur jeden Bildpunkt (jedes Pixel) der aktuelle Farbwert angegeben. Rastergraphiken haben eine bestimmte Aufl\"osung (z.B. 300\,dpi --- dots per inch). Sie sind vor allem @@ -415,29 +397,27 @@ Homepage viele Beispiele mit zugeh\"origem Code Polygone, ...) beschrieben. Der Vorteil der Vektorgraphiken ist die Skalierbakeit ohne Qualit\"atsverlust. - \vspace{1ex} \begin{minipage}[t]{0.38\textwidth} \mbox{}\\[-2ex] - \includegraphics[width=0.93\textwidth]{VectorBitmap.pdf} + \includegraphics[width=0.85\textwidth]{VectorBitmap.pdf} \rotatebox{90}{\footnotesize by Darth Stabro at en.wikipedia.org} \end{minipage} \hfill \begin{minipage}[t]{0.5\textwidth} - Von \matlab{} unterst\"utzte Formate\footnote{Auswahl, mehr Information in der Hilfe zu \code{saveas}}:\\[2ex] + Von \matlab{} unterst\"utzte Formate\footnote{mehr Information in der Hilfe zu \code{saveas()}}:\\[2ex] \begin{tabular}{|l|c|l|} \hline - \textbf{Format} & \textbf{Typ} & \code{saveas} Argument \rule[-1.2ex]{0pt}{3.5ex} \\ \hline - pdf & Vektor & \codeterm{'pdf'} \rule{0pt}{2.5ex} \\ - eps & Vektor & \codeterm{'eps', 'epsc'} \\ - SVG & Vektor & \codeterm{'svg'} \\ - PS & Vektor & \codeterm{'ps', 'psc'} \\ - jpg & Bitmap & \codeterm{'jpeg'} \\ - tif & Bitmap & \codeterm{'tiff', 'tiffn'} \\ - png & Bitmap & \codeterm{'png'} \\ - bmp & Bitmap & \codeterm{'bmp'} \\ \hline + \textbf{Format} & \textbf{Typ} & \code{saveas()} Argument \erh \\ \hline + pdf & Vektor & \varcode{'pdf'} \erb \\ + eps & Vektor & \varcode{'eps'}, \varcode{'epsc'} \\ + SVG & Vektor & \varcode{'svg'} \\ + PS & Vektor & \varcode{'ps'}, \varcode{'psc'} \\ + jpg & Bitmap & \varcode{'jpeg'} \\ + tif & Bitmap & \varcode{'tiff'}, \varcode{'tiffn'} \\ + png & Bitmap & \varcode{'png'} \\ + bmp & Bitmap & \varcode{'bmp'} \\ \hline \end{tabular} \end{minipage} - \vspace{1ex} Wenn aus \matlab{} heraus Graphiken gespeichert werden sollen, dann ist es meistens sehr sinnvoll sie als Vektorgraphik zu speichern. Im @@ -449,6 +429,13 @@ Homepage viele Beispiele mit zugeh\"origem Code Rastergraphik allerdings deutlich schneller und speichereffizienter. \end{ibox} +\lstinputlisting[caption={Skript zur Erstellung des Plots in \figref{spikedetectionfig}.}, label=niceplotlisting]{automatic_plot.m} + +Neben den Standard-Linienplots gibt es eine ganze Reihe weiterer +M\"oglichkeiten Daten zu Visualisieren. Mathworks zeigt auf seiner +Homepage viele Beispiele mit zugeh\"origem Code +\url{http://www.mathworks.de/discovery/gallery.html}. + \section{Fazit} diff --git a/pointprocesses/code/binnedRate.m b/pointprocesses/code/binnedRate.m index 18d6b82..e34366c 100644 --- a/pointprocesses/code/binnedRate.m +++ b/pointprocesses/code/binnedRate.m @@ -1,19 +1,24 @@ -function [time, rate] = binnedRate(spike_times, bin_width, dt, t_max) -% Calculates the firing rate with the binning method. The hist -% function is used to count the number of spikes in each bin. +function [time, rate] = binned_rate(spikes, bin_width, dt, t_max) +% PSTH computed with binning method. +% The hist funciton is used to count the number of spikes in each bin. +% +% [time, rate] = binned_rate(spikes, bin_width, dt, t_max) +% % Arguments: -% spike_times, vector containing the times of the spikes. -% bin_width, the width of the bins in seconds. -% dt, the temporal resolution. -% t_max, the tiral duration. +% spikes : vector containing the times of the spikes. +% bin_width: the width of the bins in seconds. +% dt : the temporal resolution. +% t_max : the tiral duration. % -% Returns two vectors containing the time and the rate. +% Returns: +% two vectors containing the time and the rate. -time = 0:dt:t_max-dt; -bins = 0:bin_width:t_max; -rate = zeros(size(time)); - -h = hist(spike_times, bins) ./ bin_width; -for i = 2:length(bins) - rate(round(bins(i - 1) / dt) + 1:round(bins(i) / dt)) = h(i); + time = 0:dt:t_max-dt; + bins = 0:bin_width:t_max; + rate = zeros(size(time)); + h = hist(spikes, bins) ./ bin_width; + for i = 2:length(bins) + rate(round(bins(i - 1) / dt) + 1:round(bins(i) / dt)) = h(i); + end end + diff --git a/pointprocesses/code/convolutionRate.m b/pointprocesses/code/convolutionRate.m index e2c4834..a2b1344 100644 --- a/pointprocesses/code/convolutionRate.m +++ b/pointprocesses/code/convolutionRate.m @@ -1,17 +1,20 @@ -function [time, rate] = convolutionRate(spike_times, sigma, dt, t_max) -% Calculates the firing rate with the convolution method. +function [time, rate] = convolution_rate(spikes, sigma, dt, t_max) +% PSTH computed with convolution method. +% +% [time, rate] = convolution_rate(spikes, sigma, dt, t_max) +% % Arguments: -% spike_times, a vector containing the spike times. -% sigma, the standard deviation of the Gaussian kernel -% in seconds. -% dt, the temporal resolution in seconds. -% t_max, the trial duration in seconds. +% spikes: a vector containing the spike times. +% sigma : the standard deviation of the Gaussian kernel in seconds. +% dt : the temporal resolution in seconds. +% t_max : the trial duration in seconds. % -% Returns two vectors containing the time and the rate. +% Returns: + two vectors containing the time and the rate. time = 0:dt:t_max - dt; rate = zeros(size(time)); -spike_indices = round(spike_times / dt); +spike_indices = round(spikes / dt); rate(spike_indices) = 1; kernel = gaussKernel(sigma, dt); diff --git a/pointprocesses/code/instantaneousRate.m b/pointprocesses/code/instantaneousRate.m index 6f8d8dd..8928c31 100644 --- a/pointprocesses/code/instantaneousRate.m +++ b/pointprocesses/code/instantaneousRate.m @@ -1,22 +1,24 @@ -function [time, rate] = instantaneousRate(spike_times, dt, t_max) -% Function calculates the firing rate as the inverse of the interspike -% interval. +function [time, rate] = instantaneous_rate(spikes, dt, t_max) +% Firing rate as the inverse of the interspike interval. +% +% [time, rate] = instantaneous_rate(spikes, dt, t_max) +% % Arguments: -% spike_times, vector containing the times of the spikes. -% dt, the temporal resolutions of the recording. -% t_max, the duration of the trial. +% spikes: vector containing the times of the spikes. +% dt : the temporal resolutions of the recording. +% t_max : the duration of the trial. % -% Returns two vectors containing the time and the rate. +% Returns: +% the vector representing time and a vector containing the rate. -time = 0:dt:t_max-dt; -rate = zeros(size(time)); + time = 0:dt:t_max-dt; + rate = zeros(size(time)); -isis = diff([0 spike_times]); -inst_rate = 1 ./ isis; -spike_indices = [1 round(spike_times ./ dt)]; + isis = diff([0 spikes]); + inst_rate = 1 ./ isis; + spike_indices = [1 round(spikes ./ dt)]; -for i = 2:length(spike_indices) - rate(spike_indices(i - 1):spike_indices(i)) = inst_rate(i - 1); + for i = 2:length(spike_indices) + rate(spike_indices(i - 1):spike_indices(i)) = inst_rate(i - 1); + end end - - diff --git a/pointprocesses/code/isi_hist.m b/pointprocesses/code/isiHist.m similarity index 90% rename from pointprocesses/code/isi_hist.m rename to pointprocesses/code/isiHist.m index f529f8c..4f28f32 100644 --- a/pointprocesses/code/isi_hist.m +++ b/pointprocesses/code/isiHist.m @@ -1,7 +1,7 @@ -function [pdf, centers] = isi_hist(isis, binwidth) +function [pdf, centers] = isiHist(isis, binwidth) % Compute normalized histogram of interspike intervals. % -% [pdf, centers] = isi_hist(isis, binwidth) +% [pdf, centers] = isiHist(isis, binwidth) % % Arguments: % isis: vector of interspike intervals in seconds diff --git a/pointprocesses/code/isis.m b/pointprocesses/code/isis.m index 869cb60..b927abd 100644 --- a/pointprocesses/code/isis.m +++ b/pointprocesses/code/isis.m @@ -2,7 +2,12 @@ function isivec = isis( spikes ) % returns a single list of isis computed from all trials in spikes % % isivec = isis( spikes ) +% +% Arguments: % spikes: a cell array of vectors of spike times in seconds +% isivec: a column vector with all the interspike intervalls +% +% Returns: % isivec: a column vector with all the interspike intervalls isivec = []; @@ -13,4 +18,3 @@ function isivec = isis( spikes ) isivec = [ isivec; difftimes(:) ]; end end - diff --git a/pointprocesses/code/plot_isi_hist.m b/pointprocesses/code/plotISIHist.m similarity index 86% rename from pointprocesses/code/plot_isi_hist.m rename to pointprocesses/code/plotISIHist.m index 9fb6bf9..e181c3a 100644 --- a/pointprocesses/code/plot_isi_hist.m +++ b/pointprocesses/code/plotISIHist.m @@ -1,7 +1,7 @@ -function plot_isi_hist(isis, binwidth) +function plotISIHist(isis, binwidth) % Plot and annotate histogram of interspike intervals. % -% isihist(isis, binwidth) +% plotISIHist(isis, binwidth) % % Arguments: % isis: vector of interspike intervals in seconds @@ -9,9 +9,9 @@ function plot_isi_hist(isis, binwidth) % compute normalized histogram: if nargin < 2 - [pdf, centers] = isi_hist(isis); + [pdf, centers] = isiHist(isis); else - [pdf, centers] = isi_hist(isis, binwidth); + [pdf, centers] = isiHist(isis, binwidth); end % plot: diff --git a/pointprocesses/code/reconstructStimulus.m b/pointprocesses/code/reconstructStimulus.m index 51cb0b1..6c46a40 100644 --- a/pointprocesses/code/reconstructStimulus.m +++ b/pointprocesses/code/reconstructStimulus.m @@ -1,19 +1,19 @@ -function s_est = reconstructStimulus(spike_times, sta, stim_duration, dt) -% Function estimates the stimulus from the Spike-Triggered-Average -% (sta). +function s_est = reconstructStimulus(spikes, sta, duration, deltat) +% Estimate the stimulus from the spike-triggered-average (STA). +% +% s_est = reconstructStimulus(spikes, sta, duration, deltat) +% % Arguments: -% spike_times, a vector containing the spike times in seconds. -% sta, a vector containing the spike-triggered-average. -% stim_duration, the total duration of the stimulus. -% dt, the sampling interval given in seconds. +% spikes : a vector containing the spike times in seconds. +% sta : a vector containing the spike-triggered-average. +% duration: the total duration of the stimulus. +% deltat : the time step of the stimulus in seconds. % % Returns: -% the estimated stimulus. - -s_est = zeros(round(stim_duration / dt), 1); - -binary_spikes = zeros(size(s_est)); -binary_spikes(round(spike_times ./ dt)) = 1; - -s_est = conv(binary_spikes, sta, 'same'); +% s_est: vector with the estimated stimulus. + s_est = zeros(round(duration / deltat), 1); + binary_spikes = zeros(size(s_est)); + binary_spikes(round(spikes ./ deltat)) = 1; + s_est = conv(binary_spikes, sta, 'same'); +end diff --git a/pointprocesses/code/spikeTriggeredAverage.m b/pointprocesses/code/spikeTriggeredAverage.m index 6954f43..fcc0352 100644 --- a/pointprocesses/code/spikeTriggeredAverage.m +++ b/pointprocesses/code/spikeTriggeredAverage.m @@ -1,32 +1,31 @@ -function [sta, std_sta, valid_spikes] = spikeTriggeredAverage(stimulus, spike_times, count, sampling_rate) -% Function estimates the Spike-Triggered-Average (sta). +function [sta, std_sta, n_spikes] = spikeTriggeredAverage(stimulus, spikes, count, deltat) +% Estimate the spike-triggered-average (STA). +% +% [sta, std_sta, n_spikes] = spikeTriggeredAverage(stimulus, spikes, count, deltat) % % Arguments: -% stimulus, a vector containing stimulus intensities -% as a function of time. -% spike_times, a vector containing the spike times -% in seconds. -% count, the number of datapoints that are taken around -% the spike times. -% sampling_rate, the sampling rate of the stimulus. +% stimulus: vector of stimulus intensities as a function of time. +% spikes : vector with spike times in seconds. +% count : number of datapoints that are taken around the spike times. +% deltat : the time step of the stimulus in seconds. % % Returns: -% the sta, a vector containing the staandard deviation and -% the number of spikes taken into account. +% sta : vector with the STA. +% std_sta : standard deviation of the STA. +% n_spikes: number of spikes contained in STA. -snippets = zeros(numel(spike_times), 2*count); -valid_spikes = 1; -for i = 1:numel(spike_times) - t = spike_times(i); - index = round(t*sampling_rate); - if index <= count || (index + count) > length(stimulus) - continue + snippets = zeros(numel(spikes), 2*count); + n_spikes = 0; + for i = 1:numel(spikes) + t = spikes(i); + index = round(t/deltat); + if index <= count || (index + count) > length(stimulus) + continue + end + snippets(n_spikes,:) = stimulus(index-count:index+count-1); + n_spikes = n_spikes + 1; end - snippets(valid_spikes,:) = stimulus(index-count:index+count-1); - valid_spikes = valid_spikes + 1; + snippets(n_spikes+1:end,:) = []; + sta = mean(snippets, 1); + std_sta = std(snippets,[],1); end - -snippets(valid_spikes:end,:) = []; - -sta = mean(snippets, 1); -std_sta = std(snippets,[],1); diff --git a/pointprocesses/lecture/Makefile b/pointprocesses/lecture/Makefile index 44c7d3b..e53a65d 100644 --- a/pointprocesses/lecture/Makefile +++ b/pointprocesses/lecture/Makefile @@ -1,21 +1,12 @@ BASENAME=pointprocesses -PYFILES=$(wildcard *.py) -PYPDFFILES=$(PYFILES:.py=.pdf) - -GPTFILES=$(wildcard *.gpt) -GPTTEXFILES=$(GPTFILES:.gpt=.tex) - all: pdf slides thumbs +include ../../chapter.mk + # script: -pdf : $(BASENAME)-chapter.pdf -$(BASENAME)-chapter.pdf : $(BASENAME)-chapter.tex $(BASENAME).tex ../../header.tex $(GPTTEXFILES) $(PYPDFFILES) - CHAPTER=$$(( $$(sed -n -e '/contentsline {chapter}/{s/.*numberline {\([0123456789]*\)}.*/\1/; p}' $(BASENAME).aux) - 1 )); \ - PAGE=$$(sed -n -e '/contentsline {chapter}/{s/.*numberline {.*}.*}{\(.*\)}{chapter.*/\1/; p}' $(BASENAME).aux); \ - sed -i -e "s/setcounter{page}{.*}/setcounter{page}{$$PAGE}/; s/setcounter{chapter}{.*}/setcounter{chapter}{$$CHAPTER}/" $(BASENAME)-chapter.tex - pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex -interaction=scrollmode $< || true +pdf : chapter # slides: @@ -31,31 +22,15 @@ $(BASENAME)-handout.pdf: $(BASENAME)-slides.tex $(GPTTEXFILES) pdfnup --nup 2x4 --no-landscape --paper a4paper --trim "-1cm -1cm -1cm -1cm" --outfile $@ thumbsfoils.pdf # 1-19 rm thumbsfoils.* -watchpdf : - while true; do ! make -q pdf && make pdf; sleep 0.5; done - watchslides : while true; do ! make -q slides && make slides; sleep 0.5; done -# python plots: -$(PYPDFFILES) : %.pdf: %.py - python $< - -# gnuplot plots: -$(GPTTEXFILES) : %.tex: %.gpt whitestyles.gp - gnuplot whitestyles.gp $< - epstopdf $*.eps - -clean : - rm -f *~ - rm -f $(BASENAME).aux $(BASENAME).log - rm -f $(BASENAME)-chapter.aux $(BASENAME)-chapter.log $(BASENAME)-chapter.out +clean : cleanchapter rm -f $(BASENAME)-slides.aux $(BASENAME)-slides.log $(BASENAME)-slides.out $(BASENAME)-slides.toc $(BASENAME)-slides.nav $(BASENAME)-slides.snm $(BASENAME)-slides.vrb - rm -f $(PYPDFFILES) $(GPTTEXFILES) -cleanall : clean - rm -f $(BASENAME)-chapter.pdf $(BASENAME)-slides.pdf $(BASENAME)-handout.pdf +cleanall : clean cleanchapter + $(BASENAME)-slides.pdf $(BASENAME)-handout.pdf help : diff --git a/pointprocesses/lecture/isihexamples.py b/pointprocesses/lecture/isihexamples.py index 9d50fbc..b03d2a9 100644 --- a/pointprocesses/lecture/isihexamples.py +++ b/pointprocesses/lecture/isihexamples.py @@ -98,4 +98,4 @@ plotisih(ax, isis(inhspikes)) plt.tight_layout() plt.savefig('isihexamples.pdf') -plt.show() +plt.close() diff --git a/pointprocesses/lecture/pointprocesses-chapter.tex b/pointprocesses/lecture/pointprocesses-chapter.tex index 70de527..4570c91 100644 --- a/pointprocesses/lecture/pointprocesses-chapter.tex +++ b/pointprocesses/lecture/pointprocesses-chapter.tex @@ -5,8 +5,10 @@ \lstset{inputpath=../code} \graphicspath{{figures/}} -\setcounter{page}{111} -\setcounter{chapter}{7} +\typein[\pagenumber]{Number of first page} +\typein[\chapternumber]{Chapter number} +\setcounter{page}{\pagenumber} +\setcounter{chapter}{\chapternumber} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -14,5 +16,11 @@ \input{pointprocesses} +\section{TODO} +\begin{itemize} +\item Add spikeraster function +\item Multitrial firing rates +\end{itemize} + \end{document} diff --git a/pointprocesses/lecture/pointprocesses.tex b/pointprocesses/lecture/pointprocesses.tex index 7249097..8437aa4 100644 --- a/pointprocesses/lecture/pointprocesses.tex +++ b/pointprocesses/lecture/pointprocesses.tex @@ -2,7 +2,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Analyse von Spiketrains} -\determ{Aktionspotentiale} (\enterm{Spikes}) sind die Tr\"ager der +\determ[Aktionspotential]{Aktionspotentiale} (\enterm{spikes}) sind die Tr\"ager der Information in Nervensystemen. Dabei ist in erster Linie nur der Zeitpunkt des Auftretens eines Aktionspotentials von Bedeutung. Die genaue Form des Aktionspotentials spielt keine oder nur eine @@ -10,13 +10,13 @@ untergeordnete Rolle. Nach etwas Vorverarbeitung haben elektrophysiologische Messungen deshalb Listen von Spikezeitpunkten als Ergebniss --- sogenannte -\enterm{Spiketrains}. Diese Messungen k\"onnen wiederholt werden und +\enterm{spiketrains}. Diese Messungen k\"onnen wiederholt werden und es ergeben sich mehrere \enterm{trials} von Spiketrains (\figref{rasterexamplesfig}). Spiketrains sind Zeitpunkte von Ereignissen --- den Aktionspotentialen --- und deren Analyse f\"allt daher in das Gebiet der Statistik von -sogenannten \determ{Punktprozessen}. +sogenannten \determ[Punktprozess]{Punktprozessen}. \begin{figure}[ht] \includegraphics[width=1\textwidth]{rasterexamples} @@ -25,7 +25,9 @@ sogenannten \determ{Punktprozessen}. (homogener Poisson Prozess mit Rate $\lambda=20$\;Hz, links) und eines nicht-station\"aren Punktprozesses (perfect integrate-and-fire Neuron getrieben mit Ohrnstein-Uhlenbeck - Rauschen mit Zeitkonstante $\tau=100$\,ms, rechts).} + Rauschen mit Zeitkonstante $\tau=100$\,ms, rechts). Jeder + vertikale Strich markiert den Zeitpunkt eines Ereignisses. + Jede Zeile zeigt die Ereignisse eines trials.} \end{figure} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -79,11 +81,12 @@ Zeitpunkte der Ereignisse durch senkrechte Striche markiert werden. Die Intervalle $T_i=t_{i+1}-t_i$ zwischen aufeinanderfolgenden Ereignissen sind reelle, positive Zahlen. Bei Aktionspotentialen -heisen die Intervalle auch \enterm{Interspikeintervalle}. Deren Statistik -kann mit den \"ublichen Gr\"o{\ss}en beschrieben werden. +heisen die Intervalle auch \determ{Interspikeintervalle} +(\enterm{interspike intervals}). Deren Statistik kann mit den +\"ublichen Gr\"o{\ss}en beschrieben werden. \begin{figure}[t] - \includegraphics[width=1\textwidth]{isihexamples}\hfill + \includegraphics[width=0.96\textwidth]{isihexamples}\vspace{-2ex} \titlecaption{\label{isihexamplesfig}Interspikeintervall Histogramme}{der in \figref{rasterexamplesfig} gezeigten Spikes.} \end{figure} @@ -104,21 +107,21 @@ kann mit den \"ublichen Gr\"o{\ss}en beschrieben werden. \frac{1}{n}\sum\limits_{i=1}^n T_i$. \item Standardabweichung der Intervalle: $\sigma_{ISI} = \sqrt{\langle (T - \langle T \rangle)^2 \rangle}$\vspace{1ex} -\item Variationskoeffizient (\enterm{coefficient of variation}): $CV_{ISI} = +\item \determ{Variationskoeffizient} (\enterm{coefficient of variation}): $CV_{ISI} = \frac{\sigma_{ISI}}{\mu_{ISI}}$. -\item Diffusions Koeffizient: $D_{ISI} = +\item \determ{Diffusionskoeffizient} (\enterm{diffusion coefficient}): $D_{ISI} = \frac{\sigma_{ISI}^2}{2\mu_{ISI}^3}$. \end{itemize} -\begin{exercise}{isi_hist.m}{} - Schreibe eine Funktion \code{isi\_hist()}, die einen Vektor mit Interspikeintervallen +\begin{exercise}{isiHist.m}{} + Schreibe eine Funktion \code{isiHist()}, die einen Vektor mit Interspikeintervallen entgegennimmt und daraus ein normiertes Histogramm der Interspikeintervalle berechnet. \end{exercise} -\begin{exercise}{plot_isi_hist.m}{} +\begin{exercise}{plotISIHist.m}{} Schreibe eine Funktion, die die Histogrammdaten der Funktion - \code{isi\_hist()} entgegennimmt, um das Histogramm zu plotten. Im + \code{isiHist()} entgegennimmt, um das Histogramm zu plotten. Im Plot sollen die Interspikeintervalle in Millisekunden aufgetragen werden. Das Histogramm soll zus\"atzlich mit Mittelwert, Standardabweichung und Variationskoeffizient der @@ -139,9 +142,10 @@ sichtbar. im Abstand des Lags $k$.} \end{figure} -Solche Ab\"angigkeiten werden durch die serielle Korrelation der -Intervalle quantifiziert. Das ist der Korrelationskoeffizient -zwischen aufeinander folgenden Intervallen getrennt durch lag $k$: +Solche Ab\"angigkeiten werden durch die \determ{serielle + Korrelationen} (\enterm{serial correlations}) der Intervalle +quantifiziert. Das ist der \determ{Korrelationskoeffizient} zwischen +aufeinander folgenden Intervallen getrennt durch lag $k$: \[ \rho_k = \frac{\langle (T_{i+k} - \langle T \rangle)(T_i - \langle T \rangle) \rangle}{\langle (T_i - \langle T \rangle)^2\rangle} = \frac{{\rm cov}(T_{i+k}, T_i)}{{\rm var}(T_i)} = {\rm corr}(T_{i+k}, T_i) \] \"Ublicherweise wird die Korrelation $\rho_k$ gegen den Lag $k$ @@ -151,6 +155,7 @@ Intervalls mit sich selber). \begin{exercise}{isiserialcorr.m}{} Schreibe eine Funktion \code{isiserialcorr()}, die einen Vektor mit Interspikeintervallen entgegennimmt und daraus die seriellen Korrelationen berechnet und plottet. + \pagebreak[4] \end{exercise} @@ -170,10 +175,10 @@ durch folgende Sch\"atzer charakterisiert werden: \item Histogramm der counts $n_i$. \item Mittlere Anzahl von Ereignissen: $\mu_N = \langle n \rangle$. \item Varianz der Anzahl: $\sigma_n^2 = \langle (n - \langle n \rangle)^2 \rangle$. -\item Fano Faktor (Varianz geteilt durch Mittelwert): $F = \frac{\sigma_n^2}{\mu_n}$. +\item \determ{Fano Faktor} (Varianz geteilt durch Mittelwert): $F = \frac{\sigma_n^2}{\mu_n}$. \end{itemize} Insbesondere ist die mittlere Rate der Ereignisse $r$ (Spikes pro -Zeit, \determ{Feuerrate}) gemessen in Hertz +Zeit, \determ{Feuerrate}) gemessen in Hertz \sindex[term]{Feuerrate!mittlere Rate} \begin{equation} \label{firingrate} r = \frac{\langle n \rangle}{W} \; . @@ -209,18 +214,18 @@ u.a. wegen dem Zentralen Grenzwertsatz die Standardverteilung. Eine \"ahnliche Rolle spielt bei Punktprozessen der \determ{Poisson Prozess}. -Beim homogenen Poisson Prozess treten Ereignisse mit einer festen Rate -$\lambda=\text{const.}$ auf und sind unabh\"angig von der Zeit $t$ und -unabh\"angig von den Zeitpunkten fr\"uherer Ereignisse -(\figref{hompoissonfig}). Die Wahrscheinlichkeit zu irgendeiner Zeit -ein Ereigniss in einem kleinen Zeitfenster der Breite $\Delta t$ zu -bekommen ist +Beim \determ[Poisson Prozess!homogener]{homogenen Poisson Prozess} +treten Ereignisse mit einer festen Rate $\lambda=\text{const.}$ auf +und sind unabh\"angig von der Zeit $t$ und unabh\"angig von den +Zeitpunkten fr\"uherer Ereignisse (\figref{hompoissonfig}). Die +Wahrscheinlichkeit zu irgendeiner Zeit ein Ereigniss in einem kleinen +Zeitfenster der Breite $\Delta t$ zu bekommen ist \begin{equation} \label{hompoissonprob} P = \lambda \cdot \Delta t \; . \end{equation} -Beim inhomogenen Poisson Prozess h\"angt die Rate $\lambda$ von der -Zeit ab: $\lambda = \lambda(t)$. +Beim \determ[Poisson Prozess!inhomogener]{inhomogenen Poisson Prozess} +h\"angt die Rate $\lambda$ von der Zeit ab: $\lambda = \lambda(t)$. \begin{exercise}{poissonspikes.m}{} Schreibe eine Funktion \code{poissonspikes()}, die die Spikezeiten @@ -253,14 +258,15 @@ Der homogene Poissonprozess hat folgende Eigenschaften: \item Das mittlere Intervall ist $\mu_{ISI} = \frac{1}{\lambda}$ . \item Die Varianz der Intervalle ist $\sigma_{ISI}^2 = \frac{1}{\lambda^2}$ . \item Der Variationskoeffizient ist also immer $CV_{ISI} = 1$ . -\item Die seriellen Korrelationen $\rho_k =0$ f\"ur $k>0$, da das - Auftreten der Ereignisse unabh\"angig von der Vorgeschichte ist. Ein - solcher Prozess wird auch \determ{Erneuerungsprozess} genannt (\enterm{renewal - process}). -\item Die Anzahl der Ereignisse $k$ innerhalb eines Fensters der L\"ange W ist Poissonverteilt: +\item Die \determ[serielle Korrelationen]{seriellen Korrelationen} + $\rho_k =0$ f\"ur $k>0$, da das Auftreten der Ereignisse + unabh\"angig von der Vorgeschichte ist. Ein solcher Prozess wird + auch \determ{Erneuerungsprozess} genannt (\enterm{renewal process}). +\item Die Anzahl der Ereignisse $k$ innerhalb eines Fensters der + L\"ange W ist \determ[Poisson-Verteilung]{Poissonverteilt}: \[ P(k) = \frac{(\lambda W)^ke^{\lambda W}}{k!} \] (\figref{hompoissoncountfig}) -\item Der Fano Faktor ist immer $F=1$ . +\item Der \determ{Fano Faktor} ist immer $F=1$ . \end{itemize} \begin{exercise}{hompoissonspikes.m}{} @@ -299,13 +305,11 @@ Abbildung \ref{psthfig} n\"aher erl\"autert. \begin{figure}[tp] \includegraphics[width=\columnwidth]{firingrates} - \titlecaption{Verschiedene Methoden die zeitabh\"angige Feuerrate - zu bestimmen.}{\textbf{A)} Rasterplot einer einzelnen neuronalen - Antwort. Jeder vertikale Strich notiert den Zeitpunkt eines - Aktionspotentials. \textbf{B)} Feurerrate aus der instantanen - Feuerrate bestimmt. \textbf{C)} klassisches PSTH mit der Binning - Methode. \textbf{D)} Feuerrate durch Faltung mit einem Gauss Kern - bestimmt.}\label{psthfig} + \titlecaption{Bestimmung der zeitabh\"angigen + Feuerrate.}{\textbf{A)} Rasterplot eines Spiketrains. \textbf{B)} + Feurerrate aus der instantanen Feuerrate bestimmt. \textbf{C)} + klassisches PSTH mit der Binning Methode. \textbf{D)} Feuerrate + durch Faltung mit einem Gauss Kern bestimmt.}\label{psthfig} \end{figure} @@ -314,26 +318,27 @@ Abbildung \ref{psthfig} n\"aher erl\"autert. \begin{figure}[tp] \includegraphics[width=\columnwidth]{isimethod} \titlecaption{Instantane Feuerrate.}{Skizze eines Spiketrains - (oben). Jeder vertikale Strich notiert den Zeitpunkt eines - Aktionspotentials. Die Pfeile zwischen aufeinanderfolgenden + (oben). Die Pfeile zwischen aufeinanderfolgenden Aktionspotentialen mit den Zahlen in Millisekunden illustrieren die Interspikeintervalle. Der Kehrwert des Interspikeintervalle ergibt die instantane Feuerrate.}\label{instrate} \end{figure} Ein sehr einfacher Weg, die zeitabh\"angige Feuerrate zu bestimmen ist -die sogenannte \determ{instantane Feuerrate}. Dabei wird die Feuerrate -aus dem Kehrwert der Interspikeintervalle, der Zeit zwischen zwei -aufeinander folgenden Aktionspotentialen (\figref{instrate} A), -bestimmt. Die abgesch\"atzte Feuerrate (\figref{instrate} B) ist -g\"ultig f\"ur das gesammte Interspikeintervall. Diese Methode hat den -Vorteil, dass sie sehr einfach zu berechnen ist und keine Annahme -\"uber eine relevante Zeitskala (der Kodierung oder des -Auslesemechanismus der postsynaptischen Zelle) macht. $r(t)$ ist -allerdings keine kontinuierliche Funktion, die Spr\"unge in der -Feuerrate k\"onnen f\"ur manche Analysen nachteilig sein. Au{\ss}erdem -wird die Feuerrate nie gleich Null, auch wenn lange keine Aktionspotentiale -generiert wurden. +die sogenannte \determ[Feuerrate!instantane]{instantane Feuerrate} +(\enterm[firing rate!instantaneous]{instantaneous firing rate}). Dabei +wird die Feuerrate aus dem Kehrwert der Interspikeintervalle, der Zeit +zwischen zwei aufeinander folgenden Aktionspotentialen +(\figref{instrate} A), bestimmt. Die abgesch\"atzte Feuerrate +(\figref{instrate} B) ist g\"ultig f\"ur das gesammte +Interspikeintervall. Diese Methode hat den Vorteil, dass sie sehr +einfach zu berechnen ist und keine Annahme \"uber eine relevante +Zeitskala (der Kodierung oder des Auslesemechanismus der +postsynaptischen Zelle) macht. $r(t)$ ist allerdings keine +kontinuierliche Funktion, die Spr\"unge in der Feuerrate k\"onnen +f\"ur manche Analysen nachteilig sein. Au{\ss}erdem wird die Feuerrate +nie gleich Null, auch wenn lange keine Aktionspotentiale generiert +wurden. \begin{exercise}{instantaneousRate.m}{} Implementiere die Absch\"atzung der Feuerrate auf Basis der @@ -345,9 +350,10 @@ generiert wurden. W\"ahrend die Instantane Rate den Kehrwert der Zeit von einem bis zum n\"achsten Aktionspotential misst, sch\"atzt das sogenannte \determ{Peri-Stimulus-Zeit-Histogramm} (\enterm{peri stimulus time - histogram}, PSTH) die Wahrscheinlichkeit ab, zu einem Zeitpunkt -Aktionspotentiale anzutreffen. Es wird versucht die mittlere Rate \eqnref{firingrate} -im Grenzwert kleiner Beobachtungszeiten abzusch\"atzen: + histogram}, \determ[PSTH|see{Peri-Stimulus-Zeit-Histogramm}]{PSTH}) +die Wahrscheinlichkeit ab, zu einem Zeitpunkt Aktionspotentiale +anzutreffen. Es wird versucht die mittlere Rate \eqnref{firingrate} im +Grenzwert kleiner Beobachtungszeiten abzusch\"atzen: \begin{equation} \label{psthrate} r(t) = \lim_{W \to 0} \frac{\langle n \rangle}{W} \; , @@ -377,9 +383,9 @@ Bei der Binning-Methode wird die Zeitachse in gleichm\"aßige Abschnitte (Bins) eingeteilt und die Anzahl Aktionspotentiale, die in die jeweiligen Bins fallen, gez\"ahlt (\figref{binpsth} A). Um diese Z\"ahlungen in die Feuerrate umzurechnen muss noch mit der Binweite -normiert werden. Das ist fast so, wie beim Absch\"atzen einer -Wahrscheinlichkeitsdichte. Es kann auch die \code{hist} Funktion zur -Bestimmung des PSTHs verwendet werden. +normiert werden. Das ist \"aquivalent zur Absch\"atzung einer +Wahrscheinlichkeitsdichte. Es kann auch die \code{hist()} Funktion zur +Bestimmung des PSTHs verwendet werden. \sindex[term]{Feuerrate!Binningmethode} Die bestimmte Feuerrate gilt f\"ur das gesamte Bin (\figref{binpsth} B). Das so berechnete PSTH hat wiederum eine stufige Form, die von der @@ -390,6 +396,7 @@ vorkommen k\"onnen nicht aufgl\"ost werden. Mit der Wahl der Binweite wird somit eine Annahme \"uber die relevante Zeitskala des Spiketrains gemacht. +\pagebreak[4] \begin{exercise}{binnedRate.m}{} Implementiere die Absch\"atzung der Feuerrate mit der ``binning'' Methode. Plotte das PSTH. @@ -421,7 +428,7 @@ wobei $\omega(\tau)$ der Filterkern und $\rho(t)$ die bin\"are Antwort ist. Bildlich geprochen wird jede 1 in $\rho(t)$ durch den Filterkern ersetzt (Abbildung \ref{convrate} A). Wenn der Kern richtig normiert wurde (Integral gleich Eins), ergibt sich die Feuerrate direkt aus der -\"Uberlagerung der Kerne (Abb. \ref{convrate} B). +\"Uberlagerung der Kerne (Abb. \ref{convrate} B). \sindex[term]{Feuerrate!Faltungsmethode} Die Faltungsmethode f\"uhrt, anders als die anderen Methoden, zu einer stetigen Funktion was insbesondere f\"ur spektrale Analysen von @@ -430,6 +437,7 @@ Binweite, die zeitliche Aufl\"osung von $r(t)$. Die Breite des Kerns macht also auch wieder eine Annahme \"uber die relevante Zeitskala des Spiketrains. +\pagebreak[4] \begin{exercise}{convolutionRate.m}{} Verwende die Faltungsmethode um die Feuerrate zu bestimmen. Plotte das Ergebnis. @@ -438,8 +446,9 @@ Spiketrains. \section{Spike-triggered Average} Die graphischer Darstellung der Feuerrate allein reicht nicht aus um den Zusammenhang zwischen neuronaler Antwort und einem Stimulus zu -analysieren. Eine Methode um mehr \"uber diesen Zusammenhang zu erfahren, -ist der \enterm{Spike-triggered average} (STA). Der STA +analysieren. Eine Methode um mehr \"uber diesen Zusammenhang zu +erfahren, ist der \enterm{spike-triggered average} +(\enterm[STA|see{spike-triggered average}]{STA}). Der STA \begin{equation} STA(\tau) = \langle s(t - \tau) \rangle = \frac{1}{N} \sum_{i=1}^{N} s(t_i - \tau) \end{equation} @@ -477,17 +486,20 @@ antworten. Der STA kann auch dazu benutzt werden, aus den Antworten der Zelle den Stimulus zu rekonstruieren (\figref{stafig} B). Bei der -\determ{invertierten Rekonstruktion} wird die Zellantwort mit dem STA -verfaltet. +\determ[invertierte Rekonstruktion]{invertierten Rekonstruktion} wird +die Zellantwort mit dem STA verfaltet. \begin{exercise}{spikeTriggeredAverage.m}{} Implementiere eine Funktion, die den STA ermittelt. Verwende dazu - den Datensatz \codeterm{sta\_data.mat}. Die Funktion sollte folgende + den Datensatz \file{sta\_data.mat}. Die Funktion sollte folgende R\"uckgabewerte haben: + \vspace{-1ex} \begin{itemize} + \setlength{\itemsep}{0ex} \item den Spike-Triggered-Average. \item die Standardabweichung der individuellen STAs. - \item die Anzahl Aktionspotentiale, die dem STA zugrunde liegen. + \item die Anzahl Aktionspotentiale, die zur Berechnung des STA verwendet wurden. + \vspace{-2ex} \end{itemize} \end{exercise} @@ -495,7 +507,5 @@ verfaltet. Rekonstruiere den Stimulus mithilfe des STA und der Spike Zeiten. Die Funktion soll Vektor als R\"uckgabewert haben, der genauso gro{\ss} ist wie der Originalstimulus aus der Datei - \codeterm{sta\_data.mat}. + \file{sta\_data.mat}. \end{exercise} - - diff --git a/pointprocesses/lecture/pointprocessscetch.gpt b/pointprocesses/lecture/pointprocessscetch.gpt index a758639..4579ff8 100644 --- a/pointprocesses/lecture/pointprocessscetch.gpt +++ b/pointprocesses/lecture/pointprocessscetch.gpt @@ -1,4 +1,4 @@ -set term epslatex size 11.4cm, 7cm +set term epslatex size 11.4cm, 6.5cm set out 'pointprocessscetch.tex' set border 0 diff --git a/pointprocesses/lecture/pointprocessscetchA.eps b/pointprocesses/lecture/pointprocessscetchA.eps index 041fcf8..3b37567 100644 --- a/pointprocesses/lecture/pointprocessscetchA.eps +++ b/pointprocesses/lecture/pointprocessscetchA.eps @@ -1,7 +1,7 @@ %!PS-Adobe-2.0 EPSF-2.0 %%Title: pointprocessscetchA.tex %%Creator: gnuplot 4.6 patchlevel 4 -%%CreationDate: Tue Nov 3 17:29:16 2015 +%%CreationDate: Sat Nov 28 12:01:31 2015 %%DocumentFonts: %%BoundingBox: 50 50 373 135 %%EndComments @@ -430,10 +430,10 @@ SDict begin [ /Title (pointprocessscetchA.tex) /Subject (gnuplot plot) /Creator (gnuplot 4.6 patchlevel 4) - /Author (grewe) + /Author (jan) % /Producer (gnuplot) % /Keywords () - /CreationDate (Tue Nov 3 17:29:16 2015) + /CreationDate (Sat Nov 28 12:01:31 2015) /DOCINFO pdfmark end } ifelse diff --git a/pointprocesses/lecture/pointprocessscetchA.pdf b/pointprocesses/lecture/pointprocessscetchA.pdf index 8da5509..e77278a 100644 Binary files a/pointprocesses/lecture/pointprocessscetchA.pdf and b/pointprocesses/lecture/pointprocessscetchA.pdf differ diff --git a/pointprocesses/lecture/pointprocessscetchB.eps b/pointprocesses/lecture/pointprocessscetchB.eps index 81e21bf..e3199ee 100644 --- a/pointprocesses/lecture/pointprocessscetchB.eps +++ b/pointprocesses/lecture/pointprocessscetchB.eps @@ -1,7 +1,7 @@ %!PS-Adobe-2.0 EPSF-2.0 %%Title: pointprocessscetchB.tex %%Creator: gnuplot 4.6 patchlevel 4 -%%CreationDate: Tue Nov 3 18:24:39 2015 +%%CreationDate: Sat Nov 28 12:01:32 2015 %%DocumentFonts: %%BoundingBox: 50 50 373 237 %%EndComments @@ -430,10 +430,10 @@ SDict begin [ /Title (pointprocessscetchB.tex) /Subject (gnuplot plot) /Creator (gnuplot 4.6 patchlevel 4) - /Author (grewe) + /Author (jan) % /Producer (gnuplot) % /Keywords () - /CreationDate (Tue Nov 3 18:24:39 2015) + /CreationDate (Sat Nov 28 12:01:32 2015) /DOCINFO pdfmark end } ifelse diff --git a/pointprocesses/lecture/pointprocessscetchB.pdf b/pointprocesses/lecture/pointprocessscetchB.pdf index f2dac5e..12d3621 100644 Binary files a/pointprocesses/lecture/pointprocessscetchB.pdf and b/pointprocesses/lecture/pointprocessscetchB.pdf differ diff --git a/pointprocesses/lecture/rasterexamples.py b/pointprocesses/lecture/rasterexamples.py index c7c2433..9c66897 100644 --- a/pointprocesses/lecture/rasterexamples.py +++ b/pointprocesses/lecture/rasterexamples.py @@ -83,4 +83,4 @@ ax.eventplot(inhspikes, colors=[[0, 0, 0]], linelength=0.8) plt.tight_layout() plt.savefig('rasterexamples.pdf') -plt.show() +plt.close() diff --git a/pointprocesses/lecture/sta.py b/pointprocesses/lecture/sta.py index f41c06d..c5d702b 100644 --- a/pointprocesses/lecture/sta.py +++ b/pointprocesses/lecture/sta.py @@ -38,18 +38,22 @@ def reconstruct_stimulus(spike_times, sta, stimulus, t_max=30., dt=1e-4): def plot_results(sta_time, st_average, stim_time, s_est, stimulus, duration, dt): + plt.xkcd() sta_ax = plt.subplot2grid((1, 3), (0, 0), rowspan=1, colspan=1) stim_ax = plt.subplot2grid((1, 3), (0, 1), rowspan=1, colspan=2) fig = plt.gcf() - fig.set_size_inches(15, 5) - fig.subplots_adjust(left=0.075, bottom=0.12, top=0.92, right=0.975) + fig.set_size_inches(8, 3) + fig.subplots_adjust(left=0.08, bottom=0.15, top=0.9, right=0.975) fig.set_facecolor("white") - sta_ax.plot(sta_time * 1000, st_average, color="dodgerblue", lw=2.) - sta_ax.set_xlabel("time [ms]", fontsize=12) - sta_ax.set_ylabel("stimulus", fontsize=12) - sta_ax.set_xlim([-50, 50]) + sta_ax.plot(sta_time * 1000, st_average, color="#FF9900", lw=2.) + sta_ax.set_xlabel("Time (ms)") + sta_ax.set_ylabel("Stimulus") + sta_ax.set_xlim(-40, 20) + sta_ax.set_xticks(np.arange(-40, 21, 20)) + sta_ax.set_ylim(-0.1, 0.2) + sta_ax.set_yticks(np.arange(-0.1, 0.21, 0.1)) # sta_ax.xaxis.grid('off') sta_ax.spines["right"].set_visible(False) sta_ax.spines["top"].set_visible(False) @@ -58,22 +62,31 @@ def plot_results(sta_time, st_average, stim_time, s_est, stimulus, duration, dt) sta_ax.spines["bottom"].set_linewidth(2.0) sta_ax.spines["left"].set_linewidth(2.0) sta_ax.tick_params(direction="out", width=2.0) - ylim = sta_ax.get_ylim() xlim = sta_ax.get_xlim() - sta_ax.plot(list(xlim), [0., 0.], zorder=1, color='darkgray', ls='--', lw=0.75) - sta_ax.plot([0., 0.], list(ylim), zorder=1, color='darkgray', ls='--', lw=0.75) + sta_ax.plot(list(xlim), [0., 0.], zorder=1, color='darkgray', ls='--', lw=1) + sta_ax.plot([0., 0.], list(ylim), zorder=1, color='darkgray', ls='--', lw=1) sta_ax.set_xlim(list(xlim)) sta_ax.set_ylim(list(ylim)) - sta_ax.text(-0.225, 1.05, "A", transform=sta_ax.transAxes, size=14) + sta_ax.annotate('Time of\nspike', + xy=(0, 0.18), xycoords='data', + xytext=(-35, 0.19), textcoords='data', ha='left', + arrowprops=dict(arrowstyle="->", relpos=(1.0,0.5), + connectionstyle="angle3,angleA=0,angleB=-70") ) + sta_ax.annotate('STA', + xy=(-10, 0.05), xycoords='data', + xytext=(-33, 0.09), textcoords='data', ha='left', + arrowprops=dict(arrowstyle="->", relpos=(1.0,0.0), + connectionstyle="angle3,angleA=60,angleB=-40") ) + #sta_ax.text(-0.25, 1.04, "A", transform=sta_ax.transAxes, size=24) - stim_ax.plot(stim_time * 1000, stimulus[:,1], label='stimulus', color='dodgerblue', lw=2.) - stim_ax.plot(stim_time * 1000, s_est, label='reconstruction', color='red', lw=2) - stim_ax.set_xlabel('time[ms]', fontsize=12) - stim_ax.set_xlim([0.0, 250]) + stim_ax.plot(stim_time * 1000, stimulus[:,1], label='stimulus', color='#0000FF', lw=2.) + stim_ax.plot(stim_time * 1000, s_est, label='reconstruction', color='#FF9900', lw=2) + stim_ax.set_xlabel('Time (ms)') + stim_ax.set_xlim(0.0, 200) stim_ax.set_ylim([-1., 1.]) - stim_ax.legend() - stim_ax.plot([0.0, 250], [0., 0.], color="darkgray", lw=0.75, ls='--', zorder=1) + stim_ax.legend(loc=(0.3, 0.85), frameon=False, fontsize=12) + stim_ax.plot([0.0, 250], [0., 0.], color="darkgray", lw=1, ls='--', zorder=1) stim_ax.spines["right"].set_visible(False) stim_ax.spines["top"].set_visible(False) stim_ax.yaxis.set_ticks_position('left') @@ -81,8 +94,9 @@ def plot_results(sta_time, st_average, stim_time, s_est, stimulus, duration, dt) stim_ax.spines["bottom"].set_linewidth(2.0) stim_ax.spines["left"].set_linewidth(2.0) stim_ax.tick_params(direction="out", width=2.0) - stim_ax.text(-0.075, 1.05, "B", transform=stim_ax.transAxes, size=14) - + #stim_ax.text(-0.1, 1.04, "B", transform=stim_ax.transAxes, size=24) + + fig.tight_layout() fig.savefig("sta.pdf") plt.close() diff --git a/programming/code/facultyWhileLoop.m b/programming/code/facultyWhileLoop.m index 8f718d1..f75ff8f 100644 --- a/programming/code/facultyWhileLoop.m +++ b/programming/code/facultyWhileLoop.m @@ -3,5 +3,6 @@ counter = 1; x = 1; while counter <= n x = x * counter; + counter = counter + 1 end -fprintf('Faculty of %i is: %i\n', n, x) \ No newline at end of file +fprintf('Faculty of %i is: %i\n', n, x) diff --git a/programming/code/ifelse.m b/programming/code/ifelse.m index 94de3d6..1d689f4 100644 --- a/programming/code/ifelse.m +++ b/programming/code/ifelse.m @@ -3,18 +3,16 @@ if x < 0.5 disp('x is less than 0.5'); end - if x < 0.5 disp('x is less than 0.5!'); else disp('x is greater than or equal to 0.5!') end - if x < 0.5 disp('x is less than 0.5!'); elseif x < 0.75 disp('x is greater than 0.5 but less than 0.75!'); else disp('x is greater than or equal to 0.75!') -end \ No newline at end of file +end diff --git a/programming/code/logicalIndexingTime.m b/programming/code/logicalIndexingTime.m index 5135f2d..7bde023 100644 --- a/programming/code/logicalIndexingTime.m +++ b/programming/code/logicalIndexingTime.m @@ -1,12 +1,12 @@ t = 0:0.001:10; x = randn(size(t)); -selection = x (t > 5 & t < 6); +selection = x(t > 5 & t < 6); figure() hold on plot(t, x, 'displayname', 'measurements') plot(t(t > 5 & t < 6), selection, 'displayname', 'selection') -xlabel('time [s]') -ylabel('intensity') +xlabel('Time [s]') +ylabel('Intensity') legend 'show' -box 'off' \ No newline at end of file +box 'off' diff --git a/programming/code/logicalVector.out b/programming/code/logicalVector.out index 950933a..14b5afb 100644 --- a/programming/code/logicalVector.out +++ b/programming/code/logicalVector.out @@ -1,12 +1,10 @@ >> logicalVector Logischer Vektor y: - y = 1 1 1 1 0 0 0 0 0 0 Datentyp von y: logical Alle Elemente aus x, die kleiner als 5 sind: - ans = 1 2 3 4 diff --git a/programming/code/vectorsize.m b/programming/code/vectorsize.m index 716a943..6a464f3 100644 --- a/programming/code/vectorsize.m +++ b/programming/code/vectorsize.m @@ -1,14 +1,3 @@ -a = (11:20); % a vector with 10 Elements -fprintf('length of a: %i\n', length(a)) -size_of_a = size(a); % get the size and store it in a new variable - -% size_of_a is a vector itself -fprintf('number of dimensions (rank) of size_of_a: %i\n', length(size_of_a)) - -% get the value of the second element of size_of_a -fprintf('number of entries in the 2nd dimesion of a: %i\n', size_of_a(2)) - -%% Uebersichtliche Alternative? -s = size(a); % Speicher den Rueckgabewert von size() in einer Variablen -s(2) % Inhalt der zweiten Zahl, d.h. Laenge der 2. Dimension -size(a,2) % Kurze Alternative +s = size(a) % Speicher den Rueckgabewert von size() in einer Variablen +s(2) % Inhalt der zweiten Zahl, d.h. Laenge der 2. Dimension +size(a,2) % Die kurze Alternative diff --git a/programming/code/vectorsize.out b/programming/code/vectorsize.out index c848de2..429d61e 100644 --- a/programming/code/vectorsize.out +++ b/programming/code/vectorsize.out @@ -1,4 +1,3 @@ ->> vectorsize -length of a: 10 -number of dimensions (rank) of size_of_a: 2 -number of entries in the 2nd dimesion of a: 10 \ No newline at end of file +s = 1 10 +ans = 10 +ans = 10 diff --git a/programming/lecture/Makefile b/programming/lecture/Makefile index 379ae0e..41ff3c5 100644 --- a/programming/lecture/Makefile +++ b/programming/lecture/Makefile @@ -2,33 +2,13 @@ BASENAME=programming #TEXFILES=boolean_logical_indexing.tex control_structures.tex data_structures.tex plotting.tex programming_basics.tex scripts_functions.tex sta_stc.tex variables_datatypes.tex vectors_matrices.tex -PYFILES=$(wildcard *.py) -PYPDFFILES=$(PYFILES:.py=.pdf) - all : pdf -# script: -pdf : $(BASENAME)-chapter.pdf - -$(BASENAME)-chapter.pdf : $(BASENAME)-chapter.tex $(BASENAME).tex $(PYPDFFILES) ../../header.tex - CHAPTER=$$(( $$(sed -n -e '/contentsline {chapter}/{s/.*numberline {\([0123456789]*\)}.*/\1/; p}' $(BASENAME).aux) - 1 )); \ - PAGE=$$(sed -n -e '/contentsline {chapter}/{s/.*numberline {.*}.*}{\(.*\)}{chapter.*/\1/; p}' $(BASENAME).aux); \ - sed -i -e "s/setcounter{page}{.*}/setcounter{page}{$$PAGE}/; s/setcounter{chapter}{.*}/setcounter{chapter}{$$CHAPTER}/" $(BASENAME)-chapter.tex - pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex -interaction=scrollmode $< || true - -$(PYPDFFILES) : %.pdf : %.py - python $< +include ../../chapter.mk -clean : - rm -f *~ - rm -f $(BASENAME).aux $(BASENAME).log - rm -f $(BASENAME)-chapter.aux $(BASENAME)-chapter.log $(BASENAME)-chapter.out - rm -f $(PYPDFFILES) $(GPTTEXFILES) - -cleanall : clean - rm -f $(BASENAME)-chapter.pdf - -watchpdf : - while true; do ! make -q pdf && make pdf; sleep 0.5; done +# script: +pdf : chapter +clean : cleanchapter +cleanall : clean cleanchapter diff --git a/programming/lecture/programming-chapter.tex b/programming/lecture/programming-chapter.tex index 8eb19a1..4ace8b1 100644 --- a/programming/lecture/programming-chapter.tex +++ b/programming/lecture/programming-chapter.tex @@ -5,8 +5,10 @@ \lstset{inputpath=../code} \graphicspath{{images/}} -\setcounter{page}{15} -\setcounter{chapter}{0} +\typein[\pagenumber]{Number of first page} +\typein[\chapternumber]{Chapter number} +\setcounter{page}{\pagenumber} +\setcounter{chapter}{\chapternumber} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -14,5 +16,21 @@ \input{programming} +\section{TODO} +\begin{itemize} +\item Ausgabeformat: \varcode{format} ? +\item Boolescher Ausdruck: ist doch eigentlich boolescher Ausdruck! +\item Expliziter die \varcode{(a:b:c)} Notation einf\"uhren! +\item Mathematische Funktionen sin(), cos(), exp() +\item Rundungsfunktionen round(), floor(), ceil() +\item Zeitvektoren, deltat, Umrechnung Zeit und Index. +\item Matrizen erstmal 2-D und nur kurz n-D +\item Zusammenfassung von Fehlermeldungen bezueglich Matrizen und Vektoren +\item Random-walk behutsam mit einer Schleife, dann zwei Schleifen. Plus Bildchen. +\item Doppelte for-Schleife +\item File output and input (load, save, fprintf, scanf) (extra chapter?) +\item help() und doc() +\end{itemize} + \end{document} diff --git a/programming/lecture/programming.tex b/programming/lecture/programming.tex index df3dd6b..62b29fe 100644 --- a/programming/lecture/programming.tex +++ b/programming/lecture/programming.tex @@ -1,15 +1,16 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{\tr{Programming basics}{Programmierung in \matlab}} +\chapter{Programmierung in \matlab} \section{Variablen und Datentypen} \subsection{Variablen} -Eine Variable ist ein Zeiger auf eine Stelle im Speicher. Dieser -Zeiger hat einen Namen, den Variablennamen, und einen Datentyp -(Abbildung \ref{variablefig}). Im Speicher wird der Wert der Variablen -bin\"ar gespeichert. Wird auf den Wert der Variable zugegriffen, wird +Eine \determ{Variable} ist ein Zeiger auf eine Stelle im +Speicher. Dieser Zeiger hat einen Namen, den Variablennamen, und einen +\determ{Datentyp} (Abbildung \ref{variablefig}). Im Speicher wird der +Wert der Variablen bin\"ar als eine Folge von \determ[Bit]{Bits} (0 +oder 1) gespeichert. Wird auf den Wert der Variable zugegriffen, wird dieses Bitmuster je nach Datentyp interpretiert. Das Beispiel in Abbildung \ref{variablefig} zeigt, dass das gleiche Bitmuster im einen Fall als 8-Bit Integer Datentyp zur Zahl 38 interpretiert wird und im @@ -39,81 +40,107 @@ befassen. \subsection{Erzeugen von Variablen} In \matlab{} kann eine Variable auf der Kommandozeile, in einem Skript oder einer Funktion an beliebiger Stelle erzeugt werden. Listing -\ref{varListing1} zeigt zwei M\"oglichkeiten dies zu tun: -\begin{lstlisting}[label=varListing1, caption=Erzeugen von Variablen.] - >> y = [] - y = - [] - >> - >> x = 38 - x = - 38 +\ref{varListing1} zeigt drei Beispiele: +\begin{lstlisting}[label=varListing1, caption={Erzeugen von Variablen.}] +>> x = 38 +x = + 38 + +>> y = [] +y = + [] + +>> z = 'A' +z = + A \end{lstlisting} Die Zeile 1 kann etwa so gelesen werden:''Erzeuge eine Variable mit -dem Namen y und weise ihr einen leeren Wert zu''. Das +dem Namen \varcode{x} und weise ihr den Wert 38 zu''. Das Gleichheitszeichen ist der sogenannte -\codeterm{Zuweisungsoperator}. Zeile 5 definiert eine Variable x, der -nun der Zahlenwert 38 zugewiesen wird. Da \matlab{}, wenn nicht anders -angegeben, immer den ``double'' Datentypen benutzt, haben beide -Variablen diesen Datentyp. +\codeterm{Zuweisungsoperator}. Zeile 5 definiert eine Variable \varcode{y}, der +ein leerer Wert zugewiesen wird. Da \matlab{}, wenn nicht anders +angegeben, immer den \codeterm{double} Datentypen benutzt, haben beide +Variablen diesen Datentyp. In Zeile 9 wird der Variablen \varcode{z} der Buchstabe +``A'' zugewiesen. \varcode{z} ist nicht ein Flie{\ss}kommazahl von Typ \codeterm{double}, +sondern ein \codeterm{character} (Zeichen). + +Der Datentyp einer Variable kann mit \code{class()} abgefragt werden. +Eine Liste aller definierten Variablen gibt \code{who} +zur\"uck. Detailliertere Informationen \"uber Variablen zeigt +\code{whos} an. \begin{lstlisting}[label=varListing2, caption={Erfragen des Datentyps einer Variable, Listen aller definierten Variablen.}] - >>disp(class(x)) - double - >> - >> who % oder whos um mehr Information zu bekommen +>>class(x) +ans = + double + +>> who +Your variables are: + +x y z + +>> whos + Name Size Bytes Class Attributes + + x 1x1 8 double + y 0x0 0 double + z 1x1 2 char \end{lstlisting} \begin{important}[Namen von Variablen] Bei der Namensgebung ist zu beachten, dass \matlab{} auf Gro{\ss}- - und Kleinschreibung achtet und ein Variablennane mit einem - alphabetischen Zeichen beginnen muss. Des Weiteren sind Umlaute, - Sonder- und Leerzeichen in Variablennamen nicht erlaubt. + und Kleinschreibung achtet und ein Variablenname mit einem + alphabetischen Zeichen beginnen muss. Umlaute, Sonder- und + Leerzeichen sind in Variablennamen nicht erlaubt. \end{important} \subsection{Arbeiten mit Variablen} Nat\"urlich kann mit den Variablen auch gearbeitet, bzw. gerechnet -werden. \matlab{} kennt alle normalen arithmetischen Operatoren wie -\code{+}, \code{-}, \code{*} und \code{/}. Die Potenz wird \"uber das -Dachsymbol \code{\^} dargestellt. Listing \ref{varListing3} zeigt, wie sie -benutzt werden. - +werden. \matlab{} kennt alle normalen +\codeterm[Operator!arithmetischer]{arithmetischen Operatoren} wie +\code[Operator!arithmetischer!1add@+]{+}, +\code[Operator!arithmetischer!2sub@-]{-}, +\code[Operator!arithmetischer!3mul@*]{*} und +\code[Operator!arithmetischer!4div@/]{/}. Die Potenz wird \"uber das +Dachsymbol \code[Operator!arithmetischer!5pow@\^{}]{\^{}} +dargestellt. Listing \ref{varListing3} zeigt, wie sie benutzt werden. + +\pagebreak[4] \begin{lstlisting}[label=varListing3, caption={Rechnen mit Variablen.}] - >> x = 1; - >> x + 10 - ans = - 11 - >> - >> x % x wurde nicht veraendert - ans = - 1 - >> - >> y = 2; - >> - >> x + y - ans = - 3 - >> - >> z = x + y - z = - 3 - >> - >> z = z * 5; - >> z - z = - 15 - >> - >> clear z +>> x = 1; +>> x + 10 +ans = + 11 +>> x % x wurde nicht veraendert +ans = + 1 + +>> y = 2; +>> x + y +ans = + 3 + +>> z = x + y +z = + 3 + +>> z = z * 5; +>> z +z = + 15 + +>> clear z % loesche die Variable z \end{lstlisting} -Beachtenswert ist z.B. in Zeilen 3 und 6, dass mit dem Inhalt einer +Beachtenswert ist in Zeilen 2 und 6, dass mit dem Inhalt einer Variablen gerechnet werden kann, ohne dass dadurch ihr Wert ver\"andert wird. Wenn der Wert einer Variablen ver\"andert werden -soll, dann muss der Variable der neue Wert explizit zugewiesen werden -(mit dem \code{=} Zuweisungsoperator, z.B. Zeilen 16, 20). Zeile 25 -zeigt wie eine einzelne Variable gel\"oscht wird. +soll, dann muss der neue Wert explizit einer Variablen zugewiesen werden +(mit dem \code[Operator!Zuweisung!=]{=} Zuweisungsoperator, +z.B. Zeilen 14 und 18). Zeile 23 zeigt wie eine einzelne Variable +gel\"oscht wird. \subsection{Datentypen} @@ -121,30 +148,32 @@ zeigt wie eine einzelne Variable gel\"oscht wird. Der Datentyp bestimmt, wie die im Speicher abgelegten Bitmuster interpretiert werden. Die wichtigsten Datentpyen sind: \begin{itemize} -\item \codeterm{integer} - Ganze Zahlen. Hier gibt es mehrere +\item \codeterm{integer}: Ganze Zahlen. Hier gibt es mehrere Unterarten, die wir in \matlab{} (meist) ignorieren k\"onnen. -\item \codeterm{double} - Flie{\ss}kommazahlen. Im Gegensatz zu den reelen Zahlen, die durch diesen Datentyp dargestellt werden, sind sie abz\"ahlbar. -\item \codeterm{complex} - Komplexe Zahlen. -\item \codeterm{logical} - Boolesche Werte, die als wahr +\item \codeterm{double}: Flie{\ss}kommazahlen. Im Gegensatz zu den reelen Zahlen, die durch diesen Datentyp dargestellt werden, sind sie abz\"ahlbar. +\item \codeterm{complex}: Komplexe Zahlen. +\item \codeterm{logical}: Boolesche Werte, die als wahr (\code{true}) oder falsch (\code{false}) interpretiert werden. -\item \codeterm{char} - ASCII Zeichen +\item \codeterm{char}: ASCII Zeichen \end{itemize} Unter den numerischen Datentypen gibt es verschiedene Arten mit -unterschiedlichem Speicherbedarf und Wertebreich. +unterschiedlichem Speicherbedarf und Wertebreich (siehe +Tabelle~\ref{dtypestab}). -\begin{table}[!h] +\begin{table}[t] \centering \titlecaption{Grundlegende numerische Datentypen und ihr Wertebereich.}{} \label{dtypestab} \begin{tabular}{llcl}\hline - Datentyp & Speicherbedarf & Wertebereich & Beispiel \rule{0pt}{2.5ex} \\ \hline - double & 64 bit & $\approx -10^{308}$ bis $\approx 10^{308} $& Flie{\ss}kommazahlen.\rule{0pt}{2.5ex}\\ - int & 64 bit & $-2^{31}$ bis $2^{31}-1$ & Ganzzahlige Werte \\ - int16 & 16 bit & $-2^{15}$ bis $2^{15}-1$ & Digitalisierte Spannungen. \\ - uint8 & 8 bit & $0$ bis $255$ & Digitalisierte Imaging Daten. \\ \hline + Datentyp & Speicherbedarf & Wertebereich & Beispiel \erh \\ \hline + \code{double} & 64 bit & $\approx -10^{308}$ bis $\approx 10^{308} $& Flie{\ss}kommazahlen.\erb\\ + \code{int} & 64 bit & $-2^{31}$ bis $2^{31}-1$ & Ganzzahlige Werte \\ + \code{int16} & 16 bit & $-2^{15}$ bis $2^{15}-1$ & Digitalisierte Spannungen. \\ + \code{uint8} & 8 bit & $0$ bis $255$ & Digitalisierte Imaging Daten. \\ \hline \end{tabular} \end{table} -\matlab{} arbeitet meist mit dem ``double'' Datentyp wenn numerische + +\matlab{} arbeitet meist mit dem \codeterm{double} Datentyp wenn numerische Daten gespeichert werden. Dennoch lohnt es sich, sich ein wenig mit den Datentypen auseinanderzusetzen (Box \ref{daqbox}). @@ -175,8 +204,8 @@ den Datentypen auseinanderzusetzen (Box \ref{daqbox}). \end{minipage}\vspace{0.25cm} Um Speicherplatz zu sparen ist es sinnvoll, die gemessenen Daten als - ``int16'' anstelle der ``double'' Werte im Rechner abzulegen. Die - Daten als ``echte'' Spannungen, also als Flie{\ss}kommawerte, + \code{int16} anstelle der \code{double} Werte im Rechner abzulegen. Die + Daten als Spannungswerte, also als Flie{\ss}kommawerte, abzulegen ben\"otigt den 4-fachen Speicherplatz (8 statt 2 Bytes) und bietet keine zus\"atzliche Information. \end{ibox} @@ -199,7 +228,7 @@ Dimension die Gr\"o{\ss}e 1 hat. Im Gegensatz zu Variablen, die einzelene Werte beinhalten (Skalare), kann ein Vektor mehrere Werte des gleichen Datentyps -beinhalten (Abbildung \ref{vectorfig} B). Die Variable \code{a} +beinhalten (Abbildung \ref{vectorfig} B). Die Variable \varcode{a} enth\"alt im Beispiel in Abbildung \ref{vectorfig} vier ganzzahlige Werte. \begin{figure} @@ -211,61 +240,67 @@ enth\"alt im Beispiel in Abbildung \ref{vectorfig} vier ganzzahlige Werte. (columnvector).}\label{vectorfig} \end{figure} -Das folgende Listing \ref{arrayListing1} zeigt, wie einfache Vektoren erstellt werden -k\"onnen. - -\begin{lstlisting}[label=arrayListing1, caption={Erstellen einfacher Zeilenvektoren.}] - >> a = [0 1 2 3 4 5 6 7 8 9] % Erstellen eines Zeilenvektors - a = - 0 1 2 3 4 5 6 7 8 9 - >> - >> b = (0:9) % etwas bequemer - b = - 0 1 2 3 4 5 6 7 8 9 - >> - >> c = (0:2:10) - c = - 0 2 4 6 8 10 +Das folgende Listing \ref{generatevectorslisting} zeigt, wie Vektoren erstellt +werden k\"onnen. + +\begin{lstlisting}[label=generatevectorslisting, caption={Erstellen einfacher Zeilenvektoren.}] +>> a = [0 1 2 3 4 5 6 7 8 9] % Erstellen eines Zeilenvektors +a = + 0 1 2 3 4 5 6 7 8 9 + +>> b = (0:9) % etwas bequemer +b = + 0 1 2 3 4 5 6 7 8 9 + +>> c = (0:2:10) +c = + 0 2 4 6 8 10 \end{lstlisting} Die L\"ange eines Vektors, d.h. die Anzahl der Elemente des Vektors, -kann mithilfe der Funktionen \code{length()} und \code{numel} bestimmt -werden. \"Ahnliche Information kann \"uber die Funktion \code{size()} -erhalten werden (Listing \ref{arrayListing2}). Im Falle des Vektors -\code{a} von oben erh\"alt man folgende Ausgabe: - -\begin{lstlisting}[label=arrayListing2, caption={Gr\"o{\ss}e von Vektoren.}] - >> length(a) - ans = - 10 - >> size(a) - ans = - 1 10 +kann mithilfe der Funktionen \code{length()} und \code{numel()} +bestimmt werden. \"Ahnliche Information kann \"uber die Funktion +\code{size()} erhalten werden (Listing \ref{vectorsizeslisting}). Der +Vektor \varcode{a} von oben hat folgende Gr\"o{\ss}en: + +\begin{lstlisting}[label=vectorsizeslisting, caption={Gr\"o{\ss}e von Vektoren.}] +>> length(a) +ans = + 10 +>> size(a) +ans = + 1 10 \end{lstlisting} -Diese Ausgabe zeigt, dass Vektoren im Grunde 2-dimensional sind. Bei -einem Zeilenvektor hat die erste Dimension die Gr\"o{\ss}e -1. \code{length(a)} gibt die l\"angste Ausdehnung an. Der \code{'}- -Operator transponiert den Spaltenvektor zu einem Zeilenvektor (Zeilen 14 ff.). - - -\begin{lstlisting}[label=arrayListing3, caption={Spaltenvektoren.}] - >> b = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] % Erstellen eines Spaltenvektors - b = - 1 - 2 - ... - 9 - 10 - >> length(b) - ans = - 10 - >> size(b) - ans = - 10 1 - >> b = b'; % Transponieren - >> size(b) - ans = - 1 10 +Die Ausgabe der \code{size()}-Funktion zeigt, dass Vektoren im Grunde +2-dimensional sind. Bei einem Zeilenvektor hat die erste Dimension die +Gr\"o{\ss}e 1. \code[length()]{length(a)} gibt die l\"angste +Ausdehnung an. Im folgenden Listing \ref{columnvectorlisting} transponiert der +\code[Operator!Matrix!']{'} - Operator einen Spaltenvektor +zu einem Zeilenvektor (Zeilen 14 ff.). + +\begin{lstlisting}[label=columnvectorlisting, caption={Spaltenvektoren.}] +>> b = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] % Erstellen eines Spaltenvektors +b = + 1 + 2 + ... + 9 + 10 + +>> length(b) +ans = + 10 +>> size(b) +ans = + 10 1 + +>> b = b' % Transponieren +b = + 1 2 3 4 5 6 7 8 9 10 + +>> size(b) +ans = + 1 10 \end{lstlisting} @@ -273,7 +308,8 @@ Operator transponiert den Spaltenvektor zu einem Zeilenvektor (Zeilen 14 ff.). \begin{figure} \includegraphics[width=0.4\columnwidth]{arrayIndexing} \titlecaption{Indices von Vektoren.}{Jedes Feld eines Vektors hat - einen Index mit dem auf den jeweiligen Inhalt zugegriffen werden + einen Index (kleine Zahl) mit dem auf den jeweiligen Inhalt + (gro{\ss}e Zahl) zugegriffen werden kann.}\label{vectorindexingfig} \end{figure} @@ -282,156 +318,243 @@ Der Zugriff auf die Inhalte eines Vektors erfolgt \"uber den Index einen fortlaufenden \codeterm{Index}, \"uber den auf die Werte des Vektors zugegriffen werden kann. Dabei spielt es keine Rolle, ob es sich um einen Zeilen- oder Spaltenvektor handelt. + \begin{important}[Indizieren] - Anders als viele andere Programmiersprachen beginnt \matlab{} mit - dem Index 1 an zu z\"ahlen. Der Zugriff auf Inhalte eines Vektors - mittels seines Indexes wird Indizieren genannnt. + Der Zugriff auf Inhalte eines Vektors mittels seines Indexes wird + Indizieren genannnt. + + Der Index des ersten Elements eines Vektors ist in \matlab{} die Eins. + + Der Index des letzten Elements entspricht der L\"ange des Vektors. \end{important} -Die Listings \ref{arrayListing4} und \ref{arrayListing5} zeigen wie + +Die Listings \ref{vectorelementslisting} und \ref{vectorrangelisting} zeigen wie mit Indexen auf die Inhalte eines Vektors zugegriffen werden kann. +Hierbei kann auf einzelne Werte zugegriffen werden oder, analog zur +Erzeugung von Vektoren, die \code[Operator!Matrix!:]{:} Notation +verwendet werden, um auf mehrere Element gleichzeitig zuzugreifen. -\begin{lstlisting}[label=arrayListing4, caption={Zugriff auf den Inhalt von Vektoren I}] - >> a = (11:20); - >> a(1) % das 1. Element - ans = - 11 - >> a(5) % das 5. Element - ans = - 15 - >> a(end) % das letzte Element - ans = - 20 +\begin{lstlisting}[label=vectorelementslisting, caption={Zugriff auf den Inhalt von Vektoren: einzelne Elemente}] +>> a = (11:20) +a = + 11 12 13 14 15 16 17 18 19 20 + +>> a(1) % das 1. Element +ans = 11 + +>> a(5) % das 5. Element +ans = 15 + +>> a(end) % das letzte Element +ans = 20 \end{lstlisting} -Hierbei kann auf einzelne Werte zugegriffen werden oder, analog zur -Erzeugung von Vektoren, die \code{:} Notation verwendet werden, um auf mehrere -Element gleichzeitig zuzugreifen. - -\begin{lstlisting}[caption={Zugriff auf den Inhalt von Vektoren I}, label=arrayListing5] - >> a([1 3 5]) % das 1., 3. und 5. Element - ans = - 11 13 15 - >> a(2:4) % alle Elemente von Index 2 bis einschliesslich 4 - ans = - 12 13 14 - >> a(1:2:end) % jedes zweite Element - ans = - 11 13 15 17 19 - >> a(:) % alle Elemente - ans = - 11 12 13 14 15 16 17 18 19 20 +\begin{lstlisting}[caption={Zugriff auf den Inhalt von Vektoren: Bereiche}, label=vectorrangelisting] +>> a([1 3 5]) % das 1., 3. und 5. Element +ans = + 11 13 15 + +>> a(2:4) % alle Elemente von Index 2 bis einschliesslich 4 +ans = + 12 13 14 + +>> a(1:2:end) % jedes zweite Element +ans = + 11 13 15 17 19 + +>> a(:) % alle Elemente als Zeilenvektor +ans = + 11 12 13 14 15 16 17 18 19 20 \end{lstlisting} \begin{exercise}{vectorsize.m}{vectorsize.out} - Der R\"uckgabewert von \code{size(a)} ist wieder ein Vektor der - L\"ange 2. Wie k\"onnte man also die Gr\"o{\ss}e von \code{a} in der - zweiten Dimension herausfinden? + Der R\"uckgabewert von \code[size()]{size(a)} ist wieder ein Vektor der + L\"ange 2. Wie k\"onnte also die Gr\"o{\ss}e von \varcode{a} in der + zweiten Dimension herausgefunden werden? \end{exercise} \subsubsection{Operationen auf Vektoren} Mit Vektoren kann sehr einfach gerechnet werden. Listing -\ref{arrayListing6} zeigt Rechnungen mit Vektoren. - -\begin{lstlisting}[caption={Rechnen mit Vektoren.},label=arrayListing6] - >> a = (0:2:8); - >> a + 5 % addiere einen Skalar - ans = - 5 7 9 11 13 - - >> a - 5 % subtrahiere einen Skalar - ans = - -5 -3 -1 1 3 - - >> a .* 2 % Multiplikation - ans = - 0 4 8 12 16 - - >> a ./ 2 % Division - ans = - 0 1 2 3 4 - - >> a(1:3) + a(2:4) % Addieren von 2 Vektoren - ans = - 2 6 10 - >> - >> a(1:2) + a(2:4) % Vektoren muessen gleich gross sein! - ??? Error using ==> plus - Matrix dimensions must agree. +\ref{vectorscalarlisting} zeigt die Verrechnung von Vektoren mit Skalaren +mit den Operatoren \code[Operator!arithmetischer!1add@+]{+}, +\code[Operator!arithmetischer!2sub@-]{-}, +\code[Operator!arithmetischer!3mul@*]{*}, +\code[Operator!arithmetischer!4div@/]{/} +\code[Operator!arithmetischer!5pow@.\^{}]{.\^}. + +\begin{lstlisting}[caption={Rechnen mit Vektoren und Skalaren.},label=vectorscalarlisting] +>> a = (0:2:8) +a = + 0 2 4 6 8 + +>> a + 5 % Addition von einem Skalar +ans = + 5 7 9 11 13 + +>> a - 5 % Subtraktion von einem Skalar +ans = + -5 -3 -1 1 3 + +>> a * 2 % Multiplikation mit einem Skalar +ans = + 0 4 8 12 16 + +>> a / 2 % Division mit einem Skalar +ans = + 0 1 2 3 4 + +>> a .^ 2 % Potenzierung mit einem Skalar +ans = + 0 4 16 36 64 +\end{lstlisting} + +Bei der elementweisen Verrechnung von zwei Vektoren muss +sichergestellt werden, dass sie die gleiche L\"ange und das gleiche +Layout (Spalten- oder Zeilenvektor) haben. Addition und Subtraktion +erfolgt immer elementweise (Listing~\ref{vectoradditionlisting}). + +\begin{lstlisting}[caption={Elementweise Addition und Subtraktion von + Vektoren.},label=vectoradditionlisting] +>> a = [4 9 12]; +>> b = [4 3 2]; +>> a + b % Addition von 2 Vektoren +ans = + 8 12 14 + +>> a - b % Subtraktion von 2 Vektoren +ans = + 0 6 10 + +>> c = [8 4]; +>> a + c % Beide Vektoren muessen gleich gross sein! +Error using + +Matrix dimensions must agree. +>> d = [8; 4; 2]; +>> a + d % Beide Vektoren muessen das gleiche Layout haben! +Error using + +Matrix dimensions must agree. +\end{lstlisting} + +Bei der Multiplikation, der Division und der Potenzierung mu{\ss} mit +vorangestellem '.' angezeigt werden, dass es sich um eine +\emph{elementweise} Verarbeitung handeln soll. F\"ur diese +elementweisen Operationen kennt \matlab{} die Operatoren +\code[Operator!arithmetischer!3mule@.*]{.*}, +\code[Operator!arithmetischer!4dive@./]{./} und +\code[Operator!arithmetischer!5powe@.\^{}]{.\^{}} +(Listing~\ref{vectorelemmultiplicationlisting}). + +\begin{lstlisting}[caption={Elementweise Multiplikation, Division und + Potenzierung von Vektoren.},label=vectorelemmultiplicationlisting] +>> a .* b % Elementweise Multiplikation +ans = + 16 27 24 + +>> a ./ b % Elementweise Division +ans = + 1 3 6 + +>> a ./ b % Elementweise Potenzierung +ans = + 256 729 144 + +>> a .* c % Beide Vektoren muessen gleich gross sein! +Error using .* +Matrix dimensions must agree. +>> a .* d % Beide Vektoren muessen das gleiche Layout haben! +Error using .* +Matrix dimensions must agree. \end{lstlisting} -Wird ein Vektor mit einem skalaren Wert verrechnet, dann ist das -problemlos m\"oglich. Bei der Multiplikation (Zeile 10), der Division -(Zeile 14) und auch der Potenzierung mu{\ss} mit vorangestellem '.' -klar gemacht werden, dass es sich um eine \emph{elementweise} -Verarbeitung handeln soll. F\"ur diese elementweisen Operationen kennt -\matlab{} die Operatoren \code{.*}, \code{./} und \code{.\^}. Die -einfachen Operatoren \code{*}, \code{/} und \code{\^} sind mit den -entsprechenden Matrixoperationen aus der linearen Algebrar belegt -(Box \ref{matrixmultiplication}). - -Zu Beachten ist des Weiteren noch die Fehlermeldung am Schluss von -Listing \ref{arrayListing6}. Wenn zwei Vektoren (elementweise) -miteinander verrechnet werden sollen, muss nicht nur die Anzahl der Elemente -\"ubereinstimmen, sondern es muss auch das Layout (Zeilen- oder -Spaltenvektoren) \"ubereinstimmen. - - -Will man Elemente aus einem Vektor entfernen, dann weist man den -entsprechenden Zellen einen leeren Wert (\code{[]}) zu. - -\begin{lstlisting}[label=arrayListing7, caption={L\"oschen von Elementen aus einem Vektor.}] - >> a = (0:2:8); - >> length(a) - ans = - 5 - - >> a(1) = [] % loesche das erste Element - a = 2 4 6 8 - - >> a([1 3]) = [] - a = 4 8 - - >> length(a) - ans = - 2 +Die einfachen Operatoren \code[Operator!arithmetischer!3mul@*]{*}, +\code[Operator!arithmetischer!4div@/]{/} und +\code[Operator!arithmetischer!5pow@\^{}]{\^{}} sind mit den +entsprechenden Matrixoperationen aus der linearen Algebrar belegt (Box +\ref{matrixmultiplication}). Insbesondere ist die Multiplikation eines +Zeilenvektors $\vec a$ mit einem Spaltenvektor $\vec b$ das Skalarprodukt +$\sum_i = a_i b_i$. + +\begin{lstlisting}[caption={Multiplikation von Vektoren.},label=vectormultiplicationlisting] +>> a * b % Multiplikation zweier Zeilenvektoren +Error using * +Inner matrix dimensions must agree. +>> a' * b' % Multiplikation zweier Spaltenvektoren +Error using * +Inner matrix dimensions must agree. + +>> a * b' % Multiplikation Zeilenvektor mit Spaltenvektor +ans = + 67 + +>> a' * b % Multiplikation Spaltenvektor mit Zeilenvektor +ans = + 16 12 8 + 36 27 18 + 48 36 24 +\end{lstlisting} + +\pagebreak[4] +Zum Entfernen von Elementen aus einem Vektor, wird den +entsprechenden Zellen ein leeren Wert (\code[Operator!Matrix!{[]}]{[]}) zugewiesen: +\begin{lstlisting}[label=vectoreraselisting, caption={L\"oschen von Elementen aus einem Vektor.}] +>> a = (0:2:8); +>> length(a) +ans = 5 + +>> a(1) = [] % loesche das erste Element +a = 2 4 6 8 + +>> a([1 3]) = [] % loesche das erste und dritte Element +a = 4 8 + +>> length(a) +ans = 2 \end{lstlisting} Neben dem L\"oschen von Vektorinhalten k\"onnen Vektoren auch -erweitert oder zusammengesetzt werden. Auch hier muss das Layout der Vektoren -\"ubereinstimmen (Listing \ref{arrayListing8}, Zeile 12). Will man -einen Vektor erweitern, kann man \"uber das Ende hinaus -zuweisen. \matlab{} erweitert dann die Variable. Dieser Vorgang ist -``rechenintensiv'' und sollte, soweit m\"oglich, vermieden werden. - -\begin{lstlisting}[caption={Zusammenf\"ugen und Erweitern von Vektoren.}, label=arrayListing8] - >> a = (0:2:8); - >> b = (10:2:19); - >> c = [a b] % erstelle einen Vektor aus einer Liste von Vektoren - c = - 0 2 4 6 8 10 12 14 16 18 - >> length(c) - ans = - 10 - >> length(a) + length(b) - ans = - 10 - >> c = [a b']; - Error using horzcat - Dimensions of matrices being concatenated are not consistent. - - >> b(6:8) = [1 2 3 4]; - In an assignment A(:) = B, the number of elements in A and B must be the same. +erweitert oder zusammengesetzt werden. Auch hier muss das Layout der +Vektoren \"ubereinstimmen (Listing \ref{vectorinsertlisting}, Zeile +10). Zum Erweitern eines Vektors kann \"uber das Ende hinaus +zugewiesen werden (Zeile 20). \matlab{} erweitert dann die Variable +entsprechend. Dieser Vorgang ist rechenintensiv da der ganze Vektor +an eine neue Stelle im Arbeitsspeicher kopiert wird und sollte, soweit +m\"oglich, vermieden werden. + +\begin{lstlisting}[caption={Zusammenf\"ugen und Erweitern von Vektoren.}, label=vectorinsertlisting] +>> a = [4 3 2 1]; +>> b = [10 12 14 16]; +>> c = [a b] % erstelle einen Vektor aus einer Liste von Vektoren +c = + 4 3 2 1 10 12 14 16 +>> length(c) +ans = 8 +>> length(a) + length(b) +ans = 8 + +>> c = [a b']; % Vektorlayout muss uebereinstimmen +Error using horzcat +Dimensions of matrices being concatenated are not consistent. + +>> a(1:3) = [5 6 7] % Weise den ersten drei Elementen neue Werte zu +a = + 5 6 7 1 +>> a(1:3) = [1 2 3 4]; % Laenge der Vektoren muss uebereinstimmen +In an assignment A(I) = B, the number of elements in B and I must be the same. + +>> a(3:6) = [1 2 3 4] % Zuweisung ueber die Laenge des Vektors hinweg +a = + 5 6 1 2 3 4 \end{lstlisting} \subsection{Matrizen} -Im Gegesatz zu den 1-dimensionalen Vektoren k\"onnen Martizen -n-dimensional sein, das hei{\ss}t, dass sie beliebig viele Dimensionen -haben k\"onnen. Von praktischer Bedeutung sind allerdings nur Matrizen -mit bis zu vier Dimensionen. Meist beschr\"ankt es sich jedoch auf 2- -bis 3-d Matrizen (Abbildung \ref{matrixfig} A,B). +Vektoren sind 1-dimensionale Spezialf\"alle von $n$-dimensionalen +Matrizen. Matrizen k\"onnen in \matlab{} beliebig viele Dimensionen +haben. Von praktischer Bedeutung sind allerdings nur Matrizen mit bis +zu vier Dimensionen. Meist beschr\"ankt es sich jedoch auf 2- bis 3-d +Matrizen (Abbildung \ref{matrixfig} A,B). \begin{figure} \includegraphics[width=0.5\columnwidth]{matrices} @@ -443,41 +566,38 @@ bis 3-d Matrizen (Abbildung \ref{matrixfig} A,B). Erzeugt werden Matrizen sehr \"ahnlich zu den Vektoren (Listing \ref{matrixListing}). Die Definition einer Matrize wird, wie beim -Vektor, durch \code{[]} eingeschlossen. Das \code{;} trennt die -einzelnen Zeilen der Matrize. +Vektor, durch \code[Operator!Matrix!{[]}]{[]} eingeschlossen. Das +Semikolon \code[Operator!Matrix!;]{;} trennt die einzelnen Zeilen der +Matrize. \begin{lstlisting}[label=matrixListing, caption={Erzeugen von Matrizen.}] - >> a = [1 2 3; 4 5 6; 7 8 9] - >> a = - 1 2 3 - 4 5 6 - 7 8 9 - >> - >> b = ones(3,3,2); - >> b - - b(:,:,1) = - 1 1 1 - 1 1 1 - 1 1 1 - - b(:,:,2) = - 1 1 1 - 1 1 1 - 1 1 1 +>> a = [1 2 3; 4 5 6; 7 8 9] +>> a = +1 2 3 +4 5 6 +7 8 9 + +>> b = ones(3, 4, 2) +b(:,:,1) = + 1 1 1 1 + 1 1 1 1 + 1 1 1 1 +b(:,:,2) = + 1 1 1 1 + 1 1 1 1 + 1 1 1 1 \end{lstlisting} Zur Defintion von mehr-dimensionalen Matrizen ist die Notation in Zeile 1 nicht geeignet. Es gibt allerdings eine Reihe von -Helferfunktionen, die n-dimensionale Matrizen erstellen k\"onnen -(z.B. \code{ones}, Zeile 7). Sollte sich die Notwendigkeit ergeben -mehrdimensionale Matrizen zusammenzuf\"ugen hilft die \code{cat} -Funktion. +Helferfunktionen, die $n$-dimensionale Matrizen erstellen k\"onnen +(z.B. \code{ones()}, Zeile 7). Die \code{cat()}-Funktion kann +mehrdimensionale Matrizen zusammenzuf\"ugen. Um Informationen \"uber die Gr\"o{\ss}e einer Matrize zu bekommen ist -die Funktion \code{length} nicht geeignet. Wie oben erw\"ahnt gibt sie -die Gr\"o{\ss}e der l\"angsten Dimension aus. Wann immer es um -Matrizen geht, wird \code{size} benutzt. +die Funktion \code{length()} nicht geeignet. Wie oben erw\"ahnt gibt sie +die Gr\"o{\ss}e der l\"angsten Dimension aus. Die \code{size()}-Funktion +gibt dagegen die L\"ange jeder Dimension als Vektor zur\"uck. \begin{figure} \includegraphics[width=0.9\columnwidth]{matrixIndexing} @@ -495,40 +615,46 @@ Der Zugriff auf Inhalte von Matrizen erfolgt \"uber den Index Koordinatensystem wird jede Zelle einer Matrize mit einem Index angesprochen, der aus $n$ Zahlen besteht wobei $n$ die Dimensionalit\"at der Matrize ist. Diese Art des Zugriffs wird -\codeterm{subscript indexing} genannt. +\codeterm{subscript indexing} genannt. Dabei bestimmt die errste Zahl +die Zeilennumer, die zweite die Splatennumer. \begin{lstlisting}[caption={Zugriff auf Inhalte von Matrizen, Indizierung.}, label=matrixIndexing] - >> x = randi(100, [3, 4, 5]); % 3-D Matrix mit Zufallszahlen - >> size(x) - ans = - 3 4 5 - >> x(1,1,1); % obere linke Ecke - ans(1,1,1) = - 14 - >> - >> x(1,1,:) % obere linke Ecke entlang der 3. Dimension - ans(1,1,:) = - 14 - ans(:,:,2) = - 58 - ans(:,:,3) = - 4 - ans(:,:,4) = - 93 - ans(:,:,5) = - 56 +>> x=rand(3,4) % 2-D Matrix mit Zufallszahlen mit 3 Zeilen und 4 Spalten +x = + 0.8147 0.9134 0.2785 0.9649 + 0.9058 0.6324 0.5469 0.1576 + 0.1270 0.0975 0.9575 0.9706 +>> size(x) +ans = + 3 4 + +>> x(1,1) % obere linke Ecke +ans = + 0.8147 +>> x(2,3) % Element der 2. Zeile, 3. Spalte +ans = + 0.5469 + +>> x(1,:) % erste Zeile +ans = + 0.8147 0.9134 0.2785 0.9649 +>> x(:,2) % zweite Spalte +ans = + 0.9134 + 0.6324 + 0.0975 \end{lstlisting} Alternativ zum \codeterm{subscript indexing} k\"onnen die Zellen einer Matrize auch \emph{linear} angesprochen werden (Abbildung \ref{matrixlinearindexingfig}). Diese Art der Adressierung ist nicht -so intuitiv verst\"andlich, kann aber sehr hilfreich sein. Der -``linare'' Index einer Zelle reicht von 1 bis \code{numel(M)} -Elemente. Wobei dieser erst entlang der 1. Dimension, dann der 2., -3. etc. Dimension ansteigt. Listing \ref{matrixLinearIndexing} zeigt -ein Beispiel f\"ur den Einsatz des linearen Indizierens z.B. wenn man -den Minimalwert aller Elemente einer Matrize ermitteln m\"ochte. +so intuitiv verst\"andlich, kann aber sehr hilfreich sein. Der lineare +Index einer Zelle reicht von 1 bis \code{numel()} Elemente. Wobei +dieser erst entlang der 1. Dimension, dann der 2., 3. etc. Dimension +ansteigt. Listing \ref{matrixLinearIndexing} zeigt ein Beispiel f\"ur +den Einsatz des linearen Indizierens, z.B. zum Ermitteln des kleinsten +Wertes in einer Matrize. \begin{figure} \includegraphics[width=0.9\columnwidth]{matrixLinearIndexing} @@ -539,302 +665,304 @@ den Minimalwert aller Elemente einer Matrize ermitteln m\"ochte. \end{figure} \begin{lstlisting}[label=matrixLinearIndexing, caption={Lineares Indizieren in Matrizen.}] - >> x = randi(100, [3, 4, 5]); % 3-D Matrix mit Zufallszahlen - >> size(x) - ans = - 3 4 5 - >> numel(x) - ans = - 60 - >> min(min(min(x))) % Minumum uber die Zeilen, Spalten, Blaetter... - ans = - 4 - >> min(x(:)) % oder so - ans = - 4 -\end{lstlisting} - - -Beim Rechnen mit Matrizen gelten die gleichen Regeln wie bei -Vektoren. Matrizen k\"onnen solange elementweise miteinander -verrechnet werden, wie die Dimensionalit\"aten -\"ubereinstimmen. Besondere Vorsicht sollte man immer dann walten -lassen, wenn man Matrizen miteinander multiplizieren, dividieren oder -potenzieren will. Hier ist es wichtig sich klarzumachen was man will: -Eine elementweise Multiplikation (\code{.*} Operator, Listing -\ref{matrixOperations} Zeile 18) oder ob eine Matrixmultiplikation -(\code{*} Operator, Listing \ref{matrixOperations} Zeile 12, Box -\ref{matrixmultiplication}) durchgef\"uhrt werden soll. - -\begin{lstlisting}[label=matrixOperations, caption={Zwei Arten von Multiplikationen auf Matrizen.}] - >> A = randi(10, [3, 3]) % 2-D Matrix - A = - 3 8 2 - 2 10 3 - 10 7 1 - >> B = randi(10, [3, 3]) % dto - B = - 2 1 7 - 1 5 9 - 5 10 5 - >> - >> A * B % Matrixmultiplikation - ans = - 24 63 103 - 29 82 119 - 32 55 138 - >> - >> A .* B % Elementweise Multiplikation - ans = - 6 8 14 - 2 50 27 - 50 70 5 +>> x = randi(100, [3, 4, 5]); % 3-D Matrix mit Zufallszahlen +>> size(x) +ans = +3 4 5 +>> numel(x) +ans = +60 +>> min(min(min(x))) % Minimum ueber die Zeilen, Spalten, Blaetter... +ans = +4 +>> min(x(:)) % oder so +ans = +4 \end{lstlisting} \begin{ibox}[t]{\label{matrixmultiplication} Matrixmultiplikation.} Die Matrixmuliplikation aus der linearen Algebra ist nicht eine - elementweise Multiplikation. Die Matrixmultiplikation ist nur - dann m\"oglich, wenn die Anzahl Spalten der ersten Matrize gleich - der Anzahl Zeilen in der zweiten Matrize ist. Formaler: zwei - Matrizen A, B k\"onnen mulipiziert $(A \cdot B)$ werden, wenn A die - Gr\"o{\ss}e $(m \times n)$ und B die Gr\"o{\ss}e $(n \times k)$ - hat. Die Mulitplikation ist m\"oglich wenn die ``inneren'' - Dimensionen $n$ gleich sind. Daraus - erkl\"art sich auch die folgende Fehlermeldung in \matlab{}: - \begin{lstlisting}[caption={Fehlermeldung bei Matrixmultiplikation}] ->> A = [1 2 3; 4 5 6]; ->> B = [2 4; 6 7]; ->> A * B -Error using * -Inner matrix dimensions must agree. ->> size(A) -ans = - 2 3 ->> size(B) -ans = - 2 2 - \end{lstlisting} + elementweise Multiplikation. Die Matrixmultiplikation ist nur dann + m\"oglich, wenn die Anzahl Spalten der ersten Matrize gleich der + Anzahl Zeilen in der zweiten Matrize ist. Formaler: zwei Matrizen + $\mathbf{A}$ und $\mathbf{B}$ k\"onnen mulipiziert $(\mathbf{A} + \cdot \mathbf{B})$ werden, wenn $\mathbf{A}$ die Gr\"o{\ss}e $(m \times n)$ und + $\mathbf{B}$ die Gr\"o{\ss}e $(n \times k)$ hat. Die Mulitplikation ist + m\"oglich wenn die \determ{inneren Dimensionen} $n$ gleich sind. + + Dann sind die Elemente $c_{i,j}$ des Matrixprodukts $\mathbf{C} = + \mathbf{A} \cdot \mathbf{B}$ gegeben durch das Skalarprodukt jeder + Zeile von $\mathbf{A}$ mit jeder Spalte aus $\mathbf{B}$: + \[ c_{i,j} = \sum_{k=1}^n a_{i,k} \; b_{k,j} \; . \] + + Die Matrixmultiplikation ist im Allgemeinen auch nicht kommutativ: + \[ \mathbf{A} \cdot \mathbf{B} \ne \mathbf{B} \cdot \mathbf{A} \; . \] Als Beispiel betrachten wir die beiden Matrizen - \[A_{(3 \times 2)} = \begin{pmatrix} 1 & 2 \\ 5 & 4 \\ -2 & 3 \end{pmatrix} - \quad \text{und} \quad - B_{(2 \times 2)} = \begin{pmatrix} -1 & 2 \\ -2 & 5 \end{pmatrix} \; . \] - Die ``inneren'' Dimensionen der Matrizen stimmen \"uberein ($(3 - \times 2) \cdot (2 \times 2)$), die Matrixmultiplikation ist - also m\"oglich. Das Produkt wird aus dem Skalarprodukt - jeder Zeile von $A$ mit jeder Spalte aus $B$ berechnet. Nachdem - $A$ drei Zeilen und $B$ zwei Spalten hat, hat das Ergebnis von $A - \cdot B$ die Gr\"o{\ss}e $(3 \times 2)$: - \[A \cdot B = \begin{pmatrix} 1 \cdot -1 + 2 \cdot -2 & 1 \cdot 2 + 2\cdot 5 \\ + \[\mathbf{A}_{(3 \times 2)} = \begin{pmatrix} 1 & 2 \\ 5 & 4 \\ -2 & 3 \end{pmatrix} + \quad \text{und} \quad \mathbf{B}_{(2 \times 2)} = \begin{pmatrix} + -1 & 2 \\ -2 & 5 \end{pmatrix} \; . \] + F\"ur das Produkt $\mathbf{A} \cdot \mathbf{B}$ stimmen die inneren + Dimensionen der Matrizen \"uberein ($(3 \times 2) \cdot (2 + \times 2)$), die Matrixmultiplikation ist also m\"oglich. Nachdem + $\mathbf{A}$ drei Zeilen und $\mathbf{B}$ zwei Spalten hat, hat das + Ergebnis von $\mathbf{A} \cdot \mathbf{B}$ die Gr\"o{\ss}e $(3 + \times 2)$: + \[ \mathbf{A} \cdot \mathbf{B} = \begin{pmatrix} 1 \cdot -1 + 2 \cdot -2 & 1 \cdot 2 + 2\cdot 5 \\ 5 \cdot -1 + 4 \cdot -2 & 5 \cdot 2 + 4 \cdot 5\\ -2 \cdot -1 + 3 \cdot -2 & -2 \cdot 2 + 3 \cdot 5 \end{pmatrix} = \begin{pmatrix} -5 & 12 \\ -13 & 30 \\ -4 & 11\end{pmatrix} \; . \] + + Das Produkt $\mathbf{B} \cdot \mathbf{A}$ ist dagegen nicht + definiert, da die inneren Dimensionen nicht \"ubereinstimmen + ($(2 \times 2) \cdot (3 \times 2)$). \end{ibox} +Beim Rechnen mit Matrizen gelten die gleichen Regeln wie bei +Vektoren. Matrizen k\"onnen solange elementweise miteinander +verrechnet werden, wie die Dimensionalit\"aten +\"ubereinstimmen. Wichtig ist auch hier wieder die Unterscheidung +zwischen elementweiser Multiplikation +(\code[Operator!arithmetischer!3mule@.*]{.*} Operator, Listing +\ref{matrixOperations} Zeile 10) oder Matrixmultiplikation +(\code[Operator!arithmetischer!3mul@*]{*} Operator, Listing +\ref{matrixOperations} Zeile 14, 17 und 21, Box~\ref{matrixmultiplication}). +Bei der Matrixmultiplikation m\"ussen die inneren Dimensionen der Matrizen \"ubereinstimmen +(Box~\ref{matrixmultiplication}). + +\pagebreak[4] +\begin{lstlisting}[label=matrixOperations, caption={Zwei Arten der Multiplikation von Matrizen.}] +>> A = randi(5, [2, 3]) % 2-D Matrix +A = + 1 5 3 + 3 2 2 +>> B = randi(5, [2, 3]) % dito +B = + 4 3 5 + 2 4 5 + +>> A .* B % elementweise Multiplikation +ans = + 4 15 15 + 6 8 10 +>> A * B % Matrixmultiplikation +Error using * +Inner matrix dimensions must agree. +>> A * B' % Matrixmultiplikation +ans = + 34 37 + 28 24 +>> A' * B % Matrixmultiplikation +ans = + 10 15 20 + 24 23 35 + 16 17 25 +\end{lstlisting} + \section{Boolesche Operationen} Boolesche Ausdr\"ucke sind Anweisungen, die zu \codeterm{wahr} oder \codeterm{falsch} ausgewertet werden. Man kennt sie z.B. aus der Mengenlehre. In der Programmierung werden sie eingesetzt, um z.B. die Beziehung zwischen Entit\"aten zu testen. Hierzu werden die -\codeterm{relationalen Operatoren} (\code{>}, \code{<}, \code{==}, -\code{!}, gr\"o{\ss}er als, kleiner als, gleich und nicht) -eingesetzt. Mehrere Ausdr\"ucke werden mittels der \codeterm{logischen - Operatoren} (\code{\&}, \code{|}, UND, ODER ) verkn\"upft. Sie sind f\"ur -uns nicht nur wichtig um Codeabschnitte bedingt auszuf\"uhren -(Verzweigungen, \ref{controlstructsec}) sondern auch um aus Vektoren -und Matrizen bequem Elemente auszuw\"ahlen (logisches Indizieren, -\ref{logicalindexingsec}). Die Tabellen \ref{logicalandor} zeigen die -Wahrheitstabellen f\"ur das logische UND (Tabelle \ref{logicalandor}, links) -und das logische ODER (Tabelle \ref{logicalandor}, rechts). Es werden die -Aussagen A und B mit dem Operator verkn\"upft. Beim logischen UND ist -der gesamte Ausdruck nur dann wahr, wenn beide Ausdr\"ucke sich zu -wahr auswerten lassen. +\codeterm{relationalen Operatoren} (\code[Operator!relationaler!>]{>}, +\code[Operator!relationaler!<]{<}, +\code[Operator!relationaler!==]{==}, +\code[Operator!relationaler!"!]{!}, gr\"o{\ss}er als, kleiner als, +gleich und nicht) eingesetzt. Mehrere Ausdr\"ucke werden mittels der +\codeterm[Operator!logischer]{logischen Operatoren} +(\code[Operator!logischer!and1@\&]{\&}, \code[Operator!logischer!or1@{"|} {}]{|}, +UND, ODER) verkn\"upft. Sie sind nicht nur wichtig, um +Codeabschnitte bedingt auszuf\"uhren (Verzweigungen, +\ref{controlstructsec}) sondern auch um aus Vektoren und Matrizen +bequem Elemente auszuw\"ahlen (logisches Indizieren, +\ref{logicalindexingsec}). + +Die Tabellen \ref{logicalandor} zeigen die Wahrheitstabellen f\"ur das +logische UND, das logische ODER und das logische XOR +(entweder-oder). Es werden die Aussagen A und B mit dem Operator +verkn\"upft. Beim logischen UND ist der gesamte Ausdruck nur dann +wahr, wenn beide Ausdr\"ucke sich zu wahr auswerten lassen. Anders +ist das beim logischen ODER. Hier ist der gesamte Ausdruck wahr, wenn +sich der eine \emph{oder} der andere Ausdruck, oder beide Ausdr\"ucke +zu wahr auswerten lassen. Das auschlie{\ss}ende ODER (XOR) ist nur +wahr, wenn entweder der eine oder der andere Ausdruck wahr ist und ist +in \matlab{} als Funktion \code[xor()]{xor(A, B)} verf\"ugbar. \begin{table}[tp] - \titlecaption{Wahrheitstabellen logisches UND (links) und logisches ODER (rechts).}{}\label{logicalandor} - \begin{minipage}[t]{0.4\textwidth} - \begin{tabular}{llll} - \multicolumn{2}{l}{\multirow{2}{*}{}} & \multicolumn{2}{c}{\textbf{B}} \\ - \multicolumn{2}{l}{} & \multicolumn{1}{|c|}{wahr} & falsch \\ \cline{2-4} - \multirow{2}{*}{\textbf{A}} & \multicolumn{1}{l|}{wahr} & \multicolumn{1}{c|}{\textcolor{mygreen}{wahr}} & \textcolor{red}{falsch} \\ \cline{2-4} - & \multicolumn{1}{l|}{falsch} & \multicolumn{1}{l|}{\textcolor{red}{falsch}} & \textcolor{red}{falsch} - \end{tabular} - \end{minipage} - \begin{minipage}[t]{0.4\textwidth} - \begin{tabular}{llll} - \multicolumn{2}{l}{\multirow{2}{*}{}} & \multicolumn{2}{c}{\textbf{B}} \\ - \multicolumn{2}{l}{} & \multicolumn{1}{|c|}{wahr} & falsch \\ \cline{2-4} - \multirow{2}{*}{\textbf{A}} & \multicolumn{1}{l|}{wahr} & \multicolumn{1}{c|}{\textcolor{mygreen}{wahr}} & \textcolor{mygreen}{wahr} \\ \cline{2-4} - & \multicolumn{1}{l|}{falsch} & \multicolumn{1}{l|}{\textcolor{mygreen}{wahr}} & \textcolor{red}{falsch} - \end{tabular} - \end{minipage} + \titlecaption{Wahrheitstabellen logisches UND, ODER und XOR.}{}\label{logicalandor} + \begin{tabular}{llll} + \multicolumn{2}{l}{\multirow{2}{*}{}} & \multicolumn{2}{c}{\textbf{B}} \\ + & \sffamily{\textbf{und}} & \multicolumn{1}{|c}{wahr} & falsch \\ \cline{2-4} + \multirow{2}{*}{\textbf{A}} & \multicolumn{1}{l|}{wahr} & \multicolumn{1}{c}{\textcolor{mygreen}{wahr}} & \textcolor{red}{falsch} \erb \\ + & \multicolumn{1}{l|}{falsch} & \multicolumn{1}{l}{\textcolor{red}{falsch}} & \textcolor{red}{falsch} + \end{tabular} + \hfill + \begin{tabular}{llll} + \multicolumn{2}{l}{\multirow{2}{*}{}} & \multicolumn{2}{c}{\textbf{B}} \\ + & \sffamily{\textbf{oder}} & \multicolumn{1}{|c}{wahr} & falsch \\ \cline{2-4} + \multirow{2}{*}{\textbf{A}} & \multicolumn{1}{l|}{wahr} & \multicolumn{1}{c}{\textcolor{mygreen}{wahr}} & \textcolor{mygreen}{wahr} \erb \\ + & \multicolumn{1}{l|}{falsch} & \multicolumn{1}{l}{\textcolor{mygreen}{wahr}} & \textcolor{red}{falsch} + \end{tabular} + \hfill + \begin{tabular}{llll} + \multicolumn{2}{l}{\multirow{2}{*}{}} & \multicolumn{2}{c}{\textbf{B}} \\ + & \sffamily{\textbf{xor}} & \multicolumn{1}{|c}{wahr} & falsch \\ \cline{2-4} + \multirow{2}{*}{\textbf{A}} & \multicolumn{1}{l|}{wahr} & \multicolumn{1}{c}{\textcolor{red}{falsch}} & \textcolor{mygreen}{wahr} \erb \\ + & \multicolumn{1}{l|}{falsch} & \multicolumn{1}{l}{\textcolor{mygreen}{wahr}} & \textcolor{red}{falsch} + \end{tabular} \end{table} -Anders ist das beim logischen ODER. Hier ist der gesamte Ausdruck -wahr, wenn sich der eine \emph{oder} der andere Ausdruck zu wahr -auswerten l\"a{\ss}t. Tabelle \ref{logicaloperators} zeigt die -logischen Operatoren, die in \matlab{} definiert sind. Zu bemerken -sind hier noch die \code{\&\&} und \code{||} Operatoren. Man kann +Tabelle \ref{logicalrelationaloperators} zeigt die logischen Operatoren, die in +\matlab{} definiert sind. Zu bemerken sind hier noch die +\code[Operator!logischer!and2@\&\&]{\&\&} und +\code[Operator!logischer!or2@{"|}{"|} {}]{||} Operatoren. Man kann beliebige Ausdr\"ucke verkn\"upfen und h\"aufig kann schon anhand des ersten Ausdrucks entschieden werden, ob der gesamte Boolesche Ausdruck zu wahr oder falsch ausgewertet werden wird. Wenn zwei Aussagen mit einem UND verkn\"upft werden und der erste zu falsch ausgewertet wird, muss der zweite gar nicht mehr gepr\"uft werden. Die Verwendung der -``short-circuit'' Versionen spart Rechenzeit. Das auschlie{\ss}ende ODER -(XOR) ist in \matlab{} nur als Funktion \code{xor(A, B)} verf\"ugbar. - -\begin{table}[th] - \titlecaption{\label{logicaloperators} - Logische Operatoren in \matlab.}{} - \begin{center} - \begin{tabular}{c|c} - \hline - \textbf{Operator} & \textbf{Beschreibung} \\ \hline - $\sim$ & logisches NOT\\ - $\&$ & logisches UND\\ - $|$ & logisches ODER\\ - $\&\&$ & short-circuit logisches UND\\ - $\|$ & short-circuit logisches ODER\\ - \hline - \end{tabular} - \end{center} +\enterm{short-circuit} Versionen spart Rechenzeit, da die Ausdr\"ucke +nur sowei wie n\"otig ausgewertet werden. + +\begin{table}[t] + \titlecaption{\label{logicalrelationaloperators} + Logische (links) und relationale (rechts) Operatoren in \matlab.}{} + \begin{tabular}{cc} + \hline + \textbf{Operator} & \textbf{Beschreibung} \erh \\ \hline + \varcode{$\sim$} & logisches NICHT \erb \\ + \varcode{$\&$} & logisches UND\\ + \varcode{$|$} & logisches ODER\\ + \varcode{$\&\&$} & short-circuit logisches UND\\ + \varcode{$\|$} & short-circuit logisches ODER\\ + \hline + \end{tabular} + \hfill + \begin{tabular}{cc} + \hline + \textbf{Operator} & \textbf{Beschreibung} \erh \\ \hline + \varcode{$==$} & gleich \erb \\ + \varcode{$\sim=$} & ungleich\\ + \varcode{$>$} & gr\"o{\ss}er als \\ + \varcode{$<$} & kleiner als \\ + \varcode{$>=$} & gr\"o{\ss}er oder gleich \\ + \varcode{$<=$} & kleiner oder gleich \\ + \hline + \end{tabular} \end{table} -Um Werte miteinander zu vergleichen gibt es die \codeterm{relationalen - Operatoren} (Tabelle \ref{relationaloperators}). Mit ihnen kann man -auf Dinge wie Gleichheit (\code{==}) gr\"o{\ss}er oder kleiner als -(\code{>}, \code{<}) testen. - -\begin{table}[th] - \titlecaption{\label{relationaloperators} - Relationale Operatoren in \matlab.}{} - \begin{center} - \begin{tabular}{c|c} - \hline - \textbf{Operator} & \textbf{Beschreibung} \\ \hline - $<$ & kleiner als\\ - $>$ & gr\"o{\ss}er als \\ - $==$ & gleich \\ - $>=$ & gr\"o{\ss}er oder gleich \\ - $<=$ & kleiner oder gleich \\ - $\sim=$ & ungleich\\ - \hline - \end{tabular} - \end{center} -\end{table} +Um Werte miteinander zu vergleichen gibt es die +\codeterm[Operator!relationaler]{relationalen Operatoren} (Tabelle +\ref{logicalrelationaloperators}). Mit ihnen kann man auf Dinge wie +Gleichheit (\varcode{==}) gr\"o{\ss}er oder kleiner als (\varcode{>}, +\varcode{<}) testen. + +\begin{important}[Zuweisungs- und Gleichheitsoperator] + Der Zuweisungsoperator \code[Operator!Zuweisung!=]{=} und der + logische Operator \code[Operator!logischer!==]{==} sind zwei + grundverschiedene Dinge. Da sie umgangsprachlich gleich sind + k\"onnen sie leider leicht verwechselt werden. +\end{important} Das Ergebnis eines Booleschen Ausdrucks ist immer vom Datentyp -\codeterm{logical}. Man kann jede beliebige Variable zu wahr oder falsch -auswerten indem man in den Typ \code{logical} umwandelt. Dabei -werden von \matlab{} alle Werte, die nicht 0 sind als wahr +\codeterm{logical}. Jede beliebige Variable zu wahr oder falsch +ausgewertet werden indem diese in den Typ \code{logical} umgewandelt +wird. Dabei werden von \matlab{} alle Werte, die nicht 0 sind als wahr eingesch\"atzt. Listing \ref{booleanexpressions} zeigt einige Beispiele. \matlab{} kennt die Schl\"usselworte \code{true} und -\code{false}. Diese sind jedoch nur Synonyme f\"ur die -\code{logical} Werte 1 und 0. - -\begin{important}[Zuweisungs- und Gleichheitsoperator] - Der Zuweisungsoperator \code{=} und der logische Operator \code{==} - sind zwei grundverschiedene Dinge. Da sie umgangsprachlich gleich - sind k\"onnen sie leider leicht verwechselt werden. -\end{important} +\code{false}. Diese sind Synonyme f\"ur die \code{logical} Werte 1 und +0. \begin{lstlisting}[caption={Boolesche Ausdr\"ucke.}, label=booleanexpressions] - >> true - ans = - 1 - >> false - ans = - 0 - >> logical(1) - ans = - 1 - >> 1 == true - ans = - 1 - >> 1 == false - ans = - 0 - >> logical('test') - ans = - 1 1 1 1 - - >> 1 > 2 - ans = - 0 - >> 1 < 2 - ans = - 1 - >> x = [2 0 0 5 0] & [1 0 3 2 0] - x = - 1 0 0 1 0 - - >> ~([2 0 0 5 0] & [1 0 3 2 0]) - ans = - 0 1 1 0 1 - - >> [2 0 0 5 0] | [1 0 3 2 0] - ans = - 1 0 1 1 0 +>> true +ans = 1 +>> false +ans = 0 +>> logical(1) +ans = 1 +>> 1 == true +ans = 1 +>> 1 == false +ans = 0 +>> logical('test') +ans = 1 1 1 1 +>> 1 > 2 +ans = 0 +>> 1 < 2 +ans = 1 +>> x = [2 0 0 5 0] & [1 0 3 2 0] +x = 1 0 0 1 0 +>> ~([2 0 0 5 0] & [1 0 3 2 0]) +ans = 0 1 1 0 1 +>> [2 0 0 5 0] | [1 0 3 2 0] +ans = 1 0 1 1 0 \end{lstlisting} \section{Logisches Indizieren}\label{logicalindexingsec} Einer der wichtigsten Einsatzorte f\"ur Boolesche Ausdr\"ucke ist das -logische Indizieren. Das logische Indizieren ist eines der +logische Indizieren. Logisches Indizieren ist eines der Schl\"usselkonzepte in \matlab{}. Nur mit diesem k\"onnen Filteroperationen auf Vektoren und Matrizen effizient durchgef\"uhrt werden. Es ist sehr m\"achtig und, wenn es einmal verstanden wurde, sehr intuitiv zu benuzten. -Das Grundkonzept hinter der logischen Indizierung ist, dass man durch -die Verwendung eines Booleschen Ausdrucks auf z.B. einen Vektor einen -logischen Vektor gleicher Gr\"o{\ss}e erh\"alt. Dieser wird -benutzt um auf den urspr\"unglichen Vektor zuzugreifen. \matlab{} gibt -nur die Werte an den Stellen zur\"uck, an denen der logische Vektor -\codeterm{wahr} ist (Listing \ref{logicalindexing1}). - +Das Grundkonzept hinter der logischen Indizierung ist, dass durch die +Verwendung eines Booleschen Ausdrucks auf z.B. einen Vektor ein +logischer Vektor gleicher Gr\"o{\ss}e zur\"uckgegeben wird. Dieser +wird benutzt um die Elemente des urspr\"unglichen Vektors +auszuw\"ahlen, bei denen der logische Vektor \codeterm{wahr} ist +(Listing \ref{logicalindexing1}). Zeile 14 kann wie +folgt gelesen werden: Gib die Elemente von \varcode{x} an den +Stellen, an denen \varcode{x < 0} wahr ist, zur\"uck. \begin{lstlisting}[caption={Beispiel logisches Indizieren.}, label=logicalindexing1] - >> x = randn(10, 1); - >> % in zwei Schritten - >> x_smaller_zero = x < 0; % logischer vektor - >> elements_smaller_zero = x(x_smaller_zero); % benutzen, um zuzugreifen - >> % oder in einem Schritt - >> elements_smaller_zero = x(x < 0); +>> x = randn(1, 6) % Zeilenvektor mit 6 Zufallszahlen +x = + -1.4023 -1.4224 0.4882 -0.1774 -0.1961 1.4193 + +>> % logisches Indizieren in zwei Schritten: +>> x_smaller_zero = x < 0 % logischer Vektor +x_smaller_zero = + 1 1 0 1 1 0 +>> elements_smaller_zero = x(x_smaller_zero) % benutzen, um zuzugreifen +elements_smaller_zero = + -1.4023 -1.4224 -0.1774 -0.1961 + +>> % logisches Indizieren in einem Schritten: +>> elements_smaller_zero = x(x < 0) +elements_smaller_zero = + -1.4023 -1.4224 -0.1774 -0.1961 \end{lstlisting} \begin{exercise}{logicalVector.m}{logicalVector.out} - Erstelle einen Vektor x mit den Werten 0-10. + Erstelle einen Vektor \varcode{x} mit den Werten 0--10. \begin{enumerate} - \item F\"uhre aus: \code{y = x < 5} - \item Gib den Inhalt von \code{y} auf dem Bildschirm aus. - \item Was ist der Datentyp von \code{y}? - \item Gibt alle Elemente aus x zur\"uck, die kleiner als 5 sind. + \item F\"uhre aus: \varcode{y = x < 5} + \item Gib den Inhalt von \varcode{y} auf dem Bildschirm aus. + \item Was ist der Datentyp von \varcode{y}? + \item Gibt alle Elemente aus \varcode{x} zur\"uck, die kleiner als 5 sind. \end{enumerate} - - Zeile 12 in der L\"osung kann wie folgt gelesen werden: Gib mir die Elemente - von (\code{x}) an den Stellen, an denen \code{x < 5} wahr ist. + \pagebreak[4] \end{exercise} -Logisches Indizieren wurde oben so benutzt, dass die Auswahl -auf dem Inhalt desselben Vektors beruhte. Ein sehr h\"aufiger Fall ist -jedoch, dass die Auswahl aus einem Vektor auf dem Inhalt eines -zweiten Vektors basiert. Ein Beispiel ist, dass man \"uber einen -gewissen Zeitraum Daten aufnimmt und aus diesen die Daten eines -bestimmten Zeitraums ausw\"ahlen m\"ochte (Abbildung -\ref{logicalindexingfig}). - - -\begin{figure}[h] +\begin{figure}[t] \includegraphics[width= 0.9\columnwidth]{logicalIndexingTime} - \titlecaption{Beispiel f\"ur ``indirektes'' logisches Indizieren.} - {Der rot markierte Abschnitt aus den Daten wurde ``indirekt'' - anhand logischen Indizierens auf dem Zeitvektor - ausgew\"ahlt.}\label{logicalindexingfig} + \titlecaption{Beispiel f\"ur logisches Indizieren.} + {Der rot markierte Abschnitt aus den Daten wurde indirekt + mit logischem Indizieren auf dem Zeitvektor + ausgew\"ahlt (\varcode{x(t > 5 \& t < 6)}).}\label{logicalindexingfig} \end{figure} +Logisches Indizieren wurde oben so benutzt, dass die Auswahl auf dem +Inhalt desselben Vektors beruhte. Ein weiterer sehr h\"aufiger Fall +ist jedoch, dass die Auswahl aus einem Vektor auf dem Inhalt eines +zweiten Vektors basiert. Ein Beispiel ist, dass \"uber einen +gewissen Zeitraum Daten aufgenommen werden und aus diesen die Daten eines +bestimmten Zeitraums ausgew\"ahlt werden sollen (\figref{logicalindexingfig}). + \begin{exercise}{logicalIndexingTime.m}{} Angenommen es werden \"uber einen bestimmten Zeitraum Messwerte genommen. Bei solchen Messungen erh\"alt man einen Vektor, der die @@ -842,13 +970,13 @@ bestimmten Zeitraums ausw\"ahlen m\"ochte (Abbildung jeweiligen Messwerten. \begin{itemize} - \item Erstelle einen Vektor \code{t = 0:0.001:10;}, der z.B. die Zeit + \item Erstelle einen Vektor \varcode{t = 0:0.001:10;}, der die Zeit repr\"asentiert. - \item Erstelle einen zweiten Vektor \code{x} mit Zufallszahlen der - die gleiche L\"ange hat wie \code{t}. Die Werte darin stellen - Messungen zu den Zeitpunkten in \code{t} dar. - \item Benutze das logische Indizieren um die Messwerte - auszuw\"ahlen, die dem zeitlichen Abschnitt 5-6\,s entsprechen. + \item Erstelle einen zweiten Vektor \varcode{x} mit Zufallszahlen, der + die gleiche L\"ange hat wie \varcode{t}. Die Werte darin stellen + Messungen zu den Zeitpunkten in \varcode{t} dar. + \item Benutze logische Indizieren um die Messwerte + auszuw\"ahlen, die dem zeitlichen Abschnitt 5--6\,s entsprechen. \end{itemize} \end{exercise} @@ -887,59 +1015,67 @@ x = Im Prinzip ist das obige Programm v\"ollig in Ordnung. Es f\"allt jedoch auf, dass die Zeilen 2 bis 5 sehr \"ahnlich sind; bis auf die Multiplikation mit einer ansteigenden Zahl \"andert sich nichts. Die -Verwendung von mehr oder weniger exakten Klonen einzelner Zeilen oder -ganzer Abschnitte ist schlechter Prgrammierstil. Dabei geht es nicht nur um -einen \"asthetischen Aspekt sondern vielmehr darum, dass es schwerwiegende Nachteile gibt. +Verwendung von mehr oder weniger exakten Wiederholungen einzelner +Zeilen oder ganzer Abschnitte ist schlechter Prgrammierstil. Dabei +geht es nicht nur um einen \"asthetischen Aspekt sondern vielmehr +darum, dass es schwerwiegende Nachteile gibt: \begin{enumerate} \item Fehleranf\"alligkeit: Beim ``Copy-and-paste'' kann leicht - vergessen werden in einzelnen Klonen die entscheidende \"Anderung - auch wirklich vorzunehmen. + vergessen werden in einzelnen Wiederholungen die entscheidende + \"Anderung auch wirklich vorzunehmen. + \shortquote{Copy and paste is a design error.}{David Parnas} \item Flexibilit\"at: Das obige Programm ist f\"ur genau einen Zweck, Berechnung der Fakult\"at von f\"unf, gemacht und kann nichts anderes. -\item Wartung: Wenn ich einen Fehler gemacht habe, dann muss ich den - Fehler in allen Klonen korrigieren (sehr leicht wird dabei der ein oder - andere Klon \"ubersehen). -\item Verst\"andlichkeit: Solche Abschnitte sind schwerer zu lesen/zu - verstehen. Das liegt zum Teil daran, dass man dazu neigt \"uber sich - wiederholende Zeilen zu springen (ist ja eh das gleiche...) und dann - den entscheidenden Teil verpasst. Zum Anderen f\"uhrt - Codeduplication zu langen, un\"ubersichtlichen Programmen. +\item Wartung: Wenn ein Fehler gemacht wurde, dann muss der Fehler in + allen Wiederholungen korrigiert werden (sehr leicht wird dabei etwas + \"ubersehen). +\item Verst\"andlichkeit: Solche Abschnitte sind schwerer zu lesen und + schwer zu verstehen. Das liegt zum Teil daran, dass man dazu neigt + \"uber sich wiederholende Zeilen zu springen (ist ja eh das + gleiche...) und dann den entscheidenden Teil verpasst. Zum Anderen + f\"uhrt Codeduplication zu langen, un\"ubersichtlichen Programmen. \end{enumerate} Alle Programmiersprachen bieten zur L\"osung dieses Problems die -Schleifen. Eine Schleife wird immer dann eingesetzt, wenn man -Abschnitte wiederholt ausf\"uhren will. +Schleifen. Eine Schleife wird immer dann eingesetzt, wenn +Abschnitte wiederholt ausgef\"uhrt werden sollen. \subsubsection{Die \code{for} -- Schleife} Der am h\"aufigsten benutzte Vertreter der Schleifen ist die -\codeterm{for-Schleife}. Sie besteht aus dem \codeterm{Schleifenkopf} und -dem \codeterm{Schleifenk\"orper}. Der Kopf regelt, wie h\"aufig der Code -im K\"orper ausgef\"uhrt wird. Der Schleifenkopf beginnt mit dem -Schl\"usselwort \code{for} auf welches folgend die -\codeterm{Laufvariable} definiert wird. In \matlab ``l\"auft''/iteriert -eine for-Schleife immer(!) \"uber einen Vektor. Die -\codeterm{Laufvariable} nimmt mit jeder Iteration einen Wert dieses -Vektors an. Im Schleifenk\"orper k\"onnen beliebige Anweisungen -ausgef\"uhrt werden. Die Schleife wird durch das Schl\"usselwort -\code{end} beendet. Listing \ref{looplisting} zeigt das -Grundger\"ust einer for-Schleife. - -\begin{lstlisting}[caption={Beispiel einer \code{for} Schleife. Die Laufvariable \code{x} nimmt mit jeder Iteration der Schleife einen Wert des Vektors \code{1:5} an.}, label=looplisting] -for x = 1:5 - % ... etwas sinnvolles mit x ... -end +\codeterm{for-Schleife}. Sie besteht aus dem +\codeterm[Schleife!Schleifenkopf]{Schleifenkopf} und dem +\codeterm[Schleife!Schleifenk{\"o}rper]{Schleifenk\"orper}. Der Kopf +regelt, wie h\"aufig der Code im K\"orper ausgef\"uhrt wird. Der +Schleifenkopf beginnt mit dem Schl\"usselwort \code{for} auf welches +folgend die \codeterm{Laufvariable} definiert wird. In \matlab +``l\"auft''/iteriert eine for-Schleife immer(!) \"uber einen +Vektor. Die \codeterm{Laufvariable} nimmt mit jeder Iteration einen +Wert dieses Vektors an. Im Schleifenk\"orper k\"onnen beliebige +Anweisungen ausgef\"uhrt werden. Die Schleife wird durch das +Schl\"usselwort \code{end} beendet. Listing \ref{looplisting} zeigt +das Grundger\"ust einer for-Schleife. + +\begin{lstlisting}[caption={Beispiel einer \varcode{for}-Schleife.}, label=looplisting] +>> for x = 1:3 + x + end +% die Laufvariable x nimmt mit jeder Iteration der Schleife +% einen Wert des Vektors 1:3 an: + 1 + 2 + 3 \end{lstlisting} \begin{exercise}{facultyLoop.m}{facultyLoop.out} Wie k\"onnte Fakult\"at mit einer Schleife implementiert werden? Implementiere eine \code{for} Schleife, die die Fakul\"at von einer - Zahl \code{n} berechnet. + Zahl \varcode{n} berechnet. \end{exercise} -\subsubsection{Die \code{while} -- Schleife} +\subsubsection{Die \varcode{while} -- Schleife} Eine weiterer Schleifentyp, der weniger h\"aufig eingesetzt wird, ist die \code{while}-Schleife. Auch sie hat ihre Entsprechungen in fast @@ -952,13 +1088,12 @@ Schleifenk\"orper ausgef\"uhrt. Die Schleife wird mit dem Schl\"usselwort \code{end} beendet. -\begin{lstlisting}[caption={Grundstruktur einer \code{while} Schleife.}, label=whileloop] +\begin{lstlisting}[caption={Grundstruktur einer \varcode{while} Schleife.}, label=whileloop] while x == true - % fuehre diesen sinnvollen code aus ... + % fuehre diesen sinnvollen Code aus ... end \end{lstlisting} - \begin{exercise}{facultyWhileLoop.m}{} Implementiere die Fakult\"at mit einer \code{while}-Schleife. \end{exercise} @@ -968,10 +1103,11 @@ end Implementiere eine \code{while}-Schleife, die unendlich l\"auft. Tipp: wenn der Boolesche Ausdruck hinter dem \code{while} zu wahr ausgewertet wird, wird die Schleife weiter ausgef\"uhrt. + Das Programm kann mit \keycode{Ctrl+C} abgebrochen werden. \end{exercise} -\subsubsection{Vergleich \code{for} -- und \code{while}--Schleife} +\subsubsection{Vergleich \varcode{for} -- und \varcode{while}--Schleife} \begin{itemize} \item Beide f\"uhren den Code im Schleifenk\"orper iterativ aus. \item Der K\"orper einer \code{for} Schleife wird mindestens 1 mal @@ -994,7 +1130,7 @@ Bedingte Anweisungen und Verzweigungen sind Kontrollstrukturen, die regeln, dass der in ihnen eingeschlossene Programmcode nur unter bestimmten Bedingungen ausgef\"uhrt wird. -\subsubsection{Die \code{if} -- Anweisung} +\subsubsection{Die \varcode{if} -- Anweisung} Am h\"aufigsten genutzter Vertreter ist die \code{if} - Anweisung. Sie wird genutzt um Programmcode nur unter bestimmten @@ -1012,27 +1148,27 @@ beendet. Listing \ref{ifelselisting} zeigt den Aufbau einer \code{if} - Anweisung. -\begin{lstlisting}[label=ifelselisting, caption={Grundger\"ust einer \code{if} Anweisung.}] - if x < y - % fuehre diesen code aus +\begin{lstlisting}[label=ifelselisting, caption={Grundger\"ust einer \varcode{if} Anweisung.}] +if x < y + % fuehre diesen code aus wenn x < y elseif x > y - % etwas anderes soll getan werden + % etwas anderes soll getan werden fuer x > y else % wenn x == y, wieder etwas anderes end \end{lstlisting} \begin{exercise}{ifelse.m}{} - Ziehe eine Zufallszahl und \"uberpr\"ufe mit einer geeigneten \code{if} Anweisung, ob sie: + Ziehe eine Zufallszahl und \"uberpr\"ufe mit einer geeigneten \code{if} Anweisung, ob sie \begin{enumerate} - \item ... kleiner als 0.5 ist. - \item ... kleiner oder gr\"o{\ss}er-gleich 0.5 ist. - \item ... 1. kleiner als 0.5, 2. gr\"o{\ss}er oder gleich 0.5 aber kleiner - als 0.75 oder 3. gr\"o{\ss}er oder gleich 0.75 ist. + \item kleiner als 0.5 ist. + \item kleiner oder gr\"o{\ss}er-gleich 0.5 ist. + \item (i) kleiner als 0.5, (ii) gr\"o{\ss}er oder gleich 0.5 aber kleiner + als 0.75 oder (iii) gr\"o{\ss}er oder gleich 0.75 ist. \end{enumerate} \end{exercise} -\subsubsection{Die \code{switch} -- Verzweigung} +\subsubsection{Die \varcode{switch} -- Verzweigung} Die \code{switch} Verzweigung wird eingesetzt wenn mehrere F\"alle auftreten k\"onnen, die einer unterschiedlichen Behandlung bed\"urfen. @@ -1049,7 +1185,7 @@ F\"alle behandelt werden. Die \code{switch} Anweisung wird mit \code{end} beendet (z.B. in Listing \ref{switchlisting}). -\begin{lstlisting}[label=switchlisting, caption={Grundger\"ust einer \code{switch} Anweisung.}] +\begin{lstlisting}[label=switchlisting, caption={Grundger\"ust einer \varcode{switch} Anweisung.}] mynumber = input('Enter a number:'); switch mynumber case -1 @@ -1058,14 +1194,14 @@ switch mynumber disp('positive one'); otherwise disp('something else'); - end +end \end{lstlisting} Wichtig ist hier, dass in jedem \code{case} auf Gleichheit der switch-Anweisung und der case-Anweisung getestet wird. -\subsubsection{Vergleich \code{if} -- Anweisung und \code{switch} -- Verzweigung} +\subsubsection{Vergleich \varcode{if} -- Anweisung und \varcode{switch} -- Verzweigung} \begin{itemize} \item Mit der \code{if} Anweisung k\"onnen beliebige F\"alle unterschieden und entsprechender Code ausgef\"uhrt werden. @@ -1082,25 +1218,35 @@ switch-Anweisung und der case-Anweisung getestet wird. Soll die Ausf\"uhrung einer Schleife abgebrochen oder \"ubersprungen werden, werden die Schl\"usselworte \code{break} und -\code{continue} eingesetzt (Listing \ref{breakcontinuelisting} -zeigt, wie sie eingesetzt werden k\"onnen). +\code{continue} eingesetzt (Listings \ref{continuelisting} +und \ref{continuelisting} zeigen, wie sie eingesetzt werden k\"onnen). + +\begin{lstlisting}[caption={Abbrechen von Schleifen mit \varcode{break}.}, label=breaklisting] +>> x = 1; + while true + if (x > 3) + break; + end + disp(x); + x = x + 1; + end +% output: + 1 + 2 + 3 +\end{lstlisting} -\begin{lstlisting}[caption={Einsatz der \code{continue} und \code{break} Schl\"usselworte um die Ausf\"uhrung von Code-Abschnitten in Schleifen zu \"uberspringen oder abzubrechen.}, label=breakcontinuelisting] -for x = 1:10 +\begin{lstlisting}[caption={\"Uberspringen von Code-Abschnitten in Schleifen mit \varcode{continue}.}, label=continuelisting] +for x = 1:5 if(x > 2 & x < 5) continue; end disp(x); end - -x = 1; -while true - if(x > 5) - break; - end - disp(x); - x = x + 1 -end +% output: + 1 + 2 + 5 \end{lstlisting} \begin{exercise}{logicalIndexingBenchmark.m}{logicalIndexingBenchmark.out} @@ -1127,7 +1273,7 @@ end \item In dem Programm sollen 10 Realisationen eines random walk mit jeweils 1000 Schritten durchgef\"uhrt werden. \item Die Position des Objektes ver\"andert sich in jedem Schritt zuf\"allig um - +1 oder -1. + $+1$ oder $-1$. \item Merke Dir alle Positionen. \item Plotte die Positionen als Funktion der Schrittnummer. \end{itemize} @@ -1143,12 +1289,12 @@ wird, dann wird es Zeile f\"ur Zeile von oben nach unten ausgef\"uhrt. \matlab{} kennt drei Arten von Programmen: \begin{enumerate} -\item Skripte -\item Funktionen -\item Objekte (werden wir ignorieren) +\item \codeterm[Skript]{Skripte} +\item \codeterm[Funktion]{Funktionen} +\item \codeterm[Objekt]{Objekte} (werden wir hier nicht behandeln) \end{enumerate} Alle Programme werden in den sogenannten \codeterm{m-files} gespeichert -(z.B. \emph{meinProgramm.m}). Um sie zu benutzen werden sie von der +(z.B. \file{meinProgramm.m}). Um sie zu benutzen werden sie von der Kommandozeile aufgerufen oder in anderen Programmen verwendet. Programme erh\"ohen die Wiederverwertbarkeit von Programmcode. Bislang haben wir ausschlie{\ss}lich Skripte @@ -1161,15 +1307,15 @@ definierte Variable und weist ihr einen neuen Wert zu, dann kann das erw\"unscht und praktisch sein. Wenn es aber unbeabsichtigt passiert kann es zu Fehlern kommen, die nur sehr schwer erkennbar sind, da ja jedes Skript f\"ur sich enwandtfrei arbeitet. Eine L\"osung f\"ur -dieses Problem bieten die \codeterm{Funktionen}. +dieses Problem bieten die \codeterm[Funktion]{Funktionen}. \subsection{Funktionen} Eine Funktion in \matlab{} wird \"ahnlich zu einer mathematischen Funktion definiert: \[ y = f(x) \] -Die Funktion hat einen Namen $f$, sie h\"angt von einem Argument $x$ -ab und liefert ein Ergebnis $y$ zur\"uck. Listing +Die Funktion hat einen Namen $f$, sie \"uber das Argument $x$ +einen Input und liefert ein Ergebnis in $y$ zur\"uck. Listing \ref{functiondefinitionlisting} zeigt wie das in \matlab{} umgesetzt wird. @@ -1200,21 +1346,22 @@ definiert. \"Uber die Definition/Benutzung von Funktionen wird folgendes erreich \item Erh\"oht die Lesbarkeit von Programmen, da sie \"ubersichtlicher werden. \end{itemize} + Das Folgende Beispiel (Listing \ref{badsinewavelisting}) zeigt eine Funktion, die eine Reihe von Sinusschwingungen unterschiedlicher Frequenzen berechnet und graphisch darstellt. -\begin{lstlisting}[caption={Eine Beispielfunktion, die eine Reihe Sinusse plottet.},label=badsinewavelisting] +\begin{lstlisting}[caption={Ein schlechtes Beispiel einer Funktion, die eine Reihe Sinusse plottet.},label=badsinewavelisting] function meineErsteFunktion() % Funktionskopf t = (0:0.01:2); % hier faengt der Funktionskoerper an frequenz = 1.0; amplituden = [0.25 0.5 0.75 1.0 1.25]; - for i = 1:length(amplituden) y = sin(frequenz * t * 2 * pi) * amplituden(i); plot(t, y) hold on; end +end \end{lstlisting} Das obige Beispiel ist ein Paradebeispiel f\"ur eine schlechte Funktion. Sie hat folgende Probleme: @@ -1254,92 +1401,107 @@ hei{\ss}en soll, (ii) welche Information sie ben\"otigt und (iii) welche Daten sie zur\"uckliefern soll. \begin{enumerate} -\item \codeterm{Name:} der Name sollte beschreiben, was die Funktion - tut. In diesem Fall berechnet sie einen Sinus. Ein geeigneter Name - w\"are also \code{calculateSinewave}. -\item \codeterm{Argumente:} die zu brechnende Sinusschwingung sei durch - ihre Frequenz und die Amplitude bestimmt. Des Weiteren soll noch - festgelegt werden, wie lang der Sinus sein soll und mit welcher - zeitlichen Aufl\"osung gerechnet werden soll. Es werden also vier - Argumente ben\"otigt, sie k\"onnten hei{\ss}en: \code{amplitude}, - \code{frequency}, \code{t\_max}, \code{t\_step}. -\item \codeterm{R\"uckgabewerte:} Um den Sinus korrekt darstellen zu k\"onnen brauchen wir die - Zeitachse und die entsprechenden Werte. Es werden also zwei - Variablen zur\"uckgegeben: \code{time, sine} +\item \codeterm[Funktion!Name]{Name}: der Name sollte beschreiben, was + die Funktion tut. In diesem Fall berechnet sie einen Sinus. Ein + geeigneter, kurzer Name w\"are also \code{sinewave()}. +\item \codeterm[Funktion!Argumente]{Argumente}: die zu brechnende + Sinusschwingung sei durch ihre Frequenz und die Amplitude + bestimmt. Des Weiteren soll noch festgelegt werden, wie lang der + Sinus sein soll und mit welcher zeitlichen Aufl\"osung gerechnet + werden soll. Es werden also vier Argumente ben\"otigt, sie k\"onnten + hei{\ss}en: \varcode{amplitude}, \varcode{frequency}, + \varcode{t\_max}, \varcode{t\_step}. +\item \codeterm[Funktion!R{\"u}ckgabewerte]{R\"uckgabewerte}: Um den + Sinus korrekt darstellen zu k\"onnen brauchen wir die Zeitachse und + die entsprechenden Werte. Es werden also zwei Variablen + zur\"uckgegeben: \varcode{time}, \varcode{sine} \end{enumerate} Mit dieser Information ist es nun gut m\"oglich die Funktion zu implementieren (Listing \ref{sinefunctionlisting}). -\begin{lstlisting}[caption={Funktion, die einen Sinus berechnet.}, label=sinefunctionlisting] -function [time, sine] = calculateSinewave(frequency, amplitude, t_max, t_step) - % The function calculates a sinewave with a given frequency and - % amplitude. - % Arguments: frequency, the frequency of the sine - % amplitude, the amplitude of the sine - % t_max, the duration of the sine in seconds - % t_step, the temporal resolution in seconds - % Returns: time, the time axis - % sine, the calculated sinewave +\begin{lstlisting}[caption={Funktion zur Berechnung eines Sinus.}, label=sinefunctionlisting] +function [time, sine] = sinewave(frequency, amplitude, t_max, t_step) +% Calculate a sinewave of a given frequency, amplitude, +% duration and temporal resolution. +% +% [time, sine] = sinewave(frequency, amplitude, t_max, t_step) +% +% Arguments: +% frequency: the frequency of the sine +% amplitude: the amplitude of the sine +% t_max : the duration of the sine in seconds +% t_step : the temporal resolution in seconds +% Returns: +% time: vector of the time axis +% sine: vector of the calculated sinewave time = (0:t_step:t_max); sine = sin(frequency .* time .* 2 * pi) .* amplitude; +end \end{lstlisting} \paragraph{II. Plotten einer einzelnen Schwingung} -Diese Aufgabe kann auch von einer Funktion \"ubernommen werden. Diese -Funktion hat keine andere Aufgabe, als die Daten zu plotten. Ihr Name -sollte sich an dieser Aufgabe orientieren -(z.B. \code{plotSinewave}). Um einen einzelnen Sinus zu plotten -werden im Wesentlichen die x-Werte und die zugeh\"origen y-Werte -ben\"otigt. Da mehrere Sinus geplottet werden sollen ist es auch -sinnvoll eine Zeichenkette f\"ur die Legende an die Funktion zu +Das Plotten der berechneten Sinuschwingung kann auch von einer +Funktion \"ubernommen werden. Diese Funktion hat keine andere Aufgabe, +als die Daten zu plotten. Ihr Name sollte sich an dieser Aufgabe +orientieren (z.B. \code{plotFunction()}). Um einen einzelnen Sinus +zu plotten werden im Wesentlichen die x-Werte und die zugeh\"origen +y-Werte ben\"otigt. Da mehrere Sinus geplottet werden sollen ist es +auch sinnvoll eine Zeichenkette f\"ur die Legende an die Funktion zu \"ubergeben. Da diese Funktion keine Berechnung durchf\"uhrt wird kein R\"uckgabewert ben\"otigt (Listing \ref{sineplotfunctionlisting}). -\begin{lstlisting}[caption={Funktion, die die Daten plottet.}, label=sineplotfunctionlisting] -function plotSinewave(x_data, y_data, name) - % Plots x-data against y-data and sets the display name. - % Arguments: x_data, the x-data - % y_data, the y-data - % name, the displayname +\begin{lstlisting}[caption={Funktion zur graphischen Darstellung der Daten.}, label=sineplotfunctionlisting] +function plotFunction(x_data, y_data, name) +% Plots x-data against y-data and sets the display name. +% +% plotFunction(x_data, y_data, name) +% +% Arguments: +% x_data: vector of the x-data +% y_data: vector of the y-data +% name : the displayname plot(x_data, y_data, 'displayname', name) +end \end{lstlisting} \paragraph{III. Erstellen eines Skriptes zur Koordinierung} Die letzte Aufgabe ist die Koordinierung der Berechung und des Plottens f\"ur mehrere Amplituden. Das ist die klassische Aufgabe -f\"ur ein Skript. Auch hier gilt es einen ausdrucksvollen Name zu -finden. Da es keine Argumente und R\"uckgabewerte gibt, m\"ussen die -ben\"otigten Informationen direkt in dem Skript defniniert werden. Es -werden ben\"otigt: ein Vektor f\"ur die Amplituden, je eine Variable -f\"ur die gew\"unschte Frequenz, die maximale Zeit auf der x-Achse und -die zeitliche Aufl\"osung. Das Skript \"offnet schlie{\ss}lich noch -eine neue Abbildung und setzt das \code{hold on} da nur das Skript +f\"ur ein \codeterm{Skript}. Auch hier gilt es einen ausdrucksvollen +Name zu finden. Da es keine Argumente und R\"uckgabewerte gibt, +m\"ussen die ben\"otigten Informationen direkt in dem Skript +defniniert werden. Es werden ben\"otigt: ein Vektor f\"ur die +Amplituden, je eine Variable f\"ur die gew\"unschte Frequenz, die +maximale Zeit auf der x-Achse und die zeitliche Aufl\"osung. Das +Skript \"offnet schlie{\ss}lich noch eine neue Abbildung mit +\code{figure()} und setzt das \code{hold on} da nur das Skript wei{\ss}, das mehr als ein Plot erzeugt werden soll. Das Skript ist in Listing \ref{sinesskriptlisting} dargestellt. -\begin{lstlisting}[caption={Kontrollskript, das die Berechnung und plotting koordiniert.}, label=sinesskriptlisting] +\begin{lstlisting}[caption={Kontrollskript zur Koordination von Berechnung und graphischer Darstellung.},label=sinesskriptlisting] amplitudes = 0.25:0.25:1.25; -frequency = 2; -t_max = 10; +frequency = 2.0; +t_max = 10.0; t_step = 0.01; - + figure() hold on - for i = 1:length(amplitudes) - [x_data, y_data] = calculateSinewave(frequency, amplitudes(i), ... - t_max, t_step); - plotSinewave(x_data, y_data, sprintf('freq: %5.2f, ampl: %5.2f',... - frequency, amplitudes(i))) + [x_data, y_data] = sinewave(frequency, amplitudes(i), ... + t_max, t_step); + plotFunction(x_data, y_data, sprintf('freq: %5.2f, ampl: %5.2f',... + frequency, amplitudes(i))) end +hold off legend('show') \end{lstlisting} \begin{exercise}{plotMultipleSinewaves.m}{} - Erweitert das Programm so, dass auch ein Satz von Frequenzen benutzt - wird. + Erweiter das Programm so, dass die Sinusse f\"ur einen Satz von + Frequenzen geplottet wird. + \pagebreak[4] \end{exercise} \subsection{Fazit} @@ -1356,7 +1518,7 @@ Die vorangegangene Aussagen klingen, als ob Skripte zu verteufeln w\"aren und und vermieden werden sollten. Dem ist nicht so. In Wahrheit sind sie daf\"ur gemacht, Hand in Hand mit den Funktionen ein Problem zu l\"osen. W\"ahrend die Funktionen relativ -kleine ``verdauliche'' Teilprobleme l\"osen. Sind die Skripte daf\"ur +kleine ``verdauliche'' Teilprobleme l\"osen, sind Skripte daf\"ur gemacht den Rahmen zu bilden und den Ablauf zu koordinieren (Abbildung \ref{programlayoutfig}). diff --git a/programmingstyle/lecture/Makefile b/programmingstyle/lecture/Makefile index 463f202..4c7aa7c 100644 --- a/programmingstyle/lecture/Makefile +++ b/programmingstyle/lecture/Makefile @@ -1,32 +1,12 @@ BASENAME=programmingstyle -PYFILES=$(wildcard *.py) -PYPDFFILES=$(PYFILES:.py=.pdf) - all : pdf -# script: -pdf : $(BASENAME)-chapter.pdf - -$(BASENAME)-chapter.pdf : $(BASENAME)-chapter.tex $(BASENAME).tex $(PYPDFFILES) ../../header.tex - CHAPTER=$$(( $$(sed -n -e '/contentsline {chapter}/{s/.*numberline {\([0123456789]*\)}.*/\1/; p}' $(BASENAME).aux) - 1 )); \ - PAGE=$$(sed -n -e '/contentsline {chapter}/{s/.*numberline {.*}.*}{\(.*\)}{chapter.*/\1/; p}' $(BASENAME).aux); \ - sed -i -e "s/setcounter{page}{.*}/setcounter{page}{$$PAGE}/; s/setcounter{chapter}{.*}/setcounter{chapter}{$$CHAPTER}/" $(BASENAME)-chapter.tex - pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex -interaction=scrollmode $< || true - -$(PYPDFFILES) : %.pdf : %.py - python $< +include ../../chapter.mk -clean : - rm -f *~ - rm -f $(BASENAME).aux $(BASENAME).log - rm -f $(BASENAME)-chapter.aux $(BASENAME)-chapter.log $(BASENAME)-chapter.out - rm -f $(PYPDFFILES) $(GPTTEXFILES) - -cleanall : clean - rm -f $(BASENAME)-chapter.pdf - -watchpdf : - while true; do ! make -q pdf && make pdf; sleep 0.5; done +# script: +pdf : chapter +clean : cleanchapter +cleanall : clean cleanchapter diff --git a/programmingstyle/lecture/programmingstyle-chapter.tex b/programmingstyle/lecture/programmingstyle-chapter.tex index d82204d..58fddce 100644 --- a/programmingstyle/lecture/programmingstyle-chapter.tex +++ b/programmingstyle/lecture/programmingstyle-chapter.tex @@ -5,8 +5,10 @@ \lstset{inputpath=../code} \graphicspath{{figures/}} -\setcounter{page}{57} -\setcounter{chapter}{2} +\typein[\pagenumber]{Number of first page} +\typein[\chapternumber]{Chapter number} +\setcounter{page}{\pagenumber} +\setcounter{chapter}{\chapternumber} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/programmingstyle/lecture/programmingstyle.tex b/programmingstyle/lecture/programmingstyle.tex index 06b4437..abf600f 100644 --- a/programmingstyle/lecture/programmingstyle.tex +++ b/programmingstyle/lecture/programmingstyle.tex @@ -1,19 +1,25 @@ \chapter{\tr{Programming style}{Programmierstil}} +\shortquote{Any code of your own that you haven't looked at for six or + more months might as well have been written by someone + else.}{Eagleson's law} + Guter Programmierstil ist keine Frage des guten Geschmacks sondern des Verst\"andnisses von Programmcode und ein Baustein in dem Bestreben wissenschaftlichen Erkenntnisgewinn reproduzierbar zu machen. Programme sollten so geschrieben und strukturiert sein, dass es sowohl -einem Au{\ss}enstehenden als auch einem selbst, nach ein paar Monaten, -leicht f\"allt den Programmablauf nachzuvollziehen und zu -verstehen. Saubere Programmierung zahlt sich aber in erster Linie -f\"ur den Verfasser eines Programmes aus. +einem Au{\ss}enstehenden als auch einem selbst --- nach ein paar +Wochen oder Monaten! --- leicht f\"allt den Programmablauf +nachzuvollziehen und zu verstehen. Saubere Programmierung zahlt sich +in erster Linie f\"ur einen selbst aus und macht es aber gleichzeitig +f\"ur andere Personen leichter, den Code nachzuvollziehen und zu +benutzen. Guter Programmierstil greift auf unterschiedlichen Ebenen an: \begin{enumerate} -\item Die Struktur von Programmen. +\item Die Dateistruktur von Programmen. \item Die Namensgebung von Skripten und Funktionen. \item Die Namensgebung f\"ur Variablen und Konstanten. \item Die Verwendung von Einr\"uckungen und Leerzeilen um Bl\"ocke im @@ -82,46 +88,45 @@ aktuellen Ordner nach passenden Dateien sucht (mehr Information zum (siehe Abbildung). Der \codeterm{Suchpfad} ist eine Liste von Ordnern in denen \matlab{} nach Funktionen und Skripten suchen soll. Die Suche nach der aufgerufenen Funktion wird dabei von oben - nach unten durchgef\"uhrt. Das heisst, dass es, bei - Namensgleichheit, eine Rolle spielen kann an welcher Stelle im + nach unten durchgef\"uhrt. Das heisst, dass es bei + Namensgleichheit eine Rolle spielen kann an welcher Stelle im Suchpfad der erste Treffer gefunden wird. Wichtig: \matlab{} sucht nicht rekursiv! Wenn die gew\"unschte Funktion in einem Unterordner des aktuellen Arbeitsverzeichnisses liegt, dieses aber nicht explizit im Suchpfad enthalten ist, so wird die Funktion nicht - gefunden werden. + gefunden. \vspace{2ex} - \includegraphics[width=0.75\textwidth]{search_path} + \includegraphics[width=0.9\textwidth]{search_path} \vspace{1.5ex} - Der Suchpfad kann sowohl \"uber die in der Abbildung gezeigte GUI - oder auch \"uber die Kommandozeile eingestellt werden. Die GUI - erlaubt Ordner aus dem Suchpfad zu entfernen, neue - Ordner (optional inklusive aller Unterordner) hinzuzuf\"ugen oder - die Reihenfolge der Pfade zu ver\"andern. - - Zum Wechseln des aktuelle Arbeitsverzeichnis wechseln wird das - Kommando \code{cd} verwendet. \code{which} zeigt an, in welchem Pfad - eine bestimmte Funktion gefunden wurde. Das aktuelle - Areitsverzeichnis wird durch den Aufruf \code{pwd} auf der - Kommandozeile ausgegeben. + Der Suchpfad kann sowohl \"uber die Kommandozeile mit dem Kommandos + \code{addpath()} und \code{userpath()} als auch\"uber die in der + Abbildung gezeigte GUI angezeigt und eingestellt werden. Die GUI + erlaubt Ordner aus dem Suchpfad zu entfernen, neue Ordner (optional + inklusive aller Unterordner) hinzuzuf\"ugen oder die Reihenfolge der + Pfade zu ver\"andern. + + Zum Wechseln des aktuellen Arbeitsverzeichnisses wird das Kommando + \code{cd} verwendet. \code{which} zeigt an, in welchem Pfad eine + bestimmte Funktion gefunden wurde. Das aktuelle Areitsverzeichnis + wird durch den Aufruf \code{pwd} auf der Kommandozeile ausgegeben. \end{ibox} \section{Namensgebung von Funktionen und Skripten} \matlab{} sucht Funktionen und Skripte ausschlie{\ss}lich anhand des -Namens. Dabei spielt die Gro{\ss}- und Kleinschreibung eine Rolle. Das -hei{\ss}t, dass die beiden Dateien \file{test\_funktion.m} und -\file{Test\_funktion.m} zwei unterschiedliche Funktionen benennen -k\"onnen. Diese Art der Variation des Namens ist nat\"urlich nicht -sinnvoll. Sie tr\"agt keine Information \"uber den Unterschied der -beiden Funktionen. Auch sagt der Name nahezu nichts \"uber den Zweck -der Funktion aus. +Namens. Dabei spielt die Gro{\ss}- und Kleinschreibung eine Rolle. Die +beiden Dateien \file{test\_funktion.m} und \file{Test\_Funktion.m} +zwei unterschiedliche Funktionen benennen k\"onnen. Diese Art der +Variation des Namens ist nat\"urlich nicht sinnvoll. Sie tr\"agt keine +Information \"uber den Unterschied der beiden Funktionen. Auch sagt +der Name nahezu nichts \"uber den Zweck der Funktion aus. Die Namensgebung f\"allt mitunter nicht leicht --- manchmal ist es sogar der schwierigste Aspekt des Programmierens! Ausdrucksstarke Namen zu finden lohnt sich aber. Ausdrucksstark bedeutet, dass sich -aus dem Namen ein R\"uckschluss auf den Zweck ziehen lassen sollte. +aus dem Namen R\"uckschl\"usse auf den Zweck ziehen lassen sollte. \begin{important}[Benennung von Funktionen und Skripten] Die Namen von Funktionen und Skripten sollten m\"oglichst viel \"uber @@ -136,10 +141,10 @@ die Namensgebung selbst keine weiteren Vorgaben. Allerdings folgt die Benennung der in \matlab{} vordefinierten Funktionen gewissen Mustern: \begin{itemize} \item Namen werden immer klein geschrieben. -\item Es werden gerne Abk\"urzungen eingesetzt (z.B. \code{xcorr} - f\"ur die Kreuzkorrelation oder \code{repmat} f\"ur ``repeat matrix'') +\item Es werden gerne Abk\"urzungen eingesetzt (z.B. \code{xcorr()} + f\"ur die Kreuzkorrelation oder \code{repmat()} f\"ur ``repeat matrix'') \item Funktionen, die zwischen Formaten konvertieren sind immer nach - dem Muster ``format2format'' (z.B. \code{num2str} f\"ur die + dem Muster ``format2format'' (z.B. \code{num2str()} f\"ur die Konvertierung ``number to string'', Umwandlung eines numerischen Wertes in einen Text) benannt. \end{itemize} @@ -158,24 +163,24 @@ F\"ur die Bennennung von Variablen und Konstanten gelten die gleichen Regeln wie f\"ur die Namen von Funktionen und Skripten. Die Maxime von gutem Programmierstil ist: \emph{``Programmcode muss lesbar sein.''}. Dabei helfen gute Namen ungemein. Auch wenn es schwer -f\"allt passende und nicht zu lange Namen zu finden, sollte einer gute -Namensgebung ernst genommen werden. +f\"allt passende und trotzdem nicht zu lange Namen zu finden, sollte +einer gute Namensgebung sehr ernst genommen werden. W\"ahrend die Namen von Funktionen und Skripten ihren Zweck beschreiben, sollten die Namen von Variablen ihren Inhalt beschreiben. Eine Variable, die die mittlere Anzahl von Aktionspotentialen speichert, k\"onnte also -\codeterm{average\_spike\_count} hei{\ss}en. Wenn die Variable nicht +\varcode{average\_spike\_count} hei{\ss}en. Wenn die Variable nicht nur einen sondern mehrere Werte aufnimmt, dann ist der Plural -angebracht (\codeterm{average\_spike\_counts}). +angebracht (\varcode{average\_spike\_counts}). -Die Laufvariablen von \code{for}-Schleifen werden oft nur \code{i}, -\code{j} oder \code{k} benannt und sollten aber die einzige Ausnahme +Die Laufvariablen von \code{for}-Schleifen werden oft nur \varcode{i}, +\varcode{j} oder \varcode{k} benannt und sollten aber die einzige Ausnahme bzgl. ausdrucksstarker Namensgebung bleiben. \begin{important}[Benennung von Variablen] Die Namen von Variablen sollten m\"oglichst viel \"uber ihren Inhalt - aussagen (\code{spike\_count} statt \code{x}). Gute Namen + aussagen (\varcode{spike\_count} statt \varcode{x}). Gute Namen f\"ur Variablen sind die beste Dokumentation. \end{important} @@ -223,7 +228,7 @@ end end \end{lstlisting} -\clearpage +\pagebreak[4] \begin{lstlisting}[label=cleancode, caption={\"Ubersichtliche Implementation des Random-walk.}] num_runs = 10; @@ -248,7 +253,7 @@ Kommentarzeilen werden in \matlab{} mit dem Prozentzeichen \code{\%} gekennzeichnet. Gezielt und sparsam eingesetzte Kommentare sind f\"ur das Verst\"andnis eines Programms sehr n\"utzlich. Am wichtigsten sind kurze Kommentare, die den Zweck und das Ziel eines Abschnitts im -Programm erl\"autern (z.B. \code{\% compute mean firing rate over all +Programm erl\"autern (z.B. \varcode{\% compute mean firing rate over all trials}). Viele und h\"aufige Kommentare k\"onnen in der Entwicklungsphase eines @@ -259,7 +264,7 @@ Zeilen sowieso weitestgehend selbsterkl\"arend sein. Die beste Dokumentation ist der Code selbst. Gut geschriebener Code mit ausdrucksstarken Variablen- und Funktionsnamen ben\"otigt keine Kommentare, um den Zweck einzelner Zeilen zu erkl\"aren. z.B. ist\\ -\code{ x = x + 2; \% add two to x}\\ +\varcode{ x = x + 2; \% add two to x}\\ ein v\"ollig unn\"otiger Kommentar. \begin{important}[Verwendung von Kommentaren] @@ -270,21 +275,29 @@ ein v\"ollig unn\"otiger Kommentar. \item Ein falscher Kommentar ist schlimmer als gar kein Kommentar! \item Kommentare m\"ussen gepflegt werden, sonst sind sie wertlos! \end{itemize} + \widequote{Good code is its own best documentation. As you're about to add + a comment, ask yourself, ``How can I improve the code so that this + comment isn't needed?'' Improve the code and then document it to + make it even clearer.}{Steve McConnell} \end{important} +\pagebreak[4] \section{Dokumentation von Funktionen} Bei allen vordefinierten \matlab{} Funktionen findet sich am Anfang eine Kommentarblock, der den Zweck der Funktion, die verschiedenen M\"oglichkeiten des Funktionsaufrufs und die Argumente und -R\"uckgabewerte beschreibt. Auch in eingenen Funktionen sind diese -Kommentare sehr hilfreich. Siehe Listing~\ref{localfunctions} f\"ur -ein Beispiel einer gut Dokumentierten Funktion. +R\"uckgabewerte beschreibt. Mit dem \code{help}- Befehl wird dieser +Kommentarblock angezeigt. Auch in eigenen Funktionen sind +diese Kommentare sehr wichtig. Siehe Listing~\ref{localfunctions} +f\"ur ein Beispiel einer gut dokumentierten Funktion. \begin{important}[Dokumentation von Funktionen] Funktionen m\"ussen unbedingt kommentiert werde! \begin{itemize} \item In wenigen Zeilen kurz den Zweck der Funktion beschreiben. + \item Den Funktionskopf nocheinmal hinschreiben, damit + klar ist, in welcher Reihenfolge Argumente \"ubergeben werden. \item F\"ur jedes Funktionsargument die Bedeutung, der erwartete Datentyp (Zahl, Vektor, Matrix, etc.), und eventuell die Einheit, in der die Zahlen erwartet werden (z.B. Sekunden). @@ -302,7 +315,7 @@ ob dieser Teil des Programms nicht in eine eigene Funktion ausgelagert werden sollte. Fast immer kann dies bejaht werden. Abschnitte nicht auszulagern f\"uhrt zu sehr langen -\codeterm{m-Files}, die leicht un\"ubersichtlich werden. Diese Art von +\codeterm{m-files}, die leicht un\"ubersichtlich werden. Diese Art von Code wird \codeterm{Spaghetticode} genannt. Es ist h\"ochste Zeit \"uber Auslagerung in Funktionen nachzudenken. @@ -318,25 +331,31 @@ Code wird \codeterm{Spaghetticode} genannt. Es ist h\"ochste Zeit \subsection{Lokale Funktionen und geschachtelte Funktionen} -Das Auslagern von Funktionalit\"at in eigene Funktionen f\"uhrt -dazu, dass eine F\"ulle von Dateien erzeugt wird, die die +Das Auslagern von Funktionalit\"at in eigene Funktionen f\"uhrt dazu, +dass eine F\"ulle von Dateien erzeugt wird, die die \"Ubersichtlichkeit nicht unbedingt erh\"oht. Wenn die auszulagernde -Funktionalit\"at an vielen Stellen ben\"otigt wird ist es -dennoch sinnvoll dies zu tun. Wenn nicht, dann bietet \matlab{} die -M\"oglichkeit sogenannte \codeterm{lokale Funktionen} oder auch -\codeterm{geschachtelte Funktionen} (\enterm{nested functions}) zu +Funktionalit\"at an vielen Stellen ben\"otigt wird ist es dennoch sehr +sinnvoll dies zu tun. Wenn Funktionen nur von einzelnen anderen +Funktionen verwendet werden, dann bietet \matlab{} die M\"oglichkeit +sogenannte \codeterm[Funktion!lokale]{lokale Funktionen} oder auch +\codeterm[Funktion!geschachtelte]{geschachtelte Funktionen} +(\enterm{nested functions}) in einer einzelnen Datei zu erstellen. Listing \ref{localfunctions} zeigt ein Beispiel f\"ur eine lokale Funktion. -\lstinputlisting[label=localfunctions, caption={\codeterm{Lokale Funktionen} erh\"ohen die Lesbarkeit sind aber nur innerhalb der definierenden Datei verf\"ugbar.}]{calculateSines.m} +\pagebreak[3] +\lstinputlisting[label=localfunctions, caption={Beispiel f\"ur den + Einsatz von lokalen Funktionen.}]{calculateSines.m} Lokale Funktionen existieren in der gleichen Datei und sind nur dort verf\"ugbar. Jede Funktion hat ihren eigenen G\"ultigkeitsbereich, das hei{\ss}t, dass Variablen aus den aufrufenden Funktionen nicht -sichtbar sind. Bei sogenannten \codeterm{geschachtelten Funktionen} -ist das anders. Diese werden innerhalb eines Funktionsk\"orpers -(zwischen den Schl\"usselworten \codeterm{function} und dem -\codeterm{end} definiert und k\"onnen auf alle Variablen der +sichtbar sind. + +Bei sogenannten \codeterm[Funktion!geschachtelte]{geschachtelten +Funktionen} ist das anders. Diese werden innerhalb eines +Funktionsk\"orpers (zwischen den Schl\"usselworten \code{function} und +dem \code{end} definiert und k\"onnen auf alle Variablen der ``Mutterfunktion'' zugreifen und diese auch ver\"andern. Folglich sollten sie nur mit Bedacht eingesetzt werden. @@ -403,8 +422,20 @@ diese sollten dann beachtet werden. Wiederholte Programmabschnitte sollten in Funktionen ausgelagert werden. Wenn diese nicht von globalem Interesse sind, kann mit -\codeterm{lokalen} oder \codeterm{geschachtelten Funktionen} die -\"Ubersichtlichkeit erh\"oht werden. +\codeterm[Funktion!lokale]{lokalen} oder +\codeterm[Funktion!geschachtelte]{geschachtelten + Funktionen} die \"Ubersichtlichkeit erh\"oht werden. + +Es lohnt sich auf den eigenen Programmierstil zu +achten!\footnote{Buchtip: Robert C. Martin: \textit{Clean Code: A + Handbook of Agile Software Craftmanship}, Prentice Hall} + +\shortquote{Programs must be written for people to read, and only + incidentally for machines to execute.}{Abelson / Sussman} + +\shortquote{Any fool can write code that a computer can + understand. Good programmers write code that humans can + understand.}{Martin Fowler} -\noindent Es lohnt sich auf den eigenen Programmierstil zu achten!\footnote{Literatur zum Programmierstil: z.B. Robert C. Martin: \textit{Clean - Code: A Handbook of Agile Software Craftmanship}, Prentice Hall} +\shortquote{First, solve the problem. Then, write the code.}{John + Johnson} diff --git a/regression/code/errorGradient.m b/regression/code/errorGradient.m index ac484ec..a24367f 100644 --- a/regression/code/errorGradient.m +++ b/regression/code/errorGradient.m @@ -1,5 +1,4 @@ load('lin_regression.mat') - ms = -1:0.5:5; ns = -10:1:10; @@ -27,4 +26,4 @@ ylabel('Intercept b') zlabel('Mean squared error') set(gcf, 'paperunits', 'centimeters', 'papersize', [15, 10.5], ... 'paperposition', [0., 0., 15, 10.5]) -saveas(gcf, 'error_gradient', 'pdf') \ No newline at end of file +saveas(gcf, 'error_gradient', 'pdf') diff --git a/regression/code/lsqGradient.m b/regression/code/lsqGradient.m index 4041d9e..39bfbbb 100644 --- a/regression/code/lsqGradient.m +++ b/regression/code/lsqGradient.m @@ -7,11 +7,8 @@ function gradient = lsqGradient(parameter, x, y) % y, vector of the corresponding measured output values % % Returns: the gradient as a vector with two elements - h = 1e-6; % stepsize for derivatives - partial_m = (lsqError([parameter(1)+h, parameter(2)], x, y) - lsqError(parameter, x, y))/ h; partial_n = (lsqError([parameter(1), parameter(2)+h], x, y) - lsqError(parameter, x, y))/ h; - gradient = [partial_m, partial_n]; end diff --git a/regression/lecture/Makefile b/regression/lecture/Makefile index 1f7271d..0347e31 100644 --- a/regression/lecture/Makefile +++ b/regression/lecture/Makefile @@ -1,32 +1,12 @@ BASENAME=regression -PYFILES=$(wildcard *.py) -PYPDFFILES=$(PYFILES:.py=.pdf) - all : pdf -# script: -pdf : $(BASENAME)-chapter.pdf - -$(BASENAME)-chapter.pdf : $(BASENAME)-chapter.tex $(BASENAME).tex $(PYPDFFILES) - CHAPTER=$$(( $$(sed -n -e '/contentsline {chapter}/{s/.*numberline {\([0123456789]*\)}.*/\1/; p}' $(BASENAME).aux) - 1 )); \ - PAGE=$$(sed -n -e '/contentsline {chapter}/{s/.*numberline {.*}.*}{\(.*\)}{chapter.*/\1/; p}' $(BASENAME).aux); \ - sed -i -e "s/setcounter{page}{.*}/setcounter{page}{$$PAGE}/; s/setcounter{chapter}{.*}/setcounter{chapter}{$$CHAPTER}/" $(BASENAME)-chapter.tex - pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex -interaction=scrollmode $< || true - -$(PYPDFFILES) : %.pdf : %.py - python $< +include ../../chapter.mk -clean : - rm -f *~ - rm -f $(BASENAME).aux $(BASENAME).log - rm -f $(BASENAME)-chapter.aux $(BASENAME)-chapter.log $(BASENAME)-chapter.out - rm -f $(PYPDFFILES) $(GPTTEXFILES) - -cleanall : clean - rm -f $(BASENAME)-chapter.pdf - -watchpdf : - while true; do ! make -q pdf && make pdf; sleep 0.5; done +# script: +pdf : chapter +clean : cleanchapter +cleanall : clean cleanchapter diff --git a/regression/lecture/regression-chapter.tex b/regression/lecture/regression-chapter.tex index 0df5e2b..0c37634 100644 --- a/regression/lecture/regression-chapter.tex +++ b/regression/lecture/regression-chapter.tex @@ -5,8 +5,10 @@ \lstset{inputpath=../code} \graphicspath{{figures/}} -\setcounter{page}{89} -\setcounter{chapter}{5} +\typein[\pagenumber]{Number of first page} +\typein[\chapternumber]{Chapter number} +\setcounter{page}{\pagenumber} +\setcounter{chapter}{\chapternumber} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/regression/lecture/regression.tex b/regression/lecture/regression.tex index 4cae7bd..cdfeb8c 100644 --- a/regression/lecture/regression.tex +++ b/regression/lecture/regression.tex @@ -68,9 +68,9 @@ Summe k\"onnen wir genauso gut fordern, dass der \emph{mittlere} Abstand der Menge der $N$ Datenpaare $(x_i, y_i)$ gegeben die Modellvorhersagen $y_i^{est}$ klein sein soll. -Am h\"aufigsten wird jedoch bei einem Kurvenfit der \determ{mittlere - quadratische Abstand} (\enterm{mean squared distance} oder -\enterm{mean squared error}) +Am h\"aufigsten wird jedoch bei einem Kurvenfit der \determ[mittlerer +quadratische Abstand]{mittlere quadratische Abstand} (\enterm{mean + squared distance} oder \enterm{mean squared error}) \begin{equation} \label{meansquarederror} f_{mse}(\{(x_i, y_i)\}|\{y^{est}_i\}) = \frac{1}{N} \sum_{i=1}^N (y_i - y^{est}_i)^2 @@ -81,10 +81,11 @@ quadratischen Abst\"ande immer positiv, unabh\"angig ob die Datenwerte zus\"atzlich gro{\ss}e Abst\"ande st\"arker gewichtet. \begin{exercise}{meanSquareError.m}{}\label{mseexercise}% - Schreibe eine Funktion \code{meanSquareError}, die die mittlere + Schreibe eine Funktion \code{meanSquareError()}, die die mittlere quadratische Abweichung zwischen einem Vektor mit den beobachteten Werten $y$ und einem Vektor mit den entsprechenden Vorhersagen - $y^{est}$ berechnet.\newpage + $y^{est}$ berechnet. + \pagebreak[4] \end{exercise} @@ -130,20 +131,21 @@ f\"ur die Zielfunktion den mittleren quadratischen Abstand der Datenpaare $(x_i, y_i)$ gegeben die Parameterwerte $m$ und $b$ der Geradengleichung. Ziel des Kurvenfits ist es, die Werte f\"ur $m$ und $b$ so zu optimieren, dass -der Fehler \eqnref{mseline} minimal wird. +der Fehler \eqnref{mseline} minimal wird (\determ{Methode der + kleinsten Quadrate}, \enterm{least square error}). \begin{exercise}{lsqError.m}{} Implementiere die Zielfunktion f\"ur die Optimierung mit der - linearen Geradengleichung als Funktion \code{lsqError}. + linearen Geradengleichung als Funktion \code{lsqError()}. \begin{itemize} \item Die Funktion \"ubernimmt drei Argumente: Das erste Argument - ist ein 2-elementiger Vektor, der die Parameter \code{m} und - \code{b} enth\"alt. Das zweite ist ein Vektor mit den $x$-Werten, + ist ein 2-elementiger Vektor, der die Parameter \varcode{m} und + \varcode{b} enth\"alt. Das zweite ist ein Vektor mit den $x$-Werten, an denen gemessen wurde, und das dritte ein Vektor mit den zugeh\"origen $y$-Werten. \item Die Funktion gibt als Ergebniss den Fehler als mittleren quadratischen Abstand \eqnref{mseline} zur\"uck. - \item Die Funktion soll die Funktion \code{meanSquareError} der + \item Die Funktion soll die Funktion \code{meanSquareError()} der vorherigen \"Ubung benutzen. \end{itemize} \end{exercise} @@ -160,7 +162,7 @@ $f_{cost}(m,b)$, die die beiden Variablen $m$ und $b$ auf einen Fehlerwert abbildet. Es gibt also f\"ur jeden Punkt in der sogenannten -\emph{Fehlerfl\"ache} einen Fehlerwert. In diesem Beispiel eines +\determ{Fehlerfl\"ache} einen Fehlerwert. In diesem Beispiel eines 2-dimensionalen Problems (zwei freie Parameter) kann die Fehlerfl\"ache graphisch durch einen 3-d \enterm{surface-plot} dargestellt werden. Dabei werden auf der $x$- und der $y$-Achse die @@ -181,12 +183,12 @@ beiden Parameter und auf der $z$-Achse der Fehlerwert aufgetragen \begin{exercise}{errorSurface.m}{}\label{errorsurfaceexercise}% Lade den Datensatz \textit{lin\_regression.mat} in den Workspace (20 - Datenpaare in den Vektoren \code{x} und \code{y}). Schreibe ein Skript + Datenpaare in den Vektoren \varcode{x} und \varcode{y}). Schreibe ein Skript \file{errorSurface.m}, dass den Fehler, berechnet als mittleren quadratischen Abstand zwischen den Daten und einer Geraden mit Steigung $m$ und $y$-Achsenabschnitt $b$, in Abh\"angigkeit von $m$ und $b$ als surface plot darstellt (siehe Hilfe f\"ur die - \code{surf} Funktion). + \code{surf()} Funktion). \end{exercise} An der Fehlerfl\"ache kann direkt erkannt werden, bei welcher @@ -278,7 +280,7 @@ Kostenfunktion verwenden. Da die Kugel immer entlang des steilsten Gef\"alles rollt, ben\"otigen wir Information \"uber die Richtung des Gef\"alles an der jeweils aktuellen Position. -Der Gradient (Box~\ref{partialderivativebox}) der Kostenfunktion +Der \determ{Gradient} (Box~\ref{partialderivativebox}) der Kostenfunktion \[ \nabla f_{cost}(m,b) = \left( \frac{\partial e(m,b)}{\partial m}, \frac{\partial f(m,b)}{\partial b} \right) \] bzgl. der beiden Parameter $m$ und $b$ der Geradengleichung ist ein Vektor, der in @@ -299,7 +301,7 @@ partielle Ableitung nach $m$ durch \begin{figure}[t] \includegraphics[width=0.75\columnwidth]{error_gradient} - \titlecaption{Der Gradienten der Fehlerfl\"ache.} + \titlecaption{Gradient der Fehlerfl\"ache.} {Jeder Pfeil zeigt die Richtung und die Steigung f\"ur verschiedene Parameterkombination aus Steigung und $y$-Achsenabschnitt an. Die Kontourlinien im Hintergrund @@ -310,7 +312,7 @@ partielle Ableitung nach $m$ durch \end{figure} \begin{exercise}{lsqGradient.m}{}\label{gradientexercise}% - Implementiere eine Funktion \code{lsqGradient}, die den + Implementiere eine Funktion \code{lsqGradient()}, die den Parametersatz $(m, b)$ der Geradengleichung als 2-elementigen Vektor sowie die $x$- und $y$-Werte der Messdaten als Argumente entgegennimmt und den Gradienten an dieser Stelle zur\"uckgibt. @@ -321,17 +323,17 @@ partielle Ableitung nach $m$ durch um f\"ur jede Parameterkombination aus der Fehlerfl\"ache (\"Ubung \ref{errorsurfaceexercise}) auch den Gradienten zu berechnen und darzustellen. Vektoren im Raum k\"onnen mithilfe der - Funktion \code{quiver} geplottet werden. + Funktion \code{quiver()} geplottet werden. \end{exercise} \section{Gradientenabstieg} -Zu guter Letzt muss nur noch der Gradientenabstieg implementiert +Zu guter Letzt muss nur noch der \determ{Gradientenabstieg} implementiert werden. Die daf\"ur ben\"otigten Zutaten haben wir aus den vorangegangenen \"Ubungen bereits vorbereitet. Wir brauchen: 1. Die Fehlerfunktion -(\code{meanSquareError.m}), 2. die Zielfunktion (\code{lsqError.m}) -und 3. den Gradienten (\code{lsqGradient.m}). Der Algorithmus +(\code{meanSquareError()}), 2. die Zielfunktion (\code{lsqError()}) +und 3. den Gradienten (\code{lsqGradient()}). Der Algorithmus f\"ur den Abstieg lautet: \begin{enumerate} \item Starte mit einer beliebigen Parameterkombination $p_0 = (m_0, @@ -342,7 +344,7 @@ f\"ur den Abstieg lautet: abbrechen. Wir suchen ja das Minimum, bei dem der Gradient gleich Null ist. Da aus numerischen Gr\"unden der Gradient nie exakt Null werden wird, k\"onnen wir nur fordern, dass er hinreichend klein - wird (z.B. \code{norm(gradient) < 0.1}). + wird (z.B. \varcode{norm(gradient) < 0.1}). \item \label{gradientstep} Gehe einen kleinen Schritt ($\epsilon = 0.01$) in die entgegensetzte Richtung des Gradienten: \[p_{i+1} = p_i - \epsilon \cdot \nabla f_{cost}(m_i, b_i)\] @@ -367,7 +369,7 @@ Punkte in Abbildung \ref{gradientdescentfig} gro{\ss}. \begin{exercise}{gradientDescent.m}{} Implementiere den Gradientenabstieg f\"ur das Problem der Parameteranpassung der linearen Geradengleichung an die Messdaten in - der Datei \code{lin\_regression.mat}. + der Datei \file{lin\_regression.mat}. \begin{enumerate} \item Merke Dir f\"ur jeden Schritt den Fehler zwischen Modellvorhersage und Daten. @@ -388,7 +390,7 @@ mittlere quadratische Abstand als Kostenfunktion in der Tat ein einziges klar definiertes Minimum. Wie wir im n\"achsten Kapitel sehen werden, kann die Position des Minimums bei Geradengleichungen sogar analytisch bestimmt werden, der Gradientenabstieg w\"are also -gar nicht n\"otig \matlabfun{polyfit}. +gar nicht n\"otig \matlabfun{polyfit()}. F\"ur Parameter, die nichtlinear in einer Funktion enthalten sind, wie z.B. die Rate $\lambda$ als Parameter in der @@ -401,9 +403,9 @@ Gradientenabstiegs auf vielf\"altige Weise verbessert werden. z.B. kann die Schrittweite an die St\"arke des Gradienten angepasst werden. Diese numerischen Tricks sind in bereits vorhandenen Funktionen implementiert. Allgemeine Funktionen sind f\"ur beliebige -Kostenfunktionen gemacht \matlabfun{fminsearch}, w\"ahrend spezielle +Kostenfunktionen gemacht \matlabfun{fminsearch()}, w\"ahrend spezielle Funktionen z.B. f\"ur die Minimierung des quadratischen Abstands bei -einem Kurvenfit angeboten werden \matlabfun{lsqcurvefit}. +einem Kurvenfit angeboten werden \matlabfun{lsqcurvefit()}. \begin{important}[Achtung Nebenminima!] Das Finden des globalen Minimums ist leider nur selten so leicht wie diff --git a/scientificcomputing-script.tex b/scientificcomputing-script.tex index c1a5a92..f75b39d 100644 --- a/scientificcomputing-script.tex +++ b/scientificcomputing-script.tex @@ -8,14 +8,20 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{document} +\hypersetup{pageanchor=false} \maketitle +\hypersetup{pageanchor=true} + +\frontmatter \tableofcontents \listoffigures \lstlistoflistings \listofexercisefs \listofiboxfs -%\listofimportantfs + + +\mainmatter %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \part{Grundlagen des Programmierens} @@ -67,9 +73,14 @@ %\chapter{Cheat-Sheet} -\addcontentsline{toc}{chapter}{Fachbegriffe} +\backmatter + +%%%% indices: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \printindex[term] -\addcontentsline{toc}{chapter}{Code} + +\printindex[enterm] + +%\setindexprenote{Some explanations.} \printindex[code] \end{document} diff --git a/statistics/code/checkmymedian.m b/statistics/code/checkmymedian.m index 14cbe0b..d2d101d 100644 --- a/statistics/code/checkmymedian.m +++ b/statistics/code/checkmymedian.m @@ -1,9 +1,9 @@ % check whether the median returned by mymedian % really separates a vector into two halfs -for i = 1:140 % loop over different length - for k = 1:10 % try several times - a = randn( i, 1 ); % generate some data - m = mymedian( a ); % compute median +for i = 1:140 % loop over different length + for k = 1:10 % try several times + a = randn( i, 1 ); % generate some data + m = mymedian( a ); % compute median if length( a(a>m) ) ~= length( a(a=x1)&(x=x1)&(r