Skip to main content

spectrl

Inline spectrum URL encoder for mass spectrometry.

Encodes a complete mass spectrum — peaks, metadata, precursor info — into a single compact, URL-safe token. The entire spectrum lives in the string. No backend required.

spectrl1.<base64url(CBOR document)>

Why

A USI references a spectrum stored in a repository. spectrl embeds it. Use spectrl when you want to share a spectrum directly in a URL, QR code, notebook, or paper — without requiring the reader to have access to the original file.

The two are complementary: a spectrl token can carry a USI back-link, and spectra too large to embed fall back to a USI reference.

Install

pip install spectrl

Requires Python 3.12+.

Quick start

Encode from mzmlpy

from mzmlpy.run import Mzml
from spectrl import encode_spectrum, from_mzmlpy

with Mzml("data.mzML") as mzml:
    spec = mzml.spectra[0]
    token = encode_spectrum(from_mzmlpy(spec))

print(token)
# spectrl1.hQ...

Encode manually

import numpy as np
from spectrl import encode_spectrum
from spectrl.model import InlineSpectrum, SpectrlCvParam

spec = InlineSpectrum(
    default_array_length=3,
    mz=np.array([147.0, 175.1, 246.2]),
    intensity=np.array([1e5, 8e4, 3e4]),
    id="scan=42",
    params=[
        SpectrlCvParam(accession="MS:1000511", value=2),   # ms level
        SpectrlCvParam(accession="MS:1000130"),             # positive scan
        SpectrlCvParam(accession="MS:1000127"),             # centroid
    ],
)

token = encode_spectrum(spec)

Decode

from spectrl import decode_token

decoded = decode_token(token)
print(decoded.mz)        # numpy array
print(decoded.intensity) # numpy array
print(decoded.id)        # "scan=42"

URL bindings

from spectrl import to_fragment, to_query, to_data_uri, extract_token

# Embed in a URL fragment (recommended — never sent to server)
url = to_fragment(token, "https://viewer.example.com/spectrum")
# https://viewer.example.com/spectrum#spectrl1.hQ...

# Or as a query parameter
url = to_query(token, "https://viewer.example.com/spectrum")
# https://viewer.example.com/spectrum?d=spectrl1.hQ...

# Or as a data URI
uri = to_data_uri(token)
# data:application/vnd.spectrl;v=1,spectrl1.hQ...

# Extract token back from any of the above
token = extract_token(url)

Extra (auxiliary) arrays

Beyond m/z, intensity, charge, and ion mobility, you can attach any per-peak array — keyed by a CV accession (a standard mzML binary array) or a free-text name (a non-standard MS:1000786 array). int32/float32 dtypes are preserved.

import numpy as np
from spectrl import encode_spectrum, decode_token
from spectrl.model import InlineSpectrum

spec = InlineSpectrum(
    default_array_length=3,
    mz=np.array([147.0, 175.1, 246.2]),
    intensity=np.array([1e5, 8e4, 3e4]),
    extra_arrays={
        "MS:1000517": np.array([120.0, 80.0, 45.0]),         # signal-to-noise array (named CV)
        "iso_score": np.array([0.98, 0.91, 0.74], np.float32),  # non-standard (MS:1000786)
    },
)
decoded = decode_token(encode_spectrum(spec))
decoded.extra_arrays["iso_score"]  # float32 array, round-tripped

Auxiliary arrays are always lossless (raw + zlib) and ride along with the canonical m/z sort. The JavaScript implementation exposes the same via extraArrays (use Int32Array/Float32Array to set the data type).

User params (free-text metadata)

For values with no CV term, attach mzML userParams at the spectrum or scan level. They're omitted entirely when empty, so a spectrum without any is byte-identical to one produced before the feature existed.

from spectrl.model import InlineSpectrum, SpectrlUserParam

spec = InlineSpectrum(
    default_array_length=3, mz=mz, intensity=intensity,
    user_params=[
        SpectrlUserParam(name="Mascot score", value=42.7, type="xsd:float"),
        SpectrlUserParam(name="reanalysis note", value="rerun semitryptic"),
    ],
)

from_mzmlpy reads spectrum- and scan-level userParams automatically. The JS implementation exposes the same via userParams. Prefer a CV term whenever one exists — userParams are heavier (no accession to compress) and uncontrolled.

Trim large spectra

from spectrl import top_n

# Keep the 50 most intense peaks before encoding
trimmed = top_n(spec, 50)
token = encode_spectrum(trimmed)

Lossless encoding

# Default is lossy MS-Numpress (~0.003 mDa m/z error, ~0.007% intensity error)
# Use lossless=True for bit-exact IEEE-754 doubles
token = encode_spectrum(spec, lossless=True)

Token format

