diff --git a/tests/data/cbf/Alberta.geojson b/tests/data/cbf/Alberta.geojson index f2654944650..4b790f19c46 100644 --- a/tests/data/cbf/Alberta.geojson +++ b/tests/data/cbf/Alberta.geojson @@ -1,7 +1 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} +{"type": "FeatureCollection", "crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:OGC:1.3:CRS84"}}, "features": [{"type": "Feature", "properties": {}, "geometry": {"type": "Polygon", "coordinates": [[[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0], [0.0, 0.0]]]}}]} \ No newline at end of file diff --git a/tests/data/cbf/Alberta.zip b/tests/data/cbf/Alberta.zip index fe275027152..cd6e828377f 100644 Binary files a/tests/data/cbf/Alberta.zip and b/tests/data/cbf/Alberta.zip differ diff --git a/tests/data/cbf/BritishColumbia.geojson b/tests/data/cbf/BritishColumbia.geojson deleted file mode 100644 index f2654944650..00000000000 --- a/tests/data/cbf/BritishColumbia.geojson +++ /dev/null @@ -1,7 +0,0 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} diff --git a/tests/data/cbf/BritishColumbia.zip b/tests/data/cbf/BritishColumbia.zip deleted file mode 100644 index 7e2b47f0504..00000000000 Binary files a/tests/data/cbf/BritishColumbia.zip and /dev/null differ diff --git a/tests/data/cbf/Manitoba.geojson b/tests/data/cbf/Manitoba.geojson deleted file mode 100644 index f2654944650..00000000000 --- a/tests/data/cbf/Manitoba.geojson +++ /dev/null @@ -1,7 +0,0 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} diff --git a/tests/data/cbf/Manitoba.zip b/tests/data/cbf/Manitoba.zip deleted file mode 100644 index ae49962b2bb..00000000000 Binary files a/tests/data/cbf/Manitoba.zip and /dev/null differ diff --git a/tests/data/cbf/NewBrunswick.geojson b/tests/data/cbf/NewBrunswick.geojson deleted file mode 100644 index f2654944650..00000000000 --- a/tests/data/cbf/NewBrunswick.geojson +++ /dev/null @@ -1,7 +0,0 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} diff --git a/tests/data/cbf/NewBrunswick.zip b/tests/data/cbf/NewBrunswick.zip deleted file mode 100644 index dbd1f116af5..00000000000 Binary files a/tests/data/cbf/NewBrunswick.zip and /dev/null differ diff --git a/tests/data/cbf/NewfoundlandAndLabrador.geojson b/tests/data/cbf/NewfoundlandAndLabrador.geojson deleted file mode 100644 index f2654944650..00000000000 --- a/tests/data/cbf/NewfoundlandAndLabrador.geojson +++ /dev/null @@ -1,7 +0,0 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} diff --git a/tests/data/cbf/NewfoundlandAndLabrador.zip b/tests/data/cbf/NewfoundlandAndLabrador.zip deleted file mode 100644 index ea4121d1b2f..00000000000 Binary files a/tests/data/cbf/NewfoundlandAndLabrador.zip and /dev/null differ diff --git a/tests/data/cbf/NorthwestTerritories.geojson b/tests/data/cbf/NorthwestTerritories.geojson deleted file mode 100644 index f2654944650..00000000000 --- a/tests/data/cbf/NorthwestTerritories.geojson +++ /dev/null @@ -1,7 +0,0 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} diff --git a/tests/data/cbf/NorthwestTerritories.zip b/tests/data/cbf/NorthwestTerritories.zip deleted file mode 100644 index cb449de6654..00000000000 Binary files a/tests/data/cbf/NorthwestTerritories.zip and /dev/null differ diff --git a/tests/data/cbf/NovaScotia.geojson b/tests/data/cbf/NovaScotia.geojson deleted file mode 100644 index f2654944650..00000000000 --- a/tests/data/cbf/NovaScotia.geojson +++ /dev/null @@ -1,7 +0,0 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} diff --git a/tests/data/cbf/NovaScotia.zip b/tests/data/cbf/NovaScotia.zip deleted file mode 100644 index e56d3e72597..00000000000 Binary files a/tests/data/cbf/NovaScotia.zip and /dev/null differ diff --git a/tests/data/cbf/Nunavut.geojson b/tests/data/cbf/Nunavut.geojson deleted file mode 100644 index f2654944650..00000000000 --- a/tests/data/cbf/Nunavut.geojson +++ /dev/null @@ -1,7 +0,0 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} diff --git a/tests/data/cbf/Nunavut.zip b/tests/data/cbf/Nunavut.zip deleted file mode 100644 index 424c462ad57..00000000000 Binary files a/tests/data/cbf/Nunavut.zip and /dev/null differ diff --git a/tests/data/cbf/Ontario.geojson b/tests/data/cbf/Ontario.geojson deleted file mode 100644 index f2654944650..00000000000 --- a/tests/data/cbf/Ontario.geojson +++ /dev/null @@ -1,7 +0,0 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} diff --git a/tests/data/cbf/Ontario.zip b/tests/data/cbf/Ontario.zip deleted file mode 100644 index 491265db755..00000000000 Binary files a/tests/data/cbf/Ontario.zip and /dev/null differ diff --git a/tests/data/cbf/PrinceEdwardIsland.geojson b/tests/data/cbf/PrinceEdwardIsland.geojson deleted file mode 100644 index f2654944650..00000000000 --- a/tests/data/cbf/PrinceEdwardIsland.geojson +++ /dev/null @@ -1,7 +0,0 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} diff --git a/tests/data/cbf/PrinceEdwardIsland.zip b/tests/data/cbf/PrinceEdwardIsland.zip deleted file mode 100644 index 1091af70ab7..00000000000 Binary files a/tests/data/cbf/PrinceEdwardIsland.zip and /dev/null differ diff --git a/tests/data/cbf/Quebec.geojson b/tests/data/cbf/Quebec.geojson deleted file mode 100644 index f2654944650..00000000000 --- a/tests/data/cbf/Quebec.geojson +++ /dev/null @@ -1,7 +0,0 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} diff --git a/tests/data/cbf/Quebec.zip b/tests/data/cbf/Quebec.zip deleted file mode 100644 index fc6cfcdf1b4..00000000000 Binary files a/tests/data/cbf/Quebec.zip and /dev/null differ diff --git a/tests/data/cbf/Saskatchewan.geojson b/tests/data/cbf/Saskatchewan.geojson deleted file mode 100644 index f2654944650..00000000000 --- a/tests/data/cbf/Saskatchewan.geojson +++ /dev/null @@ -1,7 +0,0 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} diff --git a/tests/data/cbf/Saskatchewan.zip b/tests/data/cbf/Saskatchewan.zip deleted file mode 100644 index 570c0d91ec5..00000000000 Binary files a/tests/data/cbf/Saskatchewan.zip and /dev/null differ diff --git a/tests/data/cbf/YukonTerritory.geojson b/tests/data/cbf/YukonTerritory.geojson deleted file mode 100644 index f2654944650..00000000000 --- a/tests/data/cbf/YukonTerritory.geojson +++ /dev/null @@ -1,7 +0,0 @@ -{ -"type": "FeatureCollection", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 0.0, 0.0 ], [ 0.0, 1.0 ], [ 1.0, 1.0 ], [ 1.0, 0.0 ], [ 0.0, 0.0 ] ] ] } } -] -} diff --git a/tests/data/cbf/YukonTerritory.zip b/tests/data/cbf/YukonTerritory.zip deleted file mode 100644 index 0bffe5b35ac..00000000000 Binary files a/tests/data/cbf/YukonTerritory.zip and /dev/null differ diff --git a/tests/data/cbf/data.py b/tests/data/cbf/data.py new file mode 100644 index 00000000000..28563ce3968 --- /dev/null +++ b/tests/data/cbf/data.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import hashlib +import json +import os +import shutil + + +def create_geojson(): + geojson = { + "type": "FeatureCollection", + "crs": { + "type": "name", + "properties": {"name": "urn:ogc:def:crs:OGC:1.3:CRS84"}, + }, + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0], [0.0, 0.0]] + ], + }, + } + ], + } + return geojson + + +if __name__ == "__main__": + filename = "Alberta.zip" + geojson = create_geojson() + + with open(filename.replace(".zip", ".geojson"), "w") as f: + json.dump(geojson, f) + + # compress single file directly with no directory + shutil.make_archive( + filename.replace(".zip", ""), + "zip", + os.getcwd(), + filename.replace(".zip", ".geojson"), + ) + + # Compute checksums + with open(filename, "rb") as f: + md5 = hashlib.md5(f.read()).hexdigest() + print(f"{filename}: {md5}") diff --git a/tests/datasets/test_cbf.py b/tests/datasets/test_cbf.py index 3189270b2c3..d664d117439 100644 --- a/tests/datasets/test_cbf.py +++ b/tests/datasets/test_cbf.py @@ -31,22 +31,12 @@ def dataset( self, monkeypatch: MonkeyPatch, tmp_path: Path ) -> CanadianBuildingFootprints: monkeypatch.setattr(torchgeo.datasets.utils, "download_url", download_url) - md5s = [ - "8a4a0a57367f67c69608d1452e30df13", - "1829f4054a9a81bb23871ca797a3895c", - "4358a0076fd43e9a2f436e74348813b0", - "ae3726b1263727d72565ecacfed56fb8", - "6861876d3a3ca7e79b28c61ab5906de4", - "d289c9ea49801bb287ddbde1ea5f31ef", - "3a940288297631b4e6a365266bfb949a", - "6b43b3632b165ff79c1ca0c693a61398", - "36283e0b29088ec281e77c989cbee100", - "773da9d33e3766b7237a1d7db0811832", - "cc833a65137c8a046c8f45bb695092b1", - "067664d066c4152fb96a5c129cbabadf", - "474bc084bc41b124aa4919e7a37a9648", - ] - monkeypatch.setattr(CanadianBuildingFootprints, "md5s", md5s) + monkeypatch.setattr( + CanadianBuildingFootprints, "provinces_territories", ["Alberta"] + ) + monkeypatch.setattr( + CanadianBuildingFootprints, "md5s", ["25091d1f051baa30d8f2026545cfb696"] + ) url = os.path.join("tests", "data", "cbf") + os.sep monkeypatch.setattr(CanadianBuildingFootprints, "url", url) monkeypatch.setattr(plt, "show", lambda *args: None) @@ -76,7 +66,13 @@ def test_already_downloaded(self, dataset: CanadianBuildingFootprints) -> None: def test_plot(self, dataset: CanadianBuildingFootprints) -> None: query = dataset.bounds x = dataset[query] - dataset.plot(x["mask"]) + dataset.plot(x, suptitle="Test") + + def test_plot_prediction(self, dataset: CanadianBuildingFootprints) -> None: + query = dataset.bounds + x = dataset[query] + x["prediction"] = x["mask"].clone() + dataset.plot(x, suptitle="Prediction") def test_not_downloaded(self, tmp_path: Path) -> None: with pytest.raises(RuntimeError, match="Dataset not found or corrupted."): diff --git a/torchgeo/datasets/cbf.py b/torchgeo/datasets/cbf.py index cfabfee60e7..9781d90ee20 100644 --- a/torchgeo/datasets/cbf.py +++ b/torchgeo/datasets/cbf.py @@ -6,6 +6,7 @@ import os from typing import Any, Callable, Dict, Optional +import matplotlib.pyplot as plt from rasterio.crs import CRS from .geo import VectorDataset @@ -120,3 +121,52 @@ def _download(self) -> None: self.root, md5=md5 if self.checksum else None, ) + + def plot( + self, + sample: Dict[str, Any], + show_titles: bool = True, + suptitle: Optional[str] = None, + ) -> plt.Figure: + """Plot a sample from the dataset. + + Args: + sample: a sample returned by :meth:`VectorDataset.__getitem__` + show_titles: flag indicating whether to show titles above each panel + suptitle: optional string to use as a suptitle + + Returns: + a matplotlib Figure with the rendered sample + + .. versionchanged:: 0.3 + Method now takes a sample dict, not a Tensor. Additionally, it is possible + to show subplot titles and/or use a custom suptitle. + """ + image = sample["mask"].squeeze(0) + ncols = 1 + + showing_prediction = "prediction" in sample + if showing_prediction: + pred = sample["prediction"].squeeze(0) + ncols = 2 + + fig, axs = plt.subplots(nrows=1, ncols=ncols, figsize=(4, 4)) + + if showing_prediction: + axs[0].imshow(image) + axs[0].axis("off") + axs[1].imshow(pred) + axs[1].axis("off") + if show_titles: + axs[0].set_title("Mask") + axs[1].set_title("Prediction") + else: + axs.imshow(image) + axs.axis("off") + if show_titles: + axs.set_title("Mask") + + if suptitle is not None: + plt.suptitle(suptitle) + + return fig diff --git a/torchgeo/datasets/geo.py b/torchgeo/datasets/geo.py index 55a76c4f1b7..88ec2447bbc 100644 --- a/torchgeo/datasets/geo.py +++ b/torchgeo/datasets/geo.py @@ -677,21 +677,6 @@ def __getitem__(self, query: BoundingBox) -> Dict[str, Any]: return sample - def plot(self, data: Tensor) -> None: - """Plot a data sample. - - Args: - data: the data to plot - """ - array = data.squeeze().numpy() - - # Plot the image - ax = plt.axes() - ax.imshow(array) - ax.axis("off") - plt.show() - plt.close() - class VisionDataset(Dataset[Dict[str, Any]], abc.ABC): """Abstract base class for datasets lacking geospatial information. diff --git a/torchgeo/datasets/openbuildings.py b/torchgeo/datasets/openbuildings.py index 2b630f9f8df..18690617cea 100644 --- a/torchgeo/datasets/openbuildings.py +++ b/torchgeo/datasets/openbuildings.py @@ -421,7 +421,7 @@ def _verify(self) -> None: "have manually downloaded the dataset as suggested in the documentation." ) - def plot( # type: ignore[override] + def plot( self, sample: Dict[str, Any], show_titles: bool = True,