Skip to main content

Python port of the CMS Integrated Outpatient Code Editor (I/OCE)

Project description

PyOCE

Python Version License Ruff Mypy

PyOCE is a production-grade Python port of the CMS Integrated Outpatient Code Editor (I/OCE) — the official rules engine used by the Centers for Medicare & Medicaid Services to edit, group, and price hospital outpatient claims under the OPPS (Outpatient Prospective Payment System).

What Does the I/OCE Do?

The I/OCE applies 150+ clinical and administrative edit rules to each outpatient claim, including:

  • Validity checks — bill type, dates, diagnosis codes, HCPCS/CPT codes, modifiers, revenue codes
  • NCCI edits — procedure-to-procedure code pairs that should not be billed together
  • APC assignment — grouping services into Ambulatory Payment Classifications for pricing
  • Status indicator assignment — determining whether each line is payable, packaged, or denied
  • Discounting and packaging — applying OPPS payment logic (multiple procedure discounting, composite APCs, etc.)
  • Specialty handling — FQHC visits, biosimilars, telehealth, mental health, non-opioid therapies, Section 603, and more

PyOCE replicates this logic in pure Python, verified against the CMS Java reference implementation.

Features

  • Parity-tested — Cross-validated against official CMS Java TESTDB outputs across thousands of claims
  • High throughput — Optimized LMDB-backed reference data with zero-copy memory mapping; processes 1,000+ claims per second
  • Zero-config data — Reference database is bundled as a compressed archive and auto-extracted on first use
  • Version-aware — Full support for IOCE version ranges; lookups respect historical data boundaries
  • Thread-safe — LMDB supports concurrent reads from multiple processes/threads
  • Simple API — Plain dict in, plain dict out; no ORM, no protobuf, no ceremony
  • Self-contained — Single package with bundled reference data; no external services needed
  • Reusable engineIoceComponent gives access to edit descriptions, APC descriptions, and other lookup utilities

Installation

pip install pyoce

Requirements: Python 3.12+, no system dependencies beyond the Python standard library.

On first use, the bundled reference database (~2.7 MB compressed, ~10 MB uncompressed LMDB) is automatically inflated to ~/.cache/pyoce/.

Quick Start

import pyoce

claim = {
    "claimId": "DEMO-001",
    "billType": "131",
    "dateStarted": "20240101",
    "dateEnded": "20240101",
    "principalDiagnosisCode": {"diagnosis": "J449"},
    "lineItemList": [
        {
            "serviceDate": "20240101",
            "hcpcs": "99213",
            "revenueCode": "0510",
            "unitsInput": "1",
            "charge": "15000",
        }
    ],
}

result = pyoce.process_claim(claim)

# Inspect results
print(f"Return code: {result['processingInformation']['returnCode']}")
for li in result["lineItemList"]:
    print(f"  {li['hcpcs']} → APC {li['paymentApc']}, SI {li['statusIndicator']}")

# Look up edit descriptions (human-readable)
engine = pyoce.IoceComponent()
assert result is engine.process(claim)  # same API, reusable
print(engine.get_edit_description("001"))
print(engine.get_apc_description("5021"))

Input Fields

Field Type Notes
claimId str Unique claim identifier
billType str 3-char bill type (e.g. "131" for hospital outpatient)
dateStarted / dateEnded str YYYYMMDD format
receiptDate str YYYYMMDD, used for version range lookups
principalDiagnosisCode dict {"diagnosis": "J449", "presentOnAdmission": "Y"}
secondaryDiagnosisCodeList list[dict] Additional diagnosis codes
lineItemList list[dict] Per-line: hcpcs, revenueCode, serviceDate, unitsInput, charge, optional modifiers

See the src/pyoce/model/external/ package for the full external model.

Output Fields

The output dict mirrors the input structure with additions:

  • Claim-level: claimDisposition, claimRejectionEditList, claimDenialEditList, etc.
  • Line-level: paymentApc, statusIndicator, paymentIndicator, discountingFormula, rejectionDenialFlag, edit lists per buffer type
  • Processing metadata: returnCode, version, timing information

How It Works

Claims flow through a 5-phase sequential pipeline:

INITIALIZATION → PREPROCESSING → PROCESSING → POSTPROCESSING → FINALIZATION
Phase Responsibility
Initialization Load and validate reference data tables (cached after first claim)
Preprocessing Copy input to internal model, validate bill type/dates, load table data per claim, validate contractor overrides
Processing Execute 150+ edit rules, routed by bill type (see below)
Postprocessing Calculate disposition, payment flags, discounting, composite APCs, units
Finalization Copy internal processing state back to external output model

Bill Type Routing

