0
# Chemistry and Molecular Properties
1
2
Chemical calculations including empirical formulas, isotope distributions, elemental compositions, and theoretical spectrum generation. Essential for accurate mass calculations and spectral interpretation.
3
4
## Capabilities
5
6
### Molecular Formulas
7
8
#### EmpiricalFormula
9
10
Chemical formula representation with isotope support and mass calculations.
11
12
```python { .api }
13
class EmpiricalFormula:
14
def __init__(self, formula: str = "") -> None:
15
"""
16
Create empirical formula.
17
18
Args:
19
formula (str): Chemical formula string (e.g., "C6H12O6")
20
"""
21
22
def getMonoWeight(self) -> float:
23
"""
24
Get monoisotopic molecular weight.
25
26
Returns:
27
float: Monoisotopic weight in Da
28
"""
29
30
def getAverageWeight(self) -> float:
31
"""
32
Get average molecular weight.
33
34
Returns:
35
float: Average weight in Da
36
"""
37
38
def toString(self) -> str:
39
"""
40
Get formula as string.
41
42
Returns:
43
str: Chemical formula string
44
"""
45
46
def isEmpty(self) -> bool:
47
"""
48
Check if formula is empty.
49
50
Returns:
51
bool: True if empty formula
52
"""
53
54
def getNumberOf(self, element: str) -> int:
55
"""
56
Get number of atoms for element.
57
58
Args:
59
element (str): Element symbol
60
61
Returns:
62
int: Number of atoms
63
"""
64
65
def setNumberOf(self, element: str, number: int) -> None:
66
"""
67
Set number of atoms for element.
68
69
Args:
70
element (str): Element symbol
71
number (int): Number of atoms
72
"""
73
74
def getNumberOfAtoms(self) -> int:
75
"""
76
Get total number of atoms.
77
78
Returns:
79
int: Total atom count
80
"""
81
82
def getElements(self) -> set[str]:
83
"""
84
Get all elements in formula.
85
86
Returns:
87
set[str]: Set of element symbols
88
"""
89
90
def __add__(self, other: EmpiricalFormula) -> EmpiricalFormula:
91
"""
92
Add formulas.
93
94
Args:
95
other (EmpiricalFormula): Formula to add
96
97
Returns:
98
EmpiricalFormula: Sum of formulas
99
"""
100
101
def __sub__(self, other: EmpiricalFormula) -> EmpiricalFormula:
102
"""
103
Subtract formulas.
104
105
Args:
106
other (EmpiricalFormula): Formula to subtract
107
108
Returns:
109
EmpiricalFormula: Difference of formulas
110
"""
111
112
def __mul__(self, factor: int) -> EmpiricalFormula:
113
"""
114
Multiply formula by factor.
115
116
Args:
117
factor (int): Multiplication factor
118
119
Returns:
120
EmpiricalFormula: Multiplied formula
121
"""
122
123
@staticmethod
124
def fromString(formula: str) -> EmpiricalFormula:
125
"""
126
Parse formula from string.
127
128
Args:
129
formula (str): Formula string
130
131
Returns:
132
EmpiricalFormula: Parsed formula
133
"""
134
```
135
136
### Elements and Isotopes
137
138
#### Element
139
140
Chemical element with isotope information.
141
142
```python { .api }
143
class Element:
144
def __init__(self) -> None: ...
145
146
def getName(self) -> str:
147
"""
148
Get element name.
149
150
Returns:
151
str: Full element name
152
"""
153
154
def setName(self, name: str) -> None:
155
"""
156
Set element name.
157
158
Args:
159
name (str): Element name
160
"""
161
162
def getSymbol(self) -> str:
163
"""
164
Get element symbol.
165
166
Returns:
167
str: Chemical symbol
168
"""
169
170
def setSymbol(self, symbol: str) -> None:
171
"""
172
Set element symbol.
173
174
Args:
175
symbol (str): Chemical symbol
176
"""
177
178
def getAtomicNumber(self) -> int:
179
"""
180
Get atomic number.
181
182
Returns:
183
int: Atomic number
184
"""
185
186
def setAtomicNumber(self, number: int) -> None:
187
"""
188
Set atomic number.
189
190
Args:
191
number (int): Atomic number
192
"""
193
194
def getAverageWeight(self) -> float:
195
"""
196
Get average atomic weight.
197
198
Returns:
199
float: Average weight in Da
200
"""
201
202
def setAverageWeight(self, weight: float) -> None:
203
"""
204
Set average weight.
205
206
Args:
207
weight (float): Average weight
208
"""
209
210
def getMonoWeight(self) -> float:
211
"""
212
Get monoisotopic weight.
213
214
Returns:
215
float: Monoisotopic weight in Da
216
"""
217
218
def setMonoWeight(self, weight: float) -> None:
219
"""
220
Set monoisotopic weight.
221
222
Args:
223
weight (float): Monoisotopic weight
224
"""
225
226
def getIsotopeDistribution(self) -> IsotopeDistribution:
227
"""
228
Get natural isotope distribution.
229
230
Returns:
231
IsotopeDistribution: Isotope distribution
232
"""
233
234
def setIsotopeDistribution(self, distribution: IsotopeDistribution) -> None:
235
"""
236
Set isotope distribution.
237
238
Args:
239
distribution (IsotopeDistribution): Isotope distribution
240
"""
241
242
class ElementDB:
243
@staticmethod
244
def getInstance() -> ElementDB:
245
"""
246
Get singleton instance.
247
248
Returns:
249
ElementDB: Element database instance
250
"""
251
252
def getElement(self, name: str) -> Element:
253
"""
254
Get element by name or symbol.
255
256
Args:
257
name (str): Element name or symbol
258
259
Returns:
260
Element: Chemical element
261
"""
262
263
def hasElement(self, name: str) -> bool:
264
"""
265
Check if element exists.
266
267
Args:
268
name (str): Element name or symbol
269
270
Returns:
271
bool: True if element exists
272
"""
273
274
def getNames(self) -> list[str]:
275
"""
276
Get all element names.
277
278
Returns:
279
list[str]: Element names
280
"""
281
282
def getSymbols(self) -> list[str]:
283
"""
284
Get all element symbols.
285
286
Returns:
287
list[str]: Element symbols
288
"""
289
```
290
291
### Isotope Distributions
292
293
#### IsotopeDistribution
294
295
Theoretical and experimental isotope pattern calculations.
296
297
```python { .api }
298
class IsotopeDistribution:
299
def __init__(self) -> None: ...
300
301
def set(self, formula: EmpiricalFormula) -> None:
302
"""
303
Set distribution from empirical formula.
304
305
Args:
306
formula (EmpiricalFormula): Molecular formula
307
"""
308
309
def getContainer(self) -> list[Peak1D]:
310
"""
311
Get isotope peaks.
312
313
Returns:
314
list[Peak1D]: Isotope peaks with m/z and intensity
315
"""
316
317
def setContainer(self, peaks: list[Peak1D]) -> None:
318
"""
319
Set isotope peaks.
320
321
Args:
322
peaks (list[Peak1D]): Isotope peaks
323
"""
324
325
def getMax(self) -> Peak1D:
326
"""
327
Get most abundant isotope peak.
328
329
Returns:
330
Peak1D: Monoisotopic or most abundant peak
331
"""
332
333
def getMin(self) -> Peak1D:
334
"""
335
Get least abundant isotope peak.
336
337
Returns:
338
Peak1D: Least abundant peak
339
"""
340
341
def getMostAbundant(self) -> Peak1D:
342
"""
343
Get most abundant peak.
344
345
Returns:
346
Peak1D: Most abundant isotope peak
347
"""
348
349
def size(self) -> int:
350
"""
351
Get number of isotope peaks.
352
353
Returns:
354
int: Peak count
355
"""
356
357
def empty(self) -> bool:
358
"""
359
Check if distribution is empty.
360
361
Returns:
362
bool: True if empty
363
"""
364
365
def clear(self) -> None:
366
"""Clear isotope distribution."""
367
368
def normalize(self) -> None:
369
"""Normalize peak intensities to sum to 1."""
370
371
def sort(self) -> None:
372
"""Sort peaks by m/z."""
373
374
def trimIntensity(self, cutoff: float) -> None:
375
"""
376
Remove peaks below intensity cutoff.
377
378
Args:
379
cutoff (float): Intensity cutoff (0-1)
380
"""
381
382
def __add__(self, other: IsotopeDistribution) -> IsotopeDistribution:
383
"""
384
Convolve with another distribution.
385
386
Args:
387
other (IsotopeDistribution): Distribution to convolve
388
389
Returns:
390
IsotopeDistribution: Convolved distribution
391
"""
392
393
class CoarseIsotopePatternGenerator:
394
def __init__(self) -> None: ...
395
396
def run(self, formula: EmpiricalFormula, dist: IsotopeDistribution) -> None:
397
"""
398
Generate coarse isotope pattern.
399
400
Args:
401
formula (EmpiricalFormula): Molecular formula
402
dist (IsotopeDistribution): Output distribution
403
"""
404
405
def getParameters(self) -> Param:
406
"""Get generator parameters."""
407
408
def setParameters(self, param: Param) -> None:
409
"""Set generator parameters."""
410
411
class FineIsotopePatternGenerator:
412
def __init__(self) -> None: ...
413
414
def run(self, formula: EmpiricalFormula, dist: IsotopeDistribution) -> None:
415
"""
416
Generate fine isotope pattern.
417
418
Args:
419
formula (EmpiricalFormula): Molecular formula
420
dist (IsotopeDistribution): Output distribution
421
"""
422
423
def getParameters(self) -> Param:
424
"""Get generator parameters."""
425
426
def setParameters(self, param: Param) -> None:
427
"""Set generator parameters."""
428
```
429
430
### Theoretical Spectrum Generation
431
432
#### TheoreticalSpectrumGenerator
433
434
Generate theoretical MS/MS spectra from peptide sequences.
435
436
```python { .api }
437
class TheoreticalSpectrumGenerator:
438
def __init__(self) -> None: ...
439
440
def getSpectrum(self, spectrum: MSSpectrum, peptide: AASequence,
441
charge: int, intensity: float) -> None:
442
"""
443
Generate theoretical spectrum for peptide.
444
445
Args:
446
spectrum (MSSpectrum): Output spectrum
447
peptide (AASequence): Peptide sequence
448
charge (int): Precursor charge
449
intensity (float): Base peak intensity
450
"""
451
452
def addPeaks(self, spectrum: MSSpectrum, peptide: AASequence,
453
residue_type: Residue.ResidueType, charge: int) -> None:
454
"""
455
Add specific fragment ion peaks.
456
457
Args:
458
spectrum (MSSpectrum): Output spectrum
459
peptide (AASequence): Peptide sequence
460
residue_type (Residue.ResidueType): Fragment type (b, y, etc.)
461
charge (int): Fragment charge
462
"""
463
464
def getParameters(self) -> Param:
465
"""
466
Get generation parameters.
467
468
Returns:
469
Param: Parameters for ion types, charges, etc.
470
"""
471
472
def setParameters(self, param: Param) -> None:
473
"""
474
Set generation parameters.
475
476
Args:
477
param (Param): Generation parameters
478
"""
479
480
def addAbundantImmoniumIons(self, spectrum: MSSpectrum, peptide: AASequence,
481
intensity: float) -> None:
482
"""
483
Add immonium ion peaks.
484
485
Args:
486
spectrum (MSSpectrum): Output spectrum
487
peptide (AASequence): Peptide sequence
488
intensity (float): Base intensity
489
"""
490
491
def addPrecursorPeaks(self, spectrum: MSSpectrum, peptide: AASequence,
492
charge: int, intensity: float) -> None:
493
"""
494
Add precursor ion peaks.
495
496
Args:
497
spectrum (MSSpectrum): Output spectrum
498
peptide (AASequence): Peptide sequence
499
charge (int): Precursor charge
500
intensity (float): Base intensity
501
"""
502
```
503
504
### Mass Decomposition
505
506
#### MassDecompositionAlgorithm
507
508
Find possible elemental compositions for given masses.
509
510
```python { .api }
511
class MassDecompositionAlgorithm:
512
def __init__(self) -> None: ...
513
514
def getDecompositions(self, mass: float, tolerance: float) -> list[MassDecomposition]:
515
"""
516
Get possible decompositions for mass.
517
518
Args:
519
mass (float): Target mass
520
tolerance (float): Mass tolerance
521
522
Returns:
523
list[MassDecomposition]: Possible compositions
524
"""
525
526
def getParameters(self) -> Param:
527
"""Get algorithm parameters."""
528
529
def setParameters(self, param: Param) -> None:
530
"""Set algorithm parameters."""
531
532
class MassDecomposition:
533
def __init__(self) -> None: ...
534
535
def getFormula(self) -> EmpiricalFormula:
536
"""
537
Get empirical formula.
538
539
Returns:
540
EmpiricalFormula: Chemical formula
541
"""
542
543
def getMass(self) -> float:
544
"""
545
Get calculated mass.
546
547
Returns:
548
float: Mass in Da
549
"""
550
551
def getMassError(self) -> float:
552
"""
553
Get mass error.
554
555
Returns:
556
float: Mass error in Da
557
"""
558
559
def getNumberOfAtoms(self) -> int:
560
"""
561
Get total atom count.
562
563
Returns:
564
int: Number of atoms
565
"""
566
```
567
568
### Chemical Constants
569
570
#### Constants
571
572
Physical and chemical constants for mass spectrometry.
573
574
```python { .api }
575
class Constants:
576
# Fundamental constants
577
AVOGADRO = 6.02214179e23
578
ELEMENTARY_CHARGE = 1.602176487e-19
579
580
# Mass constants (in Da)
581
C13C12_MASSDIFF_U = 1.0033548378
582
H2H_MASSDIFF_U = 1.006276744
583
N15N14_MASSDIFF_U = 0.997035
584
O18O16_MASSDIFF_U = 2.0042463
585
S34S32_MASSDIFF_U = 1.995797
586
587
# Proton mass
588
PROTON_MASS_U = 1.007276466812
589
590
# Electron mass
591
ELECTRON_MASS_U = 0.00054857990907
592
593
# Neutron mass
594
NEUTRON_MASS_U = 1.00866491588
595
596
# Common modifications (mass shifts in Da)
597
MOD_OXIDATION_M = 15.994915
598
MOD_CARBAMIDOMETHYL_C = 57.021464
599
MOD_ACETYL_NTERM = 42.010565
600
MOD_AMIDATION_CTERM = -0.984016
601
MOD_DEAMIDATION_NQ = 0.984016
602
MOD_PHOSPHORYLATION_STY = 79.966331
603
604
@staticmethod
605
def calculateMZ(mass: float, charge: int) -> float:
606
"""
607
Calculate m/z from mass and charge.
608
609
Args:
610
mass (float): Neutral mass in Da
611
charge (int): Charge state
612
613
Returns:
614
float: m/z value
615
"""
616
617
@staticmethod
618
def calculateMass(mz: float, charge: int) -> float:
619
"""
620
Calculate neutral mass from m/z and charge.
621
622
Args:
623
mz (float): m/z value
624
charge (int): Charge state
625
626
Returns:
627
float: Neutral mass in Da
628
"""
629
```
630
631
## Usage Examples
632
633
### Empirical Formula Calculations
634
635
```python
636
import pyopenms
637
638
# Create empirical formulas
639
glucose = pyopenms.EmpiricalFormula("C6H12O6")
640
water = pyopenms.EmpiricalFormula("H2O")
641
642
print(f"Glucose: {glucose.toString()}")
643
print(f"Monoisotopic weight: {glucose.getMonoWeight():.6f} Da")
644
print(f"Average weight: {glucose.getAverageWeight():.6f} Da")
645
print(f"Number of atoms: {glucose.getNumberOfAtoms()}")
646
647
# Formula arithmetic
648
dehydrated = glucose - water
649
print(f"Glucose - H2O: {dehydrated.toString()}")
650
print(f"Weight: {dehydrated.getMonoWeight():.6f} Da")
651
652
# Multiply formula
653
glucose_polymer = glucose * 10
654
print(f"(Glucose)10: {glucose_polymer.toString()}")
655
print(f"Weight: {glucose_polymer.getMonoWeight():.2f} Da")
656
657
# Access individual elements
658
print(f"Carbon atoms in glucose: {glucose.getNumberOf('C')}")
659
print(f"Elements: {glucose.getElements()}")
660
```
661
662
### Isotope Distribution Calculations
663
664
```python
665
import pyopenms
666
667
# Calculate isotope distribution for peptide
668
peptide_formula = pyopenms.EmpiricalFormula("C43H66N12O12S")
669
670
# Generate coarse isotope pattern
671
generator = pyopenms.CoarseIsotopePatternGenerator()
672
isotope_dist = pyopenms.IsotopeDistribution()
673
generator.run(peptide_formula, isotope_dist)
674
675
print(f"Isotope peaks: {isotope_dist.size()}")
676
677
# Get isotope peaks
678
peaks = isotope_dist.getContainer()
679
for i, peak in enumerate(peaks):
680
print(f"Peak {i}: m/z {peak.getMZ():.6f}, intensity {peak.getIntensity():.4f}")
681
682
# Get most abundant peak
683
most_abundant = isotope_dist.getMostAbundant()
684
print(f"Most abundant: m/z {most_abundant.getMZ():.6f}")
685
686
# Fine isotope pattern for higher accuracy
687
fine_generator = pyopenms.FineIsotopePatternGenerator()
688
fine_dist = pyopenms.IsotopeDistribution()
689
fine_generator.run(peptide_formula, fine_dist)
690
691
print(f"Fine isotope peaks: {fine_dist.size()}")
692
```
693
694
### Theoretical Spectrum Generation
695
696
```python
697
import pyopenms
698
699
# Create peptide sequence
700
peptide = pyopenms.AASequence.fromString("PEPTIDER")
701
702
# Generate theoretical spectrum
703
generator = pyopenms.TheoreticalSpectrumGenerator()
704
705
# Configure parameters
706
params = generator.getParameters()
707
params.setValue("add_b_ions", "true")
708
params.setValue("add_y_ions", "true")
709
params.setValue("add_a_ions", "false")
710
params.setValue("add_c_ions", "false")
711
params.setValue("add_x_ions", "false")
712
params.setValue("add_z_ions", "false")
713
params.setValue("add_losses", "true")
714
params.setValue("add_metainfo", "true")
715
generator.setParameters(params)
716
717
# Generate spectrum for charge 2
718
spectrum = pyopenms.MSSpectrum()
719
generator.getSpectrum(spectrum, peptide, 2, 100.0)
720
721
print(f"Generated {spectrum.size()} theoretical peaks")
722
723
# Display peaks
724
mz_array, intensity_array = spectrum.get_peaks()
725
for i in range(min(10, len(mz_array))):
726
print(f"Peak {i+1}: m/z {mz_array[i]:.4f}, intensity {intensity_array[i]:.1f}")
727
728
# Add specific fragment types
729
b_spectrum = pyopenms.MSSpectrum()
730
generator.addPeaks(b_spectrum, peptide, pyopenms.Residue.BIon, 1)
731
print(f"B-ion peaks: {b_spectrum.size()}")
732
733
y_spectrum = pyopenms.MSSpectrum()
734
generator.addPeaks(y_spectrum, peptide, pyopenms.Residue.YIon, 1)
735
print(f"Y-ion peaks: {y_spectrum.size()}")
736
```
737
738
### Element Database Usage
739
740
```python
741
import pyopenms
742
743
# Access element database
744
element_db = pyopenms.ElementDB.getInstance()
745
746
# Get element information
747
carbon = element_db.getElement("C")
748
print(f"Carbon:")
749
print(f" Name: {carbon.getName()}")
750
print(f" Symbol: {carbon.getSymbol()}")
751
print(f" Atomic number: {carbon.getAtomicNumber()}")
752
print(f" Average weight: {carbon.getAverageWeight():.6f} Da")
753
print(f" Monoisotopic weight: {carbon.getMonoWeight():.6f} Da")
754
755
# Check element existence
756
print(f"Has carbon: {element_db.hasElement('C')}")
757
print(f"Has unknown element: {element_db.hasElement('Xx')}")
758
759
# Get all elements
760
symbols = element_db.getSymbols()
761
print(f"Available elements: {len(symbols)}")
762
print(f"First 10 symbols: {symbols[:10]}")
763
```
764
765
### Mass Decomposition
766
767
```python
768
import pyopenms
769
770
# Set up mass decomposition
771
decomposer = pyopenms.MassDecompositionAlgorithm()
772
773
# Configure elements and ranges
774
params = decomposer.getParameters()
775
params.setValue("tolerance", 0.01) # 10 mDa tolerance
776
params.setValue("charge_min", 1)
777
params.setValue("charge_max", 3)
778
decomposer.setParameters(params)
779
780
# Find decompositions for a given mass
781
target_mass = 1234.5678
782
decompositions = decomposer.getDecompositions(target_mass, 0.01)
783
784
print(f"Found {len(decompositions)} possible compositions for mass {target_mass}")
785
786
for i, decomp in enumerate(decompositions[:10]): # Show first 10
787
formula = decomp.getFormula()
788
mass = decomp.getMass()
789
error = decomp.getMassError()
790
atoms = decomp.getNumberOfAtoms()
791
792
print(f"{i+1}. {formula.toString()}")
793
print(f" Mass: {mass:.6f} Da (error: {error*1000:.2f} mDa)")
794
print(f" Atoms: {atoms}")
795
```
796
797
### Constants and Conversions
798
799
```python
800
import pyopenms
801
802
# Use predefined constants
803
print(f"Proton mass: {pyopenms.Constants.PROTON_MASS_U:.9f} Da")
804
print(f"Electron mass: {pyopenms.Constants.ELECTRON_MASS_U:.9f} Da")
805
print(f"C13-C12 mass difference: {pyopenms.Constants.C13C12_MASSDIFF_U:.9f} Da")
806
807
# Common modifications
808
print(f"Oxidation (+O): {pyopenms.Constants.MOD_OXIDATION_M:.6f} Da")
809
print(f"Carbamidomethylation: {pyopenms.Constants.MOD_CARBAMIDOMETHYL_C:.6f} Da")
810
print(f"Acetylation (N-term): {pyopenms.Constants.MOD_ACETYL_NTERM:.6f} Da")
811
812
# Mass/charge conversions
813
neutral_mass = 1000.0
814
charge = 2
815
816
mz = pyopenms.Constants.calculateMZ(neutral_mass, charge)
817
print(f"Mass {neutral_mass} Da at charge {charge} -> m/z {mz:.6f}")
818
819
back_to_mass = pyopenms.Constants.calculateMass(mz, charge)
820
print(f"m/z {mz:.6f} at charge {charge} -> mass {back_to_mass:.6f} Da")
821
822
# Calculate m/z for different charge states
823
for z in range(1, 5):
824
mz_z = pyopenms.Constants.calculateMZ(neutral_mass, z)
825
print(f"Charge {z}: m/z {mz_z:.4f}")
826
```
827
828
### Formula from Sequence
829
830
```python
831
import pyopenms
832
833
# Get formula for peptide sequence
834
peptide = pyopenms.AASequence.fromString("PEPTIDER")
835
formula = peptide.getFormula()
836
837
print(f"Peptide: {peptide.toString()}")
838
print(f"Formula: {formula.toString()}")
839
print(f"Monoisotopic mass: {formula.getMonoWeight():.6f} Da")
840
841
# Add modifications and see formula change
842
modified_peptide = pyopenms.AASequence.fromString("PEPTIDEM(Oxidation)R")
843
modified_formula = modified_peptide.getFormula()
844
845
print(f"Modified peptide: {modified_peptide.toString()}")
846
print(f"Modified formula: {modified_formula.toString()}")
847
print(f"Modified mass: {modified_formula.getMonoWeight():.6f} Da")
848
849
# Calculate mass difference
850
mass_diff = modified_formula.getMonoWeight() - formula.getMonoWeight()
851
print(f"Mass difference: {mass_diff:.6f} Da")
852
print(f"Expected oxidation: {pyopenms.Constants.MOD_OXIDATION_M:.6f} Da")
853
```