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:

  • Iterationfor item in lookup:
  • Index accesslookup[id]
  • Lengthlen(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: dict[int, T])

Bases: Generic[T]

A class to perform lookups on MS1 frames. Can be iterated over to yield all frames. Can be indexed by frame ID.

Source code in src/tdfpy/lookup.py
36
37
def __init__(self, frames: dict[int, T]):
    self._frames = frames

get

get(frame_id: int, default=None)

Return the frame with the given ID, or default if not found.

Source code in src/tdfpy/lookup.py
52
53
54
def get(self, frame_id: int, default=None):
    """Return the frame with the given ID, or `default` if not found."""
    return self._frames.get(frame_id, default)

Precursor Lookup

tdfpy.PrecursorLookup

PrecursorLookup(precursors: dict[int, Precursor])

A class to perform lookups on precursors. Can be iterated over to yield all precursors. Can be indexed by precursor ID. Provides methods to query by m/z and retention time.

Source code in src/tdfpy/lookup.py
152
153
def __init__(self, precursors: dict[int, Precursor]):
    self._precursors = precursors

get

get(precursor_id: int, default=None)

Return the precursor with the given ID, or default if not found.

Source code in src/tdfpy/lookup.py
168
169
170
def get(self, precursor_id: int, default=None):
    """Return the precursor with the given ID, or `default` if not found."""
    return self._precursors.get(precursor_id, default)

query_range

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

Query precursors by m/z and/or retention time ranges.

Parameters:

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

Tuple of (min_mz, max_mz). If None, m/z filtering is skipped.

None
rt_range tuple[float, float] | None

Tuple of (min_rt, max_rt) in seconds. If None, RT filtering is skipped.

None

Yields: Precursor objects matching the criteria.

Source code in src/tdfpy/lookup.py
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
def query_range(
    self,
    mz_range: tuple[float, float] | None = None,
    rt_range: tuple[float, float] | None = None,
) -> Iterator[Precursor]:
    """
    Query precursors by m/z and/or retention time ranges.

    Args:
        mz_range: Tuple of (min_mz, max_mz). If None, m/z filtering is skipped.
        rt_range: Tuple of (min_rt, max_rt) in seconds. If None, RT filtering is skipped.
    Yields:
        Precursor objects matching the criteria.
    """
    for precursor in self._precursors.values():
        if mz_range is not None:
            prec_mz = precursor.monoisotopic_mz
            if prec_mz is None:
                prec_mz = precursor.largest_peak_mz
            if not (mz_range[0] <= prec_mz <= mz_range[1]):
                continue

        if rt_range is not None:
            if not (rt_range[0] <= precursor.rt <= rt_range[1]):
                continue

        yield precursor

query

query(
    mz: float | None = None,
    rt: float | None = None,
    mz_tolerance: float = 20.0,
    mz_tolerance_type: Literal["ppm", "da"] = "ppm",
    rt_tolerance: float = 30.0,
) -> Iterator[Precursor]

Query precursors by m/z and/or retention time.

Parameters:

Name Type Description Default
mz float | None

Target m/z value. If None, m/z filtering is skipped.

None
rt float | None

Target retention time (in seconds). If None, RT filtering is skipped.

None
mz_tolerance float

Tolerance for m/z matching.

20.0
mz_tolerance_type Literal['ppm', 'da']

Unit for m/z tolerance ("ppm" or "da"). Default is "ppm".

'ppm'
rt_tolerance float

Tolerance for retention time matching (in seconds). Default is 30s.

30.0

Yields:

Type Description
Precursor

Precursor objects matching the criteria.

Note

Uses monoisotopic_mz if available, otherwise largest_peak_mz.

Source code in src/tdfpy/lookup.py
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
def query(
    self,
    mz: float | None = None,
    rt: float | None = None,
    mz_tolerance: float = 20.0,
    mz_tolerance_type: Literal["ppm", "da"] = "ppm",
    rt_tolerance: float = 30.0,
) -> Iterator[Precursor]:
    """
    Query precursors by m/z and/or retention time.

    Args:
        mz: Target m/z value. If None, m/z filtering is skipped.
        rt: Target retention time (in seconds). If None, RT filtering is skipped.
        mz_tolerance: Tolerance for m/z matching.
        mz_tolerance_type: Unit for m/z tolerance ("ppm" or "da"). Default is "ppm".
        rt_tolerance: Tolerance for retention time matching (in seconds). Default is 30s.

    Yields:
        Precursor objects matching the criteria.

    Note:
        Uses `monoisotopic_mz` if available, otherwise `largest_peak_mz`.
    """
    choice("mz_tolerance_type", mz_tolerance_type, ("ppm", "da"))
    nonnegative("mz_tolerance", mz_tolerance)
    mz_range: tuple[float, float] | None = None
    if mz is not None:
        if mz_tolerance_type == "ppm":
            mz_range = (mz - mz * mz_tolerance / 1e6, mz + mz * mz_tolerance / 1e6)
        else:  # da
            mz_range = (mz - mz_tolerance, mz + mz_tolerance)

    nonnegative("rt_tolerance", rt_tolerance)
    rt_range: tuple[float, float] | None = None
    if rt is not None:
        rt_range = (rt - rt_tolerance, rt + rt_tolerance)

    return self.query_range(mz_range=mz_range, rt_range=rt_range)

