Skip to content

Commit

Permalink
0.2.0 release (#348)
Browse files Browse the repository at this point in the history
* 0.2.0 release

* Fix notebooks

* Fix minimal dependency tests

* Fix integration tests

* Fix integration tests

* Try to avoid running GitHub Actions twice on release PRs

* Revert "Try to avoid running GitHub Actions twice on release PRs"

This reverts commit a1ac7ab.

* GeoDatasets use intersection, not addition

* Adding stack_samples to benchmarks

* Fix zero division error in SEN12MS tests

* Replaces test models with dummy models (#344)

Co-authored-by: Adam J. Stewart <[email protected]>

* lc values must be < num_classes

* updated indices tutorial with latest indices

Co-authored-by: Caleb Robinson <[email protected]>
Co-authored-by: isaaccorley <[email protected]>
  • Loading branch information
3 people authored Jan 2, 2022
1 parent 42b9a6d commit 7f27ede
Show file tree
Hide file tree
Showing 49 changed files with 307 additions and 77 deletions.
17 changes: 9 additions & 8 deletions docs/tutorials/benchmarking.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"metadata": {
"gather": {
"logged": 1629238744113
Expand All @@ -75,7 +75,7 @@
"from torch.utils.data import DataLoader\n",
"\n",
"from torchgeo.datasets import NAIP, ChesapeakeDE\n",
"from torchgeo.datasets.utils import download_url\n",
"from torchgeo.datasets.utils import download_url, stack_samples\n",
"from torchgeo.samplers import RandomGeoSampler, GridGeoSampler, RandomBatchGeoSampler"
]
},
Expand Down Expand Up @@ -209,9 +209,9 @@
"for cache in [False, True]:\n",
" chesapeake = ChesapeakeDE(chesapeake_root, cache=cache)\n",
" naip = NAIP(naip_root, crs=chesapeake.crs, res=chesapeake.res, cache=cache)\n",
" dataset = chesapeake + naip\n",
" dataset = chesapeake & naip\n",
" sampler = RandomGeoSampler(naip, size=1000, length=888)\n",
" dataloader = DataLoader(dataset, batch_size=12, sampler=sampler)\n",
" dataloader = DataLoader(dataset, batch_size=12, sampler=sampler, collate_fn=stack_samples)\n",
" duration, count = time_epoch(dataloader)\n",
" print(duration, count)"
]
Expand Down Expand Up @@ -260,9 +260,9 @@
"for cache in [False, True]:\n",
" chesapeake = ChesapeakeDE(chesapeake_root, cache=cache)\n",
" naip = NAIP(naip_root, crs=chesapeake.crs, res=chesapeake.res, cache=cache)\n",
" dataset = chesapeake + naip\n",
" dataset = chesapeake & naip\n",
" sampler = GridGeoSampler(naip, size=1000, stride=500)\n",
" dataloader = DataLoader(dataset, batch_size=12, sampler=sampler)\n",
" dataloader = DataLoader(dataset, batch_size=12, sampler=sampler, collate_fn=stack_samples)\n",
" duration, count = time_epoch(dataloader)\n",
" print(duration, count)"
]
Expand Down Expand Up @@ -311,9 +311,9 @@
"for cache in [False, True]:\n",
" chesapeake = ChesapeakeDE(chesapeake_root, cache=cache)\n",
" naip = NAIP(naip_root, crs=chesapeake.crs, res=chesapeake.res, cache=cache)\n",
" dataset = chesapeake + naip\n",
" dataset = chesapeake & naip\n",
" sampler = RandomBatchGeoSampler(naip, size=1000, batch_size=12, length=888)\n",
" dataloader = DataLoader(dataset, batch_sampler=sampler)\n",
" dataloader = DataLoader(dataset, batch_sampler=sampler, collate_fn=stack_samples)\n",
" duration, count = time_epoch(dataloader)\n",
" print(duration, count)"
]
Expand Down Expand Up @@ -345,6 +345,7 @@
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
},
"nteract": {
Expand Down
130 changes: 88 additions & 42 deletions docs/tutorials/indices.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/tutorials/trainers.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
"import pytorch_lightning as pl\n",
"from pytorch_lightning.callbacks import EarlyStopping, ModelCheckpoint\n",
"from pytorch_lightning.loggers import CSVLogger\n",
"from torchgeo.datasets import CycloneDataModule\n",
"from torchgeo.datamodules import CycloneDataModule\n",
"from torchgeo.trainers import RegressionTask"
]
},
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1158_spring_lc.tar.gz
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1158_spring_s1.tar.gz
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1158_spring_s2.tar.gz
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1868_summer_lc.tar.gz
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1868_summer_s1.tar.gz
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1868_summer_s2.tar.gz
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1970_fall/lc_1/ROIs1970_fall_lc_1_p1.tif
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1970_fall/lc_1/ROIs1970_fall_lc_1_p2.tif
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1970_fall/s1_1/ROIs1970_fall_s1_1_p1.tif
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1970_fall/s1_1/ROIs1970_fall_s1_1_p2.tif
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1970_fall/s2_1/ROIs1970_fall_s2_1_p1.tif
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1970_fall/s2_1/ROIs1970_fall_s2_1_p2.tif
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1970_fall_lc.tar.gz
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1970_fall_s1.tar.gz
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs1970_fall_s2.tar.gz
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs2017_winter_lc.tar.gz
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs2017_winter_s1.tar.gz
Binary file not shown.
Binary file modified tests/data/sen12ms/ROIs2017_winter_s2.tar.gz
Binary file not shown.
82 changes: 82 additions & 0 deletions tests/data/sen12ms/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env python3

# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import hashlib
import os
import shutil

import numpy as np
import rasterio
from rasterio.transform import Affine
from rasterio.crs import CRS

SIZE = 64 # image width/height

np.random.seed(0)

meta = {
"driver": "GTiff",
"nodata": None,
"width": SIZE,
"height": SIZE,
"crs": CRS.from_epsg(32737),
"transform": Affine(10.0, 0.0, 390772.3389928384, 0.0, -10.0, 8114182.836060452),
}
count = {"lc": 4, "s1": 2, "s2": 13}
dtype = {"lc": np.uint16, "s1": np.float32, "s2": np.uint16}
stop = {"lc": 11, "s1": np.iinfo(np.uint16).max, "s2": np.iinfo(np.uint16).max}

file_list = []
seasons = ["ROIs1158_spring", "ROIs1868_summer", "ROIs1970_fall", "ROIs2017_winter"]
for season in seasons:
# Remove old data
if os.path.exists(season):
shutil.rmtree(season)

for source in ["lc", "s1", "s2"]:
tarball = f"{season}_{source}.tar.gz"

# Remove old data
if os.path.exists(tarball):
os.remove(tarball)

directory = os.path.join(season, f"{source}_1")
os.makedirs(directory)

# Random images
for i in range(1, 3):
filename = f"{season}_{source}_1_p{i}.tif"
meta["count"] = count[source]
meta["dtype"] = dtype[source]
with rasterio.open(os.path.join(directory, filename), "w", **meta) as f:
for j in range(1, count[source] + 1):
data = np.random.randint(stop[source], size=(SIZE, SIZE)).astype(
dtype[source]
)
f.write(data, j)

if source == "s2":
file_list.append(filename)

# Create tarballs
shutil.make_archive(f"{season}_{source}", "gztar", ".", directory)

# Compute checksums
with open(tarball, "rb") as f:
md5 = hashlib.md5(f.read()).hexdigest()
print(repr(md5) + ",")

for split in ["train", "test"]:
filename = f"{split}_list.txt"

# Create file list
with open(filename, "w") as f:
for fname in file_list:
f.write(f"{fname}\n")

# Compute checksums
with open(filename, "rb") as f:
md5 = hashlib.md5(f.read()).hexdigest()
print(repr(md5) + ",")
26 changes: 14 additions & 12 deletions tests/datasets/test_sen12ms.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,20 @@ def dataset(
self, monkeypatch: Generator[MonkeyPatch, None, None], request: SubRequest
) -> SEN12MS:
md5s = [
"7f14be13d3f62c09b4dd5b4d55c97fd6",
"48182d44b375360381f36d432956b225",
"96cf1b8405d4149c6fe61ad7100bd65d",
"ba8e7e10fba9eea6900ddc530c86025a",
"7ba7c51f2fb3a2074b7bbd3e24f9d70d",
"280c9be2d1e13e663824dccd85e1e42f",
"a5284baf48534d4bc77acb1b103ff16c",
"c6b176fed0cdd5033cb1835506e40ee4",
"adc672746b79be4c4edc8b1a564e3ff4",
"194fab4a4e067a0452824c4e39f61b77",
"7899c0c36c884ae8c991ab8518b0d177",
"ccfee543d4351bcc5aa68729e8cc795c",
"b7d9e183a460979e997b443517a78ded",
"7131dbb098c832fff84c2b8a0c8f1126",
"b1057fea6ced6d648e5b16efeac352ad",
"2da32111fcfb80939aea7b18c2250fa8",
"c688ad6475660dbdbc36f66a1dd07da7",
"2ecd0dce2a21372513955c604b07e24f",
"dbc84c03edf77a68f789a6f7d2ea66a9",
"3e42a7dc4bb1ecd8c588930bf49b5c2b",
"c29053cb8cf5d75e333b1b51d37f62fe",
"5b6880526bc6da488154092741392042",
"d1b51c39b1013f2779fecf1f362f6c28",
"078def1e13ce4e88632d65f5c73a6259",
"02d5128ac1fc2bf8762091b4f319762d",
"02d5128ac1fc2bf8762091b4f319762d",
]

