Skip to content

PRM Data Elements

Parallel Reaction Monitoring (PRM) experiments select a predefined list of precursor ions and collect high-resolution MS2 spectra for each across the chromatographic run. The two classes on this page represent those two levels of structure.

PrmTarget

A PrmTarget represents one entry in the instrument's target list — a single analyte defined by its m/z, charge state, expected retention time, and expected ion mobility. The instrument uses these values to schedule isolation windows and select the correct mobility range during data collection.

Each target accumulates back-references to all PrmTransition objects collected for it via the transitions field.

from tdfpy import PRM

with PRM("experiment.d") as prm:
    for target in prm.targets:
        print(
            f"Target {target.target_id}: "
            f"{target.precursor_mz:.4f} m/z, "
            f"charge {target.charge}, "
            f"RT {target.rt:.1f} s, "
            f"1/K0 {target.ook0:.3f}"
        )
        # All transitions collected for this target
        for tr in target.transitions:
            print(f"  Frame {tr.frame_id}, RT {tr.rt:.1f} s")

tdfpy.PrmTarget dataclass

PrmTarget(
    *,
    target_id: int,
    external_id: str | None,
    rt: float,
    ook0: float,
    precursor_mz: float,
    charge: int,
    description: str,
    transitions: tuple[PrmTransition, ...] = ()
)

A predefined PRM target ion from the PrmTargets table.

Field Type Description
target_id int Unique target ID
external_id str \| None External identifier
rt float Expected retention time in seconds
ook0 float Expected ion mobility 1/K0 (V·s/cm²)
precursor_mz float Target precursor m/z (the MonoisotopicMz column)
charge int Charge state
description str Target description
transitions tuple[PrmTransition, ...] Transitions acquired for this target

transitions is excluded from equality and hashing (each transition points back at its target).


PrmTransition

A PrmTransition represents a single MS2 acquisition event for a PRM target — one isolation window applied to a specific frame and mobility scan range. Multiple transitions are collected for each target as the analyte elutes across time.

PrmTransition provides .scan_peaks() for raw per-scan data and .centroid() for processed spectra, consistent with the DiaWindow and PasefFrameMsmsInfo APIs.

from tdfpy import PRM

with PRM("experiment.d") as prm:
    for transition in prm.transitions:
        print(
            f"Frame {transition.frame_id}, "
            f"target {transition.target.target_id}, "
            f"isolation {transition.isolation_mz:.3f} m/z, "
            f"CE {transition.collision_energy:.1f} eV"
        )
        # Centroided MS2 spectrum — shape (N, 3): [m/z, intensity, 1/K0]
        peaks = transition.centroid()
        break

tdfpy.PrmTransition dataclass

PrmTransition(
    *,
    frame_id: int,
    scan_num_begin: int,
    scan_num_end: int,
    isolation_mz: float,
    isolation_width: float,
    collision_energy: float,
    target: PrmTarget,
    rt: float,
    polarity: Polarity | None,
    _timsdata: TimsData = _timsdata_field()
)

Bases: _MobilityWindow

A PRM isolation window in one specific MS/MS frame.

One row of the PrmFrameMsMsInfo table: a contiguous range of mobility scans acquired with one isolation window and collision energy, linked to a PRM target.

Field Type Description
frame_id int Frame ID
scan_num_begin int First mobility scan (inclusive)
scan_num_end int Mobility scan range end (exclusive), so the range is [scan_num_begin, scan_num_end)
isolation_mz float Isolation window center m/z
isolation_width float Isolation window width in Th
collision_energy float Collision energy in eV
target PrmTarget Associated PRM target
rt float Retention time in seconds
polarity Polarity \| None "positive" / "negative", None if unknown

timsdata property

timsdata: TimsData

The reader's open :class:TimsData.

Raises:

Type Description
ReaderClosedError

If the reader that built this element was closed.

scan_num_range property

scan_num_range: tuple[int, int]

(scan_num_begin, scan_num_end), end exclusive.

isolation_mz_range property

isolation_mz_range: tuple[float, float]

Quadrupole isolation window (isolation_mz - width / 2, isolation_mz + width / 2), low first.

ms_level property

ms_level: int

MS level of the window's spectra: always 2 (an MS/MS isolation window).

ook0_range property

ook0_range: tuple[float, float]

(ook0_begin, ook0_end): lowest and highest 1/K0 (V·s/cm²) of the scan range, low first.

ook0_begin property

ook0_begin: float

Lowest 1/K0 (V·s/cm²) of the scan range.

ook0_end property

ook0_end: float

Highest 1/K0 (V·s/cm²) of the scan range.

ccs_range property

ccs_range: tuple[float, float]

(ccs_begin, ccs_end): CCS (Ų) range for charge 1 at isolation_mz, low first.

ccs_begin property

ccs_begin: float

Lowest CCS (Ų) of the scan range, for charge 1 at isolation_mz.

ccs_end property

ccs_end: float

Highest CCS (Ų) of the scan range, for charge 1 at isolation_mz.

