Exemplo n.º 1
0
 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)
Exemplo n.º 2
0
    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
        )
Exemplo n.º 3
0
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,
        )
Exemplo n.º 4
0
 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
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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))
Exemplo n.º 7
0
def test_footprint():
    """Fetch footprints from asset list."""
    assets = [asset1, asset2]
    foot = utils.get_footprints(assets)
    assert len(foot) == 2
Exemplo n.º 8
0
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")
Exemplo n.º 9
0
    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)
Exemplo n.º 10
0
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
Exemplo n.º 11
0
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