DIA Window Lookup

DiaWindowLookup groups windows by window_group. Because a single window group definition repeats across many frames, indexing by window_group_id returns a list 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 (±30 s default)
    for window in dia.windows.query(rt=600.0, rt_tolerance=15.0):
        print(window.window_group, window.isolation_mz)

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

tdfpy.DiaWindowLookup

DiaWindowLookup(windows: list[DiaWindow])

A class to perform lookups on DIA windows. Can be iterated over to yield all windows. Can be indexed by window ID (which is equivalent to window_group).

Source code in src/tdfpy/lookup.py
64
65
66
67
68
69
70
71
def __init__(self, windows: list[DiaWindow]):
    self._windows = windows
    # Map window_group to list of windows with that group ID
    self._window_map: dict[int, list[DiaWindow]] = {}
    for w in windows:
        if w.window_group not in self._window_map:
            self._window_map[w.window_group] = []
        self._window_map[w.window_group].append(w)

get

get(window_group_id: int, default=None)

Return windows for the given window group ID, or default if not found.

Source code in src/tdfpy/lookup.py
88
89
90
def get(self, window_group_id: int, default=None):
    """Return windows for the given window group ID, or `default` if not found."""
    return self._window_map.get(window_group_id, default)

query_range

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

Query windows by window group and/or retention time range.

Parameters:

Name Type Description Default
window_group_index int | DiaWindowGroup | None

Window group index or DiaWindowGroup to filter by. If None, all window groups are included.

None
rt_range tuple[float, float] | None

Tuple of (min_rt, max_rt) in seconds. If None, RT filtering is skipped.

None

Yields:

Type Description
DiaWindow

DiaWindow objects matching the criteria.

Source code in src/tdfpy/lookup.py
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
def query_range(
    self,
    window_group_index: int | DiaWindowGroup | None = None,
    rt_range: tuple[float, float] | None = None,
) -> Iterator[DiaWindow]:
    """
    Query windows by window group and/or retention time range.

    Args:
        window_group_index: Window group index or `DiaWindowGroup` to filter by.
            If None, all window groups are included.
        rt_range: Tuple of (min_rt, max_rt) in seconds. If None, RT filtering is skipped.

    Yields:
        DiaWindow objects matching the criteria.
    """
    for window in self._windows:
        if window_group_index is not None:
            if isinstance(window_group_index, DiaWindowGroup):
                if window.window_group != window_group_index.window_group:
                    continue
            elif window.window_group != window_group_index:
                continue
        if rt_range is not None:
            if not (rt_range[0] <= window.rt <= rt_range[1]):
                continue
        yield window

query

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

Query windows by retention time.

Parameters:

Name Type Description Default
rt float | None

Target retention time (in seconds). If None, RT filtering is skipped.

None
rt_tolerance float

Tolerance for retention time matching (in seconds). Default is 30s.

30.0

Yields: DiaWindow objects matching the criteria.

Source code in src/tdfpy/lookup.py
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
def query(
    self,
    window_group_index: int | DiaWindowGroup | None = None,
    rt: float | None = None,
    rt_tolerance: float = 30.0,
) -> Iterator[DiaWindow]:
    """
    Query windows by retention time.

    Args:
        rt: Target retention time (in seconds). If None, RT filtering is skipped.
        rt_tolerance: Tolerance for retention time matching (in seconds). Default is 30s.
    Yields:
        DiaWindow objects matching the criteria.
    """
    nonnegative("rt_tolerance", rt_tolerance)
    rt_range: tuple[float, float] | None = None
    if rt is not None:
        rt_range = (rt - rt_tolerance, rt + rt_tolerance)
    return self.query_range(
        window_group_index=window_group_index, rt_range=rt_range
    )

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.monoisotopic_mz, target.charge)

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

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

    # Query by m/z and expected RT (±30 s)
    for target in prm.targets.query(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.one_over_k0)

tdfpy.PrmTargetLookup

PrmTargetLookup(targets: dict[int, PrmTarget])

