Skip to content

Allow polygon shape to consist of disjoint parts - #14376

Draft
achaikou wants to merge 1 commit into
equinor:mainfrom
achaikou:seismic_multipolygon
Draft

Allow polygon shape to consist of disjoint parts#14376
achaikou wants to merge 1 commit into
equinor:mainfrom
achaikou:seismic_multipolygon

Conversation

@achaikou

@achaikou achaikou commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Issue
Resolves #14297

Approach
Per user's requirement polygon file may contain multiple disjoint polygons. For seismic, we need keep points that are inside one or more polygons.

Polygon shape is for now used only in seismic and seismic is unreleased yet, so we are free to change it.

  • PR title captures the intent of the changes, and is fitting for release notes.
  • Added appropriate release note label
  • Commit history is consistent and clean, in line with the contribution guidelines.
  • Make sure unit tests pass locally after every commit (git rebase -i main --exec 'just rapid-tests')

When applicable

  • When screenshots are changed: Review screenshot-PR in ert-testdata,
    merge screenshot-PR in ert-testdata before merging this PR.
  • When there are user facing changes: Updated documentation
  • New behavior or changes to existing untested code: Ensured that unit tests are added (See Ground Rules).
  • Large PR: Prepare changes in small commits for more convenient review
  • Bug fix: Add regression test for the bug
  • Bug fix: Add backport label to latest release (format: 'backport release-branch-name')

@achaikou achaikou added the release-notes:unreleased-feature-changes PR with changes to a feature which is not yet released. Not for introduction of new features! label Sep 4, 2026
@achaikou
achaikou requested a lite review from Copilot September 4, 2026 15:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new union-based parsing can produce polygons with holes, but the current vertex serialization/re-hydration cannot represent holes, which can lead to incorrect contains() results.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates PolygonShapeConfig to support boundary files containing multiple polygons (treated as the union of all polygons), enabling seismic observation filtering against disjoint polygon parts.

Changes:

  • Change PolygonShapeConfig.vertices from a single ring to a list of polygon rings (multipolygon representation).
  • Update polygon parsing to build a union geometry from multiple polygons and preserve disjoint parts while merging overlaps.
  • Expand unit test coverage for disjoint, overlapping, and normalization/simplification behavior for multipolygons, and update seismic QC tests accordingly.
File summaries
File Description
src/ert/config/_shapes.py Switch polygon handling to multipolygons; union multiple polygons from file and update containment to work across all parts.
tests/ert/unit_tests/config/test_shapes.py Update expectations for nested vertex structure and add tests for disjoint/overlapping/normalized multipolygons.
tests/ert/unit_tests/config/test_observation_quality_control.py Verify seismic QC keeps observations inside any of multiple boundary polygons.
tests/ert/unit_tests/config/test_observation_declaration.py Update boundary parsing assertions to the new nested vertex representation.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/ert/config/_shapes.py Outdated
@codecov-commenter

codecov-commenter commented Sep 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.05%. Comparing base (72b8fd4) to head (190e35c).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #14376      +/-   ##
==========================================
- Coverage   91.06%   91.05%   -0.01%     
==========================================
  Files         495      495              
  Lines       36139    36146       +7     
==========================================
+ Hits        32910    32913       +3     
- Misses       3229     3233       +4     
Flag Coverage Δ
cli-tests 35.58% <15.78%> (-0.01%) ⬇️
fuzz 43.68% <15.78%> (-0.01%) ⬇️
gui-tests 58.38% <15.78%> (-0.02%) ⬇️
performance-and-unit-tests 80.99% <100.00%> (-0.01%) ⬇️
test 45.35% <15.78%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/ert/config/_shapes.py 96.92% <100.00%> (+0.37%) ⬆️

... and 1 file with indirect coverage changes

@codspeed-hq

codspeed-hq Bot commented Sep 4, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 36 untouched benchmarks


Comparing achaikou:seismic_multipolygon (037798a) with main (72b8fd4)

Open in CodSpeed

Per user's requirement polygon file may contain multiple disjoint
polygons. For seismic, we need keep points that are inside one or more
polygons.

Polygon shape is for now used only in seismic and seismic is unreleased
yet, so we are free to change it without considerations.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The current multipolygon cleaning/parsing path can raise unintended runtime exceptions (and produce nondeterministic equality) due to insufficient geometry-type validation and use of assertions for config validation.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

src/ert/config/_shapes.py:103

  • Using assert isinstance(..., MultiPolygon) for WKT parsing can raise an AssertionError for user-supplied/serialized shapes (e.g. if wkt is a POLYGON). Since PolygonShapeConfig is a config model, this should fail with a regular exception (or accept POLYGON by wrapping it) rather than an assertion that can be stripped with -O.
    def _polygon(self) -> shapely.MultiPolygon:
        multipolygon = shapely.from_wkt(self.wkt)
        assert isinstance(multipolygon, shapely.MultiPolygon)
        shapely.prepare(multipolygon)
        return multipolygon
  • Files reviewed: 4/4 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread src/ert/config/_shapes.py
Comment on lines +87 to 95
cleaned_polygons = [
cast(
shapely.Polygon,
geom.simplify(tolerance=cls.TOLERANCE).normalize(),
)
for geom in multipolygon.geoms
]
multipolygon = shapely.MultiPolygon(cleaned_polygons)

Comment on lines +1251 to +1252
expected = "MULTIPOLYGON Z (((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)))"
assert boundary.wkt == expected
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-notes:unreleased-feature-changes PR with changes to a feature which is not yet released. Not for introduction of new features!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support multiple polygons in seismic boundary file

3 participants