Repository: microsoft/torchgeo

Issue:
Sentinel2 data set not able to locate data file downloaded from https://scihub.copernicus.eu
I see an error when I try to access the data downloaded from https://scihub.copernicus.eu/dhus/#/home for sentinel-2 using torchgeo Sentinel2 dataset. After investigating I found that the function does not uses the standard naming convention for sentinel-2 data products.

files downloaded from USGS Earth Explorer seem to have a different filename format.

Naming Conventions
https://sentinels.copernicus.eu/web/sentinel/user-guides/sentinel-2-msi/naming-convention
https://www.usgs.gov/centers/eros/science/sentinel-2-data-dictionary#tile_number

If there is a way to change file name please suggest.


----ERROR LOG----
```console
$ python train.py
Traceback (most recent call last):
  File "train.py", line 12, in <module>
    dataset = Sentinel2(root='./../data/sentinel', crs=None, transforms=None, bands=[], cache=True)
  File "/home/manish/projects/pytorch/torchgeo_lcc/torchgeo_env/lib/python3.8/site-packages/torchgeo/datasets/sentinel.py", line 103, in __init__
    super().__init__(root, crs, res, transforms, cache)
  File "/home/manish/projects/pytorch/torchgeo_lcc/torchgeo_env/lib/python3.8/site-packages/torchgeo/datasets/geo.py", line 374, in __init__
    raise FileNotFoundError(
FileNotFoundError: No Sentinel2 data was found in './../data/sentinel'
```