Lookup for PRM targets by target ID, m/z, RT, and 1/K0.

Source code in src/tdfpy/lookup.py
244
245
def __init__(self, targets: dict[int, PrmTarget]):
    self._targets = targets

get

get(target_id: int, default=None)

Return the target with the given ID, or default if not found.

Source code in src/tdfpy/lookup.py
258
259
260
def get(self, target_id: int, default=None):
    """Return the target with the given ID, or `default` if not found."""
    return self._targets.get(target_id, default)

query_range

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

Query targets by m/z, RT, and/or 1/K0 ranges.

Parameters:

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

Tuple of (min_mz, max_mz). If None, m/z filtering is skipped.

None
rt_range tuple[float, float] | None

Tuple of (min_rt, max_rt) in seconds. If None, RT filtering is skipped.

None
ook0_range tuple[float, float] | None

Tuple of (min_ook0, max_ook0). If None, 1/K0 filtering is skipped.

None

Yields:

Type Description
PrmTarget

PrmTarget objects matching the criteria.

Source code in src/tdfpy/lookup.py
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
def query_range(
    self,
    mz_range: tuple[float, float] | None = None,
    rt_range: tuple[float, float] | None = None,
    ook0_range: tuple[float, float] | None = None,
) -> Iterator[PrmTarget]:
    """Query targets by m/z, RT, and/or 1/K0 ranges.

    Args:
        mz_range: Tuple of (min_mz, max_mz). If None, m/z filtering is skipped.
        rt_range: Tuple of (min_rt, max_rt) in seconds. If None, RT filtering is skipped.
        ook0_range: Tuple of (min_ook0, max_ook0). If None, 1/K0 filtering is skipped.

    Yields:
        PrmTarget objects matching the criteria.
    """
    for target in self._targets.values():
        if mz_range is not None:
            if not (mz_range[0] <= target.monoisotopic_mz <= mz_range[1]):
                continue
        if rt_range is not None:
            if not (rt_range[0] <= target.time <= rt_range[1]):
                continue
        if ook0_range is not None:
            if not (ook0_range[0] <= target.one_over_k0 <= ook0_range[1]):
                continue
        yield target

query

query(
    mz: float | None = None,
    rt: float | None = None,
    ook0: float | None = None,
    mz_tolerance: float = 20.0,
    mz_tolerance_type: Literal["ppm", "da"] = "ppm",
    rt_tolerance: float = 30.0,
    ook0_tolerance: float = 0.05,
) -> Iterator[PrmTarget]

Query targets by m/z, RT, and/or 1/K0 with tolerances.

Parameters:

Name Type Description Default
mz float | None

Target m/z value. If None, m/z filtering is skipped.

None
rt float | None

Target retention time (in seconds). If None, RT filtering is skipped.

None
ook0 float | None

Target 1/K0 value. If None, 1/K0 filtering is skipped.

None
mz_tolerance float

Tolerance for m/z matching.

20.0
mz_tolerance_type Literal['ppm', 'da']

Unit for m/z tolerance ("ppm" or "da"). Default is "ppm".

'ppm'
rt_tolerance float

Tolerance for retention time matching (in seconds). Default is 30s.

30.0
ook0_tolerance float

Absolute tolerance for 1/K0 matching. Default is 0.05.

0.05

Yields:

Type Description
PrmTarget

PrmTarget objects matching the criteria.

Source code in src/tdfpy/lookup.py
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
def query(
    self,
    mz: float | None = None,
    rt: float | None = None,
    ook0: float | None = None,
    mz_tolerance: float = 20.0,
    mz_tolerance_type: Literal["ppm", "da"] = "ppm",
    rt_tolerance: float = 30.0,
    ook0_tolerance: float = 0.05,
) -> Iterator[PrmTarget]:
    """Query targets by m/z, RT, and/or 1/K0 with tolerances.

    Args:
        mz: Target m/z value. If None, m/z filtering is skipped.
        rt: Target retention time (in seconds). If None, RT filtering is skipped.
        ook0: Target 1/K0 value. If None, 1/K0 filtering is skipped.
        mz_tolerance: Tolerance for m/z matching.
        mz_tolerance_type: Unit for m/z tolerance ("ppm" or "da"). Default is "ppm".
        rt_tolerance: Tolerance for retention time matching (in seconds). Default is 30s.
        ook0_tolerance: Absolute tolerance for 1/K0 matching. Default is 0.05.

    Yields:
        PrmTarget objects matching the criteria.
    """
    choice("mz_tolerance_type", mz_tolerance_type, ("ppm", "da"))
    nonnegative("mz_tolerance", mz_tolerance)
    mz_range: tuple[float, float] | None = None
    if mz is not None:
        if mz_tolerance_type == "ppm":
            mz_range = (mz - mz * mz_tolerance / 1e6, mz + mz * mz_tolerance / 1e6)
        else:
            mz_range = (mz - mz_tolerance, mz + mz_tolerance)

    nonnegative("rt_tolerance", rt_tolerance)
    rt_range: tuple[float, float] | None = None
    if rt is not None:
        rt_range = (rt - rt_tolerance, rt + rt_tolerance)

    nonnegative("ook0_tolerance", ook0_tolerance)
    ook0_range: tuple[float, float] | None = None
    if ook0 is not None:
        ook0_range = (ook0 - ook0_tolerance, ook0 + ook0_tolerance)

    return self.query_range(
        mz_range=mz_range, rt_range=rt_range, ook0_range=ook0_range
    )

