Skip to content

Lookups

Lookup classes provide iteration, index access, and query methods over collections of frames, precursors, DIA windows, or PRM targets and transitions. All lookup objects support:

  • Iteration — for item in lookup:
  • Index access — lookup[id]
  • Length — len(lookup)
  • .get(id) — returns None (or a default) instead of raising on a missing ID
  • .query() — filter by m/z, retention time, or ion mobility with tolerances

MS1 Frame Lookup

tdfpy.Ms1FrameLookup

Ms1FrameLookup(frames: Mapping[int, T])

Bases: _IdLookup[T, T]

MS1 frames of a reader, indexed by frame ID, with RT queries.

Source code in src/tdfpy/lookup.py
def __init__(self, frames: Mapping[int, T]):
    super().__init__(frames.values(), frames)

get

get(key: int) -> R | None
get(key: int, default: D) -> R | D
get(key: int, default: object = None) -> object

Return the entry for key, or default (None) if it is not present.

Source code in src/tdfpy/lookup.py
def get(self, key: int, default: object = None) -> object:
    """Return the entry for ``key``, or ``default`` (``None``) if it is not present."""
    return self._index.get(key, default)

ids

ids() -> tuple[int, ...]

Every ID this lookup is indexed by, in insertion order.

Source code in src/tdfpy/lookup.py
def ids(self) -> tuple[int, ...]:
    """Every ID this lookup is indexed by, in insertion order."""
    return tuple(self._index)

query_range

query_range(
    *, rt_range: tuple[float, float] | None = None
) -> Iterator[T]

MS1 frames inside an RT range, in frame order.

Parameters:

Name Type Description Default
rt_range tuple[float, float] | None

(min_rt, max_rt) in seconds, inclusive. None keeps every frame.

None

Yields:

Type Description
T

Matching MS1 frames.

Source code in src/tdfpy/lookup.py
def query_range(self, *, rt_range: tuple[float, float] | None = None) -> Iterator[T]:
    """MS1 frames inside an RT range, in frame order.

    Args:
        rt_range: ``(min_rt, max_rt)`` in seconds, inclusive. ``None`` keeps every frame.

    Yields:
        Matching MS1 frames.
    """
    for frame in self._items:
        if _in(frame.rt, rt_range):
            yield frame

query

query(
    *, rt: float | None = None, rt_tolerance: float = 30.0
) -> Iterator[T]

MS1 frames within rt_tolerance of rt, in frame order.

Parameters:

Name Type Description Default
rt float | None

Target retention time in seconds. None keeps every frame.

None
rt_tolerance float

RT tolerance in seconds (default 30).

30.0

Yields:

Type Description
T

Matching MS1 frames.

Raises:

Type Description
TdfpyError

If rt_tolerance is negative.

Source code in src/tdfpy/lookup.py
def query(self, *, rt: float | None = None, rt_tolerance: float = 30.0) -> Iterator[T]:
    """MS1 frames within ``rt_tolerance`` of ``rt``, in frame order.

    Args:
        rt: Target retention time in seconds. ``None`` keeps every frame.
        rt_tolerance: RT tolerance in seconds (default 30).

    Yields:
        Matching MS1 frames.

    Raises:
        TdfpyError: If ``rt_tolerance`` is negative.
    """
    nonnegative("rt_tolerance", rt_tolerance)
    return self.query_range(rt_range=_tolerance_range(rt, rt_tolerance))

Precursor Lookup

tdfpy.PrecursorLookup

PrecursorLookup(precursors: Mapping[int, Precursor])

Bases: _IdLookup[Precursor, Precursor]

DDA precursors, indexed by precursor ID, with m/z and RT queries.

Source code in src/tdfpy/lookup.py
def __init__(self, precursors: Mapping[int, Precursor]):
    super().__init__(precursors.values(), precursors)

get

get(key: int) -> R | None
get(key: int, default: D) -> R | D
get(key: int, default: object = None) -> object

Return the entry for key, or default (None) if it is not present.

Source code in src/tdfpy/lookup.py
def get(self, key: int, default: object = None) -> object:
    """Return the entry for ``key``, or ``default`` (``None``) if it is not present."""
    return self._index.get(key, default)

ids

ids() -> tuple[int, ...]

