|
2 | 2 | "cells": [ |
3 | 3 | { |
4 | 4 | "cell_type": "markdown", |
5 | | - "metadata": {}, |
6 | 5 | "id": "26faf28f-336d-4ced-9be8-4217ef2deea7", |
| 6 | + "metadata": {}, |
7 | 7 | "source": [ |
8 | 8 | "# Cross-source comparison\n", |
9 | 9 | "\n", |
|
20 | 20 | }, |
21 | 21 | { |
22 | 22 | "cell_type": "markdown", |
23 | | - "metadata": {}, |
24 | 23 | "id": "76c2bc1a-3c6c-4c4b-afb9-e979957bfcfe", |
| 24 | + "metadata": {}, |
25 | 25 | "source": [ |
26 | 26 | "## Load the longest-baseline timeseries TIFF from each run" |
27 | 27 | ] |
28 | 28 | }, |
29 | 29 | { |
30 | 30 | "cell_type": "code", |
31 | | - "metadata": {}, |
32 | | - "id": "862df8b7-dddd-4dca-a7a8-6e94e9a1da0c", |
33 | 31 | "execution_count": null, |
| 32 | + "id": "862df8b7-dddd-4dca-a7a8-6e94e9a1da0c", |
| 33 | + "metadata": {}, |
34 | 34 | "outputs": [], |
35 | | - "source": "import re\nfrom datetime import datetime\nfrom pathlib import Path\n\nimport numpy as np\nimport rasterio\nimport matplotlib.pyplot as plt\n\n# Each per-source example notebook writes its outputs to ./example_<source>\n# relative to whatever directory it was launched from. Run this notebook from\n# the same CWD as those three notebooks.\nRUNS_DIR = Path(\".\")\nSOURCES = {\n \"Sentinel-1 bursts\": RUNS_DIR / \"example_s1_burst\",\n \"OPERA CSLC\": RUNS_DIR / \"example_opera_cslc\",\n \"NISAR GSLC\": RUNS_DIR / \"example_nisar\",\n}\n\nPAIR_RE = re.compile(r\"^(\\d{8})_(\\d{8})\\.tif$\")\n\ndef longest_pair(ts_dir: Path) -> tuple[Path, datetime, datetime]:\n \"\"\"Return the `YYYYMMDD_YYYYMMDD.tif` with the widest baseline.\"\"\"\n best = None\n best_span = -1\n for p in ts_dir.glob(\"*.tif\"):\n m = PAIR_RE.match(p.name)\n if not m:\n continue\n d1 = datetime.strptime(m.group(1), \"%Y%m%d\")\n d2 = datetime.strptime(m.group(2), \"%Y%m%d\")\n span = (d2 - d1).days\n if span > best_span:\n best_span = span\n best = (p, d1, d2)\n assert best is not None, f\"no pair-baseline TIFFs in {ts_dir}\"\n return best\n\ndef load_raster(path: Path):\n with rasterio.open(path) as src:\n return {\n \"data\": src.read(1, masked=True),\n \"bounds\": src.bounds,\n \"unit\": (src.units[0] if src.units else \"?\") or \"?\",\n }\n\nrasters = {}\nfor label, root in SOURCES.items():\n ts_dir = root / \"dolphin\" / \"timeseries\"\n longest_path, d1, d2 = longest_pair(ts_dir)\n r = load_raster(longest_path)\n r.update(pair_name=longest_path.name, date_start=d1, date_end=d2, baseline_days=(d2 - d1).days)\n rasters[label] = r\n print(\n f\"{label:20s} {longest_path.name} unit={r['unit']} baseline={r['baseline_days']}d\"\n )" |
| 35 | + "source": [ |
| 36 | + "import re\n", |
| 37 | + "from datetime import datetime\n", |
| 38 | + "from pathlib import Path\n", |
| 39 | + "\n", |
| 40 | + "import matplotlib.pyplot as plt\n", |
| 41 | + "import numpy as np\n", |
| 42 | + "import rasterio\n", |
| 43 | + "\n", |
| 44 | + "# Each per-source example notebook writes its outputs to ./example_<source>\n", |
| 45 | + "# relative to whatever directory it was launched from. Run this notebook from\n", |
| 46 | + "# the same CWD as those three notebooks.\n", |
| 47 | + "RUNS_DIR = Path(\".\")\n", |
| 48 | + "SOURCES = {\n", |
| 49 | + " \"Sentinel-1 bursts\": RUNS_DIR / \"example_s1_burst\",\n", |
| 50 | + " \"OPERA CSLC\": RUNS_DIR / \"example_opera_cslc\",\n", |
| 51 | + " \"NISAR GSLC\": RUNS_DIR / \"example_nisar\",\n", |
| 52 | + "}\n", |
| 53 | + "\n", |
| 54 | + "PAIR_RE = re.compile(r\"^(\\d{8})_(\\d{8})\\.tif$\")\n", |
| 55 | + "\n", |
| 56 | + "def longest_pair(ts_dir: Path) -> tuple[Path, datetime, datetime]:\n", |
| 57 | + " \"\"\"Return the `YYYYMMDD_YYYYMMDD.tif` with the widest baseline.\"\"\"\n", |
| 58 | + " best = None\n", |
| 59 | + " best_span = -1\n", |
| 60 | + " for p in ts_dir.glob(\"*.tif\"):\n", |
| 61 | + " m = PAIR_RE.match(p.name)\n", |
| 62 | + " if not m:\n", |
| 63 | + " continue\n", |
| 64 | + " d1 = datetime.strptime(m.group(1), \"%Y%m%d\")\n", |
| 65 | + " d2 = datetime.strptime(m.group(2), \"%Y%m%d\")\n", |
| 66 | + " span = (d2 - d1).days\n", |
| 67 | + " if span > best_span:\n", |
| 68 | + " best_span = span\n", |
| 69 | + " best = (p, d1, d2)\n", |
| 70 | + " assert best is not None, f\"no pair-baseline TIFFs in {ts_dir}\"\n", |
| 71 | + " return best\n", |
| 72 | + "\n", |
| 73 | + "def load_raster(path: Path):\n", |
| 74 | + " with rasterio.open(path) as src:\n", |
| 75 | + " return {\n", |
| 76 | + " \"data\": src.read(1, masked=True),\n", |
| 77 | + " \"bounds\": src.bounds,\n", |
| 78 | + " \"unit\": (src.units[0] if src.units else \"?\") or \"?\",\n", |
| 79 | + " }\n", |
| 80 | + "\n", |
| 81 | + "rasters = {}\n", |
| 82 | + "for label, root in SOURCES.items():\n", |
| 83 | + " ts_dir = root / \"dolphin\" / \"timeseries\"\n", |
| 84 | + " longest_path, d1, d2 = longest_pair(ts_dir)\n", |
| 85 | + " r = load_raster(longest_path)\n", |
| 86 | + " r.update(pair_name=longest_path.name, date_start=d1, date_end=d2, baseline_days=(d2 - d1).days)\n", |
| 87 | + " rasters[label] = r\n", |
| 88 | + " print(\n", |
| 89 | + " f\"{label:20s} {longest_path.name} unit={r['unit']} baseline={r['baseline_days']}d\"\n", |
| 90 | + " )" |
| 91 | + ] |
36 | 92 | }, |
37 | 93 | { |
38 | 94 | "cell_type": "markdown", |
39 | | - "metadata": {}, |
40 | 95 | "id": "00c745c0-7ffc-4d93-ab40-dd5dd39d3153", |
| 96 | + "metadata": {}, |
41 | 97 | "source": [ |
42 | 98 | "## Cumulative displacement (meters)\n", |
43 | 99 | "\n", |
|
46 | 102 | }, |
47 | 103 | { |
48 | 104 | "cell_type": "code", |
49 | | - "metadata": {}, |
50 | | - "id": "96cbde80-7969-4ce8-89e2-5cdbf1eb1fa4", |
51 | 105 | "execution_count": null, |
| 106 | + "id": "96cbde80-7969-4ce8-89e2-5cdbf1eb1fa4", |
| 107 | + "metadata": {}, |
52 | 108 | "outputs": [], |
53 | 109 | "source": [ |
54 | 110 | "def finite_values(a):\n", |
|
93 | 149 | }, |
94 | 150 | { |
95 | 151 | "cell_type": "markdown", |
96 | | - "metadata": {}, |
97 | 152 | "id": "c9f60e41-bfc0-43f8-9c86-09e33e07440c", |
| 153 | + "metadata": {}, |
98 | 154 | "source": [ |
99 | 155 | "## Effective velocity (meters / year)\n", |
100 | 156 | "\n", |
|
103 | 159 | }, |
104 | 160 | { |
105 | 161 | "cell_type": "code", |
106 | | - "metadata": {}, |
107 | | - "id": "80a7e0ee-35c5-486a-a580-c121c6871fe3", |
108 | 162 | "execution_count": null, |
| 163 | + "id": "80a7e0ee-35c5-486a-a580-c121c6871fe3", |
| 164 | + "metadata": {}, |
109 | 165 | "outputs": [], |
110 | 166 | "source": [ |
111 | 167 | "rasters_eff = {}\n", |
|
143 | 199 | }, |
144 | 200 | { |
145 | 201 | "cell_type": "markdown", |
146 | | - "metadata": {}, |
147 | 202 | "id": "eef5bc98-b369-4230-b9d8-295889f11efc", |
| 203 | + "metadata": {}, |
148 | 204 | "source": [ |
149 | 205 | "## Quick stats" |
150 | 206 | ] |
151 | 207 | }, |
152 | 208 | { |
153 | 209 | "cell_type": "code", |
154 | | - "metadata": {}, |
155 | | - "id": "4245053f-b51a-4d04-b741-745fb2bb04af", |
156 | 210 | "execution_count": null, |
| 211 | + "id": "4245053f-b51a-4d04-b741-745fb2bb04af", |
| 212 | + "metadata": {}, |
157 | 213 | "outputs": [], |
158 | 214 | "source": [ |
159 | 215 | "print(f\"{'source':20s} {'baseline':>10s} {'n_valid':>10s} {'disp_std':>12s} {'eff_v_std':>12s}\")\n", |
|
178 | 234 | "name": "python3" |
179 | 235 | }, |
180 | 236 | "language_info": { |
181 | | - "name": "python", |
| 237 | + "file_extension": ".py", |
182 | 238 | "mimetype": "text/x-python", |
183 | | - "file_extension": ".py" |
| 239 | + "name": "python" |
184 | 240 | } |
185 | 241 | }, |
186 | 242 | "nbformat": 4, |
|
0 commit comments