Discussion:
@tinkueg, sorry you've run into problems and are frustrated, and thanks for reporting the issue. That said, please refrain from opening future issues with such a hostile tone. The people that work on this library do so voluntarily in their spare time and do not need to read or respond to hostile issues. Also, feel free to contribute pull requests that fix or better document the issues you run into. We're all trying to make torchgeo into a better tool!
[calebrob6](https://github.com/calebrob6) I am new to open source projects and not a developer. I was unaware that it is supported by volunteers and I was thinking that it's Microsoft project! 
I have deleted my comments. Thanks for efforts by you all!
No problem! Again, thanks for reporting the issue (without issues we wouldn't be aware of problems like this) -- this is _definitely_ something we want to fix before an eventual 1.0 release.
[calebrob6](https://github.com/calebrob6) Is there a guideline that tells how I can update the documentation so that other people know about the current issues.. my be contribute by fixing things. 
I tend not to bother documenting bugs and instead try to fix them. In this case, this bug is relatively easy to fix. All we need to do is update the `filename_regex` to support both USGS Earth Explorer and Copernicus filename formats. If no one gets to it I can do this within a week.
Okay, I took a look at this. For others following this issue, this is what the file structure looks like:

### USGS EarthExplorer

```
├── L1C_T16TFM_A035544_20220412T163959.zip
└── S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE
    ├── GRANULE
    │   └── L1C_T16TFM_A035544_20220412T163959
    │       ├── IMG_DATA
    │       │   ├── T16TFM_20220412T162841_B01.jp2
    │       │   ├── T16TFM_20220412T162841_B02.jp2
    │       │   ├── T16TFM_20220412T162841_B03.jp2
    │       │   ├── T16TFM_20220412T162841_B04.jp2
    │       │   ├── T16TFM_20220412T162841_B05.jp2
    │       │   ├── T16TFM_20220412T162841_B06.jp2
    │       │   ├── T16TFM_20220412T162841_B07.jp2
    │       │   ├── T16TFM_20220412T162841_B08.jp2
    │       │   ├── T16TFM_20220412T162841_B09.jp2
    │       │   ├── T16TFM_20220412T162841_B10.jp2
    │       │   ├── T16TFM_20220412T162841_B11.jp2
    │       │   ├── T16TFM_20220412T162841_B12.jp2
    │       │   ├── T16TFM_20220412T162841_B8A.jp2
    │       │   └── T16TFM_20220412T162841_TCI.jp2
```

### Copernicus Open Access Hub

```
├── S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.zip
├── S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE
│   ├── GRANULE
│   │   └── L2A_T26EMU_A035569_20220414T110747
│   │       ├── IMG_DATA
│   │       │   ├── R10m
│   │       │   │   ├── T26EMU_20220414T110751_AOT_10m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B02_10m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B03_10m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B04_10m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B08_10m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_TCI_10m.jp2
│   │       │   │   └── T26EMU_20220414T110751_WVP_10m.jp2
│   │       │   ├── R20m
│   │       │   │   ├── T26EMU_20220414T110751_AOT_20m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B01_20m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B02_20m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B03_20m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B04_20m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B05_20m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B06_20m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B07_20m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B11_20m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B12_20m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_B8A_20m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_SCL_20m.jp2
│   │       │   │   ├── T26EMU_20220414T110751_TCI_20m.jp2
│   │       │   │   └── T26EMU_20220414T110751_WVP_20m.jp2
│   │       │   └── R60m
│   │       │       ├── T26EMU_20220414T110751_AOT_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_B01_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_B02_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_B03_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_B04_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_B05_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_B06_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_B07_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_B09_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_B11_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_B12_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_B8A_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_SCL_60m.jp2
│   │       │       ├── T26EMU_20220414T110751_TCI_60m.jp2
│   │       │       └── T26EMU_20220414T110751_WVP_60m.jp2
```
Although the zipfile name and directory structure is quite different, the filenames are almost identical except for the resolution extension at the end. So changing things to support USGS is easy (just make the resolution optional). But this raises the question of whether or not we're actually properly supporting Copernicus. Right now the resolution is just a wildcard, so we could pick up the same tile at multiple different resolutions. Also, when we search for matching tiles, I think we're replacing the resolution with a wildcard, so that could cause issues too. I'll have to think about this one. I think the correct solution is:

1. Change the `filename_glob` and `filename_regex` in `sentinel.py` to make the resolution optional
2. Remove replacement of `<resolution>` with wildcard in `geo.py`
3. Set the resolution used in `filename_regex` inside of `__init__` in `sentinel.py` based on user-specified `res`

Hopefully that should allow us to support both? I wish things were a bit more uniform. Also, we don't currently look at anything other than the filename, but other datasets will require use of the full filepath, so that may come into play at some point. Anyway, this will need extensive testing to make sure it works as expected. I'll try to get started on this soon.
@tinkueg in your issue, you mention that the dataset is unable to detect files downloaded from Copernicus. But our regex is actually designed for Copernicus, it should only be incompatible with EarthExplorer data. Can you share an example filename so I know what your data looks like?

Resolving patch:
diff --git a/torchgeo/datasets/geo.py b/torchgeo/datasets/geo.py
--- a/torchgeo/datasets/geo.py
+++ b/torchgeo/datasets/geo.py
@@ -282,7 +282,6 @@ class RasterDataset(GeoDataset):
     #: searched for to find other files:
     #:
     #: * ``band``: replaced with requested band name
-    #: * ``resolution``: replaced with a glob character
     filename_regex = ".*"
 
     #: Date format string used to parse date from filename.
@@ -412,10 +411,6 @@ def __getitem__(self, query: BoundingBox) -> Dict[str, Any]:
                             start = match.start("band")
                             end = match.end("band")
                             filename = filename[:start] + band + filename[end:]
-                        if "resolution" in match.groupdict():
-                            start = match.start("resolution")
-                            end = match.end("resolution")
-                            filename = filename[:start] + "*" + filename[end:]
                     filepath = glob.glob(os.path.join(directory, filename))[0]
                     band_filepaths.append(filepath)
                 data_list.append(self._merge_files(band_filepaths, query))
diff --git a/torchgeo/datasets/sentinel.py b/torchgeo/datasets/sentinel.py
--- a/torchgeo/datasets/sentinel.py
+++ b/torchgeo/datasets/sentinel.py
@@ -38,16 +38,14 @@ class Sentinel2(Sentinel):
     Earth's surface changes.
     """
 
-    # TODO: files downloaded from USGS Earth Explorer seem to have a different
-    # filename format than the official documentation
     # https://sentinels.copernicus.eu/web/sentinel/user-guides/sentinel-2-msi/naming-convention
     # https://sentinel.esa.int/documents/247904/685211/Sentinel-2-MSI-L2A-Product-Format-Specifications.pdf
-    filename_glob = "T*_*_B02_*m.*"
+    filename_glob = "T*_*_{}*.*"
     filename_regex = r"""
-        ^T(?P<tile>\d{2}[A-Z]{3})
-        _(?P<date>\d{8}T\d{6})
+        ^T(?P<tile>\d{{2}}[A-Z]{{3}})
+        _(?P<date>\d{{8}}T\d{{6}})
         _(?P<band>B[018][\dA])
-        _(?P<resolution>\d{2}m)
+        (?:_(?P<resolution>{}m))?
         \..*$
     """
     date_format = "%Y%m%dT%H%M%S"
@@ -76,7 +74,7 @@ def __init__(
         self,
         root: str = "data",
         crs: Optional[CRS] = None,
-        res: Optional[float] = None,
+        res: float = 10,
         bands: Sequence[str] = [],
         transforms: Optional[Callable[[Dict[str, Any]], Dict[str, Any]]] = None,
         cache: bool = True,
@@ -98,6 +96,8 @@ def __init__(
             FileNotFoundError: if no files are found in ``root``
         """
         self.bands = bands if bands else self.all_bands
+        self.filename_glob = self.filename_glob.format(self.bands[0])
+        self.filename_regex = self.filename_regex.format(res)
 
         super().__init__(root, crs, res, transforms, cache)
 


Test patch:
diff --git a/tests/data/agb_live_woody_density/data.py b/tests/data/agb_live_woody_density/data.py
--- a/tests/data/agb_live_woody_density/data.py
+++ b/tests/data/agb_live_woody_density/data.py
@@ -60,9 +60,9 @@ def create_file(path: str, dtype: str, num_channels: int) -> None:
             np.iinfo(profile["dtype"]).max, size=(SIZE, SIZE), dtype=profile["dtype"]
         )
 
-    src = rasterio.open(path, "w", **profile)
-    for i in range(1, profile["count"] + 1):
-        src.write(Z, i)
+    with rasterio.open(path, "w", **profile) as src:
+        for i in range(1, profile["count"] + 1):
+            src.write(Z, i)
 
 
 if __name__ == "__main__":
diff --git a/tests/data/astergdem/data.py b/tests/data/astergdem/data.py
--- a/tests/data/astergdem/data.py
+++ b/tests/data/astergdem/data.py
@@ -33,8 +33,8 @@ def create_file(path: str, dtype: str, num_channels: int) -> None:
     Z = np.random.randint(
         np.iinfo(profile["dtype"]).max, size=(1, SIZE, SIZE), dtype=profile["dtype"]
     )
-    src = rasterio.open(path, "w", **profile)
-    src.write(Z)
+    with rasterio.open(path, "w", **profile) as src:
+        src.write(Z)
 
 
 if __name__ == "__main__":
diff --git a/tests/data/cdl/data.py b/tests/data/cdl/data.py
--- a/tests/data/cdl/data.py
+++ b/tests/data/cdl/data.py
@@ -42,11 +42,11 @@ def create_file(path: str, dtype: str, num_channels: int) -> None:
 
     Z = np.random.randint(size=(SIZE, SIZE), low=0, high=8)
 
-    src = rasterio.open(path, "w", **profile)
-    for i in range(1, profile["count"] + 1):
-        src.write(Z, i)
+    with rasterio.open(path, "w", **profile) as src:
+        for i in range(1, profile["count"] + 1):
+            src.write(Z, i)
 
-    src.write_colormap(1, cmap)
+        src.write_colormap(1, cmap)
 
 
 directories = ["2020_30m_cdls", "2021_30m_cdls"]
diff --git a/tests/data/cms_mangrove_canopy/data.py b/tests/data/cms_mangrove_canopy/data.py
--- a/tests/data/cms_mangrove_canopy/data.py
+++ b/tests/data/cms_mangrove_canopy/data.py
@@ -39,8 +39,8 @@ def create_file(path: str, dtype: str, num_channels: int) -> None:
     Z = np.random.randint(
         np.iinfo(profile["dtype"]).max, size=(1, SIZE, SIZE), dtype=profile["dtype"]
     )
-    src = rasterio.open(path, "w", **profile)
-    src.write(Z)
+    with rasterio.open(path, "w", **profile) as src:
+        src.write(Z)
 
 
 if __name__ == "__main__":
diff --git a/tests/data/dfc2022/data.py b/tests/data/dfc2022/data.py
--- a/tests/data/dfc2022/data.py
+++ b/tests/data/dfc2022/data.py
@@ -70,9 +70,9 @@ def create_file(path: str, dtype: str, num_channels: int) -> None:
             np.iinfo(profile["dtype"]).max, size=(SIZE, SIZE), dtype=profile["dtype"]
         )
 
-    src = rasterio.open(path, "w", **profile)
-    for i in range(1, profile["count"] + 1):
-        src.write(Z, i)
+    with rasterio.open(path, "w", **profile) as src:
+        for i in range(1, profile["count"] + 1):
+            src.write(Z, i)
 
 
 if __name__ == "__main__":
diff --git a/tests/data/esri2020/data.py b/tests/data/esri2020/data.py
--- a/tests/data/esri2020/data.py
+++ b/tests/data/esri2020/data.py
@@ -33,8 +33,8 @@ def create_file(path: str, dtype: str, num_channels: int) -> None:
     Z = np.random.randint(
         np.iinfo(profile["dtype"]).max, size=(1, SIZE, SIZE), dtype=profile["dtype"]
     )
-    src = rasterio.open(path, "w", **profile)
-    src.write(Z)
+    with rasterio.open(path, "w", **profile) as src:
+        src.write(Z)
 
 
 if __name__ == "__main__":
diff --git a/tests/data/eudem/data.py b/tests/data/eudem/data.py
--- a/tests/data/eudem/data.py
+++ b/tests/data/eudem/data.py
@@ -30,8 +30,8 @@ def create_file(path: str, dtype: str, num_channels: int) -> None:
     Z = np.random.randint(
         np.iinfo(profile["dtype"]).max, size=(1, SIZE, SIZE), dtype=profile["dtype"]
     )
-    src = rasterio.open(path, "w", **profile)
-    src.write(Z)
+    with rasterio.open(path, "w", **profile) as src:
+        src.write(Z)
 
 
 if __name__ == "__main__":
diff --git a/tests/data/globbiomass/data.py b/tests/data/globbiomass/data.py
--- a/tests/data/globbiomass/data.py
+++ b/tests/data/globbiomass/data.py
@@ -36,8 +36,8 @@ def create_file(path: str, dtype: str, num_channels: int) -> None:
     Z = np.random.randint(
         np.iinfo(profile["dtype"]).max, size=(1, SIZE, SIZE), dtype=profile["dtype"]
     )
-    src = rasterio.open(path, "w", **profile)
-    src.write(Z)
+    with rasterio.open(path, "w", **profile) as src:
+        src.write(Z)
 
 
 if __name__ == "__main__":
diff --git a/tests/data/naip/data.py b/tests/data/naip/data.py
--- a/tests/data/naip/data.py
+++ b/tests/data/naip/data.py
@@ -61,9 +61,9 @@ def create_file(path: str, dtype: str, num_channels: int) -> None:
             np.iinfo(profile["dtype"]).max, size=(SIZE, SIZE), dtype=profile["dtype"]
         )
 
