@@ -364,17 +364,39 @@ impl StacMultiBandMetaData {
364364 files : & mut Vec < TileFile > ,
365365 fetch_tiles : bool ,
366366 ) -> Result < ( ) > {
367+ let Some ( ( time, z_index) ) = self . item_time_and_z_index ( item) ? else {
368+ return Ok ( ( ) ) ;
369+ } ;
370+
371+ time_steps. push ( time) ;
372+
373+ if !fetch_tiles {
374+ tracing:: trace!(
375+ "STAC query does not require fetching tiles, skipping item with id: {}" ,
376+ item. id
377+ ) ;
378+ return Ok ( ( ) ) ;
379+ }
380+
381+ for asset in item. assets . values ( ) {
382+ self . process_stac_asset ( asset, time, z_index, files) ?;
383+ }
384+
385+ Ok ( ( ) )
386+ }
387+
388+ fn item_time_and_z_index ( & self , item : & Item ) -> Result < Option < ( TimeInterval , i64 ) > > {
367389 if item. version != stac:: Version :: v1_1_0 {
368390 tracing:: warn!(
369391 "Skipping STAC item with unsupported version: {:?}" ,
370392 item. version
371393 ) ;
372- return Ok ( ( ) ) ;
394+ return Ok ( None ) ;
373395 }
374396
375397 let Some ( item_datetime) = item. properties . datetime else {
376398 tracing:: warn!( "Skipping STAC item without datetime: {}" , item. id) ;
377- return Ok ( ( ) ) ;
399+ return Ok ( None ) ;
378400 } ;
379401
380402 let z_index = item
@@ -406,133 +428,144 @@ impl StacMultiBandMetaData {
406428 }
407429 } ;
408430
409- time_steps. push ( time) ;
431+ Ok ( Some ( ( time, z_index) ) )
432+ }
410433
411- if !fetch_tiles {
412- tracing:: trace!(
413- "STAC query does not require fetching tiles, skipping item with id: {}" ,
414- item. id
434+ fn process_stac_asset (
435+ & self ,
436+ asset : & stac:: Asset ,
437+ time : TimeInterval ,
438+ z_index : i64 ,
439+ files : & mut Vec < TileFile > ,
440+ ) -> Result < ( ) > {
441+ if data_type_from_asset_v1_1_0 ( asset) != Some ( self . dataset . data_type ) {
442+ return Ok ( ( ) ) ;
443+ }
444+
445+ if !proj_code_matches_dataset ( & asset. additional_fields , self . dataset . projection ) {
446+ return Ok ( ( ) ) ;
447+ }
448+
449+ let Some ( geo_transform) = geo_transform_from_fields ( & asset. additional_fields ) else {
450+ tracing:: warn!(
451+ "Skipping asset with href {} due to missing geo transform" ,
452+ asset. href
415453 ) ;
416454 return Ok ( ( ) ) ;
455+ } ;
456+
457+ let Some ( ( height, width) ) = proj_shape_from_fields ( & asset. additional_fields ) else {
458+ tracing:: warn!(
459+ "Skipping asset with href {} due to missing projection shape" ,
460+ asset. href
461+ ) ;
462+ return Ok ( ( ) ) ;
463+ } ;
464+
465+ if ( geo_transform. x_pixel_size ( ) . abs ( ) - self . dataset . resolution . x ) . abs ( ) > 1e-9
466+ || ( geo_transform. y_pixel_size ( ) . abs ( ) - self . dataset . resolution . y ) . abs ( ) > 1e-9
467+ {
468+ return Ok ( ( ) ) ;
417469 }
418470
419- for ( _asset_key, asset) in & item. assets {
420- if data_type_from_asset_v1_1_0 ( & asset) != Some ( self . dataset . data_type ) {
421- continue ;
422- }
471+ let Some ( asset_title) = asset. title . as_deref ( ) else {
472+ tracing:: warn!(
473+ "Skipping asset with href {} due to missing title" ,
474+ asset. href
475+ ) ;
476+ return Ok ( ( ) ) ;
477+ } ;
478+
479+ let grid_bounds = GridBoundingBox2D :: new (
480+ GridIdx2D :: new ( [ 0 , 0 ] ) ,
481+ GridIdx2D :: new ( [ ( width as isize ) - 1 , ( height as isize ) - 1 ] ) ,
482+ )
483+ . map_err ( |_e| geoengine_operators:: error:: Error :: InvalidDataProviderConfig ) ?;
484+ let spatial_partition = geo_transform. grid_to_spatial_bounds ( & grid_bounds) ;
423485
424- if !proj_code_matches_dataset ( & asset. additional_fields , self . dataset . projection ) {
486+ let file_path = gdal_file_path ( & asset. href )
487+ . ok_or ( geoengine_operators:: error:: Error :: InvalidDataProviderConfig ) ?;
488+
489+ let gdal_config_options = self . gdal_config_options_for_file_path ( & file_path) ;
490+
491+ for ( dataset_band_idx, dataset_band) in self . dataset . bands . iter ( ) . enumerate ( ) {
492+ if dataset_band. asset_title != asset_title {
425493 continue ;
426494 }
427495
428- let Some ( geo_transform) = geo_transform_from_fields ( & asset. additional_fields ) else {
429- tracing:: warn!(
430- "Skipping asset with href {} due to missing geo transform" ,
431- asset. href
432- ) ;
496+ let Some ( rasterband_channel) =
497+ Self :: rasterband_channel_for_dataset_band ( asset, dataset_band. band_name . as_deref ( ) )
498+ else {
433499 continue ;
434500 } ;
435501
436- let Some ( ( height, width) ) = proj_shape_from_fields ( & asset. additional_fields ) else {
437- tracing:: warn!(
438- "Skipping asset with href {} due to missing projection shape" ,
439- asset. href
440- ) ;
441- continue ;
442- } ;
502+ files. push ( TileFile {
503+ time,
504+ spatial_partition,
505+ band : dataset_band_idx as u32 ,
506+ z_index,
507+ params : GdalDatasetParameters {
508+ file_path : file_path. clone ( ) ,
509+ rasterband_channel,
510+ geo_transform : GdalDatasetGeoTransform {
511+ origin_coordinate : geo_transform. origin_coordinate ( ) ,
512+ x_pixel_size : geo_transform. x_pixel_size ( ) ,
513+ y_pixel_size : geo_transform. y_pixel_size ( ) ,
514+ } ,
515+ width,
516+ height,
517+ file_not_found_handling : FileNotFoundHandling :: Error ,
518+ no_data_value : None ,
519+ properties_mapping : None ,
520+ gdal_open_options : None ,
521+ gdal_config_options : gdal_config_options. clone ( ) ,
522+ allow_alphaband_as_mask : false ,
523+ retry : Some ( GdalRetryOptions { max_retries : 99 } ) , // TODO: make configurable?
524+ } ,
525+ } ) ;
526+ }
443527
444- if ( geo_transform. x_pixel_size ( ) . abs ( ) - self . dataset . resolution . x ) . abs ( ) > 1e-9
445- || ( geo_transform. y_pixel_size ( ) . abs ( ) - self . dataset . resolution . y ) . abs ( ) > 1e-9
446- {
447- continue ;
448- }
528+ Ok ( ( ) )
529+ }
449530
450- let Some ( asset_title) = asset. title . as_deref ( ) else {
531+ fn rasterband_channel_for_dataset_band (
532+ asset : & stac:: Asset ,
533+ required_band_name : Option < & str > ,
534+ ) -> Option < usize > {
535+ if asset. bands . is_empty ( ) {
536+ if required_band_name. is_some ( ) {
451537 tracing:: warn!(
452- "Skipping asset with href {} due to missing title " ,
538+ "STAC asset with href {} does not include bands, but dataset configuration requires a band name. Skipping asset. " ,
453539 asset. href
454540 ) ;
455- continue ;
456- } ;
457-
458- let grid_bounds = GridBoundingBox2D :: new (
459- GridIdx2D :: new ( [ 0 , 0 ] ) ,
460- GridIdx2D :: new ( [ ( width as isize ) - 1 , ( height as isize ) - 1 ] ) ,
461- )
462- . map_err ( |_e| geoengine_operators:: error:: Error :: InvalidDataProviderConfig ) ?;
463- let spatial_partition = geo_transform. grid_to_spatial_bounds ( & grid_bounds) ;
464-
465- let file_path = gdal_file_path ( & asset. href )
466- . ok_or ( geoengine_operators:: error:: Error :: InvalidDataProviderConfig ) ?;
467-
468- let gdal_config_options = self . gdal_config_options_for_file_path ( & file_path) ;
469-
470- for ( dataset_band_idx, dataset_band) in self . dataset . bands . iter ( ) . enumerate ( ) {
471- if dataset_band. asset_title != asset_title {
472- continue ;
473- }
474-
475- let rasterband_channel = if asset. bands . is_empty ( ) {
476- if dataset_band. band_name . is_some ( ) {
477- tracing:: warn!(
478- "STAC asset with href {} does not include bands, but dataset configuration requires a band name. Skipping asset." ,
479- asset. href
480- ) ;
481- continue ;
482- }
483-
484- 1
485- } else {
486- let Some ( required_band_name) = dataset_band. band_name . as_deref ( ) else {
487- tracing:: warn!(
488- "STAC asset with href {} includes bands, but dataset configuration does not specify a band name. Skipping asset." ,
489- asset. href
490- ) ;
491- continue ;
492- } ;
493-
494- let Some ( asset_band_idx) = asset. bands . iter ( ) . position ( |asset_band| {
495- asset_band. name . as_deref ( ) == Some ( required_band_name)
496- } ) else {
497- tracing:: debug!(
498- "Skipping asset with href {} due to missing required band {}" ,
499- asset. href,
500- required_band_name
501- ) ;
502- continue ;
503- } ;
504-
505- asset_band_idx + 1
506- } ;
507-
508- files. push ( TileFile {
509- time,
510- spatial_partition,
511- band : dataset_band_idx as u32 ,
512- z_index,
513- params : GdalDatasetParameters {
514- file_path : file_path. clone ( ) ,
515- rasterband_channel,
516- geo_transform : GdalDatasetGeoTransform {
517- origin_coordinate : geo_transform. origin_coordinate ( ) ,
518- x_pixel_size : geo_transform. x_pixel_size ( ) ,
519- y_pixel_size : geo_transform. y_pixel_size ( ) ,
520- } ,
521- width,
522- height,
523- file_not_found_handling : FileNotFoundHandling :: Error ,
524- no_data_value : None ,
525- properties_mapping : None ,
526- gdal_open_options : None ,
527- gdal_config_options : gdal_config_options. clone ( ) ,
528- allow_alphaband_as_mask : false ,
529- retry : Some ( GdalRetryOptions { max_retries : 99 } ) , // TODO: make configurable?
530- } ,
531- } ) ;
541+ return None ;
532542 }
543+
544+ return Some ( 1 ) ;
533545 }
534546
535- Ok ( ( ) )
547+ let Some ( required_band_name) = required_band_name else {
548+ tracing:: warn!(
549+ "STAC asset with href {} includes bands, but dataset configuration does not specify a band name. Skipping asset." ,
550+ asset. href
551+ ) ;
552+ return None ;
553+ } ;
554+
555+ let Some ( asset_band_idx) = asset
556+ . bands
557+ . iter ( )
558+ . position ( |asset_band| asset_band. name . as_deref ( ) == Some ( required_band_name) )
559+ else {
560+ tracing:: debug!(
561+ "Skipping asset with href {} due to missing required band {}" ,
562+ asset. href,
563+ required_band_name
564+ ) ;
565+ return None ;
566+ } ;
567+
568+ Some ( asset_band_idx + 1 )
536569 }
537570
538571 fn gdal_config_options_for_file_path ( & self , file_path : & Path ) -> Option < Vec < ( String , String ) > > {
0 commit comments