Every ID this lookup is indexed by, in insertion order.

Source code in src/tdfpy/lookup.py
def ids(self) -> tuple[int, ...]:
    """Every ID this lookup is indexed by, in insertion order."""
    return tuple(self._index)

query_range

query_range(
    *,
    precursor_mz_range: tuple[float, float] | None = None,
    rt_range: tuple[float, float] | None = None
) -> Iterator[Precursor]

Precursors inside precursor m/z and/or RT ranges (inclusive).

Parameters:

Name Type Description Default
precursor_mz_range tuple[float, float] | None

(min_mz, max_mz) of :attr:Precursor.precursor_mz (monoisotopic when known, else the largest peak). None skips m/z filtering.

None
rt_range tuple[float, float] | None

(min_rt, max_rt) in seconds. None skips RT filtering.

None

Yields:

Type Description
Precursor

Matching Precursor objects.

Source code in src/tdfpy/lookup.py
def query_range(
    self,
    *,
    precursor_mz_range: tuple[float, float] | None = None,
    rt_range: tuple[float, float] | None = None,
) -> Iterator[Precursor]:
    """Precursors inside precursor m/z and/or RT ranges (inclusive).

    Args:
        precursor_mz_range: ``(min_mz, max_mz)`` of :attr:`Precursor.precursor_mz`
            (monoisotopic when known, else the largest peak). ``None`` skips m/z filtering.
        rt_range: ``(min_rt, max_rt)`` in seconds. ``None`` skips RT filtering.

    Yields:
        Matching `Precursor` objects.
    """
    for precursor in self._items:
        if _in(precursor.precursor_mz, precursor_mz_range) and _in(precursor.rt, rt_range):
            yield precursor

query

query(
    *,
    precursor_mz: float | None = None,
    rt: float | None = None,
    mz_tolerance: float = 20.0,
    mz_tolerance_unit: ToleranceUnit = "ppm",
    rt_tolerance: float = 30.0
) -> Iterator[Precursor]

Precursors within a tolerance of precursor_mz and/or rt.

Parameters:

Name Type Description Default
precursor_mz float | None

Target precursor m/z. None skips m/z filtering.

None
rt float | None

Target retention time in seconds. None skips RT filtering.

None
mz_tolerance float

m/z tolerance (default 20).

20.0
mz_tolerance_unit ToleranceUnit

"ppm" (default) or "da".

'ppm'
rt_tolerance float

RT tolerance in seconds (default 30).

30.0

Yields:

Type Description
Precursor

Matching Precursor objects, matched on :attr:Precursor.precursor_mz.

Raises:

Type Description
TdfpyError

If a tolerance is negative or mz_tolerance_unit is unknown.

Source code in src/tdfpy/lookup.py
def query(
    self,
    *,
    precursor_mz: float | None = None,
    rt: float | None = None,
    mz_tolerance: float = 20.0,
    mz_tolerance_unit: ToleranceUnit = "ppm",
    rt_tolerance: float = 30.0,
) -> Iterator[Precursor]:
    """Precursors within a tolerance of ``precursor_mz`` and/or ``rt``.

    Args:
        precursor_mz: Target precursor m/z. ``None`` skips m/z filtering.
        rt: Target retention time in seconds. ``None`` skips RT filtering.
        mz_tolerance: m/z tolerance (default 20).
        mz_tolerance_unit: ``"ppm"`` (default) or ``"da"``.
        rt_tolerance: RT tolerance in seconds (default 30).

    Yields:
        Matching `Precursor` objects, matched on :attr:`Precursor.precursor_mz`.

    Raises:
        TdfpyError: If a tolerance is negative or ``mz_tolerance_unit`` is unknown.
    """
    precursor_mz_range = _mz_range(precursor_mz, mz_tolerance, mz_tolerance_unit)
    nonnegative("rt_tolerance", rt_tolerance)
    return self.query_range(precursor_mz_range=precursor_mz_range, rt_range=_tolerance_range(rt, rt_tolerance))

DIA Window Lookup

DiaWindowLookup groups windows by window_group_id. Because a single window group definition repeats across many frames, indexing by window_group_id returns a tuple of DiaWindow objects — one per frame that used that group.

from tdfpy import DIA

