From cabfe82eecf73f2159bbdb74e2f88bc4b90afe60 Mon Sep 17 00:00:00 2001 From: Anil Madhavapeddy Date: Sun, 4 Jan 2026 19:54:26 +0530 Subject: [PATCH 1/2] add a --tile option to the cli to make it easier to query single points --- README.md | 21 +++++- geotessera/cli.py | 150 ++++++++++++++++++++++++++++++++++--- geotessera/registry_cli.py | 18 ++++- tests/tile.t | 134 +++++++++++++++++++++++++++++++++ 4 files changed, 303 insertions(+), 20 deletions(-) create mode 100644 tests/tile.t diff --git a/README.md b/README.md index 9a20ea0..b3871da 100644 --- a/README.md +++ b/README.md @@ -325,8 +325,10 @@ geotessera download [OPTIONS] Options: -o, --output PATH Output directory [required] - --bbox TEXT Bounding box: 'min_lon,min_lat,max_lon,max_lat' + --bbox TEXT Bounding box: 'lon,lat' (single tile) or 'min_lon,min_lat,max_lon,max_lat' + --tile TEXT Single tile by any point within it: 'lon,lat' --region-file PATH GeoJSON/Shapefile to define region + --country TEXT Country name (e.g., 'United Kingdom', 'UK', 'GB') -f, --format TEXT Output format: 'tiff' or 'npy' (default: tiff) --year INT Year of embeddings (default: 2024) --bands TEXT Comma-separated band indices (default: all 128) @@ -335,6 +337,15 @@ Options: -v, --verbose Verbose output ``` +Single tile examples: +```bash +# Download a single tile containing a specific point +geotessera download --tile "0.17,52.23" --year 2024 -o ./single_tile + +# Same result using --bbox with 2 coordinates +geotessera download --bbox "0.17,52.23" --year 2024 -o ./single_tile +``` + Output formats: - **tiff**: Georeferenced GeoTIFF files with UTM projection - **npy**: Raw numpy arrays with metadata.json file @@ -366,12 +377,14 @@ geotessera coverage [OPTIONS] Options: -o, --output PATH Output PNG file (default: tessera_coverage.png) --year INT Specific year to visualize + --bbox TEXT Bounding box: 'lon,lat' (single tile) or 'min_lon,min_lat,max_lon,max_lat' + --tile TEXT Single tile by any point within it: 'lon,lat' + --region-file PATH GeoJSON/Shapefile to focus on specific region + --country TEXT Country name to focus on (e.g., 'United Kingdom') --tile-color TEXT Color for tiles (default: red) --tile-alpha FLOAT Transparency 0-1 (default: 0.6) --tile-size FLOAT Size multiplier (default: 1.0) - --dpi INT Output resolution (default: 100) - --width INT Figure width in inches (default: 20) - --height INT Figure height in inches (default: 10) + --width INT Output image width in pixels (default: 2000) --no-countries Don't show country boundaries ``` diff --git a/geotessera/cli.py b/geotessera/cli.py index 725b5d7..4b060d4 100644 --- a/geotessera/cli.py +++ b/geotessera/cli.py @@ -26,6 +26,7 @@ from geotessera.registry import ( EMBEDDINGS_DIR_NAME, LANDMASKS_DIR_NAME, + tile_from_world, tile_to_landmask_filename, tile_to_embedding_paths, ) @@ -118,6 +119,23 @@ def format_bbox(bbox_coords) -> str: return f"[{min_lon_str}, {min_lat_str}] - [{max_lon_str}, {max_lat_str}]" +def point_to_tile_bbox(lon: float, lat: float) -> tuple: + """Convert a point to the bounding box of its containing tile. + + Tiles are 0.1x0.1 degree squares centered at 0.05-degree offsets. + + Args: + lon: Longitude in decimal degrees + lat: Latitude in decimal degrees + + Returns: + Tuple of (min_lon, min_lat, max_lon, max_lat) for the containing tile + """ + tile_lon, tile_lat = tile_from_world(lon, lat) + # Tile center ± 0.05 degrees + return (tile_lon - 0.05, tile_lat - 0.05, tile_lon + 0.05, tile_lat + 0.05) + + app = typer.Typer( name="geotessera", help=f"GeoTessera v{__version__}: Download satellite embedding tiles as GeoTIFFs", @@ -533,6 +551,17 @@ def coverage( help="Country name to focus coverage map on (e.g., 'United Kingdom', 'UK', 'GB')", ), ] = None, + bbox: Annotated[ + Optional[str], + typer.Option( + "--bbox", + help="Bounding box: 'lon,lat' (single tile) or 'min_lon,min_lat,max_lon,max_lat'", + ), + ] = None, + tile: Annotated[ + Optional[str], + typer.Option("--tile", help="Single tile by any point within it: 'lon,lat'"), + ] = None, tile_color: Annotated[ str, typer.Option( @@ -611,13 +640,60 @@ def coverage( country_geojson_file = None region_file_temp = None # Track if we created a temporary file - if region_file and country: + # Check mutual exclusivity of region options + region_sources = sum(1 for x in [bbox, tile, region_file, country] if x) + if region_sources > 1: rprint( - "[red]Error: Cannot specify both --region-file and --country. Choose one.[/red]" + "[red]Error: Cannot specify multiple region options. " + "Choose one of: --bbox, --tile, --region-file, --country[/red]" ) raise typer.Exit(1) - if region_file: + if tile: + try: + tile_coords = tuple(map(float, tile.split(","))) + if len(tile_coords) != 2: + rprint("[red]Error: --tile must be 'lon,lat'[/red]") + raise typer.Exit(1) + lon, lat = tile_coords + tile_center = tile_from_world(lon, lat) + region_bbox = point_to_tile_bbox(lon, lat) + rprint( + f"[green]Point ({lon}, {lat}) → tile " + f"grid_{tile_center[0]:.2f}_{tile_center[1]:.2f}[/green]" + ) + rprint(f"[green]Region bounding box:[/green] {format_bbox(region_bbox)}") + except ValueError as e: + rprint(f"[red]Error: Invalid --tile format. Use 'lon,lat': {e}[/red]") + raise typer.Exit(1) + elif bbox: + try: + bbox_coords = tuple(map(float, bbox.split(","))) + if len(bbox_coords) == 2: + # Two coordinates = single tile + lon, lat = bbox_coords + tile_center = tile_from_world(lon, lat) + region_bbox = point_to_tile_bbox(lon, lat) + rprint( + f"[green]Point ({lon}, {lat}) → tile " + f"grid_{tile_center[0]:.2f}_{tile_center[1]:.2f}[/green]" + ) + elif len(bbox_coords) == 4: + region_bbox = bbox_coords + else: + rprint( + "[red]Error: bbox must be 'lon,lat' (single tile) " + "or 'min_lon,min_lat,max_lon,max_lat'[/red]" + ) + raise typer.Exit(1) + rprint(f"[green]Region bounding box:[/green] {format_bbox(region_bbox)}") + except ValueError: + rprint( + "[red]Error: Invalid bbox format. Use: 'lon,lat' or " + "'min_lon,min_lat,max_lon,max_lat'[/red]" + ) + raise typer.Exit(1) + elif region_file: try: from .visualization import calculate_bbox_from_file @@ -892,7 +968,14 @@ def download( ] = None, bbox: Annotated[ Optional[str], - typer.Option("--bbox", help="Bounding box: 'min_lon,min_lat,max_lon,max_lat'"), + typer.Option( + "--bbox", + help="Bounding box: 'lon,lat' (single tile) or 'min_lon,min_lat,max_lon,max_lat'", + ), + ] = None, + tile: Annotated[ + Optional[str], + typer.Option("--tile", help="Single tile by any point within it: 'lon,lat'"), ] = None, region_file: Annotated[ Optional[str], @@ -1006,19 +1089,58 @@ def download( verify_hashes=not skip_hash, ) - # Parse bounding box - if bbox: + # Check mutual exclusivity of region options + region_sources = sum(1 for x in [bbox, tile, region_file, country] if x) + if region_sources > 1: + rprint( + "[red]Error: Cannot specify multiple region options. " + "Choose one of: --bbox, --tile, --region-file, --country[/red]" + ) + raise typer.Exit(1) + + # Parse bounding box or tile + if tile: + try: + tile_coords = tuple(map(float, tile.split(","))) + if len(tile_coords) != 2: + rprint("[red]Error: --tile must be 'lon,lat'[/red]") + raise typer.Exit(1) + lon, lat = tile_coords + tile_center = tile_from_world(lon, lat) + bbox_coords = point_to_tile_bbox(lon, lat) + rprint( + f"[green]Point ({lon}, {lat}) → tile " + f"grid_{tile_center[0]:.2f}_{tile_center[1]:.2f}[/green]" + ) + rprint(f"[green]Using bounding box:[/green] {format_bbox(bbox_coords)}") + except ValueError as e: + rprint(f"[red]Error: Invalid --tile format. Use 'lon,lat': {e}[/red]") + raise typer.Exit(1) + elif bbox: try: bbox_coords = tuple(map(float, bbox.split(","))) - if len(bbox_coords) != 4: + if len(bbox_coords) == 2: + # Two coordinates = single tile + lon, lat = bbox_coords + tile_center = tile_from_world(lon, lat) + bbox_coords = point_to_tile_bbox(lon, lat) rprint( - "[red]Error: bbox must be 'min_lon,min_lat,max_lon,max_lat'[/red]" + f"[green]Point ({lon}, {lat}) → tile " + f"grid_{tile_center[0]:.2f}_{tile_center[1]:.2f}[/green]" + ) + rprint(f"[green]Using bounding box:[/green] {format_bbox(bbox_coords)}") + elif len(bbox_coords) == 4: + rprint(f"[green]Using bounding box:[/green] {format_bbox(bbox_coords)}") + else: + rprint( + "[red]Error: bbox must be 'lon,lat' (single tile) " + "or 'min_lon,min_lat,max_lon,max_lat'[/red]" ) raise typer.Exit(1) - rprint(f"[green]Using bounding box:[/green] {format_bbox(bbox_coords)}") except ValueError: rprint( - "[red]Error: Invalid bbox format. Use: 'min_lon,min_lat,max_lon,max_lat'[/red]" + "[red]Error: Invalid bbox format. Use: 'lon,lat' or " + "'min_lon,min_lat,max_lon,max_lat'[/red]" ) raise typer.Exit(1) elif region_file: @@ -1098,10 +1220,14 @@ def country_progress_callback(current: int, total: int, status: str = None): rprint(f"[green]Using country '{country}':[/green] {format_bbox(bbox_coords)}") else: rprint( - "[red]Error: Must specify either --bbox, --region-file, or --country[/red]" + "[red]Error: Must specify either --bbox, --tile, --region-file, or --country[/red]" ) rprint("Examples:") - rprint(" --bbox '-0.2,51.4,0.1,51.6' # London area") + rprint(" --tile '0.17,52.23' # Single tile containing point") + rprint( + " --bbox '0.17,52.23' # Same as above (2 coords = single tile)" + ) + rprint(" --bbox '-0.2,51.4,0.1,51.6' # London area (4 coords = region)") rprint(" --region-file london.geojson # From GeoJSON file") rprint(" --country 'United Kingdom' # Country by name") raise typer.Exit(1) diff --git a/geotessera/registry_cli.py b/geotessera/registry_cli.py index e9dce75..2e92898 100644 --- a/geotessera/registry_cli.py +++ b/geotessera/registry_cli.py @@ -761,6 +761,7 @@ def progress_callback(current, total, status): # Group warnings by reason for better readability from collections import defaultdict + warnings_by_reason = defaultdict(list) for reason, path in warnings: warnings_by_reason[reason].append(path) @@ -780,7 +781,9 @@ def progress_callback(current, total, status): with open(missing_embeddings_file, "w") as f: for path in sorted(missing_embeddings): f.write(f"{path}\n") - console.print(f"\n[dim]Written {len(missing_embeddings)} paths to {missing_embeddings_file}[/dim]") + console.print( + f"\n[dim]Written {len(missing_embeddings)} paths to {missing_embeddings_file}[/dim]" + ) # Write missing scales missing_scales = warnings_by_reason.get("missing scales", []) @@ -789,7 +792,9 @@ def progress_callback(current, total, status): with open(missing_scales_file, "w") as f: for path in sorted(missing_scales): f.write(f"{path}\n") - console.print(f"[dim]Written {len(missing_scales)} paths to {missing_scales_file}[/dim]") + console.print( + f"[dim]Written {len(missing_scales)} paths to {missing_scales_file}[/dim]" + ) return True @@ -901,6 +906,7 @@ def progress_callback(current, total, status): # Group warnings by reason for better readability from collections import defaultdict + warnings_by_reason = defaultdict(list) for reason, path in warnings: warnings_by_reason[reason].append(path) @@ -920,7 +926,9 @@ def progress_callback(current, total, status): with open(missing_embeddings_file, "w") as f: for path in sorted(missing_embeddings): f.write(f"{path}\n") - console.print(f"\n[dim]Written {len(missing_embeddings)} paths to {missing_embeddings_file}[/dim]") + console.print( + f"\n[dim]Written {len(missing_embeddings)} paths to {missing_embeddings_file}[/dim]" + ) # Write missing scales missing_scales = warnings_by_reason.get("missing scales", []) @@ -929,7 +937,9 @@ def progress_callback(current, total, status): with open(missing_scales_file, "w") as f: for path in sorted(missing_scales): f.write(f"{path}\n") - console.print(f"[dim]Written {len(missing_scales)} paths to {missing_scales_file}[/dim]") + console.print( + f"[dim]Written {len(missing_scales)} paths to {missing_scales_file}[/dim]" + ) return 0 diff --git a/tests/tile.t b/tests/tile.t new file mode 100644 index 0000000..6a7d917 --- /dev/null +++ b/tests/tile.t @@ -0,0 +1,134 @@ +GeoTessera Single Tile Tests +============================= + +These are tests for the single tile download functionality using --tile and 2-coord --bbox. + +Setup +----- + +Set environment variable to disable fancy terminal output (ANSI codes, boxes, colors): + + $ export TERM=dumb + +Create a temporary directory for test outputs and cache: + + $ export TESTDIR="$CRAMTMP/test_outputs" + $ mkdir -p "$TESTDIR" + +Override XDG cache directory to use temporary location (for test isolation): + + $ export XDG_CACHE_HOME="$CRAMTMP/cache" + $ mkdir -p "$XDG_CACHE_HOME" + +Test: Single Tile with --tile Option (Dry Run) +---------------------------------------------- + +Test downloading a single tile using the --tile option with a point coordinate. +The point (0.17, 52.23) should resolve to tile grid_0.15_52.25: + + $ geotessera download \ + > --tile "0.17,52.23" \ + > --year 2024 \ + > --format tiff \ + > --dry-run \ + > --dataset-version v1 2>&1 | grep -E '(Point|tile grid_|Found|Files to download|Tiles in region)' + Point (0.17, 52.23) .* tile grid_0.15_52.25 (re) + Found 1 tiles for region in year 2024 + Files to download: 1 + Tiles in region: 1 + +Test: Single Tile with 2-coord --bbox (Dry Run) +----------------------------------------------- + +Test downloading a single tile using --bbox with only 2 coordinates. +This should behave identically to --tile: + + $ geotessera download \ + > --bbox "0.17,52.23" \ + > --year 2024 \ + > --format tiff \ + > --dry-run \ + > --dataset-version v1 2>&1 | grep -E '(Point|tile grid_|Found|Files to download|Tiles in region)' + Point (0.17, 52.23) .* tile grid_0.15_52.25 (re) + Found 1 tiles for region in year 2024 + Files to download: 1 + Tiles in region: 1 + +Test: Mutual Exclusivity of Region Options +------------------------------------------ + +Test that specifying multiple region options produces an error: + + $ geotessera download \ + > --tile "0.17,52.23" \ + > --bbox "-0.1,51.3,0.1,51.5" \ + > --year 2024 \ + > --dry-run \ + > --dataset-version v1 2>&1 | grep -E 'Error.*multiple region' + Error: Cannot specify multiple region options. Choose one of: --bbox, --tile, --region-file, --country + +Test: Invalid --tile Format (Wrong Number of Coords) +----------------------------------------------------- + +Test that --tile with wrong number of coordinates produces an error: + + $ geotessera download \ + > --tile "0.17,52.23,0.20" \ + > --year 2024 \ + > --dry-run \ + > --dataset-version v1 2>&1 | grep -E "Error.*--tile must be" + Error: --tile must be 'lon,lat' + +Test: Invalid --bbox Format (Wrong Number of Coords) +----------------------------------------------------- + +Test that --bbox with 3 coordinates produces an error: + + $ geotessera download \ + > --bbox "0.17,52.23,0.20" \ + > --year 2024 \ + > --dry-run \ + > --dataset-version v1 2>&1 | grep -E "Error.*bbox must be" + Error: bbox must be 'lon,lat' (single tile) or 'min_lon,min_lat,max_lon,max_lat' + +Test: Download Single Tile (Actual Download) +--------------------------------------------- + +Download a single tile using --tile option: + + $ geotessera download \ + > --tile "0.17,52.23" \ + > --year 2024 \ + > --format tiff \ + > --output "$TESTDIR/single_tile_tiff" \ + > --dataset-version v1 2>&1 | grep -E '(Point|SUCCESS)' | sed 's/ *$//' + Point (0.17, 52.23) .* tile grid_0.15_52.25 (re) + SUCCESS: Exported 1 GeoTIFF files + +Verify that exactly one TIFF file was created: + + $ find "$TESTDIR/single_tile_tiff/global_0.1_degree_representation/2024" -name "*.tif*" | wc -l | tr -d ' ' + 1 + +Verify the tile is named correctly (grid_0.15_52.25): + + $ find "$TESTDIR/single_tile_tiff/global_0.1_degree_representation/2024" -type d -name "grid_*" | xargs -I {} basename {} + grid_0.15_52.25 + +Test: Coverage Command with --tile Option +----------------------------------------- + +Test that coverage command also accepts --tile option: + + $ geotessera coverage \ + > --tile "0.17,52.23" \ + > --output "$TESTDIR/single_tile_coverage.png" \ + > --dataset-version v1 2>&1 | grep -E '(Point|tile grid_|Region bounding box)' + Point (0.17, 52.23) .* tile grid_0.15_52.25 (re) + Region bounding box: .* (re) + +Verify coverage image was created: + + $ test -f "$TESTDIR/single_tile_coverage.png" && echo "Coverage PNG created" + Coverage PNG created + From 3030e90b5892dcbeb68b282a65251e288ef3e13d Mon Sep 17 00:00:00 2001 From: Anil Madhavapeddy Date: Mon, 5 Jan 2026 12:47:46 +0530 Subject: [PATCH 2/2] fixes --- geotessera/cli.py | 15 +++++++++------ tests/cli.t | 2 +- tests/tile.t | 32 +++++++++++++------------------- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/geotessera/cli.py b/geotessera/cli.py index 4b060d4..e07a42b 100644 --- a/geotessera/cli.py +++ b/geotessera/cli.py @@ -123,6 +123,8 @@ def point_to_tile_bbox(lon: float, lat: float) -> tuple: """Convert a point to the bounding box of its containing tile. Tiles are 0.1x0.1 degree squares centered at 0.05-degree offsets. + Returns a point bbox at the tile center, which the registry query + will expand by 0.05 degrees to match exactly one tile. Args: lon: Longitude in decimal degrees @@ -132,8 +134,9 @@ def point_to_tile_bbox(lon: float, lat: float) -> tuple: Tuple of (min_lon, min_lat, max_lon, max_lat) for the containing tile """ tile_lon, tile_lat = tile_from_world(lon, lat) - # Tile center ± 0.05 degrees - return (tile_lon - 0.05, tile_lat - 0.05, tile_lon + 0.05, tile_lat + 0.05) + # Return point bbox at tile center - registry expands by 0.05 degrees + # which will match exactly this one tile + return (tile_lon, tile_lat, tile_lon, tile_lat) app = typer.Typer( @@ -659,7 +662,7 @@ def coverage( tile_center = tile_from_world(lon, lat) region_bbox = point_to_tile_bbox(lon, lat) rprint( - f"[green]Point ({lon}, {lat}) → tile " + f"[green]Point ({lon}, {lat}) -> tile " f"grid_{tile_center[0]:.2f}_{tile_center[1]:.2f}[/green]" ) rprint(f"[green]Region bounding box:[/green] {format_bbox(region_bbox)}") @@ -675,7 +678,7 @@ def coverage( tile_center = tile_from_world(lon, lat) region_bbox = point_to_tile_bbox(lon, lat) rprint( - f"[green]Point ({lon}, {lat}) → tile " + f"[green]Point ({lon}, {lat}) -> tile " f"grid_{tile_center[0]:.2f}_{tile_center[1]:.2f}[/green]" ) elif len(bbox_coords) == 4: @@ -1109,7 +1112,7 @@ def download( tile_center = tile_from_world(lon, lat) bbox_coords = point_to_tile_bbox(lon, lat) rprint( - f"[green]Point ({lon}, {lat}) → tile " + f"[green]Point ({lon}, {lat}) -> tile " f"grid_{tile_center[0]:.2f}_{tile_center[1]:.2f}[/green]" ) rprint(f"[green]Using bounding box:[/green] {format_bbox(bbox_coords)}") @@ -1125,7 +1128,7 @@ def download( tile_center = tile_from_world(lon, lat) bbox_coords = point_to_tile_bbox(lon, lat) rprint( - f"[green]Point ({lon}, {lat}) → tile " + f"[green]Point ({lon}, {lat}) -> tile " f"grid_{tile_center[0]:.2f}_{tile_center[1]:.2f}[/green]" ) rprint(f"[green]Using bounding box:[/green] {format_bbox(bbox_coords)}") diff --git a/tests/cli.t b/tests/cli.t index 2e8c5ad..10f6998 100644 --- a/tests/cli.t +++ b/tests/cli.t @@ -35,7 +35,7 @@ Test the info command without arguments to see library information. We just verify key information is present, ignoring formatting: $ geotessera info --dataset-version v1 2>&1 | grep -E 'Available years' - Available years: 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025 + Available years: 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025 Test: Download Dry Run for UK Tile ----------------------------------- diff --git a/tests/tile.t b/tests/tile.t index 6a7d917..8fc2b35 100644 --- a/tests/tile.t +++ b/tests/tile.t @@ -32,10 +32,10 @@ The point (0.17, 52.23) should resolve to tile grid_0.15_52.25: > --format tiff \ > --dry-run \ > --dataset-version v1 2>&1 | grep -E '(Point|tile grid_|Found|Files to download|Tiles in region)' - Point (0.17, 52.23) .* tile grid_0.15_52.25 (re) + Point (0.17, 52.23) -> tile grid_0.15_52.25 Found 1 tiles for region in year 2024 - Files to download: 1 - Tiles in region: 1 + Files to download: 1 + Tiles in region: 1 Test: Single Tile with 2-coord --bbox (Dry Run) ----------------------------------------------- @@ -49,10 +49,10 @@ This should behave identically to --tile: > --format tiff \ > --dry-run \ > --dataset-version v1 2>&1 | grep -E '(Point|tile grid_|Found|Files to download|Tiles in region)' - Point (0.17, 52.23) .* tile grid_0.15_52.25 (re) + Point (0.17, 52.23) -> tile grid_0.15_52.25 Found 1 tiles for region in year 2024 - Files to download: 1 - Tiles in region: 1 + Files to download: 1 + Tiles in region: 1 Test: Mutual Exclusivity of Region Options ------------------------------------------ @@ -64,8 +64,8 @@ Test that specifying multiple region options produces an error: > --bbox "-0.1,51.3,0.1,51.5" \ > --year 2024 \ > --dry-run \ - > --dataset-version v1 2>&1 | grep -E 'Error.*multiple region' - Error: Cannot specify multiple region options. Choose one of: --bbox, --tile, --region-file, --country + > --dataset-version v1 2>&1 | grep -E 'Cannot specify multiple region' + Error: Cannot specify multiple region options. Choose one of: --bbox, --tile, Test: Invalid --tile Format (Wrong Number of Coords) ----------------------------------------------------- @@ -102,7 +102,7 @@ Download a single tile using --tile option: > --format tiff \ > --output "$TESTDIR/single_tile_tiff" \ > --dataset-version v1 2>&1 | grep -E '(Point|SUCCESS)' | sed 's/ *$//' - Point (0.17, 52.23) .* tile grid_0.15_52.25 (re) + Point (0.17, 52.23) -> tile grid_0.15_52.25 SUCCESS: Exported 1 GeoTIFF files Verify that exactly one TIFF file was created: @@ -118,17 +118,11 @@ Verify the tile is named correctly (grid_0.15_52.25): Test: Coverage Command with --tile Option ----------------------------------------- -Test that coverage command also accepts --tile option: +Test that coverage command also accepts --tile option and parses the tile correctly: $ geotessera coverage \ > --tile "0.17,52.23" \ > --output "$TESTDIR/single_tile_coverage.png" \ - > --dataset-version v1 2>&1 | grep -E '(Point|tile grid_|Region bounding box)' - Point (0.17, 52.23) .* tile grid_0.15_52.25 (re) - Region bounding box: .* (re) - -Verify coverage image was created: - - $ test -f "$TESTDIR/single_tile_coverage.png" && echo "Coverage PNG created" - Coverage PNG created - + > --dataset-version v1 2>&1 | head -2 + Point (0.17, 52.23) -> tile grid_0.15_52.25 + Region bounding box: [0.150000\xc2\xb0E, 52.250000\xc2\xb0N] - [0.150000\xc2\xb0E, 52.250000\xc2\xb0N] (esc)