Metadata-Version: 2.1
Name: pybif6
Version: 0.2.0
Summary: ToF-SIMS BIF6 file parsing library
Author-Email: Shenghui Ye <yesh@aliyun.com>
License: GPL-3
Project-URL: Homepage, https://github.com/yesh0/pybif6
Project-URL: Issues, https://github.com/yesh0/pybif6/issues
Requires-Python: >=3.9
Requires-Dist: numpy>=1.20
Description-Content-Type: text/markdown

# pybif6

[![PyPI - Version](https://img.shields.io/pypi/v/pybif6)](https://pypi.org/project/pybif6/)

This tiny project rewrites [the BIF6 file parsing part] of [the R package `tofsims`] in Python.

[the BIF6 file parsing part]: https://github.com/lorenzgerber/tofsims/blob/master/src/c_importer.cpp
[the R package `tofsims`]: https://github.com/lorenzgerber/tofsims

## Usage

```python
import pybif6

with pybif6.parse_bif6("path/to/bif6/file") as bif6_file:
    for interval_image in bif6_file:
        print(
            f'id: {interval_image.id}, '
            f'mz_center: {interval_image.mz_center}, '
            f'mz_interval_lower: {interval_image.mz_interval_lower}, '
            f'mz_interval_upper: {interval_image.mz_interval_upper}, '
            f'image: {interval_image.image.shape}'
        )
        # The image data is stored in `interval_image.image`, a 2D numpy array.
```

## m/z fields

Each interval stores **three** floats. Upstream names them `lower`, `middle`,
`upper`, but that labelling is wrong: across real acquisitions the first value
lies *between* the other two for 100 % of intervals and is above the second for
100 % of them. A real triple, from the PC 2:3 standard spot:

```
125.5632    125.2045    125.8703
 center      lower       upper
```

The two bounds describe the software's integration window, which is ~0.7-0.8 Da
wide. The centre sits within roughly 0.03 Da of the midpoint of those bounds.
`pybif6` therefore exposes them as `mz_center`, `mz_interval_lower` and
`mz_interval_upper`.

The mislabelling is inherited, not introduced here — note also that upstream
`tofsims` sets its canonical `massValues` to `middle` (the *lower* bound), so
upstream and `pybif6` consumers do not pick the same value out of a bin.

The TIC image (interval 0) has `NaN` for all three.

## Orientation

`parse_bif6` accepts keyword-only options that orient every image:

| Option | Meaning |
|---|---|
| `flip_x` | mirror along x (reverse the columns) |
| `flip_y` | mirror along y (reverse the rows) |
| `transpose` | swap the two spatial axes |
| `rotate` | rotate counter-clockwise by 0, 90, 180 or 270 degrees |

They are applied in a fixed order — **flips, then transpose, then rotation** —
and `image_size` follows, so `image.shape == image_size` always holds. These
exist because the correct orientation depends on the instrument and on the
sample mount, which the file header does not record; the header is only a magic
string plus three unsigned integers.