with DIA("experiment.d") as dia:
    # Iterate over all windows across all frames
    for window in dia.windows:
        print(window.frame_id, window.isolation_mz, window.rt)

    # All windows belonging to window group 3 (one per frame)
    group3 = dia.windows[3]

    # Query by retention time (rt_tolerance defaults to 30 s)
    for window in dia.windows.query(rt=600.0, rt_tolerance=15.0):
        print(window.window_group_id, window.isolation_mz)

    # Query by window group AND retention time
    for window in dia.windows.query(window_group=5, rt=600.0, rt_tolerance=10.0):
        peaks = window.centroid()

tdfpy.DiaWindowLookup

DiaWindowLookup(windows: Iterable[DiaWindow])

Bases: _IdLookup[DiaWindow, tuple[DiaWindow, ...]]

Per-frame DIA windows, indexed by window group ID.

lookup[group_id] returns a tuple: every frame that used the group contributes one window per window definition.

Source code in src/tdfpy/lookup.py
def __init__(self, windows: Iterable[DiaWindow]):
    windows = tuple(windows)
    super().__init__(windows, _group(windows, lambda w: w.window_group_id))

get

get(key: int) -> R | None
get(key: int, default: D) -> R | D
get(key: int, default: object = None) -> object

Return the entry for key, or default (None) if it is not present.

Source code in src/tdfpy/lookup.py
def get(self, key: int, default: object = None) -> object:
    """Return the entry for ``key``, or ``default`` (``None``) if it is not present."""
    return self._index.get(key, default)

ids

ids() -> tuple[int, ...]

Every ID this lookup is indexed by, in insertion order.

Source code in src/tdfpy/lookup.py
def ids(self) -> tuple[int, ...]:
    """Every ID this lookup is indexed by, in insertion order."""
    return tuple(self._index)

query_range

query_range(
    *,
    window_group: int | DiaWindowGroup | None = None,
    rt_range: tuple[float, float] | None = None
) -> Iterator[DiaWindow]

Windows in a window group and/or retention time range.

Parameters:

Name Type Description Default
window_group int | DiaWindowGroup | None

Window group ID, or a DiaWindowGroup (its window_group_id is used). None keeps every group.

None
rt_range tuple[float, float] | None

(min_rt, max_rt) in seconds, inclusive. None skips RT filtering.

None

Yields:

Type Description
DiaWindow

Matching DiaWindow objects.

Source code in src/tdfpy/lookup.py
def query_range(
    self,
    *,
    window_group: int | DiaWindowGroup | None = None,
    rt_range: tuple[float, float] | None = None,
) -> Iterator[DiaWindow]:
    """Windows in a window group and/or retention time range.

    Args:
        window_group: Window group ID, or a `DiaWindowGroup` (its
            `window_group_id` is used). ``None`` keeps every group.
        rt_range: ``(min_rt, max_rt)`` in seconds, inclusive. ``None`` skips RT filtering.

    Yields:
        Matching `DiaWindow` objects.
    """
    group_id = window_group.window_group_id if isinstance(window_group, DiaWindowGroup) else window_group
    for window in self._items:
        if group_id is not None and window.window_group_id != group_id:
            continue
        if _in(window.rt, rt_range):
            yield window

query

query(
    *,
    window_group: int | DiaWindowGroup | None = None,
    rt: float | None = None,
    rt_tolerance: float = 30.0
) -> Iterator[DiaWindow]

Windows in a window group and/or within rt_tolerance of rt.

Parameters:

Name Type Description Default
window_group int | DiaWindowGroup | None

Window group ID or DiaWindowGroup. None keeps every group.

None
rt float | None

Target retention time in seconds. None skips RT filtering.

None
rt_tolerance float

RT tolerance in seconds (default 30).

30.0

Yields:

Type Description
DiaWindow

Matching DiaWindow objects.

Raises:

Type Description
TdfpyError

If rt_tolerance is negative.

