From a2148c2ef7b9658f0f96b9aeeea437679a645ad8 Mon Sep 17 00:00:00 2001
From: Repo Updater <noreply@mpcdf.mpg.de>
Date: Tue, 26 Nov 2024 07:15:33 +0100
Subject: [PATCH] e7cc044e final tweaks for Python recap

---
 environment.yml                      |   1 +
 notebooks/01--Introduction.ipynb     |  39 ++-
 notebooks/03--Python_Refresher.ipynb | 486 ++++++++++++++++++---------
 notebooks/05--NumPy_SciPy.ipynb      |  12 +-
 4 files changed, 355 insertions(+), 183 deletions(-)

diff --git a/environment.yml b/environment.yml
index 6a5003d..85713b0 100644
--- a/environment.yml
+++ b/environment.yml
@@ -13,6 +13,7 @@ dependencies:
   - libopenblas=*=*openmp*
   - numpy
   - scipy
+  - pooch
   - cython
   - pybind11
   - pandas
diff --git a/notebooks/01--Introduction.ipynb b/notebooks/01--Introduction.ipynb
index fcaac67..59aaaa7 100644
--- a/notebooks/01--Introduction.ipynb
+++ b/notebooks/01--Introduction.ipynb
@@ -33,7 +33,7 @@
     "* Efficiency with respect to development effort:  \n",
     "  $\\rightarrow$ Python helps you to get \"things done\" quickly and focus on your science.\n",
     "* Efficiency with respect to hardware utilization:  \n",
-    "  $\\rightarrow$ Python-based codes may perform well if implemented properly.\n",
+    "  $\\rightarrow$ Python-based codes can perform well if implemented properly.\n",
     "* Using Python may achieve a good overall efficiency for small- to medium-scale codes\n",
     "* And finally ... Python is already there, so we have do deal with it!"
    ]
@@ -72,7 +72,7 @@
    "source": [
     "##  Use cases often relevant to our audience\n",
     "\n",
-    "* prototype implementations of numerical or AI methods that should run (much) faster when going towards production\n",
+    "* prototype implementations of numerical or AI code that should run (much) faster when moving towards production\n",
     "* data analysis scripts that should run faster and/or operate in parallel\n",
     "* IO-handling and processing of large numerical data\n",
     "\n",
@@ -87,7 +87,7 @@
     }
    },
    "source": [
-    "## Scope of this tutorial\n",
+    "## Scope of this course\n",
     "* Learn about the tools and techniques to write efficient Python code for scientific computing\n",
     "![gain vs effort](fig/gain_vs_effort.svg)"
    ]
@@ -103,7 +103,7 @@
     "## Course Outline\n",
     "\n",
     "* Introduction\n",
-    "* Refresher of Python and the Python Ecosystem\n",
+    "* Quick refresher of Python and the Python Ecosystem\n",
     "* Basics of High Performance Computing\n",
     "* Scientific Computing with Python: NumPy and SciPy\n",
     "* Performance: Cython, JIT (Numba, JAX), C/Fortran interfacing\n",
