mirror of
https://gitlab.rlp.net/pgp/pgp1-python-einfuehrung
synced 2024-11-16 13:48:11 +00:00
2158 lines
73 KiB
Text
2158 lines
73 KiB
Text
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Kapitel 1. Einstieg in die Welt von Python:\n",
|
||
"\n",
|
||
"In unserer heutigen digitalen Welt sind Computer nicht mehr aus unserem Alltag wegzudenken. Ob in der Finanzwelt, Industrie aber auch in der Wissenschaft erledigen Computer in Sekundenschnelle komplizierte Rechnungen und helfen dem Anwender komplizierte Sachverhalte vereinfacht wieder zu geben. Daher empfiehlt es sich insbesondere als Physiker zumindest die Grundlagen einer beliebigen Programmiersprache zu beherrschen. \n",
|
||
"\n",
|
||
"Im folgenden werden wir uns gemeinsam die Grundzüge der Programmiersprache **Python** erarbeiten. Ein besonderes Augenmerk liegt hierbei auf den verschiedenen Herausforderungen die das analysieren von Experimentdaten mit sich bringt. Um euch bestens auf die Anforderungen im **physikalische Grundpraktikum (PGP)** vorzubereiten lernen wir im Folgenden wie man:\n",
|
||
"\n",
|
||
"* einfache Rechnungen mit Python durchführt\n",
|
||
"* \"Mathematische\" Funktionen definiert\n",
|
||
"* Funktionen auf größere Zahlenmengen anwendet\n",
|
||
"* Daten in Form von Graphen richtig darstellt\n",
|
||
"* eine Ausgleichsgerade von Datenpunkten berechnen kann.\n",
|
||
"\n",
|
||
"Damit ihr das neu gelernte Wissen direkt vertiefen könnt, wird dieses Notebook an verschiedenen Stellen kleinere Aufgaben für euch bereit halten."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Grundlagen zu Python bzw. Jupyter Notebooks:\n",
|
||
"\n",
|
||
"Bevor wir mit dem eigentlichen programmieren beginnen wollen müssen wir uns jedoch erst einmal mit unserem so genannten Interpreter (**Jupyter Notebook**) vertraut machen. Bei der Programmiersprache **Python** handelt es sich um eine so genannte **Interpretersprache**. Dies bedeutet, dass eingegebene Befehle, ähnlich wie bei einem Taschenrechner, direkt ausgeführt werden.\n",
|
||
"\n",
|
||
"Zum Beispiel beim berechnen von: "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:44.802747Z",
|
||
"start_time": "2019-09-30T05:49:44.777288Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"3 + 2"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Unser Interpreter, das **Jupyter Notebook**, stellt hierbei einen komfortable Interpreterumgebung dar. Diese erlaubt es uns neben **Code**-Zellen auch Texte und Formeln in so genannten **Markdown**-Zellen darzustellen. Hierbei existiert eine ganze Bandbreite an Formatierungsmöglichkeiten. Zum Beispiel:\n",
|
||
"\n",
|
||
"**Überschriften:**\n",
|
||
"\n",
|
||
"# Level 1.\n",
|
||
"## Level 2.\n",
|
||
"### Level 3.\n",
|
||
"\n",
|
||
"**Aufzählungen: **\n",
|
||
"\n",
|
||
"* Mit normalen\n",
|
||
"* Aufzählungspunkten\n",
|
||
" 1. oder \n",
|
||
" 2. Numerierungen\n",
|
||
" * Auf unterschiedlichen\n",
|
||
" 1. Ebenen\n",
|
||
"\n",
|
||
"**Schriftarten:**\n",
|
||
"\n",
|
||
"**Fett**\n",
|
||
"\n",
|
||
"*Italic (Kursive)*\n",
|
||
"\n",
|
||
"`True type`\n",
|
||
"\n",
|
||
"bzw. Syntax highlighting\n",
|
||
"\n",
|
||
"```python \n",
|
||
"def EasyFunc(x):\n",
|
||
" return 2 * x\n",
|
||
"```\n",
|
||
"\n",
|
||
"**Formeln mit Hilfe des Latex-Syntax:**\n",
|
||
"\n",
|
||
"$ f(x) = \\int\\limits_0^\\infty e^{-x} \\, dx $\n",
|
||
"\n",
|
||
"(Latex werdet ihr beim F-Praktikum kennen lernen)\n",
|
||
"\n",
|
||
"\n",
|
||
"**Bilder:**\n",
|
||
"\n",
|
||
"![The Python logo](https://www.python.org/static/community_logos/python-powered-w-200x80.png \"Das Python Logo\")\n",
|
||
"\n",
|
||
"\n",
|
||
"Darüber hinaus bietet uns das Jupyter Notebook noch diverse weitere Optionen an welche unseren harten Alltag vereinfachen. "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Neben diesen nützlichen Befehlemm gibt es noch weitere tolle Kürzel wie zum Beispiel:\n",
|
||
"* **D + D** um eine Zelle zu **löschen** \n",
|
||
"* **Y** verwandelt eine aktuelle **Markdown**-Zelle in eine **Code**-Zelle\n",
|
||
"* **Strg** + **Shift** + **Minus** Splittet eine Zelle an der Position eures Cursors \n",
|
||
"* **F** für \"Find and Replace\" (nützlich wenn ihr zum Beispiel ein Variablennamen austauschen wollt)\n",
|
||
"* **I** + **I** Um den *\"Kernel\"* zu stoppen (wichtig falls ihr mal eine unendliche LOOP gebaut habt)\n",
|
||
"\n",
|
||
"Des weiteren könnt ihr [hier](https://www.cheatography.com/weidadeyue/cheat-sheets/jupyter-notebook/) eine Auflistung weiterer Jupyter-Befehle finden."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Python als Taschenrechner:\n",
|
||
"\n",
|
||
"Neben dem einfachen summieren zweier Zahlen ermöglicht uns Python natürlich auch das verwendet weiterer Operatoren. Hierbei haben die Operatoren ähnlich wie in der Mathematik gewisse Prioritäten (*Punkt vor Strich*). Die Operation mit dem niedrigeren Prioritätswert wird zu erst ausgeführt. \n",
|
||
"\n",
|
||
"<table border=\"1\" class=\"docutils\">\n",
|
||
"<colgroup>\n",
|
||
"<col width=\"25%\">\n",
|
||
"<col width=\"40%\">\n",
|
||
"<col width=\"11%\">\n",
|
||
"<col width=\"24%\">\n",
|
||
"</colgroup>\n",
|
||
"<thead valign=\"bottom\">\n",
|
||
"<tr class=\"row-odd\"><th class=\"head\">Operator</th>\n",
|
||
"<th class=\"head\">Ergebnis</th>\n",
|
||
"<th class=\"head\">Priorität</th>\n",
|
||
"</tr>\n",
|
||
"</thead>\n",
|
||
"<tbody valign=\"top\">\n",
|
||
"<tr class=\"row-even\"><td><tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">+</span> <span class=\"pre\">y</span></tt></td>\n",
|
||
"<td>Die Summe von <em>x</em> und <em>y</em></td>\n",
|
||
"<td>6</td>\n",
|
||
"</tr>\n",
|
||
"<tr class=\"row-odd\"><td><tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">-</span> <span class=\"pre\">y</span></tt></td>\n",
|
||
"<td>Differenz von <em>x</em> und <em>y</em></td>\n",
|
||
"<td>5</td>\n",
|
||
"</tr>\n",
|
||
"<tr class=\"row-even\"><td><tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">*</span> <span class=\"pre\">y</span></tt></td>\n",
|
||
"<td>Produkt von <em>x</em> und <em>y</em></td>\n",
|
||
"<td>4</td>\n",
|
||
"</tr>\n",
|
||
"<tr class=\"row-odd\"><td><tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">/</span> <span class=\"pre\">y</span></tt></td>\n",
|
||
"<td>Quotient von <em>x</em> und <em>y</em></td>\n",
|
||
"<td>3</td>\n",
|
||
"</tr>\n",
|
||
"<tr class=\"row-odd\"><td><tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">%</span> <span class=\"pre\">y</span></tt></td>\n",
|
||
"<td>Rest von <tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">/</span> <span class=\"pre\">y</span></tt></td>\n",
|
||
"<td>2</td>\n",
|
||
"</tr>\n",
|
||
"<tr class=\"row-odd\"><td><tt class=\"docutils literal\"><span class=\"pre\">x</span> <span class=\"pre\">**</span> <span class=\"pre\">y</span></tt></td>\n",
|
||
"<td><em>x</em> bei der Potenz von <em>y</em></td>\n",
|
||
"<td>1</td>\n",
|
||
"</tr>\n",
|
||
"</tbody>\n",
|
||
"</table>\n",
|
||
"\n",
|
||
"Hier ein paar Beispiele:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:44.835098Z",
|
||
"start_time": "2019-09-30T05:49:44.820977Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"2 / 3 - 2"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:44.854156Z",
|
||
"start_time": "2019-09-30T05:49:44.838216Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"3**2 * 2 - 8 "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:44.869444Z",
|
||
"start_time": "2019-09-30T05:49:44.856320Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"3**2**2"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Wie in der Mathematik können wir auch bei Python Klammern verwenden um die Rechenreihenfolge zu ändern:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:44.885272Z",
|
||
"start_time": "2019-09-30T05:49:44.871522Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"3**2 * 2 - 8 "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:44.902760Z",
|
||
"start_time": "2019-09-30T05:49:44.887994Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"3**2 * (2 - 8 ) "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Um unsere Rechnungen besser zu Strukturieren können wir Zahlen auch Variablen zu ordnen. Hierzu verwenden wir das Gleichheitszeichen um einer Variablen (*links*) einem Wert (*rechts*) zu zuordnen."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:44.919994Z",
|
||
"start_time": "2019-09-30T05:49:44.905749Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"a = 5"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:44.936549Z",
|
||
"start_time": "2019-09-30T05:49:44.922748Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"a"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:44.951900Z",
|
||
"start_time": "2019-09-30T05:49:44.939383Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"variable = 2"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:44.968598Z",
|
||
"start_time": "2019-09-30T05:49:44.953574Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"a * variable"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Bei der Definition von Variablen ist es wichtig auf die Reihenfolge zu achten. Dies gilt nicht nur innerhalb einer Zelle..."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:44.986417Z",
|
||
"start_time": "2019-09-30T05:49:44.970615Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"a = 4\n",
|
||
"b = 3\n",
|
||
"a = 7\n",
|
||
"\n",
|
||
"a * b"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"... sondern auch für die Reihenfolge in der die Code-Zellen ausgeführt werden (Angezeigt durch In []:). "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.001728Z",
|
||
"start_time": "2019-09-30T05:49:44.989743Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"a = 7"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.017219Z",
|
||
"start_time": "2019-09-30T05:49:45.003744Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"a = 4"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.034800Z",
|
||
"start_time": "2019-09-30T05:49:45.019707Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"a * b"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Ein weiterer Vorteil (bzw. auch Nachteil) ist, dass Python eine so genannte *dynamische* Datentypenvergabe nutzt. Um besser zu verstehen was dies bedeutet gucken wir uns das Nachfolgende Beispiel an. "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.050615Z",
|
||
"start_time": "2019-09-30T05:49:45.036793Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"a = 2\n",
|
||
"b = 5\n",
|
||
"c = a * b\n",
|
||
"c"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.067030Z",
|
||
"start_time": "2019-09-30T05:49:45.052096Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"a = 2\n",
|
||
"b = 5.0\n",
|
||
"c = a * b\n",
|
||
"c "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"In der oberen Zelle ist **c** vom Datentyp `int` (*Integer*) was einer Ganzen Zahl entspricht. In der unteren Zelle jedoch ist **c** vom Datentype `float` (*Floating Point Number*) also eine Gleitkommazahl. Dies liegt daran das wir in der unteren Zelle **b** als Gleitkommazahl definiert haben. Um uns Arbeit abzunehmen hat Python für uns im Hintergrund dynamisch entschieden, dass somit **c** ebenfalls vom type `float` sein muss. \n",
|
||
"\n",
|
||
"Neben den primitiven Datentypen `float` und `int` gibt es noch die wichtigen Datentypen `str` (*string*) was einer Zeichenkette entspricht (z.B. Buchstaben, Wörter und Sätze), `complex` für Komplexe Zahlen und `bool` für Wahrheitswerte. Was genau Wahrheitswerte sind und für was diese verwendet werden, werdet ihr noch im **PGP2** lernen. \n",
|
||
"\n",
|
||
"Für das **PGP1** sind erstmal nur die typen `int`, `float` und `str` von Bedeutung."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Zeichenketten.\n",
|
||
"\n",
|
||
"Wie eben bereits erwähnt gibt es neben den Zahlen Datentypen `int`, `float` und `complex` auch noch den Datentyp einer Zeichenkette `str`. Zeichenketten werden in Programmiersprachen vielseitig verwendet z.B. bei einer Nutzereingabe (wie dem Passwort), Dateiname bei einer Installation, oder bei Textrückgaben von Programmen. Letzteres haben wir bereits in Aufgabe 2 mit Hilfe der `print`-Funktion gesehen.\n",
|
||
"\n",
|
||
"Für das PGP-1 wollen wir uns zunächst darauf beschränken, dass Zeichenketten in so genannten **Formatstrings** dazu genutzt werden können schönere `print` Rückgaben zu erzeugen bzw. wir mit Zeichnketten Achsenbeschriftungen an Graphen anbringen können. \n",
|
||
"\n",
|
||
"Zunächst erst aber einmal eine einfache Zeichenkette:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.100616Z",
|
||
"start_time": "2019-09-30T05:49:45.084372Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"'Dies ist eine Zeichenkette'"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Hierbei kann eine Zeichenkette auch alle Symbole enthalten die euer Interpreter unterstützt. In Jupyter sind dies alle gewohnten Zeichen wie Buchstaben, Zahlen, Sonderzeichen und Leerzeichen: "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.117423Z",
|
||
"start_time": "2019-09-30T05:49:45.102607Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"s1 = '0123456789'\n",
|
||
"s2 = 'äöü'\n",
|
||
"s3 = '*+~`´?ß-@€'\n",
|
||
"s4 = 'python 3.7>'\n",
|
||
"\n",
|
||
"print(s1,s2,s3,s4)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Einen **Formatstring** können wir über zwei Arten generieren (**Muss checken welche Python version im Hub genutzt wird**):"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.133467Z",
|
||
"start_time": "2019-09-30T05:49:45.120240Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"a = 'eins'\n",
|
||
"b = 2\n",
|
||
"\n",
|
||
"print('Dies ist Syntaxvariante {}'.format(a))\n",
|
||
"print()\n",
|
||
"print(f'Dies ist Syntaxvariante {b}') "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Neben dem Einfügen von Strings oder Zahlen in eine Zeichenkette können wir die eingefügten Werte auch formatieren:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.149030Z",
|
||
"start_time": "2019-09-30T05:49:45.135899Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"pi = 3.1415926535\n",
|
||
"\n",
|
||
"print(f'Dies ist pi auf 4 signifikante Stellen gerundet: {pi:.4}')\n",
|
||
"print()\n",
|
||
"print('Dies ist pi auf 4 signifikante Stellen gerundet: {:.4}'.format(pi))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"... oder sofern ihr eine Rückgabe lieber über mehrere Zeilen ausgeben lassen wollt könnt ihr dieswie folgt machen:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.164689Z",
|
||
"start_time": "2019-09-30T05:49:45.153880Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"U = 12.0 #V\n",
|
||
"dU = 0.1 #V\n",
|
||
"I = 0.30 #mA\n",
|
||
"dI = 0.01 #mA\n",
|
||
"\n",
|
||
"R = U/I #kOhm \n",
|
||
"dR = R * ((dU / U)**2 + (dI / I)**2)**0.5\n",
|
||
"\n",
|
||
"print(f'''An einem Widerstand R wurden die folgenden Werte gemessen:\n",
|
||
"Spannung: {U}+/-{dU} V\n",
|
||
"Strom: {I}+/-{dI} mA\n",
|
||
"Hierraus resultiert ein Widerstand von {R}+/-{dR:.2} kOhm ''') "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Das definieren von Funktionen:\n",
|
||
"\n",
|
||
"Anstatt Berechnungen wie bei einem Taschenrechner immer wieder manuell einzugeben, ermöglicht uns eine Programmiersprache das definieren von Funktionen. Funktionen können hierbei ähnlich wie mathematische Funktionen definiert und behandelt werden. Im folgenden wollen wir uns dies im Fall des Ohmschen Gesetzt welches durch \n",
|
||
"\n",
|
||
"$U(R, I) = R \\cdot I$ \n",
|
||
"\n",
|
||
"beschrieben wird angucken. Hierbei wird die Spannung $U$ durch die Variablen $R$ und $I$ beschrieben. Dies gilt auch analog für Funktionen in einer Programmiersprache:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.198018Z",
|
||
"start_time": "2019-09-30T05:49:45.182648Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"def Spannung(Widerstand, Strom): # U(R,I)\n",
|
||
" return Widerstand * Strom # Wiedergabe der Funktion"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Diese Funktion können wir nun auf Messdaten anwenden. Z.B. wir Messen bei einem Widerstand von $1\\,\\text{k}\\Omega$ einen Strom von $10\\,\\text{mA}$:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.213392Z",
|
||
"start_time": "2019-09-30T05:49:45.200009Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Leider müssen wir hier auf die Einheiten selbst achten.\n",
|
||
"# Deshalb ist es ratsam sich die Einheiten zu den Werten zu notieren.\n",
|
||
"U = Spannung(1000, 0.01) # in V \n",
|
||
"U "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Neben mathematischen Funktionen, können Funktionen in einer Programmiersprache auch viel allgemeinere Aufgaben erfüllen bzw. komplexe Algorithmen beinhalten. Hierzu lernt ihr jedoch noch mehr in anderen Programmierkursen. Wie zum Beispiel:\n",
|
||
"\n",
|
||
"* Computer in der Wissenschaft \n",
|
||
"* Programmieren für Physiker\n",
|
||
"* Einführung in die Programmierung"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Tipp: \n",
|
||
"Es ist ratsam gleich von Anfang an Funktionen zu dokumentieren. Hierzu wird in Python der sogenannte `Doc-Strings`. Sie beinhalten Informationen über die Funktion selbst ihre Verwendeten Parameter und ihrer Ausgabe. Zum Beispiel für unser Beispiel des Ohmschen Gesetzt:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.228841Z",
|
||
"start_time": "2019-09-30T05:49:45.213392Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"def Spannung(Strom, Widerstand):\n",
|
||
" '''\n",
|
||
" Diese Funktion berechnet die Spannung eines Ohmschen \n",
|
||
" Widerstands.\n",
|
||
" \n",
|
||
" Args:\n",
|
||
" Strom (float): Der gemessene Strom in mA.\n",
|
||
" Widerstand (float): Der Wert des verwendeten Widerstands\n",
|
||
" in Ohm.\n",
|
||
" \n",
|
||
" \n",
|
||
" Returns:\n",
|
||
" float: Die Berechnete Spannung in V.\n",
|
||
" '''\n",
|
||
" return Widerstand * Strom/1000"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Messtabellen in Python:\n",
|
||
"\n",
|
||
"Damit euch eine Programmiersprache wie Python Arbeit abnehmen kann, sollte es natürlich auch möglich sein größere Datenmengen z.b. die Werte einer Messtabelle in einer Variablen zu speichern. Python bietet hierfür mehrer verschiedene Konzepte alle mit unterschiedlichen Stärken und Schwächen. Die gängigsten Methoden sind listen, tuple, bzw. so genannte numpy.arrays und pandas.dataframes. Aufgrund der imitierten Zeit im PGP 1 werden wir uns hier lediglich mit zwei dieser vier Methoden auseinander setzen. \n",
|
||
"\n",
|
||
"Fangen wir zunächst mit Listen an. Eine Liste ist eine Ansammlung von Werten, welche alle den gleichen oder ganz unterschiedliche Datentypen haben können. Eine Liste kann auf zwei unterschiedliche Art und Weisen erstellt werden:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.253021Z",
|
||
"start_time": "2019-09-30T05:49:45.231258Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"Messwerte1 = ['Wert1', 'Wert2', 'Wert3'] # Variante 1\n",
|
||
"Messwerte1"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.268805Z",
|
||
"start_time": "2019-09-30T05:49:45.255413Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"Messwerte2 = list([2, 0.9, '1']) # Variante 2\n",
|
||
"Messwerte2"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Sobald wir eine liste erstellt haben können wir eine ganze Reihe von unterschiedlichen Manipulationen durchführen um sie nach unserem belieben zu verändern.\n",
|
||
"\n",
|
||
"Wir können zum Beispiel die bestehende Liste um ein Wert erweitern (`append`) oder einen zusätzlichen Wert an eine beliebige Stelle in der Liste hinzufügen (`insert`)."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.284401Z",
|
||
"start_time": "2019-09-30T05:49:45.270768Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"Messwerte1.append('Wert5')\n",
|
||
"Messwerte1"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.299976Z",
|
||
"start_time": "2019-09-30T05:49:45.288392Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"Messwerte1.insert(4, 'Wert4')\n",
|
||
"Messwerte1"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Ups, was ist denn in der letzten Zelle passiert? Wert4 wurde ja garnicht an Stelle 4 der Liste gesetzt, Python scheint nicht zählen zu können... \n",
|
||
"\n",
|
||
"Leider zählt Python doch richtig. In Python läuft der index von objekten in einer Liste oder ähnlichem immer von 0,1,2,3...n. Dies können wir auch ganz einfach überprüfen in dem wir unsere Liste in verschiedene \"Scheiben\" schneiden (so genanntes slicing). Dies geht wie folgt: "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.315532Z",
|
||
"start_time": "2019-09-30T05:49:45.302011Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"NeueWerte = ['Wert1', 'Wert2', 'Wert3', 'Wert4', 'Wert5', 'Wert6'] "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Die kleinste Scheibe welche wir abschneiden können ist ein einzelner Wert:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.331241Z",
|
||
"start_time": "2019-09-30T05:49:45.321614Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"NeueWerte[0] # Hier seht ihr, dass der erste Wert den Index 0 hat."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.346454Z",
|
||
"start_time": "2019-09-30T05:49:45.334501Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"wert_index_2 = NeueWerte[2] \n",
|
||
"wert_index_2"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Wie bei einer Pizza können wir uns natürlich auch größere Stücke nehmen."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.362293Z",
|
||
"start_time": "2019-09-30T05:49:45.350810Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"NeueWerte[0:3] "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.377952Z",
|
||
"start_time": "2019-09-30T05:49:45.365048Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"NeueWerte[2:5] # Ihr seht Python behandelt den letzten Wert wie in einem offenen Intervall [2,5)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.393385Z",
|
||
"start_time": "2019-09-30T05:49:45.381012Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"NeueWerte[2:] # Hier werden alle Werte mit dem Index >= 2 zurück gegeben"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.410137Z",
|
||
"start_time": "2019-09-30T05:49:45.394382Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"NeueWerte[-3:] # Mit negativen Zahlen fangt ihr vom Ende der Liste an"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Neben `insert`, `append` und `slicing` bietet Python noch ein paar weitere Listenmanipulationen an. Mit Hilfe des `+` Operators könnt ihr die Werte in einer Liste direkt an eine andere Liste anfügen."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.427269Z",
|
||
"start_time": "2019-09-30T05:49:45.412715Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"Messwerte1 + NeueWerte"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Anders als `append` welches die zweite Liste als ganzes an die erste Liste anfügt:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.452979Z",
|
||
"start_time": "2019-09-30T05:49:45.430445Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"Messwerte1.append(NeueWerte)\n",
|
||
"Messwerte1"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Aber aufgepasst bei `append` wird eure Liste an welche ihr die Daten anhängt (hier Messwerte1) direkt geändert (dies gilt auch für `insert`), während ihr beim `+` Operator die Variable überschreiben müsst damit die Änderung wirksam wird. "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.469517Z",
|
||
"start_time": "2019-09-30T05:49:45.455539Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"Messwerte1 = Messwerte1 + NeueWerte\n",
|
||
"# Tipp dies könnt ihr auch einfach mit Hilfe von\n",
|
||
"# Messwerte1 += NeueWerte\n",
|
||
"Messwerte1"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Zwei weitere nützliche Befehle im zusammenhang von listen ist die `len`- und `range`-Funktion. \n",
|
||
"\n",
|
||
"`len` gibt euch die Länge einer Liste zurück "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.485491Z",
|
||
"start_time": "2019-09-30T05:49:45.471309Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"print(Messwerte1)\n",
|
||
"len(Messwerte1)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"`range` erstellt euch ganzzahlige Werte zwischen zwei ganzen Zahlen "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.501670Z",
|
||
"start_time": "2019-09-30T05:49:45.488502Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"range(0, # <-- Startwert\n",
|
||
" 5, # <-- Endwert (nicht mehr enthalten, offenes Ende)\n",
|
||
" 2 # <-- Schrittweite\n",
|
||
" )"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Ihr könnt die `range` Rückgabe auch wieder in eine Liste umwandeln mit"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.519608Z",
|
||
"start_time": "2019-09-30T05:49:45.503662Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"list(range(0,5,2))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<div class=task>\n",
|
||
" \n",
|
||
"#### Aufgabe 4.a.: Erstellen von Messwerttabellen:\n",
|
||
"\n",
|
||
"Erstelle für jede Spalte (außer der Messwertnummer) der nachfolgende Messtabelle eine Liste welche die Messdaten beinhaltet. Benutze anschließend den `append` Befehl um deine Spaltendaten an eine weitere Liste namens *daten* anzuhängen. \n",
|
||
"\n",
|
||
"| Messwertnummer | Spannung [V] | Strom [mA] | Fehler der Spannung [V] | Fehler des Stroms in [mA] |\n",
|
||
"|----------------|--------------|------------|-------------------------|---------------------------|\n",
|
||
"| 1 | 12.00 | 110 | 0.32 | 10 |\n",
|
||
"| 2 | 11.78 | 98 | 0.15 | 10 |\n",
|
||
"| 3 | 12.56 | 102 | 0.63 | 10 |\n",
|
||
"| 4 | 12.34 | 124 | 0.12 | 10 |\n",
|
||
"| 5 | 12.01 | 105 | 0.20 | 10 |\n",
|
||
"| 6 | 11.94 | 95 | 0.17 | 10 |\n",
|
||
"\n",
|
||
"\n",
|
||
"Verwende anschließend das Slicing um die umgesetzte Leistung im Widerstand für die Meswerte 3 und 5 zu berechnen.\n",
|
||
"\n",
|
||
"**Tipp:**\n",
|
||
"\n",
|
||
"1. Ihr habt bereits die Funktionen für die Leistung in Aufgabe 3 definiert und könnt sie hier erneut verwenden. \n",
|
||
"2. Das Sclicen von verschachtelten Listen funktioniert genauso wie bei normalen Listen: \n",
|
||
"\n",
|
||
"```python\n",
|
||
"spalte0 = daten[0] #<-- Wählt die Spalte 0 an \n",
|
||
"spalte0[2] #<-- Wählt aus Spalte 0 den Messwert mit Index 2 an\n",
|
||
"# oder als Einzeiler:\n",
|
||
"daten[0][2] \n",
|
||
"```\n",
|
||
"\n",
|
||
"3. Wie verhält sich die Messwertnummer zum Listenindex?\n",
|
||
"<div>"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Arbeiten mit Messreihen:\n",
|
||
"\n",
|
||
"Bisher hat uns das programmieren eher mehr Arbeit gemacht als uns welche abgenommen. Zeitersparnis bekommen wir sofern wir viele Rechnungen hintereinander ausführen müssen. Hierfür gibt es die **for**-Schleife. Diese Schleife führt die gleichen Zeilen eins Codes wiederholt für die Elemente in einer Liste aus:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.536295Z",
|
||
"start_time": "2019-09-30T05:49:45.521273Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"liste = [1, 2, 3, 4]\n",
|
||
"\n",
|
||
"for wert in liste:\n",
|
||
" print('Wert:', wert)\n",
|
||
" rechnung = wert + 2\n",
|
||
" print('Ergebnis:', rechnung)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Bei einer Schleife ist darauf zu achten, dass der Anweisungsblock welcher wiederholt ausgeführt werden soll mit 4x Leerzeichen eingrückt wurde. Dies entspricht einmal der TAB-Taste."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.554498Z",
|
||
"start_time": "2019-09-30T05:49:45.539185Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"liste = [1, 2, 3, 4]\n",
|
||
"print('Hier läuft das Hauptprogramm')\n",
|
||
"\n",
|
||
"for wert in liste:\n",
|
||
" print('Schleife')\n",
|
||
" print('Wert:', wert)\n",
|
||
" rechnung = wert + 2\n",
|
||
" \n",
|
||
"print('Hier läuft wieder das Hauptprogramm')\n",
|
||
"rechnung = rechnung + 5\n",
|
||
"print('Letztes Ergebnis + 5: ', rechnung)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Statt das Ergebnis lediglich per `print`-Anweisung darstellen zu lassen, können wir auch unser Wissen um Listen benutzen und die berechneten Werte einer neuen Liste anfügen:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.569672Z",
|
||
"start_time": "2019-09-30T05:49:45.557148Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"Stromwerte = [101, 105, 98, 87, 112] # mA\n",
|
||
"Spannungswerte = []# Einheit? <-- Deshlab Docstrings und Help!\n",
|
||
"Widerstand = 100 # Ohm\n",
|
||
"\n",
|
||
"for Strom in Stromwerte:\n",
|
||
" Spannungswerte.append(Spannung(Strom, Widerstand))\n",
|
||
"\n",
|
||
"Spannungswerte"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Python ermöglicht uns auch eine kompaktere Schreibweise die so genannte \"list comprehension\": "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.587685Z",
|
||
"start_time": "2019-09-30T05:49:45.571574Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"Spannungswerte = [Spannung(Strom, 1000) for Strom in Stromwerte]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Wir können auch über mehre Daten gleichzeitig loopen. Hierzu kann die `zip` Anweisung genutzt werden. `zip` verbindet hierbei die einzelnen Elemente einer Liste wie bei einem Reißverschluss miteinander:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.603972Z",
|
||
"start_time": "2019-09-30T05:49:45.588679Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"Werte1 = ['A', 'B', 'C', 'D']\n",
|
||
"Werte2 = [0, 1, 2, 3]\n",
|
||
"\n",
|
||
"for w1, w2 in zip(Werte1, Werte2):\n",
|
||
" print(w1, ' und ', w2)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Dies kann zum Beispiel dann hilfreich sein wenn sich mehr als eine Variable ändern soll, z.B. bei einer Messreihe für die Schallgeschwindigkeit in Luft:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.619123Z",
|
||
"start_time": "2019-09-30T05:49:45.606905Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Gemessene Werte:\n",
|
||
"frequenzen = [30.17, 30.63, 30.01, 29.98, 30.12, 29.87, 29.94] #kHz\n",
|
||
"wellenlängen = [11.12, 11.34, 11.45, 11.25, 11.01, 11.45, 11.23] # mm\n",
|
||
"\n",
|
||
"# Variante 1:\n",
|
||
"schallgeschindigkeiten = [] # m/s\n",
|
||
"\n",
|
||
"for f,l in zip(frequenzen, wellenlängen):\n",
|
||
" schallgeschindigkeiten.append(f*l)\n",
|
||
"\n",
|
||
"print(schallgeschindigkeiten)\n",
|
||
"\n",
|
||
"# oder Variante 2:\n",
|
||
"schallgeschindigkeiten2 = [f*l for f,l in zip(frequenzen, wellenlängen)]\n",
|
||
"print(schallgeschindigkeiten2)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Wir können auch die `zip`-Anweisung mit mehr als nur zwei Listen verwenden:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:45.650337Z",
|
||
"start_time": "2019-09-30T05:49:45.622191Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"l1 = ['a', 'b', 'c']\n",
|
||
"l2 = [1, 2, 3]\n",
|
||
"l3 = ['x', 'y', 'z']\n",
|
||
"\n",
|
||
"for i,j,k in [l1, l2, l3]:\n",
|
||
" print(i, 'und', j, 'und', k)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<div class=task>\n",
|
||
" \n",
|
||
"#### Aufgabe 4.b.: Werte berechnen:\n",
|
||
"Berechnet nun für die Messwerte aus Aufgabe 4 a. die Leistung $P$ und den Widerstand $R$ sowie deren Fehler. Nutzt hierfür die ausführliche schrebweise der **for**-Schleife im Fall des Widerstands $R$ und den list-comprehension Syntax für die Leistung $P$. Fügt die berechneten Werte als neue Spalten and die Liste *daten* an. \n",
|
||
"<div>"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Das Darstellen von Messdaten mittels `matplotlib`:\n",
|
||
"Das Plotten von Daten ist eines der wichtigsten Mittel um eine Fülle von Informationen kompakt und verständlich seinem Gegenüber darzubieten. Gute Plots zu erstellen kann eine regelrechte Kunst sein und ist für ein gutes Paper, bzw. eine gute Bachelor- bzw. Masterarbeit unverzichtbar. \n",
|
||
"\n",
|
||
"<figure class=\"image\">\n",
|
||
"<img src=\"images/MaterialPythonkurs092018/Xenon1tResults1yearx1texposure.png\" alt=\"{{ Xenon1t results 2018 }}\" width=50%>\n",
|
||
"<figcaption>Resultate des XENON1T Dunkle Materie Experiments. Die Graphik wurde mittels Matplotlib in Python erstellt. </figcaption>\n",
|
||
"</figure>\n",
|
||
"\n",
|
||
"Jede Programmiersprache verfügt über zusätzliche Pakete (im Englischen \"packages\") welche die Funktionalität der verwendeten Programmiersprache erweitern. **Matplotlib** ist ein umfangreiches Package, welches das Zeichnen von 2D und 3D Grafiken ermöglicht. Alle Parameter und Einstellungen einer Grafik werden entsprechend des Python-Codes eingestellt. Dadurch wird das Erstellen der Grafik reproduzierbar und man kann schnell dieselbe Grafik mit neuen Daten füttern.\n",
|
||
"\n",
|
||
"Es ist unmöglich alle Möglichkeiten und Einstellungen die euch **Matplotlib** bietet auswendig zu kennen. Mit der Zeit werdet ihr ein solides Grundwissen der gängisten Befehle haben. Für alles weitere hilft euch die [Dokumentation und ihre Beispiele](http://matplotlib.org/). Des Weiteren ist insbesondere hier die **IPython Hilfe** und das **automatische Vervollständigen von Befehlen** besonders hilfreich.\n",
|
||
"\n",
|
||
"Für das Praktikum wollen wir uns zunächst lediglich drei unterschiedliche Arten von Plots angucken:\n",
|
||
"\n",
|
||
"* Normale Liniengrafiken\n",
|
||
"* Plots mit Fehlerbalken\n",
|
||
"* Histogramme "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Zunächst müssen wir Python mitteilen, dass wir das **Matplotlib** package nutzen möchten:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:51.120679Z",
|
||
"start_time": "2019-09-30T05:49:45.655490Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"import matplotlib.pyplot as plt "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"`import` läd für und aus dem package matplotlib das Modul `pyplot`. Mit Hilfe des Zusatzes `as plt` wird ein alias erstellt. Dieser Alias erspart uns im nachfolgenden Arbeit, wie wir im nachfolgenden Beispiel sehen können:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:51.666259Z",
|
||
"start_time": "2019-09-30T05:49:51.125088Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"plt.plot([1,2,3,4,5], # <-- x-Daten\n",
|
||
" [1,2,3,4,5] # <-- y-Daten\n",
|
||
" )\n",
|
||
"plt.show() # <-- Zeigen des Plots"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Hätten wir den Alias nicht definiert hätten wir den folgenden etwas länglichen Code benötigt:\n",
|
||
"\n",
|
||
"```python\n",
|
||
"matplotlib.pyplot.plot([1,2,3,4,5], [1,2,3,4,5])\n",
|
||
"matplotlib.pyplot.show()\n",
|
||
"```\n",
|
||
"\n",
|
||
"Innerhalb der Python-Community haben sich ein paar Standards etabliert an welche man sich halten sollte. So ist für `matplotlib.pyplot` der Alias `plt` zu verwenden. \n",
|
||
"\n",
|
||
"Im oberen Beispiel habt ihr nun auch bereits gesehen wie wir einfache Liniengrafiken erstellen können. Dabei sieht der Plot noch etwas blass aus. Dies können wir mit ein paar zusätzlichen Befehlen ändern."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:52.050116Z",
|
||
"start_time": "2019-09-30T05:49:51.670160Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"xdaten = [1,2,3,4,5]\n",
|
||
"ydaten = [1,2,2,4,5]\n",
|
||
"\n",
|
||
"plt.plot(xdaten, ydaten, # <-- Wie eben die x und y daten\n",
|
||
" color = 'red', # <-- Farbe der Linie\n",
|
||
" linestyle='dashed', # <-- Linientyp\n",
|
||
" label='Graph 1' # <-- Name der Linie\n",
|
||
" )\n",
|
||
"plt.xlabel('X-Achse') # <-- Beschriftung der x-Achse\n",
|
||
"plt.ylabel('Y-Achse') # <-- Beschiftung der y-Achse\n",
|
||
"plt.legend() # <-- Hinzufügen der Legend mit den \n",
|
||
" # in plot definierten labels\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Viele der eben verwendeten Optionen bieten euch unterschiedliche Auswahlmöglichkeiten:\n",
|
||
"\n",
|
||
"**Linestyle:**\n",
|
||
"* `''`: keine Linie\n",
|
||
"* `'-'`: durchgehende Linie\n",
|
||
"* `'--'`: gestrichelte Linie\n",
|
||
"* `'-.'`: Strich-Punktlinie\n",
|
||
"* `':'`: Punktlinie\n",
|
||
"* `'steps'`: Treppenfunktion\n",
|
||
"\n",
|
||
"**Color**:\n",
|
||
"* red, blue, yellow, \n",
|
||
"* RGB Werte von 0 bis 1 (statt von 0 bis 255): (1, 1, 1), (1, 0.2, 0.4)\n",
|
||
"\n",
|
||
"Darüber hinaus gibt es auch noch andere nützliche Styleoptionen wie `alpha` was die Transparenz eurer Linie ändert (Werte zwischen 0-1), oder `linewidth`-Option mit dessen Hilfe ihr die Linienbreite ändern könnt. \n",
|
||
"\n",
|
||
"Auch die anderen Befehle welche wir verwendetet haben verfügen über zusätzliche Optionen:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:52.416739Z",
|
||
"start_time": "2019-09-30T05:49:52.054118Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"xdaten = [1,2,3,4,5]\n",
|
||
"ydaten = [1,2,2,4,5]\n",
|
||
"\n",
|
||
"plt.plot(xdaten, ydaten, \n",
|
||
" color = 'red', \n",
|
||
" linestyle='dashed', \n",
|
||
" label='Graph 1' \n",
|
||
" )\n",
|
||
"plt.xlabel('X-Achse',\n",
|
||
" color = (0,1,0) # <-- Beschriftungsfrabe\n",
|
||
" ) \n",
|
||
"\n",
|
||
"plt.ylabel('Y-Achse', \n",
|
||
" fontsize=14) # <-- Beschiftungsgröße\n",
|
||
"\n",
|
||
"plt.legend(title='Messwerte', # <-- Legendentitel\n",
|
||
" loc=3) # <-- Legendenposition: \n",
|
||
" # 0: Best, \n",
|
||
" # 1: Oben Rechts \n",
|
||
" # 2: Oben Links\n",
|
||
" # 3: Unten Links \n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Sofern ihr mehrere Graphen in einen Plot zeichnen möchtet geht dies auch ganz einfach."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:52.783344Z",
|
||
"start_time": "2019-09-30T05:49:52.421516Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"xdaten = [-3, -2, -1, 0, 1, 2, 3]\n",
|
||
"ydaten1 = xdaten\n",
|
||
"ydaten2 = [x**2 for x in xdaten]\n",
|
||
"ydaten3 = [x**3 for x in xdaten]\n",
|
||
"\n",
|
||
"plt.plot(xdaten, ydaten1, label='Linear')\n",
|
||
"plt.plot(xdaten, ydaten2, label='Quadratisch')\n",
|
||
"plt.plot(xdaten, ydaten3, label='Cubisch')\n",
|
||
"\n",
|
||
"plt.legend(title='Exponent')\n",
|
||
"plt.xlabel('X-Werte')\n",
|
||
"plt.ylabel('Y-Werte')\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Ihr seht, das `plot` zwischen den angegebene Werte interpoliert. Möchtet ihr eine glatte Kurve zeichnen so müsst ihr die Anzahl an Punkten für die Interpolation erhöhen."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:53.132959Z",
|
||
"start_time": "2019-09-30T05:49:52.786318Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"def cubic(x):\n",
|
||
" '''\n",
|
||
" Funktion welche den cubischen Wert einer Zahl zurück gibt.\n",
|
||
" '''\n",
|
||
" return x**3\n",
|
||
"\n",
|
||
"\n",
|
||
"x1 = list(range(-3, 4, 1)) # <- Werte zwischen -3 und 3\n",
|
||
"x2 = [i/10 for i in range(-30,31,1)] # <- 10 mal mehr Werte\n",
|
||
"\n",
|
||
"y1 = [cubic(j) for j in x1]\n",
|
||
"y2 = [cubic(value) for value in x2]\n",
|
||
"\n",
|
||
"\n",
|
||
"plt.plot(x1, y1, label='Werte 1', linestyle='dashed')\n",
|
||
"plt.plot(x2, y2, label='Werte 2')\n",
|
||
"plt.xlabel('x-Werte')\n",
|
||
"plt.ylabel('y-Werte')\n",
|
||
"plt.legend()\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Errorbarplot\n",
|
||
"\n",
|
||
"In der Physik gehören zu jedem gemessen Wert ein Messunsicherheit/Messfehler. Diese Fehler sollten natürlich auch in unseren Grafiken korrekt dargestellt werden. Hierfür können wir den `errorbar`-Plot verwenden."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:53.415033Z",
|
||
"start_time": "2019-09-30T05:49:53.137171Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"spannung = [0.9, 2.0, 3.0, 4.1, 4.9, 6.2] # [V]\n",
|
||
"strom = [105, 204, 298, 391, 506, 601] # [mA]\n",
|
||
"spannung_error = [0.3]*len(spannung) # Konstanter Ablesefehler [V]\n",
|
||
"strom_error = [14, 9, 12, 8, 7, 11] # gemessener schwankender Fehler[mA]\n",
|
||
"\n",
|
||
"# plt.errorbar() # <--- Wie verwende ich den errorbar plot?\n",
|
||
"\n",
|
||
"plt.ylabel('Spannung [V]')\n",
|
||
"plt.xlabel('Strom [mA]')\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<div class=task>\n",
|
||
" \n",
|
||
"#### Aufgabe 5.: Erstelle eine `errorbar`-Plot :\n",
|
||
"\n",
|
||
"Editiert die obere Zelle so, dass ihr mit Hilfe des Befehls \n",
|
||
"\n",
|
||
"```python\n",
|
||
"plt.errorbar()\n",
|
||
"```\n",
|
||
"\n",
|
||
"einen Errorbarplot erstellt. Verwende hier für die IPython help-funktion um den exakten Syntax zu erfahren. \n",
|
||
"\n",
|
||
"**Erinnerung:**\n",
|
||
"Ihr könnt die IPython-Hilfe aufrufen in dem ihr euren Cursor innerhalb das Wort errorbar von plt.errorbar bewegt und die Tastenkombination shift + tab verwendet. Lest nun nach wie ihr die x- und y-Werte und deren Fehler an die Funktion übergeben müsst.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Leider ist diese Standardvariante des Errorbar plots noch nicht das was wir möchten. Die Messwerte sind linear interpoliert und die errorbars sehen noch etwas eigenartig aus. Dies können wir jedoch im Handumdrehen ändern. Kümmern wir uns zunächst um die Plotmarker:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:53.699576Z",
|
||
"start_time": "2019-09-30T05:49:53.418951Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"#plt.errorbar(, \n",
|
||
"# ,\n",
|
||
"# ,\n",
|
||
"# , \n",
|
||
"# # Änderungen für plotmarker: | Kurzform:\n",
|
||
"# linestyle='', # <-- Schaltet den Linienstyle aus | ls=''\n",
|
||
"# marker='d', # <-- Ändert den Markertyp in Diamanten | -----\n",
|
||
"# markerfacecolor='orange', # <-- Ändert die Markerfarbe zu Orange | mfc='orange'\n",
|
||
"# markeredgecolor='k', # <-- Setzt die Kantenfarbe auf schwarz | mec='k'\n",
|
||
"# markersize=7 # <-- Ändert die Markergröße | ms='7'\n",
|
||
"# ) \n",
|
||
"\n",
|
||
"plt.ylabel('Spannung [V]')\n",
|
||
"plt.xlabel('Strom [mA]')\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"All die Optionen welche wir hier für die Plotmarker verwendet haben können wir auch in der normalen `plt.plot`-Anweisung verwenden. Dabei gibt es eine ganze fülle an unterschiedlichen [marker Symbole](http://matplotlib.org/api/markers_api.html):\n",
|
||
" \n",
|
||
"* `+`: Plus\n",
|
||
"* `o`: Kreis\n",
|
||
"* `*`: Stern\n",
|
||
"* `,`,`.`: kleiner und sehr kleiner Punkt\n",
|
||
"* `s`: Quadrat\n",
|
||
"* `p`: Pentagon\n",
|
||
"* `h`: Hexagon\n",
|
||
"* `1`, `2`, `3`, `4`: nach unten, oben, links, rechts zeigendes Dreieck\n",
|
||
" \n",
|
||
"Nach dem wir uns um unsere Marker gekümmert haben müssen wir nun auch noch unsere Fehlerbalken enstprechend anpassen:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:53.966203Z",
|
||
"start_time": "2019-09-30T05:49:53.704110Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"plt.errorbar(strom, \n",
|
||
" spannung,\n",
|
||
" xerr=strom_error,\n",
|
||
" yerr=spannung_error, \n",
|
||
" ls='', \n",
|
||
" marker='d', \n",
|
||
" mfc='orange', \n",
|
||
" mec='k', \n",
|
||
" ms=7,\n",
|
||
" # Fehlerbalken optionen:\n",
|
||
" ecolor='k', # <-- Ändert die Linienfarbe der errorbars\n",
|
||
" elinewidth=2, # <-- Ändert die Fehlerbalkenbreite\n",
|
||
" capsize=5, # <-- Ändert die Breite der Endkappen der Fehlerbalken\n",
|
||
" capthick=2 # <-- Ändert die Dicke der Endkappen\n",
|
||
" ) \n",
|
||
"\n",
|
||
"plt.ylabel('Spannung [V]')\n",
|
||
"plt.xlabel('Strom [mA]')\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Histogramme:\n",
|
||
"\n",
|
||
"Ein weiterer Plottyp welcher häufig Verwendung findet ist das Histogramm. Um unser Histogramm mit Pseudozufallszahlen zu bestücken müssen wir diese erst erzeugen. Hierfür können wir das `numpy`-Modul verwenden. `numpy` ist ein weiteres Standardmodul welches viele nützliche Funktionen mit sich bringt. Hier wollen wir uns jedoch nur auf das erstellen von Zufallszahlen beschränken. "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:53.981719Z",
|
||
"start_time": "2019-09-30T05:49:53.970564Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"import numpy as np"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:53.997232Z",
|
||
"start_time": "2019-09-30T05:49:53.987645Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"rnd_numbers = np.random.normal(0,1,1000) # <-- Hier werden 1000 gausförmig verteile Zufallszahlen\n",
|
||
" # mit einem Mittelwert von 0 und einer Standardabweichung \n",
|
||
" # von 1 erzeugt."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Das histgrom lässt sich ganz einfach mit der `plt.hist`-Anweisung erstellt."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:54.299231Z",
|
||
"start_time": "2019-09-30T05:49:54.000609Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"plt.hist(rnd_numbers)\n",
|
||
"\n",
|
||
"plt.xlabel('Zufallswert')\n",
|
||
"plt.ylabel('Anzahl der Einträge')\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Auch für Histogramme gibt es viele unterschiedlichen Optionen welche ihr entweder mit Hilfe der Help-Funktion oder den Beispielen in der [Matplolibdokumentation](http://matplotlib.org/) herrausfinden könnt."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:54.731879Z",
|
||
"start_time": "2019-09-30T05:49:54.308613Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"rnd_numbers2 = np.random.normal(1,2,1000)\n",
|
||
"\n",
|
||
"\n",
|
||
"plt.hist(rnd_numbers, \n",
|
||
" bins=13, \n",
|
||
" range=(-3,5), # <-- Achtung im Gegensatz zur range-Anweisung ist \n",
|
||
" # das Intervall hier geschlossen [-3, 5]\n",
|
||
" histtype='step', # Ändert den Balkentyp in Stufen\n",
|
||
" linestyle='dashed',\n",
|
||
" label='Verteilung 1'\n",
|
||
" )\n",
|
||
"\n",
|
||
"plt.hist(rnd_numbers2, \n",
|
||
" bins=13, \n",
|
||
" range=(-3,5),\n",
|
||
" alpha=0.5, # Ändert die Transparenz der Balken \n",
|
||
" label='Verteilung 2'\n",
|
||
" )\n",
|
||
"\n",
|
||
"plt.legend()\n",
|
||
"plt.xlabel('Zufallswert')\n",
|
||
"plt.ylabel('Anzahl der Einträge')\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Bei Histogrammen solltet ihr immer darauf achten, dass euer binning sinnvoll gewählt ist. Weder zu viele noch zu wenig Bins führen zu einer sinnvollen Darstellung eurer Daten."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:55.814937Z",
|
||
"start_time": "2019-09-30T05:49:54.737180Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"plt.hist(rnd_numbers, \n",
|
||
" bins=100, \n",
|
||
" range=(-3,3),\n",
|
||
" label='Zu viele bins'\n",
|
||
" )\n",
|
||
"\n",
|
||
"plt.legend()\n",
|
||
"plt.xlabel('Zufallswert')\n",
|
||
"plt.ylabel('Anzahl der Einträge')\n",
|
||
"plt.show()\n",
|
||
"\n",
|
||
"plt.hist(rnd_numbers, \n",
|
||
" bins=3, \n",
|
||
" range=(-3,3),\n",
|
||
" label='Zu wenig bins'\n",
|
||
" )\n",
|
||
"\n",
|
||
"plt.legend()\n",
|
||
"plt.xlabel('Zufallswert')\n",
|
||
"plt.ylabel('Anzahl der Einträge')\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Nach dem wir jetzt die verschiedenen Plottypen mit ihren unterschiedlichen Optionen kennen gelernt haben möchten wir diese natürlich auch speichern können. Dies können wir auf zwei unterschiedliche Arten machen.\n",
|
||
"\n",
|
||
"Entweder ihr macht mit eurer Maus einen Rechtsklick auf eure Grafik und wählt \"Grafik speichern als\" aus, oder ihr verwendet statt der `plt.show`- die `plt.savefig`-Anweisung dafür."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:49:56.097579Z",
|
||
"start_time": "2019-09-30T05:49:55.820103Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"plt.errorbar(strom, \n",
|
||
" spannung,\n",
|
||
" xerr=strom_error,\n",
|
||
" yerr=spannung_error, \n",
|
||
" ls='', \n",
|
||
" marker='d', \n",
|
||
" mfc='orange', \n",
|
||
" mec='k', \n",
|
||
" ms=7,\n",
|
||
" ecolor='k', \n",
|
||
" elinewidth=2, \n",
|
||
" capsize=5, \n",
|
||
" capthick=2 \n",
|
||
" ) \n",
|
||
"\n",
|
||
"plt.ylabel('Spannung [V]')\n",
|
||
"plt.xlabel('Strom [mA]')\n",
|
||
"plt.show()\n",
|
||
"#plt.savefig(r'C:\\Users\\Daniel\\Desktop\\myplot.png', # <-- Pfad in dem der Plot gespeichert werden soll\n",
|
||
"# dpi=300) # <-- Auflösung mit dem der Plot gespeichert werden soll.\n",
|
||
"# # 300 - 600 dpi solltet ihr hier verwenden."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Fitten von Messdaten:\n",
|
||
"\n",
|
||
"### Methode der kleinsten Quadrate\n",
|
||
"\n",
|
||
"Im folgenden wolllen wir die **Methode der kleinsten Quadrate (Least Squares)** näher beleuchten. Diese Methode wird oft benutzt um eine Funktion $\\lambda(x; \\ $**$\\phi$**$)$ mit den Funktionsparametern $\\mathbf{\\phi}$ an die gemessenen Punkte **$(x,y)$** anzupassen. Um jedoch die **Methode der kleinsten Quadrate** zu verstehen wollen wir sie erst einmal anschaulich und mathematisch herleiten. Dabei stüzen wir uns im folgenden auf eine Herleitung aus dem Buch **\"Statistical Data Analysis\"** von **Glen Cowan**.\n",
|
||
"\n",
|
||
"In unserem Grundpraktikum haben wir bereits gelernt, dass Messwerte durch Zufallszahlen $x_i$ representiert werden und einer gewissen **Wahrscheinlichkeitsdichtefunktion (probability density function)** $f(x)$ unterliegen. \n",
|
||
"\n",
|
||
"<figure class=\"image\">\n",
|
||
"<img src=\"images/MaterialPythonkurs092018/PorbDensFun.png\" alt=\"{{ Beispiel PDF }}\" width=70%>\n",
|
||
"</figure>\n",
|
||
"\n",
|
||
"\n",
|
||
"Eine **pdf** gibt an mit welcher **Wahrscheinlichkeit ein Wert $x_i$** innerhalb eines **infinitesimalen Intervals $\\text{d}x_i$** zu finden ist. Des Weitren gilt das die Gesamtwahrscheinlichkeit gegeben ist durch $\\int_S f(x) dx = 1$. \n",
|
||
"\n",
|
||
"Nun betrachten wir folgendes Beispiel: In unserem Labor messen wir genau drei mal die Raumtemperartur T. Auch hier gilt, dass unsere Messung der einzelnen $T_i$ einer gewissen **Wahrscheinlichkeitsdichtefunktion** folgen. Betrachtet nun das folgende Bild; welche **Wahrscheinlichkeitsdichtefunktion** passt besser zu den gezeigten Daten und **Warum?**\n",
|
||
"\n",
|
||
"<figure class=\"image\">\n",
|
||
"<img src=\"images/MaterialPythonkurs092018/ProbMaxTemp.png\" alt=\"{{ Beispiel PDF }}\" width=100%>\n",
|
||
"</figure>\n",
|
||
"\n",
|
||
"Die rechte Verteilung spiegelt unsere Messdaten besser wieder. Dies können wir auch mathematisch ausdrücken. Für $N$ voreinander unabhängige Zufallszahlen bzw. Messpunkte (in unserem Beispiel $N = 3$) ist die Gesamtwahrscheinlichkeit gegeben durch das Produkt der einzelnen Wahrscheinlichkeitsdichten $f(x_i, \\theta)$ multipliziert mit dem jeweiligen infinitesimalen element $dx_i$\n",
|
||
"\n",
|
||
"$$\\prod_{i = 1}^{N} f(x_i,\\theta) \\ dx_i \\text{ für alle } x_i \\text{ in } [x_i, x_i + dx_i]$$\n",
|
||
"\n",
|
||
"wobei $x_i$ in unserem Beispiel den Messpunkten $T_i$ und $f(x_i,\\theta)$ unserer Gausverteilung mit $\\theta = (\\mu, \\sigma)$ entspricht. Sprich sofern unsere Werte gut von der jeweiligen **Wahrscheinlichkeitsdichtefunktion** repräsentiert werden, d.h. wir die richtigen Parameter $\\theta$ gewählt haben (wie im rechten oberen Plot), gilt \n",
|
||
"\n",
|
||
"$$ \\prod_{i = 1}^{N} f(x_i,\\theta) dx_i$$ \n",
|
||
"\n",
|
||
"ist **maximal**. Da die einzelnen $dx_i$ von unseren Parametern $\\theta$ unabhängig sind gilt die gleiche Argumentation auch für \n",
|
||
"\n",
|
||
"$$ \\mathcal{L}(x_1 ... x_N; \\theta_1 ... \\theta_N) = \\prod_{i = 1}^{N} f(x_i,\\theta)$$ \n",
|
||
"\n",
|
||
"wobei $\\mathcal{L}(x_1 ... x_N; \\theta_1 ... \\theta_N)$ die sogenannte **likely hood function** darstellt."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Wie kommen wir nun von der **likely hood function** auf unsere **Methode der kleinsten Quadrate** und dem fitten einer Funktion $\\lambda(x; \\ $**$\\phi$**$)$ an die gemessenen Punkte **$(x,y)$**? Dazu brauche wir noch einen Zwischenschritt. Oftmals ist es einfacher statt die **likely hood function** zu maximieren die so genannte **log likely hood function**\n",
|
||
"\n",
|
||
"$$ \\log( \\mathcal{L}(x_1 ... x_N; \\theta_1 ... \\theta_N)) = \\sum_{i = 1}^{N} \\log(f(x_i,\\theta))$$\n",
|
||
"\n",
|
||
"zu maximieren. Dies ist im Grunde das Gleiche, da der logarithmus eine monoton-steigende Funktion ist. Auch in unserem Fall der **Methode der kleinsten Quadrate** benötigen wir die **log likely hood function**. \n",
|
||
"\n",
|
||
"Stellt euch nun vor wir haben eine Messung mit $N$ voneinander unabhängigen Messpunkten (x,y). Des Weiteren nehmen wir an, dass alle $x_i$ ohne Fehler sind und das unsere $y_i$ gaußförmig um einen unbekannten Wahrenwert $\\lambda_i$ (sprich $\\lambda_i$ entspricht dem Erwartungswert $\\mu_i$ unserer Gaußverteilung) mit einer bekannten Varianz $\\Delta y_i^2$ verteilt sind (Diese Annahme lässt sich mit dem zentralen Grenzwertsatz begründen, so lange der Fehler sich aus der Summe kleinen Fehlern zusammensetzt). Die dazugehörige **likely hood function** ist dann gegeben durch:\n",
|
||
"\n",
|
||
"$$ \\mathcal{L}(y_1 ... y_N; \\lambda_1 ... \\lambda_N, \\Delta y_1 ... \\Delta y_N)) = \\prod_{i = 1}^{N}\\frac{1}{\\sqrt{2 \\pi \\Delta y_i^2}} \\cdot \\exp \\bigg( \\frac{ -(y_i - \\lambda_i)^2}{2 \\cdot \\Delta y_i^2}\\bigg)$$\n",
|
||
"\n",
|
||
"Beziehungsweise die **log likely hood function** mit $\\lambda_i = \\lambda(x_i; \\phi)$ ergibt sich zu\n",
|
||
"\n",
|
||
"$$ \\log(\\mathcal{L}(y, \\theta)) \\approx -\\frac{1}{2} \\sum_{i = 1}^{N}\\bigg( \\frac{ (y_i - \\lambda(x_i; \\phi))^2}{\\Delta y_i^2}\\bigg)$$\n",
|
||
"\n",
|
||
"wobei die konstanten Terme welche nicht von unserer Funktion $\\lambda(x_i; \\phi)$ abhängen vernachlässigt worden sind. Durch den Faktor $-\\frac{1}{2}$ ist das maximieren dieser **log likely hood function** gleich dem minnimieren von\n",
|
||
"\n",
|
||
"$$ \\chi(\\phi_1 ... \\phi_N)^2 = \\sum_{i = 1}^{N} \\frac{ (y_i - \\lambda(x_i; \\phi))^2}{\\Delta y_i^2}$$\n",
|
||
"\n",
|
||
"Diese Funktion ist unsere gesuchte **Methode der kleinsten Quadrate**. Mit ihrer Hilfe kann eine beliebige Funktion $\\lambda(x; \\phi)$, welche liniear in ihren Parametern $\\phi$ ist, an unsere Messdaten $(x,y\\pm\\Delta y)$ gefittet werden. Dabei stellt der Fitprozess selbst lediglich ein Minimierungsproblem dar. Im folgenden sind unsere Annahmen noch einmal grafisch in einem Beispiel dargestellt.\n",
|
||
"\n",
|
||
"<figure class=\"image\">\n",
|
||
"<img src=\"images/MaterialPythonkurs092018/LeastSquare.png\" alt=\"{{ Least Square Beispiel }}\" width=100%>\n",
|
||
"</figure>"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Es gibt verschiedene Arten von Algorithmen um Minimierungsprobleme zu lösen. Wie diese genau Aufgebaut sind lernt ihr in anderen Progrmmierkursen wie zum Beispiel *Programmieren für Physiker* oder *Computer in der Wissenschaft*. Zum Glück haben uns bereits in Python andere Menschen diese Arbeit abgenommen und wir können aus dem Package `scipy.optimize` die Funktion `curve_fit` verwenden. \n",
|
||
"\n",
|
||
"Hierbei stellt curve_fit eine Methode dar, Fit-Funktionen nach der obigen vorgestellten Methode der *kleinsten Quadraten* zu bestimmen. Dies hat zur folge, dass lediglich die y-Fehler eurer Messwerte für den Fit verwendet werden können. "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:50:00.030536Z",
|
||
"start_time": "2019-09-30T05:49:56.100407Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"from scipy.optimize import curve_fit"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Gucken wir uns einen Fit ohne Messfehler an um die Funktion etwas näher kennen zu lernen."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:50:00.063242Z",
|
||
"start_time": "2019-09-30T05:50:00.030536Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Und jetzt fitten wir:\n",
|
||
"para, pcov = curve_fit(Spannung, # <-- Funktion die an die Messdaten gefittet werden soll\n",
|
||
" strom, # <-- gemessenen \"X\"-Werte\n",
|
||
" spannung # <-- gemessenen \"Y\"-Werte \n",
|
||
" )\n",
|
||
"\n",
|
||
"print(para)\n",
|
||
"print(pcov)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Ihr seht die `curve_fit` gibt uns zwei unterschiedliche Listen zurück. Die erste Liste `para` beinhaltet die berechneten Fitparameter. `pcov` hingegen ist eine [Kovarianzmatrix](https://de.wikipedia.org/wiki/Kovarianzmatrix) auf deren Diagonalen ihr die Varianzen ($\\sigma^2$) der einzelnen Parameter findet (auf der Nebendiagonalen befinden sich die Kovarianzen, die euch aber im PGP nicht weiter zu kümmern brauchen).\n",
|
||
"\n",
|
||
"Lasst uns das Resultat mal darstellen:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:50:00.412884Z",
|
||
"start_time": "2019-09-30T05:50:00.066231Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"plt.plot(strom, \n",
|
||
" spannung, \n",
|
||
" ls='', \n",
|
||
" marker='d', \n",
|
||
" mfc='orange', \n",
|
||
" mec='k', \n",
|
||
" ms=7,\n",
|
||
" label='Messwerte aus A. 5 (ohne Fehler)'\n",
|
||
" ) \n",
|
||
"plt.plot(strom, \n",
|
||
" [Spannung(value, para[0]) for value in strom], \n",
|
||
" ls ='dashed',\n",
|
||
" color='orange',\n",
|
||
" label = f'Fitgerade mit R = {para[0]:0.2f} +/- {pcov[0,0]**(1/2):0.2f} ohm'\n",
|
||
" )\n",
|
||
"\n",
|
||
"plt.legend()\n",
|
||
"plt.ylabel('Spannung [V]')\n",
|
||
"plt.xlabel('Strom [mA]')\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Das Ergebnis sieht bereits ganz gut aus, allerdings kennt hier unsere Funktion `curve_fit` die Fehler unserer Messwerte noch garnicht. Da dies sehr unphysikalisch ist lasst uns das ganze nochmal mit Unsicherheiten wiederholen: "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:50:00.797625Z",
|
||
"start_time": "2019-09-30T05:50:00.416158Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"para2, pcov2 = curve_fit(Spannung, \n",
|
||
" strom, \n",
|
||
" spannung,\n",
|
||
" sigma=spannung_error, # <-- Diesesmal mit Fehler\n",
|
||
" absolute_sigma=True # <-- Diesen Option müssen wir auf Wahr setzen, da \n",
|
||
" # wir in der Regel absolute und keine relativen \n",
|
||
" # Unsicherheiten messen.\n",
|
||
" )\n",
|
||
"\n",
|
||
"plt.errorbar(strom, \n",
|
||
" spannung,\n",
|
||
" xerr=strom_error,\n",
|
||
" yerr=spannung_error, \n",
|
||
" ls='', \n",
|
||
" marker='d', \n",
|
||
" mfc='orange', \n",
|
||
" mec='k', \n",
|
||
" ms=7,\n",
|
||
" ecolor='k', \n",
|
||
" elinewidth=2, \n",
|
||
" capsize=5, \n",
|
||
" capthick=2, \n",
|
||
" label='Messwerte aus A. 5'\n",
|
||
" ) \n",
|
||
"plt.plot(strom, \n",
|
||
" [Spannung(value, para2[0]) for value in strom], \n",
|
||
" ls ='dashed',\n",
|
||
" color='orange',\n",
|
||
" label = f'Fitgerade mit R = {para2[0]:0.2f} +/- {pcov2[0,0]**(1/2):0.2f} ohm'\n",
|
||
" )\n",
|
||
"\n",
|
||
"plt.legend()\n",
|
||
"plt.ylabel('Spannung [V]')\n",
|
||
"plt.xlabel('Strom [mA]')\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Wie ihr sehen könnt ist der Wert für den Widerstand zwar gleich geblieben, jedoch die Unsicherheit des Wertes hat sich erhöht.\n",
|
||
"\n",
|
||
"Wie gut denkt ihr fittet unsere obige Funktion unsere Messdaten? Sehr gut? Gut? Befriedigend? Oder doch eher schlecht? Wäre es nicht gut ein Maß für die Güte des Fits zu haben? Wie könnte ein solches Maß aussehen?\n",
|
||
"\n",
|
||
"Ihr habt das entscheiden Kriterium bereits kennen gelernt, bei der Methode der kleinsten Quadrate geht es darum das $\\chi^2$ zu minimieren sprich klein zu machen. Gucken wir uns hierzu erst noch einmal an wie sich das $\\chi^2$ berechnet:\n",
|
||
"\n",
|
||
"$$ \\chi(\\phi_1 ... \\phi_N)^2 = \\sum_{i = 1}^{N} \\frac{ (y_i - \\lambda(x_i; \\phi))^2}{\\Delta y_i^2}$$\n",
|
||
"\n",
|
||
"Dies bedeute in unserem Fall:\n",
|
||
"\n",
|
||
"$$ \\chi(R)^2 = \\sum_{i = 1}^{N} \\frac{ (U_i - u(I_i; R))^2}{\\Delta U_i^2}$$\n",
|
||
"\n",
|
||
"wobei hier groß $U$ unsere gemessenen Spannung und klein $u$ unsere Funktion entspricht."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:54:46.981989Z",
|
||
"start_time": "2019-09-30T05:54:46.964058Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"chi_2 = [ (u - Spannung(I, para2[0])/du)**2 for I,u,du in zip(strom, spannung, spannung_error)]\n",
|
||
"chi_2 = sum(chi_2)\n",
|
||
"print(f'Das chi-qudrat ist {chi_2:.0f}')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Wie vergleicht sich dieses $\\chi^2$ nun mit einer Funktion welche unsere Daten schlechter beschreibt. Zum Beispiel sofern wir die Spannung über die Funktion \n",
|
||
"\n",
|
||
"$$ U(R,I) = R \\cdot I + C $$\n",
|
||
"\n",
|
||
"beschreiben würden, also zusätzlich einem konstantem Offset."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2019-09-30T05:54:48.503957Z",
|
||
"start_time": "2019-09-30T05:54:48.488400Z"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"def Spannung2(I, R, C):\n",
|
||
" return R * I + C \n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"para3, pcov3 = curve_fit(Spannung2, \n",
|
||
" strom, \n",
|
||
" spannung,\n",
|
||
" sigma=spannung_error,\n",
|
||
" absolute_sigma=True \n",
|
||
" )\n",
|
||
"\n",
|
||
"chi_2_new = [ (u - Spannung2(I, *para3)/du)**2 for I,u,du in zip(strom, spannung, spannung_error)]\n",
|
||
"chi_2_new = sum(chi_2_new)\n",
|
||
"print(f'Chi-qudrat nach URI: {chi_2:.0f}\\nChi-qudrat nach URIC: {chi_2_new:.0f}')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Wie ihr sehen könnt ist das $\\chi^2$ für unsere zweite Funktion etwas größer als für das klassische ohm'sche Gesetzt. Somit würden wir unsere zweiten Ansatz verwerfen. \n",
|
||
"\n",
|
||
"Damit man für einen gegebene Datensatz nicht hunderte von verschiedene Funktionen durchprobieren muss gibt es für das $\\chi^2$ eine allgemeine Faustregel, welche den berechneten $\\chi^2$-Wert mit der Anzahl unserer Freiheitsgrade vergleicht. Die Anzahl an Freiheitsgrade ist allgemeinhin gegeben als *Anzahl der Messwerte - Anzahl der Funktionsparameter* ($m - n$).\n",
|
||
"\n",
|
||
"1. Sofern $\\chi^2/\\text{ndof} >> 1$: sollte die Hypothese bzw. die Fitfunktion angezweifelt werden. Sie beschreibt in diesem Fall die Messdaten nur unzureichend. (Bzw. sollte $\\chi^2/\\text{ndof} > 1$ kann dies auch bedeuten, dass eure Unsicherheiten unterschätzt sind)\n",
|
||
"2. Sofern $\\chi^2/\\text{ndof} \\approx 1$: beschreibt die Hypothese bzw. die Fitfunktion die Daten wie erwartet und wird nicht abgelehnt. \n",
|
||
"3. Falls $\\chi^2/\\text{ndof} << 1$ beschreibt die Hypothese bzw. die Fitfunktion die Daten wesentlich besser als erwartet. In diesem Fall heißt es nicht, dass unsere Hypothese falsch ist, aber man sollte überprüfen ob die gemessenen Fehler nicht überschätzt worden sind (oder eine Korrelation zwischen denn Messfehlern vor liegt). \n",
|
||
"\n",
|
||
"Sofern ihr eine Arbeit schreibt und eure **Goodness-of-the-Fit** ($\\chi^2/\\text{ndof}$) angeben wollt so gebt immer beides an, das $\\chi^2$ und die Anzahl an Freiheitsgraden ndof. Beide Werte getrennt habne einen größeren Informationsgehalt als der Resultierende Quotient (genaueres lernt ihr in z.B. in der Vorlesung *Statistik, Datenanalyse und Simulationen* im Master)."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<div class=task>\n",
|
||
" \n",
|
||
"#### Aufgabe 6.: PGP Auswertung:\n",
|
||
"\n",
|
||
"Jetzt seid ihr ein letztes mal gefordert. In dieser Aufgabe wollen wir alles was wir heute gelernt haben nochmal reflektieren und anwenden. Erstellt hierfür ein neues Jupyter-Notebook und bearbeitet die Aufgaben im Skript. Sofern ihr Fragen bzw. Probleme habt vergesst nicht auf die folgenden Hilfsmöglichkeiten zurückzugreifen:\n",
|
||
"\n",
|
||
"1. Verwenden der IPython-Hilfe unter Verwendung der shift + tab Tasten.\n",
|
||
"2. Die ausführlichen Dokumentation von Python und das Angebot etlicher nützlicher Hilfsbeiträge in verschiedenen Foren (z.B. stackoverflow) im Internet.\n",
|
||
"3. Fragt bei den Assistenten nach während der Stunde nach bzw. nutzt den Emailkontakt auf der [gitlab Seite](https://gitlab.rlp.net/hoek/pgp1-python-einfuehrung/tree/master). \n"
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"kernelspec": {
|
||
"display_name": "Python 3",
|
||
"language": "python",
|
||
"name": "python3"
|
||
},
|
||
"language_info": {
|
||
"codemirror_mode": {
|
||
"name": "ipython",
|
||
"version": 3
|
||
},
|
||
"file_extension": ".py",
|
||
"mimetype": "text/x-python",
|
||
"name": "python",
|
||
"nbconvert_exporter": "python",
|
||
"pygments_lexer": "ipython3",
|
||
"version": "3.7.3"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 2
|
||
}
|