-    src = rasterio.open(path, "w", **profile)
-    for i in range(1, profile["count"] + 1):
-        src.write(Z, i)
+    with rasterio.open(path, "w", **profile) as src:
+        for i in range(1, profile["count"] + 1):
+            src.write(Z, i)
 
 
 if __name__ == "__main__":
diff --git a/tests/data/ref_cloud_cover_detection_challenge_v1/data.py b/tests/data/ref_cloud_cover_detection_challenge_v1/data.py
--- a/tests/data/ref_cloud_cover_detection_challenge_v1/data.py
+++ b/tests/data/ref_cloud_cover_detection_challenge_v1/data.py
@@ -123,9 +123,9 @@ def create_raster(path: str, dtype: str, num_channels: int, collection: str) ->
     elif collection == "labels":
         Z = np.random.randint(0, 2, (SIZE, SIZE)).astype(profile["dtype"])
 
-    src = rasterio.open(path, "w", **profile)
-    for i in range(1, profile["count"] + 1):
-        src.write(Z, i)
+    with rasterio.open(path, "w", **profile) as src:
+        for i in range(1, profile["count"] + 1):
+            src.write(Z, i)
 
 
 def create_source_item() -> Item:
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B01.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B01.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B01.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B02.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B02.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B02.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B03.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B03.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B03.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B04.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B04.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B04.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B05.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B05.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B05.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B06.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B06.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B06.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B07.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B07.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B07.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B08.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B08.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B08.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B09.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B09.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B09.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B10.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B10.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B10.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B11.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B11.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B11.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B12.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B12.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B12.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B8A.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B8A.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_B8A.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_TCI.jp2 b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_TCI.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE/GRANULE/L1C_T16TFM_A035544_20220412T163959/IMG_DATA/T16TFM_20220412T162841_TCI.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_AOT_10m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_AOT_10m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_AOT_10m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_B02_10m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_B02_10m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_B02_10m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_B03_10m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_B03_10m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_B03_10m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_B04_10m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_B04_10m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_B04_10m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_B08_10m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_B08_10m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_B08_10m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_TCI_10m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_TCI_10m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_TCI_10m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_WVP_10m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_WVP_10m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R10m/T26EMU_20220414T110751_WVP_10m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_AOT_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_AOT_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_AOT_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B01_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B01_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B01_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B02_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B02_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B02_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B03_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B03_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B03_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B04_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B04_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B04_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B05_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B05_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B05_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B06_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B06_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B06_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B07_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B07_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B07_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B11_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B11_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B11_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B12_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B12_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B12_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B8A_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B8A_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_B8A_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_SCL_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_SCL_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_SCL_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_TCI_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_TCI_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_TCI_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_WVP_20m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_WVP_20m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R20m/T26EMU_20220414T110751_WVP_20m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_AOT_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_AOT_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_AOT_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B01_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B01_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B01_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B02_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B02_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B02_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B03_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B03_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B03_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B04_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B04_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B04_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B05_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B05_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B05_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B06_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B06_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B06_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B07_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B07_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B07_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B09_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B09_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B09_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B11_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B11_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B11_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B12_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B12_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B12_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B8A_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B8A_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_B8A_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_SCL_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_SCL_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_SCL_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_TCI_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_TCI_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_TCI_60m.jp2 differ
diff --git a/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_WVP_60m.jp2 b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_WVP_60m.jp2
new file mode 100644
Binary files /dev/null and b/tests/data/sentinel2/S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE/GRANULE/L2A_T26EMU_A035569_20220414T110747/IMG_DATA/R60m/T26EMU_20220414T110751_WVP_60m.jp2 differ
diff --git a/tests/data/sentinel2/T41XNE_20200829T083611_B01_60m.tif b/tests/data/sentinel2/T41XNE_20200829T083611_B01_60m.tif
deleted file mode 100644
Binary files a/tests/data/sentinel2/T41XNE_20200829T083611_B01_60m.tif and /dev/null differ
diff --git a/tests/data/sentinel2/T41XNE_20200829T083611_B02_10m.tif b/tests/data/sentinel2/T41XNE_20200829T083611_B02_10m.tif
deleted file mode 100644
Binary files a/tests/data/sentinel2/T41XNE_20200829T083611_B02_10m.tif and /dev/null differ
diff --git a/tests/data/sentinel2/T41XNE_20200829T083611_B02_10m.tif.fake b/tests/data/sentinel2/T41XNE_20200829T083611_B02_10m.tif.fake
deleted file mode 100644
diff --git a/tests/data/sentinel2/T41XNE_20200829T083611_B03_10m.tif b/tests/data/sentinel2/T41XNE_20200829T083611_B03_10m.tif
deleted file mode 100644
Binary files a/tests/data/sentinel2/T41XNE_20200829T083611_B03_10m.tif and /dev/null differ
diff --git a/tests/data/sentinel2/T41XNE_20200829T083611_B04_10m.tif b/tests/data/sentinel2/T41XNE_20200829T083611_B04_10m.tif
deleted file mode 100644
Binary files a/tests/data/sentinel2/T41XNE_20200829T083611_B04_10m.tif and /dev/null differ
diff --git a/tests/data/sentinel2/T41XNE_20200829T083611_B05_20m.tif b/tests/data/sentinel2/T41XNE_20200829T083611_B05_20m.tif
deleted file mode 100644
Binary files a/tests/data/sentinel2/T41XNE_20200829T083611_B05_20m.tif and /dev/null differ
diff --git a/tests/data/sentinel2/T41XNE_20200829T083611_B06_20m.tif b/tests/data/sentinel2/T41XNE_20200829T083611_B06_20m.tif
deleted file mode 100644
Binary files a/tests/data/sentinel2/T41XNE_20200829T083611_B06_20m.tif and /dev/null differ
diff --git a/tests/data/sentinel2/T41XNE_20200829T083611_B07_20m.tif b/tests/data/sentinel2/T41XNE_20200829T083611_B07_20m.tif
deleted file mode 100644
Binary files a/tests/data/sentinel2/T41XNE_20200829T083611_B07_20m.tif and /dev/null differ
diff --git a/tests/data/sentinel2/T41XNE_20200829T083611_B08_10m.tif b/tests/data/sentinel2/T41XNE_20200829T083611_B08_10m.tif
deleted file mode 100644
Binary files a/tests/data/sentinel2/T41XNE_20200829T083611_B08_10m.tif and /dev/null differ
diff --git a/tests/data/sentinel2/T41XNE_20200829T083611_B09_60m.tif b/tests/data/sentinel2/T41XNE_20200829T083611_B09_60m.tif
deleted file mode 100644
Binary files a/tests/data/sentinel2/T41XNE_20200829T083611_B09_60m.tif and /dev/null differ
diff --git a/tests/data/sentinel2/T41XNE_20200829T083611_B11_20m.tif b/tests/data/sentinel2/T41XNE_20200829T083611_B11_20m.tif
deleted file mode 100644
Binary files a/tests/data/sentinel2/T41XNE_20200829T083611_B11_20m.tif and /dev/null differ
diff --git a/tests/data/sentinel2/T41XNE_20200829T083611_B8A_20m.tif b/tests/data/sentinel2/T41XNE_20200829T083611_B8A_20m.tif
deleted file mode 100644
Binary files a/tests/data/sentinel2/T41XNE_20200829T083611_B8A_20m.tif and /dev/null differ
diff --git a/tests/data/sentinel2/data.py b/tests/data/sentinel2/data.py
--- a/tests/data/sentinel2/data.py
+++ b/tests/data/sentinel2/data.py
@@ -4,40 +4,111 @@
 # Licensed under the MIT License.
 
 import os