spectrl1.<base64url(CBOR document)>
  • spectrl1 — magic + format version; clean version bumps.
  • The payload is a single CBOR document (RFC 8949), base64url-encoded without padding (RFC 4648 §5). Because it's self-contained, the raw CBOR bytes can also be shipped directly (no base64) as a backend/body payload.
  • Header — a CBOR map with integer keys mirroring mzML structure: ms level, polarity, scan times, precursor isolation window, activation method, collision energy, ProForma interpretation, and a truncated SHA-256 content hash.
  • Array blobs — one per array type (m/z, intensity, charge, ion mobility, plus any auxiliary arrays), each encoded as MS-Numpress (lossy) or raw IEEE-754 (lossless) + zlib — matching mzML's binaryDataArray pipeline — and embedded inline in the CBOR document as a byte string.

Encoding precision

Measured over 479,455 peaks from a real LC-MS/MS dataset (BSA, Orbitrap):

Array Mean error Max error
m/z (MS-Numpress linear) 0.0025 mDa / 0.006 ppm 0.005 mDa / 0.056 ppm
Intensity (MS-Numpress slof) 0.007% relative 0.029% relative

Size vs mzML

Measured on the same BSA dataset (1,684 spectra):

Format MS1 avg (545 peaks) MS2 avg (109 peaks)
Raw mzML XML 12,876 B 6,004 B
spectrl (lossy) 4,241 B 1,340 B
spectrl (lossless) 10,302 B 1,909 B

CLI

# Encode from JSON
echo '{"mz":[147.0,175.1],"intensity":[1e5,8e4]}' | spectrl encode

# Decode a token
echo "spectrl1.hQ..." | spectrl decode

# Inspect the header as readable JSON
echo "spectrl1.hQ..." | spectrl inspect

Demo

A browser demo encodes example spectra live, shows the shareable URL + QR, and decodes + plots them entirely client-side (no server). Launch it with:

just demo   # → http://127.0.0.1:8000

See demo/ for details.

Design

  • mzML-faithful — metadata is carried as CV accession maps (MS: ontology), mirroring mzML cvParam semantics. No invented field names.
  • CV binding — all accession constants come from mzmlpy's StrEnum enums; no hardcoded integers.
  • Deterministic (within an implementation) — canonical form (m/z-ascending, fixed numpress scale factors, RFC 8949 §4.2 CBOR) yields a stable token from a given implementation, plus a truncated SHA-256 content hash (key 9) verified on decode as a transport-integrity check. The hash is verified by byte-surgery on the received bytes, so it's independent of the CBOR library. Token bytes are not guaranteed identical across implementations (DEFLATE output is not canonical); see SPECIFICATION.md.
  • ProForma — carries a ProForma 2.0 peptide interpretation string (key 8), the same mechanism used by USI.

Specification

The normative token format is specified in SPECIFICATION.md (draft, intended for submission to HUPO-PSI). This README is a tutorial; the specification is the contract. A machine-readable CV/codec/key registry lives in schema/registry.json.

Contributing

See CONTRIBUTING.md and the Code of Conduct. Changes to the on-the-wire token format are governed more strictly — see the Format changes section of the contributing guide.

License

Licensed under the Apache License 2.0. If you use spectrl in research, please cite it via CITATION.cff.

Related

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spectrl-0.2.2.tar.gz (5.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spectrl-0.2.2-py3-none-any.whl (34.8 kB view details)

Uploaded Python 3

File details

Details for the file spectrl-0.2.2.tar.gz.

File metadata

  • Download URL: spectrl-0.2.2.tar.gz
  • Upload date:
  • Size: 5.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for spectrl-0.2.2.tar.gz
Algorithm Hash digest
SHA256 8912b349358c129dcb2e0bc0b9c32d2cba18315d21a5657bbb8c71bc873fc00e
MD5 f5ccded9ad7f745f3b09933d7c11fa9d
BLAKE2b-256 6241f70635ba643425f7fa26ae93bb303cbbc1b1bcd5daa5ff8d572e91f87486

See more details on using hashes here.

Provenance

The following attestation bundles were made for spectrl-0.2.2.tar.gz:

Publisher: publish.yml on pgarrett-scripps/spectrl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file spectrl-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: spectrl-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 34.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for spectrl-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b27819f586f418b4f50647098042066d3e2fb847ed60ff6e1a3a6ab4c3ab5e1a
MD5 db966a3c3329550417f30e212b885740
BLAKE2b-256 d56e9c1613c527c772a2bda1200c7af0e0716bf9963e59c01ecb94e445d88b4e

See more details on using hashes here.

Provenance

The following attestation bundles were made for spectrl-0.2.2-py3-none-any.whl:

Publisher: publish.yml on pgarrett-scripps/spectrl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

2.1.0

2 files

2.0.0

2 files

1.1.0

2 files

1.0.0

2 files

0.4.0

2 files

This release

0.2.2 This release

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page