voltage_range property

voltage_range: tuple[float, float]

(voltage_begin, voltage_end): TIMS voltage (V) range of the scan range, low first.

voltage_begin property

voltage_begin: float

Lowest TIMS voltage (V) of the scan range.

voltage_end property

voltage_end: float

Highest TIMS voltage (V) of the scan range.

scan_peaks

scan_peaks() -> list[npt.NDArray[np.float64]]

Raw peaks, one (N_i, 2) [m/z, intensity] float64 array per mobility scan.

The list has one entry per scan in this element's scan range, in scan order; empty scans give a (0, 2) array.

Raises:

Type Description
ReaderClosedError

If the reader was closed.

TdfpyError

If a window's scan range does not fit its frame (corrupt file).

Source code in src/tdfpy/elems.py
def scan_peaks(self) -> list[npt.NDArray[np.float64]]:
    """Raw peaks, one ``(N_i, 2)`` ``[m/z, intensity]`` float64 array per mobility scan.

    The list has one entry per scan in this element's scan range, in scan
    order; empty scans give a ``(0, 2)`` array.

    Raises:
        ReaderClosedError: If the reader was closed.
        TdfpyError: If a window's scan range does not fit its frame (corrupt file).
    """
    td = self.timsdata
    bounds = self._scan_bounds()
    begin, end = bounds if bounds is not None else (0, td.frame_metadata(self.frame_id).num_scans)
    arrays = []
    for index_array, int_array in td.read_scans(self.frame_id, begin, end):
        mz_array = td.index_to_mz(self.frame_id, index_array)
        arrays.append(np.stack((mz_array, int_array), axis=-1).astype(np.float64))
    return arrays

raw_peaks

raw_peaks(
    *,
    exclude: ChargeStateRegion | None = None,
    smooth: Smooth | None = None,
    noise: NoiseSpec = None,
    mobility_type: MobilityType = "ook0"
) -> npt.NDArray[np.float64]

Raw peaks as one (N, 3) [m/z, intensity, ion_mobility] array.

Restricted to this element's scan range. See :func:tdfpy.get_raw_peaks for the keyword arguments.

Raises:

Type Description
ReaderClosedError

If the reader was closed.

TdfpyError

If a window's scan range does not fit its frame (corrupt file).

Source code in src/tdfpy/elems.py
def raw_peaks(
    self,
    *,
    exclude: ChargeStateRegion | None = None,
    smooth: Smooth | None = None,
    noise: NoiseSpec = None,
    mobility_type: MobilityType = "ook0",
) -> npt.NDArray[np.float64]:
    """Raw peaks as one ``(N, 3)`` ``[m/z, intensity, ion_mobility]`` array.

    Restricted to this element's scan range. See :func:`tdfpy.get_raw_peaks`
    for the keyword arguments.

    Raises:
        ReaderClosedError: If the reader was closed.
        TdfpyError: If a window's scan range does not fit its frame (corrupt file).
    """
    return get_raw_peaks(
        self.timsdata,
        self.frame_id,
        scan_range=self._scan_bounds(),
        exclude=exclude,
        smooth=smooth,
        noise=noise,
        mobility_type=mobility_type,
    )

centroid

centroid(
    *,
    exclude: ChargeStateRegion | None = None,
    smooth: Smooth | None = None,
    noise: NoiseSpec = None,
    mobility_type: MobilityType = "ook0",
    centroid: Centroider | None = None
) -> npt.NDArray[np.float64]

Centroided peaks as one (N, 3) [m/z, intensity, ion_mobility] array.

Restricted to this element's scan range. The raw-peak keywords are passed to :func:tdfpy.get_raw_peaks; centroider settings live on :class:~tdfpy.Centroider (default :class:~tdfpy.MergePeaksCentroider).

Raises:

Type Description
ReaderClosedError

If the reader was closed.

TdfpyError

If a window's scan range does not fit its frame (corrupt file).

Source code in src/tdfpy/elems.py
def centroid(
    self,
    *,
    exclude: ChargeStateRegion | None = None,
    smooth: Smooth | None = None,
    noise: NoiseSpec = None,
    mobility_type: MobilityType = "ook0",
    centroid: Centroider | None = None,
) -> npt.NDArray[np.float64]:
    """Centroided peaks as one ``(N, 3)`` ``[m/z, intensity, ion_mobility]`` array.

    Restricted to this element's scan range. The raw-peak keywords are
    passed to :func:`tdfpy.get_raw_peaks`; centroider settings live on
    :class:`~tdfpy.Centroider` (default :class:`~tdfpy.MergePeaksCentroider`).

    Raises:
        ReaderClosedError: If the reader was closed.
        TdfpyError: If a window's scan range does not fit its frame (corrupt file).
    """
    return get_centroided_spectrum(
        self.timsdata,
        self.frame_id,
        scan_range=self._scan_bounds(),
        exclude=exclude,
        smooth=smooth,
        noise=noise,
        mobility_type=mobility_type,
        centroid=centroid,
    )