A light-weight, versatile XYZ tile server, built with Flask and Rasterio :earth_africa:

Overview

Build Status Documentation Status codecov GitHub release PyPI release License Python versions

Logo

Terracotta is a pure Python tile server that runs as a WSGI app on a dedicated webserver or as a serverless app on AWS Lambda. It is built on a modern Python 3.6 stack, powered by awesome open-source software such as Flask, Zappa, and Rasterio.

Read the docs | Explore the API | Satlas, powered by Terracotta

Why Terracotta?

  • It is trivial to get going. Got a folder full of cloud-optimized GeoTiffs in different projections you want to have a look at in your browser? terracotta serve -r {name}.tif and terracotta connect localhost:5000 get you there.
  • We make minimal assumptions about your data, so you stay in charge. Keep using the tools you know and love to create and organize your data, Terracotta serves it exactly as it is.
  • Serverless deployment is a first-priority use case, so you don’t have to worry about maintaining or scaling your architecture.
  • Terracotta instances are self-documenting. Everything the frontend needs to know about your data is accessible from only a handful of API endpoints.

The Terracotta workflow

1. Optimize raster files

$ ls -lh
total 1.4G
-rw-r--r-- 1 dimh 1049089 231M Aug 29 16:45 S2A_20160724_135032_27XVB_B02.tif
-rw-r--r-- 1 dimh 1049089 231M Aug 29 16:45 S2A_20160724_135032_27XVB_B03.tif
-rw-r--r-- 1 dimh 1049089 231M Aug 29 16:46 S2A_20160724_135032_27XVB_B04.tif
-rw-r--r-- 1 dimh 1049089 231M Aug 29 16:56 S2A_20170831_171901_25XEL_B02.tif
-rw-r--r-- 1 dimh 1049089 231M Aug 29 16:57 S2A_20170831_171901_25XEL_B03.tif
-rw-r--r-- 1 dimh 1049089 231M Aug 29 16:57 S2A_20170831_171901_25XEL_B04.tif

$ terracotta optimize-rasters *.tif -o optimized/

Optimizing rasters: 100%|██████████████████████████| [05:16<00:00, file=S2A_20170831_...25XEL_B04.tif]

2. Create a database from file name pattern

$ terracotta ingest optimized/S2A_{date}_{}_{tile}_{band}.tif -o greenland.sqlite
Ingesting raster files: 100%|███████████████████████████████████████████| 6/6 [00:49<00:00,  8.54s/it]

3. Serve it up

$ terracotta serve -d greenland.sqlite
 * Serving Flask app "terracotta.server" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://localhost:5000/ (Press CTRL+C to quit)

4. Explore the running server

Manually

You can use any HTTP-capable client, such as curl.

$ curl localhost:5000/datasets?tile=25XEL
{"page":0,"limit":100,"datasets":[{"date":"20170831","tile":"25XEL","band":"B02"},{"date":"20170831","tile":"25XEL","band":"B03"},{"date":"20170831","tile":"25XEL","band":"B04"}]}

Modern browsers (e.g. Chrome or Firefox) will render the JSON as a tree.

Interactively

