def shapes(qk: str = Query(...)): """return info.""" x, y, z = mercantile.quadkey_to_tile(qk) with MosaicBackend(self.src_path) as mosaic: assets = mosaic.assets_for_tile(x, y, z) features = get_footprints(assets, max_threads=MAX_THREADS) return FeatureCollection(features=features)
def from_urls( cls, urls: Sequence[str], minzoom: Optional[int] = None, maxzoom: Optional[int] = None, max_threads: int = 20, quiet: bool = True, **kwargs, ): """Create mosaicjson from COG urls. Attributes: urls (list): List of COGs. minzoom (int): Force mosaic min-zoom. maxzoom (int): Force mosaic max-zoom. max_threads (int): Max threads to use (default: 20). quiet (bool): Mask processing steps (default is True). kwargs (any): Options forwarded to `MosaicJSON._create_mosaic` Returns: mosaic_definition (MosaicJSON): Mosaic definition. Raises: Exception: If COGs don't have the same datatype Examples: >>> MosaicJSON.from_urls(["1.tif", "2.tif"]) """ features = get_footprints(urls, max_threads=max_threads, quiet=quiet) if minzoom is None: data_minzoom = {feat["properties"]["minzoom"] for feat in features} if len(data_minzoom) > 1: warnings.warn( "Multiple MinZoom, Assets different minzoom values", UserWarning ) minzoom = max(data_minzoom) if maxzoom is None: data_maxzoom = {feat["properties"]["maxzoom"] for feat in features} if len(data_maxzoom) > 1: warnings.warn( "Multiple MaxZoom, Assets have multiple resolution values", UserWarning, ) maxzoom = max(data_maxzoom) datatype = {feat["properties"]["datatype"] for feat in features} if len(datatype) > 1: raise Exception("Dataset should have the same data type") return cls._create_mosaic( features, minzoom=minzoom, maxzoom=maxzoom, quiet=quiet, **kwargs )
def update(input_files, input_mosaic, min_tile_cover, add_first, threads, quiet): """Update mosaic definition file.""" input_files = input_files.read().splitlines() features = get_footprints(input_files, max_threads=threads) with MosaicBackend(input_mosaic) as mosaic: mosaic.update( features, add_first=add_first, minimum_tile_cover=min_tile_cover, quiet=quiet, )
def update_mosaicjson(body: UpdateMosaicJSON): """Update an existing MosaicJSON""" src_path = self.path_dependency(body.url) with self.reader(src_path.url, reader=self.dataset_reader) as mosaic: features = get_footprints(body.files, max_threads=body.max_threads) try: mosaic.update(features, add_first=body.add_first, quiet=True) except NotImplementedError: raise BadRequestError( f"{mosaic.__class__.__name__} does not support update operations" ) return mosaic.mosaic_def
def update_mosaicjson(body: UpdateMosaicJSON): """Update an existing MosaicJSON""" mosaic_path = MosaicPath(body.url) with MosaicBackend(mosaic_path) as mosaic: features = get_footprints(body.files, max_threads=body.max_threads) try: mosaic.update(features, add_first=body.add_first, quiet=True) except NotImplementedError: raise BadRequestError( f"{mosaic.__class__.__name__} does not support update operations" ) return mosaic.mosaic_def
def footprint(input_files, output, threads, quiet): """Create mosaic definition file.""" input_files = input_files.read().splitlines() foot = { "features": get_footprints(input_files, max_threads=threads, quiet=quiet), "type": "FeatureCollection", } if output: with open(output, mode="w") as f: f.write(json.dumps(foot)) else: click.echo(json.dumps(foot))
def test_footprint(): """Fetch footprints from asset list.""" assets = [asset1, asset2] foot = utils.get_footprints(assets) assert len(foot) == 2
def test_sqlite_backend(): """Test sqlite backend.""" with MosaicBackend(f"sqlite:///{mosaic_db}:test") as mosaic: assert mosaic._backend_name == "SQLite" assert isinstance(mosaic, SQLiteBackend) assert (mosaic.mosaicid == "f7fc24d47a79f1496dcdf9997de83e6305c252a931fba2c7d006b7d8") assert mosaic.quadkey_zoom == 7 info = mosaic.info() assert not info["quadkeys"] assert list(info.dict()) == [ "bounds", "center", "minzoom", "maxzoom", "name", "quadkeys", ] info = mosaic.info(quadkeys=True) assert info["quadkeys"] assert list(mosaic.metadata.dict(exclude_none=True).keys()) == [ "mosaicjson", "name", "version", "minzoom", "maxzoom", "quadkey_zoom", "bounds", "center", ] assert mosaic.assets_for_tile(150, 182, 9) == ["cog1.tif", "cog2.tif"] assert mosaic.assets_for_point(-73, 45) == ["cog1.tif", "cog2.tif"] assert len(mosaic.get_assets(150, 182, 9)) == 2 assert len(mosaic.get_assets(147, 182, 12)) == 0 # Validation error, mosaic_def is empty with pytest.raises(ValidationError): with MosaicBackend("sqlite:///:memory::test", mosaic_def={}): pass # invalid scheme `sqlit://` with pytest.raises(ValueError): with SQLiteBackend("sqlit:///:memory::test"): pass # `:` is an invalid character for mosaic name with pytest.raises(ValueError): with SQLiteBackend("sqlite:///:memory::test:"): pass # `mosaicjson_metadata` is a reserved mosaic name with pytest.raises(AssertionError): with MosaicBackend("sqlite:///:memory::mosaicjson_metadata"): pass # Warns when changing name with pytest.warns(UserWarning): with MosaicBackend(mosaic_gz) as m: with MosaicBackend("sqlite:///:memory::test", mosaic_def=m.mosaic_def) as d: assert d.mosaic_def.name == "test" # need to set overwrite when mosaic already exists with MosaicBackend("sqlite:///:memory::test", mosaic_def=mosaic_content) as mosaic: mosaic.write() with pytest.raises(MosaicExistsError): mosaic.write() mosaic.write(overwrite=True) # files doesn't exists with pytest.raises(MosaicNotFoundError): with MosaicBackend("sqlite:///test.db:test2") as mosaic: pass # mosaic doesn't exists in DB with pytest.raises(MosaicNotFoundError): with MosaicBackend(f"sqlite:///{mosaic_db}:test2") as mosaic: pass # Test with `.` in mosaic name with pytest.warns(UserWarning): with MosaicBackend("sqlite:///:memory::test.mosaic", mosaic_def=mosaic_content) as m: m.write() assert m._mosaic_exists() assert m.mosaic_def.name == "test.mosaic" m.delete() assert not m._mosaic_exists() assert not m._fetch_metadata() mosaic_oneasset = MosaicJSON.from_urls([asset1], quiet=True) features = get_footprints([asset2], quiet=True) # Test update methods with MosaicBackend("sqlite:///:memory::test", mosaic_def=mosaic_oneasset) as m: m.write() meta = m.metadata assert len(m.get_assets(150, 182, 9)) == 1 m.update(features) assert not m.metadata == meta assets = m.get_assets(150, 182, 9) assert len(assets) == 2 assert assets[0] == asset2 assert assets[1] == asset1 # Test update with `add_first=False` with MosaicBackend("sqlite:///:memory::test2", mosaic_def=mosaic_oneasset) as m: m.write() meta = m.metadata assert len(m.get_assets(150, 182, 9)) == 1 m.update(features, add_first=False) assert not m.metadata == meta assets = m.get_assets(150, 182, 9) assert len(assets) == 2 assert assets[0] == asset1 assert assets[1] == asset2 assert SQLiteBackend.list_mosaics_in_db(mosaic_db) == ["test"] assert SQLiteBackend.list_mosaics_in_db(f"sqlite:///{mosaic_db}") == [ "test" ] with pytest.raises(ValueError): assert SQLiteBackend.list_mosaics_in_db("test.db")
def from_urls( cls, urls: Sequence[str], minzoom: Optional[int] = None, maxzoom: Optional[int] = None, max_threads: int = 20, quiet: bool = True, **kwargs, ): """ Create mosaicjson from COG urls. Attributes ---------- urls : List, required List of COG urls. minzoom: int, optional Force mosaic min-zoom. maxzoom: int, optional Force mosaic max-zoom. max_threads : int Max threads to use (default: 20). quiet: bool, optional (default: True) Mask processing steps. kwargs: any Options forwarded to MosaicJSON.from_features Returns ------- mosaic_definition : MosaicJSON Mosaic definition. """ features = get_footprints(urls, max_threads=max_threads, quiet=quiet) if minzoom is None: data_minzoom = {feat["properties"]["minzoom"] for feat in features} if len(data_minzoom) > 1: warnings.warn( "Multiple MinZoom, Assets different minzoom values", UserWarning) minzoom = max(data_minzoom) if maxzoom is None: data_maxzoom = {feat["properties"]["maxzoom"] for feat in features} if len(data_maxzoom) > 1: warnings.warn( "Multiple MaxZoom, Assets have multiple resolution values", UserWarning, ) maxzoom = max(data_maxzoom) datatype = {feat["properties"]["datatype"] for feat in features} if len(datatype) > 1: raise Exception("Dataset should have the same data type") return cls._create_mosaic(features, minzoom=minzoom, maxzoom=maxzoom, quiet=quiet, **kwargs)
def test_InMemoryReader(): """Test MemoryBackend.""" assets = [asset1, asset2] mosaicdef = MosaicJSON.from_urls(assets, quiet=False) with MosaicBackend(":memory:", mosaic_def=mosaicdef) as mosaic: assert isinstance(mosaic, MemoryBackend) assert mosaic.path == ":memory:" mosaic.write() mosaic._read() with MosaicBackend(None, mosaic_def=mosaicdef) as mosaic: assert isinstance(mosaic, MemoryBackend) assert mosaic.path == ":memory:" with MemoryBackend(mosaic_def=mosaicdef) as mosaic: (t, _), assets_used = mosaic.tile(150, 182, 9) assert t.shape (tR, _), assets_usedR = mosaic.tile(150, 182, 9, reverse=True) assert tR.shape assert not numpy.array_equal(t, tR) assert assets_used[0] == assets_usedR[-1] with pytest.raises(NoAssetFoundError): mosaic.tile(200, 182, 9) pts = mosaic.point(-73, 45) assert len(pts) == 2 assert pts[0][0].endswith(".tif") assert len(pts[0][1]) == 3 ptsR = mosaic.point(-73, 45, reverse=True) assert len(ptsR) == 2 assert ptsR[0][0] == pts[-1][0] pts = mosaic.point(-72.5, 46) assert len(pts) == 1 with pytest.raises(PointOutsideBounds): mosaic.point(-72.5, 46, allowed_exceptions=None) with pytest.raises(NoAssetFoundError): mosaic.point(-60, 45) assert mosaic.minzoom assert mosaic.maxzoom assert mosaic.bounds assert mosaic.center == mosaicdef.center with pytest.raises(NotImplementedError): mosaic.stats() with pytest.raises(NotImplementedError): mosaic.preview() with pytest.raises(NotImplementedError): mosaic.part() with pytest.raises(NotImplementedError): mosaic.feature() info = mosaic.info() assert list(info.dict()) == [ "bounds", "center", "minzoom", "maxzoom", "name", "quadkeys", ] assert mosaic.spatial_info mosaic_oneasset = MosaicJSON.from_urls([asset1], quiet=True) with MemoryBackend(mosaic_def=mosaic_oneasset) as mosaic: assert isinstance(mosaic, MemoryBackend) assert len(mosaic.get_assets(150, 182, 9)) == 1 features = get_footprints([asset2], quiet=True) mosaic.update(features) assets = mosaic.get_assets(150, 182, 9) assert len(assets) == 2 assert assets[0] == asset2 assert assets[1] == asset1
def test_file_backend(): """Test File backend.""" with MosaicBackend(mosaic_gz) as mosaic: assert mosaic._backend_name == "File" assert isinstance(mosaic, FileBackend) assert (mosaic.mosaicid == "24d43802c19ef67cc498c327b62514ecf70c2bbb1bbc243dda1ee075") assert mosaic.quadkey_zoom == 7 assert mosaic.minzoom == mosaic.mosaic_def.minzoom info = mosaic.info() assert not info["quadkeys"] assert list(info.dict()) == [ "bounds", "center", "minzoom", "maxzoom", "name", "quadkeys", ] info = mosaic.info(quadkeys=True) assert info["quadkeys"] assert list(mosaic.metadata.dict(exclude_none=True).keys()) == [ "mosaicjson", "version", "minzoom", "maxzoom", "quadkey_zoom", "bounds", "center", ] assert mosaic.assets_for_tile(150, 182, 9) == ["cog1.tif", "cog2.tif"] assert mosaic.assets_for_point(-73, 45) == ["cog1.tif", "cog2.tif"] assert len(mosaic.get_assets(150, 182, 9)) == 2 assert len(mosaic.get_assets(147, 182, 12)) == 0 with MosaicBackend(mosaic_json) as mosaic: assert isinstance(mosaic, FileBackend) assert mosaic.quadkey_zoom == 7 with MosaicBackend(mosaic_jsonV1) as mosaic: assert isinstance(mosaic, FileBackend) assert mosaic.quadkey_zoom == 7 assert list(mosaic.metadata.dict(exclude_none=True).keys()) == [ "mosaicjson", "version", "minzoom", "maxzoom", "bounds", "center", ] with pytest.raises(ValidationError): with MosaicBackend("afile.json", mosaic_def={}): pass runner = CliRunner() with runner.isolated_filesystem(): with MosaicBackend("mosaic.json", mosaic_def=mosaic_content) as mosaic: mosaic.write() assert mosaic.minzoom == mosaic_content["minzoom"] with open("mosaic.json") as f: m = json.loads(f.read()) assert m["quadkey_zoom"] == 7 with pytest.raises(MosaicExistsError): mosaic.write() mosaic.write(overwrite=True) with MosaicBackend("mosaic.json.gz", mosaic_def=mosaic_content) as mosaic: mosaic.write() with open("mosaic.json.gz", "rb") as f: m = json.loads(_decompress_gz(f.read())) assert m["quadkey_zoom"] == 7 mosaic_oneasset = MosaicJSON.from_urls([asset1], quiet=True) with MosaicBackend("umosaic.json.gz", mosaic_def=mosaic_oneasset) as mosaic: mosaic.write() assert len(mosaic.get_assets(150, 182, 9)) == 1 with MosaicBackend("umosaic.json.gz") as mosaic: features = get_footprints([asset2], quiet=True) mosaic.update(features) assets = mosaic.get_assets(150, 182, 9) assert len(assets) == 2 assert assets[0] == asset2 assert assets[1] == asset1