monkeypatch.setattr(SEN12MS, "md5s", md5s) # type: ignore[attr-defined]
Expand Down
10 changes: 7 additions & 3 deletions tests/samplers/test_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from rasterio.crs import CRS
from torch.utils.data import DataLoader

from torchgeo.datasets import BoundingBox, GeoDataset
from torchgeo.datasets import BoundingBox, GeoDataset, stack_samples
from torchgeo.samplers import BatchGeoSampler, RandomBatchGeoSampler


Expand Down Expand Up @@ -51,7 +51,9 @@ def test_len(self, sampler: CustomBatchGeoSampler) -> None:
@pytest.mark.parametrize("num_workers", [0, 1, 2])
def test_dataloader(self, sampler: CustomBatchGeoSampler, num_workers: int) -> None:
ds = CustomGeoDataset()
dl = DataLoader(ds, batch_sampler=sampler, num_workers=num_workers)
dl = DataLoader(
ds, batch_sampler=sampler, num_workers=num_workers, collate_fn=stack_samples
)
for _ in dl:
continue

Expand Down Expand Up @@ -100,6 +102,8 @@ def test_roi(self) -> None:
@pytest.mark.parametrize("num_workers", [0, 1, 2])
def test_dataloader(self, sampler: RandomBatchGeoSampler, num_workers: int) -> None:
ds = CustomGeoDataset()
dl = DataLoader(ds, batch_sampler=sampler, num_workers=num_workers)
dl = DataLoader(
ds, batch_sampler=sampler, num_workers=num_workers, collate_fn=stack_samples
)
for _ in dl:
continue
14 changes: 10 additions & 4 deletions tests/samplers/test_single.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from rasterio.crs import CRS
from torch.utils.data import DataLoader

from torchgeo.datasets import BoundingBox, GeoDataset
from torchgeo.datasets import BoundingBox, GeoDataset, stack_samples
from torchgeo.samplers import GeoSampler, GridGeoSampler, RandomGeoSampler


Expand Down Expand Up @@ -55,7 +55,9 @@ def test_abstract(self) -> None:
@pytest.mark.parametrize("num_workers", [0, 1, 2])
def test_dataloader(self, sampler: CustomGeoSampler, num_workers: int) -> None:
ds = CustomGeoDataset()
dl = DataLoader(ds, sampler=sampler, num_workers=num_workers)
dl = DataLoader(
ds, sampler=sampler, num_workers=num_workers, collate_fn=stack_samples
)
for _ in dl:
continue

Expand Down Expand Up @@ -97,7 +99,9 @@ def test_roi(self) -> None:
@pytest.mark.parametrize("num_workers", [0, 1, 2])
def test_dataloader(self, sampler: RandomGeoSampler, num_workers: int) -> None:
ds = CustomGeoDataset()
dl = DataLoader(ds, sampler=sampler, num_workers=num_workers)
dl = DataLoader(
ds, sampler=sampler, num_workers=num_workers, collate_fn=stack_samples
)
for _ in dl:
continue

Expand Down Expand Up @@ -145,6 +149,8 @@ def test_roi(self) -> None:
@pytest.mark.parametrize("num_workers", [0, 1, 2])
def test_dataloader(self, sampler: GridGeoSampler, num_workers: int) -> None:
ds = CustomGeoDataset()
dl = DataLoader(ds, sampler=sampler, num_workers=num_workers)
dl = DataLoader(
ds, sampler=sampler, num_workers=num_workers, collate_fn=stack_samples
)
for _ in dl:
continue
4 changes: 4 additions & 0 deletions tests/trainers/test_byol.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from torchgeo.trainers import BYOLTask
from torchgeo.trainers.byol import BYOL, SimCLRAugmentation

from .test_utils import ClassificationTestModel


class TestBYOL:
def test_custom_augment_fn(self) -> None:
Expand Down Expand Up @@ -53,6 +55,8 @@ def test_trainer(self, name: str, classname: Type[LightningDataModule]) -> None:
model_kwargs = conf_dict["module"]
model = BYOLTask(**model_kwargs)

model.encoder = ClassificationTestModel(**model_kwargs)

# Instantiate trainer
trainer = Trainer(fast_dev_run=True, log_every_n_steps=1)
trainer.fit(model=model, datamodule=datamodule)
Expand Down
33 changes: 29 additions & 4 deletions tests/trainers/test_classification.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
# Licensed under the MIT License.

import os
from typing import Any, Dict, Type, cast
from typing import Any, Dict, Generator, Type, cast

import pytest
import timm
from _pytest.monkeypatch import MonkeyPatch
from omegaconf import OmegaConf
from pytorch_lightning import LightningDataModule, Trainer
from torch.nn.modules import Module

from torchgeo.datamodules import (
BigEarthNetDataModule,
Expand All @@ -17,6 +20,12 @@
)
from torchgeo.trainers import ClassificationTask, MultiLabelClassificationTask

from .test_utils import ClassificationTestModel


def create_model(*args: Any, **kwargs: Any) -> Module:
return ClassificationTestModel(**kwargs)


class TestClassificationTask:
@pytest.mark.parametrize(
Expand All @@ -29,8 +38,13 @@ class TestClassificationTask:
("ucmerced", UCMercedDataModule),
],
)
def test_trainer(self, name: str, classname: Type[LightningDataModule]) -> None:
if name == "so2sat":
def test_trainer(
self,
monkeypatch: Generator[MonkeyPatch, None, None],
name: str,
classname: Type[LightningDataModule],
) -> None:
if name.startswith("so2sat"):
pytest.importorskip("h5py")

conf = OmegaConf.load(os.path.join("conf", "task_defaults", name + ".yaml"))
Expand All @@ -42,6 +56,9 @@ def test_trainer(self, name: str, classname: Type[LightningDataModule]) -> None:
datamodule = classname(**datamodule_kwargs)

# Instantiate model
monkeypatch.setattr( # type: ignore[attr-defined]
timm, "create_model", create_model
)
model_kwargs = conf_dict["module"]
model = ClassificationTask(**model_kwargs)

Expand Down Expand Up @@ -119,7 +136,12 @@ class TestMultiLabelClassificationTask:
("bigearthnet_s2", BigEarthNetDataModule),
],
)
def test_trainer(self, name: str, classname: Type[LightningDataModule]) -> None:
def test_trainer(
self,
monkeypatch: Generator[MonkeyPatch, None, None],
name: str,
classname: Type[LightningDataModule],
) -> None:
conf = OmegaConf.load(os.path.join("conf", "task_defaults", name + ".yaml"))
conf_dict = OmegaConf.to_object(conf.experiment)
conf_dict = cast(Dict[Any, Dict[Any, Any]], conf_dict)
Expand All @@ -129,6 +151,9 @@ def test_trainer(self, name: str, classname: Type[LightningDataModule]) -> None:
datamodule = classname(**datamodule_kwargs)

# Instantiate model
monkeypatch.setattr( # type: ignore[attr-defined]
timm, "create_model", create_model
)
model_kwargs = conf_dict["module"]
model = MultiLabelClassificationTask(**model_kwargs)

Expand Down
4 changes: 4 additions & 0 deletions tests/trainers/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from torchgeo.datamodules import COWCCountingDataModule, CycloneDataModule
from torchgeo.trainers import RegressionTask

from .test_utils import RegressionTestModel


class TestRegressionTask:
@pytest.mark.parametrize(
Expand All @@ -30,6 +32,8 @@ def test_trainer(self, name: str, classname: Type[LightningDataModule]) -> None:
model_kwargs = conf_dict["module"]
model = RegressionTask(**model_kwargs)

model.model = RegressionTestModel()

# Instantiate trainer
trainer = Trainer(fast_dev_run=True, log_every_n_steps=1)
trainer.fit(model=model, datamodule=datamodule)
Expand Down
Loading

0 comments on commit 7f27ede

Please sign in to comment.