Stitch image tiles into larger composite TIFs

Overview

untiler

Build Status Coverage Status

Utility to take a directory of {z}/{x}/{y}.(jpg|png) tiles, and stitch into a scenetiff (tif w/ exact merc tile bounds). Future versions will support fast indexed reading directly from tar archives.

Install

make a virtual env + activate, then:

pip install untiler

Dev installation

git clone [email protected]:mapbox/untiler.git

cd untiler

pip install -e .

Usage

Usage: untiler [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  inspectdir
  streamdir
  streammbtiles

streamdir

Given a directory of tiles + a read template, mosaic into tifs at a lower parent "composite" zoom extent

untiler streamdir [OPTIONS] INPUT_DIR OUTPUT_DIR

-c, --compositezoom INTEGER  Tile size to mosaic into [default=13]
-z, --maxzoom INTEGER        Force a maxzom [default=max in each
                           compositezoom area]
-l, --logdir TEXT            Location for log files [default=None]
-t, --readtemplate TEXT      File path template
                           [default='jpg/{z}/{x}/{y}.jpg']
-s, --scenetemplate TEXT     Template for output scenetif filenames
                           [default='{z}-{x}-{y}-tile.tif']
-w, --workers INTEGER        Number of workers in the processing pool
                           [default=4]
-x, --no-fill                Don't fill in with lower zooms
-r, --tile-resolution       Size of input tiles for eg 256, 512 etc
--help                       Show this message and exit.

streammbtiles

Mosaic an mbtiles into tifs of "composite" zoom extent

untiler streammbtiles [OPTIONS] MBTILES OUTPUT_DIR

Options:
  --co NAME=VALUE              Driver specific creation options.See the
                               documentation for the selected output driver
                               for more information.
  -c, --compositezoom INTEGER  Tile size to mosaic into [default=13]
  -z, --maxzoom INTEGER        Force a maxzom [default=max in each
                               compositezoom area]
  -s, --scenetemplate TEXT     Template for output scenetif filenames
                               [default='{z}-{x}-{y}-tile.tif']
  -w, --workers INTEGER        Number of workers in the processing pool
                               [default=4]
  -x, --no-fill                Don't fill in with lower zooms
  --help                       Show this message and exit.

inspectdir

Stream [x, y, z]s of a directory

untiler inspectdir [OPTIONS] INPUT_DIR

Options:
-z, --zoom INTEGER  Zoom to inspect [default = all]
--help              Show this message and exit.

Outputs a line-delimited stream of tile [x, y, z]s; useful to pipe into mercantile shapes to visualize geometry:

untiler inspectdir <dir> -z 19 | mercantile shapes | fio collect | geojsonio
Comments
  • KeyError: '\\d'

    KeyError: '\\d'

    Hi, I recently installed untiler. When I run any of the untiler commands, I get the error attached below. I am using Python 3.9.1.

    I'm not sure if it's an issue with the python version, I am currently trying to downgrade my python version, and will update this issue accordingly.

    in __exit__
    Traceback (most recent call last):
      File "/usr/lib/python3.9/sre_parse.py", line 1039, in parse_template
        this = chr(ESCAPES[this][1])
    KeyError: '\\d'
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/home/c_abraham/.local/bin/untiler", line 8, in <module>
        sys.exit(cli())
      File "/usr/lib/python3.9/site-packages/click/core.py", line 829, in __call__
        return self.main(*args, **kwargs)
      File "/usr/lib/python3.9/site-packages/click/core.py", line 782, in main
        rv = self.invoke(ctx)
      File "/usr/lib/python3.9/site-packages/click/core.py", line 1259, in invoke
        return _process_result(sub_ctx.command.invoke(sub_ctx))
      File "/usr/lib/python3.9/site-packages/click/core.py", line 1066, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "/usr/lib/python3.9/site-packages/click/core.py", line 610, in invoke
        return callback(*args, **kwargs)
      File "/home/c_abraham/.local/lib/python3.9/site-packages/untiler/scripts/cli.py", line 53, in streammbtiles
        untiler.stream_dir(input_tile_dir, output_dir, compositezoom, maxzoom, None, readtemplate, scenetemplate, workers, creation_options, no_fill)
      File "/home/c_abraham/.local/lib/python3.9/site-packages/untiler/__init__.py", line 225, in stream_dir
        template, readTemplate, separator = tile_utils.parse_template("%s/%s" % (inputDir, read_template))
      File "/home/c_abraham/.local/lib/python3.9/site-packages/untiler/scripts/tile_utils.py", line 151, in parse_template
        return valPattern.sub('\d+', template), valPattern.sub('%s', template), separator[0]
      File "/usr/lib/python3.9/re.py", line 327, in _subx
        template = _compile_repl(template, pattern)
      File "/usr/lib/python3.9/re.py", line 318, in _compile_repl
        return sre_parse.parse_template(repl, pattern)
      File "/usr/lib/python3.9/sre_parse.py", line 1042, in parse_template
        raise s.error('bad escape %s' % this, len(this))
    re.error: bad escape \d at position 0
    
    opened by abrac 5
  • Fix tests, update Rasterio

    Fix tests, update Rasterio

    Changes:

    • Replaces libgdal1h with libgdal1i in the Travis build
    • Updates rasterio from 1.0a8 to 1.1.2
    • Instead of checking exit codes, tests now explicitly check for the type of exception raised
    • Fixes #24
    • Drops Python 2.7 Travis builds
    opened by bhavika 4
  • adding compression selection handling

    adding compression selection handling

    Adds:

    • Input of compress and other --cos
    • An option to not fill w/ lower zooms -x
    • When an input tiles is RGBA, use the alpha band
    • Adds streaming directly from mbtiles

    cc @camillacaros

    opened by dnomadb 4
  • sudo: false with rasterio deps

    sudo: false with rasterio deps

    As per chat w/ @yhahn (https://mapbox.slack.com/archives/satellite/p1441040393007215 + many other convos), we want to able to have modules such as this testable on travis w/ sudo: false. However, I am not sure how to accomplish this on a repo that uses rasterio, which has dependencies that are installed via sudo apt-get install ....

    @sgillies can you help guide me in this?

    opened by dnomadb 2
  • Support for 512x512 tiles: ValueError: Source shape is inconsistent with given indexes

    Support for 512x512 tiles: ValueError: Source shape is inconsistent with given indexes

    I am having trouble getting untiler to work with a directory of 512x512 tiles. Support for this does not seem to be documented, but it sounds like a typical use case given Mapbox's 512x512 default in Studio. Is this supported? Is it a rasterio issue, like this?

    This is what happens when trying to untile with 512x512 images. (An equivalent run with 256x256 tiles succeeds.)

    $ untiler streamdir -t {z}/{x}/{y}.png ./tiles ./untiles 
    /usr/local/lib/python3.6/site-packages/rasterio/__init__.py:240: NotGeoreferencedWarning: Dataset has no geotransform set. Default transform will be applied (Affine.identity())
      s = DatasetReader(fp, driver=driver, **kwargs)
    /usr/local/lib/python3.6/site-packages/rasterio/__init__.py:240: NotGeoreferencedWarning: Dataset has no geotransform set. Default transform will be applied (Affine.identity())
      s = DatasetReader(fp, driver=driver, **kwargs)
    tiles/18/66179/97359.png errored
    tiles/18/66179/97403.png errored
    multiprocessing.pool.RemoteTraceback: 
    """
    Traceback (most recent call last):
      File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/pool.py", line 119, in worker
        result = (True, func(*args, **kwds))
      File "/usr/local/lib/python3.6/site-packages/untiler/__init__.py", line 201, in streaming_tile_worker
        raise e
      File "/usr/local/lib/python3.6/site-packages/untiler/__init__.py", line 192, in streaming_tile_worker
        dst.write(imdata, window=window)
      File "rasterio/_io.pyx", line 1234, in rasterio._io.DatasetWriterBase.write
    ValueError: Source shape is inconsistent with given indexes
    """
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "/usr/local/bin/untiler", line 11, in <module>
        sys.exit(cli())
      File "/usr/local/lib/python3.6/site-packages/click/core.py", line 722, in __call__
        return self.main(*args, **kwargs)
      File "/usr/local/lib/python3.6/site-packages/click/core.py", line 697, in main
        rv = self.invoke(ctx)
      File "/usr/local/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
        return _process_result(sub_ctx.command.invoke(sub_ctx))
      File "/usr/local/lib/python3.6/site-packages/click/core.py", line 895, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "/usr/local/lib/python3.6/site-packages/click/core.py", line 535, in invoke
        return callback(*args, **kwargs)
      File "/usr/local/lib/python3.6/site-packages/untiler/scripts/cli.py", line 32, in streamdir
        untiler.stream_dir(input_dir, output_dir, compositezoom, maxzoom, logdir, readtemplate, scenetemplate, workers, creation_options, no_fill)
      File "/usr/local/lib/python3.6/site-packages/untiler/__init__.py", line 255, in stream_dir
        for p in pool.imap_unordered(streaming_tile_worker, tiler.get_sub_tiles(allTiles, superTiles)):
      File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/pool.py", line 735, in next
        raise value
    ValueError: Source shape is inconsistent with given indexes
    
    opened by waissbluth 1
  • Tests broken on master

    Tests broken on master

    Tests fail on Python 3.6 - see this Travis run.

        def test_extract_mbtiles():
            with TestTiler() as tt:
                testpath = tt.path
                testmbtiles = os.path.join(os.path.dirname(__file__), 'fixtures/testtiles.mbtiles')
                runner = CliRunner()
                result = runner.invoke(cli, [
                    'streammbtiles', testmbtiles, testpath, '-z', '16', '-x', '-s',
                    '{z}-{x}-{y}-mbtiles.tif', '--co', 'compress=lzw'])
                assert result.exit_code == 0
                expected_checksums = [[13858, 8288, 51489, 31223], [17927, 52775, 411, 9217]]
                for o, c in zip(result.output.rstrip().split('\n'), expected_checksums):
                    with rio.open(o) as src:
                        checksums = [src.checksum(i) for i in src.indexes]
    >                   assert checksums == c
    E                   assert [17927, 52775, 411, 9217] == [13858, 8288, 51489, 31223]
    E                     At index 0 diff: 17927 != 13858
    E                     Use -v to get the full diff
    

    Noticed this while working on the autodeploy branch. Initially thought this was failing due to changes I'd made, but I think this is some sort of config/dependency rot that's happening otherwise.

    bug 
    opened by jqtrde 1
  • Inspectar

    Inspectar

    Proof of concept to show viability of: (a) indexing tar (b) accessing data from the indexed offsets

    This would unlock untiling without having to untar the tar.

    cc @jacquestardie @perrygeo

    opened by dnomadb 1
  • initial python3 changes [WIP]

    initial python3 changes [WIP]

    resolves #18

    TODO

    • [x] get a new release of mbutil to pypi, semi-blocked by https://github.com/mapbox/mbutil/issues/83 ( it doesn't technically affect untiler's behavior but we can't say mbutils works with py36 until we fix it)
    opened by perrygeo 1
  • Python 3.6 compatibility

    Python 3.6 compatibility

    A few things to change (that I see now):

    • A few integer division changes: https://github.com/mapbox/untiler/blob/master/untiler/scripts/tile_utils.py#L49
    • Bigger prob: mbutil is (a lot farther) from 3.5 https://github.com/mapbox/untiler/blob/master/untiler/scripts/mbtiles_extract.py#L5. I think removing it entirely and reading tiles using sqlite3 is preferable.

    cc @perrygeo

    opened by dnomadb 0
  • Revisit command line options

    Revisit command line options

    At the risk of :bike: :house_with_garden: ... @dnomadb we have some conflicts with traditional options (-c for one) and I'd like to suggest --foo-bar instead of --foobar.

    opened by sgillies 0
  • Use rasterio for tile reading

    Use rasterio for tile reading

    Using rasterio for input tile reading should be faster for reading input images. To implement:

    • [x] Use syntax:

       with rasterio.drivers():
           with rasterio.open(...) as src:
               imdata = src.read()
      
    • [x] Update tiler to handle (depth, height, width) arrays vs (height, width, depth) and (height, depth) arrays

    cc @sgillies

    opened by dnomadb 0
  • How to get this to work with QGIS

    How to get this to work with QGIS

    So it doesn't seem to work with QGIS Tiles, and the things it works with output nonsense. image these were originally grey, and you can see they didn't even stitch properly, any insight on how to make this work?

    opened by GodPhase777 0
Releases(0.0.4)
Owner
Mapbox
Mapbox is the location data platform for mobile and web applications. We're changing the way people move around cities and explore our world.
Mapbox
:earth_asia: Python Geocoder

Python Geocoder Simple and consistent geocoding library written in Python. Table of content Overview A glimpse at the API Forward Multiple results Rev

Denis 1.5k Jan 02, 2023
Manipulation and analysis of geometric objects

Shapely Manipulation and analysis of geometric objects in the Cartesian plane. Shapely is a BSD-licensed Python package for manipulation and analysis

3.1k Jan 03, 2023
Python script that can be used to generate latitude/longitude coordinates for GOES-16 full-disk extent.

goes-latlon Python script that can be used to generate latitude/longitude coordinates for GOES-16 full-disk extent. 🌎 🛰️ The grid files can be acces

Douglas Uba 3 Apr 06, 2022
GebPy is a Python-based, open source tool for the generation of geological data of minerals, rocks and complete lithological sequences.

GebPy is a Python-based, open source tool for the generation of geological data of minerals, rocks and complete lithological sequences. The data can be generated randomly or with respect to user-defi

Maximilian Beeskow 16 Nov 29, 2022
How to use COG's (Cloud optimized GeoTIFFs) with Rasterio

How to use COG's (Cloud optimized GeoTIFFs) with Rasterio According to Cogeo.org: A Cloud Opdtimized GeoTIFF (COG) is a regular GeoTIFF file, aimed at

Marvin Gabler 8 Jul 29, 2022
When traveling in the backcountry during winter time, updating yourself on current and recent weather data is important to understand likely avalanche danger.

Weather Data When traveling in the backcountry during winter time, updating yourself on current and recent weather data is important to understand lik

Trevor Allen 0 Jan 02, 2022
Processing and interpolating spatial data with a twist of machine learning

Documentation | Documentation (dev version) | Contact | Part of the Fatiando a Terra project About Verde is a Python library for processing spatial da

Fatiando a Terra 468 Dec 20, 2022
The geospatial toolkit for redistricting data.

maup maup is the geospatial toolkit for redistricting data. The package streamlines the basic workflows that arise when working with blocks, precincts

Metric Geometry and Gerrymandering Group 60 Dec 05, 2022
A utility to search, download and process Landsat 8 satellite imagery

Landsat-util Landsat-util is a command line utility that makes it easy to search, download, and process Landsat imagery. Docs For full documentation v

Development Seed 681 Dec 07, 2022
Calculate & view the trajectory and live position of any earth-orbiting satellite

satellite-visualization A cross-platform application to calculate & view the trajectory and live position of any earth-orbiting satellite in 3D. This

Space Technology and Astronomy Cell - Open Source Society 3 Jan 08, 2022
Mmdb-server - An open source fast API server to lookup IP addresses for their geographic location

mmdb-server mmdb-server is an open source fast API server to lookup IP addresses

Alexandre Dulaunoy 67 Nov 25, 2022
Python tools for geographic data

GeoPandas Python tools for geographic data Introduction GeoPandas is a project to add support for geographic data to pandas objects. It currently impl

GeoPandas 3.5k Jan 03, 2023
Earthengine-py-notebooks - A collection of 360+ Jupyter Python notebook examples for using Google Earth Engine with interactive mapping

earthengine-py-notebooks A collection of 360+ Jupyter Python notebook examples for using Google Earth Engine with interactive mapping Contact: Qiushen

Qiusheng Wu 1.1k Dec 29, 2022
Starlite-tile38 - Showcase using Tile38 via pyle38 in a Starlite application

Starlite-Tile38 Showcase using Tile38 via pyle38 in a Starlite application. Repo

Ben 8 Aug 07, 2022
Stitch image tiles into larger composite TIFs

untiler Utility to take a directory of {z}/{x}/{y}.(jpg|png) tiles, and stitch into a scenetiff (tif w/ exact merc tile bounds). Future versions will

Mapbox 38 Dec 16, 2022
python toolbox for visualizing geographical data and making maps

geoplotlib is a python toolbox for visualizing geographical data and making maps data = read_csv('data/bus.csv') geoplotlib.dot(data) geoplotlib.show(

Andrea Cuttone 976 Dec 11, 2022
Use Mapbox GL JS to visualize data in a Python Jupyter notebook

Location Data Visualization library for Jupyter Notebooks Library documentation at https://mapbox-mapboxgl-jupyter.readthedocs-hosted.com/en/latest/.

Mapbox 620 Dec 15, 2022
A ninja python package that unifies the Google Earth Engine ecosystem.

A Python package that unifies the Google Earth Engine ecosystem. EarthEngine.jl | rgee | rgee+ | eemont GitHub: https://github.com/r-earthengine/ee_ex

47 Dec 27, 2022
Tools for the extraction of OpenStreetMap street network data

OSMnet Tools for the extraction of OpenStreetMap (OSM) street network data. Intended to be used in tandem with Pandana and UrbanAccess libraries to ex

Urban Data Science Toolkit 47 Sep 21, 2022
Automated download of LANDSAT data from USGS website

LANDSAT-Download It seems USGS has changed the structure of its data, and so far, I have not been able to find the direct links to the products? Help

Olivier Hagolle 197 Dec 30, 2022