Bounding Box Too Large Error For 500 Resolution (Compared to 100 Resolution)

At a 100 resolution the BBox [-115.0, 35.0, -114.0, 37.0] downloads ok (shape (2, 2242, 844, 13)).

If I change resolution to 500 or 1000 I get an error saying the box is too large.

Making the box much smaller [-114.75, 36.25, -114.0, 36.5] doesn’t seem to help- the resolution at 500 (or 1000) seems to cause a problem.

It’s possible I am mistaken, but shouldn’t the new 5x (i.e 500) resolution result in a new box that has 1/5 of the rows/columns, of the 100 resolution shape box ?

import time
import numpy as np
import pickle
import geopandas
from eolearn.io import SentinelHubInputTask
from sentinelhub import CRS, BBox, DataSource
from eolearn.io import SentinelHubInputTask
from eolearn.core import SaveToDisk, FeatureType, OverwritePermission, LinearWorkflow

layer = ‘BANDS-S2-L1C’
save = SaveToDisk(‘mojave’, overwrite_permission=2, compress_level=1)

input_task = SentinelHubInputTask(
resolution=500,
bands_feature=(FeatureType.DATA, ‘bands’),
additional_data=[(FeatureType.MASK, ‘dataMask’)],
time_difference=datetime.timedelta(minutes=120),
data_source=DataSource.SENTINEL2_L1C,
max_threads=10,
)

bb_1 = BBox(bbox=[-115.0, 35.0, -114.0, 37.0],crs=CRS.WGS84)

#bb_1 = BBox(bbox=[-114.75, 36.25, -114.0, 36.5],crs=CRS.WGS84)

workflow = LinearWorkflow(input_task, save)

result_bb1 = workflow.execute({input_task: {‘bbox’: bb_1, ‘time_interval’: time_i},
save: {‘eopatch_folder’: ‘/deepdata/moj’}})

eopatch_nev = result_bb1[save]

This is the error when I change resolution of box that downloads at 100 but not 500:
DownloadFailedException: During execution of task SentinelHubInputTask: Failed to download from:
https://services.sentinel-hub.com/api/v1/process
with HTTPError:
400 Client Error: Bad Request for url: https://services.sentinel-hub.com/api/v1/process
Server response: “{“error”:{“status”:400,“reason”:“Bad Request”,“message”:“The bounding box area is too large! Please zoom in.”,“code”:“RENDERER_EXCEPTION”}}”

Many thanks;-)

I see you are using BBOX in WGS:84.
In Sentinel Hub API, resolution parameter is in same units as the rest of the requests, in your case in degrees. 500 degrees is not really a relevant resolution.
I am not familiar with sentinelhub-py and it might be that the package converts the units in the background, but I would recommend that you try also with units converted to degrees.

Further more, each dataset has also minimum resolutions defined. E.g. Sentinel-2 with PREVIEW level goes down to 250m.
See
https://docs.sentinel-hub.com/api/latest/#/data/Sentinel-2-L1C?id=previewmode

Many thanks for your prompt response. According to this (https://eo-learn.readthedocs.io/en/latest/_modules/eolearn/io/processing_api.html#SentinelHubInputTask), resolution is in meters.

class SentinelHubInputTask(SentinelHubInputBase):
:param data_source: Source of requested satellite data.
:type data_source: DataSource
:param size: Number of pixels in x and y dimension.
:type size: tuple(int, int)
:type resolution: Resolution in meters, passed as a tuple for X and Y axis.
:type resolution: tuple(int, int)

[I think first ‘type resolution’ should actually be ‘param resolution’]

Changing resolution to 250 doesn’t work…~180 seems to be upper limit. Again possibly different if Eval3 is used directly?

Unlike some of the other classes, there is no resx/resy parameter for SentinelHubInputTask class, even though it is using Eval 3 (which does has resx/resy when used natively), but “def generate_evalscript” does not- hence my use of the resolution parameter (as 500meters).

Are classes such as SentinelHubInputTask being deprecated for direct use of Eval3? If so what is the equivalent of “max_threads”?

Again many thanks for all your help;-)

-Apologies I probably should have posted my original issue under a different category (given minimum resolution is 250m)…the error returned stating “the bounding area is too large”, led me too believe there was a different issue.

error":{“status”:400,“reason”:“Bad Request”,“message”:“The bounding box area is too large! Please zoom in.”,“code”:"RENDERER_EXCEPTION

Hi @MMM!

Let me try to help with the issues you are having.

The resolution parameter in the SentinelHubInputTask is in fact in meters, because in the background the package projects to UTM in order to estimate the image size.

The issue lies in the unflexible SH request inside of eo-learn, where only the DETAIL preview mode is available (up to 250 m resolution). More info here, as @gmilcinski already mentioned. In order to allow for lower resolutions, one has to set the preview mode to PREVIEW or EXTENDED_PREVIEW, however, I think this is somewhat difficult to achieve in eo-learn, if not impossible. An issue already exists for this here, but no action was yet taken.