+from typing import Dict, List, Union
 
 import numpy as np
 import rasterio
+from rasterio import Affine
+from rasterio.crs import CRS
 
-SIZE = 32
+SIZE = 36
 
 np.random.seed(0)
 
-filenames = [
-    "T41XNE_20200829T083611_B01_60m.tif",
-    "T41XNE_20200829T083611_B02_10m.tif",
-    "T41XNE_20200829T083611_B03_10m.tif",
-    "T41XNE_20200829T083611_B04_10m.tif",
-    "T41XNE_20200829T083611_B05_20m.tif",
-    "T41XNE_20200829T083611_B06_20m.tif",
-    "T41XNE_20200829T083611_B07_20m.tif",
-    "T41XNE_20200829T083611_B08_10m.tif",
-    "T41XNE_20200829T083611_B8A_20m.tif",
-    "T41XNE_20200829T083611_B09_60m.tif",
-    "T41XNE_20200829T083611_B11_20m.tif",
-]
+FILENAME_HIERARCHY = Union[Dict[str, "FILENAME_HIERARCHY"], List[str]]
+
+filenames: FILENAME_HIERARCHY = {
+    # USGS Earth Explorer
+    "S2A_MSIL1C_20220412T162841_N0400_R083_T16TFM_20220412T202300.SAFE": {
+        "GRANULE": {
+            "L1C_T16TFM_A035544_20220412T163959": {
+                "IMG_DATA": [
+                    "T16TFM_20220412T162841_B01.jp2",
+                    "T16TFM_20220412T162841_B02.jp2",
+                    "T16TFM_20220412T162841_B03.jp2",
+                    "T16TFM_20220412T162841_B04.jp2",
+                    "T16TFM_20220412T162841_B05.jp2",
+                    "T16TFM_20220412T162841_B06.jp2",
+                    "T16TFM_20220412T162841_B07.jp2",
+                    "T16TFM_20220412T162841_B08.jp2",
+                    "T16TFM_20220412T162841_B09.jp2",
+                    "T16TFM_20220412T162841_B10.jp2",
+                    "T16TFM_20220412T162841_B11.jp2",
+                    "T16TFM_20220412T162841_B12.jp2",
+                    "T16TFM_20220412T162841_B8A.jp2",
+                    "T16TFM_20220412T162841_TCI.jp2",
+                ]
+            }
+        }
+    },
+    # Copernicus Open Access Hub
+    "S2A_MSIL2A_20220414T110751_N0400_R108_T26EMU_20220414T165533.SAFE": {
+        "GRANULE": {
+            "L2A_T26EMU_A035569_20220414T110747": {
+                "IMG_DATA": {
+                    "R10m": [
+                        "T26EMU_20220414T110751_AOT_10m.jp2",
+                        "T26EMU_20220414T110751_B02_10m.jp2",
+                        "T26EMU_20220414T110751_B03_10m.jp2",
+                        "T26EMU_20220414T110751_B04_10m.jp2",
+                        "T26EMU_20220414T110751_B08_10m.jp2",
+                        "T26EMU_20220414T110751_TCI_10m.jp2",
+                        "T26EMU_20220414T110751_WVP_10m.jp2",
+                    ],
+                    "R20m": [
+                        "T26EMU_20220414T110751_AOT_20m.jp2",
+                        "T26EMU_20220414T110751_B01_20m.jp2",
+                        "T26EMU_20220414T110751_B02_20m.jp2",
+                        "T26EMU_20220414T110751_B03_20m.jp2",
+                        "T26EMU_20220414T110751_B04_20m.jp2",
+                        "T26EMU_20220414T110751_B05_20m.jp2",
+                        "T26EMU_20220414T110751_B06_20m.jp2",
+                        "T26EMU_20220414T110751_B07_20m.jp2",
+                        "T26EMU_20220414T110751_B11_20m.jp2",
+                        "T26EMU_20220414T110751_B12_20m.jp2",
+                        "T26EMU_20220414T110751_B8A_20m.jp2",
+                        "T26EMU_20220414T110751_SCL_20m.jp2",
+                        "T26EMU_20220414T110751_TCI_20m.jp2",
+                        "T26EMU_20220414T110751_WVP_20m.jp2",
+                    ],
+                    "R60m": [
+                        "T26EMU_20220414T110751_AOT_60m.jp2",
+                        "T26EMU_20220414T110751_B01_60m.jp2",
+                        "T26EMU_20220414T110751_B02_60m.jp2",
+                        "T26EMU_20220414T110751_B03_60m.jp2",
+                        "T26EMU_20220414T110751_B04_60m.jp2",
+                        "T26EMU_20220414T110751_B05_60m.jp2",
+                        "T26EMU_20220414T110751_B06_60m.jp2",
+                        "T26EMU_20220414T110751_B07_60m.jp2",
+                        "T26EMU_20220414T110751_B09_60m.jp2",
+                        "T26EMU_20220414T110751_B11_60m.jp2",
+                        "T26EMU_20220414T110751_B12_60m.jp2",
+                        "T26EMU_20220414T110751_B8A_60m.jp2",
+                        "T26EMU_20220414T110751_SCL_60m.jp2",
+                        "T26EMU_20220414T110751_TCI_60m.jp2",
+                        "T26EMU_20220414T110751_WVP_60m.jp2",
+                    ],
+                }
+            }
+        }
+    },
+}
 
 
 def create_file(path: str, dtype: str, num_channels: int) -> None:
