Error: Data collection does not define bands

Hi Team,

We have a customer experiencing an issue that seems to require additional parameter settings to resolve.
The collection is filled with PlanetScope data, and the bands are the usual blue, red, green.
However, I’m having trouble pinpointing the exact source of the problem. Could anyone with expertise in this area advise or assist?

from sentinelhub import Geometry, SHConfig

from sentinelhub import CRS, DataCollection

from eolearn.io import SentinelHubInputTask

from shapely.geometry import Polygon

config = SHConfig()
coordinates = [
    [],
    [],
    [],
    [],
    [],
]
polygon = Polygon(coordinates)
geometry = Geometry(geometry=polygon, crs=CRS.WGS84)

data_collection = DataCollection.define_byoc('XXXX')
input_task = SentinelHubInputTask(
    config=config,
    data_collection=data_collection,
    resolution=3,
    bands=["blue", "red"],
)
eop = input_task.execute(geometry=geometry, bbox=geometry.bbox, time_interval=('2024-01-16', '2024-04-16'))

Traceback (most recent call last):
  File "/Users/guyon.duifhuizen/Projects/scripts/venv/lib/python3.11/site-packages/IPython/core/interactiveshell.py", line 3577, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-28-dd4d9e7aa7cd>", line 27, in <module>
    eop = input_task.execute(geometry=geometry, bbox=geometry.bbox, time_interval=('2024-01-16', '2024-04-16'))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/guyon.duifhuizen/Projects/scripts/venv/lib/python3.11/site-packages/eolearn/io/sentinelhub_process.py", line 118, in execute
    sh_requests = self._build_requests(area_bbox, size_x, size_y, timestamps, time_interval, geometry)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/guyon.duifhuizen/Projects/scripts/venv/lib/python3.11/site-packages/eolearn/io/sentinelhub_process.py", line 483, in _build_requests
    return [self._create_sh_request(time_interval, bbox, size_x, size_y, geometry) for time_interval in intervals]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/guyon.duifhuizen/Projects/scripts/venv/lib/python3.11/site-packages/eolearn/io/sentinelhub_process.py", line 483, in <listcomp>
    return [self._create_sh_request(time_interval, bbox, size_x, size_y, geometry) for time_interval in intervals]
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/guyon.duifhuizen/Projects/scripts/venv/lib/python3.11/site-packages/eolearn/io/sentinelhub_process.py", line 498, in _create_sh_request
    evalscript = generate_evalscript(
                 ^^^^^^^^^^^^^^^^^^^^
  File "/Users/guyon.duifhuizen/Projects/scripts/venv/lib/python3.11/site-packages/sentinelhub/evalscript.py", line 90, in generate_evalscript
    requested_bands = parse_data_collection_bands(data_collection, band_names + meta_band_names)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/guyon.duifhuizen/Projects/scripts/venv/lib/python3.11/site-packages/sentinelhub/evalscript.py", line 52, in parse_data_collection_bands
    band_info_dict = {band_info.name: band_info for band_info in data_collection.bands + data_collection.metabands}
                                                                 ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/guyon.duifhuizen/Projects/scripts/venv/lib/python3.11/site-packages/sentinelhub/data_collections.py", line 605, in bands
    raise ValueError(f"Data collection {self.name} does not define bands")
ValueError: Data collection BYOC_xxxx does not define bands

Solution: Use SentinelHubEvalscriptTaks instead of SentinelHubInputTask

You can leverage the EvalScript in setting your input & output bands, otherwise you’d have to specify those in the DataCollection.define_byoc(id, bands=[Band()…

from sentinelhub import Geometry, SHConfig

from sentinelhub import CRS, DataCollection, get_utm_crs

from eolearn.io import SentinelHubEvalscriptTask
from eolearn.core import FeatureType
from shapely.geometry import Polygon


evalscript_true_color = """
//VERSION=3
function setup() {
  return {
    input: ["blue","green","red", "dataMask"],
    output: [{ 
      id: "BANDS",
      bands: 3
    }]
  };
}

function evaluatePixel(sample) {
  return {
      BANDS: [sample.blue, sample.green, sample.red]
  };
}
"""

config = SHConfig()

coordinates = [
    [xx, xx],
    [xx, xx],
    [xx, xx],
    [xx, xx],
    [xx, xx],
]
polygon = Polygon(coordinates)
geometry = Geometry(geometry=polygon, crs=CRS.WGS84)
utm_crs = get_utm_crs(xx, xx)
geometry = geometry.transform(utm_crs)

data_collection = DataCollection.define_byoc("XXXX")

input_task = SentinelHubEvalscriptTask(
    features=[(FeatureType.DATA, "BANDS")],
    config=config,
    data_collection=data_collection,
    resolution=3,
    evalscript=evalscript_true_color,
)
eop = input_task.execute(bbox=geometry.bbox, time_interval=("2024-04-07", "2024-04-26"))

Note, if you want the raw values, you should set the EvalScript output SampleType: UINT16

When I run your method exactly as given here (except with coordinates specified), I get multiple timesteps returned, but all image data is “blank” i.e. 255 inside the specified polygon and 0 outside. There are no warnings of errors thrown by the process. Is there any way to debug what is going on here please?

I am querying for the exact polygon used to create the original subscription.

This is due to the evalscript sampleType. To get the raw band values back, you need to set sampleType to UINT16

//VERSION=3
function setup() {
  return {
    input: ["blue","green","red", "dataMask"],
    output: [{ 
      id: "BANDS",
      bands: 3,
      sampleType: "UINT16"
    }]
  };
}

function evaluatePixel(sample) {
  return {
      BANDS: [sample.blue, sample.green, sample.red]
  };
}

to get a true color image (not for analytic use) you need to divide the band values by 3000 and not change the sample Type. See here for more information on sample type: SampleType: what’s all the fuss about? | by Maxim Lamare | Sentinel Hub Blog | Medium