eotdl 2023.10.25.post10__py3-none-any.whl → 2023.11.2.post2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eotdl/__init__.py +1 -1
- eotdl/cli.py +6 -2
- eotdl/commands/auth.py +18 -1
- eotdl/commands/datasets.py +61 -11
- eotdl/commands/models.py +108 -0
- eotdl/curation/__init__.py +1 -4
- eotdl/curation/stac/assets.py +2 -1
- eotdl/curation/stac/dataframe.py +1 -1
- eotdl/curation/stac/extensions/label/image_name_labeler.py +6 -5
- eotdl/curation/stac/extensions/ml_dataset.py +15 -25
- eotdl/curation/stac/extent.py +1 -1
- eotdl/curation/stac/stac.py +1 -1
- eotdl/datasets/download.py +5 -4
- eotdl/datasets/ingest.py +25 -154
- eotdl/datasets/retrieve.py +1 -1
- eotdl/files/__init__.py +1 -0
- eotdl/files/ingest.py +175 -0
- eotdl/models/__init__.py +3 -0
- eotdl/models/download.py +119 -0
- eotdl/models/ingest.py +47 -0
- eotdl/models/metadata.py +16 -0
- eotdl/models/retrieve.py +26 -0
- eotdl/repos/FilesAPIRepo.py +136 -95
- eotdl/repos/ModelsAPIRepo.py +40 -0
- eotdl/repos/__init__.py +1 -0
- eotdl/shared/__init__.py +1 -0
- eotdl/tools/__init__.py +5 -6
- eotdl/tools/geo_utils.py +15 -1
- eotdl/tools/stac.py +144 -8
- eotdl/tools/time_utils.py +19 -6
- eotdl/tools/tools.py +2 -3
- {eotdl-2023.10.25.post10.dist-info → eotdl-2023.11.2.post2.dist-info}/METADATA +1 -1
- {eotdl-2023.10.25.post10.dist-info → eotdl-2023.11.2.post2.dist-info}/RECORD +38 -35
- eotdl/curation/folder_formatters/__init__.py +0 -1
- eotdl/curation/folder_formatters/base.py +0 -19
- eotdl/curation/folder_formatters/sentinel_hub.py +0 -135
- eotdl/curation/stac/utils/__init__.py +0 -5
- eotdl/curation/stac/utils/geometry.py +0 -22
- eotdl/curation/stac/utils/stac.py +0 -143
- eotdl/curation/stac/utils/time.py +0 -21
- /eotdl/{datasets/utils.py → shared/checksum.py} +0 -0
- /eotdl/{curation/stac/utils → tools}/metadata.py +0 -0
- /eotdl/{curation/stac/utils → tools}/paths.py +0 -0
- {eotdl-2023.10.25.post10.dist-info → eotdl-2023.11.2.post2.dist-info}/WHEEL +0 -0
- {eotdl-2023.10.25.post10.dist-info → eotdl-2023.11.2.post2.dist-info}/entry_points.txt +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
eotdl/__init__.py,sha256=
|
1
|
+
eotdl/__init__.py,sha256=vq3__ImOs-riW0l9qLaTFxxobD0xu7idyuL5K_MsdVA,29
|
2
2
|
eotdl/access/__init__.py,sha256=OFdCDemao6Ez1w18-ydQ8G_CqeQ8h43hFcdsJcq2UKI,208
|
3
3
|
eotdl/access/airbus/__init__.py,sha256=KdVilLghjjs_EEMGlbZntveRR7yA6pg_CdV04ulZWiQ,75
|
4
4
|
eotdl/access/airbus/client.py,sha256=thVIfCscsrOp6l2uizY6Fai4Jk4e_r-2luyr15YAxn0,11017
|
@@ -16,17 +16,15 @@ eotdl/auth/auth.py,sha256=voxwxTERghLQdqrBSyjZrgvKrcF01aWUTc0-vxLFFgY,1601
|
|
16
16
|
eotdl/auth/errors.py,sha256=PpnFU2DvnRo8xrM77wgskKi0tfEJ1Rhle4xv2RD1qpk,306
|
17
17
|
eotdl/auth/is_logged.py,sha256=QREuhkoDnarZoUZwCxVCNoESGb_Yukh0lJo1pXvrV9Q,115
|
18
18
|
eotdl/auth/logout.py,sha256=P_Sp6WmVvnG3R9V1L9541KNyHFko9DtQPqAKD2vaguw,161
|
19
|
-
eotdl/cli.py,sha256=
|
19
|
+
eotdl/cli.py,sha256=7JnlHLgi08Q8p5jjMT02uHIxNdQI8eWh7zSkZ19VqZc,423
|
20
20
|
eotdl/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
-
eotdl/commands/auth.py,sha256=
|
22
|
-
eotdl/commands/datasets.py,sha256=
|
23
|
-
eotdl/
|
24
|
-
eotdl/curation/
|
25
|
-
eotdl/curation/folder_formatters/base.py,sha256=HrwzctBdvSm-Q2A5nV6I_M5X69LAH1frGJRZbgfEEYA,380
|
26
|
-
eotdl/curation/folder_formatters/sentinel_hub.py,sha256=nCUtjoqC7hFjAhqHoz0XfeETaB5T_n9rRMcPi3nyHjs,5691
|
21
|
+
eotdl/commands/auth.py,sha256=z2cfzSWUw-AFRlkiMtnR7sIqYJMVwG94nW-7W5rmMio,1564
|
22
|
+
eotdl/commands/datasets.py,sha256=s05OOOtLi54kq-3IWZeztxaAPMVFpTxNiaofA17FEL0,4310
|
23
|
+
eotdl/commands/models.py,sha256=r1XLrVlgdG2bFKX2TaLf7CeVvRi0rrBQMT52DNirF-A,4219
|
24
|
+
eotdl/curation/__init__.py,sha256=n_zpB3byU4Dg5R33eyIMmMUBAyze_meopR-FjGbNM-Q,243
|
27
25
|
eotdl/curation/stac/__init__.py,sha256=MYeO3zfiLrou6oxSHBujyJtfDefYt6xDHU7Y6-ujMjA,198
|
28
|
-
eotdl/curation/stac/assets.py,sha256=
|
29
|
-
eotdl/curation/stac/dataframe.py,sha256=
|
26
|
+
eotdl/curation/stac/assets.py,sha256=Ejdm_vjrcyo7KplaPrxHLZDApirshFGdze6cdq9V7fE,4284
|
27
|
+
eotdl/curation/stac/dataframe.py,sha256=OUHEaZBvQGMzovHBJ44aFTeU-v3YQLaSLWzdJ8OQT68,5307
|
30
28
|
eotdl/curation/stac/dataframe_bck.py,sha256=0sMc00gnYNp58ShEGvXWbBh_5QOSpvKKYA0bKC5fFL4,8495
|
31
29
|
eotdl/curation/stac/dataframe_labeling.py,sha256=ZXl5edYHyKAjJDxsQyNXprJcnrPZyz9yzU0zHTgk99o,1414
|
32
30
|
eotdl/curation/stac/extensions/__init__.py,sha256=I3IspniNTkgeyLHdR9a_-kuXZm6TpH92b4dpWafh1Rk,596
|
@@ -35,26 +33,20 @@ eotdl/curation/stac/extensions/dem.py,sha256=GtDPNuOc_-Qxw1kJJgirGGRzZqk7hJTWHWV
|
|
35
33
|
eotdl/curation/stac/extensions/eo.py,sha256=aiN5YTNPvyC4kid0gQYzJK5MYAeUe40YmGcU9PfxHQ4,3965
|
36
34
|
eotdl/curation/stac/extensions/label/__init__.py,sha256=1MDoAAm9Va4eRkFALwzFTQ5CcWbIN25KSnjL6k75nSQ,121
|
37
35
|
eotdl/curation/stac/extensions/label/base.py,sha256=n914NVhtH7FTMmmhPIFbJh0n1wJasVgxTrvgSUMxP3c,4063
|
38
|
-
eotdl/curation/stac/extensions/label/image_name_labeler.py,sha256=
|
36
|
+
eotdl/curation/stac/extensions/label/image_name_labeler.py,sha256=ZhUG5njBSCeo17SC0_LCdNnYxVPvqSNuFGTrWd_XtUI,7922
|
39
37
|
eotdl/curation/stac/extensions/label/scaneo.py,sha256=C_3azPqN3QzMWNGJcrxt0wKO_14YFKL5D6bg83pSPqs,8757
|
40
|
-
eotdl/curation/stac/extensions/ml_dataset.py,sha256=
|
38
|
+
eotdl/curation/stac/extensions/ml_dataset.py,sha256=HKtszM6nl-rI5PQHgdgYdho9v3w2SIPJHb-VCe2pMe4,19222
|
41
39
|
eotdl/curation/stac/extensions/projection.py,sha256=NZndrCnqa_0PWtfcTAFbXjkpO83Szj2fldaUAMWM7Jc,1200
|
42
40
|
eotdl/curation/stac/extensions/raster.py,sha256=UD6cTtb4HTILw5iie1xvl7b0SmypxzyRyamFlf1YZXo,1399
|
43
41
|
eotdl/curation/stac/extensions/sar.py,sha256=_1a9MWA7YElem6u1z9ynjdfLWaeI6J8qwF8yDRqr3XI,1582
|
44
|
-
eotdl/curation/stac/extent.py,sha256=
|
42
|
+
eotdl/curation/stac/extent.py,sha256=6RMaiZ9d_iDHrewldmRZ_g6h4hh_smEawvS_9QslDYI,4941
|
45
43
|
eotdl/curation/stac/parsers.py,sha256=KumL2ieBt0ATGgKoGyc-AJ99zSMeLD4-tI5MF9ruYPw,1380
|
46
|
-
eotdl/curation/stac/stac.py,sha256=
|
47
|
-
eotdl/curation/stac/utils/__init__.py,sha256=VWbLLESvyTJGNcHutnMFosKsCQpyV4xnb4bIHuBJZqE,108
|
48
|
-
eotdl/curation/stac/utils/geometry.py,sha256=wkS7E9YjfXtbWL4hQtgjT6bh62BZZyOYmJA-9xkjWwY,388
|
49
|
-
eotdl/curation/stac/utils/metadata.py,sha256=YzXyOHfF3j6c_Az6RRgIHEI9n69vOI2DvYaMmLNatSU,1658
|
50
|
-
eotdl/curation/stac/utils/paths.py,sha256=IEzfpjadd3KnwOQ6F_1vBRyxnm12QcD1TboPRd-I15w,1166
|
51
|
-
eotdl/curation/stac/utils/stac.py,sha256=mvAdCxDTX3t634qvJ2YXEXfUo8vhZFKx57WRm3z0VVo,4840
|
52
|
-
eotdl/curation/stac/utils/time.py,sha256=hj3-SYnLriQfX-7jqJwYdFcfzzvT5KU3L8IZwGyE4FE,463
|
44
|
+
eotdl/curation/stac/stac.py,sha256=Rm5ogUxj3xLqZon4ub2VmXJfyjfim7ul-PMQe6rRTOo,13353
|
53
45
|
eotdl/datasets/__init__.py,sha256=GIfgqrFq1LblG8qT1zNthm28drw1faLAenGbKjX0rdw,174
|
54
|
-
eotdl/datasets/download.py,sha256=
|
55
|
-
eotdl/datasets/ingest.py,sha256=
|
46
|
+
eotdl/datasets/download.py,sha256=SBUsYqnKahw4MMOSzT2pxX5bDD1f1wAu31ovtuQu4Fo,4381
|
47
|
+
eotdl/datasets/ingest.py,sha256=oQ3KycGXRC8qBiV4VFfdyDfQn2HP86RAx78ZiM2MKf8,1792
|
56
48
|
eotdl/datasets/metadata.py,sha256=L23_EziGVSDJ-WZbYUYNN22GrgbCdMGxwJhgK9uzW0U,390
|
57
|
-
eotdl/datasets/retrieve.py,sha256=
|
49
|
+
eotdl/datasets/retrieve.py,sha256=DJz5K1bCLizg9YNwBnhHMFzcxMXar2socYkFONdSL4c,1041
|
58
50
|
eotdl/datasets/usecases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
59
51
|
eotdl/datasets/usecases/datasets/DownloadFile.py,sha256=PoP0Dl2LBshKzbgArgxwxIVs-KT2IsfZKi0qSyiBsoI,936
|
60
52
|
eotdl/datasets/usecases/datasets/DownloadFileURL.py,sha256=6OcNuCys45MXu9-7GtES0zg2QmY02EAkj_P3cVKVUvo,603
|
@@ -63,19 +55,30 @@ eotdl/datasets/usecases/datasets/IngestLargeDataset.py,sha256=yRl4eqDCNPcmbU0rrt
|
|
63
55
|
eotdl/datasets/usecases/datasets/IngestLargeDatasetParallel.py,sha256=G6uVmpZLkn6lqUVQkjw0ne1xlBcJKHoJik4xLnlqd6o,1612
|
64
56
|
eotdl/datasets/usecases/datasets/IngestSTAC.py,sha256=QAMLSkMFlc-ic0JWaIdAf0SXPkYcawy-RJqfvDqTD7A,3075
|
65
57
|
eotdl/datasets/usecases/datasets/__init__.py,sha256=Tx4ISHtcjbu4KUVgjTac_pjpT0vsN-QpkIwtyx8xUYg,383
|
66
|
-
eotdl/
|
58
|
+
eotdl/files/__init__.py,sha256=71KfzCidZzFV82Zmc2GRxXzpB9sZKGI95lBxySRxbPY,33
|
59
|
+
eotdl/files/ingest.py,sha256=mnjqellKIf-jVVAjharV5rehU4mmv7GxGhRwJ2BtCcw,6020
|
60
|
+
eotdl/models/__init__.py,sha256=fe1VfnlOxlfviphkkzaY4q8mkm0QxcdJxB3peScBZYk,108
|
61
|
+
eotdl/models/download.py,sha256=hWFEuJUZsjYnSDixMkHgmYDwxNMJEQ13-AJQPnyZOiY,4340
|
62
|
+
eotdl/models/ingest.py,sha256=Zxv9oL5VOqPXgJgaOROt7v2twRPqzajllpP5ZgyNf3Q,1519
|
63
|
+
eotdl/models/metadata.py,sha256=L23_EziGVSDJ-WZbYUYNN22GrgbCdMGxwJhgK9uzW0U,390
|
64
|
+
eotdl/models/retrieve.py,sha256=-Ij7dT4J1p7MW4n13OlPB9OW4tBaBXPwk9dW8IuCZPc,664
|
67
65
|
eotdl/repos/APIRepo.py,sha256=tjvtr96d1fhnKEdGDmc90NrwBW7YVCtdsKLLtV82SBE,402
|
68
66
|
eotdl/repos/AuthAPIRepo.py,sha256=T-TPDjZa1u-JnUsKoKp-T9x__L0aUfLUUdP7xZFV_hI,770
|
69
67
|
eotdl/repos/AuthRepo.py,sha256=6AWOdWgXKAVYJ2pB3Fj6X2KABoH2u-tpUyhEkNMWxX0,1001
|
70
68
|
eotdl/repos/DatasetsAPIRepo.py,sha256=HQh4PCS9zP6zPK86lsfUX08jhKIlOKUOswZaROVMkYY,9979
|
71
|
-
eotdl/repos/FilesAPIRepo.py,sha256=
|
72
|
-
eotdl/repos/
|
73
|
-
eotdl/
|
74
|
-
eotdl/
|
75
|
-
eotdl/
|
76
|
-
eotdl/tools/
|
77
|
-
eotdl/tools/
|
78
|
-
eotdl
|
79
|
-
eotdl
|
80
|
-
eotdl
|
81
|
-
eotdl
|
69
|
+
eotdl/repos/FilesAPIRepo.py,sha256=WgGTyYljlSFxD8-0BePEwdks6voVy5rPjqdTruc31MQ,10924
|
70
|
+
eotdl/repos/ModelsAPIRepo.py,sha256=6PDn1eHb0g3dVyQyB5aEGnIlWi9Ez8Vlnj4A_QL3Ea8,1211
|
71
|
+
eotdl/repos/__init__.py,sha256=WvX5TP49k7yYb5dWWNjv5kzbdluO3dJ4LqjQxRIOUVc,222
|
72
|
+
eotdl/shared/__init__.py,sha256=mF7doJC8Z5eTPmB01UQvPivThZac32DRY33T6qshXfg,41
|
73
|
+
eotdl/shared/checksum.py,sha256=4IB6N9jRO0chMDNJzpdnFDhC9wcFF9bO5oHq2HodcHw,479
|
74
|
+
eotdl/tools/__init__.py,sha256=keLICmgtaXy3rc6oOHNDli8H9YHFhElTg2GtF8Vb-eM,136
|
75
|
+
eotdl/tools/geo_utils.py,sha256=vrTOq456Ck-qZiFT1mYM2cnlacm-4Q8D_dPadsqr_NY,7153
|
76
|
+
eotdl/tools/metadata.py,sha256=YzXyOHfF3j6c_Az6RRgIHEI9n69vOI2DvYaMmLNatSU,1658
|
77
|
+
eotdl/tools/paths.py,sha256=IEzfpjadd3KnwOQ6F_1vBRyxnm12QcD1TboPRd-I15w,1166
|
78
|
+
eotdl/tools/stac.py,sha256=cqv9Dc2uUnonMKF6MP9C5h9fHs-oENjgmcnRJNRWNgA,5937
|
79
|
+
eotdl/tools/time_utils.py,sha256=pb8h4bCQTTarNHq38UfjNotefm5l4qGjpYBENzzcqHY,4212
|
80
|
+
eotdl/tools/tools.py,sha256=x2UFa5wHunX4qn3lqZYP0BtPHZB-w3dMwK1fac8LUhI,6100
|
81
|
+
eotdl-2023.11.2.post2.dist-info/METADATA,sha256=SZCcWR1nXbqijiUCFCeSOThICABwsDLvQ0K_iQ8zzWc,3929
|
82
|
+
eotdl-2023.11.2.post2.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
|
83
|
+
eotdl-2023.11.2.post2.dist-info/entry_points.txt,sha256=s6sfxUfRrSX2IP2UbrzTFTvRCtLgw3_OKcHlOKf_5F8,39
|
84
|
+
eotdl-2023.11.2.post2.dist-info/RECORD,,
|
@@ -1 +0,0 @@
|
|
1
|
-
from .sentinel_hub import SHFolderFormatter
|
@@ -1,19 +0,0 @@
|
|
1
|
-
'''
|
2
|
-
Module for folder formatter classes
|
3
|
-
'''
|
4
|
-
|
5
|
-
|
6
|
-
class FolderFormatter:
|
7
|
-
|
8
|
-
def format_folders(self) -> None:
|
9
|
-
"""
|
10
|
-
Format the folder structure of the downloaded data to a
|
11
|
-
digestible format
|
12
|
-
"""
|
13
|
-
pass
|
14
|
-
|
15
|
-
def generate_raster_metadata(self) -> None:
|
16
|
-
"""
|
17
|
-
Generate metadata.json file for a raster file
|
18
|
-
"""
|
19
|
-
pass
|
@@ -1,135 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Module for formatter classes
|
3
|
-
"""
|
4
|
-
|
5
|
-
import json
|
6
|
-
import rasterio
|
7
|
-
|
8
|
-
from typing import Optional
|
9
|
-
from os.path import join, dirname
|
10
|
-
from os import makedirs
|
11
|
-
from glob import glob
|
12
|
-
from shutil import rmtree, copyfile
|
13
|
-
from .base import FolderFormatter
|
14
|
-
|
15
|
-
|
16
|
-
class SHFolderFormatter(FolderFormatter):
|
17
|
-
"""
|
18
|
-
Class for formatting the directories of Sentinel images downloaded from Sentinel Hub Services
|
19
|
-
"""
|
20
|
-
|
21
|
-
def __init__(self, root_folder):
|
22
|
-
super().__init__()
|
23
|
-
self.root = root_folder
|
24
|
-
|
25
|
-
@classmethod
|
26
|
-
def structured_format_folders(self) -> None:
|
27
|
-
"""
|
28
|
-
Format the folder structure of the downloaded data from Sentinel Hub to a
|
29
|
-
digestible format, suitable for STAC metadata generation.
|
30
|
-
|
31
|
-
This formatted format is a structured format, where every image is located in
|
32
|
-
a single folder, with its metadata.
|
33
|
-
"""
|
34
|
-
images = glob(join(self.root, '**/*.tiff'), recursive=True)
|
35
|
-
|
36
|
-
for image in images:
|
37
|
-
# Folder with the request and response, with the if of the request
|
38
|
-
image_dir = dirname(image)
|
39
|
-
# Destination folder, with format <id>_<date>
|
40
|
-
dest_dir = dirname(image_dir)
|
41
|
-
# Get the request.json file with the request parameters
|
42
|
-
request_file = join(image_dir, 'request.json')
|
43
|
-
request_json = json.load(open(request_file))
|
44
|
-
# Generate a metadata.json file of the raster in the destination folder
|
45
|
-
# It will extract some needed parameters, which will be used later
|
46
|
-
# for the STAC generation
|
47
|
-
# It also returns the data type of the response
|
48
|
-
data_type = self.generate_raster_metadata(request_json, image, dest_dir)
|
49
|
-
# Copy the response tiff to the destination folder
|
50
|
-
copyfile(image, join(dest_dir, f'{data_type}.tiff'))
|
51
|
-
# Remove the request and response folder
|
52
|
-
rmtree(image_dir)
|
53
|
-
|
54
|
-
def unestructured_format_folders(self, output_folder: Optional[str] = None) -> None:
|
55
|
-
"""
|
56
|
-
Format the folder structure of the downloaded data from Sentinel Hub to a
|
57
|
-
digestible format, suitable for STAC metadata generation and labeling with SCANEO.
|
58
|
-
|
59
|
-
This formatted format is a unestructured format, where all the images are located
|
60
|
-
into the same folder, with them metadata files with the same name as the image.
|
61
|
-
"""
|
62
|
-
images = glob(join(self.root, '**/*.tiff'), recursive=True)
|
63
|
-
|
64
|
-
if not output_folder:
|
65
|
-
output_folder = self.root
|
66
|
-
makedirs(output_folder, exist_ok=True)
|
67
|
-
|
68
|
-
n = 0
|
69
|
-
for image in images:
|
70
|
-
# Folder with the request and response, with the id of the request
|
71
|
-
image_dir = dirname(image)
|
72
|
-
# Parent image folder, with format <id>_<date>
|
73
|
-
parent_dir = dirname(image_dir)
|
74
|
-
parent_dir_name = parent_dir.split('/')[-1]
|
75
|
-
parent_dir_name_split = parent_dir_name.split('_')
|
76
|
-
id = parent_dir_name_split[0] # ID of the given location
|
77
|
-
# Get the request.json file with the request parameters
|
78
|
-
request_file = join(image_dir, 'request.json')
|
79
|
-
request_json = json.load(open(request_file))
|
80
|
-
# Generate a metadata.json file of the raster in the destination folder
|
81
|
-
# It will extract some needed parameters, which will be used later
|
82
|
-
# for the STAC generation
|
83
|
-
# As file name, we give the same name as de image, which is <id>_<n>
|
84
|
-
n += 1
|
85
|
-
filename = f'{id}_{n}'
|
86
|
-
self.generate_raster_metadata(request_json, image, output_folder, filename)
|
87
|
-
# Copy the response tiff to the destination folder
|
88
|
-
copyfile(image, join(output_folder, f'{filename}.tif'))
|
89
|
-
# Remove the request and response folder
|
90
|
-
rmtree(parent_dir)
|
91
|
-
|
92
|
-
def generate_raster_metadata(self,
|
93
|
-
request_json: dict,
|
94
|
-
raster_path: str,
|
95
|
-
output_folder: str,
|
96
|
-
output_name: Optional[str] = 'metadata'
|
97
|
-
) -> None:
|
98
|
-
"""
|
99
|
-
Generate metadata.json file for a raster file
|
100
|
-
|
101
|
-
:param raster_path: path to the raster file
|
102
|
-
:param output_folder: output folder to write the metadata.json file to
|
103
|
-
:param date_adquired: date adquired of the raster file
|
104
|
-
:param output_name: name of the metadata file
|
105
|
-
"""
|
106
|
-
# Get the date adquired from the request json
|
107
|
-
with rasterio.open(raster_path) as ds:
|
108
|
-
bounds = ds.bounds
|
109
|
-
dst_crs = "EPSG:4326"
|
110
|
-
left, bottom, right, top = rasterio.warp.transform_bounds(
|
111
|
-
ds.crs, dst_crs, *bounds
|
112
|
-
)
|
113
|
-
bbox = [left, bottom, right, top]
|
114
|
-
|
115
|
-
payload_data = request_json['request']['payload']['input']['data'][0]
|
116
|
-
# Get the data type from the request json
|
117
|
-
data_type = payload_data['type']
|
118
|
-
# Get the acquision date from the request json
|
119
|
-
if 'timeRange' in payload_data['dataFilter']:
|
120
|
-
data_acquisition_date = payload_data['dataFilter']['timeRange']['from']
|
121
|
-
else: # DEM data does not have a timeRange
|
122
|
-
data_acquisition_date = None
|
123
|
-
|
124
|
-
# Generate the metadata.json file
|
125
|
-
metadata_path = join(output_folder, f"{output_name}.json")
|
126
|
-
metadata = {
|
127
|
-
"acquisition-date": data_acquisition_date,
|
128
|
-
"bounding-box": bbox,
|
129
|
-
"type": data_type,
|
130
|
-
}
|
131
|
-
|
132
|
-
with open(metadata_path, "w") as f:
|
133
|
-
json.dump(metadata, f)
|
134
|
-
|
135
|
-
return data_type
|
@@ -1,22 +0,0 @@
|
|
1
|
-
'''
|
2
|
-
Geometry utils
|
3
|
-
'''
|
4
|
-
|
5
|
-
from pandas import isna
|
6
|
-
|
7
|
-
|
8
|
-
def convert_df_geom_to_shape(row):
|
9
|
-
"""
|
10
|
-
Convert the geometry of a dataframe row to a shapely shape
|
11
|
-
|
12
|
-
:param row: row of a dataframe
|
13
|
-
"""
|
14
|
-
from shapely.geometry import shape
|
15
|
-
|
16
|
-
if not isna(row["geometry"]):
|
17
|
-
geo = shape(row["geometry"])
|
18
|
-
wkt = geo.wkt
|
19
|
-
else:
|
20
|
-
wkt = "POLYGON EMPTY"
|
21
|
-
|
22
|
-
return wkt
|
@@ -1,143 +0,0 @@
|
|
1
|
-
'''
|
2
|
-
STAC utils
|
3
|
-
'''
|
4
|
-
|
5
|
-
import pystac
|
6
|
-
|
7
|
-
from os.path import dirname, join, abspath
|
8
|
-
from typing import Union, Optional
|
9
|
-
from tqdm import tqdm
|
10
|
-
from traceback import print_exc
|
11
|
-
from shutil import rmtree
|
12
|
-
|
13
|
-
|
14
|
-
def get_all_children(obj: pystac.STACObject) -> list:
|
15
|
-
"""
|
16
|
-
Get all the children of a STAC object
|
17
|
-
|
18
|
-
:param obj: STAC object
|
19
|
-
"""
|
20
|
-
children = []
|
21
|
-
# Append the current object to the list
|
22
|
-
children.append(obj.to_dict())
|
23
|
-
|
24
|
-
# Collections
|
25
|
-
collections = list(obj.get_collections())
|
26
|
-
|
27
|
-
for collection in collections:
|
28
|
-
children.append(collection.to_dict())
|
29
|
-
|
30
|
-
# Items
|
31
|
-
items = obj.get_items()
|
32
|
-
for item in items:
|
33
|
-
children.append(item.to_dict())
|
34
|
-
|
35
|
-
# Items from collections
|
36
|
-
for collection in collections:
|
37
|
-
items = collection.get_items()
|
38
|
-
for item in items:
|
39
|
-
children.append(item.to_dict())
|
40
|
-
|
41
|
-
return children
|
42
|
-
|
43
|
-
|
44
|
-
def make_links_relative_to_path(path: str,
|
45
|
-
catalog: Union[pystac.Catalog, str],
|
46
|
-
) -> pystac.Catalog:
|
47
|
-
"""
|
48
|
-
Makes all asset HREFs in the catalog relative to a given path
|
49
|
-
|
50
|
-
:param path: path to make the links relative
|
51
|
-
:param catalog: catalog to make the links relative
|
52
|
-
|
53
|
-
:return: catalog with the links relative
|
54
|
-
"""
|
55
|
-
if isinstance(catalog, str):
|
56
|
-
catalog = pystac.read_file(catalog)
|
57
|
-
path = abspath(path)
|
58
|
-
|
59
|
-
catalog.make_all_asset_hrefs_absolute()
|
60
|
-
|
61
|
-
for collection in catalog.get_children():
|
62
|
-
new_collection = collection.clone()
|
63
|
-
new_collection.set_self_href(join(path, collection.id, f"collection.json"))
|
64
|
-
new_collection.set_root(catalog)
|
65
|
-
new_collection.set_parent(catalog)
|
66
|
-
catalog.remove_child(collection.id)
|
67
|
-
catalog.add_child(new_collection)
|
68
|
-
for item in collection.get_all_items():
|
69
|
-
new_item = item.clone()
|
70
|
-
new_item.set_self_href(join(path, item.id, f"{item.id}.json"))
|
71
|
-
new_item.set_parent(collection)
|
72
|
-
new_item.set_root(catalog)
|
73
|
-
new_collection.add_item(new_item)
|
74
|
-
|
75
|
-
catalog.make_all_asset_hrefs_relative()
|
76
|
-
|
77
|
-
return catalog
|
78
|
-
|
79
|
-
|
80
|
-
def merge_stac_catalogs(catalog_1: Union[pystac.Catalog, str],
|
81
|
-
catalog_2: Union[pystac.Catalog, str],
|
82
|
-
destination: Optional[str] = None,
|
83
|
-
keep_extensions: Optional[bool] = False,
|
84
|
-
catalog_type: Optional[pystac.CatalogType] = pystac.CatalogType.SELF_CONTAINED
|
85
|
-
) -> None:
|
86
|
-
"""
|
87
|
-
Merge two STAC catalogs, keeping the properties, collection and items of both catalogs
|
88
|
-
|
89
|
-
:param catalog_1: first catalog to merge
|
90
|
-
:param catalog_2: second catalog to merge
|
91
|
-
:param destination: destination folder to save the merged catalog
|
92
|
-
:param keep_extensions: keep the extensions of the first catalog
|
93
|
-
:param catalog_type: type of the catalog
|
94
|
-
"""
|
95
|
-
if isinstance(catalog_1, str):
|
96
|
-
catalog_1 = pystac.Catalog.from_file(catalog_1)
|
97
|
-
if isinstance(catalog_2, str):
|
98
|
-
catalog_2 = pystac.Catalog.from_file(catalog_2)
|
99
|
-
|
100
|
-
for col1 in tqdm(catalog_1.get_children(), desc='Merging catalogs...'):
|
101
|
-
# Check if the collection exists in catalog_2
|
102
|
-
col2 = catalog_2.get_child(col1.id)
|
103
|
-
if col2 is None:
|
104
|
-
# If it does not exist, add it
|
105
|
-
col1_ = col1.clone()
|
106
|
-
catalog_2.add_child(col1)
|
107
|
-
col2 = catalog_2.get_child(col1.id)
|
108
|
-
col2.clear_items()
|
109
|
-
for i in col1_.get_stac_objects(pystac.RelType.ITEM):
|
110
|
-
col2.add_item(i)
|
111
|
-
else:
|
112
|
-
# If it exists, merge the items
|
113
|
-
for item1 in col1.get_items():
|
114
|
-
if col2.get_item(item1.id) is None:
|
115
|
-
col2.add_item(item1)
|
116
|
-
|
117
|
-
if keep_extensions:
|
118
|
-
for ext in catalog_1.stac_extensions:
|
119
|
-
if ext not in catalog_2.stac_extensions:
|
120
|
-
catalog_2.stac_extensions.append(ext)
|
121
|
-
|
122
|
-
for extra_field_name, extra_field_value in catalog_1.extra_fields.items():
|
123
|
-
if extra_field_name not in catalog_2.extra_fields:
|
124
|
-
catalog_2.extra_fields[extra_field_name] = extra_field_value
|
125
|
-
|
126
|
-
if destination:
|
127
|
-
# TODO test
|
128
|
-
make_links_relative_to_path(destination, catalog_2)
|
129
|
-
else:
|
130
|
-
destination = dirname(catalog_2.get_self_href())
|
131
|
-
|
132
|
-
# Save the merged catalog
|
133
|
-
try:
|
134
|
-
print("Validating and saving...")
|
135
|
-
catalog_2.validate()
|
136
|
-
rmtree(destination) if not destination else None # Remove the old catalog and replace it with the new one
|
137
|
-
catalog_2.normalize_and_save(root_href=destination,
|
138
|
-
catalog_type=catalog_type
|
139
|
-
)
|
140
|
-
print("Success!")
|
141
|
-
except pystac.STACValidationError:
|
142
|
-
# Return full callback
|
143
|
-
print_exc()
|
@@ -1,21 +0,0 @@
|
|
1
|
-
'''
|
2
|
-
Time utils
|
3
|
-
'''
|
4
|
-
|
5
|
-
from typing import Union
|
6
|
-
from datetime import datetime
|
7
|
-
from dateutil import parser
|
8
|
-
|
9
|
-
|
10
|
-
def format_time_acquired(dt: Union[str, datetime]) -> str:
|
11
|
-
"""
|
12
|
-
Format the date time to the required format for STAC
|
13
|
-
|
14
|
-
:param dt: date time to format
|
15
|
-
"""
|
16
|
-
dt_str = parser.parse(dt).strftime("%Y-%m-%dT%H:%M:%S.%f")
|
17
|
-
|
18
|
-
# convert the string to datetime object
|
19
|
-
dt_obj = datetime.strptime(dt_str, "%Y-%m-%dT%H:%M:%S.%f")
|
20
|
-
|
21
|
-
return dt_obj
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|