The reason why it works up to 180 m and not 250 in your case might be due to the original geometry being in WGS84 and not UTM, so perhaps something weird is happening with the resolution that you specify and the resolution the service is working with, the two might not be the same. This is just a speculation, I don’t really understand this either.

Are classes such as SentinelHubInputTask being deprecated for direct use of Eval3? If so what is the equivalent of “max_threads”?

The SentinelHubInputTask has a more “raw” approach to the service, where you don’t really have control over the evalscript, in this case it’s being auto generated. The max_threads parameter allows for multithreaded downloading.

I also think that the error that you get in this case – The bounding box area is too large! Please zoom in. – is ambiguous or misleading, since the issue lies in the resolution, not the bbox size.

If you want a quick and dirty fix, you can hard-code the preview mode inside of the data filter field in https://github.com/sentinel-hub/sentinelhub-py/blob/master/sentinelhub/sentinelhub_request.py#L115, otherwise I’ll push for resolving this, because I also had issues with this in the past.

Cheers!

I am encountering a similar issue, it seems like there are some confusing and invisible constraints on the bounding box and resolution parameters. I have never had a problem when ordering spectral Sentinel 2 L2A data (e.g. B02, B03, B08), but I have been struggling when trying L1C or sometimes adding the geometric layers (sunAzimuthAngles, sunZenithAngles, viewAzimuthAngles, viewZenithAngles) which are stored at 5000m resolution and seem to a possible source of my problem.

Strangely, the behavior seems to be different with SENTINEL2_L2A and SENTINEL2_L1C.

I can make this request just fine:

SentinelHubRequest(
    evalscript=EVALSCRIPT, # defined below
    data_folder=work_dir,
    input_data=[
        SentinelHubRequest.input_data(
            data_collection=DataCollection.SENTINEL2_L2A,
            time_interval=['2021-05-09', '2021-05-09']
        )
    ],
    responses=[
        SentinelHubRequest.output_response('default', MimeType.TIFF),
    ],
    bbox=BBox(bbox=[-88.30, 31.97, -85.53, 32.85], crs=CRS.WGS84),
    size=(512, get_image_dimension(bbox=request_bbox, width=512)),
    config=SHConfig()
)

But an identical request pointed at SENTINEL2_L1C fails with the The bounding box area is too large! error:

SentinelHubRequest(
    evalscript=EVALSCRIPT, # defined below
    data_folder=work_dir,
    input_data=[
        SentinelHubRequest.input_data(
            data_collection=DataCollection.SENTINEL2_L1C,
            time_interval=[date, date]
        )
    ],
    responses=[
        SentinelHubRequest.output_response('default', MimeType.TIFF),
    ],
    bbox=BBox(bbox=[-88.30, 31.97, -85.53, 32.85], crs=CRS.WGS84),
    size=(512, get_image_dimension(bbox=request_bbox, width=512)),
    config=SHConfig()
)

here is my evalscript:

EVALSCRIPT = """
//VERSION=3

function setup() {
  return {
    input: [
      {
        bands: [
          "B08", "B03", "B02",
          "viewZenithMean", "viewAzimuthMean", "sunZenithAngles", "sunAzimuthAngles", "dataMask"
        ]
      }
    ],
    output: [
        {id: "default", bands: 7, sampleType: "FLOAT32", nodataValue: -9999}
    ]
  };
}

function evaluatePixel(sample) {
  if (sample.dataMask == 1) {
      return {
          default: [
            sample.B08,
            sample.B03,
            sample.B02,
            sample.viewZenithMean,
            sample.viewAzimuthMean,
            sample.sunZenithAngles,
            sample.sunAzimuthAngles
          ]
      };
  } else {
      return {
          default: [-9999, -9999, -9999, -9999, -9999, -9999, -9999]
      };
  };
}
"""

Hi @hrodman,

the reason for the difference between Sentinel-2 L1C and L2A that you are experiencing is because we have previews (pre-prepared low resolution images) available for L1C but not for S2A. The documentation about the previewMode parameter for L1C and here for L2A describes what seems as
“invisible constraints on the bounding box and resolution parameters”.

What does all this mean for your example?
You are requesting data with spatial resolution of approx. resx = 510m, resy = 190m and with default previewMode, which is DETAIL.
When requesting L1C, the maximum allowed spatial resolution for DETAIL previewMode is 200m. Because your resx=510m > 200m you get the error message. Try increasing “width” (e.g. use 1300) or change the previewMode to TILE_PREVIEW and your request should return an image.
When requesting L2A, the maximum allowed spatial resolution is 1500m. Try decreasing your width and height so that requested spatial resolution exceed this limit and you should face the same error as for L1C.

Best, Anja