@@ -119,7 +119,8 @@
     }
    },
    "source": [
-    "### *Python for HPC* complements advanced HPC courses\n",
+    "## *Python for HPC* complements advanced HPC courses\n",
+    "\n",
     "* We cannot cover traditional HPC topics in depth, and would highly recommend the following courses\n",
     "    * Node-level performance engineering\n",
     "    * Parallel programming with MPI\n",
@@ -136,7 +137,7 @@
     }
    },
    "source": [
-    "## About this Python for HPC tutorial\n",
+    "## About this Python for HPC course\n",
     "\n",
     "* Practical hands-on approach with code examples\n",
     "* Presentation is based on Jupyter notebooks\n",
@@ -174,7 +175,7 @@
    "source": [
     "### Software Option 1: Cloud-based MPCDF Jupyter notebooks\n",
     "\n",
-    "* Use the link communicated by email to access a Jupyter service on the MPCDF HPC cloud\n",
+    "* Use the link communicated by email to access a Jupyter service in the MPCDF HPC cloud\n",
     "* The course material *and* software are provided via an interactive JupyterLab interface\n",
     "* Each instance provides access to several virtual CPU cores and a few GB of RAM\n",
     "* Please keep the following points in mind\n",
@@ -194,10 +195,12 @@
     "### Software Option 2: Python infrastructure on the MPCDF HPC systems\n",
     "* Python is provided via conda-based Python distributions (now based on 'conda-forge', historically Anaconda)\n",
     "* software is accessible via environment modules, e.g.  \n",
-    "    `module purge`  \n",
-    "    `module load gcc/12 impi/2021.9`  \n",
-    "    `module load anaconda/3/2023.03`  \n",
-    "    `module load mpi4py/3.1.4`"
+    "```bash\n",
+    "$ module purge\n",
+    "$ module load gcc/12 impi/2021.9\n",
+    "$ module load anaconda/3/2023.03\n",
+    "$ module load mpi4py/3.1.4\n",
+    "```"
    ]
   },
   {
@@ -209,9 +212,21 @@
    },
    "source": [
     "### Software Option 3: Python environment for your local computer\n",
+    "\n",
     "* On a recent Linux system, install all the necessary packages via the package manager and `pip`\n",
-    "* Alternatively, install [Miniforge](https://conda-forge.org/miniforge/) and use the `conda` package manager and the file `environment.yml` that is provided together with the course material to add all necessary packages"
+    "* Alternatively, install [Miniforge](https://conda-forge.org/miniforge/) and use the `conda` package manager and the file `environment.yml` that is provided together with the course material to add all necessary packages.  \n",
+    "```bash\n",
+    "$ conda env create --file environment.yml\n",
+    "$ conda activate pyhpc\n",
+    "```"
    ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
   }
  ],
  "metadata": {
diff --git a/notebooks/03--Python_Refresher.ipynb b/notebooks/03--Python_Refresher.ipynb
index bf2a971..f893f92 100644
--- a/notebooks/03--Python_Refresher.ipynb
+++ b/notebooks/03--Python_Refresher.ipynb
@@ -45,7 +45,7 @@
     }
    },
    "source": [
-    "### Python Language Key Features\n",
+    "### Python Key Language Features\n",
     "* high-level language, extensive standard library and ecosystem\n",
     "* no type declarations, types are tracked at runtime  \n",
     "  $\\rightarrow$ code is interpreted in most implementations (or just-in-time compiled)  \n",
@@ -97,8 +97,7 @@
     "    * press \"Shift + Enter\" to execute the current cell\n",
     "    * select \"Cell\" $\\to$ \"Run all\" from the menu to run the complete notebook\n",
     "* notebook export to Python source file works via \"File\" $\\to$ \"Download as\"\n",
-    "* [papermill](https://papermill.readthedocs.io/en/latest/) allows to run notebooks in 'headless' mode without user interaction (e.g. in a batch job)\n",
-    "* locally, launch via `jupyter notebook` or `jupyter lab` from a terminal\n",
+    "* locally, launch via `jupyter lab` or `jupyter notebook` from a terminal\n",
     "* https://jupyter.org"
    ]
   },
@@ -137,7 +136,7 @@
     "```python\n",
     "a = 5\n",
     "```\n",
-    "* in Python everything is an object, i.e. contains data along with attributes and methods \n",
+    "* in Python, nearly everything is an object, i.e. contains data along with attributes and methods \n",
     "  * immutable objects may not change once created, e.g. integer, float, boolean, string, tuple\n",
     "  * mutable objects may change in place, e.g. list, set, dictionary, most user-defined classes\n",
     "  * if unsure, check via the object ID (memory location in cPython)"
@@ -472,7 +471,7 @@
     "  `if` ... `elif` ... `else`\n",
     "* loops\n",
     "    * `for` $-$ used to repeat a block of code a fixed number of times, used in combination with an iterable object (`range()`, list, etc.)\n",
-    "    * `while` $-$ used to repeat a block of code as long as a condition is satisfied\n",
+    "    * `while` $-$ used to repeat a block of code as long as a condition is `True`\n",
     "* loop modifier statements\n",
     "    * `break`\n",
     "    * `continue`\n",
@@ -667,64 +666,6 @@
     "print(f\"l = {l}\")"
    ]
   },
-  {
-   "cell_type": "markdown",
-   "metadata": {
-    "slideshow": {
-     "slide_type": "subslide"
-    }
-   },
-   "source": [
-    "### Classes\n",
-    "* classes bundle data and functionality together, are key to object oriented programming\n",
-    "* Python supports classes and related functionality, among others\n",
-    "    * methods\n",
-    "    * class and instance variables\n",
-    "    * inheritance\n",
-    "* unintended side effects may be caused by mutable class variables (see example)\n",
-    "* https://docs.python.org/3.11/tutorial/classes.html"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 12,
-   "metadata": {
-    "slideshow": {
-     "slide_type": "skip"
-    }
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "shared = ['cat'], private = ['dog']\n",
-      "shared = ['cat', 'cat'], private = ['dog']\n"
-     ]
-    }
-   ],
-   "source": [
-    "class myClass():\n",
-    "    \"\"\"A simple example class.\"\"\"\n",
-    "    shared = []  # class variable, shared by all instances\n",
-    "    \n",
-    "    def __init__(self):  # constructor\n",
-    "        self.private = []  # per-instance variable\n",
-    "    \n",
-    "    def show(self):\n",
-    "        print(\"shared = {}, private = {}\".format(self.shared, self.private))\n",
-    "\n",
-    "x = myClass()\n",
-    "x.shared.append(\"cat\")\n",
-    "x.private.append(\"dog\")\n",
-    "x.show()\n",
-    "\n",
-    "y = myClass()\n",
-    "y.shared.append(\"cat\")\n",
-    "y.private.append(\"dog\")\n",
-    "y.show()"
-   ]
-  },
   {
    "cell_type": "markdown",
    "metadata": {
@@ -813,6 +754,64 @@
     "say_hello(\"Peter\")"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Classes\n",
+    "* classes bundle data and functionality together, are key to object oriented programming\n",
+    "* Python supports classes and related functionality, among others\n",
+    "    * methods\n",
+    "    * class and instance variables\n",
+    "    * inheritance\n",
+    "* unintended side effects may be caused by mutable class variables (see example)\n",
+    "* https://docs.python.org/3.11/tutorial/classes.html"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {
+    "slideshow": {
+     "slide_type": "skip"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "shared = ['cat'], private = ['dog']\n",
+      "shared = ['cat', 'cat'], private = ['dog']\n"
+     ]
+    }
+   ],
+   "source": [
+    "class myClass():\n",
+    "    \"\"\"A simple example class.\"\"\"\n",
+    "    shared = []  # class variable, shared by all instances\n",
+    "    \n",
+    "    def __init__(self):  # constructor\n",
+    "        self.private = []  # per-instance variable\n",
+    "    \n",
+    "    def show(self):\n",
+    "        print(\"shared = {}, private = {}\".format(self.shared, self.private))\n",
+    "\n",
+    "x = myClass()\n",
+    "x.shared.append(\"cat\")\n",
+    "x.private.append(\"dog\")\n",
+    "x.show()\n",
+    "\n",
+    "y = myClass()\n",
+    "y.shared.append(\"cat\")\n",
+    "y.private.append(\"dog\")\n",
+    "y.show()"
+   ]
+  },
   {
    "cell_type": "markdown",
    "metadata": {
@@ -998,6 +997,113 @@
     "sum(first_n_sq_gen_expr)"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Basic file IO"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 20,
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "# naive way: write to a text file\n",
+    "file_name = \"/tmp/dummy.txt\"\n",
+    "fh = open(file_name, 'w')\n",
+    "fh.write(\"Hello\\n\")\n",
+    "fh.close()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 21,
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "# better: write to a text file, close file handle implicitly (ContextManager)\n",
+    "with open(file_name, 'a') as fh:\n",
+    "    fh.write(\"World\\n\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "skip"
+    }
+   },
+   "source": [
+    "#### Background information on the `with` statement and context managers\n",
+    "\n",
+    "* https://docs.python.org/3/reference/compound_stmts.html#the-with-statement\n",
+    "* https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers\n",
+    "* https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 22,
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "['Hello\\n', 'World\\n']\n"
+     ]
+    }
+   ],
+   "source": [
+    "# read the complete file into a list in memory\n",
+    "with open(file_name, 'r') as fh:\n",
+    "    lines = fh.readlines()\n",
+    "print(lines)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 23,
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Hello\n",
+      "World\n"
+     ]
+    }
+   ],
+   "source": [
+    "# when reading, the file handle `fh` is actually an iterator on the lines of the file\n",
+    "with open(file_name, 'r') as fh:\n",
+    "    for line in fh:\n",
+    "        print(line, end='')"
+   ]
+  },
   {
    "cell_type": "markdown",
    "metadata": {
@@ -1195,29 +1301,56 @@
     }
    },
    "source": [
-    "### Basic file IO"
+    "### Parameter files\n",
+    "\n",
+    "* scientific codes are often initialized using parameter files\n",
+    "    * parameter files can be edited by hand\n",
+    "    * code does not need to be changed, reads in parameter file\n",
+    "* recommended\n",
+    "    * YAML $\\to$ human-readable, compatible with many other tools\n",
+    "* less recommended\n",
+    "    * configparser (\".cfg\", contained in standard library)\n",
+    "    * JSON (\".json\", contained in standard library))\n",
+    "    * custom formats"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 20,
+   "execution_count": 29,
    "metadata": {
     "slideshow": {
-     "slide_type": "fragment"
+     "slide_type": "subslide"
     }
    },
    "outputs": [],
    "source": [
-    "# naive way: write to a text file\n",
-    "file_name = \"/tmp/dummy.txt\"\n",
-    "fh = open(file_name, 'w')\n",
-    "fh.write(\"Hello\\n\")\n",
-    "fh.close()"
+    "# let's assume our code uses a nested dict for parameter handling\n",
+    "par = {}\n",
+    "par[\"general\"] = {}\n",
+    "par[\"general\"][\"time_steps\"] = 1000\n",
+    "par[\"general\"][\"resolution\"] = (1024,1024,512)\n",
+    "par[\"species\"] = {}\n",
+    "par[\"species\"][\"H\"] = False\n",
+    "par[\"species\"][\"N\"] = True"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "#### YAML\n",
+    "\n",
+    "* available via the `pyyaml` package\n",
+    "* https://pyyaml.org/wiki/PyYAMLDocumentation"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 21,
+   "execution_count": 30,
    "metadata": {
     "slideshow": {
      "slide_type": "fragment"
@@ -1225,73 +1358,70 @@
    },
    "outputs": [],
    "source": [
-    "# better: write to a text file, close file handle implicitly (ContextManager)\n",
-    "with open(file_name, 'a') as fh:\n",
-    "    fh.write(\"World\\n\")"
+    "# write the par object to a well-formatted YAML file\n",
+    "import yaml\n",
+    "\n",
+    "with open(\"par.yaml\", 'w') as fp:\n",
+    "    yaml.safe_dump(par, fp, default_flow_style=False, indent=4)"
    ]
   },
   {
-   "cell_type": "markdown",
+   "cell_type": "code",
+   "execution_count": 31,
    "metadata": {
     "slideshow": {
-     "slide_type": "skip"
+     "slide_type": "fragment"
     }
    },
+   "outputs": [],
    "source": [
-    "#### Background information on the `with` statement and context managers\n",
-    "\n",
-    "* https://docs.python.org/3/reference/compound_stmts.html#the-with-statement\n",
-    "* https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers\n",
-    "* https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager"
+    "# read the parameters back from YAML\n",
+    "with open(\"par.yaml\", 'r') as fp:\n",
+    "    par_y = yaml.safe_load(fp)"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 22,
+   "cell_type": "markdown",
    "metadata": {
     "slideshow": {
      "slide_type": "subslide"
     }
    },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "['Hello\\n', 'World\\n']\n"
-     ]
-    }
-   ],
    "source": [
-    "# read the complete file into a list in memory\n",
-    "with open(file_name, 'r') as fh:\n",
-    "    lines = fh.readlines()\n",
-    "print(lines)"
+    "```yaml\n",
+    "# par.yaml\n",
+    "general:\n",
+    "    resolution:\n",
+    "    - 1024\n",
+    "    - 1024\n",
+    "    - 512\n",
+    "    time_steps: 1000\n",
+    "species:\n",
+    "    H: false\n",
+    "    N: true\n",
+    "```"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 23,
+   "cell_type": "markdown",
    "metadata": {
     "slideshow": {
-     "slide_type": "fragment"
+     "slide_type": "subslide"
     }
    },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Hello\n",
-      "World\n"
-     ]
-    }
-   ],
    "source": [
-    "# when reading, the file handle `fh` is actually an iterator on the lines of the file\n",
-    "with open(file_name, 'r') as fh:\n",
-    "    for line in fh:\n",
-    "        print(line, end='')"
+    "### Python Environments\n",
+    "\n",
+    "* a Python environment contains a Python interpreter *plus* a set of additional Python libraries (\"dependencies\")\n",
+    "* resides in an individual directory in user space, independent of other local environments  \n",
+    "  $\\rightarrow$ offers flexibility to install custom software versions (user-defined software stacks)\n",
+    "* often used to install complex packages with lots of dependencies, or during development and testing of a package\n",
+    "* using environment-specific metadata files (`requirements.txt` or `environment.yml`) it is possible to make environments re-creatable easily, and potentially reproducible\n",
+    "\n",
+    "#### Two popular options\n",
+    "\n",
+    "* Python Virtual Environments\n",
+    "* Conda Environments"
    ]
   },
   {
@@ -1302,37 +1432,43 @@
     }
    },
    "source": [
-    "### Parameter files\n",
+    "#### Python Virtual Environments\n",
     "\n",
-    "* scientific codes are often initialized using parameter files\n",
-    "    * parameter files can be edited by hand\n",
-    "    * code does not need to be changed, reads in parameter file\n",
-    "* recommended\n",
-    "    * YAML $\\to$ human-readable, compatible with many other tools\n",
-    "* less recommended\n",
-    "    * configparser (\".cfg\", contained in standard library)\n",
-    "    * JSON (\".json\", contained in standard library))\n",
-    "    * custom formats"
+    "* Part of Python's standard library since version 3.3, i.e. bundled with any recent Python installation\n",
+    "* Supported by Python's own package manager `pip` (and by compatible tools building upon `pip`)\n",
+    "* Packages and their dependencies are automatically downloaded from [PyPI](https://pypi.org)\n",
+    "* Only Python versions that are locally installed on the same machine are supported\n",
+    "* https://docs.python.org/3/library/venv.html"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 29,
+   "cell_type": "markdown",
    "metadata": {
     "slideshow": {
      "slide_type": "subslide"
     }
    },
-   "outputs": [],
    "source": [
-    "# let's assume our code uses a nested dict for parameter handling\n",
-    "par = {}\n",
-    "par[\"general\"] = {}\n",
-    "par[\"general\"][\"time_steps\"] = 1000\n",
-    "par[\"general\"][\"resolution\"] = (1024,1024,512)\n",
-    "par[\"species\"] = {}\n",
-    "par[\"species\"][\"H\"] = False\n",
-    "par[\"species\"][\"N\"] = True"
+    "```bash\n",
+    "$ python3 -m venv $HOME/my_venv\n",
+    "$ source $HOME/my_venv/bin/activate\n",
+    "(my_venv) $ which python3\n",
+    "/home/khr/my_venv/bin/python3\n",
+    "(my_venv) $ pip3 install numpy\n",
+    "Collecting numpy\n",
+    "Downloading numpy-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (16.3 MB)\n",
+    "Installing collected packages: numpy\n",
+    "Successfully installed numpy-2.1.3\n",
+    "(my_venv) $ python3 \n",
+    "Python 3.10.12 (main, Nov  6 2024, 20:22:13) [GCC 11.4.0] on linux\n",
+    "Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n",
+    ">>> import numpy as np\n",
+    ">>> np.__version__\n",
+    "'2.1.3'\n",
+    ">>> exit()\n",
+    "(my_venv) $ deactivate \n",
+    "$\n",
+    "```"
    ]
   },
   {
@@ -1343,42 +1479,60 @@
     }
    },
    "source": [
-    "#### YAML\n",
+    "#### Conda Environments\n",
     "\n",
-    "* available via the `pyyaml` package\n",
-    "* https://pyyaml.org/wiki/PyYAMLDocumentation"
+    "* The `conda` package manager is a fundamental component of the Anaconda ecosystem and its free counterpart (`conda-forge`)\n",
+    "* `conda` supports arbitrary software, not limited to Python packages  \n",
+    "  $\\rightarrow$ enables complex software environments, often including basic libraries pulled in via dependencies"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 30,
+   "cell_type": "markdown",
    "metadata": {
     "slideshow": {
-     "slide_type": "fragment"
+     "slide_type": "subslide"
     }
    },
-   "outputs": [],
    "source": [
-    "# write the par object to a well-formatted YAML file\n",
-    "import yaml\n",
+    "#### Preparation: Installation of the base environment\n",
     "\n",
-    "with open(\"par.yaml\", 'w') as fp:\n",
-    "    yaml.safe_dump(par, fp, default_flow_style=False, indent=4)"
+    "```bash\n",
+    "$ wget https://github.com/conda-forge/miniforge/releases/download/24.9.2-0/Miniforge3-Linux-x86_64.sh\n",
+    "$ bash Miniforge3-Linux-x86_64.sh -f -b -p /opt/apps/miniforge3\n",
+    "( ... many lines stripped ...)\n",
+    "$ source /opt/apps/miniforge3/bin/activate\n",
+    "(base) $ which python3\n",
+    "/opt/apps/miniforge3/bin/python3\n",
+    "(base) $ python3 --version\n",
+    "Python 3.12.7\n",
+    "```"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 31,
+   "cell_type": "markdown",
    "metadata": {
     "slideshow": {
-     "slide_type": "fragment"
+     "slide_type": "subslide"
     }
    },
-   "outputs": [],
    "source": [
-    "# read the parameters back from YAML\n",
-    "with open(\"par.yaml\", 'r') as fp:\n",
-    "    par_y = yaml.safe_load(fp)"
+    "#### Example: Creation of an actual Conda environment with Python 3.13 and NumPy\n",
+    "\n",
+    "```bash\n",
+    "(base) $ conda create -n my_env python=3.13\n",
+    "( ... many lines stripped ...)\n",
+    "(base) $ conda activate my_env\n",
+    "(my_env) $ which python3                                                \n",
+    "/opt/apps/miniforge3/envs/my_env/bin/python3\n",
+    "(my_env) $ python3 --version\n",
+    "Python 3.13.0\n",
+    "(my_env) $ conda install numpy\n",
+    "(my_env) $ python3            \n",
+    ">>> import numpy as np\n",
+    ">>> np.__version__\n",
+    "'2.1.3'\n",
+    ">>>\n",
+    "```"
    ]
   },
   {
@@ -1389,18 +1543,20 @@
     }
    },
    "source": [
-    "```yaml\n",
-    "# par.yaml\n",
-    "general:\n",
-    "    resolution:\n",
-    "    - 1024\n",
-    "    - 1024\n",
-    "    - 512\n",
-    "    time_steps: 1000\n",
-    "species:\n",
-    "    H: false\n",
-    "    N: true\n",
-    "```"
+    "#### Conda Environments (cont'd)\n",
+    "\n",
+    "* Observations  \n",
+    "  * The base environment contains a standalone Python installation, together with its binary dependencies\n",
+    "  * The custom environment ('my_env') containes a standalone Python installation, together with its binary dependencies\n",
+    "  * The installation of 'numpy' has pulled in additional binary dependencies, such as BLAS and LAPACK\n",
+    "* Caution  \n",
+    "  * Conda environments can become quite large (in file count and overall size)\n",
+    "  * Binary blobs downloaded from the Internet can be incompatible with the local OS, leading to runtime errors\n",
+    "  * License issues, effective since March 2024, for Anaconda software channels!\n",
+    "\n",
+    "##### More Information\n",
+    "\n",
+    "[Navigating the Anaconda Python License Change: Adopting Conda-Forge and Best Practices for HPC Python Environments (Meet MPCDF seminar, October 2024)](https://datashare.mpcdf.mpg.de/s/CZR64ip6fvi6TqA)"
    ]
   },
   {
diff --git a/notebooks/05--NumPy_SciPy.ipynb b/notebooks/05--NumPy_SciPy.ipynb
index 5b51411..9b4f549 100644
--- a/notebooks/05--NumPy_SciPy.ipynb
+++ b/notebooks/05--NumPy_SciPy.ipynb
@@ -992,7 +992,7 @@
     "\n",
     "x = np.linspace(0, 2.0, 10)\n",
     "y = np.sin(x)\n",
-    "result = integrate.simps(y, x) # Simpson rule for given sample\n",
+    "result = integrate.simpson(y, x=x) # Simpson rule for given sample\n",
     "print(result, 1.-np.cos(2.0))\n",
     "\n",
     "# simple derivative: exponential\n",
@@ -1648,8 +1648,8 @@
    },
    "outputs": [],
    "source": [
-    "filtered_loop = get_filtered_loop(image)\n",
-    "filtered_array = get_filtered_array(image)\n",
+    "filtered_loop = get_filtered_loop(image)[1:-1,1:-1]\n",
+    "filtered_array = get_filtered_array(image)[1:-1,1:-1]\n",
     "\n",
     "f, axs = plt.subplots(2, 3, figsize=(14, 8))\n",
     "axs[0, 0].imshow(image, cmap='gray')\n",
@@ -1657,7 +1657,7 @@
     "axs[0, 2].imshow(filtered_array - filtered_loop, cmap='gray')\n",
     "axs[1, 0].imshow(image[600:700, 600:700], cmap='gray')\n",
     "axs[1, 1].imshow(filtered_array[600:700, 600:700], cmap='gray')\n",
-    "axs[1, 2].imshow((image-filtered_array)[600:700, 600:700], cmap='gray')\n",
+    "axs[1, 2].imshow((image[1:-1,1:-1]-filtered_array)[600:700, 600:700], cmap='gray')\n",
     "print(\"Loop and array method yields the same: \", np.allclose(filtered_loop, filtered_array))"
    ]
   },
@@ -1687,7 +1687,7 @@
    },
    "outputs": [],
    "source": [
-    "from scipy.misc import ascent\n",
+    "from scipy.datasets import ascent\n",
     "im = plt.imshow(ascent(), cmap='gray')"
    ]
   },
@@ -1727,7 +1727,7 @@
     "    return result\n",
     "f, axs = plt.subplots(1, 2, figsize=(15, 5))\n",
     "axs[0].imshow(ascent(), cmap='gray')\n",
-    "axs[1].imshow(get_edges(ascent()), cmap='gray');None"
+    "axs[1].imshow(get_edges(ascent().astype('int32')), cmap='gray');None"
    ]
   },
   {
-- 
GitLab