phenotypic.tune.TuneSpec#

class phenotypic.tune.TuneSpec(low: float | None = None, high: float | None = None, *, step: float | None = None, log: bool = False, categories: tuple | None = None, tunable: bool = True)[source]#

Bases: object

Per-field tuning-search metadata (Tier-1 inference override).

TuneSpec mirrors the existing field-marker pattern (_ColumnRefMarker, _OperationFieldMarker): a frozen, slotted, non-pydantic sentinel that is a complete no-op at runtime and is read only by infer_search_space, via op.model_fields[name].metadata (where pydantic v2 stores Annotated extras). It rides in an Annotated[T, TuneSpec(...)] chain:

class GaussianBlur(ImageEnhancer):
    sigma:    Annotated[float, TuneSpec(0.5, 5.0, log=True)] = 2.0
    truncate: Annotated[float, TuneSpec(tunable=False)]      = 4.0

At runtime sigma is still a plain float; GaussianBlur(sigma=999.0) constructs exactly as before. The marker is the search domain, never the valid domain — validity stays the job of pydantic Field(ge=, le=).

It lives here (not in phenotypic.tune) so operation modules can import it without dragging in the tune engine — the public re-export from phenotypic.tune import TuneSpec still works.

Parameters:
  • low (float | None) – Inclusive lower search bound (positional). None leaves the bound to Tier-2 inference / the co-located Field constraint.

  • high (float | None) – Inclusive upper search bound (positional). None as low.

  • step (float | None) – Discretization stride — integer step or quantized float. None means continuous (or unit-step for integers).

  • log (bool) – Whether to sample on a logarithmic scale (default False).

  • categories (tuple | None) – Override / subset the auto-derived categorical choices. A list is coerced to a tuple so the marker stays hashable.

  • tunable (bool) – False excludes the field from tuning outright and short-circuits Tier-2 (default True).

Note

This is not a pydantic model — it is a plain slotted sentinel so it can sit in an Annotated chain without pydantic trying to validate it. It carries __eq__/__hash__ over the full field tuple so a duplicate in an Annotated chain de-dupes (PEP 593 chain semantics).

Methods

__init__

Attributes

low: float | None#
high: float | None#
step: float | None#
log: bool#
categories: tuple | None#
tunable: bool#