The processing phase dispatches to one of 24 bill-type-specific logic paths based on the claim's bill type, OPPS/non-OPPS flag, and condition codes. The most common path — 13x (Hospital Outpatient) — applies approximately 150 sequential rule checks including NCCI edits, status/payment indicator assignment, add-on code pairing, modifier validation, and specialty payment logic.

For a complete bill-type routing table, see the internal architecture documentation.

Reference Data

PyOCE ships with a pre-built LMDB database containing 39 CMS reference tables (213,277 records) covering APC assignments, HCPCS code attributes, ICD-10 diagnoses, NCCI edit pairs, offset tables, status/payment indicators, composite APCs, and all add-on code mappings — versioned across the full IOCE version range.

Overriding the Database Location

from pyoce.dao.provider import LmdbDataProvider

# Point to a custom LMDB database
LmdbDataProvider.reset_instance()
provider = LmdbDataProvider(env_path="/path/to/pyoce.mdb")

Rebuilding the Database

To rebuild the LMDB database from CMS flat files:

uv run python scripts/build_db.py

This reads Report-Tables/ (not included in the repository) and writes src/pyoce/data/pyoce.mdb.xz.

Development

# Clone and install in editable mode with dev dependencies
git clone https://github.com/cms-gov/pyoce.git
cd pyoce
uv pip install -e ".[dev]"

CI Verification

Run the exact checks used in CI:

uv run ruff format --check .   # code formatting
uv run ruff check .             # linting
uv run mypy src                 # strict type checking
uv run pytest                   # full test suite

Testing

Suite Command Requires
Unit tests uv run pytest tests/unit Nothing
Integration (parity) uv run pytest tests/integration cms_mf/claims.json (CMS TESTDB)
Full suite uv run pytest cms_mf/claims.json

Unit tests cover flag enums, data providers, DAOs, external models, converters, utilities, and individual logic rules. Integration tests feed real CMS TESTDB claims through the engine and compare output field-by-field against the Java reference implementation.

Parity Report

Generate a detailed mismatch report for all claims with expected outputs:

PYTHONPATH=. uv run python tests/integration/test_parity_report.py

Or test a single claim by ID:

PYTHONPATH=. uv run python tests/integration/test_parity_report.py --claim <id>

Project Structure

src/pyoce/
├── __init__.py             # Public API: process_claim(), IoceComponent
├── api/                    # Entry points, claim execution engine
├── model/
│   ├── external/           # Public claim/line models (dataclasses)
│   └── internal/           # Processing state models (~50 fields per claim)
├── logic/
│   ├── initialization/     # Phase 1: load & validate tables
│   ├── preprocessing/      # Phase 2: validate inputs, load per-claim data
│   ├── processing/         # Phase 3: 150+ edit rules, bill-type paths
│   │   ├── addon/          # Add-on code pairing logic
│   │   └── specialty/      # FQHC, biosimilar, telehealth, S603, etc.
│   ├── postprocessing/     # Phase 4: disposition, flags, composites
│   └── finalization/       # Phase 5: output marshaling
├── dao/                    # Data access layer (42 table DAOs, description provider)
├── rsc/                    # Flag enums, edit registry, constants
├── util/                   # FlagSet, Navigator, range maps, utilities
└── data/                   # Bundled LMDB database (compressed)

License

Apache License, Version 2.0 — see LICENSE.

Contributing

See CONTRIBUTING.md for development setup, coding standards, and pull request guidelines.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyoce-0.1.0.tar.gz (3.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyoce-0.1.0-py3-none-any.whl (3.3 MB view details)

Uploaded Python 3

File details

Details for the file pyoce-0.1.0.tar.gz.

File metadata

  • Download URL: pyoce-0.1.0.tar.gz
  • Upload date:
  • Size: 3.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyoce-0.1.0.tar.gz
Algorithm Hash digest
SHA256 00b82ae43d44c5fed7825c46c953c5119722300d55e2e4346ac391af790e0dea
MD5 daa2a8fd7946c5288f15ab089bb1f0d3
BLAKE2b-256 3f692a42b73ffc427d829decff4a387e7bf2391ad05aa89b95c7a62dc80d34ce

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyoce-0.1.0.tar.gz:

Publisher: publish.yml on Bedrock-Billing/pyoce

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyoce-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pyoce-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 3.3 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyoce-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f55810c1d036b6cd7cf9ba4ba8c2f1d67f997f19c9695976fb557cdb2c45e7be
MD5 8cc74ed12a89f5b4f13efcd81c511756
BLAKE2b-256 18653bf115ff1724555b647762041f62eba83aa468f593a5644d9fe37a9428b2

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyoce-0.1.0-py3-none-any.whl:

Publisher: publish.yml on Bedrock-Billing/pyoce

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page