Terracotta also includes a web client. You can start the client (assuming the server is running at http://localhost:5000) using

$ terracotta connect localhost:5000
 * Serving Flask app "terracotta.client" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5100/ (Press CTRL+C to quit)

Then open the client page (http://127.0.0.1:5100/ in this case) in your browser.

preview

Development

We gladly accept bug reports and pull requests via GitHub. For your code to be useful, make sure that it is covered by tests and that it satisfies our linting practices (via mypy and flake8).

To run the tests, just install the necessary dependencies via

$ pip install -e .[test]

Then, you can run

$ pytest

from the root of the repository.

Comments
  • Flask is erroring out with BrokenProcessPool

    Flask is erroring out with BrokenProcessPool

    Hi there!

    We have started using Terracotta in our K8S infrastructure on production. Basically we are serving the WSGI flask application (terracotta.server.app:app) using gunicorn alongside with an internal gRPC server which is taking internal requests and queries the terracotta HTTP endpoint for a singleband tile and returns it as a bytes object.

    However, while the first 10-50 requests work fine, I now get this error from terracotta afterwards:

     [-] Exception on /singleband/some_path/25/10/506/313.png [GET]
    Traceback (most recent call last):
      File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 2447, in wsgi_app
        response = self.full_dispatch_request()
      File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1952, in full_dispatch_request
        rv = self.handle_user_exception(e)
      File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1821, in handle_user_exception
        reraise(exc_type, exc_value, tb)
      File "/usr/local/lib/python3.8/dist-packages/flask/_compat.py", line 39, in reraise
        raise value
      File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1950, in full_dispatch_request
        rv = self.dispatch_request()
      File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1936, in dispatch_request
        return self.view_functions[rule.endpoint](**req.view_args)
      File "/usr/local/lib/python3.8/dist-packages/terracotta/server/flask_api.py", line 49, in inner
        return fun(*args, **kwargs)
      File "/usr/local/lib/python3.8/dist-packages/terracotta/server/singleband.py", line 121, in get_singleband
        return _get_singleband_image(keys, tile_xyz)
      File "/usr/local/lib/python3.8/dist-packages/terracotta/server/singleband.py", line 166, in _get_singleband_image
        image = singleband(parsed_keys, tile_xyz=tile_xyz, **options)
      File "/usr/lib/python3.8/contextlib.py", line 75, in inner
        return func(*args, **kwds)
      File "/usr/local/lib/python3.8/dist-packages/terracotta/handlers/singleband.py", line 43, in singleband
        tile_data = xyz.get_tile_data(
      File "/usr/local/lib/python3.8/dist-packages/terracotta/xyz.py", line 44, in get_tile_data
        return driver.get_raster_tile(
      File "/usr/local/lib/python3.8/dist-packages/terracotta/drivers/base.py", line 20, in inner
        return fun(self, *args, **kwargs)
      File "/usr/local/lib/python3.8/dist-packages/terracotta/drivers/raster_base.py", line 557, in get_raster_tile
        future = executor.submit(retrieve_tile)
      File "/usr/lib/python3.8/concurrent/futures/process.py", line 629, in submit
        raise BrokenProcessPool(self._broken)
    concurrent.futures.process.BrokenProcessPool: A child process terminated abruptly, the process pool is not usable anymore
    

    The worst thing about this is that the flask application doesn't seem to actually error out. Instead, every subsequent request throws the error above. That's problematic as K8s then doesn't know that the pod needs to be restarted. However, on a longer sight, this also means that we could never cater for the amount of requests (around 50 RPS) we have using terracotta if this persists.

    Has anyone encountered this yet?

    opened by rico-ci 26
  • Getting a 500 when using the newest version of Rasterio (1.0.22)

    Getting a 500 when using the newest version of Rasterio (1.0.22)

    When deploying a Lambda function through Zappa, using the newest version of Rasterio (1.0.22), we get a 500 for some tiles, while others load fine.

    When reverting back to Rasterio 1.0.13 everything works fine.

    zappa tail gives the following:

    [1554888957364] [ERROR] 2019-04-10T09:35:57.326Z b24c3c65-85ed-4390-a18b-c0cf347feec0 Exception on /rgb/italy/2018/7/70/47.png [GET]
    Traceback (most recent call last):
      File "rasterio/_base.pyx", line 213, in rasterio._base.DatasetBase.__init__
      File "rasterio/_shim.pyx", line 64, in rasterio._shim.open_dataset
      File "rasterio/_err.pyx", line 205, in rasterio._err.exc_wrap_pointer
    rasterio._err.CPLE_OpenFailedError: '/vsis3/italy-composite/rasters/italy_2018_red.tif' not recognized as a supported file format.
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/var/task/terracotta/drivers/raster_base.py", line 464, in _get_raster_tile
      src = es.enter_context(rasterio.open(path))
      File "/var/task/rasterio/env.py", line 423, in wrapper
      return f(*args, **kwds)
      File "/var/task/rasterio/__init__.py", line 216, in open
      s = DatasetReader(path, driver=driver, **kwargs)
      File "rasterio/_base.pyx", line 215, in rasterio._base.DatasetBase.__init__
    rasterio.errors.RasterioIOError: '/vsis3/italy-composite/rasters/italy_2018_red.tif' not recognized as a supported file format.
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/var/task/flask/app.py", line 2292, in wsgi_app
      response = self.full_dispatch_request()
      File "/var/task/flask/app.py", line 1815, in full_dispatch_request
      rv = self.handle_user_exception(e)
      File "/var/task/flask/app.py", line 1718, in handle_user_exception
      reraise(exc_type, exc_value, tb)
      File "/var/task/flask/_compat.py", line 35, in reraise
      raise value
      File "/var/task/flask/app.py", line 1813, in full_dispatch_request
      rv = self.dispatch_request()
      File "/var/task/flask/app.py", line 1799, in dispatch_request
      return self.view_functions[rule.endpoint](**req.view_args)
      File "/var/task/terracotta/server/flask_api.py", line 50, in inner
      return fun(*args, **kwargs)
      File "/var/task/terracotta/server/rgb.py", line 85, in get_rgb
      return _get_rgb_image(keys, tile_xyz=tile_xyz)
      File "/var/task/terracotta/server/rgb.py", line 135, in _get_rgb_image
      some_keys, rgb_values, stretch_ranges=stretch_ranges, tile_xyz=tile_xyz, **options
      File "/var/lang/lib/python3.6/contextlib.py", line 52, in inner
      return func(*args, **kwds)
      File "/var/task/terracotta/handlers/rgb.py", line 85, in rgb
      band_data = band_data_future.result()
      File "/var/lang/lib/python3.6/concurrent/futures/_base.py", line 432, in result
      return self.__get_result()
      File "/var/lang/lib/python3.6/concurrent/futures/_base.py", line 384, in __get_result
      raise self._exception
      File "/var/lang/lib/python3.6/concurrent/futures/thread.py", line 56, in run
      result = self.fn(*self.args, **self.kwargs)
      File "/var/task/cachetools/__init__.py", line 87, in wrapper
      v = method(self, *args, **kwargs)
      File "/var/lang/lib/python3.6/contextlib.py", line 52, in inner
      return func(*args, **kwds)
      File "/var/task/terracotta/drivers/raster_base.py", line 466, in _get_raster_tile
      raise IOError('error while reading file {}'.format(path))
    OSError: error while reading file s3://italy-composite/rasters/italy_2018_red.tif
    
    bug 
    opened by vlro 24
  • daskify metadata computation

    daskify metadata computation

    We have a project where we want to use Terracotta to serve up some huge watermasks. There's no way we can load an entire file into memory and do computations (a 32gb machine fails when computing the metadata), this is of course no problem for serving the files, as they are cloud-optimized.

    However, the metadata computation when creating the database still assumes that the entire file fits into memory and then some. So we should use Dask to chunk the computations when sizes exceed the memory limit.

    To speed up the common case (where files fit into memory) we could do this only when a MemoryError is thrown. Or we could set a memory limit that we think is reasonable and always chunk the files such that we never exceed that and then maybe decrease it if we hit a MemoryError. Thoughts?

    enhancement 
    opened by mrpgraae 23
  • Sqlalchemy compositional

    Sqlalchemy compositional

    Implement the compositional TerracottaDriver structure proposed in https://github.com/DHI-GRAS/terracotta/pull/240#issuecomment-1013688976.

    In a separate PR (going into #240) for better diffs.

    opened by nickeopti 20
  • Sqlalchemy

    Sqlalchemy

    ~~Draft, WIP, PR. Just made to keep track of things, and for the tests to run. Can be ignored for now.~~

    Edit: PR for improving the structure and codebase of the drivers. Was originally just for replacing the database specific code with a more general SQLAlchemy implementation. But has now also turned into a bigger, more general refactor of the entire driver code.

    opened by nickeopti 19
  • Code Review

    Code Review

    Great job so far! Here's the things I stumbled upon:

    Documentation

    • Be consistent: timestep vs timestamp
    • I don't think we need to explain the layout of the option files; an example is sufficient.
    • I think it is tremendously helpful to see example responses of the API calls early on.

    Configuration

    • Why split path and regex? Just have path_regex.
    • Not sure about the yes/no syntax for boolean settings. How does e.g. Apache or Nginx handle that?

    CLI

    • Config path could be a positional argument
    • Please wrap the config path in os.expanduser for us poor windows souls
    • 💡: Accept rasters from the command line to quickly serve up anything: terracotta *.tif (then open a leaflet map in the browser, with the data already added as a layer, for the ultimate wow effect :smile:)

    API

    • I don't think the API queries should include terracotta. You would either run this as a Flask app on its own port, or configure the proxy in your webserver.
    • Using a non-timestep API endpoint for a timestepped dataset causes an uncaught exception (500 server error; should give "Bad Request" or so)

    I'll have a look at the actual code and do some profiling later. I'll update this issue with my findings.

    opened by dionhaefner 18
  • Added support for predefined colormaps with alpha channel and an example

    Added support for predefined colormaps with alpha channel and an example

    The usecase that lead to this change is overlaying cloud coverage. See screenshot below. Cloud coverage information is extrapolated from GOES-16 ABI channel 13 and displayed on top of Bing Aerial Maps. Allowing a fourth channel in the predefined color maps allows us to have a varying transparency without sending a bulky json custom colormap with each api request. The varying transparency gives us the nice feathered edges for the clouds. image

    opened by brianpojo56 15
  • Parallel raster optimisation

    Parallel raster optimisation

    Use a multiprocessing.Pool to optimize raster files in parallel (each raster file is applied individually). Closes #55

    Currently uses multiprocessing.cpu_count() number of threads. This seems to be the number of logical (hyper-threading) cores: I'm unsure whether the number of physical cores might be preferable.

    Currently has some caveats: 1: The sub-progress bars are removed, such that only the overall progress is shown. (And the filename postfix is now showing the just-completed file, rather than the currently-being-processed file).

    2: When raising an exception because optimized files already exists (and neither --overwrite nor --skip-existing flags are set), the entire trace-stack is now shown, where it previously just showed a nice little message.

    3: The test_reoptimize test in tests/scripts/test_optimize_rasters.py fails. Not because the code performs wrongly, but because of the way exceptions inside threads are handled. When submitting a task to the Pool, an error_callback function is given, which receives any errors which occurs in the thread (and handles them in the main-thread). But apparently pytest recognizes that an error has been thrown inside the threads, and fails the test based on that. If a preprocessed file already exists, and terracotta optimize-rasters is run without --overwrite or --skip-existing flags, then the expected behaviour is to throw an exception. But somehow pytest expects the exception to be raised differently, or something like that? And I can't figure out how to make the test accept the new exception flow, such that the test just tests whether the code handles preexisting optimized files properly, and not where/how the exception is raised.

    opened by nickeopti 14
  • Re-add database user and password as settings, and rename from MYSQL_* to SQL_*

    Re-add database user and password as settings, and rename from MYSQL_* to SQL_*

    The SQLAlchemy broke setting MYSQL_USER and MYSQL_PASSWORD settings. This PR fixes that.

    It also renames the fields from MYSQL_* to the more generic SQL_*, in anticipation of the coming PostgreSQL driver (and potential future others). This is currently just a plain rename, thus breaking compatibility with deployments using the previous fields. We need to decide whether that is okay, or whether there should be some deprecation warning system first.

    Ideally, we also ought to make some tests for this. I have apparently previously broken this, without noticing. That shouldn't be possible in the future. Feel free to just add such tests -- it may take a while before I'm back to do it.

    opened by nickeopti 13
  • XYZ tiles of a given Polygon from a large raster tile

    XYZ tiles of a given Polygon from a large raster tile

    Is there a way or a workaround with terracotta that can help me serve XYZ tiles of a given polygon from a large tile? So the case is, I have a large tile but I want only a polygon section of it to be served, rest be masked out invalid, dynamically? I'm using Leaflet maps to visualise the raster tiles.

    opened by abhi1301 13
  • make CORS allowed origins configurable

    make CORS allowed origins configurable

    Make CORS allowed origins configurable for metadata and tiles via new environment variables:

    • TC_ALLOWED_ORIGINS_METADATA = '["*"]'
    • TC_ALLOWED_ORIGINS_TILES = '[]'

    Where empty list [] means no allowed origins.

    The changes are backward-compatible, so even when the user omits the new environment variables but updates Terracotta, the behavior will be the same as before: all origins allowed for /metadata, no cross-origin headers for tiles.

    Closes #160

    opened by j08lue 13
  • different table schema in sqlite driver between conda and pip terracotta version

    different table schema in sqlite driver between conda and pip terracotta version

    Hi all, I am trying to deploy terracotta to AWS but having issues. While trying to debug I realised that there is a discrepancy between the conda version and the pip version of terracotta, despite both being 0.7.5.

    in the sqlite database installed with pip the keys table is called keys, while in the conda version the table is called key_names with the primary key also called "key_name" instead of "key". This obviously creates problems when trying to run the db with terracotta serve -d

    opened by ciskoh 15
  • Add check whether Terracotta is running in multithreaded context

    Add check whether Terracotta is running in multithreaded context

    I am seeing some weird behaviour when trying to use the RelationalMetaStore class, specifically the db connection handling. Since the connection is created once and yielded down the call stack it seems we might run into some issues when trying to do the commit or the rollback if any of the downstream calls errored out. We essentially end up with a lot of AttributeError: 'NoneType' object has no attribute 'rollback'/'commit', which seems weird to me since these are only set to None in the finally block in the top-most connect call.

    I tried adding a little if self.connected: check before commiting or rollbacking which seems to reduce errors and smooth loading of the PNGs, but that seems a little icky since we are in a if not self.connected loop.

    Am I looking at this wrong? Has anyone tried using the RelationalMetaStore implementation and seen/not seen this before? I tried thinking about a reproducible example but I am struggling to figure out how that could be done.

    enhancement good first issue 
    opened by kiksekage 5
  • New release

    New release

    I wanted to use the lovely postgresql driver implemented by @nickeopti sometime back in March when it struck me that these changes werent included in the newest pypi release. Would the changes since 0.7.5 warrant a new release? 🙏

    opened by kiksekage 7
  • Support multi-band GeoTiffs

    Support multi-band GeoTiffs

    Hello

    I manage to use geotiffs as per the examples, that is making single band r/g/b files.

    Is it possible to directly use the RGB geotiffs?

    Thanks

    best regards

    Gilles

    opened by gillesserco 6
  • Terracotta CLI / API in AWS lambda

    Terracotta CLI / API in AWS lambda

    Hi All,

    I need to find the best way to run the terracotta optimize-raster and also importing the terracotta files in another python lambda to run the ingestion-script. Is it possible to run the Terracotta CLI/API through the deployed aws lambda system ?

    Thanks you in advance for your time.

    opened by zufryy 1
  • WMTS support

    WMTS support

    Experimental support for WMTS, including the Dimension tag. This is at the moment pretty much a working proof-of-concept, initially made just to test the feasibility. A lot of polishing is required before it may become ready to merge.

    But first, is this a feature we want to add? It is suprisingly simple, and doesn't add much complexity, as it primarily relies on existing functionality. It essentially just provides an endpoint for fetching GetCapabilities -- the rest is handled as usual.

    As far as I can tell the implementation adheres to the WMTS standard. I've cross-checked with Titiler as a reference point, and the processes seem comparable (apart from their implementation being much more generalised). The implementation is tested in QGIS on small test rasters.

    Remaining tasks and questions (if we want to add it):

    1. Support usage of all the normal endpoints for rasters; /rgb, /compute(?), as well as /singleband, along with all their options. This is currently hardcoded to /singleband without any options.
    2. Dynamically add zoom levels instead of hardcoding them in the wmts.xml template file? If doing so, data is available here http://schemas.opengis.net/tms/1.0/json/examples/.
    3. Are there any restrictions on zoom levels? I see Titiler deduce zoom level restrictions from data, somehow. Does Terracotta have such limits?
    4. Is it correctly understood that WorldWebMercatorQuad is the correct reference system?
    5. I've used xml.etree.ElementTree to build the capabilities XML file. It seems like the proper way for me, but I'm not satisfied with the code. I think it is too convoluted, and frankly hard to read. I'm actually leaning towards inserting elements as strings in the template instead. Thoughts on this?
    6. Where shall static template/data files be stored? Regarding the wmts.xml and possibly WebMercatorQuad.json file(s).
    7. Currently the dimension option blindly trusts the user that the supplied key makes sense as a dimension (ie that the raster files have the same bounds). Shall we verify this?
    8. Documentation.
    9. Testing. No efforts have been made here yet.
    opened by nickeopti 3
Releases(v0.7.5)
  • v0.7.5(Feb 21, 2022)

    What's Changed

    • Round data to nearest integer before converting to 8bit by @dionhaefner in https://github.com/DHI-GRAS/terracotta/pull/250
    • Update ingest.py example after changing name from create-database by @hummeltech in https://github.com/DHI-GRAS/terracotta/pull/253
    • Test on python 3.10 by @dionhaefner in https://github.com/DHI-GRAS/terracotta/pull/252

    New Contributors

    • @hummeltech made their first contribution in https://github.com/DHI-GRAS/terracotta/pull/253

    Full Changelog: https://github.com/DHI-GRAS/terracotta/compare/v0.7.4...v0.7.5

    Source code(tar.gz)
    Source code(zip)
  • v0.7.4(Dec 20, 2021)

    What's Changed

    • Switch to GH actions by @dionhaefner in https://github.com/DHI-GRAS/terracotta/pull/242
    • Now works with recent versions of rasterio

    Full Changelog: https://github.com/DHI-GRAS/terracotta/compare/v0.7.3...v0.7.4

    Source code(tar.gz)
    Source code(zip)
  • v0.7.3(Oct 12, 2021)

    What's Changed

    • Add transparency mask support for /compute by @dionhaefner in https://github.com/DHI-GRAS/terracotta/pull/222
    • optimize_rasters: skip_existing by @chapmanjacobd in https://github.com/DHI-GRAS/terracotta/pull/224
    • Require pymysql>=1.0.0, which has a context managed connection by @nickeopti in https://github.com/DHI-GRAS/terracotta/pull/229
    • Use Flask error handlers instead of decorators (#74) by @nickeopti in https://github.com/DHI-GRAS/terracotta/pull/227
    • fix docs by @dionhaefner in https://github.com/DHI-GRAS/terracotta/pull/231
    • Introduce multiqueries for dataset lookup #33 by @nickeopti in https://github.com/DHI-GRAS/terracotta/pull/230
    • Parallel raster optimisation by @nickeopti in https://github.com/DHI-GRAS/terracotta/pull/228
    • Allow CORS from localhost by default (#197) by @dionhaefner in https://github.com/DHI-GRAS/terracotta/pull/236

    New Contributors

    • @nickeopti made their first contribution in https://github.com/DHI-GRAS/terracotta/pull/229

    Full Changelog: https://github.com/DHI-GRAS/terracotta/compare/v0.7.2...v0.7.3

    Source code(tar.gz)
    Source code(zip)
  • v0.7.2(Jul 1, 2021)

  • v0.7.1(May 12, 2021)

    New features

    • A whole new and shiny preview app in React (thanks to @bertearazvan).
    • terracotta ingest now has a --skip-existing option.
    • Use of multiprocessing is now configurable via TC_USE_MULTIPROCESSING.

    Bug fixes

    • Automatically respawns broken process pools.
    • Better MySQL caching and URL parsing.
    • Bumped dependencies.
    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(Jul 1, 2020)

    We added support for custom color maps and fixes to the raster driver and the MySQL database driver

    Changes

    • You can now conveniently include your custom color maps in an EXTRA_CMAP_FOLDER of your choosing, thanks to @dionhaefner
    • Rasters with existing alpha bands now just work (#176) fixed by @dionhaefner
    • /colormap response changed: JSON key is called rgba instead of rgb and contains 4 values.

    Bug fixes

    • MySQL database driver getting into broken state limbo is now prevented (#174), by @j08lue and @dionhaefner

    Other

    • Docs now rst-magically build the color map visualizations and got rid of their Matplotlib dependency, by @dionhaefner
    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(Mar 27, 2020)

    This release contains some critical bug fixes and quality-of-life improvements.

    Changes

    • The config parameters UPSAMPLING_METHOD and DOWNSAMPLING_METHOD are now REPROJECTION_METHOD and RESAMPLING_METHOD, with different semantics.

    Bug fixes

    • As it turns out, retrieving tiles with GDAL is not thread-safe. Therefore we now use multiprocessing (on systems where it is supported) to retrieve the three RGB bands in parallel.
    • Terracotta's default transform failed to produce meaningful results in certain edge-cases. We thus reverted to GDAL's default transform, but with the additional feature that tiles never undersample the original dataset. This seems to give good performance both for high and low zoom levels.

    Other

    • Some tweaks to the docs by @YuhangCh and @j08lue.
    • CORS is now configurable thanks to @j08lue.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.2(Oct 17, 2019)

    No big changes, just some tweaks and bug fixes that accumulated during the last couple of months.

    Bug fixes:

    • Adapt to recent library versions
    • Do not use GDAL_DISABLE_READDIR_ON_OPEN anymore (#139)
    • cache_cluster_ttl in zappa_settings.toml.in is now an integer

    Other:

    • Now tested with Python 3.8
    Source code(tar.gz)
    Source code(zip)
  • v0.5.1(Apr 3, 2019)

    New features:

    • /compute API endpoint to do band math on-the-fly
    • Compressed internal tile cache by @panakouris

    Bug fixes:

    • Bump to recent versions of apispec, cachetools, flake8
    • Supplying an explicit color map now works as expected
    • Fixed broken colormaps
    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(Dec 11, 2018)

    Changes to v0.5.0b1:

    • Now terracotta connect checks whether the remote server runs a compatible version of Terracotta
    • More documentation
    • Fancy logo
    • Preview app overhaul by @JeroenDerks
    Source code(tar.gz)
    Source code(zip)
  • v0.5.0b1(Nov 29, 2018)

    • Overhaul nodata handling
    • Add documentation
    • Add types to client app
    • Fix some tile alignment bugs
    • Explicit colormaps now accept RGBA tuples
    • Fix some bugs in optimize-rasters
    • Faster lazy loading support
    • Fix some bugs when using the limit keyword for get_datasets
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Oct 4, 2018)

    This release introduces some breaking changes in the Terracotta API and deployment workflow.

    Changes

    • Added a Zappa callback that ensures consistency of settings and remote database before deployment.

    • The Terracotta version used to create a database is now added to the database and checked on connection.

    • Terracotta will now warn when calling driver.insert on a raster file that is not a cloud-optimized GeoTiff.

    • We now support proper logging, including logging to a file.

    • Preview images for datasets can be requested via /singleband/{keys}/preview.png and /rgb/{keys}/preview.png.

    • The returned tile size is now configurable from the URL for both /singleband and /rgb.

    • The preferred Zappa settings format is now TOML.

    • It is now possible to add a plaintext description of the keys in a Terracotta deployment. The response format of /keys is changed to

      [
          {
              "key": "key_name",
               "description": "key description"
          }
      ]
      

      where description is optional.

    • Various optimizations and bug fixes.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Sep 17, 2018)

    Changes:

    • /legend API endpoint renamed to /colormap
    • Removed /colormaps API endpoint
    • More performant convex hull computation to speed up ingestion in some cases
    • /colormap is now properly covered by tests that ensure consistency with images returned by /singleband
    • /singleband now accepts a explicit_color_map argument that forces Terracotta to preserve pixel values (e.g. when serving categorical data)
    • Added a recipe to serve categorical data to README
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Sep 12, 2018)

  • v0.1.0(Mar 14, 2018)

Owner
DHI GRAS
DHI GRAS is specialised in Earth observation, satellite image processing, and GIS
DHI GRAS
Tool to display your current position and angle above your radar

🛠 Tool to display your current position and angle above your radar. As a response to the CS:GO Update on 1.2.2022, which makes cl_showpos a cheat-pro

Miko 6 Jan 04, 2023
Centroids as a Service

Centroids! This application reads a valid geojson FeatureCollection and returns a valid geojson FeatureColleciton of centroids. In the output: All pro

Lyzi Diamond 20 Aug 29, 2021
Read and write rasters in parallel using Rasterio and Dask

dask-rasterio dask-rasterio provides some methods for reading and writing rasters in parallel using Rasterio and Dask arrays. Usage Read a multiband r

Dymaxion Labs 85 Aug 30, 2022
scalable analysis of images and time series

thunder scalable analysis of image and time series analysis in python Thunder is an ecosystem of tools for the analysis of image and time series data

thunder-project 813 Dec 29, 2022
geobeam - adds GIS capabilities to your Apache Beam and Dataflow pipelines.

geobeam adds GIS capabilities to your Apache Beam pipelines. What does geobeam do? geobeam enables you to ingest and analyze massive amounts of geospa

Google Cloud Platform 61 Nov 08, 2022
Google maps for Jupyter notebooks

gmaps gmaps is a plugin for including interactive Google maps in the IPython Notebook. Let's plot a heatmap of taxi pickups in San Francisco: import g

Pascal Bugnion 747 Dec 19, 2022
Water Detect Algorithm

WaterDetect Synopsis WaterDetect is an end-to-end algorithm to generate open water cover mask, specially conceived for L2A Sentinel 2 imagery from MAJ

142 Dec 30, 2022
ArcGIS Python Toolbox for WhiteboxTools

WhiteboxTools-ArcGIS ArcGIS Python Toolbox for WhiteboxTools. This repository is related to the ArcGIS Python Toolbox for WhiteboxTools, which is an A

Qiusheng Wu 190 Dec 30, 2022
Code and coordinates for Matt's 2021 xmas tree

xmastree2021 Code and coordinates for Matt's 2021 xmas tree This repository contains the code and coordinates used for Matt's 2021 Christmas tree, as

Stand-up Maths 117 Jan 01, 2023
Imperial Valley Geomorphology Map

Roughly maps the extent of basins, basin edges, and mountains in the Imperial Valley by grouping terrain classes from the Iwahashi et al. 2021 California terrian classification model.

0 Dec 13, 2022
Evaluation of file formats in the context of geo-referenced 3D geometries.

Geo-referenced Geometry File Formats Classic geometry file formats as .obj, .off, .ply, .stl or .dae do not support the utilization of coordinate syst

Advanced Information Systems and Technology 11 Mar 02, 2022
Python module to access the OpenCage geocoding API

OpenCage Geocoding Module for Python A Python module to access the OpenCage Geocoder. Build Status / Code Quality / etc Usage Supports Python 3.6 or n

OpenCage GmbH 57 Nov 01, 2022
A python package that extends Google Earth Engine.

A python package that extends Google Earth Engine GitHub: https://github.com/davemlz/eemont Documentation: https://eemont.readthedocs.io/ PyPI: https:

David Montero Loaiza 307 Jan 01, 2023
A ready-to-use curated list of Spectral Indices for Remote Sensing applications.

A ready-to-use curated list of Spectral Indices for Remote Sensing applications. GitHub: https://github.com/davemlz/awesome-ee-spectral-indices Docume

David Montero Loaiza 488 Jan 03, 2023
Python renderer for OpenStreetMap with custom icons intended to display as many map features as possible

Map Machine project consists of Python OpenStreetMap renderer: SVG map generation, SVG and PNG tile generation, Röntgen icon set: unique CC-BY 4.0 map

Sergey Vartanov 0 Dec 18, 2022
A Django application that provides country choices for use with forms, flag icons static files, and a country field for models.

Django Countries A Django application that provides country choices for use with forms, flag icons static files, and a country field for models. Insta

Chris Beaven 1.2k Jan 03, 2023
framework for large-scale SAR satellite data processing

pyroSAR A Python Framework for Large-Scale SAR Satellite Data Processing The pyroSAR package aims at providing a complete solution for the scalable or

John Truckenbrodt 389 Dec 21, 2022
Enable geospatial data mining through Google Earth Engine in Grasshopper 3D, via its most recent Hops component.

AALU_Geo Mining This repository is produced for a masterclass at the Architectural Association Landscape Urbanism programme. Requirements Rhinoceros (

4 Nov 16, 2022
A service to auto provision devices in Aruba Central based on the Geo-IP location

Location Based Provisioning Service for Aruba Central A service to auto provision devices in Aruba Central based on the Geo-IP location Geo-IP auto pr

Will Smith 3 Mar 22, 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