eodash_catalog 0.0.2__py3-none-any.whl → 0.0.3__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.

Potentially problematic release.


This version of eodash_catalog might be problematic. Click here for more details.

@@ -1,4 +1,4 @@
1
1
  # SPDX-FileCopyrightText: 2024-present Daniel Santillan <daniel.santillan@eox.at>
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
- __version__ = "0.0.2"
4
+ __version__ = "0.0.3"
@@ -86,12 +86,19 @@ def process_catalog_file(file_path, options):
86
86
  catalog_type=CatalogType.RELATIVE_PUBLISHED,
87
87
  )
88
88
  for collection in process_collections:
89
- process_collection_file(
90
- config,
91
- "%s/%s.yaml" % (options.collectionsspath, collection),
92
- catalog,
93
- options,
94
- )
89
+ file_path = "%s/%s.yaml" % (options.collectionspath, collection)
90
+ if os.path.isfile(file_path):
91
+ # if collection file exists process it as indicator
92
+ # collection will be added as single collection to indicator
93
+ process_indicator_file(config, file_path, catalog, options)
94
+ else:
95
+ # if not try to see if indicator definition available
96
+ process_indicator_file(
97
+ config,
98
+ "%s/%s.yaml" % (options.indicatorspath, collection),
99
+ catalog,
100
+ options,
101
+ )
95
102
 
96
103
  strategy = TemplateLayoutStrategy(item_template="${collection}/${year}")
97
104
  catalog.normalize_hrefs(
@@ -117,6 +124,81 @@ def process_catalog_file(file_path, options):
117
124
  print("Issue validation collection: %s" % e)
118
125
 
119
126
 
127
+ def extract_indicator_info(parent_collection):
128
+ to_extract = [
129
+ "subcode",
130
+ "themes",
131
+ "keywords",
132
+ "satellite",
133
+ "sensor",
134
+ "cities",
135
+ "countries",
136
+ ]
137
+ summaries = {}
138
+ for key in to_extract:
139
+ summaries[key] = set()
140
+
141
+ for collection in parent_collection.get_collections():
142
+ for key in to_extract:
143
+ if key in collection.extra_fields:
144
+ param = collection.extra_fields[key]
145
+ if isinstance(param, list):
146
+ for p in param:
147
+ summaries[key].add(p)
148
+ else:
149
+ summaries[key].add(param)
150
+ # extract also summary information
151
+ if collection.summaries.lists:
152
+ if key in collection.summaries.lists:
153
+ for p in collection.summaries.lists[key]:
154
+ summaries[key].add(p)
155
+
156
+ for key in to_extract:
157
+ # convert all items back to a list
158
+ summaries[key] = list(summaries[key])
159
+ # remove empty ones
160
+ if len(summaries[key]) == 0:
161
+ del summaries[key]
162
+ parent_collection.summaries = Summaries(summaries)
163
+
164
+
165
+ def iter_len_at_least(i, n):
166
+ return sum(1 for _ in zip(range(n), i)) == n
167
+
168
+
169
+ def process_indicator_file(config, file_path, catalog, options):
170
+ with open(file_path) as f:
171
+ print("Processing indicator:", file_path)
172
+ data = yaml.load(f, Loader=SafeLoader)
173
+ parent_indicator, _ = get_or_create_collection(
174
+ catalog, data["Name"], data, config
175
+ )
176
+ if "Collections" in data:
177
+ for collection in data["Collections"]:
178
+ process_collection_file(
179
+ config,
180
+ "%s/%s.yaml" % (options.collectionspath, collection),
181
+ catalog,
182
+ options,
183
+ )
184
+ else:
185
+ # we assume that collection files can also be loaded directly
186
+ process_collection_file(config, file_path, parent_indicator, options)
187
+ add_collection_information(config, parent_indicator, data)
188
+ if iter_len_at_least(parent_indicator.get_items(recursive=True), 1):
189
+ parent_indicator.update_extent_from_items()
190
+ # Add bbox extents from children
191
+ for c_child in parent_indicator.get_children():
192
+ parent_indicator.extent.spatial.bboxes.append(
193
+ c_child.extent.spatial.bboxes[0]
194
+ )
195
+ # extract collection information and add it to summary indicator level
196
+ extract_indicator_info(parent_indicator)
197
+ # add baselayer and overview information to indicator collection
198
+ add_base_overlay_info(parent_indicator, config, data)
199
+ add_to_catalog(parent_indicator, catalog, None, data)
200
+
201
+
120
202
  def process_collection_file(config, file_path, catalog, options):
121
203
  print("Processing collection:", file_path)
122
204
  with open(file_path) as f:
@@ -279,6 +361,9 @@ def handle_WMS_endpoint(config, endpoint, data, catalog, wmts=False):
279
361
  properties={},
280
362
  geometry=None,
281
363
  datetime=parser.isoparse(t),
364
+ stac_extensions=[
365
+ "https://stac-extensions.github.io/web-map-links/v1.1.0/schema.json",
366
+ ],
282
367
  )
