eotdl 2023.11.2.post5__py3-none-any.whl → 2023.11.3.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/access/__init__.py +6 -3
- eotdl/access/airbus/__init__.py +5 -1
- eotdl/access/airbus/client.py +356 -338
- eotdl/access/airbus/parameters.py +19 -4
- eotdl/access/airbus/utils.py +26 -21
- eotdl/access/download.py +30 -14
- eotdl/access/search.py +17 -6
- eotdl/access/sentinelhub/__init__.py +5 -1
- eotdl/access/sentinelhub/client.py +57 -54
- eotdl/access/sentinelhub/evalscripts.py +38 -39
- eotdl/access/sentinelhub/parameters.py +43 -23
- eotdl/access/sentinelhub/utils.py +38 -28
- eotdl/auth/errors.py +2 -1
- eotdl/commands/auth.py +3 -3
- eotdl/curation/__init__.py +5 -1
- eotdl/curation/stac/__init__.py +5 -1
- eotdl/curation/stac/assets.py +55 -32
- eotdl/curation/stac/dataframe.py +20 -14
- eotdl/curation/stac/dataframe_bck.py +2 -2
- eotdl/curation/stac/dataframe_labeling.py +15 -12
- eotdl/curation/stac/extensions/__init__.py +6 -2
- eotdl/curation/stac/extensions/base.py +8 -4
- eotdl/curation/stac/extensions/dem.py +6 -3
- eotdl/curation/stac/extensions/eo.py +10 -6
- eotdl/curation/stac/extensions/label/__init__.py +5 -1
- eotdl/curation/stac/extensions/label/base.py +40 -26
- eotdl/curation/stac/extensions/label/image_name_labeler.py +64 -43
- eotdl/curation/stac/extensions/label/scaneo.py +59 -56
- eotdl/curation/stac/extensions/ml_dataset.py +154 -56
- eotdl/curation/stac/extensions/projection.py +11 -9
- eotdl/curation/stac/extensions/raster.py +22 -14
- eotdl/curation/stac/extensions/sar.py +12 -7
- eotdl/curation/stac/extent.py +67 -40
- eotdl/curation/stac/parsers.py +18 -10
- eotdl/curation/stac/stac.py +81 -62
- eotdl/datasets/__init__.py +1 -1
- eotdl/datasets/download.py +42 -55
- eotdl/datasets/ingest.py +68 -11
- eotdl/files/__init__.py +1 -1
- eotdl/files/ingest.py +3 -1
- eotdl/models/download.py +1 -1
- eotdl/repos/AuthAPIRepo.py +0 -1
- eotdl/repos/DatasetsAPIRepo.py +22 -146
- eotdl/repos/FilesAPIRepo.py +7 -92
- eotdl/repos/ModelsAPIRepo.py +0 -1
- eotdl/tools/__init__.py +5 -1
- eotdl/tools/geo_utils.py +78 -48
- eotdl/tools/metadata.py +13 -11
- eotdl/tools/paths.py +14 -14
- eotdl/tools/stac.py +36 -31
- eotdl/tools/time_utils.py +53 -26
- eotdl/tools/tools.py +84 -50
- {eotdl-2023.11.2.post5.dist-info → eotdl-2023.11.3.post2.dist-info}/METADATA +5 -3
- eotdl-2023.11.3.post2.dist-info/RECORD +84 -0
- eotdl-2023.11.2.post5.dist-info/RECORD +0 -84
- {eotdl-2023.11.2.post5.dist-info → eotdl-2023.11.3.post2.dist-info}/WHEEL +0 -0
- {eotdl-2023.11.2.post5.dist-info → eotdl-2023.11.3.post2.dist-info}/entry_points.txt +0 -0
@@ -15,35 +15,44 @@ from ...tools.geo_utils import is_bounding_box, get_image_bbox
|
|
15
15
|
from ...tools.time_utils import is_time_interval, get_day_between
|
16
16
|
|
17
17
|
|
18
|
-
def evaluate_sentinel_parameters(
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
def evaluate_sentinel_parameters(
|
19
|
+
sensor: str,
|
20
|
+
time_interval: Union[str, datetime],
|
21
|
+
bounding_box: list,
|
22
|
+
output: Optional[str] = None,
|
23
|
+
output_needed: Optional[bool] = True,
|
24
|
+
) -> None:
|
24
25
|
"""
|
26
|
+
Evaluate parameters for Sentinel Hub access
|
25
27
|
"""
|
26
28
|
if output_needed:
|
27
29
|
if not output:
|
28
30
|
raise ValueError("Output path must be specified.")
|
29
31
|
if sensor not in SUPPORTED_SENSORS:
|
30
|
-
raise ValueError(
|
32
|
+
raise ValueError(
|
33
|
+
f"Sensor {sensor} is not supported. Supported sensors are: {SUPPORTED_SENSORS}"
|
34
|
+
)
|
31
35
|
if not time_interval:
|
32
36
|
raise ValueError("Time interval must be specified.")
|
33
37
|
else:
|
34
38
|
if len(time_interval) == 2 and not is_time_interval(time_interval):
|
35
|
-
raise ValueError(
|
39
|
+
raise ValueError(
|
40
|
+
"Time interval must be a list or tuple with two elements in format YYYY-MM-DD."
|
41
|
+
)
|
36
42
|
if not bounding_box:
|
37
43
|
raise ValueError("Bounding box must be specified.")
|
38
44
|
else:
|
39
45
|
if not is_bounding_box(bounding_box):
|
40
|
-
raise ValueError(
|
46
|
+
raise ValueError(
|
47
|
+
"Bounding box must be a list or tuple with four elements in format (lon_min, lat_min, lon_max, lat_max)."
|
48
|
+
)
|
41
49
|
|
42
50
|
|
43
|
-
def imagery_from_tmp_to_dir(
|
44
|
-
|
45
|
-
|
51
|
+
def imagery_from_tmp_to_dir(
|
52
|
+
output_dir: str, tmp_dir: Optional[str] = "/tmp/sentinelhub"
|
53
|
+
) -> None:
|
46
54
|
"""
|
55
|
+
Copy imagery from tmp to output dir
|
47
56
|
"""
|
48
57
|
downloaded_files = glob(f"{tmp_dir}/**/response.tiff")
|
49
58
|
assert len(downloaded_files) > 0, "No files downloaded"
|
@@ -51,36 +60,37 @@ def imagery_from_tmp_to_dir(output_dir: str,
|
|
51
60
|
makedirs(output_dir, exist_ok=True)
|
52
61
|
|
53
62
|
for downloaded_file in downloaded_files:
|
54
|
-
request_json = downloaded_file.replace(
|
63
|
+
request_json = downloaded_file.replace("response.tiff", "request.json")
|
55
64
|
metadata = generate_raster_metadata(downloaded_file, request_json)
|
56
|
-
if metadata[
|
65
|
+
if metadata["acquisition-date"]:
|
57
66
|
output_filename = f"{metadata['type']}_{metadata['acquisition-date']}"
|
58
67
|
else:
|
59
|
-
output_filename = metadata[
|
68
|
+
output_filename = metadata["type"]
|
60
69
|
|
61
70
|
copyfile(downloaded_file, f"{output_dir}/{output_filename}.tif")
|
62
|
-
|
63
|
-
|
71
|
+
with open(f"{output_dir}/{output_filename}.json", "w", encoding="utf-8") as f:
|
72
|
+
json.dump(metadata, f)
|
73
|
+
|
64
74
|
rmtree(tmp_dir)
|
65
75
|
|
66
76
|
|
67
|
-
def generate_raster_metadata(raster: str,
|
68
|
-
request_json: str
|
69
|
-
) -> None:
|
77
|
+
def generate_raster_metadata(raster: str, request_json: str) -> None:
|
70
78
|
"""
|
79
|
+
Generate metadata for raster
|
71
80
|
"""
|
72
81
|
bbox = get_image_bbox(raster)
|
73
|
-
|
82
|
+
with open(request_json, "r", encoding="utf-8") as f:
|
83
|
+
json_content = json.load(f)
|
74
84
|
|
75
|
-
payload_data = json_content[
|
76
|
-
sensor_type = payload_data[
|
85
|
+
payload_data = json_content["request"]["payload"]["input"]["data"][0]
|
86
|
+
sensor_type = payload_data["type"]
|
77
87
|
# Get day between from and to
|
78
|
-
if
|
79
|
-
time_range = payload_data[
|
80
|
-
acquisition_date = get_day_between(time_range[
|
81
|
-
else:
|
88
|
+
if "timeRange" in payload_data["dataFilter"] and sensor_type != "dem":
|
89
|
+
time_range = payload_data["dataFilter"]["timeRange"]
|
90
|
+
acquisition_date = get_day_between(time_range["from"], time_range["to"])
|
91
|
+
else: # DEM data does not have a timeRange
|
82
92
|
acquisition_date = None
|
83
|
-
|
93
|
+
|
84
94
|
metadata = {
|
85
95
|
"acquisition-date": acquisition_date,
|
86
96
|
"bounding-box": bbox,
|
eotdl/auth/errors.py
CHANGED
@@ -3,7 +3,8 @@ class LoginError(Exception):
|
|
3
3
|
self.message = message
|
4
4
|
super().__init__(self.message)
|
5
5
|
|
6
|
+
|
6
7
|
class AuthTimeOut(Exception):
|
7
8
|
def __init__(self, message='Authentication timed out'):
|
8
9
|
self.message = message
|
9
|
-
super().__init__(self.message)
|
10
|
+
super().__init__(self.message)
|
eotdl/commands/auth.py
CHANGED
@@ -37,14 +37,14 @@ def logout():
|
|
37
37
|
user = is_logged()
|
38
38
|
if user:
|
39
39
|
typer.echo(f"You are logged in as {user['email']}")
|
40
|
-
typer.confirm(
|
40
|
+
typer.confirm("Are you sure you want to logout?", abort=True)
|
41
41
|
logout_url = logout_user()
|
42
|
-
typer.echo(
|
42
|
+
typer.echo("You are logged out.")
|
43
43
|
typer.echo(
|
44
44
|
f"If you want to login with a different account, visit {logout_url} and login again."
|
45
45
|
)
|
46
46
|
else:
|
47
|
-
typer.echo(
|
47
|
+
typer.echo("You are not logged in.")
|
48
48
|
|
49
49
|
|
50
50
|
if __name__ == "__main__":
|
eotdl/curation/__init__.py
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
+
"""
|
2
|
+
Curation module
|
3
|
+
"""
|
4
|
+
|
1
5
|
from .stac.dataframe import STACDataFrame # , read_stac
|
2
6
|
from .stac.stac import STACGenerator
|
3
7
|
from .stac.parsers import STACIdParser, StructuredParser, UnestructuredParser
|
4
|
-
from .stac.dataframe_labeling import UnlabeledStrategy, LabeledStrategy
|
8
|
+
from .stac.dataframe_labeling import UnlabeledStrategy, LabeledStrategy
|
eotdl/curation/stac/__init__.py
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
+
"""
|
2
|
+
STAC module
|
3
|
+
"""
|
4
|
+
|
1
5
|
# from .stac import STACGenerator
|
2
6
|
# from .utils import format_time_acquired
|
3
7
|
# from .parsers import STACIdParser, StructuredParser, UnestructuredParser
|
4
|
-
from .dataframe import STACDataFrame, read_stac
|
8
|
+
from .dataframe import STACDataFrame, read_stac
|
eotdl/curation/stac/assets.py
CHANGED
@@ -1,35 +1,38 @@
|
|
1
|
-
|
1
|
+
"""
|
2
2
|
Module for STAC Asset Generators
|
3
|
-
|
3
|
+
"""
|
4
4
|
|
5
5
|
from os import remove, listdir
|
6
6
|
from os.path import dirname, join, basename, abspath
|
7
|
-
from ...tools.metadata import remove_raster_metadata
|
8
|
-
from typing import List
|
9
7
|
|
10
8
|
import pandas as pd
|
11
9
|
import rasterio
|
12
10
|
import pystac
|
13
11
|
|
12
|
+
from ...tools.metadata import remove_raster_metadata
|
13
|
+
|
14
14
|
|
15
15
|
MEDIA_TYPES_DICT = {
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
"tif": pystac.MediaType.GEOTIFF,
|
17
|
+
"tiff": pystac.MediaType.GEOTIFF,
|
18
|
+
"png": pystac.MediaType.PNG,
|
19
|
+
"jpg": pystac.MediaType.JPEG,
|
20
|
+
"jpeg": pystac.MediaType.JPEG,
|
21
21
|
}
|
22
22
|
|
23
23
|
|
24
24
|
class STACAssetGenerator:
|
25
|
+
"""
|
26
|
+
Standard STAC Asset Generator
|
27
|
+
"""
|
28
|
+
|
29
|
+
type = "None"
|
25
30
|
|
26
|
-
type = 'None'
|
27
|
-
|
28
31
|
def __init__(self):
|
29
32
|
pass
|
30
33
|
|
31
34
|
@classmethod
|
32
|
-
def extract_assets(
|
35
|
+
def extract_assets(cls, obj_info: pd.DataFrame):
|
33
36
|
"""
|
34
37
|
Generate a single asset from the raster file
|
35
38
|
|
@@ -37,24 +40,29 @@ class STACAssetGenerator:
|
|
37
40
|
"""
|
38
41
|
# If there is no bands, create a single band asset from the file, assuming thats a singleband raster
|
39
42
|
raster_path = obj_info["image"].values[0]
|
40
|
-
title = basename(raster_path).split(
|
43
|
+
title = basename(raster_path).split(".")[0]
|
41
44
|
# Get the file extension
|
42
|
-
raster_format = raster_path.split(
|
43
|
-
asset = pystac.Asset(
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
raster_format = raster_path.split(".")[-1]
|
46
|
+
asset = pystac.Asset(
|
47
|
+
href=abspath(raster_path),
|
48
|
+
title=title,
|
49
|
+
media_type=MEDIA_TYPES_DICT[raster_format],
|
50
|
+
roles=["data"],
|
51
|
+
)
|
47
52
|
|
48
53
|
return [asset]
|
49
54
|
|
50
55
|
|
51
56
|
class BandsAssetGenerator(STACAssetGenerator):
|
57
|
+
"""
|
58
|
+
Bands STAC Asset Generator
|
59
|
+
"""
|
52
60
|
|
53
|
-
type =
|
61
|
+
type = "Bands"
|
54
62
|
|
55
63
|
def __init__(self) -> None:
|
56
64
|
super().__init__()
|
57
|
-
|
65
|
+
|
58
66
|
def extract_assets(self, obj_info: pd.DataFrame):
|
59
67
|
"""
|
60
68
|
Extract the assets from the raster file from the bands column
|
@@ -69,17 +77,19 @@ class BandsAssetGenerator(STACAssetGenerator):
|
|
69
77
|
bands = bands[0] if bands else None
|
70
78
|
|
71
79
|
if bands:
|
72
|
-
with rasterio.open(raster_path,
|
80
|
+
with rasterio.open(raster_path, "r") as raster:
|
73
81
|
if isinstance(bands, str):
|
74
82
|
bands = [bands]
|
75
83
|
for band in bands:
|
76
84
|
i = bands.index(band)
|
77
|
-
raster_format = raster_path.split(
|
85
|
+
raster_format = raster_path.split(".")[
|
86
|
+
-1
|
87
|
+
] # Will be used later to save the bands files
|
78
88
|
try:
|
79
89
|
single_band = raster.read(i + 1)
|
80
90
|
except IndexError:
|
81
91
|
single_band = raster.read(1)
|
82
|
-
band_name = f
|
92
|
+
band_name = f"{band}.{raster_format}"
|
83
93
|
output_band = join(dirname(raster_path), band_name)
|
84
94
|
# Copy the metadata
|
85
95
|
metadata = raster.meta.copy()
|
@@ -88,9 +98,13 @@ class BandsAssetGenerator(STACAssetGenerator):
|
|
88
98
|
with rasterio.open(output_band, "w", **metadata) as dest:
|
89
99
|
dest.write(single_band, 1)
|
90
100
|
# Instantiate pystac asset and append it to the list
|
91
|
-
asset_list.append(
|
92
|
-
|
93
|
-
|
101
|
+
asset_list.append(
|
102
|
+
pystac.Asset(
|
103
|
+
href=output_band,
|
104
|
+
title=band,
|
105
|
+
media_type=MEDIA_TYPES_DICT[raster_format],
|
106
|
+
)
|
107
|
+
)
|
94
108
|
|
95
109
|
# Remove the original raster file and its metadata
|
96
110
|
remove(raster_path)
|
@@ -100,8 +114,11 @@ class BandsAssetGenerator(STACAssetGenerator):
|
|
100
114
|
|
101
115
|
|
102
116
|
class ExtractedAssets(STACAssetGenerator):
|
117
|
+
"""
|
118
|
+
Extracted STAC Asset Generator
|
119
|
+
"""
|
103
120
|
|
104
|
-
type =
|
121
|
+
type = "Extracted"
|
105
122
|
|
106
123
|
def __init__(self) -> None:
|
107
124
|
super().__init__()
|
@@ -115,13 +132,19 @@ class ExtractedAssets(STACAssetGenerator):
|
|
115
132
|
raster_path = obj_info["image"].values[0]
|
116
133
|
raster_dir = dirname(raster_path)
|
117
134
|
# Get the files with the same extension as the image file
|
118
|
-
files = [
|
135
|
+
files = [
|
136
|
+
f for f in listdir(raster_dir) if f.endswith(raster_path.split(".")[-1])
|
137
|
+
]
|
119
138
|
# Instantiate pystac asset and append it to the list
|
120
139
|
for file in files:
|
121
140
|
# Get the file extension
|
122
|
-
raster_format = file.split(
|
123
|
-
asset_list.append(
|
124
|
-
|
125
|
-
|
141
|
+
raster_format = file.split(".")[-1]
|
142
|
+
asset_list.append(
|
143
|
+
pystac.Asset(
|
144
|
+
href=join(raster_dir, file),
|
145
|
+
title=basename(file),
|
146
|
+
media_type=MEDIA_TYPES_DICT[raster_format],
|
147
|
+
)
|
148
|
+
)
|
126
149
|
|
127
150
|
return asset_list
|
eotdl/curation/stac/dataframe.py
CHANGED
@@ -2,26 +2,31 @@
|
|
2
2
|
Module for the STAC dataframe
|
3
3
|
"""
|
4
4
|
|
5
|
-
import pandas as pd
|
6
|
-
import geopandas as gpd
|
7
|
-
import pystac
|
8
5
|
import json
|
9
|
-
|
6
|
+
|
10
7
|
from os.path import join
|
11
8
|
from os import makedirs
|
12
9
|
from typing import Union, Optional
|
13
|
-
|
14
10
|
from math import isnan
|
15
|
-
from ...tools import convert_df_geom_to_shape, get_all_children
|
16
11
|
from pathlib import Path
|
17
12
|
|
13
|
+
import pandas as pd
|
14
|
+
import geopandas as gpd
|
15
|
+
import pystac
|
16
|
+
from geomet import wkt
|
17
|
+
|
18
|
+
from ...tools import convert_df_geom_to_shape, get_all_children
|
19
|
+
|
18
20
|
|
19
21
|
class STACDataFrame(gpd.GeoDataFrame):
|
22
|
+
"""
|
23
|
+
STACDataFrame class
|
24
|
+
"""
|
20
25
|
def __init__(self, *args, **kwargs):
|
21
26
|
super().__init__(*args, **kwargs)
|
22
27
|
|
23
28
|
@classmethod
|
24
|
-
def from_stac_file(
|
29
|
+
def from_stac_file(cls, stac_file: pystac.STACObject):
|
25
30
|
"""
|
26
31
|
Create a STACDataFrame from a STAC file
|
27
32
|
|
@@ -56,11 +61,11 @@ class STACDataFrame(gpd.GeoDataFrame):
|
|
56
61
|
# Curate the json row
|
57
62
|
row_json = self.curate_json_row(row_json, stac_id_exists)
|
58
63
|
|
59
|
-
with open(join(root_output_folder,
|
64
|
+
with open(join(root_output_folder, "catalog.json"), "w", encoding="utf-8") as f:
|
60
65
|
json.dump(row_json, f)
|
61
66
|
|
62
67
|
# Second, create the collections and their folders, if exist
|
63
|
-
collections =
|
68
|
+
collections = {}
|
64
69
|
collections_df = df[df["type"] == "Collection"]
|
65
70
|
for _, row in collections_df.iterrows():
|
66
71
|
stac_output_folder = join(root_output_folder, row[id_column])
|
@@ -71,7 +76,7 @@ class STACDataFrame(gpd.GeoDataFrame):
|
|
71
76
|
# Curate the json row
|
72
77
|
row_json = self.curate_json_row(row_json, stac_id_exists)
|
73
78
|
|
74
|
-
with open(join(stac_output_folder,
|
79
|
+
with open(join(stac_output_folder, "collection.json"), "w", encoding="utf-8") as f:
|
75
80
|
json.dump(row_json, f)
|
76
81
|
|
77
82
|
# Then, create the items and their folders, if exist
|
@@ -89,7 +94,7 @@ class STACDataFrame(gpd.GeoDataFrame):
|
|
89
94
|
# Curate the json row
|
90
95
|
row_json = self.curate_json_row(row_json, stac_id_exists)
|
91
96
|
|
92
|
-
with open(join(stac_output_folder, f'{row_json["id"]}.json'), "w") as f:
|
97
|
+
with open(join(stac_output_folder, f'{row_json["id"]}.json'), "w", encoding="utf-8") as f:
|
93
98
|
json.dump(row_json, f)
|
94
99
|
|
95
100
|
def curate_json_row(self, row: dict, stac_id_exists: bool) -> dict:
|
@@ -99,7 +104,7 @@ class STACDataFrame(gpd.GeoDataFrame):
|
|
99
104
|
:param row: row of a STACDataFrame
|
100
105
|
:param stac_id_exists: if the stac_id column exists
|
101
106
|
"""
|
102
|
-
keys_to_remove =
|
107
|
+
keys_to_remove = []
|
103
108
|
|
104
109
|
# Remove the created_at and modified_at columns, if the STACDataFrame comes from GeoDB
|
105
110
|
for i in "created_at", "modified_at":
|
@@ -130,6 +135,7 @@ class STACDataFrame(gpd.GeoDataFrame):
|
|
130
135
|
|
131
136
|
return row
|
132
137
|
|
138
|
+
|
133
139
|
def read_stac(
|
134
140
|
stac_file: Union[pystac.Catalog, pystac.Collection, str],
|
135
141
|
geometry_column: Optional[str] = "geometry",
|
@@ -140,8 +146,8 @@ def read_stac(
|
|
140
146
|
:param stac_file: STAC file to read
|
141
147
|
:param geometry_column: name of the geometry column
|
142
148
|
"""
|
143
|
-
if isinstance(stac_file, str
|
144
|
-
stac_file = pystac.read_file(stac_file)
|
149
|
+
if isinstance(stac_file, (str, Path)):
|
150
|
+
stac_file = pystac.read_file(stac_file) # we assume this is always a catalog
|
145
151
|
stac_file.make_all_asset_hrefs_absolute()
|
146
152
|
children = get_all_children(stac_file)
|
147
153
|
|
@@ -161,7 +161,7 @@ class STACDataFrame(gpd.GeoDataFrame):
|
|
161
161
|
# Curate the json row
|
162
162
|
row_json = self.curate_json_row(row_json, stac_id_exists)
|
163
163
|
|
164
|
-
with open(join(root_output_folder,
|
164
|
+
with open(join(root_output_folder, "catalog.json"), "w") as f:
|
165
165
|
json.dump(row_json, f)
|
166
166
|
|
167
167
|
# Second, create the collections and their folders, if exist
|
@@ -176,7 +176,7 @@ class STACDataFrame(gpd.GeoDataFrame):
|
|
176
176
|
# Curate the json row
|
177
177
|
row_json = self.curate_json_row(row_json, stac_id_exists)
|
178
178
|
|
179
|
-
with open(join(stac_output_folder,
|
179
|
+
with open(join(stac_output_folder, "collection.json"), "w") as f:
|
180
180
|
json.dump(row_json, f)
|
181
181
|
|
182
182
|
# Then, create the items and their folders, if exist
|
@@ -1,8 +1,7 @@
|
|
1
|
-
|
1
|
+
"""
|
2
2
|
Module for the labeling strategy when creating a STAC catalog from a dataframe
|
3
|
-
|
3
|
+
"""
|
4
4
|
|
5
|
-
import pystac
|
6
5
|
from os.path import basename
|
7
6
|
|
8
7
|
|
@@ -11,11 +10,11 @@ class LabelingStrategy:
|
|
11
10
|
Labeling strategy interface to be implemented by concrete labeling strategies
|
12
11
|
"""
|
13
12
|
|
14
|
-
def __init__(self):
|
15
|
-
pass
|
16
|
-
|
17
13
|
def get_images_labels(self, images):
|
18
|
-
|
14
|
+
"""
|
15
|
+
Get the labels of the images
|
16
|
+
"""
|
17
|
+
return
|
19
18
|
|
20
19
|
|
21
20
|
class UnlabeledStrategy(LabelingStrategy):
|
@@ -28,10 +27,11 @@ class UnlabeledStrategy(LabelingStrategy):
|
|
28
27
|
|
29
28
|
def get_images_labels(self, images):
|
30
29
|
"""
|
30
|
+
Get the labels of the images
|
31
31
|
"""
|
32
|
-
labels =
|
32
|
+
labels = []
|
33
33
|
for image in images:
|
34
|
-
labels.append(basename(image).split(
|
34
|
+
labels.append(basename(image).split(".")[0])
|
35
35
|
ixs = [labels.index(x) for x in labels]
|
36
36
|
|
37
37
|
return labels, ixs
|
@@ -48,11 +48,14 @@ class LabeledStrategy(LabelingStrategy):
|
|
48
48
|
|
49
49
|
def get_images_labels(self, images):
|
50
50
|
"""
|
51
|
+
Get the labels of the images
|
51
52
|
"""
|
52
|
-
labels =
|
53
|
+
labels = []
|
53
54
|
for image in images:
|
54
|
-
image_basename = basename(image).split(
|
55
|
-
|
55
|
+
image_basename = basename(image).split(".")[
|
56
|
+
0
|
57
|
+
] # Get filename without extension
|
58
|
+
label = image_basename.split("_")[0]
|
56
59
|
labels.append(label)
|
57
60
|
|
58
61
|
ixs = [labels.index(x) for x in labels]
|
@@ -1,3 +1,7 @@
|
|
1
|
+
"""
|
2
|
+
STAC extensions module
|
3
|
+
"""
|
4
|
+
|
1
5
|
from .sar import SarExtensionObject
|
2
6
|
from .raster import RasterExtensionObject
|
3
7
|
from .projection import ProjExtensionObject
|
@@ -7,7 +11,7 @@ from .label import LabelExtensionObject, ImageNameLabeler, ScaneoLabeler
|
|
7
11
|
from .ml_dataset import add_ml_extension, MLDatasetQualityMetrics
|
8
12
|
|
9
13
|
|
10
|
-
SUPPORTED_EXTENSIONS = (
|
14
|
+
SUPPORTED_EXTENSIONS = ("eo", "sar", "proj", "raster")
|
11
15
|
|
12
16
|
|
13
17
|
type_stac_extensions_dict = {
|
@@ -15,5 +19,5 @@ type_stac_extensions_dict = {
|
|
15
19
|
"eo": EOS2ExtensionObject(),
|
16
20
|
"dem": DEMExtensionObject(),
|
17
21
|
"raster": RasterExtensionObject(),
|
18
|
-
"proj": ProjExtensionObject()
|
22
|
+
"proj": ProjExtensionObject(),
|
19
23
|
}
|
@@ -9,13 +9,17 @@ import pandas as pd
|
|
9
9
|
|
10
10
|
|
11
11
|
class STACExtensionObject:
|
12
|
+
"""
|
13
|
+
Base model for STAC extensions objects
|
14
|
+
"""
|
12
15
|
def __init__(self) -> None:
|
13
16
|
super().__init__()
|
14
|
-
self.properties =
|
17
|
+
self.properties = {}
|
15
18
|
|
16
19
|
def add_extension_to_object(
|
17
|
-
self,
|
18
|
-
|
20
|
+
self,
|
21
|
+
obj: Union[pystac.Item, pystac.Asset],
|
22
|
+
obj_info: Optional[pd.DataFrame] = None,
|
19
23
|
) -> Union[pystac.Item, pystac.Asset]:
|
20
24
|
"""
|
21
25
|
Add the extension to the given object
|
@@ -23,4 +27,4 @@ class STACExtensionObject:
|
|
23
27
|
:param obj: object to add the extension
|
24
28
|
:param obj_info: object info from the STACDataFrame
|
25
29
|
"""
|
26
|
-
|
30
|
+
return
|
@@ -1,15 +1,18 @@
|
|
1
|
-
|
1
|
+
"""
|
2
2
|
Module for DEM STAC extensions object
|
3
|
-
|
3
|
+
"""
|
4
4
|
|
5
5
|
from .base import STACExtensionObject
|
6
6
|
|
7
7
|
|
8
8
|
class DEMExtensionObject(STACExtensionObject):
|
9
|
+
"""
|
10
|
+
DEM STAC extension object
|
11
|
+
"""
|
9
12
|
DEM_DATE_ACQUIRED = {
|
10
13
|
"start_datetime": "2011-01-01T00:00:00Z",
|
11
14
|
"end_datetime": "2015-01-07T00:00:00Z",
|
12
15
|
}
|
13
16
|
|
14
17
|
def __init__(self) -> None:
|
15
|
-
super().__init__()
|
18
|
+
super().__init__()
|
@@ -1,16 +1,21 @@
|
|
1
|
-
|
1
|
+
"""
|
2
2
|
Module for EO STAC extensions object
|
3
|
-
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import Union
|
4
6
|
|
5
7
|
import pystac
|
6
8
|
import pandas as pd
|
7
9
|
|
8
|
-
from typing import Union
|
9
|
-
from .base import STACExtensionObject
|
10
10
|
from pystac.extensions.eo import Band, EOExtension
|
11
11
|
|
12
|
+
from .base import STACExtensionObject
|
13
|
+
|
12
14
|
|
13
15
|
class EOS2ExtensionObject(STACExtensionObject):
|
16
|
+
"""
|
17
|
+
EO STAC extension object
|
18
|
+
"""
|
14
19
|
def __init__(self) -> None:
|
15
20
|
super().__init__()
|
16
21
|
self.bands_dict = {
|
@@ -82,8 +87,7 @@ class EOS2ExtensionObject(STACExtensionObject):
|
|
82
87
|
}
|
83
88
|
|
84
89
|
def add_extension_to_object(
|
85
|
-
self, obj: Union[pystac.Item, pystac.Asset],
|
86
|
-
obj_info: pd.DataFrame
|
90
|
+
self, obj: Union[pystac.Item, pystac.Asset], obj_info: pd.DataFrame
|
87
91
|
) -> Union[pystac.Item, pystac.Asset]:
|
88
92
|
"""
|
89
93
|
Add the extension to the given object
|