+    res = 10
+    root, _ = os.path.splitext(path)
+    if root.endswith("m"):
+        res = int(root[-3:-1])
+
     profile = {}
-    profile["driver"] = "GTiff"
+    profile["driver"] = "JP2OpenJPEG"
     profile["dtype"] = dtype
     profile["count"] = num_channels
-    profile["crs"] = "epsg:4326"
-    profile["transform"] = rasterio.transform.from_bounds(0, 0, 1, 1, 1, 1)
-    profile["height"] = SIZE
-    profile["width"] = SIZE
-    profile["compress"] = "lzw"
-    profile["predictor"] = 2
+    profile["crs"] = CRS.from_epsg(32616)
+    profile["transform"] = Affine(res, 0.0, 399960.0, 0.0, -res, 4500000.0)
+    profile["height"] = round(SIZE * 10 / res)
+    profile["width"] = round(SIZE * 10 / res)
 
     if "float" in profile["dtype"]:
         Z = np.random.randn(SIZE, SIZE).astype(profile["dtype"])
@@ -46,14 +117,24 @@ def create_file(path: str, dtype: str, num_channels: int) -> None:
             np.iinfo(profile["dtype"]).max, size=(SIZE, SIZE), dtype=profile["dtype"]
         )
 
-    src = rasterio.open(path, "w", **profile)
-    for i in range(1, profile["count"] + 1):
-        src.write(Z, i)
+    with rasterio.open(path, "w", **profile) as src:
+        for i in range(1, profile["count"] + 1):
+            src.write(Z, i)
 
 
-if __name__ == "__main__":
-    for f in filenames:
-        if os.path.exists(f):
-            os.remove(f)
+def create_directory(directory: str, hierarchy: FILENAME_HIERARCHY) -> None:
+    if isinstance(hierarchy, dict):
+        # Recursive case
+        for key, value in hierarchy.items():
+            path = os.path.join(directory, key)
+            os.makedirs(path, exist_ok=True)
+            create_directory(path, value)
+    else:
+        # Base case
+        for value in hierarchy:
+            path = os.path.join(directory, value)
+            create_file(path, dtype="uint16", num_channels=1)
+
 
