eodash_catalog 0.1.14__tar.gz → 0.2.1__tar.gz

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.

Files changed (39) hide show
  1. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/.bumpversion.cfg +1 -1
  2. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/Dockerfile +1 -1
  3. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/PKG-INFO +1 -1
  4. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/src/eodash_catalog/__about__.py +1 -1
  5. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/src/eodash_catalog/endpoints.py +38 -6
  6. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/src/eodash_catalog/generate_indicators.py +16 -3
  7. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/src/eodash_catalog/stac_handling.py +9 -10
  8. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/src/eodash_catalog/utils.py +3 -1
  9. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/.dockerignore +0 -0
  10. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/.github/workflows/ci.yml +0 -0
  11. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/.github/workflows/python-publish.yml +0 -0
  12. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/.gitignore +0 -0
  13. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/.vscode/extensions.json +0 -0
  14. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/.vscode/settings.json +0 -0
  15. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/LICENSE.txt +0 -0
  16. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/README.md +0 -0
  17. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/pyproject.toml +0 -0
  18. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/requirements.txt +0 -0
  19. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/ruff.toml +0 -0
  20. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/src/eodash_catalog/__init__.py +0 -0
  21. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/src/eodash_catalog/duration.py +0 -0
  22. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/src/eodash_catalog/sh_endpoint.py +0 -0
  23. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/src/eodash_catalog/thumbnails.py +0 -0
  24. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/__init__.py +0 -0
  25. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/test-data/regional_forecast.json +0 -0
  26. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/test_generate.py +0 -0
  27. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/test_geoparquet.py +0 -0
  28. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/testing-catalogs/testing-json.json +0 -0
  29. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/testing-catalogs/testing.yaml +0 -0
  30. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/testing-collections/test_CROPOMAT1.yaml +0 -0
  31. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/testing-collections/test_locations_processing.json +0 -0
  32. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/testing-collections/test_see_solar_energy.yaml +0 -0
  33. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/testing-collections/test_tif_demo_1.yaml +0 -0
  34. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/testing-collections/test_tif_demo_1_json.json +0 -0
  35. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/testing-collections/test_tif_demo_2.yaml +0 -0
  36. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/testing-collections/test_wms_no_time.yaml +0 -0
  37. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/testing-indicators/test_indicator.yaml +0 -0
  38. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/testing-layers/baselayers.yaml +0 -0
  39. {eodash_catalog-0.1.14 → eodash_catalog-0.2.1}/tests/testing-layers/overlays.yaml +0 -0
@@ -1,5 +1,5 @@
1
1
  [bumpversion]
2
- current_version = 0.1.14
2
+ current_version = 0.2.1
3
3
  commit = True
4
4
  tag = True
5
5
  parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-(?P<release>[a-z]+)\.(?P<build>\d+))?
@@ -29,4 +29,4 @@ RUN eodash_catalog --help
29
29
 
30
30
  CMD ["eodash_catalog"]
31
31
 
32
- LABEL version="0.1.14"
32
+ LABEL version="0.2.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eodash_catalog
3
- Version: 0.1.14
3
+ Version: 0.2.1
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
@@ -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.1.14"
4
+ __version__ = "0.2.1"
@@ -9,7 +9,7 @@ from itertools import groupby
9
9
  from operator import itemgetter
10
10
 
11
11
  import requests
12
- from pystac import Asset, Catalog, Collection, Item, Link, SpatialExtent, Summaries
12
+ from pystac import Asset, Catalog, Collection, Item, Link, SpatialExtent, Summaries, TemporalExtent
13
13
  from pystac_client import Client
14
14
  from shapely import wkt
15
15
  from shapely.geometry import mapping
