diff --git a/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/.pages.yml b/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/.pages.yml index c19a5ee45..0e6dbd1b9 100644 --- a/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/.pages.yml +++ b/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/.pages.yml @@ -1,5 +1,5 @@ --- nav: - - Jupyter_kernels_Tool_assisted_management.md - - Jupyter_kernels_Manual_management.md + - Python and R kernels in JupyterLab: python_and_r_kernels_in_JupyterLab.md + - Containers as kernels in JupyterLab: containers_as_kernels_in_JupyterLab.md - "*" diff --git a/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/Jupyter_kernels_Manual_management.md b/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/Jupyter_kernels_Manual_management.md deleted file mode 100644 index d859d4cd9..000000000 --- a/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/Jupyter_kernels_Manual_management.md +++ /dev/null @@ -1,436 +0,0 @@ ---- -created_at: 2025-01-24 -description: How to set up your own custom kernels for use on Mahuika JupyterHub -tags: - - JupyterHub - - Python - - R ---- - -# Jupyter kernels - Manual management - -## Introduction - -Jupyter kernels execute the code that you write. Mahuika provides a number of -Python and R kernels by default, which can be selected from the Launcher. - -Many packages are preinstalled in our default Python and R environments -and these can be extended further as described on the -[Python](../../../../Software/Available_Applications/Python.md) and -[R](../../../../Software/Available_Applications/R.md) support -pages. - -## Adding a Custom Python kernel - -You can configure custom Python kernels for running your Jupyter -notebooks. This could be necessary and/or recommended in some -situations, including: - -- If you wish to load a different combination of environment modules - than those we load in our default kernels -- If you would like to activate a virtual environment or conda - environment before launching the kernel - -The following example will create a custom kernel based on either a conda -environment (using the Miniforge3 environment module) or a Python virtual -environment (using a Python environment module). The same approach applies -to other environment modules too. - -!!! note "see also" - See the [Jupyter kernels - Tool-assisted management](./Jupyter_kernels_Tool_assisted_management.md) - page for the **preferred** way to register kernels, which uses the - `nesi-add-kernel` command line tool to automate most of these manual - steps. - -First, change directory into the path that you would like to place your -environment. - -- **If you would like to share this environment with other users**, change directory -into your project folder using `cd /nesi/project/`. Do not use the path -that includes `00_nesi_projects` or `home` in the name as this causes issues. - -Next, you will create your environment and a wrapper script for it. You can -choose whether to use a **conda environment**, or a **Python virtual -environment**: - -=== "Conda environment" - - Second, in a terminal run the following commands to load a Miniforge - environment module: - - ``` sh - module purge - module load Miniforge3 - ``` - - Now create a conda environment named "my-conda-env" using Python 3.11. - The *ipykernel* Python package is required but you can change the names - of the environment, version of Python and install other Python packages - as required. - - ``` sh - conda create --prefix ./my-conda-env python=3.11 - source $(conda info --base)/etc/profile.d/conda.sh - conda activate ./my-conda-env - conda install ipykernel - # you can pip/conda install other packages here too - ``` - - Third, we will create a wrapper for your conda environment. - Change directory into your `my-conda-env` folder: - - ``` sh - cd my-conda-env - ``` - - And add the following as `wrapper.sh` into your `my-conda-env` folder: - - ``` sh - #!/usr/bin/env bash - - # load required modules here - module purge - module load Miniforge3 - - # activate conda environment - source $(conda info --base)/etc/profile.d/conda.sh - conda deactivate # workaround for https://github.com/conda/conda/issues/9392 - conda activate my-conda-env - - # run the kernel - exec python $@ - ``` - - Make the wrapper script executable: - - ``` sh - chmod +x wrapper.sh - ``` - - Fourth, create a Jupyter kernel based on your new conda environment: - - ``` sh - python -m ipykernel install --user --name my-conda-env --display-name="My Conda Env" - ``` - - We must now edit the kernel to load the required environment - modules before the kernel is launched. Change to the directory the - kernelspec was installed to - `~/.local/share/jupyter/kernels/my-conda-env`, (assuming you kept - `--name my-conda-env` in the above command): - - ``` sh - mkdir -p ~/.local/share/jupyter/kernels/my-conda-env - cd ~/.local/share/jupyter/kernels/my-conda-env - ``` - - and edit the *kernel.json* to change the first element of the argv list - to point to the wrapper script we just created. The file should look - like this: - - ```json - { - "argv": [ - "/wrapper.sh", - "-m", - "ipykernel_launcher", - "-f", - "{connection_file}" - ], - "display_name": "My Conda Env", - "language": "python" - } - ``` - - After refreshing JupyterLab your new kernel should show up in the - Launcher as "My Conda Env". - -=== "Python virtual environment" - - Second, in a terminal run the following commands to load a Python - environment module: - - ``` sh - module purge - module load Python/3.14.4-foss-2026 - ``` - - Now create a Python virtual environment named "my-venv". - The *ipykernel* Python package is required but you can change the name - of the environment and install other Python packages as required. - - ``` sh - python3 -m venv ./my-venv - source ./my-venv/bin/activate - pip install --upgrade pip - pip install ipykernel - # you can pip install other packages here too - ``` - - Third, we will create a wrapper for your virtual environment. - Change directory into your `my-venv` folder: - - ``` sh - cd my-venv - ``` - - And add the following as `wrapper.sh` into your `my-venv` folder: - - ``` sh - #!/usr/bin/env bash - - # load required modules here - module purge - module load Python/3.14.4-foss-2026 - - # activate virtual environment - source /my-venv/bin/activate - - # run the kernel - exec python $@ - ``` - - Make the wrapper script executable: - - ``` sh - chmod +x wrapper.sh - ``` - - Fourth, create a Jupyter kernel based on your new virtual environment: - - ``` sh - python -m ipykernel install --user --name my-venv --display-name="My Venv" - ``` - - We must now edit the kernel to load the required environment - modules before the kernel is launched. Change to the directory the - kernelspec was installed to - `~/.local/share/jupyter/kernels/my-venv`, (assuming you kept - `--name my-venv` in the above command): - - ``` sh - mkdir -p ~/.local/share/jupyter/kernels/my-venv - cd ~/.local/share/jupyter/kernels/my-venv - ``` - - and edit the *kernel.json* to change the first element of the argv list - to point to the wrapper script we just created. The file should look - like this: - - ```json - { - "argv": [ - "/wrapper.sh", - "-m", - "ipykernel_launcher", - "-f", - "{connection_file}" - ], - "display_name": "My Venv", - "language": "python" - } - ``` - - After refreshing JupyterLab your new kernel should show up in the - Launcher as "My Venv". - -## Sharing your custom kernal with your project team members - -You can also configure a shared Python kernel that others with access to -the same project will be able to load. - -- To do this, you must make sure it also exists in a shared location -(other users cannot see your home directory). - -First, **you** need to perform the steps in [Adding a Custom Python kernel](#adding-a-custom-python-kernel) - -Next, **your team members** need to set up the kernel on their side. The -exact steps depend on the type of environment you created, so follow the -steps in the tab that matches it: - -=== "Conda environment" - - Second, **your team members** need to run the following commands in the - terminal: - - ``` sh - # change directory into the path that contains your conda environment - cd - - # load Miniforge3 - module purge - module load Miniforge3 - - # Activate your shared conda environment - source $(conda info --base)/etc/profile.d/conda.sh - conda activate ./my-conda-env - ``` - - Third, get **your team members** to create a Jupyter kernel based on your - conda environment: - - ``` sh - python -m ipykernel install --user --name my-conda-env --display-name="My Conda Env" - ``` - - **Your project members** must now edit the kernel in their home directories - to load the required environment modules before the kernel is launched. - Change to the directory the kernelspec was installed to - `~/.local/share/jupyter/kernels/my-conda-env`, (assuming you kept - `--name my-conda-env` in the above command): - - ``` sh - mkdir -p ~/.local/share/jupyter/kernels/my-conda-env - cd ~/.local/share/jupyter/kernels/my-conda-env - ``` - - and edit the *kernel.json* to change the first element of the argv list - to point to the wrapper script we just created. The file should look - like this: - - ```json - { - "argv": [ - "/wrapper.sh", - "-m", - "ipykernel_launcher", - "-f", - "{connection_file}" - ], - "display_name": "My Conda Env", - "language": "python" - } - ``` - - After refreshing JupyterLab your new kernel should show up in the - Launcher as "My Conda Env". - -=== "Python virtual environment" - - Second, **your team members** need to run the following commands in the - terminal: - - ``` sh - # load the Python environment module - module purge - module load Python/3.14.4-foss-2026 - - # Activate the shared virtual environment - source /my-venv/bin/activate - ``` - - Third, get **your team members** to create a Jupyter kernel based on your - virtual environment: - - ``` sh - python -m ipykernel install --user --name my-venv --display-name="My Venv" - ``` - - **Your project members** must now edit the kernel in their home directories - to load the required environment modules before the kernel is launched. - Change to the directory the kernelspec was installed to - `~/.local/share/jupyter/kernels/my-venv`, (assuming you kept - `--name my-venv` in the above command): - - ``` sh - mkdir -p ~/.local/share/jupyter/kernels/my-venv - cd ~/.local/share/jupyter/kernels/my-venv - ``` - - and edit the *kernel.json* to change the first element of the argv list - to point to the wrapper script we just created. The file should look - like this: - - ```json - { - "argv": [ - "/wrapper.sh", - "-m", - "ipykernel_launcher", - "-f", - "{connection_file}" - ], - "display_name": "My Venv", - "language": "python" - } - ``` - - After refreshing JupyterLab your new kernel should show up in the - Launcher as "My Venv". - -## Custom kernel in a Singularity container - -An example showing setting up a custom kernel running in a Singularity -container can be found on our [Lambda Stack](../../../../Software/Available_Applications/Lambda_Stack.md#lambda-stack-via-jupyter) -support page. - -## Adding a custom R kernel - -You can configure custom R kernels for running your Jupyter notebooks. -The following example will create a custom kernel based on the -R/3.6.2-gimkl-2020a environment module and will additionally load an -MPFR environment module (e.g. if you wanted to load the Rmpfr package). - -In a terminal run the following commands to load the required -environment modules: - -``` sh -module purge -module load IRkernel/1.1.1-gimkl-2020a-R-3.6.2 -module load Python/3.8.2-gimkl-2020a -``` - -The IRkernel module loads the R module as a dependency and provides the -R kernel for Jupyter. Python is required to install the kernel (since -Jupyter is written in Python). - -Now create an R Jupyter kernel based on your new conda environment: - -``` sh -R -e "IRkernel::installspec(name='myrwithmpfr', displayname = 'R with MPFR', user = TRUE)" -``` - -We must now to edit the kernel to load the required environment -modules when the kernel is launched. Change to the directory the -kernelspec was installed to -(~/.local/share/jupyter/kernels/myrwithmpfr, assuming you kept `--name -myrwithmpfr` in the above command): - -``` sh -cd ~/.local/share/jupyter/kernels/myrwithmpfr -``` - -Now create a wrapper script in that directory, called *wrapper.sh*, with -the following contents: - -``` sh -#!/usr/bin/env bash - -# load required modules here -module purge -module load MPFR/4.0.2-GCCcore-9.2.0 -module load IRkernel/1.1.1-gimkl-2020a-R-3.6.2 - -# run the kernel -exec R $@ -``` - -Make the wrapper script executable: - -``` sh -chmod +x wrapper.sh_ - "argv": [ - "/home//.local/share/jupyter/kernels/myrwithmpfr/wrapper.sh", - "--slave", - "-e", - "IRkernel::main()", - "--args", - "{connection_file}" - ], - "display_name": "R with MPFR", - "language": "R" -} -``` - -After refreshing JupyterLab your new R kernel should show up in the -Launcher as "R with MPFR". diff --git a/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/Jupyter_kernels_Tool_assisted_management.md b/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/Jupyter_kernels_Tool_assisted_management.md deleted file mode 100644 index 3b7d8b87e..000000000 --- a/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/Jupyter_kernels_Tool_assisted_management.md +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: Jupyter kernels - Tool-assisted management -description: -tags: - - JupyterHub - - Python - - R ---- - -## Introduction - -Jupyter can execute code in different computing environments using -*kernels*. Some kernels are provided by default (Python, R, etc.) but -you may want to register your computing environment to use it in -notebooks. For example, you may want to load a specific environment -module in your kernel or use a Conda environment. - -To register a Jupyter kernel, you can follow the steps highlighted in -the [Jupyter kernels - Manual management](./Jupyter_kernels_Manual_management.md) -or use the `nesi-add-kernel` tool provided within the [Jupyter on Mahuika service](https://jupyter.nesi.org.nz). -This page details the latter option, which we recommend. - -## Getting started - -First you need to open a terminal. It can be from a session on Jupyter -via OnDemand or from a regular ssh connection on Mahuika login node. If you -use the ssh option, make sure to load the JupyterLab module to have -access to the `nesi-add-kernel` tool: - -``` sh -module purge # remove all previously loaded modules -module load JupyterLab -``` - -Then, to list all available options, use the `-h` or `--help` options as -follows: - -``` sh -nesi-add-kernel --help -``` - -Here is an example to add a TensorFlow kernel, using Mahuika’s module: - -``` sh -nesi-add-kernel tf_kernel TensorFlow/2.8.2-gimkl-2022a-Python-3.10.5 -``` - -!!! warning - The name given to your kernel in `nesi-add-kernel KERNEL_NAME MODULE` must only include lowercase letters, underscores, and dashes. - -and to share the kernel with other members of your project: - -``` sh -nesi-add-kernel --shared tf_kernel_shared TensorFlow/2.8.2-gimkl-2022a-Python-3.10.5 -``` - -To list all the installed kernels, use the following command: - -``` sh -jupyter-kernelspec list -``` - -and to delete a specific kernel: - -``` sh -jupyter-kernelspec remove -``` - -where `` stands for the name of the kernel to delete. - -## Conda environment - -First, make sure the `JupyterLab` module is loaded: - -``` sh -module purge -module load JupyterLab -``` - -To add a Conda environment created using -`conda create -p `, use: - -``` sh -nesi-add-kernel my_conda_env -p -``` - -otherwise if created using `conda create -n `, use: - -``` sh -nesi-add-kernel my_conda_env -n -``` - -## Virtual environment - -If you want to use a Python virtual environment, don’t forget to specify -which Python module you used to create it. - -For example, if we create a virtual environment named `my_test_venv` -using Python 3.10.5: - -``` sh -module purge -module load Python/3.10.5-gimkl-2022a -python -m venv my_test_venv -``` - -to create the corresponding `my_test_kernel` kernel, we need to use the -command: - -``` sh -module purge -module load JupyterLab -nesi-add-kernel my_test_kernel Python/3.10.5-gimkl-2022a --venv my_test_venv -``` - -## Singularity container - -!!! danger - - This section has not been tested on Mahuika OnDemand - -To use a Singularity container, use the `-c` or `--container` options as -follows: - -``` sh -module purge -module load JupyterLab -nesi-add-kernel my_test_kernel -c -``` - -where `` is a path to your container image. - -Note that your container **must** have the `ipykernel` Python package -installed in it to be able to work as a Jupyter kernel. - -Additionally, you can use the `--container-args` option to pass more -arguments to the `singularity exec` command used to instantiate the -kernel. - -Here is an example instantiating a NVIDIA NGC container as a kernel. -First, we need to pull the container: - -``` sh -module purge -module load Singularity/3.11.3 -singularity pull nvidia_tf.sif docker://nvcr.io/nvidia/tensorflow:21.07-tf2-py3 -``` - -then we can instantiate the kernel, using the `--nv` singularity flag to -ensure that the GPU will be found at runtime (assuming our Jupyter -session has access to a GPU): - -``` sh -module purge -module load JupyterLab -nesi-add-kernel nvidia_tf -c nvidia_tf.sif --container-args "'--nv'" -``` - -Note that the double-quoting of `--nv` is needed to properly pass the -options to `singularity exec`. diff --git a/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/containers_as_kernels_in_JupyterLab.md b/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/containers_as_kernels_in_JupyterLab.md new file mode 100644 index 000000000..a7ca83aac --- /dev/null +++ b/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/containers_as_kernels_in_JupyterLab.md @@ -0,0 +1,438 @@ +--- +title: Containers as kernels in JupyterLab +description: How to use containers as kernels in JupyterLab on Mahuika +tags: + - JupyterHub +--- + +Apptainer containers can be run as kernels in JupyterLab, so that the code in +your notebook executes inside the container. + +## Adding a container as a kernel to JupyterLab + +There are two ways to run a container as a kernel; select the tab that suits you: + +- **Tool-Assisted Management**: uses the `nesi-add-kernel` command line tool to + automate most of the setup. This is the **recommended** approach if possible. +- **Manual Management**: you set up the kernel and its wrapper script by hand. + This can be useful when you need more control over how the kernel is launched. + +!!! warning + + To use containers you must launch your Jupyter session with **Cluster** set + to **Slurm HPC** and the **JupyterLab module** set to + **2026.7.0-foss-2026-4.6.0**. If you do not see **Slurm HPC** in the + **Cluster** list, [get in touch](mailto:support@nesi.org.nz). + +

JupyterLab launch form with Cluster set to Slurm HPC and JupyterLab module set to 2026.7.0-foss-2026-4.6.0

+ +=== "Tool-Assisted Management" + + The `nesi-add-kernel` tool can register a container as a kernel for you. + **This is the recommended way to run a container as a kernel.** + + First you need to open a terminal. It can be from a session on Jupyter via + OnDemand or from a regular ssh connection on the Mahuika login node. + + - If you use the ssh option, make sure to load the JupyterLab module to have + access to the `nesi-add-kernel` tool: + + ``` sh + module purge # remove all previously loaded modules + module load JupyterLab + ``` + + There are two ways to run a container as a kernel; select the tab that suits + your container: + + === "Python kernel" + + This runs a **Python** kernel *inside* the container. The container must + provide a Python interpreter with the `ipykernel` package installed. + + ``` sh + nesi-add-kernel -cp + ``` + + Where: + + - ``: the name you want to give the kernel. + - ``: the path to your Apptainer container image. + + === "Bash kernel" + + This runs a **bash** kernel that dispatches every cell into the + container. + + ``` sh + nesi-add-kernel -cb + ``` + + Where: + + - ``: the name you want to give the kernel. + - ``: the path to your Apptainer container image. + + !!! tip "Passing arguments to Apptainer" + + Use the `--container-args` option to pass additional arguments through to + the `apptainer exec` command (this works for both `-cp` and `-cb`). + Because these arguments start with `-`, use the `=` form so they are not + mistaken for options to `nesi-add-kernel` itself. For example, to enable + GPU support: + + ``` sh + nesi-add-kernel -cp --container-args="--nv" + ``` + + Multiple arguments can be passed together: + + ``` sh + nesi-add-kernel -cp --container-args="--nv --pwd /opt/app" + ``` + + !!! tip + + For more information about `nesi-add-kernel`, type into the terminal: + + ``` sh + nesi-add-kernel --help + ``` + +=== "Manual Management" + + You can also set up a container kernel by hand. You can build a kernel that + uses a container's version of python or bash: + + === "Python kernel" + + This runs a **Python** kernel *inside* the container (the manual + equivalent of the `-cp` option), so the container must provide a Python + interpreter with the `ipykernel` package installed. + + First, change directory into the path where you would like to place your + wrapper script. + + - If you would like to share it with other members of your project, use + your project folder (`cd /nesi/project/`). + - Avoid paths that include `00_nesi_projects` or `home`, as these cause + issues. + + Second, create a file called `wrapper.sh` with the following contents + (replace `` with the path to your container + image): + + ``` sh + #!/usr/bin/env bash + + # start with a clean environment + module purge + + # isolate the container interpreter from your ~/.local site-packages + export APPTAINERENV_PYTHONNOUSERSITE=True + + # bind the directory holding the Jupyter connection file (the last + # argument) so the in-container interpreter can read it + for connection_file in "$@"; do :; done + connection_dir="$(dirname "$connection_file")" + + # run a python kernel inside the container + exec apptainer exec -B "$connection_dir" --nv python "$@" + ``` + + Make the wrapper script executable: + + ``` sh + chmod +x wrapper.sh + ``` + + Third, create a directory for your kernel: + + ``` sh + mkdir -p ~/.local/share/jupyter/kernels/my-container + cd ~/.local/share/jupyter/kernels/my-container + ``` + + and create a file called *kernel.json*. The file should look like this: + + ```json + { + "argv": [ + "/wrapper.sh", + "-m", + "ipykernel_launcher", + "-f", + "{connection_file}" + ], + "display_name": "Container Name", + "language": "python" + } + ``` + + - Change `display_name` to what you would like to call your kernel by. + + After refreshing JupyterLab your new kernel should show up in the + Launcher under the display name you set in `kernel.json` (`Container + Name` in the example above). + + === "Bash kernel" + + This runs a **bash** kernel on the host that dispatches every cell into + the container (the manual equivalent of the `-cb` option). To do this you + first need to set up a Python virtual environment, in the same way as the + Manual Management approach described on the + [Python and R kernels in JupyterLab](./python_and_r_kernels_in_JupyterLab.md) + page. + + In brief, the steps below create a Python virtual environment, install + `bash_kernel` into it, write a wrapper script that points `bash_kernel` at + your container, and then register that wrapper as a Jupyter kernel. + + First, change directory into the path where you would like to place your + virtual environment. + + - If you would like to share it with other members of your project, use + your project folder (`cd /nesi/project/`). + - Avoid paths that include `00_nesi_projects` or `home`, as these cause + issues. + + Second, in a terminal run the following commands to load a Python + environment module: + + ``` sh + module purge + module load Python/3.14.4-foss-2026 + ``` + + Now create a Python virtual environment named `my-container-venv`. You can + change the name of the environment and install other Python packages as + required. + + ``` sh + python3 -m venv ./my-container-venv + source ./my-container-venv/bin/activate + pip install --upgrade pip + ``` + + Third, install `bash_kernel` in your virtual environment. + + ??? note "What is bash_kernel?" + + `bash_kernel` runs a bash shell as a Jupyter kernel. Here we point that bash shell at your container, so every cell you run in JupyterLab executes inside the container. It feels like a normal JupyterLab session, but the commands run in your container rather than on the host. + + ``` sh + pip install git+https://github.com/geoffreyweal/bash_kernel + ``` + + Fourth, create a wrapper for your virtual environment. Change directory + into your `my-container-venv` folder: + + ``` sh + cd my-container-venv + ``` + + And add the following as `wrapper.sh` into your `my-container-venv` folder: + + ``` sh + #!/usr/bin/env bash + + # load required modules here + module purge + module load Python/3.14.4-foss-2026 + + # activate the virtual environment that has bash_kernel installed + source /my-container-venv/bin/activate + + # run the kernel on the host (it dispatches every command into the container) + exec python3 "$@" + ``` + + Make the wrapper script executable: + + ``` sh + chmod +x wrapper.sh + ``` + + Fifth, create a directory for your kernel: + + ``` sh + mkdir -p ~/.local/share/jupyter/kernels/bash + cd ~/.local/share/jupyter/kernels/bash + ``` + + and create a file called *kernel.json*. The file should look like this: + + ```json + { + "argv": [ + "/wrapper.sh", + "-m", + "bash_kernel", + "-f", + "{connection_file}" + ], + "display_name": "Container Name", + "language": "bash", + "env": { + "BASH_KERNEL_CMD": "apptainer exec --nv bash" + } + } + ``` + + - Change `display_name` to what you would like to call your kernel by. + - Update the `apptainer exec` line in `BASH_KERNEL_CMD` to match your own + image, for example: + + ``` sh + "BASH_KERNEL_CMD": "apptainer exec --pwd /opt/PMDM --nv /nesi/project//containers/PMDM/pmdm_cu130.simg bash" + ``` + + After refreshing JupyterLab your new kernel should show up in the Launcher + under the display name you set in `kernel.json` (`Container Name` in the + example above). + +## Listing your kernels + +To list all the kernels that are currently installed, run: + +``` sh +module purge +module load JupyterLab +jupyter-kernelspec list +``` + +This works for any kernel, regardless of whether it was registered using the +Tool-Assisted Management or Manual Management approach. + +## Sharing a kernel + +You can also configure a shared container kernel that others with access to the +same project will be able to load. Whichever approach you use, make sure the +container image (and, for a bash kernel, the virtual environment and +`wrapper.sh`) live in a shared location such as your project folder +(`/nesi/project/`) — other users cannot read your home directory. +How you share depends on whether you registered the kernel with the +tool-assisted or manual approach: + +=== "Tool-Assisted Management" + + To share a container kernel, register it with `nesi-add-kernel` as you + normally would, but add the `--shared` flag. This installs the kernel into + your project's shared location, so other members of your project will see it + automatically. Select the tab for the kind of container kernel you are + sharing: + + === "Python kernel" + + ``` sh + nesi-add-kernel --shared -cp + ``` + + Where `` is the name you want to give to the kernel. Note + the `--shared` flag in the `nesi-add-kernel` command line. + + === "Bash kernel" + + ``` sh + nesi-add-kernel --shared -cb + ``` + + Where `` is the name you want to give to the kernel. Note + the `--shared` flag in the `nesi-add-kernel` command line. + + !!! note + + Run `nesi-add-kernel --shared` from a terminal inside a Jupyter session + on OnDemand so it can detect your project. From a regular ssh session you + will also need to pass the project code with the `--account` option, for + example `nesi-add-kernel --shared --account ...`. + +=== "Manual Management" + + For a manually-created kernel, **you** first create the kernel yourself, + following the manual steps in the **Manual Management** tab earlier on this + page, but making sure the container image and `wrapper.sh` (and, for a bash + kernel, the virtual environment) are all in your shared project folder. + + Next, **your team members** set up the kernel on their side by creating the + kernelspec in their own home directory. The steps depend on the type of + container kernel you created, so follow the matching tab: + + === "Python kernel" + + **Your team members** create a directory for the kernel: + + ``` sh + mkdir -p ~/.local/share/jupyter/kernels/my-container + cd ~/.local/share/jupyter/kernels/my-container + ``` + + and create a file called *kernel.json* that points at the shared + `wrapper.sh`. The file should look like this: + + ```json + { + "argv": [ + "/wrapper.sh", + "-m", + "ipykernel_launcher", + "-f", + "{connection_file}" + ], + "display_name": "Container Name", + "language": "python" + } + ``` + + - Change `display_name` to what you would like to call your kernel by. + + After refreshing JupyterLab the shared kernel should show up in the + Launcher. + + === "Bash kernel" + + **Your team members** create a directory for the kernel: + + ``` sh + mkdir -p ~/.local/share/jupyter/kernels/bash + cd ~/.local/share/jupyter/kernels/bash + ``` + + and create a file called *kernel.json* that points at the shared + `wrapper.sh`. The file should look like this: + + ```json + { + "argv": [ + "/wrapper.sh", + "-m", + "bash_kernel", + "-f", + "{connection_file}" + ], + "display_name": "Container Name", + "language": "bash", + "env": { + "BASH_KERNEL_CMD": "apptainer exec --nv bash" + } + } + ``` + + - Change `display_name` to what you would like to call your kernel by. + + After refreshing JupyterLab the shared kernel should show up in the + Launcher. + +## Removing a kernel + +To delete a specific kernel, run: + +``` sh +module purge +module load JupyterLab +jupyter-kernelspec list +jupyter-kernelspec remove +``` + +where `` is the name of the kernel to delete, as shown by +`jupyter-kernelspec list`. diff --git a/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/index.md b/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/index.md index 80d2b9e1f..239136e32 100644 --- a/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/index.md +++ b/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/index.md @@ -38,8 +38,8 @@ Mahuika provides some default Python and R kernels that are available to all use of environment modules. It's also possible to create additional kernels that are visible only to you (they can optionally be made visible to other members of a specific project that you belong to). See: -- [Jupyter kernels - Tool-assisted management](./Jupyter_kernels_Tool_assisted_management.md) (recommended) -- [Jupyter kernels - Manual management](./Jupyter_kernels_Manual_management.md) +- [Python and R kernels in JupyterLab - Tool-Assisted Management](./python_and_r_kernels_in_JupyterLab.md) (recommended) +- [Python and R kernels in JupyterLab - Manual Management](./python_and_r_kernels_in_JupyterLab.md) ### Jupyter terminal @@ -105,8 +105,9 @@ If your JupyterLab notebook "jumps" or skips pages unexpectedly, the cause is li #### The Solution: Adjust Windowing Mode To fix erratic scrolling, change the Windowing Mode setting to one of the following: -* `defer`: Waits for idle CPU cycles to render cells outside the viewport. This typically stops the jumping while maintaining good performance. -* `none`: Renders all cells immediately. This is the most stable option for scrolling but may slow down very large notebooks. + +- `defer`: Waits for idle CPU cycles to render cells outside the viewport. This typically stops the jumping while maintaining good performance. +- `none`: Renders all cells immediately. This is the most stable option for scrolling but may slow down very large notebooks. #### Step-by-Step Instructions 1. Open Settings: Go to Settings → Settings Editor in the top menu. diff --git a/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/python_and_r_kernels_in_JupyterLab.md b/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/python_and_r_kernels_in_JupyterLab.md new file mode 100644 index 000000000..3faa26b23 --- /dev/null +++ b/docs/Interactive_Computing/OnDemand/Apps/JupyterLab/python_and_r_kernels_in_JupyterLab.md @@ -0,0 +1,674 @@ +--- +title: Python and R kernels in JupyterLab +description: How to register and manage custom Jupyter kernels on Mahuika JupyterHub +tags: + - JupyterHub + - Python + - R +--- + +A Jupyter kernel is the actual thing that executes the code in your Jupyter notebook. +Mahuika provides a number of Python and R kernels by default; these can be selected from +the Launcher. These come with many packages preinstalled, and can be extended +further as described on the +[Python](../../../../Software/Available_Applications/Python.md) and +[R](../../../../Software/Available_Applications/R.md) support pages. + +## Adding a Kernel to JupyterLab + +Sometimes, though, you will want a kernel that runs in your own computing +environment - for example, to load a specific environment module, or to use a +Conda or Python virtual environment. There are two ways to register such a +custom kernel; select the tab that suits you: + +- **Tool-Assisted Management**: uses the `nesi-add-kernel` command line tool to + automate most of the setup. This is the **recommended** approach if possible. +- **Manual Management**: you set up the kernel and its wrapper script by hand. This + can be useful when you need more control over how the kernel is launched. + +=== "Tool-Assisted Management" + + The `nesi-add-kernel` tool automates most of the steps needed to register a + kernel. **This is the recommended way to register a Jupyter kernel.** + + The exact arguments depend on whether you are basing the kernel on an + environment module, a Python virtual environment, or a Conda environment: + + === "Environment module" + + First you need to open a terminal. It can be from a session on Jupyter + via OnDemand or from a regular ssh connection on the Mahuika login node. + + - If you use the ssh option, make sure to load the JupyterLab module to + have access to the `nesi-add-kernel` tool: + + ``` sh + module purge # remove all previously loaded modules + module load JupyterLab + ``` + + Use the `nesi-add-kernel` to register a kernel: + + ``` sh + nesi-add-kernel + ``` + + Where: + + - ``: The name you want to give the kernel. + - ``: The environment module to base the kernel on. + + Here is an example for adding a TensorFlow module to JupyterLab as a kernel: + + ``` sh + nesi-add-kernel tf_kernel TensorFlow/2.8.2-gimkl-2022a-Python-3.10.5 + ``` + + === "Python virtual environment" + + First, create your [python virtual environment](../../../../Software/Available_Applications/Python.md#installing-packages-in-your-home): + + ``` sh + module purge + module load Python/3.14.4-foss-2026 # Change the module to the version of python you want to use + python3 -m venv ./my-venv + pip install --upgrade pip + # you can pip install other packages here too + ``` + + Then create a kernel based on your virtual environment: + + ``` sh + module purge + module load JupyterLab + # The module of python you give here must be the same as the version of python you use to make the virtual environment + nesi-add-kernel --venv my-venv + ``` + + Where `` is the name you want to give to the kernel. + + === "Conda environment" + + First, create your [conda environment](../../../../Software/Available_Applications/Miniforge3.md#module-loading-and-conda-environments-isolation). You will need to begin by loading conda: + + ``` sh + # Load conda + module purge && module load Miniforge3 + source $(conda info --base)/etc/profile.d/conda.sh + export PYTHONNOUSERSITE=1 + ``` + + Then create a kernel based on your newly created conda environment: + + ``` sh + # Load JupyterLab + module load JupyterLab + + # Create your conda environment + conda create --prefix /my_conda_env python=3.11 + + # Add your conda environment as a kernel to JupyterHub + nesi-add-kernel -p + ``` + + Where `` is the name for your kernel. Alternatively, you can + create the environment by name: + + ``` sh + # Load JupyterLab + module load JupyterLab + + # Create your conda environment + conda create -n + + # Add your conda environment as a kernel to JupyterHub + nesi-add-kernel -n + ``` + + Where `` is the name for your kernel. + + === "Python environment through Container" + + You can also use the `nesi-add-kernel` tool to base a kernel on a + container. See the **Tool-Assisted Management → Python kernel** tab on the + [Containers as kernels in JupyterLab](./containers_as_kernels_in_JupyterLab.md) + page for the full instructions. + + !!! tip + + For more information about `nesi-add-kernel`, type into the terminal: + + ``` sh + nesi-add-kernel --help + ``` + +=== "Manual Management" + + If you need more control than the `nesi-add-kernel` tool provides, you can + set up a custom kernel by hand. + + You can configure custom kernels for running your Jupyter + notebooks. This could be necessary and/or recommended in some + situations, including: + + - If you wish to load a different combination of environment modules + than those we load in our default kernels + - If you would like to activate a virtual environment or conda + environment before launching the kernel + + The following examples create a custom kernel based on a conda environment, + a Python virtual environment, or an R environment module: + + === "Conda environment" + + First, change directory into the path where you would like to place your + conda environment. + + - If you would like to share it with other members of your project, use + your project folder (`cd /nesi/project/`) + - Avoid paths that include `00_nesi_projects` or `home`, as these cause + issues. + + Second, in a terminal run the following commands to load a + [Miniforge environment module](../../../../Software/Available_Applications/Miniforge3.md#module-loading-and-conda-environments-isolation): + + ``` sh + module purge && module load Miniforge3 + source $(conda info --base)/etc/profile.d/conda.sh + export PYTHONNOUSERSITE=1 + ``` + + Now create a conda environment named `my-conda-env` using Python 3.11. + The *ipykernel* Python package is required but you can change the names + of the environment, version of Python and install other Python packages + as required. + + ``` sh + conda create --prefix ./my-conda-env python=3.11 + conda activate ./my-conda-env + conda install ipykernel + # you can pip/conda install other packages here too + ``` + + Third, we will create a wrapper for your conda environment. + Change directory into your `my-conda-env` folder: + + ``` sh + cd my-conda-env + ``` + + And add the following as `wrapper.sh` into your `my-conda-env` folder + (replace `` with the absolute path to the + environment you created): + + ``` sh + #!/usr/bin/env bash + + # load required modules here + module purge + module load Miniforge3 + + # activate conda environment + source $(conda info --base)/etc/profile.d/conda.sh + conda deactivate # workaround for https://github.com/conda/conda/issues/9392 + conda activate /my-conda-env + + # run the kernel + exec python $@ + ``` + + Make the wrapper script executable: + + ``` sh + chmod +x wrapper.sh + ``` + + Fourth, create a directory for your kernel: + + ``` sh + mkdir -p ~/.local/share/jupyter/kernels/my-conda-env + cd ~/.local/share/jupyter/kernels/my-conda-env + ``` + + and create a file called *kernel.json*. It points the first element of + the argv list at the wrapper script we just created. The file should look + like this: + + ```json + { + "argv": [ + "/wrapper.sh", + "-m", + "ipykernel_launcher", + "-f", + "{connection_file}" + ], + "display_name": "My Conda Env", + "language": "python" + } + ``` + + - Change `display_name` to what you would like to call your kernel by. + + After refreshing JupyterLab your new kernel should show up in the + Launcher as "My Conda Env". + + === "Python virtual environment" + + First, change directory into the path where you would like to place your + virtual environment. + + - If you would like to share it with other members of your project, use + your project folder (`cd /nesi/project/`) + - avoid paths that include `00_nesi_projects` or `home`, as these cause + issues. + + Second, in a terminal run the following commands to load a Python + environment module: + + ``` sh + module purge + module load Python/3.14.4-foss-2026 + ``` + + Now create a Python virtual environment named `my-venv`. + The *ipykernel* Python package is required but you can change the name + of the environment and install other Python packages as required. + + ``` sh + python3 -m venv ./my-venv + source ./my-venv/bin/activate + pip install --upgrade pip + pip install ipykernel + # you can pip install other packages here too + ``` + + Third, we will create a wrapper for your virtual environment. + Change directory into your `my-venv` folder: + + ``` sh + cd my-venv + ``` + + And add the following as `wrapper.sh` into your `my-venv` folder: + + ``` sh + #!/usr/bin/env bash + + # load required modules here + module purge + module load Python/3.14.4-foss-2026 + + # activate virtual environment + source /my-venv/bin/activate + + # run the kernel + exec python $@ + ``` + + Make the wrapper script executable: + + ``` sh + chmod +x wrapper.sh + ``` + + Fourth, create a directory for your kernel: + + ``` sh + mkdir -p ~/.local/share/jupyter/kernels/my-venv + cd ~/.local/share/jupyter/kernels/my-venv + ``` + + and create a file called *kernel.json*. It points the first element of + the argv list at the wrapper script we just created. The file should look + like this: + + ```json + { + "argv": [ + "/wrapper.sh", + "-m", + "ipykernel_launcher", + "-f", + "{connection_file}" + ], + "display_name": "My Venv", + "language": "python" + } + ``` + + - Change `display_name` to what you would like to call your kernel by. + + After refreshing JupyterLab your new kernel should show up in the + Launcher as "My Venv". + + === "R kernel" + + You can configure custom R kernels for running your Jupyter notebooks. + The following example will create a custom kernel based on the + R/3.6.2-gimkl-2020a environment module and will additionally load an + MPFR environment module (e.g. if you wanted to load the Rmpfr package). + + In a terminal run the following commands to load the required + environment modules: + + ``` sh + module purge + module load IRkernel/1.1.1-gimkl-2020a-R-3.6.2 + module load Python/3.8.2-gimkl-2020a + ``` + + The IRkernel module loads the R module as a dependency and provides the + R kernel for Jupyter. Python is required to install the kernel (since + Jupyter is written in Python). + + Now create an R Jupyter kernel: + + ``` sh + R -e "IRkernel::installspec(name='myrwithmpfr', displayname = 'R with MPFR', user = TRUE)" + ``` + + We must now edit the kernel to load the required environment + modules when the kernel is launched. Change to the directory the + kernelspec was installed to + (~/.local/share/jupyter/kernels/myrwithmpfr, assuming you kept `--name + myrwithmpfr` in the above command): + + ``` sh + cd ~/.local/share/jupyter/kernels/myrwithmpfr + ``` + + Now create a wrapper script in that directory, called *wrapper.sh*, with + the following contents: + + ``` sh + #!/usr/bin/env bash + + # load required modules here + module purge + module load MPFR/4.0.2-GCCcore-9.2.0 + module load IRkernel/1.1.1-gimkl-2020a-R-3.6.2 + + # run the kernel + exec R $@ + ``` + + Make the wrapper script executable: + + ``` sh + chmod +x wrapper.sh + ``` + + and edit the *kernel.json* to change the first element of the argv list + to point to the wrapper script we just created. The file should look + like this: + + ```json + { + "argv": [ + "/home//.local/share/jupyter/kernels/myrwithmpfr/wrapper.sh", + "--slave", + "-e", + "IRkernel::main()", + "--args", + "{connection_file}" + ], + "display_name": "R with MPFR", + "language": "R" + } + ``` + + - Change `display_name` to what you would like to call your kernel by. + + After refreshing JupyterLab your new R kernel should show up in the + Launcher as "R with MPFR". + + === "Python environment through Container" + + You can also set up a kernel by hand that uses a container's version of + Python. See the **Manual Management → Python kernel** tab on the + [Containers as kernels in JupyterLab](./containers_as_kernels_in_JupyterLab.md) + page for the full instructions. + +## Listing your kernels + +To list all the kernels that are currently installed, run: + +``` sh +module purge +module load JupyterLab +jupyter-kernelspec list +``` + +This works for any kernel, regardless of whether it was registered using the +Tool-Assisted Management or Manual Management approach. + +## Sharing a kernel + +You can also configure a shared kernel that others with access to the same +project will be able to load. How you do this depends on whether you registered +the kernel with the tool-assisted or manual approach: + +=== "Tool-Assisted Management" + + To share a kernel, register it with `nesi-add-kernel` as you normally would, + but add the `--shared` flag so other members of your project can load it. + Select the tab for the kind of kernel you are sharing: + + === "Environment module" + + First you need to open a terminal. It can be from a session on Jupyter + via OnDemand or from a regular ssh connection on the Mahuika login node. + + - If you use the ssh option, make sure to load the JupyterLab module to + have access to the `nesi-add-kernel` tool: + + ``` sh + module purge # remove all previously loaded modules + module load JupyterLab + ``` + + Use the `nesi-add-kernel` command with the `--shared` flag to register a + shared kernel: + + ``` sh + nesi-add-kernel --shared + ``` + + Where: + + - ``: The name you want to give the kernel. + - ``: The environment module to base the kernel on. + + Here is an example for adding a shared TensorFlow module to JupyterLab as + a kernel: + + ``` sh + nesi-add-kernel --shared tf_kernel_shared TensorFlow/2.8.2-gimkl-2022a-Python-3.10.5 + ``` + + === "Python virtual environment" + + First, create your [python virtual environment](../../../../Software/Available_Applications/Python.md#installing-packages-in-your-home): + + ``` sh + module purge + module load Python/3.14.4-foss-2026 # Change the module to the version of python you want to use + python3 -m venv ./my-venv + pip install --upgrade pip + # you can pip install other packages here too + ``` + + Then create a shared kernel based on your virtual environment: + + ``` sh + module purge + module load JupyterLab + # The module of python you give here must be the same as the version of python you use to make the virtual environment + nesi-add-kernel --shared --venv my-venv + ``` + + Where `` is the name you want to give to the kernel. Note + the `--shared` flag in the `nesi-add-kernel` command line. + + === "Conda environment" + + First, create your [conda environment](../../../../Software/Available_Applications/Miniforge3.md#module-loading-and-conda-environments-isolation). You will need to begin by loading conda: + + ``` sh + # Load conda + module purge && module load Miniforge3 + source $(conda info --base)/etc/profile.d/conda.sh + export PYTHONNOUSERSITE=1 + ``` + + Then create a shared kernel based on your newly created conda environment: + + ``` sh + # Load JupyterLab + module load JupyterLab + + # Create your conda environment + conda create --prefix /my_conda_env python=3.11 + + # Add your conda environment as a shared kernel to JupyterHub + nesi-add-kernel --shared -p + ``` + + Where `` is the name you want to give to the kernel. Note + the `--shared` flag in the `nesi-add-kernel` command line. Alternatively, + you can create the environment by name: + + ``` sh + # Load JupyterLab + module load JupyterLab + + # Create your conda environment + conda create -n + + # Add your conda environment as a shared kernel to JupyterHub + nesi-add-kernel --shared -n + ``` + + Where `` is the name you want to give to the kernel. Note + the `--shared` flag in the `nesi-add-kernel` command line. + +=== "Manual Management" + + For a manually-created kernel, you must make sure it also exists in a shared + location (other users cannot see your home directory). + + First, **you** need to create the kernel yourself, following the manual steps + in the **Manual Management** tab earlier on this page. + + Next, **your team members** need to set up the kernel on their side. The + exact steps depend on the type of environment you created, so follow the + steps in the tab that matches it: + + === "Conda environment" + + Second, **your team members** need to run the following commands in the + terminal: + + ``` sh + # change directory into the path that contains your conda environment + cd + + # load Miniforge3 + module purge + module load Miniforge3 + + # Activate your shared conda environment + source $(conda info --base)/etc/profile.d/conda.sh + conda activate ./my-conda-env + ``` + + Third, get **your team members** to create a directory for the kernel in + their home directories: + + ``` sh + mkdir -p ~/.local/share/jupyter/kernels/my-conda-env + cd ~/.local/share/jupyter/kernels/my-conda-env + ``` + + and create a file called *kernel.json*. It points the first element of + the argv list at the wrapper script we just created. The file should look + like this: + + ```json + { + "argv": [ + "/wrapper.sh", + "-m", + "ipykernel_launcher", + "-f", + "{connection_file}" + ], + "display_name": "My Conda Env", + "language": "python" + } + ``` + + - Change `display_name` to what you would like to call your kernel by. + + After refreshing JupyterLab your new kernel should show up in the + Launcher as "My Conda Env". + + === "Python virtual environment" + + Second, **your team members** need to run the following commands in the + terminal: + + ``` sh + # load the Python environment module + module purge + module load Python/3.14.4-foss-2026 + + # Activate the shared virtual environment + source /my-venv/bin/activate + ``` + + Third, get **your team members** to create a directory for the kernel in + their home directories: + + ``` sh + mkdir -p ~/.local/share/jupyter/kernels/my-venv + cd ~/.local/share/jupyter/kernels/my-venv + ``` + + and create a file called *kernel.json*. It points the first element of + the argv list at the wrapper script we just created. The file should look + like this: + + ```json + { + "argv": [ + "/wrapper.sh", + "-m", + "ipykernel_launcher", + "-f", + "{connection_file}" + ], + "display_name": "My Venv", + "language": "python" + } + ``` + + - Change `display_name` to what you would like to call your kernel by. + + After refreshing JupyterLab your new kernel should show up in the + Launcher as "My Venv". + +## Removing a kernel + +To delete a specific kernel, run: + +``` sh +module purge +module load JupyterLab +jupyter-kernelspec list +jupyter-kernelspec remove +``` + +where `` is the name of the kernel to delete, as shown by +`jupyter-kernelspec list`. diff --git a/docs/Software/Available_Applications/Lambda_Stack.md b/docs/Software/Available_Applications/Lambda_Stack.md index 65db375bc..5d87bed85 100644 --- a/docs/Software/Available_Applications/Lambda_Stack.md +++ b/docs/Software/Available_Applications/Lambda_Stack.md @@ -70,7 +70,7 @@ ${CONTAINER} echo "Hello World" The following steps will create a custom Lambda Stack kernel that can be accessed via Mahuika's Jupyter service (based on the instructions at -[Jupyter_on_Mahuika](../../Interactive_Computing/OnDemand/Apps/JupyterLab/Jupyter_kernels_Tool_assisted_management.md)). +[Jupyter_on_Mahuika](../../Interactive_Computing/OnDemand/Apps/JupyterLab/python_and_r_kernels_in_JupyterLab.md)). First, we need to create a kernel definition and wrapper that will launch the container image. Run the following commands on the Mahuika diff --git a/docs/assets/images/OOD_jupyter_form_containers.png b/docs/assets/images/OOD_jupyter_form_containers.png new file mode 100644 index 000000000..8530ddb9b Binary files /dev/null and b/docs/assets/images/OOD_jupyter_form_containers.png differ diff --git a/docs/assets/stylesheets/theme.css b/docs/assets/stylesheets/theme.css index c79866038..8f701c94a 100644 --- a/docs/assets/stylesheets/theme.css +++ b/docs/assets/stylesheets/theme.css @@ -431,3 +431,10 @@ div.quiz-feedback { text-wrap-mode: wrap; font-size: medium; } + +/* Centre images marked with {.center} */ +img.center { + display: block; + margin-left: auto; + margin-right: auto; +} diff --git a/docs/redirect_map.yml b/docs/redirect_map.yml index e9c845e1b..c121e5485 100644 --- a/docs/redirect_map.yml +++ b/docs/redirect_map.yml @@ -80,8 +80,11 @@ Scientific_Computing/Interactive_computing_with_OnDemand/Apps/RStudio.md : Inter Scientific_Computing/Interactive_computing_with_OnDemand/Apps/virtual_desktop.md : Interactive_Computing/OnDemand/Apps/virtual_desktop.md Scientific_Computing/Interactive_computing_with_OnDemand/Apps/VSCode.md : Interactive_Computing/OnDemand/Apps/VSCode.md Scientific_Computing/Interactive_computing_with_OnDemand/Apps/JupyterLab/index.md : Interactive_Computing/OnDemand/Apps/JupyterLab/index.md -Scientific_Computing/Interactive_computing_with_OnDemand/Apps/JupyterLab/Jupyter_kernels_Manual_management.md : Interactive_Computing/OnDemand/Apps/JupyterLab/Jupyter_kernels_Manual_management.md -Scientific_Computing/Interactive_computing_with_OnDemand/Apps/JupyterLab/Jupyter_kernels_Tool_assisted_management.md : Interactive_Computing/OnDemand/Apps/JupyterLab/Jupyter_kernels_Tool_assisted_management.md +Scientific_Computing/Interactive_computing_with_OnDemand/Apps/JupyterLab/Jupyter_kernels_Manual_management.md : Interactive_Computing/OnDemand/Apps/JupyterLab/python_and_r_kernels_in_JupyterLab.md +Scientific_Computing/Interactive_computing_with_OnDemand/Apps/JupyterLab/Jupyter_kernels_Tool_assisted_management.md : Interactive_Computing/OnDemand/Apps/JupyterLab/python_and_r_kernels_in_JupyterLab.md +Interactive_Computing/OnDemand/Apps/JupyterLab/Jupyter_kernels_Manual_management.md : Interactive_Computing/OnDemand/Apps/JupyterLab/python_and_r_kernels_in_JupyterLab.md +Interactive_Computing/OnDemand/Apps/JupyterLab/Jupyter_kernels_Tool_assisted_management.md : Interactive_Computing/OnDemand/Apps/JupyterLab/python_and_r_kernels_in_JupyterLab.md +Interactive_Computing/OnDemand/Apps/JupyterLab/Jupyter_kernels.md : Interactive_Computing/OnDemand/Apps/JupyterLab/python_and_r_kernels_in_JupyterLab.md Scientific_Computing/Interactive_computing_with_OnDemand/Release_Notes/index.md : Interactive_Computing/OnDemand/Release_Notes/index.md General/Announcements/Accessing_NeSI_Support_during_the_Easter_break.md : Announcements/Accessing_NeSI_Support_during_the_Easter_break.md General/Announcements/Autodeletion_of_Scratch_Filesystem.md : Announcements/Autodeletion_of_Scratch_Filesystem.md