eotdl 2025.2.10__py3-none-any.whl → 2025.4.2__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/access/__init__.py +13 -3
- eotdl/access/download.py +47 -14
- eotdl/access/search.py +33 -5
- eotdl/access/sentinelhub/__init__.py +6 -2
- eotdl/access/sentinelhub/client.py +7 -6
- eotdl/access/sentinelhub/evalscripts.py +266 -0
- eotdl/access/sentinelhub/parameters.py +101 -23
- eotdl/access/sentinelhub/utils.py +54 -15
- eotdl/cli.py +2 -2
- eotdl/commands/datasets.py +28 -31
- eotdl/commands/models.py +27 -30
- eotdl/commands/stac.py +57 -0
- eotdl/curation/__init__.py +0 -8
- eotdl/curation/stac/__init__.py +1 -8
- eotdl/curation/stac/api.py +58 -0
- eotdl/curation/stac/stac.py +31 -341
- eotdl/datasets/__init__.py +2 -2
- eotdl/datasets/ingest.py +36 -161
- eotdl/datasets/retrieve.py +0 -9
- eotdl/datasets/stage.py +64 -0
- eotdl/files/__init__.py +0 -2
- eotdl/files/ingest.bck +178 -0
- eotdl/files/ingest.py +237 -166
- eotdl/{datasets → files}/metadata.py +16 -17
- eotdl/models/__init__.py +1 -1
- eotdl/models/ingest.py +35 -158
- eotdl/models/stage.py +63 -0
- eotdl/repos/APIRepo.py +1 -1
- eotdl/repos/DatasetsAPIRepo.py +56 -43
- eotdl/repos/FilesAPIRepo.py +260 -167
- eotdl/repos/ModelsAPIRepo.py +50 -42
- eotdl/repos/STACAPIRepo.py +40 -0
- eotdl/repos/__init__.py +1 -0
- eotdl/tools/time_utils.py +3 -3
- {eotdl-2025.2.10.dist-info → eotdl-2025.4.2.dist-info}/METADATA +1 -1
- eotdl-2025.4.2.dist-info/RECORD +66 -0
- eotdl/curation/stac/assets.py +0 -110
- eotdl/curation/stac/dataframe.py +0 -172
- eotdl/curation/stac/dataframe_bck.py +0 -253
- eotdl/curation/stac/dataframe_labeling.py +0 -63
- eotdl/curation/stac/extensions/__init__.py +0 -23
- eotdl/curation/stac/extensions/base.py +0 -30
- eotdl/curation/stac/extensions/dem.py +0 -18
- eotdl/curation/stac/extensions/eo.py +0 -117
- eotdl/curation/stac/extensions/label/__init__.py +0 -7
- eotdl/curation/stac/extensions/label/base.py +0 -136
- eotdl/curation/stac/extensions/label/image_name_labeler.py +0 -203
- eotdl/curation/stac/extensions/label/scaneo.py +0 -219
- eotdl/curation/stac/extensions/ml_dataset.py +0 -648
- eotdl/curation/stac/extensions/projection.py +0 -44
- eotdl/curation/stac/extensions/raster.py +0 -53
- eotdl/curation/stac/extensions/sar.py +0 -55
- eotdl/curation/stac/extent.py +0 -158
- eotdl/curation/stac/parsers.py +0 -61
- eotdl/datasets/download.py +0 -104
- eotdl/files/list_files.py +0 -13
- eotdl/models/metadata.py +0 -43
- eotdl-2025.2.10.dist-info/RECORD +0 -81
- {eotdl-2025.2.10.dist-info → eotdl-2025.4.2.dist-info}/WHEEL +0 -0
- {eotdl-2025.2.10.dist-info → eotdl-2025.4.2.dist-info}/entry_points.txt +0 -0
eotdl/repos/FilesAPIRepo.py
CHANGED
@@ -11,190 +11,283 @@ class FilesAPIRepo(APIRepo):
|
|
11
11
|
def __init__(self, url=None):
|
12
12
|
super().__init__(url)
|
13
13
|
|
14
|
-
def ingest_files_batch(
|
15
|
-
self,
|
16
|
-
batch, # ziped batch of files
|
17
|
-
checksums,
|
18
|
-
dataset_or_model_id,
|
19
|
-
user,
|
20
|
-
endpoint,
|
21
|
-
version=None,
|
22
|
-
):
|
23
|
-
url = self.url + f"{endpoint}/{dataset_or_model_id}/batch"
|
24
|
-
if version is not None:
|
25
|
-
url += "?version=" + str(version)
|
26
|
-
reponse = requests.post(
|
27
|
-
url,
|
28
|
-
files={"batch": ("batch.zip", batch)},
|
29
|
-
data={"checksums": checksums},
|
30
|
-
headers=self.generate_headers(user),
|
31
|
-
)
|
32
|
-
return self.format_response(reponse)
|
33
|
-
|
34
|
-
def add_files_batch_to_version(
|
35
|
-
self,
|
36
|
-
batch,
|
37
|
-
dataset_or_model_id,
|
38
|
-
version,
|
39
|
-
user,
|
40
|
-
endpoint,
|
41
|
-
):
|
42
|
-
reponse = requests.post(
|
43
|
-
self.url + f"{endpoint}/{dataset_or_model_id}/files?version={str(version)}",
|
44
|
-
data={
|
45
|
-
"filenames": [f["path"] for f in batch],
|
46
|
-
"checksums": [f["checksum"] for f in batch],
|
47
|
-
},
|
48
|
-
headers=self.generate_headers(user),
|
49
|
-
)
|
50
|
-
return self.format_response(reponse)
|
51
|
-
|
52
14
|
def ingest_file(
|
53
|
-
self,
|
15
|
+
self, file_path_or_bytes, file_name, dataset_or_model_id, user, endpoint, version=None
|
54
16
|
):
|
55
|
-
# TODO: ingest file URL
|
56
17
|
url = self.url + f"{endpoint}/{dataset_or_model_id}"
|
57
18
|
if version is not None:
|
58
19
|
url += "?version=" + str(version)
|
20
|
+
# get a presigned url to upload the file directly to the bucket
|
59
21
|
reponse = requests.post(
|
60
22
|
url,
|
61
|
-
|
62
|
-
|
23
|
+
json={
|
24
|
+
"file_name": file_name,
|
25
|
+
# "file_size": files_size,
|
26
|
+
# "checksum": checksum
|
27
|
+
},
|
63
28
|
headers=self.generate_headers(user),
|
64
29
|
)
|
65
|
-
|
30
|
+
data, error = self.format_response(reponse)
|
31
|
+
if error:
|
32
|
+
raise Exception(error)
|
33
|
+
# ingest the file
|
34
|
+
error = None
|
35
|
+
try:
|
36
|
+
presigned_url = data["presigned_url"]
|
37
|
+
if isinstance(file_path_or_bytes, (str, bytes)):
|
38
|
+
if isinstance(file_path_or_bytes, str):
|
39
|
+
# Handle file path
|
40
|
+
with open(file_path_or_bytes, 'rb') as f:
|
41
|
+
file_data = f.read()
|
42
|
+
else:
|
43
|
+
# Handle bytes directly
|
44
|
+
file_data = file_path_or_bytes
|
45
|
+
# Send file data to presigned URL
|
46
|
+
response = requests.put(presigned_url, data=file_data)
|
47
|
+
response.raise_for_status()
|
48
|
+
else:
|
49
|
+
raise TypeError("file_path_or_bytes must be either a file path string or bytes")
|
50
|
+
except Exception as e:
|
51
|
+
error = str(e)
|
52
|
+
return data, error
|
66
53
|
|
67
|
-
def
|
68
|
-
url = f"{self.url}{endpoint}/{dataset_or_model_id}/files"
|
69
|
-
if version is not None:
|
70
|
-
url += "?version=" + str(version)
|
71
|
-
response = requests.get(url)
|
72
|
-
return self.format_response(response)
|
73
|
-
|
74
|
-
def download_file(
|
54
|
+
def stage_file(
|
75
55
|
self,
|
76
56
|
dataset_or_model_id,
|
77
57
|
file_name,
|
78
58
|
user,
|
79
59
|
path,
|
80
|
-
file_version,
|
81
60
|
endpoint="datasets",
|
82
61
|
progress=False,
|
83
62
|
):
|
84
|
-
url = self.url + f"{endpoint}/{dataset_or_model_id}/
|
85
|
-
if file_version is not None:
|
86
|
-
|
87
|
-
return self.
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
with requests.get(url, headers=headers, stream=True) as r:
|
96
|
-
r.raise_for_status()
|
97
|
-
total_size = int(r.headers.get("content-length", 0))
|
98
|
-
block_size = 1024 * 1024 * 10
|
99
|
-
progress = progress and total_size > 1024 * 1024 * 16
|
100
|
-
if progress:
|
101
|
-
progress_bar = tqdm(
|
102
|
-
total=total_size,
|
103
|
-
unit="iB",
|
104
|
-
unit_scale=True,
|
105
|
-
unit_divisor=1024,
|
106
|
-
position=1,
|
107
|
-
)
|
108
|
-
with open(path, "wb") as f:
|
109
|
-
for chunk in r.iter_content(block_size):
|
110
|
-
if progress:
|
111
|
-
progress_bar.update(len(chunk))
|
112
|
-
if chunk:
|
113
|
-
f.write(chunk)
|
114
|
-
if progress:
|
115
|
-
progress_bar.close()
|
116
|
-
return path
|
117
|
-
|
118
|
-
def prepare_large_upload(
|
119
|
-
self, filename, dataset_or_model_id, checksum, user, endpoint
|
120
|
-
):
|
121
|
-
response = requests.post(
|
122
|
-
self.url + f"{endpoint}/{dataset_or_model_id}/uploadId",
|
123
|
-
json={"filname": filename, "checksum": checksum},
|
124
|
-
headers=self.generate_headers(user),
|
125
|
-
)
|
126
|
-
if response.status_code != 200:
|
127
|
-
raise Exception(response.json()["detail"])
|
128
|
-
data = response.json()
|
129
|
-
upload_id, parts = (
|
130
|
-
data["upload_id"],
|
131
|
-
data["parts"] if "parts" in data else [],
|
132
|
-
)
|
133
|
-
return upload_id, parts
|
134
|
-
|
135
|
-
def get_chunk_size(self, content_size):
|
136
|
-
# adapt chunk size to content size to avoid S3 limits (10000 parts, 500MB per part, 5TB per object)
|
137
|
-
chunk_size = 1024 * 1024 * 10 # 10 MB (up to 100 GB, 10000 parts)
|
138
|
-
if content_size >= 1024 * 1024 * 1024 * 100: # 100 GB
|
139
|
-
chunk_size = 1024 * 1024 * 100 # 100 MB (up to 1 TB, 10000 parts)
|
140
|
-
elif content_size >= 1024 * 1024 * 1024 * 1000: # 1 TB
|
141
|
-
chunk_size = 1024 * 1024 * 500 # 0.5 GB (up to 5 TB, 10000 parts)
|
142
|
-
return chunk_size
|
143
|
-
|
144
|
-
def read_in_chunks(self, file_object, CHUNK_SIZE):
|
145
|
-
while True:
|
146
|
-
data = file_object.read(CHUNK_SIZE)
|
147
|
-
if not data:
|
148
|
-
break
|
149
|
-
yield data
|
150
|
-
|
151
|
-
def ingest_large_file(
|
152
|
-
self, file_path, files_size, upload_id, user, parts, endpoint
|
63
|
+
url = self.url + f"{endpoint}/{dataset_or_model_id}/stage/{file_name}"
|
64
|
+
# if file_version is not None:
|
65
|
+
# url += "?version=" + str(file_version)
|
66
|
+
return self.stage_file_url(url, path, user)
|
67
|
+
|
68
|
+
|
69
|
+
def stage_file_url(
|
70
|
+
self,
|
71
|
+
url,
|
72
|
+
path,
|
73
|
+
user,
|
153
74
|
):
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
for
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
response
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
if response.status_code != 200:
|
178
|
-
raise Exception(response.json()["detail"])
|
179
|
-
pbar.set_description(
|
180
|
-
"{:.2f}/{:.2f} MB".format(
|
181
|
-
offset / 1024 / 1024, files_size / 1024 / 1024
|
182
|
-
)
|
183
|
-
)
|
184
|
-
pbar.close()
|
185
|
-
return
|
186
|
-
|
187
|
-
def complete_upload(self, user, upload_id, version, endpoint):
|
188
|
-
r = requests.post(
|
189
|
-
f"{self.url}{endpoint}/complete/{upload_id}?version={version}",
|
190
|
-
headers=self.generate_headers(user),
|
191
|
-
)
|
192
|
-
return self.format_response(r)
|
75
|
+
if '/stage/' in url: # asset is in EOTDL (can do better...)
|
76
|
+
file_name = url.split("/stage/")[-1]
|
77
|
+
reponse = requests.get(url, headers=self.generate_headers(user))
|
78
|
+
data, error = self.format_response(reponse)
|
79
|
+
if error:
|
80
|
+
raise Exception(error)
|
81
|
+
presigned_url = data["presigned_url"]
|
82
|
+
else:
|
83
|
+
file_name = url.split("//")[-1]
|
84
|
+
presigned_url = url
|
85
|
+
file_path = f"{path}/{file_name}"
|
86
|
+
for i in range(1, len(file_path.split("/")) - 1):
|
87
|
+
os.makedirs("/".join(file_path.split("/")[: i + 1]), exist_ok=True)
|
88
|
+
try:
|
89
|
+
response = requests.get(presigned_url)
|
90
|
+
response.raise_for_status() # This will raise an HTTPError for 4XX and 5XX status codes
|
91
|
+
with open(file_path, 'wb') as f:
|
92
|
+
f.write(response.content)
|
93
|
+
except requests.exceptions.HTTPError as e:
|
94
|
+
raise Exception(f"Failed to stage file: {str(e)}")
|
95
|
+
except Exception as e:
|
96
|
+
raise Exception(f"Unexpected error while staging file: {str(e)}")
|
97
|
+
return file_path
|
193
98
|
|
194
|
-
def
|
195
|
-
url = self.url
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
99
|
+
def generate_presigned_url(self, filename, dataset_or_model_id, user, endpoint="datasets"):
|
100
|
+
url = f"{self.url}{endpoint}/{dataset_or_model_id}/stage/{filename}"
|
101
|
+
reponse = requests.get(url, headers=self.generate_headers(user))
|
102
|
+
data, error = self.format_response(reponse)
|
103
|
+
if error:
|
104
|
+
# print("ERROR generate_presigned_url", error)
|
105
|
+
return None
|
106
|
+
return data["presigned_url"]
|
107
|
+
|
108
|
+
# can we download large files?
|
109
|
+
|
110
|
+
# with requests.get(presigned_url, headers=headers, stream=True) as r:
|
111
|
+
# r.raise_for_status()
|
112
|
+
# total_size = int(r.headers.get("content-length", 0))
|
113
|
+
# block_size = 1024 * 1024 * 10
|
114
|
+
# progress = progress and total_size > 1024 * 1024 * 16
|
115
|
+
# if progress:
|
116
|
+
# progress_bar = tqdm(
|
117
|
+
# total=total_size,
|
118
|
+
# unit="iB",
|
119
|
+
# unit_scale=True,
|
120
|
+
# unit_divisor=1024,
|
121
|
+
# position=1,
|
122
|
+
# )
|
123
|
+
# with open(path, "wb") as f:
|
124
|
+
# for chunk in r.iter_content(block_size):
|
125
|
+
# if progress:
|
126
|
+
# progress_bar.update(len(chunk))
|
127
|
+
# if chunk:
|
128
|
+
# f.write(chunk)
|
129
|
+
# if progress:
|
130
|
+
# progress_bar.close()
|
131
|
+
# return path
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
# def ingest_files_batch(
|
136
|
+
# self,
|
137
|
+
# batch, # ziped batch of files
|
138
|
+
# checksums,
|
139
|
+
# dataset_or_model_id,
|
140
|
+
# user,
|
141
|
+
# endpoint,
|
142
|
+
# version=None,
|
143
|
+
# ):
|
144
|
+
# url = self.url + f"{endpoint}/{dataset_or_model_id}/batch"
|
145
|
+
# if version is not None:
|
146
|
+
# url += "?version=" + str(version)
|
147
|
+
# reponse = requests.post(
|
148
|
+
# url,
|
149
|
+
# files={"batch": ("batch.zip", batch)},
|
150
|
+
# data={"checksums": checksums},
|
151
|
+
# headers=self.generate_headers(user),
|
152
|
+
# )
|
153
|
+
# return self.format_response(reponse)
|
154
|
+
|
155
|
+
# def add_files_batch_to_version(
|
156
|
+
# self,
|
157
|
+
# batch,
|
158
|
+
# dataset_or_model_id,
|
159
|
+
# version,
|
160
|
+
# user,
|
161
|
+
# endpoint,
|
162
|
+
# ):
|
163
|
+
# reponse = requests.post(
|
164
|
+
# self.url + f"{endpoint}/{dataset_or_model_id}/files?version={str(version)}",
|
165
|
+
# data={
|
166
|
+
# "filenames": [f["path"] for f in batch],
|
167
|
+
# "checksums": [f["checksum"] for f in batch],
|
168
|
+
# },
|
169
|
+
# headers=self.generate_headers(user),
|
170
|
+
# )
|
171
|
+
# return self.format_response(reponse)
|
172
|
+
|
173
|
+
# def retrieve_files(self, dataset_or_model_id, endpoint, version=None):
|
174
|
+
# url = f"{self.url}{endpoint}/{dataset_or_model_id}/files"
|
175
|
+
# if version is not None:
|
176
|
+
# url += "?version=" + str(version)
|
177
|
+
# response = requests.get(url)
|
178
|
+
# return self.format_response(response)
|
179
|
+
|
180
|
+
|
181
|
+
|
182
|
+
# def download_file_url(self, url, filename, path, user, progress=False):
|
183
|
+
# headers = self.generate_headers(user)
|
184
|
+
# path = f"{path}/{filename}"
|
185
|
+
# for i in range(1, len(path.split("/")) - 1):
|
186
|
+
# # print("/".join(path.split("/")[: i + 1]))
|
187
|
+
# os.makedirs("/".join(path.split("/")[: i + 1]), exist_ok=True)
|
188
|
+
# with requests.get(url, headers=headers, stream=True) as r:
|
189
|
+
# r.raise_for_status()
|
190
|
+
# total_size = int(r.headers.get("content-length", 0))
|
191
|
+
# block_size = 1024 * 1024 * 10
|
192
|
+
# progress = progress and total_size > 1024 * 1024 * 16
|
193
|
+
# if progress:
|
194
|
+
# progress_bar = tqdm(
|
195
|
+
# total=total_size,
|
196
|
+
# unit="iB",
|
197
|
+
# unit_scale=True,
|
198
|
+
# unit_divisor=1024,
|
199
|
+
# position=1,
|
200
|
+
# )
|
201
|
+
# with open(path, "wb") as f:
|
202
|
+
# for chunk in r.iter_content(block_size):
|
203
|
+
# if progress:
|
204
|
+
# progress_bar.update(len(chunk))
|
205
|
+
# if chunk:
|
206
|
+
# f.write(chunk)
|
207
|
+
# if progress:
|
208
|
+
# progress_bar.close()
|
209
|
+
# return path
|
210
|
+
|
211
|
+
# def prepare_large_upload(
|
212
|
+
# self, filename, dataset_or_model_id, checksum, user, endpoint
|
213
|
+
# ):
|
214
|
+
# response = requests.post(
|
215
|
+
# self.url + f"{endpoint}/{dataset_or_model_id}/uploadId",
|
216
|
+
# json={"filname": filename, "checksum": checksum},
|
217
|
+
# headers=self.generate_headers(user),
|
218
|
+
# )
|
219
|
+
# if response.status_code != 200:
|
220
|
+
# raise Exception(response.json()["detail"])
|
221
|
+
# data = response.json()
|
222
|
+
# upload_id, parts = (
|
223
|
+
# data["upload_id"],
|
224
|
+
# data["parts"] if "parts" in data else [],
|
225
|
+
# )
|
226
|
+
# return upload_id, parts
|
227
|
+
|
228
|
+
# def get_chunk_size(self, content_size):
|
229
|
+
# # adapt chunk size to content size to avoid S3 limits (10000 parts, 500MB per part, 5TB per object)
|
230
|
+
# chunk_size = 1024 * 1024 * 10 # 10 MB (up to 100 GB, 10000 parts)
|
231
|
+
# if content_size >= 1024 * 1024 * 1024 * 100: # 100 GB
|
232
|
+
# chunk_size = 1024 * 1024 * 100 # 100 MB (up to 1 TB, 10000 parts)
|
233
|
+
# elif content_size >= 1024 * 1024 * 1024 * 1000: # 1 TB
|
234
|
+
# chunk_size = 1024 * 1024 * 500 # 0.5 GB (up to 5 TB, 10000 parts)
|
235
|
+
# return chunk_size
|
236
|
+
|
237
|
+
# def read_in_chunks(self, file_object, CHUNK_SIZE):
|
238
|
+
# while True:
|
239
|
+
# data = file_object.read(CHUNK_SIZE)
|
240
|
+
# if not data:
|
241
|
+
# break
|
242
|
+
# yield data
|
243
|
+
|
244
|
+
# def ingest_large_file(
|
245
|
+
# self, file_path, files_size, upload_id, user, parts, endpoint
|
246
|
+
# ):
|
247
|
+
# print(endpoint)
|
248
|
+
# # content_path = os.path.abspath(file)
|
249
|
+
# # content_size = os.stat(content_path).st_size
|
250
|
+
# chunk_size = self.get_chunk_size(files_size)
|
251
|
+
# total_chunks = files_size // chunk_size
|
252
|
+
# # upload chunks sequentially
|
253
|
+
# pbar = tqdm(
|
254
|
+
# self.read_in_chunks(open(file_path, "rb"), chunk_size),
|
255
|
+
# total=total_chunks,
|
256
|
+
# )
|
257
|
+
# index = 0
|
258
|
+
# for chunk in pbar:
|
259
|
+
# part = index // chunk_size + 1
|
260
|
+
# offset = index + len(chunk)
|
261
|
+
# index = offset
|
262
|
+
# if part not in parts:
|
263
|
+
# checksum = hashlib.md5(chunk).hexdigest()
|
264
|
+
# response = requests.post(
|
265
|
+
# f"{self.url}{endpoint}/chunk/{upload_id}",
|
266
|
+
# files={"file": chunk},
|
267
|
+
# data={"part_number": part, "checksum": checksum},
|
268
|
+
# headers=self.generate_headers(user),
|
269
|
+
# )
|
270
|
+
# if response.status_code != 200:
|
271
|
+
# raise Exception(response.json()["detail"])
|
272
|
+
# pbar.set_description(
|
273
|
+
# "{:.2f}/{:.2f} MB".format(
|
274
|
+
# offset / 1024 / 1024, files_size / 1024 / 1024
|
275
|
+
# )
|
276
|
+
# )
|
277
|
+
# pbar.close()
|
278
|
+
# return
|
279
|
+
|
280
|
+
# def complete_upload(self, user, upload_id, version, endpoint):
|
281
|
+
# r = requests.post(
|
282
|
+
# f"{self.url}{endpoint}/complete/{upload_id}?version={version}",
|
283
|
+
# headers=self.generate_headers(user),
|
284
|
+
# )
|
285
|
+
# return self.format_response(r)
|
286
|
+
|
287
|
+
# def get_file_stream(self, dataset_id, filename, user, version=None):
|
288
|
+
# url = self.url + f"datasets/{dataset_id}/download/{filename}"
|
289
|
+
# if version is not None:
|
290
|
+
# url += "?version=" + str(version)
|
291
|
+
# headers = self.generate_headers(user)
|
292
|
+
# response = requests.get(url, headers=headers, stream=True)
|
293
|
+
# return BytesIO(response.content)
|
eotdl/repos/ModelsAPIRepo.py
CHANGED
@@ -20,6 +20,10 @@ class ModelsAPIRepo(APIRepo):
|
|
20
20
|
response = requests.get(url)
|
21
21
|
return self.format_response(response)
|
22
22
|
|
23
|
+
def retrieve_model(self, name):
|
24
|
+
response = requests.get(self.url + "models?name=" + name)
|
25
|
+
return self.format_response(response)
|
26
|
+
|
23
27
|
def create_model(self, metadata, user):
|
24
28
|
response = requests.post(
|
25
29
|
self.url + "models",
|
@@ -28,53 +32,57 @@ class ModelsAPIRepo(APIRepo):
|
|
28
32
|
)
|
29
33
|
return self.format_response(response)
|
30
34
|
|
31
|
-
def
|
32
|
-
response = requests.get(self.url + "models?name=" + name)
|
33
|
-
return self.format_response(response)
|
34
|
-
|
35
|
-
def create_version(self, model_id, user):
|
35
|
+
def complete_ingestion(self, model_id, version, size, user):
|
36
36
|
response = requests.post(
|
37
|
-
self.url + "models/
|
37
|
+
self.url + "models/complete/" + model_id,
|
38
|
+
json={"version": version, "size": size},
|
38
39
|
headers=self.generate_headers(user),
|
39
40
|
)
|
40
41
|
return self.format_response(response)
|
41
42
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
"authors": authors,
|
49
|
-
"source": source,
|
50
|
-
"license": license,
|
51
|
-
"thumbnail": thumbnail,
|
52
|
-
"description": content,
|
53
|
-
},
|
54
|
-
headers=self.generate_headers(user),
|
55
|
-
)
|
56
|
-
return self.format_response(response)
|
43
|
+
# def create_version(self, model_id, user):
|
44
|
+
# response = requests.post(
|
45
|
+
# self.url + "models/version/" + model_id,
|
46
|
+
# headers=self.generate_headers(user),
|
47
|
+
# )
|
48
|
+
# return self.format_response(response)
|
57
49
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
50
|
+
# def update_model(
|
51
|
+
# self, model_id, authors, source, license, thumbnail, content, user
|
52
|
+
# ):
|
53
|
+
# response = requests.put(
|
54
|
+
# self.url + f"models/{model_id}",
|
55
|
+
# json={
|
56
|
+
# "authors": authors,
|
57
|
+
# "source": source,
|
58
|
+
# "license": license,
|
59
|
+
# "thumbnail": thumbnail,
|
60
|
+
# "description": content,
|
61
|
+
# },
|
62
|
+
# headers=self.generate_headers(user),
|
63
|
+
# )
|
64
|
+
# return self.format_response(response)
|
65
65
|
|
66
|
-
def
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
66
|
+
# def create_stac_model(self, name, user):
|
67
|
+
# response = requests.post(
|
68
|
+
# self.url + "models/stac",
|
69
|
+
# json={"name": name},
|
70
|
+
# headers=self.generate_headers(user),
|
71
|
+
# )
|
72
|
+
# return self.format_response(response)
|
73
|
+
|
74
|
+
# def ingest_stac(self, stac_json, model_id, user):
|
75
|
+
# response = requests.put(
|
76
|
+
# self.url + f"models/stac/{model_id}",
|
77
|
+
# json={"stac": stac_json},
|
78
|
+
# headers=self.generate_headers(user),
|
79
|
+
# )
|
80
|
+
# return self.format_response(response)
|
73
81
|
|
74
|
-
def download_stac(self, model_id, user):
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
82
|
+
# def download_stac(self, model_id, user):
|
83
|
+
# url = self.url + "models/" + model_id + "/download"
|
84
|
+
# headers = self.generate_headers(user)
|
85
|
+
# response = requests.get(url, headers=headers)
|
86
|
+
# if response.status_code != 200:
|
87
|
+
# return None, response.json()["detail"]
|
88
|
+
# return gpd.GeoDataFrame.from_features(response.json()["features"]), None
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import requests
|
2
|
+
import geopandas as gpd
|
3
|
+
|
4
|
+
from ..repos import APIRepo
|
5
|
+
|
6
|
+
|
7
|
+
class STACAPIRepo(APIRepo):
|
8
|
+
def __init__(self, url=None):
|
9
|
+
super().__init__(url)
|
10
|
+
|
11
|
+
def status(self):
|
12
|
+
response = requests.get(self.url + "stac")
|
13
|
+
return self.format_response(response)
|
14
|
+
|
15
|
+
def collections(self):
|
16
|
+
response = requests.get(self.url + "stac/collections")
|
17
|
+
return self.format_response(response)
|
18
|
+
|
19
|
+
def collection(self, collection_id):
|
20
|
+
response = requests.get(self.url + f"stac/collections/{collection_id}")
|
21
|
+
return self.format_response(response)
|
22
|
+
|
23
|
+
def items(self, collection_id):
|
24
|
+
response = requests.get(self.url + f"stac/collections/{collection_id}/items")
|
25
|
+
return self.format_response(response)
|
26
|
+
|
27
|
+
def item(self, collection_id, item_id):
|
28
|
+
response = requests.get(self.url + f"stac/collections/{collection_id}/items/{item_id}")
|
29
|
+
return self.format_response(response)
|
30
|
+
|
31
|
+
def search(self, collection_id, query):
|
32
|
+
body = {"collection_id": collection_id}
|
33
|
+
if query is not None:
|
34
|
+
body["query"] = query
|
35
|
+
response = requests.post(self.url + f"stac/search", json=body)
|
36
|
+
return self.format_response(response)
|
37
|
+
|
38
|
+
def search_columns(self, collection_id):
|
39
|
+
response = requests.get(self.url + f"stac/search?collection={collection_id}")
|
40
|
+
return self.format_response(response)
|
eotdl/repos/__init__.py
CHANGED
eotdl/tools/time_utils.py
CHANGED
@@ -131,11 +131,11 @@ def get_day_between(
|
|
131
131
|
Get the day between two dates
|
132
132
|
"""
|
133
133
|
if isinstance(from_date, str):
|
134
|
-
from_date =
|
134
|
+
from_date = format_time_acquired(from_date)
|
135
135
|
if isinstance(to_date, str):
|
136
|
-
to_date =
|
136
|
+
to_date = format_time_acquired(to_date)
|
137
137
|
|
138
|
-
date_between = from_date +
|
138
|
+
date_between = from_date + (to_date - from_date) / 2
|
139
139
|
date_between = date_between.strftime("%Y-%m-%d")
|
140
140
|
|
141
141
|
return date_between
|