Repository: microsoft/torchgeo

Issue:
Landsat datasets don't support Level-1 products
 The part of _Geospatial datasets_ tells me that if I have downloaded Landsat8 images，I can use the code ：
`landsat8 = Landsat8(root="...", bands=["B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9"])`.
But when I run the code, the warning will appear:
`FileNotFoundError: No Landsat data was found in ...`
I make sure that my root is correct and I have downloaded Landsat8 image from USGS, but the warning also exist.



Discussion:
It could be that the filename format of the files you downloaded is different than what the dataset class expects. What do the filenames look like?
I have downloaded Landsat8 images from USGS, including _Landsat 8OLI/TIRS C1 Level-1_ products and _Landsat 8-9 OLI/TIRS C2 L1_ products. I don't know wheather they are suitable for torchgeo. 
Sincerely for your answer!
Can you share one of the filenames?
LC08_L1TP_020038_20211023_20211103_02_T1
Is there no file extension or spectral band in the filename? Are all bands in a single file?

It looks like our `Landsat` dataset is only designed to handle level 2 surface reflectance products, it doesn't know how to handle level 1 products. For now, a quick workaround would be:
```python
from torchgeo.datasets import Landsat8

Landsat8.filename_regex = r"""
    ^L                                                                               
    (?P<sensor>[COTEM])                                                              
    (?P<satellite>\d{2})                                                             
    _(?P<processing_correction_level>[A-Z0-9]{4})                                    
    _(?P<wrs_path>\d{3})                                                             
    (?P<wrs_row>\d{3})                                                               
    _(?P<date>\d{8})                                                                 
    _(?P<processing_date>\d{8})                                                      
    _(?P<collection_number>\d{2})                                                    
    _(?P<collection_category>[A-Z0-9]{2})                                                                                                            
"""
Landsat8.separate_files = False

landsat8 = Landsat8(root="...")
```
Let me know if the above code works. I'll need to think about how to handle both level 1 and 2 products. We may need separate datasets for both.
_LC08_L1TP_020038_20211023_20211103_02_T1_ is the name of folder and all relative files exist. All bands files in the folder. I don't change the format which is provided by USGS.
What are the names of the files in this folder? TorchGeo doesn't look at folder names at all.
Including _LC08_L1TP_020038_20211023_20211103_02_T1_B1.TIF_ ,_LC08_L1TP_020038_20211023_20211103_02_T1_B2.TIF_ and so on. And I try to fuse all bands to get a new tif file, but also can't be recognized. Therefore, I can make a concise conclusion that  TorchGeo is only designed to handle level 2 surface reflectance products which need to include all bands? 
Ah thanks, this is much simpler to handle than I expected. At some point in the near future I'll submit a PR to fix this. In the meantime, the following should work:
```python
from torchgeo.datasets import Landsat8

Landsat8.filename_regex = Landsat8.filename_regex.replace("_SR", "")

landsat8 = Landsat8(root="...")
```

Resolving patch:
diff --git a/torchgeo/datasets/landsat.py b/torchgeo/datasets/landsat.py
--- a/torchgeo/datasets/landsat.py
+++ b/torchgeo/datasets/landsat.py
@@ -4,7 +4,7 @@
 """Landsat datasets."""
 
 import abc
-from typing import Any, Callable, Dict, List, Optional, Sequence
+from typing import Any, Callable, Dict, Optional, Sequence
 
 from rasterio.crs import CRS
 
@@ -20,11 +20,17 @@ class Landsat(RasterDataset, abc.ABC):
     If you use this dataset in your research, please cite it using the following format:
 
     * https://www.usgs.gov/centers/eros/data-citation
-    """
 
-    # https://www.usgs.gov/faqs/what-naming-convention-landsat-collections-level-1-scenes
-    # https://www.usgs.gov/faqs/what-naming-convention-landsat-collection-2-level-1-and-level-2-scenes
-    filename_glob = ""
+    If you use any of the following Level-2 products, there may be additional citation
+    requirements, including papers you can cite. See the "Citation Information" section
+    of the following pages:
+
+    * `Surface Temperature <https://www.usgs.gov/landsat-missions/landsat-collection-2-surface-temperature>`_
+    * `Surface Reflectance <https://www.usgs.gov/landsat-missions/landsat-collection-2-surface-reflectance>`_
+    * `U.S. Analysis Ready Data <https://www.usgs.gov/landsat-missions/landsat-collection-2-us-analysis-ready-data>`_
+    """  # noqa: E501
+
+    # https://www.usgs.gov/landsat-missions/landsat-collection-2
     filename_regex = r"""
         ^L
         (?P<sensor>[COTEM])
@@ -36,15 +42,10 @@ class Landsat(RasterDataset, abc.ABC):
         _(?P<processing_date>\d{8})
         _(?P<collection_number>\d{2})
         _(?P<collection_category>[A-Z0-9]{2})
-        _SR
-        _(?P<band>B\d+)
-        \..*$
+        _(?P<band>[A-Z0-9_]+)
+        \.
     """
 
-    # https://www.usgs.gov/faqs/what-are-band-designations-landsat-satellites
-    all_bands: List[str] = []
-    rgb_bands: List[str] = []
-
     separate_files = True
 
     def __init__(
@@ -73,6 +74,7 @@ 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])
 
         super().__init__(root, crs, res, transforms, cache)
 
