Replicating Request Builder query in SH-PY

So I’m trying to use the scripts provided by the request builder to retrieve data with sentinelhub python. For some reason it keeps throwing Error 400, though.

config = SHConfig()

config.sh_client_id = xx
config.sh_client_secret = xx

evalscript = """

//VERSION=3

function setup() {

  return {

    input: [

      {

        bands: ["B01","B02","B03","B04","B05","B06","B07","B08","B8A","B09","B11","B12"],      

        units: "REFLECTANCE",            

      }

    ],

    output: [

      {

        id: "default",

        bands: 12,

        sampleType: "AUTO",        

      },    

    ],

    mosaicking: "SIMPLE",

  };

}

function evaluatePixel(samples) {

    return {

      default: [sample.B01,sample.B02,sample.B03,sample.B04,sample.B05,sample.B06,sample.B07,sample.B08,sample.B8A,sample.B09,sample.B11,sample.B12],

    };

  }

"""

bbox = BBox(bbox=[15.62174, 46.6803, 15.63014, 46.68603], crs=CRS.WGS84)

geometry = Geometry(geometry={"type":"Polygon","coordinates":[[[15.62339,46.68603],[15.62273,46.68505],[15.623,46.68499],[15.62216,46.68236],[15.62174,46.68205],[15.62268,46.68217],[15.62289,46.68263],[15.62344,46.68258],[15.62356,46.68244],[15.62337,46.68205],[15.62331,46.68128],[15.62423,46.68115],[15.62425,46.68112],[15.62476,46.68152],[15.62475,46.68225],[15.62597,46.68208],[15.62633,46.68159],[15.62701,46.68125],[15.62842,46.68039],[15.6284,46.6804],[15.62914,46.6803],[15.62971,46.68069],[15.62969,46.68098],[15.63014,46.68218],[15.63011,46.68252],[15.628,46.68341],[15.62764,46.68306],[15.62694,46.6836],[15.62544,46.68399],[15.62371,46.68391],[15.62341,46.68402],[15.62358,46.68461],[15.62405,46.68499],[15.62339,46.68603]]]}, crs=CRS.WGS84)

request = SentinelHubRequest(

    evalscript=evalscript,

    input_data=[

        SentinelHubRequest.input_data(

            data_collection=DataCollection.SENTINEL2_L2A,          

            time_interval=('2021-01-05', '2021-01-05'),          

            other_args={"dataFilter": {"mosaickingOrder": "leastRecent"}}

        ),
    ],
    responses=[
        SentinelHubRequest.output_response('default', MimeType.TIFF),
    ],
    bbox=bbox,
    geometry=geometry,
    size=[512, 509.07],
    config=config
)
response = request.get_data()

Interestingly, the following evalscript actually works, but I don’t understand why, exactly:

evalscript = """
//VERSION=3

function setup() {
  return {
    input: ["B01","B02","B03","B04","B05","B06","B07","B08","B8A","B09","B11","B12"],
    output: { bands: 12 }
  };
}

function evaluatePixel(sample) {
  return [sample.B01,sample.B02,sample.B03,sample.B04,sample.B05,sample.B06,sample.B07,sample.B08,sample.B8A,sample.B09,sample.B11,sample.B12];
}
"""

Hi!

The issue is that you are requesting B10 band, which is not present in Sentinel-L2A data. If you change the data_collection to DataCollection.SENTINEL2_L1C it will work (or if you remove the B10 from the evalscript).

Please correct me, if there is a misunderstanding, but I request B10 in neither input:bands, nor the return function. In fact even if I change my evalscript to request just one band, it still throws an error:

evalscript = """
//VERSION=3

function setup() {
  return {
    input: [
      {
        bands: ["B03"],      
        units: "REFLECTANCE",            
      }
    ],
    output: [
      {
        id: "default",
        bands: 12,
        sampleType: "AUTO",        
      },    
    ],
    mosaicking: "SIMPLE",
  };
}


function evaluatePixel(samples) {
    return {
      default: [sample.B03],
    };
  }


"""

DownloadFailedException: 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":"Failed to evaluate script!\nevalscript.js:26: ReferenceError: sample is not defined\n      default: [sample.B03],\n                ^\nReferenceError: sample is not defined\n    at evaluatePixel (evalscript.js:26:17)\n    at executeForSingleScene (<anonymous>:1119:17)\n","code":"RENDERER_EXCEPTION"}}"

Indeed you are not requesting B10, but now your output states that you are requesting 12 bands, while you are in fact only requesting one.

I’m sorry, definitely an oversight on my part. Changing output:bands to 1 doesn’t change the result, however. Here again, the script I’m using:

evalscript = """
//VERSION=3

function setup() {
  return {
    input: [
      {
        bands: ["B03"],      
        units: "REFLECTANCE",            
      }
    ],
    output: [
      {
        id: "default",
        bands: 1,
        sampleType: "AUTO",        
      },    
    ],
    mosaicking: "SIMPLE",
  };
}


function evaluatePixel(samples) {
    return {
      default: [sample.B03],
    };
  }


"""
bbox = BBox(bbox=[15.62174, 46.6803, 15.63014, 46.68603], crs=CRS.WGS84)
geometry = Geometry(geometry={"type":"Polygon","coordinates":[[[15.62339,46.68603],[15.62273,46.68505],[15.623,46.68499],[15.62216,46.68236],[15.62174,46.68205],[15.62268,46.68217],[15.62289,46.68263],[15.62344,46.68258],[15.62356,46.68244],[15.62337,46.68205],[15.62331,46.68128],[15.62423,46.68115],[15.62425,46.68112],[15.62476,46.68152],[15.62475,46.68225],[15.62597,46.68208],[15.62633,46.68159],[15.62701,46.68125],[15.62842,46.68039],[15.6284,46.6804],[15.62914,46.6803],[15.62971,46.68069],[15.62969,46.68098],[15.63014,46.68218],[15.63011,46.68252],[15.628,46.68341],[15.62764,46.68306],[15.62694,46.6836],[15.62544,46.68399],[15.62371,46.68391],[15.62341,46.68402],[15.62358,46.68461],[15.62405,46.68499],[15.62339,46.68603]]]}, crs=CRS.WGS84)

request = SentinelHubRequest(
    evalscript=evalscript,
    input_data=[
        SentinelHubRequest.input_data(
            data_collection=DataCollection.SENTINEL2_L2A,          
            time_interval=('2021-01-05', '2021-01-05'),          
            other_args={"dataFilter": {"mosaickingOrder": "leastRecent"}}
        ),
    ],
    responses=[
        SentinelHubRequest.output_response('default', MimeType.TIFF),
    ],
    bbox=bbox,
    geometry=geometry,
    size=[512, 509.07],
    config=config
)

response = request.get_data()

And the error:

DownloadFailedException: 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":"Failed to evaluate script!\nevalscript.js:26: ReferenceError: sample is not defined\n      default: [sample.B03],\n                ^\nReferenceError: sample is not defined\n    at evaluatePixel (evalscript.js:26:17)\n    at executeForSingleScene (<anonymous>:1119:17)\n","code":"RENDERER_EXCEPTION"}}"

The error description from the server is rather clear: there is no variable “sample” (it also points to the line number!).

function evaluatePixel(samples) { // <- the parameter here is samples (plural)
    return {
      default: [sample.B03],      // <- the parameter here is sample (singular)
    };
  }

In your case (simple mosacking), the appropriate way is to have function evaluatePixel(sample).