Add a custom labeler

Warning

Pre-implementation. APIs describe the target plugin surface.

Goal

Add a Python labeler subclass that derives a new structured-label modality from IQ, component metadata, or scene metadata.

When to use this

Add a custom labeler when the target is computed from IQ, component metadata, or scene metadata. If the target is natural language grounded in existing metadata and labels, see Add a custom annotation template instead.

Prerequisites

Read Concepts / Labels and decide whether the modality belongs alongside the framework’s joint label set (JointLabeler) or as an extra labeler in addition to the joint set. Extend the joint set only when replacing or coordinating the built-in bbox, segmentation, or metadata outputs. Use an extra labeler for a new training target that can coexist with those built-in labels.

Minimal command path

Subclass BaseLabeler and register it under a stable name:

from rfgen.core.types import IQ, SceneMetadata, SignalMetadata
from rfgen.labels import BaseLabeler
from rfgen.core.registry import register_labeler


@register_labeler(name="time_spans")
class TimeSpanLabeler(BaseLabeler):
    produces = frozenset({"time_spans"})

    def label(
        self,
        *,
        iq: IQ,
        emitters: tuple[SignalMetadata, ...],
        scene: SceneMetadata,
    ) -> dict[str, object]:
        spans = []
        for meta in emitters:
            spans.append({
                "start_sample": meta.start_sample,
                "duration_samples": meta.duration_samples,
                "class_name": meta.class_name,
            })
        return {"time_spans": tuple(spans)}

The registry name time_spans is the stable config value. Installed plugins advertise that name through the labeler registry and, for packaged plugins, the rfgen.labelers Python entry-point group.

Configure it as an extra labeler alongside the joint set in a LabelConfig block. The built-in joint labeler produces bbox, segmentation, and metadata. Each extra_labelers item resolves through the same labeler registry; use the object form when the labeler needs parameters.

label:
  name: joint
  extra_labelers:
    - name: time_spans
      params: {}

Verify

rfgen validate label=label/time_spans_smoke
rfgen inspect ./out/local-smoke sample --first 3

Confirm:

  • The labeler returns deterministic output for the same (iq, emitters, scene) tuple.

  • Every key in the labeler’s produces set actually appears on the resulting record.

  • Bounds are sane (e.g., spans inside scene duration; bbox coordinates inside the time-frequency window).

  • Cross-modality consistency holds against the joint set (no contradictions in start_sample / class_name / etc.).

Troubleshoot

Symptom

Fix

Labeler duplicates existing fields

Prefer an adapter or export step unless the training target is genuinely new.

Labeler is non-deterministic

Remove randomness. Labelers are pure functions of (iq, emitters, scene) and do not receive a seeded RNG.

produces keys missing on the record

Make sure the returned dict’s keys exactly match the produces frozenset.

Next steps

See Also