283
368
  add_visualization_info(item, data, endpoint, time=t)
284
369
  link = collection.add_item(item)
@@ -292,8 +377,6 @@ def handle_WMS_endpoint(config, endpoint, data, catalog, wmts=False):
292
377
  endpoint["OverwriteBBox"],
293
378
  ]
294
379
  )
295
-
296
- add_visualization_info(collection, data, endpoint)
297
380
  add_collection_information(config, collection, data)
298
381
  add_to_catalog(collection, catalog, endpoint, data)
299
382
 
@@ -332,6 +415,9 @@ def handle_SH_WMS_endpoint(config, endpoint, data, catalog):
332
415
  properties={},
333
416
  geometry=None,
334
417
  datetime=parser.isoparse(time),
418
+ stac_extensions=[
419
+ "https://stac-extensions.github.io/web-map-links/v1.1.0/schema.json",
420
+ ],
335
421
  )
336
422
  add_visualization_info(item, data, endpoint, time=time)
337
423
  item_link = collection.add_item(item)
@@ -439,11 +525,6 @@ def get_or_create_collection(catalog, collection_id, data, config, endpoint=None
439
525
  id=collection_id,
440
526
  title=data["Title"],
441
527
  description=description,
442
- stac_extensions=[
443
- "https://stac-extensions.github.io/web-map-links/v1.1.0/schema.json",
444
- "https://stac-extensions.github.io/example-links/v0.0.1/schema.json",
445
- "https://stac-extensions.github.io/scientific/v1.0.0/schema.json",
446
- ],
447
528
  extent=extent,
448
529
  )
449
530
  return (collection, times)
@@ -478,6 +559,8 @@ def add_to_catalog(collection, catalog, endpoint, data):
478
559
  link.extra_fields["title"] = collection.title
479
560
  link.extra_fields["code"] = data["EodashIdentifier"]
480
561
  link.extra_fields["id"] = data["Name"]
562
+ if "Themes" in data:
563
+ link.extra_fields["themes"] = data["Themes"]
481
564
  # Check for summaries and bubble up info
482
565
  if collection.summaries.lists:
483
566
  for sum in collection.summaries.lists:
@@ -504,6 +587,8 @@ def add_extra_fields(stac_object, data):
504
587
  stac_object.extra_fields["agency"] = data["Agency"]
505
588
  if "yAxis" in data:
506
589
  stac_object.extra_fields["yAxis"] = data["yAxis"]
590
+ if "EodashIdentifier" in data:
591
+ stac_object.extra_fields["subcode"] = data["EodashIdentifier"]
507
592
  if "DataSource" in data:
508
593
  if "Spaceborne" in data["DataSource"]:
509
594
  if "Sensor" in data["DataSource"]["Spaceborne"]:
