Backends
Starting in version 3.0.0
, we introduced specific backend
to abstract mosaicJSON storage.
Read-Write Backends¶
-
FileBackend (default,
file:///
) -
S3Backend (
s3://
) -
GCSBackend (
gs://
) -
ABSBackend (
az://{storageaccount}.blob.core.windows.net/{container}/{key}
) -
DynamoDBBackend (
dynamodb://{region}/{table_name}
). Ifregion
is not passed, it reads the value of theAWS_REGION
environment variable. If that environment variable does not exist, it falls back tous-east-1
. If you choose not to pass aregion
, you still need three/
before the table name, like sodynamodb:///{table_name}
. -
SQLiteBackend (
sqlite:///{file.db}:{mosaic_name}
)
Read Only Backends¶
Read only backend won't allow mosaic_def
in there __init__
method. .write()
and .update
methods will raise NotImplementedError
error.
- HttpBackend (
http://
,https://
) - STACBackend (
stac+:https://
). Based on SpatioTemporal Asset Catalog API.
In-Memory¶
If you have a mosaicjson document and want to use the different backend methods you can use the special MemoryBackend.
with MemoryBackend(mosaic_def=mosaicjson) as mosaic:
img = mosaic.tile(1, 1, 1)
Abstract Class¶
All backends are built from a BaseBackend
which is a sub-class or rio-tiler.io.BaseReader
.
MosaicBackend¶
To ease the usage we added a helper function to use the right backend based on the uri schema: cogeo_mosaic.backends.MosaicBackend
from cogeo_mosaic.backends import MosaicBackend
with MosaicBackend("s3://mybucket/amosaic.json") as mosaic:
assert isinstance(mosaic, cogeo_mosaic.backends.s3.S3Backend)
with MosaicBackend("gs://mybucket/amosaic.json") as mosaic:
assert isinstance(mosaic, cogeo_mosaic.backends.gs.GCSBackend)
with MosaicBackend("dynamodb://us-east-1/amosaic") as mosaic:
assert isinstance(mosaic, cogeo_mosaic.backends.dynamodb.DynamoDBBackend)
with MosaicBackend("sqlite:///mosaic.db:amosaic") as mosaic:
assert isinstance(mosaic, cogeo_mosaic.backends.sqlite.SQLiteBackend)
with MosaicBackend("file:///amosaic.json.gz") as mosaic:
assert isinstance(mosaic, cogeo_mosaic.backends.file.FileBackend)
with MosaicBackend("amosaic.json.gz") as mosaic:
assert isinstance(mosaic, cogeo_mosaic.backends.file.FileBackend)
# Read-Only
with MosaicBackend("https://mosaic.com/amosaic.json.gz") as mosaic:
assert isinstance(mosaic, cogeo_mosaic.backends.web.HttpBackend)
with MosaicBackend("stac+https://my-stac.api/search", {"collections": ["satellite"]}, 10, 12) as mosaic:
assert isinstance(mosaic, cogeo_mosaic.backends.stac.STACBackend)
# In Memory (write)
# You can pass either None or ':memory:' to define an in-memory backend
with MosaicBackend(":memory:", mosaic_def=mosaic) as mosaic:
assert isinstance(mosaic, cogeo_mosaic.backends.memory.MemoryBackend)
with MosaicBackend(None, mosaic_def=mosaic) as mosaic:
assert isinstance(mosaic, cogeo_mosaic.backends.memory.MemoryBackend)
GCS Backend¶
The GCS Backend allows read and write operations from Google Cloud Storage.
When using this backend is necessary to set the appropriate roles and IAM permissions to let cogeo-mosaic access the files. For example:
- Read-only bucket - IAM Role
roles/storage.objectViewer
. It is possible to restrict the read-only operation to a single bucket by using the following condition:resource.type == "storage.googleapis.com/Object" && resource.name.startsWith("projects/_/buckets/mybucket")
ABS Backend¶
The ABS Backend allows read and write operations from/to Azure Blob Storage.
The backend uses DefaultAzureCredential for authorization, see here for details on how to authenticate.
When using this backend is necessary to set the appropriate roles and IAM permissions to let cogeo-mosaic access the files. See the Azure standard roles; Storage Blob Data Contributor/Owner/Reader.
STAC Backend¶
The STACBackend is a read-only backend, meaning it can't be used to write a file. This backend will POST to the input url looking for STAC items which will then be used to create the mosaicJSON in memory.
import datetime
import morecantile
from cogeo_mosaic.backends.stac import STACBackend
geojson = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
30.810813903808594,
29.454247067148533
],
[
30.88600158691406,
29.454247067148533
],
[
30.88600158691406,
29.51879923863822
],
[
30.810813903808594,
29.51879923863822
],
[
30.810813903808594,
29.454247067148533
]
]
]
}
}
]
}
date_min="2019-01-01"
date_max="2019-12-11"
start = datetime.datetime.strptime(date_min, "%Y-%m-%d").strftime("%Y-%m-%dT00:00:00Z")
end = datetime.datetime.strptime(date_max, "%Y-%m-%d").strftime("%Y-%m-%dT23:59:59Z")
query = {
"collections": ["sentinel-s2-l2a-cogs"],
"datetime": f"{start}/{end}",
"query": {
"eo:cloud_cover": {
"lt": 5
}
},
"intersects": geojson["features"][0]["geometry"],
"limit": 1000,
"fields": {
'include': ['id', 'properties.datetime', 'properties.data_coverage'],
'exclude': ['assets']
}
}
with STACBackend(
"https://earth-search.aws.element84.com/v0/search",
query=query,
minzoom=8,
maxzoom=15,
) as mosaic:
print(mosaic.mosaic_def.dict(exclude={"tiles"}))
Mosaic TileMatrixSet vs Backend TileMatrixSet¶
If using a TileMatrixSet other than the default WebMercatorQuad
, user HAS TO pass mosaic min/max zoom (different than the backend min/max zoom).
with STACBackend(
"https://earth-search.aws.element84.com/v0/search",
query=query,
tms=morecantile.tms.get("WGS1984Quad"),
minzoom=8,
maxzoom=12,
mosaic_options={
"tilematrixset": morecantile.tms.get("WebMercatorQuad"), # This is Optional and will be set by default to `WebMercatorQuad` TMS
"minzoom": 8,
"maxzoom": 14,
},
) as mosaic:
print(mosaic.mosaic_def.dict(exclude={"tiles"}))
Specification¶
The STACBackend rely on Spec version 1.0.0alpha.
Paggination¶
The returned object from the POST requests might not represent the whole results and thus we need to use the paggination.
You can limit the pagination by using max_items
or limit
stac-api options.
- Limit the total result to 1000 items
with STACBackend(
"https://earth-search.aws.element84.com/v0/search",
query={},
minzoom=8,
maxzoom=15,
stac_api_options={"max_items": 1000},
) as mosaic:
print(mosaic.mosaic_def.dict(exclude={"tiles"}))
- Limit the size of each POST result
with STACBackend(
"https://earth-search.aws.element84.com/v0/search",
query={},
minzoom=8,
maxzoom=15,
stac_api_options={"limit": 100},
) as mosaic:
print(mosaic.mosaic_def.dict(exclude={"tiles"}))
Tile's asset¶
MosaicJSON tile asset is defined using accessor
option. By default the backend will try to construct or retrieve the Item url
def default_stac_accessor(feature: Dict):
"""Return feature identifier."""
link = list(filter(lambda link: link["rel"] == "self", feature["links"]))
if link:
return link[0]["href"]
link = list(filter(lambda link: link["rel"] == "root", feature["links"]))
if link:
return os.path.join(
link[0]["href"],
"collections",
feature["collection"],
"items",
feature["id"],
)
# Fall back to the item ID
return feature["id"]
This default accessor function rely on the self
or root
link to be present.
It's let to the user to built a Mosaic Tiler which will understand the asset.
Custom accessor¶
Accessor HAVE to be a callable which take a GeoJSON feature as input.
Here is an example of an accessor that will return the ulr for asset B01
with STACBackend(
"https://earth-search.aws.element84.com/v0/search",
query={},
minzoom=8,
maxzoom=15,
stac_api_options={"limit": 100},
mosaic_options={"accessor": lambda x: x["assets"]["B01"]["href"]},
) as mosaic:
print(mosaic.mosaic_def.dict(exclude={"tiles"}))