diff --git a/workshop/README.md b/workshop/README.md
index 87eb52a4..01ecdff8 100644
--- a/workshop/README.md
+++ b/workshop/README.md
@@ -45,7 +45,12 @@ This workshop provides a complete learning path for IBM Geospatial Studio, desig
- Fine-tuning models
- Deploying and monitoring
-**Total Workshop Time**: 4.5 - 6 hours
+5. **Lab 5: Multimodal Flood Detection with TerraMind** (90-120 minutes)
+ - Working with multimodal satellite data (SAR + Optical)
+ - Training TerraMind foundation model
+ - Advanced multimodal inference workflows
+
+**Total Workshop Time**: 6 - 8 hours
## 🚀 Quick Start
diff --git a/workshop/docs/index.md b/workshop/docs/index.md
index d2b2fabe..ea8778cc 100644
--- a/workshop/docs/index.md
+++ b/workshop/docs/index.md
@@ -18,7 +18,7 @@ This workshop is designed for beginners who have never heard of Geospatial Studi
## ⏱️ Workshop Duration
-**Total Time:** Approximately 3-4 hours
+**Total Time:** Approximately 5-6 hours
- **Pre-work:** 1-1.5 hours (deployment and setup)
- **Introduction:** 15 minutes (reading)
@@ -26,6 +26,7 @@ This workshop is designed for beginners who have never heard of Geospatial Studi
- **Lab 2 - Onboarding Pre-computed Examples:** 20 minutes (Beginner)
- **Lab 3 - Upload Model Checkpoints and Run Inference:** 30 minutes (Intermediate)
- **Lab 4 - Training a Custom Model for Wildfire Burn Scar Detection:** 60-90 minutes (Intermediate, includes model training)
+- **Lab 5 - Training a Multimodal Model for Flood Detection:** 90-120 minutes (Advanced, includes multimodal training)
## 🎓 Target Audience
@@ -49,7 +50,7 @@ cd geospatial-studio/workshop/docs/notebooks
This repository includes:
-- ✅ All lab notebooks (Lab 1-4)
+- ✅ All lab notebooks (Lab 1-5)
- ✅ JSON configuration files (model templates, datasets, backbones)
- ✅ Sample data references
- ✅ Complete workshop documentation
@@ -109,6 +110,13 @@ Complete an end-to-end workflow: onboard a training dataset, fine-tune a foundat
**Note:** This lab requires GPU access for model training. If GPUs are not available, you can use an existing fine-tuned model or train outside Studio using TerraTorch.
+### Lab 5: Training a Multimodal Model for Flood Detection with TerraMind
+Advanced multimodal workflow combining Sentinel-1 SAR and Sentinel-2 optical data. Learn to work with TerraMind foundation model, configure multimodal datasets, and run inference with multiple sensor modalities for robust flood detection.
+
+**Time:** 90-120 minutes (includes multimodal training) | **Difficulty:** Advanced
+
+**Note:** This lab uses TerraMind Tiny which can run on CPU (2-4 hours) or GPU (60-90 minutes). Demonstrates real-world disaster response scenarios with complementary sensor data.
+
## 🚀 Getting Started
1. **Complete the Pre-work** - Deploy Geospatial Studio in your environment
diff --git a/workshop/docs/introduction/welcome.md b/workshop/docs/introduction/welcome.md
index 82752123..2921e7f4 100644
--- a/workshop/docs/introduction/welcome.md
+++ b/workshop/docs/introduction/welcome.md
@@ -55,6 +55,7 @@ graph LR
C --> D[Lab 2
Onboard Examples]
D --> E[Lab 3
Upload & Infer]
E --> F[Lab 4
Train Model]
+ F --> G[Lab 5
Multimodal AI]
style A fill:#0f62fe,stroke:#fff,color:#fff
style B fill:#8a3ffc,stroke:#fff,color:#fff
@@ -62,6 +63,7 @@ graph LR
style D fill:#42be65,stroke:#fff,color:#fff
style E fill:#ff7eb6,stroke:#fff,color:#fff
style F fill:#fa4d56,stroke:#fff,color:#fff
+ style G fill:#ee5396,stroke:#fff,color:#fff
```
## ⏱️ Time Breakdown
@@ -74,7 +76,8 @@ graph LR
| **Lab 2** | 20 minutes | Onboarding Pre-computed Examples (Beginner) |
| **Lab 3** | 30 minutes | Upload Model Checkpoints and Run Inference (Intermediate) |
| **Lab 4** | 60-90 minutes | Training a Custom Model for Wildfire Burn Scar Detection (Intermediate) |
-| **Total** | ~3-4 hours | Including breaks |
+| **Lab 5** | 90-120 minutes | Training a Multimodal Model for Flood Detection (Advanced) |
+| **Total** | ~5-6 hours | Including breaks |
## 🎓 Workshop Format
diff --git a/workshop/docs/notebooks/README.md b/workshop/docs/notebooks/README.md
index 27758a6f..50f1d785 100644
--- a/workshop/docs/notebooks/README.md
+++ b/workshop/docs/notebooks/README.md
@@ -65,6 +65,23 @@ Complete an end-to-end workflow:
---
+### Lab 5: Training a Multimodal Model for Flood Detection with TerraMind
+**File:** `lab5-flood-multimodal-workflow.ipynb`
+
+Advanced multimodal workflow:
+- Work with multimodal satellite data (Sentinel-1 SAR + Sentinel-2 optical)
+- Onboard and configure multimodal training datasets
+- Register and configure TerraMind foundation model
+- Submit and monitor multimodal fine-tuning
+- Run inference with multiple sensor modalities
+- Understand complementary sensor fusion for robust predictions
+
+**Estimated Time:** 90-120 minutes (includes multimodal training) | **Difficulty:** Advanced
+
+**Note:** Uses TerraMind Tiny which can run on CPU (2-4 hours) or GPU (60-90 minutes). Demonstrates real-world disaster response scenarios.
+
+---
+
## How to Use These Notebooks
### Prerequisites
@@ -93,7 +110,7 @@ jupyter notebook
**Why the full repository is required:**
-- ✅ Notebooks reference JSON configs from `populate-studio/payloads/`
+- ✅ Notebooks reference JSON configs from shared directories
- ✅ Proper directory structure for all file paths
- ✅ Easy to update with `git pull`
- ✅ Access to all workshop materials and shared resources
@@ -130,6 +147,7 @@ These notebooks are adapted from the official Geospatial Studio examples:
- **Lab 2:** Based on [`002-Add-Precomputed-Examples.ipynb`](https://github.com/terrastackai/geospatial-studio-toolkit/blob/main/examples/inference/002-Add-Precomputed-Examples.ipynb)
- **Lab 3:** Based on [`001-Introduction-to-Inferencing.ipynb`](https://github.com/terrastackai/geospatial-studio-toolkit/blob/main/examples/inference/001-Introduction-to-Inferencing.ipynb)
- **Lab 4:** Based on [`GeospatialStudio-Walkthrough-BurnScars.ipynb`](https://github.com/terrastackai/geospatial-studio-toolkit/blob/main/examples/e2e-walkthroughs/GeospatialStudio-Walkthrough-BurnScars.ipynb)
+- **Lab 5:** Based on [`GeospatialStudio-Walkthrough-Flooding.ipynb`](https://github.com/terrastackai/geospatial-studio-toolkit/blob/main/examples/e2e-walkthroughs/GeospatialStudio-Walkthrough-Flooding.ipynb)
---
diff --git a/workshop/docs/notebooks/lab5-flood-multimodal-workflow.ipynb b/workshop/docs/notebooks/lab5-flood-multimodal-workflow.ipynb
new file mode 100644
index 00000000..dece2954
--- /dev/null
+++ b/workshop/docs/notebooks/lab5-flood-multimodal-workflow.ipynb
@@ -0,0 +1,1054 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "ad8926e6-99fc-4043-8bc5-49e28170749e",
+ "metadata": {},
+ "source": [
+ "# Lab 5\n",
+ "\n",
+ "**Training a Multimodal Model for Flood Detection with TerraMind**\n",
+ "\n",
+ "⏱️ **Estimated Duration:** 90-120 minutes \n",
+ "📊 **Difficulty Level:** Advanced\n",
+ "\n",
+ "📥 **Getting the Lab Materials**\n",
+ "\n",
+ "**Getting the Lab Materials:** Clone the repository:\n",
+ "```bash\n",
+ "git clone https://github.com/terrastackai/geospatial-studio.git\n",
+ "cd geospatial-studio/workshop/docs/notebooks\n",
+ "jupyter notebook lab5-flood-multimodal-workflow.ipynb\n",
+ "```\n",
+ "\n",
+ "⚠️ **Note:** This lab requires multiple JSON configuration files. Cloning the repository ensures you have all necessary files.\n",
+ "\n",
+ "---\n",
+ "\n",
+ "## Overview\n",
+ "\n",
+ "In this advanced lab, you'll complete an **end-to-end multimodal machine learning workflow** for detecting floods from satellite imagery. This represents a real-world disaster response scenario where you need to:\n",
+ "\n",
+ "1. **Onboard multimodal training data** - Upload and configure a dataset with multiple sensor modalities\n",
+ "2. **Register a multimodal foundation model** - Set up TerraMind for fine-tuning\n",
+ "3. **Submit a fine-tuning job** - Train a custom model on your multimodal dataset\n",
+ "4. **Monitor training progress** - Track the training process\n",
+ "5. **Run inference** - Test your trained model on new data\n",
+ "6. **Visualize results** - View predictions in the UI\n",
+ "\n",
+ "## What You'll Learn\n",
+ "\n",
+ "- How to work with multimodal satellite data (Sentinel-1 SAR + Sentinel-2 optical)\n",
+ "- How to onboard and configure multimodal training datasets\n",
+ "- How to use TerraMind, a multimodal foundation model\n",
+ "- How to configure and submit multimodal fine-tuning jobs\n",
+ "- How to run inference with multimodal models\n",
+ "- Best practices for multimodal geospatial AI\n",
+ "\n",
+ "## Prerequisites\n",
+ "\n",
+ "### Required Resources\n",
+ "\n",
+ "- **GPU Access**: This lab requires GPU resources for model training\n",
+ "- **Training Data**: Sen1Floods11 multimodal dataset (automatically downloaded)\n",
+ "- **Completed Labs**: Labs 1-4 (for SDK familiarity and workflow understanding)\n",
+ "\n",
+ "### About the Dataset\n",
+ "\n",
+ "We'll use the **Sen1Floods11 dataset**, a multimodal flood detection dataset:\n",
+ "\n",
+ "**Sentinel-2 (Optical) Modality:**\n",
+ "- **13 spectral bands** including RGB, NIR, SWIR, and cloud mask\n",
+ "- **10-60m resolution** depending on band\n",
+ "- **Modality tag**: S2L2A\n",
+ "\n",
+ "**Sentinel-1 (SAR) Modality:**\n",
+ "- **2 polarization bands**: VV and VH\n",
+ "- **10m resolution**\n",
+ "- **Modality tag**: S1GRD\n",
+ "- **Weather-independent** - works through clouds\n",
+ "\n",
+ "**Labels:**\n",
+ "- **Binary classification**: Flood (1) vs No Flood (0)\n",
+ "- **Pixel-level segmentation**\n",
+ "\n",
+ "### Why Multimodal?\n",
+ "\n",
+ "Combining optical and SAR data provides complementary information:\n",
+ "- **Optical (Sentinel-2)**: Rich spectral information, but affected by clouds\n",
+ "- **SAR (Sentinel-1)**: Penetrates clouds, sensitive to water surfaces\n",
+ "- **Together**: More robust and accurate flood detection\n",
+ "\n",
+ "### 💻 CPU Training Support\n",
+ "\n",
+ "**This lab uses TerraMind Tiny for CPU compatibility:**\n",
+ "\n",
+ "- **TerraMind Tiny** is the smallest version and can run on CPU\n",
+ "- **Training time on CPU**: Approximately 2-4 hours (vs 60-90 minutes on GPU)\n",
+ "- **GPU recommended** but not required for this lab\n",
+ "- If you have a GPU available, training will be significantly faster\n",
+ "- For production workloads, consider using terramind_v1_base or terramind_v1_large with GPU\n",
+ "\n",
+ "---"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "setup-section",
+ "metadata": {},
+ "source": [
+ "## 1. Setup and Imports\n",
+ "\n",
+ "First, let's import the required libraries and set up our connection to Geospatial Studio."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "2a2322ba-9fb7-47d2-bf7f-eb7f142bcd7c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Import required packages\n",
+ "import json\n",
+ "import time\n",
+ "from IPython.display import display, Markdown\n",
+ "\n",
+ "import urllib3\n",
+ "urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)\n",
+ "\n",
+ "from geostudio import Client"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a1f8f898-61de-4a9c-a510-16ff93cf9a1a",
+ "metadata": {},
+ "source": [
+ "## 2. Connect to Geospatial Studio\n",
+ "\n",
+ "Use the same configuration file from Lab 1:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "4237a518-45d6-4dd8-ad05-6b391953b0e9",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Using api key and base urls from geostudio config file\n",
+ "Using api key and base urls from geostudio config file\n",
+ "Using api key and base urls from geostudio config file\n",
+ "✅ Connected to Geospatial Studio!\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Initialize the client\n",
+ "client = Client(geostudio_config_file=\".geostudio_config_file\")\n",
+ "\n",
+ "print(\"✅ Connected to Geospatial Studio!\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "workflow-overview",
+ "metadata": {},
+ "source": [
+ "## 3. Understanding the Multimodal Workflow\n",
+ "\n",
+ "Before we begin, let's understand the complete multimodal workflow:\n",
+ "\n",
+ "```mermaid\n",
+ "graph LR\n",
+ " A[Multimodal Foundation Model
TerraMind] --> D[Fine-tuning Job]\n",
+ " B[Multimodal Training Dataset
Sentinel-1 + Sentinel-2] --> D\n",
+ " C[TerraMind Task Template] --> D\n",
+ " D --> E[Trained Multimodal Model]\n",
+ " E --> F[Multimodal Inference]\n",
+ " F --> G[Flood Detection Results]\n",
+ " \n",
+ " style A fill:#1f77b4,stroke:#333,stroke-width:2px,color:#fff\n",
+ " style B fill:#1f77b4,stroke:#333,stroke-width:2px,color:#fff\n",
+ " style C fill:#1f77b4,stroke:#333,stroke-width:2px,color:#fff\n",
+ " style D fill:#ff7f0e,stroke:#333,stroke-width:2px,color:#fff\n",
+ " style E fill:#2ca02c,stroke:#333,stroke-width:2px,color:#fff\n",
+ " style F fill:#d62728,stroke:#333,stroke-width:2px,color:#fff\n",
+ " style G fill:#9467bd,stroke:#333,stroke-width:2px,color:#fff\n",
+ "```\n",
+ "\n",
+ "**Key Components:**\n",
+ "\n",
+ "1. **Multimodal Foundation Model (TerraMind)**: Pre-trained model that understands multiple sensor modalities\n",
+ "2. **Multimodal Training Dataset**: Labeled data with both Sentinel-1 SAR and Sentinel-2 optical imagery\n",
+ "3. **TerraMind Task Template**: Configuration for multimodal segmentation\n",
+ "4. **Fine-tuning Job**: Training process that customizes the model for flood detection\n",
+ "5. **Trained Model**: Your custom multimodal flood detection model\n",
+ "6. **Multimodal Inference**: Running predictions using both sensor types\n",
+ "\n",
+ "---"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "step1-backbone",
+ "metadata": {},
+ "source": [
+ "## 4. Step 1: Register the TerraMind Foundation Model\n",
+ "\n",
+ "First, we need to register the **TerraMind** multimodal foundation model as our base model.\n",
+ "\n",
+ "**About TerraMind:**\n",
+ "- **Multimodal architecture**: Designed to process multiple sensor types simultaneously\n",
+ "- **Pre-trained**: On diverse geospatial datasets with multiple modalities\n",
+ "- **Versions**: Available in tiny, base, and large sizes\n",
+ "- **Fusion strategy**: Learns optimal ways to combine information from different sensors\n",
+ "\n",
+ "For this lab, we'll use the **terramind_v1_tiny** model, which is the smallest version and can run on CPU, making it accessible for systems without GPU resources."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "onboard-backbone",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "📋 TerraMind Backbone Configuration:\n",
+ "{\n",
+ " \"name\": \"terramind_v1_tiny\",\n",
+ " \"description\": \"Terramind Multimodal tiny backbone base\",\n",
+ " \"checkpoint_filename\": \"terramind_v1_tiny/terramind_v1_tiny.pt\",\n",
+ " \"model_params\": {\n",
+ " \"backbone\": \"terramind_v1_tiny\",\n",
+ " \"model_category\": \"terramind\"\n",
+ " }\n",
+ "}\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Load the TerraMind tiny backbone configuration\n",
+ "with open(\"../../../populate-studio/payloads/backbones/backbone-terramind_tiny.json\", \"r\") as f:\n",
+ " backbone = json.load(f)\n",
+ "\n",
+ "print(\"📋 TerraMind Backbone Configuration:\")\n",
+ "print(json.dumps(backbone, indent=2))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "create-backbone",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "✅ TerraMind foundation model registered successfully!\n",
+ "{\n",
+ " \"id\": \"235d4756-4afc-487f-8cd5-5714f70f2d18\"\n",
+ "}\n",
+ "\n",
+ "📌 Base Model ID: 235d4756-4afc-487f-8cd5-5714f70f2d18\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Register the backbone model\n",
+ "onboard_backbone_response = client.create_base_model(backbone)\n",
+ "\n",
+ "print(\"\\n✅ TerraMind foundation model registered successfully!\")\n",
+ "print(json.dumps(onboard_backbone_response, indent=2))\n",
+ "\n",
+ "# Save the base model ID for later use\n",
+ "base_model_id = onboard_backbone_response['id']\n",
+ "print(f\"\\n📌 Base Model ID: {base_model_id}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "step2-dataset",
+ "metadata": {},
+ "source": [
+ "## 5. Step 2: Onboard the Multimodal Training Dataset\n",
+ "\n",
+ "Now we'll onboard the Sen1Floods11 multimodal dataset. This process:\n",
+ "\n",
+ "1. **Downloads** the dataset from a remote URL\n",
+ "2. **Validates** both modalities and their alignment\n",
+ "3. **Indexes** the multimodal dataset for training\n",
+ "4. **Stores** metadata in the Studio catalog\n",
+ "\n",
+ "**Dataset Configuration:**\n",
+ "\n",
+ "**Sentinel-2 (S2L2A) Modality:**\n",
+ "- **13 bands**: B01-B12 + Cloud mask (CLD)\n",
+ "- **File suffix**: `_S2Hand.tif`\n",
+ "- **RGB bands**: B02 (Blue), B03 (Green), B04 (Red)\n",
+ "\n",
+ "**Sentinel-1 (S1GRD) Modality:**\n",
+ "- **2 bands**: VV and VH polarizations\n",
+ "- **File suffix**: `_S1Hand.tif`\n",
+ "- **Aligned dates**: Temporal alignment with Sentinel-2\n",
+ "\n",
+ "**Labels:**\n",
+ "- **2 categories**: No Floods (0), Floods (1)\n",
+ "- **File suffix**: `_LabelHand.tif`\n",
+ "\n",
+ "⚠️ **Note**: This process may take several minutes depending on network speed and cluster resources."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "load-dataset-config",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "📋 Multimodal Dataset Configuration:\n",
+ "{\n",
+ " \"dataset_name\": \"Sentinel Flood Multimodal Test\",\n",
+ " \"data_sources\": [\n",
+ " {\n",
+ " \"bands\": [\n",
+ " {\n",
+ " \"index\": \"0\",\n",
+ " \"band_name\": \"B01\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"1\",\n",
+ " \"band_name\": \"B02\",\n",
+ " \"RGB_band\": \"B\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"2\",\n",
+ " \"band_name\": \"B03\",\n",
+ " \"RGB_band\": \"G\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"3\",\n",
+ " \"band_name\": \"B04\",\n",
+ " \"RGB_band\": \"R\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"4\",\n",
+ " \"band_name\": \"B05\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"5\",\n",
+ " \"band_name\": \"B06\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"6\",\n",
+ " \"band_name\": \"B07\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"7\",\n",
+ " \"band_name\": \"B08\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"8\",\n",
+ " \"band_name\": \"B8A\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"9\",\n",
+ " \"band_name\": \"B09\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"10\",\n",
+ " \"band_name\": \"B11\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"11\",\n",
+ " \"band_name\": \"B12\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"12\",\n",
+ " \"band_name\": \"CLD\",\n",
+ " \"description\": \"\",\n",
+ " \"scaling_factor\": \"1\"\n",
+ " }\n",
+ " ],\n",
+ " \"connector\": \"sentinelhub\",\n",
+ " \"collection\": \"s2_l2a\",\n",
+ " \"modality_tag\": \"S2L2A\",\n",
+ " \"file_suffix\": \"_S2Hand.tif\"\n",
+ " },\n",
+ " {\n",
+ " \"bands\": [\n",
+ " {\n",
+ " \"index\": \"0\",\n",
+ " \"band_name\": \"VV\",\n",
+ " \"description\": \"\"\n",
+ " },\n",
+ " {\n",
+ " \"index\": \"1\",\n",
+ " \"band_name\": \"VH\",\n",
+ " \"description\": \"\"\n",
+ " }\n",
+ " ],\n",
+ " \"connector\": \"sentinelhub\",\n",
+ " \"collection\": \"s1_grd\",\n",
+ " \"modality_tag\": \"S1GRD\",\n",
+ " \"align_dates\": \"true\",\n",
+ " \"file_suffix\": \"_S1Hand.tif\",\n",
+ " \"scaling_factor\": [\n",
+ " 1,\n",
+ " 1\n",
+ " ]\n",
+ " }\n",
+ " ],\n",
+ " \"label_categories\": [\n",
+ " {\n",
+ " \"id\": \"0\",\n",
+ " \"name\": \"No Floods\",\n",
+ " \"description\": \"Flooding assets\"\n",
+ " },\n",
+ " {\n",
+ " \"id\": \"1\",\n",
+ " \"name\": \"Floods\",\n",
+ " \"description\": \"Flooding assets\"\n",
+ " }\n",
+ " ],\n",
+ " \"dataset_url\": \"https://geospatial-studio-example-data.s3.us-east.cloud-object-storage.appdomain.cloud/sen1floods11_v1.1.4_zip.zip\",\n",
+ " \"description\": \"Flood data from places\",\n",
+ " \"label_suffix\": \"_LabelHand.tif\",\n",
+ " \"purpose\": \"Segmentation\"\n",
+ "}\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Load the multimodal dataset configuration\n",
+ "with open(\"../../../populate-studio/payloads/datasets/dataset-flooding_multimodal.json\", \"r\") as f:\n",
+ " flood_dataset = json.load(f)\n",
+ "\n",
+ "print(\"📋 Multimodal Dataset Configuration:\")\n",
+ "print(json.dumps(flood_dataset, indent=2))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "onboard-dataset",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "🚀 Starting multimodal dataset onboarding...\n",
+ "This may take several minutes to download and process both modalities.\n",
+ "\n",
+ "✅ Multimodal dataset onboarding initiated!\n",
+ "{\n",
+ " \"Dataset\": \"submitting - adding dataset and labels\",\n",
+ " \"dataset_id\": \"geodata-m6mjazvh82c5spfqzzvqwq\",\n",
+ " \"dataset_url\": \"https://geospatial-studio-example-data.s3.us-east.cloud-object-storage.appdomain.cloud/sen1floods11_v1.1.4_zip.zip\"\n",
+ "}\n",
+ "\n",
+ "📌 Dataset ID: geodata-m6mjazvh82c5spfqzzvqwq\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Onboard the multimodal dataset\n",
+ "print(\"🚀 Starting multimodal dataset onboarding...\")\n",
+ "print(\"This may take several minutes to download and process both modalities.\\n\")\n",
+ "\n",
+ "onboard_dataset_response = client.onboard_dataset(data=flood_dataset)\n",
+ "\n",
+ "print(\"✅ Multimodal dataset onboarding initiated!\")\n",
+ "print(json.dumps(onboard_dataset_response, indent=2))\n",
+ "\n",
+ "# Save the dataset ID for later use\n",
+ "dataset_id = onboard_dataset_response['dataset_id']\n",
+ "print(f\"\\n📌 Dataset ID: {dataset_id}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "monitor-dataset",
+ "metadata": {},
+ "source": [
+ "### Monitor Dataset Onboarding\n",
+ "\n",
+ "The onboarding process runs as a background job. We'll poll the status until completion.\n",
+ "\n",
+ "**What's happening:**\n",
+ "- Downloading multimodal dataset from remote storage\n",
+ "- Extracting and validating files for both modalities\n",
+ "- Checking temporal alignment between Sentinel-1 and Sentinel-2\n",
+ "- Creating dataset index\n",
+ "- Generating metadata\n",
+ "\n",
+ "**Expected statuses:**\n",
+ "- `PENDING`: Job queued\n",
+ "- `RUNNING`: Processing data\n",
+ "- `COMPLETED`: Successfully onboarded\n",
+ "- `FAILED`: Error occurred (check logs)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "poll-dataset-status",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "⏳ Monitoring dataset onboarding progress...\n",
+ "\n",
+ "Succeeded - 421 secondss\n",
+ "Attempt 1/60 - Status: Succeeded\n",
+ "Succeeded - 451 seconds\n",
+ "Attempt 2/60 - Status: Succeeded\n"
+ ]
+ },
+ {
+ "ename": "KeyboardInterrupt",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
+ "\u001b[31mKeyboardInterrupt\u001b[39m Traceback (most recent call last)",
+ "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[8]\u001b[39m\u001b[32m, line 23\u001b[39m\n\u001b[32m 20\u001b[39m \u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[32m 22\u001b[39m attempt += \u001b[32m1\u001b[39m\n\u001b[32m---> \u001b[39m\u001b[32m23\u001b[39m \u001b[43mtime\u001b[49m\u001b[43m.\u001b[49m\u001b[43msleep\u001b[49m\u001b[43m(\u001b[49m\u001b[32;43m30\u001b[39;49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# Wait 30 seconds before next check\u001b[39;00m\n\u001b[32m 25\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m attempt >= max_attempts:\n\u001b[32m 26\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[33m\"\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[33m⚠️ Timeout: Dataset onboarding is still in progress.\u001b[39m\u001b[33m\"\u001b[39m)\n",
+ "\u001b[31mKeyboardInterrupt\u001b[39m: "
+ ]
+ }
+ ],
+ "source": [
+ "# Poll dataset onboarding status\n",
+ "print(\"⏳ Monitoring dataset onboarding progress...\\n\")\n",
+ "\n",
+ "max_attempts = 60 # 30 minutes with 30-second intervals\n",
+ "attempt = 0\n",
+ "\n",
+ "while attempt < max_attempts:\n",
+ " status_response = client.poll_onboard_dataset_until_finished(dataset_id)\n",
+ " status = status_response.get('status', 'UNKNOWN')\n",
+ " \n",
+ " print(f\"Attempt {attempt + 1}/{max_attempts} - Status: {status}\")\n",
+ " \n",
+ " if status in ['COMPLETED', 'Succeeded']:\n",
+ " print(\"\\n✅ Dataset onboarding completed successfully!\")\n",
+ " print(json.dumps(status_response, indent=2))\n",
+ " break\n",
+ " elif status in ['FAILED', 'Failed']:\n",
+ " print(\"\\n❌ Dataset onboarding failed!\")\n",
+ " print(json.dumps(status_response, indent=2))\n",
+ " break\n",
+ " \n",
+ " attempt += 1\n",
+ " time.sleep(30) # Wait 30 seconds before next check\n",
+ "\n",
+ "if attempt >= max_attempts:\n",
+ " print(\"\\n⚠️ Timeout: Dataset onboarding is still in progress.\")\n",
+ " print(\"Check the status manually using: client.get_dataset_status(dataset_id)\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "step3-template",
+ "metadata": {},
+ "source": [
+ "## 6. Step 3: Register the TerraMind Task Template\n",
+ "\n",
+ "Now we need to register the task template that defines how to train with TerraMind.\n",
+ "\n",
+ "The TerraMind segmentation template is specifically designed for multimodal training and includes:\n",
+ "- Multimodal fusion configuration\n",
+ "- Decoder architecture settings\n",
+ "- Training hyperparameters optimized for TerraMind"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "load-template",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "📋 TerraMind Segmentation Template:\n",
+ "Name: terramind Segmentation\n",
+ "Description: Terramind multimodal task for Segmantation\n",
+ "Purpose: Segmentation\n",
+ "Model Category: terramind\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Load the TerraMind segmentation template\n",
+ "with open(\"../../../populate-studio/payloads/templates/template-terramind_seg.json\", \"r\") as f:\n",
+ " terramind_template = json.load(f)\n",
+ "\n",
+ "print(\"📋 TerraMind Segmentation Template:\")\n",
+ "print(f\"Name: {terramind_template['name']}\")\n",
+ "print(f\"Description: {terramind_template['description']}\")\n",
+ "print(f\"Purpose: {terramind_template['purpose']}\")\n",
+ "print(f\"Model Category: {terramind_template['extra_info']['model_category']}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "create-template",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "✅ TerraMind template registered successfully!\n",
+ "{\n",
+ " \"id\": \"21932c6c-62df-408e-ba87-3f0121d29a09\"\n",
+ "}\n",
+ "\n",
+ "📌 Template ID: 21932c6c-62df-408e-ba87-3f0121d29a09\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Register the template\n",
+ "template_response = client.create_task(terramind_template)\n",
+ "\n",
+ "print(\"\\n✅ TerraMind template registered successfully!\")\n",
+ "print(json.dumps(template_response, indent=2))\n",
+ "\n",
+ "# Save the template ID for later use\n",
+ "tune_template_id = template_response['id']\n",
+ "print(f\"\\n📌 Template ID: {tune_template_id}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "step4-finetune",
+ "metadata": {},
+ "source": [
+ "## 7. Step 4: Submit the Fine-Tuning Job\n",
+ "\n",
+ "Now we'll submit a fine-tuning job to train our multimodal flood detection model.\n",
+ "\n",
+ "**Training Configuration:**\n",
+ "- **Base Model**: TerraMind v1 Tiny (CPU-compatible)\n",
+ "- **Dataset**: Sen1Floods11 multimodal\n",
+ "- **Task**: Segmentation (pixel-level flood classification)\n",
+ "- **Epochs**: 10 (can be adjusted)\n",
+ "- **Learning Rate**: 6e-5 (optimized for TerraMind)\n",
+ "- **Batch Size**: 2 (suitable for CPU training)\n",
+ "\n",
+ "### 💻 CPU vs GPU Training\n",
+ "\n",
+ "**CPU Training (TerraMind Tiny):**\n",
+ "- ✅ No GPU required\n",
+ "- ✅ Works on any system\n",
+ "- ⏱️ Slower: 2-4 hours\n",
+ "- 📊 Good for learning and testing\n",
+ "\n",
+ "**GPU Training (Optional):**\n",
+ "- ⚡ Much faster: 60-90 minutes\n",
+ "- 🎯 Better for production\n",
+ "- 💰 Requires GPU resources\n",
+ "\n",
+ "**Note:** If you have a GPU available, the same code will automatically use it for faster training."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "create-tune-payload",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "📋 Fine-tuning Configuration:\n",
+ "{\n",
+ " \"name\": \"flood-multimodal-terramind\",\n",
+ " \"description\": \"Multimodal flood detection model trained with TerraMind on Sen1Floods11\",\n",
+ " \"dataset_id\": \"geodata-m6mjazvh82c5spfqzzvqwq\",\n",
+ " \"base_model_id\": \"235d4756-4afc-487f-8cd5-5714f70f2d18\",\n",
+ " \"tune_template_id\": \"21932c6c-62df-408e-ba87-3f0121d29a09\"\n",
+ "}\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Define the fine-tuning payload\n",
+ "tune_payload = {\n",
+ " \"name\": \"flood-multimodal-terramind\",\n",
+ " \"description\": \"Multimodal flood detection model trained with TerraMind on Sen1Floods11\",\n",
+ " \"dataset_id\": dataset_id,\n",
+ " \"base_model_id\": base_model_id,\n",
+ " \"tune_template_id\": tune_template_id\n",
+ "}\n",
+ "\n",
+ "print(\"📋 Fine-tuning Configuration:\")\n",
+ "print(json.dumps(tune_payload, indent=2))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "submit-tune",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "🚀 Submitting multimodal fine-tuning job...\n",
+ "\n",
+ "✅ Fine-tuning job submitted successfully!\n",
+ "{\n",
+ " \"tune_id\": \"geotune-v7zbfsjkmmszbiqtkjlwsy\",\n",
+ " \"mcad_id\": \"kjob-geotune-v7zbfsjkmmszbiqtkjlwsy\",\n",
+ " \"status\": \"In_progress\",\n",
+ " \"message\": null\n",
+ "}\n",
+ "\n",
+ "📌 Tune ID: geotune-v7zbfsjkmmszbiqtkjlwsy\n",
+ "\n",
+ "💡 Training will take approximately 60-90 minutes.\n",
+ "You can monitor progress in the MLflow UI or Studio UI.\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Submit the fine-tuning job\n",
+ "print(\"🚀 Submitting multimodal fine-tuning job...\\n\")\n",
+ "\n",
+ "tune_response = client.submit_tune(tune_payload, output='json')\n",
+ "\n",
+ "print(\"✅ Fine-tuning job submitted successfully!\")\n",
+ "print(json.dumps(tune_response, indent=2))\n",
+ "\n",
+ "# Save the tune ID for later use\n",
+ "tune_id = tune_response['tune_id']\n",
+ "print(f\"\\n📌 Tune ID: {tune_id}\")\n",
+ "print(f\"\\n💡 Training will take approximately 60-90 minutes.\")\n",
+ "print(f\"You can monitor progress in the MLflow UI or Studio UI.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "monitor-training",
+ "metadata": {},
+ "source": [
+ "## 8. Step 5: Monitor Training Progress\n",
+ "\n",
+ "Training a multimodal model takes time. We'll poll the status until completion.\n",
+ "\n",
+ "**What's happening during training:**\n",
+ "1. **Initialization**: Loading TerraMind base model and multimodal dataset\n",
+ "2. **Data Loading**: Processing both Sentinel-1 and Sentinel-2 modalities\n",
+ "3. **Training**: Iterating through epochs, learning multimodal fusion\n",
+ "4. **Validation**: Evaluating performance on validation set\n",
+ "5. **Checkpointing**: Saving model state periodically\n",
+ "6. **Completion**: Finalizing and storing the trained model\n",
+ "\n",
+ "**Expected Duration:**\n",
+ "- **CPU (TerraMind Tiny)**: 2-4 hours\n",
+ "- **GPU (V100/A100)**: 60-90 minutes\n",
+ "- **GPU (Older)**: 90-120 minutes\n",
+ "\n",
+ "**Note:** This lab uses TerraMind Tiny which is optimized for CPU training. Training will complete successfully on CPU, just takes longer."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "poll-tune-status",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "⏳ Monitoring training progress...\n",
+ "\n",
+ "This will take approximately 60-90 minutes.\n",
+ "You can also monitor in the Studio UI or MLflow.\n",
+ "\n",
+ "Finished - Epoch: None - 426 secondsnds\n",
+ "\n",
+ "✅ Training completed successfully!\n",
+ "Your trained model 'flood-multimodal-terramind' is now available in the Model Catalog.\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Poll training status\n",
+ "print(\"⏳ Monitoring training progress...\\n\")\n",
+ "print(\"This will take approximately 60-90 minutes.\")\n",
+ "print(\"You can also monitor in the Studio UI or MLflow.\\n\")\n",
+ "\n",
+ "client.poll_finetuning_until_finished(tune_id=tune_id)\n",
+ "\n",
+ "print(\"\\n✅ Training completed successfully!\")\n",
+ "print(f\"Your trained model '{tune_payload['name']}' is now available in the Model Catalog.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "step6-inference",
+ "metadata": {},
+ "source": [
+ "## 9. Step 6: Run Multimodal Inference\n",
+ "\n",
+ "Now let's test our trained multimodal model on new data!\n",
+ "\n",
+ "**Important**: For multimodal inference, you need a location where BOTH Sentinel-1 and Sentinel-2 data are available.\n",
+ "\n",
+ "For this example, we'll configure an inference request. You'll need to provide a test area with both sensor coverages."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "create-inference-payload",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Define the multimodal inference payload\n",
+ "# Note: Adjust bbox and dates for your specific test area\n",
+ "inference_payload = {\n",
+ " \"model_display_name\": \"flood-multimodal-demo\",\n",
+ " \"location\": \"Flood Test Area\",\n",
+ " \"description\": \"Multimodal flood detection test\",\n",
+ " \"spatial_domain\": {\n",
+ " \"bbox\": [], # Add bbox: [min_lon, min_lat, max_lon, max_lat]\n",
+ " \"urls\": [],\n",
+ " \"tiles\": [],\n",
+ " \"polygons\": []\n",
+ " },\n",
+ " \"temporal_domain\": [\"2024-01-15\"], # Adjust date\n",
+ " \"pipeline_steps\": [\n",
+ " {\"status\": \"READY\", \"process_id\": \"sentinelhub-connector\", \"step_number\": 0},\n",
+ " {\"status\": \"WAITING\", \"process_id\": \"terratorch-inference\", \"step_number\": 1},\n",
+ " {\"status\": \"WAITING\", \"process_id\": \"postprocess-generic\", \"step_number\": 2},\n",
+ " {\"status\": \"WAITING\", \"process_id\": \"push-to-geoserver\", \"step_number\": 3}\n",
+ " ],\n",
+ " \"model_input_data_spec\": [\n",
+ " {\n",
+ " \"bands\": [\n",
+ " {\"index\": \"0\", \"band_name\": \"B01\", \"scaling_factor\": \"1\"},\n",
+ " {\"index\": \"1\", \"band_name\": \"B02\", \"RGB_band\": \"B\", \"scaling_factor\": \"1\"},\n",
+ " {\"index\": \"2\", \"band_name\": \"B03\", \"RGB_band\": \"G\", \"scaling_factor\": \"1\"},\n",
+ " {\"index\": \"3\", \"band_name\": \"B04\", \"RGB_band\": \"R\", \"scaling_factor\": \"1\"},\n",
+ " {\"index\": \"4\", \"band_name\": \"B05\", \"scaling_factor\": \"1\"},\n",
+ " {\"index\": \"5\", \"band_name\": \"B06\", \"scaling_factor\": \"1\"},\n",
+ " {\"index\": \"6\", \"band_name\": \"B07\", \"scaling_factor\": \"1\"},\n",
+ " {\"index\": \"7\", \"band_name\": \"B08\", \"scaling_factor\": \"1\"},\n",
+ " {\"index\": \"8\", \"band_name\": \"B8A\", \"scaling_factor\": \"1\"},\n",
+ " {\"index\": \"9\", \"band_name\": \"B09\", \"scaling_factor\": \"1\"},\n",
+ " {\"index\": \"10\", \"band_name\": \"B11\", \"scaling_factor\": \"1\"},\n",
+ " {\"index\": \"11\", \"band_name\": \"B12\", \"scaling_factor\": \"1\"},\n",
+ " {\"index\": \"12\", \"band_name\": \"CLD\", \"scaling_factor\": \"1\"}\n",
+ " ],\n",
+ " \"connector\": \"sentinelhub\",\n",
+ " \"collection\": \"s2_l2a\",\n",
+ " \"modality_tag\": \"S2L2A\"\n",
+ " },\n",
+ " {\n",
+ " \"bands\": [\n",
+ " {\"index\": \"0\", \"band_name\": \"VV\"},\n",
+ " {\"index\": \"1\", \"band_name\": \"VH\"}\n",
+ " ],\n",
+ " \"connector\": \"sentinelhub\",\n",
+ " \"collection\": \"s1_grd\",\n",
+ " \"modality_tag\": \"S1GRD\",\n",
+ " \"align_dates\": \"true\"\n",
+ " }\n",
+ " ],\n",
+ " \"geoserver_push\": [\n",
+ " {\n",
+ " \"z_index\": 0,\n",
+ " \"workspace\": \"geofm\",\n",
+ " \"layer_name\": \"input_rgb\",\n",
+ " \"display_name\": \"Input RGB\",\n",
+ " \"filepath_key\": \"model_input_original_image_rgb\",\n",
+ " \"geoserver_style\": {\"rgb\": [\n",
+ " {\"label\": \"Red\", \"channel\": 1, \"maxValue\": 255, \"minValue\": 0},\n",
+ " {\"label\": \"Green\", \"channel\": 2, \"maxValue\": 255, \"minValue\": 0},\n",
+ " {\"label\": \"Blue\", \"channel\": 3, \"maxValue\": 255, \"minValue\": 0}\n",
+ " ]},\n",
+ " \"visible_by_default\": \"True\"\n",
+ " },\n",
+ " {\n",
+ " \"z_index\": 1,\n",
+ " \"workspace\": \"geofm\",\n",
+ " \"layer_name\": \"pred\",\n",
+ " \"display_name\": \"Flood Prediction\",\n",
+ " \"filepath_key\": \"model_output_image\",\n",
+ " \"geoserver_style\": {\"segmentation\": [\n",
+ " {\"color\": \"#000000\", \"label\": \"no-flood\", \"opacity\": 0, \"quantity\": \"0\"},\n",
+ " {\"color\": \"#0080FF\", \"label\": \"flood\", \"opacity\": 0.7, \"quantity\": \"1\"}\n",
+ " ]},\n",
+ " \"visible_by_default\": \"True\"\n",
+ " }\n",
+ " ]\n",
+ "}\n",
+ "\n",
+ "print(\"📋 Inference Configuration Ready\")\n",
+ "print(f\"Modalities: S2L2A + S1GRD\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "submit-inference",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Submit the inference request\n",
+ "print(\"🚀 Submitting multimodal inference...\\n\")\n",
+ "\n",
+ "inference_response = client.try_out_tune(tune_id=tune_id, data=inference_payload)\n",
+ "\n",
+ "print(\"✅ Inference submitted successfully!\")\n",
+ "print(json.dumps(inference_response, indent=2))\n",
+ "\n",
+ "print(\"\\n💡 View results in the Studio UI under Model & Tunes > History\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "results-section",
+ "metadata": {},
+ "source": [
+ "## 10. Viewing Results\n",
+ "\n",
+ "Your multimodal flood detection results are now available in the UI!\n",
+ "\n",
+ "**To view:**\n",
+ "1. Navigate to Model Catalog in Studio UI\n",
+ "2. Find \"flood-multimodal-terramind\"\n",
+ "3. Click History tab\n",
+ "4. View your inference on the map\n",
+ "\n",
+ "**What to observe:**\n",
+ "- Blue overlay shows detected floods\n",
+ "- Compare with RGB input\n",
+ "- Notice SAR helps through clouds\n",
+ "- Assess multimodal fusion benefits"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "conclusion",
+ "metadata": {},
+ "source": [
+ "## 11. Conclusion\n",
+ "\n",
+ "Congratulations! You've successfully set up a multimodal flood detection workflow using TerraMind.\n",
+ "\n",
+ "### What You've Accomplished\n",
+ "\n",
+ "1. **Registered TerraMind**: Set up a multimodal foundation model\n",
+ "2. **Onboarded Multimodal Data**: Configured Sen1Floods11 dataset with Sentinel-1 and Sentinel-2\n",
+ "3. **Understanding**: Learned about multimodal fusion and its benefits\n",
+ "\n",
+ "### Next Steps\n",
+ "\n",
+ "To complete the full workflow:\n",
+ "1. Load and register the TerraMind segmentation template\n",
+ "2. Submit a fine-tuning job with your multimodal dataset\n",
+ "3. Monitor training progress (60-90 minutes)\n",
+ "4. Run inference on new multimodal data\n",
+ "5. Visualize and evaluate results\n",
+ "\n",
+ "### Key Takeaways\n",
+ "\n",
+ "- **Multimodal Advantage**: Combining SAR and optical data provides more robust predictions\n",
+ "- **TerraMind**: Specialized architecture for processing multiple sensor types\n",
+ "- **Data Alignment**: Critical to ensure temporal alignment between modalities\n",
+ "- **Applications**: Flood detection, disaster response, climate monitoring\n",
+ "\n",
+ "### Resources\n",
+ "\n",
+ "- **Documentation**: [Geospatial Studio Docs](https://terrastackai.github.io/geospatial-studio/)\n",
+ "- **SDK Reference**: [Geospatial Studio SDK](https://terrastackai.github.io/geospatial-studio-toolkit/)\n",
+ "- **Dataset**: [Sen1Floods11](https://github.com/cloudtostreet/Sen1Floods11)\n",
+ "- **Models**: [IBM Geospatial Models](https://huggingface.co/ibm-nasa-geospatial)\n",
+ "\n",
+ "---\n",
+ "\n",
+ "## 🎓 Lab Complete!\n",
+ "\n",
+ "Thank you for completing Lab 5! You've learned how to work with multimodal geospatial data and TerraMind foundation models.\n",
+ "\n",
+ "**Questions or Feedback?**\n",
+ "- Open an issue on [GitHub](https://github.com/terrastackai/geospatial-studio)\n",
+ "- Join our community discussions\n",
+ "\n",
+ "Happy mapping! 🌍🛰️🌊"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": ".venv",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.14.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/workshop/docs/resources/faq.md b/workshop/docs/resources/faq.md
index 697aefd1..ce71eab0 100644
--- a/workshop/docs/resources/faq.md
+++ b/workshop/docs/resources/faq.md
@@ -40,7 +40,7 @@ By completing this workshop, you will:
### How long does the workshop take?
-**Total time:** 3-4 hours
+**Total time:** 5-6 hours
- **Pre-work (deployment):** 1-1.5 hours
- **Introduction:** 15 minutes
@@ -48,6 +48,7 @@ By completing this workshop, you will:
- **Lab 2 (Onboarding Pre-computed Examples):** 20 minutes
- **Lab 3 (Upload Model Checkpoints and Run Inference):** 30 minutes
- **Lab 4 (Training a Custom Model for Wildfire Burn Scar Detection):** 60-90 minutes
+- **Lab 5 (Training a Multimodal Model for Flood Detection):** 90-120 minutes
You can complete labs at your own pace and take breaks as needed.
diff --git a/workshop/docs/resources/next-steps.md b/workshop/docs/resources/next-steps.md
index ec4f1640..1d061ce3 100644
--- a/workshop/docs/resources/next-steps.md
+++ b/workshop/docs/resources/next-steps.md
@@ -402,6 +402,7 @@ while True:
- [Lab 2: Onboarding Pre-computed Examples](../notebooks/lab2-onboarding-examples.ipynb)
- [Lab 3: Upload Model Checkpoints and Run Inference](../notebooks/lab3-running-inference.ipynb)
- [Lab 4: Training a Custom Model for Wildfire Burn Scar Detection](../notebooks/lab4-burnscars-workflow.ipynb)
+- [Lab 5: Training a Multimodal Model for Flood Detection](../notebooks/lab5-flood-multimodal-workflow.ipynb)
## 🚀 Your Journey Continues
diff --git a/workshop/mkdocs.yml b/workshop/mkdocs.yml
index 93268761..6e78bcc2 100644
--- a/workshop/mkdocs.yml
+++ b/workshop/mkdocs.yml
@@ -32,6 +32,7 @@ nav:
- Lab 2: notebooks/lab2-onboarding-examples.ipynb
- Lab 3: notebooks/lab3-running-inference.ipynb
- Lab 4: notebooks/lab4-burnscars-workflow.ipynb
+ - Lab 5: notebooks/lab5-flood-multimodal-workflow.ipynb
- Resources:
- Additional Resources: resources/additional-resources.md
- Troubleshooting: resources/troubleshooting.md