diff --git a/advanced_topics/connect_vscode_to_geolab.md b/advanced_topics/connect_vscode_to_geolab.md deleted file mode 100644 index 2fe0f98..0000000 --- a/advanced_topics/connect_vscode_to_geolab.md +++ /dev/null @@ -1,165 +0,0 @@ -# Connecting VS Code to a GeoLab Jupyter Instance - -This guide covers both sides of the connection: getting a usable server URL -from inside GeoLab (the **Jupyter side**), and attaching your local VS Code to -that server (the **VS Code side**). - -GeoLab runs on a 2i2c-managed JupyterHub on Kubernetes. Each user gets a pod -with its own single-user Jupyter server behind the Hub proxy. VS Code connects -to that per-user server URL over HTTPS — there is no SSH into the pod, and no -special "proxy" extension is needed. - ---- - -## Prerequisites - -On your laptop: - -- **VS Code** -- **Jupyter extension** (`ms-toolsai.jupyter`) -- **Python extension** (`ms-python.python`) — installed automatically as a dependency of the Jupyter extension - -In GeoLab: - -- A **running server**. Log in at `https://geolab.earthscope.cloud` and start - your server so the pod is alive before you try to connect. If the pod is - culled or stopped, the URL and token become invalid. - ---- - -## Jupyter side: get a connectable URL - -The `url` field reported by Jupyter points at `0.0.0.0:8888`, which is the -pod-internal address and is not reachable from your laptop. You need to rebuild -the URL against the public Hub host and append the server token. - -Open a notebook in your running GeoLab server and run this in a cell: - -```python -from jupyter_server.serverapp import list_running_servers - -data = list(list_running_servers()) - -def to_vscode_url(server_info, hub_host="https://geolab.earthscope.cloud"): - """Convert jupyter_server list output into a VS Code-connectable URL. - - Replaces the internal 0.0.0.0:8888 URL with the public Hub host, - keeping the (already URL-encoded) user path and appending the token. - """ - s = server_info[0] if isinstance(server_info, list) else server_info - base_url = s["base_url"].rstrip("/") - token = s["token"] - return f"{hub_host.rstrip('/')}{base_url}/?token={token}" - -print(to_vscode_url(data)) -``` - -This prints a line like: - -``` -https://geolab.earthscope.cloud/user/google-oauth2%7C112969120435953538875/?token=0f22dabff13f4ad48a45fe1ebebcc105 -``` - -Copy that entire line — you will paste it into VS Code in the next section. - -![Get GeoLab instance URL](../img/geolab_url.png) - -### Notes on the URL - -- The `%7C` in the path is an already-encoded `|` (pipe) from your OAuth2 user - ID. Leave it as-is. Do not re-encode it, or it becomes `%257C` and the path - breaks. -- The token identifies your session. Treat it like a password and do not commit - it or share it. -- If the token comes back empty or VS Code later rejects it, request a Hub API - token instead: go to `https://geolab.earthscope.cloud/hub/token`, click - **Request new API token**, and substitute that value for the `token` in the - URL. - ---- - -## VS Code side: connect to the server - -1. Install the **Jupyter** extension (`ms-toolsai.jupyter`) from the Extensions - view if you have not already. - -![Installing ms-toolsai](../img/add_ms-toolsai_extension.png) - -2. Open or create a notebook file (`.ipynb`) in VS Code. - -3. Click the **kernel picker** in the top-right of the notebook (it may read - "Select Kernel"). - -![Select Kernel](../img/select_kernel_vscode.png) - -4. Choose **Select Another Kernel...** - -![Select anther kernel](../img/select_another_kernel.png) - -5. Choose **Existing Jupyter Server...** - -![Exisiting Jupyter Server](../img/existing_jupyter_server.png) - -6. Choose **Enter the URL of a running Jupyter server**. - -![Enter URL](../img/enter_url_jupyter_server.png) - -7. Paste the full tokenized URL you copied from GeoLab, including the - `?token=...` part, then press Enter. - -8. When prompted, accept or edit the display name for the server. - -![Accept display name](../img/jupyter_server_display_name.png) - -9. Back in the kernel picker, select the kernel exposed by the remote server - (for example, the Python 3 kernel from your GeoLab environment). - -![Select kernel](../img/select_jupyter_kernel.png) - -10. Run a cell to confirm. Execution now happens inside your GeoLab pod, using - the GeoLab environment and compute — not your laptop. - ---- - -## Verifying you are on the remote kernel - -Run this in a cell. It should report the pod's paths and hostname, not your -laptop's: - -```python -import sys, socket, os -print("hostname:", socket.gethostname()) -print("python: ", sys.executable) -print("cwd: ", os.getcwd()) -``` - -On GeoLab you should see something like a `jupyter-...` hostname, a Python -executable under `/srv/conda/` or similar, and a working directory of -`/home/jovyan`. - ---- - -## Troubleshooting - -**"Cannot connect" or the connection times out.** -The most common cause is that your server is not running. Open the URL in a -browser first to spin up / confirm the pod, then retry in VS Code. - -**Token rejected.** -The single-user server token is sometimes empty or not accepted through the Hub -proxy. Use a Hub API token from `https://geolab.earthscope.cloud/hub/token` -instead, and rebuild the URL with it. - -**Path looks wrong (404).** -Confirm the `/user//` segment matches exactly what appears in your browser's -address bar while you are in JupyterLab. Do not manually decode the `%7C`. - -**Connection worked earlier, now fails.** -Hub servers get culled after inactivity. When the pod restarts, the URL and/or -token change. Re-run the snippet on the Jupyter side to get a fresh URL. - -**Looking for a "jupyter-server-proxy" VS Code extension.** -There isn't one, and you do not need it. `jupyter-server-proxy` is a -server-side package for proxying other web apps (like the Dask dashboard) -through the Hub; it plays no role in the VS Code connection. The Jupyter -extension talks to the server URL directly. diff --git a/advanced_topics/environments/binder_for_images.md b/advanced_topics/environments/binder_for_images.md new file mode 100644 index 0000000..0a63bcc --- /dev/null +++ b/advanced_topics/environments/binder_for_images.md @@ -0,0 +1,182 @@ +# GeoLab Binder + +There are two ways to launch a custom environment in GeoLab. The first is to [Build a custom image](custom_image_page.md) and push it to a registry, and specify the image URL when launching GeoLab. The second, called **GeoLab Binder**, is to point GeoLab at a GitHub repository and let it build the environment for you. This guide covers how the second approach works and when to use it. + +--- + +## What Is GeoLab Binder? + +GeoLab Binder lets you launch a session from a GitHub repository instead of a prebuilt image. You put configuration files in your repo that describe what packages you need, and GeoLab builds the environment automatically when you start a session. + +Behind the scenes, GeoLab reads the Dockerfile and configuration files in your repository and builds the container image for you. You write the Dockerfile (using the same template as a custom image), but you never run Docker locally or push to a registry, as GeoLab handles the build. + +Both approaches run inside GeoLab, so you have the same access to EarthScope data services either way. + +1. GitHub repo with config files +2. GeoLab builds image +3. Session launches in GeoLab + +--- + +## GeoLab Binder vs. Custom Image + +Both approaches use GeoLab's environment selector, but they use different options. The difference is what you select and what you paste. + +| | **GeoLab Binder** | **Custom Image** | +| --- | --- | --- | +| Menu option | **Build your own image** | **Other** | +| What you paste | A GitHub repo URL | A container registry URL (`ghcr.io/...`) | +| Who builds the image | GeoLab, automatically from your repo | You, locally with Docker | +| What you need | Dockerfile + config files in a GitHub repo | Docker Desktop, local build, registry push | +| EarthScope data access | Yes | Yes | +| How updates work | Push a commit, and the next launch picks up the changes | Rebuild and push a new image tag | +| Best for | Getting started quickly, iterating, sharing a repo | Stable, versioned environments; full Docker control | + +**Use GeoLab Binder when** you want to share a GitHub repository as a runnable environment without running Docker locally or managing a container registry. + +**Use a custom image when** you need a fixed, versioned environment that won't change between sessions, or when you need more control than config files allow. See [Building a Custom GeoLab Image](./building_custom_images.md). + +--- + +## Before You Start + +You need: + +- A **GitHub account** and a **GitHub repository** for your project. +- A GeoLab account at [GeoLab](https://geolab.earthscope.cloud). + +No local Docker builds or container registry required. + +--- + +## Step 1: Set Up Your GitHub Repository + +Create a new repository on GitHub (or use an existing one). Add your notebooks and at least one configuration file: + +```text +my-project/ +├── Dockerfile ← required (copy from the geolab-base template) +├── environment.yml ← your packages (conda) +├── requirements.txt ← PyPI-only packages (optional) +├── apt.txt ← system software (optional, rarely needed) +├── postBuild ← setup commands to run after install (optional) +└── my_notebook.ipynb ← your notebooks +``` + +Copy the `Dockerfile` from the `geolab-base` template at [EarthScope/GeoLab](https://github.com/EarthScope/GeoLab/tree/main/geolab-base) and leave it unchanged. All your customization goes in the other files. GeoLab Binder reads everything in the repo and builds the image when you launch. + +--- + +## Step 2: Write Your Configuration Files + +### `environment.yml`: Your Main Package List + +```yaml +name: my-binder-env +channels: + - conda-forge +dependencies: + - python=3.11 + - numpy + - matplotlib + - obspy +``` + +### `requirements.txt`: PyPI-only Packages (If Needed) + +```text +some-pypi-package==1.2.3 +``` + +### `apt.txt`: System Software (If Needed) + +```text +build-essential +``` + +### `postBuild`: One-time Setup Commands (Optional) + +If you need to run something after packages install, such as downloading a data file or enabling a Jupyter extension, create a `postBuild` file: + +```bash +#!/bin/bash +set -e +jupyter labextension install my-extension +``` + +Before committing, mark it executable: + +```bash +chmod +x postBuild +git add postBuild +git commit -m "add postBuild script" +``` + +These files use the exact same format as the custom image template. If you've worked through [Building a Custom GeoLab Image](./building_custom_images.md), you can reuse them directly. + +Once your files are ready, commit and push them to GitHub: + +```bash +git add environment.yml requirements.txt apt.txt +git commit -m "add environment configuration" +git push +``` + +If this is a new repository, you may need to set the upstream branch on your first push: + +```bash +git push -u origin main +``` + +--- + +## Step 3: Launch from Your Repo in GeoLab + +1. Go to [earthscope.org/data/geolab](https://www.earthscope.org/data/geolab/) and click **Launch GeoLab**. +2. Enter your username and password, then click **Continue**. +3. In the environment selector, choose **Build your own image**. +4. In the **Repository** field, paste the git clone URL for your repository: + + ```text + https://github.com/your-github-username/my-project.git + ``` + +5. Click **Build Image**. GeoLab will build the environment from your repository. This can take several minutes the first time. +6. When you receive a notification that the build is complete, click **Start**. + +> **If the build fails:** Check the build log for error messages. Common causes are a misspelled package name, an unavailable package version, or a syntax error in `environment.yml`. Fix the file, push the commit, and try again. + +--- + +## Step 4: Share Your Environment + +To share your environment with someone else, give them the git clone URL for your repository. They follow the same steps: go to GeoLab, choose **Build your own image**, paste the URL, and launch. + +Because the environment is defined by files in the repo, anyone who uses the same URL gets the same packages. If you update `environment.yml` and push, the next person to launch picks up the new version automatically. + +--- + +## Updating Your Environment + +Edit your configuration files, commit, and push. The next GeoLab launch from that repo URL will rebuild with the updated packages. + +```bash +# edit environment.yml, then: +git add environment.yml +git commit -m "add pandas to environment" +git push +``` + +> **Note:** A new commit triggers a fresh build on the next launch. If you're changing packages frequently, expect slower first launches while GeoLab rebuilds the image. + +--- + +## Quick Reference + +| What you want to do | How | +| --- | --- | +| Define your packages | `environment.yml` (conda), `requirements.txt` (PyPI) | +| Launch from a repo | GeoLab → Start Server → Build your own image → paste git clone URL | +| Share your environment | Share the git clone URL (`https://github.com/username/repo.git`) | +| Update your environment | Edit config files, commit, and push | +| Use a fixed versioned environment instead | See [Building a Custom GeoLab Image](./building_custom_images.md) | \ No newline at end of file diff --git a/advanced_topics/environments/building_custom_images.md b/advanced_topics/environments/building_custom_images.md new file mode 100644 index 0000000..8a960d4 --- /dev/null +++ b/advanced_topics/environments/building_custom_images.md @@ -0,0 +1,333 @@ +# Building a Custom GeoLab Image + +A GeoLab image is a complete, prepackaged computing environment that runs in JupyterLab. It includes common geophysics Python and scientific packages bundled together. Starting a GeoLab session launches an image. This step-by-step guide walks through building an image with a customized environment. + +--- + +## How It Works + +Think of an **image** as a recipe with each Python package as an ingredient. An **image** is the meal created from the recipe. Finally, a **container** is the meal served on a plate. The recipe doesn't change and you can make the same meal over and over. GeoLab does the same thing: it takes your image and launches a fresh session from it every time. + +Install Python packages in an image by editing plaintext files that list the required software. A tool called `Docker` reads those files and builds the image. The image must be published in an image repository so GeoLab can access it. Here is the process: + +```text +Edit config files → Docker builds → Image → Push image to repository → GeoLab runs it +``` + +--- + +## Before Starting + +Two pieces of software must be installed on **your computer**: + +1. **Docker Desktop.** Download it at [docker.com](https://www.docker.com/products/docker-desktop/). Install it on your computer, open it, and leave it running in the background. +2. **Git client**, to download the GeoLab Dockerfile template. Use the operating system's package manager to install a git client. + +Verify Docker and git are installed and working by opening a terminal and running: + +```bash +docker --version +git --version +``` + +If they print a version number, they are installed and working. + +In addition to the required software, a **GitHub** account at [github.com](https://github.com), a Docker account, or an AWS account is needed for publishing the image and making it available for GeoLab. + +--- + +## Step 1: Get the Template + +EarthScope provides a starter template. Download it using git to set up a working folder: + +```bash +git clone --depth 1 https://github.com/EarthScope/GeoLab.git +cp -R GeoLab/geolab-base my-geolab-image +cd my-geolab-image +``` + +The `my-geolab-image` folder contains these files: + +```text +my-geolab-image/ +├── Dockerfile ← do not edit this +├── environment.yml ← add your conda packages here +├── requirements.txt ← add PyPI-only packages here +├── apt.txt ← add system software here (rarely needed) +├── start ← do not edit this +├── test_helpers.py ← Python module with testing functions for packages +└── test_notebook.ipynb ← interactive version of the smoke test +``` + +> **The only files to edit are `environment.yml`, `requirements.txt`, and `apt.txt`.** Everything else is set up for you. + +--- + +## Step 2: Add Your Packages + +### `environment.yml`: Your Main Package List + +Add conda Python packages from `conda-forge` here. Open the file and add packages under the `dependencies` section: + +```yaml +channels: + - conda-forge + - nodefaults +dependencies: + - python=3.12 + # --- Geophysics --- + - obspy + - pygmt + # --- Geospatial --- + - cartopy + - geopandas + # add your packages below: + - my-package-name +``` + +Conda packages are preferred, because conda checks that everything works together before installing and reduces the possibility of dependency conflicts among packages. + +### `requirements.txt`: Packages Only on PyPI + +Some packages aren't available through conda-forge and must be installed from PyPI. Add them here, one per line: + +```text +earthscope-sdk==1.4.1 +seisbench +``` + +### `apt.txt`: System Software (Rarely Needed) + +Most scientific packages go in `environment.yml`. Only use `apt.txt` for low-level system tools that can't be installed any other way: + +```text +build-essential +git +``` + +--- + +## Step 3: Build and Test Locally + +Before publishing, build the image on your computer and make sure everything works. + +**Build the image:** + +```bash +docker build -f Dockerfile --tag my-geolab-image:0.1.0 . +``` + +This reads the config files and assembles the image. It can take several minutes the first time. + +**Run it locally:** + +```bash +docker run --rm -p 8888:8888 my-geolab-image:0.1.0 +``` + +Look in the output for a line like: + +```text +http://127.0.0.1:8888/lab?token=... +``` + +Copy that URL into a browser and a JupyterLab session will open. + +**Optional: Test that your packages installed correctly:** + +In the JupyterLab session, test if a package was installed and functions as expected. A simple version check is often sufficient to determine if a package has been installed and is working. + +To test a package in a notebook environment, open a notebook and add this code to a cell: + +```python +import importlib +import shutil +import subprocess +import sys + +RESULTS = [] + + +def py(modname, alias=None, smoke=None): + """Import `modname` and optionally run `smoke(mod)` as a sanity check.""" + label = alias or modname + try: + mod = importlib.import_module(modname) + if smoke is not None: + smoke(mod) + version = getattr(mod, '__version__', '') + RESULTS.append((label, 'OK', str(version), '')) + except Exception as exc: + RESULTS.append((label, 'FAIL', '', f'{type(exc).__name__}: {exc}')) + + +def cli(cmd, version_flag='--version'): + """Verify `cmd` is on $PATH and responds to a version flag.""" + path = shutil.which(cmd) + if not path: + RESULTS.append((cmd, 'FAIL', '', 'not on $PATH')) + return + try: + r = subprocess.run([cmd, version_flag], + capture_output=True, text=True, timeout=10) + line = (r.stdout or r.stderr).strip().splitlines() + version = line[0] if line else 'on PATH' + RESULTS.append((cmd, 'OK', version[:80], '')) + except Exception as exc: + RESULTS.append((cmd, 'OK', 'on PATH', f'{type(exc).__name__}')) + + +print(f'Python {sys.version}') +print(f'sys.prefix: {sys.prefix}') +``` + +Open another cell and use either the `py` or `cli` function to test a package. For example: + +```python +py('earthscope_sdk', alias='earthscope-sdk') +cli('es') # earthscope-cli entry point +``` + +Open a new cell and add the following code to summarize the results of the test: + +```python +import pandas as pd +from IPython.display import display + +df = pd.DataFrame(RESULTS, + columns=['package', 'status', 'version', 'error']) + +passed = int((df['status'] == 'OK').sum()) +total = len(df) +failed = total - passed + +print(f'Results: {passed}/{total} OK, {failed} failed') +if failed: + print('\nFailures:') + for _, row in df[df['status'] == 'FAIL'].iterrows(): + print(f" {row['package']:35s} {row['error']}") + +df.style.map( + lambda v: ('color: red; font-weight: bold' if v == 'FAIL' + else 'color: green'), + subset=['status'] +) +``` + +Each package gets a pass or fail which is display in the **Summary** cell of the notebook. If something fails, it usually means a package name is misspelled or a version is unavailable, so go back to `environment.yml` or `requirements.txt` and fix it, then rebuild. + +--- + +## Step 4: Publish Your Image to Docker Hub + +Once the local test passes, rebuild the image for GeoLab's platform and push it to a container registry. + +**Rebuild for GeoLab's platform:** + +GeoLab uses linux/amd64 images. Depending on your computer operating system (Windows or macOS), you may have to rebuild the image for the linux/amd64 platform. In addition, the image must be published in an image repository that is accessible to GeoLab. + +If you created an account using Docker Desktop, pushing an image to Docker Hub (the Docker image repository) does not require additional authentication. `Tag` or name the image with your Docker username and the name of the image. + +```bash +docker build --no-cache -f Dockerfile \ + --platform linux/amd64 \ + --tag your-docker-username/my-geolab-image:0.1.0 . +``` + +> **Why `--platform linux/amd64`?** GeoLab runs on Linux. If you're on a Mac with Apple Silicon, your local machine uses a different architecture. This flag ensures the image works on GeoLab regardless of what you built it on. + +**Push the Image to Docker Hub:** + +```bash +docker push your-docker-username/my-geolab-image:0.1.0 +``` + +By default, images published to Docker Hub are public and available for use with GeoLab. + +### Publishing to GitHub or AWS Image Repositories + +Alternatives to Docker Hub include GitHub Container Registry (ghcr) or AWS Elastic Container Registry (ECR). Choosing an image repository depends on user requirements. GitHub features a tight integration with CI (Continuous Integration) through GitHub Actions that can trigger an image build and push to ghcr. This automates the process of building and pushing an image through a `pull request`. AWS ECR offers cloud-scale uploads and downloads to support multiple instances of GeoLab requested by hundreds of users or more. + +Both ghcr and ECR have more stringent authorization practices and controls over publicly available images. For a step-by-step walkthrough for pushing images to either repository, go to [Pushing Images to GitHub or AWS ECR](./pushing_to_ghcr_ecr.md) for detailed instructions. + +--- + +## Step 5: Launch It in GeoLab + +1. Go to [earthscope.org/data/geolab](https://www.earthscope.org/data/geolab/) and click **Launch GeoLab**. +2. Enter your username and password, then click **Continue**. +3. If a **Stop My Server** button appears, click it first. +4. Click **Start My Server**. +5. Under **Environment**, choose **Other**. +6. In the **Custom image** field, enter your image name, e.g. `ghcr.io/your-github-username/my-geolab-image:0.1.0`. +7. Click **Start**. + +GeoLab will pull your image and launch a session from it. The first launch takes a minute while it downloads; after that it's cached and starts quickly. + +--- + +## Making Changes Later + +Edit your config files, then rebuild and push with a new version number: + +```bash +docker build --no-cache -f Dockerfile \ + --platform linux/amd64 \ + --tag ghcr.io/your-github-username/my-geolab-image:0.1.1 . + +docker push ghcr.io/your-github-username/my-geolab-image:0.1.1 +``` + +> **Always use a new version number** (`0.1.1`, `0.1.2`, etc.) when you rebuild. If you reuse the same tag, GeoLab may load the old cached version instead of your new one. + +## Troubleshooting Package Installation + +In general, it's best practice to install packages using the conda package manager for the GeoLab image. Conda checks packages for dependencies which ensures that dependency conflicts are resolved in the environment. Conda has a search function to discover packages. + +Some packages are only available in PyPI and are installed with the pip package manager. Pip also has a search function to find packages in PyPI. + +> **Tip:** Keep mind that installation name and import name can be different (such as, scikit-learn vs sklearn). + +### Find If a Conda Package Is Available + +To find if a package is available through the conda package manager, you can use `conda search`: + +```bash +conda search -c conda-forge #PackageName(e.g., seisbench) +``` + +### Find If a Package Is Available On PyPI + +To find if a package is available through the pip package manager, you can use `the following command. + +```bash +python -m pip index versions #PackageName(e.g., seisbench) +``` + +--- + +## Quick Reference + +| What you want to do | Where to do it | +| --- | --- | +| Add a Python package | `environment.yml` under `dependencies` | +| Add a PyPI-only package | `requirements.txt` | +| Add a system tool | `apt.txt` | +| Build locally for testing | `docker build --tag my-geolab-image:0.1.0 .` | +| Run locally | `docker run --rm -p 8888:8888 my-geolab-image:0.1.0` | +| Test packages | Run the test cells in a notebook (see Step 3) | +| Build for GeoLab | `docker build --no-cache --platform linux/amd64 --tag ghcr.io/username/image:version .` | +| Publish | `docker push ghcr.io/username/my-geolab-image:0.1.0` | + +--- + +## Getting a Personal Access Token (for GHCR) + +Before you can push images to GHCR, you need a **Personal Access Token (PAT)** with package permissions: + +1. Go to **GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)**. +2. Click **Generate new token (classic)**. +3. Give it a name (e.g. `geolab-image`), set an expiration, and check the **`write:packages`** scope. +4. Click **Generate token** and copy it, as you won't be able to see it again. + +Save your token somewhere safe (a password manager works well). You'll use it to log in to the registry in Step 4. \ No newline at end of file diff --git a/advanced_topics/environments/creating_temporary_environments.md b/advanced_topics/environments/creating_temporary_environments.md new file mode 100644 index 0000000..e66c46f --- /dev/null +++ b/advanced_topics/environments/creating_temporary_environments.md @@ -0,0 +1,185 @@ +# Creating Your Own Python Environment in GeoLab + +Python notebooks use packages: collections of reusable code that perform tasks like processing data, making maps, or analyzing signals. A notebook may need packages that aren't available at run time. An **environment** is a way to keep all of those packages organized in one tidy, self-contained workspace. + +When you launch GeoLab, you are in environment with commonly used geophysical packages. This guide shows you how to create your own environment in GeoLab. + +--- + +## What Is a Package Manager? + +GeoLab uses a tool called **conda** to install and manage packages. Think of conda like an app store for Python packages: you tell it what you want, it figures out what else is needed to make it work, and installs everything together. + +> **Heads up:** GeoLab resets when you sign out, so any packages you installed during a session won't be there next time. The solution is to define your environment in a file (explained below) so you can recreate it anytime. + +--- + +## See What's Already Installed + +Open the **terminal** in GeoLab and try these commands to get your bearings. + +**See all available environments:** + +```bash +conda env list +``` + +The one with a `*` is the currently active environment: + +```text +# conda environments: +# +base * /srv/conda +notebook /srv/conda/envs/notebook +custom_environment /home/jovyan/.conda/envs/custom_environment +``` + +**See all packages in the current environment:** + +```bash +conda list +``` + +This prints a long list. Each row shows a package name, its version, and where it came from: + +```text +# Name Version Build Channel +cartopy 0.24.1 py312h78ddc71_0 conda-forge +numpy 2.2.4 py312h7e3fe57_0 conda-forge +obspy 1.4.1 py312h7b8d3f4_0 conda-forge +xarray 2025.3.0 pyhd8ed1ab_0 conda-forge +… +``` + +--- + +## Installing a Package Without Creating a New Environment + +If you just need to add one or several packages, you can install them directly from inside a notebook cell using the line magic `%` command. This installs into the notebook's active environment: + +```python +%conda install -c conda-forge pandas +``` + +Or, for packages only available on PyPI (a different package source): + +```python +%pip install earthscope-sdk +``` + +> **Warning:** Installing with `%conda` inside a notebook can use a lot of memory because it checks for dependency conflicts among packages and selects the correct packages fix conflicts. If your notebook becomes unresponsive or the kernel crashes, use the `environment.yml` approach instead, which is more reliable for larger installs. Installing packages with pip uses less memory but does not fix dependency conflicts. Try installing with conda first, use pip if the package is not available in the conda-forge repository. + +--- + +## Create Your Own Environment + +The best method to create a custom environment is to write a file that lists every package required. Conda reads the file and builds the environment from it. This ensures you can recreate the exact same environment later, and the file can be shared, making the environment reproducible. + +> **IMPORTANT**: This section describes building a new environment that does not include the packages in the default GeoLab environment. + +### Step 1: Write an `environment.yml` File + +Open an editor, create a new file called `environment.yml`, and add the following: + +```yml +name: my_environment +channels: + - conda-forge +dependencies: + - python=3.11 + - ipykernel + - numpy + - matplotlib + # Pip-specific packages + - pip: + - seisbench +``` + +Here's what each part means: + +- **name**: What to call the environment. +- **channels**: Where to download packages from (`conda-forge` is a large, reliable source). +- **dependencies**: The packages to be installed. +- `ipykernel` is required so the environment can be used as a notebook kernel, so always include it. +- `- pip:` installs packages only available in the PyPI repository, such as seisbench. The majority of pip packages will install without a dependency conflict. If a conflict exists when running your code, Python will provide an error message and suggest the versions of packages that do not conflict. You will have manually resolve the conflict by installing the suggested packages. + +Replace `numpy`, `matplotlib`, or `seisbench` with the required packages. + +### Step 2: Build the Environment + +In the **terminal**, run: + +```bash +conda env create -f environment.yml +``` + +Alternatively, if you want to permanently add packages to the default GeoLab environment, you can export `environment.yaml` and edit the file with packages you want to install. + +```bash +conda env export > environment.yml +``` + +Conda will figure out which versions of everything are compatible and download them. This can take a few minutes, which is normal. + +> **If it fails:** Read the error message. Conda usually names the package that's causing the problem. Try removing it from the file or changing its version. + +### Step 3: Activate the Environment + +```bash +conda activate my_environment +``` + +Activating an environment switches the terminal into that workspace, so any Python commands you run use that environment's packages. The terminal prompt will update to show the environment name, confirming it worked. + +### Step 4: Register It as a Notebook Kernel + +A new environment isn't automatically available in Jupyter notebooks. To use the newly created environment, it has to be registered. Run this command **in the terminal** to register it: + +```bash +python -m ipykernel install --user --name my_environment --display-name "Python (my_environment)" +``` + +### Step 5: Switch to Your Environment in a Notebook + +1. Open a notebook and go to **Kernel > Change Kernel…** + + ![Kernel menu showing the Change Kernel option](../../img/select_kernel.png) + +2. Select **Python (my_environment)**. + + ![Kernel selector dialog with custom environment listed](../../img/select_custom.png) + +3. Check the upper-right corner of the notebook to confirm the kernel changed. + + ![Notebook header showing the active custom environment kernel](../../img/custom_env.png) + +> **Note:** This must be done for each notebook separately. There isn't a way to set it as the default for all notebooks. + +--- + +## Quick Reference for Environments + +| What you want to do | Command | +| --- | --- | +| See all environments | `conda env list` | +| See installed packages | `conda list` | +| Activate an environment | `conda activate ` | +| Leave an environment | `conda deactivate` | +| Build from a file | `conda env create -f environment.yml` | +| Register as a kernel | `python -m ipykernel install --user --name --display-name "