diff --git a/theme1/PE100/PE100-02TypesVarsAndOperators.ipynb b/theme1/PE100/PE100-02TypesVarsAndOperators.ipynb new file mode 100644 index 0000000..8cb5d2d --- /dev/null +++ b/theme1/PE100/PE100-02TypesVarsAndOperators.ipynb @@ -0,0 +1,759 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "09f4eac4-93a1-4b12-8524-fe397f7aec67", + "metadata": {}, + "source": [ + "Niklaus Wirth was one of the founding giants of Computer Science. He wrote an introductory textbook whose title neatly summed up the act and art of programming: [Algorithms + Data Structures = Programs](https://en.wikipedia.org/wiki/Algorithms_%2B_Data_Structures_%3D_Programs). Data Structures are how information is stored in a computer, and algorithms are the instructions the computer applies to transform that data.\n", + "\n", + "Let's begin our exploration of Python by looking at a few basic kinds of data. Watch the video in the next cell (right below this one, even though it might not be obvious it's a second cell) and it will guide you through some experiments." + ] + }, + { + "cell_type": "markdown", + "id": "a122c50c-a867-4e93-9cca-6019c73fedbb", + "metadata": {}, + "source": [ + "*Video for the next four code cells (ints, reals, strings, default action is printing) goes here*" + ] + }, + { + "cell_type": "markdown", + "id": "2f37dae2-3f6f-4331-8394-b2d141123de3", + "metadata": {}, + "source": [ + "To run the code in a cell, first click in the cell to select it. Then you can either\n", + "1. Go to the \"Run\" menu and choose \"Run Selected Cells\", or\n", + "1. Just press Shift + Enter." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "e16d42ed-aee8-409f-a5ed-2bd58a262890", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "403.616\n" + ] + } + ], + "source": [ + "print (403.616)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d1fb3e9-c37d-4867-ac04-1b1a4f907cff", + "metadata": {}, + "outputs": [], + "source": [ + "403.616" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ce6d68bb-7c98-4dcf-894e-e519dc7fb367", + "metadata": {}, + "outputs": [], + "source": [ + "print (\"the quick brown fox\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b907d685-1c2b-4dc4-a627-bf8c98f2b872", + "metadata": {}, + "outputs": [], + "source": [ + "print ('jumped over the lazy dogs')" + ] + }, + { + "cell_type": "markdown", + "id": "b77ca3d5-4a91-4c88-8a51-ec08a020c3fe", + "metadata": {}, + "source": [ + "At this point, we can use Python and Jupyter Lab as a scientific calculator. We have some *literals* of different types (int, real, and string, so far) and we can print them out with the ```print()``` *statement*. In fact, if we don't explicitly print anything at the end of a cell, Python will show us the last value that was computed.\n", + "\n", + "\n", + "\n", + "Take a look at the next video" + ] + }, + { + "cell_type": "markdown", + "id": "8c570718-4ec3-45a7-8fd7-5d1d4dd39d41", + "metadata": {}, + "source": [] + }, + { + "cell_type": "markdown", + "id": "c20f366f-062b-435b-9d03-bd7f0d6624e7", + "metadata": {}, + "source": [ + "Like any programming language, Python lets you \"do math\" and lots of other things. Let's take a look at some of the basic \"operators\". In all of the code-containing cells through this course, try to predict what will happen first, and then run the code." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "99b2c0e4-14aa-466a-8a25-f22604271bb8", + "metadata": {}, + "outputs": [], + "source": [ + "2+2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90383055-7b1b-47ca-8e6b-38fef949ee8f", + "metadata": {}, + "outputs": [], + "source": [ + "2*8" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "5c7336fe-ebd6-4596-8dd3-7d85e24c729d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "6-4" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ffe5e208-cd79-46ba-9985-68f2b414aa5d", + "metadata": {}, + "outputs": [], + "source": [ + "7*6" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28754cd0-96b2-4e55-9cc7-b3eb978c2f93", + "metadata": {}, + "outputs": [], + "source": [ + "16/3" + ] + }, + { + "cell_type": "markdown", + "id": "86aaa49c-f380-4f39-b877-63835aa2a940", + "metadata": {}, + "source": [ + "Besides the \"classic\" operators, there are some handy extras:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "59753692-d36a-40d7-858b-04fcd629b4c1", + "metadata": {}, + "outputs": [], + "source": [ + "16//3" + ] + }, + { + "cell_type": "markdown", + "id": "ee37f4fe-6000-4286-b292-58ee8b9b082e", + "metadata": {}, + "source": [ + "What happened there? The ```//``` operator does *integer division* - it returns the whole number part of the answer, just like when we learned division in elementary school." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dac9ed9b-95d6-41b3-ab3b-0b1229d8ef15", + "metadata": {}, + "outputs": [], + "source": [ + "16%3" + ] + }, + { + "cell_type": "markdown", + "id": "e6e3417e-4b4e-489d-b8a1-72a28a777090", + "metadata": {}, + "source": [ + "The ```%``` operator returns the remainder. This is also called \"modulo\", and the above would be pronounced \"sixteen mod 3\"." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1177f56b-554c-4c41-b85a-af6a2bc73a6a", + "metadata": {}, + "outputs": [], + "source": [ + "2**8" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b991148-b2ad-4f90-866a-ff1c7a227007", + "metadata": {}, + "outputs": [], + "source": [ + "4**2.718281828459045" + ] + }, + { + "cell_type": "markdown", + "id": "4593e2a6-b6e0-426a-b626-59422fbec5d4", + "metadata": {}, + "source": [ + "The ```**``` operator does exponentiation. The *arguments* can be integers or they can be real numbers.\n", + "Naturally, operators can be combined into arbitrarily long *expressions*." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f625e6fc-3ca6-47b7-ba35-76c420da2317", + "metadata": {}, + "outputs": [], + "source": [ + "3*4*5" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "49d8fdb7-7d0c-43bb-9db8-b4dd3700fc5e", + "metadata": {}, + "outputs": [], + "source": [ + "6+4*5" + ] + }, + { + "cell_type": "markdown", + "id": "fc93163d-ae79-4b9f-af45-e7b2a6b1e002", + "metadata": {}, + "source": [ + "Notice what happens when we use different operators. They are applied in the \"My Dear Aunt Sally\" order of precendence (multiplication, division, addition, subtraction).\n", + "\n", + "Order of operations:\n", + "* Exponentiation: ```**```\n", + "* Multiplication, Division, Remainder: ```* / // %```\n", + "* Addition and Subtraction: ```+ -```\n", + "\n", + "Within the same level, operators are applied left-to-right. 8-5+2 is evaluated as 3+2 and yields 5. The exception is exponentiation: 2 ** 3 ** 4 is treated as 2 ** 81 and yeilds an annoyingly large number" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f0ff4ca-da1e-4097-873e-cb61bbd7a22f", + "metadata": {}, + "outputs": [], + "source": [ + "print (2**3**4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4aebc6f8-d3c5-422e-8d31-6664552ad4ce", + "metadata": {}, + "outputs": [], + "source": [ + "print (2**81)" + ] + }, + { + "cell_type": "markdown", + "id": "21530437-db65-4639-a928-13808271cc0e", + "metadata": {}, + "source": [ + "Unless we just use Jupyter as a big, expensive scientific calculator, we need a way to store data. *Variables* were invented for just that purpose, and virtually every language has them. Think of them as a place to store data of some kind, and that place has a name. They behave in Python just like you'd expect." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6350b83c-2d85-4cc2-a54c-d8bf18c6d42c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "42\n" + ] + } + ], + "source": [ + "answer = 42\n", + "print(answer)" + ] + }, + { + "cell_type": "markdown", + "id": "c6b7e561-c1a0-4606-8210-6bf67d8a1dd4", + "metadata": {}, + "source": [ + "We just created a variable named ```answer``` and gave it the value 42. Variables are long-lived - later we'll talk about just how long when we start writing our own functions, but until then our variables last as long as Python (or in our case, Jupyter) is running. Take a look - answer is still there." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "56538fe2-b464-4fe1-a3e0-23ff1b555bda", + "metadata": {}, + "outputs": [], + "source": [ + "print(answer)" + ] + }, + { + "cell_type": "markdown", + "id": "2331f76d-50d7-4f93-82e5-67d339dc27a4", + "metadata": {}, + "source": [ + "The value stored in a variable can change. It can even change type:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "58211df3-28e4-4829-b5ca-ab9174213bcd", + "metadata": {}, + "outputs": [], + "source": [ + "weight = 60\n", + "weight = 70\n", + "print(weight)\n", + "weight = \"not very much.\"\n", + "print(weight)" + ] + }, + { + "cell_type": "markdown", + "id": "50f4b8a8-d02f-496b-a59a-ed147ac30f28", + "metadata": {}, + "source": [ + "We can declare many variables, and we can \"do things\" with them just like we can when we type in numbers or strings." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "74124737-2572-46e4-a696-a91f35cea69b", + "metadata": {}, + "outputs": [], + "source": [ + "volts = 120\n", + "amps = 4\n", + "watts = volts * amps\n", + "watts" + ] + }, + { + "cell_type": "markdown", + "id": "e60eb2cf-ffdd-42a6-aa53-3cb8ed98e673", + "metadata": {}, + "source": [ + "In the last line, we just put ```watts``` because Jupyter automatically prints what the last line evaluates to (unless there has been a print statement before that).\n", + "\n", + "We can use variables to change the *order of operations*. Let's see the average price of two people's meals:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1600a8b8-7222-4bf7-8f63-4fce4b3bd56d", + "metadata": {}, + "outputs": [], + "source": [ + "total = 22.41 + 19.45\n", + "average = total / 2\n", + "average" + ] + }, + { + "cell_type": "markdown", + "id": "0f7bf70a-a6dd-48b4-ac9a-8c55eab3fed2", + "metadata": {}, + "source": [ + "That's the right answer. If we hadn't done that, we would have gotten" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "199989df-a1c7-41fd-8088-19107e5025c3", + "metadata": {}, + "outputs": [], + "source": [ + "22.41 + 19.45 / 2" + ] + }, + { + "cell_type": "markdown", + "id": "5de1c48e-bab6-40c0-a35e-3692dda0c7ab", + "metadata": {}, + "source": [ + "which is utterly wrong. Beware of the order of operations... it is a frequent source of bugs in scientific programming.\n", + "\n", + "For the most part, you can pick whatever name makes sense for a variable, but there *are* some rules. When choosing a name:\n", + "1. No keywords (```False``` won't work.)\n", + "1. No spaces (```sample thickness``` is invalid)\n", + "1. The first character **must** be one of\n", + " * a-z, or A-Z, or _. (the underscore character)\n", + " * As a result, no numbers (3rd_sample_holder is invalid)\n", + "1. **After** the first character, you can then have numbers (sample_holder_3 is perfectly valid)\n", + "1. No other symbols are allowed (exploded&destroyed_spectrometers is invalid, and probably suggests it's time to review lab safety procedures).\n", + "\n", + "**Note: Uppercase vs. Lowercase matters!** ```Bevatron``` is not the same variable as ```bevatron```" + ] + }, + { + "cell_type": "markdown", + "id": "58272db5-10c0-4c33-afef-354cd9c83dfb", + "metadata": {}, + "source": [ + "We've hinted that variables have a \"type\", and that the type can change if it needs to. The way it works is that variables keep track of what *type* they are (integer, real number, or string) and what their \"value\" is. We can even interrogate a variable as see what type it is:" + ] + }, + { + "cell_type": "markdown", + "id": "56a0db35-2a45-45ca-9b27-631b08f3f91a", + "metadata": {}, + "source": [ + "Lines of code in any language can get very complicated (see \"scientific programming\", above). What happens when you run out of horizontal space and you need to go to the next line? Let's see:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2fc7b814-7512-4fb5-b81b-b103599d0cba", + "metadata": {}, + "outputs": [], + "source": [ + "my_number = 42\n", + "my_string = \"was that really the right answer?\"\n", + "\n", + "first_type = type(my_number)\n", + "second_type = type(my_string)\n", + "print(first_type, second_type)" + ] + }, + { + "cell_type": "markdown", + "id": "6f477725-51ad-487a-8b9f-bdc8e520cb1a", + "metadata": {}, + "source": [ + "The type of a variable matters. Let's create a variable with an integer in it and another with a string. Then let's do some math:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9be5ce2d-e475-442c-bcdd-1ebe1668cf6b", + "metadata": {}, + "outputs": [], + "source": [ + "first_thing = 6\n", + "second_thing = \"7\"\n", + "\n", + "print (first_thing + second_thing)" + ] + }, + { + "cell_type": "markdown", + "id": "f8ff396b-d067-485c-8c0a-f9069991d2dd", + "metadata": {}, + "source": [ + "# TODO - type coercion" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c4e88656-191d-479f-9dcf-d5c8020a1cce", + "metadata": {}, + "outputs": [], + "source": [ + "4+2\n", + "+3" + ] + }, + { + "cell_type": "markdown", + "id": "9552bdf3-e316-4151-859e-2428672a4e9d", + "metadata": {}, + "source": [ + "That isn't right. The last line, ```+3```, was evaluated and printed as the result of running that cell. It turns out, if we need to continue an expression on the next line, we just end the line with a backslash ```\\``` and press enter. It has to be a backslash, by the way, and **cannot** be the forward slash like we use for division." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a3f81522-1f91-4fc5-92d8-02d8d88d208f", + "metadata": {}, + "outputs": [], + "source": [ + "4+2\\\n", + "+3" + ] + }, + { + "cell_type": "markdown", + "id": "e7f8849e-ea52-460d-8e89-9be07b9f4433", + "metadata": {}, + "source": [ + "Time for an exercise! Try to predict what will be printed when you run the next cell. Then, run the next cell and see how you did. If you miss one, make sure you figure out what happened before you go. I know, we're professionals, I shouldn't have to say that..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7509f39-e1b5-4581-9294-6837652e2448", + "metadata": {}, + "outputs": [], + "source": [ + "print(1 + 3 + 5 * 4 / 2)\n", + "print(7 % 2 * 10)\n", + "big_num = 1 + 2 + 3 + 4 \\\n", + " + 5 + 6\n", + "print(big_num)" + ] + }, + { + "cell_type": "markdown", + "id": "43f51975-6aa2-4965-9328-ec020dc9eb21", + "metadata": {}, + "source": [ + "Now write an expression to average three numbers (12, 14, and 66), divide the result by three, and square it. You can use the code cell right below here:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bcefed42-ccac-4fc4-9ae5-f55c3dd96138", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "3f85735b-86f2-456c-9886-e93f8ee310d0", + "metadata": {}, + "source": [ + "At the beginning of this notebook, we casually mentioned \"strings\" without saying what they are. They're just \"sequences of characters\". And these can be any kind of characters - the English alphabet, the Hungarian alphabet, hiragana... it doesn't matter." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2db2513c-9836-444f-bb61-0a8e65d12eac", + "metadata": {}, + "outputs": [], + "source": [ + "print(\"I'll see you mañana, assuming I don't get irradiated to death.\")" + ] + }, + { + "cell_type": "markdown", + "id": "413f8e00-ffb5-4304-820f-80fd214ac8dc", + "metadata": {}, + "source": [ + "Some, probably most, languages contain strings inside \"double quotes\", ```\"```, which is shift+apostrophe on US English keyboards. Other languages (SQL and Pascal are the only two I can think of) use single quotes: ```'```. Python let's you use either one. You *do* have to be consistent in each string, but it can vary from one string to the next:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "614bce71-4826-4646-80b5-c8681aec3581", + "metadata": {}, + "outputs": [], + "source": [ + "print(\"double quotes work\")\n", + "print('single quotes also work')\n", + "print('but do not try to mix the two in one string!\"" + ] + }, + { + "cell_type": "markdown", + "id": "8a4046d5-9174-4726-9fe2-26fa662fe8f6", + "metadata": {}, + "source": [ + "Because we can use either type of quotation mark, we can exploit that to let us put quotation marks into strings:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d7be27f7-1a62-4e9f-a488-99fd10f3e424", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Don't put explosive mixtures in the spectrometer, please.\n", + "Of course he was warned... \"Do not turn the spectrometer into a bomb, please\" but I am sure he ignored that.\n" + ] + } + ], + "source": [ + "print(\"Don't put explosive mixtures in the spectrometer, please.\")\n", + "print('Of course he was warned... \"Do not turn the spectrometer into a bomb, please\" but I am sure he ignored that.')" + ] + }, + { + "cell_type": "markdown", + "id": "168afacb-86ec-4ae6-9a89-ae4d27188e39", + "metadata": {}, + "source": [ + "That lets us embed whichever kind of quotation mark we need into a string.\n", + "\n", + "But what if we need to embed **both** kinds of quotes into one string? We're in luck: we can use the backslash character again to \"quote\" our quotation mark. In fact, we can quote any character with it if we need to." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "2cd4377a-518b-4df0-87f2-bb4931185921", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "We told him \"Hexanitrohexaazaisowurtzitane and spectrometers don't mix, buddy\", but we're pretty sure he ignored us.\n" + ] + } + ], + "source": [ + "print(\"We told him \\\"Hexanitrohexaazaisowurtzitane and spectrometers don't mix, buddy\\\", but we're pretty sure he ignored us.\")" + ] + }, + { + "cell_type": "markdown", + "id": "8e2e7c07-3faa-4e55-a76e-a33e95878380", + "metadata": {}, + "source": [ + "That sentence contains three things, inside the string itself:\n", + "1. Double Quotes to surround a direct quotation\n", + "2. A single quote, also called an apostrophe depending on how it's used, to make a contraction, and\n", + "3. A totally not incredibly awesome/terrifying molecule you have to google to believe.\n", + "\n", + "OK, I'll save you the trouble. [Prepare to lose most of a day's productivity](https://www.science.org/content/blog-post/things-i-won-t-work-hexanitrohexaazaisowurtzitane). You're welcome." + ] + }, + { + "cell_type": "markdown", + "id": "08ded9db-0522-4fcf-a0ae-bfb6a51d2ae8", + "metadata": {}, + "source": [ + "There is one last kind of string literal. Sometimes you need a string that is several lines long. The \"triple quote\" is a way to do it. You have to use three double-quotes in a row:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a967aae-73d7-48b4-b6b9-91e9c8863b59", + "metadata": {}, + "outputs": [], + "source": [ + "gigantic = \"\"\"This is the first line,\n", + "This is the second,\n", + "and this is the third and final line of my string.\"\"\"\n", + "print(gigantic)" + ] + }, + { + "cell_type": "markdown", + "id": "9ee25637-2d26-4dc5-825f-f9dc4761e492", + "metadata": {}, + "source": [ + "Triple quotes are also an easier way to embed mixed kinds of quotation marks into strings:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2652937d-4643-4c76-9f70-a364b9dc7cf2", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"I know people who say \"The Avengers\" isn’t a good movie, but I don’t agree.\"\"\"\n" + ] + }, + { + "cell_type": "markdown", + "id": "bc86c6dd-6b54-4803-b91a-11bae88c33b9", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f3cb7279-f0ee-4e8b-ad40-0b5190dcdbcd", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a13c02dc-f8aa-4c1c-9948-c55ddcd9016c", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/theme1/PE100/PE100-03DecisionStructures.ipynb b/theme1/PE100/PE100-03DecisionStructures.ipynb new file mode 100644 index 0000000..b008cc7 --- /dev/null +++ b/theme1/PE100/PE100-03DecisionStructures.ipynb @@ -0,0 +1,683 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "adeab882-0b7a-4e03-aeeb-2a0d3d621d5f", + "metadata": {}, + "source": [ + "In the first lesson, everything we did was sequential programming. Statements are executed one after the other in exactly the order they're written in. As long as there aren't any errors, every statement will be executed.\n", + "\n", + "In almost any real Jupyter notebook or standalone program we write, there will have to be places where different code paths are taken depending on what has happened leading up to there. Suppose we're looking at absorption at one specific wavelength and we know that some of our instruments are a little bit too sensitive to changes in humidity. Maybe the first spectrometer has some insulation that is just a little too porous and reads a bit high, but the second one is even worse. We have calibration constants we can apply, but we have to apply the right constant for each individual instrument." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "b5963a34-f762-437f-b5f9-300015133d44", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "7.539441569999999" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spectrometer_number = 1 \n", + "reading = 7.00041 \n", + " \n", + "if spectrometer_number == 1: \n", + " useful_result = reading * 1.077 \n", + " \n", + "useful_result\n" + ] + }, + { + "cell_type": "markdown", + "id": "c21dcc06-0a92-42ae-9237-32c96eeaefaf", + "metadata": {}, + "source": [ + "Here we have the first Decision Structure (also called *control flow statement*) that we'll look at. Taking the above code apart, we see\n", + "several important things. \n", + " \n", + "1. This is an \"if statement\".\n", + "1. Testing to see if two things are equal is done with **two** equals\n", + "signs, not one (```==```). There's a historical reason for this, and\n", + "it's a good reason, but it *always* trips up newcomers. You have been\n", + "warned. You're welcome.\n", + "1. The last character on the ```if``` line is ```:``` (a colon ).\n", + "1. The \"body\" of the ```if``` statement, the part that is run if and only\n", + "if the tested condition is met, is indented.\n", + "\n", + "In the case of the above ```if``` statement, what the code does is\n", + "check to see if we're using spectrometer number 1 and if we are then\n", + "we add 7.7% to the reading and save it in a variable called\n", + "\"useful_result\".\n", + "\n", + "If that was all an ```if``` statement could do then it would be really\n", + "useful. But that's not all it can do. We need to do something\n", + "reasonable when we get readings from the second instrument. Such as:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "14ddbfc7-25f4-430e-b184-693dd9d85ad5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "8.3304879" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spectrometer_number = 2 \n", + "reading = 7.00041 \n", + " \n", + "if spectrometer_number == 1: \n", + " useful_result = reading * 1.077 \n", + "else: \n", + " useful_result = reading * 1.19\n", + "\n", + "useful_result" + ] + }, + { + "cell_type": "markdown", + "id": "7e7c9bc4-50b2-459b-9b0b-55e83dd57c92", + "metadata": {}, + "source": [ + "Here we have added an \"else clause\".\n", + "The above code is interpreted as \"check to see if\n", + "we're using spectrometer number 1 and if we are then we add 7.7% to\n", + "the reading and save it in a variable called useful_result. Otherwise,\n", + "set useful_result to whatever is saved in \"reading\" plus 19%.\n", + "\n", + "So far, so good. But there's more! Suppose we need to handle several\n", + "of these cheap, unreliable spectrometers. How do you suppose we could deal\n", + "with that?" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "395a880a-8aaf-4aad-a40c-d10c301d0dda", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "6.4403771999999995" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spectrometer_number = 3 \n", + "reading = 7.00041 \n", + " \n", + "if spectrometer_number == 1: \n", + " useful_result = reading * 1.077 \n", + "else: \n", + " if spectrometer_number == 2: \n", + " useful_result = reading * 1.19 \n", + " else: \n", + " if spectrometer_number == 3: \n", + " useful_result = reading * .92 \n", + " \n", + "useful_result" + ] + }, + { + "cell_type": "markdown", + "id": "f03a0082-414e-418b-8604-d3dc9f7578e0", + "metadata": {}, + "source": [ + "The above code looks a little intimidating, but all there is to it is\n", + "just a series of ```if``` statements. The logic of it goes like this:\n", + "\"If the instrument number is 1, then adjust it 7.7% and we're\n", + "done. Otherwise, it must be some other instrument number, so run our\n", + "else clause\". Then in the else clause, it does the same thing, except\n", + "checking for the second instrument and adjusting by 19%. If there was\n", + "nothing to do there (because the instrument number was 3) then we run the\n", + "```else``` clause of that second if statement. This else clause houses an\n", + "```if``` statement that checks to see if the instrument is number\n", + "three. This time it is, so the body of the if statement\n", + "is executed. We set useful_reading equal to 92% of reading.\n", + "\n", + "This is fine if we only have three instruments, but what do we\n", + "do if we have 20 of them and all but the first two are perfectly\n", + "fine? We could, in principle, type in 60 lines of code, but that\n", + "would be tedious, error prone, and would take a while to read and find\n", + "any mistakes. *Of course* there's a better way.\n", + "\n", + "Scientists and Engineers! We present... the \"elif\" statement!\n", + "\n", + "Let's see an example with 5 instruments...\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "701cf657-e57a-4bb9-9694-bed198d65f6a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "7.210422299999999" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spectrometer_number = 4 \n", + "reading = 7.00041 \n", + " \n", + "if spectrometer_number == 1: \n", + " useful_result = reading * 1.077 \n", + "elif spectrometer_number == 2: \n", + " useful_result = reading * 1.19 \n", + "elif spectrometer_number == 3: \n", + " useful_result = reading * .92 \n", + "elif spectrometer_number == 4: \n", + " useful_result = reading * 1.03 \n", + "elif spectrometer_number == 5: \n", + " useful_result = reading * 1.26 \n", + "else: \n", + " useful_result = reading \n", + " print(\"Be careful! I only lnow how to correct the first 5 instruments!\") \n", + " \n", + "useful_result" + ] + }, + { + "cell_type": "markdown", + "id": "1d95c332-4b18-4772-a2d6-d9d00dfe5d6b", + "metadata": {}, + "source": [ + "The final ```else``` clause is the one that runs **if no other clauses\n", + "ran**. If no clause, whether it's the if clause or any of the elif\n", + "clauses, then the else clause runs. It's really easy to spot\n", + "```else``` clauses even from across the room - they're the ones that\n", + "don't have a conditional test.\n", + "\n", + "Note that the ```if```, ```elif```, and ```else``` lines **must** end\n", + "with a colon. Don't feel bad if you forget one... I forget them about\n", + "half the time.\n", + "\n", + "You can run more than one line of code in response to the tested\n", + "conditions, but they have to be indented the same amount:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0f7bc533-12da-4601-911b-e70b5368ad48", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "7.00041 True\n" + ] + } + ], + "source": [ + "spectrometer_number = 103\n", + "reading = 7.00041\n", + "\n", + "if spectrometer_number == 1:\n", + " useful_result = reading * 1.077\n", + " trustworthy = False\n", + "elif spectrometer_number == 2:\n", + " useful_result = reading * 1.19\n", + " trustworthy = False\n", + "else:\n", + " useful_result = reading\n", + " trustworthy = True\n", + "\n", + "print(useful_result, trustworthy)\n" + ] + }, + { + "cell_type": "markdown", + "id": "103aa905-d274-45a4-a00d-011e04815f38", + "metadata": {}, + "source": [ + "There are three interesting things going on here. First, we've\n", + "added lines to set a variable named \"trustworthy\" to a value depending\n", + "on whether we had to adjust the reading. Evidently, if we have to\n", + "compensate for old, dry, cracking insulators then we don't really\n", + "trust the instrument.\n", + "\n", + "The second interesting thing is the values ```True``` and\n", + "```False```. These are \"Boolean\" values, and when we put them into the\n", + "\"trustworthy\" variable then it takes on the Boolean type. There are\n", + "only two values, ```True``` and ```False```. The capitalization is\n", + "important.\n", + "\n", + "The third thing to notice is that we're sending two values into the\n", + "print statement and it's printing both of them. In general, we can\n", + "give the print statement any number of *arguments*, separated by\n", + "commas, and it will print all of them separated by one space.\n", + "\n", + "The conditional test in each part of an ```if``` statement is an\n", + "expression that results in a Boolean value. So far, the only\n", + "*relational operator* (or *conditional operator*) we've seen is\n", + "```==```. There are others, though. For the sake of completeness, I'll\n", + "include ```==``` here:\n", + "\n", + "|operator|tested condition|\n", + "|--------|----------------|\n", + "|```==```| equals|\n", + "|```!=```| not equals|\n", + "|```>``` | greater than|\n", + "|```>=```| greater than or equal|\n", + "|```<``` | less than|\n", + "|```<=```| less than or equal|\n", + "\n", + "For each of the following code cells, decide what the result is, run\n", + "the cell, and see how you did:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "c716104a-9a9e-4a47-8453-8a6fba0af06b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "5 < 6" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "e443aea6-e1bc-4be5-a2ee-1c63c94fae8a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "5.99 == 5.99" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "33bca567-b087-4125-817e-c78a346cc655", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "5 != 5.00" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "de96f5ef-2981-4eac-b722-5ceaa980d280", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "5+6 < 11" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "698be490-d6dd-442e-98d7-e2092498f06e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "6 * 6 > 12 + 12 + 12" + ] + }, + { + "cell_type": "markdown", + "id": "c85d4e7c-b29e-42f0-8b5c-a9455976a909", + "metadata": {}, + "source": [ + "Relational operators also work with strings." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "a41f56ff-4d33-4512-a73a-429899136c1a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "equals Alice.\n", + "The person is not Bob.\n", + "Alice comes before Bob in alphabetical order.\n", + "Alice comes before or in the same place as Alice in sorted order\n", + "Working left to right, the M, the a, and the r match on\n", + "both strings, but when we finally get to the y and the k, y comes\n", + "after k in alphabetical order.\n" + ] + } + ], + "source": [ + "name = \"Alice\"\n", + "if name == \"Alice\":\n", + " print(\"equals Alice.\")\n", + "if name != \"Bob\":\n", + " print(\"The person is not Bob.\")\n", + "if \"Alice\" < \"Bob\":\n", + " print(\"Alice comes before Bob in alphabetical order.\")\n", + "if \"Alice\" <= \"Alice\":\n", + " print(\"Alice comes before or in the same place as Alice in sorted order\")\n", + "if \"Mary\" > \"Mark\":\n", + " print('Working left to right, the M, the a, and the r match on')\n", + " print('both strings, but when we finally get to the y and the k, y comes')\n", + " print('after k in alphabetical order.')" + ] + }, + { + "cell_type": "markdown", + "id": "685230ba-e05b-4d78-8896-fa58065780a8", + "metadata": {}, + "source": [ + "A couple words of caution: the comparisons are based on the ASCII codes for\n", + "each character. The \"A\" in ASCII stands for \"American\", and as you\n", + "might expect that means it only works for English language text. If\n", + "you need to handle other languages, even potentially, then there is a\n", + "better way to do it and we'll see that in the lesson on strings.\n", + "\n", + "Also, Capital letters are always less than lowercase letters, and not\n", + "in the way you might think. \"A\" is less than \"Z\", as you might expect,\n", + "but \"Z\" is greater than \"a\". The numbers 0-9 are the lowest of\n", + "all. Punctuation is sprinkled around and the only way to know for sure\n", + "is to look up \"ASCII Chart\".\n", + "\n", + "Let's go back to that part about running several lines of code but\n", + "they have to be indented the same amount. Python always runs \"blocks\"\n", + "of code. That block might be as short as one line:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "27181936-7635-4c39-a86b-8a6fd3343170", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "125.6636" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "circumference = 40 * 3.14159\n", + "\n", + "circumference" + ] + }, + { + "cell_type": "markdown", + "id": "7618bab7-e41a-4301-b4bd-97bb096c75e7", + "metadata": {}, + "source": [ + "or it might be arbitrarily long:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "1fbb2f6f-259b-442d-a896-5cfe7bdd8857", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1511396.1762899999" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "height = 6.01\n", + "length = 5.5\n", + "width = 14.3\n", + "density = 4.2\n", + "volume = height * width * length\n", + "mass = volume * density\n", + "energy_per_gram = 761.3\n", + "eyebrow_altering_potential = mass * energy_per_gram\n", + "\n", + "eyebrow_altering_potential" + ] + }, + { + "cell_type": "markdown", + "id": "cdbef9aa-0396-4ac4-8c8b-a9948e3d5518", + "metadata": {}, + "source": [ + "Whether it was the one line example or the eight line one, Python will\n", + "set out to run all of those lines in one shot, and as long as there\n", + "aren't any errors it'll do it. These are known as *code blocks*.\n", + "\n", + "The decision structures (again, also called *control flow statements*)\n", + "in Python all do basically the same thing: they evaluate an expression\n", + "and depending on whether it turns out True or False, they execute a\n", + "code block in some manner. This means that wherever we can have a\n", + "single line of code running in a decision structure we can have as\n", + "many lines as we want.\n", + "\n", + "Take a look at the following code block. For the four possible\n", + "combinations of ```potentially_hazardous``` and ```explody```, decide\n", + "what would be printed out. Then try out the combinations and make sure\n", + "you know why each combination was handled the way it was." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "dafda872-a797-43b1-a75b-9288d6824832", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Available oomph to ruin your day is 1511396.1762899999\n" + ] + } + ], + "source": [ + "potentially_hazardous = True\n", + "explody = True\n", + "\n", + "if potentially_hazardous and explody:\n", + " height = 6.01\n", + " length = 5.5\n", + " width = 14.3\n", + " density = 4.2\n", + " volume = height * width * length\n", + " mass = volume * density\n", + " energy_per_gram = 761.3\n", + " eyebrow_altering_potential_energy = mass * energy_per_gram\n", + " print(\"Total Available Kaboom (TAK) to ruin your day is\", eyebrow_altering_potential_energy)\n", + "elif potentially_hazardous:\n", + " print(\"Not likely to go 'kaboom', but not something you want to casually eat, either.\")\n", + " print(\"I mean, unless you're feeling brave.\")\n", + " print(\"Even then, it's a bad idea.\")\n", + "elif explody:\n", + " print(\"This is one of those things that will blow up but isn't actually hazardous.\")\n", + " print(\"I'm guessing it's a vinegar-and-baking-soda volcano.\")\n", + "else:\n", + " print(\"As far as we know, the material in quesion is no more\")\n", + " print(\"dangerous than takeout pizza. How you want to handle it\")\n", + " print(\"is up to you. Choose wisely.\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "150d6c0c-1de6-4a71-afde-c411aebe6db1", + "metadata": {}, + "source": [ + "Did you notice `potentially_hazardous and explody`? ```and```\n", + "is a **boolean operator**. We've seen the arithmetic operators already\n", + "(```+```, ```-```, ```*```, ```/```, etc.) and now here are the\n", + "boolean operators. They're named after Boolean algebra, the algebra of\n", + "logic, and are used to make larger logical expressions from smaller\n", + "ones. There are three boolean operators: ```and```, ```or```, and\n", + "```not```.\n", + "\n", + "The ```and``` operator evaluates to True if **both** of its arguments are\n", + "True. The ```or``` operator evaluates to True if **either or both**\n", + "of its arguments are true. The ```not``` operator takes only one\n", + "argument and reverses it: ```not``` turns True into False and False\n", + "into True." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "5ca9f0ff-f7e1-4632-bd02-a133817ab79e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Doctor of Medical Dentistry (DMD)\n" + ] + } + ], + "source": [ + "medical_license = True\n", + "dental_license = True\n", + "\n", + "if medical_license and dental_license:\n", + " print(\"Doctor of Medical Dentistry (DMD)\")\n", + "elif dental_license and not medical_license:\n", + " print(\"Plain old dentist.\")\n", + "elif not dental_license and medical_license:\n", + " print(\"Garden-variety doctor.\")\n", + "else:\n", + " print(\"No license at all. Run. Quickly.\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cbff1e92-c650-48cd-9366-396d25254196", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "6a0b39c4-2ad1-4d22-b5ca-7d5e66466bad", + "metadata": {}, + "source": [ + "At this point, we've seen the most basic way to alter the *flow of control* in Python: the `if` statement. In the next notebook we're going to see how to expand on that idea and make our code do something over and over." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/theme1/PE101/NumPy.ipynb b/theme1/PE101/NumPy.ipynb new file mode 100644 index 0000000..e635cbe --- /dev/null +++ b/theme1/PE101/NumPy.ipynb @@ -0,0 +1,510 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "3ff68669-a493-4d27-bb7b-5a168faaa16e", + "metadata": {}, + "source": [ + "# NumPy - A Mathematical Toolkit for Python\n", + "\n", + "In the previous section, modules for Python was introduced. In this section, we'll take a much more detailed look at one of the most useful to scientists: NumPy. This module contains numerous routinues and support frameworks for numerical computing. The routinues in it are very carefully tested for correctness and are crafted for speed. Any time you _can_ use something from this package, it's a good idea to.\n", + "\n", + "Python is built for versatility and ease of programming. Unfortunately, it is not built for speed. Over the years Python has gotten faster and faster, but there is still a speed penalty as compared to classic compiled languages like C, C++, or Fortran.\n", + "\n", + "Enter NumPy: a package of mathematical routines written in C and Fortran and made to work with Python via a \"glue\" or \"shim\" layer. This interface is invisible to the programmer. NumPy looks and behaves just like any other Python package. But under the surface lies a very fast, efficient library of algorithms.\n", + "\n", + "### A first glimpse\n", + "\n", + "Let's take a quick look at NumPy and see a few of the things it can do. NumPy is a package, not part of Python proper, so we have to tell Python to load it. It's traditional to import numpy and give it the alias \"np\" - it's less typing that way, and if you're cutting and pasting code from other sources then it's handy to follow the convention." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "de084959-df71-493d-8e30-7ab89a5552cf", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "id": "a85dfb8c-4b0d-4f1e-8229-5b1f2c4a329c", + "metadata": {}, + "source": [ + "Python, you'll recall, doesn't have an \"array\" data type. The closest it can come is the \"list\". Lists are certainly useful, but they aren't all that fast to read and even slower to write to. To make matters worse, a 2-D array is represented by a list of lists. This is great for representing complicated data but it's lousy for doing math.\n", + "\n", + "The critical NumPy data type is the array: \"NumPy arrays are faster and more compact than Python lists. An array consumes less memory and is convenient to use.\" ([source](https://numpy.org/doc/stable/user/absolute_beginners.html))\n", + "The one caveat with NumPy arrays is that all the elements inside an array need to have the same data type (e.g. integer, float, double). In practice this is rarely, if ever, a problem.\n", + "\n", + "Let's make an array of integers:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "2b954fa8-72d4-4c2a-aa3a-250949c3ff11", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 1, 2, 3, 4],\n", + " [ 5, 6, 7, 8],\n", + " [ 9, 10, 11, 12]])" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])\n", + "\n", + "a" + ] + }, + { + "cell_type": "markdown", + "id": "b70935d1-8ee5-4a1b-9b8a-dbb407dc5324", + "metadata": {}, + "source": [ + "The array `a` is now a 4x3 array of integers. The `array` method was called with one argument - a Python \"list of lists\" representation of the array. The dimensions of the array are inferred from the list of lists used to initialize it.\n", + "\n", + "There are other ways to create arrays. Here are two more common methods:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "7841cfe1-5e2a-4aa2-a87f-edc63c454ca4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0., 0., 0.])" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z = np.zeros(3)\n", + "z" + ] + }, + { + "cell_type": "markdown", + "id": "a8be4b10-4a46-4524-a06b-b027fffc9b2c", + "metadata": {}, + "source": [ + "Notice the decimal points after the zeros. These indicate that we're seeing floating point numbers." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "58af786a-c914-4e42-acc3-87e25f68e022", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1., 1., 1.],\n", + " [1., 1., 1.],\n", + " [1., 1., 1.]])" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m = np.ones((3,3))\n", + "m" + ] + }, + { + "cell_type": "markdown", + "id": "1da71297-5b0f-4244-a61c-24f7a5d6b111", + "metadata": {}, + "source": [ + "This one will throw you off if you aren't paying attention. Notice how many parantheses there are... probably more than you expected! What is going on is that the outer parentheses are there to indicate function arguments, just like calling any other functions. The inner parentheses are used to generate a tuple, in this case one with two values, both of which are threes. This tuple can be arbitrarily long:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ba910429-41d2-4c8d-a4e0-c690e354fba6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[[1., 1., 1.],\n", + " [1., 1., 1.],\n", + " [1., 1., 1.]],\n", + "\n", + " [[1., 1., 1.],\n", + " [1., 1., 1.],\n", + " [1., 1., 1.]],\n", + "\n", + " [[1., 1., 1.],\n", + " [1., 1., 1.],\n", + " [1., 1., 1.]]],\n", + "\n", + "\n", + " [[[1., 1., 1.],\n", + " [1., 1., 1.],\n", + " [1., 1., 1.]],\n", + "\n", + " [[1., 1., 1.],\n", + " [1., 1., 1.],\n", + " [1., 1., 1.]],\n", + "\n", + " [[1., 1., 1.],\n", + " [1., 1., 1.],\n", + " [1., 1., 1.]]],\n", + "\n", + "\n", + " [[[1., 1., 1.],\n", + " [1., 1., 1.],\n", + " [1., 1., 1.]],\n", + "\n", + " [[1., 1., 1.],\n", + " [1., 1., 1.],\n", + " [1., 1., 1.]],\n", + "\n", + " [[1., 1., 1.],\n", + " [1., 1., 1.],\n", + " [1., 1., 1.]]]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "big_m = np.ones((3,3,3,3))\n", + "big_m" + ] + }, + { + "cell_type": "markdown", + "id": "99be908a-4d66-4576-b7dd-0d0d01c0918c", + "metadata": {}, + "source": [ + "The output isn't terribly easy to read, but then again representing a four dimensional array on a flat page is challenging at best.\n", + "\n", + "If we ever need to see the dimensions of an array, we can use the `shape()` method. \n", + "\n", + "# FIX THIS FIX THIS FIX THIS" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "72fbfda8-ed6e-40dc-94e4-ce4ccefe0c66", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "z:\n", + "(3,)\n", + "\n", + "m:\n", + "(3, 3)\n", + "\n", + "big_m\n", + "(3, 3, 3, 3)\n" + ] + } + ], + "source": [ + "print(\"z:\")\n", + "print(np.shape(z))\n", + "print()\n", + "print(\"m:\")\n", + "print(np.shape(m))\n", + "print()\n", + "print(\"big_m\")\n", + "print(np.shape(big_m))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "66e56019-f630-46ab-98a7-b3d3350737e0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3,)" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.shape(z)\n" + ] + }, + { + "cell_type": "markdown", + "id": "72e6eaaf-b3cb-4d27-9bc1-ecfeaf1ff213", + "metadata": {}, + "source": [ + "### Let's do some actual math, shall we?\n", + "\n", + "The trivial example: add a scalar (\"a single number\") to every element of the matrix:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "2646ba7d-7d8c-4103-bf8d-da4a4bec05d4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0. 0. 0.]\n", + "[3. 3. 3.]\n" + ] + } + ], + "source": [ + "print(z)\n", + "z_plus_three = z + 3\n", + "print(z_plus_three)" + ] + }, + { + "cell_type": "markdown", + "id": "075d1805-07b2-4ef8-81c0-995fc0ac3d38", + "metadata": {}, + "source": [ + "You can use any of the Python operators, of course: `+, -, *, /, %, **`...\n", + "\n", + "CHECK THIS CHECK THIS CHECK THIS CHECK THIS the ** ooperator?" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "25781f79-c2e5-4a78-bfd8-05b92f4fedd6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1 0 1 0]\n", + " [1 0 1 0]\n", + " [1 0 1 0]]\n" + ] + } + ], + "source": [ + "print (a % 2)" + ] + }, + { + "cell_type": "markdown", + "id": "97090102-79e4-40db-bd2e-0b7544eed3ea", + "metadata": {}, + "source": [ + "Comparison operators (like >, <, and so forth) are legitimate operators, so they work too:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "45637e00-2f0e-45b1-976f-d4c5ed4a4d72", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[ 1 2 3 4]\n", + " [ 5 6 7 8]\n", + " [ 9 10 11 12]]\n", + "\n", + "[[False False False False]\n", + " [False True True True]\n", + " [ True True True True]]\n" + ] + } + ], + "source": [ + "print(a)\n", + "print()\n", + "print(a > 5)" + ] + }, + { + "cell_type": "markdown", + "id": "16d7c234-3497-4e9c-9297-64a806542ff3", + "metadata": {}, + "source": [ + "### Linear algebra, anyone?\n", + "\n", + "Let's use NumPy to do some basic linear algebra. First, we'll need another module in the NumPy package:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "7edc25f0-e902-4234-9a95-41597190e0c7", + "metadata": {}, + "outputs": [ + { + "ename": "ImportError", + "evalue": "cannot import name 'nl' from 'numpy.linalg' (/opt/homebrew/lib/python3.12/site-packages/numpy/linalg/__init__.py)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[12], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mnumpy\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mlinalg\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m nl\n", + "\u001b[0;31mImportError\u001b[0m: cannot import name 'nl' from 'numpy.linalg' (/opt/homebrew/lib/python3.12/site-packages/numpy/linalg/__init__.py)" + ] + } + ], + "source": [ + "from numpy.linalg import nl" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "e4c96df7-c701-4a2a-87f8-ea545f01c980", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1 1 1]\n", + " [1 1 0]\n", + " [1 0 0]]\n" + ] + }, + { + "ename": "AttributeError", + "evalue": "module 'numpy' has no attribute 'inv'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[27], line 4\u001b[0m\n\u001b[1;32m 1\u001b[0m k \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39marray([[\u001b[38;5;241m1\u001b[39m,\u001b[38;5;241m1\u001b[39m,\u001b[38;5;241m1\u001b[39m], [\u001b[38;5;241m1\u001b[39m,\u001b[38;5;241m1\u001b[39m,\u001b[38;5;241m0\u001b[39m], [\u001b[38;5;241m1\u001b[39m,\u001b[38;5;241m0\u001b[39m,\u001b[38;5;241m0\u001b[39m]])\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28mprint\u001b[39m(k)\n\u001b[0;32m----> 4\u001b[0m kinv \u001b[38;5;241m=\u001b[39m \u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minv\u001b[49m(k)\n\u001b[1;32m 5\u001b[0m kinv\n", + "File \u001b[0;32m/opt/homebrew/lib/python3.12/site-packages/numpy/__init__.py:333\u001b[0m, in \u001b[0;36m__getattr__\u001b[0;34m(attr)\u001b[0m\n\u001b[1;32m 330\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRemoved in NumPy 1.25.0\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 331\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mTester was removed in NumPy 1.25.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 333\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mAttributeError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmodule \u001b[39m\u001b[38;5;132;01m{!r}\u001b[39;00m\u001b[38;5;124m has no attribute \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 334\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{!r}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mformat(\u001b[38;5;18m__name__\u001b[39m, attr))\n", + "\u001b[0;31mAttributeError\u001b[0m: module 'numpy' has no attribute 'inv'" + ] + } + ], + "source": [ + "k = np.array([[1,1,1], [1,1,0], [1,0,0]])\n", + "print(k)\n", + "\n", + "kinv = np.inv(k)\n", + "kinv" + ] + }, + { + "cell_type": "markdown", + "id": "c3a4b59d-cf8d-4bf5-bc4c-5ef76b7cf33a", + "metadata": {}, + "source": [ + "And given a matrix and its inverse, you probably already guessed where this is going:" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "2a60a483-96e2-4929-a8a5-3c5d93332b8a", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'kinv' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[28], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m k \u001b[38;5;241m@\u001b[39m \u001b[43mkinv\u001b[49m\n", + "\u001b[0;31mNameError\u001b[0m: name 'kinv' is not defined" + ] + } + ], + "source": [ + "k @ kinv" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "33a135b2-6a0a-4b06-a59c-8956f0f77db4", + "metadata": {}, + "outputs": [ + { + "ename": "ModuleNotFoundError", + "evalue": "No module named 'matplotlib'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[29], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mmatplotlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpyplot\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mplt\u001b[39;00m\n\u001b[1;32m 2\u001b[0m plt\u001b[38;5;241m.\u001b[39mmatshow(a)\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'matplotlib'" + ] + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "plt.matshow(a)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d6a4998-94f6-45b4-b3fb-c3480ab717a3", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}