Skip to content

feat: empaia parser#48

Open
Adames4 wants to merge 1 commit intomainfrom
feature/empaia-parser
Open

feat: empaia parser#48
Adames4 wants to merge 1 commit intomainfrom
feature/empaia-parser

Conversation

@Adames4
Copy link
Copy Markdown
Member

@Adames4 Adames4 commented Mar 25, 2026

Parser for annotations downloaded from EMPAIA.

Summary by CodeRabbit

  • New Features

    • EMPAIAParser now available for processing EMPAIA annotation files, enabling extraction of polygon and point geometries with flexible name-based filtering.
  • Documentation

    • Added reference documentation page for the EMPAIA parser.
  • Chores

    • Version updated to 1.3.1.
    • Project author list expanded with additional contributor credits.

@Adames4 Adames4 self-assigned this Mar 25, 2026
@Adames4 Adames4 requested review from a team March 25, 2026 15:57
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 25, 2026

📝 Walkthrough

Walkthrough

The PR introduces the EMPAIAParser class for loading and filtering EMPAIA JSON annotation data, including documentation, tests, and a version bump to 1.3.1. It also modernizes Shapely imports in existing parser code.

Changes

Cohort / File(s) Summary
Documentation & Metadata
docs/reference/parsers/empaia.md, pyproject.toml
Added API reference documentation for EMPAIAParser; bumped package version to 1.3.1 and added four new authors.
Parser Module Updates
ratiopath/parsers/__init__.py
Added EMPAIAParser to module imports and __all__ export list.
New Parser Implementation
ratiopath/parsers/empaia_parser.py
Implemented EMPAIAParser class with get_polygons() and get_points() methods; filters EMPAIA JSON annotations by regex name and geometry type, converting coordinates to Shapely objects.
Existing Parser Modernization
ratiopath/parsers/asap_parser.py
Updated Shapely imports to modern API (shapely.Point, shapely.Polygon); added explicit -> None return type annotation to __init__.
Test Coverage
tests/test_parsers.py
Added comprehensive TestEMPAIAParser suite validating polygon/point retrieval, name filtering, and coordinate handling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~28 minutes

Possibly related PRs

  • #35: Version bump PR that also modifies pyproject.toml package version metadata.
  • #38: Earlier version bump PR (1.1.2→1.2.0) with similar pyproject.toml metadata updates.

Suggested reviewers

  • JakubPekar
  • vejtek

Poem

🐰 A parser hops in, EMPAIA's friend,
Filtering shapes from JSON's blend,
Polygons bloom and points align,
Version bumped, the codebase shines! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main addition in the changeset: a new parser for EMPAIA annotations with supporting documentation, exports, and tests.
Docstring Coverage ✅ Passed Docstring coverage is 91.67% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/empaia-parser

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the library's annotation parsing capabilities by integrating a new parser for EMPAIA-formatted JSON files, allowing for the extraction of both polygon and point annotations. Alongside this new feature, the project's version has been updated, and new contributors have been acknowledged. Minor code improvements were also applied to an existing parser for better consistency and type hinting.

Highlights

  • New Feature: EMPAIA Parser: Introduced a new EMPAIAParser to handle annotations from EMPAIA-formatted JSON files, supporting both polygon and point geometries.
  • Project Metadata Update: The project version has been incremented to 1.3.1, and the list of authors in pyproject.toml has been expanded to include new contributors.
  • Code Refinement and Consistency: Updated the ASAPParser to use a more direct shapely import and added a return type hint to its constructor for improved code clarity.
  • Comprehensive Test Coverage: Added a dedicated test suite for the new EMPAIAParser, ensuring its functionality for extracting polygons and points, including filtering capabilities.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
ratiopath/parsers/empaia_parser.py (2)

31-49: Note: re.match() only matches at the start of the string.

This means name="1" won't match "Annotation 1". If you intend for the pattern to match anywhere in the name, use re.search() instead. However, if matching from the start is intentional (consistent with how other parsers work), this is fine.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ratiopath/parsers/empaia_parser.py` around lines 31 - 49, The current
_get_filtered_annotations function uses name_regex.match(...) which only checks
the start of annotation["name"]; if you want the provided pattern to match
anywhere in the string, replace the use of re.match with re.search (i.e.,
compile the pattern into name_regex and call
name_regex.search(annotation["name"]) when testing annotations in
self.annotations["items"]) so names like "Annotation 1" will match a pattern
"1"; if start-anchored matching is desired, leave as-is but add a comment
clarifying the intentional behavior.