@@ -693,6 +778,61 @@ def handle_STAC_based_endpoint(config, endpoint, data, catalog, options, headers
693
778
  add_to_catalog(root_collection, catalog, endpoint, data)
694
779
 
695
780
 
781
+ def add_base_overlay_info(collection, config, data):
782
+ # check if default base layers defined
783
+ if "default_base_layers" in config:
784
+ with open("%s.yaml" % config["default_base_layers"]) as f:
785
+ base_layers = yaml.load(f, Loader=SafeLoader)
786
+ for layer in base_layers:
787
+ collection.add_link(create_web_map_link(layer, role="baselayer"))
788
+ # check if default overlay layers defined
789
+ if "default_overlay_layers" in config:
790
+ with open("%s.yaml" % config["default_overlay_layers"]) as f:
791
+ overlay_layers = yaml.load(f, Loader=SafeLoader)
792
+ for layer in overlay_layers:
793
+ collection.add_link(create_web_map_link(layer, role="overlay"))
794
+ if "BaseLayers" in data:
795
+ for layer in data["BaseLayers"]:
796
+ collection.add_link(create_web_map_link(layer, role="baselayer"))
797
+ if "OverlayLayers" in data:
798
+ for layer in data["OverlayLayers"]:
799
+ collection.add_link(create_web_map_link(layer, role="overlay"))
800
+ # TODO: possibility to overwrite default base and overlay layers
801
+
802
+
803
+ def create_web_map_link(layer, role):
804
+ extra_fields = {
805
+ "roles": [role],
806
+ "id": layer["id"],
807
+ }
808
+ if "default" in layer and layer["default"]:
809
+ extra_fields["roles"].append("default")
810
+ if "visible" in layer and layer["visible"]:
811
+ extra_fields["roles"].append("visible")
812
+ if "visible" in layer and not layer["visible"]:
813
+ extra_fields["roles"].append("invisible")
814
+
815
+ match layer["protocol"]:
816
+ case "wms":
817
+ # handle wms special config options
818
+ extra_fields["wms:layers"] = layer["layers"]
819
+ if "styles" in layer:
820
+ extra_fields["wms:styles"] = layer["styles"]
821
+ # TODO: handle wms dimensions extra_fields["wms:dimensions"]
822
+ case "wmts":
823
+ extra_fields["wmts:layer"] = layer["layer"]
824
+ # TODO: handle wmts dimensions extra_fields["wmts:dimensions"]
825
+
826
+ wml = Link(
827
+ rel=layer["protocol"],
828
+ target=layer["url"],
829
+ media_type="image/png" if "media_type" not in layer else layer["media_type"],
830
+ title=layer["name"],
831
+ extra_fields=extra_fields,
832
+ )
833
+ return wml
834
+
835
+
696
836
  def add_example_info(stac_object, data, endpoint, config):
697
837
  if "Services" in data:
698
838
  for service in data["Services"]:
@@ -839,6 +979,7 @@ def add_visualization_info(stac_object, data, endpoint, file_url=None, time=None
839
979
  instanceId = endpoint["InstanceId"]
840
980
  extra_fields = {
841
981
  "wms:layers": [endpoint["LayerId"]],
982
+ "role": ["data"],
842
983
  }
843
984
  if time != None:
844
985
  if endpoint["Name"] == "Sentinel Hub WMS":
@@ -861,7 +1002,9 @@ def add_visualization_info(stac_object, data, endpoint, file_url=None, time=None
861
1002
  Link(
862
1003
  rel="wms",
863
1004
  target="https://services.sentinel-hub.com/ogc/wms/%s" % (instanceId),
864
- media_type="text/xml",
1005
+ media_type=(
1006
+ endpoint["MimeType"] if "MimeType" in endpoint else "image/png"
1007
+ ),
865
1008
  title=data["Name"],
866
1009
  extra_fields=extra_fields,
867
1010
  )
@@ -869,7 +1012,10 @@ def add_visualization_info(stac_object, data, endpoint, file_url=None, time=None
869
1012
  # elif resource["Name"] == "GeoDB":
870
1013
  # pass
871
1014
  elif endpoint["Name"] == "WMS":
872
- extra_fields = {"wms:layers": [endpoint["LayerId"]]}
1015
+ extra_fields = {
1016
+ "wms:layers": [endpoint["LayerId"]],
1017
+ "role": ["data"],
1018
+ }
873
1019
  if time != None:
874
1020
  extra_fields["wms:dimensions"] = {
875
1021
  "TIME": time,
@@ -921,7 +1067,10 @@ def add_visualization_info(stac_object, data, endpoint, file_url=None, time=None
921
1067
  )
922
1068
  elif endpoint["Type"] == "WMTSCapabilities":
923
1069
  target_url = "%s" % (endpoint.get("EndPoint"),)
924
- extra_fields = {"wmts:layer": endpoint.get("LayerId")}
1070
+ extra_fields = {
1071
+ "wmts:layer": endpoint.get("LayerId"),
1072
+ "role": ["data"],
1073
+ }
925
1074
  dimensions = {}
926
1075
  if time != None:
927
1076
  dimensions["time"] = time
@@ -974,6 +1123,7 @@ def add_visualization_info(stac_object, data, endpoint, file_url=None, time=None
974
1123
  "matchKey": endpoint["MatchKey"],
975
1124
  "timeKey": endpoint["TimeKey"],
976
1125
  "source": endpoint["Source"],
1126
+ "role": ["data"],
977
1127
  },
978
1128
  )
979
1129
  )
@@ -995,7 +1145,7 @@ def process_STACAPI_Endpoint(
995
1145
  collection, _ = get_or_create_collection(
996
1146
  catalog, endpoint["CollectionId"], data, config, endpoint
997
1147
  )
998
- add_visualization_info(collection, data, endpoint)
1148
+ # add_visualization_info(collection, data, endpoint)
999
1149
 
1000
1150
  api = Client.open(endpoint["EndPoint"], headers=headers)
1001
1151
  if bbox == None:
@@ -1317,7 +1467,8 @@ def add_collection_information(config, collection, data):
1317
1467
  @dataclass
1318
1468
  class Options:
1319
1469
  catalogspath: str
1320
- collectionsspath: str
1470
+ collectionspath: str
1471
+ indicatorspath: str
1321
1472
  outputpath: str
1322
1473
  vd: bool
1323
1474
  ni: bool
@@ -1333,11 +1484,17 @@ class Options:
1333
1484
  default="./catalogs/",
1334
1485
  )
1335
1486
  @click.option(
1336
- "--collectionsspath",
1487
+ "--collectionspath",
1337
1488
  "-clp",
1338
1489
  help="path to collection configuration files",
1339
1490
  default="./collections/",
1340
1491
  )
1492
+ @click.option(
1493
+ "--indicatorspath",
1494
+ "-inp",
1495
+ help="path to indicaotr configuration files",
1496
+ default="./indicators/",
1497
+ )
1341
1498
  @click.option(
1342
1499
  "--outputpath",
1343
1500
  "-o",
@@ -1362,14 +1519,15 @@ class Options:
1362
1519
  nargs=-1,
1363
1520
  )
1364
1521
  def process_catalogs(
1365
- catalogspath, collectionsspath, outputpath, vd, ni, tn, collections
1522
+ catalogspath, collectionspath, indicatorspath, outputpath, vd, ni, tn, collections
1366
1523
  ):
1367
1524
  """STAC generator and harvester:
1368
1525
  This library goes over configured endpoints extracting as much information
1369
1526
  as possible and generating a STAC catalog with the information"""
1370
1527
  options = Options(
1371
1528
  catalogspath=catalogspath,
1372
- collectionsspath=collectionsspath,
1529
+ collectionspath=collectionspath,
1530
+ indicatorspath=indicatorspath,
1373
1531
  outputpath=outputpath,
1374
1532
  vd=vd,
1375
1533
  ni=ni,
eodash_catalog/utils.py CHANGED
@@ -27,12 +27,7 @@ ISO8601_PERIOD_REGEX = re.compile(
27
27
 
28
28
  def create_geojson_point(lon, lat):
29
29
  point = {"type": "Point", "coordinates": [lon, lat]}
30
-
31
- feature = {"type": "Feature", "geometry": point, "properties": {}}
32
-
33
- feature_collection = {"type": "FeatureCollection", "features": [feature]}
34
-
35
- return feature_collection
30
+ return {"type": "Feature", "geometry": point, "properties": {}}
36
31
 
37
32
 
38
33
  def retrieveExtentFromWMSWMTS(capabilties_url, layer, wmts=False):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eodash_catalog
3
- Version: 0.0.2
3
+ Version: 0.0.3
4
4
  Summary: This package is intended to help create a compatible STAC catalog for the eodash dashboard client. It supports configuration of multiple endpoint types for information extraction.
5
5
  Project-URL: Documentation, https://github.com/eodash/eodash_catalog#readme
6
6
  Project-URL: Issues, https://github.com/eodash/eodash_catalog/issues
@@ -0,0 +1,11 @@
1
+ eodash_catalog/__about__.py,sha256=XwGUn_fck5BM1feQDYsxZXExk2qm1bl87CumqjZGi90,137
2
+ eodash_catalog/__init__.py,sha256=_W_9emPYf6FUqc0P8L2SmADx6hGSd7PlQV3yRmCk5uM,115
3
+ eodash_catalog/duration.py,sha256=6rxALD9MZS6rTE1AZgvjrABr7zwg8S-kLc_w9BltvY0,11007
4
+ eodash_catalog/generate_indicators.py,sha256=oRZEITNeClFA3xiI-OJrTqC0eeUCCi3mhzY83i9IIN0,59442
5
+ eodash_catalog/sh_endpoint.py,sha256=KyZGmVrjZOCIuJizmYSy8VSWrfqqn2r-Ggh_8Q-s2vI,581
6
+ eodash_catalog/utils.py,sha256=NbwqHE5Qhd3Fke_fbl3HY803qSKJJKP1atTNrGPO7KY,6097
7
+ eodash_catalog-0.0.3.dist-info/METADATA,sha256=6rH58-poXqU6Z9-6l1SDKaNFFvm-OhxdKoqaXSKyiEg,2156
8
+ eodash_catalog-0.0.3.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
9
+ eodash_catalog-0.0.3.dist-info/entry_points.txt,sha256=kuUQrDG1PtYd8kPjf5XM6H_NtQd9Ozwl0jjiGtAvZSM,87
10
+ eodash_catalog-0.0.3.dist-info/licenses/LICENSE.txt,sha256=oJCW5zQxnFD-J0hGz6Zh5Lkpdk1oAndmWhseTmV224E,1107
11
+ eodash_catalog-0.0.3.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- eodash_catalog/__about__.py,sha256=cTzwMF0PAs7cIF-UCkp_XTlsxj_9LLhKjZkxXPGGSXY,137
2
- eodash_catalog/__init__.py,sha256=_W_9emPYf6FUqc0P8L2SmADx6hGSd7PlQV3yRmCk5uM,115
3
- eodash_catalog/duration.py,sha256=6rxALD9MZS6rTE1AZgvjrABr7zwg8S-kLc_w9BltvY0,11007
4
- eodash_catalog/generate_indicators.py,sha256=gTh2rRKAL1XkxMRdXoFKVLF-3InAW27ziu6bDn6a5DM,53345
5
- eodash_catalog/sh_endpoint.py,sha256=KyZGmVrjZOCIuJizmYSy8VSWrfqqn2r-Ggh_8Q-s2vI,581
6
- eodash_catalog/utils.py,sha256=tEzX5Nsy9yLpO0m9KWeMx0zRhEhCKStUq5Afche562w,6211
7
- eodash_catalog-0.0.2.dist-info/METADATA,sha256=3HXIEktGA9kyFzgdYWDVlbXuj4EZkfFM1_xLWTQ4H0s,2156
8
- eodash_catalog-0.0.2.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
9
- eodash_catalog-0.0.2.dist-info/entry_points.txt,sha256=kuUQrDG1PtYd8kPjf5XM6H_NtQd9Ozwl0jjiGtAvZSM,87
10
- eodash_catalog-0.0.2.dist-info/licenses/LICENSE.txt,sha256=oJCW5zQxnFD-J0hGz6Zh5Lkpdk1oAndmWhseTmV224E,1107
11
- eodash_catalog-0.0.2.dist-info/RECORD,,