Skip to content

Commit 6548c14

Browse files
Merge pull request #20 from OpenMS/copilot/add-chromatogram-support
Add chromatogram support
2 parents 77f199b + 56e28d8 commit 6548c14

File tree

6 files changed

+995
-1
lines changed

6 files changed

+995
-1
lines changed

README.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,75 @@ peaks_df = spec.to_dataframe()
299299
print(peaks_df.head())
300300
```
301301

302+
### Working with Chromatograms
303+
304+
Chromatograms (e.g., extracted ion chromatograms, total ion chromatograms) are now fully supported with a Pythonic interface similar to spectra.
305+
306+
```python
307+
from openms_python import Py_MSExperiment, Py_MSChromatogram
308+
import pandas as pd
309+
310+
# Load experiment with chromatograms
311+
exp = Py_MSExperiment.from_file('data.mzML')
312+
313+
# Check chromatogram count
314+
print(f"Chromatograms: {exp.chromatogram_count}")
315+
316+
# Access individual chromatograms
317+
if exp.chromatogram_count > 0:
318+
chrom = exp.get_chromatogram(0)
319+
print(f"MZ: {chrom.mz:.4f}")
320+
print(f"Name: {chrom.name}")
321+
print(f"Data points: {len(chrom)}")
322+
print(f"RT range: {chrom.rt_range}")
323+
print(f"TIC: {chrom.total_ion_current:.2e}")
324+
325+
# Iterate over all chromatograms
326+
for chrom in exp.chromatograms():
327+
print(f"Chromatogram: MZ={chrom.mz:.4f}, Points={len(chrom)}")
328+
329+
# Create chromatogram from DataFrame
330+
df = pd.DataFrame({
331+
'rt': [10.0, 20.0, 30.0, 40.0],
332+
'intensity': [1000.0, 5000.0, 3000.0, 500.0]
333+
})
334+
chrom = Py_MSChromatogram.from_dataframe(
335+
df,
336+
mz=445.12,
337+
name="XIC m/z 445.12",
338+
native_id="chromatogram=1"
339+
)
340+
341+
# Add to experiment
342+
exp.add_chromatogram(chrom)
343+
344+
# Chromatogram properties
345+
print(f"MZ: {chrom.mz:.4f}")
346+
print(f"Max intensity: {chrom.max_intensity}")
347+
print(f"RT at max: {chrom.rt[chrom.intensity.argmax()]:.2f}")
348+
349+
# Get data as arrays
350+
rt, intensity = chrom.data
351+
# Or individually
352+
rt_values = chrom.rt
353+
intensity_values = chrom.intensity
354+
355+
# Convert to DataFrame
356+
chrom_df = chrom.to_dataframe()
357+
358+
# Filter chromatogram by RT
359+
filtered = chrom.filter_by_rt(min_rt=15.0, max_rt=35.0)
360+
361+
# Normalize intensities
362+
normalized = chrom.normalize_intensity(max_value=100.0)
363+
normalized_tic = chrom.normalize_to_tic()
364+
365+
# Metadata access
366+
chrom["sample_id"] = "Sample_A"
367+
chrom["replicate"] = 1
368+
print(chrom.get("sample_id"))
369+
370+
302371
### Ion Mobility Support
303372

304373
`openms-python` provides comprehensive support for ion mobility data through float data arrays and mobilograms.
@@ -738,6 +807,8 @@ plt.show()
738807

739808
**Properties:**
740809
- `n_spectra`: Number of spectra
810+
- `nr_chromatograms`: Number of chromatograms
811+
- `chromatogram_count`: Alias for nr_chromatograms
741812
- `rt_range`: Tuple of (min_rt, max_rt)
742813
- `ms_levels`: Set of MS levels present
743814

@@ -750,12 +821,42 @@ plt.show()
750821
- `ms2_spectra()`: Iterator over MS2 spectra
751822
- `spectra_by_level(level)`: Iterator over specific MS level
752823
- `spectra_in_rt_range(min_rt, max_rt)`: Iterator over RT range
824+
- `get_chromatogram(index)`: Get chromatogram by index
825+
- `chromatograms()`: Iterator over all chromatograms
826+
- `add_chromatogram(chromatogram)`: Add a chromatogram to the experiment
753827
- `filter_by_ms_level(level)`: Filter by MS level
754828
- `filter_by_rt(min_rt, max_rt)`: Filter by RT range
755829
- `filter_top_n_peaks(n)`: Keep top N peaks per spectrum
756830
- `summary()`: Get summary statistics
757831
- `print_summary()`: Print formatted summary
758832

833+
### Py_MSChromatogram
834+
835+
**Properties:**
836+
- `mz`: M/z value for the chromatogram
837+
- `name`: Chromatogram name
838+
- `native_id`: Native chromatogram ID
839+
- `chromatogram_type`: Type of chromatogram
840+
- `rt_range`: Tuple of (min_rt, max_rt)
841+
- `min_rt`: Minimum retention time
842+
- `max_rt`: Maximum retention time
843+
- `min_intensity`: Minimum intensity
844+
- `max_intensity`: Maximum intensity
845+
- `total_ion_current`: Sum of all intensities
846+
- `data`: Tuple of (rt_array, intensity_array)
847+
- `rt`: RT values as NumPy array
848+
- `intensity`: Intensity values as NumPy array
849+
850+
**Methods:**
851+
- `from_numpy(rt, intensity, **metadata)`: Create from NumPy arrays (class method)
852+
- `from_dataframe(df, **metadata)`: Create from DataFrame (class method)
853+
- `to_numpy()`: Convert to NumPy arrays
854+
- `to_dataframe()`: Convert to DataFrame
855+
- `filter_by_rt(min_rt, max_rt)`: Filter data points by RT range
856+
- `filter_by_intensity(min_intensity)`: Filter by minimum intensity
857+
- `normalize_intensity(max_value)`: Normalize intensities to max value
858+
- `normalize_to_tic()`: Normalize so intensities sum to 1.0
859+
759860
### Py_MSSpectrum
760861

761862
**Properties:**
@@ -835,10 +936,13 @@ pip install -e ".[dev]"
835936
| Feature | pyOpenMS | openms-python |
836937
|---------|----------|---------------|
837938
| Get spectrum count | `exp.getNrSpectra()` | `len(exp)` |
939+
| Get chromatogram count | `exp.getNrChromatograms()` | `exp.chromatogram_count` |
838940
| Get retention time | `spec.getRT()` | `spec.retention_time` |
941+
| Get chromatogram m/z | `chrom.getMZ()` | `chrom.mz` |
839942
| Check MS1 | `spec.getMSLevel() == 1` | `spec.is_ms1` |
840943
| Load file | `MzMLFile().load(path, exp)` | `exp = MSExperiment.from_file(path)` |
841944
| Iterate MS1 | Manual loop + level check | `for spec in exp.ms1_spectra():` |
945+
| Iterate chromatograms | Manual loop + range check | `for chrom in exp.chromatograms():` |
842946
| Peak data | `peaks = spec.get_peaks(); mz = peaks[0]` | `mz, intensity = spec.peaks` |
843947
| DataFrame | Not available | `df = exp.to_dataframe()` |
844948

openms_python/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
from .py_msexperiment import Py_MSExperiment
2525
from .py_msspectrum import Py_MSSpectrum
26+
from .py_chromatogram import Py_MSChromatogram
2627
from .py_mobilogram import Py_Mobilogram
2728
from .py_feature import Py_Feature
2829
from .py_featuremap import Py_FeatureMap
@@ -100,6 +101,7 @@ def get_example(name: str, *, load: bool = False, target_dir: Union[str, Path, N
100101
__all__ = [
101102
"Py_MSExperiment",
102103
"Py_MSSpectrum",
104+
"Py_MSChromatogram",
103105
"Py_Mobilogram",
104106
"Py_Feature",
105107
"Py_FeatureMap",

0 commit comments

Comments
 (0)