60-66: Avoid creating intermediate Point objects when constructing Polygon.

Shapely's Polygon constructor accepts coordinate tuples directly. Creating Point objects adds unnecessary overhead.

♻️ Suggested simplification
 for annotation in self._get_filtered_annotations(name, "polygon"):
-    yield Polygon(
-        [
-            Point(float(coordinate[0]), float(coordinate[1]))
-            for coordinate in annotation["coordinates"]
-        ]
-    )
+    yield Polygon(
+        [
+            (float(coord[0]), float(coord[1]))
+            for coord in annotation["coordinates"]
+        ]
+    )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ratiopath/parsers/empaia_parser.py` around lines 60 - 66, The code is
creating intermediate Point objects when building a Polygon; update the polygon
construction in the loop over self._get_filtered_annotations(name, "polygon") to
pass coordinate tuples directly to shapely.geometry.Polygon instead of creating
Point instances: transform annotation["coordinates"] into an iterable of
(float(x), float(y)) tuples and pass that to Polygon (no Point instantiation),
keeping the surrounding loop and yield as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@ratiopath/parsers/empaia_parser.py`:
- Around line 31-49: The current _get_filtered_annotations function uses
name_regex.match(...) which only checks the start of annotation["name"]; if you
want the provided pattern to match anywhere in the string, replace the use of
re.match with re.search (i.e., compile the pattern into name_regex and call
name_regex.search(annotation["name"]) when testing annotations in
self.annotations["items"]) so names like "Annotation 1" will match a pattern
"1"; if start-anchored matching is desired, leave as-is but add a comment
clarifying the intentional behavior.
- Around line 60-66: The code is creating intermediate Point objects when
building a Polygon; update the polygon construction in the loop over
self._get_filtered_annotations(name, "polygon") to pass coordinate tuples
directly to shapely.geometry.Polygon instead of creating Point instances:
transform annotation["coordinates"] into an iterable of (float(x), float(y))
tuples and pass that to Polygon (no Point instantiation), keeping the
surrounding loop and yield as-is.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7e7888e3-652f-47f6-89b0-b8ba4679d90a

📥 Commits

Reviewing files that changed from the base of the PR and between 4f8c69b and 90eb060.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • docs/reference/parsers/empaia.md
  • pyproject.toml
  • ratiopath/parsers/__init__.py
  • ratiopath/parsers/asap_parser.py
  • ratiopath/parsers/empaia_parser.py
  • tests/test_parsers.py

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new EMPAIAParser for handling EMPAIA format annotation files, supporting both polygon and point features. The changes include the parser implementation, integration into the package's __init__.py, and comprehensive unit tests. The project version has been updated to 1.3.1, and new authors have been added. Feedback includes suggestions to improve efficiency in EMPAIAParser.get_polygons by directly using coordinate tuples for shapely.Polygon construction and to enhance the robustness of polygon assertions in tests by verifying the full closed coordinate sequence.

Comment on lines +61 to +66
yield Polygon(
[
Point(float(coordinate[0]), float(coordinate[1]))
for coordinate in annotation["coordinates"]
]
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

For improved efficiency and more idiomatic shapely usage, it's better to create a list of coordinate tuples directly, rather than creating intermediate shapely.Point objects. The Polygon constructor is optimized to work with sequences of tuples.

Suggested change
yield Polygon(
[
Point(float(coordinate[0]), float(coordinate[1]))
for coordinate in annotation["coordinates"]
]
)
yield Polygon(
[
(float(coordinate[0]), float(coordinate[1]))
for coordinate in annotation["coordinates"]
]
)

Comment on lines +343 to +345
assert polygon.exterior.coords[0] == (100.0, 200.0)
assert polygon.exterior.coords[1] == (150.0, 200.0)
assert polygon.exterior.coords[2] == (125.0, 250.0)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The current assertions only check the first three points of the polygon's exterior. A shapely.Polygon is a closed ring, so its exterior.coords will have the first point repeated at the end. It's more robust to assert the full sequence of coordinates to ensure the polygon is correctly formed and closed.

Suggested change
assert polygon.exterior.coords[0] == (100.0, 200.0)
assert polygon.exterior.coords[1] == (150.0, 200.0)
assert polygon.exterior.coords[2] == (125.0, 250.0)
assert list(polygon.exterior.coords) == [
(100.0, 200.0),
(150.0, 200.0),
(125.0, 250.0),
(100.0, 200.0),
]

Comment on lines +1 to +2
"""EMPAIA format annotation parser."""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
"""EMPAIA format annotation parser."""

I don't think this comment is necessary

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants