Usage
Quick Start
There are 3 parsing methods available:
* parse: Parses a single or multiple comma-separated mzPAF annotations. Returns a single PafAnnotation or a list of them.
* parse_multi: Parses multiple comma-separated mzPAF annotations. Always returns a list of PafAnnotation.
* parse_single: Parses a single mzPAF annotation. Returns a single PafAnnotation. Raises ValueError if multiple annotations are provided.
import paftacular as pft
# Parse a simple peptide ion
ann = pft.parse("y5")
print(ann.ion_type.series)
print(ann.ion_type.position)
y
5
# Parse with modifications
ann = pft.parse_single("y5-H2O^2/1.2ppm*0.95")
print(ann.charge)
print(ann.mass_error.value)
print(ann.confidence)
2
1.2
0.95
Basic Peptide Ions
import paftacular as pft
# Primary fragment ions (a, b, c, x, y, z series)
ann = pft.parse("b2")
print(ann.ion_type.series)
ann = pft.parse("y3")
print(ann.ion_type.series)
b
y
# With peptide sequence
ann = pft.parse("y3{PEP}")
print(ann.ion_type.sequence)
PEP
# Internal fragments
ann = pft.parse("m2:5{PEPTIDE}")
print(ann.ion_type.start_position)
print(ann.ion_type.end_position)
2
5
Other Ion Types
import paftacular as pft
# Precursor ion
ann = pft.parse("p^2") # Doubly-charged precursor
# Immonium ions
ann = pft.parse("IK") # Lysine immonium
ann = pft.parse("IK[Acetyl]") # Modified
# Reference compounds
ann = pft.parse("r[TMT126]")
# Chemical formula
ann = pft.parse("f{C6H12O6}")
# SMILES notation
ann = pft.parse("s{CN=C=O}")
# Unannotated/unknown peaks
ann = pft.parse("?")
ann = pft.parse("?42") # With reporter number
Modifications
import paftacular as pft
# Neutral losses (formula-based)
ann = pft.parse("y5-H2O")
ann = pft.parse("b3-NH3")
ann = pft.parse("b2-H2O-NH3") # Multiple losses
# Neutral gains
ann = pft.parse("y5+NH3")
# Mass-based losses/gains
ann = pft.parse("y5-17.03")
ann = pft.parse("b2+22.98")
# Reference-based
ann = pft.parse("y5-[Adenine]")
Isotopes
import paftacular as pft
# Generic isotope peak
ann = pft.parse("y5+i")
# Specific element
ann = pft.parse("y5+i13C")
ann = pft.parse("b2+2i13C") # Multiple isotopes
# Average isotopomer
ann = pft.parse("y5+iA")
Adducts
import paftacular as pft
# Single adduct
ann = pft.parse("y5[M+Na]")
# Multiple adducts
ann = pft.parse("y5[M+2H+Na]")
ann = pft.parse("p[M+NH4]")
Charge States
import paftacular as pft
# Singly charged (default)
ann = pft.parse("y5")
print(ann.charge) # 1
# Doubly charged
ann = pft.parse("y5^2")
print(ann.charge) # 2
# Triply charged
ann = pft.parse("b3^3")
print(ann.charge) # 3
Mass Errors and Confidence
import paftacular as pft
# Mass error in ppm
ann = pft.parse("y5/1.2ppm")
print(ann.mass_error.value) # 1.2
print(ann.mass_error.unit) # "ppm"
# Mass error in daltons
ann = pft.parse("y5/-0.003da")
# Confidence score (0.0 to 1.0)
ann = pft.parse("y5*0.95")
print(ann.confidence) # 0.95
# Combined
ann = pft.parse("y5/1.2ppm*0.95")
Complex Annotations
import paftacular as pft
# Everything at once
ann = pft.parse("&2@y5-H2O+i13C[M+H+Na]^2/-0.55ppm*0.85")
print(ann.is_auxiliary) # True (& flag)
print(ann.analyte_reference) # 2 (@ reference)
print(ann.ion_type.series) # IonSeries.Y
print(ann.ion_type.position) # 5
print(ann.neutral_mods) # Tuple with H2O loss
print(ann.isotopes) # Tuple with 13C isotope
print(ann.adducts) # Tuple with H and Na
print(ann.charge) # 2
print(ann.mass_error.value) # -0.55
print(ann.confidence) # 0.85
Mass Calculations
import paftacular as pft
# Get calculated masses
ann = pft.parse("y5")
print(ann.monoisotopic_mass) # Monoisotopic mass
print(ann.average_mass) # Average mass
print(ann.mass) # Defaults to monoisotopic
# With modifications
ann = pft.parse("y5-H2O")
print(ann.monoisotopic_mass) # Mass adjusted for water loss
# Get composition
ann = pft.parse("f{C6H12O6}")
comp = ann.composition # Counter with ElementInfo keys
print(ann.formula) # "C6H12O6"
print(ann.proforma_formula) # ProForma-style formula
Parsing Multiple Annotations
import paftacular as pft
# Parse comma-separated list (can also use parse_multi)
annotations = pft.parse("b2, y3-H2O, p^2")
for ann in annotations:
print(ann.serialize())
b2
y3-H2O
p^2
Creating Annotations Programmatically
Instead of parsing strings, you can create annotations directly using factory methods.
Basic Factory Methods
from paftacular import PafAnnotation
# Create a precursor ion
ann = PafAnnotation.make_precursor()
print(ann.serialize())
p
# Create a peptide fragment ion
ann = PafAnnotation.make_peptide("y", 5)
print(ann.serialize())
y5
# Create an internal fragment
ann = PafAnnotation.make_internal(start_position=2, end_position=5)
print(ann.serialize())
m2:5
# Create an immonium ion
ann = PafAnnotation.make_immonium("K")
print(ann.serialize())
IK
# Create a reference ion
ann = PafAnnotation.make_reference("TMT126")
print(ann.serialize())
r[TMT126]
Adding Modifications
All factory methods accept common parameters for modifications.
from paftacular import PafAnnotation
# Add neutral losses
ann = PafAnnotation.make_peptide("y", 5, neutral_losses=["-H2O", "-NH3"])
print(ann.serialize())
y5-H2O-NH3
# Add isotopes
ann = PafAnnotation.make_peptide("b", 3, isotopes=["+i13C", "+i15N"])
print(ann.serialize())
b3+i13C+i15N
# Add adducts
ann = PafAnnotation.make_precursor(adducts=["+H", "+Na"])
print(ann.serialize())
p[M+H+Na]
# Add charge state
ann = PafAnnotation.make_peptide("y", 5, charge=2)
print(ann.serialize())
y5^2
# Add mass error (in ppm)
ann = PafAnnotation.make_peptide("y", 5, mass_error=1.2, mass_error_unit="ppm")
print(ann.serialize())
y5/1.2ppm
# Add confidence score
ann = PafAnnotation.make_peptide("y", 5, confidence=0.95)
print(ann.serialize())
y5*0.95
Complex Annotations
Combine multiple parameters to create complex annotations.
from paftacular import PafAnnotation
# Everything at once
ann = PafAnnotation.make_peptide(
"y", 5,
neutral_losses=["-H2O"],
isotopes=["+i13C"],
adducts=["+H", "+Na"],
charge=2,
mass_error=-0.55,
mass_error_unit="ppm",
confidence=0.85,
is_auxiliary=True,
analyte_reference=2
)
print(ann.serialize())
&2@y5-H2O+i13C[M+H+Na]^2/-0.55ppm*0.85
With Sequences
from paftacular import PafAnnotation
# Peptide ion with sequence
ann = PafAnnotation.make_peptide("y", 3, sequence="PEP")
print(ann.serialize())
y3{PEP}
# Internal fragment with sequence
ann = PafAnnotation.make_internal(2, 5, sequence="PEPTIDE")
print(ann.serialize())
m2:5{PEPTIDE}
# Modified immonium ion
ann = PafAnnotation.make_immonium("M", modification="Oxidation")
print(ann.serialize())
IM[Oxidation]
Other Ion Types
from paftacular import PafAnnotation
# Chemical formula
ann = PafAnnotation.make_formula("C6H12O6")
print(ann.serialize())
f{C6H12O6}
# SMILES notation
ann = PafAnnotation.make_smiles("CN=C=O")
print(ann.serialize())
s{CN=C=O}
# Named compound
ann = PafAnnotation.make_named_compound("Urocanic Acid")
print(ann.serialize())
_{Urocanic Acid}
# Unknown ion
ann = PafAnnotation.make_unknown(label=42)
print(ann.serialize())
?42
Serialization (Round-trip)
import paftacular as pft
# Parse and serialize back
original = "y5-H2O^2/1.2ppm*0.95"
ann = pft.parse(original)
serialized = ann.serialize()
print(serialized)
y5-H2O^2/1.2ppm*0.95
Export to Dictionary
import paftacular as pft
# Export annotation as dictionary (e.g., for JSON)
ann = pft.parse("y5-H2O^2/1.2ppm*0.95")
data = ann.as_dict()
Peptacular Integration
paftacular integrates with peptacular
to convert its Fragment objects directly into PafAnnotation objects via to_mzpaf().
import peptacular as pt
import paftacular as pft
# Generate fragment ions from a peptide sequence
fragments = pt.fragment("PEPTIDE", charges=[1, 2], ion_types=["y", "b"])
# Convert each fragment to a PafAnnotation
annotations = [pft.to_mzpaf(f) for f in fragments]
for ann in annotations[:3]:
print(ann.serialize())
# b1{P}
# b2{PE}
# b3{PEP}
Optional parameters let you attach a mass error and confidence score to each annotation:
ann = pft.to_mzpaf(
fragments[0],
confidence=0.95,
mass_error=1.2,
mass_error_type="ppm",
)
print(ann.serialize()) # b1{P}/1.2ppm*0.95
Pass include_annotation=False to omit the embedded sequence from the annotation
(useful when sequence context is not needed):
ann = pft.to_mzpaf(fragments[0], include_annotation=False)
print(ann.serialize()) # b1
For more details, see the PSI mzPAF specification.