Architecture

This page documents the package architectural philosophy and the enforceable design rules that keep the codebase coherent. Stable policy identifiers (ARCH-NNN) keep this narrative aligned with the maintainer-local verification policy. The full design rationale lives in docs/design/DESIGN.md (approved v0.3).

Purpose

padelpy2 owns a Python bridge to the stock PaDEL-Descriptor Java JAR: typed descriptor/fingerprint catalogs, an RDKit-native Calculator, pandas DataFrame results, and a low-level padeldescriptor CLI surface compatible with padelpy. Primary users need classic-JAR fidelity (including aromatic-molecule defaults pinned by oracles) and padelpy continuity.

Non-goals include reimplementing PaDEL in pure Python, competing with Mordred or RDKit as a general descriptor engine, and multi-engine backends behind Calculator.

Principles

  • ARCH-010 — Layered architecture with acyclic imports (higher layers depend only on lower layers).

  • ARCH-020 — Public subpackages expose a curated __all__.

  • ARCH-030 — The Java engine is reached only through the engine-adapter layer (padelpy2.wrapper / internal worker); orchestration must not spawn ad hoc java processes elsewhere.

  • ARCH-040 — Default public API behavior is stable: preset catalog column schemas and dropping the Name column unless an additive opt-in says otherwise. See API stability.

  • ARCH-050 — Optional heavy dependencies (RDKit) stay behind clear import boundaries and documented extras.

  • ARCH-055 — Vendored engine is the stock Yap JAR; document identity (path/hash) wherever fidelity is claimed.

  • ARCH-060 — This page remains the public architecture contract.

Architecture style

Layered package with a functional core (catalog metadata, XML/SDF preparation, validation) and an imperative shell (subprocess or long-lived JVM worker).

Component map

Layer

Components

Responsibility

L0

padelpy2/PaDEL-Descriptor/

Stock JAR, CSVs, notices

L1

descriptors, fingerprints, config, utils

Catalogs, config, I/O utils

L2

wrapper

Java CLI / worker adapter

L3

calculator

End-to-end orchestration

L4

compat, qc (shipped)

Migration helpers, QC reports

Dependency rules

  • L4 → L3 → L2 → L1 → L0 only (no upward or cyclic imports).

  • compat and qc may use Calculator and catalog types; they must not bypass the wrapper to invoke Java.

  • Vendored assets under PaDEL-Descriptor/ are opaque binary/metadata inputs, not a Python import graph.

Public API

Top-level exports (see package __init__): Calculator, PaDELConfig, descriptors, descriptors_2d, descriptors_3d, fingerprints, padeldescriptor, and __version__.

Submodule catalogs: padelpy2.descriptors and padelpy2.fingerprints expose Descriptor / Fingerprint types and named singletons.

ARCH-020 requires each listed public package to declare an explicit __all__ as packaging matures.

Domain types

  • Descriptor — PaDEL descriptor class name, member names/descriptions, 2D/3D flag.

  • Fingerprint — PaDEL fingerprint class name, bit count, description.

  • PaDELConfig — dataclass of engine flags and subprocess timeout.

  • Calculation results — pandas.DataFrame rows aligned with input molecule order when retainorder is enabled (default).

Extension points

  • Pass custom iterables of Descriptor / Fingerprint instances into Calculator.

  • Low-level padeldescriptor for file/directory workflows (padelpy continuity).

  • Additive padelpy2.compat provides padelpy-like from_smiles / from_sdf / from_mdl helpers (not a padelpy replacement). padelpy2.qc summarizes DataFrame missingness/constants (convenience only). Do not introduce alternate descriptor engines as drop-in Calculator backends without a design revision.

Data and control flow

  1. Construct Calculator with catalog objects → build descriptortypes XML.

  2. On call: validate RDKit molecules → write temporary SDF → invoke stock-JAR adapter → read CSV → return DataFrame (Name dropped by default).

  3. Optional chunk_size batches molecules behind the same public call signature (UX parity). JVM keep-alive is deferred: each stock-JAR call starts java -jar; see Performance notes.

Exceptions

  • Temporary flat package layout (not src/) is accepted until packaging friction warrants migration (ARCH-X001).

  • Shape-only integration tests are a known validation gap until stock-JAR fidelity oracles land (ARCH-X002); see design goals G2.

Change process

Update this page and the maintainer-local architecture policy together when rules change. Keep policy identifiers stable; prefer adding a new identifier over silently redefining an existing one. Align narrative changes with docs/design/DESIGN.md.