Skip to content

Commit 3070725

Browse files
authored
Merge pull request #24 from umr-lops/s3protocol
S3protocol
2 parents 66d941a + 739859e commit 3070725

File tree

7 files changed

+88
-24
lines changed

7 files changed

+88
-24
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ __pycache__/
1919
.coverage.*
2020
.cache
2121
/docs/_build/
22+
localconfig.yml
23+
.idea

highleveltests/open_SLC_IW.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from safe_s1 import Sentinel1Reader, getconfig
2+
import time
3+
conf = getconfig.get_config()
4+
subswath = conf['nfs_iw_grd_path']
5+
print(subswath)
6+
t0 = time.time()
7+
sub_reader = Sentinel1Reader(subswath)
8+
elapse_t = time.time()-t0
9+
10+
dt = sub_reader.datatree
11+
print('out of the reader')
12+
print(dt)
13+
print('time to read the SAFE through S3: %1.2f sec'%elapse_t)

highleveltests/open_SLC_IW_S3.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# see https://stackoverflow.com/questions/69624867/no-such-file-error-when-trying-to-create-local-cache-of-s3-object
2+
from safe_s1 import Sentinel1Reader,getconfig
3+
import pdb
4+
import os
5+
import time
6+
import logging
7+
import fsspec
8+
logging.basicConfig(level=logging.INFO)
9+
logging.info('test start')
10+
conf = getconfig.get_config()
11+
access_key = conf['access_key']
12+
secret_key = conf['secret_key']
13+
entrypoint_url = conf['entrypoint_url']
14+
s3 = fsspec.filesystem("s3", anon=False,
15+
key=access_key,
16+
secret=secret_key,
17+
endpoint_url='https://'+entrypoint_url)
18+
19+
# this syntaxe works we can get content xml files but I would have to precise which subswath I want to decode in case of SLC
20+
# safe2 = 's3:///eodata/Sentinel-1/SAR/SLC/2019/10/13/S1B_IW_SLC__1SDV_20191013T155948_20191013T160015_018459_022C6B_13A2.SAFE'
21+
safe2 = 's3:///eodata/Sentinel-1/SAR/IW_GRDH_1S/2024/04/18/S1A_IW_GRDH_1SSH_20240418T080141_20240418T080210_053485_067D74_C073.SAFE'
22+
# safe2 = conf['s3_iw_grd_path']
23+
option = 'kwargs'
24+
if option == 'kwargs':
25+
storage_options = {"anon": False, "client_kwargs": {"endpoint_url": 'https://'+entrypoint_url, 'aws_access_key_id':access_key,
26+
'aws_secret_access_key':secret_key}}
27+
t0 = time.time()
28+
sub_reader = Sentinel1Reader(safe2,backend_kwargs={"storage_options": storage_options})
29+
elapse_t = time.time()-t0
30+
print('time to read the SAFE through S3: %1.2f sec'%elapse_t)
31+
else:
32+
# this solution is not supported.
33+
sub_reader = Sentinel1Reader(s3.get_mapper(safe2)) # botocore.errorfactory.NoSuchKey: An error occurred (NoSuchKey) when calling the GetObject operation: Unknown
34+
dt = sub_reader.datatree
35+
print('out of the reader')
36+
print(dt)

safe_s1/getconfig.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import yaml
2+
import os
3+
import logging
4+
import safe_s1
5+
from pathlib import Path
6+
# determine the config file we will use (config.yml by default, and a local config if one is present) and retrieve
7+
# the products names
8+
def get_config():
9+
local_config_pontential_path = os.path.join(os.path.dirname(safe_s1.__file__), 'localconfig.yml')
10+
logging.info('potential local config: %s',local_config_pontential_path)
11+
#local_config_pontential_path = Path(os.path.join('~', 'xarray-safe-s1', 'localconfig.yml')).expanduser()
12+
if os.path.exists(local_config_pontential_path):
13+
logging.info('localconfig used')
14+
config_path = local_config_pontential_path
15+
with open(config_path) as config_content:
16+
conf = yaml.load(config_content, Loader=yaml.SafeLoader)
17+
else:
18+
logging.info('default config')
19+
config_path = Path(os.path.join(os.path.dirname(safe_s1.__file__), 'config.yml'))
20+
with open(config_path) as config_content:
21+
conf = yaml.load(config_content, Loader=yaml.SafeLoader)
22+
return conf
23+