Source code in src/tdfpy/lookup.py
def query(
    self,
    *,
    window_group: int | DiaWindowGroup | None = None,
    rt: float | None = None,
    rt_tolerance: float = 30.0,
) -> Iterator[DiaWindow]:
    """Windows in a window group and/or within ``rt_tolerance`` of ``rt``.

    Args:
        window_group: Window group ID or `DiaWindowGroup`. ``None`` keeps every group.
        rt: Target retention time in seconds. ``None`` skips RT filtering.
        rt_tolerance: RT tolerance in seconds (default 30).

    Yields:
        Matching `DiaWindow` objects.

    Raises:
        TdfpyError: If ``rt_tolerance`` is negative.
    """
    nonnegative("rt_tolerance", rt_tolerance)
    return self.query_range(window_group=window_group, rt_range=_tolerance_range(rt, rt_tolerance))

PRM Lookups

In a PRM experiment the instrument cycles through a list of targets (predefined precursor ions) and collects MS2 spectra for each. The two lookup classes below reflect that structure:

  • PrmTargetLookup — the list of analytes being monitored (one entry per analyte)
  • PrmTransitionLookup — the individual MS2 acquisitions (many per target, spread across the chromatographic run)

PRM Target Lookup

PrmTargetLookup gives direct access to PrmTarget objects by their integer target_id. Use .query() to filter targets by m/z, expected retention time, or ion mobility (1/K0).

from tdfpy import PRM

with PRM("experiment.d") as prm:
    # Iterate over all targets
    for target in prm.targets:
        print(target.target_id, target.precursor_mz, target.charge)

    # Access a specific target by ID
    t = prm.targets[1]
    print(t.description, t.rt, t.ook0)

    # Query by m/z (20 ppm window)
    for target in prm.targets.query(precursor_mz=565.3189, mz_tolerance=20.0):
        print(target.target_id, target.precursor_mz)

    # Query by m/z and expected RT (±30 s)
    for target in prm.targets.query(precursor_mz=565.3189, rt=480.0, rt_tolerance=30.0):
        print(target.target_id, target.description)

    # Query by 1/K0 (ion mobility)
    for target in prm.targets.query(ook0=0.92, ook0_tolerance=0.05):
        print(target.target_id, target.ook0)

tdfpy.PrmTargetLookup

PrmTargetLookup(targets: Mapping[int, PrmTarget])

Bases: _IdLookup[PrmTarget, PrmTarget]

PRM targets, indexed by target ID, with m/z, RT and 1/K0 queries.

Source code in src/tdfpy/lookup.py
def __init__(self, targets: Mapping[int, PrmTarget]):
    super().__init__(targets.values(), targets)

get

get(key: int) -> R | None
get(key: int, default: D) -> R | D
get(key: int, default: object = None) -> object

Return the entry for key, or default (None) if it is not present.

Source code in src/tdfpy/lookup.py
def get(self, key: int, default: object = None) -> object:
    """Return the entry for ``key``, or ``default`` (``None``) if it is not present."""
    return self._index.get(key, default)

ids

ids() -> tuple[int, ...]

Every ID this lookup is indexed by, in insertion order.

Source code in src/tdfpy/lookup.py
def ids(self) -> tuple[int, ...]:
    """Every ID this lookup is indexed by, in insertion order."""
    return tuple(self._index)

query_range

query_range(
    *,
    precursor_mz_range: tuple[float, float] | None = None,
    rt_range: tuple[float, float] | None = None,
    ook0_range: tuple[float, float] | None = None
) -> Iterator[PrmTarget]

Targets inside precursor m/z, RT and/or 1/K0 ranges (inclusive).

Parameters:

Name Type Description Default
precursor_mz_range tuple[float, float] | None

(min_mz, max_mz) of :attr:PrmTarget.precursor_mz. None skips m/z filtering.

None
rt_range tuple[float, float] | None

(min_rt, max_rt) in seconds. None skips RT filtering.

None
ook0_range tuple[float, float] | None

(min_ook0, max_ook0). None skips 1/K0 filtering.

None

Yields:

Type Description
PrmTarget

Matching PrmTarget objects.

