Skip to content

Validation and filtering

mzmlpy.validate

validate(
    file: str | Path,
    *,
    decode_binary: bool = False,
    check_index: bool = False
) -> ValidationReport

Validate plain or gzip mzML without creating or repairing caches.

The default checks XML structure, list counts, IDs, references, index ID agreement, and supported array metadata. Set decode_binary to decode every array and compare lengths. Set check_index to seek to XML footer offsets and verify their targets. This does not perform full XSD, controlled-vocabulary, or embedded gzip index validation. Memory grows with IDs, references, and findings, plus the largest record.

File-open errors raise OSError. Malformed content is returned as report issues.

Source code in src/mzmlpy/validation.py
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
def validate(file: str | Path, *, decode_binary: bool = False, check_index: bool = False) -> ValidationReport:
    """Validate plain or gzip mzML without creating or repairing caches.

    The default checks XML structure, list counts, IDs, references, index ID agreement,
    and supported array metadata. Set decode_binary to decode every array and compare
    lengths. Set check_index to seek to XML footer offsets and verify their targets.
    This does not perform full XSD, controlled-vocabulary, or embedded gzip index validation.
    Memory grows with IDs, references, and findings, plus the largest record.

    File-open errors raise OSError. Malformed content is returned as report issues.
    """
    with open(file, "rb") as raw:
        compressed = raw.read(2) == b"\x1f\x8b"
        raw.seek(0)
        if compressed:
            with gzip.GzipFile(fileobj=raw) as handle:
                return _validate_stream(cast(BinaryIO, handle), decode_binary=decode_binary, check_index=check_index)
        return _validate_stream(raw, decode_binary=decode_binary, check_index=check_index)

mzmlpy.ValidationReport dataclass

ValidationReport(
    issues: tuple[ValidationIssue, ...],
    spectrum_count: int,
    chromatogram_count: int,
    arrays_decoded: int,
    index_entries_checked: int,
    complete: bool,
    decode_binary: bool,
    check_index: bool,
)

Results of the requested checks, without claiming full schema or ontology validation.

Structural validation scans XML and records IDs and references without decoding arrays. Binary decoding and byte-offset verification are explicit, potentially expensive options.

valid property

valid: bool

Whether parsing completed and the requested checks found no errors.

to_dict

to_dict() -> dict

Return JSON-serializable results, including the computed valid flag.

Source code in src/mzmlpy/validation.py
62
63
64
def to_dict(self) -> dict:
    """Return JSON-serializable results, including the computed valid flag."""
    return {"valid": self.valid, **asdict(self)}

mzmlpy.ValidationIssue dataclass

ValidationIssue(
    code: str,
    message: str,
    location: str,
    severity: Literal["error", "warning"] = "error",
)

One machine-readable finding with a stable code and an XML location.

mzmlpy.SpectrumFilter dataclass

SpectrumFilter(
    ms_level: int | None = None,
    retention_time: (
        tuple[float | None, float | None] | None
    ) = None,
    polarity: Literal["positive", "negative"] | None = None,
    precursor_mz: (
        tuple[float | None, float | None] | None
    ) = None,
    spectrum_type: (
        Literal["centroid", "profile"] | None
    ) = None,
    mobility_type: (
        Literal["inverse_reduced", "drift_time"] | None
    ) = None,
    ion_mobility: (
        tuple[float | None, float | None] | None
    ) = None,
    faims_voltage: (
        tuple[float | None, float | None] | None
    ) = None,
)

Combine metadata criteria with AND, without decoding binary arrays.

Retention times are inclusive bounds in seconds, matched against any scan. Precursor m/z bounds overlap any reported isolation window, or match a selected ion when that precursor has no usable isolation window. Missing metadata does not match a requested criterion. Either range endpoint may be None for an open bound.

matches

matches(spectrum: Spectrum) -> bool

Return whether a spectrum satisfies every supplied criterion.

Source code in src/mzmlpy/filtering.py
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
def matches(self, spectrum: Spectrum) -> bool:
    """Return whether a spectrum satisfies every supplied criterion."""
    if self.spectrum_type is not None and spectrum.spectrum_type != self.spectrum_type:
        return False
    if self.mobility_type is not None:
        attribute = (
            "inverse_reduced_ion_mobility" if self.mobility_type == "inverse_reduced" else "ion_mobility_drift_time"
        )
        if not any(_within(getattr(scan, attribute), self.ion_mobility or (None, None)) for scan in spectrum.scans):
            return False
    if self.faims_voltage is not None:
        if not any(_within(scan.faims_compensation_voltage, self.faims_voltage) for scan in spectrum.scans):
            return False
    if self.ms_level is not None and spectrum.ms_level != self.ms_level:
        return False
    if self.polarity is not None and spectrum.polarity != self.polarity:
        return False
    if self.retention_time is not None:
        if not any(
            (time := scan.scan_start_time) is not None and _within(time.total_seconds(), self.retention_time)
            for scan in spectrum.scans
        ):
            return False
    if self.precursor_mz is not None and not self._matches_precursor(spectrum):
        return False
    return True