"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",
"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 experimentellen Daten mit sich bringt. Um Sie bestens auf die Anforderungen im **physikalische Grundpraktikum (PGP)** vorzubereiten lernen wir im Folgenden wie man:\n",
"Damit Sie das neu erlernte Wissen direkt vertiefen können, wird dieses Notebook an verschiedenen Stellen kleinere Aufgaben für Sie bereit halten. Die Aufgaben sind durch orangefarbene Boxen hervorgehoben. Es gilt alle Aufgaben zu bearbeiten! "
"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",
"Im folgenden wollen wir erst einmal mit den Grundlagen des Notebooks vertraut machen. Insbesondere wollen wir lernen, wie wir eine Markdown- und eine Code-Zelle erstellen, bearbeiten und ausführen. \n",
"* Erstellt zunächst eine Code-Zelle unterhalb dieser Aufgaben Zelle und berechnen Sie die Summe zweier beliebiger ganzer Zahlen. Gehen Sie dabei wie folgt vor:\n",
" 1. Klicken Sie die Zelle dieser Aufgabe an, so dass die Zelle eine blaue Umrandung bekommt (je nach Bildschirmauflösung könnt Sie nur links einen blauen Balken erkennen). Sie befinden sich nun im so genannten \"Command Modus\". In diesem Modus könnt Sie mit Hilfe der Pfeiltasten durch das Notebook navigieren oder die Struktur des Notebooks bzw. seiner Zellen mit Hilfe von Tasten/Tastenkombinationen modifizieren.\n",
" 2. Benutzen Sie nun die Taste **B** um eine Code-Zelle unterhalb (**B**elow) dieser Zelle zu erstellen. Sie werden feststellen, dass Ihr Navigator direkt zu der neu erstellten Zelle springt (blaue Umrandung).\n",
" 3. Um nun diese neu erstellte Code-Zelle zu editieren, klicken Sie diese mit dem Mauszeiger an. Die Zellenumrandung sollte von Blau auf Grün wechseln. Dies zeigt an, dass Sie sich nun im Editiermodus für dieses Zelle befinden.\n",
" 4. Nun können Sie die Summe aus zwei beliebigen ganzen Zahlen mit Hilfe des Syntax\n",
" 5. Um diese Code-Zelle auszuführen, müssen Sie anschließend die Tastenkombination: **STRG + ENTER** oder **SHIFT + ENTER** benutzen. Das Ergebnis wird direkt unterhalb der Zelle angezeigt.\n",
" \n",
" \n",
"* Erstellen Sie nun eine Markdown-Zelle oberhalb ihrer Code-Zelle. Hierfür müssen Sie wie folgt vorgehen: \n",
" 1. Klicken Sie die zuvor erstellte Code-Zelle an. Die Zelle sollte eine grüne Umrandung anzeigen, da Sie sich nach wie vor im Editiermodus befinden.\n",
" 2. Drücken Sie die **ESC**-Taste um vom Editier- in den Command-Modus zu wechseln (blaue Umrandung).\n",
" 3. Drücken Sie nun die Taste **A** um eine neue Code-Zelle oberhalb (**A**bove) Ihrer angewählten Zelle zu erstellen. Der Navigator wird wieder automatisch zu der neu erstellten Zelle springen.\n",
" 4. Drücken Sie nun die Taste **M** um die Code-Zelle in eine Markdown-Zelle zu verwandeln. Sie werden feststellen, dass eine Markdown-Zelle im Vergleich zu einer Code Zelle kein \"In []:\"-Anzeige links der Zelle hat. \n",
" 5. Wechseln Sie nun in der Markdown-Zelle in den Editiermodus (grüne Umrandung) in dem Sie diese anklicken. \n",
" 6. Fügen Sie nun die folgenden Objekte in die Markdown-Zelle mit dem entsprechenden Syntax ein:\n",
" * Eine numerische Aufzählung (1. 2. und 3.) wobei 1. ein fett gedrucktes Wort 2. ein kursive geschriebenes Wort und 3. ein Wort im true type beinhalten soll. \n",
"In *Kapitel 0* wurden Ihnen bereits alle benötigten Formatierungen angezeigt. Sie können diese nachgucken in dem Sie in das Notebook *Kapitel 0* wechseln und die entsprechende Markdown-Zelle mittels Doppelklick anwählen. \n",
"Des weiteren können Sie [hier](https://www.cheatography.com/weidadeyue/cheat-sheets/jupyter-notebook/) eine Auflistung weiterer Jupyter-Befehle finden."
"Neben dem einfachen Summieren zweier Zahlen ermöglicht uns Python natürlich auch das Verwenden 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",
"Um unsere Rechnungen besser zu strukturieren, können wir Zahlen auch Variablen zuordnen. Hierzu verwenden wir das Gleichheitszeichen um einer Variablen (*links*) einem Wert (*rechts*) zuzuordnen."
"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. "
"In der oberen Zelle ist **c** vom Datentyp `int` (*Integer*) was einer Ganzenzahl entspricht. In der unteren Zelle jedoch ist **c** vom Datentyp `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 Typ `float` sein muss. \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 wofür diese verwendet werden, werden Sie noch im **PGP2** lernen. \n",
"Die zurückgelegte Distanz eines Objekts, welches eine beschleunigte Bewegung ausführt (z.B. der freie Fall einer Kugel in einem Gravitationsfeld), kann mit Hilfe von \n",
"beschrieben werden. Hierbei beschreibt $t$ die verstrichene Zeit, $a$ die Beschleunigung, $v_0$ die Startgeschwindigkeit und $s_0$ die Startposition des Objekts. Ersteklen Sie unterhalb der Aufgabe eine neue Code-Zelle und berechnen Sie die folgenden Werte:\n",
"Sofern ihr alle Berechnungen innerhalb einer Zelle ausführen wollt, könnt ihr mit Hilfe der `print`-Funktion eure Ergebnisse \"ausdrucken\"/anzeigen lassen. Geht dabei wie folgt vor:\n",
"Hier noch ein kleiner Kommentar zum auflösen der Formel. Wir wollen den Zeitpunkt t1 wissen an dem das Objekt auf dem Boden aufkommt (s(t1) = 0). Sprich wir müssen die obige Formel wie folgt umstellen:\n",
"wobei hier s(t1)=0 und s0 = 1.2 m ist. Solltet ihr einfach 1.2 m durch eine der Beschleunigungen Teilen bekommt ihr durch die Wurzel eine komplexe Zahl."
"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 (z.B. einem Passwort), Dateiname bei einer Installation, oder bei Textrückgaben von Programmen. Letzteres haben Sie bereits in Aufgabe 2 a. mit Hilfe der `print`-Funktion gesehen.\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 Zeichenketten Achsenbeschriftungen an Graphen anbringen können. \n",
"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: "
"Hierraus resultiert ein Widerstand von {R}+/-{dR:.2f} kOhm ''') "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Hierbei zeigt `:` an, dass sie eine spezielle Formatierung verwenden möchten. Die Zahl hinter dem `.` gibt an wie viele Nachkommastellen Sie anzeigen lassen möchten. Das `f` bedeutet, dass es sich bei der Zahl um eine Gleitkommazahl handelt."
"Lassen Sie nun Ihre berechneten Werte aus Aufgabe 2 mit Hilfe von `print` erneut ausgeben. Nutzen Sie jedoch dieses Mal **Formatstrings** für eine schönere und bedeutungsvollere Rückgabe. Achten Sie dabei ins besonders auf:\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 Gesetzes, welches durch \n",
"beschrieben wird, angucken. Hierbei wird die Spannung $U$ durch die Variablen $R$ (Widerstand) und $I$ (Strom) beschrieben. Dies gilt auch analog für Funktionen in einer Programmiersprache:"
"Bitte beachten Sie, dass die Rückgabe `return` der Funktion mit Hilfe der Tab-Taste eingerückt wurde. Dieser Syntax wird von Python vorgegeben uns muss eingehalten werden.\n",
"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}$:"
"Neben mathematischen Funktionen, können Funktionen in einer Programmiersprache auch viel allgemeinere Aufgaben erfüllen bzw. komplexe Algorithmen beinhalten. Hierfür benötigen wir meist mehr als nur eine Zeile. Um Python verständlich zu machen, dass mehre Zeilen zu einer Funktion gehören müssen wir die entsprechenden Zeilen wir zuvor den `return`-Befehl einrücken. "
"Bitte beachten Sie, das Variablen welche in einer Funktion definiert und genutzt werden auch nur dort zur Verfügung stehen. Versuchen Sie die entsprechenden Variablen im regulär im Notebook zu verwenden werden Sie einen Fehler bekommen."
"Bei einem $500\\,\\Omega$ Widerstand wird eine Spannung $U$ von 5, 10, 20 und 50 Volt angelegt. Wie hoch sollte der jeweils entsprechende Strom $I$ ausfallen und welche Leistung wird in dem Widerstand umgesetzt? \n",
"Des Weiteren nehmen Sie an, dass Ihr Widerstand einen Fehler von $+/-20\\,\\Omega$ und ihre angelegte Spannung eine Ungenauigkeit von $+/-10\\,\\%$ aufweist. Wie groß wäre der Fehler des gemessenen Stroms bei ihrer $50\\,$V Messung? Benutzen Sie hierfür die Gaus'sche Fehlerfortpflanzung und definieren Sie die entsprechende Funktion in Python.\n",
"Es ist ratsam gleich von Anfang an Funktionen zu dokumentieren. Hierzu dienen in Python die sogenannten `Doc-Strings`. Sie beinhalten Informationen über die Funktion selbst, ihre verwendeten Parameter und ihrer Ausgabe. Zum Beispiel für das Ohmschen Gesetzes würde ein solcher Doc-String wie folgt aussehen:"
"Damit uns eine Programmiersprache wie Python Arbeit abnehmen kann, sollte es auch möglich sein größere Datenmengen, wie z.B. die Werte einer Messtabelle, in einer Variablen zu speichern. Python bietet hierfür mehrer verschiedene Konzepte an. Jedes dieser Konzepte hat unterschiedlichen Stärken und Schwächen. Die gängigsten Methoden sind listen, tuple, bzw. sogenannte numpy.arrays und pandas.dataframes. Aufgrund der limitierten Zeit im PGP 1 werden wir uns hier lediglich mit zwei dieser vier Methoden auseinander setzen. \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:"
"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",
"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-10-27T12:25:06.492972Z",
"start_time": "2019-10-27T12:25:06.480376Z"
}
},
"outputs": [],
"source": [
"Messwerte1.append('Wert5')\n",
"Messwerte1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-27T12:25:06.509050Z",
"start_time": "2019-10-27T12:25:06.496701Z"
}
},
"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",
"Leider zählt Python doch richtig. In Python läuft der Index von Objekten in einer Liste 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:"
"Neben `insert`, `append` und `slicing` bietet Python noch ein paar weitere Listenmanipulationen an. Mit Hilfe des `+` Operators können Sie die Werte in einer Liste direkt an eine andere Liste anfügen."
"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. "
"Erstellen Sie für jede Spalte der nachfolgende Messtabelle eine Liste, welche die Messdaten beinhaltet. Benutzen Sie anschließend den `append` Befehl um die Daten jeder Spalte an eine weitere Liste namens *daten* anzuhängen. \n",
"Am Python-Versuchstag selbst wollen wir anhand der Messdaten zur Bestimmung der Fallbeschleunigung auf Planet ?? das fitten von Funktionen mittels $\\chi^2$ üben. Als Vorbereitung hierfür sollen Sie die Messdaten der gemessenen Zeiten und Höhen so wie ihre Fehler als Listen in Python eintippen. \n",
"Darüber hinaus definieren Sie sich eine Funktion $h(t)$ welche proportional zu $g_{??}$ ist. Diese Funktion soll am Ende des Versuchstages gegen die Messdaten in einem Höhe-gegen-Zeit Diagramm gefittet werden.\n",
" \n",
"**Tipp:**\n",
" \n",
"Um welche Art von Bewegung handelt es sich bei einem Freienfall im luftleeren Raum?\n",