@@ -31,6 +31,7 @@ from eodash_catalog.utils import (
31
31
  filter_time_entries,
32
32
  format_datetime_to_isostring_zulu,
33
33
  generate_veda_cog_link,
34
+ merge_bboxes,
34
35
  parse_datestring_to_tz_aware_datetime,
35
36
  replace_with_env_variables,
36
37
  retrieveExtentFromWCS,
@@ -499,6 +500,7 @@ def handle_GeoDB_endpoint(
499
500
  sorted_locations = sorted(response, key=itemgetter("aoi_id"))
500
501
  cities = []
501
502
  countries = []
503
+ input_data = endpoint_config.get("InputData")
502
504
  for key, value in groupby(sorted_locations, key=itemgetter("aoi_id")):
503
505
  # Finding min and max values for date
504
506
  values = list(value)
@@ -535,7 +537,6 @@ def handle_GeoDB_endpoint(
535
537
  locations_collection = get_or_create_collection(
536
538
  collection, key, sc_config, catalog_config, endpoint_config
537
539
  )
538
- input_data = endpoint_config.get("InputData")
539
540
  if input_data:
540
541
  for v in values:
541
542
  # add items based on inputData fields for each time step available in values
@@ -598,9 +599,16 @@ def handle_GeoDB_endpoint(
598
599
  # add_visualization_info(
599
600
  # item, collection_config, endpoint_config, file_url=first_match.get("FileUrl")
600
601
  # )
602
+ locations_collection.update_extent_from_items()
603
+ else:
604
+ # set spatial extent from geodb
605
+ locations_collection.extent.spatial.bboxes = [bbox]
606
+ # set time extent from geodb
607
+ individual_datetimes = [datetime.fromisoformat(v["time"]) for v in values]
608
+ time_extent = [min(individual_datetimes), max(individual_datetimes)]
609
+ locations_collection.extent.temporal = TemporalExtent([time_extent])
601
610
  locations_collection.extra_fields["subcode"] = key
602
611
  link = collection.add_child(locations_collection)
603
- locations_collection.update_extent_from_items()
604
612
  # collection.update_extent_from_items()
605
613
  # bubble up information we want to the link
606
614
  link.extra_fields["id"] = key
@@ -623,8 +631,32 @@ def handle_GeoDB_endpoint(
623
631
  add_collection_information(catalog_config, collection, collection_config)
624
632
  add_example_info(collection, collection_config, endpoint_config, catalog_config)
625
633
  collection.extra_fields["locations"] = True
626
-
627
- collection.update_extent_from_items()
634
+ if not input_data:
635
+ # we have no items, extents of collection need to be updated manually
636
+ merged_bbox = merge_bboxes(
637
+ [
638
+ c_child.extent.spatial.bboxes[0]
639
+ for c_child in collection.get_children()
640
+ if isinstance(c_child, Collection)
641
+ ]
642
+ )
643
+ collection.extent.spatial.bboxes = [merged_bbox]
644
+ # Add bbox extents from children
645
+ for c_child in collection.get_children():
646
+ if isinstance(c_child, Collection) and merged_bbox != c_child.extent.spatial.bboxes[0]:
647
+ collection.extent.spatial.bboxes.append(c_child.extent.spatial.bboxes[0])
648
+ # set time extent of collection
649
+ individual_datetimes = []
650
+ for c_child in collection.get_children():
651
+ if isinstance(c_child, Collection) and isinstance(
652
+ c_child.extent.temporal.intervals[0], list
653
+ ):
654
+ individual_datetimes.extend(c_child.extent.temporal.intervals[0]) # type: ignore
655
+ time_extent = [min(individual_datetimes), max(individual_datetimes)]
656
+ collection.extent.temporal = TemporalExtent([time_extent])
657
+ else:
658
+ # we can update from items
659
+ collection.update_extent_from_items()
628
660
  collection.summaries = Summaries(
629
661
  {
630
662
  "cities": cities,
@@ -799,7 +831,7 @@ def add_visualization_info(
799
831
  if dimensions_config := endpoint_config.get("Dimensions", {}):
800
832
  for key, value in dimensions_config.items():
801
833
  # special replace for world_settlement_footprint
802
- if collection_config["EodashIdentifier"] == "WSF":
834
+ if collection_config.get("EodashIdentifier") == "WSF":
803
835
  value = value.replace(
804
836
  "{time}", datetimes is not None and str(datetimes[0].year) or "{time}"
805
837
  )
@@ -6,11 +6,12 @@ Indicator generator to harvest information from endpoints and generate catalog
6
6
 
7
7
  import os
8
8
  import time
9
+ from datetime import datetime
9
10
  from typing import Any
10
11
 
11
12
  import click
12
13
  from dotenv import load_dotenv
13
- from pystac import Catalog, CatalogType, Collection, Link, Summaries
14
+ from pystac import Catalog, CatalogType, Collection, Link, Summaries, TemporalExtent
14
15
  from pystac.layout import TemplateLayoutStrategy
15
16
  from pystac.validation import validate_all
16
17
  from structlog import get_logger
@@ -197,6 +198,17 @@ def process_indicator_file(
197
198
  for c_child in parent_indicator.get_children():
198
199
  if isinstance(c_child, Collection) and merged_bbox != c_child.extent.spatial.bboxes[0]:
199
200
  parent_indicator.extent.spatial.bboxes.append(c_child.extent.spatial.bboxes[0])
201
+ # aggregate all time extents from the child collections and make it a indicator extent
202
+ individual_datetimes: list[datetime] = []
203
+ for c_child in parent_indicator.get_children():
204
+ if isinstance(c_child, Collection) and isinstance(
205
+ c_child.extent.temporal.intervals[0], list
206
+ ):
207
+ individual_datetimes.extend(c_child.extent.temporal.intervals[0]) # type: ignore
208
+ # filter out None
209
+ individual_datetimes = list(filter(lambda x: x is not None, individual_datetimes))
210
+ time_extent = [min(individual_datetimes), max(individual_datetimes)]
211
+ parent_indicator.extent.temporal = TemporalExtent([time_extent])
200
212
  # extract collection information and add it to summary indicator level
201
213
  extract_indicator_info(parent_indicator)
202
214
  add_process_info(parent_indicator, catalog_config, indicator_config)
@@ -278,7 +290,7 @@ def process_collection_file(
278
290
  else:
279
291
  raise ValueError("Type of Resource is not supported")
280
292
  if collection:
281
- add_single_item_if_collection_empty(collection)
293
+ add_single_item_if_collection_empty(endpoint_config, collection)
282
294
  add_projection_info(endpoint_config, collection)
283
295
  add_to_catalog(collection, catalog, endpoint_config, collection_config, disable)
284
296
  else:
@@ -395,7 +407,8 @@ def add_to_catalog(
395
407
  if collection_config.get("Subtitle"):
396
408
  link.extra_fields["subtitle"] = collection_config["Subtitle"]
397
409
  link.extra_fields["title"] = collection.title
398
- link.extra_fields["code"] = collection_config["EodashIdentifier"]
410
+ if collection_config.get("EodashIdentifier"):
411
+ link.extra_fields["code"] = collection_config["EodashIdentifier"]
399
412
  link.extra_fields["id"] = collection_config["Name"]
400
413
  if collection_config.get("Themes"):
401
414
  link.extra_fields["themes"] = collection_config["Themes"]
@@ -1,4 +1,4 @@
1
- from datetime import datetime
1
+ from datetime import datetime, timezone
2
2
 
3
3
  import requests
4
4
  import spdx_lookup as lookup
@@ -44,7 +44,7 @@ def get_or_create_collection(
44
44
  spatial_extent,
45
45
  ]
46
46
  )
47
- temporal_extent = TemporalExtent([[datetime.now(), None]])
47
+ temporal_extent = TemporalExtent([[datetime.now(tz=timezone.utc), None]])
48
48
  if endpoint_config:
49
49
  times_datetimes = get_collection_datetimes_from_config(endpoint_config)
50
50
  if len(times_datetimes) > 0:
@@ -106,8 +106,8 @@ def create_service_link(endpoint_config: dict, catalog_config: dict) -> Link:
106
106
  extra_fields["eox:flatstyle"] = []
107
107
  for flatstyle_config in endpoint_config["Flatstyle"]:
108
108
  flatstyle_obj = {
109
- "Identifier": flatstyle_config.get("Identifier"),
110
- "Url": get_full_url(flatstyle_config.get("Url"), catalog_config),
109
+ "id": flatstyle_config.get("Identifier"),
110
+ "url": get_full_url(flatstyle_config.get("Url"), catalog_config),
111
111
  }
112
112
  extra_fields["eox:flatstyle"].append(flatstyle_obj)
113
113
  else:
@@ -363,18 +363,17 @@ def add_process_info(collection: Collection, catalog_config: dict, collection_co
363
363
  },
364
364
  )
365
365
  collection.add_link(sl)
366
+ has_geodb = any(
367
+ item.get("Name") == "GeoDB" for item in collection_config.get("Resources", [])
368
+ )
366
369
  # adding additional service links
367
- if collection_config["Name"] == "GeoDB" and collection_config.get("Process", {}).get(
368
- "EndPoints"
369
- ):
370
+ if has_geodb and collection_config.get("Process", {}).get("EndPoints"):
370
371
  for endpoint in collection_config["Process"]["EndPoints"]:
371
372
  collection.add_link(create_service_link(endpoint, catalog_config))
372
373
 
373
374
  # for geodb collections now based on locations, we want to make sure
374
375
  # also manually defined processes are added to the collection
375
- if collection_config["Name"] == "GeoDB" and collection_config.get("Process", {}).get(
376
- "VegaDefinition"
377
- ):
376
+ if has_geodb and collection_config.get("Process", {}).get("VegaDefinition"):
378
377
  collection.extra_fields["eodash:vegadefinition"] = get_full_url(
379
378
  collection_config["Process"]["VegaDefinition"], catalog_config
380
379
  )
@@ -335,7 +335,7 @@ class Options:
335
335
  collections: list[str]
336
336
 
337
337
 
338
- def add_single_item_if_collection_empty(collection: Collection) -> None:
338
+ def add_single_item_if_collection_empty(endpoint_config: dict, collection: Collection) -> None:
339
339
  for link in collection.links:
340
340
  if link.rel in [RelType.CHILD, RelType.ITEM]:
341
341
  break
@@ -350,6 +350,8 @@ def add_single_item_if_collection_empty(collection: Collection) -> None:
350
350
  end_datetime=datetime.now(tz=pytztimezone("UTC")),
351
351
  )
352
352
  collection.add_item(item)
353
+ if not endpoint_config.get("OverwriteBBox"):
354
+ collection.update_extent_from_items()
353
355
 
354
356
 
355
357
  def replace_with_env_variables(s: str) -> str: