Hi,
The example below shows how you define new DataCollection
using information from SH collections web page, and create SentinelHubInputTask
that you can then add to your workflow.
from sentinelhub import (
BBox, CRS, bbox_to_dimensions,
DataCollection, Band, Unit
)
from eolearn.core import EOPatch, FeatureType
from eolearn.io import SentinelHubInputTask
import matplotlib.pyplot as plt
import datetime as dt
import numpy as np
caspian_sea_bbox = BBox([49.9604, 44.7176, 51.0481, 45.2324], crs=CRS.WGS84)
time_interval = '2015-03-10', '2020-05-01'
glc = DataCollection.define(
name='Global Land Cover, forest',
api_id='byoc-f0a97620-0e88-4c1f-a1ac-bb388fabdf2c', # type
catalog_id='f0a97620-0e88-4c1f-a1ac-bb388fabdf2c', # collectionId
service_url='https://creodias.sentinel-hub.com', # end point
is_timeless=False,
bands=[
Band('Forest_Type_layer', (Unit.DN,), (np.float32,)),
Band('Tree_CoverFraction_layer', (Unit.DN,), (np.float32,)),
]
)
input_task = SentinelHubInputTask(
data_collection=glc,
size=bbox_to_dimensions(caspian_sea_bbox, 200),
bands_feature=(FeatureType.DATA, 'glc'),
bands=['Forest_Type_layer']
)
eop = input_task.execute(bbox=caspian_sea_bbox, time_interval=time_interval)
The caveat is that the SentinelHubInputTask
wants the results to be written to FeatureType.DATA
, so you might have to create new Task that takes the particular time out of results and returns it as FeatureType.MASK_TIMELESS
. Let us know if you run into additional troubles.
I modified your example and combined it with another input task to but I am getting the error:
ValueError: During execution of task SentinelHubInputTask: Trying to write data to an existing eopatch with a different timestamp.
Each task is working on its own but chaining them produces the error.
EDIT : glc_task returns 1 in the first dimension and add_data returns 2. But I couldn’t figure out how to resolve it.
I feel like there is something basic that I am missing here.
Also, how is this working without a SHconfig object?
AOI = BBox(bbox=x5.60, 52.68, 5.75, 52.63], crs=CRS.WGS84)
time_interval = '2020-01-01', '2020-01-20'
glc = DataCollection.define(
name='Global Land Cover10m',
api_id='byoc-0b940c63-45dd-4e6b-8019-c3660b81b884', #Type
catalog_id='0b940c63-45dd-4e6b-8019-c3660b81b884', # collection_id
service_url='https://services.sentinel-hub.com', # End point
is_timeless=False,
bands=s
Band('Map', (Unit.DN,), (np.float32,)),
]
band_names = ='B02', 'B03', 'B04']
add_data = SentinelHubInputTask(
bands_feature=(FeatureType.DATA, 'BANDS'),
bands = band_names,
resolution=10,
maxcc=0.8,
time_difference=datetime.timedelta(minutes=120),
data_collection=DataCollection.SENTINEL2_L1C,
max_threads=5
)
glc_task = SentinelHubInputTask(
data_collection=glc,
size=bbox_to_dimensions(AOI, 200),
bands_feature=(FeatureType.DATA, 'glc'),
bands=s'Map']
)
workflow = LinearWorkflow(glc_task,add_data)
result = workflow.execute({
add_data: {'bbox': AOI, 'time_interval': time_interval},
glc_task: {'bbox': AOI, 'time_interval': time_interval}
})
hi,
Running this example used to work but now it gives a strange error prompting that the units were requested in reflectance but DN is clearly requested by your code.
what could cause this?
Tnx
As per byoc docs, when requesting data from BYOC, the units should be DN. The example I’ve posted, still works.
I did miss your first response, though, sorry. To answer that one: glc_task
and add_data
tasks are requesting different data collections, that have different number of observations in the requested time interval. eo-learn
is trying to enforce some structure in the EOPatch
, tasks will fail if the temporal data the task is adding is not on the same “grid” (e.g. on equal timestamps) as the existing data in the EOPatch
. In your case, you should probably create two EOPatches
(one for GLC and one for S-2/L-8/… data). Another possible way forward would be to save one (e.g. GLC) as DATA_TIMELESS
, if the GLC in your case “holds true” for all the timestamps of the other dataset you have in your EOPatch
. (This second approach for instance makes sense with DEM data as well, see example).
Thanks,
I just tried again to run your example.
still receiving :
DownloadFailedException: Failed to download from:
https://creodias.sentinel-hub.com/api/v1/process
with HTTPError:
400 Client Error: Bad Request for url: https://creodias.sentinel-hub.com/api/v1/process
Server response: "{"error":{"status":400,"reason":"Bad Request","message":"Invalid script! Band 'Forest_Type_layer' of collection 'byoc-f0a97620-0e88-4c1f-a1ac-bb388fabdf2c' requested in unsupported units 'REFLECTANCE'! Supported units for this band: [dn]. See https://shforum.sinergise.com/t/units-improvements/4442 for more information.","code":"RENDERER_EXCEPTION"}}"
This is strange because DN is specified in your code. What could cause this?
I really don’t know: I have just run my example code, and it runs without a problem. Are you sure that your collection defined DN for units? E.g. try printing out the collection… For me:
glc
<DataCollection.Global Land Cover, forest: DataCollectionDefinition(
api_id: byoc-f0a97620-0e88-4c1f-a1ac-bb388fabdf2c
catalog_id: f0a97620-0e88-4c1f-a1ac-bb388fabdf2c
service_url: https://creodias.sentinel-hub.com
bands: (Band(name='Forest_Type_layer', units=(<Unit.DN: 'DN'>,), output_types=(<class 'numpy.float32'>,)), Band(name='Tree_CoverFraction_layer', units=(<Unit.DN: 'DN'>,), output_types=(<class 'numpy.float32'>,)))
is_timeless: False
has_cloud_coverage: False
)>
(of course, substitute glc
with whatever data collection you use in your glc_task
)
I get the exact same result as you
glc
<DataCollection.Global Land Cover, forest: DataCollectionDefinition(
api_id: byoc-f0a97620-0e88-4c1f-a1ac-bb388fabdf2c
catalog_id: f0a97620-0e88-4c1f-a1ac-bb388fabdf2c
service_url: https://creodias.sentinel-hub.com
bands: (Band(name=‘Forest_Type_layer’, units=(<Unit.DN: ‘DN’>,), output_types=(<class
‘numpy.float32’>,)), Band(name=‘Tree_CoverFraction_layer’, units=(<Unit.DN: ‘DN’>,),
output_types=(<class ‘numpy.float32’>,)))
is_timeless: False
has_cloud_coverage: False )>