Package: sentinelpy
sentinelpyQueries ESA Sentinel APIs for productsFree software: MIT licenseUsagequery_sentinel_hubimportloggingfromsentinelpyimport(query_sentinel_hub,SentinelProductRequestBuilder,RequestQueryBuilder,PlatformName,QuerySentinelProductsResponse)request=(SentinelProductRequestBuilder().with_username("username").with_password("password").with_query(RequestQueryBuilder().platform_name(PlatformName.SENTINEL_1)).build())result=query_sentinel_hub(request,log_level=logging.DEBUG)assertisinstance(result,QuerySentinelProductsResponse)print(result.status_code)print(result.body)print(result.error)Positional arguments:sentinel_product_request(SentinelProductRequest)Request object containing the details of the query. You should use theSentinelProductRequestBuilderto
constructKeyword arguments:log_level(int)Level for which to log at useloggingto define correct level, defaults to 'INFO'.logger(logging.Logger)Logger to use to log messages with, defaults tologging.getLogger(__name__)if no value suppliedReturns:QuerySentinelProductsResponseobjectAPI Documentationrange_valuerange_value (function)A helper function for defining range values for queries using theRequestQueryBuilderParameters:start_val(str)Start of the rangeend_val(str)End of the rangeReturns:strrange string in format of "[MIN TO MAX]" whereMINisstart_valandMAXisend_valExamplefromsentinelpyimport(RequestQueryBuilder,range_value)query=(RequestQueryBuilder().orbit_number(range_value("1","2")).build())assertquery=="orbitnumber:[1 TO 2]"SentinelProductRequestBuilderSentinelProductRequestBuilder (class)Builder resposible for creatingSentinelProductRequestobjects.As a minimum, the username and password for the Sentinel Hub should be supplied.Constructor detailsdefault_query(str): Default value for query,defaults to*default_rows(int): Default value for rows,defaults to30default_order_by(Optional[str]): Default value for order by,defaults toNonedefault_start(int): Default value for start,defaults to0Method detailsbuildMethod that constructs theSentinelProductRequestusing the values supplied to the builderReturns:SentinelProductRequest- Built request from input dataRaises:ValueError- if username or password missingwith_usernameSets the Sentinel Hub usernameParameter:username(str)The username for Sentinel Hub APIReturns:SentinelProductRequestBuilderBuilder object withusernamesuppliedwith_passwordSets the Sentinel Hub passwordParameter:password(str)The associated password for the user for the Sentinel Hub APIReturns:SentinelProductRequestBuilderBuilder object withpasswordsuppliedwith_querySets the query (q) valueParameter:query(strorRequestQueryBuilder)The query to use to filter results. If it is aRequestQueryBuilder, thenbuildwill
callbuildon theRequestQueryBuilderbefore constructing theSentinelProductRequest.Returns:SentinelProductRequestBuilderBuilder object withquerysuppliedwith_rowsSets the rows valueParameter:rows(int)The value for rows to return in each requestReturns:SentinelProductRequestBuilderBuilder object withrowssuppliedwith_order_bySets the order_by valueParameter:order_by(str)The value for order_by to return in each requestReturns:SentinelProductRequestBuilderBuilder object withorder_bysuppliedwith_startSets the start valueParameter:start(int)The value for start to return in each requestReturns:SentinelProductRequestBuilderBuilder object withstartsuppliedExample usagefromsentinelpyimport(SentinelProductRequestBuilder,SentinelProductRequest,RequestQueryBuilder,PlatformName,)minimal=(SentinelProductRequestBuilder().with_username("username").with_password("password").build())assertminimal==SentinelProductRequest(query="*",rows=None,order_by=None,start=0,username="username",password="password")full=(SentinelProductRequestBuilder().with_username("username").with_password("password").with_query(RequestQueryBuilder().platform_name(PlatformName.SENTINEL_1)).with_start(15).with_rows(15).with_order_by('ingestiondate desc').build())assertfull==SentinelProductRequest(query="platformname:Sentinel-1",rows=15,order_by='ingestiondate desc',start=15,username="username",password="password")RequestQueryBuilderRequestQueryBuilder (class)A builder utility to build values for queries.Refer to the Sentinel Hub API documentation for more information about the values. The methods of this class
map to search keywords/operators described in the former documentation. The keywords use snake case rather than
all lowercase to adhere to Python conventions.Method detailsbuildCreates the value for query/qusing the supplied values. If two non-operators supplied in order without an operator (i.e.and_,or_, ornot_)
defaults toand_operator.If the query hasand_oror_operators at the start or an operator at the end then these are removed from the query.Returns:str- the query constructed using the builder, if no methods called returns*by defaultExamplefromsentinelpyimportRequestQueryBuilder,PlatformNamedefault_build_behaviour=RequestQueryBuilder().build()assertdefault_build_behaviour=="*"hanging_operator_start=RequestQueryBuilder().and_().platform_name(PlatformName.SENTINEL_1).build()asserthanging_operator_start=="platformname:Sentinel-1"hanging_operator_end=RequestQueryBuilder().not_().platform_name(PlatformName.SENTINEL_1).and_().build()asserthanging_operator_end=="NOT platformname:Sentinel-1"and_Logicaland- combines the previous and next clauses i.e.platform_name(X).and_().platform_name(Y)results in
the query beingplatformname:X AND platform_name:YReturns:RequestQueryBuilderselfor_Logicalor- either the previous or next clauses i.e.platform_name(X).or_().platform_name(Y)results in
the query beingplatformname:X OR platform_name:YReturns:RequestQueryBuilderselfnot_Negates the following clause.Returns:RequestQueryBuilderselfgroup_Creates a grouped clause in the query. If the parameter is aRequestQueryBuilderthen it calls thebuildmethod
before.Parameter:inner_query(strorRequestQueryBuilder)The query that is part of the group.Returns:RequestQueryBuilderselfExamplefromsentinelpyimport(RequestQueryBuilder,PlatformName,PolarisationMode)q=(RequestQueryBuilder().group_(RequestQueryBuilder().platform_name(PlatformName.SENTINEL_1).and_().polarisation_mode(PolarisationMode.HH)).or_().group_(RequestQueryBuilder().platform_name(PlatformName.SENTINEL_1).and_().not_().polarisation_mode(PolarisationMode.VH)).build())assertq==("(platformname:Sentinel-1 AND polarisationmode:HH) OR ""(platformname:Sentinel-1 AND NOT polarisationmode:VH)")begin_positionSets the beginposition filter between the parameters start/endParameters:begin_position_start(str)Start of the range that the query is interested in, in ISO date/time stamp with millis, or relative
to NOW (e.g. NOW/NOW-1DAY etc.)begin_position_end(str)End of the range that the query is interested in, in ISO date/time stamp with millis, or relative
to NOW (e.g. NOW/NOW-1DAY etc.)Returns:RequestQueryBuilderselfRaises:ValueError- ifbegin_position_startorbegin_position_endare not valid, i.e not ISO or relative
datecloud_cover_percentageThe range of acceptable values for cloud cover percentage as per Sentinel DatasetParameter:percentage(intorstring)The percentage value or range (the format ofMIN TO MAXwhere MIN is lowest acceptable and MAX is upper limit)
of limit for Cloud Cover PercentageReturns:RequestQueryBuilderselfRaises:ValueErrorif the value is not an integer or valid percentage or rangecollectionSet the value for collection. Used to specify the name of a predefined collection of productsParameter:collection(str)Value for collectionReturns:RequestQueryBuilderselfRaises:ValueErrorif supplied string is empty i.e. '' or just whitespaceend_positionSet a filter on the range for endposition (that is Sensing Stop Time) that the query is interested in.Parameter:end_position_start(str)Start of the period, in ISO date/time stamp with millis, or relative to NOW (e.g. NOW/NOW-1DAY etc.)end_position_end(str)End of the period, in ISO date/time stamp with millis, or relative to NOW (e.g. NOW/NOW-1DAY etc.)Returns:RequestQueryBuilderselfRaises:ValueError- ifend_position_startorend_position_endare not valid, i.e not ISO or relative
datefile_nameSets a filter on product filename.Parameter:filename(str)Name of the product file to filter results byReturns:RequestQueryBuilderselfRaises:ValueErrorif supplied string is empty i.e. '' or just whitespacefootprintSets a filter on geographic area that the query is interested in. Can use either a simple bounding box described
as a WKT Polygon or a point described by aLatitudeLongitudepair. Refer to the Sentinel Hub documentation for
in depth information about footprint.Parameter:geographic_type(str)The Area of Interest for the query. Can either be a point (lat/lon
pair e.g. "0.000, 1.000") or a Polygon (WKT polygon without cut outs,
e.g. POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10)))Can have the Intersects() or can be just the coordinate pair or PolygonReturns:RequestQueryBuilderselfRaises:ValueErrorif not valid WKT Polygon or pointingestion_dateSets a filter on the date the Sentinel product was ingested using the supplied range.Parameter:ingestion_date_start(str)Start of the period,  in ISO date/time stamp with millis, or relative to NOW (e.g. NOW/NOW-1DAY etc.)ingestion_date_end(str)End of the period, in ISO date/time stamp with millis, or relative to NOW (e.g. NOW/NOW-1DAY etc.)Returns:RequestQueryBuilderselfRaises:ValueError- ifingestion_date_startoringestion_date_endare not valid, i.e not ISO or relativelast_orbit_numberSets on a filter on the last orbit number or range range of last orbit numbers (i.e[MIN TO MAX]whereby MIN
is the lowest last orbit number and MAX is highest).Parameter:orbit_number(strorint)The orbit number or range that should be used. Can be a single value i.e. 1234 or a range such as [1234 TO 4321]
must be between 0 and 999999Returns:RequestQueryBuilderselfRaises:ValueErrorif value is not a valid number or rangelast_relative_orbit_numberSets a filter on the last orbit number or range range of last orbit numbers (i.e[MIN TO MAX]whereby MIN
is the lowest last orbit number and MAX is highest). Relative orbit number of the oldest line within the image
data (the start of the product) and relative orbit number of the most recent line within the image data
(the end of the product), respectively.Parameter:orbit_number(strorint)The orbit number or range that should be used. Can be a single value i.e. 1234 or a range such as [1234 TO 4321]
must be between 0 and 175Returns:RequestQueryBuilderselfRaises:ValueErrorif value is not a valid number or rangeorbit_directionSets a filter on the orbit direction for the oldest data in the productParameter:orbit_direction(OrbitDirection)Direction that the query is interested inReturns:RequestQueryBuilderselforbit_numberSets a filter on the orbit number or range range of orbit numbers (i.e[MIN TO MAX]whereby MIN
is the lowest orbit number and MAX is highest).Parameter:orbit_number(strorint)The orbit number or range that should be used. Can be a single value i.e. 1234 or a range such as [1234 TO 4321].
must be between 0 and 999999Returns:RequestQueryBuilderselfRaises:ValueErrorif value is not a valid number or rangeplatform_nameSets a filter on the platform nameParameter:platform_name(PlatformName)The platform name to filter the results byReturns:RequestQueryBuilderselfpolarisation_modeSets a filter on polarisation mode.Parameter:polarisation_mode(PolarisationMode)Specified value for polarisation_modeReturns:RequestQueryBuilderselfproduct_typeSets a filter on product type. Note the valid combinations withplatform_nameParameter:product_type(Sentinel1ProductTypeorSentinel2ProductTypeorSentinel3ProductTypeorSentinel5PProductType)Specified value for product type to filter the results onReturns:RequestQueryBuilderselfrelative_orbit_numberSet filter on relative orbit number of the oldest line within the image data (the start of the product).Parameter:orbit_number(strorint)The orbit number or range that should be used. Can be a single value i.e. 123 or a range such as [123 TO 124].
must be between 0 and 175Returns:RequestQueryBuilderselfRaises:ValueErrorif value is not a valid number or rangesensor_operational_modeSet filter on sensor operational modeParameter:sensor_operational_mode(SensorOperationalMode)The value to filter products onReturns:RequestQueryBuilderselfswath_identifierSearch all valid swath identifiers for the Sentinel-1 SAR instrument. The S1-S6 swaths apply to SM products, the IW and IW1-3 swaths apply to IW products (IW is used for detected IW products where the 3 swaths are merged into one image), the EW and EW1-5 swaths apply to EW products (EW is used for detected EW products where the 5 swaths are merged into one image).Parameter:swath_identifier(SwathIdentifier)Swath Identifier to filter products withReturns:RequestQueryBuilderselftimelinessFilter sentinel products on timelinessParameter:timeliness(Timeliness)Value of timeliness that the query is interested inReturns:RequestQueryBuilderselfExamplefromsentinelpyimportRequestQueryBuilder,PlatformNamesimple_q=(RequestQueryBuilder().platform_name(PlatformName.SENTINEL_1).build())assertsimple_q=="platformname:Sentinel-1"multiple_clauses_q=(RequestQueryBuilder().platform_name(PlatformName.SENTINEL_3).and_().cloud_cover_percentage("[0 TO 5]").and_().footprint("POLYGON((-4.53 29.85, 26.75 29.85, 26.75 46.80,-4.53 46.80,-4.53 29.85))").build())assertmultiple_clauses_q==('platformname:Sentinel-3 AND cloudcoverpercentage:[0 TO 5] AND ''footprint:"Intersects(POLYGON((-4.53 29.85, 26.75 29.85, 26.75 46.''80,-4.53 46.80,-4.53 29.85)))"')SentinelProductRequestSentinelProductRequest (NamedTuple/class)Named Tuple representing a request. Best practice would be to use the builders (SentinelProductRequestBuilderandRequestQueryBuilder) to derive.Properties:query(str)Query string value for 'q' in the request.Sentinel hub documentation. This can be constructed using theRequestQueryBuilder.rows(int)Number of rows to return from the APIReference to documentationorder_by(Optional[str])Field to order the results onReference to documentationstart(int)Start position of the records to returnReference to documentationusername(str)Valid username to use to authenticate with the Sentinel Hub APIpassword(str)Valid password to use to authenticate with the Sentinel Hub APIQuerySentinelProductsResponseQuerySentinelProductsResponse (NamedTuple/class)Represents the result from the Sentinel Hub APICan be interacted with as an object or in a more functional style using
the 'on' methods (on_success/on_failure).Property Detailsstatus_code(Optional[int])The HTTP Status code representing the outcome of the querybody(Optional[Dict[str, Any]])The resulting data from the Sentinel Huberror(Optional[BaseException])An error object if there was an error or exception raisedsuccess(bool)Whether or not the query was successfulMethod detailsraise_errorIf encountered an error raise error encountered. Otherwise do nothingSituations this would be useful:Prevent exceptions being swallowedYou prefer to handle exception rather than checking if value is NoneReturns:NoneRaises: Error that was encountered when querying the APIon_successA functional style method for handling successful results. When the action was successful, calls
the supplied function with data from Sentinel Hub API and returns theQuerySentinelProductsResponseso that other methods can be chainedParameters:callback: (Callable[[Dict[str, Any]], None])Function which defines the successful behaviourReturns:QuerySentinelProductsResponseselfon_failureA functional style method for handling cases where the API was not reachable or
there was an error either in the response or parsing the response, i.e. the request
was not successful.Parameters:callback: (Callable[[QuerySentinelProductsResponse], None])Function which defines the failure behaviour, which will be called with named tuple representing the
resultReturns:QuerySentinelProductsResponseselfExamplefromsentinelpyimportQuerySentinelProductsResponse# You can use the attributes of the response in a more object fashion# Successful response:successful_response=QuerySentinelProductsResponse(200,{})assertsuccessful_response.successassertsuccessful_response.status_code==200assertsuccessful_response.body=={}assertsuccessful_response.errorisNone# Failed response:failed_response=QuerySentinelProductsResponse(400,{})assertnotfailed_response.successassertfailed_response.status_code==400assertfailed_response.body=={}assertfailed_response.errorisNone# Erroneous responseerroneous_response=QuerySentinelProductsResponse(None,None,IOError())assertnoterroneous_response.successasserterroneous_response.status_codeisNoneasserterroneous_response.bodyisNoneassertisinstance(erroneous_response.error,IOError)# Using the functional style methodssuccessful_response.on_success(lambdadata:print(f'success:{data}')).on_failure(lambdafailure_response:print(f'failure:{failure_response.status_code}'))# success:{}failed_response.on_success(lambdadata:print(f'success:{data}')).on_failure(lambdafailure_response:print(f'failure:{failure_response.status_code}'))# failure:400EnumerationsIn order to simplify validation there are some Enumerations representing some of the types in theRequestQueryBuilder, each
valid option maps to a value defined by the API.Refer to the Sentinel Hub API documentation for more information about the valuesThe enumerations are as follows:OrbitDirectionPlatformNamePolarisationModeProductTypeSensorOperationalModeSentinel1ProductTypeSentinel2ProductTypeSentinel3ProductTypeSentinel5PProductTypeSwathIdentifierTimelinessFeaturesQueries the Sentinel Hub for productsDefine your requests using theRequestQueryBuilderandSentinelProductRequestBuilderobjectsDevelopment DocumentationBuilt using Poetry.poetry installTo install the library locally from sourceCreditsThis package was created with Cookiecutter and theUKHO/cookiecutter-pypackageproject template.Cookiecutter:https://github.com/cookiecutter/cookiecutterUKHO/cookiecutter-pypackage:https://github.com/UKHO/cookiecutter-pypackage