PRM Transition Lookup

PrmTransitionLookup gives access to PrmTransition objects — the individual MS2 acquisitions captured during the run. Indexing by target_id returns a list 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 (list — one per MS2 frame)
    transitions = prm.transitions[1]
    for t in transitions:
        print(t.frame_id, t.rt, t.collision_energy)
        peaks = t.peaks  # list of (mz, intensity) arrays 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.time, rt_tolerance=20.0):
        print(tr.frame_id, tr.isolation_mz)

tdfpy.PrmTransitionLookup

PrmTransitionLookup(transitions: list[PrmTransition])

Lookup for PRM transitions by target ID and RT.

Source code in src/tdfpy/lookup.py
341
342
343
344
345
346
347
348
def __init__(self, transitions: list[PrmTransition]):
    self._transitions = transitions
    self._target_map: dict[int, list[PrmTransition]] = {}
    for t in transitions:
        tid = t.target.target_id
        if tid not in self._target_map:
            self._target_map[tid] = []
        self._target_map[tid].append(t)

get

get(target_id: int, default=None)

Return transitions for the given target ID, or default if not found.

Source code in src/tdfpy/lookup.py
364
365
366
def get(self, target_id: int, default=None):
    """Return transitions for the given target ID, or `default` if not found."""
    return self._target_map.get(target_id, default)

query_range

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

Query transitions by target and/or retention time range.

Parameters:

Name Type Description Default
target int | PrmTarget | None

Target ID or PrmTarget to filter by. If None, all targets are included.

None
rt_range tuple[float, float] | None

Tuple of (min_rt, max_rt) in seconds. If None, RT filtering is skipped.

None

Yields:

Type Description
PrmTransition

PrmTransition objects matching the criteria.

Source code in src/tdfpy/lookup.py
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
def query_range(
    self,
    target: int | PrmTarget | None = None,
    rt_range: tuple[float, float] | None = None,
) -> Iterator[PrmTransition]:
    """Query transitions by target and/or retention time range.

    Args:
        target: Target ID or PrmTarget to filter by. If None, all targets are included.
        rt_range: Tuple of (min_rt, max_rt) in seconds. If None, RT filtering is skipped.

    Yields:
        PrmTransition objects matching the criteria.
    """
    target_id: int | None = None
    if target is not None:
        target_id = target.target_id if isinstance(target, PrmTarget) else target

    for transition in self._transitions:
        if target_id is not None:
            if transition.target.target_id != target_id:
                continue
        if rt_range is not None:
            if not (rt_range[0] <= transition.rt <= rt_range[1]):
                continue
        yield transition

query

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

Query transitions by target and/or retention time.

Parameters:

Name Type Description Default
target int | PrmTarget | None

Target ID or PrmTarget to filter by. If None, all targets are included.

None
rt float | None

Target retention time (in seconds). If None, RT filtering is skipped.

None
rt_tolerance float

Tolerance for retention time matching (in seconds). Default is 30s.

30.0

Yields:

Type Description
PrmTransition

PrmTransition objects matching the criteria.

Source code in src/tdfpy/lookup.py
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
def query(
    self,
    target: int | PrmTarget | None = None,
    rt: float | None = None,
    rt_tolerance: float = 30.0,
) -> Iterator[PrmTransition]:
    """Query transitions by target and/or retention time.

    Args:
        target: Target ID or PrmTarget to filter by. If None, all targets are included.
        rt: Target retention time (in seconds). If None, RT filtering is skipped.
        rt_tolerance: Tolerance for retention time matching (in seconds). Default is 30s.

    Yields:
        PrmTransition objects matching the criteria.
    """
    nonnegative("rt_tolerance", rt_tolerance)
    rt_range: tuple[float, float] | None = None
    if rt is not None:
        rt_range = (rt - rt_tolerance, rt + rt_tolerance)
    return self.query_range(target=target, rt_range=rt_range)