Skip to content

All test_index_cloning tests fail with Antimeridian 0.4.5 #2299

@pjonsson

Description

@pjonsson

Antimeridian 0.4.5 started erroring if the geometry was unfixable, and all test_index_cloning tests fail for that reason. Here's the output from one of the tests:

cfg_env_pair = (<datacube.cfg.api.ODCEnvironment object at 0x70a4bb4c4cb0>, <datacube.cfg.api.ODCEnvironment object at 0x70a4bb4c4b90>)
uninitialised_postgres_db_pair = (PostgisDb<engine=Engine(postgresql://opendatacube:***@postgres:35432/pgisintegration)>, PostgresDb<engine=Engine(postgresql+psycopg://opendatacube:***@postgres:35432/pgintegration)>)
extended_eo3_metadata_type_doc = {'dataset': {'creation_dt': ['properties', 'odc:processing_datetime'], 'format': ['properties', 'odc:file_format'], 'g...tial', 'projection'], 'id': ['id'], ...}, 'description': 'EO3 for ARD Landsat Collection 3', 'name': 'eo3_landsat_ard'}
base_eo3_product_doc = {'description': 'Geoscience Australia Landsat Water Observations Collection 3', 'license': 'CC-BY-4.0', 'measurements'...a': {'product': {'name': 'ga_ls_wo_3'}, 'properties': {'odc:file_format': 'GeoTIFF', 'odc:product_family': 'wo'}}, ...}
extended_eo3_product_doc = {'description': 'Geoscience Australia Landsat 8 Operational Land Imager and Thermal Infra-Red Scanner Analysis Ready D...8c_ard_3'}, 'properties': {'eo:platform': 'landsat-8', 'odc:producer': 'ga.gov.au', 'odc:product_family': 'ard'}}, ...}
africa_s2_product_doc = {'description': 'Sentinel-2a and Sentinel-2b imagery, processed to Level 2A (Surface Reflectance) and converted to Clo...t16', 'name': 'B06', 'nodata': 0, ...}, ...], 'metadata': {'product': {'name': 's2_l2a'}}, 'metadata_type': 'eo3', ...}
eo3_ls8_dataset_doc = ({'$schema': 'https://schemas.opendatacube.org/dataset', 'accessories': {'checksum:sha1': {'path': 'ga_ls8c_ard_3-0-0_...://dea-public-data/baseline/ga_ls8c_ard_3/090/086/2016/05/12/ga_ls8c_ard_3-0-0_090086_2016-05-12_final.stac-item.json')
eo3_ls8_dataset2_doc = ({'$schema': 'https://schemas.opendatacube.org/dataset', 'accessories': {'checksum:sha1': {'path': 'ga_ls8c_ard_3-0-0_...://dea-public-data/baseline/ga_ls8c_ard_3/090/086/2016/05/28/ga_ls8c_ard_3-0-0_090086_2016-05-28_final.stac-item.json')
eo3_ls8_dataset3_doc = ({'$schema': 'https://schemas.opendatacube.org/dataset', 'crs': 'epsg:32653', 'geometry': {'coordinates': [[[388119.0,...://dea-public-data/baseline/ga_ls8c_ard_3/101/077/2013/04/04/ga_ls8c_ard_3-0-0_101077_2013-04-04_final.stac-item.json')
eo3_ls8_dataset4_doc = ({'$schema': 'https://schemas.opendatacube.org/dataset', 'crs': 'epsg:32653', 'geometry': {'coordinates': [[[476439.0,...://dea-public-data/baseline/ga_ls8c_ard_3/101/077/2013/07/21/ga_ls8c_ard_3-0-0_101077_2013-07-21_final.stac-item.json')
eo3_wo_dataset_doc = ({'$schema': 'https://schemas.opendatacube.org/dataset', 'accessories': {'checksum:sha1': {'path': 'ga_ls_wo_3_090086_...s3://dea-public-data/derivative/ga_ls_wo_3/1-6-0/090/086/2016/05/12/ga_ls_wo_3_090086_2016-05-12_final.stac-item.json')
eo3_africa_dataset_doc = ({'$schema': 'https://schemas.opendatacube.org/dataset', 'accessories': {'info': {'path': 'https://roda.sentinel-hub.c... 's3://deafrica-sentinel-2/sentinel-s2-l2a-cogs/37/M/CQ/2022/8/S2A_37MCQ_20220808_0_L2A/S2A_37MCQ_20220808_0_L2A.json')
eo3_africa_dataset2_doc = ({'$schema': 'https://schemas.opendatacube.org/dataset', 'accessories': {'info': {'path': 'https://roda.sentinel-hub.c... 's3://deafrica-sentinel-2/sentinel-s2-l2a-cogs/39/M/XR/2020/9/S2A_39MXR_20200909_0_L2A/S2A_39MXR_20200909_0_L2A.json')

    @pytest.fixture
    def index_pair_populated_empty(
        cfg_env_pair: tuple[ODCEnvironment, ...],
        uninitialised_postgres_db_pair,
        extended_eo3_metadata_type_doc,
        base_eo3_product_doc,
        extended_eo3_product_doc,
        africa_s2_product_doc,
        eo3_ls8_dataset_doc,
        eo3_ls8_dataset2_doc,
        eo3_ls8_dataset3_doc,
        eo3_ls8_dataset4_doc,
        eo3_wo_dataset_doc,
        eo3_africa_dataset_doc,
        eo3_africa_dataset2_doc,
    ) -> Generator[tuple]:
        populated_cfg, empty_cfg = cfg_env_pair
        populated_idx = index_connect(populated_cfg, validate_connection=False)
        empty_idx = index_connect(empty_cfg, validate_connection=False)
        populated_idx.init_db()
        empty_idx.init_db(with_default_types=False)
        assert list(empty_idx.products.get_all()) == []
        assert list(populated_idx.products.get_all()) == []
        # Populate the populated index
        populated_idx.metadata_types.add(
            populated_idx.metadata_types.from_doc(extended_eo3_metadata_type_doc)
        )
        for prod_doc in (
            base_eo3_product_doc,
            extended_eo3_product_doc,
            africa_s2_product_doc,
        ):
            populated_idx.products.add_document(prod_doc)
        for ds_doc, ds_path in (
            eo3_ls8_dataset_doc,
            eo3_ls8_dataset2_doc,
            eo3_ls8_dataset3_doc,
            eo3_ls8_dataset4_doc,
            eo3_wo_dataset_doc,
            eo3_africa_dataset_doc,
            eo3_africa_dataset2_doc,
        ):
>           doc_to_ds(populated_idx, ds_doc["product"]["name"], ds_doc, ds_path)

integration_tests/conftest.py:715:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
integration_tests/conftest.py:310: in doc_to_ds
    index.datasets.add(ds, with_lineage=index.supports_lineage)
datacube/index/postgis/_datasets.py:192: in add
    transaction.update_spindex(dsids=[dataset.id])
datacube/drivers/postgis/_api.py:982: in update_spindex
    self.insert_dataset_spatial(dsid, crs, geom)
datacube/drivers/postgis/_api.py:377: in insert_dataset_spatial
    values = generate_dataset_spatial_values(dataset_id, crs, extent)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
datacube/drivers/postgis/_spatial.py:269: in generate_dataset_spatial_values
    extent = sanitise_extent(extent, crs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
datacube/drivers/postgis/_spatial.py:258: in sanitise_extent
    return Geom(fix_shape(prelim.geom), crs=crs)
                ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.12/site-packages/antimeridian/_implementation.py:217: in fix_shape
    fix_polygon(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

polygon = <POLYGON ((52.89 -4.056, 52.89 -4.056, 52.89 -4.055, 52.89 -4.056))>

    def fix_polygon(
        polygon: Polygon,
        *,
        force_north_pole: bool = False,
        force_south_pole: bool = False,
        fix_winding: bool = True,
        great_circle: bool = True,
    ) -> Union[Polygon, MultiPolygon]:
        """Fixes a [shapely.Polygon][].

        If the input polygon is wound clockwise, it will be fixed to be wound
        counterclockwise _unless_ `fix_winding` is `False` in which case it
        will be corrected by adding a counterclockwise polygon from (-180, -90) to
        (180, 90) as its exterior.

        In rare cases, the underlying algorithm might need a little help to fix the polygon.
        For example, a polygon that just barely crosses over a pole might have very
        few points at high latitudes, leading to ambiguous antimeridian crossing
        points and invalid geometries. We provide two flags, `force_north_pole`
        and `force_south_pole` for those cases. Most users can ignore these
        flags.

        If either `force_north_pole` or `force_south_pole` is `True`
        `fix_winding` is set to `False`

        Args:
            polygon: The input polygon
            force_north_pole: If the polygon crosses the antimeridian, force the
                joined segments to enclose the north pole.
            force_south_pole: If the polygon crosses the antimeridian, force the
                joined segments to enclose the south pole.
            fix_winding: If the polygon is wound clockwise, reverse its
                coordinates before applying the algorithm.
            great_circle: Compute meridian crossings on the sphere rather than
                using 2D geometry.

        Returns:
            The fixed polygon, either as a single polygon or a multi-polygon (if it
                was split)
        """
        if force_north_pole or force_south_pole:
            fix_winding = False
        polygons = fix_polygon_to_list(
            polygon,
            force_north_pole=force_north_pole,
            force_south_pole=force_south_pole,
            fix_winding=fix_winding,
            great_circle=great_circle,
        )
        if len(polygons) == 1:
            polygon = polygons[0]
            if shapely.is_ccw(polygon.exterior):
                return polygon
            else:
                pole_covering_polygon = Polygon(
                    [(-180, 90), (-180, -90), (180, -90), (180, 90)],
                    [polygon.exterior.coords],
                )
                if shapely.is_valid(pole_covering_polygon):
                    return pole_covering_polygon
                else:
>                   raise ValueError(
                        "Fixed polygon is invalid, check your input polygon for validity. "
                        "Reason your polygon is invalid: "
                        + shapely.is_valid_reason(polygon)
                    )
E                   ValueError: Fixed polygon is invalid, check your input polygon for validity. Reason your polygon is invalid: Too few points in geometry component[52.8896991867137 -4.05589014056015]

.venv/lib/python3.12/site-packages/antimeridian/_implementation.py:368: ValueError
___ ERROR at setup of test_index_clone_small_batch[datacube_env_name_pair3] ____

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions