Metadata-Version: 2.4
Name: quantion
Version: 0.1.6
Summary: Quantion library
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.21
Provides-Extra: pandas
Requires-Dist: pandas>=1.3; extra == "pandas"
Provides-Extra: test
Requires-Dist: pytest>=7; extra == "test"

# quantion-py

Python wrappers for the quantion Rust library for LC-MS data processing.

## Install

```bash
pip install git+https://github.com/phenological/quantion#subdirectory=wrappers/python
```

The install downloads the native library for your platform from the GitHub release that matches the package version.

## Concepts

**Sample**: A parsed mzML or ion file held in memory. Create samples with `parse_mzml()` or `parse_ion()`. Use as a context manager (`with`) to ensure automatic cleanup.

**XY data**: A pair of numeric sequences where `x` is retention time and `y` is intensity.

## Quick start

Load a file and extract peaks in a few lines:

```python
import quantion

raw = open("sample.mzML", "rb").read()

with quantion.parse_mzml(raw) as sample:
    eic   = quantion.calculate_eic(sample, target_mz=174.112, from_to={"from": 1, "to": 15})
    peaks = quantion.find_peaks(eic["x"], eic["y"], options={"auto_noise": True, "min_snr": 3.0})
    for p in peaks:
        print(f"rt={p['rt']:.3f}  intensity={p['intensity']:.0f}")
```

The library loads automatically on import. No initialization call needed.

## Load files

### Load mzML

Load an mzML file into a sample.

```python
sample = quantion.parse_mzml(bytes)
```

### Load ion

Load an ion binary file into a sample.

```python
sample = quantion.parse_ion(bytes)
```

## Convert

### Sample to JSON

Get JSON from a sample.

```python
json = quantion.ion_to_json(sample)
```

### Sample to mzML

Get mzML text from a sample.

```python
mzml = quantion.ion_to_mzml(sample)
```

### Sample to ion

Convert a sample to compressed ion bytes.

```python
ion_bytes = quantion.mzml_to_ion(sample, level=5, f32_compress=False)
```

### Sample instance methods

Convert using sample methods.

```python
with quantion.parse_mzml(data) as sample:
    json = sample.to_json()
    mzml = sample.to_mzml()
    ion_bytes = sample.to_ion(level=12)
    sample.dispose()
```

## Extract from samples

### Extract EIC

Get an extracted ion chromatogram for one m/z from a sample.

```python
eic = quantion.calculate_eic(sample, target_mz=174.112, from_to={"from": 1, "to": 15}, ppm_tol=20.0, mz_tol=0.005)
```

### Get scans

Get scans from a sample by retention time range and MS level.

```python
scans = quantion.get_scans(sample, rt_range=(1, 15), level=1)
```

## Process XY data

### Calculate baseline

Estimate a baseline for XY data.

```python
baseline = quantion.calculate_baseline(y, lambda_=0, max_iterations=0)
```

### Find noise level

Estimate the noise level in XY data. The result has `width`, the number of
points the estimate came from, and `intensity`, the noise level itself.

```python
noise = quantion.find_noise_level(y)["intensity"]
```

### Find peaks

Find all peaks in XY data.

```python
peaks = quantion.find_peaks(x, y, options={"auto_noise": True, "min_snr": 3.0})
```

### Get single peak

Find one peak near a target retention time in XY data.

```python
peak = quantion.get_peak(x, y, rt=5.3, range=0.6, options={"auto_noise": True})
```

## Predict retention times

Load an ONNX model from a path, a URL, or bytes, read the keys and values stored
in it, and make a warp model from it. The model stays usable after `load_warp`,
and the warp keeps working if the model is disposed.

```python
model = quantion.load_model("model.onnx")
model.get_keys()                  # ["points", "time_from", ..., "targets"]
model.get_value("points")         # "1024"

warp = quantion.load_warp(model)
warp.get_value("targets")         # the warp has the same keys and values
```

Predict each target's retention time in a sample. You get one
`{"rt", "uncertainty"}` per target, in the same order.

```python
targets = [{"id": "feature_1", "mz": 300.1, "rt": 2.38}]
rts = warp.predict_rts(sample, targets)
```

Without reference RTs, calibrate from anchor samples such as LTRs or QCs: give
the samples and, for each one, the targets seen in it. Each target gets the
median calibrated RT over the samples where it was seen. One sample works, three
are better, five or more are best. Each RT must be the one measured in
that anchor sample: a generic target list runs without error but gives wrong RTs.

```python
anchor_samples = [ltr_1, ltr_2, ltr_3]
target_lists = [seen_in_ltr_1, seen_in_ltr_2, seen_in_ltr_3]
calibrated = warp.calibrate(anchor_samples, target_lists)
rts = warp.predict_rts(other_sample, calibrated)

warp.dispose()
model.dispose()
```

## Find peaks from samples

### From EICs

Find peaks for many targets using extracted ion chromatograms from a sample.

```python
targets = [
    {"rt": 5.3, "mz": 174.112, "range": 0.5, "id": "compound_A"},
    {"rt": 7.1, "mz": 203.156, "range": 0.5, "id": "compound_B"},
]

peaks = quantion.get_peaks_from_eic(
    sample, targets,
    from_to={"from": 0.5, "to": 10.0},
    options={"auto_noise": True},
    cores=2
)
```

### From chromatograms

Find peaks from stored chromatograms in a sample.

```python
items = [
    {"idx": 0, "rt": 5.3, "window": 0.5},
    {"idx": 5, "rt": 7.1, "window": 0.5},
]

peaks = quantion.get_peaks_from_chrom(sample, items, options=None, cores=2)
```

## Untargeted

### Targeted feature detection

Find targeted features by m/z and retention time from a sample.

```python
targets = [
    {"rt": 5.3, "mz": 174.112, "range": 0.5, "id": "A"},
    {"rt": 7.1, "mz": 203.156, "range": 0.5, "id": "B"},
]

features = quantion.find_feature(
    sample, targets,
    scan_eic={"ppm_tolerance": 10, "mz_tolerance": 0.003},
    eic={"ppm_tolerance": 20, "mz_tolerance": 0.005},
    options={"auto_noise": True},
    cores=2,
)
```

### From single sample

Find all features in a sample.

```python
features = quantion.find_features(
    sample,
    from_to={"from": 1, "to": 15},
    eic={"ppm_tolerance": 10, "mz_tolerance": 0.005},
    grid={"start": 40, "end": 1000, "step_size": 0.005},
    options={"auto_noise": True, "min_snr": 3},
    cores=4,
)
```

### Align features across samples

Find and align features across many samples.

```python
features = quantion.get_features(
    "/path/to/ion/dir",
    from_to={"from": 0, "to": 20},
    eic={"ppm_tolerance": 5},
    grid={"start": 50, "end": 1000, "step_size": 0.01},
    grouping={"ppm_tolerance": 5, "rt_tolerance": 0.05, "frequency": 2},
    cores=8,
)
```

## Peak detection options

Pass peak detection options as a dictionary:

```python
options = {
    "min_integral":        0.0,
    "min_intensity":       150.0,
    "min_peak_width_points": 5,
    "noise":               float("nan"),
    "auto_noise":          True,
    "auto_baseline":       True,
    "lambda_":             0,
    "max_iterations":      0,
    "allow_overlap":       False,
    "min_snr":             3.0,
}
```
