Skip to content

Commit b94b292

Browse files
committed
Add example script and test for accessing chromatograms
1 parent 9ab9315 commit b94b292

File tree

2 files changed

+288
-0
lines changed

2 files changed

+288
-0
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
import os
5+
import sys
6+
import pymzml
7+
8+
9+
def main(mzml_file):
10+
"""
11+
Example script demonstrating how to access both spectra and chromatograms
12+
using pymzML.
13+
14+
Usage:
15+
./access_spectra_and_chromatograms.py <path_to_mzml_file>
16+
"""
17+
print("Initializing Reader...")
18+
# Initialize with skip_chromatogram=False to include chromatograms during iteration
19+
run = pymzml.run.Reader(mzml_file, skip_chromatogram=False)
20+
21+
# Access the first spectrum using indexing (traditional way)
22+
print("\nAccessing first spectrum using indexing (run[0]):")
23+
try:
24+
spectrum = run[0]
25+
print(f"Spectrum ID: {spectrum.ID}")
26+
print(f"MS Level: {spectrum.ms_level}")
27+
print(f"Retention Time: {spectrum.scan_time_in_minutes()} minutes")
28+
print(f"Number of peaks: {len(spectrum.peaks('raw'))}")
29+
except Exception as e:
30+
print(f"Error accessing spectrum: {e}")
31+
32+
# Access the first spectrum using the new get_spectrum method
33+
print("\nAccessing first spectrum using get_spectrum(0):")
34+
try:
35+
spectrum = run.get_spectrum(0)
36+
print(f"Spectrum ID: {spectrum.ID}")
37+
print(f"MS Level: {spectrum.ms_level}")
38+
print(f"Retention Time: {spectrum.scan_time_in_minutes()} minutes")
39+
print(f"Number of peaks: {len(spectrum.peaks('raw'))}")
40+
except Exception as e:
41+
print(f"Error accessing spectrum: {e}")
42+
43+
# Access the TIC chromatogram using string identifier
44+
print("\nAccessing TIC chromatogram using run['TIC']:")
45+
try:
46+
chromatogram = run["TIC"]
47+
print(f"Chromatogram ID: {chromatogram.ID}")
48+
print(f"Number of data points: {len(chromatogram.peaks())}")
49+
50+
# Print the first few data points
51+
print("\nFirst 5 data points (time, intensity):")
52+
for i, (time, intensity) in enumerate(chromatogram.peaks()):
53+
if i >= 5:
54+
break
55+
print(f" {time:.4f}, {intensity:.2f}")
56+
except Exception as e:
57+
print(f"Error accessing chromatogram: {e}")
58+
59+
# Access the first chromatogram using the new get_chromatogram method
60+
print("\nAccessing first chromatogram using get_chromatogram(0):")
61+
try:
62+
chromatogram = run.get_chromatogram(0)
63+
print(f"Chromatogram ID: {chromatogram.ID}")
64+
print(f"Number of data points: {len(chromatogram.peaks())}")
65+
66+
# Print the first few data points
67+
print("\nFirst 5 data points (time, intensity):")
68+
for i, (time, intensity) in enumerate(chromatogram.peaks()):
69+
if i >= 5:
70+
break
71+
print(f" {time:.4f}, {intensity:.2f}")
72+
except Exception as e:
73+
print(f"Error accessing chromatogram: {e}")
74+
75+
# Demonstrate iterating through all items (spectra and chromatograms)
76+
print("\nIterating through first few items (spectra and chromatograms):")
77+
count = 0
78+
for item in run:
79+
if count >= 5:
80+
break
81+
if isinstance(item, pymzml.spec.Spectrum):
82+
print(f" Spectrum {item.ID}, MS level {item.ms_level}, RT {item.scan_time_in_minutes():.2f} min")
83+
elif isinstance(item, pymzml.spec.Chromatogram):
84+
print(f" Chromatogram {item.ID}, {len(item.peaks())} data points")
85+
count += 1
86+
87+
print("\nDone!")
88+
89+
90+
if __name__ == "__main__":
91+
if len(sys.argv) < 2:
92+
print(main.__doc__)
93+
print("Please provide a path to an mzML file.")
94+
sys.exit(1)
95+
96+
mzml_file = sys.argv[1]
97+
if not os.path.exists(mzml_file):
98+
print(f"Error: File '{mzml_file}' not found.")
99+
sys.exit(1)
100+
101+
main(mzml_file)
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""
4+
Test cases for the new functionality in pymzml.run.Reader
5+
related to accessing spectra and chromatograms.
6+
"""
7+
import os
8+
import sys
9+
10+
# Add parent directory to Python path
11+
sys.path.append(os.path.abspath(os.path.dirname(os.path.dirname(__file__))))
12+
13+
import unittest
14+
import pymzml.run as run
15+
from pymzml.spec import Spectrum, Chromatogram
16+
import test_file_paths
17+
18+
19+
class AccessSpectraAndChromatogramsTest(unittest.TestCase):
20+
"""
21+
Test cases for the new functionality in pymzml.run.Reader
22+
related to accessing spectra and chromatograms.
23+
"""
24+
25+
def setUp(self):
26+
"""Set up test cases."""
27+
self.paths = test_file_paths.paths
28+
29+
# Use a file with chromatograms for testing
30+
# mini.chrom.mzML is at index 3
31+
for i, path in enumerate(self.paths):
32+
if "mini.chrom.mzML" in path and not path.endswith(".gz") and not path.endswith(".idx.gz"):
33+
self.chrom_file = path
34+
break
35+
else:
36+
# Fallback to a known index if the file name is not found
37+
self.chrom_file = self.paths[3] # mini.chrom.mzML
38+
39+
# Initialize readers with different settings
40+
self.reader_with_chromatograms = run.Reader(
41+
self.chrom_file,
42+
skip_chromatogram=False
43+
)
44+
45+
self.reader_skip_chromatograms = run.Reader(
46+
self.chrom_file,
47+
skip_chromatogram=True
48+
)
49+
50+
def test_get_spectrum_method(self):
51+
"""Test the get_spectrum method."""
52+
# Check if the file has spectra
53+
spec_count = self.reader_with_chromatograms.get_spectrum_count()
54+
if spec_count is None or spec_count == 0:
55+
self.skipTest("Test file does not contain spectra")
56+
57+
# Test that get_spectrum(0) returns the same as reader[0]
58+
try:
59+
spectrum_by_index = self.reader_with_chromatograms[0]
60+
spectrum_by_method = self.reader_with_chromatograms.get_spectrum(0)
61+
62+
self.assertIsInstance(spectrum_by_index, Spectrum)
63+
self.assertIsInstance(spectrum_by_method, Spectrum)
64+
self.assertEqual(spectrum_by_index.ID, spectrum_by_method.ID)
65+
66+
# Test accessing a spectrum by ID
67+
spectrum_id = spectrum_by_index.ID
68+
if isinstance(spectrum_id, str):
69+
spectrum_by_id = self.reader_with_chromatograms[spectrum_id]
70+
self.assertEqual(spectrum_by_index.ID, spectrum_by_id.ID)
71+
except IndexError:
72+
self.skipTest("Could not access spectrum at index 0")
73+
74+
def test_get_chromatogram_method(self):
75+
"""Test the get_chromatogram method."""
76+
# Check if the file has chromatograms
77+
chrom_count = self.reader_with_chromatograms.get_chromatogram_count()
78+
if chrom_count is None or chrom_count == 0:
79+
self.skipTest("Test file does not contain chromatograms")
80+
81+
# Test accessing chromatogram by index
82+
try:
83+
chrom_by_index = self.reader_with_chromatograms.get_chromatogram(0)
84+
self.assertIsInstance(chrom_by_index, Chromatogram)
85+
86+
# If we successfully got a chromatogram by index, try to get it by ID
87+
chrom_id = chrom_by_index.ID
88+
if chrom_id:
89+
chrom_by_id = self.reader_with_chromatograms[chrom_id]
90+
self.assertIsInstance(chrom_by_id, Chromatogram)
91+
self.assertEqual(chrom_by_id.ID, chrom_id)
92+
except Exception as e:
93+
self.skipTest(f"Could not access chromatogram at index 0: {e}")
94+
95+
# Test that the chromatogram count is correct
96+
self.assertIsNotNone(self.reader_with_chromatograms.get_chromatogram_count())
97+
98+
def test_skip_chromatogram_parameter(self):
99+
"""Test the skip_chromatogram parameter."""
100+
# Check if the file has both spectra and chromatograms
101+
spec_count = self.reader_with_chromatograms.get_spectrum_count()
102+
chrom_count = self.reader_with_chromatograms.get_chromatogram_count()
103+
104+
if spec_count is None or spec_count == 0:
105+
self.skipTest("Test file does not contain spectra")
106+
if chrom_count is None or chrom_count == 0:
107+
self.skipTest("Test file does not contain chromatograms")
108+
109+
# With skip_chromatogram=False, we should see both spectra and chromatograms
110+
# Reset the reader to ensure we start from the beginning
111+
self.reader_with_chromatograms.close()
112+
self.reader_with_chromatograms = run.Reader(
113+
self.chrom_file,
114+
skip_chromatogram=False
115+
)
116+
117+
# Collect items
118+
spectra_found = False
119+
chromatograms_found = False
120+
count = 0
121+
max_items = 20 # Increase the limit to ensure we see both types
122+
123+
for item in self.reader_with_chromatograms:
124+
if isinstance(item, Spectrum):
125+
spectra_found = True
126+
elif isinstance(item, Chromatogram):
127+
chromatograms_found = True
128+
129+
if spectra_found and chromatograms_found:
130+
break
131+
132+
count += 1
133+
if count >= max_items:
134+
break
135+
136+
# Check that we found both types
137+
self.assertTrue(spectra_found, "No spectra found when iterating with skip_chromatogram=False")
138+
self.assertTrue(chromatograms_found, "No chromatograms found when iterating with skip_chromatogram=False")
139+
140+
# With skip_chromatogram=True, we should only see spectra
141+
# Reset the reader to ensure we start from the beginning
142+
self.reader_skip_chromatograms.close()
143+
self.reader_skip_chromatograms = run.Reader(
144+
self.chrom_file,
145+
skip_chromatogram=True
146+
)
147+
148+
# Collect items
149+
items_without_chromatograms = []
150+
for item in self.reader_skip_chromatograms:
151+
items_without_chromatograms.append(item)
152+
if len(items_without_chromatograms) >= 10: # Limit to first 10 items
153+
break
154+
155+
# Check that we only have spectra (if any items were found)
156+
if items_without_chromatograms:
157+
only_spectra = all(isinstance(item, Spectrum) for item in items_without_chromatograms)
158+
self.assertTrue(only_spectra, "Found non-spectrum items when iterating with skip_chromatogram=True")
159+
160+
def test_chromatogram_index_out_of_range(self):
161+
"""Test that accessing a chromatogram with an out-of-range index raises an exception."""
162+
# Check if the file has chromatograms
163+
chrom_count = self.reader_with_chromatograms.get_chromatogram_count()
164+
if chrom_count is None or chrom_count == 0:
165+
self.skipTest("Test file does not contain chromatograms")
166+
167+
with self.assertRaises(Exception):
168+
self.reader_with_chromatograms.get_chromatogram(100) # Assuming there are fewer than 100 chromatograms
169+
170+
def test_chromatogram_invalid_identifier(self):
171+
"""Test that accessing a chromatogram with an invalid identifier raises an exception."""
172+
# Check if the file has chromatograms
173+
chrom_count = self.reader_with_chromatograms.get_chromatogram_count()
174+
if chrom_count is None or chrom_count == 0:
175+
self.skipTest("Test file does not contain chromatograms")
176+
177+
with self.assertRaises(Exception):
178+
self.reader_with_chromatograms.get_chromatogram("NonExistentChromatogram")
179+
180+
def tearDown(self):
181+
"""Clean up after tests."""
182+
self.reader_with_chromatograms.close()
183+
self.reader_skip_chromatograms.close()
184+
185+
186+
if __name__ == "__main__":
187+
unittest.main(verbosity=3)

0 commit comments

Comments
 (0)