@@ -80,73 +82,85 @@ def __init__(
 class Landsat1(Landsat):
     """Landsat 1 Multispectral Scanner (MSS)."""
 
-    filename_glob = "LM01_*_SR_B4.*"
+    filename_glob = "LM01_*_{}.*"
 
-    all_bands = ["B4", "B5", "B6", "B7"]
-    rgb_bands = ["B6", "B5", "B4"]
+    all_bands = ["SR_B4", "SR_B5", "SR_B6", "SR_B7"]
+    rgb_bands = ["SR_B6", "SR_B5", "SR_B4"]
 
 
 class Landsat2(Landsat1):
     """Landsat 2 Multispectral Scanner (MSS)."""
 
-    filename_glob = "LM02_*_SR_B4.*"
+    filename_glob = "LM02_*_{}.*"
 
 
 class Landsat3(Landsat1):
     """Landsat 3 Multispectral Scanner (MSS)."""
 
-    filename_glob = "LM03_*_SR_B4.*"
+    filename_glob = "LM03_*_{}.*"
 
 
 class Landsat4MSS(Landsat):
     """Landsat 4 Multispectral Scanner (MSS)."""
 
-    filename_glob = "LM04_*_SR_B1.*"
+    filename_glob = "LM04_*_{}.*"
 
-    all_bands = ["B1", "B2", "B3", "B4"]
-    rgb_bands = ["B3", "B2", "B1"]
+    all_bands = ["SR_B1", "SR_B2", "SR_B3", "SR_B4"]
+    rgb_bands = ["SR_B3", "SR_B2", "SR_B1"]
 
 
 class Landsat4TM(Landsat):
     """Landsat 4 Thematic Mapper (TM)."""
 
-    filename_glob = "LT04_*_SR_B1.*"
+    filename_glob = "LT04_*_{}.*"
 
-    all_bands = ["B1", "B2", "B3", "B4", "B5", "B6", "B7"]
-    rgb_bands = ["B3", "B2", "B1"]
+    all_bands = ["SR_B1", "SR_B2", "SR_B3", "SR_B4", "SR_B5", "SR_B6", "SR_B7"]
+    rgb_bands = ["SR_B3", "SR_B2", "SR_B1"]
 
 
 class Landsat5MSS(Landsat4MSS):
     """Landsat 4 Multispectral Scanner (MSS)."""
 
-    filename_glob = "LM04_*_SR_B1.*"
+    filename_glob = "LM04_*_{}.*"
 
 
 class Landsat5TM(Landsat4TM):
     """Landsat 5 Thematic Mapper (TM)."""
 
-    filename_glob = "LT05_*_SR_B1.*"
+    filename_glob = "LT05_*_{}.*"
 
 
 class Landsat7(Landsat):
     """Landsat 7 Enhanced Thematic Mapper Plus (ETM+)."""
 
-    filename_glob = "LE07_*_SR_B1.*"
+    filename_glob = "LE07_*_{}.*"
 
-    all_bands = ["B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8"]
-    rgb_bands = ["B3", "B2", "B1"]
+    all_bands = ["SR_B1", "SR_B2", "SR_B3", "SR_B4", "SR_B5", "SR_B6", "SR_B7", "SR_B8"]
+    rgb_bands = ["SR_B3", "SR_B2", "SR_B1"]
 
 
 class Landsat8(Landsat):
     """Landsat 8 Operational Land Imager (OLI) and Thermal Infrared Sensor (TIRS)."""
 
-    filename_glob = "LC08_*_SR_B2.*"
+    filename_glob = "LC08_*_{}.*"
 
-    all_bands = ["B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "B10", "B11"]
-    rgb_bands = ["B4", "B3", "B2"]
+    all_bands = [
+        "SR_B1",
+        "SR_B2",
+        "SR_B3",
+        "SR_B4",
+        "SR_B5",
+        "SR_B6",
+        "SR_B7",
+        "SR_B8",
+        "SR_B9",
+        "SR_B10",
+        "SR_B11",
+    ]
+    rgb_bands = ["SR_B4", "SR_B3", "SR_B2"]
 
 
 class Landsat9(Landsat8):
     """Landsat 9 Operational Land Imager (OLI) and Thermal Infrared Sensor (TIRS)."""
 
-    filename_glob = "LC09_*_SR_B2.*"
+    filename_glob = "LC09_*_{}.*"


Test patch:
diff --git a/tests/datasets/test_landsat.py b/tests/datasets/test_landsat.py
--- a/tests/datasets/test_landsat.py
+++ b/tests/datasets/test_landsat.py
@@ -17,7 +17,7 @@ class TestLandsat8:
     @pytest.fixture
     def dataset(self, monkeypatch: MonkeyPatch) -> Landsat8:
         root = os.path.join("tests", "data", "landsat8")
-        bands = ["B1", "B2", "B3", "B4", "B5", "B6", "B7"]
+        bands = ["SR_B1", "SR_B2", "SR_B3", "SR_B4", "SR_B5", "SR_B6", "SR_B7"]
         transforms = nn.Identity()  # type: ignore[no-untyped-call]
         return Landsat8(root, bands=bands, transforms=transforms)