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.
Files changed (58) hide show
  1. eotdl/__init__.py +1 -1
  2. eotdl/access/__init__.py +6 -3
  3. eotdl/access/airbus/__init__.py +5 -1
  4. eotdl/access/airbus/client.py +356 -338
  5. eotdl/access/airbus/parameters.py +19 -4
  6. eotdl/access/airbus/utils.py +26 -21
  7. eotdl/access/download.py +30 -14
  8. eotdl/access/search.py +17 -6
  9. eotdl/access/sentinelhub/__init__.py +5 -1
  10. eotdl/access/sentinelhub/client.py +57 -54
  11. eotdl/access/sentinelhub/evalscripts.py +38 -39
  12. eotdl/access/sentinelhub/parameters.py +43 -23
  13. eotdl/access/sentinelhub/utils.py +38 -28
  14. eotdl/auth/errors.py +2 -1
  15. eotdl/commands/auth.py +3 -3
  16. eotdl/curation/__init__.py +5 -1
  17. eotdl/curation/stac/__init__.py +5 -1
  18. eotdl/curation/stac/assets.py +55 -32
  19. eotdl/curation/stac/dataframe.py +20 -14
  20. eotdl/curation/stac/dataframe_bck.py +2 -2
  21. eotdl/curation/stac/dataframe_labeling.py +15 -12
  22. eotdl/curation/stac/extensions/__init__.py +6 -2
  23. eotdl/curation/stac/extensions/base.py +8 -4
  24. eotdl/curation/stac/extensions/dem.py +6 -3
  25. eotdl/curation/stac/extensions/eo.py +10 -6
  26. eotdl/curation/stac/extensions/label/__init__.py +5 -1
  27. eotdl/curation/stac/extensions/label/base.py +40 -26
  28. eotdl/curation/stac/extensions/label/image_name_labeler.py +64 -43
  29. eotdl/curation/stac/extensions/label/scaneo.py +59 -56
  30. eotdl/curation/stac/extensions/ml_dataset.py +154 -56
  31. eotdl/curation/stac/extensions/projection.py +11 -9
  32. eotdl/curation/stac/extensions/raster.py +22 -14
  33. eotdl/curation/stac/extensions/sar.py +12 -7
  34. eotdl/curation/stac/extent.py +67 -40
  35. eotdl/curation/stac/parsers.py +18 -10
  36. eotdl/curation/stac/stac.py +81 -62
  37. eotdl/datasets/__init__.py +1 -1
  38. eotdl/datasets/download.py +42 -55
  39. eotdl/datasets/ingest.py +68 -11
  40. eotdl/files/__init__.py +1 -1
  41. eotdl/files/ingest.py +3 -1
  42. eotdl/models/download.py +1 -1
  43. eotdl/repos/AuthAPIRepo.py +0 -1
  44. eotdl/repos/DatasetsAPIRepo.py +22 -146
  45. eotdl/repos/FilesAPIRepo.py +7 -92
  46. eotdl/repos/ModelsAPIRepo.py +0 -1
  47. eotdl/tools/__init__.py +5 -1
  48. eotdl/tools/geo_utils.py +78 -48
  49. eotdl/tools/metadata.py +13 -11
  50. eotdl/tools/paths.py +14 -14
  51. eotdl/tools/stac.py +36 -31
  52. eotdl/tools/time_utils.py +53 -26
  53. eotdl/tools/tools.py +84 -50
  54. {eotdl-2023.11.2.post5.dist-info → eotdl-2023.11.3.post2.dist-info}/METADATA +5 -3
  55. eotdl-2023.11.3.post2.dist-info/RECORD +84 -0
  56. eotdl-2023.11.2.post5.dist-info/RECORD +0 -84
  57. {eotdl-2023.11.2.post5.dist-info → eotdl-2023.11.3.post2.dist-info}/WHEEL +0 -0
  58. {eotdl-2023.11.2.post5.dist-info → eotdl-2023.11.3.post2.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,9 @@
1
1
  """Implements the :stac-ext:`Machine Learning Dataset Extension <ml-dataset>`."""
2
2
 
3
+ from typing import Any, Dict, List, Optional, Generic, TypeVar, Union, Set
4
+ from shutil import rmtree
5
+ from os.path import dirname, exists
6
+
3
7
  import traceback
4
8
  import json
5
9
  import random
@@ -10,11 +14,8 @@ from tqdm import tqdm
10
14
  from pystac.extensions.base import ExtensionManagementMixin, PropertiesExtension
11
15
  from pystac.extensions.label import LabelExtension
12
16
  from pystac import STACValidationError
13
- from shutil import rmtree
14
- from os.path import dirname, exists
15
17
  from pystac.cache import ResolvedObjectCache
16
18
  from pystac.extensions.hooks import ExtensionHooks
17
- from typing import Any, Dict, List, Optional, Generic, TypeVar, Union, Set
18
19
  from ....tools import make_links_relative_to_path
19
20
 
20
21
  T = TypeVar("T", pystac.Item, pystac.Collection, pystac.Catalog)
@@ -74,74 +75,129 @@ class MLDatasetExtension(
74
75
  self._resolved_objects = ResolvedObjectCache()
75
76
 
76
77
  def apply(self, name: str = None) -> None:
78
+ """
79
+ Applies the :stac-ext:`Machine Learning Dataset Extension <ml-dataset>` to the extended
80
+ :class:`~pystac.Catalog`.
81
+ """
77
82
  self.name = name
78
83
 
79
84
  @property
80
85
  def name(self) -> str:
86
+ """
87
+ Name of the ML Dataset.
88
+ """
81
89
  return self.extra_fields[f"{PREFIX}name"]
82
90
 
83
91
  @name.setter
84
92
  def name(self, v: str) -> None:
93
+ """
94
+ Set the name of the ML Dataset.
95
+ """
85
96
  self.extra_fields[f"{PREFIX}name"] = v
86
97
 
87
98
  @property
88
99
  def tasks(self) -> List:
100
+ """
101
+ Tasks of the ML Dataset.
102
+ """
89
103
  return self.extra_fields[f"{PREFIX}tasks"]
90
104
 
91
105
  @tasks.setter
92
106
  def tasks(self, v: Union[list, tuple]) -> None:
107
+ """
108
+ Set the tasks of the ML Dataset.
109
+ """
93
110
  self.extra_fields[f"{PREFIX}tasks"] = v
94
111
 
95
112
  @property
96
113
  def type(self) -> str:
114
+ """
115
+ Type of the ML Dataset.
116
+ """
97
117
  return self.extra_fields[f"{PREFIX}type"]
98
118
 
99
119
  @type.setter
100
120
  def type(self, v: str) -> None:
121
+ """
122
+ Set the type of the ML Dataset.
123
+ """
101
124
  self.extra_fields[f"{PREFIX}type"] = v
102
125
 
103
126
  @property
104
127
  def inputs_type(self) -> str:
128
+ """
129
+ Inputs type of the ML Dataset.
130
+ """
105
131
  return self.extra_fields[f"{PREFIX}inputs-type"]
106
132
 
107
133
  @inputs_type.setter
108
134
  def inputs_type(self, v: str) -> None:
135
+ """
136
+ Set the inputs type of the ML Dataset.
137
+ """
109
138
  self.extra_fields[f"{PREFIX}inputs-type"] = v
110
139
 
111
140
  @property
112
141
  def annotations_type(self) -> str:
142
+ """
143
+ Annotations type of the ML Dataset.
144
+ """
113
145
  return self.extra_fields[f"{PREFIX}annotations-type"]
114
146
 
115
147
  @annotations_type.setter
116
148
  def annotations_type(self, v: str) -> None:
149
+ """
150
+ Set the annotations type of the ML Dataset.
151
+ """
117
152
  self.extra_fields[f"{PREFIX}annotations-type"] = v
118
153
 
119
154
  @property
120
155
  def splits(self) -> List[str]:
121
- self.extra_fields[f"{PREFIX}splits"]
156
+ """
157
+ Splits of the ML Dataset.
158
+ """
159
+ return self.extra_fields[f"{PREFIX}splits"]
122
160
 
123
161
  @splits.setter
124
162
  def splits(self, v: dict) -> None:
163
+ """
164
+ Set the splits of the ML Dataset.
165
+ """
125
166
  self.extra_fields[f"{PREFIX}splits"] = v
126
167
 
127
168
  @property
128
169
  def quality_metrics(self) -> List[dict]:
129
- self.extra_fields[f"{PREFIX}quality-metrics"]
170
+ """
171
+ Quality metrics of the ML Dataset.
172
+ """
173
+ return self.extra_fields[f"{PREFIX}quality-metrics"]
130
174
 
131
175
  @quality_metrics.setter
132
176
  def quality_metrics(self, v: dict) -> None:
177
+ """
178
+ Set the quality metrics of the ML Dataset.
179
+ """
133
180
  self.extra_fields[f"{PREFIX}quality-metrics"] = v
134
181
 
135
182
  @property
136
183
  def version(self) -> str:
137
- self.extra_fields[f"{PREFIX}version"]
184
+ """
185
+ Version of the ML Dataset.
186
+ """
187
+ return self.extra_fields[f"{PREFIX}version"]
138
188
 
139
189
  @version.setter
140
190
  def version(self, v: str) -> None:
191
+ """
192
+ Set the version of the ML Dataset.
193
+ """
141
194
  self.extra_fields[f"{PREFIX}version"] = v
142
195
 
143
196
  @classmethod
144
197
  def get_schema_uri(cls) -> str:
198
+ """
199
+ Get the JSON Schema URI that validates the extended object.
200
+ """
145
201
  return SCHEMA_URI
146
202
 
147
203
  def add_metric(self, metric: dict) -> None:
@@ -150,11 +206,11 @@ class MLDatasetExtension(
150
206
  Args:
151
207
  metric : The metric to add.
152
208
  """
153
- if not self.extra_fields.get(f'{PREFIX}quality-metrics'):
154
- self.extra_fields[f'{PREFIX}quality-metrics'] = []
209
+ if not self.extra_fields.get(f"{PREFIX}quality-metrics"):
210
+ self.extra_fields[f"{PREFIX}quality-metrics"] = []
155
211
 
156
- if metric not in self.extra_fields[f'{PREFIX}quality-metrics']:
157
- self.extra_fields[f'{PREFIX}quality-metrics'].append(metric)
212
+ if metric not in self.extra_fields[f"{PREFIX}quality-metrics"]:
213
+ self.extra_fields[f"{PREFIX}quality-metrics"].append(metric)
158
214
 
159
215
  def add_metrics(self, metrics: List[dict]) -> None:
160
216
  """Add a list of metrics to this object's set of metrics.
@@ -204,23 +260,34 @@ class CollectionMLDatasetExtension(MLDatasetExtension[pystac.Collection]):
204
260
  self.properties[f"{PREFIX}split-items"] = []
205
261
 
206
262
  def __repr__(self) -> str:
207
- return "<CollectionMLDatasetExtension Item id={}>".format(self.collection.id)
263
+ return f"<CollectionMLDatasetExtension Item id={self.collection.id}>"
208
264
 
209
265
  @property
210
266
  def splits(self) -> List[dict]:
211
- return self._splits
267
+ """
268
+ Splits of the ML Dataset.
269
+ """
270
+ return self.extra_fields[f"{PREFIX}splits"]
212
271
 
213
272
  @splits.setter
214
273
  def splits(self, v: dict) -> None:
274
+ """
275
+ Set the splits of the ML Dataset.
276
+ """
215
277
  self.properties[f"{PREFIX}split-items"] = v
216
278
 
217
279
  def add_split(self, v: dict) -> None:
280
+ """
281
+ Add a split to the ML Dataset.
282
+ """
218
283
  self.properties[f"{PREFIX}split-items"].append(v)
219
284
 
220
285
  def create_and_add_split(
221
286
  self, split_data: List[pystac.Item], split_type: str
222
287
  ) -> None:
223
- """ """
288
+ """
289
+ Create and add a split to the ML Dataset.
290
+ """
224
291
  items_ids = [item.id for item in split_data]
225
292
  items_ids.sort()
226
293
 
@@ -238,7 +305,6 @@ class CollectionMLDatasetExtension(MLDatasetExtension[pystac.Collection]):
238
305
  item_ml.split = split_type
239
306
 
240
307
 
241
-
242
308
  class ItemMLDatasetExtension(MLDatasetExtension[pystac.Item]):
243
309
  """A concrete implementation of :class:`MLDatasetExtension` on an
244
310
  :class:`~pystac.Item` that extends the properties of the Item to include properties
@@ -257,22 +323,32 @@ class ItemMLDatasetExtension(MLDatasetExtension[pystac.Item]):
257
323
 
258
324
  @property
259
325
  def split(self) -> str:
260
- return self._split
326
+ """
327
+ Split of the ML Dataset.
328
+ """
329
+ return self.properties[f"{PREFIX}split"]
261
330
 
262
331
  @split.setter
263
332
  def split(self, v: str) -> None:
333
+ """
334
+ Set the split of the ML Dataset.
335
+ """
264
336
  self.properties[f"{PREFIX}split"] = v
265
337
 
266
338
  def __repr__(self) -> str:
267
- return "<ItemMLDatasetExtension Item id={}>".format(self.item.id)
339
+ return f"<ItemMLDatasetExtension Item id={self.item.id}>"
268
340
 
269
341
 
270
342
  class MLDatasetQualityMetrics:
271
- """ """
343
+ """
344
+ ML Dataset Quality Metrics
345
+ """
272
346
 
273
347
  @classmethod
274
- def calculate(self, catalog: Union[pystac.Catalog, str]) -> None:
275
- """ """
348
+ def calculate(cls, catalog: Union[pystac.Catalog, str]) -> None:
349
+ """
350
+ Calculate the quality metrics of the catalog
351
+ """
276
352
  if isinstance(catalog, str):
277
353
  catalog = MLDatasetExtension(pystac.read_file(catalog))
278
354
  elif isinstance(catalog, pystac.Catalog):
@@ -284,15 +360,15 @@ class MLDatasetQualityMetrics:
284
360
  )
285
361
 
286
362
  try:
287
- catalog.add_metric(self._search_spatial_duplicates(catalog))
288
- catalog.add_metric(self._get_classes_balance(catalog))
289
- except AttributeError:
363
+ catalog.add_metric(cls._search_spatial_duplicates(catalog))
364
+ catalog.add_metric(cls._get_classes_balance(catalog))
365
+ except AttributeError as exc:
290
366
  raise pystac.ExtensionNotImplemented(
291
- f"The catalog does not have the required properties or the ML-Dataset extension to calculate the metrics"
367
+ f"The catalog does not have the required properties or the ML-Dataset extension to calculate the metrics: {exc}"
292
368
  )
293
369
  finally:
294
370
  catalog.make_all_asset_hrefs_relative()
295
-
371
+
296
372
  try:
297
373
  print("Validating and saving...")
298
374
  catalog.validate()
@@ -303,26 +379,32 @@ class MLDatasetQualityMetrics:
303
379
  catalog.set_root(catalog)
304
380
  catalog.normalize_and_save(root_href=destination)
305
381
  print("Success!")
306
- except STACValidationError as error:
382
+ except STACValidationError:
307
383
  # Return full callback
308
384
  traceback.print_exc()
309
385
 
310
386
  @staticmethod
311
387
  def _search_spatial_duplicates(catalog: pystac.Catalog):
312
- """ """
388
+ """
389
+ Search for spatial duplicates in the catalog
390
+ """
313
391
  items = list(
314
392
  set(
315
- [item
316
- for item in tqdm(catalog.get_items(recursive=True), desc="Looking for spatial duplicates...")
317
- if not LabelExtension.has_extension(item)
318
- ]
319
- )
393
+ [
394
+ item
395
+ for item in tqdm(
396
+ catalog.get_items(recursive=True),
397
+ desc="Looking for spatial duplicates...",
398
+ )
399
+ if not LabelExtension.has_extension(item)
400
+ ]
320
401
  )
402
+ )
321
403
 
322
404
  # Initialize the spatial duplicates dict
323
405
  spatial_duplicates = {"name": "spatial-duplicates", "values": [], "total": 0}
324
406
 
325
- items_bboxes = dict()
407
+ items_bboxes = {}
326
408
  for item in items:
327
409
  # Get the item bounding box
328
410
  bbox = str(item.bbox)
@@ -340,12 +422,15 @@ class MLDatasetQualityMetrics:
340
422
 
341
423
  @staticmethod
342
424
  def _get_classes_balance(catalog: pystac.Catalog) -> dict:
343
- """ """
425
+ """
426
+ Get the classes balance of the catalog
427
+ """
344
428
 
345
429
  def get_label_properties(items: List[pystac.Item]) -> List:
346
430
  """
431
+ Get the label properties of the catalog
347
432
  """
348
- label_properties = list()
433
+ label_properties = []
349
434
  for label in items:
350
435
  label_ext = LabelExtension.ext(label)
351
436
  for prop in label_ext.label_properties:
@@ -353,30 +438,36 @@ class MLDatasetQualityMetrics:
353
438
  label_properties.append(prop)
354
439
 
355
440
  return label_properties
356
-
441
+
357
442
  catalog.make_all_asset_hrefs_absolute()
358
443
 
359
444
  labels = list(
360
445
  set(
361
- [item
362
- for item in tqdm(catalog.get_items(recursive=True), desc="Calculating classes balance...")
363
- if LabelExtension.has_extension(item)
364
- ]
365
- )
446
+ [
447
+ item
448
+ for item in tqdm(
449
+ catalog.get_items(recursive=True),
450
+ desc="Calculating classes balance...",
451
+ )
452
+ if LabelExtension.has_extension(item)
453
+ ]
366
454
  )
455
+ )
367
456
 
368
457
  # Initialize the classes balance dict
369
458
  classes_balance = {"name": "classes-balance", "values": []}
370
459
  label_properties = get_label_properties(labels)
371
460
 
372
- for property in label_properties:
373
- property_balance = {"name": property, "values": []}
374
- properties = dict()
461
+ for prop in label_properties:
462
+ property_balance = {"name": prop, "values": []}
463
+ properties = {}
375
464
  for label in labels:
465
+ if 'labels' not in label.assets:
466
+ continue
376
467
  asset_path = label.assets["labels"].href
377
468
  # Open the linked geoJSON to obtain the label properties
378
469
  try:
379
- with open(asset_path) as f:
470
+ with open(asset_path, mode="r", encoding="utf-8") as f:
380
471
  label_data = json.load(f)
381
472
  except FileNotFoundError:
382
473
  raise FileNotFoundError(
@@ -384,8 +475,8 @@ class MLDatasetQualityMetrics:
384
475
  )
385
476
  # Get the property
386
477
  for feature in label_data["features"]:
387
- if property in feature["properties"]:
388
- property_value = feature["properties"][property]
478
+ if prop in feature["properties"]:
479
+ property_value = feature["properties"][prop]
389
480
  else:
390
481
  if feature["properties"]["labels"]:
391
482
  property_value = feature["properties"]["labels"][0]
@@ -394,7 +485,7 @@ class MLDatasetQualityMetrics:
394
485
  if property_value not in properties:
395
486
  properties[property_value] = 0
396
487
  properties[property_value] += 1
397
-
488
+
398
489
  # Create the property balance dict
399
490
  total_labels = sum(properties.values())
400
491
  for key, value in properties.items():
@@ -414,6 +505,9 @@ class MLDatasetQualityMetrics:
414
505
 
415
506
 
416
507
  class MLDatasetExtensionHooks(ExtensionHooks):
508
+ """
509
+ ML Dataset Extension Hooks
510
+ """
417
511
  schema_uri: str = SCHEMA_URI
418
512
  prev_extension_ids: Set[str] = set()
419
513
  stac_object_types = {
@@ -480,15 +574,19 @@ def add_ml_extension(
480
574
 
481
575
  # Normalize the ref on the same folder
482
576
  if destination:
483
- catalog_ml_dataset = make_links_relative_to_path(destination, catalog_ml_dataset)
577
+ catalog_ml_dataset = make_links_relative_to_path(
578
+ destination, catalog_ml_dataset
579
+ )
484
580
 
485
581
  try:
486
582
  print("Validating and saving...")
487
583
  catalog_ml_dataset.validate()
488
- rmtree(destination) if exists(destination) else None # Remove the old catalog and replace it with the new one
489
- catalog_ml_dataset.normalize_and_save(root_href=destination,
490
- catalog_type=catalog_type
491
- )
584
+ rmtree(destination) if exists(
585
+ destination
586
+ ) else None # Remove the old catalog and replace it with the new one
587
+ catalog_ml_dataset.normalize_and_save(
588
+ root_href=destination, catalog_type=catalog_type
589
+ )
492
590
  print("Success!")
493
591
  except STACValidationError:
494
592
  # Return full callback
@@ -500,7 +598,7 @@ def make_splits(
500
598
  splits_names: Optional[List[str]] = ("Training", "Validation", "Test"),
501
599
  splits_proportions: Optional[List[int]] = (80, 10, 10),
502
600
  verbose: Optional[bool] = True,
503
- **kwargs,
601
+ **kwargs: Optional[dict],
504
602
  ) -> None:
505
603
  """
506
604
  Makes the splits of the labels collection.
@@ -514,7 +612,7 @@ def make_splits(
514
612
  raise ValueError("The sum of the splits must be 100")
515
613
 
516
614
  # Get all items in the labels collection
517
- items = [item for item in labels_collection.get_items(recursive=True)]
615
+ items = list(labels_collection.get_items(recursive=True))
518
616
 
519
617
  # Calculate indices to split the items
520
618
  length = len(items)
@@ -536,9 +634,9 @@ def make_splits(
536
634
 
537
635
  # Split the items
538
636
  train_items = items[:idx_train]
539
- test_items = items[idx_train : idx_train + idx_test]
637
+ test_items = items[idx_train: idx_train + idx_test]
540
638
  if val_size:
541
- val_items = items[idx_train + idx_test : idx_train + idx_test + idx_val]
639
+ val_items = items[idx_train + idx_test: idx_train + idx_test + idx_val]
542
640
 
543
641
  # Create the splits in the collection
544
642
  labels_collection = MLDatasetExtension.ext(labels_collection, add_if_missing=True)
@@ -1,24 +1,26 @@
1
- '''
1
+ """
2
2
  Module for projection 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
  import rasterio
8
10
 
9
- from typing import Union
10
- from .base import STACExtensionObject
11
11
  from pystac.extensions.projection import ProjectionExtension
12
-
12
+ from .base import STACExtensionObject
13
13
 
14
14
 
15
15
  class ProjExtensionObject(STACExtensionObject):
16
+ """
17
+ Projection extension object
18
+ """
16
19
  def __init__(self) -> None:
17
20
  super().__init__()
18
21
 
19
22
  def add_extension_to_object(
20
- self, obj: Union[pystac.Item, pystac.Asset],
21
- obj_info: pd.DataFrame
23
+ self, obj: Union[pystac.Item, pystac.Asset], obj_info: pd.DataFrame
22
24
  ) -> Union[pystac.Item, pystac.Asset]:
23
25
  """
24
26
  Add the extension to the given object
@@ -31,12 +33,12 @@ class ProjExtensionObject(STACExtensionObject):
31
33
  return obj
32
34
  elif isinstance(obj, pystac.Item):
33
35
  proj_ext = ProjectionExtension.ext(obj, add_if_missing=True)
34
- ds = rasterio.open(obj_info['image'].values[0])
36
+ ds = rasterio.open(obj_info["image"].values[0])
35
37
  # Assume all the bands have the same projection
36
38
  proj_ext.apply(
37
39
  epsg=ds.crs.to_epsg(),
38
40
  transform=ds.transform,
39
41
  shape=ds.shape,
40
- )
42
+ )
41
43
 
42
44
  return obj
@@ -1,23 +1,28 @@
1
- '''
1
+ """
2
2
  Module for raster STAC extensions object
3
- '''
3
+ """
4
+
5
+ from typing import Union, Optional
4
6
 
5
7
  import pystac
6
8
  import rasterio
7
9
  import pandas as pd
8
10
 
9
11
  from pystac.extensions.raster import RasterExtension, RasterBand
10
- from typing import Union, Optional
11
12
  from .base import STACExtensionObject
12
13
 
13
14
 
14
15
  class RasterExtensionObject(STACExtensionObject):
16
+ """
17
+ Raster extension object
18
+ """
15
19
  def __init__(self) -> None:
16
20
  super().__init__()
17
21
 
18
22
  def add_extension_to_object(
19
- self, obj: Union[pystac.Item, pystac.Asset],
20
- obj_info: Optional[pd.DataFrame] = None
23
+ self,
24
+ obj: Union[pystac.Item, pystac.Asset],
25
+ obj_info: Optional[pd.DataFrame] = None,
21
26
  ) -> Union[pystac.Item, pystac.Asset]:
22
27
  """
23
28
  Add the extension to the given object
@@ -30,16 +35,19 @@ class RasterExtensionObject(STACExtensionObject):
30
35
  else:
31
36
  raster_ext = RasterExtension.ext(obj, add_if_missing=True)
32
37
  src = rasterio.open(obj.href)
33
- bands = list()
38
+ bands = []
34
39
  for band in src.indexes:
35
- bands.append(RasterBand.create(
36
- nodata=src.nodatavals[band - 1],
37
- data_type=src.dtypes[band - 1],
38
- spatial_resolution=src.res) if src.nodatavals else RasterBand.create(
40
+ bands.append(
41
+ RasterBand.create(
42
+ nodata=src.nodatavals[band - 1],
39
43
  data_type=src.dtypes[band - 1],
40
- spatial_resolution=src.res))
44
+ spatial_resolution=src.res,
45
+ )
46
+ if src.nodatavals
47
+ else RasterBand.create(
48
+ data_type=src.dtypes[band - 1], spatial_resolution=src.res
49
+ )
50
+ )
41
51
  raster_ext.apply(bands=bands)
42
-
43
- return obj
44
-
45
52
 
53
+ return obj
@@ -1,26 +1,31 @@
1
- '''
1
+ """
2
2
  Module for SAR STAC extensions object
3
- '''
3
+ """
4
+
5
+ from typing import Optional, Union
4
6
 
5
7
  import pystac
6
8
  import pandas as pd
7
9
 
8
- from .base import STACExtensionObject
9
-
10
- from typing import Optional, Union
11
10
  from pystac.extensions.sar import SarExtension
12
11
  from pystac.extensions.sar import FrequencyBand, Polarization
13
12
 
13
+ from .base import STACExtensionObject
14
+
14
15
 
15
16
  class SarExtensionObject(STACExtensionObject):
17
+ """
18
+ SAR extension object
19
+ """
16
20
  def __init__(self) -> None:
17
21
  super().__init__()
18
22
  self.polarizations = [Polarization.VV, Polarization.VH]
19
23
  self.polarizations_dict = {"VV": Polarization.VV, "VH": Polarization.VH}
20
24
 
21
25
  def add_extension_to_object(
22
- self, obj: Union[pystac.Item, pystac.Asset],
23
- obj_info: Optional[pd.DataFrame] = None
26
+ self,
27
+ obj: Union[pystac.Item, pystac.Asset],
28
+ obj_info: Optional[pd.DataFrame] = None,
24
29
  ) -> Union[pystac.Item, pystac.Asset]:
25
30
  """
26
31
  Add the extension to the given object