@@ -595,7 +595,23 @@ async def list_objects(self, datapoint: xr.Dataset | CopernicusStorageGranule) -
595595
596596 Returns:
597597 List of object keys available for the given datapoint, relative to the granule location."""
598- return await list_object_paths (self ._store , _copernicus_s3_prefix (datapoint ))
598+ return await self ._list_objects (datapoint )
599+
600+ async def _list_objects (self , datapoint : xr .Dataset | CopernicusStorageGranule ) -> list [str ]:
601+ """List all available objects for a given datapoint.
602+
603+ Args:
604+ datapoint: The datapoint to list available objects the data for.
605+
606+ Returns:
607+ List of object keys available for the given datapoint, relative to the granule location."""
608+
609+ granule = CopernicusStorageGranule .from_data (datapoint )
610+ # special handling for Sentinel-5P, where the location is not a folder but a single file
611+ if granule .location .endswith (".nc" ):
612+ return [Path (granule .granule_name ).name ]
613+
614+ return await list_object_paths (self ._store , _copernicus_s3_prefix (granule ))
599615
600616 async def download (
601617 self ,
@@ -615,8 +631,10 @@ async def download(
615631 Returns:
616632 The path to the downloaded data directory.
617633 """
618- all_objects = await list_object_paths (self ._store , _copernicus_s3_prefix (datapoint ))
619- return await self ._download_objects (datapoint , all_objects , output_dir , show_progress , max_concurrent_downloads )
634+ granule = CopernicusStorageGranule .from_data (datapoint )
635+
636+ all_objects = await self ._list_objects (granule )
637+ return await self ._download_objects (granule , all_objects , output_dir , show_progress , max_concurrent_downloads )
620638
621639 async def download_objects (
622640 self ,
@@ -652,7 +670,14 @@ async def _download_objects(
652670 show_progress : bool = True ,
653671 max_concurrent_downloads : int = 4 ,
654672 ) -> Path :
655- prefix = _copernicus_s3_prefix (datapoint )
673+ granule = CopernicusStorageGranule .from_data (datapoint )
674+ prefix = _copernicus_s3_prefix (granule )
675+ single_file = False
676+
677+ # special handling for Sentinel-5P, where the location is not a folder but a single file
678+ if granule .location .endswith (".nc" ):
679+ single_file = True
680+ prefix = str (Path (prefix ).parent )
656681
657682 base_folder = output_dir or self ._cache
658683 if base_folder is None :
@@ -663,8 +688,61 @@ async def _download_objects(
663688 return output_folder
664689
665690 await download_objects (self ._store , prefix , objects , output_folder , show_progress , max_concurrent_downloads )
691+ if single_file :
692+ return output_folder / objects [0 ]
666693 return output_folder
667694
695+ async def download_quicklook (self , datapoint : xr .Dataset | CopernicusStorageGranule ) -> Path :
696+ """Download the quicklook image for a given datapoint.
697+
698+ Args:
699+ datapoint: The datapoint to download the quicklook for.
700+
701+ Raises:
702+ ValueError: If no quicklook is available for the given datapoint.
703+
704+ Returns:
705+ The path to the downloaded quicklook image.
706+ """
707+ return await self ._download_quicklook (datapoint )
708+
709+ async def quicklook (
710+ self , datapoint : xr .Dataset | CopernicusStorageGranule , width : int = 600 , height : int = 600
711+ ) -> None :
712+ """Display the quicklook image for a given datapoint.
713+
714+ Requires an IPython kernel to be running. If you are not using IPython, use download_quicklook instead.
715+
716+ Args:
717+ datapoint: The datapoint to download the quicklook for.
718+ width: Display width of the image in pixels. Defaults to 600.
719+ height: Display height of the image in pixels. Defaults to 600.
720+
721+ Raises:
722+ ImportError: In case IPython is not available.
723+ ValueError: If no quicklook is available for the given datapoint.
724+ """
725+ if Image is None :
726+ raise ImportError ("IPython is not available, please use download_preview instead." )
727+ granule = CopernicusStorageGranule .from_data (datapoint )
728+ quicklook = await self ._download_quicklook (granule )
729+ _display_quicklook (quicklook , width , height , f"<code>{ granule .granule_name } © ESA { granule .time .year } </code>" )
730+
731+ async def _download_quicklook (self , datapoint : xr .Dataset | CopernicusStorageGranule ) -> Path :
732+ granule = CopernicusStorageGranule .from_data (datapoint )
733+ if granule .thumbnail is None :
734+ raise ValueError (f"No quicklook available for { granule .granule_name } " )
735+
736+ prefix = _copernicus_s3_prefix (granule )
737+ output_folder = (
738+ self ._cache / self ._STORAGE_PROVIDER / Path (prefix )
739+ if self ._cache is not None
740+ else Path .cwd () / self ._STORAGE_PROVIDER
741+ )
742+
743+ await download_objects (self ._store , prefix , [granule .thumbnail ], output_folder , show_progress = False )
744+ return output_folder / granule .thumbnail
745+
668746
669747def _landsat_s3_prefix (datapoint : xr .Dataset | USGSLandsatStorageGranule ) -> str :
670748 granule = USGSLandsatStorageGranule .from_data (datapoint )
0 commit comments