Metadata-Version: 2.4
Name: ptir5
Version: 0.1.1
Summary: Read-only Python library for PTIR5 files (HDF5-based format from Photothermal Spectroscopy Corp.)
Project-URL: Homepage, https://github.com/photothermal/PTIR5-py.git
Project-URL: Repository, https://github.com/photothermal/PTIR5-py.git
Author: Photothermal Spectroscopy Corp.
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: h5py>=3.9
Requires-Dist: numpy>=1.24
Provides-Extra: dev
Requires-Dist: mypy>=1.5; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Description-Content-Type: text/markdown

# ptir5

[![CI](https://github.com/photothermal/PTIR5-py/actions/workflows/python-app.yml/badge.svg)](https://github.com/photothermal/PTIR5-py/actions/workflows/python-app.yml)
[![PyPI version](https://img.shields.io/pypi/v/ptir5)](https://pypi.org/project/ptir5/)
[![conda-forge version](https://img.shields.io/conda/vn/conda-forge/ptir5)](https://anaconda.org/conda-forge/ptir5)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

Read-only Python library for PTIR5 files — the HDF5-based native format of
[Photothermal Spectroscopy Corp.'s](https://www.photothermal.com/) PTIR Studio
software (v5.0+).

## Installation

From PyPI:

```bash
pip install ptir5
```

From conda-forge:

```bash
conda install -c conda-forge ptir5
```

For local development and testing:

```bash
pip install -e .[dev]
pytest -q
```

## Quick Start

```python
import ptir5

with ptir5.open("sample.ptir") as f:
    # List all measurements
    for m in f.measurements:
        print(m.label, m.measurement_type, m.data.shape)

    # Access a specific spectrum
    spec = f.measurements[0]
    x = spec.x_values        # wavenumber axis
    y = spec.data             # signal values

    # Navigate the document tree
    if f.tree:
        for node, folders, leaves in f.tree.walk():
            for leaf in leaves:
                if leaf.measurement is not None:
                    print(leaf.name, leaf.measurement.data.shape)
```

## Features

- **Read-only access** to all PTIR5 measurement types as numpy arrays
- **16 measurement types**: O-PTIR spectra/images/hyperspectra, Raman spectra/hyperspectra, camera images, fluorescence images, FL-PTIR images, PTSRS spectra/images, and image stacks
- **Hierarchical tree navigation** matching PTIR Studio's document structure
- **Flat measurement enumeration** with type filtering and GUID lookup
- **Background spectra** access
- **Generated data** (ROI spectra, band images) from hyperspectral measurements
- **Lazy loading** — data is read from disk only when accessed
- **Dict-like metadata** with Python-native types

## Data Types

| Type | Class | Array Shape | Dtype |
|------|-------|-------------|-------|
| O-PTIR Spectrum | `OPTIRSpectrum` | `(points,)` | float32 |
| Raman Spectrum | `RamanSpectrum` | `(points,)` | float32 |
| Generated Spectrum | `GeneratedSpectrum` | `(points,)` | float32 |
| PTSRS Spectrum | `PTSRSSpectrum` | `(points,)` | float32 |
| O-PTIR Image | `OPTIRImage` | `(height, width)` | float32 |
| Generated Image | `GeneratedImage` | `(height, width)` | float32 |
| PTSRS Image | `PTSRSImage` | `(height, width)` | float32 |
| Camera Image | `CameraImage` | `(height, width, bpp)` | uint8 |
| Fluorescence Image | `FluorescenceImage` | `(height, width, bpp)` | uint8 |
| FL-PTIR Image | `FLPTIRImage` | `(height, width, bpp)` | uint8 |
| O-PTIR Hyperspectra | `OPTIRHyperspectra` | `(points, height, width)` | float32 |
| Raman Hyperspectra | `RamanHyperspectra` | `(points, height, width)` | float32 |
| O-PTIR Image Stack | `OPTIRImageStack` | `(images, height, width)` | float32 |
| PTSRS Image Stack | `PTSRSImageStack` | `(images, height, width)` | float32 |
| Camera Image Stack | `CameraImageStack` | `(images, height, width, bpp)` | uint8 |
| FL-PTIR Image Stack (legacy) | `FLPTIRImageStack` | `(images, height, width, 4)` ¹ | uint8 |
| FL-PTIR Image Stack | `FLPTIRImageStack` | `(images, height, width)` | float32 |

¹ Legacy rank-4 storage encodes one `float32` per pixel as four `uint8` bytes.
Use `m.read_image(i)` or `m.data_float32` to get canonical `float32` imagery
for either storage format; `m.data` returns the raw on-disk dataset. See
[`docs/data_types.md`](docs/data_types.md#flptirimagestack--dual-format) for
details.

## Requirements

- Python >= 3.11
- h5py >= 3.9
- numpy >= 1.24

## License

MIT