safe_s1/metadata.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import os
22
import re
3-
3+
import pdb
44
import dask
55
import fsspec
66
import numpy as np
@@ -21,7 +21,7 @@ class Sentinel1Reader:
2121

2222
def __init__(self, name, backend_kwargs=None):
2323
if not isinstance(name, (str, os.PathLike)):
24-
raise ValueError(f"cannot deal with object of type {type(name)}: {name}")
24+
raise ValueError(f"cannot deal with object of type {type(name)}: {name}")
2525
# gdal dataset name
2626
if not name.startswith('SENTINEL1_DS:'):
2727
name = 'SENTINEL1_DS:%s:' % name
@@ -39,10 +39,13 @@ def __init__(self, name, backend_kwargs=None):
3939
"""Dataset path"""
4040
self.safe = os.path.basename(self.path)
4141

42+
self.path = os.fspath(self.path)
43+
4244
if backend_kwargs is None:
4345
backend_kwargs = {}
44-
self.path = os.fspath(self.path)
46+
4547
storage_options = backend_kwargs.get("storage_options", {})
48+
4649
mapper = fsspec.get_mapper(self.path, **storage_options)
4750
self.xml_parser = XmlParser(
4851
xpath_mappings=sentinel1_xml_mappings.xpath_mappings,
@@ -89,7 +92,6 @@ def __init__(self, name, backend_kwargs=None):
8992
'geolocationGrid': None,
9093
}
9194
if not self.multidataset:
92-
9395
self._dict = {
9496
'geolocationGrid': self.geoloc,
9597
'orbit': self.orbit,
@@ -105,6 +107,9 @@ def __init__(self, name, backend_kwargs=None):
105107
}
106108
self.dt = datatree.DataTree.from_dict(self._dict)
107109
assert self.dt==self.datatree
110+
else:
111+
print('multidataset')
112+
raise Exception()
108113

109114
def load_digital_number(self, resolution=None, chunks=None, resampling=rasterio.enums.Resampling.rms):
110115
"""

safe_s1/sentinel1_xml_mappings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ def df_files(annotation_files, measurement_files, noise_files, calibration_files
472472
def xsd_files_func(xsd_product_file):
473473
"""
474474
return a xarray Dataset with path of the different xsd files
475-
:param xsd_product:
475+
:param xsd_product: str
476476
:return:
477477
"""
478478
ds = xr.Dataset()

test/test_s1reader.py

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,15 @@
1-
import safe_s1
2-
from safe_s1 import sentinel1_xml_mappings, Sentinel1Reader
3-
import os
1+
from safe_s1 import sentinel1_xml_mappings, Sentinel1Reader, getconfig
42
import logging
5-
from pathlib import Path
6-
import yaml
3+
74

85
logging.basicConfig()
96
logging.captureWarnings(True)
107

118
logger = logging.getLogger('s1_reader_test')
129
logger.setLevel(logging.DEBUG)
1310

14-
15-
# determine the config file we will use (config.yml by default, and a local config if one is present) and retrieve
16-
# the products names
17-
local_config_pontential_path = Path(os.path.join('~', 'xarray-safe-s1', 'localconfig.yml')).expanduser()
18-
if local_config_pontential_path.exists():
19-
config_path = local_config_pontential_path
20-
with open(config_path) as config_content:
21-
products = yaml.load(config_content, Loader=yaml.SafeLoader)['product_paths']
22-
else:
23-
config_path = Path(os.path.join(os.path.dirname(safe_s1.__file__), 'config.yml'))
24-
with open(config_path) as config_content:
25-
raw_products = yaml.load(config_content, Loader=yaml.SafeLoader)['product_paths']
26-
products = [sentinel1_xml_mappings.get_test_file(filename) for filename in raw_products]
27-
11+
conf = getconfig.get_config()
12+
products = [sentinel1_xml_mappings.get_test_file(filename) for filename in conf['product_paths']]
2813

2914
# Try to apply the reader on different products
3015
def test_reader():

0 commit comments

Comments
 (0)