summaryrefslogtreecommitdiff
path: root/python/atms-310/notebooks/Week 03 M.ipynb
diff options
context:
space:
mode:
authorpants <niklasjo2004@gmail.com>2026-09-21 14:17:15 -0700
committerpants <niklasjo2004@gmail.com>2026-09-21 14:17:15 -0700
commit3813621611945a0be23384c0c4d395b4c4a614ad (patch)
tree1812fd440839272e7dd16f5635e180769a66f5f1 /python/atms-310/notebooks/Week 03 M.ipynb
Diffstat (limited to 'python/atms-310/notebooks/Week 03 M.ipynb')
-rw-r--r--python/atms-310/notebooks/Week 03 M.ipynb335
1 files changed, 335 insertions, 0 deletions
diff --git a/python/atms-310/notebooks/Week 03 M.ipynb b/python/atms-310/notebooks/Week 03 M.ipynb
new file mode 100644
index 0000000..f68849f
--- /dev/null
+++ b/python/atms-310/notebooks/Week 03 M.ipynb
@@ -0,0 +1,335 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "<h1>5. Modules and Exception Handling</h1>\n",
+ "<h2>10/09/2023</h2>"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "<h2>5.0 Last Time...</h2>\n",
+ "\n",
+ "<ul>\n",
+ " <li>A <b>for loop</b> lets you repeat an operation a specified number of times.</li>\n",
+ " <li>Indentation is critical for loops in Python.</li>\n",
+ " <li>The range() function will create a list of all values up to the specified integer.</li>\n",
+ " <li>Hardcoding is the act of (often unnecessarily) restricting a piece of code so it only works under specific circumstances.</li>\n",
+ " <li>A <b>while loop</b> lets you repeat an operation until a particular condition is met.</li>\n",
+ " <li>The index in a while loop must be initialized and care should be taken to avoid infinite loops.</li>\n",
+ "</ul>"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "<h2>5.1 Modules</h2>\n",
+ "\n",
+ "A <b>module</b> is just a library of Python source code files that will give you access to new (frequently more specialized) functions.\n",
+ "\n",
+ "To import a module, the syntax is simply: <b>import \\<module name\\></b>."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "-0.7568024953079283\n"
+ ]
+ }
+ ],
+ "source": [
+ "# An extremely useful module in the atmospheric science world is NumPy.\n",
+ "# This package lets you use a variety of mathematical (and array-based) functions and variables.\n",
+ "import numpy\n",
+ "\n",
+ "\n",
+ "# As soon as the module is imported, you have access to all its contents.\n",
+ "\n",
+ "# To refer to a function or variable within numpy, just follow it with a \n",
+ "# period, then the function or variable in question.\n",
+ "\n",
+ "# As an example, numpy will let you calculate the sine of a given number.\n",
+ "a = numpy.sin(4)\n",
+ "print(a)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Some modules have what are called <b>submodules</b> that can be referred to in a similar way. For instance, the module NumPy has a submodule called ma, which in turn has particular functions defined within it. If you wanted to run the <b>array</b> function inside the <b>ma</b> submodule inside the <b>NumPy</b> module, it would look like <b>numpy.ma.array</b>.\n",
+ "\n",
+ "Modules have detailed documentation (typically easily found via Google) that will let you browse all the available functions at your disposal. This instance of Jupyter has several modules preinstalled; they may be missing if you try running them on a Python build at home. Fortunately, there are generally helpful instructions online for downloading new modules so they can be imported into your code."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "-0.7568024953079282"
+ ]
+ },
+ "execution_count": 1,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# If you find yourself typing the same module name again and again, \n",
+ "# you can rename it to something a little quicker!\n",
+ "\n",
+ "import numpy as np\n",
+ "\n",
+ "a = np.sin(4)\n",
+ "a"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "As a meteorological example, let's return to our list of Celsius temperatures from yesterday. NumPy will enable us to easily calculate the maximum and minimum temperatures."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The maximum temperature is 36.5 and the minimum temperature is 13.5.\n"
+ ]
+ }
+ ],
+ "source": [
+ "# First, here's our temperature list.\n",
+ "\n",
+ "temp = [23.5,24.5,18.0,26.8,17.7,17.0,27.1,24.6,13.5,36.5]\n",
+ "\n",
+ "# Let's import NumPy.\n",
+ "\n",
+ "import numpy as np\n",
+ "\n",
+ "# Now, use the max() and min() functions within the NumPy module\n",
+ "# to calculate the maximum and minimum temperatures.\n",
+ "\n",
+ "maxT = np.max(temp)\n",
+ "minT = np.min(temp)\n",
+ "\n",
+ "# We can even output a nice sentence summing it up!\n",
+ "\n",
+ "print(\"The maximum temperature is \"+str(maxT)+\" and the minimum temperature is \"+str(minT)+\".\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "<b>An example!</b>\n",
+ "\n",
+ "In the box below, write a block of code that will apply a NumPy mathematical function of your choice to the list of temperatures <b>(temp)</b> above: https://numpy.org/doc/stable/reference/routines.math.html. Don't forget to include your module import statement!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[-0.99808203 -0.59135753 -0.75098725 0.9953511 -0.91258245 -0.96139749\n",
+ " 0.92243282 -0.50789659 0.80378443 -0.93171689]\n",
+ "[-0.06190529 0.80640949 0.66031671 -0.09631292 0.40889274 -0.27516334\n",
+ " -0.38615761 0.86141805 0.59492066 0.36318541]\n",
+ "[ 16.12272495 -0.73332164 -1.13731371 -10.33455467 -2.23183823\n",
+ " 3.49391565 -2.38874697 -0.58960523 1.35107835 -2.56540287]\n"
+ ]
+ }
+ ],
+ "source": [
+ "temp = [23.5,24.5,18.0,26.8,17.7,17.0,27.1,24.6,13.5,36.5]\n",
+ "import numpy as np\n",
+ "\n",
+ "# Mathematical function #1.\n",
+ "print(np.sin(temp))\n",
+ "\n",
+ "# Mathematical function #2.\n",
+ "print(np.cos(temp))\n",
+ "print(np.tan(temp))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "<h2>5.2 Exception Handling</h2>\n",
+ "\n",
+ "An \"exception\" is a very polite way of saying \"error\" in programming-speak. Often we use an if statement to determine whether something is going to cause a problem, and then use a <b>raise</b> statement to tell the code to stop and output a particular error."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "6\n",
+ "12.566370614359172\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Let's say we have a code that will attempt to calculate the area of a circle\n",
+ "# based on its radius.\n",
+ "# It works well for positive values of radius, but we want to allow for the\n",
+ "# possibility that someone might enter a negative radius.\n",
+ "\n",
+ "import numpy as np\n",
+ "\n",
+ "def circle_area(radius):\n",
+ " if radius < 0:\n",
+ " raise ValueError('Radius cannot be negative, you fool!')\n",
+ " area = np.pi * (radius**2)\n",
+ " return area\n",
+ "\n",
+ "def quadarea(base, height):\n",
+ " if base < 0:\n",
+ " raise ValueError('enter a POSITIVE number')\n",
+ " elif height < 0:\n",
+ " raise ValueError('POSITIVE integer please')\n",
+ " x = base*height\n",
+ " return x\n",
+ "# Now try calling this function with a positive radius to make sure it works.\n",
+ "print(quadarea(2,3))\n",
+ "print(circle_area(2))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "ValueError",
+ "evalue": "Radius cannot be negative, you fool!",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[0;32mIn[15], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# Now try calling this function with a negative radius.\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mcircle_area\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[38;5;241;43m2\u001b[39;49m\u001b[43m)\u001b[49m)\n",
+ "Cell \u001b[0;32mIn[14], line 10\u001b[0m, in \u001b[0;36mcircle_area\u001b[0;34m(radius)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcircle_area\u001b[39m(radius):\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m radius \u001b[38;5;241m<\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[0;32m---> 10\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mRadius cannot be negative, you fool!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 11\u001b[0m area \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mpi \u001b[38;5;241m*\u001b[39m (radius\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m2\u001b[39m)\n\u001b[1;32m 12\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m area\n",
+ "\u001b[0;31mValueError\u001b[0m: Radius cannot be negative, you fool!"
+ ]
+ }
+ ],
+ "source": [
+ "# Now try calling this function with a negative radius.\n",
+ "\n",
+ "print(circle_area(-2))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The syntax for <b>raise</b> is the exception class (for instance, ValueError() if a value is forbidden; this is the most common type of exception you'll have, but we'll see others as we go) followed by user-defined text that will give you more information about the error.\n",
+ "\n",
+ "Luckily, Python also lets you build in ways to deal with common exceptions if you're pretty sure you know where the user went wrong. For example, they may have accidentally put a negative sign on the radius, but you're pretty sure they just meant the positive value. In that case, you can use a <b>try/except</b> block, which will attempt to resolve the error."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "28.274333882308138\n"
+ ]
+ }
+ ],
+ "source": [
+ "# As an example, this code will call the area() function, and if it gets\n",
+ "# a ValueError exception, it'll try again with the absolute value\n",
+ "# of the range.\n",
+ "\n",
+ "radius = -3\n",
+ "try:\n",
+ " a = circle_area(radius)\n",
+ "except ValueError:\n",
+ " a = circle_area(abs(radius))\n",
+ " \n",
+ "print(a)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "<h2>TAKE-HOME POINTS</h2>\n",
+ "\n",
+ "<ul>\n",
+ " <li>A <b>module</b> is a library of Python source code that gives access to new variables and functions.</li>\n",
+ " <li>Modules can be imported as whatever name you like.</li>\n",
+ " <li>A <b>raise</b> statement lets you define your own error conditions and stop code when they're met.</li>\n",
+ " <li>A <b>try/except</b> block will let you fix common issues that would otherwise result in exceptions.</li>\n",
+ "</ul>"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# you can import modules with any name you want"
+ ]
+ }
+ ],
+ "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.11.4"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}