Thank you for the explanation, Anja. I did not know about the previewMode parameter. I think it would be helpful to add some detail to the error message like "bounding box too large for {previewMode} for this collection".

I tried setting previewMode to 'PREVIEW' and and 'TILE_PREVIEW' but I got a new error message:

Failed to download from:
https://services.sentinel-hub.com/api/v1/process
with HTTPError:
500 Server Error: Internal Server Error for url: https://services.sentinel-hub.com/api/v1/process
Server response: "{"error":{"status":500,"reason":"Internal Server Error","message":"Illegal request to https://sentinel-s2-l1c-preview.s3.amazonaws.com/51939/152/metadata.xml. HTTP Status: 403.","code":"RENDERER_EXCEPTION"}}"

My request looks like this:

SentinelHubRequest(
    evalscript=EVALSCRIPT, # defined below
    data_folder=work_dir,
    input_data=[
        SentinelHubRequest.input_data(
            data_collection=DataCollection.SENTINEL2_L1C,
            time_interval=[date, date],
            other_args={
                'dataFilter': {
                    'previewMode': 'TILE_PREVIEW'
                }
            }
        )
    ],
    responses=[
        SentinelHubRequest.output_response('default', MimeType.TIFF),
    ],
    bbox=BBox(bbox=[-88.30, 31.97, -85.53, 32.85], crs=CRS.WGS84),
    size=(512, get_image_dimension(bbox=request_bbox, width=512)),
    config=SHConfig()
)

Hi @hrodman ,

you get this error message, if you use ‘PREVIEW’ option, right? This is expected (but not documented, apologies), since we do not have previews for angles.
However, using ‘TILE_PREVIEW’ option should work. For example, the snippet below (combined from what you provided and slightly changed) works for me:

from sentinelhub import MimeType, CRS, BBox, SentinelHubRequest, SentinelHubDownloadClient, \
    DataCollection, bbox_to_dimensions, DownloadRequest

from sentinelhub import SHConfig

config = SHConfig()

config.sh_client_id = os.environ['SH_CLIENT_ID']
config.sh_client_secret = os.environ['SH_CLIENT_SECRET']

EVALSCRIPT = """
//VERSION=3

function setup() {
  return {
    input: [
      {
        bands: [
          "B08", "B03", "B02",
          "viewZenithMean", "viewAzimuthMean", "sunZenithAngles", "sunAzimuthAngles", "dataMask"
        ]
      }
    ],
    output: [
        {id: "default", bands: 7, sampleType: "FLOAT32", nodataValue: -9999}
    ]
  };
}

function evaluatePixel(sample) {
  if (sample.dataMask == 1) {
      return {
          default: [
            sample.B08,
            sample.B03,
            sample.B02,
            sample.viewZenithMean,
            sample.viewAzimuthMean,
            sample.sunZenithAngles,
            sample.sunAzimuthAngles
          ]
      };
  } else {
      return {
          default: [-9999, -9999, -9999, -9999, -9999, -9999, -9999]
      };
  };
}
"""

request_L1C = SentinelHubRequest(
    evalscript=EVALSCRIPT, 
    input_data=[
        SentinelHubRequest.input_data(
            data_collection=DataCollection.SENTINEL2_L1C,
            time_interval=['2021-05-09', '2021-05-09'],
            other_args={
                'dataFilter': {
                    'previewMode': 'TILE_PREVIEW'
                }
            }
        )
    ],
    responses=[
        SentinelHubRequest.output_response('default', MimeType.TIFF),
    ],
    bbox=BBox(bbox=[-88.30, 31.97, -85.53, 32.85], crs=CRS.WGS84),
    size=(512, 512),
    config=config
)

imgs = request_L1C.get_data()

Is this in line with your observations?

Best, Anja

The request that you sent works for me, but when I make the bounding box slightly larger I get the “illegal request” error message. Do you know why this request would fail?

request_bbox = BBox(bbox=[-89.22, 31.59, -84.44, 33.10], crs=CRS.WGS84)
request_L1C = SentinelHubRequest(
    evalscript=EVALSCRIPT, 
    input_data=[
        SentinelHubRequest.input_data(
            data_collection=DataCollection.SENTINEL2_L1C,
            time_interval=['2021-05-09', '2021-05-09'],
            other_args={
                'dataFilter': {
                    'previewMode': 'TILE_PREVIEW'
                }
            }
        )
    ],
    responses=[
        SentinelHubRequest.output_response('default', MimeType.TIFF),
    ],
    bbox=request_bbox,
    size=(512, get_image_dimension(bbox=request_bbox, width=512)),
    config=config
)

With this bbox and size you exceed the spatial resolution limit for TILE_PREVIEW, which is 640m and SH switches to PREVIEW.

Got it, thanks! It would be very helpful if the python api could print more information with that error message. Something like “the bounding box is too large for this resolution {res_x}, {res_y} for {previewMode} preview mode”.