Architecture¶
This page describes how the chebpy source is organised: the two runtime type
hierarchies, the layered module import graph and its direction rule, where the
Chebfun implementation lives, and which files this repository owns versus
those synced from the Rhiza template.
Type hierarchies¶
chebpy has two abstract hierarchies that meet in Classicfun. One
describes a function on the reference interval [-1, 1]; the other places such
a function onto an arbitrary interval [a, b].
Onefun (abstract) a function on the reference interval [-1, 1]
└─ Smoothfun (abstract)
├─ Chebtech Chebyshev series (aperiodic functions)
└─ Trigtech Fourier series (periodic functions)
Fun (abstract)
└─ Classicfun (abstract) maps [-1, 1] ↔ [a, b]; wraps one Onefun
├─ Bndfun bounded interval, affine map
├─ CompactFun (semi-)infinite interval via numerical-support truncation
└─ Singfun endpoint singularities via a non-affine clustering map
A Classicfun holds an Onefun (its representation on [-1, 1]) together
with the interval or map that places it on [a, b]. The choice of Onefun
subclass is orthogonal to the choice of Classicfun subclass: e.g. a Bndfun
usually wraps a Chebtech, but a periodic piece wraps a Trigtech.
The Chebfun container¶
Chebfun is the user-facing class. It is not part of the Fun hierarchy;
it is a container holding an ordered array of Fun pieces over a Domain
(one piece per sub-interval between breakpoints). Piecewise operations
(arithmetic, calculus, root-finding, conv, …) fan out over the pieces.
Chebfun ──holds──▶ [ Fun, Fun, … ] one piece per sub-interval
each Fun ──holds──▶ Onefun on [-1, 1]
Module layering¶
Modules are organised into layers. A module imports only from strictly lower layers (plus, in a few noted cases, siblings in its own layer). Lower layers never import upper layers at module scope — see Import direction for the one audited exception.
L7 High-level API / apps api · quasimatrix · gpr
L6 Container + impl chebfun · _convolution · _pointwise ·
_singular_construction · _ufuncs
L5 Classicfun pieces bndfun · compactfun · singfun
L4 Interval-mapped base classicfun
L3 Reference reps (Onefun) chebtech · trigtech
L2 Numerical kernels algorithms · chebyshev
L1 Primitives utilities · plotting · smoothfun
L0 Foundations settings · exceptions · decorators · maps · fun · onefun
chebpy/__init__.py sits above everything as the package facade, re-exporting
the public surface (chebfun, chebpts, pwc, trigfun, CompactFun,
Singfun, Trigtech, Quasimatrix, gpr, …).
Selected module dependencies (top-level imports):
| Module | Imports |
|---|---|
utilities |
decorators, exceptions, settings |
algorithms |
decorators, settings, utilities |
chebtech / trigtech |
algorithms*/decorators, plotting, settings, smoothfun, utilities |
classicfun |
chebtech, trigtech, fun, decorators, exceptions, plotting, settings, utilities |
bndfun / compactfun / singfun |
classicfun (+ exceptions/settings/utilities/maps) |
chebfun |
bndfun, _ufuncs, decorators, exceptions, plotting, settings, utilities |
api |
algorithms, bndfun, chebfun, settings, utilities |
gpr |
algorithms, chebfun, quasimatrix, settings |
*trigtech does not import algorithms at module scope; it defers that import
(see below).
The Chebfun implementation modules¶
Chebfun is large, so its self-contained algorithms live in dedicated modules.
The public Chebfun methods are thin, documented wrappers that delegate:
| Module | Provides | Fronted by |
|---|---|---|
_convolution.py |
Hale–Townsend / Gauss–Legendre convolution | Chebfun.conv |
_pointwise.py |
root-splitting step ops | Chebfun.abs, sign, ceil, floor, maximum, minimum |
_singular_construction.py |
endpoint-singularity piece construction | the sing= Chebfun constructors |
_ufuncs.py |
registers elementwise NumPy ufunc methods | Chebfun.sin, exp, … |
These modules operate on a Chebfun passed in as an argument (constructing
results via f.__class__(...)) and reference Chebfun only under
TYPE_CHECKING, so importing them never creates a runtime cycle.
Import direction and deferred imports¶
The layering rule is enforced by keeping upward references out of module scope. Function-local (deferred) imports are used for three reasons:
- Typing only —
_convolution,_pointwise,_ufuncsimportChebfununderTYPE_CHECKING. - Breaking sibling cycles — e.g.
singfun/compactfunimportbndfuninsiderestrict;trigtechimportschebtechinsideroots. - Lazy/optional heavy paths —
chebfunimports its implementation modules (_convolution,_pointwise,_singular_construction) inside the relevant methods.
Known exception (tech debt)¶
utilities.generate_funs() contains a function-local
from .compactfun import CompactFun — an L1 module reaching up to L5. This
is the one genuine layering back-edge (a hidden utilities ↔ compactfun
cycle), deferred so it does not manifest at import time. It is tracked in
issue #417; the intended fix is
to inject the compact constructor rather than import it here.
Source ownership: this repo vs Rhiza¶
This project syncs its development infrastructure from the
jebel-quant/rhiza template. The
machine-readable list of synced files is the files: block of
.rhiza/template.lock; that file is authoritative. In summary:
Owned by this repository — edit here:
src/chebpy/**— the librarytests/**— chebpy's own test suite (note:.rhiza/tests/**is Rhiza's)pyproject.toml,README.md,mkdocs.yml,cliff.tomldocs/**exceptdocs/mkdocs-base.yml- project notebooks
Managed by Rhiza — do not edit in place; change upstream in Rhiza or via
.rhiza/template.yml, then re-sync:
Makefileand.rhiza/make.d/*.mk, plus everything under.rhiza/**.github/workflows/rhiza_*.yml.pre-commit-config.yaml,ruff.toml,pytest.ini,.bandit,.editorconfigdocs/mkdocs-base.yml.devcontainer/*and.claude/commands/rhiza_*.md
When scoring or reviewing the repo, attribute gaps in Rhiza-managed files to the template (fix upstream), and gaps in the owned files to this project.