-        create_file(path=f, dtype="int32", num_channels=1)
+if __name__ == "__main__":
+    create_directory(".", filenames)
diff --git a/tests/data/usavars/data.py b/tests/data/usavars/data.py
--- a/tests/data/usavars/data.py
+++ b/tests/data/usavars/data.py
@@ -42,8 +42,8 @@ def create_file(path: str, dtype: str, num_channels: int) -> None:
     Z = np.random.randint(
         np.iinfo(profile["dtype"]).max, size=(4, SIZE, SIZE), dtype=profile["dtype"]
     )
-    src = rasterio.open(path, "w", **profile)
-    src.write(Z)
+    with rasterio.open(path, "w", **profile) as src:
+        src.write(Z)
 
 
 # Remove old data
diff --git a/tests/datasets/test_sentinel.py b/tests/datasets/test_sentinel.py
--- a/tests/datasets/test_sentinel.py
+++ b/tests/datasets/test_sentinel.py
@@ -17,24 +17,13 @@ class TestSentinel2:
     @pytest.fixture
     def dataset(self) -> Sentinel2:
         root = os.path.join("tests", "data", "sentinel2")
-        bands = [
-            "B01",
-            "B02",
-            "B03",
-            "B04",
-            "B05",
-            "B06",
-            "B07",
-            "B08",
-            "B8A",
-            "B09",
-            "B11",
-        ]
+        res = 10
+        bands = ["B02", "B03", "B04", "B08"]
         transforms = nn.Identity()
-        return Sentinel2(root, bands=bands, transforms=transforms)
+        return Sentinel2(root, res=res, bands=bands, transforms=transforms)
 
     def test_separate_files(self, dataset: Sentinel2) -> None:
-        assert dataset.index.count(dataset.index.bounds) == 1
+        assert dataset.index.count(dataset.index.bounds) == 2
 
     def test_getitem(self, dataset: Sentinel2) -> None:
         x = dataset[dataset.bounds]
@@ -60,8 +49,8 @@ def test_plot(self, dataset: Sentinel2) -> None:
         plt.close()
 
     def test_plot_wrong_bands(self, dataset: Sentinel2) -> None:
-        bands = ("B01",)
-        ds = Sentinel2(root=dataset.root, bands=bands)
+        bands = ["B02"]
+        ds = Sentinel2(root=dataset.root, res=dataset.res, bands=bands)
         x = dataset[dataset.bounds]
         with pytest.raises(
             ValueError, match="Dataset doesn't contain some of the RGB bands"