Conversation
This reverts commit 424e2ba.
This reverts commit e853bb7.
This reverts commit 688000f.
Add sparse tile option to merge config / remove output_quantized_alpha
- merger.py: remove double height_adjustment application from _merge_tiles (was already applied in _decode_tile, causing doubled elevation offsets) - database.py: INSERT OR REPLACE to handle duplicate tiles on re-run - test_cli.py: skip test_cli_good_elev (GeoTIFF output mode removed); use MBTilesDatabase for test_merge_command sources (was empty files) - test_encoders.py: use np.allclose(atol=0.5) for roundtrip tests (terrarium ignores interval; float32 precision causes ~0.15 max error) - test_mbtiler.py: skip test_RGBtiler_format_fails (format validation moved to CLI click.Choice) - test_merger.py: fix _merger() helper to default num_sources=2; use _WORLD_BOUNDS to avoid mercantile InvalidLatitudeError at lat=±90
- merger.py: fix source priority — mask should be np.isnan(result) so higher-priority (first) sources win; previous mask ~np.isnan(resampled_data) caused every subsequent source to overwrite earlier ones (last wins bug) - cli.py: fix resampling choice 'gaussian' -> 'gauss' to match rasterio's Resampling enum member name; tests correctly pass 'gauss'
- test/download_fixtures.py: script to fetch z0-z2 tiles from both tile servers into MBTiles fixture files (auto-decompresses gzip responses) - test/fixtures/gebco_sample.mbtiles: 21 WebP tiles from ocean-rgb endpoint - test/fixtures/jaxa_sample.mbtiles: 21 WebP tiles from jaxa_terrainrgb_webp endpoint - test/test_merger.py: TestLiveMerge (6 tests) mirroring merge_bathymetry.json: JAXA land (priority 1) over GEBCO bathymetry (priority 2), z0-z2, webp output - produces output with tiles at all 3 zoom levels - output tiles are valid WebP RGB 512x512 images - JAXA land takes priority (positive elevation in East Asia z=2/2/1 tile) - sparse_tiles mode produces <= full mode tile count - output_nodata config key accepted without error Tests skip automatically when fixture files are absent.
- Add test/expected/z{0,2}_x*_y*.png: lossless PNG reference tiles generated
by running the GEBCO+JAXA merger once and frozen as ground truth
- Add test/generate_expected_tiles.py: regeneration script to re-run whenever
merger behaviour is intentionally changed
- Add TestLiveMerge.test_output_matches_expected_tiles: decodes output tiles to
elevation arrays and asserts np.allclose(atol=1.0) against references
- Update _EXPECTED_TILES_DIR to point to existing test/expected/ convention
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds MBTiles/raster merge functionality and sparse tile support to rio-rgbify, along with a significant refactor of the core processing pipeline, new output format options, an improved CLI command structure, a proper MBTiles database abstraction, a new image encoding module, and a full GitHub Actions CI suite.
New Features
mergeCommand — Merge Multiple Terrain Sources into One MBTilesA new
mergeCLI command reads a JSON configuration file and blends multiple Terrain-RGB MBTiles or raster DEM sources into a single output MBTiles file.Key capabilities:
mask_values(e.g.[0, -1, -10000]) so ocean-only tiles don't stomp land tilesTerrainRGBMerger) — merges encoded Terrain-RGB tiles from existing MBTiles files; supports bothmapboxandterrariumencodingRasterRGBMerger) — merges raw DEM GeoTIFFs directly into the output MBTiles with automatic reprojectionnearest,bilinear,cubic,cubic_spline,lanczos,average,mode,gaussmapboxorterrariumfor the output tilespngorwebpbounds: [west, south, east, north]restricts generated tiles to a geographic regionoutput_nodata— fill pixels with no valid source data with a fixed elevation value instead of leaving them NaNExample
merge_example.json:{ "sources": [ { "path": "/path/to/bathymetry.mbtiles", "encoding": "mapbox", "height_adjustment": -5.0 }, { "path": "/path/to/base_terrain.mbtiles", "encoding": "mapbox", "mask_values": [-1, 0] }, { "path": "/path/to/secondary_terrain.mbtiles", "encoding": "terrarium" } ], "output_path": "/path/to/output.mbtiles", "output_encoding": "mapbox", "output_format": "webp", "resampling": "bilinear", "min_zoom": 2, "max_zoom": 10, "bounds": [-10, 10, 20, 50] }Sparse Tiles Mode
Both
mergeandrgbifysupport"sparse_tiles": true. When enabled:Refactored & Improved Modules
mbtiler.py— Complete Rewrite_tile_worker(usingriomucho) with a standaloneprocess_tilefunction compatible with Python'smultiprocessingspawncontext (required on macOS/Windows)multiprocessing.get_context("spawn")for reliability across platforms--batch-size) to avoid excess memory use on large datasetsOperationalError(database locked) with exponential backoff--gaussian-blur-sigma) applied post-reprojection to reduce artefacts at tile seams; sigma scales automatically with zoom level--resamplingoption replaces the hardcodedbilinear--batch-sizeoption for explicit control over memory/throughput trade-offriomuchoandrasterio.rio.options.creation_optionsscripts/cli.py— Multi-Command Group@click.commandto a@click.group(main_group) with two subcommands:rgbifyandmergergbifygains--batch-sizeand--resamplingoptionsmergereads all configuration from a JSON file (--config)--verbose/-vlogging flag to both commandsimage.py— New Image Encoding Module (replacesencoders.py)ImageEncoder.data_to_rgb()— encodes float elevation arrays tomapboxorterrariumRGBImageEncoder.save_rgb_to_bytes()— saves to PNG or WebP bytes via PillowImageFormatenum (PNG,WEBP)database.py— New MBTiles Database AbstractionMBTilesDatabasecontext manager wraps SQLite MBTiles creationtiles_shallow/tiles_data/tilesview schema (de-duplicated tile data storage)insert_tile_with_retry()with exponential backoff for concurrent write safetyadd_metadata()for writing MBTiles metadata rowsINSERT OR REPLACEto safely re-run without UNIQUE constraint violationsTesting
New Test Suite (
test/test_merger.py— 32+ tests across 6 classes)TestTerrainRGBMergerMergeTilesTestTerrainRGBMergerIntegrationTestRasterRGBMergerExtractTileTestRasterRGBMergerGetMaxZoomTestRasterRGBMergerIntegrationTestMergeCLImergecommand: basic, sparse, height adjustment, missing config, raster type, terrarium encodingTestLiveMergeLive Test Fixtures (
test/fixtures/)gebco_sample.mbtiles— 21 WebP tiles (z=0–2), GEBCO 2024 global bathymetry, 512×512jaxa_sample.mbtiles— 21 WebP tiles (z=0–2), JAXA AW3D30 2024 land elevation, 512×512test/download_fixtures.py— re-download script (handles server-side gzip decompression)Reference Output Comparison (
test/expected/)z0_x0_y0.png,z2_x2_y1.png,z2_x0_y2.png— lossless PNG reference tiles from a known-good merge runtest/generate_expected_tiles.py— regeneration script; run when merge behaviour is intentionally changedTestLiveMerge.test_output_matches_expected_tiles— decodes both reference and live output to elevation arrays and assertsnp.allclose(atol=1.0 m)Updated Existing Tests
test/test_encoders.py— roundtrip tolerance relaxed toatol=0.5(float precision); coversmapboxandterrariumtest/test_mbtiler.py— format-validation test skipped (validation moved toclick.Choice)test/test_cli.py— fully updated for new multi-command group;test_merge_commanduses real MBTiles databasesGitHub Actions CI (
.github/workflows/tests.yml) — Newubuntu-latestDependencies
scipyscipy.ndimage.gaussian_filterPillowimage.pypsutilmbtiler.pymercantileriomuchomultiprocessingpoolBreaking Changes
rgbifycommand no longer supports GeoTIFF output (.tifdestination) — output is MBTiles onlyencoders.py(data_to_rgb) is replaced byimage.py(ImageEncoder.data_to_rgb) — any code importing directly fromrio_rgbify.encoderswill need updatingmain_group);rgbifyis a subcommand (rio rgbify ...still works), andrio merge ...is new