Source code in src/tdfpy/lookup.py
def query_range(
    self,
    *,
    precursor_mz_range: tuple[float, float] | None = None,
    rt_range: tuple[float, float] | None = None,
    ook0_range: tuple[float, float] | None = None,
) -> Iterator[PrmTarget]:
    """Targets inside precursor m/z, RT and/or 1/K0 ranges (inclusive).

    Args:
        precursor_mz_range: ``(min_mz, max_mz)`` of :attr:`PrmTarget.precursor_mz`. ``None`` skips m/z filtering.
        rt_range: ``(min_rt, max_rt)`` in seconds. ``None`` skips RT filtering.
        ook0_range: ``(min_ook0, max_ook0)``. ``None`` skips 1/K0 filtering.

    Yields:
        Matching `PrmTarget` objects.
    """
    for target in self._items:
        if _in(target.precursor_mz, precursor_mz_range) and _in(target.rt, rt_range) and _in(target.ook0, ook0_range):
            yield target

query

query(
    *,
    precursor_mz: float | None = None,
    rt: float | None = None,
    ook0: float | None = None,
    mz_tolerance: float = 20.0,
    mz_tolerance_unit: ToleranceUnit = "ppm",
    rt_tolerance: float = 30.0,
    ook0_tolerance: float = 0.05
) -> Iterator[PrmTarget]

Targets within a tolerance of precursor_mz, rt and/or ook0.

Parameters:

Name Type Description Default
precursor_mz float | None

Target precursor m/z. None skips m/z filtering.

None
rt float | None

Target retention time in seconds. None skips RT filtering.

None
ook0 float | None

Target 1/K0. None skips 1/K0 filtering.

None
mz_tolerance float

m/z tolerance (default 20).

20.0
mz_tolerance_unit ToleranceUnit

"ppm" (default) or "da".

'ppm'
rt_tolerance float

RT tolerance in seconds (default 30).

30.0
ook0_tolerance float

Absolute 1/K0 tolerance (default 0.05).

0.05

Yields:

Type Description
PrmTarget

Matching PrmTarget objects.

Raises:

Type Description
TdfpyError

If a tolerance is negative or mz_tolerance_unit is unknown.

Source code in src/tdfpy/lookup.py
def query(
    self,
    *,
    precursor_mz: float | None = None,
    rt: float | None = None,
    ook0: float | None = None,
    mz_tolerance: float = 20.0,
    mz_tolerance_unit: ToleranceUnit = "ppm",
    rt_tolerance: float = 30.0,
    ook0_tolerance: float = 0.05,
) -> Iterator[PrmTarget]:
    """Targets within a tolerance of ``precursor_mz``, ``rt`` and/or ``ook0``.

    Args:
        precursor_mz: Target precursor m/z. ``None`` skips m/z filtering.
        rt: Target retention time in seconds. ``None`` skips RT filtering.
        ook0: Target 1/K0. ``None`` skips 1/K0 filtering.
        mz_tolerance: m/z tolerance (default 20).
        mz_tolerance_unit: ``"ppm"`` (default) or ``"da"``.
        rt_tolerance: RT tolerance in seconds (default 30).
        ook0_tolerance: Absolute 1/K0 tolerance (default 0.05).

    Yields:
        Matching `PrmTarget` objects.

    Raises:
        TdfpyError: If a tolerance is negative or ``mz_tolerance_unit`` is unknown.
    """
    precursor_mz_range = _mz_range(precursor_mz, mz_tolerance, mz_tolerance_unit)
    nonnegative("rt_tolerance", rt_tolerance)
    nonnegative("ook0_tolerance", ook0_tolerance)
    return self.query_range(
        precursor_mz_range=precursor_mz_range,
        rt_range=_tolerance_range(rt, rt_tolerance),
        ook0_range=_tolerance_range(ook0, ook0_tolerance),
    )

PRM Transition Lookup

PrmTransitionLookup gives access to PrmTransition objects — the individual MS2 acquisitions captured during the run. Indexing by target_id returns a tuple of all transitions collected for that target across the chromatographic run.

from tdfpy import PRM

with PRM("experiment.d") as prm:
    # All transitions for target 1 (tuple — one per MS2 frame)
    transitions = prm.transitions[1]
    for t in transitions:
        print(t.frame_id, t.rt, t.collision_energy)
        peaks = t.scan_peaks()  # list of (N, 2) [m/z, intensity] arrays, one per mobility scan

    # Query transitions for a specific target near a retention time
    for tr in prm.transitions.query(target=1, rt=480.0, rt_tolerance=30.0):
        centroided = tr.centroid()  # shape (N, 3): [m/z, intensity, 1/K0]

    # Query using a PrmTarget object directly
    target = prm.targets[1]
    for tr in prm.transitions.query(target=target, rt=target.rt, rt_tolerance=20.0):
        print(tr.frame_id, tr.isolation_mz)

tdfpy.PrmTransitionLookup

PrmTransitionLookup(transitions: Iterable[PrmTransition])

Bases: _IdLookup[PrmTransition, tuple[PrmTransition, ...]]

PRM transitions, indexed by target ID.

lookup[target_id] returns a tuple: a target is acquired in many frames.

Source code in src/tdfpy/lookup.py
def __init__(self, transitions: Iterable[PrmTransition]):
    transitions = tuple(transitions)
    super().__init__(transitions, _group(transitions, lambda t: t.target.target_id))

get

get(key: int) -> R | None
get(key: int, default: D) -> R | D
get(key: int, default: object = None) -> object

Return the entry for key, or default (None) if it is not present.

Source code in src/tdfpy/lookup.py
def get(self, key: int, default: object = None) -> object:
    """Return the entry for ``key``, or ``default`` (``None``) if it is not present."""
    return self._index.get(key, default)

ids

ids() -> tuple[int, ...]

Every ID this lookup is indexed by, in insertion order.

Source code in src/tdfpy/lookup.py
def ids(self) -> tuple[int, ...]:
    """Every ID this lookup is indexed by, in insertion order."""
    return tuple(self._index)

query_range

query_range(
    *,
    target: int | PrmTarget | None = None,
    rt_range: tuple[float, float] | None = None
) -> Iterator[PrmTransition]

Transitions of one target and/or inside an RT range.

Parameters:

Name Type Description Default
target int | PrmTarget | None

Target ID or PrmTarget. None keeps every target.

None
rt_range tuple[float, float] | None

(min_rt, max_rt) in seconds. None skips RT filtering.

None

Yields:

Type Description
PrmTransition

Matching PrmTransition objects.

Source code in src/tdfpy/lookup.py
def query_range(
    self,
    *,
    target: int | PrmTarget | None = None,
    rt_range: tuple[float, float] | None = None,
) -> Iterator[PrmTransition]:
    """Transitions of one target and/or inside an RT range.

    Args:
        target: Target ID or `PrmTarget`. ``None`` keeps every target.
        rt_range: ``(min_rt, max_rt)`` in seconds. ``None`` skips RT filtering.

    Yields:
        Matching `PrmTransition` objects.
    """
    target_id = target.target_id if isinstance(target, PrmTarget) else target
    for transition in self._items:
        if target_id is not None and transition.target.target_id != target_id:
            continue
        if _in(transition.rt, rt_range):
            yield transition

query

query(
    *,
    target: int | PrmTarget | None = None,
    rt: float | None = None,
    rt_tolerance: float = 30.0
) -> Iterator[PrmTransition]

Transitions of one target and/or within rt_tolerance of rt.

Parameters:

Name Type Description Default
target int | PrmTarget | None

Target ID or PrmTarget. None keeps every target.

None
rt float | None

Target retention time in seconds. None skips RT filtering.

None
rt_tolerance float

RT tolerance in seconds (default 30).

30.0

Yields:

Type Description
PrmTransition

Matching PrmTransition objects.

Raises:

Type Description
TdfpyError

If rt_tolerance is negative.

Source code in src/tdfpy/lookup.py
def query(
    self,
    *,
    target: int | PrmTarget | None = None,
    rt: float | None = None,
    rt_tolerance: float = 30.0,
) -> Iterator[PrmTransition]:
    """Transitions of one target and/or within ``rt_tolerance`` of ``rt``.

    Args:
        target: Target ID or `PrmTarget`. ``None`` keeps every target.
        rt: Target retention time in seconds. ``None`` skips RT filtering.
        rt_tolerance: RT tolerance in seconds (default 30).

    Yields:
        Matching `PrmTransition` objects.

    Raises:
        TdfpyError: If ``rt_tolerance`` is negative.
    """
    nonnegative("rt_tolerance", rt_tolerance)
    return self.query_range(target=target, rt_range=_tolerance_range(rt, rt_tolerance))