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
16
17
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
32
33
34
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
129
130
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
145
146
147
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.

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.

Source code in src/tdfpy/lookup.py
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
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.

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 20s.

Yields: Precursor objects matching the criteria.

Note: Uses monoisotopic_mz if available, otherwise largest_peak_mz.

Source code in src/tdfpy/lookup.py
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
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 20s.

    Yields:
        Precursor objects matching the criteria.

    Note:
        Uses `monoisotopic_mz` if available, otherwise `largest_peak_mz`.
    """
    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)

    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
44
45
46
47
48
49
50
51
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
66
67
68
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.

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.

Source code in src/tdfpy/lookup.py
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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_index:
                    continue
            elif window.window_index != 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.

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.

Source code in src/tdfpy/lookup.py
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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.
    """
    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
218
219
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
232
233
234
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.

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.

Source code in src/tdfpy/lookup.py
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
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.

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.

Source code in src/tdfpy/lookup.py
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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
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.
    """
    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)

    rt_range: tuple[float, float] | None = None
    if rt is not None:
        rt_range = (rt - rt_tolerance, rt + rt_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
309
310
311
312
313
314
315
316
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
330
331
332
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.

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.

Source code in src/tdfpy/lookup.py
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
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.

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.

Source code in src/tdfpy/lookup.py
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
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.
    """
    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)