Skip to content

[models] Simplify the reading order, exporters and document builder - #2182

Merged
felixdittrich92 merged 2 commits into
mindee:mainfrom
felixdittrich92:order-simplify
Oct 26, 2026
Merged

felixdittrich92 merged 2 commits into
mindee:mainfrom
felixdittrich92:order-simplify

Conversation

@felixdittrich92

@felixdittrich92 felixdittrich92 commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

What

A readability refactor of the reading-order pipeline added in #2167. The output does not change: it is bit-identical to main for every input tested, including degenerate ones (NaN / inf coordinates). The public API is unchanged.

  • doctr/models/reading_order/base.py
    • Label roles come from one lookup table, and the module has shared vectorized geometry helpers.
    • The topological sort is split into:
      • the multi-column detection (_column_gutter);
      • the preference for continuing the current column (_continuation).
    • Input checks and de-skewing live in one place (_canonical_boxes), and the label-aware ordering in _sort.
    • The rules for joining two elements into one segment live in a small class, _SegmentJoins.
  • doctr/io/exporters.py, doctr/io/figures.py
    • page_reading_order is now a short pipeline: element labels → ordering labels → column voters → segments → items.
    • Everything about the figures of a page lives in _PageFigures: upright boxes, text inside figures, page furniture and caption pairing.
  • doctr/models/builder.py
    • Table building is split into grid normalization, word-to-cell assignment, table de-skewing and geometry export.
    • Line splitting is a single loop.
  • Tests: 120 → 47 test functions (3484 → 2874 lines), mostly parametrized. Every original assertion is kept, and coverage is the same or higher.
main this PR
Functions rated D / E / F (radon) 6 0
Highest cyclomatic complexity 65 (page_reading_order) 19
Average cyclomatic complexity 5.86 4.91
Builder + exports, per page 22.8 ms 23.0 ms (within noise)

How it was checked

Everything is compared against main (6c46df2):

  • Real pages: 655 page images, as straight boxes and as rotated polygons (716 captures), from CORD, SROIE, XFUND, OmniDocBench, PDF test corpora, a held-out set and rotated pages.
    • 12 builder configurations plus the KIE builder: no layout, layout, tables only, layout + tables, straight-box export, resolve_lines=False, resolve_blocks and the keep_reading_order variants.
    • Outputs compared: blocks, tables, ordered items, labels, direction, plain text (with and without furniture, RTL, vertical), Markdown / HTML / AsciiDoc (with placeholders and with embedded images), JSON (ordered and raw, plus a round trip) and hOCR.
    • 10,024 / 10,024 page × configuration results are identical.
  • Fuzzing: identical in all 6,100 cases.
    • 3,200 differential cases through the builder and the public reading-order API, in all four reading directions.
    • 2,100 cases with degenerate inputs (NaN / inf / inverted / zero-size / duplicated boxes, odd labels, broken table cells).
    • 800 directly built pages with degenerate layout regions, figures and tables.
  • Unit tests, ruff and project-wide mypy pass. evaluate-text-recognition fails on main too, so it is unrelated.

@codecov

codecov Bot commented Oct 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.37370% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.71%. Comparing base (6c46df2) to head (6ee2a4f).

Files with missing lines Patch % Lines
doctr/models/reading_order/base.py 99.07% 2 Missing ⚠️
doctr/io/exporters.py 99.42% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2182   +/-   ##
=======================================
  Coverage   97.71%   97.71%           
=======================================
  Files         170      170           
  Lines       10922    10888   -34     
=======================================
- Hits        10672    10639   -33     
+ Misses        250      249    -1     
Flag Coverage Δ
unittests 97.71% <99.37%> (+<0.01%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@felixdittrich92 felixdittrich92 changed the title Test [models] Simplify the reading order, exporters and document builder Oct 26, 2026
@felixdittrich92 felixdittrich92 self-assigned this Oct 26, 2026
@felixdittrich92 felixdittrich92 added this to the 1.2.0 milestone Oct 26, 2026
@felixdittrich92 felixdittrich92 added module: models Related to doctr.models module: io Related to doctr.io ext: tests Related to tests folder type: code quality Related to code quality topic: reading order Related to the task of reading order labels Oct 26, 2026
@felixdittrich92
felixdittrich92 marked this pull request as ready for review October 26, 2026 13:53
@felixdittrich92
felixdittrich92 merged commit 323de1f into mindee:main Oct 26, 2026
52 of 54 checks passed
@felixdittrich92
felixdittrich92 deleted the order-simplify branch October 26, 2026 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ext: tests Related to tests folder module: io Related to doctr.io module: models Related to doctr.models topic: reading order Related to the task of reading order type: code quality Related to code quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant